From fb0849ff8a3688c76e4530af80e4aeea6f69fb25 Mon Sep 17 00:00:00 2001 From: "Mr.doob" Date: Fri, 27 Sep 2024 00:06:24 +0900 Subject: [PATCH] r169 --- build/three.cjs | 498 +- build/three.module.js | 498 +- build/three.module.min.js | 2 +- build/three.webgpu.js | 47022 ++++----- build/three.webgpu.min.js | 2 +- build/three.webgpu.nodes.js | 79926 ++++++++++++++++ build/three.webgpu.nodes.min.js | 6 + docs/api/en/audio/Audio.html | 4 +- docs/api/en/materials/LineBasicMaterial.html | 4 +- docs/api/en/math/Triangle.html | 14 + docs/api/en/objects/BatchedMesh.html | 45 +- docs/api/en/objects/LOD.html | 9 + docs/api/en/renderers/WebGLRenderer.html | 10 +- docs/api/zh/extras/TextureUtils.html | 42 + docs/api/zh/objects/InstancedMesh.html | 50 +- docs/examples/en/controls/DragControls.html | 15 - .../en/controls/TransformControls.html | 29 +- .../en/geometries/SDFGeometryGenerator.html | 70 - .../en/geometries/TeapotGeometry.html | 3 +- docs/examples/en/lines/Line2.html | 65 + docs/examples/en/lines/LineGeometry.html | 84 + docs/examples/en/lines/LineMaterial.html | 92 + docs/examples/en/lines/LineSegments2.html | 69 + .../en/lines/LineSegmentsGeometry.html | 103 + docs/examples/ko/controls/MapControls.html | 122 + docs/examples/ko/webxr/XREstimatedLight.html | 117 + docs/examples/zh/controls/DragControls.html | 15 - docs/examples/zh/controls/OrbitControls.html | 56 +- .../zh/controls/PointerLockControls.html | 5 + .../zh/controls/TrackballControls.html | 54 +- .../zh/controls/TransformControls.html | 32 +- .../zh/geometries/SDFGeometryGenerator.html | 72 - .../zh/geometries/TeapotGeometry.html | 3 +- docs/index.html | 10 +- docs/list.json | 23 +- .../How-to-create-VR-content.html | 10 +- .../introduction/Libraries-and-Plugins.html | 1 + .../How-to-create-VR-content.html | 10 +- .../en/introduction/How-to-update-things.html | 2 +- .../introduction/Libraries-and-Plugins.html | 1 + .../How-to-create-VR-content.html | 10 +- .../fr/introduction/How-to-update-things.html | 19 +- .../How-to-use-post-processing.html | 10 +- .../introduction/Libraries-and-Plugins.html | 15 +- .../How-to-create-VR-content.html | 10 +- .../introduction/Libraries-and-Plugins.html | 1 + .../How-to-create-VR-content.html | 10 +- .../introduction/Libraries-and-Plugins.html | 1 + .../manual/ko/introduction/Drawing-lines.html | 4 +- .../How-to-create-VR-content.html | 10 +- .../How-to-create-VR-content.html | 10 +- .../introduction/Libraries-and-Plugins.html | 1 + .../introduction/Libraries-and-Plugins.html | 1 + .../How-to-create-VR-content.html | 10 +- .../introduction/Libraries-and-Plugins.html | 1 + docs/page.css | 4 + editor/js/Viewport.js | 2 +- examples/files.json | 14 +- examples/jsm/Addons.js | 6 - examples/jsm/controls/TrackballControls.js | 44 +- examples/jsm/controls/TransformControls.js | 159 +- examples/jsm/exporters/DRACOExporter.js | 6 +- examples/jsm/exporters/EXRExporter.js | 30 +- examples/jsm/exporters/KTX2Exporter.js | 34 +- examples/jsm/exporters/OBJExporter.js | 6 +- examples/jsm/exporters/PLYExporter.js | 16 +- examples/jsm/geometries/DecalGeometry.js | 5 +- .../jsm/geometries/InstancedPointsGeometry.js | 2 +- .../jsm/geometries/SDFGeometryGenerator.js | 144 - examples/jsm/helpers/LightProbeHelper.js | 2 +- examples/jsm/helpers/LightProbeHelperGPU.js | 65 + examples/jsm/libs/basis/basis_transcoder.js | 18 +- examples/jsm/libs/basis/basis_transcoder.wasm | Bin 499935 -> 527333 bytes examples/jsm/libs/ktx-parse.module.js | 2 +- examples/jsm/lights/LightProbeGenerator.js | 34 +- examples/jsm/loaders/ColladaLoader.js | 15 +- examples/jsm/loaders/DRACOLoader.js | 4 +- examples/jsm/loaders/FBXLoader.js | 50 +- examples/jsm/loaders/GLTFLoader.js | 15 +- examples/jsm/loaders/KTX2Loader.js | 17 +- examples/jsm/loaders/MTLLoader.js | 7 +- examples/jsm/loaders/MaterialXLoader.js | 39 +- examples/jsm/loaders/OBJLoader.js | 8 +- examples/jsm/loaders/PCDLoader.js | 9 +- examples/jsm/loaders/PDBLoader.js | 5 +- examples/jsm/loaders/PLYLoader.js | 13 +- examples/jsm/loaders/STLLoader.js | 5 +- examples/jsm/loaders/TiltLoader.js | 520 - examples/jsm/loaders/VRMLLoader.js | 20 +- examples/jsm/loaders/VTKLoader.js | 7 +- examples/jsm/loaders/XYZLoader.js | 5 +- examples/jsm/misc/Timer.js | 2 +- examples/jsm/modifiers/CurveModifierGPU.js | 233 + examples/jsm/objects/LensflareMesh.js | 322 + examples/jsm/objects/SkyMesh.js | 3 +- examples/jsm/objects/Water2Mesh.js | 5 +- examples/jsm/objects/WaterMesh.js | 3 +- examples/jsm/physics/JoltPhysics.js | 2 +- examples/jsm/physics/RapierPhysics.js | 2 +- examples/jsm/transpiler/GLSLDecoder.js | 2 +- examples/jsm/transpiler/ShaderToyDecoder.js | 4 +- examples/jsm/utils/GPUStatsPanel.js | 95 - .../jsm/utils/GeometryCompressionUtils.js | 159 +- examples/jsm/utils/PackedPhongMaterial.js | 178 - examples/jsm/utils/ShadowMapViewer.js | 11 +- examples/jsm/utils/ShadowMapViewerGPU.js | 201 + examples/jsm/utils/SkeletonUtils.js | 150 +- examples/jsm/utils/TextureUtils.js | 1 + examples/jsm/utils/TextureUtilsGPU.js | 63 + .../jsm/webxr/XRControllerModelFactory.js | 2 +- examples/misc_controls_transform.html | 5 +- examples/misc_exporter_exr.html | 6 +- examples/misc_exporter_gltf.html | 8 +- examples/models/fbx/mixamo.fbx | Bin 0 -> 3080384 bytes examples/models/gltf/readyplayer.me.glb | Bin 0 -> 1838884 bytes .../webgl_buffergeometry_compression.jpg | Bin 12213 -> 0 bytes examples/screenshots/webgl_geometry_sdf.jpg | Bin 12088 -> 0 bytes examples/screenshots/webgl_lightprobe.jpg | Bin 23774 -> 23964 bytes examples/screenshots/webgl_loader_tilt.jpg | Bin 31877 -> 0 bytes .../webgl_postprocessing_advanced.jpg | Bin 58556 -> 51095 bytes .../webgpu_animation_retargeting.jpg | Bin 0 -> 31917 bytes ...bgpu_animation_retargeting_readyplayer.jpg | Bin 0 -> 22063 bytes .../screenshots/webgpu_backdrop_water.jpg | Bin 45343 -> 44758 bytes examples/screenshots/webgpu_compute_birds.jpg | Bin 31596 -> 115565 bytes .../webgpu_compute_sort_bitonic.jpg | Bin 0 -> 25044 bytes examples/screenshots/webgpu_compute_water.jpg | Bin 0 -> 28410 bytes examples/screenshots/webgpu_lensflares.jpg | Bin 0 -> 28227 bytes examples/screenshots/webgpu_lightprobe.jpg | Bin 23828 -> 23947 bytes .../webgpu_lightprobe_cubecamera.jpg | Bin 0 -> 23976 bytes examples/screenshots/webgpu_lights_custom.jpg | Bin 82957 -> 86122 bytes .../screenshots/webgpu_materials_arrays.jpg | Bin 0 -> 11114 bytes .../screenshots/webgpu_materials_toon.jpg | Bin 17503 -> 23787 bytes .../screenshots/webgpu_modifier_curve.jpg | Bin 0 -> 13094 bytes examples/screenshots/webgpu_shadowmap_vsm.jpg | Bin 0 -> 11355 bytes examples/screenshots/webgpu_tonemapping.jpg | Bin 0 -> 25273 bytes .../webgpu_tsl_angular_slicing.jpg | Bin 33553 -> 33812 bytes .../screenshots/webgpu_tsl_raging_sea.jpg | Bin 25165 -> 28103 bytes .../webgpu_tsl_vfx_linkedparticles.jpg | Bin 0 -> 43528 bytes examples/tags.json | 3 + examples/textures/tiltbrush/Light.webp | Bin 34660 -> 0 bytes examples/webgl_animation_skinning_ik.html | 2 +- .../webgl_buffergeometry_compression.html | 273 - examples/webgl_decals.html | 11 +- examples/webgl_geometry_sdf.html | 212 - examples/webgl_geometry_spline_editor.html | 2 +- examples/webgl_lightprobe.html | 9 + examples/webgl_lightprobe_cubecamera.html | 6 +- examples/webgl_lines_fat.html | 17 +- examples/webgl_lines_fat_raycasting.html | 18 +- examples/webgl_loader_tilt.html | 91 - examples/webgl_modifier_curve.html | 2 +- examples/webgl_modifier_curve_instanced.html | 2 +- examples/webgl_postprocessing_advanced.html | 4 +- examples/webgl_postprocessing_ssaa.html | 2 +- examples/webgl_shadowmap_progressive.html | 4 +- examples/webgl_tonemapping.html | 32 +- examples/webgpu_animation_retargeting.html | 301 + ...gpu_animation_retargeting_readyplayer.html | 210 + examples/webgpu_backdrop.html | 8 +- examples/webgpu_backdrop_area.html | 4 +- examples/webgpu_backdrop_water.html | 10 +- examples/webgpu_compute_audio.html | 4 +- examples/webgpu_compute_birds.html | 133 +- examples/webgpu_compute_particles_snow.html | 6 +- examples/webgpu_compute_sort_bitonic.html | 572 + examples/webgpu_compute_water.html | 505 + examples/webgpu_instance_mesh.html | 2 +- examples/webgpu_lensflares.html | 186 + examples/webgpu_lightprobe.html | 9 + examples/webgpu_lightprobe_cubecamera.html | 125 + examples/webgpu_lights_custom.html | 15 +- examples/webgpu_materials.html | 24 +- examples/webgpu_materials_arrays.html | 174 + examples/webgpu_materials_toon.html | 12 +- examples/webgpu_mesh_batch.html | 15 +- examples/webgpu_modifier_curve.html | 220 + examples/webgpu_mrt.html | 10 +- examples/webgpu_mrt_mask.html | 4 +- examples/webgpu_multiple_rendertargets.html | 4 +- ...ebgpu_multiple_rendertargets_readback.html | 4 +- examples/webgpu_occlusion.html | 4 +- examples/webgpu_performance.html | 35 +- examples/webgpu_performance_renderbundle.html | 24 +- examples/webgpu_portal.html | 4 +- .../webgpu_postprocessing_anamorphic.html | 4 +- .../webgpu_postprocessing_motion_blur.html | 5 +- examples/webgpu_postprocessing_ssaa.html | 2 +- examples/webgpu_reflection.html | 5 +- examples/webgpu_refraction.html | 4 +- examples/webgpu_shadowmap_opacity.html | 1 + examples/webgpu_shadowmap_vsm.html | 240 + examples/webgpu_skinning.html | 4 +- examples/webgpu_storage_buffer.html | 9 +- examples/webgpu_tonemapping.html | 189 + examples/webgpu_tsl_angular_slicing.html | 3 +- ...bgpu_tsl_compute_attractors_particles.html | 2 +- examples/webgpu_tsl_halftone.html | 4 +- examples/webgpu_tsl_procedural_terrain.html | 5 +- examples/webgpu_tsl_raging_sea.html | 4 +- examples/webgpu_tsl_vfx_linkedparticles.html | 455 + examples/webgpu_volume_perlin.html | 4 +- examples/webxr_xr_controls_transform.html | 2 +- index.html | 2 +- manual/fr/cameras.html | 30 +- manual/fr/fog.html | 10 +- manual/fr/fundamentals.html | 16 +- manual/fr/lights.html | 30 +- manual/fr/materials.html | 22 +- manual/fr/primitives.html | 22 +- manual/fr/responsive.html | 12 +- manual/fr/scenegraph.html | 29 +- manual/fr/setup.html | 4 +- manual/fr/shadows.html | 36 +- manual/fr/textures.html | 60 +- 214 files changed, 111291 insertions(+), 25335 deletions(-) create mode 100644 build/three.webgpu.nodes.js create mode 100644 build/three.webgpu.nodes.min.js create mode 100644 docs/api/zh/extras/TextureUtils.html delete mode 100644 docs/examples/en/geometries/SDFGeometryGenerator.html create mode 100644 docs/examples/en/lines/Line2.html create mode 100644 docs/examples/en/lines/LineGeometry.html create mode 100644 docs/examples/en/lines/LineMaterial.html create mode 100644 docs/examples/en/lines/LineSegments2.html create mode 100644 docs/examples/en/lines/LineSegmentsGeometry.html create mode 100644 docs/examples/ko/controls/MapControls.html create mode 100644 docs/examples/ko/webxr/XREstimatedLight.html delete mode 100644 docs/examples/zh/geometries/SDFGeometryGenerator.html delete mode 100644 examples/jsm/geometries/SDFGeometryGenerator.js create mode 100644 examples/jsm/helpers/LightProbeHelperGPU.js delete mode 100644 examples/jsm/loaders/TiltLoader.js create mode 100644 examples/jsm/modifiers/CurveModifierGPU.js create mode 100644 examples/jsm/objects/LensflareMesh.js delete mode 100644 examples/jsm/utils/GPUStatsPanel.js delete mode 100644 examples/jsm/utils/PackedPhongMaterial.js create mode 100644 examples/jsm/utils/ShadowMapViewerGPU.js create mode 100644 examples/jsm/utils/TextureUtilsGPU.js create mode 100644 examples/models/fbx/mixamo.fbx create mode 100644 examples/models/gltf/readyplayer.me.glb delete mode 100644 examples/screenshots/webgl_buffergeometry_compression.jpg delete mode 100644 examples/screenshots/webgl_geometry_sdf.jpg delete mode 100644 examples/screenshots/webgl_loader_tilt.jpg create mode 100644 examples/screenshots/webgpu_animation_retargeting.jpg create mode 100644 examples/screenshots/webgpu_animation_retargeting_readyplayer.jpg create mode 100644 examples/screenshots/webgpu_compute_sort_bitonic.jpg create mode 100644 examples/screenshots/webgpu_compute_water.jpg create mode 100644 examples/screenshots/webgpu_lensflares.jpg create mode 100644 examples/screenshots/webgpu_lightprobe_cubecamera.jpg create mode 100644 examples/screenshots/webgpu_materials_arrays.jpg create mode 100644 examples/screenshots/webgpu_modifier_curve.jpg create mode 100644 examples/screenshots/webgpu_shadowmap_vsm.jpg create mode 100644 examples/screenshots/webgpu_tonemapping.jpg create mode 100644 examples/screenshots/webgpu_tsl_vfx_linkedparticles.jpg delete mode 100644 examples/textures/tiltbrush/Light.webp delete mode 100644 examples/webgl_buffergeometry_compression.html delete mode 100644 examples/webgl_geometry_sdf.html delete mode 100644 examples/webgl_loader_tilt.html create mode 100644 examples/webgpu_animation_retargeting.html create mode 100644 examples/webgpu_animation_retargeting_readyplayer.html create mode 100644 examples/webgpu_compute_sort_bitonic.html create mode 100644 examples/webgpu_compute_water.html create mode 100644 examples/webgpu_lensflares.html create mode 100644 examples/webgpu_lightprobe_cubecamera.html create mode 100644 examples/webgpu_materials_arrays.html create mode 100644 examples/webgpu_modifier_curve.html create mode 100644 examples/webgpu_shadowmap_vsm.html create mode 100644 examples/webgpu_tonemapping.html create mode 100644 examples/webgpu_tsl_vfx_linkedparticles.html diff --git a/build/three.cjs b/build/three.cjs index 59dccfea241256..f7d7094d4838c8 100644 --- a/build/three.cjs +++ b/build/three.cjs @@ -5,7 +5,7 @@ */ 'use strict'; -const REVISION = '168'; +const REVISION = '169'; const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; @@ -1594,6 +1594,38 @@ function probeAsync( gl, sync, interval ) { } +function toNormalizedProjectionMatrix( projectionMatrix ) { + + const m = projectionMatrix.elements; + + // Convert [-1, 1] to [0, 1] projection matrix + m[ 2 ] = 0.5 * m[ 2 ] + 0.5 * m[ 3 ]; + m[ 6 ] = 0.5 * m[ 6 ] + 0.5 * m[ 7 ]; + m[ 10 ] = 0.5 * m[ 10 ] + 0.5 * m[ 11 ]; + m[ 14 ] = 0.5 * m[ 14 ] + 0.5 * m[ 15 ]; + +} + +function toReversedProjectionMatrix( projectionMatrix ) { + + const m = projectionMatrix.elements; + const isPerspectiveMatrix = m[ 11 ] === - 1; + + // Reverse [0, 1] projection matrix + if ( isPerspectiveMatrix ) { + + m[ 10 ] = - m[ 10 ] - 1; + m[ 14 ] = - m[ 14 ]; + + } else { + + m[ 10 ] = - m[ 10 ]; + m[ 14 ] = - m[ 14 ] + 1; + + } + +} + /** * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping * or clipping. Based on W3C specifications for sRGB and Display P3, @@ -8189,6 +8221,10 @@ const _vap = /*@__PURE__*/ new Vector3(); const _vbp = /*@__PURE__*/ new Vector3(); const _vcp = /*@__PURE__*/ new Vector3(); +const _v40 = /*@__PURE__*/ new Vector4(); +const _v41 = /*@__PURE__*/ new Vector4(); +const _v42 = /*@__PURE__*/ new Vector4(); + class Triangle { constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { @@ -8283,6 +8319,25 @@ class Triangle { } + static getInterpolatedAttribute( attr, i1, i2, i3, barycoord, target ) { + + _v40.setScalar( 0 ); + _v41.setScalar( 0 ); + _v42.setScalar( 0 ); + + _v40.fromBufferAttribute( attr, i1 ); + _v41.fromBufferAttribute( attr, i2 ); + _v42.fromBufferAttribute( attr, i3 ); + + target.setScalar( 0 ); + target.addScaledVector( _v40, barycoord.x ); + target.addScaledVector( _v41, barycoord.y ); + target.addScaledVector( _v42, barycoord.z ); + + return target; + + } + static isFrontFacing( a, b, c, direction ) { _v0$2.subVectors( c, b ); @@ -9898,7 +9953,6 @@ class BufferAttribute { this.normalized = normalized; this.usage = StaticDrawUsage; - this._updateRange = { offset: 0, count: - 1 }; this.updateRanges = []; this.gpuType = FloatType; @@ -9914,13 +9968,6 @@ class BufferAttribute { } - get updateRange() { - - warnOnce( 'THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 - return this._updateRange; - - } - setUsage( value ) { this.usage = value; @@ -11565,14 +11612,6 @@ const _vC$1 = /*@__PURE__*/ new Vector3(); const _tempA = /*@__PURE__*/ new Vector3(); const _morphA = /*@__PURE__*/ new Vector3(); -const _uvA$1 = /*@__PURE__*/ new Vector2(); -const _uvB$1 = /*@__PURE__*/ new Vector2(); -const _uvC$1 = /*@__PURE__*/ new Vector2(); - -const _normalA = /*@__PURE__*/ new Vector3(); -const _normalB = /*@__PURE__*/ new Vector3(); -const _normalC = /*@__PURE__*/ new Vector3(); - const _intersectionPoint = /*@__PURE__*/ new Vector3(); const _intersectionPointWorld = /*@__PURE__*/ new Vector3(); @@ -11915,33 +11954,24 @@ function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, n if ( intersection ) { - if ( uv ) { + const barycoord = new Vector3(); + Triangle.getBarycoord( _intersectionPoint, _vA$1, _vB$1, _vC$1, barycoord ); - _uvA$1.fromBufferAttribute( uv, a ); - _uvB$1.fromBufferAttribute( uv, b ); - _uvC$1.fromBufferAttribute( uv, c ); + if ( uv ) { - intersection.uv = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); + intersection.uv = Triangle.getInterpolatedAttribute( uv, a, b, c, barycoord, new Vector2() ); } if ( uv1 ) { - _uvA$1.fromBufferAttribute( uv1, a ); - _uvB$1.fromBufferAttribute( uv1, b ); - _uvC$1.fromBufferAttribute( uv1, c ); - - intersection.uv1 = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); + intersection.uv1 = Triangle.getInterpolatedAttribute( uv1, a, b, c, barycoord, new Vector2() ); } if ( normal ) { - _normalA.fromBufferAttribute( normal, a ); - _normalB.fromBufferAttribute( normal, b ); - _normalC.fromBufferAttribute( normal, c ); - - intersection.normal = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC, new Vector3() ); + intersection.normal = Triangle.getInterpolatedAttribute( normal, a, b, c, barycoord, new Vector3() ); if ( intersection.normal.dot( ray.direction ) > 0 ) { @@ -11962,6 +11992,7 @@ function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, n Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal ); intersection.face = face; + intersection.barycoord = barycoord; } @@ -13605,40 +13636,71 @@ function WebGLAttributes( gl ) { function updateBuffer( buffer, attribute, bufferType ) { const array = attribute.array; - const updateRange = attribute._updateRange; // @deprecated, r159 const updateRanges = attribute.updateRanges; gl.bindBuffer( bufferType, buffer ); - if ( updateRange.count === - 1 && updateRanges.length === 0 ) { + if ( updateRanges.length === 0 ) { // Not using update ranges gl.bufferSubData( bufferType, 0, array ); - } + } else { - if ( updateRanges.length !== 0 ) { + // Before applying update ranges, we merge any adjacent / overlapping + // ranges to reduce load on `gl.bufferSubData`. Empirically, this has led + // to performance improvements for applications which make heavy use of + // update ranges. Likely due to GPU command overhead. + // + // Note that to reduce garbage collection between frames, we merge the + // update ranges in-place. This is safe because this method will clear the + // update ranges once updated. - for ( let i = 0, l = updateRanges.length; i < l; i ++ ) { + updateRanges.sort( ( a, b ) => a.start - b.start ); + // To merge the update ranges in-place, we work from left to right in the + // existing updateRanges array, merging ranges. This may result in a final + // array which is smaller than the original. This index tracks the last + // index representing a merged range, any data after this index can be + // trimmed once the merge algorithm is completed. + let mergeIndex = 0; + + for ( let i = 1; i < updateRanges.length; i ++ ) { + + const previousRange = updateRanges[ mergeIndex ]; const range = updateRanges[ i ]; - gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT, - array, range.start, range.count ); + // We add one here to merge adjacent ranges. This is safe because ranges + // operate over positive integers. + if ( range.start <= previousRange.start + previousRange.count + 1 ) { + + previousRange.count = Math.max( + previousRange.count, + range.start + range.count - previousRange.start + ); + + } else { + + ++ mergeIndex; + updateRanges[ mergeIndex ] = range; + + } } - attribute.clearUpdateRanges(); + // Trim the array to only contain the merged ranges. + updateRanges.length = mergeIndex + 1; - } + for ( let i = 0, l = updateRanges.length; i < l; i ++ ) { - // @deprecated, r159 - if ( updateRange.count !== - 1 ) { + const range = updateRanges[ i ]; - gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, - array, updateRange.offset, updateRange.count ); + gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT, + array, range.start, range.count ); + + } - updateRange.count = - 1; // reset range + attribute.clearUpdateRanges(); } @@ -14099,7 +14161,7 @@ const vertex$2 = "#include \n#include \n#include < const fragment$2 = "uniform vec3 color;\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\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}"; -const vertex$1 = "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}"; +const vertex$1 = "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[ 3 ];\n\tvec2 scale = vec2( length( modelMatrix[ 0 ].xyz ), length( modelMatrix[ 1 ].xyz ) );\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}"; const fragment$1 = "uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \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}"; @@ -15865,6 +15927,14 @@ function WebGLCapabilities( gl, extensions, parameters, utils ) { } const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; + const reverseDepthBuffer = parameters.reverseDepthBuffer === true && extensions.has( 'EXT_clip_control' ); + + if ( reverseDepthBuffer === true ) { + + const ext = extensions.get( 'EXT_clip_control' ); + ext.clipControlEXT( ext.LOWER_LEFT_EXT, ext.ZERO_TO_ONE_EXT ); + + } const maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS ); const maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ); @@ -15892,6 +15962,7 @@ function WebGLCapabilities( gl, extensions, parameters, utils ) { precision: precision, logarithmicDepthBuffer: logarithmicDepthBuffer, + reverseDepthBuffer: reverseDepthBuffer, maxTextures: maxTextures, maxVertexTextures: maxVertexTextures, @@ -19909,6 +19980,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', + parameters.reverseDepthBuffer ? '#define USE_REVERSEDEPTHBUF' : '', 'uniform mat4 modelMatrix;', 'uniform mat4 modelViewMatrix;', @@ -20074,6 +20146,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', + parameters.reverseDepthBuffer ? '#define USE_REVERSEDEPTHBUF' : '', 'uniform mat4 viewMatrix;', 'uniform vec3 cameraPosition;', @@ -20466,6 +20539,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities const programs = []; const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; + const reverseDepthBuffer = capabilities.reverseDepthBuffer; const SUPPORTS_VERTEX_TEXTURES = capabilities.vertexTextures; let precision = capabilities.precision; @@ -20757,6 +20831,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities sizeAttenuation: material.sizeAttenuation === true, logarithmicDepthBuffer: logarithmicDepthBuffer, + reverseDepthBuffer: reverseDepthBuffer, skinning: object.isSkinnedMesh === true, @@ -20976,38 +21051,40 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities _programLayers.enable( 2 ); if ( parameters.logarithmicDepthBuffer ) _programLayers.enable( 3 ); - if ( parameters.skinning ) + if ( parameters.reverseDepthBuffer ) _programLayers.enable( 4 ); - if ( parameters.morphTargets ) + if ( parameters.skinning ) _programLayers.enable( 5 ); - if ( parameters.morphNormals ) + if ( parameters.morphTargets ) _programLayers.enable( 6 ); - if ( parameters.morphColors ) + if ( parameters.morphNormals ) _programLayers.enable( 7 ); - if ( parameters.premultipliedAlpha ) + if ( parameters.morphColors ) _programLayers.enable( 8 ); - if ( parameters.shadowMapEnabled ) + if ( parameters.premultipliedAlpha ) _programLayers.enable( 9 ); - if ( parameters.doubleSided ) + if ( parameters.shadowMapEnabled ) _programLayers.enable( 10 ); - if ( parameters.flipSided ) + if ( parameters.doubleSided ) _programLayers.enable( 11 ); - if ( parameters.useDepthPacking ) + if ( parameters.flipSided ) _programLayers.enable( 12 ); - if ( parameters.dithering ) + if ( parameters.useDepthPacking ) _programLayers.enable( 13 ); - if ( parameters.transmission ) + if ( parameters.dithering ) _programLayers.enable( 14 ); - if ( parameters.sheen ) + if ( parameters.transmission ) _programLayers.enable( 15 ); - if ( parameters.opaque ) + if ( parameters.sheen ) _programLayers.enable( 16 ); - if ( parameters.pointsUvs ) + if ( parameters.opaque ) _programLayers.enable( 17 ); - if ( parameters.decodeVideoTexture ) + if ( parameters.pointsUvs ) _programLayers.enable( 18 ); - if ( parameters.alphaToCoverage ) + if ( parameters.decodeVideoTexture ) _programLayers.enable( 19 ); + if ( parameters.alphaToCoverage ) + _programLayers.enable( 20 ); array.push( _programLayers.mask ); @@ -22565,6 +22642,18 @@ function WebGLShadowMap( renderer, objects, capabilities ) { } +const reversedFuncs = { + [ NeverDepth ]: AlwaysDepth, + [ LessDepth ]: GreaterDepth, + [ EqualDepth ]: NotEqualDepth, + [ LessEqualDepth ]: GreaterEqualDepth, + + [ AlwaysDepth ]: NeverDepth, + [ GreaterDepth ]: LessDepth, + [ NotEqualDepth ]: EqualDepth, + [ GreaterEqualDepth ]: LessEqualDepth, +}; + function WebGLState( gl ) { function ColorBuffer() { @@ -22629,6 +22718,7 @@ function WebGLState( gl ) { function DepthBuffer() { let locked = false; + let reversed = false; let currentDepthMask = null; let currentDepthFunc = null; @@ -22636,6 +22726,12 @@ function WebGLState( gl ) { return { + setReversed: function ( value ) { + + reversed = value; + + }, + setTest: function ( depthTest ) { if ( depthTest ) { @@ -22663,6 +22759,8 @@ function WebGLState( gl ) { setFunc: function ( depthFunc ) { + if ( reversed ) depthFunc = reversedFuncs[ depthFunc ]; + if ( currentDepthFunc !== depthFunc ) { switch ( depthFunc ) { @@ -24204,6 +24302,28 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } + if ( glFormat === _gl.RGB_INTEGER ) { + + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RGB8UI; + if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.RGB16UI; + if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.RGB32UI; + if ( glType === _gl.BYTE ) internalFormat = _gl.RGB8I; + if ( glType === _gl.SHORT ) internalFormat = _gl.RGB16I; + if ( glType === _gl.INT ) internalFormat = _gl.RGB32I; + + } + + if ( glFormat === _gl.RGBA_INTEGER ) { + + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RGBA8UI; + if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.RGBA16UI; + if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.RGBA32UI; + if ( glType === _gl.BYTE ) internalFormat = _gl.RGBA8I; + if ( glType === _gl.SHORT ) internalFormat = _gl.RGBA16I; + if ( glType === _gl.INT ) internalFormat = _gl.RGBA32I; + + } + if ( glFormat === _gl.RGB ) { if ( glType === _gl.UNSIGNED_INT_5_9_9_9_REV ) internalFormat = _gl.RGB9_E5; @@ -28797,6 +28917,7 @@ class WebGLRenderer { // camera matrices cache + const _currentProjectionMatrix = new Matrix4(); const _projScreenMatrix = new Matrix4(); const _vector3 = new Vector3(); @@ -28892,6 +29013,8 @@ class WebGLRenderer { state = new WebGLState( _gl ); + if ( capabilities.reverseDepthBuffer ) state.buffers.depth.setReversed( true ); + info = new WebGLInfo( _gl ); properties = new WebGLProperties(); textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ); @@ -29191,7 +29314,13 @@ class WebGLRenderer { } - if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT; + if ( depth ) { + + bits |= _gl.DEPTH_BUFFER_BIT; + _gl.clearDepth( this.capabilities.reverseDepthBuffer ? 0 : 1 ); + + } + if ( stencil ) { bits |= _gl.STENCIL_BUFFER_BIT; @@ -29580,6 +29709,12 @@ class WebGLRenderer { scene.traverse( function ( object ) { + if ( ! ( object.isMesh || object.isPoints || object.isLine || object.isSprite ) ) { + + return; + + } + const material = object.material; if ( material ) { @@ -30566,7 +30701,21 @@ class WebGLRenderer { // common camera uniforms - p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); + if ( capabilities.reverseDepthBuffer ) { + + _currentProjectionMatrix.copy( camera.projectionMatrix ); + + toNormalizedProjectionMatrix( _currentProjectionMatrix ); + toReversedProjectionMatrix( _currentProjectionMatrix ); + + p_uniforms.setValue( _gl, 'projectionMatrix', _currentProjectionMatrix ); + + } else { + + p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); + + } + p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); const uCamPos = p_uniforms.map.cameraPosition; @@ -31047,61 +31196,55 @@ class WebGLRenderer { if ( framebuffer ) { - state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - - try { - - const texture = renderTarget.texture; - const textureFormat = texture.format; - const textureType = texture.type; - - if ( ! capabilities.textureFormatReadable( textureFormat ) ) { - - throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.' ); + const texture = renderTarget.texture; + const textureFormat = texture.format; + const textureType = texture.type; - } + if ( ! capabilities.textureFormatReadable( textureFormat ) ) { - if ( ! capabilities.textureTypeReadable( textureType ) ) { + throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.' ); - throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.' ); + } - } + if ( ! capabilities.textureTypeReadable( textureType ) ) { - // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) - if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { + throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.' ); - const glBuffer = _gl.createBuffer(); - _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); - _gl.bufferData( _gl.PIXEL_PACK_BUFFER, buffer.byteLength, _gl.STREAM_READ ); - _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), 0 ); - _gl.flush(); + } - // check if the commands have finished every 8 ms - const sync = _gl.fenceSync( _gl.SYNC_GPU_COMMANDS_COMPLETE, 0 ); - await probeAsync( _gl, sync, 4 ); + // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) + if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { - try { + // set the active frame buffer to the one we want to read + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); - _gl.getBufferSubData( _gl.PIXEL_PACK_BUFFER, 0, buffer ); + const glBuffer = _gl.createBuffer(); + _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); + _gl.bufferData( _gl.PIXEL_PACK_BUFFER, buffer.byteLength, _gl.STREAM_READ ); + _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), 0 ); - } finally { + // reset the frame buffer to the currently set buffer before waiting + const currFramebuffer = _currentRenderTarget !== null ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; + state.bindFramebuffer( _gl.FRAMEBUFFER, currFramebuffer ); - _gl.deleteBuffer( glBuffer ); - _gl.deleteSync( sync ); + // check if the commands have finished every 8 ms + const sync = _gl.fenceSync( _gl.SYNC_GPU_COMMANDS_COMPLETE, 0 ); - } + _gl.flush(); - return buffer; + await probeAsync( _gl, sync, 4 ); - } + // read the data and delete the buffer + _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); + _gl.getBufferSubData( _gl.PIXEL_PACK_BUFFER, 0, buffer ); + _gl.deleteBuffer( glBuffer ); + _gl.deleteSync( sync ); - } finally { + return buffer; - // restore framebuffer of current render target if necessary + } else { - const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; - state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: requested read bounds are out of range.' ); } @@ -31587,7 +31730,6 @@ class InterleavedBuffer { this.count = array !== undefined ? array.length / stride : 0; this.usage = StaticDrawUsage; - this._updateRange = { offset: 0, count: - 1 }; this.updateRanges = []; this.version = 0; @@ -31604,13 +31746,6 @@ class InterleavedBuffer { } - get updateRange() { - - warnOnce( 'THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 - return this._updateRange; - - } - setUsage( value ) { this.usage = value; @@ -32375,6 +32510,27 @@ class LOD extends Object3D { } + removeLevel( distance ) { + + const levels = this.levels; + + for ( let i = 0; i < levels.length; i ++ ) { + + if ( levels[ i ].distance === distance ) { + + const removedElements = levels.splice( i, 1 ); + this.remove( removedElements[ 0 ].object ); + + return true; + + } + + } + + return false; + + } + getCurrentLevel() { return this._currentLevel; @@ -33494,6 +33650,9 @@ class BatchedMesh extends Mesh { // stores visible, active, and geometry id per object this._drawInfo = []; + // instance ids that have been set as inactive, and are available to be overwritten + this._availableInstanceIds = []; + // geometry information this._drawRanges = []; this._reservedRanges = []; @@ -33693,23 +33852,36 @@ class BatchedMesh extends Mesh { addInstance( geometryId ) { + const atCapacity = this._drawInfo.length >= this.maxInstanceCount; + // ensure we're not over geometry - if ( this._drawInfo.length >= this._maxInstanceCount ) { + if ( atCapacity && this._availableInstanceIds.length === 0 ) { throw new Error( 'BatchedMesh: Maximum item count reached.' ); } - this._drawInfo.push( { - + const instanceDrawInfo = { visible: true, active: true, geometryIndex: geometryId, + }; - } ); + let drawId = null; + + // Prioritize using previously freed instance ids + if ( this._availableInstanceIds.length > 0 ) { + + drawId = this._availableInstanceIds.pop(); + this._drawInfo[ drawId ] = instanceDrawInfo; + + } else { + + drawId = this._drawInfo.length; + this._drawInfo.push( instanceDrawInfo ); + + } - // initialize the matrix - const drawId = this._drawInfo.length - 1; const matricesTexture = this._matricesTexture; const matricesArray = matricesTexture.image.data; _identityMatrix.toArray( matricesArray, drawId * 16 ); @@ -33958,11 +34130,8 @@ class BatchedMesh extends Mesh { } */ - /* deleteInstance( instanceId ) { - // Note: User needs to call optimize() afterward to pack the data. - const drawInfo = this._drawInfo; if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { @@ -33971,12 +34140,12 @@ class BatchedMesh extends Mesh { } drawInfo[ instanceId ].active = false; + this._availableInstanceIds.push( instanceId ); this._visibilityChanged = true; return this; } - */ // get bounding box and compute it if it doesn't exist getBoundingBoxAt( geometryId, target ) { @@ -34181,6 +34350,59 @@ class BatchedMesh extends Mesh { } + setGeometryIdAt( instanceId, geometryId ) { + + // return early if the geometry is out of range or not active + const drawInfo = this._drawInfo; + if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { + + return null; + + } + + // check if the provided geometryId is within the valid range + if ( geometryId < 0 || geometryId >= this._geometryCount ) { + + return null; + + } + + drawInfo[ instanceId ].geometryIndex = geometryId; + + return this; + + } + + getGeometryIdAt( instanceId ) { + + const drawInfo = this._drawInfo; + if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { + + return - 1; + + } + + return drawInfo[ instanceId ].geometryIndex; + + } + + getGeometryRangeAt( geometryId, target = {} ) { + + if ( geometryId < 0 || geometryId >= this._geometryCount ) { + + return null; + + } + + const drawRange = this._drawRanges[ geometryId ]; + + target.start = drawRange.start; + target.count = drawRange.count; + + return target; + + } + raycast( raycaster, intersects ) { const drawInfo = this._drawInfo; @@ -34732,6 +34954,7 @@ function checkIntersection( object, raycaster, ray, thresholdSq, a, b ) { index: a, face: null, faceIndex: null, + barycoord: null, object: object }; @@ -34997,6 +35220,8 @@ function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, inte point: intersectPoint, index: index, face: null, + faceIndex: null, + barycoord: null, object: object } ); @@ -37499,12 +37724,19 @@ class CylinderGeometry extends BufferGeometry { // faces - indices.push( a, b, d ); - indices.push( b, c, d ); + if ( radiusTop > 0 ) { - // update group counter + indices.push( a, b, d ); + groupCount += 3; - groupCount += 6; + } + + if ( radiusBottom > 0 ) { + + indices.push( b, c, d ); + groupCount += 3; + + } } @@ -45814,7 +46046,7 @@ class MaterialLoader extends Loader { } - const material = MaterialLoader.createMaterialFromType( json.type ); + const material = this.createMaterialFromType( json.type ); if ( json.uuid !== undefined ) material.uuid = json.uuid; if ( json.name !== undefined ) material.name = json.name; @@ -46070,6 +46302,12 @@ class MaterialLoader extends Loader { } + createMaterialFromType( type ) { + + return MaterialLoader.createMaterialFromType( type ); + + } + static createMaterialFromType( type ) { const materialLib = { @@ -47900,7 +48138,7 @@ class Clock { function now() { - return ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732 + return performance.now(); } @@ -48192,7 +48430,7 @@ class Audio extends Object3D { } - stop() { + stop( delay = 0 ) { if ( this.hasPlaybackControl === false ) { @@ -48205,7 +48443,7 @@ class Audio extends Object3D { if ( this.source !== null ) { - this.source.stop(); + this.source.stop( this.context.currentTime + delay ); this.source.onended = null; } @@ -53847,7 +54085,7 @@ class ShapePath { class Controls extends EventDispatcher { - constructor( object, domElement ) { + constructor( object, domElement = null ) { super(); diff --git a/build/three.module.js b/build/three.module.js index 99b665f0966a5c..f0f4a90230d0fd 100644 --- a/build/three.module.js +++ b/build/three.module.js @@ -3,7 +3,7 @@ * Copyright 2010-2024 Three.js Authors * SPDX-License-Identifier: MIT */ -const REVISION = '168'; +const REVISION = '169'; const MOUSE = { LEFT: 0, MIDDLE: 1, RIGHT: 2, ROTATE: 0, DOLLY: 1, PAN: 2 }; const TOUCH = { ROTATE: 0, PAN: 1, DOLLY_PAN: 2, DOLLY_ROTATE: 3 }; @@ -1592,6 +1592,38 @@ function probeAsync( gl, sync, interval ) { } +function toNormalizedProjectionMatrix( projectionMatrix ) { + + const m = projectionMatrix.elements; + + // Convert [-1, 1] to [0, 1] projection matrix + m[ 2 ] = 0.5 * m[ 2 ] + 0.5 * m[ 3 ]; + m[ 6 ] = 0.5 * m[ 6 ] + 0.5 * m[ 7 ]; + m[ 10 ] = 0.5 * m[ 10 ] + 0.5 * m[ 11 ]; + m[ 14 ] = 0.5 * m[ 14 ] + 0.5 * m[ 15 ]; + +} + +function toReversedProjectionMatrix( projectionMatrix ) { + + const m = projectionMatrix.elements; + const isPerspectiveMatrix = m[ 11 ] === - 1; + + // Reverse [0, 1] projection matrix + if ( isPerspectiveMatrix ) { + + m[ 10 ] = - m[ 10 ] - 1; + m[ 14 ] = - m[ 14 ]; + + } else { + + m[ 10 ] = - m[ 10 ]; + m[ 14 ] = - m[ 14 ] + 1; + + } + +} + /** * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping * or clipping. Based on W3C specifications for sRGB and Display P3, @@ -8187,6 +8219,10 @@ const _vap = /*@__PURE__*/ new Vector3(); const _vbp = /*@__PURE__*/ new Vector3(); const _vcp = /*@__PURE__*/ new Vector3(); +const _v40 = /*@__PURE__*/ new Vector4(); +const _v41 = /*@__PURE__*/ new Vector4(); +const _v42 = /*@__PURE__*/ new Vector4(); + class Triangle { constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { @@ -8281,6 +8317,25 @@ class Triangle { } + static getInterpolatedAttribute( attr, i1, i2, i3, barycoord, target ) { + + _v40.setScalar( 0 ); + _v41.setScalar( 0 ); + _v42.setScalar( 0 ); + + _v40.fromBufferAttribute( attr, i1 ); + _v41.fromBufferAttribute( attr, i2 ); + _v42.fromBufferAttribute( attr, i3 ); + + target.setScalar( 0 ); + target.addScaledVector( _v40, barycoord.x ); + target.addScaledVector( _v41, barycoord.y ); + target.addScaledVector( _v42, barycoord.z ); + + return target; + + } + static isFrontFacing( a, b, c, direction ) { _v0$2.subVectors( c, b ); @@ -9896,7 +9951,6 @@ class BufferAttribute { this.normalized = normalized; this.usage = StaticDrawUsage; - this._updateRange = { offset: 0, count: - 1 }; this.updateRanges = []; this.gpuType = FloatType; @@ -9912,13 +9966,6 @@ class BufferAttribute { } - get updateRange() { - - warnOnce( 'THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 - return this._updateRange; - - } - setUsage( value ) { this.usage = value; @@ -11563,14 +11610,6 @@ const _vC$1 = /*@__PURE__*/ new Vector3(); const _tempA = /*@__PURE__*/ new Vector3(); const _morphA = /*@__PURE__*/ new Vector3(); -const _uvA$1 = /*@__PURE__*/ new Vector2(); -const _uvB$1 = /*@__PURE__*/ new Vector2(); -const _uvC$1 = /*@__PURE__*/ new Vector2(); - -const _normalA = /*@__PURE__*/ new Vector3(); -const _normalB = /*@__PURE__*/ new Vector3(); -const _normalC = /*@__PURE__*/ new Vector3(); - const _intersectionPoint = /*@__PURE__*/ new Vector3(); const _intersectionPointWorld = /*@__PURE__*/ new Vector3(); @@ -11913,33 +11952,24 @@ function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, n if ( intersection ) { - if ( uv ) { + const barycoord = new Vector3(); + Triangle.getBarycoord( _intersectionPoint, _vA$1, _vB$1, _vC$1, barycoord ); - _uvA$1.fromBufferAttribute( uv, a ); - _uvB$1.fromBufferAttribute( uv, b ); - _uvC$1.fromBufferAttribute( uv, c ); + if ( uv ) { - intersection.uv = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); + intersection.uv = Triangle.getInterpolatedAttribute( uv, a, b, c, barycoord, new Vector2() ); } if ( uv1 ) { - _uvA$1.fromBufferAttribute( uv1, a ); - _uvB$1.fromBufferAttribute( uv1, b ); - _uvC$1.fromBufferAttribute( uv1, c ); - - intersection.uv1 = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _uvA$1, _uvB$1, _uvC$1, new Vector2() ); + intersection.uv1 = Triangle.getInterpolatedAttribute( uv1, a, b, c, barycoord, new Vector2() ); } if ( normal ) { - _normalA.fromBufferAttribute( normal, a ); - _normalB.fromBufferAttribute( normal, b ); - _normalC.fromBufferAttribute( normal, c ); - - intersection.normal = Triangle.getInterpolation( _intersectionPoint, _vA$1, _vB$1, _vC$1, _normalA, _normalB, _normalC, new Vector3() ); + intersection.normal = Triangle.getInterpolatedAttribute( normal, a, b, c, barycoord, new Vector3() ); if ( intersection.normal.dot( ray.direction ) > 0 ) { @@ -11960,6 +11990,7 @@ function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, n Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal ); intersection.face = face; + intersection.barycoord = barycoord; } @@ -13603,40 +13634,71 @@ function WebGLAttributes( gl ) { function updateBuffer( buffer, attribute, bufferType ) { const array = attribute.array; - const updateRange = attribute._updateRange; // @deprecated, r159 const updateRanges = attribute.updateRanges; gl.bindBuffer( bufferType, buffer ); - if ( updateRange.count === - 1 && updateRanges.length === 0 ) { + if ( updateRanges.length === 0 ) { // Not using update ranges gl.bufferSubData( bufferType, 0, array ); - } + } else { - if ( updateRanges.length !== 0 ) { + // Before applying update ranges, we merge any adjacent / overlapping + // ranges to reduce load on `gl.bufferSubData`. Empirically, this has led + // to performance improvements for applications which make heavy use of + // update ranges. Likely due to GPU command overhead. + // + // Note that to reduce garbage collection between frames, we merge the + // update ranges in-place. This is safe because this method will clear the + // update ranges once updated. - for ( let i = 0, l = updateRanges.length; i < l; i ++ ) { + updateRanges.sort( ( a, b ) => a.start - b.start ); + // To merge the update ranges in-place, we work from left to right in the + // existing updateRanges array, merging ranges. This may result in a final + // array which is smaller than the original. This index tracks the last + // index representing a merged range, any data after this index can be + // trimmed once the merge algorithm is completed. + let mergeIndex = 0; + + for ( let i = 1; i < updateRanges.length; i ++ ) { + + const previousRange = updateRanges[ mergeIndex ]; const range = updateRanges[ i ]; - gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT, - array, range.start, range.count ); + // We add one here to merge adjacent ranges. This is safe because ranges + // operate over positive integers. + if ( range.start <= previousRange.start + previousRange.count + 1 ) { + + previousRange.count = Math.max( + previousRange.count, + range.start + range.count - previousRange.start + ); + + } else { + + ++ mergeIndex; + updateRanges[ mergeIndex ] = range; + + } } - attribute.clearUpdateRanges(); + // Trim the array to only contain the merged ranges. + updateRanges.length = mergeIndex + 1; - } + for ( let i = 0, l = updateRanges.length; i < l; i ++ ) { - // @deprecated, r159 - if ( updateRange.count !== - 1 ) { + const range = updateRanges[ i ]; - gl.bufferSubData( bufferType, updateRange.offset * array.BYTES_PER_ELEMENT, - array, updateRange.offset, updateRange.count ); + gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT, + array, range.start, range.count ); + + } - updateRange.count = - 1; // reset range + attribute.clearUpdateRanges(); } @@ -14097,7 +14159,7 @@ const vertex$2 = "#include \n#include \n#include < const fragment$2 = "uniform vec3 color;\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\tgl_FragColor = vec4( color, opacity * ( 1.0 - getShadowMask() ) );\n\t#include \n\t#include \n\t#include \n}"; -const vertex$1 = "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}"; +const vertex$1 = "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[ 3 ];\n\tvec2 scale = vec2( length( modelMatrix[ 0 ].xyz ), length( modelMatrix[ 1 ].xyz ) );\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}"; const fragment$1 = "uniform vec3 diffuse;\nuniform float opacity;\n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \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}"; @@ -15863,6 +15925,14 @@ function WebGLCapabilities( gl, extensions, parameters, utils ) { } const logarithmicDepthBuffer = parameters.logarithmicDepthBuffer === true; + const reverseDepthBuffer = parameters.reverseDepthBuffer === true && extensions.has( 'EXT_clip_control' ); + + if ( reverseDepthBuffer === true ) { + + const ext = extensions.get( 'EXT_clip_control' ); + ext.clipControlEXT( ext.LOWER_LEFT_EXT, ext.ZERO_TO_ONE_EXT ); + + } const maxTextures = gl.getParameter( gl.MAX_TEXTURE_IMAGE_UNITS ); const maxVertexTextures = gl.getParameter( gl.MAX_VERTEX_TEXTURE_IMAGE_UNITS ); @@ -15890,6 +15960,7 @@ function WebGLCapabilities( gl, extensions, parameters, utils ) { precision: precision, logarithmicDepthBuffer: logarithmicDepthBuffer, + reverseDepthBuffer: reverseDepthBuffer, maxTextures: maxTextures, maxVertexTextures: maxVertexTextures, @@ -19907,6 +19978,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.numLightProbes > 0 ? '#define USE_LIGHT_PROBES' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', + parameters.reverseDepthBuffer ? '#define USE_REVERSEDEPTHBUF' : '', 'uniform mat4 modelMatrix;', 'uniform mat4 modelViewMatrix;', @@ -20072,6 +20144,7 @@ function WebGLProgram( renderer, cacheKey, parameters, bindingStates ) { parameters.decodeVideoTexture ? '#define DECODE_VIDEO_TEXTURE' : '', parameters.logarithmicDepthBuffer ? '#define USE_LOGDEPTHBUF' : '', + parameters.reverseDepthBuffer ? '#define USE_REVERSEDEPTHBUF' : '', 'uniform mat4 viewMatrix;', 'uniform vec3 cameraPosition;', @@ -20464,6 +20537,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities const programs = []; const logarithmicDepthBuffer = capabilities.logarithmicDepthBuffer; + const reverseDepthBuffer = capabilities.reverseDepthBuffer; const SUPPORTS_VERTEX_TEXTURES = capabilities.vertexTextures; let precision = capabilities.precision; @@ -20755,6 +20829,7 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities sizeAttenuation: material.sizeAttenuation === true, logarithmicDepthBuffer: logarithmicDepthBuffer, + reverseDepthBuffer: reverseDepthBuffer, skinning: object.isSkinnedMesh === true, @@ -20974,38 +21049,40 @@ function WebGLPrograms( renderer, cubemaps, cubeuvmaps, extensions, capabilities _programLayers.enable( 2 ); if ( parameters.logarithmicDepthBuffer ) _programLayers.enable( 3 ); - if ( parameters.skinning ) + if ( parameters.reverseDepthBuffer ) _programLayers.enable( 4 ); - if ( parameters.morphTargets ) + if ( parameters.skinning ) _programLayers.enable( 5 ); - if ( parameters.morphNormals ) + if ( parameters.morphTargets ) _programLayers.enable( 6 ); - if ( parameters.morphColors ) + if ( parameters.morphNormals ) _programLayers.enable( 7 ); - if ( parameters.premultipliedAlpha ) + if ( parameters.morphColors ) _programLayers.enable( 8 ); - if ( parameters.shadowMapEnabled ) + if ( parameters.premultipliedAlpha ) _programLayers.enable( 9 ); - if ( parameters.doubleSided ) + if ( parameters.shadowMapEnabled ) _programLayers.enable( 10 ); - if ( parameters.flipSided ) + if ( parameters.doubleSided ) _programLayers.enable( 11 ); - if ( parameters.useDepthPacking ) + if ( parameters.flipSided ) _programLayers.enable( 12 ); - if ( parameters.dithering ) + if ( parameters.useDepthPacking ) _programLayers.enable( 13 ); - if ( parameters.transmission ) + if ( parameters.dithering ) _programLayers.enable( 14 ); - if ( parameters.sheen ) + if ( parameters.transmission ) _programLayers.enable( 15 ); - if ( parameters.opaque ) + if ( parameters.sheen ) _programLayers.enable( 16 ); - if ( parameters.pointsUvs ) + if ( parameters.opaque ) _programLayers.enable( 17 ); - if ( parameters.decodeVideoTexture ) + if ( parameters.pointsUvs ) _programLayers.enable( 18 ); - if ( parameters.alphaToCoverage ) + if ( parameters.decodeVideoTexture ) _programLayers.enable( 19 ); + if ( parameters.alphaToCoverage ) + _programLayers.enable( 20 ); array.push( _programLayers.mask ); @@ -22563,6 +22640,18 @@ function WebGLShadowMap( renderer, objects, capabilities ) { } +const reversedFuncs = { + [ NeverDepth ]: AlwaysDepth, + [ LessDepth ]: GreaterDepth, + [ EqualDepth ]: NotEqualDepth, + [ LessEqualDepth ]: GreaterEqualDepth, + + [ AlwaysDepth ]: NeverDepth, + [ GreaterDepth ]: LessDepth, + [ NotEqualDepth ]: EqualDepth, + [ GreaterEqualDepth ]: LessEqualDepth, +}; + function WebGLState( gl ) { function ColorBuffer() { @@ -22627,6 +22716,7 @@ function WebGLState( gl ) { function DepthBuffer() { let locked = false; + let reversed = false; let currentDepthMask = null; let currentDepthFunc = null; @@ -22634,6 +22724,12 @@ function WebGLState( gl ) { return { + setReversed: function ( value ) { + + reversed = value; + + }, + setTest: function ( depthTest ) { if ( depthTest ) { @@ -22661,6 +22757,8 @@ function WebGLState( gl ) { setFunc: function ( depthFunc ) { + if ( reversed ) depthFunc = reversedFuncs[ depthFunc ]; + if ( currentDepthFunc !== depthFunc ) { switch ( depthFunc ) { @@ -24202,6 +24300,28 @@ function WebGLTextures( _gl, extensions, state, properties, capabilities, utils, } + if ( glFormat === _gl.RGB_INTEGER ) { + + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RGB8UI; + if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.RGB16UI; + if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.RGB32UI; + if ( glType === _gl.BYTE ) internalFormat = _gl.RGB8I; + if ( glType === _gl.SHORT ) internalFormat = _gl.RGB16I; + if ( glType === _gl.INT ) internalFormat = _gl.RGB32I; + + } + + if ( glFormat === _gl.RGBA_INTEGER ) { + + if ( glType === _gl.UNSIGNED_BYTE ) internalFormat = _gl.RGBA8UI; + if ( glType === _gl.UNSIGNED_SHORT ) internalFormat = _gl.RGBA16UI; + if ( glType === _gl.UNSIGNED_INT ) internalFormat = _gl.RGBA32UI; + if ( glType === _gl.BYTE ) internalFormat = _gl.RGBA8I; + if ( glType === _gl.SHORT ) internalFormat = _gl.RGBA16I; + if ( glType === _gl.INT ) internalFormat = _gl.RGBA32I; + + } + if ( glFormat === _gl.RGB ) { if ( glType === _gl.UNSIGNED_INT_5_9_9_9_REV ) internalFormat = _gl.RGB9_E5; @@ -28795,6 +28915,7 @@ class WebGLRenderer { // camera matrices cache + const _currentProjectionMatrix = new Matrix4(); const _projScreenMatrix = new Matrix4(); const _vector3 = new Vector3(); @@ -28890,6 +29011,8 @@ class WebGLRenderer { state = new WebGLState( _gl ); + if ( capabilities.reverseDepthBuffer ) state.buffers.depth.setReversed( true ); + info = new WebGLInfo( _gl ); properties = new WebGLProperties(); textures = new WebGLTextures( _gl, extensions, state, properties, capabilities, utils, info ); @@ -29189,7 +29312,13 @@ class WebGLRenderer { } - if ( depth ) bits |= _gl.DEPTH_BUFFER_BIT; + if ( depth ) { + + bits |= _gl.DEPTH_BUFFER_BIT; + _gl.clearDepth( this.capabilities.reverseDepthBuffer ? 0 : 1 ); + + } + if ( stencil ) { bits |= _gl.STENCIL_BUFFER_BIT; @@ -29578,6 +29707,12 @@ class WebGLRenderer { scene.traverse( function ( object ) { + if ( ! ( object.isMesh || object.isPoints || object.isLine || object.isSprite ) ) { + + return; + + } + const material = object.material; if ( material ) { @@ -30564,7 +30699,21 @@ class WebGLRenderer { // common camera uniforms - p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); + if ( capabilities.reverseDepthBuffer ) { + + _currentProjectionMatrix.copy( camera.projectionMatrix ); + + toNormalizedProjectionMatrix( _currentProjectionMatrix ); + toReversedProjectionMatrix( _currentProjectionMatrix ); + + p_uniforms.setValue( _gl, 'projectionMatrix', _currentProjectionMatrix ); + + } else { + + p_uniforms.setValue( _gl, 'projectionMatrix', camera.projectionMatrix ); + + } + p_uniforms.setValue( _gl, 'viewMatrix', camera.matrixWorldInverse ); const uCamPos = p_uniforms.map.cameraPosition; @@ -31045,61 +31194,55 @@ class WebGLRenderer { if ( framebuffer ) { - state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - - try { - - const texture = renderTarget.texture; - const textureFormat = texture.format; - const textureType = texture.type; - - if ( ! capabilities.textureFormatReadable( textureFormat ) ) { - - throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.' ); + const texture = renderTarget.texture; + const textureFormat = texture.format; + const textureType = texture.type; - } + if ( ! capabilities.textureFormatReadable( textureFormat ) ) { - if ( ! capabilities.textureTypeReadable( textureType ) ) { + throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.' ); - throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.' ); + } - } + if ( ! capabilities.textureTypeReadable( textureType ) ) { - // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) - if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { + throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.' ); - const glBuffer = _gl.createBuffer(); - _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); - _gl.bufferData( _gl.PIXEL_PACK_BUFFER, buffer.byteLength, _gl.STREAM_READ ); - _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), 0 ); - _gl.flush(); + } - // check if the commands have finished every 8 ms - const sync = _gl.fenceSync( _gl.SYNC_GPU_COMMANDS_COMPLETE, 0 ); - await probeAsync( _gl, sync, 4 ); + // the following if statement ensures valid read requests (no out-of-bounds pixels, see #8604) + if ( ( x >= 0 && x <= ( renderTarget.width - width ) ) && ( y >= 0 && y <= ( renderTarget.height - height ) ) ) { - try { + // set the active frame buffer to the one we want to read + state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); - _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); - _gl.getBufferSubData( _gl.PIXEL_PACK_BUFFER, 0, buffer ); + const glBuffer = _gl.createBuffer(); + _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); + _gl.bufferData( _gl.PIXEL_PACK_BUFFER, buffer.byteLength, _gl.STREAM_READ ); + _gl.readPixels( x, y, width, height, utils.convert( textureFormat ), utils.convert( textureType ), 0 ); - } finally { + // reset the frame buffer to the currently set buffer before waiting + const currFramebuffer = _currentRenderTarget !== null ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; + state.bindFramebuffer( _gl.FRAMEBUFFER, currFramebuffer ); - _gl.deleteBuffer( glBuffer ); - _gl.deleteSync( sync ); + // check if the commands have finished every 8 ms + const sync = _gl.fenceSync( _gl.SYNC_GPU_COMMANDS_COMPLETE, 0 ); - } + _gl.flush(); - return buffer; + await probeAsync( _gl, sync, 4 ); - } + // read the data and delete the buffer + _gl.bindBuffer( _gl.PIXEL_PACK_BUFFER, glBuffer ); + _gl.getBufferSubData( _gl.PIXEL_PACK_BUFFER, 0, buffer ); + _gl.deleteBuffer( glBuffer ); + _gl.deleteSync( sync ); - } finally { + return buffer; - // restore framebuffer of current render target if necessary + } else { - const framebuffer = ( _currentRenderTarget !== null ) ? properties.get( _currentRenderTarget ).__webglFramebuffer : null; - state.bindFramebuffer( _gl.FRAMEBUFFER, framebuffer ); + throw new Error( 'THREE.WebGLRenderer.readRenderTargetPixelsAsync: requested read bounds are out of range.' ); } @@ -31585,7 +31728,6 @@ class InterleavedBuffer { this.count = array !== undefined ? array.length / stride : 0; this.usage = StaticDrawUsage; - this._updateRange = { offset: 0, count: - 1 }; this.updateRanges = []; this.version = 0; @@ -31602,13 +31744,6 @@ class InterleavedBuffer { } - get updateRange() { - - warnOnce( 'THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 - return this._updateRange; - - } - setUsage( value ) { this.usage = value; @@ -32373,6 +32508,27 @@ class LOD extends Object3D { } + removeLevel( distance ) { + + const levels = this.levels; + + for ( let i = 0; i < levels.length; i ++ ) { + + if ( levels[ i ].distance === distance ) { + + const removedElements = levels.splice( i, 1 ); + this.remove( removedElements[ 0 ].object ); + + return true; + + } + + } + + return false; + + } + getCurrentLevel() { return this._currentLevel; @@ -33492,6 +33648,9 @@ class BatchedMesh extends Mesh { // stores visible, active, and geometry id per object this._drawInfo = []; + // instance ids that have been set as inactive, and are available to be overwritten + this._availableInstanceIds = []; + // geometry information this._drawRanges = []; this._reservedRanges = []; @@ -33691,23 +33850,36 @@ class BatchedMesh extends Mesh { addInstance( geometryId ) { + const atCapacity = this._drawInfo.length >= this.maxInstanceCount; + // ensure we're not over geometry - if ( this._drawInfo.length >= this._maxInstanceCount ) { + if ( atCapacity && this._availableInstanceIds.length === 0 ) { throw new Error( 'BatchedMesh: Maximum item count reached.' ); } - this._drawInfo.push( { - + const instanceDrawInfo = { visible: true, active: true, geometryIndex: geometryId, + }; - } ); + let drawId = null; + + // Prioritize using previously freed instance ids + if ( this._availableInstanceIds.length > 0 ) { + + drawId = this._availableInstanceIds.pop(); + this._drawInfo[ drawId ] = instanceDrawInfo; + + } else { + + drawId = this._drawInfo.length; + this._drawInfo.push( instanceDrawInfo ); + + } - // initialize the matrix - const drawId = this._drawInfo.length - 1; const matricesTexture = this._matricesTexture; const matricesArray = matricesTexture.image.data; _identityMatrix.toArray( matricesArray, drawId * 16 ); @@ -33956,11 +34128,8 @@ class BatchedMesh extends Mesh { } */ - /* deleteInstance( instanceId ) { - // Note: User needs to call optimize() afterward to pack the data. - const drawInfo = this._drawInfo; if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { @@ -33969,12 +34138,12 @@ class BatchedMesh extends Mesh { } drawInfo[ instanceId ].active = false; + this._availableInstanceIds.push( instanceId ); this._visibilityChanged = true; return this; } - */ // get bounding box and compute it if it doesn't exist getBoundingBoxAt( geometryId, target ) { @@ -34179,6 +34348,59 @@ class BatchedMesh extends Mesh { } + setGeometryIdAt( instanceId, geometryId ) { + + // return early if the geometry is out of range or not active + const drawInfo = this._drawInfo; + if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { + + return null; + + } + + // check if the provided geometryId is within the valid range + if ( geometryId < 0 || geometryId >= this._geometryCount ) { + + return null; + + } + + drawInfo[ instanceId ].geometryIndex = geometryId; + + return this; + + } + + getGeometryIdAt( instanceId ) { + + const drawInfo = this._drawInfo; + if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { + + return - 1; + + } + + return drawInfo[ instanceId ].geometryIndex; + + } + + getGeometryRangeAt( geometryId, target = {} ) { + + if ( geometryId < 0 || geometryId >= this._geometryCount ) { + + return null; + + } + + const drawRange = this._drawRanges[ geometryId ]; + + target.start = drawRange.start; + target.count = drawRange.count; + + return target; + + } + raycast( raycaster, intersects ) { const drawInfo = this._drawInfo; @@ -34730,6 +34952,7 @@ function checkIntersection( object, raycaster, ray, thresholdSq, a, b ) { index: a, face: null, faceIndex: null, + barycoord: null, object: object }; @@ -34995,6 +35218,8 @@ function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, inte point: intersectPoint, index: index, face: null, + faceIndex: null, + barycoord: null, object: object } ); @@ -37497,12 +37722,19 @@ class CylinderGeometry extends BufferGeometry { // faces - indices.push( a, b, d ); - indices.push( b, c, d ); + if ( radiusTop > 0 ) { - // update group counter + indices.push( a, b, d ); + groupCount += 3; - groupCount += 6; + } + + if ( radiusBottom > 0 ) { + + indices.push( b, c, d ); + groupCount += 3; + + } } @@ -45812,7 +46044,7 @@ class MaterialLoader extends Loader { } - const material = MaterialLoader.createMaterialFromType( json.type ); + const material = this.createMaterialFromType( json.type ); if ( json.uuid !== undefined ) material.uuid = json.uuid; if ( json.name !== undefined ) material.name = json.name; @@ -46068,6 +46300,12 @@ class MaterialLoader extends Loader { } + createMaterialFromType( type ) { + + return MaterialLoader.createMaterialFromType( type ); + + } + static createMaterialFromType( type ) { const materialLib = { @@ -47898,7 +48136,7 @@ class Clock { function now() { - return ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732 + return performance.now(); } @@ -48190,7 +48428,7 @@ class Audio extends Object3D { } - stop() { + stop( delay = 0 ) { if ( this.hasPlaybackControl === false ) { @@ -48203,7 +48441,7 @@ class Audio extends Object3D { if ( this.source !== null ) { - this.source.stop(); + this.source.stop( this.context.currentTime + delay ); this.source.onended = null; } @@ -53845,7 +54083,7 @@ class ShapePath { class Controls extends EventDispatcher { - constructor( object, domElement ) { + constructor( object, domElement = null ) { super(); diff --git a/build/three.module.min.js b/build/three.module.min.js index 37ba7e294348c6..424ef1c8e5dd8c 100644 --- a/build/three.module.min.js +++ b/build/three.module.min.js @@ -3,4 +3,4 @@ * Copyright 2010-2024 Three.js Authors * SPDX-License-Identifier: MIT */ -const t="168",e={LEFT:0,MIDDLE:1,RIGHT:2,ROTATE:0,DOLLY:1,PAN:2},n={ROTATE:0,PAN:1,DOLLY_PAN:2,DOLLY_ROTATE:3},i=0,r=1,s=2,a=3,o=0,l=1,c=2,h=3,u=0,d=1,p=2,m=0,f=1,g=2,v=3,_=4,x=5,y=100,M=101,S=102,b=103,w=104,T=200,E=201,A=202,R=203,C=204,P=205,I=206,L=207,U=208,N=209,D=210,O=211,F=212,B=213,z=214,k=0,V=1,H=2,G=3,W=4,X=5,j=6,q=7,Y=0,Z=1,J=2,K=0,$=1,Q=2,tt=3,et=4,nt=5,it=6,rt=7,st="attached",at="detached",ot=300,lt=301,ct=302,ht=303,ut=304,dt=306,pt=1e3,mt=1001,ft=1002,gt=1003,vt=1004,_t=1004,xt=1005,yt=1005,Mt=1006,St=1007,bt=1007,wt=1008,Tt=1008,Et=1009,At=1010,Rt=1011,Ct=1012,Pt=1013,It=1014,Lt=1015,Ut=1016,Nt=1017,Dt=1018,Ot=1020,Ft=35902,Bt=1021,zt=1022,kt=1023,Vt=1024,Ht=1025,Gt=1026,Wt=1027,Xt=1028,jt=1029,qt=1030,Yt=1031,Zt=1032,Jt=1033,Kt=33776,$t=33777,Qt=33778,te=33779,ee=35840,ne=35841,ie=35842,re=35843,se=36196,ae=37492,oe=37496,le=37808,ce=37809,he=37810,ue=37811,de=37812,pe=37813,me=37814,fe=37815,ge=37816,ve=37817,_e=37818,xe=37819,ye=37820,Me=37821,Se=36492,be=36494,we=36495,Te=36283,Ee=36284,Ae=36285,Re=36286,Ce=2200,Pe=2201,Ie=2202,Le=2300,Ue=2301,Ne=2302,De=2400,Oe=2401,Fe=2402,Be=2500,ze=2501,ke=0,Ve=1,He=2,Ge=3200,We=3201,Xe=3202,je=3203,qe=0,Ye=1,Ze="",Je="srgb",Ke="srgb-linear",$e="display-p3",Qe="display-p3-linear",tn="linear",en="srgb",nn="rec709",rn="p3",sn=0,an=7680,on=7681,ln=7682,cn=7683,hn=34055,un=34056,dn=5386,pn=512,mn=513,fn=514,gn=515,vn=516,_n=517,xn=518,yn=519,Mn=512,Sn=513,bn=514,wn=515,Tn=516,En=517,An=518,Rn=519,Cn=35044,Pn=35048,In=35040,Ln=35045,Un=35049,Nn=35041,Dn=35046,On=35050,Fn=35042,Bn="100",zn="300 es",kn=2e3,Vn=2001;class Hn{addEventListener(t,e){void 0===this._listeners&&(this._listeners={});const n=this._listeners;void 0===n[t]&&(n[t]=[]),-1===n[t].indexOf(e)&&n[t].push(e)}hasEventListener(t,e){if(void 0===this._listeners)return!1;const n=this._listeners;return void 0!==n[t]&&-1!==n[t].indexOf(e)}removeEventListener(t,e){if(void 0===this._listeners)return;const n=this._listeners[t];if(void 0!==n){const t=n.indexOf(e);-1!==t&&n.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 n=e.slice(0);for(let e=0,i=n.length;e>8&255]+Gn[t>>16&255]+Gn[t>>24&255]+"-"+Gn[255&e]+Gn[e>>8&255]+"-"+Gn[e>>16&15|64]+Gn[e>>24&255]+"-"+Gn[63&n|128]+Gn[n>>8&255]+"-"+Gn[n>>16&255]+Gn[n>>24&255]+Gn[255&i]+Gn[i>>8&255]+Gn[i>>16&255]+Gn[i>>24&255]).toLowerCase()}function Yn(t,e,n){return Math.max(e,Math.min(n,t))}function Zn(t,e){return(t%e+e)%e}function Jn(t,e,n){return(1-n)*t+n*e}function Kn(t,e){switch(e.constructor){case Float32Array:return t;case Uint32Array:return t/4294967295;case Uint16Array:return t/65535;case Uint8Array:return t/255;case Int32Array:return Math.max(t/2147483647,-1);case Int16Array:return Math.max(t/32767,-1);case Int8Array:return Math.max(t/127,-1);default:throw new Error("Invalid component type.")}}function $n(t,e){switch(e.constructor){case Float32Array:return t;case Uint32Array:return Math.round(4294967295*t);case Uint16Array:return Math.round(65535*t);case Uint8Array:return Math.round(255*t);case Int32Array:return Math.round(2147483647*t);case Int16Array:return Math.round(32767*t);case Int8Array:return Math.round(127*t);default:throw new Error("Invalid component type.")}}const Qn={DEG2RAD:Xn,RAD2DEG:jn,generateUUID:qn,clamp:Yn,euclideanModulo:Zn,mapLinear:function(t,e,n,i,r){return i+(t-e)*(r-i)/(n-e)},inverseLerp:function(t,e,n){return t!==e?(n-t)/(e-t):0},lerp:Jn,damp:function(t,e,n,i){return Jn(t,e,1-Math.exp(-n*i))},pingpong:function(t,e=1){return e-Math.abs(Zn(t,2*e)-e)},smoothstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-e))*t*(3-2*t)},smootherstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-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&&(Wn=t);let e=Wn+=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*Xn},radToDeg:function(t){return t*jn},isPowerOfTwo:function(t){return 0==(t&t-1)&&0!==t},ceilPowerOfTwo:function(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))},floorPowerOfTwo:function(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))},setQuaternionFromProperEuler:function(t,e,n,i,r){const s=Math.cos,a=Math.sin,o=s(n/2),l=a(n/2),c=s((e+i)/2),h=a((e+i)/2),u=s((e-i)/2),d=a((e-i)/2),p=s((i-e)/2),m=a((i-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:$n,denormalize:Kn};class ti{constructor(t=0,e=0){ti.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,n=this.y,i=t.elements;return this.x=i[0]*e+i[3]*n+i[6],this.y=i[1]*e+i[4]*n+i[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 n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}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=Math.trunc(this.x),this.y=Math.trunc(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}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(Yn(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y;return e*e+n*n}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,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,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 n=Math.cos(e),i=Math.sin(e),r=this.x-t.x,s=this.y-t.y;return this.x=r*n-s*i+t.x,this.y=r*i+s*n+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class ei{constructor(t,e,n,i,r,s,a,o,l){ei.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],void 0!==t&&this.set(t,e,n,i,r,s,a,o,l)}set(t,e,n,i,r,s,a,o,l){const c=this.elements;return c[0]=t,c[1]=i,c[2]=a,c[3]=e,c[4]=r,c[5]=o,c[6]=n,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,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],this}extractBasis(t,e,n){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),n.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 n=t.elements,i=e.elements,r=this.elements,s=n[0],a=n[3],o=n[6],l=n[1],c=n[4],h=n[7],u=n[2],d=n[5],p=n[8],m=i[0],f=i[3],g=i[6],v=i[1],_=i[4],x=i[7],y=i[2],M=i[5],S=i[8];return r[0]=s*m+a*v+o*y,r[3]=s*f+a*_+o*M,r[6]=s*g+a*x+o*S,r[1]=l*m+c*v+h*y,r[4]=l*f+c*_+h*M,r[7]=l*g+c*x+h*S,r[2]=u*m+d*v+p*y,r[5]=u*f+d*_+p*M,r[8]=u*g+d*x+p*S,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],n=t[1],i=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-n*r*c+n*a*o+i*r*l-i*s*o}invert(){const t=this.elements,e=t[0],n=t[1],i=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+n*u+i*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]=(i*l-c*n)*m,t[2]=(a*n-i*s)*m,t[3]=u*m,t[4]=(c*e-i*o)*m,t[5]=(i*r-a*e)*m,t[6]=d*m,t[7]=(n*o-l*e)*m,t[8]=(s*e-n*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,n,i,r,s,a){const o=Math.cos(r),l=Math.sin(r);return this.set(n*o,n*l,-n*(o*s+l*a)+s+t,-i*l,i*o,-i*(-l*s+o*a)+a+e,0,0,1),this}scale(t,e){return this.premultiply(ni.makeScale(t,e)),this}rotate(t){return this.premultiply(ni.makeRotation(-t)),this}translate(t,e){return this.premultiply(ni.makeTranslation(t,e)),this}makeTranslation(t,e){return t.isVector2?this.set(1,0,t.x,0,1,t.y,0,0,1):this.set(1,0,t,0,1,e,0,0,1),this}makeRotation(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,n,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,n=t.elements;for(let t=0;t<9;t++)if(e[t]!==n[t])return!1;return!0}fromArray(t,e=0){for(let n=0;n<9;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t}clone(){return(new this.constructor).fromArray(this.elements)}}const ni=new ei;function ii(t){for(let e=t.length-1;e>=0;--e)if(t[e]>=65535)return!0;return!1}const ri={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function si(t,e){return new ri[t](e)}function ai(t){return document.createElementNS("http://www.w3.org/1999/xhtml",t)}function oi(){const t=ai("canvas");return t.style.display="block",t}const li={};function ci(t){t in li||(li[t]=!0,console.warn(t))}const hi=(new ei).set(.8224621,.177538,0,.0331941,.9668058,0,.0170827,.0723974,.9105199),ui=(new ei).set(1.2249401,-.2249404,0,-.0420569,1.0420571,0,-.0196376,-.0786361,1.0982735),di={[Ke]:{transfer:tn,primaries:nn,luminanceCoefficients:[.2126,.7152,.0722],toReference:t=>t,fromReference:t=>t},[Je]:{transfer:en,primaries:nn,luminanceCoefficients:[.2126,.7152,.0722],toReference:t=>t.convertSRGBToLinear(),fromReference:t=>t.convertLinearToSRGB()},[Qe]:{transfer:tn,primaries:rn,luminanceCoefficients:[.2289,.6917,.0793],toReference:t=>t.applyMatrix3(ui),fromReference:t=>t.applyMatrix3(hi)},[$e]:{transfer:en,primaries:rn,luminanceCoefficients:[.2289,.6917,.0793],toReference:t=>t.convertSRGBToLinear().applyMatrix3(ui),fromReference:t=>t.applyMatrix3(hi).convertLinearToSRGB()}},pi=new Set([Ke,Qe]),mi={enabled:!0,_workingColorSpace:Ke,get workingColorSpace(){return this._workingColorSpace},set workingColorSpace(t){if(!pi.has(t))throw new Error(`Unsupported working color space, "${t}".`);this._workingColorSpace=t},convert:function(t,e,n){if(!1===this.enabled||e===n||!e||!n)return t;const i=di[e].toReference;return(0,di[n].fromReference)(i(t))},fromWorkingColorSpace:function(t,e){return this.convert(t,this._workingColorSpace,e)},toWorkingColorSpace:function(t,e){return this.convert(t,e,this._workingColorSpace)},getPrimaries:function(t){return di[t].primaries},getTransfer:function(t){return t===Ze?tn:di[t].transfer},getLuminanceCoefficients:function(t,e=this._workingColorSpace){return t.fromArray(di[e].luminanceCoefficients)}};function fi(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}function gi(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}let vi;class _i{static getDataURL(t){if(/^data:/i.test(t.src))return t.src;if("undefined"==typeof HTMLCanvasElement)return t.src;let e;if(t instanceof HTMLCanvasElement)e=t;else{void 0===vi&&(vi=ai("canvas")),vi.width=t.width,vi.height=t.height;const n=vi.getContext("2d");t instanceof ImageData?n.putImageData(t,0,0):n.drawImage(t,0,0,t.width,t.height),e=vi}return e.width>2048||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=ai("canvas");e.width=t.width,e.height=t.height;const n=e.getContext("2d");n.drawImage(t,0,0,t.width,t.height);const i=n.getImageData(0,0,t.width,t.height),r=i.data;for(let t=0;t0&&(n.userData=this.userData),e||(t.textures[this.uuid]=n),n}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(t){if(this.mapping!==ot)return t;if(t.applyMatrix3(this.matrix),t.x<0||t.x>1)switch(this.wrapS){case pt:t.x=t.x-Math.floor(t.x);break;case mt:t.x=t.x<0?0:1;break;case ft: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 pt:t.y=t.y-Math.floor(t.y);break;case mt:t.y=t.y<0?0:1;break;case ft: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)}set needsPMREMUpdate(t){!0===t&&this.pmremVersion++}}bi.DEFAULT_IMAGE=null,bi.DEFAULT_MAPPING=ot,bi.DEFAULT_ANISOTROPY=1;class wi{constructor(t=0,e=0,n=0,i=1){wi.prototype.isVector4=!0,this.x=t,this.y=e,this.z=n,this.w=i}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,n,i){return this.x=t,this.y=e,this.z=n,this.w=i,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,n=this.y,i=this.z,r=this.w,s=t.elements;return this.x=s[0]*e+s[4]*n+s[8]*i+s[12]*r,this.y=s[1]*e+s[5]*n+s[9]*i+s[13]*r,this.z=s[2]*e+s[6]*n+s[10]*i+s[14]*r,this.w=s[3]*e+s[7]*n+s[11]*i+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,n,i,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,i=1-e*e;if(i>Number.EPSILON){const r=Math.sqrt(i),s=Math.atan2(r,e*n);t=Math.sin(t*s)/r,a=Math.sin(a*s)/r}const r=a*n;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,n,i,r,s){const a=n[i],o=n[i+1],l=n[i+2],c=n[i+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,n,i){return this._x=t,this._y=e,this._z=n,this._w=i,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=!0){const n=t._x,i=t._y,r=t._z,s=t._order,a=Math.cos,o=Math.sin,l=a(n/2),c=a(i/2),h=a(r/2),u=o(n/2),d=o(i/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!0===e&&this._onChangeCallback(),this}setFromAxisAngle(t,e){const n=e/2,i=Math.sin(n);return this._x=t.x*i,this._y=t.y*i,this._z=t.z*i,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,n=e[0],i=e[4],r=e[8],s=e[1],a=e[5],o=e[9],l=e[2],c=e[6],h=e[10],u=n+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-i)*t}else if(n>a&&n>h){const t=2*Math.sqrt(1+n-a-h);this._w=(c-o)/t,this._x=.25*t,this._y=(i+s)/t,this._z=(r+l)/t}else if(a>h){const t=2*Math.sqrt(1+a-n-h);this._w=(r-l)/t,this._x=(i+s)/t,this._y=.25*t,this._z=(o+c)/t}else{const t=2*Math.sqrt(1+h-n-a);this._w=(s-i)/t,this._x=(r+l)/t,this._y=(o+c)/t,this._z=.25*t}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let n=t.dot(e)+1;return nMath.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=n):(this._x=0,this._y=-t.z,this._z=t.y,this._w=n)):(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=n),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(Yn(this.dot(t),-1,1)))}rotateTowards(t,e){const n=this.angleTo(t);if(0===n)return this;const i=Math.min(1,e/n);return this.slerp(t,i),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 n=t._x,i=t._y,r=t._z,s=t._w,a=e._x,o=e._y,l=e._z,c=e._w;return this._x=n*c+s*a+i*l-r*o,this._y=i*c+s*o+r*a-n*l,this._z=r*c+s*l+n*o-i*a,this._w=s*c-n*a-i*o-r*l,this._onChangeCallback(),this}slerp(t,e){if(0===e)return this;if(1===e)return this.copy(t);const n=this._x,i=this._y,r=this._z,s=this._w;let a=s*t._w+n*t._x+i*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=n,this._y=i,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*n+e*this._x,this._y=t*i+e*this._y,this._z=t*r+e*this._z,this.normalize(),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=n*h+this._x*u,this._y=i*h+this._y*u,this._z=r*h+this._z*u,this._onChangeCallback(),this}slerpQuaternions(t,e,n){return this.copy(t).slerp(e,n)}random(){const t=2*Math.PI*Math.random(),e=2*Math.PI*Math.random(),n=Math.random(),i=Math.sqrt(1-n),r=Math.sqrt(n);return this.set(i*Math.sin(t),i*Math.cos(t),r*Math.sin(e),r*Math.cos(e))}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._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class Li{constructor(t=0,e=0,n=0){Li.prototype.isVector3=!0,this.x=t,this.y=e,this.z=n}set(t,e,n){return void 0===n&&(n=this.z),this.x=t,this.y=e,this.z=n,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(Ni.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(Ni.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[3]*n+r[6]*i,this.y=r[1]*e+r[4]*n+r[7]*i,this.z=r[2]*e+r[5]*n+r[8]*i,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,n=this.y,i=this.z,r=t.elements,s=1/(r[3]*e+r[7]*n+r[11]*i+r[15]);return this.x=(r[0]*e+r[4]*n+r[8]*i+r[12])*s,this.y=(r[1]*e+r[5]*n+r[9]*i+r[13])*s,this.z=(r[2]*e+r[6]*n+r[10]*i+r[14])*s,this}applyQuaternion(t){const e=this.x,n=this.y,i=this.z,r=t.x,s=t.y,a=t.z,o=t.w,l=2*(s*i-a*n),c=2*(a*e-r*i),h=2*(r*n-s*e);return this.x=e+o*l+s*h-a*c,this.y=n+o*c+a*l-r*h,this.z=i+o*h+r*c-s*l,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,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[4]*n+r[8]*i,this.y=r[1]*e+r[5]*n+r[9]*i,this.z=r[2]*e+r[6]*n+r[10]*i,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 n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}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=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(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,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this.z=t.z+(e.z-t.z)*n,this}cross(t){return this.crossVectors(this,t)}crossVectors(t,e){const n=t.x,i=t.y,r=t.z,s=e.x,a=e.y,o=e.z;return this.x=i*o-r*a,this.y=r*s-n*o,this.z=n*a-i*s,this}projectOnVector(t){const e=t.lengthSq();if(0===e)return this.set(0,0,0);const n=t.dot(this)/e;return this.copy(t).multiplyScalar(n)}projectOnPlane(t){return Ui.copy(this).projectOnVector(t),this.sub(Ui)}reflect(t){return this.sub(Ui.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 n=this.dot(t)/e;return Math.acos(Yn(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y,i=this.z-t.z;return e*e+n*n+i*i}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,n){const i=Math.sin(e)*t;return this.x=i*Math.sin(n),this.y=Math.cos(e)*t,this.z=i*Math.cos(n),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,n){return this.x=t*Math.sin(e),this.y=n,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(),n=this.setFromMatrixColumn(t,1).length(),i=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=n,this.z=i,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}setFromColor(t){return this.x=t.r,this.y=t.g,this.z=t.b,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=Math.random()*Math.PI*2,e=2*Math.random()-1,n=Math.sqrt(1-e*e);return this.x=n*Math.cos(t),this.y=e,this.z=n*Math.sin(t),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const Ui=new Li,Ni=new Ii;class Di{constructor(t=new Li(1/0,1/0,1/0),e=new Li(-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){this.makeEmpty();for(let e=0,n=t.length;e=this.min.x&&t.x<=this.max.x&&t.y>=this.min.y&&t.y<=this.max.y&&t.z>=this.min.z&&t.z<=this.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.x>=this.min.x&&t.min.x<=this.max.x&&t.max.y>=this.min.y&&t.min.y<=this.max.y&&t.max.z>=this.min.z&&t.min.z<=this.max.z}intersectsSphere(t){return this.clampPoint(t.center,Fi),Fi.distanceToSquared(t.center)<=t.radius*t.radius}intersectsPlane(t){let e,n;return t.normal.x>0?(e=t.normal.x*this.min.x,n=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,n=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,n+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,n+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,n+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,n+=t.normal.z*this.min.z),e<=-t.constant&&n>=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(Xi),ji.subVectors(this.max,Xi),zi.subVectors(t.a,Xi),ki.subVectors(t.b,Xi),Vi.subVectors(t.c,Xi),Hi.subVectors(ki,zi),Gi.subVectors(Vi,ki),Wi.subVectors(zi,Vi);let e=[0,-Hi.z,Hi.y,0,-Gi.z,Gi.y,0,-Wi.z,Wi.y,Hi.z,0,-Hi.x,Gi.z,0,-Gi.x,Wi.z,0,-Wi.x,-Hi.y,Hi.x,0,-Gi.y,Gi.x,0,-Wi.y,Wi.x,0];return!!Zi(e,zi,ki,Vi,ji)&&(e=[1,0,0,0,1,0,0,0,1],!!Zi(e,zi,ki,Vi,ji)&&(qi.crossVectors(Hi,Gi),e=[qi.x,qi.y,qi.z],Zi(e,zi,ki,Vi,ji)))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,Fi).distanceTo(t)}getBoundingSphere(t){return this.isEmpty()?t.makeEmpty():(this.getCenter(t.center),t.radius=.5*this.getSize(Fi).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()||(Oi[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),Oi[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),Oi[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),Oi[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),Oi[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),Oi[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),Oi[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),Oi[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(Oi)),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 Oi=[new Li,new Li,new Li,new Li,new Li,new Li,new Li,new Li],Fi=new Li,Bi=new Di,zi=new Li,ki=new Li,Vi=new Li,Hi=new Li,Gi=new Li,Wi=new Li,Xi=new Li,ji=new Li,qi=new Li,Yi=new Li;function Zi(t,e,n,i,r){for(let s=0,a=t.length-3;s<=a;s+=3){Yi.fromArray(t,s);const a=r.x*Math.abs(Yi.x)+r.y*Math.abs(Yi.y)+r.z*Math.abs(Yi.z),o=e.dot(Yi),l=n.dot(Yi),c=i.dot(Yi);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))>a)return!1}return!0}const Ji=new Di,Ki=new Li,$i=new Li;class Qi{constructor(t=new Li,e=-1){this.isSphere=!0,this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const n=this.center;void 0!==e?n.copy(e):Ji.setFromPoints(t).getCenter(n);let i=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;Ki.subVectors(t,this.center);const e=Ki.lengthSq();if(e>this.radius*this.radius){const t=Math.sqrt(e),n=.5*(t-this.radius);this.center.addScaledVector(Ki,n/t),this.radius+=n}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):($i.subVectors(t.center,this.center).setLength(t.radius),this.expandByPoint(Ki.copy(t.center).add($i)),this.expandByPoint(Ki.copy(t.center).sub($i))),this)}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const tr=new Li,er=new Li,nr=new Li,ir=new Li,rr=new Li,sr=new Li,ar=new Li;class or{constructor(t=new Li,e=new Li(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.origin).addScaledVector(this.direction,t)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,tr)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const n=e.dot(this.direction);return n<0?e.copy(this.origin):e.copy(this.origin).addScaledVector(this.direction,n)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=tr.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):(tr.copy(this.origin).addScaledVector(this.direction,e),tr.distanceToSquared(t))}distanceSqToSegment(t,e,n,i){er.copy(t).add(e).multiplyScalar(.5),nr.copy(e).sub(t).normalize(),ir.copy(this.origin).sub(er);const r=.5*t.distanceTo(e),s=-this.direction.dot(nr),a=ir.dot(this.direction),o=-ir.dot(nr),l=ir.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 n&&n.copy(this.origin).addScaledVector(this.direction,h),i&&i.copy(er).addScaledVector(nr,u),d}intersectSphere(t,e){tr.subVectors(t.center,this.origin);const n=tr.dot(this.direction),i=tr.dot(tr)-n*n,r=t.radius*t.radius;if(i>r)return null;const s=Math.sqrt(r-i),a=n-s,o=n+s;return 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 n=-(this.origin.dot(t.normal)+t.constant)/e;return n>=0?n:null}intersectPlane(t,e){const n=this.distanceToPlane(t);return null===n?null:this.at(n,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 n,i,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?(n=(t.min.x-u.x)*l,i=(t.max.x-u.x)*l):(n=(t.max.x-u.x)*l,i=(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),n>s||r>i?null:((r>n||isNaN(n))&&(n=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),n>o||a>i?null:((a>n||n!=n)&&(n=a),(o=0?n:i,e)))}intersectsBox(t){return null!==this.intersectBox(t,tr)}intersectTriangle(t,e,n,i,r){rr.subVectors(e,t),sr.subVectors(n,t),ar.crossVectors(rr,sr);let s,a=this.direction.dot(ar);if(a>0){if(i)return null;s=1}else{if(!(a<0))return null;s=-1,a=-a}ir.subVectors(this.origin,t);const o=s*this.direction.dot(sr.crossVectors(ir,sr));if(o<0)return null;const l=s*this.direction.dot(rr.cross(ir));if(l<0)return null;if(o+l>a)return null;const c=-s*ir.dot(ar);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 lr{constructor(t,e,n,i,r,s,a,o,l,c,h,u,d,p,m,f){lr.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],void 0!==t&&this.set(t,e,n,i,r,s,a,o,l,c,h,u,d,p,m,f)}set(t,e,n,i,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]=n,g[12]=i,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 lr).fromArray(this.elements)}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],e[9]=n[9],e[10]=n[10],e[11]=n[11],e[12]=n[12],e[13]=n[13],e[14]=n[14],e[15]=n[15],this}copyPosition(t){const e=this.elements,n=t.elements;return e[12]=n[12],e[13]=n[13],e[14]=n[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,n){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this}makeBasis(t,e,n){return this.set(t.x,e.x,n.x,0,t.y,e.y,n.y,0,t.z,e.z,n.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,n=t.elements,i=1/cr.setFromMatrixColumn(t,0).length(),r=1/cr.setFromMatrixColumn(t,1).length(),s=1/cr.setFromMatrixColumn(t,2).length();return e[0]=n[0]*i,e[1]=n[1]*i,e[2]=n[2]*i,e[3]=0,e[4]=n[4]*r,e[5]=n[5]*r,e[6]=n[6]*r,e[7]=0,e[8]=n[8]*s,e[9]=n[9]*s,e[10]=n[10]*s,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){const e=this.elements,n=t.x,i=t.y,r=t.z,s=Math.cos(n),a=Math.sin(n),o=Math.cos(i),l=Math.sin(i),c=Math.cos(r),h=Math.sin(r);if("XYZ"===t.order){const t=s*c,n=s*h,i=a*c,r=a*h;e[0]=o*c,e[4]=-o*h,e[8]=l,e[1]=n+i*l,e[5]=t-r*l,e[9]=-a*o,e[2]=r-t*l,e[6]=i+n*l,e[10]=s*o}else if("YXZ"===t.order){const t=o*c,n=o*h,i=l*c,r=l*h;e[0]=t+r*a,e[4]=i*a-n,e[8]=s*l,e[1]=s*h,e[5]=s*c,e[9]=-a,e[2]=n*a-i,e[6]=r+t*a,e[10]=s*o}else if("ZXY"===t.order){const t=o*c,n=o*h,i=l*c,r=l*h;e[0]=t-r*a,e[4]=-s*h,e[8]=i+n*a,e[1]=n+i*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,n=s*h,i=a*c,r=a*h;e[0]=o*c,e[4]=i*l-n,e[8]=t*l+r,e[1]=o*h,e[5]=r*l+t,e[9]=n*l-i,e[2]=-l,e[6]=a*o,e[10]=s*o}else if("YZX"===t.order){const t=s*o,n=s*l,i=a*o,r=a*l;e[0]=o*c,e[4]=r-t*h,e[8]=i*h+n,e[1]=h,e[5]=s*c,e[9]=-a*c,e[2]=-l*c,e[6]=n*h+i,e[10]=t-r*h}else if("XZY"===t.order){const t=s*o,n=s*l,i=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]=n*h-i,e[2]=i*h-n,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(ur,t,dr)}lookAt(t,e,n){const i=this.elements;return fr.subVectors(t,e),0===fr.lengthSq()&&(fr.z=1),fr.normalize(),pr.crossVectors(n,fr),0===pr.lengthSq()&&(1===Math.abs(n.z)?fr.x+=1e-4:fr.z+=1e-4,fr.normalize(),pr.crossVectors(n,fr)),pr.normalize(),mr.crossVectors(fr,pr),i[0]=pr.x,i[4]=mr.x,i[8]=fr.x,i[1]=pr.y,i[5]=mr.y,i[9]=fr.y,i[2]=pr.z,i[6]=mr.z,i[10]=fr.z,this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,i=e.elements,r=this.elements,s=n[0],a=n[4],o=n[8],l=n[12],c=n[1],h=n[5],u=n[9],d=n[13],p=n[2],m=n[6],f=n[10],g=n[14],v=n[3],_=n[7],x=n[11],y=n[15],M=i[0],S=i[4],b=i[8],w=i[12],T=i[1],E=i[5],A=i[9],R=i[13],C=i[2],P=i[6],I=i[10],L=i[14],U=i[3],N=i[7],D=i[11],O=i[15];return r[0]=s*M+a*T+o*C+l*U,r[4]=s*S+a*E+o*P+l*N,r[8]=s*b+a*A+o*I+l*D,r[12]=s*w+a*R+o*L+l*O,r[1]=c*M+h*T+u*C+d*U,r[5]=c*S+h*E+u*P+d*N,r[9]=c*b+h*A+u*I+d*D,r[13]=c*w+h*R+u*L+d*O,r[2]=p*M+m*T+f*C+g*U,r[6]=p*S+m*E+f*P+g*N,r[10]=p*b+m*A+f*I+g*D,r[14]=p*w+m*R+f*L+g*O,r[3]=v*M+_*T+x*C+y*U,r[7]=v*S+_*E+x*P+y*N,r[11]=v*b+_*A+x*I+y*D,r[15]=v*w+_*R+x*L+y*O,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],n=t[4],i=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-i*l*h-r*a*u+n*l*u+i*a*d-n*o*d)+t[7]*(+e*o*d-e*l*u+r*s*u-i*s*d+i*l*c-r*o*c)+t[11]*(+e*l*h-e*a*d-r*s*h+n*s*d+r*a*c-n*l*c)+t[15]*(-i*a*c-e*o*h+e*a*u+i*s*h-n*s*u+n*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,n){const i=this.elements;return t.isVector3?(i[12]=t.x,i[13]=t.y,i[14]=t.z):(i[12]=t,i[13]=e,i[14]=n),this}invert(){const t=this.elements,e=t[0],n=t[1],i=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,_=p*u*l-c*f*l-p*o*d+s*f*d+c*o*g-s*u*g,x=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+n*_+i*x+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 S=1/M;return t[0]=v*S,t[1]=(m*u*r-h*f*r-m*i*d+n*f*d+h*i*g-n*u*g)*S,t[2]=(a*f*r-m*o*r+m*i*l-n*f*l-a*i*g+n*o*g)*S,t[3]=(h*o*r-a*u*r-h*i*l+n*u*l+a*i*d-n*o*d)*S,t[4]=_*S,t[5]=(c*f*r-p*u*r+p*i*d-e*f*d-c*i*g+e*u*g)*S,t[6]=(p*o*r-s*f*r-p*i*l+e*f*l+s*i*g-e*o*g)*S,t[7]=(s*u*r-c*o*r+c*i*l-e*u*l-s*i*d+e*o*d)*S,t[8]=x*S,t[9]=(p*h*r-c*m*r-p*n*d+e*m*d+c*n*g-e*h*g)*S,t[10]=(s*m*r-p*a*r+p*n*l-e*m*l-s*n*g+e*a*g)*S,t[11]=(c*a*r-s*h*r-c*n*l+e*h*l+s*n*d-e*a*d)*S,t[12]=y*S,t[13]=(c*m*i-p*h*i+p*n*u-e*m*u-c*n*f+e*h*f)*S,t[14]=(p*a*i-s*m*i-p*n*o+e*m*o+s*n*f-e*a*f)*S,t[15]=(s*h*i-c*a*i+c*n*o-e*h*o-s*n*u+e*a*u)*S,this}scale(t){const e=this.elements,n=t.x,i=t.y,r=t.z;return e[0]*=n,e[4]*=i,e[8]*=r,e[1]*=n,e[5]*=i,e[9]*=r,e[2]*=n,e[6]*=i,e[10]*=r,e[3]*=n,e[7]*=i,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],n=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],i=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,n,i))}makeTranslation(t,e,n){return t.isVector3?this.set(1,0,0,t.x,0,1,0,t.y,0,0,1,t.z,0,0,0,1):this.set(1,0,0,t,0,1,0,e,0,0,1,n,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),n=Math.sin(t);return this.set(1,0,0,0,0,e,-n,0,0,n,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,0,n,0,0,1,0,0,-n,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,0,n,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const n=Math.cos(e),i=Math.sin(e),r=1-n,s=t.x,a=t.y,o=t.z,l=r*s,c=r*a;return this.set(l*s+n,l*a-i*o,l*o+i*a,0,l*a+i*o,c*a+n,c*o-i*s,0,l*o-i*a,c*o+i*s,r*o*o+n,0,0,0,0,1),this}makeScale(t,e,n){return this.set(t,0,0,0,0,e,0,0,0,0,n,0,0,0,0,1),this}makeShear(t,e,n,i,r,s){return this.set(1,n,r,0,t,1,s,0,e,i,1,0,0,0,0,1),this}compose(t,e,n){const i=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,_=o*c,x=o*h,y=n.x,M=n.y,S=n.z;return i[0]=(1-(m+g))*y,i[1]=(d+x)*y,i[2]=(p-_)*y,i[3]=0,i[4]=(d-x)*M,i[5]=(1-(u+g))*M,i[6]=(f+v)*M,i[7]=0,i[8]=(p+_)*S,i[9]=(f-v)*S,i[10]=(1-(u+m))*S,i[11]=0,i[12]=t.x,i[13]=t.y,i[14]=t.z,i[15]=1,this}decompose(t,e,n){const i=this.elements;let r=cr.set(i[0],i[1],i[2]).length();const s=cr.set(i[4],i[5],i[6]).length(),a=cr.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),t.x=i[12],t.y=i[13],t.z=i[14],hr.copy(this);const o=1/r,l=1/s,c=1/a;return hr.elements[0]*=o,hr.elements[1]*=o,hr.elements[2]*=o,hr.elements[4]*=l,hr.elements[5]*=l,hr.elements[6]*=l,hr.elements[8]*=c,hr.elements[9]*=c,hr.elements[10]*=c,e.setFromRotationMatrix(hr),n.x=r,n.y=s,n.z=a,this}makePerspective(t,e,n,i,r,s,a=2e3){const o=this.elements,l=2*r/(e-t),c=2*r/(n-i),h=(e+t)/(e-t),u=(n+i)/(n-i);let d,p;if(a===kn)d=-(s+r)/(s-r),p=-2*s*r/(s-r);else{if(a!==Vn)throw new Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: "+a);d=-s/(s-r),p=-s*r/(s-r)}return o[0]=l,o[4]=0,o[8]=h,o[12]=0,o[1]=0,o[5]=c,o[9]=u,o[13]=0,o[2]=0,o[6]=0,o[10]=d,o[14]=p,o[3]=0,o[7]=0,o[11]=-1,o[15]=0,this}makeOrthographic(t,e,n,i,r,s,a=2e3){const o=this.elements,l=1/(e-t),c=1/(n-i),h=1/(s-r),u=(e+t)*l,d=(n+i)*c;let p,m;if(a===kn)p=(s+r)*h,m=-2*h;else{if(a!==Vn)throw new Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: "+a);p=r*h,m=-1*h}return o[0]=2*l,o[4]=0,o[8]=0,o[12]=-u,o[1]=0,o[5]=2*c,o[9]=0,o[13]=-d,o[2]=0,o[6]=0,o[10]=m,o[14]=-p,o[3]=0,o[7]=0,o[11]=0,o[15]=1,this}equals(t){const e=this.elements,n=t.elements;for(let t=0;t<16;t++)if(e[t]!==n[t])return!1;return!0}fromArray(t,e=0){for(let n=0;n<16;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t[e+9]=n[9],t[e+10]=n[10],t[e+11]=n[11],t[e+12]=n[12],t[e+13]=n[13],t[e+14]=n[14],t[e+15]=n[15],t}}const cr=new Li,hr=new lr,ur=new Li(0,0,0),dr=new Li(1,1,1),pr=new Li,mr=new Li,fr=new Li,gr=new lr,vr=new Ii;class _r{constructor(t=0,e=0,n=0,i=_r.DEFAULT_ORDER){this.isEuler=!0,this._x=t,this._y=e,this._z=n,this._order=i}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,n,i=this._order){return this._x=t,this._y=e,this._z=n,this._order=i,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,n=!0){const i=t.elements,r=i[0],s=i[4],a=i[8],o=i[1],l=i[5],c=i[9],h=i[2],u=i[6],d=i[10];switch(e){case"XYZ":this._y=Math.asin(Yn(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(-Yn(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(Yn(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(-Yn(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(Yn(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(-Yn(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===n&&this._onChangeCallback(),this}setFromQuaternion(t,e,n){return gr.makeRotationFromQuaternion(t),this.setFromRotationMatrix(gr,e,n)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return vr.setFromEuler(this),this.setFromQuaternion(vr,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}}_r.DEFAULT_ORDER="XYZ";class xr{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&&(i.userData=this.userData),i.layers=this.layers.mask,i.matrix=this.matrix.toArray(),i.up=this.up.toArray(),!1===this.matrixAutoUpdate&&(i.matrixAutoUpdate=!1),this.isInstancedMesh&&(i.type="InstancedMesh",i.count=this.count,i.instanceMatrix=this.instanceMatrix.toJSON(),null!==this.instanceColor&&(i.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(i.type="BatchedMesh",i.perObjectFrustumCulled=this.perObjectFrustumCulled,i.sortObjects=this.sortObjects,i.drawRanges=this._drawRanges,i.reservedRanges=this._reservedRanges,i.visibility=this._visibility,i.active=this._active,i.bounds=this._bounds.map((t=>({boxInitialized:t.boxInitialized,boxMin:t.box.min.toArray(),boxMax:t.box.max.toArray(),sphereInitialized:t.sphereInitialized,sphereRadius:t.sphere.radius,sphereCenter:t.sphere.center.toArray()}))),i.maxInstanceCount=this._maxInstanceCount,i.maxVertexCount=this._maxVertexCount,i.maxIndexCount=this._maxIndexCount,i.geometryInitialized=this._geometryInitialized,i.geometryCount=this._geometryCount,i.matricesTexture=this._matricesTexture.toJSON(t),null!==this._colorsTexture&&(i.colorsTexture=this._colorsTexture.toJSON(t)),null!==this.boundingSphere&&(i.boundingSphere={center:i.boundingSphere.center.toArray(),radius:i.boundingSphere.radius}),null!==this.boundingBox&&(i.boundingBox={min:i.boundingBox.min.toArray(),max:i.boundingBox.max.toArray()})),this.isScene)this.background&&(this.background.isColor?i.background=this.background.toJSON():this.background.isTexture&&(i.background=this.background.toJSON(t).uuid)),this.environment&&this.environment.isTexture&&!0!==this.environment.isRenderTargetTexture&&(i.environment=this.environment.toJSON(t).uuid);else if(this.isMesh||this.isLine||this.isPoints){i.geometry=r(t.geometries,this.geometry);const e=this.geometry.parameters;if(void 0!==e&&void 0!==e.shapes){const n=e.shapes;if(Array.isArray(n))for(let e=0,i=n.length;e0){i.children=[];for(let e=0;e0){i.animations=[];for(let e=0;e0&&(n.geometries=e),i.length>0&&(n.materials=i),r.length>0&&(n.textures=r),a.length>0&&(n.images=a),o.length>0&&(n.shapes=o),l.length>0&&(n.skeletons=l),c.length>0&&(n.animations=c),h.length>0&&(n.nodes=h)}return n.object=i,n;function s(t){const e=[];for(const n in t){const i=t[n];delete i.metadata,e.push(i)}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.matrixWorldAutoUpdate=t.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,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.animations=t.animations.slice(),this.userData=JSON.parse(JSON.stringify(t.userData)),!0===e)for(let e=0;e0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(t,e,n,i,r){Or.subVectors(i,e),Fr.subVectors(n,e),Br.subVectors(t,e);const s=Or.dot(Or),a=Or.dot(Fr),o=Or.dot(Br),l=Fr.dot(Fr),c=Fr.dot(Br),h=s*l-a*a;if(0===h)return r.set(0,0,0),null;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,n,i){return null!==this.getBarycoord(t,e,n,i,zr)&&(zr.x>=0&&zr.y>=0&&zr.x+zr.y<=1)}static getInterpolation(t,e,n,i,r,s,a,o){return null===this.getBarycoord(t,e,n,i,zr)?(o.x=0,o.y=0,"z"in o&&(o.z=0),"w"in o&&(o.w=0),null):(o.setScalar(0),o.addScaledVector(r,zr.x),o.addScaledVector(s,zr.y),o.addScaledVector(a,zr.z),o)}static isFrontFacing(t,e,n,i){return Or.subVectors(n,e),Fr.subVectors(t,e),Or.cross(Fr).dot(i)<0}set(t,e,n){return this.a.copy(t),this.b.copy(e),this.c.copy(n),this}setFromPointsAndIndices(t,e,n,i){return this.a.copy(t[e]),this.b.copy(t[n]),this.c.copy(t[i]),this}setFromAttributeAndIndices(t,e,n,i){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,n),this.c.fromBufferAttribute(t,i),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 Or.subVectors(this.c,this.b),Fr.subVectors(this.a,this.b),.5*Or.cross(Fr).length()}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return jr.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return jr.getBarycoord(t,this.a,this.b,this.c,e)}getInterpolation(t,e,n,i,r){return jr.getInterpolation(t,this.a,this.b,this.c,e,n,i,r)}containsPoint(t){return jr.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return jr.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const n=this.a,i=this.b,r=this.c;let s,a;kr.subVectors(i,n),Vr.subVectors(r,n),Gr.subVectors(t,n);const o=kr.dot(Gr),l=Vr.dot(Gr);if(o<=0&&l<=0)return e.copy(n);Wr.subVectors(t,i);const c=kr.dot(Wr),h=Vr.dot(Wr);if(c>=0&&h<=c)return e.copy(i);const u=o*h-c*l;if(u<=0&&o>=0&&c<=0)return s=o/(o-c),e.copy(n).addScaledVector(kr,s);Xr.subVectors(t,r);const d=kr.dot(Xr),p=Vr.dot(Xr);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(n).addScaledVector(Vr,a);const f=c*p-d*h;if(f<=0&&h-c>=0&&d-p>=0)return Hr.subVectors(r,i),a=(h-c)/(h-c+(d-p)),e.copy(i).addScaledVector(Hr,a);const g=1/(f+m+u);return s=m*g,a=u*g,e.copy(n).addScaledVector(kr,s).addScaledVector(Vr,a)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}const qr={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},Yr={h:0,s:0,l:0},Zr={h:0,s:0,l:0};function Jr(t,e,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?t+6*(e-t)*n:n<.5?e:n<2/3?t+6*(e-t)*(2/3-n):t}class Kr{constructor(t,e,n){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(t,e,n)}set(t,e,n){if(void 0===e&&void 0===n){const e=t;e&&e.isColor?this.copy(e):"number"==typeof e?this.setHex(e):"string"==typeof e&&this.setStyle(e)}else this.setRGB(t,e,n);return this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t,e=Je){return t=Math.floor(t),this.r=(t>>16&255)/255,this.g=(t>>8&255)/255,this.b=(255&t)/255,mi.toWorkingColorSpace(this,e),this}setRGB(t,e,n,i=mi.workingColorSpace){return this.r=t,this.g=e,this.b=n,mi.toWorkingColorSpace(this,i),this}setHSL(t,e,n,i=mi.workingColorSpace){if(t=Zn(t,1),e=Yn(e,0,1),n=Yn(n,0,1),0===e)this.r=this.g=this.b=n;else{const i=n<=.5?n*(1+e):n+e-n*e,r=2*n-i;this.r=Jr(r,i,t+1/3),this.g=Jr(r,i,t),this.b=Jr(r,i,t-1/3)}return mi.toWorkingColorSpace(this,i),this}setStyle(t,e=Je){function n(e){void 0!==e&&parseFloat(e)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}let i;if(i=/^(\w+)\(([^\)]*)\)/.exec(t)){let r;const s=i[1],a=i[2];switch(s){case"rgb":case"rgba":if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,e);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,e);break;case"hsl":case"hsla":if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,e);break;default:console.warn("THREE.Color: Unknown color model "+t)}}else if(i=/^\#([A-Fa-f\d]+)$/.exec(t)){const n=i[1],r=n.length;if(3===r)return this.setRGB(parseInt(n.charAt(0),16)/15,parseInt(n.charAt(1),16)/15,parseInt(n.charAt(2),16)/15,e);if(6===r)return this.setHex(parseInt(n,16),e);console.warn("THREE.Color: Invalid hex color "+t)}else if(t&&t.length>0)return this.setColorName(t,e);return this}setColorName(t,e=Je){const n=qr[t.toLowerCase()];return void 0!==n?this.setHex(n,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=fi(t.r),this.g=fi(t.g),this.b=fi(t.b),this}copyLinearToSRGB(t){return this.r=gi(t.r),this.g=gi(t.g),this.b=gi(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(t=Je){return mi.fromWorkingColorSpace($r.copy(this),t),65536*Math.round(Yn(255*$r.r,0,255))+256*Math.round(Yn(255*$r.g,0,255))+Math.round(Yn(255*$r.b,0,255))}getHexString(t=Je){return("000000"+this.getHex(t).toString(16)).slice(-6)}getHSL(t,e=mi.workingColorSpace){mi.fromWorkingColorSpace($r.copy(this),e);const n=$r.r,i=$r.g,r=$r.b,s=Math.max(n,i,r),a=Math.min(n,i,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 n:o=(i-r)/t+(i0!=t>0&&this.version++,this._alphaTest=t}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(void 0!==t)for(const e in t){const n=t[e];if(void 0===n){console.warn(`THREE.Material: parameter '${e}' has value of undefined.`);continue}const i=this[e];void 0!==i?i&&i.isColor?i.set(n):i&&i.isVector3&&n&&n.isVector3?i.copy(n):this[e]=n:console.warn(`THREE.Material: '${e}' is not a property of THREE.${this.type}.`)}}toJSON(t){const e=void 0===t||"string"==typeof t;e&&(t={textures:{},images:{}});const n={metadata:{version:4.6,type:"Material",generator:"Material.toJSON"}};function i(t){const e=[];for(const n in t){const i=t[n];delete i.metadata,e.push(i)}return e}if(n.uuid=this.uuid,n.type=this.type,""!==this.name&&(n.name=this.name),this.color&&this.color.isColor&&(n.color=this.color.getHex()),void 0!==this.roughness&&(n.roughness=this.roughness),void 0!==this.metalness&&(n.metalness=this.metalness),void 0!==this.sheen&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),void 0!==this.emissiveIntensity&&1!==this.emissiveIntensity&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(n.shininess=this.shininess),void 0!==this.clearcoat&&(n.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.dispersion&&(n.dispersion=this.dispersion),void 0!==this.iridescence&&(n.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(n.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(n.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(n.iridescenceMap=this.iridescenceMap.toJSON(t).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(n.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(t).uuid),void 0!==this.anisotropy&&(n.anisotropy=this.anisotropy),void 0!==this.anisotropyRotation&&(n.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(n.anisotropyMap=this.anisotropyMap.toJSON(t).uuid),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(t).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(t).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(t).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(t).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(t).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(t).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(t).uuid,void 0!==this.combine&&(n.combine=this.combine)),void 0!==this.envMapRotation&&(n.envMapRotation=this.envMapRotation.toArray()),void 0!==this.envMapIntensity&&(n.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(n.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(t).uuid),void 0!==this.transmission&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(t).uuid),void 0!==this.thickness&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(t).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(n.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(n.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(n.size=this.size),null!==this.shadowSide&&(n.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(n.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(n.blending=this.blending),this.side!==u&&(n.side=this.side),!0===this.vertexColors&&(n.vertexColors=!0),this.opacity<1&&(n.opacity=this.opacity),!0===this.transparent&&(n.transparent=!0),this.blendSrc!==C&&(n.blendSrc=this.blendSrc),this.blendDst!==P&&(n.blendDst=this.blendDst),this.blendEquation!==y&&(n.blendEquation=this.blendEquation),null!==this.blendSrcAlpha&&(n.blendSrcAlpha=this.blendSrcAlpha),null!==this.blendDstAlpha&&(n.blendDstAlpha=this.blendDstAlpha),null!==this.blendEquationAlpha&&(n.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&&this.blendColor.isColor&&(n.blendColor=this.blendColor.getHex()),0!==this.blendAlpha&&(n.blendAlpha=this.blendAlpha),3!==this.depthFunc&&(n.depthFunc=this.depthFunc),!1===this.depthTest&&(n.depthTest=this.depthTest),!1===this.depthWrite&&(n.depthWrite=this.depthWrite),!1===this.colorWrite&&(n.colorWrite=this.colorWrite),255!==this.stencilWriteMask&&(n.stencilWriteMask=this.stencilWriteMask),519!==this.stencilFunc&&(n.stencilFunc=this.stencilFunc),0!==this.stencilRef&&(n.stencilRef=this.stencilRef),255!==this.stencilFuncMask&&(n.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==an&&(n.stencilFail=this.stencilFail),this.stencilZFail!==an&&(n.stencilZFail=this.stencilZFail),this.stencilZPass!==an&&(n.stencilZPass=this.stencilZPass),!0===this.stencilWrite&&(n.stencilWrite=this.stencilWrite),void 0!==this.rotation&&0!==this.rotation&&(n.rotation=this.rotation),!0===this.polygonOffset&&(n.polygonOffset=!0),0!==this.polygonOffsetFactor&&(n.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(n.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(n.linewidth=this.linewidth),void 0!==this.dashSize&&(n.dashSize=this.dashSize),void 0!==this.gapSize&&(n.gapSize=this.gapSize),void 0!==this.scale&&(n.scale=this.scale),!0===this.dithering&&(n.dithering=!0),this.alphaTest>0&&(n.alphaTest=this.alphaTest),!0===this.alphaHash&&(n.alphaHash=!0),!0===this.alphaToCoverage&&(n.alphaToCoverage=!0),!0===this.premultipliedAlpha&&(n.premultipliedAlpha=!0),!0===this.forceSinglePass&&(n.forceSinglePass=!0),!0===this.wireframe&&(n.wireframe=!0),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(n.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(n.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(n.flatShading=!0),!1===this.visible&&(n.visible=!1),!1===this.toneMapped&&(n.toneMapped=!1),!1===this.fog&&(n.fog=!1),Object.keys(this.userData).length>0&&(n.userData=this.userData),e){const e=i(t.textures),r=i(t.images);e.length>0&&(n.textures=e),r.length>0&&(n.images=r)}return n}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.blendColor.copy(t.blendColor),this.blendAlpha=t.blendAlpha,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 n=null;if(null!==e){const t=e.length;n=new Array(t);for(let i=0;i!==t;++i)n[i]=e[i].clone()}return this.clippingPlanes=n,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.alphaHash=t.alphaHash,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.forceSinglePass=t.forceSinglePass,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++}onBuild(){console.warn("Material: onBuild() has been removed.")}}class es extends ts{constructor(t){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new Kr(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.envMapRotation=new _r,this.combine=Y,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.envMapRotation.copy(t.envMapRotation),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 ns=is();function is(){const t=new ArrayBuffer(4),e=new Float32Array(t),n=new Uint32Array(t),i=new Uint32Array(512),r=new Uint32Array(512);for(let t=0;t<256;++t){const e=t-127;e<-27?(i[t]=0,i[256|t]=32768,r[t]=24,r[256|t]=24):e<-14?(i[t]=1024>>-e-14,i[256|t]=1024>>-e-14|32768,r[t]=-e-1,r[256|t]=-e-1):e<=15?(i[t]=e+15<<10,i[256|t]=e+15<<10|32768,r[t]=13,r[256|t]=13):e<128?(i[t]=31744,i[256|t]=64512,r[t]=24,r[256|t]=24):(i[t]=31744,i[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,n=0;for(;0==(8388608&e);)e<<=1,n-=8388608;e&=-8388609,n+=947912704,s[t]=e|n}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:n,baseTable:i,shiftTable:r,mantissaTable:s,exponentTable:a,offsetTable:o}}function rs(t){Math.abs(t)>65504&&console.warn("THREE.DataUtils.toHalfFloat(): Value out of range."),t=Yn(t,-65504,65504),ns.floatView[0]=t;const e=ns.uint32View[0],n=e>>23&511;return ns.baseTable[n]+((8388607&e)>>ns.shiftTable[n])}function ss(t){const e=t>>10;return ns.uint32View[0]=ns.mantissaTable[ns.offsetTable[e]+(1023&t)]+ns.exponentTable[e],ns.floatView[0]}const as={toHalfFloat:rs,fromHalfFloat:ss},os=new Li,ls=new ti;class cs{constructor(t,e,n=!1){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=n,this.usage=Cn,this._updateRange={offset:0,count:-1},this.updateRanges=[],this.gpuType=Lt,this.version=0}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}get updateRange(){return ci("THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead."),this._updateRange}setUsage(t){return this.usage=t,this}addUpdateRange(t,e){this.updateRanges.push({start:t,count:e})}clearUpdateRanges(){this.updateRanges.length=0}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.gpuType=t.gpuType,this}copyAt(t,e,n){t*=this.itemSize,n*=e.itemSize;for(let i=0,r=this.itemSize;i0&&(t.userData=this.userData),void 0!==this.parameters){const e=this.parameters;for(const n in e)void 0!==e[n]&&(t[n]=e[n]);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 n=this.attributes;for(const e in n){const i=n[e];t.data.attributes[e]=i.toJSON(t.data)}const i={};let r=!1;for(const e in this.morphAttributes){const n=this.morphAttributes[e],s=[];for(let e=0,i=n.length;e0&&(i[e]=s,r=!0)}r&&(t.data.morphAttributes=i,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 n=t.index;null!==n&&this.setIndex(n.clone(e));const i=t.attributes;for(const t in i){const n=i[t];this.setAttribute(t,n.clone(e))}const r=t.morphAttributes;for(const t in r){const n=[],i=r[t];for(let t=0,r=i.length;t0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;t(t.far-t.near)**2)return}As.copy(r).invert(),Rs.copy(t.ray).applyMatrix4(As),null!==n.boundingBox&&!1===Rs.intersectsBox(n.boundingBox)||this._computeIntersections(t,e,Rs)}}_computeIntersections(t,e,n){let i;const r=this.geometry,s=this.material,a=r.index,o=r.attributes.position,l=r.attributes.uv,c=r.attributes.uv1,h=r.attributes.normal,u=r.groups,d=r.drawRange;if(null!==a)if(Array.isArray(s))for(let r=0,o=u.length;rn.far?null:{distance:c,point:Gs.clone(),object:t}}(t,e,n,i,Is,Ls,Us,Hs);if(h){r&&(Os.fromBufferAttribute(r,o),Fs.fromBufferAttribute(r,l),Bs.fromBufferAttribute(r,c),h.uv=jr.getInterpolation(Hs,Is,Ls,Us,Os,Fs,Bs,new ti)),s&&(Os.fromBufferAttribute(s,o),Fs.fromBufferAttribute(s,l),Bs.fromBufferAttribute(s,c),h.uv1=jr.getInterpolation(Hs,Is,Ls,Us,Os,Fs,Bs,new ti)),a&&(zs.fromBufferAttribute(a,o),ks.fromBufferAttribute(a,l),Vs.fromBufferAttribute(a,c),h.normal=jr.getInterpolation(Hs,Is,Ls,Us,zs,ks,Vs,new Li),h.normal.dot(i.direction)>0&&h.normal.multiplyScalar(-1));const t={a:o,b:l,c:c,normal:new Li,materialIndex:0};jr.getNormal(Is,Ls,Us,t.normal),h.face=t}return h}class js extends Es{constructor(t=1,e=1,n=1,i=1,r=1,s=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:n,widthSegments:i,heightSegments:r,depthSegments:s};const a=this;i=Math.floor(i),r=Math.floor(r),s=Math.floor(s);const o=[],l=[],c=[],h=[];let u=0,d=0;function p(t,e,n,i,r,s,p,m,f,g,v){const _=s/f,x=p/g,y=s/2,M=p/2,S=m/2,b=f+1,w=g+1;let T=0,E=0;const A=new Li;for(let s=0;s0?1:-1,c.push(A.x,A.y,A.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,e.lights=this.lights,e.clipping=this.clipping;const n={};for(const t in this.extensions)!0===this.extensions[t]&&(n[t]=!0);return Object.keys(n).length>0&&(e.extensions=n),e}}class $s extends Dr{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new lr,this.projectionMatrix=new lr,this.projectionMatrixInverse=new lr,this.coordinateSystem=kn}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this.coordinateSystem=t.coordinateSystem,this}getWorldDirection(t){return super.getWorldDirection(t).negate()}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)}}const Qs=new Li,ta=new ti,ea=new ti;class na extends $s{constructor(t=50,e=1,n=.1,i=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=t,this.zoom=1,this.near=n,this.far=i,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*jn*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(.5*Xn*this.fov);return.5*this.getFilmHeight()/t}getEffectiveFOV(){return 2*jn*Math.atan(Math.tan(.5*Xn*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}getViewBounds(t,e,n){Qs.set(-1,-1,.5).applyMatrix4(this.projectionMatrixInverse),e.set(Qs.x,Qs.y).multiplyScalar(-t/Qs.z),Qs.set(1,1,.5).applyMatrix4(this.projectionMatrixInverse),n.set(Qs.x,Qs.y).multiplyScalar(-t/Qs.z)}getViewSize(t,e){return this.getViewBounds(t,ta,ea),e.subVectors(ea,ta)}setViewOffset(t,e,n,i,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=n,this.view.offsetY=i,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*Xn*this.fov)/this.zoom,n=2*e,i=this.aspect*n,r=-.5*i;const s=this.view;if(null!==this.view&&this.view.enabled){const t=s.fullWidth,a=s.fullHeight;r+=s.offsetX*i/t,e-=s.offsetY*n/a,i*=s.width/t,n*=s.height/a}const a=this.filmOffset;0!==a&&(r+=t*a/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,e,e-n,t,this.far,this.coordinateSystem),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 ia=-90;class ra extends Dr{constructor(t,e,n){super(),this.type="CubeCamera",this.renderTarget=n,this.coordinateSystem=null,this.activeMipmapLevel=0;const i=new na(ia,1,t,e);i.layers=this.layers,this.add(i);const r=new na(ia,1,t,e);r.layers=this.layers,this.add(r);const s=new na(ia,1,t,e);s.layers=this.layers,this.add(s);const a=new na(ia,1,t,e);a.layers=this.layers,this.add(a);const o=new na(ia,1,t,e);o.layers=this.layers,this.add(o);const l=new na(ia,1,t,e);l.layers=this.layers,this.add(l)}updateCoordinateSystem(){const t=this.coordinateSystem,e=this.children.concat(),[n,i,r,s,a,o]=e;for(const t of e)this.remove(t);if(t===kn)n.up.set(0,1,0),n.lookAt(1,0,0),i.up.set(0,1,0),i.lookAt(-1,0,0),r.up.set(0,0,-1),r.lookAt(0,1,0),s.up.set(0,0,1),s.lookAt(0,-1,0),a.up.set(0,1,0),a.lookAt(0,0,1),o.up.set(0,1,0),o.lookAt(0,0,-1);else{if(t!==Vn)throw new Error("THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: "+t);n.up.set(0,-1,0),n.lookAt(-1,0,0),i.up.set(0,-1,0),i.lookAt(1,0,0),r.up.set(0,0,1),r.lookAt(0,1,0),s.up.set(0,0,-1),s.lookAt(0,-1,0),a.up.set(0,-1,0),a.lookAt(0,0,1),o.up.set(0,-1,0),o.lookAt(0,0,-1)}for(const t of e)this.add(t),t.updateMatrixWorld()}update(t,e){null===this.parent&&this.updateMatrixWorld();const{renderTarget:n,activeMipmapLevel:i}=this;this.coordinateSystem!==t.coordinateSystem&&(this.coordinateSystem=t.coordinateSystem,this.updateCoordinateSystem());const[r,s,a,o,l,c]=this.children,h=t.getRenderTarget(),u=t.getActiveCubeFace(),d=t.getActiveMipmapLevel(),p=t.xr.enabled;t.xr.enabled=!1;const m=n.texture.generateMipmaps;n.texture.generateMipmaps=!1,t.setRenderTarget(n,0,i),t.render(e,r),t.setRenderTarget(n,1,i),t.render(e,s),t.setRenderTarget(n,2,i),t.render(e,a),t.setRenderTarget(n,3,i),t.render(e,o),t.setRenderTarget(n,4,i),t.render(e,l),n.texture.generateMipmaps=m,t.setRenderTarget(n,5,i),t.render(e,c),t.setRenderTarget(h,u,d),t.xr.enabled=p,n.texture.needsPMREMUpdate=!0}}class sa extends bi{constructor(t,e,n,i,r,s,a,o,l,c){super(t=void 0!==t?t:[],e=void 0!==e?e:lt,n,i,r,s,a,o,l,c),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}class aa extends Ei{constructor(t=1,e={}){super(t,t,e),this.isWebGLCubeRenderTarget=!0;const n={width:t,height:t,depth:1},i=[n,n,n,n,n,n];this.texture=new sa(i,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==e.generateMipmaps&&e.generateMipmaps,this.texture.minFilter=void 0!==e.minFilter?e.minFilter:Mt}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.colorSpace=e.colorSpace,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const n={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"},i=new js(5,5,5),r=new Ks({name:"CubemapFromEquirect",uniforms:qs(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:d,blending:0});r.uniforms.tEquirect.value=e;const s=new Ws(i,r),a=e.minFilter;e.minFilter===wt&&(e.minFilter=Mt);return new ra(1,10,this).update(t,s),e.minFilter=a,s.geometry.dispose(),s.material.dispose(),this}clear(t,e,n,i){const r=t.getRenderTarget();for(let r=0;r<6;r++)t.setRenderTarget(this,r),t.clear(e,n,i);t.setRenderTarget(r)}}const oa=new Li,la=new Li,ca=new ei;class ha{constructor(t=new Li(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,n,i){return this.normal.set(t,e,n),this.constant=i,this}setFromNormalAndCoplanarPoint(t,e){return this.normal.copy(t),this.constant=-e.dot(this.normal),this}setFromCoplanarPoints(t,e,n){const i=oa.subVectors(n,e).cross(la.subVectors(t,e)).normalize();return this.setFromNormalAndCoplanarPoint(i,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(t).addScaledVector(this.normal,-this.distanceToPoint(t))}intersectLine(t,e){const n=t.delta(oa),i=this.normal.dot(n);if(0===i)return 0===this.distanceToPoint(t.start)?e.copy(t.start):null;const r=-(t.start.dot(this.normal)+this.constant)/i;return r<0||r>1?null:e.copy(t.start).addScaledVector(n,r)}intersectsLine(t){const e=this.distanceToPoint(t.start),n=this.distanceToPoint(t.end);return e<0&&n>0||n<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 n=e||ca.getNormalMatrix(t),i=this.coplanarPoint(oa).applyMatrix4(t),r=this.normal.applyMatrix3(n).normalize();return this.constant=-i.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 ua=new Qi,da=new Li;class pa{constructor(t=new ha,e=new ha,n=new ha,i=new ha,r=new ha,s=new ha){this.planes=[t,e,n,i,r,s]}set(t,e,n,i,r,s){const a=this.planes;return a[0].copy(t),a[1].copy(e),a[2].copy(n),a[3].copy(i),a[4].copy(r),a[5].copy(s),this}copy(t){const e=this.planes;for(let n=0;n<6;n++)e[n].copy(t.planes[n]);return this}setFromProjectionMatrix(t,e=2e3){const n=this.planes,i=t.elements,r=i[0],s=i[1],a=i[2],o=i[3],l=i[4],c=i[5],h=i[6],u=i[7],d=i[8],p=i[9],m=i[10],f=i[11],g=i[12],v=i[13],_=i[14],x=i[15];if(n[0].setComponents(o-r,u-l,f-d,x-g).normalize(),n[1].setComponents(o+r,u+l,f+d,x+g).normalize(),n[2].setComponents(o+s,u+c,f+p,x+v).normalize(),n[3].setComponents(o-s,u-c,f-p,x-v).normalize(),n[4].setComponents(o-a,u-h,f-m,x-_).normalize(),e===kn)n[5].setComponents(o+a,u+h,f+m,x+_).normalize();else{if(e!==Vn)throw new Error("THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: "+e);n[5].setComponents(a,h,m,_).normalize()}return this}intersectsObject(t){if(void 0!==t.boundingSphere)null===t.boundingSphere&&t.computeBoundingSphere(),ua.copy(t.boundingSphere).applyMatrix4(t.matrixWorld);else{const e=t.geometry;null===e.boundingSphere&&e.computeBoundingSphere(),ua.copy(e.boundingSphere).applyMatrix4(t.matrixWorld)}return this.intersectsSphere(ua)}intersectsSprite(t){return ua.center.set(0,0,0),ua.radius=.7071067811865476,ua.applyMatrix4(t.matrixWorld),this.intersectsSphere(ua)}intersectsSphere(t){const e=this.planes,n=t.center,i=-t.radius;for(let t=0;t<6;t++){if(e[t].distanceToPoint(n)0?t.max.x:t.min.x,da.y=i.normal.y>0?t.max.y:t.min.y,da.z=i.normal.z>0?t.max.z:t.min.z,i.distanceToPoint(da)<0)return!1}return!0}containsPoint(t){const e=this.planes;for(let n=0;n<6;n++)if(e[n].distanceToPoint(t)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function ma(){let t=null,e=!1,n=null,i=null;function r(e,s){n(e,s),i=t.requestAnimationFrame(r)}return{start:function(){!0!==e&&null!==n&&(i=t.requestAnimationFrame(r),e=!0)},stop:function(){t.cancelAnimationFrame(i),e=!1},setAnimationLoop:function(t){n=t},setContext:function(e){t=e}}}function fa(t){const e=new WeakMap;return{get:function(t){return t.isInterleavedBufferAttribute&&(t=t.data),e.get(t)},remove:function(n){n.isInterleavedBufferAttribute&&(n=n.data);const i=e.get(n);i&&(t.deleteBuffer(i.buffer),e.delete(n))},update:function(n,i){if(n.isInterleavedBufferAttribute&&(n=n.data),n.isGLBufferAttribute){const t=e.get(n);return void((!t||t.version 0\n\tvec4 plane;\n\t#ifdef ALPHA_TO_COVERAGE\n\t\tfloat distanceToPlane, distanceGradient;\n\t\tfloat clipOpacity = 1.0;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\tclipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\tif ( clipOpacity == 0.0 ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tfloat unionClipOpacity = 1.0;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\t\tunionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tclipOpacity *= 1.0 - unionClipOpacity;\n\t\t#endif\n\t\tdiffuseColor.a *= clipOpacity;\n\t\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tbool clipped = true;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tif ( clipped ) discard;\n\t\t#endif\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 ) || defined( USE_BATCHING_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 ) || defined( USE_BATCHING_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\n#ifdef USE_BATCHING_COLOR\n\tvec3 batchingColor = getBatchingColor( getIndirectIndex( gl_DrawID ) );\n\tvColor.xyz *= batchingColor.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};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\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}\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}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated",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\thighp vec2 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_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\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_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );\n\ttransformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) );\n\ttransformedNormal = bm * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = bm * transformedTangent;\n\t#endif\n#endif\n#ifdef USE_INSTANCING\n\tmat3 im = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) );\n\ttransformedNormal = im * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = im * transformedTangent;\n\t#endif\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\ttransformedTangent = ( modelViewMatrix * vec4( transformedTangent, 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, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",colorspace_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",colorspace_pars_fragment:"\nconst mat3 LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = mat3(\n\tvec3( 0.8224621, 0.177538, 0.0 ),\n\tvec3( 0.0331941, 0.9668058, 0.0 ),\n\tvec3( 0.0170827, 0.0723974, 0.9105199 )\n);\nconst mat3 LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.2249401, - 0.2249404, 0.0 ),\n\tvec3( - 0.0420569, 1.0420571, 0.0 ),\n\tvec3( - 0.0196376, - 0.0786361, 1.0982735 )\n);\nvec4 LinearSRGBToLinearDisplayP3( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_SRGB_TO_LINEAR_DISPLAY_P3, value.a );\n}\nvec4 LinearDisplayP3ToLinearSRGB( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_DISPLAY_P3_TO_LINEAR_SRGB, value.a );\n}\nvec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferOETF( 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, envMapRotation * 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\tuniform mat3 envMapRotation;\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:"#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * 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#ifdef 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, envMapRotation * 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\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\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_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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, 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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, 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;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\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\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif ( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\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, 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 vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\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 vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, 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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, 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( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\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 USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\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, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).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_DISPERSION\n\tmaterial.dispersion = dispersion;\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, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).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_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\tfloat dispersion;\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\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\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 dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 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}\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\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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\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( 0, 1, 0 ),\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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, 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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, 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( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, 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:"\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\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, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, 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, geometryPosition, 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 *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, 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, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, 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, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, 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\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\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 ], geometryNormal );\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, vLightMapUv );\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( geometryNormal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF )\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\tvFragDepth = 1.0 + gl_Position.w;\n\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vMapUv );\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\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\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\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_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\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, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphinstance_vertex:"#ifdef USE_INSTANCING_MORPH\n\tfloat morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\tfloat morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tmorphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r;\n\t}\n#endif",morphcolor_vertex:"#if defined( USE_MORPHCOLORS )\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\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\t#ifndef USE_INSTANCING_MORPH\n\t\tuniform float morphTargetBaseInfluence;\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t#endif\n\tuniform sampler2DArray morphTargetsTexture;\n\tuniform ivec2 morphTargetsTextureSize;\n\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t}\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t}\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 *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal,\n\t\t#if defined( USE_NORMALMAP )\n\t\t\tvNormalMapUv\n\t\t#elif defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tvClearcoatNormalMapUv\n\t\t#else\n\t\t\tvUv\n\t\t#endif\n\t\t);\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 nonPerturbedNormal = normal;",normal_fragment_maps:"#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).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( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\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 USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.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 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\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",opaque_fragment:"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\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.;const float ShiftRight8 = 1. / 256.;\nconst float Inv255 = 1. / 255.;\nconst vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 );\nconst vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g );\nconst vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b );\nconst vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a );\nvec4 packDepthToRGBA( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec4( 0., 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec4( 1., 1., 1., 1. );\n\tfloat vuf;\n\tfloat af = modf( v * PackFactors.a, vuf );\n\tfloat bf = modf( vuf * ShiftRight8, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af );\n}\nvec3 packDepthToRGB( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec3( 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec3( 1., 1., 1. );\n\tfloat vuf;\n\tfloat bf = modf( v * PackFactors.b, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec3( vuf * Inv255, gf * PackUpscale, bf );\n}\nvec2 packDepthToRG( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec2( 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec2( 1., 1. );\n\tfloat vuf;\n\tfloat gf = modf( v * 256., vuf );\n\treturn vec2( vuf * Inv255, gf );\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors4 );\n}\nfloat unpackRGBToDepth( const in vec3 v ) {\n\treturn dot( v, UnpackFactors3 );\n}\nfloat unpackRGToDepth( const in vec2 v ) {\n\treturn v.r * UnpackFactors2.r + v.g * UnpackFactors2.g;\n}\nvec4 pack2HalfToRGBA( const in 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( const in 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 depth, const in float near, const in float far ) {\n\treturn depth * ( 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 depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - 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_BATCHING\n\tmvPosition = batchingMatrix * mvPosition;\n#endif\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, vRoughnessMapUv );\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 shadowIntensity;\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 shadowIntensity;\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 shadowIntensity;\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 shadowIntensity, 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\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\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 texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.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 texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.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 mix( 1.0, shadow, shadowIntensity );\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 shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\t\n\t\tfloat lightToPositionLength = length( lightToPosition );\n\t\tif ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t\t) * ( 1.0 / 9.0 );\n\t\t\t#else\n\t\t\t\tshadow = texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\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 shadowIntensity;\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 shadowIntensity;\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 shadowIntensity;\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_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#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#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.shadowIntensity, 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.shadowIntensity, 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.shadowIntensity, 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\tmat4 getBoneMatrix( const in float i ) {\n\t\tint size = textureSize( boneTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\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, vSpecularMapUv );\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 saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 CineonToneMapping( 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( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.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}\nconst mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.6605, - 0.1246, - 0.0182 ),\n\tvec3( - 0.5876, 1.1329, - 0.1006 ),\n\tvec3( - 0.0728, - 0.0083, 1.1187 )\n);\nconst mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3(\n\tvec3( 0.6274, 0.0691, 0.0164 ),\n\tvec3( 0.3293, 0.9195, 0.0880 ),\n\tvec3( 0.0433, 0.0113, 0.8956 )\n);\nvec3 agxDefaultContrastApprox( vec3 x ) {\n\tvec3 x2 = x * x;\n\tvec3 x4 = x2 * x2;\n\treturn + 15.5 * x4 * x2\n\t\t- 40.14 * x4 * x\n\t\t+ 31.96 * x4\n\t\t- 6.868 * x2 * x\n\t\t+ 0.4298 * x2\n\t\t+ 0.1191 * x\n\t\t- 0.00232;\n}\nvec3 AgXToneMapping( vec3 color ) {\n\tconst mat3 AgXInsetMatrix = mat3(\n\t\tvec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ),\n\t\tvec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ),\n\t\tvec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 )\n\t);\n\tconst mat3 AgXOutsetMatrix = mat3(\n\t\tvec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ),\n\t\tvec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ),\n\t\tvec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 )\n\t);\n\tconst float AgxMinEv = - 12.47393;\tconst float AgxMaxEv = 4.026069;\n\tcolor *= toneMappingExposure;\n\tcolor = LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor = AgXInsetMatrix * color;\n\tcolor = max( color, 1e-10 );\tcolor = log2( color );\n\tcolor = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv );\n\tcolor = clamp( color, 0.0, 1.0 );\n\tcolor = agxDefaultContrastApprox( color );\n\tcolor = AgXOutsetMatrix * color;\n\tcolor = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) );\n\tcolor = LINEAR_REC2020_TO_LINEAR_SRGB * color;\n\tcolor = clamp( color, 0.0, 1.0 );\n\treturn color;\n}\nvec3 NeutralToneMapping( vec3 color ) {\n\tconst float StartCompression = 0.8 - 0.04;\n\tconst float Desaturation = 0.15;\n\tcolor *= toneMappingExposure;\n\tfloat x = min( color.r, min( color.g, color.b ) );\n\tfloat offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\n\tcolor -= offset;\n\tfloat peak = max( color.r, max( color.g, color.b ) );\n\tif ( peak < StartCompression ) return color;\n\tfloat d = 1. - StartCompression;\n\tfloat newPeak = 1. - d * d / ( peak + d - StartCompression );\n\tcolor *= newPeak / peak;\n\tfloat g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. );\n\treturn mix( color, vec3( newPeak ), g );\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, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.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\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\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 lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\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 dispersion, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec4 transmittedLight;\n\t\tvec3 transmittance;\n\t\t#ifdef USE_DISPERSION\n\t\t\tfloat halfSpread = ( ior - 1.0 ) * 0.025 * dispersion;\n\t\t\tvec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread );\n\t\t\tfor ( int i = 0; i < 3; i ++ ) {\n\t\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix );\n\t\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\n\t\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\t\trefractionCoords += 1.0;\n\t\t\t\trefractionCoords /= 2.0;\n\t\t\n\t\t\t\tvec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] );\n\t\t\t\ttransmittedLight[ i ] = transmissionSample[ i ];\n\t\t\t\ttransmittedLight.a += transmissionSample.a;\n\t\t\t\ttransmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ];\n\t\t\t}\n\t\t\ttransmittedLight.a /= 3.0;\n\t\t\n\t\t#else\n\t\t\n\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\trefractionCoords += 1.0;\n\t\t\trefractionCoords /= 2.0;\n\t\t\ttransmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\t\ttransmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\t\n\t\t#endif\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif",uv_pars_fragment:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_pars_vertex:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_vertex:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 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_BATCHING\n\t\tworldPosition = batchingMatrix * worldPosition;\n\t#endif\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;\nuniform mat3 backgroundRotation;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, backgroundRotation * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, backgroundRotation * 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 \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \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 \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \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\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#elif DEPTH_PACKING == 3202\n\t\tgl_FragColor = vec4( packDepthToRGB( fragCoordZ ), 1.0 );\n\t#elif DEPTH_PACKING == 3203\n\t\tgl_FragColor = vec4( packDepthToRG( fragCoordZ ), 0.0, 1.0 );\n\t#endif\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\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#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 \n#include \nvoid main () {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \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 \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\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 \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\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}",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#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\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\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, vLightMapUv );\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\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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \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\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 \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\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 \n#include \nvoid main() {\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\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( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\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#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",meshnormal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), diffuseColor.a );\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\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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \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\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\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 USE_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 USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_DISPERSION\n\tuniform float dispersion;\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_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \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\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 + sheenSpecularDirect + sheenSpecularIndirect;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * 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\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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \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}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \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 \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \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 \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}",shadow_frag:"uniform vec3 color;\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\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 \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \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}"},_a={common:{diffuse:{value:new Kr(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new ei},alphaMap:{value:null},alphaMapTransform:{value:new ei},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new ei}},envmap:{envMap:{value:null},envMapRotation:{value:new ei},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new ei}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new ei}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new ei},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new ei},normalScale:{value:new ti(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new ei},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new ei}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new ei}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new ei}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new Kr(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowIntensity:1,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 Kr(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new ei},alphaTest:{value:0},uvTransform:{value:new ei}},sprite:{diffuse:{value:new Kr(16777215)},opacity:{value:1},center:{value:new ti(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new ei},alphaMap:{value:null},alphaMapTransform:{value:new ei},alphaTest:{value:0}}},xa={basic:{uniforms:Ys([_a.common,_a.specularmap,_a.envmap,_a.aomap,_a.lightmap,_a.fog]),vertexShader:va.meshbasic_vert,fragmentShader:va.meshbasic_frag},lambert:{uniforms:Ys([_a.common,_a.specularmap,_a.envmap,_a.aomap,_a.lightmap,_a.emissivemap,_a.bumpmap,_a.normalmap,_a.displacementmap,_a.fog,_a.lights,{emissive:{value:new Kr(0)}}]),vertexShader:va.meshlambert_vert,fragmentShader:va.meshlambert_frag},phong:{uniforms:Ys([_a.common,_a.specularmap,_a.envmap,_a.aomap,_a.lightmap,_a.emissivemap,_a.bumpmap,_a.normalmap,_a.displacementmap,_a.fog,_a.lights,{emissive:{value:new Kr(0)},specular:{value:new Kr(1118481)},shininess:{value:30}}]),vertexShader:va.meshphong_vert,fragmentShader:va.meshphong_frag},standard:{uniforms:Ys([_a.common,_a.envmap,_a.aomap,_a.lightmap,_a.emissivemap,_a.bumpmap,_a.normalmap,_a.displacementmap,_a.roughnessmap,_a.metalnessmap,_a.fog,_a.lights,{emissive:{value:new Kr(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:va.meshphysical_vert,fragmentShader:va.meshphysical_frag},toon:{uniforms:Ys([_a.common,_a.aomap,_a.lightmap,_a.emissivemap,_a.bumpmap,_a.normalmap,_a.displacementmap,_a.gradientmap,_a.fog,_a.lights,{emissive:{value:new Kr(0)}}]),vertexShader:va.meshtoon_vert,fragmentShader:va.meshtoon_frag},matcap:{uniforms:Ys([_a.common,_a.bumpmap,_a.normalmap,_a.displacementmap,_a.fog,{matcap:{value:null}}]),vertexShader:va.meshmatcap_vert,fragmentShader:va.meshmatcap_frag},points:{uniforms:Ys([_a.points,_a.fog]),vertexShader:va.points_vert,fragmentShader:va.points_frag},dashed:{uniforms:Ys([_a.common,_a.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:va.linedashed_vert,fragmentShader:va.linedashed_frag},depth:{uniforms:Ys([_a.common,_a.displacementmap]),vertexShader:va.depth_vert,fragmentShader:va.depth_frag},normal:{uniforms:Ys([_a.common,_a.bumpmap,_a.normalmap,_a.displacementmap,{opacity:{value:1}}]),vertexShader:va.meshnormal_vert,fragmentShader:va.meshnormal_frag},sprite:{uniforms:Ys([_a.sprite,_a.fog]),vertexShader:va.sprite_vert,fragmentShader:va.sprite_frag},background:{uniforms:{uvTransform:{value:new ei},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:va.background_vert,fragmentShader:va.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1},backgroundRotation:{value:new ei}},vertexShader:va.backgroundCube_vert,fragmentShader:va.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:va.cube_vert,fragmentShader:va.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:va.equirect_vert,fragmentShader:va.equirect_frag},distanceRGBA:{uniforms:Ys([_a.common,_a.displacementmap,{referencePosition:{value:new Li},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:va.distanceRGBA_vert,fragmentShader:va.distanceRGBA_frag},shadow:{uniforms:Ys([_a.lights,_a.fog,{color:{value:new Kr(0)},opacity:{value:1}}]),vertexShader:va.shadow_vert,fragmentShader:va.shadow_frag}};xa.physical={uniforms:Ys([xa.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new ei},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new ei},clearcoatNormalScale:{value:new ti(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new ei},dispersion:{value:0},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new ei},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new ei},sheen:{value:0},sheenColor:{value:new Kr(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new ei},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new ei},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new ei},transmissionSamplerSize:{value:new ti},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new ei},attenuationDistance:{value:0},attenuationColor:{value:new Kr(0)},specularColor:{value:new Kr(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new ei},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new ei},anisotropyVector:{value:new ti},anisotropyMap:{value:null},anisotropyMapTransform:{value:new ei}}]),vertexShader:va.meshphysical_vert,fragmentShader:va.meshphysical_frag};const ya={r:0,b:0,g:0},Ma=new _r,Sa=new lr;function ba(t,e,n,i,r,s,a){const o=new Kr(0);let l,c,h=!0===s?0:1,p=null,m=0,f=null;function g(t){let i=!0===t.isScene?t.background:null;if(i&&i.isTexture){i=(t.backgroundBlurriness>0?n:e).get(i)}return i}function v(e,n){e.getRGB(ya,Zs(t)),i.buffers.color.setClear(ya.r,ya.g,ya.b,n,a)}return{getClearColor:function(){return o},setClearColor:function(t,e=1){o.set(t),h=e,v(o,h)},getClearAlpha:function(){return h},setClearAlpha:function(t){h=t,v(o,h)},render:function(e){let n=!1;const r=g(e);null===r?v(o,h):r&&r.isColor&&(v(r,1),n=!0);const s=t.xr.getEnvironmentBlendMode();"additive"===s?i.buffers.color.setClear(0,0,0,1,a):"alpha-blend"===s&&i.buffers.color.setClear(0,0,0,0,a),(t.autoClear||n)&&(i.buffers.depth.setTest(!0),i.buffers.depth.setMask(!0),i.buffers.color.setMask(!0),t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil))},addToRenderList:function(e,n){const i=g(n);i&&(i.isCubeTexture||i.mapping===dt)?(void 0===c&&(c=new Ws(new js(1,1,1),new Ks({name:"BackgroundCubeMaterial",uniforms:qs(xa.backgroundCube.uniforms),vertexShader:xa.backgroundCube.vertexShader,fragmentShader:xa.backgroundCube.fragmentShader,side:d,depthTest:!1,depthWrite:!1,fog:!1})),c.geometry.deleteAttribute("normal"),c.geometry.deleteAttribute("uv"),c.onBeforeRender=function(t,e,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(c.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),r.update(c)),Ma.copy(n.backgroundRotation),Ma.x*=-1,Ma.y*=-1,Ma.z*=-1,i.isCubeTexture&&!1===i.isRenderTargetTexture&&(Ma.y*=-1,Ma.z*=-1),c.material.uniforms.envMap.value=i,c.material.uniforms.flipEnvMap.value=i.isCubeTexture&&!1===i.isRenderTargetTexture?-1:1,c.material.uniforms.backgroundBlurriness.value=n.backgroundBlurriness,c.material.uniforms.backgroundIntensity.value=n.backgroundIntensity,c.material.uniforms.backgroundRotation.value.setFromMatrix4(Sa.makeRotationFromEuler(Ma)),c.material.toneMapped=mi.getTransfer(i.colorSpace)!==en,p===i&&m===i.version&&f===t.toneMapping||(c.material.needsUpdate=!0,p=i,m=i.version,f=t.toneMapping),c.layers.enableAll(),e.unshift(c,c.geometry,c.material,0,0,null)):i&&i.isTexture&&(void 0===l&&(l=new Ws(new ga(2,2),new Ks({name:"BackgroundMaterial",uniforms:qs(xa.background.uniforms),vertexShader:xa.background.vertexShader,fragmentShader:xa.background.fragmentShader,side:u,depthTest:!1,depthWrite:!1,fog:!1})),l.geometry.deleteAttribute("normal"),Object.defineProperty(l.material,"map",{get:function(){return this.uniforms.t2D.value}}),r.update(l)),l.material.uniforms.t2D.value=i,l.material.uniforms.backgroundIntensity.value=n.backgroundIntensity,l.material.toneMapped=mi.getTransfer(i.colorSpace)!==en,!0===i.matrixAutoUpdate&&i.updateMatrix(),l.material.uniforms.uvTransform.value.copy(i.matrix),p===i&&m===i.version&&f===t.toneMapping||(l.material.needsUpdate=!0,p=i,m=i.version,f=t.toneMapping),l.layers.enableAll(),e.unshift(l,l.geometry,l.material,0,0,null))}}}function wa(t,e){const n=t.getParameter(t.MAX_VERTEX_ATTRIBS),i={},r=c(null);let s=r,a=!1;function o(e){return t.bindVertexArray(e)}function l(e){return t.deleteVertexArray(e)}function c(t){const e=[],i=[],r=[];for(let t=0;t=0){const n=r[e];let i=a[e];if(void 0===i&&("instanceMatrix"===e&&t.instanceMatrix&&(i=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(i=t.instanceColor)),void 0===n)return!0;if(n.attribute!==i)return!0;if(i&&n.data!==i.data)return!0;o++}}return s.attributesNum!==o||s.index!==i}(n,f,l,g),v&&function(t,e,n,i){const r={},a=e.attributes;let o=0;const l=n.getAttributes();for(const e in l){if(l[e].location>=0){let n=a[e];void 0===n&&("instanceMatrix"===e&&t.instanceMatrix&&(n=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(n=t.instanceColor));const i={};i.attribute=n,n&&n.data&&(i.data=n.data),r[e]=i,o++}}s.attributes=r,s.attributesNum=o,s.index=i}(n,f,l,g),null!==g&&e.update(g,t.ELEMENT_ARRAY_BUFFER),(v||a)&&(a=!1,function(n,i,r,s){h();const a=s.attributes,o=r.getAttributes(),l=i.defaultAttributeValues;for(const i in o){const r=o[i];if(r.location>=0){let o=a[i];if(void 0===o&&("instanceMatrix"===i&&n.instanceMatrix&&(o=n.instanceMatrix),"instanceColor"===i&&n.instanceColor&&(o=n.instanceColor)),void 0!==o){const i=o.normalized,a=o.itemSize,l=e.get(o);if(void 0===l)continue;const c=l.buffer,h=l.type,p=l.bytesPerElement,f=h===t.INT||h===t.UNSIGNED_INT||o.gpuType===Pt;if(o.isInterleavedBufferAttribute){const e=o.data,l=e.stride,g=o.offset;if(e.isInstancedInterleavedBuffer){for(let t=0;t0&&t.getShaderPrecisionFormat(t.FRAGMENT_SHADER,t.HIGH_FLOAT).precision>0)return"highp";e="mediump"}return"mediump"===e&&t.getShaderPrecisionFormat(t.VERTEX_SHADER,t.MEDIUM_FLOAT).precision>0&&t.getShaderPrecisionFormat(t.FRAGMENT_SHADER,t.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}let a=void 0!==n.precision?n.precision:"highp";const o=s(a);o!==a&&(console.warn("THREE.WebGLRenderer:",a,"not supported, using",o,"instead."),a=o);const l=!0===n.logarithmicDepthBuffer,c=t.getParameter(t.MAX_TEXTURE_IMAGE_UNITS),h=t.getParameter(t.MAX_VERTEX_TEXTURE_IMAGE_UNITS);return{isWebGL2:!0,getMaxAnisotropy:function(){if(void 0!==r)return r;if(!0===e.has("EXT_texture_filter_anisotropic")){const n=e.get("EXT_texture_filter_anisotropic");r=t.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else r=0;return r},getMaxPrecision:s,textureFormatReadable:function(e){return e===kt||i.convert(e)===t.getParameter(t.IMPLEMENTATION_COLOR_READ_FORMAT)},textureTypeReadable:function(n){const r=n===Ut&&(e.has("EXT_color_buffer_half_float")||e.has("EXT_color_buffer_float"));return!(n!==Et&&i.convert(n)!==t.getParameter(t.IMPLEMENTATION_COLOR_READ_TYPE)&&n!==Lt&&!r)},precision:a,logarithmicDepthBuffer:l,maxTextures:c,maxVertexTextures:h,maxTextureSize:t.getParameter(t.MAX_TEXTURE_SIZE),maxCubemapSize:t.getParameter(t.MAX_CUBE_MAP_TEXTURE_SIZE),maxAttributes:t.getParameter(t.MAX_VERTEX_ATTRIBS),maxVertexUniforms:t.getParameter(t.MAX_VERTEX_UNIFORM_VECTORS),maxVaryings:t.getParameter(t.MAX_VARYING_VECTORS),maxFragmentUniforms:t.getParameter(t.MAX_FRAGMENT_UNIFORM_VECTORS),vertexTextures:h>0,maxSamples:t.getParameter(t.MAX_SAMPLES)}}function Aa(t){const e=this;let n=null,i=0,r=!1,s=!1;const a=new ha,o=new ei,l={value:null,needsUpdate:!1};function c(t,n,i,r){const s=null!==t?t.length:0;let c=null;if(0!==s){if(c=l.value,!0!==r||null===c){const e=i+4*s,r=n.matrixWorldInverse;o.getNormalMatrix(r),(null===c||c.length0);e.numPlanes=i,e.numIntersection=0}();else{const t=s?0:i,e=4*t;let r=m.clippingState||null;l.value=r,r=c(u,o,e,h);for(let t=0;t!==e;++t)r[t]=n[t];m.clippingState=r,this.numIntersection=d?this.numPlanes:0,this.numPlanes+=t}}}function Ra(t){let e=new WeakMap;function n(t,e){return e===ht?t.mapping=lt:e===ut&&(t.mapping=ct),t}function i(t){const n=t.target;n.removeEventListener("dispose",i);const r=e.get(n);void 0!==r&&(e.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture){const s=r.mapping;if(s===ht||s===ut){if(e.has(r)){return n(e.get(r).texture,r.mapping)}{const s=r.image;if(s&&s.height>0){const a=new aa(s.height);return a.fromEquirectangularTexture(t,r),e.set(r,a),r.addEventListener("dispose",i),n(a.texture,r.mapping)}return null}}}return r},dispose:function(){e=new WeakMap}}}class Ca extends $s{constructor(t=-1,e=1,n=1,i=-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=n,this.bottom=i,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,n,i,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=n,this.view.offsetY=i,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),n=(this.right+this.left)/2,i=(this.top+this.bottom)/2;let r=n-t,s=n+t,a=i+e,o=i-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.coordinateSystem),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 Pa=[.125,.215,.35,.446,.526,.582],Ia=20,La=new Ca,Ua=new Kr;let Na=null,Da=0,Oa=0,Fa=!1;const Ba=(1+Math.sqrt(5))/2,za=1/Ba,ka=[new Li(-Ba,za,0),new Li(Ba,za,0),new Li(-za,0,Ba),new Li(za,0,Ba),new Li(0,Ba,-za),new Li(0,Ba,za),new Li(-1,1,-1),new Li(1,1,-1),new Li(-1,1,1),new Li(1,1,1)];class Va{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,n=.1,i=100){Na=this._renderer.getRenderTarget(),Da=this._renderer.getActiveCubeFace(),Oa=this._renderer.getActiveMipmapLevel(),Fa=this._renderer.xr.enabled,this._renderer.xr.enabled=!1,this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(t,n,i,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=Xa(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=Wa(),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=Pa[a-t+4-1]:0===a&&(o=0),i.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),_=new Float32Array(f*p*d),x=new Float32Array(g*p*d);for(let t=0;t2?0:-1,i=[e,n,0,e+2/3,n,0,e+2/3,n+1,0,e,n,0,e+2/3,n+1,0,e,n+1,0];v.set(i,m*p*t),_.set(u,f*p*t);const r=[t,t,t,t,t,t];x.set(r,g*p*t)}const y=new Es;y.setAttribute("position",new cs(v,m)),y.setAttribute("uv",new cs(_,f)),y.setAttribute("faceIndex",new cs(x,g)),e.push(y),r>4&&r--}return{lodPlanes:e,sizeLods:n,sigmas:i}}(i)),this._blurMaterial=function(t,e,n){const i=new Float32Array(Ia),r=new Li(0,1,0),s=new Ks({name:"SphericalGaussianBlur",defines:{n:Ia,CUBEUV_TEXEL_WIDTH:1/e,CUBEUV_TEXEL_HEIGHT:1/n,CUBEUV_MAX_MIP:`${t}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:i},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:r}},vertexShader:ja(),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});return s}(i,t,e)}return i}_compileMaterial(t){const e=new Ws(this._lodPlanes[0],t);this._renderer.compile(e,La)}_sceneToCubeUV(t,e,n,i){const r=new na(90,1,e,n),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(Ua),o.toneMapping=K,o.autoClear=!1;const h=new es({name:"PMREM.Background",side:d,depthWrite:!1,depthTest:!1}),u=new Ws(new js,h);let p=!1;const m=t.background;m?m.isColor&&(h.color.copy(m),t.background=null,p=!0):(h.color.copy(Ua),p=!0);for(let e=0;e<6;e++){const n=e%3;0===n?(r.up.set(0,s[e],0),r.lookAt(a[e],0,0)):1===n?(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;Ga(i,n*l,e>2?l:0,l,l),o.setRenderTarget(i),p&&o.render(u,r),o.render(t,r)}u.geometry.dispose(),u.material.dispose(),o.toneMapping=c,o.autoClear=l,t.background=m}_textureToCubeUV(t,e){const n=this._renderer,i=t.mapping===lt||t.mapping===ct;i?(null===this._cubemapMaterial&&(this._cubemapMaterial=Xa()),this._cubemapMaterial.uniforms.flipEnvMap.value=!1===t.isRenderTargetTexture?-1:1):null===this._equirectMaterial&&(this._equirectMaterial=Wa());const r=i?this._cubemapMaterial:this._equirectMaterial,s=new Ws(this._lodPlanes[0],r);r.uniforms.envMap.value=t;const a=this._cubeSize;Ga(e,0,0,3*a,2*a),n.setRenderTarget(e),n.render(s,La)}_applyPMREM(t){const e=this._renderer,n=e.autoClear;e.autoClear=!1;const i=this._lodPlanes.length;for(let e=1;eIa&&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?i-v+4:0),4*(this._cubeSize-_),3*_,2*_),o.setRenderTarget(e),o.render(c,La)}}function Ha(t,e,n){const i=new Ei(t,e,n);return i.texture.mapping=dt,i.texture.name="PMREM.cubeUv",i.scissorTest=!0,i}function Ga(t,e,n,i,r){t.viewport.set(e,n,i,r),t.scissor.set(e,n,i,r)}function Wa(){return new Ks({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:ja(),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 Xa(){return new Ks({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:ja(),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 ja(){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 qa(t){let e=new WeakMap,n=null;function i(t){const n=t.target;n.removeEventListener("dispose",i);const r=e.get(n);void 0!==r&&(e.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture){const s=r.mapping,a=s===ht||s===ut,o=s===lt||s===ct;if(a||o){let s=e.get(r);const l=void 0!==s?s.texture.pmremVersion:0;if(r.isRenderTargetTexture&&r.pmremVersion!==l)return null===n&&(n=new Va(t)),s=a?n.fromEquirectangular(r,s):n.fromCubemap(r,s),s.texture.pmremVersion=r.pmremVersion,e.set(r,s),s.texture;if(void 0!==s)return s.texture;{const l=r.image;return a&&l&&l.height>0||o&&l&&function(t){let e=0;const n=6;for(let i=0;ie.maxTextureSize&&(y=Math.ceil(x/e.maxTextureSize),x=e.maxTextureSize);const M=new Float32Array(x*y*4*h),S=new Ai(M,x,y,h);S.type=Lt,S.needsUpdate=!0;const b=4*_;for(let T=0;T0)return t;const r=e*n;let s=ao[r];if(void 0===s&&(s=new Float32Array(r),ao[r]=s),0!==e){i.toArray(s,0);for(let i=1,r=0;i!==e;++i)r+=n,t[i].toArray(s,r)}return s}function po(t,e){if(t.length!==e.length)return!1;for(let n=0,i=t.length;n":" "} ${r}: ${n[t]}`)}return i.join("\n")}(t.getShaderSource(e),i)}return r}function ul(t,e){const n=function(t){const e=mi.getPrimaries(mi.workingColorSpace),n=mi.getPrimaries(t);let i;switch(e===n?i="":e===rn&&n===nn?i="LinearDisplayP3ToLinearSRGB":e===nn&&n===rn&&(i="LinearSRGBToLinearDisplayP3"),t){case Ke:case Qe:return[i,"LinearTransferOETF"];case Je:case $e:return[i,"sRGBTransferOETF"];default:return console.warn("THREE.WebGLProgram: Unsupported color space:",t),[i,"LinearTransferOETF"]}}(e);return`vec4 ${t}( vec4 value ) { return ${n[0]}( ${n[1]}( value ) ); }`}function dl(t,e){let n;switch(e){case $:n="Linear";break;case Q:n="Reinhard";break;case tt:n="Cineon";break;case et:n="ACESFilmic";break;case it:n="AgX";break;case rt:n="Neutral";break;case nt:n="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",e),n="Linear"}return"vec3 "+t+"( vec3 color ) { return "+n+"ToneMapping( color ); }"}const pl=new Li;function ml(){mi.getLuminanceCoefficients(pl);return["float luminance( const in vec3 rgb ) {",`\tconst vec3 weights = vec3( ${pl.x.toFixed(4)}, ${pl.y.toFixed(4)}, ${pl.z.toFixed(4)} );`,"\treturn dot( weights, rgb );","}"].join("\n")}function fl(t){return""!==t}function gl(t,e){const n=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,n).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 vl(t,e){return t.replace(/NUM_CLIPPING_PLANES/g,e.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,e.numClippingPlanes-e.numClipIntersection)}const _l=/^[ \t]*#include +<([\w\d./]+)>/gm;function xl(t){return t.replace(_l,Ml)}const yl=new Map;function Ml(t,e){let n=va[e];if(void 0===n){const t=yl.get(e);if(void 0===t)throw new Error("Can not resolve #include <"+e+">");n=va[t],console.warn('THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.',e,t)}return xl(n)}const Sl=/#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 bl(t){return t.replace(Sl,wl)}function wl(t,e,n,i){let r="";for(let t=parseInt(e);t0&&(x+="\n"),y=["#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v].filter(fl).join("\n"),y.length>0&&(y+="\n")):(x=[Tl(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v,n.extensionClipCullDistance?"#define USE_CLIP_DISTANCE":"",n.batching?"#define USE_BATCHING":"",n.batchingColor?"#define USE_BATCHING_COLOR":"",n.instancing?"#define USE_INSTANCING":"",n.instancingColor?"#define USE_INSTANCING_COLOR":"",n.instancingMorph?"#define USE_INSTANCING_MORPH":"",n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+p:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.displacementMap?"#define USE_DISPLACEMENTMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropy?"#define USE_ANISOTROPY":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaHash?"#define USE_ALPHAHASH":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.mapUv?"#define MAP_UV "+n.mapUv:"",n.alphaMapUv?"#define ALPHAMAP_UV "+n.alphaMapUv:"",n.lightMapUv?"#define LIGHTMAP_UV "+n.lightMapUv:"",n.aoMapUv?"#define AOMAP_UV "+n.aoMapUv:"",n.emissiveMapUv?"#define EMISSIVEMAP_UV "+n.emissiveMapUv:"",n.bumpMapUv?"#define BUMPMAP_UV "+n.bumpMapUv:"",n.normalMapUv?"#define NORMALMAP_UV "+n.normalMapUv:"",n.displacementMapUv?"#define DISPLACEMENTMAP_UV "+n.displacementMapUv:"",n.metalnessMapUv?"#define METALNESSMAP_UV "+n.metalnessMapUv:"",n.roughnessMapUv?"#define ROUGHNESSMAP_UV "+n.roughnessMapUv:"",n.anisotropyMapUv?"#define ANISOTROPYMAP_UV "+n.anisotropyMapUv:"",n.clearcoatMapUv?"#define CLEARCOATMAP_UV "+n.clearcoatMapUv:"",n.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+n.clearcoatNormalMapUv:"",n.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+n.clearcoatRoughnessMapUv:"",n.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+n.iridescenceMapUv:"",n.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+n.iridescenceThicknessMapUv:"",n.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+n.sheenColorMapUv:"",n.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+n.sheenRoughnessMapUv:"",n.specularMapUv?"#define SPECULARMAP_UV "+n.specularMapUv:"",n.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+n.specularColorMapUv:"",n.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+n.specularIntensityMapUv:"",n.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+n.transmissionMapUv:"",n.thicknessMapUv?"#define THICKNESSMAP_UV "+n.thicknessMapUv:"",n.vertexTangents&&!1===n.flatShading?"#define USE_TANGENT":"",n.vertexColors?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.flatShading?"#define FLAT_SHADED":"",n.skinning?"#define USE_SKINNING":"",n.morphTargets?"#define USE_MORPHTARGETS":"",n.morphNormals&&!1===n.flatShading?"#define USE_MORPHNORMALS":"",n.morphColors?"#define USE_MORPHCOLORS":"",n.morphTargetsCount>0?"#define MORPHTARGETS_TEXTURE_STRIDE "+n.morphTextureStride:"",n.morphTargetsCount>0?"#define MORPHTARGETS_COUNT "+n.morphTargetsCount:"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+u:"",n.sizeAttenuation?"#define USE_SIZEATTENUATION":"",n.numLightProbes>0?"#define USE_LIGHT_PROBES":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"","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","#ifdef USE_INSTANCING_MORPH","\tuniform sampler2D morphTexture;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_UV1","\tattribute vec2 uv1;","#endif","#ifdef USE_UV2","\tattribute vec2 uv2;","#endif","#ifdef USE_UV3","\tattribute vec2 uv3;","#endif","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )","\tattribute vec4 color;","#elif defined( USE_COLOR )","\tattribute vec3 color;","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(fl).join("\n"),y=[Tl(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.alphaToCoverage?"#define ALPHA_TO_COVERAGE":"",n.map?"#define USE_MAP":"",n.matcap?"#define USE_MATCAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+d:"",n.envMap?"#define "+p:"",n.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":"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropy?"#define USE_ANISOTROPY":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoat?"#define USE_CLEARCOAT":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.dispersion?"#define USE_DISPERSION":"",n.iridescence?"#define USE_IRIDESCENCE":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaTest?"#define USE_ALPHATEST":"",n.alphaHash?"#define USE_ALPHAHASH":"",n.sheen?"#define USE_SHEEN":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.vertexTangents&&!1===n.flatShading?"#define USE_TANGENT":"",n.vertexColors||n.instancingColor||n.batchingColor?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.gradientMap?"#define USE_GRADIENTMAP":"",n.flatShading?"#define FLAT_SHADED":"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+u:"",n.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",n.numLightProbes>0?"#define USE_LIGHT_PROBES":"",n.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",n.toneMapping!==K?"#define TONE_MAPPING":"",n.toneMapping!==K?va.tonemapping_pars_fragment:"",n.toneMapping!==K?dl("toneMapping",n.toneMapping):"",n.dithering?"#define DITHERING":"",n.opaque?"#define OPAQUE":"",va.colorspace_pars_fragment,ul("linearToOutputTexel",n.outputColorSpace),ml(),n.useDepthPacking?"#define DEPTH_PACKING "+n.depthPacking:"","\n"].filter(fl).join("\n")),a=xl(a),a=gl(a,n),a=vl(a,n),o=xl(o),o=gl(o,n),o=vl(o,n),a=bl(a),o=bl(o),!0!==n.isRawShaderMaterial&&(M="#version 300 es\n",x=[g,"#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+x,y=["#define varying in",n.glslVersion===zn?"":"layout(location = 0) out highp vec4 pc_fragColor;",n.glslVersion===zn?"":"#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 S=M+x+a,b=M+y+o,w=ol(r,r.VERTEX_SHADER,S),T=ol(r,r.FRAGMENT_SHADER,b);function E(e){if(t.debug.checkShaderErrors){const n=r.getProgramInfoLog(_).trim(),i=r.getShaderInfoLog(w).trim(),s=r.getShaderInfoLog(T).trim();let a=!0,o=!0;if(!1===r.getProgramParameter(_,r.LINK_STATUS))if(a=!1,"function"==typeof t.debug.onShaderError)t.debug.onShaderError(r,_,w,T);else{const t=hl(r,w,"vertex"),i=hl(r,T,"fragment");console.error("THREE.WebGLProgram: Shader Error "+r.getError()+" - VALIDATE_STATUS "+r.getProgramParameter(_,r.VALIDATE_STATUS)+"\n\nMaterial Name: "+e.name+"\nMaterial Type: "+e.type+"\n\nProgram Info Log: "+n+"\n"+t+"\n"+i)}else""!==n?console.warn("THREE.WebGLProgram: Program Info Log:",n):""!==i&&""!==s||(o=!1);o&&(e.diagnostics={runnable:a,programLog:n,vertexShader:{log:i,prefix:x},fragmentShader:{log:s,prefix:y}})}r.deleteShader(w),r.deleteShader(T),A=new al(r,_),R=function(t,e){const n={},i=t.getProgramParameter(e,t.ACTIVE_ATTRIBUTES);for(let r=0;r0,q=s.clearcoat>0,Y=s.dispersion>0,Z=s.iridescence>0,J=s.sheen>0,$=s.transmission>0,Q=j&&!!s.anisotropyMap,tt=q&&!!s.clearcoatMap,et=q&&!!s.clearcoatNormalMap,nt=q&&!!s.clearcoatRoughnessMap,it=Z&&!!s.iridescenceMap,rt=Z&&!!s.iridescenceThicknessMap,st=J&&!!s.sheenColorMap,at=J&&!!s.sheenRoughnessMap,ot=!!s.specularMap,lt=!!s.specularColorMap,ct=!!s.specularIntensityMap,ht=$&&!!s.transmissionMap,ut=$&&!!s.thicknessMap,pt=!!s.gradientMap,mt=!!s.alphaMap,ft=s.alphaTest>0,gt=!!s.alphaHash,vt=!!s.extensions;let _t=K;s.toneMapped&&(null!==L&&!0!==L.isXRRenderTarget||(_t=t.toneMapping));const xt={shaderID:w,shaderType:s.type,shaderName:s.name,vertexShader:A,fragmentShader:R,defines:s.defines,customVertexShaderID:C,customFragmentShaderID:P,isRawShaderMaterial:!0===s.isRawShaderMaterial,glslVersion:s.glslVersion,precision:m,batching:N,batchingColor:N&&null!==_._colorsTexture,instancing:U,instancingColor:U&&null!==_.instanceColor,instancingMorph:U&&null!==_.morphTexture,supportsVertexTextures:p,outputColorSpace:null===L?t.outputColorSpace:!0===L.isXRRenderTarget?L.texture.colorSpace:Ke,alphaToCoverage:!!s.alphaToCoverage,map:D,matcap:O,envMap:F,envMapMode:F&&S.mapping,envMapCubeUVHeight:b,aoMap:B,lightMap:z,bumpMap:k,normalMap:V,displacementMap:p&&H,emissiveMap:G,normalMapObjectSpace:V&&1===s.normalMapType,normalMapTangentSpace:V&&0===s.normalMapType,metalnessMap:W,roughnessMap:X,anisotropy:j,anisotropyMap:Q,clearcoat:q,clearcoatMap:tt,clearcoatNormalMap:et,clearcoatRoughnessMap:nt,dispersion:Y,iridescence:Z,iridescenceMap:it,iridescenceThicknessMap:rt,sheen:J,sheenColorMap:st,sheenRoughnessMap:at,specularMap:ot,specularColorMap:lt,specularIntensityMap:ct,transmission:$,transmissionMap:ht,thicknessMap:ut,gradientMap:pt,opaque:!1===s.transparent&&1===s.blending&&!1===s.alphaToCoverage,alphaMap:mt,alphaTest:ft,alphaHash:gt,combine:s.combine,mapUv:D&&g(s.map.channel),aoMapUv:B&&g(s.aoMap.channel),lightMapUv:z&&g(s.lightMap.channel),bumpMapUv:k&&g(s.bumpMap.channel),normalMapUv:V&&g(s.normalMap.channel),displacementMapUv:H&&g(s.displacementMap.channel),emissiveMapUv:G&&g(s.emissiveMap.channel),metalnessMapUv:W&&g(s.metalnessMap.channel),roughnessMapUv:X&&g(s.roughnessMap.channel),anisotropyMapUv:Q&&g(s.anisotropyMap.channel),clearcoatMapUv:tt&&g(s.clearcoatMap.channel),clearcoatNormalMapUv:et&&g(s.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:nt&&g(s.clearcoatRoughnessMap.channel),iridescenceMapUv:it&&g(s.iridescenceMap.channel),iridescenceThicknessMapUv:rt&&g(s.iridescenceThicknessMap.channel),sheenColorMapUv:st&&g(s.sheenColorMap.channel),sheenRoughnessMapUv:at&&g(s.sheenRoughnessMap.channel),specularMapUv:ot&&g(s.specularMap.channel),specularColorMapUv:lt&&g(s.specularColorMap.channel),specularIntensityMapUv:ct&&g(s.specularIntensityMap.channel),transmissionMapUv:ht&&g(s.transmissionMap.channel),thicknessMapUv:ut&&g(s.thicknessMap.channel),alphaMapUv:mt&&g(s.alphaMap.channel),vertexTangents:!!y.attributes.tangent&&(V||j),vertexColors:s.vertexColors,vertexAlphas:!0===s.vertexColors&&!!y.attributes.color&&4===y.attributes.color.itemSize,pointsUvs:!0===_.isPoints&&!!y.attributes.uv&&(D||mt),fog:!!x,useFog:!0===s.fog,fogExp2:!!x&&x.isFogExp2,flatShading:!0===s.flatShading,sizeAttenuation:!0===s.sizeAttenuation,logarithmicDepthBuffer:u,skinning:!0===_.isSkinnedMesh,morphTargets:void 0!==y.morphAttributes.position,morphNormals:void 0!==y.morphAttributes.normal,morphColors:void 0!==y.morphAttributes.color,morphTargetsCount:E,morphTextureStride:I,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,numLightProbes:o.numLightProbes,numClippingPlanes:a.numPlanes,numClipIntersection:a.numIntersection,dithering:s.dithering,shadowMapEnabled:t.shadowMap.enabled&&h.length>0,shadowMapType:t.shadowMap.type,toneMapping:_t,decodeVideoTexture:D&&!0===s.map.isVideoTexture&&mi.getTransfer(s.map.colorSpace)===en,premultipliedAlpha:s.premultipliedAlpha,doubleSided:2===s.side,flipSided:s.side===d,useDepthPacking:s.depthPacking>=0,depthPacking:s.depthPacking||0,index0AttributeName:s.index0AttributeName,extensionClipCullDistance:vt&&!0===s.extensions.clipCullDistance&&i.has("WEBGL_clip_cull_distance"),extensionMultiDraw:(vt&&!0===s.extensions.multiDraw||N)&&i.has("WEBGL_multi_draw"),rendererExtensionParallelShaderCompile:i.has("KHR_parallel_shader_compile"),customProgramCacheKey:s.customProgramCacheKey()};return xt.vertexUv1s=c.has(1),xt.vertexUv2s=c.has(2),xt.vertexUv3s=c.has(3),c.clear(),xt},getProgramCacheKey:function(e){const n=[];if(e.shaderID?n.push(e.shaderID):(n.push(e.customVertexShaderID),n.push(e.customFragmentShaderID)),void 0!==e.defines)for(const t in e.defines)n.push(t),n.push(e.defines[t]);return!1===e.isRawShaderMaterial&&(!function(t,e){t.push(e.precision),t.push(e.outputColorSpace),t.push(e.envMapMode),t.push(e.envMapCubeUVHeight),t.push(e.mapUv),t.push(e.alphaMapUv),t.push(e.lightMapUv),t.push(e.aoMapUv),t.push(e.bumpMapUv),t.push(e.normalMapUv),t.push(e.displacementMapUv),t.push(e.emissiveMapUv),t.push(e.metalnessMapUv),t.push(e.roughnessMapUv),t.push(e.anisotropyMapUv),t.push(e.clearcoatMapUv),t.push(e.clearcoatNormalMapUv),t.push(e.clearcoatRoughnessMapUv),t.push(e.iridescenceMapUv),t.push(e.iridescenceThicknessMapUv),t.push(e.sheenColorMapUv),t.push(e.sheenRoughnessMapUv),t.push(e.specularMapUv),t.push(e.specularColorMapUv),t.push(e.specularIntensityMapUv),t.push(e.transmissionMapUv),t.push(e.thicknessMapUv),t.push(e.combine),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.numLightProbes),t.push(e.shadowMapType),t.push(e.toneMapping),t.push(e.numClippingPlanes),t.push(e.numClipIntersection),t.push(e.depthPacking)}(n,e),function(t,e){o.disableAll(),e.supportsVertexTextures&&o.enable(0);e.instancing&&o.enable(1);e.instancingColor&&o.enable(2);e.instancingMorph&&o.enable(3);e.matcap&&o.enable(4);e.envMap&&o.enable(5);e.normalMapObjectSpace&&o.enable(6);e.normalMapTangentSpace&&o.enable(7);e.clearcoat&&o.enable(8);e.iridescence&&o.enable(9);e.alphaTest&&o.enable(10);e.vertexColors&&o.enable(11);e.vertexAlphas&&o.enable(12);e.vertexUv1s&&o.enable(13);e.vertexUv2s&&o.enable(14);e.vertexUv3s&&o.enable(15);e.vertexTangents&&o.enable(16);e.anisotropy&&o.enable(17);e.alphaHash&&o.enable(18);e.batching&&o.enable(19);e.dispersion&&o.enable(20);e.batchingColor&&o.enable(21);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.doubleSided&&o.enable(10);e.flipSided&&o.enable(11);e.useDepthPacking&&o.enable(12);e.dithering&&o.enable(13);e.transmission&&o.enable(14);e.sheen&&o.enable(15);e.opaque&&o.enable(16);e.pointsUvs&&o.enable(17);e.decodeVideoTexture&&o.enable(18);e.alphaToCoverage&&o.enable(19);t.push(o.mask)}(n,e),n.push(t.outputColorSpace)),n.push(e.customProgramCacheKey),n.join()},getUniforms:function(t){const e=f[t.type];let n;if(e){const t=xa[e];n=Js.clone(t.uniforms)}else n=t.uniforms;return n},acquireProgram:function(e,n){let i;for(let t=0,e=h.length;t0?i.push(h):!0===a.transparent?r.push(h):n.push(h)},unshift:function(t,e,a,o,l,c){const h=s(t,e,a,o,l,c);a.transmission>0?i.unshift(h):!0===a.transparent?r.unshift(h):n.unshift(h)},finish:function(){for(let n=e,i=t.length;n1&&n.sort(t||Ll),i.length>1&&i.sort(e||Ul),r.length>1&&r.sort(e||Ul)}}}function Dl(){let t=new WeakMap;return{get:function(e,n){const i=t.get(e);let r;return void 0===i?(r=new Nl,t.set(e,[r])):n>=i.length?(r=new Nl,i.push(r)):r=i[n],r},dispose:function(){t=new WeakMap}}}function Ol(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let n;switch(e.type){case"DirectionalLight":n={direction:new Li,color:new Kr};break;case"SpotLight":n={position:new Li,direction:new Li,color:new Kr,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":n={position:new Li,color:new Kr,distance:0,decay:0};break;case"HemisphereLight":n={direction:new Li,skyColor:new Kr,groundColor:new Kr};break;case"RectAreaLight":n={color:new Kr,position:new Li,halfWidth:new Li,halfHeight:new Li}}return t[e.id]=n,n}}}let Fl=0;function Bl(t,e){return(e.castShadow?2:0)-(t.castShadow?2:0)+(e.map?1:0)-(t.map?1:0)}function zl(t){const e=new Ol,n=function(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let n;switch(e.type){case"DirectionalLight":case"SpotLight":n={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new ti};break;case"PointLight":n={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new ti,shadowCameraNear:1,shadowCameraFar:1e3}}return t[e.id]=n,n}}}(),i={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1,numLightProbes:-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,numLightProbes:0};for(let t=0;t<9;t++)i.probe.push(new Li);const r=new Li,s=new lr,a=new lr;return{setup:function(r){let s=0,a=0,o=0;for(let t=0;t<9;t++)i.probe[t].set(0,0,0);let l=0,c=0,h=0,u=0,d=0,p=0,m=0,f=0,g=0,v=0,_=0;r.sort(Bl);for(let t=0,x=r.length;t0&&(!0===t.has("OES_texture_float_linear")?(i.rectAreaLTC1=_a.LTC_FLOAT_1,i.rectAreaLTC2=_a.LTC_FLOAT_2):(i.rectAreaLTC1=_a.LTC_HALF_1,i.rectAreaLTC2=_a.LTC_HALF_2)),i.ambient[0]=s,i.ambient[1]=a,i.ambient[2]=o;const x=i.hash;x.directionalLength===l&&x.pointLength===c&&x.spotLength===h&&x.rectAreaLength===u&&x.hemiLength===d&&x.numDirectionalShadows===p&&x.numPointShadows===m&&x.numSpotShadows===f&&x.numSpotMaps===g&&x.numLightProbes===_||(i.directional.length=l,i.spot.length=h,i.rectArea.length=u,i.point.length=c,i.hemi.length=d,i.directionalShadow.length=p,i.directionalShadowMap.length=p,i.pointShadow.length=m,i.pointShadowMap.length=m,i.spotShadow.length=f,i.spotShadowMap.length=f,i.directionalShadowMatrix.length=p,i.pointShadowMatrix.length=m,i.spotLightMatrix.length=f+g-v,i.spotLightMap.length=g,i.numSpotLightShadowsWithMaps=v,i.numLightProbes=_,x.directionalLength=l,x.pointLength=c,x.spotLength=h,x.rectAreaLength=u,x.hemiLength=d,x.numDirectionalShadows=p,x.numPointShadows=m,x.numSpotShadows=f,x.numSpotMaps=g,x.numLightProbes=_,i.version=Fl++)},setupView:function(t,e){let n=0,o=0,l=0,c=0,h=0;const u=e.matrixWorldInverse;for(let e=0,d=t.length;e=r.length?(s=new kl(t),r.push(s)):s=r[i],s},dispose:function(){e=new WeakMap}}}class Hl extends ts{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 Gl extends ts{constructor(t){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",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.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}function Wl(t,e,n){let i=new pa;const r=new ti,s=new ti,a=new wi,o=new Hl({depthPacking:3201}),c=new Gl,p={},m=n.maxTextureSize,f={[u]:d,[d]:u,2:2},g=new Ks({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new ti},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}"}),v=g.clone();v.defines.HORIZONTAL_PASS=1;const _=new Es;_.setAttribute("position",new cs(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const x=new Ws(_,g),y=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=l;let M=this.type;function S(n,i){const s=e.update(x);g.defines.VSM_SAMPLES!==n.blurSamples&&(g.defines.VSM_SAMPLES=n.blurSamples,v.defines.VSM_SAMPLES=n.blurSamples,g.needsUpdate=!0,v.needsUpdate=!0),null===n.mapPass&&(n.mapPass=new Ei(r.x,r.y)),g.uniforms.shadow_pass.value=n.map.texture,g.uniforms.resolution.value=n.mapSize,g.uniforms.radius.value=n.radius,t.setRenderTarget(n.mapPass),t.clear(),t.renderBufferDirect(i,null,s,g,x,null),v.uniforms.shadow_pass.value=n.mapPass.texture,v.uniforms.resolution.value=n.mapSize,v.uniforms.radius.value=n.radius,t.setRenderTarget(n.map),t.clear(),t.renderBufferDirect(i,null,s,v,x,null)}function b(e,n,i,r){let s=null;const a=!0===i.isPointLight?e.customDistanceMaterial:e.customDepthMaterial;if(void 0!==a)s=a;else if(s=!0===i.isPointLight?c:o,t.localClippingEnabled&&!0===n.clipShadows&&Array.isArray(n.clippingPlanes)&&0!==n.clippingPlanes.length||n.displacementMap&&0!==n.displacementScale||n.alphaMap&&n.alphaTest>0||n.map&&n.alphaTest>0){const t=s.uuid,e=n.uuid;let i=p[t];void 0===i&&(i={},p[t]=i);let r=i[e];void 0===r&&(r=s.clone(),i[e]=r,n.addEventListener("dispose",T)),s=r}if(s.visible=n.visible,s.wireframe=n.wireframe,s.side=r===h?null!==n.shadowSide?n.shadowSide:n.side:null!==n.shadowSide?n.shadowSide:f[n.side],s.alphaMap=n.alphaMap,s.alphaTest=n.alphaTest,s.map=n.map,s.clipShadows=n.clipShadows,s.clippingPlanes=n.clippingPlanes,s.clipIntersection=n.clipIntersection,s.displacementMap=n.displacementMap,s.displacementScale=n.displacementScale,s.displacementBias=n.displacementBias,s.wireframeLinewidth=n.wireframeLinewidth,s.linewidth=n.linewidth,!0===i.isPointLight&&!0===s.isMeshDistanceMaterial){t.properties.get(s).light=i}return s}function w(n,r,s,a,o){if(!1===n.visible)return;if(n.layers.test(r.layers)&&(n.isMesh||n.isLine||n.isPoints)&&(n.castShadow||n.receiveShadow&&o===h)&&(!n.frustumCulled||i.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(s.matrixWorldInverse,n.matrixWorld);const i=e.update(n),l=n.material;if(Array.isArray(l)){const e=i.groups;for(let c=0,h=e.length;cm||r.y>m)&&(r.x>m&&(s.x=Math.floor(m/g.x),r.x=s.x*g.x,u.mapSize.x=s.x),r.y>m&&(s.y=Math.floor(m/g.y),r.y=s.y*g.y,u.mapSize.y=s.y)),null===u.map||!0===p||!0===f){const t=this.type!==h?{minFilter:gt,magFilter:gt}:{};null!==u.map&&u.map.dispose(),u.map=new Ei(r.x,r.y,t),u.map.texture.name=c.name+".shadowMap",u.camera.updateProjectionMatrix()}t.setRenderTarget(u.map),t.clear();const v=u.getViewportCount();for(let t=0;t=1):-1!==N.indexOf("OpenGL ES")&&(U=parseFloat(/^OpenGL ES (\d)/.exec(N)[1]),L=U>=2);let D=null,O={};const F=t.getParameter(t.SCISSOR_BOX),B=t.getParameter(t.VIEWPORT),z=(new wi).fromArray(F),k=(new wi).fromArray(B);function V(e,n,i,r){const s=new Uint8Array(4),a=t.createTexture();t.bindTexture(e,a),t.texParameteri(e,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(e,t.TEXTURE_MAG_FILTER,t.NEAREST);for(let a=0;ae?(t.repeat.x=1,t.repeat.y=n/e,t.offset.x=0,t.offset.y=(1-t.repeat.y)/2):(t.repeat.x=e/n,t.repeat.y=1,t.offset.x=(1-t.repeat.x)/2,t.offset.y=0),t},cover:function(t,e){const n=t.image&&t.image.width?t.image.width/t.image.height:1;return n>e?(t.repeat.x=e/n,t.repeat.y=1,t.offset.x=(1-t.repeat.x)/2,t.offset.y=0):(t.repeat.x=1,t.repeat.y=n/e,t.offset.x=0,t.offset.y=(1-t.repeat.y)/2),t},fill:function(t){return t.repeat.x=1,t.repeat.y=1,t.offset.x=0,t.offset.y=0,t},getByteLength:jl};function Yl(t,e,n,i,r,s,a){const o=e.has("WEBGL_multisampled_render_to_texture")?e.get("WEBGL_multisampled_render_to_texture"):null,l="undefined"!=typeof navigator&&/OculusBrowser/g.test(navigator.userAgent),c=new ti,h=new WeakMap;let u;const d=new WeakMap;let p=!1;try{p="undefined"!=typeof OffscreenCanvas&&null!==new OffscreenCanvas(1,1).getContext("2d")}catch(t){}function m(t,e){return p?new OffscreenCanvas(t,e):ai("canvas")}function f(t,e,n){let i=1;const r=k(t);if((r.width>n||r.height>n)&&(i=n/Math.max(r.width,r.height)),i<1){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap||"undefined"!=typeof VideoFrame&&t instanceof VideoFrame){const n=Math.floor(i*r.width),s=Math.floor(i*r.height);void 0===u&&(u=m(n,s));const a=e?m(n,s):u;a.width=n,a.height=s;return a.getContext("2d").drawImage(t,0,0,n,s),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+r.width+"x"+r.height+") to ("+n+"x"+s+")."),a}return"data"in t&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+r.width+"x"+r.height+")."),t}return t}function g(t){return t.generateMipmaps&&t.minFilter!==gt&&t.minFilter!==Mt}function v(e){t.generateMipmap(e)}function _(n,i,r,s,a=!1){if(null!==n){if(void 0!==t[n])return t[n];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+n+"'")}let o=i;if(i===t.RED&&(r===t.FLOAT&&(o=t.R32F),r===t.HALF_FLOAT&&(o=t.R16F),r===t.UNSIGNED_BYTE&&(o=t.R8)),i===t.RED_INTEGER&&(r===t.UNSIGNED_BYTE&&(o=t.R8UI),r===t.UNSIGNED_SHORT&&(o=t.R16UI),r===t.UNSIGNED_INT&&(o=t.R32UI),r===t.BYTE&&(o=t.R8I),r===t.SHORT&&(o=t.R16I),r===t.INT&&(o=t.R32I)),i===t.RG&&(r===t.FLOAT&&(o=t.RG32F),r===t.HALF_FLOAT&&(o=t.RG16F),r===t.UNSIGNED_BYTE&&(o=t.RG8)),i===t.RG_INTEGER&&(r===t.UNSIGNED_BYTE&&(o=t.RG8UI),r===t.UNSIGNED_SHORT&&(o=t.RG16UI),r===t.UNSIGNED_INT&&(o=t.RG32UI),r===t.BYTE&&(o=t.RG8I),r===t.SHORT&&(o=t.RG16I),r===t.INT&&(o=t.RG32I)),i===t.RGB&&r===t.UNSIGNED_INT_5_9_9_9_REV&&(o=t.RGB9_E5),i===t.RGBA){const e=a?tn:mi.getTransfer(s);r===t.FLOAT&&(o=t.RGBA32F),r===t.HALF_FLOAT&&(o=t.RGBA16F),r===t.UNSIGNED_BYTE&&(o=e===en?t.SRGB8_ALPHA8:t.RGBA8),r===t.UNSIGNED_SHORT_4_4_4_4&&(o=t.RGBA4),r===t.UNSIGNED_SHORT_5_5_5_1&&(o=t.RGB5_A1)}return o!==t.R16F&&o!==t.R32F&&o!==t.RG16F&&o!==t.RG32F&&o!==t.RGBA16F&&o!==t.RGBA32F||e.get("EXT_color_buffer_float"),o}function x(e,n){let i;return e?null===n||n===It||n===Ot?i=t.DEPTH24_STENCIL8:n===Lt?i=t.DEPTH32F_STENCIL8:n===Ct&&(i=t.DEPTH24_STENCIL8,console.warn("DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.")):null===n||n===It||n===Ot?i=t.DEPTH_COMPONENT24:n===Lt?i=t.DEPTH_COMPONENT32F:n===Ct&&(i=t.DEPTH_COMPONENT16),i}function y(t,e){return!0===g(t)||t.isFramebufferTexture&&t.minFilter!==gt&&t.minFilter!==Mt?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 M(t){const e=t.target;e.removeEventListener("dispose",M),function(t){const e=i.get(t);if(void 0===e.__webglInit)return;const n=t.source,r=d.get(n);if(r){const i=r[e.__cacheKey];i.usedTimes--,0===i.usedTimes&&b(t),0===Object.keys(r).length&&d.delete(n)}i.remove(t)}(e),e.isVideoTexture&&h.delete(e)}function S(e){const n=e.target;n.removeEventListener("dispose",S),function(e){const n=i.get(e);e.depthTexture&&e.depthTexture.dispose();if(e.isWebGLCubeRenderTarget)for(let e=0;e<6;e++){if(Array.isArray(n.__webglFramebuffer[e]))for(let i=0;i0&&s.__version!==e.version){const t=e.image;if(null===t)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else{if(!1!==t.complete)return void I(s,e,r);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}n.bindTexture(t.TEXTURE_2D,s.__webglTexture,t.TEXTURE0+r)}const E={[pt]:t.REPEAT,[mt]:t.CLAMP_TO_EDGE,[ft]:t.MIRRORED_REPEAT},A={[gt]:t.NEAREST,[vt]:t.NEAREST_MIPMAP_NEAREST,[xt]:t.NEAREST_MIPMAP_LINEAR,[Mt]:t.LINEAR,[St]:t.LINEAR_MIPMAP_NEAREST,[wt]:t.LINEAR_MIPMAP_LINEAR},R={512:t.NEVER,519:t.ALWAYS,513:t.LESS,[wn]:t.LEQUAL,514:t.EQUAL,518:t.GEQUAL,516:t.GREATER,517:t.NOTEQUAL};function C(n,s){if(s.type!==Lt||!1!==e.has("OES_texture_float_linear")||s.magFilter!==Mt&&s.magFilter!==St&&s.magFilter!==xt&&s.magFilter!==wt&&s.minFilter!==Mt&&s.minFilter!==St&&s.minFilter!==xt&&s.minFilter!==wt||console.warn("THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device."),t.texParameteri(n,t.TEXTURE_WRAP_S,E[s.wrapS]),t.texParameteri(n,t.TEXTURE_WRAP_T,E[s.wrapT]),n!==t.TEXTURE_3D&&n!==t.TEXTURE_2D_ARRAY||t.texParameteri(n,t.TEXTURE_WRAP_R,E[s.wrapR]),t.texParameteri(n,t.TEXTURE_MAG_FILTER,A[s.magFilter]),t.texParameteri(n,t.TEXTURE_MIN_FILTER,A[s.minFilter]),s.compareFunction&&(t.texParameteri(n,t.TEXTURE_COMPARE_MODE,t.COMPARE_REF_TO_TEXTURE),t.texParameteri(n,t.TEXTURE_COMPARE_FUNC,R[s.compareFunction])),!0===e.has("EXT_texture_filter_anisotropic")){if(s.magFilter===gt)return;if(s.minFilter!==xt&&s.minFilter!==wt)return;if(s.type===Lt&&!1===e.has("OES_texture_float_linear"))return;if(s.anisotropy>1||i.get(s).__currentAnisotropy){const a=e.get("EXT_texture_filter_anisotropic");t.texParameterf(n,a.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(s.anisotropy,r.getMaxAnisotropy())),i.get(s).__currentAnisotropy=s.anisotropy}}}function P(e,n){let i=!1;void 0===e.__webglInit&&(e.__webglInit=!0,n.addEventListener("dispose",M));const r=n.source;let s=d.get(r);void 0===s&&(s={},d.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.colorSpace),e.join()}(n);if(o!==e.__cacheKey){void 0===s[o]&&(s[o]={texture:t.createTexture(),usedTimes:0},a.memory.textures++,i=!0),s[o].usedTimes++;const r=s[e.__cacheKey];void 0!==r&&(s[e.__cacheKey].usedTimes--,0===r.usedTimes&&b(n)),e.__cacheKey=o,e.__webglTexture=s[o].texture}return i}function I(e,a,o){let l=t.TEXTURE_2D;(a.isDataArrayTexture||a.isCompressedArrayTexture)&&(l=t.TEXTURE_2D_ARRAY),a.isData3DTexture&&(l=t.TEXTURE_3D);const c=P(e,a),h=a.source;n.bindTexture(l,e.__webglTexture,t.TEXTURE0+o);const u=i.get(h);if(h.version!==u.__version||!0===c){n.activeTexture(t.TEXTURE0+o);const e=mi.getPrimaries(mi.workingColorSpace),i=a.colorSpace===Ze?null:mi.getPrimaries(a.colorSpace),d=a.colorSpace===Ze||e===i?t.NONE:t.BROWSER_DEFAULT_WEBGL;t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,a.flipY),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,a.premultiplyAlpha),t.pixelStorei(t.UNPACK_ALIGNMENT,a.unpackAlignment),t.pixelStorei(t.UNPACK_COLORSPACE_CONVERSION_WEBGL,d);let p=f(a.image,!1,r.maxTextureSize);p=z(a,p);const m=s.convert(a.format,a.colorSpace),M=s.convert(a.type);let S,b=_(a.internalFormat,m,M,a.colorSpace,a.isVideoTexture);C(l,a);const w=a.mipmaps,T=!0!==a.isVideoTexture,E=void 0===u.__version||!0===c,A=h.dataReady,R=y(a,p);if(a.isDepthTexture)b=x(a.format===Wt,a.type),E&&(T?n.texStorage2D(t.TEXTURE_2D,1,b,p.width,p.height):n.texImage2D(t.TEXTURE_2D,0,b,p.width,p.height,0,m,M,null));else if(a.isDataTexture)if(w.length>0){T&&E&&n.texStorage2D(t.TEXTURE_2D,R,b,w[0].width,w[0].height);for(let e=0,i=w.length;e0){const i=jl(S.width,S.height,a.format,a.type);for(const r of a.layerUpdates){const s=S.data.subarray(r*i/S.data.BYTES_PER_ELEMENT,(r+1)*i/S.data.BYTES_PER_ELEMENT);n.compressedTexSubImage3D(t.TEXTURE_2D_ARRAY,e,0,0,r,S.width,S.height,1,m,s,0,0)}a.clearLayerUpdates()}else n.compressedTexSubImage3D(t.TEXTURE_2D_ARRAY,e,0,0,0,S.width,S.height,p.depth,m,S.data,0,0)}else n.compressedTexImage3D(t.TEXTURE_2D_ARRAY,e,b,S.width,S.height,p.depth,0,S.data,0,0);else console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()");else T?A&&n.texSubImage3D(t.TEXTURE_2D_ARRAY,e,0,0,0,S.width,S.height,p.depth,m,M,S.data):n.texImage3D(t.TEXTURE_2D_ARRAY,e,b,S.width,S.height,p.depth,0,m,M,S.data)}else{T&&E&&n.texStorage2D(t.TEXTURE_2D,R,b,w[0].width,w[0].height);for(let e=0,i=w.length;e0){const e=jl(p.width,p.height,a.format,a.type);for(const i of a.layerUpdates){const r=p.data.subarray(i*e/p.data.BYTES_PER_ELEMENT,(i+1)*e/p.data.BYTES_PER_ELEMENT);n.texSubImage3D(t.TEXTURE_2D_ARRAY,0,0,0,i,p.width,p.height,1,m,M,r)}a.clearLayerUpdates()}else n.texSubImage3D(t.TEXTURE_2D_ARRAY,0,0,0,0,p.width,p.height,p.depth,m,M,p.data)}else n.texImage3D(t.TEXTURE_2D_ARRAY,0,b,p.width,p.height,p.depth,0,m,M,p.data);else if(a.isData3DTexture)T?(E&&n.texStorage3D(t.TEXTURE_3D,R,b,p.width,p.height,p.depth),A&&n.texSubImage3D(t.TEXTURE_3D,0,0,0,0,p.width,p.height,p.depth,m,M,p.data)):n.texImage3D(t.TEXTURE_3D,0,b,p.width,p.height,p.depth,0,m,M,p.data);else if(a.isFramebufferTexture){if(E)if(T)n.texStorage2D(t.TEXTURE_2D,R,b,p.width,p.height);else{let e=p.width,i=p.height;for(let r=0;r>=1,i>>=1}}else if(w.length>0){if(T&&E){const e=k(w[0]);n.texStorage2D(t.TEXTURE_2D,R,b,e.width,e.height)}for(let e=0,i=w.length;e>h),i=Math.max(1,r.height>>h);c===t.TEXTURE_3D||c===t.TEXTURE_2D_ARRAY?n.texImage3D(c,h,p,e,i,r.depth,0,u,d,null):n.texImage2D(c,h,p,e,i,0,u,d,null)}n.bindFramebuffer(t.FRAMEBUFFER,e),B(r)?o.framebufferTexture2DMultisampleEXT(t.FRAMEBUFFER,l,c,i.get(a).__webglTexture,0,F(r)):(c===t.TEXTURE_2D||c>=t.TEXTURE_CUBE_MAP_POSITIVE_X&&c<=t.TEXTURE_CUBE_MAP_NEGATIVE_Z)&&t.framebufferTexture2D(t.FRAMEBUFFER,l,c,i.get(a).__webglTexture,h),n.bindFramebuffer(t.FRAMEBUFFER,null)}function U(e,n,i){if(t.bindRenderbuffer(t.RENDERBUFFER,e),n.depthBuffer){const r=n.depthTexture,s=r&&r.isDepthTexture?r.type:null,a=x(n.stencilBuffer,s),l=n.stencilBuffer?t.DEPTH_STENCIL_ATTACHMENT:t.DEPTH_ATTACHMENT,c=F(n);B(n)?o.renderbufferStorageMultisampleEXT(t.RENDERBUFFER,c,a,n.width,n.height):i?t.renderbufferStorageMultisample(t.RENDERBUFFER,c,a,n.width,n.height):t.renderbufferStorage(t.RENDERBUFFER,a,n.width,n.height),t.framebufferRenderbuffer(t.FRAMEBUFFER,l,t.RENDERBUFFER,e)}else{const e=n.textures;for(let r=0;r{delete r.__boundDepthTexture,delete r.__depthDisposeCallback,t.removeEventListener("dispose",e)};t.addEventListener("dispose",e),r.__depthDisposeCallback=e}r.__boundDepthTexture=t}if(e.depthTexture&&!r.__autoAllocateDepthBuffer){if(s)throw new Error("target.depthTexture not supported in Cube render targets");!function(e,r){if(r&&r.isWebGLCubeRenderTarget)throw new Error("Depth Texture with cube render targets is not supported");if(n.bindFramebuffer(t.FRAMEBUFFER,e),!r.depthTexture||!r.depthTexture.isDepthTexture)throw new Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture");i.get(r.depthTexture).__webglTexture&&r.depthTexture.image.width===r.width&&r.depthTexture.image.height===r.height||(r.depthTexture.image.width=r.width,r.depthTexture.image.height=r.height,r.depthTexture.needsUpdate=!0),T(r.depthTexture,0);const s=i.get(r.depthTexture).__webglTexture,a=F(r);if(r.depthTexture.format===Gt)B(r)?o.framebufferTexture2DMultisampleEXT(t.FRAMEBUFFER,t.DEPTH_ATTACHMENT,t.TEXTURE_2D,s,0,a):t.framebufferTexture2D(t.FRAMEBUFFER,t.DEPTH_ATTACHMENT,t.TEXTURE_2D,s,0);else{if(r.depthTexture.format!==Wt)throw new Error("Unknown depthTexture format");B(r)?o.framebufferTexture2DMultisampleEXT(t.FRAMEBUFFER,t.DEPTH_STENCIL_ATTACHMENT,t.TEXTURE_2D,s,0,a):t.framebufferTexture2D(t.FRAMEBUFFER,t.DEPTH_STENCIL_ATTACHMENT,t.TEXTURE_2D,s,0)}}(r.__webglFramebuffer,e)}else if(s){r.__webglDepthbuffer=[];for(let i=0;i<6;i++)if(n.bindFramebuffer(t.FRAMEBUFFER,r.__webglFramebuffer[i]),void 0===r.__webglDepthbuffer[i])r.__webglDepthbuffer[i]=t.createRenderbuffer(),U(r.__webglDepthbuffer[i],e,!1);else{const n=e.stencilBuffer?t.DEPTH_STENCIL_ATTACHMENT:t.DEPTH_ATTACHMENT,s=r.__webglDepthbuffer[i];t.bindRenderbuffer(t.RENDERBUFFER,s),t.framebufferRenderbuffer(t.FRAMEBUFFER,n,t.RENDERBUFFER,s)}}else if(n.bindFramebuffer(t.FRAMEBUFFER,r.__webglFramebuffer),void 0===r.__webglDepthbuffer)r.__webglDepthbuffer=t.createRenderbuffer(),U(r.__webglDepthbuffer,e,!1);else{const n=e.stencilBuffer?t.DEPTH_STENCIL_ATTACHMENT:t.DEPTH_ATTACHMENT,i=r.__webglDepthbuffer;t.bindRenderbuffer(t.RENDERBUFFER,i),t.framebufferRenderbuffer(t.FRAMEBUFFER,n,t.RENDERBUFFER,i)}n.bindFramebuffer(t.FRAMEBUFFER,null)}const D=[],O=[];function F(t){return Math.min(r.maxSamples,t.samples)}function B(t){const n=i.get(t);return t.samples>0&&!0===e.has("WEBGL_multisampled_render_to_texture")&&!1!==n.__useRenderToTexture}function z(t,e){const n=t.colorSpace,i=t.format,r=t.type;return!0===t.isCompressedTexture||!0===t.isVideoTexture||n!==Ke&&n!==Ze&&(mi.getTransfer(n)===en?i===kt&&r===Et||console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture color space:",n)),e}function k(t){return"undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement?(c.width=t.naturalWidth||t.width,c.height=t.naturalHeight||t.height):"undefined"!=typeof VideoFrame&&t instanceof VideoFrame?(c.width=t.displayWidth,c.height=t.displayHeight):(c.width=t.width,c.height=t.height),c}this.allocateTextureUnit=function(){const t=w;return t>=r.maxTextures&&console.warn("THREE.WebGLTextures: Trying to use "+t+" texture units while this GPU supports only "+r.maxTextures),w+=1,t},this.resetTextureUnits=function(){w=0},this.setTexture2D=T,this.setTexture2DArray=function(e,r){const s=i.get(e);e.version>0&&s.__version!==e.version?I(s,e,r):n.bindTexture(t.TEXTURE_2D_ARRAY,s.__webglTexture,t.TEXTURE0+r)},this.setTexture3D=function(e,r){const s=i.get(e);e.version>0&&s.__version!==e.version?I(s,e,r):n.bindTexture(t.TEXTURE_3D,s.__webglTexture,t.TEXTURE0+r)},this.setTextureCube=function(e,a){const o=i.get(e);e.version>0&&o.__version!==e.version?function(e,a,o){if(6!==a.image.length)return;const l=P(e,a),c=a.source;n.bindTexture(t.TEXTURE_CUBE_MAP,e.__webglTexture,t.TEXTURE0+o);const h=i.get(c);if(c.version!==h.__version||!0===l){n.activeTexture(t.TEXTURE0+o);const e=mi.getPrimaries(mi.workingColorSpace),i=a.colorSpace===Ze?null:mi.getPrimaries(a.colorSpace),u=a.colorSpace===Ze||e===i?t.NONE:t.BROWSER_DEFAULT_WEBGL;t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,a.flipY),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,a.premultiplyAlpha),t.pixelStorei(t.UNPACK_ALIGNMENT,a.unpackAlignment),t.pixelStorei(t.UNPACK_COLORSPACE_CONVERSION_WEBGL,u);const d=a.isCompressedTexture||a.image[0].isCompressedTexture,p=a.image[0]&&a.image[0].isDataTexture,m=[];for(let t=0;t<6;t++)m[t]=d||p?p?a.image[t].image:a.image[t]:f(a.image[t],!0,r.maxCubemapSize),m[t]=z(a,m[t]);const x=m[0],M=s.convert(a.format,a.colorSpace),S=s.convert(a.type),b=_(a.internalFormat,M,S,a.colorSpace),w=!0!==a.isVideoTexture,T=void 0===h.__version||!0===l,E=c.dataReady;let A,R=y(a,x);if(C(t.TEXTURE_CUBE_MAP,a),d){w&&T&&n.texStorage2D(t.TEXTURE_CUBE_MAP,R,b,x.width,x.height);for(let e=0;e<6;e++){A=m[e].mipmaps;for(let i=0;i0&&R++;const e=k(m[0]);n.texStorage2D(t.TEXTURE_CUBE_MAP,R,b,e.width,e.height)}for(let e=0;e<6;e++)if(p){w?E&&n.texSubImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,0,0,0,m[e].width,m[e].height,M,S,m[e].data):n.texImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,0,b,m[e].width,m[e].height,0,M,S,m[e].data);for(let i=0;i1;if(u||(void 0===l.__webglTexture&&(l.__webglTexture=t.createTexture()),l.__version=r.version,a.memory.textures++),h){o.__webglFramebuffer=[];for(let e=0;e<6;e++)if(r.mipmaps&&r.mipmaps.length>0){o.__webglFramebuffer[e]=[];for(let n=0;n0){o.__webglFramebuffer=[];for(let e=0;e0&&!1===B(e)){o.__webglMultisampledFramebuffer=t.createFramebuffer(),o.__webglColorRenderbuffer=[],n.bindFramebuffer(t.FRAMEBUFFER,o.__webglMultisampledFramebuffer);for(let n=0;n0)for(let i=0;i0)for(let n=0;n0)if(!1===B(e)){const r=e.textures,s=e.width,a=e.height;let o=t.COLOR_BUFFER_BIT;const c=e.stencilBuffer?t.DEPTH_STENCIL_ATTACHMENT:t.DEPTH_ATTACHMENT,h=i.get(e),u=r.length>1;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,n),null!==r&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,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&&(i=e.getPose(t.targetRaySpace,n),null===i&&null!==r&&(i=r),null!==i&&(a.matrix.fromArray(i.transform.matrix),a.matrix.decompose(a.position,a.rotation,a.scale),a.matrixWorldNeedsUpdate=!0,i.linearVelocity?(a.hasLinearVelocity=!0,a.linearVelocity.copy(i.linearVelocity)):a.hasLinearVelocity=!1,i.angularVelocity?(a.hasAngularVelocity=!0,a.angularVelocity.copy(i.angularVelocity)):a.hasAngularVelocity=!1,this.dispatchEvent($l)))}return null!==a&&(a.visible=null!==i),null!==o&&(o.visible=null!==r),null!==l&&(l.visible=null!==s),this}_getHandJoint(t,e){if(void 0===t.joints[e.jointName]){const n=new Kl;n.matrixAutoUpdate=!1,n.visible=!1,t.joints[e.jointName]=n,t.add(n)}return t.joints[e.jointName]}}class tc{constructor(){this.texture=null,this.mesh=null,this.depthNear=0,this.depthFar=0}init(t,e,n){if(null===this.texture){const i=new bi;t.properties.get(i).__webglTexture=e.texture,e.depthNear==n.depthNear&&e.depthFar==n.depthFar||(this.depthNear=e.depthNear,this.depthFar=e.depthFar),this.texture=i}}getMesh(t){if(null!==this.texture&&null===this.mesh){const e=t.cameras[0].viewport,n=new Ks({vertexShader:"\nvoid main() {\n\n\tgl_Position = vec4( position, 1.0 );\n\n}",fragmentShader:"\nuniform sampler2DArray depthColor;\nuniform float depthWidth;\nuniform float depthHeight;\n\nvoid main() {\n\n\tvec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight );\n\n\tif ( coord.x >= 1.0 ) {\n\n\t\tgl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r;\n\n\t} else {\n\n\t\tgl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r;\n\n\t}\n\n}",uniforms:{depthColor:{value:this.texture},depthWidth:{value:e.z},depthHeight:{value:e.w}}});this.mesh=new Ws(new ga(20,20),n)}return this.mesh}reset(){this.texture=null,this.mesh=null}getDepthTexture(){return this.texture}}class ec extends Hn{constructor(t,e){super();const n=this;let i=null,r=1,s=null,a="local-floor",o=1,l=null,c=null,h=null,u=null,d=null,p=null;const m=new tc,f=e.getContextAttributes();let g=null,v=null;const _=[],x=[],y=new ti;let M=null;const S=new na;S.layers.enable(1),S.viewport=new wi;const b=new na;b.layers.enable(2),b.viewport=new wi;const w=[S,b],T=new Jl;T.layers.enable(1),T.layers.enable(2);let E=null,A=null;function R(t){const e=x.indexOf(t.inputSource);if(-1===e)return;const n=_[e];void 0!==n&&(n.update(t.inputSource,t.frame,l||s),n.dispatchEvent({type:t.type,data:t.inputSource}))}function C(){i.removeEventListener("select",R),i.removeEventListener("selectstart",R),i.removeEventListener("selectend",R),i.removeEventListener("squeeze",R),i.removeEventListener("squeezestart",R),i.removeEventListener("squeezeend",R),i.removeEventListener("end",C),i.removeEventListener("inputsourceschange",P);for(let t=0;t<_.length;t++){const e=x[t];null!==e&&(x[t]=null,_[t].disconnect(e))}E=null,A=null,m.reset(),t.setRenderTarget(g),d=null,u=null,h=null,i=null,v=null,D.stop(),n.isPresenting=!1,t.setPixelRatio(M),t.setSize(y.width,y.height,!1),n.dispatchEvent({type:"sessionend"})}function P(t){for(let e=0;e=0&&(x[i]=null,_[i].disconnect(n))}for(let e=0;e=x.length){x.push(n),i=t;break}if(null===x[t]){x[t]=n,i=t;break}}if(-1===i)break}const r=_[i];r&&r.connect(n)}}this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(t){let e=_[t];return void 0===e&&(e=new Ql,_[t]=e),e.getTargetRaySpace()},this.getControllerGrip=function(t){let e=_[t];return void 0===e&&(e=new Ql,_[t]=e),e.getGripSpace()},this.getHand=function(t){let e=_[t];return void 0===e&&(e=new Ql,_[t]=e),e.getHandSpace()},this.setFramebufferScaleFactor=function(t){r=t,!0===n.isPresenting&&console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting.")},this.setReferenceSpaceType=function(t){a=t,!0===n.isPresenting&&console.warn("THREE.WebXRManager: Cannot change reference space type while presenting.")},this.getReferenceSpace=function(){return l||s},this.setReferenceSpace=function(t){l=t},this.getBaseLayer=function(){return null!==u?u:d},this.getBinding=function(){return h},this.getFrame=function(){return p},this.getSession=function(){return i},this.setSession=async function(c){if(i=c,null!==i){if(g=t.getRenderTarget(),i.addEventListener("select",R),i.addEventListener("selectstart",R),i.addEventListener("selectend",R),i.addEventListener("squeeze",R),i.addEventListener("squeezestart",R),i.addEventListener("squeezeend",R),i.addEventListener("end",C),i.addEventListener("inputsourceschange",P),!0!==f.xrCompatible&&await e.makeXRCompatible(),M=t.getPixelRatio(),t.getSize(y),void 0===i.renderState.layers){const n={antialias:f.antialias,alpha:!0,depth:f.depth,stencil:f.stencil,framebufferScaleFactor:r};d=new XRWebGLLayer(i,e,n),i.updateRenderState({baseLayer:d}),t.setPixelRatio(1),t.setSize(d.framebufferWidth,d.framebufferHeight,!1),v=new Ei(d.framebufferWidth,d.framebufferHeight,{format:kt,type:Et,colorSpace:t.outputColorSpace,stencilBuffer:f.stencil})}else{let n=null,s=null,a=null;f.depth&&(a=f.stencil?e.DEPTH24_STENCIL8:e.DEPTH_COMPONENT24,n=f.stencil?Wt:Gt,s=f.stencil?Ot:It);const o={colorFormat:e.RGBA8,depthFormat:a,scaleFactor:r};h=new XRWebGLBinding(i,e),u=h.createProjectionLayer(o),i.updateRenderState({layers:[u]}),t.setPixelRatio(1),t.setSize(u.textureWidth,u.textureHeight,!1),v=new Ei(u.textureWidth,u.textureHeight,{format:kt,type:Et,depthTexture:new to(u.textureWidth,u.textureHeight,s,void 0,void 0,void 0,void 0,void 0,void 0,n),stencilBuffer:f.stencil,colorSpace:t.outputColorSpace,samples:f.antialias?4:0,resolveDepthBuffer:!1===u.ignoreDepthValues})}v.isXRRenderTarget=!0,this.setFoveation(o),l=null,s=await i.requestReferenceSpace(a),D.setContext(i),D.start(),n.isPresenting=!0,n.dispatchEvent({type:"sessionstart"})}},this.getEnvironmentBlendMode=function(){if(null!==i)return i.environmentBlendMode},this.getDepthTexture=function(){return m.getDepthTexture()};const I=new Li,L=new Li;function U(t,e){null===e?t.matrixWorld.copy(t.matrix):t.matrixWorld.multiplyMatrices(e.matrixWorld,t.matrix),t.matrixWorldInverse.copy(t.matrixWorld).invert()}this.updateCamera=function(t){if(null===i)return;let e=t.near,n=t.far;null!==m.texture&&(m.depthNear>0&&(e=m.depthNear),m.depthFar>0&&(n=m.depthFar)),T.near=b.near=S.near=e,T.far=b.far=S.far=n,E===T.near&&A===T.far||(i.updateRenderState({depthNear:T.near,depthFar:T.far}),E=T.near,A=T.far);const r=t.parent,s=T.cameras;U(T,r);for(let t=0;t0&&(t.alphaTest.value=i.alphaTest);const r=e.get(i),s=r.envMap,a=r.envMapRotation;s&&(t.envMap.value=s,nc.copy(a),nc.x*=-1,nc.y*=-1,nc.z*=-1,s.isCubeTexture&&!1===s.isRenderTargetTexture&&(nc.y*=-1,nc.z*=-1),t.envMapRotation.value.setFromMatrix4(ic.makeRotationFromEuler(nc)),t.flipEnvMap.value=s.isCubeTexture&&!1===s.isRenderTargetTexture?-1:1,t.reflectivity.value=i.reflectivity,t.ior.value=i.ior,t.refractionRatio.value=i.refractionRatio),i.lightMap&&(t.lightMap.value=i.lightMap,t.lightMapIntensity.value=i.lightMapIntensity,n(i.lightMap,t.lightMapTransform)),i.aoMap&&(t.aoMap.value=i.aoMap,t.aoMapIntensity.value=i.aoMapIntensity,n(i.aoMap,t.aoMapTransform))}return{refreshFogUniforms:function(e,n){n.color.getRGB(e.fogColor.value,Zs(t)),n.isFog?(e.fogNear.value=n.near,e.fogFar.value=n.far):n.isFogExp2&&(e.fogDensity.value=n.density)},refreshMaterialUniforms:function(t,r,s,a,o){r.isMeshBasicMaterial||r.isMeshLambertMaterial?i(t,r):r.isMeshToonMaterial?(i(t,r),function(t,e){e.gradientMap&&(t.gradientMap.value=e.gradientMap)}(t,r)):r.isMeshPhongMaterial?(i(t,r),function(t,e){t.specular.value.copy(e.specular),t.shininess.value=Math.max(e.shininess,1e-4)}(t,r)):r.isMeshStandardMaterial?(i(t,r),function(t,e){t.metalness.value=e.metalness,e.metalnessMap&&(t.metalnessMap.value=e.metalnessMap,n(e.metalnessMap,t.metalnessMapTransform));t.roughness.value=e.roughness,e.roughnessMap&&(t.roughnessMap.value=e.roughnessMap,n(e.roughnessMap,t.roughnessMapTransform));e.envMap&&(t.envMapIntensity.value=e.envMapIntensity)}(t,r),r.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,n(e.sheenColorMap,t.sheenColorMapTransform)),e.sheenRoughnessMap&&(t.sheenRoughnessMap.value=e.sheenRoughnessMap,n(e.sheenRoughnessMap,t.sheenRoughnessMapTransform)));e.clearcoat>0&&(t.clearcoat.value=e.clearcoat,t.clearcoatRoughness.value=e.clearcoatRoughness,e.clearcoatMap&&(t.clearcoatMap.value=e.clearcoatMap,n(e.clearcoatMap,t.clearcoatMapTransform)),e.clearcoatRoughnessMap&&(t.clearcoatRoughnessMap.value=e.clearcoatRoughnessMap,n(e.clearcoatRoughnessMap,t.clearcoatRoughnessMapTransform)),e.clearcoatNormalMap&&(t.clearcoatNormalMap.value=e.clearcoatNormalMap,n(e.clearcoatNormalMap,t.clearcoatNormalMapTransform),t.clearcoatNormalScale.value.copy(e.clearcoatNormalScale),e.side===d&&t.clearcoatNormalScale.value.negate()));e.dispersion>0&&(t.dispersion.value=e.dispersion);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,n(e.iridescenceMap,t.iridescenceMapTransform)),e.iridescenceThicknessMap&&(t.iridescenceThicknessMap.value=e.iridescenceThicknessMap,n(e.iridescenceThicknessMap,t.iridescenceThicknessMapTransform)));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,n(e.transmissionMap,t.transmissionMapTransform)),t.thickness.value=e.thickness,e.thicknessMap&&(t.thicknessMap.value=e.thicknessMap,n(e.thicknessMap,t.thicknessMapTransform)),t.attenuationDistance.value=e.attenuationDistance,t.attenuationColor.value.copy(e.attenuationColor));e.anisotropy>0&&(t.anisotropyVector.value.set(e.anisotropy*Math.cos(e.anisotropyRotation),e.anisotropy*Math.sin(e.anisotropyRotation)),e.anisotropyMap&&(t.anisotropyMap.value=e.anisotropyMap,n(e.anisotropyMap,t.anisotropyMapTransform)));t.specularIntensity.value=e.specularIntensity,t.specularColor.value.copy(e.specularColor),e.specularColorMap&&(t.specularColorMap.value=e.specularColorMap,n(e.specularColorMap,t.specularColorMapTransform));e.specularIntensityMap&&(t.specularIntensityMap.value=e.specularIntensityMap,n(e.specularIntensityMap,t.specularIntensityMapTransform))}(t,r,o)):r.isMeshMatcapMaterial?(i(t,r),function(t,e){e.matcap&&(t.matcap.value=e.matcap)}(t,r)):r.isMeshDepthMaterial?i(t,r):r.isMeshDistanceMaterial?(i(t,r),function(t,n){const i=e.get(n).light;t.referencePosition.value.setFromMatrixPosition(i.matrixWorld),t.nearDistance.value=i.shadow.camera.near,t.farDistance.value=i.shadow.camera.far}(t,r)):r.isMeshNormalMaterial?i(t,r):r.isLineBasicMaterial?(function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,e.map&&(t.map.value=e.map,n(e.map,t.mapTransform))}(t,r),r.isLineDashedMaterial&&function(t,e){t.dashSize.value=e.dashSize,t.totalSize.value=e.dashSize+e.gapSize,t.scale.value=e.scale}(t,r)):r.isPointsMaterial?function(t,e,i,r){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.size.value=e.size*i,t.scale.value=.5*r,e.map&&(t.map.value=e.map,n(e.map,t.uvTransform));e.alphaMap&&(t.alphaMap.value=e.alphaMap,n(e.alphaMap,t.alphaMapTransform));e.alphaTest>0&&(t.alphaTest.value=e.alphaTest)}(t,r,s,a):r.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,n(e.map,t.mapTransform));e.alphaMap&&(t.alphaMap.value=e.alphaMap,n(e.alphaMap,t.alphaMapTransform));e.alphaTest>0&&(t.alphaTest.value=e.alphaTest)}(t,r):r.isShadowMaterial?(t.color.value.copy(r.color),t.opacity.value=r.opacity):r.isShaderMaterial&&(r.uniformsNeedUpdate=!1)}}}function sc(t,e,n,i){let r={},s={},a=[];const o=t.getParameter(t.MAX_UNIFORM_BUFFER_BINDINGS);function l(t,e,n,i){const r=t.value,s=e+"_"+n;if(void 0===i[s])return i[s]="number"==typeof r||"boolean"==typeof r?r:r.clone(),!0;{const t=i[s];if("number"==typeof r||"boolean"==typeof r){if(t!==r)return i[s]=r,!0}else if(!1===t.equals(r))return t.copy(r),!0}return!1}function c(t){const e={boundary:0,storage:0};return"number"==typeof t||"boolean"==typeof t?(e.boundary=4,e.storage=4):t.isVector2?(e.boundary=8,e.storage=8):t.isVector3||t.isColor?(e.boundary=16,e.storage=12):t.isVector4?(e.boundary=16,e.storage=16):t.isMatrix3?(e.boundary=48,e.storage=48):t.isMatrix4?(e.boundary=64,e.storage=64):t.isTexture?console.warn("THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group."):console.warn("THREE.WebGLRenderer: Unsupported uniform value type.",t),e}function h(e){const n=e.target;n.removeEventListener("dispose",h);const i=a.indexOf(n.__bindingPointIndex);a.splice(i,1),t.deleteBuffer(r[n.id]),delete r[n.id],delete s[n.id]}return{bind:function(t,e){const n=e.program;i.uniformBlockBinding(t,n)},update:function(n,u){let d=r[n.id];void 0===d&&(!function(t){const e=t.uniforms;let n=0;const i=16;for(let t=0,r=e.length;t0&&(n+=i-r);t.__size=n,t.__cache={}}(n),d=function(e){const n=function(){for(let t=0;t0),u=!!n.morphAttributes.position,d=!!n.morphAttributes.normal,p=!!n.morphAttributes.color;let m=K;i.toneMapped&&(null!==T&&!0!==T.isXRRenderTarget||(m=M.toneMapping));const f=n.morphAttributes.position||n.morphAttributes.normal||n.morphAttributes.color,g=void 0!==f?f.length:0,v=et.get(i),x=_.state.lights;if(!0===H&&(!0===G||t!==A)){const e=t===A&&i.id===E;dt.setState(i,t,e)}let y=!1;i.version===v.__version?v.needsLights&&v.lightsStateVersion!==x.state.version||v.outputColorSpace!==o||r.isBatchedMesh&&!1===v.batching?y=!0:r.isBatchedMesh||!0!==v.batching?r.isBatchedMesh&&!0===v.batchingColor&&null===r.colorTexture||r.isBatchedMesh&&!1===v.batchingColor&&null!==r.colorTexture||r.isInstancedMesh&&!1===v.instancing?y=!0:r.isInstancedMesh||!0!==v.instancing?r.isSkinnedMesh&&!1===v.skinning?y=!0:r.isSkinnedMesh||!0!==v.skinning?r.isInstancedMesh&&!0===v.instancingColor&&null===r.instanceColor||r.isInstancedMesh&&!1===v.instancingColor&&null!==r.instanceColor||r.isInstancedMesh&&!0===v.instancingMorph&&null===r.morphTexture||r.isInstancedMesh&&!1===v.instancingMorph&&null!==r.morphTexture||v.envMap!==l||!0===i.fog&&v.fog!==s?y=!0:void 0===v.numClippingPlanes||v.numClippingPlanes===dt.numPlanes&&v.numIntersection===dt.numIntersection?(v.vertexAlphas!==c||v.vertexTangents!==h||v.morphTargets!==u||v.morphNormals!==d||v.morphColors!==p||v.toneMapping!==m||v.morphTargetsCount!==g)&&(y=!0):y=!0:y=!0:y=!0:y=!0:(y=!0,v.__version=i.version);let S=v.currentProgram;!0===y&&(S=Zt(i,e,r));let b=!1,w=!1,R=!1;const C=S.getUniforms(),P=v.uniforms;Q.useProgram(S.program)&&(b=!0,w=!0,R=!0);i.id!==E&&(E=i.id,w=!0);if(b||A!==t){C.setValue(Mt,"projectionMatrix",t.projectionMatrix),C.setValue(Mt,"viewMatrix",t.matrixWorldInverse);const e=C.map.cameraPosition;void 0!==e&&e.setValue(Mt,X.setFromMatrixPosition(t.matrixWorld)),$.logarithmicDepthBuffer&&C.setValue(Mt,"logDepthBufFC",2/(Math.log(t.far+1)/Math.LN2)),(i.isMeshPhongMaterial||i.isMeshToonMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial)&&C.setValue(Mt,"isOrthographic",!0===t.isOrthographicCamera),A!==t&&(A=t,w=!0,R=!0)}if(r.isSkinnedMesh){C.setOptional(Mt,r,"bindMatrix"),C.setOptional(Mt,r,"bindMatrixInverse");const t=r.skeleton;t&&(null===t.boneTexture&&t.computeBoneTexture(),C.setValue(Mt,"boneTexture",t.boneTexture,nt))}r.isBatchedMesh&&(C.setOptional(Mt,r,"batchingTexture"),C.setValue(Mt,"batchingTexture",r._matricesTexture,nt),C.setOptional(Mt,r,"batchingIdTexture"),C.setValue(Mt,"batchingIdTexture",r._indirectTexture,nt),C.setOptional(Mt,r,"batchingColorTexture"),null!==r._colorsTexture&&C.setValue(Mt,"batchingColorTexture",r._colorsTexture,nt));const I=n.morphAttributes;void 0===I.position&&void 0===I.normal&&void 0===I.color||ft.update(r,n,S);(w||v.receiveShadow!==r.receiveShadow)&&(v.receiveShadow=r.receiveShadow,C.setValue(Mt,"receiveShadow",r.receiveShadow));i.isMeshGouraudMaterial&&null!==i.envMap&&(P.envMap.value=l,P.flipEnvMap.value=l.isCubeTexture&&!1===l.isRenderTargetTexture?-1:1);i.isMeshStandardMaterial&&null===i.envMap&&null!==e.environment&&(P.envMapIntensity.value=e.environmentIntensity);w&&(C.setValue(Mt,"toneMappingExposure",M.toneMappingExposure),v.needsLights&&(U=R,(L=P).ambientLightColor.needsUpdate=U,L.lightProbe.needsUpdate=U,L.directionalLights.needsUpdate=U,L.directionalLightShadows.needsUpdate=U,L.pointLights.needsUpdate=U,L.pointLightShadows.needsUpdate=U,L.spotLights.needsUpdate=U,L.spotLightShadows.needsUpdate=U,L.rectAreaLights.needsUpdate=U,L.hemisphereLights.needsUpdate=U),s&&!0===i.fog&&ct.refreshFogUniforms(P,s),ct.refreshMaterialUniforms(P,i,D,N,_.state.transmissionRenderTarget[t.id]),al.upload(Mt,Kt(v),P,nt));var L,U;i.isShaderMaterial&&!0===i.uniformsNeedUpdate&&(al.upload(Mt,Kt(v),P,nt),i.uniformsNeedUpdate=!1);i.isSpriteMaterial&&C.setValue(Mt,"center",r.center);if(C.setValue(Mt,"modelViewMatrix",r.modelViewMatrix),C.setValue(Mt,"normalMatrix",r.normalMatrix),C.setValue(Mt,"modelMatrix",r.matrixWorld),i.isShaderMaterial||i.isRawShaderMaterial){const t=i.uniformsGroups;for(let e=0,n=t.length;e{function n(){i.forEach((function(t){et.get(t).currentProgram.isReady()&&i.delete(t)})),0!==i.size?setTimeout(n,10):e(t)}null!==J.get("KHR_parallel_shader_compile")?n():setTimeout(n,10)}))};let Bt=null;function zt(){Vt.stop()}function kt(){Vt.start()}const Vt=new ma;function Ht(t,e,n,i){if(!1===t.visible)return;if(t.layers.test(e.layers))if(t.isGroup)n=t.renderOrder;else if(t.isLOD)!0===t.autoUpdate&&t.update(e);else if(t.isLight)_.pushLight(t),t.castShadow&&_.pushShadow(t);else if(t.isSprite){if(!t.frustumCulled||V.intersectsSprite(t)){i&&j.setFromMatrixPosition(t.matrixWorld).applyMatrix4(W);const e=ot.update(t),r=t.material;r.visible&&v.push(t,e,r,n,j.z,null)}}else if((t.isMesh||t.isLine||t.isPoints)&&(!t.frustumCulled||V.intersectsObject(t))){const e=ot.update(t),r=t.material;if(i&&(void 0!==t.boundingSphere?(null===t.boundingSphere&&t.computeBoundingSphere(),j.copy(t.boundingSphere.center)):(null===e.boundingSphere&&e.computeBoundingSphere(),j.copy(e.boundingSphere.center)),j.applyMatrix4(t.matrixWorld).applyMatrix4(W)),Array.isArray(r)){const i=e.groups;for(let s=0,a=i.length;s0&&Xt(r,e,n),s.length>0&&Xt(s,e,n),a.length>0&&Xt(a,e,n),Q.buffers.depth.setTest(!0),Q.buffers.depth.setMask(!0),Q.buffers.color.setMask(!0),Q.setPolygonOffset(!1)}function Wt(t,e,n,i){if(null!==(!0===n.isScene?n.overrideMaterial:null))return;void 0===_.state.transmissionRenderTarget[i.id]&&(_.state.transmissionRenderTarget[i.id]=new Ei(1,1,{generateMipmaps:!0,type:J.has("EXT_color_buffer_half_float")||J.has("EXT_color_buffer_float")?Ut:Et,minFilter:wt,samples:4,stencilBuffer:s,resolveDepthBuffer:!1,resolveStencilBuffer:!1,colorSpace:mi.workingColorSpace}));const r=_.state.transmissionRenderTarget[i.id],a=i.viewport||R;r.setSize(a.z,a.w);const o=M.getRenderTarget();M.setRenderTarget(r),M.getClearColor(I),L=M.getClearAlpha(),L<1&&M.setClearColor(16777215,.5),M.clear(),Y&&mt.render(n);const l=M.toneMapping;M.toneMapping=K;const c=i.viewport;if(void 0!==i.viewport&&(i.viewport=void 0),_.setupLightsView(i),!0===H&&dt.setGlobalState(M.clippingPlanes,i),Xt(t,n,i),nt.updateMultisampleRenderTarget(r),nt.updateRenderTargetMipmap(r),!1===J.has("WEBGL_multisampled_render_to_texture")){let t=!1;for(let r=0,s=e.length;r0)for(let e=0,s=n.length;e0&&Wt(i,r,t,e),Y&&mt.render(t),Gt(v,t,e);null!==T&&(nt.updateMultisampleRenderTarget(T),nt.updateRenderTargetMipmap(T)),!0===t.isScene&&t.onAfterRender(M,t,e),xt.resetDefaultState(),E=-1,A=null,y.pop(),y.length>0?(_=y[y.length-1],!0===H&&dt.setGlobalState(M.clippingPlanes,_.state.camera)):_=null,x.pop(),v=x.length>0?x[x.length-1]:null},this.getActiveCubeFace=function(){return b},this.getActiveMipmapLevel=function(){return w},this.getRenderTarget=function(){return T},this.setRenderTargetTextures=function(t,e,n){et.get(t.texture).__webglTexture=e,et.get(t.depthTexture).__webglTexture=n;const i=et.get(t);i.__hasExternalTextures=!0,i.__autoAllocateDepthBuffer=void 0===n,i.__autoAllocateDepthBuffer||!0===J.has("WEBGL_multisampled_render_to_texture")&&(console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"),i.__useRenderToTexture=!1)},this.setRenderTargetFramebuffer=function(t,e){const n=et.get(t);n.__webglFramebuffer=e,n.__useDefaultFramebuffer=void 0===e},this.setRenderTarget=function(t,e=0,n=0){T=t,b=e,w=n;let i=!0,r=null,s=!1,a=!1;if(t){const o=et.get(t);if(void 0!==o.__useDefaultFramebuffer)Q.bindFramebuffer(Mt.FRAMEBUFFER,null),i=!1;else if(void 0===o.__webglFramebuffer)nt.setupRenderTarget(t);else if(o.__hasExternalTextures)nt.rebindTextures(t,et.get(t.texture).__webglTexture,et.get(t.depthTexture).__webglTexture);else if(t.depthBuffer){const e=t.depthTexture;if(o.__boundDepthTexture!==e){if(null!==e&&et.has(e)&&(t.width!==e.image.width||t.height!==e.image.height))throw new Error("WebGLRenderTarget: Attached DepthTexture is initialized to the incorrect size.");nt.setupDepthRenderbuffer(t)}}const l=t.texture;(l.isData3DTexture||l.isDataArrayTexture||l.isCompressedArrayTexture)&&(a=!0);const c=et.get(t).__webglFramebuffer;t.isWebGLCubeRenderTarget?(r=Array.isArray(c[e])?c[e][n]:c[e],s=!0):r=t.samples>0&&!1===nt.useMultisampledRTT(t)?et.get(t).__webglMultisampledFramebuffer:Array.isArray(c)?c[n]:c,R.copy(t.viewport),C.copy(t.scissor),P=t.scissorTest}else R.copy(B).multiplyScalar(D).floor(),C.copy(z).multiplyScalar(D).floor(),P=k;if(Q.bindFramebuffer(Mt.FRAMEBUFFER,r)&&i&&Q.drawBuffers(t,r),Q.viewport(R),Q.scissor(C),Q.setScissorTest(P),s){const i=et.get(t.texture);Mt.framebufferTexture2D(Mt.FRAMEBUFFER,Mt.COLOR_ATTACHMENT0,Mt.TEXTURE_CUBE_MAP_POSITIVE_X+e,i.__webglTexture,n)}else if(a){const i=et.get(t.texture),r=e||0;Mt.framebufferTextureLayer(Mt.FRAMEBUFFER,Mt.COLOR_ATTACHMENT0,i.__webglTexture,n||0,r)}E=-1},this.readRenderTargetPixels=function(t,e,n,i,r,s,a){if(!t||!t.isWebGLRenderTarget)return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=et.get(t).__webglFramebuffer;if(t.isWebGLCubeRenderTarget&&void 0!==a&&(o=o[a]),o){Q.bindFramebuffer(Mt.FRAMEBUFFER,o);try{const a=t.texture,o=a.format,l=a.type;if(!$.textureFormatReadable(o))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");if(!$.textureTypeReadable(l))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");e>=0&&e<=t.width-i&&n>=0&&n<=t.height-r&&Mt.readPixels(e,n,i,r,_t.convert(o),_t.convert(l),s)}finally{const t=null!==T?et.get(T).__webglFramebuffer:null;Q.bindFramebuffer(Mt.FRAMEBUFFER,t)}}},this.readRenderTargetPixelsAsync=async function(t,e,n,i,r,s,a){if(!t||!t.isWebGLRenderTarget)throw new Error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=et.get(t).__webglFramebuffer;if(t.isWebGLCubeRenderTarget&&void 0!==a&&(o=o[a]),o){Q.bindFramebuffer(Mt.FRAMEBUFFER,o);try{const a=t.texture,o=a.format,l=a.type;if(!$.textureFormatReadable(o))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.");if(!$.textureTypeReadable(l))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.");if(e>=0&&e<=t.width-i&&n>=0&&n<=t.height-r){const t=Mt.createBuffer();Mt.bindBuffer(Mt.PIXEL_PACK_BUFFER,t),Mt.bufferData(Mt.PIXEL_PACK_BUFFER,s.byteLength,Mt.STREAM_READ),Mt.readPixels(e,n,i,r,_t.convert(o),_t.convert(l),0),Mt.flush();const a=Mt.fenceSync(Mt.SYNC_GPU_COMMANDS_COMPLETE,0);await function(t,e,n){return new Promise((function(i,r){setTimeout((function s(){switch(t.clientWaitSync(e,t.SYNC_FLUSH_COMMANDS_BIT,0)){case t.WAIT_FAILED:r();break;case t.TIMEOUT_EXPIRED:setTimeout(s,n);break;default:i()}}),n)}))}(Mt,a,4);try{Mt.bindBuffer(Mt.PIXEL_PACK_BUFFER,t),Mt.getBufferSubData(Mt.PIXEL_PACK_BUFFER,0,s)}finally{Mt.deleteBuffer(t),Mt.deleteSync(a)}return s}}finally{const t=null!==T?et.get(T).__webglFramebuffer:null;Q.bindFramebuffer(Mt.FRAMEBUFFER,t)}}},this.copyFramebufferToTexture=function(t,e=null,n=0){!0!==t.isTexture&&(ci("WebGLRenderer: copyFramebufferToTexture function signature has changed."),e=arguments[0]||null,t=arguments[1]);const i=Math.pow(2,-n),r=Math.floor(t.image.width*i),s=Math.floor(t.image.height*i),a=null!==e?e.x:0,o=null!==e?e.y:0;nt.setTexture2D(t,0),Mt.copyTexSubImage2D(Mt.TEXTURE_2D,n,0,0,a,o,r,s),Q.unbindTexture()},this.copyTextureToTexture=function(t,e,n=null,i=null,r=0){let s,a,o,l,c,h;!0!==t.isTexture&&(ci("WebGLRenderer: copyTextureToTexture function signature has changed."),i=arguments[0]||null,t=arguments[1],e=arguments[2],r=arguments[3]||0,n=null),null!==n?(s=n.max.x-n.min.x,a=n.max.y-n.min.y,o=n.min.x,l=n.min.y):(s=t.image.width,a=t.image.height,o=0,l=0),null!==i?(c=i.x,h=i.y):(c=0,h=0);const u=_t.convert(e.format),d=_t.convert(e.type);nt.setTexture2D(e,0),Mt.pixelStorei(Mt.UNPACK_FLIP_Y_WEBGL,e.flipY),Mt.pixelStorei(Mt.UNPACK_PREMULTIPLY_ALPHA_WEBGL,e.premultiplyAlpha),Mt.pixelStorei(Mt.UNPACK_ALIGNMENT,e.unpackAlignment);const p=Mt.getParameter(Mt.UNPACK_ROW_LENGTH),m=Mt.getParameter(Mt.UNPACK_IMAGE_HEIGHT),f=Mt.getParameter(Mt.UNPACK_SKIP_PIXELS),g=Mt.getParameter(Mt.UNPACK_SKIP_ROWS),v=Mt.getParameter(Mt.UNPACK_SKIP_IMAGES),_=t.isCompressedTexture?t.mipmaps[r]:t.image;Mt.pixelStorei(Mt.UNPACK_ROW_LENGTH,_.width),Mt.pixelStorei(Mt.UNPACK_IMAGE_HEIGHT,_.height),Mt.pixelStorei(Mt.UNPACK_SKIP_PIXELS,o),Mt.pixelStorei(Mt.UNPACK_SKIP_ROWS,l),t.isDataTexture?Mt.texSubImage2D(Mt.TEXTURE_2D,r,c,h,s,a,u,d,_.data):t.isCompressedTexture?Mt.compressedTexSubImage2D(Mt.TEXTURE_2D,r,c,h,_.width,_.height,u,_.data):Mt.texSubImage2D(Mt.TEXTURE_2D,r,c,h,s,a,u,d,_),Mt.pixelStorei(Mt.UNPACK_ROW_LENGTH,p),Mt.pixelStorei(Mt.UNPACK_IMAGE_HEIGHT,m),Mt.pixelStorei(Mt.UNPACK_SKIP_PIXELS,f),Mt.pixelStorei(Mt.UNPACK_SKIP_ROWS,g),Mt.pixelStorei(Mt.UNPACK_SKIP_IMAGES,v),0===r&&e.generateMipmaps&&Mt.generateMipmap(Mt.TEXTURE_2D),Q.unbindTexture()},this.copyTextureToTexture3D=function(t,e,n=null,i=null,r=0){let s,a,o,l,c,h,u,d,p;!0!==t.isTexture&&(ci("WebGLRenderer: copyTextureToTexture3D function signature has changed."),n=arguments[0]||null,i=arguments[1]||null,t=arguments[2],e=arguments[3],r=arguments[4]||0);const m=t.isCompressedTexture?t.mipmaps[r]:t.image;null!==n?(s=n.max.x-n.min.x,a=n.max.y-n.min.y,o=n.max.z-n.min.z,l=n.min.x,c=n.min.y,h=n.min.z):(s=m.width,a=m.height,o=m.depth,l=0,c=0,h=0),null!==i?(u=i.x,d=i.y,p=i.z):(u=0,d=0,p=0);const f=_t.convert(e.format),g=_t.convert(e.type);let v;if(e.isData3DTexture)nt.setTexture3D(e,0),v=Mt.TEXTURE_3D;else{if(!e.isDataArrayTexture&&!e.isCompressedArrayTexture)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");nt.setTexture2DArray(e,0),v=Mt.TEXTURE_2D_ARRAY}Mt.pixelStorei(Mt.UNPACK_FLIP_Y_WEBGL,e.flipY),Mt.pixelStorei(Mt.UNPACK_PREMULTIPLY_ALPHA_WEBGL,e.premultiplyAlpha),Mt.pixelStorei(Mt.UNPACK_ALIGNMENT,e.unpackAlignment);const _=Mt.getParameter(Mt.UNPACK_ROW_LENGTH),x=Mt.getParameter(Mt.UNPACK_IMAGE_HEIGHT),y=Mt.getParameter(Mt.UNPACK_SKIP_PIXELS),M=Mt.getParameter(Mt.UNPACK_SKIP_ROWS),S=Mt.getParameter(Mt.UNPACK_SKIP_IMAGES);Mt.pixelStorei(Mt.UNPACK_ROW_LENGTH,m.width),Mt.pixelStorei(Mt.UNPACK_IMAGE_HEIGHT,m.height),Mt.pixelStorei(Mt.UNPACK_SKIP_PIXELS,l),Mt.pixelStorei(Mt.UNPACK_SKIP_ROWS,c),Mt.pixelStorei(Mt.UNPACK_SKIP_IMAGES,h),t.isDataTexture||t.isData3DTexture?Mt.texSubImage3D(v,r,u,d,p,s,a,o,f,g,m.data):e.isCompressedArrayTexture?Mt.compressedTexSubImage3D(v,r,u,d,p,s,a,o,f,m.data):Mt.texSubImage3D(v,r,u,d,p,s,a,o,f,g,m),Mt.pixelStorei(Mt.UNPACK_ROW_LENGTH,_),Mt.pixelStorei(Mt.UNPACK_IMAGE_HEIGHT,x),Mt.pixelStorei(Mt.UNPACK_SKIP_PIXELS,y),Mt.pixelStorei(Mt.UNPACK_SKIP_ROWS,M),Mt.pixelStorei(Mt.UNPACK_SKIP_IMAGES,S),0===r&&e.generateMipmaps&&Mt.generateMipmap(v),Q.unbindTexture()},this.initRenderTarget=function(t){void 0===et.get(t).__webglFramebuffer&&nt.setupRenderTarget(t)},this.initTexture=function(t){t.isCubeTexture?nt.setTextureCube(t,0):t.isData3DTexture?nt.setTexture3D(t,0):t.isDataArrayTexture||t.isCompressedArrayTexture?nt.setTexture2DArray(t,0):nt.setTexture2D(t,0),Q.unbindTexture()},this.resetState=function(){b=0,w=0,T=null,Q.reset(),xt.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}get coordinateSystem(){return kn}get outputColorSpace(){return this._outputColorSpace}set outputColorSpace(t){this._outputColorSpace=t;const e=this.getContext();e.drawingBufferColorSpace=t===$e?"display-p3":"srgb",e.unpackColorSpace=mi.workingColorSpace===Qe?"display-p3":"srgb"}}class oc{constructor(t,e=25e-5){this.isFogExp2=!0,this.name="",this.color=new Kr(t),this.density=e}clone(){return new oc(this.color,this.density)}toJSON(){return{type:"FogExp2",name:this.name,color:this.color.getHex(),density:this.density}}}class lc{constructor(t,e=1,n=1e3){this.isFog=!0,this.name="",this.color=new Kr(t),this.near=e,this.far=n}clone(){return new lc(this.color,this.near,this.far)}toJSON(){return{type:"Fog",name:this.name,color:this.color.getHex(),near:this.near,far:this.far}}}class cc extends Dr{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.backgroundRotation=new _r,this.environmentIntensity=1,this.environmentRotation=new _r,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,this.backgroundRotation.copy(t.backgroundRotation),this.environmentIntensity=t.environmentIntensity,this.environmentRotation.copy(t.environmentRotation),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.object.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(e.object.backgroundIntensity=this.backgroundIntensity),e.object.backgroundRotation=this.backgroundRotation.toArray(),1!==this.environmentIntensity&&(e.object.environmentIntensity=this.environmentIntensity),e.object.environmentRotation=this.environmentRotation.toArray(),e}}class hc{constructor(t,e){this.isInterleavedBuffer=!0,this.array=t,this.stride=e,this.count=void 0!==t?t.length/e:0,this.usage=Cn,this._updateRange={offset:0,count:-1},this.updateRanges=[],this.version=0,this.uuid=qn()}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}get updateRange(){return ci("THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead."),this._updateRange}setUsage(t){return this.usage=t,this}addUpdateRange(t,e){this.updateRanges.push({start:t,count:e})}clearUpdateRanges(){this.updateRanges.length=0}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,n){t*=this.stride,n*=e.stride;for(let i=0,r=this.stride;it.far||e.push({distance:o,point:fc.clone(),uv:jr.getInterpolation(fc,Mc,Sc,bc,wc,Tc,Ec,new ti),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 Rc(t,e,n,i,r,s){_c.subVectors(t,n).addScalar(.5).multiply(i),void 0!==r?(xc.x=s*_c.x-r*_c.y,xc.y=r*_c.x+s*_c.y):xc.copy(_c),t.copy(e),t.x+=xc.x,t.y+=xc.y,t.applyMatrix4(yc)}const Cc=new Li,Pc=new Li;class Ic extends Dr{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,n=e.length;t0){let n,i;for(n=1,i=e.length;n0){Cc.setFromMatrixPosition(this.matrixWorld);const n=t.ray.origin.distanceTo(Cc);this.getObjectForDistance(n).raycast(t,e)}}update(t){const e=this.levels;if(e.length>1){Cc.setFromMatrixPosition(t.matrixWorld),Pc.setFromMatrixPosition(this.matrixWorld);const n=Cc.distanceTo(Pc)/t.zoom;let i,r;for(e[0].object.visible=!0,i=1,r=e.length;i=t))break;e[i-1].object.visible=!1,e[i].object.visible=!0}for(this._currentLevel=i-1;i=i.length&&i.push({start:-1,count:-1,z:-1,index:-1});const s=i[this.index];r.push(s),this.index++,s.start=t.start,s.count=t.count,s.z=e,s.index=n}reset(){this.list.length=0,this.index=0}}const sh=new lr,ah=new lr,oh=new lr,lh=new Kr(1,1,1),ch=new lr,hh=new pa,uh=new Di,dh=new Qi,ph=new Li,mh=new Li,fh=new Li,gh=new rh,vh=new Ws,_h=[];function xh(t,e,n=0){const i=e.itemSize;if(t.isInterleavedBufferAttribute||t.array.constructor!==e.array.constructor){const r=t.count;for(let s=0;s65535?new Uint32Array(i):new Uint16Array(i);e.setIndex(new cs(t,1))}this._geometryInitialized=!0}}_validateGeometry(t){const e=this.geometry;if(Boolean(t.getIndex())!==Boolean(e.getIndex()))throw new Error('BatchedMesh: All geometries must consistently have "index".');for(const n in e.attributes){if(!t.hasAttribute(n))throw new Error(`BatchedMesh: Added geometry missing "${n}". All geometries must have consistent attributes.`);const i=t.getAttribute(n),r=e.getAttribute(n);if(i.itemSize!==r.itemSize||i.normalized!==r.normalized)throw new Error("BatchedMesh: All attributes must have a consistent itemSize and normalized value.")}}setCustomSort(t){return this.customSort=t,this}computeBoundingBox(){null===this.boundingBox&&(this.boundingBox=new Di);const t=this.boundingBox,e=this._drawInfo;t.makeEmpty();for(let n=0,i=e.length;n=this._maxInstanceCount)throw new Error("BatchedMesh: Maximum item count reached.");this._drawInfo.push({visible:!0,active:!0,geometryIndex:t});const e=this._drawInfo.length-1,n=this._matricesTexture,i=n.image.data;oh.toArray(i,16*e),n.needsUpdate=!0;const r=this._colorsTexture;return r&&(lh.toArray(r.image.data,4*e),r.needsUpdate=!0),e}addGeometry(t,e=-1,n=-1){if(this._initializeGeometry(t),this._validateGeometry(t),this._drawInfo.length>=this._maxInstanceCount)throw new Error("BatchedMesh: Maximum item count reached.");const i={vertexStart:-1,vertexCount:-1,indexStart:-1,indexCount:-1};let r=null;const s=this._reservedRanges,a=this._drawRanges,o=this._bounds;0!==this._geometryCount&&(r=s[s.length-1]),i.vertexCount=-1===e?t.getAttribute("position").count:e,i.vertexStart=null===r?0:r.vertexStart+r.vertexCount;const l=t.getIndex(),c=null!==l;if(c&&(i.indexCount=-1===n?l.count:n,i.indexStart=null===r?0:r.indexStart+r.indexCount),-1!==i.indexStart&&i.indexStart+i.indexCount>this._maxIndexCount||i.vertexStart+i.vertexCount>this._maxVertexCount)throw new Error("BatchedMesh: Reserved space request exceeds the maximum buffer size.");const h=this._geometryCount;return this._geometryCount++,s.push(i),a.push({start:c?i.indexStart:i.vertexStart,count:-1}),o.push({boxInitialized:!1,box:new Di,sphereInitialized:!1,sphere:new Qi}),this.setGeometryAt(h,t),h}setGeometryAt(t,e){if(t>=this._geometryCount)throw new Error("BatchedMesh: Maximum geometry count reached.");this._validateGeometry(e);const n=this.geometry,i=null!==n.getIndex(),r=n.getIndex(),s=e.getIndex(),a=this._reservedRanges[t];if(i&&s.count>a.indexCount||e.attributes.position.count>a.vertexCount)throw new Error("BatchedMesh: Reserved space not large enough for provided geometry.");const o=a.vertexStart,l=a.vertexCount;for(const t in n.attributes){const i=e.getAttribute(t),r=n.getAttribute(t);xh(i,r,o);const s=i.itemSize;for(let t=i.count,e=l;t=this._geometryCount)return null;const n=this._bounds[t],i=n.box,r=this.geometry;if(!1===n.boxInitialized){i.makeEmpty();const e=r.index,s=r.attributes.position,a=this._drawRanges[t];for(let t=a.start,n=a.start+a.count;t=this._geometryCount)return null;const n=this._bounds[t],i=n.sphere,r=this.geometry;if(!1===n.sphereInitialized){i.makeEmpty(),this.getBoundingBoxAt(t,uh),uh.getCenter(i.center);const e=r.index,s=r.attributes.position,a=this._drawRanges[t];let o=0;for(let t=a.start,n=a.start+a.count;t=n.length||!1===n[t].active||(e.toArray(r,16*t),i.needsUpdate=!0),this}getMatrixAt(t,e){const n=this._drawInfo,i=this._matricesTexture.image.data;return t>=n.length||!1===n[t].active?null:e.fromArray(i,16*t)}setColorAt(t,e){null===this._colorsTexture&&this._initColorsTexture();const n=this._colorsTexture,i=this._colorsTexture.image.data,r=this._drawInfo;return t>=r.length||!1===r[t].active||(e.toArray(i,4*t),n.needsUpdate=!0),this}getColorAt(t,e){const n=this._colorsTexture.image.data,i=this._drawInfo;return t>=i.length||!1===i[t].active?null:e.fromArray(n,4*t)}setVisibleAt(t,e){const n=this._drawInfo;return t>=n.length||!1===n[t].active||n[t].visible===e||(n[t].visible=e,this._visibilityChanged=!0),this}getVisibleAt(t){const e=this._drawInfo;return!(t>=e.length||!1===e[t].active)&&e[t].visible}raycast(t,e){const n=this._drawInfo,i=this._drawRanges,r=this.matrixWorld,s=this.geometry;vh.material=this.material,vh.geometry.index=s.index,vh.geometry.attributes=s.attributes,null===vh.geometry.boundingBox&&(vh.geometry.boundingBox=new Di),null===vh.geometry.boundingSphere&&(vh.geometry.boundingSphere=new Qi);for(let s=0,a=n.length;s({...t}))),this._reservedRanges=t._reservedRanges.map((t=>({...t}))),this._drawInfo=t._drawInfo.map((t=>({...t}))),this._bounds=t._bounds.map((t=>({boxInitialized:t.boxInitialized,box:t.box.clone(),sphereInitialized:t.sphereInitialized,sphere:t.sphere.clone()}))),this._maxInstanceCount=t._maxInstanceCount,this._maxVertexCount=t._maxVertexCount,this._maxIndexCount=t._maxIndexCount,this._geometryInitialized=t._geometryInitialized,this._geometryCount=t._geometryCount,this._multiDrawCounts=t._multiDrawCounts.slice(),this._multiDrawStarts=t._multiDrawStarts.slice(),this._matricesTexture=t._matricesTexture.clone(),this._matricesTexture.image.data=this._matricesTexture.image.data.slice(),null!==this._colorsTexture&&(this._colorsTexture=t._colorsTexture.clone(),this._colorsTexture.image.data=this._colorsTexture.image.data.slice()),this}dispose(){return this.geometry.dispose(),this._matricesTexture.dispose(),this._matricesTexture=null,this._indirectTexture.dispose(),this._indirectTexture=null,null!==this._colorsTexture&&(this._colorsTexture.dispose(),this._colorsTexture=null),this}onBeforeRender(t,e,n,i,r){if(!this._visibilityChanged&&!this.perObjectFrustumCulled&&!this.sortObjects)return;const s=i.getIndex(),a=null===s?1:s.array.BYTES_PER_ELEMENT,o=this._drawInfo,l=this._multiDrawStarts,c=this._multiDrawCounts,h=this._drawRanges,u=this.perObjectFrustumCulled,d=this._indirectTexture,p=d.image.data;u&&(ch.multiplyMatrices(n.projectionMatrix,n.matrixWorldInverse).multiply(this.matrixWorld),hh.setFromProjectionMatrix(ch,t.coordinateSystem));let m=0;if(this.sortObjects){ah.copy(this.matrixWorld).invert(),ph.setFromMatrixPosition(n.matrixWorld).applyMatrix4(ah),mh.set(0,0,-1).transformDirection(n.matrixWorld).transformDirection(ah);for(let t=0,e=o.length;t0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;ti)return;Ah.applyMatrix4(t.matrixWorld);const o=e.ray.origin.distanceTo(Ah);return oe.far?void 0:{distance:o,point:Rh.clone().applyMatrix4(t.matrixWorld),index:r,face:null,faceIndex:null,object:t}}const Ih=new Li,Lh=new Li;class Uh extends Ch{constructor(t,e){super(t,e),this.isLineSegments=!0,this.type="LineSegments"}computeLineDistances(){const t=this.geometry;if(null===t.index){const e=t.attributes.position,n=[];for(let t=0,i=e.count;t0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;tr.far)return;s.push({distance:l,distanceToRay:Math.sqrt(o),point:n,index:e,face:null,object:a})}}class Hh extends bi{constructor(t,e,n,i,r,s,a,o,l){super(t,e,n,i,r,s,a,o,l),this.isVideoTexture=!0,this.minFilter=void 0!==s?s:Mt,this.magFilter=void 0!==r?r:Mt,this.generateMipmaps=!1;const c=this;"requestVideoFrameCallback"in t&&t.requestVideoFrameCallback((function e(){c.needsUpdate=!0,t.requestVideoFrameCallback(e)}))}clone(){return new this.constructor(this.image).copy(this)}update(){const t=this.image;!1==="requestVideoFrameCallback"in t&&t.readyState>=t.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}class Gh extends bi{constructor(t,e){super({width:t,height:e}),this.isFramebufferTexture=!0,this.magFilter=gt,this.minFilter=gt,this.generateMipmaps=!1,this.needsUpdate=!0}}class Wh extends bi{constructor(t,e,n,i,r,s,a,o,l,c,h,u){super(null,s,a,o,l,c,i,r,h,u),this.isCompressedTexture=!0,this.image={width:e,height:n},this.mipmaps=t,this.flipY=!1,this.generateMipmaps=!1}}class Xh extends Wh{constructor(t,e,n,i,r,s){super(t,e,n,r,s),this.isCompressedArrayTexture=!0,this.image.depth=i,this.wrapR=mt,this.layerUpdates=new Set}addLayerUpdate(t){this.layerUpdates.add(t)}clearLayerUpdates(){this.layerUpdates.clear()}}class jh extends Wh{constructor(t,e,n){super(void 0,t[0].width,t[0].height,e,n,lt),this.isCompressedCubeTexture=!0,this.isCubeTexture=!0,this.image=t}}class qh extends bi{constructor(t,e,n,i,r,s,a,o,l){super(t,e,n,i,r,s,a,o,l),this.isCanvasTexture=!0,this.needsUpdate=!0}}class Yh{constructor(){this.type="Curve",this.arcLengthDivisions=200}getPoint(){return console.warn("THREE.Curve: .getPoint() not implemented."),null}getPointAt(t,e){const n=this.getUtoTmapping(t);return this.getPoint(n,e)}getPoints(t=5){const e=[];for(let n=0;n<=t;n++)e.push(this.getPoint(n/t));return e}getSpacedPoints(t=5){const e=[];for(let n=0;n<=t;n++)e.push(this.getPointAt(n/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 n,i=this.getPoint(0),r=0;e.push(0);for(let s=1;s<=t;s++)n=this.getPoint(s/t),r+=n.distanceTo(i),e.push(r),i=n;return this.cacheArcLengths=e,e}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(t,e){const n=this.getLengths();let i=0;const r=n.length;let s;s=e||t*n[r-1];let a,o=0,l=r-1;for(;o<=l;)if(i=Math.floor(o+(l-o)/2),a=n[i]-s,a<0)o=i+1;else{if(!(a>0)){l=i;break}l=i-1}if(i=l,n[i]===s)return i/(r-1);const c=n[i];return(i+(s-c)/(n[i+1]-c))/(r-1)}getTangent(t,e){const n=1e-4;let i=t-n,r=t+n;i<0&&(i=0),r>1&&(r=1);const s=this.getPoint(i),a=this.getPoint(r),o=e||(s.isVector2?new ti:new Li);return o.copy(a).sub(s).normalize(),o}getTangentAt(t,e){const n=this.getUtoTmapping(t);return this.getTangent(n,e)}computeFrenetFrames(t,e){const n=new Li,i=[],r=[],s=[],a=new Li,o=new lr;for(let e=0;e<=t;e++){const n=e/t;i[e]=this.getTangentAt(n,new Li)}r[0]=new Li,s[0]=new Li;let l=Number.MAX_VALUE;const c=Math.abs(i[0].x),h=Math.abs(i[0].y),u=Math.abs(i[0].z);c<=l&&(l=c,n.set(1,0,0)),h<=l&&(l=h,n.set(0,1,0)),u<=l&&n.set(0,0,1),a.crossVectors(i[0],n).normalize(),r[0].crossVectors(i[0],a),s[0].crossVectors(i[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(i[e-1],i[e]),a.length()>Number.EPSILON){a.normalize();const t=Math.acos(Yn(i[e-1].dot(i[e]),-1,1));r[e].applyMatrix4(o.makeRotationAxis(a,t))}s[e].crossVectors(i[e],r[e])}if(!0===e){let e=Math.acos(Yn(r[0].dot(r[t]),-1,1));e/=t,i[0].dot(a.crossVectors(r[0],r[t]))>0&&(e=-e);for(let n=1;n<=t;n++)r[n].applyMatrix4(o.makeRotationAxis(i[n],e*n)),s[n].crossVectors(i[n],r[n])}return{tangents:i,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.6,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t}fromJSON(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}class Zh extends Yh{constructor(t=0,e=0,n=1,i=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=n,this.yRadius=i,this.aStartAngle=r,this.aEndAngle=s,this.aClockwise=a,this.aRotation=o}getPoint(t,e=new ti){const n=e,i=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const s=Math.abs(r)i;)r-=i;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=i[(l-1)%r]:($h.subVectors(i[0],i[1]).add(i[0]),a=$h);const h=i[l%r],u=i[(l+1)%r];if(this.closed||l+2i.length-2?i.length-1:s+1],h=i[s>i.length-3?i.length-1:s+2];return n.set(iu(a,o.x,l.x,c.x,h.x),iu(a,o.y,l.y,c.y,h.y)),n}copy(t){super.copy(t),this.points=[];for(let e=0,n=t.points.length;e=n){const t=i[r]-n,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 n=0,i=this.curves.length;n1&&!e[e.length-1].equals(e[0])&&e.push(e[0]),e}copy(t){super.copy(t),this.curves=[];for(let e=0,n=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 gu extends Es{constructor(t=[new ti(0,-.5),new ti(.5,0),new ti(0,.5)],e=12,n=0,i=2*Math.PI){super(),this.type="LatheGeometry",this.parameters={points:t,segments:e,phiStart:n,phiLength:i},e=Math.floor(e),i=Yn(i,0,2*Math.PI);const r=[],s=[],a=[],o=[],l=[],c=1/e,h=new Li,u=new ti,d=new Li,p=new Li,m=new Li;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=n+r*c*i,p=Math.sin(d),m=Math.cos(d);for(let n=0;n<=t.length-1;n++){h.x=t[n].x*p,h.y=t[n].y,h.z=t[n].x*m,s.push(h.x,h.y,h.z),u.x=r/e,u.y=n/(t.length-1),a.push(u.x,u.y);const i=o[3*n+0]*p,c=o[3*n+1],d=o[3*n+0]*m;l.push(i,c,d)}}for(let n=0;n0&&v(!0),e>0&&v(!1)),this.setIndex(c),this.setAttribute("position",new _s(h,3)),this.setAttribute("normal",new _s(u,3)),this.setAttribute("uv",new _s(d,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new xu(t.radiusTop,t.radiusBottom,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class yu extends xu{constructor(t=1,e=1,n=32,i=1,r=!1,s=0,a=2*Math.PI){super(0,t,e,n,i,r,s,a),this.type="ConeGeometry",this.parameters={radius:t,height:e,radialSegments:n,heightSegments:i,openEnded:r,thetaStart:s,thetaLength:a}}static fromJSON(t){return new yu(t.radius,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class Mu extends Es{constructor(t=[],e=[],n=1,i=0){super(),this.type="PolyhedronGeometry",this.parameters={vertices:t,indices:e,radius:n,detail:i};const r=[],s=[];function a(t,e,n,i){const r=i+1,s=[];for(let i=0;i<=r;i++){s[i]=[];const a=t.clone().lerp(n,i/r),o=e.clone().lerp(n,i/r),l=r-i;for(let t=0;t<=l;t++)s[i][t]=0===t&&i===r?a:a.clone().lerp(o,t/l)}for(let t=0;t.9&&a<.1&&(e<.2&&(s[t+0]+=1),n<.2&&(s[t+2]+=1),i<.2&&(s[t+4]+=1))}}()}(),this.setAttribute("position",new _s(r,3)),this.setAttribute("normal",new _s(r.slice(),3)),this.setAttribute("uv",new _s(s,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new Mu(t.vertices,t.indices,t.radius,t.details)}}class Su extends Mu{constructor(t=1,e=0){const n=(1+Math.sqrt(5))/2,i=1/n;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,-i,-n,0,-i,n,0,i,-n,0,i,n,-i,-n,0,-i,n,0,i,-n,0,i,n,0,-n,0,-i,n,0,-i,-n,0,i,n,0,i],[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 Su(t.radius,t.detail)}}const bu=new Li,wu=new Li,Tu=new Li,Eu=new jr;class Au extends Es{constructor(t=null,e=1){if(super(),this.type="EdgesGeometry",this.parameters={geometry:t,thresholdAngle:e},null!==t){const n=4,i=Math.pow(10,n),r=Math.cos(Xn*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*n){o=c=t[0],l=h=t[1];for(let e=n;ec&&(c=u),d>h&&(h=d);p=Math.max(c-o,h-l),p=0!==p?32767/p:0}return Lu(s,a,n,o,l,p,0),a};function Pu(t,e,n,i,r){let s,a;if(r===function(t,e,n,i){let r=0;for(let s=e,a=n-i;s0)for(s=e;s=e;s-=i)a=Ku(s,t[s],t[s+1],a);return a&&Xu(a,a.next)&&($u(a),a=a.next),a}function Iu(t,e){if(!t)return t;e||(e=t);let n,i=t;do{if(n=!1,i.steiner||!Xu(i,i.next)&&0!==Wu(i.prev,i,i.next))i=i.next;else{if($u(i),i=e=i.prev,i===i.next)break;n=!0}}while(n||i!==e);return e}function Lu(t,e,n,i,r,s,a){if(!t)return;!a&&s&&function(t,e,n,i){let r=t;do{0===r.z&&(r.z=ku(r.x,r.y,e,n,i)),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,n,i,r,s,a,o,l,c=1;do{for(n=t,t=null,s=null,a=0;n;){for(a++,i=n,o=0,e=0;e0||l>0&&i;)0!==o&&(0===l||!i||n.z<=i.z)?(r=n,n=n.nextZ,o--):(r=i,i=i.nextZ,l--),s?s.nextZ=r:t=r,r.prevZ=s,s=r;n=i}s.nextZ=null,c*=2}while(a>1)}(r)}(t,i,r,s);let o,l,c=t;for(;t.prev!==t.next;)if(o=t.prev,l=t.next,s?Nu(t,i,r,s):Uu(t))e.push(o.i/n|0),e.push(t.i/n|0),e.push(l.i/n|0),$u(t),t=l.next,c=l.next;else if((t=l)===c){a?1===a?Lu(t=Du(Iu(t),e,n),e,n,i,r,s,2):2===a&&Ou(t,e,n,i,r,s):Lu(Iu(t),e,n,i,r,s,1);break}}function Uu(t){const e=t.prev,n=t,i=t.next;if(Wu(e,n,i)>=0)return!1;const r=e.x,s=n.x,a=i.x,o=e.y,l=n.y,c=i.y,h=rs?r>a?r:a:s>a?s:a,p=o>l?o>c?o:c:l>c?l:c;let m=i.next;for(;m!==e;){if(m.x>=h&&m.x<=d&&m.y>=u&&m.y<=p&&Hu(r,o,s,l,a,c,m.x,m.y)&&Wu(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function Nu(t,e,n,i){const r=t.prev,s=t,a=t.next;if(Wu(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=ku(p,m,e,n,i),_=ku(f,g,e,n,i);let x=t.prevZ,y=t.nextZ;for(;x&&x.z>=v&&y&&y.z<=_;){if(x.x>=p&&x.x<=f&&x.y>=m&&x.y<=g&&x!==r&&x!==a&&Hu(o,h,l,u,c,d,x.x,x.y)&&Wu(x.prev,x,x.next)>=0)return!1;if(x=x.prevZ,y.x>=p&&y.x<=f&&y.y>=m&&y.y<=g&&y!==r&&y!==a&&Hu(o,h,l,u,c,d,y.x,y.y)&&Wu(y.prev,y,y.next)>=0)return!1;y=y.nextZ}for(;x&&x.z>=v;){if(x.x>=p&&x.x<=f&&x.y>=m&&x.y<=g&&x!==r&&x!==a&&Hu(o,h,l,u,c,d,x.x,x.y)&&Wu(x.prev,x,x.next)>=0)return!1;x=x.prevZ}for(;y&&y.z<=_;){if(y.x>=p&&y.x<=f&&y.y>=m&&y.y<=g&&y!==r&&y!==a&&Hu(o,h,l,u,c,d,y.x,y.y)&&Wu(y.prev,y,y.next)>=0)return!1;y=y.nextZ}return!0}function Du(t,e,n){let i=t;do{const r=i.prev,s=i.next.next;!Xu(r,s)&&ju(r,i,i.next,s)&&Zu(r,s)&&Zu(s,r)&&(e.push(r.i/n|0),e.push(i.i/n|0),e.push(s.i/n|0),$u(i),$u(i.next),i=t=s),i=i.next}while(i!==t);return Iu(i)}function Ou(t,e,n,i,r,s){let a=t;do{let t=a.next.next;for(;t!==a.prev;){if(a.i!==t.i&&Gu(a,t)){let o=Ju(a,t);return a=Iu(a,a.next),o=Iu(o,o.next),Lu(a,e,n,i,r,s,0),void Lu(o,e,n,i,r,s,0)}t=t.next}a=a.next}while(a!==t)}function Fu(t,e){return t.x-e.x}function Bu(t,e){const n=function(t,e){let n,i=e,r=-1/0;const s=t.x,a=t.y;do{if(a<=i.y&&a>=i.next.y&&i.next.y!==i.y){const t=i.x+(a-i.y)*(i.next.x-i.x)/(i.next.y-i.y);if(t<=s&&t>r&&(r=t,n=i.x=i.x&&i.x>=l&&s!==i.x&&Hu(an.x||i.x===n.x&&zu(n,i)))&&(n=i,u=h)),i=i.next}while(i!==o);return n}(t,e);if(!n)return e;const i=Ju(n,t);return Iu(i,i.next),Iu(n,n.next)}function zu(t,e){return Wu(t.prev,t,e.prev)<0&&Wu(e.next,t,t.next)<0}function ku(t,e,n,i,r){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=(t-n)*r|0)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=(e-i)*r|0)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function Vu(t){let e=t,n=t;do{(e.x=(t-a)*(s-o)&&(t-a)*(i-o)>=(n-a)*(e-o)&&(n-a)*(s-o)>=(r-a)*(i-o)}function Gu(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){let n=t;do{if(n.i!==t.i&&n.next.i!==t.i&&n.i!==e.i&&n.next.i!==e.i&&ju(n,n.next,t,e))return!0;n=n.next}while(n!==t);return!1}(t,e)&&(Zu(t,e)&&Zu(e,t)&&function(t,e){let n=t,i=!1;const r=(t.x+e.x)/2,s=(t.y+e.y)/2;do{n.y>s!=n.next.y>s&&n.next.y!==n.y&&r<(n.next.x-n.x)*(s-n.y)/(n.next.y-n.y)+n.x&&(i=!i),n=n.next}while(n!==t);return i}(t,e)&&(Wu(t.prev,t,e.prev)||Wu(t,e.prev,e))||Xu(t,e)&&Wu(t.prev,t,t.next)>0&&Wu(e.prev,e,e.next)>0)}function Wu(t,e,n){return(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y)}function Xu(t,e){return t.x===e.x&&t.y===e.y}function ju(t,e,n,i){const r=Yu(Wu(t,e,n)),s=Yu(Wu(t,e,i)),a=Yu(Wu(n,i,t)),o=Yu(Wu(n,i,e));return r!==s&&a!==o||(!(0!==r||!qu(t,n,e))||(!(0!==s||!qu(t,i,e))||(!(0!==a||!qu(n,t,i))||!(0!==o||!qu(n,e,i)))))}function qu(t,e,n){return e.x<=Math.max(t.x,n.x)&&e.x>=Math.min(t.x,n.x)&&e.y<=Math.max(t.y,n.y)&&e.y>=Math.min(t.y,n.y)}function Yu(t){return t>0?1:t<0?-1:0}function Zu(t,e){return Wu(t.prev,t,t.next)<0?Wu(t,e,t.next)>=0&&Wu(t,t.prev,e)>=0:Wu(t,e,t.prev)<0||Wu(t,t.next,e)<0}function Ju(t,e){const n=new Qu(t.i,t.x,t.y),i=new Qu(e.i,e.x,e.y),r=t.next,s=e.prev;return t.next=e,e.prev=t,n.next=r,r.prev=n,i.next=n,n.prev=i,s.next=i,i.prev=s,i}function Ku(t,e,n,i){const r=new Qu(t,e,n);return i?(r.next=i.next,r.prev=i,i.next.prev=r,i.next=r):(r.prev=r,r.next=r),r}function $u(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 Qu(t,e,n){this.i=t,this.x=e,this.y=n,this.prev=null,this.next=null,this.z=0,this.prevZ=null,this.nextZ=null,this.steiner=!1}class td{static area(t){const e=t.length;let n=0;for(let i=e-1,r=0;r2&&t[e-1].equals(t[0])&&t.pop()}function nd(t,e){for(let n=0;nNumber.EPSILON){const u=Math.sqrt(h),d=Math.sqrt(l*l+c*c),p=e.x-o/u,m=e.y+a/u,f=((n.x-c/d-p)*c-(n.y+l/d-m)*l)/(a*c-o*l);i=p+a*f-t.x,r=m+o*f-t.y;const g=i*i+r*r;if(g<=2)return new ti(i,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?(i=-o,r=a,s=Math.sqrt(h)):(i=a,r=o,s=Math.sqrt(h/2))}return new ti(i/s,r/s)}const I=[];for(let t=0,e=E.length,n=e-1,i=t+1;t=0;t--){const e=t/p,n=h*Math.cos(e*Math.PI/2),i=u*Math.sin(e*Math.PI/2)+d;for(let t=0,e=E.length;t=0;){const i=n;let r=n-1;r<0&&(r=t.length-1);for(let t=0,n=o+2*p;t0)&&d.push(e,r,l),(t!==n-1||o0!=t>0&&this.version++,this._anisotropy=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 dispersion(){return this._dispersion}set dispersion(t){this._dispersion>0!=t>0&&this.version++,this._dispersion=t}get sheen(){return this._sheen}set sheen(t){this._sheen>0!=t>0&&this.version++,this._sheen=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.anisotropy=t.anisotropy,this.anisotropyRotation=t.anisotropyRotation,this.anisotropyMap=t.anisotropyMap,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.dispersion=t.dispersion,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 Md extends ts{constructor(t){super(),this.isMeshPhongMaterial=!0,this.type="MeshPhongMaterial",this.color=new Kr(16777215),this.specular=new Kr(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Kr(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new ti(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new _r,this.combine=Y,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.envMapRotation.copy(t.envMapRotation),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 Sd extends ts{constructor(t){super(),this.isMeshToonMaterial=!0,this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new Kr(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Kr(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new ti(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 bd extends ts{constructor(t){super(),this.isMeshNormalMaterial=!0,this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new ti(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 wd extends ts{constructor(t){super(),this.isMeshLambertMaterial=!0,this.type="MeshLambertMaterial",this.color=new Kr(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Kr(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new ti(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new _r,this.combine=Y,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.envMapRotation.copy(t.envMapRotation),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 Td extends ts{constructor(t){super(),this.isMeshMatcapMaterial=!0,this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new Kr(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new ti(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 Ed extends Mh{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 Ad(t,e,n){return!t||!n&&t.constructor===e?t:"number"==typeof e.BYTES_PER_ELEMENT?new e(t):Array.prototype.slice.call(t)}function Rd(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)}function Cd(t){const e=t.length,n=new Array(e);for(let t=0;t!==e;++t)n[t]=t;return n.sort((function(e,n){return t[e]-t[n]})),n}function Pd(t,e,n){const i=t.length,r=new t.constructor(i);for(let s=0,a=0;a!==i;++s){const i=n[s]*e;for(let n=0;n!==e;++n)r[a++]=t[i+n]}return r}function Id(t,e,n,i){let r=1,s=t[0];for(;void 0!==s&&void 0===s[i];)s=t[r++];if(void 0===s)return;let a=s[i];if(void 0!==a)if(Array.isArray(a))do{a=s[i],void 0!==a&&(e.push(s.time),n.push.apply(n,a)),s=t[r++]}while(void 0!==s);else if(void 0!==a.toArray)do{a=s[i],void 0!==a&&(e.push(s.time),a.toArray(n,n.length)),s=t[r++]}while(void 0!==s);else do{a=s[i],void 0!==a&&(e.push(s.time),n.push(a)),s=t[r++]}while(void 0!==s)}const Ld={convertArray:Ad,isTypedArray:Rd,getKeyframeOrder:Cd,sortedArray:Pd,flattenJSON:Id,subclip:function(t,e,n,i,r=30){const s=t.clone();s.name=e;const a=[];for(let t=0;t=i)){l.push(e.times[t]);for(let n=0;ns.tracks[t].times[0]&&(o=s.tracks[t].times[0]);for(let t=0;t=i.times[u]){const t=u*l+o,e=t+l-o;d=i.values.slice(t,e)}else{const t=i.createInterpolant(),e=o,n=l-o;t.evaluate(s),d=t.resultBuffer.slice(e,n)}if("quaternion"===r){(new Ii).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=n,n=0}}for(;n>>1;te;)--s;if(++s,0!==r||s!==i){r>=s&&(s=Math.max(s,1),r=s-1);const t=this.getValueSize();this.times=n.slice(r,s),this.values=this.values.slice(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 n=this.times,i=this.values,r=n.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),t=!1);let s=null;for(let e=0;e!==r;e++){const i=n[e];if("number"==typeof i&&isNaN(i)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,e,i),t=!1;break}if(null!==s&&s>i){console.error("THREE.KeyframeTrack: Out of order keys.",this,e,i,s),t=!1;break}s=i}if(void 0!==i&&Rd(i))for(let e=0,n=i.length;e!==n;++e){const n=i[e];if(isNaN(n)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,e,n),t=!1;break}}return t}optimize(){const t=this.times.slice(),e=this.values.slice(),n=this.getValueSize(),i=this.getInterpolation()===Ne,r=t.length-1;let s=1;for(let a=1;a0){t[s]=t[r];for(let t=r*n,i=s*n,a=0;a!==n;++a)e[i+a]=e[t+a];++s}return s!==t.length?(this.times=t.slice(0,s),this.values=e.slice(0,s*n)):(this.times=t,this.values=e),this}clone(){const t=this.times.slice(),e=this.values.slice(),n=new(0,this.constructor)(this.name,t,e);return n.createInterpolant=this.createInterpolant,n}}Fd.prototype.TimeBufferType=Float32Array,Fd.prototype.ValueBufferType=Float32Array,Fd.prototype.DefaultInterpolation=Ue;class Bd extends Fd{constructor(t,e,n){super(t,e,n)}}Bd.prototype.ValueTypeName="bool",Bd.prototype.ValueBufferType=Array,Bd.prototype.DefaultInterpolation=Le,Bd.prototype.InterpolantFactoryMethodLinear=void 0,Bd.prototype.InterpolantFactoryMethodSmooth=void 0;class zd extends Fd{}zd.prototype.ValueTypeName="color";class kd extends Fd{}kd.prototype.ValueTypeName="number";class Vd extends Ud{constructor(t,e,n,i){super(t,e,n,i)}interpolate_(t,e,n,i){const r=this.resultBuffer,s=this.sampleValues,a=this.valueSize,o=(n-e)/(i-e);let l=t*a;for(let t=l+a;l!==t;l+=4)Ii.slerpFlat(r,0,s,l-a,s,l,o);return r}}class Hd extends Fd{InterpolantFactoryMethodLinear(t){return new Vd(this.times,this.values,this.getValueSize(),t)}}Hd.prototype.ValueTypeName="quaternion",Hd.prototype.InterpolantFactoryMethodSmooth=void 0;class Gd extends Fd{constructor(t,e,n){super(t,e,n)}}Gd.prototype.ValueTypeName="string",Gd.prototype.ValueBufferType=Array,Gd.prototype.DefaultInterpolation=Le,Gd.prototype.InterpolantFactoryMethodLinear=void 0,Gd.prototype.InterpolantFactoryMethodSmooth=void 0;class Wd extends Fd{}Wd.prototype.ValueTypeName="vector";class Xd{constructor(t="",e=-1,n=[],i=2500){this.name=t,this.tracks=n,this.duration=e,this.blendMode=i,this.uuid=qn(),this.duration<0&&this.resetDuration()}static parse(t){const e=[],n=t.tracks,i=1/(t.fps||1);for(let t=0,r=n.length;t!==r;++t)e.push(jd(n[t]).scale(i));const r=new this(t.name,t.duration,e,t.blendMode);return r.uuid=t.uuid,r}static toJSON(t){const e=[],n=t.tracks,i={name:t.name,duration:t.duration,tracks:e,uuid:t.uuid,blendMode:t.blendMode};for(let t=0,i=n.length;t!==i;++t)e.push(Fd.toJSON(n[t]));return i}static CreateFromMorphTargetSequence(t,e,n,i){const r=e.length,s=[];for(let t=0;t1){const t=s[1];let e=i[t];e||(i[t]=e=[]),e.push(n)}}const s=[];for(const t in i)s.push(this.CreateFromMorphTargetSequence(t,i[t],e,n));return s}static parseAnimation(t,e){if(!t)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const n=function(t,e,n,i,r){if(0!==n.length){const s=[],a=[];Id(n,s,a,i),0!==s.length&&r.push(new t(e,s,a))}},i=[],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!==Kd[t])return void Kd[t].push({onLoad:e,onProgress:n,onError:i});Kd[t]=[],Kd[t].push({onLoad:e,onProgress:n,onError:i});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 n=Kd[t],i=e.body.getReader(),r=e.headers.get("X-File-Size")||e.headers.get("Content-Length"),s=r?parseInt(r):0,a=0!==s;let o=0;const l=new ReadableStream({start(t){!function e(){i.read().then((({done:i,value:r})=>{if(i)t.close();else{o+=r.byteLength;const i=new ProgressEvent("progress",{lengthComputable:a,loaded:o,total:s});for(let t=0,e=n.length;t{t.error(e)}))}()}});return new Response(l)}throw new $d(`fetch for "${e.url}" responded with ${e.status}: ${e.statusText}`,e)})).then((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),n=e&&e[1]?e[1].toLowerCase():void 0,i=new TextDecoder(n);return t.arrayBuffer().then((t=>i.decode(t)))}}})).then((e=>{qd.add(t,e);const n=Kd[t];delete Kd[t];for(let t=0,i=n.length;t{const n=Kd[t];if(void 0===n)throw this.manager.itemError(t),e;delete Kd[t];for(let t=0,i=n.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 tp extends Jd{constructor(t){super(t)}load(t,e,n,i){const r=this,s=new Qd(this.manager);s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(t,(function(n){try{e(r.parse(JSON.parse(n)))}catch(e){i?i(e):console.error(e),r.manager.itemError(t)}}),n,i)}parse(t){const e=[];for(let n=0;n0:i.vertexColors=t.vertexColors),void 0!==t.uniforms)for(const e in t.uniforms){const r=t.uniforms[e];switch(i.uniforms[e]={},r.type){case"t":i.uniforms[e].value=n(r.value);break;case"c":i.uniforms[e].value=(new Kr).setHex(r.value);break;case"v2":i.uniforms[e].value=(new ti).fromArray(r.value);break;case"v3":i.uniforms[e].value=(new Li).fromArray(r.value);break;case"v4":i.uniforms[e].value=(new wi).fromArray(r.value);break;case"m3":i.uniforms[e].value=(new ei).fromArray(r.value);break;case"m4":i.uniforms[e].value=(new lr).fromArray(r.value);break;default:i.uniforms[e].value=r.value}}if(void 0!==t.defines&&(i.defines=t.defines),void 0!==t.vertexShader&&(i.vertexShader=t.vertexShader),void 0!==t.fragmentShader&&(i.fragmentShader=t.fragmentShader),void 0!==t.glslVersion&&(i.glslVersion=t.glslVersion),void 0!==t.extensions)for(const e in t.extensions)i.extensions[e]=t.extensions[e];if(void 0!==t.lights&&(i.lights=t.lights),void 0!==t.clipping&&(i.clipping=t.clipping),void 0!==t.size&&(i.size=t.size),void 0!==t.sizeAttenuation&&(i.sizeAttenuation=t.sizeAttenuation),void 0!==t.map&&(i.map=n(t.map)),void 0!==t.matcap&&(i.matcap=n(t.matcap)),void 0!==t.alphaMap&&(i.alphaMap=n(t.alphaMap)),void 0!==t.bumpMap&&(i.bumpMap=n(t.bumpMap)),void 0!==t.bumpScale&&(i.bumpScale=t.bumpScale),void 0!==t.normalMap&&(i.normalMap=n(t.normalMap)),void 0!==t.normalMapType&&(i.normalMapType=t.normalMapType),void 0!==t.normalScale){let e=t.normalScale;!1===Array.isArray(e)&&(e=[e,e]),i.normalScale=(new ti).fromArray(e)}return void 0!==t.displacementMap&&(i.displacementMap=n(t.displacementMap)),void 0!==t.displacementScale&&(i.displacementScale=t.displacementScale),void 0!==t.displacementBias&&(i.displacementBias=t.displacementBias),void 0!==t.roughnessMap&&(i.roughnessMap=n(t.roughnessMap)),void 0!==t.metalnessMap&&(i.metalnessMap=n(t.metalnessMap)),void 0!==t.emissiveMap&&(i.emissiveMap=n(t.emissiveMap)),void 0!==t.emissiveIntensity&&(i.emissiveIntensity=t.emissiveIntensity),void 0!==t.specularMap&&(i.specularMap=n(t.specularMap)),void 0!==t.specularIntensityMap&&(i.specularIntensityMap=n(t.specularIntensityMap)),void 0!==t.specularColorMap&&(i.specularColorMap=n(t.specularColorMap)),void 0!==t.envMap&&(i.envMap=n(t.envMap)),void 0!==t.envMapRotation&&i.envMapRotation.fromArray(t.envMapRotation),void 0!==t.envMapIntensity&&(i.envMapIntensity=t.envMapIntensity),void 0!==t.reflectivity&&(i.reflectivity=t.reflectivity),void 0!==t.refractionRatio&&(i.refractionRatio=t.refractionRatio),void 0!==t.lightMap&&(i.lightMap=n(t.lightMap)),void 0!==t.lightMapIntensity&&(i.lightMapIntensity=t.lightMapIntensity),void 0!==t.aoMap&&(i.aoMap=n(t.aoMap)),void 0!==t.aoMapIntensity&&(i.aoMapIntensity=t.aoMapIntensity),void 0!==t.gradientMap&&(i.gradientMap=n(t.gradientMap)),void 0!==t.clearcoatMap&&(i.clearcoatMap=n(t.clearcoatMap)),void 0!==t.clearcoatRoughnessMap&&(i.clearcoatRoughnessMap=n(t.clearcoatRoughnessMap)),void 0!==t.clearcoatNormalMap&&(i.clearcoatNormalMap=n(t.clearcoatNormalMap)),void 0!==t.clearcoatNormalScale&&(i.clearcoatNormalScale=(new ti).fromArray(t.clearcoatNormalScale)),void 0!==t.iridescenceMap&&(i.iridescenceMap=n(t.iridescenceMap)),void 0!==t.iridescenceThicknessMap&&(i.iridescenceThicknessMap=n(t.iridescenceThicknessMap)),void 0!==t.transmissionMap&&(i.transmissionMap=n(t.transmissionMap)),void 0!==t.thicknessMap&&(i.thicknessMap=n(t.thicknessMap)),void 0!==t.anisotropyMap&&(i.anisotropyMap=n(t.anisotropyMap)),void 0!==t.sheenColorMap&&(i.sheenColorMap=n(t.sheenColorMap)),void 0!==t.sheenRoughnessMap&&(i.sheenRoughnessMap=n(t.sheenRoughnessMap)),i}setTextures(t){return this.textures=t,this}static createMaterialFromType(t){return new{ShadowMaterial:vd,SpriteMaterial:pc,RawShaderMaterial:_d,ShaderMaterial:Ks,PointsMaterial:Dh,MeshPhysicalMaterial:yd,MeshStandardMaterial:xd,MeshPhongMaterial:Md,MeshToonMaterial:Sd,MeshNormalMaterial:bd,MeshLambertMaterial:wd,MeshDepthMaterial:Hl,MeshDistanceMaterial:Gl,MeshBasicMaterial:es,MeshMatcapMaterial:Td,LineDashedMaterial:Ed,LineBasicMaterial:Mh,Material:ts}[t]}}class Ep{static decodeText(t){if(console.warn("THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead."),"undefined"!=typeof TextDecoder)return(new TextDecoder).decode(t);let e="";for(let n=0,i=t.length;n0){const n=new Yd(e);r=new np(n),r.setCrossOrigin(this.crossOrigin);for(let e=0,n=t.length;e0){i=new np(this.manager),i.setCrossOrigin(this.crossOrigin);for(let e=0,i=t.length;e{const e=new Di;e.min.fromArray(t.boxMin),e.max.fromArray(t.boxMax);const n=new Qi;return n.radius=t.sphereRadius,n.center.fromArray(t.sphereCenter),{boxInitialized:t.boxInitialized,box:e,sphereInitialized:t.sphereInitialized,sphere:n}})),s._maxInstanceCount=t.maxInstanceCount,s._maxVertexCount=t.maxVertexCount,s._maxIndexCount=t.maxIndexCount,s._geometryInitialized=t.geometryInitialized,s._geometryCount=t.geometryCount,s._matricesTexture=h(t.matricesTexture.uuid),void 0!==t.colorsTexture&&(s._colorsTexture=h(t.colorsTexture.uuid));break;case"LOD":s=new Ic;break;case"Line":s=new Ch(l(t.geometry),c(t.material));break;case"LineLoop":s=new Nh(l(t.geometry),c(t.material));break;case"LineSegments":s=new Uh(l(t.geometry),c(t.material));break;case"PointCloud":case"Points":s=new kh(l(t.geometry),c(t.material));break;case"Sprite":s=new Ac(c(t.material));break;case"Group":s=new Kl;break;case"Bone":s=new Hc;break;default:s=new Dr}if(s.uuid=t.uuid,void 0!==t.name&&(s.name=t.name),void 0!==t.matrix?(s.matrix.fromArray(t.matrix),void 0!==t.matrixAutoUpdate&&(s.matrixAutoUpdate=t.matrixAutoUpdate),s.matrixAutoUpdate&&s.matrix.decompose(s.position,s.quaternion,s.scale)):(void 0!==t.position&&s.position.fromArray(t.position),void 0!==t.rotation&&s.rotation.fromArray(t.rotation),void 0!==t.quaternion&&s.quaternion.fromArray(t.quaternion),void 0!==t.scale&&s.scale.fromArray(t.scale)),void 0!==t.up&&s.up.fromArray(t.up),void 0!==t.castShadow&&(s.castShadow=t.castShadow),void 0!==t.receiveShadow&&(s.receiveShadow=t.receiveShadow),t.shadow&&(void 0!==t.shadow.intensity&&(s.shadow.intensity=t.shadow.intensity),void 0!==t.shadow.bias&&(s.shadow.bias=t.shadow.bias),void 0!==t.shadow.normalBias&&(s.shadow.normalBias=t.shadow.normalBias),void 0!==t.shadow.radius&&(s.shadow.radius=t.shadow.radius),void 0!==t.shadow.mapSize&&s.shadow.mapSize.fromArray(t.shadow.mapSize),void 0!==t.shadow.camera&&(s.shadow.camera=this.parseObject(t.shadow.camera))),void 0!==t.visible&&(s.visible=t.visible),void 0!==t.frustumCulled&&(s.frustumCulled=t.frustumCulled),void 0!==t.renderOrder&&(s.renderOrder=t.renderOrder),void 0!==t.userData&&(s.userData=t.userData),void 0!==t.layers&&(s.layers.mask=t.layers),void 0!==t.children){const a=t.children;for(let t=0;t{e&&e(n),r.manager.itemEnd(t)})).catch((t=>{i&&i(t)})):(setTimeout((function(){e&&e(s),r.manager.itemEnd(t)}),0),s);const a={};a.credentials="anonymous"===this.crossOrigin?"same-origin":"include",a.headers=this.requestHeader;const o=fetch(t,a).then((function(t){return t.blob()})).then((function(t){return createImageBitmap(t,Object.assign(r.options,{colorSpaceConversion:"none"}))})).then((function(n){return qd.add(t,n),e&&e(n),r.manager.itemEnd(t),n})).catch((function(e){i&&i(e),qd.remove(t),r.manager.itemError(t),r.manager.itemEnd(t)}));qd.add(t,o),r.manager.itemStart(t)}}let Np;class Dp{static getContext(){return void 0===Np&&(Np=new(window.AudioContext||window.webkitAudioContext)),Np}static setContext(t){Np=t}}class Op extends Jd{constructor(t){super(t)}load(t,e,n,i){const r=this,s=new Qd(this.manager);function a(e){i?i(e):console.error(e),r.manager.itemError(t)}s.setResponseType("arraybuffer"),s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(t,(function(t){try{const n=t.slice(0);Dp.getContext().decodeAudioData(n,(function(t){e(t)})).catch(a)}catch(t){a(t)}}),n,i)}}const Fp=new lr,Bp=new lr,zp=new lr;class kp{constructor(){this.type="StereoCamera",this.aspect=1,this.eyeSep=.064,this.cameraL=new na,this.cameraL.layers.enable(1),this.cameraL.matrixAutoUpdate=!1,this.cameraR=new na,this.cameraR.layers.enable(2),this.cameraR.matrixAutoUpdate=!1,this._cache={focus:null,fov:null,aspect:null,near:null,far:null,zoom:null,eyeSep:null}}update(t){const e=this._cache;if(e.focus!==t.focus||e.fov!==t.fov||e.aspect!==t.aspect*this.aspect||e.near!==t.near||e.far!==t.far||e.zoom!==t.zoom||e.eyeSep!==this.eyeSep){e.focus=t.focus,e.fov=t.fov,e.aspect=t.aspect*this.aspect,e.near=t.near,e.far=t.far,e.zoom=t.zoom,e.eyeSep=this.eyeSep,zp.copy(t.projectionMatrix);const n=e.eyeSep/2,i=n*e.near/e.focus,r=e.near*Math.tan(Xn*e.fov*.5)/e.zoom;let s,a;Bp.elements[12]=-n,Fp.elements[12]=n,s=-r*e.aspect+i,a=r*e.aspect+i,zp.elements[0]=2*e.near/(a-s),zp.elements[8]=(a+s)/(a-s),this.cameraL.projectionMatrix.copy(zp),s=-r*e.aspect-i,a=r*e.aspect-i,zp.elements[0]=2*e.near/(a-s),zp.elements[8]=(a+s)/(a-s),this.cameraR.projectionMatrix.copy(zp)}this.cameraL.matrixWorld.copy(t.matrixWorld).multiply(Bp),this.cameraR.matrixWorld.copy(t.matrixWorld).multiply(Fp)}}class Vp{constructor(t=!0){this.autoStart=t,this.startTime=0,this.oldTime=0,this.elapsedTime=0,this.running=!1}start(){this.startTime=Hp(),this.oldTime=this.startTime,this.elapsedTime=0,this.running=!0}stop(){this.getElapsedTime(),this.running=!1,this.autoStart=!1}getElapsedTime(){return this.getDelta(),this.elapsedTime}getDelta(){let t=0;if(this.autoStart&&!this.running)return this.start(),0;if(this.running){const e=Hp();t=(e-this.oldTime)/1e3,this.oldTime=e,this.elapsedTime+=t}return t}}function Hp(){return("undefined"==typeof performance?Date:performance).now()}const Gp=new Li,Wp=new Ii,Xp=new Li,jp=new Li;class qp extends Dr{constructor(){super(),this.type="AudioListener",this.context=Dp.getContext(),this.gain=this.context.createGain(),this.gain.connect(this.context.destination),this.filter=null,this.timeDelta=0,this._clock=new Vp}getInput(){return this.gain}removeFilter(){return null!==this.filter&&(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination),this.gain.connect(this.context.destination),this.filter=null),this}getFilter(){return this.filter}setFilter(t){return null!==this.filter?(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination)):this.gain.disconnect(this.context.destination),this.filter=t,this.gain.connect(this.filter),this.filter.connect(this.context.destination),this}getMasterVolume(){return this.gain.gain.value}setMasterVolume(t){return this.gain.gain.setTargetAtTime(t,this.context.currentTime,.01),this}updateMatrixWorld(t){super.updateMatrixWorld(t);const e=this.context.listener,n=this.up;if(this.timeDelta=this._clock.getDelta(),this.matrixWorld.decompose(Gp,Wp,Xp),jp.set(0,0,-1).applyQuaternion(Wp),e.positionX){const t=this.context.currentTime+this.timeDelta;e.positionX.linearRampToValueAtTime(Gp.x,t),e.positionY.linearRampToValueAtTime(Gp.y,t),e.positionZ.linearRampToValueAtTime(Gp.z,t),e.forwardX.linearRampToValueAtTime(jp.x,t),e.forwardY.linearRampToValueAtTime(jp.y,t),e.forwardZ.linearRampToValueAtTime(jp.z,t),e.upX.linearRampToValueAtTime(n.x,t),e.upY.linearRampToValueAtTime(n.y,t),e.upZ.linearRampToValueAtTime(n.z,t)}else e.setPosition(Gp.x,Gp.y,Gp.z),e.setOrientation(jp.x,jp.y,jp.z,n.x,n.y,n.z)}}class Yp extends Dr{constructor(t){super(),this.type="Audio",this.listener=t,this.context=t.context,this.gain=this.context.createGain(),this.gain.connect(t.getInput()),this.autoplay=!1,this.buffer=null,this.detune=0,this.loop=!1,this.loopStart=0,this.loopEnd=0,this.offset=0,this.duration=void 0,this.playbackRate=1,this.isPlaying=!1,this.hasPlaybackControl=!0,this.source=null,this.sourceType="empty",this._startedAt=0,this._progress=0,this._connected=!1,this.filters=[]}getOutput(){return this.gain}setNodeSource(t){return this.hasPlaybackControl=!1,this.sourceType="audioNode",this.source=t,this.connect(),this}setMediaElementSource(t){return this.hasPlaybackControl=!1,this.sourceType="mediaNode",this.source=this.context.createMediaElementSource(t),this.connect(),this}setMediaStreamSource(t){return this.hasPlaybackControl=!1,this.sourceType="mediaStreamNode",this.source=this.context.createMediaStreamSource(t),this.connect(),this}setBuffer(t){return this.buffer=t,this.sourceType="buffer",this.autoplay&&this.play(),this}play(t=0){if(!0===this.isPlaying)return void console.warn("THREE.Audio: Audio is already playing.");if(!1===this.hasPlaybackControl)return void console.warn("THREE.Audio: this Audio has no playback control.");this._startedAt=this.context.currentTime+t;const e=this.context.createBufferSource();return e.buffer=this.buffer,e.loop=this.loop,e.loopStart=this.loopStart,e.loopEnd=this.loopEnd,e.onended=this.onEnded.bind(this),e.start(this._startedAt,this._progress+this.offset,this.duration),this.isPlaying=!0,this.source=e,this.setDetune(this.detune),this.setPlaybackRate(this.playbackRate),this.connect()}pause(){if(!1!==this.hasPlaybackControl)return!0===this.isPlaying&&(this._progress+=Math.max(this.context.currentTime-this._startedAt,0)*this.playbackRate,!0===this.loop&&(this._progress=this._progress%(this.duration||this.buffer.duration)),this.source.stop(),this.source.onended=null,this.isPlaying=!1),this;console.warn("THREE.Audio: this Audio has no playback control.")}stop(){if(!1!==this.hasPlaybackControl)return this._progress=0,null!==this.source&&(this.source.stop(),this.source.onended=null),this.isPlaying=!1,this;console.warn("THREE.Audio: this Audio has no playback control.")}connect(){if(this.filters.length>0){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(n,i,this._addIndex*e,1,e);for(let t=e,r=e+e;t!==r;++t)if(n[t]!==n[t+e]){a.setValue(n,i);break}}saveOriginalState(){const t=this.binding,e=this.buffer,n=this.valueSize,i=n*this._origIndex;t.getValue(e,i);for(let t=n,r=i;t!==r;++t)e[t]=e[i+t%n];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 n=t;n=.5)for(let i=0;i!==r;++i)t[e+i]=t[n+i]}_slerp(t,e,n,i){Ii.slerpFlat(t,e,t,e,t,n,i)}_slerpAdditive(t,e,n,i,r){const s=this._workIndex*r;Ii.multiplyQuaternionsFlat(t,s,t,e,t,n),Ii.slerpFlat(t,e,t,e,t,s,i)}_lerp(t,e,n,i,r){const s=1-i;for(let a=0;a!==r;++a){const r=e+a;t[r]=t[r]*s+t[n+a]*i}}_lerpAdditive(t,e,n,i,r){for(let s=0;s!==r;++s){const r=e+s;t[r]=t[r]+t[n+s]*i}}}const nm="\\[\\]\\.:\\/",im=new RegExp("["+nm+"]","g"),rm="[^"+nm+"]",sm="[^"+nm.replace("\\.","")+"]",am=new RegExp("^"+/((?:WC+[\/:])*)/.source.replace("WC",rm)+/(WCOD+)?/.source.replace("WCOD",sm)+/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",rm)+/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",rm)+"$"),om=["material","materials","bones","map"];class lm{constructor(t,e,n){this.path=e,this.parsedPath=n||lm.parseTrackName(e),this.node=lm.findNode(t,this.parsedPath.nodeName),this.rootNode=t,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(t,e,n){return t&&t.isAnimationObjectGroup?new lm.Composite(t,e,n):new lm(t,e,n)}static sanitizeNodeName(t){return t.replace(/\s/g,"_").replace(im,"")}static parseTrackName(t){const e=am.exec(t);if(null===e)throw new Error("PropertyBinding: Cannot parse trackName: "+t);const n={nodeName:e[2],objectName:e[3],objectIndex:e[4],propertyName:e[5],propertyIndex:e[6]},i=n.nodeName&&n.nodeName.lastIndexOf(".");if(void 0!==i&&-1!==i){const t=n.nodeName.substring(i+1);-1!==om.indexOf(t)&&(n.nodeName=n.nodeName.substring(0,i),n.objectName=t)}if(null===n.propertyName||0===n.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+t);return n}static findNode(t,e){if(void 0===e||""===e||"."===e||-1===e||e===t.name||e===t.uuid)return t;if(t.skeleton){const n=t.skeleton.getBoneByName(e);if(void 0!==n)return n}if(t.children){const n=function(t){for(let i=0;i=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=i;t!==e;++t){const e=n[t],i=e[s],r=e[l];e[l]=i,e[s]=r}}}this.nCachedObjects_=r}uncache(){const t=this._objects,e=this._indicesByUUID,n=this._bindings,i=n.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=i;t!==e;++t){const e=n[t];e[l]=e[r],e.pop()}}}this.nCachedObjects_=r}subscribe_(t,e){const n=this._bindingsIndicesByPath;let i=n[t];const r=this._bindings;if(void 0!==i)return r[i];const s=this._paths,a=this._parsedPaths,o=this._objects,l=o.length,c=this.nCachedObjects_,h=new Array(l);i=r.length,n[t]=i,s.push(t),a.push(e),r.push(h);for(let n=c,i=o.length;n!==i;++n){const i=o[n];h[n]=new lm(i,t,e)}return h}unsubscribe_(t){const e=this._bindingsIndicesByPath,n=e[t];if(void 0!==n){const i=this._paths,r=this._parsedPaths,s=this._bindings,a=s.length-1,o=s[a];e[t[a]]=n,s[n]=o,s.pop(),r[n]=r[a],r.pop(),i[n]=i[a],i.pop()}}}class hm{constructor(t,e,n=null,i=e.blendMode){this._mixer=t,this._clip=e,this._localRoot=n,this.blendMode=i;const r=e.tracks,s=r.length,a=new Array(s),o={endingStart:De,endingEnd:De};for(let t=0;t!==s;++t){const e=r[t].createInterpolant(null);a[t]=e,e.settings=o}this._interpolantSettings=o,this._interpolants=a,this._propertyBindings=new Array(s),this._cacheIndex=null,this._byClipCacheIndex=null,this._timeScaleInterpolant=null,this._weightInterpolant=null,this.loop=2201,this._loopCount=-1,this._startTime=null,this.time=0,this.timeScale=1,this._effectiveTimeScale=1,this.weight=1,this._effectiveWeight=1,this.repetitions=1/0,this.paused=!1,this.enabled=!0,this.clampWhenFinished=!1,this.zeroSlopeAtStart=!0,this.zeroSlopeAtEnd=!0}play(){return this._mixer._activateAction(this),this}stop(){return this._mixer._deactivateAction(this),this.reset()}reset(){return this.paused=!1,this.enabled=!0,this.time=0,this._loopCount=-1,this._startTime=null,this.stopFading().stopWarping()}isRunning(){return this.enabled&&!this.paused&&0!==this.timeScale&&null===this._startTime&&this._mixer._isActiveAction(this)}isScheduled(){return this._mixer._isActiveAction(this)}startAt(t){return this._startTime=t,this}setLoop(t,e){return this.loop=t,this.repetitions=e,this}setEffectiveWeight(t){return this.weight=t,this._effectiveWeight=this.enabled?t:0,this.stopFading()}getEffectiveWeight(){return this._effectiveWeight}fadeIn(t){return this._scheduleFading(t,0,1)}fadeOut(t){return this._scheduleFading(t,1,0)}crossFadeFrom(t,e,n){if(t.fadeOut(e),this.fadeIn(e),n){const n=this._clip.duration,i=t._clip.duration,r=i/n,s=n/i;t.warp(1,r,e),this.warp(s,1,e)}return this}crossFadeTo(t,e,n){return t.crossFadeFrom(this,e,n)}stopFading(){const t=this._weightInterpolant;return null!==t&&(this._weightInterpolant=null,this._mixer._takeBackControlInterpolant(t)),this}setEffectiveTimeScale(t){return this.timeScale=t,this._effectiveTimeScale=this.paused?0:t,this.stopWarping()}getEffectiveTimeScale(){return this._effectiveTimeScale}setDuration(t){return this.timeScale=this._clip.duration/t,this.stopWarping()}syncWith(t){return this.time=t.time,this.timeScale=t.timeScale,this.stopWarping()}halt(t){return this.warp(this._effectiveTimeScale,0,t)}warp(t,e,n){const i=this._mixer,r=i.time,s=this.timeScale;let a=this._timeScaleInterpolant;null===a&&(a=i._lendControlInterpolant(),this._timeScaleInterpolant=a);const o=a.parameterPositions,l=a.sampleValues;return o[0]=r,o[1]=r+n,l[0]=t/s,l[1]=e/s,this}stopWarping(){const t=this._timeScaleInterpolant;return null!==t&&(this._timeScaleInterpolant=null,this._mixer._takeBackControlInterpolant(t)),this}getMixer(){return this._mixer}getClip(){return this._clip}getRoot(){return this._localRoot||this._mixer._root}_update(t,e,n,i){if(!this.enabled)return void this._updateWeight(t);const r=this._startTime;if(null!==r){const i=(t-r)*n;i<0||0===n?e=0:(this._startTime=null,e=n*i)}e*=this._updateTimeScale(t);const s=this._updateTime(e),a=this._updateWeight(t);if(a>0){const t=this._interpolants,e=this._propertyBindings;if(this.blendMode===ze)for(let n=0,i=t.length;n!==i;++n)t[n].evaluate(s),e[n].accumulateAdditive(a);else for(let n=0,r=t.length;n!==r;++n)t[n].evaluate(s),e[n].accumulate(i,a)}}_updateWeight(t){let e=0;if(this.enabled){e=this.weight;const n=this._weightInterpolant;if(null!==n){const i=n.evaluate(t)[0];e*=i,t>n.parameterPositions[1]&&(this.stopFading(),0===i&&(this.enabled=!1))}}return this._effectiveWeight=e,e}_updateTimeScale(t){let e=0;if(!this.paused){e=this.timeScale;const n=this._timeScaleInterpolant;if(null!==n){e*=n.evaluate(t)[0],t>n.parameterPositions[1]&&(this.stopWarping(),0===e?this.paused=!0:this.timeScale=e)}}return this._effectiveTimeScale=e,e}_updateTime(t){const e=this._clip.duration,n=this.loop;let i=this.time+t,r=this._loopCount;const s=2202===n;if(0===t)return-1===r?i:s&&1==(1&r)?e-i:i;if(2200===n){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));t:{if(i>=e)i=e;else{if(!(i<0)){this.time=i;break t}i=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=i,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)),i>=e||i<0){const n=Math.floor(i/e);i-=e*n,r+=Math.abs(n);const a=this.repetitions-r;if(a<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,i=t>0?e:0,this.time=i,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=i,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:n})}}else this.time=i;if(s&&1==(1&r))return e-i}return i}_setEndings(t,e,n){const i=this._interpolantSettings;n?(i.endingStart=Oe,i.endingEnd=Oe):(i.endingStart=t?this.zeroSlopeAtStart?Oe:De:Fe,i.endingEnd=e?this.zeroSlopeAtEnd?Oe:De:Fe)}_scheduleFading(t,e,n){const i=this._mixer,r=i.time;let s=this._weightInterpolant;null===s&&(s=i._lendControlInterpolant(),this._weightInterpolant=s);const a=s.parameterPositions,o=s.sampleValues;return a[0]=r,o[0]=e,a[1]=r+t,o[1]=n,this}}const um=new Float32Array(1);class dm extends Hn{constructor(t){super(),this._root=t,this._initMemoryManager(),this._accuIndex=0,this.time=0,this.timeScale=1}_bindAction(t,e){const n=t._localRoot||this._root,i=t._clip.tracks,r=i.length,s=t._propertyBindings,a=t._interpolants,o=n.uuid,l=this._bindingsByRootAndName;let c=l[o];void 0===c&&(c={},l[o]=c);for(let t=0;t!==r;++t){const r=i[t],l=r.name;let h=c[l];if(void 0!==h)++h.referenceCount,s[t]=h;else{if(h=s[t],void 0!==h){null===h._cacheIndex&&(++h.referenceCount,this._addInactiveBinding(h,o,l));continue}const i=e&&e._propertyBindings[t].binding.parsedPath;h=new em(lm.create(n,l,i),r.ValueTypeName,r.getValueSize()),++h.referenceCount,this._addInactiveBinding(h,o,l),s[t]=h}a[t].resultBuffer=h.buffer}}_activateAction(t){if(!this._isActiveAction(t)){if(null===t._cacheIndex){const e=(t._localRoot||this._root).uuid,n=t._clip.uuid,i=this._actionsByClip[n];this._bindAction(t,i&&i.knownActions[0]),this._addInactiveAction(t,n,e)}const e=t._propertyBindings;for(let t=0,n=e.length;t!==n;++t){const n=e[t];0==n.useCount++&&(this._lendBinding(n),n.saveOriginalState())}this._lendAction(t)}}_deactivateAction(t){if(this._isActiveAction(t)){const e=t._propertyBindings;for(let t=0,n=e.length;t!==n;++t){const n=e[t];0==--n.useCount&&(n.restoreOriginalState(),this._takeBackBinding(n))}this._takeBackAction(t)}}_initMemoryManager(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;const t=this;this.stats={actions:{get total(){return t._actions.length},get inUse(){return t._nActiveActions}},bindings:{get total(){return t._bindings.length},get inUse(){return t._nActiveBindings}},controlInterpolants:{get total(){return t._controlInterpolants.length},get inUse(){return t._nActiveControlInterpolants}}}}_isActiveAction(t){const e=t._cacheIndex;return null!==e&&e=0;--e)t[e].stop();return this}update(t){t*=this.timeScale;const e=this._actions,n=this._nActiveActions,i=this.time+=t,r=Math.sign(t),s=this._accuIndex^=1;for(let a=0;a!==n;++a){e[a]._update(i,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=this.min.x&&t.x<=this.max.x&&t.y>=this.min.y&&t.y<=this.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.x>=this.min.x&&t.min.x<=this.max.x&&t.max.y>=this.min.y&&t.min.y<=this.max.y}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,Tm).distanceTo(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}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 Am=new Li,Rm=new Li;class Cm{constructor(t=new Li,e=new Li){this.start=t,this.end=e}set(t,e){return this.start.copy(t),this.end.copy(e),this}copy(t){return this.start.copy(t.start),this.end.copy(t.end),this}getCenter(t){return t.addVectors(this.start,this.end).multiplyScalar(.5)}delta(t){return t.subVectors(this.end,this.start)}distanceSq(){return this.start.distanceToSquared(this.end)}distance(){return this.start.distanceTo(this.end)}at(t,e){return this.delta(e).multiplyScalar(t).add(this.start)}closestPointToPointParameter(t,e){Am.subVectors(t,this.start),Rm.subVectors(this.end,this.start);const n=Rm.dot(Rm);let i=Rm.dot(Am)/n;return e&&(i=Yn(i,0,1)),i}closestPointToPoint(t,e,n){const i=this.closestPointToPointParameter(t,e);return this.delta(n).multiplyScalar(i).add(this.start)}applyMatrix4(t){return this.start.applyMatrix4(t),this.end.applyMatrix4(t),this}equals(t){return t.start.equals(this.start)&&t.end.equals(this.end)}clone(){return(new this.constructor).copy(this)}}const Pm=new Li;class Im extends Dr{constructor(t,e){super(),this.light=t,this.matrixAutoUpdate=!1,this.color=e,this.type="SpotLightHelper";const n=new Es,i=[0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,-1,0,1,0,0,0,0,1,1,0,0,0,0,-1,1];for(let t=0,e=1,n=32;t1)for(let n=0;n.99999)this.quaternion.set(0,0,0,1);else if(t.y<-.99999)this.quaternion.set(1,0,0,0);else{nf.set(t.z,0,-t.x).normalize();const e=Math.acos(t.y);this.quaternion.setFromAxisAngle(nf,e)}}setLength(t,e=.2*t,n=.2*e){this.line.scale.set(1,Math.max(1e-4,t-e),1),this.line.updateMatrix(),this.cone.scale.set(n,e,n),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()}}class of extends Uh{constructor(t=1){const e=[0,0,0,t,0,0,0,0,0,0,t,0,0,0,0,0,0,t],n=new Es;n.setAttribute("position",new _s(e,3)),n.setAttribute("color",new _s([1,0,0,1,.6,0,0,1,0,.6,1,0,0,0,1,0,.6,1],3));super(n,new Mh({vertexColors:!0,toneMapped:!1})),this.type="AxesHelper"}setColors(t,e,n){const i=new Kr,r=this.geometry.attributes.color.array;return i.set(t),i.toArray(r,0),i.toArray(r,3),i.set(e),i.toArray(r,6),i.toArray(r,9),i.set(n),i.toArray(r,12),i.toArray(r,15),this.geometry.attributes.color.needsUpdate=!0,this}dispose(){this.geometry.dispose(),this.material.dispose()}}class lf{constructor(){this.type="ShapePath",this.color=new Kr,this.subPaths=[],this.currentPath=null}moveTo(t,e){return this.currentPath=new fu,this.subPaths.push(this.currentPath),this.currentPath.moveTo(t,e),this}lineTo(t,e){return this.currentPath.lineTo(t,e),this}quadraticCurveTo(t,e,n,i){return this.currentPath.quadraticCurveTo(t,e,n,i),this}bezierCurveTo(t,e,n,i,r,s){return this.currentPath.bezierCurveTo(t,e,n,i,r,s),this}splineThru(t){return this.currentPath.splineThru(t),this}toShapes(t){function e(t,e){const n=e.length;let i=!1;for(let r=n-1,s=0;sNumber.EPSILON){if(l<0&&(n=e[s],o=-o,a=e[r],l=-l),t.ya.y)continue;if(t.y===n.y){if(t.x===n.x)return!0}else{const e=l*(t.x-n.x)-o*(t.y-n.y);if(0===e)return!0;if(e<0)continue;i=!i}}else{if(t.y!==n.y)continue;if(a.x<=t.x&&t.x<=n.x||n.x<=t.x&&t.x<=a.x)return!0}}return i}const n=td.isClockWise,i=this.subPaths;if(0===i.length)return[];let r,s,a;const o=[];if(1===i.length)return s=i[0],a=new Ru,a.curves=s.curves,o.push(a),o;let l=!n(i[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=i.length;e1){let t=!1,n=0;for(let t=0,e=h.length;t0&&!1===t&&(p=c)}for(let t=0,e=h.length;t>8&255]+Gn[t>>16&255]+Gn[t>>24&255]+"-"+Gn[255&e]+Gn[e>>8&255]+"-"+Gn[e>>16&15|64]+Gn[e>>24&255]+"-"+Gn[63&n|128]+Gn[n>>8&255]+"-"+Gn[n>>16&255]+Gn[n>>24&255]+Gn[255&i]+Gn[i>>8&255]+Gn[i>>16&255]+Gn[i>>24&255]).toLowerCase()}function Yn(t,e,n){return Math.max(e,Math.min(n,t))}function Zn(t,e){return(t%e+e)%e}function Jn(t,e,n){return(1-n)*t+n*e}function Kn(t,e){switch(e.constructor){case Float32Array:return t;case Uint32Array:return t/4294967295;case Uint16Array:return t/65535;case Uint8Array:return t/255;case Int32Array:return Math.max(t/2147483647,-1);case Int16Array:return Math.max(t/32767,-1);case Int8Array:return Math.max(t/127,-1);default:throw new Error("Invalid component type.")}}function $n(t,e){switch(e.constructor){case Float32Array:return t;case Uint32Array:return Math.round(4294967295*t);case Uint16Array:return Math.round(65535*t);case Uint8Array:return Math.round(255*t);case Int32Array:return Math.round(2147483647*t);case Int16Array:return Math.round(32767*t);case Int8Array:return Math.round(127*t);default:throw new Error("Invalid component type.")}}const Qn={DEG2RAD:Xn,RAD2DEG:jn,generateUUID:qn,clamp:Yn,euclideanModulo:Zn,mapLinear:function(t,e,n,i,r){return i+(t-e)*(r-i)/(n-e)},inverseLerp:function(t,e,n){return t!==e?(n-t)/(e-t):0},lerp:Jn,damp:function(t,e,n,i){return Jn(t,e,1-Math.exp(-n*i))},pingpong:function(t,e=1){return e-Math.abs(Zn(t,2*e)-e)},smoothstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-e))*t*(3-2*t)},smootherstep:function(t,e,n){return t<=e?0:t>=n?1:(t=(t-e)/(n-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&&(Wn=t);let e=Wn+=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*Xn},radToDeg:function(t){return t*jn},isPowerOfTwo:function(t){return 0==(t&t-1)&&0!==t},ceilPowerOfTwo:function(t){return Math.pow(2,Math.ceil(Math.log(t)/Math.LN2))},floorPowerOfTwo:function(t){return Math.pow(2,Math.floor(Math.log(t)/Math.LN2))},setQuaternionFromProperEuler:function(t,e,n,i,r){const s=Math.cos,a=Math.sin,o=s(n/2),l=a(n/2),c=s((e+i)/2),h=a((e+i)/2),u=s((e-i)/2),d=a((e-i)/2),p=s((i-e)/2),m=a((i-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:$n,denormalize:Kn};class ti{constructor(t=0,e=0){ti.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,n=this.y,i=t.elements;return this.x=i[0]*e+i[3]*n+i[6],this.y=i[1]*e+i[4]*n+i[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 n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}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=Math.trunc(this.x),this.y=Math.trunc(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}angleTo(t){const e=Math.sqrt(this.lengthSq()*t.lengthSq());if(0===e)return Math.PI/2;const n=this.dot(t)/e;return Math.acos(Yn(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y;return e*e+n*n}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,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,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 n=Math.cos(e),i=Math.sin(e),r=this.x-t.x,s=this.y-t.y;return this.x=r*n-s*i+t.x,this.y=r*i+s*n+t.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class ei{constructor(t,e,n,i,r,s,a,o,l){ei.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],void 0!==t&&this.set(t,e,n,i,r,s,a,o,l)}set(t,e,n,i,r,s,a,o,l){const c=this.elements;return c[0]=t,c[1]=i,c[2]=a,c[3]=e,c[4]=r,c[5]=o,c[6]=n,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,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],this}extractBasis(t,e,n){return t.setFromMatrix3Column(this,0),e.setFromMatrix3Column(this,1),n.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 n=t.elements,i=e.elements,r=this.elements,s=n[0],a=n[3],o=n[6],l=n[1],c=n[4],h=n[7],u=n[2],d=n[5],p=n[8],m=i[0],f=i[3],g=i[6],v=i[1],_=i[4],x=i[7],y=i[2],M=i[5],S=i[8];return r[0]=s*m+a*v+o*y,r[3]=s*f+a*_+o*M,r[6]=s*g+a*x+o*S,r[1]=l*m+c*v+h*y,r[4]=l*f+c*_+h*M,r[7]=l*g+c*x+h*S,r[2]=u*m+d*v+p*y,r[5]=u*f+d*_+p*M,r[8]=u*g+d*x+p*S,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],n=t[1],i=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-n*r*c+n*a*o+i*r*l-i*s*o}invert(){const t=this.elements,e=t[0],n=t[1],i=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+n*u+i*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]=(i*l-c*n)*m,t[2]=(a*n-i*s)*m,t[3]=u*m,t[4]=(c*e-i*o)*m,t[5]=(i*r-a*e)*m,t[6]=d*m,t[7]=(n*o-l*e)*m,t[8]=(s*e-n*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,n,i,r,s,a){const o=Math.cos(r),l=Math.sin(r);return this.set(n*o,n*l,-n*(o*s+l*a)+s+t,-i*l,i*o,-i*(-l*s+o*a)+a+e,0,0,1),this}scale(t,e){return this.premultiply(ni.makeScale(t,e)),this}rotate(t){return this.premultiply(ni.makeRotation(-t)),this}translate(t,e){return this.premultiply(ni.makeTranslation(t,e)),this}makeTranslation(t,e){return t.isVector2?this.set(1,0,t.x,0,1,t.y,0,0,1):this.set(1,0,t,0,1,e,0,0,1),this}makeRotation(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,n,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,n=t.elements;for(let t=0;t<9;t++)if(e[t]!==n[t])return!1;return!0}fromArray(t,e=0){for(let n=0;n<9;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t}clone(){return(new this.constructor).fromArray(this.elements)}}const ni=new ei;function ii(t){for(let e=t.length-1;e>=0;--e)if(t[e]>=65535)return!0;return!1}const ri={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function si(t,e){return new ri[t](e)}function ai(t){return document.createElementNS("http://www.w3.org/1999/xhtml",t)}function oi(){const t=ai("canvas");return t.style.display="block",t}const li={};function ci(t){t in li||(li[t]=!0,console.warn(t))}const hi=(new ei).set(.8224621,.177538,0,.0331941,.9668058,0,.0170827,.0723974,.9105199),ui=(new ei).set(1.2249401,-.2249404,0,-.0420569,1.0420571,0,-.0196376,-.0786361,1.0982735),di={[Ke]:{transfer:tn,primaries:nn,luminanceCoefficients:[.2126,.7152,.0722],toReference:t=>t,fromReference:t=>t},[Je]:{transfer:en,primaries:nn,luminanceCoefficients:[.2126,.7152,.0722],toReference:t=>t.convertSRGBToLinear(),fromReference:t=>t.convertLinearToSRGB()},[Qe]:{transfer:tn,primaries:rn,luminanceCoefficients:[.2289,.6917,.0793],toReference:t=>t.applyMatrix3(ui),fromReference:t=>t.applyMatrix3(hi)},[$e]:{transfer:en,primaries:rn,luminanceCoefficients:[.2289,.6917,.0793],toReference:t=>t.convertSRGBToLinear().applyMatrix3(ui),fromReference:t=>t.applyMatrix3(hi).convertLinearToSRGB()}},pi=new Set([Ke,Qe]),mi={enabled:!0,_workingColorSpace:Ke,get workingColorSpace(){return this._workingColorSpace},set workingColorSpace(t){if(!pi.has(t))throw new Error(`Unsupported working color space, "${t}".`);this._workingColorSpace=t},convert:function(t,e,n){if(!1===this.enabled||e===n||!e||!n)return t;const i=di[e].toReference;return(0,di[n].fromReference)(i(t))},fromWorkingColorSpace:function(t,e){return this.convert(t,this._workingColorSpace,e)},toWorkingColorSpace:function(t,e){return this.convert(t,e,this._workingColorSpace)},getPrimaries:function(t){return di[t].primaries},getTransfer:function(t){return t===Ze?tn:di[t].transfer},getLuminanceCoefficients:function(t,e=this._workingColorSpace){return t.fromArray(di[e].luminanceCoefficients)}};function fi(t){return t<.04045?.0773993808*t:Math.pow(.9478672986*t+.0521327014,2.4)}function gi(t){return t<.0031308?12.92*t:1.055*Math.pow(t,.41666)-.055}let vi;class _i{static getDataURL(t){if(/^data:/i.test(t.src))return t.src;if("undefined"==typeof HTMLCanvasElement)return t.src;let e;if(t instanceof HTMLCanvasElement)e=t;else{void 0===vi&&(vi=ai("canvas")),vi.width=t.width,vi.height=t.height;const n=vi.getContext("2d");t instanceof ImageData?n.putImageData(t,0,0):n.drawImage(t,0,0,t.width,t.height),e=vi}return e.width>2048||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=ai("canvas");e.width=t.width,e.height=t.height;const n=e.getContext("2d");n.drawImage(t,0,0,t.width,t.height);const i=n.getImageData(0,0,t.width,t.height),r=i.data;for(let t=0;t0&&(n.userData=this.userData),e||(t.textures[this.uuid]=n),n}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(t){if(this.mapping!==ot)return t;if(t.applyMatrix3(this.matrix),t.x<0||t.x>1)switch(this.wrapS){case pt:t.x=t.x-Math.floor(t.x);break;case mt:t.x=t.x<0?0:1;break;case ft: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 pt:t.y=t.y-Math.floor(t.y);break;case mt:t.y=t.y<0?0:1;break;case ft: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)}set needsPMREMUpdate(t){!0===t&&this.pmremVersion++}}bi.DEFAULT_IMAGE=null,bi.DEFAULT_MAPPING=ot,bi.DEFAULT_ANISOTROPY=1;class wi{constructor(t=0,e=0,n=0,i=1){wi.prototype.isVector4=!0,this.x=t,this.y=e,this.z=n,this.w=i}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,n,i){return this.x=t,this.y=e,this.z=n,this.w=i,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,n=this.y,i=this.z,r=this.w,s=t.elements;return this.x=s[0]*e+s[4]*n+s[8]*i+s[12]*r,this.y=s[1]*e+s[5]*n+s[9]*i+s[13]*r,this.z=s[2]*e+s[6]*n+s[10]*i+s[14]*r,this.w=s[3]*e+s[7]*n+s[11]*i+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,n,i,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,i=1-e*e;if(i>Number.EPSILON){const r=Math.sqrt(i),s=Math.atan2(r,e*n);t=Math.sin(t*s)/r,a=Math.sin(a*s)/r}const r=a*n;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,n,i,r,s){const a=n[i],o=n[i+1],l=n[i+2],c=n[i+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,n,i){return this._x=t,this._y=e,this._z=n,this._w=i,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=!0){const n=t._x,i=t._y,r=t._z,s=t._order,a=Math.cos,o=Math.sin,l=a(n/2),c=a(i/2),h=a(r/2),u=o(n/2),d=o(i/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!0===e&&this._onChangeCallback(),this}setFromAxisAngle(t,e){const n=e/2,i=Math.sin(n);return this._x=t.x*i,this._y=t.y*i,this._z=t.z*i,this._w=Math.cos(n),this._onChangeCallback(),this}setFromRotationMatrix(t){const e=t.elements,n=e[0],i=e[4],r=e[8],s=e[1],a=e[5],o=e[9],l=e[2],c=e[6],h=e[10],u=n+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-i)*t}else if(n>a&&n>h){const t=2*Math.sqrt(1+n-a-h);this._w=(c-o)/t,this._x=.25*t,this._y=(i+s)/t,this._z=(r+l)/t}else if(a>h){const t=2*Math.sqrt(1+a-n-h);this._w=(r-l)/t,this._x=(i+s)/t,this._y=.25*t,this._z=(o+c)/t}else{const t=2*Math.sqrt(1+h-n-a);this._w=(s-i)/t,this._x=(r+l)/t,this._y=(o+c)/t,this._z=.25*t}return this._onChangeCallback(),this}setFromUnitVectors(t,e){let n=t.dot(e)+1;return nMath.abs(t.z)?(this._x=-t.y,this._y=t.x,this._z=0,this._w=n):(this._x=0,this._y=-t.z,this._z=t.y,this._w=n)):(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=n),this.normalize()}angleTo(t){return 2*Math.acos(Math.abs(Yn(this.dot(t),-1,1)))}rotateTowards(t,e){const n=this.angleTo(t);if(0===n)return this;const i=Math.min(1,e/n);return this.slerp(t,i),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 n=t._x,i=t._y,r=t._z,s=t._w,a=e._x,o=e._y,l=e._z,c=e._w;return this._x=n*c+s*a+i*l-r*o,this._y=i*c+s*o+r*a-n*l,this._z=r*c+s*l+n*o-i*a,this._w=s*c-n*a-i*o-r*l,this._onChangeCallback(),this}slerp(t,e){if(0===e)return this;if(1===e)return this.copy(t);const n=this._x,i=this._y,r=this._z,s=this._w;let a=s*t._w+n*t._x+i*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=n,this._y=i,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*n+e*this._x,this._y=t*i+e*this._y,this._z=t*r+e*this._z,this.normalize(),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=n*h+this._x*u,this._y=i*h+this._y*u,this._z=r*h+this._z*u,this._onChangeCallback(),this}slerpQuaternions(t,e,n){return this.copy(t).slerp(e,n)}random(){const t=2*Math.PI*Math.random(),e=2*Math.PI*Math.random(),n=Math.random(),i=Math.sqrt(1-n),r=Math.sqrt(n);return this.set(i*Math.sin(t),i*Math.cos(t),r*Math.sin(e),r*Math.cos(e))}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._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(t){return this._onChangeCallback=t,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class Li{constructor(t=0,e=0,n=0){Li.prototype.isVector3=!0,this.x=t,this.y=e,this.z=n}set(t,e,n){return void 0===n&&(n=this.z),this.x=t,this.y=e,this.z=n,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(Ni.setFromEuler(t))}applyAxisAngle(t,e){return this.applyQuaternion(Ni.setFromAxisAngle(t,e))}applyMatrix3(t){const e=this.x,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[3]*n+r[6]*i,this.y=r[1]*e+r[4]*n+r[7]*i,this.z=r[2]*e+r[5]*n+r[8]*i,this}applyNormalMatrix(t){return this.applyMatrix3(t).normalize()}applyMatrix4(t){const e=this.x,n=this.y,i=this.z,r=t.elements,s=1/(r[3]*e+r[7]*n+r[11]*i+r[15]);return this.x=(r[0]*e+r[4]*n+r[8]*i+r[12])*s,this.y=(r[1]*e+r[5]*n+r[9]*i+r[13])*s,this.z=(r[2]*e+r[6]*n+r[10]*i+r[14])*s,this}applyQuaternion(t){const e=this.x,n=this.y,i=this.z,r=t.x,s=t.y,a=t.z,o=t.w,l=2*(s*i-a*n),c=2*(a*e-r*i),h=2*(r*n-s*e);return this.x=e+o*l+s*h-a*c,this.y=n+o*c+a*l-r*h,this.z=i+o*h+r*c-s*l,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,n=this.y,i=this.z,r=t.elements;return this.x=r[0]*e+r[4]*n+r[8]*i,this.y=r[1]*e+r[5]*n+r[9]*i,this.z=r[2]*e+r[6]*n+r[10]*i,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 n=this.length();return this.divideScalar(n||1).multiplyScalar(Math.max(t,Math.min(e,n)))}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=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(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,n){return this.x=t.x+(e.x-t.x)*n,this.y=t.y+(e.y-t.y)*n,this.z=t.z+(e.z-t.z)*n,this}cross(t){return this.crossVectors(this,t)}crossVectors(t,e){const n=t.x,i=t.y,r=t.z,s=e.x,a=e.y,o=e.z;return this.x=i*o-r*a,this.y=r*s-n*o,this.z=n*a-i*s,this}projectOnVector(t){const e=t.lengthSq();if(0===e)return this.set(0,0,0);const n=t.dot(this)/e;return this.copy(t).multiplyScalar(n)}projectOnPlane(t){return Ui.copy(this).projectOnVector(t),this.sub(Ui)}reflect(t){return this.sub(Ui.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 n=this.dot(t)/e;return Math.acos(Yn(n,-1,1))}distanceTo(t){return Math.sqrt(this.distanceToSquared(t))}distanceToSquared(t){const e=this.x-t.x,n=this.y-t.y,i=this.z-t.z;return e*e+n*n+i*i}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,n){const i=Math.sin(e)*t;return this.x=i*Math.sin(n),this.y=Math.cos(e)*t,this.z=i*Math.cos(n),this}setFromCylindrical(t){return this.setFromCylindricalCoords(t.radius,t.theta,t.y)}setFromCylindricalCoords(t,e,n){return this.x=t*Math.sin(e),this.y=n,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(),n=this.setFromMatrixColumn(t,1).length(),i=this.setFromMatrixColumn(t,2).length();return this.x=e,this.y=n,this.z=i,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}setFromColor(t){return this.x=t.r,this.y=t.g,this.z=t.b,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=Math.random()*Math.PI*2,e=2*Math.random()-1,n=Math.sqrt(1-e*e);return this.x=n*Math.cos(t),this.y=e,this.z=n*Math.sin(t),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const Ui=new Li,Ni=new Ii;class Di{constructor(t=new Li(1/0,1/0,1/0),e=new Li(-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){this.makeEmpty();for(let e=0,n=t.length;e=this.min.x&&t.x<=this.max.x&&t.y>=this.min.y&&t.y<=this.max.y&&t.z>=this.min.z&&t.z<=this.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.x>=this.min.x&&t.min.x<=this.max.x&&t.max.y>=this.min.y&&t.min.y<=this.max.y&&t.max.z>=this.min.z&&t.min.z<=this.max.z}intersectsSphere(t){return this.clampPoint(t.center,Fi),Fi.distanceToSquared(t.center)<=t.radius*t.radius}intersectsPlane(t){let e,n;return t.normal.x>0?(e=t.normal.x*this.min.x,n=t.normal.x*this.max.x):(e=t.normal.x*this.max.x,n=t.normal.x*this.min.x),t.normal.y>0?(e+=t.normal.y*this.min.y,n+=t.normal.y*this.max.y):(e+=t.normal.y*this.max.y,n+=t.normal.y*this.min.y),t.normal.z>0?(e+=t.normal.z*this.min.z,n+=t.normal.z*this.max.z):(e+=t.normal.z*this.max.z,n+=t.normal.z*this.min.z),e<=-t.constant&&n>=-t.constant}intersectsTriangle(t){if(this.isEmpty())return!1;this.getCenter(Xi),ji.subVectors(this.max,Xi),zi.subVectors(t.a,Xi),ki.subVectors(t.b,Xi),Vi.subVectors(t.c,Xi),Hi.subVectors(ki,zi),Gi.subVectors(Vi,ki),Wi.subVectors(zi,Vi);let e=[0,-Hi.z,Hi.y,0,-Gi.z,Gi.y,0,-Wi.z,Wi.y,Hi.z,0,-Hi.x,Gi.z,0,-Gi.x,Wi.z,0,-Wi.x,-Hi.y,Hi.x,0,-Gi.y,Gi.x,0,-Wi.y,Wi.x,0];return!!Zi(e,zi,ki,Vi,ji)&&(e=[1,0,0,0,1,0,0,0,1],!!Zi(e,zi,ki,Vi,ji)&&(qi.crossVectors(Hi,Gi),e=[qi.x,qi.y,qi.z],Zi(e,zi,ki,Vi,ji)))}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,Fi).distanceTo(t)}getBoundingSphere(t){return this.isEmpty()?t.makeEmpty():(this.getCenter(t.center),t.radius=.5*this.getSize(Fi).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()||(Oi[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(t),Oi[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(t),Oi[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(t),Oi[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(t),Oi[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(t),Oi[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(t),Oi[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(t),Oi[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(t),this.setFromPoints(Oi)),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 Oi=[new Li,new Li,new Li,new Li,new Li,new Li,new Li,new Li],Fi=new Li,Bi=new Di,zi=new Li,ki=new Li,Vi=new Li,Hi=new Li,Gi=new Li,Wi=new Li,Xi=new Li,ji=new Li,qi=new Li,Yi=new Li;function Zi(t,e,n,i,r){for(let s=0,a=t.length-3;s<=a;s+=3){Yi.fromArray(t,s);const a=r.x*Math.abs(Yi.x)+r.y*Math.abs(Yi.y)+r.z*Math.abs(Yi.z),o=e.dot(Yi),l=n.dot(Yi),c=i.dot(Yi);if(Math.max(-Math.max(o,l,c),Math.min(o,l,c))>a)return!1}return!0}const Ji=new Di,Ki=new Li,$i=new Li;class Qi{constructor(t=new Li,e=-1){this.isSphere=!0,this.center=t,this.radius=e}set(t,e){return this.center.copy(t),this.radius=e,this}setFromPoints(t,e){const n=this.center;void 0!==e?n.copy(e):Ji.setFromPoints(t).getCenter(n);let i=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;Ki.subVectors(t,this.center);const e=Ki.lengthSq();if(e>this.radius*this.radius){const t=Math.sqrt(e),n=.5*(t-this.radius);this.center.addScaledVector(Ki,n/t),this.radius+=n}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):($i.subVectors(t.center,this.center).setLength(t.radius),this.expandByPoint(Ki.copy(t.center).add($i)),this.expandByPoint(Ki.copy(t.center).sub($i))),this)}equals(t){return t.center.equals(this.center)&&t.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const tr=new Li,er=new Li,nr=new Li,ir=new Li,rr=new Li,sr=new Li,ar=new Li;class or{constructor(t=new Li,e=new Li(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.origin).addScaledVector(this.direction,t)}lookAt(t){return this.direction.copy(t).sub(this.origin).normalize(),this}recast(t){return this.origin.copy(this.at(t,tr)),this}closestPointToPoint(t,e){e.subVectors(t,this.origin);const n=e.dot(this.direction);return n<0?e.copy(this.origin):e.copy(this.origin).addScaledVector(this.direction,n)}distanceToPoint(t){return Math.sqrt(this.distanceSqToPoint(t))}distanceSqToPoint(t){const e=tr.subVectors(t,this.origin).dot(this.direction);return e<0?this.origin.distanceToSquared(t):(tr.copy(this.origin).addScaledVector(this.direction,e),tr.distanceToSquared(t))}distanceSqToSegment(t,e,n,i){er.copy(t).add(e).multiplyScalar(.5),nr.copy(e).sub(t).normalize(),ir.copy(this.origin).sub(er);const r=.5*t.distanceTo(e),s=-this.direction.dot(nr),a=ir.dot(this.direction),o=-ir.dot(nr),l=ir.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 n&&n.copy(this.origin).addScaledVector(this.direction,h),i&&i.copy(er).addScaledVector(nr,u),d}intersectSphere(t,e){tr.subVectors(t.center,this.origin);const n=tr.dot(this.direction),i=tr.dot(tr)-n*n,r=t.radius*t.radius;if(i>r)return null;const s=Math.sqrt(r-i),a=n-s,o=n+s;return 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 n=-(this.origin.dot(t.normal)+t.constant)/e;return n>=0?n:null}intersectPlane(t,e){const n=this.distanceToPlane(t);return null===n?null:this.at(n,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 n,i,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?(n=(t.min.x-u.x)*l,i=(t.max.x-u.x)*l):(n=(t.max.x-u.x)*l,i=(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),n>s||r>i?null:((r>n||isNaN(n))&&(n=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),n>o||a>i?null:((a>n||n!=n)&&(n=a),(o=0?n:i,e)))}intersectsBox(t){return null!==this.intersectBox(t,tr)}intersectTriangle(t,e,n,i,r){rr.subVectors(e,t),sr.subVectors(n,t),ar.crossVectors(rr,sr);let s,a=this.direction.dot(ar);if(a>0){if(i)return null;s=1}else{if(!(a<0))return null;s=-1,a=-a}ir.subVectors(this.origin,t);const o=s*this.direction.dot(sr.crossVectors(ir,sr));if(o<0)return null;const l=s*this.direction.dot(rr.cross(ir));if(l<0)return null;if(o+l>a)return null;const c=-s*ir.dot(ar);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 lr{constructor(t,e,n,i,r,s,a,o,l,c,h,u,d,p,m,f){lr.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],void 0!==t&&this.set(t,e,n,i,r,s,a,o,l,c,h,u,d,p,m,f)}set(t,e,n,i,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]=n,g[12]=i,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 lr).fromArray(this.elements)}copy(t){const e=this.elements,n=t.elements;return e[0]=n[0],e[1]=n[1],e[2]=n[2],e[3]=n[3],e[4]=n[4],e[5]=n[5],e[6]=n[6],e[7]=n[7],e[8]=n[8],e[9]=n[9],e[10]=n[10],e[11]=n[11],e[12]=n[12],e[13]=n[13],e[14]=n[14],e[15]=n[15],this}copyPosition(t){const e=this.elements,n=t.elements;return e[12]=n[12],e[13]=n[13],e[14]=n[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,n){return t.setFromMatrixColumn(this,0),e.setFromMatrixColumn(this,1),n.setFromMatrixColumn(this,2),this}makeBasis(t,e,n){return this.set(t.x,e.x,n.x,0,t.y,e.y,n.y,0,t.z,e.z,n.z,0,0,0,0,1),this}extractRotation(t){const e=this.elements,n=t.elements,i=1/cr.setFromMatrixColumn(t,0).length(),r=1/cr.setFromMatrixColumn(t,1).length(),s=1/cr.setFromMatrixColumn(t,2).length();return e[0]=n[0]*i,e[1]=n[1]*i,e[2]=n[2]*i,e[3]=0,e[4]=n[4]*r,e[5]=n[5]*r,e[6]=n[6]*r,e[7]=0,e[8]=n[8]*s,e[9]=n[9]*s,e[10]=n[10]*s,e[11]=0,e[12]=0,e[13]=0,e[14]=0,e[15]=1,this}makeRotationFromEuler(t){const e=this.elements,n=t.x,i=t.y,r=t.z,s=Math.cos(n),a=Math.sin(n),o=Math.cos(i),l=Math.sin(i),c=Math.cos(r),h=Math.sin(r);if("XYZ"===t.order){const t=s*c,n=s*h,i=a*c,r=a*h;e[0]=o*c,e[4]=-o*h,e[8]=l,e[1]=n+i*l,e[5]=t-r*l,e[9]=-a*o,e[2]=r-t*l,e[6]=i+n*l,e[10]=s*o}else if("YXZ"===t.order){const t=o*c,n=o*h,i=l*c,r=l*h;e[0]=t+r*a,e[4]=i*a-n,e[8]=s*l,e[1]=s*h,e[5]=s*c,e[9]=-a,e[2]=n*a-i,e[6]=r+t*a,e[10]=s*o}else if("ZXY"===t.order){const t=o*c,n=o*h,i=l*c,r=l*h;e[0]=t-r*a,e[4]=-s*h,e[8]=i+n*a,e[1]=n+i*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,n=s*h,i=a*c,r=a*h;e[0]=o*c,e[4]=i*l-n,e[8]=t*l+r,e[1]=o*h,e[5]=r*l+t,e[9]=n*l-i,e[2]=-l,e[6]=a*o,e[10]=s*o}else if("YZX"===t.order){const t=s*o,n=s*l,i=a*o,r=a*l;e[0]=o*c,e[4]=r-t*h,e[8]=i*h+n,e[1]=h,e[5]=s*c,e[9]=-a*c,e[2]=-l*c,e[6]=n*h+i,e[10]=t-r*h}else if("XZY"===t.order){const t=s*o,n=s*l,i=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]=n*h-i,e[2]=i*h-n,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(ur,t,dr)}lookAt(t,e,n){const i=this.elements;return fr.subVectors(t,e),0===fr.lengthSq()&&(fr.z=1),fr.normalize(),pr.crossVectors(n,fr),0===pr.lengthSq()&&(1===Math.abs(n.z)?fr.x+=1e-4:fr.z+=1e-4,fr.normalize(),pr.crossVectors(n,fr)),pr.normalize(),mr.crossVectors(fr,pr),i[0]=pr.x,i[4]=mr.x,i[8]=fr.x,i[1]=pr.y,i[5]=mr.y,i[9]=fr.y,i[2]=pr.z,i[6]=mr.z,i[10]=fr.z,this}multiply(t){return this.multiplyMatrices(this,t)}premultiply(t){return this.multiplyMatrices(t,this)}multiplyMatrices(t,e){const n=t.elements,i=e.elements,r=this.elements,s=n[0],a=n[4],o=n[8],l=n[12],c=n[1],h=n[5],u=n[9],d=n[13],p=n[2],m=n[6],f=n[10],g=n[14],v=n[3],_=n[7],x=n[11],y=n[15],M=i[0],S=i[4],b=i[8],w=i[12],T=i[1],E=i[5],A=i[9],R=i[13],C=i[2],P=i[6],I=i[10],L=i[14],U=i[3],N=i[7],D=i[11],O=i[15];return r[0]=s*M+a*T+o*C+l*U,r[4]=s*S+a*E+o*P+l*N,r[8]=s*b+a*A+o*I+l*D,r[12]=s*w+a*R+o*L+l*O,r[1]=c*M+h*T+u*C+d*U,r[5]=c*S+h*E+u*P+d*N,r[9]=c*b+h*A+u*I+d*D,r[13]=c*w+h*R+u*L+d*O,r[2]=p*M+m*T+f*C+g*U,r[6]=p*S+m*E+f*P+g*N,r[10]=p*b+m*A+f*I+g*D,r[14]=p*w+m*R+f*L+g*O,r[3]=v*M+_*T+x*C+y*U,r[7]=v*S+_*E+x*P+y*N,r[11]=v*b+_*A+x*I+y*D,r[15]=v*w+_*R+x*L+y*O,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],n=t[4],i=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-i*l*h-r*a*u+n*l*u+i*a*d-n*o*d)+t[7]*(+e*o*d-e*l*u+r*s*u-i*s*d+i*l*c-r*o*c)+t[11]*(+e*l*h-e*a*d-r*s*h+n*s*d+r*a*c-n*l*c)+t[15]*(-i*a*c-e*o*h+e*a*u+i*s*h-n*s*u+n*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,n){const i=this.elements;return t.isVector3?(i[12]=t.x,i[13]=t.y,i[14]=t.z):(i[12]=t,i[13]=e,i[14]=n),this}invert(){const t=this.elements,e=t[0],n=t[1],i=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,_=p*u*l-c*f*l-p*o*d+s*f*d+c*o*g-s*u*g,x=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+n*_+i*x+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 S=1/M;return t[0]=v*S,t[1]=(m*u*r-h*f*r-m*i*d+n*f*d+h*i*g-n*u*g)*S,t[2]=(a*f*r-m*o*r+m*i*l-n*f*l-a*i*g+n*o*g)*S,t[3]=(h*o*r-a*u*r-h*i*l+n*u*l+a*i*d-n*o*d)*S,t[4]=_*S,t[5]=(c*f*r-p*u*r+p*i*d-e*f*d-c*i*g+e*u*g)*S,t[6]=(p*o*r-s*f*r-p*i*l+e*f*l+s*i*g-e*o*g)*S,t[7]=(s*u*r-c*o*r+c*i*l-e*u*l-s*i*d+e*o*d)*S,t[8]=x*S,t[9]=(p*h*r-c*m*r-p*n*d+e*m*d+c*n*g-e*h*g)*S,t[10]=(s*m*r-p*a*r+p*n*l-e*m*l-s*n*g+e*a*g)*S,t[11]=(c*a*r-s*h*r-c*n*l+e*h*l+s*n*d-e*a*d)*S,t[12]=y*S,t[13]=(c*m*i-p*h*i+p*n*u-e*m*u-c*n*f+e*h*f)*S,t[14]=(p*a*i-s*m*i-p*n*o+e*m*o+s*n*f-e*a*f)*S,t[15]=(s*h*i-c*a*i+c*n*o-e*h*o-s*n*u+e*a*u)*S,this}scale(t){const e=this.elements,n=t.x,i=t.y,r=t.z;return e[0]*=n,e[4]*=i,e[8]*=r,e[1]*=n,e[5]*=i,e[9]*=r,e[2]*=n,e[6]*=i,e[10]*=r,e[3]*=n,e[7]*=i,e[11]*=r,this}getMaxScaleOnAxis(){const t=this.elements,e=t[0]*t[0]+t[1]*t[1]+t[2]*t[2],n=t[4]*t[4]+t[5]*t[5]+t[6]*t[6],i=t[8]*t[8]+t[9]*t[9]+t[10]*t[10];return Math.sqrt(Math.max(e,n,i))}makeTranslation(t,e,n){return t.isVector3?this.set(1,0,0,t.x,0,1,0,t.y,0,0,1,t.z,0,0,0,1):this.set(1,0,0,t,0,1,0,e,0,0,1,n,0,0,0,1),this}makeRotationX(t){const e=Math.cos(t),n=Math.sin(t);return this.set(1,0,0,0,0,e,-n,0,0,n,e,0,0,0,0,1),this}makeRotationY(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,0,n,0,0,1,0,0,-n,0,e,0,0,0,0,1),this}makeRotationZ(t){const e=Math.cos(t),n=Math.sin(t);return this.set(e,-n,0,0,n,e,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(t,e){const n=Math.cos(e),i=Math.sin(e),r=1-n,s=t.x,a=t.y,o=t.z,l=r*s,c=r*a;return this.set(l*s+n,l*a-i*o,l*o+i*a,0,l*a+i*o,c*a+n,c*o-i*s,0,l*o-i*a,c*o+i*s,r*o*o+n,0,0,0,0,1),this}makeScale(t,e,n){return this.set(t,0,0,0,0,e,0,0,0,0,n,0,0,0,0,1),this}makeShear(t,e,n,i,r,s){return this.set(1,n,r,0,t,1,s,0,e,i,1,0,0,0,0,1),this}compose(t,e,n){const i=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,_=o*c,x=o*h,y=n.x,M=n.y,S=n.z;return i[0]=(1-(m+g))*y,i[1]=(d+x)*y,i[2]=(p-_)*y,i[3]=0,i[4]=(d-x)*M,i[5]=(1-(u+g))*M,i[6]=(f+v)*M,i[7]=0,i[8]=(p+_)*S,i[9]=(f-v)*S,i[10]=(1-(u+m))*S,i[11]=0,i[12]=t.x,i[13]=t.y,i[14]=t.z,i[15]=1,this}decompose(t,e,n){const i=this.elements;let r=cr.set(i[0],i[1],i[2]).length();const s=cr.set(i[4],i[5],i[6]).length(),a=cr.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),t.x=i[12],t.y=i[13],t.z=i[14],hr.copy(this);const o=1/r,l=1/s,c=1/a;return hr.elements[0]*=o,hr.elements[1]*=o,hr.elements[2]*=o,hr.elements[4]*=l,hr.elements[5]*=l,hr.elements[6]*=l,hr.elements[8]*=c,hr.elements[9]*=c,hr.elements[10]*=c,e.setFromRotationMatrix(hr),n.x=r,n.y=s,n.z=a,this}makePerspective(t,e,n,i,r,s,a=2e3){const o=this.elements,l=2*r/(e-t),c=2*r/(n-i),h=(e+t)/(e-t),u=(n+i)/(n-i);let d,p;if(a===kn)d=-(s+r)/(s-r),p=-2*s*r/(s-r);else{if(a!==Vn)throw new Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: "+a);d=-s/(s-r),p=-s*r/(s-r)}return o[0]=l,o[4]=0,o[8]=h,o[12]=0,o[1]=0,o[5]=c,o[9]=u,o[13]=0,o[2]=0,o[6]=0,o[10]=d,o[14]=p,o[3]=0,o[7]=0,o[11]=-1,o[15]=0,this}makeOrthographic(t,e,n,i,r,s,a=2e3){const o=this.elements,l=1/(e-t),c=1/(n-i),h=1/(s-r),u=(e+t)*l,d=(n+i)*c;let p,m;if(a===kn)p=(s+r)*h,m=-2*h;else{if(a!==Vn)throw new Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: "+a);p=r*h,m=-1*h}return o[0]=2*l,o[4]=0,o[8]=0,o[12]=-u,o[1]=0,o[5]=2*c,o[9]=0,o[13]=-d,o[2]=0,o[6]=0,o[10]=m,o[14]=-p,o[3]=0,o[7]=0,o[11]=0,o[15]=1,this}equals(t){const e=this.elements,n=t.elements;for(let t=0;t<16;t++)if(e[t]!==n[t])return!1;return!0}fromArray(t,e=0){for(let n=0;n<16;n++)this.elements[n]=t[n+e];return this}toArray(t=[],e=0){const n=this.elements;return t[e]=n[0],t[e+1]=n[1],t[e+2]=n[2],t[e+3]=n[3],t[e+4]=n[4],t[e+5]=n[5],t[e+6]=n[6],t[e+7]=n[7],t[e+8]=n[8],t[e+9]=n[9],t[e+10]=n[10],t[e+11]=n[11],t[e+12]=n[12],t[e+13]=n[13],t[e+14]=n[14],t[e+15]=n[15],t}}const cr=new Li,hr=new lr,ur=new Li(0,0,0),dr=new Li(1,1,1),pr=new Li,mr=new Li,fr=new Li,gr=new lr,vr=new Ii;class _r{constructor(t=0,e=0,n=0,i=_r.DEFAULT_ORDER){this.isEuler=!0,this._x=t,this._y=e,this._z=n,this._order=i}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,n,i=this._order){return this._x=t,this._y=e,this._z=n,this._order=i,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,n=!0){const i=t.elements,r=i[0],s=i[4],a=i[8],o=i[1],l=i[5],c=i[9],h=i[2],u=i[6],d=i[10];switch(e){case"XYZ":this._y=Math.asin(Yn(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(-Yn(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(Yn(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(-Yn(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(Yn(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(-Yn(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===n&&this._onChangeCallback(),this}setFromQuaternion(t,e,n){return gr.makeRotationFromQuaternion(t),this.setFromRotationMatrix(gr,e,n)}setFromVector3(t,e=this._order){return this.set(t.x,t.y,t.z,e)}reorder(t){return vr.setFromEuler(this),this.setFromQuaternion(vr,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}}_r.DEFAULT_ORDER="XYZ";class xr{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&&(i.userData=this.userData),i.layers=this.layers.mask,i.matrix=this.matrix.toArray(),i.up=this.up.toArray(),!1===this.matrixAutoUpdate&&(i.matrixAutoUpdate=!1),this.isInstancedMesh&&(i.type="InstancedMesh",i.count=this.count,i.instanceMatrix=this.instanceMatrix.toJSON(),null!==this.instanceColor&&(i.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(i.type="BatchedMesh",i.perObjectFrustumCulled=this.perObjectFrustumCulled,i.sortObjects=this.sortObjects,i.drawRanges=this._drawRanges,i.reservedRanges=this._reservedRanges,i.visibility=this._visibility,i.active=this._active,i.bounds=this._bounds.map((t=>({boxInitialized:t.boxInitialized,boxMin:t.box.min.toArray(),boxMax:t.box.max.toArray(),sphereInitialized:t.sphereInitialized,sphereRadius:t.sphere.radius,sphereCenter:t.sphere.center.toArray()}))),i.maxInstanceCount=this._maxInstanceCount,i.maxVertexCount=this._maxVertexCount,i.maxIndexCount=this._maxIndexCount,i.geometryInitialized=this._geometryInitialized,i.geometryCount=this._geometryCount,i.matricesTexture=this._matricesTexture.toJSON(t),null!==this._colorsTexture&&(i.colorsTexture=this._colorsTexture.toJSON(t)),null!==this.boundingSphere&&(i.boundingSphere={center:i.boundingSphere.center.toArray(),radius:i.boundingSphere.radius}),null!==this.boundingBox&&(i.boundingBox={min:i.boundingBox.min.toArray(),max:i.boundingBox.max.toArray()})),this.isScene)this.background&&(this.background.isColor?i.background=this.background.toJSON():this.background.isTexture&&(i.background=this.background.toJSON(t).uuid)),this.environment&&this.environment.isTexture&&!0!==this.environment.isRenderTargetTexture&&(i.environment=this.environment.toJSON(t).uuid);else if(this.isMesh||this.isLine||this.isPoints){i.geometry=r(t.geometries,this.geometry);const e=this.geometry.parameters;if(void 0!==e&&void 0!==e.shapes){const n=e.shapes;if(Array.isArray(n))for(let e=0,i=n.length;e0){i.children=[];for(let e=0;e0){i.animations=[];for(let e=0;e0&&(n.geometries=e),i.length>0&&(n.materials=i),r.length>0&&(n.textures=r),a.length>0&&(n.images=a),o.length>0&&(n.shapes=o),l.length>0&&(n.skeletons=l),c.length>0&&(n.animations=c),h.length>0&&(n.nodes=h)}return n.object=i,n;function s(t){const e=[];for(const n in t){const i=t[n];delete i.metadata,e.push(i)}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.matrixWorldAutoUpdate=t.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=t.matrixWorldNeedsUpdate,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.animations=t.animations.slice(),this.userData=JSON.parse(JSON.stringify(t.userData)),!0===e)for(let e=0;e0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(t,e,n,i,r){Or.subVectors(i,e),Fr.subVectors(n,e),Br.subVectors(t,e);const s=Or.dot(Or),a=Or.dot(Fr),o=Or.dot(Br),l=Fr.dot(Fr),c=Fr.dot(Br),h=s*l-a*a;if(0===h)return r.set(0,0,0),null;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,n,i){return null!==this.getBarycoord(t,e,n,i,zr)&&(zr.x>=0&&zr.y>=0&&zr.x+zr.y<=1)}static getInterpolation(t,e,n,i,r,s,a,o){return null===this.getBarycoord(t,e,n,i,zr)?(o.x=0,o.y=0,"z"in o&&(o.z=0),"w"in o&&(o.w=0),null):(o.setScalar(0),o.addScaledVector(r,zr.x),o.addScaledVector(s,zr.y),o.addScaledVector(a,zr.z),o)}static getInterpolatedAttribute(t,e,n,i,r,s){return jr.setScalar(0),qr.setScalar(0),Yr.setScalar(0),jr.fromBufferAttribute(t,e),qr.fromBufferAttribute(t,n),Yr.fromBufferAttribute(t,i),s.setScalar(0),s.addScaledVector(jr,r.x),s.addScaledVector(qr,r.y),s.addScaledVector(Yr,r.z),s}static isFrontFacing(t,e,n,i){return Or.subVectors(n,e),Fr.subVectors(t,e),Or.cross(Fr).dot(i)<0}set(t,e,n){return this.a.copy(t),this.b.copy(e),this.c.copy(n),this}setFromPointsAndIndices(t,e,n,i){return this.a.copy(t[e]),this.b.copy(t[n]),this.c.copy(t[i]),this}setFromAttributeAndIndices(t,e,n,i){return this.a.fromBufferAttribute(t,e),this.b.fromBufferAttribute(t,n),this.c.fromBufferAttribute(t,i),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 Or.subVectors(this.c,this.b),Fr.subVectors(this.a,this.b),.5*Or.cross(Fr).length()}getMidpoint(t){return t.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(t){return Zr.getNormal(this.a,this.b,this.c,t)}getPlane(t){return t.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(t,e){return Zr.getBarycoord(t,this.a,this.b,this.c,e)}getInterpolation(t,e,n,i,r){return Zr.getInterpolation(t,this.a,this.b,this.c,e,n,i,r)}containsPoint(t){return Zr.containsPoint(t,this.a,this.b,this.c)}isFrontFacing(t){return Zr.isFrontFacing(this.a,this.b,this.c,t)}intersectsBox(t){return t.intersectsTriangle(this)}closestPointToPoint(t,e){const n=this.a,i=this.b,r=this.c;let s,a;kr.subVectors(i,n),Vr.subVectors(r,n),Gr.subVectors(t,n);const o=kr.dot(Gr),l=Vr.dot(Gr);if(o<=0&&l<=0)return e.copy(n);Wr.subVectors(t,i);const c=kr.dot(Wr),h=Vr.dot(Wr);if(c>=0&&h<=c)return e.copy(i);const u=o*h-c*l;if(u<=0&&o>=0&&c<=0)return s=o/(o-c),e.copy(n).addScaledVector(kr,s);Xr.subVectors(t,r);const d=kr.dot(Xr),p=Vr.dot(Xr);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(n).addScaledVector(Vr,a);const f=c*p-d*h;if(f<=0&&h-c>=0&&d-p>=0)return Hr.subVectors(r,i),a=(h-c)/(h-c+(d-p)),e.copy(i).addScaledVector(Hr,a);const g=1/(f+m+u);return s=m*g,a=u*g,e.copy(n).addScaledVector(kr,s).addScaledVector(Vr,a)}equals(t){return t.a.equals(this.a)&&t.b.equals(this.b)&&t.c.equals(this.c)}}const Jr={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},Kr={h:0,s:0,l:0},$r={h:0,s:0,l:0};function Qr(t,e,n){return n<0&&(n+=1),n>1&&(n-=1),n<1/6?t+6*(e-t)*n:n<.5?e:n<2/3?t+6*(e-t)*(2/3-n):t}class ts{constructor(t,e,n){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(t,e,n)}set(t,e,n){if(void 0===e&&void 0===n){const e=t;e&&e.isColor?this.copy(e):"number"==typeof e?this.setHex(e):"string"==typeof e&&this.setStyle(e)}else this.setRGB(t,e,n);return this}setScalar(t){return this.r=t,this.g=t,this.b=t,this}setHex(t,e=Je){return t=Math.floor(t),this.r=(t>>16&255)/255,this.g=(t>>8&255)/255,this.b=(255&t)/255,mi.toWorkingColorSpace(this,e),this}setRGB(t,e,n,i=mi.workingColorSpace){return this.r=t,this.g=e,this.b=n,mi.toWorkingColorSpace(this,i),this}setHSL(t,e,n,i=mi.workingColorSpace){if(t=Zn(t,1),e=Yn(e,0,1),n=Yn(n,0,1),0===e)this.r=this.g=this.b=n;else{const i=n<=.5?n*(1+e):n+e-n*e,r=2*n-i;this.r=Qr(r,i,t+1/3),this.g=Qr(r,i,t),this.b=Qr(r,i,t-1/3)}return mi.toWorkingColorSpace(this,i),this}setStyle(t,e=Je){function n(e){void 0!==e&&parseFloat(e)<1&&console.warn("THREE.Color: Alpha component of "+t+" will be ignored.")}let i;if(i=/^(\w+)\(([^\)]*)\)/.exec(t)){let r;const s=i[1],a=i[2];switch(s){case"rgb":case"rgba":if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,e);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,e);break;case"hsl":case"hsla":if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(a))return n(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,e);break;default:console.warn("THREE.Color: Unknown color model "+t)}}else if(i=/^\#([A-Fa-f\d]+)$/.exec(t)){const n=i[1],r=n.length;if(3===r)return this.setRGB(parseInt(n.charAt(0),16)/15,parseInt(n.charAt(1),16)/15,parseInt(n.charAt(2),16)/15,e);if(6===r)return this.setHex(parseInt(n,16),e);console.warn("THREE.Color: Invalid hex color "+t)}else if(t&&t.length>0)return this.setColorName(t,e);return this}setColorName(t,e=Je){const n=Jr[t.toLowerCase()];return void 0!==n?this.setHex(n,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=fi(t.r),this.g=fi(t.g),this.b=fi(t.b),this}copyLinearToSRGB(t){return this.r=gi(t.r),this.g=gi(t.g),this.b=gi(t.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(t=Je){return mi.fromWorkingColorSpace(es.copy(this),t),65536*Math.round(Yn(255*es.r,0,255))+256*Math.round(Yn(255*es.g,0,255))+Math.round(Yn(255*es.b,0,255))}getHexString(t=Je){return("000000"+this.getHex(t).toString(16)).slice(-6)}getHSL(t,e=mi.workingColorSpace){mi.fromWorkingColorSpace(es.copy(this),e);const n=es.r,i=es.g,r=es.b,s=Math.max(n,i,r),a=Math.min(n,i,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 n:o=(i-r)/t+(i0!=t>0&&this.version++,this._alphaTest=t}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(t){if(void 0!==t)for(const e in t){const n=t[e];if(void 0===n){console.warn(`THREE.Material: parameter '${e}' has value of undefined.`);continue}const i=this[e];void 0!==i?i&&i.isColor?i.set(n):i&&i.isVector3&&n&&n.isVector3?i.copy(n):this[e]=n:console.warn(`THREE.Material: '${e}' is not a property of THREE.${this.type}.`)}}toJSON(t){const e=void 0===t||"string"==typeof t;e&&(t={textures:{},images:{}});const n={metadata:{version:4.6,type:"Material",generator:"Material.toJSON"}};function i(t){const e=[];for(const n in t){const i=t[n];delete i.metadata,e.push(i)}return e}if(n.uuid=this.uuid,n.type=this.type,""!==this.name&&(n.name=this.name),this.color&&this.color.isColor&&(n.color=this.color.getHex()),void 0!==this.roughness&&(n.roughness=this.roughness),void 0!==this.metalness&&(n.metalness=this.metalness),void 0!==this.sheen&&(n.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(n.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(n.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(n.emissive=this.emissive.getHex()),void 0!==this.emissiveIntensity&&1!==this.emissiveIntensity&&(n.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(n.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(n.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(n.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(n.shininess=this.shininess),void 0!==this.clearcoat&&(n.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(n.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(n.clearcoatMap=this.clearcoatMap.toJSON(t).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(n.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(t).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(n.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(t).uuid,n.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.dispersion&&(n.dispersion=this.dispersion),void 0!==this.iridescence&&(n.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(n.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(n.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(n.iridescenceMap=this.iridescenceMap.toJSON(t).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(n.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(t).uuid),void 0!==this.anisotropy&&(n.anisotropy=this.anisotropy),void 0!==this.anisotropyRotation&&(n.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(n.anisotropyMap=this.anisotropyMap.toJSON(t).uuid),this.map&&this.map.isTexture&&(n.map=this.map.toJSON(t).uuid),this.matcap&&this.matcap.isTexture&&(n.matcap=this.matcap.toJSON(t).uuid),this.alphaMap&&this.alphaMap.isTexture&&(n.alphaMap=this.alphaMap.toJSON(t).uuid),this.lightMap&&this.lightMap.isTexture&&(n.lightMap=this.lightMap.toJSON(t).uuid,n.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(n.aoMap=this.aoMap.toJSON(t).uuid,n.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(n.bumpMap=this.bumpMap.toJSON(t).uuid,n.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(n.normalMap=this.normalMap.toJSON(t).uuid,n.normalMapType=this.normalMapType,n.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(n.displacementMap=this.displacementMap.toJSON(t).uuid,n.displacementScale=this.displacementScale,n.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(n.roughnessMap=this.roughnessMap.toJSON(t).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(n.metalnessMap=this.metalnessMap.toJSON(t).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(n.emissiveMap=this.emissiveMap.toJSON(t).uuid),this.specularMap&&this.specularMap.isTexture&&(n.specularMap=this.specularMap.toJSON(t).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(n.specularIntensityMap=this.specularIntensityMap.toJSON(t).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(n.specularColorMap=this.specularColorMap.toJSON(t).uuid),this.envMap&&this.envMap.isTexture&&(n.envMap=this.envMap.toJSON(t).uuid,void 0!==this.combine&&(n.combine=this.combine)),void 0!==this.envMapRotation&&(n.envMapRotation=this.envMapRotation.toArray()),void 0!==this.envMapIntensity&&(n.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(n.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(n.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(n.gradientMap=this.gradientMap.toJSON(t).uuid),void 0!==this.transmission&&(n.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(n.transmissionMap=this.transmissionMap.toJSON(t).uuid),void 0!==this.thickness&&(n.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(n.thicknessMap=this.thicknessMap.toJSON(t).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(n.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(n.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(n.size=this.size),null!==this.shadowSide&&(n.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(n.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(n.blending=this.blending),this.side!==u&&(n.side=this.side),!0===this.vertexColors&&(n.vertexColors=!0),this.opacity<1&&(n.opacity=this.opacity),!0===this.transparent&&(n.transparent=!0),this.blendSrc!==C&&(n.blendSrc=this.blendSrc),this.blendDst!==P&&(n.blendDst=this.blendDst),this.blendEquation!==y&&(n.blendEquation=this.blendEquation),null!==this.blendSrcAlpha&&(n.blendSrcAlpha=this.blendSrcAlpha),null!==this.blendDstAlpha&&(n.blendDstAlpha=this.blendDstAlpha),null!==this.blendEquationAlpha&&(n.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&&this.blendColor.isColor&&(n.blendColor=this.blendColor.getHex()),0!==this.blendAlpha&&(n.blendAlpha=this.blendAlpha),3!==this.depthFunc&&(n.depthFunc=this.depthFunc),!1===this.depthTest&&(n.depthTest=this.depthTest),!1===this.depthWrite&&(n.depthWrite=this.depthWrite),!1===this.colorWrite&&(n.colorWrite=this.colorWrite),255!==this.stencilWriteMask&&(n.stencilWriteMask=this.stencilWriteMask),519!==this.stencilFunc&&(n.stencilFunc=this.stencilFunc),0!==this.stencilRef&&(n.stencilRef=this.stencilRef),255!==this.stencilFuncMask&&(n.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==an&&(n.stencilFail=this.stencilFail),this.stencilZFail!==an&&(n.stencilZFail=this.stencilZFail),this.stencilZPass!==an&&(n.stencilZPass=this.stencilZPass),!0===this.stencilWrite&&(n.stencilWrite=this.stencilWrite),void 0!==this.rotation&&0!==this.rotation&&(n.rotation=this.rotation),!0===this.polygonOffset&&(n.polygonOffset=!0),0!==this.polygonOffsetFactor&&(n.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(n.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(n.linewidth=this.linewidth),void 0!==this.dashSize&&(n.dashSize=this.dashSize),void 0!==this.gapSize&&(n.gapSize=this.gapSize),void 0!==this.scale&&(n.scale=this.scale),!0===this.dithering&&(n.dithering=!0),this.alphaTest>0&&(n.alphaTest=this.alphaTest),!0===this.alphaHash&&(n.alphaHash=!0),!0===this.alphaToCoverage&&(n.alphaToCoverage=!0),!0===this.premultipliedAlpha&&(n.premultipliedAlpha=!0),!0===this.forceSinglePass&&(n.forceSinglePass=!0),!0===this.wireframe&&(n.wireframe=!0),this.wireframeLinewidth>1&&(n.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(n.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(n.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(n.flatShading=!0),!1===this.visible&&(n.visible=!1),!1===this.toneMapped&&(n.toneMapped=!1),!1===this.fog&&(n.fog=!1),Object.keys(this.userData).length>0&&(n.userData=this.userData),e){const e=i(t.textures),r=i(t.images);e.length>0&&(n.textures=e),r.length>0&&(n.images=r)}return n}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.blendColor.copy(t.blendColor),this.blendAlpha=t.blendAlpha,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 n=null;if(null!==e){const t=e.length;n=new Array(t);for(let i=0;i!==t;++i)n[i]=e[i].clone()}return this.clippingPlanes=n,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.alphaHash=t.alphaHash,this.alphaToCoverage=t.alphaToCoverage,this.premultipliedAlpha=t.premultipliedAlpha,this.forceSinglePass=t.forceSinglePass,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++}onBuild(){console.warn("Material: onBuild() has been removed.")}}class rs extends is{constructor(t){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new ts(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.envMapRotation=new _r,this.combine=Y,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.envMapRotation.copy(t.envMapRotation),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 ss=as();function as(){const t=new ArrayBuffer(4),e=new Float32Array(t),n=new Uint32Array(t),i=new Uint32Array(512),r=new Uint32Array(512);for(let t=0;t<256;++t){const e=t-127;e<-27?(i[t]=0,i[256|t]=32768,r[t]=24,r[256|t]=24):e<-14?(i[t]=1024>>-e-14,i[256|t]=1024>>-e-14|32768,r[t]=-e-1,r[256|t]=-e-1):e<=15?(i[t]=e+15<<10,i[256|t]=e+15<<10|32768,r[t]=13,r[256|t]=13):e<128?(i[t]=31744,i[256|t]=64512,r[t]=24,r[256|t]=24):(i[t]=31744,i[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,n=0;for(;0==(8388608&e);)e<<=1,n-=8388608;e&=-8388609,n+=947912704,s[t]=e|n}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:n,baseTable:i,shiftTable:r,mantissaTable:s,exponentTable:a,offsetTable:o}}function os(t){Math.abs(t)>65504&&console.warn("THREE.DataUtils.toHalfFloat(): Value out of range."),t=Yn(t,-65504,65504),ss.floatView[0]=t;const e=ss.uint32View[0],n=e>>23&511;return ss.baseTable[n]+((8388607&e)>>ss.shiftTable[n])}function ls(t){const e=t>>10;return ss.uint32View[0]=ss.mantissaTable[ss.offsetTable[e]+(1023&t)]+ss.exponentTable[e],ss.floatView[0]}const cs={toHalfFloat:os,fromHalfFloat:ls},hs=new Li,us=new ti;class ds{constructor(t,e,n=!1){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=n,this.usage=Cn,this.updateRanges=[],this.gpuType=Lt,this.version=0}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}addUpdateRange(t,e){this.updateRanges.push({start:t,count:e})}clearUpdateRanges(){this.updateRanges.length=0}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.gpuType=t.gpuType,this}copyAt(t,e,n){t*=this.itemSize,n*=e.itemSize;for(let i=0,r=this.itemSize;i0&&(t.userData=this.userData),void 0!==this.parameters){const e=this.parameters;for(const n in e)void 0!==e[n]&&(t[n]=e[n]);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 n=this.attributes;for(const e in n){const i=n[e];t.data.attributes[e]=i.toJSON(t.data)}const i={};let r=!1;for(const e in this.morphAttributes){const n=this.morphAttributes[e],s=[];for(let e=0,i=n.length;e0&&(i[e]=s,r=!0)}r&&(t.data.morphAttributes=i,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 n=t.index;null!==n&&this.setIndex(n.clone(e));const i=t.attributes;for(const t in i){const n=i[t];this.setAttribute(t,n.clone(e))}const r=t.morphAttributes;for(const t in r){const n=[],i=r[t];for(let t=0,r=i.length;t0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;t(t.far-t.near)**2)return}Ps.copy(r).invert(),Is.copy(t.ray).applyMatrix4(Ps),null!==n.boundingBox&&!1===Is.intersectsBox(n.boundingBox)||this._computeIntersections(t,e,Is)}}_computeIntersections(t,e,n){let i;const r=this.geometry,s=this.material,a=r.index,o=r.attributes.position,l=r.attributes.uv,c=r.attributes.uv1,h=r.attributes.normal,u=r.groups,d=r.drawRange;if(null!==a)if(Array.isArray(s))for(let r=0,o=u.length;rn.far?null:{distance:c,point:ks.clone(),object:t}}(t,e,n,i,Ns,Ds,Os,zs);if(h){const t=new Li;Zr.getBarycoord(zs,Ns,Ds,Os,t),r&&(h.uv=Zr.getInterpolatedAttribute(r,o,l,c,t,new ti)),s&&(h.uv1=Zr.getInterpolatedAttribute(s,o,l,c,t,new ti)),a&&(h.normal=Zr.getInterpolatedAttribute(a,o,l,c,t,new Li),h.normal.dot(i.direction)>0&&h.normal.multiplyScalar(-1));const e={a:o,b:l,c:c,normal:new Li,materialIndex:0};Zr.getNormal(Ns,Ds,Os,e.normal),h.face=e,h.barycoord=t}return h}class Gs extends Cs{constructor(t=1,e=1,n=1,i=1,r=1,s=1){super(),this.type="BoxGeometry",this.parameters={width:t,height:e,depth:n,widthSegments:i,heightSegments:r,depthSegments:s};const a=this;i=Math.floor(i),r=Math.floor(r),s=Math.floor(s);const o=[],l=[],c=[],h=[];let u=0,d=0;function p(t,e,n,i,r,s,p,m,f,g,v){const _=s/f,x=p/g,y=s/2,M=p/2,S=m/2,b=f+1,w=g+1;let T=0,E=0;const A=new Li;for(let s=0;s0?1:-1,c.push(A.x,A.y,A.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,e.lights=this.lights,e.clipping=this.clipping;const n={};for(const t in this.extensions)!0===this.extensions[t]&&(n[t]=!0);return Object.keys(n).length>0&&(e.extensions=n),e}}class Zs extends Dr{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new lr,this.projectionMatrix=new lr,this.projectionMatrixInverse=new lr,this.coordinateSystem=kn}copy(t,e){return super.copy(t,e),this.matrixWorldInverse.copy(t.matrixWorldInverse),this.projectionMatrix.copy(t.projectionMatrix),this.projectionMatrixInverse.copy(t.projectionMatrixInverse),this.coordinateSystem=t.coordinateSystem,this}getWorldDirection(t){return super.getWorldDirection(t).negate()}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)}}const Js=new Li,Ks=new ti,$s=new ti;class Qs extends Zs{constructor(t=50,e=1,n=.1,i=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=t,this.zoom=1,this.near=n,this.far=i,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*jn*Math.atan(e),this.updateProjectionMatrix()}getFocalLength(){const t=Math.tan(.5*Xn*this.fov);return.5*this.getFilmHeight()/t}getEffectiveFOV(){return 2*jn*Math.atan(Math.tan(.5*Xn*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}getViewBounds(t,e,n){Js.set(-1,-1,.5).applyMatrix4(this.projectionMatrixInverse),e.set(Js.x,Js.y).multiplyScalar(-t/Js.z),Js.set(1,1,.5).applyMatrix4(this.projectionMatrixInverse),n.set(Js.x,Js.y).multiplyScalar(-t/Js.z)}getViewSize(t,e){return this.getViewBounds(t,Ks,$s),e.subVectors($s,Ks)}setViewOffset(t,e,n,i,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=n,this.view.offsetY=i,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*Xn*this.fov)/this.zoom,n=2*e,i=this.aspect*n,r=-.5*i;const s=this.view;if(null!==this.view&&this.view.enabled){const t=s.fullWidth,a=s.fullHeight;r+=s.offsetX*i/t,e-=s.offsetY*n/a,i*=s.width/t,n*=s.height/a}const a=this.filmOffset;0!==a&&(r+=t*a/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,e,e-n,t,this.far,this.coordinateSystem),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 ta=-90;class ea extends Dr{constructor(t,e,n){super(),this.type="CubeCamera",this.renderTarget=n,this.coordinateSystem=null,this.activeMipmapLevel=0;const i=new Qs(ta,1,t,e);i.layers=this.layers,this.add(i);const r=new Qs(ta,1,t,e);r.layers=this.layers,this.add(r);const s=new Qs(ta,1,t,e);s.layers=this.layers,this.add(s);const a=new Qs(ta,1,t,e);a.layers=this.layers,this.add(a);const o=new Qs(ta,1,t,e);o.layers=this.layers,this.add(o);const l=new Qs(ta,1,t,e);l.layers=this.layers,this.add(l)}updateCoordinateSystem(){const t=this.coordinateSystem,e=this.children.concat(),[n,i,r,s,a,o]=e;for(const t of e)this.remove(t);if(t===kn)n.up.set(0,1,0),n.lookAt(1,0,0),i.up.set(0,1,0),i.lookAt(-1,0,0),r.up.set(0,0,-1),r.lookAt(0,1,0),s.up.set(0,0,1),s.lookAt(0,-1,0),a.up.set(0,1,0),a.lookAt(0,0,1),o.up.set(0,1,0),o.lookAt(0,0,-1);else{if(t!==Vn)throw new Error("THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: "+t);n.up.set(0,-1,0),n.lookAt(-1,0,0),i.up.set(0,-1,0),i.lookAt(1,0,0),r.up.set(0,0,1),r.lookAt(0,1,0),s.up.set(0,0,-1),s.lookAt(0,-1,0),a.up.set(0,-1,0),a.lookAt(0,0,1),o.up.set(0,-1,0),o.lookAt(0,0,-1)}for(const t of e)this.add(t),t.updateMatrixWorld()}update(t,e){null===this.parent&&this.updateMatrixWorld();const{renderTarget:n,activeMipmapLevel:i}=this;this.coordinateSystem!==t.coordinateSystem&&(this.coordinateSystem=t.coordinateSystem,this.updateCoordinateSystem());const[r,s,a,o,l,c]=this.children,h=t.getRenderTarget(),u=t.getActiveCubeFace(),d=t.getActiveMipmapLevel(),p=t.xr.enabled;t.xr.enabled=!1;const m=n.texture.generateMipmaps;n.texture.generateMipmaps=!1,t.setRenderTarget(n,0,i),t.render(e,r),t.setRenderTarget(n,1,i),t.render(e,s),t.setRenderTarget(n,2,i),t.render(e,a),t.setRenderTarget(n,3,i),t.render(e,o),t.setRenderTarget(n,4,i),t.render(e,l),n.texture.generateMipmaps=m,t.setRenderTarget(n,5,i),t.render(e,c),t.setRenderTarget(h,u,d),t.xr.enabled=p,n.texture.needsPMREMUpdate=!0}}class na extends bi{constructor(t,e,n,i,r,s,a,o,l,c){super(t=void 0!==t?t:[],e=void 0!==e?e:lt,n,i,r,s,a,o,l,c),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(t){this.image=t}}class ia extends Ei{constructor(t=1,e={}){super(t,t,e),this.isWebGLCubeRenderTarget=!0;const n={width:t,height:t,depth:1},i=[n,n,n,n,n,n];this.texture=new na(i,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==e.generateMipmaps&&e.generateMipmaps,this.texture.minFilter=void 0!==e.minFilter?e.minFilter:Mt}fromEquirectangularTexture(t,e){this.texture.type=e.type,this.texture.colorSpace=e.colorSpace,this.texture.generateMipmaps=e.generateMipmaps,this.texture.minFilter=e.minFilter,this.texture.magFilter=e.magFilter;const n={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"},i=new Gs(5,5,5),r=new Ys({name:"CubemapFromEquirect",uniforms:Ws(n.uniforms),vertexShader:n.vertexShader,fragmentShader:n.fragmentShader,side:d,blending:0});r.uniforms.tEquirect.value=e;const s=new Vs(i,r),a=e.minFilter;e.minFilter===wt&&(e.minFilter=Mt);return new ea(1,10,this).update(t,s),e.minFilter=a,s.geometry.dispose(),s.material.dispose(),this}clear(t,e,n,i){const r=t.getRenderTarget();for(let r=0;r<6;r++)t.setRenderTarget(this,r),t.clear(e,n,i);t.setRenderTarget(r)}}const ra=new Li,sa=new Li,aa=new ei;class oa{constructor(t=new Li(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,n,i){return this.normal.set(t,e,n),this.constant=i,this}setFromNormalAndCoplanarPoint(t,e){return this.normal.copy(t),this.constant=-e.dot(this.normal),this}setFromCoplanarPoints(t,e,n){const i=ra.subVectors(n,e).cross(sa.subVectors(t,e)).normalize();return this.setFromNormalAndCoplanarPoint(i,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(t).addScaledVector(this.normal,-this.distanceToPoint(t))}intersectLine(t,e){const n=t.delta(ra),i=this.normal.dot(n);if(0===i)return 0===this.distanceToPoint(t.start)?e.copy(t.start):null;const r=-(t.start.dot(this.normal)+this.constant)/i;return r<0||r>1?null:e.copy(t.start).addScaledVector(n,r)}intersectsLine(t){const e=this.distanceToPoint(t.start),n=this.distanceToPoint(t.end);return e<0&&n>0||n<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 n=e||aa.getNormalMatrix(t),i=this.coplanarPoint(ra).applyMatrix4(t),r=this.normal.applyMatrix3(n).normalize();return this.constant=-i.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 la=new Qi,ca=new Li;class ha{constructor(t=new oa,e=new oa,n=new oa,i=new oa,r=new oa,s=new oa){this.planes=[t,e,n,i,r,s]}set(t,e,n,i,r,s){const a=this.planes;return a[0].copy(t),a[1].copy(e),a[2].copy(n),a[3].copy(i),a[4].copy(r),a[5].copy(s),this}copy(t){const e=this.planes;for(let n=0;n<6;n++)e[n].copy(t.planes[n]);return this}setFromProjectionMatrix(t,e=2e3){const n=this.planes,i=t.elements,r=i[0],s=i[1],a=i[2],o=i[3],l=i[4],c=i[5],h=i[6],u=i[7],d=i[8],p=i[9],m=i[10],f=i[11],g=i[12],v=i[13],_=i[14],x=i[15];if(n[0].setComponents(o-r,u-l,f-d,x-g).normalize(),n[1].setComponents(o+r,u+l,f+d,x+g).normalize(),n[2].setComponents(o+s,u+c,f+p,x+v).normalize(),n[3].setComponents(o-s,u-c,f-p,x-v).normalize(),n[4].setComponents(o-a,u-h,f-m,x-_).normalize(),e===kn)n[5].setComponents(o+a,u+h,f+m,x+_).normalize();else{if(e!==Vn)throw new Error("THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: "+e);n[5].setComponents(a,h,m,_).normalize()}return this}intersectsObject(t){if(void 0!==t.boundingSphere)null===t.boundingSphere&&t.computeBoundingSphere(),la.copy(t.boundingSphere).applyMatrix4(t.matrixWorld);else{const e=t.geometry;null===e.boundingSphere&&e.computeBoundingSphere(),la.copy(e.boundingSphere).applyMatrix4(t.matrixWorld)}return this.intersectsSphere(la)}intersectsSprite(t){return la.center.set(0,0,0),la.radius=.7071067811865476,la.applyMatrix4(t.matrixWorld),this.intersectsSphere(la)}intersectsSphere(t){const e=this.planes,n=t.center,i=-t.radius;for(let t=0;t<6;t++){if(e[t].distanceToPoint(n)0?t.max.x:t.min.x,ca.y=i.normal.y>0?t.max.y:t.min.y,ca.z=i.normal.z>0?t.max.z:t.min.z,i.distanceToPoint(ca)<0)return!1}return!0}containsPoint(t){const e=this.planes;for(let n=0;n<6;n++)if(e[n].distanceToPoint(t)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function ua(){let t=null,e=!1,n=null,i=null;function r(e,s){n(e,s),i=t.requestAnimationFrame(r)}return{start:function(){!0!==e&&null!==n&&(i=t.requestAnimationFrame(r),e=!0)},stop:function(){t.cancelAnimationFrame(i),e=!1},setAnimationLoop:function(t){n=t},setContext:function(e){t=e}}}function da(t){const e=new WeakMap;return{get:function(t){return t.isInterleavedBufferAttribute&&(t=t.data),e.get(t)},remove:function(n){n.isInterleavedBufferAttribute&&(n=n.data);const i=e.get(n);i&&(t.deleteBuffer(i.buffer),e.delete(n))},update:function(n,i){if(n.isInterleavedBufferAttribute&&(n=n.data),n.isGLBufferAttribute){const t=e.get(n);return void((!t||t.versiont.start-e.start));let e=0;for(let t=1;t 0\n\tvec4 plane;\n\t#ifdef ALPHA_TO_COVERAGE\n\t\tfloat distanceToPlane, distanceGradient;\n\t\tfloat clipOpacity = 1.0;\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\tclipOpacity *= smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\tif ( clipOpacity == 0.0 ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tfloat unionClipOpacity = 1.0;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tdistanceToPlane = - dot( vClipPosition, plane.xyz ) + plane.w;\n\t\t\t\tdistanceGradient = fwidth( distanceToPlane ) / 2.0;\n\t\t\t\tunionClipOpacity *= 1.0 - smoothstep( - distanceGradient, distanceGradient, distanceToPlane );\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tclipOpacity *= 1.0 - unionClipOpacity;\n\t\t#endif\n\t\tdiffuseColor.a *= clipOpacity;\n\t\tif ( diffuseColor.a == 0.0 ) discard;\n\t#else\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < UNION_CLIPPING_PLANES; i ++ ) {\n\t\t\tplane = clippingPlanes[ i ];\n\t\t\tif ( dot( vClipPosition, plane.xyz ) > plane.w ) discard;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t\t#if UNION_CLIPPING_PLANES < NUM_CLIPPING_PLANES\n\t\t\tbool clipped = true;\n\t\t\t#pragma unroll_loop_start\n\t\t\tfor ( int i = UNION_CLIPPING_PLANES; i < NUM_CLIPPING_PLANES; i ++ ) {\n\t\t\t\tplane = clippingPlanes[ i ];\n\t\t\t\tclipped = ( dot( vClipPosition, plane.xyz ) > plane.w ) && clipped;\n\t\t\t}\n\t\t\t#pragma unroll_loop_end\n\t\t\tif ( clipped ) discard;\n\t\t#endif\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 ) || defined( USE_BATCHING_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 ) || defined( USE_BATCHING_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\n#ifdef USE_BATCHING_COLOR\n\tvec3 batchingColor = getBatchingColor( getIndirectIndex( gl_DrawID ) );\n\tvColor.xyz *= batchingColor.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};\n#ifdef USE_ALPHAHASH\n\tvarying vec3 vPosition;\n#endif\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}\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}\nvec3 BRDF_Lambert( const in vec3 diffuseColor ) {\n\treturn RECIPROCAL_PI * diffuseColor;\n}\nvec3 F_Schlick( const in vec3 f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n}\nfloat F_Schlick( const in float f0, const in float f90, const in float dotVH ) {\n\tfloat fresnel = exp2( ( - 5.55473 * dotVH - 6.98316 ) * dotVH );\n\treturn f0 * ( 1.0 - fresnel ) + ( f90 * fresnel );\n} // validated",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\thighp vec2 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_m0 - 2.0\n\t#define cubeUV_r1 0.8\n\t#define cubeUV_m1 - 1.0\n\t#define cubeUV_r4 0.4\n\t#define cubeUV_m4 2.0\n\t#define cubeUV_r5 0.305\n\t#define cubeUV_m5 3.0\n\t#define cubeUV_r6 0.21\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_TANGENT\n\tvec3 transformedTangent = objectTangent;\n#endif\n#ifdef USE_BATCHING\n\tmat3 bm = mat3( batchingMatrix );\n\ttransformedNormal /= vec3( dot( bm[ 0 ], bm[ 0 ] ), dot( bm[ 1 ], bm[ 1 ] ), dot( bm[ 2 ], bm[ 2 ] ) );\n\ttransformedNormal = bm * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = bm * transformedTangent;\n\t#endif\n#endif\n#ifdef USE_INSTANCING\n\tmat3 im = mat3( instanceMatrix );\n\ttransformedNormal /= vec3( dot( im[ 0 ], im[ 0 ] ), dot( im[ 1 ], im[ 1 ] ), dot( im[ 2 ], im[ 2 ] ) );\n\ttransformedNormal = im * transformedNormal;\n\t#ifdef USE_TANGENT\n\t\ttransformedTangent = im * transformedTangent;\n\t#endif\n#endif\ntransformedNormal = normalMatrix * transformedNormal;\n#ifdef FLIP_SIDED\n\ttransformedNormal = - transformedNormal;\n#endif\n#ifdef USE_TANGENT\n\ttransformedTangent = ( modelViewMatrix * vec4( transformedTangent, 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, vDisplacementMapUv ).x * displacementScale + displacementBias );\n#endif",emissivemap_fragment:"#ifdef USE_EMISSIVEMAP\n\tvec4 emissiveColor = texture2D( emissiveMap, vEmissiveMapUv );\n\ttotalEmissiveRadiance *= emissiveColor.rgb;\n#endif",emissivemap_pars_fragment:"#ifdef USE_EMISSIVEMAP\n\tuniform sampler2D emissiveMap;\n#endif",colorspace_fragment:"gl_FragColor = linearToOutputTexel( gl_FragColor );",colorspace_pars_fragment:"\nconst mat3 LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = mat3(\n\tvec3( 0.8224621, 0.177538, 0.0 ),\n\tvec3( 0.0331941, 0.9668058, 0.0 ),\n\tvec3( 0.0170827, 0.0723974, 0.9105199 )\n);\nconst mat3 LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.2249401, - 0.2249404, 0.0 ),\n\tvec3( - 0.0420569, 1.0420571, 0.0 ),\n\tvec3( - 0.0196376, - 0.0786361, 1.0982735 )\n);\nvec4 LinearSRGBToLinearDisplayP3( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_SRGB_TO_LINEAR_DISPLAY_P3, value.a );\n}\nvec4 LinearDisplayP3ToLinearSRGB( in vec4 value ) {\n\treturn vec4( value.rgb * LINEAR_DISPLAY_P3_TO_LINEAR_SRGB, value.a );\n}\nvec4 LinearTransferOETF( in vec4 value ) {\n\treturn value;\n}\nvec4 sRGBTransferOETF( 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, envMapRotation * 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\tuniform mat3 envMapRotation;\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:"#ifdef USE_ENVMAP\n\tvec3 getIBLIrradiance( const in vec3 normal ) {\n\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\tvec3 worldNormal = inverseTransformDirection( normal, viewMatrix );\n\t\t\tvec4 envMapColor = textureCubeUV( envMap, envMapRotation * 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#ifdef 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, envMapRotation * 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\t#ifdef USE_ANISOTROPY\n\t\tvec3 getIBLAnisotropyRadiance( const in vec3 viewDir, const in vec3 normal, const in float roughness, const in vec3 bitangent, const in float anisotropy ) {\n\t\t\t#ifdef ENVMAP_TYPE_CUBE_UV\n\t\t\t\tvec3 bentNormal = cross( bitangent, viewDir );\n\t\t\t\tbentNormal = normalize( cross( bentNormal, bitangent ) );\n\t\t\t\tbentNormal = normalize( mix( bentNormal, normal, pow2( pow2( 1.0 - anisotropy * ( 1.0 - roughness ) ) ) ) );\n\t\t\t\treturn getIBLRadiance( viewDir, bentNormal, roughness );\n\t\t\t#else\n\t\t\t\treturn vec3( 0.0 );\n\t\t\t#endif\n\t\t}\n\t#endif\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_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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in LambertMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, 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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, 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;\n#if defined( USE_LIGHT_PROBES )\n\tuniform vec3 lightProbe[ 9 ];\n#endif\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\tfloat distanceFalloff = 1.0 / max( pow( lightDistance, decayExponent ), 0.01 );\n\tif ( cutoffDistance > 0.0 ) {\n\t\tdistanceFalloff *= pow2( saturate( 1.0 - pow4( lightDistance / cutoffDistance ) ) );\n\t}\n\treturn distanceFalloff;\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, 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 vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = pointLight.position - geometryPosition;\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 vec3 geometryPosition, out IncidentLight light ) {\n\t\tvec3 lVector = spotLight.position - geometryPosition;\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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in ToonMaterial material, inout ReflectedLight reflectedLight ) {\n\tvec3 irradiance = getGradientIrradiance( geometryNormal, directLight.direction ) * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Toon( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, 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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in BlinnPhongMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n\treflectedLight.directSpecular += irradiance * BRDF_BlinnPhong( directLight.direction, geometryViewDir, geometryNormal, material.specularColor, material.specularShininess ) * material.specularStrength;\n}\nvoid RE_IndirectDiffuse_BlinnPhong( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, 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( nonPerturbedNormal ) ), abs( dFdy( nonPerturbedNormal ) ) );\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 USE_SPECULAR\n\t\tfloat specularIntensityFactor = specularIntensity;\n\t\tvec3 specularColorFactor = specularColor;\n\t\t#ifdef USE_SPECULAR_COLORMAP\n\t\t\tspecularColorFactor *= texture2D( specularColorMap, vSpecularColorMapUv ).rgb;\n\t\t#endif\n\t\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\t\tspecularIntensityFactor *= texture2D( specularIntensityMap, vSpecularIntensityMapUv ).a;\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, vClearcoatMapUv ).x;\n\t#endif\n\t#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\t\tmaterial.clearcoatRoughness *= texture2D( clearcoatRoughnessMap, vClearcoatRoughnessMapUv ).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_DISPERSION\n\tmaterial.dispersion = dispersion;\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, vIridescenceMapUv ).r;\n\t#endif\n\t#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\t\tmaterial.iridescenceThickness = (iridescenceThicknessMaximum - iridescenceThicknessMinimum) * texture2D( iridescenceThicknessMap, vIridescenceThicknessMapUv ).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_SHEEN_COLORMAP\n\t\tmaterial.sheenColor *= texture2D( sheenColorMap, vSheenColorMapUv ).rgb;\n\t#endif\n\tmaterial.sheenRoughness = clamp( sheenRoughness, 0.07, 1.0 );\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tmaterial.sheenRoughness *= texture2D( sheenRoughnessMap, vSheenRoughnessMapUv ).a;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\t#ifdef USE_ANISOTROPYMAP\n\t\tmat2 anisotropyMat = mat2( anisotropyVector.x, anisotropyVector.y, - anisotropyVector.y, anisotropyVector.x );\n\t\tvec3 anisotropyPolar = texture2D( anisotropyMap, vAnisotropyMapUv ).rgb;\n\t\tvec2 anisotropyV = anisotropyMat * normalize( 2.0 * anisotropyPolar.rg - vec2( 1.0 ) ) * anisotropyPolar.b;\n\t#else\n\t\tvec2 anisotropyV = anisotropyVector;\n\t#endif\n\tmaterial.anisotropy = length( anisotropyV );\n\tif( material.anisotropy == 0.0 ) {\n\t\tanisotropyV = vec2( 1.0, 0.0 );\n\t} else {\n\t\tanisotropyV /= material.anisotropy;\n\t\tmaterial.anisotropy = saturate( material.anisotropy );\n\t}\n\tmaterial.alphaT = mix( pow2( material.roughness ), 1.0, pow2( material.anisotropy ) );\n\tmaterial.anisotropyT = tbn[ 0 ] * anisotropyV.x + tbn[ 1 ] * anisotropyV.y;\n\tmaterial.anisotropyB = tbn[ 1 ] * anisotropyV.x - tbn[ 0 ] * anisotropyV.y;\n#endif",lights_physical_pars_fragment:"struct PhysicalMaterial {\n\tvec3 diffuseColor;\n\tfloat roughness;\n\tvec3 specularColor;\n\tfloat specularF90;\n\tfloat dispersion;\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\t#ifdef USE_ANISOTROPY\n\t\tfloat anisotropy;\n\t\tfloat alphaT;\n\t\tvec3 anisotropyT;\n\t\tvec3 anisotropyB;\n\t#endif\n};\nvec3 clearcoatSpecularDirect = vec3( 0.0 );\nvec3 clearcoatSpecularIndirect = vec3( 0.0 );\nvec3 sheenSpecularDirect = vec3( 0.0 );\nvec3 sheenSpecularIndirect = vec3(0.0 );\nvec3 Schlick_to_F0( const in vec3 f, const in float f90, const in float dotVH ) {\n float x = clamp( 1.0 - dotVH, 0.0, 1.0 );\n float x2 = x * x;\n float x5 = clamp( x * x2 * x2, 0.0, 0.9999 );\n return ( f - vec3( f90 ) * x5 ) / ( 1.0 - x5 );\n}\nfloat V_GGX_SmithCorrelated( const in float alpha, const in float dotNL, const in float dotNV ) {\n\tfloat a2 = pow2( alpha );\n\tfloat gv = dotNL * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNV ) );\n\tfloat gl = dotNV * sqrt( a2 + ( 1.0 - a2 ) * pow2( dotNL ) );\n\treturn 0.5 / max( gv + gl, EPSILON );\n}\nfloat D_GGX( const in float alpha, const in float dotNH ) {\n\tfloat a2 = pow2( alpha );\n\tfloat denom = pow2( dotNH ) * ( a2 - 1.0 ) + 1.0;\n\treturn RECIPROCAL_PI * a2 / pow2( denom );\n}\n#ifdef USE_ANISOTROPY\n\tfloat V_GGX_SmithCorrelated_Anisotropic( const in float alphaT, const in float alphaB, const in float dotTV, const in float dotBV, const in float dotTL, const in float dotBL, const in float dotNV, const in float dotNL ) {\n\t\tfloat gv = dotNL * length( vec3( alphaT * dotTV, alphaB * dotBV, dotNV ) );\n\t\tfloat gl = dotNV * length( vec3( alphaT * dotTL, alphaB * dotBL, dotNL ) );\n\t\tfloat v = 0.5 / ( gv + gl );\n\t\treturn saturate(v);\n\t}\n\tfloat D_GGX_Anisotropic( const in float alphaT, const in float alphaB, const in float dotNH, const in float dotTH, const in float dotBH ) {\n\t\tfloat a2 = alphaT * alphaB;\n\t\thighp vec3 v = vec3( alphaB * dotTH, alphaT * dotBH, a2 * dotNH );\n\t\thighp float v2 = dot( v, v );\n\t\tfloat w2 = a2 / v2;\n\t\treturn RECIPROCAL_PI * a2 * pow2 ( w2 );\n\t}\n#endif\n#ifdef USE_CLEARCOAT\n\tvec3 BRDF_GGX_Clearcoat( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material) {\n\t\tvec3 f0 = material.clearcoatF0;\n\t\tfloat f90 = material.clearcoatF90;\n\t\tfloat roughness = material.clearcoatRoughness;\n\t\tfloat alpha = pow2( roughness );\n\t\tvec3 halfDir = normalize( lightDir + viewDir );\n\t\tfloat dotNL = saturate( dot( normal, lightDir ) );\n\t\tfloat dotNV = saturate( dot( normal, viewDir ) );\n\t\tfloat dotNH = saturate( dot( normal, halfDir ) );\n\t\tfloat dotVH = saturate( dot( viewDir, halfDir ) );\n\t\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t\treturn F * ( V * D );\n\t}\n#endif\nvec3 BRDF_GGX( const in vec3 lightDir, const in vec3 viewDir, const in vec3 normal, const in PhysicalMaterial material ) {\n\tvec3 f0 = material.specularColor;\n\tfloat f90 = material.specularF90;\n\tfloat roughness = material.roughness;\n\tfloat alpha = pow2( roughness );\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 dotVH = saturate( dot( viewDir, halfDir ) );\n\tvec3 F = F_Schlick( f0, f90, dotVH );\n\t#ifdef USE_IRIDESCENCE\n\t\tF = mix( F, material.iridescenceFresnel, material.iridescence );\n\t#endif\n\t#ifdef USE_ANISOTROPY\n\t\tfloat dotTL = dot( material.anisotropyT, lightDir );\n\t\tfloat dotTV = dot( material.anisotropyT, viewDir );\n\t\tfloat dotTH = dot( material.anisotropyT, halfDir );\n\t\tfloat dotBL = dot( material.anisotropyB, lightDir );\n\t\tfloat dotBV = dot( material.anisotropyB, viewDir );\n\t\tfloat dotBH = dot( material.anisotropyB, halfDir );\n\t\tfloat V = V_GGX_SmithCorrelated_Anisotropic( material.alphaT, alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL );\n\t\tfloat D = D_GGX_Anisotropic( material.alphaT, alpha, dotNH, dotTH, dotBH );\n\t#else\n\t\tfloat V = V_GGX_SmithCorrelated( alpha, dotNL, dotNV );\n\t\tfloat D = D_GGX( alpha, dotNH );\n\t#endif\n\treturn F * ( V * D );\n}\nvec2 LTC_Uv( const in vec3 N, const in vec3 V, const in float roughness ) {\n\tconst float LUT_SIZE = 64.0;\n\tconst float LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE;\n\tconst float LUT_BIAS = 0.5 / LUT_SIZE;\n\tfloat dotNV = saturate( dot( N, V ) );\n\tvec2 uv = vec2( roughness, sqrt( 1.0 - dotNV ) );\n\tuv = uv * LUT_SCALE + LUT_BIAS;\n\treturn uv;\n}\nfloat LTC_ClippedSphereFormFactor( const in vec3 f ) {\n\tfloat l = length( f );\n\treturn max( ( l * l + f.z ) / ( l + 1.0 ), 0.0 );\n}\nvec3 LTC_EdgeVectorFormFactor( const in vec3 v1, const in vec3 v2 ) {\n\tfloat x = dot( v1, v2 );\n\tfloat y = abs( x );\n\tfloat a = 0.8543985 + ( 0.4965155 + 0.0145206 * y ) * y;\n\tfloat b = 3.4175940 + ( 4.1616724 + y ) * y;\n\tfloat v = a / b;\n\tfloat theta_sintheta = ( x > 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}\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\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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\t\tvec3 normal = geometryNormal;\n\t\tvec3 viewDir = geometryViewDir;\n\t\tvec3 position = geometryPosition;\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( 0, 1, 0 ),\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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight ) {\n\tfloat dotNL = saturate( dot( geometryNormal, directLight.direction ) );\n\tvec3 irradiance = dotNL * directLight.color;\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNLcc = saturate( dot( geometryClearcoatNormal, directLight.direction ) );\n\t\tvec3 ccIrradiance = dotNLcc * directLight.color;\n\t\tclearcoatSpecularDirect += ccIrradiance * BRDF_GGX_Clearcoat( directLight.direction, geometryViewDir, geometryClearcoatNormal, material );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularDirect += irradiance * BRDF_Sheen( directLight.direction, geometryViewDir, geometryNormal, material.sheenColor, material.sheenRoughness );\n\t#endif\n\treflectedLight.directSpecular += irradiance * BRDF_GGX( directLight.direction, geometryViewDir, geometryNormal, material );\n\treflectedLight.directDiffuse += irradiance * BRDF_Lambert( material.diffuseColor );\n}\nvoid RE_IndirectDiffuse_Physical( const in vec3 irradiance, const in vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, 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 vec3 geometryPosition, const in vec3 geometryNormal, const in vec3 geometryViewDir, const in vec3 geometryClearcoatNormal, const in PhysicalMaterial material, inout ReflectedLight reflectedLight) {\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatSpecularIndirect += clearcoatRadiance * EnvironmentBRDF( geometryClearcoatNormal, geometryViewDir, material.clearcoatF0, material.clearcoatF90, material.clearcoatRoughness );\n\t#endif\n\t#ifdef USE_SHEEN\n\t\tsheenSpecularIndirect += irradiance * material.sheenColor * IBLSheenBRDF( geometryNormal, geometryViewDir, 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( geometryNormal, geometryViewDir, material.specularColor, material.specularF90, material.iridescence, material.iridescenceFresnel, material.roughness, singleScattering, multiScattering );\n\t#else\n\t\tcomputeMultiscattering( geometryNormal, geometryViewDir, 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:"\nvec3 geometryPosition = - vViewPosition;\nvec3 geometryNormal = normal;\nvec3 geometryViewDir = ( isOrthographic ) ? vec3( 0, 0, 1 ) : normalize( vViewPosition );\nvec3 geometryClearcoatNormal = vec3( 0.0 );\n#ifdef USE_CLEARCOAT\n\tgeometryClearcoatNormal = clearcoatNormal;\n#endif\n#ifdef USE_IRIDESCENCE\n\tfloat dotNVi = saturate( dot( normal, geometryViewDir ) );\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, geometryPosition, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_POINT_LIGHT_SHADOWS )\n\t\tpointLightShadow = pointLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getPointShadow( pointShadowMap[ i ], pointLightShadow.shadowMapSize, pointLightShadow.shadowIntensity, pointLightShadow.shadowBias, pointLightShadow.shadowRadius, vPointShadowCoord[ i ], pointLightShadow.shadowCameraNear, pointLightShadow.shadowCameraFar ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, 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, geometryPosition, 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 *= ( directLight.visible && receiveShadow ) ? getShadow( spotShadowMap[ i ], spotLightShadow.shadowMapSize, spotLightShadow.shadowIntensity, spotLightShadow.shadowBias, spotLightShadow.shadowRadius, vSpotLightCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, 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, directLight );\n\t\t#if defined( USE_SHADOWMAP ) && ( UNROLLED_LOOP_INDEX < NUM_DIR_LIGHT_SHADOWS )\n\t\tdirectionalLightShadow = directionalLightShadows[ i ];\n\t\tdirectLight.color *= ( directLight.visible && receiveShadow ) ? getShadow( directionalShadowMap[ i ], directionalLightShadow.shadowMapSize, directionalLightShadow.shadowIntensity, directionalLightShadow.shadowBias, directionalLightShadow.shadowRadius, vDirectionalShadowCoord[ i ] ) : 1.0;\n\t\t#endif\n\t\tRE_Direct( directLight, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, 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, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, 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\t#if defined( USE_LIGHT_PROBES )\n\t\tirradiance += getLightProbeIrradiance( lightProbe, geometryNormal );\n\t#endif\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 ], geometryNormal );\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, vLightMapUv );\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( geometryNormal );\n\t#endif\n#endif\n#if defined( USE_ENVMAP ) && defined( RE_IndirectSpecular )\n\t#ifdef USE_ANISOTROPY\n\t\tradiance += getIBLAnisotropyRadiance( geometryViewDir, geometryNormal, material.roughness, material.anisotropyB, material.anisotropy );\n\t#else\n\t\tradiance += getIBLRadiance( geometryViewDir, geometryNormal, material.roughness );\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tclearcoatRadiance += getIBLRadiance( geometryViewDir, geometryClearcoatNormal, material.clearcoatRoughness );\n\t#endif\n#endif",lights_fragment_end:"#if defined( RE_IndirectDiffuse )\n\tRE_IndirectDiffuse( irradiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif\n#if defined( RE_IndirectSpecular )\n\tRE_IndirectSpecular( radiance, iblIrradiance, clearcoatRadiance, geometryPosition, geometryNormal, geometryViewDir, geometryClearcoatNormal, material, reflectedLight );\n#endif",logdepthbuf_fragment:"#if defined( USE_LOGDEPTHBUF )\n\tgl_FragDepth = vIsPerspective == 0.0 ? gl_FragCoord.z : log2( vFragDepth ) * logDepthBufFC * 0.5;\n#endif",logdepthbuf_pars_fragment:"#if defined( USE_LOGDEPTHBUF )\n\tuniform float logDepthBufFC;\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_pars_vertex:"#ifdef USE_LOGDEPTHBUF\n\tvarying float vFragDepth;\n\tvarying float vIsPerspective;\n#endif",logdepthbuf_vertex:"#ifdef USE_LOGDEPTHBUF\n\tvFragDepth = 1.0 + gl_Position.w;\n\tvIsPerspective = float( isPerspectiveMatrix( projectionMatrix ) );\n#endif",map_fragment:"#ifdef USE_MAP\n\tvec4 sampledDiffuseColor = texture2D( map, vMapUv );\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\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\t#if defined( USE_POINTS_UV )\n\t\tvec2 uv = vUv;\n\t#else\n\t\tvec2 uv = ( uvTransform * vec3( gl_PointCoord.x, 1.0 - gl_PointCoord.y, 1 ) ).xy;\n\t#endif\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_POINTS_UV )\n\tvarying vec2 vUv;\n#else\n\t#if defined( USE_MAP ) || defined( USE_ALPHAMAP )\n\t\tuniform mat3 uvTransform;\n\t#endif\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, vMetalnessMapUv );\n\tmetalnessFactor *= texelMetalness.b;\n#endif",metalnessmap_pars_fragment:"#ifdef USE_METALNESSMAP\n\tuniform sampler2D metalnessMap;\n#endif",morphinstance_vertex:"#ifdef USE_INSTANCING_MORPH\n\tfloat morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\tfloat morphTargetBaseInfluence = texelFetch( morphTexture, ivec2( 0, gl_InstanceID ), 0 ).r;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tmorphTargetInfluences[i] = texelFetch( morphTexture, ivec2( i + 1, gl_InstanceID ), 0 ).r;\n\t}\n#endif",morphcolor_vertex:"#if defined( USE_MORPHCOLORS )\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\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) objectNormal += getMorph( gl_VertexID, i, 1 ).xyz * morphTargetInfluences[ i ];\n\t}\n#endif",morphtarget_pars_vertex:"#ifdef USE_MORPHTARGETS\n\t#ifndef USE_INSTANCING_MORPH\n\t\tuniform float morphTargetBaseInfluence;\n\t\tuniform float morphTargetInfluences[ MORPHTARGETS_COUNT ];\n\t#endif\n\tuniform sampler2DArray morphTargetsTexture;\n\tuniform ivec2 morphTargetsTextureSize;\n\tvec4 getMorph( const in int vertexIndex, const in int morphTargetIndex, const in int offset ) {\n\t\tint texelIndex = vertexIndex * MORPHTARGETS_TEXTURE_STRIDE + offset;\n\t\tint y = texelIndex / morphTargetsTextureSize.x;\n\t\tint x = texelIndex - y * morphTargetsTextureSize.x;\n\t\tivec3 morphUV = ivec3( x, y, morphTargetIndex );\n\t\treturn texelFetch( morphTargetsTexture, morphUV, 0 );\n\t}\n#endif",morphtarget_vertex:"#ifdef USE_MORPHTARGETS\n\ttransformed *= morphTargetBaseInfluence;\n\tfor ( int i = 0; i < MORPHTARGETS_COUNT; i ++ ) {\n\t\tif ( morphTargetInfluences[ i ] != 0.0 ) transformed += getMorph( gl_VertexID, i, 0 ).xyz * morphTargetInfluences[ i ];\n\t}\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 *= faceDirection;\n\t#endif\n#endif\n#if defined( USE_NORMALMAP_TANGENTSPACE ) || defined( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY )\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn = getTangentFrame( - vViewPosition, normal,\n\t\t#if defined( USE_NORMALMAP )\n\t\t\tvNormalMapUv\n\t\t#elif defined( USE_CLEARCOAT_NORMALMAP )\n\t\t\tvClearcoatNormalMapUv\n\t\t#else\n\t\t\tvUv\n\t\t#endif\n\t\t);\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn[0] *= faceDirection;\n\t\ttbn[1] *= faceDirection;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\t#ifdef USE_TANGENT\n\t\tmat3 tbn2 = mat3( normalize( vTangent ), normalize( vBitangent ), normal );\n\t#else\n\t\tmat3 tbn2 = getTangentFrame( - vViewPosition, normal, vClearcoatNormalMapUv );\n\t#endif\n\t#if defined( DOUBLE_SIDED ) && ! defined( FLAT_SHADED )\n\t\ttbn2[0] *= faceDirection;\n\t\ttbn2[1] *= faceDirection;\n\t#endif\n#endif\nvec3 nonPerturbedNormal = normal;",normal_fragment_maps:"#ifdef USE_NORMALMAP_OBJECTSPACE\n\tnormal = texture2D( normalMap, vNormalMapUv ).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( USE_NORMALMAP_TANGENTSPACE )\n\tvec3 mapN = texture2D( normalMap, vNormalMapUv ).xyz * 2.0 - 1.0;\n\tmapN.xy *= normalScale;\n\tnormal = normalize( tbn * mapN );\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 USE_NORMALMAP_OBJECTSPACE\n\tuniform mat3 normalMatrix;\n#endif\n#if ! defined ( USE_TANGENT ) && ( defined ( USE_NORMALMAP_TANGENTSPACE ) || defined ( USE_CLEARCOAT_NORMALMAP ) || defined( USE_ANISOTROPY ) )\n\tmat3 getTangentFrame( vec3 eye_pos, vec3 surf_norm, vec2 uv ) {\n\t\tvec3 q0 = dFdx( eye_pos.xyz );\n\t\tvec3 q1 = dFdy( eye_pos.xyz );\n\t\tvec2 st0 = dFdx( uv.st );\n\t\tvec2 st1 = dFdy( uv.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 : inversesqrt( det );\n\t\treturn mat3( T * scale, B * scale, N );\n\t}\n#endif",clearcoat_normal_fragment_begin:"#ifdef USE_CLEARCOAT\n\tvec3 clearcoatNormal = nonPerturbedNormal;\n#endif",clearcoat_normal_fragment_maps:"#ifdef USE_CLEARCOAT_NORMALMAP\n\tvec3 clearcoatMapN = texture2D( clearcoatNormalMap, vClearcoatNormalMapUv ).xyz * 2.0 - 1.0;\n\tclearcoatMapN.xy *= clearcoatNormalScale;\n\tclearcoatNormal = normalize( tbn2 * clearcoatMapN );\n#endif",clearcoat_pars_fragment:"#ifdef USE_CLEARCOATMAP\n\tuniform sampler2D clearcoatMap;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform sampler2D clearcoatNormalMap;\n\tuniform vec2 clearcoatNormalScale;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform sampler2D clearcoatRoughnessMap;\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",opaque_fragment:"#ifdef OPAQUE\ndiffuseColor.a = 1.0;\n#endif\n#ifdef USE_TRANSMISSION\ndiffuseColor.a *= material.transmissionAlpha;\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.;const float ShiftRight8 = 1. / 256.;\nconst float Inv255 = 1. / 255.;\nconst vec4 PackFactors = vec4( 1.0, 256.0, 256.0 * 256.0, 256.0 * 256.0 * 256.0 );\nconst vec2 UnpackFactors2 = vec2( UnpackDownscale, 1.0 / PackFactors.g );\nconst vec3 UnpackFactors3 = vec3( UnpackDownscale / PackFactors.rg, 1.0 / PackFactors.b );\nconst vec4 UnpackFactors4 = vec4( UnpackDownscale / PackFactors.rgb, 1.0 / PackFactors.a );\nvec4 packDepthToRGBA( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec4( 0., 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec4( 1., 1., 1., 1. );\n\tfloat vuf;\n\tfloat af = modf( v * PackFactors.a, vuf );\n\tfloat bf = modf( vuf * ShiftRight8, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec4( vuf * Inv255, gf * PackUpscale, bf * PackUpscale, af );\n}\nvec3 packDepthToRGB( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec3( 0., 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec3( 1., 1., 1. );\n\tfloat vuf;\n\tfloat bf = modf( v * PackFactors.b, vuf );\n\tfloat gf = modf( vuf * ShiftRight8, vuf );\n\treturn vec3( vuf * Inv255, gf * PackUpscale, bf );\n}\nvec2 packDepthToRG( const in float v ) {\n\tif( v <= 0.0 )\n\t\treturn vec2( 0., 0. );\n\tif( v >= 1.0 )\n\t\treturn vec2( 1., 1. );\n\tfloat vuf;\n\tfloat gf = modf( v * 256., vuf );\n\treturn vec2( vuf * Inv255, gf );\n}\nfloat unpackRGBAToDepth( const in vec4 v ) {\n\treturn dot( v, UnpackFactors4 );\n}\nfloat unpackRGBToDepth( const in vec3 v ) {\n\treturn dot( v, UnpackFactors3 );\n}\nfloat unpackRGToDepth( const in vec2 v ) {\n\treturn v.r * UnpackFactors2.r + v.g * UnpackFactors2.g;\n}\nvec4 pack2HalfToRGBA( const in 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( const in 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 depth, const in float near, const in float far ) {\n\treturn depth * ( 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 depth, const in float near, const in float far ) {\n\treturn ( near * far ) / ( ( far - near ) * depth - 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_BATCHING\n\tmvPosition = batchingMatrix * mvPosition;\n#endif\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, vRoughnessMapUv );\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 shadowIntensity;\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 shadowIntensity;\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 shadowIntensity;\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 shadowIntensity, 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\tbool inFrustum = shadowCoord.x >= 0.0 && shadowCoord.x <= 1.0 && shadowCoord.y >= 0.0 && shadowCoord.y <= 1.0;\n\t\tbool frustumTest = inFrustum && shadowCoord.z <= 1.0;\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 texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, -dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.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 texture2DCompare( shadowMap, uv + vec2( 2.0 * dx, 2.0 * dy ), shadowCoord.z ),\n\t\t\t\t\t\t f.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 mix( 1.0, shadow, shadowIntensity );\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 shadowIntensity, float shadowBias, float shadowRadius, vec4 shadowCoord, float shadowCameraNear, float shadowCameraFar ) {\n\t\tfloat shadow = 1.0;\n\t\tvec3 lightToPosition = shadowCoord.xyz;\n\t\t\n\t\tfloat lightToPositionLength = length( lightToPosition );\n\t\tif ( lightToPositionLength - shadowCameraFar <= 0.0 && lightToPositionLength - shadowCameraNear >= 0.0 ) {\n\t\t\tfloat dp = ( lightToPositionLength - shadowCameraNear ) / ( shadowCameraFar - shadowCameraNear );\t\t\tdp += shadowBias;\n\t\t\tvec3 bd3D = normalize( lightToPosition );\n\t\t\tvec2 texelSize = vec2( 1.0 ) / ( shadowMapSize * vec2( 4.0, 2.0 ) );\n\t\t\t#if defined( SHADOWMAP_TYPE_PCF ) || defined( SHADOWMAP_TYPE_PCF_SOFT ) || defined( SHADOWMAP_TYPE_VSM )\n\t\t\t\tvec2 offset = vec2( - 1, 1 ) * shadowRadius * texelSize.y;\n\t\t\t\tshadow = (\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yyx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxy, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.xxx, texelSize.y ), dp ) +\n\t\t\t\t\ttexture2DCompare( shadowMap, cubeToUV( bd3D + offset.yxx, texelSize.y ), dp )\n\t\t\t\t) * ( 1.0 / 9.0 );\n\t\t\t#else\n\t\t\t\tshadow = texture2DCompare( shadowMap, cubeToUV( bd3D, texelSize.y ), dp );\n\t\t\t#endif\n\t\t}\n\t\treturn mix( 1.0, shadow, shadowIntensity );\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 shadowIntensity;\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 shadowIntensity;\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 shadowIntensity;\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_DIR_LIGHT_SHADOWS > 0 || NUM_POINT_LIGHT_SHADOWS > 0 ) ) || ( NUM_SPOT_LIGHT_COORDS > 0 )\n\tvec3 shadowWorldNormal = inverseTransformDirection( transformedNormal, viewMatrix );\n\tvec4 shadowWorldPosition;\n#endif\n#if defined( USE_SHADOWMAP )\n\t#if NUM_DIR_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_DIR_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * directionalLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvDirectionalShadowCoord[ i ] = directionalShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n\t#if NUM_POINT_LIGHT_SHADOWS > 0\n\t\t#pragma unroll_loop_start\n\t\tfor ( int i = 0; i < NUM_POINT_LIGHT_SHADOWS; i ++ ) {\n\t\t\tshadowWorldPosition = worldPosition + vec4( shadowWorldNormal * pointLightShadows[ i ].shadowNormalBias, 0 );\n\t\t\tvPointShadowCoord[ i ] = pointShadowMatrix[ i ] * shadowWorldPosition;\n\t\t}\n\t\t#pragma unroll_loop_end\n\t#endif\n#endif\n#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#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.shadowIntensity, 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.shadowIntensity, 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.shadowIntensity, 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\tmat4 getBoneMatrix( const in float i ) {\n\t\tint size = textureSize( boneTexture, 0 ).x;\n\t\tint j = int( i ) * 4;\n\t\tint x = j % size;\n\t\tint y = j / size;\n\t\tvec4 v1 = texelFetch( boneTexture, ivec2( x, y ), 0 );\n\t\tvec4 v2 = texelFetch( boneTexture, ivec2( x + 1, y ), 0 );\n\t\tvec4 v3 = texelFetch( boneTexture, ivec2( x + 2, y ), 0 );\n\t\tvec4 v4 = texelFetch( boneTexture, ivec2( x + 3, y ), 0 );\n\t\treturn mat4( v1, v2, v3, v4 );\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, vSpecularMapUv );\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 saturate( toneMappingExposure * color );\n}\nvec3 ReinhardToneMapping( vec3 color ) {\n\tcolor *= toneMappingExposure;\n\treturn saturate( color / ( vec3( 1.0 ) + color ) );\n}\nvec3 CineonToneMapping( 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( 1.60475, -0.10208, -0.00327 ),\t\tvec3( -0.53108, 1.10813, -0.07276 ),\n\t\tvec3( -0.07367, -0.00605, 1.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}\nconst mat3 LINEAR_REC2020_TO_LINEAR_SRGB = mat3(\n\tvec3( 1.6605, - 0.1246, - 0.0182 ),\n\tvec3( - 0.5876, 1.1329, - 0.1006 ),\n\tvec3( - 0.0728, - 0.0083, 1.1187 )\n);\nconst mat3 LINEAR_SRGB_TO_LINEAR_REC2020 = mat3(\n\tvec3( 0.6274, 0.0691, 0.0164 ),\n\tvec3( 0.3293, 0.9195, 0.0880 ),\n\tvec3( 0.0433, 0.0113, 0.8956 )\n);\nvec3 agxDefaultContrastApprox( vec3 x ) {\n\tvec3 x2 = x * x;\n\tvec3 x4 = x2 * x2;\n\treturn + 15.5 * x4 * x2\n\t\t- 40.14 * x4 * x\n\t\t+ 31.96 * x4\n\t\t- 6.868 * x2 * x\n\t\t+ 0.4298 * x2\n\t\t+ 0.1191 * x\n\t\t- 0.00232;\n}\nvec3 AgXToneMapping( vec3 color ) {\n\tconst mat3 AgXInsetMatrix = mat3(\n\t\tvec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ),\n\t\tvec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ),\n\t\tvec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 )\n\t);\n\tconst mat3 AgXOutsetMatrix = mat3(\n\t\tvec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ),\n\t\tvec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ),\n\t\tvec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 )\n\t);\n\tconst float AgxMinEv = - 12.47393;\tconst float AgxMaxEv = 4.026069;\n\tcolor *= toneMappingExposure;\n\tcolor = LINEAR_SRGB_TO_LINEAR_REC2020 * color;\n\tcolor = AgXInsetMatrix * color;\n\tcolor = max( color, 1e-10 );\tcolor = log2( color );\n\tcolor = ( color - AgxMinEv ) / ( AgxMaxEv - AgxMinEv );\n\tcolor = clamp( color, 0.0, 1.0 );\n\tcolor = agxDefaultContrastApprox( color );\n\tcolor = AgXOutsetMatrix * color;\n\tcolor = pow( max( vec3( 0.0 ), color ), vec3( 2.2 ) );\n\tcolor = LINEAR_REC2020_TO_LINEAR_SRGB * color;\n\tcolor = clamp( color, 0.0, 1.0 );\n\treturn color;\n}\nvec3 NeutralToneMapping( vec3 color ) {\n\tconst float StartCompression = 0.8 - 0.04;\n\tconst float Desaturation = 0.15;\n\tcolor *= toneMappingExposure;\n\tfloat x = min( color.r, min( color.g, color.b ) );\n\tfloat offset = x < 0.08 ? x - 6.25 * x * x : 0.04;\n\tcolor -= offset;\n\tfloat peak = max( color.r, max( color.g, color.b ) );\n\tif ( peak < StartCompression ) return color;\n\tfloat d = 1. - StartCompression;\n\tfloat newPeak = 1. - d * d / ( peak + d - StartCompression );\n\tcolor *= newPeak / peak;\n\tfloat g = 1. - 1. / ( Desaturation * ( peak - newPeak ) + 1. );\n\treturn mix( color, vec3( newPeak ), g );\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, vTransmissionMapUv ).r;\n\t#endif\n\t#ifdef USE_THICKNESSMAP\n\t\tmaterial.thickness *= texture2D( thicknessMap, vThicknessMapUv ).g;\n\t#endif\n\tvec3 pos = vWorldPosition;\n\tvec3 v = normalize( cameraPosition - pos );\n\tvec3 n = inverseTransformDirection( normal, viewMatrix );\n\tvec4 transmitted = getIBLVolumeRefraction(\n\t\tn, v, material.roughness, material.diffuseColor, material.specularColor, material.specularF90,\n\t\tpos, modelMatrix, viewMatrix, projectionMatrix, material.dispersion, material.ior, material.thickness,\n\t\tmaterial.attenuationColor, material.attenuationDistance );\n\tmaterial.transmissionAlpha = mix( material.transmissionAlpha, transmitted.a, material.transmission );\n\ttotalDiffuse = mix( totalDiffuse, transmitted.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\tfloat w0( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - a + 3.0 ) - 3.0 ) + 1.0 );\n\t}\n\tfloat w1( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * ( 3.0 * a - 6.0 ) + 4.0 );\n\t}\n\tfloat w2( float a ){\n\t\treturn ( 1.0 / 6.0 ) * ( a * ( a * ( - 3.0 * a + 3.0 ) + 3.0 ) + 1.0 );\n\t}\n\tfloat w3( float a ) {\n\t\treturn ( 1.0 / 6.0 ) * ( a * a * a );\n\t}\n\tfloat g0( float a ) {\n\t\treturn w0( a ) + w1( a );\n\t}\n\tfloat g1( float a ) {\n\t\treturn w2( a ) + w3( a );\n\t}\n\tfloat h0( float a ) {\n\t\treturn - 1.0 + w1( a ) / ( w0( a ) + w1( a ) );\n\t}\n\tfloat h1( float a ) {\n\t\treturn 1.0 + w3( a ) / ( w2( a ) + w3( a ) );\n\t}\n\tvec4 bicubic( sampler2D tex, vec2 uv, vec4 texelSize, float lod ) {\n\t\tuv = uv * texelSize.zw + 0.5;\n\t\tvec2 iuv = floor( uv );\n\t\tvec2 fuv = fract( uv );\n\t\tfloat g0x = g0( fuv.x );\n\t\tfloat g1x = g1( fuv.x );\n\t\tfloat h0x = h0( fuv.x );\n\t\tfloat h1x = h1( fuv.x );\n\t\tfloat h0y = h0( fuv.y );\n\t\tfloat h1y = h1( fuv.y );\n\t\tvec2 p0 = ( vec2( iuv.x + h0x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p1 = ( vec2( iuv.x + h1x, iuv.y + h0y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p2 = ( vec2( iuv.x + h0x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\tvec2 p3 = ( vec2( iuv.x + h1x, iuv.y + h1y ) - 0.5 ) * texelSize.xy;\n\t\treturn g0( fuv.y ) * ( g0x * textureLod( tex, p0, lod ) + g1x * textureLod( tex, p1, lod ) ) +\n\t\t\tg1( fuv.y ) * ( g0x * textureLod( tex, p2, lod ) + g1x * textureLod( tex, p3, lod ) );\n\t}\n\tvec4 textureBicubic( sampler2D sampler, vec2 uv, float lod ) {\n\t\tvec2 fLodSize = vec2( textureSize( sampler, int( lod ) ) );\n\t\tvec2 cLodSize = vec2( textureSize( sampler, int( lod + 1.0 ) ) );\n\t\tvec2 fLodSizeInv = 1.0 / fLodSize;\n\t\tvec2 cLodSizeInv = 1.0 / cLodSize;\n\t\tvec4 fSample = bicubic( sampler, uv, vec4( fLodSizeInv, fLodSize ), floor( lod ) );\n\t\tvec4 cSample = bicubic( sampler, uv, vec4( cLodSizeInv, cLodSize ), ceil( lod ) );\n\t\treturn mix( fSample, cSample, fract( lod ) );\n\t}\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 lod = log2( transmissionSamplerSize.x ) * applyIorToRoughness( roughness, ior );\n\t\treturn textureBicubic( transmissionSamplerMap, fragCoord.xy, lod );\n\t}\n\tvec3 volumeAttenuation( const in float transmissionDistance, const in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tif ( isinf( attenuationDistance ) ) {\n\t\t\treturn vec3( 1.0 );\n\t\t} else {\n\t\t\tvec3 attenuationCoefficient = -log( attenuationColor ) / attenuationDistance;\n\t\t\tvec3 transmittance = exp( - attenuationCoefficient * transmissionDistance );\t\t\treturn transmittance;\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 dispersion, const in float ior, const in float thickness,\n\t\tconst in vec3 attenuationColor, const in float attenuationDistance ) {\n\t\tvec4 transmittedLight;\n\t\tvec3 transmittance;\n\t\t#ifdef USE_DISPERSION\n\t\t\tfloat halfSpread = ( ior - 1.0 ) * 0.025 * dispersion;\n\t\t\tvec3 iors = vec3( ior - halfSpread, ior, ior + halfSpread );\n\t\t\tfor ( int i = 0; i < 3; i ++ ) {\n\t\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, iors[ i ], modelMatrix );\n\t\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\n\t\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\t\trefractionCoords += 1.0;\n\t\t\t\trefractionCoords /= 2.0;\n\t\t\n\t\t\t\tvec4 transmissionSample = getTransmissionSample( refractionCoords, roughness, iors[ i ] );\n\t\t\t\ttransmittedLight[ i ] = transmissionSample[ i ];\n\t\t\t\ttransmittedLight.a += transmissionSample.a;\n\t\t\t\ttransmittance[ i ] = diffuseColor[ i ] * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance )[ i ];\n\t\t\t}\n\t\t\ttransmittedLight.a /= 3.0;\n\t\t\n\t\t#else\n\t\t\n\t\t\tvec3 transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix );\n\t\t\tvec3 refractedRayExit = position + transmissionRay;\n\t\t\tvec4 ndcPos = projMatrix * viewMatrix * vec4( refractedRayExit, 1.0 );\n\t\t\tvec2 refractionCoords = ndcPos.xy / ndcPos.w;\n\t\t\trefractionCoords += 1.0;\n\t\t\trefractionCoords /= 2.0;\n\t\t\ttransmittedLight = getTransmissionSample( refractionCoords, roughness, ior );\n\t\t\ttransmittance = diffuseColor * volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance );\n\t\t\n\t\t#endif\n\t\tvec3 attenuatedColor = transmittance * transmittedLight.rgb;\n\t\tvec3 F = EnvironmentBRDF( n, v, specularColor, specularF90, roughness );\n\t\tfloat transmittanceFactor = ( transmittance.r + transmittance.g + transmittance.b ) / 3.0;\n\t\treturn vec4( ( 1.0 - F ) * attenuatedColor, 1.0 - ( 1.0 - transmittedLight.a ) * transmittanceFactor );\n\t}\n#endif",uv_pars_fragment:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_pars_vertex:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvarying vec2 vUv;\n#endif\n#ifdef USE_MAP\n\tuniform mat3 mapTransform;\n\tvarying vec2 vMapUv;\n#endif\n#ifdef USE_ALPHAMAP\n\tuniform mat3 alphaMapTransform;\n\tvarying vec2 vAlphaMapUv;\n#endif\n#ifdef USE_LIGHTMAP\n\tuniform mat3 lightMapTransform;\n\tvarying vec2 vLightMapUv;\n#endif\n#ifdef USE_AOMAP\n\tuniform mat3 aoMapTransform;\n\tvarying vec2 vAoMapUv;\n#endif\n#ifdef USE_BUMPMAP\n\tuniform mat3 bumpMapTransform;\n\tvarying vec2 vBumpMapUv;\n#endif\n#ifdef USE_NORMALMAP\n\tuniform mat3 normalMapTransform;\n\tvarying vec2 vNormalMapUv;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tuniform mat3 displacementMapTransform;\n\tvarying vec2 vDisplacementMapUv;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tuniform mat3 emissiveMapTransform;\n\tvarying vec2 vEmissiveMapUv;\n#endif\n#ifdef USE_METALNESSMAP\n\tuniform mat3 metalnessMapTransform;\n\tvarying vec2 vMetalnessMapUv;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tuniform mat3 roughnessMapTransform;\n\tvarying vec2 vRoughnessMapUv;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tuniform mat3 anisotropyMapTransform;\n\tvarying vec2 vAnisotropyMapUv;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tuniform mat3 clearcoatMapTransform;\n\tvarying vec2 vClearcoatMapUv;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tuniform mat3 clearcoatNormalMapTransform;\n\tvarying vec2 vClearcoatNormalMapUv;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tuniform mat3 clearcoatRoughnessMapTransform;\n\tvarying vec2 vClearcoatRoughnessMapUv;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tuniform mat3 sheenColorMapTransform;\n\tvarying vec2 vSheenColorMapUv;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tuniform mat3 sheenRoughnessMapTransform;\n\tvarying vec2 vSheenRoughnessMapUv;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tuniform mat3 iridescenceMapTransform;\n\tvarying vec2 vIridescenceMapUv;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tuniform mat3 iridescenceThicknessMapTransform;\n\tvarying vec2 vIridescenceThicknessMapUv;\n#endif\n#ifdef USE_SPECULARMAP\n\tuniform mat3 specularMapTransform;\n\tvarying vec2 vSpecularMapUv;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tuniform mat3 specularColorMapTransform;\n\tvarying vec2 vSpecularColorMapUv;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tuniform mat3 specularIntensityMapTransform;\n\tvarying vec2 vSpecularIntensityMapUv;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tuniform mat3 transmissionMapTransform;\n\tvarying vec2 vTransmissionMapUv;\n#endif\n#ifdef USE_THICKNESSMAP\n\tuniform mat3 thicknessMapTransform;\n\tvarying vec2 vThicknessMapUv;\n#endif",uv_vertex:"#if defined( USE_UV ) || defined( USE_ANISOTROPY )\n\tvUv = vec3( uv, 1 ).xy;\n#endif\n#ifdef USE_MAP\n\tvMapUv = ( mapTransform * vec3( MAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ALPHAMAP\n\tvAlphaMapUv = ( alphaMapTransform * vec3( ALPHAMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_LIGHTMAP\n\tvLightMapUv = ( lightMapTransform * vec3( LIGHTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_AOMAP\n\tvAoMapUv = ( aoMapTransform * vec3( AOMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_BUMPMAP\n\tvBumpMapUv = ( bumpMapTransform * vec3( BUMPMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_NORMALMAP\n\tvNormalMapUv = ( normalMapTransform * vec3( NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_DISPLACEMENTMAP\n\tvDisplacementMapUv = ( displacementMapTransform * vec3( DISPLACEMENTMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_EMISSIVEMAP\n\tvEmissiveMapUv = ( emissiveMapTransform * vec3( EMISSIVEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_METALNESSMAP\n\tvMetalnessMapUv = ( metalnessMapTransform * vec3( METALNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ROUGHNESSMAP\n\tvRoughnessMapUv = ( roughnessMapTransform * vec3( ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_ANISOTROPYMAP\n\tvAnisotropyMapUv = ( anisotropyMapTransform * vec3( ANISOTROPYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOATMAP\n\tvClearcoatMapUv = ( clearcoatMapTransform * vec3( CLEARCOATMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_NORMALMAP\n\tvClearcoatNormalMapUv = ( clearcoatNormalMapTransform * vec3( CLEARCOAT_NORMALMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_CLEARCOAT_ROUGHNESSMAP\n\tvClearcoatRoughnessMapUv = ( clearcoatRoughnessMapTransform * vec3( CLEARCOAT_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCEMAP\n\tvIridescenceMapUv = ( iridescenceMapTransform * vec3( IRIDESCENCEMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_IRIDESCENCE_THICKNESSMAP\n\tvIridescenceThicknessMapUv = ( iridescenceThicknessMapTransform * vec3( IRIDESCENCE_THICKNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_COLORMAP\n\tvSheenColorMapUv = ( sheenColorMapTransform * vec3( SHEEN_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SHEEN_ROUGHNESSMAP\n\tvSheenRoughnessMapUv = ( sheenRoughnessMapTransform * vec3( SHEEN_ROUGHNESSMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULARMAP\n\tvSpecularMapUv = ( specularMapTransform * vec3( SPECULARMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_COLORMAP\n\tvSpecularColorMapUv = ( specularColorMapTransform * vec3( SPECULAR_COLORMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_SPECULAR_INTENSITYMAP\n\tvSpecularIntensityMapUv = ( specularIntensityMapTransform * vec3( SPECULAR_INTENSITYMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_TRANSMISSIONMAP\n\tvTransmissionMapUv = ( transmissionMapTransform * vec3( TRANSMISSIONMAP_UV, 1 ) ).xy;\n#endif\n#ifdef USE_THICKNESSMAP\n\tvThicknessMapUv = ( thicknessMapTransform * vec3( THICKNESSMAP_UV, 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_BATCHING\n\t\tworldPosition = batchingMatrix * worldPosition;\n\t#endif\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;\nuniform mat3 backgroundRotation;\nvarying vec3 vWorldDirection;\n#include \nvoid main() {\n\t#ifdef ENVMAP_TYPE_CUBE\n\t\tvec4 texColor = textureCube( envMap, backgroundRotation * vec3( flipEnvMap * vWorldDirection.x, vWorldDirection.yz ) );\n\t#elif defined( ENVMAP_TYPE_CUBE_UV )\n\t\tvec4 texColor = textureCubeUV( envMap, backgroundRotation * 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 \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\t#include \n\t#include \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 \n#include \nvarying vec2 vHighPrecisionZW;\nvoid main() {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \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\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#elif DEPTH_PACKING == 3202\n\t\tgl_FragColor = vec4( packDepthToRGB( fragCoordZ ), 1.0 );\n\t#elif DEPTH_PACKING == 3203\n\t\tgl_FragColor = vec4( packDepthToRG( fragCoordZ ), 0.0, 1.0 );\n\t#endif\n}",distanceRGBA_vert:"#define DISTANCE\nvarying vec3 vWorldPosition;\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#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 \n#include \nvoid main () {\n\tvec4 diffuseColor = vec4( 1.0 );\n\t#include \n\t#include \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 \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\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 \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tif ( mod( vLineDistance, totalSize ) > dashSize ) {\n\t\tdiscard;\n\t}\n\tvec3 outgoingLight = vec3( 0.0 );\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}",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#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\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\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, vLightMapUv );\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\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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \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\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 \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\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 \n#include \nvoid main() {\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\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( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\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#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvViewPosition = - mvPosition.xyz;\n#endif\n}",meshnormal_frag:"#define NORMAL\nuniform float opacity;\n#if defined( FLAT_SHADED ) || defined( USE_BUMPMAP ) || defined( USE_NORMALMAP_TANGENTSPACE )\n\tvarying vec3 vViewPosition;\n#endif\n#include \n#include \n#include \n#include \n#include \n#include \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( 0.0, 0.0, 0.0, opacity );\n\t#include \n\t#include \n\t#include \n\t#include \n\tgl_FragColor = vec4( packNormalToRGB( normal ), diffuseColor.a );\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\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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \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\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\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 USE_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 USE_SPECULAR\n\tuniform float specularIntensity;\n\tuniform vec3 specularColor;\n\t#ifdef USE_SPECULAR_COLORMAP\n\t\tuniform sampler2D specularColorMap;\n\t#endif\n\t#ifdef USE_SPECULAR_INTENSITYMAP\n\t\tuniform sampler2D specularIntensityMap;\n\t#endif\n#endif\n#ifdef USE_CLEARCOAT\n\tuniform float clearcoat;\n\tuniform float clearcoatRoughness;\n#endif\n#ifdef USE_DISPERSION\n\tuniform float dispersion;\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_SHEEN_COLORMAP\n\t\tuniform sampler2D sheenColorMap;\n\t#endif\n\t#ifdef USE_SHEEN_ROUGHNESSMAP\n\t\tuniform sampler2D sheenRoughnessMap;\n\t#endif\n#endif\n#ifdef USE_ANISOTROPY\n\tuniform vec2 anisotropyVector;\n\t#ifdef USE_ANISOTROPYMAP\n\t\tuniform sampler2D anisotropyMap;\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 \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \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\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 + sheenSpecularDirect + sheenSpecularIndirect;\n\t#endif\n\t#ifdef USE_CLEARCOAT\n\t\tfloat dotNVcc = saturate( dot( geometryClearcoatNormal, geometryViewDir ) );\n\t\tvec3 Fcc = F_Schlick( material.clearcoatF0, material.clearcoatF90, dotNVcc );\n\t\toutgoingLight = outgoingLight * ( 1.0 - material.clearcoat * Fcc ) + ( clearcoatSpecularDirect + clearcoatSpecularIndirect ) * 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\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\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \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}",points_vert:"uniform float size;\nuniform float scale;\n#include \n#include \n#include \n#include \n#include \n#include \n#ifdef USE_POINTS_UV\n\tvarying vec2 vUv;\n\tuniform mat3 uvTransform;\n#endif\nvoid main() {\n\t#ifdef USE_POINTS_UV\n\t\tvUv = ( uvTransform * vec3( uv, 1 ) ).xy;\n\t#endif\n\t#include \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 \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \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 \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}",shadow_frag:"uniform vec3 color;\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\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[ 3 ];\n\tvec2 scale = vec2( length( modelMatrix[ 0 ].xyz ), length( modelMatrix[ 1 ].xyz ) );\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 \n#include \nvoid main() {\n\tvec4 diffuseColor = vec4( diffuse, opacity );\n\t#include \n\tvec3 outgoingLight = vec3( 0.0 );\n\t#include \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}"},fa={common:{diffuse:{value:new ts(16777215)},opacity:{value:1},map:{value:null},mapTransform:{value:new ei},alphaMap:{value:null},alphaMapTransform:{value:new ei},alphaTest:{value:0}},specularmap:{specularMap:{value:null},specularMapTransform:{value:new ei}},envmap:{envMap:{value:null},envMapRotation:{value:new ei},flipEnvMap:{value:-1},reflectivity:{value:1},ior:{value:1.5},refractionRatio:{value:.98}},aomap:{aoMap:{value:null},aoMapIntensity:{value:1},aoMapTransform:{value:new ei}},lightmap:{lightMap:{value:null},lightMapIntensity:{value:1},lightMapTransform:{value:new ei}},bumpmap:{bumpMap:{value:null},bumpMapTransform:{value:new ei},bumpScale:{value:1}},normalmap:{normalMap:{value:null},normalMapTransform:{value:new ei},normalScale:{value:new ti(1,1)}},displacementmap:{displacementMap:{value:null},displacementMapTransform:{value:new ei},displacementScale:{value:1},displacementBias:{value:0}},emissivemap:{emissiveMap:{value:null},emissiveMapTransform:{value:new ei}},metalnessmap:{metalnessMap:{value:null},metalnessMapTransform:{value:new ei}},roughnessmap:{roughnessMap:{value:null},roughnessMapTransform:{value:new ei}},gradientmap:{gradientMap:{value:null}},fog:{fogDensity:{value:25e-5},fogNear:{value:1},fogFar:{value:2e3},fogColor:{value:new ts(16777215)}},lights:{ambientLightColor:{value:[]},lightProbe:{value:[]},directionalLights:{value:[],properties:{direction:{},color:{}}},directionalLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},directionalShadowMap:{value:[]},directionalShadowMatrix:{value:[]},spotLights:{value:[],properties:{color:{},position:{},direction:{},distance:{},coneCos:{},penumbraCos:{},decay:{}}},spotLightShadows:{value:[],properties:{shadowIntensity:1,shadowBias:{},shadowNormalBias:{},shadowRadius:{},shadowMapSize:{}}},spotLightMap:{value:[]},spotShadowMap:{value:[]},spotLightMatrix:{value:[]},pointLights:{value:[],properties:{color:{},position:{},decay:{},distance:{}}},pointLightShadows:{value:[],properties:{shadowIntensity:1,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 ts(16777215)},opacity:{value:1},size:{value:1},scale:{value:1},map:{value:null},alphaMap:{value:null},alphaMapTransform:{value:new ei},alphaTest:{value:0},uvTransform:{value:new ei}},sprite:{diffuse:{value:new ts(16777215)},opacity:{value:1},center:{value:new ti(.5,.5)},rotation:{value:0},map:{value:null},mapTransform:{value:new ei},alphaMap:{value:null},alphaMapTransform:{value:new ei},alphaTest:{value:0}}},ga={basic:{uniforms:Xs([fa.common,fa.specularmap,fa.envmap,fa.aomap,fa.lightmap,fa.fog]),vertexShader:ma.meshbasic_vert,fragmentShader:ma.meshbasic_frag},lambert:{uniforms:Xs([fa.common,fa.specularmap,fa.envmap,fa.aomap,fa.lightmap,fa.emissivemap,fa.bumpmap,fa.normalmap,fa.displacementmap,fa.fog,fa.lights,{emissive:{value:new ts(0)}}]),vertexShader:ma.meshlambert_vert,fragmentShader:ma.meshlambert_frag},phong:{uniforms:Xs([fa.common,fa.specularmap,fa.envmap,fa.aomap,fa.lightmap,fa.emissivemap,fa.bumpmap,fa.normalmap,fa.displacementmap,fa.fog,fa.lights,{emissive:{value:new ts(0)},specular:{value:new ts(1118481)},shininess:{value:30}}]),vertexShader:ma.meshphong_vert,fragmentShader:ma.meshphong_frag},standard:{uniforms:Xs([fa.common,fa.envmap,fa.aomap,fa.lightmap,fa.emissivemap,fa.bumpmap,fa.normalmap,fa.displacementmap,fa.roughnessmap,fa.metalnessmap,fa.fog,fa.lights,{emissive:{value:new ts(0)},roughness:{value:1},metalness:{value:0},envMapIntensity:{value:1}}]),vertexShader:ma.meshphysical_vert,fragmentShader:ma.meshphysical_frag},toon:{uniforms:Xs([fa.common,fa.aomap,fa.lightmap,fa.emissivemap,fa.bumpmap,fa.normalmap,fa.displacementmap,fa.gradientmap,fa.fog,fa.lights,{emissive:{value:new ts(0)}}]),vertexShader:ma.meshtoon_vert,fragmentShader:ma.meshtoon_frag},matcap:{uniforms:Xs([fa.common,fa.bumpmap,fa.normalmap,fa.displacementmap,fa.fog,{matcap:{value:null}}]),vertexShader:ma.meshmatcap_vert,fragmentShader:ma.meshmatcap_frag},points:{uniforms:Xs([fa.points,fa.fog]),vertexShader:ma.points_vert,fragmentShader:ma.points_frag},dashed:{uniforms:Xs([fa.common,fa.fog,{scale:{value:1},dashSize:{value:1},totalSize:{value:2}}]),vertexShader:ma.linedashed_vert,fragmentShader:ma.linedashed_frag},depth:{uniforms:Xs([fa.common,fa.displacementmap]),vertexShader:ma.depth_vert,fragmentShader:ma.depth_frag},normal:{uniforms:Xs([fa.common,fa.bumpmap,fa.normalmap,fa.displacementmap,{opacity:{value:1}}]),vertexShader:ma.meshnormal_vert,fragmentShader:ma.meshnormal_frag},sprite:{uniforms:Xs([fa.sprite,fa.fog]),vertexShader:ma.sprite_vert,fragmentShader:ma.sprite_frag},background:{uniforms:{uvTransform:{value:new ei},t2D:{value:null},backgroundIntensity:{value:1}},vertexShader:ma.background_vert,fragmentShader:ma.background_frag},backgroundCube:{uniforms:{envMap:{value:null},flipEnvMap:{value:-1},backgroundBlurriness:{value:0},backgroundIntensity:{value:1},backgroundRotation:{value:new ei}},vertexShader:ma.backgroundCube_vert,fragmentShader:ma.backgroundCube_frag},cube:{uniforms:{tCube:{value:null},tFlip:{value:-1},opacity:{value:1}},vertexShader:ma.cube_vert,fragmentShader:ma.cube_frag},equirect:{uniforms:{tEquirect:{value:null}},vertexShader:ma.equirect_vert,fragmentShader:ma.equirect_frag},distanceRGBA:{uniforms:Xs([fa.common,fa.displacementmap,{referencePosition:{value:new Li},nearDistance:{value:1},farDistance:{value:1e3}}]),vertexShader:ma.distanceRGBA_vert,fragmentShader:ma.distanceRGBA_frag},shadow:{uniforms:Xs([fa.lights,fa.fog,{color:{value:new ts(0)},opacity:{value:1}}]),vertexShader:ma.shadow_vert,fragmentShader:ma.shadow_frag}};ga.physical={uniforms:Xs([ga.standard.uniforms,{clearcoat:{value:0},clearcoatMap:{value:null},clearcoatMapTransform:{value:new ei},clearcoatNormalMap:{value:null},clearcoatNormalMapTransform:{value:new ei},clearcoatNormalScale:{value:new ti(1,1)},clearcoatRoughness:{value:0},clearcoatRoughnessMap:{value:null},clearcoatRoughnessMapTransform:{value:new ei},dispersion:{value:0},iridescence:{value:0},iridescenceMap:{value:null},iridescenceMapTransform:{value:new ei},iridescenceIOR:{value:1.3},iridescenceThicknessMinimum:{value:100},iridescenceThicknessMaximum:{value:400},iridescenceThicknessMap:{value:null},iridescenceThicknessMapTransform:{value:new ei},sheen:{value:0},sheenColor:{value:new ts(0)},sheenColorMap:{value:null},sheenColorMapTransform:{value:new ei},sheenRoughness:{value:1},sheenRoughnessMap:{value:null},sheenRoughnessMapTransform:{value:new ei},transmission:{value:0},transmissionMap:{value:null},transmissionMapTransform:{value:new ei},transmissionSamplerSize:{value:new ti},transmissionSamplerMap:{value:null},thickness:{value:0},thicknessMap:{value:null},thicknessMapTransform:{value:new ei},attenuationDistance:{value:0},attenuationColor:{value:new ts(0)},specularColor:{value:new ts(1,1,1)},specularColorMap:{value:null},specularColorMapTransform:{value:new ei},specularIntensity:{value:1},specularIntensityMap:{value:null},specularIntensityMapTransform:{value:new ei},anisotropyVector:{value:new ti},anisotropyMap:{value:null},anisotropyMapTransform:{value:new ei}}]),vertexShader:ma.meshphysical_vert,fragmentShader:ma.meshphysical_frag};const va={r:0,b:0,g:0},_a=new _r,xa=new lr;function ya(t,e,n,i,r,s,a){const o=new ts(0);let l,c,h=!0===s?0:1,p=null,m=0,f=null;function g(t){let i=!0===t.isScene?t.background:null;if(i&&i.isTexture){i=(t.backgroundBlurriness>0?n:e).get(i)}return i}function v(e,n){e.getRGB(va,js(t)),i.buffers.color.setClear(va.r,va.g,va.b,n,a)}return{getClearColor:function(){return o},setClearColor:function(t,e=1){o.set(t),h=e,v(o,h)},getClearAlpha:function(){return h},setClearAlpha:function(t){h=t,v(o,h)},render:function(e){let n=!1;const r=g(e);null===r?v(o,h):r&&r.isColor&&(v(r,1),n=!0);const s=t.xr.getEnvironmentBlendMode();"additive"===s?i.buffers.color.setClear(0,0,0,1,a):"alpha-blend"===s&&i.buffers.color.setClear(0,0,0,0,a),(t.autoClear||n)&&(i.buffers.depth.setTest(!0),i.buffers.depth.setMask(!0),i.buffers.color.setMask(!0),t.clear(t.autoClearColor,t.autoClearDepth,t.autoClearStencil))},addToRenderList:function(e,n){const i=g(n);i&&(i.isCubeTexture||i.mapping===dt)?(void 0===c&&(c=new Vs(new Gs(1,1,1),new Ys({name:"BackgroundCubeMaterial",uniforms:Ws(ga.backgroundCube.uniforms),vertexShader:ga.backgroundCube.vertexShader,fragmentShader:ga.backgroundCube.fragmentShader,side:d,depthTest:!1,depthWrite:!1,fog:!1})),c.geometry.deleteAttribute("normal"),c.geometry.deleteAttribute("uv"),c.onBeforeRender=function(t,e,n){this.matrixWorld.copyPosition(n.matrixWorld)},Object.defineProperty(c.material,"envMap",{get:function(){return this.uniforms.envMap.value}}),r.update(c)),_a.copy(n.backgroundRotation),_a.x*=-1,_a.y*=-1,_a.z*=-1,i.isCubeTexture&&!1===i.isRenderTargetTexture&&(_a.y*=-1,_a.z*=-1),c.material.uniforms.envMap.value=i,c.material.uniforms.flipEnvMap.value=i.isCubeTexture&&!1===i.isRenderTargetTexture?-1:1,c.material.uniforms.backgroundBlurriness.value=n.backgroundBlurriness,c.material.uniforms.backgroundIntensity.value=n.backgroundIntensity,c.material.uniforms.backgroundRotation.value.setFromMatrix4(xa.makeRotationFromEuler(_a)),c.material.toneMapped=mi.getTransfer(i.colorSpace)!==en,p===i&&m===i.version&&f===t.toneMapping||(c.material.needsUpdate=!0,p=i,m=i.version,f=t.toneMapping),c.layers.enableAll(),e.unshift(c,c.geometry,c.material,0,0,null)):i&&i.isTexture&&(void 0===l&&(l=new Vs(new pa(2,2),new Ys({name:"BackgroundMaterial",uniforms:Ws(ga.background.uniforms),vertexShader:ga.background.vertexShader,fragmentShader:ga.background.fragmentShader,side:u,depthTest:!1,depthWrite:!1,fog:!1})),l.geometry.deleteAttribute("normal"),Object.defineProperty(l.material,"map",{get:function(){return this.uniforms.t2D.value}}),r.update(l)),l.material.uniforms.t2D.value=i,l.material.uniforms.backgroundIntensity.value=n.backgroundIntensity,l.material.toneMapped=mi.getTransfer(i.colorSpace)!==en,!0===i.matrixAutoUpdate&&i.updateMatrix(),l.material.uniforms.uvTransform.value.copy(i.matrix),p===i&&m===i.version&&f===t.toneMapping||(l.material.needsUpdate=!0,p=i,m=i.version,f=t.toneMapping),l.layers.enableAll(),e.unshift(l,l.geometry,l.material,0,0,null))}}}function Ma(t,e){const n=t.getParameter(t.MAX_VERTEX_ATTRIBS),i={},r=c(null);let s=r,a=!1;function o(e){return t.bindVertexArray(e)}function l(e){return t.deleteVertexArray(e)}function c(t){const e=[],i=[],r=[];for(let t=0;t=0){const n=r[e];let i=a[e];if(void 0===i&&("instanceMatrix"===e&&t.instanceMatrix&&(i=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(i=t.instanceColor)),void 0===n)return!0;if(n.attribute!==i)return!0;if(i&&n.data!==i.data)return!0;o++}}return s.attributesNum!==o||s.index!==i}(n,f,l,g),v&&function(t,e,n,i){const r={},a=e.attributes;let o=0;const l=n.getAttributes();for(const e in l){if(l[e].location>=0){let n=a[e];void 0===n&&("instanceMatrix"===e&&t.instanceMatrix&&(n=t.instanceMatrix),"instanceColor"===e&&t.instanceColor&&(n=t.instanceColor));const i={};i.attribute=n,n&&n.data&&(i.data=n.data),r[e]=i,o++}}s.attributes=r,s.attributesNum=o,s.index=i}(n,f,l,g),null!==g&&e.update(g,t.ELEMENT_ARRAY_BUFFER),(v||a)&&(a=!1,function(n,i,r,s){h();const a=s.attributes,o=r.getAttributes(),l=i.defaultAttributeValues;for(const i in o){const r=o[i];if(r.location>=0){let o=a[i];if(void 0===o&&("instanceMatrix"===i&&n.instanceMatrix&&(o=n.instanceMatrix),"instanceColor"===i&&n.instanceColor&&(o=n.instanceColor)),void 0!==o){const i=o.normalized,a=o.itemSize,l=e.get(o);if(void 0===l)continue;const c=l.buffer,h=l.type,p=l.bytesPerElement,f=h===t.INT||h===t.UNSIGNED_INT||o.gpuType===Pt;if(o.isInterleavedBufferAttribute){const e=o.data,l=e.stride,g=o.offset;if(e.isInstancedInterleavedBuffer){for(let t=0;t0&&t.getShaderPrecisionFormat(t.FRAGMENT_SHADER,t.HIGH_FLOAT).precision>0)return"highp";e="mediump"}return"mediump"===e&&t.getShaderPrecisionFormat(t.VERTEX_SHADER,t.MEDIUM_FLOAT).precision>0&&t.getShaderPrecisionFormat(t.FRAGMENT_SHADER,t.MEDIUM_FLOAT).precision>0?"mediump":"lowp"}let a=void 0!==n.precision?n.precision:"highp";const o=s(a);o!==a&&(console.warn("THREE.WebGLRenderer:",a,"not supported, using",o,"instead."),a=o);const l=!0===n.logarithmicDepthBuffer,c=!0===n.reverseDepthBuffer&&e.has("EXT_clip_control");if(!0===c){const t=e.get("EXT_clip_control");t.clipControlEXT(t.LOWER_LEFT_EXT,t.ZERO_TO_ONE_EXT)}const h=t.getParameter(t.MAX_TEXTURE_IMAGE_UNITS),u=t.getParameter(t.MAX_VERTEX_TEXTURE_IMAGE_UNITS);return{isWebGL2:!0,getMaxAnisotropy:function(){if(void 0!==r)return r;if(!0===e.has("EXT_texture_filter_anisotropic")){const n=e.get("EXT_texture_filter_anisotropic");r=t.getParameter(n.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else r=0;return r},getMaxPrecision:s,textureFormatReadable:function(e){return e===kt||i.convert(e)===t.getParameter(t.IMPLEMENTATION_COLOR_READ_FORMAT)},textureTypeReadable:function(n){const r=n===Ut&&(e.has("EXT_color_buffer_half_float")||e.has("EXT_color_buffer_float"));return!(n!==Et&&i.convert(n)!==t.getParameter(t.IMPLEMENTATION_COLOR_READ_TYPE)&&n!==Lt&&!r)},precision:a,logarithmicDepthBuffer:l,reverseDepthBuffer:c,maxTextures:h,maxVertexTextures:u,maxTextureSize:t.getParameter(t.MAX_TEXTURE_SIZE),maxCubemapSize:t.getParameter(t.MAX_CUBE_MAP_TEXTURE_SIZE),maxAttributes:t.getParameter(t.MAX_VERTEX_ATTRIBS),maxVertexUniforms:t.getParameter(t.MAX_VERTEX_UNIFORM_VECTORS),maxVaryings:t.getParameter(t.MAX_VARYING_VECTORS),maxFragmentUniforms:t.getParameter(t.MAX_FRAGMENT_UNIFORM_VECTORS),vertexTextures:u>0,maxSamples:t.getParameter(t.MAX_SAMPLES)}}function wa(t){const e=this;let n=null,i=0,r=!1,s=!1;const a=new oa,o=new ei,l={value:null,needsUpdate:!1};function c(t,n,i,r){const s=null!==t?t.length:0;let c=null;if(0!==s){if(c=l.value,!0!==r||null===c){const e=i+4*s,r=n.matrixWorldInverse;o.getNormalMatrix(r),(null===c||c.length0);e.numPlanes=i,e.numIntersection=0}();else{const t=s?0:i,e=4*t;let r=m.clippingState||null;l.value=r,r=c(u,o,e,h);for(let t=0;t!==e;++t)r[t]=n[t];m.clippingState=r,this.numIntersection=d?this.numPlanes:0,this.numPlanes+=t}}}function Ta(t){let e=new WeakMap;function n(t,e){return e===ht?t.mapping=lt:e===ut&&(t.mapping=ct),t}function i(t){const n=t.target;n.removeEventListener("dispose",i);const r=e.get(n);void 0!==r&&(e.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture){const s=r.mapping;if(s===ht||s===ut){if(e.has(r)){return n(e.get(r).texture,r.mapping)}{const s=r.image;if(s&&s.height>0){const a=new ia(s.height);return a.fromEquirectangularTexture(t,r),e.set(r,a),r.addEventListener("dispose",i),n(a.texture,r.mapping)}return null}}}return r},dispose:function(){e=new WeakMap}}}class Ea extends Zs{constructor(t=-1,e=1,n=1,i=-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=n,this.bottom=i,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,n,i,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=n,this.view.offsetY=i,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),n=(this.right+this.left)/2,i=(this.top+this.bottom)/2;let r=n-t,s=n+t,a=i+e,o=i-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.coordinateSystem),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 Aa=[.125,.215,.35,.446,.526,.582],Ra=20,Ca=new Ea,Pa=new ts;let Ia=null,La=0,Ua=0,Na=!1;const Da=(1+Math.sqrt(5))/2,Oa=1/Da,Fa=[new Li(-Da,Oa,0),new Li(Da,Oa,0),new Li(-Oa,0,Da),new Li(Oa,0,Da),new Li(0,Da,-Oa),new Li(0,Da,Oa),new Li(-1,1,-1),new Li(1,1,-1),new Li(-1,1,1),new Li(1,1,1)];class Ba{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,n=.1,i=100){Ia=this._renderer.getRenderTarget(),La=this._renderer.getActiveCubeFace(),Ua=this._renderer.getActiveMipmapLevel(),Na=this._renderer.xr.enabled,this._renderer.xr.enabled=!1,this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(t,n,i,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=Ha(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=Va(),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=Aa[a-t+4-1]:0===a&&(o=0),i.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),_=new Float32Array(f*p*d),x=new Float32Array(g*p*d);for(let t=0;t2?0:-1,i=[e,n,0,e+2/3,n,0,e+2/3,n+1,0,e,n,0,e+2/3,n+1,0,e,n+1,0];v.set(i,m*p*t),_.set(u,f*p*t);const r=[t,t,t,t,t,t];x.set(r,g*p*t)}const y=new Cs;y.setAttribute("position",new ds(v,m)),y.setAttribute("uv",new ds(_,f)),y.setAttribute("faceIndex",new ds(x,g)),e.push(y),r>4&&r--}return{lodPlanes:e,sizeLods:n,sigmas:i}}(i)),this._blurMaterial=function(t,e,n){const i=new Float32Array(Ra),r=new Li(0,1,0),s=new Ys({name:"SphericalGaussianBlur",defines:{n:Ra,CUBEUV_TEXEL_WIDTH:1/e,CUBEUV_TEXEL_HEIGHT:1/n,CUBEUV_MAX_MIP:`${t}.0`},uniforms:{envMap:{value:null},samples:{value:1},weights:{value:i},latitudinal:{value:!1},dTheta:{value:0},mipInt:{value:0},poleAxis:{value:r}},vertexShader:Ga(),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});return s}(i,t,e)}return i}_compileMaterial(t){const e=new Vs(this._lodPlanes[0],t);this._renderer.compile(e,Ca)}_sceneToCubeUV(t,e,n,i){const r=new Qs(90,1,e,n),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(Pa),o.toneMapping=K,o.autoClear=!1;const h=new rs({name:"PMREM.Background",side:d,depthWrite:!1,depthTest:!1}),u=new Vs(new Gs,h);let p=!1;const m=t.background;m?m.isColor&&(h.color.copy(m),t.background=null,p=!0):(h.color.copy(Pa),p=!0);for(let e=0;e<6;e++){const n=e%3;0===n?(r.up.set(0,s[e],0),r.lookAt(a[e],0,0)):1===n?(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;ka(i,n*l,e>2?l:0,l,l),o.setRenderTarget(i),p&&o.render(u,r),o.render(t,r)}u.geometry.dispose(),u.material.dispose(),o.toneMapping=c,o.autoClear=l,t.background=m}_textureToCubeUV(t,e){const n=this._renderer,i=t.mapping===lt||t.mapping===ct;i?(null===this._cubemapMaterial&&(this._cubemapMaterial=Ha()),this._cubemapMaterial.uniforms.flipEnvMap.value=!1===t.isRenderTargetTexture?-1:1):null===this._equirectMaterial&&(this._equirectMaterial=Va());const r=i?this._cubemapMaterial:this._equirectMaterial,s=new Vs(this._lodPlanes[0],r);r.uniforms.envMap.value=t;const a=this._cubeSize;ka(e,0,0,3*a,2*a),n.setRenderTarget(e),n.render(s,Ca)}_applyPMREM(t){const e=this._renderer,n=e.autoClear;e.autoClear=!1;const i=this._lodPlanes.length;for(let e=1;eRa&&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?i-v+4:0),4*(this._cubeSize-_),3*_,2*_),o.setRenderTarget(e),o.render(c,Ca)}}function za(t,e,n){const i=new Ei(t,e,n);return i.texture.mapping=dt,i.texture.name="PMREM.cubeUv",i.scissorTest=!0,i}function ka(t,e,n,i,r){t.viewport.set(e,n,i,r),t.scissor.set(e,n,i,r)}function Va(){return new Ys({name:"EquirectangularToCubeUV",uniforms:{envMap:{value:null}},vertexShader:Ga(),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 Ha(){return new Ys({name:"CubemapToCubeUV",uniforms:{envMap:{value:null},flipEnvMap:{value:-1}},vertexShader:Ga(),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 Ga(){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 Wa(t){let e=new WeakMap,n=null;function i(t){const n=t.target;n.removeEventListener("dispose",i);const r=e.get(n);void 0!==r&&(e.delete(n),r.dispose())}return{get:function(r){if(r&&r.isTexture){const s=r.mapping,a=s===ht||s===ut,o=s===lt||s===ct;if(a||o){let s=e.get(r);const l=void 0!==s?s.texture.pmremVersion:0;if(r.isRenderTargetTexture&&r.pmremVersion!==l)return null===n&&(n=new Ba(t)),s=a?n.fromEquirectangular(r,s):n.fromCubemap(r,s),s.texture.pmremVersion=r.pmremVersion,e.set(r,s),s.texture;if(void 0!==s)return s.texture;{const l=r.image;return a&&l&&l.height>0||o&&l&&function(t){let e=0;const n=6;for(let i=0;ie.maxTextureSize&&(y=Math.ceil(x/e.maxTextureSize),x=e.maxTextureSize);const M=new Float32Array(x*y*4*h),S=new Ai(M,x,y,h);S.type=Lt,S.needsUpdate=!0;const b=4*_;for(let T=0;T0)return t;const r=e*n;let s=io[r];if(void 0===s&&(s=new Float32Array(r),io[r]=s),0!==e){i.toArray(s,0);for(let i=1,r=0;i!==e;++i)r+=n,t[i].toArray(s,r)}return s}function co(t,e){if(t.length!==e.length)return!1;for(let n=0,i=t.length;n":" "} ${r}: ${n[t]}`)}return i.join("\n")}(t.getShaderSource(e),i)}return r}function ll(t,e){const n=function(t){const e=mi.getPrimaries(mi.workingColorSpace),n=mi.getPrimaries(t);let i;switch(e===n?i="":e===rn&&n===nn?i="LinearDisplayP3ToLinearSRGB":e===nn&&n===rn&&(i="LinearSRGBToLinearDisplayP3"),t){case Ke:case Qe:return[i,"LinearTransferOETF"];case Je:case $e:return[i,"sRGBTransferOETF"];default:return console.warn("THREE.WebGLProgram: Unsupported color space:",t),[i,"LinearTransferOETF"]}}(e);return`vec4 ${t}( vec4 value ) { return ${n[0]}( ${n[1]}( value ) ); }`}function cl(t,e){let n;switch(e){case $:n="Linear";break;case Q:n="Reinhard";break;case tt:n="Cineon";break;case et:n="ACESFilmic";break;case it:n="AgX";break;case rt:n="Neutral";break;case nt:n="Custom";break;default:console.warn("THREE.WebGLProgram: Unsupported toneMapping:",e),n="Linear"}return"vec3 "+t+"( vec3 color ) { return "+n+"ToneMapping( color ); }"}const hl=new Li;function ul(){mi.getLuminanceCoefficients(hl);return["float luminance( const in vec3 rgb ) {",`\tconst vec3 weights = vec3( ${hl.x.toFixed(4)}, ${hl.y.toFixed(4)}, ${hl.z.toFixed(4)} );`,"\treturn dot( weights, rgb );","}"].join("\n")}function dl(t){return""!==t}function pl(t,e){const n=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,n).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 ml(t,e){return t.replace(/NUM_CLIPPING_PLANES/g,e.numClippingPlanes).replace(/UNION_CLIPPING_PLANES/g,e.numClippingPlanes-e.numClipIntersection)}const fl=/^[ \t]*#include +<([\w\d./]+)>/gm;function gl(t){return t.replace(fl,_l)}const vl=new Map;function _l(t,e){let n=ma[e];if(void 0===n){const t=vl.get(e);if(void 0===t)throw new Error("Can not resolve #include <"+e+">");n=ma[t],console.warn('THREE.WebGLRenderer: Shader chunk "%s" has been deprecated. Use "%s" instead.',e,t)}return gl(n)}const xl=/#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 yl(t){return t.replace(xl,Ml)}function Ml(t,e,n,i){let r="";for(let t=parseInt(e);t0&&(x+="\n"),y=["#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v].filter(dl).join("\n"),y.length>0&&(y+="\n")):(x=[Sl(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v,n.extensionClipCullDistance?"#define USE_CLIP_DISTANCE":"",n.batching?"#define USE_BATCHING":"",n.batchingColor?"#define USE_BATCHING_COLOR":"",n.instancing?"#define USE_INSTANCING":"",n.instancingColor?"#define USE_INSTANCING_COLOR":"",n.instancingMorph?"#define USE_INSTANCING_MORPH":"",n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.map?"#define USE_MAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+p:"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.displacementMap?"#define USE_DISPLACEMENTMAP":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropy?"#define USE_ANISOTROPY":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaHash?"#define USE_ALPHAHASH":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.mapUv?"#define MAP_UV "+n.mapUv:"",n.alphaMapUv?"#define ALPHAMAP_UV "+n.alphaMapUv:"",n.lightMapUv?"#define LIGHTMAP_UV "+n.lightMapUv:"",n.aoMapUv?"#define AOMAP_UV "+n.aoMapUv:"",n.emissiveMapUv?"#define EMISSIVEMAP_UV "+n.emissiveMapUv:"",n.bumpMapUv?"#define BUMPMAP_UV "+n.bumpMapUv:"",n.normalMapUv?"#define NORMALMAP_UV "+n.normalMapUv:"",n.displacementMapUv?"#define DISPLACEMENTMAP_UV "+n.displacementMapUv:"",n.metalnessMapUv?"#define METALNESSMAP_UV "+n.metalnessMapUv:"",n.roughnessMapUv?"#define ROUGHNESSMAP_UV "+n.roughnessMapUv:"",n.anisotropyMapUv?"#define ANISOTROPYMAP_UV "+n.anisotropyMapUv:"",n.clearcoatMapUv?"#define CLEARCOATMAP_UV "+n.clearcoatMapUv:"",n.clearcoatNormalMapUv?"#define CLEARCOAT_NORMALMAP_UV "+n.clearcoatNormalMapUv:"",n.clearcoatRoughnessMapUv?"#define CLEARCOAT_ROUGHNESSMAP_UV "+n.clearcoatRoughnessMapUv:"",n.iridescenceMapUv?"#define IRIDESCENCEMAP_UV "+n.iridescenceMapUv:"",n.iridescenceThicknessMapUv?"#define IRIDESCENCE_THICKNESSMAP_UV "+n.iridescenceThicknessMapUv:"",n.sheenColorMapUv?"#define SHEEN_COLORMAP_UV "+n.sheenColorMapUv:"",n.sheenRoughnessMapUv?"#define SHEEN_ROUGHNESSMAP_UV "+n.sheenRoughnessMapUv:"",n.specularMapUv?"#define SPECULARMAP_UV "+n.specularMapUv:"",n.specularColorMapUv?"#define SPECULAR_COLORMAP_UV "+n.specularColorMapUv:"",n.specularIntensityMapUv?"#define SPECULAR_INTENSITYMAP_UV "+n.specularIntensityMapUv:"",n.transmissionMapUv?"#define TRANSMISSIONMAP_UV "+n.transmissionMapUv:"",n.thicknessMapUv?"#define THICKNESSMAP_UV "+n.thicknessMapUv:"",n.vertexTangents&&!1===n.flatShading?"#define USE_TANGENT":"",n.vertexColors?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.flatShading?"#define FLAT_SHADED":"",n.skinning?"#define USE_SKINNING":"",n.morphTargets?"#define USE_MORPHTARGETS":"",n.morphNormals&&!1===n.flatShading?"#define USE_MORPHNORMALS":"",n.morphColors?"#define USE_MORPHCOLORS":"",n.morphTargetsCount>0?"#define MORPHTARGETS_TEXTURE_STRIDE "+n.morphTextureStride:"",n.morphTargetsCount>0?"#define MORPHTARGETS_COUNT "+n.morphTargetsCount:"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+u:"",n.sizeAttenuation?"#define USE_SIZEATTENUATION":"",n.numLightProbes>0?"#define USE_LIGHT_PROBES":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.reverseDepthBuffer?"#define USE_REVERSEDEPTHBUF":"","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","#ifdef USE_INSTANCING_MORPH","\tuniform sampler2D morphTexture;","#endif","attribute vec3 position;","attribute vec3 normal;","attribute vec2 uv;","#ifdef USE_UV1","\tattribute vec2 uv1;","#endif","#ifdef USE_UV2","\tattribute vec2 uv2;","#endif","#ifdef USE_UV3","\tattribute vec2 uv3;","#endif","#ifdef USE_TANGENT","\tattribute vec4 tangent;","#endif","#if defined( USE_COLOR_ALPHA )","\tattribute vec4 color;","#elif defined( USE_COLOR )","\tattribute vec3 color;","#endif","#ifdef USE_SKINNING","\tattribute vec4 skinIndex;","\tattribute vec4 skinWeight;","#endif","\n"].filter(dl).join("\n"),y=[Sl(n),"#define SHADER_TYPE "+n.shaderType,"#define SHADER_NAME "+n.shaderName,v,n.useFog&&n.fog?"#define USE_FOG":"",n.useFog&&n.fogExp2?"#define FOG_EXP2":"",n.alphaToCoverage?"#define ALPHA_TO_COVERAGE":"",n.map?"#define USE_MAP":"",n.matcap?"#define USE_MATCAP":"",n.envMap?"#define USE_ENVMAP":"",n.envMap?"#define "+d:"",n.envMap?"#define "+p:"",n.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":"",n.lightMap?"#define USE_LIGHTMAP":"",n.aoMap?"#define USE_AOMAP":"",n.bumpMap?"#define USE_BUMPMAP":"",n.normalMap?"#define USE_NORMALMAP":"",n.normalMapObjectSpace?"#define USE_NORMALMAP_OBJECTSPACE":"",n.normalMapTangentSpace?"#define USE_NORMALMAP_TANGENTSPACE":"",n.emissiveMap?"#define USE_EMISSIVEMAP":"",n.anisotropy?"#define USE_ANISOTROPY":"",n.anisotropyMap?"#define USE_ANISOTROPYMAP":"",n.clearcoat?"#define USE_CLEARCOAT":"",n.clearcoatMap?"#define USE_CLEARCOATMAP":"",n.clearcoatRoughnessMap?"#define USE_CLEARCOAT_ROUGHNESSMAP":"",n.clearcoatNormalMap?"#define USE_CLEARCOAT_NORMALMAP":"",n.dispersion?"#define USE_DISPERSION":"",n.iridescence?"#define USE_IRIDESCENCE":"",n.iridescenceMap?"#define USE_IRIDESCENCEMAP":"",n.iridescenceThicknessMap?"#define USE_IRIDESCENCE_THICKNESSMAP":"",n.specularMap?"#define USE_SPECULARMAP":"",n.specularColorMap?"#define USE_SPECULAR_COLORMAP":"",n.specularIntensityMap?"#define USE_SPECULAR_INTENSITYMAP":"",n.roughnessMap?"#define USE_ROUGHNESSMAP":"",n.metalnessMap?"#define USE_METALNESSMAP":"",n.alphaMap?"#define USE_ALPHAMAP":"",n.alphaTest?"#define USE_ALPHATEST":"",n.alphaHash?"#define USE_ALPHAHASH":"",n.sheen?"#define USE_SHEEN":"",n.sheenColorMap?"#define USE_SHEEN_COLORMAP":"",n.sheenRoughnessMap?"#define USE_SHEEN_ROUGHNESSMAP":"",n.transmission?"#define USE_TRANSMISSION":"",n.transmissionMap?"#define USE_TRANSMISSIONMAP":"",n.thicknessMap?"#define USE_THICKNESSMAP":"",n.vertexTangents&&!1===n.flatShading?"#define USE_TANGENT":"",n.vertexColors||n.instancingColor||n.batchingColor?"#define USE_COLOR":"",n.vertexAlphas?"#define USE_COLOR_ALPHA":"",n.vertexUv1s?"#define USE_UV1":"",n.vertexUv2s?"#define USE_UV2":"",n.vertexUv3s?"#define USE_UV3":"",n.pointsUvs?"#define USE_POINTS_UV":"",n.gradientMap?"#define USE_GRADIENTMAP":"",n.flatShading?"#define FLAT_SHADED":"",n.doubleSided?"#define DOUBLE_SIDED":"",n.flipSided?"#define FLIP_SIDED":"",n.shadowMapEnabled?"#define USE_SHADOWMAP":"",n.shadowMapEnabled?"#define "+u:"",n.premultipliedAlpha?"#define PREMULTIPLIED_ALPHA":"",n.numLightProbes>0?"#define USE_LIGHT_PROBES":"",n.decodeVideoTexture?"#define DECODE_VIDEO_TEXTURE":"",n.logarithmicDepthBuffer?"#define USE_LOGDEPTHBUF":"",n.reverseDepthBuffer?"#define USE_REVERSEDEPTHBUF":"","uniform mat4 viewMatrix;","uniform vec3 cameraPosition;","uniform bool isOrthographic;",n.toneMapping!==K?"#define TONE_MAPPING":"",n.toneMapping!==K?ma.tonemapping_pars_fragment:"",n.toneMapping!==K?cl("toneMapping",n.toneMapping):"",n.dithering?"#define DITHERING":"",n.opaque?"#define OPAQUE":"",ma.colorspace_pars_fragment,ll("linearToOutputTexel",n.outputColorSpace),ul(),n.useDepthPacking?"#define DEPTH_PACKING "+n.depthPacking:"","\n"].filter(dl).join("\n")),a=gl(a),a=pl(a,n),a=ml(a,n),o=gl(o),o=pl(o,n),o=ml(o,n),a=yl(a),o=yl(o),!0!==n.isRawShaderMaterial&&(M="#version 300 es\n",x=[g,"#define attribute in","#define varying out","#define texture2D texture"].join("\n")+"\n"+x,y=["#define varying in",n.glslVersion===zn?"":"layout(location = 0) out highp vec4 pc_fragColor;",n.glslVersion===zn?"":"#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 S=M+x+a,b=M+y+o,w=rl(r,r.VERTEX_SHADER,S),T=rl(r,r.FRAGMENT_SHADER,b);function E(e){if(t.debug.checkShaderErrors){const n=r.getProgramInfoLog(_).trim(),i=r.getShaderInfoLog(w).trim(),s=r.getShaderInfoLog(T).trim();let a=!0,o=!0;if(!1===r.getProgramParameter(_,r.LINK_STATUS))if(a=!1,"function"==typeof t.debug.onShaderError)t.debug.onShaderError(r,_,w,T);else{const t=ol(r,w,"vertex"),i=ol(r,T,"fragment");console.error("THREE.WebGLProgram: Shader Error "+r.getError()+" - VALIDATE_STATUS "+r.getProgramParameter(_,r.VALIDATE_STATUS)+"\n\nMaterial Name: "+e.name+"\nMaterial Type: "+e.type+"\n\nProgram Info Log: "+n+"\n"+t+"\n"+i)}else""!==n?console.warn("THREE.WebGLProgram: Program Info Log:",n):""!==i&&""!==s||(o=!1);o&&(e.diagnostics={runnable:a,programLog:n,vertexShader:{log:i,prefix:x},fragmentShader:{log:s,prefix:y}})}r.deleteShader(w),r.deleteShader(T),A=new il(r,_),R=function(t,e){const n={},i=t.getProgramParameter(e,t.ACTIVE_ATTRIBUTES);for(let r=0;r0,Y=s.clearcoat>0,Z=s.dispersion>0,J=s.iridescence>0,$=s.sheen>0,Q=s.transmission>0,tt=q&&!!s.anisotropyMap,et=Y&&!!s.clearcoatMap,nt=Y&&!!s.clearcoatNormalMap,it=Y&&!!s.clearcoatRoughnessMap,rt=J&&!!s.iridescenceMap,st=J&&!!s.iridescenceThicknessMap,at=$&&!!s.sheenColorMap,ot=$&&!!s.sheenRoughnessMap,lt=!!s.specularMap,ct=!!s.specularColorMap,ht=!!s.specularIntensityMap,ut=Q&&!!s.transmissionMap,pt=Q&&!!s.thicknessMap,mt=!!s.gradientMap,ft=!!s.alphaMap,gt=s.alphaTest>0,vt=!!s.alphaHash,_t=!!s.extensions;let xt=K;s.toneMapped&&(null!==U&&!0!==U.isXRRenderTarget||(xt=t.toneMapping));const yt={shaderID:T,shaderType:s.type,shaderName:s.name,vertexShader:R,fragmentShader:C,defines:s.defines,customVertexShaderID:P,customFragmentShaderID:I,isRawShaderMaterial:!0===s.isRawShaderMaterial,glslVersion:s.glslVersion,precision:f,batching:D,batchingColor:D&&null!==x._colorsTexture,instancing:N,instancingColor:N&&null!==x.instanceColor,instancingMorph:N&&null!==x.morphTexture,supportsVertexTextures:m,outputColorSpace:null===U?t.outputColorSpace:!0===U.isXRRenderTarget?U.texture.colorSpace:Ke,alphaToCoverage:!!s.alphaToCoverage,map:O,matcap:F,envMap:B,envMapMode:B&&b.mapping,envMapCubeUVHeight:w,aoMap:z,lightMap:k,bumpMap:V,normalMap:H,displacementMap:m&&G,emissiveMap:W,normalMapObjectSpace:H&&1===s.normalMapType,normalMapTangentSpace:H&&0===s.normalMapType,metalnessMap:X,roughnessMap:j,anisotropy:q,anisotropyMap:tt,clearcoat:Y,clearcoatMap:et,clearcoatNormalMap:nt,clearcoatRoughnessMap:it,dispersion:Z,iridescence:J,iridescenceMap:rt,iridescenceThicknessMap:st,sheen:$,sheenColorMap:at,sheenRoughnessMap:ot,specularMap:lt,specularColorMap:ct,specularIntensityMap:ht,transmission:Q,transmissionMap:ut,thicknessMap:pt,gradientMap:mt,opaque:!1===s.transparent&&1===s.blending&&!1===s.alphaToCoverage,alphaMap:ft,alphaTest:gt,alphaHash:vt,combine:s.combine,mapUv:O&&v(s.map.channel),aoMapUv:z&&v(s.aoMap.channel),lightMapUv:k&&v(s.lightMap.channel),bumpMapUv:V&&v(s.bumpMap.channel),normalMapUv:H&&v(s.normalMap.channel),displacementMapUv:G&&v(s.displacementMap.channel),emissiveMapUv:W&&v(s.emissiveMap.channel),metalnessMapUv:X&&v(s.metalnessMap.channel),roughnessMapUv:j&&v(s.roughnessMap.channel),anisotropyMapUv:tt&&v(s.anisotropyMap.channel),clearcoatMapUv:et&&v(s.clearcoatMap.channel),clearcoatNormalMapUv:nt&&v(s.clearcoatNormalMap.channel),clearcoatRoughnessMapUv:it&&v(s.clearcoatRoughnessMap.channel),iridescenceMapUv:rt&&v(s.iridescenceMap.channel),iridescenceThicknessMapUv:st&&v(s.iridescenceThicknessMap.channel),sheenColorMapUv:at&&v(s.sheenColorMap.channel),sheenRoughnessMapUv:ot&&v(s.sheenRoughnessMap.channel),specularMapUv:lt&&v(s.specularMap.channel),specularColorMapUv:ct&&v(s.specularColorMap.channel),specularIntensityMapUv:ht&&v(s.specularIntensityMap.channel),transmissionMapUv:ut&&v(s.transmissionMap.channel),thicknessMapUv:pt&&v(s.thicknessMap.channel),alphaMapUv:ft&&v(s.alphaMap.channel),vertexTangents:!!M.attributes.tangent&&(H||q),vertexColors:s.vertexColors,vertexAlphas:!0===s.vertexColors&&!!M.attributes.color&&4===M.attributes.color.itemSize,pointsUvs:!0===x.isPoints&&!!M.attributes.uv&&(O||ft),fog:!!y,useFog:!0===s.fog,fogExp2:!!y&&y.isFogExp2,flatShading:!0===s.flatShading,sizeAttenuation:!0===s.sizeAttenuation,logarithmicDepthBuffer:u,reverseDepthBuffer:p,skinning:!0===x.isSkinnedMesh,morphTargets:void 0!==M.morphAttributes.position,morphNormals:void 0!==M.morphAttributes.normal,morphColors:void 0!==M.morphAttributes.color,morphTargetsCount:A,morphTextureStride:L,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,numLightProbes:o.numLightProbes,numClippingPlanes:a.numPlanes,numClipIntersection:a.numIntersection,dithering:s.dithering,shadowMapEnabled:t.shadowMap.enabled&&h.length>0,shadowMapType:t.shadowMap.type,toneMapping:xt,decodeVideoTexture:O&&!0===s.map.isVideoTexture&&mi.getTransfer(s.map.colorSpace)===en,premultipliedAlpha:s.premultipliedAlpha,doubleSided:2===s.side,flipSided:s.side===d,useDepthPacking:s.depthPacking>=0,depthPacking:s.depthPacking||0,index0AttributeName:s.index0AttributeName,extensionClipCullDistance:_t&&!0===s.extensions.clipCullDistance&&i.has("WEBGL_clip_cull_distance"),extensionMultiDraw:(_t&&!0===s.extensions.multiDraw||D)&&i.has("WEBGL_multi_draw"),rendererExtensionParallelShaderCompile:i.has("KHR_parallel_shader_compile"),customProgramCacheKey:s.customProgramCacheKey()};return yt.vertexUv1s=c.has(1),yt.vertexUv2s=c.has(2),yt.vertexUv3s=c.has(3),c.clear(),yt},getProgramCacheKey:function(e){const n=[];if(e.shaderID?n.push(e.shaderID):(n.push(e.customVertexShaderID),n.push(e.customFragmentShaderID)),void 0!==e.defines)for(const t in e.defines)n.push(t),n.push(e.defines[t]);return!1===e.isRawShaderMaterial&&(!function(t,e){t.push(e.precision),t.push(e.outputColorSpace),t.push(e.envMapMode),t.push(e.envMapCubeUVHeight),t.push(e.mapUv),t.push(e.alphaMapUv),t.push(e.lightMapUv),t.push(e.aoMapUv),t.push(e.bumpMapUv),t.push(e.normalMapUv),t.push(e.displacementMapUv),t.push(e.emissiveMapUv),t.push(e.metalnessMapUv),t.push(e.roughnessMapUv),t.push(e.anisotropyMapUv),t.push(e.clearcoatMapUv),t.push(e.clearcoatNormalMapUv),t.push(e.clearcoatRoughnessMapUv),t.push(e.iridescenceMapUv),t.push(e.iridescenceThicknessMapUv),t.push(e.sheenColorMapUv),t.push(e.sheenRoughnessMapUv),t.push(e.specularMapUv),t.push(e.specularColorMapUv),t.push(e.specularIntensityMapUv),t.push(e.transmissionMapUv),t.push(e.thicknessMapUv),t.push(e.combine),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.numLightProbes),t.push(e.shadowMapType),t.push(e.toneMapping),t.push(e.numClippingPlanes),t.push(e.numClipIntersection),t.push(e.depthPacking)}(n,e),function(t,e){o.disableAll(),e.supportsVertexTextures&&o.enable(0);e.instancing&&o.enable(1);e.instancingColor&&o.enable(2);e.instancingMorph&&o.enable(3);e.matcap&&o.enable(4);e.envMap&&o.enable(5);e.normalMapObjectSpace&&o.enable(6);e.normalMapTangentSpace&&o.enable(7);e.clearcoat&&o.enable(8);e.iridescence&&o.enable(9);e.alphaTest&&o.enable(10);e.vertexColors&&o.enable(11);e.vertexAlphas&&o.enable(12);e.vertexUv1s&&o.enable(13);e.vertexUv2s&&o.enable(14);e.vertexUv3s&&o.enable(15);e.vertexTangents&&o.enable(16);e.anisotropy&&o.enable(17);e.alphaHash&&o.enable(18);e.batching&&o.enable(19);e.dispersion&&o.enable(20);e.batchingColor&&o.enable(21);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.reverseDepthBuffer&&o.enable(4);e.skinning&&o.enable(5);e.morphTargets&&o.enable(6);e.morphNormals&&o.enable(7);e.morphColors&&o.enable(8);e.premultipliedAlpha&&o.enable(9);e.shadowMapEnabled&&o.enable(10);e.doubleSided&&o.enable(11);e.flipSided&&o.enable(12);e.useDepthPacking&&o.enable(13);e.dithering&&o.enable(14);e.transmission&&o.enable(15);e.sheen&&o.enable(16);e.opaque&&o.enable(17);e.pointsUvs&&o.enable(18);e.decodeVideoTexture&&o.enable(19);e.alphaToCoverage&&o.enable(20);t.push(o.mask)}(n,e),n.push(t.outputColorSpace)),n.push(e.customProgramCacheKey),n.join()},getUniforms:function(t){const e=g[t.type];let n;if(e){const t=ga[e];n=qs.clone(t.uniforms)}else n=t.uniforms;return n},acquireProgram:function(e,n){let i;for(let t=0,e=h.length;t0?i.push(h):!0===a.transparent?r.push(h):n.push(h)},unshift:function(t,e,a,o,l,c){const h=s(t,e,a,o,l,c);a.transmission>0?i.unshift(h):!0===a.transparent?r.unshift(h):n.unshift(h)},finish:function(){for(let n=e,i=t.length;n1&&n.sort(t||Cl),i.length>1&&i.sort(e||Pl),r.length>1&&r.sort(e||Pl)}}}function Ll(){let t=new WeakMap;return{get:function(e,n){const i=t.get(e);let r;return void 0===i?(r=new Il,t.set(e,[r])):n>=i.length?(r=new Il,i.push(r)):r=i[n],r},dispose:function(){t=new WeakMap}}}function Ul(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let n;switch(e.type){case"DirectionalLight":n={direction:new Li,color:new ts};break;case"SpotLight":n={position:new Li,direction:new Li,color:new ts,distance:0,coneCos:0,penumbraCos:0,decay:0};break;case"PointLight":n={position:new Li,color:new ts,distance:0,decay:0};break;case"HemisphereLight":n={direction:new Li,skyColor:new ts,groundColor:new ts};break;case"RectAreaLight":n={color:new ts,position:new Li,halfWidth:new Li,halfHeight:new Li}}return t[e.id]=n,n}}}let Nl=0;function Dl(t,e){return(e.castShadow?2:0)-(t.castShadow?2:0)+(e.map?1:0)-(t.map?1:0)}function Ol(t){const e=new Ul,n=function(){const t={};return{get:function(e){if(void 0!==t[e.id])return t[e.id];let n;switch(e.type){case"DirectionalLight":case"SpotLight":n={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new ti};break;case"PointLight":n={shadowIntensity:1,shadowBias:0,shadowNormalBias:0,shadowRadius:1,shadowMapSize:new ti,shadowCameraNear:1,shadowCameraFar:1e3}}return t[e.id]=n,n}}}(),i={version:0,hash:{directionalLength:-1,pointLength:-1,spotLength:-1,rectAreaLength:-1,hemiLength:-1,numDirectionalShadows:-1,numPointShadows:-1,numSpotShadows:-1,numSpotMaps:-1,numLightProbes:-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,numLightProbes:0};for(let t=0;t<9;t++)i.probe.push(new Li);const r=new Li,s=new lr,a=new lr;return{setup:function(r){let s=0,a=0,o=0;for(let t=0;t<9;t++)i.probe[t].set(0,0,0);let l=0,c=0,h=0,u=0,d=0,p=0,m=0,f=0,g=0,v=0,_=0;r.sort(Dl);for(let t=0,x=r.length;t0&&(!0===t.has("OES_texture_float_linear")?(i.rectAreaLTC1=fa.LTC_FLOAT_1,i.rectAreaLTC2=fa.LTC_FLOAT_2):(i.rectAreaLTC1=fa.LTC_HALF_1,i.rectAreaLTC2=fa.LTC_HALF_2)),i.ambient[0]=s,i.ambient[1]=a,i.ambient[2]=o;const x=i.hash;x.directionalLength===l&&x.pointLength===c&&x.spotLength===h&&x.rectAreaLength===u&&x.hemiLength===d&&x.numDirectionalShadows===p&&x.numPointShadows===m&&x.numSpotShadows===f&&x.numSpotMaps===g&&x.numLightProbes===_||(i.directional.length=l,i.spot.length=h,i.rectArea.length=u,i.point.length=c,i.hemi.length=d,i.directionalShadow.length=p,i.directionalShadowMap.length=p,i.pointShadow.length=m,i.pointShadowMap.length=m,i.spotShadow.length=f,i.spotShadowMap.length=f,i.directionalShadowMatrix.length=p,i.pointShadowMatrix.length=m,i.spotLightMatrix.length=f+g-v,i.spotLightMap.length=g,i.numSpotLightShadowsWithMaps=v,i.numLightProbes=_,x.directionalLength=l,x.pointLength=c,x.spotLength=h,x.rectAreaLength=u,x.hemiLength=d,x.numDirectionalShadows=p,x.numPointShadows=m,x.numSpotShadows=f,x.numSpotMaps=g,x.numLightProbes=_,i.version=Nl++)},setupView:function(t,e){let n=0,o=0,l=0,c=0,h=0;const u=e.matrixWorldInverse;for(let e=0,d=t.length;e=r.length?(s=new Fl(t),r.push(s)):s=r[i],s},dispose:function(){e=new WeakMap}}}class zl extends is{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 kl extends is{constructor(t){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",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.map=t.map,this.alphaMap=t.alphaMap,this.displacementMap=t.displacementMap,this.displacementScale=t.displacementScale,this.displacementBias=t.displacementBias,this}}function Vl(t,e,n){let i=new ha;const r=new ti,s=new ti,a=new wi,o=new zl({depthPacking:3201}),c=new kl,p={},m=n.maxTextureSize,f={[u]:d,[d]:u,2:2},g=new Ys({defines:{VSM_SAMPLES:8},uniforms:{shadow_pass:{value:null},resolution:{value:new ti},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}"}),v=g.clone();v.defines.HORIZONTAL_PASS=1;const _=new Cs;_.setAttribute("position",new ds(new Float32Array([-1,-1,.5,3,-1,.5,-1,3,.5]),3));const x=new Vs(_,g),y=this;this.enabled=!1,this.autoUpdate=!0,this.needsUpdate=!1,this.type=l;let M=this.type;function S(n,i){const s=e.update(x);g.defines.VSM_SAMPLES!==n.blurSamples&&(g.defines.VSM_SAMPLES=n.blurSamples,v.defines.VSM_SAMPLES=n.blurSamples,g.needsUpdate=!0,v.needsUpdate=!0),null===n.mapPass&&(n.mapPass=new Ei(r.x,r.y)),g.uniforms.shadow_pass.value=n.map.texture,g.uniforms.resolution.value=n.mapSize,g.uniforms.radius.value=n.radius,t.setRenderTarget(n.mapPass),t.clear(),t.renderBufferDirect(i,null,s,g,x,null),v.uniforms.shadow_pass.value=n.mapPass.texture,v.uniforms.resolution.value=n.mapSize,v.uniforms.radius.value=n.radius,t.setRenderTarget(n.map),t.clear(),t.renderBufferDirect(i,null,s,v,x,null)}function b(e,n,i,r){let s=null;const a=!0===i.isPointLight?e.customDistanceMaterial:e.customDepthMaterial;if(void 0!==a)s=a;else if(s=!0===i.isPointLight?c:o,t.localClippingEnabled&&!0===n.clipShadows&&Array.isArray(n.clippingPlanes)&&0!==n.clippingPlanes.length||n.displacementMap&&0!==n.displacementScale||n.alphaMap&&n.alphaTest>0||n.map&&n.alphaTest>0){const t=s.uuid,e=n.uuid;let i=p[t];void 0===i&&(i={},p[t]=i);let r=i[e];void 0===r&&(r=s.clone(),i[e]=r,n.addEventListener("dispose",T)),s=r}if(s.visible=n.visible,s.wireframe=n.wireframe,s.side=r===h?null!==n.shadowSide?n.shadowSide:n.side:null!==n.shadowSide?n.shadowSide:f[n.side],s.alphaMap=n.alphaMap,s.alphaTest=n.alphaTest,s.map=n.map,s.clipShadows=n.clipShadows,s.clippingPlanes=n.clippingPlanes,s.clipIntersection=n.clipIntersection,s.displacementMap=n.displacementMap,s.displacementScale=n.displacementScale,s.displacementBias=n.displacementBias,s.wireframeLinewidth=n.wireframeLinewidth,s.linewidth=n.linewidth,!0===i.isPointLight&&!0===s.isMeshDistanceMaterial){t.properties.get(s).light=i}return s}function w(n,r,s,a,o){if(!1===n.visible)return;if(n.layers.test(r.layers)&&(n.isMesh||n.isLine||n.isPoints)&&(n.castShadow||n.receiveShadow&&o===h)&&(!n.frustumCulled||i.intersectsObject(n))){n.modelViewMatrix.multiplyMatrices(s.matrixWorldInverse,n.matrixWorld);const i=e.update(n),l=n.material;if(Array.isArray(l)){const e=i.groups;for(let c=0,h=e.length;cm||r.y>m)&&(r.x>m&&(s.x=Math.floor(m/g.x),r.x=s.x*g.x,u.mapSize.x=s.x),r.y>m&&(s.y=Math.floor(m/g.y),r.y=s.y*g.y,u.mapSize.y=s.y)),null===u.map||!0===p||!0===f){const t=this.type!==h?{minFilter:gt,magFilter:gt}:{};null!==u.map&&u.map.dispose(),u.map=new Ei(r.x,r.y,t),u.map.texture.name=c.name+".shadowMap",u.camera.updateProjectionMatrix()}t.setRenderTarget(u.map),t.clear();const v=u.getViewportCount();for(let t=0;t=1):-1!==N.indexOf("OpenGL ES")&&(U=parseFloat(/^OpenGL ES (\d)/.exec(N)[1]),L=U>=2);let D=null,O={};const F=t.getParameter(t.SCISSOR_BOX),B=t.getParameter(t.VIEWPORT),z=(new wi).fromArray(F),k=(new wi).fromArray(B);function V(e,n,i,r){const s=new Uint8Array(4),a=t.createTexture();t.bindTexture(e,a),t.texParameteri(e,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(e,t.TEXTURE_MAG_FILTER,t.NEAREST);for(let a=0;ae?(t.repeat.x=1,t.repeat.y=n/e,t.offset.x=0,t.offset.y=(1-t.repeat.y)/2):(t.repeat.x=e/n,t.repeat.y=1,t.offset.x=(1-t.repeat.x)/2,t.offset.y=0),t},cover:function(t,e){const n=t.image&&t.image.width?t.image.width/t.image.height:1;return n>e?(t.repeat.x=e/n,t.repeat.y=1,t.offset.x=(1-t.repeat.x)/2,t.offset.y=0):(t.repeat.x=1,t.repeat.y=n/e,t.offset.x=0,t.offset.y=(1-t.repeat.y)/2),t},fill:function(t){return t.repeat.x=1,t.repeat.y=1,t.offset.x=0,t.offset.y=0,t},getByteLength:Wl};function jl(t,e,n,i,r,s,a){const o=e.has("WEBGL_multisampled_render_to_texture")?e.get("WEBGL_multisampled_render_to_texture"):null,l="undefined"!=typeof navigator&&/OculusBrowser/g.test(navigator.userAgent),c=new ti,h=new WeakMap;let u;const d=new WeakMap;let p=!1;try{p="undefined"!=typeof OffscreenCanvas&&null!==new OffscreenCanvas(1,1).getContext("2d")}catch(t){}function m(t,e){return p?new OffscreenCanvas(t,e):ai("canvas")}function f(t,e,n){let i=1;const r=k(t);if((r.width>n||r.height>n)&&(i=n/Math.max(r.width,r.height)),i<1){if("undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&t instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&t instanceof ImageBitmap||"undefined"!=typeof VideoFrame&&t instanceof VideoFrame){const n=Math.floor(i*r.width),s=Math.floor(i*r.height);void 0===u&&(u=m(n,s));const a=e?m(n,s):u;a.width=n,a.height=s;return a.getContext("2d").drawImage(t,0,0,n,s),console.warn("THREE.WebGLRenderer: Texture has been resized from ("+r.width+"x"+r.height+") to ("+n+"x"+s+")."),a}return"data"in t&&console.warn("THREE.WebGLRenderer: Image in DataTexture is too big ("+r.width+"x"+r.height+")."),t}return t}function g(t){return t.generateMipmaps&&t.minFilter!==gt&&t.minFilter!==Mt}function v(e){t.generateMipmap(e)}function _(n,i,r,s,a=!1){if(null!==n){if(void 0!==t[n])return t[n];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+n+"'")}let o=i;if(i===t.RED&&(r===t.FLOAT&&(o=t.R32F),r===t.HALF_FLOAT&&(o=t.R16F),r===t.UNSIGNED_BYTE&&(o=t.R8)),i===t.RED_INTEGER&&(r===t.UNSIGNED_BYTE&&(o=t.R8UI),r===t.UNSIGNED_SHORT&&(o=t.R16UI),r===t.UNSIGNED_INT&&(o=t.R32UI),r===t.BYTE&&(o=t.R8I),r===t.SHORT&&(o=t.R16I),r===t.INT&&(o=t.R32I)),i===t.RG&&(r===t.FLOAT&&(o=t.RG32F),r===t.HALF_FLOAT&&(o=t.RG16F),r===t.UNSIGNED_BYTE&&(o=t.RG8)),i===t.RG_INTEGER&&(r===t.UNSIGNED_BYTE&&(o=t.RG8UI),r===t.UNSIGNED_SHORT&&(o=t.RG16UI),r===t.UNSIGNED_INT&&(o=t.RG32UI),r===t.BYTE&&(o=t.RG8I),r===t.SHORT&&(o=t.RG16I),r===t.INT&&(o=t.RG32I)),i===t.RGB_INTEGER&&(r===t.UNSIGNED_BYTE&&(o=t.RGB8UI),r===t.UNSIGNED_SHORT&&(o=t.RGB16UI),r===t.UNSIGNED_INT&&(o=t.RGB32UI),r===t.BYTE&&(o=t.RGB8I),r===t.SHORT&&(o=t.RGB16I),r===t.INT&&(o=t.RGB32I)),i===t.RGBA_INTEGER&&(r===t.UNSIGNED_BYTE&&(o=t.RGBA8UI),r===t.UNSIGNED_SHORT&&(o=t.RGBA16UI),r===t.UNSIGNED_INT&&(o=t.RGBA32UI),r===t.BYTE&&(o=t.RGBA8I),r===t.SHORT&&(o=t.RGBA16I),r===t.INT&&(o=t.RGBA32I)),i===t.RGB&&r===t.UNSIGNED_INT_5_9_9_9_REV&&(o=t.RGB9_E5),i===t.RGBA){const e=a?tn:mi.getTransfer(s);r===t.FLOAT&&(o=t.RGBA32F),r===t.HALF_FLOAT&&(o=t.RGBA16F),r===t.UNSIGNED_BYTE&&(o=e===en?t.SRGB8_ALPHA8:t.RGBA8),r===t.UNSIGNED_SHORT_4_4_4_4&&(o=t.RGBA4),r===t.UNSIGNED_SHORT_5_5_5_1&&(o=t.RGB5_A1)}return o!==t.R16F&&o!==t.R32F&&o!==t.RG16F&&o!==t.RG32F&&o!==t.RGBA16F&&o!==t.RGBA32F||e.get("EXT_color_buffer_float"),o}function x(e,n){let i;return e?null===n||n===It||n===Ot?i=t.DEPTH24_STENCIL8:n===Lt?i=t.DEPTH32F_STENCIL8:n===Ct&&(i=t.DEPTH24_STENCIL8,console.warn("DepthTexture: 16 bit depth attachment is not supported with stencil. Using 24-bit attachment.")):null===n||n===It||n===Ot?i=t.DEPTH_COMPONENT24:n===Lt?i=t.DEPTH_COMPONENT32F:n===Ct&&(i=t.DEPTH_COMPONENT16),i}function y(t,e){return!0===g(t)||t.isFramebufferTexture&&t.minFilter!==gt&&t.minFilter!==Mt?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 M(t){const e=t.target;e.removeEventListener("dispose",M),function(t){const e=i.get(t);if(void 0===e.__webglInit)return;const n=t.source,r=d.get(n);if(r){const i=r[e.__cacheKey];i.usedTimes--,0===i.usedTimes&&b(t),0===Object.keys(r).length&&d.delete(n)}i.remove(t)}(e),e.isVideoTexture&&h.delete(e)}function S(e){const n=e.target;n.removeEventListener("dispose",S),function(e){const n=i.get(e);e.depthTexture&&e.depthTexture.dispose();if(e.isWebGLCubeRenderTarget)for(let e=0;e<6;e++){if(Array.isArray(n.__webglFramebuffer[e]))for(let i=0;i0&&s.__version!==e.version){const t=e.image;if(null===t)console.warn("THREE.WebGLRenderer: Texture marked for update but no image data found.");else{if(!1!==t.complete)return void I(s,e,r);console.warn("THREE.WebGLRenderer: Texture marked for update but image is incomplete")}}n.bindTexture(t.TEXTURE_2D,s.__webglTexture,t.TEXTURE0+r)}const E={[pt]:t.REPEAT,[mt]:t.CLAMP_TO_EDGE,[ft]:t.MIRRORED_REPEAT},A={[gt]:t.NEAREST,[vt]:t.NEAREST_MIPMAP_NEAREST,[xt]:t.NEAREST_MIPMAP_LINEAR,[Mt]:t.LINEAR,[St]:t.LINEAR_MIPMAP_NEAREST,[wt]:t.LINEAR_MIPMAP_LINEAR},R={512:t.NEVER,519:t.ALWAYS,513:t.LESS,[wn]:t.LEQUAL,514:t.EQUAL,518:t.GEQUAL,516:t.GREATER,517:t.NOTEQUAL};function C(n,s){if(s.type!==Lt||!1!==e.has("OES_texture_float_linear")||s.magFilter!==Mt&&s.magFilter!==St&&s.magFilter!==xt&&s.magFilter!==wt&&s.minFilter!==Mt&&s.minFilter!==St&&s.minFilter!==xt&&s.minFilter!==wt||console.warn("THREE.WebGLRenderer: Unable to use linear filtering with floating point textures. OES_texture_float_linear not supported on this device."),t.texParameteri(n,t.TEXTURE_WRAP_S,E[s.wrapS]),t.texParameteri(n,t.TEXTURE_WRAP_T,E[s.wrapT]),n!==t.TEXTURE_3D&&n!==t.TEXTURE_2D_ARRAY||t.texParameteri(n,t.TEXTURE_WRAP_R,E[s.wrapR]),t.texParameteri(n,t.TEXTURE_MAG_FILTER,A[s.magFilter]),t.texParameteri(n,t.TEXTURE_MIN_FILTER,A[s.minFilter]),s.compareFunction&&(t.texParameteri(n,t.TEXTURE_COMPARE_MODE,t.COMPARE_REF_TO_TEXTURE),t.texParameteri(n,t.TEXTURE_COMPARE_FUNC,R[s.compareFunction])),!0===e.has("EXT_texture_filter_anisotropic")){if(s.magFilter===gt)return;if(s.minFilter!==xt&&s.minFilter!==wt)return;if(s.type===Lt&&!1===e.has("OES_texture_float_linear"))return;if(s.anisotropy>1||i.get(s).__currentAnisotropy){const a=e.get("EXT_texture_filter_anisotropic");t.texParameterf(n,a.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(s.anisotropy,r.getMaxAnisotropy())),i.get(s).__currentAnisotropy=s.anisotropy}}}function P(e,n){let i=!1;void 0===e.__webglInit&&(e.__webglInit=!0,n.addEventListener("dispose",M));const r=n.source;let s=d.get(r);void 0===s&&(s={},d.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.colorSpace),e.join()}(n);if(o!==e.__cacheKey){void 0===s[o]&&(s[o]={texture:t.createTexture(),usedTimes:0},a.memory.textures++,i=!0),s[o].usedTimes++;const r=s[e.__cacheKey];void 0!==r&&(s[e.__cacheKey].usedTimes--,0===r.usedTimes&&b(n)),e.__cacheKey=o,e.__webglTexture=s[o].texture}return i}function I(e,a,o){let l=t.TEXTURE_2D;(a.isDataArrayTexture||a.isCompressedArrayTexture)&&(l=t.TEXTURE_2D_ARRAY),a.isData3DTexture&&(l=t.TEXTURE_3D);const c=P(e,a),h=a.source;n.bindTexture(l,e.__webglTexture,t.TEXTURE0+o);const u=i.get(h);if(h.version!==u.__version||!0===c){n.activeTexture(t.TEXTURE0+o);const e=mi.getPrimaries(mi.workingColorSpace),i=a.colorSpace===Ze?null:mi.getPrimaries(a.colorSpace),d=a.colorSpace===Ze||e===i?t.NONE:t.BROWSER_DEFAULT_WEBGL;t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,a.flipY),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,a.premultiplyAlpha),t.pixelStorei(t.UNPACK_ALIGNMENT,a.unpackAlignment),t.pixelStorei(t.UNPACK_COLORSPACE_CONVERSION_WEBGL,d);let p=f(a.image,!1,r.maxTextureSize);p=z(a,p);const m=s.convert(a.format,a.colorSpace),M=s.convert(a.type);let S,b=_(a.internalFormat,m,M,a.colorSpace,a.isVideoTexture);C(l,a);const w=a.mipmaps,T=!0!==a.isVideoTexture,E=void 0===u.__version||!0===c,A=h.dataReady,R=y(a,p);if(a.isDepthTexture)b=x(a.format===Wt,a.type),E&&(T?n.texStorage2D(t.TEXTURE_2D,1,b,p.width,p.height):n.texImage2D(t.TEXTURE_2D,0,b,p.width,p.height,0,m,M,null));else if(a.isDataTexture)if(w.length>0){T&&E&&n.texStorage2D(t.TEXTURE_2D,R,b,w[0].width,w[0].height);for(let e=0,i=w.length;e0){const i=Wl(S.width,S.height,a.format,a.type);for(const r of a.layerUpdates){const s=S.data.subarray(r*i/S.data.BYTES_PER_ELEMENT,(r+1)*i/S.data.BYTES_PER_ELEMENT);n.compressedTexSubImage3D(t.TEXTURE_2D_ARRAY,e,0,0,r,S.width,S.height,1,m,s,0,0)}a.clearLayerUpdates()}else n.compressedTexSubImage3D(t.TEXTURE_2D_ARRAY,e,0,0,0,S.width,S.height,p.depth,m,S.data,0,0)}else n.compressedTexImage3D(t.TEXTURE_2D_ARRAY,e,b,S.width,S.height,p.depth,0,S.data,0,0);else console.warn("THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()");else T?A&&n.texSubImage3D(t.TEXTURE_2D_ARRAY,e,0,0,0,S.width,S.height,p.depth,m,M,S.data):n.texImage3D(t.TEXTURE_2D_ARRAY,e,b,S.width,S.height,p.depth,0,m,M,S.data)}else{T&&E&&n.texStorage2D(t.TEXTURE_2D,R,b,w[0].width,w[0].height);for(let e=0,i=w.length;e0){const e=Wl(p.width,p.height,a.format,a.type);for(const i of a.layerUpdates){const r=p.data.subarray(i*e/p.data.BYTES_PER_ELEMENT,(i+1)*e/p.data.BYTES_PER_ELEMENT);n.texSubImage3D(t.TEXTURE_2D_ARRAY,0,0,0,i,p.width,p.height,1,m,M,r)}a.clearLayerUpdates()}else n.texSubImage3D(t.TEXTURE_2D_ARRAY,0,0,0,0,p.width,p.height,p.depth,m,M,p.data)}else n.texImage3D(t.TEXTURE_2D_ARRAY,0,b,p.width,p.height,p.depth,0,m,M,p.data);else if(a.isData3DTexture)T?(E&&n.texStorage3D(t.TEXTURE_3D,R,b,p.width,p.height,p.depth),A&&n.texSubImage3D(t.TEXTURE_3D,0,0,0,0,p.width,p.height,p.depth,m,M,p.data)):n.texImage3D(t.TEXTURE_3D,0,b,p.width,p.height,p.depth,0,m,M,p.data);else if(a.isFramebufferTexture){if(E)if(T)n.texStorage2D(t.TEXTURE_2D,R,b,p.width,p.height);else{let e=p.width,i=p.height;for(let r=0;r>=1,i>>=1}}else if(w.length>0){if(T&&E){const e=k(w[0]);n.texStorage2D(t.TEXTURE_2D,R,b,e.width,e.height)}for(let e=0,i=w.length;e>h),i=Math.max(1,r.height>>h);c===t.TEXTURE_3D||c===t.TEXTURE_2D_ARRAY?n.texImage3D(c,h,p,e,i,r.depth,0,u,d,null):n.texImage2D(c,h,p,e,i,0,u,d,null)}n.bindFramebuffer(t.FRAMEBUFFER,e),B(r)?o.framebufferTexture2DMultisampleEXT(t.FRAMEBUFFER,l,c,i.get(a).__webglTexture,0,F(r)):(c===t.TEXTURE_2D||c>=t.TEXTURE_CUBE_MAP_POSITIVE_X&&c<=t.TEXTURE_CUBE_MAP_NEGATIVE_Z)&&t.framebufferTexture2D(t.FRAMEBUFFER,l,c,i.get(a).__webglTexture,h),n.bindFramebuffer(t.FRAMEBUFFER,null)}function U(e,n,i){if(t.bindRenderbuffer(t.RENDERBUFFER,e),n.depthBuffer){const r=n.depthTexture,s=r&&r.isDepthTexture?r.type:null,a=x(n.stencilBuffer,s),l=n.stencilBuffer?t.DEPTH_STENCIL_ATTACHMENT:t.DEPTH_ATTACHMENT,c=F(n);B(n)?o.renderbufferStorageMultisampleEXT(t.RENDERBUFFER,c,a,n.width,n.height):i?t.renderbufferStorageMultisample(t.RENDERBUFFER,c,a,n.width,n.height):t.renderbufferStorage(t.RENDERBUFFER,a,n.width,n.height),t.framebufferRenderbuffer(t.FRAMEBUFFER,l,t.RENDERBUFFER,e)}else{const e=n.textures;for(let r=0;r{delete r.__boundDepthTexture,delete r.__depthDisposeCallback,t.removeEventListener("dispose",e)};t.addEventListener("dispose",e),r.__depthDisposeCallback=e}r.__boundDepthTexture=t}if(e.depthTexture&&!r.__autoAllocateDepthBuffer){if(s)throw new Error("target.depthTexture not supported in Cube render targets");!function(e,r){if(r&&r.isWebGLCubeRenderTarget)throw new Error("Depth Texture with cube render targets is not supported");if(n.bindFramebuffer(t.FRAMEBUFFER,e),!r.depthTexture||!r.depthTexture.isDepthTexture)throw new Error("renderTarget.depthTexture must be an instance of THREE.DepthTexture");i.get(r.depthTexture).__webglTexture&&r.depthTexture.image.width===r.width&&r.depthTexture.image.height===r.height||(r.depthTexture.image.width=r.width,r.depthTexture.image.height=r.height,r.depthTexture.needsUpdate=!0),T(r.depthTexture,0);const s=i.get(r.depthTexture).__webglTexture,a=F(r);if(r.depthTexture.format===Gt)B(r)?o.framebufferTexture2DMultisampleEXT(t.FRAMEBUFFER,t.DEPTH_ATTACHMENT,t.TEXTURE_2D,s,0,a):t.framebufferTexture2D(t.FRAMEBUFFER,t.DEPTH_ATTACHMENT,t.TEXTURE_2D,s,0);else{if(r.depthTexture.format!==Wt)throw new Error("Unknown depthTexture format");B(r)?o.framebufferTexture2DMultisampleEXT(t.FRAMEBUFFER,t.DEPTH_STENCIL_ATTACHMENT,t.TEXTURE_2D,s,0,a):t.framebufferTexture2D(t.FRAMEBUFFER,t.DEPTH_STENCIL_ATTACHMENT,t.TEXTURE_2D,s,0)}}(r.__webglFramebuffer,e)}else if(s){r.__webglDepthbuffer=[];for(let i=0;i<6;i++)if(n.bindFramebuffer(t.FRAMEBUFFER,r.__webglFramebuffer[i]),void 0===r.__webglDepthbuffer[i])r.__webglDepthbuffer[i]=t.createRenderbuffer(),U(r.__webglDepthbuffer[i],e,!1);else{const n=e.stencilBuffer?t.DEPTH_STENCIL_ATTACHMENT:t.DEPTH_ATTACHMENT,s=r.__webglDepthbuffer[i];t.bindRenderbuffer(t.RENDERBUFFER,s),t.framebufferRenderbuffer(t.FRAMEBUFFER,n,t.RENDERBUFFER,s)}}else if(n.bindFramebuffer(t.FRAMEBUFFER,r.__webglFramebuffer),void 0===r.__webglDepthbuffer)r.__webglDepthbuffer=t.createRenderbuffer(),U(r.__webglDepthbuffer,e,!1);else{const n=e.stencilBuffer?t.DEPTH_STENCIL_ATTACHMENT:t.DEPTH_ATTACHMENT,i=r.__webglDepthbuffer;t.bindRenderbuffer(t.RENDERBUFFER,i),t.framebufferRenderbuffer(t.FRAMEBUFFER,n,t.RENDERBUFFER,i)}n.bindFramebuffer(t.FRAMEBUFFER,null)}const D=[],O=[];function F(t){return Math.min(r.maxSamples,t.samples)}function B(t){const n=i.get(t);return t.samples>0&&!0===e.has("WEBGL_multisampled_render_to_texture")&&!1!==n.__useRenderToTexture}function z(t,e){const n=t.colorSpace,i=t.format,r=t.type;return!0===t.isCompressedTexture||!0===t.isVideoTexture||n!==Ke&&n!==Ze&&(mi.getTransfer(n)===en?i===kt&&r===Et||console.warn("THREE.WebGLTextures: sRGB encoded textures have to use RGBAFormat and UnsignedByteType."):console.error("THREE.WebGLTextures: Unsupported texture color space:",n)),e}function k(t){return"undefined"!=typeof HTMLImageElement&&t instanceof HTMLImageElement?(c.width=t.naturalWidth||t.width,c.height=t.naturalHeight||t.height):"undefined"!=typeof VideoFrame&&t instanceof VideoFrame?(c.width=t.displayWidth,c.height=t.displayHeight):(c.width=t.width,c.height=t.height),c}this.allocateTextureUnit=function(){const t=w;return t>=r.maxTextures&&console.warn("THREE.WebGLTextures: Trying to use "+t+" texture units while this GPU supports only "+r.maxTextures),w+=1,t},this.resetTextureUnits=function(){w=0},this.setTexture2D=T,this.setTexture2DArray=function(e,r){const s=i.get(e);e.version>0&&s.__version!==e.version?I(s,e,r):n.bindTexture(t.TEXTURE_2D_ARRAY,s.__webglTexture,t.TEXTURE0+r)},this.setTexture3D=function(e,r){const s=i.get(e);e.version>0&&s.__version!==e.version?I(s,e,r):n.bindTexture(t.TEXTURE_3D,s.__webglTexture,t.TEXTURE0+r)},this.setTextureCube=function(e,a){const o=i.get(e);e.version>0&&o.__version!==e.version?function(e,a,o){if(6!==a.image.length)return;const l=P(e,a),c=a.source;n.bindTexture(t.TEXTURE_CUBE_MAP,e.__webglTexture,t.TEXTURE0+o);const h=i.get(c);if(c.version!==h.__version||!0===l){n.activeTexture(t.TEXTURE0+o);const e=mi.getPrimaries(mi.workingColorSpace),i=a.colorSpace===Ze?null:mi.getPrimaries(a.colorSpace),u=a.colorSpace===Ze||e===i?t.NONE:t.BROWSER_DEFAULT_WEBGL;t.pixelStorei(t.UNPACK_FLIP_Y_WEBGL,a.flipY),t.pixelStorei(t.UNPACK_PREMULTIPLY_ALPHA_WEBGL,a.premultiplyAlpha),t.pixelStorei(t.UNPACK_ALIGNMENT,a.unpackAlignment),t.pixelStorei(t.UNPACK_COLORSPACE_CONVERSION_WEBGL,u);const d=a.isCompressedTexture||a.image[0].isCompressedTexture,p=a.image[0]&&a.image[0].isDataTexture,m=[];for(let t=0;t<6;t++)m[t]=d||p?p?a.image[t].image:a.image[t]:f(a.image[t],!0,r.maxCubemapSize),m[t]=z(a,m[t]);const x=m[0],M=s.convert(a.format,a.colorSpace),S=s.convert(a.type),b=_(a.internalFormat,M,S,a.colorSpace),w=!0!==a.isVideoTexture,T=void 0===h.__version||!0===l,E=c.dataReady;let A,R=y(a,x);if(C(t.TEXTURE_CUBE_MAP,a),d){w&&T&&n.texStorage2D(t.TEXTURE_CUBE_MAP,R,b,x.width,x.height);for(let e=0;e<6;e++){A=m[e].mipmaps;for(let i=0;i0&&R++;const e=k(m[0]);n.texStorage2D(t.TEXTURE_CUBE_MAP,R,b,e.width,e.height)}for(let e=0;e<6;e++)if(p){w?E&&n.texSubImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,0,0,0,m[e].width,m[e].height,M,S,m[e].data):n.texImage2D(t.TEXTURE_CUBE_MAP_POSITIVE_X+e,0,b,m[e].width,m[e].height,0,M,S,m[e].data);for(let i=0;i1;if(u||(void 0===l.__webglTexture&&(l.__webglTexture=t.createTexture()),l.__version=r.version,a.memory.textures++),h){o.__webglFramebuffer=[];for(let e=0;e<6;e++)if(r.mipmaps&&r.mipmaps.length>0){o.__webglFramebuffer[e]=[];for(let n=0;n0){o.__webglFramebuffer=[];for(let e=0;e0&&!1===B(e)){o.__webglMultisampledFramebuffer=t.createFramebuffer(),o.__webglColorRenderbuffer=[],n.bindFramebuffer(t.FRAMEBUFFER,o.__webglMultisampledFramebuffer);for(let n=0;n0)for(let i=0;i0)for(let n=0;n0)if(!1===B(e)){const r=e.textures,s=e.width,a=e.height;let o=t.COLOR_BUFFER_BIT;const c=e.stencilBuffer?t.DEPTH_STENCIL_ATTACHMENT:t.DEPTH_ATTACHMENT,h=i.get(e),u=r.length>1;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,n),null!==r&&(o.matrix.fromArray(r.transform.matrix),o.matrix.decompose(o.position,o.rotation,o.scale),o.matrixWorldNeedsUpdate=!0,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&&(i=e.getPose(t.targetRaySpace,n),null===i&&null!==r&&(i=r),null!==i&&(a.matrix.fromArray(i.transform.matrix),a.matrix.decompose(a.position,a.rotation,a.scale),a.matrixWorldNeedsUpdate=!0,i.linearVelocity?(a.hasLinearVelocity=!0,a.linearVelocity.copy(i.linearVelocity)):a.hasLinearVelocity=!1,i.angularVelocity?(a.hasAngularVelocity=!0,a.angularVelocity.copy(i.angularVelocity)):a.hasAngularVelocity=!1,this.dispatchEvent(Jl)))}return null!==a&&(a.visible=null!==i),null!==o&&(o.visible=null!==r),null!==l&&(l.visible=null!==s),this}_getHandJoint(t,e){if(void 0===t.joints[e.jointName]){const n=new Zl;n.matrixAutoUpdate=!1,n.visible=!1,t.joints[e.jointName]=n,t.add(n)}return t.joints[e.jointName]}}class $l{constructor(){this.texture=null,this.mesh=null,this.depthNear=0,this.depthFar=0}init(t,e,n){if(null===this.texture){const i=new bi;t.properties.get(i).__webglTexture=e.texture,e.depthNear==n.depthNear&&e.depthFar==n.depthFar||(this.depthNear=e.depthNear,this.depthFar=e.depthFar),this.texture=i}}getMesh(t){if(null!==this.texture&&null===this.mesh){const e=t.cameras[0].viewport,n=new Ys({vertexShader:"\nvoid main() {\n\n\tgl_Position = vec4( position, 1.0 );\n\n}",fragmentShader:"\nuniform sampler2DArray depthColor;\nuniform float depthWidth;\nuniform float depthHeight;\n\nvoid main() {\n\n\tvec2 coord = vec2( gl_FragCoord.x / depthWidth, gl_FragCoord.y / depthHeight );\n\n\tif ( coord.x >= 1.0 ) {\n\n\t\tgl_FragDepth = texture( depthColor, vec3( coord.x - 1.0, coord.y, 1 ) ).r;\n\n\t} else {\n\n\t\tgl_FragDepth = texture( depthColor, vec3( coord.x, coord.y, 0 ) ).r;\n\n\t}\n\n}",uniforms:{depthColor:{value:this.texture},depthWidth:{value:e.z},depthHeight:{value:e.w}}});this.mesh=new Vs(new pa(20,20),n)}return this.mesh}reset(){this.texture=null,this.mesh=null}getDepthTexture(){return this.texture}}class Ql extends Hn{constructor(t,e){super();const n=this;let i=null,r=1,s=null,a="local-floor",o=1,l=null,c=null,h=null,u=null,d=null,p=null;const m=new $l,f=e.getContextAttributes();let g=null,v=null;const _=[],x=[],y=new ti;let M=null;const S=new Qs;S.layers.enable(1),S.viewport=new wi;const b=new Qs;b.layers.enable(2),b.viewport=new wi;const w=[S,b],T=new Yl;T.layers.enable(1),T.layers.enable(2);let E=null,A=null;function R(t){const e=x.indexOf(t.inputSource);if(-1===e)return;const n=_[e];void 0!==n&&(n.update(t.inputSource,t.frame,l||s),n.dispatchEvent({type:t.type,data:t.inputSource}))}function C(){i.removeEventListener("select",R),i.removeEventListener("selectstart",R),i.removeEventListener("selectend",R),i.removeEventListener("squeeze",R),i.removeEventListener("squeezestart",R),i.removeEventListener("squeezeend",R),i.removeEventListener("end",C),i.removeEventListener("inputsourceschange",P);for(let t=0;t<_.length;t++){const e=x[t];null!==e&&(x[t]=null,_[t].disconnect(e))}E=null,A=null,m.reset(),t.setRenderTarget(g),d=null,u=null,h=null,i=null,v=null,D.stop(),n.isPresenting=!1,t.setPixelRatio(M),t.setSize(y.width,y.height,!1),n.dispatchEvent({type:"sessionend"})}function P(t){for(let e=0;e=0&&(x[i]=null,_[i].disconnect(n))}for(let e=0;e=x.length){x.push(n),i=t;break}if(null===x[t]){x[t]=n,i=t;break}}if(-1===i)break}const r=_[i];r&&r.connect(n)}}this.cameraAutoUpdate=!0,this.enabled=!1,this.isPresenting=!1,this.getController=function(t){let e=_[t];return void 0===e&&(e=new Kl,_[t]=e),e.getTargetRaySpace()},this.getControllerGrip=function(t){let e=_[t];return void 0===e&&(e=new Kl,_[t]=e),e.getGripSpace()},this.getHand=function(t){let e=_[t];return void 0===e&&(e=new Kl,_[t]=e),e.getHandSpace()},this.setFramebufferScaleFactor=function(t){r=t,!0===n.isPresenting&&console.warn("THREE.WebXRManager: Cannot change framebuffer scale while presenting.")},this.setReferenceSpaceType=function(t){a=t,!0===n.isPresenting&&console.warn("THREE.WebXRManager: Cannot change reference space type while presenting.")},this.getReferenceSpace=function(){return l||s},this.setReferenceSpace=function(t){l=t},this.getBaseLayer=function(){return null!==u?u:d},this.getBinding=function(){return h},this.getFrame=function(){return p},this.getSession=function(){return i},this.setSession=async function(c){if(i=c,null!==i){if(g=t.getRenderTarget(),i.addEventListener("select",R),i.addEventListener("selectstart",R),i.addEventListener("selectend",R),i.addEventListener("squeeze",R),i.addEventListener("squeezestart",R),i.addEventListener("squeezeend",R),i.addEventListener("end",C),i.addEventListener("inputsourceschange",P),!0!==f.xrCompatible&&await e.makeXRCompatible(),M=t.getPixelRatio(),t.getSize(y),void 0===i.renderState.layers){const n={antialias:f.antialias,alpha:!0,depth:f.depth,stencil:f.stencil,framebufferScaleFactor:r};d=new XRWebGLLayer(i,e,n),i.updateRenderState({baseLayer:d}),t.setPixelRatio(1),t.setSize(d.framebufferWidth,d.framebufferHeight,!1),v=new Ei(d.framebufferWidth,d.framebufferHeight,{format:kt,type:Et,colorSpace:t.outputColorSpace,stencilBuffer:f.stencil})}else{let n=null,s=null,a=null;f.depth&&(a=f.stencil?e.DEPTH24_STENCIL8:e.DEPTH_COMPONENT24,n=f.stencil?Wt:Gt,s=f.stencil?Ot:It);const o={colorFormat:e.RGBA8,depthFormat:a,scaleFactor:r};h=new XRWebGLBinding(i,e),u=h.createProjectionLayer(o),i.updateRenderState({layers:[u]}),t.setPixelRatio(1),t.setSize(u.textureWidth,u.textureHeight,!1),v=new Ei(u.textureWidth,u.textureHeight,{format:kt,type:Et,depthTexture:new Ka(u.textureWidth,u.textureHeight,s,void 0,void 0,void 0,void 0,void 0,void 0,n),stencilBuffer:f.stencil,colorSpace:t.outputColorSpace,samples:f.antialias?4:0,resolveDepthBuffer:!1===u.ignoreDepthValues})}v.isXRRenderTarget=!0,this.setFoveation(o),l=null,s=await i.requestReferenceSpace(a),D.setContext(i),D.start(),n.isPresenting=!0,n.dispatchEvent({type:"sessionstart"})}},this.getEnvironmentBlendMode=function(){if(null!==i)return i.environmentBlendMode},this.getDepthTexture=function(){return m.getDepthTexture()};const I=new Li,L=new Li;function U(t,e){null===e?t.matrixWorld.copy(t.matrix):t.matrixWorld.multiplyMatrices(e.matrixWorld,t.matrix),t.matrixWorldInverse.copy(t.matrixWorld).invert()}this.updateCamera=function(t){if(null===i)return;let e=t.near,n=t.far;null!==m.texture&&(m.depthNear>0&&(e=m.depthNear),m.depthFar>0&&(n=m.depthFar)),T.near=b.near=S.near=e,T.far=b.far=S.far=n,E===T.near&&A===T.far||(i.updateRenderState({depthNear:T.near,depthFar:T.far}),E=T.near,A=T.far);const r=t.parent,s=T.cameras;U(T,r);for(let t=0;t0&&(t.alphaTest.value=i.alphaTest);const r=e.get(i),s=r.envMap,a=r.envMapRotation;s&&(t.envMap.value=s,tc.copy(a),tc.x*=-1,tc.y*=-1,tc.z*=-1,s.isCubeTexture&&!1===s.isRenderTargetTexture&&(tc.y*=-1,tc.z*=-1),t.envMapRotation.value.setFromMatrix4(ec.makeRotationFromEuler(tc)),t.flipEnvMap.value=s.isCubeTexture&&!1===s.isRenderTargetTexture?-1:1,t.reflectivity.value=i.reflectivity,t.ior.value=i.ior,t.refractionRatio.value=i.refractionRatio),i.lightMap&&(t.lightMap.value=i.lightMap,t.lightMapIntensity.value=i.lightMapIntensity,n(i.lightMap,t.lightMapTransform)),i.aoMap&&(t.aoMap.value=i.aoMap,t.aoMapIntensity.value=i.aoMapIntensity,n(i.aoMap,t.aoMapTransform))}return{refreshFogUniforms:function(e,n){n.color.getRGB(e.fogColor.value,js(t)),n.isFog?(e.fogNear.value=n.near,e.fogFar.value=n.far):n.isFogExp2&&(e.fogDensity.value=n.density)},refreshMaterialUniforms:function(t,r,s,a,o){r.isMeshBasicMaterial||r.isMeshLambertMaterial?i(t,r):r.isMeshToonMaterial?(i(t,r),function(t,e){e.gradientMap&&(t.gradientMap.value=e.gradientMap)}(t,r)):r.isMeshPhongMaterial?(i(t,r),function(t,e){t.specular.value.copy(e.specular),t.shininess.value=Math.max(e.shininess,1e-4)}(t,r)):r.isMeshStandardMaterial?(i(t,r),function(t,e){t.metalness.value=e.metalness,e.metalnessMap&&(t.metalnessMap.value=e.metalnessMap,n(e.metalnessMap,t.metalnessMapTransform));t.roughness.value=e.roughness,e.roughnessMap&&(t.roughnessMap.value=e.roughnessMap,n(e.roughnessMap,t.roughnessMapTransform));e.envMap&&(t.envMapIntensity.value=e.envMapIntensity)}(t,r),r.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,n(e.sheenColorMap,t.sheenColorMapTransform)),e.sheenRoughnessMap&&(t.sheenRoughnessMap.value=e.sheenRoughnessMap,n(e.sheenRoughnessMap,t.sheenRoughnessMapTransform)));e.clearcoat>0&&(t.clearcoat.value=e.clearcoat,t.clearcoatRoughness.value=e.clearcoatRoughness,e.clearcoatMap&&(t.clearcoatMap.value=e.clearcoatMap,n(e.clearcoatMap,t.clearcoatMapTransform)),e.clearcoatRoughnessMap&&(t.clearcoatRoughnessMap.value=e.clearcoatRoughnessMap,n(e.clearcoatRoughnessMap,t.clearcoatRoughnessMapTransform)),e.clearcoatNormalMap&&(t.clearcoatNormalMap.value=e.clearcoatNormalMap,n(e.clearcoatNormalMap,t.clearcoatNormalMapTransform),t.clearcoatNormalScale.value.copy(e.clearcoatNormalScale),e.side===d&&t.clearcoatNormalScale.value.negate()));e.dispersion>0&&(t.dispersion.value=e.dispersion);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,n(e.iridescenceMap,t.iridescenceMapTransform)),e.iridescenceThicknessMap&&(t.iridescenceThicknessMap.value=e.iridescenceThicknessMap,n(e.iridescenceThicknessMap,t.iridescenceThicknessMapTransform)));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,n(e.transmissionMap,t.transmissionMapTransform)),t.thickness.value=e.thickness,e.thicknessMap&&(t.thicknessMap.value=e.thicknessMap,n(e.thicknessMap,t.thicknessMapTransform)),t.attenuationDistance.value=e.attenuationDistance,t.attenuationColor.value.copy(e.attenuationColor));e.anisotropy>0&&(t.anisotropyVector.value.set(e.anisotropy*Math.cos(e.anisotropyRotation),e.anisotropy*Math.sin(e.anisotropyRotation)),e.anisotropyMap&&(t.anisotropyMap.value=e.anisotropyMap,n(e.anisotropyMap,t.anisotropyMapTransform)));t.specularIntensity.value=e.specularIntensity,t.specularColor.value.copy(e.specularColor),e.specularColorMap&&(t.specularColorMap.value=e.specularColorMap,n(e.specularColorMap,t.specularColorMapTransform));e.specularIntensityMap&&(t.specularIntensityMap.value=e.specularIntensityMap,n(e.specularIntensityMap,t.specularIntensityMapTransform))}(t,r,o)):r.isMeshMatcapMaterial?(i(t,r),function(t,e){e.matcap&&(t.matcap.value=e.matcap)}(t,r)):r.isMeshDepthMaterial?i(t,r):r.isMeshDistanceMaterial?(i(t,r),function(t,n){const i=e.get(n).light;t.referencePosition.value.setFromMatrixPosition(i.matrixWorld),t.nearDistance.value=i.shadow.camera.near,t.farDistance.value=i.shadow.camera.far}(t,r)):r.isMeshNormalMaterial?i(t,r):r.isLineBasicMaterial?(function(t,e){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,e.map&&(t.map.value=e.map,n(e.map,t.mapTransform))}(t,r),r.isLineDashedMaterial&&function(t,e){t.dashSize.value=e.dashSize,t.totalSize.value=e.dashSize+e.gapSize,t.scale.value=e.scale}(t,r)):r.isPointsMaterial?function(t,e,i,r){t.diffuse.value.copy(e.color),t.opacity.value=e.opacity,t.size.value=e.size*i,t.scale.value=.5*r,e.map&&(t.map.value=e.map,n(e.map,t.uvTransform));e.alphaMap&&(t.alphaMap.value=e.alphaMap,n(e.alphaMap,t.alphaMapTransform));e.alphaTest>0&&(t.alphaTest.value=e.alphaTest)}(t,r,s,a):r.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,n(e.map,t.mapTransform));e.alphaMap&&(t.alphaMap.value=e.alphaMap,n(e.alphaMap,t.alphaMapTransform));e.alphaTest>0&&(t.alphaTest.value=e.alphaTest)}(t,r):r.isShadowMaterial?(t.color.value.copy(r.color),t.opacity.value=r.opacity):r.isShaderMaterial&&(r.uniformsNeedUpdate=!1)}}}function ic(t,e,n,i){let r={},s={},a=[];const o=t.getParameter(t.MAX_UNIFORM_BUFFER_BINDINGS);function l(t,e,n,i){const r=t.value,s=e+"_"+n;if(void 0===i[s])return i[s]="number"==typeof r||"boolean"==typeof r?r:r.clone(),!0;{const t=i[s];if("number"==typeof r||"boolean"==typeof r){if(t!==r)return i[s]=r,!0}else if(!1===t.equals(r))return t.copy(r),!0}return!1}function c(t){const e={boundary:0,storage:0};return"number"==typeof t||"boolean"==typeof t?(e.boundary=4,e.storage=4):t.isVector2?(e.boundary=8,e.storage=8):t.isVector3||t.isColor?(e.boundary=16,e.storage=12):t.isVector4?(e.boundary=16,e.storage=16):t.isMatrix3?(e.boundary=48,e.storage=48):t.isMatrix4?(e.boundary=64,e.storage=64):t.isTexture?console.warn("THREE.WebGLRenderer: Texture samplers can not be part of an uniforms group."):console.warn("THREE.WebGLRenderer: Unsupported uniform value type.",t),e}function h(e){const n=e.target;n.removeEventListener("dispose",h);const i=a.indexOf(n.__bindingPointIndex);a.splice(i,1),t.deleteBuffer(r[n.id]),delete r[n.id],delete s[n.id]}return{bind:function(t,e){const n=e.program;i.uniformBlockBinding(t,n)},update:function(n,u){let d=r[n.id];void 0===d&&(!function(t){const e=t.uniforms;let n=0;const i=16;for(let t=0,r=e.length;t0&&(n+=i-r);t.__size=n,t.__cache={}}(n),d=function(e){const n=function(){for(let t=0;t0),u=!!n.morphAttributes.position,d=!!n.morphAttributes.normal,p=!!n.morphAttributes.color;let m=K;i.toneMapped&&(null!==T&&!0!==T.isXRRenderTarget||(m=M.toneMapping));const f=n.morphAttributes.position||n.morphAttributes.normal||n.morphAttributes.color,g=void 0!==f?f.length:0,v=nt.get(i),x=_.state.lights;if(!0===H&&(!0===G||t!==A)){const e=t===A&&i.id===E;pt.setState(i,t,e)}let y=!1;i.version===v.__version?v.needsLights&&v.lightsStateVersion!==x.state.version||v.outputColorSpace!==o||r.isBatchedMesh&&!1===v.batching?y=!0:r.isBatchedMesh||!0!==v.batching?r.isBatchedMesh&&!0===v.batchingColor&&null===r.colorTexture||r.isBatchedMesh&&!1===v.batchingColor&&null!==r.colorTexture||r.isInstancedMesh&&!1===v.instancing?y=!0:r.isInstancedMesh||!0!==v.instancing?r.isSkinnedMesh&&!1===v.skinning?y=!0:r.isSkinnedMesh||!0!==v.skinning?r.isInstancedMesh&&!0===v.instancingColor&&null===r.instanceColor||r.isInstancedMesh&&!1===v.instancingColor&&null!==r.instanceColor||r.isInstancedMesh&&!0===v.instancingMorph&&null===r.morphTexture||r.isInstancedMesh&&!1===v.instancingMorph&&null!==r.morphTexture||v.envMap!==l||!0===i.fog&&v.fog!==s?y=!0:void 0===v.numClippingPlanes||v.numClippingPlanes===pt.numPlanes&&v.numIntersection===pt.numIntersection?(v.vertexAlphas!==c||v.vertexTangents!==h||v.morphTargets!==u||v.morphNormals!==d||v.morphColors!==p||v.toneMapping!==m||v.morphTargetsCount!==g)&&(y=!0):y=!0:y=!0:y=!0:y=!0:(y=!0,v.__version=i.version);let S=v.currentProgram;!0===y&&(S=Kt(i,e,r));let b=!1,w=!1,R=!1;const C=S.getUniforms(),P=v.uniforms;tt.useProgram(S.program)&&(b=!0,w=!0,R=!0);i.id!==E&&(E=i.id,w=!0);if(b||A!==t){Q.reverseDepthBuffer?(W.copy(t.projectionMatrix),function(t){const e=t.elements;e[2]=.5*e[2]+.5*e[3],e[6]=.5*e[6]+.5*e[7],e[10]=.5*e[10]+.5*e[11],e[14]=.5*e[14]+.5*e[15]}(W),function(t){const e=t.elements;-1===e[11]?(e[10]=-e[10]-1,e[14]=-e[14]):(e[10]=-e[10],e[14]=1-e[14])}(W),C.setValue(St,"projectionMatrix",W)):C.setValue(St,"projectionMatrix",t.projectionMatrix),C.setValue(St,"viewMatrix",t.matrixWorldInverse);const e=C.map.cameraPosition;void 0!==e&&e.setValue(St,j.setFromMatrixPosition(t.matrixWorld)),Q.logarithmicDepthBuffer&&C.setValue(St,"logDepthBufFC",2/(Math.log(t.far+1)/Math.LN2)),(i.isMeshPhongMaterial||i.isMeshToonMaterial||i.isMeshLambertMaterial||i.isMeshBasicMaterial||i.isMeshStandardMaterial||i.isShaderMaterial)&&C.setValue(St,"isOrthographic",!0===t.isOrthographicCamera),A!==t&&(A=t,w=!0,R=!0)}if(r.isSkinnedMesh){C.setOptional(St,r,"bindMatrix"),C.setOptional(St,r,"bindMatrixInverse");const t=r.skeleton;t&&(null===t.boneTexture&&t.computeBoneTexture(),C.setValue(St,"boneTexture",t.boneTexture,it))}r.isBatchedMesh&&(C.setOptional(St,r,"batchingTexture"),C.setValue(St,"batchingTexture",r._matricesTexture,it),C.setOptional(St,r,"batchingIdTexture"),C.setValue(St,"batchingIdTexture",r._indirectTexture,it),C.setOptional(St,r,"batchingColorTexture"),null!==r._colorsTexture&&C.setValue(St,"batchingColorTexture",r._colorsTexture,it));const I=n.morphAttributes;void 0===I.position&&void 0===I.normal&&void 0===I.color||gt.update(r,n,S);(w||v.receiveShadow!==r.receiveShadow)&&(v.receiveShadow=r.receiveShadow,C.setValue(St,"receiveShadow",r.receiveShadow));i.isMeshGouraudMaterial&&null!==i.envMap&&(P.envMap.value=l,P.flipEnvMap.value=l.isCubeTexture&&!1===l.isRenderTargetTexture?-1:1);i.isMeshStandardMaterial&&null===i.envMap&&null!==e.environment&&(P.envMapIntensity.value=e.environmentIntensity);w&&(C.setValue(St,"toneMappingExposure",M.toneMappingExposure),v.needsLights&&(U=R,(L=P).ambientLightColor.needsUpdate=U,L.lightProbe.needsUpdate=U,L.directionalLights.needsUpdate=U,L.directionalLightShadows.needsUpdate=U,L.pointLights.needsUpdate=U,L.pointLightShadows.needsUpdate=U,L.spotLights.needsUpdate=U,L.spotLightShadows.needsUpdate=U,L.rectAreaLights.needsUpdate=U,L.hemisphereLights.needsUpdate=U),s&&!0===i.fog&&ht.refreshFogUniforms(P,s),ht.refreshMaterialUniforms(P,i,D,N,_.state.transmissionRenderTarget[t.id]),il.upload(St,$t(v),P,it));var L,U;i.isShaderMaterial&&!0===i.uniformsNeedUpdate&&(il.upload(St,$t(v),P,it),i.uniformsNeedUpdate=!1);i.isSpriteMaterial&&C.setValue(St,"center",r.center);if(C.setValue(St,"modelViewMatrix",r.modelViewMatrix),C.setValue(St,"normalMatrix",r.normalMatrix),C.setValue(St,"modelMatrix",r.matrixWorld),i.isShaderMaterial||i.isRawShaderMaterial){const t=i.uniformsGroups;for(let e=0,n=t.length;e{function n(){i.forEach((function(t){nt.get(t).currentProgram.isReady()&&i.delete(t)})),0!==i.size?setTimeout(n,10):e(t)}null!==$.get("KHR_parallel_shader_compile")?n():setTimeout(n,10)}))};let zt=null;function kt(){Ht.stop()}function Vt(){Ht.start()}const Ht=new ua;function Gt(t,e,n,i){if(!1===t.visible)return;if(t.layers.test(e.layers))if(t.isGroup)n=t.renderOrder;else if(t.isLOD)!0===t.autoUpdate&&t.update(e);else if(t.isLight)_.pushLight(t),t.castShadow&&_.pushShadow(t);else if(t.isSprite){if(!t.frustumCulled||V.intersectsSprite(t)){i&&q.setFromMatrixPosition(t.matrixWorld).applyMatrix4(X);const e=lt.update(t),r=t.material;r.visible&&v.push(t,e,r,n,q.z,null)}}else if((t.isMesh||t.isLine||t.isPoints)&&(!t.frustumCulled||V.intersectsObject(t))){const e=lt.update(t),r=t.material;if(i&&(void 0!==t.boundingSphere?(null===t.boundingSphere&&t.computeBoundingSphere(),q.copy(t.boundingSphere.center)):(null===e.boundingSphere&&e.computeBoundingSphere(),q.copy(e.boundingSphere.center)),q.applyMatrix4(t.matrixWorld).applyMatrix4(X)),Array.isArray(r)){const i=e.groups;for(let s=0,a=i.length;s0&&qt(r,e,n),s.length>0&&qt(s,e,n),a.length>0&&qt(a,e,n),tt.buffers.depth.setTest(!0),tt.buffers.depth.setMask(!0),tt.buffers.color.setMask(!0),tt.setPolygonOffset(!1)}function Xt(t,e,n,i){if(null!==(!0===n.isScene?n.overrideMaterial:null))return;void 0===_.state.transmissionRenderTarget[i.id]&&(_.state.transmissionRenderTarget[i.id]=new Ei(1,1,{generateMipmaps:!0,type:$.has("EXT_color_buffer_half_float")||$.has("EXT_color_buffer_float")?Ut:Et,minFilter:wt,samples:4,stencilBuffer:s,resolveDepthBuffer:!1,resolveStencilBuffer:!1,colorSpace:mi.workingColorSpace}));const r=_.state.transmissionRenderTarget[i.id],a=i.viewport||R;r.setSize(a.z,a.w);const o=M.getRenderTarget();M.setRenderTarget(r),M.getClearColor(I),L=M.getClearAlpha(),L<1&&M.setClearColor(16777215,.5),M.clear(),Z&&ft.render(n);const l=M.toneMapping;M.toneMapping=K;const c=i.viewport;if(void 0!==i.viewport&&(i.viewport=void 0),_.setupLightsView(i),!0===H&&pt.setGlobalState(M.clippingPlanes,i),qt(t,n,i),it.updateMultisampleRenderTarget(r),it.updateRenderTargetMipmap(r),!1===$.has("WEBGL_multisampled_render_to_texture")){let t=!1;for(let r=0,s=e.length;r0)for(let e=0,s=n.length;e0&&Xt(i,r,t,e),Z&&ft.render(t),Wt(v,t,e);null!==T&&(it.updateMultisampleRenderTarget(T),it.updateRenderTargetMipmap(T)),!0===t.isScene&&t.onAfterRender(M,t,e),yt.resetDefaultState(),E=-1,A=null,y.pop(),y.length>0?(_=y[y.length-1],!0===H&&pt.setGlobalState(M.clippingPlanes,_.state.camera)):_=null,x.pop(),v=x.length>0?x[x.length-1]:null},this.getActiveCubeFace=function(){return b},this.getActiveMipmapLevel=function(){return w},this.getRenderTarget=function(){return T},this.setRenderTargetTextures=function(t,e,n){nt.get(t.texture).__webglTexture=e,nt.get(t.depthTexture).__webglTexture=n;const i=nt.get(t);i.__hasExternalTextures=!0,i.__autoAllocateDepthBuffer=void 0===n,i.__autoAllocateDepthBuffer||!0===$.has("WEBGL_multisampled_render_to_texture")&&(console.warn("THREE.WebGLRenderer: Render-to-texture extension was disabled because an external texture was provided"),i.__useRenderToTexture=!1)},this.setRenderTargetFramebuffer=function(t,e){const n=nt.get(t);n.__webglFramebuffer=e,n.__useDefaultFramebuffer=void 0===e},this.setRenderTarget=function(t,e=0,n=0){T=t,b=e,w=n;let i=!0,r=null,s=!1,a=!1;if(t){const o=nt.get(t);if(void 0!==o.__useDefaultFramebuffer)tt.bindFramebuffer(St.FRAMEBUFFER,null),i=!1;else if(void 0===o.__webglFramebuffer)it.setupRenderTarget(t);else if(o.__hasExternalTextures)it.rebindTextures(t,nt.get(t.texture).__webglTexture,nt.get(t.depthTexture).__webglTexture);else if(t.depthBuffer){const e=t.depthTexture;if(o.__boundDepthTexture!==e){if(null!==e&&nt.has(e)&&(t.width!==e.image.width||t.height!==e.image.height))throw new Error("WebGLRenderTarget: Attached DepthTexture is initialized to the incorrect size.");it.setupDepthRenderbuffer(t)}}const l=t.texture;(l.isData3DTexture||l.isDataArrayTexture||l.isCompressedArrayTexture)&&(a=!0);const c=nt.get(t).__webglFramebuffer;t.isWebGLCubeRenderTarget?(r=Array.isArray(c[e])?c[e][n]:c[e],s=!0):r=t.samples>0&&!1===it.useMultisampledRTT(t)?nt.get(t).__webglMultisampledFramebuffer:Array.isArray(c)?c[n]:c,R.copy(t.viewport),C.copy(t.scissor),P=t.scissorTest}else R.copy(B).multiplyScalar(D).floor(),C.copy(z).multiplyScalar(D).floor(),P=k;if(tt.bindFramebuffer(St.FRAMEBUFFER,r)&&i&&tt.drawBuffers(t,r),tt.viewport(R),tt.scissor(C),tt.setScissorTest(P),s){const i=nt.get(t.texture);St.framebufferTexture2D(St.FRAMEBUFFER,St.COLOR_ATTACHMENT0,St.TEXTURE_CUBE_MAP_POSITIVE_X+e,i.__webglTexture,n)}else if(a){const i=nt.get(t.texture),r=e||0;St.framebufferTextureLayer(St.FRAMEBUFFER,St.COLOR_ATTACHMENT0,i.__webglTexture,n||0,r)}E=-1},this.readRenderTargetPixels=function(t,e,n,i,r,s,a){if(!t||!t.isWebGLRenderTarget)return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=nt.get(t).__webglFramebuffer;if(t.isWebGLCubeRenderTarget&&void 0!==a&&(o=o[a]),o){tt.bindFramebuffer(St.FRAMEBUFFER,o);try{const a=t.texture,o=a.format,l=a.type;if(!Q.textureFormatReadable(o))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in RGBA or implementation defined format.");if(!Q.textureTypeReadable(l))return void console.error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not in UnsignedByteType or implementation defined type.");e>=0&&e<=t.width-i&&n>=0&&n<=t.height-r&&St.readPixels(e,n,i,r,xt.convert(o),xt.convert(l),s)}finally{const t=null!==T?nt.get(T).__webglFramebuffer:null;tt.bindFramebuffer(St.FRAMEBUFFER,t)}}},this.readRenderTargetPixelsAsync=async function(t,e,n,i,r,s,a){if(!t||!t.isWebGLRenderTarget)throw new Error("THREE.WebGLRenderer.readRenderTargetPixels: renderTarget is not THREE.WebGLRenderTarget.");let o=nt.get(t).__webglFramebuffer;if(t.isWebGLCubeRenderTarget&&void 0!==a&&(o=o[a]),o){const a=t.texture,l=a.format,c=a.type;if(!Q.textureFormatReadable(l))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in RGBA or implementation defined format.");if(!Q.textureTypeReadable(c))throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: renderTarget is not in UnsignedByteType or implementation defined type.");if(e>=0&&e<=t.width-i&&n>=0&&n<=t.height-r){tt.bindFramebuffer(St.FRAMEBUFFER,o);const t=St.createBuffer();St.bindBuffer(St.PIXEL_PACK_BUFFER,t),St.bufferData(St.PIXEL_PACK_BUFFER,s.byteLength,St.STREAM_READ),St.readPixels(e,n,i,r,xt.convert(l),xt.convert(c),0);const a=null!==T?nt.get(T).__webglFramebuffer:null;tt.bindFramebuffer(St.FRAMEBUFFER,a);const h=St.fenceSync(St.SYNC_GPU_COMMANDS_COMPLETE,0);return St.flush(),await function(t,e,n){return new Promise((function(i,r){setTimeout((function s(){switch(t.clientWaitSync(e,t.SYNC_FLUSH_COMMANDS_BIT,0)){case t.WAIT_FAILED:r();break;case t.TIMEOUT_EXPIRED:setTimeout(s,n);break;default:i()}}),n)}))}(St,h,4),St.bindBuffer(St.PIXEL_PACK_BUFFER,t),St.getBufferSubData(St.PIXEL_PACK_BUFFER,0,s),St.deleteBuffer(t),St.deleteSync(h),s}throw new Error("THREE.WebGLRenderer.readRenderTargetPixelsAsync: requested read bounds are out of range.")}},this.copyFramebufferToTexture=function(t,e=null,n=0){!0!==t.isTexture&&(ci("WebGLRenderer: copyFramebufferToTexture function signature has changed."),e=arguments[0]||null,t=arguments[1]);const i=Math.pow(2,-n),r=Math.floor(t.image.width*i),s=Math.floor(t.image.height*i),a=null!==e?e.x:0,o=null!==e?e.y:0;it.setTexture2D(t,0),St.copyTexSubImage2D(St.TEXTURE_2D,n,0,0,a,o,r,s),tt.unbindTexture()},this.copyTextureToTexture=function(t,e,n=null,i=null,r=0){let s,a,o,l,c,h;!0!==t.isTexture&&(ci("WebGLRenderer: copyTextureToTexture function signature has changed."),i=arguments[0]||null,t=arguments[1],e=arguments[2],r=arguments[3]||0,n=null),null!==n?(s=n.max.x-n.min.x,a=n.max.y-n.min.y,o=n.min.x,l=n.min.y):(s=t.image.width,a=t.image.height,o=0,l=0),null!==i?(c=i.x,h=i.y):(c=0,h=0);const u=xt.convert(e.format),d=xt.convert(e.type);it.setTexture2D(e,0),St.pixelStorei(St.UNPACK_FLIP_Y_WEBGL,e.flipY),St.pixelStorei(St.UNPACK_PREMULTIPLY_ALPHA_WEBGL,e.premultiplyAlpha),St.pixelStorei(St.UNPACK_ALIGNMENT,e.unpackAlignment);const p=St.getParameter(St.UNPACK_ROW_LENGTH),m=St.getParameter(St.UNPACK_IMAGE_HEIGHT),f=St.getParameter(St.UNPACK_SKIP_PIXELS),g=St.getParameter(St.UNPACK_SKIP_ROWS),v=St.getParameter(St.UNPACK_SKIP_IMAGES),_=t.isCompressedTexture?t.mipmaps[r]:t.image;St.pixelStorei(St.UNPACK_ROW_LENGTH,_.width),St.pixelStorei(St.UNPACK_IMAGE_HEIGHT,_.height),St.pixelStorei(St.UNPACK_SKIP_PIXELS,o),St.pixelStorei(St.UNPACK_SKIP_ROWS,l),t.isDataTexture?St.texSubImage2D(St.TEXTURE_2D,r,c,h,s,a,u,d,_.data):t.isCompressedTexture?St.compressedTexSubImage2D(St.TEXTURE_2D,r,c,h,_.width,_.height,u,_.data):St.texSubImage2D(St.TEXTURE_2D,r,c,h,s,a,u,d,_),St.pixelStorei(St.UNPACK_ROW_LENGTH,p),St.pixelStorei(St.UNPACK_IMAGE_HEIGHT,m),St.pixelStorei(St.UNPACK_SKIP_PIXELS,f),St.pixelStorei(St.UNPACK_SKIP_ROWS,g),St.pixelStorei(St.UNPACK_SKIP_IMAGES,v),0===r&&e.generateMipmaps&&St.generateMipmap(St.TEXTURE_2D),tt.unbindTexture()},this.copyTextureToTexture3D=function(t,e,n=null,i=null,r=0){let s,a,o,l,c,h,u,d,p;!0!==t.isTexture&&(ci("WebGLRenderer: copyTextureToTexture3D function signature has changed."),n=arguments[0]||null,i=arguments[1]||null,t=arguments[2],e=arguments[3],r=arguments[4]||0);const m=t.isCompressedTexture?t.mipmaps[r]:t.image;null!==n?(s=n.max.x-n.min.x,a=n.max.y-n.min.y,o=n.max.z-n.min.z,l=n.min.x,c=n.min.y,h=n.min.z):(s=m.width,a=m.height,o=m.depth,l=0,c=0,h=0),null!==i?(u=i.x,d=i.y,p=i.z):(u=0,d=0,p=0);const f=xt.convert(e.format),g=xt.convert(e.type);let v;if(e.isData3DTexture)it.setTexture3D(e,0),v=St.TEXTURE_3D;else{if(!e.isDataArrayTexture&&!e.isCompressedArrayTexture)return void console.warn("THREE.WebGLRenderer.copyTextureToTexture3D: only supports THREE.DataTexture3D and THREE.DataTexture2DArray.");it.setTexture2DArray(e,0),v=St.TEXTURE_2D_ARRAY}St.pixelStorei(St.UNPACK_FLIP_Y_WEBGL,e.flipY),St.pixelStorei(St.UNPACK_PREMULTIPLY_ALPHA_WEBGL,e.premultiplyAlpha),St.pixelStorei(St.UNPACK_ALIGNMENT,e.unpackAlignment);const _=St.getParameter(St.UNPACK_ROW_LENGTH),x=St.getParameter(St.UNPACK_IMAGE_HEIGHT),y=St.getParameter(St.UNPACK_SKIP_PIXELS),M=St.getParameter(St.UNPACK_SKIP_ROWS),S=St.getParameter(St.UNPACK_SKIP_IMAGES);St.pixelStorei(St.UNPACK_ROW_LENGTH,m.width),St.pixelStorei(St.UNPACK_IMAGE_HEIGHT,m.height),St.pixelStorei(St.UNPACK_SKIP_PIXELS,l),St.pixelStorei(St.UNPACK_SKIP_ROWS,c),St.pixelStorei(St.UNPACK_SKIP_IMAGES,h),t.isDataTexture||t.isData3DTexture?St.texSubImage3D(v,r,u,d,p,s,a,o,f,g,m.data):e.isCompressedArrayTexture?St.compressedTexSubImage3D(v,r,u,d,p,s,a,o,f,m.data):St.texSubImage3D(v,r,u,d,p,s,a,o,f,g,m),St.pixelStorei(St.UNPACK_ROW_LENGTH,_),St.pixelStorei(St.UNPACK_IMAGE_HEIGHT,x),St.pixelStorei(St.UNPACK_SKIP_PIXELS,y),St.pixelStorei(St.UNPACK_SKIP_ROWS,M),St.pixelStorei(St.UNPACK_SKIP_IMAGES,S),0===r&&e.generateMipmaps&&St.generateMipmap(v),tt.unbindTexture()},this.initRenderTarget=function(t){void 0===nt.get(t).__webglFramebuffer&&it.setupRenderTarget(t)},this.initTexture=function(t){t.isCubeTexture?it.setTextureCube(t,0):t.isData3DTexture?it.setTexture3D(t,0):t.isDataArrayTexture||t.isCompressedArrayTexture?it.setTexture2DArray(t,0):it.setTexture2D(t,0),tt.unbindTexture()},this.resetState=function(){b=0,w=0,T=null,tt.reset(),yt.reset()},"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}get coordinateSystem(){return kn}get outputColorSpace(){return this._outputColorSpace}set outputColorSpace(t){this._outputColorSpace=t;const e=this.getContext();e.drawingBufferColorSpace=t===$e?"display-p3":"srgb",e.unpackColorSpace=mi.workingColorSpace===Qe?"display-p3":"srgb"}}class sc{constructor(t,e=25e-5){this.isFogExp2=!0,this.name="",this.color=new ts(t),this.density=e}clone(){return new sc(this.color,this.density)}toJSON(){return{type:"FogExp2",name:this.name,color:this.color.getHex(),density:this.density}}}class ac{constructor(t,e=1,n=1e3){this.isFog=!0,this.name="",this.color=new ts(t),this.near=e,this.far=n}clone(){return new ac(this.color,this.near,this.far)}toJSON(){return{type:"Fog",name:this.name,color:this.color.getHex(),near:this.near,far:this.far}}}class oc extends Dr{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.backgroundRotation=new _r,this.environmentIntensity=1,this.environmentRotation=new _r,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,this.backgroundRotation.copy(t.backgroundRotation),this.environmentIntensity=t.environmentIntensity,this.environmentRotation.copy(t.environmentRotation),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.object.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(e.object.backgroundIntensity=this.backgroundIntensity),e.object.backgroundRotation=this.backgroundRotation.toArray(),1!==this.environmentIntensity&&(e.object.environmentIntensity=this.environmentIntensity),e.object.environmentRotation=this.environmentRotation.toArray(),e}}class lc{constructor(t,e){this.isInterleavedBuffer=!0,this.array=t,this.stride=e,this.count=void 0!==t?t.length/e:0,this.usage=Cn,this.updateRanges=[],this.version=0,this.uuid=qn()}onUploadCallback(){}set needsUpdate(t){!0===t&&this.version++}setUsage(t){return this.usage=t,this}addUpdateRange(t,e){this.updateRanges.push({start:t,count:e})}clearUpdateRanges(){this.updateRanges.length=0}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,n){t*=this.stride,n*=e.stride;for(let i=0,r=this.stride;it.far||e.push({distance:o,point:pc.clone(),uv:Zr.getInterpolation(pc,xc,yc,Mc,Sc,bc,wc,new ti),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 Ec(t,e,n,i,r,s){gc.subVectors(t,n).addScalar(.5).multiply(i),void 0!==r?(vc.x=s*gc.x-r*gc.y,vc.y=r*gc.x+s*gc.y):vc.copy(gc),t.copy(e),t.x+=vc.x,t.y+=vc.y,t.applyMatrix4(_c)}const Ac=new Li,Rc=new Li;class Cc extends Dr{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,n=e.length;t0){let n,i;for(n=1,i=e.length;n0){Ac.setFromMatrixPosition(this.matrixWorld);const n=t.ray.origin.distanceTo(Ac);this.getObjectForDistance(n).raycast(t,e)}}update(t){const e=this.levels;if(e.length>1){Ac.setFromMatrixPosition(t.matrixWorld),Rc.setFromMatrixPosition(this.matrixWorld);const n=Ac.distanceTo(Rc)/t.zoom;let i,r;for(e[0].object.visible=!0,i=1,r=e.length;i=t))break;e[i-1].object.visible=!1,e[i].object.visible=!0}for(this._currentLevel=i-1;i=i.length&&i.push({start:-1,count:-1,z:-1,index:-1});const s=i[this.index];r.push(s),this.index++,s.start=t.start,s.count=t.count,s.z=e,s.index=n}reset(){this.list.length=0,this.index=0}}const ih=new lr,rh=new lr,sh=new lr,ah=new ts(1,1,1),oh=new lr,lh=new ha,ch=new Di,hh=new Qi,uh=new Li,dh=new Li,ph=new Li,mh=new nh,fh=new Vs,gh=[];function vh(t,e,n=0){const i=e.itemSize;if(t.isInterleavedBufferAttribute||t.array.constructor!==e.array.constructor){const r=t.count;for(let s=0;s65535?new Uint32Array(i):new Uint16Array(i);e.setIndex(new ds(t,1))}this._geometryInitialized=!0}}_validateGeometry(t){const e=this.geometry;if(Boolean(t.getIndex())!==Boolean(e.getIndex()))throw new Error('BatchedMesh: All geometries must consistently have "index".');for(const n in e.attributes){if(!t.hasAttribute(n))throw new Error(`BatchedMesh: Added geometry missing "${n}". All geometries must have consistent attributes.`);const i=t.getAttribute(n),r=e.getAttribute(n);if(i.itemSize!==r.itemSize||i.normalized!==r.normalized)throw new Error("BatchedMesh: All attributes must have a consistent itemSize and normalized value.")}}setCustomSort(t){return this.customSort=t,this}computeBoundingBox(){null===this.boundingBox&&(this.boundingBox=new Di);const t=this.boundingBox,e=this._drawInfo;t.makeEmpty();for(let n=0,i=e.length;n=this.maxInstanceCount&&0===this._availableInstanceIds.length)throw new Error("BatchedMesh: Maximum item count reached.");const e={visible:!0,active:!0,geometryIndex:t};let n=null;this._availableInstanceIds.length>0?(n=this._availableInstanceIds.pop(),this._drawInfo[n]=e):(n=this._drawInfo.length,this._drawInfo.push(e));const i=this._matricesTexture,r=i.image.data;sh.toArray(r,16*n),i.needsUpdate=!0;const s=this._colorsTexture;return s&&(ah.toArray(s.image.data,4*n),s.needsUpdate=!0),n}addGeometry(t,e=-1,n=-1){if(this._initializeGeometry(t),this._validateGeometry(t),this._drawInfo.length>=this._maxInstanceCount)throw new Error("BatchedMesh: Maximum item count reached.");const i={vertexStart:-1,vertexCount:-1,indexStart:-1,indexCount:-1};let r=null;const s=this._reservedRanges,a=this._drawRanges,o=this._bounds;0!==this._geometryCount&&(r=s[s.length-1]),i.vertexCount=-1===e?t.getAttribute("position").count:e,i.vertexStart=null===r?0:r.vertexStart+r.vertexCount;const l=t.getIndex(),c=null!==l;if(c&&(i.indexCount=-1===n?l.count:n,i.indexStart=null===r?0:r.indexStart+r.indexCount),-1!==i.indexStart&&i.indexStart+i.indexCount>this._maxIndexCount||i.vertexStart+i.vertexCount>this._maxVertexCount)throw new Error("BatchedMesh: Reserved space request exceeds the maximum buffer size.");const h=this._geometryCount;return this._geometryCount++,s.push(i),a.push({start:c?i.indexStart:i.vertexStart,count:-1}),o.push({boxInitialized:!1,box:new Di,sphereInitialized:!1,sphere:new Qi}),this.setGeometryAt(h,t),h}setGeometryAt(t,e){if(t>=this._geometryCount)throw new Error("BatchedMesh: Maximum geometry count reached.");this._validateGeometry(e);const n=this.geometry,i=null!==n.getIndex(),r=n.getIndex(),s=e.getIndex(),a=this._reservedRanges[t];if(i&&s.count>a.indexCount||e.attributes.position.count>a.vertexCount)throw new Error("BatchedMesh: Reserved space not large enough for provided geometry.");const o=a.vertexStart,l=a.vertexCount;for(const t in n.attributes){const i=e.getAttribute(t),r=n.getAttribute(t);vh(i,r,o);const s=i.itemSize;for(let t=i.count,e=l;t=e.length||!1===e[t].active||(e[t].active=!1,this._availableInstanceIds.push(t),this._visibilityChanged=!0),this}getBoundingBoxAt(t,e){if(t>=this._geometryCount)return null;const n=this._bounds[t],i=n.box,r=this.geometry;if(!1===n.boxInitialized){i.makeEmpty();const e=r.index,s=r.attributes.position,a=this._drawRanges[t];for(let t=a.start,n=a.start+a.count;t=this._geometryCount)return null;const n=this._bounds[t],i=n.sphere,r=this.geometry;if(!1===n.sphereInitialized){i.makeEmpty(),this.getBoundingBoxAt(t,ch),ch.getCenter(i.center);const e=r.index,s=r.attributes.position,a=this._drawRanges[t];let o=0;for(let t=a.start,n=a.start+a.count;t=n.length||!1===n[t].active||(e.toArray(r,16*t),i.needsUpdate=!0),this}getMatrixAt(t,e){const n=this._drawInfo,i=this._matricesTexture.image.data;return t>=n.length||!1===n[t].active?null:e.fromArray(i,16*t)}setColorAt(t,e){null===this._colorsTexture&&this._initColorsTexture();const n=this._colorsTexture,i=this._colorsTexture.image.data,r=this._drawInfo;return t>=r.length||!1===r[t].active||(e.toArray(i,4*t),n.needsUpdate=!0),this}getColorAt(t,e){const n=this._colorsTexture.image.data,i=this._drawInfo;return t>=i.length||!1===i[t].active?null:e.fromArray(n,4*t)}setVisibleAt(t,e){const n=this._drawInfo;return t>=n.length||!1===n[t].active||n[t].visible===e||(n[t].visible=e,this._visibilityChanged=!0),this}getVisibleAt(t){const e=this._drawInfo;return!(t>=e.length||!1===e[t].active)&&e[t].visible}setGeometryIdAt(t,e){const n=this._drawInfo;return t>=n.length||!1===n[t].active||e<0||e>=this._geometryCount?null:(n[t].geometryIndex=e,this)}getGeometryIdAt(t){const e=this._drawInfo;return t>=e.length||!1===e[t].active?-1:e[t].geometryIndex}getGeometryRangeAt(t,e={}){if(t<0||t>=this._geometryCount)return null;const n=this._drawRanges[t];return e.start=n.start,e.count=n.count,e}raycast(t,e){const n=this._drawInfo,i=this._drawRanges,r=this.matrixWorld,s=this.geometry;fh.material=this.material,fh.geometry.index=s.index,fh.geometry.attributes=s.attributes,null===fh.geometry.boundingBox&&(fh.geometry.boundingBox=new Di),null===fh.geometry.boundingSphere&&(fh.geometry.boundingSphere=new Qi);for(let s=0,a=n.length;s({...t}))),this._reservedRanges=t._reservedRanges.map((t=>({...t}))),this._drawInfo=t._drawInfo.map((t=>({...t}))),this._bounds=t._bounds.map((t=>({boxInitialized:t.boxInitialized,box:t.box.clone(),sphereInitialized:t.sphereInitialized,sphere:t.sphere.clone()}))),this._maxInstanceCount=t._maxInstanceCount,this._maxVertexCount=t._maxVertexCount,this._maxIndexCount=t._maxIndexCount,this._geometryInitialized=t._geometryInitialized,this._geometryCount=t._geometryCount,this._multiDrawCounts=t._multiDrawCounts.slice(),this._multiDrawStarts=t._multiDrawStarts.slice(),this._matricesTexture=t._matricesTexture.clone(),this._matricesTexture.image.data=this._matricesTexture.image.data.slice(),null!==this._colorsTexture&&(this._colorsTexture=t._colorsTexture.clone(),this._colorsTexture.image.data=this._colorsTexture.image.data.slice()),this}dispose(){return this.geometry.dispose(),this._matricesTexture.dispose(),this._matricesTexture=null,this._indirectTexture.dispose(),this._indirectTexture=null,null!==this._colorsTexture&&(this._colorsTexture.dispose(),this._colorsTexture=null),this}onBeforeRender(t,e,n,i,r){if(!this._visibilityChanged&&!this.perObjectFrustumCulled&&!this.sortObjects)return;const s=i.getIndex(),a=null===s?1:s.array.BYTES_PER_ELEMENT,o=this._drawInfo,l=this._multiDrawStarts,c=this._multiDrawCounts,h=this._drawRanges,u=this.perObjectFrustumCulled,d=this._indirectTexture,p=d.image.data;u&&(oh.multiplyMatrices(n.projectionMatrix,n.matrixWorldInverse).multiply(this.matrixWorld),lh.setFromProjectionMatrix(oh,t.coordinateSystem));let m=0;if(this.sortObjects){rh.copy(this.matrixWorld).invert(),uh.setFromMatrixPosition(n.matrixWorld).applyMatrix4(rh),dh.set(0,0,-1).transformDirection(n.matrixWorld).transformDirection(rh);for(let t=0,e=o.length;t0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;ti)return;Th.applyMatrix4(t.matrixWorld);const o=e.ray.origin.distanceTo(Th);return oe.far?void 0:{distance:o,point:Eh.clone().applyMatrix4(t.matrixWorld),index:r,face:null,faceIndex:null,barycoord:null,object:t}}const Ch=new Li,Ph=new Li;class Ih extends Ah{constructor(t,e){super(t,e),this.isLineSegments=!0,this.type="LineSegments"}computeLineDistances(){const t=this.geometry;if(null===t.index){const e=t.attributes.position,n=[];for(let t=0,i=e.count;t0){const n=t[e[0]];if(void 0!==n){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let t=0,e=n.length;tr.far)return;s.push({distance:l,distanceToRay:Math.sqrt(o),point:n,index:e,face:null,faceIndex:null,barycoord:null,object:a})}}class kh extends bi{constructor(t,e,n,i,r,s,a,o,l){super(t,e,n,i,r,s,a,o,l),this.isVideoTexture=!0,this.minFilter=void 0!==s?s:Mt,this.magFilter=void 0!==r?r:Mt,this.generateMipmaps=!1;const c=this;"requestVideoFrameCallback"in t&&t.requestVideoFrameCallback((function e(){c.needsUpdate=!0,t.requestVideoFrameCallback(e)}))}clone(){return new this.constructor(this.image).copy(this)}update(){const t=this.image;!1==="requestVideoFrameCallback"in t&&t.readyState>=t.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}class Vh extends bi{constructor(t,e){super({width:t,height:e}),this.isFramebufferTexture=!0,this.magFilter=gt,this.minFilter=gt,this.generateMipmaps=!1,this.needsUpdate=!0}}class Hh extends bi{constructor(t,e,n,i,r,s,a,o,l,c,h,u){super(null,s,a,o,l,c,i,r,h,u),this.isCompressedTexture=!0,this.image={width:e,height:n},this.mipmaps=t,this.flipY=!1,this.generateMipmaps=!1}}class Gh extends Hh{constructor(t,e,n,i,r,s){super(t,e,n,r,s),this.isCompressedArrayTexture=!0,this.image.depth=i,this.wrapR=mt,this.layerUpdates=new Set}addLayerUpdate(t){this.layerUpdates.add(t)}clearLayerUpdates(){this.layerUpdates.clear()}}class Wh extends Hh{constructor(t,e,n){super(void 0,t[0].width,t[0].height,e,n,lt),this.isCompressedCubeTexture=!0,this.isCubeTexture=!0,this.image=t}}class Xh extends bi{constructor(t,e,n,i,r,s,a,o,l){super(t,e,n,i,r,s,a,o,l),this.isCanvasTexture=!0,this.needsUpdate=!0}}class jh{constructor(){this.type="Curve",this.arcLengthDivisions=200}getPoint(){return console.warn("THREE.Curve: .getPoint() not implemented."),null}getPointAt(t,e){const n=this.getUtoTmapping(t);return this.getPoint(n,e)}getPoints(t=5){const e=[];for(let n=0;n<=t;n++)e.push(this.getPoint(n/t));return e}getSpacedPoints(t=5){const e=[];for(let n=0;n<=t;n++)e.push(this.getPointAt(n/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 n,i=this.getPoint(0),r=0;e.push(0);for(let s=1;s<=t;s++)n=this.getPoint(s/t),r+=n.distanceTo(i),e.push(r),i=n;return this.cacheArcLengths=e,e}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(t,e){const n=this.getLengths();let i=0;const r=n.length;let s;s=e||t*n[r-1];let a,o=0,l=r-1;for(;o<=l;)if(i=Math.floor(o+(l-o)/2),a=n[i]-s,a<0)o=i+1;else{if(!(a>0)){l=i;break}l=i-1}if(i=l,n[i]===s)return i/(r-1);const c=n[i];return(i+(s-c)/(n[i+1]-c))/(r-1)}getTangent(t,e){const n=1e-4;let i=t-n,r=t+n;i<0&&(i=0),r>1&&(r=1);const s=this.getPoint(i),a=this.getPoint(r),o=e||(s.isVector2?new ti:new Li);return o.copy(a).sub(s).normalize(),o}getTangentAt(t,e){const n=this.getUtoTmapping(t);return this.getTangent(n,e)}computeFrenetFrames(t,e){const n=new Li,i=[],r=[],s=[],a=new Li,o=new lr;for(let e=0;e<=t;e++){const n=e/t;i[e]=this.getTangentAt(n,new Li)}r[0]=new Li,s[0]=new Li;let l=Number.MAX_VALUE;const c=Math.abs(i[0].x),h=Math.abs(i[0].y),u=Math.abs(i[0].z);c<=l&&(l=c,n.set(1,0,0)),h<=l&&(l=h,n.set(0,1,0)),u<=l&&n.set(0,0,1),a.crossVectors(i[0],n).normalize(),r[0].crossVectors(i[0],a),s[0].crossVectors(i[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(i[e-1],i[e]),a.length()>Number.EPSILON){a.normalize();const t=Math.acos(Yn(i[e-1].dot(i[e]),-1,1));r[e].applyMatrix4(o.makeRotationAxis(a,t))}s[e].crossVectors(i[e],r[e])}if(!0===e){let e=Math.acos(Yn(r[0].dot(r[t]),-1,1));e/=t,i[0].dot(a.crossVectors(r[0],r[t]))>0&&(e=-e);for(let n=1;n<=t;n++)r[n].applyMatrix4(o.makeRotationAxis(i[n],e*n)),s[n].crossVectors(i[n],r[n])}return{tangents:i,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.6,type:"Curve",generator:"Curve.toJSON"}};return t.arcLengthDivisions=this.arcLengthDivisions,t.type=this.type,t}fromJSON(t){return this.arcLengthDivisions=t.arcLengthDivisions,this}}class qh extends jh{constructor(t=0,e=0,n=1,i=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=n,this.yRadius=i,this.aStartAngle=r,this.aEndAngle=s,this.aClockwise=a,this.aRotation=o}getPoint(t,e=new ti){const n=e,i=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const s=Math.abs(r)i;)r-=i;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=i[(l-1)%r]:(Jh.subVectors(i[0],i[1]).add(i[0]),a=Jh);const h=i[l%r],u=i[(l+1)%r];if(this.closed||l+2i.length-2?i.length-1:s+1],h=i[s>i.length-3?i.length-1:s+2];return n.set(eu(a,o.x,l.x,c.x,h.x),eu(a,o.y,l.y,c.y,h.y)),n}copy(t){super.copy(t),this.points=[];for(let e=0,n=t.points.length;e=n){const t=i[r]-n,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 n=0,i=this.curves.length;n1&&!e[e.length-1].equals(e[0])&&e.push(e[0]),e}copy(t){super.copy(t),this.curves=[];for(let e=0,n=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 mu extends Cs{constructor(t=[new ti(0,-.5),new ti(.5,0),new ti(0,.5)],e=12,n=0,i=2*Math.PI){super(),this.type="LatheGeometry",this.parameters={points:t,segments:e,phiStart:n,phiLength:i},e=Math.floor(e),i=Yn(i,0,2*Math.PI);const r=[],s=[],a=[],o=[],l=[],c=1/e,h=new Li,u=new ti,d=new Li,p=new Li,m=new Li;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=n+r*c*i,p=Math.sin(d),m=Math.cos(d);for(let n=0;n<=t.length-1;n++){h.x=t[n].x*p,h.y=t[n].y,h.z=t[n].x*m,s.push(h.x,h.y,h.z),u.x=r/e,u.y=n/(t.length-1),a.push(u.x,u.y);const i=o[3*n+0]*p,c=o[3*n+1],d=o[3*n+0]*m;l.push(i,c,d)}}for(let n=0;n0&&(c.push(r,s,o),_+=3),e>0&&(c.push(s,a,o),_+=3)}l.addGroup(g,_,0),g+=_}(),!1===s&&(t>0&&v(!0),e>0&&v(!1)),this.setIndex(c),this.setAttribute("position",new Ms(h,3)),this.setAttribute("normal",new Ms(u,3)),this.setAttribute("uv",new Ms(d,2))}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new vu(t.radiusTop,t.radiusBottom,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class _u extends vu{constructor(t=1,e=1,n=32,i=1,r=!1,s=0,a=2*Math.PI){super(0,t,e,n,i,r,s,a),this.type="ConeGeometry",this.parameters={radius:t,height:e,radialSegments:n,heightSegments:i,openEnded:r,thetaStart:s,thetaLength:a}}static fromJSON(t){return new _u(t.radius,t.height,t.radialSegments,t.heightSegments,t.openEnded,t.thetaStart,t.thetaLength)}}class xu extends Cs{constructor(t=[],e=[],n=1,i=0){super(),this.type="PolyhedronGeometry",this.parameters={vertices:t,indices:e,radius:n,detail:i};const r=[],s=[];function a(t,e,n,i){const r=i+1,s=[];for(let i=0;i<=r;i++){s[i]=[];const a=t.clone().lerp(n,i/r),o=e.clone().lerp(n,i/r),l=r-i;for(let t=0;t<=l;t++)s[i][t]=0===t&&i===r?a:a.clone().lerp(o,t/l)}for(let t=0;t.9&&a<.1&&(e<.2&&(s[t+0]+=1),n<.2&&(s[t+2]+=1),i<.2&&(s[t+4]+=1))}}()}(),this.setAttribute("position",new Ms(r,3)),this.setAttribute("normal",new Ms(r.slice(),3)),this.setAttribute("uv",new Ms(s,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}copy(t){return super.copy(t),this.parameters=Object.assign({},t.parameters),this}static fromJSON(t){return new xu(t.vertices,t.indices,t.radius,t.details)}}class yu extends xu{constructor(t=1,e=0){const n=(1+Math.sqrt(5))/2,i=1/n;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,-i,-n,0,-i,n,0,i,-n,0,i,n,-i,-n,0,-i,n,0,i,-n,0,i,n,0,-n,0,-i,n,0,-i,-n,0,i,n,0,i],[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 yu(t.radius,t.detail)}}const Mu=new Li,Su=new Li,bu=new Li,wu=new Zr;class Tu extends Cs{constructor(t=null,e=1){if(super(),this.type="EdgesGeometry",this.parameters={geometry:t,thresholdAngle:e},null!==t){const n=4,i=Math.pow(10,n),r=Math.cos(Xn*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*n){o=c=t[0],l=h=t[1];for(let e=n;ec&&(c=u),d>h&&(h=d);p=Math.max(c-o,h-l),p=0!==p?32767/p:0}return Pu(s,a,n,o,l,p,0),a};function Ru(t,e,n,i,r){let s,a;if(r===function(t,e,n,i){let r=0;for(let s=e,a=n-i;s0)for(s=e;s=e;s-=i)a=Zu(s,t[s],t[s+1],a);return a&&Gu(a,a.next)&&(Ju(a),a=a.next),a}function Cu(t,e){if(!t)return t;e||(e=t);let n,i=t;do{if(n=!1,i.steiner||!Gu(i,i.next)&&0!==Hu(i.prev,i,i.next))i=i.next;else{if(Ju(i),i=e=i.prev,i===i.next)break;n=!0}}while(n||i!==e);return e}function Pu(t,e,n,i,r,s,a){if(!t)return;!a&&s&&function(t,e,n,i){let r=t;do{0===r.z&&(r.z=Bu(r.x,r.y,e,n,i)),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,n,i,r,s,a,o,l,c=1;do{for(n=t,t=null,s=null,a=0;n;){for(a++,i=n,o=0,e=0;e0||l>0&&i;)0!==o&&(0===l||!i||n.z<=i.z)?(r=n,n=n.nextZ,o--):(r=i,i=i.nextZ,l--),s?s.nextZ=r:t=r,r.prevZ=s,s=r;n=i}s.nextZ=null,c*=2}while(a>1)}(r)}(t,i,r,s);let o,l,c=t;for(;t.prev!==t.next;)if(o=t.prev,l=t.next,s?Lu(t,i,r,s):Iu(t))e.push(o.i/n|0),e.push(t.i/n|0),e.push(l.i/n|0),Ju(t),t=l.next,c=l.next;else if((t=l)===c){a?1===a?Pu(t=Uu(Cu(t),e,n),e,n,i,r,s,2):2===a&&Nu(t,e,n,i,r,s):Pu(Cu(t),e,n,i,r,s,1);break}}function Iu(t){const e=t.prev,n=t,i=t.next;if(Hu(e,n,i)>=0)return!1;const r=e.x,s=n.x,a=i.x,o=e.y,l=n.y,c=i.y,h=rs?r>a?r:a:s>a?s:a,p=o>l?o>c?o:c:l>c?l:c;let m=i.next;for(;m!==e;){if(m.x>=h&&m.x<=d&&m.y>=u&&m.y<=p&&ku(r,o,s,l,a,c,m.x,m.y)&&Hu(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function Lu(t,e,n,i){const r=t.prev,s=t,a=t.next;if(Hu(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=Bu(p,m,e,n,i),_=Bu(f,g,e,n,i);let x=t.prevZ,y=t.nextZ;for(;x&&x.z>=v&&y&&y.z<=_;){if(x.x>=p&&x.x<=f&&x.y>=m&&x.y<=g&&x!==r&&x!==a&&ku(o,h,l,u,c,d,x.x,x.y)&&Hu(x.prev,x,x.next)>=0)return!1;if(x=x.prevZ,y.x>=p&&y.x<=f&&y.y>=m&&y.y<=g&&y!==r&&y!==a&&ku(o,h,l,u,c,d,y.x,y.y)&&Hu(y.prev,y,y.next)>=0)return!1;y=y.nextZ}for(;x&&x.z>=v;){if(x.x>=p&&x.x<=f&&x.y>=m&&x.y<=g&&x!==r&&x!==a&&ku(o,h,l,u,c,d,x.x,x.y)&&Hu(x.prev,x,x.next)>=0)return!1;x=x.prevZ}for(;y&&y.z<=_;){if(y.x>=p&&y.x<=f&&y.y>=m&&y.y<=g&&y!==r&&y!==a&&ku(o,h,l,u,c,d,y.x,y.y)&&Hu(y.prev,y,y.next)>=0)return!1;y=y.nextZ}return!0}function Uu(t,e,n){let i=t;do{const r=i.prev,s=i.next.next;!Gu(r,s)&&Wu(r,i,i.next,s)&&qu(r,s)&&qu(s,r)&&(e.push(r.i/n|0),e.push(i.i/n|0),e.push(s.i/n|0),Ju(i),Ju(i.next),i=t=s),i=i.next}while(i!==t);return Cu(i)}function Nu(t,e,n,i,r,s){let a=t;do{let t=a.next.next;for(;t!==a.prev;){if(a.i!==t.i&&Vu(a,t)){let o=Yu(a,t);return a=Cu(a,a.next),o=Cu(o,o.next),Pu(a,e,n,i,r,s,0),void Pu(o,e,n,i,r,s,0)}t=t.next}a=a.next}while(a!==t)}function Du(t,e){return t.x-e.x}function Ou(t,e){const n=function(t,e){let n,i=e,r=-1/0;const s=t.x,a=t.y;do{if(a<=i.y&&a>=i.next.y&&i.next.y!==i.y){const t=i.x+(a-i.y)*(i.next.x-i.x)/(i.next.y-i.y);if(t<=s&&t>r&&(r=t,n=i.x=i.x&&i.x>=l&&s!==i.x&&ku(an.x||i.x===n.x&&Fu(n,i)))&&(n=i,u=h)),i=i.next}while(i!==o);return n}(t,e);if(!n)return e;const i=Yu(n,t);return Cu(i,i.next),Cu(n,n.next)}function Fu(t,e){return Hu(t.prev,t,e.prev)<0&&Hu(e.next,t,t.next)<0}function Bu(t,e,n,i,r){return(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=(t-n)*r|0)|t<<8))|t<<4))|t<<2))|t<<1))|(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=(e-i)*r|0)|e<<8))|e<<4))|e<<2))|e<<1))<<1}function zu(t){let e=t,n=t;do{(e.x=(t-a)*(s-o)&&(t-a)*(i-o)>=(n-a)*(e-o)&&(n-a)*(s-o)>=(r-a)*(i-o)}function Vu(t,e){return t.next.i!==e.i&&t.prev.i!==e.i&&!function(t,e){let n=t;do{if(n.i!==t.i&&n.next.i!==t.i&&n.i!==e.i&&n.next.i!==e.i&&Wu(n,n.next,t,e))return!0;n=n.next}while(n!==t);return!1}(t,e)&&(qu(t,e)&&qu(e,t)&&function(t,e){let n=t,i=!1;const r=(t.x+e.x)/2,s=(t.y+e.y)/2;do{n.y>s!=n.next.y>s&&n.next.y!==n.y&&r<(n.next.x-n.x)*(s-n.y)/(n.next.y-n.y)+n.x&&(i=!i),n=n.next}while(n!==t);return i}(t,e)&&(Hu(t.prev,t,e.prev)||Hu(t,e.prev,e))||Gu(t,e)&&Hu(t.prev,t,t.next)>0&&Hu(e.prev,e,e.next)>0)}function Hu(t,e,n){return(e.y-t.y)*(n.x-e.x)-(e.x-t.x)*(n.y-e.y)}function Gu(t,e){return t.x===e.x&&t.y===e.y}function Wu(t,e,n,i){const r=ju(Hu(t,e,n)),s=ju(Hu(t,e,i)),a=ju(Hu(n,i,t)),o=ju(Hu(n,i,e));return r!==s&&a!==o||(!(0!==r||!Xu(t,n,e))||(!(0!==s||!Xu(t,i,e))||(!(0!==a||!Xu(n,t,i))||!(0!==o||!Xu(n,e,i)))))}function Xu(t,e,n){return e.x<=Math.max(t.x,n.x)&&e.x>=Math.min(t.x,n.x)&&e.y<=Math.max(t.y,n.y)&&e.y>=Math.min(t.y,n.y)}function ju(t){return t>0?1:t<0?-1:0}function qu(t,e){return Hu(t.prev,t,t.next)<0?Hu(t,e,t.next)>=0&&Hu(t,t.prev,e)>=0:Hu(t,e,t.prev)<0||Hu(t,t.next,e)<0}function Yu(t,e){const n=new Ku(t.i,t.x,t.y),i=new Ku(e.i,e.x,e.y),r=t.next,s=e.prev;return t.next=e,e.prev=t,n.next=r,r.prev=n,i.next=n,n.prev=i,s.next=i,i.prev=s,i}function Zu(t,e,n,i){const r=new Ku(t,e,n);return i?(r.next=i.next,r.prev=i,i.next.prev=r,i.next=r):(r.prev=r,r.next=r),r}function Ju(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 Ku(t,e,n){this.i=t,this.x=e,this.y=n,this.prev=null,this.next=null,this.z=0,this.prevZ=null,this.nextZ=null,this.steiner=!1}class $u{static area(t){const e=t.length;let n=0;for(let i=e-1,r=0;r2&&t[e-1].equals(t[0])&&t.pop()}function td(t,e){for(let n=0;nNumber.EPSILON){const u=Math.sqrt(h),d=Math.sqrt(l*l+c*c),p=e.x-o/u,m=e.y+a/u,f=((n.x-c/d-p)*c-(n.y+l/d-m)*l)/(a*c-o*l);i=p+a*f-t.x,r=m+o*f-t.y;const g=i*i+r*r;if(g<=2)return new ti(i,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?(i=-o,r=a,s=Math.sqrt(h)):(i=a,r=o,s=Math.sqrt(h/2))}return new ti(i/s,r/s)}const I=[];for(let t=0,e=E.length,n=e-1,i=t+1;t=0;t--){const e=t/p,n=h*Math.cos(e*Math.PI/2),i=u*Math.sin(e*Math.PI/2)+d;for(let t=0,e=E.length;t=0;){const i=n;let r=n-1;r<0&&(r=t.length-1);for(let t=0,n=o+2*p;t0)&&d.push(e,r,l),(t!==n-1||o0!=t>0&&this.version++,this._anisotropy=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 dispersion(){return this._dispersion}set dispersion(t){this._dispersion>0!=t>0&&this.version++,this._dispersion=t}get sheen(){return this._sheen}set sheen(t){this._sheen>0!=t>0&&this.version++,this._sheen=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.anisotropy=t.anisotropy,this.anisotropyRotation=t.anisotropyRotation,this.anisotropyMap=t.anisotropyMap,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.dispersion=t.dispersion,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 xd extends is{constructor(t){super(),this.isMeshPhongMaterial=!0,this.type="MeshPhongMaterial",this.color=new ts(16777215),this.specular=new ts(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new ts(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new ti(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new _r,this.combine=Y,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.envMapRotation.copy(t.envMapRotation),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 yd extends is{constructor(t){super(),this.isMeshToonMaterial=!0,this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new ts(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new ts(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new ti(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 Md extends is{constructor(t){super(),this.isMeshNormalMaterial=!0,this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new ti(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 Sd extends is{constructor(t){super(),this.isMeshLambertMaterial=!0,this.type="MeshLambertMaterial",this.color=new ts(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new ts(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new ti(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new _r,this.combine=Y,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.envMapRotation.copy(t.envMapRotation),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 bd extends is{constructor(t){super(),this.isMeshMatcapMaterial=!0,this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new ts(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new ti(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 wd extends xh{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 Td(t,e,n){return!t||!n&&t.constructor===e?t:"number"==typeof e.BYTES_PER_ELEMENT?new e(t):Array.prototype.slice.call(t)}function Ed(t){return ArrayBuffer.isView(t)&&!(t instanceof DataView)}function Ad(t){const e=t.length,n=new Array(e);for(let t=0;t!==e;++t)n[t]=t;return n.sort((function(e,n){return t[e]-t[n]})),n}function Rd(t,e,n){const i=t.length,r=new t.constructor(i);for(let s=0,a=0;a!==i;++s){const i=n[s]*e;for(let n=0;n!==e;++n)r[a++]=t[i+n]}return r}function Cd(t,e,n,i){let r=1,s=t[0];for(;void 0!==s&&void 0===s[i];)s=t[r++];if(void 0===s)return;let a=s[i];if(void 0!==a)if(Array.isArray(a))do{a=s[i],void 0!==a&&(e.push(s.time),n.push.apply(n,a)),s=t[r++]}while(void 0!==s);else if(void 0!==a.toArray)do{a=s[i],void 0!==a&&(e.push(s.time),a.toArray(n,n.length)),s=t[r++]}while(void 0!==s);else do{a=s[i],void 0!==a&&(e.push(s.time),n.push(a)),s=t[r++]}while(void 0!==s)}const Pd={convertArray:Td,isTypedArray:Ed,getKeyframeOrder:Ad,sortedArray:Rd,flattenJSON:Cd,subclip:function(t,e,n,i,r=30){const s=t.clone();s.name=e;const a=[];for(let t=0;t=i)){l.push(e.times[t]);for(let n=0;ns.tracks[t].times[0]&&(o=s.tracks[t].times[0]);for(let t=0;t=i.times[u]){const t=u*l+o,e=t+l-o;d=i.values.slice(t,e)}else{const t=i.createInterpolant(),e=o,n=l-o;t.evaluate(s),d=t.resultBuffer.slice(e,n)}if("quaternion"===r){(new Ii).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=n,n=0}}for(;n>>1;te;)--s;if(++s,0!==r||s!==i){r>=s&&(s=Math.max(s,1),r=s-1);const t=this.getValueSize();this.times=n.slice(r,s),this.values=this.values.slice(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 n=this.times,i=this.values,r=n.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),t=!1);let s=null;for(let e=0;e!==r;e++){const i=n[e];if("number"==typeof i&&isNaN(i)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,e,i),t=!1;break}if(null!==s&&s>i){console.error("THREE.KeyframeTrack: Out of order keys.",this,e,i,s),t=!1;break}s=i}if(void 0!==i&&Ed(i))for(let e=0,n=i.length;e!==n;++e){const n=i[e];if(isNaN(n)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,e,n),t=!1;break}}return t}optimize(){const t=this.times.slice(),e=this.values.slice(),n=this.getValueSize(),i=this.getInterpolation()===Ne,r=t.length-1;let s=1;for(let a=1;a0){t[s]=t[r];for(let t=r*n,i=s*n,a=0;a!==n;++a)e[i+a]=e[t+a];++s}return s!==t.length?(this.times=t.slice(0,s),this.values=e.slice(0,s*n)):(this.times=t,this.values=e),this}clone(){const t=this.times.slice(),e=this.values.slice(),n=new(0,this.constructor)(this.name,t,e);return n.createInterpolant=this.createInterpolant,n}}Dd.prototype.TimeBufferType=Float32Array,Dd.prototype.ValueBufferType=Float32Array,Dd.prototype.DefaultInterpolation=Ue;class Od extends Dd{constructor(t,e,n){super(t,e,n)}}Od.prototype.ValueTypeName="bool",Od.prototype.ValueBufferType=Array,Od.prototype.DefaultInterpolation=Le,Od.prototype.InterpolantFactoryMethodLinear=void 0,Od.prototype.InterpolantFactoryMethodSmooth=void 0;class Fd extends Dd{}Fd.prototype.ValueTypeName="color";class Bd extends Dd{}Bd.prototype.ValueTypeName="number";class zd extends Id{constructor(t,e,n,i){super(t,e,n,i)}interpolate_(t,e,n,i){const r=this.resultBuffer,s=this.sampleValues,a=this.valueSize,o=(n-e)/(i-e);let l=t*a;for(let t=l+a;l!==t;l+=4)Ii.slerpFlat(r,0,s,l-a,s,l,o);return r}}class kd extends Dd{InterpolantFactoryMethodLinear(t){return new zd(this.times,this.values,this.getValueSize(),t)}}kd.prototype.ValueTypeName="quaternion",kd.prototype.InterpolantFactoryMethodSmooth=void 0;class Vd extends Dd{constructor(t,e,n){super(t,e,n)}}Vd.prototype.ValueTypeName="string",Vd.prototype.ValueBufferType=Array,Vd.prototype.DefaultInterpolation=Le,Vd.prototype.InterpolantFactoryMethodLinear=void 0,Vd.prototype.InterpolantFactoryMethodSmooth=void 0;class Hd extends Dd{}Hd.prototype.ValueTypeName="vector";class Gd{constructor(t="",e=-1,n=[],i=2500){this.name=t,this.tracks=n,this.duration=e,this.blendMode=i,this.uuid=qn(),this.duration<0&&this.resetDuration()}static parse(t){const e=[],n=t.tracks,i=1/(t.fps||1);for(let t=0,r=n.length;t!==r;++t)e.push(Wd(n[t]).scale(i));const r=new this(t.name,t.duration,e,t.blendMode);return r.uuid=t.uuid,r}static toJSON(t){const e=[],n=t.tracks,i={name:t.name,duration:t.duration,tracks:e,uuid:t.uuid,blendMode:t.blendMode};for(let t=0,i=n.length;t!==i;++t)e.push(Dd.toJSON(n[t]));return i}static CreateFromMorphTargetSequence(t,e,n,i){const r=e.length,s=[];for(let t=0;t1){const t=s[1];let e=i[t];e||(i[t]=e=[]),e.push(n)}}const s=[];for(const t in i)s.push(this.CreateFromMorphTargetSequence(t,i[t],e,n));return s}static parseAnimation(t,e){if(!t)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const n=function(t,e,n,i,r){if(0!==n.length){const s=[],a=[];Cd(n,s,a,i),0!==s.length&&r.push(new t(e,s,a))}},i=[],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!==Zd[t])return void Zd[t].push({onLoad:e,onProgress:n,onError:i});Zd[t]=[],Zd[t].push({onLoad:e,onProgress:n,onError:i});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 n=Zd[t],i=e.body.getReader(),r=e.headers.get("X-File-Size")||e.headers.get("Content-Length"),s=r?parseInt(r):0,a=0!==s;let o=0;const l=new ReadableStream({start(t){!function e(){i.read().then((({done:i,value:r})=>{if(i)t.close();else{o+=r.byteLength;const i=new ProgressEvent("progress",{lengthComputable:a,loaded:o,total:s});for(let t=0,e=n.length;t{t.error(e)}))}()}});return new Response(l)}throw new Jd(`fetch for "${e.url}" responded with ${e.status}: ${e.statusText}`,e)})).then((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),n=e&&e[1]?e[1].toLowerCase():void 0,i=new TextDecoder(n);return t.arrayBuffer().then((t=>i.decode(t)))}}})).then((e=>{Xd.add(t,e);const n=Zd[t];delete Zd[t];for(let t=0,i=n.length;t{const n=Zd[t];if(void 0===n)throw this.manager.itemError(t),e;delete Zd[t];for(let t=0,i=n.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 $d extends Yd{constructor(t){super(t)}load(t,e,n,i){const r=this,s=new Kd(this.manager);s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(t,(function(n){try{e(r.parse(JSON.parse(n)))}catch(e){i?i(e):console.error(e),r.manager.itemError(t)}}),n,i)}parse(t){const e=[];for(let n=0;n0:i.vertexColors=t.vertexColors),void 0!==t.uniforms)for(const e in t.uniforms){const r=t.uniforms[e];switch(i.uniforms[e]={},r.type){case"t":i.uniforms[e].value=n(r.value);break;case"c":i.uniforms[e].value=(new ts).setHex(r.value);break;case"v2":i.uniforms[e].value=(new ti).fromArray(r.value);break;case"v3":i.uniforms[e].value=(new Li).fromArray(r.value);break;case"v4":i.uniforms[e].value=(new wi).fromArray(r.value);break;case"m3":i.uniforms[e].value=(new ei).fromArray(r.value);break;case"m4":i.uniforms[e].value=(new lr).fromArray(r.value);break;default:i.uniforms[e].value=r.value}}if(void 0!==t.defines&&(i.defines=t.defines),void 0!==t.vertexShader&&(i.vertexShader=t.vertexShader),void 0!==t.fragmentShader&&(i.fragmentShader=t.fragmentShader),void 0!==t.glslVersion&&(i.glslVersion=t.glslVersion),void 0!==t.extensions)for(const e in t.extensions)i.extensions[e]=t.extensions[e];if(void 0!==t.lights&&(i.lights=t.lights),void 0!==t.clipping&&(i.clipping=t.clipping),void 0!==t.size&&(i.size=t.size),void 0!==t.sizeAttenuation&&(i.sizeAttenuation=t.sizeAttenuation),void 0!==t.map&&(i.map=n(t.map)),void 0!==t.matcap&&(i.matcap=n(t.matcap)),void 0!==t.alphaMap&&(i.alphaMap=n(t.alphaMap)),void 0!==t.bumpMap&&(i.bumpMap=n(t.bumpMap)),void 0!==t.bumpScale&&(i.bumpScale=t.bumpScale),void 0!==t.normalMap&&(i.normalMap=n(t.normalMap)),void 0!==t.normalMapType&&(i.normalMapType=t.normalMapType),void 0!==t.normalScale){let e=t.normalScale;!1===Array.isArray(e)&&(e=[e,e]),i.normalScale=(new ti).fromArray(e)}return void 0!==t.displacementMap&&(i.displacementMap=n(t.displacementMap)),void 0!==t.displacementScale&&(i.displacementScale=t.displacementScale),void 0!==t.displacementBias&&(i.displacementBias=t.displacementBias),void 0!==t.roughnessMap&&(i.roughnessMap=n(t.roughnessMap)),void 0!==t.metalnessMap&&(i.metalnessMap=n(t.metalnessMap)),void 0!==t.emissiveMap&&(i.emissiveMap=n(t.emissiveMap)),void 0!==t.emissiveIntensity&&(i.emissiveIntensity=t.emissiveIntensity),void 0!==t.specularMap&&(i.specularMap=n(t.specularMap)),void 0!==t.specularIntensityMap&&(i.specularIntensityMap=n(t.specularIntensityMap)),void 0!==t.specularColorMap&&(i.specularColorMap=n(t.specularColorMap)),void 0!==t.envMap&&(i.envMap=n(t.envMap)),void 0!==t.envMapRotation&&i.envMapRotation.fromArray(t.envMapRotation),void 0!==t.envMapIntensity&&(i.envMapIntensity=t.envMapIntensity),void 0!==t.reflectivity&&(i.reflectivity=t.reflectivity),void 0!==t.refractionRatio&&(i.refractionRatio=t.refractionRatio),void 0!==t.lightMap&&(i.lightMap=n(t.lightMap)),void 0!==t.lightMapIntensity&&(i.lightMapIntensity=t.lightMapIntensity),void 0!==t.aoMap&&(i.aoMap=n(t.aoMap)),void 0!==t.aoMapIntensity&&(i.aoMapIntensity=t.aoMapIntensity),void 0!==t.gradientMap&&(i.gradientMap=n(t.gradientMap)),void 0!==t.clearcoatMap&&(i.clearcoatMap=n(t.clearcoatMap)),void 0!==t.clearcoatRoughnessMap&&(i.clearcoatRoughnessMap=n(t.clearcoatRoughnessMap)),void 0!==t.clearcoatNormalMap&&(i.clearcoatNormalMap=n(t.clearcoatNormalMap)),void 0!==t.clearcoatNormalScale&&(i.clearcoatNormalScale=(new ti).fromArray(t.clearcoatNormalScale)),void 0!==t.iridescenceMap&&(i.iridescenceMap=n(t.iridescenceMap)),void 0!==t.iridescenceThicknessMap&&(i.iridescenceThicknessMap=n(t.iridescenceThicknessMap)),void 0!==t.transmissionMap&&(i.transmissionMap=n(t.transmissionMap)),void 0!==t.thicknessMap&&(i.thicknessMap=n(t.thicknessMap)),void 0!==t.anisotropyMap&&(i.anisotropyMap=n(t.anisotropyMap)),void 0!==t.sheenColorMap&&(i.sheenColorMap=n(t.sheenColorMap)),void 0!==t.sheenRoughnessMap&&(i.sheenRoughnessMap=n(t.sheenRoughnessMap)),i}setTextures(t){return this.textures=t,this}createMaterialFromType(t){return bp.createMaterialFromType(t)}static createMaterialFromType(t){return new{ShadowMaterial:fd,SpriteMaterial:uc,RawShaderMaterial:gd,ShaderMaterial:Ys,PointsMaterial:Uh,MeshPhysicalMaterial:_d,MeshStandardMaterial:vd,MeshPhongMaterial:xd,MeshToonMaterial:yd,MeshNormalMaterial:Md,MeshLambertMaterial:Sd,MeshDepthMaterial:zl,MeshDistanceMaterial:kl,MeshBasicMaterial:rs,MeshMatcapMaterial:bd,LineDashedMaterial:wd,LineBasicMaterial:xh,Material:is}[t]}}class wp{static decodeText(t){if(console.warn("THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead."),"undefined"!=typeof TextDecoder)return(new TextDecoder).decode(t);let e="";for(let n=0,i=t.length;n0){const n=new jd(e);r=new tp(n),r.setCrossOrigin(this.crossOrigin);for(let e=0,n=t.length;e0){i=new tp(this.manager),i.setCrossOrigin(this.crossOrigin);for(let e=0,i=t.length;e{const e=new Di;e.min.fromArray(t.boxMin),e.max.fromArray(t.boxMax);const n=new Qi;return n.radius=t.sphereRadius,n.center.fromArray(t.sphereCenter),{boxInitialized:t.boxInitialized,box:e,sphereInitialized:t.sphereInitialized,sphere:n}})),s._maxInstanceCount=t.maxInstanceCount,s._maxVertexCount=t.maxVertexCount,s._maxIndexCount=t.maxIndexCount,s._geometryInitialized=t.geometryInitialized,s._geometryCount=t.geometryCount,s._matricesTexture=h(t.matricesTexture.uuid),void 0!==t.colorsTexture&&(s._colorsTexture=h(t.colorsTexture.uuid));break;case"LOD":s=new Cc;break;case"Line":s=new Ah(l(t.geometry),c(t.material));break;case"LineLoop":s=new Lh(l(t.geometry),c(t.material));break;case"LineSegments":s=new Ih(l(t.geometry),c(t.material));break;case"PointCloud":case"Points":s=new Bh(l(t.geometry),c(t.material));break;case"Sprite":s=new Tc(c(t.material));break;case"Group":s=new Zl;break;case"Bone":s=new kc;break;default:s=new Dr}if(s.uuid=t.uuid,void 0!==t.name&&(s.name=t.name),void 0!==t.matrix?(s.matrix.fromArray(t.matrix),void 0!==t.matrixAutoUpdate&&(s.matrixAutoUpdate=t.matrixAutoUpdate),s.matrixAutoUpdate&&s.matrix.decompose(s.position,s.quaternion,s.scale)):(void 0!==t.position&&s.position.fromArray(t.position),void 0!==t.rotation&&s.rotation.fromArray(t.rotation),void 0!==t.quaternion&&s.quaternion.fromArray(t.quaternion),void 0!==t.scale&&s.scale.fromArray(t.scale)),void 0!==t.up&&s.up.fromArray(t.up),void 0!==t.castShadow&&(s.castShadow=t.castShadow),void 0!==t.receiveShadow&&(s.receiveShadow=t.receiveShadow),t.shadow&&(void 0!==t.shadow.intensity&&(s.shadow.intensity=t.shadow.intensity),void 0!==t.shadow.bias&&(s.shadow.bias=t.shadow.bias),void 0!==t.shadow.normalBias&&(s.shadow.normalBias=t.shadow.normalBias),void 0!==t.shadow.radius&&(s.shadow.radius=t.shadow.radius),void 0!==t.shadow.mapSize&&s.shadow.mapSize.fromArray(t.shadow.mapSize),void 0!==t.shadow.camera&&(s.shadow.camera=this.parseObject(t.shadow.camera))),void 0!==t.visible&&(s.visible=t.visible),void 0!==t.frustumCulled&&(s.frustumCulled=t.frustumCulled),void 0!==t.renderOrder&&(s.renderOrder=t.renderOrder),void 0!==t.userData&&(s.userData=t.userData),void 0!==t.layers&&(s.layers.mask=t.layers),void 0!==t.children){const a=t.children;for(let t=0;t{e&&e(n),r.manager.itemEnd(t)})).catch((t=>{i&&i(t)})):(setTimeout((function(){e&&e(s),r.manager.itemEnd(t)}),0),s);const a={};a.credentials="anonymous"===this.crossOrigin?"same-origin":"include",a.headers=this.requestHeader;const o=fetch(t,a).then((function(t){return t.blob()})).then((function(t){return createImageBitmap(t,Object.assign(r.options,{colorSpaceConversion:"none"}))})).then((function(n){return Xd.add(t,n),e&&e(n),r.manager.itemEnd(t),n})).catch((function(e){i&&i(e),Xd.remove(t),r.manager.itemError(t),r.manager.itemEnd(t)}));Xd.add(t,o),r.manager.itemStart(t)}}let Lp;class Up{static getContext(){return void 0===Lp&&(Lp=new(window.AudioContext||window.webkitAudioContext)),Lp}static setContext(t){Lp=t}}class Np extends Yd{constructor(t){super(t)}load(t,e,n,i){const r=this,s=new Kd(this.manager);function a(e){i?i(e):console.error(e),r.manager.itemError(t)}s.setResponseType("arraybuffer"),s.setPath(this.path),s.setRequestHeader(this.requestHeader),s.setWithCredentials(this.withCredentials),s.load(t,(function(t){try{const n=t.slice(0);Up.getContext().decodeAudioData(n,(function(t){e(t)})).catch(a)}catch(t){a(t)}}),n,i)}}const Dp=new lr,Op=new lr,Fp=new lr;class Bp{constructor(){this.type="StereoCamera",this.aspect=1,this.eyeSep=.064,this.cameraL=new Qs,this.cameraL.layers.enable(1),this.cameraL.matrixAutoUpdate=!1,this.cameraR=new Qs,this.cameraR.layers.enable(2),this.cameraR.matrixAutoUpdate=!1,this._cache={focus:null,fov:null,aspect:null,near:null,far:null,zoom:null,eyeSep:null}}update(t){const e=this._cache;if(e.focus!==t.focus||e.fov!==t.fov||e.aspect!==t.aspect*this.aspect||e.near!==t.near||e.far!==t.far||e.zoom!==t.zoom||e.eyeSep!==this.eyeSep){e.focus=t.focus,e.fov=t.fov,e.aspect=t.aspect*this.aspect,e.near=t.near,e.far=t.far,e.zoom=t.zoom,e.eyeSep=this.eyeSep,Fp.copy(t.projectionMatrix);const n=e.eyeSep/2,i=n*e.near/e.focus,r=e.near*Math.tan(Xn*e.fov*.5)/e.zoom;let s,a;Op.elements[12]=-n,Dp.elements[12]=n,s=-r*e.aspect+i,a=r*e.aspect+i,Fp.elements[0]=2*e.near/(a-s),Fp.elements[8]=(a+s)/(a-s),this.cameraL.projectionMatrix.copy(Fp),s=-r*e.aspect-i,a=r*e.aspect-i,Fp.elements[0]=2*e.near/(a-s),Fp.elements[8]=(a+s)/(a-s),this.cameraR.projectionMatrix.copy(Fp)}this.cameraL.matrixWorld.copy(t.matrixWorld).multiply(Op),this.cameraR.matrixWorld.copy(t.matrixWorld).multiply(Dp)}}class zp{constructor(t=!0){this.autoStart=t,this.startTime=0,this.oldTime=0,this.elapsedTime=0,this.running=!1}start(){this.startTime=kp(),this.oldTime=this.startTime,this.elapsedTime=0,this.running=!0}stop(){this.getElapsedTime(),this.running=!1,this.autoStart=!1}getElapsedTime(){return this.getDelta(),this.elapsedTime}getDelta(){let t=0;if(this.autoStart&&!this.running)return this.start(),0;if(this.running){const e=kp();t=(e-this.oldTime)/1e3,this.oldTime=e,this.elapsedTime+=t}return t}}function kp(){return performance.now()}const Vp=new Li,Hp=new Ii,Gp=new Li,Wp=new Li;class Xp extends Dr{constructor(){super(),this.type="AudioListener",this.context=Up.getContext(),this.gain=this.context.createGain(),this.gain.connect(this.context.destination),this.filter=null,this.timeDelta=0,this._clock=new zp}getInput(){return this.gain}removeFilter(){return null!==this.filter&&(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination),this.gain.connect(this.context.destination),this.filter=null),this}getFilter(){return this.filter}setFilter(t){return null!==this.filter?(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination)):this.gain.disconnect(this.context.destination),this.filter=t,this.gain.connect(this.filter),this.filter.connect(this.context.destination),this}getMasterVolume(){return this.gain.gain.value}setMasterVolume(t){return this.gain.gain.setTargetAtTime(t,this.context.currentTime,.01),this}updateMatrixWorld(t){super.updateMatrixWorld(t);const e=this.context.listener,n=this.up;if(this.timeDelta=this._clock.getDelta(),this.matrixWorld.decompose(Vp,Hp,Gp),Wp.set(0,0,-1).applyQuaternion(Hp),e.positionX){const t=this.context.currentTime+this.timeDelta;e.positionX.linearRampToValueAtTime(Vp.x,t),e.positionY.linearRampToValueAtTime(Vp.y,t),e.positionZ.linearRampToValueAtTime(Vp.z,t),e.forwardX.linearRampToValueAtTime(Wp.x,t),e.forwardY.linearRampToValueAtTime(Wp.y,t),e.forwardZ.linearRampToValueAtTime(Wp.z,t),e.upX.linearRampToValueAtTime(n.x,t),e.upY.linearRampToValueAtTime(n.y,t),e.upZ.linearRampToValueAtTime(n.z,t)}else e.setPosition(Vp.x,Vp.y,Vp.z),e.setOrientation(Wp.x,Wp.y,Wp.z,n.x,n.y,n.z)}}class jp extends Dr{constructor(t){super(),this.type="Audio",this.listener=t,this.context=t.context,this.gain=this.context.createGain(),this.gain.connect(t.getInput()),this.autoplay=!1,this.buffer=null,this.detune=0,this.loop=!1,this.loopStart=0,this.loopEnd=0,this.offset=0,this.duration=void 0,this.playbackRate=1,this.isPlaying=!1,this.hasPlaybackControl=!0,this.source=null,this.sourceType="empty",this._startedAt=0,this._progress=0,this._connected=!1,this.filters=[]}getOutput(){return this.gain}setNodeSource(t){return this.hasPlaybackControl=!1,this.sourceType="audioNode",this.source=t,this.connect(),this}setMediaElementSource(t){return this.hasPlaybackControl=!1,this.sourceType="mediaNode",this.source=this.context.createMediaElementSource(t),this.connect(),this}setMediaStreamSource(t){return this.hasPlaybackControl=!1,this.sourceType="mediaStreamNode",this.source=this.context.createMediaStreamSource(t),this.connect(),this}setBuffer(t){return this.buffer=t,this.sourceType="buffer",this.autoplay&&this.play(),this}play(t=0){if(!0===this.isPlaying)return void console.warn("THREE.Audio: Audio is already playing.");if(!1===this.hasPlaybackControl)return void console.warn("THREE.Audio: this Audio has no playback control.");this._startedAt=this.context.currentTime+t;const e=this.context.createBufferSource();return e.buffer=this.buffer,e.loop=this.loop,e.loopStart=this.loopStart,e.loopEnd=this.loopEnd,e.onended=this.onEnded.bind(this),e.start(this._startedAt,this._progress+this.offset,this.duration),this.isPlaying=!0,this.source=e,this.setDetune(this.detune),this.setPlaybackRate(this.playbackRate),this.connect()}pause(){if(!1!==this.hasPlaybackControl)return!0===this.isPlaying&&(this._progress+=Math.max(this.context.currentTime-this._startedAt,0)*this.playbackRate,!0===this.loop&&(this._progress=this._progress%(this.duration||this.buffer.duration)),this.source.stop(),this.source.onended=null,this.isPlaying=!1),this;console.warn("THREE.Audio: this Audio has no playback control.")}stop(t=0){if(!1!==this.hasPlaybackControl)return this._progress=0,null!==this.source&&(this.source.stop(this.context.currentTime+t),this.source.onended=null),this.isPlaying=!1,this;console.warn("THREE.Audio: this Audio has no playback control.")}connect(){if(this.filters.length>0){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(n,i,this._addIndex*e,1,e);for(let t=e,r=e+e;t!==r;++t)if(n[t]!==n[t+e]){a.setValue(n,i);break}}saveOriginalState(){const t=this.binding,e=this.buffer,n=this.valueSize,i=n*this._origIndex;t.getValue(e,i);for(let t=n,r=i;t!==r;++t)e[t]=e[i+t%n];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 n=t;n=.5)for(let i=0;i!==r;++i)t[e+i]=t[n+i]}_slerp(t,e,n,i){Ii.slerpFlat(t,e,t,e,t,n,i)}_slerpAdditive(t,e,n,i,r){const s=this._workIndex*r;Ii.multiplyQuaternionsFlat(t,s,t,e,t,n),Ii.slerpFlat(t,e,t,e,t,s,i)}_lerp(t,e,n,i,r){const s=1-i;for(let a=0;a!==r;++a){const r=e+a;t[r]=t[r]*s+t[n+a]*i}}_lerpAdditive(t,e,n,i,r){for(let s=0;s!==r;++s){const r=e+s;t[r]=t[r]+t[n+s]*i}}}const tm="\\[\\]\\.:\\/",em=new RegExp("["+tm+"]","g"),nm="[^"+tm+"]",im="[^"+tm.replace("\\.","")+"]",rm=new RegExp("^"+/((?:WC+[\/:])*)/.source.replace("WC",nm)+/(WCOD+)?/.source.replace("WCOD",im)+/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",nm)+/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",nm)+"$"),sm=["material","materials","bones","map"];class am{constructor(t,e,n){this.path=e,this.parsedPath=n||am.parseTrackName(e),this.node=am.findNode(t,this.parsedPath.nodeName),this.rootNode=t,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(t,e,n){return t&&t.isAnimationObjectGroup?new am.Composite(t,e,n):new am(t,e,n)}static sanitizeNodeName(t){return t.replace(/\s/g,"_").replace(em,"")}static parseTrackName(t){const e=rm.exec(t);if(null===e)throw new Error("PropertyBinding: Cannot parse trackName: "+t);const n={nodeName:e[2],objectName:e[3],objectIndex:e[4],propertyName:e[5],propertyIndex:e[6]},i=n.nodeName&&n.nodeName.lastIndexOf(".");if(void 0!==i&&-1!==i){const t=n.nodeName.substring(i+1);-1!==sm.indexOf(t)&&(n.nodeName=n.nodeName.substring(0,i),n.objectName=t)}if(null===n.propertyName||0===n.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+t);return n}static findNode(t,e){if(void 0===e||""===e||"."===e||-1===e||e===t.name||e===t.uuid)return t;if(t.skeleton){const n=t.skeleton.getBoneByName(e);if(void 0!==n)return n}if(t.children){const n=function(t){for(let i=0;i=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=i;t!==e;++t){const e=n[t],i=e[s],r=e[l];e[l]=i,e[s]=r}}}this.nCachedObjects_=r}uncache(){const t=this._objects,e=this._indicesByUUID,n=this._bindings,i=n.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=i;t!==e;++t){const e=n[t];e[l]=e[r],e.pop()}}}this.nCachedObjects_=r}subscribe_(t,e){const n=this._bindingsIndicesByPath;let i=n[t];const r=this._bindings;if(void 0!==i)return r[i];const s=this._paths,a=this._parsedPaths,o=this._objects,l=o.length,c=this.nCachedObjects_,h=new Array(l);i=r.length,n[t]=i,s.push(t),a.push(e),r.push(h);for(let n=c,i=o.length;n!==i;++n){const i=o[n];h[n]=new am(i,t,e)}return h}unsubscribe_(t){const e=this._bindingsIndicesByPath,n=e[t];if(void 0!==n){const i=this._paths,r=this._parsedPaths,s=this._bindings,a=s.length-1,o=s[a];e[t[a]]=n,s[n]=o,s.pop(),r[n]=r[a],r.pop(),i[n]=i[a],i.pop()}}}class lm{constructor(t,e,n=null,i=e.blendMode){this._mixer=t,this._clip=e,this._localRoot=n,this.blendMode=i;const r=e.tracks,s=r.length,a=new Array(s),o={endingStart:De,endingEnd:De};for(let t=0;t!==s;++t){const e=r[t].createInterpolant(null);a[t]=e,e.settings=o}this._interpolantSettings=o,this._interpolants=a,this._propertyBindings=new Array(s),this._cacheIndex=null,this._byClipCacheIndex=null,this._timeScaleInterpolant=null,this._weightInterpolant=null,this.loop=2201,this._loopCount=-1,this._startTime=null,this.time=0,this.timeScale=1,this._effectiveTimeScale=1,this.weight=1,this._effectiveWeight=1,this.repetitions=1/0,this.paused=!1,this.enabled=!0,this.clampWhenFinished=!1,this.zeroSlopeAtStart=!0,this.zeroSlopeAtEnd=!0}play(){return this._mixer._activateAction(this),this}stop(){return this._mixer._deactivateAction(this),this.reset()}reset(){return this.paused=!1,this.enabled=!0,this.time=0,this._loopCount=-1,this._startTime=null,this.stopFading().stopWarping()}isRunning(){return this.enabled&&!this.paused&&0!==this.timeScale&&null===this._startTime&&this._mixer._isActiveAction(this)}isScheduled(){return this._mixer._isActiveAction(this)}startAt(t){return this._startTime=t,this}setLoop(t,e){return this.loop=t,this.repetitions=e,this}setEffectiveWeight(t){return this.weight=t,this._effectiveWeight=this.enabled?t:0,this.stopFading()}getEffectiveWeight(){return this._effectiveWeight}fadeIn(t){return this._scheduleFading(t,0,1)}fadeOut(t){return this._scheduleFading(t,1,0)}crossFadeFrom(t,e,n){if(t.fadeOut(e),this.fadeIn(e),n){const n=this._clip.duration,i=t._clip.duration,r=i/n,s=n/i;t.warp(1,r,e),this.warp(s,1,e)}return this}crossFadeTo(t,e,n){return t.crossFadeFrom(this,e,n)}stopFading(){const t=this._weightInterpolant;return null!==t&&(this._weightInterpolant=null,this._mixer._takeBackControlInterpolant(t)),this}setEffectiveTimeScale(t){return this.timeScale=t,this._effectiveTimeScale=this.paused?0:t,this.stopWarping()}getEffectiveTimeScale(){return this._effectiveTimeScale}setDuration(t){return this.timeScale=this._clip.duration/t,this.stopWarping()}syncWith(t){return this.time=t.time,this.timeScale=t.timeScale,this.stopWarping()}halt(t){return this.warp(this._effectiveTimeScale,0,t)}warp(t,e,n){const i=this._mixer,r=i.time,s=this.timeScale;let a=this._timeScaleInterpolant;null===a&&(a=i._lendControlInterpolant(),this._timeScaleInterpolant=a);const o=a.parameterPositions,l=a.sampleValues;return o[0]=r,o[1]=r+n,l[0]=t/s,l[1]=e/s,this}stopWarping(){const t=this._timeScaleInterpolant;return null!==t&&(this._timeScaleInterpolant=null,this._mixer._takeBackControlInterpolant(t)),this}getMixer(){return this._mixer}getClip(){return this._clip}getRoot(){return this._localRoot||this._mixer._root}_update(t,e,n,i){if(!this.enabled)return void this._updateWeight(t);const r=this._startTime;if(null!==r){const i=(t-r)*n;i<0||0===n?e=0:(this._startTime=null,e=n*i)}e*=this._updateTimeScale(t);const s=this._updateTime(e),a=this._updateWeight(t);if(a>0){const t=this._interpolants,e=this._propertyBindings;if(this.blendMode===ze)for(let n=0,i=t.length;n!==i;++n)t[n].evaluate(s),e[n].accumulateAdditive(a);else for(let n=0,r=t.length;n!==r;++n)t[n].evaluate(s),e[n].accumulate(i,a)}}_updateWeight(t){let e=0;if(this.enabled){e=this.weight;const n=this._weightInterpolant;if(null!==n){const i=n.evaluate(t)[0];e*=i,t>n.parameterPositions[1]&&(this.stopFading(),0===i&&(this.enabled=!1))}}return this._effectiveWeight=e,e}_updateTimeScale(t){let e=0;if(!this.paused){e=this.timeScale;const n=this._timeScaleInterpolant;if(null!==n){e*=n.evaluate(t)[0],t>n.parameterPositions[1]&&(this.stopWarping(),0===e?this.paused=!0:this.timeScale=e)}}return this._effectiveTimeScale=e,e}_updateTime(t){const e=this._clip.duration,n=this.loop;let i=this.time+t,r=this._loopCount;const s=2202===n;if(0===t)return-1===r?i:s&&1==(1&r)?e-i:i;if(2200===n){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));t:{if(i>=e)i=e;else{if(!(i<0)){this.time=i;break t}i=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=i,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)),i>=e||i<0){const n=Math.floor(i/e);i-=e*n,r+=Math.abs(n);const a=this.repetitions-r;if(a<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,i=t>0?e:0,this.time=i,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=i,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:n})}}else this.time=i;if(s&&1==(1&r))return e-i}return i}_setEndings(t,e,n){const i=this._interpolantSettings;n?(i.endingStart=Oe,i.endingEnd=Oe):(i.endingStart=t?this.zeroSlopeAtStart?Oe:De:Fe,i.endingEnd=e?this.zeroSlopeAtEnd?Oe:De:Fe)}_scheduleFading(t,e,n){const i=this._mixer,r=i.time;let s=this._weightInterpolant;null===s&&(s=i._lendControlInterpolant(),this._weightInterpolant=s);const a=s.parameterPositions,o=s.sampleValues;return a[0]=r,o[0]=e,a[1]=r+t,o[1]=n,this}}const cm=new Float32Array(1);class hm extends Hn{constructor(t){super(),this._root=t,this._initMemoryManager(),this._accuIndex=0,this.time=0,this.timeScale=1}_bindAction(t,e){const n=t._localRoot||this._root,i=t._clip.tracks,r=i.length,s=t._propertyBindings,a=t._interpolants,o=n.uuid,l=this._bindingsByRootAndName;let c=l[o];void 0===c&&(c={},l[o]=c);for(let t=0;t!==r;++t){const r=i[t],l=r.name;let h=c[l];if(void 0!==h)++h.referenceCount,s[t]=h;else{if(h=s[t],void 0!==h){null===h._cacheIndex&&(++h.referenceCount,this._addInactiveBinding(h,o,l));continue}const i=e&&e._propertyBindings[t].binding.parsedPath;h=new Qp(am.create(n,l,i),r.ValueTypeName,r.getValueSize()),++h.referenceCount,this._addInactiveBinding(h,o,l),s[t]=h}a[t].resultBuffer=h.buffer}}_activateAction(t){if(!this._isActiveAction(t)){if(null===t._cacheIndex){const e=(t._localRoot||this._root).uuid,n=t._clip.uuid,i=this._actionsByClip[n];this._bindAction(t,i&&i.knownActions[0]),this._addInactiveAction(t,n,e)}const e=t._propertyBindings;for(let t=0,n=e.length;t!==n;++t){const n=e[t];0==n.useCount++&&(this._lendBinding(n),n.saveOriginalState())}this._lendAction(t)}}_deactivateAction(t){if(this._isActiveAction(t)){const e=t._propertyBindings;for(let t=0,n=e.length;t!==n;++t){const n=e[t];0==--n.useCount&&(n.restoreOriginalState(),this._takeBackBinding(n))}this._takeBackAction(t)}}_initMemoryManager(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;const t=this;this.stats={actions:{get total(){return t._actions.length},get inUse(){return t._nActiveActions}},bindings:{get total(){return t._bindings.length},get inUse(){return t._nActiveBindings}},controlInterpolants:{get total(){return t._controlInterpolants.length},get inUse(){return t._nActiveControlInterpolants}}}}_isActiveAction(t){const e=t._cacheIndex;return null!==e&&e=0;--e)t[e].stop();return this}update(t){t*=this.timeScale;const e=this._actions,n=this._nActiveActions,i=this.time+=t,r=Math.sign(t),s=this._accuIndex^=1;for(let a=0;a!==n;++a){e[a]._update(i,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=this.min.x&&t.x<=this.max.x&&t.y>=this.min.y&&t.y<=this.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.x>=this.min.x&&t.min.x<=this.max.x&&t.max.y>=this.min.y&&t.min.y<=this.max.y}clampPoint(t,e){return e.copy(t).clamp(this.min,this.max)}distanceToPoint(t){return this.clampPoint(t,bm).distanceTo(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}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 Tm=new Li,Em=new Li;class Am{constructor(t=new Li,e=new Li){this.start=t,this.end=e}set(t,e){return this.start.copy(t),this.end.copy(e),this}copy(t){return this.start.copy(t.start),this.end.copy(t.end),this}getCenter(t){return t.addVectors(this.start,this.end).multiplyScalar(.5)}delta(t){return t.subVectors(this.end,this.start)}distanceSq(){return this.start.distanceToSquared(this.end)}distance(){return this.start.distanceTo(this.end)}at(t,e){return this.delta(e).multiplyScalar(t).add(this.start)}closestPointToPointParameter(t,e){Tm.subVectors(t,this.start),Em.subVectors(this.end,this.start);const n=Em.dot(Em);let i=Em.dot(Tm)/n;return e&&(i=Yn(i,0,1)),i}closestPointToPoint(t,e,n){const i=this.closestPointToPointParameter(t,e);return this.delta(n).multiplyScalar(i).add(this.start)}applyMatrix4(t){return this.start.applyMatrix4(t),this.end.applyMatrix4(t),this}equals(t){return t.start.equals(this.start)&&t.end.equals(this.end)}clone(){return(new this.constructor).copy(this)}}const Rm=new Li;class Cm extends Dr{constructor(t,e){super(),this.light=t,this.matrixAutoUpdate=!1,this.color=e,this.type="SpotLightHelper";const n=new Cs,i=[0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,-1,0,1,0,0,0,0,1,1,0,0,0,0,-1,1];for(let t=0,e=1,n=32;t1)for(let n=0;n.99999)this.quaternion.set(0,0,0,1);else if(t.y<-.99999)this.quaternion.set(1,0,0,0);else{tf.set(t.z,0,-t.x).normalize();const e=Math.acos(t.y);this.quaternion.setFromAxisAngle(tf,e)}}setLength(t,e=.2*t,n=.2*e){this.line.scale.set(1,Math.max(1e-4,t-e),1),this.line.updateMatrix(),this.cone.scale.set(n,e,n),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()}}class sf extends Ih{constructor(t=1){const e=[0,0,0,t,0,0,0,0,0,0,t,0,0,0,0,0,0,t],n=new Cs;n.setAttribute("position",new Ms(e,3)),n.setAttribute("color",new Ms([1,0,0,1,.6,0,0,1,0,.6,1,0,0,0,1,0,.6,1],3));super(n,new xh({vertexColors:!0,toneMapped:!1})),this.type="AxesHelper"}setColors(t,e,n){const i=new ts,r=this.geometry.attributes.color.array;return i.set(t),i.toArray(r,0),i.toArray(r,3),i.set(e),i.toArray(r,6),i.toArray(r,9),i.set(n),i.toArray(r,12),i.toArray(r,15),this.geometry.attributes.color.needsUpdate=!0,this}dispose(){this.geometry.dispose(),this.material.dispose()}}class af{constructor(){this.type="ShapePath",this.color=new ts,this.subPaths=[],this.currentPath=null}moveTo(t,e){return this.currentPath=new pu,this.subPaths.push(this.currentPath),this.currentPath.moveTo(t,e),this}lineTo(t,e){return this.currentPath.lineTo(t,e),this}quadraticCurveTo(t,e,n,i){return this.currentPath.quadraticCurveTo(t,e,n,i),this}bezierCurveTo(t,e,n,i,r,s){return this.currentPath.bezierCurveTo(t,e,n,i,r,s),this}splineThru(t){return this.currentPath.splineThru(t),this}toShapes(t){function e(t,e){const n=e.length;let i=!1;for(let r=n-1,s=0;sNumber.EPSILON){if(l<0&&(n=e[s],o=-o,a=e[r],l=-l),t.ya.y)continue;if(t.y===n.y){if(t.x===n.x)return!0}else{const e=l*(t.x-n.x)-o*(t.y-n.y);if(0===e)return!0;if(e<0)continue;i=!i}}else{if(t.y!==n.y)continue;if(a.x<=t.x&&t.x<=n.x||n.x<=t.x&&t.x<=a.x)return!0}}return i}const n=$u.isClockWise,i=this.subPaths;if(0===i.length)return[];let r,s,a;const o=[];if(1===i.length)return s=i[0],a=new Eu,a.curves=s.curves,o.push(a),o;let l=!n(i[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=i.length;e1){let t=!1,n=0;for(let t=0,e=h.length;t0&&!1===t&&(p=c)}for(let t=0,e=h.length;t 0 ) { @@ -11931,6 +11929,7 @@ function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, n Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal ); intersection.face = face; + intersection.barycoord = barycoord; } @@ -13177,7 +13176,6 @@ class InterleavedBuffer { this.count = array !== undefined ? array.length / stride : 0; this.usage = StaticDrawUsage; - this._updateRange = { offset: 0, count: - 1 }; this.updateRanges = []; this.version = 0; @@ -13194,13 +13192,6 @@ class InterleavedBuffer { } - get updateRange() { - - warnOnce( 'THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead.' ); // @deprecated, r159 - return this._updateRange; - - } - setUsage( value ) { this.usage = value; @@ -13965,6 +13956,27 @@ class LOD extends Object3D { } + removeLevel( distance ) { + + const levels = this.levels; + + for ( let i = 0; i < levels.length; i ++ ) { + + if ( levels[ i ].distance === distance ) { + + const removedElements = levels.splice( i, 1 ); + this.remove( removedElements[ 0 ].object ); + + return true; + + } + + } + + return false; + + } + getCurrentLevel() { return this._currentLevel; @@ -14106,7 +14118,7 @@ const _basePosition = /*@__PURE__*/ new Vector3(); const _skinIndex = /*@__PURE__*/ new Vector4(); const _skinWeight = /*@__PURE__*/ new Vector4(); -const _vector3$1 = /*@__PURE__*/ new Vector3(); +const _vector3 = /*@__PURE__*/ new Vector3(); const _matrix4 = /*@__PURE__*/ new Matrix4(); const _vertex = /*@__PURE__*/ new Vector3(); @@ -14336,7 +14348,7 @@ class SkinnedMesh extends Mesh { _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); - vector.addScaledVector( _vector3$1.copy( _basePosition ).applyMatrix4( _matrix4 ), weight ); + vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight ); } @@ -15464,6 +15476,9 @@ class BatchedMesh extends Mesh { // stores visible, active, and geometry id per object this._drawInfo = []; + // instance ids that have been set as inactive, and are available to be overwritten + this._availableInstanceIds = []; + // geometry information this._drawRanges = []; this._reservedRanges = []; @@ -15663,23 +15678,36 @@ class BatchedMesh extends Mesh { addInstance( geometryId ) { + const atCapacity = this._drawInfo.length >= this.maxInstanceCount; + // ensure we're not over geometry - if ( this._drawInfo.length >= this._maxInstanceCount ) { + if ( atCapacity && this._availableInstanceIds.length === 0 ) { throw new Error( 'BatchedMesh: Maximum item count reached.' ); } - this._drawInfo.push( { - + const instanceDrawInfo = { visible: true, active: true, geometryIndex: geometryId, + }; - } ); + let drawId = null; + + // Prioritize using previously freed instance ids + if ( this._availableInstanceIds.length > 0 ) { + + drawId = this._availableInstanceIds.pop(); + this._drawInfo[ drawId ] = instanceDrawInfo; + + } else { + + drawId = this._drawInfo.length; + this._drawInfo.push( instanceDrawInfo ); + + } - // initialize the matrix - const drawId = this._drawInfo.length - 1; const matricesTexture = this._matricesTexture; const matricesArray = matricesTexture.image.data; _identityMatrix.toArray( matricesArray, drawId * 16 ); @@ -15928,11 +15956,8 @@ class BatchedMesh extends Mesh { } */ - /* deleteInstance( instanceId ) { - // Note: User needs to call optimize() afterward to pack the data. - const drawInfo = this._drawInfo; if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { @@ -15941,12 +15966,12 @@ class BatchedMesh extends Mesh { } drawInfo[ instanceId ].active = false; + this._availableInstanceIds.push( instanceId ); this._visibilityChanged = true; return this; } - */ // get bounding box and compute it if it doesn't exist getBoundingBoxAt( geometryId, target ) { @@ -16151,6 +16176,59 @@ class BatchedMesh extends Mesh { } + setGeometryIdAt( instanceId, geometryId ) { + + // return early if the geometry is out of range or not active + const drawInfo = this._drawInfo; + if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { + + return null; + + } + + // check if the provided geometryId is within the valid range + if ( geometryId < 0 || geometryId >= this._geometryCount ) { + + return null; + + } + + drawInfo[ instanceId ].geometryIndex = geometryId; + + return this; + + } + + getGeometryIdAt( instanceId ) { + + const drawInfo = this._drawInfo; + if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { + + return - 1; + + } + + return drawInfo[ instanceId ].geometryIndex; + + } + + getGeometryRangeAt( geometryId, target = {} ) { + + if ( geometryId < 0 || geometryId >= this._geometryCount ) { + + return null; + + } + + const drawRange = this._drawRanges[ geometryId ]; + + target.start = drawRange.start; + target.count = drawRange.count; + + return target; + + } + raycast( raycaster, intersects ) { const drawInfo = this._drawInfo; @@ -16702,6 +16780,7 @@ function checkIntersection( object, raycaster, ray, thresholdSq, a, b ) { index: a, face: null, faceIndex: null, + barycoord: null, object: object }; @@ -16967,6 +17046,8 @@ function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, inte point: intersectPoint, index: index, face: null, + faceIndex: null, + barycoord: null, object: object } ); @@ -19535,12 +19616,19 @@ class CylinderGeometry extends BufferGeometry { // faces - indices.push( a, b, d ); - indices.push( b, c, d ); + if ( radiusTop > 0 ) { - // update group counter + indices.push( a, b, d ); + groupCount += 3; - groupCount += 6; + } + + if ( radiusBottom > 0 ) { + + indices.push( b, c, d ); + groupCount += 3; + + } } @@ -24269,19580 +24357,19393 @@ class LineDashedMaterial extends LineBasicMaterial { } -function getCacheKey$1( object, force = false ) { +// converts an array to a specific type +function convertArray( array, type, forceClone ) { - let cacheKey = '{'; + if ( ! array || // let 'undefined' and 'null' pass + ! forceClone && array.constructor === type ) return array; - if ( object.isNode === true ) { + if ( typeof type.BYTES_PER_ELEMENT === 'number' ) { - cacheKey += object.id; - object = object.getSelf(); + return new type( array ); // create typed array } - for ( const { property, childNode } of getNodeChildren( object ) ) { - - cacheKey += ',' + property.slice( 0, - 4 ) + ':' + childNode.getCacheKey( force ); + return Array.prototype.slice.call( array ); // create Array - } +} - cacheKey += '}'; +function isTypedArray( object ) { - return cacheKey; + return ArrayBuffer.isView( object ) && + ! ( object instanceof DataView ); } -function* getNodeChildren( node, toJSON = false ) { +// returns an array by which times and values can be sorted +function getKeyframeOrder( times ) { - for ( const property in node ) { + function compareTime( i, j ) { - // Ignore private properties. - if ( property.startsWith( '_' ) === true ) continue; + return times[ i ] - times[ j ]; - const object = node[ property ]; + } - if ( Array.isArray( object ) === true ) { + const n = times.length; + const result = new Array( n ); + for ( let i = 0; i !== n; ++ i ) result[ i ] = i; - for ( let i = 0; i < object.length; i ++ ) { + result.sort( compareTime ); - const child = object[ i ]; + return result; - if ( child && ( child.isNode === true || toJSON && typeof child.toJSON === 'function' ) ) { +} - yield { property, index: i, childNode: child }; +// uses the array previously returned by 'getKeyframeOrder' to sort data +function sortedArray( values, stride, order ) { - } + const nValues = values.length; + const result = new values.constructor( nValues ); - } + for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) { - } else if ( object && object.isNode === true ) { + const srcOffset = order[ i ] * stride; - yield { property, childNode: object }; + for ( let j = 0; j !== stride; ++ j ) { - } else if ( typeof object === 'object' ) { + result[ dstOffset ++ ] = values[ srcOffset + j ]; - for ( const subProperty in object ) { + } - const child = object[ subProperty ]; + } - if ( child && ( child.isNode === true || toJSON && typeof child.toJSON === 'function' ) ) { + return result; - yield { property, index: subProperty, childNode: child }; +} - } +// function for parsing AOS keyframe formats +function flattenJSON( jsonKeys, times, values, valuePropertyName ) { - } + let i = 1, key = jsonKeys[ 0 ]; - } + while ( key !== undefined && key[ valuePropertyName ] === undefined ) { + + key = jsonKeys[ i ++ ]; } -} + if ( key === undefined ) return; // no data -function getValueType( value ) { + let value = key[ valuePropertyName ]; + if ( value === undefined ) return; // no data - if ( value === undefined || value === null ) return null; + if ( Array.isArray( value ) ) { - const typeOf = typeof value; + do { - if ( value.isNode === true ) { + value = key[ valuePropertyName ]; - return 'node'; + if ( value !== undefined ) { - } else if ( typeOf === 'number' ) { + times.push( key.time ); + values.push.apply( values, value ); // push all elements - return 'float'; + } - } else if ( typeOf === 'boolean' ) { + key = jsonKeys[ i ++ ]; - return 'bool'; + } while ( key !== undefined ); - } else if ( typeOf === 'string' ) { + } else if ( value.toArray !== undefined ) { - return 'string'; + // ...assume THREE.Math-ish - } else if ( typeOf === 'function' ) { + do { - return 'shader'; + value = key[ valuePropertyName ]; - } else if ( value.isVector2 === true ) { + if ( value !== undefined ) { - return 'vec2'; + times.push( key.time ); + value.toArray( values, values.length ); - } else if ( value.isVector3 === true ) { + } - return 'vec3'; + key = jsonKeys[ i ++ ]; - } else if ( value.isVector4 === true ) { + } while ( key !== undefined ); - return 'vec4'; + } else { - } else if ( value.isMatrix3 === true ) { + // otherwise push as-is - return 'mat3'; + do { - } else if ( value.isMatrix4 === true ) { + value = key[ valuePropertyName ]; - return 'mat4'; + if ( value !== undefined ) { - } else if ( value.isColor === true ) { + times.push( key.time ); + values.push( value ); - return 'color'; + } - } else if ( value instanceof ArrayBuffer ) { + key = jsonKeys[ i ++ ]; - return 'ArrayBuffer'; + } while ( key !== undefined ); } - return null; - } -function getValueFromType( type, ...params ) { - - const last4 = type ? type.slice( - 4 ) : undefined; - - if ( params.length === 1 ) { // ensure same behaviour as in NodeBuilder.format() - - if ( last4 === 'vec2' ) params = [ params[ 0 ], params[ 0 ] ]; - else if ( last4 === 'vec3' ) params = [ params[ 0 ], params[ 0 ], params[ 0 ] ]; - else if ( last4 === 'vec4' ) params = [ params[ 0 ], params[ 0 ], params[ 0 ], params[ 0 ] ]; +function subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) { - } + const clip = sourceClip.clone(); - if ( type === 'color' ) { + clip.name = name; - return new Color( ...params ); + const tracks = []; - } else if ( last4 === 'vec2' ) { + for ( let i = 0; i < clip.tracks.length; ++ i ) { - return new Vector2( ...params ); + const track = clip.tracks[ i ]; + const valueSize = track.getValueSize(); - } else if ( last4 === 'vec3' ) { + const times = []; + const values = []; - return new Vector3( ...params ); + for ( let j = 0; j < track.times.length; ++ j ) { - } else if ( last4 === 'vec4' ) { + const frame = track.times[ j ] * fps; - return new Vector4( ...params ); + if ( frame < startFrame || frame >= endFrame ) continue; - } else if ( last4 === 'mat3' ) { + times.push( track.times[ j ] ); - return new Matrix3( ...params ); + for ( let k = 0; k < valueSize; ++ k ) { - } else if ( last4 === 'mat4' ) { + values.push( track.values[ j * valueSize + k ] ); - return new Matrix4( ...params ); + } - } else if ( type === 'bool' ) { + } - return params[ 0 ] || false; + if ( times.length === 0 ) continue; - } else if ( ( type === 'float' ) || ( type === 'int' ) || ( type === 'uint' ) ) { + track.times = convertArray( times, track.times.constructor ); + track.values = convertArray( values, track.values.constructor ); - return params[ 0 ] || 0; + tracks.push( track ); - } else if ( type === 'string' ) { + } - return params[ 0 ] || ''; + clip.tracks = tracks; - } else if ( type === 'ArrayBuffer' ) { + // find minimum .times value across all tracks in the trimmed clip - return base64ToArrayBuffer( params[ 0 ] ); + let minStartTime = Infinity; - } + for ( let i = 0; i < clip.tracks.length; ++ i ) { - return null; + if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) { -} + minStartTime = clip.tracks[ i ].times[ 0 ]; -function arrayBufferToBase64( arrayBuffer ) { + } - let chars = ''; + } - const array = new Uint8Array( arrayBuffer ); + // shift all tracks such that clip begins at t=0 - for ( let i = 0; i < array.length; i ++ ) { + for ( let i = 0; i < clip.tracks.length; ++ i ) { - chars += String.fromCharCode( array[ i ] ); + clip.tracks[ i ].shift( - 1 * minStartTime ); } - return btoa( chars ); + clip.resetDuration(); + + return clip; } -function base64ToArrayBuffer( base64 ) { +function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) { - return Uint8Array.from( atob( base64 ), c => c.charCodeAt( 0 ) ).buffer; + if ( fps <= 0 ) fps = 30; -} + const numTracks = referenceClip.tracks.length; + const referenceTime = referenceFrame / fps; -var NodeUtils = /*#__PURE__*/Object.freeze({ - __proto__: null, - arrayBufferToBase64: arrayBufferToBase64, - base64ToArrayBuffer: base64ToArrayBuffer, - getCacheKey: getCacheKey$1, - getNodeChildren: getNodeChildren, - getValueFromType: getValueFromType, - getValueType: getValueType -}); + // Make each track's values relative to the values at the reference frame + for ( let i = 0; i < numTracks; ++ i ) { -const NodeShaderStage = { - VERTEX: 'vertex', - FRAGMENT: 'fragment' -}; + const referenceTrack = referenceClip.tracks[ i ]; + const referenceTrackType = referenceTrack.ValueTypeName; -const NodeUpdateType = { - NONE: 'none', - FRAME: 'frame', - RENDER: 'render', - OBJECT: 'object' -}; + // Skip this track if it's non-numeric + if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue; -const NodeType = { - BOOLEAN: 'bool', - INTEGER: 'int', - FLOAT: 'float', - VECTOR2: 'vec2', - VECTOR3: 'vec3', - VECTOR4: 'vec4', - MATRIX2: 'mat2', - MATRIX3: 'mat3', - MATRIX4: 'mat4' -}; + // Find the track in the target clip whose name and type matches the reference track + const targetTrack = targetClip.tracks.find( function ( track ) { -const defaultShaderStages = [ 'fragment', 'vertex' ]; -const defaultBuildStages = [ 'setup', 'analyze', 'generate' ]; -const shaderStages = [ ...defaultShaderStages, 'compute' ]; -const vectorComponents = [ 'x', 'y', 'z', 'w' ]; + return track.name === referenceTrack.name + && track.ValueTypeName === referenceTrackType; -const Nodes$1 = new Map(); + } ); -let _nodeId = 0; + if ( targetTrack === undefined ) continue; -class Node extends EventDispatcher { + let referenceOffset = 0; + const referenceValueSize = referenceTrack.getValueSize(); - constructor( nodeType = null ) { + if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) { - super(); + referenceOffset = referenceValueSize / 3; - this.nodeType = nodeType; + } - this.updateType = NodeUpdateType.NONE; - this.updateBeforeType = NodeUpdateType.NONE; - this.updateAfterType = NodeUpdateType.NONE; + let targetOffset = 0; + const targetValueSize = targetTrack.getValueSize(); - this.uuid = MathUtils.generateUUID(); + if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) { - this.version = 0; + targetOffset = targetValueSize / 3; - this._cacheKey = null; - this._cacheKeyVersion = 0; + } - this.global = false; + const lastIndex = referenceTrack.times.length - 1; + let referenceValue; - this.isNode = true; + // Find the value to subtract out of the track + if ( referenceTime <= referenceTrack.times[ 0 ] ) { - Object.defineProperty( this, 'id', { value: _nodeId ++ } ); + // Reference frame is earlier than the first keyframe, so just use the first keyframe + const startIndex = referenceOffset; + const endIndex = referenceValueSize - referenceOffset; + referenceValue = referenceTrack.values.slice( startIndex, endIndex ); - } + } else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) { - set needsUpdate( value ) { + // Reference frame is after the last keyframe, so just use the last keyframe + const startIndex = lastIndex * referenceValueSize + referenceOffset; + const endIndex = startIndex + referenceValueSize - referenceOffset; + referenceValue = referenceTrack.values.slice( startIndex, endIndex ); - if ( value === true ) { + } else { - this.version ++; + // Interpolate to the reference value + const interpolant = referenceTrack.createInterpolant(); + const startIndex = referenceOffset; + const endIndex = referenceValueSize - referenceOffset; + interpolant.evaluate( referenceTime ); + referenceValue = interpolant.resultBuffer.slice( startIndex, endIndex ); } - } - - get type() { + // Conjugate the quaternion + if ( referenceTrackType === 'quaternion' ) { - return this.constructor.type; + const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate(); + referenceQuat.toArray( referenceValue ); - } + } - onUpdate( callback, updateType ) { + // Subtract the reference value from all of the track values - this.updateType = updateType; - this.update = callback.bind( this.getSelf() ); + const numTimes = targetTrack.times.length; + for ( let j = 0; j < numTimes; ++ j ) { - return this; + const valueStart = j * targetValueSize + targetOffset; - } + if ( referenceTrackType === 'quaternion' ) { - onFrameUpdate( callback ) { + // Multiply the conjugate for quaternion track types + Quaternion.multiplyQuaternionsFlat( + targetTrack.values, + valueStart, + referenceValue, + 0, + targetTrack.values, + valueStart + ); - return this.onUpdate( callback, NodeUpdateType.FRAME ); + } else { - } + const valueEnd = targetValueSize - targetOffset * 2; - onRenderUpdate( callback ) { + // Subtract each value for all other numeric track types + for ( let k = 0; k < valueEnd; ++ k ) { - return this.onUpdate( callback, NodeUpdateType.RENDER ); + targetTrack.values[ valueStart + k ] -= referenceValue[ k ]; - } + } - onObjectUpdate( callback ) { + } - return this.onUpdate( callback, NodeUpdateType.OBJECT ); + } } - onReference( callback ) { + targetClip.blendMode = AdditiveAnimationBlendMode; - this.updateReference = callback.bind( this.getSelf() ); + return targetClip; - return this; +} - } +const AnimationUtils = { + convertArray: convertArray, + isTypedArray: isTypedArray, + getKeyframeOrder: getKeyframeOrder, + sortedArray: sortedArray, + flattenJSON: flattenJSON, + subclip: subclip, + makeClipAdditive: makeClipAdditive +}; - getSelf() { +/** + * Abstract base class of interpolants over parametric samples. + * + * The parameter domain is one dimensional, typically the time or a path + * along a curve defined by the data. + * + * The sample values can have any dimensionality and derived classes may + * apply special interpretations to the data. + * + * This class provides the interval seek in a Template Method, deferring + * the actual interpolation to derived classes. + * + * Time complexity is O(1) for linear access crossing at most two points + * and O(log N) for random access, where N is the number of positions. + * + * References: + * + * http://www.oodesign.com/template-method-pattern.html + * + */ - // Returns non-node object. +class Interpolant { - return this.self || this; + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - } + this.parameterPositions = parameterPositions; + this._cachedIndex = 0; - updateReference( /*state*/ ) { + this.resultBuffer = resultBuffer !== undefined ? + resultBuffer : new sampleValues.constructor( sampleSize ); + this.sampleValues = sampleValues; + this.valueSize = sampleSize; - return this; + this.settings = null; + this.DefaultSettings_ = {}; } - isGlobal( /*builder*/ ) { + evaluate( t ) { - return this.global; - - } - - * getChildren() { - - for ( const { childNode } of getNodeChildren( this ) ) { - - yield childNode; + const pp = this.parameterPositions; + let i1 = this._cachedIndex, + t1 = pp[ i1 ], + t0 = pp[ i1 - 1 ]; - } + validate_interval: { - } + seek: { - dispose() { + let right; - this.dispatchEvent( { type: 'dispose' } ); + linear_scan: { - } + //- See http://jsperf.com/comparison-to-undefined/3 + //- slower code: + //- + //- if ( t >= t1 || t1 === undefined ) { + forward_scan: if ( ! ( t < t1 ) ) { - traverse( callback ) { + for ( let giveUpAt = i1 + 2; ; ) { - callback( this ); + if ( t1 === undefined ) { - for ( const childNode of this.getChildren() ) { + if ( t < t0 ) break forward_scan; - childNode.traverse( callback ); + // after end - } + i1 = pp.length; + this._cachedIndex = i1; + return this.copySampleValue_( i1 - 1 ); - } + } - getCacheKey( force = false ) { + if ( i1 === giveUpAt ) break; // this loop - force = force || this.version !== this._cacheKeyVersion; + t0 = t1; + t1 = pp[ ++ i1 ]; - if ( force === true || this._cacheKey === null ) { + if ( t < t1 ) { - this._cacheKey = getCacheKey$1( this, force ); - this._cacheKeyVersion = this.version; + // we have arrived at the sought interval + break seek; - } + } - return this._cacheKey; + } - } + // prepare binary search on the right side of the index + right = pp.length; + break linear_scan; - getScope() { + } - return this; + //- slower code: + //- if ( t < t0 || t0 === undefined ) { + if ( ! ( t >= t0 ) ) { - } + // looping? - getHash( /*builder*/ ) { + const t1global = pp[ 1 ]; - return this.uuid; + if ( t < t1global ) { - } + i1 = 2; // + 1, using the scan for the details + t0 = t1global; - getUpdateType() { + } - return this.updateType; + // linear reverse scan - } + for ( let giveUpAt = i1 - 2; ; ) { - getUpdateBeforeType() { + if ( t0 === undefined ) { - return this.updateBeforeType; + // before start - } + this._cachedIndex = 0; + return this.copySampleValue_( 0 ); - getUpdateAfterType() { + } - return this.updateAfterType; + if ( i1 === giveUpAt ) break; // this loop - } + t1 = t0; + t0 = pp[ -- i1 - 1 ]; - getElementType( builder ) { + if ( t >= t0 ) { - const type = this.getNodeType( builder ); - const elementType = builder.getElementType( type ); + // we have arrived at the sought interval + break seek; - return elementType; + } - } + } - getNodeType( builder ) { + // prepare binary search on the left side of the index + right = i1; + i1 = 0; + break linear_scan; - const nodeProperties = builder.getNodeProperties( this ); + } - if ( nodeProperties.outputNode ) { + // the interval is valid - return nodeProperties.outputNode.getNodeType( builder ); + break validate_interval; - } + } // linear scan - return this.nodeType; + // binary search - } + while ( i1 < right ) { - getShared( builder ) { + const mid = ( i1 + right ) >>> 1; - const hash = this.getHash( builder ); - const nodeFromHash = builder.getNodeFromHash( hash ); + if ( t < pp[ mid ] ) { - return nodeFromHash || this; + right = mid; - } + } else { - setup( builder ) { + i1 = mid + 1; - const nodeProperties = builder.getNodeProperties( this ); + } - let index = 0; + } - for ( const childNode of this.getChildren() ) { + t1 = pp[ i1 ]; + t0 = pp[ i1 - 1 ]; - nodeProperties[ 'node' + index ++ ] = childNode; + // check boundary cases, again - } + if ( t0 === undefined ) { - // return a outputNode if exists - return null; + this._cachedIndex = 0; + return this.copySampleValue_( 0 ); - } + } - analyze( builder ) { + if ( t1 === undefined ) { - const usageCount = builder.increaseUsage( this ); + i1 = pp.length; + this._cachedIndex = i1; + return this.copySampleValue_( i1 - 1 ); - if ( usageCount === 1 ) { + } - // node flow children + } // seek - const nodeProperties = builder.getNodeProperties( this ); + this._cachedIndex = i1; - for ( const childNode of Object.values( nodeProperties ) ) { + this.intervalChanged_( i1, t0, t1 ); - if ( childNode && childNode.isNode === true ) { + } // validate_interval - childNode.build( builder ); + return this.interpolate_( i1, t0, t, t1 ); - } + } - } + getSettings_() { - } + return this.settings || this.DefaultSettings_; } - generate( builder, output ) { - - const { outputNode } = builder.getNodeProperties( this ); + copySampleValue_( index ) { - if ( outputNode && outputNode.isNode === true ) { + // copies a sample value to the result buffer - return outputNode.build( builder, output ); + const result = this.resultBuffer, + values = this.sampleValues, + stride = this.valueSize, + offset = index * stride; - } + for ( let i = 0; i !== stride; ++ i ) { - } + result[ i ] = values[ offset + i ]; - updateBefore( /*frame*/ ) { + } - console.warn( 'Abstract function.' ); + return result; } - updateAfter( /*frame*/ ) { + // Template methods for derived classes: - console.warn( 'Abstract function.' ); + interpolate_( /* i1, t0, t, t1 */ ) { + + throw new Error( 'call to abstract method' ); + // implementations shall return this.resultBuffer } - update( /*frame*/ ) { + intervalChanged_( /* i1, t0, t1 */ ) { - console.warn( 'Abstract function.' ); + // empty } - build( builder, output = null ) { +} - const refNode = this.getShared( builder ); +/** + * Fast and simple cubic spline interpolant. + * + * It was derived from a Hermitian construction setting the first derivative + * at each sample position to the linear slope between neighboring positions + * over their parameter interval. + */ - if ( this !== refNode ) { +class CubicInterpolant extends Interpolant { - return refNode.build( builder, output ); + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - } + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); - builder.addNode( this ); - builder.addChain( this ); + this._weightPrev = - 0; + this._offsetPrev = - 0; + this._weightNext = - 0; + this._offsetNext = - 0; - /* Build stages expected results: - - "setup" -> Node - - "analyze" -> null - - "generate" -> String - */ - let result = null; + this.DefaultSettings_ = { - const buildStage = builder.getBuildStage(); + endingStart: ZeroCurvatureEnding, + endingEnd: ZeroCurvatureEnding - if ( buildStage === 'setup' ) { + }; - this.updateReference( builder ); + } - const properties = builder.getNodeProperties( this ); + intervalChanged_( i1, t0, t1 ) { - if ( properties.initialized !== true ) { + const pp = this.parameterPositions; + let iPrev = i1 - 2, + iNext = i1 + 1, - const stackNodesBeforeSetup = builder.stack.nodes.length; + tPrev = pp[ iPrev ], + tNext = pp[ iNext ]; - properties.initialized = true; - properties.outputNode = this.setup( builder ); + if ( tPrev === undefined ) { - if ( properties.outputNode !== null && builder.stack.nodes.length !== stackNodesBeforeSetup ) ; + switch ( this.getSettings_().endingStart ) { - for ( const childNode of Object.values( properties ) ) { + case ZeroSlopeEnding: - if ( childNode && childNode.isNode === true ) { + // f'(t0) = 0 + iPrev = i1; + tPrev = 2 * t0 - t1; - childNode.build( builder ); + break; - } + case WrapAroundEnding: - } + // use the other end of the curve + iPrev = pp.length - 2; + tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ]; - } + break; - } else if ( buildStage === 'analyze' ) { + default: // ZeroCurvatureEnding - this.analyze( builder ); + // f''(t0) = 0 a.k.a. Natural Spline + iPrev = i1; + tPrev = t1; - } else if ( buildStage === 'generate' ) { + } - const isGenerateOnce = this.generate.length === 1; + } - if ( isGenerateOnce ) { + if ( tNext === undefined ) { - const type = this.getNodeType( builder ); - const nodeData = builder.getDataFromNode( this ); + switch ( this.getSettings_().endingEnd ) { - result = nodeData.snippet; + case ZeroSlopeEnding: - if ( result === undefined ) { + // f'(tN) = 0 + iNext = i1; + tNext = 2 * t1 - t0; - result = this.generate( builder ) || ''; + break; - nodeData.snippet = result; + case WrapAroundEnding: - } + // use the other end of the curve + iNext = 1; + tNext = t1 + pp[ 1 ] - pp[ 0 ]; - result = builder.format( result, type, output ); + break; - } else { + default: // ZeroCurvatureEnding - result = this.generate( builder, output ) || ''; + // f''(tN) = 0, a.k.a. Natural Spline + iNext = i1 - 1; + tNext = t0; } } - builder.removeChain( this ); + const halfDt = ( t1 - t0 ) * 0.5, + stride = this.valueSize; - return result; + this._weightPrev = halfDt / ( t0 - tPrev ); + this._weightNext = halfDt / ( tNext - t1 ); + this._offsetPrev = iPrev * stride; + this._offsetNext = iNext * stride; } - getSerializeChildren() { - - return getNodeChildren( this ); + interpolate_( i1, t0, t, t1 ) { - } + const result = this.resultBuffer, + values = this.sampleValues, + stride = this.valueSize, - serialize( json ) { + o1 = i1 * stride, o0 = o1 - stride, + oP = this._offsetPrev, oN = this._offsetNext, + wP = this._weightPrev, wN = this._weightNext, - const nodeChildren = this.getSerializeChildren(); + p = ( t - t0 ) / ( t1 - t0 ), + pp = p * p, + ppp = pp * p; - const inputNodes = {}; + // evaluate polynomials - for ( const { property, index, childNode } of nodeChildren ) { + const sP = - wP * ppp + 2 * wP * pp - wP * p; + const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1; + const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p; + const sN = wN * ppp - wN * pp; - if ( index !== undefined ) { + // combine data linearly - if ( inputNodes[ property ] === undefined ) { + for ( let i = 0; i !== stride; ++ i ) { - inputNodes[ property ] = Number.isInteger( index ) ? [] : {}; + result[ i ] = + sP * values[ oP + i ] + + s0 * values[ o0 + i ] + + s1 * values[ o1 + i ] + + sN * values[ oN + i ]; - } + } - inputNodes[ property ][ index ] = childNode.toJSON( json.meta ).uuid; + return result; - } else { + } - inputNodes[ property ] = childNode.toJSON( json.meta ).uuid; +} - } +class LinearInterpolant extends Interpolant { - } + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - if ( Object.keys( inputNodes ).length > 0 ) { + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); - json.inputNodes = inputNodes; + } - } + interpolate_( i1, t0, t, t1 ) { - } + const result = this.resultBuffer, + values = this.sampleValues, + stride = this.valueSize, - deserialize( json ) { + offset1 = i1 * stride, + offset0 = offset1 - stride, - if ( json.inputNodes !== undefined ) { + weight1 = ( t - t0 ) / ( t1 - t0 ), + weight0 = 1 - weight1; - const nodes = json.meta.nodes; + for ( let i = 0; i !== stride; ++ i ) { - for ( const property in json.inputNodes ) { + result[ i ] = + values[ offset0 + i ] * weight0 + + values[ offset1 + i ] * weight1; - if ( Array.isArray( json.inputNodes[ property ] ) ) { + } - const inputArray = []; + return result; - for ( const uuid of json.inputNodes[ property ] ) { + } - inputArray.push( nodes[ uuid ] ); +} - } +/** + * + * Interpolant that evaluates to the sample value at the position preceding + * the parameter. + */ - this[ property ] = inputArray; +class DiscreteInterpolant extends Interpolant { - } else if ( typeof json.inputNodes[ property ] === 'object' ) { + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - const inputObject = {}; + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); - for ( const subProperty in json.inputNodes[ property ] ) { + } - const uuid = json.inputNodes[ property ][ subProperty ]; + interpolate_( i1 /*, t0, t, t1 */ ) { - inputObject[ subProperty ] = nodes[ uuid ]; + return this.copySampleValue_( i1 - 1 ); - } + } - this[ property ] = inputObject; +} - } else { +class KeyframeTrack { - const uuid = json.inputNodes[ property ]; + constructor( name, times, values, interpolation ) { - this[ property ] = nodes[ uuid ]; + if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' ); + if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name ); - } + this.name = name; - } + this.times = convertArray( times, this.TimeBufferType ); + this.values = convertArray( values, this.ValueBufferType ); - } + this.setInterpolation( interpolation || this.DefaultInterpolation ); } - toJSON( meta ) { + // Serialization (in static context, because of constructor invocation + // and automatic invocation of .toJSON): - const { uuid, type } = this; - const isRoot = ( meta === undefined || typeof meta === 'string' ); + static toJSON( track ) { - if ( isRoot ) { + const trackType = track.constructor; - meta = { - textures: {}, - images: {}, - nodes: {} - }; + let json; - } + // derived classes can define a static toJSON method + if ( trackType.toJSON !== this.toJSON ) { - // serialize + json = trackType.toJSON( track ); - let data = meta.nodes[ uuid ]; + } else { - if ( data === undefined ) { + // by default, we assume the data can be serialized as-is + json = { - data = { - uuid, - type, - meta, - metadata: { - version: 4.6, - type: 'Node', - generator: 'Node.toJSON' - } - }; + 'name': track.name, + 'times': convertArray( track.times, Array ), + 'values': convertArray( track.values, Array ) - if ( isRoot !== true ) meta.nodes[ data.uuid ] = data; + }; - this.serialize( data ); + const interpolation = track.getInterpolation(); - delete data.meta; + if ( interpolation !== track.DefaultInterpolation ) { - } + json.interpolation = interpolation; - // TODO: Copied from Object3D.toJSON + } - function extractFromCache( cache ) { + } - const values = []; + json.type = track.ValueTypeName; // mandatory - for ( const key in cache ) { + return json; - const data = cache[ key ]; - delete data.metadata; - values.push( data ); + } - } + InterpolantFactoryMethodDiscrete( result ) { - return values; + return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result ); - } + } - if ( isRoot ) { + InterpolantFactoryMethodLinear( result ) { - const textures = extractFromCache( meta.textures ); - const images = extractFromCache( meta.images ); - const nodes = extractFromCache( meta.nodes ); + return new LinearInterpolant( this.times, this.values, this.getValueSize(), result ); - if ( textures.length > 0 ) data.textures = textures; - if ( images.length > 0 ) data.images = images; - if ( nodes.length > 0 ) data.nodes = nodes; + } - } + InterpolantFactoryMethodSmooth( result ) { - return data; + return new CubicInterpolant( this.times, this.values, this.getValueSize(), result ); } -} + setInterpolation( interpolation ) { -Node.type = /*@__PURE__*/ registerNode( '', Node ); + let factoryMethod; -function registerNode( type, nodeClass ) { + switch ( interpolation ) { - const suffix = 'Node'; - const nodeType = type + suffix; + case InterpolateDiscrete: - if ( typeof nodeClass !== 'function' ) throw new Error( `TSL.Node: Node class ${ type } is not a class` ); + factoryMethod = this.InterpolantFactoryMethodDiscrete; - if ( Nodes$1.has( nodeType ) ) { + break; - console.warn( `TSL.Node: Redefinition of node class ${ nodeType }` ); - return; + case InterpolateLinear: - } + factoryMethod = this.InterpolantFactoryMethodLinear; - if ( type.slice( - suffix.length ) === suffix ) { + break; - console.warn( `TSL.Node: Node class ${ nodeType } should not have '${ suffix }' suffix.` ); - return; + case InterpolateSmooth: - } + factoryMethod = this.InterpolantFactoryMethodSmooth; - Nodes$1.set( nodeType, nodeClass ); - nodeClass.type = nodeType; + break; - return nodeType; + } -} + if ( factoryMethod === undefined ) { -function createNodeFromType( type ) { + const message = 'unsupported interpolation for ' + + this.ValueTypeName + ' keyframe track named ' + this.name; - const Class = Nodes$1.get( type ); + if ( this.createInterpolant === undefined ) { - if ( Class !== undefined ) { + // fall back to default, unless the default itself is messed up + if ( interpolation !== this.DefaultInterpolation ) { - return new Class(); + this.setInterpolation( this.DefaultInterpolation ); - } + } else { -} + throw new Error( message ); // fatal, in this case -class ArrayElementNode extends Node { // @TODO: If extending from TempNode it breaks webgpu_compute + } - constructor( node, indexNode ) { + } - super(); + console.warn( 'THREE.KeyframeTrack:', message ); + return this; - this.node = node; - this.indexNode = indexNode; + } - this.isArrayElementNode = true; + this.createInterpolant = factoryMethod; - } + return this; - getNodeType( builder ) { + } - return this.node.getElementType( builder ); + getInterpolation() { - } + switch ( this.createInterpolant ) { - generate( builder ) { + case this.InterpolantFactoryMethodDiscrete: - const nodeSnippet = this.node.build( builder ); - const indexSnippet = this.indexNode.build( builder, 'uint' ); + return InterpolateDiscrete; - return `${nodeSnippet}[ ${indexSnippet} ]`; + case this.InterpolantFactoryMethodLinear: - } + return InterpolateLinear; -} + case this.InterpolantFactoryMethodSmooth: -ArrayElementNode.type = /*@__PURE__*/ registerNode( 'ArrayElement', ArrayElementNode ); + return InterpolateSmooth; -class ConvertNode extends Node { + } - constructor( node, convertTo ) { + } - super(); + getValueSize() { - this.node = node; - this.convertTo = convertTo; + return this.values.length / this.times.length; } - getNodeType( builder ) { - - const requestType = this.node.getNodeType( builder ); + // move all keyframes either forwards or backwards in time + shift( timeOffset ) { - let convertTo = null; + if ( timeOffset !== 0.0 ) { - for ( const overloadingType of this.convertTo.split( '|' ) ) { + const times = this.times; - if ( convertTo === null || builder.getTypeLength( requestType ) === builder.getTypeLength( overloadingType ) ) { + for ( let i = 0, n = times.length; i !== n; ++ i ) { - convertTo = overloadingType; + times[ i ] += timeOffset; } } - return convertTo; - - } - - serialize( data ) { - - super.serialize( data ); - - data.convertTo = this.convertTo; + return this; } - deserialize( data ) { + // scale all keyframe times by a factor (useful for frame <-> seconds conversions) + scale( timeScale ) { - super.deserialize( data ); + if ( timeScale !== 1.0 ) { - this.convertTo = data.convertTo; + const times = this.times; - } + for ( let i = 0, n = times.length; i !== n; ++ i ) { - generate( builder, output ) { + times[ i ] *= timeScale; - const node = this.node; - const type = this.getNodeType( builder ); + } - const snippet = node.build( builder, type ); + } - return builder.format( snippet, type, output ); + return this; } -} - -ConvertNode.type = /*@__PURE__*/ registerNode( 'Convert', ConvertNode ); + // removes keyframes before and after animation without changing any values within the range [startTime, endTime]. + // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values + trim( startTime, endTime ) { -class TempNode extends Node { + const times = this.times, + nKeys = times.length; - constructor( type ) { + let from = 0, + to = nKeys - 1; - super( type ); + while ( from !== nKeys && times[ from ] < startTime ) { - this.isTempNode = true; + ++ from; - } + } - hasDependencies( builder ) { + while ( to !== - 1 && times[ to ] > endTime ) { - return builder.getDataFromNode( this ).usageCount > 1; + -- to; - } + } - build( builder, output ) { + ++ to; // inclusive -> exclusive bound - const buildStage = builder.getBuildStage(); + if ( from !== 0 || to !== nKeys ) { - if ( buildStage === 'generate' ) { + // empty tracks are forbidden, so keep at least one keyframe + if ( from >= to ) { - const type = builder.getVectorType( this.getNodeType( builder, output ) ); - const nodeData = builder.getDataFromNode( this ); + to = Math.max( to, 1 ); + from = to - 1; - if ( nodeData.propertyName !== undefined ) { + } - return builder.format( nodeData.propertyName, type, output ); + const stride = this.getValueSize(); + this.times = times.slice( from, to ); + this.values = this.values.slice( from * stride, to * stride ); - } else if ( type !== 'void' && output !== 'void' && this.hasDependencies( builder ) ) { + } - const snippet = super.build( builder, type ); + return this; - const nodeVar = builder.getVarFromNode( this, null, type ); - const propertyName = builder.getPropertyName( nodeVar ); + } - builder.addLineFlowCode( `${propertyName} = ${snippet}` ); + // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable + validate() { - nodeData.snippet = snippet; - nodeData.propertyName = propertyName; + let valid = true; - return builder.format( nodeData.propertyName, type, output ); + const valueSize = this.getValueSize(); + if ( valueSize - Math.floor( valueSize ) !== 0 ) { - } + console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this ); + valid = false; } - return super.build( builder, output ); + const times = this.times, + values = this.values, - } + nKeys = times.length; -} + if ( nKeys === 0 ) { -TempNode.type = /*@__PURE__*/ registerNode( 'Temp', TempNode ); + console.error( 'THREE.KeyframeTrack: Track is empty.', this ); + valid = false; -class JoinNode extends TempNode { + } - constructor( nodes = [], nodeType = null ) { + let prevTime = null; - super( nodeType ); + for ( let i = 0; i !== nKeys; i ++ ) { - this.nodes = nodes; + const currTime = times[ i ]; - } + if ( typeof currTime === 'number' && isNaN( currTime ) ) { - getNodeType( builder ) { + console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime ); + valid = false; + break; - if ( this.nodeType !== null ) { + } - return builder.getVectorType( this.nodeType ); + if ( prevTime !== null && prevTime > currTime ) { - } + console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime ); + valid = false; + break; - return builder.getTypeFromLength( this.nodes.reduce( ( count, cur ) => count + builder.getTypeLength( cur.getNodeType( builder ) ), 0 ) ); + } - } + prevTime = currTime; - generate( builder, output ) { + } - const type = this.getNodeType( builder ); - const nodes = this.nodes; + if ( values !== undefined ) { - const primitiveType = builder.getComponentType( type ); + if ( isTypedArray( values ) ) { - const snippetValues = []; + for ( let i = 0, n = values.length; i !== n; ++ i ) { - for ( const input of nodes ) { + const value = values[ i ]; - let inputSnippet = input.build( builder ); + if ( isNaN( value ) ) { - const inputPrimitiveType = builder.getComponentType( input.getNodeType( builder ) ); + console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value ); + valid = false; + break; - if ( inputPrimitiveType !== primitiveType ) { + } - inputSnippet = builder.format( inputSnippet, inputPrimitiveType, primitiveType ); + } } - snippetValues.push( inputSnippet ); - } - const snippet = `${ builder.getType( type ) }( ${ snippetValues.join( ', ' ) } )`; - - return builder.format( snippet, type, output ); + return valid; } -} + // removes equivalent sequential keys as common in morph target sequences + // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0) + optimize() { -JoinNode.type = /*@__PURE__*/ registerNode( 'Join', JoinNode ); + // times or values may be shared with other tracks, so overwriting is unsafe + const times = this.times.slice(), + values = this.values.slice(), + stride = this.getValueSize(), -const stringVectorComponents = vectorComponents.join( '' ); + smoothInterpolation = this.getInterpolation() === InterpolateSmooth, -class SplitNode extends Node { + lastIndex = times.length - 1; - constructor( node, components = 'x' ) { + let writeIndex = 1; - super(); + for ( let i = 1; i < lastIndex; ++ i ) { - this.node = node; - this.components = components; + let keep = false; - this.isSplitNode = true; + const time = times[ i ]; + const timeNext = times[ i + 1 ]; - } + // remove adjacent keyframes scheduled at the same time - getVectorLength() { + if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) { - let vectorLength = this.components.length; + if ( ! smoothInterpolation ) { - for ( const c of this.components ) { + // remove unnecessary keyframes same as their neighbors - vectorLength = Math.max( vectorComponents.indexOf( c ) + 1, vectorLength ); + const offset = i * stride, + offsetP = offset - stride, + offsetN = offset + stride; - } + for ( let j = 0; j !== stride; ++ j ) { - return vectorLength; + const value = values[ offset + j ]; - } + if ( value !== values[ offsetP + j ] || + value !== values[ offsetN + j ] ) { - getComponentType( builder ) { + keep = true; + break; - return builder.getComponentType( this.node.getNodeType( builder ) ); + } - } + } - getNodeType( builder ) { + } else { - return builder.getTypeFromLength( this.components.length, this.getComponentType( builder ) ); + keep = true; - } + } - generate( builder, output ) { + } - const node = this.node; - const nodeTypeLength = builder.getTypeLength( node.getNodeType( builder ) ); + // in-place compaction - let snippet = null; + if ( keep ) { - if ( nodeTypeLength > 1 ) { + if ( i !== writeIndex ) { - let type = null; + times[ writeIndex ] = times[ i ]; - const componentsLength = this.getVectorLength(); + const readOffset = i * stride, + writeOffset = writeIndex * stride; - if ( componentsLength >= nodeTypeLength ) { + for ( let j = 0; j !== stride; ++ j ) { - // needed expand the input node + values[ writeOffset + j ] = values[ readOffset + j ]; - type = builder.getTypeFromLength( this.getVectorLength(), this.getComponentType( builder ) ); + } - } + } - const nodeSnippet = node.build( builder, type ); + ++ writeIndex; - if ( this.components.length === nodeTypeLength && this.components === stringVectorComponents.slice( 0, this.components.length ) ) { + } - // unnecessary swizzle + } - snippet = builder.format( nodeSnippet, type, output ); + // flush last keyframe (compaction looks ahead) - } else { + if ( lastIndex > 0 ) { - snippet = builder.format( `${nodeSnippet}.${this.components}`, this.getNodeType( builder ), output ); + times[ writeIndex ] = times[ lastIndex ]; - } + for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) { - } else { + values[ writeOffset + j ] = values[ readOffset + j ]; - // ignore .components if .node returns float/integer + } - snippet = node.build( builder, output ); + ++ writeIndex; } - return snippet; + if ( writeIndex !== times.length ) { - } + this.times = times.slice( 0, writeIndex ); + this.values = values.slice( 0, writeIndex * stride ); - serialize( data ) { + } else { - super.serialize( data ); + this.times = times; + this.values = values; - data.components = this.components; + } + + return this; } - deserialize( data ) { + clone() { - super.deserialize( data ); + const times = this.times.slice(); + const values = this.values.slice(); - this.components = data.components; + const TypedKeyframeTrack = this.constructor; + const track = new TypedKeyframeTrack( this.name, times, values ); + + // Interpolant argument to constructor is not saved, so copy the factory method directly. + track.createInterpolant = this.createInterpolant; + + return track; } } -SplitNode.type = /*@__PURE__*/ registerNode( 'Split', SplitNode ); - -class SetNode extends TempNode { +KeyframeTrack.prototype.TimeBufferType = Float32Array; +KeyframeTrack.prototype.ValueBufferType = Float32Array; +KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear; - constructor( sourceNode, components, targetNode ) { +/** + * A Track of Boolean keyframe values. + */ +class BooleanKeyframeTrack extends KeyframeTrack { - super(); + // No interpolation parameter because only InterpolateDiscrete is valid. + constructor( name, times, values ) { - this.sourceNode = sourceNode; - this.components = components; - this.targetNode = targetNode; + super( name, times, values ); } - getNodeType( builder ) { +} - return this.sourceNode.getNodeType( builder ); +BooleanKeyframeTrack.prototype.ValueTypeName = 'bool'; +BooleanKeyframeTrack.prototype.ValueBufferType = Array; +BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; +BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; +BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; - } +/** + * A Track of keyframe values that represent color. + */ +class ColorKeyframeTrack extends KeyframeTrack {} - generate( builder ) { +ColorKeyframeTrack.prototype.ValueTypeName = 'color'; - const { sourceNode, components, targetNode } = this; +/** + * A Track of numeric keyframe values. + */ +class NumberKeyframeTrack extends KeyframeTrack {} - const sourceType = this.getNodeType( builder ); - const targetType = builder.getTypeFromLength( components.length ); +NumberKeyframeTrack.prototype.ValueTypeName = 'number'; - const targetSnippet = targetNode.build( builder, targetType ); - const sourceSnippet = sourceNode.build( builder, sourceType ); +/** + * Spherical linear unit quaternion interpolant. + */ - const length = builder.getTypeLength( sourceType ); - const snippetValues = []; +class QuaternionLinearInterpolant extends Interpolant { - for ( let i = 0; i < length; i ++ ) { + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { - const component = vectorComponents[ i ]; + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); - if ( component === components[ 0 ] ) { + } - snippetValues.push( targetSnippet ); + interpolate_( i1, t0, t, t1 ) { - i += components.length - 1; + const result = this.resultBuffer, + values = this.sampleValues, + stride = this.valueSize, - } else { + alpha = ( t - t0 ) / ( t1 - t0 ); - snippetValues.push( sourceSnippet + '.' + component ); + let offset = i1 * stride; - } + for ( let end = offset + stride; offset !== end; offset += 4 ) { + + Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha ); } - return `${ builder.getType( sourceType ) }( ${ snippetValues.join( ', ' ) } )`; + return result; } } -SetNode.type = /*@__PURE__*/ registerNode( 'Set', SetNode ); - -class FlipNode extends TempNode { - - constructor( sourceNode, components ) { +/** + * A Track of quaternion keyframe values. + */ +class QuaternionKeyframeTrack extends KeyframeTrack { - super(); + InterpolantFactoryMethodLinear( result ) { - this.sourceNode = sourceNode; - this.components = components; + return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result ); } - getNodeType( builder ) { - - return this.sourceNode.getNodeType( builder ); - - } +} - generate( builder ) { +QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion'; +// ValueBufferType is inherited +// DefaultInterpolation is inherited; +QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; - const { components, sourceNode } = this; +/** + * A Track that interpolates Strings + */ +class StringKeyframeTrack extends KeyframeTrack { - const sourceType = this.getNodeType( builder ); - const sourceSnippet = sourceNode.build( builder ); + // No interpolation parameter because only InterpolateDiscrete is valid. + constructor( name, times, values ) { - const sourceCache = builder.getVarFromNode( this ); - const sourceProperty = builder.getPropertyName( sourceCache ); + super( name, times, values ); - builder.addLineFlowCode( sourceProperty + ' = ' + sourceSnippet ); + } - const length = builder.getTypeLength( sourceType ); - const snippetValues = []; +} - let componentIndex = 0; +StringKeyframeTrack.prototype.ValueTypeName = 'string'; +StringKeyframeTrack.prototype.ValueBufferType = Array; +StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; +StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; +StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; - for ( let i = 0; i < length; i ++ ) { +/** + * A Track of vectored keyframe values. + */ +class VectorKeyframeTrack extends KeyframeTrack {} - const component = vectorComponents[ i ]; +VectorKeyframeTrack.prototype.ValueTypeName = 'vector'; - if ( component === components[ componentIndex ] ) { +class AnimationClip { - snippetValues.push( '1.0 - ' + ( sourceProperty + '.' + component ) ); + constructor( name = '', duration = - 1, tracks = [], blendMode = NormalAnimationBlendMode ) { - componentIndex ++; + this.name = name; + this.tracks = tracks; + this.duration = duration; + this.blendMode = blendMode; - } else { + this.uuid = generateUUID(); - snippetValues.push( sourceProperty + '.' + component ); + // this means it should figure out its duration by scanning the tracks + if ( this.duration < 0 ) { - } + this.resetDuration(); } - return `${ builder.getType( sourceType ) }( ${ snippetValues.join( ', ' ) } )`; - } -} -FlipNode.type = /*@__PURE__*/ registerNode( 'Flip', FlipNode ); + static parse( json ) { -class InputNode extends Node { + const tracks = [], + jsonTracks = json.tracks, + frameTime = 1.0 / ( json.fps || 1.0 ); - constructor( value, nodeType = null ) { + for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) { - super( nodeType ); + tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) ); - this.isInputNode = true; + } - this.value = value; - this.precision = null; + const clip = new this( json.name, json.duration, tracks, json.blendMode ); + clip.uuid = json.uuid; - } + return clip; - getNodeType( /*builder*/ ) { + } - if ( this.nodeType === null ) { + static toJSON( clip ) { - return getValueType( this.value ); + const tracks = [], + clipTracks = clip.tracks; - } + const json = { - return this.nodeType; - - } - - getInputType( builder ) { + 'name': clip.name, + 'duration': clip.duration, + 'tracks': tracks, + 'uuid': clip.uuid, + 'blendMode': clip.blendMode - return this.getNodeType( builder ); + }; - } + for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) { - setPrecision( precision ) { + tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) ); - this.precision = precision; + } - return this; + return json; } - serialize( data ) { + static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) { - super.serialize( data ); + const numMorphTargets = morphTargetSequence.length; + const tracks = []; - data.value = this.value; + for ( let i = 0; i < numMorphTargets; i ++ ) { - if ( this.value && this.value.toArray ) data.value = this.value.toArray(); + let times = []; + let values = []; - data.valueType = getValueType( this.value ); - data.nodeType = this.nodeType; + times.push( + ( i + numMorphTargets - 1 ) % numMorphTargets, + i, + ( i + 1 ) % numMorphTargets ); - if ( data.valueType === 'ArrayBuffer' ) data.value = arrayBufferToBase64( data.value ); + values.push( 0, 1, 0 ); - data.precision = this.precision; + const order = getKeyframeOrder( times ); + times = sortedArray( times, 1, order ); + values = sortedArray( values, 1, order ); - } + // if there is a key at the first frame, duplicate it as the + // last frame as well for perfect loop. + if ( ! noLoop && times[ 0 ] === 0 ) { - deserialize( data ) { + times.push( numMorphTargets ); + values.push( values[ 0 ] ); - super.deserialize( data ); + } - this.nodeType = data.nodeType; - this.value = Array.isArray( data.value ) ? getValueFromType( data.valueType, ...data.value ) : data.value; + tracks.push( + new NumberKeyframeTrack( + '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']', + times, values + ).scale( 1.0 / fps ) ); - this.precision = data.precision || null; + } - if ( this.value && this.value.fromArray ) this.value = this.value.fromArray( data.value ); + return new this( name, - 1, tracks ); } - generate( /*builder, output*/ ) { - - console.warn( 'Abstract function.' ); + static findByName( objectOrClipArray, name ) { - } + let clipArray = objectOrClipArray; -} + if ( ! Array.isArray( objectOrClipArray ) ) { -InputNode.type = /*@__PURE__*/ registerNode( 'Input', InputNode ); + const o = objectOrClipArray; + clipArray = o.geometry && o.geometry.animations || o.animations; -class ConstNode extends InputNode { + } - constructor( value, nodeType = null ) { + for ( let i = 0; i < clipArray.length; i ++ ) { - super( value, nodeType ); + if ( clipArray[ i ].name === name ) { - this.isConstNode = true; + return clipArray[ i ]; - } + } - generateConst( builder ) { + } - return builder.generateConst( this.getNodeType( builder ), this.value ); + return null; } - generate( builder, output ) { - - const type = this.getNodeType( builder ); + static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) { - return builder.format( this.generateConst( builder ), type, output ); + const animationToMorphTargets = {}; - } + // tested with https://regex101.com/ on trick sequences + // such flamingo_flyA_003, flamingo_run1_003, crdeath0059 + const pattern = /^([\w-]*?)([\d]+)$/; -} + // sort morph target names into animation groups based + // patterns like Walk_001, Walk_002, Run_001, Run_002 + for ( let i = 0, il = morphTargets.length; i < il; i ++ ) { -ConstNode.type = /*@__PURE__*/ registerNode( 'Const', ConstNode ); + const morphTarget = morphTargets[ i ]; + const parts = morphTarget.name.match( pattern ); -// + if ( parts && parts.length > 1 ) { -let currentStack = null; + const name = parts[ 1 ]; -const NodeElements = new Map(); + let animationMorphTargets = animationToMorphTargets[ name ]; -function addMethodChaining( name, nodeElement ) { + if ( ! animationMorphTargets ) { - if ( NodeElements.has( name ) ) { + animationToMorphTargets[ name ] = animationMorphTargets = []; - console.warn( `Redefinition of method chaining ${ name }` ); - return; + } - } + animationMorphTargets.push( morphTarget ); - if ( typeof nodeElement !== 'function' ) throw new Error( `Node element ${ name } is not a function` ); + } - NodeElements.set( name, nodeElement ); + } -} + const clips = []; -const parseSwizzle = ( props ) => props.replace( /r|s/g, 'x' ).replace( /g|t/g, 'y' ).replace( /b|p/g, 'z' ).replace( /a|q/g, 'w' ); -const parseSwizzleAndSort = ( props ) => parseSwizzle( props ).split( '' ).sort().join( '' ); + for ( const name in animationToMorphTargets ) { -const shaderNodeHandler = { + clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) ); - setup( NodeClosure, params ) { + } - const inputs = params.shift(); + return clips; - return NodeClosure( nodeObjects( inputs ), ...params ); + } - }, + // parse the animation.hierarchy format + static parseAnimation( animation, bones ) { - get( node, prop, nodeObj ) { + if ( ! animation ) { - if ( typeof prop === 'string' && node[ prop ] === undefined ) { + console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' ); + return null; - if ( node.isStackNode !== true && prop === 'assign' ) { + } - return ( ...params ) => { + const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) { - currentStack.assign( nodeObj, ...params ); + // only return track if there are actually keys. + if ( animationKeys.length !== 0 ) { - return nodeObj; + const times = []; + const values = []; - }; + flattenJSON( animationKeys, times, values, propertyName ); - } else if ( NodeElements.has( prop ) ) { + // empty keys are filtered out, so check again + if ( times.length !== 0 ) { - const nodeElement = NodeElements.get( prop ); + destTracks.push( new trackType( trackName, times, values ) ); - return node.isStackNode ? ( ...params ) => nodeObj.add( nodeElement( ...params ) ) : ( ...params ) => nodeElement( nodeObj, ...params ); + } - } else if ( prop === 'self' ) { + } - return node; + }; - } else if ( prop.endsWith( 'Assign' ) && NodeElements.has( prop.slice( 0, prop.length - 'Assign'.length ) ) ) { + const tracks = []; - const nodeElement = NodeElements.get( prop.slice( 0, prop.length - 'Assign'.length ) ); + const clipName = animation.name || 'default'; + const fps = animation.fps || 30; + const blendMode = animation.blendMode; - return node.isStackNode ? ( ...params ) => nodeObj.assign( params[ 0 ], nodeElement( ...params ) ) : ( ...params ) => nodeObj.assign( nodeElement( nodeObj, ...params ) ); + // automatic length determination in AnimationClip. + let duration = animation.length || - 1; - } else if ( /^[xyzwrgbastpq]{1,4}$/.test( prop ) === true ) { + const hierarchyTracks = animation.hierarchy || []; - // accessing properties ( swizzle ) + for ( let h = 0; h < hierarchyTracks.length; h ++ ) { - prop = parseSwizzle( prop ); + const animationKeys = hierarchyTracks[ h ].keys; - return nodeObject( new SplitNode( nodeObj, prop ) ); + // skip empty tracks + if ( ! animationKeys || animationKeys.length === 0 ) continue; - } else if ( /^set[XYZWRGBASTPQ]{1,4}$/.test( prop ) === true ) { + // process morph targets + if ( animationKeys[ 0 ].morphTargets ) { - // set properties ( swizzle ) and sort to xyzw sequence + // figure out all morph targets used in this track + const morphTargetNames = {}; - prop = parseSwizzleAndSort( prop.slice( 3 ).toLowerCase() ); + let k; - return ( value ) => nodeObject( new SetNode( node, prop, value ) ); + for ( k = 0; k < animationKeys.length; k ++ ) { - } else if ( /^flip[XYZWRGBASTPQ]{1,4}$/.test( prop ) === true ) { + if ( animationKeys[ k ].morphTargets ) { - // set properties ( swizzle ) and sort to xyzw sequence + for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) { - prop = parseSwizzleAndSort( prop.slice( 4 ).toLowerCase() ); + morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1; - return () => nodeObject( new FlipNode( nodeObject( node ), prop ) ); + } - } else if ( prop === 'width' || prop === 'height' || prop === 'depth' ) { + } - // accessing property + } - if ( prop === 'width' ) prop = 'x'; - else if ( prop === 'height' ) prop = 'y'; - else if ( prop === 'depth' ) prop = 'z'; + // create a track for each morph target with all zero + // morphTargetInfluences except for the keys in which + // the morphTarget is named. + for ( const morphTargetName in morphTargetNames ) { - return nodeObject( new SplitNode( node, prop ) ); + const times = []; + const values = []; - } else if ( /^\d+$/.test( prop ) === true ) { + for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) { - // accessing array + const animationKey = animationKeys[ k ]; - return nodeObject( new ArrayElementNode( nodeObj, new ConstNode( Number( prop ), 'uint' ) ) ); + times.push( animationKey.time ); + values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 ); - } + } - } + tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) ); - return Reflect.get( node, prop, nodeObj ); + } - }, + duration = morphTargetNames.length * fps; - set( node, prop, value, nodeObj ) { + } else { - if ( typeof prop === 'string' && node[ prop ] === undefined ) { + // ...assume skeletal animation - // setting properties + const boneName = '.bones[' + bones[ h ].name + ']'; - if ( /^[xyzwrgbastpq]{1,4}$/.test( prop ) === true || prop === 'width' || prop === 'height' || prop === 'depth' || /^\d+$/.test( prop ) === true ) { + addNonemptyTrack( + VectorKeyframeTrack, boneName + '.position', + animationKeys, 'pos', tracks ); - nodeObj[ prop ].assign( value ); + addNonemptyTrack( + QuaternionKeyframeTrack, boneName + '.quaternion', + animationKeys, 'rot', tracks ); - return true; + addNonemptyTrack( + VectorKeyframeTrack, boneName + '.scale', + animationKeys, 'scl', tracks ); } } - return Reflect.set( node, prop, value, nodeObj ); + if ( tracks.length === 0 ) { - } + return null; -}; + } -const nodeObjectsCacheMap = new WeakMap(); -const nodeBuilderFunctionsCacheMap = new WeakMap(); + const clip = new this( clipName, duration, tracks, blendMode ); -const ShaderNodeObject = function ( obj, altType = null ) { + return clip; - const type = getValueType( obj ); + } - if ( type === 'node' ) { + resetDuration() { - let nodeObject = nodeObjectsCacheMap.get( obj ); + const tracks = this.tracks; + let duration = 0; - if ( nodeObject === undefined ) { + for ( let i = 0, n = tracks.length; i !== n; ++ i ) { - nodeObject = new Proxy( obj, shaderNodeHandler ); + const track = this.tracks[ i ]; - nodeObjectsCacheMap.set( obj, nodeObject ); - nodeObjectsCacheMap.set( nodeObject, nodeObject ); + duration = Math.max( duration, track.times[ track.times.length - 1 ] ); } - return nodeObject; - - } else if ( ( altType === null && ( type === 'float' || type === 'boolean' ) ) || ( type && type !== 'shader' && type !== 'string' ) ) { - - return nodeObject( getConstNode( obj, altType ) ); - - } else if ( type === 'shader' ) { + this.duration = duration; - return Fn( obj ); + return this; } - return obj; + trim() { -}; + for ( let i = 0; i < this.tracks.length; i ++ ) { -const ShaderNodeObjects = function ( objects, altType = null ) { + this.tracks[ i ].trim( 0, this.duration ); - for ( const name in objects ) { + } - objects[ name ] = nodeObject( objects[ name ], altType ); + return this; } - return objects; + validate() { -}; + let valid = true; -const ShaderNodeArray = function ( array, altType = null ) { + for ( let i = 0; i < this.tracks.length; i ++ ) { - const len = array.length; + valid = valid && this.tracks[ i ].validate(); - for ( let i = 0; i < len; i ++ ) { + } - array[ i ] = nodeObject( array[ i ], altType ); + return valid; } - return array; + optimize() { -}; + for ( let i = 0; i < this.tracks.length; i ++ ) { -const ShaderNodeProxy = function ( NodeClass, scope = null, factor = null, settings = null ) { + this.tracks[ i ].optimize(); - const assignNode = ( node ) => nodeObject( settings !== null ? Object.assign( node, settings ) : node ); + } - if ( scope === null ) { + return this; - return ( ...params ) => { + } - return assignNode( new NodeClass( ...nodeArray( params ) ) ); + clone() { - }; + const tracks = []; - } else if ( factor !== null ) { + for ( let i = 0; i < this.tracks.length; i ++ ) { - factor = nodeObject( factor ); + tracks.push( this.tracks[ i ].clone() ); - return ( ...params ) => { + } - return assignNode( new NodeClass( scope, ...nodeArray( params ), factor ) ); + return new this.constructor( this.name, this.duration, tracks, this.blendMode ); - }; + } - } else { + toJSON() { - return ( ...params ) => { + return this.constructor.toJSON( this ); - return assignNode( new NodeClass( scope, ...nodeArray( params ) ) ); + } - }; +} - } +function getTrackTypeForValueTypeName( typeName ) { -}; + switch ( typeName.toLowerCase() ) { -const ShaderNodeImmutable = function ( NodeClass, ...params ) { + case 'scalar': + case 'double': + case 'float': + case 'number': + case 'integer': - return nodeObject( new NodeClass( ...nodeArray( params ) ) ); + return NumberKeyframeTrack; -}; + case 'vector': + case 'vector2': + case 'vector3': + case 'vector4': -class ShaderCallNodeInternal extends Node { + return VectorKeyframeTrack; - constructor( shaderNode, inputNodes ) { + case 'color': - super(); + return ColorKeyframeTrack; - this.shaderNode = shaderNode; - this.inputNodes = inputNodes; + case 'quaternion': - } + return QuaternionKeyframeTrack; - getNodeType( builder ) { + case 'bool': + case 'boolean': - return this.shaderNode.nodeType || this.getOutputNode( builder ).getNodeType( builder ); + return BooleanKeyframeTrack; - } + case 'string': - call( builder ) { + return StringKeyframeTrack; - const { shaderNode, inputNodes } = this; + } - const properties = builder.getNodeProperties( shaderNode ); - if ( properties.onceOutput ) return properties.onceOutput; + throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName ); - // +} - let result = null; +function parseKeyframeTrack( json ) { - if ( shaderNode.layout ) { + if ( json.type === undefined ) { - let functionNodesCacheMap = nodeBuilderFunctionsCacheMap.get( builder.constructor ); + throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' ); - if ( functionNodesCacheMap === undefined ) { + } - functionNodesCacheMap = new WeakMap(); + const trackType = getTrackTypeForValueTypeName( json.type ); - nodeBuilderFunctionsCacheMap.set( builder.constructor, functionNodesCacheMap ); + if ( json.times === undefined ) { - } + const times = [], values = []; - let functionNode = functionNodesCacheMap.get( shaderNode ); + flattenJSON( json.keys, times, values, 'value' ); - if ( functionNode === undefined ) { + json.times = times; + json.values = values; - functionNode = nodeObject( builder.buildFunctionNode( shaderNode ) ); + } - functionNodesCacheMap.set( shaderNode, functionNode ); + // derived classes can define a static parse method + if ( trackType.parse !== undefined ) { - } + return trackType.parse( json ); - if ( builder.currentFunctionNode !== null ) { + } else { - builder.currentFunctionNode.includes.push( functionNode ); + // by default, we assume a constructor compatible with the base + return new trackType( json.name, json.times, json.values, json.interpolation ); - } + } - result = nodeObject( functionNode.call( inputNodes ) ); +} - } else { +const Cache = { - const jsFunc = shaderNode.jsFunc; - const outputNode = inputNodes !== null ? jsFunc( inputNodes, builder ) : jsFunc( builder ); + enabled: false, - result = nodeObject( outputNode ); + files: {}, - } + add: function ( key, file ) { - if ( shaderNode.once ) { + if ( this.enabled === false ) return; - properties.onceOutput = result; + // console.log( 'THREE.Cache', 'Adding key:', key ); - } + this.files[ key ] = file; - return result; + }, - } + get: function ( key ) { - getOutputNode( builder ) { + if ( this.enabled === false ) return; - const properties = builder.getNodeProperties( this ); + // console.log( 'THREE.Cache', 'Checking key:', key ); - if ( properties.outputNode === null ) { + return this.files[ key ]; - properties.outputNode = this.setupOutput( builder ); + }, - } + remove: function ( key ) { - return properties.outputNode; + delete this.files[ key ]; - } + }, - setup( builder ) { + clear: function () { - return this.getOutputNode( builder ); + this.files = {}; } - setupOutput( builder ) { +}; - builder.addStack(); +class LoadingManager { - builder.stack.outputNode = this.call( builder ); + constructor( onLoad, onProgress, onError ) { - return builder.removeStack(); + const scope = this; - } + let isLoading = false; + let itemsLoaded = 0; + let itemsTotal = 0; + let urlModifier = undefined; + const handlers = []; - generate( builder, output ) { + // Refer to #5689 for the reason why we don't set .onStart + // in the constructor - const outputNode = this.getOutputNode( builder ); + this.onStart = undefined; + this.onLoad = onLoad; + this.onProgress = onProgress; + this.onError = onError; - return outputNode.build( builder, output ); + this.itemStart = function ( url ) { - } + itemsTotal ++; -} + if ( isLoading === false ) { -class ShaderNodeInternal extends Node { + if ( scope.onStart !== undefined ) { - constructor( jsFunc, nodeType ) { + scope.onStart( url, itemsLoaded, itemsTotal ); - super( nodeType ); + } - this.jsFunc = jsFunc; - this.layout = null; + } - this.global = true; + isLoading = true; - this.once = false; + }; - } + this.itemEnd = function ( url ) { - setLayout( layout ) { + itemsLoaded ++; - this.layout = layout; + if ( scope.onProgress !== undefined ) { - return this; + scope.onProgress( url, itemsLoaded, itemsTotal ); - } + } - call( inputs = null ) { + if ( itemsLoaded === itemsTotal ) { - nodeObjects( inputs ); + isLoading = false; - return nodeObject( new ShaderCallNodeInternal( this, inputs ) ); + if ( scope.onLoad !== undefined ) { - } + scope.onLoad(); - setup() { + } - return this.call(); + } - } + }; -} + this.itemError = function ( url ) { -const bools = [ false, true ]; -const uints = [ 0, 1, 2, 3 ]; -const ints = [ - 1, - 2 ]; -const floats = [ 0.5, 1.5, 1 / 3, 1e-6, 1e6, Math.PI, Math.PI * 2, 1 / Math.PI, 2 / Math.PI, 1 / ( Math.PI * 2 ), Math.PI / 2 ]; + if ( scope.onError !== undefined ) { -const boolsCacheMap = new Map(); -for ( const bool of bools ) boolsCacheMap.set( bool, new ConstNode( bool ) ); + scope.onError( url ); -const uintsCacheMap = new Map(); -for ( const uint of uints ) uintsCacheMap.set( uint, new ConstNode( uint, 'uint' ) ); + } -const intsCacheMap = new Map( [ ...uintsCacheMap ].map( el => new ConstNode( el.value, 'int' ) ) ); -for ( const int of ints ) intsCacheMap.set( int, new ConstNode( int, 'int' ) ); + }; -const floatsCacheMap = new Map( [ ...intsCacheMap ].map( el => new ConstNode( el.value ) ) ); -for ( const float of floats ) floatsCacheMap.set( float, new ConstNode( float ) ); -for ( const float of floats ) floatsCacheMap.set( - float, new ConstNode( - float ) ); + this.resolveURL = function ( url ) { -const cacheMaps = { bool: boolsCacheMap, uint: uintsCacheMap, ints: intsCacheMap, float: floatsCacheMap }; + if ( urlModifier ) { -const constNodesCacheMap = new Map( [ ...boolsCacheMap, ...floatsCacheMap ] ); + return urlModifier( url ); -const getConstNode = ( value, type ) => { + } - if ( constNodesCacheMap.has( value ) ) { + return url; - return constNodesCacheMap.get( value ); + }; - } else if ( value.isNode === true ) { + this.setURLModifier = function ( transform ) { - return value; + urlModifier = transform; - } else { + return this; - return new ConstNode( value, type ); + }; - } + this.addHandler = function ( regex, loader ) { -}; + handlers.push( regex, loader ); -const safeGetNodeType = ( node ) => { + return this; - try { + }; - return node.getNodeType(); + this.removeHandler = function ( regex ) { - } catch ( _ ) { + const index = handlers.indexOf( regex ); - return undefined; + if ( index !== - 1 ) { - } + handlers.splice( index, 2 ); -}; + } -const ConvertType = function ( type, cacheMap = null ) { + return this; - return ( ...params ) => { + }; - if ( params.length === 0 || ( ! [ 'bool', 'float', 'int', 'uint' ].includes( type ) && params.every( param => typeof param !== 'object' ) ) ) { + this.getHandler = function ( file ) { - params = [ getValueFromType( type, ...params ) ]; + for ( let i = 0, l = handlers.length; i < l; i += 2 ) { - } + const regex = handlers[ i ]; + const loader = handlers[ i + 1 ]; - if ( params.length === 1 && cacheMap !== null && cacheMap.has( params[ 0 ] ) ) { + if ( regex.global ) regex.lastIndex = 0; // see #17920 - return nodeObject( cacheMap.get( params[ 0 ] ) ); + if ( regex.test( file ) ) { - } + return loader; - if ( params.length === 1 ) { + } - const node = getConstNode( params[ 0 ], type ); - if ( safeGetNodeType( node ) === type ) return nodeObject( node ); - return nodeObject( new ConvertNode( node, type ) ); + } - } + return null; - const nodes = params.map( param => getConstNode( param ) ); - return nodeObject( new JoinNode( nodes, type ) ); + }; - }; + } -}; +} -// exports +const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager(); -const defined = ( v ) => typeof v === 'object' && v !== null ? v.value : v; // TODO: remove boolean conversion and defined function +class Loader { -// utils + constructor( manager ) { -const getConstNodeType = ( value ) => ( value !== undefined && value !== null ) ? ( value.nodeType || value.convertTo || ( typeof value === 'string' ? value : null ) ) : null; + this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; -// shader node base + this.crossOrigin = 'anonymous'; + this.withCredentials = false; + this.path = ''; + this.resourcePath = ''; + this.requestHeader = {}; -function ShaderNode( jsFunc, nodeType ) { + } - return new Proxy( new ShaderNodeInternal( jsFunc, nodeType ), shaderNodeHandler ); + load( /* url, onLoad, onProgress, onError */ ) {} -} + loadAsync( url, onProgress ) { -const nodeObject = ( val, altType = null ) => /* new */ ShaderNodeObject( val, altType ); -const nodeObjects = ( val, altType = null ) => new ShaderNodeObjects( val, altType ); -const nodeArray = ( val, altType = null ) => new ShaderNodeArray( val, altType ); -const nodeProxy = ( ...params ) => new ShaderNodeProxy( ...params ); -const nodeImmutable = ( ...params ) => new ShaderNodeImmutable( ...params ); + const scope = this; -const Fn = ( jsFunc, nodeType ) => { + return new Promise( function ( resolve, reject ) { - const shaderNode = new ShaderNode( jsFunc, nodeType ); + scope.load( url, resolve, onProgress, reject ); - const fn = ( ...params ) => { + } ); - let inputs; + } - nodeObjects( params ); + parse( /* data */ ) {} - if ( params[ 0 ] && params[ 0 ].isNode ) { + setCrossOrigin( crossOrigin ) { - inputs = [ ...params ]; + this.crossOrigin = crossOrigin; + return this; - } else { + } - inputs = params[ 0 ]; + setWithCredentials( value ) { - } + this.withCredentials = value; + return this; - return shaderNode.call( inputs ); + } - }; + setPath( path ) { - fn.shaderNode = shaderNode; + this.path = path; + return this; - fn.setLayout = ( layout ) => { + } - shaderNode.setLayout( layout ); + setResourcePath( resourcePath ) { - return fn; + this.resourcePath = resourcePath; + return this; - }; + } - fn.once = () => { + setRequestHeader( requestHeader ) { - shaderNode.once = true; + this.requestHeader = requestHeader; + return this; - return fn; + } - }; +} - return fn; +Loader.DEFAULT_MATERIAL_NAME = '__DEFAULT'; -}; +const loading = {}; -const tslFn = ( ...params ) => { // @deprecated, r168 +class HttpError extends Error { - console.warn( 'TSL.ShaderNode: tslFn() has been renamed to Fn().' ); - return Fn( ...params ); + constructor( message, response ) { -}; + super( message ); + this.response = response; -// + } -addMethodChaining( 'toGlobal', ( node ) => { +} - node.global = true; +class FileLoader extends Loader { - return node; + constructor( manager ) { -} ); + super( manager ); -// + } -const setCurrentStack = ( stack ) => { + load( url, onLoad, onProgress, onError ) { - currentStack = stack; + if ( url === undefined ) url = ''; -}; + if ( this.path !== undefined ) url = this.path + url; -const getCurrentStack = () => currentStack; + url = this.manager.resolveURL( url ); -const If = ( ...params ) => currentStack.If( ...params ); + const cached = Cache.get( url ); -function append( node ) { + if ( cached !== undefined ) { - if ( currentStack ) currentStack.add( node ); + this.manager.itemStart( url ); - return node; + setTimeout( () => { -} + if ( onLoad ) onLoad( cached ); -addMethodChaining( 'append', append ); + this.manager.itemEnd( url ); -// types + }, 0 ); -const color = new ConvertType( 'color' ); + return cached; -const float = new ConvertType( 'float', cacheMaps.float ); -const int = new ConvertType( 'int', cacheMaps.ints ); -const uint = new ConvertType( 'uint', cacheMaps.uint ); -const bool = new ConvertType( 'bool', cacheMaps.bool ); + } -const vec2 = new ConvertType( 'vec2' ); -const ivec2 = new ConvertType( 'ivec2' ); -const uvec2 = new ConvertType( 'uvec2' ); -const bvec2 = new ConvertType( 'bvec2' ); + // Check if request is duplicate -const vec3 = new ConvertType( 'vec3' ); -const ivec3 = new ConvertType( 'ivec3' ); -const uvec3 = new ConvertType( 'uvec3' ); -const bvec3 = new ConvertType( 'bvec3' ); + if ( loading[ url ] !== undefined ) { -const vec4 = new ConvertType( 'vec4' ); -const ivec4 = new ConvertType( 'ivec4' ); -const uvec4 = new ConvertType( 'uvec4' ); -const bvec4 = new ConvertType( 'bvec4' ); + loading[ url ].push( { -const mat2 = new ConvertType( 'mat2' ); -const mat3 = new ConvertType( 'mat3' ); -const mat4 = new ConvertType( 'mat4' ); + onLoad: onLoad, + onProgress: onProgress, + onError: onError -const string = ( value = '' ) => nodeObject( new ConstNode( value, 'string' ) ); -const arrayBuffer = ( value ) => nodeObject( new ConstNode( value, 'ArrayBuffer' ) ); + } ); -addMethodChaining( 'toColor', color ); -addMethodChaining( 'toFloat', float ); -addMethodChaining( 'toInt', int ); -addMethodChaining( 'toUint', uint ); -addMethodChaining( 'toBool', bool ); -addMethodChaining( 'toVec2', vec2 ); -addMethodChaining( 'toIVec2', ivec2 ); -addMethodChaining( 'toUVec2', uvec2 ); -addMethodChaining( 'toBVec2', bvec2 ); -addMethodChaining( 'toVec3', vec3 ); -addMethodChaining( 'toIVec3', ivec3 ); -addMethodChaining( 'toUVec3', uvec3 ); -addMethodChaining( 'toBVec3', bvec3 ); -addMethodChaining( 'toVec4', vec4 ); -addMethodChaining( 'toIVec4', ivec4 ); -addMethodChaining( 'toUVec4', uvec4 ); -addMethodChaining( 'toBVec4', bvec4 ); -addMethodChaining( 'toMat2', mat2 ); -addMethodChaining( 'toMat3', mat3 ); -addMethodChaining( 'toMat4', mat4 ); + return; -// basic nodes + } -const element = /*@__PURE__*/ nodeProxy( ArrayElementNode ); -const convert = ( node, types ) => nodeObject( new ConvertNode( nodeObject( node ), types ) ); -const split = ( node, channels ) => nodeObject( new SplitNode( nodeObject( node ), channels ) ); + // Initialise array for duplicate requests + loading[ url ] = []; -addMethodChaining( 'element', element ); -addMethodChaining( 'convert', convert ); + loading[ url ].push( { + onLoad: onLoad, + onProgress: onProgress, + onError: onError, + } ); -class UniformGroupNode extends Node { + // create request + const req = new Request( url, { + headers: new Headers( this.requestHeader ), + credentials: this.withCredentials ? 'include' : 'same-origin', + // An abort controller could be added within a future PR + } ); - constructor( name, shared = false ) { + // record states ( avoid data race ) + const mimeType = this.mimeType; + const responseType = this.responseType; - super( 'string' ); + // start the fetch + fetch( req ) + .then( response => { - this.name = name; - this.version = 0; + if ( response.status === 200 || response.status === 0 ) { - this.shared = shared; + // Some browsers return HTTP Status 0 when using non-http protocol + // e.g. 'file://' or 'data://'. Handle as success. - this.isUniformGroup = true; + if ( response.status === 0 ) { - } + console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); - set needsUpdate( value ) { + } - if ( value === true ) this.version ++; + // Workaround: Checking if response.body === undefined for Alipay browser #23548 - } + if ( typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined ) { - serialize( data ) { + return response; - super.serialize( data ); + } - data.name = this.name; - data.version = this.version; - data.shared = this.shared; + const callbacks = loading[ url ]; + const reader = response.body.getReader(); - } + // Nginx needs X-File-Size check + // https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content + const contentLength = response.headers.get( 'X-File-Size' ) || response.headers.get( 'Content-Length' ); + const total = contentLength ? parseInt( contentLength ) : 0; + const lengthComputable = total !== 0; + let loaded = 0; - deserialize( data ) { + // periodically read data into the new stream tracking while download progress + const stream = new ReadableStream( { + start( controller ) { - super.deserialize( data ); + readData(); - this.name = data.name; - this.version = data.version; - this.shared = data.shared; + function readData() { - } + reader.read().then( ( { done, value } ) => { -} + if ( done ) { -UniformGroupNode.type = /*@__PURE__*/ registerNode( 'UniformGroup', UniformGroupNode ); + controller.close(); -const uniformGroup = ( name ) => new UniformGroupNode( name ); -const sharedUniformGroup = ( name ) => new UniformGroupNode( name, true ); + } else { -const frameGroup = /*@__PURE__*/ sharedUniformGroup( 'frame' ); -const renderGroup = /*@__PURE__*/ sharedUniformGroup( 'render' ); -const objectGroup = /*@__PURE__*/ uniformGroup( 'object' ); + loaded += value.byteLength; -class UniformNode extends InputNode { + const event = new ProgressEvent( 'progress', { lengthComputable, loaded, total } ); + for ( let i = 0, il = callbacks.length; i < il; i ++ ) { - constructor( value, nodeType = null ) { + const callback = callbacks[ i ]; + if ( callback.onProgress ) callback.onProgress( event ); - super( value, nodeType ); + } - this.isUniformNode = true; + controller.enqueue( value ); + readData(); - this.name = ''; - this.groupNode = objectGroup; + } - } + }, ( e ) => { - label( name ) { + controller.error( e ); - this.name = name; + } ); - return this; + } - } + } - setGroup( group ) { + } ); - this.groupNode = group; + return new Response( stream ); - return this; + } else { - } + throw new HttpError( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response ); - getGroup() { + } - return this.groupNode; + } ) + .then( response => { - } + switch ( responseType ) { - getUniformHash( builder ) { + case 'arraybuffer': - return this.getHash( builder ); + return response.arrayBuffer(); - } + case 'blob': - onUpdate( callback, updateType ) { + return response.blob(); - const self = this.getSelf(); + case 'document': - callback = callback.bind( self ); + return response.text() + .then( text => { - return super.onUpdate( ( frame ) => { + const parser = new DOMParser(); + return parser.parseFromString( text, mimeType ); - const value = callback( frame, self ); + } ); - if ( value !== undefined ) { + case 'json': - this.value = value; + return response.json(); - } + default: - }, updateType ); + if ( mimeType === undefined ) { - } + return response.text(); - generate( builder, output ) { + } else { - const type = this.getNodeType( builder ); + // sniff encoding + const re = /charset="?([^;"\s]*)"?/i; + const exec = re.exec( mimeType ); + const label = exec && exec[ 1 ] ? exec[ 1 ].toLowerCase() : undefined; + const decoder = new TextDecoder( label ); + return response.arrayBuffer().then( ab => decoder.decode( ab ) ); - const hash = this.getUniformHash( builder ); + } - let sharedNode = builder.getNodeFromHash( hash ); + } - if ( sharedNode === undefined ) { + } ) + .then( data => { - builder.setHashNode( this, hash ); + // Add to cache only on HTTP success, so that we do not cache + // error response bodies as proper responses to requests. + Cache.add( url, data ); - sharedNode = this; + const callbacks = loading[ url ]; + delete loading[ url ]; - } + for ( let i = 0, il = callbacks.length; i < il; i ++ ) { - const sharedNodeType = sharedNode.getInputType( builder ); + const callback = callbacks[ i ]; + if ( callback.onLoad ) callback.onLoad( data ); - const nodeUniform = builder.getUniformFromNode( sharedNode, sharedNodeType, builder.shaderStage, this.name || builder.context.label ); - const propertyName = builder.getPropertyName( nodeUniform ); + } - if ( builder.context.label !== undefined ) delete builder.context.label; + } ) + .catch( err => { - return builder.format( propertyName, type, output ); + // Abort errors and other errors are handled the same - } + const callbacks = loading[ url ]; -} + if ( callbacks === undefined ) { -UniformNode.type = /*@__PURE__*/ registerNode( 'Uniform', UniformNode ); + // When onLoad was called and url was deleted in `loading` + this.manager.itemError( url ); + throw err; -const uniform = ( arg1, arg2 ) => { + } - const nodeType = getConstNodeType( arg2 || arg1 ); + delete loading[ url ]; - // @TODO: get ConstNode from .traverse() in the future - const value = ( arg1 && arg1.isNode === true ) ? ( arg1.node && arg1.node.value ) || arg1.value : arg1; + for ( let i = 0, il = callbacks.length; i < il; i ++ ) { - return nodeObject( new UniformNode( value, nodeType ) ); + const callback = callbacks[ i ]; + if ( callback.onError ) callback.onError( err ); -}; + } -class PropertyNode extends Node { + this.manager.itemError( url ); - constructor( nodeType, name = null, varying = false ) { + } ) + .finally( () => { - super( nodeType ); + this.manager.itemEnd( url ); - this.name = name; - this.varying = varying; + } ); - this.isPropertyNode = true; + this.manager.itemStart( url ); } - getHash( builder ) { + setResponseType( value ) { - return this.name || super.getHash( builder ); + this.responseType = value; + return this; } - isGlobal( /*builder*/ ) { + setMimeType( value ) { - return true; + this.mimeType = value; + return this; } - generate( builder ) { - - let nodeVar; - - if ( this.varying === true ) { - - nodeVar = builder.getVaryingFromNode( this, this.name ); - nodeVar.needsInterpolation = true; - - } else { +} - nodeVar = builder.getVarFromNode( this, this.name ); +class AnimationLoader extends Loader { - } + constructor( manager ) { - return builder.getPropertyName( nodeVar ); + super( manager ); } -} + load( url, onLoad, onProgress, onError ) { -PropertyNode.type = /*@__PURE__*/ registerNode( 'Property', PropertyNode ); + const scope = this; -const property = ( type, name ) => nodeObject( new PropertyNode( type, name ) ); -const varyingProperty = ( type, name ) => nodeObject( new PropertyNode( type, name, true ) ); + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + loader.load( url, function ( text ) { -const diffuseColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec4', 'DiffuseColor' ); -const emissive = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'EmissiveColor' ); -const roughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Roughness' ); -const metalness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Metalness' ); -const clearcoat = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Clearcoat' ); -const clearcoatRoughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'ClearcoatRoughness' ); -const sheen = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'Sheen' ); -const sheenRoughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'SheenRoughness' ); -const iridescence = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Iridescence' ); -const iridescenceIOR = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IridescenceIOR' ); -const iridescenceThickness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IridescenceThickness' ); -const alphaT = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'AlphaT' ); -const anisotropy = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Anisotropy' ); -const anisotropyT = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'AnisotropyT' ); -const anisotropyB = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'AnisotropyB' ); -const specularColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'color', 'SpecularColor' ); -const specularF90 = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'SpecularF90' ); -const shininess = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Shininess' ); -const output = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec4', 'Output' ); -const dashSize = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'dashSize' ); -const gapSize = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'gapSize' ); -const pointWidth = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'pointWidth' ); -const ior = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IOR' ); -const transmission = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Transmission' ); -const thickness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Thickness' ); -const attenuationDistance = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'AttenuationDistance' ); -const attenuationColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'color', 'AttenuationColor' ); -const dispersion = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Dispersion' ); + try { -class AssignNode extends TempNode { + onLoad( scope.parse( JSON.parse( text ) ) ); - constructor( targetNode, sourceNode ) { + } catch ( e ) { - super(); + if ( onError ) { - this.targetNode = targetNode; - this.sourceNode = sourceNode; + onError( e ); - } + } else { - hasDependencies() { + console.error( e ); - return false; + } - } + scope.manager.itemError( url ); - getNodeType( builder, output ) { + } - return output !== 'void' ? this.targetNode.getNodeType( builder ) : 'void'; + }, onProgress, onError ); } - needsSplitAssign( builder ) { + parse( json ) { - const { targetNode } = this; + const animations = []; - if ( builder.isAvailable( 'swizzleAssign' ) === false && targetNode.isSplitNode && targetNode.components.length > 1 ) { + for ( let i = 0; i < json.length; i ++ ) { - const targetLength = builder.getTypeLength( targetNode.node.getNodeType( builder ) ); - const assignDiferentVector = vectorComponents.join( '' ).slice( 0, targetLength ) !== targetNode.components; + const clip = AnimationClip.parse( json[ i ] ); - return assignDiferentVector; + animations.push( clip ); } - return false; + return animations; } - generate( builder, output ) { - - const { targetNode, sourceNode } = this; - - const needsSplitAssign = this.needsSplitAssign( builder ); +} - const targetType = targetNode.getNodeType( builder ); +/** + * Abstract Base class to block based textures loader (dds, pvr, ...) + * + * Sub classes have to implement the parse() method which will be used in load(). + */ - const target = targetNode.context( { assign: true } ).build( builder ); - const source = sourceNode.build( builder, targetType ); +class CompressedTextureLoader extends Loader { - const sourceType = sourceNode.getNodeType( builder ); + constructor( manager ) { - const nodeData = builder.getDataFromNode( this ); + super( manager ); - // + } - let snippet; + load( url, onLoad, onProgress, onError ) { - if ( nodeData.initialized === true ) { + const scope = this; - if ( output !== 'void' ) { + const images = []; - snippet = target; + const texture = new CompressedTexture(); - } + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setResponseType( 'arraybuffer' ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( scope.withCredentials ); - } else if ( needsSplitAssign ) { + let loaded = 0; - const sourceVar = builder.getVarFromNode( this, null, targetType ); - const sourceProperty = builder.getPropertyName( sourceVar ); + function loadTexture( i ) { - builder.addLineFlowCode( `${ sourceProperty } = ${ source }` ); + loader.load( url[ i ], function ( buffer ) { - const targetRoot = targetNode.node.context( { assign: true } ).build( builder ); + const texDatas = scope.parse( buffer, true ); - for ( let i = 0; i < targetNode.components.length; i ++ ) { + images[ i ] = { + width: texDatas.width, + height: texDatas.height, + format: texDatas.format, + mipmaps: texDatas.mipmaps + }; - const component = targetNode.components[ i ]; + loaded += 1; - builder.addLineFlowCode( `${ targetRoot }.${ component } = ${ sourceProperty }[ ${ i } ]` ); + if ( loaded === 6 ) { - } + if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter; - if ( output !== 'void' ) { + texture.image = images; + texture.format = texDatas.format; + texture.needsUpdate = true; - snippet = target; + if ( onLoad ) onLoad( texture ); - } + } - } else { + }, onProgress, onError ); - snippet = `${ target } = ${ source }`; + } - if ( output === 'void' || sourceType === 'void' ) { + if ( Array.isArray( url ) ) { - builder.addLineFlowCode( snippet ); + for ( let i = 0, il = url.length; i < il; ++ i ) { - if ( output !== 'void' ) { + loadTexture( i ); - snippet = target; + } - } + } else { - } + // compressed cubemap texture stored in a single DDS file - } + loader.load( url, function ( buffer ) { - nodeData.initialized = true; + const texDatas = scope.parse( buffer, true ); - return builder.format( snippet, targetType, output ); + if ( texDatas.isCubemap ) { - } + const faces = texDatas.mipmaps.length / texDatas.mipmapCount; -} + for ( let f = 0; f < faces; f ++ ) { -AssignNode.type = /*@__PURE__*/ registerNode( 'Assign', AssignNode ); + images[ f ] = { mipmaps: [] }; -const assign = /*@__PURE__*/ nodeProxy( AssignNode ); + for ( let i = 0; i < texDatas.mipmapCount; i ++ ) { -addMethodChaining( 'assign', assign ); + images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] ); + images[ f ].format = texDatas.format; + images[ f ].width = texDatas.width; + images[ f ].height = texDatas.height; -class FunctionCallNode extends TempNode { + } - constructor( functionNode = null, parameters = {} ) { + } - super(); + texture.image = images; - this.functionNode = functionNode; - this.parameters = parameters; + } else { - } + texture.image.width = texDatas.width; + texture.image.height = texDatas.height; + texture.mipmaps = texDatas.mipmaps; - setParameters( parameters ) { + } - this.parameters = parameters; + if ( texDatas.mipmapCount === 1 ) { - return this; + texture.minFilter = LinearFilter; - } + } - getParameters() { + texture.format = texDatas.format; + texture.needsUpdate = true; - return this.parameters; + if ( onLoad ) onLoad( texture ); - } + }, onProgress, onError ); - getNodeType( builder ) { + } - return this.functionNode.getNodeType( builder ); + return texture; } - generate( builder ) { - - const params = []; +} - const functionNode = this.functionNode; +class ImageLoader extends Loader { - const inputs = functionNode.getInputs( builder ); - const parameters = this.parameters; + constructor( manager ) { - if ( Array.isArray( parameters ) ) { + super( manager ); - for ( let i = 0; i < parameters.length; i ++ ) { + } - const inputNode = inputs[ i ]; - const node = parameters[ i ]; + load( url, onLoad, onProgress, onError ) { - params.push( node.build( builder, inputNode.type ) ); + if ( this.path !== undefined ) url = this.path + url; - } + url = this.manager.resolveURL( url ); - } else { + const scope = this; - for ( const inputNode of inputs ) { + const cached = Cache.get( url ); - const node = parameters[ inputNode.name ]; + if ( cached !== undefined ) { - if ( node !== undefined ) { + scope.manager.itemStart( url ); - params.push( node.build( builder, inputNode.type ) ); + setTimeout( function () { - } else { + if ( onLoad ) onLoad( cached ); - throw new Error( `FunctionCallNode: Input '${inputNode.name}' not found in FunctionNode.` ); + scope.manager.itemEnd( url ); - } + }, 0 ); - } + return cached; } - const functionName = functionNode.build( builder, 'property' ); - - return `${functionName}( ${params.join( ', ' )} )`; + const image = createElementNS( 'img' ); - } + function onImageLoad() { -} + removeEventListeners(); -FunctionCallNode.type = /*@__PURE__*/ registerNode( 'FunctionCall', FunctionCallNode ); + Cache.add( url, this ); -const call = ( func, ...params ) => { + if ( onLoad ) onLoad( this ); - params = params.length > 1 || ( params[ 0 ] && params[ 0 ].isNode === true ) ? nodeArray( params ) : nodeObjects( params[ 0 ] ); + scope.manager.itemEnd( url ); - return nodeObject( new FunctionCallNode( nodeObject( func ), params ) ); + } -}; + function onImageError( event ) { -addMethodChaining( 'call', call ); + removeEventListeners(); -class OperatorNode extends TempNode { + if ( onError ) onError( event ); - constructor( op, aNode, bNode, ...params ) { + scope.manager.itemError( url ); + scope.manager.itemEnd( url ); - super(); + } - if ( params.length > 0 ) { + function removeEventListeners() { - let finalOp = new OperatorNode( op, aNode, bNode ); + image.removeEventListener( 'load', onImageLoad, false ); + image.removeEventListener( 'error', onImageError, false ); - for ( let i = 0; i < params.length - 1; i ++ ) { + } - finalOp = new OperatorNode( op, finalOp, params[ i ] ); + image.addEventListener( 'load', onImageLoad, false ); + image.addEventListener( 'error', onImageError, false ); - } + if ( url.slice( 0, 5 ) !== 'data:' ) { - aNode = finalOp; - bNode = params[ params.length - 1 ]; + if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin; } - this.op = op; - this.aNode = aNode; - this.bNode = bNode; + scope.manager.itemStart( url ); - } + image.src = url; - getNodeType( builder, output ) { + return image; - const op = this.op; + } - const aNode = this.aNode; - const bNode = this.bNode; +} - const typeA = aNode.getNodeType( builder ); - const typeB = typeof bNode !== 'undefined' ? bNode.getNodeType( builder ) : null; +class CubeTextureLoader extends Loader { - if ( typeA === 'void' || typeB === 'void' ) { + constructor( manager ) { - return 'void'; + super( manager ); - } else if ( op === '%' ) { + } - return typeA; + load( urls, onLoad, onProgress, onError ) { - } else if ( op === '~' || op === '&' || op === '|' || op === '^' || op === '>>' || op === '<<' ) { + const texture = new CubeTexture(); + texture.colorSpace = SRGBColorSpace; - return builder.getIntegerType( typeA ); + const loader = new ImageLoader( this.manager ); + loader.setCrossOrigin( this.crossOrigin ); + loader.setPath( this.path ); - } else if ( op === '!' || op === '==' || op === '&&' || op === '||' || op === '^^' ) { + let loaded = 0; - return 'bool'; + function loadTexture( i ) { - } else if ( op === '<' || op === '>' || op === '<=' || op === '>=' ) { + loader.load( urls[ i ], function ( image ) { - const typeLength = output ? builder.getTypeLength( output ) : Math.max( builder.getTypeLength( typeA ), builder.getTypeLength( typeB ) ); + texture.images[ i ] = image; - return typeLength > 1 ? `bvec${ typeLength }` : 'bool'; + loaded ++; - } else { + if ( loaded === 6 ) { - if ( typeA === 'float' && builder.isMatrix( typeB ) ) { + texture.needsUpdate = true; - return typeB; + if ( onLoad ) onLoad( texture ); - } else if ( builder.isMatrix( typeA ) && builder.isVector( typeB ) ) { + } - // matrix x vector + }, undefined, onError ); - return builder.getVectorFromMatrix( typeA ); + } - } else if ( builder.isVector( typeA ) && builder.isMatrix( typeB ) ) { + for ( let i = 0; i < urls.length; ++ i ) { - // vector x matrix + loadTexture( i ); - return builder.getVectorFromMatrix( typeB ); + } - } else if ( builder.getTypeLength( typeB ) > builder.getTypeLength( typeA ) ) { + return texture; - // anytype x anytype: use the greater length vector + } - return typeB; +} - } +/** + * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...) + * + * Sub classes have to implement the parse() method which will be used in load(). + */ - return typeA; +class DataTextureLoader extends Loader { - } + constructor( manager ) { + + super( manager ); } - generate( builder, output ) { + load( url, onLoad, onProgress, onError ) { - const op = this.op; + const scope = this; - const aNode = this.aNode; - const bNode = this.bNode; + const texture = new DataTexture(); - const type = this.getNodeType( builder, output ); + const loader = new FileLoader( this.manager ); + loader.setResponseType( 'arraybuffer' ); + loader.setRequestHeader( this.requestHeader ); + loader.setPath( this.path ); + loader.setWithCredentials( scope.withCredentials ); + loader.load( url, function ( buffer ) { - let typeA = null; - let typeB = null; + let texData; - if ( type !== 'void' ) { + try { - typeA = aNode.getNodeType( builder ); - typeB = typeof bNode !== 'undefined' ? bNode.getNodeType( builder ) : null; + texData = scope.parse( buffer ); - if ( op === '<' || op === '>' || op === '<=' || op === '>=' || op === '==' ) { + } catch ( error ) { - if ( builder.isVector( typeA ) ) { + if ( onError !== undefined ) { - typeB = typeA; + onError( error ); - } else if ( typeA !== typeB ) { + } else { - typeA = typeB = 'float'; + console.error( error ); + return; } - } else if ( op === '>>' || op === '<<' ) { + } - typeA = type; - typeB = builder.changeComponentType( typeB, 'uint' ); + if ( texData.image !== undefined ) { - } else if ( builder.isMatrix( typeA ) && builder.isVector( typeB ) ) { + texture.image = texData.image; - // matrix x vector + } else if ( texData.data !== undefined ) { - typeB = builder.getVectorFromMatrix( typeA ); + texture.image.width = texData.width; + texture.image.height = texData.height; + texture.image.data = texData.data; - } else if ( builder.isVector( typeA ) && builder.isMatrix( typeB ) ) { + } - // vector x matrix + texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping; + texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping; - typeA = builder.getVectorFromMatrix( typeB ); + texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter; + texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter; - } else { + texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1; - // anytype x anytype + if ( texData.colorSpace !== undefined ) { - typeA = typeB = type; + texture.colorSpace = texData.colorSpace; } - } else { + if ( texData.flipY !== undefined ) { - typeA = typeB = type; + texture.flipY = texData.flipY; - } + } - const a = aNode.build( builder, typeA ); - const b = typeof bNode !== 'undefined' ? bNode.build( builder, typeB ) : null; + if ( texData.format !== undefined ) { - const outputLength = builder.getTypeLength( output ); - const fnOpSnippet = builder.getFunctionOperator( op ); + texture.format = texData.format; - if ( output !== 'void' ) { + } - if ( op === '<' && outputLength > 1 ) { + if ( texData.type !== undefined ) { - if ( builder.useComparisonMethod ) { + texture.type = texData.type; - return builder.format( `${ builder.getMethod( 'lessThan', output ) }( ${ a }, ${ b } )`, type, output ); + } - } else { + if ( texData.mipmaps !== undefined ) { - return builder.format( `( ${ a } < ${ b } )`, type, output ); + texture.mipmaps = texData.mipmaps; + texture.minFilter = LinearMipmapLinearFilter; // presumably... - } + } - } else if ( op === '<=' && outputLength > 1 ) { + if ( texData.mipmapCount === 1 ) { - if ( builder.useComparisonMethod ) { + texture.minFilter = LinearFilter; - return builder.format( `${ builder.getMethod( 'lessThanEqual', output ) }( ${ a }, ${ b } )`, type, output ); + } - } else { + if ( texData.generateMipmaps !== undefined ) { - return builder.format( `( ${ a } <= ${ b } )`, type, output ); + texture.generateMipmaps = texData.generateMipmaps; - } + } - } else if ( op === '>' && outputLength > 1 ) { + texture.needsUpdate = true; - if ( builder.useComparisonMethod ) { + if ( onLoad ) onLoad( texture, texData ); - return builder.format( `${ builder.getMethod( 'greaterThan', output ) }( ${ a }, ${ b } )`, type, output ); + }, onProgress, onError ); - } else { - return builder.format( `( ${ a } > ${ b } )`, type, output ); + return texture; - } + } - } else if ( op === '>=' && outputLength > 1 ) { +} - if ( builder.useComparisonMethod ) { +class TextureLoader extends Loader { - return builder.format( `${ builder.getMethod( 'greaterThanEqual', output ) }( ${ a }, ${ b } )`, type, output ); + constructor( manager ) { - } else { + super( manager ); - return builder.format( `( ${ a } >= ${ b } )`, type, output ); + } - } + load( url, onLoad, onProgress, onError ) { - } else if ( op === '!' || op === '~' ) { + const texture = new Texture(); - return builder.format( `(${op}${a})`, typeA, output ); + const loader = new ImageLoader( this.manager ); + loader.setCrossOrigin( this.crossOrigin ); + loader.setPath( this.path ); - } else if ( fnOpSnippet ) { + loader.load( url, function ( image ) { - return builder.format( `${ fnOpSnippet }( ${ a }, ${ b } )`, type, output ); + texture.image = image; + texture.needsUpdate = true; - } else { + if ( onLoad !== undefined ) { - return builder.format( `( ${ a } ${ op } ${ b } )`, type, output ); + onLoad( texture ); } - } else if ( typeA !== 'void' ) { + }, onProgress, onError ); - if ( fnOpSnippet ) { + return texture; - return builder.format( `${ fnOpSnippet }( ${ a }, ${ b } )`, type, output ); + } - } else { +} - return builder.format( `${ a } ${ op } ${ b }`, type, output ); +class Light extends Object3D { - } + constructor( color, intensity = 1 ) { - } + super(); - } + this.isLight = true; - serialize( data ) { + this.type = 'Light'; - super.serialize( data ); - - data.op = this.op; + this.color = new Color( color ); + this.intensity = intensity; } - deserialize( data ) { - - super.deserialize( data ); + dispose() { - this.op = data.op; + // Empty here in base class; some subclasses override. } -} + copy( source, recursive ) { -OperatorNode.type = /*@__PURE__*/ registerNode( 'Operator', OperatorNode ); + super.copy( source, recursive ); -const add = /*@__PURE__*/ nodeProxy( OperatorNode, '+' ); -const sub = /*@__PURE__*/ nodeProxy( OperatorNode, '-' ); -const mul = /*@__PURE__*/ nodeProxy( OperatorNode, '*' ); -const div = /*@__PURE__*/ nodeProxy( OperatorNode, '/' ); -const modInt = /*@__PURE__*/ nodeProxy( OperatorNode, '%' ); -const equal = /*@__PURE__*/ nodeProxy( OperatorNode, '==' ); -const notEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '!=' ); -const lessThan = /*@__PURE__*/ nodeProxy( OperatorNode, '<' ); -const greaterThan = /*@__PURE__*/ nodeProxy( OperatorNode, '>' ); -const lessThanEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '<=' ); -const greaterThanEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '>=' ); -const and = /*@__PURE__*/ nodeProxy( OperatorNode, '&&' ); -const or = /*@__PURE__*/ nodeProxy( OperatorNode, '||' ); -const not = /*@__PURE__*/ nodeProxy( OperatorNode, '!' ); -const xor = /*@__PURE__*/ nodeProxy( OperatorNode, '^^' ); -const bitAnd = /*@__PURE__*/ nodeProxy( OperatorNode, '&' ); -const bitNot = /*@__PURE__*/ nodeProxy( OperatorNode, '~' ); -const bitOr = /*@__PURE__*/ nodeProxy( OperatorNode, '|' ); -const bitXor = /*@__PURE__*/ nodeProxy( OperatorNode, '^' ); -const shiftLeft = /*@__PURE__*/ nodeProxy( OperatorNode, '<<' ); -const shiftRight = /*@__PURE__*/ nodeProxy( OperatorNode, '>>' ); + this.color.copy( source.color ); + this.intensity = source.intensity; -addMethodChaining( 'add', add ); -addMethodChaining( 'sub', sub ); -addMethodChaining( 'mul', mul ); -addMethodChaining( 'div', div ); -addMethodChaining( 'modInt', modInt ); -addMethodChaining( 'equal', equal ); -addMethodChaining( 'notEqual', notEqual ); -addMethodChaining( 'lessThan', lessThan ); -addMethodChaining( 'greaterThan', greaterThan ); -addMethodChaining( 'lessThanEqual', lessThanEqual ); -addMethodChaining( 'greaterThanEqual', greaterThanEqual ); -addMethodChaining( 'and', and ); -addMethodChaining( 'or', or ); -addMethodChaining( 'not', not ); -addMethodChaining( 'xor', xor ); -addMethodChaining( 'bitAnd', bitAnd ); -addMethodChaining( 'bitNot', bitNot ); -addMethodChaining( 'bitOr', bitOr ); -addMethodChaining( 'bitXor', bitXor ); -addMethodChaining( 'shiftLeft', shiftLeft ); -addMethodChaining( 'shiftRight', shiftRight ); + return this; + } -const remainder = ( ...params ) => { // @deprecated, r168 + toJSON( meta ) { - console.warn( 'TSL.OperatorNode: .remainder() has been renamed to .modInt().' ); - return modInt( ...params ); + const data = super.toJSON( meta ); -}; + data.object.color = this.color.getHex(); + data.object.intensity = this.intensity; -addMethodChaining( 'remainder', remainder ); + if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex(); -class MathNode extends TempNode { + if ( this.distance !== undefined ) data.object.distance = this.distance; + if ( this.angle !== undefined ) data.object.angle = this.angle; + if ( this.decay !== undefined ) data.object.decay = this.decay; + if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra; - constructor( method, aNode, bNode = null, cNode = null ) { + if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON(); + if ( this.target !== undefined ) data.object.target = this.target.uuid; - super(); + return data; - this.method = method; + } - this.aNode = aNode; - this.bNode = bNode; - this.cNode = cNode; +} - } +class HemisphereLight extends Light { - getInputType( builder ) { + constructor( skyColor, groundColor, intensity ) { - const aType = this.aNode.getNodeType( builder ); - const bType = this.bNode ? this.bNode.getNodeType( builder ) : null; - const cType = this.cNode ? this.cNode.getNodeType( builder ) : null; + super( skyColor, intensity ); - const aLen = builder.isMatrix( aType ) ? 0 : builder.getTypeLength( aType ); - const bLen = builder.isMatrix( bType ) ? 0 : builder.getTypeLength( bType ); - const cLen = builder.isMatrix( cType ) ? 0 : builder.getTypeLength( cType ); + this.isHemisphereLight = true; - if ( aLen > bLen && aLen > cLen ) { + this.type = 'HemisphereLight'; - return aType; + this.position.copy( Object3D.DEFAULT_UP ); + this.updateMatrix(); - } else if ( bLen > cLen ) { + this.groundColor = new Color( groundColor ); - return bType; + } - } else if ( cLen > aLen ) { + copy( source, recursive ) { - return cType; + super.copy( source, recursive ); - } + this.groundColor.copy( source.groundColor ); - return aType; + return this; } - getNodeType( builder ) { +} - const method = this.method; +const _projScreenMatrix$2 = /*@__PURE__*/ new Matrix4(); +const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3(); +const _lookTarget$1 = /*@__PURE__*/ new Vector3(); - if ( method === MathNode.LENGTH || method === MathNode.DISTANCE || method === MathNode.DOT ) { +class LightShadow { - return 'float'; + constructor( camera ) { - } else if ( method === MathNode.CROSS ) { + this.camera = camera; - return 'vec3'; + this.intensity = 1; - } else if ( method === MathNode.ALL ) { + this.bias = 0; + this.normalBias = 0; + this.radius = 1; + this.blurSamples = 8; - return 'bool'; + this.mapSize = new Vector2( 512, 512 ); - } else if ( method === MathNode.EQUALS ) { + this.map = null; + this.mapPass = null; + this.matrix = new Matrix4(); - return builder.changeComponentType( this.aNode.getNodeType( builder ), 'bool' ); + this.autoUpdate = true; + this.needsUpdate = false; - } else if ( method === MathNode.MOD ) { + this._frustum = new Frustum(); + this._frameExtents = new Vector2( 1, 1 ); - return this.aNode.getNodeType( builder ); + this._viewportCount = 1; - } else { + this._viewports = [ - return this.getInputType( builder ); + new Vector4( 0, 0, 1, 1 ) - } + ]; } - generate( builder, output ) { - - const method = this.method; + getViewportCount() { - const type = this.getNodeType( builder ); - const inputType = this.getInputType( builder ); + return this._viewportCount; - const a = this.aNode; - const b = this.bNode; - const c = this.cNode; + } - const isWebGL = builder.renderer.isWebGLRenderer === true; + getFrustum() { - if ( method === MathNode.TRANSFORM_DIRECTION ) { + return this._frustum; - // dir can be either a direction vector or a normal vector - // upper-left 3x3 of matrix is assumed to be orthogonal + } - let tA = a; - let tB = b; + updateMatrices( light ) { - if ( builder.isMatrix( tA.getNodeType( builder ) ) ) { + const shadowCamera = this.camera; + const shadowMatrix = this.matrix; - tB = vec4( vec3( tB ), 0.0 ); + _lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld ); + shadowCamera.position.copy( _lightPositionWorld$1 ); - } else { + _lookTarget$1.setFromMatrixPosition( light.target.matrixWorld ); + shadowCamera.lookAt( _lookTarget$1 ); + shadowCamera.updateMatrixWorld(); - tA = vec4( vec3( tA ), 0.0 ); + _projScreenMatrix$2.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); + this._frustum.setFromProjectionMatrix( _projScreenMatrix$2 ); - } + shadowMatrix.set( + 0.5, 0.0, 0.0, 0.5, + 0.0, 0.5, 0.0, 0.5, + 0.0, 0.0, 0.5, 0.5, + 0.0, 0.0, 0.0, 1.0 + ); - const mulNode = mul( tA, tB ).xyz; + shadowMatrix.multiply( _projScreenMatrix$2 ); - return normalize( mulNode ).build( builder, output ); + } - } else if ( method === MathNode.NEGATE ) { + getViewport( viewportIndex ) { - return builder.format( '( - ' + a.build( builder, inputType ) + ' )', type, output ); + return this._viewports[ viewportIndex ]; - } else if ( method === MathNode.ONE_MINUS ) { + } - return sub( 1.0, a ).build( builder, output ); + getFrameExtents() { - } else if ( method === MathNode.RECIPROCAL ) { + return this._frameExtents; - return div( 1.0, a ).build( builder, output ); + } - } else if ( method === MathNode.DIFFERENCE ) { + dispose() { - return abs( sub( a, b ) ).build( builder, output ); + if ( this.map ) { - } else { + this.map.dispose(); - const params = []; + } - if ( method === MathNode.CROSS || method === MathNode.MOD ) { + if ( this.mapPass ) { - params.push( - a.build( builder, type ), - b.build( builder, type ) - ); + this.mapPass.dispose(); - } else if ( isWebGL && method === MathNode.STEP ) { + } - params.push( - a.build( builder, builder.getTypeLength( a.getNodeType( builder ) ) === 1 ? 'float' : inputType ), - b.build( builder, inputType ) - ); + } - } else if ( ( isWebGL && ( method === MathNode.MIN || method === MathNode.MAX ) ) || method === MathNode.MOD ) { + copy( source ) { - params.push( - a.build( builder, inputType ), - b.build( builder, builder.getTypeLength( b.getNodeType( builder ) ) === 1 ? 'float' : inputType ) - ); + this.camera = source.camera.clone(); - } else if ( method === MathNode.REFRACT ) { + this.intensity = source.intensity; - params.push( - a.build( builder, inputType ), - b.build( builder, inputType ), - c.build( builder, 'float' ) - ); + this.bias = source.bias; + this.radius = source.radius; - } else if ( method === MathNode.MIX ) { + this.mapSize.copy( source.mapSize ); - params.push( - a.build( builder, inputType ), - b.build( builder, inputType ), - c.build( builder, builder.getTypeLength( c.getNodeType( builder ) ) === 1 ? 'float' : inputType ) - ); + return this; - } else { + } - params.push( a.build( builder, inputType ) ); - if ( b !== null ) params.push( b.build( builder, inputType ) ); - if ( c !== null ) params.push( c.build( builder, inputType ) ); + clone() { - } + return new this.constructor().copy( this ); - return builder.format( `${ builder.getMethod( method, type ) }( ${params.join( ', ' )} )`, type, output ); + } - } + toJSON() { - } + const object = {}; - serialize( data ) { + if ( this.intensity !== 1 ) object.intensity = this.intensity; + if ( this.bias !== 0 ) object.bias = this.bias; + if ( this.normalBias !== 0 ) object.normalBias = this.normalBias; + if ( this.radius !== 1 ) object.radius = this.radius; + if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray(); - super.serialize( data ); + object.camera = this.camera.toJSON( false ).object; + delete object.camera.matrix; - data.method = this.method; + return object; } - deserialize( data ) { +} - super.deserialize( data ); +class SpotLightShadow extends LightShadow { - this.method = data.method; + constructor() { - } + super( new PerspectiveCamera( 50, 1, 0.5, 500 ) ); -} + this.isSpotLightShadow = true; -// 1 input + this.focus = 1; -MathNode.ALL = 'all'; -MathNode.ANY = 'any'; -MathNode.EQUALS = 'equals'; + } -MathNode.RADIANS = 'radians'; -MathNode.DEGREES = 'degrees'; -MathNode.EXP = 'exp'; -MathNode.EXP2 = 'exp2'; -MathNode.LOG = 'log'; -MathNode.LOG2 = 'log2'; -MathNode.SQRT = 'sqrt'; -MathNode.INVERSE_SQRT = 'inversesqrt'; -MathNode.FLOOR = 'floor'; -MathNode.CEIL = 'ceil'; -MathNode.NORMALIZE = 'normalize'; -MathNode.FRACT = 'fract'; -MathNode.SIN = 'sin'; -MathNode.COS = 'cos'; -MathNode.TAN = 'tan'; -MathNode.ASIN = 'asin'; -MathNode.ACOS = 'acos'; -MathNode.ATAN = 'atan'; -MathNode.ABS = 'abs'; -MathNode.SIGN = 'sign'; -MathNode.LENGTH = 'length'; -MathNode.NEGATE = 'negate'; -MathNode.ONE_MINUS = 'oneMinus'; -MathNode.DFDX = 'dFdx'; -MathNode.DFDY = 'dFdy'; -MathNode.ROUND = 'round'; -MathNode.RECIPROCAL = 'reciprocal'; -MathNode.TRUNC = 'trunc'; -MathNode.FWIDTH = 'fwidth'; -MathNode.BITCAST = 'bitcast'; -MathNode.TRANSPOSE = 'transpose'; + updateMatrices( light ) { -// 2 inputs + const camera = this.camera; -MathNode.ATAN2 = 'atan2'; -MathNode.MIN = 'min'; -MathNode.MAX = 'max'; -MathNode.MOD = 'mod'; -MathNode.STEP = 'step'; -MathNode.REFLECT = 'reflect'; -MathNode.DISTANCE = 'distance'; -MathNode.DIFFERENCE = 'difference'; -MathNode.DOT = 'dot'; -MathNode.CROSS = 'cross'; -MathNode.POW = 'pow'; -MathNode.TRANSFORM_DIRECTION = 'transformDirection'; + const fov = RAD2DEG * 2 * light.angle * this.focus; + const aspect = this.mapSize.width / this.mapSize.height; + const far = light.distance || camera.far; -// 3 inputs + if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) { -MathNode.MIX = 'mix'; -MathNode.CLAMP = 'clamp'; -MathNode.REFRACT = 'refract'; -MathNode.SMOOTHSTEP = 'smoothstep'; -MathNode.FACEFORWARD = 'faceforward'; + camera.fov = fov; + camera.aspect = aspect; + camera.far = far; + camera.updateProjectionMatrix(); -MathNode.type = /*@__PURE__*/ registerNode( 'Math', MathNode ); + } -const EPSILON = /*@__PURE__*/ float( 1e-6 ); -const INFINITY = /*@__PURE__*/ float( 1e6 ); -const PI = /*@__PURE__*/ float( Math.PI ); -const PI2 = /*@__PURE__*/ float( Math.PI * 2 ); + super.updateMatrices( light ); -const all = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ALL ); -const any = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ANY ); -const equals = /*@__PURE__*/ nodeProxy( MathNode, MathNode.EQUALS ); + } -const radians = /*@__PURE__*/ nodeProxy( MathNode, MathNode.RADIANS ); -const degrees = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DEGREES ); -const exp = /*@__PURE__*/ nodeProxy( MathNode, MathNode.EXP ); -const exp2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.EXP2 ); -const log = /*@__PURE__*/ nodeProxy( MathNode, MathNode.LOG ); -const log2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.LOG2 ); -const sqrt = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SQRT ); -const inverseSqrt = /*@__PURE__*/ nodeProxy( MathNode, MathNode.INVERSE_SQRT ); -const floor = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FLOOR ); -const ceil = /*@__PURE__*/ nodeProxy( MathNode, MathNode.CEIL ); -const normalize = /*@__PURE__*/ nodeProxy( MathNode, MathNode.NORMALIZE ); -const fract = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FRACT ); -const sin = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SIN ); -const cos = /*@__PURE__*/ nodeProxy( MathNode, MathNode.COS ); -const tan = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TAN ); -const asin = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ASIN ); -const acos = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ACOS ); -const atan = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ATAN ); -const abs = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ABS ); -const sign = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SIGN ); -const length = /*@__PURE__*/ nodeProxy( MathNode, MathNode.LENGTH ); -const negate = /*@__PURE__*/ nodeProxy( MathNode, MathNode.NEGATE ); -const oneMinus = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ONE_MINUS ); -const dFdx = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DFDX ); -const dFdy = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DFDY ); -const round = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ROUND ); -const reciprocal = /*@__PURE__*/ nodeProxy( MathNode, MathNode.RECIPROCAL ); -const trunc = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TRUNC ); -const fwidth = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FWIDTH ); -const bitcast = /*@__PURE__*/ nodeProxy( MathNode, MathNode.BITCAST ); -const transpose = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TRANSPOSE ); + copy( source ) { -const atan2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ATAN2 ); -const min$1 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MIN ); -const max$1 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MAX ); -const mod = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MOD ); -const step = /*@__PURE__*/ nodeProxy( MathNode, MathNode.STEP ); -const reflect = /*@__PURE__*/ nodeProxy( MathNode, MathNode.REFLECT ); -const distance = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DISTANCE ); -const difference = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DIFFERENCE ); -const dot = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DOT ); -const cross = /*@__PURE__*/ nodeProxy( MathNode, MathNode.CROSS ); -const pow = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW ); -const pow2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW, 2 ); -const pow3 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW, 3 ); -const pow4 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW, 4 ); -const transformDirection = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TRANSFORM_DIRECTION ); + super.copy( source ); -const cbrt = ( a ) => mul( sign( a ), pow( abs( a ), 1.0 / 3.0 ) ); -const lengthSq = ( a ) => dot( a, a ); -const mix = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MIX ); -const clamp = ( value, low = 0, high = 1 ) => nodeObject( new MathNode( MathNode.CLAMP, nodeObject( value ), nodeObject( low ), nodeObject( high ) ) ); -const saturate = ( value ) => clamp( value ); -const refract = /*@__PURE__*/ nodeProxy( MathNode, MathNode.REFRACT ); -const smoothstep = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SMOOTHSTEP ); -const faceForward = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FACEFORWARD ); + this.focus = source.focus; -const rand = /*@__PURE__*/ Fn( ( [ uv ] ) => { + return this; - const a = 12.9898, b = 78.233, c = 43758.5453; - const dt = dot( uv.xy, vec2( a, b ) ), sn = mod( dt, PI ); + } - return fract( sin( sn ).mul( c ) ); +} -} ); +class SpotLight extends Light { -const mixElement = ( t, e1, e2 ) => mix( e1, e2, t ); -const smoothstepElement = ( x, low, high ) => smoothstep( low, high, x ); + constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2 ) { -addMethodChaining( 'all', all ); -addMethodChaining( 'any', any ); -addMethodChaining( 'equals', equals ); + super( color, intensity ); -addMethodChaining( 'radians', radians ); -addMethodChaining( 'degrees', degrees ); -addMethodChaining( 'exp', exp ); -addMethodChaining( 'exp2', exp2 ); -addMethodChaining( 'log', log ); -addMethodChaining( 'log2', log2 ); -addMethodChaining( 'sqrt', sqrt ); -addMethodChaining( 'inverseSqrt', inverseSqrt ); -addMethodChaining( 'floor', floor ); -addMethodChaining( 'ceil', ceil ); -addMethodChaining( 'normalize', normalize ); -addMethodChaining( 'fract', fract ); -addMethodChaining( 'sin', sin ); -addMethodChaining( 'cos', cos ); -addMethodChaining( 'tan', tan ); -addMethodChaining( 'asin', asin ); -addMethodChaining( 'acos', acos ); -addMethodChaining( 'atan', atan ); -addMethodChaining( 'abs', abs ); -addMethodChaining( 'sign', sign ); -addMethodChaining( 'length', length ); -addMethodChaining( 'lengthSq', lengthSq ); -addMethodChaining( 'negate', negate ); -addMethodChaining( 'oneMinus', oneMinus ); -addMethodChaining( 'dFdx', dFdx ); -addMethodChaining( 'dFdy', dFdy ); -addMethodChaining( 'round', round ); -addMethodChaining( 'reciprocal', reciprocal ); -addMethodChaining( 'trunc', trunc ); -addMethodChaining( 'fwidth', fwidth ); -addMethodChaining( 'atan2', atan2 ); -addMethodChaining( 'min', min$1 ); -addMethodChaining( 'max', max$1 ); -addMethodChaining( 'mod', mod ); -addMethodChaining( 'step', step ); -addMethodChaining( 'reflect', reflect ); -addMethodChaining( 'distance', distance ); -addMethodChaining( 'dot', dot ); -addMethodChaining( 'cross', cross ); -addMethodChaining( 'pow', pow ); -addMethodChaining( 'pow2', pow2 ); -addMethodChaining( 'pow3', pow3 ); -addMethodChaining( 'pow4', pow4 ); -addMethodChaining( 'transformDirection', transformDirection ); -addMethodChaining( 'mix', mixElement ); -addMethodChaining( 'clamp', clamp ); -addMethodChaining( 'refract', refract ); -addMethodChaining( 'smoothstep', smoothstepElement ); -addMethodChaining( 'faceForward', faceForward ); -addMethodChaining( 'difference', difference ); -addMethodChaining( 'saturate', saturate ); -addMethodChaining( 'cbrt', cbrt ); -addMethodChaining( 'transpose', transpose ); -addMethodChaining( 'rand', rand ); + this.isSpotLight = true; -class ConditionalNode extends Node { + this.type = 'SpotLight'; - constructor( condNode, ifNode, elseNode = null ) { + this.position.copy( Object3D.DEFAULT_UP ); + this.updateMatrix(); - super(); + this.target = new Object3D(); - this.condNode = condNode; + this.distance = distance; + this.angle = angle; + this.penumbra = penumbra; + this.decay = decay; - this.ifNode = ifNode; - this.elseNode = elseNode; + this.map = null; + + this.shadow = new SpotLightShadow(); } - getNodeType( builder ) { + get power() { - const ifType = this.ifNode.getNodeType( builder ); - - if ( this.elseNode !== null ) { - - const elseType = this.elseNode.getNodeType( builder ); - - if ( builder.getTypeLength( elseType ) > builder.getTypeLength( ifType ) ) { - - return elseType; - - } - - } - - return ifType; + // compute the light's luminous power (in lumens) from its intensity (in candela) + // by convention for a spotlight, luminous power (lm) = π * luminous intensity (cd) + return this.intensity * Math.PI; } - setup( builder ) { + set power( power ) { - const properties = builder.getNodeProperties( this ); - properties.condNode = this.condNode.cache(); - properties.ifNode = this.ifNode.cache(); - properties.elseNode = this.elseNode ? this.elseNode.cache() : null; + // set the light's intensity (in candela) from the desired luminous power (in lumens) + this.intensity = power / Math.PI; } - generate( builder, output ) { - - const type = this.getNodeType( builder ); - - const nodeData = builder.getDataFromNode( this ); + dispose() { - if ( nodeData.nodeProperty !== undefined ) { + this.shadow.dispose(); - return nodeData.nodeProperty; + } - } + copy( source, recursive ) { - const { condNode, ifNode, elseNode } = builder.getNodeProperties( this ); + super.copy( source, recursive ); - const needsOutput = output !== 'void'; - const nodeProperty = needsOutput ? property( type ).build( builder ) : ''; + this.distance = source.distance; + this.angle = source.angle; + this.penumbra = source.penumbra; + this.decay = source.decay; - nodeData.nodeProperty = nodeProperty; + this.target = source.target.clone(); - const nodeSnippet = condNode.build( builder, 'bool' ); + this.shadow = source.shadow.clone(); - builder.addFlowCode( `\n${ builder.tab }if ( ${ nodeSnippet } ) {\n\n` ).addFlowTab(); + return this; - let ifSnippet = ifNode.build( builder, type ); + } - if ( ifSnippet ) { +} - if ( needsOutput ) { +const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4(); +const _lightPositionWorld = /*@__PURE__*/ new Vector3(); +const _lookTarget = /*@__PURE__*/ new Vector3(); - ifSnippet = nodeProperty + ' = ' + ifSnippet + ';'; +class PointLightShadow extends LightShadow { - } else { + constructor() { - ifSnippet = 'return ' + ifSnippet + ';'; + super( new PerspectiveCamera( 90, 1, 0.5, 500 ) ); - } + this.isPointLightShadow = true; - } + this._frameExtents = new Vector2( 4, 2 ); - builder.removeFlowTab().addFlowCode( builder.tab + '\t' + ifSnippet + '\n\n' + builder.tab + '}' ); + this._viewportCount = 6; - if ( elseNode !== null ) { + this._viewports = [ + // These viewports map a cube-map onto a 2D texture with the + // following orientation: + // + // xzXZ + // y Y + // + // X - Positive x direction + // x - Negative x direction + // Y - Positive y direction + // y - Negative y direction + // Z - Positive z direction + // z - Negative z direction - builder.addFlowCode( ' else {\n\n' ).addFlowTab(); + // positive X + new Vector4( 2, 1, 1, 1 ), + // negative X + new Vector4( 0, 1, 1, 1 ), + // positive Z + new Vector4( 3, 1, 1, 1 ), + // negative Z + new Vector4( 1, 1, 1, 1 ), + // positive Y + new Vector4( 3, 0, 1, 1 ), + // negative Y + new Vector4( 1, 0, 1, 1 ) + ]; - let elseSnippet = elseNode.build( builder, type ); + this._cubeDirections = [ + new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ), + new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 ) + ]; - if ( elseSnippet ) { + this._cubeUps = [ + new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), + new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 ) + ]; - if ( needsOutput ) { + } - elseSnippet = nodeProperty + ' = ' + elseSnippet + ';'; + updateMatrices( light, viewportIndex = 0 ) { - } else { + const camera = this.camera; + const shadowMatrix = this.matrix; - elseSnippet = 'return ' + elseSnippet + ';'; + const far = light.distance || camera.far; - } + if ( far !== camera.far ) { - } + camera.far = far; + camera.updateProjectionMatrix(); - builder.removeFlowTab().addFlowCode( builder.tab + '\t' + elseSnippet + '\n\n' + builder.tab + '}\n\n' ); + } - } else { + _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); + camera.position.copy( _lightPositionWorld ); - builder.addFlowCode( '\n\n' ); + _lookTarget.copy( camera.position ); + _lookTarget.add( this._cubeDirections[ viewportIndex ] ); + camera.up.copy( this._cubeUps[ viewportIndex ] ); + camera.lookAt( _lookTarget ); + camera.updateMatrixWorld(); - } + shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); - return builder.format( nodeProperty, type, output ); + _projScreenMatrix$1.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); + this._frustum.setFromProjectionMatrix( _projScreenMatrix$1 ); } } -ConditionalNode.type = /*@__PURE__*/ registerNode( 'Conditional', ConditionalNode ); - -const select = /*@__PURE__*/ nodeProxy( ConditionalNode ); - -addMethodChaining( 'select', select ); - -// - -const cond = ( ...params ) => { // @deprecated, r168 - - console.warn( 'TSL.ConditionalNode: cond() has been renamed to select().' ); - return select( ...params ); - -}; +class PointLight extends Light { -addMethodChaining( 'cond', cond ); + constructor( color, intensity, distance = 0, decay = 2 ) { -class ContextNode extends Node { + super( color, intensity ); - constructor( node, value = {} ) { + this.isPointLight = true; - super(); + this.type = 'PointLight'; - this.isContextNode = true; + this.distance = distance; + this.decay = decay; - this.node = node; - this.value = value; + this.shadow = new PointLightShadow(); } - getScope() { + get power() { - return this.node.getScope(); + // compute the light's luminous power (in lumens) from its intensity (in candela) + // for an isotropic light source, luminous power (lm) = 4 π luminous intensity (cd) + return this.intensity * 4 * Math.PI; } - getNodeType( builder ) { + set power( power ) { - return this.node.getNodeType( builder ); + // set the light's intensity (in candela) from the desired luminous power (in lumens) + this.intensity = power / ( 4 * Math.PI ); } - analyze( builder ) { + dispose() { - this.node.build( builder ); + this.shadow.dispose(); } - setup( builder ) { - - const previousContext = builder.getContext(); + copy( source, recursive ) { - builder.setContext( { ...builder.context, ...this.value } ); + super.copy( source, recursive ); - const node = this.node.build( builder ); + this.distance = source.distance; + this.decay = source.decay; - builder.setContext( previousContext ); + this.shadow = source.shadow.clone(); - return node; + return this; } - generate( builder, output ) { - - const previousContext = builder.getContext(); +} - builder.setContext( { ...builder.context, ...this.value } ); +class OrthographicCamera extends Camera { - const snippet = this.node.build( builder, output ); + constructor( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) { - builder.setContext( previousContext ); + super(); - return snippet; + this.isOrthographicCamera = true; - } + this.type = 'OrthographicCamera'; -} + this.zoom = 1; + this.view = null; -ContextNode.type = /*@__PURE__*/ registerNode( 'Context', ContextNode ); + this.left = left; + this.right = right; + this.top = top; + this.bottom = bottom; -const context = /*@__PURE__*/ nodeProxy( ContextNode ); -const label = ( node, name ) => context( node, { label: name } ); + this.near = near; + this.far = far; -addMethodChaining( 'context', context ); -addMethodChaining( 'label', label ); + this.updateProjectionMatrix(); -class VarNode extends Node { + } - constructor( node, name = null ) { + copy( source, recursive ) { - super(); + super.copy( source, recursive ); - this.node = node; - this.name = name; + this.left = source.left; + this.right = source.right; + this.top = source.top; + this.bottom = source.bottom; + this.near = source.near; + this.far = source.far; - this.global = true; + this.zoom = source.zoom; + this.view = source.view === null ? null : Object.assign( {}, source.view ); - this.isVarNode = true; + return this; } - getHash( builder ) { - - return this.name || super.getHash( builder ); + setViewOffset( fullWidth, fullHeight, x, y, width, height ) { - } + if ( this.view === null ) { - getNodeType( builder ) { + this.view = { + enabled: true, + fullWidth: 1, + fullHeight: 1, + offsetX: 0, + offsetY: 0, + width: 1, + height: 1 + }; - return this.node.getNodeType( builder ); + } - } + this.view.enabled = true; + this.view.fullWidth = fullWidth; + this.view.fullHeight = fullHeight; + this.view.offsetX = x; + this.view.offsetY = y; + this.view.width = width; + this.view.height = height; - generate( builder ) { + this.updateProjectionMatrix(); - const { node, name } = this; + } - const nodeVar = builder.getVarFromNode( this, name, builder.getVectorType( this.getNodeType( builder ) ) ); + clearViewOffset() { - const propertyName = builder.getPropertyName( nodeVar ); + if ( this.view !== null ) { - const snippet = node.build( builder, nodeVar.type ); + this.view.enabled = false; - builder.addLineFlowCode( `${propertyName} = ${snippet}` ); + } - return propertyName; + this.updateProjectionMatrix(); } -} + updateProjectionMatrix() { -VarNode.type = /*@__PURE__*/ registerNode( 'Var', VarNode ); + const dx = ( this.right - this.left ) / ( 2 * this.zoom ); + const dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); + const cx = ( this.right + this.left ) / 2; + const cy = ( this.top + this.bottom ) / 2; -const temp = /*@__PURE__*/ nodeProxy( VarNode ); + let left = cx - dx; + let right = cx + dx; + let top = cy + dy; + let bottom = cy - dy; -addMethodChaining( 'temp', temp ); // @TODO: Will be removed in the future -addMethodChaining( 'toVar', ( ...params ) => temp( ...params ).append() ); + if ( this.view !== null && this.view.enabled ) { -class VaryingNode extends Node { + const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom; + const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom; - constructor( node, name = null ) { + left += scaleW * this.view.offsetX; + right = left + scaleW * this.view.width; + top -= scaleH * this.view.offsetY; + bottom = top - scaleH * this.view.height; - super(); + } - this.node = node; - this.name = name; + this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem ); - this.isVaryingNode = true; + this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); } - isGlobal() { + toJSON( meta ) { - return true; + const data = super.toJSON( meta ); - } + data.object.zoom = this.zoom; + data.object.left = this.left; + data.object.right = this.right; + data.object.top = this.top; + data.object.bottom = this.bottom; + data.object.near = this.near; + data.object.far = this.far; - getHash( builder ) { + if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); - return this.name || super.getHash( builder ); + return data; } - getNodeType( builder ) { +} - // VaryingNode is auto type +class DirectionalLightShadow extends LightShadow { - return this.node.getNodeType( builder ); + constructor() { + + super( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); + + this.isDirectionalLightShadow = true; } - setupVarying( builder ) { +} - const properties = builder.getNodeProperties( this ); +class DirectionalLight extends Light { - let varying = properties.varying; + constructor( color, intensity ) { - if ( varying === undefined ) { + super( color, intensity ); - const name = this.name; - const type = this.getNodeType( builder ); + this.isDirectionalLight = true; - properties.varying = varying = builder.getVaryingFromNode( this, name, type ); - properties.node = this.node; + this.type = 'DirectionalLight'; - } + this.position.copy( Object3D.DEFAULT_UP ); + this.updateMatrix(); - // this property can be used to check if the varying can be optimized for a variable - varying.needsInterpolation || ( varying.needsInterpolation = ( builder.shaderStage === 'fragment' ) ); + this.target = new Object3D(); - return varying; + this.shadow = new DirectionalLightShadow(); } - setup( builder ) { + dispose() { - this.setupVarying( builder ); + this.shadow.dispose(); } - analyze( builder ) { - - this.setupVarying( builder ); + copy( source ) { - return this.node.analyze( builder ); + super.copy( source ); - } + this.target = source.target.clone(); + this.shadow = source.shadow.clone(); - generate( builder ) { + return this; - const properties = builder.getNodeProperties( this ); - const varying = this.setupVarying( builder ); + } - if ( properties.propertyName === undefined ) { +} - const type = this.getNodeType( builder ); - const propertyName = builder.getPropertyName( varying, NodeShaderStage.VERTEX ); +class AmbientLight extends Light { - // force node run in vertex stage - builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, this.node, type, propertyName ); + constructor( color, intensity ) { - properties.propertyName = propertyName; + super( color, intensity ); - } + this.isAmbientLight = true; - return builder.getPropertyName( varying ); + this.type = 'AmbientLight'; } } -VaryingNode.type = /*@__PURE__*/ registerNode( 'Varying', VaryingNode ); +class RectAreaLight extends Light { -const varying = /*@__PURE__*/ nodeProxy( VaryingNode ); + constructor( color, intensity, width = 10, height = 10 ) { -addMethodChaining( 'varying', varying ); + super( color, intensity ); -const getColorSpaceName = ( colorSpace ) => { + this.isRectAreaLight = true; - let method = null; + this.type = 'RectAreaLight'; - if ( colorSpace === LinearSRGBColorSpace ) { + this.width = width; + this.height = height; - method = 'Linear'; + } - } else if ( colorSpace === SRGBColorSpace ) { + get power() { - method = 'sRGB'; + // compute the light's luminous power (in lumens) from its intensity (in nits) + return this.intensity * this.width * this.height * Math.PI; } - return method; + set power( power ) { -}; + // set the light's intensity (in nits) from the desired luminous power (in lumens) + this.intensity = power / ( this.width * this.height * Math.PI ); -const getColorSpaceMethod = ( source, target ) => { + } - return getColorSpaceName( source ) + 'To' + getColorSpaceName( target ); + copy( source ) { -}; + super.copy( source ); -class ColorSpaceNode extends TempNode { + this.width = source.width; + this.height = source.height; - constructor( colorNode, target = null, source = null ) { + return this; - super( 'vec4' ); + } - this.colorNode = colorNode; - this.target = target; - this.source = source; + toJSON( meta ) { - } + const data = super.toJSON( meta ); - setup( builder ) { + data.object.width = this.width; + data.object.height = this.height; - const { renderer, context } = builder; + return data; - const source = this.source || context.outputColorSpace || renderer.outputColorSpace; - const target = this.target || context.outputColorSpace || renderer.outputColorSpace; - const colorNode = this.colorNode; + } - if ( source === target ) return colorNode; +} - const colorSpace = getColorSpaceMethod( source, target ); +/** + * Primary reference: + * https://graphics.stanford.edu/papers/envmap/envmap.pdf + * + * Secondary reference: + * https://www.ppsloan.org/publications/StupidSH36.pdf + */ - let outputNode = null; +// 3-band SH defined by 9 coefficients - const colorSpaceFn = renderer.nodes.library.getColorSpaceFunction( colorSpace ); +class SphericalHarmonics3 { - if ( colorSpaceFn !== null ) { + constructor() { - outputNode = vec4( colorSpaceFn( colorNode.rgb ), colorNode.a ); + this.isSphericalHarmonics3 = true; - } else { + this.coefficients = []; - console.error( 'ColorSpaceNode: Unsupported Color Space configuration.', colorSpace ); + for ( let i = 0; i < 9; i ++ ) { - outputNode = colorNode; + this.coefficients.push( new Vector3() ); } - return outputNode; - } -} - -ColorSpaceNode.type = /*@__PURE__*/ registerNode( 'ColorSpace', ColorSpaceNode ); + set( coefficients ) { -const toOutputColorSpace = ( node, colorSpace = null ) => nodeObject( new ColorSpaceNode( nodeObject( node ), colorSpace, LinearSRGBColorSpace ) ); -const toWorkingColorSpace = ( node, colorSpace = null ) => nodeObject( new ColorSpaceNode( nodeObject( node ), LinearSRGBColorSpace, colorSpace ) ); + for ( let i = 0; i < 9; i ++ ) { -addMethodChaining( 'toOutputColorSpace', toOutputColorSpace ); -addMethodChaining( 'toWorkingColorSpace', toWorkingColorSpace ); + this.coefficients[ i ].copy( coefficients[ i ] ); -let ReferenceElementNode$1 = class ReferenceElementNode extends ArrayElementNode { + } - constructor( referenceNode, indexNode ) { + return this; - super( referenceNode, indexNode ); + } - this.referenceNode = referenceNode; + zero() { - this.isReferenceElementNode = true; + for ( let i = 0; i < 9; i ++ ) { - } + this.coefficients[ i ].set( 0, 0, 0 ); - getNodeType() { + } - return this.referenceNode.uniformType; + return this; } - generate( builder ) { + // get the radiance in the direction of the normal + // target is a Vector3 + getAt( normal, target ) { - const snippet = super.generate( builder ); - const arrayType = this.referenceNode.getNodeType(); - const elementType = this.getNodeType(); + // normal is assumed to be unit length - return builder.format( snippet, arrayType, elementType ); + const x = normal.x, y = normal.y, z = normal.z; - } + const coeff = this.coefficients; -}; + // band 0 + target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 ); -class ReferenceBaseNode extends Node { + // band 1 + target.addScaledVector( coeff[ 1 ], 0.488603 * y ); + target.addScaledVector( coeff[ 2 ], 0.488603 * z ); + target.addScaledVector( coeff[ 3 ], 0.488603 * x ); - constructor( property, uniformType, object = null, count = null ) { + // band 2 + target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) ); + target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) ); + target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) ); + target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) ); + target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) ); - super(); + return target; - this.property = property; - this.uniformType = uniformType; - this.object = object; - this.count = count; + } - this.properties = property.split( '.' ); - this.reference = object; - this.node = null; + // get the irradiance (radiance convolved with cosine lobe) in the direction of the normal + // target is a Vector3 + // https://graphics.stanford.edu/papers/envmap/envmap.pdf + getIrradianceAt( normal, target ) { - this.updateType = NodeUpdateType.OBJECT; + // normal is assumed to be unit length - } + const x = normal.x, y = normal.y, z = normal.z; - element( indexNode ) { + const coeff = this.coefficients; - return nodeObject( new ReferenceElementNode$1( this, nodeObject( indexNode ) ) ); + // band 0 + target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // π * 0.282095 - } + // band 1 + target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * π / 3 ) * 0.488603 + target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z ); + target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x ); - setNodeType( uniformType ) { + // band 2 + target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( π / 4 ) * 1.092548 + target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z ); + target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( π / 4 ) * 0.315392 * 3 + target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z ); + target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( π / 4 ) * 0.546274 - this.node = uniform( null, uniformType ).getSelf(); + return target; } - getNodeType( builder ) { + add( sh ) { - if ( this.node === null ) { + for ( let i = 0; i < 9; i ++ ) { - this.updateValue(); + this.coefficients[ i ].add( sh.coefficients[ i ] ); } - return this.node.getNodeType( builder ); + return this; } - getValueFromReference( object = this.reference ) { + addScaledSH( sh, s ) { - const { properties } = this; + for ( let i = 0; i < 9; i ++ ) { - let value = object[ properties[ 0 ] ]; + this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s ); - for ( let i = 1; i < properties.length; i ++ ) { + } - value = value[ properties[ i ] ]; + return this; + + } + + scale( s ) { + + for ( let i = 0; i < 9; i ++ ) { + + this.coefficients[ i ].multiplyScalar( s ); } - return value; + return this; } - updateReference( state ) { + lerp( sh, alpha ) { - this.reference = this.object !== null ? this.object : state.object; + for ( let i = 0; i < 9; i ++ ) { - return this.reference; + this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha ); + + } + + return this; } - setup() { + equals( sh ) { - this.updateValue(); + for ( let i = 0; i < 9; i ++ ) { - return this.node; + if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) { + + return false; + + } + + } + + return true; } - update( /*frame*/ ) { + copy( sh ) { - this.updateValue(); + return this.set( sh.coefficients ); } - updateValue() { + clone() { - if ( this.node === null ) this.setNodeType( this.uniformType ); + return new this.constructor().copy( this ); - const value = this.getValueFromReference(); + } - if ( Array.isArray( value ) ) { + fromArray( array, offset = 0 ) { - this.node.array = value; + const coefficients = this.coefficients; - } else { + for ( let i = 0; i < 9; i ++ ) { - this.node.value = value; + coefficients[ i ].fromArray( array, offset + ( i * 3 ) ); } + return this; + } -} + toArray( array = [], offset = 0 ) { -ReferenceBaseNode.type = /*@__PURE__*/ registerNode( 'ReferenceBase', ReferenceBaseNode ); + const coefficients = this.coefficients; -class RendererReferenceNode extends ReferenceBaseNode { + for ( let i = 0; i < 9; i ++ ) { - constructor( property, inputType, renderer = null ) { + coefficients[ i ].toArray( array, offset + ( i * 3 ) ); - super( property, inputType, renderer ); + } - this.renderer = renderer; + return array; } - updateReference( state ) { + // evaluate the basis functions + // shBasis is an Array[ 9 ] + static getBasisAt( normal, shBasis ) { - this.reference = this.renderer !== null ? this.renderer : state.renderer; + // normal is assumed to be unit length - return this.reference; + const x = normal.x, y = normal.y, z = normal.z; - } + // band 0 + shBasis[ 0 ] = 0.282095; -} + // band 1 + shBasis[ 1 ] = 0.488603 * y; + shBasis[ 2 ] = 0.488603 * z; + shBasis[ 3 ] = 0.488603 * x; -RendererReferenceNode.type = /*@__PURE__*/ registerNode( 'RendererReference', RendererReferenceNode ); + // band 2 + shBasis[ 4 ] = 1.092548 * x * y; + shBasis[ 5 ] = 1.092548 * y * z; + shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 ); + shBasis[ 7 ] = 1.092548 * x * z; + shBasis[ 8 ] = 0.546274 * ( x * x - y * y ); -const rendererReference = ( name, type, renderer ) => nodeObject( new RendererReferenceNode( name, type, renderer ) ); + } -class ToneMappingNode extends TempNode { +} - constructor( toneMapping, exposureNode = toneMappingExposure, colorNode = null ) { +class LightProbe extends Light { - super( 'vec3' ); + constructor( sh = new SphericalHarmonics3(), intensity = 1 ) { - this.toneMapping = toneMapping; + super( undefined, intensity ); - this.exposureNode = exposureNode; - this.colorNode = colorNode; + this.isLightProbe = true; + + this.sh = sh; } - getCacheKey() { + copy( source ) { + + super.copy( source ); - let cacheKey = super.getCacheKey(); - cacheKey = '{toneMapping:' + this.toneMapping + ',nodes:' + cacheKey + '}'; + this.sh.copy( source.sh ); - return cacheKey; + return this; } - setup( builder ) { + fromJSON( json ) { - const colorNode = this.colorNode || builder.context.color; - const toneMapping = this.toneMapping; + this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON(); + this.sh.fromArray( json.sh ); - if ( toneMapping === NoToneMapping ) return colorNode; + return this; - let outputNode = null; + } - const toneMappingFn = builder.renderer.nodes.library.getToneMappingFunction( toneMapping ); + toJSON( meta ) { - if ( toneMappingFn !== null ) { + const data = super.toJSON( meta ); - outputNode = vec4( toneMappingFn( colorNode.rgb, this.exposureNode ), colorNode.a ); + data.object.sh = this.sh.toArray(); - } else { + return data; - console.error( 'ToneMappingNode: Unsupported Tone Mapping configuration.', toneMapping ); + } - outputNode = colorNode; +} - } +class MaterialLoader extends Loader { - return outputNode; + constructor( manager ) { - } + super( manager ); + this.textures = {}; -} + } -ToneMappingNode.type = /*@__PURE__*/ registerNode( 'ToneMapping', ToneMappingNode ); + load( url, onLoad, onProgress, onError ) { -const toneMapping = ( mapping, exposure, color ) => nodeObject( new ToneMappingNode( mapping, nodeObject( exposure ), nodeObject( color ) ) ); -const toneMappingExposure = /*@__PURE__*/ rendererReference( 'toneMappingExposure', 'float' ); + const scope = this; -addMethodChaining( 'toneMapping', ( color, mapping, exposure ) => toneMapping( mapping, exposure, color ) ); + const loader = new FileLoader( scope.manager ); + loader.setPath( scope.path ); + loader.setRequestHeader( scope.requestHeader ); + loader.setWithCredentials( scope.withCredentials ); + loader.load( url, function ( text ) { -class BufferAttributeNode extends InputNode { + try { - constructor( value, bufferType = null, bufferStride = 0, bufferOffset = 0 ) { + onLoad( scope.parse( JSON.parse( text ) ) ); - super( value, bufferType ); + } catch ( e ) { - this.isBufferNode = true; + if ( onError ) { - this.bufferType = bufferType; - this.bufferStride = bufferStride; - this.bufferOffset = bufferOffset; + onError( e ); - this.usage = StaticDrawUsage; - this.instanced = false; + } else { - this.attribute = null; + console.error( e ); - this.global = true; + } - if ( value && value.isBufferAttribute === true ) { + scope.manager.itemError( url ); - this.attribute = value; - this.usage = value.usage; - this.instanced = value.isInstancedBufferAttribute; + } - } + }, onProgress, onError ); } - getHash( builder ) { - - if ( this.bufferStride === 0 && this.bufferOffset === 0 ) { + parse( json ) { - let bufferData = builder.globalCache.getData( this.value ); + const textures = this.textures; - if ( bufferData === undefined ) { + function getTexture( name ) { - bufferData = { - node: this - }; + if ( textures[ name ] === undefined ) { - builder.globalCache.setData( this.value, bufferData ); + console.warn( 'THREE.MaterialLoader: Undefined texture', name ); } - return bufferData.node.uuid; + return textures[ name ]; } - return this.uuid; - - } + const material = this.createMaterialFromType( json.type ); - getNodeType( builder ) { + if ( json.uuid !== undefined ) material.uuid = json.uuid; + if ( json.name !== undefined ) material.name = json.name; + if ( json.color !== undefined && material.color !== undefined ) material.color.setHex( json.color ); + if ( json.roughness !== undefined ) material.roughness = json.roughness; + if ( json.metalness !== undefined ) material.metalness = json.metalness; + if ( json.sheen !== undefined ) material.sheen = json.sheen; + if ( json.sheenColor !== undefined ) material.sheenColor = new Color().setHex( json.sheenColor ); + if ( json.sheenRoughness !== undefined ) material.sheenRoughness = json.sheenRoughness; + if ( json.emissive !== undefined && material.emissive !== undefined ) material.emissive.setHex( json.emissive ); + if ( json.specular !== undefined && material.specular !== undefined ) material.specular.setHex( json.specular ); + if ( json.specularIntensity !== undefined ) material.specularIntensity = json.specularIntensity; + if ( json.specularColor !== undefined && material.specularColor !== undefined ) material.specularColor.setHex( json.specularColor ); + if ( json.shininess !== undefined ) material.shininess = json.shininess; + if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat; + if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness; + if ( json.dispersion !== undefined ) material.dispersion = json.dispersion; + if ( json.iridescence !== undefined ) material.iridescence = json.iridescence; + if ( json.iridescenceIOR !== undefined ) material.iridescenceIOR = json.iridescenceIOR; + if ( json.iridescenceThicknessRange !== undefined ) material.iridescenceThicknessRange = json.iridescenceThicknessRange; + if ( json.transmission !== undefined ) material.transmission = json.transmission; + if ( json.thickness !== undefined ) material.thickness = json.thickness; + if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance; + if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor ); + if ( json.anisotropy !== undefined ) material.anisotropy = json.anisotropy; + if ( json.anisotropyRotation !== undefined ) material.anisotropyRotation = json.anisotropyRotation; + if ( json.fog !== undefined ) material.fog = json.fog; + if ( json.flatShading !== undefined ) material.flatShading = json.flatShading; + if ( json.blending !== undefined ) material.blending = json.blending; + if ( json.combine !== undefined ) material.combine = json.combine; + if ( json.side !== undefined ) material.side = json.side; + if ( json.shadowSide !== undefined ) material.shadowSide = json.shadowSide; + if ( json.opacity !== undefined ) material.opacity = json.opacity; + if ( json.transparent !== undefined ) material.transparent = json.transparent; + if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest; + if ( json.alphaHash !== undefined ) material.alphaHash = json.alphaHash; + if ( json.depthFunc !== undefined ) material.depthFunc = json.depthFunc; + if ( json.depthTest !== undefined ) material.depthTest = json.depthTest; + if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite; + if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite; + if ( json.blendSrc !== undefined ) material.blendSrc = json.blendSrc; + if ( json.blendDst !== undefined ) material.blendDst = json.blendDst; + if ( json.blendEquation !== undefined ) material.blendEquation = json.blendEquation; + if ( json.blendSrcAlpha !== undefined ) material.blendSrcAlpha = json.blendSrcAlpha; + if ( json.blendDstAlpha !== undefined ) material.blendDstAlpha = json.blendDstAlpha; + if ( json.blendEquationAlpha !== undefined ) material.blendEquationAlpha = json.blendEquationAlpha; + if ( json.blendColor !== undefined && material.blendColor !== undefined ) material.blendColor.setHex( json.blendColor ); + if ( json.blendAlpha !== undefined ) material.blendAlpha = json.blendAlpha; + if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask; + if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc; + if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef; + if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask; + if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail; + if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail; + if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass; + if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite; - if ( this.bufferType === null ) { + if ( json.wireframe !== undefined ) material.wireframe = json.wireframe; + if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth; + if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap; + if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin; - this.bufferType = builder.getTypeFromAttribute( this.attribute ); + if ( json.rotation !== undefined ) material.rotation = json.rotation; - } + if ( json.linewidth !== undefined ) material.linewidth = json.linewidth; + if ( json.dashSize !== undefined ) material.dashSize = json.dashSize; + if ( json.gapSize !== undefined ) material.gapSize = json.gapSize; + if ( json.scale !== undefined ) material.scale = json.scale; - return this.bufferType; + if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset; + if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor; + if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits; - } + if ( json.dithering !== undefined ) material.dithering = json.dithering; - setup( builder ) { + if ( json.alphaToCoverage !== undefined ) material.alphaToCoverage = json.alphaToCoverage; + if ( json.premultipliedAlpha !== undefined ) material.premultipliedAlpha = json.premultipliedAlpha; + if ( json.forceSinglePass !== undefined ) material.forceSinglePass = json.forceSinglePass; - if ( this.attribute !== null ) return; + if ( json.visible !== undefined ) material.visible = json.visible; - const type = this.getNodeType( builder ); - const array = this.value; - const itemSize = builder.getTypeLength( type ); - const stride = this.bufferStride || itemSize; - const offset = this.bufferOffset; + if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped; - const buffer = array.isInterleavedBuffer === true ? array : new InterleavedBuffer( array, stride ); - const bufferAttribute = new InterleavedBufferAttribute( buffer, itemSize, offset ); + if ( json.userData !== undefined ) material.userData = json.userData; - buffer.setUsage( this.usage ); + if ( json.vertexColors !== undefined ) { - this.attribute = bufferAttribute; - this.attribute.isInstancedBufferAttribute = this.instanced; // @TODO: Add a possible: InstancedInterleavedBufferAttribute + if ( typeof json.vertexColors === 'number' ) { - } + material.vertexColors = ( json.vertexColors > 0 ) ? true : false; - generate( builder ) { + } else { - const nodeType = this.getNodeType( builder ); + material.vertexColors = json.vertexColors; - const nodeAttribute = builder.getBufferAttributeFromNode( this, nodeType ); - const propertyName = builder.getPropertyName( nodeAttribute ); + } - let output = null; + } - if ( builder.shaderStage === 'vertex' || builder.shaderStage === 'compute' ) { + // Shader Material - this.name = propertyName; + if ( json.uniforms !== undefined ) { - output = propertyName; + for ( const name in json.uniforms ) { - } else { + const uniform = json.uniforms[ name ]; - const nodeVarying = varying( this ); + material.uniforms[ name ] = {}; - output = nodeVarying.build( builder, nodeType ); + switch ( uniform.type ) { - } + case 't': + material.uniforms[ name ].value = getTexture( uniform.value ); + break; - return output; + case 'c': + material.uniforms[ name ].value = new Color().setHex( uniform.value ); + break; - } + case 'v2': + material.uniforms[ name ].value = new Vector2().fromArray( uniform.value ); + break; - getInputType( /*builder*/ ) { + case 'v3': + material.uniforms[ name ].value = new Vector3().fromArray( uniform.value ); + break; - return 'bufferAttribute'; + case 'v4': + material.uniforms[ name ].value = new Vector4().fromArray( uniform.value ); + break; - } + case 'm3': + material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value ); + break; - setUsage( value ) { + case 'm4': + material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value ); + break; - this.usage = value; + default: + material.uniforms[ name ].value = uniform.value; - if ( this.attribute && this.attribute.isBufferAttribute === true ) { + } - this.attribute.usage = value; + } } - return this; + if ( json.defines !== undefined ) material.defines = json.defines; + if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader; + if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader; + if ( json.glslVersion !== undefined ) material.glslVersion = json.glslVersion; - } + if ( json.extensions !== undefined ) { - setInstanced( value ) { + for ( const key in json.extensions ) { - this.instanced = value; + material.extensions[ key ] = json.extensions[ key ]; - return this; + } - } + } -} + if ( json.lights !== undefined ) material.lights = json.lights; + if ( json.clipping !== undefined ) material.clipping = json.clipping; -BufferAttributeNode.type = /*@__PURE__*/ registerNode( 'BufferAttribute', BufferAttributeNode ); + // for PointsMaterial -const bufferAttribute = ( array, type, stride, offset ) => nodeObject( new BufferAttributeNode( array, type, stride, offset ) ); -const dynamicBufferAttribute = ( array, type, stride, offset ) => bufferAttribute( array, type, stride, offset ).setUsage( DynamicDrawUsage ); + if ( json.size !== undefined ) material.size = json.size; + if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation; -const instancedBufferAttribute = ( array, type, stride, offset ) => bufferAttribute( array, type, stride, offset ).setInstanced( true ); -const instancedDynamicBufferAttribute = ( array, type, stride, offset ) => dynamicBufferAttribute( array, type, stride, offset ).setInstanced( true ); + // maps -addMethodChaining( 'toAttribute', ( bufferNode ) => bufferAttribute( bufferNode.value ) ); + if ( json.map !== undefined ) material.map = getTexture( json.map ); + if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap ); -class ComputeNode extends Node { + if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap ); - constructor( computeNode, count, workgroupSize = [ 64 ] ) { + if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap ); + if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale; - super( 'void' ); + if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap ); + if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType; + if ( json.normalScale !== undefined ) { - this.isComputeNode = true; + let normalScale = json.normalScale; - this.computeNode = computeNode; + if ( Array.isArray( normalScale ) === false ) { - this.count = count; - this.workgroupSize = workgroupSize; - this.dispatchCount = 0; + // Blender exporter used to export a scalar. See #7459 - this.version = 1; - this.updateBeforeType = NodeUpdateType.OBJECT; + normalScale = [ normalScale, normalScale ]; - this.updateDispatchCount(); + } - } + material.normalScale = new Vector2().fromArray( normalScale ); - dispose() { + } - this.dispatchEvent( { type: 'dispose' } ); + if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap ); + if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale; + if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias; - } + if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap ); + if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap ); - set needsUpdate( value ) { + if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap ); + if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity; - if ( value === true ) this.version ++; + if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap ); + if ( json.specularIntensityMap !== undefined ) material.specularIntensityMap = getTexture( json.specularIntensityMap ); + if ( json.specularColorMap !== undefined ) material.specularColorMap = getTexture( json.specularColorMap ); - } + if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap ); + if ( json.envMapRotation !== undefined ) material.envMapRotation.fromArray( json.envMapRotation ); + if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity; - updateDispatchCount() { + if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity; + if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio; - const { count, workgroupSize } = this; + if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap ); + if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity; - let size = workgroupSize[ 0 ]; + if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap ); + if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity; - for ( let i = 1; i < workgroupSize.length; i ++ ) - size *= workgroupSize[ i ]; + if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap ); - this.dispatchCount = Math.ceil( count / size ); + if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap ); + if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap ); + if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap ); + if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale ); - } + if ( json.iridescenceMap !== undefined ) material.iridescenceMap = getTexture( json.iridescenceMap ); + if ( json.iridescenceThicknessMap !== undefined ) material.iridescenceThicknessMap = getTexture( json.iridescenceThicknessMap ); - onInit() { } + if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap ); + if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap ); - updateBefore( { renderer } ) { + if ( json.anisotropyMap !== undefined ) material.anisotropyMap = getTexture( json.anisotropyMap ); - renderer.compute( this ); + if ( json.sheenColorMap !== undefined ) material.sheenColorMap = getTexture( json.sheenColorMap ); + if ( json.sheenRoughnessMap !== undefined ) material.sheenRoughnessMap = getTexture( json.sheenRoughnessMap ); + + return material; } - generate( builder ) { + setTextures( value ) { - const { shaderStage } = builder; + this.textures = value; + return this; - if ( shaderStage === 'compute' ) { + } - const snippet = this.computeNode.build( builder, 'void' ); + createMaterialFromType( type ) { - if ( snippet !== '' ) { + return MaterialLoader.createMaterialFromType( type ); - builder.addLineFlowCode( snippet ); + } - } + static createMaterialFromType( type ) { - } + const materialLib = { + ShadowMaterial, + SpriteMaterial, + RawShaderMaterial, + ShaderMaterial, + PointsMaterial, + MeshPhysicalMaterial, + MeshStandardMaterial, + MeshPhongMaterial, + MeshToonMaterial, + MeshNormalMaterial, + MeshLambertMaterial, + MeshDepthMaterial, + MeshDistanceMaterial, + MeshBasicMaterial, + MeshMatcapMaterial, + LineDashedMaterial, + LineBasicMaterial, + Material + }; + + return new materialLib[ type ](); } } -ComputeNode.type = /*@__PURE__*/ registerNode( 'Compute', ComputeNode ); - -const compute = ( node, count, workgroupSize ) => nodeObject( new ComputeNode( nodeObject( node ), count, workgroupSize ) ); +class LoaderUtils { -addMethodChaining( 'compute', compute ); + static decodeText( array ) { // @deprecated, r165 -class CacheNode extends Node { + console.warn( 'THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead.' ); - constructor( node, parent = true ) { + if ( typeof TextDecoder !== 'undefined' ) { - super(); + return new TextDecoder().decode( array ); - this.node = node; - this.parent = parent; + } - this.isCacheNode = true; + // Avoid the String.fromCharCode.apply(null, array) shortcut, which + // throws a "maximum call stack size exceeded" error for large arrays. - } + let s = ''; - getNodeType( builder ) { + for ( let i = 0, il = array.length; i < il; i ++ ) { - return this.node.getNodeType( builder ); + // Implicitly assumes little-endian. + s += String.fromCharCode( array[ i ] ); - } + } - build( builder, ...params ) { + try { - const previousCache = builder.getCache(); - const cache = builder.getCacheFromNode( this, parent ); + // merges multi-byte utf-8 characters. - builder.setCache( cache ); + return decodeURIComponent( escape( s ) ); - const data = this.node.build( builder, ...params ); + } catch ( e ) { // see #16358 - builder.setCache( previousCache ); + return s; - return data; + } } -} - -CacheNode.type = /*@__PURE__*/ registerNode( 'Cache', CacheNode ); - -const cache = ( node, ...params ) => nodeObject( new CacheNode( nodeObject( node ), ...params ) ); - -addMethodChaining( 'cache', cache ); - -class BypassNode extends Node { - - constructor( returnNode, callNode ) { + static extractUrlBase( url ) { - super(); + const index = url.lastIndexOf( '/' ); - this.isBypassNode = true; + if ( index === - 1 ) return './'; - this.outputNode = returnNode; - this.callNode = callNode; + return url.slice( 0, index + 1 ); } - getNodeType( builder ) { + static resolveURL( url, path ) { - return this.outputNode.getNodeType( builder ); + // Invalid URL + if ( typeof url !== 'string' || url === '' ) return ''; - } + // Host Relative URL + if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) { - generate( builder ) { + path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' ); - const snippet = this.callNode.build( builder, 'void' ); + } - if ( snippet !== '' ) { + // Absolute URL http://,https://,// + if ( /^(https?:)?\/\//i.test( url ) ) return url; - builder.addLineFlowCode( snippet ); + // Data URI + if ( /^data:.*,.*$/i.test( url ) ) return url; - } + // Blob URL + if ( /^blob:.*$/i.test( url ) ) return url; - return this.outputNode.build( builder ); + // Relative URL + return path + url; } } -BypassNode.type = /*@__PURE__*/ registerNode( 'Bypass', BypassNode ); +class InstancedBufferGeometry extends BufferGeometry { -const bypass = /*@__PURE__*/ nodeProxy( BypassNode ); + constructor() { -addMethodChaining( 'bypass', bypass ); + super(); -class RemapNode extends Node { + this.isInstancedBufferGeometry = true; - constructor( node, inLowNode, inHighNode, outLowNode = float( 0 ), outHighNode = float( 1 ) ) { + this.type = 'InstancedBufferGeometry'; + this.instanceCount = Infinity; - super(); + } - this.node = node; - this.inLowNode = inLowNode; - this.inHighNode = inHighNode; - this.outLowNode = outLowNode; - this.outHighNode = outHighNode; + copy( source ) { - this.doClamp = true; + super.copy( source ); + + this.instanceCount = source.instanceCount; + + return this; } - setup() { + toJSON() { - const { node, inLowNode, inHighNode, outLowNode, outHighNode, doClamp } = this; + const data = super.toJSON(); - let t = node.sub( inLowNode ).div( inHighNode.sub( inLowNode ) ); + data.instanceCount = this.instanceCount; - if ( doClamp === true ) t = t.clamp(); + data.isInstancedBufferGeometry = true; - return t.mul( outHighNode.sub( outLowNode ) ).add( outLowNode ); + return data; } } -RemapNode.type = /*@__PURE__*/ registerNode( 'Remap', RemapNode ); +class BufferGeometryLoader extends Loader { -const remap = /*@__PURE__*/ nodeProxy( RemapNode, null, null, { doClamp: false } ); -const remapClamp = /*@__PURE__*/ nodeProxy( RemapNode ); + constructor( manager ) { -addMethodChaining( 'remap', remap ); -addMethodChaining( 'remapClamp', remapClamp ); + super( manager ); -class ExpressionNode extends Node { + } - constructor( snippet = '', nodeType = 'void' ) { + load( url, onLoad, onProgress, onError ) { - super( nodeType ); + const scope = this; - this.snippet = snippet; + const loader = new FileLoader( scope.manager ); + loader.setPath( scope.path ); + loader.setRequestHeader( scope.requestHeader ); + loader.setWithCredentials( scope.withCredentials ); + loader.load( url, function ( text ) { - } + try { - generate( builder, output ) { + onLoad( scope.parse( JSON.parse( text ) ) ); - const type = this.getNodeType( builder ); - const snippet = this.snippet; + } catch ( e ) { - if ( type === 'void' ) { + if ( onError ) { - builder.addLineFlowCode( snippet ); + onError( e ); - } else { + } else { - return builder.format( `( ${ snippet } )`, type, output ); + console.error( e ); - } + } - } + scope.manager.itemError( url ); -} + } -ExpressionNode.type = /*@__PURE__*/ registerNode( 'Expression', ExpressionNode ); + }, onProgress, onError ); -const expression = /*@__PURE__*/ nodeProxy( ExpressionNode ); + } -const Discard = ( conditional ) => ( conditional ? select( conditional, expression( 'discard' ) ) : expression( 'discard' ) ).append(); -const Return = () => expression( 'return' ).append(); + parse( json ) { -addMethodChaining( 'discard', Discard ); + const interleavedBufferMap = {}; + const arrayBufferMap = {}; -class RenderOutputNode extends TempNode { + function getInterleavedBuffer( json, uuid ) { - constructor( colorNode, toneMapping, outputColorSpace ) { + if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ]; - super( 'vec4' ); + const interleavedBuffers = json.interleavedBuffers; + const interleavedBuffer = interleavedBuffers[ uuid ]; - this.colorNode = colorNode; - this.toneMapping = toneMapping; - this.outputColorSpace = outputColorSpace; + const buffer = getArrayBuffer( json, interleavedBuffer.buffer ); - this.isRenderOutput = true; + const array = getTypedArray( interleavedBuffer.type, buffer ); + const ib = new InterleavedBuffer( array, interleavedBuffer.stride ); + ib.uuid = interleavedBuffer.uuid; - } + interleavedBufferMap[ uuid ] = ib; - setup( { context } ) { + return ib; - let outputNode = this.colorNode || context.color; + } - // tone mapping + function getArrayBuffer( json, uuid ) { - const toneMapping = ( this.toneMapping !== null ? this.toneMapping : context.toneMapping ) || NoToneMapping; - const outputColorSpace = ( this.outputColorSpace !== null ? this.outputColorSpace : context.outputColorSpace ) || LinearSRGBColorSpace; + if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ]; - if ( toneMapping !== NoToneMapping ) { + const arrayBuffers = json.arrayBuffers; + const arrayBuffer = arrayBuffers[ uuid ]; - outputNode = outputNode.toneMapping( toneMapping ); + const ab = new Uint32Array( arrayBuffer ).buffer; - } + arrayBufferMap[ uuid ] = ab; - // output color space + return ab; - if ( outputColorSpace === SRGBColorSpace ) { + } - outputNode = outputNode.toOutputColorSpace( outputColorSpace ); + const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry(); - } + const index = json.data.index; - return outputNode; + if ( index !== undefined ) { - } + const typedArray = getTypedArray( index.type, index.array ); + geometry.setIndex( new BufferAttribute( typedArray, 1 ) ); -} + } -RenderOutputNode.type = /*@__PURE__*/ registerNode( 'RenderOutput', RenderOutputNode ); + const attributes = json.data.attributes; -const renderOutput = ( color, toneMapping = null, outputColorSpace = null ) => nodeObject( new RenderOutputNode( nodeObject( color ), toneMapping, outputColorSpace ) ); + for ( const key in attributes ) { -addMethodChaining( 'renderOutput', renderOutput ); + const attribute = attributes[ key ]; + let bufferAttribute; -// Non-PURE exports list, side-effects are required here. -// TSL Base Syntax + if ( attribute.isInterleavedBufferAttribute ) { + const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data ); + bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized ); -function addNodeElement( name/*, nodeElement*/ ) { + } else { - console.warn( 'THREE.TSLBase: AddNodeElement has been removed in favor of tree-shaking. Trying add', name ); + const typedArray = getTypedArray( attribute.type, attribute.array ); + const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute; + bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized ); -} + } -class AttributeNode extends Node { + if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name; + if ( attribute.usage !== undefined ) bufferAttribute.setUsage( attribute.usage ); - constructor( attributeName, nodeType = null ) { + geometry.setAttribute( key, bufferAttribute ); - super( nodeType ); + } - this.global = true; + const morphAttributes = json.data.morphAttributes; - this._attributeName = attributeName; + if ( morphAttributes ) { - } + for ( const key in morphAttributes ) { - getHash( builder ) { + const attributeArray = morphAttributes[ key ]; - return this.getAttributeName( builder ); + const array = []; - } + for ( let i = 0, il = attributeArray.length; i < il; i ++ ) { - getNodeType( builder ) { + const attribute = attributeArray[ i ]; + let bufferAttribute; - let nodeType = this.nodeType; + if ( attribute.isInterleavedBufferAttribute ) { - if ( nodeType === null ) { + const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data ); + bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized ); - const attributeName = this.getAttributeName( builder ); + } else { - if ( builder.hasGeometryAttribute( attributeName ) ) { + const typedArray = getTypedArray( attribute.type, attribute.array ); + bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ); - const attribute = builder.geometry.getAttribute( attributeName ); + } - nodeType = builder.getTypeFromAttribute( attribute ); + if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name; + array.push( bufferAttribute ); - } else { + } - nodeType = 'float'; + geometry.morphAttributes[ key ] = array; } } - return nodeType; - - } - - setAttributeName( attributeName ) { - - this._attributeName = attributeName; + const morphTargetsRelative = json.data.morphTargetsRelative; - return this; + if ( morphTargetsRelative ) { - } + geometry.morphTargetsRelative = true; - getAttributeName( /*builder*/ ) { + } - return this._attributeName; + const groups = json.data.groups || json.data.drawcalls || json.data.offsets; - } + if ( groups !== undefined ) { - generate( builder ) { + for ( let i = 0, n = groups.length; i !== n; ++ i ) { - const attributeName = this.getAttributeName( builder ); - const nodeType = this.getNodeType( builder ); - const geometryAttribute = builder.hasGeometryAttribute( attributeName ); + const group = groups[ i ]; - if ( geometryAttribute === true ) { + geometry.addGroup( group.start, group.count, group.materialIndex ); - const attribute = builder.geometry.getAttribute( attributeName ); - const attributeType = builder.getTypeFromAttribute( attribute ); + } - const nodeAttribute = builder.getAttribute( attributeName, attributeType ); + } - if ( builder.shaderStage === 'vertex' ) { + const boundingSphere = json.data.boundingSphere; - return builder.format( nodeAttribute.name, attributeType, nodeType ); + if ( boundingSphere !== undefined ) { - } else { + const center = new Vector3(); - const nodeVarying = varying( this ); + if ( boundingSphere.center !== undefined ) { - return nodeVarying.build( builder, nodeType ); + center.fromArray( boundingSphere.center ); } - } else { + geometry.boundingSphere = new Sphere( center, boundingSphere.radius ); - console.warn( `AttributeNode: Vertex attribute "${ attributeName }" not found on geometry.` ); + } - return builder.generateConst( nodeType ); + if ( json.name ) geometry.name = json.name; + if ( json.userData ) geometry.userData = json.userData; - } + return geometry; } - serialize( data ) { +} - super.serialize( data ); +class ObjectLoader extends Loader { - data.global = this.global; - data._attributeName = this._attributeName; + constructor( manager ) { - } + super( manager ); - deserialize( data ) { + } - super.deserialize( data ); + load( url, onLoad, onProgress, onError ) { - this.global = data.global; - this._attributeName = data._attributeName; + const scope = this; - } + const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; + this.resourcePath = this.resourcePath || path; -} + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + loader.load( url, function ( text ) { -AttributeNode.type = /*@__PURE__*/ registerNode( 'Attribute', AttributeNode ); + let json = null; -const attribute = ( name, nodeType ) => nodeObject( new AttributeNode( name, nodeType ) ); + try { -const uv = ( index ) => attribute( 'uv' + ( index > 0 ? index : '' ), 'vec2' ); + json = JSON.parse( text ); -class TextureSizeNode extends Node { + } catch ( error ) { - constructor( textureNode, levelNode = null ) { + if ( onError !== undefined ) onError( error ); - super( 'uvec2' ); + console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message ); - this.isTextureSizeNode = true; + return; - this.textureNode = textureNode; - this.levelNode = levelNode; + } - } + const metadata = json.metadata; - generate( builder, output ) { + if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { - const textureProperty = this.textureNode.build( builder, 'property' ); - const levelNode = this.levelNode.build( builder, 'int' ); + if ( onError !== undefined ) onError( new Error( 'THREE.ObjectLoader: Can\'t load ' + url ) ); - return builder.format( `${ builder.getMethod( 'textureDimensions' ) }( ${ textureProperty }, ${ levelNode } )`, this.getNodeType( builder ), output ); + console.error( 'THREE.ObjectLoader: Can\'t load ' + url ); + return; - } + } -} + scope.parse( json, onLoad ); -TextureSizeNode.type = /*@__PURE__*/ registerNode( 'TextureSize', TextureSizeNode ); + }, onProgress, onError ); -const textureSize = /*@__PURE__*/ nodeProxy( TextureSizeNode ); + } -class MaxMipLevelNode extends UniformNode { + async loadAsync( url, onProgress ) { - constructor( textureNode ) { + const scope = this; - super( 0 ); + const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; + this.resourcePath = this.resourcePath || path; - this._textureNode = textureNode; + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); - this.updateType = NodeUpdateType.FRAME; + const text = await loader.loadAsync( url, onProgress ); - } + const json = JSON.parse( text ); - get textureNode() { + const metadata = json.metadata; - return this._textureNode; + if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { - } + throw new Error( 'THREE.ObjectLoader: Can\'t load ' + url ); - get texture() { + } - return this._textureNode.value; + return await scope.parseAsync( json ); } - update() { + parse( json, onLoad ) { - const texture = this.texture; - const images = texture.images; - const image = ( images && images.length > 0 ) ? ( ( images[ 0 ] && images[ 0 ].image ) || images[ 0 ] ) : texture.image; + const animations = this.parseAnimations( json.animations ); + const shapes = this.parseShapes( json.shapes ); + const geometries = this.parseGeometries( json.geometries, shapes ); - if ( image && image.width !== undefined ) { + const images = this.parseImages( json.images, function () { - const { width, height } = image; + if ( onLoad !== undefined ) onLoad( object ); - this.value = Math.log2( Math.max( width, height ) ); + } ); - } + const textures = this.parseTextures( json.textures, images ); + const materials = this.parseMaterials( json.materials, textures ); - } + const object = this.parseObject( json.object, geometries, materials, textures, animations ); + const skeletons = this.parseSkeletons( json.skeletons, object ); -} + this.bindSkeletons( object, skeletons ); + this.bindLightTargets( object ); -MaxMipLevelNode.type = /*@__PURE__*/ registerNode( 'MaxMipLevel', MaxMipLevelNode ); + // -const maxMipLevel = /*@__PURE__*/ nodeProxy( MaxMipLevelNode ); + if ( onLoad !== undefined ) { -class TextureNode extends UniformNode { + let hasImages = false; - constructor( value, uvNode = null, levelNode = null, biasNode = null ) { + for ( const uuid in images ) { - super( value ); + if ( images[ uuid ].data instanceof HTMLImageElement ) { - this.isTextureNode = true; + hasImages = true; + break; - this.uvNode = uvNode; - this.levelNode = levelNode; - this.biasNode = biasNode; - this.compareNode = null; - this.depthNode = null; - this.gradNode = null; + } - this.sampler = true; - this.updateMatrix = false; - this.updateType = NodeUpdateType.NONE; + } - this.referenceNode = null; + if ( hasImages === false ) onLoad( object ); - this._value = value; - this._matrixUniform = null; + } - this.setUpdateMatrix( uvNode === null ); + return object; } - set value( value ) { + async parseAsync( json ) { - if ( this.referenceNode ) { + const animations = this.parseAnimations( json.animations ); + const shapes = this.parseShapes( json.shapes ); + const geometries = this.parseGeometries( json.geometries, shapes ); - this.referenceNode.value = value; + const images = await this.parseImagesAsync( json.images ); - } else { + const textures = this.parseTextures( json.textures, images ); + const materials = this.parseMaterials( json.materials, textures ); - this._value = value; + const object = this.parseObject( json.object, geometries, materials, textures, animations ); + const skeletons = this.parseSkeletons( json.skeletons, object ); - } + this.bindSkeletons( object, skeletons ); + this.bindLightTargets( object ); + + return object; } - get value() { + parseShapes( json ) { - return this.referenceNode ? this.referenceNode.value : this._value; + const shapes = {}; - } + if ( json !== undefined ) { - getUniformHash( /*builder*/ ) { + for ( let i = 0, l = json.length; i < l; i ++ ) { - return this.value.uuid; + const shape = new Shape().fromJSON( json[ i ] ); - } + shapes[ shape.uuid ] = shape; - getNodeType( /*builder*/ ) { + } - if ( this.value.isDepthTexture === true ) return 'float'; + } - if ( this.value.type === UnsignedIntType ) { + return shapes; - return 'uvec4'; + } - } else if ( this.value.type === IntType ) { + parseSkeletons( json, object ) { - return 'ivec4'; + const skeletons = {}; + const bones = {}; - } + // generate bone lookup table - return 'vec4'; + object.traverse( function ( child ) { - } + if ( child.isBone ) bones[ child.uuid ] = child; - getInputType( /*builder*/ ) { + } ); - return 'texture'; + // create skeletons - } + if ( json !== undefined ) { - getDefaultUV() { + for ( let i = 0, l = json.length; i < l; i ++ ) { - return uv( this.value.channel ); + const skeleton = new Skeleton().fromJSON( json[ i ], bones ); - } + skeletons[ skeleton.uuid ] = skeleton; - updateReference( /*state*/ ) { + } - return this.value; + } - } + return skeletons; - getTransformedUV( uvNode ) { + } - if ( this._matrixUniform === null ) this._matrixUniform = uniform( this.value.matrix ); + parseGeometries( json, shapes ) { - return this._matrixUniform.mul( vec3( uvNode, 1 ) ).xy; + const geometries = {}; - } + if ( json !== undefined ) { - setUpdateMatrix( value ) { + const bufferGeometryLoader = new BufferGeometryLoader(); - this.updateMatrix = value; - this.updateType = value ? NodeUpdateType.FRAME : NodeUpdateType.NONE; + for ( let i = 0, l = json.length; i < l; i ++ ) { - return this; + let geometry; + const data = json[ i ]; - } + switch ( data.type ) { - setupUV( builder, uvNode ) { + case 'BufferGeometry': + case 'InstancedBufferGeometry': - const texture = this.value; + geometry = bufferGeometryLoader.parse( data ); + break; - if ( builder.isFlipY() && ( texture.isRenderTargetTexture === true || texture.isFramebufferTexture === true || texture.isDepthTexture === true ) ) { + default: - uvNode = uvNode.setY( uvNode.y.oneMinus() ); + if ( data.type in Geometries$1 ) { - } + geometry = Geometries$1[ data.type ].fromJSON( data, shapes ); - return uvNode; + } else { - } + console.warn( `THREE.ObjectLoader: Unsupported geometry type "${ data.type }"` ); - setup( builder ) { + } - const properties = builder.getNodeProperties( this ); - properties.referenceNode = this.referenceNode; + } - // + geometry.uuid = data.uuid; - let uvNode = this.uvNode; + if ( data.name !== undefined ) geometry.name = data.name; + if ( data.userData !== undefined ) geometry.userData = data.userData; - if ( ( uvNode === null || builder.context.forceUVContext === true ) && builder.context.getUV ) { + geometries[ data.uuid ] = geometry; - uvNode = builder.context.getUV( this ); + } } - if ( ! uvNode ) uvNode = this.getDefaultUV(); + return geometries; - if ( this.updateMatrix === true ) { + } - uvNode = this.getTransformedUV( uvNode ); + parseMaterials( json, textures ) { - } + const cache = {}; // MultiMaterial + const materials = {}; - uvNode = this.setupUV( builder, uvNode ); + if ( json !== undefined ) { - // + const loader = new MaterialLoader(); + loader.setTextures( textures ); - let levelNode = this.levelNode; + for ( let i = 0, l = json.length; i < l; i ++ ) { - if ( levelNode === null && builder.context.getTextureLevel ) { + const data = json[ i ]; - levelNode = builder.context.getTextureLevel( this ); + if ( cache[ data.uuid ] === undefined ) { - } + cache[ data.uuid ] = loader.parse( data ); - // + } - properties.uvNode = uvNode; - properties.levelNode = levelNode; - properties.biasNode = this.biasNode; - properties.compareNode = this.compareNode; - properties.gradNode = this.gradNode; - properties.depthNode = this.depthNode; + materials[ data.uuid ] = cache[ data.uuid ]; - } + } - generateUV( builder, uvNode ) { + } - return uvNode.build( builder, this.sampler === true ? 'vec2' : 'ivec2' ); + return materials; } - generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, biasSnippet, depthSnippet, compareSnippet, gradSnippet ) { - - const texture = this.value; - - let snippet; + parseAnimations( json ) { - if ( levelSnippet ) { + const animations = {}; - snippet = builder.generateTextureLevel( texture, textureProperty, uvSnippet, levelSnippet, depthSnippet ); + if ( json !== undefined ) { - } else if ( biasSnippet ) { + for ( let i = 0; i < json.length; i ++ ) { - snippet = builder.generateTextureBias( texture, textureProperty, uvSnippet, biasSnippet, depthSnippet ); + const data = json[ i ]; - } else if ( gradSnippet ) { + const clip = AnimationClip.parse( data ); - snippet = builder.generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet, depthSnippet ); + animations[ clip.uuid ] = clip; - } else if ( compareSnippet ) { + } - snippet = builder.generateTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, depthSnippet ); + } - } else if ( this.sampler === false ) { + return animations; - snippet = builder.generateTextureLoad( texture, textureProperty, uvSnippet, depthSnippet ); + } - } else { + parseImages( json, onLoad ) { - snippet = builder.generateTexture( texture, textureProperty, uvSnippet, depthSnippet ); + const scope = this; + const images = {}; - } + let loader; - return snippet; + function loadImage( url ) { - } + scope.manager.itemStart( url ); - generate( builder, output ) { + return loader.load( url, function () { - const properties = builder.getNodeProperties( this ); + scope.manager.itemEnd( url ); - const texture = this.value; + }, undefined, function () { - if ( ! texture || texture.isTexture !== true ) { + scope.manager.itemError( url ); + scope.manager.itemEnd( url ); - throw new Error( 'TextureNode: Need a three.js texture.' ); + } ); } - const textureProperty = super.generate( builder, 'property' ); - - if ( output === 'sampler' ) { + function deserializeImage( image ) { - return textureProperty + '_sampler'; + if ( typeof image === 'string' ) { - } else if ( builder.isReference( output ) ) { + const url = image; - return textureProperty; + const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url; - } else { + return loadImage( path ); - const nodeData = builder.getDataFromNode( this ); + } else { - let propertyName = nodeData.propertyName; + if ( image.data ) { - if ( propertyName === undefined ) { + return { + data: getTypedArray( image.type, image.data ), + width: image.width, + height: image.height + }; - const { uvNode, levelNode, biasNode, compareNode, depthNode, gradNode } = properties; + } else { - const uvSnippet = this.generateUV( builder, uvNode ); - const levelSnippet = levelNode ? levelNode.build( builder, 'float' ) : null; - const biasSnippet = biasNode ? biasNode.build( builder, 'float' ) : null; - const depthSnippet = depthNode ? depthNode.build( builder, 'int' ) : null; - const compareSnippet = compareNode ? compareNode.build( builder, 'float' ) : null; - const gradSnippet = gradNode ? [ gradNode[ 0 ].build( builder, 'vec2' ), gradNode[ 1 ].build( builder, 'vec2' ) ] : null; + return null; - const nodeVar = builder.getVarFromNode( this ); + } - propertyName = builder.getPropertyName( nodeVar ); + } - const snippet = this.generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, biasSnippet, depthSnippet, compareSnippet, gradSnippet ); + } - builder.addLineFlowCode( `${propertyName} = ${snippet}` ); + if ( json !== undefined && json.length > 0 ) { - nodeData.snippet = snippet; - nodeData.propertyName = propertyName; + const manager = new LoadingManager( onLoad ); - } + loader = new ImageLoader( manager ); + loader.setCrossOrigin( this.crossOrigin ); - let snippet = propertyName; - const nodeType = this.getNodeType( builder ); + for ( let i = 0, il = json.length; i < il; i ++ ) { - if ( builder.needsToWorkingColorSpace( texture ) ) { + const image = json[ i ]; + const url = image.url; - snippet = toWorkingColorSpace( expression( snippet, nodeType ), texture.colorSpace ).setup( builder ).build( builder, nodeType ); + if ( Array.isArray( url ) ) { - } + // load array of images e.g CubeTexture - return builder.format( snippet, nodeType, output ); + const imageArray = []; - } + for ( let j = 0, jl = url.length; j < jl; j ++ ) { - } + const currentUrl = url[ j ]; - setSampler( value ) { + const deserializedImage = deserializeImage( currentUrl ); - this.sampler = value; + if ( deserializedImage !== null ) { - return this; + if ( deserializedImage instanceof HTMLImageElement ) { - } + imageArray.push( deserializedImage ); - getSampler() { + } else { - return this.sampler; + // special case: handle array of data textures for cube textures - } + imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) ); - // @TODO: Move to TSL + } - uv( uvNode ) { + } - const textureNode = this.clone(); - textureNode.uvNode = nodeObject( uvNode ); - textureNode.referenceNode = this.getSelf(); + } - return nodeObject( textureNode ); + images[ image.uuid ] = new Source( imageArray ); - } + } else { - blur( amountNode ) { + // load single image - const textureNode = this.clone(); - textureNode.biasNode = nodeObject( amountNode ).mul( maxMipLevel( textureNode ) ); - textureNode.referenceNode = this.getSelf(); + const deserializedImage = deserializeImage( image.url ); + images[ image.uuid ] = new Source( deserializedImage ); - return nodeObject( textureNode ); - } + } - level( levelNode ) { + } - const textureNode = this.clone(); - textureNode.levelNode = nodeObject( levelNode ); - textureNode.referenceNode = this.getSelf(); + } - return nodeObject( textureNode ); + return images; } - size( levelNode ) { + async parseImagesAsync( json ) { - return textureSize( this, levelNode ); + const scope = this; + const images = {}; - } + let loader; - bias( biasNode ) { + async function deserializeImage( image ) { - const textureNode = this.clone(); - textureNode.biasNode = nodeObject( biasNode ); - textureNode.referenceNode = this.getSelf(); + if ( typeof image === 'string' ) { - return nodeObject( textureNode ); + const url = image; - } + const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url; - compare( compareNode ) { + return await loader.loadAsync( path ); - const textureNode = this.clone(); - textureNode.compareNode = nodeObject( compareNode ); - textureNode.referenceNode = this.getSelf(); + } else { - return nodeObject( textureNode ); + if ( image.data ) { - } + return { + data: getTypedArray( image.type, image.data ), + width: image.width, + height: image.height + }; - grad( gradNodeX, gradNodeY ) { + } else { - const textureNode = this.clone(); - textureNode.gradNode = [ nodeObject( gradNodeX ), nodeObject( gradNodeY ) ]; - textureNode.referenceNode = this.getSelf(); + return null; - return nodeObject( textureNode ); + } - } + } - depth( depthNode ) { + } - const textureNode = this.clone(); - textureNode.depthNode = nodeObject( depthNode ); - textureNode.referenceNode = this.getSelf(); + if ( json !== undefined && json.length > 0 ) { - return nodeObject( textureNode ); + loader = new ImageLoader( this.manager ); + loader.setCrossOrigin( this.crossOrigin ); - } + for ( let i = 0, il = json.length; i < il; i ++ ) { - // -- + const image = json[ i ]; + const url = image.url; - serialize( data ) { + if ( Array.isArray( url ) ) { - super.serialize( data ); + // load array of images e.g CubeTexture - data.value = this.value.toJSON( data.meta ).uuid; - data.sampler = this.sampler; - data.updateMatrix = this.updateMatrix; - data.updateType = this.updateType; + const imageArray = []; - } + for ( let j = 0, jl = url.length; j < jl; j ++ ) { - deserialize( data ) { + const currentUrl = url[ j ]; - super.deserialize( data ); + const deserializedImage = await deserializeImage( currentUrl ); - this.value = data.meta.textures[ data.value ]; - this.sampler = data.sampler; - this.updateMatrix = data.updateMatrix; - this.updateType = data.updateType; + if ( deserializedImage !== null ) { - } + if ( deserializedImage instanceof HTMLImageElement ) { - update() { + imageArray.push( deserializedImage ); - const texture = this.value; - const matrixUniform = this._matrixUniform; + } else { - if ( matrixUniform !== null ) matrixUniform.value = texture.matrix; + // special case: handle array of data textures for cube textures - if ( texture.matrixAutoUpdate === true ) { + imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) ); - texture.updateMatrix(); + } - } + } - } + } - clone() { + images[ image.uuid ] = new Source( imageArray ); - const newNode = new this.constructor( this.value, this.uvNode, this.levelNode, this.biasNode ); - newNode.sampler = this.sampler; + } else { - return newNode; + // load single image - } + const deserializedImage = await deserializeImage( image.url ); + images[ image.uuid ] = new Source( deserializedImage ); -} + } -TextureNode.type = /*@__PURE__*/ registerNode( 'Texture', TextureNode ); + } -const texture = /*@__PURE__*/ nodeProxy( TextureNode ); -const textureLoad = ( ...params ) => texture( ...params ).setSampler( false ); + } -//export const textureLevel = ( value, uv, level ) => texture( value, uv ).level( level ); + return images; -const sampler = ( aTexture ) => ( aTexture.isNode === true ? aTexture : texture( aTexture ) ).convert( 'sampler' ); + } -const cameraGroup = /*@__PURE__*/ sharedUniformGroup( 'camera' ).onRenderUpdate( () => { + parseTextures( json, images ) { - cameraGroup.needsUpdate = true; + function parseConstant( value, type ) { -} ); + if ( typeof value === 'number' ) return value; -const cameraNear = /*@__PURE__*/ uniform( 'float' ).label( 'cameraNear' ).setGroup( cameraGroup ).onRenderUpdate( ( { camera } ) => camera.near ); -const cameraFar = /*@__PURE__*/ uniform( 'float' ).label( 'cameraFar' ).setGroup( cameraGroup ).onRenderUpdate( ( { camera } ) => camera.far ); -const cameraLogDepth = /*@__PURE__*/ uniform( 'float' ).label( 'cameraLogDepth' ).setGroup( cameraGroup ).onRenderUpdate( ( { camera } ) => 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); -const cameraProjectionMatrix = /*@__PURE__*/ uniform( 'mat4' ).label( 'cameraProjectionMatrix' ).setGroup( cameraGroup ).onRenderUpdate( ( { camera } ) => camera.projectionMatrix ); -const cameraProjectionMatrixInverse = /*@__PURE__*/ uniform( 'mat4' ).label( 'cameraProjectionMatrixInverse' ).setGroup( cameraGroup ).onRenderUpdate( ( { camera } ) => camera.projectionMatrixInverse ); -const cameraViewMatrix = /*@__PURE__*/ uniform( 'mat4' ).label( 'cameraViewMatrix' ).setGroup( cameraGroup ).onRenderUpdate( ( { camera } ) => camera.matrixWorldInverse ); -const cameraWorldMatrix = /*@__PURE__*/ uniform( 'mat4' ).label( 'cameraWorldMatrix' ).setGroup( cameraGroup ).onRenderUpdate( ( { camera } ) => camera.matrixWorld ); -const cameraNormalMatrix = /*@__PURE__*/ uniform( 'mat3' ).label( 'cameraNormalMatrix' ).setGroup( cameraGroup ).onRenderUpdate( ( { camera } ) => camera.normalMatrix ); -const cameraPosition = /*@__PURE__*/ uniform( new Vector3() ).label( 'cameraPosition' ).setGroup( cameraGroup ).onRenderUpdate( ( { camera }, self ) => self.value.setFromMatrixPosition( camera.matrixWorld ) ); + console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value ); -class Object3DNode extends Node { + return type[ value ]; - constructor( scope = Object3DNode.VIEW_MATRIX, object3d = null ) { + } - super(); + const textures = {}; - this.scope = scope; - this.object3d = object3d; + if ( json !== undefined ) { - this.updateType = NodeUpdateType.OBJECT; + for ( let i = 0, l = json.length; i < l; i ++ ) { - this._uniformNode = new UniformNode( null ); + const data = json[ i ]; - } + if ( data.image === undefined ) { - getNodeType() { + console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid ); - const scope = this.scope; + } - if ( scope === Object3DNode.WORLD_MATRIX || scope === Object3DNode.VIEW_MATRIX ) { + if ( images[ data.image ] === undefined ) { - return 'mat4'; + console.warn( 'THREE.ObjectLoader: Undefined image', data.image ); - } else if ( scope === Object3DNode.NORMAL_MATRIX ) { + } - return 'mat3'; + const source = images[ data.image ]; + const image = source.data; - } else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION || scope === Object3DNode.SCALE ) { + let texture; - return 'vec3'; + if ( Array.isArray( image ) ) { - } + texture = new CubeTexture(); - } + if ( image.length === 6 ) texture.needsUpdate = true; - update( frame ) { + } else { - const object = this.object3d; - const uniformNode = this._uniformNode; - const scope = this.scope; + if ( image && image.data ) { - if ( scope === Object3DNode.VIEW_MATRIX ) { + texture = new DataTexture(); - uniformNode.value = object.modelViewMatrix; + } else { - } else if ( scope === Object3DNode.NORMAL_MATRIX ) { + texture = new Texture(); - uniformNode.value = object.normalMatrix; + } - } else if ( scope === Object3DNode.WORLD_MATRIX ) { + if ( image ) texture.needsUpdate = true; // textures can have undefined image data - uniformNode.value = object.matrixWorld; + } - } else if ( scope === Object3DNode.POSITION ) { + texture.source = source; - uniformNode.value = uniformNode.value || new Vector3(); + texture.uuid = data.uuid; - uniformNode.value.setFromMatrixPosition( object.matrixWorld ); + if ( data.name !== undefined ) texture.name = data.name; - } else if ( scope === Object3DNode.SCALE ) { + if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); + if ( data.channel !== undefined ) texture.channel = data.channel; - uniformNode.value = uniformNode.value || new Vector3(); + if ( data.offset !== undefined ) texture.offset.fromArray( data.offset ); + if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat ); + if ( data.center !== undefined ) texture.center.fromArray( data.center ); + if ( data.rotation !== undefined ) texture.rotation = data.rotation; - uniformNode.value.setFromMatrixScale( object.matrixWorld ); + if ( data.wrap !== undefined ) { - } else if ( scope === Object3DNode.DIRECTION ) { + texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING ); + texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING ); - uniformNode.value = uniformNode.value || new Vector3(); + } - object.getWorldDirection( uniformNode.value ); + if ( data.format !== undefined ) texture.format = data.format; + if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat; + if ( data.type !== undefined ) texture.type = data.type; + if ( data.colorSpace !== undefined ) texture.colorSpace = data.colorSpace; - } else if ( scope === Object3DNode.VIEW_POSITION ) { + if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); + if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); + if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy; - const camera = frame.camera; + if ( data.flipY !== undefined ) texture.flipY = data.flipY; - uniformNode.value = uniformNode.value || new Vector3(); - uniformNode.value.setFromMatrixPosition( object.matrixWorld ); + if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps; + if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha; + if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment; + if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction; - uniformNode.value.applyMatrix4( camera.matrixWorldInverse ); + if ( data.userData !== undefined ) texture.userData = data.userData; + + textures[ data.uuid ] = texture; + + } } - } + return textures; - generate( builder ) { + } - const scope = this.scope; + parseObject( data, geometries, materials, textures, animations ) { - if ( scope === Object3DNode.WORLD_MATRIX || scope === Object3DNode.VIEW_MATRIX ) { + let object; - this._uniformNode.nodeType = 'mat4'; + function getGeometry( name ) { - } else if ( scope === Object3DNode.NORMAL_MATRIX ) { + if ( geometries[ name ] === undefined ) { - this._uniformNode.nodeType = 'mat3'; + console.warn( 'THREE.ObjectLoader: Undefined geometry', name ); - } else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION || scope === Object3DNode.SCALE ) { + } - this._uniformNode.nodeType = 'vec3'; + return geometries[ name ]; } - return this._uniformNode.build( builder ); + function getMaterial( name ) { - } + if ( name === undefined ) return undefined; - serialize( data ) { + if ( Array.isArray( name ) ) { - super.serialize( data ); + const array = []; - data.scope = this.scope; + for ( let i = 0, l = name.length; i < l; i ++ ) { - } + const uuid = name[ i ]; - deserialize( data ) { + if ( materials[ uuid ] === undefined ) { - super.deserialize( data ); + console.warn( 'THREE.ObjectLoader: Undefined material', uuid ); - this.scope = data.scope; + } - } + array.push( materials[ uuid ] ); -} + } -Object3DNode.VIEW_MATRIX = 'viewMatrix'; -Object3DNode.NORMAL_MATRIX = 'normalMatrix'; -Object3DNode.WORLD_MATRIX = 'worldMatrix'; -Object3DNode.POSITION = 'position'; -Object3DNode.SCALE = 'scale'; -Object3DNode.VIEW_POSITION = 'viewPosition'; -Object3DNode.DIRECTION = 'direction'; + return array; -Object3DNode.type = /*@__PURE__*/ registerNode( 'Object3D', Object3DNode ); + } -const objectDirection = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.DIRECTION ); -const objectViewMatrix = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.VIEW_MATRIX ); -const objectNormalMatrix = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.NORMAL_MATRIX ); -const objectWorldMatrix = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.WORLD_MATRIX ); -const objectPosition = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.POSITION ); -const objectScale = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.SCALE ); -const objectViewPosition = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.VIEW_POSITION ); + if ( materials[ name ] === undefined ) { -class ModelNode extends Object3DNode { + console.warn( 'THREE.ObjectLoader: Undefined material', name ); - constructor( scope = ModelNode.VIEW_MATRIX ) { + } - super( scope ); + return materials[ name ]; - } + } - update( frame ) { + function getTexture( uuid ) { - this.object3d = frame.object; + if ( textures[ uuid ] === undefined ) { - super.update( frame ); + console.warn( 'THREE.ObjectLoader: Undefined texture', uuid ); - } + } -} + return textures[ uuid ]; -ModelNode.type = /*@__PURE__*/ registerNode( 'Model', ModelNode ); + } -const modelDirection = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.DIRECTION ); -const modelViewMatrix = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.VIEW_MATRIX ).label( 'modelViewMatrix' ).toVar( 'ModelViewMatrix' ); -const modelNormalMatrix = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.NORMAL_MATRIX ); -const modelWorldMatrix = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.WORLD_MATRIX ); -const modelPosition = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.POSITION ); -const modelScale = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.SCALE ); -const modelViewPosition = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.VIEW_POSITION ); -const modelWorldMatrixInverse = /*@__PURE__*/ uniform( new Matrix4() ).onObjectUpdate( ( { object }, self ) => self.value.copy( object.matrixWorld ).invert() ); + let geometry, material; -const positionGeometry = /*@__PURE__*/ attribute( 'position', 'vec3' ); -const positionLocal = /*@__PURE__*/ positionGeometry.varying( 'positionLocal' ); -const positionPrevious = /*@__PURE__*/ positionGeometry.varying( 'positionPrevious' ); -const positionWorld = /*@__PURE__*/ modelWorldMatrix.mul( positionLocal ).xyz.varying( 'v_positionWorld' ); -const positionWorldDirection = /*@__PURE__*/ positionLocal.transformDirection( modelWorldMatrix ).varying( 'v_positionWorldDirection' ).normalize().toVar( 'positionWorldDirection' ); -const positionView = /*@__PURE__*/ modelViewMatrix.mul( positionLocal ).xyz.varying( 'v_positionView' ); -const positionViewDirection = /*@__PURE__*/ positionView.negate().varying( 'v_positionViewDirection' ).normalize().toVar( 'positionViewDirection' ); + switch ( data.type ) { -class FrontFacingNode extends Node { + case 'Scene': - constructor() { + object = new Scene(); - super( 'bool' ); + if ( data.background !== undefined ) { - this.isFrontFacingNode = true; + if ( Number.isInteger( data.background ) ) { - } + object.background = new Color( data.background ); - generate( builder ) { + } else { - const { renderer, material } = builder; + object.background = getTexture( data.background ); - if ( renderer.coordinateSystem === WebGLCoordinateSystem ) { + } - if ( material.side === BackSide ) { + } - return 'false'; + if ( data.environment !== undefined ) { - } + object.environment = getTexture( data.environment ); - } + } - return builder.getFrontFacing(); + if ( data.fog !== undefined ) { - } + if ( data.fog.type === 'Fog' ) { -} + object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far ); -FrontFacingNode.type = /*@__PURE__*/ registerNode( 'FrontFacing', FrontFacingNode ); + } else if ( data.fog.type === 'FogExp2' ) { -const frontFacing = /*@__PURE__*/ nodeImmutable( FrontFacingNode ); -const faceDirection = /*@__PURE__*/ float( frontFacing ).mul( 2.0 ).sub( 1.0 ); + object.fog = new FogExp2( data.fog.color, data.fog.density ); -const normalGeometry = /*@__PURE__*/ attribute( 'normal', 'vec3' ); + } -const normalLocal = /*@__PURE__*/ ( Fn( ( builder ) => { + if ( data.fog.name !== '' ) { - if ( builder.geometry.hasAttribute( 'normal' ) === false ) { + object.fog.name = data.fog.name; - console.warn( 'TSL.NormalNode: Vertex attribute "normal" not found on geometry.' ); + } - return vec3( 0, 1, 0 ); + } - } + if ( data.backgroundBlurriness !== undefined ) object.backgroundBlurriness = data.backgroundBlurriness; + if ( data.backgroundIntensity !== undefined ) object.backgroundIntensity = data.backgroundIntensity; + if ( data.backgroundRotation !== undefined ) object.backgroundRotation.fromArray( data.backgroundRotation ); - return normalGeometry; + if ( data.environmentIntensity !== undefined ) object.environmentIntensity = data.environmentIntensity; + if ( data.environmentRotation !== undefined ) object.environmentRotation.fromArray( data.environmentRotation ); -}, 'vec3' ).once() )().toVar( 'normalLocal' ); + break; -const normalFlat = /*@__PURE__*/ positionView.dFdx().cross( positionView.dFdy() ).normalize().toVar( 'normalFlat' ); + case 'PerspectiveCamera': -let normalViewVarying = null; + object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far ); -const normalView = /*@__PURE__*/ ( Fn( ( builder ) => { + if ( data.focus !== undefined ) object.focus = data.focus; + if ( data.zoom !== undefined ) object.zoom = data.zoom; + if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge; + if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset; + if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); - let node; + break; - if ( builder.material.flatShading === true ) { + case 'OrthographicCamera': - node = normalFlat; + object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far ); - } else { + if ( data.zoom !== undefined ) object.zoom = data.zoom; + if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); - node = normalViewVarying || ( normalViewVarying = varying( modelNormalMatrix.mul( normalLocal ), 'v_normalView' ).normalize() ); + break; - } + case 'AmbientLight': - return node; + object = new AmbientLight( data.color, data.intensity ); -}, 'vec3' ).once() )().toVar( 'normalView' ); + break; -const normalWorld = /*@__PURE__*/ varying( normalView.transformDirection( cameraViewMatrix ), 'v_normalWorld' ).normalize().toVar( 'normalWorld' ); + case 'DirectionalLight': -const transformedNormalView = /*@__PURE__*/ ( Fn( ( builder ) => { + object = new DirectionalLight( data.color, data.intensity ); + object.target = data.target || ''; - return builder.context.setupNormal(); + break; -}, 'vec3' ).once() )().mul( faceDirection ).toVar( 'transformedNormalView' ); + case 'PointLight': + object = new PointLight( data.color, data.intensity, data.distance, data.decay ); -const transformedNormalWorld = /*@__PURE__*/ transformedNormalView.transformDirection( cameraViewMatrix ).normalize().toVar( 'transformedNormalWorld' ); + break; -const transformedClearcoatNormalView = /*@__PURE__*/ ( Fn( ( builder ) => { + case 'RectAreaLight': - return builder.context.setupClearcoatNormal(); + object = new RectAreaLight( data.color, data.intensity, data.width, data.height ); -}, 'vec3' ).once() )().mul( faceDirection ).toVar( 'transformedClearcoatNormalView' ); + break; -const materialRefractionRatio = /*@__PURE__*/ uniform( 0 ).onReference( ( { material } ) => material ).onRenderUpdate( ( { material } ) => material.refractionRatio ); + case 'SpotLight': -const reflectView = /*@__PURE__*/ positionViewDirection.negate().reflect( transformedNormalView ); -const refractView = /*@__PURE__*/ positionViewDirection.negate().refract( transformedNormalView, materialRefractionRatio ); + object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay ); + object.target = data.target || ''; -const reflectVector = /*@__PURE__*/ reflectView.transformDirection( cameraViewMatrix ).toVar( 'reflectVector' ); -const refractVector = /*@__PURE__*/ refractView.transformDirection( cameraViewMatrix ).toVar( 'reflectVector' ); + break; -class CubeTextureNode extends TextureNode { + case 'HemisphereLight': - constructor( value, uvNode = null, levelNode = null, biasNode = null ) { + object = new HemisphereLight( data.color, data.groundColor, data.intensity ); - super( value, uvNode, levelNode, biasNode ); + break; - this.isCubeTextureNode = true; + case 'LightProbe': - } + object = new LightProbe().fromJSON( data ); - getInputType( /*builder*/ ) { + break; - return 'cubeTexture'; + case 'SkinnedMesh': - } + geometry = getGeometry( data.geometry ); + material = getMaterial( data.material ); - getDefaultUV() { + object = new SkinnedMesh( geometry, material ); - const texture = this.value; + if ( data.bindMode !== undefined ) object.bindMode = data.bindMode; + if ( data.bindMatrix !== undefined ) object.bindMatrix.fromArray( data.bindMatrix ); + if ( data.skeleton !== undefined ) object.skeleton = data.skeleton; - if ( texture.mapping === CubeReflectionMapping ) { + break; - return reflectVector; + case 'Mesh': - } else if ( texture.mapping === CubeRefractionMapping ) { + geometry = getGeometry( data.geometry ); + material = getMaterial( data.material ); - return refractVector; + object = new Mesh( geometry, material ); - } else { + break; - console.error( 'THREE.CubeTextureNode: Mapping "%s" not supported.', texture.mapping ); + case 'InstancedMesh': - return vec3( 0, 0, 0 ); + geometry = getGeometry( data.geometry ); + material = getMaterial( data.material ); + const count = data.count; + const instanceMatrix = data.instanceMatrix; + const instanceColor = data.instanceColor; - } + object = new InstancedMesh( geometry, material, count ); + object.instanceMatrix = new InstancedBufferAttribute( new Float32Array( instanceMatrix.array ), 16 ); + if ( instanceColor !== undefined ) object.instanceColor = new InstancedBufferAttribute( new Float32Array( instanceColor.array ), instanceColor.itemSize ); - } + break; - setUpdateMatrix( /*updateMatrix*/ ) { } // Ignore .updateMatrix for CubeTextureNode + case 'BatchedMesh': - setupUV( builder, uvNode ) { + geometry = getGeometry( data.geometry ); + material = getMaterial( data.material ); - const texture = this.value; + object = new BatchedMesh( data.maxInstanceCount, data.maxVertexCount, data.maxIndexCount, material ); + object.geometry = geometry; + object.perObjectFrustumCulled = data.perObjectFrustumCulled; + object.sortObjects = data.sortObjects; - if ( builder.renderer.coordinateSystem === WebGPUCoordinateSystem || ! texture.isRenderTargetTexture ) { + object._drawRanges = data.drawRanges; + object._reservedRanges = data.reservedRanges; - return vec3( uvNode.x.negate(), uvNode.yz ); + object._visibility = data.visibility; + object._active = data.active; + object._bounds = data.bounds.map( bound => { - } else { + const box = new Box3(); + box.min.fromArray( bound.boxMin ); + box.max.fromArray( bound.boxMax ); - return uvNode; + const sphere = new Sphere(); + sphere.radius = bound.sphereRadius; + sphere.center.fromArray( bound.sphereCenter ); - } + return { + boxInitialized: bound.boxInitialized, + box: box, - } + sphereInitialized: bound.sphereInitialized, + sphere: sphere + }; - generateUV( builder, cubeUV ) { + } ); - return cubeUV.build( builder, 'vec3' ); + object._maxInstanceCount = data.maxInstanceCount; + object._maxVertexCount = data.maxVertexCount; + object._maxIndexCount = data.maxIndexCount; - } + object._geometryInitialized = data.geometryInitialized; + object._geometryCount = data.geometryCount; -} + object._matricesTexture = getTexture( data.matricesTexture.uuid ); + if ( data.colorsTexture !== undefined ) object._colorsTexture = getTexture( data.colorsTexture.uuid ); -CubeTextureNode.type = /*@__PURE__*/ registerNode( 'CubeTexture', CubeTextureNode ); + break; -const cubeTexture = /*@__PURE__*/ nodeProxy( CubeTextureNode ); + case 'LOD': -class BufferNode extends UniformNode { + object = new LOD(); - constructor( value, bufferType, bufferCount = 0 ) { + break; - super( value, bufferType ); + case 'Line': - this.isBufferNode = true; + object = new Line( getGeometry( data.geometry ), getMaterial( data.material ) ); - this.bufferType = bufferType; - this.bufferCount = bufferCount; + break; - } + case 'LineLoop': - getElementType( builder ) { + object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) ); - return this.getNodeType( builder ); + break; - } + case 'LineSegments': - getInputType( /*builder*/ ) { + object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) ); - return 'buffer'; + break; - } + case 'PointCloud': + case 'Points': -} + object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) ); -BufferNode.type = /*@__PURE__*/ registerNode( 'Buffer', BufferNode ); + break; -const buffer = ( value, type, count ) => nodeObject( new BufferNode( value, type, count ) ); + case 'Sprite': -class UniformArrayElementNode extends ArrayElementNode { + object = new Sprite( getMaterial( data.material ) ); - constructor( arrayBuffer, indexNode ) { + break; - super( arrayBuffer, indexNode ); + case 'Group': - this.isArrayBufferElementNode = true; + object = new Group(); - } + break; - getNodeType( builder ) { + case 'Bone': - return this.node.getElementType( builder ); + object = new Bone(); - } + break; - generate( builder ) { + default: - const snippet = super.generate( builder ); - const type = this.getNodeType(); + object = new Object3D(); - return builder.format( snippet, 'vec4', type ); + } - } + object.uuid = data.uuid; -} + if ( data.name !== undefined ) object.name = data.name; -class UniformArrayNode extends BufferNode { + if ( data.matrix !== undefined ) { - constructor( value, elementType = null ) { + object.matrix.fromArray( data.matrix ); - super( null, 'vec4' ); + if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate; + if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale ); - this.array = value; - this.elementType = elementType; + } else { - this._elementType = null; - this._elementLength = 0; + if ( data.position !== undefined ) object.position.fromArray( data.position ); + if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation ); + if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion ); + if ( data.scale !== undefined ) object.scale.fromArray( data.scale ); - this.updateType = NodeUpdateType.RENDER; + } - this.isArrayBufferNode = true; + if ( data.up !== undefined ) object.up.fromArray( data.up ); - } + if ( data.castShadow !== undefined ) object.castShadow = data.castShadow; + if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow; - getElementType() { + if ( data.shadow ) { - return this.elementType || this._elementType; + if ( data.shadow.intensity !== undefined ) object.shadow.intensity = data.shadow.intensity; + if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias; + if ( data.shadow.normalBias !== undefined ) object.shadow.normalBias = data.shadow.normalBias; + if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius; + if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize ); + if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera ); - } + } - getElementLength() { + if ( data.visible !== undefined ) object.visible = data.visible; + if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled; + if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder; + if ( data.userData !== undefined ) object.userData = data.userData; + if ( data.layers !== undefined ) object.layers.mask = data.layers; - return this._elementLength; + if ( data.children !== undefined ) { - } + const children = data.children; - update( /*frame*/ ) { + for ( let i = 0; i < children.length; i ++ ) { - const { array, value } = this; + object.add( this.parseObject( children[ i ], geometries, materials, textures, animations ) ); - const elementLength = this.getElementLength(); - const elementType = this.getElementType(); + } - if ( elementLength === 1 ) { + } - for ( let i = 0; i < array.length; i ++ ) { + if ( data.animations !== undefined ) { - const index = i * 4; + const objectAnimations = data.animations; - value[ index ] = array[ i ]; + for ( let i = 0; i < objectAnimations.length; i ++ ) { + + const uuid = objectAnimations[ i ]; + + object.animations.push( animations[ uuid ] ); } - } else if ( elementType === 'color' ) { + } - for ( let i = 0; i < array.length; i ++ ) { + if ( data.type === 'LOD' ) { - const index = i * 4; - const vector = array[ i ]; + if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate; - value[ index ] = vector.r; - value[ index + 1 ] = vector.g; - value[ index + 2 ] = vector.b || 0; - //value[ index + 3 ] = vector.a || 0; + const levels = data.levels; - } + for ( let l = 0; l < levels.length; l ++ ) { - } else { + const level = levels[ l ]; + const child = object.getObjectByProperty( 'uuid', level.object ); - for ( let i = 0; i < array.length; i ++ ) { + if ( child !== undefined ) { - const index = i * 4; - const vector = array[ i ]; + object.addLevel( child, level.distance, level.hysteresis ); - value[ index ] = vector.x; - value[ index + 1 ] = vector.y; - value[ index + 2 ] = vector.z || 0; - value[ index + 3 ] = vector.w || 0; + } } } - } + return object; - setup( builder ) { + } - const length = this.array.length; + bindSkeletons( object, skeletons ) { - this._elementType = this.elementType === null ? getValueType( this.array[ 0 ] ) : this.elementType; - this._elementLength = builder.getTypeLength( this._elementType ); + if ( Object.keys( skeletons ).length === 0 ) return; - let arrayType = Float32Array; + object.traverse( function ( child ) { - if ( this._elementType.charAt( 0 ) === 'i' ) arrayType = Int32Array; - else if ( this._elementType.charAt( 0 ) === 'u' ) arrayType = Uint32Array; + if ( child.isSkinnedMesh === true && child.skeleton !== undefined ) { - this.value = new arrayType( length * 4 ); - this.bufferCount = length; - this.bufferType = builder.changeComponentType( 'vec4', builder.getComponentType( this._elementType ) ); + const skeleton = skeletons[ child.skeleton ]; - return super.setup( builder ); + if ( skeleton === undefined ) { - } + console.warn( 'THREE.ObjectLoader: No skeleton found with UUID:', child.skeleton ); - element( indexNode ) { + } else { - return nodeObject( new UniformArrayElementNode( this, nodeObject( indexNode ) ) ); + child.bind( skeleton, child.bindMatrix ); - } + } -} + } -UniformArrayNode.type = /*@__PURE__*/ registerNode( 'UniformArray', UniformArrayNode ); + } ); -const uniformArray = ( values, nodeType ) => nodeObject( new UniformArrayNode( values, nodeType ) ); + } -class ReferenceElementNode extends ArrayElementNode { + bindLightTargets( object ) { - constructor( referenceNode, indexNode ) { + object.traverse( function ( child ) { - super( referenceNode, indexNode ); + if ( child.isDirectionalLight || child.isSpotLight ) { - this.referenceNode = referenceNode; + const uuid = child.target; - this.isReferenceElementNode = true; + const target = object.getObjectByProperty( 'uuid', uuid ); - } + if ( target !== undefined ) { - getNodeType() { + child.target = target; - return this.referenceNode.uniformType; + } else { - } + child.target = new Object3D(); - generate( builder ) { + } - const snippet = super.generate( builder ); - const arrayType = this.referenceNode.getNodeType(); - const elementType = this.getNodeType(); + } - return builder.format( snippet, arrayType, elementType ); + } ); } } -// TODO: Extends this from ReferenceBaseNode -class ReferenceNode extends Node { +const TEXTURE_MAPPING = { + UVMapping: UVMapping, + CubeReflectionMapping: CubeReflectionMapping, + CubeRefractionMapping: CubeRefractionMapping, + EquirectangularReflectionMapping: EquirectangularReflectionMapping, + EquirectangularRefractionMapping: EquirectangularRefractionMapping, + CubeUVReflectionMapping: CubeUVReflectionMapping +}; - constructor( property, uniformType, object = null, count = null ) { +const TEXTURE_WRAPPING = { + RepeatWrapping: RepeatWrapping, + ClampToEdgeWrapping: ClampToEdgeWrapping, + MirroredRepeatWrapping: MirroredRepeatWrapping +}; - super(); +const TEXTURE_FILTER = { + NearestFilter: NearestFilter, + NearestMipmapNearestFilter: NearestMipmapNearestFilter, + NearestMipmapLinearFilter: NearestMipmapLinearFilter, + LinearFilter: LinearFilter, + LinearMipmapNearestFilter: LinearMipmapNearestFilter, + LinearMipmapLinearFilter: LinearMipmapLinearFilter +}; - this.property = property; - this.uniformType = uniformType; - this.object = object; - this.count = count; +class ImageBitmapLoader extends Loader { - this.properties = property.split( '.' ); - this.reference = object; - this.node = null; + constructor( manager ) { - this.updateType = NodeUpdateType.OBJECT; + super( manager ); - } + this.isImageBitmapLoader = true; - element( indexNode ) { + if ( typeof createImageBitmap === 'undefined' ) { - return nodeObject( new ReferenceElementNode( this, nodeObject( indexNode ) ) ); + console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' ); - } + } - setNodeType( uniformType ) { + if ( typeof fetch === 'undefined' ) { - let node = null; + console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' ); - if ( this.count !== null ) { + } - node = buffer( null, uniformType, this.count ); + this.options = { premultiplyAlpha: 'none' }; - } else if ( Array.isArray( this.getValueFromReference() ) ) { + } - node = uniformArray( null, uniformType ); + setOptions( options ) { - } else if ( uniformType === 'texture' ) { + this.options = options; - node = texture( null ); + return this; - } else if ( uniformType === 'cubeTexture' ) { + } - node = cubeTexture( null ); - - } else { + load( url, onLoad, onProgress, onError ) { - node = uniform( null, uniformType ); + if ( url === undefined ) url = ''; - } + if ( this.path !== undefined ) url = this.path + url; - this.node = node.getSelf(); + url = this.manager.resolveURL( url ); - } + const scope = this; - getNodeType( builder ) { + const cached = Cache.get( url ); - if ( this.node === null ) { + if ( cached !== undefined ) { - this.updateValue(); + scope.manager.itemStart( url ); - } + // If cached is a promise, wait for it to resolve + if ( cached.then ) { - return this.node.getNodeType( builder ); + cached.then( imageBitmap => { - } + if ( onLoad ) onLoad( imageBitmap ); - getValueFromReference( object = this.reference ) { + scope.manager.itemEnd( url ); - const { properties } = this; + } ).catch( e => { - let value = object[ properties[ 0 ] ]; + if ( onError ) onError( e ); - for ( let i = 1; i < properties.length; i ++ ) { + } ); + return; - value = value[ properties[ i ] ]; + } - } + // If cached is not a promise (i.e., it's already an imageBitmap) + setTimeout( function () { - return value; + if ( onLoad ) onLoad( cached ); - } + scope.manager.itemEnd( url ); - updateReference( state ) { + }, 0 ); - this.reference = this.object !== null ? this.object : state.object; + return cached; - return this.reference; + } - } + const fetchOptions = {}; + fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include'; + fetchOptions.headers = this.requestHeader; - setup() { + const promise = fetch( url, fetchOptions ).then( function ( res ) { - this.updateValue(); + return res.blob(); - return this.node; + } ).then( function ( blob ) { - } + return createImageBitmap( blob, Object.assign( scope.options, { colorSpaceConversion: 'none' } ) ); - update( /*frame*/ ) { + } ).then( function ( imageBitmap ) { - this.updateValue(); + Cache.add( url, imageBitmap ); - } + if ( onLoad ) onLoad( imageBitmap ); - updateValue() { + scope.manager.itemEnd( url ); - if ( this.node === null ) this.setNodeType( this.uniformType ); + return imageBitmap; - const value = this.getValueFromReference(); + } ).catch( function ( e ) { - if ( Array.isArray( value ) ) { + if ( onError ) onError( e ); - this.node.array = value; + Cache.remove( url ); - } else { + scope.manager.itemError( url ); + scope.manager.itemEnd( url ); - this.node.value = value; + } ); - } + Cache.add( url, promise ); + scope.manager.itemStart( url ); } } -ReferenceNode.type = /*@__PURE__*/ registerNode( 'Reference', ReferenceNode ); - -const reference = ( name, type, object ) => nodeObject( new ReferenceNode( name, type, object ) ); -const referenceBuffer = ( name, type, count, object ) => nodeObject( new ReferenceNode( name, type, object, count ) ); +let _context; -class MaterialReferenceNode extends ReferenceNode { +class AudioContext { - constructor( property, inputType, material = null ) { + static getContext() { - super( property, inputType, material ); + if ( _context === undefined ) { - this.material = material; + _context = new ( window.AudioContext || window.webkitAudioContext )(); - //this.updateType = NodeUpdateType.RENDER; + } - this.isMaterialReferenceNode = true; + return _context; } - /*setNodeType( node ) { - - super.setNodeType( node ); - - this.node.groupNode = renderGroup; - - }*/ - - updateReference( state ) { - - this.reference = this.material !== null ? this.material : state.material; + static setContext( value ) { - return this.reference; + _context = value; } } -MaterialReferenceNode.type = /*@__PURE__*/ registerNode( 'MaterialReference', MaterialReferenceNode ); +class AudioLoader extends Loader { -const materialReference = ( name, type, material ) => nodeObject( new MaterialReferenceNode( name, type, material ) ); + constructor( manager ) { -const tangentGeometry = /*@__PURE__*/ Fn( ( builder ) => { + super( manager ); - if ( builder.geometry.hasAttribute( 'tangent' ) === false ) { + } - builder.geometry.computeTangents(); + load( url, onLoad, onProgress, onError ) { - } + const scope = this; - return attribute( 'tangent', 'vec4' ); + const loader = new FileLoader( this.manager ); + loader.setResponseType( 'arraybuffer' ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + loader.load( url, function ( buffer ) { -} )(); + try { -const tangentLocal = /*@__PURE__*/ tangentGeometry.xyz.toVar( 'tangentLocal' ); -const tangentView = /*@__PURE__*/ modelViewMatrix.mul( vec4( tangentLocal, 0 ) ).xyz.varying( 'v_tangentView' ).normalize().toVar( 'tangentView' ); -const tangentWorld = /*@__PURE__*/ tangentView.transformDirection( cameraViewMatrix ).varying( 'v_tangentWorld' ).normalize().toVar( 'tangentWorld' ); -const transformedTangentView = /*@__PURE__*/ tangentView.toVar( 'transformedTangentView' ); -const transformedTangentWorld = /*@__PURE__*/ transformedTangentView.transformDirection( cameraViewMatrix ).normalize().toVar( 'transformedTangentWorld' ); + // Create a copy of the buffer. The `decodeAudioData` method + // detaches the buffer when complete, preventing reuse. + const bufferCopy = buffer.slice( 0 ); -const getBitangent = ( crossNormalTangent ) => crossNormalTangent.mul( tangentGeometry.w ).xyz; + const context = AudioContext.getContext(); + context.decodeAudioData( bufferCopy, function ( audioBuffer ) { -const bitangentGeometry = /*@__PURE__*/ varying( getBitangent( normalGeometry.cross( tangentGeometry ) ), 'v_bitangentGeometry' ).normalize().toVar( 'bitangentGeometry' ); -const bitangentLocal = /*@__PURE__*/ varying( getBitangent( normalLocal.cross( tangentLocal ) ), 'v_bitangentLocal' ).normalize().toVar( 'bitangentLocal' ); -const bitangentView = /*@__PURE__*/ varying( getBitangent( normalView.cross( tangentView ) ), 'v_bitangentView' ).normalize().toVar( 'bitangentView' ); -const bitangentWorld = /*@__PURE__*/ varying( getBitangent( normalWorld.cross( tangentWorld ) ), 'v_bitangentWorld' ).normalize().toVar( 'bitangentWorld' ); -const transformedBitangentView = /*@__PURE__*/ getBitangent( transformedNormalView.cross( transformedTangentView ) ).normalize().toVar( 'transformedBitangentView' ); -const transformedBitangentWorld = /*@__PURE__*/ transformedBitangentView.transformDirection( cameraViewMatrix ).normalize().toVar( 'transformedBitangentWorld' ); + onLoad( audioBuffer ); -const TBNViewMatrix = /*@__PURE__*/ mat3( tangentView, bitangentView, normalView ); + } ).catch( handleError ); -const parallaxDirection = /*@__PURE__*/ positionViewDirection.mul( TBNViewMatrix )/*.normalize()*/; -const parallaxUV = ( uv, scale ) => uv.sub( parallaxDirection.mul( scale ) ); + } catch ( e ) { -const transformedBentNormalView = /*@__PURE__*/ ( () => { + handleError( e ); - // https://google.github.io/filament/Filament.md.html#lighting/imagebasedlights/anisotropy + } - let bentNormal = anisotropyB.cross( positionViewDirection ); - bentNormal = bentNormal.cross( anisotropyB ).normalize(); - bentNormal = mix( bentNormal, transformedNormalView, anisotropy.mul( roughness.oneMinus() ).oneMinus().pow2().pow2() ).normalize(); + }, onProgress, onError ); - return bentNormal; + function handleError( e ) { + if ( onError ) { -} )(); + onError( e ); -// Normal Mapping Without Precomputed Tangents -// http://www.thetenthplanet.de/archives/1180 + } else { -const perturbNormal2Arb = /*@__PURE__*/ Fn( ( inputs ) => { + console.error( e ); - const { eye_pos, surf_norm, mapN, uv } = inputs; + } - const q0 = eye_pos.dFdx(); - const q1 = eye_pos.dFdy(); - const st0 = uv.dFdx(); - const st1 = uv.dFdy(); + scope.manager.itemError( url ); - const N = surf_norm; // normalized + } - const q1perp = q1.cross( N ); - const q0perp = N.cross( q0 ); + } - const T = q1perp.mul( st0.x ).add( q0perp.mul( st1.x ) ); - const B = q1perp.mul( st0.y ).add( q0perp.mul( st1.y ) ); +} - const det = T.dot( T ).max( B.dot( B ) ); - const scale = faceDirection.mul( det.inverseSqrt() ); +const _eyeRight = /*@__PURE__*/ new Matrix4(); +const _eyeLeft = /*@__PURE__*/ new Matrix4(); +const _projectionMatrix = /*@__PURE__*/ new Matrix4(); - return add( T.mul( mapN.x, scale ), B.mul( mapN.y, scale ), N.mul( mapN.z ) ).normalize(); +class StereoCamera { -} ); + constructor() { -class NormalMapNode extends TempNode { + this.type = 'StereoCamera'; - constructor( node, scaleNode = null ) { + this.aspect = 1; - super( 'vec3' ); + this.eyeSep = 0.064; - this.node = node; - this.scaleNode = scaleNode; + this.cameraL = new PerspectiveCamera(); + this.cameraL.layers.enable( 1 ); + this.cameraL.matrixAutoUpdate = false; - this.normalMapType = TangentSpaceNormalMap; + this.cameraR = new PerspectiveCamera(); + this.cameraR.layers.enable( 2 ); + this.cameraR.matrixAutoUpdate = false; + + this._cache = { + focus: null, + fov: null, + aspect: null, + near: null, + far: null, + zoom: null, + eyeSep: null + }; } - setup( builder ) { + update( camera ) { - const { normalMapType, scaleNode } = this; + const cache = this._cache; - let normalMap = this.node.mul( 2.0 ).sub( 1.0 ); + const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov || + cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near || + cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep; - if ( scaleNode !== null ) { + if ( needsUpdate ) { - normalMap = vec3( normalMap.xy.mul( scaleNode ), normalMap.z ); + cache.focus = camera.focus; + cache.fov = camera.fov; + cache.aspect = camera.aspect * this.aspect; + cache.near = camera.near; + cache.far = camera.far; + cache.zoom = camera.zoom; + cache.eyeSep = this.eyeSep; - } + // Off-axis stereoscopic effect based on + // http://paulbourke.net/stereographics/stereorender/ - let outputNode = null; + _projectionMatrix.copy( camera.projectionMatrix ); + const eyeSepHalf = cache.eyeSep / 2; + const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus; + const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom; + let xmin, xmax; - if ( normalMapType === ObjectSpaceNormalMap ) { + // translate xOffset + + _eyeLeft.elements[ 12 ] = - eyeSepHalf; + _eyeRight.elements[ 12 ] = eyeSepHalf; - outputNode = modelNormalMatrix.mul( normalMap ).normalize(); + // for left eye - } else if ( normalMapType === TangentSpaceNormalMap ) { + xmin = - ymax * cache.aspect + eyeSepOnProjection; + xmax = ymax * cache.aspect + eyeSepOnProjection; - const tangent = builder.hasGeometryAttribute( 'tangent' ); + _projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin ); + _projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); - if ( tangent === true ) { + this.cameraL.projectionMatrix.copy( _projectionMatrix ); - outputNode = TBNViewMatrix.mul( normalMap ).normalize(); + // for right eye - } else { + xmin = - ymax * cache.aspect - eyeSepOnProjection; + xmax = ymax * cache.aspect - eyeSepOnProjection; - outputNode = perturbNormal2Arb( { - eye_pos: positionView, - surf_norm: normalView, - mapN: normalMap, - uv: uv() - } ); + _projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin ); + _projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); - } + this.cameraR.projectionMatrix.copy( _projectionMatrix ); } - return outputNode; + this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft ); + this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight ); } } -NormalMapNode.type = /*@__PURE__*/ registerNode( 'NormalMap', NormalMapNode ); +class ArrayCamera extends PerspectiveCamera { -const normalMap = /*@__PURE__*/ nodeProxy( NormalMapNode ); + constructor( array = [] ) { -// Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen -// https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf + super(); -const dHdxy_fwd = Fn( ( { textureNode, bumpScale } ) => { + this.isArrayCamera = true; - // It's used to preserve the same TextureNode instance - const sampleTexture = ( callback ) => textureNode.cache().context( { getUV: ( texNode ) => callback( texNode.uvNode || uv() ), forceUVContext: true } ); + this.cameras = array; - const Hll = float( sampleTexture( ( uvNode ) => uvNode ) ); + } - return vec2( - float( sampleTexture( ( uvNode ) => uvNode.add( uvNode.dFdx() ) ) ).sub( Hll ), - float( sampleTexture( ( uvNode ) => uvNode.add( uvNode.dFdy() ) ) ).sub( Hll ) - ).mul( bumpScale ); +} -} ); +class Clock { -// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2) + constructor( autoStart = true ) { -const perturbNormalArb = Fn( ( inputs ) => { + this.autoStart = autoStart; - const { surf_pos, surf_norm, dHdxy } = inputs; + this.startTime = 0; + this.oldTime = 0; + this.elapsedTime = 0; - // normalize is done to ensure that the bump map looks the same regardless of the texture's scale - const vSigmaX = surf_pos.dFdx().normalize(); - const vSigmaY = surf_pos.dFdy().normalize(); - const vN = surf_norm; // normalized + this.running = false; - const R1 = vSigmaY.cross( vN ); - const R2 = vN.cross( vSigmaX ); + } - const fDet = vSigmaX.dot( R1 ).mul( faceDirection ); + start() { - const vGrad = fDet.sign().mul( dHdxy.x.mul( R1 ).add( dHdxy.y.mul( R2 ) ) ); + this.startTime = now(); - return fDet.abs().mul( surf_norm ).sub( vGrad ).normalize(); + this.oldTime = this.startTime; + this.elapsedTime = 0; + this.running = true; -} ); + } -class BumpMapNode extends TempNode { + stop() { - constructor( textureNode, scaleNode = null ) { + this.getElapsedTime(); + this.running = false; + this.autoStart = false; - super( 'vec3' ); + } - this.textureNode = textureNode; - this.scaleNode = scaleNode; + getElapsedTime() { + + this.getDelta(); + return this.elapsedTime; } - setup() { + getDelta() { - const bumpScale = this.scaleNode !== null ? this.scaleNode : 1; - const dHdxy = dHdxy_fwd( { textureNode: this.textureNode, bumpScale } ); + let diff = 0; - return perturbNormalArb( { - surf_pos: positionView, - surf_norm: normalView, - dHdxy - } ); + if ( this.autoStart && ! this.running ) { - } + this.start(); + return 0; -} + } -const bumpMap = /*@__PURE__*/ nodeProxy( BumpMapNode ); + if ( this.running ) { -const _propertyCache = new Map(); + const newTime = now(); -class MaterialNode extends Node { + diff = ( newTime - this.oldTime ) / 1000; + this.oldTime = newTime; - constructor( scope ) { + this.elapsedTime += diff; - super(); + } - this.scope = scope; + return diff; } - getCache( property, type ) { +} - let node = _propertyCache.get( property ); +function now() { - if ( node === undefined ) { + return performance.now(); - node = materialReference( property, type ); +} - _propertyCache.set( property, node ); +const _position$1 = /*@__PURE__*/ new Vector3(); +const _quaternion$1 = /*@__PURE__*/ new Quaternion(); +const _scale$1 = /*@__PURE__*/ new Vector3(); +const _orientation$1 = /*@__PURE__*/ new Vector3(); - } +class AudioListener extends Object3D { - return node; + constructor() { - } + super(); - getFloat( property ) { + this.type = 'AudioListener'; - return this.getCache( property, 'float' ); + this.context = AudioContext.getContext(); - } + this.gain = this.context.createGain(); + this.gain.connect( this.context.destination ); - getColor( property ) { + this.filter = null; - return this.getCache( property, 'color' ); + this.timeDelta = 0; + + // private + + this._clock = new Clock(); } - getTexture( property ) { + getInput() { - return this.getCache( property === 'map' ? 'map' : property + 'Map', 'texture' ); + return this.gain; } - setup( builder ) { + removeFilter() { - const material = builder.context.material; - const scope = this.scope; + if ( this.filter !== null ) { - let node = null; + this.gain.disconnect( this.filter ); + this.filter.disconnect( this.context.destination ); + this.gain.connect( this.context.destination ); + this.filter = null; - if ( scope === MaterialNode.COLOR ) { + } - const colorNode = material.color !== undefined ? this.getColor( scope ) : vec3(); + return this; - if ( material.map && material.map.isTexture === true ) { + } - node = colorNode.mul( this.getTexture( 'map' ) ); + getFilter() { - } else { + return this.filter; - node = colorNode; + } - } + setFilter( value ) { - } else if ( scope === MaterialNode.OPACITY ) { + if ( this.filter !== null ) { - const opacityNode = this.getFloat( scope ); + this.gain.disconnect( this.filter ); + this.filter.disconnect( this.context.destination ); - if ( material.alphaMap && material.alphaMap.isTexture === true ) { + } else { - node = opacityNode.mul( this.getTexture( 'alpha' ) ); + this.gain.disconnect( this.context.destination ); - } else { + } - node = opacityNode; + this.filter = value; + this.gain.connect( this.filter ); + this.filter.connect( this.context.destination ); - } + return this; - } else if ( scope === MaterialNode.SPECULAR_STRENGTH ) { + } - if ( material.specularMap && material.specularMap.isTexture === true ) { + getMasterVolume() { - node = this.getTexture( 'specular' ).r; + return this.gain.gain.value; - } else { + } - node = float( 1 ); + setMasterVolume( value ) { - } + this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 ); - } else if ( scope === MaterialNode.SPECULAR_INTENSITY ) { + return this; - const specularIntensity = this.getFloat( scope ); + } - if ( material.specularMap ) { + updateMatrixWorld( force ) { - node = specularIntensity.mul( this.getTexture( scope ).a ); + super.updateMatrixWorld( force ); - } else { + const listener = this.context.listener; + const up = this.up; - node = specularIntensity; + this.timeDelta = this._clock.getDelta(); - } + this.matrixWorld.decompose( _position$1, _quaternion$1, _scale$1 ); - } else if ( scope === MaterialNode.SPECULAR_COLOR ) { + _orientation$1.set( 0, 0, - 1 ).applyQuaternion( _quaternion$1 ); - const specularColorNode = this.getColor( scope ); + if ( listener.positionX ) { - if ( material.specularColorMap && material.specularColorMap.isTexture === true ) { + // code path for Chrome (see #14393) - node = specularColorNode.mul( this.getTexture( scope ).rgb ); + const endTime = this.context.currentTime + this.timeDelta; - } else { + listener.positionX.linearRampToValueAtTime( _position$1.x, endTime ); + listener.positionY.linearRampToValueAtTime( _position$1.y, endTime ); + listener.positionZ.linearRampToValueAtTime( _position$1.z, endTime ); + listener.forwardX.linearRampToValueAtTime( _orientation$1.x, endTime ); + listener.forwardY.linearRampToValueAtTime( _orientation$1.y, endTime ); + listener.forwardZ.linearRampToValueAtTime( _orientation$1.z, endTime ); + listener.upX.linearRampToValueAtTime( up.x, endTime ); + listener.upY.linearRampToValueAtTime( up.y, endTime ); + listener.upZ.linearRampToValueAtTime( up.z, endTime ); - node = specularColorNode; + } else { - } + listener.setPosition( _position$1.x, _position$1.y, _position$1.z ); + listener.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z, up.x, up.y, up.z ); - } else if ( scope === MaterialNode.ROUGHNESS ) { // TODO: cleanup similar branches + } - const roughnessNode = this.getFloat( scope ); + } - if ( material.roughnessMap && material.roughnessMap.isTexture === true ) { +} - node = roughnessNode.mul( this.getTexture( scope ).g ); +class Audio extends Object3D { - } else { + constructor( listener ) { - node = roughnessNode; - - } + super(); - } else if ( scope === MaterialNode.METALNESS ) { + this.type = 'Audio'; - const metalnessNode = this.getFloat( scope ); + this.listener = listener; + this.context = listener.context; - if ( material.metalnessMap && material.metalnessMap.isTexture === true ) { + this.gain = this.context.createGain(); + this.gain.connect( listener.getInput() ); - node = metalnessNode.mul( this.getTexture( scope ).b ); + this.autoplay = false; - } else { + this.buffer = null; + this.detune = 0; + this.loop = false; + this.loopStart = 0; + this.loopEnd = 0; + this.offset = 0; + this.duration = undefined; + this.playbackRate = 1; + this.isPlaying = false; + this.hasPlaybackControl = true; + this.source = null; + this.sourceType = 'empty'; - node = metalnessNode; + this._startedAt = 0; + this._progress = 0; + this._connected = false; - } + this.filters = []; - } else if ( scope === MaterialNode.EMISSIVE ) { + } - const emissiveIntensityNode = this.getFloat( 'emissiveIntensity' ); - const emissiveNode = this.getColor( scope ).mul( emissiveIntensityNode ); + getOutput() { - if ( material.emissiveMap && material.emissiveMap.isTexture === true ) { + return this.gain; - node = emissiveNode.mul( this.getTexture( scope ) ); + } - } else { + setNodeSource( audioNode ) { - node = emissiveNode; + this.hasPlaybackControl = false; + this.sourceType = 'audioNode'; + this.source = audioNode; + this.connect(); - } + return this; - } else if ( scope === MaterialNode.NORMAL ) { + } - if ( material.normalMap ) { + setMediaElementSource( mediaElement ) { - node = normalMap( this.getTexture( 'normal' ), this.getCache( 'normalScale', 'vec2' ) ); + this.hasPlaybackControl = false; + this.sourceType = 'mediaNode'; + this.source = this.context.createMediaElementSource( mediaElement ); + this.connect(); - } else if ( material.bumpMap ) { + return this; - node = bumpMap( this.getTexture( 'bump' ).r, this.getFloat( 'bumpScale' ) ); + } - } else { + setMediaStreamSource( mediaStream ) { - node = normalView; + this.hasPlaybackControl = false; + this.sourceType = 'mediaStreamNode'; + this.source = this.context.createMediaStreamSource( mediaStream ); + this.connect(); - } + return this; - } else if ( scope === MaterialNode.CLEARCOAT ) { + } - const clearcoatNode = this.getFloat( scope ); + setBuffer( audioBuffer ) { - if ( material.clearcoatMap && material.clearcoatMap.isTexture === true ) { + this.buffer = audioBuffer; + this.sourceType = 'buffer'; - node = clearcoatNode.mul( this.getTexture( scope ).r ); + if ( this.autoplay ) this.play(); - } else { + return this; - node = clearcoatNode; + } - } + play( delay = 0 ) { - } else if ( scope === MaterialNode.CLEARCOAT_ROUGHNESS ) { + if ( this.isPlaying === true ) { - const clearcoatRoughnessNode = this.getFloat( scope ); + console.warn( 'THREE.Audio: Audio is already playing.' ); + return; - if ( material.clearcoatRoughnessMap && material.clearcoatRoughnessMap.isTexture === true ) { + } - node = clearcoatRoughnessNode.mul( this.getTexture( scope ).r ); + if ( this.hasPlaybackControl === false ) { - } else { + console.warn( 'THREE.Audio: this Audio has no playback control.' ); + return; - node = clearcoatRoughnessNode; + } - } + this._startedAt = this.context.currentTime + delay; - } else if ( scope === MaterialNode.CLEARCOAT_NORMAL ) { + const source = this.context.createBufferSource(); + source.buffer = this.buffer; + source.loop = this.loop; + source.loopStart = this.loopStart; + source.loopEnd = this.loopEnd; + source.onended = this.onEnded.bind( this ); + source.start( this._startedAt, this._progress + this.offset, this.duration ); - if ( material.clearcoatNormalMap ) { + this.isPlaying = true; - node = normalMap( this.getTexture( scope ), this.getCache( scope + 'Scale', 'vec2' ) ); + this.source = source; - } else { + this.setDetune( this.detune ); + this.setPlaybackRate( this.playbackRate ); - node = normalView; + return this.connect(); - } + } - } else if ( scope === MaterialNode.SHEEN ) { + pause() { - const sheenNode = this.getColor( 'sheenColor' ).mul( this.getFloat( 'sheen' ) ); // Move this mul() to CPU + if ( this.hasPlaybackControl === false ) { - if ( material.sheenColorMap && material.sheenColorMap.isTexture === true ) { + console.warn( 'THREE.Audio: this Audio has no playback control.' ); + return; - node = sheenNode.mul( this.getTexture( 'sheenColor' ).rgb ); + } - } else { + if ( this.isPlaying === true ) { - node = sheenNode; + // update current progress - } + this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate; - } else if ( scope === MaterialNode.SHEEN_ROUGHNESS ) { + if ( this.loop === true ) { - const sheenRoughnessNode = this.getFloat( scope ); + // ensure _progress does not exceed duration with looped audios - if ( material.sheenRoughnessMap && material.sheenRoughnessMap.isTexture === true ) { + this._progress = this._progress % ( this.duration || this.buffer.duration ); - node = sheenRoughnessNode.mul( this.getTexture( scope ).a ); + } - } else { + this.source.stop(); + this.source.onended = null; - node = sheenRoughnessNode; + this.isPlaying = false; - } + } - node = node.clamp( 0.07, 1.0 ); + return this; - } else if ( scope === MaterialNode.ANISOTROPY ) { + } - if ( material.anisotropyMap && material.anisotropyMap.isTexture === true ) { + stop( delay = 0 ) { - const anisotropyPolar = this.getTexture( scope ); - const anisotropyMat = mat2( materialAnisotropyVector.x, materialAnisotropyVector.y, materialAnisotropyVector.y.negate(), materialAnisotropyVector.x ); + if ( this.hasPlaybackControl === false ) { - node = anisotropyMat.mul( anisotropyPolar.rg.mul( 2.0 ).sub( vec2( 1.0 ) ).normalize().mul( anisotropyPolar.b ) ); + console.warn( 'THREE.Audio: this Audio has no playback control.' ); + return; - } else { + } - node = materialAnisotropyVector; + this._progress = 0; - } + if ( this.source !== null ) { - } else if ( scope === MaterialNode.IRIDESCENCE_THICKNESS ) { + this.source.stop( this.context.currentTime + delay ); + this.source.onended = null; - const iridescenceThicknessMaximum = reference( '1', 'float', material.iridescenceThicknessRange ); + } - if ( material.iridescenceThicknessMap ) { + this.isPlaying = false; - const iridescenceThicknessMinimum = reference( '0', 'float', material.iridescenceThicknessRange ); + return this; - node = iridescenceThicknessMaximum.sub( iridescenceThicknessMinimum ).mul( this.getTexture( scope ).g ).add( iridescenceThicknessMinimum ); + } - } else { + connect() { - node = iridescenceThicknessMaximum; + if ( this.filters.length > 0 ) { - } + this.source.connect( this.filters[ 0 ] ); - } else if ( scope === MaterialNode.TRANSMISSION ) { + for ( let i = 1, l = this.filters.length; i < l; i ++ ) { - const transmissionNode = this.getFloat( scope ); + this.filters[ i - 1 ].connect( this.filters[ i ] ); - if ( material.transmissionMap ) { + } - node = transmissionNode.mul( this.getTexture( scope ).r ); + this.filters[ this.filters.length - 1 ].connect( this.getOutput() ); - } else { + } else { - node = transmissionNode; + this.source.connect( this.getOutput() ); - } + } - } else if ( scope === MaterialNode.THICKNESS ) { + this._connected = true; - const thicknessNode = this.getFloat( scope ); + return this; - if ( material.thicknessMap ) { + } - node = thicknessNode.mul( this.getTexture( scope ).g ); + disconnect() { - } else { + if ( this._connected === false ) { - node = thicknessNode; + return; - } + } - } else if ( scope === MaterialNode.IOR ) { + if ( this.filters.length > 0 ) { - node = this.getFloat( scope ); + this.source.disconnect( this.filters[ 0 ] ); - } else if ( scope === MaterialNode.LIGHT_MAP ) { + for ( let i = 1, l = this.filters.length; i < l; i ++ ) { - node = this.getTexture( scope ).rgb.mul( this.getFloat( 'lightMapIntensity' ) ); + this.filters[ i - 1 ].disconnect( this.filters[ i ] ); - } else if ( scope === MaterialNode.AO_MAP ) { + } - node = this.getTexture( scope ).r.sub( 1.0 ).mul( this.getFloat( 'aoMapIntensity' ) ).add( 1.0 ); + this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() ); } else { - const outputType = this.getNodeType( builder ); - - node = this.getCache( scope, outputType ); + this.source.disconnect( this.getOutput() ); } - return node; - - } - -} + this._connected = false; -MaterialNode.ALPHA_TEST = 'alphaTest'; -MaterialNode.COLOR = 'color'; -MaterialNode.OPACITY = 'opacity'; -MaterialNode.SHININESS = 'shininess'; -MaterialNode.SPECULAR = 'specular'; -MaterialNode.SPECULAR_STRENGTH = 'specularStrength'; -MaterialNode.SPECULAR_INTENSITY = 'specularIntensity'; -MaterialNode.SPECULAR_COLOR = 'specularColor'; -MaterialNode.REFLECTIVITY = 'reflectivity'; -MaterialNode.ROUGHNESS = 'roughness'; -MaterialNode.METALNESS = 'metalness'; -MaterialNode.NORMAL = 'normal'; -MaterialNode.CLEARCOAT = 'clearcoat'; -MaterialNode.CLEARCOAT_ROUGHNESS = 'clearcoatRoughness'; -MaterialNode.CLEARCOAT_NORMAL = 'clearcoatNormal'; -MaterialNode.EMISSIVE = 'emissive'; -MaterialNode.ROTATION = 'rotation'; -MaterialNode.SHEEN = 'sheen'; -MaterialNode.SHEEN_ROUGHNESS = 'sheenRoughness'; -MaterialNode.ANISOTROPY = 'anisotropy'; -MaterialNode.IRIDESCENCE = 'iridescence'; -MaterialNode.IRIDESCENCE_IOR = 'iridescenceIOR'; -MaterialNode.IRIDESCENCE_THICKNESS = 'iridescenceThickness'; -MaterialNode.IOR = 'ior'; -MaterialNode.TRANSMISSION = 'transmission'; -MaterialNode.THICKNESS = 'thickness'; -MaterialNode.ATTENUATION_DISTANCE = 'attenuationDistance'; -MaterialNode.ATTENUATION_COLOR = 'attenuationColor'; -MaterialNode.LINE_SCALE = 'scale'; -MaterialNode.LINE_DASH_SIZE = 'dashSize'; -MaterialNode.LINE_GAP_SIZE = 'gapSize'; -MaterialNode.LINE_WIDTH = 'linewidth'; -MaterialNode.LINE_DASH_OFFSET = 'dashOffset'; -MaterialNode.POINT_WIDTH = 'pointWidth'; -MaterialNode.DISPERSION = 'dispersion'; -MaterialNode.LIGHT_MAP = 'light'; -MaterialNode.AO_MAP = 'ao'; + return this; -MaterialNode.type = /*@__PURE__*/ registerNode( 'Material', MaterialNode ); + } -const materialAlphaTest = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ALPHA_TEST ); -const materialColor = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.COLOR ); -const materialShininess = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SHININESS ); -const materialEmissive = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.EMISSIVE ); -const materialOpacity = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.OPACITY ); -const materialSpecular = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR ); + getFilters() { -const materialSpecularIntensity = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR_INTENSITY ); -const materialSpecularColor = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR_COLOR ); + return this.filters; -const materialSpecularStrength = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR_STRENGTH ); -const materialReflectivity = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.REFLECTIVITY ); -const materialRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ROUGHNESS ); -const materialMetalness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.METALNESS ); -const materialNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.NORMAL ).context( { getUV: null } ); -const materialClearcoat = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT ); -const materialClearcoatRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_ROUGHNESS ); -const materialClearcoatNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_NORMAL ).context( { getUV: null } ); -const materialRotation = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ROTATION ); -const materialSheen = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SHEEN ); -const materialSheenRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SHEEN_ROUGHNESS ); -const materialAnisotropy = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ANISOTROPY ); -const materialIridescence = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE ); -const materialIridescenceIOR = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE_IOR ); -const materialIridescenceThickness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE_THICKNESS ); -const materialTransmission = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.TRANSMISSION ); -const materialThickness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.THICKNESS ); -const materialIOR = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.IOR ); -const materialAttenuationDistance = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ATTENUATION_DISTANCE ); -const materialAttenuationColor = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ATTENUATION_COLOR ); -const materialLineScale = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_SCALE ); -const materialLineDashSize = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_DASH_SIZE ); -const materialLineGapSize = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_GAP_SIZE ); -const materialLineWidth = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_WIDTH ); -const materialLineDashOffset = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_DASH_OFFSET ); -const materialPointWidth = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.POINT_WIDTH ); -const materialDispersion = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.DISPERSION ); -const materialLightMap = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LIGHT_MAP ); -const materialAOMap = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.AO_MAP ); -/*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.REFRACTION_RATIO ); -const materialAnisotropyVector = /*@__PURE__*/ uniform( new Vector2() ).onReference( function ( frame ) { + } - return frame.material; + setFilters( value ) { -} ).onRenderUpdate( function ( { material } ) { + if ( ! value ) value = []; - this.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) ); + if ( this._connected === true ) { -} ); + this.disconnect(); + this.filters = value.slice(); + this.connect(); -class ModelViewProjectionNode extends TempNode { + } else { - constructor( positionNode = null ) { + this.filters = value.slice(); - super( 'vec4' ); + } - this.positionNode = positionNode; + return this; } - setup( builder ) { + setDetune( value ) { - if ( builder.shaderStage === 'fragment' ) { + this.detune = value; - return varying( builder.context.mvp ); + if ( this.isPlaying === true && this.source.detune !== undefined ) { - } + this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 ); - const position = this.positionNode || positionLocal; + } - return cameraProjectionMatrix.mul( modelViewMatrix ).mul( position ); + return this; } -} + getDetune() { -ModelViewProjectionNode.type = /*@__PURE__*/ registerNode( 'ModelViewProjection', ModelViewProjectionNode ); + return this.detune; -const modelViewProjection = /*@__PURE__*/ nodeProxy( ModelViewProjectionNode ); + } -class IndexNode extends Node { + getFilter() { - constructor( scope ) { + return this.getFilters()[ 0 ]; - super( 'uint' ); + } - this.scope = scope; + setFilter( filter ) { - this.isInstanceIndexNode = true; + return this.setFilters( filter ? [ filter ] : [] ); } - generate( builder ) { - - const nodeType = this.getNodeType( builder ); - const scope = this.scope; + setPlaybackRate( value ) { - let propertyName; + if ( this.hasPlaybackControl === false ) { - if ( scope === IndexNode.VERTEX ) { + console.warn( 'THREE.Audio: this Audio has no playback control.' ); + return; - propertyName = builder.getVertexIndex(); + } - } else if ( scope === IndexNode.INSTANCE ) { + this.playbackRate = value; - propertyName = builder.getInstanceIndex(); + if ( this.isPlaying === true ) { - } else if ( scope === IndexNode.DRAW ) { + this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 ); - propertyName = builder.getDrawIndex(); + } - } else if ( scope === IndexNode.INVOCATION_LOCAL ) { + return this; - propertyName = builder.getInvocationLocalIndex(); + } - } else { + getPlaybackRate() { - throw new Error( 'THREE.IndexNode: Unknown scope: ' + scope ); + return this.playbackRate; - } + } - let output; + onEnded() { - if ( builder.shaderStage === 'vertex' || builder.shaderStage === 'compute' ) { + this.isPlaying = false; - output = propertyName; + } - } else { + getLoop() { - const nodeVarying = varying( this ); + if ( this.hasPlaybackControl === false ) { - output = nodeVarying.build( builder, nodeType ); + console.warn( 'THREE.Audio: this Audio has no playback control.' ); + return false; } - return output; + return this.loop; } -} + setLoop( value ) { -IndexNode.VERTEX = 'vertex'; -IndexNode.INSTANCE = 'instance'; -IndexNode.INVOCATION_LOCAL = 'invocationLocal'; -IndexNode.DRAW = 'draw'; + if ( this.hasPlaybackControl === false ) { -IndexNode.type = /*@__PURE__*/ registerNode( 'Index', IndexNode ); + console.warn( 'THREE.Audio: this Audio has no playback control.' ); + return; -const vertexIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.VERTEX ); -const instanceIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.INSTANCE ); -const invocationLocalIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.INVOCATION_LOCAL ); -const drawIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.DRAW ); + } -class InstancedInterleavedBuffer extends InterleavedBuffer { + this.loop = value; - constructor( array, stride, meshPerAttribute = 1 ) { + if ( this.isPlaying === true ) { - super( array, stride ); + this.source.loop = this.loop; - this.isInstancedInterleavedBuffer = true; + } - this.meshPerAttribute = meshPerAttribute; + return this; } - copy( source ) { - - super.copy( source ); + setLoopStart( value ) { - this.meshPerAttribute = source.meshPerAttribute; + this.loopStart = value; return this; } - clone( data ) { - - const ib = super.clone( data ); + setLoopEnd( value ) { - ib.meshPerAttribute = this.meshPerAttribute; + this.loopEnd = value; - return ib; + return this; } - toJSON( data ) { + getVolume() { - const json = super.toJSON( data ); + return this.gain.gain.value; - json.isInstancedInterleavedBuffer = true; - json.meshPerAttribute = this.meshPerAttribute; + } - return json; + setVolume( value ) { + + this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 ); + + return this; } } -class InstanceNode extends Node { +const _position = /*@__PURE__*/ new Vector3(); +const _quaternion = /*@__PURE__*/ new Quaternion(); +const _scale = /*@__PURE__*/ new Vector3(); +const _orientation = /*@__PURE__*/ new Vector3(); - constructor( instanceMesh ) { +class PositionalAudio extends Audio { - super( 'void' ); + constructor( listener ) { - this.instanceMesh = instanceMesh; + super( listener ); - this.instanceMatrixNode = null; + this.panner = this.context.createPanner(); + this.panner.panningModel = 'HRTF'; + this.panner.connect( this.gain ); - this.instanceColorNode = null; + } - this.updateType = NodeUpdateType.FRAME; + connect() { - this.buffer = null; - this.bufferColor = null; + super.connect(); + + this.panner.connect( this.gain ); } - setup( builder ) { + disconnect() { - let instanceMatrixNode = this.instanceMatrixNode; - let instanceColorNode = this.instanceColorNode; + super.disconnect(); - const instanceMesh = this.instanceMesh; + this.panner.disconnect( this.gain ); - if ( instanceMatrixNode === null ) { + } - const instanceAttribute = instanceMesh.instanceMatrix; + getOutput() { - // Both WebGPU and WebGL backends have UBO max limited to 64kb. Matrix count number bigger than 1000 ( 16 * 4 * 1000 = 64kb ) will fallback to attribute. + return this.panner; - if ( instanceMesh.count <= 1000 ) { + } - instanceMatrixNode = buffer( instanceAttribute.array, 'mat4', instanceMesh.count ).element( instanceIndex ); + getRefDistance() { - } else { + return this.panner.refDistance; - const buffer = new InstancedInterleavedBuffer( instanceAttribute.array, 16, 1 ); + } - this.buffer = buffer; + setRefDistance( value ) { - const bufferFn = instanceAttribute.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute; + this.panner.refDistance = value; - const instanceBuffers = [ - // F.Signature -> bufferAttribute( array, type, stride, offset ) - bufferFn( buffer, 'vec4', 16, 0 ), - bufferFn( buffer, 'vec4', 16, 4 ), - bufferFn( buffer, 'vec4', 16, 8 ), - bufferFn( buffer, 'vec4', 16, 12 ) - ]; + return this; - instanceMatrixNode = mat4( ...instanceBuffers ); - - } + } - this.instanceMatrixNode = instanceMatrixNode; + getRolloffFactor() { - } + return this.panner.rolloffFactor; - const instanceColorAttribute = instanceMesh.instanceColor; + } - if ( instanceColorAttribute && instanceColorNode === null ) { + setRolloffFactor( value ) { - const buffer = new InstancedBufferAttribute( instanceColorAttribute.array, 3 ); + this.panner.rolloffFactor = value; - const bufferFn = instanceColorAttribute.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute; + return this; - this.bufferColor = buffer; + } - instanceColorNode = vec3( bufferFn( buffer, 'vec3', 3, 0 ) ); + getDistanceModel() { - this.instanceColorNode = instanceColorNode; + return this.panner.distanceModel; - } + } - // POSITION + setDistanceModel( value ) { - const instancePosition = instanceMatrixNode.mul( positionLocal ).xyz; - positionLocal.assign( instancePosition ); + this.panner.distanceModel = value; - // NORMAL + return this; - if ( builder.hasGeometryAttribute( 'normal' ) ) { + } - const m = mat3( instanceMatrixNode ); + getMaxDistance() { - const transformedNormal = normalLocal.div( vec3( m[ 0 ].dot( m[ 0 ] ), m[ 1 ].dot( m[ 1 ] ), m[ 2 ].dot( m[ 2 ] ) ) ); + return this.panner.maxDistance; - const instanceNormal = m.mul( transformedNormal ).xyz; + } - // ASSIGNS + setMaxDistance( value ) { - normalLocal.assign( instanceNormal ); + this.panner.maxDistance = value; - } + return this; - // COLOR + } - if ( this.instanceColorNode !== null ) { + setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) { - varyingProperty( 'vec3', 'vInstanceColor' ).assign( this.instanceColorNode ); + this.panner.coneInnerAngle = coneInnerAngle; + this.panner.coneOuterAngle = coneOuterAngle; + this.panner.coneOuterGain = coneOuterGain; - } + return this; } - update( /*frame*/ ) { - - if ( this.instanceMesh.instanceMatrix.usage !== DynamicDrawUsage && this.buffer != null && this.instanceMesh.instanceMatrix.version !== this.buffer.version ) { - - this.buffer.version = this.instanceMesh.instanceMatrix.version; + updateMatrixWorld( force ) { - } + super.updateMatrixWorld( force ); - if ( this.instanceMesh.instanceColor && this.instanceMesh.instanceColor.usage !== DynamicDrawUsage && this.bufferColor != null && this.instanceMesh.instanceColor.version !== this.bufferColor.version ) { + if ( this.hasPlaybackControl === true && this.isPlaying === false ) return; - this.bufferColor.version = this.instanceMesh.instanceColor.version; + this.matrixWorld.decompose( _position, _quaternion, _scale ); - } + _orientation.set( 0, 0, 1 ).applyQuaternion( _quaternion ); - } + const panner = this.panner; -} + if ( panner.positionX ) { -InstanceNode.type = /*@__PURE__*/ registerNode( 'Instance', InstanceNode ); + // code path for Chrome and Firefox (see #14393) -const instance = /*@__PURE__*/ nodeProxy( InstanceNode ); + const endTime = this.context.currentTime + this.listener.timeDelta; -class BatchNode extends Node { + panner.positionX.linearRampToValueAtTime( _position.x, endTime ); + panner.positionY.linearRampToValueAtTime( _position.y, endTime ); + panner.positionZ.linearRampToValueAtTime( _position.z, endTime ); + panner.orientationX.linearRampToValueAtTime( _orientation.x, endTime ); + panner.orientationY.linearRampToValueAtTime( _orientation.y, endTime ); + panner.orientationZ.linearRampToValueAtTime( _orientation.z, endTime ); - constructor( batchMesh ) { + } else { - super( 'void' ); + panner.setPosition( _position.x, _position.y, _position.z ); + panner.setOrientation( _orientation.x, _orientation.y, _orientation.z ); - this.batchMesh = batchMesh; + } + } - this.batchingIdNode = null; +} - } +class AudioAnalyser { - setup( builder ) { + constructor( audio, fftSize = 2048 ) { - // POSITION + this.analyser = audio.context.createAnalyser(); + this.analyser.fftSize = fftSize; - if ( this.batchingIdNode === null ) { + this.data = new Uint8Array( this.analyser.frequencyBinCount ); - if ( builder.getDrawIndex() === null ) { + audio.getOutput().connect( this.analyser ); - this.batchingIdNode = instanceIndex; + } - } else { - this.batchingIdNode = drawIndex; + getFrequencyData() { - } + this.analyser.getByteFrequencyData( this.data ); - } + return this.data; - const getIndirectIndex = Fn( ( [ id ] ) => { + } - const size = textureSize( textureLoad( this.batchMesh._indirectTexture ), 0 ); - const x = int( id ).modInt( int( size ) ); - const y = int( id ).div( int( size ) ); - return textureLoad( this.batchMesh._indirectTexture, ivec2( x, y ) ).x; + getAverageFrequency() { - } ).setLayout( { - name: 'getIndirectIndex', - type: 'uint', - inputs: [ - { name: 'id', type: 'int' } - ] - } ); + let value = 0; + const data = this.getFrequencyData(); - const indirectId = getIndirectIndex( int( this.batchingIdNode ) ); + for ( let i = 0; i < data.length; i ++ ) { - const matricesTexture = this.batchMesh._matricesTexture; + value += data[ i ]; - const size = textureSize( textureLoad( matricesTexture ), 0 ); - const j = float( indirectId ).mul( 4 ).toInt().toVar(); + } - const x = j.modInt( size ); - const y = j.div( int( size ) ); - const batchingMatrix = mat4( - textureLoad( matricesTexture, ivec2( x, y ) ), - textureLoad( matricesTexture, ivec2( x.add( 1 ), y ) ), - textureLoad( matricesTexture, ivec2( x.add( 2 ), y ) ), - textureLoad( matricesTexture, ivec2( x.add( 3 ), y ) ) - ); + return value / data.length; + } - const colorsTexture = this.batchMesh._colorsTexture; +} - if ( colorsTexture !== null ) { +class PropertyMixer { - const getBatchingColor = Fn( ( [ id ] ) => { + constructor( binding, typeName, valueSize ) { - const size = textureSize( textureLoad( colorsTexture ), 0 ).x; - const j = id; - const x = j.modInt( size ); - const y = j.div( size ); - return textureLoad( colorsTexture, ivec2( x, y ) ).rgb; + this.binding = binding; + this.valueSize = valueSize; - } ).setLayout( { - name: 'getBatchingColor', - type: 'vec3', - inputs: [ - { name: 'id', type: 'int' } - ] - } ); + let mixFunction, + mixFunctionAdditive, + setIdentity; - const color = getBatchingColor( indirectId ); + // buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ] + // + // interpolators can use .buffer as their .result + // the data then goes to 'incoming' + // + // 'accu0' and 'accu1' are used frame-interleaved for + // the cumulative result and are compared to detect + // changes + // + // 'orig' stores the original state of the property + // + // 'add' is used for additive cumulative results + // + // 'work' is optional and is only present for quaternion types. It is used + // to store intermediate quaternion multiplication results - varyingProperty( 'vec3', 'vBatchColor' ).assign( color ); + switch ( typeName ) { - } + case 'quaternion': + mixFunction = this._slerp; + mixFunctionAdditive = this._slerpAdditive; + setIdentity = this._setAdditiveIdentityQuaternion; - const bm = mat3( batchingMatrix ); + this.buffer = new Float64Array( valueSize * 6 ); + this._workIndex = 5; + break; - positionLocal.assign( batchingMatrix.mul( positionLocal ) ); + case 'string': + case 'bool': + mixFunction = this._select; - const transformedNormal = normalLocal.div( vec3( bm[ 0 ].dot( bm[ 0 ] ), bm[ 1 ].dot( bm[ 1 ] ), bm[ 2 ].dot( bm[ 2 ] ) ) ); + // Use the regular mix function and for additive on these types, + // additive is not relevant for non-numeric types + mixFunctionAdditive = this._select; - const batchingNormal = bm.mul( transformedNormal ).xyz; + setIdentity = this._setAdditiveIdentityOther; - normalLocal.assign( batchingNormal ); + this.buffer = new Array( valueSize * 5 ); + break; - if ( builder.hasGeometryAttribute( 'tangent' ) ) { + default: + mixFunction = this._lerp; + mixFunctionAdditive = this._lerpAdditive; + setIdentity = this._setAdditiveIdentityNumeric; - tangentLocal.mulAssign( bm ); + this.buffer = new Float64Array( valueSize * 5 ); } - } - -} + this._mixBufferRegion = mixFunction; + this._mixBufferRegionAdditive = mixFunctionAdditive; + this._setIdentity = setIdentity; + this._origIndex = 3; + this._addIndex = 4; -BatchNode.type = /*@__PURE__*/ registerNode( 'Batch', BatchNode ); + this.cumulativeWeight = 0; + this.cumulativeWeightAdditive = 0; -const batch = /*@__PURE__*/ nodeProxy( BatchNode ); + this.useCount = 0; + this.referenceCount = 0; -const _frameId = new WeakMap(); + } -class SkinningNode extends Node { + // accumulate data in the 'incoming' region into 'accu' + accumulate( accuIndex, weight ) { - constructor( skinnedMesh, useReference = false ) { + // note: happily accumulating nothing when weight = 0, the caller knows + // the weight and shouldn't have made the call in the first place - super( 'void' ); + const buffer = this.buffer, + stride = this.valueSize, + offset = accuIndex * stride + stride; - this.skinnedMesh = skinnedMesh; - this.useReference = useReference; + let currentWeight = this.cumulativeWeight; - this.updateType = NodeUpdateType.OBJECT; + if ( currentWeight === 0 ) { - // + // accuN := incoming * weight - this.skinIndexNode = attribute( 'skinIndex', 'uvec4' ); - this.skinWeightNode = attribute( 'skinWeight', 'vec4' ); + for ( let i = 0; i !== stride; ++ i ) { - let bindMatrixNode, bindMatrixInverseNode, boneMatricesNode; + buffer[ offset + i ] = buffer[ i ]; - if ( useReference ) { + } - bindMatrixNode = reference( 'bindMatrix', 'mat4' ); - bindMatrixInverseNode = reference( 'bindMatrixInverse', 'mat4' ); - boneMatricesNode = referenceBuffer( 'skeleton.boneMatrices', 'mat4', skinnedMesh.skeleton.bones.length ); + currentWeight = weight; } else { - bindMatrixNode = uniform( skinnedMesh.bindMatrix, 'mat4' ); - bindMatrixInverseNode = uniform( skinnedMesh.bindMatrixInverse, 'mat4' ); - boneMatricesNode = buffer( skinnedMesh.skeleton.boneMatrices, 'mat4', skinnedMesh.skeleton.bones.length ); + // accuN := accuN + incoming * weight + + currentWeight += weight; + const mix = weight / currentWeight; + this._mixBufferRegion( buffer, offset, 0, mix, stride ); } - this.bindMatrixNode = bindMatrixNode; - this.bindMatrixInverseNode = bindMatrixInverseNode; - this.boneMatricesNode = boneMatricesNode; - this.previousBoneMatricesNode = null; + this.cumulativeWeight = currentWeight; } - getSkinnedPosition( boneMatrices = this.boneMatricesNode, position = positionLocal ) { + // accumulate data in the 'incoming' region into 'add' + accumulateAdditive( weight ) { - const { skinIndexNode, skinWeightNode, bindMatrixNode, bindMatrixInverseNode } = this; + const buffer = this.buffer, + stride = this.valueSize, + offset = stride * this._addIndex; - const boneMatX = boneMatrices.element( skinIndexNode.x ); - const boneMatY = boneMatrices.element( skinIndexNode.y ); - const boneMatZ = boneMatrices.element( skinIndexNode.z ); - const boneMatW = boneMatrices.element( skinIndexNode.w ); + if ( this.cumulativeWeightAdditive === 0 ) { - // POSITION + // add = identity - const skinVertex = bindMatrixNode.mul( position ); + this._setIdentity(); - const skinned = add( - boneMatX.mul( skinWeightNode.x ).mul( skinVertex ), - boneMatY.mul( skinWeightNode.y ).mul( skinVertex ), - boneMatZ.mul( skinWeightNode.z ).mul( skinVertex ), - boneMatW.mul( skinWeightNode.w ).mul( skinVertex ) - ); + } - return bindMatrixInverseNode.mul( skinned ).xyz; + // add := add + incoming * weight + + this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride ); + this.cumulativeWeightAdditive += weight; } - getSkinnedNormal( boneMatrices = this.boneMatricesNode, normal = normalLocal ) { + // apply the state of 'accu' to the binding when accus differ + apply( accuIndex ) { - const { skinIndexNode, skinWeightNode, bindMatrixNode, bindMatrixInverseNode } = this; + const stride = this.valueSize, + buffer = this.buffer, + offset = accuIndex * stride + stride, - const boneMatX = boneMatrices.element( skinIndexNode.x ); - const boneMatY = boneMatrices.element( skinIndexNode.y ); - const boneMatZ = boneMatrices.element( skinIndexNode.z ); - const boneMatW = boneMatrices.element( skinIndexNode.w ); + weight = this.cumulativeWeight, + weightAdditive = this.cumulativeWeightAdditive, - // NORMAL + binding = this.binding; - let skinMatrix = add( - skinWeightNode.x.mul( boneMatX ), - skinWeightNode.y.mul( boneMatY ), - skinWeightNode.z.mul( boneMatZ ), - skinWeightNode.w.mul( boneMatW ) - ); + this.cumulativeWeight = 0; + this.cumulativeWeightAdditive = 0; - skinMatrix = bindMatrixInverseNode.mul( skinMatrix ).mul( bindMatrixNode ); + if ( weight < 1 ) { - return skinMatrix.transformDirection( normal ).xyz; + // accuN := accuN + original * ( 1 - cumulativeWeight ) - } + const originalValueOffset = stride * this._origIndex; - getPreviousSkinnedPosition( builder ) { + this._mixBufferRegion( + buffer, offset, originalValueOffset, 1 - weight, stride ); - const skinnedMesh = builder.object; + } - if ( this.previousBoneMatricesNode === null ) { + if ( weightAdditive > 0 ) { - skinnedMesh.skeleton.previousBoneMatrices = new Float32Array( skinnedMesh.skeleton.boneMatrices ); + // accuN := accuN + additive accuN - this.previousBoneMatricesNode = referenceBuffer( 'skeleton.previousBoneMatrices', 'mat4', skinnedMesh.skeleton.bones.length ); + this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride ); } - return this.getSkinnedPosition( this.previousBoneMatricesNode, positionPrevious ); + for ( let i = stride, e = stride + stride; i !== e; ++ i ) { - } + if ( buffer[ i ] !== buffer[ i + stride ] ) { - needsPreviousBoneMatrices( builder ) { + // value has changed -> update scene graph - const mrt = builder.renderer.getMRT(); + binding.setValue( buffer, offset ); + break; - return mrt && mrt.has( 'velocity' ); + } - } + } - setup( builder ) { + } - if ( this.needsPreviousBoneMatrices( builder ) ) { + // remember the state of the bound property and copy it to both accus + saveOriginalState() { - positionPrevious.assign( this.getPreviousSkinnedPosition( builder ) ); + const binding = this.binding; - } + const buffer = this.buffer, + stride = this.valueSize, - const skinPosition = this.getSkinnedPosition(); + originalValueOffset = stride * this._origIndex; + binding.getValue( buffer, originalValueOffset ); - positionLocal.assign( skinPosition ); + // accu[0..1] := orig -- initially detect changes against the original + for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) { - if ( builder.hasGeometryAttribute( 'normal' ) ) { + buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ]; - const skinNormal = this.getSkinnedNormal(); + } - normalLocal.assign( skinNormal ); + // Add to identity for additive + this._setIdentity(); - if ( builder.hasGeometryAttribute( 'tangent' ) ) { + this.cumulativeWeight = 0; + this.cumulativeWeightAdditive = 0; - tangentLocal.assign( skinNormal ); + } - } + // apply the state previously taken via 'saveOriginalState' to the binding + restoreOriginalState() { - } + const originalValueOffset = this.valueSize * 3; + this.binding.setValue( this.buffer, originalValueOffset ); } - generate( builder, output ) { + _setAdditiveIdentityNumeric() { - if ( output !== 'void' ) { + const startIndex = this._addIndex * this.valueSize; + const endIndex = startIndex + this.valueSize; - return positionLocal.build( builder, output ); + for ( let i = startIndex; i < endIndex; i ++ ) { + + this.buffer[ i ] = 0; } } - update( frame ) { + _setAdditiveIdentityQuaternion() { - const object = this.useReference ? frame.object : this.skinnedMesh; - const skeleton = object.skeleton; + this._setAdditiveIdentityNumeric(); + this.buffer[ this._addIndex * this.valueSize + 3 ] = 1; - if ( _frameId.get( skeleton ) === frame.frameId ) return; + } - _frameId.set( skeleton, frame.frameId ); + _setAdditiveIdentityOther() { - if ( this.previousBoneMatricesNode !== null ) skeleton.previousBoneMatrices.set( skeleton.boneMatrices ); + const startIndex = this._origIndex * this.valueSize; + const targetIndex = this._addIndex * this.valueSize; - skeleton.update(); + for ( let i = 0; i < this.valueSize; i ++ ) { - } + this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ]; -} + } -SkinningNode.type = /*@__PURE__*/ registerNode( 'Skinning', SkinningNode ); + } -const skinning = ( skinnedMesh ) => nodeObject( new SkinningNode( skinnedMesh ) ); -const skinningReference = ( skinnedMesh ) => nodeObject( new SkinningNode( skinnedMesh, true ) ); -class LoopNode extends Node { + // mix functions - constructor( params = [] ) { + _select( buffer, dstOffset, srcOffset, t, stride ) { - super(); + if ( t >= 0.5 ) { - this.params = params; + for ( let i = 0; i !== stride; ++ i ) { - } + buffer[ dstOffset + i ] = buffer[ srcOffset + i ]; - getVarName( index ) { + } - return String.fromCharCode( 'i'.charCodeAt() + index ); + } } - getProperties( builder ) { + _slerp( buffer, dstOffset, srcOffset, t ) { - const properties = builder.getNodeProperties( this ); + Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t ); - if ( properties.stackNode !== undefined ) return properties; + } - // + _slerpAdditive( buffer, dstOffset, srcOffset, t, stride ) { - const inputs = {}; + const workOffset = this._workIndex * stride; - for ( let i = 0, l = this.params.length - 1; i < l; i ++ ) { + // Store result in intermediate buffer offset + Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset ); - const param = this.params[ i ]; + // Slerp to the intermediate result + Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t ); - const name = ( param.isNode !== true && param.name ) || this.getVarName( i ); - const type = ( param.isNode !== true && param.type ) || 'int'; + } - inputs[ name ] = expression( name, type ); + _lerp( buffer, dstOffset, srcOffset, t, stride ) { - } + const s = 1 - t; - const stack = builder.addStack(); // TODO: cache() it + for ( let i = 0; i !== stride; ++ i ) { - properties.returnsNode = this.params[ this.params.length - 1 ]( inputs, stack, builder ); - properties.stackNode = stack; + const j = dstOffset + i; - builder.removeStack(); + buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t; - return properties; + } } - getNodeType( builder ) { + _lerpAdditive( buffer, dstOffset, srcOffset, t, stride ) { - const { returnsNode } = this.getProperties( builder ); + for ( let i = 0; i !== stride; ++ i ) { - return returnsNode ? returnsNode.getNodeType( builder ) : 'void'; + const j = dstOffset + i; - } + buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t; - setup( builder ) { + } - // setup properties + } - this.getProperties( builder ); +} - } +// Characters [].:/ are reserved for track binding syntax. +const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/'; +const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' ); - generate( builder ) { +// Attempts to allow node names from any language. ES5's `\w` regexp matches +// only latin characters, and the unicode \p{L} is not yet supported. So +// instead, we exclude reserved characters and match everything else. +const _wordChar = '[^' + _RESERVED_CHARS_RE + ']'; +const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']'; - const properties = this.getProperties( builder ); +// Parent directories, delimited by '/' or ':'. Currently unused, but must +// be matched to parse the rest of the track name. +const _directoryRe = /*@__PURE__*/ /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar ); - const params = this.params; - const stackNode = properties.stackNode; +// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'. +const _nodeRe = /*@__PURE__*/ /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot ); - for ( let i = 0, l = params.length - 1; i < l; i ++ ) { +// Object on target node, and accessor. May not contain reserved +// characters. Accessor may contain any character except closing bracket. +const _objectRe = /*@__PURE__*/ /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar ); - const param = params[ i ]; +// Property and accessor. May not contain reserved characters. Accessor may +// contain any non-bracket characters. +const _propertyRe = /*@__PURE__*/ /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar ); - let start = null, end = null, name = null, type = null, condition = null, update = null; +const _trackRe = new RegExp( '' + + '^' + + _directoryRe + + _nodeRe + + _objectRe + + _propertyRe + + '$' +); - if ( param.isNode ) { +const _supportedObjectNames = [ 'material', 'materials', 'bones', 'map' ]; - type = 'int'; - name = this.getVarName( i ); - start = '0'; - end = param.build( builder, type ); - condition = '<'; +class Composite { - } else { + constructor( targetGroup, path, optionalParsedPath ) { - type = param.type || 'int'; - name = param.name || this.getVarName( i ); - start = param.start; - end = param.end; - condition = param.condition; - update = param.update; + const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path ); - if ( typeof start === 'number' ) start = start.toString(); - else if ( start && start.isNode ) start = start.build( builder, type ); + this._targetGroup = targetGroup; + this._bindings = targetGroup.subscribe_( path, parsedPath ); - if ( typeof end === 'number' ) end = end.toString(); - else if ( end && end.isNode ) end = end.build( builder, type ); + } - if ( start !== undefined && end === undefined ) { + getValue( array, offset ) { - start = start + ' - 1'; - end = '0'; - condition = '>='; + this.bind(); // bind all binding - } else if ( end !== undefined && start === undefined ) { + const firstValidIndex = this._targetGroup.nCachedObjects_, + binding = this._bindings[ firstValidIndex ]; - start = '0'; - condition = '<'; + // and only call .getValue on the first + if ( binding !== undefined ) binding.getValue( array, offset ); - } + } - if ( condition === undefined ) { + setValue( array, offset ) { - if ( Number( start ) > Number( end ) ) { + const bindings = this._bindings; - condition = '>='; + for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { - } else { + bindings[ i ].setValue( array, offset ); - condition = '<'; + } - } + } - } + bind() { - } + const bindings = this._bindings; - const internalParam = { start, end, condition }; + for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { - // + bindings[ i ].bind(); - const startSnippet = internalParam.start; - const endSnippet = internalParam.end; + } - let declarationSnippet = ''; - let conditionalSnippet = ''; - let updateSnippet = ''; + } - if ( ! update ) { + unbind() { - if ( type === 'int' || type === 'uint' ) { + const bindings = this._bindings; - if ( condition.includes( '<' ) ) update = '++'; - else update = '--'; + for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { - } else { + bindings[ i ].unbind(); - if ( condition.includes( '<' ) ) update = '+= 1.'; - else update = '-= 1.'; + } - } + } - } +} - declarationSnippet += builder.getVar( type, name ) + ' = ' + startSnippet; +// Note: This class uses a State pattern on a per-method basis: +// 'bind' sets 'this.getValue' / 'setValue' and shadows the +// prototype version of these methods with one that represents +// the bound state. When the property is not found, the methods +// become no-ops. +class PropertyBinding { - conditionalSnippet += name + ' ' + condition + ' ' + endSnippet; - updateSnippet += name + ' ' + update; + constructor( rootNode, path, parsedPath ) { - const forSnippet = `for ( ${ declarationSnippet }; ${ conditionalSnippet }; ${ updateSnippet } )`; + this.path = path; + this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path ); - builder.addFlowCode( ( i === 0 ? '\n' : '' ) + builder.tab + forSnippet + ' {\n\n' ).addFlowTab(); + this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ); - } + this.rootNode = rootNode; - const stackSnippet = stackNode.build( builder, 'void' ); + // initial state of these methods that calls 'bind' + this.getValue = this._getValue_unbound; + this.setValue = this._setValue_unbound; - const returnsSnippet = properties.returnsNode ? properties.returnsNode.build( builder ) : ''; + } - builder.removeFlowTab().addFlowCode( '\n' + builder.tab + stackSnippet ); - for ( let i = 0, l = this.params.length - 1; i < l; i ++ ) { + static create( root, path, parsedPath ) { - builder.addFlowCode( ( i === 0 ? '' : builder.tab ) + '}\n\n' ).removeFlowTab(); + if ( ! ( root && root.isAnimationObjectGroup ) ) { - } + return new PropertyBinding( root, path, parsedPath ); - builder.addFlowTab(); + } else { - return returnsSnippet; + return new PropertyBinding.Composite( root, path, parsedPath ); + + } } -} + /** + * Replaces spaces with underscores and removes unsupported characters from + * node names, to ensure compatibility with parseTrackName(). + * + * @param {string} name Node name to be sanitized. + * @return {string} + */ + static sanitizeNodeName( name ) { -LoopNode.type = /*@__PURE__*/ registerNode( 'Loop', LoopNode ); + return name.replace( /\s/g, '_' ).replace( _reservedRe, '' ); -const Loop = ( ...params ) => nodeObject( new LoopNode( nodeArray( params, 'int' ) ) ).append(); -const Continue = () => expression( 'continue' ).append(); -const Break = () => expression( 'break' ).append(); + } -const _morphTextures = /*@__PURE__*/ new WeakMap(); -const _morphVec4 = /*@__PURE__*/ new Vector4(); + static parseTrackName( trackName ) { -const getMorph = /*@__PURE__*/ Fn( ( { bufferMap, influence, stride, width, depth, offset } ) => { + const matches = _trackRe.exec( trackName ); - const texelIndex = int( vertexIndex ).mul( stride ).add( offset ); + if ( matches === null ) { - const y = texelIndex.div( width ); - const x = texelIndex.sub( y.mul( width ) ); + throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName ); - const bufferAttrib = textureLoad( bufferMap, ivec2( x, y ) ).depth( depth ); + } - return bufferAttrib.mul( influence ); + const results = { + // directoryName: matches[ 1 ], // (tschw) currently unused + nodeName: matches[ 2 ], + objectName: matches[ 3 ], + objectIndex: matches[ 4 ], + propertyName: matches[ 5 ], // required + propertyIndex: matches[ 6 ] + }; -} ); + const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' ); -function getEntry( geometry ) { + if ( lastDot !== undefined && lastDot !== - 1 ) { - const hasMorphPosition = geometry.morphAttributes.position !== undefined; - const hasMorphNormals = geometry.morphAttributes.normal !== undefined; - const hasMorphColors = geometry.morphAttributes.color !== undefined; + const objectName = results.nodeName.substring( lastDot + 1 ); - // instead of using attributes, the WebGL 2 code path encodes morph targets - // into an array of data textures. Each layer represents a single morph target. + // Object names must be checked against an allowlist. Otherwise, there + // is no way to parse 'foo.bar.baz': 'baz' must be a property, but + // 'bar' could be the objectName, or part of a nodeName (which can + // include '.' characters). + if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) { - const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; - const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; + results.nodeName = results.nodeName.substring( 0, lastDot ); + results.objectName = objectName; - let entry = _morphTextures.get( geometry ); + } - if ( entry === undefined || entry.count !== morphTargetsCount ) { + } - if ( entry !== undefined ) entry.texture.dispose(); + if ( results.propertyName === null || results.propertyName.length === 0 ) { - const morphTargets = geometry.morphAttributes.position || []; - const morphNormals = geometry.morphAttributes.normal || []; - const morphColors = geometry.morphAttributes.color || []; + throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName ); - let vertexDataCount = 0; + } - if ( hasMorphPosition === true ) vertexDataCount = 1; - if ( hasMorphNormals === true ) vertexDataCount = 2; - if ( hasMorphColors === true ) vertexDataCount = 3; + return results; - let width = geometry.attributes.position.count * vertexDataCount; - let height = 1; + } - const maxTextureSize = 4096; // @TODO: Use 'capabilities.maxTextureSize' + static findNode( root, nodeName ) { - if ( width > maxTextureSize ) { + if ( nodeName === undefined || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) { - height = Math.ceil( width / maxTextureSize ); - width = maxTextureSize; + return root; } - const buffer = new Float32Array( width * height * 4 * morphTargetsCount ); - - const bufferTexture = new DataArrayTexture( buffer, width, height, morphTargetsCount ); - bufferTexture.type = FloatType; - bufferTexture.needsUpdate = true; + // search into skeleton bones. + if ( root.skeleton ) { - // fill buffer + const bone = root.skeleton.getBoneByName( nodeName ); - const vertexDataStride = vertexDataCount * 4; + if ( bone !== undefined ) { - for ( let i = 0; i < morphTargetsCount; i ++ ) { + return bone; - const morphTarget = morphTargets[ i ]; - const morphNormal = morphNormals[ i ]; - const morphColor = morphColors[ i ]; + } - const offset = width * height * 4 * i; + } - for ( let j = 0; j < morphTarget.count; j ++ ) { + // search into node subtree. + if ( root.children ) { - const stride = j * vertexDataStride; + const searchNodeSubtree = function ( children ) { - if ( hasMorphPosition === true ) { + for ( let i = 0; i < children.length; i ++ ) { - _morphVec4.fromBufferAttribute( morphTarget, j ); + const childNode = children[ i ]; - buffer[ offset + stride + 0 ] = _morphVec4.x; - buffer[ offset + stride + 1 ] = _morphVec4.y; - buffer[ offset + stride + 2 ] = _morphVec4.z; - buffer[ offset + stride + 3 ] = 0; + if ( childNode.name === nodeName || childNode.uuid === nodeName ) { - } + return childNode; - if ( hasMorphNormals === true ) { + } - _morphVec4.fromBufferAttribute( morphNormal, j ); + const result = searchNodeSubtree( childNode.children ); - buffer[ offset + stride + 4 ] = _morphVec4.x; - buffer[ offset + stride + 5 ] = _morphVec4.y; - buffer[ offset + stride + 6 ] = _morphVec4.z; - buffer[ offset + stride + 7 ] = 0; + if ( result ) return result; } - if ( hasMorphColors === true ) { + return null; - _morphVec4.fromBufferAttribute( morphColor, j ); + }; - buffer[ offset + stride + 8 ] = _morphVec4.x; - buffer[ offset + stride + 9 ] = _morphVec4.y; - buffer[ offset + stride + 10 ] = _morphVec4.z; - buffer[ offset + stride + 11 ] = ( morphColor.itemSize === 4 ) ? _morphVec4.w : 1; + const subTreeNode = searchNodeSubtree( root.children ); - } + if ( subTreeNode ) { + + return subTreeNode; } } - entry = { - count: morphTargetsCount, - texture: bufferTexture, - stride: vertexDataCount, - size: new Vector2( width, height ) - }; - - _morphTextures.set( geometry, entry ); - - function disposeTexture() { + return null; - bufferTexture.dispose(); + } - _morphTextures.delete( geometry ); + // these are used to "bind" a nonexistent property + _getValue_unavailable() {} + _setValue_unavailable() {} - geometry.removeEventListener( 'dispose', disposeTexture ); + // Getters - } + _getValue_direct( buffer, offset ) { - geometry.addEventListener( 'dispose', disposeTexture ); + buffer[ offset ] = this.targetObject[ this.propertyName ]; } - return entry; - -} - - -class MorphNode extends Node { + _getValue_array( buffer, offset ) { - constructor( mesh ) { + const source = this.resolvedProperty; - super( 'void' ); + for ( let i = 0, n = source.length; i !== n; ++ i ) { - this.mesh = mesh; - this.morphBaseInfluence = uniform( 1 ); + buffer[ offset ++ ] = source[ i ]; - this.updateType = NodeUpdateType.OBJECT; + } } - setup( builder ) { + _getValue_arrayElement( buffer, offset ) { - const { geometry } = builder; + buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ]; - const hasMorphPosition = geometry.morphAttributes.position !== undefined; - const hasMorphNormals = geometry.hasAttribute( 'normal' ) && geometry.morphAttributes.normal !== undefined; + } - const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; - const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; + _getValue_toArray( buffer, offset ) { - // nodes + this.resolvedProperty.toArray( buffer, offset ); - const { texture: bufferMap, stride, size } = getEntry( geometry ); + } - if ( hasMorphPosition === true ) positionLocal.mulAssign( this.morphBaseInfluence ); - if ( hasMorphNormals === true ) normalLocal.mulAssign( this.morphBaseInfluence ); + // Direct - const width = int( size.width ); + _setValue_direct( buffer, offset ) { - Loop( morphTargetsCount, ( { i } ) => { + this.targetObject[ this.propertyName ] = buffer[ offset ]; - const influence = float( 0 ).toVar(); + } - if ( this.mesh.count > 1 && ( this.mesh.morphTexture !== null && this.mesh.morphTexture !== undefined ) ) { + _setValue_direct_setNeedsUpdate( buffer, offset ) { - influence.assign( textureLoad( this.mesh.morphTexture, ivec2( int( i ).add( 1 ), int( instanceIndex ) ) ).r ); + this.targetObject[ this.propertyName ] = buffer[ offset ]; + this.targetObject.needsUpdate = true; - } else { + } - influence.assign( reference( 'morphTargetInfluences', 'float' ).element( i ).toVar() ); + _setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) { - } + this.targetObject[ this.propertyName ] = buffer[ offset ]; + this.targetObject.matrixWorldNeedsUpdate = true; - if ( hasMorphPosition === true ) { + } - positionLocal.addAssign( getMorph( { - bufferMap, - influence, - stride, - width, - depth: i, - offset: int( 0 ) - } ) ); + // EntireArray - } + _setValue_array( buffer, offset ) { - if ( hasMorphNormals === true ) { + const dest = this.resolvedProperty; - normalLocal.addAssign( getMorph( { - bufferMap, - influence, - stride, - width, - depth: i, - offset: int( 1 ) - } ) ); + for ( let i = 0, n = dest.length; i !== n; ++ i ) { - } + dest[ i ] = buffer[ offset ++ ]; - } ); + } } - update() { - - const morphBaseInfluence = this.morphBaseInfluence; - - if ( this.mesh.geometry.morphTargetsRelative ) { + _setValue_array_setNeedsUpdate( buffer, offset ) { - morphBaseInfluence.value = 1; + const dest = this.resolvedProperty; - } else { + for ( let i = 0, n = dest.length; i !== n; ++ i ) { - morphBaseInfluence.value = 1 - this.mesh.morphTargetInfluences.reduce( ( a, b ) => a + b, 0 ); + dest[ i ] = buffer[ offset ++ ]; } - } + this.targetObject.needsUpdate = true; -} + } -MorphNode.type = /*@__PURE__*/ registerNode( 'Morph', MorphNode ); + _setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) { -const morphReference = /*@__PURE__*/ nodeProxy( MorphNode ); + const dest = this.resolvedProperty; -const sortLights = ( lights ) => { + for ( let i = 0, n = dest.length; i !== n; ++ i ) { - return lights.sort( ( a, b ) => a.id - b.id ); + dest[ i ] = buffer[ offset ++ ]; -}; + } -const getLightNodeById = ( id, lightNodes ) => { + this.targetObject.matrixWorldNeedsUpdate = true; - for ( const lightNode of lightNodes ) { + } - if ( lightNode.isAnalyticLightNode && lightNode.light.id === id ) { + // ArrayElement - return lightNode; + _setValue_arrayElement( buffer, offset ) { - } + this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; } - return null; - -}; + _setValue_arrayElement_setNeedsUpdate( buffer, offset ) { -class LightsNode extends Node { + this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; + this.targetObject.needsUpdate = true; - constructor( lights = [] ) { + } - super( 'vec3' ); + _setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) { - this.totalDiffuseNode = vec3().toVar( 'totalDiffuse' ); - this.totalSpecularNode = vec3().toVar( 'totalSpecular' ); + this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; + this.targetObject.matrixWorldNeedsUpdate = true; - this.outgoingLightNode = vec3().toVar( 'outgoingLight' ); + } - this._lights = lights; + // HasToFromArray - this._lightNodes = null; - this._lightNodesHash = null; + _setValue_fromArray( buffer, offset ) { - this.global = true; + this.resolvedProperty.fromArray( buffer, offset ); } - getHash( builder ) { - - if ( this._lightNodesHash === null ) { - - if ( this._lightNodes === null ) this.setupLightsNode( builder ); + _setValue_fromArray_setNeedsUpdate( buffer, offset ) { - const hash = []; + this.resolvedProperty.fromArray( buffer, offset ); + this.targetObject.needsUpdate = true; - for ( const lightNode of this._lightNodes ) { + } - hash.push( lightNode.getHash() ); + _setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) { - } + this.resolvedProperty.fromArray( buffer, offset ); + this.targetObject.matrixWorldNeedsUpdate = true; - this._lightNodesHash = 'lights-' + hash.join( ',' ); + } - } + _getValue_unbound( targetArray, offset ) { - return this._lightNodesHash; + this.bind(); + this.getValue( targetArray, offset ); } - analyze( builder ) { + _setValue_unbound( sourceArray, offset ) { - const properties = builder.getDataFromNode( this ); + this.bind(); + this.setValue( sourceArray, offset ); - for ( const node of properties.nodes ) { + } - node.build( builder ); + // create getter / setter pair for a property in the scene graph + bind() { - } + let targetObject = this.node; + const parsedPath = this.parsedPath; - } + const objectName = parsedPath.objectName; + const propertyName = parsedPath.propertyName; + let propertyIndex = parsedPath.propertyIndex; - setupLightsNode( builder ) { + if ( ! targetObject ) { - const lightNodes = []; + targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ); - const previousLightNodes = this._lightNodes; + this.node = targetObject; - const lights = sortLights( this._lights ); - const nodeLibrary = builder.renderer.nodes.library; + } - for ( const light of lights ) { + // set fail state so we can just 'return' on error + this.getValue = this._getValue_unavailable; + this.setValue = this._setValue_unavailable; - if ( light.isNode ) { + // ensure there is a value node + if ( ! targetObject ) { - lightNodes.push( nodeObject( light ) ); + console.warn( 'THREE.PropertyBinding: No target node found for track: ' + this.path + '.' ); + return; - } else { + } - let lightNode = null; + if ( objectName ) { - if ( previousLightNodes !== null ) { + let objectIndex = parsedPath.objectIndex; - lightNode = getLightNodeById( light.id, previousLightNodes ); // resuse existing light node + // special cases were we need to reach deeper into the hierarchy to get the face materials.... + switch ( objectName ) { - } + case 'materials': - if ( lightNode === null ) { + if ( ! targetObject.material ) { - const lightNodeClass = nodeLibrary.getLightNodeClass( light.constructor ); + console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); + return; - if ( lightNodeClass === undefined ) { + } - console.warn( `LightsNode.setupNodeLights: Light node not found for ${ light.constructor.name }` ); - continue; + if ( ! targetObject.material.materials ) { + + console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this ); + return; } - lightNodes.push( nodeObject( new lightNodeClass( light ) ) ); + targetObject = targetObject.material.materials; - } + break; - } + case 'bones': - } + if ( ! targetObject.skeleton ) { - this._lightNodes = lightNodes; + console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this ); + return; - } + } - setup( builder ) { + // potential future optimization: skip this if propertyIndex is already an integer + // and convert the integer string to a true integer. - if ( this._lightNodes === null ) this.setupLightsNode( builder ); + targetObject = targetObject.skeleton.bones; - const context = builder.context; - const lightingModel = context.lightingModel; + // support resolving morphTarget names into indices. + for ( let i = 0; i < targetObject.length; i ++ ) { - let outgoingLightNode = this.outgoingLightNode; + if ( targetObject[ i ].name === objectIndex ) { - if ( lightingModel ) { + objectIndex = i; + break; - const { _lightNodes, totalDiffuseNode, totalSpecularNode } = this; + } - context.outgoingLight = outgoingLightNode; + } - const stack = builder.addStack(); + break; - // + case 'map': - const properties = builder.getDataFromNode( this ); - properties.nodes = stack.nodes; + if ( 'map' in targetObject ) { - // + targetObject = targetObject.map; + break; - lightingModel.start( context, stack, builder ); + } - // lights + if ( ! targetObject.material ) { - for ( const lightNode of _lightNodes ) { + console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); + return; - lightNode.build( builder ); + } - } + if ( ! targetObject.material.map ) { - // + console.error( 'THREE.PropertyBinding: Can not bind to material.map as node.material does not have a map.', this ); + return; - lightingModel.indirect( context, stack, builder ); + } - // + targetObject = targetObject.material.map; + break; - const { backdrop, backdropAlpha } = context; - const { directDiffuse, directSpecular, indirectDiffuse, indirectSpecular } = context.reflectedLight; + default: - let totalDiffuse = directDiffuse.add( indirectDiffuse ); + if ( targetObject[ objectName ] === undefined ) { - if ( backdrop !== null ) { + console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this ); + return; - if ( backdropAlpha !== null ) { + } - totalDiffuse = vec3( backdropAlpha.mix( totalDiffuse, backdrop ) ); + targetObject = targetObject[ objectName ]; - } else { + } - totalDiffuse = vec3( backdrop ); + + if ( objectIndex !== undefined ) { + + if ( targetObject[ objectIndex ] === undefined ) { + + console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject ); + return; } - context.material.transparent = true; + targetObject = targetObject[ objectIndex ]; } - totalDiffuseNode.assign( totalDiffuse ); - totalSpecularNode.assign( directSpecular.add( indirectSpecular ) ); - - outgoingLightNode.assign( totalDiffuseNode.add( totalSpecularNode ) ); + } - // + // resolve property + const nodeProperty = targetObject[ propertyName ]; - lightingModel.finish( context, stack, builder ); + if ( nodeProperty === undefined ) { - // + const nodeName = parsedPath.nodeName; - outgoingLightNode = outgoingLightNode.bypass( builder.removeStack() ); + console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName + + '.' + propertyName + ' but it wasn\'t found.', targetObject ); + return; } - return outgoingLightNode; + // determine versioning scheme + let versioning = this.Versioning.None; - } + this.targetObject = targetObject; - setLights( lights ) { + if ( targetObject.needsUpdate !== undefined ) { // material - this._lights = lights; + versioning = this.Versioning.NeedsUpdate; - this._lightNodes = null; - this._lightNodesHash = null; + } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform - return this; + versioning = this.Versioning.MatrixWorldNeedsUpdate; - } + } - getLights() { + // determine how the property gets bound + let bindingType = this.BindingType.Direct; - return this._lights; + if ( propertyIndex !== undefined ) { - } + // access a sub element of the property array (only primitives are supported right now) -} + if ( propertyName === 'morphTargetInfluences' ) { -LightsNode.type = /*@__PURE__*/ registerNode( 'Lights', LightsNode ); + // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer. -const lights = /*@__PURE__*/ nodeProxy( LightsNode ); + // support resolving morphTarget names into indices. + if ( ! targetObject.geometry ) { -class LightingNode extends Node { + console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this ); + return; - constructor() { + } - super( 'vec3' ); + if ( ! targetObject.geometry.morphAttributes ) { - this.isLightingNode = true; + console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this ); + return; - } + } - generate( /*builder*/ ) { + if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) { - console.warn( 'Abstract function.' ); + propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ]; - } + } -} + } -LightingNode.type = /*@__PURE__*/ registerNode( 'Lighting', LightingNode ); + bindingType = this.BindingType.ArrayElement; -class AONode extends LightingNode { + this.resolvedProperty = nodeProperty; + this.propertyIndex = propertyIndex; - constructor( aoNode = null ) { + } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) { - super(); + // must use copy for Object3D.Euler/Quaternion - this.aoNode = aoNode; + bindingType = this.BindingType.HasFromToArray; - } + this.resolvedProperty = nodeProperty; - setup( builder ) { + } else if ( Array.isArray( nodeProperty ) ) { - builder.context.ambientOcclusion.mulAssign( this.aoNode ); + bindingType = this.BindingType.EntireArray; - } + this.resolvedProperty = nodeProperty; -} + } else { -AONode.type = /*@__PURE__*/ registerNode( 'AO', AONode ); + this.propertyName = propertyName; -class LightingContextNode extends ContextNode { + } - constructor( node, lightingModel = null, backdropNode = null, backdropAlphaNode = null ) { + // select getter / setter + this.getValue = this.GetterByBindingType[ bindingType ]; + this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ]; - super( node ); + } - this.lightingModel = lightingModel; - this.backdropNode = backdropNode; - this.backdropAlphaNode = backdropAlphaNode; + unbind() { - this._value = null; + this.node = null; - } + // back to the prototype version of getValue / setValue + // note: avoiding to mutate the shape of 'this' via 'delete' + this.getValue = this._getValue_unbound; + this.setValue = this._setValue_unbound; - getContext() { + } - const { backdropNode, backdropAlphaNode } = this; +} - const directDiffuse = vec3().toVar( 'directDiffuse' ), - directSpecular = vec3().toVar( 'directSpecular' ), - indirectDiffuse = vec3().toVar( 'indirectDiffuse' ), - indirectSpecular = vec3().toVar( 'indirectSpecular' ); +PropertyBinding.Composite = Composite; - const reflectedLight = { - directDiffuse, - directSpecular, - indirectDiffuse, - indirectSpecular - }; +PropertyBinding.prototype.BindingType = { + Direct: 0, + EntireArray: 1, + ArrayElement: 2, + HasFromToArray: 3 +}; - const context = { - radiance: vec3().toVar( 'radiance' ), - irradiance: vec3().toVar( 'irradiance' ), - iblIrradiance: vec3().toVar( 'iblIrradiance' ), - ambientOcclusion: float( 1 ).toVar( 'ambientOcclusion' ), - reflectedLight, - backdrop: backdropNode, - backdropAlpha: backdropAlphaNode - }; +PropertyBinding.prototype.Versioning = { + None: 0, + NeedsUpdate: 1, + MatrixWorldNeedsUpdate: 2 +}; - return context; +PropertyBinding.prototype.GetterByBindingType = [ - } + PropertyBinding.prototype._getValue_direct, + PropertyBinding.prototype._getValue_array, + PropertyBinding.prototype._getValue_arrayElement, + PropertyBinding.prototype._getValue_toArray, - setup( builder ) { +]; - this.value = this._value || ( this._value = this.getContext() ); - this.value.lightingModel = this.lightingModel || builder.context.lightingModel; +PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [ - return super.setup( builder ); + [ + // Direct + PropertyBinding.prototype._setValue_direct, + PropertyBinding.prototype._setValue_direct_setNeedsUpdate, + PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate, - } + ], [ -} + // EntireArray -LightingContextNode.type = /*@__PURE__*/ registerNode( 'LightingContext', LightingContextNode ); + PropertyBinding.prototype._setValue_array, + PropertyBinding.prototype._setValue_array_setNeedsUpdate, + PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate, -const lightingContext = /*@__PURE__*/ nodeProxy( LightingContextNode ); + ], [ -class IrradianceNode extends LightingNode { + // ArrayElement + PropertyBinding.prototype._setValue_arrayElement, + PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate, + PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate, - constructor( node ) { + ], [ - super(); + // HasToFromArray + PropertyBinding.prototype._setValue_fromArray, + PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate, + PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate, - this.node = node; + ] - } +]; - setup( builder ) { +/** + * + * A group of objects that receives a shared animation state. + * + * Usage: + * + * - Add objects you would otherwise pass as 'root' to the + * constructor or the .clipAction method of AnimationMixer. + * + * - Instead pass this object as 'root'. + * + * - You can also add and remove objects later when the mixer + * is running. + * + * Note: + * + * Objects of this class appear as one object to the mixer, + * so cache control of the individual objects must be done + * on the group. + * + * Limitation: + * + * - The animated properties must be compatible among the + * all objects in the group. + * + * - A single property can either be controlled through a + * target group or directly, but not both. + */ - builder.context.irradiance.addAssign( this.node ); +class AnimationObjectGroup { - } + constructor() { -} + this.isAnimationObjectGroup = true; -IrradianceNode.type = /*@__PURE__*/ registerNode( 'Irradiance', IrradianceNode ); + this.uuid = generateUUID(); -let resolution, viewportResult; + // cached objects followed by the active ones + this._objects = Array.prototype.slice.call( arguments ); -class ViewportNode extends Node { + this.nCachedObjects_ = 0; // threshold + // note: read by PropertyBinding.Composite - constructor( scope ) { + const indices = {}; + this._indicesByUUID = indices; // for bookkeeping - super(); + for ( let i = 0, n = arguments.length; i !== n; ++ i ) { - this.scope = scope; + indices[ arguments[ i ].uuid ] = i; - this.isViewportNode = true; + } - } + this._paths = []; // inside: string + this._parsedPaths = []; // inside: { we don't care, here } + this._bindings = []; // inside: Array< PropertyBinding > + this._bindingsIndicesByPath = {}; // inside: indices in these arrays - getNodeType() { + const scope = this; - if ( this.scope === ViewportNode.VIEWPORT ) return 'vec4'; - else return 'vec2'; + this.stats = { - } + objects: { + get total() { - getUpdateType() { + return scope._objects.length; - let updateType = NodeUpdateType.NONE; + }, + get inUse() { - if ( this.scope === ViewportNode.RESOLUTION || this.scope === ViewportNode.VIEWPORT ) { + return this.total - scope.nCachedObjects_; - updateType = NodeUpdateType.RENDER; + } + }, + get bindingsPerObject() { - } + return scope._bindings.length; - this.updateType = updateType; + } - return updateType; + }; } - update( { renderer } ) { + add() { - if ( this.scope === ViewportNode.VIEWPORT ) { + const objects = this._objects, + indicesByUUID = this._indicesByUUID, + paths = this._paths, + parsedPaths = this._parsedPaths, + bindings = this._bindings, + nBindings = bindings.length; - renderer.getViewport( viewportResult ); + let knownObject = undefined, + nObjects = objects.length, + nCachedObjects = this.nCachedObjects_; - } else { + for ( let i = 0, n = arguments.length; i !== n; ++ i ) { - renderer.getDrawingBufferSize( resolution ); + const object = arguments[ i ], + uuid = object.uuid; + let index = indicesByUUID[ uuid ]; - } + if ( index === undefined ) { - } + // unknown object -> add it to the ACTIVE region - setup( /*builder*/ ) { + index = nObjects ++; + indicesByUUID[ uuid ] = index; + objects.push( object ); - const scope = this.scope; + // accounting is done, now do the same for all bindings - let output = null; + for ( let j = 0, m = nBindings; j !== m; ++ j ) { - if ( scope === ViewportNode.RESOLUTION ) { + bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) ); - output = uniform( resolution || ( resolution = new Vector2() ) ); + } - } else if ( scope === ViewportNode.VIEWPORT ) { + } else if ( index < nCachedObjects ) { - output = uniform( viewportResult || ( viewportResult = new Vector4() ) ); + knownObject = objects[ index ]; - } else { + // move existing object to the ACTIVE region - output = vec2( viewportCoordinate.div( viewportResolution ) ); + const firstActiveIndex = -- nCachedObjects, + lastCachedObject = objects[ firstActiveIndex ]; - } + indicesByUUID[ lastCachedObject.uuid ] = index; + objects[ index ] = lastCachedObject; - return output; + indicesByUUID[ uuid ] = firstActiveIndex; + objects[ firstActiveIndex ] = object; - } + // accounting is done, now do the same for all bindings - generate( builder ) { + for ( let j = 0, m = nBindings; j !== m; ++ j ) { - if ( this.scope === ViewportNode.COORDINATE ) { + const bindingsForPath = bindings[ j ], + lastCached = bindingsForPath[ firstActiveIndex ]; - let coord = builder.getFragCoord(); + let binding = bindingsForPath[ index ]; - if ( builder.isFlipY() ) { + bindingsForPath[ index ] = lastCached; - // follow webgpu standards + if ( binding === undefined ) { - const resolution = builder.getNodeProperties( viewportResolution ).outputNode.build( builder ); + // since we do not bother to create new bindings + // for objects that are cached, the binding may + // or may not exist - coord = `${ builder.getType( 'vec2' ) }( ${ coord }.x, ${ resolution }.y - ${ coord }.y )`; + binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ); - } + } - return coord; + bindingsForPath[ firstActiveIndex ] = binding; - } + } - return super.generate( builder ); + } else if ( objects[ index ] !== knownObject ) { - } + console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' + + 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' ); -} + } // else the object is already where we want it to be -ViewportNode.COORDINATE = 'coordinate'; -ViewportNode.RESOLUTION = 'resolution'; -ViewportNode.VIEWPORT = 'viewport'; -ViewportNode.UV = 'uv'; + } // for arguments -ViewportNode.type = /*@__PURE__*/ registerNode( 'Viewport', ViewportNode ); + this.nCachedObjects_ = nCachedObjects; -const viewportCoordinate = /*@__PURE__*/ nodeImmutable( ViewportNode, ViewportNode.COORDINATE ); -const viewportResolution = /*@__PURE__*/ nodeImmutable( ViewportNode, ViewportNode.RESOLUTION ); -const viewport = /*@__PURE__*/ nodeImmutable( ViewportNode, ViewportNode.VIEWPORT ); -const viewportUV = /*@__PURE__*/ nodeImmutable( ViewportNode, ViewportNode.UV ); + } -const viewportTopLeft = /*@__PURE__*/ ( Fn( () => { // @deprecated, r168 + remove() { - console.warn( 'TSL.ViewportNode: "viewportTopLeft" is deprecated. Use "viewportUV" instead.' ); + const objects = this._objects, + indicesByUUID = this._indicesByUUID, + bindings = this._bindings, + nBindings = bindings.length; - return viewportUV; + let nCachedObjects = this.nCachedObjects_; -}, 'vec2' ).once() )(); + for ( let i = 0, n = arguments.length; i !== n; ++ i ) { -const viewportBottomLeft = /*@__PURE__*/ ( Fn( () => { // @deprecated, r168 + const object = arguments[ i ], + uuid = object.uuid, + index = indicesByUUID[ uuid ]; - console.warn( 'TSL.ViewportNode: "viewportBottomLeft" is deprecated. Use "viewportUV.flipY()" instead.' ); + if ( index !== undefined && index >= nCachedObjects ) { - return viewportUV.flipY(); + // move existing object into the CACHED region -}, 'vec2' ).once() )(); + const lastCachedIndex = nCachedObjects ++, + firstActiveObject = objects[ lastCachedIndex ]; -const _size$a = /*@__PURE__*/ new Vector2(); + indicesByUUID[ firstActiveObject.uuid ] = index; + objects[ index ] = firstActiveObject; -class ViewportTextureNode extends TextureNode { + indicesByUUID[ uuid ] = lastCachedIndex; + objects[ lastCachedIndex ] = object; - constructor( uvNode = viewportUV, levelNode = null, framebufferTexture = null ) { + // accounting is done, now do the same for all bindings - if ( framebufferTexture === null ) { + for ( let j = 0, m = nBindings; j !== m; ++ j ) { - framebufferTexture = new FramebufferTexture(); - framebufferTexture.minFilter = LinearMipmapLinearFilter; + const bindingsForPath = bindings[ j ], + firstActive = bindingsForPath[ lastCachedIndex ], + binding = bindingsForPath[ index ]; - } + bindingsForPath[ index ] = firstActive; + bindingsForPath[ lastCachedIndex ] = binding; - super( framebufferTexture, uvNode, levelNode ); + } - this.generateMipmaps = false; + } - this.isOutputTextureNode = true; + } // for arguments - this.updateBeforeType = NodeUpdateType.FRAME; + this.nCachedObjects_ = nCachedObjects; } - updateBefore( frame ) { + // remove & forget + uncache() { - const renderer = frame.renderer; - renderer.getDrawingBufferSize( _size$a ); + const objects = this._objects, + indicesByUUID = this._indicesByUUID, + bindings = this._bindings, + nBindings = bindings.length; - // + let nCachedObjects = this.nCachedObjects_, + nObjects = objects.length; - const framebufferTexture = this.value; + for ( let i = 0, n = arguments.length; i !== n; ++ i ) { - if ( framebufferTexture.image.width !== _size$a.width || framebufferTexture.image.height !== _size$a.height ) { + const object = arguments[ i ], + uuid = object.uuid, + index = indicesByUUID[ uuid ]; - framebufferTexture.image.width = _size$a.width; - framebufferTexture.image.height = _size$a.height; - framebufferTexture.needsUpdate = true; + if ( index !== undefined ) { - } + delete indicesByUUID[ uuid ]; - // + if ( index < nCachedObjects ) { - const currentGenerateMipmaps = framebufferTexture.generateMipmaps; - framebufferTexture.generateMipmaps = this.generateMipmaps; + // object is cached, shrink the CACHED region - renderer.copyFramebufferToTexture( framebufferTexture ); + const firstActiveIndex = -- nCachedObjects, + lastCachedObject = objects[ firstActiveIndex ], + lastIndex = -- nObjects, + lastObject = objects[ lastIndex ]; - framebufferTexture.generateMipmaps = currentGenerateMipmaps; + // last cached object takes this object's place + indicesByUUID[ lastCachedObject.uuid ] = index; + objects[ index ] = lastCachedObject; - } + // last object goes to the activated slot and pop + indicesByUUID[ lastObject.uuid ] = firstActiveIndex; + objects[ firstActiveIndex ] = lastObject; + objects.pop(); - clone() { + // accounting is done, now do the same for all bindings - const viewportTextureNode = new this.constructor( this.uvNode, this.levelNode, this.value ); - viewportTextureNode.generateMipmaps = this.generateMipmaps; + for ( let j = 0, m = nBindings; j !== m; ++ j ) { - return viewportTextureNode; + const bindingsForPath = bindings[ j ], + lastCached = bindingsForPath[ firstActiveIndex ], + last = bindingsForPath[ lastIndex ]; - } + bindingsForPath[ index ] = lastCached; + bindingsForPath[ firstActiveIndex ] = last; + bindingsForPath.pop(); -} + } -ViewportTextureNode.type = /*@__PURE__*/ registerNode( 'ViewportTexture', ViewportTextureNode ); + } else { -const viewportTexture = /*@__PURE__*/ nodeProxy( ViewportTextureNode ); -const viewportMipTexture = /*@__PURE__*/ nodeProxy( ViewportTextureNode, null, null, { generateMipmaps: true } ); + // object is active, just swap with the last and pop -let sharedDepthbuffer = null; + const lastIndex = -- nObjects, + lastObject = objects[ lastIndex ]; -class ViewportDepthTextureNode extends ViewportTextureNode { + if ( lastIndex > 0 ) { - constructor( uvNode = viewportUV, levelNode = null ) { + indicesByUUID[ lastObject.uuid ] = index; - if ( sharedDepthbuffer === null ) { + } - sharedDepthbuffer = new DepthTexture(); + objects[ index ] = lastObject; + objects.pop(); - } + // accounting is done, now do the same for all bindings - super( uvNode, levelNode, sharedDepthbuffer ); + for ( let j = 0, m = nBindings; j !== m; ++ j ) { - } + const bindingsForPath = bindings[ j ]; -} + bindingsForPath[ index ] = bindingsForPath[ lastIndex ]; + bindingsForPath.pop(); -ViewportDepthTextureNode.type = /*@__PURE__*/ registerNode( 'ViewportDepthTexture', ViewportDepthTextureNode ); + } -const viewportDepthTexture = /*@__PURE__*/ nodeProxy( ViewportDepthTextureNode ); + } // cached or active -class ViewportDepthNode extends Node { + } // if object is known - constructor( scope, valueNode = null ) { + } // for arguments - super( 'float' ); + this.nCachedObjects_ = nCachedObjects; - this.scope = scope; - this.valueNode = valueNode; + } - this.isViewportDepthNode = true; + // Internal interface used by befriended PropertyBinding.Composite: - } + subscribe_( path, parsedPath ) { - generate( builder ) { + // returns an array of bindings for the given path that is changed + // according to the contained objects in the group - const { scope } = this; + const indicesByPath = this._bindingsIndicesByPath; + let index = indicesByPath[ path ]; + const bindings = this._bindings; - if ( scope === ViewportDepthNode.DEPTH_BASE ) { + if ( index !== undefined ) return bindings[ index ]; - return builder.getFragDepth(); + const paths = this._paths, + parsedPaths = this._parsedPaths, + objects = this._objects, + nObjects = objects.length, + nCachedObjects = this.nCachedObjects_, + bindingsForPath = new Array( nObjects ); - } + index = bindings.length; - return super.generate( builder ); + indicesByPath[ path ] = index; - } + paths.push( path ); + parsedPaths.push( parsedPath ); + bindings.push( bindingsForPath ); - setup( { camera } ) { + for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) { - const { scope } = this; - const value = this.valueNode; + const object = objects[ i ]; + bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath ); - let node = null; + } - if ( scope === ViewportDepthNode.DEPTH_BASE ) { + return bindingsForPath; - if ( value !== null ) { + } - node = depthBase().assign( value ); + unsubscribe_( path ) { - } + // tells the group to forget about a property path and no longer + // update the array previously obtained with 'subscribe_' - } else if ( scope === ViewportDepthNode.DEPTH ) { + const indicesByPath = this._bindingsIndicesByPath, + index = indicesByPath[ path ]; - if ( camera.isPerspectiveCamera ) { + if ( index !== undefined ) { - node = viewZToPerspectiveDepth( positionView.z, cameraNear, cameraFar ); + const paths = this._paths, + parsedPaths = this._parsedPaths, + bindings = this._bindings, + lastBindingsIndex = bindings.length - 1, + lastBindings = bindings[ lastBindingsIndex ], + lastBindingsPath = path[ lastBindingsIndex ]; - } else { + indicesByPath[ lastBindingsPath ] = index; - node = viewZToOrthographicDepth( positionView.z, cameraNear, cameraFar ); + bindings[ index ] = lastBindings; + bindings.pop(); - } + parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ]; + parsedPaths.pop(); - } else if ( scope === ViewportDepthNode.LINEAR_DEPTH ) { + paths[ index ] = paths[ lastBindingsIndex ]; + paths.pop(); - if ( value !== null ) { + } - if ( camera.isPerspectiveCamera ) { + } - const viewZ = perspectiveDepthToViewZ( value, cameraNear, cameraFar ); +} - node = viewZToOrthographicDepth( viewZ, cameraNear, cameraFar ); +class AnimationAction { - } else { + constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) { - node = value; + this._mixer = mixer; + this._clip = clip; + this._localRoot = localRoot; + this.blendMode = blendMode; - } + const tracks = clip.tracks, + nTracks = tracks.length, + interpolants = new Array( nTracks ); - } else { + const interpolantSettings = { + endingStart: ZeroCurvatureEnding, + endingEnd: ZeroCurvatureEnding + }; - node = viewZToOrthographicDepth( positionView.z, cameraNear, cameraFar ); + for ( let i = 0; i !== nTracks; ++ i ) { - } + const interpolant = tracks[ i ].createInterpolant( null ); + interpolants[ i ] = interpolant; + interpolant.settings = interpolantSettings; } - return node; + this._interpolantSettings = interpolantSettings; - } + this._interpolants = interpolants; // bound by the mixer -} + // inside: PropertyMixer (managed by the mixer) + this._propertyBindings = new Array( nTracks ); -ViewportDepthNode.DEPTH_BASE = 'depthBase'; -ViewportDepthNode.DEPTH = 'depth'; -ViewportDepthNode.LINEAR_DEPTH = 'linearDepth'; + this._cacheIndex = null; // for the memory manager + this._byClipCacheIndex = null; // for the memory manager -ViewportDepthNode.type = /*@__PURE__*/ registerNode( 'ViewportDepth', ViewportDepthNode ); + this._timeScaleInterpolant = null; + this._weightInterpolant = null; -// NOTE: viewZ, the z-coordinate in camera space, is negative for points in front of the camera + this.loop = LoopRepeat; + this._loopCount = - 1; -// -near maps to 0; -far maps to 1 -const viewZToOrthographicDepth = ( viewZ, near, far ) => viewZ.add( near ).div( near.sub( far ) ); + // global mixer time when the action is to be started + // it's set back to 'null' upon start of the action + this._startTime = null; -// maps orthographic depth in [ 0, 1 ] to viewZ -const orthographicDepthToViewZ = ( depth, near, far ) => near.sub( far ).mul( depth ).sub( near ); + // scaled local time of the action + // gets clamped or wrapped to 0..clip.duration according to loop + this.time = 0; -// NOTE: https://twitter.com/gonnavis/status/1377183786949959682 + this.timeScale = 1; + this._effectiveTimeScale = 1; -// -near maps to 0; -far maps to 1 -const viewZToPerspectiveDepth = ( viewZ, near, far ) => near.add( viewZ ).mul( far ).div( far.sub( near ).mul( viewZ ) ); + this.weight = 1; + this._effectiveWeight = 1; -// maps perspective depth in [ 0, 1 ] to viewZ -const perspectiveDepthToViewZ = ( depth, near, far ) => near.mul( far ).div( far.sub( near ).mul( depth ).sub( far ) ); + this.repetitions = Infinity; // no. of repetitions when looping -const depthBase = /*@__PURE__*/ nodeProxy( ViewportDepthNode, ViewportDepthNode.DEPTH_BASE ); + this.paused = false; // true -> zero effective time scale + this.enabled = true; // false -> zero effective weight -const depth = /*@__PURE__*/ nodeImmutable( ViewportDepthNode, ViewportDepthNode.DEPTH ); -const linearDepth = /*@__PURE__*/ nodeProxy( ViewportDepthNode, ViewportDepthNode.LINEAR_DEPTH ); -const viewportLinearDepth = /*@__PURE__*/ linearDepth( viewportDepthTexture() ); + this.clampWhenFinished = false;// keep feeding the last frame? -depth.assign = ( value ) => depthBase( value ); + this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate + this.zeroSlopeAtEnd = true;// clips for start, loop and end -class ClippingNode extends Node { + } - constructor( scope = ClippingNode.DEFAULT ) { + // State & Scheduling - super(); + play() { - this.scope = scope; + this._mixer._activateAction( this ); - } + return this; - setup( builder ) { + } - super.setup( builder ); + stop() { - const clippingContext = builder.clippingContext; - const { localClipIntersection, localClippingCount, globalClippingCount } = clippingContext; + this._mixer._deactivateAction( this ); - const numClippingPlanes = globalClippingCount + localClippingCount; - const numUnionClippingPlanes = localClipIntersection ? numClippingPlanes - localClippingCount : numClippingPlanes; + return this.reset(); - if ( this.scope === ClippingNode.ALPHA_TO_COVERAGE ) { + } - return this.setupAlphaToCoverage( clippingContext.planes, numClippingPlanes, numUnionClippingPlanes ); + reset() { - } else { + this.paused = false; + this.enabled = true; - return this.setupDefault( clippingContext.planes, numClippingPlanes, numUnionClippingPlanes ); + this.time = 0; // restart clip + this._loopCount = - 1;// forget previous loops + this._startTime = null;// forget scheduling - } + return this.stopFading().stopWarping(); } - setupAlphaToCoverage( planes, numClippingPlanes, numUnionClippingPlanes ) { - - return Fn( () => { + isRunning() { - const clippingPlanes = uniformArray( planes ); + return this.enabled && ! this.paused && this.timeScale !== 0 && + this._startTime === null && this._mixer._isActiveAction( this ); - const distanceToPlane = property( 'float', 'distanceToPlane' ); - const distanceGradient = property( 'float', 'distanceToGradient' ); + } - const clipOpacity = property( 'float', 'clipOpacity' ); + // return true when play has been called + isScheduled() { - clipOpacity.assign( 1 ); + return this._mixer._isActiveAction( this ); - let plane; + } - Loop( numUnionClippingPlanes, ( { i } ) => { + startAt( time ) { - plane = clippingPlanes.element( i ); + this._startTime = time; - distanceToPlane.assign( positionView.dot( plane.xyz ).negate().add( plane.w ) ); - distanceGradient.assign( distanceToPlane.fwidth().div( 2.0 ) ); + return this; - clipOpacity.mulAssign( smoothstep( distanceGradient.negate(), distanceGradient, distanceToPlane ) ); + } - clipOpacity.equal( 0.0 ).discard(); + setLoop( mode, repetitions ) { - } ); + this.loop = mode; + this.repetitions = repetitions; - if ( numUnionClippingPlanes < numClippingPlanes ) { + return this; - const unionClipOpacity = property( 'float', 'unionclipOpacity' ); + } - unionClipOpacity.assign( 1 ); + // Weight - Loop( { start: numUnionClippingPlanes, end: numClippingPlanes }, ( { i } ) => { + // set the weight stopping any scheduled fading + // although .enabled = false yields an effective weight of zero, this + // method does *not* change .enabled, because it would be confusing + setEffectiveWeight( weight ) { - plane = clippingPlanes.element( i ); + this.weight = weight; - distanceToPlane.assign( positionView.dot( plane.xyz ).negate().add( plane.w ) ); - distanceGradient.assign( distanceToPlane.fwidth().div( 2.0 ) ); + // note: same logic as when updated at runtime + this._effectiveWeight = this.enabled ? weight : 0; - unionClipOpacity.mulAssign( smoothstep( distanceGradient.negate(), distanceGradient, distanceToPlane ).oneMinus() ); + return this.stopFading(); - } ); + } - clipOpacity.mulAssign( unionClipOpacity.oneMinus() ); + // return the weight considering fading and .enabled + getEffectiveWeight() { - } + return this._effectiveWeight; - diffuseColor.a.mulAssign( clipOpacity ); + } - diffuseColor.a.equal( 0.0 ).discard(); + fadeIn( duration ) { - } )(); + return this._scheduleFading( duration, 0, 1 ); } - setupDefault( planes, numClippingPlanes, numUnionClippingPlanes ) { + fadeOut( duration ) { - return Fn( () => { + return this._scheduleFading( duration, 1, 0 ); - const clippingPlanes = uniformArray( planes ); + } - let plane; + crossFadeFrom( fadeOutAction, duration, warp ) { - Loop( numUnionClippingPlanes, ( { i } ) => { + fadeOutAction.fadeOut( duration ); + this.fadeIn( duration ); - plane = clippingPlanes.element( i ); - positionView.dot( plane.xyz ).greaterThan( plane.w ).discard(); + if ( warp ) { - } ); + const fadeInDuration = this._clip.duration, + fadeOutDuration = fadeOutAction._clip.duration, - if ( numUnionClippingPlanes < numClippingPlanes ) { + startEndRatio = fadeOutDuration / fadeInDuration, + endStartRatio = fadeInDuration / fadeOutDuration; - const clipped = property( 'bool', 'clipped' ); + fadeOutAction.warp( 1.0, startEndRatio, duration ); + this.warp( endStartRatio, 1.0, duration ); - clipped.assign( true ); + } - Loop( { start: numUnionClippingPlanes, end: numClippingPlanes }, ( { i } ) => { + return this; - plane = clippingPlanes.element( i ); - clipped.assign( positionView.dot( plane.xyz ).greaterThan( plane.w ).and( clipped ) ); + } - } ); + crossFadeTo( fadeInAction, duration, warp ) { - clipped.discard(); + return fadeInAction.crossFadeFrom( this, duration, warp ); - } + } - } )(); + stopFading() { - } + const weightInterpolant = this._weightInterpolant; -} + if ( weightInterpolant !== null ) { -ClippingNode.ALPHA_TO_COVERAGE = 'alphaToCoverage'; -ClippingNode.DEFAULT = 'default'; + this._weightInterpolant = null; + this._mixer._takeBackControlInterpolant( weightInterpolant ); -ClippingNode.type = /*@__PURE__*/ registerNode( 'Clipping', ClippingNode ); + } -const clipping = () => nodeObject( new ClippingNode() ); + return this; -const clippingAlpha = () => nodeObject( new ClippingNode( ClippingNode.ALPHA_TO_COVERAGE ) ); + } -const NodeMaterials = new Map(); + // Time Scale Control -class NodeMaterial extends Material { + // set the time scale stopping any scheduled warping + // although .paused = true yields an effective time scale of zero, this + // method does *not* change .paused, because it would be confusing + setEffectiveTimeScale( timeScale ) { - constructor() { + this.timeScale = timeScale; + this._effectiveTimeScale = this.paused ? 0 : timeScale; - super(); + return this.stopWarping(); - this.isNodeMaterial = true; + } - this.type = this.constructor.type; + // return the time scale considering warping and .paused + getEffectiveTimeScale() { - this.forceSinglePass = false; + return this._effectiveTimeScale; - this.fog = true; - this.lights = false; + } - this.lightsNode = null; - this.envNode = null; - this.aoNode = null; + setDuration( duration ) { - this.colorNode = null; - this.normalNode = null; - this.opacityNode = null; - this.backdropNode = null; - this.backdropAlphaNode = null; - this.alphaTestNode = null; + this.timeScale = this._clip.duration / duration; - this.positionNode = null; + return this.stopWarping(); - this.depthNode = null; - this.shadowNode = null; - this.shadowPositionNode = null; + } - this.outputNode = null; - this.mrtNode = null; + syncWith( action ) { - this.fragmentNode = null; - this.vertexNode = null; + this.time = action.time; + this.timeScale = action.timeScale; + + return this.stopWarping(); } - customProgramCacheKey() { + halt( duration ) { - return this.type + getCacheKey$1( this ); + return this.warp( this._effectiveTimeScale, 0, duration ); } - build( builder ) { + warp( startTimeScale, endTimeScale, duration ) { - this.setup( builder ); + const mixer = this._mixer, + now = mixer.time, + timeScale = this.timeScale; - } + let interpolant = this._timeScaleInterpolant; - setup( builder ) { + if ( interpolant === null ) { - builder.context.setupNormal = () => this.setupNormal( builder ); + interpolant = mixer._lendControlInterpolant(); + this._timeScaleInterpolant = interpolant; - // < VERTEX STAGE > + } - builder.addStack(); + const times = interpolant.parameterPositions, + values = interpolant.sampleValues; - builder.stack.outputNode = this.vertexNode || this.setupPosition( builder ); + times[ 0 ] = now; + times[ 1 ] = now + duration; - builder.addFlow( 'vertex', builder.removeStack() ); + values[ 0 ] = startTimeScale / timeScale; + values[ 1 ] = endTimeScale / timeScale; - // < FRAGMENT STAGE > + return this; - builder.addStack(); + } - let resultNode; + stopWarping() { - const clippingNode = this.setupClipping( builder ); + const timeScaleInterpolant = this._timeScaleInterpolant; - if ( this.depthWrite === true ) this.setupDepth( builder ); + if ( timeScaleInterpolant !== null ) { - if ( this.fragmentNode === null ) { + this._timeScaleInterpolant = null; + this._mixer._takeBackControlInterpolant( timeScaleInterpolant ); - this.setupDiffuseColor( builder ); - this.setupVariants( builder ); + } - const outgoingLightNode = this.setupLighting( builder ); + return this; - if ( clippingNode !== null ) builder.stack.add( clippingNode ); + } - // force unsigned floats - useful for RenderTargets + // Object Accessors - const basicOutput = vec4( outgoingLightNode, diffuseColor.a ).max( 0 ); + getMixer() { - resultNode = this.setupOutput( builder, basicOutput ); + return this._mixer; - // OUTPUT NODE + } - output.assign( resultNode ); + getClip() { - // + return this._clip; - if ( this.outputNode !== null ) resultNode = this.outputNode; + } - // MRT + getRoot() { - const renderTarget = builder.renderer.getRenderTarget(); + return this._localRoot || this._mixer._root; - if ( renderTarget !== null ) { + } - const mrt = builder.renderer.getMRT(); - const materialMRT = this.mrtNode; + // Interna - if ( mrt !== null ) { + _update( time, deltaTime, timeDirection, accuIndex ) { - resultNode = mrt; + // called by the mixer - if ( materialMRT !== null ) { + if ( ! this.enabled ) { - resultNode = mrt.merge( materialMRT ); + // call ._updateWeight() to update ._effectiveWeight - } + this._updateWeight( time ); + return; - } else if ( materialMRT !== null ) { + } - resultNode = materialMRT; + const startTime = this._startTime; - } + if ( startTime !== null ) { - } + // check for scheduled start of action - } else { + const timeRunning = ( time - startTime ) * timeDirection; + if ( timeRunning < 0 || timeDirection === 0 ) { - let fragmentNode = this.fragmentNode; + deltaTime = 0; - if ( fragmentNode.isOutputStructNode !== true ) { + } else { - fragmentNode = vec4( fragmentNode ); - } + this._startTime = null; // unschedule + deltaTime = timeDirection * timeRunning; - resultNode = this.setupOutput( builder, fragmentNode ); + } } - builder.stack.outputNode = resultNode; + // apply time scale and advance time - builder.addFlow( 'fragment', builder.removeStack() ); + deltaTime *= this._updateTimeScale( time ); + const clipTime = this._updateTime( deltaTime ); - } + // note: _updateTime may disable the action resulting in + // an effective weight of 0 - setupClipping( builder ) { + const weight = this._updateWeight( time ); - if ( builder.clippingContext === null ) return null; + if ( weight > 0 ) { - const { globalClippingCount, localClippingCount } = builder.clippingContext; + const interpolants = this._interpolants; + const propertyMixers = this._propertyBindings; - let result = null; + switch ( this.blendMode ) { - if ( globalClippingCount || localClippingCount ) { + case AdditiveAnimationBlendMode: - if ( this.alphaToCoverage ) { + for ( let j = 0, m = interpolants.length; j !== m; ++ j ) { - // to be added to flow when the color/alpha value has been determined - result = clippingAlpha(); + interpolants[ j ].evaluate( clipTime ); + propertyMixers[ j ].accumulateAdditive( weight ); - } else { + } - builder.stack.add( clipping() ); + break; + + case NormalAnimationBlendMode: + default: + + for ( let j = 0, m = interpolants.length; j !== m; ++ j ) { + + interpolants[ j ].evaluate( clipTime ); + propertyMixers[ j ].accumulate( accuIndex, weight ); + + } } } - return result; - } - setupDepth( builder ) { + _updateWeight( time ) { - const { renderer } = builder; + let weight = 0; - // Depth - - let depthNode = this.depthNode; + if ( this.enabled ) { - if ( depthNode === null ) { + weight = this.weight; + const interpolant = this._weightInterpolant; - const mrt = renderer.getMRT(); + if ( interpolant !== null ) { - if ( mrt && mrt.has( 'depth' ) ) { + const interpolantValue = interpolant.evaluate( time )[ 0 ]; - depthNode = mrt.get( 'depth' ); + weight *= interpolantValue; - } else if ( renderer.logarithmicDepthBuffer === true ) { + if ( time > interpolant.parameterPositions[ 1 ] ) { - const fragDepth = modelViewProjection().w.add( 1 ); + this.stopFading(); - depthNode = fragDepth.log2().mul( cameraLogDepth ).mul( 0.5 ); + if ( interpolantValue === 0 ) { - } + // faded out, disable + this.enabled = false; - } + } - if ( depthNode !== null ) { + } - depth.assign( depthNode ).append(); + } } + this._effectiveWeight = weight; + return weight; + } - setupPosition( builder ) { + _updateTimeScale( time ) { - const { object } = builder; - const geometry = object.geometry; + let timeScale = 0; - builder.addStack(); + if ( ! this.paused ) { - // Vertex + timeScale = this.timeScale; - if ( geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color ) { + const interpolant = this._timeScaleInterpolant; - morphReference( object ).append(); + if ( interpolant !== null ) { - } + const interpolantValue = interpolant.evaluate( time )[ 0 ]; - if ( object.isSkinnedMesh === true ) { + timeScale *= interpolantValue; - skinningReference( object ).append(); + if ( time > interpolant.parameterPositions[ 1 ] ) { - } + this.stopWarping(); - if ( this.displacementMap ) { + if ( timeScale === 0 ) { - const displacementMap = materialReference( 'displacementMap', 'texture' ); - const displacementScale = materialReference( 'displacementScale', 'float' ); - const displacementBias = materialReference( 'displacementBias', 'float' ); + // motion has halted, pause + this.paused = true; - positionLocal.addAssign( normalLocal.normalize().mul( ( displacementMap.x.mul( displacementScale ).add( displacementBias ) ) ) ); + } else { - } + // warp done - apply final time scale + this.timeScale = timeScale; - if ( object.isBatchedMesh ) { + } - batch( object ).append(); + } - } + } - if ( ( object.instanceMatrix && object.instanceMatrix.isInstancedBufferAttribute === true ) ) { + } - instance( object ).append(); + this._effectiveTimeScale = timeScale; + return timeScale; - } + } - if ( this.positionNode !== null ) { + _updateTime( deltaTime ) { - positionLocal.assign( this.positionNode ); + const duration = this._clip.duration; + const loop = this.loop; - } + let time = this.time + deltaTime; + let loopCount = this._loopCount; - const mvp = modelViewProjection(); + const pingPong = ( loop === LoopPingPong ); - builder.context.vertex = builder.removeStack(); - builder.context.mvp = mvp; + if ( deltaTime === 0 ) { - return mvp; + if ( loopCount === - 1 ) return time; - } + return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time; - setupDiffuseColor( { object, geometry } ) { + } - let colorNode = this.colorNode ? vec4( this.colorNode ) : materialColor; + if ( loop === LoopOnce ) { - // VERTEX COLORS + if ( loopCount === - 1 ) { - if ( this.vertexColors === true && geometry.hasAttribute( 'color' ) ) { + // just started - colorNode = vec4( colorNode.xyz.mul( attribute( 'color', 'vec3' ) ), colorNode.a ); + this._loopCount = 0; + this._setEndings( true, true, false ); - } + } - // Instanced colors + handle_stop: { - if ( object.instanceColor ) { + if ( time >= duration ) { - const instanceColor = varyingProperty( 'vec3', 'vInstanceColor' ); + time = duration; - colorNode = instanceColor.mul( colorNode ); + } else if ( time < 0 ) { - } + time = 0; - if ( object.isBatchedMesh && object._colorsTexture ) { + } else { - const batchColor = varyingProperty( 'vec3', 'vBatchColor' ); + this.time = time; - colorNode = batchColor.mul( colorNode ); + break handle_stop; - } + } + if ( this.clampWhenFinished ) this.paused = true; + else this.enabled = false; - // COLOR + this.time = time; - diffuseColor.assign( colorNode ); + this._mixer.dispatchEvent( { + type: 'finished', action: this, + direction: deltaTime < 0 ? - 1 : 1 + } ); - // OPACITY + } - const opacityNode = this.opacityNode ? float( this.opacityNode ) : materialOpacity; - diffuseColor.a.assign( diffuseColor.a.mul( opacityNode ) ); + } else { // repetitive Repeat or PingPong - // ALPHA TEST + if ( loopCount === - 1 ) { - if ( this.alphaTestNode !== null || this.alphaTest > 0 ) { + // just started - const alphaTestNode = this.alphaTestNode !== null ? float( this.alphaTestNode ) : materialAlphaTest; + if ( deltaTime >= 0 ) { - diffuseColor.a.lessThanEqual( alphaTestNode ).discard(); + loopCount = 0; - } + this._setEndings( true, this.repetitions === 0, pingPong ); - if ( this.transparent === false && this.blending === NormalBlending && this.alphaToCoverage === false ) { + } else { - diffuseColor.a.assign( 1.0 ); + // when looping in reverse direction, the initial + // transition through zero counts as a repetition, + // so leave loopCount at -1 - } + this._setEndings( this.repetitions === 0, true, pingPong ); - } + } - setupVariants( /*builder*/ ) { + } - // Interface function. + if ( time >= duration || time < 0 ) { - } + // wrap around - setupOutgoingLight() { + const loopDelta = Math.floor( time / duration ); // signed + time -= duration * loopDelta; - return ( this.lights === true ) ? vec3( 0 ) : diffuseColor.rgb; + loopCount += Math.abs( loopDelta ); - } + const pending = this.repetitions - loopCount; - setupNormal() { + if ( pending <= 0 ) { - return this.normalNode ? vec3( this.normalNode ) : materialNormal; + // have to stop (switch state, clamp time, fire event) - } + if ( this.clampWhenFinished ) this.paused = true; + else this.enabled = false; - setupEnvironment( /*builder*/ ) { + time = deltaTime > 0 ? duration : 0; - let node = null; + this.time = time; - if ( this.envNode ) { + this._mixer.dispatchEvent( { + type: 'finished', action: this, + direction: deltaTime > 0 ? 1 : - 1 + } ); - node = this.envNode; + } else { - } else if ( this.envMap ) { + // keep running - node = this.envMap.isCubeTexture ? materialReference( 'envMap', 'cubeTexture' ) : materialReference( 'envMap', 'texture' ); + if ( pending === 1 ) { - } + // entering the last round - return node; + const atStart = deltaTime < 0; + this._setEndings( atStart, ! atStart, pingPong ); - } + } else { - setupLightMap( builder ) { + this._setEndings( false, false, pingPong ); - let node = null; + } - if ( builder.material.lightMap ) { + this._loopCount = loopCount; - node = new IrradianceNode( materialLightMap ); + this.time = time; - } + this._mixer.dispatchEvent( { + type: 'loop', action: this, loopDelta: loopDelta + } ); - return node; + } - } + } else { - setupLights( builder ) { + this.time = time; - const materialLightsNode = []; + } - // + if ( pingPong && ( loopCount & 1 ) === 1 ) { - const envNode = this.setupEnvironment( builder ); + // invert time for the "pong round" - if ( envNode && envNode.isLightingNode ) { + return duration - time; - materialLightsNode.push( envNode ); + } } - const lightMapNode = this.setupLightMap( builder ); + return time; - if ( lightMapNode && lightMapNode.isLightingNode ) { + } - materialLightsNode.push( lightMapNode ); + _setEndings( atStart, atEnd, pingPong ) { - } + const settings = this._interpolantSettings; - if ( this.aoNode !== null || builder.material.aoMap ) { + if ( pingPong ) { - const aoNode = this.aoNode !== null ? this.aoNode : materialAOMap; + settings.endingStart = ZeroSlopeEnding; + settings.endingEnd = ZeroSlopeEnding; - materialLightsNode.push( new AONode( aoNode ) ); + } else { - } + // assuming for LoopOnce atStart == atEnd == true - let lightsN = this.lightsNode || builder.lightsNode; + if ( atStart ) { - if ( materialLightsNode.length > 0 ) { + settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding; - lightsN = lights( [ ...lightsN.getLights(), ...materialLightsNode ] ); + } else { - } + settings.endingStart = WrapAroundEnding; - return lightsN; + } - } + if ( atEnd ) { - setupLightingModel( /*builder*/ ) { + settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding; - // Interface function. + } else { - } + settings.endingEnd = WrapAroundEnding; - setupLighting( builder ) { + } - const { material } = builder; - const { backdropNode, backdropAlphaNode, emissiveNode } = this; + } - // OUTGOING LIGHT + } - const lights = this.lights === true || this.lightsNode !== null; + _scheduleFading( duration, weightNow, weightThen ) { - const lightsNode = lights ? this.setupLights( builder ) : null; + const mixer = this._mixer, now = mixer.time; + let interpolant = this._weightInterpolant; - let outgoingLightNode = this.setupOutgoingLight( builder ); + if ( interpolant === null ) { - if ( lightsNode && lightsNode.getScope().getLights().length > 0 ) { + interpolant = mixer._lendControlInterpolant(); + this._weightInterpolant = interpolant; - const lightingModel = this.setupLightingModel( builder ); + } - outgoingLightNode = lightingContext( lightsNode, lightingModel, backdropNode, backdropAlphaNode ); + const times = interpolant.parameterPositions, + values = interpolant.sampleValues; - } else if ( backdropNode !== null ) { + times[ 0 ] = now; + values[ 0 ] = weightNow; + times[ 1 ] = now + duration; + values[ 1 ] = weightThen; - outgoingLightNode = vec3( backdropAlphaNode !== null ? mix( outgoingLightNode, backdropNode, backdropAlphaNode ) : backdropNode ); + return this; - } + } - // EMISSIVE +} - if ( ( emissiveNode && emissiveNode.isNode === true ) || ( material.emissive && material.emissive.isColor === true ) ) { +const _controlInterpolantsResultBuffer = new Float32Array( 1 ); - emissive.assign( vec3( emissiveNode ? emissiveNode : materialEmissive ) ); - outgoingLightNode = outgoingLightNode.add( emissive ); +class AnimationMixer extends EventDispatcher { - } + constructor( root ) { - return outgoingLightNode; + super(); + + this._root = root; + this._initMemoryManager(); + this._accuIndex = 0; + this.time = 0; + this.timeScale = 1.0; } - setupOutput( builder, outputNode ) { + _bindAction( action, prototypeAction ) { - // FOG + const root = action._localRoot || this._root, + tracks = action._clip.tracks, + nTracks = tracks.length, + bindings = action._propertyBindings, + interpolants = action._interpolants, + rootUuid = root.uuid, + bindingsByRoot = this._bindingsByRootAndName; - if ( this.fog === true ) { + let bindingsByName = bindingsByRoot[ rootUuid ]; - const fogNode = builder.fogNode; + if ( bindingsByName === undefined ) { - if ( fogNode ) outputNode = vec4( fogNode.mix( outputNode.rgb, fogNode.colorNode ), outputNode.a ); + bindingsByName = {}; + bindingsByRoot[ rootUuid ] = bindingsByName; } - return outputNode; + for ( let i = 0; i !== nTracks; ++ i ) { - } + const track = tracks[ i ], + trackName = track.name; - setDefaultValues( material ) { + let binding = bindingsByName[ trackName ]; - // This approach is to reuse the native refreshUniforms* - // and turn available the use of features like transmission and environment in core + if ( binding !== undefined ) { - for ( const property in material ) { + ++ binding.referenceCount; + bindings[ i ] = binding; - const value = material[ property ]; + } else { - if ( this[ property ] === undefined ) { + binding = bindings[ i ]; - this[ property ] = value; + if ( binding !== undefined ) { - if ( value && value.clone ) this[ property ] = value.clone(); + // existing binding, make sure the cache knows - } + if ( binding._cacheIndex === null ) { - } + ++ binding.referenceCount; + this._addInactiveBinding( binding, rootUuid, trackName ); - const descriptors = Object.getOwnPropertyDescriptors( material.constructor.prototype ); + } - for ( const key in descriptors ) { + continue; - if ( Object.getOwnPropertyDescriptor( this.constructor.prototype, key ) === undefined && - descriptors[ key ].get !== undefined ) { + } - Object.defineProperty( this.constructor.prototype, key, descriptors[ key ] ); + const path = prototypeAction && prototypeAction. + _propertyBindings[ i ].binding.parsedPath; + + binding = new PropertyMixer( + PropertyBinding.create( root, trackName, path ), + track.ValueTypeName, track.getValueSize() ); + + ++ binding.referenceCount; + this._addInactiveBinding( binding, rootUuid, trackName ); + + bindings[ i ] = binding; } + interpolants[ i ].resultBuffer = binding.buffer; + } } - toJSON( meta ) { - - const isRoot = ( meta === undefined || typeof meta === 'string' ); + _activateAction( action ) { - if ( isRoot ) { + if ( ! this._isActiveAction( action ) ) { - meta = { - textures: {}, - images: {}, - nodes: {} - }; + if ( action._cacheIndex === null ) { - } + // this action has been forgotten by the cache, but the user + // appears to be still using it -> rebind - const data = Material.prototype.toJSON.call( this, meta ); - const nodeChildren = getNodeChildren( this ); + const rootUuid = ( action._localRoot || this._root ).uuid, + clipUuid = action._clip.uuid, + actionsForClip = this._actionsByClip[ clipUuid ]; - data.inputNodes = {}; + this._bindAction( action, + actionsForClip && actionsForClip.knownActions[ 0 ] ); - for ( const { property, childNode } of nodeChildren ) { + this._addInactiveAction( action, clipUuid, rootUuid ); - data.inputNodes[ property ] = childNode.toJSON( meta ).uuid; + } - } + const bindings = action._propertyBindings; - // TODO: Copied from Object3D.toJSON + // increment reference counts / sort out state + for ( let i = 0, n = bindings.length; i !== n; ++ i ) { - function extractFromCache( cache ) { + const binding = bindings[ i ]; - const values = []; + if ( binding.useCount ++ === 0 ) { - for ( const key in cache ) { + this._lendBinding( binding ); + binding.saveOriginalState(); - const data = cache[ key ]; - delete data.metadata; - values.push( data ); + } } - return values; + this._lendAction( action ); } - if ( isRoot ) { - - const textures = extractFromCache( meta.textures ); - const images = extractFromCache( meta.images ); - const nodes = extractFromCache( meta.nodes ); - - if ( textures.length > 0 ) data.textures = textures; - if ( images.length > 0 ) data.images = images; - if ( nodes.length > 0 ) data.nodes = nodes; + } - } + _deactivateAction( action ) { - return data; + if ( this._isActiveAction( action ) ) { - } + const bindings = action._propertyBindings; - copy( source ) { + // decrement reference counts / sort out state + for ( let i = 0, n = bindings.length; i !== n; ++ i ) { - this.lightsNode = source.lightsNode; - this.envNode = source.envNode; + const binding = bindings[ i ]; - this.colorNode = source.colorNode; - this.normalNode = source.normalNode; - this.opacityNode = source.opacityNode; - this.backdropNode = source.backdropNode; - this.backdropAlphaNode = source.backdropAlphaNode; - this.alphaTestNode = source.alphaTestNode; + if ( -- binding.useCount === 0 ) { - this.positionNode = source.positionNode; + binding.restoreOriginalState(); + this._takeBackBinding( binding ); - this.depthNode = source.depthNode; - this.shadowNode = source.shadowNode; - this.shadowPositionNode = source.shadowPositionNode; + } - this.outputNode = source.outputNode; - this.mrtNode = source.mrtNode; + } - this.fragmentNode = source.fragmentNode; - this.vertexNode = source.vertexNode; + this._takeBackAction( action ); - return super.copy( source ); + } } -} + // Memory manager -NodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( '', NodeMaterial ); + _initMemoryManager() { -function registerNodeMaterial( type, nodeMaterialClass ) { + this._actions = []; // 'nActiveActions' followed by inactive ones + this._nActiveActions = 0; - const suffix = 'NodeMaterial'; - const nodeMaterialType = type + suffix; + this._actionsByClip = {}; + // inside: + // { + // knownActions: Array< AnimationAction > - used as prototypes + // actionByRoot: AnimationAction - lookup + // } - if ( typeof nodeMaterialClass !== 'function' ) throw new Error( `THREE.Node: NodeMaterial class "${ type }" is not a class.` ); - if ( NodeMaterials.has( nodeMaterialType ) ) { + this._bindings = []; // 'nActiveBindings' followed by inactive ones + this._nActiveBindings = 0; - console.warn( `THREE.Node: Redefinition of NodeMaterial class "${ nodeMaterialType }".` ); - return; + this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer > - } - if ( type.slice( - suffix.length ) === suffix ) { + this._controlInterpolants = []; // same game as above + this._nActiveControlInterpolants = 0; - console.warn( `THREE.NodeMaterial: NodeMaterial class ${ nodeMaterialType } should not have '${ suffix }' suffix.` ); - return; + const scope = this; - } + this.stats = { - NodeMaterials.set( nodeMaterialType, nodeMaterialClass ); - nodeMaterialClass.type = nodeMaterialType; + actions: { + get total() { - return nodeMaterialType; + return scope._actions.length; -} + }, + get inUse() { -function createNodeMaterialFromType( type ) { + return scope._nActiveActions; - const Material = NodeMaterials.get( type ); + } + }, + bindings: { + get total() { - if ( Material !== undefined ) { + return scope._bindings.length; - return new Material(); + }, + get inUse() { - } + return scope._nActiveBindings; -} + } + }, + controlInterpolants: { + get total() { -const _defaultValues$e = /*@__PURE__*/ new PointsMaterial(); + return scope._controlInterpolants.length; -class InstancedPointsNodeMaterial extends NodeMaterial { + }, + get inUse() { - constructor( params = {} ) { + return scope._nActiveControlInterpolants; - super(); + } + } - this.lights = false; + }; - this.useAlphaToCoverage = true; + } - this.useColor = params.vertexColors; + // Memory management for AnimationAction objects - this.pointWidth = 1; + _isActiveAction( action ) { - this.pointColorNode = null; + const index = action._cacheIndex; + return index !== null && index < this._nActiveActions; - this.pointWidthNode = null; + } - this.setDefaultValues( _defaultValues$e ); + _addInactiveAction( action, clipUuid, rootUuid ) { - this.setupShaders(); + const actions = this._actions, + actionsByClip = this._actionsByClip; - this.setValues( params ); + let actionsForClip = actionsByClip[ clipUuid ]; - } + if ( actionsForClip === undefined ) { - setup( builder ) { + actionsForClip = { - this.setupShaders(); + knownActions: [ action ], + actionByRoot: {} - super.setup( builder ); + }; - } + action._byClipCacheIndex = 0; - setupShaders() { + actionsByClip[ clipUuid ] = actionsForClip; - const useAlphaToCoverage = this.alphaToCoverage; - const useColor = this.useColor; + } else { - this.vertexNode = Fn( () => { + const knownActions = actionsForClip.knownActions; - //vUv = uv; - varying( vec2(), 'vUv' ).assign( uv() ); // @TODO: Analyze other way to do this + action._byClipCacheIndex = knownActions.length; + knownActions.push( action ); - const instancePosition = attribute( 'instancePosition' ).xyz; + } - // camera space - const mvPos = property( 'vec4', 'mvPos' ); - mvPos.assign( modelViewMatrix.mul( vec4( instancePosition, 1.0 ) ) ); + action._cacheIndex = actions.length; + actions.push( action ); - const aspect = viewport.z.div( viewport.w ); + actionsForClip.actionByRoot[ rootUuid ] = action; - // clip space - const clipPos = cameraProjectionMatrix.mul( mvPos ); + } - // offset in ndc space - const offset = property( 'vec2', 'offset' ); - offset.assign( positionGeometry.xy ); + _removeInactiveAction( action ) { - offset.mulAssign( this.pointWidthNode ? this.pointWidthNode : materialPointWidth ); + const actions = this._actions, + lastInactiveAction = actions[ actions.length - 1 ], + cacheIndex = action._cacheIndex; - offset.assign( offset.div( viewport.z ) ); - offset.y.assign( offset.y.mul( aspect ) ); + lastInactiveAction._cacheIndex = cacheIndex; + actions[ cacheIndex ] = lastInactiveAction; + actions.pop(); - // back to clip space - offset.assign( offset.mul( clipPos.w ) ); + action._cacheIndex = null; - //clipPos.xy += offset; - clipPos.assign( clipPos.add( vec4( offset, 0, 0 ) ) ); - return clipPos; + const clipUuid = action._clip.uuid, + actionsByClip = this._actionsByClip, + actionsForClip = actionsByClip[ clipUuid ], + knownActionsForClip = actionsForClip.knownActions, - //vec4 mvPosition = mvPos; // this was used for somethihng... + lastKnownAction = + knownActionsForClip[ knownActionsForClip.length - 1 ], - } )(); + byClipCacheIndex = action._byClipCacheIndex; - this.fragmentNode = Fn( () => { + lastKnownAction._byClipCacheIndex = byClipCacheIndex; + knownActionsForClip[ byClipCacheIndex ] = lastKnownAction; + knownActionsForClip.pop(); - const vUv = varying( vec2(), 'vUv' ); + action._byClipCacheIndex = null; - // force assignment into correct place in flow - const alpha = property( 'float', 'alpha' ); - alpha.assign( 1 ); - const a = vUv.x; - const b = vUv.y; + const actionByRoot = actionsForClip.actionByRoot, + rootUuid = ( action._localRoot || this._root ).uuid; - const len2 = a.mul( a ).add( b.mul( b ) ); + delete actionByRoot[ rootUuid ]; - if ( useAlphaToCoverage ) { + if ( knownActionsForClip.length === 0 ) { - // force assignment out of following 'if' statement - to avoid uniform control flow errors - const dlen = property( 'float', 'dlen' ); - dlen.assign( len2.fwidth() ); + delete actionsByClip[ clipUuid ]; - alpha.assign( smoothstep( dlen.oneMinus(), dlen.add( 1 ), len2 ).oneMinus() ); + } - } else { + this._removeInactiveBindingsForAction( action ); - len2.greaterThan( 1.0 ).discard(); + } - } + _removeInactiveBindingsForAction( action ) { - let pointColorNode; + const bindings = action._propertyBindings; - if ( this.pointColorNode ) { + for ( let i = 0, n = bindings.length; i !== n; ++ i ) { - pointColorNode = this.pointColorNode; + const binding = bindings[ i ]; - } else { + if ( -- binding.referenceCount === 0 ) { - if ( useColor ) { + this._removeInactiveBinding( binding ); - const instanceColor = attribute( 'instanceColor' ); + } - pointColorNode = instanceColor.mul( materialColor ); + } - } else { + } - pointColorNode = materialColor; + _lendAction( action ) { - } + // [ active actions | inactive actions ] + // [ active actions >| inactive actions ] + // s a + // <-swap-> + // a s - } + const actions = this._actions, + prevIndex = action._cacheIndex, - alpha.mulAssign( materialOpacity ); + lastActiveIndex = this._nActiveActions ++, - return vec4( pointColorNode, alpha ); + firstInactiveAction = actions[ lastActiveIndex ]; - } )(); + action._cacheIndex = lastActiveIndex; + actions[ lastActiveIndex ] = action; + + firstInactiveAction._cacheIndex = prevIndex; + actions[ prevIndex ] = firstInactiveAction; } - get alphaToCoverage() { + _takeBackAction( action ) { - return this.useAlphaToCoverage; + // [ active actions | inactive actions ] + // [ active actions |< inactive actions ] + // a s + // <-swap-> + // s a - } + const actions = this._actions, + prevIndex = action._cacheIndex, - set alphaToCoverage( value ) { + firstInactiveIndex = -- this._nActiveActions, - if ( this.useAlphaToCoverage !== value ) { + lastActiveAction = actions[ firstInactiveIndex ]; - this.useAlphaToCoverage = value; - this.needsUpdate = true; + action._cacheIndex = firstInactiveIndex; + actions[ firstInactiveIndex ] = action; - } + lastActiveAction._cacheIndex = prevIndex; + actions[ prevIndex ] = lastActiveAction; } -} - -InstancedPointsNodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'InstancedPoints', InstancedPointsNodeMaterial ); + // Memory management for PropertyMixer objects -const _defaultValues$d = /*@__PURE__*/ new LineBasicMaterial(); + _addInactiveBinding( binding, rootUuid, trackName ) { -class LineBasicNodeMaterial extends NodeMaterial { + const bindingsByRoot = this._bindingsByRootAndName, + bindings = this._bindings; - constructor( parameters ) { + let bindingByName = bindingsByRoot[ rootUuid ]; - super(); + if ( bindingByName === undefined ) { - this.isLineBasicNodeMaterial = true; + bindingByName = {}; + bindingsByRoot[ rootUuid ] = bindingByName; - this.lights = false; + } - this.setDefaultValues( _defaultValues$d ); + bindingByName[ trackName ] = binding; - this.setValues( parameters ); + binding._cacheIndex = bindings.length; + bindings.push( binding ); } -} - -LineBasicNodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'LineBasic', LineBasicNodeMaterial ); - -const _defaultValues$c = /*@__PURE__*/ new LineDashedMaterial(); - -class LineDashedNodeMaterial extends NodeMaterial { + _removeInactiveBinding( binding ) { - constructor( parameters ) { + const bindings = this._bindings, + propBinding = binding.binding, + rootUuid = propBinding.rootNode.uuid, + trackName = propBinding.path, + bindingsByRoot = this._bindingsByRootAndName, + bindingByName = bindingsByRoot[ rootUuid ], - super(); + lastInactiveBinding = bindings[ bindings.length - 1 ], + cacheIndex = binding._cacheIndex; - this.isLineDashedNodeMaterial = true; + lastInactiveBinding._cacheIndex = cacheIndex; + bindings[ cacheIndex ] = lastInactiveBinding; + bindings.pop(); - this.lights = false; + delete bindingByName[ trackName ]; - this.setDefaultValues( _defaultValues$c ); + if ( Object.keys( bindingByName ).length === 0 ) { - this.offsetNode = null; - this.dashScaleNode = null; - this.dashSizeNode = null; - this.gapSizeNode = null; + delete bindingsByRoot[ rootUuid ]; - this.setValues( parameters ); + } } - setupVariants() { + _lendBinding( binding ) { - const offsetNode = this.offsetNode; - const dashScaleNode = this.dashScaleNode ? float( this.dashScaleNode ) : materialLineScale; - const dashSizeNode = this.dashSizeNode ? float( this.dashSizeNode ) : materialLineDashSize; - const gapSizeNode = this.dashSizeNode ? float( this.dashGapNode ) : materialLineGapSize; + const bindings = this._bindings, + prevIndex = binding._cacheIndex, - dashSize.assign( dashSizeNode ); - gapSize.assign( gapSizeNode ); + lastActiveIndex = this._nActiveBindings ++, - const vLineDistance = varying( attribute( 'lineDistance' ).mul( dashScaleNode ) ); - const vLineDistanceOffset = offsetNode ? vLineDistance.add( offsetNode ) : vLineDistance; + firstInactiveBinding = bindings[ lastActiveIndex ]; - vLineDistanceOffset.mod( dashSize.add( gapSize ) ).greaterThan( dashSize ).discard(); + binding._cacheIndex = lastActiveIndex; + bindings[ lastActiveIndex ] = binding; + + firstInactiveBinding._cacheIndex = prevIndex; + bindings[ prevIndex ] = firstInactiveBinding; } -} + _takeBackBinding( binding ) { -LineDashedNodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'LineDashed', LineDashedNodeMaterial ); + const bindings = this._bindings, + prevIndex = binding._cacheIndex, -const _defaultValues$b = /*@__PURE__*/ new LineDashedMaterial(); + firstInactiveIndex = -- this._nActiveBindings, -class Line2NodeMaterial extends NodeMaterial { + lastActiveBinding = bindings[ firstInactiveIndex ]; - constructor( params = {} ) { + binding._cacheIndex = firstInactiveIndex; + bindings[ firstInactiveIndex ] = binding; - super(); + lastActiveBinding._cacheIndex = prevIndex; + bindings[ prevIndex ] = lastActiveBinding; - this.lights = false; + } - this.setDefaultValues( _defaultValues$b ); - this.useAlphaToCoverage = true; - this.useColor = params.vertexColors; - this.useDash = params.dashed; - this.useWorldUnits = false; + // Memory management of Interpolants for weight and time scale - this.dashOffset = 0; - this.lineWidth = 1; + _lendControlInterpolant() { - this.lineColorNode = null; + const interpolants = this._controlInterpolants, + lastActiveIndex = this._nActiveControlInterpolants ++; - this.offsetNode = null; - this.dashScaleNode = null; - this.dashSizeNode = null; - this.gapSizeNode = null; + let interpolant = interpolants[ lastActiveIndex ]; - this.setValues( params ); + if ( interpolant === undefined ) { - } + interpolant = new LinearInterpolant( + new Float32Array( 2 ), new Float32Array( 2 ), + 1, _controlInterpolantsResultBuffer ); - setup( builder ) { + interpolant.__cacheIndex = lastActiveIndex; + interpolants[ lastActiveIndex ] = interpolant; - this.setupShaders(); + } - super.setup( builder ); + return interpolant; } - setupShaders() { + _takeBackControlInterpolant( interpolant ) { - const useAlphaToCoverage = this.alphaToCoverage; - const useColor = this.useColor; - const useDash = this.dashed; - const useWorldUnits = this.worldUnits; + const interpolants = this._controlInterpolants, + prevIndex = interpolant.__cacheIndex, - const trimSegment = Fn( ( { start, end } ) => { + firstInactiveIndex = -- this._nActiveControlInterpolants, - const a = cameraProjectionMatrix.element( 2 ).element( 2 ); // 3nd entry in 3th column - const b = cameraProjectionMatrix.element( 3 ).element( 2 ); // 3nd entry in 4th column - const nearEstimate = b.mul( - 0.5 ).div( a ); + lastActiveInterpolant = interpolants[ firstInactiveIndex ]; - const alpha = nearEstimate.sub( start.z ).div( end.z.sub( start.z ) ); + interpolant.__cacheIndex = firstInactiveIndex; + interpolants[ firstInactiveIndex ] = interpolant; - return vec4( mix( start.xyz, end.xyz, alpha ), end.w ); + lastActiveInterpolant.__cacheIndex = prevIndex; + interpolants[ prevIndex ] = lastActiveInterpolant; - } ); + } - this.vertexNode = Fn( () => { + // return an action for a clip optionally using a custom root target + // object (this method allocates a lot of dynamic memory in case a + // previously unknown clip/root combination is specified) + clipAction( clip, optionalRoot, blendMode ) { - varyingProperty( 'vec2', 'vUv' ).assign( uv() ); + const root = optionalRoot || this._root, + rootUuid = root.uuid; - const instanceStart = attribute( 'instanceStart' ); - const instanceEnd = attribute( 'instanceEnd' ); + let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip; - // camera space + const clipUuid = clipObject !== null ? clipObject.uuid : clip; - const start = property( 'vec4', 'start' ); - const end = property( 'vec4', 'end' ); + const actionsForClip = this._actionsByClip[ clipUuid ]; + let prototypeAction = null; - start.assign( modelViewMatrix.mul( vec4( instanceStart, 1.0 ) ) ); // force assignment into correct place in flow - end.assign( modelViewMatrix.mul( vec4( instanceEnd, 1.0 ) ) ); + if ( blendMode === undefined ) { - if ( useWorldUnits ) { + if ( clipObject !== null ) { - varyingProperty( 'vec3', 'worldStart' ).assign( start.xyz ); - varyingProperty( 'vec3', 'worldEnd' ).assign( end.xyz ); + blendMode = clipObject.blendMode; - } + } else { - const aspect = viewport.z.div( viewport.w ); + blendMode = NormalAnimationBlendMode; - // special case for perspective projection, and segments that terminate either in, or behind, the camera plane - // clearly the gpu firmware has a way of addressing this issue when projecting into ndc space - // but we need to perform ndc-space calculations in the shader, so we must address this issue directly - // perhaps there is a more elegant solution -- WestLangley + } - const perspective = cameraProjectionMatrix.element( 2 ).element( 3 ).equal( - 1.0 ); // 4th entry in the 3rd column + } - If( perspective, () => { + if ( actionsForClip !== undefined ) { - If( start.z.lessThan( 0.0 ).and( end.z.greaterThan( 0.0 ) ), () => { + const existingAction = actionsForClip.actionByRoot[ rootUuid ]; - end.assign( trimSegment( { start: start, end: end } ) ); + if ( existingAction !== undefined && existingAction.blendMode === blendMode ) { - } ).ElseIf( end.z.lessThan( 0.0 ).and( start.z.greaterThanEqual( 0.0 ) ), () => { + return existingAction; - start.assign( trimSegment( { start: end, end: start } ) ); + } - } ); + // we know the clip, so we don't have to parse all + // the bindings again but can just copy + prototypeAction = actionsForClip.knownActions[ 0 ]; - } ); + // also, take the clip from the prototype action + if ( clipObject === null ) + clipObject = prototypeAction._clip; - // clip space - const clipStart = cameraProjectionMatrix.mul( start ); - const clipEnd = cameraProjectionMatrix.mul( end ); + } - // ndc space - const ndcStart = clipStart.xyz.div( clipStart.w ); - const ndcEnd = clipEnd.xyz.div( clipEnd.w ); + // clip must be known when specified via string + if ( clipObject === null ) return null; - // direction - const dir = ndcEnd.xy.sub( ndcStart.xy ).toVar(); + // allocate all resources required to run it + const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode ); - // account for clip-space aspect ratio - dir.x.assign( dir.x.mul( aspect ) ); - dir.assign( dir.normalize() ); + this._bindAction( newAction, prototypeAction ); - const clip = vec4().toVar(); + // and make the action known to the memory manager + this._addInactiveAction( newAction, clipUuid, rootUuid ); - if ( useWorldUnits ) { + return newAction; - // get the offset direction as perpendicular to the view vector + } - const worldDir = end.xyz.sub( start.xyz ).normalize(); - const tmpFwd = mix( start.xyz, end.xyz, 0.5 ).normalize(); - const worldUp = worldDir.cross( tmpFwd ).normalize(); - const worldFwd = worldDir.cross( worldUp ); + // get an existing action + existingAction( clip, optionalRoot ) { - const worldPos = varyingProperty( 'vec4', 'worldPos' ); + const root = optionalRoot || this._root, + rootUuid = root.uuid, - worldPos.assign( positionGeometry.y.lessThan( 0.5 ).select( start, end ) ); + clipObject = typeof clip === 'string' ? + AnimationClip.findByName( root, clip ) : clip, - // height offset - const hw = materialLineWidth.mul( 0.5 ); - worldPos.addAssign( vec4( positionGeometry.x.lessThan( 0.0 ).select( worldUp.mul( hw ), worldUp.mul( hw ).negate() ), 0 ) ); + clipUuid = clipObject ? clipObject.uuid : clip, - // don't extend the line if we're rendering dashes because we - // won't be rendering the endcaps - if ( ! useDash ) { + actionsForClip = this._actionsByClip[ clipUuid ]; - // cap extension - worldPos.addAssign( vec4( positionGeometry.y.lessThan( 0.5 ).select( worldDir.mul( hw ).negate(), worldDir.mul( hw ) ), 0 ) ); + if ( actionsForClip !== undefined ) { - // add width to the box - worldPos.addAssign( vec4( worldFwd.mul( hw ), 0 ) ); + return actionsForClip.actionByRoot[ rootUuid ] || null; - // endcaps - If( positionGeometry.y.greaterThan( 1.0 ).or( positionGeometry.y.lessThan( 0.0 ) ), () => { + } - worldPos.subAssign( vec4( worldFwd.mul( 2.0 ).mul( hw ), 0 ) ); + return null; - } ); + } - } + // deactivates all previously scheduled actions + stopAllAction() { - // project the worldpos - clip.assign( cameraProjectionMatrix.mul( worldPos ) ); + const actions = this._actions, + nActions = this._nActiveActions; - // shift the depth of the projected points so the line - // segments overlap neatly - const clipPose = vec3().toVar(); + for ( let i = nActions - 1; i >= 0; -- i ) { - clipPose.assign( positionGeometry.y.lessThan( 0.5 ).select( ndcStart, ndcEnd ) ); - clip.z.assign( clipPose.z.mul( clip.w ) ); + actions[ i ].stop(); - } else { + } - const offset = property( 'vec2', 'offset' ); + return this; - offset.assign( vec2( dir.y, dir.x.negate() ) ); + } - // undo aspect ratio adjustment - dir.x.assign( dir.x.div( aspect ) ); - offset.x.assign( offset.x.div( aspect ) ); + // advance the time and update apply the animation + update( deltaTime ) { - // sign flip - offset.assign( positionGeometry.x.lessThan( 0.0 ).select( offset.negate(), offset ) ); + deltaTime *= this.timeScale; - // endcaps - If( positionGeometry.y.lessThan( 0.0 ), () => { + const actions = this._actions, + nActions = this._nActiveActions, - offset.assign( offset.sub( dir ) ); + time = this.time += deltaTime, + timeDirection = Math.sign( deltaTime ), - } ).ElseIf( positionGeometry.y.greaterThan( 1.0 ), () => { + accuIndex = this._accuIndex ^= 1; - offset.assign( offset.add( dir ) ); + // run active actions - } ); + for ( let i = 0; i !== nActions; ++ i ) { - // adjust for linewidth - offset.assign( offset.mul( materialLineWidth ) ); + const action = actions[ i ]; - // adjust for clip-space to screen-space conversion // maybe resolution should be based on viewport ... - offset.assign( offset.div( viewport.w ) ); + action._update( time, deltaTime, timeDirection, accuIndex ); - // select end - clip.assign( positionGeometry.y.lessThan( 0.5 ).select( clipStart, clipEnd ) ); + } - // back to clip space - offset.assign( offset.mul( clip.w ) ); + // update scene graph - clip.assign( clip.add( vec4( offset, 0, 0 ) ) ); + const bindings = this._bindings, + nBindings = this._nActiveBindings; - } + for ( let i = 0; i !== nBindings; ++ i ) { - return clip; + bindings[ i ].apply( accuIndex ); - } )(); + } - const closestLineToLine = Fn( ( { p1, p2, p3, p4 } ) => { + return this; - const p13 = p1.sub( p3 ); - const p43 = p4.sub( p3 ); + } - const p21 = p2.sub( p1 ); + // Allows you to seek to a specific time in an animation. + setTime( timeInSeconds ) { - const d1343 = p13.dot( p43 ); - const d4321 = p43.dot( p21 ); - const d1321 = p13.dot( p21 ); - const d4343 = p43.dot( p43 ); - const d2121 = p21.dot( p21 ); + this.time = 0; // Zero out time attribute for AnimationMixer object; + for ( let i = 0; i < this._actions.length; i ++ ) { - const denom = d2121.mul( d4343 ).sub( d4321.mul( d4321 ) ); - const numer = d1343.mul( d4321 ).sub( d1321.mul( d4343 ) ); + this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects. - const mua = numer.div( denom ).clamp(); - const mub = d1343.add( d4321.mul( mua ) ).div( d4343 ).clamp(); + } - return vec2( mua, mub ); + return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object. - } ); + } - this.fragmentNode = Fn( () => { + // return this mixer's root target object + getRoot() { - const vUv = varyingProperty( 'vec2', 'vUv' ); + return this._root; - if ( useDash ) { + } - const offsetNode = this.offsetNode ? float( this.offsetNodeNode ) : materialLineDashOffset; - const dashScaleNode = this.dashScaleNode ? float( this.dashScaleNode ) : materialLineScale; - const dashSizeNode = this.dashSizeNode ? float( this.dashSizeNode ) : materialLineDashSize; - const gapSizeNode = this.dashSizeNode ? float( this.dashGapNode ) : materialLineGapSize; + // free all resources specific to a particular clip + uncacheClip( clip ) { - dashSize.assign( dashSizeNode ); - gapSize.assign( gapSizeNode ); + const actions = this._actions, + clipUuid = clip.uuid, + actionsByClip = this._actionsByClip, + actionsForClip = actionsByClip[ clipUuid ]; - const instanceDistanceStart = attribute( 'instanceDistanceStart' ); - const instanceDistanceEnd = attribute( 'instanceDistanceEnd' ); + if ( actionsForClip !== undefined ) { - const lineDistance = positionGeometry.y.lessThan( 0.5 ).select( dashScaleNode.mul( instanceDistanceStart ), materialLineScale.mul( instanceDistanceEnd ) ); + // note: just calling _removeInactiveAction would mess up the + // iteration state and also require updating the state we can + // just throw away - const vLineDistance = varying( lineDistance.add( materialLineDashOffset ) ); - const vLineDistanceOffset = offsetNode ? vLineDistance.add( offsetNode ) : vLineDistance; + const actionsToRemove = actionsForClip.knownActions; - vUv.y.lessThan( - 1.0 ).or( vUv.y.greaterThan( 1.0 ) ).discard(); // discard endcaps - vLineDistanceOffset.mod( dashSize.add( gapSize ) ).greaterThan( dashSize ).discard(); // todo - FIX + for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) { - } + const action = actionsToRemove[ i ]; - // force assignment into correct place in flow - const alpha = property( 'float', 'alpha' ); - alpha.assign( 1 ); + this._deactivateAction( action ); - if ( useWorldUnits ) { + const cacheIndex = action._cacheIndex, + lastInactiveAction = actions[ actions.length - 1 ]; - const worldStart = varyingProperty( 'vec3', 'worldStart' ); - const worldEnd = varyingProperty( 'vec3', 'worldEnd' ); + action._cacheIndex = null; + action._byClipCacheIndex = null; - // Find the closest points on the view ray and the line segment - const rayEnd = varyingProperty( 'vec4', 'worldPos' ).xyz.normalize().mul( 1e5 ); - const lineDir = worldEnd.sub( worldStart ); - const params = closestLineToLine( { p1: worldStart, p2: worldEnd, p3: vec3( 0.0, 0.0, 0.0 ), p4: rayEnd } ); + lastInactiveAction._cacheIndex = cacheIndex; + actions[ cacheIndex ] = lastInactiveAction; + actions.pop(); - const p1 = worldStart.add( lineDir.mul( params.x ) ); - const p2 = rayEnd.mul( params.y ); - const delta = p1.sub( p2 ); - const len = delta.length(); - const norm = len.div( materialLineWidth ); + this._removeInactiveBindingsForAction( action ); - if ( ! useDash ) { + } - if ( useAlphaToCoverage ) { + delete actionsByClip[ clipUuid ]; - const dnorm = norm.fwidth(); - alpha.assign( smoothstep( dnorm.negate().add( 0.5 ), dnorm.add( 0.5 ), norm ).oneMinus() ); + } - } else { + } - norm.greaterThan( 0.5 ).discard(); + // free all resources specific to a particular root target object + uncacheRoot( root ) { - } + const rootUuid = root.uuid, + actionsByClip = this._actionsByClip; - } + for ( const clipUuid in actionsByClip ) { - } else { + const actionByRoot = actionsByClip[ clipUuid ].actionByRoot, + action = actionByRoot[ rootUuid ]; - // round endcaps + if ( action !== undefined ) { - if ( useAlphaToCoverage ) { + this._deactivateAction( action ); + this._removeInactiveAction( action ); - const a = vUv.x; - const b = vUv.y.greaterThan( 0.0 ).select( vUv.y.sub( 1.0 ), vUv.y.add( 1.0 ) ); + } - const len2 = a.mul( a ).add( b.mul( b ) ); + } - // force assignment out of following 'if' statement - to avoid uniform control flow errors - const dlen = property( 'float', 'dlen' ); - dlen.assign( len2.fwidth() ); + const bindingsByRoot = this._bindingsByRootAndName, + bindingByName = bindingsByRoot[ rootUuid ]; - If( vUv.y.abs().greaterThan( 1.0 ), () => { + if ( bindingByName !== undefined ) { - alpha.assign( smoothstep( dlen.oneMinus(), dlen.add( 1 ), len2 ).oneMinus() ); + for ( const trackName in bindingByName ) { - } ); + const binding = bindingByName[ trackName ]; + binding.restoreOriginalState(); + this._removeInactiveBinding( binding ); - } else { + } - If( vUv.y.abs().greaterThan( 1.0 ), () => { + } - const a = vUv.x; - const b = vUv.y.greaterThan( 0.0 ).select( vUv.y.sub( 1.0 ), vUv.y.add( 1.0 ) ); - const len2 = a.mul( a ).add( b.mul( b ) ); + } - len2.greaterThan( 1.0 ).discard(); + // remove a targeted clip from the cache + uncacheAction( clip, optionalRoot ) { - } ); + const action = this.existingAction( clip, optionalRoot ); - } + if ( action !== null ) { - } + this._deactivateAction( action ); + this._removeInactiveAction( action ); - let lineColorNode; + } - if ( this.lineColorNode ) { + } - lineColorNode = this.lineColorNode; +} - } else { +let Uniform$1 = class Uniform { - if ( useColor ) { + constructor( value ) { - const instanceColorStart = attribute( 'instanceColorStart' ); - const instanceColorEnd = attribute( 'instanceColorEnd' ); + this.value = value; - const instanceColor = positionGeometry.y.lessThan( 0.5 ).select( instanceColorStart, instanceColorEnd ); + } - lineColorNode = instanceColor.mul( materialColor ); + clone() { - } else { + return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() ); - lineColorNode = materialColor; + } - } +}; - } +let _id$8 = 0; - return vec4( lineColorNode, alpha ); +let UniformsGroup$1 = class UniformsGroup extends EventDispatcher { - } )(); + constructor() { - } + super(); + this.isUniformsGroup = true; - get worldUnits() { + Object.defineProperty( this, 'id', { value: _id$8 ++ } ); - return this.useWorldUnits; + this.name = ''; - } + this.usage = StaticDrawUsage; + this.uniforms = []; - set worldUnits( value ) { + } - if ( this.useWorldUnits !== value ) { + add( uniform ) { - this.useWorldUnits = value; - this.needsUpdate = true; + this.uniforms.push( uniform ); - } + return this; } + remove( uniform ) { - get dashed() { + const index = this.uniforms.indexOf( uniform ); - return this.useDash; + if ( index !== - 1 ) this.uniforms.splice( index, 1 ); - } + return this; - set dashed( value ) { + } - if ( this.useDash !== value ) { + setName( name ) { - this.useDash = value; - this.needsUpdate = true; + this.name = name; - } + return this; } + setUsage( value ) { - get alphaToCoverage() { + this.usage = value; - return this.useAlphaToCoverage; + return this; } - set alphaToCoverage( value ) { - - if ( this.useAlphaToCoverage !== value ) { + dispose() { - this.useAlphaToCoverage = value; - this.needsUpdate = true; + this.dispatchEvent( { type: 'dispose' } ); - } + return this; } -} + copy( source ) { -Line2NodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'Line2', Line2NodeMaterial ); + this.name = source.name; + this.usage = source.usage; -const directionToColor = ( node ) => nodeObject( node ).mul( 0.5 ).add( 0.5 ); -const colorToDirection = ( node ) => nodeObject( node ).mul( 2.0 ).sub( 1 ); + const uniformsSource = source.uniforms; -const _defaultValues$a = /*@__PURE__*/ new MeshNormalMaterial(); + this.uniforms.length = 0; -class MeshNormalNodeMaterial extends NodeMaterial { + for ( let i = 0, l = uniformsSource.length; i < l; i ++ ) { - constructor( parameters ) { + const uniforms = Array.isArray( uniformsSource[ i ] ) ? uniformsSource[ i ] : [ uniformsSource[ i ] ]; - super(); + for ( let j = 0; j < uniforms.length; j ++ ) { - this.lights = false; + this.uniforms.push( uniforms[ j ].clone() ); - this.isMeshNormalNodeMaterial = true; + } - this.setDefaultValues( _defaultValues$a ); + } - this.setValues( parameters ); + return this; } - setupDiffuseColor() { - - const opacityNode = this.opacityNode ? float( this.opacityNode ) : materialOpacity; + clone() { - diffuseColor.assign( vec4( directionToColor( transformedNormalView ), opacityNode ) ); + return new this.constructor().copy( this ); } -} +}; -MeshNormalNodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'MeshNormal', MeshNormalNodeMaterial ); +class InstancedInterleavedBuffer extends InterleavedBuffer { -class EquirectUVNode extends TempNode { + constructor( array, stride, meshPerAttribute = 1 ) { - constructor( dirNode = positionWorldDirection ) { + super( array, stride ); - super( 'vec2' ); + this.isInstancedInterleavedBuffer = true; - this.dirNode = dirNode; + this.meshPerAttribute = meshPerAttribute; } - setup() { + copy( source ) { - const dir = this.dirNode; + super.copy( source ); - const u = dir.z.atan2( dir.x ).mul( 1 / ( Math.PI * 2 ) ).add( 0.5 ); - const v = dir.y.clamp( - 1.0, 1.0 ).asin().mul( 1 / Math.PI ).add( 0.5 ); + this.meshPerAttribute = source.meshPerAttribute; - return vec2( u, v ); + return this; } -} + clone( data ) { -EquirectUVNode.type = /*@__PURE__*/ registerNode( 'EquirectUV', EquirectUVNode ); + const ib = super.clone( data ); -const equirectUV = /*@__PURE__*/ nodeProxy( EquirectUVNode ); + ib.meshPerAttribute = this.meshPerAttribute; -// @TODO: Consider rename WebGLCubeRenderTarget to just CubeRenderTarget + return ib; -class CubeRenderTarget extends WebGLCubeRenderTarget { + } - constructor( size = 1, options = {} ) { + toJSON( data ) { - super( size, options ); + const json = super.toJSON( data ); - this.isCubeRenderTarget = true; + json.isInstancedInterleavedBuffer = true; + json.meshPerAttribute = this.meshPerAttribute; + + return json; } - fromEquirectangularTexture( renderer, texture$1 ) { +} - const currentMinFilter = texture$1.minFilter; - const currentGenerateMipmaps = texture$1.generateMipmaps; +class GLBufferAttribute { - texture$1.generateMipmaps = true; + constructor( buffer, type, itemSize, elementSize, count ) { - this.texture.type = texture$1.type; - this.texture.colorSpace = texture$1.colorSpace; + this.isGLBufferAttribute = true; - this.texture.generateMipmaps = texture$1.generateMipmaps; - this.texture.minFilter = texture$1.minFilter; - this.texture.magFilter = texture$1.magFilter; + this.name = ''; - const geometry = new BoxGeometry( 5, 5, 5 ); + this.buffer = buffer; + this.type = type; + this.itemSize = itemSize; + this.elementSize = elementSize; + this.count = count; - const uvNode = equirectUV( positionWorldDirection ); + this.version = 0; - const material = new NodeMaterial(); - material.colorNode = texture( texture$1, uvNode, 0 ); - material.side = BackSide; - material.blending = NoBlending; + } - const mesh = new Mesh( geometry, material ); + set needsUpdate( value ) { - const scene = new Scene(); - scene.add( mesh ); + if ( value === true ) this.version ++; - // Avoid blurred poles - if ( texture$1.minFilter === LinearMipmapLinearFilter ) texture$1.minFilter = LinearFilter; + } - const camera = new CubeCamera( 1, 10, this ); + setBuffer( buffer ) { - const currentMRT = renderer.getMRT(); - renderer.setMRT( null ); + this.buffer = buffer; - camera.update( renderer, scene ); + return this; - renderer.setMRT( currentMRT ); + } - texture$1.minFilter = currentMinFilter; - texture$1.currentGenerateMipmaps = currentGenerateMipmaps; + setType( type, elementSize ) { - mesh.geometry.dispose(); - mesh.material.dispose(); + this.type = type; + this.elementSize = elementSize; return this; } -} - -const _cache$1 = new WeakMap(); - -class CubeMapNode extends TempNode { - - constructor( envNode ) { + setItemSize( itemSize ) { - super( 'vec3' ); + this.itemSize = itemSize; - this.envNode = envNode; + return this; - this._cubeTexture = null; - this._cubeTextureNode = cubeTexture(); + } - const defaultTexture = new CubeTexture(); - defaultTexture.isRenderTargetTexture = true; + setCount( count ) { - this._defaultTexture = defaultTexture; + this.count = count; - this.updateBeforeType = NodeUpdateType.RENDER; + return this; } - updateBefore( frame ) { +} - const { renderer, material } = frame; +const _matrix = /*@__PURE__*/ new Matrix4(); - const envNode = this.envNode; +class Raycaster { - if ( envNode.isTextureNode || envNode.isMaterialReferenceNode ) { + constructor( origin, direction, near = 0, far = Infinity ) { - const texture = ( envNode.isTextureNode ) ? envNode.value : material[ envNode.property ]; + this.ray = new Ray( origin, direction ); + // direction is assumed to be normalized (for accurate distance calculations) - if ( texture && texture.isTexture ) { + this.near = near; + this.far = far; + this.camera = null; + this.layers = new Layers(); - const mapping = texture.mapping; + this.params = { + Mesh: {}, + Line: { threshold: 1 }, + LOD: {}, + Points: { threshold: 1 }, + Sprite: {} + }; - if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) { + } - // check for converted cubemap map + set( origin, direction ) { - if ( _cache$1.has( texture ) ) { + // direction is assumed to be normalized (for accurate distance calculations) - const cubeMap = _cache$1.get( texture ); + this.ray.set( origin, direction ); - mapTextureMapping( cubeMap, texture.mapping ); - this._cubeTexture = cubeMap; + } - } else { + setFromCamera( coords, camera ) { - // create cube map from equirectangular map + if ( camera.isPerspectiveCamera ) { - const image = texture.image; + this.ray.origin.setFromMatrixPosition( camera.matrixWorld ); + this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize(); + this.camera = camera; - if ( isEquirectangularMapReady$1( image ) ) { + } else if ( camera.isOrthographicCamera ) { - const renderTarget = new CubeRenderTarget( image.height ); - renderTarget.fromEquirectangularTexture( renderer, texture ); + this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera + this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); + this.camera = camera; - mapTextureMapping( renderTarget.texture, texture.mapping ); - this._cubeTexture = renderTarget.texture; + } else { - _cache$1.set( texture, renderTarget.texture ); + console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type ); - texture.addEventListener( 'dispose', onTextureDispose ); + } - } else { + } - // default cube texture as fallback when equirectangular texture is not yet loaded + setFromXRController( controller ) { - this._cubeTexture = this._defaultTexture; + _matrix.identity().extractRotation( controller.matrixWorld ); - } + this.ray.origin.setFromMatrixPosition( controller.matrixWorld ); + this.ray.direction.set( 0, 0, - 1 ).applyMatrix4( _matrix ); - } + return this; - // + } - this._cubeTextureNode.value = this._cubeTexture; + intersectObject( object, recursive = true, intersects = [] ) { - } else { + intersect( object, this, intersects, recursive ); - // envNode already refers to a cube map + intersects.sort( ascSort ); - this._cubeTextureNode = this.envNode; + return intersects; - } + } - } + intersectObjects( objects, recursive = true, intersects = [] ) { - } + for ( let i = 0, l = objects.length; i < l; i ++ ) { - } + intersect( objects[ i ], this, intersects, recursive ); - setup( builder ) { + } - this.updateBefore( builder ); + intersects.sort( ascSort ); - return this._cubeTextureNode; + return intersects; } } -CubeMapNode.type = /*@__PURE__*/ registerNode( 'CubeMap', CubeMapNode ); - -function isEquirectangularMapReady$1( image ) { - - if ( image === null || image === undefined ) return false; +function ascSort( a, b ) { - return image.height > 0; + return a.distance - b.distance; } -function onTextureDispose( event ) { - - const texture = event.target; - - texture.removeEventListener( 'dispose', onTextureDispose ); +function intersect( object, raycaster, intersects, recursive ) { - const renderTarget = _cache$1.get( texture ); + let propagate = true; - if ( renderTarget !== undefined ) { + if ( object.layers.test( raycaster.layers ) ) { - _cache$1.delete( texture ); + const result = object.raycast( raycaster, intersects ); - renderTarget.dispose(); + if ( result === false ) propagate = false; } -} - -function mapTextureMapping( texture, mapping ) { + if ( propagate === true && recursive === true ) { - if ( mapping === EquirectangularReflectionMapping ) { + const children = object.children; - texture.mapping = CubeReflectionMapping; + for ( let i = 0, l = children.length; i < l; i ++ ) { - } else if ( mapping === EquirectangularRefractionMapping ) { + intersect( children[ i ], raycaster, intersects, true ); - texture.mapping = CubeRefractionMapping; + } } } -const cubeMapNode = /*@__PURE__*/ nodeProxy( CubeMapNode ); - -class BasicEnvironmentNode extends LightingNode { +/** + * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system + * + * phi (the polar angle) is measured from the positive y-axis. The positive y-axis is up. + * theta (the azimuthal angle) is measured from the positive z-axis. + */ +class Spherical { - constructor( envNode = null ) { + constructor( radius = 1, phi = 0, theta = 0 ) { - super(); + this.radius = radius; + this.phi = phi; // polar angle + this.theta = theta; // azimuthal angle - this.envNode = envNode; + return this; } - setup( builder ) { + set( radius, phi, theta ) { - // environment property is used in the finish() method of BasicLightingModel + this.radius = radius; + this.phi = phi; + this.theta = theta; - builder.context.environment = cubeMapNode( this.envNode ); + return this; } -} + copy( other ) { -BasicEnvironmentNode.type = /*@__PURE__*/ registerNode( 'BasicEnvironment', BasicEnvironmentNode ); + this.radius = other.radius; + this.phi = other.phi; + this.theta = other.theta; -class BasicLightMapNode extends LightingNode { + return this; - constructor( lightMapNode = null ) { + } - super(); + // restrict phi to be between EPS and PI-EPS + makeSafe() { - this.lightMapNode = lightMapNode; + const EPS = 0.000001; + this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) ); + + return this; } - setup( builder ) { + setFromVector3( v ) { - // irradianceLightMap property is used in the indirectDiffuse() method of BasicLightingModel + return this.setFromCartesianCoords( v.x, v.y, v.z ); - const RECIPROCAL_PI = float( 1 / Math.PI ); + } - builder.context.irradianceLightMap = this.lightMapNode.mul( RECIPROCAL_PI ); + setFromCartesianCoords( x, y, z ) { - } + this.radius = Math.sqrt( x * x + y * y + z * z ); -} + if ( this.radius === 0 ) { -BasicLightMapNode.type = /*@__PURE__*/ registerNode( 'BasicLightMap', BasicLightMapNode ); + this.theta = 0; + this.phi = 0; -class LightingModel { + } else { - start( /*input, stack, builder*/ ) { } + this.theta = Math.atan2( x, z ); + this.phi = Math.acos( clamp$1( y / this.radius, - 1, 1 ) ); - finish( /*input, stack, builder*/ ) { } + } - direct( /*input, stack, builder*/ ) { } + return this; - directRectArea( /*input, stack, builder*/ ) {} + } - indirect( /*input, stack, builder*/ ) { } + clone() { - ambientOcclusion( /*input, stack, builder*/ ) { } + return new this.constructor().copy( this ); + + } } -class BasicLightingModel extends LightingModel { +/** + * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system + */ - constructor() { +class Cylindrical { - super(); + constructor( radius = 1, theta = 0, y = 0 ) { - } + this.radius = radius; // distance from the origin to a point in the x-z plane + this.theta = theta; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis + this.y = y; // height above the x-z plane - indirect( context, stack, builder ) { - - const ambientOcclusion = context.ambientOcclusion; - const reflectedLight = context.reflectedLight; - const irradianceLightMap = builder.context.irradianceLightMap; - - reflectedLight.indirectDiffuse.assign( vec4( 0.0 ) ); - - // accumulation (baked indirect lighting only) + return this; - if ( irradianceLightMap ) { + } - reflectedLight.indirectDiffuse.addAssign( irradianceLightMap ); + set( radius, theta, y ) { - } else { + this.radius = radius; + this.theta = theta; + this.y = y; - reflectedLight.indirectDiffuse.addAssign( vec4( 1.0, 1.0, 1.0, 0.0 ) ); + return this; - } + } - // modulation + copy( other ) { - reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion ); + this.radius = other.radius; + this.theta = other.theta; + this.y = other.y; - reflectedLight.indirectDiffuse.mulAssign( diffuseColor.rgb ); + return this; } - finish( context, stack, builder ) { - - const material = builder.material; - const outgoingLight = context.outgoingLight; - const envNode = builder.context.environment; + setFromVector3( v ) { - if ( envNode ) { + return this.setFromCartesianCoords( v.x, v.y, v.z ); - switch ( material.combine ) { + } - case MultiplyOperation: - outgoingLight.rgb.assign( mix( outgoingLight.rgb, outgoingLight.rgb.mul( envNode.rgb ), materialSpecularStrength.mul( materialReflectivity ) ) ); - break; + setFromCartesianCoords( x, y, z ) { - case MixOperation: - outgoingLight.rgb.assign( mix( outgoingLight.rgb, envNode.rgb, materialSpecularStrength.mul( materialReflectivity ) ) ); - break; + this.radius = Math.sqrt( x * x + z * z ); + this.theta = Math.atan2( x, z ); + this.y = y; - case AddOperation: - outgoingLight.rgb.addAssign( envNode.rgb.mul( materialSpecularStrength.mul( materialReflectivity ) ) ); - break; + return this; - default: - console.warn( 'THREE.BasicLightingModel: Unsupported .combine value:', material.combine ); - break; + } - } + clone() { - } + return new this.constructor().copy( this ); } } -const _defaultValues$9 = /*@__PURE__*/ new MeshBasicMaterial(); - -class MeshBasicNodeMaterial extends NodeMaterial { - - constructor( parameters ) { - - super(); - - this.isMeshBasicNodeMaterial = true; +class Matrix2 { - this.lights = true; + constructor( n11, n12, n21, n22 ) { - this.setDefaultValues( _defaultValues$9 ); + Matrix2.prototype.isMatrix2 = true; - this.setValues( parameters ); + this.elements = [ + 1, 0, + 0, 1, + ]; - } + if ( n11 !== undefined ) { - setupNormal() { + this.set( n11, n12, n21, n22 ); - return normalView; // see #28839 + } } - setupEnvironment( builder ) { + identity() { - const envNode = super.setupEnvironment( builder ); + this.set( + 1, 0, + 0, 1, + ); - return envNode ? new BasicEnvironmentNode( envNode ) : null; + return this; } - setupLightMap( builder ) { - - let node = null; + fromArray( array, offset = 0 ) { - if ( builder.material.lightMap ) { + for ( let i = 0; i < 4; i ++ ) { - node = new BasicLightMapNode( materialLightMap ); + this.elements[ i ] = array[ i + offset ]; } - return node; + return this; } - setupOutgoingLight() { - - return diffuseColor.rgb; + set( n11, n12, n21, n22 ) { - } + const te = this.elements; - setupLightingModel() { + te[ 0 ] = n11; te[ 2 ] = n12; + te[ 1 ] = n21; te[ 3 ] = n22; - return new BasicLightingModel(); + return this; } } -MeshBasicNodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'MeshBasic', MeshBasicNodeMaterial ); +const _vector$4 = /*@__PURE__*/ new Vector2(); -const F_Schlick = /*@__PURE__*/ Fn( ( { f0, f90, dotVH } ) => { +class Box2 { - // Original approximation by Christophe Schlick '94 - // float fresnel = pow( 1.0 - dotVH, 5.0 ); + constructor( min = new Vector2( + Infinity, + Infinity ), max = new Vector2( - Infinity, - Infinity ) ) { - // Optimized variant (presented by Epic at SIGGRAPH '13) - // https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf - const fresnel = dotVH.mul( - 5.55473 ).sub( 6.98316 ).mul( dotVH ).exp2(); + this.isBox2 = true; - return f0.mul( fresnel.oneMinus() ).add( f90.mul( fresnel ) ); + this.min = min; + this.max = max; -} ); // validated + } -const BRDF_Lambert = /*@__PURE__*/ Fn( ( inputs ) => { + set( min, max ) { - return inputs.diffuseColor.mul( 1 / Math.PI ); // punctual light + this.min.copy( min ); + this.max.copy( max ); -} ); // validated + return this; -const G_BlinnPhong_Implicit = () => float( 0.25 ); + } -const D_BlinnPhong = /*@__PURE__*/ Fn( ( { dotNH } ) => { + setFromPoints( points ) { - return shininess.mul( float( 0.5 ) ).add( 1.0 ).mul( float( 1 / Math.PI ) ).mul( dotNH.pow( shininess ) ); + this.makeEmpty(); -} ); + for ( let i = 0, il = points.length; i < il; i ++ ) { -const BRDF_BlinnPhong = /*@__PURE__*/ Fn( ( { lightDirection } ) => { + this.expandByPoint( points[ i ] ); - const halfDir = lightDirection.add( positionViewDirection ).normalize(); + } - const dotNH = transformedNormalView.dot( halfDir ).clamp(); - const dotVH = positionViewDirection.dot( halfDir ).clamp(); + return this; - const F = F_Schlick( { f0: specularColor, f90: 1.0, dotVH } ); - const G = G_BlinnPhong_Implicit(); - const D = D_BlinnPhong( { dotNH } ); + } - return F.mul( G ).mul( D ); + setFromCenterAndSize( center, size ) { -} ); + const halfSize = _vector$4.copy( size ).multiplyScalar( 0.5 ); + this.min.copy( center ).sub( halfSize ); + this.max.copy( center ).add( halfSize ); -class PhongLightingModel extends BasicLightingModel { + return this; - constructor( specular = true ) { + } - super(); + clone() { - this.specular = specular; + return new this.constructor().copy( this ); } - direct( { lightDirection, lightColor, reflectedLight } ) { + copy( box ) { - const dotNL = transformedNormalView.dot( lightDirection ).clamp(); - const irradiance = dotNL.mul( lightColor ); + this.min.copy( box.min ); + this.max.copy( box.max ); - reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) ); + return this; - if ( this.specular === true ) { + } - reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_BlinnPhong( { lightDirection } ) ).mul( materialSpecularStrength ) ); + makeEmpty() { - } + this.min.x = this.min.y = + Infinity; + this.max.x = this.max.y = - Infinity; + + return this; } - indirect( { ambientOcclusion, irradiance, reflectedLight } ) { + isEmpty() { - reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) ); + // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes - reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion ); + return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ); } -} + getCenter( target ) { -const _defaultValues$8 = /*@__PURE__*/ new MeshLambertMaterial(); + return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); -class MeshLambertNodeMaterial extends NodeMaterial { + } - constructor( parameters ) { + getSize( target ) { - super(); + return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min ); - this.isMeshLambertNodeMaterial = true; + } - this.lights = true; + expandByPoint( point ) { - this.setDefaultValues( _defaultValues$8 ); + this.min.min( point ); + this.max.max( point ); - this.setValues( parameters ); + return this; } - setupEnvironment( builder ) { + expandByVector( vector ) { - const envNode = super.setupEnvironment( builder ); + this.min.sub( vector ); + this.max.add( vector ); - return envNode ? new BasicEnvironmentNode( envNode ) : null; + return this; } - setupLightingModel( /*builder*/ ) { - - return new PhongLightingModel( false ); // ( specular ) -> force lambert + expandByScalar( scalar ) { - } + this.min.addScalar( - scalar ); + this.max.addScalar( scalar ); -} + return this; -MeshLambertNodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'MeshLambert', MeshLambertNodeMaterial ); + } -const _defaultValues$7 = /*@__PURE__*/ new MeshPhongMaterial(); + containsPoint( point ) { -class MeshPhongNodeMaterial extends NodeMaterial { + return point.x >= this.min.x && point.x <= this.max.x && + point.y >= this.min.y && point.y <= this.max.y; - constructor( parameters ) { + } - super(); + containsBox( box ) { - this.isMeshPhongNodeMaterial = true; + return this.min.x <= box.min.x && box.max.x <= this.max.x && + this.min.y <= box.min.y && box.max.y <= this.max.y; - this.lights = true; + } - this.shininessNode = null; - this.specularNode = null; + getParameter( point, target ) { - this.setDefaultValues( _defaultValues$7 ); + // This can potentially have a divide by zero if the box + // has a size dimension of 0. - this.setValues( parameters ); + return target.set( + ( point.x - this.min.x ) / ( this.max.x - this.min.x ), + ( point.y - this.min.y ) / ( this.max.y - this.min.y ) + ); } - setupEnvironment( builder ) { + intersectsBox( box ) { - const envNode = super.setupEnvironment( builder ); + // using 4 splitting planes to rule out intersections - return envNode ? new BasicEnvironmentNode( envNode ) : null; + return box.max.x >= this.min.x && box.min.x <= this.max.x && + box.max.y >= this.min.y && box.min.y <= this.max.y; } - setupLightingModel( /*builder*/ ) { + clampPoint( point, target ) { - return new PhongLightingModel(); + return target.copy( point ).clamp( this.min, this.max ); } - setupVariants() { + distanceToPoint( point ) { - // SHININESS + return this.clampPoint( point, _vector$4 ).distanceTo( point ); - const shininessNode = ( this.shininessNode ? float( this.shininessNode ) : materialShininess ).max( 1e-4 ); // to prevent pow( 0.0, 0.0 ) + } - shininess.assign( shininessNode ); + intersect( box ) { - // SPECULAR COLOR + this.min.max( box.min ); + this.max.min( box.max ); - const specularNode = this.specularNode || materialSpecular; + if ( this.isEmpty() ) this.makeEmpty(); - specularColor.assign( specularNode ); + return this; } - copy( source ) { + union( box ) { - this.shininessNode = source.shininessNode; - this.specularNode = source.specularNode; + this.min.min( box.min ); + this.max.max( box.max ); - return super.copy( source ); + return this; } -} + translate( offset ) { -MeshPhongNodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'MeshPhong', MeshPhongNodeMaterial ); + this.min.add( offset ); + this.max.add( offset ); -const getGeometryRoughness = /*@__PURE__*/ Fn( () => { + return this; - const dxy = normalView.dFdx().abs().max( normalView.dFdy().abs() ); - const geometryRoughness = dxy.x.max( dxy.y ).max( dxy.z ); + } - return geometryRoughness; + equals( box ) { -} ); + return box.min.equals( this.min ) && box.max.equals( this.max ); -const getRoughness = /*@__PURE__*/ Fn( ( inputs ) => { + } - const { roughness } = inputs; +} - const geometryRoughness = getGeometryRoughness(); +const _startP = /*@__PURE__*/ new Vector3(); +const _startEnd = /*@__PURE__*/ new Vector3(); - let roughnessFactor = roughness.max( 0.0525 ); // 0.0525 corresponds to the base mip of a 256 cubemap. - roughnessFactor = roughnessFactor.add( geometryRoughness ); - roughnessFactor = roughnessFactor.min( 1.0 ); +class Line3 { - return roughnessFactor; + constructor( start = new Vector3(), end = new Vector3() ) { -} ); + this.start = start; + this.end = end; -// Moving Frostbite to Physically Based Rendering 3.0 - page 12, listing 2 -// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf -const V_GGX_SmithCorrelated = /*@__PURE__*/ Fn( ( { alpha, dotNL, dotNV } ) => { + } - const a2 = alpha.pow2(); + set( start, end ) { - const gv = dotNL.mul( a2.add( a2.oneMinus().mul( dotNV.pow2() ) ).sqrt() ); - const gl = dotNV.mul( a2.add( a2.oneMinus().mul( dotNL.pow2() ) ).sqrt() ); + this.start.copy( start ); + this.end.copy( end ); - return div( 0.5, gv.add( gl ).max( EPSILON ) ); + return this; -} ).setLayout( { - name: 'V_GGX_SmithCorrelated', - type: 'float', - inputs: [ - { name: 'alpha', type: 'float' }, - { name: 'dotNL', type: 'float' }, - { name: 'dotNV', type: 'float' } - ] -} ); // validated + } -// https://google.github.io/filament/Filament.md.html#materialsystem/anisotropicmodel/anisotropicspecularbrdf + copy( line ) { -const V_GGX_SmithCorrelated_Anisotropic = /*@__PURE__*/ Fn( ( { alphaT, alphaB, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL } ) => { + this.start.copy( line.start ); + this.end.copy( line.end ); - const gv = dotNL.mul( vec3( alphaT.mul( dotTV ), alphaB.mul( dotBV ), dotNV ).length() ); - const gl = dotNV.mul( vec3( alphaT.mul( dotTL ), alphaB.mul( dotBL ), dotNL ).length() ); - const v = div( 0.5, gv.add( gl ) ); + return this; - return v.saturate(); + } -} ).setLayout( { - name: 'V_GGX_SmithCorrelated_Anisotropic', - type: 'float', - inputs: [ - { name: 'alphaT', type: 'float', qualifier: 'in' }, - { name: 'alphaB', type: 'float', qualifier: 'in' }, - { name: 'dotTV', type: 'float', qualifier: 'in' }, - { name: 'dotBV', type: 'float', qualifier: 'in' }, - { name: 'dotTL', type: 'float', qualifier: 'in' }, - { name: 'dotBL', type: 'float', qualifier: 'in' }, - { name: 'dotNV', type: 'float', qualifier: 'in' }, - { name: 'dotNL', type: 'float', qualifier: 'in' } - ] -} ); + getCenter( target ) { -// Microfacet Models for Refraction through Rough Surfaces - equation (33) -// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html -// alpha is "roughness squared" in Disney’s reparameterization -const D_GGX = /*@__PURE__*/ Fn( ( { alpha, dotNH } ) => { + return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); - const a2 = alpha.pow2(); + } - const denom = dotNH.pow2().mul( a2.oneMinus() ).oneMinus(); // avoid alpha = 0 with dotNH = 1 + delta( target ) { - return a2.div( denom.pow2() ).mul( 1 / Math.PI ); + return target.subVectors( this.end, this.start ); -} ).setLayout( { - name: 'D_GGX', - type: 'float', - inputs: [ - { name: 'alpha', type: 'float' }, - { name: 'dotNH', type: 'float' } - ] -} ); // validated + } -const RECIPROCAL_PI = /*@__PURE__*/ float( 1 / Math.PI ); + distanceSq() { -// https://google.github.io/filament/Filament.md.html#materialsystem/anisotropicmodel/anisotropicspecularbrdf + return this.start.distanceToSquared( this.end ); -const D_GGX_Anisotropic = /*@__PURE__*/ Fn( ( { alphaT, alphaB, dotNH, dotTH, dotBH } ) => { + } - const a2 = alphaT.mul( alphaB ); - const v = vec3( alphaB.mul( dotTH ), alphaT.mul( dotBH ), a2.mul( dotNH ) ); - const v2 = v.dot( v ); - const w2 = a2.div( v2 ); + distance() { - return RECIPROCAL_PI.mul( a2.mul( w2.pow2() ) ); + return this.start.distanceTo( this.end ); -} ).setLayout( { - name: 'D_GGX_Anisotropic', - type: 'float', - inputs: [ - { name: 'alphaT', type: 'float', qualifier: 'in' }, - { name: 'alphaB', type: 'float', qualifier: 'in' }, - { name: 'dotNH', type: 'float', qualifier: 'in' }, - { name: 'dotTH', type: 'float', qualifier: 'in' }, - { name: 'dotBH', type: 'float', qualifier: 'in' } - ] -} ); + } -// GGX Distribution, Schlick Fresnel, GGX_SmithCorrelated Visibility -const BRDF_GGX = /*@__PURE__*/ Fn( ( inputs ) => { + at( t, target ) { - const { lightDirection, f0, f90, roughness, f, USE_IRIDESCENCE, USE_ANISOTROPY } = inputs; + return this.delta( target ).multiplyScalar( t ).add( this.start ); - const normalView = inputs.normalView || transformedNormalView; + } - const alpha = roughness.pow2(); // UE4's roughness + closestPointToPointParameter( point, clampToLine ) { - const halfDir = lightDirection.add( positionViewDirection ).normalize(); + _startP.subVectors( point, this.start ); + _startEnd.subVectors( this.end, this.start ); - const dotNL = normalView.dot( lightDirection ).clamp(); - const dotNV = normalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV - const dotNH = normalView.dot( halfDir ).clamp(); - const dotVH = positionViewDirection.dot( halfDir ).clamp(); + const startEnd2 = _startEnd.dot( _startEnd ); + const startEnd_startP = _startEnd.dot( _startP ); - let F = F_Schlick( { f0, f90, dotVH } ); - let V, D; + let t = startEnd_startP / startEnd2; - if ( defined( USE_IRIDESCENCE ) ) { + if ( clampToLine ) { - F = iridescence.mix( F, f ); + t = clamp$1( t, 0, 1 ); - } + } - if ( defined( USE_ANISOTROPY ) ) { + return t; - const dotTL = anisotropyT.dot( lightDirection ); - const dotTV = anisotropyT.dot( positionViewDirection ); - const dotTH = anisotropyT.dot( halfDir ); - const dotBL = anisotropyB.dot( lightDirection ); - const dotBV = anisotropyB.dot( positionViewDirection ); - const dotBH = anisotropyB.dot( halfDir ); + } - V = V_GGX_SmithCorrelated_Anisotropic( { alphaT, alphaB: alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL } ); - D = D_GGX_Anisotropic( { alphaT, alphaB: alpha, dotNH, dotTH, dotBH } ); + closestPointToPoint( point, clampToLine, target ) { - } else { + const t = this.closestPointToPointParameter( point, clampToLine ); - V = V_GGX_SmithCorrelated( { alpha, dotNL, dotNV } ); - D = D_GGX( { alpha, dotNH } ); + return this.delta( target ).multiplyScalar( t ).add( this.start ); } - return F.mul( V ).mul( D ); + applyMatrix4( matrix ) { -} ); // validated + this.start.applyMatrix4( matrix ); + this.end.applyMatrix4( matrix ); -// Analytical approximation of the DFG LUT, one half of the -// split-sum approximation used in indirect specular lighting. -// via 'environmentBRDF' from "Physically Based Shading on Mobile" -// https://www.unrealengine.com/blog/physically-based-shading-on-mobile -const DFGApprox = /*@__PURE__*/ Fn( ( { roughness, dotNV } ) => { + return this; - const c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 ); + } - const c1 = vec4( 1, 0.0425, 1.04, - 0.04 ); + equals( line ) { - const r = roughness.mul( c0 ).add( c1 ); + return line.start.equals( this.start ) && line.end.equals( this.end ); - const a004 = r.x.mul( r.x ).min( dotNV.mul( - 9.28 ).exp2() ).mul( r.x ).add( r.y ); + } - const fab = vec2( - 1.04, 1.04 ).mul( a004 ).add( r.zw ); + clone() { - return fab; + return new this.constructor().copy( this ); -} ).setLayout( { - name: 'DFGApprox', - type: 'vec2', - inputs: [ - { name: 'roughness', type: 'float' }, - { name: 'dotNV', type: 'vec3' } - ] -} ); + } -const EnvironmentBRDF = /*@__PURE__*/ Fn( ( inputs ) => { +} - const { dotNV, specularColor, specularF90, roughness } = inputs; +const _vector$3 = /*@__PURE__*/ new Vector3(); - const fab = DFGApprox( { dotNV, roughness } ); - return specularColor.mul( fab.x ).add( specularF90.mul( fab.y ) ); +class SpotLightHelper extends Object3D { -} ); + constructor( light, color ) { -const Schlick_to_F0 = /*@__PURE__*/ Fn( ( { f, f90, dotVH } ) => { + super(); - const x = dotVH.oneMinus().saturate(); - const x2 = x.mul( x ); - const x5 = x.mul( x2, x2 ).clamp( 0, .9999 ); + this.light = light; - return f.sub( vec3( f90 ).mul( x5 ) ).div( x5.oneMinus() ); + this.matrixAutoUpdate = false; -} ).setLayout( { - name: 'Schlick_to_F0', - type: 'vec3', - inputs: [ - { name: 'f', type: 'vec3' }, - { name: 'f90', type: 'float' }, - { name: 'dotVH', type: 'float' } - ] -} ); + this.color = color; -// https://github.com/google/filament/blob/master/shaders/src/brdf.fs -const D_Charlie = /*@__PURE__*/ Fn( ( { roughness, dotNH } ) => { + this.type = 'SpotLightHelper'; - const alpha = roughness.pow2(); + const geometry = new BufferGeometry(); - // Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF" - const invAlpha = float( 1.0 ).div( alpha ); - const cos2h = dotNH.pow2(); - const sin2h = cos2h.oneMinus().max( 0.0078125 ); // 2^(-14/2), so sin2h^2 > 0 in fp16 + const positions = [ + 0, 0, 0, 0, 0, 1, + 0, 0, 0, 1, 0, 1, + 0, 0, 0, - 1, 0, 1, + 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, - 1, 1 + ]; - return float( 2.0 ).add( invAlpha ).mul( sin2h.pow( invAlpha.mul( 0.5 ) ) ).div( 2.0 * Math.PI ); + for ( let i = 0, j = 1, l = 32; i < l; i ++, j ++ ) { -} ).setLayout( { - name: 'D_Charlie', - type: 'float', - inputs: [ - { name: 'roughness', type: 'float' }, - { name: 'dotNH', type: 'float' } - ] -} ); + const p1 = ( i / l ) * Math.PI * 2; + const p2 = ( j / l ) * Math.PI * 2; -// https://github.com/google/filament/blob/master/shaders/src/brdf.fs -const V_Neubelt = /*@__PURE__*/ Fn( ( { dotNV, dotNL } ) => { + positions.push( + Math.cos( p1 ), Math.sin( p1 ), 1, + Math.cos( p2 ), Math.sin( p2 ), 1 + ); - // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886" - return float( 1.0 ).div( float( 4.0 ).mul( dotNL.add( dotNV ).sub( dotNL.mul( dotNV ) ) ) ); + } -} ).setLayout( { - name: 'V_Neubelt', - type: 'float', - inputs: [ - { name: 'dotNV', type: 'float' }, - { name: 'dotNL', type: 'float' } - ] -} ); + geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); -const BRDF_Sheen = /*@__PURE__*/ Fn( ( { lightDirection } ) => { + const material = new LineBasicMaterial( { fog: false, toneMapped: false } ); - const halfDir = lightDirection.add( positionViewDirection ).normalize(); + this.cone = new LineSegments( geometry, material ); + this.add( this.cone ); - const dotNL = transformedNormalView.dot( lightDirection ).clamp(); - const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); - const dotNH = transformedNormalView.dot( halfDir ).clamp(); + this.update(); - const D = D_Charlie( { roughness: sheenRoughness, dotNH } ); - const V = V_Neubelt( { dotNV, dotNL } ); + } - return sheen.mul( D ).mul( V ); + dispose() { -} ); + this.cone.geometry.dispose(); + this.cone.material.dispose(); -// Rect Area Light + } -// Real-Time Polygonal-Light Shading with Linearly Transformed Cosines -// by Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt -// code: https://github.com/selfshadow/ltc_code/ + update() { -const LTC_Uv = /*@__PURE__*/ Fn( ( { N, V, roughness } ) => { + this.light.updateWorldMatrix( true, false ); + this.light.target.updateWorldMatrix( true, false ); - const LUT_SIZE = 64.0; - const LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE; - const LUT_BIAS = 0.5 / LUT_SIZE; + // update the local matrix based on the parent and light target transforms + if ( this.parent ) { - const dotNV = N.dot( V ).saturate(); + this.parent.updateWorldMatrix( true ); - // texture parameterized by sqrt( GGX alpha ) and sqrt( 1 - cos( theta ) ) - const uv = vec2( roughness, dotNV.oneMinus().sqrt() ); + this.matrix + .copy( this.parent.matrixWorld ) + .invert() + .multiply( this.light.matrixWorld ); - uv.assign( uv.mul( LUT_SCALE ).add( LUT_BIAS ) ); + } else { - return uv; + this.matrix.copy( this.light.matrixWorld ); -} ).setLayout( { - name: 'LTC_Uv', - type: 'vec2', - inputs: [ - { name: 'N', type: 'vec3' }, - { name: 'V', type: 'vec3' }, - { name: 'roughness', type: 'float' } - ] -} ); + } -const LTC_ClippedSphereFormFactor = /*@__PURE__*/ Fn( ( { f } ) => { + this.matrixWorld.copy( this.light.matrixWorld ); - // Real-Time Area Lighting: a Journey from Research to Production (p.102) - // An approximation of the form factor of a horizon-clipped rectangle. + const coneLength = this.light.distance ? this.light.distance : 1000; + const coneWidth = coneLength * Math.tan( this.light.angle ); - const l = f.length(); + this.cone.scale.set( coneWidth, coneWidth, coneLength ); - return max$1( l.mul( l ).add( f.z ).div( l.add( 1.0 ) ), 0 ); + _vector$3.setFromMatrixPosition( this.light.target.matrixWorld ); -} ).setLayout( { - name: 'LTC_ClippedSphereFormFactor', - type: 'float', - inputs: [ - { name: 'f', type: 'vec3' } - ] -} ); + this.cone.lookAt( _vector$3 ); -const LTC_EdgeVectorFormFactor = /*@__PURE__*/ Fn( ( { v1, v2 } ) => { + if ( this.color !== undefined ) { - const x = v1.dot( v2 ); - const y = x.abs().toVar(); + this.cone.material.color.set( this.color ); - // rational polynomial approximation to theta / sin( theta ) / 2PI - const a = y.mul( 0.0145206 ).add( 0.4965155 ).mul( y ).add( 0.8543985 ).toVar(); - const b = y.add( 4.1616724 ).mul( y ).add( 3.4175940 ).toVar(); - const v = a.div( b ); + } else { - const theta_sintheta = x.greaterThan( 0.0 ).select( v, max$1( x.mul( x ).oneMinus(), 1e-7 ).inverseSqrt().mul( 0.5 ).sub( v ) ); + this.cone.material.color.copy( this.light.color ); - return v1.cross( v2 ).mul( theta_sintheta ); + } -} ).setLayout( { - name: 'LTC_EdgeVectorFormFactor', - type: 'vec3', - inputs: [ - { name: 'v1', type: 'vec3' }, - { name: 'v2', type: 'vec3' } - ] -} ); + } -const LTC_Evaluate = /*@__PURE__*/ Fn( ( { N, V, P, mInv, p0, p1, p2, p3 } ) => { +} - // bail if point is on back side of plane of light - // assumes ccw winding order of light vertices - const v1 = p1.sub( p0 ).toVar(); - const v2 = p3.sub( p0 ).toVar(); +const _vector$2 = /*@__PURE__*/ new Vector3(); +const _boneMatrix = /*@__PURE__*/ new Matrix4(); +const _matrixWorldInv = /*@__PURE__*/ new Matrix4(); - const lightNormal = v1.cross( v2 ); - const result = vec3().toVar(); - If( lightNormal.dot( P.sub( p0 ) ).greaterThanEqual( 0.0 ), () => { +class SkeletonHelper extends LineSegments { - // construct orthonormal basis around N - const T1 = V.sub( N.mul( V.dot( N ) ) ).normalize(); - const T2 = N.cross( T1 ).negate(); // negated from paper; possibly due to a different handedness of world coordinate system + constructor( object ) { - // compute transform - const mat = mInv.mul( mat3( T1, T2, N ).transpose() ).toVar(); + const bones = getBoneList( object ); - // transform rect - // & project rect onto sphere - const coords0 = mat.mul( p0.sub( P ) ).normalize().toVar(); - const coords1 = mat.mul( p1.sub( P ) ).normalize().toVar(); - const coords2 = mat.mul( p2.sub( P ) ).normalize().toVar(); - const coords3 = mat.mul( p3.sub( P ) ).normalize().toVar(); + const geometry = new BufferGeometry(); - // calculate vector form factor - const vectorFormFactor = vec3( 0 ).toVar(); - vectorFormFactor.addAssign( LTC_EdgeVectorFormFactor( { v1: coords0, v2: coords1 } ) ); - vectorFormFactor.addAssign( LTC_EdgeVectorFormFactor( { v1: coords1, v2: coords2 } ) ); - vectorFormFactor.addAssign( LTC_EdgeVectorFormFactor( { v1: coords2, v2: coords3 } ) ); - vectorFormFactor.addAssign( LTC_EdgeVectorFormFactor( { v1: coords3, v2: coords0 } ) ); + const vertices = []; + const colors = []; - // adjust for horizon clipping - result.assign( vec3( LTC_ClippedSphereFormFactor( { f: vectorFormFactor } ) ) ); + const color1 = new Color( 0, 0, 1 ); + const color2 = new Color( 0, 1, 0 ); - } ); + for ( let i = 0; i < bones.length; i ++ ) { - return result; + const bone = bones[ i ]; -} ).setLayout( { - name: 'LTC_Evaluate', - type: 'vec3', - inputs: [ - { name: 'N', type: 'vec3' }, - { name: 'V', type: 'vec3' }, - { name: 'P', type: 'vec3' }, - { name: 'mInv', type: 'mat3' }, - { name: 'p0', type: 'vec3' }, - { name: 'p1', type: 'vec3' }, - { name: 'p2', type: 'vec3' }, - { name: 'p3', type: 'vec3' } - ] -} ); + if ( bone.parent && bone.parent.isBone ) { -// Mipped Bicubic Texture Filtering by N8 -// https://www.shadertoy.com/view/Dl2SDW + vertices.push( 0, 0, 0 ); + vertices.push( 0, 0, 0 ); + colors.push( color1.r, color1.g, color1.b ); + colors.push( color2.r, color2.g, color2.b ); -const bC = 1.0 / 6.0; + } -const w0 = ( a ) => mul( bC, mul( a, mul( a, a.negate().add( 3.0 ) ).sub( 3.0 ) ).add( 1.0 ) ); + } -const w1 = ( a ) => mul( bC, mul( a, mul( a, mul( 3.0, a ).sub( 6.0 ) ) ).add( 4.0 ) ); + geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); -const w2 = ( a ) => mul( bC, mul( a, mul( a, mul( - 3.0, a ).add( 3.0 ) ).add( 3.0 ) ).add( 1.0 ) ); + const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } ); -const w3 = ( a ) => mul( bC, pow( a, 3 ) ); + super( geometry, material ); -const g0 = ( a ) => w0( a ).add( w1( a ) ); + this.isSkeletonHelper = true; -const g1 = ( a ) => w2( a ).add( w3( a ) ); + this.type = 'SkeletonHelper'; -// h0 and h1 are the two offset functions -const h0 = ( a ) => add( - 1.0, w1( a ).div( w0( a ).add( w1( a ) ) ) ); + this.root = object; + this.bones = bones; -const h1 = ( a ) => add( 1.0, w3( a ).div( w2( a ).add( w3( a ) ) ) ); + this.matrix = object.matrixWorld; + this.matrixAutoUpdate = false; -const bicubic = ( textureNode, texelSize, lod ) => { + } - const uv = textureNode.uvNode; - const uvScaled = mul( uv, texelSize.zw ).add( 0.5 ); + updateMatrixWorld( force ) { - const iuv = floor( uvScaled ); - const fuv = fract( uvScaled ); + const bones = this.bones; - const g0x = g0( fuv.x ); - const g1x = g1( fuv.x ); - const h0x = h0( fuv.x ); - const h1x = h1( fuv.x ); - const h0y = h0( fuv.y ); - const h1y = h1( fuv.y ); + const geometry = this.geometry; + const position = geometry.getAttribute( 'position' ); - const p0 = vec2( iuv.x.add( h0x ), iuv.y.add( h0y ) ).sub( 0.5 ).mul( texelSize.xy ); - const p1 = vec2( iuv.x.add( h1x ), iuv.y.add( h0y ) ).sub( 0.5 ).mul( texelSize.xy ); - const p2 = vec2( iuv.x.add( h0x ), iuv.y.add( h1y ) ).sub( 0.5 ).mul( texelSize.xy ); - const p3 = vec2( iuv.x.add( h1x ), iuv.y.add( h1y ) ).sub( 0.5 ).mul( texelSize.xy ); + _matrixWorldInv.copy( this.root.matrixWorld ).invert(); - const a = g0( fuv.y ).mul( add( g0x.mul( textureNode.uv( p0 ).level( lod ) ), g1x.mul( textureNode.uv( p1 ).level( lod ) ) ) ); - const b = g1( fuv.y ).mul( add( g0x.mul( textureNode.uv( p2 ).level( lod ) ), g1x.mul( textureNode.uv( p3 ).level( lod ) ) ) ); + for ( let i = 0, j = 0; i < bones.length; i ++ ) { - return a.add( b ); + const bone = bones[ i ]; -}; + if ( bone.parent && bone.parent.isBone ) { -const textureBicubic = /*@__PURE__*/ Fn( ( [ textureNode, lodNode = float( 3 ) ] ) => { + _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld ); + _vector$2.setFromMatrixPosition( _boneMatrix ); + position.setXYZ( j, _vector$2.x, _vector$2.y, _vector$2.z ); - const fLodSize = vec2( textureNode.size( int( lodNode ) ) ); - const cLodSize = vec2( textureNode.size( int( lodNode.add( 1.0 ) ) ) ); - const fLodSizeInv = div( 1.0, fLodSize ); - const cLodSizeInv = div( 1.0, cLodSize ); - const fSample = bicubic( textureNode, vec4( fLodSizeInv, fLodSize ), floor( lodNode ) ); - const cSample = bicubic( textureNode, vec4( cLodSizeInv, cLodSize ), ceil( lodNode ) ); + _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld ); + _vector$2.setFromMatrixPosition( _boneMatrix ); + position.setXYZ( j + 1, _vector$2.x, _vector$2.y, _vector$2.z ); - return fract( lodNode ).mix( fSample, cSample ); + j += 2; -} ); + } -// -// Transmission -// + } -const getVolumeTransmissionRay = /*@__PURE__*/ Fn( ( [ n, v, thickness, ior, modelMatrix ] ) => { + geometry.getAttribute( 'position' ).needsUpdate = true; - // Direction of refracted light. - const refractionVector = vec3( refract( v.negate(), normalize( n ), div( 1.0, ior ) ) ); + super.updateMatrixWorld( force ); - // Compute rotation-independant scaling of the model matrix. - const modelScale = vec3( - length( modelMatrix[ 0 ].xyz ), - length( modelMatrix[ 1 ].xyz ), - length( modelMatrix[ 2 ].xyz ) - ); + } - // The thickness is specified in local space. - return normalize( refractionVector ).mul( thickness.mul( modelScale ) ); + dispose() { -} ).setLayout( { - name: 'getVolumeTransmissionRay', - type: 'vec3', - inputs: [ - { name: 'n', type: 'vec3' }, - { name: 'v', type: 'vec3' }, - { name: 'thickness', type: 'float' }, - { name: 'ior', type: 'float' }, - { name: 'modelMatrix', type: 'mat4' } - ] -} ); + this.geometry.dispose(); + this.material.dispose(); -const applyIorToRoughness = /*@__PURE__*/ Fn( ( [ roughness, ior ] ) => { + } - // Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and - // an IOR of 1.5 results in the default amount of microfacet refraction. - return roughness.mul( clamp( ior.mul( 2.0 ).sub( 2.0 ), 0.0, 1.0 ) ); +} -} ).setLayout( { - name: 'applyIorToRoughness', - type: 'float', - inputs: [ - { name: 'roughness', type: 'float' }, - { name: 'ior', type: 'float' } - ] -} ); -const singleViewportMipTexture = /*@__PURE__*/ viewportMipTexture(); +function getBoneList( object ) { -const getTransmissionSample = /*@__PURE__*/ Fn( ( [ fragCoord, roughness, ior ] ) => { + const boneList = []; - const transmissionSample = singleViewportMipTexture.uv( fragCoord ); - //const transmissionSample = viewportMipTexture( fragCoord ); + if ( object.isBone === true ) { - const lod = log2( float( viewportResolution.x ) ).mul( applyIorToRoughness( roughness, ior ) ); + boneList.push( object ); - return textureBicubic( transmissionSample, lod ); + } -} ); + for ( let i = 0; i < object.children.length; i ++ ) { -const volumeAttenuation = /*@__PURE__*/ Fn( ( [ transmissionDistance, attenuationColor, attenuationDistance ] ) => { + boneList.push.apply( boneList, getBoneList( object.children[ i ] ) ); - If( attenuationDistance.notEqual( 0 ), () => { + } - // Compute light attenuation using Beer's law. - const attenuationCoefficient = log( attenuationColor ).negate().div( attenuationDistance ); - const transmittance = exp( attenuationCoefficient.negate().mul( transmissionDistance ) ); + return boneList; - return transmittance; +} - } ); +class PointLightHelper extends Mesh { - // Attenuation distance is +∞, i.e. the transmitted color is not attenuated at all. - return vec3( 1.0 ); + constructor( light, sphereSize, color ) { -} ).setLayout( { - name: 'volumeAttenuation', - type: 'vec3', - inputs: [ - { name: 'transmissionDistance', type: 'float' }, - { name: 'attenuationColor', type: 'vec3' }, - { name: 'attenuationDistance', type: 'float' } - ] -} ); + const geometry = new SphereGeometry( sphereSize, 4, 2 ); + const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } ); -const getIBLVolumeRefraction = /*@__PURE__*/ Fn( ( [ n, v, roughness, diffuseColor, specularColor, specularF90, position, modelMatrix, viewMatrix, projMatrix, ior, thickness, attenuationColor, attenuationDistance, dispersion ] ) => { + super( geometry, material ); - let transmittedLight, transmittance; + this.light = light; - if ( dispersion ) { + this.color = color; - transmittedLight = vec4().toVar(); - transmittance = vec3().toVar(); + this.type = 'PointLightHelper'; - const halfSpread = ior.sub( 1.0 ).mul( dispersion.mul( 0.025 ) ); - const iors = vec3( ior.sub( halfSpread ), ior, ior.add( halfSpread ) ); + this.matrix = this.light.matrixWorld; + this.matrixAutoUpdate = false; - Loop( { start: 0, end: 3 }, ( { i } ) => { + this.update(); - const ior = iors.element( i ); - const transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); - const refractedRayExit = position.add( transmissionRay ); + /* + // TODO: delete this comment? + const distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 ); + const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } ); - // Project refracted vector on the framebuffer, while mapping to normalized device coordinates. - const ndcPos = projMatrix.mul( viewMatrix.mul( vec4( refractedRayExit, 1.0 ) ) ); - const refractionCoords = vec2( ndcPos.xy.div( ndcPos.w ) ).toVar(); - refractionCoords.addAssign( 1.0 ); - refractionCoords.divAssign( 2.0 ); - refractionCoords.assign( vec2( refractionCoords.x, refractionCoords.y.oneMinus() ) ); // webgpu + this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial ); + this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial ); - // Sample framebuffer to get pixel the refracted ray hits. - const transmissionSample = getTransmissionSample( refractionCoords, roughness, ior ); + const d = light.distance; - transmittedLight.element( i ).assign( transmissionSample.element( i ) ); - transmittedLight.a.addAssign( transmissionSample.a ); + if ( d === 0.0 ) { - transmittance.element( i ).assign( diffuseColor.element( i ).mul( volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ).element( i ) ) ); + this.lightDistance.visible = false; - } ); + } else { - transmittedLight.a.divAssign( 3.0 ); + this.lightDistance.scale.set( d, d, d ); - } else { + } - const transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); - const refractedRayExit = position.add( transmissionRay ); + this.add( this.lightDistance ); + */ - // Project refracted vector on the framebuffer, while mapping to normalized device coordinates. - const ndcPos = projMatrix.mul( viewMatrix.mul( vec4( refractedRayExit, 1.0 ) ) ); - const refractionCoords = vec2( ndcPos.xy.div( ndcPos.w ) ).toVar(); - refractionCoords.addAssign( 1.0 ); - refractionCoords.divAssign( 2.0 ); - refractionCoords.assign( vec2( refractionCoords.x, refractionCoords.y.oneMinus() ) ); // webgpu + } - // Sample framebuffer to get pixel the refracted ray hits. - transmittedLight = getTransmissionSample( refractionCoords, roughness, ior ); - transmittance = diffuseColor.mul( volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ) ); + dispose() { + + this.geometry.dispose(); + this.material.dispose(); } - const attenuatedColor = transmittance.rgb.mul( transmittedLight.rgb ); - const dotNV = n.dot( v ).clamp(); + update() { - // Get the specular component. - const F = vec3( EnvironmentBRDF( { // n, v, specularColor, specularF90, roughness - dotNV, - specularColor, - specularF90, - roughness - } ) ); + this.light.updateWorldMatrix( true, false ); - // As less light is transmitted, the opacity should be increased. This simple approximation does a decent job - // of modulating a CSS background, and has no effect when the buffer is opaque, due to a solid object or clear color. - const transmittanceFactor = transmittance.r.add( transmittance.g, transmittance.b ).div( 3.0 ); + if ( this.color !== undefined ) { - return vec4( F.oneMinus().mul( attenuatedColor ), transmittedLight.a.oneMinus().mul( transmittanceFactor ).oneMinus() ); + this.material.color.set( this.color ); -} ); + } else { -// -// Iridescence -// + this.material.color.copy( this.light.color ); -// XYZ to linear-sRGB color space -const XYZ_TO_REC709 = /*@__PURE__*/ mat3( - 3.2404542, - 0.9692660, 0.0556434, - - 1.5371385, 1.8760108, - 0.2040259, - - 0.4985314, 0.0415560, 1.0572252 -); + } -// Assume air interface for top -// Note: We don't handle the case fresnel0 == 1 -const Fresnel0ToIor = ( fresnel0 ) => { + /* + const d = this.light.distance; - const sqrtF0 = fresnel0.sqrt(); - return vec3( 1.0 ).add( sqrtF0 ).div( vec3( 1.0 ).sub( sqrtF0 ) ); + if ( d === 0.0 ) { -}; + this.lightDistance.visible = false; -// ior is a value between 1.0 and 3.0. 1.0 is air interface -const IorToFresnel0 = ( transmittedIor, incidentIor ) => { + } else { - return transmittedIor.sub( incidentIor ).div( transmittedIor.add( incidentIor ) ).pow2(); + this.lightDistance.visible = true; + this.lightDistance.scale.set( d, d, d ); -}; + } + */ -// Fresnel equations for dielectric/dielectric interfaces. -// Ref: https://belcour.github.io/blog/research/2017/05/01/brdf-thin-film.html -// Evaluation XYZ sensitivity curves in Fourier space -const evalSensitivity = ( OPD, shift ) => { + } - const phase = OPD.mul( 2.0 * Math.PI * 1.0e-9 ); - const val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 ); - const pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 ); - const VAR = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 ); +} - const x = float( 9.7470e-14 * Math.sqrt( 2.0 * Math.PI * 4.5282e+09 ) ).mul( phase.mul( 2.2399e+06 ).add( shift.x ).cos() ).mul( phase.pow2().mul( - 4.5282e+09 ).exp() ); +const _vector$1 = /*@__PURE__*/ new Vector3(); +const _color1 = /*@__PURE__*/ new Color(); +const _color2 = /*@__PURE__*/ new Color(); - let xyz = val.mul( VAR.mul( 2.0 * Math.PI ).sqrt() ).mul( pos.mul( phase ).add( shift ).cos() ).mul( phase.pow2().negate().mul( VAR ).exp() ); - xyz = vec3( xyz.x.add( x ), xyz.y, xyz.z ).div( 1.0685e-7 ); +class HemisphereLightHelper extends Object3D { - const rgb = XYZ_TO_REC709.mul( xyz ); + constructor( light, size, color ) { - return rgb; + super(); -}; + this.light = light; -const evalIridescence = /*@__PURE__*/ Fn( ( { outsideIOR, eta2, cosTheta1, thinFilmThickness, baseF0 } ) => { + this.matrix = light.matrixWorld; + this.matrixAutoUpdate = false; - // Force iridescenceIOR -> outsideIOR when thinFilmThickness -> 0.0 - const iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) ); - // Evaluate the cosTheta on the base layer (Snell law) - const sinTheta2Sq = outsideIOR.div( iridescenceIOR ).pow2().mul( float( 1 ).sub( cosTheta1.pow2() ) ); + this.color = color; - // Handle TIR: - const cosTheta2Sq = float( 1 ).sub( sinTheta2Sq ); - /*if ( cosTheta2Sq < 0.0 ) { + this.type = 'HemisphereLightHelper'; - return vec3( 1.0 ); + const geometry = new OctahedronGeometry( size ); + geometry.rotateY( Math.PI * 0.5 ); - }*/ + this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } ); + if ( this.color === undefined ) this.material.vertexColors = true; - const cosTheta2 = cosTheta2Sq.sqrt(); + const position = geometry.getAttribute( 'position' ); + const colors = new Float32Array( position.count * 3 ); - // First interface - const R0 = IorToFresnel0( iridescenceIOR, outsideIOR ); - const R12 = F_Schlick( { f0: R0, f90: 1.0, dotVH: cosTheta1 } ); - //const R21 = R12; - const T121 = R12.oneMinus(); - const phi12 = iridescenceIOR.lessThan( outsideIOR ).select( Math.PI, 0.0 ); - const phi21 = float( Math.PI ).sub( phi12 ); - - // Second interface - const baseIOR = Fresnel0ToIor( baseF0.clamp( 0.0, 0.9999 ) ); // guard against 1.0 - const R1 = IorToFresnel0( baseIOR, iridescenceIOR.toVec3() ); - const R23 = F_Schlick( { f0: R1, f90: 1.0, dotVH: cosTheta2 } ); - const phi23 = vec3( - baseIOR.x.lessThan( iridescenceIOR ).select( Math.PI, 0.0 ), - baseIOR.y.lessThan( iridescenceIOR ).select( Math.PI, 0.0 ), - baseIOR.z.lessThan( iridescenceIOR ).select( Math.PI, 0.0 ) - ); - - // Phase shift - const OPD = iridescenceIOR.mul( thinFilmThickness, cosTheta2, 2.0 ); - const phi = vec3( phi21 ).add( phi23 ); - - // Compound terms - const R123 = R12.mul( R23 ).clamp( 1e-5, 0.9999 ); - const r123 = R123.sqrt(); - const Rs = T121.pow2().mul( R23 ).div( vec3( 1.0 ).sub( R123 ) ); - - // Reflectance term for m = 0 (DC term amplitude) - const C0 = R12.add( Rs ); - let I = C0; + geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) ); - // Reflectance term for m > 0 (pairs of diracs) - let Cm = Rs.sub( T121 ); - for ( let m = 1; m <= 2; ++ m ) { + this.add( new Mesh( geometry, this.material ) ); - Cm = Cm.mul( r123 ); - const Sm = evalSensitivity( float( m ).mul( OPD ), float( m ).mul( phi ) ).mul( 2.0 ); - I = I.add( Cm.mul( Sm ) ); + this.update(); } - // Since out of gamut colors might be produced, negative color values are clamped to 0. - return I.max( vec3( 0.0 ) ); + dispose() { -} ).setLayout( { - name: 'evalIridescence', - type: 'vec3', - inputs: [ - { name: 'outsideIOR', type: 'float' }, - { name: 'eta2', type: 'float' }, - { name: 'cosTheta1', type: 'float' }, - { name: 'thinFilmThickness', type: 'float' }, - { name: 'baseF0', type: 'vec3' } - ] -} ); + this.children[ 0 ].geometry.dispose(); + this.children[ 0 ].material.dispose(); -// -// Sheen -// + } -// This is a curve-fit approxmation to the "Charlie sheen" BRDF integrated over the hemisphere from -// Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF". The analysis can be found -// in the Sheen section of https://drive.google.com/file/d/1T0D1VSyR4AllqIJTQAraEIzjlb5h4FKH/view?usp=sharing -const IBLSheenBRDF = /*@__PURE__*/ Fn( ( { normal, viewDir, roughness } ) => { + update() { - const dotNV = normal.dot( viewDir ).saturate(); + const mesh = this.children[ 0 ]; - const r2 = roughness.pow2(); + if ( this.color !== undefined ) { - const a = select( - roughness.lessThan( 0.25 ), - float( - 339.2 ).mul( r2 ).add( float( 161.4 ).mul( roughness ) ).sub( 25.9 ), - float( - 8.48 ).mul( r2 ).add( float( 14.3 ).mul( roughness ) ).sub( 9.95 ) - ); + this.material.color.set( this.color ); - const b = select( - roughness.lessThan( 0.25 ), - float( 44.0 ).mul( r2 ).sub( float( 23.7 ).mul( roughness ) ).add( 3.26 ), - float( 1.97 ).mul( r2 ).sub( float( 3.27 ).mul( roughness ) ).add( 0.72 ) - ); + } else { - const DG = select( roughness.lessThan( 0.25 ), 0.0, float( 0.1 ).mul( roughness ).sub( 0.025 ) ).add( a.mul( dotNV ).add( b ).exp() ); + const colors = mesh.geometry.getAttribute( 'color' ); - return DG.mul( 1.0 / Math.PI ).saturate(); + _color1.copy( this.light.color ); + _color2.copy( this.light.groundColor ); -} ); + for ( let i = 0, l = colors.count; i < l; i ++ ) { -const clearcoatF0 = vec3( 0.04 ); -const clearcoatF90 = float( 1 ); + const color = ( i < ( l / 2 ) ) ? _color1 : _color2; -// + colors.setXYZ( i, color.r, color.g, color.b ); -class PhysicalLightingModel extends LightingModel { + } - constructor( clearcoat = false, sheen = false, iridescence = false, anisotropy = false, transmission = false, dispersion = false ) { + colors.needsUpdate = true; - super(); + } - this.clearcoat = clearcoat; - this.sheen = sheen; - this.iridescence = iridescence; - this.anisotropy = anisotropy; - this.transmission = transmission; - this.dispersion = dispersion; + this.light.updateWorldMatrix( true, false ); - this.clearcoatRadiance = null; - this.clearcoatSpecularDirect = null; - this.clearcoatSpecularIndirect = null; - this.sheenSpecularDirect = null; - this.sheenSpecularIndirect = null; - this.iridescenceFresnel = null; - this.iridescenceF0 = null; + mesh.lookAt( _vector$1.setFromMatrixPosition( this.light.matrixWorld ).negate() ); } - start( context ) { - - if ( this.clearcoat === true ) { +} - this.clearcoatRadiance = vec3().toVar( 'clearcoatRadiance' ); - this.clearcoatSpecularDirect = vec3().toVar( 'clearcoatSpecularDirect' ); - this.clearcoatSpecularIndirect = vec3().toVar( 'clearcoatSpecularIndirect' ); +class GridHelper extends LineSegments { - } + constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) { - if ( this.sheen === true ) { + color1 = new Color( color1 ); + color2 = new Color( color2 ); - this.sheenSpecularDirect = vec3().toVar( 'sheenSpecularDirect' ); - this.sheenSpecularIndirect = vec3().toVar( 'sheenSpecularIndirect' ); + const center = divisions / 2; + const step = size / divisions; + const halfSize = size / 2; - } + const vertices = [], colors = []; - if ( this.iridescence === true ) { + for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) { - const dotNVi = transformedNormalView.dot( positionViewDirection ).clamp(); + vertices.push( - halfSize, 0, k, halfSize, 0, k ); + vertices.push( k, 0, - halfSize, k, 0, halfSize ); - this.iridescenceFresnel = evalIridescence( { - outsideIOR: float( 1.0 ), - eta2: iridescenceIOR, - cosTheta1: dotNVi, - thinFilmThickness: iridescenceThickness, - baseF0: specularColor - } ); + const color = i === center ? color1 : color2; - this.iridescenceF0 = Schlick_to_F0( { f: this.iridescenceFresnel, f90: 1.0, dotVH: dotNVi } ); + color.toArray( colors, j ); j += 3; + color.toArray( colors, j ); j += 3; + color.toArray( colors, j ); j += 3; + color.toArray( colors, j ); j += 3; } - if ( this.transmission === true ) { + const geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); - const position = positionWorld; - const v = cameraPosition.sub( positionWorld ).normalize(); // TODO: Create Node for this, same issue in MaterialX - const n = transformedNormalWorld; + const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); - context.backdrop = getIBLVolumeRefraction( - n, - v, - roughness, - diffuseColor, - specularColor, - specularF90, // specularF90 - position, // positionWorld - modelWorldMatrix, // modelMatrix - cameraViewMatrix, // viewMatrix - cameraProjectionMatrix, // projMatrix - ior, - thickness, - attenuationColor, - attenuationDistance, - this.dispersion ? dispersion : null - ); + super( geometry, material ); - context.backdropAlpha = transmission; + this.type = 'GridHelper'; - diffuseColor.a.mulAssign( mix( 1, context.backdrop.a, transmission ) ); + } - } + dispose() { + + this.geometry.dispose(); + this.material.dispose(); } - // Fdez-Agüera's "Multiple-Scattering Microfacet Model for Real-Time Image Based Lighting" - // Approximates multiscattering in order to preserve energy. - // http://www.jcgt.org/published/0008/01/03/ +} - computeMultiscattering( singleScatter, multiScatter, specularF90 ) { +class PolarGridHelper extends LineSegments { - const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV + constructor( radius = 10, sectors = 16, rings = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888 ) { - const fab = DFGApprox( { roughness, dotNV } ); + color1 = new Color( color1 ); + color2 = new Color( color2 ); - const Fr = this.iridescenceF0 ? iridescence.mix( specularColor, this.iridescenceF0 ) : specularColor; + const vertices = []; + const colors = []; - const FssEss = Fr.mul( fab.x ).add( specularF90.mul( fab.y ) ); + // create the sectors - const Ess = fab.x.add( fab.y ); - const Ems = Ess.oneMinus(); + if ( sectors > 1 ) { - const Favg = specularColor.add( specularColor.oneMinus().mul( 0.047619 ) ); // 1/21 - const Fms = FssEss.mul( Favg ).div( Ems.mul( Favg ).oneMinus() ); + for ( let i = 0; i < sectors; i ++ ) { - singleScatter.addAssign( FssEss ); - multiScatter.addAssign( Fms.mul( Ems ) ); + const v = ( i / sectors ) * ( Math.PI * 2 ); - } + const x = Math.sin( v ) * radius; + const z = Math.cos( v ) * radius; - direct( { lightDirection, lightColor, reflectedLight } ) { + vertices.push( 0, 0, 0 ); + vertices.push( x, 0, z ); - const dotNL = transformedNormalView.dot( lightDirection ).clamp(); - const irradiance = dotNL.mul( lightColor ); + const color = ( i & 1 ) ? color1 : color2; - if ( this.sheen === true ) { + colors.push( color.r, color.g, color.b ); + colors.push( color.r, color.g, color.b ); - this.sheenSpecularDirect.addAssign( irradiance.mul( BRDF_Sheen( { lightDirection } ) ) ); + } } - if ( this.clearcoat === true ) { + // create the rings - const dotNLcc = transformedClearcoatNormalView.dot( lightDirection ).clamp(); - const ccIrradiance = dotNLcc.mul( lightColor ); + for ( let i = 0; i < rings; i ++ ) { - this.clearcoatSpecularDirect.addAssign( ccIrradiance.mul( BRDF_GGX( { lightDirection, f0: clearcoatF0, f90: clearcoatF90, roughness: clearcoatRoughness, normalView: transformedClearcoatNormalView } ) ) ); + const color = ( i & 1 ) ? color1 : color2; - } + const r = radius - ( radius / rings * i ); - reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) ); + for ( let j = 0; j < divisions; j ++ ) { - reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_GGX( { lightDirection, f0: specularColor, f90: 1, roughness, iridescence: this.iridescence, f: this.iridescenceFresnel, USE_IRIDESCENCE: this.iridescence, USE_ANISOTROPY: this.anisotropy } ) ) ); + // first vertex - } + let v = ( j / divisions ) * ( Math.PI * 2 ); - directRectArea( { lightColor, lightPosition, halfWidth, halfHeight, reflectedLight, ltc_1, ltc_2 } ) { + let x = Math.sin( v ) * r; + let z = Math.cos( v ) * r; - const p0 = lightPosition.add( halfWidth ).sub( halfHeight ); // counterclockwise; light shines in local neg z direction - const p1 = lightPosition.sub( halfWidth ).sub( halfHeight ); - const p2 = lightPosition.sub( halfWidth ).add( halfHeight ); - const p3 = lightPosition.add( halfWidth ).add( halfHeight ); + vertices.push( x, 0, z ); + colors.push( color.r, color.g, color.b ); - const N = transformedNormalView; - const V = positionViewDirection; - const P = positionView.toVar(); + // second vertex - const uv = LTC_Uv( { N, V, roughness } ); + v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 ); - const t1 = ltc_1.uv( uv ).toVar(); - const t2 = ltc_2.uv( uv ).toVar(); + x = Math.sin( v ) * r; + z = Math.cos( v ) * r; - const mInv = mat3( - vec3( t1.x, 0, t1.y ), - vec3( 0, 1, 0 ), - vec3( t1.z, 0, t1.w ) - ).toVar(); + vertices.push( x, 0, z ); + colors.push( color.r, color.g, color.b ); - // LTC Fresnel Approximation by Stephen Hill - // http://blog.selfshadow.com/publications/s2016-advances/s2016_ltc_fresnel.pdf - const fresnel = specularColor.mul( t2.x ).add( specularColor.oneMinus().mul( t2.y ) ).toVar(); + } - reflectedLight.directSpecular.addAssign( lightColor.mul( fresnel ).mul( LTC_Evaluate( { N, V, P, mInv, p0, p1, p2, p3 } ) ) ); + } - reflectedLight.directDiffuse.addAssign( lightColor.mul( diffuseColor ).mul( LTC_Evaluate( { N, V, P, mInv: mat3( 1, 0, 0, 0, 1, 0, 0, 0, 1 ), p0, p1, p2, p3 } ) ) ); + const geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); - } + const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); - indirect( context, stack, builder ) { + super( geometry, material ); - this.indirectDiffuse( context, stack, builder ); - this.indirectSpecular( context, stack, builder ); - this.ambientOcclusion( context, stack, builder ); + this.type = 'PolarGridHelper'; } - indirectDiffuse( { irradiance, reflectedLight } ) { + dispose() { - reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) ); + this.geometry.dispose(); + this.material.dispose(); } - indirectSpecular( { radiance, iblIrradiance, reflectedLight } ) { +} - if ( this.sheen === true ) { +const _v1 = /*@__PURE__*/ new Vector3(); +const _v2 = /*@__PURE__*/ new Vector3(); +const _v3 = /*@__PURE__*/ new Vector3(); - this.sheenSpecularIndirect.addAssign( iblIrradiance.mul( - sheen, - IBLSheenBRDF( { - normal: transformedNormalView, - viewDir: positionViewDirection, - roughness: sheenRoughness - } ) - ) ); +class DirectionalLightHelper extends Object3D { - } + constructor( light, size, color ) { - if ( this.clearcoat === true ) { + super(); - const dotNVcc = transformedClearcoatNormalView.dot( positionViewDirection ).clamp(); + this.light = light; - const clearcoatEnv = EnvironmentBRDF( { - dotNV: dotNVcc, - specularColor: clearcoatF0, - specularF90: clearcoatF90, - roughness: clearcoatRoughness - } ); + this.matrix = light.matrixWorld; + this.matrixAutoUpdate = false; - this.clearcoatSpecularIndirect.addAssign( this.clearcoatRadiance.mul( clearcoatEnv ) ); + this.color = color; - } + this.type = 'DirectionalLightHelper'; - // Both indirect specular and indirect diffuse light accumulate here + if ( size === undefined ) size = 1; - const singleScattering = vec3().toVar( 'singleScattering' ); - const multiScattering = vec3().toVar( 'multiScattering' ); - const cosineWeightedIrradiance = iblIrradiance.mul( 1 / Math.PI ); + let geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new Float32BufferAttribute( [ + - size, size, 0, + size, size, 0, + size, - size, 0, + - size, - size, 0, + - size, size, 0 + ], 3 ) ); - this.computeMultiscattering( singleScattering, multiScattering, specularF90 ); + const material = new LineBasicMaterial( { fog: false, toneMapped: false } ); - const totalScattering = singleScattering.add( multiScattering ); + this.lightPlane = new Line( geometry, material ); + this.add( this.lightPlane ); - const diffuse = diffuseColor.mul( totalScattering.r.max( totalScattering.g ).max( totalScattering.b ).oneMinus() ); + geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) ); - reflectedLight.indirectSpecular.addAssign( radiance.mul( singleScattering ) ); - reflectedLight.indirectSpecular.addAssign( multiScattering.mul( cosineWeightedIrradiance ) ); + this.targetLine = new Line( geometry, material ); + this.add( this.targetLine ); - reflectedLight.indirectDiffuse.addAssign( diffuse.mul( cosineWeightedIrradiance ) ); + this.update(); } - ambientOcclusion( { ambientOcclusion, reflectedLight } ) { + dispose() { - const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV + this.lightPlane.geometry.dispose(); + this.lightPlane.material.dispose(); + this.targetLine.geometry.dispose(); + this.targetLine.material.dispose(); - const aoNV = dotNV.add( ambientOcclusion ); - const aoExp = roughness.mul( - 16.0 ).oneMinus().negate().exp2(); + } - const aoNode = ambientOcclusion.sub( aoNV.pow( aoExp ).oneMinus() ).clamp(); + update() { - if ( this.clearcoat === true ) { + this.light.updateWorldMatrix( true, false ); + this.light.target.updateWorldMatrix( true, false ); - this.clearcoatSpecularIndirect.mulAssign( ambientOcclusion ); + _v1.setFromMatrixPosition( this.light.matrixWorld ); + _v2.setFromMatrixPosition( this.light.target.matrixWorld ); + _v3.subVectors( _v2, _v1 ); - } + this.lightPlane.lookAt( _v2 ); - if ( this.sheen === true ) { + if ( this.color !== undefined ) { - this.sheenSpecularIndirect.mulAssign( ambientOcclusion ); + this.lightPlane.material.color.set( this.color ); + this.targetLine.material.color.set( this.color ); + + } else { + + this.lightPlane.material.color.copy( this.light.color ); + this.targetLine.material.color.copy( this.light.color ); } - reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion ); - reflectedLight.indirectSpecular.mulAssign( aoNode ); + this.targetLine.lookAt( _v2 ); + this.targetLine.scale.z = _v3.length(); } - finish( context ) { +} - const { outgoingLight } = context; +const _vector = /*@__PURE__*/ new Vector3(); +const _camera$1 = /*@__PURE__*/ new Camera(); - if ( this.clearcoat === true ) { +/** + * - shows frustum, line of sight and up of the camera + * - suitable for fast updates + * - based on frustum visualization in lightgl.js shadowmap example + * https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html + */ - const dotNVcc = transformedClearcoatNormalView.dot( positionViewDirection ).clamp(); +class CameraHelper extends LineSegments { - const Fcc = F_Schlick( { - dotVH: dotNVcc, - f0: clearcoatF0, - f90: clearcoatF90 - } ); + constructor( camera ) { - const clearcoatLight = outgoingLight.mul( clearcoat.mul( Fcc ).oneMinus() ).add( this.clearcoatSpecularDirect.add( this.clearcoatSpecularIndirect ).mul( clearcoat ) ); + const geometry = new BufferGeometry(); + const material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } ); - outgoingLight.assign( clearcoatLight ); + const vertices = []; + const colors = []; - } + const pointMap = {}; - if ( this.sheen === true ) { + // near - const sheenEnergyComp = sheen.r.max( sheen.g ).max( sheen.b ).mul( 0.157 ).oneMinus(); - const sheenLight = outgoingLight.mul( sheenEnergyComp ).add( this.sheenSpecularDirect, this.sheenSpecularIndirect ); + addLine( 'n1', 'n2' ); + addLine( 'n2', 'n4' ); + addLine( 'n4', 'n3' ); + addLine( 'n3', 'n1' ); - outgoingLight.assign( sheenLight ); + // far - } + addLine( 'f1', 'f2' ); + addLine( 'f2', 'f4' ); + addLine( 'f4', 'f3' ); + addLine( 'f3', 'f1' ); - } + // sides -} + addLine( 'n1', 'f1' ); + addLine( 'n2', 'f2' ); + addLine( 'n3', 'f3' ); + addLine( 'n4', 'f4' ); -// These defines must match with PMREMGenerator + // cone -const cubeUV_r0 = /*@__PURE__*/ float( 1.0 ); -const cubeUV_m0 = /*@__PURE__*/ float( - 2.0 ); -const cubeUV_r1 = /*@__PURE__*/ float( 0.8 ); -const cubeUV_m1 = /*@__PURE__*/ float( - 1.0 ); -const cubeUV_r4 = /*@__PURE__*/ float( 0.4 ); -const cubeUV_m4 = /*@__PURE__*/ float( 2.0 ); -const cubeUV_r5 = /*@__PURE__*/ float( 0.305 ); -const cubeUV_m5 = /*@__PURE__*/ float( 3.0 ); -const cubeUV_r6 = /*@__PURE__*/ float( 0.21 ); -const cubeUV_m6 = /*@__PURE__*/ float( 4.0 ); + addLine( 'p', 'n1' ); + addLine( 'p', 'n2' ); + addLine( 'p', 'n3' ); + addLine( 'p', 'n4' ); -const cubeUV_minMipLevel = /*@__PURE__*/ float( 4.0 ); -const cubeUV_minTileSize = /*@__PURE__*/ float( 16.0 ); + // up -// These shader functions convert between the UV coordinates of a single face of -// a cubemap, the 0-5 integer index of a cube face, and the direction vector for -// sampling a textureCube (not generally normalized ). + addLine( 'u1', 'u2' ); + addLine( 'u2', 'u3' ); + addLine( 'u3', 'u1' ); -const getFace = /*@__PURE__*/ Fn( ( [ direction ] ) => { + // target - const absDirection = vec3( abs( direction ) ).toVar(); - const face = float( - 1.0 ).toVar(); + addLine( 'c', 't' ); + addLine( 'p', 'c' ); - If( absDirection.x.greaterThan( absDirection.z ), () => { + // cross - If( absDirection.x.greaterThan( absDirection.y ), () => { + addLine( 'cn1', 'cn2' ); + addLine( 'cn3', 'cn4' ); - face.assign( select( direction.x.greaterThan( 0.0 ), 0.0, 3.0 ) ); + addLine( 'cf1', 'cf2' ); + addLine( 'cf3', 'cf4' ); - } ).Else( () => { + function addLine( a, b ) { - face.assign( select( direction.y.greaterThan( 0.0 ), 1.0, 4.0 ) ); + addPoint( a ); + addPoint( b ); - } ); + } - } ).Else( () => { + function addPoint( id ) { - If( absDirection.z.greaterThan( absDirection.y ), () => { + vertices.push( 0, 0, 0 ); + colors.push( 0, 0, 0 ); - face.assign( select( direction.z.greaterThan( 0.0 ), 2.0, 5.0 ) ); + if ( pointMap[ id ] === undefined ) { - } ).Else( () => { + pointMap[ id ] = []; - face.assign( select( direction.y.greaterThan( 0.0 ), 1.0, 4.0 ) ); + } - } ); + pointMap[ id ].push( ( vertices.length / 3 ) - 1 ); - } ); + } - return face; + geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); -} ).setLayout( { - name: 'getFace', - type: 'float', - inputs: [ - { name: 'direction', type: 'vec3' } - ] -} ); + super( geometry, material ); -// RH coordinate system; PMREM face-indexing convention -const getUV = /*@__PURE__*/ Fn( ( [ direction, face ] ) => { + this.type = 'CameraHelper'; - const uv = vec2().toVar(); + this.camera = camera; + if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix(); - If( face.equal( 0.0 ), () => { + this.matrix = camera.matrixWorld; + this.matrixAutoUpdate = false; - uv.assign( vec2( direction.z, direction.y ).div( abs( direction.x ) ) ); // pos x + this.pointMap = pointMap; - } ).ElseIf( face.equal( 1.0 ), () => { + this.update(); - uv.assign( vec2( direction.x.negate(), direction.z.negate() ).div( abs( direction.y ) ) ); // pos y + // colors - } ).ElseIf( face.equal( 2.0 ), () => { + const colorFrustum = new Color( 0xffaa00 ); + const colorCone = new Color( 0xff0000 ); + const colorUp = new Color( 0x00aaff ); + const colorTarget = new Color( 0xffffff ); + const colorCross = new Color( 0x333333 ); - uv.assign( vec2( direction.x.negate(), direction.y ).div( abs( direction.z ) ) ); // pos z + this.setColors( colorFrustum, colorCone, colorUp, colorTarget, colorCross ); - } ).ElseIf( face.equal( 3.0 ), () => { + } - uv.assign( vec2( direction.z.negate(), direction.y ).div( abs( direction.x ) ) ); // neg x + setColors( frustum, cone, up, target, cross ) { - } ).ElseIf( face.equal( 4.0 ), () => { + const geometry = this.geometry; - uv.assign( vec2( direction.x.negate(), direction.z ).div( abs( direction.y ) ) ); // neg y + const colorAttribute = geometry.getAttribute( 'color' ); - } ).Else( () => { + // near - uv.assign( vec2( direction.x, direction.y ).div( abs( direction.z ) ) ); // neg z + colorAttribute.setXYZ( 0, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 1, frustum.r, frustum.g, frustum.b ); // n1, n2 + colorAttribute.setXYZ( 2, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 3, frustum.r, frustum.g, frustum.b ); // n2, n4 + colorAttribute.setXYZ( 4, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 5, frustum.r, frustum.g, frustum.b ); // n4, n3 + colorAttribute.setXYZ( 6, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 7, frustum.r, frustum.g, frustum.b ); // n3, n1 - } ); + // far - return mul( 0.5, uv.add( 1.0 ) ); + colorAttribute.setXYZ( 8, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 9, frustum.r, frustum.g, frustum.b ); // f1, f2 + colorAttribute.setXYZ( 10, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 11, frustum.r, frustum.g, frustum.b ); // f2, f4 + colorAttribute.setXYZ( 12, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 13, frustum.r, frustum.g, frustum.b ); // f4, f3 + colorAttribute.setXYZ( 14, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 15, frustum.r, frustum.g, frustum.b ); // f3, f1 -} ).setLayout( { - name: 'getUV', - type: 'vec2', - inputs: [ - { name: 'direction', type: 'vec3' }, - { name: 'face', type: 'float' } - ] -} ); + // sides -const roughnessToMip = /*@__PURE__*/ Fn( ( [ roughness ] ) => { + colorAttribute.setXYZ( 16, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 17, frustum.r, frustum.g, frustum.b ); // n1, f1 + colorAttribute.setXYZ( 18, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 19, frustum.r, frustum.g, frustum.b ); // n2, f2 + colorAttribute.setXYZ( 20, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 21, frustum.r, frustum.g, frustum.b ); // n3, f3 + colorAttribute.setXYZ( 22, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 23, frustum.r, frustum.g, frustum.b ); // n4, f4 - const mip = float( 0.0 ).toVar(); + // cone - If( roughness.greaterThanEqual( cubeUV_r1 ), () => { + colorAttribute.setXYZ( 24, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 25, cone.r, cone.g, cone.b ); // p, n1 + colorAttribute.setXYZ( 26, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 27, cone.r, cone.g, cone.b ); // p, n2 + colorAttribute.setXYZ( 28, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 29, cone.r, cone.g, cone.b ); // p, n3 + colorAttribute.setXYZ( 30, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 31, cone.r, cone.g, cone.b ); // p, n4 - mip.assign( cubeUV_r0.sub( roughness ).mul( cubeUV_m1.sub( cubeUV_m0 ) ).div( cubeUV_r0.sub( cubeUV_r1 ) ).add( cubeUV_m0 ) ); + // up - } ).ElseIf( roughness.greaterThanEqual( cubeUV_r4 ), () => { + colorAttribute.setXYZ( 32, up.r, up.g, up.b ); colorAttribute.setXYZ( 33, up.r, up.g, up.b ); // u1, u2 + colorAttribute.setXYZ( 34, up.r, up.g, up.b ); colorAttribute.setXYZ( 35, up.r, up.g, up.b ); // u2, u3 + colorAttribute.setXYZ( 36, up.r, up.g, up.b ); colorAttribute.setXYZ( 37, up.r, up.g, up.b ); // u3, u1 - mip.assign( cubeUV_r1.sub( roughness ).mul( cubeUV_m4.sub( cubeUV_m1 ) ).div( cubeUV_r1.sub( cubeUV_r4 ) ).add( cubeUV_m1 ) ); + // target - } ).ElseIf( roughness.greaterThanEqual( cubeUV_r5 ), () => { + colorAttribute.setXYZ( 38, target.r, target.g, target.b ); colorAttribute.setXYZ( 39, target.r, target.g, target.b ); // c, t + colorAttribute.setXYZ( 40, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 41, cross.r, cross.g, cross.b ); // p, c - mip.assign( cubeUV_r4.sub( roughness ).mul( cubeUV_m5.sub( cubeUV_m4 ) ).div( cubeUV_r4.sub( cubeUV_r5 ) ).add( cubeUV_m4 ) ); + // cross - } ).ElseIf( roughness.greaterThanEqual( cubeUV_r6 ), () => { + colorAttribute.setXYZ( 42, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 43, cross.r, cross.g, cross.b ); // cn1, cn2 + colorAttribute.setXYZ( 44, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 45, cross.r, cross.g, cross.b ); // cn3, cn4 - mip.assign( cubeUV_r5.sub( roughness ).mul( cubeUV_m6.sub( cubeUV_m5 ) ).div( cubeUV_r5.sub( cubeUV_r6 ) ).add( cubeUV_m5 ) ); + colorAttribute.setXYZ( 46, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 47, cross.r, cross.g, cross.b ); // cf1, cf2 + colorAttribute.setXYZ( 48, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 49, cross.r, cross.g, cross.b ); // cf3, cf4 - } ).Else( () => { + colorAttribute.needsUpdate = true; - mip.assign( float( - 2.0 ).mul( log2( mul( 1.16, roughness ) ) ) ); // 1.16 = 1.79^0.25 + } - } ); + update() { - return mip; + const geometry = this.geometry; + const pointMap = this.pointMap; -} ).setLayout( { - name: 'roughnessToMip', - type: 'float', - inputs: [ - { name: 'roughness', type: 'float' } - ] -} ); + const w = 1, h = 1; -// RH coordinate system; PMREM face-indexing convention -const getDirection = /*@__PURE__*/ Fn( ( [ uv_immutable, face ] ) => { + // we need just camera projection matrix inverse + // world matrix must be identity - const uv = uv_immutable.toVar(); - uv.assign( mul( 2.0, uv ).sub( 1.0 ) ); - const direction = vec3( uv, 1.0 ).toVar(); + _camera$1.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse ); - If( face.equal( 0.0 ), () => { + // center / target - direction.assign( direction.zyx ); // ( 1, v, u ) pos x + setPoint( 'c', pointMap, geometry, _camera$1, 0, 0, - 1 ); + setPoint( 't', pointMap, geometry, _camera$1, 0, 0, 1 ); - } ).ElseIf( face.equal( 1.0 ), () => { + // near - direction.assign( direction.xzy ); - direction.xz.mulAssign( - 1.0 ); // ( -u, 1, -v ) pos y + setPoint( 'n1', pointMap, geometry, _camera$1, - w, - h, - 1 ); + setPoint( 'n2', pointMap, geometry, _camera$1, w, - h, - 1 ); + setPoint( 'n3', pointMap, geometry, _camera$1, - w, h, - 1 ); + setPoint( 'n4', pointMap, geometry, _camera$1, w, h, - 1 ); - } ).ElseIf( face.equal( 2.0 ), () => { + // far - direction.x.mulAssign( - 1.0 ); // ( -u, v, 1 ) pos z + setPoint( 'f1', pointMap, geometry, _camera$1, - w, - h, 1 ); + setPoint( 'f2', pointMap, geometry, _camera$1, w, - h, 1 ); + setPoint( 'f3', pointMap, geometry, _camera$1, - w, h, 1 ); + setPoint( 'f4', pointMap, geometry, _camera$1, w, h, 1 ); - } ).ElseIf( face.equal( 3.0 ), () => { + // up - direction.assign( direction.zyx ); - direction.xz.mulAssign( - 1.0 ); // ( -1, v, -u ) neg x + setPoint( 'u1', pointMap, geometry, _camera$1, w * 0.7, h * 1.1, - 1 ); + setPoint( 'u2', pointMap, geometry, _camera$1, - w * 0.7, h * 1.1, - 1 ); + setPoint( 'u3', pointMap, geometry, _camera$1, 0, h * 2, - 1 ); - } ).ElseIf( face.equal( 4.0 ), () => { + // cross - direction.assign( direction.xzy ); - direction.xy.mulAssign( - 1.0 ); // ( -u, -1, v ) neg y + setPoint( 'cf1', pointMap, geometry, _camera$1, - w, 0, 1 ); + setPoint( 'cf2', pointMap, geometry, _camera$1, w, 0, 1 ); + setPoint( 'cf3', pointMap, geometry, _camera$1, 0, - h, 1 ); + setPoint( 'cf4', pointMap, geometry, _camera$1, 0, h, 1 ); - } ).ElseIf( face.equal( 5.0 ), () => { + setPoint( 'cn1', pointMap, geometry, _camera$1, - w, 0, - 1 ); + setPoint( 'cn2', pointMap, geometry, _camera$1, w, 0, - 1 ); + setPoint( 'cn3', pointMap, geometry, _camera$1, 0, - h, - 1 ); + setPoint( 'cn4', pointMap, geometry, _camera$1, 0, h, - 1 ); - direction.z.mulAssign( - 1.0 ); // ( u, v, -1 ) neg zS + geometry.getAttribute( 'position' ).needsUpdate = true; - } ); + } - return direction; + dispose() { -} ).setLayout( { - name: 'getDirection', - type: 'vec3', - inputs: [ - { name: 'uv', type: 'vec2' }, - { name: 'face', type: 'float' } - ] -} ); + this.geometry.dispose(); + this.material.dispose(); -// + } -const textureCubeUV = /*@__PURE__*/ Fn( ( [ envMap, sampleDir_immutable, roughness_immutable, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP ] ) => { +} - const roughness = float( roughness_immutable ); - const sampleDir = vec3( sampleDir_immutable ); - const mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP ); - const mipF = fract( mip ); - const mipInt = floor( mip ); - const color0 = vec3( bilinearCubeUV( envMap, sampleDir, mipInt, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP ) ).toVar(); +function setPoint( point, pointMap, geometry, camera, x, y, z ) { - If( mipF.notEqual( 0.0 ), () => { + _vector.set( x, y, z ).unproject( camera ); - const color1 = vec3( bilinearCubeUV( envMap, sampleDir, mipInt.add( 1.0 ), CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP ) ).toVar(); + const points = pointMap[ point ]; - color0.assign( mix( color0, color1, mipF ) ); + if ( points !== undefined ) { - } ); + const position = geometry.getAttribute( 'position' ); - return color0; + for ( let i = 0, l = points.length; i < l; i ++ ) { -} ); + position.setXYZ( points[ i ], _vector.x, _vector.y, _vector.z ); -const bilinearCubeUV = /*@__PURE__*/ Fn( ( [ envMap, direction_immutable, mipInt_immutable, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP ] ) => { + } - const mipInt = float( mipInt_immutable ).toVar(); - const direction = vec3( direction_immutable ); - const face = float( getFace( direction ) ).toVar(); - const filterInt = float( max$1( cubeUV_minMipLevel.sub( mipInt ), 0.0 ) ).toVar(); - mipInt.assign( max$1( mipInt, cubeUV_minMipLevel ) ); - const faceSize = float( exp2( mipInt ) ).toVar(); - const uv = vec2( getUV( direction, face ).mul( faceSize.sub( 2.0 ) ).add( 1.0 ) ).toVar(); + } - If( face.greaterThan( 2.0 ), () => { +} - uv.y.addAssign( faceSize ); - face.subAssign( 3.0 ); +const _box = /*@__PURE__*/ new Box3(); - } ); +class BoxHelper extends LineSegments { - uv.x.addAssign( face.mul( faceSize ) ); - uv.x.addAssign( filterInt.mul( mul( 3.0, cubeUV_minTileSize ) ) ); - uv.y.addAssign( mul( 4.0, exp2( CUBEUV_MAX_MIP ).sub( faceSize ) ) ); - uv.x.mulAssign( CUBEUV_TEXEL_WIDTH ); - uv.y.mulAssign( CUBEUV_TEXEL_HEIGHT ); + constructor( object, color = 0xffff00 ) { - return envMap.uv( uv ).grad( vec2(), vec2() ); // disable anisotropic filtering + const indices = 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 ] ); + const positions = new Float32Array( 8 * 3 ); -} ); + const geometry = new BufferGeometry(); + geometry.setIndex( new BufferAttribute( indices, 1 ) ); + geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) ); -const getSample = /*@__PURE__*/ Fn( ( { envMap, mipInt, outputDirection, theta, axis, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP } ) => { + super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); - const cosTheta = cos( theta ); + this.object = object; + this.type = 'BoxHelper'; - // Rodrigues' axis-angle rotation - const sampleDirection = outputDirection.mul( cosTheta ) - .add( axis.cross( outputDirection ).mul( sin( theta ) ) ) - .add( axis.mul( axis.dot( outputDirection ).mul( cosTheta.oneMinus() ) ) ); + this.matrixAutoUpdate = false; - return bilinearCubeUV( envMap, sampleDirection, mipInt, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP ); + this.update(); -} ); + } -const blur = /*@__PURE__*/ Fn( ( { n, latitudinal, poleAxis, outputDirection, weights, samples, dTheta, mipInt, envMap, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP } ) => { + update( object ) { - const axis = vec3( select( latitudinal, poleAxis, cross( poleAxis, outputDirection ) ) ).toVar(); + if ( object !== undefined ) { - If( all( axis.equals( vec3( 0.0 ) ) ), () => { + console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' ); - axis.assign( vec3( outputDirection.z, 0.0, outputDirection.x.negate() ) ); + } - } ); + if ( this.object !== undefined ) { - axis.assign( normalize( axis ) ); + _box.setFromObject( this.object ); - const gl_FragColor = vec3().toVar(); - gl_FragColor.addAssign( weights.element( int( 0 ) ).mul( getSample( { theta: 0.0, axis, outputDirection, mipInt, envMap, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP } ) ) ); + } - Loop( { start: int( 1 ), end: n }, ( { i } ) => { + if ( _box.isEmpty() ) return; - If( i.greaterThanEqual( samples ), () => { + const min = _box.min; + const max = _box.max; - Break(); + /* + 5____4 + 1/___0/| + | 6__|_7 + 2/___3/ - } ); + 0: max.x, max.y, max.z + 1: min.x, max.y, max.z + 2: min.x, min.y, max.z + 3: max.x, min.y, max.z + 4: max.x, max.y, min.z + 5: min.x, max.y, min.z + 6: min.x, min.y, min.z + 7: max.x, min.y, min.z + */ - const theta = float( dTheta.mul( float( i ) ) ).toVar(); - gl_FragColor.addAssign( weights.element( i ).mul( getSample( { theta: theta.mul( - 1.0 ), axis, outputDirection, mipInt, envMap, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP } ) ) ); - gl_FragColor.addAssign( weights.element( i ).mul( getSample( { theta, axis, outputDirection, mipInt, envMap, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP } ) ) ); + const position = this.geometry.attributes.position; + const array = position.array; - } ); + array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z; + array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z; + array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z; + array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z; + array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z; + array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z; + array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z; + array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z; - return vec4( gl_FragColor, 1 ); + position.needsUpdate = true; -} ); + this.geometry.computeBoundingSphere(); -let _generator = null; + } -const _cache = new WeakMap(); + setFromObject( object ) { -function _generateCubeUVSize( imageHeight ) { + this.object = object; + this.update(); - const maxMip = Math.log2( imageHeight ) - 2; + return this; - const texelHeight = 1.0 / imageHeight; + } - const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) ); + copy( source, recursive ) { - return { texelWidth, texelHeight, maxMip }; + super.copy( source, recursive ); -} + this.object = source.object; -function _getPMREMFromTexture( texture ) { + return this; - let cacheTexture = _cache.get( texture ); + } - const pmremVersion = cacheTexture !== undefined ? cacheTexture.pmremVersion : - 1; + dispose() { - if ( pmremVersion !== texture.pmremVersion ) { + this.geometry.dispose(); + this.material.dispose(); - const image = texture.image; + } - if ( texture.isCubeTexture ) { +} - if ( isCubeMapReady( image ) ) { +class Box3Helper extends LineSegments { - cacheTexture = _generator.fromCubemap( texture, cacheTexture ); + constructor( box, color = 0xffff00 ) { - } else { + const indices = 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 ] ); - return null; + const positions = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 1, - 1, 1, - 1, - 1 ]; - } + const geometry = new BufferGeometry(); + geometry.setIndex( new BufferAttribute( indices, 1 ) ); - } else { + geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); - if ( isEquirectangularMapReady( image ) ) { + super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); - cacheTexture = _generator.fromEquirectangular( texture, cacheTexture ); + this.box = box; - } else { + this.type = 'Box3Helper'; - return null; + this.geometry.computeBoundingSphere(); - } + } - } + updateMatrixWorld( force ) { - cacheTexture.pmremVersion = texture.pmremVersion; + const box = this.box; - _cache.set( texture, cacheTexture ); + if ( box.isEmpty() ) return; + + box.getCenter( this.position ); + + box.getSize( this.scale ); + + this.scale.multiplyScalar( 0.5 ); + + super.updateMatrixWorld( force ); } - return cacheTexture.texture; + dispose() { -} + this.geometry.dispose(); + this.material.dispose(); -class PMREMNode extends TempNode { + } - constructor( value, uvNode = null, levelNode = null ) { +} - super( 'vec3' ); +class PlaneHelper extends Line { - this._value = value; - this._pmrem = null; + constructor( plane, size = 1, hex = 0xffff00 ) { - this.uvNode = uvNode; - this.levelNode = levelNode; + const color = hex; - this._generator = null; + const positions = [ 1, - 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, - 1, 0, 1, 1, 0 ]; - const defaultTexture = new Texture(); - defaultTexture.isRenderTargetTexture = true; + const geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + geometry.computeBoundingSphere(); - this._texture = texture( defaultTexture ); + super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); - this._width = uniform( 0 ); - this._height = uniform( 0 ); - this._maxMip = uniform( 0 ); + this.type = 'PlaneHelper'; - this.updateBeforeType = NodeUpdateType.RENDER; + this.plane = plane; - } + this.size = size; - set value( value ) { + const positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ]; - this._value = value; - this._pmrem = null; + const geometry2 = new BufferGeometry(); + geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) ); + geometry2.computeBoundingSphere(); + + this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) ); } - get value() { + updateMatrixWorld( force ) { - return this._value; + this.position.set( 0, 0, 0 ); - } + this.scale.set( 0.5 * this.size, 0.5 * this.size, 1 ); - updateFromTexture( texture ) { + this.lookAt( this.plane.normal ); - const cubeUVSize = _generateCubeUVSize( texture.image.height ); + this.translateZ( - this.plane.constant ); - this._texture.value = texture; - this._width.value = cubeUVSize.texelWidth; - this._height.value = cubeUVSize.texelHeight; - this._maxMip.value = cubeUVSize.maxMip; + super.updateMatrixWorld( force ); } - updateBefore() { + dispose() { - let pmrem = this._pmrem; + this.geometry.dispose(); + this.material.dispose(); + this.children[ 0 ].geometry.dispose(); + this.children[ 0 ].material.dispose(); - const pmremVersion = pmrem ? pmrem.pmremVersion : - 1; - const texture = this._value; + } - if ( pmremVersion !== texture.pmremVersion ) { +} - if ( texture.isPMREMTexture === true ) { +const _axis = /*@__PURE__*/ new Vector3(); +let _lineGeometry, _coneGeometry; - pmrem = texture; +class ArrowHelper extends Object3D { - } else { + // dir is assumed to be normalized - pmrem = _getPMREMFromTexture( texture ); + constructor( dir = new Vector3( 0, 0, 1 ), origin = new Vector3( 0, 0, 0 ), length = 1, color = 0xffff00, headLength = length * 0.2, headWidth = headLength * 0.2 ) { - } + super(); - if ( pmrem !== null ) { + this.type = 'ArrowHelper'; - this._pmrem = pmrem; + if ( _lineGeometry === undefined ) { - this.updateFromTexture( pmrem ); + _lineGeometry = new BufferGeometry(); + _lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) ); - } + _coneGeometry = new CylinderGeometry( 0, 0.5, 1, 5, 1 ); + _coneGeometry.translate( 0, - 0.5, 0 ); } - } - - setup( builder ) { + this.position.copy( origin ); - if ( _generator === null ) { + this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); + this.line.matrixAutoUpdate = false; + this.add( this.line ); - _generator = builder.createPMREMGenerator(); + this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) ); + this.cone.matrixAutoUpdate = false; + this.add( this.cone ); - } + this.setDirection( dir ); + this.setLength( length, headLength, headWidth ); - // + } - this.updateBefore( builder ); + setDirection( dir ) { - // + // dir is assumed to be normalized - let uvNode = this.uvNode; + if ( dir.y > 0.99999 ) { - if ( uvNode === null && builder.context.getUV ) { + this.quaternion.set( 0, 0, 0, 1 ); - uvNode = builder.context.getUV( this ); + } else if ( dir.y < - 0.99999 ) { - } + this.quaternion.set( 1, 0, 0, 0 ); - // + } else { - const texture = this.value; + _axis.set( dir.z, 0, - dir.x ).normalize(); - if ( builder.renderer.coordinateSystem === WebGLCoordinateSystem && texture.isPMREMTexture !== true && texture.isRenderTargetTexture === true ) { + const radians = Math.acos( dir.y ); - uvNode = vec3( uvNode.x.negate(), uvNode.yz ); + this.quaternion.setFromAxisAngle( _axis, radians ); } - // + } - let levelNode = this.levelNode; + setLength( length, headLength = length * 0.2, headWidth = headLength * 0.2 ) { - if ( levelNode === null && builder.context.getTextureLevel ) { + this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458 + this.line.updateMatrix(); - levelNode = builder.context.getTextureLevel( this ); + this.cone.scale.set( headWidth, headLength, headWidth ); + this.cone.position.y = length; + this.cone.updateMatrix(); - } + } - // + setColor( color ) { - return textureCubeUV( this._texture, uvNode, levelNode, this._width, this._height, this._maxMip ); + this.line.material.color.set( color ); + this.cone.material.color.set( color ); } -} + copy( source ) { -PMREMNode.type = /*@__PURE__*/ registerNode( 'PMREM', PMREMNode ); + super.copy( source, false ); -function isCubeMapReady( image ) { + this.line.copy( source.line ); + this.cone.copy( source.cone ); - if ( image === null || image === undefined ) return false; + return this; - let count = 0; - const length = 6; + } - for ( let i = 0; i < length; i ++ ) { + dispose() { - if ( image[ i ] !== undefined ) count ++; + this.line.geometry.dispose(); + this.line.material.dispose(); + this.cone.geometry.dispose(); + this.cone.material.dispose(); } - return count === length; - - } -function isEquirectangularMapReady( image ) { +class AxesHelper extends LineSegments { - if ( image === null || image === undefined ) return false; + constructor( size = 1 ) { - return image.height > 0; + const vertices = [ + 0, 0, 0, size, 0, 0, + 0, 0, 0, 0, size, 0, + 0, 0, 0, 0, 0, size + ]; -} + const colors = [ + 1, 0, 0, 1, 0.6, 0, + 0, 1, 0, 0.6, 1, 0, + 0, 0, 1, 0, 0.6, 1 + ]; -const pmremTexture = /*@__PURE__*/ nodeProxy( PMREMNode ); + const geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); -const _envNodeCache = new WeakMap(); + const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); -class EnvironmentNode extends LightingNode { + super( geometry, material ); - constructor( envNode = null ) { + this.type = 'AxesHelper'; - super(); + } - this.envNode = envNode; + setColors( xAxisColor, yAxisColor, zAxisColor ) { - } + const color = new Color(); + const array = this.geometry.attributes.color.array; - setup( builder ) { + color.set( xAxisColor ); + color.toArray( array, 0 ); + color.toArray( array, 3 ); - const { material } = builder; + color.set( yAxisColor ); + color.toArray( array, 6 ); + color.toArray( array, 9 ); - let envNode = this.envNode; + color.set( zAxisColor ); + color.toArray( array, 12 ); + color.toArray( array, 15 ); - if ( envNode.isTextureNode || envNode.isMaterialReferenceNode ) { + this.geometry.attributes.color.needsUpdate = true; - const value = ( envNode.isTextureNode ) ? envNode.value : material[ envNode.property ]; + return this; - let cacheEnvNode = _envNodeCache.get( value ); + } - if ( cacheEnvNode === undefined ) { + dispose() { - cacheEnvNode = pmremTexture( value ); + this.geometry.dispose(); + this.material.dispose(); - _envNodeCache.set( value, cacheEnvNode ); + } - } +} - envNode = cacheEnvNode; +class ShapePath { - } + constructor() { - // + this.type = 'ShapePath'; - const envMap = material.envMap; - const intensity = envMap ? reference( 'envMapIntensity', 'float', builder.material ) : reference( 'environmentIntensity', 'float', builder.scene ); // @TODO: Add materialEnvIntensity in MaterialNode + this.color = new Color(); - const useAnisotropy = material.useAnisotropy === true || material.anisotropy > 0; - const radianceNormalView = useAnisotropy ? transformedBentNormalView : transformedNormalView; + this.subPaths = []; + this.currentPath = null; - const radiance = envNode.context( createRadianceContext( roughness, radianceNormalView ) ).mul( intensity ); - const irradiance = envNode.context( createIrradianceContext( transformedNormalWorld ) ).mul( Math.PI ).mul( intensity ); + } - const isolateRadiance = cache( radiance ); - const isolateIrradiance = cache( irradiance ); + moveTo( x, y ) { - // + this.currentPath = new Path(); + this.subPaths.push( this.currentPath ); + this.currentPath.moveTo( x, y ); - builder.context.radiance.addAssign( isolateRadiance ); + return this; - builder.context.iblIrradiance.addAssign( isolateIrradiance ); + } - // + lineTo( x, y ) { - const clearcoatRadiance = builder.context.lightingModel.clearcoatRadiance; + this.currentPath.lineTo( x, y ); - if ( clearcoatRadiance ) { + return this; - const clearcoatRadianceContext = envNode.context( createRadianceContext( clearcoatRoughness, transformedClearcoatNormalView ) ).mul( intensity ); - const isolateClearcoatRadiance = cache( clearcoatRadianceContext ); + } - clearcoatRadiance.addAssign( isolateClearcoatRadiance ); + quadraticCurveTo( aCPx, aCPy, aX, aY ) { - } + this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY ); + + return this; } -} + bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { -EnvironmentNode.type = /*@__PURE__*/ registerNode( 'Environment', EnvironmentNode ); + this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ); -const createRadianceContext = ( roughnessNode, normalViewNode ) => { + return this; - let reflectVec = null; + } - return { - getUV: () => { + splineThru( pts ) { - if ( reflectVec === null ) { + this.currentPath.splineThru( pts ); - reflectVec = positionViewDirection.negate().reflect( normalViewNode ); + return this; - // Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane. - reflectVec = roughnessNode.mul( roughnessNode ).mix( reflectVec, normalViewNode ).normalize(); + } - reflectVec = reflectVec.transformDirection( cameraViewMatrix ); + toShapes( isCCW ) { - } + function toShapesNoHoles( inSubpaths ) { - return reflectVec; + const shapes = []; - }, - getTextureLevel: () => { + for ( let i = 0, l = inSubpaths.length; i < l; i ++ ) { - return roughnessNode; + const tmpPath = inSubpaths[ i ]; - } - }; + const tmpShape = new Shape(); + tmpShape.curves = tmpPath.curves; -}; + shapes.push( tmpShape ); -const createIrradianceContext = ( normalWorldNode ) => { + } - return { - getUV: () => { + return shapes; - return normalWorldNode; + } - }, - getTextureLevel: () => { + function isPointInsidePolygon( inPt, inPolygon ) { - return float( 1.0 ); + const polyLen = inPolygon.length; - } - }; + // inPt on polygon contour => immediate success or + // toggling of inside/outside at every single! intersection point of an edge + // with the horizontal line through inPt, left of inPt + // not counting lowerY endpoints of edges and whole edges on that line + let inside = false; + for ( let p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) { -}; + let edgeLowPt = inPolygon[ p ]; + let edgeHighPt = inPolygon[ q ]; -const _defaultValues$6 = /*@__PURE__*/ new MeshStandardMaterial(); + let edgeDx = edgeHighPt.x - edgeLowPt.x; + let edgeDy = edgeHighPt.y - edgeLowPt.y; -class MeshStandardNodeMaterial extends NodeMaterial { + if ( Math.abs( edgeDy ) > Number.EPSILON ) { - constructor( parameters ) { + // not parallel + if ( edgeDy < 0 ) { - super(); + edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx; + edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy; - this.isMeshStandardNodeMaterial = true; + } - this.lights = true; + if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue; - this.emissiveNode = null; + if ( inPt.y === edgeLowPt.y ) { - this.metalnessNode = null; - this.roughnessNode = null; + if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ? + // continue; // no intersection or edgeLowPt => doesn't count !!! - this.setDefaultValues( _defaultValues$6 ); + } else { - this.setValues( parameters ); + const perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y ); + if ( perpEdge === 0 ) return true; // inPt is on contour ? + if ( perpEdge < 0 ) continue; + inside = ! inside; // true intersection left of inPt - } + } - setupEnvironment( builder ) { + } else { - let envNode = super.setupEnvironment( builder ); + // parallel or collinear + if ( inPt.y !== edgeLowPt.y ) continue; // parallel + // edge lies on the same horizontal line as inPt + if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) || + ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour ! + // continue; - if ( envNode === null && builder.environmentNode ) { + } - envNode = builder.environmentNode; + } + + return inside; } - return envNode ? new EnvironmentNode( envNode ) : null; + const isClockWise = ShapeUtils.isClockWise; - } + const subPaths = this.subPaths; + if ( subPaths.length === 0 ) return []; - setupLightingModel( /*builder*/ ) { + let solid, tmpPath, tmpShape; + const shapes = []; - return new PhysicalLightingModel(); + if ( subPaths.length === 1 ) { - } + tmpPath = subPaths[ 0 ]; + tmpShape = new Shape(); + tmpShape.curves = tmpPath.curves; + shapes.push( tmpShape ); + return shapes; - setupSpecular() { + } - const specularColorNode = mix( vec3( 0.04 ), diffuseColor.rgb, metalness ); + let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() ); + holesFirst = isCCW ? ! holesFirst : holesFirst; - specularColor.assign( specularColorNode ); - specularF90.assign( 1.0 ); + // console.log("Holes first", holesFirst); - } + const betterShapeHoles = []; + const newShapes = []; + let newShapeHoles = []; + let mainIdx = 0; + let tmpPoints; - setupVariants() { + newShapes[ mainIdx ] = undefined; + newShapeHoles[ mainIdx ] = []; - // METALNESS + for ( let i = 0, l = subPaths.length; i < l; i ++ ) { - const metalnessNode = this.metalnessNode ? float( this.metalnessNode ) : materialMetalness; + tmpPath = subPaths[ i ]; + tmpPoints = tmpPath.getPoints(); + solid = isClockWise( tmpPoints ); + solid = isCCW ? ! solid : solid; - metalness.assign( metalnessNode ); + if ( solid ) { - // ROUGHNESS + if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++; - let roughnessNode = this.roughnessNode ? float( this.roughnessNode ) : materialRoughness; - roughnessNode = getRoughness( { roughness: roughnessNode } ); + newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints }; + newShapes[ mainIdx ].s.curves = tmpPath.curves; - roughness.assign( roughnessNode ); + if ( holesFirst ) mainIdx ++; + newShapeHoles[ mainIdx ] = []; - // SPECULAR COLOR + //console.log('cw', i); - this.setupSpecular(); + } else { - // DIFFUSE COLOR + newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } ); - diffuseColor.assign( vec4( diffuseColor.rgb.mul( metalnessNode.oneMinus() ), diffuseColor.a ) ); + //console.log('ccw', i); - } + } - copy( source ) { + } - this.emissiveNode = source.emissiveNode; + // only Holes? -> probably all Shapes with wrong orientation + if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths ); - this.metalnessNode = source.metalnessNode; - this.roughnessNode = source.roughnessNode; - return super.copy( source ); + if ( newShapes.length > 1 ) { - } + let ambiguous = false; + let toChange = 0; -} + for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { -MeshStandardNodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'MeshStandard', MeshStandardNodeMaterial ); + betterShapeHoles[ sIdx ] = []; -const _defaultValues$5 = /*@__PURE__*/ new MeshPhysicalMaterial(); + } -class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { + for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { - constructor( parameters ) { + const sho = newShapeHoles[ sIdx ]; - super(); + for ( let hIdx = 0; hIdx < sho.length; hIdx ++ ) { - this.isMeshPhysicalNodeMaterial = true; + const ho = sho[ hIdx ]; + let hole_unassigned = true; - this.clearcoatNode = null; - this.clearcoatRoughnessNode = null; - this.clearcoatNormalNode = null; + for ( let s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) { - this.sheenNode = null; - this.sheenRoughnessNode = null; + if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) { - this.iridescenceNode = null; - this.iridescenceIORNode = null; - this.iridescenceThicknessNode = null; + if ( sIdx !== s2Idx ) toChange ++; - this.specularIntensityNode = null; - this.specularColorNode = null; + if ( hole_unassigned ) { - this.iorNode = null; - this.transmissionNode = null; - this.thicknessNode = null; - this.attenuationDistanceNode = null; - this.attenuationColorNode = null; - this.dispersionNode = null; + hole_unassigned = false; + betterShapeHoles[ s2Idx ].push( ho ); - this.anisotropyNode = null; + } else { - this.setDefaultValues( _defaultValues$5 ); + ambiguous = true; - this.setValues( parameters ); + } - } + } - get useClearcoat() { + } - return this.clearcoat > 0 || this.clearcoatNode !== null; + if ( hole_unassigned ) { - } + betterShapeHoles[ sIdx ].push( ho ); - get useIridescence() { + } - return this.iridescence > 0 || this.iridescenceNode !== null; + } - } + } - get useSheen() { + if ( toChange > 0 && ambiguous === false ) { - return this.sheen > 0 || this.sheenNode !== null; + newShapeHoles = betterShapeHoles; - } + } - get useAnisotropy() { + } - return this.anisotropy > 0 || this.anisotropyNode !== null; + let tmpHoles; - } + for ( let i = 0, il = newShapes.length; i < il; i ++ ) { - get useTransmission() { + tmpShape = newShapes[ i ].s; + shapes.push( tmpShape ); + tmpHoles = newShapeHoles[ i ]; - return this.transmission > 0 || this.transmissionNode !== null; + for ( let j = 0, jl = tmpHoles.length; j < jl; j ++ ) { - } + tmpShape.holes.push( tmpHoles[ j ].h ); - get useDispersion() { + } - return this.dispersion > 0 || this.dispersionNode !== null; + } - } + //console.log("shape", shapes); - setupSpecular() { + return shapes; - const iorNode = this.iorNode ? float( this.iorNode ) : materialIOR; + } - ior.assign( iorNode ); - specularColor.assign( mix( min$1( pow2( ior.sub( 1.0 ).div( ior.add( 1.0 ) ) ).mul( materialSpecularColor ), vec3( 1.0 ) ).mul( materialSpecularIntensity ), diffuseColor.rgb, metalness ) ); - specularF90.assign( mix( materialSpecularIntensity, 1.0, metalness ) ); +} - } +class Controls extends EventDispatcher { - setupLightingModel( /*builder*/ ) { + constructor( object, domElement = null ) { - return new PhysicalLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useAnisotropy, this.useTransmission, this.useDispersion ); + super(); - } + this.object = object; + this.domElement = domElement; - setupVariants( builder ) { + this.enabled = true; - super.setupVariants( builder ); + this.state = - 1; - // CLEARCOAT + this.keys = {}; + this.mouseButtons = { LEFT: null, MIDDLE: null, RIGHT: null }; + this.touches = { ONE: null, TWO: null }; - if ( this.useClearcoat ) { + } - const clearcoatNode = this.clearcoatNode ? float( this.clearcoatNode ) : materialClearcoat; - const clearcoatRoughnessNode = this.clearcoatRoughnessNode ? float( this.clearcoatRoughnessNode ) : materialClearcoatRoughness; + connect() {} - clearcoat.assign( clearcoatNode ); - clearcoatRoughness.assign( getRoughness( { roughness: clearcoatRoughnessNode } ) ); + disconnect() {} - } + dispose() {} - // SHEEN + update( /* delta */ ) {} - if ( this.useSheen ) { +} - const sheenNode = this.sheenNode ? vec3( this.sheenNode ) : materialSheen; - const sheenRoughnessNode = this.sheenRoughnessNode ? float( this.sheenRoughnessNode ) : materialSheenRoughness; +class WebGLMultipleRenderTargets extends WebGLRenderTarget { // @deprecated, r162 - sheen.assign( sheenNode ); - sheenRoughness.assign( sheenRoughnessNode ); + constructor( width = 1, height = 1, count = 1, options = {} ) { - } + console.warn( 'THREE.WebGLMultipleRenderTargets has been deprecated and will be removed in r172. Use THREE.WebGLRenderTarget and set the "count" parameter to enable MRT.' ); - // IRIDESCENCE + super( width, height, { ...options, count } ); - if ( this.useIridescence ) { + this.isWebGLMultipleRenderTargets = true; - const iridescenceNode = this.iridescenceNode ? float( this.iridescenceNode ) : materialIridescence; - const iridescenceIORNode = this.iridescenceIORNode ? float( this.iridescenceIORNode ) : materialIridescenceIOR; - const iridescenceThicknessNode = this.iridescenceThicknessNode ? float( this.iridescenceThicknessNode ) : materialIridescenceThickness; + } - iridescence.assign( iridescenceNode ); - iridescenceIOR.assign( iridescenceIORNode ); - iridescenceThickness.assign( iridescenceThicknessNode ); + get texture() { - } + return this.textures; - // ANISOTROPY + } - if ( this.useAnisotropy ) { +} - const anisotropyV = ( this.anisotropyNode ? vec2( this.anisotropyNode ) : materialAnisotropy ).toVar(); +const refreshUniforms = [ + 'alphaMap', + 'alphaTest', + 'anisotropy', + 'anisotropyMap', + 'anisotropyRotation', + 'aoMap', + 'attenuationColor', + 'attenuationDistance', + 'bumpMap', + 'clearcoat', + 'clearcoatMap', + 'clearcoatNormalMap', + 'clearcoatNormalScale', + 'clearcoatRoughness', + 'color', + 'dispersion', + 'displacementMap', + 'emissive', + 'emissiveMap', + 'envMap', + 'gradientMap', + 'ior', + 'iridescence', + 'iridescenceIOR', + 'iridescenceMap', + 'iridescenceThicknessMap', + 'lightMap', + 'map', + 'matcap', + 'metalness', + 'metalnessMap', + 'normalMap', + 'normalScale', + 'opacity', + 'roughness', + 'roughnessMap', + 'sheen', + 'sheenColor', + 'sheenColorMap', + 'sheenRoughnessMap', + 'shininess', + 'specular', + 'specularColor', + 'specularColorMap', + 'specularIntensity', + 'specularIntensityMap', + 'specularMap', + 'thickness', + 'transmission', + 'transmissionMap' +]; - anisotropy.assign( anisotropyV.length() ); +class NodeMaterialObserver { - If( anisotropy.equal( 0.0 ), () => { + constructor( builder ) { - anisotropyV.assign( vec2( 1.0, 0.0 ) ); + this.renderObjects = new WeakMap(); + this.hasNode = this.containsNode( builder ); + this.hasAnimation = builder.object.isSkinnedMesh === true; + this.refreshUniforms = refreshUniforms; + this.renderId = 0; - } ).Else( () => { + } - anisotropyV.divAssign( vec2( anisotropy ) ); - anisotropy.assign( anisotropy.saturate() ); + firstInitialization( renderObject ) { - } ); + const hasInitialized = this.renderObjects.has( renderObject ); - // Roughness along the anisotropy bitangent is the material roughness, while the tangent roughness increases with anisotropy. - alphaT.assign( anisotropy.pow2().mix( roughness.pow2(), 1.0 ) ); + if ( hasInitialized === false ) { - anisotropyT.assign( TBNViewMatrix[ 0 ].mul( anisotropyV.x ).add( TBNViewMatrix[ 1 ].mul( anisotropyV.y ) ) ); - anisotropyB.assign( TBNViewMatrix[ 1 ].mul( anisotropyV.x ).sub( TBNViewMatrix[ 0 ].mul( anisotropyV.y ) ) ); + this.getRenderObjectData( renderObject ); + + return true; } - // TRANSMISSION + return false; - if ( this.useTransmission ) { + } - const transmissionNode = this.transmissionNode ? float( this.transmissionNode ) : materialTransmission; - const thicknessNode = this.thicknessNode ? float( this.thicknessNode ) : materialThickness; - const attenuationDistanceNode = this.attenuationDistanceNode ? float( this.attenuationDistanceNode ) : materialAttenuationDistance; - const attenuationColorNode = this.attenuationColorNode ? vec3( this.attenuationColorNode ) : materialAttenuationColor; + getRenderObjectData( renderObject ) { - transmission.assign( transmissionNode ); - thickness.assign( thicknessNode ); - attenuationDistance.assign( attenuationDistanceNode ); - attenuationColor.assign( attenuationColorNode ); + let data = this.renderObjects.get( renderObject ); - if ( this.useDispersion ) { + if ( data === undefined ) { - const dispersionNode = this.dispersionNode ? float( this.dispersionNode ) : materialDispersion; + data = { + material: this.getMaterialData( renderObject.material ), + worldMatrix: renderObject.object.matrixWorld.clone() + }; - dispersion.assign( dispersionNode ); + if ( renderObject.object.center ) { + + data.center = renderObject.object.center.clone(); } - } + if ( renderObject.object.morphTargetInfluences ) { - } + data.morphTargetInfluences = renderObject.object.morphTargetInfluences.slice(); - setupClearcoatNormal() { + } - return this.clearcoatNormalNode ? vec3( this.clearcoatNormalNode ) : materialClearcoatNormal; + if ( renderObject.bundle !== null ) { - } + data.version = renderObject.bundle.version; - setup( builder ) { + } - builder.context.setupClearcoatNormal = () => this.setupClearcoatNormal( builder ); + this.renderObjects.set( renderObject, data ); - super.setup( builder ); + } - } + return data; - copy( source ) { + } - this.clearcoatNode = source.clearcoatNode; - this.clearcoatRoughnessNode = source.clearcoatRoughnessNode; - this.clearcoatNormalNode = source.clearcoatNormalNode; + containsNode( builder ) { - this.sheenNode = source.sheenNode; - this.sheenRoughnessNode = source.sheenRoughnessNode; + const material = builder.material; - this.iridescenceNode = source.iridescenceNode; - this.iridescenceIORNode = source.iridescenceIORNode; - this.iridescenceThicknessNode = source.iridescenceThicknessNode; + for ( const property in material ) { - this.specularIntensityNode = source.specularIntensityNode; - this.specularColorNode = source.specularColorNode; + if ( material[ property ] && material[ property ].isNode ) + return true; - this.transmissionNode = source.transmissionNode; - this.thicknessNode = source.thicknessNode; - this.attenuationDistanceNode = source.attenuationDistanceNode; - this.attenuationColorNode = source.attenuationColorNode; - this.dispersionNode = source.dispersionNode; + } - this.anisotropyNode = source.anisotropyNode; + if ( builder.renderer.nodes.modelViewMatrix !== null || builder.renderer.nodes.modelNormalViewMatrix !== null ) + return true; - return super.copy( source ); + return false; } -} + getMaterialData( material ) { -MeshPhysicalNodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'MeshPhysical', MeshPhysicalNodeMaterial ); + const data = {}; -class SSSLightingModel extends PhysicalLightingModel { + for ( const property of this.refreshUniforms ) { - constructor( useClearcoat, useSheen, useIridescence, useSSS ) { + const value = material[ property ]; - super( useClearcoat, useSheen, useIridescence ); + if ( value === null || value === undefined ) continue; - this.useSSS = useSSS; + if ( typeof value === 'object' && value.clone !== undefined ) { - } + if ( value.isTexture === true ) { - direct( { lightDirection, lightColor, reflectedLight }, stack, builder ) { + data[ property ] = { id: value.id, version: value.version }; - if ( this.useSSS === true ) { + } else { - const material = builder.material; + data[ property ] = value.clone(); - const { thicknessColorNode, thicknessDistortionNode, thicknessAmbientNode, thicknessAttenuationNode, thicknessPowerNode, thicknessScaleNode } = material; + } - const scatteringHalf = lightDirection.add( transformedNormalView.mul( thicknessDistortionNode ) ).normalize(); - const scatteringDot = float( positionViewDirection.dot( scatteringHalf.negate() ).saturate().pow( thicknessPowerNode ).mul( thicknessScaleNode ) ); - const scatteringIllu = vec3( scatteringDot.add( thicknessAmbientNode ).mul( thicknessColorNode ) ); + } else { - reflectedLight.directDiffuse.addAssign( scatteringIllu.mul( thicknessAttenuationNode.mul( lightColor ) ) ); + data[ property ] = value; + + } } - super.direct( { lightDirection, lightColor, reflectedLight }, stack, builder ); + return data; } -} + equals( renderObject ) { -class MeshSSSNodeMaterial extends MeshPhysicalNodeMaterial { + const { object, material } = renderObject; - constructor( parameters ) { + const renderObjectData = this.getRenderObjectData( renderObject ); - super( parameters ); + // world matrix - this.thicknessColorNode = null; - this.thicknessDistortionNode = float( 0.1 ); - this.thicknessAmbientNode = float( 0.0 ); - this.thicknessAttenuationNode = float( .1 ); - this.thicknessPowerNode = float( 2.0 ); - this.thicknessScaleNode = float( 10.0 ); + if ( renderObjectData.worldMatrix.equals( object.matrixWorld ) !== true ) { - } + renderObjectData.worldMatrix.copy( object.matrixWorld ); - get useSSS() { + return false; - return this.thicknessColorNode !== null; + } - } + // material - setupLightingModel( /*builder*/ ) { + const materialData = renderObjectData.material; - return new SSSLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useSSS ); + for ( const property in materialData ) { - } + const value = materialData[ property ]; + const mtlValue = material[ property ]; - copy( source ) { + if ( value.equals !== undefined ) { - this.thicknessColorNode = source.thicknessColorNode; - this.thicknessDistortionNode = source.thicknessDistortionNode; - this.thicknessAmbientNode = source.thicknessAmbientNode; - this.thicknessAttenuationNode = source.thicknessAttenuationNode; - this.thicknessPowerNode = source.thicknessPowerNode; - this.thicknessScaleNode = source.thicknessScaleNode; + if ( value.equals( mtlValue ) === false ) { - return super.copy( source ); + value.copy( mtlValue ); - } + return false; -} + } -MeshSSSNodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'MeshSSS', MeshSSSNodeMaterial ); + } else if ( mtlValue.isTexture === true ) { -const getGradientIrradiance = /*@__PURE__*/ Fn( ( { normal, lightDirection, builder } ) => { + if ( value.id !== mtlValue.id || value.version !== mtlValue.version ) { - // dotNL will be from -1.0 to 1.0 - const dotNL = normal.dot( lightDirection ); - const coord = vec2( dotNL.mul( 0.5 ).add( 0.5 ), 0.0 ); + value.id = mtlValue.id; + value.version = mtlValue.version; - if ( builder.material.gradientMap ) { + return false; - const gradientMap = materialReference( 'gradientMap', 'texture' ).context( { getUV: () => coord } ); + } - return vec3( gradientMap.r ); + } else if ( value !== mtlValue ) { - } else { + materialData[ property ] = mtlValue; - const fw = coord.fwidth().mul( 0.5 ); + return false; - return mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( float( 0.7 ).sub( fw.x ), float( 0.7 ).add( fw.x ), coord.x ) ); + } - } + } -} ); + // morph targets -class ToonLightingModel extends LightingModel { + if ( renderObjectData.morphTargetInfluences ) { - direct( { lightDirection, lightColor, reflectedLight }, stack, builder ) { + let morphChanged = false; - const irradiance = getGradientIrradiance( { normal: normalGeometry, lightDirection, builder } ).mul( lightColor ); + for ( let i = 0; i < renderObjectData.morphTargetInfluences.length; i ++ ) { - reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) ); + if ( renderObjectData.morphTargetInfluences[ i ] !== object.morphTargetInfluences[ i ] ) { - } + morphChanged = true; - indirect( { ambientOcclusion, irradiance, reflectedLight } ) { + } - reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) ); + } - reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion ); + if ( morphChanged ) return true; - } + } -} + // center -const _defaultValues$4 = /*@__PURE__*/ new MeshToonMaterial(); + if ( renderObjectData.center ) { -class MeshToonNodeMaterial extends NodeMaterial { + if ( renderObjectData.center.equals( object.center ) === false ) { - constructor( parameters ) { + renderObjectData.center.copy( object.center ); - super(); + return true; - this.isMeshToonNodeMaterial = true; + } - this.lights = true; + } - this.setDefaultValues( _defaultValues$4 ); + // bundle - this.setValues( parameters ); + if ( renderObject.bundle !== null ) { - } + renderObjectData.version = renderObject.bundle.version; - setupLightingModel( /*builder*/ ) { + } - return new ToonLightingModel(); + return true; } -} + needsRefresh( renderObject, nodeFrame ) { -MeshToonNodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'MeshToon', MeshToonNodeMaterial ); + if ( this.hasNode || this.hasAnimation || this.firstInitialization( renderObject ) ) + return true; -class MatcapUVNode extends TempNode { + const { renderId } = nodeFrame; - constructor() { + if ( this.renderId !== renderId ) { - super( 'vec2' ); + this.renderId = renderId; - } + return true; - setup() { + } - const x = vec3( positionViewDirection.z, 0, positionViewDirection.x.negate() ).normalize(); - const y = positionViewDirection.cross( x ); + const isStatic = renderObject.object.static === true; + const isBundle = renderObject.bundle !== null && renderObject.bundle.static === true && this.getRenderObjectData( renderObject ).version === renderObject.bundle.version; - return vec2( x.dot( transformedNormalView ), y.dot( transformedNormalView ) ).mul( 0.495 ).add( 0.5 ); // 0.495 to remove artifacts caused by undersized matcap disks + if ( isStatic || isBundle ) + return false; + + const notEqual = this.equals( renderObject ) !== true; + + return notEqual; } } -MatcapUVNode.type = /*@__PURE__*/ registerNode( 'MatcapUV', MatcapUVNode ); +// cyrb53 (c) 2018 bryc (github.com/bryc). License: Public domain. Attribution appreciated. +// A fast and simple 64-bit (or 53-bit) string hash function with decent collision resistance. +// Largely inspired by MurmurHash2/3, but with a focus on speed/simplicity. +// See https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript/52171480#52171480 +// https://github.com/bryc/code/blob/master/jshash/experimental/cyrb53.js +function cyrb53( value, seed = 0 ) { -const matcapUV = /*@__PURE__*/ nodeImmutable( MatcapUVNode ); + let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed; -const _defaultValues$3 = /*@__PURE__*/ new MeshMatcapMaterial(); + if ( value instanceof Array ) { -class MeshMatcapNodeMaterial extends NodeMaterial { + for ( let i = 0, val; i < value.length; i ++ ) { - constructor( parameters ) { + val = value[ i ]; + h1 = Math.imul( h1 ^ val, 2654435761 ); + h2 = Math.imul( h2 ^ val, 1597334677 ); - super(); + } - this.lights = false; + } else { - this.isMeshMatcapNodeMaterial = true; + for ( let i = 0, ch; i < value.length; i ++ ) { - this.setDefaultValues( _defaultValues$3 ); + ch = value.charCodeAt( i ); + h1 = Math.imul( h1 ^ ch, 2654435761 ); + h2 = Math.imul( h2 ^ ch, 1597334677 ); - this.setValues( parameters ); + } } - setupVariants( builder ) { - - const uv = matcapUV; + h1 = Math.imul( h1 ^ ( h1 >>> 16 ), 2246822507 ); + h1 ^= Math.imul( h2 ^ ( h2 >>> 13 ), 3266489909 ); + h2 = Math.imul( h2 ^ ( h2 >>> 16 ), 2246822507 ); + h2 ^= Math.imul( h1 ^ ( h1 >>> 13 ), 3266489909 ); - let matcapColor; + return 4294967296 * ( 2097151 & h2 ) + ( h1 >>> 0 ); - if ( builder.material.matcap ) { +} - matcapColor = materialReference( 'matcap', 'texture' ).context( { getUV: () => uv } ); +const hashString = ( str ) => cyrb53( str ); +const hashArray = ( array ) => cyrb53( array ); +const hash$1 = ( ...params ) => cyrb53( params ); - } else { +function getCacheKey$1( object, force = false ) { - matcapColor = vec3( mix( 0.2, 0.8, uv.y ) ); // default if matcap is missing + const values = []; - } + if ( object.isNode === true ) { - diffuseColor.rgb.mulAssign( matcapColor.rgb ); + values.push( object.id ); + object = object.getSelf(); } -} + for ( const { property, childNode } of getNodeChildren( object ) ) { -MeshMatcapNodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'MeshMatcap', MeshMatcapNodeMaterial ); + values.push( values, cyrb53( property.slice( 0, - 4 ) ), childNode.getCacheKey( force ) ); -const _defaultValues$2 = /*@__PURE__*/ new PointsMaterial(); + } -class PointsNodeMaterial extends NodeMaterial { + return cyrb53( values ); - constructor( parameters ) { +} - super(); +function* getNodeChildren( node, toJSON = false ) { - this.isPointsNodeMaterial = true; + for ( const property in node ) { - this.lights = false; - this.transparent = true; + // Ignore private properties. + if ( property.startsWith( '_' ) === true ) continue; - this.sizeNode = null; + const object = node[ property ]; - this.setDefaultValues( _defaultValues$2 ); + if ( Array.isArray( object ) === true ) { - this.setValues( parameters ); + for ( let i = 0; i < object.length; i ++ ) { - } + const child = object[ i ]; - copy( source ) { + if ( child && ( child.isNode === true || toJSON && typeof child.toJSON === 'function' ) ) { - this.sizeNode = source.sizeNode; + yield { property, index: i, childNode: child }; - return super.copy( source ); + } - } + } -} + } else if ( object && object.isNode === true ) { -PointsNodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'Points', PointsNodeMaterial ); + yield { property, childNode: object }; -class RotateNode extends TempNode { + } else if ( typeof object === 'object' ) { - constructor( positionNode, rotationNode ) { + for ( const subProperty in object ) { - super(); + const child = object[ subProperty ]; - this.positionNode = positionNode; - this.rotationNode = rotationNode; + if ( child && ( child.isNode === true || toJSON && typeof child.toJSON === 'function' ) ) { - } + yield { property, index: subProperty, childNode: child }; - getNodeType( builder ) { + } - return this.positionNode.getNodeType( builder ); + } + + } } - setup( builder ) { +} - const { rotationNode, positionNode } = this; +function getValueType( value ) { - const nodeType = this.getNodeType( builder ); + if ( value === undefined || value === null ) return null; - if ( nodeType === 'vec2' ) { + const typeOf = typeof value; - const cosAngle = rotationNode.cos(); - const sinAngle = rotationNode.sin(); + if ( value.isNode === true ) { - const rotationMatrix = mat2( - cosAngle, sinAngle, - sinAngle.negate(), cosAngle - ); + return 'node'; - return rotationMatrix.mul( positionNode ); + } else if ( typeOf === 'number' ) { - } else { + return 'float'; - const rotation = rotationNode; - const rotationXMatrix = mat4( vec4( 1.0, 0.0, 0.0, 0.0 ), vec4( 0.0, cos( rotation.x ), sin( rotation.x ).negate(), 0.0 ), vec4( 0.0, sin( rotation.x ), cos( rotation.x ), 0.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) ); - const rotationYMatrix = mat4( vec4( cos( rotation.y ), 0.0, sin( rotation.y ), 0.0 ), vec4( 0.0, 1.0, 0.0, 0.0 ), vec4( sin( rotation.y ).negate(), 0.0, cos( rotation.y ), 0.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) ); - const rotationZMatrix = mat4( vec4( cos( rotation.z ), sin( rotation.z ).negate(), 0.0, 0.0 ), vec4( sin( rotation.z ), cos( rotation.z ), 0.0, 0.0 ), vec4( 0.0, 0.0, 1.0, 0.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) ); + } else if ( typeOf === 'boolean' ) { - return rotationXMatrix.mul( rotationYMatrix ).mul( rotationZMatrix ).mul( vec4( positionNode, 1.0 ) ).xyz; + return 'bool'; - } + } else if ( typeOf === 'string' ) { - } + return 'string'; -} + } else if ( typeOf === 'function' ) { -RotateNode.type = /*@__PURE__*/ registerNode( 'Rotate', RotateNode ); + return 'shader'; -const rotate = /*@__PURE__*/ nodeProxy( RotateNode ); + } else if ( value.isVector2 === true ) { -const _defaultValues$1 = /*@__PURE__*/ new SpriteMaterial(); + return 'vec2'; -class SpriteNodeMaterial extends NodeMaterial { + } else if ( value.isVector3 === true ) { - constructor( parameters ) { + return 'vec3'; - super(); + } else if ( value.isVector4 === true ) { - this.isSpriteNodeMaterial = true; + return 'vec4'; - this.lights = false; + } else if ( value.isMatrix3 === true ) { - this.positionNode = null; - this.rotationNode = null; - this.scaleNode = null; + return 'mat3'; - this.setDefaultValues( _defaultValues$1 ); + } else if ( value.isMatrix4 === true ) { - this.setValues( parameters ); + return 'mat4'; - } + } else if ( value.isColor === true ) { - setupPosition( { object, context } ) { + return 'color'; - // < VERTEX STAGE > + } else if ( value instanceof ArrayBuffer ) { - const { positionNode, rotationNode, scaleNode } = this; + return 'ArrayBuffer'; - const vertex = positionLocal; + } - let mvPosition = modelViewMatrix.mul( vec3( positionNode || 0 ) ); + return null; - let scale = vec2( modelWorldMatrix[ 0 ].xyz.length(), modelWorldMatrix[ 1 ].xyz.length() ); +} - if ( scaleNode !== null ) { +function getValueFromType( type, ...params ) { - scale = scale.mul( scaleNode ); + const last4 = type ? type.slice( - 4 ) : undefined; - } + if ( params.length === 1 ) { // ensure same behaviour as in NodeBuilder.format() - let alignedPosition = vertex.xy; + if ( last4 === 'vec2' ) params = [ params[ 0 ], params[ 0 ] ]; + else if ( last4 === 'vec3' ) params = [ params[ 0 ], params[ 0 ], params[ 0 ] ]; + else if ( last4 === 'vec4' ) params = [ params[ 0 ], params[ 0 ], params[ 0 ], params[ 0 ] ]; - if ( object.center && object.center.isVector2 === true ) { + } - alignedPosition = alignedPosition.sub( uniform( object.center ).sub( 0.5 ) ); + if ( type === 'color' ) { - } + return new Color( ...params ); - alignedPosition = alignedPosition.mul( scale ); + } else if ( last4 === 'vec2' ) { - const rotation = float( rotationNode || materialRotation ); + return new Vector2( ...params ); - const rotatedPosition = rotate( alignedPosition, rotation ); + } else if ( last4 === 'vec3' ) { - mvPosition = vec4( mvPosition.xy.add( rotatedPosition ), mvPosition.zw ); + return new Vector3( ...params ); - const modelViewProjection = cameraProjectionMatrix.mul( mvPosition ); + } else if ( last4 === 'vec4' ) { - context.vertex = vertex; + return new Vector4( ...params ); - return modelViewProjection; + } else if ( last4 === 'mat3' ) { - } + return new Matrix3( ...params ); - copy( source ) { + } else if ( last4 === 'mat4' ) { - this.positionNode = source.positionNode; - this.rotationNode = source.rotationNode; - this.scaleNode = source.scaleNode; + return new Matrix4( ...params ); - return super.copy( source ); + } else if ( type === 'bool' ) { - } + return params[ 0 ] || false; -} + } else if ( ( type === 'float' ) || ( type === 'int' ) || ( type === 'uint' ) ) { -SpriteNodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'Sprite', SpriteNodeMaterial ); + return params[ 0 ] || 0; -class ShadowMaskModel extends LightingModel { + } else if ( type === 'string' ) { - constructor() { + return params[ 0 ] || ''; - super(); + } else if ( type === 'ArrayBuffer' ) { - this.shadowNode = float( 1 ).toVar( 'shadowMask' ); + return base64ToArrayBuffer( params[ 0 ] ); } - direct( { shadowMask } ) { + return null; - this.shadowNode.mulAssign( shadowMask ); +} - } +function arrayBufferToBase64( arrayBuffer ) { - finish( context ) { + let chars = ''; - diffuseColor.a.mulAssign( this.shadowNode.oneMinus() ); + const array = new Uint8Array( arrayBuffer ); - context.outgoingLight.rgb.assign( diffuseColor.rgb ); // TODO: Optimize LightsNode to avoid this assignment + for ( let i = 0; i < array.length; i ++ ) { + + chars += String.fromCharCode( array[ i ] ); } + return btoa( chars ); + } -const _defaultValues = /*@__PURE__*/ new ShadowMaterial(); +function base64ToArrayBuffer( base64 ) { -class ShadowNodeMaterial extends NodeMaterial { + return Uint8Array.from( atob( base64 ), c => c.charCodeAt( 0 ) ).buffer; - constructor( parameters ) { +} - super(); +var NodeUtils = /*#__PURE__*/Object.freeze({ + __proto__: null, + arrayBufferToBase64: arrayBufferToBase64, + base64ToArrayBuffer: base64ToArrayBuffer, + getCacheKey: getCacheKey$1, + getNodeChildren: getNodeChildren, + getValueFromType: getValueFromType, + getValueType: getValueType, + hash: hash$1, + hashArray: hashArray, + hashString: hashString +}); - this.isShadowNodeMaterial = true; +const NodeShaderStage = { + VERTEX: 'vertex', + FRAGMENT: 'fragment' +}; - this.lights = true; +const NodeUpdateType = { + NONE: 'none', + FRAME: 'frame', + RENDER: 'render', + OBJECT: 'object' +}; - this.setDefaultValues( _defaultValues ); +const NodeType = { + BOOLEAN: 'bool', + INTEGER: 'int', + FLOAT: 'float', + VECTOR2: 'vec2', + VECTOR3: 'vec3', + VECTOR4: 'vec4', + MATRIX2: 'mat2', + MATRIX3: 'mat3', + MATRIX4: 'mat4' +}; - this.setValues( parameters ); +const defaultShaderStages = [ 'fragment', 'vertex' ]; +const defaultBuildStages = [ 'setup', 'analyze', 'generate' ]; +const shaderStages = [ ...defaultShaderStages, 'compute' ]; +const vectorComponents = [ 'x', 'y', 'z', 'w' ]; - } +let _nodeId = 0; - setupLightingModel( /*builder*/ ) { +class Node extends EventDispatcher { - return new ShadowMaskModel(); + static get type() { - } + return 'Node'; -} + } -ShadowNodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'Shadow', ShadowNodeMaterial ); + constructor( nodeType = null ) { -const normal = Fn( ( { texture, uv } ) => { + super(); - const epsilon = 0.0001; + this.nodeType = nodeType; - const ret = vec3().temp(); + this.updateType = NodeUpdateType.NONE; + this.updateBeforeType = NodeUpdateType.NONE; + this.updateAfterType = NodeUpdateType.NONE; - If( uv.x.lessThan( epsilon ), () => { + this.uuid = MathUtils.generateUUID(); - ret.assign( vec3( 1, 0, 0 ) ); + this.version = 0; - } ).ElseIf( uv.y.lessThan( epsilon ), () => { + this._cacheKey = null; + this._cacheKeyVersion = 0; - ret.assign( vec3( 0, 1, 0 ) ); + this.global = false; - } ).ElseIf( uv.z.lessThan( epsilon ), () => { + this.isNode = true; - ret.assign( vec3( 0, 0, 1 ) ); + Object.defineProperty( this, 'id', { value: _nodeId ++ } ); - } ).ElseIf( uv.x.greaterThan( 1 - epsilon ), () => { + } - ret.assign( vec3( - 1, 0, 0 ) ); + set needsUpdate( value ) { - } ).ElseIf( uv.y.greaterThan( 1 - epsilon ), () => { + if ( value === true ) { - ret.assign( vec3( 0, - 1, 0 ) ); + this.version ++; - } ).ElseIf( uv.z.greaterThan( 1 - epsilon ), () => { + } - ret.assign( vec3( 0, 0, - 1 ) ); + } - } ).Else( () => { + get type() { - const step = 0.01; + return this.constructor.type; - const x = texture.uv( uv.add( vec3( - step, 0.0, 0.0 ) ) ).r.sub( texture.uv( uv.add( vec3( step, 0.0, 0.0 ) ) ).r ); - const y = texture.uv( uv.add( vec3( 0.0, - step, 0.0 ) ) ).r.sub( texture.uv( uv.add( vec3( 0.0, step, 0.0 ) ) ).r ); - const z = texture.uv( uv.add( vec3( 0.0, 0.0, - step ) ) ).r.sub( texture.uv( uv.add( vec3( 0.0, 0.0, step ) ) ).r ); + } - ret.assign( vec3( x, y, z ) ); + onUpdate( callback, updateType ) { - } ); + this.updateType = updateType; + this.update = callback.bind( this.getSelf() ); - return ret.normalize(); + return this; -} ); + } + onFrameUpdate( callback ) { -class Texture3DNode extends TextureNode { + return this.onUpdate( callback, NodeUpdateType.FRAME ); - constructor( value, uvNode = null, levelNode = null ) { + } - super( value, uvNode, levelNode ); + onRenderUpdate( callback ) { - this.isTexture3DNode = true; + return this.onUpdate( callback, NodeUpdateType.RENDER ); } - getInputType( /*builder*/ ) { + onObjectUpdate( callback ) { - return 'texture3D'; + return this.onUpdate( callback, NodeUpdateType.OBJECT ); } - getDefaultUV() { + onReference( callback ) { - return vec3( 0.5, 0.5, 0.5 ); + this.updateReference = callback.bind( this.getSelf() ); + + return this; } - setUpdateMatrix( /*updateMatrix*/ ) { } // Ignore .updateMatrix for 3d TextureNode + getSelf() { - setupUV( builder, uvNode ) { + // Returns non-node object. - return uvNode; + return this.self || this; } - generateUV( builder, uvNode ) { + updateReference( /*state*/ ) { - return uvNode.build( builder, 'vec3' ); + return this; } - normal( uvNode ) { + isGlobal( /*builder*/ ) { - return normal( { texture: this, uv: uvNode } ); + return this.global; } -} - -Texture3DNode.type = /*@__PURE__*/ registerNode( 'Texture3D', Texture3DNode ); + * getChildren() { -const texture3D = /*@__PURE__*/ nodeProxy( Texture3DNode ); + for ( const { childNode } of getNodeChildren( this ) ) { -class VolumeNodeMaterial extends NodeMaterial { + yield childNode; - constructor( params = {} ) { + } - super(); + } - this.lights = false; - this.isVolumeNodeMaterial = true; - this.testNode = null; + dispose() { - this.setValues( params ); + this.dispatchEvent( { type: 'dispose' } ); } - setup( builder ) { + traverse( callback ) { - const map = texture3D( this.map, null, 0 ); + callback( this ); - const hitBox = Fn( ( { orig, dir } ) => { + for ( const childNode of this.getChildren() ) { - const box_min = vec3( - 0.5 ); - const box_max = vec3( 0.5 ); + childNode.traverse( callback ); - const inv_dir = dir.reciprocal(); + } - const tmin_tmp = box_min.sub( orig ).mul( inv_dir ); - const tmax_tmp = box_max.sub( orig ).mul( inv_dir ); + } - const tmin = min$1( tmin_tmp, tmax_tmp ); - const tmax = max$1( tmin_tmp, tmax_tmp ); + getCacheKey( force = false ) { - const t0 = max$1( tmin.x, max$1( tmin.y, tmin.z ) ); - const t1 = min$1( tmax.x, min$1( tmax.y, tmax.z ) ); + force = force || this.version !== this._cacheKeyVersion; - return vec2( t0, t1 ); + if ( force === true || this._cacheKey === null ) { - } ); + this._cacheKey = getCacheKey$1( this, force ); + this._cacheKeyVersion = this.version; - this.fragmentNode = Fn( () => { + } - const vOrigin = varying( vec3( modelWorldMatrixInverse.mul( vec4( cameraPosition, 1.0 ) ) ) ); - const vDirection = varying( positionGeometry.sub( vOrigin ) ); + return this._cacheKey; - const rayDir = vDirection.normalize(); - const bounds = property( 'vec2', 'bounds' ).assign( hitBox( { orig: vOrigin, dir: rayDir } ) ); + } - bounds.x.greaterThan( bounds.y ).discard(); + getScope() { - bounds.assign( vec2( max$1( bounds.x, 0.0 ), bounds.y ) ); + return this; - const p = property( 'vec3', 'p' ).assign( vOrigin.add( bounds.x.mul( rayDir ) ) ); - const inc = property( 'vec3', 'inc' ).assign( vec3( rayDir.abs().reciprocal() ) ); - const delta = property( 'float', 'delta' ).assign( min$1( inc.x, min$1( inc.y, inc.z ) ) ); + } - delta.divAssign( materialReference( 'steps', 'float' ) ); + getHash( /*builder*/ ) { - const ac = property( 'vec4', 'ac' ).assign( vec4( materialReference( 'base', 'color' ), 0.0 ) ); + return this.uuid; - Loop( { type: 'float', start: bounds.x, end: bounds.y, update: '+= delta' }, () => { + } - const d = property( 'float', 'd' ).assign( map.uv( p.add( 0.5 ) ).r ); + getUpdateType() { - if ( this.testNode !== null ) { + return this.updateType; - this.testNode( { map: map, mapValue: d, probe: p, finalColor: ac } ).append(); + } - } else { + getUpdateBeforeType() { - // default to show surface of mesh - ac.a.assign( 1 ); - Break(); + return this.updateBeforeType; - } + } - p.addAssign( rayDir.mul( delta ) ); + getUpdateAfterType() { - } ); + return this.updateAfterType; - ac.a.equal( 0 ).discard(); + } - return vec4( ac ); + getElementType( builder ) { - } )(); + const type = this.getNodeType( builder ); + const elementType = builder.getElementType( type ); - super.setup( builder ); + return elementType; } -} + getNodeType( builder ) { -VolumeNodeMaterial.type = /*@__PURE__*/ registerNodeMaterial( 'Volume', VolumeNodeMaterial ); + const nodeProperties = builder.getNodeProperties( this ); -// converts an array to a specific type -function convertArray( array, type, forceClone ) { + if ( nodeProperties.outputNode ) { - if ( ! array || // let 'undefined' and 'null' pass - ! forceClone && array.constructor === type ) return array; + return nodeProperties.outputNode.getNodeType( builder ); - if ( typeof type.BYTES_PER_ELEMENT === 'number' ) { + } - return new type( array ); // create typed array + return this.nodeType; } - return Array.prototype.slice.call( array ); // create Array + getShared( builder ) { -} + const hash = this.getHash( builder ); + const nodeFromHash = builder.getNodeFromHash( hash ); -function isTypedArray( object ) { + return nodeFromHash || this; - return ArrayBuffer.isView( object ) && - ! ( object instanceof DataView ); + } -} + setup( builder ) { -// returns an array by which times and values can be sorted -function getKeyframeOrder( times ) { + const nodeProperties = builder.getNodeProperties( this ); - function compareTime( i, j ) { + let index = 0; - return times[ i ] - times[ j ]; + for ( const childNode of this.getChildren() ) { + + nodeProperties[ 'node' + index ++ ] = childNode; + + } + + // return a outputNode if exists + return null; } - const n = times.length; - const result = new Array( n ); - for ( let i = 0; i !== n; ++ i ) result[ i ] = i; + analyze( builder ) { - result.sort( compareTime ); + const usageCount = builder.increaseUsage( this ); - return result; + if ( usageCount === 1 ) { -} + // node flow children -// uses the array previously returned by 'getKeyframeOrder' to sort data -function sortedArray( values, stride, order ) { + const nodeProperties = builder.getNodeProperties( this ); - const nValues = values.length; - const result = new values.constructor( nValues ); + for ( const childNode of Object.values( nodeProperties ) ) { - for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) { + if ( childNode && childNode.isNode === true ) { - const srcOffset = order[ i ] * stride; + childNode.build( builder ); - for ( let j = 0; j !== stride; ++ j ) { + } - result[ dstOffset ++ ] = values[ srcOffset + j ]; + } } } - return result; + generate( builder, output ) { -} + const { outputNode } = builder.getNodeProperties( this ); -// function for parsing AOS keyframe formats -function flattenJSON( jsonKeys, times, values, valuePropertyName ) { + if ( outputNode && outputNode.isNode === true ) { - let i = 1, key = jsonKeys[ 0 ]; + return outputNode.build( builder, output ); - while ( key !== undefined && key[ valuePropertyName ] === undefined ) { + } - key = jsonKeys[ i ++ ]; + } + + updateBefore( /*frame*/ ) { + + console.warn( 'Abstract function.' ); } - if ( key === undefined ) return; // no data + updateAfter( /*frame*/ ) { - let value = key[ valuePropertyName ]; - if ( value === undefined ) return; // no data + console.warn( 'Abstract function.' ); - if ( Array.isArray( value ) ) { + } - do { + update( /*frame*/ ) { - value = key[ valuePropertyName ]; + console.warn( 'Abstract function.' ); - if ( value !== undefined ) { + } - times.push( key.time ); - values.push.apply( values, value ); // push all elements + build( builder, output = null ) { - } + const refNode = this.getShared( builder ); - key = jsonKeys[ i ++ ]; + if ( this !== refNode ) { - } while ( key !== undefined ); + return refNode.build( builder, output ); - } else if ( value.toArray !== undefined ) { + } - // ...assume THREE.Math-ish + builder.addNode( this ); + builder.addChain( this ); - do { + /* Build stages expected results: + - "setup" -> Node + - "analyze" -> null + - "generate" -> String + */ + let result = null; - value = key[ valuePropertyName ]; + const buildStage = builder.getBuildStage(); - if ( value !== undefined ) { + if ( buildStage === 'setup' ) { - times.push( key.time ); - value.toArray( values, values.length ); + this.updateReference( builder ); - } + const properties = builder.getNodeProperties( this ); - key = jsonKeys[ i ++ ]; + if ( properties.initialized !== true ) { - } while ( key !== undefined ); + const stackNodesBeforeSetup = builder.stack.nodes.length; - } else { + properties.initialized = true; + properties.outputNode = this.setup( builder ); - // otherwise push as-is + if ( properties.outputNode !== null && builder.stack.nodes.length !== stackNodesBeforeSetup ) ; - do { + for ( const childNode of Object.values( properties ) ) { - value = key[ valuePropertyName ]; + if ( childNode && childNode.isNode === true ) { - if ( value !== undefined ) { + childNode.build( builder ); - times.push( key.time ); - values.push( value ); + } - } + } - key = jsonKeys[ i ++ ]; + } - } while ( key !== undefined ); + } else if ( buildStage === 'analyze' ) { - } + this.analyze( builder ); -} + } else if ( buildStage === 'generate' ) { -function subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) { + const isGenerateOnce = this.generate.length === 1; - const clip = sourceClip.clone(); + if ( isGenerateOnce ) { - clip.name = name; + const type = this.getNodeType( builder ); + const nodeData = builder.getDataFromNode( this ); - const tracks = []; + result = nodeData.snippet; - for ( let i = 0; i < clip.tracks.length; ++ i ) { + if ( result === undefined ) { - const track = clip.tracks[ i ]; - const valueSize = track.getValueSize(); + result = this.generate( builder ) || ''; - const times = []; - const values = []; + nodeData.snippet = result; - for ( let j = 0; j < track.times.length; ++ j ) { + } else if ( nodeData.flowCodes !== undefined && builder.context.nodeBlock !== undefined ) { - const frame = track.times[ j ] * fps; + builder.addFlowCodeHierarchy( this, builder.context.nodeBlock ); - if ( frame < startFrame || frame >= endFrame ) continue; + } - times.push( track.times[ j ] ); + result = builder.format( result, type, output ); - for ( let k = 0; k < valueSize; ++ k ) { + } else { - values.push( track.values[ j * valueSize + k ] ); + result = this.generate( builder, output ) || ''; } } - if ( times.length === 0 ) continue; - - track.times = convertArray( times, track.times.constructor ); - track.values = convertArray( values, track.values.constructor ); + builder.removeChain( this ); - tracks.push( track ); + return result; } - clip.tracks = tracks; - - // find minimum .times value across all tracks in the trimmed clip + getSerializeChildren() { - let minStartTime = Infinity; + return getNodeChildren( this ); - for ( let i = 0; i < clip.tracks.length; ++ i ) { + } - if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) { + serialize( json ) { - minStartTime = clip.tracks[ i ].times[ 0 ]; + const nodeChildren = this.getSerializeChildren(); - } + const inputNodes = {}; - } + for ( const { property, index, childNode } of nodeChildren ) { - // shift all tracks such that clip begins at t=0 + if ( index !== undefined ) { - for ( let i = 0; i < clip.tracks.length; ++ i ) { + if ( inputNodes[ property ] === undefined ) { - clip.tracks[ i ].shift( - 1 * minStartTime ); + inputNodes[ property ] = Number.isInteger( index ) ? [] : {}; - } + } - clip.resetDuration(); + inputNodes[ property ][ index ] = childNode.toJSON( json.meta ).uuid; - return clip; + } else { -} + inputNodes[ property ] = childNode.toJSON( json.meta ).uuid; -function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) { + } - if ( fps <= 0 ) fps = 30; + } - const numTracks = referenceClip.tracks.length; - const referenceTime = referenceFrame / fps; + if ( Object.keys( inputNodes ).length > 0 ) { - // Make each track's values relative to the values at the reference frame - for ( let i = 0; i < numTracks; ++ i ) { + json.inputNodes = inputNodes; - const referenceTrack = referenceClip.tracks[ i ]; - const referenceTrackType = referenceTrack.ValueTypeName; + } - // Skip this track if it's non-numeric - if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue; + } - // Find the track in the target clip whose name and type matches the reference track - const targetTrack = targetClip.tracks.find( function ( track ) { + deserialize( json ) { - return track.name === referenceTrack.name - && track.ValueTypeName === referenceTrackType; + if ( json.inputNodes !== undefined ) { - } ); + const nodes = json.meta.nodes; - if ( targetTrack === undefined ) continue; + for ( const property in json.inputNodes ) { - let referenceOffset = 0; - const referenceValueSize = referenceTrack.getValueSize(); + if ( Array.isArray( json.inputNodes[ property ] ) ) { - if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) { + const inputArray = []; - referenceOffset = referenceValueSize / 3; + for ( const uuid of json.inputNodes[ property ] ) { - } + inputArray.push( nodes[ uuid ] ); - let targetOffset = 0; - const targetValueSize = targetTrack.getValueSize(); + } - if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) { + this[ property ] = inputArray; - targetOffset = targetValueSize / 3; + } else if ( typeof json.inputNodes[ property ] === 'object' ) { - } + const inputObject = {}; - const lastIndex = referenceTrack.times.length - 1; - let referenceValue; + for ( const subProperty in json.inputNodes[ property ] ) { - // Find the value to subtract out of the track - if ( referenceTime <= referenceTrack.times[ 0 ] ) { + const uuid = json.inputNodes[ property ][ subProperty ]; - // Reference frame is earlier than the first keyframe, so just use the first keyframe - const startIndex = referenceOffset; - const endIndex = referenceValueSize - referenceOffset; - referenceValue = referenceTrack.values.slice( startIndex, endIndex ); + inputObject[ subProperty ] = nodes[ uuid ]; - } else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) { + } - // Reference frame is after the last keyframe, so just use the last keyframe - const startIndex = lastIndex * referenceValueSize + referenceOffset; - const endIndex = startIndex + referenceValueSize - referenceOffset; - referenceValue = referenceTrack.values.slice( startIndex, endIndex ); + this[ property ] = inputObject; - } else { + } else { - // Interpolate to the reference value - const interpolant = referenceTrack.createInterpolant(); - const startIndex = referenceOffset; - const endIndex = referenceValueSize - referenceOffset; - interpolant.evaluate( referenceTime ); - referenceValue = interpolant.resultBuffer.slice( startIndex, endIndex ); + const uuid = json.inputNodes[ property ]; - } + this[ property ] = nodes[ uuid ]; - // Conjugate the quaternion - if ( referenceTrackType === 'quaternion' ) { + } - const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate(); - referenceQuat.toArray( referenceValue ); + } } - // Subtract the reference value from all of the track values + } - const numTimes = targetTrack.times.length; - for ( let j = 0; j < numTimes; ++ j ) { + toJSON( meta ) { - const valueStart = j * targetValueSize + targetOffset; + const { uuid, type } = this; + const isRoot = ( meta === undefined || typeof meta === 'string' ); - if ( referenceTrackType === 'quaternion' ) { + if ( isRoot ) { - // Multiply the conjugate for quaternion track types - Quaternion.multiplyQuaternionsFlat( - targetTrack.values, - valueStart, - referenceValue, - 0, - targetTrack.values, - valueStart - ); + meta = { + textures: {}, + images: {}, + nodes: {} + }; - } else { + } - const valueEnd = targetValueSize - targetOffset * 2; + // serialize - // Subtract each value for all other numeric track types - for ( let k = 0; k < valueEnd; ++ k ) { + let data = meta.nodes[ uuid ]; - targetTrack.values[ valueStart + k ] -= referenceValue[ k ]; + if ( data === undefined ) { + data = { + uuid, + type, + meta, + metadata: { + version: 4.6, + type: 'Node', + generator: 'Node.toJSON' } + }; - } + if ( isRoot !== true ) meta.nodes[ data.uuid ] = data; - } + this.serialize( data ); - } + delete data.meta; - targetClip.blendMode = AdditiveAnimationBlendMode; + } - return targetClip; + // TODO: Copied from Object3D.toJSON -} + function extractFromCache( cache ) { -const AnimationUtils = { - convertArray: convertArray, - isTypedArray: isTypedArray, - getKeyframeOrder: getKeyframeOrder, - sortedArray: sortedArray, - flattenJSON: flattenJSON, - subclip: subclip, - makeClipAdditive: makeClipAdditive -}; + const values = []; -/** - * Abstract base class of interpolants over parametric samples. - * - * The parameter domain is one dimensional, typically the time or a path - * along a curve defined by the data. - * - * The sample values can have any dimensionality and derived classes may - * apply special interpretations to the data. - * - * This class provides the interval seek in a Template Method, deferring - * the actual interpolation to derived classes. - * - * Time complexity is O(1) for linear access crossing at most two points - * and O(log N) for random access, where N is the number of positions. - * - * References: - * - * http://www.oodesign.com/template-method-pattern.html - * - */ + for ( const key in cache ) { -class Interpolant { + const data = cache[ key ]; + delete data.metadata; + values.push( data ); - constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + } - this.parameterPositions = parameterPositions; - this._cachedIndex = 0; + return values; - this.resultBuffer = resultBuffer !== undefined ? - resultBuffer : new sampleValues.constructor( sampleSize ); - this.sampleValues = sampleValues; - this.valueSize = sampleSize; + } - this.settings = null; - this.DefaultSettings_ = {}; + if ( isRoot ) { - } + const textures = extractFromCache( meta.textures ); + const images = extractFromCache( meta.images ); + const nodes = extractFromCache( meta.nodes ); - evaluate( t ) { + if ( textures.length > 0 ) data.textures = textures; + if ( images.length > 0 ) data.images = images; + if ( nodes.length > 0 ) data.nodes = nodes; - const pp = this.parameterPositions; - let i1 = this._cachedIndex, - t1 = pp[ i1 ], - t0 = pp[ i1 - 1 ]; + } - validate_interval: { + return data; - seek: { + } - let right; +} - linear_scan: { +class ArrayElementNode extends Node { - //- See http://jsperf.com/comparison-to-undefined/3 - //- slower code: - //- - //- if ( t >= t1 || t1 === undefined ) { - forward_scan: if ( ! ( t < t1 ) ) { + static get type() { - for ( let giveUpAt = i1 + 2; ; ) { + return 'ArrayElementNode'; - if ( t1 === undefined ) { + } // @TODO: If extending from TempNode it breaks webgpu_compute - if ( t < t0 ) break forward_scan; + constructor( node, indexNode ) { - // after end + super(); - i1 = pp.length; - this._cachedIndex = i1; - return this.copySampleValue_( i1 - 1 ); + this.node = node; + this.indexNode = indexNode; - } + this.isArrayElementNode = true; - if ( i1 === giveUpAt ) break; // this loop + } - t0 = t1; - t1 = pp[ ++ i1 ]; + getNodeType( builder ) { - if ( t < t1 ) { + return this.node.getElementType( builder ); - // we have arrived at the sought interval - break seek; + } - } + generate( builder ) { - } + const nodeSnippet = this.node.build( builder ); + const indexSnippet = this.indexNode.build( builder, 'uint' ); - // prepare binary search on the right side of the index - right = pp.length; - break linear_scan; + return `${nodeSnippet}[ ${indexSnippet} ]`; - } + } - //- slower code: - //- if ( t < t0 || t0 === undefined ) { - if ( ! ( t >= t0 ) ) { +} - // looping? +class ConvertNode extends Node { - const t1global = pp[ 1 ]; + static get type() { - if ( t < t1global ) { + return 'ConvertNode'; - i1 = 2; // + 1, using the scan for the details - t0 = t1global; + } - } + constructor( node, convertTo ) { - // linear reverse scan + super(); - for ( let giveUpAt = i1 - 2; ; ) { + this.node = node; + this.convertTo = convertTo; - if ( t0 === undefined ) { + } - // before start + getNodeType( builder ) { - this._cachedIndex = 0; - return this.copySampleValue_( 0 ); + const requestType = this.node.getNodeType( builder ); - } + let convertTo = null; - if ( i1 === giveUpAt ) break; // this loop + for ( const overloadingType of this.convertTo.split( '|' ) ) { - t1 = t0; - t0 = pp[ -- i1 - 1 ]; + if ( convertTo === null || builder.getTypeLength( requestType ) === builder.getTypeLength( overloadingType ) ) { - if ( t >= t0 ) { + convertTo = overloadingType; - // we have arrived at the sought interval - break seek; + } - } + } - } + return convertTo; - // prepare binary search on the left side of the index - right = i1; - i1 = 0; - break linear_scan; + } - } + serialize( data ) { - // the interval is valid + super.serialize( data ); - break validate_interval; + data.convertTo = this.convertTo; - } // linear scan + } - // binary search + deserialize( data ) { - while ( i1 < right ) { + super.deserialize( data ); - const mid = ( i1 + right ) >>> 1; + this.convertTo = data.convertTo; - if ( t < pp[ mid ] ) { + } - right = mid; + generate( builder, output ) { - } else { + const node = this.node; + const type = this.getNodeType( builder ); - i1 = mid + 1; + const snippet = node.build( builder, type ); - } + return builder.format( snippet, type, output ); - } + } - t1 = pp[ i1 ]; - t0 = pp[ i1 - 1 ]; +} - // check boundary cases, again +class TempNode extends Node { - if ( t0 === undefined ) { + static get type() { - this._cachedIndex = 0; - return this.copySampleValue_( 0 ); + return 'TempNode'; - } + } - if ( t1 === undefined ) { + constructor( type ) { - i1 = pp.length; - this._cachedIndex = i1; - return this.copySampleValue_( i1 - 1 ); + super( type ); - } + this.isTempNode = true; - } // seek + } - this._cachedIndex = i1; + hasDependencies( builder ) { - this.intervalChanged_( i1, t0, t1 ); + return builder.getDataFromNode( this ).usageCount > 1; - } // validate_interval + } - return this.interpolate_( i1, t0, t, t1 ); + build( builder, output ) { - } + const buildStage = builder.getBuildStage(); - getSettings_() { + if ( buildStage === 'generate' ) { - return this.settings || this.DefaultSettings_; + const type = builder.getVectorType( this.getNodeType( builder, output ) ); + const nodeData = builder.getDataFromNode( this ); - } + if ( nodeData.propertyName !== undefined ) { - copySampleValue_( index ) { + return builder.format( nodeData.propertyName, type, output ); - // copies a sample value to the result buffer + } else if ( type !== 'void' && output !== 'void' && this.hasDependencies( builder ) ) { - const result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, - offset = index * stride; + const snippet = super.build( builder, type ); - for ( let i = 0; i !== stride; ++ i ) { + const nodeVar = builder.getVarFromNode( this, null, type ); + const propertyName = builder.getPropertyName( nodeVar ); - result[ i ] = values[ offset + i ]; + builder.addLineFlowCode( `${propertyName} = ${snippet}`, this ); + + nodeData.snippet = snippet; + nodeData.propertyName = propertyName; + + return builder.format( nodeData.propertyName, type, output ); + + } } - return result; + return super.build( builder, output ); } - // Template methods for derived classes: +} - interpolate_( /* i1, t0, t, t1 */ ) { +class JoinNode extends TempNode { - throw new Error( 'call to abstract method' ); - // implementations shall return this.resultBuffer + static get type() { + + return 'JoinNode'; } - intervalChanged_( /* i1, t0, t1 */ ) { + constructor( nodes = [], nodeType = null ) { - // empty + super( nodeType ); + + this.nodes = nodes; } -} + getNodeType( builder ) { -/** - * Fast and simple cubic spline interpolant. - * - * It was derived from a Hermitian construction setting the first derivative - * at each sample position to the linear slope between neighboring positions - * over their parameter interval. - */ + if ( this.nodeType !== null ) { -class CubicInterpolant extends Interpolant { + return builder.getVectorType( this.nodeType ); - constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + } - super( parameterPositions, sampleValues, sampleSize, resultBuffer ); + return builder.getTypeFromLength( this.nodes.reduce( ( count, cur ) => count + builder.getTypeLength( cur.getNodeType( builder ) ), 0 ) ); - this._weightPrev = - 0; - this._offsetPrev = - 0; - this._weightNext = - 0; - this._offsetNext = - 0; + } - this.DefaultSettings_ = { + generate( builder, output ) { - endingStart: ZeroCurvatureEnding, - endingEnd: ZeroCurvatureEnding + const type = this.getNodeType( builder ); + const nodes = this.nodes; - }; + const primitiveType = builder.getComponentType( type ); - } + const snippetValues = []; - intervalChanged_( i1, t0, t1 ) { + for ( const input of nodes ) { - const pp = this.parameterPositions; - let iPrev = i1 - 2, - iNext = i1 + 1, + let inputSnippet = input.build( builder ); - tPrev = pp[ iPrev ], - tNext = pp[ iNext ]; + const inputPrimitiveType = builder.getComponentType( input.getNodeType( builder ) ); - if ( tPrev === undefined ) { + if ( inputPrimitiveType !== primitiveType ) { - switch ( this.getSettings_().endingStart ) { + inputSnippet = builder.format( inputSnippet, inputPrimitiveType, primitiveType ); - case ZeroSlopeEnding: + } - // f'(t0) = 0 - iPrev = i1; - tPrev = 2 * t0 - t1; + snippetValues.push( inputSnippet ); - break; + } - case WrapAroundEnding: + const snippet = `${ builder.getType( type ) }( ${ snippetValues.join( ', ' ) } )`; - // use the other end of the curve - iPrev = pp.length - 2; - tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ]; + return builder.format( snippet, type, output ); - break; + } - default: // ZeroCurvatureEnding +} - // f''(t0) = 0 a.k.a. Natural Spline - iPrev = i1; - tPrev = t1; +const stringVectorComponents = vectorComponents.join( '' ); - } +class SplitNode extends Node { - } + static get type() { - if ( tNext === undefined ) { + return 'SplitNode'; - switch ( this.getSettings_().endingEnd ) { + } - case ZeroSlopeEnding: + constructor( node, components = 'x' ) { - // f'(tN) = 0 - iNext = i1; - tNext = 2 * t1 - t0; + super(); - break; + this.node = node; + this.components = components; - case WrapAroundEnding: + this.isSplitNode = true; - // use the other end of the curve - iNext = 1; - tNext = t1 + pp[ 1 ] - pp[ 0 ]; + } - break; + getVectorLength() { - default: // ZeroCurvatureEnding + let vectorLength = this.components.length; - // f''(tN) = 0, a.k.a. Natural Spline - iNext = i1 - 1; - tNext = t0; + for ( const c of this.components ) { - } + vectorLength = Math.max( vectorComponents.indexOf( c ) + 1, vectorLength ); } - const halfDt = ( t1 - t0 ) * 0.5, - stride = this.valueSize; + return vectorLength; - this._weightPrev = halfDt / ( t0 - tPrev ); - this._weightNext = halfDt / ( tNext - t1 ); - this._offsetPrev = iPrev * stride; - this._offsetNext = iNext * stride; + } + + getComponentType( builder ) { + + return builder.getComponentType( this.node.getNodeType( builder ) ); } - interpolate_( i1, t0, t, t1 ) { + getNodeType( builder ) { - const result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, + return builder.getTypeFromLength( this.components.length, this.getComponentType( builder ) ); - o1 = i1 * stride, o0 = o1 - stride, - oP = this._offsetPrev, oN = this._offsetNext, - wP = this._weightPrev, wN = this._weightNext, + } - p = ( t - t0 ) / ( t1 - t0 ), - pp = p * p, - ppp = pp * p; + generate( builder, output ) { - // evaluate polynomials + const node = this.node; + const nodeTypeLength = builder.getTypeLength( node.getNodeType( builder ) ); - const sP = - wP * ppp + 2 * wP * pp - wP * p; - const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1; - const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p; - const sN = wN * ppp - wN * pp; + let snippet = null; - // combine data linearly + if ( nodeTypeLength > 1 ) { - for ( let i = 0; i !== stride; ++ i ) { + let type = null; - result[ i ] = - sP * values[ oP + i ] + - s0 * values[ o0 + i ] + - s1 * values[ o1 + i ] + - sN * values[ oN + i ]; + const componentsLength = this.getVectorLength(); - } + if ( componentsLength >= nodeTypeLength ) { - return result; + // needed expand the input node - } + type = builder.getTypeFromLength( this.getVectorLength(), this.getComponentType( builder ) ); -} + } -class LinearInterpolant extends Interpolant { + const nodeSnippet = node.build( builder, type ); - constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + if ( this.components.length === nodeTypeLength && this.components === stringVectorComponents.slice( 0, this.components.length ) ) { - super( parameterPositions, sampleValues, sampleSize, resultBuffer ); + // unnecessary swizzle - } + snippet = builder.format( nodeSnippet, type, output ); - interpolate_( i1, t0, t, t1 ) { + } else { - const result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, + snippet = builder.format( `${nodeSnippet}.${this.components}`, this.getNodeType( builder ), output ); - offset1 = i1 * stride, - offset0 = offset1 - stride, + } - weight1 = ( t - t0 ) / ( t1 - t0 ), - weight0 = 1 - weight1; + } else { - for ( let i = 0; i !== stride; ++ i ) { + // ignore .components if .node returns float/integer - result[ i ] = - values[ offset0 + i ] * weight0 + - values[ offset1 + i ] * weight1; + snippet = node.build( builder, output ); } - return result; + return snippet; } -} - -/** - * - * Interpolant that evaluates to the sample value at the position preceding - * the parameter. - */ - -class DiscreteInterpolant extends Interpolant { + serialize( data ) { - constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + super.serialize( data ); - super( parameterPositions, sampleValues, sampleSize, resultBuffer ); + data.components = this.components; } - interpolate_( i1 /*, t0, t, t1 */ ) { + deserialize( data ) { - return this.copySampleValue_( i1 - 1 ); + super.deserialize( data ); + + this.components = data.components; } } -class KeyframeTrack { +class SetNode extends TempNode { - constructor( name, times, values, interpolation ) { + static get type() { - if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' ); - if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name ); + return 'SetNode'; - this.name = name; + } - this.times = convertArray( times, this.TimeBufferType ); - this.values = convertArray( values, this.ValueBufferType ); + constructor( sourceNode, components, targetNode ) { - this.setInterpolation( interpolation || this.DefaultInterpolation ); + super(); + + this.sourceNode = sourceNode; + this.components = components; + this.targetNode = targetNode; } - // Serialization (in static context, because of constructor invocation - // and automatic invocation of .toJSON): + getNodeType( builder ) { - static toJSON( track ) { + return this.sourceNode.getNodeType( builder ); - const trackType = track.constructor; + } - let json; + generate( builder ) { - // derived classes can define a static toJSON method - if ( trackType.toJSON !== this.toJSON ) { + const { sourceNode, components, targetNode } = this; - json = trackType.toJSON( track ); + const sourceType = this.getNodeType( builder ); + const targetType = builder.getTypeFromLength( components.length, targetNode.getNodeType( builder ) ); - } else { + const targetSnippet = targetNode.build( builder, targetType ); + const sourceSnippet = sourceNode.build( builder, sourceType ); - // by default, we assume the data can be serialized as-is - json = { + const length = builder.getTypeLength( sourceType ); + const snippetValues = []; - 'name': track.name, - 'times': convertArray( track.times, Array ), - 'values': convertArray( track.values, Array ) + for ( let i = 0; i < length; i ++ ) { - }; + const component = vectorComponents[ i ]; - const interpolation = track.getInterpolation(); + if ( component === components[ 0 ] ) { - if ( interpolation !== track.DefaultInterpolation ) { + snippetValues.push( targetSnippet ); - json.interpolation = interpolation; + i += components.length - 1; + + } else { + + snippetValues.push( sourceSnippet + '.' + component ); } } - json.type = track.ValueTypeName; // mandatory - - return json; + return `${ builder.getType( sourceType ) }( ${ snippetValues.join( ', ' ) } )`; } - InterpolantFactoryMethodDiscrete( result ) { - - return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result ); +} - } +class FlipNode extends TempNode { - InterpolantFactoryMethodLinear( result ) { + static get type() { - return new LinearInterpolant( this.times, this.values, this.getValueSize(), result ); + return 'FlipNode'; } - InterpolantFactoryMethodSmooth( result ) { + constructor( sourceNode, components ) { - return new CubicInterpolant( this.times, this.values, this.getValueSize(), result ); + super(); - } + this.sourceNode = sourceNode; + this.components = components; - setInterpolation( interpolation ) { + } - let factoryMethod; + getNodeType( builder ) { - switch ( interpolation ) { + return this.sourceNode.getNodeType( builder ); - case InterpolateDiscrete: + } - factoryMethod = this.InterpolantFactoryMethodDiscrete; + generate( builder ) { - break; + const { components, sourceNode } = this; - case InterpolateLinear: + const sourceType = this.getNodeType( builder ); + const sourceSnippet = sourceNode.build( builder ); - factoryMethod = this.InterpolantFactoryMethodLinear; + const sourceCache = builder.getVarFromNode( this ); + const sourceProperty = builder.getPropertyName( sourceCache ); - break; + builder.addLineFlowCode( sourceProperty + ' = ' + sourceSnippet, this ); - case InterpolateSmooth: + const length = builder.getTypeLength( sourceType ); + const snippetValues = []; - factoryMethod = this.InterpolantFactoryMethodSmooth; + let componentIndex = 0; - break; + for ( let i = 0; i < length; i ++ ) { - } + const component = vectorComponents[ i ]; - if ( factoryMethod === undefined ) { + if ( component === components[ componentIndex ] ) { - const message = 'unsupported interpolation for ' + - this.ValueTypeName + ' keyframe track named ' + this.name; + snippetValues.push( '1.0 - ' + ( sourceProperty + '.' + component ) ); - if ( this.createInterpolant === undefined ) { + componentIndex ++; - // fall back to default, unless the default itself is messed up - if ( interpolation !== this.DefaultInterpolation ) { + } else { - this.setInterpolation( this.DefaultInterpolation ); + snippetValues.push( sourceProperty + '.' + component ); - } else { + } - throw new Error( message ); // fatal, in this case + } - } + return `${ builder.getType( sourceType ) }( ${ snippetValues.join( ', ' ) } )`; - } + } - console.warn( 'THREE.KeyframeTrack:', message ); - return this; +} - } +class InputNode extends Node { - this.createInterpolant = factoryMethod; + static get type() { - return this; + return 'InputNode'; } - getInterpolation() { + constructor( value, nodeType = null ) { - switch ( this.createInterpolant ) { + super( nodeType ); - case this.InterpolantFactoryMethodDiscrete: + this.isInputNode = true; - return InterpolateDiscrete; + this.value = value; + this.precision = null; - case this.InterpolantFactoryMethodLinear: + } - return InterpolateLinear; + getNodeType( /*builder*/ ) { - case this.InterpolantFactoryMethodSmooth: + if ( this.nodeType === null ) { - return InterpolateSmooth; + return getValueType( this.value ); } + return this.nodeType; + } - getValueSize() { + getInputType( builder ) { - return this.values.length / this.times.length; + return this.getNodeType( builder ); } - // move all keyframes either forwards or backwards in time - shift( timeOffset ) { + setPrecision( precision ) { - if ( timeOffset !== 0.0 ) { + this.precision = precision; - const times = this.times; + return this; - for ( let i = 0, n = times.length; i !== n; ++ i ) { + } - times[ i ] += timeOffset; + serialize( data ) { - } + super.serialize( data ); - } + data.value = this.value; - return this; + if ( this.value && this.value.toArray ) data.value = this.value.toArray(); - } + data.valueType = getValueType( this.value ); + data.nodeType = this.nodeType; - // scale all keyframe times by a factor (useful for frame <-> seconds conversions) - scale( timeScale ) { + if ( data.valueType === 'ArrayBuffer' ) data.value = arrayBufferToBase64( data.value ); - if ( timeScale !== 1.0 ) { + data.precision = this.precision; - const times = this.times; + } - for ( let i = 0, n = times.length; i !== n; ++ i ) { + deserialize( data ) { - times[ i ] *= timeScale; + super.deserialize( data ); - } + this.nodeType = data.nodeType; + this.value = Array.isArray( data.value ) ? getValueFromType( data.valueType, ...data.value ) : data.value; - } + this.precision = data.precision || null; - return this; + if ( this.value && this.value.fromArray ) this.value = this.value.fromArray( data.value ); } - // removes keyframes before and after animation without changing any values within the range [startTime, endTime]. - // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values - trim( startTime, endTime ) { + generate( /*builder, output*/ ) { - const times = this.times, - nKeys = times.length; + console.warn( 'Abstract function.' ); - let from = 0, - to = nKeys - 1; + } - while ( from !== nKeys && times[ from ] < startTime ) { +} - ++ from; +class ConstNode extends InputNode { - } - - while ( to !== - 1 && times[ to ] > endTime ) { - - -- to; - - } + static get type() { - ++ to; // inclusive -> exclusive bound + return 'ConstNode'; - if ( from !== 0 || to !== nKeys ) { + } - // empty tracks are forbidden, so keep at least one keyframe - if ( from >= to ) { + constructor( value, nodeType = null ) { - to = Math.max( to, 1 ); - from = to - 1; + super( value, nodeType ); - } + this.isConstNode = true; - const stride = this.getValueSize(); - this.times = times.slice( from, to ); - this.values = this.values.slice( from * stride, to * stride ); + } - } + generateConst( builder ) { - return this; + return builder.generateConst( this.getNodeType( builder ), this.value ); } - // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable - validate() { + generate( builder, output ) { - let valid = true; + const type = this.getNodeType( builder ); - const valueSize = this.getValueSize(); - if ( valueSize - Math.floor( valueSize ) !== 0 ) { + return builder.format( this.generateConst( builder ), type, output ); - console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this ); - valid = false; + } - } +} - const times = this.times, - values = this.values, +// - nKeys = times.length; +let currentStack = null; - if ( nKeys === 0 ) { +const NodeElements = new Map(); - console.error( 'THREE.KeyframeTrack: Track is empty.', this ); - valid = false; +function addMethodChaining( name, nodeElement ) { - } + if ( NodeElements.has( name ) ) { - let prevTime = null; + console.warn( `Redefinition of method chaining ${ name }` ); + return; - for ( let i = 0; i !== nKeys; i ++ ) { + } - const currTime = times[ i ]; + if ( typeof nodeElement !== 'function' ) throw new Error( `Node element ${ name } is not a function` ); - if ( typeof currTime === 'number' && isNaN( currTime ) ) { + NodeElements.set( name, nodeElement ); - console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime ); - valid = false; - break; +} - } +const parseSwizzle = ( props ) => props.replace( /r|s/g, 'x' ).replace( /g|t/g, 'y' ).replace( /b|p/g, 'z' ).replace( /a|q/g, 'w' ); +const parseSwizzleAndSort = ( props ) => parseSwizzle( props ).split( '' ).sort().join( '' ); - if ( prevTime !== null && prevTime > currTime ) { +const shaderNodeHandler = { - console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime ); - valid = false; - break; + setup( NodeClosure, params ) { - } + const inputs = params.shift(); - prevTime = currTime; + return NodeClosure( nodeObjects( inputs ), ...params ); - } + }, - if ( values !== undefined ) { + get( node, prop, nodeObj ) { - if ( isTypedArray( values ) ) { + if ( typeof prop === 'string' && node[ prop ] === undefined ) { - for ( let i = 0, n = values.length; i !== n; ++ i ) { + if ( node.isStackNode !== true && prop === 'assign' ) { - const value = values[ i ]; + return ( ...params ) => { - if ( isNaN( value ) ) { + currentStack.assign( nodeObj, ...params ); - console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value ); - valid = false; - break; + return nodeObj; - } + }; - } + } else if ( NodeElements.has( prop ) ) { - } + const nodeElement = NodeElements.get( prop ); - } + return node.isStackNode ? ( ...params ) => nodeObj.add( nodeElement( ...params ) ) : ( ...params ) => nodeElement( nodeObj, ...params ); - return valid; + } else if ( prop === 'self' ) { - } + return node; - // removes equivalent sequential keys as common in morph target sequences - // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0) - optimize() { + } else if ( prop.endsWith( 'Assign' ) && NodeElements.has( prop.slice( 0, prop.length - 'Assign'.length ) ) ) { - // times or values may be shared with other tracks, so overwriting is unsafe - const times = this.times.slice(), - values = this.values.slice(), - stride = this.getValueSize(), + const nodeElement = NodeElements.get( prop.slice( 0, prop.length - 'Assign'.length ) ); - smoothInterpolation = this.getInterpolation() === InterpolateSmooth, + return node.isStackNode ? ( ...params ) => nodeObj.assign( params[ 0 ], nodeElement( ...params ) ) : ( ...params ) => nodeObj.assign( nodeElement( nodeObj, ...params ) ); - lastIndex = times.length - 1; + } else if ( /^[xyzwrgbastpq]{1,4}$/.test( prop ) === true ) { - let writeIndex = 1; + // accessing properties ( swizzle ) - for ( let i = 1; i < lastIndex; ++ i ) { + prop = parseSwizzle( prop ); - let keep = false; + return nodeObject( new SplitNode( nodeObj, prop ) ); - const time = times[ i ]; - const timeNext = times[ i + 1 ]; + } else if ( /^set[XYZWRGBASTPQ]{1,4}$/.test( prop ) === true ) { - // remove adjacent keyframes scheduled at the same time + // set properties ( swizzle ) and sort to xyzw sequence - if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) { + prop = parseSwizzleAndSort( prop.slice( 3 ).toLowerCase() ); - if ( ! smoothInterpolation ) { + return ( value ) => nodeObject( new SetNode( node, prop, value ) ); - // remove unnecessary keyframes same as their neighbors + } else if ( /^flip[XYZWRGBASTPQ]{1,4}$/.test( prop ) === true ) { - const offset = i * stride, - offsetP = offset - stride, - offsetN = offset + stride; + // set properties ( swizzle ) and sort to xyzw sequence - for ( let j = 0; j !== stride; ++ j ) { + prop = parseSwizzleAndSort( prop.slice( 4 ).toLowerCase() ); - const value = values[ offset + j ]; + return () => nodeObject( new FlipNode( nodeObject( node ), prop ) ); - if ( value !== values[ offsetP + j ] || - value !== values[ offsetN + j ] ) { + } else if ( prop === 'width' || prop === 'height' || prop === 'depth' ) { - keep = true; - break; + // accessing property - } + if ( prop === 'width' ) prop = 'x'; + else if ( prop === 'height' ) prop = 'y'; + else if ( prop === 'depth' ) prop = 'z'; - } + return nodeObject( new SplitNode( node, prop ) ); - } else { + } else if ( /^\d+$/.test( prop ) === true ) { - keep = true; + // accessing array - } + return nodeObject( new ArrayElementNode( nodeObj, new ConstNode( Number( prop ), 'uint' ) ) ); } - // in-place compaction - - if ( keep ) { + } - if ( i !== writeIndex ) { + return Reflect.get( node, prop, nodeObj ); - times[ writeIndex ] = times[ i ]; + }, - const readOffset = i * stride, - writeOffset = writeIndex * stride; + set( node, prop, value, nodeObj ) { - for ( let j = 0; j !== stride; ++ j ) { + if ( typeof prop === 'string' && node[ prop ] === undefined ) { - values[ writeOffset + j ] = values[ readOffset + j ]; + // setting properties - } + if ( /^[xyzwrgbastpq]{1,4}$/.test( prop ) === true || prop === 'width' || prop === 'height' || prop === 'depth' || /^\d+$/.test( prop ) === true ) { - } + nodeObj[ prop ].assign( value ); - ++ writeIndex; + return true; } } - // flush last keyframe (compaction looks ahead) - - if ( lastIndex > 0 ) { + return Reflect.set( node, prop, value, nodeObj ); - times[ writeIndex ] = times[ lastIndex ]; + } - for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) { +}; - values[ writeOffset + j ] = values[ readOffset + j ]; +const nodeObjectsCacheMap = new WeakMap(); +const nodeBuilderFunctionsCacheMap = new WeakMap(); - } +const ShaderNodeObject = function ( obj, altType = null ) { - ++ writeIndex; + const type = getValueType( obj ); - } + if ( type === 'node' ) { - if ( writeIndex !== times.length ) { + let nodeObject = nodeObjectsCacheMap.get( obj ); - this.times = times.slice( 0, writeIndex ); - this.values = values.slice( 0, writeIndex * stride ); + if ( nodeObject === undefined ) { - } else { + nodeObject = new Proxy( obj, shaderNodeHandler ); - this.times = times; - this.values = values; + nodeObjectsCacheMap.set( obj, nodeObject ); + nodeObjectsCacheMap.set( nodeObject, nodeObject ); } - return this; - - } - - clone() { + return nodeObject; - const times = this.times.slice(); - const values = this.values.slice(); + } else if ( ( altType === null && ( type === 'float' || type === 'boolean' ) ) || ( type && type !== 'shader' && type !== 'string' ) ) { - const TypedKeyframeTrack = this.constructor; - const track = new TypedKeyframeTrack( this.name, times, values ); + return nodeObject( getConstNode( obj, altType ) ); - // Interpolant argument to constructor is not saved, so copy the factory method directly. - track.createInterpolant = this.createInterpolant; + } else if ( type === 'shader' ) { - return track; + return Fn( obj ); } -} + return obj; -KeyframeTrack.prototype.TimeBufferType = Float32Array; -KeyframeTrack.prototype.ValueBufferType = Float32Array; -KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear; +}; -/** - * A Track of Boolean keyframe values. - */ -class BooleanKeyframeTrack extends KeyframeTrack { +const ShaderNodeObjects = function ( objects, altType = null ) { - // No interpolation parameter because only InterpolateDiscrete is valid. - constructor( name, times, values ) { + for ( const name in objects ) { - super( name, times, values ); + objects[ name ] = nodeObject( objects[ name ], altType ); } -} + return objects; -BooleanKeyframeTrack.prototype.ValueTypeName = 'bool'; -BooleanKeyframeTrack.prototype.ValueBufferType = Array; -BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; -BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; -BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; +}; -/** - * A Track of keyframe values that represent color. - */ -class ColorKeyframeTrack extends KeyframeTrack {} +const ShaderNodeArray = function ( array, altType = null ) { -ColorKeyframeTrack.prototype.ValueTypeName = 'color'; + const len = array.length; -/** - * A Track of numeric keyframe values. - */ -class NumberKeyframeTrack extends KeyframeTrack {} + for ( let i = 0; i < len; i ++ ) { -NumberKeyframeTrack.prototype.ValueTypeName = 'number'; + array[ i ] = nodeObject( array[ i ], altType ); -/** - * Spherical linear unit quaternion interpolant. - */ + } -class QuaternionLinearInterpolant extends Interpolant { + return array; - constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { +}; - super( parameterPositions, sampleValues, sampleSize, resultBuffer ); +const ShaderNodeProxy = function ( NodeClass, scope = null, factor = null, settings = null ) { - } + const assignNode = ( node ) => nodeObject( settings !== null ? Object.assign( node, settings ) : node ); - interpolate_( i1, t0, t, t1 ) { + if ( scope === null ) { - const result = this.resultBuffer, - values = this.sampleValues, - stride = this.valueSize, + return ( ...params ) => { - alpha = ( t - t0 ) / ( t1 - t0 ); + return assignNode( new NodeClass( ...nodeArray( params ) ) ); - let offset = i1 * stride; + }; - for ( let end = offset + stride; offset !== end; offset += 4 ) { + } else if ( factor !== null ) { - Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha ); + factor = nodeObject( factor ); - } + return ( ...params ) => { - return result; + return assignNode( new NodeClass( scope, ...nodeArray( params ), factor ) ); - } + }; -} + } else { -/** - * A Track of quaternion keyframe values. - */ -class QuaternionKeyframeTrack extends KeyframeTrack { + return ( ...params ) => { - InterpolantFactoryMethodLinear( result ) { + return assignNode( new NodeClass( scope, ...nodeArray( params ) ) ); - return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result ); + }; } -} +}; -QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion'; -// ValueBufferType is inherited -// DefaultInterpolation is inherited; -QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; +const ShaderNodeImmutable = function ( NodeClass, ...params ) { -/** - * A Track that interpolates Strings - */ -class StringKeyframeTrack extends KeyframeTrack { + return nodeObject( new NodeClass( ...nodeArray( params ) ) ); - // No interpolation parameter because only InterpolateDiscrete is valid. - constructor( name, times, values ) { +}; - super( name, times, values ); +class ShaderCallNodeInternal extends Node { + + constructor( shaderNode, inputNodes ) { + + super(); + + this.shaderNode = shaderNode; + this.inputNodes = inputNodes; } -} + getNodeType( builder ) { -StringKeyframeTrack.prototype.ValueTypeName = 'string'; -StringKeyframeTrack.prototype.ValueBufferType = Array; -StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; -StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; -StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; + return this.shaderNode.nodeType || this.getOutputNode( builder ).getNodeType( builder ); -/** - * A Track of vectored keyframe values. - */ -class VectorKeyframeTrack extends KeyframeTrack {} + } -VectorKeyframeTrack.prototype.ValueTypeName = 'vector'; + call( builder ) { -class AnimationClip { + const { shaderNode, inputNodes } = this; - constructor( name = '', duration = - 1, tracks = [], blendMode = NormalAnimationBlendMode ) { + const properties = builder.getNodeProperties( shaderNode ); + if ( properties.onceOutput ) return properties.onceOutput; - this.name = name; - this.tracks = tracks; - this.duration = duration; - this.blendMode = blendMode; + // - this.uuid = generateUUID(); + let result = null; - // this means it should figure out its duration by scanning the tracks - if ( this.duration < 0 ) { + if ( shaderNode.layout ) { - this.resetDuration(); + let functionNodesCacheMap = nodeBuilderFunctionsCacheMap.get( builder.constructor ); - } + if ( functionNodesCacheMap === undefined ) { - } + functionNodesCacheMap = new WeakMap(); + nodeBuilderFunctionsCacheMap.set( builder.constructor, functionNodesCacheMap ); - static parse( json ) { + } - const tracks = [], - jsonTracks = json.tracks, - frameTime = 1.0 / ( json.fps || 1.0 ); + let functionNode = functionNodesCacheMap.get( shaderNode ); - for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) { + if ( functionNode === undefined ) { - tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) ); + functionNode = nodeObject( builder.buildFunctionNode( shaderNode ) ); - } + functionNodesCacheMap.set( shaderNode, functionNode ); - const clip = new this( json.name, json.duration, tracks, json.blendMode ); - clip.uuid = json.uuid; + } - return clip; + if ( builder.currentFunctionNode !== null ) { - } + builder.currentFunctionNode.includes.push( functionNode ); - static toJSON( clip ) { + } - const tracks = [], - clipTracks = clip.tracks; + result = nodeObject( functionNode.call( inputNodes ) ); - const json = { + } else { - 'name': clip.name, - 'duration': clip.duration, - 'tracks': tracks, - 'uuid': clip.uuid, - 'blendMode': clip.blendMode + const jsFunc = shaderNode.jsFunc; + const outputNode = inputNodes !== null ? jsFunc( inputNodes, builder ) : jsFunc( builder ); - }; + result = nodeObject( outputNode ); - for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) { + } - tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) ); + if ( shaderNode.once ) { + + properties.onceOutput = result; } - return json; + return result; } - static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) { + getOutputNode( builder ) { - const numMorphTargets = morphTargetSequence.length; - const tracks = []; + const properties = builder.getNodeProperties( this ); - for ( let i = 0; i < numMorphTargets; i ++ ) { + if ( properties.outputNode === null ) { - let times = []; - let values = []; + properties.outputNode = this.setupOutput( builder ); - times.push( - ( i + numMorphTargets - 1 ) % numMorphTargets, - i, - ( i + 1 ) % numMorphTargets ); + } - values.push( 0, 1, 0 ); + return properties.outputNode; - const order = getKeyframeOrder( times ); - times = sortedArray( times, 1, order ); - values = sortedArray( values, 1, order ); + } - // if there is a key at the first frame, duplicate it as the - // last frame as well for perfect loop. - if ( ! noLoop && times[ 0 ] === 0 ) { + setup( builder ) { - times.push( numMorphTargets ); - values.push( values[ 0 ] ); + return this.getOutputNode( builder ); - } + } - tracks.push( - new NumberKeyframeTrack( - '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']', - times, values - ).scale( 1.0 / fps ) ); + setupOutput( builder ) { - } + builder.addStack(); - return new this( name, - 1, tracks ); + builder.stack.outputNode = this.call( builder ); + + return builder.removeStack(); } - static findByName( objectOrClipArray, name ) { + generate( builder, output ) { - let clipArray = objectOrClipArray; + const outputNode = this.getOutputNode( builder ); - if ( ! Array.isArray( objectOrClipArray ) ) { + return outputNode.build( builder, output ); - const o = objectOrClipArray; - clipArray = o.geometry && o.geometry.animations || o.animations; + } - } +} - for ( let i = 0; i < clipArray.length; i ++ ) { +class ShaderNodeInternal extends Node { - if ( clipArray[ i ].name === name ) { + constructor( jsFunc, nodeType ) { - return clipArray[ i ]; + super( nodeType ); - } + this.jsFunc = jsFunc; + this.layout = null; - } + this.global = true; - return null; + this.once = false; } - static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) { + setLayout( layout ) { - const animationToMorphTargets = {}; + this.layout = layout; - // tested with https://regex101.com/ on trick sequences - // such flamingo_flyA_003, flamingo_run1_003, crdeath0059 - const pattern = /^([\w-]*?)([\d]+)$/; + return this; - // sort morph target names into animation groups based - // patterns like Walk_001, Walk_002, Run_001, Run_002 - for ( let i = 0, il = morphTargets.length; i < il; i ++ ) { + } - const morphTarget = morphTargets[ i ]; - const parts = morphTarget.name.match( pattern ); + call( inputs = null ) { - if ( parts && parts.length > 1 ) { + nodeObjects( inputs ); - const name = parts[ 1 ]; + return nodeObject( new ShaderCallNodeInternal( this, inputs ) ); - let animationMorphTargets = animationToMorphTargets[ name ]; + } - if ( ! animationMorphTargets ) { + setup() { - animationToMorphTargets[ name ] = animationMorphTargets = []; + return this.call(); - } + } - animationMorphTargets.push( morphTarget ); +} - } +const bools = [ false, true ]; +const uints = [ 0, 1, 2, 3 ]; +const ints = [ - 1, - 2 ]; +const floats = [ 0.5, 1.5, 1 / 3, 1e-6, 1e6, Math.PI, Math.PI * 2, 1 / Math.PI, 2 / Math.PI, 1 / ( Math.PI * 2 ), Math.PI / 2 ]; - } - - const clips = []; - - for ( const name in animationToMorphTargets ) { +const boolsCacheMap = new Map(); +for ( const bool of bools ) boolsCacheMap.set( bool, new ConstNode( bool ) ); - clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) ); +const uintsCacheMap = new Map(); +for ( const uint of uints ) uintsCacheMap.set( uint, new ConstNode( uint, 'uint' ) ); - } +const intsCacheMap = new Map( [ ...uintsCacheMap ].map( el => new ConstNode( el.value, 'int' ) ) ); +for ( const int of ints ) intsCacheMap.set( int, new ConstNode( int, 'int' ) ); - return clips; +const floatsCacheMap = new Map( [ ...intsCacheMap ].map( el => new ConstNode( el.value ) ) ); +for ( const float of floats ) floatsCacheMap.set( float, new ConstNode( float ) ); +for ( const float of floats ) floatsCacheMap.set( - float, new ConstNode( - float ) ); - } +const cacheMaps = { bool: boolsCacheMap, uint: uintsCacheMap, ints: intsCacheMap, float: floatsCacheMap }; - // parse the animation.hierarchy format - static parseAnimation( animation, bones ) { +const constNodesCacheMap = new Map( [ ...boolsCacheMap, ...floatsCacheMap ] ); - if ( ! animation ) { +const getConstNode = ( value, type ) => { - console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' ); - return null; + if ( constNodesCacheMap.has( value ) ) { - } + return constNodesCacheMap.get( value ); - const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) { + } else if ( value.isNode === true ) { - // only return track if there are actually keys. - if ( animationKeys.length !== 0 ) { + return value; - const times = []; - const values = []; + } else { - flattenJSON( animationKeys, times, values, propertyName ); + return new ConstNode( value, type ); - // empty keys are filtered out, so check again - if ( times.length !== 0 ) { + } - destTracks.push( new trackType( trackName, times, values ) ); +}; - } +const safeGetNodeType = ( node ) => { - } + try { - }; + return node.getNodeType(); - const tracks = []; + } catch ( _ ) { - const clipName = animation.name || 'default'; - const fps = animation.fps || 30; - const blendMode = animation.blendMode; + return undefined; - // automatic length determination in AnimationClip. - let duration = animation.length || - 1; + } - const hierarchyTracks = animation.hierarchy || []; +}; - for ( let h = 0; h < hierarchyTracks.length; h ++ ) { +const ConvertType = function ( type, cacheMap = null ) { - const animationKeys = hierarchyTracks[ h ].keys; + return ( ...params ) => { - // skip empty tracks - if ( ! animationKeys || animationKeys.length === 0 ) continue; + if ( params.length === 0 || ( ! [ 'bool', 'float', 'int', 'uint' ].includes( type ) && params.every( param => typeof param !== 'object' ) ) ) { - // process morph targets - if ( animationKeys[ 0 ].morphTargets ) { + params = [ getValueFromType( type, ...params ) ]; - // figure out all morph targets used in this track - const morphTargetNames = {}; + } - let k; + if ( params.length === 1 && cacheMap !== null && cacheMap.has( params[ 0 ] ) ) { - for ( k = 0; k < animationKeys.length; k ++ ) { + return nodeObject( cacheMap.get( params[ 0 ] ) ); - if ( animationKeys[ k ].morphTargets ) { + } - for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) { + if ( params.length === 1 ) { - morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1; + const node = getConstNode( params[ 0 ], type ); + if ( safeGetNodeType( node ) === type ) return nodeObject( node ); + return nodeObject( new ConvertNode( node, type ) ); - } + } - } + const nodes = params.map( param => getConstNode( param ) ); + return nodeObject( new JoinNode( nodes, type ) ); - } + }; - // create a track for each morph target with all zero - // morphTargetInfluences except for the keys in which - // the morphTarget is named. - for ( const morphTargetName in morphTargetNames ) { +}; - const times = []; - const values = []; +// exports - for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) { +const defined = ( v ) => typeof v === 'object' && v !== null ? v.value : v; // TODO: remove boolean conversion and defined function - const animationKey = animationKeys[ k ]; +// utils - times.push( animationKey.time ); - values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 ); +const getConstNodeType = ( value ) => ( value !== undefined && value !== null ) ? ( value.nodeType || value.convertTo || ( typeof value === 'string' ? value : null ) ) : null; - } +// shader node base - tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) ); +function ShaderNode( jsFunc, nodeType ) { - } + return new Proxy( new ShaderNodeInternal( jsFunc, nodeType ), shaderNodeHandler ); - duration = morphTargetNames.length * fps; +} - } else { +const nodeObject = ( val, altType = null ) => /* new */ ShaderNodeObject( val, altType ); +const nodeObjects = ( val, altType = null ) => new ShaderNodeObjects( val, altType ); +const nodeArray = ( val, altType = null ) => new ShaderNodeArray( val, altType ); +const nodeProxy = ( ...params ) => new ShaderNodeProxy( ...params ); +const nodeImmutable = ( ...params ) => new ShaderNodeImmutable( ...params ); - // ...assume skeletal animation +const Fn = ( jsFunc, nodeType ) => { - const boneName = '.bones[' + bones[ h ].name + ']'; + const shaderNode = new ShaderNode( jsFunc, nodeType ); - addNonemptyTrack( - VectorKeyframeTrack, boneName + '.position', - animationKeys, 'pos', tracks ); + const fn = ( ...params ) => { - addNonemptyTrack( - QuaternionKeyframeTrack, boneName + '.quaternion', - animationKeys, 'rot', tracks ); + let inputs; - addNonemptyTrack( - VectorKeyframeTrack, boneName + '.scale', - animationKeys, 'scl', tracks ); + nodeObjects( params ); - } + if ( params[ 0 ] && params[ 0 ].isNode ) { - } + inputs = [ ...params ]; - if ( tracks.length === 0 ) { + } else { - return null; + inputs = params[ 0 ]; } - const clip = new this( clipName, duration, tracks, blendMode ); - - return clip; - - } - - resetDuration() { - - const tracks = this.tracks; - let duration = 0; + return shaderNode.call( inputs ); - for ( let i = 0, n = tracks.length; i !== n; ++ i ) { + }; - const track = this.tracks[ i ]; + fn.shaderNode = shaderNode; - duration = Math.max( duration, track.times[ track.times.length - 1 ] ); + fn.setLayout = ( layout ) => { - } + shaderNode.setLayout( layout ); - this.duration = duration; + return fn; - return this; + }; - } + fn.once = () => { - trim() { + shaderNode.once = true; - for ( let i = 0; i < this.tracks.length; i ++ ) { + return fn; - this.tracks[ i ].trim( 0, this.duration ); + }; - } + return fn; - return this; +}; - } +const tslFn = ( ...params ) => { // @deprecated, r168 - validate() { + console.warn( 'TSL.ShaderNode: tslFn() has been renamed to Fn().' ); + return Fn( ...params ); - let valid = true; +}; - for ( let i = 0; i < this.tracks.length; i ++ ) { +// - valid = valid && this.tracks[ i ].validate(); +addMethodChaining( 'toGlobal', ( node ) => { - } + node.global = true; - return valid; + return node; - } +} ); - optimize() { +// - for ( let i = 0; i < this.tracks.length; i ++ ) { +const setCurrentStack = ( stack ) => { - this.tracks[ i ].optimize(); + currentStack = stack; - } +}; - return this; +const getCurrentStack = () => currentStack; - } +const If = ( ...params ) => currentStack.If( ...params ); - clone() { +function append( node ) { - const tracks = []; + if ( currentStack ) currentStack.add( node ); - for ( let i = 0; i < this.tracks.length; i ++ ) { + return node; - tracks.push( this.tracks[ i ].clone() ); +} - } +addMethodChaining( 'append', append ); - return new this.constructor( this.name, this.duration, tracks, this.blendMode ); +// types - } +const color = new ConvertType( 'color' ); - toJSON() { +const float = new ConvertType( 'float', cacheMaps.float ); +const int = new ConvertType( 'int', cacheMaps.ints ); +const uint = new ConvertType( 'uint', cacheMaps.uint ); +const bool = new ConvertType( 'bool', cacheMaps.bool ); - return this.constructor.toJSON( this ); +const vec2 = new ConvertType( 'vec2' ); +const ivec2 = new ConvertType( 'ivec2' ); +const uvec2 = new ConvertType( 'uvec2' ); +const bvec2 = new ConvertType( 'bvec2' ); - } +const vec3 = new ConvertType( 'vec3' ); +const ivec3 = new ConvertType( 'ivec3' ); +const uvec3 = new ConvertType( 'uvec3' ); +const bvec3 = new ConvertType( 'bvec3' ); -} +const vec4 = new ConvertType( 'vec4' ); +const ivec4 = new ConvertType( 'ivec4' ); +const uvec4 = new ConvertType( 'uvec4' ); +const bvec4 = new ConvertType( 'bvec4' ); -function getTrackTypeForValueTypeName( typeName ) { +const mat2 = new ConvertType( 'mat2' ); +const mat3 = new ConvertType( 'mat3' ); +const mat4 = new ConvertType( 'mat4' ); - switch ( typeName.toLowerCase() ) { +const string = ( value = '' ) => nodeObject( new ConstNode( value, 'string' ) ); +const arrayBuffer = ( value ) => nodeObject( new ConstNode( value, 'ArrayBuffer' ) ); - case 'scalar': - case 'double': - case 'float': - case 'number': - case 'integer': +addMethodChaining( 'toColor', color ); +addMethodChaining( 'toFloat', float ); +addMethodChaining( 'toInt', int ); +addMethodChaining( 'toUint', uint ); +addMethodChaining( 'toBool', bool ); +addMethodChaining( 'toVec2', vec2 ); +addMethodChaining( 'toIVec2', ivec2 ); +addMethodChaining( 'toUVec2', uvec2 ); +addMethodChaining( 'toBVec2', bvec2 ); +addMethodChaining( 'toVec3', vec3 ); +addMethodChaining( 'toIVec3', ivec3 ); +addMethodChaining( 'toUVec3', uvec3 ); +addMethodChaining( 'toBVec3', bvec3 ); +addMethodChaining( 'toVec4', vec4 ); +addMethodChaining( 'toIVec4', ivec4 ); +addMethodChaining( 'toUVec4', uvec4 ); +addMethodChaining( 'toBVec4', bvec4 ); +addMethodChaining( 'toMat2', mat2 ); +addMethodChaining( 'toMat3', mat3 ); +addMethodChaining( 'toMat4', mat4 ); - return NumberKeyframeTrack; +// basic nodes - case 'vector': - case 'vector2': - case 'vector3': - case 'vector4': +const element = /*@__PURE__*/ nodeProxy( ArrayElementNode ); +const convert = ( node, types ) => nodeObject( new ConvertNode( nodeObject( node ), types ) ); +const split = ( node, channels ) => nodeObject( new SplitNode( nodeObject( node ), channels ) ); - return VectorKeyframeTrack; +addMethodChaining( 'element', element ); +addMethodChaining( 'convert', convert ); - case 'color': +class UniformGroupNode extends Node { - return ColorKeyframeTrack; + static get type() { - case 'quaternion': + return 'UniformGroupNode'; - return QuaternionKeyframeTrack; + } - case 'bool': - case 'boolean': + constructor( name, shared = false, order = 1 ) { - return BooleanKeyframeTrack; + super( 'string' ); - case 'string': + this.name = name; + this.version = 0; - return StringKeyframeTrack; + this.shared = shared; + this.order = order; + this.isUniformGroup = true; } - throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName ); - -} - -function parseKeyframeTrack( json ) { - - if ( json.type === undefined ) { + set needsUpdate( value ) { - throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' ); + if ( value === true ) this.version ++; } - const trackType = getTrackTypeForValueTypeName( json.type ); - - if ( json.times === undefined ) { - - const times = [], values = []; + serialize( data ) { - flattenJSON( json.keys, times, values, 'value' ); + super.serialize( data ); - json.times = times; - json.values = values; + data.name = this.name; + data.version = this.version; + data.shared = this.shared; } - // derived classes can define a static parse method - if ( trackType.parse !== undefined ) { - - return trackType.parse( json ); + deserialize( data ) { - } else { + super.deserialize( data ); - // by default, we assume a constructor compatible with the base - return new trackType( json.name, json.times, json.values, json.interpolation ); + this.name = data.name; + this.version = data.version; + this.shared = data.shared; } } -const Cache = { +const uniformGroup = ( name ) => new UniformGroupNode( name ); +const sharedUniformGroup = ( name, order = 0 ) => new UniformGroupNode( name, true, order ); - enabled: false, +const frameGroup = /*@__PURE__*/ sharedUniformGroup( 'frame' ); +const renderGroup = /*@__PURE__*/ sharedUniformGroup( 'render' ); +const objectGroup = /*@__PURE__*/ uniformGroup( 'object' ); - files: {}, +class UniformNode extends InputNode { - add: function ( key, file ) { + static get type() { - if ( this.enabled === false ) return; + return 'UniformNode'; - // console.log( 'THREE.Cache', 'Adding key:', key ); + } - this.files[ key ] = file; + constructor( value, nodeType = null ) { - }, + super( value, nodeType ); - get: function ( key ) { + this.isUniformNode = true; - if ( this.enabled === false ) return; + this.name = ''; + this.groupNode = objectGroup; - // console.log( 'THREE.Cache', 'Checking key:', key ); + } - return this.files[ key ]; + label( name ) { - }, + this.name = name; - remove: function ( key ) { + return this; - delete this.files[ key ]; + } - }, + setGroup( group ) { - clear: function () { + this.groupNode = group; - this.files = {}; + return this; } -}; + getGroup() { -class LoadingManager { + return this.groupNode; - constructor( onLoad, onProgress, onError ) { + } - const scope = this; + getUniformHash( builder ) { - let isLoading = false; - let itemsLoaded = 0; - let itemsTotal = 0; - let urlModifier = undefined; - const handlers = []; + return this.getHash( builder ); - // Refer to #5689 for the reason why we don't set .onStart - // in the constructor + } - this.onStart = undefined; - this.onLoad = onLoad; - this.onProgress = onProgress; - this.onError = onError; + onUpdate( callback, updateType ) { - this.itemStart = function ( url ) { + const self = this.getSelf(); - itemsTotal ++; + callback = callback.bind( self ); - if ( isLoading === false ) { + return super.onUpdate( ( frame ) => { - if ( scope.onStart !== undefined ) { + const value = callback( frame, self ); - scope.onStart( url, itemsLoaded, itemsTotal ); + if ( value !== undefined ) { - } + this.value = value; } - isLoading = true; - - }; - - this.itemEnd = function ( url ) { + }, updateType ); - itemsLoaded ++; + } - if ( scope.onProgress !== undefined ) { + generate( builder, output ) { - scope.onProgress( url, itemsLoaded, itemsTotal ); + const type = this.getNodeType( builder ); - } + const hash = this.getUniformHash( builder ); - if ( itemsLoaded === itemsTotal ) { + let sharedNode = builder.getNodeFromHash( hash ); - isLoading = false; + if ( sharedNode === undefined ) { - if ( scope.onLoad !== undefined ) { + builder.setHashNode( this, hash ); - scope.onLoad(); + sharedNode = this; - } + } - } + const sharedNodeType = sharedNode.getInputType( builder ); - }; + const nodeUniform = builder.getUniformFromNode( sharedNode, sharedNodeType, builder.shaderStage, this.name || builder.context.label ); + const propertyName = builder.getPropertyName( nodeUniform ); - this.itemError = function ( url ) { + if ( builder.context.label !== undefined ) delete builder.context.label; - if ( scope.onError !== undefined ) { + return builder.format( propertyName, type, output ); - scope.onError( url ); + } - } +} - }; +const uniform = ( arg1, arg2 ) => { - this.resolveURL = function ( url ) { + const nodeType = getConstNodeType( arg2 || arg1 ); - if ( urlModifier ) { + // @TODO: get ConstNode from .traverse() in the future + const value = ( arg1 && arg1.isNode === true ) ? ( arg1.node && arg1.node.value ) || arg1.value : arg1; - return urlModifier( url ); + return nodeObject( new UniformNode( value, nodeType ) ); - } +}; - return url; +class PropertyNode extends Node { - }; + static get type() { - this.setURLModifier = function ( transform ) { + return 'PropertyNode'; - urlModifier = transform; + } - return this; + constructor( nodeType, name = null, varying = false ) { - }; + super( nodeType ); - this.addHandler = function ( regex, loader ) { + this.name = name; + this.varying = varying; - handlers.push( regex, loader ); + this.isPropertyNode = true; - return this; + } - }; + getHash( builder ) { - this.removeHandler = function ( regex ) { + return this.name || super.getHash( builder ); - const index = handlers.indexOf( regex ); + } - if ( index !== - 1 ) { + isGlobal( /*builder*/ ) { - handlers.splice( index, 2 ); + return true; - } + } - return this; + generate( builder ) { - }; + let nodeVar; - this.getHandler = function ( file ) { + if ( this.varying === true ) { - for ( let i = 0, l = handlers.length; i < l; i += 2 ) { + nodeVar = builder.getVaryingFromNode( this, this.name ); + nodeVar.needsInterpolation = true; - const regex = handlers[ i ]; - const loader = handlers[ i + 1 ]; + } else { - if ( regex.global ) regex.lastIndex = 0; // see #17920 + nodeVar = builder.getVarFromNode( this, this.name ); - if ( regex.test( file ) ) { + } - return loader; + return builder.getPropertyName( nodeVar ); - } + } - } +} - return null; +const property = ( type, name ) => nodeObject( new PropertyNode( type, name ) ); +const varyingProperty = ( type, name ) => nodeObject( new PropertyNode( type, name, true ) ); - }; +const diffuseColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec4', 'DiffuseColor' ); +const emissive = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'EmissiveColor' ); +const roughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Roughness' ); +const metalness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Metalness' ); +const clearcoat = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Clearcoat' ); +const clearcoatRoughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'ClearcoatRoughness' ); +const sheen = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'Sheen' ); +const sheenRoughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'SheenRoughness' ); +const iridescence = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Iridescence' ); +const iridescenceIOR = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IridescenceIOR' ); +const iridescenceThickness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IridescenceThickness' ); +const alphaT = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'AlphaT' ); +const anisotropy = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Anisotropy' ); +const anisotropyT = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'AnisotropyT' ); +const anisotropyB = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'AnisotropyB' ); +const specularColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'color', 'SpecularColor' ); +const specularF90 = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'SpecularF90' ); +const shininess = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Shininess' ); +const output = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec4', 'Output' ); +const dashSize = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'dashSize' ); +const gapSize = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'gapSize' ); +const pointWidth = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'pointWidth' ); +const ior = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IOR' ); +const transmission = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Transmission' ); +const thickness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Thickness' ); +const attenuationDistance = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'AttenuationDistance' ); +const attenuationColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'color', 'AttenuationColor' ); +const dispersion = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Dispersion' ); - } +class AssignNode extends TempNode { -} + static get type() { -const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager(); + return 'AssignNode'; -class Loader { + } - constructor( manager ) { + constructor( targetNode, sourceNode ) { - this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + super(); - this.crossOrigin = 'anonymous'; - this.withCredentials = false; - this.path = ''; - this.resourcePath = ''; - this.requestHeader = {}; + this.targetNode = targetNode; + this.sourceNode = sourceNode; } - load( /* url, onLoad, onProgress, onError */ ) {} - - loadAsync( url, onProgress ) { + hasDependencies() { - const scope = this; + return false; - return new Promise( function ( resolve, reject ) { + } - scope.load( url, resolve, onProgress, reject ); + getNodeType( builder, output ) { - } ); + return output !== 'void' ? this.targetNode.getNodeType( builder ) : 'void'; } - parse( /* data */ ) {} + needsSplitAssign( builder ) { - setCrossOrigin( crossOrigin ) { + const { targetNode } = this; - this.crossOrigin = crossOrigin; - return this; + if ( builder.isAvailable( 'swizzleAssign' ) === false && targetNode.isSplitNode && targetNode.components.length > 1 ) { - } + const targetLength = builder.getTypeLength( targetNode.node.getNodeType( builder ) ); + const assignDiferentVector = vectorComponents.join( '' ).slice( 0, targetLength ) !== targetNode.components; - setWithCredentials( value ) { + return assignDiferentVector; - this.withCredentials = value; - return this; + } - } + return false; - setPath( path ) { + } - this.path = path; - return this; + generate( builder, output ) { - } + const { targetNode, sourceNode } = this; - setResourcePath( resourcePath ) { + const needsSplitAssign = this.needsSplitAssign( builder ); - this.resourcePath = resourcePath; - return this; + const targetType = targetNode.getNodeType( builder ); - } + const target = targetNode.context( { assign: true } ).build( builder ); + const source = sourceNode.build( builder, targetType ); - setRequestHeader( requestHeader ) { + const sourceType = sourceNode.getNodeType( builder ); - this.requestHeader = requestHeader; - return this; + const nodeData = builder.getDataFromNode( this ); - } + // -} + let snippet; -Loader.DEFAULT_MATERIAL_NAME = '__DEFAULT'; + if ( nodeData.initialized === true ) { -const loading = {}; + if ( output !== 'void' ) { -class HttpError extends Error { + snippet = target; - constructor( message, response ) { + } - super( message ); - this.response = response; + } else if ( needsSplitAssign ) { - } + const sourceVar = builder.getVarFromNode( this, null, targetType ); + const sourceProperty = builder.getPropertyName( sourceVar ); -} + builder.addLineFlowCode( `${ sourceProperty } = ${ source }`, this ); -class FileLoader extends Loader { + const targetRoot = targetNode.node.context( { assign: true } ).build( builder ); - constructor( manager ) { + for ( let i = 0; i < targetNode.components.length; i ++ ) { - super( manager ); + const component = targetNode.components[ i ]; - } + builder.addLineFlowCode( `${ targetRoot }.${ component } = ${ sourceProperty }[ ${ i } ]`, this ); - load( url, onLoad, onProgress, onError ) { + } - if ( url === undefined ) url = ''; + if ( output !== 'void' ) { - if ( this.path !== undefined ) url = this.path + url; + snippet = target; - url = this.manager.resolveURL( url ); + } - const cached = Cache.get( url ); + } else { - if ( cached !== undefined ) { + snippet = `${ target } = ${ source }`; - this.manager.itemStart( url ); + if ( output === 'void' || sourceType === 'void' ) { - setTimeout( () => { + builder.addLineFlowCode( snippet, this ); - if ( onLoad ) onLoad( cached ); + if ( output !== 'void' ) { - this.manager.itemEnd( url ); + snippet = target; - }, 0 ); + } - return cached; + } } - // Check if request is duplicate + nodeData.initialized = true; - if ( loading[ url ] !== undefined ) { + return builder.format( snippet, targetType, output ); - loading[ url ].push( { + } - onLoad: onLoad, - onProgress: onProgress, - onError: onError +} - } ); +const assign = /*@__PURE__*/ nodeProxy( AssignNode ); - return; +addMethodChaining( 'assign', assign ); - } +class FunctionCallNode extends TempNode { - // Initialise array for duplicate requests - loading[ url ] = []; + static get type() { - loading[ url ].push( { - onLoad: onLoad, - onProgress: onProgress, - onError: onError, - } ); + return 'FunctionCallNode'; - // create request - const req = new Request( url, { - headers: new Headers( this.requestHeader ), - credentials: this.withCredentials ? 'include' : 'same-origin', - // An abort controller could be added within a future PR - } ); + } - // record states ( avoid data race ) - const mimeType = this.mimeType; - const responseType = this.responseType; + constructor( functionNode = null, parameters = {} ) { - // start the fetch - fetch( req ) - .then( response => { + super(); - if ( response.status === 200 || response.status === 0 ) { + this.functionNode = functionNode; + this.parameters = parameters; - // Some browsers return HTTP Status 0 when using non-http protocol - // e.g. 'file://' or 'data://'. Handle as success. + } - if ( response.status === 0 ) { + setParameters( parameters ) { - console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); + this.parameters = parameters; - } + return this; - // Workaround: Checking if response.body === undefined for Alipay browser #23548 + } - if ( typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined ) { + getParameters() { - return response; + return this.parameters; - } + } - const callbacks = loading[ url ]; - const reader = response.body.getReader(); + getNodeType( builder ) { - // Nginx needs X-File-Size check - // https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content - const contentLength = response.headers.get( 'X-File-Size' ) || response.headers.get( 'Content-Length' ); - const total = contentLength ? parseInt( contentLength ) : 0; - const lengthComputable = total !== 0; - let loaded = 0; + return this.functionNode.getNodeType( builder ); - // periodically read data into the new stream tracking while download progress - const stream = new ReadableStream( { - start( controller ) { + } - readData(); + generate( builder ) { - function readData() { + const params = []; - reader.read().then( ( { done, value } ) => { + const functionNode = this.functionNode; - if ( done ) { + const inputs = functionNode.getInputs( builder ); + const parameters = this.parameters; - controller.close(); + if ( Array.isArray( parameters ) ) { - } else { + for ( let i = 0; i < parameters.length; i ++ ) { - loaded += value.byteLength; + const inputNode = inputs[ i ]; + const node = parameters[ i ]; - const event = new ProgressEvent( 'progress', { lengthComputable, loaded, total } ); - for ( let i = 0, il = callbacks.length; i < il; i ++ ) { + params.push( node.build( builder, inputNode.type ) ); - const callback = callbacks[ i ]; - if ( callback.onProgress ) callback.onProgress( event ); + } - } + } else { - controller.enqueue( value ); - readData(); + for ( const inputNode of inputs ) { - } + const node = parameters[ inputNode.name ]; - }, ( e ) => { + if ( node !== undefined ) { - controller.error( e ); + params.push( node.build( builder, inputNode.type ) ); - } ); + } else { - } + throw new Error( `FunctionCallNode: Input '${inputNode.name}' not found in FunctionNode.` ); - } + } - } ); + } - return new Response( stream ); + } - } else { + const functionName = functionNode.build( builder, 'property' ); - throw new HttpError( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response ); + return `${functionName}( ${params.join( ', ' )} )`; - } + } - } ) - .then( response => { +} - switch ( responseType ) { +const call = ( func, ...params ) => { - case 'arraybuffer': + params = params.length > 1 || ( params[ 0 ] && params[ 0 ].isNode === true ) ? nodeArray( params ) : nodeObjects( params[ 0 ] ); - return response.arrayBuffer(); + return nodeObject( new FunctionCallNode( nodeObject( func ), params ) ); - case 'blob': +}; - return response.blob(); +addMethodChaining( 'call', call ); - case 'document': +class OperatorNode extends TempNode { - return response.text() - .then( text => { + static get type() { - const parser = new DOMParser(); - return parser.parseFromString( text, mimeType ); + return 'OperatorNode'; - } ); + } - case 'json': + constructor( op, aNode, bNode, ...params ) { - return response.json(); + super(); - default: + if ( params.length > 0 ) { - if ( mimeType === undefined ) { + let finalOp = new OperatorNode( op, aNode, bNode ); - return response.text(); + for ( let i = 0; i < params.length - 1; i ++ ) { - } else { + finalOp = new OperatorNode( op, finalOp, params[ i ] ); - // sniff encoding - const re = /charset="?([^;"\s]*)"?/i; - const exec = re.exec( mimeType ); - const label = exec && exec[ 1 ] ? exec[ 1 ].toLowerCase() : undefined; - const decoder = new TextDecoder( label ); - return response.arrayBuffer().then( ab => decoder.decode( ab ) ); + } - } + aNode = finalOp; + bNode = params[ params.length - 1 ]; - } + } - } ) - .then( data => { + this.op = op; + this.aNode = aNode; + this.bNode = bNode; - // Add to cache only on HTTP success, so that we do not cache - // error response bodies as proper responses to requests. - Cache.add( url, data ); + } - const callbacks = loading[ url ]; - delete loading[ url ]; + getNodeType( builder, output ) { - for ( let i = 0, il = callbacks.length; i < il; i ++ ) { + const op = this.op; - const callback = callbacks[ i ]; - if ( callback.onLoad ) callback.onLoad( data ); + const aNode = this.aNode; + const bNode = this.bNode; - } + const typeA = aNode.getNodeType( builder ); + const typeB = typeof bNode !== 'undefined' ? bNode.getNodeType( builder ) : null; - } ) - .catch( err => { + if ( typeA === 'void' || typeB === 'void' ) { - // Abort errors and other errors are handled the same + return 'void'; - const callbacks = loading[ url ]; + } else if ( op === '%' ) { - if ( callbacks === undefined ) { + return typeA; - // When onLoad was called and url was deleted in `loading` - this.manager.itemError( url ); - throw err; + } else if ( op === '~' || op === '&' || op === '|' || op === '^' || op === '>>' || op === '<<' ) { - } + return builder.getIntegerType( typeA ); - delete loading[ url ]; + } else if ( op === '!' || op === '==' || op === '&&' || op === '||' || op === '^^' ) { - for ( let i = 0, il = callbacks.length; i < il; i ++ ) { + return 'bool'; - const callback = callbacks[ i ]; - if ( callback.onError ) callback.onError( err ); + } else if ( op === '<' || op === '>' || op === '<=' || op === '>=' ) { - } + const typeLength = output ? builder.getTypeLength( output ) : Math.max( builder.getTypeLength( typeA ), builder.getTypeLength( typeB ) ); - this.manager.itemError( url ); + return typeLength > 1 ? `bvec${ typeLength }` : 'bool'; - } ) - .finally( () => { + } else { - this.manager.itemEnd( url ); + if ( typeA === 'float' && builder.isMatrix( typeB ) ) { - } ); + return typeB; - this.manager.itemStart( url ); + } else if ( builder.isMatrix( typeA ) && builder.isVector( typeB ) ) { - } + // matrix x vector - setResponseType( value ) { + return builder.getVectorFromMatrix( typeA ); - this.responseType = value; - return this; + } else if ( builder.isVector( typeA ) && builder.isMatrix( typeB ) ) { - } + // vector x matrix - setMimeType( value ) { + return builder.getVectorFromMatrix( typeB ); - this.mimeType = value; - return this; + } else if ( builder.getTypeLength( typeB ) > builder.getTypeLength( typeA ) ) { - } + // anytype x anytype: use the greater length vector -} + return typeB; -class AnimationLoader extends Loader { + } - constructor( manager ) { + return typeA; - super( manager ); + } } - load( url, onLoad, onProgress, onError ) { - - const scope = this; - - const loader = new FileLoader( this.manager ); - loader.setPath( this.path ); - loader.setRequestHeader( this.requestHeader ); - loader.setWithCredentials( this.withCredentials ); - loader.load( url, function ( text ) { + generate( builder, output ) { - try { + const op = this.op; - onLoad( scope.parse( JSON.parse( text ) ) ); + const aNode = this.aNode; + const bNode = this.bNode; - } catch ( e ) { + const type = this.getNodeType( builder, output ); - if ( onError ) { + let typeA = null; + let typeB = null; - onError( e ); + if ( type !== 'void' ) { - } else { + typeA = aNode.getNodeType( builder ); + typeB = typeof bNode !== 'undefined' ? bNode.getNodeType( builder ) : null; - console.error( e ); + if ( op === '<' || op === '>' || op === '<=' || op === '>=' || op === '==' ) { - } + if ( builder.isVector( typeA ) ) { - scope.manager.itemError( url ); + typeB = typeA; - } + } else if ( typeA !== typeB ) { - }, onProgress, onError ); + typeA = typeB = 'float'; - } + } - parse( json ) { + } else if ( op === '>>' || op === '<<' ) { - const animations = []; + typeA = type; + typeB = builder.changeComponentType( typeB, 'uint' ); - for ( let i = 0; i < json.length; i ++ ) { + } else if ( builder.isMatrix( typeA ) && builder.isVector( typeB ) ) { - const clip = AnimationClip.parse( json[ i ] ); + // matrix x vector - animations.push( clip ); + typeB = builder.getVectorFromMatrix( typeA ); - } + } else if ( builder.isVector( typeA ) && builder.isMatrix( typeB ) ) { - return animations; + // vector x matrix - } + typeA = builder.getVectorFromMatrix( typeB ); -} + } else { -/** - * Abstract Base class to block based textures loader (dds, pvr, ...) - * - * Sub classes have to implement the parse() method which will be used in load(). - */ + // anytype x anytype -class CompressedTextureLoader extends Loader { + typeA = typeB = type; - constructor( manager ) { + } - super( manager ); + } else { - } + typeA = typeB = type; - load( url, onLoad, onProgress, onError ) { + } - const scope = this; + const a = aNode.build( builder, typeA ); + const b = typeof bNode !== 'undefined' ? bNode.build( builder, typeB ) : null; - const images = []; + const outputLength = builder.getTypeLength( output ); + const fnOpSnippet = builder.getFunctionOperator( op ); - const texture = new CompressedTexture(); + if ( output !== 'void' ) { - const loader = new FileLoader( this.manager ); - loader.setPath( this.path ); - loader.setResponseType( 'arraybuffer' ); - loader.setRequestHeader( this.requestHeader ); - loader.setWithCredentials( scope.withCredentials ); + if ( op === '<' && outputLength > 1 ) { - let loaded = 0; + if ( builder.useComparisonMethod ) { - function loadTexture( i ) { + return builder.format( `${ builder.getMethod( 'lessThan', output ) }( ${ a }, ${ b } )`, type, output ); - loader.load( url[ i ], function ( buffer ) { + } else { - const texDatas = scope.parse( buffer, true ); + return builder.format( `( ${ a } < ${ b } )`, type, output ); - images[ i ] = { - width: texDatas.width, - height: texDatas.height, - format: texDatas.format, - mipmaps: texDatas.mipmaps - }; + } - loaded += 1; + } else if ( op === '<=' && outputLength > 1 ) { - if ( loaded === 6 ) { + if ( builder.useComparisonMethod ) { - if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter; + return builder.format( `${ builder.getMethod( 'lessThanEqual', output ) }( ${ a }, ${ b } )`, type, output ); - texture.image = images; - texture.format = texDatas.format; - texture.needsUpdate = true; + } else { - if ( onLoad ) onLoad( texture ); + return builder.format( `( ${ a } <= ${ b } )`, type, output ); } - }, onProgress, onError ); + } else if ( op === '>' && outputLength > 1 ) { - } + if ( builder.useComparisonMethod ) { - if ( Array.isArray( url ) ) { + return builder.format( `${ builder.getMethod( 'greaterThan', output ) }( ${ a }, ${ b } )`, type, output ); - for ( let i = 0, il = url.length; i < il; ++ i ) { + } else { - loadTexture( i ); - - } - - } else { - - // compressed cubemap texture stored in a single DDS file + return builder.format( `( ${ a } > ${ b } )`, type, output ); - loader.load( url, function ( buffer ) { + } - const texDatas = scope.parse( buffer, true ); + } else if ( op === '>=' && outputLength > 1 ) { - if ( texDatas.isCubemap ) { + if ( builder.useComparisonMethod ) { - const faces = texDatas.mipmaps.length / texDatas.mipmapCount; + return builder.format( `${ builder.getMethod( 'greaterThanEqual', output ) }( ${ a }, ${ b } )`, type, output ); - for ( let f = 0; f < faces; f ++ ) { + } else { - images[ f ] = { mipmaps: [] }; + return builder.format( `( ${ a } >= ${ b } )`, type, output ); - for ( let i = 0; i < texDatas.mipmapCount; i ++ ) { + } - images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] ); - images[ f ].format = texDatas.format; - images[ f ].width = texDatas.width; - images[ f ].height = texDatas.height; + } else if ( op === '!' || op === '~' ) { - } + return builder.format( `(${op}${a})`, typeA, output ); - } + } else if ( fnOpSnippet ) { - texture.image = images; + return builder.format( `${ fnOpSnippet }( ${ a }, ${ b } )`, type, output ); - } else { + } else { - texture.image.width = texDatas.width; - texture.image.height = texDatas.height; - texture.mipmaps = texDatas.mipmaps; + return builder.format( `( ${ a } ${ op } ${ b } )`, type, output ); - } + } - if ( texDatas.mipmapCount === 1 ) { + } else if ( typeA !== 'void' ) { - texture.minFilter = LinearFilter; + if ( fnOpSnippet ) { - } + return builder.format( `${ fnOpSnippet }( ${ a }, ${ b } )`, type, output ); - texture.format = texDatas.format; - texture.needsUpdate = true; + } else { - if ( onLoad ) onLoad( texture ); + return builder.format( `${ a } ${ op } ${ b }`, type, output ); - }, onProgress, onError ); + } } - return texture; - } -} - -class ImageLoader extends Loader { + serialize( data ) { - constructor( manager ) { + super.serialize( data ); - super( manager ); + data.op = this.op; } - load( url, onLoad, onProgress, onError ) { - - if ( this.path !== undefined ) url = this.path + url; + deserialize( data ) { - url = this.manager.resolveURL( url ); + super.deserialize( data ); - const scope = this; + this.op = data.op; - const cached = Cache.get( url ); + } - if ( cached !== undefined ) { +} - scope.manager.itemStart( url ); +const add = /*@__PURE__*/ nodeProxy( OperatorNode, '+' ); +const sub = /*@__PURE__*/ nodeProxy( OperatorNode, '-' ); +const mul = /*@__PURE__*/ nodeProxy( OperatorNode, '*' ); +const div = /*@__PURE__*/ nodeProxy( OperatorNode, '/' ); +const modInt = /*@__PURE__*/ nodeProxy( OperatorNode, '%' ); +const equal = /*@__PURE__*/ nodeProxy( OperatorNode, '==' ); +const notEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '!=' ); +const lessThan = /*@__PURE__*/ nodeProxy( OperatorNode, '<' ); +const greaterThan = /*@__PURE__*/ nodeProxy( OperatorNode, '>' ); +const lessThanEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '<=' ); +const greaterThanEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '>=' ); +const and = /*@__PURE__*/ nodeProxy( OperatorNode, '&&' ); +const or = /*@__PURE__*/ nodeProxy( OperatorNode, '||' ); +const not = /*@__PURE__*/ nodeProxy( OperatorNode, '!' ); +const xor = /*@__PURE__*/ nodeProxy( OperatorNode, '^^' ); +const bitAnd = /*@__PURE__*/ nodeProxy( OperatorNode, '&' ); +const bitNot = /*@__PURE__*/ nodeProxy( OperatorNode, '~' ); +const bitOr = /*@__PURE__*/ nodeProxy( OperatorNode, '|' ); +const bitXor = /*@__PURE__*/ nodeProxy( OperatorNode, '^' ); +const shiftLeft = /*@__PURE__*/ nodeProxy( OperatorNode, '<<' ); +const shiftRight = /*@__PURE__*/ nodeProxy( OperatorNode, '>>' ); - setTimeout( function () { +addMethodChaining( 'add', add ); +addMethodChaining( 'sub', sub ); +addMethodChaining( 'mul', mul ); +addMethodChaining( 'div', div ); +addMethodChaining( 'modInt', modInt ); +addMethodChaining( 'equal', equal ); +addMethodChaining( 'notEqual', notEqual ); +addMethodChaining( 'lessThan', lessThan ); +addMethodChaining( 'greaterThan', greaterThan ); +addMethodChaining( 'lessThanEqual', lessThanEqual ); +addMethodChaining( 'greaterThanEqual', greaterThanEqual ); +addMethodChaining( 'and', and ); +addMethodChaining( 'or', or ); +addMethodChaining( 'not', not ); +addMethodChaining( 'xor', xor ); +addMethodChaining( 'bitAnd', bitAnd ); +addMethodChaining( 'bitNot', bitNot ); +addMethodChaining( 'bitOr', bitOr ); +addMethodChaining( 'bitXor', bitXor ); +addMethodChaining( 'shiftLeft', shiftLeft ); +addMethodChaining( 'shiftRight', shiftRight ); - if ( onLoad ) onLoad( cached ); - scope.manager.itemEnd( url ); +const remainder = ( ...params ) => { // @deprecated, r168 - }, 0 ); + console.warn( 'TSL.OperatorNode: .remainder() has been renamed to .modInt().' ); + return modInt( ...params ); - return cached; +}; - } +addMethodChaining( 'remainder', remainder ); - const image = createElementNS( 'img' ); +class MathNode extends TempNode { - function onImageLoad() { + static get type() { - removeEventListeners(); + return 'MathNode'; - Cache.add( url, this ); + } - if ( onLoad ) onLoad( this ); + constructor( method, aNode, bNode = null, cNode = null ) { - scope.manager.itemEnd( url ); + super(); - } + this.method = method; - function onImageError( event ) { + this.aNode = aNode; + this.bNode = bNode; + this.cNode = cNode; - removeEventListeners(); + } - if ( onError ) onError( event ); + getInputType( builder ) { - scope.manager.itemError( url ); - scope.manager.itemEnd( url ); + const aType = this.aNode.getNodeType( builder ); + const bType = this.bNode ? this.bNode.getNodeType( builder ) : null; + const cType = this.cNode ? this.cNode.getNodeType( builder ) : null; - } + const aLen = builder.isMatrix( aType ) ? 0 : builder.getTypeLength( aType ); + const bLen = builder.isMatrix( bType ) ? 0 : builder.getTypeLength( bType ); + const cLen = builder.isMatrix( cType ) ? 0 : builder.getTypeLength( cType ); - function removeEventListeners() { + if ( aLen > bLen && aLen > cLen ) { - image.removeEventListener( 'load', onImageLoad, false ); - image.removeEventListener( 'error', onImageError, false ); + return aType; - } + } else if ( bLen > cLen ) { - image.addEventListener( 'load', onImageLoad, false ); - image.addEventListener( 'error', onImageError, false ); + return bType; - if ( url.slice( 0, 5 ) !== 'data:' ) { + } else if ( cLen > aLen ) { - if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin; + return cType; } - scope.manager.itemStart( url ); - - image.src = url; - - return image; - - } - -} - -class CubeTextureLoader extends Loader { - - constructor( manager ) { - - super( manager ); + return aType; } - load( urls, onLoad, onProgress, onError ) { - - const texture = new CubeTexture(); - texture.colorSpace = SRGBColorSpace; - - const loader = new ImageLoader( this.manager ); - loader.setCrossOrigin( this.crossOrigin ); - loader.setPath( this.path ); + getNodeType( builder ) { - let loaded = 0; + const method = this.method; - function loadTexture( i ) { + if ( method === MathNode.LENGTH || method === MathNode.DISTANCE || method === MathNode.DOT ) { - loader.load( urls[ i ], function ( image ) { + return 'float'; - texture.images[ i ] = image; + } else if ( method === MathNode.CROSS ) { - loaded ++; + return 'vec3'; - if ( loaded === 6 ) { + } else if ( method === MathNode.ALL ) { - texture.needsUpdate = true; + return 'bool'; - if ( onLoad ) onLoad( texture ); + } else if ( method === MathNode.EQUALS ) { - } + return builder.changeComponentType( this.aNode.getNodeType( builder ), 'bool' ); - }, undefined, onError ); + } else if ( method === MathNode.MOD ) { - } + return this.aNode.getNodeType( builder ); - for ( let i = 0; i < urls.length; ++ i ) { + } else { - loadTexture( i ); + return this.getInputType( builder ); } - return texture; - } -} - -/** - * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...) - * - * Sub classes have to implement the parse() method which will be used in load(). - */ - -class DataTextureLoader extends Loader { - - constructor( manager ) { - - super( manager ); - - } + generate( builder, output ) { - load( url, onLoad, onProgress, onError ) { + const method = this.method; - const scope = this; + const type = this.getNodeType( builder ); + const inputType = this.getInputType( builder ); - const texture = new DataTexture(); + const a = this.aNode; + const b = this.bNode; + const c = this.cNode; - const loader = new FileLoader( this.manager ); - loader.setResponseType( 'arraybuffer' ); - loader.setRequestHeader( this.requestHeader ); - loader.setPath( this.path ); - loader.setWithCredentials( scope.withCredentials ); - loader.load( url, function ( buffer ) { + const isWebGL = builder.renderer.isWebGLRenderer === true; - let texData; + if ( method === MathNode.TRANSFORM_DIRECTION ) { - try { + // dir can be either a direction vector or a normal vector + // upper-left 3x3 of matrix is assumed to be orthogonal - texData = scope.parse( buffer ); + let tA = a; + let tB = b; - } catch ( error ) { + if ( builder.isMatrix( tA.getNodeType( builder ) ) ) { - if ( onError !== undefined ) { + tB = vec4( vec3( tB ), 0.0 ); - onError( error ); + } else { - } else { + tA = vec4( vec3( tA ), 0.0 ); - console.error( error ); - return; + } - } + const mulNode = mul( tA, tB ).xyz; - } + return normalize( mulNode ).build( builder, output ); - if ( texData.image !== undefined ) { + } else if ( method === MathNode.NEGATE ) { - texture.image = texData.image; + return builder.format( '( - ' + a.build( builder, inputType ) + ' )', type, output ); - } else if ( texData.data !== undefined ) { + } else if ( method === MathNode.ONE_MINUS ) { - texture.image.width = texData.width; - texture.image.height = texData.height; - texture.image.data = texData.data; + return sub( 1.0, a ).build( builder, output ); - } + } else if ( method === MathNode.RECIPROCAL ) { - texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping; - texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping; + return div( 1.0, a ).build( builder, output ); - texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter; - texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter; + } else if ( method === MathNode.DIFFERENCE ) { - texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1; + return abs( sub( a, b ) ).build( builder, output ); - if ( texData.colorSpace !== undefined ) { + } else { - texture.colorSpace = texData.colorSpace; + const params = []; - } + if ( method === MathNode.CROSS || method === MathNode.MOD ) { - if ( texData.flipY !== undefined ) { + params.push( + a.build( builder, type ), + b.build( builder, type ) + ); - texture.flipY = texData.flipY; + } else if ( isWebGL && method === MathNode.STEP ) { - } + params.push( + a.build( builder, builder.getTypeLength( a.getNodeType( builder ) ) === 1 ? 'float' : inputType ), + b.build( builder, inputType ) + ); - if ( texData.format !== undefined ) { + } else if ( ( isWebGL && ( method === MathNode.MIN || method === MathNode.MAX ) ) || method === MathNode.MOD ) { - texture.format = texData.format; + params.push( + a.build( builder, inputType ), + b.build( builder, builder.getTypeLength( b.getNodeType( builder ) ) === 1 ? 'float' : inputType ) + ); - } + } else if ( method === MathNode.REFRACT ) { - if ( texData.type !== undefined ) { + params.push( + a.build( builder, inputType ), + b.build( builder, inputType ), + c.build( builder, 'float' ) + ); - texture.type = texData.type; + } else if ( method === MathNode.MIX ) { - } + params.push( + a.build( builder, inputType ), + b.build( builder, inputType ), + c.build( builder, builder.getTypeLength( c.getNodeType( builder ) ) === 1 ? 'float' : inputType ) + ); - if ( texData.mipmaps !== undefined ) { + } else { - texture.mipmaps = texData.mipmaps; - texture.minFilter = LinearMipmapLinearFilter; // presumably... + params.push( a.build( builder, inputType ) ); + if ( b !== null ) params.push( b.build( builder, inputType ) ); + if ( c !== null ) params.push( c.build( builder, inputType ) ); } - if ( texData.mipmapCount === 1 ) { - - texture.minFilter = LinearFilter; + return builder.format( `${ builder.getMethod( method, type ) }( ${params.join( ', ' )} )`, type, output ); - } + } - if ( texData.generateMipmaps !== undefined ) { + } - texture.generateMipmaps = texData.generateMipmaps; + serialize( data ) { - } + super.serialize( data ); - texture.needsUpdate = true; + data.method = this.method; - if ( onLoad ) onLoad( texture, texData ); + } - }, onProgress, onError ); + deserialize( data ) { + super.deserialize( data ); - return texture; + this.method = data.method; } } -class TextureLoader extends Loader { +// 1 input - constructor( manager ) { +MathNode.ALL = 'all'; +MathNode.ANY = 'any'; +MathNode.EQUALS = 'equals'; - super( manager ); +MathNode.RADIANS = 'radians'; +MathNode.DEGREES = 'degrees'; +MathNode.EXP = 'exp'; +MathNode.EXP2 = 'exp2'; +MathNode.LOG = 'log'; +MathNode.LOG2 = 'log2'; +MathNode.SQRT = 'sqrt'; +MathNode.INVERSE_SQRT = 'inversesqrt'; +MathNode.FLOOR = 'floor'; +MathNode.CEIL = 'ceil'; +MathNode.NORMALIZE = 'normalize'; +MathNode.FRACT = 'fract'; +MathNode.SIN = 'sin'; +MathNode.COS = 'cos'; +MathNode.TAN = 'tan'; +MathNode.ASIN = 'asin'; +MathNode.ACOS = 'acos'; +MathNode.ATAN = 'atan'; +MathNode.ABS = 'abs'; +MathNode.SIGN = 'sign'; +MathNode.LENGTH = 'length'; +MathNode.NEGATE = 'negate'; +MathNode.ONE_MINUS = 'oneMinus'; +MathNode.DFDX = 'dFdx'; +MathNode.DFDY = 'dFdy'; +MathNode.ROUND = 'round'; +MathNode.RECIPROCAL = 'reciprocal'; +MathNode.TRUNC = 'trunc'; +MathNode.FWIDTH = 'fwidth'; +MathNode.BITCAST = 'bitcast'; +MathNode.TRANSPOSE = 'transpose'; - } +// 2 inputs - load( url, onLoad, onProgress, onError ) { +MathNode.ATAN2 = 'atan2'; +MathNode.MIN = 'min'; +MathNode.MAX = 'max'; +MathNode.MOD = 'mod'; +MathNode.STEP = 'step'; +MathNode.REFLECT = 'reflect'; +MathNode.DISTANCE = 'distance'; +MathNode.DIFFERENCE = 'difference'; +MathNode.DOT = 'dot'; +MathNode.CROSS = 'cross'; +MathNode.POW = 'pow'; +MathNode.TRANSFORM_DIRECTION = 'transformDirection'; - const texture = new Texture(); +// 3 inputs - const loader = new ImageLoader( this.manager ); - loader.setCrossOrigin( this.crossOrigin ); - loader.setPath( this.path ); +MathNode.MIX = 'mix'; +MathNode.CLAMP = 'clamp'; +MathNode.REFRACT = 'refract'; +MathNode.SMOOTHSTEP = 'smoothstep'; +MathNode.FACEFORWARD = 'faceforward'; - loader.load( url, function ( image ) { +const EPSILON = /*@__PURE__*/ float( 1e-6 ); +const INFINITY = /*@__PURE__*/ float( 1e6 ); +const PI = /*@__PURE__*/ float( Math.PI ); +const PI2 = /*@__PURE__*/ float( Math.PI * 2 ); - texture.image = image; - texture.needsUpdate = true; +const all = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ALL ); +const any = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ANY ); +const equals = /*@__PURE__*/ nodeProxy( MathNode, MathNode.EQUALS ); - if ( onLoad !== undefined ) { +const radians = /*@__PURE__*/ nodeProxy( MathNode, MathNode.RADIANS ); +const degrees = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DEGREES ); +const exp = /*@__PURE__*/ nodeProxy( MathNode, MathNode.EXP ); +const exp2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.EXP2 ); +const log = /*@__PURE__*/ nodeProxy( MathNode, MathNode.LOG ); +const log2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.LOG2 ); +const sqrt = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SQRT ); +const inverseSqrt = /*@__PURE__*/ nodeProxy( MathNode, MathNode.INVERSE_SQRT ); +const floor = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FLOOR ); +const ceil = /*@__PURE__*/ nodeProxy( MathNode, MathNode.CEIL ); +const normalize = /*@__PURE__*/ nodeProxy( MathNode, MathNode.NORMALIZE ); +const fract = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FRACT ); +const sin = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SIN ); +const cos = /*@__PURE__*/ nodeProxy( MathNode, MathNode.COS ); +const tan = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TAN ); +const asin = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ASIN ); +const acos = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ACOS ); +const atan = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ATAN ); +const abs = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ABS ); +const sign = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SIGN ); +const length = /*@__PURE__*/ nodeProxy( MathNode, MathNode.LENGTH ); +const negate = /*@__PURE__*/ nodeProxy( MathNode, MathNode.NEGATE ); +const oneMinus = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ONE_MINUS ); +const dFdx = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DFDX ); +const dFdy = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DFDY ); +const round = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ROUND ); +const reciprocal = /*@__PURE__*/ nodeProxy( MathNode, MathNode.RECIPROCAL ); +const trunc = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TRUNC ); +const fwidth = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FWIDTH ); +const bitcast = /*@__PURE__*/ nodeProxy( MathNode, MathNode.BITCAST ); +const transpose = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TRANSPOSE ); - onLoad( texture ); +const atan2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ATAN2 ); +const min$1 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MIN ); +const max$1 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MAX ); +const mod = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MOD ); +const step = /*@__PURE__*/ nodeProxy( MathNode, MathNode.STEP ); +const reflect = /*@__PURE__*/ nodeProxy( MathNode, MathNode.REFLECT ); +const distance = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DISTANCE ); +const difference = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DIFFERENCE ); +const dot = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DOT ); +const cross = /*@__PURE__*/ nodeProxy( MathNode, MathNode.CROSS ); +const pow = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW ); +const pow2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW, 2 ); +const pow3 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW, 3 ); +const pow4 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW, 4 ); +const transformDirection = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TRANSFORM_DIRECTION ); - } +const cbrt = ( a ) => mul( sign( a ), pow( abs( a ), 1.0 / 3.0 ) ); +const lengthSq = ( a ) => dot( a, a ); +const mix = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MIX ); +const clamp = ( value, low = 0, high = 1 ) => nodeObject( new MathNode( MathNode.CLAMP, nodeObject( value ), nodeObject( low ), nodeObject( high ) ) ); +const saturate = ( value ) => clamp( value ); +const refract = /*@__PURE__*/ nodeProxy( MathNode, MathNode.REFRACT ); +const smoothstep = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SMOOTHSTEP ); +const faceForward = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FACEFORWARD ); - }, onProgress, onError ); +const rand = /*@__PURE__*/ Fn( ( [ uv ] ) => { - return texture; + const a = 12.9898, b = 78.233, c = 43758.5453; + const dt = dot( uv.xy, vec2( a, b ) ), sn = mod( dt, PI ); - } + return fract( sin( sn ).mul( c ) ); -} +} ); -class Light extends Object3D { +const mixElement = ( t, e1, e2 ) => mix( e1, e2, t ); +const smoothstepElement = ( x, low, high ) => smoothstep( low, high, x ); - constructor( color, intensity = 1 ) { +addMethodChaining( 'all', all ); +addMethodChaining( 'any', any ); +addMethodChaining( 'equals', equals ); - super(); +addMethodChaining( 'radians', radians ); +addMethodChaining( 'degrees', degrees ); +addMethodChaining( 'exp', exp ); +addMethodChaining( 'exp2', exp2 ); +addMethodChaining( 'log', log ); +addMethodChaining( 'log2', log2 ); +addMethodChaining( 'sqrt', sqrt ); +addMethodChaining( 'inverseSqrt', inverseSqrt ); +addMethodChaining( 'floor', floor ); +addMethodChaining( 'ceil', ceil ); +addMethodChaining( 'normalize', normalize ); +addMethodChaining( 'fract', fract ); +addMethodChaining( 'sin', sin ); +addMethodChaining( 'cos', cos ); +addMethodChaining( 'tan', tan ); +addMethodChaining( 'asin', asin ); +addMethodChaining( 'acos', acos ); +addMethodChaining( 'atan', atan ); +addMethodChaining( 'abs', abs ); +addMethodChaining( 'sign', sign ); +addMethodChaining( 'length', length ); +addMethodChaining( 'lengthSq', lengthSq ); +addMethodChaining( 'negate', negate ); +addMethodChaining( 'oneMinus', oneMinus ); +addMethodChaining( 'dFdx', dFdx ); +addMethodChaining( 'dFdy', dFdy ); +addMethodChaining( 'round', round ); +addMethodChaining( 'reciprocal', reciprocal ); +addMethodChaining( 'trunc', trunc ); +addMethodChaining( 'fwidth', fwidth ); +addMethodChaining( 'atan2', atan2 ); +addMethodChaining( 'min', min$1 ); +addMethodChaining( 'max', max$1 ); +addMethodChaining( 'mod', mod ); +addMethodChaining( 'step', step ); +addMethodChaining( 'reflect', reflect ); +addMethodChaining( 'distance', distance ); +addMethodChaining( 'dot', dot ); +addMethodChaining( 'cross', cross ); +addMethodChaining( 'pow', pow ); +addMethodChaining( 'pow2', pow2 ); +addMethodChaining( 'pow3', pow3 ); +addMethodChaining( 'pow4', pow4 ); +addMethodChaining( 'transformDirection', transformDirection ); +addMethodChaining( 'mix', mixElement ); +addMethodChaining( 'clamp', clamp ); +addMethodChaining( 'refract', refract ); +addMethodChaining( 'smoothstep', smoothstepElement ); +addMethodChaining( 'faceForward', faceForward ); +addMethodChaining( 'difference', difference ); +addMethodChaining( 'saturate', saturate ); +addMethodChaining( 'cbrt', cbrt ); +addMethodChaining( 'transpose', transpose ); +addMethodChaining( 'rand', rand ); - this.isLight = true; +class ConditionalNode extends Node { - this.type = 'Light'; + static get type() { - this.color = new Color( color ); - this.intensity = intensity; + return 'ConditionalNode'; } - dispose() { + constructor( condNode, ifNode, elseNode = null ) { - // Empty here in base class; some subclasses override. + super(); + + this.condNode = condNode; + + this.ifNode = ifNode; + this.elseNode = elseNode; } - copy( source, recursive ) { + getNodeType( builder ) { - super.copy( source, recursive ); + const ifType = this.ifNode.getNodeType( builder ); - this.color.copy( source.color ); - this.intensity = source.intensity; + if ( this.elseNode !== null ) { - return this; + const elseType = this.elseNode.getNodeType( builder ); + + if ( builder.getTypeLength( elseType ) > builder.getTypeLength( ifType ) ) { + + return elseType; + + } + + } + + return ifType; } - toJSON( meta ) { + setup( builder ) { - const data = super.toJSON( meta ); + const condNode = this.condNode.cache(); + const ifNode = this.ifNode.cache(); + const elseNode = this.elseNode ? this.elseNode.cache() : null; - data.object.color = this.color.getHex(); - data.object.intensity = this.intensity; + // - if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex(); + const currentNodeBlock = builder.context.nodeBlock; - if ( this.distance !== undefined ) data.object.distance = this.distance; - if ( this.angle !== undefined ) data.object.angle = this.angle; - if ( this.decay !== undefined ) data.object.decay = this.decay; - if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra; + builder.getDataFromNode( ifNode ).parentNodeBlock = currentNodeBlock; + if ( elseNode !== null ) builder.getDataFromNode( elseNode ).parentNodeBlock = currentNodeBlock; - if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON(); - if ( this.target !== undefined ) data.object.target = this.target.uuid; + // - return data; + const properties = builder.getNodeProperties( this ); + properties.condNode = condNode; + properties.ifNode = ifNode.context( { nodeBlock: ifNode } ); + properties.elseNode = elseNode ? elseNode.context( { nodeBlock: elseNode } ) : null; } -} + generate( builder, output ) { -class HemisphereLight extends Light { + const type = this.getNodeType( builder ); - constructor( skyColor, groundColor, intensity ) { + const nodeData = builder.getDataFromNode( this ); - super( skyColor, intensity ); + if ( nodeData.nodeProperty !== undefined ) { - this.isHemisphereLight = true; + return nodeData.nodeProperty; - this.type = 'HemisphereLight'; + } - this.position.copy( Object3D.DEFAULT_UP ); - this.updateMatrix(); + const { condNode, ifNode, elseNode } = builder.getNodeProperties( this ); - this.groundColor = new Color( groundColor ); + const needsOutput = output !== 'void'; + const nodeProperty = needsOutput ? property( type ).build( builder ) : ''; - } + nodeData.nodeProperty = nodeProperty; - copy( source, recursive ) { + const nodeSnippet = condNode.build( builder, 'bool' ); - super.copy( source, recursive ); + builder.addFlowCode( `\n${ builder.tab }if ( ${ nodeSnippet } ) {\n\n` ).addFlowTab(); - this.groundColor.copy( source.groundColor ); + let ifSnippet = ifNode.build( builder, type ); - return this; + if ( ifSnippet ) { - } + if ( needsOutput ) { -} + ifSnippet = nodeProperty + ' = ' + ifSnippet + ';'; -const _projScreenMatrix$2 = /*@__PURE__*/ new Matrix4(); -const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3(); -const _lookTarget$1 = /*@__PURE__*/ new Vector3(); + } else { -class LightShadow { + ifSnippet = 'return ' + ifSnippet + ';'; - constructor( camera ) { + } - this.camera = camera; + } - this.intensity = 1; + builder.removeFlowTab().addFlowCode( builder.tab + '\t' + ifSnippet + '\n\n' + builder.tab + '}' ); - this.bias = 0; - this.normalBias = 0; - this.radius = 1; - this.blurSamples = 8; + if ( elseNode !== null ) { - this.mapSize = new Vector2( 512, 512 ); + builder.addFlowCode( ' else {\n\n' ).addFlowTab(); - this.map = null; - this.mapPass = null; - this.matrix = new Matrix4(); + let elseSnippet = elseNode.build( builder, type ); - this.autoUpdate = true; - this.needsUpdate = false; + if ( elseSnippet ) { - this._frustum = new Frustum(); - this._frameExtents = new Vector2( 1, 1 ); + if ( needsOutput ) { - this._viewportCount = 1; + elseSnippet = nodeProperty + ' = ' + elseSnippet + ';'; - this._viewports = [ + } else { - new Vector4( 0, 0, 1, 1 ) + elseSnippet = 'return ' + elseSnippet + ';'; - ]; + } - } + } - getViewportCount() { + builder.removeFlowTab().addFlowCode( builder.tab + '\t' + elseSnippet + '\n\n' + builder.tab + '}\n\n' ); - return this._viewportCount; + } else { - } + builder.addFlowCode( '\n\n' ); - getFrustum() { + } - return this._frustum; + return builder.format( nodeProperty, type, output ); } - updateMatrices( light ) { +} - const shadowCamera = this.camera; - const shadowMatrix = this.matrix; +const select = /*@__PURE__*/ nodeProxy( ConditionalNode ); - _lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld ); - shadowCamera.position.copy( _lightPositionWorld$1 ); +addMethodChaining( 'select', select ); - _lookTarget$1.setFromMatrixPosition( light.target.matrixWorld ); - shadowCamera.lookAt( _lookTarget$1 ); - shadowCamera.updateMatrixWorld(); +// - _projScreenMatrix$2.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); - this._frustum.setFromProjectionMatrix( _projScreenMatrix$2 ); +const cond = ( ...params ) => { // @deprecated, r168 - shadowMatrix.set( - 0.5, 0.0, 0.0, 0.5, - 0.0, 0.5, 0.0, 0.5, - 0.0, 0.0, 0.5, 0.5, - 0.0, 0.0, 0.0, 1.0 - ); + console.warn( 'TSL.ConditionalNode: cond() has been renamed to select().' ); + return select( ...params ); - shadowMatrix.multiply( _projScreenMatrix$2 ); +}; - } +addMethodChaining( 'cond', cond ); - getViewport( viewportIndex ) { +class ContextNode extends Node { - return this._viewports[ viewportIndex ]; + static get type() { + + return 'ContextNode'; } - getFrameExtents() { + constructor( node, value = {} ) { - return this._frameExtents; + super(); - } + this.isContextNode = true; - dispose() { + this.node = node; + this.value = value; - if ( this.map ) { + } - this.map.dispose(); + getScope() { - } + return this.node.getScope(); - if ( this.mapPass ) { + } - this.mapPass.dispose(); + getNodeType( builder ) { - } + return this.node.getNodeType( builder ); } - copy( source ) { + analyze( builder ) { - this.camera = source.camera.clone(); + this.node.build( builder ); - this.intensity = source.intensity; + } - this.bias = source.bias; - this.radius = source.radius; + setup( builder ) { - this.mapSize.copy( source.mapSize ); + const previousContext = builder.getContext(); - return this; + builder.setContext( { ...builder.context, ...this.value } ); - } + const node = this.node.build( builder ); - clone() { + builder.setContext( previousContext ); - return new this.constructor().copy( this ); + return node; } - toJSON() { + generate( builder, output ) { - const object = {}; + const previousContext = builder.getContext(); - if ( this.intensity !== 1 ) object.intensity = this.intensity; - if ( this.bias !== 0 ) object.bias = this.bias; - if ( this.normalBias !== 0 ) object.normalBias = this.normalBias; - if ( this.radius !== 1 ) object.radius = this.radius; - if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray(); + builder.setContext( { ...builder.context, ...this.value } ); - object.camera = this.camera.toJSON( false ).object; - delete object.camera.matrix; + const snippet = this.node.build( builder, output ); - return object; + builder.setContext( previousContext ); + + return snippet; } } -class SpotLightShadow extends LightShadow { +const context = /*@__PURE__*/ nodeProxy( ContextNode ); +const label = ( node, name ) => context( node, { label: name } ); - constructor() { +addMethodChaining( 'context', context ); +addMethodChaining( 'label', label ); - super( new PerspectiveCamera( 50, 1, 0.5, 500 ) ); +class VarNode extends Node { - this.isSpotLightShadow = true; + static get type() { - this.focus = 1; + return 'VarNode'; } - updateMatrices( light ) { - - const camera = this.camera; - - const fov = RAD2DEG * 2 * light.angle * this.focus; - const aspect = this.mapSize.width / this.mapSize.height; - const far = light.distance || camera.far; + constructor( node, name = null ) { - if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) { + super(); - camera.fov = fov; - camera.aspect = aspect; - camera.far = far; - camera.updateProjectionMatrix(); + this.node = node; + this.name = name; - } + this.global = true; - super.updateMatrices( light ); + this.isVarNode = true; } - copy( source ) { + getHash( builder ) { - super.copy( source ); + return this.name || super.getHash( builder ); - this.focus = source.focus; + } - return this; + getNodeType( builder ) { + + return this.node.getNodeType( builder ); } -} + generate( builder ) { -class SpotLight extends Light { + const { node, name } = this; - constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2 ) { + const nodeVar = builder.getVarFromNode( this, name, builder.getVectorType( this.getNodeType( builder ) ) ); - super( color, intensity ); + const propertyName = builder.getPropertyName( nodeVar ); - this.isSpotLight = true; + const snippet = node.build( builder, nodeVar.type ); - this.type = 'SpotLight'; + builder.addLineFlowCode( `${propertyName} = ${snippet}`, this ); - this.position.copy( Object3D.DEFAULT_UP ); - this.updateMatrix(); + return propertyName; - this.target = new Object3D(); + } - this.distance = distance; - this.angle = angle; - this.penumbra = penumbra; - this.decay = decay; +} - this.map = null; +const temp = /*@__PURE__*/ nodeProxy( VarNode ); - this.shadow = new SpotLightShadow(); +addMethodChaining( 'temp', temp ); // @TODO: Will be removed in the future +addMethodChaining( 'toVar', ( ...params ) => temp( ...params ).append() ); - } +class VaryingNode extends Node { - get power() { + static get type() { - // compute the light's luminous power (in lumens) from its intensity (in candela) - // by convention for a spotlight, luminous power (lm) = π * luminous intensity (cd) - return this.intensity * Math.PI; + return 'VaryingNode'; } - set power( power ) { + constructor( node, name = null ) { - // set the light's intensity (in candela) from the desired luminous power (in lumens) - this.intensity = power / Math.PI; + super(); + + this.node = node; + this.name = name; + + this.isVaryingNode = true; } - dispose() { + isGlobal() { - this.shadow.dispose(); + return true; } - copy( source, recursive ) { + getHash( builder ) { - super.copy( source, recursive ); + return this.name || super.getHash( builder ); - this.distance = source.distance; - this.angle = source.angle; - this.penumbra = source.penumbra; - this.decay = source.decay; + } - this.target = source.target.clone(); + getNodeType( builder ) { - this.shadow = source.shadow.clone(); + // VaryingNode is auto type - return this; + return this.node.getNodeType( builder ); } -} + setupVarying( builder ) { -const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4(); -const _lightPositionWorld = /*@__PURE__*/ new Vector3(); -const _lookTarget = /*@__PURE__*/ new Vector3(); + const properties = builder.getNodeProperties( this ); -class PointLightShadow extends LightShadow { + let varying = properties.varying; - constructor() { + if ( varying === undefined ) { - super( new PerspectiveCamera( 90, 1, 0.5, 500 ) ); + const name = this.name; + const type = this.getNodeType( builder ); - this.isPointLightShadow = true; + properties.varying = varying = builder.getVaryingFromNode( this, name, type ); + properties.node = this.node; - this._frameExtents = new Vector2( 4, 2 ); + } - this._viewportCount = 6; + // this property can be used to check if the varying can be optimized for a variable + varying.needsInterpolation || ( varying.needsInterpolation = ( builder.shaderStage === 'fragment' ) ); - this._viewports = [ - // These viewports map a cube-map onto a 2D texture with the - // following orientation: - // - // xzXZ - // y Y - // - // X - Positive x direction - // x - Negative x direction - // Y - Positive y direction - // y - Negative y direction - // Z - Positive z direction - // z - Negative z direction + return varying; - // positive X - new Vector4( 2, 1, 1, 1 ), - // negative X - new Vector4( 0, 1, 1, 1 ), - // positive Z - new Vector4( 3, 1, 1, 1 ), - // negative Z - new Vector4( 1, 1, 1, 1 ), - // positive Y - new Vector4( 3, 0, 1, 1 ), - // negative Y - new Vector4( 1, 0, 1, 1 ) - ]; + } - this._cubeDirections = [ - new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ), - new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 ) - ]; + setup( builder ) { - this._cubeUps = [ - new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), - new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 ) - ]; + this.setupVarying( builder ); } - updateMatrices( light, viewportIndex = 0 ) { + analyze( builder ) { - const camera = this.camera; - const shadowMatrix = this.matrix; + this.setupVarying( builder ); - const far = light.distance || camera.far; + return this.node.analyze( builder ); - if ( far !== camera.far ) { + } - camera.far = far; - camera.updateProjectionMatrix(); + generate( builder ) { - } + const properties = builder.getNodeProperties( this ); + const varying = this.setupVarying( builder ); - _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); - camera.position.copy( _lightPositionWorld ); + if ( properties.propertyName === undefined ) { - _lookTarget.copy( camera.position ); - _lookTarget.add( this._cubeDirections[ viewportIndex ] ); - camera.up.copy( this._cubeUps[ viewportIndex ] ); - camera.lookAt( _lookTarget ); - camera.updateMatrixWorld(); + const type = this.getNodeType( builder ); + const propertyName = builder.getPropertyName( varying, NodeShaderStage.VERTEX ); - shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); + // force node run in vertex stage + builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, this.node, type, propertyName ); - _projScreenMatrix$1.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); - this._frustum.setFromProjectionMatrix( _projScreenMatrix$1 ); + properties.propertyName = propertyName; + + } + + return builder.getPropertyName( varying ); } } -class PointLight extends Light { - - constructor( color, intensity, distance = 0, decay = 2 ) { +const varying = /*@__PURE__*/ nodeProxy( VaryingNode ); - super( color, intensity ); +addMethodChaining( 'varying', varying ); - this.isPointLight = true; +const WORKING_COLOR_SPACE = 'WorkingColorSpace'; +const OUTPUT_COLOR_SPACE = 'OutputColorSpace'; - this.type = 'PointLight'; +function getColorSpaceName( colorSpace ) { - this.distance = distance; - this.decay = decay; + let method = null; - this.shadow = new PointLightShadow(); + if ( colorSpace === LinearSRGBColorSpace ) { - } + method = 'Linear'; - get power() { + } else if ( colorSpace === SRGBColorSpace ) { - // compute the light's luminous power (in lumens) from its intensity (in candela) - // for an isotropic light source, luminous power (lm) = 4 π luminous intensity (cd) - return this.intensity * 4 * Math.PI; + method = 'sRGB'; } - set power( power ) { + return method; - // set the light's intensity (in candela) from the desired luminous power (in lumens) - this.intensity = power / ( 4 * Math.PI ); +} - } +function getColorSpaceMethod( source, target ) { - dispose() { + return getColorSpaceName( source ) + 'To' + getColorSpaceName( target ); - this.shadow.dispose(); +} - } +class ColorSpaceNode extends TempNode { - copy( source, recursive ) { + static get type() { - super.copy( source, recursive ); + return 'ColorSpaceNode'; - this.distance = source.distance; - this.decay = source.decay; + } - this.shadow = source.shadow.clone(); + constructor( colorNode, source, target ) { - return this; + super( 'vec4' ); + + this.colorNode = colorNode; + this.source = source; + this.target = target; } -} + getColorSpace( builder, colorSpace ) { -class OrthographicCamera extends Camera { + if ( colorSpace === WORKING_COLOR_SPACE ) { - constructor( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) { + return ColorManagement.workingColorSpace; - super(); + } else if ( colorSpace === OUTPUT_COLOR_SPACE ) { - this.isOrthographicCamera = true; + return builder.context.outputColorSpace || builder.renderer.outputColorSpace; - this.type = 'OrthographicCamera'; + } - this.zoom = 1; - this.view = null; + return colorSpace; - this.left = left; - this.right = right; - this.top = top; - this.bottom = bottom; + } - this.near = near; - this.far = far; + setup( builder ) { - this.updateProjectionMatrix(); + const { renderer } = builder; + const { colorNode } = this; - } + const source = this.getColorSpace( builder, this.source ); + const target = this.getColorSpace( builder, this.target ); - copy( source, recursive ) { + if ( source === target ) return colorNode; - super.copy( source, recursive ); + const colorSpace = getColorSpaceMethod( source, target ); - this.left = source.left; - this.right = source.right; - this.top = source.top; - this.bottom = source.bottom; - this.near = source.near; - this.far = source.far; + let outputNode = null; - this.zoom = source.zoom; - this.view = source.view === null ? null : Object.assign( {}, source.view ); + const colorSpaceFn = renderer.nodes.library.getColorSpaceFunction( colorSpace ); - return this; + if ( colorSpaceFn !== null ) { - } + outputNode = vec4( colorSpaceFn( colorNode.rgb ), colorNode.a ); - setViewOffset( fullWidth, fullHeight, x, y, width, height ) { + } else { - if ( this.view === null ) { + console.error( 'ColorSpaceNode: Unsupported Color Space configuration.', colorSpace ); - this.view = { - enabled: true, - fullWidth: 1, - fullHeight: 1, - offsetX: 0, - offsetY: 0, - width: 1, - height: 1 - }; + outputNode = colorNode; } - this.view.enabled = true; - this.view.fullWidth = fullWidth; - this.view.fullHeight = fullHeight; - this.view.offsetX = x; - this.view.offsetY = y; - this.view.width = width; - this.view.height = height; - - this.updateProjectionMatrix(); + return outputNode; } - clearViewOffset() { - - if ( this.view !== null ) { - - this.view.enabled = false; +} - } +const toOutputColorSpace = ( node ) => nodeObject( new ColorSpaceNode( nodeObject( node ), WORKING_COLOR_SPACE, OUTPUT_COLOR_SPACE ) ); +const toWorkingColorSpace = ( node ) => nodeObject( new ColorSpaceNode( nodeObject( node ), OUTPUT_COLOR_SPACE, WORKING_COLOR_SPACE ) ); - this.updateProjectionMatrix(); +const workingToColorSpace = ( node, colorSpace ) => nodeObject( new ColorSpaceNode( nodeObject( node ), WORKING_COLOR_SPACE, colorSpace ) ); +const colorSpaceToWorking = ( node, colorSpace ) => nodeObject( new ColorSpaceNode( nodeObject( node ), colorSpace, WORKING_COLOR_SPACE ) ); - } +addMethodChaining( 'toOutputColorSpace', toOutputColorSpace ); +addMethodChaining( 'toWorkingColorSpace', toWorkingColorSpace ); - updateProjectionMatrix() { +addMethodChaining( 'workingToColorSpace', workingToColorSpace ); +addMethodChaining( 'colorSpaceToWorking', colorSpaceToWorking ); - const dx = ( this.right - this.left ) / ( 2 * this.zoom ); - const dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); - const cx = ( this.right + this.left ) / 2; - const cy = ( this.top + this.bottom ) / 2; +let ReferenceElementNode$1 = class ReferenceElementNode extends ArrayElementNode { - let left = cx - dx; - let right = cx + dx; - let top = cy + dy; - let bottom = cy - dy; + static get type() { - if ( this.view !== null && this.view.enabled ) { + return 'ReferenceElementNode'; - const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom; - const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom; + } - left += scaleW * this.view.offsetX; - right = left + scaleW * this.view.width; - top -= scaleH * this.view.offsetY; - bottom = top - scaleH * this.view.height; + constructor( referenceNode, indexNode ) { - } + super( referenceNode, indexNode ); - this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem ); + this.referenceNode = referenceNode; - this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); + this.isReferenceElementNode = true; } - toJSON( meta ) { + getNodeType() { - const data = super.toJSON( meta ); + return this.referenceNode.uniformType; - data.object.zoom = this.zoom; - data.object.left = this.left; - data.object.right = this.right; - data.object.top = this.top; - data.object.bottom = this.bottom; - data.object.near = this.near; - data.object.far = this.far; + } - if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); + generate( builder ) { - return data; + const snippet = super.generate( builder ); + const arrayType = this.referenceNode.getNodeType(); + const elementType = this.getNodeType(); - } + return builder.format( snippet, arrayType, elementType ); -} + } -class DirectionalLightShadow extends LightShadow { +}; - constructor() { +class ReferenceBaseNode extends Node { - super( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); + static get type() { - this.isDirectionalLightShadow = true; + return 'ReferenceBaseNode'; } -} + constructor( property, uniformType, object = null, count = null ) { -class DirectionalLight extends Light { + super(); - constructor( color, intensity ) { + this.property = property; + this.uniformType = uniformType; + this.object = object; + this.count = count; - super( color, intensity ); + this.properties = property.split( '.' ); + this.reference = object; + this.node = null; + this.group = null; - this.isDirectionalLight = true; + this.updateType = NodeUpdateType.OBJECT; - this.type = 'DirectionalLight'; + } - this.position.copy( Object3D.DEFAULT_UP ); - this.updateMatrix(); + setGroup( group ) { - this.target = new Object3D(); + this.group = group; - this.shadow = new DirectionalLightShadow(); + return this; } - dispose() { + element( indexNode ) { - this.shadow.dispose(); + return nodeObject( new ReferenceElementNode$1( this, nodeObject( indexNode ) ) ); } - copy( source ) { + setNodeType( uniformType ) { - super.copy( source ); + const node = uniform( null, uniformType ).getSelf(); - this.target = source.target.clone(); - this.shadow = source.shadow.clone(); + if ( this.group !== null ) { - return this; + node.setGroup( this.group ); - } + } -} + this.node = node; -class AmbientLight extends Light { + } - constructor( color, intensity ) { + getNodeType( builder ) { - super( color, intensity ); + if ( this.node === null ) { - this.isAmbientLight = true; + this.updateReference( builder ); + this.updateValue(); - this.type = 'AmbientLight'; + } + + return this.node.getNodeType( builder ); } -} + getValueFromReference( object = this.reference ) { -class RectAreaLight extends Light { + const { properties } = this; - constructor( color, intensity, width = 10, height = 10 ) { + let value = object[ properties[ 0 ] ]; - super( color, intensity ); + for ( let i = 1; i < properties.length; i ++ ) { - this.isRectAreaLight = true; + value = value[ properties[ i ] ]; - this.type = 'RectAreaLight'; + } - this.width = width; - this.height = height; + return value; } - get power() { + updateReference( state ) { - // compute the light's luminous power (in lumens) from its intensity (in nits) - return this.intensity * this.width * this.height * Math.PI; + this.reference = this.object !== null ? this.object : state.object; + + return this.reference; } - set power( power ) { + setup() { - // set the light's intensity (in nits) from the desired luminous power (in lumens) - this.intensity = power / ( this.width * this.height * Math.PI ); + this.updateValue(); + + return this.node; } - copy( source ) { + update( /*frame*/ ) { - super.copy( source ); + this.updateValue(); - this.width = source.width; - this.height = source.height; + } - return this; + updateValue() { - } + if ( this.node === null ) this.setNodeType( this.uniformType ); - toJSON( meta ) { + const value = this.getValueFromReference(); - const data = super.toJSON( meta ); + if ( Array.isArray( value ) ) { - data.object.width = this.width; - data.object.height = this.height; + this.node.array = value; - return data; + } else { + + this.node.value = value; + + } } } -/** - * Primary reference: - * https://graphics.stanford.edu/papers/envmap/envmap.pdf - * - * Secondary reference: - * https://www.ppsloan.org/publications/StupidSH36.pdf - */ +const reference$1 = ( name, type, object ) => nodeObject( new ReferenceBaseNode( name, type, object ) ); -// 3-band SH defined by 9 coefficients +class RendererReferenceNode extends ReferenceBaseNode { -class SphericalHarmonics3 { + static get type() { - constructor() { + return 'RendererReferenceNode'; - this.isSphericalHarmonics3 = true; + } - this.coefficients = []; + constructor( property, inputType, renderer = null ) { - for ( let i = 0; i < 9; i ++ ) { + super( property, inputType, renderer ); - this.coefficients.push( new Vector3() ); + this.renderer = renderer; - } + this.setGroup( renderGroup ); } - set( coefficients ) { - - for ( let i = 0; i < 9; i ++ ) { - - this.coefficients[ i ].copy( coefficients[ i ] ); + updateReference( state ) { - } + this.reference = this.renderer !== null ? this.renderer : state.renderer; - return this; + return this.reference; } - zero() { +} - for ( let i = 0; i < 9; i ++ ) { +const rendererReference = ( name, type, renderer ) => nodeObject( new RendererReferenceNode( name, type, renderer ) ); - this.coefficients[ i ].set( 0, 0, 0 ); +class ToneMappingNode extends TempNode { - } + static get type() { - return this; + return 'ToneMappingNode'; } - // get the radiance in the direction of the normal - // target is a Vector3 - getAt( normal, target ) { - - // normal is assumed to be unit length + constructor( toneMapping, exposureNode = toneMappingExposure, colorNode = null ) { - const x = normal.x, y = normal.y, z = normal.z; + super( 'vec3' ); - const coeff = this.coefficients; + this.toneMapping = toneMapping; - // band 0 - target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 ); + this.exposureNode = exposureNode; + this.colorNode = colorNode; - // band 1 - target.addScaledVector( coeff[ 1 ], 0.488603 * y ); - target.addScaledVector( coeff[ 2 ], 0.488603 * z ); - target.addScaledVector( coeff[ 3 ], 0.488603 * x ); + } - // band 2 - target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) ); - target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) ); - target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) ); - target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) ); - target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) ); + getCacheKey() { - return target; + return hash$1( super.getCacheKey(), this.toneMapping ); } - // get the irradiance (radiance convolved with cosine lobe) in the direction of the normal - // target is a Vector3 - // https://graphics.stanford.edu/papers/envmap/envmap.pdf - getIrradianceAt( normal, target ) { - - // normal is assumed to be unit length - - const x = normal.x, y = normal.y, z = normal.z; + setup( builder ) { - const coeff = this.coefficients; + const colorNode = this.colorNode || builder.context.color; + const toneMapping = this.toneMapping; - // band 0 - target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // π * 0.282095 + if ( toneMapping === NoToneMapping ) return colorNode; - // band 1 - target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * π / 3 ) * 0.488603 - target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z ); - target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x ); + let outputNode = null; - // band 2 - target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( π / 4 ) * 1.092548 - target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z ); - target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( π / 4 ) * 0.315392 * 3 - target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z ); - target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( π / 4 ) * 0.546274 + const toneMappingFn = builder.renderer.nodes.library.getToneMappingFunction( toneMapping ); - return target; + if ( toneMappingFn !== null ) { - } + outputNode = vec4( toneMappingFn( colorNode.rgb, this.exposureNode ), colorNode.a ); - add( sh ) { + } else { - for ( let i = 0; i < 9; i ++ ) { + console.error( 'ToneMappingNode: Unsupported Tone Mapping configuration.', toneMapping ); - this.coefficients[ i ].add( sh.coefficients[ i ] ); + outputNode = colorNode; } - return this; + return outputNode; } - addScaledSH( sh, s ) { +} - for ( let i = 0; i < 9; i ++ ) { +const toneMapping = ( mapping, exposure, color ) => nodeObject( new ToneMappingNode( mapping, nodeObject( exposure ), nodeObject( color ) ) ); +const toneMappingExposure = /*@__PURE__*/ rendererReference( 'toneMappingExposure', 'float' ); - this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s ); +addMethodChaining( 'toneMapping', ( color, mapping, exposure ) => toneMapping( mapping, exposure, color ) ); - } +class BufferAttributeNode extends InputNode { - return this; + static get type() { + + return 'BufferAttributeNode'; } - scale( s ) { + constructor( value, bufferType = null, bufferStride = 0, bufferOffset = 0 ) { - for ( let i = 0; i < 9; i ++ ) { + super( value, bufferType ); - this.coefficients[ i ].multiplyScalar( s ); + this.isBufferNode = true; - } + this.bufferType = bufferType; + this.bufferStride = bufferStride; + this.bufferOffset = bufferOffset; - return this; + this.usage = StaticDrawUsage; + this.instanced = false; - } + this.attribute = null; - lerp( sh, alpha ) { + this.global = true; - for ( let i = 0; i < 9; i ++ ) { + if ( value && value.isBufferAttribute === true ) { - this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha ); + this.attribute = value; + this.usage = value.usage; + this.instanced = value.isInstancedBufferAttribute; } - return this; - } - equals( sh ) { + getHash( builder ) { - for ( let i = 0; i < 9; i ++ ) { + if ( this.bufferStride === 0 && this.bufferOffset === 0 ) { - if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) { + let bufferData = builder.globalCache.getData( this.value ); - return false; + if ( bufferData === undefined ) { + + bufferData = { + node: this + }; + + builder.globalCache.setData( this.value, bufferData ); } + return bufferData.node.uuid; + } - return true; + return this.uuid; } - copy( sh ) { + getNodeType( builder ) { - return this.set( sh.coefficients ); + if ( this.bufferType === null ) { - } + this.bufferType = builder.getTypeFromAttribute( this.attribute ); - clone() { + } - return new this.constructor().copy( this ); + return this.bufferType; } - fromArray( array, offset = 0 ) { + setup( builder ) { - const coefficients = this.coefficients; + if ( this.attribute !== null ) return; - for ( let i = 0; i < 9; i ++ ) { + const type = this.getNodeType( builder ); + const array = this.value; + const itemSize = builder.getTypeLength( type ); + const stride = this.bufferStride || itemSize; + const offset = this.bufferOffset; - coefficients[ i ].fromArray( array, offset + ( i * 3 ) ); + const buffer = array.isInterleavedBuffer === true ? array : new InterleavedBuffer( array, stride ); + const bufferAttribute = new InterleavedBufferAttribute( buffer, itemSize, offset ); - } + buffer.setUsage( this.usage ); - return this; + this.attribute = bufferAttribute; + this.attribute.isInstancedBufferAttribute = this.instanced; // @TODO: Add a possible: InstancedInterleavedBufferAttribute } - toArray( array = [], offset = 0 ) { - - const coefficients = this.coefficients; + generate( builder ) { - for ( let i = 0; i < 9; i ++ ) { + const nodeType = this.getNodeType( builder ); - coefficients[ i ].toArray( array, offset + ( i * 3 ) ); + const nodeAttribute = builder.getBufferAttributeFromNode( this, nodeType ); + const propertyName = builder.getPropertyName( nodeAttribute ); - } + let output = null; - return array; + if ( builder.shaderStage === 'vertex' || builder.shaderStage === 'compute' ) { - } + this.name = propertyName; - // evaluate the basis functions - // shBasis is an Array[ 9 ] - static getBasisAt( normal, shBasis ) { + output = propertyName; - // normal is assumed to be unit length + } else { - const x = normal.x, y = normal.y, z = normal.z; + const nodeVarying = varying( this ); - // band 0 - shBasis[ 0 ] = 0.282095; + output = nodeVarying.build( builder, nodeType ); - // band 1 - shBasis[ 1 ] = 0.488603 * y; - shBasis[ 2 ] = 0.488603 * z; - shBasis[ 3 ] = 0.488603 * x; + } - // band 2 - shBasis[ 4 ] = 1.092548 * x * y; - shBasis[ 5 ] = 1.092548 * y * z; - shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 ); - shBasis[ 7 ] = 1.092548 * x * z; - shBasis[ 8 ] = 0.546274 * ( x * x - y * y ); + return output; } -} - -class LightProbe extends Light { - - constructor( sh = new SphericalHarmonics3(), intensity = 1 ) { + getInputType( /*builder*/ ) { - super( undefined, intensity ); + return 'bufferAttribute'; - this.isLightProbe = true; + } - this.sh = sh; + setUsage( value ) { - } + this.usage = value; - copy( source ) { + if ( this.attribute && this.attribute.isBufferAttribute === true ) { - super.copy( source ); + this.attribute.usage = value; - this.sh.copy( source.sh ); + } return this; } - fromJSON( json ) { + setInstanced( value ) { - this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON(); - this.sh.fromArray( json.sh ); + this.instanced = value; return this; } - toJSON( meta ) { - - const data = super.toJSON( meta ); - - data.object.sh = this.sh.toArray(); +} - return data; +const bufferAttribute = ( array, type, stride, offset ) => nodeObject( new BufferAttributeNode( array, type, stride, offset ) ); +const dynamicBufferAttribute = ( array, type, stride, offset ) => bufferAttribute( array, type, stride, offset ).setUsage( DynamicDrawUsage ); - } +const instancedBufferAttribute = ( array, type, stride, offset ) => bufferAttribute( array, type, stride, offset ).setInstanced( true ); +const instancedDynamicBufferAttribute = ( array, type, stride, offset ) => dynamicBufferAttribute( array, type, stride, offset ).setInstanced( true ); -} +addMethodChaining( 'toAttribute', ( bufferNode ) => bufferAttribute( bufferNode.value ) ); -class MaterialLoader extends Loader { +class ComputeNode extends Node { - constructor( manager ) { + static get type() { - super( manager ); - this.textures = {}; + return 'ComputeNode'; } - load( url, onLoad, onProgress, onError ) { + constructor( computeNode, count, workgroupSize = [ 64 ] ) { - const scope = this; + super( 'void' ); - const loader = new FileLoader( scope.manager ); - loader.setPath( scope.path ); - loader.setRequestHeader( scope.requestHeader ); - loader.setWithCredentials( scope.withCredentials ); - loader.load( url, function ( text ) { + this.isComputeNode = true; - try { - - onLoad( scope.parse( JSON.parse( text ) ) ); + this.computeNode = computeNode; - } catch ( e ) { + this.count = count; + this.workgroupSize = workgroupSize; + this.dispatchCount = 0; - if ( onError ) { + this.version = 1; + this.updateBeforeType = NodeUpdateType.OBJECT; - onError( e ); + this.updateDispatchCount(); - } else { + } - console.error( e ); + dispose() { - } + this.dispatchEvent( { type: 'dispose' } ); - scope.manager.itemError( url ); + } - } + set needsUpdate( value ) { - }, onProgress, onError ); + if ( value === true ) this.version ++; } - parse( json ) { + updateDispatchCount() { - const textures = this.textures; + const { count, workgroupSize } = this; - function getTexture( name ) { + let size = workgroupSize[ 0 ]; - if ( textures[ name ] === undefined ) { + for ( let i = 1; i < workgroupSize.length; i ++ ) + size *= workgroupSize[ i ]; - console.warn( 'THREE.MaterialLoader: Undefined texture', name ); + this.dispatchCount = Math.ceil( count / size ); - } + } - return textures[ name ]; + onInit() { } - } + updateBefore( { renderer } ) { - const material = MaterialLoader.createMaterialFromType( json.type ); + renderer.compute( this ); - if ( json.uuid !== undefined ) material.uuid = json.uuid; - if ( json.name !== undefined ) material.name = json.name; - if ( json.color !== undefined && material.color !== undefined ) material.color.setHex( json.color ); - if ( json.roughness !== undefined ) material.roughness = json.roughness; - if ( json.metalness !== undefined ) material.metalness = json.metalness; - if ( json.sheen !== undefined ) material.sheen = json.sheen; - if ( json.sheenColor !== undefined ) material.sheenColor = new Color().setHex( json.sheenColor ); - if ( json.sheenRoughness !== undefined ) material.sheenRoughness = json.sheenRoughness; - if ( json.emissive !== undefined && material.emissive !== undefined ) material.emissive.setHex( json.emissive ); - if ( json.specular !== undefined && material.specular !== undefined ) material.specular.setHex( json.specular ); - if ( json.specularIntensity !== undefined ) material.specularIntensity = json.specularIntensity; - if ( json.specularColor !== undefined && material.specularColor !== undefined ) material.specularColor.setHex( json.specularColor ); - if ( json.shininess !== undefined ) material.shininess = json.shininess; - if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat; - if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness; - if ( json.dispersion !== undefined ) material.dispersion = json.dispersion; - if ( json.iridescence !== undefined ) material.iridescence = json.iridescence; - if ( json.iridescenceIOR !== undefined ) material.iridescenceIOR = json.iridescenceIOR; - if ( json.iridescenceThicknessRange !== undefined ) material.iridescenceThicknessRange = json.iridescenceThicknessRange; - if ( json.transmission !== undefined ) material.transmission = json.transmission; - if ( json.thickness !== undefined ) material.thickness = json.thickness; - if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance; - if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor ); - if ( json.anisotropy !== undefined ) material.anisotropy = json.anisotropy; - if ( json.anisotropyRotation !== undefined ) material.anisotropyRotation = json.anisotropyRotation; - if ( json.fog !== undefined ) material.fog = json.fog; - if ( json.flatShading !== undefined ) material.flatShading = json.flatShading; - if ( json.blending !== undefined ) material.blending = json.blending; - if ( json.combine !== undefined ) material.combine = json.combine; - if ( json.side !== undefined ) material.side = json.side; - if ( json.shadowSide !== undefined ) material.shadowSide = json.shadowSide; - if ( json.opacity !== undefined ) material.opacity = json.opacity; - if ( json.transparent !== undefined ) material.transparent = json.transparent; - if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest; - if ( json.alphaHash !== undefined ) material.alphaHash = json.alphaHash; - if ( json.depthFunc !== undefined ) material.depthFunc = json.depthFunc; - if ( json.depthTest !== undefined ) material.depthTest = json.depthTest; - if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite; - if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite; - if ( json.blendSrc !== undefined ) material.blendSrc = json.blendSrc; - if ( json.blendDst !== undefined ) material.blendDst = json.blendDst; - if ( json.blendEquation !== undefined ) material.blendEquation = json.blendEquation; - if ( json.blendSrcAlpha !== undefined ) material.blendSrcAlpha = json.blendSrcAlpha; - if ( json.blendDstAlpha !== undefined ) material.blendDstAlpha = json.blendDstAlpha; - if ( json.blendEquationAlpha !== undefined ) material.blendEquationAlpha = json.blendEquationAlpha; - if ( json.blendColor !== undefined && material.blendColor !== undefined ) material.blendColor.setHex( json.blendColor ); - if ( json.blendAlpha !== undefined ) material.blendAlpha = json.blendAlpha; - if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask; - if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc; - if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef; - if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask; - if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail; - if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail; - if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass; - if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite; + } - if ( json.wireframe !== undefined ) material.wireframe = json.wireframe; - if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth; - if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap; - if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin; + generate( builder ) { - if ( json.rotation !== undefined ) material.rotation = json.rotation; + const { shaderStage } = builder; - if ( json.linewidth !== undefined ) material.linewidth = json.linewidth; - if ( json.dashSize !== undefined ) material.dashSize = json.dashSize; - if ( json.gapSize !== undefined ) material.gapSize = json.gapSize; - if ( json.scale !== undefined ) material.scale = json.scale; + if ( shaderStage === 'compute' ) { - if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset; - if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor; - if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits; + const snippet = this.computeNode.build( builder, 'void' ); - if ( json.dithering !== undefined ) material.dithering = json.dithering; + if ( snippet !== '' ) { - if ( json.alphaToCoverage !== undefined ) material.alphaToCoverage = json.alphaToCoverage; - if ( json.premultipliedAlpha !== undefined ) material.premultipliedAlpha = json.premultipliedAlpha; - if ( json.forceSinglePass !== undefined ) material.forceSinglePass = json.forceSinglePass; + builder.addLineFlowCode( snippet, this ); - if ( json.visible !== undefined ) material.visible = json.visible; + } - if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped; + } - if ( json.userData !== undefined ) material.userData = json.userData; + } - if ( json.vertexColors !== undefined ) { +} - if ( typeof json.vertexColors === 'number' ) { +const compute = ( node, count, workgroupSize ) => nodeObject( new ComputeNode( nodeObject( node ), count, workgroupSize ) ); - material.vertexColors = ( json.vertexColors > 0 ) ? true : false; +addMethodChaining( 'compute', compute ); - } else { +class CacheNode extends Node { - material.vertexColors = json.vertexColors; + static get type() { - } + return 'CacheNode'; - } + } - // Shader Material + constructor( node, parent = true ) { - if ( json.uniforms !== undefined ) { + super(); - for ( const name in json.uniforms ) { + this.node = node; + this.parent = parent; - const uniform = json.uniforms[ name ]; + this.isCacheNode = true; - material.uniforms[ name ] = {}; + } - switch ( uniform.type ) { + getNodeType( builder ) { - case 't': - material.uniforms[ name ].value = getTexture( uniform.value ); - break; + return this.node.getNodeType( builder ); - case 'c': - material.uniforms[ name ].value = new Color().setHex( uniform.value ); - break; + } - case 'v2': - material.uniforms[ name ].value = new Vector2().fromArray( uniform.value ); - break; + build( builder, ...params ) { - case 'v3': - material.uniforms[ name ].value = new Vector3().fromArray( uniform.value ); - break; + const previousCache = builder.getCache(); + const cache = builder.getCacheFromNode( this, this.parent ); - case 'v4': - material.uniforms[ name ].value = new Vector4().fromArray( uniform.value ); - break; + builder.setCache( cache ); - case 'm3': - material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value ); - break; + const data = this.node.build( builder, ...params ); - case 'm4': - material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value ); - break; + builder.setCache( previousCache ); - default: - material.uniforms[ name ].value = uniform.value; + return data; - } + } - } +} - } +const cache = ( node, ...params ) => nodeObject( new CacheNode( nodeObject( node ), ...params ) ); - if ( json.defines !== undefined ) material.defines = json.defines; - if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader; - if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader; - if ( json.glslVersion !== undefined ) material.glslVersion = json.glslVersion; +addMethodChaining( 'cache', cache ); - if ( json.extensions !== undefined ) { +class BypassNode extends Node { - for ( const key in json.extensions ) { + static get type() { - material.extensions[ key ] = json.extensions[ key ]; + return 'BypassNode'; - } + } - } + constructor( returnNode, callNode ) { - if ( json.lights !== undefined ) material.lights = json.lights; - if ( json.clipping !== undefined ) material.clipping = json.clipping; + super(); - // for PointsMaterial + this.isBypassNode = true; - if ( json.size !== undefined ) material.size = json.size; - if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation; + this.outputNode = returnNode; + this.callNode = callNode; - // maps + } - if ( json.map !== undefined ) material.map = getTexture( json.map ); - if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap ); + getNodeType( builder ) { - if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap ); + return this.outputNode.getNodeType( builder ); - if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap ); - if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale; + } - if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap ); - if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType; - if ( json.normalScale !== undefined ) { + generate( builder ) { - let normalScale = json.normalScale; + const snippet = this.callNode.build( builder, 'void' ); - if ( Array.isArray( normalScale ) === false ) { + if ( snippet !== '' ) { - // Blender exporter used to export a scalar. See #7459 + builder.addLineFlowCode( snippet, this ); - normalScale = [ normalScale, normalScale ]; + } - } + return this.outputNode.build( builder ); - material.normalScale = new Vector2().fromArray( normalScale ); + } - } +} - if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap ); - if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale; - if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias; +const bypass = /*@__PURE__*/ nodeProxy( BypassNode ); - if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap ); - if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap ); +addMethodChaining( 'bypass', bypass ); - if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap ); - if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity; +class RemapNode extends Node { - if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap ); - if ( json.specularIntensityMap !== undefined ) material.specularIntensityMap = getTexture( json.specularIntensityMap ); - if ( json.specularColorMap !== undefined ) material.specularColorMap = getTexture( json.specularColorMap ); + static get type() { - if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap ); - if ( json.envMapRotation !== undefined ) material.envMapRotation.fromArray( json.envMapRotation ); - if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity; + return 'RemapNode'; - if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity; - if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio; + } - if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap ); - if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity; + constructor( node, inLowNode, inHighNode, outLowNode = float( 0 ), outHighNode = float( 1 ) ) { - if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap ); - if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity; + super(); - if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap ); + this.node = node; + this.inLowNode = inLowNode; + this.inHighNode = inHighNode; + this.outLowNode = outLowNode; + this.outHighNode = outHighNode; - if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap ); - if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap ); - if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap ); - if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale ); + this.doClamp = true; - if ( json.iridescenceMap !== undefined ) material.iridescenceMap = getTexture( json.iridescenceMap ); - if ( json.iridescenceThicknessMap !== undefined ) material.iridescenceThicknessMap = getTexture( json.iridescenceThicknessMap ); + } - if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap ); - if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap ); + setup() { - if ( json.anisotropyMap !== undefined ) material.anisotropyMap = getTexture( json.anisotropyMap ); + const { node, inLowNode, inHighNode, outLowNode, outHighNode, doClamp } = this; - if ( json.sheenColorMap !== undefined ) material.sheenColorMap = getTexture( json.sheenColorMap ); - if ( json.sheenRoughnessMap !== undefined ) material.sheenRoughnessMap = getTexture( json.sheenRoughnessMap ); + let t = node.sub( inLowNode ).div( inHighNode.sub( inLowNode ) ); - return material; + if ( doClamp === true ) t = t.clamp(); + + return t.mul( outHighNode.sub( outLowNode ) ).add( outLowNode ); } - setTextures( value ) { +} - this.textures = value; - return this; +const remap = /*@__PURE__*/ nodeProxy( RemapNode, null, null, { doClamp: false } ); +const remapClamp = /*@__PURE__*/ nodeProxy( RemapNode ); - } +addMethodChaining( 'remap', remap ); +addMethodChaining( 'remapClamp', remapClamp ); - static createMaterialFromType( type ) { +class ExpressionNode extends Node { - const materialLib = { - ShadowMaterial, - SpriteMaterial, - RawShaderMaterial, - ShaderMaterial, - PointsMaterial, - MeshPhysicalMaterial, - MeshStandardMaterial, - MeshPhongMaterial, - MeshToonMaterial, - MeshNormalMaterial, - MeshLambertMaterial, - MeshDepthMaterial, - MeshDistanceMaterial, - MeshBasicMaterial, - MeshMatcapMaterial, - LineDashedMaterial, - LineBasicMaterial, - Material - }; + static get type() { - return new materialLib[ type ](); + return 'ExpressionNode'; } -} - -class LoaderUtils { + constructor( snippet = '', nodeType = 'void' ) { - static decodeText( array ) { // @deprecated, r165 + super( nodeType ); - console.warn( 'THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead.' ); + this.snippet = snippet; - if ( typeof TextDecoder !== 'undefined' ) { + } - return new TextDecoder().decode( array ); + generate( builder, output ) { - } + const type = this.getNodeType( builder ); + const snippet = this.snippet; - // Avoid the String.fromCharCode.apply(null, array) shortcut, which - // throws a "maximum call stack size exceeded" error for large arrays. + if ( type === 'void' ) { - let s = ''; + builder.addLineFlowCode( snippet, this ); - for ( let i = 0, il = array.length; i < il; i ++ ) { + } else { - // Implicitly assumes little-endian. - s += String.fromCharCode( array[ i ] ); + return builder.format( `( ${ snippet } )`, type, output ); } - try { + } - // merges multi-byte utf-8 characters. +} - return decodeURIComponent( escape( s ) ); +const expression = /*@__PURE__*/ nodeProxy( ExpressionNode ); - } catch ( e ) { // see #16358 +const Discard = ( conditional ) => ( conditional ? select( conditional, expression( 'discard' ) ) : expression( 'discard' ) ).append(); +const Return = () => expression( 'return' ).append(); - return s; +addMethodChaining( 'discard', Discard ); - } +class RenderOutputNode extends TempNode { + + static get type() { + + return 'RenderOutputNode'; } - static extractUrlBase( url ) { + constructor( colorNode, toneMapping, outputColorSpace ) { - const index = url.lastIndexOf( '/' ); + super( 'vec4' ); - if ( index === - 1 ) return './'; + this.colorNode = colorNode; + this.toneMapping = toneMapping; + this.outputColorSpace = outputColorSpace; - return url.slice( 0, index + 1 ); + this.isRenderOutput = true; } - static resolveURL( url, path ) { + setup( { context } ) { - // Invalid URL - if ( typeof url !== 'string' || url === '' ) return ''; + let outputNode = this.colorNode || context.color; - // Host Relative URL - if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) { + // tone mapping - path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' ); + const toneMapping = ( this.toneMapping !== null ? this.toneMapping : context.toneMapping ) || NoToneMapping; + const outputColorSpace = ( this.outputColorSpace !== null ? this.outputColorSpace : context.outputColorSpace ) || NoColorSpace; + + if ( toneMapping !== NoToneMapping ) { + + outputNode = outputNode.toneMapping( toneMapping ); } - // Absolute URL http://,https://,// - if ( /^(https?:)?\/\//i.test( url ) ) return url; + // working to output color space - // Data URI - if ( /^data:.*,.*$/i.test( url ) ) return url; + if ( outputColorSpace !== NoColorSpace && outputColorSpace !== ColorManagement.workingColorSpace ) { - // Blob URL - if ( /^blob:.*$/i.test( url ) ) return url; + outputNode = outputNode.workingToColorSpace( outputColorSpace ); - // Relative URL - return path + url; + } + + return outputNode; } } -class InstancedBufferGeometry extends BufferGeometry { +const renderOutput = ( color, toneMapping = null, outputColorSpace = null ) => nodeObject( new RenderOutputNode( nodeObject( color ), toneMapping, outputColorSpace ) ); - constructor() { +addMethodChaining( 'renderOutput', renderOutput ); - super(); +// Non-PURE exports list, side-effects are required here. +// TSL Base Syntax - this.isInstancedBufferGeometry = true; - this.type = 'InstancedBufferGeometry'; - this.instanceCount = Infinity; +function addNodeElement( name/*, nodeElement*/ ) { - } + console.warn( 'THREE.TSLBase: AddNodeElement has been removed in favor of tree-shaking. Trying add', name ); - copy( source ) { +} - super.copy( source ); +class AttributeNode extends Node { - this.instanceCount = source.instanceCount; + static get type() { - return this; + return 'AttributeNode'; } - toJSON() { - - const data = super.toJSON(); + constructor( attributeName, nodeType = null ) { - data.instanceCount = this.instanceCount; + super( nodeType ); - data.isInstancedBufferGeometry = true; + this.global = true; - return data; + this._attributeName = attributeName; } -} + getHash( builder ) { -class BufferGeometryLoader extends Loader { + return this.getAttributeName( builder ); - constructor( manager ) { + } - super( manager ); + getNodeType( builder ) { - } + let nodeType = this.nodeType; - load( url, onLoad, onProgress, onError ) { + if ( nodeType === null ) { - const scope = this; + const attributeName = this.getAttributeName( builder ); - const loader = new FileLoader( scope.manager ); - loader.setPath( scope.path ); - loader.setRequestHeader( scope.requestHeader ); - loader.setWithCredentials( scope.withCredentials ); - loader.load( url, function ( text ) { + if ( builder.hasGeometryAttribute( attributeName ) ) { - try { + const attribute = builder.geometry.getAttribute( attributeName ); - onLoad( scope.parse( JSON.parse( text ) ) ); + nodeType = builder.getTypeFromAttribute( attribute ); - } catch ( e ) { + } else { - if ( onError ) { + nodeType = 'float'; - onError( e ); + } - } else { + } - console.error( e ); + return nodeType; - } + } - scope.manager.itemError( url ); + setAttributeName( attributeName ) { - } + this._attributeName = attributeName; - }, onProgress, onError ); + return this; } - parse( json ) { + getAttributeName( /*builder*/ ) { - const interleavedBufferMap = {}; - const arrayBufferMap = {}; + return this._attributeName; - function getInterleavedBuffer( json, uuid ) { + } - if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ]; + generate( builder ) { - const interleavedBuffers = json.interleavedBuffers; - const interleavedBuffer = interleavedBuffers[ uuid ]; + const attributeName = this.getAttributeName( builder ); + const nodeType = this.getNodeType( builder ); + const geometryAttribute = builder.hasGeometryAttribute( attributeName ); - const buffer = getArrayBuffer( json, interleavedBuffer.buffer ); + if ( geometryAttribute === true ) { - const array = getTypedArray( interleavedBuffer.type, buffer ); - const ib = new InterleavedBuffer( array, interleavedBuffer.stride ); - ib.uuid = interleavedBuffer.uuid; + const attribute = builder.geometry.getAttribute( attributeName ); + const attributeType = builder.getTypeFromAttribute( attribute ); - interleavedBufferMap[ uuid ] = ib; + const nodeAttribute = builder.getAttribute( attributeName, attributeType ); - return ib; + if ( builder.shaderStage === 'vertex' ) { - } + return builder.format( nodeAttribute.name, attributeType, nodeType ); - function getArrayBuffer( json, uuid ) { + } else { - if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ]; + const nodeVarying = varying( this ); - const arrayBuffers = json.arrayBuffers; - const arrayBuffer = arrayBuffers[ uuid ]; + return nodeVarying.build( builder, nodeType ); - const ab = new Uint32Array( arrayBuffer ).buffer; + } - arrayBufferMap[ uuid ] = ab; + } else { - return ab; + console.warn( `AttributeNode: Vertex attribute "${ attributeName }" not found on geometry.` ); + + return builder.generateConst( nodeType ); } - const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry(); + } - const index = json.data.index; + serialize( data ) { - if ( index !== undefined ) { + super.serialize( data ); - const typedArray = getTypedArray( index.type, index.array ); - geometry.setIndex( new BufferAttribute( typedArray, 1 ) ); - - } - - const attributes = json.data.attributes; - - for ( const key in attributes ) { - - const attribute = attributes[ key ]; - let bufferAttribute; + data.global = this.global; + data._attributeName = this._attributeName; - if ( attribute.isInterleavedBufferAttribute ) { + } - const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data ); - bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized ); + deserialize( data ) { - } else { + super.deserialize( data ); - const typedArray = getTypedArray( attribute.type, attribute.array ); - const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute; - bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized ); + this.global = data.global; + this._attributeName = data._attributeName; - } + } - if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name; - if ( attribute.usage !== undefined ) bufferAttribute.setUsage( attribute.usage ); +} - geometry.setAttribute( key, bufferAttribute ); +const attribute = ( name, nodeType ) => nodeObject( new AttributeNode( name, nodeType ) ); - } +const uv = ( index ) => attribute( 'uv' + ( index > 0 ? index : '' ), 'vec2' ); - const morphAttributes = json.data.morphAttributes; +class TextureSizeNode extends Node { - if ( morphAttributes ) { + static get type() { - for ( const key in morphAttributes ) { + return 'TextureSizeNode'; - const attributeArray = morphAttributes[ key ]; + } - const array = []; + constructor( textureNode, levelNode = null ) { - for ( let i = 0, il = attributeArray.length; i < il; i ++ ) { + super( 'uvec2' ); - const attribute = attributeArray[ i ]; - let bufferAttribute; + this.isTextureSizeNode = true; - if ( attribute.isInterleavedBufferAttribute ) { + this.textureNode = textureNode; + this.levelNode = levelNode; - const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data ); - bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized ); + } - } else { + generate( builder, output ) { - const typedArray = getTypedArray( attribute.type, attribute.array ); - bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ); + const textureProperty = this.textureNode.build( builder, 'property' ); + const level = this.levelNode === null ? '0' : this.levelNode.build( builder, 'int' ); - } + return builder.format( `${ builder.getMethod( 'textureDimensions' ) }( ${ textureProperty }, ${ level } )`, this.getNodeType( builder ), output ); - if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name; - array.push( bufferAttribute ); + } - } +} - geometry.morphAttributes[ key ] = array; +const textureSize = /*@__PURE__*/ nodeProxy( TextureSizeNode ); - } +class MaxMipLevelNode extends UniformNode { - } + static get type() { - const morphTargetsRelative = json.data.morphTargetsRelative; + return 'MaxMipLevelNode'; - if ( morphTargetsRelative ) { + } - geometry.morphTargetsRelative = true; + constructor( textureNode ) { - } + super( 0 ); - const groups = json.data.groups || json.data.drawcalls || json.data.offsets; + this._textureNode = textureNode; - if ( groups !== undefined ) { + this.updateType = NodeUpdateType.FRAME; - for ( let i = 0, n = groups.length; i !== n; ++ i ) { + } - const group = groups[ i ]; + get textureNode() { - geometry.addGroup( group.start, group.count, group.materialIndex ); + return this._textureNode; - } + } - } + get texture() { - const boundingSphere = json.data.boundingSphere; + return this._textureNode.value; - if ( boundingSphere !== undefined ) { + } - const center = new Vector3(); + update() { - if ( boundingSphere.center !== undefined ) { + const texture = this.texture; + const images = texture.images; + const image = ( images && images.length > 0 ) ? ( ( images[ 0 ] && images[ 0 ].image ) || images[ 0 ] ) : texture.image; - center.fromArray( boundingSphere.center ); + if ( image && image.width !== undefined ) { - } + const { width, height } = image; - geometry.boundingSphere = new Sphere( center, boundingSphere.radius ); + this.value = Math.log2( Math.max( width, height ) ); } - if ( json.name ) geometry.name = json.name; - if ( json.userData ) geometry.userData = json.userData; - - return geometry; - } } -class ObjectLoader extends Loader { +const maxMipLevel = /*@__PURE__*/ nodeProxy( MaxMipLevelNode ); - constructor( manager ) { +class TextureNode extends UniformNode { - super( manager ); + static get type() { - } + return 'TextureNode'; - load( url, onLoad, onProgress, onError ) { + } - const scope = this; + constructor( value, uvNode = null, levelNode = null, biasNode = null ) { - const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; - this.resourcePath = this.resourcePath || path; + super( value ); - const loader = new FileLoader( this.manager ); - loader.setPath( this.path ); - loader.setRequestHeader( this.requestHeader ); - loader.setWithCredentials( this.withCredentials ); - loader.load( url, function ( text ) { + this.isTextureNode = true; - let json = null; + this.uvNode = uvNode; + this.levelNode = levelNode; + this.biasNode = biasNode; + this.compareNode = null; + this.depthNode = null; + this.gradNode = null; - try { + this.sampler = true; + this.updateMatrix = false; + this.updateType = NodeUpdateType.NONE; - json = JSON.parse( text ); + this.referenceNode = null; - } catch ( error ) { + this._value = value; + this._matrixUniform = null; - if ( onError !== undefined ) onError( error ); + this.setUpdateMatrix( uvNode === null ); - console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message ); + } - return; + set value( value ) { - } + if ( this.referenceNode ) { - const metadata = json.metadata; + this.referenceNode.value = value; - if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { + } else { - if ( onError !== undefined ) onError( new Error( 'THREE.ObjectLoader: Can\'t load ' + url ) ); + this._value = value; - console.error( 'THREE.ObjectLoader: Can\'t load ' + url ); - return; + } - } + } - scope.parse( json, onLoad ); + get value() { - }, onProgress, onError ); + return this.referenceNode ? this.referenceNode.value : this._value; } - async loadAsync( url, onProgress ) { + getUniformHash( /*builder*/ ) { - const scope = this; + return this.value.uuid; - const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; - this.resourcePath = this.resourcePath || path; + } - const loader = new FileLoader( this.manager ); - loader.setPath( this.path ); - loader.setRequestHeader( this.requestHeader ); - loader.setWithCredentials( this.withCredentials ); + getNodeType( /*builder*/ ) { - const text = await loader.loadAsync( url, onProgress ); + if ( this.value.isDepthTexture === true ) return 'float'; - const json = JSON.parse( text ); + if ( this.value.type === UnsignedIntType ) { - const metadata = json.metadata; + return 'uvec4'; - if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { + } else if ( this.value.type === IntType ) { - throw new Error( 'THREE.ObjectLoader: Can\'t load ' + url ); + return 'ivec4'; } - return await scope.parseAsync( json ); + return 'vec4'; } - parse( json, onLoad ) { + getInputType( /*builder*/ ) { - const animations = this.parseAnimations( json.animations ); - const shapes = this.parseShapes( json.shapes ); - const geometries = this.parseGeometries( json.geometries, shapes ); + return 'texture'; - const images = this.parseImages( json.images, function () { + } - if ( onLoad !== undefined ) onLoad( object ); + getDefaultUV() { - } ); + return uv( this.value.channel ); - const textures = this.parseTextures( json.textures, images ); - const materials = this.parseMaterials( json.materials, textures ); + } - const object = this.parseObject( json.object, geometries, materials, textures, animations ); - const skeletons = this.parseSkeletons( json.skeletons, object ); + updateReference( /*state*/ ) { - this.bindSkeletons( object, skeletons ); - this.bindLightTargets( object ); + return this.value; - // + } - if ( onLoad !== undefined ) { + getTransformedUV( uvNode ) { - let hasImages = false; + if ( this._matrixUniform === null ) this._matrixUniform = uniform( this.value.matrix ); - for ( const uuid in images ) { + return this._matrixUniform.mul( vec3( uvNode, 1 ) ).xy; - if ( images[ uuid ].data instanceof HTMLImageElement ) { + } - hasImages = true; - break; + setUpdateMatrix( value ) { - } + this.updateMatrix = value; + this.updateType = value ? NodeUpdateType.FRAME : NodeUpdateType.NONE; - } + return this; - if ( hasImages === false ) onLoad( object ); + } - } + setupUV( builder, uvNode ) { - return object; + const texture = this.value; - } + if ( builder.isFlipY() && ( texture.isRenderTargetTexture === true || texture.isFramebufferTexture === true || texture.isDepthTexture === true ) ) { - async parseAsync( json ) { + if ( this.sampler ) { - const animations = this.parseAnimations( json.animations ); - const shapes = this.parseShapes( json.shapes ); - const geometries = this.parseGeometries( json.geometries, shapes ); + uvNode = uvNode.flipY(); - const images = await this.parseImagesAsync( json.images ); + } else { - const textures = this.parseTextures( json.textures, images ); - const materials = this.parseMaterials( json.materials, textures ); + uvNode = uvNode.setY( int( textureSize( this, this.levelNode ).y ).sub( uvNode.y ).sub( 1 ) ); - const object = this.parseObject( json.object, geometries, materials, textures, animations ); - const skeletons = this.parseSkeletons( json.skeletons, object ); + } - this.bindSkeletons( object, skeletons ); - this.bindLightTargets( object ); + } - return object; + return uvNode; } - parseShapes( json ) { - - const shapes = {}; + setup( builder ) { - if ( json !== undefined ) { + const properties = builder.getNodeProperties( this ); + properties.referenceNode = this.referenceNode; - for ( let i = 0, l = json.length; i < l; i ++ ) { + // - const shape = new Shape().fromJSON( json[ i ] ); + let uvNode = this.uvNode; - shapes[ shape.uuid ] = shape; + if ( ( uvNode === null || builder.context.forceUVContext === true ) && builder.context.getUV ) { - } + uvNode = builder.context.getUV( this ); } - return shapes; - - } + if ( ! uvNode ) uvNode = this.getDefaultUV(); - parseSkeletons( json, object ) { + if ( this.updateMatrix === true ) { - const skeletons = {}; - const bones = {}; + uvNode = this.getTransformedUV( uvNode ); - // generate bone lookup table + } - object.traverse( function ( child ) { + uvNode = this.setupUV( builder, uvNode ); - if ( child.isBone ) bones[ child.uuid ] = child; + // - } ); + let levelNode = this.levelNode; - // create skeletons + if ( levelNode === null && builder.context.getTextureLevel ) { - if ( json !== undefined ) { + levelNode = builder.context.getTextureLevel( this ); - for ( let i = 0, l = json.length; i < l; i ++ ) { + } - const skeleton = new Skeleton().fromJSON( json[ i ], bones ); + // - skeletons[ skeleton.uuid ] = skeleton; + properties.uvNode = uvNode; + properties.levelNode = levelNode; + properties.biasNode = this.biasNode; + properties.compareNode = this.compareNode; + properties.gradNode = this.gradNode; + properties.depthNode = this.depthNode; - } + } - } + generateUV( builder, uvNode ) { - return skeletons; + return uvNode.build( builder, this.sampler === true ? 'vec2' : 'ivec2' ); } - parseGeometries( json, shapes ) { + generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, biasSnippet, depthSnippet, compareSnippet, gradSnippet ) { - const geometries = {}; + const texture = this.value; - if ( json !== undefined ) { + let snippet; - const bufferGeometryLoader = new BufferGeometryLoader(); + if ( levelSnippet ) { - for ( let i = 0, l = json.length; i < l; i ++ ) { + snippet = builder.generateTextureLevel( texture, textureProperty, uvSnippet, levelSnippet, depthSnippet ); - let geometry; - const data = json[ i ]; + } else if ( biasSnippet ) { - switch ( data.type ) { + snippet = builder.generateTextureBias( texture, textureProperty, uvSnippet, biasSnippet, depthSnippet ); - case 'BufferGeometry': - case 'InstancedBufferGeometry': + } else if ( gradSnippet ) { - geometry = bufferGeometryLoader.parse( data ); - break; + snippet = builder.generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet, depthSnippet ); - default: + } else if ( compareSnippet ) { - if ( data.type in Geometries$1 ) { + snippet = builder.generateTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, depthSnippet ); - geometry = Geometries$1[ data.type ].fromJSON( data, shapes ); + } else if ( this.sampler === false ) { - } else { + snippet = builder.generateTextureLoad( texture, textureProperty, uvSnippet, depthSnippet ); - console.warn( `THREE.ObjectLoader: Unsupported geometry type "${ data.type }"` ); + } else { - } + snippet = builder.generateTexture( texture, textureProperty, uvSnippet, depthSnippet ); - } + } - geometry.uuid = data.uuid; + return snippet; - if ( data.name !== undefined ) geometry.name = data.name; - if ( data.userData !== undefined ) geometry.userData = data.userData; + } - geometries[ data.uuid ] = geometry; + generate( builder, output ) { - } + const properties = builder.getNodeProperties( this ); - } + const texture = this.value; - return geometries; + if ( ! texture || texture.isTexture !== true ) { - } + throw new Error( 'TextureNode: Need a three.js texture.' ); - parseMaterials( json, textures ) { + } - const cache = {}; // MultiMaterial - const materials = {}; + const textureProperty = super.generate( builder, 'property' ); - if ( json !== undefined ) { + if ( output === 'sampler' ) { - const loader = new MaterialLoader(); - loader.setTextures( textures ); + return textureProperty + '_sampler'; - for ( let i = 0, l = json.length; i < l; i ++ ) { + } else if ( builder.isReference( output ) ) { - const data = json[ i ]; + return textureProperty; - if ( cache[ data.uuid ] === undefined ) { + } else { - cache[ data.uuid ] = loader.parse( data ); + const nodeData = builder.getDataFromNode( this ); - } + let propertyName = nodeData.propertyName; - materials[ data.uuid ] = cache[ data.uuid ]; + if ( propertyName === undefined ) { - } + const { uvNode, levelNode, biasNode, compareNode, depthNode, gradNode } = properties; - } + const uvSnippet = this.generateUV( builder, uvNode ); + const levelSnippet = levelNode ? levelNode.build( builder, 'float' ) : null; + const biasSnippet = biasNode ? biasNode.build( builder, 'float' ) : null; + const depthSnippet = depthNode ? depthNode.build( builder, 'int' ) : null; + const compareSnippet = compareNode ? compareNode.build( builder, 'float' ) : null; + const gradSnippet = gradNode ? [ gradNode[ 0 ].build( builder, 'vec2' ), gradNode[ 1 ].build( builder, 'vec2' ) ] : null; - return materials; + const nodeVar = builder.getVarFromNode( this ); - } + propertyName = builder.getPropertyName( nodeVar ); - parseAnimations( json ) { + const snippet = this.generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, biasSnippet, depthSnippet, compareSnippet, gradSnippet ); - const animations = {}; + builder.addLineFlowCode( `${propertyName} = ${snippet}`, this ); - if ( json !== undefined ) { + nodeData.snippet = snippet; + nodeData.propertyName = propertyName; - for ( let i = 0; i < json.length; i ++ ) { + } - const data = json[ i ]; + let snippet = propertyName; + const nodeType = this.getNodeType( builder ); - const clip = AnimationClip.parse( data ); + if ( builder.needsToWorkingColorSpace( texture ) ) { - animations[ clip.uuid ] = clip; + snippet = colorSpaceToWorking( expression( snippet, nodeType ), texture.colorSpace ).setup( builder ).build( builder, nodeType ); } - } + return builder.format( snippet, nodeType, output ); - return animations; + } } - parseImages( json, onLoad ) { + setSampler( value ) { - const scope = this; - const images = {}; + this.sampler = value; - let loader; + return this; - function loadImage( url ) { + } - scope.manager.itemStart( url ); + getSampler() { - return loader.load( url, function () { + return this.sampler; - scope.manager.itemEnd( url ); + } - }, undefined, function () { + // @TODO: Move to TSL - scope.manager.itemError( url ); - scope.manager.itemEnd( url ); + uv( uvNode ) { - } ); + const textureNode = this.clone(); + textureNode.uvNode = nodeObject( uvNode ); + textureNode.referenceNode = this.getSelf(); - } + return nodeObject( textureNode ); - function deserializeImage( image ) { + } - if ( typeof image === 'string' ) { + blur( amountNode ) { - const url = image; + const textureNode = this.clone(); + textureNode.biasNode = nodeObject( amountNode ).mul( maxMipLevel( textureNode ) ); + textureNode.referenceNode = this.getSelf(); - const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url; + return nodeObject( textureNode ); - return loadImage( path ); + } - } else { + level( levelNode ) { - if ( image.data ) { + const textureNode = this.clone(); + textureNode.levelNode = nodeObject( levelNode ); + textureNode.referenceNode = this.getSelf(); - return { - data: getTypedArray( image.type, image.data ), - width: image.width, - height: image.height - }; + return nodeObject( textureNode ); - } else { + } - return null; + size( levelNode ) { - } + return textureSize( this, levelNode ); - } + } - } + bias( biasNode ) { - if ( json !== undefined && json.length > 0 ) { + const textureNode = this.clone(); + textureNode.biasNode = nodeObject( biasNode ); + textureNode.referenceNode = this.getSelf(); - const manager = new LoadingManager( onLoad ); + return nodeObject( textureNode ); - loader = new ImageLoader( manager ); - loader.setCrossOrigin( this.crossOrigin ); + } - for ( let i = 0, il = json.length; i < il; i ++ ) { + compare( compareNode ) { - const image = json[ i ]; - const url = image.url; + const textureNode = this.clone(); + textureNode.compareNode = nodeObject( compareNode ); + textureNode.referenceNode = this.getSelf(); - if ( Array.isArray( url ) ) { + return nodeObject( textureNode ); - // load array of images e.g CubeTexture + } - const imageArray = []; + grad( gradNodeX, gradNodeY ) { - for ( let j = 0, jl = url.length; j < jl; j ++ ) { + const textureNode = this.clone(); + textureNode.gradNode = [ nodeObject( gradNodeX ), nodeObject( gradNodeY ) ]; + textureNode.referenceNode = this.getSelf(); - const currentUrl = url[ j ]; + return nodeObject( textureNode ); - const deserializedImage = deserializeImage( currentUrl ); + } - if ( deserializedImage !== null ) { + depth( depthNode ) { - if ( deserializedImage instanceof HTMLImageElement ) { + const textureNode = this.clone(); + textureNode.depthNode = nodeObject( depthNode ); + textureNode.referenceNode = this.getSelf(); - imageArray.push( deserializedImage ); + return nodeObject( textureNode ); - } else { + } - // special case: handle array of data textures for cube textures + // -- - imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) ); + serialize( data ) { - } + super.serialize( data ); - } + data.value = this.value.toJSON( data.meta ).uuid; + data.sampler = this.sampler; + data.updateMatrix = this.updateMatrix; + data.updateType = this.updateType; - } + } - images[ image.uuid ] = new Source( imageArray ); + deserialize( data ) { - } else { + super.deserialize( data ); - // load single image + this.value = data.meta.textures[ data.value ]; + this.sampler = data.sampler; + this.updateMatrix = data.updateMatrix; + this.updateType = data.updateType; - const deserializedImage = deserializeImage( image.url ); - images[ image.uuid ] = new Source( deserializedImage ); + } + update() { - } + const texture = this.value; + const matrixUniform = this._matrixUniform; - } + if ( matrixUniform !== null ) matrixUniform.value = texture.matrix; - } + if ( texture.matrixAutoUpdate === true ) { - return images; + texture.updateMatrix(); + + } } - async parseImagesAsync( json ) { + clone() { - const scope = this; - const images = {}; + const newNode = new this.constructor( this.value, this.uvNode, this.levelNode, this.biasNode ); + newNode.sampler = this.sampler; - let loader; + return newNode; - async function deserializeImage( image ) { + } - if ( typeof image === 'string' ) { +} - const url = image; +const texture = /*@__PURE__*/ nodeProxy( TextureNode ); +const textureLoad = ( ...params ) => texture( ...params ).setSampler( false ); - const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url; +//export const textureLevel = ( value, uv, level ) => texture( value, uv ).level( level ); - return await loader.loadAsync( path ); +const sampler = ( aTexture ) => ( aTexture.isNode === true ? aTexture : texture( aTexture ) ).convert( 'sampler' ); - } else { +const cameraNear = /*@__PURE__*/ uniform( 'float' ).label( 'cameraNear' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.near ); +const cameraFar = /*@__PURE__*/ uniform( 'float' ).label( 'cameraFar' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.far ); +const cameraLogDepth = /*@__PURE__*/ uniform( 'float' ).label( 'cameraLogDepth' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); +const cameraProjectionMatrix = /*@__PURE__*/ uniform( 'mat4' ).label( 'cameraProjectionMatrix' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.projectionMatrix ); +const cameraProjectionMatrixInverse = /*@__PURE__*/ uniform( 'mat4' ).label( 'cameraProjectionMatrixInverse' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.projectionMatrixInverse ); +const cameraViewMatrix = /*@__PURE__*/ uniform( 'mat4' ).label( 'cameraViewMatrix' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.matrixWorldInverse ); +const cameraWorldMatrix = /*@__PURE__*/ uniform( 'mat4' ).label( 'cameraWorldMatrix' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.matrixWorld ); +const cameraNormalMatrix = /*@__PURE__*/ uniform( 'mat3' ).label( 'cameraNormalMatrix' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.normalMatrix ); +const cameraPosition = /*@__PURE__*/ uniform( new Vector3() ).label( 'cameraPosition' ).setGroup( renderGroup ).onRenderUpdate( ( { camera }, self ) => self.value.setFromMatrixPosition( camera.matrixWorld ) ); - if ( image.data ) { +class Object3DNode extends Node { - return { - data: getTypedArray( image.type, image.data ), - width: image.width, - height: image.height - }; + static get type() { - } else { + return 'Object3DNode'; - return null; + } - } + constructor( scope, object3d = null ) { - } + super(); - } + this.scope = scope; + this.object3d = object3d; - if ( json !== undefined && json.length > 0 ) { + this.updateType = NodeUpdateType.OBJECT; - loader = new ImageLoader( this.manager ); - loader.setCrossOrigin( this.crossOrigin ); + this._uniformNode = new UniformNode( null ); - for ( let i = 0, il = json.length; i < il; i ++ ) { + } - const image = json[ i ]; - const url = image.url; + getNodeType() { - if ( Array.isArray( url ) ) { + const scope = this.scope; - // load array of images e.g CubeTexture + if ( scope === Object3DNode.WORLD_MATRIX ) { - const imageArray = []; + return 'mat4'; - for ( let j = 0, jl = url.length; j < jl; j ++ ) { + } else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION || scope === Object3DNode.SCALE ) { - const currentUrl = url[ j ]; + return 'vec3'; - const deserializedImage = await deserializeImage( currentUrl ); + } - if ( deserializedImage !== null ) { + } - if ( deserializedImage instanceof HTMLImageElement ) { + update( frame ) { - imageArray.push( deserializedImage ); + const object = this.object3d; + const uniformNode = this._uniformNode; + const scope = this.scope; - } else { + if ( scope === Object3DNode.WORLD_MATRIX ) { - // special case: handle array of data textures for cube textures + uniformNode.value = object.matrixWorld; - imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) ); + } else if ( scope === Object3DNode.POSITION ) { - } + uniformNode.value = uniformNode.value || new Vector3(); - } + uniformNode.value.setFromMatrixPosition( object.matrixWorld ); - } + } else if ( scope === Object3DNode.SCALE ) { - images[ image.uuid ] = new Source( imageArray ); + uniformNode.value = uniformNode.value || new Vector3(); - } else { + uniformNode.value.setFromMatrixScale( object.matrixWorld ); - // load single image + } else if ( scope === Object3DNode.DIRECTION ) { - const deserializedImage = await deserializeImage( image.url ); - images[ image.uuid ] = new Source( deserializedImage ); + uniformNode.value = uniformNode.value || new Vector3(); - } + object.getWorldDirection( uniformNode.value ); - } + } else if ( scope === Object3DNode.VIEW_POSITION ) { - } + const camera = frame.camera; - return images; + uniformNode.value = uniformNode.value || new Vector3(); + uniformNode.value.setFromMatrixPosition( object.matrixWorld ); + + uniformNode.value.applyMatrix4( camera.matrixWorldInverse ); + + } } - parseTextures( json, images ) { + generate( builder ) { - function parseConstant( value, type ) { + const scope = this.scope; - if ( typeof value === 'number' ) return value; + if ( scope === Object3DNode.WORLD_MATRIX ) { - console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value ); + this._uniformNode.nodeType = 'mat4'; - return type[ value ]; + } else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION || scope === Object3DNode.SCALE ) { - } + this._uniformNode.nodeType = 'vec3'; - const textures = {}; + } - if ( json !== undefined ) { + return this._uniformNode.build( builder ); - for ( let i = 0, l = json.length; i < l; i ++ ) { + } - const data = json[ i ]; + serialize( data ) { - if ( data.image === undefined ) { + super.serialize( data ); - console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid ); + data.scope = this.scope; - } + } - if ( images[ data.image ] === undefined ) { + deserialize( data ) { - console.warn( 'THREE.ObjectLoader: Undefined image', data.image ); + super.deserialize( data ); - } + this.scope = data.scope; - const source = images[ data.image ]; - const image = source.data; + } - let texture; +} - if ( Array.isArray( image ) ) { +Object3DNode.WORLD_MATRIX = 'worldMatrix'; +Object3DNode.POSITION = 'position'; +Object3DNode.SCALE = 'scale'; +Object3DNode.VIEW_POSITION = 'viewPosition'; +Object3DNode.DIRECTION = 'direction'; - texture = new CubeTexture(); +const objectDirection = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.DIRECTION ); +const objectWorldMatrix = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.WORLD_MATRIX ); +const objectPosition = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.POSITION ); +const objectScale = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.SCALE ); +const objectViewPosition = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.VIEW_POSITION ); - if ( image.length === 6 ) texture.needsUpdate = true; +class ModelNode extends Object3DNode { - } else { + static get type() { - if ( image && image.data ) { + return 'ModelNode'; - texture = new DataTexture(); + } - } else { + constructor( scope ) { - texture = new Texture(); + super( scope ); - } + } - if ( image ) texture.needsUpdate = true; // textures can have undefined image data + update( frame ) { - } + this.object3d = frame.object; - texture.source = source; + super.update( frame ); - texture.uuid = data.uuid; + } - if ( data.name !== undefined ) texture.name = data.name; +} - if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); - if ( data.channel !== undefined ) texture.channel = data.channel; +const modelDirection = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.DIRECTION ); +const modelWorldMatrix = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.WORLD_MATRIX ); +const modelPosition = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.POSITION ); +const modelScale = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.SCALE ); +const modelViewPosition = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.VIEW_POSITION ); +const modelNormalMatrix = /*@__PURE__*/ uniform( new Matrix3() ).onObjectUpdate( ( { object }, self ) => self.value.getNormalMatrix( object.matrixWorld ) ); +const modelWorldMatrixInverse = /*@__PURE__*/ uniform( new Matrix4() ).onObjectUpdate( ( { object }, self ) => self.value.copy( object.matrixWorld ).invert() ); +const modelViewMatrix = /*@__PURE__*/ cameraViewMatrix.mul( modelWorldMatrix ).toVar( 'modelViewMatrix' ); - if ( data.offset !== undefined ) texture.offset.fromArray( data.offset ); - if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat ); - if ( data.center !== undefined ) texture.center.fromArray( data.center ); - if ( data.rotation !== undefined ) texture.rotation = data.rotation; +const highPrecisionModelViewMatrix = /*@__PURE__*/ ( Fn( ( builder ) => { - if ( data.wrap !== undefined ) { + builder.context.isHighPrecisionModelViewMatrix = true; - texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING ); - texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING ); + return uniform( 'mat4' ).onObjectUpdate( ( { object, camera } ) => { - } + return object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); - if ( data.format !== undefined ) texture.format = data.format; - if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat; - if ( data.type !== undefined ) texture.type = data.type; - if ( data.colorSpace !== undefined ) texture.colorSpace = data.colorSpace; + } ); - if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); - if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); - if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy; +} ).once() )().toVar( 'highPrecisionModelViewMatrix' ); - if ( data.flipY !== undefined ) texture.flipY = data.flipY; +const highPrecisionModelNormalViewMatrix = /*@__PURE__*/ ( Fn( ( builder ) => { - if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps; - if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha; - if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment; - if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction; + const isHighPrecisionModelViewMatrix = builder.context.isHighPrecisionModelViewMatrix; - if ( data.userData !== undefined ) texture.userData = data.userData; + return uniform( 'mat3' ).onObjectUpdate( ( { object, camera } ) => { - textures[ data.uuid ] = texture; + if ( isHighPrecisionModelViewMatrix !== true ) { - } + object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); } - return textures; + return object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); - } + } ); - parseObject( data, geometries, materials, textures, animations ) { +} ).once() )().toVar( 'highPrecisionModelNormalMatrix' ); - let object; +const positionGeometry = /*@__PURE__*/ attribute( 'position', 'vec3' ); +const positionLocal = /*@__PURE__*/ positionGeometry.varying( 'positionLocal' ); +const positionPrevious = /*@__PURE__*/ positionGeometry.varying( 'positionPrevious' ); +const positionWorld = /*@__PURE__*/ modelWorldMatrix.mul( positionLocal ).xyz.varying( 'v_positionWorld' ); +const positionWorldDirection = /*@__PURE__*/ positionLocal.transformDirection( modelWorldMatrix ).varying( 'v_positionWorldDirection' ).normalize().toVar( 'positionWorldDirection' ); +const positionView = /*@__PURE__*/ modelViewMatrix.mul( positionLocal ).xyz.varying( 'v_positionView' ); +const positionViewDirection = /*@__PURE__*/ positionView.negate().varying( 'v_positionViewDirection' ).normalize().toVar( 'positionViewDirection' ); - function getGeometry( name ) { +class FrontFacingNode extends Node { - if ( geometries[ name ] === undefined ) { + static get type() { - console.warn( 'THREE.ObjectLoader: Undefined geometry', name ); + return 'FrontFacingNode'; - } + } - return geometries[ name ]; + constructor() { - } + super( 'bool' ); - function getMaterial( name ) { + this.isFrontFacingNode = true; - if ( name === undefined ) return undefined; + } - if ( Array.isArray( name ) ) { + generate( builder ) { - const array = []; + const { renderer, material } = builder; - for ( let i = 0, l = name.length; i < l; i ++ ) { + if ( renderer.coordinateSystem === WebGLCoordinateSystem ) { - const uuid = name[ i ]; + if ( material.side === BackSide ) { - if ( materials[ uuid ] === undefined ) { + return 'false'; - console.warn( 'THREE.ObjectLoader: Undefined material', uuid ); + } - } + } - array.push( materials[ uuid ] ); + return builder.getFrontFacing(); - } + } - return array; +} - } +const frontFacing = /*@__PURE__*/ nodeImmutable( FrontFacingNode ); +const faceDirection = /*@__PURE__*/ float( frontFacing ).mul( 2.0 ).sub( 1.0 ); - if ( materials[ name ] === undefined ) { +const normalGeometry = /*@__PURE__*/ attribute( 'normal', 'vec3' ); - console.warn( 'THREE.ObjectLoader: Undefined material', name ); +const normalLocal = /*@__PURE__*/ ( Fn( ( builder ) => { - } + if ( builder.geometry.hasAttribute( 'normal' ) === false ) { - return materials[ name ]; + console.warn( 'TSL.NormalNode: Vertex attribute "normal" not found on geometry.' ); - } + return vec3( 0, 1, 0 ); - function getTexture( uuid ) { + } - if ( textures[ uuid ] === undefined ) { + return normalGeometry; - console.warn( 'THREE.ObjectLoader: Undefined texture', uuid ); +}, 'vec3' ).once() )().toVar( 'normalLocal' ); - } +const normalFlat = /*@__PURE__*/ positionView.dFdx().cross( positionView.dFdy() ).normalize().toVar( 'normalFlat' ); - return textures[ uuid ]; +const normalView = /*@__PURE__*/ ( Fn( ( builder ) => { - } + let node; - let geometry, material; + if ( builder.material.flatShading === true ) { - switch ( data.type ) { + node = normalFlat; - case 'Scene': + } else { - object = new Scene(); + node = varying( transformNormalToView( normalLocal ), 'v_normalView' ).normalize(); - if ( data.background !== undefined ) { + } - if ( Number.isInteger( data.background ) ) { + return node; - object.background = new Color( data.background ); +}, 'vec3' ).once() )().toVar( 'normalView' ); - } else { +const normalWorld = /*@__PURE__*/ varying( normalView.transformDirection( cameraViewMatrix ), 'v_normalWorld' ).normalize().toVar( 'normalWorld' ); - object.background = getTexture( data.background ); +const transformedNormalView = /*@__PURE__*/ ( Fn( ( builder ) => { - } + return builder.context.setupNormal(); - } +}, 'vec3' ).once() )().mul( faceDirection ).toVar( 'transformedNormalView' ); - if ( data.environment !== undefined ) { - object.environment = getTexture( data.environment ); +const transformedNormalWorld = /*@__PURE__*/ transformedNormalView.transformDirection( cameraViewMatrix ).toVar( 'transformedNormalWorld' ); - } +const transformedClearcoatNormalView = /*@__PURE__*/ ( Fn( ( builder ) => { - if ( data.fog !== undefined ) { + return builder.context.setupClearcoatNormal(); - if ( data.fog.type === 'Fog' ) { +}, 'vec3' ).once() )().mul( faceDirection ).toVar( 'transformedClearcoatNormalView' ); - object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far ); +const transformNormal = /*@__PURE__*/ Fn( ( [ normal, matrix = modelWorldMatrix ] ) => { - } else if ( data.fog.type === 'FogExp2' ) { + const m = mat3( matrix ); - object.fog = new FogExp2( data.fog.color, data.fog.density ); + const transformedNormal = normal.div( vec3( m[ 0 ].dot( m[ 0 ] ), m[ 1 ].dot( m[ 1 ] ), m[ 2 ].dot( m[ 2 ] ) ) ); - } + return m.mul( transformedNormal ).xyz; - if ( data.fog.name !== '' ) { +} ); - object.fog.name = data.fog.name; +const transformNormalToView = /*@__PURE__*/ Fn( ( [ normal ], builder ) => { - } + const modelNormalViewMatrix = builder.renderer.nodes.modelNormalViewMatrix; - } + if ( modelNormalViewMatrix !== null ) { - if ( data.backgroundBlurriness !== undefined ) object.backgroundBlurriness = data.backgroundBlurriness; - if ( data.backgroundIntensity !== undefined ) object.backgroundIntensity = data.backgroundIntensity; - if ( data.backgroundRotation !== undefined ) object.backgroundRotation.fromArray( data.backgroundRotation ); + return modelNormalViewMatrix.transformDirection( normal ); - if ( data.environmentIntensity !== undefined ) object.environmentIntensity = data.environmentIntensity; - if ( data.environmentRotation !== undefined ) object.environmentRotation.fromArray( data.environmentRotation ); + } - break; + // - case 'PerspectiveCamera': + const transformedNormal = modelNormalMatrix.mul( normal ); - object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far ); + return cameraViewMatrix.transformDirection( transformedNormal ); - if ( data.focus !== undefined ) object.focus = data.focus; - if ( data.zoom !== undefined ) object.zoom = data.zoom; - if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge; - if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset; - if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); +} ); - break; +const materialRefractionRatio = /*@__PURE__*/ uniform( 0 ).onReference( ( { material } ) => material ).onRenderUpdate( ( { material } ) => material.refractionRatio ); - case 'OrthographicCamera': +const reflectView = /*@__PURE__*/ positionViewDirection.negate().reflect( transformedNormalView ); +const refractView = /*@__PURE__*/ positionViewDirection.negate().refract( transformedNormalView, materialRefractionRatio ); - object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far ); +const reflectVector = /*@__PURE__*/ reflectView.transformDirection( cameraViewMatrix ).toVar( 'reflectVector' ); +const refractVector = /*@__PURE__*/ refractView.transformDirection( cameraViewMatrix ).toVar( 'reflectVector' ); - if ( data.zoom !== undefined ) object.zoom = data.zoom; - if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); +class CubeTextureNode extends TextureNode { - break; + static get type() { - case 'AmbientLight': + return 'CubeTextureNode'; - object = new AmbientLight( data.color, data.intensity ); + } - break; + constructor( value, uvNode = null, levelNode = null, biasNode = null ) { - case 'DirectionalLight': + super( value, uvNode, levelNode, biasNode ); - object = new DirectionalLight( data.color, data.intensity ); - object.target = data.target || ''; + this.isCubeTextureNode = true; - break; + } - case 'PointLight': + getInputType( /*builder*/ ) { - object = new PointLight( data.color, data.intensity, data.distance, data.decay ); + return 'cubeTexture'; - break; + } - case 'RectAreaLight': + getDefaultUV() { - object = new RectAreaLight( data.color, data.intensity, data.width, data.height ); + const texture = this.value; - break; + if ( texture.mapping === CubeReflectionMapping ) { - case 'SpotLight': + return reflectVector; - object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay ); - object.target = data.target || ''; + } else if ( texture.mapping === CubeRefractionMapping ) { - break; + return refractVector; - case 'HemisphereLight': + } else { - object = new HemisphereLight( data.color, data.groundColor, data.intensity ); + console.error( 'THREE.CubeTextureNode: Mapping "%s" not supported.', texture.mapping ); - break; + return vec3( 0, 0, 0 ); - case 'LightProbe': + } - object = new LightProbe().fromJSON( data ); + } - break; + setUpdateMatrix( /*updateMatrix*/ ) { } // Ignore .updateMatrix for CubeTextureNode - case 'SkinnedMesh': + setupUV( builder, uvNode ) { - geometry = getGeometry( data.geometry ); - material = getMaterial( data.material ); + const texture = this.value; - object = new SkinnedMesh( geometry, material ); + if ( builder.renderer.coordinateSystem === WebGPUCoordinateSystem || ! texture.isRenderTargetTexture ) { - if ( data.bindMode !== undefined ) object.bindMode = data.bindMode; - if ( data.bindMatrix !== undefined ) object.bindMatrix.fromArray( data.bindMatrix ); - if ( data.skeleton !== undefined ) object.skeleton = data.skeleton; + return vec3( uvNode.x.negate(), uvNode.yz ); - break; + } else { - case 'Mesh': + return uvNode; - geometry = getGeometry( data.geometry ); - material = getMaterial( data.material ); + } - object = new Mesh( geometry, material ); + } - break; + generateUV( builder, cubeUV ) { - case 'InstancedMesh': + return cubeUV.build( builder, 'vec3' ); - geometry = getGeometry( data.geometry ); - material = getMaterial( data.material ); - const count = data.count; - const instanceMatrix = data.instanceMatrix; - const instanceColor = data.instanceColor; + } - object = new InstancedMesh( geometry, material, count ); - object.instanceMatrix = new InstancedBufferAttribute( new Float32Array( instanceMatrix.array ), 16 ); - if ( instanceColor !== undefined ) object.instanceColor = new InstancedBufferAttribute( new Float32Array( instanceColor.array ), instanceColor.itemSize ); +} - break; +const cubeTexture = /*@__PURE__*/ nodeProxy( CubeTextureNode ); - case 'BatchedMesh': +class BufferNode extends UniformNode { - geometry = getGeometry( data.geometry ); - material = getMaterial( data.material ); + static get type() { - object = new BatchedMesh( data.maxInstanceCount, data.maxVertexCount, data.maxIndexCount, material ); - object.geometry = geometry; - object.perObjectFrustumCulled = data.perObjectFrustumCulled; - object.sortObjects = data.sortObjects; + return 'BufferNode'; - object._drawRanges = data.drawRanges; - object._reservedRanges = data.reservedRanges; + } - object._visibility = data.visibility; - object._active = data.active; - object._bounds = data.bounds.map( bound => { + constructor( value, bufferType, bufferCount = 0 ) { - const box = new Box3(); - box.min.fromArray( bound.boxMin ); - box.max.fromArray( bound.boxMax ); + super( value, bufferType ); - const sphere = new Sphere(); - sphere.radius = bound.sphereRadius; - sphere.center.fromArray( bound.sphereCenter ); + this.isBufferNode = true; - return { - boxInitialized: bound.boxInitialized, - box: box, + this.bufferType = bufferType; + this.bufferCount = bufferCount; - sphereInitialized: bound.sphereInitialized, - sphere: sphere - }; + } - } ); + getElementType( builder ) { - object._maxInstanceCount = data.maxInstanceCount; - object._maxVertexCount = data.maxVertexCount; - object._maxIndexCount = data.maxIndexCount; + return this.getNodeType( builder ); - object._geometryInitialized = data.geometryInitialized; - object._geometryCount = data.geometryCount; + } - object._matricesTexture = getTexture( data.matricesTexture.uuid ); - if ( data.colorsTexture !== undefined ) object._colorsTexture = getTexture( data.colorsTexture.uuid ); + getInputType( /*builder*/ ) { - break; + return 'buffer'; - case 'LOD': + } - object = new LOD(); +} - break; +const buffer = ( value, type, count ) => nodeObject( new BufferNode( value, type, count ) ); - case 'Line': +class UniformArrayElementNode extends ArrayElementNode { - object = new Line( getGeometry( data.geometry ), getMaterial( data.material ) ); + static get type() { - break; + return 'UniformArrayElementNode'; - case 'LineLoop': + } - object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) ); + constructor( arrayBuffer, indexNode ) { - break; + super( arrayBuffer, indexNode ); - case 'LineSegments': + this.isArrayBufferElementNode = true; - object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) ); + } - break; + generate( builder ) { - case 'PointCloud': - case 'Points': + const snippet = super.generate( builder ); + const type = this.getNodeType(); - object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) ); + return builder.format( snippet, 'vec4', type ); - break; + } - case 'Sprite': +} - object = new Sprite( getMaterial( data.material ) ); +class UniformArrayNode extends BufferNode { - break; + static get type() { - case 'Group': + return 'UniformArrayNode'; - object = new Group(); + } - break; + constructor( value, elementType = null ) { - case 'Bone': + super( null, 'vec4' ); - object = new Bone(); + this.array = value; + this.elementType = elementType; - break; + this._elementType = null; + this._elementLength = 0; - default: + this.updateType = NodeUpdateType.RENDER; - object = new Object3D(); + this.isArrayBufferNode = true; - } + } - object.uuid = data.uuid; + getElementType() { - if ( data.name !== undefined ) object.name = data.name; + return this.elementType || this._elementType; - if ( data.matrix !== undefined ) { + } - object.matrix.fromArray( data.matrix ); + getElementLength() { - if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate; - if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale ); + return this._elementLength; - } else { + } - if ( data.position !== undefined ) object.position.fromArray( data.position ); - if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation ); - if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion ); - if ( data.scale !== undefined ) object.scale.fromArray( data.scale ); + update( /*frame*/ ) { - } + const { array, value } = this; - if ( data.up !== undefined ) object.up.fromArray( data.up ); + const elementLength = this.getElementLength(); + const elementType = this.getElementType(); - if ( data.castShadow !== undefined ) object.castShadow = data.castShadow; - if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow; + if ( elementLength === 1 ) { - if ( data.shadow ) { + for ( let i = 0; i < array.length; i ++ ) { - if ( data.shadow.intensity !== undefined ) object.shadow.intensity = data.shadow.intensity; - if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias; - if ( data.shadow.normalBias !== undefined ) object.shadow.normalBias = data.shadow.normalBias; - if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius; - if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize ); - if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera ); + const index = i * 4; - } + value[ index ] = array[ i ]; - if ( data.visible !== undefined ) object.visible = data.visible; - if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled; - if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder; - if ( data.userData !== undefined ) object.userData = data.userData; - if ( data.layers !== undefined ) object.layers.mask = data.layers; + } - if ( data.children !== undefined ) { + } else if ( elementType === 'color' ) { - const children = data.children; + for ( let i = 0; i < array.length; i ++ ) { - for ( let i = 0; i < children.length; i ++ ) { + const index = i * 4; + const vector = array[ i ]; - object.add( this.parseObject( children[ i ], geometries, materials, textures, animations ) ); + value[ index ] = vector.r; + value[ index + 1 ] = vector.g; + value[ index + 2 ] = vector.b || 0; + //value[ index + 3 ] = vector.a || 0; } - } - - if ( data.animations !== undefined ) { - - const objectAnimations = data.animations; + } else { - for ( let i = 0; i < objectAnimations.length; i ++ ) { + for ( let i = 0; i < array.length; i ++ ) { - const uuid = objectAnimations[ i ]; + const index = i * 4; + const vector = array[ i ]; - object.animations.push( animations[ uuid ] ); + value[ index ] = vector.x; + value[ index + 1 ] = vector.y; + value[ index + 2 ] = vector.z || 0; + value[ index + 3 ] = vector.w || 0; } } - if ( data.type === 'LOD' ) { - - if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate; - - const levels = data.levels; - - for ( let l = 0; l < levels.length; l ++ ) { + } - const level = levels[ l ]; - const child = object.getObjectByProperty( 'uuid', level.object ); + setup( builder ) { - if ( child !== undefined ) { + const length = this.array.length; - object.addLevel( child, level.distance, level.hysteresis ); + this._elementType = this.elementType === null ? getValueType( this.array[ 0 ] ) : this.elementType; + this._elementLength = builder.getTypeLength( this._elementType ); - } + let arrayType = Float32Array; - } + if ( this._elementType.charAt( 0 ) === 'i' ) arrayType = Int32Array; + else if ( this._elementType.charAt( 0 ) === 'u' ) arrayType = Uint32Array; - } + this.value = new arrayType( length * 4 ); + this.bufferCount = length; + this.bufferType = builder.changeComponentType( 'vec4', builder.getComponentType( this._elementType ) ); - return object; + return super.setup( builder ); } - bindSkeletons( object, skeletons ) { + element( indexNode ) { - if ( Object.keys( skeletons ).length === 0 ) return; + return nodeObject( new UniformArrayElementNode( this, nodeObject( indexNode ) ) ); - object.traverse( function ( child ) { + } - if ( child.isSkinnedMesh === true && child.skeleton !== undefined ) { +} - const skeleton = skeletons[ child.skeleton ]; +const uniformArray = ( values, nodeType ) => nodeObject( new UniformArrayNode( values, nodeType ) ); - if ( skeleton === undefined ) { +// - console.warn( 'THREE.ObjectLoader: No skeleton found with UUID:', child.skeleton ); +const uniforms = ( values, nodeType ) => { // @deprecated, r168 - } else { + console.warn( 'TSL.UniformArrayNode: uniforms() has been renamed to uniformArray().' ); + return nodeObject( new UniformArrayNode( values, nodeType ) ); - child.bind( skeleton, child.bindMatrix ); +}; - } +class ReferenceElementNode extends ArrayElementNode { - } + static get type() { - } ); + return 'ReferenceElementNode'; } - bindLightTargets( object ) { - - object.traverse( function ( child ) { + constructor( referenceNode, indexNode ) { - if ( child.isDirectionalLight || child.isSpotLight ) { + super( referenceNode, indexNode ); - const uuid = child.target; + this.referenceNode = referenceNode; - const target = object.getObjectByProperty( 'uuid', uuid ); + this.isReferenceElementNode = true; - if ( target !== undefined ) { + } - child.target = target; + getNodeType() { - } else { + return this.referenceNode.uniformType; - child.target = new Object3D(); + } - } + generate( builder ) { - } + const snippet = super.generate( builder ); + const arrayType = this.referenceNode.getNodeType(); + const elementType = this.getNodeType(); - } ); + return builder.format( snippet, arrayType, elementType ); } } -const TEXTURE_MAPPING = { - UVMapping: UVMapping, - CubeReflectionMapping: CubeReflectionMapping, - CubeRefractionMapping: CubeRefractionMapping, - EquirectangularReflectionMapping: EquirectangularReflectionMapping, - EquirectangularRefractionMapping: EquirectangularRefractionMapping, - CubeUVReflectionMapping: CubeUVReflectionMapping -}; +// TODO: Extends this from ReferenceBaseNode +class ReferenceNode extends Node { -const TEXTURE_WRAPPING = { - RepeatWrapping: RepeatWrapping, - ClampToEdgeWrapping: ClampToEdgeWrapping, - MirroredRepeatWrapping: MirroredRepeatWrapping -}; + static get type() { -const TEXTURE_FILTER = { - NearestFilter: NearestFilter, - NearestMipmapNearestFilter: NearestMipmapNearestFilter, - NearestMipmapLinearFilter: NearestMipmapLinearFilter, - LinearFilter: LinearFilter, - LinearMipmapNearestFilter: LinearMipmapNearestFilter, - LinearMipmapLinearFilter: LinearMipmapLinearFilter -}; + return 'ReferenceNode'; -class ImageBitmapLoader extends Loader { + } - constructor( manager ) { + constructor( property, uniformType, object = null, count = null ) { - super( manager ); + super(); - this.isImageBitmapLoader = true; + this.property = property; + this.uniformType = uniformType; + this.object = object; + this.count = count; - if ( typeof createImageBitmap === 'undefined' ) { + this.properties = property.split( '.' ); + this.reference = object; + this.node = null; + this.group = null; + this.name = null; - console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' ); + this.updateType = NodeUpdateType.OBJECT; - } + } - if ( typeof fetch === 'undefined' ) { + element( indexNode ) { - console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' ); + return nodeObject( new ReferenceElementNode( this, nodeObject( indexNode ) ) ); - } + } - this.options = { premultiplyAlpha: 'none' }; + setGroup( group ) { + + this.group = group; + + return this; } - setOptions( options ) { + label( name ) { - this.options = options; + this.name = name; return this; } - load( url, onLoad, onProgress, onError ) { + setNodeType( uniformType ) { - if ( url === undefined ) url = ''; + let node = null; - if ( this.path !== undefined ) url = this.path + url; + if ( this.count !== null ) { - url = this.manager.resolveURL( url ); + node = buffer( null, uniformType, this.count ); - const scope = this; + } else if ( Array.isArray( this.getValueFromReference() ) ) { - const cached = Cache.get( url ); + node = uniformArray( null, uniformType ); - if ( cached !== undefined ) { + } else if ( uniformType === 'texture' ) { - scope.manager.itemStart( url ); + node = texture( null ); - // If cached is a promise, wait for it to resolve - if ( cached.then ) { + } else if ( uniformType === 'cubeTexture' ) { - cached.then( imageBitmap => { + node = cubeTexture( null ); - if ( onLoad ) onLoad( imageBitmap ); + } else { - scope.manager.itemEnd( url ); + node = uniform( null, uniformType ); - } ).catch( e => { + } - if ( onError ) onError( e ); + if ( this.group !== null ) { - } ); - return; + node.setGroup( this.group ); - } + } - // If cached is not a promise (i.e., it's already an imageBitmap) - setTimeout( function () { + if ( this.name !== null ) node.label( this.name ); - if ( onLoad ) onLoad( cached ); + this.node = node.getSelf(); - scope.manager.itemEnd( url ); + } - }, 0 ); + getNodeType( builder ) { - return cached; + if ( this.node === null ) { + + this.updateReference( builder ); + this.updateValue(); } - const fetchOptions = {}; - fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include'; - fetchOptions.headers = this.requestHeader; + return this.node.getNodeType( builder ); - const promise = fetch( url, fetchOptions ).then( function ( res ) { + } - return res.blob(); + getValueFromReference( object = this.reference ) { - } ).then( function ( blob ) { + const { properties } = this; - return createImageBitmap( blob, Object.assign( scope.options, { colorSpaceConversion: 'none' } ) ); + let value = object[ properties[ 0 ] ]; - } ).then( function ( imageBitmap ) { + for ( let i = 1; i < properties.length; i ++ ) { - Cache.add( url, imageBitmap ); + value = value[ properties[ i ] ]; - if ( onLoad ) onLoad( imageBitmap ); + } - scope.manager.itemEnd( url ); + return value; - return imageBitmap; + } - } ).catch( function ( e ) { + updateReference( state ) { - if ( onError ) onError( e ); + this.reference = this.object !== null ? this.object : state.object; - Cache.remove( url ); + return this.reference; - scope.manager.itemError( url ); - scope.manager.itemEnd( url ); + } - } ); + setup() { - Cache.add( url, promise ); - scope.manager.itemStart( url ); + this.updateValue(); + + return this.node; } -} + update( /*frame*/ ) { -let _context; + this.updateValue(); -class AudioContext { + } - static getContext() { + updateValue() { - if ( _context === undefined ) { + if ( this.node === null ) this.setNodeType( this.uniformType ); - _context = new ( window.AudioContext || window.webkitAudioContext )(); + const value = this.getValueFromReference(); - } + if ( Array.isArray( value ) ) { - return _context; + this.node.array = value; - } + } else { - static setContext( value ) { + this.node.value = value; - _context = value; + } } } -class AudioLoader extends Loader { +const reference = ( name, type, object ) => nodeObject( new ReferenceNode( name, type, object ) ); +const referenceBuffer = ( name, type, count, object ) => nodeObject( new ReferenceNode( name, type, object, count ) ); - constructor( manager ) { +class MaterialReferenceNode extends ReferenceNode { - super( manager ); + static get type() { - } + return 'MaterialReferenceNode'; - load( url, onLoad, onProgress, onError ) { + } - const scope = this; + constructor( property, inputType, material = null ) { - const loader = new FileLoader( this.manager ); - loader.setResponseType( 'arraybuffer' ); - loader.setPath( this.path ); - loader.setRequestHeader( this.requestHeader ); - loader.setWithCredentials( this.withCredentials ); - loader.load( url, function ( buffer ) { + super( property, inputType, material ); - try { + this.material = material; - // Create a copy of the buffer. The `decodeAudioData` method - // detaches the buffer when complete, preventing reuse. - const bufferCopy = buffer.slice( 0 ); + //this.updateType = NodeUpdateType.RENDER; - const context = AudioContext.getContext(); - context.decodeAudioData( bufferCopy, function ( audioBuffer ) { + this.isMaterialReferenceNode = true; - onLoad( audioBuffer ); + } - } ).catch( handleError ); + /*setNodeType( node ) { - } catch ( e ) { + super.setNodeType( node ); - handleError( e ); + this.node.groupNode = renderGroup; - } + }*/ - }, onProgress, onError ); + updateReference( state ) { - function handleError( e ) { + this.reference = this.material !== null ? this.material : state.material; - if ( onError ) { + return this.reference; - onError( e ); + } - } else { +} - console.error( e ); +const materialReference = ( name, type, material ) => nodeObject( new MaterialReferenceNode( name, type, material ) ); - } +const tangentGeometry = /*@__PURE__*/ Fn( ( builder ) => { - scope.manager.itemError( url ); + if ( builder.geometry.hasAttribute( 'tangent' ) === false ) { - } + builder.geometry.computeTangents(); } -} + return attribute( 'tangent', 'vec4' ); -const _eyeRight = /*@__PURE__*/ new Matrix4(); -const _eyeLeft = /*@__PURE__*/ new Matrix4(); -const _projectionMatrix = /*@__PURE__*/ new Matrix4(); +} )(); -class StereoCamera { +const tangentLocal = /*@__PURE__*/ tangentGeometry.xyz.toVar( 'tangentLocal' ); +const tangentView = /*@__PURE__*/ modelViewMatrix.mul( vec4( tangentLocal, 0 ) ).xyz.varying( 'v_tangentView' ).normalize().toVar( 'tangentView' ); +const tangentWorld = /*@__PURE__*/ tangentView.transformDirection( cameraViewMatrix ).varying( 'v_tangentWorld' ).normalize().toVar( 'tangentWorld' ); +const transformedTangentView = /*@__PURE__*/ tangentView.toVar( 'transformedTangentView' ); +const transformedTangentWorld = /*@__PURE__*/ transformedTangentView.transformDirection( cameraViewMatrix ).normalize().toVar( 'transformedTangentWorld' ); - constructor() { +const getBitangent = ( crossNormalTangent ) => crossNormalTangent.mul( tangentGeometry.w ).xyz; - this.type = 'StereoCamera'; +const bitangentGeometry = /*@__PURE__*/ varying( getBitangent( normalGeometry.cross( tangentGeometry ) ), 'v_bitangentGeometry' ).normalize().toVar( 'bitangentGeometry' ); +const bitangentLocal = /*@__PURE__*/ varying( getBitangent( normalLocal.cross( tangentLocal ) ), 'v_bitangentLocal' ).normalize().toVar( 'bitangentLocal' ); +const bitangentView = /*@__PURE__*/ varying( getBitangent( normalView.cross( tangentView ) ), 'v_bitangentView' ).normalize().toVar( 'bitangentView' ); +const bitangentWorld = /*@__PURE__*/ varying( getBitangent( normalWorld.cross( tangentWorld ) ), 'v_bitangentWorld' ).normalize().toVar( 'bitangentWorld' ); +const transformedBitangentView = /*@__PURE__*/ getBitangent( transformedNormalView.cross( transformedTangentView ) ).normalize().toVar( 'transformedBitangentView' ); +const transformedBitangentWorld = /*@__PURE__*/ transformedBitangentView.transformDirection( cameraViewMatrix ).normalize().toVar( 'transformedBitangentWorld' ); - this.aspect = 1; +const TBNViewMatrix = /*@__PURE__*/ mat3( tangentView, bitangentView, normalView ); - this.eyeSep = 0.064; +const parallaxDirection = /*@__PURE__*/ positionViewDirection.mul( TBNViewMatrix )/*.normalize()*/; +const parallaxUV = ( uv, scale ) => uv.sub( parallaxDirection.mul( scale ) ); - this.cameraL = new PerspectiveCamera(); - this.cameraL.layers.enable( 1 ); - this.cameraL.matrixAutoUpdate = false; +const transformedBentNormalView = /*@__PURE__*/ ( () => { - this.cameraR = new PerspectiveCamera(); - this.cameraR.layers.enable( 2 ); - this.cameraR.matrixAutoUpdate = false; + // https://google.github.io/filament/Filament.md.html#lighting/imagebasedlights/anisotropy - this._cache = { - focus: null, - fov: null, - aspect: null, - near: null, - far: null, - zoom: null, - eyeSep: null - }; + let bentNormal = anisotropyB.cross( positionViewDirection ); + bentNormal = bentNormal.cross( anisotropyB ).normalize(); + bentNormal = mix( bentNormal, transformedNormalView, anisotropy.mul( roughness.oneMinus() ).oneMinus().pow2().pow2() ).normalize(); - } + return bentNormal; - update( camera ) { - const cache = this._cache; +} )(); - const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov || - cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near || - cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep; +// Normal Mapping Without Precomputed Tangents +// http://www.thetenthplanet.de/archives/1180 - if ( needsUpdate ) { +const perturbNormal2Arb = /*@__PURE__*/ Fn( ( inputs ) => { - cache.focus = camera.focus; - cache.fov = camera.fov; - cache.aspect = camera.aspect * this.aspect; - cache.near = camera.near; - cache.far = camera.far; - cache.zoom = camera.zoom; - cache.eyeSep = this.eyeSep; + const { eye_pos, surf_norm, mapN, uv } = inputs; - // Off-axis stereoscopic effect based on - // http://paulbourke.net/stereographics/stereorender/ + const q0 = eye_pos.dFdx(); + const q1 = eye_pos.dFdy(); + const st0 = uv.dFdx(); + const st1 = uv.dFdy(); - _projectionMatrix.copy( camera.projectionMatrix ); - const eyeSepHalf = cache.eyeSep / 2; - const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus; - const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom; - let xmin, xmax; + const N = surf_norm; // normalized - // translate xOffset + const q1perp = q1.cross( N ); + const q0perp = N.cross( q0 ); - _eyeLeft.elements[ 12 ] = - eyeSepHalf; - _eyeRight.elements[ 12 ] = eyeSepHalf; + const T = q1perp.mul( st0.x ).add( q0perp.mul( st1.x ) ); + const B = q1perp.mul( st0.y ).add( q0perp.mul( st1.y ) ); - // for left eye + const det = T.dot( T ).max( B.dot( B ) ); + const scale = faceDirection.mul( det.inverseSqrt() ); - xmin = - ymax * cache.aspect + eyeSepOnProjection; - xmax = ymax * cache.aspect + eyeSepOnProjection; + return add( T.mul( mapN.x, scale ), B.mul( mapN.y, scale ), N.mul( mapN.z ) ).normalize(); - _projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin ); - _projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); +} ); - this.cameraL.projectionMatrix.copy( _projectionMatrix ); +class NormalMapNode extends TempNode { - // for right eye + static get type() { - xmin = - ymax * cache.aspect - eyeSepOnProjection; - xmax = ymax * cache.aspect - eyeSepOnProjection; + return 'NormalMapNode'; - _projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin ); - _projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); + } - this.cameraR.projectionMatrix.copy( _projectionMatrix ); + constructor( node, scaleNode = null ) { - } + super( 'vec3' ); - this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft ); - this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight ); + this.node = node; + this.scaleNode = scaleNode; + + this.normalMapType = TangentSpaceNormalMap; } -} + setup( builder ) { -class ArrayCamera extends PerspectiveCamera { + const { normalMapType, scaleNode } = this; - constructor( array = [] ) { + let normalMap = this.node.mul( 2.0 ).sub( 1.0 ); - super(); + if ( scaleNode !== null ) { - this.isArrayCamera = true; + normalMap = vec3( normalMap.xy.mul( scaleNode ), normalMap.z ); - this.cameras = array; + } - } + let outputNode = null; -} + if ( normalMapType === ObjectSpaceNormalMap ) { -class Clock { + outputNode = transformNormalToView( normalMap ); - constructor( autoStart = true ) { + } else if ( normalMapType === TangentSpaceNormalMap ) { - this.autoStart = autoStart; + const tangent = builder.hasGeometryAttribute( 'tangent' ); - this.startTime = 0; - this.oldTime = 0; - this.elapsedTime = 0; + if ( tangent === true ) { - this.running = false; + outputNode = TBNViewMatrix.mul( normalMap ).normalize(); - } + } else { - start() { + outputNode = perturbNormal2Arb( { + eye_pos: positionView, + surf_norm: normalView, + mapN: normalMap, + uv: uv() + } ); - this.startTime = now(); + } - this.oldTime = this.startTime; - this.elapsedTime = 0; - this.running = true; + } + + return outputNode; } - stop() { +} - this.getElapsedTime(); - this.running = false; - this.autoStart = false; +const normalMap = /*@__PURE__*/ nodeProxy( NormalMapNode ); - } +// Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen +// https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf - getElapsedTime() { +const dHdxy_fwd = Fn( ( { textureNode, bumpScale } ) => { - this.getDelta(); - return this.elapsedTime; + // It's used to preserve the same TextureNode instance + const sampleTexture = ( callback ) => textureNode.cache().context( { getUV: ( texNode ) => callback( texNode.uvNode || uv() ), forceUVContext: true } ); - } + const Hll = float( sampleTexture( ( uvNode ) => uvNode ) ); - getDelta() { + return vec2( + float( sampleTexture( ( uvNode ) => uvNode.add( uvNode.dFdx() ) ) ).sub( Hll ), + float( sampleTexture( ( uvNode ) => uvNode.add( uvNode.dFdy() ) ) ).sub( Hll ) + ).mul( bumpScale ); - let diff = 0; +} ); - if ( this.autoStart && ! this.running ) { +// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2) - this.start(); - return 0; +const perturbNormalArb = Fn( ( inputs ) => { - } + const { surf_pos, surf_norm, dHdxy } = inputs; - if ( this.running ) { + // normalize is done to ensure that the bump map looks the same regardless of the texture's scale + const vSigmaX = surf_pos.dFdx().normalize(); + const vSigmaY = surf_pos.dFdy().normalize(); + const vN = surf_norm; // normalized - const newTime = now(); + const R1 = vSigmaY.cross( vN ); + const R2 = vN.cross( vSigmaX ); - diff = ( newTime - this.oldTime ) / 1000; - this.oldTime = newTime; + const fDet = vSigmaX.dot( R1 ).mul( faceDirection ); - this.elapsedTime += diff; + const vGrad = fDet.sign().mul( dHdxy.x.mul( R1 ).add( dHdxy.y.mul( R2 ) ) ); - } + return fDet.abs().mul( surf_norm ).sub( vGrad ).normalize(); - return diff; +} ); - } +class BumpMapNode extends TempNode { -} + static get type() { -function now() { + return 'BumpMapNode'; - return ( typeof performance === 'undefined' ? Date : performance ).now(); // see #10732 + } -} + constructor( textureNode, scaleNode = null ) { -const _position$1 = /*@__PURE__*/ new Vector3(); -const _quaternion$1 = /*@__PURE__*/ new Quaternion(); -const _scale$1 = /*@__PURE__*/ new Vector3(); -const _orientation$1 = /*@__PURE__*/ new Vector3(); + super( 'vec3' ); -class AudioListener extends Object3D { + this.textureNode = textureNode; + this.scaleNode = scaleNode; - constructor() { + } - super(); + setup() { - this.type = 'AudioListener'; + const bumpScale = this.scaleNode !== null ? this.scaleNode : 1; + const dHdxy = dHdxy_fwd( { textureNode: this.textureNode, bumpScale } ); - this.context = AudioContext.getContext(); + return perturbNormalArb( { + surf_pos: positionView, + surf_norm: normalView, + dHdxy + } ); - this.gain = this.context.createGain(); - this.gain.connect( this.context.destination ); + } - this.filter = null; +} - this.timeDelta = 0; +const bumpMap = /*@__PURE__*/ nodeProxy( BumpMapNode ); - // private +const _propertyCache = new Map(); - this._clock = new Clock(); +class MaterialNode extends Node { + + static get type() { + + return 'MaterialNode'; } - getInput() { + constructor( scope ) { - return this.gain; + super(); - } + this.scope = scope; - removeFilter() { + } - if ( this.filter !== null ) { + getCache( property, type ) { - this.gain.disconnect( this.filter ); - this.filter.disconnect( this.context.destination ); - this.gain.connect( this.context.destination ); - this.filter = null; + let node = _propertyCache.get( property ); - } + if ( node === undefined ) { - return this; + node = materialReference( property, type ); - } + _propertyCache.set( property, node ); - getFilter() { + } - return this.filter; + return node; } - setFilter( value ) { + getFloat( property ) { - if ( this.filter !== null ) { + return this.getCache( property, 'float' ); - this.gain.disconnect( this.filter ); - this.filter.disconnect( this.context.destination ); + } - } else { + getColor( property ) { - this.gain.disconnect( this.context.destination ); + return this.getCache( property, 'color' ); - } + } - this.filter = value; - this.gain.connect( this.filter ); - this.filter.connect( this.context.destination ); + getTexture( property ) { - return this; + return this.getCache( property === 'map' ? 'map' : property + 'Map', 'texture' ); } - getMasterVolume() { + setup( builder ) { - return this.gain.gain.value; + const material = builder.context.material; + const scope = this.scope; - } + let node = null; - setMasterVolume( value ) { + if ( scope === MaterialNode.COLOR ) { - this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 ); + const colorNode = material.color !== undefined ? this.getColor( scope ) : vec3(); - return this; + if ( material.map && material.map.isTexture === true ) { - } + node = colorNode.mul( this.getTexture( 'map' ) ); - updateMatrixWorld( force ) { + } else { - super.updateMatrixWorld( force ); + node = colorNode; - const listener = this.context.listener; - const up = this.up; + } - this.timeDelta = this._clock.getDelta(); + } else if ( scope === MaterialNode.OPACITY ) { - this.matrixWorld.decompose( _position$1, _quaternion$1, _scale$1 ); + const opacityNode = this.getFloat( scope ); - _orientation$1.set( 0, 0, - 1 ).applyQuaternion( _quaternion$1 ); + if ( material.alphaMap && material.alphaMap.isTexture === true ) { - if ( listener.positionX ) { + node = opacityNode.mul( this.getTexture( 'alpha' ) ); - // code path for Chrome (see #14393) + } else { - const endTime = this.context.currentTime + this.timeDelta; + node = opacityNode; - listener.positionX.linearRampToValueAtTime( _position$1.x, endTime ); - listener.positionY.linearRampToValueAtTime( _position$1.y, endTime ); - listener.positionZ.linearRampToValueAtTime( _position$1.z, endTime ); - listener.forwardX.linearRampToValueAtTime( _orientation$1.x, endTime ); - listener.forwardY.linearRampToValueAtTime( _orientation$1.y, endTime ); - listener.forwardZ.linearRampToValueAtTime( _orientation$1.z, endTime ); - listener.upX.linearRampToValueAtTime( up.x, endTime ); - listener.upY.linearRampToValueAtTime( up.y, endTime ); - listener.upZ.linearRampToValueAtTime( up.z, endTime ); + } - } else { + } else if ( scope === MaterialNode.SPECULAR_STRENGTH ) { - listener.setPosition( _position$1.x, _position$1.y, _position$1.z ); - listener.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z, up.x, up.y, up.z ); + if ( material.specularMap && material.specularMap.isTexture === true ) { - } + node = this.getTexture( 'specular' ).r; - } + } else { -} + node = float( 1 ); -class Audio extends Object3D { + } - constructor( listener ) { + } else if ( scope === MaterialNode.SPECULAR_INTENSITY ) { - super(); + const specularIntensity = this.getFloat( scope ); - this.type = 'Audio'; + if ( material.specularMap ) { - this.listener = listener; - this.context = listener.context; + node = specularIntensity.mul( this.getTexture( scope ).a ); - this.gain = this.context.createGain(); - this.gain.connect( listener.getInput() ); + } else { - this.autoplay = false; + node = specularIntensity; - this.buffer = null; - this.detune = 0; - this.loop = false; - this.loopStart = 0; - this.loopEnd = 0; - this.offset = 0; - this.duration = undefined; - this.playbackRate = 1; - this.isPlaying = false; - this.hasPlaybackControl = true; - this.source = null; - this.sourceType = 'empty'; + } - this._startedAt = 0; - this._progress = 0; - this._connected = false; + } else if ( scope === MaterialNode.SPECULAR_COLOR ) { - this.filters = []; + const specularColorNode = this.getColor( scope ); - } + if ( material.specularColorMap && material.specularColorMap.isTexture === true ) { - getOutput() { + node = specularColorNode.mul( this.getTexture( scope ).rgb ); - return this.gain; + } else { - } + node = specularColorNode; - setNodeSource( audioNode ) { + } - this.hasPlaybackControl = false; - this.sourceType = 'audioNode'; - this.source = audioNode; - this.connect(); + } else if ( scope === MaterialNode.ROUGHNESS ) { // TODO: cleanup similar branches - return this; + const roughnessNode = this.getFloat( scope ); - } + if ( material.roughnessMap && material.roughnessMap.isTexture === true ) { - setMediaElementSource( mediaElement ) { + node = roughnessNode.mul( this.getTexture( scope ).g ); - this.hasPlaybackControl = false; - this.sourceType = 'mediaNode'; - this.source = this.context.createMediaElementSource( mediaElement ); - this.connect(); + } else { - return this; + node = roughnessNode; - } + } - setMediaStreamSource( mediaStream ) { + } else if ( scope === MaterialNode.METALNESS ) { - this.hasPlaybackControl = false; - this.sourceType = 'mediaStreamNode'; - this.source = this.context.createMediaStreamSource( mediaStream ); - this.connect(); + const metalnessNode = this.getFloat( scope ); - return this; + if ( material.metalnessMap && material.metalnessMap.isTexture === true ) { - } + node = metalnessNode.mul( this.getTexture( scope ).b ); - setBuffer( audioBuffer ) { + } else { - this.buffer = audioBuffer; - this.sourceType = 'buffer'; + node = metalnessNode; - if ( this.autoplay ) this.play(); + } - return this; + } else if ( scope === MaterialNode.EMISSIVE ) { - } + const emissiveIntensityNode = this.getFloat( 'emissiveIntensity' ); + const emissiveNode = this.getColor( scope ).mul( emissiveIntensityNode ); - play( delay = 0 ) { + if ( material.emissiveMap && material.emissiveMap.isTexture === true ) { - if ( this.isPlaying === true ) { + node = emissiveNode.mul( this.getTexture( scope ) ); - console.warn( 'THREE.Audio: Audio is already playing.' ); - return; + } else { - } + node = emissiveNode; - if ( this.hasPlaybackControl === false ) { + } - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; + } else if ( scope === MaterialNode.NORMAL ) { - } + if ( material.normalMap ) { - this._startedAt = this.context.currentTime + delay; + node = normalMap( this.getTexture( 'normal' ), this.getCache( 'normalScale', 'vec2' ) ); + node.normalMapType = material.normalMapType; - const source = this.context.createBufferSource(); - source.buffer = this.buffer; - source.loop = this.loop; - source.loopStart = this.loopStart; - source.loopEnd = this.loopEnd; - source.onended = this.onEnded.bind( this ); - source.start( this._startedAt, this._progress + this.offset, this.duration ); + } else if ( material.bumpMap ) { - this.isPlaying = true; + node = bumpMap( this.getTexture( 'bump' ).r, this.getFloat( 'bumpScale' ) ); - this.source = source; + } else { - this.setDetune( this.detune ); - this.setPlaybackRate( this.playbackRate ); + node = normalView; - return this.connect(); + } - } + } else if ( scope === MaterialNode.CLEARCOAT ) { - pause() { + const clearcoatNode = this.getFloat( scope ); - if ( this.hasPlaybackControl === false ) { + if ( material.clearcoatMap && material.clearcoatMap.isTexture === true ) { - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; + node = clearcoatNode.mul( this.getTexture( scope ).r ); - } + } else { - if ( this.isPlaying === true ) { + node = clearcoatNode; - // update current progress + } - this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate; + } else if ( scope === MaterialNode.CLEARCOAT_ROUGHNESS ) { - if ( this.loop === true ) { + const clearcoatRoughnessNode = this.getFloat( scope ); - // ensure _progress does not exceed duration with looped audios + if ( material.clearcoatRoughnessMap && material.clearcoatRoughnessMap.isTexture === true ) { - this._progress = this._progress % ( this.duration || this.buffer.duration ); + node = clearcoatRoughnessNode.mul( this.getTexture( scope ).r ); - } + } else { - this.source.stop(); - this.source.onended = null; + node = clearcoatRoughnessNode; - this.isPlaying = false; + } - } + } else if ( scope === MaterialNode.CLEARCOAT_NORMAL ) { - return this; + if ( material.clearcoatNormalMap ) { - } + node = normalMap( this.getTexture( scope ), this.getCache( scope + 'Scale', 'vec2' ) ); - stop() { + } else { - if ( this.hasPlaybackControl === false ) { + node = normalView; - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; + } - } + } else if ( scope === MaterialNode.SHEEN ) { - this._progress = 0; + const sheenNode = this.getColor( 'sheenColor' ).mul( this.getFloat( 'sheen' ) ); // Move this mul() to CPU - if ( this.source !== null ) { + if ( material.sheenColorMap && material.sheenColorMap.isTexture === true ) { - this.source.stop(); - this.source.onended = null; + node = sheenNode.mul( this.getTexture( 'sheenColor' ).rgb ); - } + } else { - this.isPlaying = false; + node = sheenNode; - return this; + } - } + } else if ( scope === MaterialNode.SHEEN_ROUGHNESS ) { - connect() { + const sheenRoughnessNode = this.getFloat( scope ); - if ( this.filters.length > 0 ) { + if ( material.sheenRoughnessMap && material.sheenRoughnessMap.isTexture === true ) { - this.source.connect( this.filters[ 0 ] ); + node = sheenRoughnessNode.mul( this.getTexture( scope ).a ); - for ( let i = 1, l = this.filters.length; i < l; i ++ ) { + } else { - this.filters[ i - 1 ].connect( this.filters[ i ] ); + node = sheenRoughnessNode; } - this.filters[ this.filters.length - 1 ].connect( this.getOutput() ); + node = node.clamp( 0.07, 1.0 ); - } else { + } else if ( scope === MaterialNode.ANISOTROPY ) { - this.source.connect( this.getOutput() ); + if ( material.anisotropyMap && material.anisotropyMap.isTexture === true ) { - } + const anisotropyPolar = this.getTexture( scope ); + const anisotropyMat = mat2( materialAnisotropyVector.x, materialAnisotropyVector.y, materialAnisotropyVector.y.negate(), materialAnisotropyVector.x ); - this._connected = true; + node = anisotropyMat.mul( anisotropyPolar.rg.mul( 2.0 ).sub( vec2( 1.0 ) ).normalize().mul( anisotropyPolar.b ) ); - return this; + } else { - } + node = materialAnisotropyVector; - disconnect() { + } - if ( this._connected === false ) { + } else if ( scope === MaterialNode.IRIDESCENCE_THICKNESS ) { - return; + const iridescenceThicknessMaximum = reference( '1', 'float', material.iridescenceThicknessRange ); - } + if ( material.iridescenceThicknessMap ) { - if ( this.filters.length > 0 ) { + const iridescenceThicknessMinimum = reference( '0', 'float', material.iridescenceThicknessRange ); - this.source.disconnect( this.filters[ 0 ] ); + node = iridescenceThicknessMaximum.sub( iridescenceThicknessMinimum ).mul( this.getTexture( scope ).g ).add( iridescenceThicknessMinimum ); - for ( let i = 1, l = this.filters.length; i < l; i ++ ) { + } else { - this.filters[ i - 1 ].disconnect( this.filters[ i ] ); + node = iridescenceThicknessMaximum; } - this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() ); + } else if ( scope === MaterialNode.TRANSMISSION ) { - } else { + const transmissionNode = this.getFloat( scope ); - this.source.disconnect( this.getOutput() ); + if ( material.transmissionMap ) { - } + node = transmissionNode.mul( this.getTexture( scope ).r ); - this._connected = false; + } else { - return this; + node = transmissionNode; - } + } - getFilters() { + } else if ( scope === MaterialNode.THICKNESS ) { - return this.filters; + const thicknessNode = this.getFloat( scope ); - } + if ( material.thicknessMap ) { - setFilters( value ) { + node = thicknessNode.mul( this.getTexture( scope ).g ); - if ( ! value ) value = []; + } else { - if ( this._connected === true ) { + node = thicknessNode; - this.disconnect(); - this.filters = value.slice(); - this.connect(); + } - } else { + } else if ( scope === MaterialNode.IOR ) { - this.filters = value.slice(); + node = this.getFloat( scope ); - } + } else if ( scope === MaterialNode.LIGHT_MAP ) { - return this; + node = this.getTexture( scope ).rgb.mul( this.getFloat( 'lightMapIntensity' ) ); - } + } else if ( scope === MaterialNode.AO_MAP ) { - setDetune( value ) { + node = this.getTexture( scope ).r.sub( 1.0 ).mul( this.getFloat( 'aoMapIntensity' ) ).add( 1.0 ); - this.detune = value; + } else { - if ( this.isPlaying === true && this.source.detune !== undefined ) { + const outputType = this.getNodeType( builder ); - this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 ); + node = this.getCache( scope, outputType ); } - return this; + return node; } - getDetune() { - - return this.detune; +} - } - - getFilter() { +MaterialNode.ALPHA_TEST = 'alphaTest'; +MaterialNode.COLOR = 'color'; +MaterialNode.OPACITY = 'opacity'; +MaterialNode.SHININESS = 'shininess'; +MaterialNode.SPECULAR = 'specular'; +MaterialNode.SPECULAR_STRENGTH = 'specularStrength'; +MaterialNode.SPECULAR_INTENSITY = 'specularIntensity'; +MaterialNode.SPECULAR_COLOR = 'specularColor'; +MaterialNode.REFLECTIVITY = 'reflectivity'; +MaterialNode.ROUGHNESS = 'roughness'; +MaterialNode.METALNESS = 'metalness'; +MaterialNode.NORMAL = 'normal'; +MaterialNode.CLEARCOAT = 'clearcoat'; +MaterialNode.CLEARCOAT_ROUGHNESS = 'clearcoatRoughness'; +MaterialNode.CLEARCOAT_NORMAL = 'clearcoatNormal'; +MaterialNode.EMISSIVE = 'emissive'; +MaterialNode.ROTATION = 'rotation'; +MaterialNode.SHEEN = 'sheen'; +MaterialNode.SHEEN_ROUGHNESS = 'sheenRoughness'; +MaterialNode.ANISOTROPY = 'anisotropy'; +MaterialNode.IRIDESCENCE = 'iridescence'; +MaterialNode.IRIDESCENCE_IOR = 'iridescenceIOR'; +MaterialNode.IRIDESCENCE_THICKNESS = 'iridescenceThickness'; +MaterialNode.IOR = 'ior'; +MaterialNode.TRANSMISSION = 'transmission'; +MaterialNode.THICKNESS = 'thickness'; +MaterialNode.ATTENUATION_DISTANCE = 'attenuationDistance'; +MaterialNode.ATTENUATION_COLOR = 'attenuationColor'; +MaterialNode.LINE_SCALE = 'scale'; +MaterialNode.LINE_DASH_SIZE = 'dashSize'; +MaterialNode.LINE_GAP_SIZE = 'gapSize'; +MaterialNode.LINE_WIDTH = 'linewidth'; +MaterialNode.LINE_DASH_OFFSET = 'dashOffset'; +MaterialNode.POINT_WIDTH = 'pointWidth'; +MaterialNode.DISPERSION = 'dispersion'; +MaterialNode.LIGHT_MAP = 'light'; +MaterialNode.AO_MAP = 'ao'; - return this.getFilters()[ 0 ]; +const materialAlphaTest = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ALPHA_TEST ); +const materialColor = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.COLOR ); +const materialShininess = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SHININESS ); +const materialEmissive = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.EMISSIVE ); +const materialOpacity = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.OPACITY ); +const materialSpecular = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR ); - } +const materialSpecularIntensity = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR_INTENSITY ); +const materialSpecularColor = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR_COLOR ); - setFilter( filter ) { +const materialSpecularStrength = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR_STRENGTH ); +const materialReflectivity = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.REFLECTIVITY ); +const materialRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ROUGHNESS ); +const materialMetalness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.METALNESS ); +const materialNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.NORMAL ).context( { getUV: null } ); +const materialClearcoat = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT ); +const materialClearcoatRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_ROUGHNESS ); +const materialClearcoatNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_NORMAL ).context( { getUV: null } ); +const materialRotation = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ROTATION ); +const materialSheen = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SHEEN ); +const materialSheenRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SHEEN_ROUGHNESS ); +const materialAnisotropy = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ANISOTROPY ); +const materialIridescence = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE ); +const materialIridescenceIOR = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE_IOR ); +const materialIridescenceThickness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE_THICKNESS ); +const materialTransmission = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.TRANSMISSION ); +const materialThickness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.THICKNESS ); +const materialIOR = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.IOR ); +const materialAttenuationDistance = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ATTENUATION_DISTANCE ); +const materialAttenuationColor = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ATTENUATION_COLOR ); +const materialLineScale = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_SCALE ); +const materialLineDashSize = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_DASH_SIZE ); +const materialLineGapSize = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_GAP_SIZE ); +const materialLineWidth = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_WIDTH ); +const materialLineDashOffset = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_DASH_OFFSET ); +const materialPointWidth = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.POINT_WIDTH ); +const materialDispersion = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.DISPERSION ); +const materialLightMap = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LIGHT_MAP ); +const materialAOMap = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.AO_MAP ); +const materialAnisotropyVector = /*@__PURE__*/ uniform( new Vector2() ).onReference( function ( frame ) { - return this.setFilters( filter ? [ filter ] : [] ); + return frame.material; - } +} ).onRenderUpdate( function ( { material } ) { - setPlaybackRate( value ) { + this.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) ); - if ( this.hasPlaybackControl === false ) { +} ); - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; +class ModelViewProjectionNode extends TempNode { - } + static get type() { - this.playbackRate = value; + return 'ModelViewProjectionNode'; - if ( this.isPlaying === true ) { + } - this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 ); + constructor( positionNode = null ) { - } + super( 'vec4' ); - return this; + this.positionNode = positionNode; } - getPlaybackRate() { + setup( builder ) { - return this.playbackRate; + if ( builder.shaderStage === 'fragment' ) { - } + return varying( builder.context.mvp ); - onEnded() { + } - this.isPlaying = false; + const position = this.positionNode || positionLocal; + const viewMatrix = builder.renderer.nodes.modelViewMatrix || modelViewMatrix; + + return cameraProjectionMatrix.mul( viewMatrix ).mul( position ); } - getLoop() { +} - if ( this.hasPlaybackControl === false ) { +const modelViewProjection = /*@__PURE__*/ nodeProxy( ModelViewProjectionNode ); - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return false; +class IndexNode extends Node { - } + static get type() { - return this.loop; + return 'IndexNode'; } - setLoop( value ) { + constructor( scope ) { - if ( this.hasPlaybackControl === false ) { + super( 'uint' ); - console.warn( 'THREE.Audio: this Audio has no playback control.' ); - return; + this.scope = scope; - } + this.isInstanceIndexNode = true; - this.loop = value; + } - if ( this.isPlaying === true ) { + generate( builder ) { - this.source.loop = this.loop; + const nodeType = this.getNodeType( builder ); + const scope = this.scope; - } + let propertyName; - return this; + if ( scope === IndexNode.VERTEX ) { - } + // The index of a vertex within a mesh. + propertyName = builder.getVertexIndex(); - setLoopStart( value ) { + } else if ( scope === IndexNode.INSTANCE ) { - this.loopStart = value; + // The index of either a mesh instance or an invocation of a compute shader. + propertyName = builder.getInstanceIndex(); - return this; + } else if ( scope === IndexNode.DRAW ) { - } + // The index of a draw call. + propertyName = builder.getDrawIndex(); - setLoopEnd( value ) { + } else if ( scope === IndexNode.INVOCATION_LOCAL ) { - this.loopEnd = value; + // The index of a compute invocation within the scope of a workgroup load. + propertyName = builder.getInvocationLocalIndex(); - return this; + } else if ( scope === IndexNode.INVOCATION_SUBGROUP ) { - } + // The index of a compute invocation within the scope of a subgroup. + propertyName = builder.getInvocationSubgroupIndex(); - getVolume() { + } else if ( scope === IndexNode.SUBGROUP ) { - return this.gain.gain.value; + // The index of the subgroup the current compute invocation belongs to. + propertyName = builder.getSubgroupIndex(); - } + } else { - setVolume( value ) { + throw new Error( 'THREE.IndexNode: Unknown scope: ' + scope ); - this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 ); + } - return this; + let output; - } + if ( builder.shaderStage === 'vertex' || builder.shaderStage === 'compute' ) { -} + output = propertyName; -const _position = /*@__PURE__*/ new Vector3(); -const _quaternion = /*@__PURE__*/ new Quaternion(); -const _scale = /*@__PURE__*/ new Vector3(); -const _orientation = /*@__PURE__*/ new Vector3(); + } else { -class PositionalAudio extends Audio { + const nodeVarying = varying( this ); - constructor( listener ) { + output = nodeVarying.build( builder, nodeType ); - super( listener ); + } - this.panner = this.context.createPanner(); - this.panner.panningModel = 'HRTF'; - this.panner.connect( this.gain ); + return output; } - connect() { - - super.connect(); +} - this.panner.connect( this.gain ); +IndexNode.VERTEX = 'vertex'; +IndexNode.INSTANCE = 'instance'; +IndexNode.SUBGROUP = 'subgroup'; +IndexNode.INVOCATION_LOCAL = 'invocationLocal'; +IndexNode.INVOCATION_SUBGROUP = 'invocationSubgroup'; +IndexNode.DRAW = 'draw'; - } +const vertexIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.VERTEX ); +const instanceIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.INSTANCE ); +const subgroupIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.SUBGROUP ); +const invocationSubgroupIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.INVOCATION_SUBGROUP ); +const invocationLocalIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.INVOCATION_LOCAL ); +const drawIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.DRAW ); - disconnect() { +class InstanceNode extends Node { - super.disconnect(); + static get type() { - this.panner.disconnect( this.gain ); + return 'InstanceNode'; } - getOutput() { - - return this.panner; - - } + constructor( instanceMesh ) { - getRefDistance() { + super( 'void' ); - return this.panner.refDistance; + this.instanceMesh = instanceMesh; - } + this.instanceMatrixNode = null; - setRefDistance( value ) { + this.instanceColorNode = null; - this.panner.refDistance = value; + this.updateType = NodeUpdateType.FRAME; - return this; + this.buffer = null; + this.bufferColor = null; } - getRolloffFactor() { - - return this.panner.rolloffFactor; + setup( builder ) { - } + let instanceMatrixNode = this.instanceMatrixNode; + let instanceColorNode = this.instanceColorNode; - setRolloffFactor( value ) { + const instanceMesh = this.instanceMesh; - this.panner.rolloffFactor = value; + if ( instanceMatrixNode === null ) { - return this; + const instanceAttribute = instanceMesh.instanceMatrix; - } + // Both WebGPU and WebGL backends have UBO max limited to 64kb. Matrix count number bigger than 1000 ( 16 * 4 * 1000 = 64kb ) will fallback to attribute. - getDistanceModel() { + if ( instanceMesh.count <= 1000 ) { - return this.panner.distanceModel; + instanceMatrixNode = buffer( instanceAttribute.array, 'mat4', Math.max( instanceMesh.count, 1 ) ).element( instanceIndex ); - } + } else { - setDistanceModel( value ) { + const buffer = new InstancedInterleavedBuffer( instanceAttribute.array, 16, 1 ); - this.panner.distanceModel = value; + this.buffer = buffer; - return this; + const bufferFn = instanceAttribute.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute; - } + const instanceBuffers = [ + // F.Signature -> bufferAttribute( array, type, stride, offset ) + bufferFn( buffer, 'vec4', 16, 0 ), + bufferFn( buffer, 'vec4', 16, 4 ), + bufferFn( buffer, 'vec4', 16, 8 ), + bufferFn( buffer, 'vec4', 16, 12 ) + ]; - getMaxDistance() { + instanceMatrixNode = mat4( ...instanceBuffers ); - return this.panner.maxDistance; + } - } + this.instanceMatrixNode = instanceMatrixNode; - setMaxDistance( value ) { + } - this.panner.maxDistance = value; + const instanceColorAttribute = instanceMesh.instanceColor; - return this; + if ( instanceColorAttribute && instanceColorNode === null ) { - } + const buffer = new InstancedBufferAttribute( instanceColorAttribute.array, 3 ); - setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) { + const bufferFn = instanceColorAttribute.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute; - this.panner.coneInnerAngle = coneInnerAngle; - this.panner.coneOuterAngle = coneOuterAngle; - this.panner.coneOuterGain = coneOuterGain; + this.bufferColor = buffer; - return this; + instanceColorNode = vec3( bufferFn( buffer, 'vec3', 3, 0 ) ); - } + this.instanceColorNode = instanceColorNode; - updateMatrixWorld( force ) { + } - super.updateMatrixWorld( force ); + // POSITION - if ( this.hasPlaybackControl === true && this.isPlaying === false ) return; + const instancePosition = instanceMatrixNode.mul( positionLocal ).xyz; + positionLocal.assign( instancePosition ); - this.matrixWorld.decompose( _position, _quaternion, _scale ); + // NORMAL - _orientation.set( 0, 0, 1 ).applyQuaternion( _quaternion ); + if ( builder.hasGeometryAttribute( 'normal' ) ) { - const panner = this.panner; + const instanceNormal = transformNormal( normalLocal, instanceMatrixNode ); - if ( panner.positionX ) { + // ASSIGNS - // code path for Chrome and Firefox (see #14393) + normalLocal.assign( instanceNormal ); - const endTime = this.context.currentTime + this.listener.timeDelta; + } - panner.positionX.linearRampToValueAtTime( _position.x, endTime ); - panner.positionY.linearRampToValueAtTime( _position.y, endTime ); - panner.positionZ.linearRampToValueAtTime( _position.z, endTime ); - panner.orientationX.linearRampToValueAtTime( _orientation.x, endTime ); - panner.orientationY.linearRampToValueAtTime( _orientation.y, endTime ); - panner.orientationZ.linearRampToValueAtTime( _orientation.z, endTime ); + // COLOR - } else { + if ( this.instanceColorNode !== null ) { - panner.setPosition( _position.x, _position.y, _position.z ); - panner.setOrientation( _orientation.x, _orientation.y, _orientation.z ); + varyingProperty( 'vec3', 'vInstanceColor' ).assign( this.instanceColorNode ); } } -} + update( /*frame*/ ) { -class AudioAnalyser { + if ( this.instanceMesh.instanceMatrix.usage !== DynamicDrawUsage && this.buffer != null && this.instanceMesh.instanceMatrix.version !== this.buffer.version ) { - constructor( audio, fftSize = 2048 ) { + this.buffer.version = this.instanceMesh.instanceMatrix.version; - this.analyser = audio.context.createAnalyser(); - this.analyser.fftSize = fftSize; + } - this.data = new Uint8Array( this.analyser.frequencyBinCount ); + if ( this.instanceMesh.instanceColor && this.instanceMesh.instanceColor.usage !== DynamicDrawUsage && this.bufferColor != null && this.instanceMesh.instanceColor.version !== this.bufferColor.version ) { - audio.getOutput().connect( this.analyser ); + this.bufferColor.version = this.instanceMesh.instanceColor.version; + + } } +} + +const instance = /*@__PURE__*/ nodeProxy( InstanceNode ); - getFrequencyData() { +class BatchNode extends Node { - this.analyser.getByteFrequencyData( this.data ); + static get type() { - return this.data; + return 'BatchNode'; } - getAverageFrequency() { - - let value = 0; - const data = this.getFrequencyData(); + constructor( batchMesh ) { - for ( let i = 0; i < data.length; i ++ ) { + super( 'void' ); - value += data[ i ]; + this.batchMesh = batchMesh; - } - return value / data.length; + this.batchingIdNode = null; } -} - -class PropertyMixer { + setup( builder ) { - constructor( binding, typeName, valueSize ) { + // POSITION - this.binding = binding; - this.valueSize = valueSize; + if ( this.batchingIdNode === null ) { - let mixFunction, - mixFunctionAdditive, - setIdentity; + if ( builder.getDrawIndex() === null ) { - // buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ] - // - // interpolators can use .buffer as their .result - // the data then goes to 'incoming' - // - // 'accu0' and 'accu1' are used frame-interleaved for - // the cumulative result and are compared to detect - // changes - // - // 'orig' stores the original state of the property - // - // 'add' is used for additive cumulative results - // - // 'work' is optional and is only present for quaternion types. It is used - // to store intermediate quaternion multiplication results + this.batchingIdNode = instanceIndex; - switch ( typeName ) { + } else { - case 'quaternion': - mixFunction = this._slerp; - mixFunctionAdditive = this._slerpAdditive; - setIdentity = this._setAdditiveIdentityQuaternion; + this.batchingIdNode = drawIndex; - this.buffer = new Float64Array( valueSize * 6 ); - this._workIndex = 5; - break; + } - case 'string': - case 'bool': - mixFunction = this._select; + } - // Use the regular mix function and for additive on these types, - // additive is not relevant for non-numeric types - mixFunctionAdditive = this._select; + const getIndirectIndex = Fn( ( [ id ] ) => { - setIdentity = this._setAdditiveIdentityOther; + const size = textureSize( textureLoad( this.batchMesh._indirectTexture ), 0 ); + const x = int( id ).modInt( int( size ) ); + const y = int( id ).div( int( size ) ); + return textureLoad( this.batchMesh._indirectTexture, ivec2( x, y ) ).x; - this.buffer = new Array( valueSize * 5 ); - break; + } ).setLayout( { + name: 'getIndirectIndex', + type: 'uint', + inputs: [ + { name: 'id', type: 'int' } + ] + } ); - default: - mixFunction = this._lerp; - mixFunctionAdditive = this._lerpAdditive; - setIdentity = this._setAdditiveIdentityNumeric; + const indirectId = getIndirectIndex( int( this.batchingIdNode ) ); - this.buffer = new Float64Array( valueSize * 5 ); + const matricesTexture = this.batchMesh._matricesTexture; - } + const size = textureSize( textureLoad( matricesTexture ), 0 ); + const j = float( indirectId ).mul( 4 ).toInt().toVar(); - this._mixBufferRegion = mixFunction; - this._mixBufferRegionAdditive = mixFunctionAdditive; - this._setIdentity = setIdentity; - this._origIndex = 3; - this._addIndex = 4; + const x = j.modInt( size ); + const y = j.div( int( size ) ); + const batchingMatrix = mat4( + textureLoad( matricesTexture, ivec2( x, y ) ), + textureLoad( matricesTexture, ivec2( x.add( 1 ), y ) ), + textureLoad( matricesTexture, ivec2( x.add( 2 ), y ) ), + textureLoad( matricesTexture, ivec2( x.add( 3 ), y ) ) + ); - this.cumulativeWeight = 0; - this.cumulativeWeightAdditive = 0; - this.useCount = 0; - this.referenceCount = 0; + const colorsTexture = this.batchMesh._colorsTexture; - } + if ( colorsTexture !== null ) { - // accumulate data in the 'incoming' region into 'accu' - accumulate( accuIndex, weight ) { + const getBatchingColor = Fn( ( [ id ] ) => { - // note: happily accumulating nothing when weight = 0, the caller knows - // the weight and shouldn't have made the call in the first place + const size = textureSize( textureLoad( colorsTexture ), 0 ).x; + const j = id; + const x = j.modInt( size ); + const y = j.div( size ); + return textureLoad( colorsTexture, ivec2( x, y ) ).rgb; - const buffer = this.buffer, - stride = this.valueSize, - offset = accuIndex * stride + stride; + } ).setLayout( { + name: 'getBatchingColor', + type: 'vec3', + inputs: [ + { name: 'id', type: 'int' } + ] + } ); - let currentWeight = this.cumulativeWeight; + const color = getBatchingColor( indirectId ); - if ( currentWeight === 0 ) { + varyingProperty( 'vec3', 'vBatchColor' ).assign( color ); - // accuN := incoming * weight + } - for ( let i = 0; i !== stride; ++ i ) { + const bm = mat3( batchingMatrix ); - buffer[ offset + i ] = buffer[ i ]; + positionLocal.assign( batchingMatrix.mul( positionLocal ) ); - } + const transformedNormal = normalLocal.div( vec3( bm[ 0 ].dot( bm[ 0 ] ), bm[ 1 ].dot( bm[ 1 ] ), bm[ 2 ].dot( bm[ 2 ] ) ) ); - currentWeight = weight; + const batchingNormal = bm.mul( transformedNormal ).xyz; - } else { + normalLocal.assign( batchingNormal ); - // accuN := accuN + incoming * weight + if ( builder.hasGeometryAttribute( 'tangent' ) ) { - currentWeight += weight; - const mix = weight / currentWeight; - this._mixBufferRegion( buffer, offset, 0, mix, stride ); + tangentLocal.mulAssign( bm ); } - this.cumulativeWeight = currentWeight; - } - // accumulate data in the 'incoming' region into 'add' - accumulateAdditive( weight ) { - - const buffer = this.buffer, - stride = this.valueSize, - offset = stride * this._addIndex; - - if ( this.cumulativeWeightAdditive === 0 ) { +} - // add = identity +const batch = /*@__PURE__*/ nodeProxy( BatchNode ); - this._setIdentity(); +const _frameId = new WeakMap(); - } +class SkinningNode extends Node { - // add := add + incoming * weight + static get type() { - this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride ); - this.cumulativeWeightAdditive += weight; + return 'SkinningNode'; } - // apply the state of 'accu' to the binding when accus differ - apply( accuIndex ) { + constructor( skinnedMesh, useReference = false ) { - const stride = this.valueSize, - buffer = this.buffer, - offset = accuIndex * stride + stride, + super( 'void' ); - weight = this.cumulativeWeight, - weightAdditive = this.cumulativeWeightAdditive, + this.skinnedMesh = skinnedMesh; + this.useReference = useReference; - binding = this.binding; - - this.cumulativeWeight = 0; - this.cumulativeWeightAdditive = 0; - - if ( weight < 1 ) { + this.updateType = NodeUpdateType.OBJECT; - // accuN := accuN + original * ( 1 - cumulativeWeight ) + // - const originalValueOffset = stride * this._origIndex; + this.skinIndexNode = attribute( 'skinIndex', 'uvec4' ); + this.skinWeightNode = attribute( 'skinWeight', 'vec4' ); - this._mixBufferRegion( - buffer, offset, originalValueOffset, 1 - weight, stride ); + let bindMatrixNode, bindMatrixInverseNode, boneMatricesNode; - } + if ( useReference ) { - if ( weightAdditive > 0 ) { + bindMatrixNode = reference( 'bindMatrix', 'mat4' ); + bindMatrixInverseNode = reference( 'bindMatrixInverse', 'mat4' ); + boneMatricesNode = referenceBuffer( 'skeleton.boneMatrices', 'mat4', skinnedMesh.skeleton.bones.length ); - // accuN := accuN + additive accuN + } else { - this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride ); + bindMatrixNode = uniform( skinnedMesh.bindMatrix, 'mat4' ); + bindMatrixInverseNode = uniform( skinnedMesh.bindMatrixInverse, 'mat4' ); + boneMatricesNode = buffer( skinnedMesh.skeleton.boneMatrices, 'mat4', skinnedMesh.skeleton.bones.length ); } - for ( let i = stride, e = stride + stride; i !== e; ++ i ) { + this.bindMatrixNode = bindMatrixNode; + this.bindMatrixInverseNode = bindMatrixInverseNode; + this.boneMatricesNode = boneMatricesNode; + this.previousBoneMatricesNode = null; - if ( buffer[ i ] !== buffer[ i + stride ] ) { + } - // value has changed -> update scene graph + getSkinnedPosition( boneMatrices = this.boneMatricesNode, position = positionLocal ) { - binding.setValue( buffer, offset ); - break; + const { skinIndexNode, skinWeightNode, bindMatrixNode, bindMatrixInverseNode } = this; - } + const boneMatX = boneMatrices.element( skinIndexNode.x ); + const boneMatY = boneMatrices.element( skinIndexNode.y ); + const boneMatZ = boneMatrices.element( skinIndexNode.z ); + const boneMatW = boneMatrices.element( skinIndexNode.w ); - } + // POSITION - } + const skinVertex = bindMatrixNode.mul( position ); - // remember the state of the bound property and copy it to both accus - saveOriginalState() { + const skinned = add( + boneMatX.mul( skinWeightNode.x ).mul( skinVertex ), + boneMatY.mul( skinWeightNode.y ).mul( skinVertex ), + boneMatZ.mul( skinWeightNode.z ).mul( skinVertex ), + boneMatW.mul( skinWeightNode.w ).mul( skinVertex ) + ); - const binding = this.binding; + return bindMatrixInverseNode.mul( skinned ).xyz; - const buffer = this.buffer, - stride = this.valueSize, + } - originalValueOffset = stride * this._origIndex; + getSkinnedNormal( boneMatrices = this.boneMatricesNode, normal = normalLocal ) { - binding.getValue( buffer, originalValueOffset ); + const { skinIndexNode, skinWeightNode, bindMatrixNode, bindMatrixInverseNode } = this; - // accu[0..1] := orig -- initially detect changes against the original - for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) { + const boneMatX = boneMatrices.element( skinIndexNode.x ); + const boneMatY = boneMatrices.element( skinIndexNode.y ); + const boneMatZ = boneMatrices.element( skinIndexNode.z ); + const boneMatW = boneMatrices.element( skinIndexNode.w ); - buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ]; + // NORMAL - } + let skinMatrix = add( + skinWeightNode.x.mul( boneMatX ), + skinWeightNode.y.mul( boneMatY ), + skinWeightNode.z.mul( boneMatZ ), + skinWeightNode.w.mul( boneMatW ) + ); - // Add to identity for additive - this._setIdentity(); + skinMatrix = bindMatrixInverseNode.mul( skinMatrix ).mul( bindMatrixNode ); - this.cumulativeWeight = 0; - this.cumulativeWeightAdditive = 0; + return skinMatrix.transformDirection( normal ).xyz; } - // apply the state previously taken via 'saveOriginalState' to the binding - restoreOriginalState() { - - const originalValueOffset = this.valueSize * 3; - this.binding.setValue( this.buffer, originalValueOffset ); - - } + getPreviousSkinnedPosition( builder ) { - _setAdditiveIdentityNumeric() { + const skinnedMesh = builder.object; - const startIndex = this._addIndex * this.valueSize; - const endIndex = startIndex + this.valueSize; + if ( this.previousBoneMatricesNode === null ) { - for ( let i = startIndex; i < endIndex; i ++ ) { + skinnedMesh.skeleton.previousBoneMatrices = new Float32Array( skinnedMesh.skeleton.boneMatrices ); - this.buffer[ i ] = 0; + this.previousBoneMatricesNode = referenceBuffer( 'skeleton.previousBoneMatrices', 'mat4', skinnedMesh.skeleton.bones.length ); } + return this.getSkinnedPosition( this.previousBoneMatricesNode, positionPrevious ); + } - _setAdditiveIdentityQuaternion() { + needsPreviousBoneMatrices( builder ) { - this._setAdditiveIdentityNumeric(); - this.buffer[ this._addIndex * this.valueSize + 3 ] = 1; + const mrt = builder.renderer.getMRT(); - } + return mrt && mrt.has( 'velocity' ); - _setAdditiveIdentityOther() { + } - const startIndex = this._origIndex * this.valueSize; - const targetIndex = this._addIndex * this.valueSize; + setup( builder ) { - for ( let i = 0; i < this.valueSize; i ++ ) { + if ( this.needsPreviousBoneMatrices( builder ) ) { - this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ]; + positionPrevious.assign( this.getPreviousSkinnedPosition( builder ) ); } - } + const skinPosition = this.getSkinnedPosition(); - // mix functions + positionLocal.assign( skinPosition ); - _select( buffer, dstOffset, srcOffset, t, stride ) { + if ( builder.hasGeometryAttribute( 'normal' ) ) { - if ( t >= 0.5 ) { + const skinNormal = this.getSkinnedNormal(); - for ( let i = 0; i !== stride; ++ i ) { + normalLocal.assign( skinNormal ); - buffer[ dstOffset + i ] = buffer[ srcOffset + i ]; + if ( builder.hasGeometryAttribute( 'tangent' ) ) { + + tangentLocal.assign( skinNormal ); } @@ -43850,11292 +43751,11058 @@ class PropertyMixer { } - _slerp( buffer, dstOffset, srcOffset, t ) { - - Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t ); - - } - - _slerpAdditive( buffer, dstOffset, srcOffset, t, stride ) { + generate( builder, output ) { - const workOffset = this._workIndex * stride; + if ( output !== 'void' ) { - // Store result in intermediate buffer offset - Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset ); + return positionLocal.build( builder, output ); - // Slerp to the intermediate result - Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t ); + } } - _lerp( buffer, dstOffset, srcOffset, t, stride ) { + update( frame ) { - const s = 1 - t; + const object = this.useReference ? frame.object : this.skinnedMesh; + const skeleton = object.skeleton; - for ( let i = 0; i !== stride; ++ i ) { + if ( _frameId.get( skeleton ) === frame.frameId ) return; - const j = dstOffset + i; + _frameId.set( skeleton, frame.frameId ); - buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t; + if ( this.previousBoneMatricesNode !== null ) skeleton.previousBoneMatrices.set( skeleton.boneMatrices ); - } + skeleton.update(); } - _lerpAdditive( buffer, dstOffset, srcOffset, t, stride ) { +} - for ( let i = 0; i !== stride; ++ i ) { +const skinning = ( skinnedMesh ) => nodeObject( new SkinningNode( skinnedMesh ) ); +const skinningReference = ( skinnedMesh ) => nodeObject( new SkinningNode( skinnedMesh, true ) ); - const j = dstOffset + i; +class LoopNode extends Node { - buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t; + static get type() { - } + return 'LoopNode'; } -} - -// Characters [].:/ are reserved for track binding syntax. -const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/'; -const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' ); + constructor( params = [] ) { -// Attempts to allow node names from any language. ES5's `\w` regexp matches -// only latin characters, and the unicode \p{L} is not yet supported. So -// instead, we exclude reserved characters and match everything else. -const _wordChar = '[^' + _RESERVED_CHARS_RE + ']'; -const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']'; + super(); -// Parent directories, delimited by '/' or ':'. Currently unused, but must -// be matched to parse the rest of the track name. -const _directoryRe = /*@__PURE__*/ /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar ); + this.params = params; -// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'. -const _nodeRe = /*@__PURE__*/ /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot ); + } -// Object on target node, and accessor. May not contain reserved -// characters. Accessor may contain any character except closing bracket. -const _objectRe = /*@__PURE__*/ /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar ); + getVarName( index ) { -// Property and accessor. May not contain reserved characters. Accessor may -// contain any non-bracket characters. -const _propertyRe = /*@__PURE__*/ /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar ); + return String.fromCharCode( 'i'.charCodeAt() + index ); -const _trackRe = new RegExp( '' - + '^' - + _directoryRe - + _nodeRe - + _objectRe - + _propertyRe - + '$' -); + } -const _supportedObjectNames = [ 'material', 'materials', 'bones', 'map' ]; + getProperties( builder ) { -class Composite { + const properties = builder.getNodeProperties( this ); - constructor( targetGroup, path, optionalParsedPath ) { + if ( properties.stackNode !== undefined ) return properties; - const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path ); + // - this._targetGroup = targetGroup; - this._bindings = targetGroup.subscribe_( path, parsedPath ); + const inputs = {}; - } + for ( let i = 0, l = this.params.length - 1; i < l; i ++ ) { - getValue( array, offset ) { + const param = this.params[ i ]; - this.bind(); // bind all binding + const name = ( param.isNode !== true && param.name ) || this.getVarName( i ); + const type = ( param.isNode !== true && param.type ) || 'int'; - const firstValidIndex = this._targetGroup.nCachedObjects_, - binding = this._bindings[ firstValidIndex ]; + inputs[ name ] = expression( name, type ); - // and only call .getValue on the first - if ( binding !== undefined ) binding.getValue( array, offset ); + } - } + const stack = builder.addStack(); // TODO: cache() it - setValue( array, offset ) { + properties.returnsNode = this.params[ this.params.length - 1 ]( inputs, stack, builder ); + properties.stackNode = stack; - const bindings = this._bindings; + builder.removeStack(); - for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { + return properties; - bindings[ i ].setValue( array, offset ); + } - } + getNodeType( builder ) { - } + const { returnsNode } = this.getProperties( builder ); - bind() { + return returnsNode ? returnsNode.getNodeType( builder ) : 'void'; - const bindings = this._bindings; + } - for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { + setup( builder ) { - bindings[ i ].bind(); + // setup properties - } + this.getProperties( builder ); } - unbind() { - - const bindings = this._bindings; + generate( builder ) { - for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { + const properties = this.getProperties( builder ); - bindings[ i ].unbind(); + const params = this.params; + const stackNode = properties.stackNode; - } + for ( let i = 0, l = params.length - 1; i < l; i ++ ) { - } + const param = params[ i ]; -} + let start = null, end = null, name = null, type = null, condition = null, update = null; -// Note: This class uses a State pattern on a per-method basis: -// 'bind' sets 'this.getValue' / 'setValue' and shadows the -// prototype version of these methods with one that represents -// the bound state. When the property is not found, the methods -// become no-ops. -class PropertyBinding { + if ( param.isNode ) { - constructor( rootNode, path, parsedPath ) { + type = 'int'; + name = this.getVarName( i ); + start = '0'; + end = param.build( builder, type ); + condition = '<'; - this.path = path; - this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path ); + } else { - this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ); + type = param.type || 'int'; + name = param.name || this.getVarName( i ); + start = param.start; + end = param.end; + condition = param.condition; + update = param.update; - this.rootNode = rootNode; + if ( typeof start === 'number' ) start = start.toString(); + else if ( start && start.isNode ) start = start.build( builder, type ); - // initial state of these methods that calls 'bind' - this.getValue = this._getValue_unbound; - this.setValue = this._setValue_unbound; + if ( typeof end === 'number' ) end = end.toString(); + else if ( end && end.isNode ) end = end.build( builder, type ); - } + if ( start !== undefined && end === undefined ) { + start = start + ' - 1'; + end = '0'; + condition = '>='; - static create( root, path, parsedPath ) { + } else if ( end !== undefined && start === undefined ) { - if ( ! ( root && root.isAnimationObjectGroup ) ) { + start = '0'; + condition = '<'; - return new PropertyBinding( root, path, parsedPath ); + } - } else { + if ( condition === undefined ) { - return new PropertyBinding.Composite( root, path, parsedPath ); + if ( Number( start ) > Number( end ) ) { - } + condition = '>='; - } + } else { - /** - * Replaces spaces with underscores and removes unsupported characters from - * node names, to ensure compatibility with parseTrackName(). - * - * @param {string} name Node name to be sanitized. - * @return {string} - */ - static sanitizeNodeName( name ) { + condition = '<'; - return name.replace( /\s/g, '_' ).replace( _reservedRe, '' ); + } - } + } - static parseTrackName( trackName ) { + } - const matches = _trackRe.exec( trackName ); + const internalParam = { start, end, condition }; - if ( matches === null ) { + // - throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName ); + const startSnippet = internalParam.start; + const endSnippet = internalParam.end; - } + let declarationSnippet = ''; + let conditionalSnippet = ''; + let updateSnippet = ''; - const results = { - // directoryName: matches[ 1 ], // (tschw) currently unused - nodeName: matches[ 2 ], - objectName: matches[ 3 ], - objectIndex: matches[ 4 ], - propertyName: matches[ 5 ], // required - propertyIndex: matches[ 6 ] - }; + if ( ! update ) { - const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' ); + if ( type === 'int' || type === 'uint' ) { - if ( lastDot !== undefined && lastDot !== - 1 ) { + if ( condition.includes( '<' ) ) update = '++'; + else update = '--'; - const objectName = results.nodeName.substring( lastDot + 1 ); + } else { - // Object names must be checked against an allowlist. Otherwise, there - // is no way to parse 'foo.bar.baz': 'baz' must be a property, but - // 'bar' could be the objectName, or part of a nodeName (which can - // include '.' characters). - if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) { + if ( condition.includes( '<' ) ) update = '+= 1.'; + else update = '-= 1.'; - results.nodeName = results.nodeName.substring( 0, lastDot ); - results.objectName = objectName; + } } - } + declarationSnippet += builder.getVar( type, name ) + ' = ' + startSnippet; - if ( results.propertyName === null || results.propertyName.length === 0 ) { + conditionalSnippet += name + ' ' + condition + ' ' + endSnippet; + updateSnippet += name + ' ' + update; - throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName ); + const forSnippet = `for ( ${ declarationSnippet }; ${ conditionalSnippet }; ${ updateSnippet } )`; + + builder.addFlowCode( ( i === 0 ? '\n' : '' ) + builder.tab + forSnippet + ' {\n\n' ).addFlowTab(); } - return results; + const stackSnippet = stackNode.build( builder, 'void' ); - } + const returnsSnippet = properties.returnsNode ? properties.returnsNode.build( builder ) : ''; - static findNode( root, nodeName ) { + builder.removeFlowTab().addFlowCode( '\n' + builder.tab + stackSnippet ); - if ( nodeName === undefined || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) { + for ( let i = 0, l = this.params.length - 1; i < l; i ++ ) { - return root; + builder.addFlowCode( ( i === 0 ? '' : builder.tab ) + '}\n\n' ).removeFlowTab(); } - // search into skeleton bones. - if ( root.skeleton ) { - - const bone = root.skeleton.getBoneByName( nodeName ); + builder.addFlowTab(); - if ( bone !== undefined ) { + return returnsSnippet; - return bone; + } - } +} - } +const Loop = ( ...params ) => nodeObject( new LoopNode( nodeArray( params, 'int' ) ) ).append(); +const Continue = () => expression( 'continue' ).append(); +const Break = () => expression( 'break' ).append(); - // search into node subtree. - if ( root.children ) { +// - const searchNodeSubtree = function ( children ) { +const loop = ( ...params ) => { // @deprecated, r168 - for ( let i = 0; i < children.length; i ++ ) { + console.warn( 'TSL.LoopNode: loop() has been renamed to Loop().' ); + return Loop( ...params ); - const childNode = children[ i ]; +}; - if ( childNode.name === nodeName || childNode.uuid === nodeName ) { +const _morphTextures = /*@__PURE__*/ new WeakMap(); +const _morphVec4 = /*@__PURE__*/ new Vector4(); - return childNode; +const getMorph = /*@__PURE__*/ Fn( ( { bufferMap, influence, stride, width, depth, offset } ) => { - } + const texelIndex = int( vertexIndex ).mul( stride ).add( offset ); - const result = searchNodeSubtree( childNode.children ); + const y = texelIndex.div( width ); + const x = texelIndex.sub( y.mul( width ) ); - if ( result ) return result; + const bufferAttrib = textureLoad( bufferMap, ivec2( x, y ) ).depth( depth ); - } + return bufferAttrib.mul( influence ); - return null; +} ); - }; +function getEntry( geometry ) { - const subTreeNode = searchNodeSubtree( root.children ); + const hasMorphPosition = geometry.morphAttributes.position !== undefined; + const hasMorphNormals = geometry.morphAttributes.normal !== undefined; + const hasMorphColors = geometry.morphAttributes.color !== undefined; - if ( subTreeNode ) { + // instead of using attributes, the WebGL 2 code path encodes morph targets + // into an array of data textures. Each layer represents a single morph target. - return subTreeNode; + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; - } + let entry = _morphTextures.get( geometry ); - } + if ( entry === undefined || entry.count !== morphTargetsCount ) { - return null; + if ( entry !== undefined ) entry.texture.dispose(); - } + const morphTargets = geometry.morphAttributes.position || []; + const morphNormals = geometry.morphAttributes.normal || []; + const morphColors = geometry.morphAttributes.color || []; - // these are used to "bind" a nonexistent property - _getValue_unavailable() {} - _setValue_unavailable() {} + let vertexDataCount = 0; - // Getters + if ( hasMorphPosition === true ) vertexDataCount = 1; + if ( hasMorphNormals === true ) vertexDataCount = 2; + if ( hasMorphColors === true ) vertexDataCount = 3; - _getValue_direct( buffer, offset ) { + let width = geometry.attributes.position.count * vertexDataCount; + let height = 1; - buffer[ offset ] = this.targetObject[ this.propertyName ]; + const maxTextureSize = 4096; // @TODO: Use 'capabilities.maxTextureSize' - } + if ( width > maxTextureSize ) { - _getValue_array( buffer, offset ) { + height = Math.ceil( width / maxTextureSize ); + width = maxTextureSize; - const source = this.resolvedProperty; + } - for ( let i = 0, n = source.length; i !== n; ++ i ) { + const buffer = new Float32Array( width * height * 4 * morphTargetsCount ); - buffer[ offset ++ ] = source[ i ]; + const bufferTexture = new DataArrayTexture( buffer, width, height, morphTargetsCount ); + bufferTexture.type = FloatType; + bufferTexture.needsUpdate = true; - } + // fill buffer - } + const vertexDataStride = vertexDataCount * 4; - _getValue_arrayElement( buffer, offset ) { + for ( let i = 0; i < morphTargetsCount; i ++ ) { - buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ]; + const morphTarget = morphTargets[ i ]; + const morphNormal = morphNormals[ i ]; + const morphColor = morphColors[ i ]; - } + const offset = width * height * 4 * i; - _getValue_toArray( buffer, offset ) { + for ( let j = 0; j < morphTarget.count; j ++ ) { - this.resolvedProperty.toArray( buffer, offset ); + const stride = j * vertexDataStride; - } + if ( hasMorphPosition === true ) { - // Direct + _morphVec4.fromBufferAttribute( morphTarget, j ); - _setValue_direct( buffer, offset ) { + buffer[ offset + stride + 0 ] = _morphVec4.x; + buffer[ offset + stride + 1 ] = _morphVec4.y; + buffer[ offset + stride + 2 ] = _morphVec4.z; + buffer[ offset + stride + 3 ] = 0; - this.targetObject[ this.propertyName ] = buffer[ offset ]; + } - } + if ( hasMorphNormals === true ) { - _setValue_direct_setNeedsUpdate( buffer, offset ) { + _morphVec4.fromBufferAttribute( morphNormal, j ); - this.targetObject[ this.propertyName ] = buffer[ offset ]; - this.targetObject.needsUpdate = true; - - } - - _setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) { - - this.targetObject[ this.propertyName ] = buffer[ offset ]; - this.targetObject.matrixWorldNeedsUpdate = true; + buffer[ offset + stride + 4 ] = _morphVec4.x; + buffer[ offset + stride + 5 ] = _morphVec4.y; + buffer[ offset + stride + 6 ] = _morphVec4.z; + buffer[ offset + stride + 7 ] = 0; - } + } - // EntireArray + if ( hasMorphColors === true ) { - _setValue_array( buffer, offset ) { + _morphVec4.fromBufferAttribute( morphColor, j ); - const dest = this.resolvedProperty; + buffer[ offset + stride + 8 ] = _morphVec4.x; + buffer[ offset + stride + 9 ] = _morphVec4.y; + buffer[ offset + stride + 10 ] = _morphVec4.z; + buffer[ offset + stride + 11 ] = ( morphColor.itemSize === 4 ) ? _morphVec4.w : 1; - for ( let i = 0, n = dest.length; i !== n; ++ i ) { + } - dest[ i ] = buffer[ offset ++ ]; + } } - } + entry = { + count: morphTargetsCount, + texture: bufferTexture, + stride: vertexDataCount, + size: new Vector2( width, height ) + }; - _setValue_array_setNeedsUpdate( buffer, offset ) { + _morphTextures.set( geometry, entry ); - const dest = this.resolvedProperty; + function disposeTexture() { - for ( let i = 0, n = dest.length; i !== n; ++ i ) { + bufferTexture.dispose(); - dest[ i ] = buffer[ offset ++ ]; + _morphTextures.delete( geometry ); + + geometry.removeEventListener( 'dispose', disposeTexture ); } - this.targetObject.needsUpdate = true; + geometry.addEventListener( 'dispose', disposeTexture ); } - _setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) { + return entry; - const dest = this.resolvedProperty; +} - for ( let i = 0, n = dest.length; i !== n; ++ i ) { - dest[ i ] = buffer[ offset ++ ]; +class MorphNode extends Node { - } + static get type() { - this.targetObject.matrixWorldNeedsUpdate = true; + return 'MorphNode'; } - // ArrayElement - - _setValue_arrayElement( buffer, offset ) { - - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; + constructor( mesh ) { - } + super( 'void' ); - _setValue_arrayElement_setNeedsUpdate( buffer, offset ) { + this.mesh = mesh; + this.morphBaseInfluence = uniform( 1 ); - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; - this.targetObject.needsUpdate = true; + this.updateType = NodeUpdateType.OBJECT; } - _setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) { + setup( builder ) { - this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; - this.targetObject.matrixWorldNeedsUpdate = true; + const { geometry } = builder; - } + const hasMorphPosition = geometry.morphAttributes.position !== undefined; + const hasMorphNormals = geometry.hasAttribute( 'normal' ) && geometry.morphAttributes.normal !== undefined; - // HasToFromArray + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; - _setValue_fromArray( buffer, offset ) { + // nodes - this.resolvedProperty.fromArray( buffer, offset ); + const { texture: bufferMap, stride, size } = getEntry( geometry ); - } + if ( hasMorphPosition === true ) positionLocal.mulAssign( this.morphBaseInfluence ); + if ( hasMorphNormals === true ) normalLocal.mulAssign( this.morphBaseInfluence ); - _setValue_fromArray_setNeedsUpdate( buffer, offset ) { + const width = int( size.width ); - this.resolvedProperty.fromArray( buffer, offset ); - this.targetObject.needsUpdate = true; + Loop( morphTargetsCount, ( { i } ) => { - } + const influence = float( 0 ).toVar(); - _setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) { + if ( this.mesh.count > 1 && ( this.mesh.morphTexture !== null && this.mesh.morphTexture !== undefined ) ) { - this.resolvedProperty.fromArray( buffer, offset ); - this.targetObject.matrixWorldNeedsUpdate = true; + influence.assign( textureLoad( this.mesh.morphTexture, ivec2( int( i ).add( 1 ), int( instanceIndex ) ) ).r ); - } + } else { - _getValue_unbound( targetArray, offset ) { + influence.assign( reference( 'morphTargetInfluences', 'float' ).element( i ).toVar() ); - this.bind(); - this.getValue( targetArray, offset ); + } - } + if ( hasMorphPosition === true ) { - _setValue_unbound( sourceArray, offset ) { + positionLocal.addAssign( getMorph( { + bufferMap, + influence, + stride, + width, + depth: i, + offset: int( 0 ) + } ) ); - this.bind(); - this.setValue( sourceArray, offset ); + } - } + if ( hasMorphNormals === true ) { - // create getter / setter pair for a property in the scene graph - bind() { + normalLocal.addAssign( getMorph( { + bufferMap, + influence, + stride, + width, + depth: i, + offset: int( 1 ) + } ) ); - let targetObject = this.node; - const parsedPath = this.parsedPath; + } - const objectName = parsedPath.objectName; - const propertyName = parsedPath.propertyName; - let propertyIndex = parsedPath.propertyIndex; + } ); - if ( ! targetObject ) { + } - targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ); + update() { - this.node = targetObject; + const morphBaseInfluence = this.morphBaseInfluence; - } + if ( this.mesh.geometry.morphTargetsRelative ) { - // set fail state so we can just 'return' on error - this.getValue = this._getValue_unavailable; - this.setValue = this._setValue_unavailable; + morphBaseInfluence.value = 1; - // ensure there is a value node - if ( ! targetObject ) { + } else { - console.warn( 'THREE.PropertyBinding: No target node found for track: ' + this.path + '.' ); - return; + morphBaseInfluence.value = 1 - this.mesh.morphTargetInfluences.reduce( ( a, b ) => a + b, 0 ); } - if ( objectName ) { + } - let objectIndex = parsedPath.objectIndex; +} - // special cases were we need to reach deeper into the hierarchy to get the face materials.... - switch ( objectName ) { +const morphReference = /*@__PURE__*/ nodeProxy( MorphNode ); - case 'materials': +const sortLights = ( lights ) => { - if ( ! targetObject.material ) { + return lights.sort( ( a, b ) => a.id - b.id ); - console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); - return; +}; - } +const getLightNodeById = ( id, lightNodes ) => { - if ( ! targetObject.material.materials ) { + for ( const lightNode of lightNodes ) { - console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this ); - return; + if ( lightNode.isAnalyticLightNode && lightNode.light.id === id ) { - } + return lightNode; - targetObject = targetObject.material.materials; + } - break; + } - case 'bones': + return null; - if ( ! targetObject.skeleton ) { +}; - console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this ); - return; +const _lightsNodeRef = /*@__PURE__*/ new WeakMap(); - } +class LightsNode extends Node { - // potential future optimization: skip this if propertyIndex is already an integer - // and convert the integer string to a true integer. + static get type() { - targetObject = targetObject.skeleton.bones; + return 'LightsNode'; - // support resolving morphTarget names into indices. - for ( let i = 0; i < targetObject.length; i ++ ) { + } - if ( targetObject[ i ].name === objectIndex ) { + constructor( lights = [] ) { - objectIndex = i; - break; + super( 'vec3' ); - } + this.totalDiffuseNode = vec3().toVar( 'totalDiffuse' ); + this.totalSpecularNode = vec3().toVar( 'totalSpecular' ); - } + this.outgoingLightNode = vec3().toVar( 'outgoingLight' ); - break; + this._lights = lights; - case 'map': + this._lightNodes = null; + this._lightNodesHash = null; - if ( 'map' in targetObject ) { + this.global = true; - targetObject = targetObject.map; - break; + } - } + getHash( builder ) { - if ( ! targetObject.material ) { + if ( this._lightNodesHash === null ) { - console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); - return; + if ( this._lightNodes === null ) this.setupLightsNode( builder ); - } + const hash = []; - if ( ! targetObject.material.map ) { + for ( const lightNode of this._lightNodes ) { - console.error( 'THREE.PropertyBinding: Can not bind to material.map as node.material does not have a map.', this ); - return; + hash.push( lightNode.getHash() ); - } + } - targetObject = targetObject.material.map; - break; + this._lightNodesHash = 'lights-' + hash.join( ',' ); - default: + } - if ( targetObject[ objectName ] === undefined ) { + return this._lightNodesHash; - console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this ); - return; + } - } + analyze( builder ) { - targetObject = targetObject[ objectName ]; + const properties = builder.getDataFromNode( this ); - } + for ( const node of properties.nodes ) { + node.build( builder ); - if ( objectIndex !== undefined ) { + } - if ( targetObject[ objectIndex ] === undefined ) { + } - console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject ); - return; + setupLightsNode( builder ) { - } + const lightNodes = []; - targetObject = targetObject[ objectIndex ]; + const previousLightNodes = this._lightNodes; - } + const lights = sortLights( this._lights ); + const nodeLibrary = builder.renderer.nodes.library; - } + for ( const light of lights ) { - // resolve property - const nodeProperty = targetObject[ propertyName ]; + if ( light.isNode ) { - if ( nodeProperty === undefined ) { + lightNodes.push( nodeObject( light ) ); - const nodeName = parsedPath.nodeName; + } else { - console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName + - '.' + propertyName + ' but it wasn\'t found.', targetObject ); - return; + let lightNode = null; - } + if ( previousLightNodes !== null ) { - // determine versioning scheme - let versioning = this.Versioning.None; + lightNode = getLightNodeById( light.id, previousLightNodes ); // resuse existing light node - this.targetObject = targetObject; + } - if ( targetObject.needsUpdate !== undefined ) { // material + if ( lightNode === null ) { - versioning = this.Versioning.NeedsUpdate; + const lightNodeClass = nodeLibrary.getLightNodeClass( light.constructor ); - } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform + if ( lightNodeClass === null ) { - versioning = this.Versioning.MatrixWorldNeedsUpdate; + console.warn( `LightsNode.setupNodeLights: Light node not found for ${ light.constructor.name }` ); + continue; - } + } - // determine how the property gets bound - let bindingType = this.BindingType.Direct; + let lightNode = null; - if ( propertyIndex !== undefined ) { + if ( ! _lightsNodeRef.has( light ) ) { - // access a sub element of the property array (only primitives are supported right now) + lightNode = new lightNodeClass( light ); + _lightsNodeRef.set( light, lightNode ); - if ( propertyName === 'morphTargetInfluences' ) { + } else { - // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer. + lightNode = _lightsNodeRef.get( light ); - // support resolving morphTarget names into indices. - if ( ! targetObject.geometry ) { + } - console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this ); - return; + lightNodes.push( lightNode ); } - if ( ! targetObject.geometry.morphAttributes ) { + } - console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this ); - return; + } - } + this._lightNodes = lightNodes; - if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) { + } - propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ]; + setup( builder ) { - } + if ( this._lightNodes === null ) this.setupLightsNode( builder ); - } + const context = builder.context; + const lightingModel = context.lightingModel; - bindingType = this.BindingType.ArrayElement; + let outgoingLightNode = this.outgoingLightNode; - this.resolvedProperty = nodeProperty; - this.propertyIndex = propertyIndex; + if ( lightingModel ) { - } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) { + const { _lightNodes, totalDiffuseNode, totalSpecularNode } = this; - // must use copy for Object3D.Euler/Quaternion + context.outgoingLight = outgoingLightNode; - bindingType = this.BindingType.HasFromToArray; + const stack = builder.addStack(); - this.resolvedProperty = nodeProperty; + // - } else if ( Array.isArray( nodeProperty ) ) { + const properties = builder.getDataFromNode( this ); + properties.nodes = stack.nodes; - bindingType = this.BindingType.EntireArray; + // - this.resolvedProperty = nodeProperty; + lightingModel.start( context, stack, builder ); - } else { + // lights - this.propertyName = propertyName; + for ( const lightNode of _lightNodes ) { - } + lightNode.build( builder ); - // select getter / setter - this.getValue = this.GetterByBindingType[ bindingType ]; - this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ]; + } - } + // - unbind() { + lightingModel.indirect( context, stack, builder ); - this.node = null; + // - // back to the prototype version of getValue / setValue - // note: avoiding to mutate the shape of 'this' via 'delete' - this.getValue = this._getValue_unbound; - this.setValue = this._setValue_unbound; + const { backdrop, backdropAlpha } = context; + const { directDiffuse, directSpecular, indirectDiffuse, indirectSpecular } = context.reflectedLight; - } + let totalDiffuse = directDiffuse.add( indirectDiffuse ); -} + if ( backdrop !== null ) { -PropertyBinding.Composite = Composite; + if ( backdropAlpha !== null ) { -PropertyBinding.prototype.BindingType = { - Direct: 0, - EntireArray: 1, - ArrayElement: 2, - HasFromToArray: 3 -}; + totalDiffuse = vec3( backdropAlpha.mix( totalDiffuse, backdrop ) ); -PropertyBinding.prototype.Versioning = { - None: 0, - NeedsUpdate: 1, - MatrixWorldNeedsUpdate: 2 -}; + } else { -PropertyBinding.prototype.GetterByBindingType = [ + totalDiffuse = vec3( backdrop ); - PropertyBinding.prototype._getValue_direct, - PropertyBinding.prototype._getValue_array, - PropertyBinding.prototype._getValue_arrayElement, - PropertyBinding.prototype._getValue_toArray, + } -]; + context.material.transparent = true; -PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [ + } - [ - // Direct - PropertyBinding.prototype._setValue_direct, - PropertyBinding.prototype._setValue_direct_setNeedsUpdate, - PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate, + totalDiffuseNode.assign( totalDiffuse ); + totalSpecularNode.assign( directSpecular.add( indirectSpecular ) ); - ], [ + outgoingLightNode.assign( totalDiffuseNode.add( totalSpecularNode ) ); - // EntireArray + // - PropertyBinding.prototype._setValue_array, - PropertyBinding.prototype._setValue_array_setNeedsUpdate, - PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate, + lightingModel.finish( context, stack, builder ); - ], [ + // - // ArrayElement - PropertyBinding.prototype._setValue_arrayElement, - PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate, - PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate, + outgoingLightNode = outgoingLightNode.bypass( builder.removeStack() ); - ], [ + } - // HasToFromArray - PropertyBinding.prototype._setValue_fromArray, - PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate, - PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate, + return outgoingLightNode; - ] + } -]; + setLights( lights ) { -/** - * - * A group of objects that receives a shared animation state. - * - * Usage: - * - * - Add objects you would otherwise pass as 'root' to the - * constructor or the .clipAction method of AnimationMixer. - * - * - Instead pass this object as 'root'. - * - * - You can also add and remove objects later when the mixer - * is running. - * - * Note: - * - * Objects of this class appear as one object to the mixer, - * so cache control of the individual objects must be done - * on the group. - * - * Limitation: - * - * - The animated properties must be compatible among the - * all objects in the group. - * - * - A single property can either be controlled through a - * target group or directly, but not both. - */ + this._lights = lights; -class AnimationObjectGroup { + this._lightNodes = null; + this._lightNodesHash = null; - constructor() { + return this; - this.isAnimationObjectGroup = true; + } - this.uuid = generateUUID(); + getLights() { - // cached objects followed by the active ones - this._objects = Array.prototype.slice.call( arguments ); + return this._lights; - this.nCachedObjects_ = 0; // threshold - // note: read by PropertyBinding.Composite + } - const indices = {}; - this._indicesByUUID = indices; // for bookkeeping +} - for ( let i = 0, n = arguments.length; i !== n; ++ i ) { +const lights = /*@__PURE__*/ nodeProxy( LightsNode ); - indices[ arguments[ i ].uuid ] = i; +class LightingNode extends Node { - } + static get type() { - this._paths = []; // inside: string - this._parsedPaths = []; // inside: { we don't care, here } - this._bindings = []; // inside: Array< PropertyBinding > - this._bindingsIndicesByPath = {}; // inside: indices in these arrays + return 'LightingNode'; - const scope = this; + } - this.stats = { + constructor() { - objects: { - get total() { + super( 'vec3' ); - return scope._objects.length; + this.isLightingNode = true; - }, - get inUse() { + } - return this.total - scope.nCachedObjects_; + generate( /*builder*/ ) { - } - }, - get bindingsPerObject() { + console.warn( 'Abstract function.' ); - return scope._bindings.length; + } - } +} - }; +class AONode extends LightingNode { + + static get type() { + + return 'AONode'; } - add() { + constructor( aoNode = null ) { - const objects = this._objects, - indicesByUUID = this._indicesByUUID, - paths = this._paths, - parsedPaths = this._parsedPaths, - bindings = this._bindings, - nBindings = bindings.length; - - let knownObject = undefined, - nObjects = objects.length, - nCachedObjects = this.nCachedObjects_; - - for ( let i = 0, n = arguments.length; i !== n; ++ i ) { - - const object = arguments[ i ], - uuid = object.uuid; - let index = indicesByUUID[ uuid ]; - - if ( index === undefined ) { - - // unknown object -> add it to the ACTIVE region - - index = nObjects ++; - indicesByUUID[ uuid ] = index; - objects.push( object ); - - // accounting is done, now do the same for all bindings + super(); - for ( let j = 0, m = nBindings; j !== m; ++ j ) { + this.aoNode = aoNode; - bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) ); + } - } + setup( builder ) { - } else if ( index < nCachedObjects ) { + builder.context.ambientOcclusion.mulAssign( this.aoNode ); - knownObject = objects[ index ]; + } - // move existing object to the ACTIVE region +} - const firstActiveIndex = -- nCachedObjects, - lastCachedObject = objects[ firstActiveIndex ]; +class LightingContextNode extends ContextNode { - indicesByUUID[ lastCachedObject.uuid ] = index; - objects[ index ] = lastCachedObject; + static get type() { - indicesByUUID[ uuid ] = firstActiveIndex; - objects[ firstActiveIndex ] = object; + return 'LightingContextNode'; - // accounting is done, now do the same for all bindings + } - for ( let j = 0, m = nBindings; j !== m; ++ j ) { + constructor( node, lightingModel = null, backdropNode = null, backdropAlphaNode = null ) { - const bindingsForPath = bindings[ j ], - lastCached = bindingsForPath[ firstActiveIndex ]; + super( node ); - let binding = bindingsForPath[ index ]; + this.lightingModel = lightingModel; + this.backdropNode = backdropNode; + this.backdropAlphaNode = backdropAlphaNode; - bindingsForPath[ index ] = lastCached; + this._value = null; - if ( binding === undefined ) { + } - // since we do not bother to create new bindings - // for objects that are cached, the binding may - // or may not exist + getContext() { - binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ); + const { backdropNode, backdropAlphaNode } = this; - } + const directDiffuse = vec3().toVar( 'directDiffuse' ), + directSpecular = vec3().toVar( 'directSpecular' ), + indirectDiffuse = vec3().toVar( 'indirectDiffuse' ), + indirectSpecular = vec3().toVar( 'indirectSpecular' ); - bindingsForPath[ firstActiveIndex ] = binding; + const reflectedLight = { + directDiffuse, + directSpecular, + indirectDiffuse, + indirectSpecular + }; - } + const context = { + radiance: vec3().toVar( 'radiance' ), + irradiance: vec3().toVar( 'irradiance' ), + iblIrradiance: vec3().toVar( 'iblIrradiance' ), + ambientOcclusion: float( 1 ).toVar( 'ambientOcclusion' ), + reflectedLight, + backdrop: backdropNode, + backdropAlpha: backdropAlphaNode + }; - } else if ( objects[ index ] !== knownObject ) { + return context; - console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' + - 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' ); + } - } // else the object is already where we want it to be + setup( builder ) { - } // for arguments + this.value = this._value || ( this._value = this.getContext() ); + this.value.lightingModel = this.lightingModel || builder.context.lightingModel; - this.nCachedObjects_ = nCachedObjects; + return super.setup( builder ); } - remove() { +} - const objects = this._objects, - indicesByUUID = this._indicesByUUID, - bindings = this._bindings, - nBindings = bindings.length; +const lightingContext = /*@__PURE__*/ nodeProxy( LightingContextNode ); - let nCachedObjects = this.nCachedObjects_; +class IrradianceNode extends LightingNode { - for ( let i = 0, n = arguments.length; i !== n; ++ i ) { + static get type() { - const object = arguments[ i ], - uuid = object.uuid, - index = indicesByUUID[ uuid ]; + return 'IrradianceNode'; - if ( index !== undefined && index >= nCachedObjects ) { + } - // move existing object into the CACHED region + constructor( node ) { - const lastCachedIndex = nCachedObjects ++, - firstActiveObject = objects[ lastCachedIndex ]; + super(); - indicesByUUID[ firstActiveObject.uuid ] = index; - objects[ index ] = firstActiveObject; + this.node = node; - indicesByUUID[ uuid ] = lastCachedIndex; - objects[ lastCachedIndex ] = object; + } - // accounting is done, now do the same for all bindings + setup( builder ) { - for ( let j = 0, m = nBindings; j !== m; ++ j ) { + builder.context.irradiance.addAssign( this.node ); - const bindingsForPath = bindings[ j ], - firstActive = bindingsForPath[ lastCachedIndex ], - binding = bindingsForPath[ index ]; + } - bindingsForPath[ index ] = firstActive; - bindingsForPath[ lastCachedIndex ] = binding; +} - } +let screenSizeVec, viewportVec; - } +class ScreenNode extends Node { - } // for arguments + static get type() { - this.nCachedObjects_ = nCachedObjects; + return 'ScreenNode'; } - // remove & forget - uncache() { - - const objects = this._objects, - indicesByUUID = this._indicesByUUID, - bindings = this._bindings, - nBindings = bindings.length; + constructor( scope ) { - let nCachedObjects = this.nCachedObjects_, - nObjects = objects.length; + super(); - for ( let i = 0, n = arguments.length; i !== n; ++ i ) { + this.scope = scope; - const object = arguments[ i ], - uuid = object.uuid, - index = indicesByUUID[ uuid ]; + this.isViewportNode = true; - if ( index !== undefined ) { + } - delete indicesByUUID[ uuid ]; + getNodeType() { - if ( index < nCachedObjects ) { + if ( this.scope === ScreenNode.VIEWPORT ) return 'vec4'; + else return 'vec2'; - // object is cached, shrink the CACHED region + } - const firstActiveIndex = -- nCachedObjects, - lastCachedObject = objects[ firstActiveIndex ], - lastIndex = -- nObjects, - lastObject = objects[ lastIndex ]; + getUpdateType() { - // last cached object takes this object's place - indicesByUUID[ lastCachedObject.uuid ] = index; - objects[ index ] = lastCachedObject; + let updateType = NodeUpdateType.NONE; - // last object goes to the activated slot and pop - indicesByUUID[ lastObject.uuid ] = firstActiveIndex; - objects[ firstActiveIndex ] = lastObject; - objects.pop(); + if ( this.scope === ScreenNode.SIZE || this.scope === ScreenNode.VIEWPORT ) { - // accounting is done, now do the same for all bindings + updateType = NodeUpdateType.RENDER; - for ( let j = 0, m = nBindings; j !== m; ++ j ) { + } - const bindingsForPath = bindings[ j ], - lastCached = bindingsForPath[ firstActiveIndex ], - last = bindingsForPath[ lastIndex ]; + this.updateType = updateType; - bindingsForPath[ index ] = lastCached; - bindingsForPath[ firstActiveIndex ] = last; - bindingsForPath.pop(); + return updateType; - } + } - } else { + update( { renderer } ) { - // object is active, just swap with the last and pop + const renderTarget = renderer.getRenderTarget(); - const lastIndex = -- nObjects, - lastObject = objects[ lastIndex ]; + if ( this.scope === ScreenNode.VIEWPORT ) { - if ( lastIndex > 0 ) { + if ( renderTarget !== null ) { - indicesByUUID[ lastObject.uuid ] = index; + viewportVec.copy( renderTarget.viewport ); - } + } else { - objects[ index ] = lastObject; - objects.pop(); + renderer.getViewport( viewportVec ); - // accounting is done, now do the same for all bindings + viewportVec.multiplyScalar( renderer.getPixelRatio() ); - for ( let j = 0, m = nBindings; j !== m; ++ j ) { + } - const bindingsForPath = bindings[ j ]; + } else { - bindingsForPath[ index ] = bindingsForPath[ lastIndex ]; - bindingsForPath.pop(); + if ( renderTarget !== null ) { - } + screenSizeVec.width = renderTarget.width; + screenSizeVec.height = renderTarget.height; - } // cached or active + } else { - } // if object is known + renderer.getDrawingBufferSize( screenSizeVec ); - } // for arguments + } - this.nCachedObjects_ = nCachedObjects; + } } - // Internal interface used by befriended PropertyBinding.Composite: - - subscribe_( path, parsedPath ) { - - // returns an array of bindings for the given path that is changed - // according to the contained objects in the group + setup( /*builder*/ ) { - const indicesByPath = this._bindingsIndicesByPath; - let index = indicesByPath[ path ]; - const bindings = this._bindings; + const scope = this.scope; - if ( index !== undefined ) return bindings[ index ]; + let output = null; - const paths = this._paths, - parsedPaths = this._parsedPaths, - objects = this._objects, - nObjects = objects.length, - nCachedObjects = this.nCachedObjects_, - bindingsForPath = new Array( nObjects ); + if ( scope === ScreenNode.SIZE ) { - index = bindings.length; + output = uniform( screenSizeVec || ( screenSizeVec = new Vector2() ) ); - indicesByPath[ path ] = index; + } else if ( scope === ScreenNode.VIEWPORT ) { - paths.push( path ); - parsedPaths.push( parsedPath ); - bindings.push( bindingsForPath ); + output = uniform( viewportVec || ( viewportVec = new Vector4() ) ); - for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) { + } else { - const object = objects[ i ]; - bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath ); + output = vec2( screenCoordinate.div( screenSize ) ); } - return bindingsForPath; + return output; } - unsubscribe_( path ) { + generate( builder ) { - // tells the group to forget about a property path and no longer - // update the array previously obtained with 'subscribe_' + if ( this.scope === ScreenNode.COORDINATE ) { - const indicesByPath = this._bindingsIndicesByPath, - index = indicesByPath[ path ]; + let coord = builder.getFragCoord(); - if ( index !== undefined ) { + if ( builder.isFlipY() ) { - const paths = this._paths, - parsedPaths = this._parsedPaths, - bindings = this._bindings, - lastBindingsIndex = bindings.length - 1, - lastBindings = bindings[ lastBindingsIndex ], - lastBindingsPath = path[ lastBindingsIndex ]; + // follow webgpu standards - indicesByPath[ lastBindingsPath ] = index; + const size = builder.getNodeProperties( screenSize ).outputNode.build( builder ); - bindings[ index ] = lastBindings; - bindings.pop(); + coord = `${ builder.getType( 'vec2' ) }( ${ coord }.x, ${ size }.y - ${ coord }.y )`; - parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ]; - parsedPaths.pop(); + } - paths[ index ] = paths[ lastBindingsIndex ]; - paths.pop(); + return coord; } + return super.generate( builder ); + } } -class AnimationAction { +ScreenNode.COORDINATE = 'coordinate'; +ScreenNode.VIEWPORT = 'viewport'; +ScreenNode.SIZE = 'size'; +ScreenNode.UV = 'uv'; - constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) { +// Screen - this._mixer = mixer; - this._clip = clip; - this._localRoot = localRoot; - this.blendMode = blendMode; +const screenUV = /*@__PURE__*/ nodeImmutable( ScreenNode, ScreenNode.UV ); +const screenSize = /*@__PURE__*/ nodeImmutable( ScreenNode, ScreenNode.SIZE ); +const screenCoordinate = /*@__PURE__*/ nodeImmutable( ScreenNode, ScreenNode.COORDINATE ); - const tracks = clip.tracks, - nTracks = tracks.length, - interpolants = new Array( nTracks ); +// Viewport - const interpolantSettings = { - endingStart: ZeroCurvatureEnding, - endingEnd: ZeroCurvatureEnding - }; +const viewport = /*@__PURE__*/ nodeImmutable( ScreenNode, ScreenNode.VIEWPORT ); +const viewportSize = viewport.zw; +const viewportCoordinate = /*@__PURE__*/ screenCoordinate.sub( viewport.xy ); +const viewportUV = /*@__PURE__*/ viewportCoordinate.div( viewportSize ); - for ( let i = 0; i !== nTracks; ++ i ) { +// Deprecated - const interpolant = tracks[ i ].createInterpolant( null ); - interpolants[ i ] = interpolant; - interpolant.settings = interpolantSettings; +const viewportResolution = /*@__PURE__*/ ( Fn( () => { // @deprecated, r169 - } + console.warn( 'TSL.ViewportNode: "viewportResolution" is deprecated. Use "screenSize" instead.' ); - this._interpolantSettings = interpolantSettings; + return screenSize; - this._interpolants = interpolants; // bound by the mixer +}, 'vec2' ).once() )(); - // inside: PropertyMixer (managed by the mixer) - this._propertyBindings = new Array( nTracks ); +const viewportTopLeft = /*@__PURE__*/ ( Fn( () => { // @deprecated, r168 - this._cacheIndex = null; // for the memory manager - this._byClipCacheIndex = null; // for the memory manager + console.warn( 'TSL.ViewportNode: "viewportTopLeft" is deprecated. Use "screenUV" instead.' ); - this._timeScaleInterpolant = null; - this._weightInterpolant = null; + return screenUV; - this.loop = LoopRepeat; - this._loopCount = - 1; +}, 'vec2' ).once() )(); - // global mixer time when the action is to be started - // it's set back to 'null' upon start of the action - this._startTime = null; +const viewportBottomLeft = /*@__PURE__*/ ( Fn( () => { // @deprecated, r168 - // scaled local time of the action - // gets clamped or wrapped to 0..clip.duration according to loop - this.time = 0; + console.warn( 'TSL.ViewportNode: "viewportBottomLeft" is deprecated. Use "screenUV.flipY()" instead.' ); - this.timeScale = 1; - this._effectiveTimeScale = 1; + return screenUV.flipY(); - this.weight = 1; - this._effectiveWeight = 1; +}, 'vec2' ).once() )(); - this.repetitions = Infinity; // no. of repetitions when looping +const _size$a = /*@__PURE__*/ new Vector2(); - this.paused = false; // true -> zero effective time scale - this.enabled = true; // false -> zero effective weight +class ViewportTextureNode extends TextureNode { - this.clampWhenFinished = false;// keep feeding the last frame? + static get type() { - this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate - this.zeroSlopeAtEnd = true;// clips for start, loop and end + return 'ViewportTextureNode'; } - // State & Scheduling + constructor( uvNode = screenUV, levelNode = null, framebufferTexture = null ) { - play() { + if ( framebufferTexture === null ) { - this._mixer._activateAction( this ); + framebufferTexture = new FramebufferTexture(); + framebufferTexture.minFilter = LinearMipmapLinearFilter; - return this; + } - } + super( framebufferTexture, uvNode, levelNode ); - stop() { + this.generateMipmaps = false; - this._mixer._deactivateAction( this ); + this.isOutputTextureNode = true; - return this.reset(); + this.updateBeforeType = NodeUpdateType.FRAME; } - reset() { + updateBefore( frame ) { - this.paused = false; - this.enabled = true; + const renderer = frame.renderer; + renderer.getDrawingBufferSize( _size$a ); - this.time = 0; // restart clip - this._loopCount = - 1;// forget previous loops - this._startTime = null;// forget scheduling + // - return this.stopFading().stopWarping(); + const framebufferTexture = this.value; - } + if ( framebufferTexture.image.width !== _size$a.width || framebufferTexture.image.height !== _size$a.height ) { - isRunning() { + framebufferTexture.image.width = _size$a.width; + framebufferTexture.image.height = _size$a.height; + framebufferTexture.needsUpdate = true; - return this.enabled && ! this.paused && this.timeScale !== 0 && - this._startTime === null && this._mixer._isActiveAction( this ); + } - } + // - // return true when play has been called - isScheduled() { + const currentGenerateMipmaps = framebufferTexture.generateMipmaps; + framebufferTexture.generateMipmaps = this.generateMipmaps; - return this._mixer._isActiveAction( this ); + renderer.copyFramebufferToTexture( framebufferTexture ); + + framebufferTexture.generateMipmaps = currentGenerateMipmaps; } - startAt( time ) { + clone() { - this._startTime = time; + const viewportTextureNode = new this.constructor( this.uvNode, this.levelNode, this.value ); + viewportTextureNode.generateMipmaps = this.generateMipmaps; - return this; + return viewportTextureNode; } - setLoop( mode, repetitions ) { +} - this.loop = mode; - this.repetitions = repetitions; +const viewportTexture = /*@__PURE__*/ nodeProxy( ViewportTextureNode ); +const viewportMipTexture = /*@__PURE__*/ nodeProxy( ViewportTextureNode, null, null, { generateMipmaps: true } ); - return this; +let sharedDepthbuffer = null; + +class ViewportDepthTextureNode extends ViewportTextureNode { + + static get type() { + + return 'ViewportDepthTextureNode'; } - // Weight + constructor( uvNode = screenUV, levelNode = null ) { - // set the weight stopping any scheduled fading - // although .enabled = false yields an effective weight of zero, this - // method does *not* change .enabled, because it would be confusing - setEffectiveWeight( weight ) { + if ( sharedDepthbuffer === null ) { - this.weight = weight; + sharedDepthbuffer = new DepthTexture(); - // note: same logic as when updated at runtime - this._effectiveWeight = this.enabled ? weight : 0; + } - return this.stopFading(); + super( uvNode, levelNode, sharedDepthbuffer ); } - // return the weight considering fading and .enabled - getEffectiveWeight() { +} - return this._effectiveWeight; +const viewportDepthTexture = /*@__PURE__*/ nodeProxy( ViewportDepthTextureNode ); - } +class ViewportDepthNode extends Node { - fadeIn( duration ) { + static get type() { - return this._scheduleFading( duration, 0, 1 ); + return 'ViewportDepthNode'; } - fadeOut( duration ) { + constructor( scope, valueNode = null ) { - return this._scheduleFading( duration, 1, 0 ); + super( 'float' ); - } + this.scope = scope; + this.valueNode = valueNode; - crossFadeFrom( fadeOutAction, duration, warp ) { + this.isViewportDepthNode = true; - fadeOutAction.fadeOut( duration ); - this.fadeIn( duration ); + } - if ( warp ) { + generate( builder ) { - const fadeInDuration = this._clip.duration, - fadeOutDuration = fadeOutAction._clip.duration, + const { scope } = this; - startEndRatio = fadeOutDuration / fadeInDuration, - endStartRatio = fadeInDuration / fadeOutDuration; + if ( scope === ViewportDepthNode.DEPTH_BASE ) { - fadeOutAction.warp( 1.0, startEndRatio, duration ); - this.warp( endStartRatio, 1.0, duration ); + return builder.getFragDepth(); } - return this; + return super.generate( builder ); } - crossFadeTo( fadeInAction, duration, warp ) { + setup( { camera } ) { - return fadeInAction.crossFadeFrom( this, duration, warp ); + const { scope } = this; + const value = this.valueNode; - } + let node = null; - stopFading() { + if ( scope === ViewportDepthNode.DEPTH_BASE ) { - const weightInterpolant = this._weightInterpolant; + if ( value !== null ) { - if ( weightInterpolant !== null ) { + node = depthBase().assign( value ); - this._weightInterpolant = null; - this._mixer._takeBackControlInterpolant( weightInterpolant ); + } - } + } else if ( scope === ViewportDepthNode.DEPTH ) { - return this; + if ( camera.isPerspectiveCamera ) { - } + node = viewZToPerspectiveDepth( positionView.z, cameraNear, cameraFar ); - // Time Scale Control + } else { - // set the time scale stopping any scheduled warping - // although .paused = true yields an effective time scale of zero, this - // method does *not* change .paused, because it would be confusing - setEffectiveTimeScale( timeScale ) { + node = viewZToOrthographicDepth( positionView.z, cameraNear, cameraFar ); - this.timeScale = timeScale; - this._effectiveTimeScale = this.paused ? 0 : timeScale; + } - return this.stopWarping(); + } else if ( scope === ViewportDepthNode.LINEAR_DEPTH ) { - } + if ( value !== null ) { - // return the time scale considering warping and .paused - getEffectiveTimeScale() { + if ( camera.isPerspectiveCamera ) { - return this._effectiveTimeScale; + const viewZ = perspectiveDepthToViewZ( value, cameraNear, cameraFar ); - } + node = viewZToOrthographicDepth( viewZ, cameraNear, cameraFar ); - setDuration( duration ) { + } else { - this.timeScale = this._clip.duration / duration; + node = value; - return this.stopWarping(); + } - } + } else { - syncWith( action ) { + node = viewZToOrthographicDepth( positionView.z, cameraNear, cameraFar ); - this.time = action.time; - this.timeScale = action.timeScale; + } - return this.stopWarping(); + } + + return node; } - halt( duration ) { +} - return this.warp( this._effectiveTimeScale, 0, duration ); +ViewportDepthNode.DEPTH_BASE = 'depthBase'; +ViewportDepthNode.DEPTH = 'depth'; +ViewportDepthNode.LINEAR_DEPTH = 'linearDepth'; - } +// NOTE: viewZ, the z-coordinate in camera space, is negative for points in front of the camera - warp( startTimeScale, endTimeScale, duration ) { +// -near maps to 0; -far maps to 1 +const viewZToOrthographicDepth = ( viewZ, near, far ) => viewZ.add( near ).div( near.sub( far ) ); - const mixer = this._mixer, - now = mixer.time, - timeScale = this.timeScale; +// maps orthographic depth in [ 0, 1 ] to viewZ +const orthographicDepthToViewZ = ( depth, near, far ) => near.sub( far ).mul( depth ).sub( near ); - let interpolant = this._timeScaleInterpolant; +// NOTE: https://twitter.com/gonnavis/status/1377183786949959682 - if ( interpolant === null ) { +// -near maps to 0; -far maps to 1 +const viewZToPerspectiveDepth = ( viewZ, near, far ) => near.add( viewZ ).mul( far ).div( far.sub( near ).mul( viewZ ) ); - interpolant = mixer._lendControlInterpolant(); - this._timeScaleInterpolant = interpolant; +// maps perspective depth in [ 0, 1 ] to viewZ +const perspectiveDepthToViewZ = ( depth, near, far ) => near.mul( far ).div( far.sub( near ).mul( depth ).sub( far ) ); - } +const depthBase = /*@__PURE__*/ nodeProxy( ViewportDepthNode, ViewportDepthNode.DEPTH_BASE ); - const times = interpolant.parameterPositions, - values = interpolant.sampleValues; +const depth = /*@__PURE__*/ nodeImmutable( ViewportDepthNode, ViewportDepthNode.DEPTH ); +const linearDepth = /*@__PURE__*/ nodeProxy( ViewportDepthNode, ViewportDepthNode.LINEAR_DEPTH ); +const viewportLinearDepth = /*@__PURE__*/ linearDepth( viewportDepthTexture() ); - times[ 0 ] = now; - times[ 1 ] = now + duration; +depth.assign = ( value ) => depthBase( value ); - values[ 0 ] = startTimeScale / timeScale; - values[ 1 ] = endTimeScale / timeScale; +class ClippingNode extends Node { - return this; + static get type() { + + return 'ClippingNode'; } - stopWarping() { + constructor( scope = ClippingNode.DEFAULT ) { - const timeScaleInterpolant = this._timeScaleInterpolant; + super(); - if ( timeScaleInterpolant !== null ) { + this.scope = scope; - this._timeScaleInterpolant = null; - this._mixer._takeBackControlInterpolant( timeScaleInterpolant ); + } - } + setup( builder ) { - return this; + super.setup( builder ); - } + const clippingContext = builder.clippingContext; + const { localClipIntersection, localClippingCount, globalClippingCount } = clippingContext; - // Object Accessors + const numClippingPlanes = globalClippingCount + localClippingCount; + const numUnionClippingPlanes = localClipIntersection ? numClippingPlanes - localClippingCount : numClippingPlanes; - getMixer() { + if ( this.scope === ClippingNode.ALPHA_TO_COVERAGE ) { - return this._mixer; + return this.setupAlphaToCoverage( clippingContext.planes, numClippingPlanes, numUnionClippingPlanes ); - } + } else { - getClip() { + return this.setupDefault( clippingContext.planes, numClippingPlanes, numUnionClippingPlanes ); - return this._clip; + } } - getRoot() { + setupAlphaToCoverage( planes, numClippingPlanes, numUnionClippingPlanes ) { - return this._localRoot || this._mixer._root; + return Fn( () => { - } + const clippingPlanes = uniformArray( planes ); - // Interna + const distanceToPlane = property( 'float', 'distanceToPlane' ); + const distanceGradient = property( 'float', 'distanceToGradient' ); - _update( time, deltaTime, timeDirection, accuIndex ) { + const clipOpacity = property( 'float', 'clipOpacity' ); - // called by the mixer + clipOpacity.assign( 1 ); - if ( ! this.enabled ) { + let plane; - // call ._updateWeight() to update ._effectiveWeight + Loop( numUnionClippingPlanes, ( { i } ) => { - this._updateWeight( time ); - return; + plane = clippingPlanes.element( i ); - } + distanceToPlane.assign( positionView.dot( plane.xyz ).negate().add( plane.w ) ); + distanceGradient.assign( distanceToPlane.fwidth().div( 2.0 ) ); - const startTime = this._startTime; + clipOpacity.mulAssign( smoothstep( distanceGradient.negate(), distanceGradient, distanceToPlane ) ); - if ( startTime !== null ) { + clipOpacity.equal( 0.0 ).discard(); - // check for scheduled start of action + } ); - const timeRunning = ( time - startTime ) * timeDirection; - if ( timeRunning < 0 || timeDirection === 0 ) { + if ( numUnionClippingPlanes < numClippingPlanes ) { - deltaTime = 0; + const unionClipOpacity = property( 'float', 'unionclipOpacity' ); - } else { + unionClipOpacity.assign( 1 ); + Loop( { start: numUnionClippingPlanes, end: numClippingPlanes }, ( { i } ) => { - this._startTime = null; // unschedule - deltaTime = timeDirection * timeRunning; + plane = clippingPlanes.element( i ); + + distanceToPlane.assign( positionView.dot( plane.xyz ).negate().add( plane.w ) ); + distanceGradient.assign( distanceToPlane.fwidth().div( 2.0 ) ); + + unionClipOpacity.mulAssign( smoothstep( distanceGradient.negate(), distanceGradient, distanceToPlane ).oneMinus() ); + + } ); + + clipOpacity.mulAssign( unionClipOpacity.oneMinus() ); } - } + diffuseColor.a.mulAssign( clipOpacity ); - // apply time scale and advance time + diffuseColor.a.equal( 0.0 ).discard(); - deltaTime *= this._updateTimeScale( time ); - const clipTime = this._updateTime( deltaTime ); + } )(); - // note: _updateTime may disable the action resulting in - // an effective weight of 0 + } - const weight = this._updateWeight( time ); + setupDefault( planes, numClippingPlanes, numUnionClippingPlanes ) { - if ( weight > 0 ) { + return Fn( () => { - const interpolants = this._interpolants; - const propertyMixers = this._propertyBindings; + const clippingPlanes = uniformArray( planes ); - switch ( this.blendMode ) { + let plane; - case AdditiveAnimationBlendMode: + Loop( numUnionClippingPlanes, ( { i } ) => { - for ( let j = 0, m = interpolants.length; j !== m; ++ j ) { + plane = clippingPlanes.element( i ); + positionView.dot( plane.xyz ).greaterThan( plane.w ).discard(); - interpolants[ j ].evaluate( clipTime ); - propertyMixers[ j ].accumulateAdditive( weight ); + } ); - } + if ( numUnionClippingPlanes < numClippingPlanes ) { - break; + const clipped = property( 'bool', 'clipped' ); - case NormalAnimationBlendMode: - default: + clipped.assign( true ); - for ( let j = 0, m = interpolants.length; j !== m; ++ j ) { + Loop( { start: numUnionClippingPlanes, end: numClippingPlanes }, ( { i } ) => { - interpolants[ j ].evaluate( clipTime ); - propertyMixers[ j ].accumulate( accuIndex, weight ); + plane = clippingPlanes.element( i ); + clipped.assign( positionView.dot( plane.xyz ).greaterThan( plane.w ).and( clipped ) ); - } + } ); + + clipped.discard(); } - } + } )(); } - _updateWeight( time ) { - - let weight = 0; +} - if ( this.enabled ) { +ClippingNode.ALPHA_TO_COVERAGE = 'alphaToCoverage'; +ClippingNode.DEFAULT = 'default'; - weight = this.weight; - const interpolant = this._weightInterpolant; +const clipping = () => nodeObject( new ClippingNode() ); - if ( interpolant !== null ) { +const clippingAlpha = () => nodeObject( new ClippingNode( ClippingNode.ALPHA_TO_COVERAGE ) ); - const interpolantValue = interpolant.evaluate( time )[ 0 ]; +class NodeMaterial extends Material { - weight *= interpolantValue; + static get type() { - if ( time > interpolant.parameterPositions[ 1 ] ) { + return 'NodeMaterial'; - this.stopFading(); + } - if ( interpolantValue === 0 ) { + constructor() { - // faded out, disable - this.enabled = false; + super(); - } + this.isNodeMaterial = true; - } + this.type = this.constructor.type; - } + this.forceSinglePass = false; - } + this.fog = true; + this.lights = false; - this._effectiveWeight = weight; - return weight; + this.lightsNode = null; + this.envNode = null; + this.aoNode = null; - } + this.colorNode = null; + this.normalNode = null; + this.opacityNode = null; + this.backdropNode = null; + this.backdropAlphaNode = null; + this.alphaTestNode = null; - _updateTimeScale( time ) { + this.positionNode = null; - let timeScale = 0; + this.depthNode = null; + this.shadowNode = null; + this.shadowPositionNode = null; - if ( ! this.paused ) { + this.outputNode = null; + this.mrtNode = null; - timeScale = this.timeScale; + this.fragmentNode = null; + this.vertexNode = null; - const interpolant = this._timeScaleInterpolant; + } - if ( interpolant !== null ) { + customProgramCacheKey() { - const interpolantValue = interpolant.evaluate( time )[ 0 ]; + return this.type + getCacheKey$1( this ); - timeScale *= interpolantValue; + } - if ( time > interpolant.parameterPositions[ 1 ] ) { + build( builder ) { - this.stopWarping(); + this.setup( builder ); - if ( timeScale === 0 ) { + } - // motion has halted, pause - this.paused = true; + setupObserver( builder ) { - } else { + return new NodeMaterialObserver( builder ); - // warp done - apply final time scale - this.timeScale = timeScale; + } - } + setup( builder ) { - } + builder.context.setupNormal = () => this.setupNormal( builder ); - } + // < VERTEX STAGE > - } + builder.addStack(); - this._effectiveTimeScale = timeScale; - return timeScale; + builder.stack.outputNode = this.vertexNode || this.setupPosition( builder ); - } + builder.addFlow( 'vertex', builder.removeStack() ); - _updateTime( deltaTime ) { + // < FRAGMENT STAGE > - const duration = this._clip.duration; - const loop = this.loop; + builder.addStack(); - let time = this.time + deltaTime; - let loopCount = this._loopCount; + let resultNode; - const pingPong = ( loop === LoopPingPong ); + const clippingNode = this.setupClipping( builder ); - if ( deltaTime === 0 ) { + if ( this.depthWrite === true ) this.setupDepth( builder ); - if ( loopCount === - 1 ) return time; + if ( this.fragmentNode === null ) { - return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time; + this.setupDiffuseColor( builder ); + this.setupVariants( builder ); - } + const outgoingLightNode = this.setupLighting( builder ); - if ( loop === LoopOnce ) { + if ( clippingNode !== null ) builder.stack.add( clippingNode ); - if ( loopCount === - 1 ) { + // force unsigned floats - useful for RenderTargets - // just started + const basicOutput = vec4( outgoingLightNode, diffuseColor.a ).max( 0 ); - this._loopCount = 0; - this._setEndings( true, true, false ); + resultNode = this.setupOutput( builder, basicOutput ); - } + // OUTPUT NODE - handle_stop: { + output.assign( resultNode ); - if ( time >= duration ) { + // - time = duration; + if ( this.outputNode !== null ) resultNode = this.outputNode; - } else if ( time < 0 ) { + // MRT - time = 0; + const renderTarget = builder.renderer.getRenderTarget(); - } else { + if ( renderTarget !== null ) { - this.time = time; + const mrt = builder.renderer.getMRT(); + const materialMRT = this.mrtNode; - break handle_stop; + if ( mrt !== null ) { - } + resultNode = mrt; - if ( this.clampWhenFinished ) this.paused = true; - else this.enabled = false; + if ( materialMRT !== null ) { - this.time = time; + resultNode = mrt.merge( materialMRT ); - this._mixer.dispatchEvent( { - type: 'finished', action: this, - direction: deltaTime < 0 ? - 1 : 1 - } ); + } - } + } else if ( materialMRT !== null ) { - } else { // repetitive Repeat or PingPong + resultNode = materialMRT; - if ( loopCount === - 1 ) { + } - // just started + } - if ( deltaTime >= 0 ) { + } else { - loopCount = 0; + let fragmentNode = this.fragmentNode; - this._setEndings( true, this.repetitions === 0, pingPong ); + if ( fragmentNode.isOutputStructNode !== true ) { - } else { + fragmentNode = vec4( fragmentNode ); - // when looping in reverse direction, the initial - // transition through zero counts as a repetition, - // so leave loopCount at -1 + } - this._setEndings( this.repetitions === 0, true, pingPong ); + resultNode = this.setupOutput( builder, fragmentNode ); - } + } - } + builder.stack.outputNode = resultNode; - if ( time >= duration || time < 0 ) { + builder.addFlow( 'fragment', builder.removeStack() ); - // wrap around + // < MONITOR > - const loopDelta = Math.floor( time / duration ); // signed - time -= duration * loopDelta; + builder.monitor = this.setupObserver( builder ); - loopCount += Math.abs( loopDelta ); + } - const pending = this.repetitions - loopCount; + setupClipping( builder ) { - if ( pending <= 0 ) { + if ( builder.clippingContext === null ) return null; - // have to stop (switch state, clamp time, fire event) + const { globalClippingCount, localClippingCount } = builder.clippingContext; - if ( this.clampWhenFinished ) this.paused = true; - else this.enabled = false; + let result = null; - time = deltaTime > 0 ? duration : 0; + if ( globalClippingCount || localClippingCount ) { - this.time = time; + const samples = builder.renderer.samples; - this._mixer.dispatchEvent( { - type: 'finished', action: this, - direction: deltaTime > 0 ? 1 : - 1 - } ); + if ( this.alphaToCoverage && samples > 1 ) { - } else { + // to be added to flow when the color/alpha value has been determined + result = clippingAlpha(); - // keep running + } else { - if ( pending === 1 ) { + builder.stack.add( clipping() ); - // entering the last round + } - const atStart = deltaTime < 0; - this._setEndings( atStart, ! atStart, pingPong ); + } - } else { + return result; - this._setEndings( false, false, pingPong ); + } - } + setupDepth( builder ) { - this._loopCount = loopCount; + const { renderer } = builder; - this.time = time; + // Depth - this._mixer.dispatchEvent( { - type: 'loop', action: this, loopDelta: loopDelta - } ); + let depthNode = this.depthNode; - } + if ( depthNode === null ) { - } else { + const mrt = renderer.getMRT(); - this.time = time; + if ( mrt && mrt.has( 'depth' ) ) { - } + depthNode = mrt.get( 'depth' ); - if ( pingPong && ( loopCount & 1 ) === 1 ) { + } else if ( renderer.logarithmicDepthBuffer === true ) { - // invert time for the "pong round" + const fragDepth = modelViewProjection().w.add( 1 ); - return duration - time; + depthNode = fragDepth.log2().mul( cameraLogDepth ).mul( 0.5 ); } } - return time; + if ( depthNode !== null ) { + + depth.assign( depthNode ).append(); + + } } - _setEndings( atStart, atEnd, pingPong ) { + setupPosition( builder ) { - const settings = this._interpolantSettings; + const { object } = builder; + const geometry = object.geometry; - if ( pingPong ) { + builder.addStack(); - settings.endingStart = ZeroSlopeEnding; - settings.endingEnd = ZeroSlopeEnding; + // Vertex - } else { + if ( geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color ) { - // assuming for LoopOnce atStart == atEnd == true + morphReference( object ).append(); - if ( atStart ) { + } - settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding; + if ( object.isSkinnedMesh === true ) { - } else { + skinningReference( object ).append(); - settings.endingStart = WrapAroundEnding; + } - } + if ( this.displacementMap ) { - if ( atEnd ) { + const displacementMap = materialReference( 'displacementMap', 'texture' ); + const displacementScale = materialReference( 'displacementScale', 'float' ); + const displacementBias = materialReference( 'displacementBias', 'float' ); - settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding; + positionLocal.addAssign( normalLocal.normalize().mul( ( displacementMap.x.mul( displacementScale ).add( displacementBias ) ) ) ); - } else { + } - settings.endingEnd = WrapAroundEnding; + if ( object.isBatchedMesh ) { - } + batch( object ).append(); } - } + if ( ( object.instanceMatrix && object.instanceMatrix.isInstancedBufferAttribute === true ) ) { - _scheduleFading( duration, weightNow, weightThen ) { + instance( object ).append(); - const mixer = this._mixer, now = mixer.time; - let interpolant = this._weightInterpolant; + } - if ( interpolant === null ) { + if ( this.positionNode !== null ) { - interpolant = mixer._lendControlInterpolant(); - this._weightInterpolant = interpolant; + positionLocal.assign( this.positionNode ); } - const times = interpolant.parameterPositions, - values = interpolant.sampleValues; + const mvp = modelViewProjection(); - times[ 0 ] = now; - values[ 0 ] = weightNow; - times[ 1 ] = now + duration; - values[ 1 ] = weightThen; + builder.context.vertex = builder.removeStack(); + builder.context.mvp = mvp; - return this; + return mvp; } -} + setupDiffuseColor( { object, geometry } ) { -const _controlInterpolantsResultBuffer = new Float32Array( 1 ); + let colorNode = this.colorNode ? vec4( this.colorNode ) : materialColor; + // VERTEX COLORS -class AnimationMixer extends EventDispatcher { + if ( this.vertexColors === true && geometry.hasAttribute( 'color' ) ) { - constructor( root ) { + colorNode = vec4( colorNode.xyz.mul( attribute( 'color', 'vec3' ) ), colorNode.a ); - super(); + } - this._root = root; - this._initMemoryManager(); - this._accuIndex = 0; - this.time = 0; - this.timeScale = 1.0; + // Instanced colors - } + if ( object.instanceColor ) { - _bindAction( action, prototypeAction ) { + const instanceColor = varyingProperty( 'vec3', 'vInstanceColor' ); - const root = action._localRoot || this._root, - tracks = action._clip.tracks, - nTracks = tracks.length, - bindings = action._propertyBindings, - interpolants = action._interpolants, - rootUuid = root.uuid, - bindingsByRoot = this._bindingsByRootAndName; + colorNode = instanceColor.mul( colorNode ); - let bindingsByName = bindingsByRoot[ rootUuid ]; + } - if ( bindingsByName === undefined ) { + if ( object.isBatchedMesh && object._colorsTexture ) { - bindingsByName = {}; - bindingsByRoot[ rootUuid ] = bindingsByName; + const batchColor = varyingProperty( 'vec3', 'vBatchColor' ); + + colorNode = batchColor.mul( colorNode ); } - for ( let i = 0; i !== nTracks; ++ i ) { - const track = tracks[ i ], - trackName = track.name; + // COLOR - let binding = bindingsByName[ trackName ]; + diffuseColor.assign( colorNode ); - if ( binding !== undefined ) { + // OPACITY - ++ binding.referenceCount; - bindings[ i ] = binding; + const opacityNode = this.opacityNode ? float( this.opacityNode ) : materialOpacity; + diffuseColor.a.assign( diffuseColor.a.mul( opacityNode ) ); - } else { + // ALPHA TEST - binding = bindings[ i ]; + if ( this.alphaTestNode !== null || this.alphaTest > 0 ) { - if ( binding !== undefined ) { - - // existing binding, make sure the cache knows - - if ( binding._cacheIndex === null ) { + const alphaTestNode = this.alphaTestNode !== null ? float( this.alphaTestNode ) : materialAlphaTest; - ++ binding.referenceCount; - this._addInactiveBinding( binding, rootUuid, trackName ); + diffuseColor.a.lessThanEqual( alphaTestNode ).discard(); - } + } - continue; + if ( this.transparent === false && this.blending === NormalBlending && this.alphaToCoverage === false ) { - } + diffuseColor.a.assign( 1.0 ); - const path = prototypeAction && prototypeAction. - _propertyBindings[ i ].binding.parsedPath; + } - binding = new PropertyMixer( - PropertyBinding.create( root, trackName, path ), - track.ValueTypeName, track.getValueSize() ); + } - ++ binding.referenceCount; - this._addInactiveBinding( binding, rootUuid, trackName ); + setupVariants( /*builder*/ ) { - bindings[ i ] = binding; + // Interface function. - } + } - interpolants[ i ].resultBuffer = binding.buffer; + setupOutgoingLight() { - } + return ( this.lights === true ) ? vec3( 0 ) : diffuseColor.rgb; } - _activateAction( action ) { + setupNormal() { - if ( ! this._isActiveAction( action ) ) { + return this.normalNode ? vec3( this.normalNode ) : materialNormal; - if ( action._cacheIndex === null ) { + } - // this action has been forgotten by the cache, but the user - // appears to be still using it -> rebind + setupEnvironment( /*builder*/ ) { - const rootUuid = ( action._localRoot || this._root ).uuid, - clipUuid = action._clip.uuid, - actionsForClip = this._actionsByClip[ clipUuid ]; + let node = null; - this._bindAction( action, - actionsForClip && actionsForClip.knownActions[ 0 ] ); + if ( this.envNode ) { - this._addInactiveAction( action, clipUuid, rootUuid ); + node = this.envNode; - } + } else if ( this.envMap ) { - const bindings = action._propertyBindings; + node = this.envMap.isCubeTexture ? materialReference( 'envMap', 'cubeTexture' ) : materialReference( 'envMap', 'texture' ); - // increment reference counts / sort out state - for ( let i = 0, n = bindings.length; i !== n; ++ i ) { + } - const binding = bindings[ i ]; + return node; - if ( binding.useCount ++ === 0 ) { + } - this._lendBinding( binding ); - binding.saveOriginalState(); + setupLightMap( builder ) { - } + let node = null; - } + if ( builder.material.lightMap ) { - this._lendAction( action ); + node = new IrradianceNode( materialLightMap ); } + return node; + } - _deactivateAction( action ) { + setupLights( builder ) { - if ( this._isActiveAction( action ) ) { + const materialLightsNode = []; - const bindings = action._propertyBindings; + // - // decrement reference counts / sort out state - for ( let i = 0, n = bindings.length; i !== n; ++ i ) { + const envNode = this.setupEnvironment( builder ); - const binding = bindings[ i ]; + if ( envNode && envNode.isLightingNode ) { - if ( -- binding.useCount === 0 ) { + materialLightsNode.push( envNode ); - binding.restoreOriginalState(); - this._takeBackBinding( binding ); + } - } + const lightMapNode = this.setupLightMap( builder ); - } + if ( lightMapNode && lightMapNode.isLightingNode ) { - this._takeBackAction( action ); + materialLightsNode.push( lightMapNode ); } - } + if ( this.aoNode !== null || builder.material.aoMap ) { - // Memory manager + const aoNode = this.aoNode !== null ? this.aoNode : materialAOMap; - _initMemoryManager() { + materialLightsNode.push( new AONode( aoNode ) ); - this._actions = []; // 'nActiveActions' followed by inactive ones - this._nActiveActions = 0; + } - this._actionsByClip = {}; - // inside: - // { - // knownActions: Array< AnimationAction > - used as prototypes - // actionByRoot: AnimationAction - lookup - // } + let lightsN = this.lightsNode || builder.lightsNode; + if ( materialLightsNode.length > 0 ) { - this._bindings = []; // 'nActiveBindings' followed by inactive ones - this._nActiveBindings = 0; + lightsN = lights( [ ...lightsN.getLights(), ...materialLightsNode ] ); - this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer > + } + return lightsN; - this._controlInterpolants = []; // same game as above - this._nActiveControlInterpolants = 0; + } - const scope = this; + setupLightingModel( /*builder*/ ) { - this.stats = { + // Interface function. - actions: { - get total() { + } - return scope._actions.length; + setupLighting( builder ) { - }, - get inUse() { + const { material } = builder; + const { backdropNode, backdropAlphaNode, emissiveNode } = this; - return scope._nActiveActions; + // OUTGOING LIGHT - } - }, - bindings: { - get total() { + const lights = this.lights === true || this.lightsNode !== null; - return scope._bindings.length; + const lightsNode = lights ? this.setupLights( builder ) : null; - }, - get inUse() { + let outgoingLightNode = this.setupOutgoingLight( builder ); - return scope._nActiveBindings; + if ( lightsNode && lightsNode.getScope().getLights().length > 0 ) { - } - }, - controlInterpolants: { - get total() { + const lightingModel = this.setupLightingModel( builder ); - return scope._controlInterpolants.length; + outgoingLightNode = lightingContext( lightsNode, lightingModel, backdropNode, backdropAlphaNode ); - }, - get inUse() { + } else if ( backdropNode !== null ) { - return scope._nActiveControlInterpolants; + outgoingLightNode = vec3( backdropAlphaNode !== null ? mix( outgoingLightNode, backdropNode, backdropAlphaNode ) : backdropNode ); - } - } + } - }; + // EMISSIVE - } + if ( ( emissiveNode && emissiveNode.isNode === true ) || ( material.emissive && material.emissive.isColor === true ) ) { - // Memory management for AnimationAction objects + emissive.assign( vec3( emissiveNode ? emissiveNode : materialEmissive ) ); - _isActiveAction( action ) { + outgoingLightNode = outgoingLightNode.add( emissive ); - const index = action._cacheIndex; - return index !== null && index < this._nActiveActions; + } - } + return outgoingLightNode; - _addInactiveAction( action, clipUuid, rootUuid ) { + } - const actions = this._actions, - actionsByClip = this._actionsByClip; + setupOutput( builder, outputNode ) { - let actionsForClip = actionsByClip[ clipUuid ]; + // FOG - if ( actionsForClip === undefined ) { + if ( this.fog === true ) { - actionsForClip = { + const fogNode = builder.fogNode; - knownActions: [ action ], - actionByRoot: {} + if ( fogNode ) outputNode = vec4( fogNode.mix( outputNode.rgb, fogNode.colorNode ), outputNode.a ); - }; + } - action._byClipCacheIndex = 0; + return outputNode; - actionsByClip[ clipUuid ] = actionsForClip; + } - } else { + setDefaultValues( material ) { - const knownActions = actionsForClip.knownActions; + // This approach is to reuse the native refreshUniforms* + // and turn available the use of features like transmission and environment in core - action._byClipCacheIndex = knownActions.length; - knownActions.push( action ); + for ( const property in material ) { - } + const value = material[ property ]; - action._cacheIndex = actions.length; - actions.push( action ); + if ( this[ property ] === undefined ) { - actionsForClip.actionByRoot[ rootUuid ] = action; + this[ property ] = value; - } + if ( value && value.clone ) this[ property ] = value.clone(); - _removeInactiveAction( action ) { + } - const actions = this._actions, - lastInactiveAction = actions[ actions.length - 1 ], - cacheIndex = action._cacheIndex; + } - lastInactiveAction._cacheIndex = cacheIndex; - actions[ cacheIndex ] = lastInactiveAction; - actions.pop(); + const descriptors = Object.getOwnPropertyDescriptors( material.constructor.prototype ); - action._cacheIndex = null; + for ( const key in descriptors ) { + if ( Object.getOwnPropertyDescriptor( this.constructor.prototype, key ) === undefined && + descriptors[ key ].get !== undefined ) { - const clipUuid = action._clip.uuid, - actionsByClip = this._actionsByClip, - actionsForClip = actionsByClip[ clipUuid ], - knownActionsForClip = actionsForClip.knownActions, + Object.defineProperty( this.constructor.prototype, key, descriptors[ key ] ); - lastKnownAction = - knownActionsForClip[ knownActionsForClip.length - 1 ], + } - byClipCacheIndex = action._byClipCacheIndex; + } - lastKnownAction._byClipCacheIndex = byClipCacheIndex; - knownActionsForClip[ byClipCacheIndex ] = lastKnownAction; - knownActionsForClip.pop(); + } - action._byClipCacheIndex = null; + toJSON( meta ) { + const isRoot = ( meta === undefined || typeof meta === 'string' ); - const actionByRoot = actionsForClip.actionByRoot, - rootUuid = ( action._localRoot || this._root ).uuid; + if ( isRoot ) { - delete actionByRoot[ rootUuid ]; + meta = { + textures: {}, + images: {}, + nodes: {} + }; - if ( knownActionsForClip.length === 0 ) { + } - delete actionsByClip[ clipUuid ]; + const data = Material.prototype.toJSON.call( this, meta ); + const nodeChildren = getNodeChildren( this ); - } + data.inputNodes = {}; - this._removeInactiveBindingsForAction( action ); + for ( const { property, childNode } of nodeChildren ) { - } + data.inputNodes[ property ] = childNode.toJSON( meta ).uuid; - _removeInactiveBindingsForAction( action ) { + } - const bindings = action._propertyBindings; + // TODO: Copied from Object3D.toJSON - for ( let i = 0, n = bindings.length; i !== n; ++ i ) { + function extractFromCache( cache ) { - const binding = bindings[ i ]; + const values = []; - if ( -- binding.referenceCount === 0 ) { + for ( const key in cache ) { - this._removeInactiveBinding( binding ); + const data = cache[ key ]; + delete data.metadata; + values.push( data ); } + return values; + } - } + if ( isRoot ) { - _lendAction( action ) { + const textures = extractFromCache( meta.textures ); + const images = extractFromCache( meta.images ); + const nodes = extractFromCache( meta.nodes ); - // [ active actions | inactive actions ] - // [ active actions >| inactive actions ] - // s a - // <-swap-> - // a s + if ( textures.length > 0 ) data.textures = textures; + if ( images.length > 0 ) data.images = images; + if ( nodes.length > 0 ) data.nodes = nodes; - const actions = this._actions, - prevIndex = action._cacheIndex, + } - lastActiveIndex = this._nActiveActions ++, + return data; - firstInactiveAction = actions[ lastActiveIndex ]; + } - action._cacheIndex = lastActiveIndex; - actions[ lastActiveIndex ] = action; + copy( source ) { - firstInactiveAction._cacheIndex = prevIndex; - actions[ prevIndex ] = firstInactiveAction; + this.lightsNode = source.lightsNode; + this.envNode = source.envNode; - } + this.colorNode = source.colorNode; + this.normalNode = source.normalNode; + this.opacityNode = source.opacityNode; + this.backdropNode = source.backdropNode; + this.backdropAlphaNode = source.backdropAlphaNode; + this.alphaTestNode = source.alphaTestNode; - _takeBackAction( action ) { + this.positionNode = source.positionNode; - // [ active actions | inactive actions ] - // [ active actions |< inactive actions ] - // a s - // <-swap-> - // s a + this.depthNode = source.depthNode; + this.shadowNode = source.shadowNode; + this.shadowPositionNode = source.shadowPositionNode; - const actions = this._actions, - prevIndex = action._cacheIndex, + this.outputNode = source.outputNode; + this.mrtNode = source.mrtNode; - firstInactiveIndex = -- this._nActiveActions, + this.fragmentNode = source.fragmentNode; + this.vertexNode = source.vertexNode; - lastActiveAction = actions[ firstInactiveIndex ]; + return super.copy( source ); - action._cacheIndex = firstInactiveIndex; - actions[ firstInactiveIndex ] = action; + } - lastActiveAction._cacheIndex = prevIndex; - actions[ prevIndex ] = lastActiveAction; +} - } +const _defaultValues$e = /*@__PURE__*/ new PointsMaterial(); - // Memory management for PropertyMixer objects +class InstancedPointsNodeMaterial extends NodeMaterial { - _addInactiveBinding( binding, rootUuid, trackName ) { + static get type() { - const bindingsByRoot = this._bindingsByRootAndName, - bindings = this._bindings; + return 'InstancedPointsNodeMaterial'; - let bindingByName = bindingsByRoot[ rootUuid ]; + } - if ( bindingByName === undefined ) { + constructor( params = {} ) { - bindingByName = {}; - bindingsByRoot[ rootUuid ] = bindingByName; + super(); - } + this.lights = false; - bindingByName[ trackName ] = binding; + this.useAlphaToCoverage = true; - binding._cacheIndex = bindings.length; - bindings.push( binding ); + this.useColor = params.vertexColors; - } + this.pointWidth = 1; - _removeInactiveBinding( binding ) { + this.pointColorNode = null; - const bindings = this._bindings, - propBinding = binding.binding, - rootUuid = propBinding.rootNode.uuid, - trackName = propBinding.path, - bindingsByRoot = this._bindingsByRootAndName, - bindingByName = bindingsByRoot[ rootUuid ], + this.pointWidthNode = null; - lastInactiveBinding = bindings[ bindings.length - 1 ], - cacheIndex = binding._cacheIndex; + this.setDefaultValues( _defaultValues$e ); - lastInactiveBinding._cacheIndex = cacheIndex; - bindings[ cacheIndex ] = lastInactiveBinding; - bindings.pop(); + this.setValues( params ); - delete bindingByName[ trackName ]; + } - if ( Object.keys( bindingByName ).length === 0 ) { + setup( builder ) { - delete bindingsByRoot[ rootUuid ]; + this.setupShaders( builder ); - } + super.setup( builder ); } - _lendBinding( binding ) { + setupShaders( { renderer } ) { - const bindings = this._bindings, - prevIndex = binding._cacheIndex, + const useAlphaToCoverage = this.alphaToCoverage; + const useColor = this.useColor; - lastActiveIndex = this._nActiveBindings ++, + this.vertexNode = Fn( () => { - firstInactiveBinding = bindings[ lastActiveIndex ]; + const instancePosition = attribute( 'instancePosition' ).xyz; - binding._cacheIndex = lastActiveIndex; - bindings[ lastActiveIndex ] = binding; + // camera space + const mvPos = vec4( modelViewMatrix.mul( vec4( instancePosition, 1.0 ) ) ); - firstInactiveBinding._cacheIndex = prevIndex; - bindings[ prevIndex ] = firstInactiveBinding; + const aspect = viewport.z.div( viewport.w ); - } + // clip space + const clipPos = cameraProjectionMatrix.mul( mvPos ); - _takeBackBinding( binding ) { + // offset in ndc space + const offset = positionGeometry.xy.toVar(); - const bindings = this._bindings, - prevIndex = binding._cacheIndex, + offset.mulAssign( this.pointWidthNode ? this.pointWidthNode : materialPointWidth ); - firstInactiveIndex = -- this._nActiveBindings, + offset.assign( offset.div( viewport.z ) ); + offset.y.assign( offset.y.mul( aspect ) ); - lastActiveBinding = bindings[ firstInactiveIndex ]; + // back to clip space + offset.assign( offset.mul( clipPos.w ) ); - binding._cacheIndex = firstInactiveIndex; - bindings[ firstInactiveIndex ] = binding; + //clipPos.xy += offset; + clipPos.addAssign( vec4( offset, 0, 0 ) ); - lastActiveBinding._cacheIndex = prevIndex; - bindings[ prevIndex ] = lastActiveBinding; + return clipPos; - } + } )(); + this.fragmentNode = Fn( () => { - // Memory management of Interpolants for weight and time scale + const alpha = float( 1 ).toVar(); - _lendControlInterpolant() { + const len2 = lengthSq( uv().mul( 2 ).sub( 1 ) ); - const interpolants = this._controlInterpolants, - lastActiveIndex = this._nActiveControlInterpolants ++; + if ( useAlphaToCoverage && renderer.samples > 1 ) { - let interpolant = interpolants[ lastActiveIndex ]; + const dlen = float( len2.fwidth() ).toVar(); - if ( interpolant === undefined ) { + alpha.assign( smoothstep( dlen.oneMinus(), dlen.add( 1 ), len2 ).oneMinus() ); - interpolant = new LinearInterpolant( - new Float32Array( 2 ), new Float32Array( 2 ), - 1, _controlInterpolantsResultBuffer ); + } else { - interpolant.__cacheIndex = lastActiveIndex; - interpolants[ lastActiveIndex ] = interpolant; + len2.greaterThan( 1.0 ).discard(); - } + } - return interpolant; + let pointColorNode; - } + if ( this.pointColorNode ) { - _takeBackControlInterpolant( interpolant ) { + pointColorNode = this.pointColorNode; - const interpolants = this._controlInterpolants, - prevIndex = interpolant.__cacheIndex, + } else { - firstInactiveIndex = -- this._nActiveControlInterpolants, + if ( useColor ) { - lastActiveInterpolant = interpolants[ firstInactiveIndex ]; + const instanceColor = attribute( 'instanceColor' ); - interpolant.__cacheIndex = firstInactiveIndex; - interpolants[ firstInactiveIndex ] = interpolant; + pointColorNode = instanceColor.mul( materialColor ); - lastActiveInterpolant.__cacheIndex = prevIndex; - interpolants[ prevIndex ] = lastActiveInterpolant; + } else { - } + pointColorNode = materialColor; - // return an action for a clip optionally using a custom root target - // object (this method allocates a lot of dynamic memory in case a - // previously unknown clip/root combination is specified) - clipAction( clip, optionalRoot, blendMode ) { + } - const root = optionalRoot || this._root, - rootUuid = root.uuid; + } - let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip; + alpha.mulAssign( materialOpacity ); - const clipUuid = clipObject !== null ? clipObject.uuid : clip; + return vec4( pointColorNode, alpha ); - const actionsForClip = this._actionsByClip[ clipUuid ]; - let prototypeAction = null; + } )(); - if ( blendMode === undefined ) { + } - if ( clipObject !== null ) { + get alphaToCoverage() { - blendMode = clipObject.blendMode; + return this.useAlphaToCoverage; - } else { + } - blendMode = NormalAnimationBlendMode; + set alphaToCoverage( value ) { - } + if ( this.useAlphaToCoverage !== value ) { + + this.useAlphaToCoverage = value; + this.needsUpdate = true; } - if ( actionsForClip !== undefined ) { + } - const existingAction = actionsForClip.actionByRoot[ rootUuid ]; +} - if ( existingAction !== undefined && existingAction.blendMode === blendMode ) { +const _defaultValues$d = /*@__PURE__*/ new LineBasicMaterial(); - return existingAction; +class LineBasicNodeMaterial extends NodeMaterial { - } + static get type() { - // we know the clip, so we don't have to parse all - // the bindings again but can just copy - prototypeAction = actionsForClip.knownActions[ 0 ]; + return 'LineBasicNodeMaterial'; - // also, take the clip from the prototype action - if ( clipObject === null ) - clipObject = prototypeAction._clip; + } - } + constructor( parameters ) { - // clip must be known when specified via string - if ( clipObject === null ) return null; + super(); - // allocate all resources required to run it - const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode ); + this.isLineBasicNodeMaterial = true; - this._bindAction( newAction, prototypeAction ); + this.lights = false; - // and make the action known to the memory manager - this._addInactiveAction( newAction, clipUuid, rootUuid ); + this.setDefaultValues( _defaultValues$d ); - return newAction; + this.setValues( parameters ); } - // get an existing action - existingAction( clip, optionalRoot ) { - - const root = optionalRoot || this._root, - rootUuid = root.uuid, - - clipObject = typeof clip === 'string' ? - AnimationClip.findByName( root, clip ) : clip, - - clipUuid = clipObject ? clipObject.uuid : clip, - - actionsForClip = this._actionsByClip[ clipUuid ]; +} - if ( actionsForClip !== undefined ) { +const _defaultValues$c = /*@__PURE__*/ new LineDashedMaterial(); - return actionsForClip.actionByRoot[ rootUuid ] || null; +class LineDashedNodeMaterial extends NodeMaterial { - } + static get type() { - return null; + return 'LineDashedNodeMaterial'; } - // deactivates all previously scheduled actions - stopAllAction() { + constructor( parameters ) { - const actions = this._actions, - nActions = this._nActiveActions; + super(); - for ( let i = nActions - 1; i >= 0; -- i ) { + this.isLineDashedNodeMaterial = true; - actions[ i ].stop(); + this.lights = false; - } + this.setDefaultValues( _defaultValues$c ); - return this; + this.offsetNode = null; + this.dashScaleNode = null; + this.dashSizeNode = null; + this.gapSizeNode = null; - } + this.setValues( parameters ); - // advance the time and update apply the animation - update( deltaTime ) { + } - deltaTime *= this.timeScale; + setupVariants() { - const actions = this._actions, - nActions = this._nActiveActions, + const offsetNode = this.offsetNode; + const dashScaleNode = this.dashScaleNode ? float( this.dashScaleNode ) : materialLineScale; + const dashSizeNode = this.dashSizeNode ? float( this.dashSizeNode ) : materialLineDashSize; + const gapSizeNode = this.dashSizeNode ? float( this.dashGapNode ) : materialLineGapSize; - time = this.time += deltaTime, - timeDirection = Math.sign( deltaTime ), + dashSize.assign( dashSizeNode ); + gapSize.assign( gapSizeNode ); - accuIndex = this._accuIndex ^= 1; + const vLineDistance = varying( attribute( 'lineDistance' ).mul( dashScaleNode ) ); + const vLineDistanceOffset = offsetNode ? vLineDistance.add( offsetNode ) : vLineDistance; - // run active actions + vLineDistanceOffset.mod( dashSize.add( gapSize ) ).greaterThan( dashSize ).discard(); - for ( let i = 0; i !== nActions; ++ i ) { + } - const action = actions[ i ]; +} - action._update( time, deltaTime, timeDirection, accuIndex ); +const _defaultValues$b = /*@__PURE__*/ new LineDashedMaterial(); - } +class Line2NodeMaterial extends NodeMaterial { - // update scene graph + static get type() { - const bindings = this._bindings, - nBindings = this._nActiveBindings; + return 'Line2NodeMaterial'; - for ( let i = 0; i !== nBindings; ++ i ) { + } - bindings[ i ].apply( accuIndex ); + constructor( params = {} ) { - } + super(); - return this; + this.lights = false; - } + this.setDefaultValues( _defaultValues$b ); - // Allows you to seek to a specific time in an animation. - setTime( timeInSeconds ) { + this.useAlphaToCoverage = true; + this.useColor = params.vertexColors; + this.useDash = params.dashed; + this.useWorldUnits = false; - this.time = 0; // Zero out time attribute for AnimationMixer object; - for ( let i = 0; i < this._actions.length; i ++ ) { + this.dashOffset = 0; + this.lineWidth = 1; - this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects. + this.lineColorNode = null; - } + this.offsetNode = null; + this.dashScaleNode = null; + this.dashSizeNode = null; + this.gapSizeNode = null; - return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object. + this.setValues( params ); } - // return this mixer's root target object - getRoot() { + setup( builder ) { - return this._root; + this.setupShaders( builder ); + + super.setup( builder ); } - // free all resources specific to a particular clip - uncacheClip( clip ) { + setupShaders( { renderer } ) { - const actions = this._actions, - clipUuid = clip.uuid, - actionsByClip = this._actionsByClip, - actionsForClip = actionsByClip[ clipUuid ]; + const useAlphaToCoverage = this.alphaToCoverage; + const useColor = this.useColor; + const useDash = this.dashed; + const useWorldUnits = this.worldUnits; - if ( actionsForClip !== undefined ) { + const trimSegment = Fn( ( { start, end } ) => { - // note: just calling _removeInactiveAction would mess up the - // iteration state and also require updating the state we can - // just throw away + const a = cameraProjectionMatrix.element( 2 ).element( 2 ); // 3nd entry in 3th column + const b = cameraProjectionMatrix.element( 3 ).element( 2 ); // 3nd entry in 4th column + const nearEstimate = b.mul( - 0.5 ).div( a ); - const actionsToRemove = actionsForClip.knownActions; + const alpha = nearEstimate.sub( start.z ).div( end.z.sub( start.z ) ); - for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) { + return vec4( mix( start.xyz, end.xyz, alpha ), end.w ); - const action = actionsToRemove[ i ]; + } ).setLayout( { + name: 'trimSegment', + type: 'vec4', + inputs: [ + { name: 'start', type: 'vec4' }, + { name: 'end', type: 'vec4' } + ] + } ); - this._deactivateAction( action ); + this.vertexNode = Fn( () => { - const cacheIndex = action._cacheIndex, - lastInactiveAction = actions[ actions.length - 1 ]; + const instanceStart = attribute( 'instanceStart' ); + const instanceEnd = attribute( 'instanceEnd' ); - action._cacheIndex = null; - action._byClipCacheIndex = null; + // camera space - lastInactiveAction._cacheIndex = cacheIndex; - actions[ cacheIndex ] = lastInactiveAction; - actions.pop(); + const start = vec4( modelViewMatrix.mul( vec4( instanceStart, 1.0 ) ) ).toVar( 'start' ); + const end = vec4( modelViewMatrix.mul( vec4( instanceEnd, 1.0 ) ) ).toVar( 'end' ); - this._removeInactiveBindingsForAction( action ); + if ( useWorldUnits ) { + + varyingProperty( 'vec3', 'worldStart' ).assign( start.xyz ); + varyingProperty( 'vec3', 'worldEnd' ).assign( end.xyz ); } - delete actionsByClip[ clipUuid ]; + const aspect = viewport.z.div( viewport.w ); - } + // special case for perspective projection, and segments that terminate either in, or behind, the camera plane + // clearly the gpu firmware has a way of addressing this issue when projecting into ndc space + // but we need to perform ndc-space calculations in the shader, so we must address this issue directly + // perhaps there is a more elegant solution -- WestLangley - } + const perspective = cameraProjectionMatrix.element( 2 ).element( 3 ).equal( - 1.0 ); // 4th entry in the 3rd column - // free all resources specific to a particular root target object - uncacheRoot( root ) { + If( perspective, () => { - const rootUuid = root.uuid, - actionsByClip = this._actionsByClip; + If( start.z.lessThan( 0.0 ).and( end.z.greaterThan( 0.0 ) ), () => { - for ( const clipUuid in actionsByClip ) { + end.assign( trimSegment( { start: start, end: end } ) ); - const actionByRoot = actionsByClip[ clipUuid ].actionByRoot, - action = actionByRoot[ rootUuid ]; + } ).ElseIf( end.z.lessThan( 0.0 ).and( start.z.greaterThanEqual( 0.0 ) ), () => { - if ( action !== undefined ) { + start.assign( trimSegment( { start: end, end: start } ) ); - this._deactivateAction( action ); - this._removeInactiveAction( action ); + } ); - } + } ); - } + // clip space + const clipStart = cameraProjectionMatrix.mul( start ); + const clipEnd = cameraProjectionMatrix.mul( end ); - const bindingsByRoot = this._bindingsByRootAndName, - bindingByName = bindingsByRoot[ rootUuid ]; + // ndc space + const ndcStart = clipStart.xyz.div( clipStart.w ); + const ndcEnd = clipEnd.xyz.div( clipEnd.w ); - if ( bindingByName !== undefined ) { + // direction + const dir = ndcEnd.xy.sub( ndcStart.xy ).toVar(); - for ( const trackName in bindingByName ) { + // account for clip-space aspect ratio + dir.x.assign( dir.x.mul( aspect ) ); + dir.assign( dir.normalize() ); - const binding = bindingByName[ trackName ]; - binding.restoreOriginalState(); - this._removeInactiveBinding( binding ); + const clip = vec4().toVar(); - } + if ( useWorldUnits ) { - } + // get the offset direction as perpendicular to the view vector - } + const worldDir = end.xyz.sub( start.xyz ).normalize(); + const tmpFwd = mix( start.xyz, end.xyz, 0.5 ).normalize(); + const worldUp = worldDir.cross( tmpFwd ).normalize(); + const worldFwd = worldDir.cross( worldUp ); - // remove a targeted clip from the cache - uncacheAction( clip, optionalRoot ) { + const worldPos = varyingProperty( 'vec4', 'worldPos' ); - const action = this.existingAction( clip, optionalRoot ); + worldPos.assign( positionGeometry.y.lessThan( 0.5 ).select( start, end ) ); - if ( action !== null ) { + // height offset + const hw = materialLineWidth.mul( 0.5 ); + worldPos.addAssign( vec4( positionGeometry.x.lessThan( 0.0 ).select( worldUp.mul( hw ), worldUp.mul( hw ).negate() ), 0 ) ); - this._deactivateAction( action ); - this._removeInactiveAction( action ); + // don't extend the line if we're rendering dashes because we + // won't be rendering the endcaps + if ( ! useDash ) { - } + // cap extension + worldPos.addAssign( vec4( positionGeometry.y.lessThan( 0.5 ).select( worldDir.mul( hw ).negate(), worldDir.mul( hw ) ), 0 ) ); - } + // add width to the box + worldPos.addAssign( vec4( worldFwd.mul( hw ), 0 ) ); -} + // endcaps + If( positionGeometry.y.greaterThan( 1.0 ).or( positionGeometry.y.lessThan( 0.0 ) ), () => { -let Uniform$1 = class Uniform { + worldPos.subAssign( vec4( worldFwd.mul( 2.0 ).mul( hw ), 0 ) ); - constructor( value ) { + } ); - this.value = value; + } - } + // project the worldpos + clip.assign( cameraProjectionMatrix.mul( worldPos ) ); - clone() { + // shift the depth of the projected points so the line + // segments overlap neatly + const clipPose = vec3().toVar(); - return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() ); + clipPose.assign( positionGeometry.y.lessThan( 0.5 ).select( ndcStart, ndcEnd ) ); + clip.z.assign( clipPose.z.mul( clip.w ) ); - } + } else { -}; + const offset = vec2( dir.y, dir.x.negate() ).toVar( 'offset' ); -let _id$8 = 0; + // undo aspect ratio adjustment + dir.x.assign( dir.x.div( aspect ) ); + offset.x.assign( offset.x.div( aspect ) ); -let UniformsGroup$1 = class UniformsGroup extends EventDispatcher { + // sign flip + offset.assign( positionGeometry.x.lessThan( 0.0 ).select( offset.negate(), offset ) ); - constructor() { + // endcaps + If( positionGeometry.y.lessThan( 0.0 ), () => { - super(); + offset.assign( offset.sub( dir ) ); - this.isUniformsGroup = true; + } ).ElseIf( positionGeometry.y.greaterThan( 1.0 ), () => { - Object.defineProperty( this, 'id', { value: _id$8 ++ } ); + offset.assign( offset.add( dir ) ); - this.name = ''; + } ); - this.usage = StaticDrawUsage; - this.uniforms = []; + // adjust for linewidth + offset.assign( offset.mul( materialLineWidth ) ); - } + // adjust for clip-space to screen-space conversion // maybe resolution should be based on viewport ... + offset.assign( offset.div( viewport.w ) ); - add( uniform ) { + // select end + clip.assign( positionGeometry.y.lessThan( 0.5 ).select( clipStart, clipEnd ) ); - this.uniforms.push( uniform ); + // back to clip space + offset.assign( offset.mul( clip.w ) ); - return this; + clip.assign( clip.add( vec4( offset, 0, 0 ) ) ); - } + } - remove( uniform ) { + return clip; - const index = this.uniforms.indexOf( uniform ); + } )(); - if ( index !== - 1 ) this.uniforms.splice( index, 1 ); + const closestLineToLine = Fn( ( { p1, p2, p3, p4 } ) => { - return this; + const p13 = p1.sub( p3 ); + const p43 = p4.sub( p3 ); - } + const p21 = p2.sub( p1 ); - setName( name ) { + const d1343 = p13.dot( p43 ); + const d4321 = p43.dot( p21 ); + const d1321 = p13.dot( p21 ); + const d4343 = p43.dot( p43 ); + const d2121 = p21.dot( p21 ); - this.name = name; + const denom = d2121.mul( d4343 ).sub( d4321.mul( d4321 ) ); + const numer = d1343.mul( d4321 ).sub( d1321.mul( d4343 ) ); - return this; + const mua = numer.div( denom ).clamp(); + const mub = d1343.add( d4321.mul( mua ) ).div( d4343 ).clamp(); - } + return vec2( mua, mub ); - setUsage( value ) { + } ); - this.usage = value; + this.fragmentNode = Fn( () => { - return this; + const vUv = uv(); - } + if ( useDash ) { - dispose() { + const offsetNode = this.offsetNode ? float( this.offsetNodeNode ) : materialLineDashOffset; + const dashScaleNode = this.dashScaleNode ? float( this.dashScaleNode ) : materialLineScale; + const dashSizeNode = this.dashSizeNode ? float( this.dashSizeNode ) : materialLineDashSize; + const gapSizeNode = this.dashSizeNode ? float( this.dashGapNode ) : materialLineGapSize; - this.dispatchEvent( { type: 'dispose' } ); + dashSize.assign( dashSizeNode ); + gapSize.assign( gapSizeNode ); - return this; + const instanceDistanceStart = attribute( 'instanceDistanceStart' ); + const instanceDistanceEnd = attribute( 'instanceDistanceEnd' ); - } + const lineDistance = positionGeometry.y.lessThan( 0.5 ).select( dashScaleNode.mul( instanceDistanceStart ), materialLineScale.mul( instanceDistanceEnd ) ); - copy( source ) { + const vLineDistance = varying( lineDistance.add( materialLineDashOffset ) ); + const vLineDistanceOffset = offsetNode ? vLineDistance.add( offsetNode ) : vLineDistance; - this.name = source.name; - this.usage = source.usage; + vUv.y.lessThan( - 1.0 ).or( vUv.y.greaterThan( 1.0 ) ).discard(); // discard endcaps + vLineDistanceOffset.mod( dashSize.add( gapSize ) ).greaterThan( dashSize ).discard(); // todo - FIX - const uniformsSource = source.uniforms; + } - this.uniforms.length = 0; + const alpha = float( 1 ).toVar( 'alpha' ); - for ( let i = 0, l = uniformsSource.length; i < l; i ++ ) { + if ( useWorldUnits ) { - const uniforms = Array.isArray( uniformsSource[ i ] ) ? uniformsSource[ i ] : [ uniformsSource[ i ] ]; + const worldStart = varyingProperty( 'vec3', 'worldStart' ); + const worldEnd = varyingProperty( 'vec3', 'worldEnd' ); - for ( let j = 0; j < uniforms.length; j ++ ) { + // Find the closest points on the view ray and the line segment + const rayEnd = varyingProperty( 'vec4', 'worldPos' ).xyz.normalize().mul( 1e5 ); + const lineDir = worldEnd.sub( worldStart ); + const params = closestLineToLine( { p1: worldStart, p2: worldEnd, p3: vec3( 0.0, 0.0, 0.0 ), p4: rayEnd } ); - this.uniforms.push( uniforms[ j ].clone() ); + const p1 = worldStart.add( lineDir.mul( params.x ) ); + const p2 = rayEnd.mul( params.y ); + const delta = p1.sub( p2 ); + const len = delta.length(); + const norm = len.div( materialLineWidth ); - } + if ( ! useDash ) { - } + if ( useAlphaToCoverage && renderer.samples > 1 ) { - return this; + const dnorm = norm.fwidth(); + alpha.assign( smoothstep( dnorm.negate().add( 0.5 ), dnorm.add( 0.5 ), norm ).oneMinus() ); - } + } else { - clone() { + norm.greaterThan( 0.5 ).discard(); - return new this.constructor().copy( this ); + } - } + } -}; + } else { -class GLBufferAttribute { + // round endcaps - constructor( buffer, type, itemSize, elementSize, count ) { + if ( useAlphaToCoverage && renderer.samples > 1 ) { - this.isGLBufferAttribute = true; + const a = vUv.x; + const b = vUv.y.greaterThan( 0.0 ).select( vUv.y.sub( 1.0 ), vUv.y.add( 1.0 ) ); - this.name = ''; + const len2 = a.mul( a ).add( b.mul( b ) ); - this.buffer = buffer; - this.type = type; - this.itemSize = itemSize; - this.elementSize = elementSize; - this.count = count; + const dlen = float( len2.fwidth() ).toVar( 'dlen' ); - this.version = 0; + If( vUv.y.abs().greaterThan( 1.0 ), () => { - } + alpha.assign( smoothstep( dlen.oneMinus(), dlen.add( 1 ), len2 ).oneMinus() ); - set needsUpdate( value ) { + } ); - if ( value === true ) this.version ++; + } else { - } + If( vUv.y.abs().greaterThan( 1.0 ), () => { - setBuffer( buffer ) { + const a = vUv.x; + const b = vUv.y.greaterThan( 0.0 ).select( vUv.y.sub( 1.0 ), vUv.y.add( 1.0 ) ); + const len2 = a.mul( a ).add( b.mul( b ) ); - this.buffer = buffer; + len2.greaterThan( 1.0 ).discard(); - return this; + } ); - } + } - setType( type, elementSize ) { + } - this.type = type; - this.elementSize = elementSize; + let lineColorNode; - return this; + if ( this.lineColorNode ) { - } + lineColorNode = this.lineColorNode; - setItemSize( itemSize ) { + } else { - this.itemSize = itemSize; + if ( useColor ) { - return this; + const instanceColorStart = attribute( 'instanceColorStart' ); + const instanceColorEnd = attribute( 'instanceColorEnd' ); - } + const instanceColor = positionGeometry.y.lessThan( 0.5 ).select( instanceColorStart, instanceColorEnd ); - setCount( count ) { + lineColorNode = instanceColor.mul( materialColor ); - this.count = count; + } else { - return this; + lineColorNode = materialColor; - } + } -} + } -const _matrix = /*@__PURE__*/ new Matrix4(); + return vec4( lineColorNode, alpha ); -class Raycaster { + } )(); - constructor( origin, direction, near = 0, far = Infinity ) { + } - this.ray = new Ray( origin, direction ); - // direction is assumed to be normalized (for accurate distance calculations) - this.near = near; - this.far = far; - this.camera = null; - this.layers = new Layers(); + get worldUnits() { - this.params = { - Mesh: {}, - Line: { threshold: 1 }, - LOD: {}, - Points: { threshold: 1 }, - Sprite: {} - }; + return this.useWorldUnits; } - set( origin, direction ) { + set worldUnits( value ) { - // direction is assumed to be normalized (for accurate distance calculations) + if ( this.useWorldUnits !== value ) { - this.ray.set( origin, direction ); + this.useWorldUnits = value; + this.needsUpdate = true; + + } } - setFromCamera( coords, camera ) { - if ( camera.isPerspectiveCamera ) { + get dashed() { - this.ray.origin.setFromMatrixPosition( camera.matrixWorld ); - this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize(); - this.camera = camera; + return this.useDash; - } else if ( camera.isOrthographicCamera ) { + } - this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera - this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); - this.camera = camera; + set dashed( value ) { - } else { + if ( this.useDash !== value ) { - console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type ); + this.useDash = value; + this.needsUpdate = true; } } - setFromXRController( controller ) { - - _matrix.identity().extractRotation( controller.matrixWorld ); - this.ray.origin.setFromMatrixPosition( controller.matrixWorld ); - this.ray.direction.set( 0, 0, - 1 ).applyMatrix4( _matrix ); + get alphaToCoverage() { - return this; + return this.useAlphaToCoverage; } - intersectObject( object, recursive = true, intersects = [] ) { + set alphaToCoverage( value ) { - intersect( object, this, intersects, recursive ); + if ( this.useAlphaToCoverage !== value ) { - intersects.sort( ascSort ); + this.useAlphaToCoverage = value; + this.needsUpdate = true; - return intersects; + } } - intersectObjects( objects, recursive = true, intersects = [] ) { +} - for ( let i = 0, l = objects.length; i < l; i ++ ) { +const directionToColor = ( node ) => nodeObject( node ).mul( 0.5 ).add( 0.5 ); +const colorToDirection = ( node ) => nodeObject( node ).mul( 2.0 ).sub( 1 ); - intersect( objects[ i ], this, intersects, recursive ); +const _defaultValues$a = /*@__PURE__*/ new MeshNormalMaterial(); - } +class MeshNormalNodeMaterial extends NodeMaterial { - intersects.sort( ascSort ); + static get type() { - return intersects; + return 'MeshNormalNodeMaterial'; } -} - -function ascSort( a, b ) { - - return a.distance - b.distance; - -} + constructor( parameters ) { -function intersect( object, raycaster, intersects, recursive ) { + super(); - let propagate = true; + this.lights = false; - if ( object.layers.test( raycaster.layers ) ) { + this.isMeshNormalNodeMaterial = true; - const result = object.raycast( raycaster, intersects ); + this.setDefaultValues( _defaultValues$a ); - if ( result === false ) propagate = false; + this.setValues( parameters ); } - if ( propagate === true && recursive === true ) { - - const children = object.children; - - for ( let i = 0, l = children.length; i < l; i ++ ) { + setupDiffuseColor() { - intersect( children[ i ], raycaster, intersects, true ); + const opacityNode = this.opacityNode ? float( this.opacityNode ) : materialOpacity; - } + diffuseColor.assign( vec4( directionToColor( transformedNormalView ), opacityNode ) ); } } -/** - * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system - * - * phi (the polar angle) is measured from the positive y-axis. The positive y-axis is up. - * theta (the azimuthal angle) is measured from the positive z-axis. - */ -class Spherical { - - constructor( radius = 1, phi = 0, theta = 0 ) { +class EquirectUVNode extends TempNode { - this.radius = radius; - this.phi = phi; // polar angle - this.theta = theta; // azimuthal angle + static get type() { - return this; + return 'EquirectUVNode'; } - set( radius, phi, theta ) { + constructor( dirNode = positionWorldDirection ) { - this.radius = radius; - this.phi = phi; - this.theta = theta; + super( 'vec2' ); - return this; + this.dirNode = dirNode; } - copy( other ) { + setup() { - this.radius = other.radius; - this.phi = other.phi; - this.theta = other.theta; + const dir = this.dirNode; - return this; + const u = dir.z.atan2( dir.x ).mul( 1 / ( Math.PI * 2 ) ).add( 0.5 ); + const v = dir.y.clamp( - 1.0, 1.0 ).asin().mul( 1 / Math.PI ).add( 0.5 ); + + return vec2( u, v ); } - // restrict phi to be between EPS and PI-EPS - makeSafe() { +} - const EPS = 0.000001; - this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) ); +const equirectUV = /*@__PURE__*/ nodeProxy( EquirectUVNode ); - return this; +// @TODO: Consider rename WebGLCubeRenderTarget to just CubeRenderTarget - } +class CubeRenderTarget extends WebGLCubeRenderTarget { - setFromVector3( v ) { + constructor( size = 1, options = {} ) { - return this.setFromCartesianCoords( v.x, v.y, v.z ); + super( size, options ); + + this.isCubeRenderTarget = true; } - setFromCartesianCoords( x, y, z ) { + fromEquirectangularTexture( renderer, texture$1 ) { - this.radius = Math.sqrt( x * x + y * y + z * z ); + const currentMinFilter = texture$1.minFilter; + const currentGenerateMipmaps = texture$1.generateMipmaps; - if ( this.radius === 0 ) { + texture$1.generateMipmaps = true; - this.theta = 0; - this.phi = 0; + this.texture.type = texture$1.type; + this.texture.colorSpace = texture$1.colorSpace; - } else { + this.texture.generateMipmaps = texture$1.generateMipmaps; + this.texture.minFilter = texture$1.minFilter; + this.texture.magFilter = texture$1.magFilter; - this.theta = Math.atan2( x, z ); - this.phi = Math.acos( clamp$1( y / this.radius, - 1, 1 ) ); + const geometry = new BoxGeometry( 5, 5, 5 ); - } + const uvNode = equirectUV( positionWorldDirection ); - return this; + const material = new NodeMaterial(); + material.colorNode = texture( texture$1, uvNode, 0 ); + material.side = BackSide; + material.blending = NoBlending; - } + const mesh = new Mesh( geometry, material ); - clone() { + const scene = new Scene(); + scene.add( mesh ); - return new this.constructor().copy( this ); + // Avoid blurred poles + if ( texture$1.minFilter === LinearMipmapLinearFilter ) texture$1.minFilter = LinearFilter; - } + const camera = new CubeCamera( 1, 10, this ); -} + const currentMRT = renderer.getMRT(); + renderer.setMRT( null ); -/** - * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system - */ + camera.update( renderer, scene ); -class Cylindrical { + renderer.setMRT( currentMRT ); - constructor( radius = 1, theta = 0, y = 0 ) { + texture$1.minFilter = currentMinFilter; + texture$1.currentGenerateMipmaps = currentGenerateMipmaps; - this.radius = radius; // distance from the origin to a point in the x-z plane - this.theta = theta; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis - this.y = y; // height above the x-z plane + mesh.geometry.dispose(); + mesh.material.dispose(); return this; } - set( radius, theta, y ) { - - this.radius = radius; - this.theta = theta; - this.y = y; - - return this; +} - } +const _cache$1 = new WeakMap(); - copy( other ) { +class CubeMapNode extends TempNode { - this.radius = other.radius; - this.theta = other.theta; - this.y = other.y; + static get type() { - return this; + return 'CubeMapNode'; } - setFromVector3( v ) { + constructor( envNode ) { - return this.setFromCartesianCoords( v.x, v.y, v.z ); + super( 'vec3' ); - } + this.envNode = envNode; - setFromCartesianCoords( x, y, z ) { + this._cubeTexture = null; + this._cubeTextureNode = cubeTexture(); - this.radius = Math.sqrt( x * x + z * z ); - this.theta = Math.atan2( x, z ); - this.y = y; + const defaultTexture = new CubeTexture(); + defaultTexture.isRenderTargetTexture = true; - return this; + this._defaultTexture = defaultTexture; + + this.updateBeforeType = NodeUpdateType.RENDER; } - clone() { + updateBefore( frame ) { - return new this.constructor().copy( this ); + const { renderer, material } = frame; - } + const envNode = this.envNode; -} + if ( envNode.isTextureNode || envNode.isMaterialReferenceNode ) { -class Matrix2 { + const texture = ( envNode.isTextureNode ) ? envNode.value : material[ envNode.property ]; - constructor( n11, n12, n21, n22 ) { + if ( texture && texture.isTexture ) { - Matrix2.prototype.isMatrix2 = true; + const mapping = texture.mapping; - this.elements = [ - 1, 0, - 0, 1, - ]; + if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) { - if ( n11 !== undefined ) { + // check for converted cubemap map - this.set( n11, n12, n21, n22 ); + if ( _cache$1.has( texture ) ) { - } + const cubeMap = _cache$1.get( texture ); - } + mapTextureMapping( cubeMap, texture.mapping ); + this._cubeTexture = cubeMap; - identity() { + } else { - this.set( - 1, 0, - 0, 1, - ); + // create cube map from equirectangular map - return this; + const image = texture.image; - } + if ( isEquirectangularMapReady$1( image ) ) { - fromArray( array, offset = 0 ) { + const renderTarget = new CubeRenderTarget( image.height ); + renderTarget.fromEquirectangularTexture( renderer, texture ); - for ( let i = 0; i < 4; i ++ ) { + mapTextureMapping( renderTarget.texture, texture.mapping ); + this._cubeTexture = renderTarget.texture; - this.elements[ i ] = array[ i + offset ]; + _cache$1.set( texture, renderTarget.texture ); - } + texture.addEventListener( 'dispose', onTextureDispose ); - return this; + } else { - } + // default cube texture as fallback when equirectangular texture is not yet loaded - set( n11, n12, n21, n22 ) { + this._cubeTexture = this._defaultTexture; - const te = this.elements; + } - te[ 0 ] = n11; te[ 2 ] = n12; - te[ 1 ] = n21; te[ 3 ] = n22; + } - return this; + // - } + this._cubeTextureNode.value = this._cubeTexture; -} + } else { -const _vector$4 = /*@__PURE__*/ new Vector2(); + // envNode already refers to a cube map -class Box2 { + this._cubeTextureNode = this.envNode; - constructor( min = new Vector2( + Infinity, + Infinity ), max = new Vector2( - Infinity, - Infinity ) ) { + } - this.isBox2 = true; + } - this.min = min; - this.max = max; + } } - set( min, max ) { + setup( builder ) { - this.min.copy( min ); - this.max.copy( max ); + this.updateBefore( builder ); - return this; + return this._cubeTextureNode; } - setFromPoints( points ) { - - this.makeEmpty(); +} - for ( let i = 0, il = points.length; i < il; i ++ ) { +function isEquirectangularMapReady$1( image ) { - this.expandByPoint( points[ i ] ); + if ( image === null || image === undefined ) return false; - } + return image.height > 0; - return this; +} - } +function onTextureDispose( event ) { - setFromCenterAndSize( center, size ) { + const texture = event.target; - const halfSize = _vector$4.copy( size ).multiplyScalar( 0.5 ); - this.min.copy( center ).sub( halfSize ); - this.max.copy( center ).add( halfSize ); + texture.removeEventListener( 'dispose', onTextureDispose ); - return this; + const renderTarget = _cache$1.get( texture ); - } + if ( renderTarget !== undefined ) { - clone() { + _cache$1.delete( texture ); - return new this.constructor().copy( this ); + renderTarget.dispose(); } - copy( box ) { - - this.min.copy( box.min ); - this.max.copy( box.max ); +} - return this; +function mapTextureMapping( texture, mapping ) { - } + if ( mapping === EquirectangularReflectionMapping ) { - makeEmpty() { + texture.mapping = CubeReflectionMapping; - this.min.x = this.min.y = + Infinity; - this.max.x = this.max.y = - Infinity; + } else if ( mapping === EquirectangularRefractionMapping ) { - return this; + texture.mapping = CubeRefractionMapping; } - isEmpty() { - - // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes +} - return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ); +const cubeMapNode = /*@__PURE__*/ nodeProxy( CubeMapNode ); - } +class BasicEnvironmentNode extends LightingNode { - getCenter( target ) { + static get type() { - return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); + return 'BasicEnvironmentNode'; } - getSize( target ) { + constructor( envNode = null ) { - return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min ); + super(); + + this.envNode = envNode; } - expandByPoint( point ) { + setup( builder ) { - this.min.min( point ); - this.max.max( point ); + // environment property is used in the finish() method of BasicLightingModel - return this; + builder.context.environment = cubeMapNode( this.envNode ); } - expandByVector( vector ) { +} - this.min.sub( vector ); - this.max.add( vector ); +class BasicLightMapNode extends LightingNode { - return this; + static get type() { + + return 'BasicLightMapNode'; } - expandByScalar( scalar ) { + constructor( lightMapNode = null ) { - this.min.addScalar( - scalar ); - this.max.addScalar( scalar ); + super(); - return this; + this.lightMapNode = lightMapNode; } - containsPoint( point ) { + setup( builder ) { - return point.x >= this.min.x && point.x <= this.max.x && - point.y >= this.min.y && point.y <= this.max.y; + // irradianceLightMap property is used in the indirectDiffuse() method of BasicLightingModel + + const RECIPROCAL_PI = float( 1 / Math.PI ); + + builder.context.irradianceLightMap = this.lightMapNode.mul( RECIPROCAL_PI ); } - containsBox( box ) { +} - return this.min.x <= box.min.x && box.max.x <= this.max.x && - this.min.y <= box.min.y && box.max.y <= this.max.y; +class LightingModel { - } + start( /*input, stack, builder*/ ) { } - getParameter( point, target ) { + finish( /*input, stack, builder*/ ) { } - // This can potentially have a divide by zero if the box - // has a size dimension of 0. + direct( /*input, stack, builder*/ ) { } - return target.set( - ( point.x - this.min.x ) / ( this.max.x - this.min.x ), - ( point.y - this.min.y ) / ( this.max.y - this.min.y ) - ); + directRectArea( /*input, stack, builder*/ ) {} - } + indirect( /*input, stack, builder*/ ) { } - intersectsBox( box ) { + ambientOcclusion( /*input, stack, builder*/ ) { } - // using 4 splitting planes to rule out intersections +} - return box.max.x >= this.min.x && box.min.x <= this.max.x && - box.max.y >= this.min.y && box.min.y <= this.max.y; +class BasicLightingModel extends LightingModel { + + constructor() { + + super(); } - clampPoint( point, target ) { + indirect( context, stack, builder ) { - return target.copy( point ).clamp( this.min, this.max ); + const ambientOcclusion = context.ambientOcclusion; + const reflectedLight = context.reflectedLight; + const irradianceLightMap = builder.context.irradianceLightMap; - } + reflectedLight.indirectDiffuse.assign( vec4( 0.0 ) ); - distanceToPoint( point ) { + // accumulation (baked indirect lighting only) - return this.clampPoint( point, _vector$4 ).distanceTo( point ); + if ( irradianceLightMap ) { - } + reflectedLight.indirectDiffuse.addAssign( irradianceLightMap ); - intersect( box ) { + } else { - this.min.max( box.min ); - this.max.min( box.max ); + reflectedLight.indirectDiffuse.addAssign( vec4( 1.0, 1.0, 1.0, 0.0 ) ); - if ( this.isEmpty() ) this.makeEmpty(); + } - return this; + // modulation + + reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion ); + + reflectedLight.indirectDiffuse.mulAssign( diffuseColor.rgb ); } - union( box ) { + finish( context, stack, builder ) { - this.min.min( box.min ); - this.max.max( box.max ); + const material = builder.material; + const outgoingLight = context.outgoingLight; + const envNode = builder.context.environment; - return this; + if ( envNode ) { - } + switch ( material.combine ) { - translate( offset ) { + case MultiplyOperation: + outgoingLight.rgb.assign( mix( outgoingLight.rgb, outgoingLight.rgb.mul( envNode.rgb ), materialSpecularStrength.mul( materialReflectivity ) ) ); + break; - this.min.add( offset ); - this.max.add( offset ); + case MixOperation: + outgoingLight.rgb.assign( mix( outgoingLight.rgb, envNode.rgb, materialSpecularStrength.mul( materialReflectivity ) ) ); + break; - return this; + case AddOperation: + outgoingLight.rgb.addAssign( envNode.rgb.mul( materialSpecularStrength.mul( materialReflectivity ) ) ); + break; - } + default: + console.warn( 'THREE.BasicLightingModel: Unsupported .combine value:', material.combine ); + break; - equals( box ) { + } - return box.min.equals( this.min ) && box.max.equals( this.max ); + } } } -const _startP = /*@__PURE__*/ new Vector3(); -const _startEnd = /*@__PURE__*/ new Vector3(); +const _defaultValues$9 = /*@__PURE__*/ new MeshBasicMaterial(); -class Line3 { +class MeshBasicNodeMaterial extends NodeMaterial { - constructor( start = new Vector3(), end = new Vector3() ) { + static get type() { - this.start = start; - this.end = end; + return 'MeshBasicNodeMaterial'; } - set( start, end ) { - - this.start.copy( start ); - this.end.copy( end ); + constructor( parameters ) { - return this; + super(); - } + this.isMeshBasicNodeMaterial = true; - copy( line ) { + this.lights = true; - this.start.copy( line.start ); - this.end.copy( line.end ); + this.setDefaultValues( _defaultValues$9 ); - return this; + this.setValues( parameters ); } - getCenter( target ) { + setupNormal() { - return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); + return normalView; // see #28839 } - delta( target ) { + setupEnvironment( builder ) { - return target.subVectors( this.end, this.start ); + const envNode = super.setupEnvironment( builder ); + + return envNode ? new BasicEnvironmentNode( envNode ) : null; } - distanceSq() { + setupLightMap( builder ) { - return this.start.distanceToSquared( this.end ); + let node = null; - } + if ( builder.material.lightMap ) { - distance() { + node = new BasicLightMapNode( materialLightMap ); - return this.start.distanceTo( this.end ); + } + + return node; } - at( t, target ) { + setupOutgoingLight() { - return this.delta( target ).multiplyScalar( t ).add( this.start ); + return diffuseColor.rgb; } - closestPointToPointParameter( point, clampToLine ) { + setupLightingModel() { - _startP.subVectors( point, this.start ); - _startEnd.subVectors( this.end, this.start ); + return new BasicLightingModel(); - const startEnd2 = _startEnd.dot( _startEnd ); - const startEnd_startP = _startEnd.dot( _startP ); + } - let t = startEnd_startP / startEnd2; +} - if ( clampToLine ) { +const F_Schlick = /*@__PURE__*/ Fn( ( { f0, f90, dotVH } ) => { - t = clamp$1( t, 0, 1 ); + // Original approximation by Christophe Schlick '94 + // float fresnel = pow( 1.0 - dotVH, 5.0 ); - } + // Optimized variant (presented by Epic at SIGGRAPH '13) + // https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf + const fresnel = dotVH.mul( - 5.55473 ).sub( 6.98316 ).mul( dotVH ).exp2(); - return t; + return f0.mul( fresnel.oneMinus() ).add( f90.mul( fresnel ) ); - } +} ); // validated - closestPointToPoint( point, clampToLine, target ) { +const BRDF_Lambert = /*@__PURE__*/ Fn( ( inputs ) => { - const t = this.closestPointToPointParameter( point, clampToLine ); + return inputs.diffuseColor.mul( 1 / Math.PI ); // punctual light - return this.delta( target ).multiplyScalar( t ).add( this.start ); +} ); // validated - } +const G_BlinnPhong_Implicit = () => float( 0.25 ); - applyMatrix4( matrix ) { +const D_BlinnPhong = /*@__PURE__*/ Fn( ( { dotNH } ) => { - this.start.applyMatrix4( matrix ); - this.end.applyMatrix4( matrix ); - - return this; - - } - - equals( line ) { + return shininess.mul( float( 0.5 ) ).add( 1.0 ).mul( float( 1 / Math.PI ) ).mul( dotNH.pow( shininess ) ); - return line.start.equals( this.start ) && line.end.equals( this.end ); +} ); - } +const BRDF_BlinnPhong = /*@__PURE__*/ Fn( ( { lightDirection } ) => { - clone() { + const halfDir = lightDirection.add( positionViewDirection ).normalize(); - return new this.constructor().copy( this ); + const dotNH = transformedNormalView.dot( halfDir ).clamp(); + const dotVH = positionViewDirection.dot( halfDir ).clamp(); - } + const F = F_Schlick( { f0: specularColor, f90: 1.0, dotVH } ); + const G = G_BlinnPhong_Implicit(); + const D = D_BlinnPhong( { dotNH } ); -} + return F.mul( G ).mul( D ); -const _vector$3 = /*@__PURE__*/ new Vector3(); +} ); -class SpotLightHelper extends Object3D { +class PhongLightingModel extends BasicLightingModel { - constructor( light, color ) { + constructor( specular = true ) { super(); - this.light = light; - - this.matrixAutoUpdate = false; - - this.color = color; + this.specular = specular; - this.type = 'SpotLightHelper'; + } - const geometry = new BufferGeometry(); + direct( { lightDirection, lightColor, reflectedLight } ) { - const positions = [ - 0, 0, 0, 0, 0, 1, - 0, 0, 0, 1, 0, 1, - 0, 0, 0, - 1, 0, 1, - 0, 0, 0, 0, 1, 1, - 0, 0, 0, 0, - 1, 1 - ]; + const dotNL = transformedNormalView.dot( lightDirection ).clamp(); + const irradiance = dotNL.mul( lightColor ); - for ( let i = 0, j = 1, l = 32; i < l; i ++, j ++ ) { + reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) ); - const p1 = ( i / l ) * Math.PI * 2; - const p2 = ( j / l ) * Math.PI * 2; + if ( this.specular === true ) { - positions.push( - Math.cos( p1 ), Math.sin( p1 ), 1, - Math.cos( p2 ), Math.sin( p2 ), 1 - ); + reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_BlinnPhong( { lightDirection } ) ).mul( materialSpecularStrength ) ); } - geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + } - const material = new LineBasicMaterial( { fog: false, toneMapped: false } ); + indirect( { ambientOcclusion, irradiance, reflectedLight } ) { - this.cone = new LineSegments( geometry, material ); - this.add( this.cone ); + reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) ); - this.update(); + reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion ); } - dispose() { - - this.cone.geometry.dispose(); - this.cone.material.dispose(); - - } +} - update() { +const _defaultValues$8 = /*@__PURE__*/ new MeshLambertMaterial(); - this.light.updateWorldMatrix( true, false ); - this.light.target.updateWorldMatrix( true, false ); +class MeshLambertNodeMaterial extends NodeMaterial { - // update the local matrix based on the parent and light target transforms - if ( this.parent ) { + static get type() { - this.parent.updateWorldMatrix( true ); + return 'MeshLambertNodeMaterial'; - this.matrix - .copy( this.parent.matrixWorld ) - .invert() - .multiply( this.light.matrixWorld ); + } - } else { + constructor( parameters ) { - this.matrix.copy( this.light.matrixWorld ); + super(); - } + this.isMeshLambertNodeMaterial = true; - this.matrixWorld.copy( this.light.matrixWorld ); + this.lights = true; - const coneLength = this.light.distance ? this.light.distance : 1000; - const coneWidth = coneLength * Math.tan( this.light.angle ); + this.setDefaultValues( _defaultValues$8 ); - this.cone.scale.set( coneWidth, coneWidth, coneLength ); + this.setValues( parameters ); - _vector$3.setFromMatrixPosition( this.light.target.matrixWorld ); + } - this.cone.lookAt( _vector$3 ); + setupEnvironment( builder ) { - if ( this.color !== undefined ) { + const envNode = super.setupEnvironment( builder ); - this.cone.material.color.set( this.color ); + return envNode ? new BasicEnvironmentNode( envNode ) : null; - } else { + } - this.cone.material.color.copy( this.light.color ); + setupLightingModel( /*builder*/ ) { - } + return new PhongLightingModel( false ); // ( specular ) -> force lambert } } -const _vector$2 = /*@__PURE__*/ new Vector3(); -const _boneMatrix = /*@__PURE__*/ new Matrix4(); -const _matrixWorldInv = /*@__PURE__*/ new Matrix4(); - - -class SkeletonHelper extends LineSegments { - - constructor( object ) { - - const bones = getBoneList( object ); - - const geometry = new BufferGeometry(); - - const vertices = []; - const colors = []; - - const color1 = new Color( 0, 0, 1 ); - const color2 = new Color( 0, 1, 0 ); - - for ( let i = 0; i < bones.length; i ++ ) { - - const bone = bones[ i ]; +const _defaultValues$7 = /*@__PURE__*/ new MeshPhongMaterial(); - if ( bone.parent && bone.parent.isBone ) { +class MeshPhongNodeMaterial extends NodeMaterial { - vertices.push( 0, 0, 0 ); - vertices.push( 0, 0, 0 ); - colors.push( color1.r, color1.g, color1.b ); - colors.push( color2.r, color2.g, color2.b ); + static get type() { - } + return 'MeshPhongNodeMaterial'; - } + } - geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + constructor( parameters ) { - const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } ); + super(); - super( geometry, material ); + this.isMeshPhongNodeMaterial = true; - this.isSkeletonHelper = true; + this.lights = true; - this.type = 'SkeletonHelper'; + this.shininessNode = null; + this.specularNode = null; - this.root = object; - this.bones = bones; + this.setDefaultValues( _defaultValues$7 ); - this.matrix = object.matrixWorld; - this.matrixAutoUpdate = false; + this.setValues( parameters ); } - updateMatrixWorld( force ) { + setupEnvironment( builder ) { - const bones = this.bones; + const envNode = super.setupEnvironment( builder ); - const geometry = this.geometry; - const position = geometry.getAttribute( 'position' ); + return envNode ? new BasicEnvironmentNode( envNode ) : null; - _matrixWorldInv.copy( this.root.matrixWorld ).invert(); + } - for ( let i = 0, j = 0; i < bones.length; i ++ ) { + setupLightingModel( /*builder*/ ) { - const bone = bones[ i ]; + return new PhongLightingModel(); - if ( bone.parent && bone.parent.isBone ) { + } - _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld ); - _vector$2.setFromMatrixPosition( _boneMatrix ); - position.setXYZ( j, _vector$2.x, _vector$2.y, _vector$2.z ); + setupVariants() { - _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld ); - _vector$2.setFromMatrixPosition( _boneMatrix ); - position.setXYZ( j + 1, _vector$2.x, _vector$2.y, _vector$2.z ); + // SHININESS - j += 2; + const shininessNode = ( this.shininessNode ? float( this.shininessNode ) : materialShininess ).max( 1e-4 ); // to prevent pow( 0.0, 0.0 ) - } + shininess.assign( shininessNode ); - } + // SPECULAR COLOR - geometry.getAttribute( 'position' ).needsUpdate = true; + const specularNode = this.specularNode || materialSpecular; - super.updateMatrixWorld( force ); + specularColor.assign( specularNode ); } - dispose() { + copy( source ) { - this.geometry.dispose(); - this.material.dispose(); + this.shininessNode = source.shininessNode; + this.specularNode = source.specularNode; + + return super.copy( source ); } } +const getGeometryRoughness = /*@__PURE__*/ Fn( () => { -function getBoneList( object ) { - - const boneList = []; + const dxy = normalView.dFdx().abs().max( normalView.dFdy().abs() ); + const geometryRoughness = dxy.x.max( dxy.y ).max( dxy.z ); - if ( object.isBone === true ) { + return geometryRoughness; - boneList.push( object ); +} ); - } +const getRoughness = /*@__PURE__*/ Fn( ( inputs ) => { - for ( let i = 0; i < object.children.length; i ++ ) { + const { roughness } = inputs; - boneList.push.apply( boneList, getBoneList( object.children[ i ] ) ); + const geometryRoughness = getGeometryRoughness(); - } + let roughnessFactor = roughness.max( 0.0525 ); // 0.0525 corresponds to the base mip of a 256 cubemap. + roughnessFactor = roughnessFactor.add( geometryRoughness ); + roughnessFactor = roughnessFactor.min( 1.0 ); - return boneList; + return roughnessFactor; -} +} ); -class PointLightHelper extends Mesh { +// Moving Frostbite to Physically Based Rendering 3.0 - page 12, listing 2 +// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf +const V_GGX_SmithCorrelated = /*@__PURE__*/ Fn( ( { alpha, dotNL, dotNV } ) => { - constructor( light, sphereSize, color ) { + const a2 = alpha.pow2(); - const geometry = new SphereGeometry( sphereSize, 4, 2 ); - const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } ); + const gv = dotNL.mul( a2.add( a2.oneMinus().mul( dotNV.pow2() ) ).sqrt() ); + const gl = dotNV.mul( a2.add( a2.oneMinus().mul( dotNL.pow2() ) ).sqrt() ); - super( geometry, material ); + return div( 0.5, gv.add( gl ).max( EPSILON ) ); - this.light = light; +} ).setLayout( { + name: 'V_GGX_SmithCorrelated', + type: 'float', + inputs: [ + { name: 'alpha', type: 'float' }, + { name: 'dotNL', type: 'float' }, + { name: 'dotNV', type: 'float' } + ] +} ); // validated - this.color = color; +// https://google.github.io/filament/Filament.md.html#materialsystem/anisotropicmodel/anisotropicspecularbrdf - this.type = 'PointLightHelper'; +const V_GGX_SmithCorrelated_Anisotropic = /*@__PURE__*/ Fn( ( { alphaT, alphaB, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL } ) => { - this.matrix = this.light.matrixWorld; - this.matrixAutoUpdate = false; + const gv = dotNL.mul( vec3( alphaT.mul( dotTV ), alphaB.mul( dotBV ), dotNV ).length() ); + const gl = dotNV.mul( vec3( alphaT.mul( dotTL ), alphaB.mul( dotBL ), dotNL ).length() ); + const v = div( 0.5, gv.add( gl ) ); - this.update(); + return v.saturate(); +} ).setLayout( { + name: 'V_GGX_SmithCorrelated_Anisotropic', + type: 'float', + inputs: [ + { name: 'alphaT', type: 'float', qualifier: 'in' }, + { name: 'alphaB', type: 'float', qualifier: 'in' }, + { name: 'dotTV', type: 'float', qualifier: 'in' }, + { name: 'dotBV', type: 'float', qualifier: 'in' }, + { name: 'dotTL', type: 'float', qualifier: 'in' }, + { name: 'dotBL', type: 'float', qualifier: 'in' }, + { name: 'dotNV', type: 'float', qualifier: 'in' }, + { name: 'dotNL', type: 'float', qualifier: 'in' } + ] +} ); - /* - // TODO: delete this comment? - const distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 ); - const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } ); +// Microfacet Models for Refraction through Rough Surfaces - equation (33) +// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html +// alpha is "roughness squared" in Disney’s reparameterization +const D_GGX = /*@__PURE__*/ Fn( ( { alpha, dotNH } ) => { - this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial ); - this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial ); + const a2 = alpha.pow2(); - const d = light.distance; + const denom = dotNH.pow2().mul( a2.oneMinus() ).oneMinus(); // avoid alpha = 0 with dotNH = 1 - if ( d === 0.0 ) { + return a2.div( denom.pow2() ).mul( 1 / Math.PI ); - this.lightDistance.visible = false; +} ).setLayout( { + name: 'D_GGX', + type: 'float', + inputs: [ + { name: 'alpha', type: 'float' }, + { name: 'dotNH', type: 'float' } + ] +} ); // validated - } else { +const RECIPROCAL_PI = /*@__PURE__*/ float( 1 / Math.PI ); - this.lightDistance.scale.set( d, d, d ); +// https://google.github.io/filament/Filament.md.html#materialsystem/anisotropicmodel/anisotropicspecularbrdf - } +const D_GGX_Anisotropic = /*@__PURE__*/ Fn( ( { alphaT, alphaB, dotNH, dotTH, dotBH } ) => { - this.add( this.lightDistance ); - */ + const a2 = alphaT.mul( alphaB ); + const v = vec3( alphaB.mul( dotTH ), alphaT.mul( dotBH ), a2.mul( dotNH ) ); + const v2 = v.dot( v ); + const w2 = a2.div( v2 ); - } + return RECIPROCAL_PI.mul( a2.mul( w2.pow2() ) ); - dispose() { +} ).setLayout( { + name: 'D_GGX_Anisotropic', + type: 'float', + inputs: [ + { name: 'alphaT', type: 'float', qualifier: 'in' }, + { name: 'alphaB', type: 'float', qualifier: 'in' }, + { name: 'dotNH', type: 'float', qualifier: 'in' }, + { name: 'dotTH', type: 'float', qualifier: 'in' }, + { name: 'dotBH', type: 'float', qualifier: 'in' } + ] +} ); - this.geometry.dispose(); - this.material.dispose(); +// GGX Distribution, Schlick Fresnel, GGX_SmithCorrelated Visibility +const BRDF_GGX = /*@__PURE__*/ Fn( ( inputs ) => { - } + const { lightDirection, f0, f90, roughness, f, USE_IRIDESCENCE, USE_ANISOTROPY } = inputs; - update() { + const normalView = inputs.normalView || transformedNormalView; - this.light.updateWorldMatrix( true, false ); + const alpha = roughness.pow2(); // UE4's roughness - if ( this.color !== undefined ) { + const halfDir = lightDirection.add( positionViewDirection ).normalize(); - this.material.color.set( this.color ); + const dotNL = normalView.dot( lightDirection ).clamp(); + const dotNV = normalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV + const dotNH = normalView.dot( halfDir ).clamp(); + const dotVH = positionViewDirection.dot( halfDir ).clamp(); - } else { + let F = F_Schlick( { f0, f90, dotVH } ); + let V, D; - this.material.color.copy( this.light.color ); + if ( defined( USE_IRIDESCENCE ) ) { - } + F = iridescence.mix( F, f ); - /* - const d = this.light.distance; + } - if ( d === 0.0 ) { + if ( defined( USE_ANISOTROPY ) ) { - this.lightDistance.visible = false; + const dotTL = anisotropyT.dot( lightDirection ); + const dotTV = anisotropyT.dot( positionViewDirection ); + const dotTH = anisotropyT.dot( halfDir ); + const dotBL = anisotropyB.dot( lightDirection ); + const dotBV = anisotropyB.dot( positionViewDirection ); + const dotBH = anisotropyB.dot( halfDir ); - } else { + V = V_GGX_SmithCorrelated_Anisotropic( { alphaT, alphaB: alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL } ); + D = D_GGX_Anisotropic( { alphaT, alphaB: alpha, dotNH, dotTH, dotBH } ); - this.lightDistance.visible = true; - this.lightDistance.scale.set( d, d, d ); + } else { - } - */ + V = V_GGX_SmithCorrelated( { alpha, dotNL, dotNV } ); + D = D_GGX( { alpha, dotNH } ); } -} + return F.mul( V ).mul( D ); -const _vector$1 = /*@__PURE__*/ new Vector3(); -const _color1 = /*@__PURE__*/ new Color(); -const _color2 = /*@__PURE__*/ new Color(); +} ); // validated -class HemisphereLightHelper extends Object3D { +// Analytical approximation of the DFG LUT, one half of the +// split-sum approximation used in indirect specular lighting. +// via 'environmentBRDF' from "Physically Based Shading on Mobile" +// https://www.unrealengine.com/blog/physically-based-shading-on-mobile +const DFGApprox = /*@__PURE__*/ Fn( ( { roughness, dotNV } ) => { - constructor( light, size, color ) { + const c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 ); - super(); + const c1 = vec4( 1, 0.0425, 1.04, - 0.04 ); - this.light = light; + const r = roughness.mul( c0 ).add( c1 ); - this.matrix = light.matrixWorld; - this.matrixAutoUpdate = false; + const a004 = r.x.mul( r.x ).min( dotNV.mul( - 9.28 ).exp2() ).mul( r.x ).add( r.y ); - this.color = color; + const fab = vec2( - 1.04, 1.04 ).mul( a004 ).add( r.zw ); - this.type = 'HemisphereLightHelper'; + return fab; - const geometry = new OctahedronGeometry( size ); - geometry.rotateY( Math.PI * 0.5 ); +} ).setLayout( { + name: 'DFGApprox', + type: 'vec2', + inputs: [ + { name: 'roughness', type: 'float' }, + { name: 'dotNV', type: 'vec3' } + ] +} ); - this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } ); - if ( this.color === undefined ) this.material.vertexColors = true; +const EnvironmentBRDF = /*@__PURE__*/ Fn( ( inputs ) => { - const position = geometry.getAttribute( 'position' ); - const colors = new Float32Array( position.count * 3 ); + const { dotNV, specularColor, specularF90, roughness } = inputs; - geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) ); + const fab = DFGApprox( { dotNV, roughness } ); + return specularColor.mul( fab.x ).add( specularF90.mul( fab.y ) ); - this.add( new Mesh( geometry, this.material ) ); +} ); - this.update(); +const Schlick_to_F0 = /*@__PURE__*/ Fn( ( { f, f90, dotVH } ) => { - } + const x = dotVH.oneMinus().saturate(); + const x2 = x.mul( x ); + const x5 = x.mul( x2, x2 ).clamp( 0, .9999 ); - dispose() { + return f.sub( vec3( f90 ).mul( x5 ) ).div( x5.oneMinus() ); - this.children[ 0 ].geometry.dispose(); - this.children[ 0 ].material.dispose(); +} ).setLayout( { + name: 'Schlick_to_F0', + type: 'vec3', + inputs: [ + { name: 'f', type: 'vec3' }, + { name: 'f90', type: 'float' }, + { name: 'dotVH', type: 'float' } + ] +} ); - } +// https://github.com/google/filament/blob/master/shaders/src/brdf.fs +const D_Charlie = /*@__PURE__*/ Fn( ( { roughness, dotNH } ) => { - update() { + const alpha = roughness.pow2(); - const mesh = this.children[ 0 ]; + // Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF" + const invAlpha = float( 1.0 ).div( alpha ); + const cos2h = dotNH.pow2(); + const sin2h = cos2h.oneMinus().max( 0.0078125 ); // 2^(-14/2), so sin2h^2 > 0 in fp16 - if ( this.color !== undefined ) { + return float( 2.0 ).add( invAlpha ).mul( sin2h.pow( invAlpha.mul( 0.5 ) ) ).div( 2.0 * Math.PI ); - this.material.color.set( this.color ); +} ).setLayout( { + name: 'D_Charlie', + type: 'float', + inputs: [ + { name: 'roughness', type: 'float' }, + { name: 'dotNH', type: 'float' } + ] +} ); - } else { +// https://github.com/google/filament/blob/master/shaders/src/brdf.fs +const V_Neubelt = /*@__PURE__*/ Fn( ( { dotNV, dotNL } ) => { - const colors = mesh.geometry.getAttribute( 'color' ); + // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886" + return float( 1.0 ).div( float( 4.0 ).mul( dotNL.add( dotNV ).sub( dotNL.mul( dotNV ) ) ) ); - _color1.copy( this.light.color ); - _color2.copy( this.light.groundColor ); +} ).setLayout( { + name: 'V_Neubelt', + type: 'float', + inputs: [ + { name: 'dotNV', type: 'float' }, + { name: 'dotNL', type: 'float' } + ] +} ); - for ( let i = 0, l = colors.count; i < l; i ++ ) { +const BRDF_Sheen = /*@__PURE__*/ Fn( ( { lightDirection } ) => { - const color = ( i < ( l / 2 ) ) ? _color1 : _color2; + const halfDir = lightDirection.add( positionViewDirection ).normalize(); - colors.setXYZ( i, color.r, color.g, color.b ); + const dotNL = transformedNormalView.dot( lightDirection ).clamp(); + const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); + const dotNH = transformedNormalView.dot( halfDir ).clamp(); - } + const D = D_Charlie( { roughness: sheenRoughness, dotNH } ); + const V = V_Neubelt( { dotNV, dotNL } ); - colors.needsUpdate = true; + return sheen.mul( D ).mul( V ); - } +} ); - this.light.updateWorldMatrix( true, false ); +// Rect Area Light - mesh.lookAt( _vector$1.setFromMatrixPosition( this.light.matrixWorld ).negate() ); +// Real-Time Polygonal-Light Shading with Linearly Transformed Cosines +// by Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt +// code: https://github.com/selfshadow/ltc_code/ - } +const LTC_Uv = /*@__PURE__*/ Fn( ( { N, V, roughness } ) => { -} + const LUT_SIZE = 64.0; + const LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE; + const LUT_BIAS = 0.5 / LUT_SIZE; -class GridHelper extends LineSegments { + const dotNV = N.dot( V ).saturate(); - constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) { + // texture parameterized by sqrt( GGX alpha ) and sqrt( 1 - cos( theta ) ) + const uv = vec2( roughness, dotNV.oneMinus().sqrt() ); - color1 = new Color( color1 ); - color2 = new Color( color2 ); + uv.assign( uv.mul( LUT_SCALE ).add( LUT_BIAS ) ); - const center = divisions / 2; - const step = size / divisions; - const halfSize = size / 2; - - const vertices = [], colors = []; - - for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) { + return uv; - vertices.push( - halfSize, 0, k, halfSize, 0, k ); - vertices.push( k, 0, - halfSize, k, 0, halfSize ); +} ).setLayout( { + name: 'LTC_Uv', + type: 'vec2', + inputs: [ + { name: 'N', type: 'vec3' }, + { name: 'V', type: 'vec3' }, + { name: 'roughness', type: 'float' } + ] +} ); - const color = i === center ? color1 : color2; +const LTC_ClippedSphereFormFactor = /*@__PURE__*/ Fn( ( { f } ) => { - color.toArray( colors, j ); j += 3; - color.toArray( colors, j ); j += 3; - color.toArray( colors, j ); j += 3; - color.toArray( colors, j ); j += 3; + // Real-Time Area Lighting: a Journey from Research to Production (p.102) + // An approximation of the form factor of a horizon-clipped rectangle. - } + const l = f.length(); - const geometry = new BufferGeometry(); - geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + return max$1( l.mul( l ).add( f.z ).div( l.add( 1.0 ) ), 0 ); - const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); +} ).setLayout( { + name: 'LTC_ClippedSphereFormFactor', + type: 'float', + inputs: [ + { name: 'f', type: 'vec3' } + ] +} ); - super( geometry, material ); +const LTC_EdgeVectorFormFactor = /*@__PURE__*/ Fn( ( { v1, v2 } ) => { - this.type = 'GridHelper'; + const x = v1.dot( v2 ); + const y = x.abs().toVar(); - } + // rational polynomial approximation to theta / sin( theta ) / 2PI + const a = y.mul( 0.0145206 ).add( 0.4965155 ).mul( y ).add( 0.8543985 ).toVar(); + const b = y.add( 4.1616724 ).mul( y ).add( 3.4175940 ).toVar(); + const v = a.div( b ); - dispose() { + const theta_sintheta = x.greaterThan( 0.0 ).select( v, max$1( x.mul( x ).oneMinus(), 1e-7 ).inverseSqrt().mul( 0.5 ).sub( v ) ); - this.geometry.dispose(); - this.material.dispose(); + return v1.cross( v2 ).mul( theta_sintheta ); - } +} ).setLayout( { + name: 'LTC_EdgeVectorFormFactor', + type: 'vec3', + inputs: [ + { name: 'v1', type: 'vec3' }, + { name: 'v2', type: 'vec3' } + ] +} ); -} +const LTC_Evaluate = /*@__PURE__*/ Fn( ( { N, V, P, mInv, p0, p1, p2, p3 } ) => { -class PolarGridHelper extends LineSegments { + // bail if point is on back side of plane of light + // assumes ccw winding order of light vertices + const v1 = p1.sub( p0 ).toVar(); + const v2 = p3.sub( p0 ).toVar(); - constructor( radius = 10, sectors = 16, rings = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888 ) { + const lightNormal = v1.cross( v2 ); + const result = vec3().toVar(); - color1 = new Color( color1 ); - color2 = new Color( color2 ); + If( lightNormal.dot( P.sub( p0 ) ).greaterThanEqual( 0.0 ), () => { - const vertices = []; - const colors = []; + // construct orthonormal basis around N + const T1 = V.sub( N.mul( V.dot( N ) ) ).normalize(); + const T2 = N.cross( T1 ).negate(); // negated from paper; possibly due to a different handedness of world coordinate system - // create the sectors + // compute transform + const mat = mInv.mul( mat3( T1, T2, N ).transpose() ).toVar(); - if ( sectors > 1 ) { + // transform rect + // & project rect onto sphere + const coords0 = mat.mul( p0.sub( P ) ).normalize().toVar(); + const coords1 = mat.mul( p1.sub( P ) ).normalize().toVar(); + const coords2 = mat.mul( p2.sub( P ) ).normalize().toVar(); + const coords3 = mat.mul( p3.sub( P ) ).normalize().toVar(); - for ( let i = 0; i < sectors; i ++ ) { + // calculate vector form factor + const vectorFormFactor = vec3( 0 ).toVar(); + vectorFormFactor.addAssign( LTC_EdgeVectorFormFactor( { v1: coords0, v2: coords1 } ) ); + vectorFormFactor.addAssign( LTC_EdgeVectorFormFactor( { v1: coords1, v2: coords2 } ) ); + vectorFormFactor.addAssign( LTC_EdgeVectorFormFactor( { v1: coords2, v2: coords3 } ) ); + vectorFormFactor.addAssign( LTC_EdgeVectorFormFactor( { v1: coords3, v2: coords0 } ) ); - const v = ( i / sectors ) * ( Math.PI * 2 ); + // adjust for horizon clipping + result.assign( vec3( LTC_ClippedSphereFormFactor( { f: vectorFormFactor } ) ) ); - const x = Math.sin( v ) * radius; - const z = Math.cos( v ) * radius; + } ); - vertices.push( 0, 0, 0 ); - vertices.push( x, 0, z ); + return result; - const color = ( i & 1 ) ? color1 : color2; +} ).setLayout( { + name: 'LTC_Evaluate', + type: 'vec3', + inputs: [ + { name: 'N', type: 'vec3' }, + { name: 'V', type: 'vec3' }, + { name: 'P', type: 'vec3' }, + { name: 'mInv', type: 'mat3' }, + { name: 'p0', type: 'vec3' }, + { name: 'p1', type: 'vec3' }, + { name: 'p2', type: 'vec3' }, + { name: 'p3', type: 'vec3' } + ] +} ); - colors.push( color.r, color.g, color.b ); - colors.push( color.r, color.g, color.b ); +// Mipped Bicubic Texture Filtering by N8 +// https://www.shadertoy.com/view/Dl2SDW - } +const bC = 1.0 / 6.0; - } +const w0 = ( a ) => mul( bC, mul( a, mul( a, a.negate().add( 3.0 ) ).sub( 3.0 ) ).add( 1.0 ) ); - // create the rings +const w1 = ( a ) => mul( bC, mul( a, mul( a, mul( 3.0, a ).sub( 6.0 ) ) ).add( 4.0 ) ); - for ( let i = 0; i < rings; i ++ ) { +const w2 = ( a ) => mul( bC, mul( a, mul( a, mul( - 3.0, a ).add( 3.0 ) ).add( 3.0 ) ).add( 1.0 ) ); - const color = ( i & 1 ) ? color1 : color2; +const w3 = ( a ) => mul( bC, pow( a, 3 ) ); - const r = radius - ( radius / rings * i ); +const g0 = ( a ) => w0( a ).add( w1( a ) ); - for ( let j = 0; j < divisions; j ++ ) { +const g1 = ( a ) => w2( a ).add( w3( a ) ); - // first vertex +// h0 and h1 are the two offset functions +const h0 = ( a ) => add( - 1.0, w1( a ).div( w0( a ).add( w1( a ) ) ) ); - let v = ( j / divisions ) * ( Math.PI * 2 ); +const h1 = ( a ) => add( 1.0, w3( a ).div( w2( a ).add( w3( a ) ) ) ); - let x = Math.sin( v ) * r; - let z = Math.cos( v ) * r; +const bicubic = ( textureNode, texelSize, lod ) => { - vertices.push( x, 0, z ); - colors.push( color.r, color.g, color.b ); + const uv = textureNode.uvNode; + const uvScaled = mul( uv, texelSize.zw ).add( 0.5 ); - // second vertex + const iuv = floor( uvScaled ); + const fuv = fract( uvScaled ); - v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 ); + const g0x = g0( fuv.x ); + const g1x = g1( fuv.x ); + const h0x = h0( fuv.x ); + const h1x = h1( fuv.x ); + const h0y = h0( fuv.y ); + const h1y = h1( fuv.y ); - x = Math.sin( v ) * r; - z = Math.cos( v ) * r; + const p0 = vec2( iuv.x.add( h0x ), iuv.y.add( h0y ) ).sub( 0.5 ).mul( texelSize.xy ); + const p1 = vec2( iuv.x.add( h1x ), iuv.y.add( h0y ) ).sub( 0.5 ).mul( texelSize.xy ); + const p2 = vec2( iuv.x.add( h0x ), iuv.y.add( h1y ) ).sub( 0.5 ).mul( texelSize.xy ); + const p3 = vec2( iuv.x.add( h1x ), iuv.y.add( h1y ) ).sub( 0.5 ).mul( texelSize.xy ); - vertices.push( x, 0, z ); - colors.push( color.r, color.g, color.b ); + const a = g0( fuv.y ).mul( add( g0x.mul( textureNode.uv( p0 ).level( lod ) ), g1x.mul( textureNode.uv( p1 ).level( lod ) ) ) ); + const b = g1( fuv.y ).mul( add( g0x.mul( textureNode.uv( p2 ).level( lod ) ), g1x.mul( textureNode.uv( p3 ).level( lod ) ) ) ); - } + return a.add( b ); - } +}; - const geometry = new BufferGeometry(); - geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); +const textureBicubic = /*@__PURE__*/ Fn( ( [ textureNode, lodNode = float( 3 ) ] ) => { - const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); + const fLodSize = vec2( textureNode.size( int( lodNode ) ) ); + const cLodSize = vec2( textureNode.size( int( lodNode.add( 1.0 ) ) ) ); + const fLodSizeInv = div( 1.0, fLodSize ); + const cLodSizeInv = div( 1.0, cLodSize ); + const fSample = bicubic( textureNode, vec4( fLodSizeInv, fLodSize ), floor( lodNode ) ); + const cSample = bicubic( textureNode, vec4( cLodSizeInv, cLodSize ), ceil( lodNode ) ); - super( geometry, material ); + return fract( lodNode ).mix( fSample, cSample ); - this.type = 'PolarGridHelper'; +} ); - } +// +// Transmission +// - dispose() { +const getVolumeTransmissionRay = /*@__PURE__*/ Fn( ( [ n, v, thickness, ior, modelMatrix ] ) => { - this.geometry.dispose(); - this.material.dispose(); + // Direction of refracted light. + const refractionVector = vec3( refract( v.negate(), normalize( n ), div( 1.0, ior ) ) ); - } + // Compute rotation-independant scaling of the model matrix. + const modelScale = vec3( + length( modelMatrix[ 0 ].xyz ), + length( modelMatrix[ 1 ].xyz ), + length( modelMatrix[ 2 ].xyz ) + ); -} + // The thickness is specified in local space. + return normalize( refractionVector ).mul( thickness.mul( modelScale ) ); -const _v1 = /*@__PURE__*/ new Vector3(); -const _v2 = /*@__PURE__*/ new Vector3(); -const _v3 = /*@__PURE__*/ new Vector3(); +} ).setLayout( { + name: 'getVolumeTransmissionRay', + type: 'vec3', + inputs: [ + { name: 'n', type: 'vec3' }, + { name: 'v', type: 'vec3' }, + { name: 'thickness', type: 'float' }, + { name: 'ior', type: 'float' }, + { name: 'modelMatrix', type: 'mat4' } + ] +} ); -class DirectionalLightHelper extends Object3D { +const applyIorToRoughness = /*@__PURE__*/ Fn( ( [ roughness, ior ] ) => { - constructor( light, size, color ) { + // Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and + // an IOR of 1.5 results in the default amount of microfacet refraction. + return roughness.mul( clamp( ior.mul( 2.0 ).sub( 2.0 ), 0.0, 1.0 ) ); - super(); +} ).setLayout( { + name: 'applyIorToRoughness', + type: 'float', + inputs: [ + { name: 'roughness', type: 'float' }, + { name: 'ior', type: 'float' } + ] +} ); - this.light = light; +const singleViewportMipTexture = /*@__PURE__*/ viewportMipTexture(); - this.matrix = light.matrixWorld; - this.matrixAutoUpdate = false; +const getTransmissionSample = /*@__PURE__*/ Fn( ( [ fragCoord, roughness, ior ] ) => { - this.color = color; + const transmissionSample = singleViewportMipTexture.uv( fragCoord ); + //const transmissionSample = viewportMipTexture( fragCoord ); - this.type = 'DirectionalLightHelper'; + const lod = log2( float( screenSize.x ) ).mul( applyIorToRoughness( roughness, ior ) ); - if ( size === undefined ) size = 1; + return textureBicubic( transmissionSample, lod ); - let geometry = new BufferGeometry(); - geometry.setAttribute( 'position', new Float32BufferAttribute( [ - - size, size, 0, - size, size, 0, - size, - size, 0, - - size, - size, 0, - - size, size, 0 - ], 3 ) ); +} ); - const material = new LineBasicMaterial( { fog: false, toneMapped: false } ); +const volumeAttenuation = /*@__PURE__*/ Fn( ( [ transmissionDistance, attenuationColor, attenuationDistance ] ) => { - this.lightPlane = new Line( geometry, material ); - this.add( this.lightPlane ); + If( attenuationDistance.notEqual( 0 ), () => { - geometry = new BufferGeometry(); - geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) ); + // Compute light attenuation using Beer's law. + const attenuationCoefficient = log( attenuationColor ).negate().div( attenuationDistance ); + const transmittance = exp( attenuationCoefficient.negate().mul( transmissionDistance ) ); - this.targetLine = new Line( geometry, material ); - this.add( this.targetLine ); + return transmittance; - this.update(); + } ); - } + // Attenuation distance is +∞, i.e. the transmitted color is not attenuated at all. + return vec3( 1.0 ); - dispose() { +} ).setLayout( { + name: 'volumeAttenuation', + type: 'vec3', + inputs: [ + { name: 'transmissionDistance', type: 'float' }, + { name: 'attenuationColor', type: 'vec3' }, + { name: 'attenuationDistance', type: 'float' } + ] +} ); - this.lightPlane.geometry.dispose(); - this.lightPlane.material.dispose(); - this.targetLine.geometry.dispose(); - this.targetLine.material.dispose(); +const getIBLVolumeRefraction = /*@__PURE__*/ Fn( ( [ n, v, roughness, diffuseColor, specularColor, specularF90, position, modelMatrix, viewMatrix, projMatrix, ior, thickness, attenuationColor, attenuationDistance, dispersion ] ) => { - } + let transmittedLight, transmittance; - update() { + if ( dispersion ) { - this.light.updateWorldMatrix( true, false ); - this.light.target.updateWorldMatrix( true, false ); + transmittedLight = vec4().toVar(); + transmittance = vec3().toVar(); - _v1.setFromMatrixPosition( this.light.matrixWorld ); - _v2.setFromMatrixPosition( this.light.target.matrixWorld ); - _v3.subVectors( _v2, _v1 ); + const halfSpread = ior.sub( 1.0 ).mul( dispersion.mul( 0.025 ) ); + const iors = vec3( ior.sub( halfSpread ), ior, ior.add( halfSpread ) ); - this.lightPlane.lookAt( _v2 ); + Loop( { start: 0, end: 3 }, ( { i } ) => { - if ( this.color !== undefined ) { + const ior = iors.element( i ); - this.lightPlane.material.color.set( this.color ); - this.targetLine.material.color.set( this.color ); + const transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); + const refractedRayExit = position.add( transmissionRay ); - } else { + // Project refracted vector on the framebuffer, while mapping to normalized device coordinates. + const ndcPos = projMatrix.mul( viewMatrix.mul( vec4( refractedRayExit, 1.0 ) ) ); + const refractionCoords = vec2( ndcPos.xy.div( ndcPos.w ) ).toVar(); + refractionCoords.addAssign( 1.0 ); + refractionCoords.divAssign( 2.0 ); + refractionCoords.assign( vec2( refractionCoords.x, refractionCoords.y.oneMinus() ) ); // webgpu - this.lightPlane.material.color.copy( this.light.color ); - this.targetLine.material.color.copy( this.light.color ); + // Sample framebuffer to get pixel the refracted ray hits. + const transmissionSample = getTransmissionSample( refractionCoords, roughness, ior ); - } + transmittedLight.element( i ).assign( transmissionSample.element( i ) ); + transmittedLight.a.addAssign( transmissionSample.a ); - this.targetLine.lookAt( _v2 ); - this.targetLine.scale.z = _v3.length(); + transmittance.element( i ).assign( diffuseColor.element( i ).mul( volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ).element( i ) ) ); - } + } ); -} + transmittedLight.a.divAssign( 3.0 ); -const _vector = /*@__PURE__*/ new Vector3(); -const _camera$1 = /*@__PURE__*/ new Camera(); + } else { -/** - * - shows frustum, line of sight and up of the camera - * - suitable for fast updates - * - based on frustum visualization in lightgl.js shadowmap example - * https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html - */ + const transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); + const refractedRayExit = position.add( transmissionRay ); -class CameraHelper extends LineSegments { + // Project refracted vector on the framebuffer, while mapping to normalized device coordinates. + const ndcPos = projMatrix.mul( viewMatrix.mul( vec4( refractedRayExit, 1.0 ) ) ); + const refractionCoords = vec2( ndcPos.xy.div( ndcPos.w ) ).toVar(); + refractionCoords.addAssign( 1.0 ); + refractionCoords.divAssign( 2.0 ); + refractionCoords.assign( vec2( refractionCoords.x, refractionCoords.y.oneMinus() ) ); // webgpu - constructor( camera ) { + // Sample framebuffer to get pixel the refracted ray hits. + transmittedLight = getTransmissionSample( refractionCoords, roughness, ior ); + transmittance = diffuseColor.mul( volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ) ); - const geometry = new BufferGeometry(); - const material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } ); + } - const vertices = []; - const colors = []; + const attenuatedColor = transmittance.rgb.mul( transmittedLight.rgb ); + const dotNV = n.dot( v ).clamp(); - const pointMap = {}; + // Get the specular component. + const F = vec3( EnvironmentBRDF( { // n, v, specularColor, specularF90, roughness + dotNV, + specularColor, + specularF90, + roughness + } ) ); - // near + // As less light is transmitted, the opacity should be increased. This simple approximation does a decent job + // of modulating a CSS background, and has no effect when the buffer is opaque, due to a solid object or clear color. + const transmittanceFactor = transmittance.r.add( transmittance.g, transmittance.b ).div( 3.0 ); - addLine( 'n1', 'n2' ); - addLine( 'n2', 'n4' ); - addLine( 'n4', 'n3' ); - addLine( 'n3', 'n1' ); + return vec4( F.oneMinus().mul( attenuatedColor ), transmittedLight.a.oneMinus().mul( transmittanceFactor ).oneMinus() ); - // far +} ); - addLine( 'f1', 'f2' ); - addLine( 'f2', 'f4' ); - addLine( 'f4', 'f3' ); - addLine( 'f3', 'f1' ); +// +// Iridescence +// - // sides +// XYZ to linear-sRGB color space +const XYZ_TO_REC709 = /*@__PURE__*/ mat3( + 3.2404542, - 0.9692660, 0.0556434, + - 1.5371385, 1.8760108, - 0.2040259, + - 0.4985314, 0.0415560, 1.0572252 +); - addLine( 'n1', 'f1' ); - addLine( 'n2', 'f2' ); - addLine( 'n3', 'f3' ); - addLine( 'n4', 'f4' ); +// Assume air interface for top +// Note: We don't handle the case fresnel0 == 1 +const Fresnel0ToIor = ( fresnel0 ) => { - // cone + const sqrtF0 = fresnel0.sqrt(); + return vec3( 1.0 ).add( sqrtF0 ).div( vec3( 1.0 ).sub( sqrtF0 ) ); - addLine( 'p', 'n1' ); - addLine( 'p', 'n2' ); - addLine( 'p', 'n3' ); - addLine( 'p', 'n4' ); +}; - // up +// ior is a value between 1.0 and 3.0. 1.0 is air interface +const IorToFresnel0 = ( transmittedIor, incidentIor ) => { - addLine( 'u1', 'u2' ); - addLine( 'u2', 'u3' ); - addLine( 'u3', 'u1' ); + return transmittedIor.sub( incidentIor ).div( transmittedIor.add( incidentIor ) ).pow2(); - // target +}; - addLine( 'c', 't' ); - addLine( 'p', 'c' ); +// Fresnel equations for dielectric/dielectric interfaces. +// Ref: https://belcour.github.io/blog/research/2017/05/01/brdf-thin-film.html +// Evaluation XYZ sensitivity curves in Fourier space +const evalSensitivity = ( OPD, shift ) => { - // cross + const phase = OPD.mul( 2.0 * Math.PI * 1.0e-9 ); + const val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 ); + const pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 ); + const VAR = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 ); - addLine( 'cn1', 'cn2' ); - addLine( 'cn3', 'cn4' ); + const x = float( 9.7470e-14 * Math.sqrt( 2.0 * Math.PI * 4.5282e+09 ) ).mul( phase.mul( 2.2399e+06 ).add( shift.x ).cos() ).mul( phase.pow2().mul( - 4.5282e+09 ).exp() ); - addLine( 'cf1', 'cf2' ); - addLine( 'cf3', 'cf4' ); + let xyz = val.mul( VAR.mul( 2.0 * Math.PI ).sqrt() ).mul( pos.mul( phase ).add( shift ).cos() ).mul( phase.pow2().negate().mul( VAR ).exp() ); + xyz = vec3( xyz.x.add( x ), xyz.y, xyz.z ).div( 1.0685e-7 ); - function addLine( a, b ) { + const rgb = XYZ_TO_REC709.mul( xyz ); - addPoint( a ); - addPoint( b ); + return rgb; - } +}; - function addPoint( id ) { +const evalIridescence = /*@__PURE__*/ Fn( ( { outsideIOR, eta2, cosTheta1, thinFilmThickness, baseF0 } ) => { - vertices.push( 0, 0, 0 ); - colors.push( 0, 0, 0 ); + // Force iridescenceIOR -> outsideIOR when thinFilmThickness -> 0.0 + const iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) ); + // Evaluate the cosTheta on the base layer (Snell law) + const sinTheta2Sq = outsideIOR.div( iridescenceIOR ).pow2().mul( float( 1 ).sub( cosTheta1.pow2() ) ); - if ( pointMap[ id ] === undefined ) { + // Handle TIR: + const cosTheta2Sq = float( 1 ).sub( sinTheta2Sq ); + /*if ( cosTheta2Sq < 0.0 ) { - pointMap[ id ] = []; + return vec3( 1.0 ); - } + }*/ - pointMap[ id ].push( ( vertices.length / 3 ) - 1 ); + const cosTheta2 = cosTheta2Sq.sqrt(); - } + // First interface + const R0 = IorToFresnel0( iridescenceIOR, outsideIOR ); + const R12 = F_Schlick( { f0: R0, f90: 1.0, dotVH: cosTheta1 } ); + //const R21 = R12; + const T121 = R12.oneMinus(); + const phi12 = iridescenceIOR.lessThan( outsideIOR ).select( Math.PI, 0.0 ); + const phi21 = float( Math.PI ).sub( phi12 ); - geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + // Second interface + const baseIOR = Fresnel0ToIor( baseF0.clamp( 0.0, 0.9999 ) ); // guard against 1.0 + const R1 = IorToFresnel0( baseIOR, iridescenceIOR.toVec3() ); + const R23 = F_Schlick( { f0: R1, f90: 1.0, dotVH: cosTheta2 } ); + const phi23 = vec3( + baseIOR.x.lessThan( iridescenceIOR ).select( Math.PI, 0.0 ), + baseIOR.y.lessThan( iridescenceIOR ).select( Math.PI, 0.0 ), + baseIOR.z.lessThan( iridescenceIOR ).select( Math.PI, 0.0 ) + ); - super( geometry, material ); + // Phase shift + const OPD = iridescenceIOR.mul( thinFilmThickness, cosTheta2, 2.0 ); + const phi = vec3( phi21 ).add( phi23 ); - this.type = 'CameraHelper'; + // Compound terms + const R123 = R12.mul( R23 ).clamp( 1e-5, 0.9999 ); + const r123 = R123.sqrt(); + const Rs = T121.pow2().mul( R23 ).div( vec3( 1.0 ).sub( R123 ) ); - this.camera = camera; - if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix(); + // Reflectance term for m = 0 (DC term amplitude) + const C0 = R12.add( Rs ); + let I = C0; - this.matrix = camera.matrixWorld; - this.matrixAutoUpdate = false; + // Reflectance term for m > 0 (pairs of diracs) + let Cm = Rs.sub( T121 ); + for ( let m = 1; m <= 2; ++ m ) { - this.pointMap = pointMap; + Cm = Cm.mul( r123 ); + const Sm = evalSensitivity( float( m ).mul( OPD ), float( m ).mul( phi ) ).mul( 2.0 ); + I = I.add( Cm.mul( Sm ) ); - this.update(); + } - // colors + // Since out of gamut colors might be produced, negative color values are clamped to 0. + return I.max( vec3( 0.0 ) ); - const colorFrustum = new Color( 0xffaa00 ); - const colorCone = new Color( 0xff0000 ); - const colorUp = new Color( 0x00aaff ); - const colorTarget = new Color( 0xffffff ); - const colorCross = new Color( 0x333333 ); - - this.setColors( colorFrustum, colorCone, colorUp, colorTarget, colorCross ); - - } +} ).setLayout( { + name: 'evalIridescence', + type: 'vec3', + inputs: [ + { name: 'outsideIOR', type: 'float' }, + { name: 'eta2', type: 'float' }, + { name: 'cosTheta1', type: 'float' }, + { name: 'thinFilmThickness', type: 'float' }, + { name: 'baseF0', type: 'vec3' } + ] +} ); - setColors( frustum, cone, up, target, cross ) { +// +// Sheen +// - const geometry = this.geometry; +// This is a curve-fit approxmation to the "Charlie sheen" BRDF integrated over the hemisphere from +// Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF". The analysis can be found +// in the Sheen section of https://drive.google.com/file/d/1T0D1VSyR4AllqIJTQAraEIzjlb5h4FKH/view?usp=sharing +const IBLSheenBRDF = /*@__PURE__*/ Fn( ( { normal, viewDir, roughness } ) => { - const colorAttribute = geometry.getAttribute( 'color' ); + const dotNV = normal.dot( viewDir ).saturate(); - // near + const r2 = roughness.pow2(); - colorAttribute.setXYZ( 0, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 1, frustum.r, frustum.g, frustum.b ); // n1, n2 - colorAttribute.setXYZ( 2, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 3, frustum.r, frustum.g, frustum.b ); // n2, n4 - colorAttribute.setXYZ( 4, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 5, frustum.r, frustum.g, frustum.b ); // n4, n3 - colorAttribute.setXYZ( 6, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 7, frustum.r, frustum.g, frustum.b ); // n3, n1 + const a = select( + roughness.lessThan( 0.25 ), + float( - 339.2 ).mul( r2 ).add( float( 161.4 ).mul( roughness ) ).sub( 25.9 ), + float( - 8.48 ).mul( r2 ).add( float( 14.3 ).mul( roughness ) ).sub( 9.95 ) + ); - // far + const b = select( + roughness.lessThan( 0.25 ), + float( 44.0 ).mul( r2 ).sub( float( 23.7 ).mul( roughness ) ).add( 3.26 ), + float( 1.97 ).mul( r2 ).sub( float( 3.27 ).mul( roughness ) ).add( 0.72 ) + ); - colorAttribute.setXYZ( 8, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 9, frustum.r, frustum.g, frustum.b ); // f1, f2 - colorAttribute.setXYZ( 10, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 11, frustum.r, frustum.g, frustum.b ); // f2, f4 - colorAttribute.setXYZ( 12, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 13, frustum.r, frustum.g, frustum.b ); // f4, f3 - colorAttribute.setXYZ( 14, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 15, frustum.r, frustum.g, frustum.b ); // f3, f1 + const DG = select( roughness.lessThan( 0.25 ), 0.0, float( 0.1 ).mul( roughness ).sub( 0.025 ) ).add( a.mul( dotNV ).add( b ).exp() ); - // sides + return DG.mul( 1.0 / Math.PI ).saturate(); - colorAttribute.setXYZ( 16, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 17, frustum.r, frustum.g, frustum.b ); // n1, f1 - colorAttribute.setXYZ( 18, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 19, frustum.r, frustum.g, frustum.b ); // n2, f2 - colorAttribute.setXYZ( 20, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 21, frustum.r, frustum.g, frustum.b ); // n3, f3 - colorAttribute.setXYZ( 22, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 23, frustum.r, frustum.g, frustum.b ); // n4, f4 +} ); - // cone +const clearcoatF0 = vec3( 0.04 ); +const clearcoatF90 = float( 1 ); - colorAttribute.setXYZ( 24, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 25, cone.r, cone.g, cone.b ); // p, n1 - colorAttribute.setXYZ( 26, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 27, cone.r, cone.g, cone.b ); // p, n2 - colorAttribute.setXYZ( 28, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 29, cone.r, cone.g, cone.b ); // p, n3 - colorAttribute.setXYZ( 30, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 31, cone.r, cone.g, cone.b ); // p, n4 +// - // up +class PhysicalLightingModel extends LightingModel { - colorAttribute.setXYZ( 32, up.r, up.g, up.b ); colorAttribute.setXYZ( 33, up.r, up.g, up.b ); // u1, u2 - colorAttribute.setXYZ( 34, up.r, up.g, up.b ); colorAttribute.setXYZ( 35, up.r, up.g, up.b ); // u2, u3 - colorAttribute.setXYZ( 36, up.r, up.g, up.b ); colorAttribute.setXYZ( 37, up.r, up.g, up.b ); // u3, u1 + constructor( clearcoat = false, sheen = false, iridescence = false, anisotropy = false, transmission = false, dispersion = false ) { - // target + super(); - colorAttribute.setXYZ( 38, target.r, target.g, target.b ); colorAttribute.setXYZ( 39, target.r, target.g, target.b ); // c, t - colorAttribute.setXYZ( 40, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 41, cross.r, cross.g, cross.b ); // p, c + this.clearcoat = clearcoat; + this.sheen = sheen; + this.iridescence = iridescence; + this.anisotropy = anisotropy; + this.transmission = transmission; + this.dispersion = dispersion; - // cross + this.clearcoatRadiance = null; + this.clearcoatSpecularDirect = null; + this.clearcoatSpecularIndirect = null; + this.sheenSpecularDirect = null; + this.sheenSpecularIndirect = null; + this.iridescenceFresnel = null; + this.iridescenceF0 = null; - colorAttribute.setXYZ( 42, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 43, cross.r, cross.g, cross.b ); // cn1, cn2 - colorAttribute.setXYZ( 44, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 45, cross.r, cross.g, cross.b ); // cn3, cn4 + } - colorAttribute.setXYZ( 46, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 47, cross.r, cross.g, cross.b ); // cf1, cf2 - colorAttribute.setXYZ( 48, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 49, cross.r, cross.g, cross.b ); // cf3, cf4 + start( context ) { - colorAttribute.needsUpdate = true; + if ( this.clearcoat === true ) { - } + this.clearcoatRadiance = vec3().toVar( 'clearcoatRadiance' ); + this.clearcoatSpecularDirect = vec3().toVar( 'clearcoatSpecularDirect' ); + this.clearcoatSpecularIndirect = vec3().toVar( 'clearcoatSpecularIndirect' ); - update() { + } - const geometry = this.geometry; - const pointMap = this.pointMap; + if ( this.sheen === true ) { - const w = 1, h = 1; + this.sheenSpecularDirect = vec3().toVar( 'sheenSpecularDirect' ); + this.sheenSpecularIndirect = vec3().toVar( 'sheenSpecularIndirect' ); - // we need just camera projection matrix inverse - // world matrix must be identity + } - _camera$1.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse ); + if ( this.iridescence === true ) { - // center / target + const dotNVi = transformedNormalView.dot( positionViewDirection ).clamp(); - setPoint( 'c', pointMap, geometry, _camera$1, 0, 0, - 1 ); - setPoint( 't', pointMap, geometry, _camera$1, 0, 0, 1 ); + this.iridescenceFresnel = evalIridescence( { + outsideIOR: float( 1.0 ), + eta2: iridescenceIOR, + cosTheta1: dotNVi, + thinFilmThickness: iridescenceThickness, + baseF0: specularColor + } ); - // near + this.iridescenceF0 = Schlick_to_F0( { f: this.iridescenceFresnel, f90: 1.0, dotVH: dotNVi } ); - setPoint( 'n1', pointMap, geometry, _camera$1, - w, - h, - 1 ); - setPoint( 'n2', pointMap, geometry, _camera$1, w, - h, - 1 ); - setPoint( 'n3', pointMap, geometry, _camera$1, - w, h, - 1 ); - setPoint( 'n4', pointMap, geometry, _camera$1, w, h, - 1 ); + } - // far + if ( this.transmission === true ) { - setPoint( 'f1', pointMap, geometry, _camera$1, - w, - h, 1 ); - setPoint( 'f2', pointMap, geometry, _camera$1, w, - h, 1 ); - setPoint( 'f3', pointMap, geometry, _camera$1, - w, h, 1 ); - setPoint( 'f4', pointMap, geometry, _camera$1, w, h, 1 ); + const position = positionWorld; + const v = cameraPosition.sub( positionWorld ).normalize(); // TODO: Create Node for this, same issue in MaterialX + const n = transformedNormalWorld; - // up + context.backdrop = getIBLVolumeRefraction( + n, + v, + roughness, + diffuseColor, + specularColor, + specularF90, // specularF90 + position, // positionWorld + modelWorldMatrix, // modelMatrix + cameraViewMatrix, // viewMatrix + cameraProjectionMatrix, // projMatrix + ior, + thickness, + attenuationColor, + attenuationDistance, + this.dispersion ? dispersion : null + ); - setPoint( 'u1', pointMap, geometry, _camera$1, w * 0.7, h * 1.1, - 1 ); - setPoint( 'u2', pointMap, geometry, _camera$1, - w * 0.7, h * 1.1, - 1 ); - setPoint( 'u3', pointMap, geometry, _camera$1, 0, h * 2, - 1 ); + context.backdropAlpha = transmission; - // cross + diffuseColor.a.mulAssign( mix( 1, context.backdrop.a, transmission ) ); - setPoint( 'cf1', pointMap, geometry, _camera$1, - w, 0, 1 ); - setPoint( 'cf2', pointMap, geometry, _camera$1, w, 0, 1 ); - setPoint( 'cf3', pointMap, geometry, _camera$1, 0, - h, 1 ); - setPoint( 'cf4', pointMap, geometry, _camera$1, 0, h, 1 ); + } - setPoint( 'cn1', pointMap, geometry, _camera$1, - w, 0, - 1 ); - setPoint( 'cn2', pointMap, geometry, _camera$1, w, 0, - 1 ); - setPoint( 'cn3', pointMap, geometry, _camera$1, 0, - h, - 1 ); - setPoint( 'cn4', pointMap, geometry, _camera$1, 0, h, - 1 ); + } - geometry.getAttribute( 'position' ).needsUpdate = true; + // Fdez-Agüera's "Multiple-Scattering Microfacet Model for Real-Time Image Based Lighting" + // Approximates multiscattering in order to preserve energy. + // http://www.jcgt.org/published/0008/01/03/ - } + computeMultiscattering( singleScatter, multiScatter, specularF90 ) { - dispose() { + const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV - this.geometry.dispose(); - this.material.dispose(); + const fab = DFGApprox( { roughness, dotNV } ); - } + const Fr = this.iridescenceF0 ? iridescence.mix( specularColor, this.iridescenceF0 ) : specularColor; -} + const FssEss = Fr.mul( fab.x ).add( specularF90.mul( fab.y ) ); + const Ess = fab.x.add( fab.y ); + const Ems = Ess.oneMinus(); -function setPoint( point, pointMap, geometry, camera, x, y, z ) { + const Favg = specularColor.add( specularColor.oneMinus().mul( 0.047619 ) ); // 1/21 + const Fms = FssEss.mul( Favg ).div( Ems.mul( Favg ).oneMinus() ); - _vector.set( x, y, z ).unproject( camera ); + singleScatter.addAssign( FssEss ); + multiScatter.addAssign( Fms.mul( Ems ) ); - const points = pointMap[ point ]; + } - if ( points !== undefined ) { + direct( { lightDirection, lightColor, reflectedLight } ) { - const position = geometry.getAttribute( 'position' ); + const dotNL = transformedNormalView.dot( lightDirection ).clamp(); + const irradiance = dotNL.mul( lightColor ); - for ( let i = 0, l = points.length; i < l; i ++ ) { + if ( this.sheen === true ) { - position.setXYZ( points[ i ], _vector.x, _vector.y, _vector.z ); + this.sheenSpecularDirect.addAssign( irradiance.mul( BRDF_Sheen( { lightDirection } ) ) ); } - } + if ( this.clearcoat === true ) { -} + const dotNLcc = transformedClearcoatNormalView.dot( lightDirection ).clamp(); + const ccIrradiance = dotNLcc.mul( lightColor ); -const _box = /*@__PURE__*/ new Box3(); + this.clearcoatSpecularDirect.addAssign( ccIrradiance.mul( BRDF_GGX( { lightDirection, f0: clearcoatF0, f90: clearcoatF90, roughness: clearcoatRoughness, normalView: transformedClearcoatNormalView } ) ) ); -class BoxHelper extends LineSegments { + } - constructor( object, color = 0xffff00 ) { + reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) ); - const indices = 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 ] ); - const positions = new Float32Array( 8 * 3 ); + reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_GGX( { lightDirection, f0: specularColor, f90: 1, roughness, iridescence: this.iridescence, f: this.iridescenceFresnel, USE_IRIDESCENCE: this.iridescence, USE_ANISOTROPY: this.anisotropy } ) ) ); - const geometry = new BufferGeometry(); - geometry.setIndex( new BufferAttribute( indices, 1 ) ); - geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) ); + } - super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); + directRectArea( { lightColor, lightPosition, halfWidth, halfHeight, reflectedLight, ltc_1, ltc_2 } ) { - this.object = object; - this.type = 'BoxHelper'; + const p0 = lightPosition.add( halfWidth ).sub( halfHeight ); // counterclockwise; light shines in local neg z direction + const p1 = lightPosition.sub( halfWidth ).sub( halfHeight ); + const p2 = lightPosition.sub( halfWidth ).add( halfHeight ); + const p3 = lightPosition.add( halfWidth ).add( halfHeight ); - this.matrixAutoUpdate = false; + const N = transformedNormalView; + const V = positionViewDirection; + const P = positionView.toVar(); - this.update(); + const uv = LTC_Uv( { N, V, roughness } ); - } + const t1 = ltc_1.uv( uv ).toVar(); + const t2 = ltc_2.uv( uv ).toVar(); - update( object ) { + const mInv = mat3( + vec3( t1.x, 0, t1.y ), + vec3( 0, 1, 0 ), + vec3( t1.z, 0, t1.w ) + ).toVar(); - if ( object !== undefined ) { + // LTC Fresnel Approximation by Stephen Hill + // http://blog.selfshadow.com/publications/s2016-advances/s2016_ltc_fresnel.pdf + const fresnel = specularColor.mul( t2.x ).add( specularColor.oneMinus().mul( t2.y ) ).toVar(); - console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' ); + reflectedLight.directSpecular.addAssign( lightColor.mul( fresnel ).mul( LTC_Evaluate( { N, V, P, mInv, p0, p1, p2, p3 } ) ) ); - } + reflectedLight.directDiffuse.addAssign( lightColor.mul( diffuseColor ).mul( LTC_Evaluate( { N, V, P, mInv: mat3( 1, 0, 0, 0, 1, 0, 0, 0, 1 ), p0, p1, p2, p3 } ) ) ); - if ( this.object !== undefined ) { + } - _box.setFromObject( this.object ); + indirect( context, stack, builder ) { - } + this.indirectDiffuse( context, stack, builder ); + this.indirectSpecular( context, stack, builder ); + this.ambientOcclusion( context, stack, builder ); - if ( _box.isEmpty() ) return; + } - const min = _box.min; - const max = _box.max; + indirectDiffuse( { irradiance, reflectedLight } ) { - /* - 5____4 - 1/___0/| - | 6__|_7 - 2/___3/ + reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) ); - 0: max.x, max.y, max.z - 1: min.x, max.y, max.z - 2: min.x, min.y, max.z - 3: max.x, min.y, max.z - 4: max.x, max.y, min.z - 5: min.x, max.y, min.z - 6: min.x, min.y, min.z - 7: max.x, min.y, min.z - */ + } - const position = this.geometry.attributes.position; - const array = position.array; + indirectSpecular( { radiance, iblIrradiance, reflectedLight } ) { - array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z; - array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z; - array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z; - array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z; - array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z; - array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z; - array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z; - array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z; + if ( this.sheen === true ) { - position.needsUpdate = true; + this.sheenSpecularIndirect.addAssign( iblIrradiance.mul( + sheen, + IBLSheenBRDF( { + normal: transformedNormalView, + viewDir: positionViewDirection, + roughness: sheenRoughness + } ) + ) ); - this.geometry.computeBoundingSphere(); + } - } + if ( this.clearcoat === true ) { - setFromObject( object ) { + const dotNVcc = transformedClearcoatNormalView.dot( positionViewDirection ).clamp(); - this.object = object; - this.update(); + const clearcoatEnv = EnvironmentBRDF( { + dotNV: dotNVcc, + specularColor: clearcoatF0, + specularF90: clearcoatF90, + roughness: clearcoatRoughness + } ); - return this; + this.clearcoatSpecularIndirect.addAssign( this.clearcoatRadiance.mul( clearcoatEnv ) ); - } + } - copy( source, recursive ) { + // Both indirect specular and indirect diffuse light accumulate here - super.copy( source, recursive ); + const singleScattering = vec3().toVar( 'singleScattering' ); + const multiScattering = vec3().toVar( 'multiScattering' ); + const cosineWeightedIrradiance = iblIrradiance.mul( 1 / Math.PI ); - this.object = source.object; + this.computeMultiscattering( singleScattering, multiScattering, specularF90 ); - return this; + const totalScattering = singleScattering.add( multiScattering ); - } + const diffuse = diffuseColor.mul( totalScattering.r.max( totalScattering.g ).max( totalScattering.b ).oneMinus() ); - dispose() { + reflectedLight.indirectSpecular.addAssign( radiance.mul( singleScattering ) ); + reflectedLight.indirectSpecular.addAssign( multiScattering.mul( cosineWeightedIrradiance ) ); - this.geometry.dispose(); - this.material.dispose(); + reflectedLight.indirectDiffuse.addAssign( diffuse.mul( cosineWeightedIrradiance ) ); } -} - -class Box3Helper extends LineSegments { + ambientOcclusion( { ambientOcclusion, reflectedLight } ) { - constructor( box, color = 0xffff00 ) { + const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV - const indices = 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 ] ); + const aoNV = dotNV.add( ambientOcclusion ); + const aoExp = roughness.mul( - 16.0 ).oneMinus().negate().exp2(); - const positions = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 1, - 1, 1, - 1, - 1 ]; + const aoNode = ambientOcclusion.sub( aoNV.pow( aoExp ).oneMinus() ).clamp(); - const geometry = new BufferGeometry(); + if ( this.clearcoat === true ) { - geometry.setIndex( new BufferAttribute( indices, 1 ) ); + this.clearcoatSpecularIndirect.mulAssign( ambientOcclusion ); - geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + } - super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); + if ( this.sheen === true ) { - this.box = box; + this.sheenSpecularIndirect.mulAssign( ambientOcclusion ); - this.type = 'Box3Helper'; + } - this.geometry.computeBoundingSphere(); + reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion ); + reflectedLight.indirectSpecular.mulAssign( aoNode ); } - updateMatrixWorld( force ) { + finish( context ) { - const box = this.box; + const { outgoingLight } = context; - if ( box.isEmpty() ) return; + if ( this.clearcoat === true ) { - box.getCenter( this.position ); + const dotNVcc = transformedClearcoatNormalView.dot( positionViewDirection ).clamp(); - box.getSize( this.scale ); + const Fcc = F_Schlick( { + dotVH: dotNVcc, + f0: clearcoatF0, + f90: clearcoatF90 + } ); - this.scale.multiplyScalar( 0.5 ); + const clearcoatLight = outgoingLight.mul( clearcoat.mul( Fcc ).oneMinus() ).add( this.clearcoatSpecularDirect.add( this.clearcoatSpecularIndirect ).mul( clearcoat ) ); - super.updateMatrixWorld( force ); + outgoingLight.assign( clearcoatLight ); - } + } - dispose() { + if ( this.sheen === true ) { - this.geometry.dispose(); - this.material.dispose(); + const sheenEnergyComp = sheen.r.max( sheen.g ).max( sheen.b ).mul( 0.157 ).oneMinus(); + const sheenLight = outgoingLight.mul( sheenEnergyComp ).add( this.sheenSpecularDirect, this.sheenSpecularIndirect ); + + outgoingLight.assign( sheenLight ); + + } } } -class PlaneHelper extends Line { +// These defines must match with PMREMGenerator - constructor( plane, size = 1, hex = 0xffff00 ) { +const cubeUV_r0 = /*@__PURE__*/ float( 1.0 ); +const cubeUV_m0 = /*@__PURE__*/ float( - 2.0 ); +const cubeUV_r1 = /*@__PURE__*/ float( 0.8 ); +const cubeUV_m1 = /*@__PURE__*/ float( - 1.0 ); +const cubeUV_r4 = /*@__PURE__*/ float( 0.4 ); +const cubeUV_m4 = /*@__PURE__*/ float( 2.0 ); +const cubeUV_r5 = /*@__PURE__*/ float( 0.305 ); +const cubeUV_m5 = /*@__PURE__*/ float( 3.0 ); +const cubeUV_r6 = /*@__PURE__*/ float( 0.21 ); +const cubeUV_m6 = /*@__PURE__*/ float( 4.0 ); - const color = hex; +const cubeUV_minMipLevel = /*@__PURE__*/ float( 4.0 ); +const cubeUV_minTileSize = /*@__PURE__*/ float( 16.0 ); - const positions = [ 1, - 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, - 1, 0, 1, 1, 0 ]; +// These shader functions convert between the UV coordinates of a single face of +// a cubemap, the 0-5 integer index of a cube face, and the direction vector for +// sampling a textureCube (not generally normalized ). - const geometry = new BufferGeometry(); - geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); - geometry.computeBoundingSphere(); +const getFace = /*@__PURE__*/ Fn( ( [ direction ] ) => { - super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); + const absDirection = vec3( abs( direction ) ).toVar(); + const face = float( - 1.0 ).toVar(); - this.type = 'PlaneHelper'; + If( absDirection.x.greaterThan( absDirection.z ), () => { - this.plane = plane; + If( absDirection.x.greaterThan( absDirection.y ), () => { - this.size = size; + face.assign( select( direction.x.greaterThan( 0.0 ), 0.0, 3.0 ) ); - const positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ]; + } ).Else( () => { - const geometry2 = new BufferGeometry(); - geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) ); - geometry2.computeBoundingSphere(); + face.assign( select( direction.y.greaterThan( 0.0 ), 1.0, 4.0 ) ); - this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) ); + } ); - } + } ).Else( () => { - updateMatrixWorld( force ) { + If( absDirection.z.greaterThan( absDirection.y ), () => { - this.position.set( 0, 0, 0 ); + face.assign( select( direction.z.greaterThan( 0.0 ), 2.0, 5.0 ) ); - this.scale.set( 0.5 * this.size, 0.5 * this.size, 1 ); + } ).Else( () => { - this.lookAt( this.plane.normal ); + face.assign( select( direction.y.greaterThan( 0.0 ), 1.0, 4.0 ) ); - this.translateZ( - this.plane.constant ); + } ); - super.updateMatrixWorld( force ); + } ); - } + return face; - dispose() { +} ).setLayout( { + name: 'getFace', + type: 'float', + inputs: [ + { name: 'direction', type: 'vec3' } + ] +} ); - this.geometry.dispose(); - this.material.dispose(); - this.children[ 0 ].geometry.dispose(); - this.children[ 0 ].material.dispose(); +// RH coordinate system; PMREM face-indexing convention +const getUV = /*@__PURE__*/ Fn( ( [ direction, face ] ) => { - } + const uv = vec2().toVar(); -} + If( face.equal( 0.0 ), () => { -const _axis = /*@__PURE__*/ new Vector3(); -let _lineGeometry, _coneGeometry; + uv.assign( vec2( direction.z, direction.y ).div( abs( direction.x ) ) ); // pos x -class ArrowHelper extends Object3D { + } ).ElseIf( face.equal( 1.0 ), () => { - // dir is assumed to be normalized + uv.assign( vec2( direction.x.negate(), direction.z.negate() ).div( abs( direction.y ) ) ); // pos y - constructor( dir = new Vector3( 0, 0, 1 ), origin = new Vector3( 0, 0, 0 ), length = 1, color = 0xffff00, headLength = length * 0.2, headWidth = headLength * 0.2 ) { + } ).ElseIf( face.equal( 2.0 ), () => { - super(); + uv.assign( vec2( direction.x.negate(), direction.y ).div( abs( direction.z ) ) ); // pos z - this.type = 'ArrowHelper'; + } ).ElseIf( face.equal( 3.0 ), () => { - if ( _lineGeometry === undefined ) { + uv.assign( vec2( direction.z.negate(), direction.y ).div( abs( direction.x ) ) ); // neg x - _lineGeometry = new BufferGeometry(); - _lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) ); + } ).ElseIf( face.equal( 4.0 ), () => { - _coneGeometry = new CylinderGeometry( 0, 0.5, 1, 5, 1 ); - _coneGeometry.translate( 0, - 0.5, 0 ); + uv.assign( vec2( direction.x.negate(), direction.z ).div( abs( direction.y ) ) ); // neg y - } + } ).Else( () => { - this.position.copy( origin ); + uv.assign( vec2( direction.x, direction.y ).div( abs( direction.z ) ) ); // neg z - this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); - this.line.matrixAutoUpdate = false; - this.add( this.line ); + } ); - this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) ); - this.cone.matrixAutoUpdate = false; - this.add( this.cone ); + return mul( 0.5, uv.add( 1.0 ) ); - this.setDirection( dir ); - this.setLength( length, headLength, headWidth ); - - } +} ).setLayout( { + name: 'getUV', + type: 'vec2', + inputs: [ + { name: 'direction', type: 'vec3' }, + { name: 'face', type: 'float' } + ] +} ); - setDirection( dir ) { +const roughnessToMip = /*@__PURE__*/ Fn( ( [ roughness ] ) => { - // dir is assumed to be normalized + const mip = float( 0.0 ).toVar(); - if ( dir.y > 0.99999 ) { + If( roughness.greaterThanEqual( cubeUV_r1 ), () => { - this.quaternion.set( 0, 0, 0, 1 ); + mip.assign( cubeUV_r0.sub( roughness ).mul( cubeUV_m1.sub( cubeUV_m0 ) ).div( cubeUV_r0.sub( cubeUV_r1 ) ).add( cubeUV_m0 ) ); - } else if ( dir.y < - 0.99999 ) { + } ).ElseIf( roughness.greaterThanEqual( cubeUV_r4 ), () => { - this.quaternion.set( 1, 0, 0, 0 ); + mip.assign( cubeUV_r1.sub( roughness ).mul( cubeUV_m4.sub( cubeUV_m1 ) ).div( cubeUV_r1.sub( cubeUV_r4 ) ).add( cubeUV_m1 ) ); - } else { + } ).ElseIf( roughness.greaterThanEqual( cubeUV_r5 ), () => { - _axis.set( dir.z, 0, - dir.x ).normalize(); + mip.assign( cubeUV_r4.sub( roughness ).mul( cubeUV_m5.sub( cubeUV_m4 ) ).div( cubeUV_r4.sub( cubeUV_r5 ) ).add( cubeUV_m4 ) ); - const radians = Math.acos( dir.y ); + } ).ElseIf( roughness.greaterThanEqual( cubeUV_r6 ), () => { - this.quaternion.setFromAxisAngle( _axis, radians ); + mip.assign( cubeUV_r5.sub( roughness ).mul( cubeUV_m6.sub( cubeUV_m5 ) ).div( cubeUV_r5.sub( cubeUV_r6 ) ).add( cubeUV_m5 ) ); - } + } ).Else( () => { - } + mip.assign( float( - 2.0 ).mul( log2( mul( 1.16, roughness ) ) ) ); // 1.16 = 1.79^0.25 - setLength( length, headLength = length * 0.2, headWidth = headLength * 0.2 ) { + } ); - this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458 - this.line.updateMatrix(); + return mip; - this.cone.scale.set( headWidth, headLength, headWidth ); - this.cone.position.y = length; - this.cone.updateMatrix(); +} ).setLayout( { + name: 'roughnessToMip', + type: 'float', + inputs: [ + { name: 'roughness', type: 'float' } + ] +} ); - } +// RH coordinate system; PMREM face-indexing convention +const getDirection = /*@__PURE__*/ Fn( ( [ uv_immutable, face ] ) => { - setColor( color ) { + const uv = uv_immutable.toVar(); + uv.assign( mul( 2.0, uv ).sub( 1.0 ) ); + const direction = vec3( uv, 1.0 ).toVar(); - this.line.material.color.set( color ); - this.cone.material.color.set( color ); + If( face.equal( 0.0 ), () => { - } + direction.assign( direction.zyx ); // ( 1, v, u ) pos x - copy( source ) { + } ).ElseIf( face.equal( 1.0 ), () => { - super.copy( source, false ); + direction.assign( direction.xzy ); + direction.xz.mulAssign( - 1.0 ); // ( -u, 1, -v ) pos y - this.line.copy( source.line ); - this.cone.copy( source.cone ); + } ).ElseIf( face.equal( 2.0 ), () => { - return this; + direction.x.mulAssign( - 1.0 ); // ( -u, v, 1 ) pos z - } + } ).ElseIf( face.equal( 3.0 ), () => { - dispose() { + direction.assign( direction.zyx ); + direction.xz.mulAssign( - 1.0 ); // ( -1, v, -u ) neg x - this.line.geometry.dispose(); - this.line.material.dispose(); - this.cone.geometry.dispose(); - this.cone.material.dispose(); + } ).ElseIf( face.equal( 4.0 ), () => { - } + direction.assign( direction.xzy ); + direction.xy.mulAssign( - 1.0 ); // ( -u, -1, v ) neg y -} + } ).ElseIf( face.equal( 5.0 ), () => { -class AxesHelper extends LineSegments { + direction.z.mulAssign( - 1.0 ); // ( u, v, -1 ) neg zS - constructor( size = 1 ) { + } ); - const vertices = [ - 0, 0, 0, size, 0, 0, - 0, 0, 0, 0, size, 0, - 0, 0, 0, 0, 0, size - ]; + return direction; - const colors = [ - 1, 0, 0, 1, 0.6, 0, - 0, 1, 0, 0.6, 1, 0, - 0, 0, 1, 0, 0.6, 1 - ]; +} ).setLayout( { + name: 'getDirection', + type: 'vec3', + inputs: [ + { name: 'uv', type: 'vec2' }, + { name: 'face', type: 'float' } + ] +} ); - const geometry = new BufferGeometry(); - geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); - geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); +// - const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); +const textureCubeUV = /*@__PURE__*/ Fn( ( [ envMap, sampleDir_immutable, roughness_immutable, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP ] ) => { - super( geometry, material ); + const roughness = float( roughness_immutable ); + const sampleDir = vec3( sampleDir_immutable ); - this.type = 'AxesHelper'; + const mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP ); + const mipF = fract( mip ); + const mipInt = floor( mip ); + const color0 = vec3( bilinearCubeUV( envMap, sampleDir, mipInt, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP ) ).toVar(); - } + If( mipF.notEqual( 0.0 ), () => { - setColors( xAxisColor, yAxisColor, zAxisColor ) { + const color1 = vec3( bilinearCubeUV( envMap, sampleDir, mipInt.add( 1.0 ), CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP ) ).toVar(); - const color = new Color(); - const array = this.geometry.attributes.color.array; + color0.assign( mix( color0, color1, mipF ) ); - color.set( xAxisColor ); - color.toArray( array, 0 ); - color.toArray( array, 3 ); + } ); - color.set( yAxisColor ); - color.toArray( array, 6 ); - color.toArray( array, 9 ); + return color0; - color.set( zAxisColor ); - color.toArray( array, 12 ); - color.toArray( array, 15 ); +} ); - this.geometry.attributes.color.needsUpdate = true; +const bilinearCubeUV = /*@__PURE__*/ Fn( ( [ envMap, direction_immutable, mipInt_immutable, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP ] ) => { - return this; + const mipInt = float( mipInt_immutable ).toVar(); + const direction = vec3( direction_immutable ); + const face = float( getFace( direction ) ).toVar(); + const filterInt = float( max$1( cubeUV_minMipLevel.sub( mipInt ), 0.0 ) ).toVar(); + mipInt.assign( max$1( mipInt, cubeUV_minMipLevel ) ); + const faceSize = float( exp2( mipInt ) ).toVar(); + const uv = vec2( getUV( direction, face ).mul( faceSize.sub( 2.0 ) ).add( 1.0 ) ).toVar(); - } + If( face.greaterThan( 2.0 ), () => { - dispose() { + uv.y.addAssign( faceSize ); + face.subAssign( 3.0 ); - this.geometry.dispose(); - this.material.dispose(); + } ); - } + uv.x.addAssign( face.mul( faceSize ) ); + uv.x.addAssign( filterInt.mul( mul( 3.0, cubeUV_minTileSize ) ) ); + uv.y.addAssign( mul( 4.0, exp2( CUBEUV_MAX_MIP ).sub( faceSize ) ) ); + uv.x.mulAssign( CUBEUV_TEXEL_WIDTH ); + uv.y.mulAssign( CUBEUV_TEXEL_HEIGHT ); -} + return envMap.uv( uv ).grad( vec2(), vec2() ); // disable anisotropic filtering -class ShapePath { +} ); - constructor() { +const getSample = /*@__PURE__*/ Fn( ( { envMap, mipInt, outputDirection, theta, axis, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP } ) => { - this.type = 'ShapePath'; + const cosTheta = cos( theta ); - this.color = new Color(); + // Rodrigues' axis-angle rotation + const sampleDirection = outputDirection.mul( cosTheta ) + .add( axis.cross( outputDirection ).mul( sin( theta ) ) ) + .add( axis.mul( axis.dot( outputDirection ).mul( cosTheta.oneMinus() ) ) ); - this.subPaths = []; - this.currentPath = null; + return bilinearCubeUV( envMap, sampleDirection, mipInt, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP ); - } +} ); - moveTo( x, y ) { +const blur = /*@__PURE__*/ Fn( ( { n, latitudinal, poleAxis, outputDirection, weights, samples, dTheta, mipInt, envMap, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP } ) => { - this.currentPath = new Path(); - this.subPaths.push( this.currentPath ); - this.currentPath.moveTo( x, y ); + const axis = vec3( select( latitudinal, poleAxis, cross( poleAxis, outputDirection ) ) ).toVar(); - return this; + If( all( axis.equals( vec3( 0.0 ) ) ), () => { - } + axis.assign( vec3( outputDirection.z, 0.0, outputDirection.x.negate() ) ); - lineTo( x, y ) { + } ); - this.currentPath.lineTo( x, y ); + axis.assign( normalize( axis ) ); - return this; + const gl_FragColor = vec3().toVar(); + gl_FragColor.addAssign( weights.element( int( 0 ) ).mul( getSample( { theta: 0.0, axis, outputDirection, mipInt, envMap, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP } ) ) ); - } + Loop( { start: int( 1 ), end: n }, ( { i } ) => { - quadraticCurveTo( aCPx, aCPy, aX, aY ) { + If( i.greaterThanEqual( samples ), () => { - this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY ); + Break(); - return this; + } ); - } + const theta = float( dTheta.mul( float( i ) ) ).toVar(); + gl_FragColor.addAssign( weights.element( i ).mul( getSample( { theta: theta.mul( - 1.0 ), axis, outputDirection, mipInt, envMap, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP } ) ) ); + gl_FragColor.addAssign( weights.element( i ).mul( getSample( { theta, axis, outputDirection, mipInt, envMap, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP } ) ) ); - bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { + } ); - this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ); + return vec4( gl_FragColor, 1 ); - return this; +} ); - } +let _generator = null; - splineThru( pts ) { +const _cache = new WeakMap(); - this.currentPath.splineThru( pts ); +function _generateCubeUVSize( imageHeight ) { - return this; + const maxMip = Math.log2( imageHeight ) - 2; - } + const texelHeight = 1.0 / imageHeight; - toShapes( isCCW ) { + const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) ); - function toShapesNoHoles( inSubpaths ) { + return { texelWidth, texelHeight, maxMip }; - const shapes = []; +} - for ( let i = 0, l = inSubpaths.length; i < l; i ++ ) { +function _getPMREMFromTexture( texture ) { - const tmpPath = inSubpaths[ i ]; + let cacheTexture = _cache.get( texture ); - const tmpShape = new Shape(); - tmpShape.curves = tmpPath.curves; + const pmremVersion = cacheTexture !== undefined ? cacheTexture.pmremVersion : - 1; - shapes.push( tmpShape ); + if ( pmremVersion !== texture.pmremVersion ) { - } + const image = texture.image; - return shapes; + if ( texture.isCubeTexture ) { - } + if ( isCubeMapReady( image ) ) { - function isPointInsidePolygon( inPt, inPolygon ) { + cacheTexture = _generator.fromCubemap( texture, cacheTexture ); - const polyLen = inPolygon.length; + } else { - // inPt on polygon contour => immediate success or - // toggling of inside/outside at every single! intersection point of an edge - // with the horizontal line through inPt, left of inPt - // not counting lowerY endpoints of edges and whole edges on that line - let inside = false; - for ( let p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) { + return null; - let edgeLowPt = inPolygon[ p ]; - let edgeHighPt = inPolygon[ q ]; + } - let edgeDx = edgeHighPt.x - edgeLowPt.x; - let edgeDy = edgeHighPt.y - edgeLowPt.y; - if ( Math.abs( edgeDy ) > Number.EPSILON ) { + } else { - // not parallel - if ( edgeDy < 0 ) { + if ( isEquirectangularMapReady( image ) ) { - edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx; - edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy; + cacheTexture = _generator.fromEquirectangular( texture, cacheTexture ); - } + } else { - if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue; + return null; - if ( inPt.y === edgeLowPt.y ) { + } - if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ? - // continue; // no intersection or edgeLowPt => doesn't count !!! + } - } else { + cacheTexture.pmremVersion = texture.pmremVersion; - const perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y ); - if ( perpEdge === 0 ) return true; // inPt is on contour ? - if ( perpEdge < 0 ) continue; - inside = ! inside; // true intersection left of inPt + _cache.set( texture, cacheTexture ); - } + } - } else { + return cacheTexture.texture; - // parallel or collinear - if ( inPt.y !== edgeLowPt.y ) continue; // parallel - // edge lies on the same horizontal line as inPt - if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) || - ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour ! - // continue; +} - } +class PMREMNode extends TempNode { - } + static get type() { - return inside; + return 'PMREMNode'; - } + } - const isClockWise = ShapeUtils.isClockWise; + constructor( value, uvNode = null, levelNode = null ) { - const subPaths = this.subPaths; - if ( subPaths.length === 0 ) return []; + super( 'vec3' ); - let solid, tmpPath, tmpShape; - const shapes = []; + this._value = value; + this._pmrem = null; - if ( subPaths.length === 1 ) { + this.uvNode = uvNode; + this.levelNode = levelNode; - tmpPath = subPaths[ 0 ]; - tmpShape = new Shape(); - tmpShape.curves = tmpPath.curves; - shapes.push( tmpShape ); - return shapes; + this._generator = null; - } + const defaultTexture = new Texture(); + defaultTexture.isRenderTargetTexture = true; - let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() ); - holesFirst = isCCW ? ! holesFirst : holesFirst; + this._texture = texture( defaultTexture ); - // console.log("Holes first", holesFirst); + this._width = uniform( 0 ); + this._height = uniform( 0 ); + this._maxMip = uniform( 0 ); - const betterShapeHoles = []; - const newShapes = []; - let newShapeHoles = []; - let mainIdx = 0; - let tmpPoints; + this.updateBeforeType = NodeUpdateType.RENDER; - newShapes[ mainIdx ] = undefined; - newShapeHoles[ mainIdx ] = []; + } - for ( let i = 0, l = subPaths.length; i < l; i ++ ) { + set value( value ) { - tmpPath = subPaths[ i ]; - tmpPoints = tmpPath.getPoints(); - solid = isClockWise( tmpPoints ); - solid = isCCW ? ! solid : solid; + this._value = value; + this._pmrem = null; - if ( solid ) { + } - if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++; + get value() { - newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints }; - newShapes[ mainIdx ].s.curves = tmpPath.curves; + return this._value; - if ( holesFirst ) mainIdx ++; - newShapeHoles[ mainIdx ] = []; + } - //console.log('cw', i); + updateFromTexture( texture ) { - } else { + const cubeUVSize = _generateCubeUVSize( texture.image.height ); - newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } ); + this._texture.value = texture; + this._width.value = cubeUVSize.texelWidth; + this._height.value = cubeUVSize.texelHeight; + this._maxMip.value = cubeUVSize.maxMip; - //console.log('ccw', i); + } - } + updateBefore() { - } + let pmrem = this._pmrem; - // only Holes? -> probably all Shapes with wrong orientation - if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths ); + const pmremVersion = pmrem ? pmrem.pmremVersion : - 1; + const texture = this._value; + if ( pmremVersion !== texture.pmremVersion ) { - if ( newShapes.length > 1 ) { + if ( texture.isPMREMTexture === true ) { - let ambiguous = false; - let toChange = 0; + pmrem = texture; - for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { + } else { - betterShapeHoles[ sIdx ] = []; + pmrem = _getPMREMFromTexture( texture ); } - for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { - - const sho = newShapeHoles[ sIdx ]; + if ( pmrem !== null ) { - for ( let hIdx = 0; hIdx < sho.length; hIdx ++ ) { + this._pmrem = pmrem; - const ho = sho[ hIdx ]; - let hole_unassigned = true; + this.updateFromTexture( pmrem ); - for ( let s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) { + } - if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) { + } - if ( sIdx !== s2Idx ) toChange ++; + } - if ( hole_unassigned ) { + setup( builder ) { - hole_unassigned = false; - betterShapeHoles[ s2Idx ].push( ho ); + if ( _generator === null ) { - } else { + _generator = builder.createPMREMGenerator(); - ambiguous = true; + } - } + // - } + this.updateBefore( builder ); - } + // - if ( hole_unassigned ) { + let uvNode = this.uvNode; - betterShapeHoles[ sIdx ].push( ho ); + if ( uvNode === null && builder.context.getUV ) { - } + uvNode = builder.context.getUV( this ); - } + } - } + // - if ( toChange > 0 && ambiguous === false ) { + const texture = this.value; - newShapeHoles = betterShapeHoles; + if ( builder.renderer.coordinateSystem === WebGLCoordinateSystem && texture.isPMREMTexture !== true && texture.isRenderTargetTexture === true ) { - } + uvNode = vec3( uvNode.x.negate(), uvNode.yz ); } - let tmpHoles; - - for ( let i = 0, il = newShapes.length; i < il; i ++ ) { - - tmpShape = newShapes[ i ].s; - shapes.push( tmpShape ); - tmpHoles = newShapeHoles[ i ]; + // - for ( let j = 0, jl = tmpHoles.length; j < jl; j ++ ) { + let levelNode = this.levelNode; - tmpShape.holes.push( tmpHoles[ j ].h ); + if ( levelNode === null && builder.context.getTextureLevel ) { - } + levelNode = builder.context.getTextureLevel( this ); } - //console.log("shape", shapes); + // - return shapes; + return textureCubeUV( this._texture, uvNode, levelNode, this._width, this._height, this._maxMip ); } } -class Controls extends EventDispatcher { +function isCubeMapReady( image ) { - constructor( object, domElement ) { + if ( image === null || image === undefined ) return false; - super(); + let count = 0; + const length = 6; - this.object = object; - this.domElement = domElement; + for ( let i = 0; i < length; i ++ ) { - this.enabled = true; + if ( image[ i ] !== undefined ) count ++; - this.state = - 1; + } - this.keys = {}; - this.mouseButtons = { LEFT: null, MIDDLE: null, RIGHT: null }; - this.touches = { ONE: null, TWO: null }; + return count === length; - } - connect() {} +} - disconnect() {} +function isEquirectangularMapReady( image ) { - dispose() {} + if ( image === null || image === undefined ) return false; - update( /* delta */ ) {} + return image.height > 0; } -class WebGLMultipleRenderTargets extends WebGLRenderTarget { // @deprecated, r162 +const pmremTexture = /*@__PURE__*/ nodeProxy( PMREMNode ); - constructor( width = 1, height = 1, count = 1, options = {} ) { +const _envNodeCache = new WeakMap(); - console.warn( 'THREE.WebGLMultipleRenderTargets has been deprecated and will be removed in r172. Use THREE.WebGLRenderTarget and set the "count" parameter to enable MRT.' ); +class EnvironmentNode extends LightingNode { - super( width, height, { ...options, count } ); + static get type() { - this.isWebGLMultipleRenderTargets = true; + return 'EnvironmentNode'; } - get texture() { + constructor( envNode = null ) { - return this.textures; + super(); + + this.envNode = envNode; } -} + setup( builder ) { -class Animation { + const { material } = builder; - constructor( nodes, info ) { + let envNode = this.envNode; - this.nodes = nodes; - this.info = info; + if ( envNode.isTextureNode || envNode.isMaterialReferenceNode ) { - this.animationLoop = null; - this.requestId = null; + const value = ( envNode.isTextureNode ) ? envNode.value : material[ envNode.property ]; - this._init(); + let cacheEnvNode = _envNodeCache.get( value ); - } + if ( cacheEnvNode === undefined ) { - _init() { - - const update = ( time, frame ) => { + cacheEnvNode = pmremTexture( value ); - this.requestId = self.requestAnimationFrame( update ); + _envNodeCache.set( value, cacheEnvNode ); - if ( this.info.autoReset === true ) this.info.reset(); + } - this.nodes.nodeFrame.update(); + envNode = cacheEnvNode; - this.info.frame = this.nodes.nodeFrame.frameId; + } - if ( this.animationLoop !== null ) this.animationLoop( time, frame ); + // - }; + const envMap = material.envMap; + const intensity = envMap ? reference( 'envMapIntensity', 'float', builder.material ) : reference( 'environmentIntensity', 'float', builder.scene ); // @TODO: Add materialEnvIntensity in MaterialNode - update(); + const useAnisotropy = material.useAnisotropy === true || material.anisotropy > 0; + const radianceNormalView = useAnisotropy ? transformedBentNormalView : transformedNormalView; - } + const radiance = envNode.context( createRadianceContext( roughness, radianceNormalView ) ).mul( intensity ); + const irradiance = envNode.context( createIrradianceContext( transformedNormalWorld ) ).mul( Math.PI ).mul( intensity ); - dispose() { + const isolateRadiance = cache( radiance ); + const isolateIrradiance = cache( irradiance ); - self.cancelAnimationFrame( this.requestId ); - this.requestId = null; + // - } + builder.context.radiance.addAssign( isolateRadiance ); - setAnimationLoop( callback ) { + builder.context.iblIrradiance.addAssign( isolateIrradiance ); - this.animationLoop = callback; + // - } + const clearcoatRadiance = builder.context.lightingModel.clearcoatRadiance; -} + if ( clearcoatRadiance ) { -class ChainMap { + const clearcoatRadianceContext = envNode.context( createRadianceContext( clearcoatRoughness, transformedClearcoatNormalView ) ).mul( intensity ); + const isolateClearcoatRadiance = cache( clearcoatRadianceContext ); - constructor() { + clearcoatRadiance.addAssign( isolateClearcoatRadiance ); - this.weakMap = new WeakMap(); + } } - get( keys ) { +} - let map = this.weakMap; +const createRadianceContext = ( roughnessNode, normalViewNode ) => { - for ( let i = 0; i < keys.length; i ++ ) { + let reflectVec = null; - map = map.get( keys[ i ] ); + return { + getUV: () => { - if ( map === undefined ) return undefined; + if ( reflectVec === null ) { - } + reflectVec = positionViewDirection.negate().reflect( normalViewNode ); - return map.get( keys[ keys.length - 1 ] ); + // Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane. + reflectVec = roughnessNode.mul( roughnessNode ).mix( reflectVec, normalViewNode ).normalize(); - } + reflectVec = reflectVec.transformDirection( cameraViewMatrix ); - set( keys, value ) { + } - let map = this.weakMap; + return reflectVec; - for ( let i = 0; i < keys.length; i ++ ) { + }, + getTextureLevel: () => { - const key = keys[ i ]; + return roughnessNode; - if ( map.has( key ) === false ) map.set( key, new WeakMap() ); + } + }; - map = map.get( key ); +}; - } +const createIrradianceContext = ( normalWorldNode ) => { - return map.set( keys[ keys.length - 1 ], value ); + return { + getUV: () => { - } + return normalWorldNode; - delete( keys ) { + }, + getTextureLevel: () => { - let map = this.weakMap; + return float( 1.0 ); - for ( let i = 0; i < keys.length; i ++ ) { + } + }; - map = map.get( keys[ i ] ); +}; - if ( map === undefined ) return false; +const _defaultValues$6 = /*@__PURE__*/ new MeshStandardMaterial(); - } +class MeshStandardNodeMaterial extends NodeMaterial { - return map.delete( keys[ keys.length - 1 ] ); + static get type() { - } + return 'MeshStandardNodeMaterial'; -} + } -const _plane = /*@__PURE__*/ new Plane(); + constructor( parameters ) { -class ClippingContext { + super(); - constructor() { + this.isMeshStandardNodeMaterial = true; - this.version = 0; + this.lights = true; - this.globalClippingCount = 0; + this.emissiveNode = null; - this.localClippingCount = 0; - this.localClippingEnabled = false; - this.localClipIntersection = false; + this.metalnessNode = null; + this.roughnessNode = null; - this.planes = []; + this.setDefaultValues( _defaultValues$6 ); - this.parentVersion = 0; - this.viewNormalMatrix = new Matrix3(); - this.cacheKey = ''; + this.setValues( parameters ); } - projectPlanes( source, offset ) { + setupEnvironment( builder ) { - const l = source.length; - const planes = this.planes; + let envNode = super.setupEnvironment( builder ); - for ( let i = 0; i < l; i ++ ) { + if ( envNode === null && builder.environmentNode ) { - _plane.copy( source[ i ] ).applyMatrix4( this.viewMatrix, this.viewNormalMatrix ); + envNode = builder.environmentNode; - const v = planes[ offset + i ]; - const normal = _plane.normal; + } - v.x = - normal.x; - v.y = - normal.y; - v.z = - normal.z; - v.w = _plane.constant; + return envNode ? new EnvironmentNode( envNode ) : null; - } + } + + setupLightingModel( /*builder*/ ) { + + return new PhysicalLightingModel(); } - updateGlobal( renderer, camera ) { + setupSpecular() { - const rendererClippingPlanes = renderer.clippingPlanes; - this.viewMatrix = camera.matrixWorldInverse; + const specularColorNode = mix( vec3( 0.04 ), diffuseColor.rgb, metalness ); - this.viewNormalMatrix.getNormalMatrix( this.viewMatrix ); + specularColor.assign( specularColorNode ); + specularF90.assign( 1.0 ); - let update = false; + } - if ( Array.isArray( rendererClippingPlanes ) && rendererClippingPlanes.length !== 0 ) { + setupVariants() { - const l = rendererClippingPlanes.length; + // METALNESS - if ( l !== this.globalClippingCount ) { + const metalnessNode = this.metalnessNode ? float( this.metalnessNode ) : materialMetalness; - const planes = []; + metalness.assign( metalnessNode ); - for ( let i = 0; i < l; i ++ ) { + // ROUGHNESS - planes.push( new Vector4() ); + let roughnessNode = this.roughnessNode ? float( this.roughnessNode ) : materialRoughness; + roughnessNode = getRoughness( { roughness: roughnessNode } ); - } + roughness.assign( roughnessNode ); - this.globalClippingCount = l; - this.planes = planes; + // SPECULAR COLOR - update = true; + this.setupSpecular(); - } + // DIFFUSE COLOR - this.projectPlanes( rendererClippingPlanes, 0 ); + diffuseColor.assign( vec4( diffuseColor.rgb.mul( metalnessNode.oneMinus() ), diffuseColor.a ) ); - } else if ( this.globalClippingCount !== 0 ) { + } - this.globalClippingCount = 0; - this.planes = []; - update = true; + copy( source ) { - } + this.emissiveNode = source.emissiveNode; - if ( renderer.localClippingEnabled !== this.localClippingEnabled ) { + this.metalnessNode = source.metalnessNode; + this.roughnessNode = source.roughnessNode; - this.localClippingEnabled = renderer.localClippingEnabled; - update = true; + return super.copy( source ); - } + } - if ( update ) { +} - this.version ++; - this.cacheKey = `${ this.globalClippingCount }:${ this.localClippingEnabled === undefined ? false : this.localClippingEnabled }:`; +const _defaultValues$5 = /*@__PURE__*/ new MeshPhysicalMaterial(); - } +class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { + + static get type() { + + return 'MeshPhysicalNodeMaterial'; } - update( parent, material ) { + constructor( parameters ) { - let update = false; + super(); - if ( this !== parent && parent.version !== this.parentVersion ) { + this.isMeshPhysicalNodeMaterial = true; - this.globalClippingCount = material.isShadowNodeMaterial ? 0 : parent.globalClippingCount; - this.localClippingEnabled = parent.localClippingEnabled; - this.planes = Array.from( parent.planes ); - this.parentVersion = parent.version; - this.viewMatrix = parent.viewMatrix; - this.viewNormalMatrix = parent.viewNormalMatrix; + this.clearcoatNode = null; + this.clearcoatRoughnessNode = null; + this.clearcoatNormalNode = null; - update = true; + this.sheenNode = null; + this.sheenRoughnessNode = null; - } + this.iridescenceNode = null; + this.iridescenceIORNode = null; + this.iridescenceThicknessNode = null; - if ( this.localClippingEnabled ) { + this.specularIntensityNode = null; + this.specularColorNode = null; - const localClippingPlanes = material.clippingPlanes; + this.iorNode = null; + this.transmissionNode = null; + this.thicknessNode = null; + this.attenuationDistanceNode = null; + this.attenuationColorNode = null; + this.dispersionNode = null; - if ( ( Array.isArray( localClippingPlanes ) && localClippingPlanes.length !== 0 ) ) { + this.anisotropyNode = null; - const l = localClippingPlanes.length; - const planes = this.planes; - const offset = this.globalClippingCount; + this.setDefaultValues( _defaultValues$5 ); - if ( update || l !== this.localClippingCount ) { + this.setValues( parameters ); - planes.length = offset + l; + } - for ( let i = 0; i < l; i ++ ) { + get useClearcoat() { - planes[ offset + i ] = new Vector4(); + return this.clearcoat > 0 || this.clearcoatNode !== null; - } + } - this.localClippingCount = l; - update = true; + get useIridescence() { - } + return this.iridescence > 0 || this.iridescenceNode !== null; - this.projectPlanes( localClippingPlanes, offset ); + } + get useSheen() { - } else if ( this.localClippingCount !== 0 ) { + return this.sheen > 0 || this.sheenNode !== null; - this.localClippingCount = 0; - update = true; + } - } + get useAnisotropy() { - if ( this.localClipIntersection !== material.clipIntersection ) { + return this.anisotropy > 0 || this.anisotropyNode !== null; - this.localClipIntersection = material.clipIntersection; - update = true; + } - } + get useTransmission() { - } + return this.transmission > 0 || this.transmissionNode !== null; - if ( update ) { + } - this.version += parent.version; - this.cacheKey = parent.cacheKey + `:${ this.localClippingCount }:${ this.localClipIntersection === undefined ? false : this.localClipIntersection }`; + get useDispersion() { - } + return this.dispersion > 0 || this.dispersionNode !== null; } -} - -let _id$7 = 0; + setupSpecular() { -function getKeys( obj ) { + const iorNode = this.iorNode ? float( this.iorNode ) : materialIOR; - const keys = Object.keys( obj ); + ior.assign( iorNode ); + specularColor.assign( mix( min$1( pow2( ior.sub( 1.0 ).div( ior.add( 1.0 ) ) ).mul( materialSpecularColor ), vec3( 1.0 ) ).mul( materialSpecularIntensity ), diffuseColor.rgb, metalness ) ); + specularF90.assign( mix( materialSpecularIntensity, 1.0, metalness ) ); - let proto = Object.getPrototypeOf( obj ); + } - while ( proto ) { + setupLightingModel( /*builder*/ ) { - const descriptors = Object.getOwnPropertyDescriptors( proto ); + return new PhysicalLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useAnisotropy, this.useTransmission, this.useDispersion ); - for ( const key in descriptors ) { + } - if ( descriptors[ key ] !== undefined ) { + setupVariants( builder ) { - const descriptor = descriptors[ key ]; + super.setupVariants( builder ); - if ( descriptor && typeof descriptor.get === 'function' ) { + // CLEARCOAT - keys.push( key ); + if ( this.useClearcoat ) { - } + const clearcoatNode = this.clearcoatNode ? float( this.clearcoatNode ) : materialClearcoat; + const clearcoatRoughnessNode = this.clearcoatRoughnessNode ? float( this.clearcoatRoughnessNode ) : materialClearcoatRoughness; - } + clearcoat.assign( clearcoatNode ); + clearcoatRoughness.assign( getRoughness( { roughness: clearcoatRoughnessNode } ) ); } - proto = Object.getPrototypeOf( proto ); + // SHEEN - } + if ( this.useSheen ) { - return keys; + const sheenNode = this.sheenNode ? vec3( this.sheenNode ) : materialSheen; + const sheenRoughnessNode = this.sheenRoughnessNode ? float( this.sheenRoughnessNode ) : materialSheenRoughness; -} + sheen.assign( sheenNode ); + sheenRoughness.assign( sheenRoughnessNode ); -class RenderObject { + } - constructor( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext ) { + // IRIDESCENCE - this._nodes = nodes; - this._geometries = geometries; + if ( this.useIridescence ) { - this.id = _id$7 ++; + const iridescenceNode = this.iridescenceNode ? float( this.iridescenceNode ) : materialIridescence; + const iridescenceIORNode = this.iridescenceIORNode ? float( this.iridescenceIORNode ) : materialIridescenceIOR; + const iridescenceThicknessNode = this.iridescenceThicknessNode ? float( this.iridescenceThicknessNode ) : materialIridescenceThickness; - this.renderer = renderer; - this.object = object; - this.material = material; - this.scene = scene; - this.camera = camera; - this.lightsNode = lightsNode; - this.context = renderContext; + iridescence.assign( iridescenceNode ); + iridescenceIOR.assign( iridescenceIORNode ); + iridescenceThickness.assign( iridescenceThicknessNode ); - this.geometry = object.geometry; - this.version = material.version; + } - this.drawRange = null; + // ANISOTROPY - this.attributes = null; - this.pipeline = null; - this.vertexBuffers = null; + if ( this.useAnisotropy ) { - this.updateClipping( renderContext.clippingContext ); + const anisotropyV = ( this.anisotropyNode ? vec2( this.anisotropyNode ) : materialAnisotropy ).toVar(); - this.clippingContextVersion = this.clippingContext.version; + anisotropy.assign( anisotropyV.length() ); - this.initialNodesCacheKey = this.getDynamicCacheKey(); - this.initialCacheKey = this.getCacheKey(); + If( anisotropy.equal( 0.0 ), () => { - this._nodeBuilderState = null; - this._bindings = null; + anisotropyV.assign( vec2( 1.0, 0.0 ) ); - this.onDispose = null; + } ).Else( () => { - this.isRenderObject = true; + anisotropyV.divAssign( vec2( anisotropy ) ); + anisotropy.assign( anisotropy.saturate() ); - this.onMaterialDispose = () => { + } ); - this.dispose(); + // Roughness along the anisotropy bitangent is the material roughness, while the tangent roughness increases with anisotropy. + alphaT.assign( anisotropy.pow2().mix( roughness.pow2(), 1.0 ) ); - }; + anisotropyT.assign( TBNViewMatrix[ 0 ].mul( anisotropyV.x ).add( TBNViewMatrix[ 1 ].mul( anisotropyV.y ) ) ); + anisotropyB.assign( TBNViewMatrix[ 1 ].mul( anisotropyV.x ).sub( TBNViewMatrix[ 0 ].mul( anisotropyV.y ) ) ); - this.material.addEventListener( 'dispose', this.onMaterialDispose ); + } - } + // TRANSMISSION - updateClipping( parent ) { + if ( this.useTransmission ) { - const material = this.material; + const transmissionNode = this.transmissionNode ? float( this.transmissionNode ) : materialTransmission; + const thicknessNode = this.thicknessNode ? float( this.thicknessNode ) : materialThickness; + const attenuationDistanceNode = this.attenuationDistanceNode ? float( this.attenuationDistanceNode ) : materialAttenuationDistance; + const attenuationColorNode = this.attenuationColorNode ? vec3( this.attenuationColorNode ) : materialAttenuationColor; - let clippingContext = this.clippingContext; + transmission.assign( transmissionNode ); + thickness.assign( thicknessNode ); + attenuationDistance.assign( attenuationDistanceNode ); + attenuationColor.assign( attenuationColorNode ); - if ( Array.isArray( material.clippingPlanes ) ) { + if ( this.useDispersion ) { - if ( clippingContext === parent || ! clippingContext ) { + const dispersionNode = this.dispersionNode ? float( this.dispersionNode ) : materialDispersion; - clippingContext = new ClippingContext(); - this.clippingContext = clippingContext; + dispersion.assign( dispersionNode ); } - clippingContext.update( parent, material ); + } - } else if ( this.clippingContext !== parent ) { + } - this.clippingContext = parent; + setupClearcoatNormal() { - } + return this.clearcoatNormalNode ? vec3( this.clearcoatNormalNode ) : materialClearcoatNormal; } - get clippingNeedsUpdate() { - - if ( this.clippingContext.version === this.clippingContextVersion ) return false; + setup( builder ) { - this.clippingContextVersion = this.clippingContext.version; + builder.context.setupClearcoatNormal = () => this.setupClearcoatNormal( builder ); - return true; + super.setup( builder ); } - getNodeBuilderState() { + copy( source ) { - return this._nodeBuilderState || ( this._nodeBuilderState = this._nodes.getForRender( this ) ); + this.clearcoatNode = source.clearcoatNode; + this.clearcoatRoughnessNode = source.clearcoatRoughnessNode; + this.clearcoatNormalNode = source.clearcoatNormalNode; - } + this.sheenNode = source.sheenNode; + this.sheenRoughnessNode = source.sheenRoughnessNode; - getBindings() { + this.iridescenceNode = source.iridescenceNode; + this.iridescenceIORNode = source.iridescenceIORNode; + this.iridescenceThicknessNode = source.iridescenceThicknessNode; - return this._bindings || ( this._bindings = this.getNodeBuilderState().createBindings() ); + this.specularIntensityNode = source.specularIntensityNode; + this.specularColorNode = source.specularColorNode; - } + this.transmissionNode = source.transmissionNode; + this.thicknessNode = source.thicknessNode; + this.attenuationDistanceNode = source.attenuationDistanceNode; + this.attenuationColorNode = source.attenuationColorNode; + this.dispersionNode = source.dispersionNode; - getIndex() { + this.anisotropyNode = source.anisotropyNode; - return this._geometries.getIndex( this ); + return super.copy( source ); } - getChainArray() { +} - return [ this.object, this.material, this.context, this.lightsNode ]; +class SSSLightingModel extends PhysicalLightingModel { - } + constructor( useClearcoat, useSheen, useIridescence, useSSS ) { - getAttributes() { + super( useClearcoat, useSheen, useIridescence ); - if ( this.attributes !== null ) return this.attributes; + this.useSSS = useSSS; - const nodeAttributes = this.getNodeBuilderState().nodeAttributes; - const geometry = this.geometry; + } - const attributes = []; - const vertexBuffers = new Set(); + direct( { lightDirection, lightColor, reflectedLight }, stack, builder ) { - for ( const nodeAttribute of nodeAttributes ) { + if ( this.useSSS === true ) { - const attribute = nodeAttribute.node && nodeAttribute.node.attribute ? nodeAttribute.node.attribute : geometry.getAttribute( nodeAttribute.name ); + const material = builder.material; - if ( attribute === undefined ) continue; + const { thicknessColorNode, thicknessDistortionNode, thicknessAmbientNode, thicknessAttenuationNode, thicknessPowerNode, thicknessScaleNode } = material; - attributes.push( attribute ); + const scatteringHalf = lightDirection.add( transformedNormalView.mul( thicknessDistortionNode ) ).normalize(); + const scatteringDot = float( positionViewDirection.dot( scatteringHalf.negate() ).saturate().pow( thicknessPowerNode ).mul( thicknessScaleNode ) ); + const scatteringIllu = vec3( scatteringDot.add( thicknessAmbientNode ).mul( thicknessColorNode ) ); - const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute; - vertexBuffers.add( bufferAttribute ); + reflectedLight.directDiffuse.addAssign( scatteringIllu.mul( thicknessAttenuationNode.mul( lightColor ) ) ); } - this.attributes = attributes; - this.vertexBuffers = Array.from( vertexBuffers.values() ); - - return attributes; + super.direct( { lightDirection, lightColor, reflectedLight }, stack, builder ); } - getVertexBuffers() { - - if ( this.vertexBuffers === null ) this.getAttributes(); +} - return this.vertexBuffers; +class MeshSSSNodeMaterial extends MeshPhysicalNodeMaterial { - } + static get type() { - getMaterialCacheKey() { + return 'MeshSSSNodeMaterial'; - const { object, material } = this; + } - let cacheKey = material.customProgramCacheKey(); + constructor( parameters ) { - for ( const property of getKeys( material ) ) { + super( parameters ); - if ( /^(is[A-Z]|_)|^(visible|version|uuid|name|opacity|userData)$/.test( property ) ) continue; + this.thicknessColorNode = null; + this.thicknessDistortionNode = float( 0.1 ); + this.thicknessAmbientNode = float( 0.0 ); + this.thicknessAttenuationNode = float( .1 ); + this.thicknessPowerNode = float( 2.0 ); + this.thicknessScaleNode = float( 10.0 ); - const value = material[ property ]; + } - let valueKey; + get useSSS() { - if ( value !== null ) { + return this.thicknessColorNode !== null; - // some material values require a formatting + } - const type = typeof value; + setupLightingModel( /*builder*/ ) { - if ( type === 'number' ) { + return new SSSLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useSSS ); - valueKey = value !== 0 ? '1' : '0'; // Convert to on/off, important for clearcoat, transmission, etc + } - } else if ( type === 'object' ) { + copy( source ) { - valueKey = '{'; + this.thicknessColorNode = source.thicknessColorNode; + this.thicknessDistortionNode = source.thicknessDistortionNode; + this.thicknessAmbientNode = source.thicknessAmbientNode; + this.thicknessAttenuationNode = source.thicknessAttenuationNode; + this.thicknessPowerNode = source.thicknessPowerNode; + this.thicknessScaleNode = source.thicknessScaleNode; - if ( value.isTexture ) { + return super.copy( source ); - valueKey += value.mapping; + } - } +} - valueKey += '}'; +const getGradientIrradiance = /*@__PURE__*/ Fn( ( { normal, lightDirection, builder } ) => { - } else { + // dotNL will be from -1.0 to 1.0 + const dotNL = normal.dot( lightDirection ); + const coord = vec2( dotNL.mul( 0.5 ).add( 0.5 ), 0.0 ); - valueKey = String( value ); + if ( builder.material.gradientMap ) { - } + const gradientMap = materialReference( 'gradientMap', 'texture' ).context( { getUV: () => coord } ); - } else { + return vec3( gradientMap.r ); - valueKey = String( value ); + } else { - } + const fw = coord.fwidth().mul( 0.5 ); - cacheKey += /*property + ':' +*/ valueKey + ','; + return mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( float( 0.7 ).sub( fw.x ), float( 0.7 ).add( fw.x ), coord.x ) ); - } + } - cacheKey += this.clippingContext.cacheKey + ','; +} ); - if ( object.skeleton ) { +class ToonLightingModel extends LightingModel { - cacheKey += object.skeleton.bones.length + ','; + direct( { lightDirection, lightColor, reflectedLight }, stack, builder ) { - } + const irradiance = getGradientIrradiance( { normal: normalGeometry, lightDirection, builder } ).mul( lightColor ); - if ( object.morphTargetInfluences ) { + reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) ); - cacheKey += object.morphTargetInfluences.length + ','; + } - } + indirect( { ambientOcclusion, irradiance, reflectedLight } ) { - if ( object.isBatchedMesh ) { + reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) ); - cacheKey += object._matricesTexture.uuid + ','; + reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion ); - if ( object._colorsTexture !== null ) { + } - cacheKey += object._colorsTexture.uuid + ','; +} - } +const _defaultValues$4 = /*@__PURE__*/ new MeshToonMaterial(); - } +class MeshToonNodeMaterial extends NodeMaterial { - if ( object.count > 1 ) { + static get type() { - cacheKey += object.count + ',' + object.uuid + ','; + return 'MeshToonNodeMaterial'; - } + } - return cacheKey; + constructor( parameters ) { + + super(); + + this.isMeshToonNodeMaterial = true; + + this.lights = true; + + this.setDefaultValues( _defaultValues$4 ); + + this.setValues( parameters ); } - get needsUpdate() { + setupLightingModel( /*builder*/ ) { - return this.initialNodesCacheKey !== this.getDynamicCacheKey() || this.clippingNeedsUpdate; + return new ToonLightingModel(); } - getDynamicCacheKey() { +} - // Environment Nodes Cache Key +class MatcapUVNode extends TempNode { + + static get type() { - return this.object.receiveShadow + ',' + this._nodes.getCacheKey( this.scene, this.lightsNode ); + return 'MatcapUVNode'; } - getCacheKey() { + constructor() { - return this.getMaterialCacheKey() + ',' + this.getDynamicCacheKey(); + super( 'vec2' ); } - dispose() { + setup() { - this.material.removeEventListener( 'dispose', this.onMaterialDispose ); + const x = vec3( positionViewDirection.z, 0, positionViewDirection.x.negate() ).normalize(); + const y = positionViewDirection.cross( x ); - this.onDispose(); + return vec2( x.dot( transformedNormalView ), y.dot( transformedNormalView ) ).mul( 0.495 ).add( 0.5 ); // 0.495 to remove artifacts caused by undersized matcap disks } } -class RenderObjects { - - constructor( renderer, nodes, geometries, pipelines, bindings, info ) { +const matcapUV = /*@__PURE__*/ nodeImmutable( MatcapUVNode ); - this.renderer = renderer; - this.nodes = nodes; - this.geometries = geometries; - this.pipelines = pipelines; - this.bindings = bindings; - this.info = info; +const _defaultValues$3 = /*@__PURE__*/ new MeshMatcapMaterial(); - this.chainMaps = {}; +class MeshMatcapNodeMaterial extends NodeMaterial { - } + static get type() { - get( object, material, scene, camera, lightsNode, renderContext, passId ) { + return 'MeshMatcapNodeMaterial'; - const chainMap = this.getChainMap( passId ); - const chainArray = [ object, material, renderContext, lightsNode ]; + } - let renderObject = chainMap.get( chainArray ); + constructor( parameters ) { - if ( renderObject === undefined ) { + super(); - renderObject = this.createRenderObject( this.nodes, this.geometries, this.renderer, object, material, scene, camera, lightsNode, renderContext, passId ); + this.lights = false; - chainMap.set( chainArray, renderObject ); + this.isMeshMatcapNodeMaterial = true; - } else { + this.setDefaultValues( _defaultValues$3 ); - renderObject.updateClipping( renderContext.clippingContext ); + this.setValues( parameters ); - if ( renderObject.version !== material.version || renderObject.needsUpdate ) { + } - if ( renderObject.initialCacheKey !== renderObject.getCacheKey() ) { + setupVariants( builder ) { - renderObject.dispose(); + const uv = matcapUV; - renderObject = this.get( object, material, scene, camera, lightsNode, renderContext, passId ); + let matcapColor; - } else { + if ( builder.material.matcap ) { - renderObject.version = material.version; + matcapColor = materialReference( 'matcap', 'texture' ).context( { getUV: () => uv } ); - } + } else { - } + matcapColor = vec3( mix( 0.2, 0.8, uv.y ) ); // default if matcap is missing } - return renderObject; + diffuseColor.rgb.mulAssign( matcapColor.rgb ); } - getChainMap( passId = 'default' ) { +} - return this.chainMaps[ passId ] || ( this.chainMaps[ passId ] = new ChainMap() ); +const _defaultValues$2 = /*@__PURE__*/ new PointsMaterial(); - } +class PointsNodeMaterial extends NodeMaterial { - dispose() { + static get type() { - this.chainMaps = {}; + return 'PointsNodeMaterial'; } - createRenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext, passId ) { - - const chainMap = this.getChainMap( passId ); + constructor( parameters ) { - const renderObject = new RenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext ); + super(); - renderObject.onDispose = () => { + this.isPointsNodeMaterial = true; - this.pipelines.delete( renderObject ); - this.bindings.delete( renderObject ); - this.nodes.delete( renderObject ); + this.lights = false; + this.transparent = true; - chainMap.delete( renderObject.getChainArray() ); + this.sizeNode = null; - }; + this.setDefaultValues( _defaultValues$2 ); - return renderObject; + this.setValues( parameters ); } + copy( source ) { -} + this.sizeNode = source.sizeNode; -class DataMap { + return super.copy( source ); - constructor() { + } - this.data = new WeakMap(); +} - } +class RotateNode extends TempNode { - get( object ) { + static get type() { - let map = this.data.get( object ); + return 'RotateNode'; - if ( map === undefined ) { + } - map = {}; - this.data.set( object, map ); + constructor( positionNode, rotationNode ) { - } + super(); - return map; + this.positionNode = positionNode; + this.rotationNode = rotationNode; } - delete( object ) { + getNodeType( builder ) { - let map; + return this.positionNode.getNodeType( builder ); - if ( this.data.has( object ) ) { + } - map = this.data.get( object ); + setup( builder ) { - this.data.delete( object ); + const { rotationNode, positionNode } = this; - } + const nodeType = this.getNodeType( builder ); - return map; + if ( nodeType === 'vec2' ) { - } + const cosAngle = rotationNode.cos(); + const sinAngle = rotationNode.sin(); - has( object ) { + const rotationMatrix = mat2( + cosAngle, sinAngle, + sinAngle.negate(), cosAngle + ); - return this.data.has( object ); + return rotationMatrix.mul( positionNode ); - } + } else { - dispose() { + const rotation = rotationNode; + const rotationXMatrix = mat4( vec4( 1.0, 0.0, 0.0, 0.0 ), vec4( 0.0, cos( rotation.x ), sin( rotation.x ).negate(), 0.0 ), vec4( 0.0, sin( rotation.x ), cos( rotation.x ), 0.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) ); + const rotationYMatrix = mat4( vec4( cos( rotation.y ), 0.0, sin( rotation.y ), 0.0 ), vec4( 0.0, 1.0, 0.0, 0.0 ), vec4( sin( rotation.y ).negate(), 0.0, cos( rotation.y ), 0.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) ); + const rotationZMatrix = mat4( vec4( cos( rotation.z ), sin( rotation.z ).negate(), 0.0, 0.0 ), vec4( sin( rotation.z ), cos( rotation.z ), 0.0, 0.0 ), vec4( 0.0, 0.0, 1.0, 0.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) ); - this.data = new WeakMap(); + return rotationXMatrix.mul( rotationYMatrix ).mul( rotationZMatrix ).mul( vec4( positionNode, 1.0 ) ).xyz; + + } } } -const AttributeType = { - VERTEX: 1, - INDEX: 2, - STORAGE: 4 -}; +const rotate = /*@__PURE__*/ nodeProxy( RotateNode ); -// size of a chunk in bytes (STD140 layout) +const _defaultValues$1 = /*@__PURE__*/ new SpriteMaterial(); -const GPU_CHUNK_BYTES = 16; +class SpriteNodeMaterial extends NodeMaterial { -// @TODO: Move to src/constants.js + static get type() { -const BlendColorFactor = 211; -const OneMinusBlendColorFactor = 212; + return 'SpriteNodeMaterial'; -class Attributes extends DataMap { + } - constructor( backend ) { + constructor( parameters ) { super(); - this.backend = backend; - - } - - delete( attribute ) { - - const attributeData = super.delete( attribute ); + this.isSpriteNodeMaterial = true; - if ( attributeData !== undefined ) { + this.lights = false; + this._useSizeAttenuation = true; - this.backend.destroyAttribute( attribute ); + this.positionNode = null; + this.rotationNode = null; + this.scaleNode = null; - } + this.setDefaultValues( _defaultValues$1 ); - return attributeData; + this.setValues( parameters ); } - update( attribute, type ) { + setupPosition( { object, camera, context } ) { - const data = this.get( attribute ); + const sizeAttenuation = this.sizeAttenuation; - if ( data.version === undefined ) { + // < VERTEX STAGE > - if ( type === AttributeType.VERTEX ) { + const { positionNode, rotationNode, scaleNode } = this; - this.backend.createAttribute( attribute ); + const vertex = positionLocal; - } else if ( type === AttributeType.INDEX ) { + let mvPosition = modelViewMatrix.mul( vec3( positionNode || 0 ) ); - this.backend.createIndexAttribute( attribute ); + let scale = vec2( modelWorldMatrix[ 0 ].xyz.length(), modelWorldMatrix[ 1 ].xyz.length() ); - } else if ( type === AttributeType.STORAGE ) { + if ( scaleNode !== null ) { - this.backend.createStorageAttribute( attribute ); + scale = scale.mul( scaleNode ); - } + } - data.version = this._getBufferAttribute( attribute ).version; - } else { + if ( ! sizeAttenuation && camera.isPerspectiveCamera ) { - const bufferAttribute = this._getBufferAttribute( attribute ); + scale = scale.mul( mvPosition.z.negate() ); - if ( data.version < bufferAttribute.version || bufferAttribute.usage === DynamicDrawUsage ) { + } - this.backend.updateAttribute( attribute ); + let alignedPosition = vertex.xy; - data.version = bufferAttribute.version; + if ( object.center && object.center.isVector2 === true ) { - } + const center = reference$1( 'center', 'vec2' ); + + alignedPosition = alignedPosition.sub( center.sub( 0.5 ) ); } - } + alignedPosition = alignedPosition.mul( scale ); - _getBufferAttribute( attribute ) { + const rotation = float( rotationNode || materialRotation ); - if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; + const rotatedPosition = rotate( alignedPosition, rotation ); - return attribute; + mvPosition = vec4( mvPosition.xy.add( rotatedPosition ), mvPosition.zw ); - } + const modelViewProjection = cameraProjectionMatrix.mul( mvPosition ); -} + context.vertex = vertex; -function arrayNeedsUint32( array ) { + return modelViewProjection; - // assumes larger values usually on last + } - for ( let i = array.length - 1; i >= 0; -- i ) { + copy( source ) { - if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565 + this.positionNode = source.positionNode; + this.rotationNode = source.rotationNode; + this.scaleNode = source.scaleNode; + + return super.copy( source ); } - return false; + get sizeAttenuation() { -} + return this._useSizeAttenuation; -function getWireframeVersion( geometry ) { + } - return ( geometry.index !== null ) ? geometry.index.version : geometry.attributes.position.version; + set sizeAttenuation( value ) { -} + if ( this._useSizeAttenuation !== value ) { -function getWireframeIndex( geometry ) { + this._useSizeAttenuation = value; + this.needsUpdate = true; - const indices = []; + } - const geometryIndex = geometry.index; - const geometryPosition = geometry.attributes.position; + } - if ( geometryIndex !== null ) { +} - const array = geometryIndex.array; +class ShadowMaskModel extends LightingModel { - for ( let i = 0, l = array.length; i < l; i += 3 ) { + constructor() { - const a = array[ i + 0 ]; - const b = array[ i + 1 ]; - const c = array[ i + 2 ]; + super(); - indices.push( a, b, b, c, c, a ); + this.shadowNode = float( 1 ).toVar( 'shadowMask' ); - } + } - } else { + direct( { shadowMask } ) { - const array = geometryPosition.array; + this.shadowNode.mulAssign( shadowMask ); - for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) { + } - const a = i + 0; - const b = i + 1; - const c = i + 2; + finish( context ) { - indices.push( a, b, b, c, c, a ); + diffuseColor.a.mulAssign( this.shadowNode.oneMinus() ); - } + context.outgoingLight.rgb.assign( diffuseColor.rgb ); // TODO: Optimize LightsNode to avoid this assignment } - const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); - attribute.version = getWireframeVersion( geometry ); - - return attribute; - } -class Geometries extends DataMap { +const _defaultValues = /*@__PURE__*/ new ShadowMaterial(); - constructor( attributes, info ) { +class ShadowNodeMaterial extends NodeMaterial { - super(); + static get type() { - this.attributes = attributes; - this.info = info; + return 'ShadowNodeMaterial'; - this.wireframes = new WeakMap(); + } - this.attributeCall = new WeakMap(); + constructor( parameters ) { - } + super(); - has( renderObject ) { + this.isShadowNodeMaterial = true; - const geometry = renderObject.geometry; + this.lights = true; - return super.has( geometry ) && this.get( geometry ).initialized === true; + this.setDefaultValues( _defaultValues ); - } + this.setValues( parameters ); - updateForRender( renderObject ) { + } - if ( this.has( renderObject ) === false ) this.initGeometry( renderObject ); + setupLightingModel( /*builder*/ ) { - this.updateAttributes( renderObject ); + return new ShadowMaskModel(); } - initGeometry( renderObject ) { +} - const geometry = renderObject.geometry; - const geometryData = this.get( geometry ); +const normal = Fn( ( { texture, uv } ) => { - geometryData.initialized = true; + const epsilon = 0.0001; - this.info.memory.geometries ++; + const ret = vec3().toVar(); - const onDispose = () => { + If( uv.x.lessThan( epsilon ), () => { - this.info.memory.geometries --; + ret.assign( vec3( 1, 0, 0 ) ); - const index = geometry.index; - const geometryAttributes = renderObject.getAttributes(); + } ).ElseIf( uv.y.lessThan( epsilon ), () => { - if ( index !== null ) { + ret.assign( vec3( 0, 1, 0 ) ); - this.attributes.delete( index ); + } ).ElseIf( uv.z.lessThan( epsilon ), () => { - } + ret.assign( vec3( 0, 0, 1 ) ); - for ( const geometryAttribute of geometryAttributes ) { + } ).ElseIf( uv.x.greaterThan( 1 - epsilon ), () => { - this.attributes.delete( geometryAttribute ); + ret.assign( vec3( - 1, 0, 0 ) ); - } + } ).ElseIf( uv.y.greaterThan( 1 - epsilon ), () => { - const wireframeAttribute = this.wireframes.get( geometry ); + ret.assign( vec3( 0, - 1, 0 ) ); - if ( wireframeAttribute !== undefined ) { + } ).ElseIf( uv.z.greaterThan( 1 - epsilon ), () => { - this.attributes.delete( wireframeAttribute ); + ret.assign( vec3( 0, 0, - 1 ) ); - } + } ).Else( () => { - geometry.removeEventListener( 'dispose', onDispose ); + const step = 0.01; - }; + const x = texture.uv( uv.add( vec3( - step, 0.0, 0.0 ) ) ).r.sub( texture.uv( uv.add( vec3( step, 0.0, 0.0 ) ) ).r ); + const y = texture.uv( uv.add( vec3( 0.0, - step, 0.0 ) ) ).r.sub( texture.uv( uv.add( vec3( 0.0, step, 0.0 ) ) ).r ); + const z = texture.uv( uv.add( vec3( 0.0, 0.0, - step ) ) ).r.sub( texture.uv( uv.add( vec3( 0.0, 0.0, step ) ) ).r ); - geometry.addEventListener( 'dispose', onDispose ); + ret.assign( vec3( x, y, z ) ); - } + } ); - updateAttributes( renderObject ) { + return ret.normalize(); - const attributes = renderObject.getAttributes(); +} ); - for ( const attribute of attributes ) { - if ( attribute.isStorageBufferAttribute || attribute.isStorageInstancedBufferAttribute ) { +class Texture3DNode extends TextureNode { - this.updateAttribute( attribute, AttributeType.STORAGE ); + static get type() { - } else { + return 'Texture3DNode'; - this.updateAttribute( attribute, AttributeType.VERTEX ); + } - } + constructor( value, uvNode = null, levelNode = null ) { - } + super( value, uvNode, levelNode ); - const index = this.getIndex( renderObject ); + this.isTexture3DNode = true; - if ( index !== null ) { + } - this.updateAttribute( index, AttributeType.INDEX ); + getInputType( /*builder*/ ) { - } + return 'texture3D'; } - updateAttribute( attribute, type ) { + getDefaultUV() { - const callId = this.info.render.calls; + return vec3( 0.5, 0.5, 0.5 ); - if ( ! attribute.isInterleavedBufferAttribute ) { + } - if ( this.attributeCall.get( attribute ) !== callId ) { + setUpdateMatrix( /*updateMatrix*/ ) { } // Ignore .updateMatrix for 3d TextureNode - this.attributes.update( attribute, type ); + setupUV( builder, uvNode ) { - this.attributeCall.set( attribute, callId ); + return uvNode; - } + } - } else { + generateUV( builder, uvNode ) { - if ( this.attributeCall.get( attribute ) === undefined ) { + return uvNode.build( builder, 'vec3' ); - this.attributes.update( attribute, type ); + } - this.attributeCall.set( attribute, callId ); + normal( uvNode ) { - } else if ( this.attributeCall.get( attribute.data ) !== callId ) { + return normal( { texture: this, uv: uvNode } ); - this.attributes.update( attribute, type ); + } - this.attributeCall.set( attribute.data, callId ); +} - this.attributeCall.set( attribute, callId ); +const texture3D = /*@__PURE__*/ nodeProxy( Texture3DNode ); - } +class VolumeNodeMaterial extends NodeMaterial { - } + static get type() { - } + return 'VolumeNodeMaterial'; - getIndex( renderObject ) { + } - const { geometry, material } = renderObject; + constructor( params = {} ) { - let index = geometry.index; + super(); - if ( material.wireframe === true ) { + this.lights = false; + this.isVolumeNodeMaterial = true; + this.testNode = null; - const wireframes = this.wireframes; + this.setValues( params ); - let wireframeAttribute = wireframes.get( geometry ); + } - if ( wireframeAttribute === undefined ) { + setup( builder ) { - wireframeAttribute = getWireframeIndex( geometry ); + const map = texture3D( this.map, null, 0 ); - wireframes.set( geometry, wireframeAttribute ); + const hitBox = Fn( ( { orig, dir } ) => { - } else if ( wireframeAttribute.version !== getWireframeVersion( geometry ) ) { + const box_min = vec3( - 0.5 ); + const box_max = vec3( 0.5 ); - this.attributes.delete( wireframeAttribute ); + const inv_dir = dir.reciprocal(); - wireframeAttribute = getWireframeIndex( geometry ); + const tmin_tmp = box_min.sub( orig ).mul( inv_dir ); + const tmax_tmp = box_max.sub( orig ).mul( inv_dir ); - wireframes.set( geometry, wireframeAttribute ); + const tmin = min$1( tmin_tmp, tmax_tmp ); + const tmax = max$1( tmin_tmp, tmax_tmp ); - } + const t0 = max$1( tmin.x, max$1( tmin.y, tmin.z ) ); + const t1 = min$1( tmax.x, min$1( tmax.y, tmax.z ) ); - index = wireframeAttribute; + return vec2( t0, t1 ); - } + } ); - return index; + this.fragmentNode = Fn( () => { - } + const vOrigin = varying( vec3( modelWorldMatrixInverse.mul( vec4( cameraPosition, 1.0 ) ) ) ); + const vDirection = varying( positionGeometry.sub( vOrigin ) ); -} + const rayDir = vDirection.normalize(); + const bounds = vec2( hitBox( { orig: vOrigin, dir: rayDir } ) ).toVar(); -class Info { + bounds.x.greaterThan( bounds.y ).discard(); - constructor() { + bounds.assign( vec2( max$1( bounds.x, 0.0 ), bounds.y ) ); - this.autoReset = true; + const p = vec3( vOrigin.add( bounds.x.mul( rayDir ) ) ).toVar(); + const inc = vec3( rayDir.abs().reciprocal() ).toVar(); + const delta = float( min$1( inc.x, min$1( inc.y, inc.z ) ) ).toVar( 'delta' ); // used 'delta' name in loop - this.frame = 0; - this.calls = 0; + delta.divAssign( materialReference( 'steps', 'float' ) ); - this.render = { - calls: 0, - frameCalls: 0, - drawCalls: 0, - triangles: 0, - points: 0, - lines: 0, - timestamp: 0, - previousFrameCalls: 0, - timestampCalls: 0 - }; + const ac = vec4( materialReference( 'base', 'color' ), 0.0 ).toVar(); - this.compute = { - calls: 0, - frameCalls: 0, - timestamp: 0, - previousFrameCalls: 0, - timestampCalls: 0 - }; + Loop( { type: 'float', start: bounds.x, end: bounds.y, update: '+= delta' }, () => { - this.memory = { - geometries: 0, - textures: 0 - }; + const d = property( 'float', 'd' ).assign( map.uv( p.add( 0.5 ) ).r ); - } + if ( this.testNode !== null ) { - update( object, count, instanceCount ) { + this.testNode( { map: map, mapValue: d, probe: p, finalColor: ac } ).append(); - this.render.drawCalls ++; + } else { - if ( object.isMesh || object.isSprite ) { + // default to show surface of mesh + ac.a.assign( 1 ); + Break(); - this.render.triangles += instanceCount * ( count / 3 ); + } - } else if ( object.isPoints ) { + p.addAssign( rayDir.mul( delta ) ); - this.render.points += instanceCount * count; + } ); - } else if ( object.isLineSegments ) { + ac.a.equal( 0 ).discard(); - this.render.lines += instanceCount * ( count / 2 ); + return vec4( ac ); - } else if ( object.isLine ) { + } )(); - this.render.lines += instanceCount * ( count - 1 ); + super.setup( builder ); - } else { + } - console.error( 'THREE.WebGPUInfo: Unknown object type.' ); +} - } +class Animation { + + constructor( nodes, info ) { + + this.nodes = nodes; + this.info = info; + + this.animationLoop = null; + this.requestId = null; + + this._init(); } - updateTimestamp( type, time ) { + _init() { - if ( this[ type ].timestampCalls === 0 ) { + const update = ( time, frame ) => { - this[ type ].timestamp = 0; + this.requestId = self.requestAnimationFrame( update ); - } + if ( this.info.autoReset === true ) this.info.reset(); + this.nodes.nodeFrame.update(); - this[ type ].timestamp += time; + this.info.frame = this.nodes.nodeFrame.frameId; - this[ type ].timestampCalls ++; + if ( this.animationLoop !== null ) this.animationLoop( time, frame ); + }; - if ( this[ type ].timestampCalls >= this[ type ].previousFrameCalls ) { + update(); - this[ type ].timestampCalls = 0; + } - } + dispose() { + self.cancelAnimationFrame( this.requestId ); + this.requestId = null; } - reset() { + setAnimationLoop( callback ) { - const previousRenderFrameCalls = this.render.frameCalls; - this.render.previousFrameCalls = previousRenderFrameCalls; + this.animationLoop = callback; - const previousComputeFrameCalls = this.compute.frameCalls; - this.compute.previousFrameCalls = previousComputeFrameCalls; + } +} - this.render.drawCalls = 0; - this.render.frameCalls = 0; - this.compute.frameCalls = 0; +class ChainMap { - this.render.triangles = 0; - this.render.points = 0; - this.render.lines = 0; + constructor() { + this.weakMap = new WeakMap(); } - dispose() { - - this.reset(); + get( keys ) { - this.calls = 0; + let map = this.weakMap; - this.render.calls = 0; - this.compute.calls = 0; + for ( let i = 0; i < keys.length; i ++ ) { - this.render.timestamp = 0; - this.compute.timestamp = 0; - this.memory.geometries = 0; - this.memory.textures = 0; + map = map.get( keys[ i ] ); - } + if ( map === undefined ) return undefined; -} + } -class Pipeline { + return map.get( keys[ keys.length - 1 ] ); - constructor( cacheKey ) { + } - this.cacheKey = cacheKey; + set( keys, value ) { - this.usedTimes = 0; + let map = this.weakMap; - } + for ( let i = 0; i < keys.length; i ++ ) { -} + const key = keys[ i ]; -class RenderPipeline extends Pipeline { + if ( map.has( key ) === false ) map.set( key, new WeakMap() ); - constructor( cacheKey, vertexProgram, fragmentProgram ) { + map = map.get( key ); - super( cacheKey ); + } - this.vertexProgram = vertexProgram; - this.fragmentProgram = fragmentProgram; + return map.set( keys[ keys.length - 1 ], value ); } -} + delete( keys ) { -class ComputePipeline extends Pipeline { + let map = this.weakMap; - constructor( cacheKey, computeProgram ) { + for ( let i = 0; i < keys.length; i ++ ) { - super( cacheKey ); + map = map.get( keys[ i ] ); - this.computeProgram = computeProgram; + if ( map === undefined ) return false; - this.isComputePipeline = true; + } + + return map.delete( keys[ keys.length - 1 ] ); } } -let _id$6 = 0; +const _plane = /*@__PURE__*/ new Plane(); -class ProgrammableStage { +class ClippingContext { - constructor( code, type, transforms = null, attributes = null ) { + constructor() { - this.id = _id$6 ++; + this.version = 0; - this.code = code; - this.stage = type; - this.transforms = transforms; - this.attributes = attributes; + this.globalClippingCount = 0; - this.usedTimes = 0; + this.localClippingCount = 0; + this.localClippingEnabled = false; + this.localClipIntersection = false; + + this.planes = []; + + this.parentVersion = 0; + this.viewNormalMatrix = new Matrix3(); + this.cacheKey = 0; } -} + projectPlanes( source, offset ) { -class Pipelines extends DataMap { + const l = source.length; + const planes = this.planes; - constructor( backend, nodes ) { + for ( let i = 0; i < l; i ++ ) { - super(); + _plane.copy( source[ i ] ).applyMatrix4( this.viewMatrix, this.viewNormalMatrix ); - this.backend = backend; - this.nodes = nodes; + const v = planes[ offset + i ]; + const normal = _plane.normal; - this.bindings = null; // set by the bindings + v.x = - normal.x; + v.y = - normal.y; + v.z = - normal.z; + v.w = _plane.constant; - this.caches = new Map(); - this.programs = { - vertex: new Map(), - fragment: new Map(), - compute: new Map() - }; + } } - getForCompute( computeNode, bindings ) { + updateGlobal( renderer, camera ) { - const { backend } = this; + const rendererClippingPlanes = renderer.clippingPlanes; + this.viewMatrix = camera.matrixWorldInverse; - const data = this.get( computeNode ); + this.viewNormalMatrix.getNormalMatrix( this.viewMatrix ); - if ( this._needsComputeUpdate( computeNode ) ) { + let update = false; - const previousPipeline = data.pipeline; + if ( Array.isArray( rendererClippingPlanes ) && rendererClippingPlanes.length !== 0 ) { - if ( previousPipeline ) { + const l = rendererClippingPlanes.length; - previousPipeline.usedTimes --; - previousPipeline.computeProgram.usedTimes --; + if ( l !== this.globalClippingCount ) { - } + const planes = []; - // get shader + for ( let i = 0; i < l; i ++ ) { - const nodeBuilderState = this.nodes.getForCompute( computeNode ); + planes.push( new Vector4() ); - // programmable stage + } - let stageCompute = this.programs.compute.get( nodeBuilderState.computeShader ); + this.globalClippingCount = l; + this.planes = planes; - if ( stageCompute === undefined ) { + update = true; - if ( previousPipeline && previousPipeline.computeProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.computeProgram ); + } - stageCompute = new ProgrammableStage( nodeBuilderState.computeShader, 'compute', nodeBuilderState.transforms, nodeBuilderState.nodeAttributes ); - this.programs.compute.set( nodeBuilderState.computeShader, stageCompute ); + this.projectPlanes( rendererClippingPlanes, 0 ); - backend.createProgram( stageCompute ); + } else if ( this.globalClippingCount !== 0 ) { - } + this.globalClippingCount = 0; + this.planes = []; + update = true; - // determine compute pipeline + } - const cacheKey = this._getComputeCacheKey( computeNode, stageCompute ); + if ( renderer.localClippingEnabled !== this.localClippingEnabled ) { - let pipeline = this.caches.get( cacheKey ); + this.localClippingEnabled = renderer.localClippingEnabled; + update = true; - if ( pipeline === undefined ) { + } - if ( previousPipeline && previousPipeline.usedTimes === 0 ) this._releasePipeline( previousPipeline ); + if ( update ) { - pipeline = this._getComputePipeline( computeNode, stageCompute, cacheKey, bindings ); + this.version ++; + this.cacheKey = hash$1( this.globalClippingCount, this.localClippingEnabled === true ? 1 : 0 ); - } + } - // keep track of all used times + } - pipeline.usedTimes ++; - stageCompute.usedTimes ++; + update( parent, material ) { - // + let update = false; - data.version = computeNode.version; - data.pipeline = pipeline; + if ( this !== parent && parent.version !== this.parentVersion ) { + + this.globalClippingCount = material.isShadowNodeMaterial ? 0 : parent.globalClippingCount; + this.localClippingEnabled = parent.localClippingEnabled; + this.planes = Array.from( parent.planes ); + this.parentVersion = parent.version; + this.viewMatrix = parent.viewMatrix; + this.viewNormalMatrix = parent.viewNormalMatrix; + + update = true; } - return data.pipeline; + if ( this.localClippingEnabled ) { - } + const localClippingPlanes = material.clippingPlanes; - getForRender( renderObject, promises = null ) { + if ( ( Array.isArray( localClippingPlanes ) && localClippingPlanes.length !== 0 ) ) { - const { backend } = this; + const l = localClippingPlanes.length; + const planes = this.planes; + const offset = this.globalClippingCount; - const data = this.get( renderObject ); + if ( update || l !== this.localClippingCount ) { - if ( this._needsRenderUpdate( renderObject ) ) { + planes.length = offset + l; - const previousPipeline = data.pipeline; + for ( let i = 0; i < l; i ++ ) { - if ( previousPipeline ) { + planes[ offset + i ] = new Vector4(); - previousPipeline.usedTimes --; - previousPipeline.vertexProgram.usedTimes --; - previousPipeline.fragmentProgram.usedTimes --; + } - } + this.localClippingCount = l; + update = true; - // get shader + } - const nodeBuilderState = renderObject.getNodeBuilderState(); + this.projectPlanes( localClippingPlanes, offset ); - // programmable stages - let stageVertex = this.programs.vertex.get( nodeBuilderState.vertexShader ); + } else if ( this.localClippingCount !== 0 ) { - if ( stageVertex === undefined ) { + this.localClippingCount = 0; + update = true; - if ( previousPipeline && previousPipeline.vertexProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.vertexProgram ); + } - stageVertex = new ProgrammableStage( nodeBuilderState.vertexShader, 'vertex' ); - this.programs.vertex.set( nodeBuilderState.vertexShader, stageVertex ); + if ( this.localClipIntersection !== material.clipIntersection ) { - backend.createProgram( stageVertex ); + this.localClipIntersection = material.clipIntersection; + update = true; } - let stageFragment = this.programs.fragment.get( nodeBuilderState.fragmentShader ); + } - if ( stageFragment === undefined ) { + if ( update ) { - if ( previousPipeline && previousPipeline.fragmentProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.fragmentProgram ); + this.version += parent.version; + this.cacheKey = hash$1( parent.cacheKey, this.localClippingCount, this.localClipIntersection === true ? 1 : 0 ); - stageFragment = new ProgrammableStage( nodeBuilderState.fragmentShader, 'fragment' ); - this.programs.fragment.set( nodeBuilderState.fragmentShader, stageFragment ); + } - backend.createProgram( stageFragment ); + } - } +} - // determine render pipeline +let _id$7 = 0; - const cacheKey = this._getRenderCacheKey( renderObject, stageVertex, stageFragment ); +function getKeys( obj ) { - let pipeline = this.caches.get( cacheKey ); + const keys = Object.keys( obj ); - if ( pipeline === undefined ) { + let proto = Object.getPrototypeOf( obj ); - if ( previousPipeline && previousPipeline.usedTimes === 0 ) this._releasePipeline( previousPipeline ); + while ( proto ) { - pipeline = this._getRenderPipeline( renderObject, stageVertex, stageFragment, cacheKey, promises ); + const descriptors = Object.getOwnPropertyDescriptors( proto ); - } else { + for ( const key in descriptors ) { - renderObject.pipeline = pipeline; + if ( descriptors[ key ] !== undefined ) { - } + const descriptor = descriptors[ key ]; - // keep track of all used times + if ( descriptor && typeof descriptor.get === 'function' ) { - pipeline.usedTimes ++; - stageVertex.usedTimes ++; - stageFragment.usedTimes ++; + keys.push( key ); - // + } - data.pipeline = pipeline; + } } - return data.pipeline; + proto = Object.getPrototypeOf( proto ); } - delete( object ) { + return keys; - const pipeline = this.get( object ).pipeline; +} - if ( pipeline ) { +class RenderObject { - // pipeline + constructor( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext ) { - pipeline.usedTimes --; + this._nodes = nodes; + this._geometries = geometries; - if ( pipeline.usedTimes === 0 ) this._releasePipeline( pipeline ); + this.id = _id$7 ++; - // programs + this.renderer = renderer; + this.object = object; + this.material = material; + this.scene = scene; + this.camera = camera; + this.lightsNode = lightsNode; + this.context = renderContext; - if ( pipeline.isComputePipeline ) { + this.geometry = object.geometry; + this.version = material.version; - pipeline.computeProgram.usedTimes --; + this.drawRange = null; - if ( pipeline.computeProgram.usedTimes === 0 ) this._releaseProgram( pipeline.computeProgram ); + this.attributes = null; + this.pipeline = null; + this.vertexBuffers = null; + this.drawParams = null; - } else { + this.bundle = null; - pipeline.fragmentProgram.usedTimes --; - pipeline.vertexProgram.usedTimes --; + this.updateClipping( renderContext.clippingContext ); - if ( pipeline.vertexProgram.usedTimes === 0 ) this._releaseProgram( pipeline.vertexProgram ); - if ( pipeline.fragmentProgram.usedTimes === 0 ) this._releaseProgram( pipeline.fragmentProgram ); + this.clippingContextVersion = this.clippingContext.version; - } + this.initialNodesCacheKey = this.getDynamicCacheKey(); + this.initialCacheKey = this.getCacheKey(); - } + this._nodeBuilderState = null; + this._bindings = null; + this._monitor = null; - return super.delete( object ); + this.onDispose = null; - } + this.isRenderObject = true; - dispose() { + this.onMaterialDispose = () => { - super.dispose(); + this.dispose(); - this.caches = new Map(); - this.programs = { - vertex: new Map(), - fragment: new Map(), - compute: new Map() }; - } + this.material.addEventListener( 'dispose', this.onMaterialDispose ); - updateForRender( renderObject ) { + } - this.getForRender( renderObject ); + updateClipping( parent ) { - } + const material = this.material; - _getComputePipeline( computeNode, stageCompute, cacheKey, bindings ) { + let clippingContext = this.clippingContext; - // check for existing pipeline + if ( Array.isArray( material.clippingPlanes ) ) { - cacheKey = cacheKey || this._getComputeCacheKey( computeNode, stageCompute ); + if ( clippingContext === parent || ! clippingContext ) { - let pipeline = this.caches.get( cacheKey ); + clippingContext = new ClippingContext(); + this.clippingContext = clippingContext; - if ( pipeline === undefined ) { + } - pipeline = new ComputePipeline( cacheKey, stageCompute ); + clippingContext.update( parent, material ); - this.caches.set( cacheKey, pipeline ); + } else if ( this.clippingContext !== parent ) { - this.backend.createComputePipeline( pipeline, bindings ); + this.clippingContext = parent; } - return pipeline; - } - _getRenderPipeline( renderObject, stageVertex, stageFragment, cacheKey, promises ) { - - // check for existing pipeline + get clippingNeedsUpdate() { - cacheKey = cacheKey || this._getRenderCacheKey( renderObject, stageVertex, stageFragment ); + if ( this.clippingContext.version === this.clippingContextVersion ) return false; - let pipeline = this.caches.get( cacheKey ); + this.clippingContextVersion = this.clippingContext.version; - if ( pipeline === undefined ) { + return true; - pipeline = new RenderPipeline( cacheKey, stageVertex, stageFragment ); + } - this.caches.set( cacheKey, pipeline ); + getNodeBuilderState() { - renderObject.pipeline = pipeline; + return this._nodeBuilderState || ( this._nodeBuilderState = this._nodes.getForRender( this ) ); - this.backend.createRenderPipeline( renderObject, promises ); + } - } + getMonitor() { - return pipeline; + return this._monitor || ( this._monitor = this.getNodeBuilderState().monitor ); } - _getComputeCacheKey( computeNode, stageCompute ) { + getBindings() { - return computeNode.id + ',' + stageCompute.id; + return this._bindings || ( this._bindings = this.getNodeBuilderState().createBindings() ); } - _getRenderCacheKey( renderObject, stageVertex, stageFragment ) { + getIndex() { - return stageVertex.id + ',' + stageFragment.id + ',' + this.backend.getRenderCacheKey( renderObject ); + return this._geometries.getIndex( this ); } - _releasePipeline( pipeline ) { + getChainArray() { - this.caches.delete( pipeline.cacheKey ); + return [ this.object, this.material, this.context, this.lightsNode ]; } - _releaseProgram( program ) { + getAttributes() { - const code = program.code; - const stage = program.stage; + if ( this.attributes !== null ) return this.attributes; - this.programs[ stage ].delete( code ); + const nodeAttributes = this.getNodeBuilderState().nodeAttributes; + const geometry = this.geometry; - } + const attributes = []; + const vertexBuffers = new Set(); - _needsComputeUpdate( computeNode ) { + for ( const nodeAttribute of nodeAttributes ) { - const data = this.get( computeNode ); + const attribute = nodeAttribute.node && nodeAttribute.node.attribute ? nodeAttribute.node.attribute : geometry.getAttribute( nodeAttribute.name ); - return data.pipeline === undefined || data.version !== computeNode.version; + if ( attribute === undefined ) continue; - } + attributes.push( attribute ); - _needsRenderUpdate( renderObject ) { + const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute; + vertexBuffers.add( bufferAttribute ); - const data = this.get( renderObject ); + } - return data.pipeline === undefined || this.backend.needsRenderUpdate( renderObject ); + this.attributes = attributes; + this.vertexBuffers = Array.from( vertexBuffers.values() ); + + return attributes; } -} + getVertexBuffers() { -class Bindings extends DataMap { + if ( this.vertexBuffers === null ) this.getAttributes(); - constructor( backend, nodes, textures, attributes, pipelines, info ) { + return this.vertexBuffers; - super(); + } - this.backend = backend; - this.textures = textures; - this.pipelines = pipelines; - this.attributes = attributes; - this.nodes = nodes; - this.info = info; + getDrawParameters() { - this.pipelines.bindings = this; // assign bindings to pipelines + const { object, material, geometry, group, drawRange } = this; - } + const drawParams = this.drawParams || ( this.drawParams = { + vertexCount: 0, + firstVertex: 0, + instanceCount: 0, + firstInstance: 0 + } ); - getForRender( renderObject ) { + const index = this.getIndex(); + const hasIndex = ( index !== null ); + const instanceCount = geometry.isInstancedBufferGeometry ? geometry.instanceCount : ( object.count > 1 ? object.count : 1 ); - const bindings = renderObject.getBindings(); + if ( instanceCount === 0 ) return null; - for ( const bindGroup of bindings ) { + drawParams.instanceCount = instanceCount; - const groupData = this.get( bindGroup ); + if ( object.isBatchedMesh === true ) return drawParams; - if ( groupData.bindGroup === undefined ) { + let rangeFactor = 1; - // each object defines an array of bindings (ubos, textures, samplers etc.) + if ( material.wireframe === true && ! object.isPoints && ! object.isLineSegments && ! object.isLine && ! object.isLineLoop ) { - this._init( bindGroup ); + rangeFactor = 2; - this.backend.createBindings( bindGroup, bindings ); + } - groupData.bindGroup = bindGroup; + let firstVertex = drawRange.start * rangeFactor; + let lastVertex = ( drawRange.start + drawRange.count ) * rangeFactor; - } + if ( group !== null ) { + + firstVertex = Math.max( firstVertex, group.start * rangeFactor ); + lastVertex = Math.min( lastVertex, ( group.start + group.count ) * rangeFactor ); } - return bindings; + const itemCount = hasIndex === true ? index.count : geometry.attributes.position.count; - } + firstVertex = Math.max( firstVertex, 0 ); + lastVertex = Math.min( lastVertex, itemCount ); - getForCompute( computeNode ) { + const count = lastVertex - firstVertex; - const bindings = this.nodes.getForCompute( computeNode ).bindings; + if ( count < 0 || count === Infinity ) return null; - for ( const bindGroup of bindings ) { + drawParams.vertexCount = count; + drawParams.firstVertex = firstVertex; - const groupData = this.get( bindGroup ); + return drawParams; - if ( groupData.bindGroup === undefined ) { + } - this._init( bindGroup ); + getGeometryCacheKey() { - this.backend.createBindings( bindGroup, bindings ); + const { geometry } = this; - groupData.bindGroup = bindGroup; + let cacheKey = ''; - } + for ( const name of Object.keys( geometry.attributes ).sort() ) { - } + const attribute = geometry.attributes[ name ]; - return bindings; + cacheKey += name + ','; - } + if ( attribute.data ) cacheKey += attribute.data.stride + ','; + if ( attribute.offset ) cacheKey += attribute.offset + ','; + if ( attribute.itemSize ) cacheKey += attribute.itemSize + ','; + if ( attribute.normalized ) cacheKey += 'n,'; - updateForCompute( computeNode ) { + } - this._updateBindings( this.getForCompute( computeNode ) ); + if ( geometry.index ) { - } + cacheKey += 'index,'; - updateForRender( renderObject ) { + } - this._updateBindings( this.getForRender( renderObject ) ); + return cacheKey; } - _updateBindings( bindings ) { + getMaterialCacheKey() { - for ( const bindGroup of bindings ) { + const { object, material } = this; - this._update( bindGroup, bindings ); + let cacheKey = material.customProgramCacheKey(); - } + for ( const property of getKeys( material ) ) { - } + if ( /^(is[A-Z]|_)|^(visible|version|uuid|name|opacity|userData)$/.test( property ) ) continue; - _init( bindGroup ) { + const value = material[ property ]; - for ( const binding of bindGroup.bindings ) { + let valueKey; - if ( binding.isSampledTexture ) { + if ( value !== null ) { - this.textures.updateTexture( binding.texture ); + // some material values require a formatting - } else if ( binding.isStorageBuffer ) { + const type = typeof value; - const attribute = binding.attribute; + if ( type === 'number' ) { - this.attributes.update( attribute, AttributeType.STORAGE ); + valueKey = value !== 0 ? '1' : '0'; // Convert to on/off, important for clearcoat, transmission, etc - } + } else if ( type === 'object' ) { - } + valueKey = '{'; - } + if ( value.isTexture ) { - _update( bindGroup, bindings ) { + valueKey += value.mapping; - const { backend } = this; + } - let needsBindingsUpdate = false; + valueKey += '}'; - // iterate over all bindings and check if buffer updates or a new binding group is required + } else { - for ( const binding of bindGroup.bindings ) { + valueKey = String( value ); - if ( binding.isNodeUniformsGroup ) { + } - const updated = this.nodes.updateGroup( binding ); + } else { - if ( ! updated ) continue; + valueKey = String( value ); } - if ( binding.isUniformBuffer ) { + cacheKey += /*property + ':' +*/ valueKey + ','; - const updated = binding.update(); + } - if ( updated ) { + cacheKey += this.clippingContext.cacheKey + ','; - backend.updateBinding( binding ); + if ( object.geometry ) { - } + cacheKey += this.getGeometryCacheKey(); - } else if ( binding.isSampler ) { + } - binding.update(); + if ( object.skeleton ) { - } else if ( binding.isSampledTexture ) { + cacheKey += object.skeleton.bones.length + ','; - if ( binding.needsBindingsUpdate( this.textures.get( binding.texture ).generation ) ) needsBindingsUpdate = true; + } - const updated = binding.update(); + if ( object.morphTargetInfluences ) { - const texture = binding.texture; + cacheKey += object.morphTargetInfluences.length + ','; - if ( updated ) { + } - this.textures.updateTexture( texture ); + if ( object.isBatchedMesh ) { - } + cacheKey += object._matricesTexture.uuid + ','; - const textureData = backend.get( texture ); + if ( object._colorsTexture !== null ) { - if ( backend.isWebGPUBackend === true && textureData.texture === undefined && textureData.externalTexture === undefined ) { + cacheKey += object._colorsTexture.uuid + ','; - // TODO: Remove this once we found why updated === false isn't bound to a texture in the WebGPU backend - console.error( 'Bindings._update: binding should be available:', binding, updated, texture, binding.textureNode.value, needsBindingsUpdate ); + } - this.textures.updateTexture( texture ); - needsBindingsUpdate = true; + } - } + if ( object.count > 1 ) { - if ( texture.isStorageTexture === true ) { + // TODO: https://github.com/mrdoob/three.js/pull/29066#issuecomment-2269400850 - const textureData = this.get( texture ); + cacheKey += object.uuid + ','; - if ( binding.store === true ) { + } - textureData.needsMipmap = true; + return hashString( cacheKey ); - } else if ( texture.generateMipmaps === true && this.textures.needsMipmaps( texture ) && textureData.needsMipmap === true ) { + } - this.backend.generateMipmaps( texture ); + get needsUpdate() { - textureData.needsMipmap = false; + return /*this.object.static !== true &&*/ ( this.initialNodesCacheKey !== this.getDynamicCacheKey() || this.clippingNeedsUpdate ); - } + } - } + getDynamicCacheKey() { - } + // Environment Nodes Cache Key - } + let cacheKey = this._nodes.getCacheKey( this.scene, this.lightsNode ); - if ( needsBindingsUpdate === true ) { + if ( this.object.receiveShadow ) { - this.backend.updateBindings( bindGroup, bindings ); + cacheKey += 1; } + return cacheKey; + } -} + getCacheKey() { -class NodeAttribute { + return this.getMaterialCacheKey() + this.getDynamicCacheKey(); - constructor( name, type, node = null ) { + } - this.isNodeAttribute = true; + dispose() { - this.name = name; - this.type = type; - this.node = node; + this.material.removeEventListener( 'dispose', this.onMaterialDispose ); + + this.onDispose(); } } -class NodeUniform { +const chainArray = []; - constructor( name, type, node ) { +class RenderObjects { - this.isNodeUniform = true; + constructor( renderer, nodes, geometries, pipelines, bindings, info ) { - this.name = name; - this.type = type; - this.node = node.getSelf(); + this.renderer = renderer; + this.nodes = nodes; + this.geometries = geometries; + this.pipelines = pipelines; + this.bindings = bindings; + this.info = info; + + this.chainMaps = {}; } - get value() { + get( object, material, scene, camera, lightsNode, renderContext, passId ) { - return this.node.value; + const chainMap = this.getChainMap( passId ); - } + // reuse chainArray + chainArray[ 0 ] = object; + chainArray[ 1 ] = material; + chainArray[ 2 ] = renderContext; + chainArray[ 3 ] = lightsNode; - set value( val ) { + let renderObject = chainMap.get( chainArray ); - this.node.value = val; + if ( renderObject === undefined ) { - } + renderObject = this.createRenderObject( this.nodes, this.geometries, this.renderer, object, material, scene, camera, lightsNode, renderContext, passId ); - get id() { + chainMap.set( chainArray, renderObject ); - return this.node.id; + } else { - } + renderObject.updateClipping( renderContext.clippingContext ); - get groupNode() { + if ( renderObject.version !== material.version || renderObject.needsUpdate ) { - return this.node.groupNode; + if ( renderObject.initialCacheKey !== renderObject.getCacheKey() ) { - } + renderObject.dispose(); -} + renderObject = this.get( object, material, scene, camera, lightsNode, renderContext, passId ); -class NodeVar { + } else { - constructor( name, type ) { + renderObject.version = material.version; - this.isNodeVar = true; + } - this.name = name; - this.type = type; + } - } + } -} + return renderObject; -class NodeVarying extends NodeVar { + } - constructor( name, type ) { + getChainMap( passId = 'default' ) { - super( name, type ); + return this.chainMaps[ passId ] || ( this.chainMaps[ passId ] = new ChainMap() ); - this.needsInterpolation = false; + } - this.isNodeVarying = true; + dispose() { + + this.chainMaps = {}; } -} + createRenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext, passId ) { -class NodeCode { + const chainMap = this.getChainMap( passId ); - constructor( name, type, code = '' ) { + const renderObject = new RenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext ); - this.name = name; - this.type = type; - this.code = code; + renderObject.onDispose = () => { - Object.defineProperty( this, 'isNodeCode', { value: true } ); + this.pipelines.delete( renderObject ); + this.bindings.delete( renderObject ); + this.nodes.delete( renderObject ); - } + chainMap.delete( renderObject.getChainArray() ); -} + }; -let id$1 = 0; + return renderObject; -class NodeCache { + } - constructor( parent = null ) { - this.id = id$1 ++; - this.nodesData = new WeakMap(); +} - this.parent = parent; +class DataMap { + + constructor() { + + this.data = new WeakMap(); } - getData( node ) { + get( object ) { - let data = this.nodesData.get( node ); + let map = this.data.get( object ); - if ( data === undefined && this.parent !== null ) { + if ( map === undefined ) { - data = this.parent.getData( node ); + map = {}; + this.data.set( object, map ); } - return data; + return map; } - setData( node, data ) { - - this.nodesData.set( node, data ); + delete( object ) { - } + let map; -} + if ( this.data.has( object ) ) { -class ParameterNode extends PropertyNode { + map = this.data.get( object ); - constructor( nodeType, name = null ) { + this.data.delete( object ); - super( nodeType, name ); + } - this.isParameterNode = true; + return map; } - getHash() { + has( object ) { - return this.uuid; + return this.data.has( object ); } - generate() { + dispose() { - return this.name; + this.data = new WeakMap(); } } -ParameterNode.type = /*@__PURE__*/ registerNode( 'Parameter', ParameterNode ); +const AttributeType = { + VERTEX: 1, + INDEX: 2, + STORAGE: 4 +}; -const parameter = ( type, name ) => nodeObject( new ParameterNode( type, name ) ); +// size of a chunk in bytes (STD140 layout) -class CodeNode extends Node { +const GPU_CHUNK_BYTES = 16; - constructor( code = '', includes = [], language = '' ) { +// @TODO: Move to src/constants.js - super( 'code' ); +const BlendColorFactor = 211; +const OneMinusBlendColorFactor = 212; - this.isCodeNode = true; +class Attributes extends DataMap { - this.code = code; - this.language = language; + constructor( backend ) { - this.includes = includes; + super(); + + this.backend = backend; } - isGlobal() { + delete( attribute ) { - return true; + const attributeData = super.delete( attribute ); - } + if ( attributeData !== undefined ) { - setIncludes( includes ) { + this.backend.destroyAttribute( attribute ); - this.includes = includes; + } - return this; + return attributeData; } - getIncludes( /*builder*/ ) { + update( attribute, type ) { - return this.includes; + const data = this.get( attribute ); - } + if ( data.version === undefined ) { - generate( builder ) { + if ( type === AttributeType.VERTEX ) { - const includes = this.getIncludes( builder ); + this.backend.createAttribute( attribute ); - for ( const include of includes ) { + } else if ( type === AttributeType.INDEX ) { - include.build( builder ); + this.backend.createIndexAttribute( attribute ); - } + } else if ( type === AttributeType.STORAGE ) { - const nodeCode = builder.getCodeFromNode( this, this.getNodeType( builder ) ); - nodeCode.code = this.code; + this.backend.createStorageAttribute( attribute ); - return nodeCode.code; + } - } + data.version = this._getBufferAttribute( attribute ).version; - serialize( data ) { + } else { - super.serialize( data ); + const bufferAttribute = this._getBufferAttribute( attribute ); - data.code = this.code; - data.language = this.language; + if ( data.version < bufferAttribute.version || bufferAttribute.usage === DynamicDrawUsage ) { - } + this.backend.updateAttribute( attribute ); - deserialize( data ) { + data.version = bufferAttribute.version; - super.deserialize( data ); + } - this.code = data.code; - this.language = data.language; + } } -} - -CodeNode.type = /*@__PURE__*/ registerNode( 'Code', CodeNode ); + _getBufferAttribute( attribute ) { -const code = /*@__PURE__*/ nodeProxy( CodeNode ); + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; -const js = ( src, includes ) => code( src, includes, 'js' ); -const wgsl = ( src, includes ) => code( src, includes, 'wgsl' ); -const glsl = ( src, includes ) => code( src, includes, 'glsl' ); + return attribute; -class FunctionNode extends CodeNode { + } - constructor( code = '', includes = [], language = '' ) { +} - super( code, includes, language ); +function arrayNeedsUint32( array ) { - } + // assumes larger values usually on last - getNodeType( builder ) { + for ( let i = array.length - 1; i >= 0; -- i ) { - return this.getNodeFunction( builder ).type; + if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565 } - getInputs( builder ) { - - return this.getNodeFunction( builder ).inputs; + return false; - } +} - getNodeFunction( builder ) { +function getWireframeVersion( geometry ) { - const nodeData = builder.getDataFromNode( this ); + return ( geometry.index !== null ) ? geometry.index.version : geometry.attributes.position.version; - let nodeFunction = nodeData.nodeFunction; +} - if ( nodeFunction === undefined ) { +function getWireframeIndex( geometry ) { - nodeFunction = builder.parser.parseFunction( this.code ); + const indices = []; - nodeData.nodeFunction = nodeFunction; + const geometryIndex = geometry.index; + const geometryPosition = geometry.attributes.position; - } + if ( geometryIndex !== null ) { - return nodeFunction; + const array = geometryIndex.array; - } + for ( let i = 0, l = array.length; i < l; i += 3 ) { - generate( builder, output ) { + const a = array[ i + 0 ]; + const b = array[ i + 1 ]; + const c = array[ i + 2 ]; - super.generate( builder ); + indices.push( a, b, b, c, c, a ); - const nodeFunction = this.getNodeFunction( builder ); + } - const name = nodeFunction.name; - const type = nodeFunction.type; + } else { - const nodeCode = builder.getCodeFromNode( this, type ); + const array = geometryPosition.array; - if ( name !== '' ) { + for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) { - // use a custom property name + const a = i + 0; + const b = i + 1; + const c = i + 2; - nodeCode.name = name; + indices.push( a, b, b, c, c, a ); } - const propertyName = builder.getPropertyName( nodeCode ); + } - const code = this.getNodeFunction( builder ).getCode( propertyName ); + const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); + attribute.version = getWireframeVersion( geometry ); - nodeCode.code = code + '\n'; + return attribute; - if ( output === 'property' ) { +} - return propertyName; +class Geometries extends DataMap { - } else { + constructor( attributes, info ) { - return builder.format( `${ propertyName }()`, type, output ); + super(); - } + this.attributes = attributes; + this.info = info; - } + this.wireframes = new WeakMap(); -} + this.attributeCall = new WeakMap(); -FunctionNode.type = /*@__PURE__*/ registerNode( 'Function', FunctionNode ); + } -const nativeFn = ( code, includes = [], language = '' ) => { + has( renderObject ) { - for ( let i = 0; i < includes.length; i ++ ) { + const geometry = renderObject.geometry; - const include = includes[ i ]; + return super.has( geometry ) && this.get( geometry ).initialized === true; - // TSL Function: glslFn, wgslFn + } - if ( typeof include === 'function' ) { + updateForRender( renderObject ) { - includes[ i ] = include.functionNode; + if ( this.has( renderObject ) === false ) this.initGeometry( renderObject ); - } + this.updateAttributes( renderObject ); } - const functionNode = nodeObject( new FunctionNode( code, includes, language ) ); + initGeometry( renderObject ) { - const fn = ( ...params ) => functionNode.call( ...params ); - fn.functionNode = functionNode; + const geometry = renderObject.geometry; + const geometryData = this.get( geometry ); - return fn; + geometryData.initialized = true; -}; + this.info.memory.geometries ++; -const glslFn = ( code, includes ) => nativeFn( code, includes, 'glsl' ); -const wgslFn = ( code, includes ) => nativeFn( code, includes, 'wgsl' ); + const onDispose = () => { -class Uniform { + this.info.memory.geometries --; - constructor( name, value ) { + const index = geometry.index; + const geometryAttributes = renderObject.getAttributes(); - this.name = name; - this.value = value; + if ( index !== null ) { - this.boundary = 0; // used to build the uniform buffer according to the STD140 layout - this.itemSize = 0; + this.attributes.delete( index ); - this.offset = 0; // this property is set by WebGPUUniformsGroup and marks the start position in the uniform buffer + } - } + for ( const geometryAttribute of geometryAttributes ) { - setValue( value ) { + this.attributes.delete( geometryAttribute ); - this.value = value; + } - } + const wireframeAttribute = this.wireframes.get( geometry ); - getValue() { + if ( wireframeAttribute !== undefined ) { - return this.value; + this.attributes.delete( wireframeAttribute ); + + } + + geometry.removeEventListener( 'dispose', onDispose ); + + }; + + geometry.addEventListener( 'dispose', onDispose ); } -} + updateAttributes( renderObject ) { -class NumberUniform extends Uniform { + const attributes = renderObject.getAttributes(); - constructor( name, value = 0 ) { + for ( const attribute of attributes ) { - super( name, value ); + if ( attribute.isStorageBufferAttribute || attribute.isStorageInstancedBufferAttribute ) { - this.isNumberUniform = true; + this.updateAttribute( attribute, AttributeType.STORAGE ); - this.boundary = 4; - this.itemSize = 1; + } else { - } + this.updateAttribute( attribute, AttributeType.VERTEX ); -} + } -class Vector2Uniform extends Uniform { + } - constructor( name, value = new Vector2() ) { + const index = this.getIndex( renderObject ); - super( name, value ); + if ( index !== null ) { - this.isVector2Uniform = true; + this.updateAttribute( index, AttributeType.INDEX ); - this.boundary = 8; - this.itemSize = 2; + } } -} + updateAttribute( attribute, type ) { -class Vector3Uniform extends Uniform { + const callId = this.info.render.calls; - constructor( name, value = new Vector3() ) { + if ( ! attribute.isInterleavedBufferAttribute ) { - super( name, value ); + if ( this.attributeCall.get( attribute ) !== callId ) { - this.isVector3Uniform = true; + this.attributes.update( attribute, type ); - this.boundary = 16; - this.itemSize = 3; + this.attributeCall.set( attribute, callId ); - } + } -} + } else { -class Vector4Uniform extends Uniform { + if ( this.attributeCall.get( attribute ) === undefined ) { - constructor( name, value = new Vector4() ) { + this.attributes.update( attribute, type ); - super( name, value ); + this.attributeCall.set( attribute, callId ); - this.isVector4Uniform = true; + } else if ( this.attributeCall.get( attribute.data ) !== callId ) { - this.boundary = 16; - this.itemSize = 4; + this.attributes.update( attribute, type ); - } + this.attributeCall.set( attribute.data, callId ); -} + this.attributeCall.set( attribute, callId ); -class ColorUniform extends Uniform { + } - constructor( name, value = new Color() ) { + } - super( name, value ); + } - this.isColorUniform = true; + getIndex( renderObject ) { - this.boundary = 16; - this.itemSize = 3; + const { geometry, material } = renderObject; - } + let index = geometry.index; -} + if ( material.wireframe === true ) { -class Matrix3Uniform extends Uniform { + const wireframes = this.wireframes; - constructor( name, value = new Matrix3() ) { + let wireframeAttribute = wireframes.get( geometry ); - super( name, value ); + if ( wireframeAttribute === undefined ) { - this.isMatrix3Uniform = true; + wireframeAttribute = getWireframeIndex( geometry ); - this.boundary = 48; - this.itemSize = 12; + wireframes.set( geometry, wireframeAttribute ); - } + } else if ( wireframeAttribute.version !== getWireframeVersion( geometry ) ) { -} + this.attributes.delete( wireframeAttribute ); -class Matrix4Uniform extends Uniform { + wireframeAttribute = getWireframeIndex( geometry ); - constructor( name, value = new Matrix4() ) { + wireframes.set( geometry, wireframeAttribute ); - super( name, value ); + } - this.isMatrix4Uniform = true; + index = wireframeAttribute; - this.boundary = 64; - this.itemSize = 16; + } + + return index; } } -class NumberNodeUniform extends NumberUniform { +class Info { - constructor( nodeUniform ) { + constructor() { - super( nodeUniform.name, nodeUniform.value ); + this.autoReset = true; - this.nodeUniform = nodeUniform; + this.frame = 0; + this.calls = 0; - } + this.render = { + calls: 0, + frameCalls: 0, + drawCalls: 0, + triangles: 0, + points: 0, + lines: 0, + timestamp: 0, + previousFrameCalls: 0, + timestampCalls: 0 + }; - getValue() { + this.compute = { + calls: 0, + frameCalls: 0, + timestamp: 0, + previousFrameCalls: 0, + timestampCalls: 0 + }; - return this.nodeUniform.value; + this.memory = { + geometries: 0, + textures: 0 + }; } -} - -class Vector2NodeUniform extends Vector2Uniform { + update( object, count, instanceCount ) { - constructor( nodeUniform ) { + this.render.drawCalls ++; - super( nodeUniform.name, nodeUniform.value ); + if ( object.isMesh || object.isSprite ) { - this.nodeUniform = nodeUniform; + this.render.triangles += instanceCount * ( count / 3 ); - } + } else if ( object.isPoints ) { - getValue() { + this.render.points += instanceCount * count; - return this.nodeUniform.value; + } else if ( object.isLineSegments ) { - } + this.render.lines += instanceCount * ( count / 2 ); -} + } else if ( object.isLine ) { -class Vector3NodeUniform extends Vector3Uniform { + this.render.lines += instanceCount * ( count - 1 ); - constructor( nodeUniform ) { + } else { - super( nodeUniform.name, nodeUniform.value ); + console.error( 'THREE.WebGPUInfo: Unknown object type.' ); - this.nodeUniform = nodeUniform; + } } - getValue() { + updateTimestamp( type, time ) { - return this.nodeUniform.value; + if ( this[ type ].timestampCalls === 0 ) { - } + this[ type ].timestamp = 0; -} + } -class Vector4NodeUniform extends Vector4Uniform { - constructor( nodeUniform ) { + this[ type ].timestamp += time; - super( nodeUniform.name, nodeUniform.value ); + this[ type ].timestampCalls ++; - this.nodeUniform = nodeUniform; - } + if ( this[ type ].timestampCalls >= this[ type ].previousFrameCalls ) { - getValue() { + this[ type ].timestampCalls = 0; - return this.nodeUniform.value; + } - } -} + } -class ColorNodeUniform extends ColorUniform { + reset() { - constructor( nodeUniform ) { + const previousRenderFrameCalls = this.render.frameCalls; + this.render.previousFrameCalls = previousRenderFrameCalls; - super( nodeUniform.name, nodeUniform.value ); + const previousComputeFrameCalls = this.compute.frameCalls; + this.compute.previousFrameCalls = previousComputeFrameCalls; - this.nodeUniform = nodeUniform; - } + this.render.drawCalls = 0; + this.render.frameCalls = 0; + this.compute.frameCalls = 0; - getValue() { + this.render.triangles = 0; + this.render.points = 0; + this.render.lines = 0; - return this.nodeUniform.value; } -} + dispose() { -class Matrix3NodeUniform extends Matrix3Uniform { + this.reset(); - constructor( nodeUniform ) { + this.calls = 0; - super( nodeUniform.name, nodeUniform.value ); + this.render.calls = 0; + this.compute.calls = 0; - this.nodeUniform = nodeUniform; + this.render.timestamp = 0; + this.compute.timestamp = 0; + this.memory.geometries = 0; + this.memory.textures = 0; } - getValue() { +} - return this.nodeUniform.value; +class Pipeline { + + constructor( cacheKey ) { + + this.cacheKey = cacheKey; + + this.usedTimes = 0; } } -class Matrix4NodeUniform extends Matrix4Uniform { +class RenderPipeline extends Pipeline { - constructor( nodeUniform ) { + constructor( cacheKey, vertexProgram, fragmentProgram ) { - super( nodeUniform.name, nodeUniform.value ); + super( cacheKey ); - this.nodeUniform = nodeUniform; + this.vertexProgram = vertexProgram; + this.fragmentProgram = fragmentProgram; } - getValue() { +} - return this.nodeUniform.value; +class ComputePipeline extends Pipeline { - } + constructor( cacheKey, computeProgram ) { -} + super( cacheKey ); -class StackNode extends Node { + this.computeProgram = computeProgram; - constructor( parent = null ) { + this.isComputePipeline = true; - super(); + } - this.nodes = []; - this.outputNode = null; +} - this.parent = parent; +let _id$6 = 0; - this._currentCond = null; +class ProgrammableStage { - this.isStackNode = true; + constructor( code, type, transforms = null, attributes = null ) { - } + this.id = _id$6 ++; - getNodeType( builder ) { + this.code = code; + this.stage = type; + this.transforms = transforms; + this.attributes = attributes; - return this.outputNode ? this.outputNode.getNodeType( builder ) : 'void'; + this.usedTimes = 0; } - add( node ) { +} - this.nodes.push( node ); +class Pipelines extends DataMap { - return this; + constructor( backend, nodes ) { - } + super(); - If( boolNode, method ) { + this.backend = backend; + this.nodes = nodes; - const methodNode = new ShaderNode( method ); - this._currentCond = select( boolNode, methodNode ); + this.bindings = null; // set by the bindings - return this.add( this._currentCond ); + this.caches = new Map(); + this.programs = { + vertex: new Map(), + fragment: new Map(), + compute: new Map() + }; } - ElseIf( boolNode, method ) { + getForCompute( computeNode, bindings ) { - const methodNode = new ShaderNode( method ); - const ifNode = select( boolNode, methodNode ); + const { backend } = this; - this._currentCond.elseNode = ifNode; - this._currentCond = ifNode; + const data = this.get( computeNode ); - return this; + if ( this._needsComputeUpdate( computeNode ) ) { - } + const previousPipeline = data.pipeline; - Else( method ) { + if ( previousPipeline ) { - this._currentCond.elseNode = new ShaderNode( method ); + previousPipeline.usedTimes --; + previousPipeline.computeProgram.usedTimes --; - return this; + } - } + // get shader - build( builder, ...params ) { + const nodeBuilderState = this.nodes.getForCompute( computeNode ); - const previousStack = getCurrentStack(); + // programmable stage - setCurrentStack( this ); + let stageCompute = this.programs.compute.get( nodeBuilderState.computeShader ); - for ( const node of this.nodes ) { + if ( stageCompute === undefined ) { - node.build( builder, 'void' ); + if ( previousPipeline && previousPipeline.computeProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.computeProgram ); - } + stageCompute = new ProgrammableStage( nodeBuilderState.computeShader, 'compute', nodeBuilderState.transforms, nodeBuilderState.nodeAttributes ); + this.programs.compute.set( nodeBuilderState.computeShader, stageCompute ); - setCurrentStack( previousStack ); + backend.createProgram( stageCompute ); - return this.outputNode ? this.outputNode.build( builder, ...params ) : super.build( builder, ...params ); + } - } + // determine compute pipeline - // + const cacheKey = this._getComputeCacheKey( computeNode, stageCompute ); - else( ...params ) { // @deprecated, r168 + let pipeline = this.caches.get( cacheKey ); - console.warn( 'TSL.StackNode: .else() has been renamed to .Else().' ); - return this.Else( ...params ); + if ( pipeline === undefined ) { - } + if ( previousPipeline && previousPipeline.usedTimes === 0 ) this._releasePipeline( previousPipeline ); - elseif( ...params ) { // @deprecated, r168 + pipeline = this._getComputePipeline( computeNode, stageCompute, cacheKey, bindings ); - console.warn( 'TSL.StackNode: .elseif() has been renamed to .ElseIf().' ); - return this.ElseIf( ...params ); + } - } + // keep track of all used times -} + pipeline.usedTimes ++; + stageCompute.usedTimes ++; -StackNode.type = /*@__PURE__*/ registerNode( 'Stack', StackNode ); + // -const stack = /*@__PURE__*/ nodeProxy( StackNode ); + data.version = computeNode.version; + data.pipeline = pipeline; -const LOD_MIN = 4; + } -// The standard deviations (radians) associated with the extra mips. These are -// chosen to approximate a Trowbridge-Reitz distribution function times the -// geometric shadowing function. These sigma values squared must match the -// variance #defines in cube_uv_reflection_fragment.glsl.js. -const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ]; + return data.pipeline; -// The maximum length of the blur for loop. Smaller sigmas will use fewer -// samples and exit early, but not recompile the shader. -const MAX_SAMPLES = 20; + } -const _flatCamera = /*@__PURE__*/ new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); -const _cubeCamera = /*@__PURE__*/ new PerspectiveCamera( 90, 1 ); -const _clearColor$2 = /*@__PURE__*/ new Color(); -let _oldTarget = null; -let _oldActiveCubeFace = 0; -let _oldActiveMipmapLevel = 0; + getForRender( renderObject, promises = null ) { -// Golden Ratio -const PHI = ( 1 + Math.sqrt( 5 ) ) / 2; -const INV_PHI = 1 / PHI; + const { backend } = this; -// Vertices of a dodecahedron (except the opposites, which represent the -// same axis), used as axis directions evenly spread on a sphere. -const _axisDirections = [ - /*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ), - /*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ), - /*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ), - /*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ), - /*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ), - /*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ), - /*@__PURE__*/ new Vector3( - 1, 1, - 1 ), - /*@__PURE__*/ new Vector3( 1, 1, - 1 ), - /*@__PURE__*/ new Vector3( - 1, 1, 1 ), - /*@__PURE__*/ new Vector3( 1, 1, 1 ) -]; + const data = this.get( renderObject ); -// + if ( this._needsRenderUpdate( renderObject ) ) { -// WebGPU Face indices -const _faceLib = [ - 3, 1, 5, - 0, 4, 2 -]; + const previousPipeline = data.pipeline; -const direction = getDirection( uv(), attribute( 'faceIndex' ) ).normalize(); -const outputDirection = vec3( direction.x, direction.y.negate(), direction.z ); + if ( previousPipeline ) { -/** - * This class generates a Prefiltered, Mipmapped Radiance Environment Map - * (PMREM) from a cubeMap environment texture. This allows different levels of - * blur to be quickly accessed based on material roughness. It is packed into a - * special CubeUV format that allows us to perform custom interpolation so that - * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap - * chain, it only goes down to the LOD_MIN level (above), and then creates extra - * even more filtered 'mips' at the same LOD_MIN resolution, associated with - * higher roughness levels. In this way we maintain resolution to smoothly - * interpolate diffuse lighting while limiting sampling computation. - * - * Paper: Fast, Accurate Image-Based Lighting - * https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view -*/ + previousPipeline.usedTimes --; + previousPipeline.vertexProgram.usedTimes --; + previousPipeline.fragmentProgram.usedTimes --; -class PMREMGenerator { + } - constructor( renderer ) { + // get shader - this._renderer = renderer; - this._pingPongRenderTarget = null; + const nodeBuilderState = renderObject.getNodeBuilderState(); - this._lodMax = 0; - this._cubeSize = 0; - this._lodPlanes = []; - this._sizeLods = []; - this._sigmas = []; - this._lodMeshes = []; + // programmable stages - this._blurMaterial = null; - this._cubemapMaterial = null; - this._equirectMaterial = null; - this._backgroundBox = null; + let stageVertex = this.programs.vertex.get( nodeBuilderState.vertexShader ); - } + if ( stageVertex === undefined ) { - /** - * Generates a PMREM from a supplied Scene, which can be faster than using an - * image if networking bandwidth is low. Optional sigma specifies a blur radius - * in radians to be applied to the scene before PMREM generation. Optional near - * and far planes ensure the scene is rendered in its entirety (the cubeCamera - * is placed at the origin). - */ - fromScene( scene, sigma = 0, near = 0.1, far = 100 ) { + if ( previousPipeline && previousPipeline.vertexProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.vertexProgram ); - _oldTarget = this._renderer.getRenderTarget(); - _oldActiveCubeFace = this._renderer.getActiveCubeFace(); - _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); + stageVertex = new ProgrammableStage( nodeBuilderState.vertexShader, 'vertex' ); + this.programs.vertex.set( nodeBuilderState.vertexShader, stageVertex ); - this._setSize( 256 ); + backend.createProgram( stageVertex ); - const cubeUVRenderTarget = this._allocateTargets(); - cubeUVRenderTarget.depthBuffer = true; + } - this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget ); + let stageFragment = this.programs.fragment.get( nodeBuilderState.fragmentShader ); - if ( sigma > 0 ) { + if ( stageFragment === undefined ) { - this._blur( cubeUVRenderTarget, 0, 0, sigma ); + if ( previousPipeline && previousPipeline.fragmentProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.fragmentProgram ); - } + stageFragment = new ProgrammableStage( nodeBuilderState.fragmentShader, 'fragment' ); + this.programs.fragment.set( nodeBuilderState.fragmentShader, stageFragment ); - this._applyPMREM( cubeUVRenderTarget ); + backend.createProgram( stageFragment ); - this._cleanup( cubeUVRenderTarget ); + } - return cubeUVRenderTarget; + // determine render pipeline - } + const cacheKey = this._getRenderCacheKey( renderObject, stageVertex, stageFragment ); - /** - * Generates a PMREM from an equirectangular texture, which can be either LDR - * or HDR. The ideal input image size is 1k (1024 x 512), - * as this matches best with the 256 x 256 cubemap output. - */ - fromEquirectangular( equirectangular, renderTarget = null ) { + let pipeline = this.caches.get( cacheKey ); - return this._fromTexture( equirectangular, renderTarget ); + if ( pipeline === undefined ) { - } + if ( previousPipeline && previousPipeline.usedTimes === 0 ) this._releasePipeline( previousPipeline ); - /** - * Generates a PMREM from an cubemap texture, which can be either LDR - * or HDR. The ideal input cube size is 256 x 256, - * as this matches best with the 256 x 256 cubemap output. - */ - fromCubemap( cubemap, renderTarget = null ) { + pipeline = this._getRenderPipeline( renderObject, stageVertex, stageFragment, cacheKey, promises ); - return this._fromTexture( cubemap, renderTarget ); + } else { - } + renderObject.pipeline = pipeline; - /** - * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during - * your texture's network fetch for increased concurrency. - */ - compileCubemapShader() { + } - if ( this._cubemapMaterial === null ) { + // keep track of all used times - this._cubemapMaterial = _getCubemapMaterial(); - this._compileMaterial( this._cubemapMaterial ); + pipeline.usedTimes ++; + stageVertex.usedTimes ++; + stageFragment.usedTimes ++; + + // + + data.pipeline = pipeline; } + return data.pipeline; + } - /** - * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during - * your texture's network fetch for increased concurrency. - */ - compileEquirectangularShader() { + delete( object ) { - if ( this._equirectMaterial === null ) { + const pipeline = this.get( object ).pipeline; - this._equirectMaterial = _getEquirectMaterial(); - this._compileMaterial( this._equirectMaterial ); + if ( pipeline ) { - } + // pipeline - } + pipeline.usedTimes --; - /** - * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class, - * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on - * one of them will cause any others to also become unusable. - */ - dispose() { + if ( pipeline.usedTimes === 0 ) this._releasePipeline( pipeline ); - this._dispose(); + // programs - if ( this._cubemapMaterial !== null ) this._cubemapMaterial.dispose(); - if ( this._equirectMaterial !== null ) this._equirectMaterial.dispose(); - if ( this._backgroundBox !== null ) { + if ( pipeline.isComputePipeline ) { - this._backgroundBox.geometry.dispose(); - this._backgroundBox.material.dispose(); + pipeline.computeProgram.usedTimes --; + + if ( pipeline.computeProgram.usedTimes === 0 ) this._releaseProgram( pipeline.computeProgram ); + + } else { + + pipeline.fragmentProgram.usedTimes --; + pipeline.vertexProgram.usedTimes --; + + if ( pipeline.vertexProgram.usedTimes === 0 ) this._releaseProgram( pipeline.vertexProgram ); + if ( pipeline.fragmentProgram.usedTimes === 0 ) this._releaseProgram( pipeline.fragmentProgram ); + + } } + return super.delete( object ); + } - // private interface + dispose() { - _setSize( cubeSize ) { + super.dispose(); - this._lodMax = Math.floor( Math.log2( cubeSize ) ); - this._cubeSize = Math.pow( 2, this._lodMax ); + this.caches = new Map(); + this.programs = { + vertex: new Map(), + fragment: new Map(), + compute: new Map() + }; } - _dispose() { + updateForRender( renderObject ) { - if ( this._blurMaterial !== null ) this._blurMaterial.dispose(); + this.getForRender( renderObject ); - if ( this._pingPongRenderTarget !== null ) this._pingPongRenderTarget.dispose(); + } - for ( let i = 0; i < this._lodPlanes.length; i ++ ) { + _getComputePipeline( computeNode, stageCompute, cacheKey, bindings ) { - this._lodPlanes[ i ].dispose(); + // check for existing pipeline + + cacheKey = cacheKey || this._getComputeCacheKey( computeNode, stageCompute ); + + let pipeline = this.caches.get( cacheKey ); + + if ( pipeline === undefined ) { + + pipeline = new ComputePipeline( cacheKey, stageCompute ); + + this.caches.set( cacheKey, pipeline ); + + this.backend.createComputePipeline( pipeline, bindings ); } + return pipeline; + } - _cleanup( outputTarget ) { + _getRenderPipeline( renderObject, stageVertex, stageFragment, cacheKey, promises ) { - this._renderer.setRenderTarget( _oldTarget, _oldActiveCubeFace, _oldActiveMipmapLevel ); - outputTarget.scissorTest = false; - _setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height ); + // check for existing pipeline - } + cacheKey = cacheKey || this._getRenderCacheKey( renderObject, stageVertex, stageFragment ); - _fromTexture( texture, renderTarget ) { + let pipeline = this.caches.get( cacheKey ); - if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) { + if ( pipeline === undefined ) { - this._setSize( texture.image.length === 0 ? 16 : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) ); + pipeline = new RenderPipeline( cacheKey, stageVertex, stageFragment ); - } else { // Equirectangular + this.caches.set( cacheKey, pipeline ); - this._setSize( texture.image.width / 4 ); + renderObject.pipeline = pipeline; + + this.backend.createRenderPipeline( renderObject, promises ); } - _oldTarget = this._renderer.getRenderTarget(); - _oldActiveCubeFace = this._renderer.getActiveCubeFace(); - _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); + return pipeline; - const cubeUVRenderTarget = renderTarget || this._allocateTargets(); - this._textureToCubeUV( texture, cubeUVRenderTarget ); - this._applyPMREM( cubeUVRenderTarget ); - this._cleanup( cubeUVRenderTarget ); + } - return cubeUVRenderTarget; + _getComputeCacheKey( computeNode, stageCompute ) { + + return computeNode.id + ',' + stageCompute.id; } - _allocateTargets() { + _getRenderCacheKey( renderObject, stageVertex, stageFragment ) { - const width = 3 * Math.max( this._cubeSize, 16 * 7 ); - const height = 4 * this._cubeSize; + return stageVertex.id + ',' + stageFragment.id + ',' + this.backend.getRenderCacheKey( renderObject ); - const params = { - magFilter: LinearFilter, - minFilter: LinearFilter, - generateMipmaps: false, - type: HalfFloatType, - format: RGBAFormat, - colorSpace: LinearSRGBColorSpace, - //depthBuffer: false - }; + } - const cubeUVRenderTarget = _createRenderTarget( width, height, params ); + _releasePipeline( pipeline ) { - if ( this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width || this._pingPongRenderTarget.height !== height ) { + this.caches.delete( pipeline.cacheKey ); - if ( this._pingPongRenderTarget !== null ) { + } - this._dispose(); + _releaseProgram( program ) { - } + const code = program.code; + const stage = program.stage; - this._pingPongRenderTarget = _createRenderTarget( width, height, params ); + this.programs[ stage ].delete( code ); - const { _lodMax } = this; - ( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas, lodMeshes: this._lodMeshes } = _createPlanes( _lodMax ) ); + } - this._blurMaterial = _getBlurShader( _lodMax, width, height ); + _needsComputeUpdate( computeNode ) { - } + const data = this.get( computeNode ); - return cubeUVRenderTarget; + return data.pipeline === undefined || data.version !== computeNode.version; } - _compileMaterial( material ) { + _needsRenderUpdate( renderObject ) { - const tmpMesh = this._lodMeshes[ 0 ]; - tmpMesh.material = material; + const data = this.get( renderObject ); - this._renderer.compile( tmpMesh, _flatCamera ); + return data.pipeline === undefined || this.backend.needsRenderUpdate( renderObject ); } - _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) { +} - const cubeCamera = _cubeCamera; - cubeCamera.near = near; - cubeCamera.far = far; +class Bindings extends DataMap { - // px, py, pz, nx, ny, nz - const upSign = [ - 1, 1, - 1, - 1, - 1, - 1 ]; - const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ]; + constructor( backend, nodes, textures, attributes, pipelines, info ) { - const renderer = this._renderer; + super(); - const originalAutoClear = renderer.autoClear; + this.backend = backend; + this.textures = textures; + this.pipelines = pipelines; + this.attributes = attributes; + this.nodes = nodes; + this.info = info; - renderer.getClearColor( _clearColor$2 ); + this.pipelines.bindings = this; // assign bindings to pipelines - renderer.autoClear = false; + } - let backgroundBox = this._backgroundBox; + getForRender( renderObject ) { - if ( backgroundBox === null ) { + const bindings = renderObject.getBindings(); - const backgroundMaterial = new MeshBasicMaterial( { - name: 'PMREM.Background', - side: BackSide, - depthWrite: false, - depthTest: false - } ); + for ( const bindGroup of bindings ) { - backgroundBox = new Mesh( new BoxGeometry(), backgroundMaterial ); + const groupData = this.get( bindGroup ); - } + if ( groupData.bindGroup === undefined ) { - let useSolidColor = false; - const background = scene.background; + // each object defines an array of bindings (ubos, textures, samplers etc.) - if ( background ) { + this._init( bindGroup ); - if ( background.isColor ) { + this.backend.createBindings( bindGroup, bindings ); - backgroundBox.material.color.copy( background ); - scene.background = null; - useSolidColor = true; + groupData.bindGroup = bindGroup; } - } else { - - backgroundBox.material.color.copy( _clearColor$2 ); - useSolidColor = true; - } - renderer.setRenderTarget( cubeUVRenderTarget ); + return bindings; - renderer.clear(); + } - if ( useSolidColor ) { + getForCompute( computeNode ) { - renderer.render( backgroundBox, cubeCamera ); + const bindings = this.nodes.getForCompute( computeNode ).bindings; - } + for ( const bindGroup of bindings ) { - for ( let i = 0; i < 6; i ++ ) { + const groupData = this.get( bindGroup ); - const col = i % 3; + if ( groupData.bindGroup === undefined ) { - if ( col === 0 ) { + this._init( bindGroup ); - cubeCamera.up.set( 0, upSign[ i ], 0 ); - cubeCamera.lookAt( forwardSign[ i ], 0, 0 ); + this.backend.createBindings( bindGroup, bindings ); - } else if ( col === 1 ) { + groupData.bindGroup = bindGroup; - cubeCamera.up.set( 0, 0, upSign[ i ] ); - cubeCamera.lookAt( 0, forwardSign[ i ], 0 ); + } - } else { + } - cubeCamera.up.set( 0, upSign[ i ], 0 ); - cubeCamera.lookAt( 0, 0, forwardSign[ i ] ); + return bindings; - } + } - const size = this._cubeSize; + updateForCompute( computeNode ) { - _setViewport( cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size ); + this._updateBindings( this.getForCompute( computeNode ) ); - renderer.render( scene, cubeCamera ); + } - } + updateForRender( renderObject ) { - renderer.autoClear = originalAutoClear; - scene.background = background; + this._updateBindings( this.getForRender( renderObject ) ); } - _textureToCubeUV( texture, cubeUVRenderTarget ) { + _updateBindings( bindings ) { - const renderer = this._renderer; + for ( const bindGroup of bindings ) { - const isCubeTexture = ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ); + this._update( bindGroup, bindings ); - if ( isCubeTexture ) { + } - if ( this._cubemapMaterial === null ) { + } - this._cubemapMaterial = _getCubemapMaterial( texture ); + _init( bindGroup ) { - } + for ( const binding of bindGroup.bindings ) { - } else { + if ( binding.isSampledTexture ) { - if ( this._equirectMaterial === null ) { + this.textures.updateTexture( binding.texture ); - this._equirectMaterial = _getEquirectMaterial( texture ); + } else if ( binding.isStorageBuffer ) { + + const attribute = binding.attribute; + + this.attributes.update( attribute, AttributeType.STORAGE ); } } - const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial; - material.fragmentNode.value = texture; - - const mesh = this._lodMeshes[ 0 ]; - mesh.material = material; + } - const size = this._cubeSize; + _update( bindGroup, bindings ) { - _setViewport( cubeUVRenderTarget, 0, 0, 3 * size, 2 * size ); + const { backend } = this; - renderer.setRenderTarget( cubeUVRenderTarget ); - renderer.render( mesh, _flatCamera ); + let needsBindingsUpdate = false; - } + // iterate over all bindings and check if buffer updates or a new binding group is required - _applyPMREM( cubeUVRenderTarget ) { + for ( const binding of bindGroup.bindings ) { - const renderer = this._renderer; - const autoClear = renderer.autoClear; - renderer.autoClear = false; - const n = this._lodPlanes.length; + if ( binding.isNodeUniformsGroup ) { - for ( let i = 1; i < n; i ++ ) { + const updated = this.nodes.updateGroup( binding ); - const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] ); + if ( ! updated ) continue; - const poleAxis = _axisDirections[ ( n - i - 1 ) % _axisDirections.length ]; + } - this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis ); + if ( binding.isUniformBuffer ) { - } + const updated = binding.update(); - renderer.autoClear = autoClear; + if ( updated ) { - } + backend.updateBinding( binding ); - /** - * This is a two-pass Gaussian blur for a cubemap. Normally this is done - * vertically and horizontally, but this breaks down on a cube. Here we apply - * the blur latitudinally (around the poles), and then longitudinally (towards - * the poles) to approximate the orthogonally-separable blur. It is least - * accurate at the poles, but still does a decent job. - */ - _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) { + } - const pingPongRenderTarget = this._pingPongRenderTarget; + } else if ( binding.isSampler ) { - this._halfBlur( - cubeUVRenderTarget, - pingPongRenderTarget, - lodIn, - lodOut, - sigma, - 'latitudinal', - poleAxis ); + binding.update(); - this._halfBlur( - pingPongRenderTarget, - cubeUVRenderTarget, - lodOut, - lodOut, - sigma, - 'longitudinal', - poleAxis ); + } else if ( binding.isSampledTexture ) { - } + if ( binding.needsBindingsUpdate( this.textures.get( binding.texture ).generation ) ) needsBindingsUpdate = true; - _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) { + const updated = binding.update(); - const renderer = this._renderer; - const blurMaterial = this._blurMaterial; + const texture = binding.texture; - if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) { + if ( updated ) { - console.error( 'blur direction must be either latitudinal or longitudinal!' ); + this.textures.updateTexture( texture ); - } + } - // Number of standard deviations at which to cut off the discrete approximation. - const STANDARD_DEVIATIONS = 3; + const textureData = backend.get( texture ); - const blurMesh = this._lodMeshes[ lodOut ]; - blurMesh.material = blurMaterial; + if ( backend.isWebGPUBackend === true && textureData.texture === undefined && textureData.externalTexture === undefined ) { - const blurUniforms = blurMaterial.uniforms; + // TODO: Remove this once we found why updated === false isn't bound to a texture in the WebGPU backend + console.error( 'Bindings._update: binding should be available:', binding, updated, texture, binding.textureNode.value, needsBindingsUpdate ); - const pixels = this._sizeLods[ lodIn ] - 1; - const radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 ); - const sigmaPixels = sigmaRadians / radiansPerPixel; - const samples = isFinite( sigmaRadians ) ? 1 + Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES; + this.textures.updateTexture( texture ); + needsBindingsUpdate = true; - if ( samples > MAX_SAMPLES ) { + } - console.warn( `sigmaRadians, ${ - sigmaRadians}, is too large and will clip, as it requested ${ - samples} samples when the maximum is set to ${MAX_SAMPLES}` ); + if ( texture.isStorageTexture === true ) { - } + const textureData = this.get( texture ); - const weights = []; - let sum = 0; + if ( binding.store === true ) { - for ( let i = 0; i < MAX_SAMPLES; ++ i ) { + textureData.needsMipmap = true; - const x = i / sigmaPixels; - const weight = Math.exp( - x * x / 2 ); - weights.push( weight ); + } else if ( texture.generateMipmaps === true && this.textures.needsMipmaps( texture ) && textureData.needsMipmap === true ) { - if ( i === 0 ) { + this.backend.generateMipmaps( texture ); - sum += weight; + textureData.needsMipmap = false; - } else if ( i < samples ) { + } - sum += 2 * weight; + } } } - for ( let i = 0; i < weights.length; i ++ ) { + if ( needsBindingsUpdate === true ) { - weights[ i ] = weights[ i ] / sum; + this.backend.updateBindings( bindGroup, bindings ); } - targetIn.texture.frame = ( targetIn.texture.frame || 0 ) + 1; - - blurUniforms.envMap.value = targetIn.texture; - blurUniforms.samples.value = samples; - blurUniforms.weights.array = weights; - blurUniforms.latitudinal.value = direction === 'latitudinal' ? 1 : 0; - - if ( poleAxis ) { + } - blurUniforms.poleAxis.value = poleAxis; +} - } +class NodeAttribute { - const { _lodMax } = this; - blurUniforms.dTheta.value = radiansPerPixel; - blurUniforms.mipInt.value = _lodMax - lodIn; + constructor( name, type, node = null ) { - const outputSize = this._sizeLods[ lodOut ]; - const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 ); - const y = 4 * ( this._cubeSize - outputSize ); + this.isNodeAttribute = true; - _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize ); - renderer.setRenderTarget( targetOut ); - renderer.render( blurMesh, _flatCamera ); + this.name = name; + this.type = type; + this.node = node; } } -function _createPlanes( lodMax ) { +class NodeUniform { - const lodPlanes = []; - const sizeLods = []; - const sigmas = []; - const lodMeshes = []; + constructor( name, type, node ) { - let lod = lodMax; + this.isNodeUniform = true; - const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length; + this.name = name; + this.type = type; + this.node = node.getSelf(); - for ( let i = 0; i < totalLods; i ++ ) { + } - const sizeLod = Math.pow( 2, lod ); - sizeLods.push( sizeLod ); - let sigma = 1.0 / sizeLod; + get value() { - if ( i > lodMax - LOD_MIN ) { + return this.node.value; - sigma = EXTRA_LOD_SIGMA[ i - lodMax + LOD_MIN - 1 ]; + } - } else if ( i === 0 ) { + set value( val ) { - sigma = 0; + this.node.value = val; - } + } - sigmas.push( sigma ); + get id() { - const texelSize = 1.0 / ( sizeLod - 2 ); - const min = - texelSize; - const max = 1 + texelSize; - const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ]; + return this.node.id; - const cubeFaces = 6; - const vertices = 6; - const positionSize = 3; - const uvSize = 2; - const faceIndexSize = 1; + } - const position = new Float32Array( positionSize * vertices * cubeFaces ); - const uv = new Float32Array( uvSize * vertices * cubeFaces ); - const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces ); + get groupNode() { - for ( let face = 0; face < cubeFaces; face ++ ) { - - const x = ( face % 3 ) * 2 / 3 - 1; - const y = face > 2 ? 0 : - 1; - const coordinates = [ - x, y, 0, - x + 2 / 3, y, 0, - x + 2 / 3, y + 1, 0, - x, y, 0, - x + 2 / 3, y + 1, 0, - x, y + 1, 0 - ]; + return this.node.groupNode; - const faceIdx = _faceLib[ face ]; - position.set( coordinates, positionSize * vertices * faceIdx ); - uv.set( uv1, uvSize * vertices * faceIdx ); - const fill = [ faceIdx, faceIdx, faceIdx, faceIdx, faceIdx, faceIdx ]; - faceIndex.set( fill, faceIndexSize * vertices * faceIdx ); + } - } +} - const planes = new BufferGeometry(); - planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) ); - planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) ); - planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) ); - lodPlanes.push( planes ); - lodMeshes.push( new Mesh( planes, null ) ); +class NodeVar { - if ( lod > LOD_MIN ) { + constructor( name, type ) { - lod --; + this.isNodeVar = true; - } + this.name = name; + this.type = type; } - return { lodPlanes, sizeLods, sigmas, lodMeshes }; - -} - -function _createRenderTarget( width, height, params ) { - - const cubeUVRenderTarget = new RenderTarget( width, height, params ); - cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping; - cubeUVRenderTarget.texture.name = 'PMREM.cubeUv'; - cubeUVRenderTarget.texture.isPMREMTexture = true; - cubeUVRenderTarget.scissorTest = true; - return cubeUVRenderTarget; - } -function _setViewport( target, x, y, width, height ) { +class NodeVarying extends NodeVar { - target.viewport.set( x, y, width, height ); - target.scissor.set( x, y, width, height ); + constructor( name, type ) { -} + super( name, type ); -function _getMaterial( type ) { + this.needsInterpolation = false; - const material = new NodeMaterial(); - material.depthTest = false; - material.depthWrite = false; - material.blending = NoBlending; - material.name = `PMREM_${ type }`; + this.isNodeVarying = true; - return material; + } } -function _getBlurShader( lodMax, width, height ) { +class NodeCode { - const weights = uniformArray( new Array( MAX_SAMPLES ).fill( 0 ) ); - const poleAxis = uniform( new Vector3( 0, 1, 0 ) ); - const dTheta = uniform( 0 ); - const n = float( MAX_SAMPLES ); - const latitudinal = uniform( 0 ); // false, bool - const samples = uniform( 1 ); // int - const envMap = texture( null ); - const mipInt = uniform( 0 ); // int - const CUBEUV_TEXEL_WIDTH = float( 1 / width ); - const CUBEUV_TEXEL_HEIGHT = float( 1 / height ); - const CUBEUV_MAX_MIP = float( lodMax ); + constructor( name, type, code = '' ) { - const materialUniforms = { - n, - latitudinal, - weights, - poleAxis, - outputDirection, - dTheta, - samples, - envMap, - mipInt, - CUBEUV_TEXEL_WIDTH, - CUBEUV_TEXEL_HEIGHT, - CUBEUV_MAX_MIP - }; + this.name = name; + this.type = type; + this.code = code; - const material = _getMaterial( 'blur' ); - material.uniforms = materialUniforms; // TODO: Move to outside of the material - material.fragmentNode = blur( { ...materialUniforms, latitudinal: latitudinal.equal( 1 ) } ); + Object.defineProperty( this, 'isNodeCode', { value: true } ); - return material; + } } -function _getCubemapMaterial( envTexture ) { - - const material = _getMaterial( 'cubemap' ); - material.fragmentNode = cubeTexture( envTexture, outputDirection ); +let id$1 = 0; - return material; +class NodeCache { -} + constructor( parent = null ) { -function _getEquirectMaterial( envTexture ) { + this.id = id$1 ++; + this.nodesData = new WeakMap(); - const material = _getMaterial( 'equirect' ); - material.fragmentNode = texture( envTexture, equirectUV( outputDirection ), 0 ); + this.parent = parent; - return material; + } -} + getData( node ) { -let _id$5 = 0; + let data = this.nodesData.get( node ); -class BindGroup { + if ( data === undefined && this.parent !== null ) { - constructor( name = '', bindings = [], index = 0, bindingsReference = [] ) { + data = this.parent.getData( node ); - this.name = name; - this.bindings = bindings; - this.index = index; - this.bindingsReference = bindingsReference; + } - this.id = _id$5 ++; + return data; } -} + setData( node, data ) { -const rendererCache = new WeakMap(); + this.nodesData.set( node, data ); -const typeFromLength = new Map( [ - [ 2, 'vec2' ], - [ 3, 'vec3' ], - [ 4, 'vec4' ], - [ 9, 'mat3' ], - [ 16, 'mat4' ] -] ); + } -const typeFromArray = new Map( [ - [ Int8Array, 'int' ], - [ Int16Array, 'int' ], - [ Int32Array, 'int' ], - [ Uint8Array, 'uint' ], - [ Uint16Array, 'uint' ], - [ Uint32Array, 'uint' ], - [ Float32Array, 'float' ] -] ); +} -const toFloat = ( value ) => { +class ParameterNode extends PropertyNode { - value = Number( value ); + static get type() { - return value + ( value % 1 ? '' : '.0' ); + return 'ParameterNode'; -}; + } -class NodeBuilder { + constructor( nodeType, name = null ) { - constructor( object, renderer, parser ) { + super( nodeType, name ); - this.object = object; - this.material = ( object && object.material ) || null; - this.geometry = ( object && object.geometry ) || null; - this.renderer = renderer; - this.parser = parser; - this.scene = null; - this.camera = null; + this.isParameterNode = true; - this.nodes = []; - this.updateNodes = []; - this.updateBeforeNodes = []; - this.updateAfterNodes = []; - this.hashNodes = {}; + } - this.lightsNode = null; - this.environmentNode = null; - this.fogNode = null; + getHash() { - this.clippingContext = null; + return this.uuid; - this.vertexShader = null; - this.fragmentShader = null; - this.computeShader = null; + } - this.flowNodes = { vertex: [], fragment: [], compute: [] }; - this.flowCode = { vertex: '', fragment: '', compute: '' }; - this.uniforms = { vertex: [], fragment: [], compute: [], index: 0 }; - this.structs = { vertex: [], fragment: [], compute: [], index: 0 }; - this.bindings = { vertex: {}, fragment: {}, compute: {} }; - this.bindingsIndexes = {}; - this.bindGroups = null; - this.attributes = []; - this.bufferAttributes = []; - this.varyings = []; - this.codes = {}; - this.vars = {}; - this.flow = { code: '' }; - this.chaining = []; - this.stack = stack(); - this.stacks = []; - this.tab = '\t'; + generate() { - this.instanceBindGroups = true; + return this.name; - this.currentFunctionNode = null; + } - this.context = { - material: this.material - }; +} - this.cache = new NodeCache(); - this.globalCache = this.cache; +const parameter = ( type, name ) => nodeObject( new ParameterNode( type, name ) ); - this.flowsData = new WeakMap(); +class CodeNode extends Node { - this.shaderStage = null; - this.buildStage = null; + static get type() { - this.useComparisonMethod = false; + return 'CodeNode'; } - getBindGroupsCache() { + constructor( code = '', includes = [], language = '' ) { - let bindGroupsCache = rendererCache.get( this.renderer ); + super( 'code' ); - if ( bindGroupsCache === undefined ) { + this.isCodeNode = true; - bindGroupsCache = new ChainMap(); + this.code = code; + this.language = language; - rendererCache.set( this.renderer, bindGroupsCache ); + this.includes = includes; - } + } - return bindGroupsCache; + isGlobal() { + + return true; } - createRenderTarget( width, height, options ) { + setIncludes( includes ) { - return new RenderTarget( width, height, options ); + this.includes = includes; + + return this; } - createCubeRenderTarget( size, options ) { + getIncludes( /*builder*/ ) { - return new CubeRenderTarget( size, options ); + return this.includes; } - createPMREMGenerator() { + generate( builder ) { - // TODO: Move Materials.js to outside of the Nodes.js in order to remove this function and improve tree-shaking support + const includes = this.getIncludes( builder ); - return new PMREMGenerator( this.renderer ); + for ( const include of includes ) { - } + include.build( builder ); - includes( node ) { + } - return this.nodes.includes( node ); + const nodeCode = builder.getCodeFromNode( this, this.getNodeType( builder ) ); + nodeCode.code = this.code; - } + return nodeCode.code; - _getBindGroup( groupName, bindings ) { + } - const bindGroupsCache = this.getBindGroupsCache(); + serialize( data ) { - // + super.serialize( data ); - const bindingsArray = []; + data.code = this.code; + data.language = this.language; - let sharedGroup = true; + } - for ( const binding of bindings ) { + deserialize( data ) { - bindingsArray.push( binding ); + super.deserialize( data ); - sharedGroup = sharedGroup && binding.groupNode.shared !== true; + this.code = data.code; + this.language = data.language; - } + } - // +} - let bindGroup; +const code = /*@__PURE__*/ nodeProxy( CodeNode ); - if ( sharedGroup ) { +const js = ( src, includes ) => code( src, includes, 'js' ); +const wgsl = ( src, includes ) => code( src, includes, 'wgsl' ); +const glsl = ( src, includes ) => code( src, includes, 'glsl' ); - bindGroup = bindGroupsCache.get( bindingsArray ); +class FunctionNode extends CodeNode { - if ( bindGroup === undefined ) { + static get type() { - bindGroup = new BindGroup( groupName, bindingsArray, this.bindingsIndexes[ groupName ].group, bindingsArray ); + return 'FunctionNode'; - bindGroupsCache.set( bindingsArray, bindGroup ); + } - } + constructor( code = '', includes = [], language = '' ) { - } else { + super( code, includes, language ); - bindGroup = new BindGroup( groupName, bindingsArray, this.bindingsIndexes[ groupName ].group, bindingsArray ); + } - } + getNodeType( builder ) { - return bindGroup; + return this.getNodeFunction( builder ).type; } - getBindGroupArray( groupName, shaderStage ) { + getInputs( builder ) { - const bindings = this.bindings[ shaderStage ]; + return this.getNodeFunction( builder ).inputs; - let bindGroup = bindings[ groupName ]; + } - if ( bindGroup === undefined ) { + getNodeFunction( builder ) { - if ( this.bindingsIndexes[ groupName ] === undefined ) { + const nodeData = builder.getDataFromNode( this ); - this.bindingsIndexes[ groupName ] = { binding: 0, group: Object.keys( this.bindingsIndexes ).length }; + let nodeFunction = nodeData.nodeFunction; - } + if ( nodeFunction === undefined ) { - bindings[ groupName ] = bindGroup = []; + nodeFunction = builder.parser.parseFunction( this.code ); + + nodeData.nodeFunction = nodeFunction; } - return bindGroup; + return nodeFunction; } - getBindings() { - - let bindingsGroups = this.bindGroups; + generate( builder, output ) { - if ( bindingsGroups === null ) { + super.generate( builder ); - const groups = {}; - const bindings = this.bindings; + const nodeFunction = this.getNodeFunction( builder ); - for ( const shaderStage of shaderStages ) { + const name = nodeFunction.name; + const type = nodeFunction.type; - for ( const groupName in bindings[ shaderStage ] ) { + const nodeCode = builder.getCodeFromNode( this, type ); - const uniforms = bindings[ shaderStage ][ groupName ]; + if ( name !== '' ) { - const groupUniforms = groups[ groupName ] || ( groups[ groupName ] = [] ); - groupUniforms.push( ...uniforms ); + // use a custom property name - } + nodeCode.name = name; - } + } - bindingsGroups = []; + const propertyName = builder.getPropertyName( nodeCode ); - for ( const groupName in groups ) { + const code = this.getNodeFunction( builder ).getCode( propertyName ); - const group = groups[ groupName ]; + nodeCode.code = code + '\n'; - const bindingsGroup = this._getBindGroup( groupName, group ); + if ( output === 'property' ) { - bindingsGroups.push( bindingsGroup ); + return propertyName; - } + } else { - this.bindGroups = bindingsGroups; + return builder.format( `${ propertyName }()`, type, output ); } - return bindingsGroups; - } - setHashNode( node, hash ) { +} - this.hashNodes[ hash ] = node; +const nativeFn = ( code, includes = [], language = '' ) => { - } + for ( let i = 0; i < includes.length; i ++ ) { - addNode( node ) { + const include = includes[ i ]; - if ( this.nodes.includes( node ) === false ) { + // TSL Function: glslFn, wgslFn - this.nodes.push( node ); + if ( typeof include === 'function' ) { - this.setHashNode( node, node.getHash( this ) ); + includes[ i ] = include.functionNode; } } - buildUpdateNodes() { - - for ( const node of this.nodes ) { - - const updateType = node.getUpdateType(); - const updateBeforeType = node.getUpdateBeforeType(); - const updateAfterType = node.getUpdateAfterType(); - - if ( updateType !== NodeUpdateType.NONE ) { + const functionNode = nodeObject( new FunctionNode( code, includes, language ) ); - this.updateNodes.push( node.getSelf() ); + const fn = ( ...params ) => functionNode.call( ...params ); + fn.functionNode = functionNode; - } + return fn; - if ( updateBeforeType !== NodeUpdateType.NONE ) { +}; - this.updateBeforeNodes.push( node ); +const glslFn = ( code, includes ) => nativeFn( code, includes, 'glsl' ); +const wgslFn = ( code, includes ) => nativeFn( code, includes, 'wgsl' ); - } +class Uniform { - if ( updateAfterType !== NodeUpdateType.NONE ) { + constructor( name, value ) { - this.updateAfterNodes.push( node ); + this.name = name; + this.value = value; - } + this.boundary = 0; // used to build the uniform buffer according to the STD140 layout + this.itemSize = 0; - } + this.offset = 0; // this property is set by WebGPUUniformsGroup and marks the start position in the uniform buffer } - get currentNode() { + setValue( value ) { - return this.chaining[ this.chaining.length - 1 ]; + this.value = value; } - isFilteredTexture( texture ) { + getValue() { - return ( texture.magFilter === LinearFilter || texture.magFilter === LinearMipmapNearestFilter || texture.magFilter === NearestMipmapLinearFilter || texture.magFilter === LinearMipmapLinearFilter || - texture.minFilter === LinearFilter || texture.minFilter === LinearMipmapNearestFilter || texture.minFilter === NearestMipmapLinearFilter || texture.minFilter === LinearMipmapLinearFilter ); + return this.value; } - addChain( node ) { - - /* - if ( this.chaining.indexOf( node ) !== - 1 ) { +} - console.warn( 'Recursive node: ', node ); +class NumberUniform extends Uniform { - } - */ + constructor( name, value = 0 ) { - this.chaining.push( node ); + super( name, value ); - } + this.isNumberUniform = true; - removeChain( node ) { + this.boundary = 4; + this.itemSize = 1; - const lastChain = this.chaining.pop(); + } - if ( lastChain !== node ) { +} - throw new Error( 'NodeBuilder: Invalid node chaining!' ); +class Vector2Uniform extends Uniform { - } + constructor( name, value = new Vector2() ) { - } + super( name, value ); - getMethod( method ) { + this.isVector2Uniform = true; - return method; + this.boundary = 8; + this.itemSize = 2; } - getNodeFromHash( hash ) { +} - return this.hashNodes[ hash ]; +class Vector3Uniform extends Uniform { - } + constructor( name, value = new Vector3() ) { - addFlow( shaderStage, node ) { + super( name, value ); - this.flowNodes[ shaderStage ].push( node ); + this.isVector3Uniform = true; - return node; + this.boundary = 16; + this.itemSize = 3; } - setContext( context ) { +} - this.context = context; +class Vector4Uniform extends Uniform { - } + constructor( name, value = new Vector4() ) { - getContext() { + super( name, value ); - return this.context; + this.isVector4Uniform = true; + + this.boundary = 16; + this.itemSize = 4; } - getSharedContext() { +} - ({ ...this.context }); +class ColorUniform extends Uniform { - return this.context; + constructor( name, value = new Color() ) { - } + super( name, value ); - setCache( cache ) { + this.isColorUniform = true; - this.cache = cache; + this.boundary = 16; + this.itemSize = 3; } - getCache() { +} - return this.cache; +class Matrix3Uniform extends Uniform { - } + constructor( name, value = new Matrix3() ) { - getCacheFromNode( node, parent = true ) { + super( name, value ); - const data = this.getDataFromNode( node ); - if ( data.cache === undefined ) data.cache = new NodeCache( parent ? this.getCache() : null ); + this.isMatrix3Uniform = true; - return data.cache; + this.boundary = 48; + this.itemSize = 12; } - isAvailable( /*name*/ ) { +} - return false; +class Matrix4Uniform extends Uniform { - } + constructor( name, value = new Matrix4() ) { - getVertexIndex() { + super( name, value ); - console.warn( 'Abstract function.' ); + this.isMatrix4Uniform = true; + + this.boundary = 64; + this.itemSize = 16; } - getInstanceIndex() { +} - console.warn( 'Abstract function.' ); +class NumberNodeUniform extends NumberUniform { - } + constructor( nodeUniform ) { - getDrawIndex() { + super( nodeUniform.name, nodeUniform.value ); - console.warn( 'Abstract function.' ); + this.nodeUniform = nodeUniform; } - getFrontFacing() { + getValue() { - console.warn( 'Abstract function.' ); + return this.nodeUniform.value; } - getFragCoord() { +} - console.warn( 'Abstract function.' ); +class Vector2NodeUniform extends Vector2Uniform { - } + constructor( nodeUniform ) { - isFlipY() { + super( nodeUniform.name, nodeUniform.value ); - return false; + this.nodeUniform = nodeUniform; } - increaseUsage( node ) { - - const nodeData = this.getDataFromNode( node ); - nodeData.usageCount = nodeData.usageCount === undefined ? 1 : nodeData.usageCount + 1; + getValue() { - return nodeData.usageCount; + return this.nodeUniform.value; } - generateTexture( /* texture, textureProperty, uvSnippet */ ) { +} - console.warn( 'Abstract function.' ); +class Vector3NodeUniform extends Vector3Uniform { - } + constructor( nodeUniform ) { - generateTextureLod( /* texture, textureProperty, uvSnippet, levelSnippet */ ) { + super( nodeUniform.name, nodeUniform.value ); - console.warn( 'Abstract function.' ); + this.nodeUniform = nodeUniform; } - generateConst( type, value = null ) { + getValue() { - if ( value === null ) { + return this.nodeUniform.value; - if ( type === 'float' || type === 'int' || type === 'uint' ) value = 0; - else if ( type === 'bool' ) value = false; - else if ( type === 'color' ) value = new Color(); - else if ( type === 'vec2' ) value = new Vector2(); - else if ( type === 'vec3' ) value = new Vector3(); - else if ( type === 'vec4' ) value = new Vector4(); + } - } +} - if ( type === 'float' ) return toFloat( value ); - if ( type === 'int' ) return `${ Math.round( value ) }`; - if ( type === 'uint' ) return value >= 0 ? `${ Math.round( value ) }u` : '0u'; - if ( type === 'bool' ) return value ? 'true' : 'false'; - if ( type === 'color' ) return `${ this.getType( 'vec3' ) }( ${ toFloat( value.r ) }, ${ toFloat( value.g ) }, ${ toFloat( value.b ) } )`; +class Vector4NodeUniform extends Vector4Uniform { - const typeLength = this.getTypeLength( type ); + constructor( nodeUniform ) { - const componentType = this.getComponentType( type ); + super( nodeUniform.name, nodeUniform.value ); - const generateConst = value => this.generateConst( componentType, value ); + this.nodeUniform = nodeUniform; - if ( typeLength === 2 ) { + } - return `${ this.getType( type ) }( ${ generateConst( value.x ) }, ${ generateConst( value.y ) } )`; + getValue() { - } else if ( typeLength === 3 ) { + return this.nodeUniform.value; - return `${ this.getType( type ) }( ${ generateConst( value.x ) }, ${ generateConst( value.y ) }, ${ generateConst( value.z ) } )`; + } - } else if ( typeLength === 4 ) { +} - return `${ this.getType( type ) }( ${ generateConst( value.x ) }, ${ generateConst( value.y ) }, ${ generateConst( value.z ) }, ${ generateConst( value.w ) } )`; +class ColorNodeUniform extends ColorUniform { - } else if ( typeLength > 4 && value && ( value.isMatrix3 || value.isMatrix4 ) ) { + constructor( nodeUniform ) { - return `${ this.getType( type ) }( ${ value.elements.map( generateConst ).join( ', ' ) } )`; + super( nodeUniform.name, nodeUniform.value ); - } else if ( typeLength > 4 ) { + this.nodeUniform = nodeUniform; - return `${ this.getType( type ) }()`; + } - } + getValue() { - throw new Error( `NodeBuilder: Type '${type}' not found in generate constant attempt.` ); + return this.nodeUniform.value; } - getType( type ) { +} - if ( type === 'color' ) return 'vec3'; +class Matrix3NodeUniform extends Matrix3Uniform { - return type; + constructor( nodeUniform ) { + + super( nodeUniform.name, nodeUniform.value ); + + this.nodeUniform = nodeUniform; } - hasGeometryAttribute( name ) { + getValue() { - return this.geometry && this.geometry.getAttribute( name ) !== undefined; + return this.nodeUniform.value; } - getAttribute( name, type ) { +} - const attributes = this.attributes; +class Matrix4NodeUniform extends Matrix4Uniform { - // find attribute + constructor( nodeUniform ) { - for ( const attribute of attributes ) { + super( nodeUniform.name, nodeUniform.value ); - if ( attribute.name === name ) { + this.nodeUniform = nodeUniform; - return attribute; + } - } + getValue() { - } + return this.nodeUniform.value; - // create a new if no exist + } - const attribute = new NodeAttribute( name, type ); +} - attributes.push( attribute ); +class StackNode extends Node { - return attribute; + static get type() { + + return 'StackNode'; } - getPropertyName( node/*, shaderStage*/ ) { + constructor( parent = null ) { - return node.name; + super(); - } + this.nodes = []; + this.outputNode = null; - isVector( type ) { + this.parent = parent; - return /vec\d/.test( type ); + this._currentCond = null; + + this.isStackNode = true; } - isMatrix( type ) { + getNodeType( builder ) { - return /mat\d/.test( type ); + return this.outputNode ? this.outputNode.getNodeType( builder ) : 'void'; } - isReference( type ) { + add( node ) { - return type === 'void' || type === 'property' || type === 'sampler' || type === 'texture' || type === 'cubeTexture' || type === 'storageTexture' || type === 'depthTexture' || type === 'texture3D'; + this.nodes.push( node ); - } + return this; - needsToWorkingColorSpace( /*texture*/ ) { + } - return false; + If( boolNode, method ) { - } + const methodNode = new ShaderNode( method ); + this._currentCond = select( boolNode, methodNode ); - getComponentTypeFromTexture( texture ) { + return this.add( this._currentCond ); - const type = texture.type; + } - if ( texture.isDataTexture ) { + ElseIf( boolNode, method ) { - if ( type === IntType ) return 'int'; - if ( type === UnsignedIntType ) return 'uint'; + const methodNode = new ShaderNode( method ); + const ifNode = select( boolNode, methodNode ); - } + this._currentCond.elseNode = ifNode; + this._currentCond = ifNode; - return 'float'; + return this; } - getElementType( type ) { + Else( method ) { - if ( type === 'mat2' ) return 'vec2'; - if ( type === 'mat3' ) return 'vec3'; - if ( type === 'mat4' ) return 'vec4'; + this._currentCond.elseNode = new ShaderNode( method ); - return this.getComponentType( type ); + return this; } - getComponentType( type ) { + build( builder, ...params ) { - type = this.getVectorType( type ); + const previousStack = getCurrentStack(); - if ( type === 'float' || type === 'bool' || type === 'int' || type === 'uint' ) return type; + setCurrentStack( this ); - const componentType = /(b|i|u|)(vec|mat)([2-4])/.exec( type ); + for ( const node of this.nodes ) { - if ( componentType === null ) return null; + node.build( builder, 'void' ); - if ( componentType[ 1 ] === 'b' ) return 'bool'; - if ( componentType[ 1 ] === 'i' ) return 'int'; - if ( componentType[ 1 ] === 'u' ) return 'uint'; + } - return 'float'; + setCurrentStack( previousStack ); + + return this.outputNode ? this.outputNode.build( builder, ...params ) : super.build( builder, ...params ); } - getVectorType( type ) { + // - if ( type === 'color' ) return 'vec3'; - if ( type === 'texture' || type === 'cubeTexture' || type === 'storageTexture' || type === 'texture3D' ) return 'vec4'; + else( ...params ) { // @deprecated, r168 - return type; + console.warn( 'TSL.StackNode: .else() has been renamed to .Else().' ); + return this.Else( ...params ); } - getTypeFromLength( length, componentType = 'float' ) { - - if ( length === 1 ) return componentType; - - const baseType = typeFromLength.get( length ); - const prefix = componentType === 'float' ? '' : componentType[ 0 ]; + elseif( ...params ) { // @deprecated, r168 - return prefix + baseType; + console.warn( 'TSL.StackNode: .elseif() has been renamed to .ElseIf().' ); + return this.ElseIf( ...params ); } - getTypeFromArray( array ) { +} - return typeFromArray.get( array.constructor ); +const stack = /*@__PURE__*/ nodeProxy( StackNode ); - } +const LOD_MIN = 4; - getTypeFromAttribute( attribute ) { +// The standard deviations (radians) associated with the extra mips. These are +// chosen to approximate a Trowbridge-Reitz distribution function times the +// geometric shadowing function. These sigma values squared must match the +// variance #defines in cube_uv_reflection_fragment.glsl.js. +const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ]; - let dataAttribute = attribute; +// The maximum length of the blur for loop. Smaller sigmas will use fewer +// samples and exit early, but not recompile the shader. +const MAX_SAMPLES = 20; - if ( attribute.isInterleavedBufferAttribute ) dataAttribute = attribute.data; +const _flatCamera = /*@__PURE__*/ new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); +const _cubeCamera = /*@__PURE__*/ new PerspectiveCamera( 90, 1 ); +const _clearColor$2 = /*@__PURE__*/ new Color(); +let _oldTarget = null; +let _oldActiveCubeFace = 0; +let _oldActiveMipmapLevel = 0; - const array = dataAttribute.array; - const itemSize = attribute.itemSize; - const normalized = attribute.normalized; +// Golden Ratio +const PHI = ( 1 + Math.sqrt( 5 ) ) / 2; +const INV_PHI = 1 / PHI; - let arrayType; +// Vertices of a dodecahedron (except the opposites, which represent the +// same axis), used as axis directions evenly spread on a sphere. +const _axisDirections = [ + /*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ), + /*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ), + /*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ), + /*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ), + /*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ), + /*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ), + /*@__PURE__*/ new Vector3( - 1, 1, - 1 ), + /*@__PURE__*/ new Vector3( 1, 1, - 1 ), + /*@__PURE__*/ new Vector3( - 1, 1, 1 ), + /*@__PURE__*/ new Vector3( 1, 1, 1 ) +]; - if ( ! ( attribute instanceof Float16BufferAttribute ) && normalized !== true ) { +// - arrayType = this.getTypeFromArray( array ); +// WebGPU Face indices +const _faceLib = [ + 3, 1, 5, + 0, 4, 2 +]; - } +const direction = getDirection( uv(), attribute( 'faceIndex' ) ).normalize(); +const outputDirection = vec3( direction.x, direction.y.negate(), direction.z ); - return this.getTypeFromLength( itemSize, arrayType ); +/** + * This class generates a Prefiltered, Mipmapped Radiance Environment Map + * (PMREM) from a cubeMap environment texture. This allows different levels of + * blur to be quickly accessed based on material roughness. It is packed into a + * special CubeUV format that allows us to perform custom interpolation so that + * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap + * chain, it only goes down to the LOD_MIN level (above), and then creates extra + * even more filtered 'mips' at the same LOD_MIN resolution, associated with + * higher roughness levels. In this way we maintain resolution to smoothly + * interpolate diffuse lighting while limiting sampling computation. + * + * Paper: Fast, Accurate Image-Based Lighting + * https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view +*/ - } +class PMREMGenerator { - getTypeLength( type ) { + constructor( renderer ) { - const vecType = this.getVectorType( type ); - const vecNum = /vec([2-4])/.exec( vecType ); + this._renderer = renderer; + this._pingPongRenderTarget = null; - if ( vecNum !== null ) return Number( vecNum[ 1 ] ); - if ( vecType === 'float' || vecType === 'bool' || vecType === 'int' || vecType === 'uint' ) return 1; - if ( /mat2/.test( type ) === true ) return 4; - if ( /mat3/.test( type ) === true ) return 9; - if ( /mat4/.test( type ) === true ) return 16; + this._lodMax = 0; + this._cubeSize = 0; + this._lodPlanes = []; + this._sizeLods = []; + this._sigmas = []; + this._lodMeshes = []; - return 0; + this._blurMaterial = null; + this._cubemapMaterial = null; + this._equirectMaterial = null; + this._backgroundBox = null; } - getVectorFromMatrix( type ) { + /** + * Generates a PMREM from a supplied Scene, which can be faster than using an + * image if networking bandwidth is low. Optional sigma specifies a blur radius + * in radians to be applied to the scene before PMREM generation. Optional near + * and far planes ensure the scene is rendered in its entirety (the cubeCamera + * is placed at the origin). + */ + fromScene( scene, sigma = 0, near = 0.1, far = 100 ) { - return type.replace( 'mat', 'vec' ); + _oldTarget = this._renderer.getRenderTarget(); + _oldActiveCubeFace = this._renderer.getActiveCubeFace(); + _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); - } + this._setSize( 256 ); - changeComponentType( type, newComponentType ) { + const cubeUVRenderTarget = this._allocateTargets(); + cubeUVRenderTarget.depthBuffer = true; - return this.getTypeFromLength( this.getTypeLength( type ), newComponentType ); + this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget ); - } + if ( sigma > 0 ) { - getIntegerType( type ) { + this._blur( cubeUVRenderTarget, 0, 0, sigma ); - const componentType = this.getComponentType( type ); + } - if ( componentType === 'int' || componentType === 'uint' ) return type; + this._applyPMREM( cubeUVRenderTarget ); - return this.changeComponentType( type, 'int' ); + this._cleanup( cubeUVRenderTarget ); + + return cubeUVRenderTarget; } - addStack() { + /** + * Generates a PMREM from an equirectangular texture, which can be either LDR + * or HDR. The ideal input image size is 1k (1024 x 512), + * as this matches best with the 256 x 256 cubemap output. + */ + fromEquirectangular( equirectangular, renderTarget = null ) { - this.stack = stack( this.stack ); + return this._fromTexture( equirectangular, renderTarget ); - this.stacks.push( getCurrentStack() || this.stack ); - setCurrentStack( this.stack ); + } - return this.stack; + /** + * Generates a PMREM from an cubemap texture, which can be either LDR + * or HDR. The ideal input cube size is 256 x 256, + * as this matches best with the 256 x 256 cubemap output. + */ + fromCubemap( cubemap, renderTarget = null ) { + + return this._fromTexture( cubemap, renderTarget ); } - removeStack() { + /** + * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during + * your texture's network fetch for increased concurrency. + */ + async compileCubemapShader() { - const lastStack = this.stack; - this.stack = lastStack.parent; + if ( this._cubemapMaterial === null ) { - setCurrentStack( this.stacks.pop() ); + this._cubemapMaterial = _getCubemapMaterial(); + await this._compileMaterial( this._cubemapMaterial ); - return lastStack; + } } - getDataFromNode( node, shaderStage = this.shaderStage, cache = null ) { + /** + * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during + * your texture's network fetch for increased concurrency. + */ + async compileEquirectangularShader() { - cache = cache === null ? ( node.isGlobal( this ) ? this.globalCache : this.cache ) : cache; + if ( this._equirectMaterial === null ) { - let nodeData = cache.getData( node ); + this._equirectMaterial = _getEquirectMaterial(); + await this._compileMaterial( this._equirectMaterial ); - if ( nodeData === undefined ) { + } - nodeData = {}; + } - cache.setData( node, nodeData ); + /** + * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class, + * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on + * one of them will cause any others to also become unusable. + */ + dispose() { - } + this._dispose(); - if ( nodeData[ shaderStage ] === undefined ) nodeData[ shaderStage ] = {}; + if ( this._cubemapMaterial !== null ) this._cubemapMaterial.dispose(); + if ( this._equirectMaterial !== null ) this._equirectMaterial.dispose(); + if ( this._backgroundBox !== null ) { - return nodeData[ shaderStage ]; + this._backgroundBox.geometry.dispose(); + this._backgroundBox.material.dispose(); + + } } - getNodeProperties( node, shaderStage = 'any' ) { + // private interface - const nodeData = this.getDataFromNode( node, shaderStage ); + _setSize( cubeSize ) { - return nodeData.properties || ( nodeData.properties = { outputNode: null } ); + this._lodMax = Math.floor( Math.log2( cubeSize ) ); + this._cubeSize = Math.pow( 2, this._lodMax ); } - getBufferAttributeFromNode( node, type ) { - - const nodeData = this.getDataFromNode( node ); + _dispose() { - let bufferAttribute = nodeData.bufferAttribute; + if ( this._blurMaterial !== null ) this._blurMaterial.dispose(); - if ( bufferAttribute === undefined ) { + if ( this._pingPongRenderTarget !== null ) this._pingPongRenderTarget.dispose(); - const index = this.uniforms.index ++; + for ( let i = 0; i < this._lodPlanes.length; i ++ ) { - bufferAttribute = new NodeAttribute( 'nodeAttribute' + index, type, node ); + this._lodPlanes[ i ].dispose(); - this.bufferAttributes.push( bufferAttribute ); + } - nodeData.bufferAttribute = bufferAttribute; + } - } + _cleanup( outputTarget ) { - return bufferAttribute; + this._renderer.setRenderTarget( _oldTarget, _oldActiveCubeFace, _oldActiveMipmapLevel ); + outputTarget.scissorTest = false; + _setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height ); } - getStructTypeFromNode( node, shaderStage = this.shaderStage ) { - - const nodeData = this.getDataFromNode( node, shaderStage ); + _fromTexture( texture, renderTarget ) { - if ( nodeData.structType === undefined ) { + if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) { - const index = this.structs.index ++; + this._setSize( texture.image.length === 0 ? 16 : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) ); - node.name = `StructType${ index }`; - this.structs[ shaderStage ].push( node ); + } else { // Equirectangular - nodeData.structType = node; + this._setSize( texture.image.width / 4 ); } - return node; + _oldTarget = this._renderer.getRenderTarget(); + _oldActiveCubeFace = this._renderer.getActiveCubeFace(); + _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); - } + const cubeUVRenderTarget = renderTarget || this._allocateTargets(); + this._textureToCubeUV( texture, cubeUVRenderTarget ); + this._applyPMREM( cubeUVRenderTarget ); + this._cleanup( cubeUVRenderTarget ); - getUniformFromNode( node, type, shaderStage = this.shaderStage, name = null ) { + return cubeUVRenderTarget; - const nodeData = this.getDataFromNode( node, shaderStage, this.globalCache ); + } - let nodeUniform = nodeData.uniform; + _allocateTargets() { - if ( nodeUniform === undefined ) { + const width = 3 * Math.max( this._cubeSize, 16 * 7 ); + const height = 4 * this._cubeSize; - const index = this.uniforms.index ++; + const params = { + magFilter: LinearFilter, + minFilter: LinearFilter, + generateMipmaps: false, + type: HalfFloatType, + format: RGBAFormat, + colorSpace: LinearSRGBColorSpace, + //depthBuffer: false + }; - nodeUniform = new NodeUniform( name || ( 'nodeUniform' + index ), type, node ); + const cubeUVRenderTarget = _createRenderTarget( width, height, params ); - this.uniforms[ shaderStage ].push( nodeUniform ); + if ( this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width || this._pingPongRenderTarget.height !== height ) { - nodeData.uniform = nodeUniform; + if ( this._pingPongRenderTarget !== null ) { - } + this._dispose(); - return nodeUniform; + } - } + this._pingPongRenderTarget = _createRenderTarget( width, height, params ); - getVarFromNode( node, name = null, type = node.getNodeType( this ), shaderStage = this.shaderStage ) { + const { _lodMax } = this; + ( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas, lodMeshes: this._lodMeshes } = _createPlanes( _lodMax ) ); - const nodeData = this.getDataFromNode( node, shaderStage ); + this._blurMaterial = _getBlurShader( _lodMax, width, height ); - let nodeVar = nodeData.variable; + } - if ( nodeVar === undefined ) { + return cubeUVRenderTarget; - const vars = this.vars[ shaderStage ] || ( this.vars[ shaderStage ] = [] ); + } - if ( name === null ) name = 'nodeVar' + vars.length; + async _compileMaterial( material ) { - nodeVar = new NodeVar( name, type ); + const tmpMesh = new Mesh( this._lodPlanes[ 0 ], material ); + await this._renderer.compile( tmpMesh, _flatCamera ); - vars.push( nodeVar ); + } - nodeData.variable = nodeVar; - - } - - return nodeVar; + _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) { - } + const cubeCamera = _cubeCamera; + cubeCamera.near = near; + cubeCamera.far = far; - getVaryingFromNode( node, name = null, type = node.getNodeType( this ) ) { + // px, py, pz, nx, ny, nz + const upSign = [ - 1, 1, - 1, - 1, - 1, - 1 ]; + const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ]; - const nodeData = this.getDataFromNode( node, 'any' ); + const renderer = this._renderer; - let nodeVarying = nodeData.varying; + const originalAutoClear = renderer.autoClear; - if ( nodeVarying === undefined ) { + renderer.getClearColor( _clearColor$2 ); - const varyings = this.varyings; - const index = varyings.length; + renderer.autoClear = false; - if ( name === null ) name = 'nodeVarying' + index; + let backgroundBox = this._backgroundBox; - nodeVarying = new NodeVarying( name, type ); + if ( backgroundBox === null ) { - varyings.push( nodeVarying ); + const backgroundMaterial = new MeshBasicMaterial( { + name: 'PMREM.Background', + side: BackSide, + depthWrite: false, + depthTest: false + } ); - nodeData.varying = nodeVarying; + backgroundBox = new Mesh( new BoxGeometry(), backgroundMaterial ); } - return nodeVarying; - - } - - getCodeFromNode( node, type, shaderStage = this.shaderStage ) { - - const nodeData = this.getDataFromNode( node ); + let useSolidColor = false; + const background = scene.background; - let nodeCode = nodeData.code; + if ( background ) { - if ( nodeCode === undefined ) { + if ( background.isColor ) { - const codes = this.codes[ shaderStage ] || ( this.codes[ shaderStage ] = [] ); - const index = codes.length; + backgroundBox.material.color.copy( background ); + scene.background = null; + useSolidColor = true; - nodeCode = new NodeCode( 'nodeCode' + index, type ); + } - codes.push( nodeCode ); + } else { - nodeData.code = nodeCode; + backgroundBox.material.color.copy( _clearColor$2 ); + useSolidColor = true; } - return nodeCode; - - } - - addLineFlowCode( code ) { - - if ( code === '' ) return this; + renderer.setRenderTarget( cubeUVRenderTarget ); - code = this.tab + code; + renderer.clear(); - if ( ! /;\s*$/.test( code ) ) { + if ( useSolidColor ) { - code = code + ';\n'; + renderer.render( backgroundBox, cubeCamera ); } - this.flow.code += code; + for ( let i = 0; i < 6; i ++ ) { - return this; + const col = i % 3; - } + if ( col === 0 ) { - addFlowCode( code ) { + cubeCamera.up.set( 0, upSign[ i ], 0 ); + cubeCamera.lookAt( forwardSign[ i ], 0, 0 ); - this.flow.code += code; + } else if ( col === 1 ) { - return this; + cubeCamera.up.set( 0, 0, upSign[ i ] ); + cubeCamera.lookAt( 0, forwardSign[ i ], 0 ); - } + } else { - addFlowTab() { + cubeCamera.up.set( 0, upSign[ i ], 0 ); + cubeCamera.lookAt( 0, 0, forwardSign[ i ] ); - this.tab += '\t'; + } - return this; + const size = this._cubeSize; - } + _setViewport( cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size ); - removeFlowTab() { + renderer.render( scene, cubeCamera ); - this.tab = this.tab.slice( 0, - 1 ); + } - return this; + renderer.autoClear = originalAutoClear; + scene.background = background; } - getFlowData( node/*, shaderStage*/ ) { + _textureToCubeUV( texture, cubeUVRenderTarget ) { - return this.flowsData.get( node ); + const renderer = this._renderer; - } + const isCubeTexture = ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ); - flowNode( node ) { + if ( isCubeTexture ) { - const output = node.getNodeType( this ); + if ( this._cubemapMaterial === null ) { - const flowData = this.flowChildNode( node, output ); + this._cubemapMaterial = _getCubemapMaterial( texture ); - this.flowsData.set( node, flowData ); + } - return flowData; + } else { - } + if ( this._equirectMaterial === null ) { - buildFunctionNode( shaderNode ) { + this._equirectMaterial = _getEquirectMaterial( texture ); - const fn = new FunctionNode(); + } - const previous = this.currentFunctionNode; + } - this.currentFunctionNode = fn; + const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial; + material.fragmentNode.value = texture; - fn.code = this.buildFunctionCode( shaderNode ); + const mesh = this._lodMeshes[ 0 ]; + mesh.material = material; - this.currentFunctionNode = previous; + const size = this._cubeSize; - return fn; + _setViewport( cubeUVRenderTarget, 0, 0, 3 * size, 2 * size ); - } + renderer.setRenderTarget( cubeUVRenderTarget ); + renderer.render( mesh, _flatCamera ); - flowShaderNode( shaderNode ) { + } - const layout = shaderNode.layout; + _applyPMREM( cubeUVRenderTarget ) { - const inputs = { - [ Symbol.iterator ]() { + const renderer = this._renderer; + const autoClear = renderer.autoClear; + renderer.autoClear = false; + const n = this._lodPlanes.length; - let index = 0; - const values = Object.values( this ); - return { - next: () => ( { - value: values[ index ], - done: index ++ >= values.length - } ) - }; + for ( let i = 1; i < n; i ++ ) { - } - }; + const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] ); - for ( const input of layout.inputs ) { + const poleAxis = _axisDirections[ ( n - i - 1 ) % _axisDirections.length ]; - inputs[ input.name ] = new ParameterNode( input.type, input.name ); + this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis ); } - // - - shaderNode.layout = null; - - const callNode = shaderNode.call( inputs ); - const flowData = this.flowStagesNode( callNode, layout.type ); + renderer.autoClear = autoClear; - shaderNode.layout = layout; + } - return flowData; + /** + * This is a two-pass Gaussian blur for a cubemap. Normally this is done + * vertically and horizontally, but this breaks down on a cube. Here we apply + * the blur latitudinally (around the poles), and then longitudinally (towards + * the poles) to approximate the orthogonally-separable blur. It is least + * accurate at the poles, but still does a decent job. + */ + _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) { - } + const pingPongRenderTarget = this._pingPongRenderTarget; - flowStagesNode( node, output = null ) { + this._halfBlur( + cubeUVRenderTarget, + pingPongRenderTarget, + lodIn, + lodOut, + sigma, + 'latitudinal', + poleAxis ); - const previousFlow = this.flow; - const previousVars = this.vars; - const previousCache = this.cache; - const previousBuildStage = this.buildStage; - const previousStack = this.stack; + this._halfBlur( + pingPongRenderTarget, + cubeUVRenderTarget, + lodOut, + lodOut, + sigma, + 'longitudinal', + poleAxis ); - const flow = { - code: '' - }; + } - this.flow = flow; - this.vars = {}; - this.cache = new NodeCache(); - this.stack = stack(); + _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) { - for ( const buildStage of defaultBuildStages ) { + const renderer = this._renderer; + const blurMaterial = this._blurMaterial; - this.setBuildStage( buildStage ); + if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) { - flow.result = node.build( this, output ); + console.error( 'blur direction must be either latitudinal or longitudinal!' ); } - flow.vars = this.getVars( this.shaderStage ); + // Number of standard deviations at which to cut off the discrete approximation. + const STANDARD_DEVIATIONS = 3; - this.flow = previousFlow; - this.vars = previousVars; - this.cache = previousCache; - this.stack = previousStack; + const blurMesh = this._lodMeshes[ lodOut ]; + blurMesh.material = blurMaterial; - this.setBuildStage( previousBuildStage ); + const blurUniforms = blurMaterial.uniforms; - return flow; + const pixels = this._sizeLods[ lodIn ] - 1; + const radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 ); + const sigmaPixels = sigmaRadians / radiansPerPixel; + const samples = isFinite( sigmaRadians ) ? 1 + Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES; - } + if ( samples > MAX_SAMPLES ) { - getFunctionOperator() { + console.warn( `sigmaRadians, ${ + sigmaRadians}, is too large and will clip, as it requested ${ + samples} samples when the maximum is set to ${MAX_SAMPLES}` ); - return null; + } - } + const weights = []; + let sum = 0; - flowChildNode( node, output = null ) { + for ( let i = 0; i < MAX_SAMPLES; ++ i ) { - const previousFlow = this.flow; + const x = i / sigmaPixels; + const weight = Math.exp( - x * x / 2 ); + weights.push( weight ); - const flow = { - code: '' - }; + if ( i === 0 ) { - this.flow = flow; + sum += weight; - flow.result = node.build( this, output ); + } else if ( i < samples ) { - this.flow = previousFlow; + sum += 2 * weight; - return flow; + } - } + } - flowNodeFromShaderStage( shaderStage, node, output = null, propertyName = null ) { + for ( let i = 0; i < weights.length; i ++ ) { - const previousShaderStage = this.shaderStage; + weights[ i ] = weights[ i ] / sum; - this.setShaderStage( shaderStage ); + } - const flowData = this.flowChildNode( node, output ); + targetIn.texture.frame = ( targetIn.texture.frame || 0 ) + 1; - if ( propertyName !== null ) { + blurUniforms.envMap.value = targetIn.texture; + blurUniforms.samples.value = samples; + blurUniforms.weights.array = weights; + blurUniforms.latitudinal.value = direction === 'latitudinal' ? 1 : 0; - flowData.code += `${ this.tab + propertyName } = ${ flowData.result };\n`; + if ( poleAxis ) { + + blurUniforms.poleAxis.value = poleAxis; } - this.flowCode[ shaderStage ] = this.flowCode[ shaderStage ] + flowData.code; + const { _lodMax } = this; + blurUniforms.dTheta.value = radiansPerPixel; + blurUniforms.mipInt.value = _lodMax - lodIn; - this.setShaderStage( previousShaderStage ); + const outputSize = this._sizeLods[ lodOut ]; + const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 ); + const y = 4 * ( this._cubeSize - outputSize ); - return flowData; + _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize ); + renderer.setRenderTarget( targetOut ); + renderer.render( blurMesh, _flatCamera ); } - getAttributesArray() { +} - return this.attributes.concat( this.bufferAttributes ); +function _createPlanes( lodMax ) { - } + const lodPlanes = []; + const sizeLods = []; + const sigmas = []; + const lodMeshes = []; - getAttributes( /*shaderStage*/ ) { + let lod = lodMax; - console.warn( 'Abstract function.' ); + const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length; - } + for ( let i = 0; i < totalLods; i ++ ) { - getVaryings( /*shaderStage*/ ) { + const sizeLod = Math.pow( 2, lod ); + sizeLods.push( sizeLod ); + let sigma = 1.0 / sizeLod; - console.warn( 'Abstract function.' ); + if ( i > lodMax - LOD_MIN ) { - } + sigma = EXTRA_LOD_SIGMA[ i - lodMax + LOD_MIN - 1 ]; - getVar( type, name ) { + } else if ( i === 0 ) { - return `${ this.getType( type ) } ${ name }`; + sigma = 0; - } + } - getVars( shaderStage ) { + sigmas.push( sigma ); - let snippet = ''; + const texelSize = 1.0 / ( sizeLod - 2 ); + const min = - texelSize; + const max = 1 + texelSize; + const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ]; - const vars = this.vars[ shaderStage ]; + const cubeFaces = 6; + const vertices = 6; + const positionSize = 3; + const uvSize = 2; + const faceIndexSize = 1; - if ( vars !== undefined ) { + const position = new Float32Array( positionSize * vertices * cubeFaces ); + const uv = new Float32Array( uvSize * vertices * cubeFaces ); + const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces ); - for ( const variable of vars ) { + for ( let face = 0; face < cubeFaces; face ++ ) { - snippet += `${ this.getVar( variable.type, variable.name ) }; `; + const x = ( face % 3 ) * 2 / 3 - 1; + const y = face > 2 ? 0 : - 1; + const coordinates = [ + x, y, 0, + x + 2 / 3, y, 0, + x + 2 / 3, y + 1, 0, + x, y, 0, + x + 2 / 3, y + 1, 0, + x, y + 1, 0 + ]; - } + const faceIdx = _faceLib[ face ]; + position.set( coordinates, positionSize * vertices * faceIdx ); + uv.set( uv1, uvSize * vertices * faceIdx ); + const fill = [ faceIdx, faceIdx, faceIdx, faceIdx, faceIdx, faceIdx ]; + faceIndex.set( fill, faceIndexSize * vertices * faceIdx ); } - return snippet; + const planes = new BufferGeometry(); + planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) ); + planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) ); + planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) ); + lodPlanes.push( planes ); + lodMeshes.push( new Mesh( planes, null ) ); - } + if ( lod > LOD_MIN ) { - getUniforms( /*shaderStage*/ ) { + lod --; - console.warn( 'Abstract function.' ); + } } - getCodes( shaderStage ) { + return { lodPlanes, sizeLods, sigmas, lodMeshes }; - const codes = this.codes[ shaderStage ]; +} - let code = ''; +function _createRenderTarget( width, height, params ) { - if ( codes !== undefined ) { + const cubeUVRenderTarget = new RenderTarget( width, height, params ); + cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping; + cubeUVRenderTarget.texture.name = 'PMREM.cubeUv'; + cubeUVRenderTarget.texture.isPMREMTexture = true; + cubeUVRenderTarget.scissorTest = true; + return cubeUVRenderTarget; - for ( const nodeCode of codes ) { +} - code += nodeCode.code + '\n'; +function _setViewport( target, x, y, width, height ) { - } + target.viewport.set( x, y, width, height ); + target.scissor.set( x, y, width, height ); - } +} - return code; +function _getMaterial( type ) { - } + const material = new NodeMaterial(); + material.depthTest = false; + material.depthWrite = false; + material.blending = NoBlending; + material.name = `PMREM_${ type }`; - getHash() { + return material; - return this.vertexShader + this.fragmentShader + this.computeShader; +} - } +function _getBlurShader( lodMax, width, height ) { - setShaderStage( shaderStage ) { + const weights = uniformArray( new Array( MAX_SAMPLES ).fill( 0 ) ); + const poleAxis = uniform( new Vector3( 0, 1, 0 ) ); + const dTheta = uniform( 0 ); + const n = float( MAX_SAMPLES ); + const latitudinal = uniform( 0 ); // false, bool + const samples = uniform( 1 ); // int + const envMap = texture( null ); + const mipInt = uniform( 0 ); // int + const CUBEUV_TEXEL_WIDTH = float( 1 / width ); + const CUBEUV_TEXEL_HEIGHT = float( 1 / height ); + const CUBEUV_MAX_MIP = float( lodMax ); - this.shaderStage = shaderStage; + const materialUniforms = { + n, + latitudinal, + weights, + poleAxis, + outputDirection, + dTheta, + samples, + envMap, + mipInt, + CUBEUV_TEXEL_WIDTH, + CUBEUV_TEXEL_HEIGHT, + CUBEUV_MAX_MIP + }; - } + const material = _getMaterial( 'blur' ); + material.uniforms = materialUniforms; // TODO: Move to outside of the material + material.fragmentNode = blur( { ...materialUniforms, latitudinal: latitudinal.equal( 1 ) } ); - getShaderStage() { + return material; - return this.shaderStage; +} - } +function _getCubemapMaterial( envTexture ) { - setBuildStage( buildStage ) { + const material = _getMaterial( 'cubemap' ); + material.fragmentNode = cubeTexture( envTexture, outputDirection ); - this.buildStage = buildStage; + return material; - } +} - getBuildStage() { +function _getEquirectMaterial( envTexture ) { - return this.buildStage; + const material = _getMaterial( 'equirect' ); + material.fragmentNode = texture( envTexture, equirectUV( outputDirection ), 0 ); - } + return material; - buildCode() { +} - console.warn( 'Abstract function.' ); +let _id$5 = 0; - } +class BindGroup { - build() { + constructor( name = '', bindings = [], index = 0, bindingsReference = [] ) { - const { object, material, renderer } = this; + this.name = name; + this.bindings = bindings; + this.index = index; + this.bindingsReference = bindingsReference; - if ( material !== null ) { + this.id = _id$5 ++; - let nodeMaterial = renderer.nodes.library.fromMaterial( material ); + } - if ( nodeMaterial === null ) { +} - console.error( `NodeMaterial: Material "${ material.type }" is not compatible.` ); +const rendererCache = new WeakMap(); - nodeMaterial = new NodeMaterial(); +const typeFromLength = new Map( [ + [ 2, 'vec2' ], + [ 3, 'vec3' ], + [ 4, 'vec4' ], + [ 9, 'mat3' ], + [ 16, 'mat4' ] +] ); - } +const typeFromArray = new Map( [ + [ Int8Array, 'int' ], + [ Int16Array, 'int' ], + [ Int32Array, 'int' ], + [ Uint8Array, 'uint' ], + [ Uint16Array, 'uint' ], + [ Uint32Array, 'uint' ], + [ Float32Array, 'float' ] +] ); - nodeMaterial.build( this ); +const toFloat = ( value ) => { - } else { + value = Number( value ); - this.addFlow( 'compute', object ); + return value + ( value % 1 ? '' : '.0' ); - } +}; - // setup() -> stage 1: create possible new nodes and returns an output reference node - // analyze() -> stage 2: analyze nodes to possible optimization and validation - // generate() -> stage 3: generate shader +class NodeBuilder { - for ( const buildStage of defaultBuildStages ) { + constructor( object, renderer, parser ) { - this.setBuildStage( buildStage ); + this.object = object; + this.material = ( object && object.material ) || null; + this.geometry = ( object && object.geometry ) || null; + this.renderer = renderer; + this.parser = parser; + this.scene = null; + this.camera = null; - if ( this.context.vertex && this.context.vertex.isNode ) { + this.nodes = []; + this.updateNodes = []; + this.updateBeforeNodes = []; + this.updateAfterNodes = []; + this.hashNodes = {}; - this.flowNodeFromShaderStage( 'vertex', this.context.vertex ); + this.monitor = null; - } + this.lightsNode = null; + this.environmentNode = null; + this.fogNode = null; - for ( const shaderStage of shaderStages ) { + this.clippingContext = null; - this.setShaderStage( shaderStage ); + this.vertexShader = null; + this.fragmentShader = null; + this.computeShader = null; - const flowNodes = this.flowNodes[ shaderStage ]; + this.flowNodes = { vertex: [], fragment: [], compute: [] }; + this.flowCode = { vertex: '', fragment: '', compute: '' }; + this.uniforms = { vertex: [], fragment: [], compute: [], index: 0 }; + this.structs = { vertex: [], fragment: [], compute: [], index: 0 }; + this.bindings = { vertex: {}, fragment: {}, compute: {} }; + this.bindingsIndexes = {}; + this.bindGroups = null; + this.attributes = []; + this.bufferAttributes = []; + this.varyings = []; + this.codes = {}; + this.vars = {}; + this.flow = { code: '' }; + this.chaining = []; + this.stack = stack(); + this.stacks = []; + this.tab = '\t'; - for ( const node of flowNodes ) { + this.currentFunctionNode = null; - if ( buildStage === 'generate' ) { + this.context = { + material: this.material + }; - this.flowNode( node ); + this.cache = new NodeCache(); + this.globalCache = this.cache; - } else { + this.flowsData = new WeakMap(); - node.build( this ); + this.shaderStage = null; + this.buildStage = null; - } + this.useComparisonMethod = false; - } + } - } + getBindGroupsCache() { - } + let bindGroupsCache = rendererCache.get( this.renderer ); - this.setBuildStage( null ); - this.setShaderStage( null ); + if ( bindGroupsCache === undefined ) { - // stage 4: build code for a specific output + bindGroupsCache = new ChainMap(); - this.buildCode(); - this.buildUpdateNodes(); + rendererCache.set( this.renderer, bindGroupsCache ); - return this; + } - } + return bindGroupsCache; - getNodeUniform( uniformNode, type ) { + } - if ( type === 'float' || type === 'int' || type === 'uint' ) return new NumberNodeUniform( uniformNode ); - if ( type === 'vec2' || type === 'ivec2' || type === 'uvec2' ) return new Vector2NodeUniform( uniformNode ); - if ( type === 'vec3' || type === 'ivec3' || type === 'uvec3' ) return new Vector3NodeUniform( uniformNode ); - if ( type === 'vec4' || type === 'ivec4' || type === 'uvec4' ) return new Vector4NodeUniform( uniformNode ); - if ( type === 'color' ) return new ColorNodeUniform( uniformNode ); - if ( type === 'mat3' ) return new Matrix3NodeUniform( uniformNode ); - if ( type === 'mat4' ) return new Matrix4NodeUniform( uniformNode ); + createRenderTarget( width, height, options ) { - throw new Error( `Uniform "${type}" not declared.` ); + return new RenderTarget( width, height, options ); } - createNodeMaterial( type = 'NodeMaterial' ) { // @deprecated, r168 + createCubeRenderTarget( size, options ) { - throw new Error( `THREE.NodeBuilder: createNodeMaterial() was deprecated. Use new ${ type }() instead.` ); + return new CubeRenderTarget( size, options ); } - format( snippet, fromType, toType ) { - - fromType = this.getVectorType( fromType ); - toType = this.getVectorType( toType ); + createPMREMGenerator() { - if ( fromType === toType || toType === null || this.isReference( toType ) ) { + // TODO: Move Materials.js to outside of the Nodes.js in order to remove this function and improve tree-shaking support - return snippet; + return new PMREMGenerator( this.renderer ); - } + } - const fromTypeLength = this.getTypeLength( fromType ); - const toTypeLength = this.getTypeLength( toType ); + includes( node ) { - if ( fromTypeLength === 16 && toTypeLength === 9 ) { + return this.nodes.includes( node ); - return `${ this.getType( toType ) }(${ snippet }[0].xyz, ${ snippet }[1].xyz, ${ snippet }[2].xyz)`; + } - } + _getBindGroup( groupName, bindings ) { - if ( fromTypeLength === 9 && toTypeLength === 4 ) { + const bindGroupsCache = this.getBindGroupsCache(); - return `${ this.getType( toType ) }(${ snippet }[0].xy, ${ snippet }[1].xy)`; + // - } + const bindingsArray = []; + let sharedGroup = true; - if ( fromTypeLength > 4 ) { // fromType is matrix-like + for ( const binding of bindings ) { - // @TODO: ignore for now + bindingsArray.push( binding ); - return snippet; + sharedGroup = sharedGroup && binding.groupNode.shared !== true; } - if ( toTypeLength > 4 || toTypeLength === 0 ) { // toType is matrix-like or unknown + // - // @TODO: ignore for now + let bindGroup; - return snippet; + if ( sharedGroup ) { - } + bindGroup = bindGroupsCache.get( bindingsArray ); - if ( fromTypeLength === toTypeLength ) { + if ( bindGroup === undefined ) { - return `${ this.getType( toType ) }( ${ snippet } )`; + bindGroup = new BindGroup( groupName, bindingsArray, this.bindingsIndexes[ groupName ].group, bindingsArray ); - } + bindGroupsCache.set( bindingsArray, bindGroup ); - if ( fromTypeLength > toTypeLength ) { + } - return this.format( `${ snippet }.${ 'xyz'.slice( 0, toTypeLength ) }`, this.getTypeFromLength( toTypeLength, this.getComponentType( fromType ) ), toType ); + } else { + + bindGroup = new BindGroup( groupName, bindingsArray, this.bindingsIndexes[ groupName ].group, bindingsArray ); } - if ( toTypeLength === 4 && fromTypeLength > 1 ) { // toType is vec4-like + return bindGroup; - return `${ this.getType( toType ) }( ${ this.format( snippet, fromType, 'vec3' ) }, 1.0 )`; + } - } + getBindGroupArray( groupName, shaderStage ) { - if ( fromTypeLength === 2 ) { // fromType is vec2-like and toType is vec3-like + const bindings = this.bindings[ shaderStage ]; - return `${ this.getType( toType ) }( ${ this.format( snippet, fromType, 'vec2' ) }, 0.0 )`; + let bindGroup = bindings[ groupName ]; - } + if ( bindGroup === undefined ) { - if ( fromTypeLength === 1 && toTypeLength > 1 && fromType !== this.getComponentType( toType ) ) { // fromType is float-like + if ( this.bindingsIndexes[ groupName ] === undefined ) { - // convert a number value to vector type, e.g: - // vec3( 1u ) -> vec3( float( 1u ) ) + this.bindingsIndexes[ groupName ] = { binding: 0, group: Object.keys( this.bindingsIndexes ).length }; - snippet = `${ this.getType( this.getComponentType( toType ) ) }( ${ snippet } )`; + } + + bindings[ groupName ] = bindGroup = []; } - return `${ this.getType( toType ) }( ${ snippet } )`; // fromType is float-like + return bindGroup; } - getSignature() { + getBindings() { - return `// Three.js r${ REVISION } - Node System\n`; + let bindingsGroups = this.bindGroups; - } + if ( bindingsGroups === null ) { -} + const groups = {}; + const bindings = this.bindings; -class NodeFrame { + for ( const shaderStage of shaderStages ) { - constructor() { + for ( const groupName in bindings[ shaderStage ] ) { - this.time = 0; - this.deltaTime = 0; + const uniforms = bindings[ shaderStage ][ groupName ]; - this.frameId = 0; - this.renderId = 0; + const groupUniforms = groups[ groupName ] || ( groups[ groupName ] = [] ); + groupUniforms.push( ...uniforms ); - this.startTime = null; + } - this.updateMap = new WeakMap(); - this.updateBeforeMap = new WeakMap(); - this.updateAfterMap = new WeakMap(); + } - this.renderer = null; - this.material = null; - this.camera = null; - this.object = null; - this.scene = null; + bindingsGroups = []; - } + for ( const groupName in groups ) { - _getMaps( referenceMap, nodeRef ) { + const group = groups[ groupName ]; - let maps = referenceMap.get( nodeRef ); + const bindingsGroup = this._getBindGroup( groupName, group ); - if ( maps === undefined ) { + bindingsGroups.push( bindingsGroup ); - maps = { - renderMap: new WeakMap(), - frameMap: new WeakMap() - }; + } - referenceMap.set( nodeRef, maps ); + this.bindGroups = bindingsGroups; } - return maps; + return bindingsGroups; } - updateBeforeNode( node ) { - - const updateType = node.getUpdateBeforeType(); - const reference = node.updateReference( this ); - - if ( updateType === NodeUpdateType.FRAME ) { - - const { frameMap } = this._getMaps( this.updateBeforeMap, reference ); + sortBindingGroups() { - if ( frameMap.get( reference ) !== this.frameId ) { + const bindingsGroups = this.getBindings(); - if ( node.updateBefore( this ) !== false ) { + bindingsGroups.sort( ( a, b ) => ( a.bindings[ 0 ].groupNode.order - b.bindings[ 0 ].groupNode.order ) ); - frameMap.set( reference, this.frameId ); + for ( let i = 0; i < bindingsGroups.length; i ++ ) { - } + const bindingGroup = bindingsGroups[ i ]; + this.bindingsIndexes[ bindingGroup.name ].group = i; - } + bindingGroup.index = i; - } else if ( updateType === NodeUpdateType.RENDER ) { + } - const { renderMap } = this._getMaps( this.updateBeforeMap, reference ); + } - if ( renderMap.get( reference ) !== this.renderId ) { + setHashNode( node, hash ) { - if ( node.updateBefore( this ) !== false ) { + this.hashNodes[ hash ] = node; - renderMap.set( reference, this.renderId ); + } - } + addNode( node ) { - } + if ( this.nodes.includes( node ) === false ) { - } else if ( updateType === NodeUpdateType.OBJECT ) { + this.nodes.push( node ); - node.updateBefore( this ); + this.setHashNode( node, node.getHash( this ) ); } } - updateAfterNode( node ) { - - const updateType = node.getUpdateAfterType(); - const reference = node.updateReference( this ); - - if ( updateType === NodeUpdateType.FRAME ) { - - const { frameMap } = this._getMaps( this.updateAfterMap, reference ); + buildUpdateNodes() { - if ( frameMap.get( reference ) !== this.frameId ) { + for ( const node of this.nodes ) { - if ( node.updateAfter( this ) !== false ) { + const updateType = node.getUpdateType(); + const updateBeforeType = node.getUpdateBeforeType(); + const updateAfterType = node.getUpdateAfterType(); - frameMap.set( reference, this.frameId ); + if ( updateType !== NodeUpdateType.NONE ) { - } + this.updateNodes.push( node.getSelf() ); } - } else if ( updateType === NodeUpdateType.RENDER ) { - - const { renderMap } = this._getMaps( this.updateAfterMap, reference ); + if ( updateBeforeType !== NodeUpdateType.NONE ) { - if ( renderMap.get( reference ) !== this.renderId ) { + this.updateBeforeNodes.push( node.getSelf() ); - if ( node.updateAfter( this ) !== false ) { + } - renderMap.set( reference, this.renderId ); + if ( updateAfterType !== NodeUpdateType.NONE ) { - } + this.updateAfterNodes.push( node.getSelf() ); } - } else if ( updateType === NodeUpdateType.OBJECT ) { - - node.updateAfter( this ); - } } - updateNode( node ) { - - const updateType = node.getUpdateType(); - const reference = node.updateReference( this ); - - if ( updateType === NodeUpdateType.FRAME ) { + get currentNode() { - const { frameMap } = this._getMaps( this.updateMap, reference ); + return this.chaining[ this.chaining.length - 1 ]; - if ( frameMap.get( reference ) !== this.frameId ) { + } - if ( node.update( this ) !== false ) { + isFilteredTexture( texture ) { - frameMap.set( reference, this.frameId ); + return ( texture.magFilter === LinearFilter || texture.magFilter === LinearMipmapNearestFilter || texture.magFilter === NearestMipmapLinearFilter || texture.magFilter === LinearMipmapLinearFilter || + texture.minFilter === LinearFilter || texture.minFilter === LinearMipmapNearestFilter || texture.minFilter === NearestMipmapLinearFilter || texture.minFilter === LinearMipmapLinearFilter ); - } + } - } + addChain( node ) { - } else if ( updateType === NodeUpdateType.RENDER ) { + /* + if ( this.chaining.indexOf( node ) !== - 1 ) { - const { renderMap } = this._getMaps( this.updateMap, reference ); + console.warn( 'Recursive node: ', node ); - if ( renderMap.get( reference ) !== this.renderId ) { + } + */ - if ( node.update( this ) !== false ) { + this.chaining.push( node ); - renderMap.set( reference, this.renderId ); + } - } + removeChain( node ) { - } + const lastChain = this.chaining.pop(); - } else if ( updateType === NodeUpdateType.OBJECT ) { + if ( lastChain !== node ) { - node.update( this ); + throw new Error( 'NodeBuilder: Invalid node chaining!' ); } } - update() { - - this.frameId ++; - - if ( this.lastTime === undefined ) this.lastTime = performance.now(); - - this.deltaTime = ( performance.now() - this.lastTime ) / 1000; - - this.lastTime = performance.now(); + getMethod( method ) { - this.time += this.deltaTime; + return method; } -} - -class NodeFunctionInput { - - constructor( type, name, count = null, qualifier = '', isConst = false ) { + getNodeFromHash( hash ) { - this.type = type; - this.name = name; - this.count = count; - this.qualifier = qualifier; - this.isConst = isConst; + return this.hashNodes[ hash ]; } -} + addFlow( shaderStage, node ) { -NodeFunctionInput.isNodeFunctionInput = true; + this.flowNodes[ shaderStage ].push( node ); -class StructTypeNode extends Node { + return node; - constructor( types ) { + } - super(); + setContext( context ) { - this.types = types; - this.isStructTypeNode = true; + this.context = context; } - getMemberTypes() { + getContext() { - return this.types; + return this.context; } -} - -StructTypeNode.type = /*@__PURE__*/ registerNode( 'StructType', StructTypeNode ); + getSharedContext() { -class OutputStructNode extends Node { + ({ ...this.context }); - constructor( ...members ) { + return this.context; - super(); + } - this.members = members; + setCache( cache ) { - this.isOutputStructNode = true; + this.cache = cache; } - setup( builder ) { - - super.setup( builder ); + getCache() { - const members = this.members; - const types = []; + return this.cache; - for ( let i = 0; i < members.length; i ++ ) { + } - types.push( members[ i ].getNodeType( builder ) ); + getCacheFromNode( node, parent = true ) { - } + const data = this.getDataFromNode( node ); + if ( data.cache === undefined ) data.cache = new NodeCache( parent ? this.getCache() : null ); - this.nodeType = builder.getStructTypeFromNode( new StructTypeNode( types ) ).name; + return data.cache; } - generate( builder, output ) { + isAvailable( /*name*/ ) { - const propertyName = builder.getOutputStructName(); - const members = this.members; + return false; - const structPrefix = propertyName !== '' ? propertyName + '.' : ''; + } - for ( let i = 0; i < members.length; i ++ ) { + getVertexIndex() { - const snippet = members[ i ].build( builder, output ); + console.warn( 'Abstract function.' ); - builder.addLineFlowCode( `${ structPrefix }m${ i } = ${ snippet }` ); + } - } + getInstanceIndex() { - return propertyName; + console.warn( 'Abstract function.' ); } -} + getDrawIndex() { -OutputStructNode.type = /*@__PURE__*/ registerNode( 'OutputStruct', OutputStructNode ); + console.warn( 'Abstract function.' ); -const outputStruct = /*@__PURE__*/ nodeProxy( OutputStructNode ); + } -function getTextureIndex( textures, name ) { + getFrontFacing() { - for ( let i = 0; i < textures.length; i ++ ) { + console.warn( 'Abstract function.' ); - if ( textures[ i ].name === name ) { + } - return i; + getFragCoord() { - } + console.warn( 'Abstract function.' ); } - return - 1; - -} + isFlipY() { -class MRTNode extends OutputStructNode { + return false; - constructor( outputNodes ) { + } - super(); + increaseUsage( node ) { - this.outputNodes = outputNodes; + const nodeData = this.getDataFromNode( node ); + nodeData.usageCount = nodeData.usageCount === undefined ? 1 : nodeData.usageCount + 1; - this.isMRTNode = true; + return nodeData.usageCount; } - has( name ) { + generateTexture( /* texture, textureProperty, uvSnippet */ ) { - return this.outputNodes[ name ] !== undefined; + console.warn( 'Abstract function.' ); } - get( name ) { + generateTextureLod( /* texture, textureProperty, uvSnippet, levelSnippet */ ) { - return this.outputNodes[ name ]; + console.warn( 'Abstract function.' ); } - merge( mrtNode ) { + generateConst( type, value = null ) { - const outputs = { ...this.outputNodes, ...mrtNode.outputNodes }; + if ( value === null ) { - return mrt( outputs ); + if ( type === 'float' || type === 'int' || type === 'uint' ) value = 0; + else if ( type === 'bool' ) value = false; + else if ( type === 'color' ) value = new Color(); + else if ( type === 'vec2' ) value = new Vector2(); + else if ( type === 'vec3' ) value = new Vector3(); + else if ( type === 'vec4' ) value = new Vector4(); - } + } - setup( builder ) { + if ( type === 'float' ) return toFloat( value ); + if ( type === 'int' ) return `${ Math.round( value ) }`; + if ( type === 'uint' ) return value >= 0 ? `${ Math.round( value ) }u` : '0u'; + if ( type === 'bool' ) return value ? 'true' : 'false'; + if ( type === 'color' ) return `${ this.getType( 'vec3' ) }( ${ toFloat( value.r ) }, ${ toFloat( value.g ) }, ${ toFloat( value.b ) } )`; - const outputNodes = this.outputNodes; - const mrt = builder.renderer.getRenderTarget(); + const typeLength = this.getTypeLength( type ); - const members = []; + const componentType = this.getComponentType( type ); - const textures = mrt.textures; + const generateConst = value => this.generateConst( componentType, value ); - for ( const name in outputNodes ) { + if ( typeLength === 2 ) { - const index = getTextureIndex( textures, name ); + return `${ this.getType( type ) }( ${ generateConst( value.x ) }, ${ generateConst( value.y ) } )`; - members[ index ] = vec4( outputNodes[ name ] ); + } else if ( typeLength === 3 ) { - } + return `${ this.getType( type ) }( ${ generateConst( value.x ) }, ${ generateConst( value.y ) }, ${ generateConst( value.z ) } )`; - this.members = members; + } else if ( typeLength === 4 ) { - return super.setup( builder ); + return `${ this.getType( type ) }( ${ generateConst( value.x ) }, ${ generateConst( value.y ) }, ${ generateConst( value.z ) }, ${ generateConst( value.w ) } )`; - } + } else if ( typeLength > 4 && value && ( value.isMatrix3 || value.isMatrix4 ) ) { -} + return `${ this.getType( type ) }( ${ value.elements.map( generateConst ).join( ', ' ) } )`; -MRTNode.type = /*@__PURE__*/ registerNode( 'MRT', MRTNode ); + } else if ( typeLength > 4 ) { -const mrt = /*@__PURE__*/ nodeProxy( MRTNode ); + return `${ this.getType( type ) }()`; -class FunctionOverloadingNode extends Node { + } - constructor( functionNodes = [], ...parametersNodes ) { + throw new Error( `NodeBuilder: Type '${type}' not found in generate constant attempt.` ); - super(); + } - this.functionNodes = functionNodes; - this.parametersNodes = parametersNodes; + getType( type ) { - this._candidateFnCall = null; + if ( type === 'color' ) return 'vec3'; - this.global = true; + return type; } - getNodeType() { + hasGeometryAttribute( name ) { - return this.functionNodes[ 0 ].shaderNode.layout.type; + return this.geometry && this.geometry.getAttribute( name ) !== undefined; } - setup( builder ) { - - const params = this.parametersNodes; - - let candidateFnCall = this._candidateFnCall; + getAttribute( name, type ) { - if ( candidateFnCall === null ) { + const attributes = this.attributes; - let candidateFn = null; - let candidateScore = - 1; + // find attribute - for ( const functionNode of this.functionNodes ) { + for ( const attribute of attributes ) { - const shaderNode = functionNode.shaderNode; - const layout = shaderNode.layout; + if ( attribute.name === name ) { - if ( layout === null ) { + return attribute; - throw new Error( 'FunctionOverloadingNode: FunctionNode must be a layout.' ); + } - } + } - const inputs = layout.inputs; + // create a new if no exist - if ( params.length === inputs.length ) { + const attribute = new NodeAttribute( name, type ); - let score = 0; + attributes.push( attribute ); - for ( let i = 0; i < params.length; i ++ ) { + return attribute; - const param = params[ i ]; - const input = inputs[ i ]; + } - if ( param.getNodeType( builder ) === input.type ) { + getPropertyName( node/*, shaderStage*/ ) { - score ++; + return node.name; - } else { + } - score = 0; + isVector( type ) { - } + return /vec\d/.test( type ); - } + } - if ( score > candidateScore ) { + isMatrix( type ) { - candidateFn = functionNode; - candidateScore = score; + return /mat\d/.test( type ); - } + } - } + isReference( type ) { - } + return type === 'void' || type === 'property' || type === 'sampler' || type === 'texture' || type === 'cubeTexture' || type === 'storageTexture' || type === 'depthTexture' || type === 'texture3D'; - this._candidateFnCall = candidateFnCall = candidateFn( ...params ); + } - } + needsToWorkingColorSpace( /*texture*/ ) { - return candidateFnCall; + return false; } -} + getComponentTypeFromTexture( texture ) { -FunctionOverloadingNode.type = /*@__PURE__*/ registerNode( 'FunctionOverloading', FunctionOverloadingNode ); + const type = texture.type; -const overloadingBaseFn = /*@__PURE__*/ nodeProxy( FunctionOverloadingNode ); + if ( texture.isDataTexture ) { -const overloadingFn = ( functionNodes ) => ( ...params ) => overloadingBaseFn( functionNodes, ...params ); + if ( type === IntType ) return 'int'; + if ( type === UnsignedIntType ) return 'uint'; -class TimerNode extends UniformNode { + } - constructor( scope = TimerNode.LOCAL, scale = 1, value = 0 ) { + return 'float'; - super( value ); + } - this.scope = scope; - this.scale = scale; + getElementType( type ) { - this.updateType = NodeUpdateType.FRAME; + if ( type === 'mat2' ) return 'vec2'; + if ( type === 'mat3' ) return 'vec3'; + if ( type === 'mat4' ) return 'vec4'; + + return this.getComponentType( type ); } - /* - @TODO: - getNodeType( builder ) { - const scope = this.scope; + getComponentType( type ) { - if ( scope === TimerNode.FRAME ) { + type = this.getVectorType( type ); - return 'uint'; + if ( type === 'float' || type === 'bool' || type === 'int' || type === 'uint' ) return type; - } + const componentType = /(b|i|u|)(vec|mat)([2-4])/.exec( type ); + + if ( componentType === null ) return null; + + if ( componentType[ 1 ] === 'b' ) return 'bool'; + if ( componentType[ 1 ] === 'i' ) return 'int'; + if ( componentType[ 1 ] === 'u' ) return 'uint'; return 'float'; } -*/ - update( frame ) { - const scope = this.scope; - const scale = this.scale; + getVectorType( type ) { - if ( scope === TimerNode.LOCAL ) { + if ( type === 'color' ) return 'vec3'; + if ( type === 'texture' || type === 'cubeTexture' || type === 'storageTexture' || type === 'texture3D' ) return 'vec4'; - this.value += frame.deltaTime * scale; + return type; - } else if ( scope === TimerNode.DELTA ) { + } - this.value = frame.deltaTime * scale; + getTypeFromLength( length, componentType = 'float' ) { - } else if ( scope === TimerNode.FRAME ) { + if ( length === 1 ) return componentType; - this.value = frame.frameId; + const baseType = typeFromLength.get( length ); + const prefix = componentType === 'float' ? '' : componentType[ 0 ]; - } else { + return prefix + baseType; - // global + } - this.value = frame.time * scale; + getTypeFromArray( array ) { - } + return typeFromArray.get( array.constructor ); } - serialize( data ) { - - super.serialize( data ); - - data.scope = this.scope; - data.scale = this.scale; + getTypeFromAttribute( attribute ) { - } + let dataAttribute = attribute; - deserialize( data ) { + if ( attribute.isInterleavedBufferAttribute ) dataAttribute = attribute.data; - super.deserialize( data ); + const array = dataAttribute.array; + const itemSize = attribute.itemSize; + const normalized = attribute.normalized; - this.scope = data.scope; - this.scale = data.scale; + let arrayType; - } + if ( ! ( attribute instanceof Float16BufferAttribute ) && normalized !== true ) { -} + arrayType = this.getTypeFromArray( array ); -TimerNode.LOCAL = 'local'; -TimerNode.GLOBAL = 'global'; -TimerNode.DELTA = 'delta'; -TimerNode.FRAME = 'frame'; + } -TimerNode.type = /*@__PURE__*/ registerNode( 'Timer', TimerNode ); + return this.getTypeFromLength( itemSize, arrayType ); -// @TODO: add support to use node in timeScale -const timerLocal = ( timeScale, value = 0 ) => nodeObject( new TimerNode( TimerNode.LOCAL, timeScale, value ) ); -const timerGlobal = ( timeScale, value = 0 ) => nodeObject( new TimerNode( TimerNode.GLOBAL, timeScale, value ) ); -const timerDelta = ( timeScale, value = 0 ) => nodeObject( new TimerNode( TimerNode.DELTA, timeScale, value ) ); -const frameId = /*@__PURE__*/ nodeImmutable( TimerNode, TimerNode.FRAME ).toUint(); + } -class OscNode extends Node { + getTypeLength( type ) { - constructor( method = OscNode.SINE, timeNode = timerLocal() ) { + const vecType = this.getVectorType( type ); + const vecNum = /vec([2-4])/.exec( vecType ); - super(); + if ( vecNum !== null ) return Number( vecNum[ 1 ] ); + if ( vecType === 'float' || vecType === 'bool' || vecType === 'int' || vecType === 'uint' ) return 1; + if ( /mat2/.test( type ) === true ) return 4; + if ( /mat3/.test( type ) === true ) return 9; + if ( /mat4/.test( type ) === true ) return 16; - this.method = method; - this.timeNode = timeNode; + return 0; } - getNodeType( builder ) { + getVectorFromMatrix( type ) { - return this.timeNode.getNodeType( builder ); + return type.replace( 'mat', 'vec' ); } - setup() { - - const method = this.method; - const timeNode = nodeObject( this.timeNode ); + changeComponentType( type, newComponentType ) { - let outputNode = null; + return this.getTypeFromLength( this.getTypeLength( type ), newComponentType ); - if ( method === OscNode.SINE ) { + } - outputNode = timeNode.add( 0.75 ).mul( Math.PI * 2 ).sin().mul( 0.5 ).add( 0.5 ); + getIntegerType( type ) { - } else if ( method === OscNode.SQUARE ) { + const componentType = this.getComponentType( type ); - outputNode = timeNode.fract().round(); + if ( componentType === 'int' || componentType === 'uint' ) return type; - } else if ( method === OscNode.TRIANGLE ) { + return this.changeComponentType( type, 'int' ); - outputNode = timeNode.add( 0.5 ).fract().mul( 2 ).sub( 1 ).abs(); + } - } else if ( method === OscNode.SAWTOOTH ) { + addStack() { - outputNode = timeNode.fract(); + this.stack = stack( this.stack ); - } + this.stacks.push( getCurrentStack() || this.stack ); + setCurrentStack( this.stack ); - return outputNode; + return this.stack; } - serialize( data ) { + removeStack() { - super.serialize( data ); + const lastStack = this.stack; + this.stack = lastStack.parent; - data.method = this.method; + setCurrentStack( this.stacks.pop() ); + + return lastStack; } - deserialize( data ) { + getDataFromNode( node, shaderStage = this.shaderStage, cache = null ) { - super.deserialize( data ); + cache = cache === null ? ( node.isGlobal( this ) ? this.globalCache : this.cache ) : cache; - this.method = data.method; + let nodeData = cache.getData( node ); - } + if ( nodeData === undefined ) { -} + nodeData = {}; -OscNode.SINE = 'sine'; -OscNode.SQUARE = 'square'; -OscNode.TRIANGLE = 'triangle'; -OscNode.SAWTOOTH = 'sawtooth'; + cache.setData( node, nodeData ); -OscNode.type = /*@__PURE__*/ registerNode( 'Osc', OscNode ); + } -const oscSine = /*@__PURE__*/ nodeProxy( OscNode, OscNode.SINE ); -const oscSquare = /*@__PURE__*/ nodeProxy( OscNode, OscNode.SQUARE ); -const oscTriangle = /*@__PURE__*/ nodeProxy( OscNode, OscNode.TRIANGLE ); -const oscSawtooth = /*@__PURE__*/ nodeProxy( OscNode, OscNode.SAWTOOTH ); + if ( nodeData[ shaderStage ] === undefined ) nodeData[ shaderStage ] = {}; -class SpriteSheetUVNode extends Node { + return nodeData[ shaderStage ]; - constructor( countNode, uvNode = uv(), frameNode = float( 0 ) ) { + } - super( 'vec2' ); + getNodeProperties( node, shaderStage = 'any' ) { - this.countNode = countNode; - this.uvNode = uvNode; - this.frameNode = frameNode; + const nodeData = this.getDataFromNode( node, shaderStage ); + + return nodeData.properties || ( nodeData.properties = { outputNode: null } ); } - setup() { + getBufferAttributeFromNode( node, type ) { - const { frameNode, uvNode, countNode } = this; + const nodeData = this.getDataFromNode( node ); - const { width, height } = countNode; + let bufferAttribute = nodeData.bufferAttribute; - const frameNum = frameNode.mod( width.mul( height ) ).floor(); + if ( bufferAttribute === undefined ) { - const column = frameNum.mod( width ); - const row = height.sub( frameNum.add( 1 ).div( width ).ceil() ); + const index = this.uniforms.index ++; - const scale = countNode.reciprocal(); - const uvFrameOffset = vec2( column, row ); + bufferAttribute = new NodeAttribute( 'nodeAttribute' + index, type, node ); - return uvNode.add( uvFrameOffset ).mul( scale ); + this.bufferAttributes.push( bufferAttribute ); - } + nodeData.bufferAttribute = bufferAttribute; -} + } -SpriteSheetUVNode.type = /*@__PURE__*/ registerNode( 'SpriteSheetUV', SpriteSheetUVNode ); + return bufferAttribute; -const spritesheetUV = /*@__PURE__*/ nodeProxy( SpriteSheetUVNode ); + } -class StorageArrayElementNode extends ArrayElementNode { + getStructTypeFromNode( node, shaderStage = this.shaderStage ) { - constructor( storageBufferNode, indexNode ) { + const nodeData = this.getDataFromNode( node, shaderStage ); - super( storageBufferNode, indexNode ); + if ( nodeData.structType === undefined ) { - this.isStorageArrayElementNode = true; + const index = this.structs.index ++; - } + node.name = `StructType${ index }`; + this.structs[ shaderStage ].push( node ); - set storageBufferNode( value ) { + nodeData.structType = node; - this.node = value; + } + + return node; } - get storageBufferNode() { + getUniformFromNode( node, type, shaderStage = this.shaderStage, name = null ) { - return this.node; + const nodeData = this.getDataFromNode( node, shaderStage, this.globalCache ); - } + let nodeUniform = nodeData.uniform; - setup( builder ) { + if ( nodeUniform === undefined ) { - if ( builder.isAvailable( 'storageBuffer' ) === false ) { + const index = this.uniforms.index ++; - if ( ! this.node.instanceIndex && this.node.bufferObject === true ) { + nodeUniform = new NodeUniform( name || ( 'nodeUniform' + index ), type, node ); - builder.setupPBO( this.node ); + this.uniforms[ shaderStage ].push( nodeUniform ); - } + nodeData.uniform = nodeUniform; } - return super.setup( builder ); + return nodeUniform; } - generate( builder, output ) { + getVarFromNode( node, name = null, type = node.getNodeType( this ), shaderStage = this.shaderStage ) { - let snippet; + const nodeData = this.getDataFromNode( node, shaderStage ); - const isAssignContext = builder.context.assign; + let nodeVar = nodeData.variable; - // + if ( nodeVar === undefined ) { - if ( builder.isAvailable( 'storageBuffer' ) === false ) { + const vars = this.vars[ shaderStage ] || ( this.vars[ shaderStage ] = [] ); - const { node } = this; + if ( name === null ) name = 'nodeVar' + vars.length; - if ( ! node.instanceIndex && this.node.bufferObject === true && isAssignContext !== true ) { + nodeVar = new NodeVar( name, type ); - snippet = builder.generatePBO( this ); + vars.push( nodeVar ); - } else { + nodeData.variable = nodeVar; - snippet = node.build( builder ); + } - } + return nodeVar; - } else { + } - snippet = super.generate( builder ); + getVaryingFromNode( node, name = null, type = node.getNodeType( this ) ) { - } + const nodeData = this.getDataFromNode( node, 'any' ); - if ( isAssignContext !== true ) { + let nodeVarying = nodeData.varying; - const type = this.getNodeType( builder ); + if ( nodeVarying === undefined ) { - snippet = builder.format( snippet, type, output ); + const varyings = this.varyings; + const index = varyings.length; + + if ( name === null ) name = 'nodeVarying' + index; + + nodeVarying = new NodeVarying( name, type ); + + varyings.push( nodeVarying ); + + nodeData.varying = nodeVarying; } - return snippet; + return nodeVarying; } -} + getCodeFromNode( node, type, shaderStage = this.shaderStage ) { -StorageArrayElementNode.type = /*@__PURE__*/ registerNode( 'StorageArrayElement', StorageArrayElementNode ); + const nodeData = this.getDataFromNode( node ); -const storageElement = /*@__PURE__*/ nodeProxy( StorageArrayElementNode ); + let nodeCode = nodeData.code; -class TriplanarTexturesNode extends Node { + if ( nodeCode === undefined ) { - constructor( textureXNode, textureYNode = null, textureZNode = null, scaleNode = float( 1 ), positionNode = positionLocal, normalNode = normalLocal ) { + const codes = this.codes[ shaderStage ] || ( this.codes[ shaderStage ] = [] ); + const index = codes.length; - super( 'vec4' ); + nodeCode = new NodeCode( 'nodeCode' + index, type ); - this.textureXNode = textureXNode; - this.textureYNode = textureYNode; - this.textureZNode = textureZNode; + codes.push( nodeCode ); - this.scaleNode = scaleNode; + nodeData.code = nodeCode; - this.positionNode = positionNode; - this.normalNode = normalNode; + } - } + return nodeCode; - setup() { + } - const { textureXNode, textureYNode, textureZNode, scaleNode, positionNode, normalNode } = this; + addFlowCodeHierarchy( node, nodeBlock ) { - // Ref: https://github.com/keijiro/StandardTriplanar + const { flowCodes, flowCodeBlock } = this.getDataFromNode( node ); - // Blending factor of triplanar mapping - let bf = normalNode.abs().normalize(); - bf = bf.div( bf.dot( vec3( 1.0 ) ) ); + let needsFlowCode = true; + let nodeBlockHierarchy = nodeBlock; - // Triplanar mapping - const tx = positionNode.yz.mul( scaleNode ); - const ty = positionNode.zx.mul( scaleNode ); - const tz = positionNode.xy.mul( scaleNode ); + while ( nodeBlockHierarchy ) { - // Base color - const textureX = textureXNode.value; - const textureY = textureYNode !== null ? textureYNode.value : textureX; - const textureZ = textureZNode !== null ? textureZNode.value : textureX; + if ( flowCodeBlock.get( nodeBlockHierarchy ) === true ) { - const cx = texture( textureX, tx ).mul( bf.x ); - const cy = texture( textureY, ty ).mul( bf.y ); - const cz = texture( textureZ, tz ).mul( bf.z ); + needsFlowCode = false; + break; - return add( cx, cy, cz ); + } - } + nodeBlockHierarchy = this.getDataFromNode( nodeBlockHierarchy ).parentNodeBlock; -} + } -TriplanarTexturesNode.type = /*@__PURE__*/ registerNode( 'TriplanarTextures', TriplanarTexturesNode ); + if ( needsFlowCode ) { -const triplanarTextures = /*@__PURE__*/ nodeProxy( TriplanarTexturesNode ); -const triplanarTexture = ( ...params ) => triplanarTextures( ...params ); + for ( const flowCode of flowCodes ) { -const _reflectorPlane = new Plane(); -const _normal = new Vector3(); -const _reflectorWorldPosition = new Vector3(); -const _cameraWorldPosition = new Vector3(); -const _rotationMatrix = new Matrix4(); -const _lookAtPosition = new Vector3( 0, 0, - 1 ); -const clipPlane = new Vector4(); + this.addLineFlowCode( flowCode ); -const _view = new Vector3(); -const _target = new Vector3(); -const _q = new Vector4(); + } -const _size$9 = new Vector2(); + } -const _defaultRT = new RenderTarget(); -const _defaultUV = viewportUV.flipX(); + } -let _inReflector = false; + addLineFlowCodeBlock( node, code, nodeBlock ) { -class ReflectorNode extends TextureNode { + const nodeData = this.getDataFromNode( node ); + const flowCodes = nodeData.flowCodes || ( nodeData.flowCodes = [] ); + const codeBlock = nodeData.flowCodeBlock || ( nodeData.flowCodeBlock = new WeakMap() ); - constructor( parameters = {} ) { + flowCodes.push( code ); + codeBlock.set( nodeBlock, true ); - super( _defaultRT.texture, _defaultUV ); + } - const { - target = new Object3D(), - resolution = 1, - generateMipmaps = false, - bounces = true - } = parameters; + addLineFlowCode( code, node = null ) { - // + if ( code === '' ) return this; - this.target = target; - this.resolution = resolution; - this.generateMipmaps = generateMipmaps; - this.bounces = bounces; + if ( node !== null && this.context.nodeBlock ) { - this.updateBeforeType = bounces ? NodeUpdateType.RENDER : NodeUpdateType.FRAME; + this.addLineFlowCodeBlock( node, code, this.context.nodeBlock ); - this.virtualCameras = new WeakMap(); - this.renderTargets = new WeakMap(); + } + code = this.tab + code; - } + if ( ! /;\s*$/.test( code ) ) { - _updateResolution( renderTarget, renderer ) { + code = code + ';\n'; - const resolution = this.resolution; + } - renderer.getDrawingBufferSize( _size$9 ); + this.flow.code += code; - renderTarget.setSize( Math.round( _size$9.width * resolution ), Math.round( _size$9.height * resolution ) ); + return this; } - setup( builder ) { + addFlowCode( code ) { - this._updateResolution( _defaultRT, builder.renderer ); + this.flow.code += code; - return super.setup( builder ); + return this; } - getTextureNode() { + addFlowTab() { - return this.textureNode; + this.tab += '\t'; - } + return this; - getVirtualCamera( camera ) { + } - let virtualCamera = this.virtualCameras.get( camera ); + removeFlowTab() { - if ( virtualCamera === undefined ) { + this.tab = this.tab.slice( 0, - 1 ); - virtualCamera = camera.clone(); + return this; - this.virtualCameras.set( camera, virtualCamera ); + } - } + getFlowData( node/*, shaderStage*/ ) { - return virtualCamera; + return this.flowsData.get( node ); } - getRenderTarget( camera ) { + flowNode( node ) { - let renderTarget = this.renderTargets.get( camera ); + const output = node.getNodeType( this ); - if ( renderTarget === undefined ) { + const flowData = this.flowChildNode( node, output ); - renderTarget = new RenderTarget( 0, 0, { type: HalfFloatType } ); + this.flowsData.set( node, flowData ); - if ( this.generateMipmaps === true ) { + return flowData; - renderTarget.texture.minFilter = LinearMipMapLinearFilter; - renderTarget.texture.generateMipmaps = true; + } - } + buildFunctionNode( shaderNode ) { - this.renderTargets.set( camera, renderTarget ); + const fn = new FunctionNode(); - } + const previous = this.currentFunctionNode; - return renderTarget; + this.currentFunctionNode = fn; - } + fn.code = this.buildFunctionCode( shaderNode ); - updateBefore( frame ) { + this.currentFunctionNode = previous; - if ( this.bounces === false && _inReflector ) return false; + return fn; - _inReflector = true; + } - const { scene, camera, renderer, material } = frame; - const { target } = this; + flowShaderNode( shaderNode ) { - const virtualCamera = this.getVirtualCamera( camera ); - const renderTarget = this.getRenderTarget( virtualCamera ); + const layout = shaderNode.layout; - renderer.getDrawingBufferSize( _size$9 ); + const inputs = { + [ Symbol.iterator ]() { - this._updateResolution( renderTarget, renderer ); + let index = 0; + const values = Object.values( this ); + return { + next: () => ( { + value: values[ index ], + done: index ++ >= values.length + } ) + }; - // + } + }; - _reflectorWorldPosition.setFromMatrixPosition( target.matrixWorld ); - _cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld ); + for ( const input of layout.inputs ) { - _rotationMatrix.extractRotation( target.matrixWorld ); + inputs[ input.name ] = new ParameterNode( input.type, input.name ); - _normal.set( 0, 0, 1 ); - _normal.applyMatrix4( _rotationMatrix ); + } - _view.subVectors( _reflectorWorldPosition, _cameraWorldPosition ); + // - // Avoid rendering when reflector is facing away + shaderNode.layout = null; - if ( _view.dot( _normal ) > 0 ) return; + const callNode = shaderNode.call( inputs ); + const flowData = this.flowStagesNode( callNode, layout.type ); - _view.reflect( _normal ).negate(); - _view.add( _reflectorWorldPosition ); + shaderNode.layout = layout; - _rotationMatrix.extractRotation( camera.matrixWorld ); + return flowData; - _lookAtPosition.set( 0, 0, - 1 ); - _lookAtPosition.applyMatrix4( _rotationMatrix ); - _lookAtPosition.add( _cameraWorldPosition ); + } - _target.subVectors( _reflectorWorldPosition, _lookAtPosition ); - _target.reflect( _normal ).negate(); - _target.add( _reflectorWorldPosition ); + flowStagesNode( node, output = null ) { - // + const previousFlow = this.flow; + const previousVars = this.vars; + const previousCache = this.cache; + const previousBuildStage = this.buildStage; + const previousStack = this.stack; - virtualCamera.coordinateSystem = camera.coordinateSystem; - virtualCamera.position.copy( _view ); - virtualCamera.up.set( 0, 1, 0 ); - virtualCamera.up.applyMatrix4( _rotationMatrix ); - virtualCamera.up.reflect( _normal ); - virtualCamera.lookAt( _target ); + const flow = { + code: '' + }; - virtualCamera.near = camera.near; - virtualCamera.far = camera.far; + this.flow = flow; + this.vars = {}; + this.cache = new NodeCache(); + this.stack = stack(); - virtualCamera.updateMatrixWorld(); - virtualCamera.projectionMatrix.copy( camera.projectionMatrix ); + for ( const buildStage of defaultBuildStages ) { - // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html - // Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf - _reflectorPlane.setFromNormalAndCoplanarPoint( _normal, _reflectorWorldPosition ); - _reflectorPlane.applyMatrix4( virtualCamera.matrixWorldInverse ); + this.setBuildStage( buildStage ); - clipPlane.set( _reflectorPlane.normal.x, _reflectorPlane.normal.y, _reflectorPlane.normal.z, _reflectorPlane.constant ); + flow.result = node.build( this, output ); - const projectionMatrix = virtualCamera.projectionMatrix; + } - _q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ]; - _q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ]; - _q.z = - 1.0; - _q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; + flow.vars = this.getVars( this.shaderStage ); - // Calculate the scaled plane vector - clipPlane.multiplyScalar( 1.0 / clipPlane.dot( _q ) ); + this.flow = previousFlow; + this.vars = previousVars; + this.cache = previousCache; + this.stack = previousStack; - const clipBias = 0; + this.setBuildStage( previousBuildStage ); - // Replacing the third row of the projection matrix - projectionMatrix.elements[ 2 ] = clipPlane.x; - projectionMatrix.elements[ 6 ] = clipPlane.y; - projectionMatrix.elements[ 10 ] = clipPlane.z - clipBias; - projectionMatrix.elements[ 14 ] = clipPlane.w; + return flow; - // + } - this.value = renderTarget.texture; + getFunctionOperator() { - material.visible = false; + return null; - const currentRenderTarget = renderer.getRenderTarget(); - const currentMRT = renderer.getMRT(); + } - renderer.setMRT( null ); - renderer.setRenderTarget( renderTarget ); + flowChildNode( node, output = null ) { - renderer.render( scene, virtualCamera ); + const previousFlow = this.flow; - renderer.setMRT( currentMRT ); - renderer.setRenderTarget( currentRenderTarget ); + const flow = { + code: '' + }; - material.visible = true; + this.flow = flow; - _inReflector = false; + flow.result = node.build( this, output ); - } + this.flow = previousFlow; -} + return flow; -const reflector = ( parameters ) => nodeObject( new ReflectorNode( parameters ) ); + } -ReflectorNode.type = /*@__PURE__*/ registerNode( 'Reflector', ReflectorNode ); + flowNodeFromShaderStage( shaderStage, node, output = null, propertyName = null ) { -// Helper for passes that need to fill the viewport with a single quad. + const previousShaderStage = this.shaderStage; -const _camera = /*@__PURE__*/ new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); + this.setShaderStage( shaderStage ); -// https://github.com/mrdoob/three.js/pull/21358 + const flowData = this.flowChildNode( node, output ); -class QuadGeometry extends BufferGeometry { + if ( propertyName !== null ) { - constructor( flipY = false ) { + flowData.code += `${ this.tab + propertyName } = ${ flowData.result };\n`; - super(); + } - const uv = flipY === false ? [ 0, - 1, 0, 1, 2, 1 ] : [ 0, 2, 0, 0, 2, 0 ]; + this.flowCode[ shaderStage ] = this.flowCode[ shaderStage ] + flowData.code; - this.setAttribute( 'position', new Float32BufferAttribute( [ - 1, 3, 0, - 1, - 1, 0, 3, - 1, 0 ], 3 ) ); - this.setAttribute( 'uv', new Float32BufferAttribute( uv, 2 ) ); + this.setShaderStage( previousShaderStage ); + + return flowData; } -} + getAttributesArray() { -const _geometry = /*@__PURE__*/ new QuadGeometry(); + return this.attributes.concat( this.bufferAttributes ); -class QuadMesh extends Mesh { + } - constructor( material = null ) { + getAttributes( /*shaderStage*/ ) { - super( _geometry, material ); + console.warn( 'Abstract function.' ); - this.camera = _camera; + } - this.isQuadMesh = true; + getVaryings( /*shaderStage*/ ) { + + console.warn( 'Abstract function.' ); } - renderAsync( renderer ) { + getVar( type, name ) { - return renderer.renderAsync( this, _camera ); + return `${ this.getType( type ) } ${ name }`; } - render( renderer ) { + getVars( shaderStage ) { - renderer.render( this, _camera ); + let snippet = ''; + + const vars = this.vars[ shaderStage ]; + + if ( vars !== undefined ) { + + for ( const variable of vars ) { + + snippet += `${ this.getVar( variable.type, variable.name ) }; `; + + } + + } + + return snippet; } -} + getUniforms( /*shaderStage*/ ) { -const _size$8 = /*@__PURE__*/ new Vector2(); + console.warn( 'Abstract function.' ); -class RTTNode extends TextureNode { + } - constructor( node, width = null, height = null, options = { type: HalfFloatType } ) { + getCodes( shaderStage ) { - const renderTarget = new RenderTarget( width, height, options ); + const codes = this.codes[ shaderStage ]; - super( renderTarget.texture, uv() ); + let code = ''; - this.node = node; - this.width = width; - this.height = height; + if ( codes !== undefined ) { - this.renderTarget = renderTarget; + for ( const nodeCode of codes ) { - this.textureNeedsUpdate = true; - this.autoUpdate = true; + code += nodeCode.code + '\n'; - this.updateMap = new WeakMap(); + } - this._rttNode = null; - this._quadMesh = new QuadMesh( new NodeMaterial() ); + } - this.updateBeforeType = NodeUpdateType.RENDER; + return code; } - get autoSize() { + getHash() { - return this.width === null; + return this.vertexShader + this.fragmentShader + this.computeShader; } - setup( builder ) { - - this._rttNode = this.node.context( builder.getSharedContext() ); - this._quadMesh.material.name = 'RTT'; - this._quadMesh.material.needsUpdate = true; + setShaderStage( shaderStage ) { - return super.setup( builder ); + this.shaderStage = shaderStage; } - setSize( width, height ) { + getShaderStage() { - this.width = width; - this.height = height; + return this.shaderStage; - const effectiveWidth = width * this.pixelRatio; - const effectiveHeight = height * this.pixelRatio; + } - this.renderTarget.setSize( effectiveWidth, effectiveHeight ); + setBuildStage( buildStage ) { - this.textureNeedsUpdate = true; + this.buildStage = buildStage; } - setPixelRatio( pixelRatio ) { + getBuildStage() { - this.pixelRatio = pixelRatio; + return this.buildStage; - this.setSize( this.width, this.height ); + } + + buildCode() { + + console.warn( 'Abstract function.' ); } - updateBefore( { renderer } ) { + build() { - if ( this.textureNeedsUpdate === false && this.autoUpdate === false ) return; + const { object, material, renderer } = this; - this.textureNeedsUpdate = false; + if ( material !== null ) { - // + let nodeMaterial = renderer.nodes.library.fromMaterial( material ); - if ( this.autoSize === true ) { + if ( nodeMaterial === null ) { - this.pixelRatio = renderer.getPixelRatio(); + console.error( `NodeMaterial: Material "${ material.type }" is not compatible.` ); - const size = renderer.getSize( _size$8 ); + nodeMaterial = new NodeMaterial(); - this.setSize( size.width, size.height ); + } + + nodeMaterial.build( this ); + + } else { + + this.addFlow( 'compute', object ); } - // + // setup() -> stage 1: create possible new nodes and returns an output reference node + // analyze() -> stage 2: analyze nodes to possible optimization and validation + // generate() -> stage 3: generate shader - this._quadMesh.material.fragmentNode = this._rttNode; + for ( const buildStage of defaultBuildStages ) { - // + this.setBuildStage( buildStage ); - const currentRenderTarget = renderer.getRenderTarget(); + if ( this.context.vertex && this.context.vertex.isNode ) { - renderer.setRenderTarget( this.renderTarget ); + this.flowNodeFromShaderStage( 'vertex', this.context.vertex ); - this._quadMesh.render( renderer ); + } - renderer.setRenderTarget( currentRenderTarget ); + for ( const shaderStage of shaderStages ) { - } + this.setShaderStage( shaderStage ); - clone() { + const flowNodes = this.flowNodes[ shaderStage ]; - const newNode = new TextureNode( this.value, this.uvNode, this.levelNode ); - newNode.sampler = this.sampler; - newNode.referenceNode = this; + for ( const node of flowNodes ) { - return newNode; + if ( buildStage === 'generate' ) { - } + this.flowNode( node ); -} + } else { -RTTNode.type = /*@__PURE__*/ registerNode( 'RTT', RTTNode ); + node.build( this ); -const rtt = ( node, ...params ) => nodeObject( new RTTNode( nodeObject( node ), ...params ) ); -const convertToTexture = ( node, ...params ) => node.isTextureNode ? node : rtt( node, ...params ); + } -class VertexColorNode extends AttributeNode { + } - constructor( index = 0 ) { + } - super( null, 'vec4' ); + } - this.isVertexColorNode = true; + this.setBuildStage( null ); + this.setShaderStage( null ); - this.index = index; + // stage 4: build code for a specific output + + this.buildCode(); + this.buildUpdateNodes(); + + return this; } - getAttributeName( /*builder*/ ) { + getNodeUniform( uniformNode, type ) { - const index = this.index; + if ( type === 'float' || type === 'int' || type === 'uint' ) return new NumberNodeUniform( uniformNode ); + if ( type === 'vec2' || type === 'ivec2' || type === 'uvec2' ) return new Vector2NodeUniform( uniformNode ); + if ( type === 'vec3' || type === 'ivec3' || type === 'uvec3' ) return new Vector3NodeUniform( uniformNode ); + if ( type === 'vec4' || type === 'ivec4' || type === 'uvec4' ) return new Vector4NodeUniform( uniformNode ); + if ( type === 'color' ) return new ColorNodeUniform( uniformNode ); + if ( type === 'mat3' ) return new Matrix3NodeUniform( uniformNode ); + if ( type === 'mat4' ) return new Matrix4NodeUniform( uniformNode ); - return 'color' + ( index > 0 ? index : '' ); + throw new Error( `Uniform "${type}" not declared.` ); } - generate( builder ) { + createNodeMaterial( type = 'NodeMaterial' ) { // @deprecated, r168 - const attributeName = this.getAttributeName( builder ); - const geometryAttribute = builder.hasGeometryAttribute( attributeName ); + throw new Error( `THREE.NodeBuilder: createNodeMaterial() was deprecated. Use new ${ type }() instead.` ); - let result; + } - if ( geometryAttribute === true ) { + format( snippet, fromType, toType ) { - result = super.generate( builder ); + fromType = this.getVectorType( fromType ); + toType = this.getVectorType( toType ); - } else { + if ( fromType === toType || toType === null || this.isReference( toType ) ) { - // Vertex color fallback should be white - result = builder.generateConst( this.nodeType, new Vector4( 1, 1, 1, 1 ) ); + return snippet; } - return result; + const fromTypeLength = this.getTypeLength( fromType ); + const toTypeLength = this.getTypeLength( toType ); - } + if ( fromTypeLength === 16 && toTypeLength === 9 ) { - serialize( data ) { + return `${ this.getType( toType ) }(${ snippet }[0].xyz, ${ snippet }[1].xyz, ${ snippet }[2].xyz)`; - super.serialize( data ); + } - data.index = this.index; + if ( fromTypeLength === 9 && toTypeLength === 4 ) { - } + return `${ this.getType( toType ) }(${ snippet }[0].xy, ${ snippet }[1].xy)`; - deserialize( data ) { + } - super.deserialize( data ); - this.index = data.index; + if ( fromTypeLength > 4 ) { // fromType is matrix-like - } + // @TODO: ignore for now -} + return snippet; -VertexColorNode.type = /*@__PURE__*/ registerNode( 'VertexColor', VertexColorNode ); + } -const vertexColor = ( ...params ) => nodeObject( new VertexColorNode( ...params ) ); + if ( toTypeLength > 4 || toTypeLength === 0 ) { // toType is matrix-like or unknown -class PointUVNode extends Node { + // @TODO: ignore for now - constructor() { + return snippet; - super( 'vec2' ); + } - this.isPointUVNode = true; + if ( fromTypeLength === toTypeLength ) { - } + return `${ this.getType( toType ) }( ${ snippet } )`; - generate( /*builder*/ ) { + } - return 'vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y )'; + if ( fromTypeLength > toTypeLength ) { - } + return this.format( `${ snippet }.${ 'xyz'.slice( 0, toTypeLength ) }`, this.getTypeFromLength( toTypeLength, this.getComponentType( fromType ) ), toType ); -} + } -PointUVNode.type = /*@__PURE__*/ registerNode( 'PointUV', PointUVNode ); + if ( toTypeLength === 4 && fromTypeLength > 1 ) { // toType is vec4-like -const pointUV = /*@__PURE__*/ nodeImmutable( PointUVNode ); + return `${ this.getType( toType ) }( ${ this.format( snippet, fromType, 'vec3' ) }, 1.0 )`; -class SceneNode extends Node { + } - constructor( scope = SceneNode.BACKGROUND_BLURRINESS, scene = null ) { + if ( fromTypeLength === 2 ) { // fromType is vec2-like and toType is vec3-like - super(); + return `${ this.getType( toType ) }( ${ this.format( snippet, fromType, 'vec2' ) }, 0.0 )`; - this.scope = scope; - this.scene = scene; + } + + if ( fromTypeLength === 1 && toTypeLength > 1 && fromType !== this.getComponentType( toType ) ) { // fromType is float-like + + // convert a number value to vector type, e.g: + // vec3( 1u ) -> vec3( float( 1u ) ) + + snippet = `${ this.getType( this.getComponentType( toType ) ) }( ${ snippet } )`; + + } + + return `${ this.getType( toType ) }( ${ snippet } )`; // fromType is float-like } - setup( builder ) { + getSignature() { - const scope = this.scope; - const scene = this.scene !== null ? this.scene : builder.scene; + return `// Three.js r${ REVISION } - Node System\n`; - let output; + } - if ( scope === SceneNode.BACKGROUND_BLURRINESS ) { +} - output = reference( 'backgroundBlurriness', 'float', scene ); +class NodeFrame { - } else if ( scope === SceneNode.BACKGROUND_INTENSITY ) { + constructor() { - output = reference( 'backgroundIntensity', 'float', scene ); + this.time = 0; + this.deltaTime = 0; - } else { + this.frameId = 0; + this.renderId = 0; - console.error( 'THREE.SceneNode: Unknown scope:', scope ); + this.startTime = null; - } + this.updateMap = new WeakMap(); + this.updateBeforeMap = new WeakMap(); + this.updateAfterMap = new WeakMap(); - return output; + this.renderer = null; + this.material = null; + this.camera = null; + this.object = null; + this.scene = null; } -} + _getMaps( referenceMap, nodeRef ) { -SceneNode.BACKGROUND_BLURRINESS = 'backgroundBlurriness'; -SceneNode.BACKGROUND_INTENSITY = 'backgroundIntensity'; + let maps = referenceMap.get( nodeRef ); -SceneNode.type = /*@__PURE__*/ registerNode( 'Scene', SceneNode ); + if ( maps === undefined ) { -const backgroundBlurriness = /*@__PURE__*/ nodeImmutable( SceneNode, SceneNode.BACKGROUND_BLURRINESS ); -const backgroundIntensity = /*@__PURE__*/ nodeImmutable( SceneNode, SceneNode.BACKGROUND_INTENSITY ); + maps = { + renderMap: new WeakMap(), + frameMap: new WeakMap() + }; -const GPUPrimitiveTopology = { - PointList: 'point-list', - LineList: 'line-list', - LineStrip: 'line-strip', - TriangleList: 'triangle-list', - TriangleStrip: 'triangle-strip', -}; + referenceMap.set( nodeRef, maps ); -const GPUCompareFunction = { - Never: 'never', - Less: 'less', - Equal: 'equal', - LessEqual: 'less-equal', - Greater: 'greater', - NotEqual: 'not-equal', - GreaterEqual: 'greater-equal', - Always: 'always' -}; + } -const GPUStoreOp = { - Store: 'store', - Discard: 'discard' -}; + return maps; -const GPULoadOp = { - Load: 'load', - Clear: 'clear' -}; + } -const GPUFrontFace = { - CCW: 'ccw', - CW: 'cw' -}; + updateBeforeNode( node ) { -const GPUCullMode = { - None: 'none', - Front: 'front', - Back: 'back' -}; + const updateType = node.getUpdateBeforeType(); + const reference = node.updateReference( this ); -const GPUIndexFormat = { - Uint16: 'uint16', - Uint32: 'uint32' -}; + if ( updateType === NodeUpdateType.FRAME ) { -const GPUTextureFormat = { + const { frameMap } = this._getMaps( this.updateBeforeMap, reference ); - // 8-bit formats + if ( frameMap.get( reference ) !== this.frameId ) { - R8Unorm: 'r8unorm', - R8Snorm: 'r8snorm', - R8Uint: 'r8uint', - R8Sint: 'r8sint', + if ( node.updateBefore( this ) !== false ) { - // 16-bit formats + frameMap.set( reference, this.frameId ); - R16Uint: 'r16uint', - R16Sint: 'r16sint', - R16Float: 'r16float', - RG8Unorm: 'rg8unorm', - RG8Snorm: 'rg8snorm', - RG8Uint: 'rg8uint', - RG8Sint: 'rg8sint', - - // 32-bit formats - - R32Uint: 'r32uint', - R32Sint: 'r32sint', - R32Float: 'r32float', - RG16Uint: 'rg16uint', - RG16Sint: 'rg16sint', - RG16Float: 'rg16float', - RGBA8Unorm: 'rgba8unorm', - RGBA8UnormSRGB: 'rgba8unorm-srgb', - RGBA8Snorm: 'rgba8snorm', - RGBA8Uint: 'rgba8uint', - RGBA8Sint: 'rgba8sint', - BGRA8Unorm: 'bgra8unorm', - BGRA8UnormSRGB: 'bgra8unorm-srgb', - // Packed 32-bit formats - RGB9E5UFloat: 'rgb9e5ufloat', - RGB10A2Unorm: 'rgb10a2unorm', - RG11B10uFloat: 'rgb10a2unorm', - - // 64-bit formats + } - RG32Uint: 'rg32uint', - RG32Sint: 'rg32sint', - RG32Float: 'rg32float', - RGBA16Uint: 'rgba16uint', - RGBA16Sint: 'rgba16sint', - RGBA16Float: 'rgba16float', + } - // 128-bit formats + } else if ( updateType === NodeUpdateType.RENDER ) { - RGBA32Uint: 'rgba32uint', - RGBA32Sint: 'rgba32sint', - RGBA32Float: 'rgba32float', + const { renderMap } = this._getMaps( this.updateBeforeMap, reference ); - // Depth and stencil formats + if ( renderMap.get( reference ) !== this.renderId ) { - Stencil8: 'stencil8', - Depth16Unorm: 'depth16unorm', - Depth24Plus: 'depth24plus', - Depth24PlusStencil8: 'depth24plus-stencil8', - Depth32Float: 'depth32float', + if ( node.updateBefore( this ) !== false ) { - // 'depth32float-stencil8' extension + renderMap.set( reference, this.renderId ); - Depth32FloatStencil8: 'depth32float-stencil8', + } - // BC compressed formats usable if 'texture-compression-bc' is both - // supported by the device/user agent and enabled in requestDevice. + } - BC1RGBAUnorm: 'bc1-rgba-unorm', - BC1RGBAUnormSRGB: 'bc1-rgba-unorm-srgb', - BC2RGBAUnorm: 'bc2-rgba-unorm', - BC2RGBAUnormSRGB: 'bc2-rgba-unorm-srgb', - BC3RGBAUnorm: 'bc3-rgba-unorm', - BC3RGBAUnormSRGB: 'bc3-rgba-unorm-srgb', - BC4RUnorm: 'bc4-r-unorm', - BC4RSnorm: 'bc4-r-snorm', - BC5RGUnorm: 'bc5-rg-unorm', - BC5RGSnorm: 'bc5-rg-snorm', - BC6HRGBUFloat: 'bc6h-rgb-ufloat', - BC6HRGBFloat: 'bc6h-rgb-float', - BC7RGBAUnorm: 'bc7-rgba-unorm', - BC7RGBAUnormSRGB: 'bc7-rgba-srgb', + } else if ( updateType === NodeUpdateType.OBJECT ) { - // ETC2 compressed formats usable if 'texture-compression-etc2' is both - // supported by the device/user agent and enabled in requestDevice. + node.updateBefore( this ); - ETC2RGB8Unorm: 'etc2-rgb8unorm', - ETC2RGB8UnormSRGB: 'etc2-rgb8unorm-srgb', - ETC2RGB8A1Unorm: 'etc2-rgb8a1unorm', - ETC2RGB8A1UnormSRGB: 'etc2-rgb8a1unorm-srgb', - ETC2RGBA8Unorm: 'etc2-rgba8unorm', - ETC2RGBA8UnormSRGB: 'etc2-rgba8unorm-srgb', - EACR11Unorm: 'eac-r11unorm', - EACR11Snorm: 'eac-r11snorm', - EACRG11Unorm: 'eac-rg11unorm', - EACRG11Snorm: 'eac-rg11snorm', + } - // ASTC compressed formats usable if 'texture-compression-astc' is both - // supported by the device/user agent and enabled in requestDevice. + } - ASTC4x4Unorm: 'astc-4x4-unorm', - ASTC4x4UnormSRGB: 'astc-4x4-unorm-srgb', - ASTC5x4Unorm: 'astc-5x4-unorm', - ASTC5x4UnormSRGB: 'astc-5x4-unorm-srgb', - ASTC5x5Unorm: 'astc-5x5-unorm', - ASTC5x5UnormSRGB: 'astc-5x5-unorm-srgb', - ASTC6x5Unorm: 'astc-6x5-unorm', - ASTC6x5UnormSRGB: 'astc-6x5-unorm-srgb', - ASTC6x6Unorm: 'astc-6x6-unorm', - ASTC6x6UnormSRGB: 'astc-6x6-unorm-srgb', - ASTC8x5Unorm: 'astc-8x5-unorm', - ASTC8x5UnormSRGB: 'astc-8x5-unorm-srgb', - ASTC8x6Unorm: 'astc-8x6-unorm', - ASTC8x6UnormSRGB: 'astc-8x6-unorm-srgb', - ASTC8x8Unorm: 'astc-8x8-unorm', - ASTC8x8UnormSRGB: 'astc-8x8-unorm-srgb', - ASTC10x5Unorm: 'astc-10x5-unorm', - ASTC10x5UnormSRGB: 'astc-10x5-unorm-srgb', - ASTC10x6Unorm: 'astc-10x6-unorm', - ASTC10x6UnormSRGB: 'astc-10x6-unorm-srgb', - ASTC10x8Unorm: 'astc-10x8-unorm', - ASTC10x8UnormSRGB: 'astc-10x8-unorm-srgb', - ASTC10x10Unorm: 'astc-10x10-unorm', - ASTC10x10UnormSRGB: 'astc-10x10-unorm-srgb', - ASTC12x10Unorm: 'astc-12x10-unorm', - ASTC12x10UnormSRGB: 'astc-12x10-unorm-srgb', - ASTC12x12Unorm: 'astc-12x12-unorm', - ASTC12x12UnormSRGB: 'astc-12x12-unorm-srgb', + updateAfterNode( node ) { -}; + const updateType = node.getUpdateAfterType(); + const reference = node.updateReference( this ); -const GPUAddressMode = { - ClampToEdge: 'clamp-to-edge', - Repeat: 'repeat', - MirrorRepeat: 'mirror-repeat' -}; + if ( updateType === NodeUpdateType.FRAME ) { -const GPUFilterMode = { - Linear: 'linear', - Nearest: 'nearest' -}; + const { frameMap } = this._getMaps( this.updateAfterMap, reference ); -const GPUBlendFactor = { - Zero: 'zero', - One: 'one', - Src: 'src', - OneMinusSrc: 'one-minus-src', - SrcAlpha: 'src-alpha', - OneMinusSrcAlpha: 'one-minus-src-alpha', - Dst: 'dst', - OneMinusDstColor: 'one-minus-dst', - DstAlpha: 'dst-alpha', - OneMinusDstAlpha: 'one-minus-dst-alpha', - SrcAlphaSaturated: 'src-alpha-saturated', - Constant: 'constant', - OneMinusConstant: 'one-minus-constant' -}; + if ( frameMap.get( reference ) !== this.frameId ) { -const GPUBlendOperation = { - Add: 'add', - Subtract: 'subtract', - ReverseSubtract: 'reverse-subtract', - Min: 'min', - Max: 'max' -}; + if ( node.updateAfter( this ) !== false ) { -const GPUColorWriteFlags = { - None: 0, - Red: 0x1, - Green: 0x2, - Blue: 0x4, - Alpha: 0x8, - All: 0xF -}; + frameMap.set( reference, this.frameId ); -const GPUStencilOperation = { - Keep: 'keep', - Zero: 'zero', - Replace: 'replace', - Invert: 'invert', - IncrementClamp: 'increment-clamp', - DecrementClamp: 'decrement-clamp', - IncrementWrap: 'increment-wrap', - DecrementWrap: 'decrement-wrap' -}; + } -const GPUBufferBindingType = { - Uniform: 'uniform', - Storage: 'storage', - ReadOnlyStorage: 'read-only-storage' -}; + } -const GPUStorageTextureAccess = { - WriteOnly: 'write-only', - ReadOnly: 'read-only', - ReadWrite: 'read-write', -}; + } else if ( updateType === NodeUpdateType.RENDER ) { -const GPUTextureSampleType = { - Float: 'float', - UnfilterableFloat: 'unfilterable-float', - Depth: 'depth', - SInt: 'sint', - UInt: 'uint' -}; + const { renderMap } = this._getMaps( this.updateAfterMap, reference ); -const GPUTextureDimension = { - OneD: '1d', - TwoD: '2d', - ThreeD: '3d' -}; + if ( renderMap.get( reference ) !== this.renderId ) { -const GPUTextureViewDimension = { - OneD: '1d', - TwoD: '2d', - TwoDArray: '2d-array', - Cube: 'cube', - CubeArray: 'cube-array', - ThreeD: '3d' -}; + if ( node.updateAfter( this ) !== false ) { -const GPUTextureAspect = { - All: 'all', - StencilOnly: 'stencil-only', - DepthOnly: 'depth-only' -}; + renderMap.set( reference, this.renderId ); -const GPUInputStepMode = { - Vertex: 'vertex', - Instance: 'instance' -}; + } -const GPUFeatureName = { - DepthClipControl: 'depth-clip-control', - Depth32FloatStencil8: 'depth32float-stencil8', - TextureCompressionBC: 'texture-compression-bc', - TextureCompressionETC2: 'texture-compression-etc2', - TextureCompressionASTC: 'texture-compression-astc', - TimestampQuery: 'timestamp-query', - IndirectFirstInstance: 'indirect-first-instance', - ShaderF16: 'shader-f16', - RG11B10UFloat: 'rg11b10ufloat-renderable', - BGRA8UNormStorage: 'bgra8unorm-storage', - Float32Filterable: 'float32-filterable', - ClipDistances: 'clip-distances', - DualSourceBlending: 'dual-source-blending', - Subgroups: 'subgroups' -}; + } -class StorageBufferNode extends BufferNode { + } else if ( updateType === NodeUpdateType.OBJECT ) { - constructor( value, bufferType, bufferCount = 0 ) { + node.updateAfter( this ); - super( value, bufferType, bufferCount ); + } - this.isStorageBufferNode = true; + } - this.access = GPUBufferBindingType.Storage; + updateNode( node ) { - this.bufferObject = false; - this.bufferCount = bufferCount; + const updateType = node.getUpdateType(); + const reference = node.updateReference( this ); - this._attribute = null; - this._varying = null; + if ( updateType === NodeUpdateType.FRAME ) { - this.global = true; + const { frameMap } = this._getMaps( this.updateMap, reference ); - if ( value.isStorageBufferAttribute !== true && value.isStorageInstancedBufferAttribute !== true ) { + if ( frameMap.get( reference ) !== this.frameId ) { - // TOOD: Improve it, possibly adding a new property to the BufferAttribute to identify it as a storage buffer read-only attribute in Renderer + if ( node.update( this ) !== false ) { - if ( value.isInstancedBufferAttribute ) value.isStorageInstancedBufferAttribute = true; - else value.isStorageBufferAttribute = true; + frameMap.set( reference, this.frameId ); - } + } - } + } - getHash( builder ) { + } else if ( updateType === NodeUpdateType.RENDER ) { - if ( this.bufferCount === 0 ) { + const { renderMap } = this._getMaps( this.updateMap, reference ); - let bufferData = builder.globalCache.getData( this.value ); + if ( renderMap.get( reference ) !== this.renderId ) { - if ( bufferData === undefined ) { + if ( node.update( this ) !== false ) { - bufferData = { - node: this - }; + renderMap.set( reference, this.renderId ); - builder.globalCache.setData( this.value, bufferData ); + } } - return bufferData.node.uuid; - - } - - return this.uuid; - - } + } else if ( updateType === NodeUpdateType.OBJECT ) { - getInputType( /*builder*/ ) { + node.update( this ); - return 'storageBuffer'; + } } - element( indexNode ) { + update() { - return storageElement( this, indexNode ); + this.frameId ++; - } + if ( this.lastTime === undefined ) this.lastTime = performance.now(); - setBufferObject( value ) { + this.deltaTime = ( performance.now() - this.lastTime ) / 1000; - this.bufferObject = value; + this.lastTime = performance.now(); - return this; + this.time += this.deltaTime; } - setAccess( value ) { - - this.access = value; - - return this; +} - } +class NodeFunctionInput { - toReadOnly() { + constructor( type, name, count = null, qualifier = '', isConst = false ) { - return this.setAccess( GPUBufferBindingType.ReadOnlyStorage ); + this.type = type; + this.name = name; + this.count = count; + this.qualifier = qualifier; + this.isConst = isConst; } - generate( builder ) { +} - if ( builder.isAvailable( 'storageBuffer' ) ) { +NodeFunctionInput.isNodeFunctionInput = true; - return super.generate( builder ); +class StructTypeNode extends Node { - } + static get type() { - const nodeType = this.getNodeType( builder ); + return 'StructTypeNode'; - if ( this._attribute === null ) { + } - this._attribute = bufferAttribute( this.value ); - this._varying = varying( this._attribute ); + constructor( types ) { - } + super(); + this.types = types; + this.isStructTypeNode = true; - const output = this._varying.build( builder, nodeType ); + } - builder.registerTransform( output, this._attribute ); + getMemberTypes() { - return output; + return this.types; } } -StorageBufferNode.type = /*@__PURE__*/ registerNode( 'StorageBuffer', StorageBufferNode ); - -// Read-Write Storage -const storage = ( value, type, count ) => nodeObject( new StorageBufferNode( value, type, count ) ); -const storageObject = ( value, type, count ) => nodeObject( new StorageBufferNode( value, type, count ).setBufferObject( true ) ); - -class StorageTextureNode extends TextureNode { - - constructor( value, uvNode, storeNode = null ) { +class OutputStructNode extends Node { - super( value, uvNode ); + static get type() { - this.storeNode = storeNode; + return 'OutputStructNode'; - this.isStorageTextureNode = true; + } - this.access = GPUStorageTextureAccess.WriteOnly; + constructor( ...members ) { - } + super(); - getInputType( /*builder*/ ) { + this.members = members; - return 'storageTexture'; + this.isOutputStructNode = true; } @@ -55143,2733 +54810,2728 @@ class StorageTextureNode extends TextureNode { super.setup( builder ); - const properties = builder.getNodeProperties( this ); - properties.storeNode = this.storeNode; + const members = this.members; + const types = []; - } + for ( let i = 0; i < members.length; i ++ ) { - setAccess( value ) { + types.push( members[ i ].getNodeType( builder ) ); - this.access = value; - return this; + } + + this.nodeType = builder.getStructTypeFromNode( new StructTypeNode( types ) ).name; } generate( builder, output ) { - let snippet; + const propertyName = builder.getOutputStructName(); + const members = this.members; - if ( this.storeNode !== null ) { + const structPrefix = propertyName !== '' ? propertyName + '.' : ''; - snippet = this.generateStore( builder ); + for ( let i = 0; i < members.length; i ++ ) { - } else { + const snippet = members[ i ].build( builder, output ); - snippet = super.generate( builder, output ); + builder.addLineFlowCode( `${ structPrefix }m${ i } = ${ snippet }`, this ); } - return snippet; + return propertyName; } - toReadOnly() { - - return this.setAccess( GPUStorageTextureAccess.ReadOnly ); +} - } +const outputStruct = /*@__PURE__*/ nodeProxy( OutputStructNode ); - toWriteOnly() { +function getTextureIndex( textures, name ) { - return this.setAccess( GPUStorageTextureAccess.WriteOnly ); + for ( let i = 0; i < textures.length; i ++ ) { - } + if ( textures[ i ].name === name ) { - generateStore( builder ) { + return i; - const properties = builder.getNodeProperties( this ); + } - const { uvNode, storeNode } = properties; + } - const textureProperty = super.generate( builder, 'property' ); - const uvSnippet = uvNode.build( builder, 'uvec2' ); - const storeSnippet = storeNode.build( builder, 'vec4' ); + return - 1; - const snippet = builder.generateTextureStore( builder, textureProperty, uvSnippet, storeSnippet ); +} - builder.addLineFlowCode( snippet ); +class MRTNode extends OutputStructNode { - } + static get type() { -} + return 'MRTNode'; -StorageTextureNode.type = /*@__PURE__*/ registerNode( 'StorageTexture', StorageTextureNode ); + } -const storageTexture = /*@__PURE__*/ nodeProxy( StorageTextureNode ); + constructor( outputNodes ) { -const textureStore = ( value, uvNode, storeNode ) => { + super(); - const node = storageTexture( value, uvNode, storeNode ); + this.outputNodes = outputNodes; - if ( storeNode !== null ) node.append(); + this.isMRTNode = true; - return node; + } -}; + has( name ) { -class UserDataNode extends ReferenceNode { + return this.outputNodes[ name ] !== undefined; - constructor( property, inputType, userData = null ) { + } - super( property, inputType, userData ); + get( name ) { - this.userData = userData; + return this.outputNodes[ name ]; } - update( frame ) { + merge( mrtNode ) { - this.reference = this.userData !== null ? this.userData : frame.object.userData; + const outputs = { ...this.outputNodes, ...mrtNode.outputNodes }; - super.update( frame ); + return mrt( outputs ); } -} - -UserDataNode.type = /*@__PURE__*/ registerNode( 'UserData', UserDataNode ); + setup( builder ) { -const userData = ( name, inputType, userData ) => nodeObject( new UserDataNode( name, inputType, userData ) ); + const outputNodes = this.outputNodes; + const mrt = builder.renderer.getRenderTarget(); -class PosterizeNode extends TempNode { + const members = []; - constructor( sourceNode, stepsNode ) { + const textures = mrt.textures; - super(); + for ( const name in outputNodes ) { - this.sourceNode = sourceNode; - this.stepsNode = stepsNode; + const index = getTextureIndex( textures, name ); - } + members[ index ] = vec4( outputNodes[ name ] ); - setup() { + } - const { sourceNode, stepsNode } = this; + this.members = members; - return sourceNode.mul( stepsNode ).floor().div( stepsNode ); + return super.setup( builder ); } } -PosterizeNode.type = /*@__PURE__*/ registerNode( 'Posterize', PosterizeNode ); +const mrt = /*@__PURE__*/ nodeProxy( MRTNode ); -const posterize = /*@__PURE__*/ nodeProxy( PosterizeNode ); +class FunctionOverloadingNode extends Node { -let _sharedFramebuffer = null; + static get type() { -class ViewportSharedTextureNode extends ViewportTextureNode { + return 'FunctionOverloadingNode'; - constructor( uvNode = viewportUV, levelNode = null ) { + } - if ( _sharedFramebuffer === null ) { + constructor( functionNodes = [], ...parametersNodes ) { - _sharedFramebuffer = new FramebufferTexture(); + super(); - } + this.functionNodes = functionNodes; + this.parametersNodes = parametersNodes; - super( uvNode, levelNode, _sharedFramebuffer ); + this._candidateFnCall = null; + + this.global = true; } - updateReference() { + getNodeType() { - return this; + return this.functionNodes[ 0 ].shaderNode.layout.type; } -} + setup( builder ) { -ViewportSharedTextureNode.type = /*@__PURE__*/ registerNode( 'ViewportSharedTexture', ViewportSharedTextureNode ); + const params = this.parametersNodes; -const viewportSharedTexture = /*@__PURE__*/ nodeProxy( ViewportSharedTextureNode ); + let candidateFnCall = this._candidateFnCall; -const _size$7 = /*@__PURE__*/ new Vector2(); + if ( candidateFnCall === null ) { -class PassTextureNode extends TextureNode { + let candidateFn = null; + let candidateScore = - 1; - constructor( passNode, texture ) { + for ( const functionNode of this.functionNodes ) { - super( texture ); + const shaderNode = functionNode.shaderNode; + const layout = shaderNode.layout; - this.passNode = passNode; + if ( layout === null ) { - this.setUpdateMatrix( false ); + throw new Error( 'FunctionOverloadingNode: FunctionNode must be a layout.' ); - } + } - setup( builder ) { + const inputs = layout.inputs; - if ( builder.object.isQuadMesh ) this.passNode.build( builder ); + if ( params.length === inputs.length ) { - return super.setup( builder ); + let score = 0; - } + for ( let i = 0; i < params.length; i ++ ) { - clone() { + const param = params[ i ]; + const input = inputs[ i ]; - return new this.constructor( this.passNode, this.value ); + if ( param.getNodeType( builder ) === input.type ) { - } + score ++; -} + } else { -PassTextureNode.type = /*@__PURE__*/ registerNode( 'PassTexture', PassTextureNode ); + score = 0; -class PassMultipleTextureNode extends PassTextureNode { + } - constructor( passNode, textureName, previousTexture = false ) { + } - super( passNode, null ); + if ( score > candidateScore ) { - this.textureName = textureName; - this.previousTexture = previousTexture; + candidateFn = functionNode; + candidateScore = score; - } + } - updateTexture() { + } - this.value = this.previousTexture ? this.passNode.getPreviousTexture( this.textureName ) : this.passNode.getTexture( this.textureName ); + } + + this._candidateFnCall = candidateFnCall = candidateFn( ...params ); + + } + + return candidateFnCall; } - setup( builder ) { +} - this.updateTexture(); +const overloadingBaseFn = /*@__PURE__*/ nodeProxy( FunctionOverloadingNode ); - return super.setup( builder ); +const overloadingFn = ( functionNodes ) => ( ...params ) => overloadingBaseFn( functionNodes, ...params ); + +class TimerNode extends UniformNode { + + static get type() { + + return 'TimerNode'; } - clone() { + constructor( scope = TimerNode.LOCAL, scale = 1, value = 0 ) { - return new this.constructor( this.passNode, this.textureName, this.previousTexture ); + super( value ); + + this.scope = scope; + this.scale = scale; + + this.updateType = NodeUpdateType.FRAME; } + /* + @TODO: + getNodeType( builder ) { -} + const scope = this.scope; -PassMultipleTextureNode.type = /*@__PURE__*/ registerNode( 'PassMultipleTexture', PassMultipleTextureNode ); + if ( scope === TimerNode.FRAME ) { -class PassNode extends TempNode { + return 'uint'; - constructor( scope, scene, camera, options = {} ) { + } - super( 'vec4' ); + return 'float'; - this.scope = scope; - this.scene = scene; - this.camera = camera; - this.options = options; + } +*/ + update( frame ) { - this._pixelRatio = 1; - this._width = 1; - this._height = 1; + const scope = this.scope; + const scale = this.scale; - const depthTexture = new DepthTexture(); - depthTexture.isRenderTargetTexture = true; - //depthTexture.type = FloatType; - depthTexture.name = 'depth'; + if ( scope === TimerNode.LOCAL ) { - const renderTarget = new RenderTarget( this._width * this._pixelRatio, this._height * this._pixelRatio, { type: HalfFloatType, ...options, } ); - renderTarget.texture.name = 'output'; - renderTarget.depthTexture = depthTexture; + this.value += frame.deltaTime * scale; - this.renderTarget = renderTarget; + } else if ( scope === TimerNode.DELTA ) { - this.updateBeforeType = NodeUpdateType.FRAME; + this.value = frame.deltaTime * scale; - this._textures = { - output: renderTarget.texture, - depth: depthTexture - }; + } else if ( scope === TimerNode.FRAME ) { - this._textureNodes = {}; - this._linearDepthNodes = {}; - this._viewZNodes = {}; + this.value = frame.frameId; - this._previousTextures = {}; - this._previousTextureNodes = {}; + } else { - this._cameraNear = uniform( 0 ); - this._cameraFar = uniform( 0 ); + // global - this._mrt = null; + this.value = frame.time * scale; - this.isPassNode = true; + } } - setMRT( mrt ) { + serialize( data ) { - this._mrt = mrt; + super.serialize( data ); - return this; + data.scope = this.scope; + data.scale = this.scale; } - getMRT() { + deserialize( data ) { - return this._mrt; + super.deserialize( data ); + + this.scope = data.scope; + this.scale = data.scale; } - isGlobal() { +} - return true; +TimerNode.LOCAL = 'local'; +TimerNode.GLOBAL = 'global'; +TimerNode.DELTA = 'delta'; +TimerNode.FRAME = 'frame'; - } +// @TODO: add support to use node in timeScale +const timerLocal = ( timeScale, value = 0 ) => nodeObject( new TimerNode( TimerNode.LOCAL, timeScale, value ) ); +const timerGlobal = ( timeScale, value = 0 ) => nodeObject( new TimerNode( TimerNode.GLOBAL, timeScale, value ) ); +const timerDelta = ( timeScale, value = 0 ) => nodeObject( new TimerNode( TimerNode.DELTA, timeScale, value ) ); +const frameId = /*@__PURE__*/ nodeImmutable( TimerNode, TimerNode.FRAME ).toUint(); - getTexture( name ) { +class OscNode extends Node { - let texture = this._textures[ name ]; + static get type() { - if ( texture === undefined ) { + return 'OscNode'; - const refTexture = this.renderTarget.texture; + } - texture = refTexture.clone(); - texture.isRenderTargetTexture = true; - texture.name = name; + constructor( method = OscNode.SINE, timeNode = timerLocal() ) { - this._textures[ name ] = texture; + super(); - this.renderTarget.textures.push( texture ); + this.method = method; + this.timeNode = timeNode; - } + } - return texture; + getNodeType( builder ) { + + return this.timeNode.getNodeType( builder ); } - getPreviousTexture( name ) { + setup() { - let texture = this._previousTextures[ name ]; + const method = this.method; + const timeNode = nodeObject( this.timeNode ); - if ( texture === undefined ) { + let outputNode = null; - texture = this.getTexture( name ).clone(); - texture.isRenderTargetTexture = true; + if ( method === OscNode.SINE ) { - this._previousTextures[ name ] = texture; + outputNode = timeNode.add( 0.75 ).mul( Math.PI * 2 ).sin().mul( 0.5 ).add( 0.5 ); + + } else if ( method === OscNode.SQUARE ) { + + outputNode = timeNode.fract().round(); + + } else if ( method === OscNode.TRIANGLE ) { + + outputNode = timeNode.add( 0.5 ).fract().mul( 2 ).sub( 1 ).abs(); + + } else if ( method === OscNode.SAWTOOTH ) { + + outputNode = timeNode.fract(); } - return texture; + return outputNode; } - toggleTexture( name ) { - - const prevTexture = this._previousTextures[ name ]; + serialize( data ) { - if ( prevTexture !== undefined ) { + super.serialize( data ); - const texture = this._textures[ name ]; + data.method = this.method; - const index = this.renderTarget.textures.indexOf( texture ); - this.renderTarget.textures[ index ] = prevTexture; + } - this._textures[ name ] = prevTexture; - this._previousTextures[ name ] = texture; + deserialize( data ) { - this._textureNodes[ name ].updateTexture(); - this._previousTextureNodes[ name ].updateTexture(); + super.deserialize( data ); - } + this.method = data.method; } - getTextureNode( name = 'output' ) { +} - let textureNode = this._textureNodes[ name ]; +OscNode.SINE = 'sine'; +OscNode.SQUARE = 'square'; +OscNode.TRIANGLE = 'triangle'; +OscNode.SAWTOOTH = 'sawtooth'; - if ( textureNode === undefined ) { +const oscSine = /*@__PURE__*/ nodeProxy( OscNode, OscNode.SINE ); +const oscSquare = /*@__PURE__*/ nodeProxy( OscNode, OscNode.SQUARE ); +const oscTriangle = /*@__PURE__*/ nodeProxy( OscNode, OscNode.TRIANGLE ); +const oscSawtooth = /*@__PURE__*/ nodeProxy( OscNode, OscNode.SAWTOOTH ); - this._textureNodes[ name ] = textureNode = nodeObject( new PassMultipleTextureNode( this, name ) ); - this._textureNodes[ name ].updateTexture(); +class SpriteSheetUVNode extends Node { - } + static get type() { - return textureNode; + return 'SpriteSheetUVNode'; } - getPreviousTextureNode( name = 'output' ) { + constructor( countNode, uvNode = uv(), frameNode = float( 0 ) ) { - let textureNode = this._previousTextureNodes[ name ]; + super( 'vec2' ); - if ( textureNode === undefined ) { + this.countNode = countNode; + this.uvNode = uvNode; + this.frameNode = frameNode; - if ( this._textureNodes[ name ] === undefined ) this.getTextureNode( name ); + } - this._previousTextureNodes[ name ] = textureNode = nodeObject( new PassMultipleTextureNode( this, name, true ) ); - this._previousTextureNodes[ name ].updateTexture(); + setup() { - } + const { frameNode, uvNode, countNode } = this; - return textureNode; + const { width, height } = countNode; - } + const frameNum = frameNode.mod( width.mul( height ) ).floor(); - getViewZNode( name = 'depth' ) { + const column = frameNum.mod( width ); + const row = height.sub( frameNum.add( 1 ).div( width ).ceil() ); - let viewZNode = this._viewZNodes[ name ]; + const scale = countNode.reciprocal(); + const uvFrameOffset = vec2( column, row ); - if ( viewZNode === undefined ) { + return uvNode.add( uvFrameOffset ).mul( scale ); - const cameraNear = this._cameraNear; - const cameraFar = this._cameraFar; + } - this._viewZNodes[ name ] = viewZNode = perspectiveDepthToViewZ( this.getTextureNode( name ), cameraNear, cameraFar ); +} - } +const spritesheetUV = /*@__PURE__*/ nodeProxy( SpriteSheetUVNode ); - return viewZNode; +class StorageArrayElementNode extends ArrayElementNode { + + static get type() { + + return 'StorageArrayElementNode'; } - getLinearDepthNode( name = 'depth' ) { + constructor( storageBufferNode, indexNode ) { - let linearDepthNode = this._linearDepthNodes[ name ]; + super( storageBufferNode, indexNode ); - if ( linearDepthNode === undefined ) { + this.isStorageArrayElementNode = true; - const cameraNear = this._cameraNear; - const cameraFar = this._cameraFar; - const viewZNode = this.getViewZNode( name ); + } - // TODO: just if ( builder.camera.isPerspectiveCamera ) + set storageBufferNode( value ) { - this._linearDepthNodes[ name ] = linearDepthNode = viewZToOrthographicDepth( viewZNode, cameraNear, cameraFar ); + this.node = value; - } + } - return linearDepthNode; + get storageBufferNode() { + + return this.node; } - setup( { renderer } ) { + setup( builder ) { - this.renderTarget.samples = this.options.samples === undefined ? renderer.samples : this.options.samples; + if ( builder.isAvailable( 'storageBuffer' ) === false ) { - // Disable MSAA for WebGL backend for now - if ( renderer.backend.isWebGLBackend === true ) { + if ( this.node.bufferObject === true ) { - this.renderTarget.samples = 0; + builder.setupPBO( this.node ); - } + } - this.renderTarget.depthTexture.isMultisampleRenderTargetTexture = this.renderTarget.samples > 1; + } - return this.scope === PassNode.COLOR ? this.getTextureNode() : this.getLinearDepthNode(); + return super.setup( builder ); } - updateBefore( frame ) { + generate( builder, output ) { - const { renderer } = frame; - const { scene, camera } = this; + let snippet; - this._pixelRatio = renderer.getPixelRatio(); + const isAssignContext = builder.context.assign; - const size = renderer.getSize( _size$7 ); + // - this.setSize( size.width, size.height ); + if ( builder.isAvailable( 'storageBuffer' ) === false ) { - const currentRenderTarget = renderer.getRenderTarget(); - const currentMRT = renderer.getMRT(); + if ( this.node.bufferObject === true && isAssignContext !== true ) { - this._cameraNear.value = camera.near; - this._cameraFar.value = camera.far; + snippet = builder.generatePBO( this ); - for ( const name in this._previousTextures ) { + } else { - this.toggleTexture( name ); + snippet = this.node.build( builder ); - } + } - renderer.setRenderTarget( this.renderTarget ); - renderer.setMRT( this._mrt ); + } else { - renderer.render( scene, camera ); + snippet = super.generate( builder ); - renderer.setRenderTarget( currentRenderTarget ); - renderer.setMRT( currentMRT ); + } - } + if ( isAssignContext !== true ) { - setSize( width, height ) { + const type = this.getNodeType( builder ); - this._width = width; - this._height = height; + snippet = builder.format( snippet, type, output ); - const effectiveWidth = this._width * this._pixelRatio; - const effectiveHeight = this._height * this._pixelRatio; + } - this.renderTarget.setSize( effectiveWidth, effectiveHeight ); + return snippet; } - setPixelRatio( pixelRatio ) { - - this._pixelRatio = pixelRatio; +} - this.setSize( this._width, this._height ); +const storageElement = /*@__PURE__*/ nodeProxy( StorageArrayElementNode ); - } +class TriplanarTexturesNode extends Node { - dispose() { + static get type() { - this.renderTarget.dispose(); + return 'TriplanarTexturesNode'; } + constructor( textureXNode, textureYNode = null, textureZNode = null, scaleNode = float( 1 ), positionNode = positionLocal, normalNode = normalLocal ) { -} + super( 'vec4' ); -PassNode.COLOR = 'color'; -PassNode.DEPTH = 'depth'; + this.textureXNode = textureXNode; + this.textureYNode = textureYNode; + this.textureZNode = textureZNode; -PassNode.type = /*@__PURE__*/ registerNode( 'Pass', PassNode ); + this.scaleNode = scaleNode; -const pass = ( scene, camera, options ) => nodeObject( new PassNode( PassNode.COLOR, scene, camera, options ) ); -const passTexture = ( pass, texture ) => nodeObject( new PassTextureNode( pass, texture ) ); -const depthPass = ( scene, camera ) => nodeObject( new PassNode( PassNode.DEPTH, scene, camera ) ); + this.positionNode = positionNode; + this.normalNode = normalNode; -// WebGPU: The use of a single QuadMesh for both gaussian blur passes results in a single RenderObject with a SampledTexture binding that -// alternates between source textures and triggers creation of new BindGroups and BindGroupLayouts every frame. + } -const _quadMesh1 = /*@__PURE__*/ new QuadMesh(); -const _quadMesh2 = /*@__PURE__*/ new QuadMesh(); + setup() { -class GaussianBlurNode extends TempNode { + const { textureXNode, textureYNode, textureZNode, scaleNode, positionNode, normalNode } = this; - constructor( textureNode, directionNode = null, sigma = 2 ) { + // Ref: https://github.com/keijiro/StandardTriplanar - super( 'vec4' ); + // Blending factor of triplanar mapping + let bf = normalNode.abs().normalize(); + bf = bf.div( bf.dot( vec3( 1.0 ) ) ); - this.textureNode = textureNode; - this.directionNode = directionNode; - this.sigma = sigma; + // Triplanar mapping + const tx = positionNode.yz.mul( scaleNode ); + const ty = positionNode.zx.mul( scaleNode ); + const tz = positionNode.xy.mul( scaleNode ); - this._invSize = uniform( new Vector2() ); - this._passDirection = uniform( new Vector2() ); + // Base color + const textureX = textureXNode.value; + const textureY = textureYNode !== null ? textureYNode.value : textureX; + const textureZ = textureZNode !== null ? textureZNode.value : textureX; - this._horizontalRT = new RenderTarget(); - this._horizontalRT.texture.name = 'GaussianBlurNode.horizontal'; - this._verticalRT = new RenderTarget(); - this._verticalRT.texture.name = 'GaussianBlurNode.vertical'; + const cx = texture( textureX, tx ).mul( bf.x ); + const cy = texture( textureY, ty ).mul( bf.y ); + const cz = texture( textureZ, tz ).mul( bf.z ); - this._textureNode = passTexture( this, this._verticalRT.texture ); + return add( cx, cy, cz ); - this.updateBeforeType = NodeUpdateType.RENDER; + } - this.resolution = new Vector2( 1, 1 ); +} - } +const triplanarTextures = /*@__PURE__*/ nodeProxy( TriplanarTexturesNode ); +const triplanarTexture = ( ...params ) => triplanarTextures( ...params ); - setSize( width, height ) { +const _reflectorPlane = new Plane(); +const _normal = new Vector3(); +const _reflectorWorldPosition = new Vector3(); +const _cameraWorldPosition = new Vector3(); +const _rotationMatrix = new Matrix4(); +const _lookAtPosition = new Vector3( 0, 0, - 1 ); +const clipPlane = new Vector4(); - width = Math.max( Math.round( width * this.resolution.x ), 1 ); - height = Math.max( Math.round( height * this.resolution.y ), 1 ); +const _view = new Vector3(); +const _target = new Vector3(); +const _q = new Vector4(); - this._invSize.value.set( 1 / width, 1 / height ); - this._horizontalRT.setSize( width, height ); - this._verticalRT.setSize( width, height ); +const _size$9 = new Vector2(); - } +const _defaultRT = new RenderTarget(); +const _defaultUV = screenUV.flipX(); - updateBefore( frame ) { +let _inReflector = false; - const { renderer } = frame; +class ReflectorNode extends TextureNode { - const textureNode = this.textureNode; - const map = textureNode.value; + static get type() { - const currentRenderTarget = renderer.getRenderTarget(); - const currentMRT = renderer.getMRT(); + return 'ReflectorNode'; - const currentTexture = textureNode.value; + } - _quadMesh1.material = this._material; - _quadMesh2.material = this._material; + constructor( parameters = {} ) { - this.setSize( map.image.width, map.image.height ); + super( _defaultRT.texture, _defaultUV ); - const textureType = map.type; + const { + target = new Object3D(), + resolution = 1, + generateMipmaps = false, + bounces = true + } = parameters; - this._horizontalRT.texture.type = textureType; - this._verticalRT.texture.type = textureType; + // - // clear + this.target = target; + this.resolution = resolution; + this.generateMipmaps = generateMipmaps; + this.bounces = bounces; - renderer.setMRT( null ); + this.updateBeforeType = bounces ? NodeUpdateType.RENDER : NodeUpdateType.FRAME; - // horizontal + this.virtualCameras = new WeakMap(); + this.renderTargets = new WeakMap(); - renderer.setRenderTarget( this._horizontalRT ); - this._passDirection.value.set( 1, 0 ); + } - _quadMesh1.render( renderer ); + _updateResolution( renderTarget, renderer ) { - // vertical + const resolution = this.resolution; - textureNode.value = this._horizontalRT.texture; - renderer.setRenderTarget( this._verticalRT ); + renderer.getDrawingBufferSize( _size$9 ); - this._passDirection.value.set( 0, 1 ); + renderTarget.setSize( Math.round( _size$9.width * resolution ), Math.round( _size$9.height * resolution ) ); - _quadMesh2.render( renderer ); + } - // restore + setup( builder ) { - renderer.setRenderTarget( currentRenderTarget ); - renderer.setMRT( currentMRT ); - textureNode.value = currentTexture; + this._updateResolution( _defaultRT, builder.renderer ); + + return super.setup( builder ); } getTextureNode() { - return this._textureNode; + return this.textureNode; } - setup( builder ) { + getVirtualCamera( camera ) { - const textureNode = this.textureNode; + let virtualCamera = this.virtualCameras.get( camera ); - if ( textureNode.isTextureNode !== true ) { + if ( virtualCamera === undefined ) { - console.error( 'GaussianBlurNode requires a TextureNode.' ); + virtualCamera = camera.clone(); - return vec4(); + this.virtualCameras.set( camera, virtualCamera ); } - // + return virtualCamera; - const uvNode = textureNode.uvNode || uv(); - const directionNode = vec2( this.directionNode || 1 ); + } - const sampleTexture = ( uv ) => textureNode.uv( uv ); + getRenderTarget( camera ) { - const blur = Fn( () => { + let renderTarget = this.renderTargets.get( camera ); - const kernelSize = 3 + ( 2 * this.sigma ); - const gaussianCoefficients = this._getCoefficients( kernelSize ); + if ( renderTarget === undefined ) { - const invSize = this._invSize; - const direction = directionNode.mul( this._passDirection ); + renderTarget = new RenderTarget( 0, 0, { type: HalfFloatType } ); - const weightSum = float( gaussianCoefficients[ 0 ] ).toVar(); - const diffuseSum = vec4( sampleTexture( uvNode ).mul( weightSum ) ).toVar(); + if ( this.generateMipmaps === true ) { - for ( let i = 1; i < kernelSize; i ++ ) { - - const x = float( i ); - const w = float( gaussianCoefficients[ i ] ); - - const uvOffset = vec2( direction.mul( invSize.mul( x ) ) ).toVar(); - - const sample1 = vec4( sampleTexture( uvNode.add( uvOffset ) ) ); - const sample2 = vec4( sampleTexture( uvNode.sub( uvOffset ) ) ); - - diffuseSum.addAssign( sample1.add( sample2 ).mul( w ) ); - weightSum.addAssign( mul( 2.0, w ) ); + renderTarget.texture.minFilter = LinearMipMapLinearFilter; + renderTarget.texture.generateMipmaps = true; } - return diffuseSum.div( weightSum ); - - } ); - - // - - const material = this._material || ( this._material = new NodeMaterial() ); - material.fragmentNode = blur().context( builder.getSharedContext() ); - material.name = 'Gaussian_blur'; - material.needsUpdate = true; - - // - - const properties = builder.getNodeProperties( this ); - properties.textureNode = textureNode; - - // - - return this._textureNode; - - } + this.renderTargets.set( camera, renderTarget ); - dispose() { + } - this._horizontalRT.dispose(); - this._verticalRT.dispose(); + return renderTarget; } - _getCoefficients( kernelRadius ) { - - const coefficients = []; - - for ( let i = 0; i < kernelRadius; i ++ ) { + updateBefore( frame ) { - coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius ); + if ( this.bounces === false && _inReflector ) return false; - } + _inReflector = true; - return coefficients; + const { scene, camera, renderer, material } = frame; + const { target } = this; - } + const virtualCamera = this.getVirtualCamera( camera ); + const renderTarget = this.getRenderTarget( virtualCamera ); -} + renderer.getDrawingBufferSize( _size$9 ); -GaussianBlurNode.type = /*@__PURE__*/ registerNode( 'GaussianBlur', GaussianBlurNode ); + this._updateResolution( renderTarget, renderer ); -const gaussianBlur = ( node, directionNode, sigma ) => nodeObject( new GaussianBlurNode( convertToTexture( node ), directionNode, sigma ) ); + // -const _size$6 = /*@__PURE__*/ new Vector2(); + _reflectorWorldPosition.setFromMatrixPosition( target.matrixWorld ); + _cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld ); -const _quadMeshComp = /*@__PURE__*/ new QuadMesh(); + _rotationMatrix.extractRotation( target.matrixWorld ); -class AfterImageNode extends TempNode { + _normal.set( 0, 0, 1 ); + _normal.applyMatrix4( _rotationMatrix ); - constructor( textureNode, damp = 0.96 ) { + _view.subVectors( _reflectorWorldPosition, _cameraWorldPosition ); - super( textureNode ); + // Avoid rendering when reflector is facing away - this.textureNode = textureNode; - this.textureNodeOld = texture(); - this.damp = uniform( damp ); + if ( _view.dot( _normal ) > 0 ) return; - this._compRT = new RenderTarget(); - this._compRT.texture.name = 'AfterImageNode.comp'; + _view.reflect( _normal ).negate(); + _view.add( _reflectorWorldPosition ); - this._oldRT = new RenderTarget(); - this._oldRT.texture.name = 'AfterImageNode.old'; + _rotationMatrix.extractRotation( camera.matrixWorld ); - this._textureNode = passTexture( this, this._compRT.texture ); + _lookAtPosition.set( 0, 0, - 1 ); + _lookAtPosition.applyMatrix4( _rotationMatrix ); + _lookAtPosition.add( _cameraWorldPosition ); - this.updateBeforeType = NodeUpdateType.RENDER; + _target.subVectors( _reflectorWorldPosition, _lookAtPosition ); + _target.reflect( _normal ).negate(); + _target.add( _reflectorWorldPosition ); - } + // - getTextureNode() { + virtualCamera.coordinateSystem = camera.coordinateSystem; + virtualCamera.position.copy( _view ); + virtualCamera.up.set( 0, 1, 0 ); + virtualCamera.up.applyMatrix4( _rotationMatrix ); + virtualCamera.up.reflect( _normal ); + virtualCamera.lookAt( _target ); - return this._textureNode; + virtualCamera.near = camera.near; + virtualCamera.far = camera.far; - } + virtualCamera.updateMatrixWorld(); + virtualCamera.projectionMatrix.copy( camera.projectionMatrix ); - setSize( width, height ) { + // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html + // Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf + _reflectorPlane.setFromNormalAndCoplanarPoint( _normal, _reflectorWorldPosition ); + _reflectorPlane.applyMatrix4( virtualCamera.matrixWorldInverse ); - this._compRT.setSize( width, height ); - this._oldRT.setSize( width, height ); + clipPlane.set( _reflectorPlane.normal.x, _reflectorPlane.normal.y, _reflectorPlane.normal.z, _reflectorPlane.constant ); - } + const projectionMatrix = virtualCamera.projectionMatrix; - updateBefore( frame ) { + _q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ]; + _q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ]; + _q.z = - 1.0; + _q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; - const { renderer } = frame; + // Calculate the scaled plane vector + clipPlane.multiplyScalar( 1.0 / clipPlane.dot( _q ) ); - const textureNode = this.textureNode; - const map = textureNode.value; + const clipBias = 0; - const textureType = map.type; + // Replacing the third row of the projection matrix + projectionMatrix.elements[ 2 ] = clipPlane.x; + projectionMatrix.elements[ 6 ] = clipPlane.y; + projectionMatrix.elements[ 10 ] = clipPlane.z - clipBias; + projectionMatrix.elements[ 14 ] = clipPlane.w; - this._compRT.texture.type = textureType; - this._oldRT.texture.type = textureType; + // - renderer.getDrawingBufferSize( _size$6 ); + this.value = renderTarget.texture; - this.setSize( _size$6.x, _size$6.y ); + material.visible = false; const currentRenderTarget = renderer.getRenderTarget(); - const currentTexture = textureNode.value; - - this.textureNodeOld.value = this._oldRT.texture; + const currentMRT = renderer.getMRT(); - // comp - renderer.setRenderTarget( this._compRT ); - _quadMeshComp.render( renderer ); + renderer.setMRT( null ); + renderer.setRenderTarget( renderTarget ); - // Swap the textures - const temp = this._oldRT; - this._oldRT = this._compRT; - this._compRT = temp; + renderer.render( scene, virtualCamera ); + renderer.setMRT( currentMRT ); renderer.setRenderTarget( currentRenderTarget ); - textureNode.value = currentTexture; + + material.visible = true; + + _inReflector = false; } - setup( builder ) { +} - const textureNode = this.textureNode; - const textureNodeOld = this.textureNodeOld; +const reflector = ( parameters ) => nodeObject( new ReflectorNode( parameters ) ); - // +// Helper for passes that need to fill the viewport with a single quad. - const uvNode = textureNode.uvNode || uv(); +const _camera = /*@__PURE__*/ new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); - textureNodeOld.uvNode = uvNode; +// https://github.com/mrdoob/three.js/pull/21358 - const sampleTexture = ( uv ) => textureNode.uv( uv ); +class QuadGeometry extends BufferGeometry { - const when_gt = Fn( ( [ x_immutable, y_immutable ] ) => { + constructor( flipY = false ) { - const y = float( y_immutable ).toVar(); - const x = vec4( x_immutable ).toVar(); + super(); - return max$1( sign( x.sub( y ) ), 0.0 ); + const uv = flipY === false ? [ 0, - 1, 0, 1, 2, 1 ] : [ 0, 2, 0, 0, 2, 0 ]; - } ); + this.setAttribute( 'position', new Float32BufferAttribute( [ - 1, 3, 0, - 1, - 1, 0, 3, - 1, 0 ], 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uv, 2 ) ); - const afterImg = Fn( () => { + } - const texelOld = vec4( textureNodeOld ); - const texelNew = vec4( sampleTexture( uvNode ) ); +} - texelOld.mulAssign( this.damp.mul( when_gt( texelOld, 0.1 ) ) ); - return max$1( texelNew, texelOld ); +const _geometry = /*@__PURE__*/ new QuadGeometry(); - } ); +class QuadMesh extends Mesh { - // + constructor( material = null ) { - const materialComposed = this._materialComposed || ( this._materialComposed = new NodeMaterial() ); - materialComposed.name = 'AfterImage'; - materialComposed.fragmentNode = afterImg(); + super( _geometry, material ); - _quadMeshComp.material = materialComposed; + this.camera = _camera; - // + this.isQuadMesh = true; - const properties = builder.getNodeProperties( this ); - properties.textureNode = textureNode; + } - // + renderAsync( renderer ) { - return this._textureNode; + return renderer.renderAsync( this, _camera ); } - dispose() { + render( renderer ) { - this._compRT.dispose(); - this._oldRT.dispose(); + renderer.render( this, _camera ); } } -const afterImage = ( node, damp ) => nodeObject( new AfterImageNode( convertToTexture( node ), damp ) ); - -const grayscale = /*@__PURE__*/ Fn( ( [ color ] ) => { +const _size$8 = /*@__PURE__*/ new Vector2(); - return luminance( color.rgb ); +class RTTNode extends TextureNode { -} ); + static get type() { -const saturation = /*@__PURE__*/ Fn( ( [ color, adjustment = float( 1 ) ] ) => { + return 'RTTNode'; - return adjustment.mix( luminance( color.rgb ), color.rgb ); + } -} ); + constructor( node, width = null, height = null, options = { type: HalfFloatType } ) { -const vibrance = /*@__PURE__*/ Fn( ( [ color, adjustment = float( 1 ) ] ) => { + const renderTarget = new RenderTarget( width, height, options ); - const average = add( color.r, color.g, color.b ).div( 3.0 ); + super( renderTarget.texture, uv() ); - const mx = color.r.max( color.g.max( color.b ) ); - const amt = mx.sub( average ).mul( adjustment ).mul( - 3.0 ); + this.node = node; + this.width = width; + this.height = height; - return mix( color.rgb, mx, amt ); + this.renderTarget = renderTarget; -} ); + this.textureNeedsUpdate = true; + this.autoUpdate = true; -const hue = /*@__PURE__*/ Fn( ( [ color, adjustment = float( 1 ) ] ) => { + this.updateMap = new WeakMap(); - const k = vec3( 0.57735, 0.57735, 0.57735 ); + this._rttNode = null; + this._quadMesh = new QuadMesh( new NodeMaterial() ); - const cosAngle = adjustment.cos(); + this.updateBeforeType = NodeUpdateType.RENDER; - return vec3( color.rgb.mul( cosAngle ).add( k.cross( color.rgb ).mul( adjustment.sin() ).add( k.mul( dot( k, color.rgb ).mul( cosAngle.oneMinus() ) ) ) ) ); + } -} ); + get autoSize() { -const _luminanceCoefficients = /*@__PURE__*/ new Vector3(); -const luminance = ( - color, - luminanceCoefficients = vec3( ... ColorManagement.getLuminanceCoefficients( _luminanceCoefficients ) ) -) => dot( color, luminanceCoefficients ); + return this.width === null; -const threshold = ( color, threshold ) => mix( vec3( 0.0 ), color, luminance( color ).sub( threshold ).max( 0 ) ); + } -const _quadMesh$4 = /*@__PURE__*/ new QuadMesh(); + setup( builder ) { -class AnamorphicNode extends TempNode { + this._rttNode = this.node.context( builder.getSharedContext() ); + this._quadMesh.material.name = 'RTT'; + this._quadMesh.material.needsUpdate = true; - constructor( textureNode, tresholdNode, scaleNode, samples ) { + return super.setup( builder ); - super( 'vec4' ); + } - this.textureNode = textureNode; - this.tresholdNode = tresholdNode; - this.scaleNode = scaleNode; - this.colorNode = vec3( 0.1, 0.0, 1.0 ); - this.samples = samples; - this.resolution = new Vector2( 1, 1 ); + setSize( width, height ) { - this._renderTarget = new RenderTarget(); - this._renderTarget.texture.name = 'anamorphic'; + this.width = width; + this.height = height; - this._invSize = uniform( new Vector2() ); + const effectiveWidth = width * this.pixelRatio; + const effectiveHeight = height * this.pixelRatio; - this._textureNode = passTexture( this, this._renderTarget.texture ); + this.renderTarget.setSize( effectiveWidth, effectiveHeight ); - this.updateBeforeType = NodeUpdateType.RENDER; + this.textureNeedsUpdate = true; } - getTextureNode() { + setPixelRatio( pixelRatio ) { - return this._textureNode; + this.pixelRatio = pixelRatio; - } + this.setSize( this.width, this.height ); - setSize( width, height ) { + } - this._invSize.value.set( 1 / width, 1 / height ); + updateBefore( { renderer } ) { - width = Math.max( Math.round( width * this.resolution.x ), 1 ); - height = Math.max( Math.round( height * this.resolution.y ), 1 ); + if ( this.textureNeedsUpdate === false && this.autoUpdate === false ) return; - this._renderTarget.setSize( width, height ); + this.textureNeedsUpdate = false; - } + // - updateBefore( frame ) { + if ( this.autoSize === true ) { - const { renderer } = frame; + this.pixelRatio = renderer.getPixelRatio(); - const textureNode = this.textureNode; - const map = textureNode.value; + const size = renderer.getSize( _size$8 ); - this._renderTarget.texture.type = map.type; + this.setSize( size.width, size.height ); - const currentRenderTarget = renderer.getRenderTarget(); - const currentTexture = textureNode.value; + } - _quadMesh$4.material = this._material; + // - this.setSize( map.image.width, map.image.height ); + this._quadMesh.material.fragmentNode = this._rttNode; - // render + // - renderer.setRenderTarget( this._renderTarget ); + const currentRenderTarget = renderer.getRenderTarget(); - _quadMesh$4.render( renderer ); + renderer.setRenderTarget( this.renderTarget ); - // restore + this._quadMesh.render( renderer ); renderer.setRenderTarget( currentRenderTarget ); - textureNode.value = currentTexture; } - setup( builder ) { - - const textureNode = this.textureNode; - const uvNode = textureNode.uvNode || uv(); + clone() { - const sampleTexture = ( uv ) => textureNode.uv( uv ); + const newNode = new TextureNode( this.value, this.uvNode, this.levelNode ); + newNode.sampler = this.sampler; + newNode.referenceNode = this; - const anamorph = Fn( () => { + return newNode; - const samples = this.samples; - const halfSamples = Math.floor( samples / 2 ); + } - const total = vec3( 0 ).toVar(); +} - Loop( { start: - halfSamples, end: halfSamples }, ( { i } ) => { +const rtt = ( node, ...params ) => nodeObject( new RTTNode( nodeObject( node ), ...params ) ); +const convertToTexture = ( node, ...params ) => node.isTextureNode ? node : rtt( node, ...params ); - const softness = float( i ).abs().div( halfSamples ).oneMinus(); +class VertexColorNode extends AttributeNode { - const uv = vec2( uvNode.x.add( this._invSize.x.mul( i ).mul( this.scaleNode ) ), uvNode.y ); - const color = sampleTexture( uv ); - const pass = threshold( color, this.tresholdNode ).mul( softness ); + static get type() { - total.addAssign( pass ); + return 'VertexColorNode'; - } ); + } - return total.mul( this.colorNode ); + constructor( index = 0 ) { - } ); + super( null, 'vec4' ); - // + this.isVertexColorNode = true; - const material = this._material || ( this._material = new NodeMaterial() ); - material.name = 'Anamorphic'; - material.fragmentNode = anamorph(); + this.index = index; - // + } - const properties = builder.getNodeProperties( this ); - properties.textureNode = textureNode; + getAttributeName( /*builder*/ ) { - // + const index = this.index; - return this._textureNode; + return 'color' + ( index > 0 ? index : '' ); } - dispose() { - - this._renderTarget.dispose(); - - } + generate( builder ) { -} + const attributeName = this.getAttributeName( builder ); + const geometryAttribute = builder.hasGeometryAttribute( attributeName ); -const anamorphic = ( node, threshold = .9, scale = 3, samples = 32 ) => nodeObject( new AnamorphicNode( convertToTexture( node ), nodeObject( threshold ), nodeObject( scale ), samples ) ); + let result; -class SobelOperatorNode extends TempNode { + if ( geometryAttribute === true ) { - constructor( textureNode ) { + result = super.generate( builder ); - super(); + } else { - this.textureNode = textureNode; + // Vertex color fallback should be white + result = builder.generateConst( this.nodeType, new Vector4( 1, 1, 1, 1 ) ); - this.updateBeforeType = NodeUpdateType.RENDER; + } - this._invSize = uniform( new Vector2() ); + return result; } - updateBefore() { + serialize( data ) { - const map = this.textureNode.value; + super.serialize( data ); - this._invSize.value.set( 1 / map.image.width, 1 / map.image.height ); + data.index = this.index; } - setup() { - - const { textureNode } = this; + deserialize( data ) { - const uvNode = textureNode.uvNode || uv(); + super.deserialize( data ); - const sampleTexture = ( uv ) => textureNode.uv( uv ); + this.index = data.index; - const sobel = Fn( () => { + } - // Sobel Edge Detection (see https://youtu.be/uihBwtPIBxM) +} - const texel = this._invSize; +const vertexColor = ( ...params ) => nodeObject( new VertexColorNode( ...params ) ); - // kernel definition (in glsl matrices are filled in column-major order) +class PointUVNode extends Node { - const Gx = mat3( - 1, - 2, - 1, 0, 0, 0, 1, 2, 1 ); // x direction kernel - const Gy = mat3( - 1, 0, 1, - 2, 0, 2, - 1, 0, 1 ); // y direction kernel + static get type() { - // fetch the 3x3 neighbourhood of a fragment + return 'PointUVNode'; - // first column + } - const tx0y0 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( - 1, - 1 ) ) ) ).xyz ); - const tx0y1 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( - 1, 0 ) ) ) ).xyz ); - const tx0y2 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( - 1, 1 ) ) ) ).xyz ); + constructor() { - // second column + super( 'vec2' ); - const tx1y0 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 0, - 1 ) ) ) ).xyz ); - const tx1y1 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 0, 0 ) ) ) ).xyz ); - const tx1y2 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 0, 1 ) ) ) ).xyz ); + this.isPointUVNode = true; - // third column + } - const tx2y0 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 1, - 1 ) ) ) ).xyz ); - const tx2y1 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 1, 0 ) ) ) ).xyz ); - const tx2y2 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 1, 1 ) ) ) ).xyz ); + generate( /*builder*/ ) { - // gradient value in x direction + return 'vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y )'; - const valueGx = add( - Gx[ 0 ][ 0 ].mul( tx0y0 ), - Gx[ 1 ][ 0 ].mul( tx1y0 ), - Gx[ 2 ][ 0 ].mul( tx2y0 ), - Gx[ 0 ][ 1 ].mul( tx0y1 ), - Gx[ 1 ][ 1 ].mul( tx1y1 ), - Gx[ 2 ][ 1 ].mul( tx2y1 ), - Gx[ 0 ][ 2 ].mul( tx0y2 ), - Gx[ 1 ][ 2 ].mul( tx1y2 ), - Gx[ 2 ][ 2 ].mul( tx2y2 ) - ); + } +} - // gradient value in y direction +const pointUV = /*@__PURE__*/ nodeImmutable( PointUVNode ); - const valueGy = add( - Gy[ 0 ][ 0 ].mul( tx0y0 ), - Gy[ 1 ][ 0 ].mul( tx1y0 ), - Gy[ 2 ][ 0 ].mul( tx2y0 ), - Gy[ 0 ][ 1 ].mul( tx0y1 ), - Gy[ 1 ][ 1 ].mul( tx1y1 ), - Gy[ 2 ][ 1 ].mul( tx2y1 ), - Gy[ 0 ][ 2 ].mul( tx0y2 ), - Gy[ 1 ][ 2 ].mul( tx1y2 ), - Gy[ 2 ][ 2 ].mul( tx2y2 ) - ); +class SceneNode extends Node { - // magnitute of the total gradient + static get type() { - const G = valueGx.mul( valueGx ).add( valueGy.mul( valueGy ) ).sqrt(); + return 'SceneNode'; - return vec4( vec3( G ), 1 ); + } - } ); + constructor( scope = SceneNode.BACKGROUND_BLURRINESS, scene = null ) { - const outputNode = sobel(); + super(); - return outputNode; + this.scope = scope; + this.scene = scene; } -} + setup( builder ) { -SobelOperatorNode.type = /*@__PURE__*/ registerNode( 'SobelOperator', SobelOperatorNode ); + const scope = this.scope; + const scene = this.scene !== null ? this.scene : builder.scene; -const sobel = ( node ) => nodeObject( new SobelOperatorNode( convertToTexture( node ) ) ); + let output; -class DepthOfFieldNode extends TempNode { + if ( scope === SceneNode.BACKGROUND_BLURRINESS ) { - constructor( textureNode, viewZNode, focusNode, apertureNode, maxblurNode ) { + output = reference( 'backgroundBlurriness', 'float', scene ); - super(); + } else if ( scope === SceneNode.BACKGROUND_INTENSITY ) { - this.textureNode = textureNode; - this.viewZNode = viewZNode; + output = reference( 'backgroundIntensity', 'float', scene ); - this.focusNode = focusNode; - this.apertureNode = apertureNode; - this.maxblurNode = maxblurNode; + } else { - this._aspect = uniform( 0 ); + console.error( 'THREE.SceneNode: Unknown scope:', scope ); - this.updateBeforeType = NodeUpdateType.RENDER; + } + + return output; } - updateBefore() { +} - const map = this.textureNode.value; +SceneNode.BACKGROUND_BLURRINESS = 'backgroundBlurriness'; +SceneNode.BACKGROUND_INTENSITY = 'backgroundIntensity'; - this._aspect.value = map.image.width / map.image.height; - - } +const backgroundBlurriness = /*@__PURE__*/ nodeImmutable( SceneNode, SceneNode.BACKGROUND_BLURRINESS ); +const backgroundIntensity = /*@__PURE__*/ nodeImmutable( SceneNode, SceneNode.BACKGROUND_INTENSITY ); - setup() { +const GPUPrimitiveTopology = { + PointList: 'point-list', + LineList: 'line-list', + LineStrip: 'line-strip', + TriangleList: 'triangle-list', + TriangleStrip: 'triangle-strip', +}; - const textureNode = this.textureNode; - const uvNode = textureNode.uvNode || uv(); +const GPUCompareFunction = { + Never: 'never', + Less: 'less', + Equal: 'equal', + LessEqual: 'less-equal', + Greater: 'greater', + NotEqual: 'not-equal', + GreaterEqual: 'greater-equal', + Always: 'always' +}; - const sampleTexture = ( uv ) => textureNode.uv( uv ); +const GPUStoreOp = { + Store: 'store', + Discard: 'discard' +}; - const dof = Fn( () => { +const GPULoadOp = { + Load: 'load', + Clear: 'clear' +}; - const aspectcorrect = vec2( 1.0, this._aspect ); +const GPUFrontFace = { + CCW: 'ccw', + CW: 'cw' +}; - const factor = this.focusNode.add( this.viewZNode ); +const GPUCullMode = { + None: 'none', + Front: 'front', + Back: 'back' +}; - const dofblur = vec2( clamp( factor.mul( this.apertureNode ), this.maxblurNode.negate(), this.maxblurNode ) ); +const GPUIndexFormat = { + Uint16: 'uint16', + Uint32: 'uint32' +}; - const dofblur9 = dofblur.mul( 0.9 ); - const dofblur7 = dofblur.mul( 0.7 ); - const dofblur4 = dofblur.mul( 0.4 ); +const GPUTextureFormat = { - let col = vec4( 0.0 ); + // 8-bit formats - col = col.add( sampleTexture( uvNode ) ); + R8Unorm: 'r8unorm', + R8Snorm: 'r8snorm', + R8Uint: 'r8uint', + R8Sint: 'r8sint', - col = col.add( sampleTexture( uvNode.add( vec2( 0.0, 0.4 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.15, 0.37 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.37, 0.15 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.40, 0.0 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.37, - 0.15 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.15, - 0.37 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.0, - 0.4 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.15, 0.37 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.37, 0.15 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.4, 0.0 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.37, - 0.15 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.15, - 0.37 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.15, 0.37 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.37, 0.15 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.37, - 0.15 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.15, - 0.37 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.15, 0.37 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.37, 0.15 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.37, - 0.15 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.15, - 0.37 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.40, 0.0 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.0, - 0.4 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.4, 0.0 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.0, 0.4 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.4, 0.0 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.0, - 0.4 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.4, 0.0 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); - col = col.add( sampleTexture( uvNode.add( vec2( 0.0, 0.4 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); + // 16-bit formats - col = col.div( 41 ); - col.a = 1; + R16Uint: 'r16uint', + R16Sint: 'r16sint', + R16Float: 'r16float', + RG8Unorm: 'rg8unorm', + RG8Snorm: 'rg8snorm', + RG8Uint: 'rg8uint', + RG8Sint: 'rg8sint', - return vec4( col ); + // 32-bit formats + R32Uint: 'r32uint', + R32Sint: 'r32sint', + R32Float: 'r32float', + RG16Uint: 'rg16uint', + RG16Sint: 'rg16sint', + RG16Float: 'rg16float', + RGBA8Unorm: 'rgba8unorm', + RGBA8UnormSRGB: 'rgba8unorm-srgb', + RGBA8Snorm: 'rgba8snorm', + RGBA8Uint: 'rgba8uint', + RGBA8Sint: 'rgba8sint', + BGRA8Unorm: 'bgra8unorm', + BGRA8UnormSRGB: 'bgra8unorm-srgb', + // Packed 32-bit formats + RGB9E5UFloat: 'rgb9e5ufloat', + RGB10A2Unorm: 'rgb10a2unorm', + RG11B10uFloat: 'rgb10a2unorm', - } ); + // 64-bit formats - const outputNode = dof(); + RG32Uint: 'rg32uint', + RG32Sint: 'rg32sint', + RG32Float: 'rg32float', + RGBA16Uint: 'rgba16uint', + RGBA16Sint: 'rgba16sint', + RGBA16Float: 'rgba16float', - return outputNode; + // 128-bit formats - } + RGBA32Uint: 'rgba32uint', + RGBA32Sint: 'rgba32sint', + RGBA32Float: 'rgba32float', -} + // Depth and stencil formats -DepthOfFieldNode.type = /*@__PURE__*/ registerNode( 'DepthOfField', DepthOfFieldNode ); + Stencil8: 'stencil8', + Depth16Unorm: 'depth16unorm', + Depth24Plus: 'depth24plus', + Depth24PlusStencil8: 'depth24plus-stencil8', + Depth32Float: 'depth32float', -const dof = ( node, viewZNode, focus = 1, aperture = 0.025, maxblur = 1 ) => nodeObject( new DepthOfFieldNode( convertToTexture( node ), nodeObject( viewZNode ), nodeObject( focus ), nodeObject( aperture ), nodeObject( maxblur ) ) ); + // 'depth32float-stencil8' extension -class DotScreenNode extends TempNode { + Depth32FloatStencil8: 'depth32float-stencil8', - constructor( inputNode, center = new Vector2( 0.5, 0.5 ), angle = 1.57, scale = 1 ) { + // BC compressed formats usable if 'texture-compression-bc' is both + // supported by the device/user agent and enabled in requestDevice. - super( 'vec4' ); + BC1RGBAUnorm: 'bc1-rgba-unorm', + BC1RGBAUnormSRGB: 'bc1-rgba-unorm-srgb', + BC2RGBAUnorm: 'bc2-rgba-unorm', + BC2RGBAUnormSRGB: 'bc2-rgba-unorm-srgb', + BC3RGBAUnorm: 'bc3-rgba-unorm', + BC3RGBAUnormSRGB: 'bc3-rgba-unorm-srgb', + BC4RUnorm: 'bc4-r-unorm', + BC4RSnorm: 'bc4-r-snorm', + BC5RGUnorm: 'bc5-rg-unorm', + BC5RGSnorm: 'bc5-rg-snorm', + BC6HRGBUFloat: 'bc6h-rgb-ufloat', + BC6HRGBFloat: 'bc6h-rgb-float', + BC7RGBAUnorm: 'bc7-rgba-unorm', + BC7RGBAUnormSRGB: 'bc7-rgba-srgb', - this.inputNode = inputNode; - this.center = uniform( center ); - this.angle = uniform( angle ); - this.scale = uniform( scale ); + // ETC2 compressed formats usable if 'texture-compression-etc2' is both + // supported by the device/user agent and enabled in requestDevice. - } + ETC2RGB8Unorm: 'etc2-rgb8unorm', + ETC2RGB8UnormSRGB: 'etc2-rgb8unorm-srgb', + ETC2RGB8A1Unorm: 'etc2-rgb8a1unorm', + ETC2RGB8A1UnormSRGB: 'etc2-rgb8a1unorm-srgb', + ETC2RGBA8Unorm: 'etc2-rgba8unorm', + ETC2RGBA8UnormSRGB: 'etc2-rgba8unorm-srgb', + EACR11Unorm: 'eac-r11unorm', + EACR11Snorm: 'eac-r11snorm', + EACRG11Unorm: 'eac-rg11unorm', + EACRG11Snorm: 'eac-rg11snorm', - setup() { + // ASTC compressed formats usable if 'texture-compression-astc' is both + // supported by the device/user agent and enabled in requestDevice. - const inputNode = this.inputNode; + ASTC4x4Unorm: 'astc-4x4-unorm', + ASTC4x4UnormSRGB: 'astc-4x4-unorm-srgb', + ASTC5x4Unorm: 'astc-5x4-unorm', + ASTC5x4UnormSRGB: 'astc-5x4-unorm-srgb', + ASTC5x5Unorm: 'astc-5x5-unorm', + ASTC5x5UnormSRGB: 'astc-5x5-unorm-srgb', + ASTC6x5Unorm: 'astc-6x5-unorm', + ASTC6x5UnormSRGB: 'astc-6x5-unorm-srgb', + ASTC6x6Unorm: 'astc-6x6-unorm', + ASTC6x6UnormSRGB: 'astc-6x6-unorm-srgb', + ASTC8x5Unorm: 'astc-8x5-unorm', + ASTC8x5UnormSRGB: 'astc-8x5-unorm-srgb', + ASTC8x6Unorm: 'astc-8x6-unorm', + ASTC8x6UnormSRGB: 'astc-8x6-unorm-srgb', + ASTC8x8Unorm: 'astc-8x8-unorm', + ASTC8x8UnormSRGB: 'astc-8x8-unorm-srgb', + ASTC10x5Unorm: 'astc-10x5-unorm', + ASTC10x5UnormSRGB: 'astc-10x5-unorm-srgb', + ASTC10x6Unorm: 'astc-10x6-unorm', + ASTC10x6UnormSRGB: 'astc-10x6-unorm-srgb', + ASTC10x8Unorm: 'astc-10x8-unorm', + ASTC10x8UnormSRGB: 'astc-10x8-unorm-srgb', + ASTC10x10Unorm: 'astc-10x10-unorm', + ASTC10x10UnormSRGB: 'astc-10x10-unorm-srgb', + ASTC12x10Unorm: 'astc-12x10-unorm', + ASTC12x10UnormSRGB: 'astc-12x10-unorm-srgb', + ASTC12x12Unorm: 'astc-12x12-unorm', + ASTC12x12UnormSRGB: 'astc-12x12-unorm-srgb', - const pattern = Fn( () => { +}; - const s = sin( this.angle ); - const c = cos( this.angle ); +const GPUAddressMode = { + ClampToEdge: 'clamp-to-edge', + Repeat: 'repeat', + MirrorRepeat: 'mirror-repeat' +}; - const tex = uv().mul( viewportResolution ).sub( this.center ); - const point = vec2( c.mul( tex.x ).sub( s.mul( tex.y ) ), s.mul( tex.x ).add( c.mul( tex.y ) ) ).mul( this.scale ); +const GPUFilterMode = { + Linear: 'linear', + Nearest: 'nearest' +}; - return sin( point.x ).mul( sin( point.y ) ).mul( 4 ); +const GPUBlendFactor = { + Zero: 'zero', + One: 'one', + Src: 'src', + OneMinusSrc: 'one-minus-src', + SrcAlpha: 'src-alpha', + OneMinusSrcAlpha: 'one-minus-src-alpha', + Dst: 'dst', + OneMinusDstColor: 'one-minus-dst', + DstAlpha: 'dst-alpha', + OneMinusDstAlpha: 'one-minus-dst-alpha', + SrcAlphaSaturated: 'src-alpha-saturated', + Constant: 'constant', + OneMinusConstant: 'one-minus-constant' +}; - } ); +const GPUBlendOperation = { + Add: 'add', + Subtract: 'subtract', + ReverseSubtract: 'reverse-subtract', + Min: 'min', + Max: 'max' +}; - const dotScreen = Fn( () => { +const GPUColorWriteFlags = { + None: 0, + Red: 0x1, + Green: 0x2, + Blue: 0x4, + Alpha: 0x8, + All: 0xF +}; - const color = inputNode; +const GPUStencilOperation = { + Keep: 'keep', + Zero: 'zero', + Replace: 'replace', + Invert: 'invert', + IncrementClamp: 'increment-clamp', + DecrementClamp: 'decrement-clamp', + IncrementWrap: 'increment-wrap', + DecrementWrap: 'decrement-wrap' +}; - const average = add( color.r, color.g, color.b ).div( 3 ); +const GPUBufferBindingType = { + Uniform: 'uniform', + Storage: 'storage', + ReadOnlyStorage: 'read-only-storage' +}; - return vec4( vec3( average.mul( 10 ).sub( 5 ).add( pattern() ) ), color.a ); +const GPUStorageTextureAccess = { + WriteOnly: 'write-only', + ReadOnly: 'read-only', + ReadWrite: 'read-write', +}; - } ); +const GPUTextureSampleType = { + Float: 'float', + UnfilterableFloat: 'unfilterable-float', + Depth: 'depth', + SInt: 'sint', + UInt: 'uint' +}; - const outputNode = dotScreen(); +const GPUTextureDimension = { + OneD: '1d', + TwoD: '2d', + ThreeD: '3d' +}; - return outputNode; +const GPUTextureViewDimension = { + OneD: '1d', + TwoD: '2d', + TwoDArray: '2d-array', + Cube: 'cube', + CubeArray: 'cube-array', + ThreeD: '3d' +}; - } +const GPUTextureAspect = { + All: 'all', + StencilOnly: 'stencil-only', + DepthOnly: 'depth-only' +}; -} +const GPUInputStepMode = { + Vertex: 'vertex', + Instance: 'instance' +}; -DotScreenNode.type = /*@__PURE__*/ registerNode( 'DotScreen', DotScreenNode ); +const GPUFeatureName = { + DepthClipControl: 'depth-clip-control', + Depth32FloatStencil8: 'depth32float-stencil8', + TextureCompressionBC: 'texture-compression-bc', + TextureCompressionETC2: 'texture-compression-etc2', + TextureCompressionASTC: 'texture-compression-astc', + TimestampQuery: 'timestamp-query', + IndirectFirstInstance: 'indirect-first-instance', + ShaderF16: 'shader-f16', + RG11B10UFloat: 'rg11b10ufloat-renderable', + BGRA8UNormStorage: 'bgra8unorm-storage', + Float32Filterable: 'float32-filterable', + ClipDistances: 'clip-distances', + DualSourceBlending: 'dual-source-blending', + Subgroups: 'subgroups' +}; -const dotScreen = ( node, center, angle, scale ) => nodeObject( new DotScreenNode( nodeObject( node ), center, angle, scale ) ); +class StorageBufferNode extends BufferNode { -class RGBShiftNode extends TempNode { + static get type() { - constructor( textureNode, amount = 0.005, angle = 0 ) { + return 'StorageBufferNode'; - super( 'vec4' ); + } - this.textureNode = textureNode; - this.amount = uniform( amount ); - this.angle = uniform( angle ); + constructor( value, bufferType, bufferCount = 0 ) { - } + super( value, bufferType, bufferCount ); - setup() { + this.isStorageBufferNode = true; - const { textureNode } = this; + this.access = GPUBufferBindingType.Storage; + this.isAtomic = false; - const uvNode = textureNode.uvNode || uv(); + this.bufferObject = false; + this.bufferCount = bufferCount; - const sampleTexture = ( uv ) => textureNode.uv( uv ); + this._attribute = null; + this._varying = null; - const rgbShift = Fn( () => { + this.global = true; - const offset = vec2( cos( this.angle ), sin( this.angle ) ).mul( this.amount ); - const cr = sampleTexture( uvNode.add( offset ) ); - const cga = sampleTexture( uvNode ); - const cb = sampleTexture( uvNode.sub( offset ) ); + if ( value.isStorageBufferAttribute !== true && value.isStorageInstancedBufferAttribute !== true ) { - return vec4( cr.r, cga.g, cb.b, cga.a ); + // TOOD: Improve it, possibly adding a new property to the BufferAttribute to identify it as a storage buffer read-only attribute in Renderer - } ); + if ( value.isInstancedBufferAttribute ) value.isStorageInstancedBufferAttribute = true; + else value.isStorageBufferAttribute = true; - return rgbShift(); + } } -} + getHash( builder ) { -RGBShiftNode.type = /*@__PURE__*/ registerNode( 'RGBShift', RGBShiftNode ); + if ( this.bufferCount === 0 ) { -const rgbShift = ( node, amount, angle ) => nodeObject( new RGBShiftNode( convertToTexture( node ), amount, angle ) ); + let bufferData = builder.globalCache.getData( this.value ); -class FilmNode extends TempNode { + if ( bufferData === undefined ) { - constructor( inputNode, intensityNode = null, uvNode = null ) { + bufferData = { + node: this + }; - super(); + builder.globalCache.setData( this.value, bufferData ); - this.inputNode = inputNode; - this.intensityNode = intensityNode; - this.uvNode = uvNode; + } + + return bufferData.node.uuid; + + } + + return this.uuid; } - setup() { + getInputType( /*builder*/ ) { - const uvNode = this.uvNode || uv(); + return 'storageBuffer'; - const film = Fn( () => { + } - const base = this.inputNode.rgb; - const noise = rand( fract( uvNode.add( timerLocal() ) ) ); + element( indexNode ) { - let color = base.add( base.mul( clamp( noise.add( 0.1 ), 0, 1 ) ) ); + return storageElement( this, indexNode ); - if ( this.intensityNode !== null ) { + } - color = mix( base, color, this.intensityNode ); + setBufferObject( value ) { - } + this.bufferObject = value; - return vec4( color, this.inputNode.a ); + return this; - } ); + } - const outputNode = film(); + setAccess( value ) { - return outputNode; + this.access = value; + + return this; } -} + toReadOnly() { -FilmNode.type = /*@__PURE__*/ registerNode( 'Film', FilmNode ); + return this.setAccess( GPUBufferBindingType.ReadOnlyStorage ); -const film = /*@__PURE__*/ nodeProxy( FilmNode ); + } -class Lut3DNode extends TempNode { + setAtomic( value ) { - constructor( inputNode, lutNode, size, intensityNode ) { + this.isAtomic = value; - super(); + return this; - this.inputNode = inputNode; - this.lutNode = lutNode; - this.size = uniform( size ); - this.intensityNode = intensityNode; + } + + toAtomic() { + + return this.setAtomic( true ); } - setup() { + generate( builder ) { - const { inputNode, lutNode } = this; + if ( builder.isAvailable( 'storageBuffer' ) ) { - const sampleLut = ( uv ) => lutNode.uv( uv ); + return super.generate( builder ); - const lut3D = Fn( () => { + } - const base = inputNode; + const nodeType = this.getNodeType( builder ); - // pull the sample in by half a pixel so the sample begins at the center of the edge pixels. + if ( this._attribute === null ) { - const pixelWidth = float( 1.0 ).div( this.size ); - const halfPixelWidth = float( 0.5 ).div( this.size ); - const uvw = vec3( halfPixelWidth ).add( base.rgb.mul( float( 1.0 ).sub( pixelWidth ) ) ); + this._attribute = bufferAttribute( this.value ); + this._varying = varying( this._attribute ); - const lutValue = vec4( sampleLut( uvw ).rgb, base.a ); + } - return vec4( mix( base, lutValue, this.intensityNode ) ); - } ); + const output = this._varying.build( builder, nodeType ); - const outputNode = lut3D(); + builder.registerTransform( output, this._attribute ); - return outputNode; + return output; } } -Lut3DNode.type = /*@__PURE__*/ registerNode( 'Lut3D', Lut3DNode ); +// Read-Write Storage +const storage = ( value, type, count ) => nodeObject( new StorageBufferNode( value, type, count ) ); +const storageObject = ( value, type, count ) => nodeObject( new StorageBufferNode( value, type, count ).setBufferObject( true ) ); -const lut3D = ( node, lut, size, intensity ) => nodeObject( new Lut3DNode( nodeObject( node ), nodeObject( lut ), size, nodeObject( intensity ) ) ); +class StorageTextureNode extends TextureNode { -const _quadMesh$3 = /*@__PURE__*/ new QuadMesh(); -const _currentClearColor$1 = /*@__PURE__*/ new Color(); -const _size$5 = /*@__PURE__*/ new Vector2(); + static get type() { -class GTAONode extends TempNode { + return 'StorageTextureNode'; - constructor( depthNode, normalNode, camera ) { + } - super(); + constructor( value, uvNode, storeNode = null ) { - this.depthNode = depthNode; - this.normalNode = normalNode; + super( value, uvNode ); - this.radius = uniform( 0.25 ); - this.resolution = uniform( new Vector2() ); - this.thickness = uniform( 1 ); - this.distanceExponent = uniform( 1 ); - this.distanceFallOff = uniform( 1 ); - this.scale = uniform( 1 ); - this.noiseNode = texture( generateMagicSquareNoise() ); + this.storeNode = storeNode; - this.cameraProjectionMatrix = uniform( camera.projectionMatrix ); - this.cameraProjectionMatrixInverse = uniform( camera.projectionMatrixInverse ); + this.isStorageTextureNode = true; - this.SAMPLES = uniform( 16 ); + this.access = GPUStorageTextureAccess.WriteOnly; - this._aoRenderTarget = new RenderTarget(); - this._aoRenderTarget.texture.name = 'GTAONode.AO'; + } - this._material = null; - this._textureNode = passTexture( this, this._aoRenderTarget.texture ); + getInputType( /*builder*/ ) { - this.updateBeforeType = NodeUpdateType.FRAME; + return 'storageTexture'; } - getTextureNode() { + setup( builder ) { - return this._textureNode; + super.setup( builder ); + + const properties = builder.getNodeProperties( this ); + properties.storeNode = this.storeNode; } - setSize( width, height ) { + setAccess( value ) { - this.resolution.value.set( width, height ); - this._aoRenderTarget.setSize( width, height ); + this.access = value; + return this; } - updateBefore( frame ) { - - const { renderer } = frame; + generate( builder, output ) { - const size = renderer.getDrawingBufferSize( _size$5 ); + let snippet; - const currentRenderTarget = renderer.getRenderTarget(); - const currentMRT = renderer.getMRT(); - renderer.getClearColor( _currentClearColor$1 ); - const currentClearAlpha = renderer.getClearAlpha(); + if ( this.storeNode !== null ) { - _quadMesh$3.material = this._material; + snippet = this.generateStore( builder ); - this.setSize( size.width, size.height ); + } else { - // clear + snippet = super.generate( builder, output ); - renderer.setMRT( null ); - renderer.setClearColor( 0xffffff, 1 ); + } - // ao + return snippet; - renderer.setRenderTarget( this._aoRenderTarget ); - _quadMesh$3.render( renderer ); + } - // restore + toReadOnly() { - renderer.setRenderTarget( currentRenderTarget ); - renderer.setMRT( currentMRT ); - renderer.setClearColor( _currentClearColor$1, currentClearAlpha ); + return this.setAccess( GPUStorageTextureAccess.ReadOnly ); } - setup( builder ) { + toWriteOnly() { - const uvNode = uv(); + return this.setAccess( GPUStorageTextureAccess.WriteOnly ); - const sampleDepth = ( uv ) => this.depthNode.uv( uv ).x; - const sampleNoise = ( uv ) => this.noiseNode.uv( uv ); + } - const getSceneUvAndDepth = Fn( ( [ sampleViewPos ] )=> { + generateStore( builder ) { - const sampleClipPos = this.cameraProjectionMatrix.mul( vec4( sampleViewPos, 1.0 ) ); - let sampleUv = sampleClipPos.xy.div( sampleClipPos.w ).mul( 0.5 ).add( 0.5 ).toVar(); - sampleUv = vec2( sampleUv.x, sampleUv.y.oneMinus() ); - const sampleSceneDepth = sampleDepth( sampleUv ); - return vec3( sampleUv, sampleSceneDepth ); + const properties = builder.getNodeProperties( this ); - } ); + const { uvNode, storeNode } = properties; - const getViewPosition = Fn( ( [ screenPosition, depth ] ) => { + const textureProperty = super.generate( builder, 'property' ); + const uvSnippet = uvNode.build( builder, 'uvec2' ); + const storeSnippet = storeNode.build( builder, 'vec4' ); - screenPosition = vec2( screenPosition.x, screenPosition.y.oneMinus() ).mul( 2.0 ).sub( 1.0 ); + const snippet = builder.generateTextureStore( builder, textureProperty, uvSnippet, storeSnippet ); - const clipSpacePosition = vec4( vec3( screenPosition, depth ), 1.0 ); - const viewSpacePosition = vec4( this.cameraProjectionMatrixInverse.mul( clipSpacePosition ) ); + builder.addLineFlowCode( snippet, this ); - return viewSpacePosition.xyz.div( viewSpacePosition.w ); + } - } ); +} - const ao = Fn( () => { +const storageTexture = /*@__PURE__*/ nodeProxy( StorageTextureNode ); - const depth = sampleDepth( uvNode ); +const textureStore = ( value, uvNode, storeNode ) => { - depth.greaterThanEqual( 1.0 ).discard(); + const node = storageTexture( value, uvNode, storeNode ); - const viewPosition = getViewPosition( uvNode, depth ); - const viewNormal = this.normalNode.rgb.normalize(); + if ( storeNode !== null ) node.append(); - const radiusToUse = this.radius; + return node; - const noiseResolution = textureSize( this.noiseNode, 0 ); - let noiseUv = vec2( uvNode.x, uvNode.y.oneMinus() ); - noiseUv = noiseUv.mul( this.resolution.div( noiseResolution ) ); - const noiseTexel = sampleNoise( noiseUv ); - const randomVec = noiseTexel.xyz.mul( 2.0 ).sub( 1.0 ); - const tangent = vec3( randomVec.xy, 0.0 ).normalize(); - const bitangent = vec3( tangent.y.mul( - 1.0 ), tangent.x, 0.0 ); - const kernelMatrix = mat3( tangent, bitangent, vec3( 0.0, 0.0, 1.0 ) ); +}; - const DIRECTIONS = this.SAMPLES.lessThan( 30 ).select( 3, 5 ); - const STEPS = add( this.SAMPLES, DIRECTIONS.sub( 1 ) ).div( DIRECTIONS ); +class UserDataNode extends ReferenceNode { - const ao = float( 0 ).toVar(); + static get type() { - Loop( { start: int( 0 ), end: DIRECTIONS, type: 'int', condition: '<' }, ( { i } ) => { + return 'UserDataNode'; - const angle = float( i ).div( float( DIRECTIONS ) ).mul( PI ); - const sampleDir = vec4( cos( angle ), sin( angle ), 0., add( 0.5, mul( 0.5, noiseTexel.w ) ) ); - sampleDir.xyz = normalize( kernelMatrix.mul( sampleDir.xyz ) ); + } - const viewDir = normalize( viewPosition.xyz.negate() ); - const sliceBitangent = normalize( cross( sampleDir.xyz, viewDir ) ); - const sliceTangent = cross( sliceBitangent, viewDir ); - const normalInSlice = normalize( viewNormal.sub( sliceBitangent.mul( dot( viewNormal, sliceBitangent ) ) ) ); + constructor( property, inputType, userData = null ) { - const tangentToNormalInSlice = cross( normalInSlice, sliceBitangent ); - const cosHorizons = vec2( dot( viewDir, tangentToNormalInSlice ), dot( viewDir, tangentToNormalInSlice.negate() ) ).toVar(); + super( property, inputType, userData ); - Loop( { end: STEPS, type: 'int', name: 'j', condition: '<' }, ( { j } ) => { + this.userData = userData; - const sampleViewOffset = sampleDir.xyz.mul( radiusToUse ).mul( sampleDir.w ).mul( pow( div( float( j ).add( 1.0 ), float( STEPS ) ), this.distanceExponent ) ); + } - // x + updateReference( state ) { - const sampleSceneUvDepthX = getSceneUvAndDepth( viewPosition.add( sampleViewOffset ) ); - const sampleSceneViewPositionX = getViewPosition( sampleSceneUvDepthX.xy, sampleSceneUvDepthX.z ); - const viewDeltaX = sampleSceneViewPositionX.sub( viewPosition ); + this.reference = this.userData !== null ? this.userData : state.object.userData; - If( abs( viewDeltaX.z ).lessThan( this.thickness ), () => { + return this.reference; - const sampleCosHorizon = dot( viewDir, normalize( viewDeltaX ) ); - cosHorizons.x.addAssign( max$1( 0, mul( sampleCosHorizon.sub( cosHorizons.x ), mix( 1.0, float( 2.0 ).div( float( j ).add( 2 ) ), this.distanceFallOff ) ) ) ); + } - } ); +} - // y +const userData = ( name, inputType, userData ) => nodeObject( new UserDataNode( name, inputType, userData ) ); - const sampleSceneUvDepthY = getSceneUvAndDepth( viewPosition.sub( sampleViewOffset ) ); - const sampleSceneViewPositionY = getViewPosition( sampleSceneUvDepthY.xy, sampleSceneUvDepthY.z ); - const viewDeltaY = sampleSceneViewPositionY.sub( viewPosition ); +class PosterizeNode extends TempNode { - If( abs( viewDeltaY.z ).lessThan( this.thickness ), () => { + static get type() { - const sampleCosHorizon = dot( viewDir, normalize( viewDeltaY ) ); - cosHorizons.y.addAssign( max$1( 0, mul( sampleCosHorizon.sub( cosHorizons.y ), mix( 1.0, float( 2.0 ).div( float( j ).add( 2 ) ), this.distanceFallOff ) ) ) ); + return 'PosterizeNode'; - } ); + } - } ); + constructor( sourceNode, stepsNode ) { - const sinHorizons = sqrt( sub( 1.0, cosHorizons.mul( cosHorizons ) ) ); - const nx = dot( normalInSlice, sliceTangent ); - const ny = dot( normalInSlice, viewDir ); - const nxb = mul( 0.5, acos( cosHorizons.y ).sub( acos( cosHorizons.x ) ).add( sinHorizons.x.mul( cosHorizons.x ).sub( sinHorizons.y.mul( cosHorizons.y ) ) ) ); - const nyb = mul( 0.5, sub( 2.0, cosHorizons.x.mul( cosHorizons.x ) ).sub( cosHorizons.y.mul( cosHorizons.y ) ) ); - const occlusion = nx.mul( nxb ).add( ny.mul( nyb ) ); - ao.addAssign( occlusion ); + super(); - } ); + this.sourceNode = sourceNode; + this.stepsNode = stepsNode; - ao.assign( clamp( ao.div( DIRECTIONS ), 0, 1 ) ); - ao.assign( pow( ao, this.scale ) ); + } - return vec4( vec3( ao ), 1.0 ); + setup() { - } ); + const { sourceNode, stepsNode } = this; - const material = this._material || ( this._material = new NodeMaterial() ); - material.fragmentNode = ao().context( builder.getSharedContext() ); - material.name = 'GTAO'; - material.needsUpdate = true; + return sourceNode.mul( stepsNode ).floor().div( stepsNode ); - // + } - return this._textureNode; +} - } +const posterize = /*@__PURE__*/ nodeProxy( PosterizeNode ); - dispose() { +let _sharedFramebuffer = null; - this._aoRenderTarget.dispose(); +class ViewportSharedTextureNode extends ViewportTextureNode { - } + static get type() { -} + return 'ViewportSharedTextureNode'; -GTAONode.type = /*@__PURE__*/ registerNode( 'GTAO', GTAONode ); + } -function generateMagicSquareNoise( size = 5 ) { + constructor( uvNode = screenUV, levelNode = null ) { - const noiseSize = Math.floor( size ) % 2 === 0 ? Math.floor( size ) + 1 : Math.floor( size ); - const magicSquare = generateMagicSquare( noiseSize ); - const noiseSquareSize = magicSquare.length; - const data = new Uint8Array( noiseSquareSize * 4 ); + if ( _sharedFramebuffer === null ) { - for ( let inx = 0; inx < noiseSquareSize; ++ inx ) { + _sharedFramebuffer = new FramebufferTexture(); - const iAng = magicSquare[ inx ]; - const angle = ( 2 * Math.PI * iAng ) / noiseSquareSize; - const randomVec = new Vector3( - Math.cos( angle ), - Math.sin( angle ), - 0 - ).normalize(); - data[ inx * 4 ] = ( randomVec.x * 0.5 + 0.5 ) * 255; - data[ inx * 4 + 1 ] = ( randomVec.y * 0.5 + 0.5 ) * 255; - data[ inx * 4 + 2 ] = 127; - data[ inx * 4 + 3 ] = 255; + } + + super( uvNode, levelNode, _sharedFramebuffer ); } - const noiseTexture = new DataTexture( data, noiseSize, noiseSize ); - noiseTexture.wrapS = RepeatWrapping; - noiseTexture.wrapT = RepeatWrapping; - noiseTexture.needsUpdate = true; + updateReference() { - return noiseTexture; + return this; + + } } -function generateMagicSquare( size ) { +const viewportSharedTexture = /*@__PURE__*/ nodeProxy( ViewportSharedTextureNode ); - const noiseSize = Math.floor( size ) % 2 === 0 ? Math.floor( size ) + 1 : Math.floor( size ); - const noiseSquareSize = noiseSize * noiseSize; - const magicSquare = Array( noiseSquareSize ).fill( 0 ); - let i = Math.floor( noiseSize / 2 ); - let j = noiseSize - 1; +const _size$7 = /*@__PURE__*/ new Vector2(); - for ( let num = 1; num <= noiseSquareSize; ) { +class PassTextureNode extends TextureNode { - if ( i === - 1 && j === noiseSize ) { + static get type() { - j = noiseSize - 2; - i = 0; + return 'PassTextureNode'; - } else { + } - if ( j === noiseSize ) { + constructor( passNode, texture ) { - j = 0; + super( texture ); - } + this.passNode = passNode; - if ( i < 0 ) { + this.setUpdateMatrix( false ); - i = noiseSize - 1; + } - } + setup( builder ) { - } + if ( builder.object.isQuadMesh ) this.passNode.build( builder ); - if ( magicSquare[ i * noiseSize + j ] !== 0 ) { + return super.setup( builder ); - j -= 2; - i ++; - continue; + } - } else { + clone() { - magicSquare[ i * noiseSize + j ] = num ++; + return new this.constructor( this.passNode, this.value ); - } + } - j ++; - i --; +} + +class PassMultipleTextureNode extends PassTextureNode { + + static get type() { + + return 'PassMultipleTextureNode'; } - return magicSquare; + constructor( passNode, textureName, previousTexture = false ) { -} + super( passNode, null ); -const ao = ( depthNode, normalNode, camera ) => nodeObject( new GTAONode( nodeObject( depthNode ), nodeObject( normalNode ), camera ) ); + this.textureName = textureName; + this.previousTexture = previousTexture; -class DenoiseNode extends TempNode { + } - constructor( textureNode, depthNode, normalNode, noiseNode, camera ) { + updateTexture() { - super(); + this.value = this.previousTexture ? this.passNode.getPreviousTexture( this.textureName ) : this.passNode.getTexture( this.textureName ); - this.textureNode = textureNode; - this.depthNode = depthNode; - this.normalNode = normalNode; - this.noiseNode = noiseNode; + } - this.cameraProjectionMatrixInverse = uniform( camera.projectionMatrixInverse ); - this.lumaPhi = uniform( 5 ); - this.depthPhi = uniform( 5 ); - this.normalPhi = uniform( 5 ); - this.radius = uniform( 5 ); - this.index = uniform( 0 ); + setup( builder ) { - this._resolution = uniform( new Vector2() ); - this._sampleVectors = uniformArray( generatePdSamplePointInitializer( 16, 2, 1 ) ); + this.updateTexture(); - this.updateBeforeType = NodeUpdateType.RENDER; + return super.setup( builder ); } - updateBefore() { + clone() { - const map = this.textureNode.value; + return new this.constructor( this.passNode, this.textureName, this.previousTexture ); - this._resolution.value.set( map.image.width, map.image.height ); + } + +} + +class PassNode extends TempNode { + + static get type() { + + return 'PassNode'; } - setup() { + constructor( scope, scene, camera, options = {} ) { - const uvNode = uv(); + super( 'vec4' ); - const sampleTexture = ( uv ) => this.textureNode.uv( uv ); - const sampleDepth = ( uv ) => this.depthNode.uv( uv ).x; - const sampleNormal = ( uv ) => this.normalNode.uv( uv ); - const sampleNoise = ( uv ) => this.noiseNode.uv( uv ); + this.scope = scope; + this.scene = scene; + this.camera = camera; + this.options = options; - const getViewPosition = Fn( ( [ screenPosition, depth ] ) => { + this._pixelRatio = 1; + this._width = 1; + this._height = 1; - screenPosition = vec2( screenPosition.x, screenPosition.y.oneMinus() ).mul( 2.0 ).sub( 1.0 ); + const depthTexture = new DepthTexture(); + depthTexture.isRenderTargetTexture = true; + //depthTexture.type = FloatType; + depthTexture.name = 'depth'; - const clipSpacePosition = vec4( vec3( screenPosition, depth ), 1.0 ); - const viewSpacePosition = vec4( this.cameraProjectionMatrixInverse.mul( clipSpacePosition ) ); + const renderTarget = new RenderTarget( this._width * this._pixelRatio, this._height * this._pixelRatio, { type: HalfFloatType, ...options, } ); + renderTarget.texture.name = 'output'; + renderTarget.depthTexture = depthTexture; - return viewSpacePosition.xyz.div( viewSpacePosition.w ); + this.renderTarget = renderTarget; - } ); + this.updateBeforeType = NodeUpdateType.FRAME; - const denoiseSample = Fn( ( [ center, viewNormal, viewPosition, sampleUv ] ) => { + this._textures = { + output: renderTarget.texture, + depth: depthTexture + }; - const texel = sampleTexture( sampleUv ); - const depth = sampleDepth( sampleUv ); - const normal = sampleNormal( sampleUv ).rgb.normalize(); - const neighborColor = texel.rgb; - const viewPos = getViewPosition( sampleUv, depth ); + this._textureNodes = {}; + this._linearDepthNodes = {}; + this._viewZNodes = {}; - const normalDiff = dot( viewNormal, normal ).toVar(); - const normalSimilarity = pow( max$1( normalDiff, 0 ), this.normalPhi ).toVar(); - const lumaDiff = abs( luminance( neighborColor ).sub( luminance( center ) ) ).toVar(); - const lumaSimilarity = max$1( float( 1.0 ).sub( lumaDiff.div( this.lumaPhi ) ), 0 ).toVar(); - const depthDiff = abs( dot( viewPosition.sub( viewPos ), viewNormal ) ).toVar(); - const depthSimilarity = max$1( float( 1.0 ).sub( depthDiff.div( this.depthPhi ) ), 0 ); - const w = lumaSimilarity.mul( depthSimilarity ).mul( normalSimilarity ); + this._previousTextures = {}; + this._previousTextureNodes = {}; - return vec4( neighborColor.mul( w ), w ); + this._cameraNear = uniform( 0 ); + this._cameraFar = uniform( 0 ); - } ); + this._mrt = null; - const denoise = Fn( ( [ uvNode ] ) => { + this.isPassNode = true; - const depth = sampleDepth( uvNode ); - const viewNormal = sampleNormal( uvNode ).rgb.normalize(); + } - const texel = sampleTexture( uvNode ); + setMRT( mrt ) { - If( depth.greaterThanEqual( 1.0 ).or( dot( viewNormal, viewNormal ).equal( 0.0 ) ), () => { + this._mrt = mrt; - return texel; + return this; - } ); + } - const center = vec3( texel.rgb ); + getMRT() { - const viewPosition = getViewPosition( uvNode, depth ); + return this._mrt; - const noiseResolution = textureSize( this.noiseNode, 0 ); - let noiseUv = vec2( uvNode.x, uvNode.y.oneMinus() ); - noiseUv = noiseUv.mul( this._resolution.div( noiseResolution ) ); - const noiseTexel = sampleNoise( noiseUv ); + } - const x = sin( noiseTexel.element( this.index.mod( 4 ).mul( 2 ).mul( PI ) ) ); - const y = cos( noiseTexel.element( this.index.mod( 4 ).mul( 2 ).mul( PI ) ) ); + isGlobal() { - const noiseVec = vec2( x, y ); - const rotationMatrix = mat2( noiseVec.x, noiseVec.y.negate(), noiseVec.x, noiseVec.y ); + return true; - const totalWeight = float( 1.0 ).toVar(); - const denoised = vec3( texel.rgb ).toVar(); + } - Loop( { start: int( 0 ), end: int( 16 ), type: 'int', condition: '<' }, ( { i } ) => { + getTexture( name ) { - const sampleDir = this._sampleVectors.element( i ).toVar(); - const offset = rotationMatrix.mul( sampleDir.xy.mul( float( 1.0 ).add( sampleDir.z.mul( this.radius.sub( 1 ) ) ) ) ).div( this._resolution ).toVar(); - const sampleUv = uvNode.add( offset ).toVar(); + let texture = this._textures[ name ]; - const result = denoiseSample( center, viewNormal, viewPosition, sampleUv ); + if ( texture === undefined ) { - denoised.addAssign( result.xyz ); - totalWeight.addAssign( result.w ); + const refTexture = this.renderTarget.texture; - } ); + texture = refTexture.clone(); + texture.isRenderTargetTexture = true; + texture.name = name; - If( totalWeight.greaterThan( float( 0 ) ), () => { + this._textures[ name ] = texture; - denoised.divAssign( totalWeight ); + this.renderTarget.textures.push( texture ); - } ); + } - return vec4( denoised, texel.a ); + return texture; - } ).setLayout( { - name: 'denoise', - type: 'vec4', - inputs: [ - { name: 'uv', type: 'vec2' } - ] - } ); + } - const output = Fn( () => { + getPreviousTexture( name ) { - return denoise( uvNode ); + let texture = this._previousTextures[ name ]; - } ); + if ( texture === undefined ) { - const outputNode = output(); + texture = this.getTexture( name ).clone(); + texture.isRenderTargetTexture = true; - return outputNode; + this._previousTextures[ name ] = texture; + + } + + return texture; } -} + toggleTexture( name ) { -DenoiseNode.type = /*@__PURE__*/ registerNode( 'Denoise', DenoiseNode ); + const prevTexture = this._previousTextures[ name ]; -function generatePdSamplePointInitializer( samples, rings, radiusExponent ) { + if ( prevTexture !== undefined ) { - const poissonDisk = generateDenoiseSamples( samples, rings, radiusExponent ); + const texture = this._textures[ name ]; - const array = []; + const index = this.renderTarget.textures.indexOf( texture ); + this.renderTarget.textures[ index ] = prevTexture; - for ( let i = 0; i < samples; i ++ ) { + this._textures[ name ] = prevTexture; + this._previousTextures[ name ] = texture; - const sample = poissonDisk[ i ]; - array.push( sample ); + this._textureNodes[ name ].updateTexture(); + this._previousTextureNodes[ name ].updateTexture(); + + } } - return array; + getTextureNode( name = 'output' ) { -} + let textureNode = this._textureNodes[ name ]; -function generateDenoiseSamples( numSamples, numRings, radiusExponent ) { + if ( textureNode === undefined ) { - const samples = []; + this._textureNodes[ name ] = textureNode = nodeObject( new PassMultipleTextureNode( this, name ) ); + this._textureNodes[ name ].updateTexture(); - for ( let i = 0; i < numSamples; i ++ ) { + } - const angle = 2 * Math.PI * numRings * i / numSamples; - const radius = Math.pow( i / ( numSamples - 1 ), radiusExponent ); - samples.push( new Vector3( Math.cos( angle ), Math.sin( angle ), radius ) ); + return textureNode; } - return samples; + getPreviousTextureNode( name = 'output' ) { -} + let textureNode = this._previousTextureNodes[ name ]; -const denoise = ( node, depthNode, normalNode, noiseNode, camera ) => nodeObject( new DenoiseNode( convertToTexture( node ), nodeObject( depthNode ), nodeObject( normalNode ), nodeObject( noiseNode ), camera ) ); + if ( textureNode === undefined ) { -class FXAANode extends TempNode { + if ( this._textureNodes[ name ] === undefined ) this.getTextureNode( name ); - constructor( textureNode ) { + this._previousTextureNodes[ name ] = textureNode = nodeObject( new PassMultipleTextureNode( this, name, true ) ); + this._previousTextureNodes[ name ].updateTexture(); - super(); + } - this.textureNode = textureNode; + return textureNode; - this.updateBeforeType = NodeUpdateType.RENDER; + } - this._invSize = uniform( new Vector2() ); + getViewZNode( name = 'depth' ) { - } + let viewZNode = this._viewZNodes[ name ]; - updateBefore() { + if ( viewZNode === undefined ) { - const map = this.textureNode.value; + const cameraNear = this._cameraNear; + const cameraFar = this._cameraFar; - this._invSize.value.set( 1 / map.image.width, 1 / map.image.height ); + this._viewZNodes[ name ] = viewZNode = perspectiveDepthToViewZ( this.getTextureNode( name ), cameraNear, cameraFar ); + + } + + return viewZNode; } - setup() { + getLinearDepthNode( name = 'depth' ) { - const textureNode = this.textureNode.bias( - 100 ); - const uvNode = textureNode.uvNode || uv(); + let linearDepthNode = this._linearDepthNodes[ name ]; - // FXAA 3.11 implementation by NVIDIA, ported to WebGL by Agost Biro (biro@archilogic.com) + if ( linearDepthNode === undefined ) { - //---------------------------------------------------------------------------------- - // File: es3-kepler\FXAA\assets\shaders/FXAA_DefaultES.frag - // SDK Version: v3.00 - // Email: gameworks@nvidia.com - // Site: http://developer.nvidia.com/ - // - // Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. - // - // Redistribution and use in source and binary forms, with or without - // modification, are permitted provided that the following conditions - // are met: - // * Redistributions of source code must retain the above copyright - // notice, this list of conditions and the following disclaimer. - // * Redistributions in binary form must reproduce the above copyright - // notice, this list of conditions and the following disclaimer in the - // documentation and/or other materials provided with the distribution. - // * Neither the name of NVIDIA CORPORATION nor the names of its - // contributors may be used to endorse or promote products derived - // from this software without specific prior written permission. - // - // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY - // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR - // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, - // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, - // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR - // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY - // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - // - //---------------------------------------------------------------------------------- + const cameraNear = this._cameraNear; + const cameraFar = this._cameraFar; + const viewZNode = this.getViewZNode( name ); - const FxaaTexTop = ( p ) => textureNode.uv( p ); - const FxaaTexOff = ( p, o, r ) => textureNode.uv( p.add( o.mul( r ) ) ); + // TODO: just if ( builder.camera.isPerspectiveCamera ) - const NUM_SAMPLES = int( 5 ); + this._linearDepthNodes[ name ] = linearDepthNode = viewZToOrthographicDepth( viewZNode, cameraNear, cameraFar ); - const contrast = Fn( ( [ a_immutable, b_immutable ] ) => { + } - // assumes colors have premultipliedAlpha, so that the calculated color contrast is scaled by alpha + return linearDepthNode; - const b = vec4( b_immutable ).toVar(); - const a = vec4( a_immutable ).toVar(); - const diff = vec4( abs( a.sub( b ) ) ).toVar(); + } - return max$1( max$1( max$1( diff.r, diff.g ), diff.b ), diff.a ); + setup( { renderer } ) { - } ); + this.renderTarget.samples = this.options.samples === undefined ? renderer.samples : this.options.samples; - // FXAA3 QUALITY - PC + // Disable MSAA for WebGL backend for now + if ( renderer.backend.isWebGLBackend === true ) { - const FxaaPixelShader = Fn( ( [ uv, fxaaQualityRcpFrame, fxaaQualityEdgeThreshold, fxaaQualityinvEdgeThreshold ] ) => { + this.renderTarget.samples = 0; - const rgbaM = FxaaTexTop( uv ).toVar(); - const rgbaS = FxaaTexOff( uv, vec2( 0.0, - 1.0 ), fxaaQualityRcpFrame.xy ).toVar(); - const rgbaE = FxaaTexOff( uv, vec2( 1.0, 0.0 ), fxaaQualityRcpFrame.xy ).toVar(); - const rgbaN = FxaaTexOff( uv, vec2( 0.0, 1.0 ), fxaaQualityRcpFrame.xy ).toVar(); - const rgbaW = FxaaTexOff( uv, vec2( - 1.0, 0.0 ), fxaaQualityRcpFrame.xy ).toVar(); - // . S . - // W M E - // . N . + } - const contrastN = contrast( rgbaM, rgbaN ).toVar(); - const contrastS = contrast( rgbaM, rgbaS ).toVar(); - const contrastE = contrast( rgbaM, rgbaE ).toVar(); - const contrastW = contrast( rgbaM, rgbaW ).toVar(); + this.renderTarget.depthTexture.isMultisampleRenderTargetTexture = this.renderTarget.samples > 1; - const maxValue = max$1( contrastN, max$1( contrastS, max$1( contrastE, contrastW ) ) ).toVar(); + return this.scope === PassNode.COLOR ? this.getTextureNode() : this.getLinearDepthNode(); - // . 0 . - // 0 0 0 - // . 0 . + } - If( maxValue.lessThan( fxaaQualityEdgeThreshold ), () => { + updateBefore( frame ) { - return rgbaM; // assuming define FXAA_DISCARD is always 0 + const { renderer } = frame; + const { scene, camera } = this; - } ); + this._pixelRatio = renderer.getPixelRatio(); - // + const size = renderer.getSize( _size$7 ); - const relativeVContrast = sub( contrastN.add( contrastS ), ( contrastE.add( contrastW ) ) ).toVar(); - relativeVContrast.mulAssign( fxaaQualityinvEdgeThreshold ); + this.setSize( size.width, size.height ); - // 45 deg edge detection and corners of objects, aka V/H contrast is too similar + const currentRenderTarget = renderer.getRenderTarget(); + const currentMRT = renderer.getMRT(); - If( abs( relativeVContrast ).lessThan( 0.3 ), () => { + this._cameraNear.value = camera.near; + this._cameraFar.value = camera.far; - // locate the edge + for ( const name in this._previousTextures ) { - const x = contrastE.greaterThan( contrastW ).select( 1, - 1 ).toVar(); - const y = contrastS.greaterThan( contrastN ).select( 1, - 1 ).toVar(); + this.toggleTexture( name ); - const dirToEdge = vec2( x, y ).toVar(); - // . 2 . . 1 . - // 1 0 2 ~= 0 0 1 - // . 1 . . 0 . + } - // tap 2 pixels and see which ones are "outside" the edge, to - // determine if the edge is vertical or horizontal + renderer.setRenderTarget( this.renderTarget ); + renderer.setMRT( this._mrt ); - const rgbaAlongH = FxaaTexOff( uv, vec2( dirToEdge.x, dirToEdge.y ), fxaaQualityRcpFrame.xy ); - const matchAlongH = contrast( rgbaM, rgbaAlongH ).toVar(); - // . 1 . - // 0 0 1 - // . 0 H + renderer.render( scene, camera ); - const rgbaAlongV = FxaaTexOff( uv, vec2( dirToEdge.x.negate(), dirToEdge.y.negate() ), fxaaQualityRcpFrame.xy ); - const matchAlongV = contrast( rgbaM, rgbaAlongV ).toVar(); - // V 1 . - // 0 0 1 - // . 0 . + renderer.setRenderTarget( currentRenderTarget ); + renderer.setMRT( currentMRT ); - relativeVContrast.assign( matchAlongV.sub( matchAlongH ) ); - relativeVContrast.mulAssign( fxaaQualityinvEdgeThreshold ); + } - If( abs( relativeVContrast ).lessThan( 0.3 ), () => { // 45 deg edge + setSize( width, height ) { - // 1 1 . - // 0 0 1 - // . 0 1 + this._width = width; + this._height = height; - // do a simple blur - const sum = rgbaN.add( rgbaS ).add( rgbaE ).add( rgbaW ); - return mix( rgbaM, sum.mul( 0.25 ), 0.4 ); + const effectiveWidth = this._width * this._pixelRatio; + const effectiveHeight = this._height * this._pixelRatio; - } ); + this.renderTarget.setSize( effectiveWidth, effectiveHeight ); - } ); + } - const offNP = vec2().toVar(); + setPixelRatio( pixelRatio ) { - If( relativeVContrast.lessThanEqual( 0 ), () => { + this._pixelRatio = pixelRatio; - rgbaN.assign( rgbaW ); - rgbaS.assign( rgbaE ); + this.setSize( this._width, this._height ); - // . 0 . 1 - // 1 0 1 -> 0 - // . 0 . 1 + } - offNP.x.assign( 0 ); - offNP.y.assign( fxaaQualityRcpFrame.y ); + dispose() { - } ).Else( () => { + this.renderTarget.dispose(); - offNP.x.assign( fxaaQualityRcpFrame.x ); - offNP.y.assign( 0 ); + } - } ); - const mn = contrast( rgbaM, rgbaN ).toVar(); - const ms = contrast( rgbaM, rgbaS ).toVar(); +} - If( mn.lessThanEqual( ms ), () => { +PassNode.COLOR = 'color'; +PassNode.DEPTH = 'depth'; - rgbaN.assign( rgbaS ); +const pass = ( scene, camera, options ) => nodeObject( new PassNode( PassNode.COLOR, scene, camera, options ) ); +const passTexture = ( pass, texture ) => nodeObject( new PassTextureNode( pass, texture ) ); +const depthPass = ( scene, camera ) => nodeObject( new PassNode( PassNode.DEPTH, scene, camera ) ); - } ); +// WebGPU: The use of a single QuadMesh for both gaussian blur passes results in a single RenderObject with a SampledTexture binding that +// alternates between source textures and triggers creation of new BindGroups and BindGroupLayouts every frame. - const doneN = int( 0 ).toVar(); - const doneP = int( 0 ).toVar(); +const _quadMesh1 = /*@__PURE__*/ new QuadMesh(); +const _quadMesh2 = /*@__PURE__*/ new QuadMesh(); - const nDist = float( 0 ).toVar(); - const pDist = float( 0 ).toVar(); +class GaussianBlurNode extends TempNode { - const posN = vec2( uv ).toVar(); - const posP = vec2( uv ).toVar(); + static get type() { - const iterationsUsedN = int( 0 ).toVar(); - const iterationsUsedP = int( 0 ).toVar(); + return 'GaussianBlurNode'; - Loop( NUM_SAMPLES, ( { i } ) => { + } - const increment = i.add( 1 ).toVar(); + constructor( textureNode, directionNode = null, sigma = 2 ) { - If( doneN.equal( 0 ), () => { + super( 'vec4' ); - nDist.addAssign( increment ); - posN.assign( uv.add( offNP.mul( nDist ) ) ); - const rgbaEndN = FxaaTexTop( posN.xy ); + this.textureNode = textureNode; + this.directionNode = directionNode; + this.sigma = sigma; - const nm = contrast( rgbaEndN, rgbaM ).toVar(); - const nn = contrast( rgbaEndN, rgbaN ).toVar(); + this._invSize = uniform( new Vector2() ); + this._passDirection = uniform( new Vector2() ); - If( nm.greaterThan( nn ), () => { + this._horizontalRT = new RenderTarget(); + this._horizontalRT.texture.name = 'GaussianBlurNode.horizontal'; + this._verticalRT = new RenderTarget(); + this._verticalRT.texture.name = 'GaussianBlurNode.vertical'; - doneN.assign( 1 ); + this._textureNode = passTexture( this, this._verticalRT.texture ); - } ); + this.updateBeforeType = NodeUpdateType.RENDER; - iterationsUsedN.assign( i ); + this.resolution = new Vector2( 1, 1 ); - } ); + } - If( doneP.equal( 0 ), () => { + setSize( width, height ) { - pDist.addAssign( increment ); - posP.assign( uv.sub( offNP.mul( pDist ) ) ); - const rgbaEndP = FxaaTexTop( posP.xy ); + width = Math.max( Math.round( width * this.resolution.x ), 1 ); + height = Math.max( Math.round( height * this.resolution.y ), 1 ); - const pm = contrast( rgbaEndP, rgbaM ).toVar(); - const pn = contrast( rgbaEndP, rgbaN ).toVar(); + this._invSize.value.set( 1 / width, 1 / height ); + this._horizontalRT.setSize( width, height ); + this._verticalRT.setSize( width, height ); - If( pm.greaterThan( pn ), () => { + } - doneP.assign( 1 ); + updateBefore( frame ) { - } ); + const { renderer } = frame; - iterationsUsedP.assign( i ); + const textureNode = this.textureNode; + const map = textureNode.value; - } ); + const currentRenderTarget = renderer.getRenderTarget(); + const currentMRT = renderer.getMRT(); - If( doneN.equal( 1 ).or( doneP.equal( 1 ) ), () => { + const currentTexture = textureNode.value; - Break(); + _quadMesh1.material = this._material; + _quadMesh2.material = this._material; - } ); + this.setSize( map.image.width, map.image.height ); - } ); + const textureType = map.type; - If( doneN.equal( 0 ).and( doneP.equal( 0 ) ), () => { + this._horizontalRT.texture.type = textureType; + this._verticalRT.texture.type = textureType; - return rgbaM; // failed to find end of edge + // clear - } ); + renderer.setMRT( null ); - const distN = float( 1 ).toVar(); - const distP = float( 1 ).toVar(); + // horizontal - If( doneN.equal( 1 ), () => { + renderer.setRenderTarget( this._horizontalRT ); - distN.assign( float( iterationsUsedN ).div( float( NUM_SAMPLES.sub( 1 ) ) ) ); + this._passDirection.value.set( 1, 0 ); - } ); + _quadMesh1.render( renderer ); - If( doneP.equal( 1 ), () => { + // vertical - distP.assign( float( iterationsUsedP ).div( float( NUM_SAMPLES.sub( 1 ) ) ) ); + textureNode.value = this._horizontalRT.texture; + renderer.setRenderTarget( this._verticalRT ); - } ); + this._passDirection.value.set( 0, 1 ); - const dist = min$1( distN, distP ); + _quadMesh2.render( renderer ); - // hacky way of reduces blurriness of mostly diagonal edges - // but reduces AA quality - dist.assign( pow( dist, 0.5 ) ); - dist.assign( float( 1 ).sub( dist ) ); + // restore - return mix( rgbaM, rgbaN, dist.mul( 0.5 ) ); + renderer.setRenderTarget( currentRenderTarget ); + renderer.setMRT( currentMRT ); + textureNode.value = currentTexture; - } ).setLayout( { - name: 'FxaaPixelShader', - type: 'vec4', - inputs: [ - { name: 'uv', type: 'vec2' }, - { name: 'fxaaQualityRcpFrame', type: 'vec2' }, - { name: 'fxaaQualityEdgeThreshold', type: 'float' }, - { name: 'fxaaQualityinvEdgeThreshold', type: 'float' }, - ] - } ); + } - const fxaa = Fn( () => { + getTextureNode() { - const edgeDetectionQuality = float( 0.2 ); - const invEdgeDetectionQuality = float( 1 ).div( edgeDetectionQuality ); + return this._textureNode; - return FxaaPixelShader( uvNode, this._invSize, edgeDetectionQuality, invEdgeDetectionQuality ); + } - } ); + setup( builder ) { - const outputNode = fxaa(); + const textureNode = this.textureNode; - return outputNode; + if ( textureNode.isTextureNode !== true ) { - } + console.error( 'GaussianBlurNode requires a TextureNode.' ); -} + return vec4(); -FXAANode.type = /*@__PURE__*/ registerNode( 'FXAA', FXAANode ); + } -const fxaa = ( node ) => nodeObject( new FXAANode( convertToTexture( node ) ) ); + // -const _quadMesh$2 = /*@__PURE__*/ new QuadMesh(); + const uvNode = textureNode.uvNode || uv(); + const directionNode = vec2( this.directionNode || 1 ); -const _clearColor$1 = /*@__PURE__*/ new Color( 0, 0, 0 ); -const _currentClearColor = /*@__PURE__*/ new Color(); -const _size$4 = /*@__PURE__*/ new Vector2(); + const sampleTexture = ( uv ) => textureNode.uv( uv ); -const _BlurDirectionX = /*@__PURE__*/ new Vector2( 1.0, 0.0 ); -const _BlurDirectionY = /*@__PURE__*/ new Vector2( 0.0, 1.0 ); + const blur = Fn( () => { -class BloomNode extends TempNode { + const kernelSize = 3 + ( 2 * this.sigma ); + const gaussianCoefficients = this._getCoefficients( kernelSize ); - constructor( inputNode, strength = 1, radius = 0, threshold = 0 ) { + const invSize = this._invSize; + const direction = directionNode.mul( this._passDirection ); - super(); + const weightSum = float( gaussianCoefficients[ 0 ] ).toVar(); + const diffuseSum = vec4( sampleTexture( uvNode ).mul( weightSum ) ).toVar(); - this.inputNode = inputNode; - this.strength = uniform( strength ); - this.radius = uniform( radius ); - this.threshold = uniform( threshold ); + for ( let i = 1; i < kernelSize; i ++ ) { - this.smoothWidth = uniform( 0.01 ); + const x = float( i ); + const w = float( gaussianCoefficients[ i ] ); - // + const uvOffset = vec2( direction.mul( invSize.mul( x ) ) ).toVar(); - this._renderTargetsHorizontal = []; - this._renderTargetsVertical = []; - this._nMips = 5; + const sample1 = vec4( sampleTexture( uvNode.add( uvOffset ) ) ); + const sample2 = vec4( sampleTexture( uvNode.sub( uvOffset ) ) ); - // render targets + diffuseSum.addAssign( sample1.add( sample2 ).mul( w ) ); + weightSum.addAssign( mul( 2.0, w ) ); - this._renderTargetBright = new RenderTarget( 1, 1, { type: HalfFloatType } ); - this._renderTargetBright.texture.name = 'UnrealBloomPass.bright'; - this._renderTargetBright.texture.generateMipmaps = false; + } - for ( let i = 0; i < this._nMips; i ++ ) { + return diffuseSum.div( weightSum ); - const renderTargetHorizontal = new RenderTarget( 1, 1, { type: HalfFloatType } ); + } ); - renderTargetHorizontal.texture.name = 'UnrealBloomPass.h' + i; - renderTargetHorizontal.texture.generateMipmaps = false; + // - this._renderTargetsHorizontal.push( renderTargetHorizontal ); + const material = this._material || ( this._material = new NodeMaterial() ); + material.fragmentNode = blur().context( builder.getSharedContext() ); + material.name = 'Gaussian_blur'; + material.needsUpdate = true; - const renderTargetVertical = new RenderTarget( 1, 1, { type: HalfFloatType } ); + // - renderTargetVertical.texture.name = 'UnrealBloomPass.v' + i; - renderTargetVertical.texture.generateMipmaps = false; + const properties = builder.getNodeProperties( this ); + properties.textureNode = textureNode; - this._renderTargetsVertical.push( renderTargetVertical ); + // - } + return this._textureNode; - // materials + } - this._compositeMaterial = null; - this._highPassFilterMaterial = null; - this._separableBlurMaterials = []; + dispose() { - // pass and texture nodes + this._horizontalRT.dispose(); + this._verticalRT.dispose(); - this._textureNodeBright = texture( this._renderTargetBright.texture ); - this._textureNodeBlur0 = texture( this._renderTargetsVertical[ 0 ].texture ); - this._textureNodeBlur1 = texture( this._renderTargetsVertical[ 1 ].texture ); - this._textureNodeBlur2 = texture( this._renderTargetsVertical[ 2 ].texture ); - this._textureNodeBlur3 = texture( this._renderTargetsVertical[ 3 ].texture ); - this._textureNodeBlur4 = texture( this._renderTargetsVertical[ 4 ].texture ); + } - this._textureOutput = passTexture( this, this._renderTargetsHorizontal[ 0 ].texture ); + _getCoefficients( kernelRadius ) { - this.updateBeforeType = NodeUpdateType.FRAME; + const coefficients = []; - } + for ( let i = 0; i < kernelRadius; i ++ ) { - getTextureNode() { + coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius ); - return this._textureOutput; + } - } + return coefficients; - setSize( width, height ) { + } - let resx = Math.round( width / 2 ); - let resy = Math.round( height / 2 ); +} - this._renderTargetBright.setSize( resx, resy ); +const gaussianBlur = ( node, directionNode, sigma ) => nodeObject( new GaussianBlurNode( convertToTexture( node ), directionNode, sigma ) ); - for ( let i = 0; i < this._nMips; i ++ ) { +const _size$6 = /*@__PURE__*/ new Vector2(); - this._renderTargetsHorizontal[ i ].setSize( resx, resy ); - this._renderTargetsVertical[ i ].setSize( resx, resy ); +const _quadMeshComp = /*@__PURE__*/ new QuadMesh(); - this._separableBlurMaterials[ i ].invSize.value.set( 1 / resx, 1 / resy ); +class AfterImageNode extends TempNode { - resx = Math.round( resx / 2 ); - resy = Math.round( resy / 2 ); + static get type() { - } + return 'AfterImageNode'; } - updateBefore( frame ) { - - const { renderer } = frame; + constructor( textureNode, damp = 0.96 ) { - const size = renderer.getDrawingBufferSize( _size$4 ); - this.setSize( size.width, size.height ); + super( textureNode ); - const currentRenderTarget = renderer.getRenderTarget(); - const currentMRT = renderer.getMRT(); - renderer.getClearColor( _currentClearColor ); - const currentClearAlpha = renderer.getClearAlpha(); + this.textureNode = textureNode; + this.textureNodeOld = texture(); + this.damp = uniform( damp ); - this.setSize( size.width, size.height ); + this._compRT = new RenderTarget(); + this._compRT.texture.name = 'AfterImageNode.comp'; - renderer.setMRT( null ); - renderer.setClearColor( _clearColor$1, 0 ); + this._oldRT = new RenderTarget(); + this._oldRT.texture.name = 'AfterImageNode.old'; - // 1. Extract Bright Areas + this._textureNode = passTexture( this, this._compRT.texture ); - renderer.setRenderTarget( this._renderTargetBright ); - _quadMesh$2.material = this._highPassFilterMaterial; - _quadMesh$2.render( renderer ); + this.updateBeforeType = NodeUpdateType.RENDER; - // 2. Blur All the mips progressively + } - let inputRenderTarget = this._renderTargetBright; + getTextureNode() { - for ( let i = 0; i < this._nMips; i ++ ) { + return this._textureNode; - _quadMesh$2.material = this._separableBlurMaterials[ i ]; + } - this._separableBlurMaterials[ i ].colorTexture.value = inputRenderTarget.texture; - this._separableBlurMaterials[ i ].direction.value = _BlurDirectionX; - renderer.setRenderTarget( this._renderTargetsHorizontal[ i ] ); - renderer.clear(); - _quadMesh$2.render( renderer ); + setSize( width, height ) { - this._separableBlurMaterials[ i ].colorTexture.value = this._renderTargetsHorizontal[ i ].texture; - this._separableBlurMaterials[ i ].direction.value = _BlurDirectionY; - renderer.setRenderTarget( this._renderTargetsVertical[ i ] ); - renderer.clear(); - _quadMesh$2.render( renderer ); + this._compRT.setSize( width, height ); + this._oldRT.setSize( width, height ); - inputRenderTarget = this._renderTargetsVertical[ i ]; + } - } + updateBefore( frame ) { - // 3. Composite All the mips + const { renderer } = frame; - renderer.setRenderTarget( this._renderTargetsHorizontal[ 0 ] ); - renderer.clear(); - _quadMesh$2.material = this._compositeMaterial; - _quadMesh$2.render( renderer ); + const textureNode = this.textureNode; + const map = textureNode.value; - // restore + const textureType = map.type; - renderer.setRenderTarget( currentRenderTarget ); - renderer.setMRT( currentMRT ); - renderer.setClearColor( _currentClearColor, currentClearAlpha ); + this._compRT.texture.type = textureType; + this._oldRT.texture.type = textureType; - } + renderer.getDrawingBufferSize( _size$6 ); - setup( builder ) { + this.setSize( _size$6.x, _size$6.y ); - // luminosity high pass material + const currentRenderTarget = renderer.getRenderTarget(); + const currentTexture = textureNode.value; - const luminosityHighPass = Fn( () => { + this.textureNodeOld.value = this._oldRT.texture; - const texel = this.inputNode; - const v = luminance( texel.rgb ); + // comp + renderer.setRenderTarget( this._compRT ); + _quadMeshComp.render( renderer ); - const alpha = smoothstep( this.threshold, this.threshold.add( this.smoothWidth ), v ); + // Swap the textures + const temp = this._oldRT; + this._oldRT = this._compRT; + this._compRT = temp; - return mix( vec4( 0 ), texel, alpha ); + renderer.setRenderTarget( currentRenderTarget ); + textureNode.value = currentTexture; - } ); + } - this._highPassFilterMaterial = this._highPassFilterMaterial || new NodeMaterial(); - this._highPassFilterMaterial.fragmentNode = luminosityHighPass().context( builder.getSharedContext() ); - this._highPassFilterMaterial.name = 'Bloom_highPass'; - this._highPassFilterMaterial.needsUpdate = true; + setup( builder ) { - // gaussian blur materials + const textureNode = this.textureNode; + const textureNodeOld = this.textureNodeOld; - const kernelSizeArray = [ 3, 5, 7, 9, 11 ]; + // - for ( let i = 0; i < this._nMips; i ++ ) { + const uvNode = textureNode.uvNode || uv(); - this._separableBlurMaterials.push( this._getSeperableBlurMaterial( builder, kernelSizeArray[ i ] ) ); + textureNodeOld.uvNode = uvNode; - } + const sampleTexture = ( uv ) => textureNode.uv( uv ); - // composite material + const when_gt = Fn( ( [ x_immutable, y_immutable ] ) => { - const bloomFactors = uniformArray( [ 1.0, 0.8, 0.6, 0.4, 0.2 ] ); - const bloomTintColors = uniformArray( [ new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ) ] ); - - const lerpBloomFactor = Fn( ( [ factor, radius ] ) => { + const y = float( y_immutable ).toVar(); + const x = vec4( x_immutable ).toVar(); - const mirrorFactor = float( 1.2 ).sub( factor ); - return mix( factor, mirrorFactor, radius ); + return max$1( sign( x.sub( y ) ), 0.0 ); - } ).setLayout( { - name: 'lerpBloomFactor', - type: 'float', - inputs: [ - { name: 'factor', type: 'float' }, - { name: 'radius', type: 'float' }, - ] } ); + const afterImg = Fn( () => { - const compositePass = Fn( () => { + const texelOld = vec4( textureNodeOld ); + const texelNew = vec4( sampleTexture( uvNode ) ); - const color0 = lerpBloomFactor( bloomFactors.element( 0 ), this.radius ).mul( vec4( bloomTintColors.element( 0 ), 1.0 ) ).mul( this._textureNodeBlur0 ); - const color1 = lerpBloomFactor( bloomFactors.element( 1 ), this.radius ).mul( vec4( bloomTintColors.element( 1 ), 1.0 ) ).mul( this._textureNodeBlur1 ); - const color2 = lerpBloomFactor( bloomFactors.element( 2 ), this.radius ).mul( vec4( bloomTintColors.element( 2 ), 1.0 ) ).mul( this._textureNodeBlur2 ); - const color3 = lerpBloomFactor( bloomFactors.element( 3 ), this.radius ).mul( vec4( bloomTintColors.element( 3 ), 1.0 ) ).mul( this._textureNodeBlur3 ); - const color4 = lerpBloomFactor( bloomFactors.element( 4 ), this.radius ).mul( vec4( bloomTintColors.element( 4 ), 1.0 ) ).mul( this._textureNodeBlur4 ); + texelOld.mulAssign( this.damp.mul( when_gt( texelOld, 0.1 ) ) ); + return max$1( texelNew, texelOld ); - const sum = color0.add( color1 ).add( color2 ).add( color3 ).add( color4 ); + } ); - return sum.mul( this.strength ); + // - } ); + const materialComposed = this._materialComposed || ( this._materialComposed = new NodeMaterial() ); + materialComposed.name = 'AfterImage'; + materialComposed.fragmentNode = afterImg(); - this._compositeMaterial = this._compositeMaterial || new NodeMaterial(); - this._compositeMaterial.fragmentNode = compositePass().context( builder.getSharedContext() ); - this._compositeMaterial.name = 'Bloom_comp'; - this._compositeMaterial.needsUpdate = true; + _quadMeshComp.material = materialComposed; // - return this._textureOutput; + const properties = builder.getNodeProperties( this ); + properties.textureNode = textureNode; + + // + + return this._textureNode; } dispose() { - for ( let i = 0; i < this._renderTargetsHorizontal.length; i ++ ) { + this._compRT.dispose(); + this._oldRT.dispose(); - this._renderTargetsHorizontal[ i ].dispose(); + } - } +} - for ( let i = 0; i < this._renderTargetsVertical.length; i ++ ) { +const afterImage = ( node, damp ) => nodeObject( new AfterImageNode( convertToTexture( node ), damp ) ); - this._renderTargetsVertical[ i ].dispose(); +const grayscale = /*@__PURE__*/ Fn( ( [ color ] ) => { - } + return luminance( color.rgb ); - this._renderTargetBright.dispose(); +} ); - } +const saturation = /*@__PURE__*/ Fn( ( [ color, adjustment = float( 1 ) ] ) => { - _getSeperableBlurMaterial( builder, kernelRadius ) { + return adjustment.mix( luminance( color.rgb ), color.rgb ); - const coefficients = []; +} ); - for ( let i = 0; i < kernelRadius; i ++ ) { +const vibrance = /*@__PURE__*/ Fn( ( [ color, adjustment = float( 1 ) ] ) => { - coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius ); + const average = add( color.r, color.g, color.b ).div( 3.0 ); - } + const mx = color.r.max( color.g.max( color.b ) ); + const amt = mx.sub( average ).mul( adjustment ).mul( - 3.0 ); - // + return mix( color.rgb, mx, amt ); - const colorTexture = texture(); - const gaussianCoefficients = uniformArray( coefficients ); - const invSize = uniform( new Vector2() ); - const direction = uniform( new Vector2( 0.5, 0.5 ) ); +} ); - const uvNode = uv(); - const sampleTexel = ( uv ) => colorTexture.uv( uv ); +const hue = /*@__PURE__*/ Fn( ( [ color, adjustment = float( 1 ) ] ) => { - const seperableBlurPass = Fn( () => { + const k = vec3( 0.57735, 0.57735, 0.57735 ); - const weightSum = gaussianCoefficients.element( 0 ).toVar(); - const diffuseSum = sampleTexel( uvNode ).rgb.mul( weightSum ).toVar(); + const cosAngle = adjustment.cos(); - Loop( { start: int( 1 ), end: int( kernelRadius ), type: 'int', condition: '<' }, ( { i } ) => { + return vec3( color.rgb.mul( cosAngle ).add( k.cross( color.rgb ).mul( adjustment.sin() ).add( k.mul( dot( k, color.rgb ).mul( cosAngle.oneMinus() ) ) ) ) ); - const x = float( i ); - const w = gaussianCoefficients.element( i ); - const uvOffset = direction.mul( invSize ).mul( x ); - const sample1 = sampleTexel( uvNode.add( uvOffset ) ).rgb; - const sample2 = sampleTexel( uvNode.sub( uvOffset ) ).rgb; - diffuseSum.addAssign( add( sample1, sample2 ).mul( w ) ); - weightSum.addAssign( float( 2.0 ).mul( w ) ); +} ); - } ); +const _luminanceCoefficients = /*@__PURE__*/ new Vector3(); +const luminance = ( + color, + luminanceCoefficients = vec3( ... ColorManagement.getLuminanceCoefficients( _luminanceCoefficients ) ) +) => dot( color, luminanceCoefficients ); - return vec4( diffuseSum.div( weightSum ), 1.0 ); +const threshold = ( color, threshold ) => mix( vec3( 0.0 ), color, luminance( color ).sub( threshold ).max( 0 ) ); - } ); +const _quadMesh$5 = /*@__PURE__*/ new QuadMesh(); - const seperableBlurMaterial = new NodeMaterial(); - seperableBlurMaterial.fragmentNode = seperableBlurPass().context( builder.getSharedContext() ); - seperableBlurMaterial.name = 'Bloom_seperable'; - seperableBlurMaterial.needsUpdate = true; +class AnamorphicNode extends TempNode { - // uniforms - seperableBlurMaterial.colorTexture = colorTexture; - seperableBlurMaterial.direction = direction; - seperableBlurMaterial.invSize = invSize; + static get type() { - return seperableBlurMaterial; + return 'AnamorphicNode'; } -} + constructor( textureNode, tresholdNode, scaleNode, samples ) { -const bloom = ( node, strength, radius, threshold ) => nodeObject( new BloomNode( nodeObject( node ), strength, radius, threshold ) ); + super( 'vec4' ); -class TransitionNode extends TempNode { + this.textureNode = textureNode; + this.tresholdNode = tresholdNode; + this.scaleNode = scaleNode; + this.colorNode = vec3( 0.1, 0.0, 1.0 ); + this.samples = samples; + this.resolution = new Vector2( 1, 1 ); - constructor( textureNodeA, textureNodeB, mixTextureNode, mixRatioNode, thresholdNode, useTextureNode ) { + this._renderTarget = new RenderTarget(); + this._renderTarget.texture.name = 'anamorphic'; - super(); + this._invSize = uniform( new Vector2() ); - // Input textures + this._textureNode = passTexture( this, this._renderTarget.texture ); - this.textureNodeA = textureNodeA; - this.textureNodeB = textureNodeB; - this.mixTextureNode = mixTextureNode; + this.updateBeforeType = NodeUpdateType.RENDER; - // Uniforms + } - this.mixRatioNode = mixRatioNode; - this.thresholdNode = thresholdNode; - this.useTextureNode = useTextureNode; + getTextureNode() { - } + return this._textureNode; - setup() { + } - const { textureNodeA, textureNodeB, mixTextureNode, mixRatioNode, thresholdNode, useTextureNode } = this; + setSize( width, height ) { - const sampleTexture = ( textureNode ) => { + this._invSize.value.set( 1 / width, 1 / height ); - const uvNodeTexture = textureNode.uvNode || uv(); - return textureNode.uv( uvNodeTexture ); + width = Math.max( Math.round( width * this.resolution.x ), 1 ); + height = Math.max( Math.round( height * this.resolution.y ), 1 ); - }; + this._renderTarget.setSize( width, height ); - const transition = Fn( () => { + } - const texelOne = sampleTexture( textureNodeA ); - const texelTwo = sampleTexture( textureNodeB ); + updateBefore( frame ) { - const color = vec4().toVar(); + const { renderer } = frame; - If( useTextureNode.equal( int( 1 ) ), () => { + const textureNode = this.textureNode; + const map = textureNode.value; - const transitionTexel = sampleTexture( mixTextureNode ); - const r = mixRatioNode.mul( thresholdNode.mul( 2.0 ).add( 1.0 ) ).sub( thresholdNode ); - const mixf = clamp( sub( transitionTexel.r, r ).mul( float( 1.0 ).div( thresholdNode ) ), 0.0, 1.0 ); + this._renderTarget.texture.type = map.type; - color.assign( mix( texelOne, texelTwo, mixf ) ); + const currentRenderTarget = renderer.getRenderTarget(); + const currentTexture = textureNode.value; - } ).Else( () => { + _quadMesh$5.material = this._material; - color.assign( mix( texelTwo, texelOne, mixRatioNode ) ); + this.setSize( map.image.width, map.image.height ); - } ); + // render - return color; + renderer.setRenderTarget( this._renderTarget ); - } ); + _quadMesh$5.render( renderer ); - const outputNode = transition(); + // restore - return outputNode; + renderer.setRenderTarget( currentRenderTarget ); + textureNode.value = currentTexture; } -} + setup( builder ) { -TransitionNode.type = /*@__PURE__*/ registerNode( 'Transition', TransitionNode ); + const textureNode = this.textureNode; + const uvNode = textureNode.uvNode || uv(); -const transition = ( nodeA, nodeB, mixTexture, mixRatio = 0.0, threshold = 0.1, useTexture = 0 ) => nodeObject( new TransitionNode( convertToTexture( nodeA ), convertToTexture( nodeB ), convertToTexture( mixTexture ), nodeObject( mixRatio ), nodeObject( threshold ), nodeObject( useTexture ) ) ); + const sampleTexture = ( uv ) => textureNode.uv( uv ); -class PixelationNode extends TempNode { + const anamorph = Fn( () => { - constructor( textureNode, depthNode, normalNode, pixelSize, normalEdgeStrength, depthEdgeStrength ) { + const samples = this.samples; + const halfSamples = Math.floor( samples / 2 ); - super(); + const total = vec3( 0 ).toVar(); - // Input textures + Loop( { start: - halfSamples, end: halfSamples }, ( { i } ) => { - this.textureNode = textureNode; - this.depthNode = depthNode; - this.normalNode = normalNode; + const softness = float( i ).abs().div( halfSamples ).oneMinus(); - // Input uniforms + const uv = vec2( uvNode.x.add( this._invSize.x.mul( i ).mul( this.scaleNode ) ), uvNode.y ); + const color = sampleTexture( uv ); + const pass = threshold( color, this.tresholdNode ).mul( softness ); - this.pixelSize = pixelSize; - this.normalEdgeStrength = normalEdgeStrength; - this.depthEdgeStrength = depthEdgeStrength; + total.addAssign( pass ); - // Private uniforms + } ); - this._resolution = uniform( new Vector4() ); + return total.mul( this.colorNode ); - this.updateBeforeType = NodeUpdateType.RENDER; + } ); - } + // - updateBefore() { + const material = this._material || ( this._material = new NodeMaterial() ); + material.name = 'Anamorphic'; + material.fragmentNode = anamorph(); - const map = this.textureNode.value; + // - const width = map.image.width; - const height = map.image.height; + const properties = builder.getNodeProperties( this ); + properties.textureNode = textureNode; - this._resolution.value.set( width, height, 1 / width, 1 / height ); + // + + return this._textureNode; } - setup() { + dispose() { - const { textureNode, depthNode, normalNode } = this; + this._renderTarget.dispose(); - const uvNodeTexture = textureNode.uvNode || uv(); - const uvNodeDepth = depthNode.uvNode || uv(); - const uvNodeNormal = normalNode.uvNode || uv(); + } - const sampleTexture = () => textureNode.uv( uvNodeTexture ); +} - const sampleDepth = ( x, y ) => depthNode.uv( uvNodeDepth.add( vec2( x, y ).mul( this._resolution.zw ) ) ).r; +const anamorphic = ( node, threshold = .9, scale = 3, samples = 32 ) => nodeObject( new AnamorphicNode( convertToTexture( node ), nodeObject( threshold ), nodeObject( scale ), samples ) ); - const sampleNormal = ( x, y ) => normalNode.uv( uvNodeNormal.add( vec2( x, y ).mul( this._resolution.zw ) ) ).rgb.normalize(); +class SobelOperatorNode extends TempNode { - const depthEdgeIndicator = ( depth ) => { + static get type() { - const diff = property( 'float', 'diff' ); - diff.addAssign( clamp( sampleDepth( 1, 0 ).sub( depth ) ) ); - diff.addAssign( clamp( sampleDepth( - 1, 0 ).sub( depth ) ) ); - diff.addAssign( clamp( sampleDepth( 0, 1 ).sub( depth ) ) ); - diff.addAssign( clamp( sampleDepth( 0, - 1 ).sub( depth ) ) ); + return 'SobelOperatorNode'; - return floor( smoothstep( 0.01, 0.02, diff ).mul( 2 ) ).div( 2 ); + } - }; + constructor( textureNode ) { - const neighborNormalEdgeIndicator = ( x, y, depth, normal ) => { + super(); - const depthDiff = sampleDepth( x, y ).sub( depth ); - const neighborNormal = sampleNormal( x, y ); + this.textureNode = textureNode; - // Edge pixels should yield to faces who's normals are closer to the bias normal. + this.updateBeforeType = NodeUpdateType.RENDER; - const normalEdgeBias = vec3( 1, 1, 1 ); // This should probably be a parameter. - const normalDiff = dot( normal.sub( neighborNormal ), normalEdgeBias ); - const normalIndicator = clamp( smoothstep( - 0.01, 0.01, normalDiff ), 0.0, 1.0 ); + this._invSize = uniform( new Vector2() ); - // Only the shallower pixel should detect the normal edge. + } - const depthIndicator = clamp( sign( depthDiff.mul( .25 ).add( .0025 ) ), 0.0, 1.0 ); + updateBefore() { - return float( 1.0 ).sub( dot( normal, neighborNormal ) ).mul( depthIndicator ).mul( normalIndicator ); + const map = this.textureNode.value; - }; + this._invSize.value.set( 1 / map.image.width, 1 / map.image.height ); - const normalEdgeIndicator = ( depth, normal ) => { + } - const indicator = property( 'float', 'indicator' ); + setup() { - indicator.addAssign( neighborNormalEdgeIndicator( 0, - 1, depth, normal ) ); - indicator.addAssign( neighborNormalEdgeIndicator( 0, 1, depth, normal ) ); - indicator.addAssign( neighborNormalEdgeIndicator( - 1, 0, depth, normal ) ); - indicator.addAssign( neighborNormalEdgeIndicator( 1, 0, depth, normal ) ); + const { textureNode } = this; - return step( 0.1, indicator ); + const uvNode = textureNode.uvNode || uv(); - }; + const sampleTexture = ( uv ) => textureNode.uv( uv ); - const pixelation = Fn( () => { + const sobel = Fn( () => { - const texel = sampleTexture(); + // Sobel Edge Detection (see https://youtu.be/uihBwtPIBxM) - const depth = property( 'float', 'depth' ); - const normal = property( 'vec3', 'normal' ); + const texel = this._invSize; - If( this.depthEdgeStrength.greaterThan( 0.0 ).or( this.normalEdgeStrength.greaterThan( 0.0 ) ), () => { + // kernel definition (in glsl matrices are filled in column-major order) - depth.assign( sampleDepth( 0, 0 ) ); - normal.assign( sampleNormal( 0, 0 ) ); + const Gx = mat3( - 1, - 2, - 1, 0, 0, 0, 1, 2, 1 ); // x direction kernel + const Gy = mat3( - 1, 0, 1, - 2, 0, 2, - 1, 0, 1 ); // y direction kernel - } ); + // fetch the 3x3 neighbourhood of a fragment - const dei = property( 'float', 'dei' ); + // first column - If( this.depthEdgeStrength.greaterThan( 0.0 ), () => { + const tx0y0 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( - 1, - 1 ) ) ) ).xyz ); + const tx0y1 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( - 1, 0 ) ) ) ).xyz ); + const tx0y2 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( - 1, 1 ) ) ) ).xyz ); - dei.assign( depthEdgeIndicator( depth ) ); + // second column - } ); + const tx1y0 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 0, - 1 ) ) ) ).xyz ); + const tx1y1 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 0, 0 ) ) ) ).xyz ); + const tx1y2 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 0, 1 ) ) ) ).xyz ); - const nei = property( 'float', 'nei' ); + // third column - If( this.normalEdgeStrength.greaterThan( 0.0 ), () => { + const tx2y0 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 1, - 1 ) ) ) ).xyz ); + const tx2y1 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 1, 0 ) ) ) ).xyz ); + const tx2y2 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 1, 1 ) ) ) ).xyz ); - nei.assign( normalEdgeIndicator( depth, normal ) ); + // gradient value in x direction - } ); + const valueGx = add( + Gx[ 0 ][ 0 ].mul( tx0y0 ), + Gx[ 1 ][ 0 ].mul( tx1y0 ), + Gx[ 2 ][ 0 ].mul( tx2y0 ), + Gx[ 0 ][ 1 ].mul( tx0y1 ), + Gx[ 1 ][ 1 ].mul( tx1y1 ), + Gx[ 2 ][ 1 ].mul( tx2y1 ), + Gx[ 0 ][ 2 ].mul( tx0y2 ), + Gx[ 1 ][ 2 ].mul( tx1y2 ), + Gx[ 2 ][ 2 ].mul( tx2y2 ) + ); - const strength = dei.greaterThan( 0 ).select( float( 1.0 ).sub( dei.mul( this.depthEdgeStrength ) ), nei.mul( this.normalEdgeStrength ).add( 1 ) ); - return texel.mul( strength ); + // gradient value in y direction + + const valueGy = add( + Gy[ 0 ][ 0 ].mul( tx0y0 ), + Gy[ 1 ][ 0 ].mul( tx1y0 ), + Gy[ 2 ][ 0 ].mul( tx2y0 ), + Gy[ 0 ][ 1 ].mul( tx0y1 ), + Gy[ 1 ][ 1 ].mul( tx1y1 ), + Gy[ 2 ][ 1 ].mul( tx2y1 ), + Gy[ 0 ][ 2 ].mul( tx0y2 ), + Gy[ 1 ][ 2 ].mul( tx1y2 ), + Gy[ 2 ][ 2 ].mul( tx2y2 ) + ); + + // magnitute of the total gradient + + const G = valueGx.mul( valueGx ).add( valueGy.mul( valueGy ) ).sqrt(); + + return vec4( vec3( G ), 1 ); } ); - const outputNode = pixelation(); + const outputNode = sobel(); return outputNode; @@ -57877,5260 +57539,7620 @@ class PixelationNode extends TempNode { } -PixelationNode.type = /*@__PURE__*/ registerNode( 'Pixelation', PixelationNode ); +const sobel = ( node ) => nodeObject( new SobelOperatorNode( convertToTexture( node ) ) ); -const pixelation = ( node, depthNode, normalNode, pixelSize = 6, normalEdgeStrength = 0.3, depthEdgeStrength = 0.4 ) => nodeObject( new PixelationNode( convertToTexture( node ), convertToTexture( depthNode ), convertToTexture( normalNode ), nodeObject( pixelSize ), nodeObject( normalEdgeStrength ), nodeObject( depthEdgeStrength ) ) ); +class DepthOfFieldNode extends TempNode { -class PixelationPassNode extends PassNode { + static get type() { - constructor( scene, camera, pixelSize = 6, normalEdgeStrength = 0.3, depthEdgeStrength = 0.4 ) { + return 'DepthOfFieldNode'; - super( 'color', scene, camera, { minFilter: NearestFilter, magFilter: NearestFilter } ); + } - this.pixelSize = pixelSize; - this.normalEdgeStrength = normalEdgeStrength; - this.depthEdgeStrength = depthEdgeStrength; + constructor( textureNode, viewZNode, focusNode, apertureNode, maxblurNode ) { - this.isPixelationPassNode = true; + super(); - this._mrt = mrt( { - output: output, - normal: normalView - } ); + this.textureNode = textureNode; + this.viewZNode = viewZNode; - } + this.focusNode = focusNode; + this.apertureNode = apertureNode; + this.maxblurNode = maxblurNode; - setSize( width, height ) { + this._aspect = uniform( 0 ); - const pixelSize = this.pixelSize.value ? this.pixelSize.value : this.pixelSize; + this.updateBeforeType = NodeUpdateType.RENDER; - const adjustedWidth = Math.floor( width / pixelSize ); - const adjustedHeight = Math.floor( height / pixelSize ); + } - super.setSize( adjustedWidth, adjustedHeight ); + updateBefore() { + + const map = this.textureNode.value; + + this._aspect.value = map.image.width / map.image.height; } setup() { - const color = super.getTextureNode( 'output' ); - const depth = super.getTextureNode( 'depth' ); - const normal = super.getTextureNode( 'normal' ); - - return pixelation( color, depth, normal, this.pixelSize, this.normalEdgeStrength, this.depthEdgeStrength ); + const textureNode = this.textureNode; + const uvNode = textureNode.uvNode || uv(); - } + const sampleTexture = ( uv ) => textureNode.uv( uv ); -} + const dof = Fn( () => { -const pixelationPass = ( scene, camera, pixelSize, normalEdgeStrength, depthEdgeStrength ) => nodeObject( new PixelationPassNode( scene, camera, pixelSize, normalEdgeStrength, depthEdgeStrength ) ); + const aspectcorrect = vec2( 1.0, this._aspect ); -PixelationPassNode.type = /*@__PURE__*/ registerNode( 'PixelationPass', PixelationPassNode ); + const factor = this.focusNode.add( this.viewZNode ); -const _size$3 = /*@__PURE__*/ new Vector2(); + const dofblur = vec2( clamp( factor.mul( this.apertureNode ), this.maxblurNode.negate(), this.maxblurNode ) ); -/** -* -* Supersample Anti-Aliasing Render Pass -* -* This manual approach to SSAA re-renders the scene ones for each sample with camera jitter and accumulates the results. -* -* References: https://en.wikipedia.org/wiki/Supersampling -* -*/ + const dofblur9 = dofblur.mul( 0.9 ); + const dofblur7 = dofblur.mul( 0.7 ); + const dofblur4 = dofblur.mul( 0.4 ); -class SSAAPassNode extends PassNode { + let col = vec4( 0.0 ); - constructor( scene, camera ) { + col = col.add( sampleTexture( uvNode ) ); - super( PassNode.COLOR, scene, camera ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.0, 0.4 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.15, 0.37 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.37, 0.15 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.40, 0.0 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.37, - 0.15 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.15, - 0.37 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.0, - 0.4 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.15, 0.37 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.37, 0.15 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.4, 0.0 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.37, - 0.15 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.15, - 0.37 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.15, 0.37 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.37, 0.15 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.37, - 0.15 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.15, - 0.37 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.15, 0.37 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.37, 0.15 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.37, - 0.15 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.15, - 0.37 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.40, 0.0 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.0, - 0.4 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.4, 0.0 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.0, 0.4 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.4, 0.0 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.0, - 0.4 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.4, 0.0 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.0, 0.4 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); - this.isSSAAPassNode = true; + col = col.div( 41 ); + col.a = 1; - this.sampleLevel = 4; // specified as n, where the number of samples is 2^n, so sampleLevel = 4, is 2^4 samples, 16. - this.unbiased = true; - this.clearColor = new Color( 0x000000 ); - this.clearAlpha = 0; + return vec4( col ); - this._currentClearColor = new Color(); - this.sampleWeight = uniform( 1 ); + } ); - this.sampleRenderTarget = null; + const outputNode = dof(); - this._quadMesh = new QuadMesh(); + return outputNode; } - updateBefore( frame ) { +} - const { renderer } = frame; - const { scene, camera } = this; +const dof = ( node, viewZNode, focus = 1, aperture = 0.025, maxblur = 1 ) => nodeObject( new DepthOfFieldNode( convertToTexture( node ), nodeObject( viewZNode ), nodeObject( focus ), nodeObject( aperture ), nodeObject( maxblur ) ) ); - this._pixelRatio = renderer.getPixelRatio(); +class DotScreenNode extends TempNode { - const size = renderer.getSize( _size$3 ); + static get type() { - this.setSize( size.width, size.height ); - this.sampleRenderTarget.setSize( this.renderTarget.width, this.renderTarget.height ); + return 'DotScreenNode'; - // save current renderer settings + } - renderer.getClearColor( this._currentClearColor ); - const currentClearAlpha = renderer.getClearAlpha(); - const currentRenderTarget = renderer.getRenderTarget(); - const currentMRT = renderer.getMRT(); - const currentAutoClear = renderer.autoClear; + constructor( inputNode, center = new Vector2( 0.5, 0.5 ), angle = 1.57, scale = 1 ) { - // + super( 'vec4' ); - this._cameraNear.value = camera.near; - this._cameraFar.value = camera.far; - - renderer.setMRT( this.getMRT() ); - renderer.autoClear = false; - - const jitterOffsets = _JitterVectors[ Math.max( 0, Math.min( this.sampleLevel, 5 ) ) ]; - - const baseSampleWeight = 1.0 / jitterOffsets.length; - const roundingRange = 1 / 32; + this.inputNode = inputNode; + this.center = uniform( center ); + this.angle = uniform( angle ); + this.scale = uniform( scale ); - const viewOffset = { + } - fullWidth: this.renderTarget.width, - fullHeight: this.renderTarget.height, - offsetX: 0, - offsetY: 0, - width: this.renderTarget.width, - height: this.renderTarget.height + setup() { - }; + const inputNode = this.inputNode; - const originalViewOffset = Object.assign( {}, camera.view ); + const pattern = Fn( () => { - if ( originalViewOffset.enabled ) Object.assign( viewOffset, originalViewOffset ); + const s = sin( this.angle ); + const c = cos( this.angle ); - // render the scene multiple times, each slightly jitter offset from the last and accumulate the results. + const tex = uv().mul( screenSize ).sub( this.center ); + const point = vec2( c.mul( tex.x ).sub( s.mul( tex.y ) ), s.mul( tex.x ).add( c.mul( tex.y ) ) ).mul( this.scale ); - for ( let i = 0; i < jitterOffsets.length; i ++ ) { + return sin( point.x ).mul( sin( point.y ) ).mul( 4 ); - const jitterOffset = jitterOffsets[ i ]; + } ); - if ( camera.setViewOffset ) { + const dotScreen = Fn( () => { - camera.setViewOffset( + const color = inputNode; - viewOffset.fullWidth, viewOffset.fullHeight, + const average = add( color.r, color.g, color.b ).div( 3 ); - viewOffset.offsetX + jitterOffset[ 0 ] * 0.0625, viewOffset.offsetY + jitterOffset[ 1 ] * 0.0625, // 0.0625 = 1 / 16 + return vec4( vec3( average.mul( 10 ).sub( 5 ).add( pattern() ) ), color.a ); - viewOffset.width, viewOffset.height + } ); - ); + const outputNode = dotScreen(); - } + return outputNode; - this.sampleWeight.value = baseSampleWeight; + } - if ( this.unbiased ) { +} - // the theory is that equal weights for each sample lead to an accumulation of rounding errors. - // The following equation varies the sampleWeight per sample so that it is uniformly distributed - // across a range of values whose rounding errors cancel each other out. +const dotScreen = ( node, center, angle, scale ) => nodeObject( new DotScreenNode( nodeObject( node ), center, angle, scale ) ); - const uniformCenteredDistribution = ( - 0.5 + ( i + 0.5 ) / jitterOffsets.length ); - this.sampleWeight.value += roundingRange * uniformCenteredDistribution; +class RGBShiftNode extends TempNode { - } + static get type() { - renderer.setClearColor( this.clearColor, this.clearAlpha ); - renderer.setRenderTarget( this.sampleRenderTarget ); - renderer.clear(); - renderer.render( scene, camera ); + return 'RGBShiftNode'; - // accumulation + } - renderer.setRenderTarget( this.renderTarget ); + constructor( textureNode, amount = 0.005, angle = 0 ) { - if ( i === 0 ) { + super( 'vec4' ); - renderer.setClearColor( 0x000000, 0.0 ); - renderer.clear(); + this.textureNode = textureNode; + this.amount = uniform( amount ); + this.angle = uniform( angle ); - } + } - this._quadMesh.render( renderer ); + setup() { - } + const { textureNode } = this; - renderer.copyTextureToTexture( this.sampleRenderTarget.depthTexture, this.renderTarget.depthTexture ); + const uvNode = textureNode.uvNode || uv(); - // restore + const sampleTexture = ( uv ) => textureNode.uv( uv ); - if ( camera.setViewOffset && originalViewOffset.enabled ) { + const rgbShift = Fn( () => { - camera.setViewOffset( + const offset = vec2( cos( this.angle ), sin( this.angle ) ).mul( this.amount ); + const cr = sampleTexture( uvNode.add( offset ) ); + const cga = sampleTexture( uvNode ); + const cb = sampleTexture( uvNode.sub( offset ) ); - originalViewOffset.fullWidth, originalViewOffset.fullHeight, + return vec4( cr.r, cga.g, cb.b, cga.a ); - originalViewOffset.offsetX, originalViewOffset.offsetY, + } ); - originalViewOffset.width, originalViewOffset.height + return rgbShift(); - ); + } - } else if ( camera.clearViewOffset ) { +} - camera.clearViewOffset(); +const rgbShift = ( node, amount, angle ) => nodeObject( new RGBShiftNode( convertToTexture( node ), amount, angle ) ); - } +class FilmNode extends TempNode { - renderer.setRenderTarget( currentRenderTarget ); - renderer.setMRT( currentMRT ); + static get type() { - renderer.autoClear = currentAutoClear; - renderer.setClearColor( this._currentClearColor, currentClearAlpha ); + return 'FilmNode'; } - setup( builder ) { - - if ( this.sampleRenderTarget === null ) { - - this.sampleRenderTarget = this.renderTarget.clone(); + constructor( inputNode, intensityNode = null, uvNode = null ) { - } + super(); - let sampleTexture; + this.inputNode = inputNode; + this.intensityNode = intensityNode; + this.uvNode = uvNode; - const passMRT = this.getMRT(); + } - if ( passMRT !== null ) { + setup() { - const outputs = {}; + const uvNode = this.uvNode || uv(); - for ( const name in passMRT.outputNodes ) { + const film = Fn( () => { - const index = getTextureIndex( this.sampleRenderTarget.textures, name ); + const base = this.inputNode.rgb; + const noise = rand( fract( uvNode.add( timerLocal() ) ) ); - if ( index >= 0 ) { + let color = base.add( base.mul( clamp( noise.add( 0.1 ), 0, 1 ) ) ); - outputs[ name ] = texture( this.sampleRenderTarget.textures[ index ] ).mul( this.sampleWeight ); + if ( this.intensityNode !== null ) { - } + color = mix( base, color, this.intensityNode ); } - sampleTexture = mrt( outputs ); - - } else { - - sampleTexture = texture( this.sampleRenderTarget.texture ).mul( this.sampleWeight ); - - } - - this._quadMesh.material = new NodeMaterial(); - this._quadMesh.material.fragmentNode = sampleTexture; - this._quadMesh.material.transparent = true; - this._quadMesh.material.depthTest = false; - this._quadMesh.material.depthWrite = false; - this._quadMesh.material.premultipliedAlpha = true; - this._quadMesh.material.blending = AdditiveBlending; - this._quadMesh.material.normals = false; - this._quadMesh.material.name = 'SSAA'; - - return super.setup( builder ); - - } - - dispose() { - - super.dispose(); + return vec4( color, this.inputNode.a ); - if ( this.sampleRenderTarget !== null ) { + } ); - this.sampleRenderTarget.dispose(); + const outputNode = film(); - } + return outputNode; } } -SSAAPassNode.type = /*@__PURE__*/ registerNode( 'SSAAPass', SSAAPassNode ); - -// These jitter vectors are specified in integers because it is easier. -// I am assuming a [-8,8) integer grid, but it needs to be mapped onto [-0.5,0.5) -// before being used, thus these integers need to be scaled by 1/16. -// -// Sample patterns reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 -const _JitterVectors = [ - [ - [ 0, 0 ] - ], - [ - [ 4, 4 ], [ - 4, - 4 ] - ], - [ - [ - 2, - 6 ], [ 6, - 2 ], [ - 6, 2 ], [ 2, 6 ] - ], - [ - [ 1, - 3 ], [ - 1, 3 ], [ 5, 1 ], [ - 3, - 5 ], - [ - 5, 5 ], [ - 7, - 1 ], [ 3, 7 ], [ 7, - 7 ] - ], - [ - [ 1, 1 ], [ - 1, - 3 ], [ - 3, 2 ], [ 4, - 1 ], - [ - 5, - 2 ], [ 2, 5 ], [ 5, 3 ], [ 3, - 5 ], - [ - 2, 6 ], [ 0, - 7 ], [ - 4, - 6 ], [ - 6, 4 ], - [ - 8, 0 ], [ 7, - 4 ], [ 6, 7 ], [ - 7, - 8 ] - ], - [ - [ - 4, - 7 ], [ - 7, - 5 ], [ - 3, - 5 ], [ - 5, - 4 ], - [ - 1, - 4 ], [ - 2, - 2 ], [ - 6, - 1 ], [ - 4, 0 ], - [ - 7, 1 ], [ - 1, 2 ], [ - 6, 3 ], [ - 3, 3 ], - [ - 7, 6 ], [ - 3, 6 ], [ - 5, 7 ], [ - 1, 7 ], - [ 5, - 7 ], [ 1, - 6 ], [ 6, - 5 ], [ 4, - 4 ], - [ 2, - 3 ], [ 7, - 2 ], [ 1, - 1 ], [ 4, - 1 ], - [ 2, 1 ], [ 6, 2 ], [ 0, 4 ], [ 4, 4 ], - [ 2, 5 ], [ 7, 5 ], [ 5, 6 ], [ 3, 7 ] - ] -]; +const film = /*@__PURE__*/ nodeProxy( FilmNode ); -const ssaaPass = ( scene, camera ) => nodeObject( new SSAAPassNode( scene, camera ) ); +class Lut3DNode extends TempNode { -const _size$2 = /*@__PURE__*/ new Vector2(); + static get type() { -class StereoPassNode extends PassNode { + return 'Lut3DNode'; - constructor( scene, camera ) { + } - super( PassNode.COLOR, scene, camera ); + constructor( inputNode, lutNode, size, intensityNode ) { - this.isStereoPassNode = true; + super(); - this.stereo = new StereoCamera(); - this.stereo.aspect = 0.5; + this.inputNode = inputNode; + this.lutNode = lutNode; + this.size = uniform( size ); + this.intensityNode = intensityNode; } - updateBefore( frame ) { - - const { renderer } = frame; - const { scene, camera, stereo, renderTarget } = this; - - this._pixelRatio = renderer.getPixelRatio(); - - stereo.cameraL.coordinateSystem = renderer.coordinateSystem; - stereo.cameraR.coordinateSystem = renderer.coordinateSystem; - stereo.update( camera ); + setup() { - const size = renderer.getSize( _size$2 ); - this.setSize( size.width, size.height ); + const { inputNode, lutNode } = this; - const currentAutoClear = renderer.autoClear; - renderer.autoClear = false; + const sampleLut = ( uv ) => lutNode.uv( uv ); - const currentRenderTarget = renderer.getRenderTarget(); - const currentMRT = renderer.getMRT(); + const lut3D = Fn( () => { - this._cameraNear.value = camera.near; - this._cameraFar.value = camera.far; + const base = inputNode; - for ( const name in this._previousTextures ) { + // pull the sample in by half a pixel so the sample begins at the center of the edge pixels. - this.toggleTexture( name ); + const pixelWidth = float( 1.0 ).div( this.size ); + const halfPixelWidth = float( 0.5 ).div( this.size ); + const uvw = vec3( halfPixelWidth ).add( base.rgb.mul( float( 1.0 ).sub( pixelWidth ) ) ); - } + const lutValue = vec4( sampleLut( uvw ).rgb, base.a ); - renderer.setRenderTarget( renderTarget ); - renderer.setMRT( this._mrt ); - renderer.clear(); + return vec4( mix( base, lutValue, this.intensityNode ) ); - renderTarget.scissorTest = true; + } ); - renderTarget.scissor.set( 0, 0, renderTarget.width / 2, renderTarget.height ); - renderTarget.viewport.set( 0, 0, renderTarget.width / 2, renderTarget.height ); - renderer.render( scene, stereo.cameraL ); + const outputNode = lut3D(); - renderTarget.scissor.set( renderTarget.width / 2, 0, renderTarget.width / 2, renderTarget.height ); - renderTarget.viewport.set( renderTarget.width / 2, 0, renderTarget.width / 2, renderTarget.height ); - renderer.render( scene, stereo.cameraR ); + return outputNode; - renderTarget.scissorTest = false; + } - renderer.setRenderTarget( currentRenderTarget ); - renderer.setMRT( currentMRT ); +} - renderer.autoClear = currentAutoClear; +const lut3D = ( node, lut, size, intensity ) => nodeObject( new Lut3DNode( nodeObject( node ), nodeObject( lut ), size, nodeObject( intensity ) ) ); - } +const _quadMesh$4 = /*@__PURE__*/ new QuadMesh(); +const _currentClearColor$1 = /*@__PURE__*/ new Color(); +const _size$5 = /*@__PURE__*/ new Vector2(); -} +class GTAONode extends TempNode { -StereoPassNode.type = /*@__PURE__*/ registerNode( 'StereoPass', StereoPassNode ); + static get type() { -const stereoPass = ( scene, camera ) => nodeObject( new StereoPassNode( scene, camera ) ); + return 'GTAONode'; -const _size$1 = /*@__PURE__*/ new Vector2(); -const _quadMesh$1 = /*@__PURE__*/ new QuadMesh(); + } -class StereoCompositePassNode extends PassNode { + constructor( depthNode, normalNode, camera ) { - constructor( scene, camera ) { + super(); - super( PassNode.COLOR, scene, camera ); + this.depthNode = depthNode; + this.normalNode = normalNode; - this.isStereoCompositePassNode = true; + this.radius = uniform( 0.25 ); + this.resolution = uniform( new Vector2() ); + this.thickness = uniform( 1 ); + this.distanceExponent = uniform( 1 ); + this.distanceFallOff = uniform( 1 ); + this.scale = uniform( 1 ); + this.noiseNode = texture( generateMagicSquareNoise() ); - this.stereo = new StereoCamera(); - const _params = { minFilter: LinearFilter, magFilter: NearestFilter, type: HalfFloatType }; + this.cameraProjectionMatrix = uniform( camera.projectionMatrix ); + this.cameraProjectionMatrixInverse = uniform( camera.projectionMatrixInverse ); - this._renderTargetL = new RenderTarget( 1, 1, _params ); - this._renderTargetR = new RenderTarget( 1, 1, _params ); + this.SAMPLES = uniform( 16 ); - this._mapLeft = texture( this._renderTargetL.texture ); - this._mapRight = texture( this._renderTargetR.texture ); + this._aoRenderTarget = new RenderTarget(); + this._aoRenderTarget.texture.name = 'GTAONode.AO'; this._material = null; + this._textureNode = passTexture( this, this._aoRenderTarget.texture ); + + this.updateBeforeType = NodeUpdateType.FRAME; } - updateStereoCamera( coordinateSystem ) { + getTextureNode() { - this.stereo.cameraL.coordinateSystem = coordinateSystem; - this.stereo.cameraR.coordinateSystem = coordinateSystem; - this.stereo.update( this.camera ); + return this._textureNode; } setSize( width, height ) { - super.setSize( width, height ); - - this._renderTargetL.setSize( this.renderTarget.width, this.renderTarget.height ); - this._renderTargetR.setSize( this.renderTarget.width, this.renderTarget.height ); + this.resolution.value.set( width, height ); + this._aoRenderTarget.setSize( width, height ); } updateBefore( frame ) { const { renderer } = frame; - const { scene, stereo, renderTarget } = this; - - this._pixelRatio = renderer.getPixelRatio(); - - this.updateStereoCamera( renderer.coordinateSystem ); - const size = renderer.getSize( _size$1 ); - this.setSize( size.width, size.height ); + const size = renderer.getDrawingBufferSize( _size$5 ); const currentRenderTarget = renderer.getRenderTarget(); + const currentMRT = renderer.getMRT(); + renderer.getClearColor( _currentClearColor$1 ); + const currentClearAlpha = renderer.getClearAlpha(); - // left + _quadMesh$4.material = this._material; - renderer.setRenderTarget( this._renderTargetL ); - renderer.render( scene, stereo.cameraL ); + this.setSize( size.width, size.height ); - // right + // clear - renderer.setRenderTarget( this._renderTargetR ); - renderer.render( scene, stereo.cameraR ); + renderer.setMRT( null ); + renderer.setClearColor( 0xffffff, 1 ); - // composite + // ao - renderer.setRenderTarget( renderTarget ); - _quadMesh$1.material = this._material; - _quadMesh$1.render( renderer ); + renderer.setRenderTarget( this._aoRenderTarget ); + _quadMesh$4.render( renderer ); // restore renderer.setRenderTarget( currentRenderTarget ); + renderer.setMRT( currentMRT ); + renderer.setClearColor( _currentClearColor$1, currentClearAlpha ); } - dispose() { - - super.dispose(); - - this._renderTargetL.dispose(); - this._renderTargetR.dispose(); - - if ( this._material !== null ) { - - this._material.dispose(); - - } + setup( builder ) { - } + const uvNode = uv(); -} + const sampleDepth = ( uv ) => this.depthNode.uv( uv ).x; + const sampleNoise = ( uv ) => this.noiseNode.uv( uv ); -StereoCompositePassNode.type = /*@__PURE__*/ registerNode( 'StereoCompositePass', StereoCompositePassNode ); + const getSceneUvAndDepth = Fn( ( [ sampleViewPos ] )=> { -class AnaglyphPassNode extends StereoCompositePassNode { + const sampleClipPos = this.cameraProjectionMatrix.mul( vec4( sampleViewPos, 1.0 ) ); + let sampleUv = sampleClipPos.xy.div( sampleClipPos.w ).mul( 0.5 ).add( 0.5 ).toVar(); + sampleUv = vec2( sampleUv.x, sampleUv.y.oneMinus() ); + const sampleSceneDepth = sampleDepth( sampleUv ); + return vec3( sampleUv, sampleSceneDepth ); - constructor( scene, camera ) { + } ); - super( scene, camera ); + const getViewPosition = Fn( ( [ screenPosition, depth ] ) => { - this.isAnaglyphPassNode = true; + screenPosition = vec2( screenPosition.x, screenPosition.y.oneMinus() ).mul( 2.0 ).sub( 1.0 ); - // Dubois matrices from https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.7.6968&rep=rep1&type=pdf#page=4 + const clipSpacePosition = vec4( vec3( screenPosition, depth ), 1.0 ); + const viewSpacePosition = vec4( this.cameraProjectionMatrixInverse.mul( clipSpacePosition ) ); - this._colorMatrixLeft = uniform( new Matrix3().fromArray( [ - 0.456100, - 0.0400822, - 0.0152161, - 0.500484, - 0.0378246, - 0.0205971, - 0.176381, - 0.0157589, - 0.00546856 - ] ) ); + return viewSpacePosition.xyz.div( viewSpacePosition.w ); - this._colorMatrixRight = uniform( new Matrix3().fromArray( [ - - 0.0434706, 0.378476, - 0.0721527, - - 0.0879388, 0.73364, - 0.112961, - - 0.00155529, - 0.0184503, 1.2264 - ] ) ); + } ); - } + const ao = Fn( () => { - setup( builder ) { + const depth = sampleDepth( uvNode ); - const uvNode = uv(); + depth.greaterThanEqual( 1.0 ).discard(); - const anaglyph = Fn( () => { + const viewPosition = getViewPosition( uvNode, depth ); + const viewNormal = this.normalNode.rgb.normalize(); - const colorL = this._mapLeft.uv( uvNode ); - const colorR = this._mapRight.uv( uvNode ); + const radiusToUse = this.radius; - const color = clamp( this._colorMatrixLeft.mul( colorL.rgb ).add( this._colorMatrixRight.mul( colorR.rgb ) ) ); + const noiseResolution = textureSize( this.noiseNode, 0 ); + let noiseUv = vec2( uvNode.x, uvNode.y.oneMinus() ); + noiseUv = noiseUv.mul( this.resolution.div( noiseResolution ) ); + const noiseTexel = sampleNoise( noiseUv ); + const randomVec = noiseTexel.xyz.mul( 2.0 ).sub( 1.0 ); + const tangent = vec3( randomVec.xy, 0.0 ).normalize(); + const bitangent = vec3( tangent.y.mul( - 1.0 ), tangent.x, 0.0 ); + const kernelMatrix = mat3( tangent, bitangent, vec3( 0.0, 0.0, 1.0 ) ); - return vec4( color.rgb, max$1( colorL.a, colorR.a ) ); + const DIRECTIONS = this.SAMPLES.lessThan( 30 ).select( 3, 5 ); + const STEPS = add( this.SAMPLES, DIRECTIONS.sub( 1 ) ).div( DIRECTIONS ); - } ); + const ao = float( 0 ).toVar(); - const material = this._material || ( this._material = new NodeMaterial() ); - material.fragmentNode = anaglyph().context( builder.getSharedContext() ); - material.name = 'Anaglyph'; - material.needsUpdate = true; + Loop( { start: int( 0 ), end: DIRECTIONS, type: 'int', condition: '<' }, ( { i } ) => { - return super.setup( builder ); + const angle = float( i ).div( float( DIRECTIONS ) ).mul( PI ); + const sampleDir = vec4( cos( angle ), sin( angle ), 0., add( 0.5, mul( 0.5, noiseTexel.w ) ) ); + sampleDir.xyz = normalize( kernelMatrix.mul( sampleDir.xyz ) ); - } + const viewDir = normalize( viewPosition.xyz.negate() ); + const sliceBitangent = normalize( cross( sampleDir.xyz, viewDir ) ); + const sliceTangent = cross( sliceBitangent, viewDir ); + const normalInSlice = normalize( viewNormal.sub( sliceBitangent.mul( dot( viewNormal, sliceBitangent ) ) ) ); -} + const tangentToNormalInSlice = cross( normalInSlice, sliceBitangent ); + const cosHorizons = vec2( dot( viewDir, tangentToNormalInSlice ), dot( viewDir, tangentToNormalInSlice.negate() ) ).toVar(); -const anaglyphPass = ( scene, camera ) => nodeObject( new AnaglyphPassNode( scene, camera ) ); + Loop( { end: STEPS, type: 'int', name: 'j', condition: '<' }, ( { j } ) => { -class ParallaxBarrierPassNode extends StereoCompositePassNode { + const sampleViewOffset = sampleDir.xyz.mul( radiusToUse ).mul( sampleDir.w ).mul( pow( div( float( j ).add( 1.0 ), float( STEPS ) ), this.distanceExponent ) ); - constructor( scene, camera ) { + // x - super( scene, camera ); + const sampleSceneUvDepthX = getSceneUvAndDepth( viewPosition.add( sampleViewOffset ) ); + const sampleSceneViewPositionX = getViewPosition( sampleSceneUvDepthX.xy, sampleSceneUvDepthX.z ); + const viewDeltaX = sampleSceneViewPositionX.sub( viewPosition ); - this.isParallaxBarrierPassNode = true; + If( abs( viewDeltaX.z ).lessThan( this.thickness ), () => { - } + const sampleCosHorizon = dot( viewDir, normalize( viewDeltaX ) ); + cosHorizons.x.addAssign( max$1( 0, mul( sampleCosHorizon.sub( cosHorizons.x ), mix( 1.0, float( 2.0 ).div( float( j ).add( 2 ) ), this.distanceFallOff ) ) ) ); - setup( builder ) { + } ); - const uvNode = uv(); + // y - const parallaxBarrier = Fn( () => { + const sampleSceneUvDepthY = getSceneUvAndDepth( viewPosition.sub( sampleViewOffset ) ); + const sampleSceneViewPositionY = getViewPosition( sampleSceneUvDepthY.xy, sampleSceneUvDepthY.z ); + const viewDeltaY = sampleSceneViewPositionY.sub( viewPosition ); - const color = vec4().toVar(); + If( abs( viewDeltaY.z ).lessThan( this.thickness ), () => { - If( mod( viewportCoordinate.y, 2 ).greaterThan( 1 ), () => { + const sampleCosHorizon = dot( viewDir, normalize( viewDeltaY ) ); + cosHorizons.y.addAssign( max$1( 0, mul( sampleCosHorizon.sub( cosHorizons.y ), mix( 1.0, float( 2.0 ).div( float( j ).add( 2 ) ), this.distanceFallOff ) ) ) ); - color.assign( this._mapLeft.uv( uvNode ) ); + } ); - } ).Else( () => { + } ); - color.assign( this._mapRight.uv( uvNode ) ); + const sinHorizons = sqrt( sub( 1.0, cosHorizons.mul( cosHorizons ) ) ); + const nx = dot( normalInSlice, sliceTangent ); + const ny = dot( normalInSlice, viewDir ); + const nxb = mul( 0.5, acos( cosHorizons.y ).sub( acos( cosHorizons.x ) ).add( sinHorizons.x.mul( cosHorizons.x ).sub( sinHorizons.y.mul( cosHorizons.y ) ) ) ); + const nyb = mul( 0.5, sub( 2.0, cosHorizons.x.mul( cosHorizons.x ) ).sub( cosHorizons.y.mul( cosHorizons.y ) ) ); + const occlusion = nx.mul( nxb ).add( ny.mul( nyb ) ); + ao.addAssign( occlusion ); } ); - return color; + ao.assign( clamp( ao.div( DIRECTIONS ), 0, 1 ) ); + ao.assign( pow( ao, this.scale ) ); + + return vec4( vec3( ao ), 1.0 ); } ); const material = this._material || ( this._material = new NodeMaterial() ); - material.fragmentNode = parallaxBarrier().context( builder.getSharedContext() ); + material.fragmentNode = ao().context( builder.getSharedContext() ); + material.name = 'GTAO'; material.needsUpdate = true; - return super.setup( builder ); + // + + return this._textureNode; } -} + dispose() { -ParallaxBarrierPassNode.type = /*@__PURE__*/ registerNode( 'ParallaxBarrierPass', ParallaxBarrierPassNode ); + this._aoRenderTarget.dispose(); -const parallaxBarrierPass = ( scene, camera ) => nodeObject( new ParallaxBarrierPassNode( scene, camera ) ); + } -class ScriptableValueNode extends Node { +} - constructor( value = null ) { +function generateMagicSquareNoise( size = 5 ) { - super(); + const noiseSize = Math.floor( size ) % 2 === 0 ? Math.floor( size ) + 1 : Math.floor( size ); + const magicSquare = generateMagicSquare( noiseSize ); + const noiseSquareSize = magicSquare.length; + const data = new Uint8Array( noiseSquareSize * 4 ); - this._value = value; - this._cache = null; - - this.inputType = null; - this.outpuType = null; - - this.events = new EventDispatcher(); + for ( let inx = 0; inx < noiseSquareSize; ++ inx ) { - this.isScriptableValueNode = true; + const iAng = magicSquare[ inx ]; + const angle = ( 2 * Math.PI * iAng ) / noiseSquareSize; + const randomVec = new Vector3( + Math.cos( angle ), + Math.sin( angle ), + 0 + ).normalize(); + data[ inx * 4 ] = ( randomVec.x * 0.5 + 0.5 ) * 255; + data[ inx * 4 + 1 ] = ( randomVec.y * 0.5 + 0.5 ) * 255; + data[ inx * 4 + 2 ] = 127; + data[ inx * 4 + 3 ] = 255; } - get isScriptableOutputNode() { - - return this.outputType !== null; + const noiseTexture = new DataTexture( data, noiseSize, noiseSize ); + noiseTexture.wrapS = RepeatWrapping; + noiseTexture.wrapT = RepeatWrapping; + noiseTexture.needsUpdate = true; - } + return noiseTexture; - set value( val ) { +} - if ( this._value === val ) return; +function generateMagicSquare( size ) { - if ( this._cache && this.inputType === 'URL' && this.value.value instanceof ArrayBuffer ) { + const noiseSize = Math.floor( size ) % 2 === 0 ? Math.floor( size ) + 1 : Math.floor( size ); + const noiseSquareSize = noiseSize * noiseSize; + const magicSquare = Array( noiseSquareSize ).fill( 0 ); + let i = Math.floor( noiseSize / 2 ); + let j = noiseSize - 1; - URL.revokeObjectURL( this._cache ); + for ( let num = 1; num <= noiseSquareSize; ) { - this._cache = null; + if ( i === - 1 && j === noiseSize ) { - } + j = noiseSize - 2; + i = 0; - this._value = val; + } else { - this.events.dispatchEvent( { type: 'change' } ); + if ( j === noiseSize ) { - this.refresh(); + j = 0; - } + } - get value() { + if ( i < 0 ) { - return this._value; + i = noiseSize - 1; - } + } - refresh() { + } - this.events.dispatchEvent( { type: 'refresh' } ); + if ( magicSquare[ i * noiseSize + j ] !== 0 ) { - } + j -= 2; + i ++; + continue; - getValue() { + } else { - const value = this.value; + magicSquare[ i * noiseSize + j ] = num ++; - if ( value && this._cache === null && this.inputType === 'URL' && value.value instanceof ArrayBuffer ) { + } - this._cache = URL.createObjectURL( new Blob( [ value.value ] ) ); + j ++; + i --; - } else if ( value && value.value !== null && value.value !== undefined && ( - ( ( this.inputType === 'URL' || this.inputType === 'String' ) && typeof value.value === 'string' ) || - ( this.inputType === 'Number' && typeof value.value === 'number' ) || - ( this.inputType === 'Vector2' && value.value.isVector2 ) || - ( this.inputType === 'Vector3' && value.value.isVector3 ) || - ( this.inputType === 'Vector4' && value.value.isVector4 ) || - ( this.inputType === 'Color' && value.value.isColor ) || - ( this.inputType === 'Matrix3' && value.value.isMatrix3 ) || - ( this.inputType === 'Matrix4' && value.value.isMatrix4 ) - ) ) { + } - return value.value; + return magicSquare; - } +} - return this._cache || value; +const ao = ( depthNode, normalNode, camera ) => nodeObject( new GTAONode( nodeObject( depthNode ), nodeObject( normalNode ), camera ) ); - } +class DenoiseNode extends TempNode { - getNodeType( builder ) { + static get type() { - return this.value && this.value.isNode ? this.value.getNodeType( builder ) : 'float'; + return 'DenoiseNode'; } - setup() { + constructor( textureNode, depthNode, normalNode, noiseNode, camera ) { - return this.value && this.value.isNode ? this.value : float(); + super(); - } + this.textureNode = textureNode; + this.depthNode = depthNode; + this.normalNode = normalNode; + this.noiseNode = noiseNode; - serialize( data ) { + this.cameraProjectionMatrixInverse = uniform( camera.projectionMatrixInverse ); + this.lumaPhi = uniform( 5 ); + this.depthPhi = uniform( 5 ); + this.normalPhi = uniform( 5 ); + this.radius = uniform( 5 ); + this.index = uniform( 0 ); - super.serialize( data ); + this._resolution = uniform( new Vector2() ); + this._sampleVectors = uniformArray( generatePdSamplePointInitializer( 16, 2, 1 ) ); - if ( this.value !== null ) { + this.updateBeforeType = NodeUpdateType.RENDER; - if ( this.inputType === 'ArrayBuffer' ) { + } - data.value = arrayBufferToBase64( this.value ); + updateBefore() { - } else { + const map = this.textureNode.value; - data.value = this.value ? this.value.toJSON( data.meta ).uuid : null; + this._resolution.value.set( map.image.width, map.image.height ); - } + } - } else { + setup() { - data.value = null; + const uvNode = uv(); - } + const sampleTexture = ( uv ) => this.textureNode.uv( uv ); + const sampleDepth = ( uv ) => this.depthNode.uv( uv ).x; + const sampleNormal = ( uv ) => this.normalNode.uv( uv ); + const sampleNoise = ( uv ) => this.noiseNode.uv( uv ); - data.inputType = this.inputType; - data.outputType = this.outputType; + const getViewPosition = Fn( ( [ screenPosition, depth ] ) => { - } + screenPosition = vec2( screenPosition.x, screenPosition.y.oneMinus() ).mul( 2.0 ).sub( 1.0 ); - deserialize( data ) { + const clipSpacePosition = vec4( vec3( screenPosition, depth ), 1.0 ); + const viewSpacePosition = vec4( this.cameraProjectionMatrixInverse.mul( clipSpacePosition ) ); - super.deserialize( data ); + return viewSpacePosition.xyz.div( viewSpacePosition.w ); - let value = null; + } ); - if ( data.value !== null ) { + const denoiseSample = Fn( ( [ center, viewNormal, viewPosition, sampleUv ] ) => { - if ( data.inputType === 'ArrayBuffer' ) { + const texel = sampleTexture( sampleUv ); + const depth = sampleDepth( sampleUv ); + const normal = sampleNormal( sampleUv ).rgb.normalize(); + const neighborColor = texel.rgb; + const viewPos = getViewPosition( sampleUv, depth ); - value = base64ToArrayBuffer( data.value ); + const normalDiff = dot( viewNormal, normal ).toVar(); + const normalSimilarity = pow( max$1( normalDiff, 0 ), this.normalPhi ).toVar(); + const lumaDiff = abs( luminance( neighborColor ).sub( luminance( center ) ) ).toVar(); + const lumaSimilarity = max$1( float( 1.0 ).sub( lumaDiff.div( this.lumaPhi ) ), 0 ).toVar(); + const depthDiff = abs( dot( viewPosition.sub( viewPos ), viewNormal ) ).toVar(); + const depthSimilarity = max$1( float( 1.0 ).sub( depthDiff.div( this.depthPhi ) ), 0 ); + const w = lumaSimilarity.mul( depthSimilarity ).mul( normalSimilarity ); - } else if ( data.inputType === 'Texture' ) { + return vec4( neighborColor.mul( w ), w ); - value = data.meta.textures[ data.value ]; + } ); - } else { + const denoise = Fn( ( [ uvNode ] ) => { - value = data.meta.nodes[ data.value ] || null; + const depth = sampleDepth( uvNode ); + const viewNormal = sampleNormal( uvNode ).rgb.normalize(); - } + const texel = sampleTexture( uvNode ); - } + If( depth.greaterThanEqual( 1.0 ).or( dot( viewNormal, viewNormal ).equal( 0.0 ) ), () => { - this.value = value; + return texel; - this.inputType = data.inputType; - this.outputType = data.outputType; + } ); - } + const center = vec3( texel.rgb ); -} + const viewPosition = getViewPosition( uvNode, depth ); -ScriptableValueNode.type = /*@__PURE__*/ registerNode( 'ScriptableValue', ScriptableValueNode ); + const noiseResolution = textureSize( this.noiseNode, 0 ); + let noiseUv = vec2( uvNode.x, uvNode.y.oneMinus() ); + noiseUv = noiseUv.mul( this._resolution.div( noiseResolution ) ); + const noiseTexel = sampleNoise( noiseUv ); -const scriptableValue = /*@__PURE__*/ nodeProxy( ScriptableValueNode ); + const x = sin( noiseTexel.element( this.index.mod( 4 ).mul( 2 ).mul( PI ) ) ); + const y = cos( noiseTexel.element( this.index.mod( 4 ).mul( 2 ).mul( PI ) ) ); -class Resources extends Map { + const noiseVec = vec2( x, y ); + const rotationMatrix = mat2( noiseVec.x, noiseVec.y.negate(), noiseVec.x, noiseVec.y ); - get( key, callback = null, ...params ) { + const totalWeight = float( 1.0 ).toVar(); + const denoised = vec3( texel.rgb ).toVar(); - if ( this.has( key ) ) return super.get( key ); + Loop( { start: int( 0 ), end: int( 16 ), type: 'int', condition: '<' }, ( { i } ) => { - if ( callback !== null ) { + const sampleDir = this._sampleVectors.element( i ).toVar(); + const offset = rotationMatrix.mul( sampleDir.xy.mul( float( 1.0 ).add( sampleDir.z.mul( this.radius.sub( 1 ) ) ) ) ).div( this._resolution ).toVar(); + const sampleUv = uvNode.add( offset ).toVar(); - const value = callback( ...params ); - this.set( key, value ); - return value; + const result = denoiseSample( center, viewNormal, viewPosition, sampleUv ); - } + denoised.addAssign( result.xyz ); + totalWeight.addAssign( result.w ); - } + } ); -} + If( totalWeight.greaterThan( float( 0 ) ), () => { -class Parameters { + denoised.divAssign( totalWeight ); - constructor( scriptableNode ) { + } ); - this.scriptableNode = scriptableNode; + return vec4( denoised, texel.a ); - } + } ).setLayout( { + name: 'denoise', + type: 'vec4', + inputs: [ + { name: 'uv', type: 'vec2' } + ] + } ); - get parameters() { + const output = Fn( () => { - return this.scriptableNode.parameters; + return denoise( uvNode ); - } + } ); - get layout() { + const outputNode = output(); - return this.scriptableNode.getLayout(); + return outputNode; } - getInputLayout( id ) { +} - return this.scriptableNode.getInputLayout( id ); +function generatePdSamplePointInitializer( samples, rings, radiusExponent ) { - } + const poissonDisk = generateDenoiseSamples( samples, rings, radiusExponent ); - get( name ) { + const array = []; - const param = this.parameters[ name ]; - const value = param ? param.getValue() : null; + for ( let i = 0; i < samples; i ++ ) { - return value; + const sample = poissonDisk[ i ]; + array.push( sample ); } + return array; + } -const global = new Resources(); +function generateDenoiseSamples( numSamples, numRings, radiusExponent ) { -class ScriptableNode extends Node { + const samples = []; - constructor( codeNode = null, parameters = {} ) { + for ( let i = 0; i < numSamples; i ++ ) { - super(); + const angle = 2 * Math.PI * numRings * i / numSamples; + const radius = Math.pow( i / ( numSamples - 1 ), radiusExponent ); + samples.push( new Vector3( Math.cos( angle ), Math.sin( angle ), radius ) ); - this.codeNode = codeNode; - this.parameters = parameters; + } - this._local = new Resources(); - this._output = scriptableValue(); - this._outputs = {}; - this._source = this.source; - this._method = null; - this._object = null; - this._value = null; - this._needsOutputUpdate = true; + return samples; - this.onRefresh = this.onRefresh.bind( this ); +} - this.isScriptableNode = true; +const denoise = ( node, depthNode, normalNode, noiseNode, camera ) => nodeObject( new DenoiseNode( convertToTexture( node ), nodeObject( depthNode ), nodeObject( normalNode ), nodeObject( noiseNode ), camera ) ); - } +class FXAANode extends TempNode { - get source() { + static get type() { - return this.codeNode ? this.codeNode.code : ''; + return 'FXAANode'; } - setLocal( name, value ) { + constructor( textureNode ) { - return this._local.set( name, value ); + super(); - } + this.textureNode = textureNode; - getLocal( name ) { + this.updateBeforeType = NodeUpdateType.RENDER; - return this._local.get( name ); + this._invSize = uniform( new Vector2() ); } - onRefresh() { + updateBefore() { - this._refresh(); + const map = this.textureNode.value; + + this._invSize.value.set( 1 / map.image.width, 1 / map.image.height ); } - getInputLayout( id ) { + setup() { - for ( const element of this.getLayout() ) { + const textureNode = this.textureNode.bias( - 100 ); + const uvNode = textureNode.uvNode || uv(); - if ( element.inputType && ( element.id === id || element.name === id ) ) { + // FXAA 3.11 implementation by NVIDIA, ported to WebGL by Agost Biro (biro@archilogic.com) - return element; + //---------------------------------------------------------------------------------- + // File: es3-kepler\FXAA\assets\shaders/FXAA_DefaultES.frag + // SDK Version: v3.00 + // Email: gameworks@nvidia.com + // Site: http://developer.nvidia.com/ + // + // Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. + // + // Redistribution and use in source and binary forms, with or without + // modification, are permitted provided that the following conditions + // are met: + // * Redistributions of source code must retain the above copyright + // notice, this list of conditions and the following disclaimer. + // * Redistributions in binary form must reproduce the above copyright + // notice, this list of conditions and the following disclaimer in the + // documentation and/or other materials provided with the distribution. + // * Neither the name of NVIDIA CORPORATION nor the names of its + // contributors may be used to endorse or promote products derived + // from this software without specific prior written permission. + // + // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + // + //---------------------------------------------------------------------------------- - } + const FxaaTexTop = ( p ) => textureNode.uv( p ); + const FxaaTexOff = ( p, o, r ) => textureNode.uv( p.add( o.mul( r ) ) ); - } + const NUM_SAMPLES = int( 5 ); - } + const contrast = Fn( ( [ a_immutable, b_immutable ] ) => { - getOutputLayout( id ) { + // assumes colors have premultipliedAlpha, so that the calculated color contrast is scaled by alpha - for ( const element of this.getLayout() ) { + const b = vec4( b_immutable ).toVar(); + const a = vec4( a_immutable ).toVar(); + const diff = vec4( abs( a.sub( b ) ) ).toVar(); - if ( element.outputType && ( element.id === id || element.name === id ) ) { + return max$1( max$1( max$1( diff.r, diff.g ), diff.b ), diff.a ); - return element; + } ); - } + // FXAA3 QUALITY - PC - } + const FxaaPixelShader = Fn( ( [ uv, fxaaQualityRcpFrame, fxaaQualityEdgeThreshold, fxaaQualityinvEdgeThreshold ] ) => { - } + const rgbaM = FxaaTexTop( uv ).toVar(); + const rgbaS = FxaaTexOff( uv, vec2( 0.0, - 1.0 ), fxaaQualityRcpFrame.xy ).toVar(); + const rgbaE = FxaaTexOff( uv, vec2( 1.0, 0.0 ), fxaaQualityRcpFrame.xy ).toVar(); + const rgbaN = FxaaTexOff( uv, vec2( 0.0, 1.0 ), fxaaQualityRcpFrame.xy ).toVar(); + const rgbaW = FxaaTexOff( uv, vec2( - 1.0, 0.0 ), fxaaQualityRcpFrame.xy ).toVar(); + // . S . + // W M E + // . N . - setOutput( name, value ) { + const contrastN = contrast( rgbaM, rgbaN ).toVar(); + const contrastS = contrast( rgbaM, rgbaS ).toVar(); + const contrastE = contrast( rgbaM, rgbaE ).toVar(); + const contrastW = contrast( rgbaM, rgbaW ).toVar(); - const outputs = this._outputs; + const maxValue = max$1( contrastN, max$1( contrastS, max$1( contrastE, contrastW ) ) ).toVar(); - if ( outputs[ name ] === undefined ) { + // . 0 . + // 0 0 0 + // . 0 . - outputs[ name ] = scriptableValue( value ); + If( maxValue.lessThan( fxaaQualityEdgeThreshold ), () => { - } else { + return rgbaM; // assuming define FXAA_DISCARD is always 0 - outputs[ name ].value = value; + } ); - } + // - return this; + const relativeVContrast = sub( contrastN.add( contrastS ), ( contrastE.add( contrastW ) ) ).toVar(); + relativeVContrast.mulAssign( fxaaQualityinvEdgeThreshold ); - } + // 45 deg edge detection and corners of objects, aka V/H contrast is too similar - getOutput( name ) { + If( abs( relativeVContrast ).lessThan( 0.3 ), () => { - return this._outputs[ name ]; + // locate the edge - } + const x = contrastE.greaterThan( contrastW ).select( 1, - 1 ).toVar(); + const y = contrastS.greaterThan( contrastN ).select( 1, - 1 ).toVar(); - getParameter( name ) { + const dirToEdge = vec2( x, y ).toVar(); + // . 2 . . 1 . + // 1 0 2 ~= 0 0 1 + // . 1 . . 0 . - return this.parameters[ name ]; + // tap 2 pixels and see which ones are "outside" the edge, to + // determine if the edge is vertical or horizontal - } + const rgbaAlongH = FxaaTexOff( uv, vec2( dirToEdge.x, dirToEdge.y ), fxaaQualityRcpFrame.xy ); + const matchAlongH = contrast( rgbaM, rgbaAlongH ).toVar(); + // . 1 . + // 0 0 1 + // . 0 H - setParameter( name, value ) { + const rgbaAlongV = FxaaTexOff( uv, vec2( dirToEdge.x.negate(), dirToEdge.y.negate() ), fxaaQualityRcpFrame.xy ); + const matchAlongV = contrast( rgbaM, rgbaAlongV ).toVar(); + // V 1 . + // 0 0 1 + // . 0 . - const parameters = this.parameters; + relativeVContrast.assign( matchAlongV.sub( matchAlongH ) ); + relativeVContrast.mulAssign( fxaaQualityinvEdgeThreshold ); - if ( value && value.isScriptableNode ) { + If( abs( relativeVContrast ).lessThan( 0.3 ), () => { // 45 deg edge - this.deleteParameter( name ); + // 1 1 . + // 0 0 1 + // . 0 1 - parameters[ name ] = value; - parameters[ name ].getDefaultOutput().events.addEventListener( 'refresh', this.onRefresh ); + // do a simple blur + const sum = rgbaN.add( rgbaS ).add( rgbaE ).add( rgbaW ); + return mix( rgbaM, sum.mul( 0.25 ), 0.4 ); - } else if ( value && value.isScriptableValueNode ) { + } ); - this.deleteParameter( name ); + } ); - parameters[ name ] = value; - parameters[ name ].events.addEventListener( 'refresh', this.onRefresh ); + const offNP = vec2().toVar(); - } else if ( parameters[ name ] === undefined ) { + If( relativeVContrast.lessThanEqual( 0 ), () => { - parameters[ name ] = scriptableValue( value ); - parameters[ name ].events.addEventListener( 'refresh', this.onRefresh ); + rgbaN.assign( rgbaW ); + rgbaS.assign( rgbaE ); - } else { + // . 0 . 1 + // 1 0 1 -> 0 + // . 0 . 1 - parameters[ name ].value = value; + offNP.x.assign( 0 ); + offNP.y.assign( fxaaQualityRcpFrame.y ); - } + } ).Else( () => { - return this; + offNP.x.assign( fxaaQualityRcpFrame.x ); + offNP.y.assign( 0 ); - } + } ); - getValue() { + const mn = contrast( rgbaM, rgbaN ).toVar(); + const ms = contrast( rgbaM, rgbaS ).toVar(); - return this.getDefaultOutput().getValue(); + If( mn.lessThanEqual( ms ), () => { - } + rgbaN.assign( rgbaS ); - deleteParameter( name ) { + } ); - let valueNode = this.parameters[ name ]; + const doneN = int( 0 ).toVar(); + const doneP = int( 0 ).toVar(); - if ( valueNode ) { + const nDist = float( 0 ).toVar(); + const pDist = float( 0 ).toVar(); - if ( valueNode.isScriptableNode ) valueNode = valueNode.getDefaultOutput(); + const posN = vec2( uv ).toVar(); + const posP = vec2( uv ).toVar(); - valueNode.events.removeEventListener( 'refresh', this.onRefresh ); + const iterationsUsedN = int( 0 ).toVar(); + const iterationsUsedP = int( 0 ).toVar(); - } + Loop( NUM_SAMPLES, ( { i } ) => { - return this; + const increment = i.add( 1 ).toVar(); - } + If( doneN.equal( 0 ), () => { - clearParameters() { + nDist.addAssign( increment ); + posN.assign( uv.add( offNP.mul( nDist ) ) ); + const rgbaEndN = FxaaTexTop( posN.xy ); - for ( const name of Object.keys( this.parameters ) ) { + const nm = contrast( rgbaEndN, rgbaM ).toVar(); + const nn = contrast( rgbaEndN, rgbaN ).toVar(); - this.deleteParameter( name ); + If( nm.greaterThan( nn ), () => { - } + doneN.assign( 1 ); - this.needsUpdate = true; + } ); - return this; + iterationsUsedN.assign( i ); - } + } ); - call( name, ...params ) { - - const object = this.getObject(); - const method = object[ name ]; + If( doneP.equal( 0 ), () => { - if ( typeof method === 'function' ) { + pDist.addAssign( increment ); + posP.assign( uv.sub( offNP.mul( pDist ) ) ); + const rgbaEndP = FxaaTexTop( posP.xy ); - return method( ...params ); + const pm = contrast( rgbaEndP, rgbaM ).toVar(); + const pn = contrast( rgbaEndP, rgbaN ).toVar(); - } + If( pm.greaterThan( pn ), () => { - } + doneP.assign( 1 ); - async callAsync( name, ...params ) { + } ); - const object = this.getObject(); - const method = object[ name ]; + iterationsUsedP.assign( i ); - if ( typeof method === 'function' ) { + } ); - return method.constructor.name === 'AsyncFunction' ? await method( ...params ) : method( ...params ); + If( doneN.equal( 1 ).or( doneP.equal( 1 ) ), () => { - } + Break(); - } + } ); - getNodeType( builder ) { + } ); - return this.getDefaultOutputNode().getNodeType( builder ); + If( doneN.equal( 0 ).and( doneP.equal( 0 ) ), () => { - } + return rgbaM; // failed to find end of edge - refresh( output = null ) { + } ); - if ( output !== null ) { + const distN = float( 1 ).toVar(); + const distP = float( 1 ).toVar(); - this.getOutput( output ).refresh(); + If( doneN.equal( 1 ), () => { - } else { + distN.assign( float( iterationsUsedN ).div( float( NUM_SAMPLES.sub( 1 ) ) ) ); - this._refresh(); + } ); - } + If( doneP.equal( 1 ), () => { - } + distP.assign( float( iterationsUsedP ).div( float( NUM_SAMPLES.sub( 1 ) ) ) ); - getObject() { + } ); - if ( this.needsUpdate ) this.dispose(); - if ( this._object !== null ) return this._object; + const dist = min$1( distN, distP ); - // + // hacky way of reduces blurriness of mostly diagonal edges + // but reduces AA quality + dist.assign( pow( dist, 0.5 ) ); + dist.assign( float( 1 ).sub( dist ) ); - const refresh = () => this.refresh(); - const setOutput = ( id, value ) => this.setOutput( id, value ); + return mix( rgbaM, rgbaN, dist.mul( 0.5 ) ); - const parameters = new Parameters( this ); + } ).setLayout( { + name: 'FxaaPixelShader', + type: 'vec4', + inputs: [ + { name: 'uv', type: 'vec2' }, + { name: 'fxaaQualityRcpFrame', type: 'vec2' }, + { name: 'fxaaQualityEdgeThreshold', type: 'float' }, + { name: 'fxaaQualityinvEdgeThreshold', type: 'float' }, + ] + } ); - const THREE = global.get( 'THREE' ); - const TSL = global.get( 'TSL' ); + const fxaa = Fn( () => { - const method = this.getMethod( this.codeNode ); - const params = [ parameters, this._local, global, refresh, setOutput, THREE, TSL ]; + const edgeDetectionQuality = float( 0.2 ); + const invEdgeDetectionQuality = float( 1 ).div( edgeDetectionQuality ); - this._object = method( ...params ); + return FxaaPixelShader( uvNode, this._invSize, edgeDetectionQuality, invEdgeDetectionQuality ); - const layout = this._object.layout; + } ); - if ( layout ) { + const outputNode = fxaa(); - if ( layout.cache === false ) { + return outputNode; - this._local.clear(); + } - } +} - // default output - this._output.outputType = layout.outputType || null; +const fxaa = ( node ) => nodeObject( new FXAANode( convertToTexture( node ) ) ); - if ( Array.isArray( layout.elements ) ) { +const _quadMesh$3 = /*@__PURE__*/ new QuadMesh(); - for ( const element of layout.elements ) { +const _clearColor$1 = /*@__PURE__*/ new Color( 0, 0, 0 ); +const _currentClearColor = /*@__PURE__*/ new Color(); +const _size$4 = /*@__PURE__*/ new Vector2(); - const id = element.id || element.name; +const _BlurDirectionX = /*@__PURE__*/ new Vector2( 1.0, 0.0 ); +const _BlurDirectionY = /*@__PURE__*/ new Vector2( 0.0, 1.0 ); - if ( element.inputType ) { +class BloomNode extends TempNode { - if ( this.getParameter( id ) === undefined ) this.setParameter( id, null ); + static get type() { - this.getParameter( id ).inputType = element.inputType; + return 'BloomNode'; - } + } - if ( element.outputType ) { + constructor( inputNode, strength = 1, radius = 0, threshold = 0 ) { - if ( this.getOutput( id ) === undefined ) this.setOutput( id, null ); + super(); - this.getOutput( id ).outputType = element.outputType; + this.inputNode = inputNode; + this.strength = uniform( strength ); + this.radius = uniform( radius ); + this.threshold = uniform( threshold ); - } + this.smoothWidth = uniform( 0.01 ); - } + // - } + this._renderTargetsHorizontal = []; + this._renderTargetsVertical = []; + this._nMips = 5; - } + // render targets - return this._object; + this._renderTargetBright = new RenderTarget( 1, 1, { type: HalfFloatType } ); + this._renderTargetBright.texture.name = 'UnrealBloomPass.bright'; + this._renderTargetBright.texture.generateMipmaps = false; - } + for ( let i = 0; i < this._nMips; i ++ ) { - deserialize( data ) { + const renderTargetHorizontal = new RenderTarget( 1, 1, { type: HalfFloatType } ); - super.deserialize( data ); + renderTargetHorizontal.texture.name = 'UnrealBloomPass.h' + i; + renderTargetHorizontal.texture.generateMipmaps = false; - for ( const name in this.parameters ) { + this._renderTargetsHorizontal.push( renderTargetHorizontal ); - let valueNode = this.parameters[ name ]; + const renderTargetVertical = new RenderTarget( 1, 1, { type: HalfFloatType } ); - if ( valueNode.isScriptableNode ) valueNode = valueNode.getDefaultOutput(); + renderTargetVertical.texture.name = 'UnrealBloomPass.v' + i; + renderTargetVertical.texture.generateMipmaps = false; - valueNode.events.addEventListener( 'refresh', this.onRefresh ); + this._renderTargetsVertical.push( renderTargetVertical ); } - } + // materials - getLayout() { + this._compositeMaterial = null; + this._highPassFilterMaterial = null; + this._separableBlurMaterials = []; - return this.getObject().layout; + // pass and texture nodes + + this._textureNodeBright = texture( this._renderTargetBright.texture ); + this._textureNodeBlur0 = texture( this._renderTargetsVertical[ 0 ].texture ); + this._textureNodeBlur1 = texture( this._renderTargetsVertical[ 1 ].texture ); + this._textureNodeBlur2 = texture( this._renderTargetsVertical[ 2 ].texture ); + this._textureNodeBlur3 = texture( this._renderTargetsVertical[ 3 ].texture ); + this._textureNodeBlur4 = texture( this._renderTargetsVertical[ 4 ].texture ); + + this._textureOutput = passTexture( this, this._renderTargetsHorizontal[ 0 ].texture ); + + this.updateBeforeType = NodeUpdateType.FRAME; } - getDefaultOutputNode() { + getTextureNode() { - const output = this.getDefaultOutput().value; + return this._textureOutput; - if ( output && output.isNode ) { + } - return output; + setSize( width, height ) { - } + let resx = Math.round( width / 2 ); + let resy = Math.round( height / 2 ); - return float(); + this._renderTargetBright.setSize( resx, resy ); - } + for ( let i = 0; i < this._nMips; i ++ ) { - getDefaultOutput() { + this._renderTargetsHorizontal[ i ].setSize( resx, resy ); + this._renderTargetsVertical[ i ].setSize( resx, resy ); - return this._exec()._output; + this._separableBlurMaterials[ i ].invSize.value.set( 1 / resx, 1 / resy ); + + resx = Math.round( resx / 2 ); + resy = Math.round( resy / 2 ); + + } } - getMethod() { + updateBefore( frame ) { - if ( this.needsUpdate ) this.dispose(); - if ( this._method !== null ) return this._method; + const { renderer } = frame; - // + const size = renderer.getDrawingBufferSize( _size$4 ); + this.setSize( size.width, size.height ); - const parametersProps = [ 'parameters', 'local', 'global', 'refresh', 'setOutput', 'THREE', 'TSL' ]; - const interfaceProps = [ 'layout', 'init', 'main', 'dispose' ]; + const currentRenderTarget = renderer.getRenderTarget(); + const currentMRT = renderer.getMRT(); + renderer.getClearColor( _currentClearColor ); + const currentClearAlpha = renderer.getClearAlpha(); - const properties = interfaceProps.join( ', ' ); - const declarations = 'var ' + properties + '; var output = {};\n'; - const returns = '\nreturn { ...output, ' + properties + ' };'; + this.setSize( size.width, size.height ); - const code = declarations + this.codeNode.code + returns; + renderer.setMRT( null ); + renderer.setClearColor( _clearColor$1, 0 ); - // + // 1. Extract Bright Areas - this._method = new Function( ...parametersProps, code ); + renderer.setRenderTarget( this._renderTargetBright ); + _quadMesh$3.material = this._highPassFilterMaterial; + _quadMesh$3.render( renderer ); - return this._method; + // 2. Blur All the mips progressively - } + let inputRenderTarget = this._renderTargetBright; - dispose() { + for ( let i = 0; i < this._nMips; i ++ ) { - if ( this._method === null ) return; + _quadMesh$3.material = this._separableBlurMaterials[ i ]; - if ( this._object && typeof this._object.dispose === 'function' ) { + this._separableBlurMaterials[ i ].colorTexture.value = inputRenderTarget.texture; + this._separableBlurMaterials[ i ].direction.value = _BlurDirectionX; + renderer.setRenderTarget( this._renderTargetsHorizontal[ i ] ); + renderer.clear(); + _quadMesh$3.render( renderer ); - this._object.dispose(); + this._separableBlurMaterials[ i ].colorTexture.value = this._renderTargetsHorizontal[ i ].texture; + this._separableBlurMaterials[ i ].direction.value = _BlurDirectionY; + renderer.setRenderTarget( this._renderTargetsVertical[ i ] ); + renderer.clear(); + _quadMesh$3.render( renderer ); + + inputRenderTarget = this._renderTargetsVertical[ i ]; } - this._method = null; - this._object = null; - this._source = null; - this._value = null; - this._needsOutputUpdate = true; - this._output.value = null; - this._outputs = {}; + // 3. Composite All the mips - } + renderer.setRenderTarget( this._renderTargetsHorizontal[ 0 ] ); + renderer.clear(); + _quadMesh$3.material = this._compositeMaterial; + _quadMesh$3.render( renderer ); - setup() { + // restore - return this.getDefaultOutputNode(); + renderer.setRenderTarget( currentRenderTarget ); + renderer.setMRT( currentMRT ); + renderer.setClearColor( _currentClearColor, currentClearAlpha ); } - getCacheKey( force ) { + setup( builder ) { - const cacheKey = [ this.source, this.getDefaultOutputNode().getCacheKey( force ) ]; + // luminosity high pass material - for ( const param in this.parameters ) { + const luminosityHighPass = Fn( () => { - cacheKey.push( this.parameters[ param ].getCacheKey( force ) ); + const texel = this.inputNode; + const v = luminance( texel.rgb ); - } + const alpha = smoothstep( this.threshold, this.threshold.add( this.smoothWidth ), v ); - return cacheKey.join( ',' ); + return mix( vec4( 0 ), texel, alpha ); - } + } ); - set needsUpdate( value ) { + this._highPassFilterMaterial = this._highPassFilterMaterial || new NodeMaterial(); + this._highPassFilterMaterial.fragmentNode = luminosityHighPass().context( builder.getSharedContext() ); + this._highPassFilterMaterial.name = 'Bloom_highPass'; + this._highPassFilterMaterial.needsUpdate = true; - if ( value === true ) this.dispose(); + // gaussian blur materials - } + const kernelSizeArray = [ 3, 5, 7, 9, 11 ]; - get needsUpdate() { + for ( let i = 0; i < this._nMips; i ++ ) { - return this.source !== this._source; + this._separableBlurMaterials.push( this._getSeperableBlurMaterial( builder, kernelSizeArray[ i ] ) ); - } + } - _exec() { + // composite material - if ( this.codeNode === null ) return this; + const bloomFactors = uniformArray( [ 1.0, 0.8, 0.6, 0.4, 0.2 ] ); + const bloomTintColors = uniformArray( [ new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ) ] ); - if ( this._needsOutputUpdate === true ) { + const lerpBloomFactor = Fn( ( [ factor, radius ] ) => { - this._value = this.call( 'main' ); + const mirrorFactor = float( 1.2 ).sub( factor ); + return mix( factor, mirrorFactor, radius ); - this._needsOutputUpdate = false; + } ).setLayout( { + name: 'lerpBloomFactor', + type: 'float', + inputs: [ + { name: 'factor', type: 'float' }, + { name: 'radius', type: 'float' }, + ] + } ); - } - this._output.value = this._value; + const compositePass = Fn( () => { - return this; + const color0 = lerpBloomFactor( bloomFactors.element( 0 ), this.radius ).mul( vec4( bloomTintColors.element( 0 ), 1.0 ) ).mul( this._textureNodeBlur0 ); + const color1 = lerpBloomFactor( bloomFactors.element( 1 ), this.radius ).mul( vec4( bloomTintColors.element( 1 ), 1.0 ) ).mul( this._textureNodeBlur1 ); + const color2 = lerpBloomFactor( bloomFactors.element( 2 ), this.radius ).mul( vec4( bloomTintColors.element( 2 ), 1.0 ) ).mul( this._textureNodeBlur2 ); + const color3 = lerpBloomFactor( bloomFactors.element( 3 ), this.radius ).mul( vec4( bloomTintColors.element( 3 ), 1.0 ) ).mul( this._textureNodeBlur3 ); + const color4 = lerpBloomFactor( bloomFactors.element( 4 ), this.radius ).mul( vec4( bloomTintColors.element( 4 ), 1.0 ) ).mul( this._textureNodeBlur4 ); - } + const sum = color0.add( color1 ).add( color2 ).add( color3 ).add( color4 ); - _refresh() { + return sum.mul( this.strength ); - this.needsUpdate = true; + } ); - this._exec(); + this._compositeMaterial = this._compositeMaterial || new NodeMaterial(); + this._compositeMaterial.fragmentNode = compositePass().context( builder.getSharedContext() ); + this._compositeMaterial.name = 'Bloom_comp'; + this._compositeMaterial.needsUpdate = true; - this._output.refresh(); + // + + return this._textureOutput; } -} + dispose() { -ScriptableNode.type = /*@__PURE__*/ registerNode( 'Scriptable', ScriptableNode ); + for ( let i = 0; i < this._renderTargetsHorizontal.length; i ++ ) { -const scriptable = /*@__PURE__*/ nodeProxy( ScriptableNode ); + this._renderTargetsHorizontal[ i ].dispose(); -class FogNode extends Node { + } - constructor( colorNode, factorNode ) { + for ( let i = 0; i < this._renderTargetsVertical.length; i ++ ) { - super( 'float' ); + this._renderTargetsVertical[ i ].dispose(); - this.isFogNode = true; + } - this.colorNode = colorNode; - this.factorNode = factorNode; + this._renderTargetBright.dispose(); } - getViewZNode( builder ) { - - let viewZ; + _getSeperableBlurMaterial( builder, kernelRadius ) { - const getViewZ = builder.context.getViewZ; + const coefficients = []; - if ( getViewZ !== undefined ) { + for ( let i = 0; i < kernelRadius; i ++ ) { - viewZ = getViewZ( this ); + coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius ); } - return ( viewZ || positionView.z ).negate(); + // - } + const colorTexture = texture(); + const gaussianCoefficients = uniformArray( coefficients ); + const invSize = uniform( new Vector2() ); + const direction = uniform( new Vector2( 0.5, 0.5 ) ); - setup() { + const uvNode = uv(); + const sampleTexel = ( uv ) => colorTexture.uv( uv ); - return this.factorNode; + const seperableBlurPass = Fn( () => { - } + const weightSum = gaussianCoefficients.element( 0 ).toVar(); + const diffuseSum = sampleTexel( uvNode ).rgb.mul( weightSum ).toVar(); -} + Loop( { start: int( 1 ), end: int( kernelRadius ), type: 'int', condition: '<' }, ( { i } ) => { -FogNode.type = /*@__PURE__*/ registerNode( 'Fog', FogNode ); + const x = float( i ); + const w = gaussianCoefficients.element( i ); + const uvOffset = direction.mul( invSize ).mul( x ); + const sample1 = sampleTexel( uvNode.add( uvOffset ) ).rgb; + const sample2 = sampleTexel( uvNode.sub( uvOffset ) ).rgb; + diffuseSum.addAssign( add( sample1, sample2 ).mul( w ) ); + weightSum.addAssign( float( 2.0 ).mul( w ) ); -const fog = /*@__PURE__*/ nodeProxy( FogNode ); + } ); -class FogRangeNode extends FogNode { + return vec4( diffuseSum.div( weightSum ), 1.0 ); - constructor( colorNode, nearNode, farNode ) { + } ); - super( colorNode ); + const seperableBlurMaterial = new NodeMaterial(); + seperableBlurMaterial.fragmentNode = seperableBlurPass().context( builder.getSharedContext() ); + seperableBlurMaterial.name = 'Bloom_seperable'; + seperableBlurMaterial.needsUpdate = true; - this.isFogRangeNode = true; + // uniforms + seperableBlurMaterial.colorTexture = colorTexture; + seperableBlurMaterial.direction = direction; + seperableBlurMaterial.invSize = invSize; - this.nearNode = nearNode; - this.farNode = farNode; + return seperableBlurMaterial; } - setup( builder ) { +} - const viewZ = this.getViewZNode( builder ); +const bloom = ( node, strength, radius, threshold ) => nodeObject( new BloomNode( nodeObject( node ), strength, radius, threshold ) ); - return smoothstep( this.nearNode, this.farNode, viewZ ); +class TransitionNode extends TempNode { - } + static get type() { -} + return 'TransitionNode'; -FogRangeNode.type = /*@__PURE__*/ registerNode( 'FogRange', FogRangeNode ); + } -const rangeFog = /*@__PURE__*/ nodeProxy( FogRangeNode ); + constructor( textureNodeA, textureNodeB, mixTextureNode, mixRatioNode, thresholdNode, useTextureNode ) { -class FogExp2Node extends FogNode { + super(); - constructor( colorNode, densityNode ) { + // Input textures - super( colorNode ); + this.textureNodeA = textureNodeA; + this.textureNodeB = textureNodeB; + this.mixTextureNode = mixTextureNode; - this.isFogExp2Node = true; + // Uniforms - this.densityNode = densityNode; + this.mixRatioNode = mixRatioNode; + this.thresholdNode = thresholdNode; + this.useTextureNode = useTextureNode; } - setup( builder ) { - - const viewZ = this.getViewZNode( builder ); - const density = this.densityNode; + setup() { - return density.mul( density, viewZ, viewZ ).negate().exp().oneMinus(); + const { textureNodeA, textureNodeB, mixTextureNode, mixRatioNode, thresholdNode, useTextureNode } = this; - } + const sampleTexture = ( textureNode ) => { -} + const uvNodeTexture = textureNode.uvNode || uv(); + return textureNode.uv( uvNodeTexture ); -FogExp2Node.type = /*@__PURE__*/ registerNode( 'FogExp2', FogExp2Node ); + }; -const densityFog = /*@__PURE__*/ nodeProxy( FogExp2Node ); + const transition = Fn( () => { -let min = null; -let max = null; + const texelOne = sampleTexture( textureNodeA ); + const texelTwo = sampleTexture( textureNodeB ); -class RangeNode extends Node { + const color = vec4().toVar(); - constructor( minNode = float(), maxNode = float() ) { + If( useTextureNode.equal( int( 1 ) ), () => { - super(); + const transitionTexel = sampleTexture( mixTextureNode ); + const r = mixRatioNode.mul( thresholdNode.mul( 2.0 ).add( 1.0 ) ).sub( thresholdNode ); + const mixf = clamp( sub( transitionTexel.r, r ).mul( float( 1.0 ).div( thresholdNode ) ), 0.0, 1.0 ); - this.minNode = minNode; - this.maxNode = maxNode; + color.assign( mix( texelOne, texelTwo, mixf ) ); - } + } ).Else( () => { - getVectorLength( builder ) { + color.assign( mix( texelTwo, texelOne, mixRatioNode ) ); - const minLength = builder.getTypeLength( getValueType( this.minNode.value ) ); - const maxLength = builder.getTypeLength( getValueType( this.maxNode.value ) ); + } ); - return minLength > maxLength ? minLength : maxLength; + return color; - } + } ); - getNodeType( builder ) { + const outputNode = transition(); - return builder.object.count > 1 ? builder.getTypeFromLength( this.getVectorLength( builder ) ) : 'float'; + return outputNode; } - setup( builder ) { +} - const object = builder.object; +const transition = ( nodeA, nodeB, mixTexture, mixRatio = 0.0, threshold = 0.1, useTexture = 0 ) => nodeObject( new TransitionNode( convertToTexture( nodeA ), convertToTexture( nodeB ), convertToTexture( mixTexture ), nodeObject( mixRatio ), nodeObject( threshold ), nodeObject( useTexture ) ) ); - let output = null; +class PixelationNode extends TempNode { - if ( object.count > 1 ) { + static get type() { - const minValue = this.minNode.value; - const maxValue = this.maxNode.value; + return 'PixelationNode'; - const minLength = builder.getTypeLength( getValueType( minValue ) ); - const maxLength = builder.getTypeLength( getValueType( maxValue ) ); + } - min = min || new Vector4(); - max = max || new Vector4(); + constructor( textureNode, depthNode, normalNode, pixelSize, normalEdgeStrength, depthEdgeStrength ) { - min.setScalar( 0 ); - max.setScalar( 0 ); + super(); - if ( minLength === 1 ) min.setScalar( minValue ); - else if ( minValue.isColor ) min.set( minValue.r, minValue.g, minValue.b ); - else min.set( minValue.x, minValue.y, minValue.z || 0, minValue.w || 0 ); + // Input textures - if ( maxLength === 1 ) max.setScalar( maxValue ); - else if ( maxValue.isColor ) max.set( maxValue.r, maxValue.g, maxValue.b ); - else max.set( maxValue.x, maxValue.y, maxValue.z || 0, maxValue.w || 0 ); + this.textureNode = textureNode; + this.depthNode = depthNode; + this.normalNode = normalNode; - const stride = 4; + // Input uniforms - const length = stride * object.count; - const array = new Float32Array( length ); + this.pixelSize = pixelSize; + this.normalEdgeStrength = normalEdgeStrength; + this.depthEdgeStrength = depthEdgeStrength; - for ( let i = 0; i < length; i ++ ) { + // Private uniforms - const index = i % stride; + this._resolution = uniform( new Vector4() ); - const minElementValue = min.getComponent( index ); - const maxElementValue = max.getComponent( index ); + this.updateBeforeType = NodeUpdateType.RENDER; - array[ i ] = MathUtils.lerp( minElementValue, maxElementValue, Math.random() ); + } - } + updateBefore() { - const nodeType = this.getNodeType( builder ); - - if ( object.count <= 4096 ) { + const map = this.textureNode.value; - output = buffer( array, 'vec4', object.count ).element( instanceIndex ).convert( nodeType ); + const width = map.image.width; + const height = map.image.height; - } else { + this._resolution.value.set( width, height, 1 / width, 1 / height ); - // TODO: Improve anonymous buffer attribute creation removing this part - const bufferAttribute = new InstancedBufferAttribute( array, 4 ); - builder.geometry.setAttribute( '__range' + this.id, bufferAttribute ); + } - output = instancedBufferAttribute( bufferAttribute ).convert( nodeType ); + setup() { - } + const { textureNode, depthNode, normalNode } = this; - } else { + const uvNodeTexture = textureNode.uvNode || uv(); + const uvNodeDepth = depthNode.uvNode || uv(); + const uvNodeNormal = normalNode.uvNode || uv(); - output = float( 0 ); + const sampleTexture = () => textureNode.uv( uvNodeTexture ); - } + const sampleDepth = ( x, y ) => depthNode.uv( uvNodeDepth.add( vec2( x, y ).mul( this._resolution.zw ) ) ).r; - return output; + const sampleNormal = ( x, y ) => normalNode.uv( uvNodeNormal.add( vec2( x, y ).mul( this._resolution.zw ) ) ).rgb.normalize(); - } + const depthEdgeIndicator = ( depth ) => { -} + const diff = property( 'float', 'diff' ); + diff.addAssign( clamp( sampleDepth( 1, 0 ).sub( depth ) ) ); + diff.addAssign( clamp( sampleDepth( - 1, 0 ).sub( depth ) ) ); + diff.addAssign( clamp( sampleDepth( 0, 1 ).sub( depth ) ) ); + diff.addAssign( clamp( sampleDepth( 0, - 1 ).sub( depth ) ) ); -RangeNode.type = /*@__PURE__*/ registerNode( 'Range', RangeNode ); + return floor( smoothstep( 0.01, 0.02, diff ).mul( 2 ) ).div( 2 ); -const range = /*@__PURE__*/ nodeProxy( RangeNode ); + }; -class LightNode extends Node { + const neighborNormalEdgeIndicator = ( x, y, depth, normal ) => { - constructor( scope = LightNode.TARGET_DIRECTION, light = null ) { + const depthDiff = sampleDepth( x, y ).sub( depth ); + const neighborNormal = sampleNormal( x, y ); - super(); + // Edge pixels should yield to faces who's normals are closer to the bias normal. - this.scope = scope; - this.light = light; + const normalEdgeBias = vec3( 1, 1, 1 ); // This should probably be a parameter. + const normalDiff = dot( normal.sub( neighborNormal ), normalEdgeBias ); + const normalIndicator = clamp( smoothstep( - 0.01, 0.01, normalDiff ), 0.0, 1.0 ); - } + // Only the shallower pixel should detect the normal edge. - setup() { + const depthIndicator = clamp( sign( depthDiff.mul( .25 ).add( .0025 ) ), 0.0, 1.0 ); - const { scope, light } = this; + return float( 1.0 ).sub( dot( normal, neighborNormal ) ).mul( depthIndicator ).mul( normalIndicator ); - let output = null; + }; - if ( scope === LightNode.TARGET_DIRECTION ) { + const normalEdgeIndicator = ( depth, normal ) => { - output = cameraViewMatrix.transformDirection( objectPosition( light ).sub( objectPosition( light.target ) ) ); + const indicator = property( 'float', 'indicator' ); - } + indicator.addAssign( neighborNormalEdgeIndicator( 0, - 1, depth, normal ) ); + indicator.addAssign( neighborNormalEdgeIndicator( 0, 1, depth, normal ) ); + indicator.addAssign( neighborNormalEdgeIndicator( - 1, 0, depth, normal ) ); + indicator.addAssign( neighborNormalEdgeIndicator( 1, 0, depth, normal ) ); - return output; + return step( 0.1, indicator ); - } + }; - serialize( data ) { + const pixelation = Fn( () => { - super.serialize( data ); + const texel = sampleTexture(); - data.scope = this.scope; + const depth = property( 'float', 'depth' ); + const normal = property( 'vec3', 'normal' ); - } + If( this.depthEdgeStrength.greaterThan( 0.0 ).or( this.normalEdgeStrength.greaterThan( 0.0 ) ), () => { - deserialize( data ) { + depth.assign( sampleDepth( 0, 0 ) ); + normal.assign( sampleNormal( 0, 0 ) ); - super.deserialize( data ); + } ); - this.scope = data.scope; + const dei = property( 'float', 'dei' ); - } + If( this.depthEdgeStrength.greaterThan( 0.0 ), () => { -} + dei.assign( depthEdgeIndicator( depth ) ); -LightNode.TARGET_DIRECTION = 'targetDirection'; + } ); -LightNode.type = /*@__PURE__*/ registerNode( 'Light', LightNode ); + const nei = property( 'float', 'nei' ); -const lightTargetDirection = /*@__PURE__*/ nodeProxy( LightNode, LightNode.TARGET_DIRECTION ); + If( this.normalEdgeStrength.greaterThan( 0.0 ), () => { -const BasicShadowMap = Fn( ( { depthTexture, shadowCoord } ) => { + nei.assign( normalEdgeIndicator( depth, normal ) ); - return texture( depthTexture, shadowCoord.xy ).compare( shadowCoord.z ); + } ); -} ); + const strength = dei.greaterThan( 0 ).select( float( 1.0 ).sub( dei.mul( this.depthEdgeStrength ) ), nei.mul( this.normalEdgeStrength ).add( 1 ) ); -const PCFShadowMap = Fn( ( { depthTexture, shadowCoord, shadow } ) => { + return texel.mul( strength ); - const depthCompare = ( uv, compare ) => texture( depthTexture, uv ).compare( compare ); + } ); - const mapSize = reference( 'mapSize', 'vec2', shadow ); - const radius = reference( 'radius', 'float', shadow ); + const outputNode = pixelation(); - const texelSize = vec2( 1 ).div( mapSize ); - const dx0 = texelSize.x.negate().mul( radius ); - const dy0 = texelSize.y.negate().mul( radius ); - const dx1 = texelSize.x.mul( radius ); - const dy1 = texelSize.y.mul( radius ); - const dx2 = dx0.div( 2 ); - const dy2 = dy0.div( 2 ); - const dx3 = dx1.div( 2 ); - const dy3 = dy1.div( 2 ); + return outputNode; - return add( - depthCompare( shadowCoord.xy.add( vec2( dx0, dy0 ) ), shadowCoord.z ), - depthCompare( shadowCoord.xy.add( vec2( 0, dy0 ) ), shadowCoord.z ), - depthCompare( shadowCoord.xy.add( vec2( dx1, dy0 ) ), shadowCoord.z ), - depthCompare( shadowCoord.xy.add( vec2( dx2, dy2 ) ), shadowCoord.z ), - depthCompare( shadowCoord.xy.add( vec2( 0, dy2 ) ), shadowCoord.z ), - depthCompare( shadowCoord.xy.add( vec2( dx3, dy2 ) ), shadowCoord.z ), - depthCompare( shadowCoord.xy.add( vec2( dx0, 0 ) ), shadowCoord.z ), - depthCompare( shadowCoord.xy.add( vec2( dx2, 0 ) ), shadowCoord.z ), - depthCompare( shadowCoord.xy, shadowCoord.z ), - depthCompare( shadowCoord.xy.add( vec2( dx3, 0 ) ), shadowCoord.z ), - depthCompare( shadowCoord.xy.add( vec2( dx1, 0 ) ), shadowCoord.z ), - depthCompare( shadowCoord.xy.add( vec2( dx2, dy3 ) ), shadowCoord.z ), - depthCompare( shadowCoord.xy.add( vec2( 0, dy3 ) ), shadowCoord.z ), - depthCompare( shadowCoord.xy.add( vec2( dx3, dy3 ) ), shadowCoord.z ), - depthCompare( shadowCoord.xy.add( vec2( dx0, dy1 ) ), shadowCoord.z ), - depthCompare( shadowCoord.xy.add( vec2( 0, dy1 ) ), shadowCoord.z ), - depthCompare( shadowCoord.xy.add( vec2( dx1, dy1 ) ), shadowCoord.z ) - ).mul( 1 / 17 ); + } -} ); +} -const PCFSoftShadowMap = Fn( ( { depthTexture, shadowCoord, shadow } ) => { +const pixelation = ( node, depthNode, normalNode, pixelSize = 6, normalEdgeStrength = 0.3, depthEdgeStrength = 0.4 ) => nodeObject( new PixelationNode( convertToTexture( node ), convertToTexture( depthNode ), convertToTexture( normalNode ), nodeObject( pixelSize ), nodeObject( normalEdgeStrength ), nodeObject( depthEdgeStrength ) ) ); - const depthCompare = ( uv, compare ) => texture( depthTexture, uv ).compare( compare ); +class PixelationPassNode extends PassNode { - const mapSize = reference( 'mapSize', 'vec2', shadow ); + static get type() { - const texelSize = vec2( 1 ).div( mapSize ); - const dx = texelSize.x; - const dy = texelSize.y; + return 'PixelationPassNode'; - const uv = shadowCoord.xy; - const f = fract( uv.mul( mapSize ).add( 0.5 ) ); - uv.subAssign( f.mul( texelSize ) ); + } - return add( - depthCompare( uv, shadowCoord.z ), - depthCompare( uv.add( vec2( dx, 0 ) ), shadowCoord.z ), - depthCompare( uv.add( vec2( 0, dy ) ), shadowCoord.z ), - depthCompare( uv.add( texelSize ), shadowCoord.z ), - mix( - depthCompare( uv.add( vec2( dx.negate(), 0 ) ), shadowCoord.z ), - depthCompare( uv.add( vec2( dx.mul( 2 ), 0 ) ), shadowCoord.z ), - f.x - ), - mix( - depthCompare( uv.add( vec2( dx.negate(), dy ) ), shadowCoord.z ), - depthCompare( uv.add( vec2( dx.mul( 2 ), dy ) ), shadowCoord.z ), - f.x - ), - mix( - depthCompare( uv.add( vec2( 0, dy.negate() ) ), shadowCoord.z ), - depthCompare( uv.add( vec2( 0, dy.mul( 2 ) ) ), shadowCoord.z ), - f.y - ), - mix( - depthCompare( uv.add( vec2( dx, dy.negate() ) ), shadowCoord.z ), - depthCompare( uv.add( vec2( dx, dy.mul( 2 ) ) ), shadowCoord.z ), - f.y - ), - mix( - mix( - depthCompare( uv.add( vec2( dx.negate(), dy.negate() ) ), shadowCoord.z ), - depthCompare( uv.add( vec2( dx.mul( 2 ), dy.negate() ) ), shadowCoord.z ), - f.x - ), - mix( - depthCompare( uv.add( vec2( dx.negate(), dy.mul( 2 ) ) ), shadowCoord.z ), - depthCompare( uv.add( vec2( dx.mul( 2 ), dy.mul( 2 ) ) ), shadowCoord.z ), - f.x - ), - f.y - ) - ).mul( 1 / 9 ); + constructor( scene, camera, pixelSize = 6, normalEdgeStrength = 0.3, depthEdgeStrength = 0.4 ) { -} ); + super( 'color', scene, camera, { minFilter: NearestFilter, magFilter: NearestFilter } ); -const shadowFilterLib = [ BasicShadowMap, PCFShadowMap, PCFSoftShadowMap ]; + this.pixelSize = pixelSize; + this.normalEdgeStrength = normalEdgeStrength; + this.depthEdgeStrength = depthEdgeStrength; -// + this.isPixelationPassNode = true; -let overrideMaterial = null; + this._mrt = mrt( { + output: output, + normal: normalView + } ); -class AnalyticLightNode extends LightingNode { + } - constructor( light = null ) { + setSize( width, height ) { - super(); + const pixelSize = this.pixelSize.value ? this.pixelSize.value : this.pixelSize; - this.updateType = NodeUpdateType.FRAME; + const adjustedWidth = Math.floor( width / pixelSize ); + const adjustedHeight = Math.floor( height / pixelSize ); - this.light = light; + super.setSize( adjustedWidth, adjustedHeight ); - this.color = new Color(); - this.colorNode = uniform( this.color ); + } - this.baseColorNode = null; + setup() { - this.shadowMap = null; - this.shadowNode = null; - this.shadowColorNode = null; + const color = super.getTextureNode( 'output' ); + const depth = super.getTextureNode( 'depth' ); + const normal = super.getTextureNode( 'normal' ); - this.isAnalyticLightNode = true; + return pixelation( color, depth, normal, this.pixelSize, this.normalEdgeStrength, this.depthEdgeStrength ); } - getCacheKey() { +} - return super.getCacheKey() + '-' + ( this.light.id + '-' + ( this.light.castShadow ? '1' : '0' ) ); +const pixelationPass = ( scene, camera, pixelSize, normalEdgeStrength, depthEdgeStrength ) => nodeObject( new PixelationPassNode( scene, camera, pixelSize, normalEdgeStrength, depthEdgeStrength ) ); - } +const _size$3 = /*@__PURE__*/ new Vector2(); - getHash() { +/** +* +* Supersample Anti-Aliasing Render Pass +* +* This manual approach to SSAA re-renders the scene ones for each sample with camera jitter and accumulates the results. +* +* References: https://en.wikipedia.org/wiki/Supersampling +* +*/ - return this.light.uuid; +class SSAAPassNode extends PassNode { + + static get type() { + + return 'SSAAPassNode'; } - setupShadow( builder ) { + constructor( scene, camera ) { - const { object, renderer } = builder; + super( PassNode.COLOR, scene, camera ); - let shadowColorNode = this.shadowColorNode; + this.isSSAAPassNode = true; - if ( shadowColorNode === null ) { + this.sampleLevel = 4; // specified as n, where the number of samples is 2^n, so sampleLevel = 4, is 2^4 samples, 16. + this.unbiased = true; + this.clearColor = new Color( 0x000000 ); + this.clearAlpha = 0; - if ( overrideMaterial === null ) { + this._currentClearColor = new Color(); - overrideMaterial = new NodeMaterial(); - overrideMaterial.fragmentNode = vec4( 0, 0, 0, 1 ); - overrideMaterial.isShadowNodeMaterial = true; // Use to avoid other overrideMaterial override material.fragmentNode unintentionally when using material.shadowNode - overrideMaterial.name = 'ShadowMaterial'; + this.sampleWeight = uniform( 1 ); - } + this.sampleRenderTarget = null; - const depthTexture = new DepthTexture(); - depthTexture.compareFunction = LessCompare; + this._quadMesh = new QuadMesh(); - const shadow = this.light.shadow; - const shadowMap = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height ); - shadowMap.depthTexture = depthTexture; + } - shadow.camera.updateProjectionMatrix(); + updateBefore( frame ) { - // + const { renderer } = frame; + const { scene, camera } = this; - const shadowIntensity = reference( 'intensity', 'float', shadow ); - const bias = reference( 'bias', 'float', shadow ); - const normalBias = reference( 'normalBias', 'float', shadow ); + this._pixelRatio = renderer.getPixelRatio(); - const position = object.material.shadowPositionNode || positionWorld; + const size = renderer.getSize( _size$3 ); - let shadowCoord = uniform( shadow.matrix ).mul( position.add( normalWorld.mul( normalBias ) ) ); - shadowCoord = shadowCoord.xyz.div( shadowCoord.w ); + this.setSize( size.width, size.height ); + this.sampleRenderTarget.setSize( this.renderTarget.width, this.renderTarget.height ); - let coordZ = shadowCoord.z.add( bias ); + // save current renderer settings - if ( renderer.coordinateSystem === WebGPUCoordinateSystem ) { + renderer.getClearColor( this._currentClearColor ); + const currentClearAlpha = renderer.getClearAlpha(); + const currentRenderTarget = renderer.getRenderTarget(); + const currentMRT = renderer.getMRT(); + const currentAutoClear = renderer.autoClear; - coordZ = coordZ.mul( 2 ).sub( 1 ); // WebGPU: Convertion [ 0, 1 ] to [ - 1, 1 ] + // - } + this._cameraNear.value = camera.near; + this._cameraFar.value = camera.far; - shadowCoord = vec3( - shadowCoord.x, - shadowCoord.y.oneMinus(), // follow webgpu standards - coordZ - ); + renderer.setMRT( this.getMRT() ); + renderer.autoClear = false; - const frustumTest = shadowCoord.x.greaterThanEqual( 0 ) - .and( shadowCoord.x.lessThanEqual( 1 ) ) - .and( shadowCoord.y.greaterThanEqual( 0 ) ) - .and( shadowCoord.y.lessThanEqual( 1 ) ) - .and( shadowCoord.z.lessThanEqual( 1 ) ); + const jitterOffsets = _JitterVectors[ Math.max( 0, Math.min( this.sampleLevel, 5 ) ) ]; - // + const baseSampleWeight = 1.0 / jitterOffsets.length; + const roundingRange = 1 / 32; - const filterFn = shadow.filterNode || shadowFilterLib[ renderer.shadowMap.type ] || null; + const viewOffset = { - if ( filterFn === null ) { + fullWidth: this.renderTarget.width, + fullHeight: this.renderTarget.height, + offsetX: 0, + offsetY: 0, + width: this.renderTarget.width, + height: this.renderTarget.height - throw new Error( 'THREE.WebGPURenderer: Shadow map type not supported yet.' ); + }; - } + const originalViewOffset = Object.assign( {}, camera.view ); - const shadowColor = texture( shadowMap.texture, shadowCoord ); - const shadowNode = frustumTest.select( filterFn( { depthTexture, shadowCoord, shadow } ), float( 1 ) ); + if ( originalViewOffset.enabled ) Object.assign( viewOffset, originalViewOffset ); - this.shadowMap = shadowMap; + // render the scene multiple times, each slightly jitter offset from the last and accumulate the results. - this.shadowNode = shadowNode; - this.shadowColorNode = shadowColorNode = this.colorNode.mul( mix( 1, shadowNode.rgb.mix( shadowColor, 1 ), shadowIntensity.mul( shadowColor.a ) ) ); + for ( let i = 0; i < jitterOffsets.length; i ++ ) { - this.baseColorNode = this.colorNode; + const jitterOffset = jitterOffsets[ i ]; - } + if ( camera.setViewOffset ) { - // + camera.setViewOffset( - this.colorNode = shadowColorNode; + viewOffset.fullWidth, viewOffset.fullHeight, - this.updateBeforeType = NodeUpdateType.RENDER; + viewOffset.offsetX + jitterOffset[ 0 ] * 0.0625, viewOffset.offsetY + jitterOffset[ 1 ] * 0.0625, // 0.0625 = 1 / 16 - } + viewOffset.width, viewOffset.height - setup( builder ) { + ); - this.colorNode = this.baseColorNode || this.colorNode; + } - if ( this.light.castShadow ) { + this.sampleWeight.value = baseSampleWeight; - if ( builder.object.receiveShadow ) { + if ( this.unbiased ) { - this.setupShadow( builder ); + // the theory is that equal weights for each sample lead to an accumulation of rounding errors. + // The following equation varies the sampleWeight per sample so that it is uniformly distributed + // across a range of values whose rounding errors cancel each other out. + + const uniformCenteredDistribution = ( - 0.5 + ( i + 0.5 ) / jitterOffsets.length ); + this.sampleWeight.value += roundingRange * uniformCenteredDistribution; } - } else if ( this.shadowNode !== null ) { + renderer.setClearColor( this.clearColor, this.clearAlpha ); + renderer.setRenderTarget( this.sampleRenderTarget ); + renderer.clear(); + renderer.render( scene, camera ); - this.disposeShadow(); + // accumulation - } + renderer.setRenderTarget( this.renderTarget ); - } + if ( i === 0 ) { - updateShadow( frame ) { + renderer.setClearColor( 0x000000, 0.0 ); + renderer.clear(); - const { shadowMap, light } = this; - const { renderer, scene, camera } = frame; + } + this._quadMesh.render( renderer ); - const depthVersion = shadowMap.depthTexture.version; - this._depthVersionCached = depthVersion; + } - const currentOverrideMaterial = scene.overrideMaterial; + renderer.copyTextureToTexture( this.sampleRenderTarget.depthTexture, this.renderTarget.depthTexture ); - scene.overrideMaterial = overrideMaterial; + // restore - shadowMap.setSize( light.shadow.mapSize.width, light.shadow.mapSize.height ); + if ( camera.setViewOffset && originalViewOffset.enabled ) { - light.shadow.updateMatrices( light ); - light.shadow.camera.layers.mask = camera.layers.mask; + camera.setViewOffset( - const currentRenderTarget = renderer.getRenderTarget(); - const currentRenderObjectFunction = renderer.getRenderObjectFunction(); + originalViewOffset.fullWidth, originalViewOffset.fullHeight, - renderer.setRenderObjectFunction( ( object, ...params ) => { + originalViewOffset.offsetX, originalViewOffset.offsetY, - if ( object.castShadow === true ) { + originalViewOffset.width, originalViewOffset.height - renderer.renderObject( object, ...params ); + ); - } + } else if ( camera.clearViewOffset ) { - } ); + camera.clearViewOffset(); - renderer.setRenderTarget( shadowMap ); - renderer.render( scene, light.shadow.camera ); + } renderer.setRenderTarget( currentRenderTarget ); - renderer.setRenderObjectFunction( currentRenderObjectFunction ); + renderer.setMRT( currentMRT ); - scene.overrideMaterial = currentOverrideMaterial; + renderer.autoClear = currentAutoClear; + renderer.setClearColor( this._currentClearColor, currentClearAlpha ); } - disposeShadow() { + setup( builder ) { - this.shadowMap.dispose(); - this.shadowMap = null; + if ( this.sampleRenderTarget === null ) { - this.shadowNode = null; - this.shadowColorNode = null; + this.sampleRenderTarget = this.renderTarget.clone(); - this.baseColorNode = null; + } - this.updateBeforeType = NodeUpdateType.NONE; + let sampleTexture; - } + const passMRT = this.getMRT(); - updateBefore( frame ) { + if ( passMRT !== null ) { - const shadow = this.light.shadow; + const outputs = {}; - const needsUpdate = shadow.needsUpdate || shadow.autoUpdate; + for ( const name in passMRT.outputNodes ) { - if ( needsUpdate ) { + const index = getTextureIndex( this.sampleRenderTarget.textures, name ); - this.updateShadow( frame ); + if ( index >= 0 ) { - if ( this.shadowMap.depthTexture.version === this._depthVersionCached ) { + outputs[ name ] = texture( this.sampleRenderTarget.textures[ index ] ).mul( this.sampleWeight ); - shadow.needsUpdate = false; + } } - } + sampleTexture = mrt( outputs ); - } + } else { - update( /*frame*/ ) { + sampleTexture = texture( this.sampleRenderTarget.texture ).mul( this.sampleWeight ); - const { light } = this; + } - this.color.copy( light.color ).multiplyScalar( light.intensity ); + this._quadMesh.material = new NodeMaterial(); + this._quadMesh.material.fragmentNode = sampleTexture; + this._quadMesh.material.transparent = true; + this._quadMesh.material.depthTest = false; + this._quadMesh.material.depthWrite = false; + this._quadMesh.material.premultipliedAlpha = true; + this._quadMesh.material.blending = AdditiveBlending; + this._quadMesh.material.normals = false; + this._quadMesh.material.name = 'SSAA'; + + return super.setup( builder ); } -} + dispose() { -AnalyticLightNode.type = /*@__PURE__*/ registerNode( 'AnalyticLight', AnalyticLightNode ); + super.dispose(); -const getDistanceAttenuation = /*@__PURE__*/ Fn( ( inputs ) => { + if ( this.sampleRenderTarget !== null ) { - const { lightDistance, cutoffDistance, decayExponent } = inputs; + this.sampleRenderTarget.dispose(); - // based upon Frostbite 3 Moving to Physically-based Rendering - // page 32, equation 26: E[window1] - // https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf - const distanceFalloff = lightDistance.pow( decayExponent ).max( 0.01 ).reciprocal(); + } - return cutoffDistance.greaterThan( 0 ).select( - distanceFalloff.mul( lightDistance.div( cutoffDistance ).pow4().oneMinus().clamp().pow2() ), - distanceFalloff - ); + } -} ); // validated +} -class PointLightNode extends AnalyticLightNode { +// These jitter vectors are specified in integers because it is easier. +// I am assuming a [-8,8) integer grid, but it needs to be mapped onto [-0.5,0.5) +// before being used, thus these integers need to be scaled by 1/16. +// +// Sample patterns reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 +const _JitterVectors = [ + [ + [ 0, 0 ] + ], + [ + [ 4, 4 ], [ - 4, - 4 ] + ], + [ + [ - 2, - 6 ], [ 6, - 2 ], [ - 6, 2 ], [ 2, 6 ] + ], + [ + [ 1, - 3 ], [ - 1, 3 ], [ 5, 1 ], [ - 3, - 5 ], + [ - 5, 5 ], [ - 7, - 1 ], [ 3, 7 ], [ 7, - 7 ] + ], + [ + [ 1, 1 ], [ - 1, - 3 ], [ - 3, 2 ], [ 4, - 1 ], + [ - 5, - 2 ], [ 2, 5 ], [ 5, 3 ], [ 3, - 5 ], + [ - 2, 6 ], [ 0, - 7 ], [ - 4, - 6 ], [ - 6, 4 ], + [ - 8, 0 ], [ 7, - 4 ], [ 6, 7 ], [ - 7, - 8 ] + ], + [ + [ - 4, - 7 ], [ - 7, - 5 ], [ - 3, - 5 ], [ - 5, - 4 ], + [ - 1, - 4 ], [ - 2, - 2 ], [ - 6, - 1 ], [ - 4, 0 ], + [ - 7, 1 ], [ - 1, 2 ], [ - 6, 3 ], [ - 3, 3 ], + [ - 7, 6 ], [ - 3, 6 ], [ - 5, 7 ], [ - 1, 7 ], + [ 5, - 7 ], [ 1, - 6 ], [ 6, - 5 ], [ 4, - 4 ], + [ 2, - 3 ], [ 7, - 2 ], [ 1, - 1 ], [ 4, - 1 ], + [ 2, 1 ], [ 6, 2 ], [ 0, 4 ], [ 4, 4 ], + [ 2, 5 ], [ 7, 5 ], [ 5, 6 ], [ 3, 7 ] + ] +]; - constructor( light = null ) { +const ssaaPass = ( scene, camera ) => nodeObject( new SSAAPassNode( scene, camera ) ); - super( light ); +const _size$2 = /*@__PURE__*/ new Vector2(); - this.cutoffDistanceNode = uniform( 0 ); - this.decayExponentNode = uniform( 0 ); +class StereoPassNode extends PassNode { - } + static get type() { - update( frame ) { + return 'StereoPassNode'; - const { light } = this; + } - super.update( frame ); + constructor( scene, camera ) { - this.cutoffDistanceNode.value = light.distance; - this.decayExponentNode.value = light.decay; + super( PassNode.COLOR, scene, camera ); - } + this.isStereoPassNode = true; - setup( builder ) { - - const { colorNode, cutoffDistanceNode, decayExponentNode, light } = this; + this.stereo = new StereoCamera(); + this.stereo.aspect = 0.5; - const lightingModel = builder.context.lightingModel; + } - const lVector = objectViewPosition( light ).sub( positionView ); // @TODO: Add it into LightNode + updateBefore( frame ) { - const lightDirection = lVector.normalize(); - const lightDistance = lVector.length(); + const { renderer } = frame; + const { scene, camera, stereo, renderTarget } = this; - const lightAttenuation = getDistanceAttenuation( { - lightDistance, - cutoffDistance: cutoffDistanceNode, - decayExponent: decayExponentNode - } ); + this._pixelRatio = renderer.getPixelRatio(); - const lightColor = colorNode.mul( lightAttenuation ); + stereo.cameraL.coordinateSystem = renderer.coordinateSystem; + stereo.cameraR.coordinateSystem = renderer.coordinateSystem; + stereo.update( camera ); - const reflectedLight = builder.context.reflectedLight; + const size = renderer.getSize( _size$2 ); + this.setSize( size.width, size.height ); - lightingModel.direct( { - lightDirection, - lightColor, - reflectedLight - }, builder.stack, builder ); + const currentAutoClear = renderer.autoClear; + renderer.autoClear = false; - } + const currentRenderTarget = renderer.getRenderTarget(); + const currentMRT = renderer.getMRT(); -} + this._cameraNear.value = camera.near; + this._cameraFar.value = camera.far; -PointLightNode.type = /*@__PURE__*/ registerNode( 'PointLight', PointLightNode ); + for ( const name in this._previousTextures ) { -class DirectionalLightNode extends AnalyticLightNode { + this.toggleTexture( name ); - constructor( light = null ) { + } - super( light ); + renderer.setRenderTarget( renderTarget ); + renderer.setMRT( this._mrt ); + renderer.clear(); - } + renderTarget.scissorTest = true; - setup( builder ) { + renderTarget.scissor.set( 0, 0, renderTarget.width / 2, renderTarget.height ); + renderTarget.viewport.set( 0, 0, renderTarget.width / 2, renderTarget.height ); + renderer.render( scene, stereo.cameraL ); - super.setup( builder ); + renderTarget.scissor.set( renderTarget.width / 2, 0, renderTarget.width / 2, renderTarget.height ); + renderTarget.viewport.set( renderTarget.width / 2, 0, renderTarget.width / 2, renderTarget.height ); + renderer.render( scene, stereo.cameraR ); - const lightingModel = builder.context.lightingModel; + renderTarget.scissorTest = false; - const lightColor = this.colorNode; - const lightDirection = lightTargetDirection( this.light ); - const reflectedLight = builder.context.reflectedLight; + renderer.setRenderTarget( currentRenderTarget ); + renderer.setMRT( currentMRT ); - lightingModel.direct( { - lightDirection, - lightColor, - reflectedLight - }, builder.stack, builder ); + renderer.autoClear = currentAutoClear; } } -DirectionalLightNode.type = /*@__PURE__*/ registerNode( 'DirectionalLight', DirectionalLightNode ); - -const _matrix41 = /*@__PURE__*/ new Matrix4(); -const _matrix42 = /*@__PURE__*/ new Matrix4(); - -let ltcLib = null; +const stereoPass = ( scene, camera ) => nodeObject( new StereoPassNode( scene, camera ) ); -class RectAreaLightNode extends AnalyticLightNode { +const _size$1 = /*@__PURE__*/ new Vector2(); +const _quadMesh$2 = /*@__PURE__*/ new QuadMesh(); - constructor( light = null ) { +class StereoCompositePassNode extends PassNode { - super( light ); + static get type() { - this.halfHeight = uniform( new Vector3() ); - this.halfWidth = uniform( new Vector3() ); + return 'StereoCompositePassNode'; } - update( frame ) { + constructor( scene, camera ) { - super.update( frame ); + super( PassNode.COLOR, scene, camera ); - const { light } = this; + this.isStereoCompositePassNode = true; - const viewMatrix = frame.camera.matrixWorldInverse; + this.stereo = new StereoCamera(); + const _params = { minFilter: LinearFilter, magFilter: NearestFilter, type: HalfFloatType }; - _matrix42.identity(); - _matrix41.copy( light.matrixWorld ); - _matrix41.premultiply( viewMatrix ); - _matrix42.extractRotation( _matrix41 ); + this._renderTargetL = new RenderTarget( 1, 1, _params ); + this._renderTargetR = new RenderTarget( 1, 1, _params ); - this.halfWidth.value.set( light.width * 0.5, 0.0, 0.0 ); - this.halfHeight.value.set( 0.0, light.height * 0.5, 0.0 ); + this._mapLeft = texture( this._renderTargetL.texture ); + this._mapRight = texture( this._renderTargetR.texture ); - this.halfWidth.value.applyMatrix4( _matrix42 ); - this.halfHeight.value.applyMatrix4( _matrix42 ); + this._material = null; } - setup( builder ) { - - super.setup( builder ); + updateStereoCamera( coordinateSystem ) { - let ltc_1, ltc_2; + this.stereo.cameraL.coordinateSystem = coordinateSystem; + this.stereo.cameraR.coordinateSystem = coordinateSystem; + this.stereo.update( this.camera ); - if ( builder.isAvailable( 'float32Filterable' ) ) { + } - ltc_1 = texture( ltcLib.LTC_FLOAT_1 ); - ltc_2 = texture( ltcLib.LTC_FLOAT_2 ); + setSize( width, height ) { - } else { + super.setSize( width, height ); - ltc_1 = texture( ltcLib.LTC_HALF_1 ); - ltc_2 = texture( ltcLib.LTC_HALF_2 ); + this._renderTargetL.setSize( this.renderTarget.width, this.renderTarget.height ); + this._renderTargetR.setSize( this.renderTarget.width, this.renderTarget.height ); - } + } - const { colorNode, light } = this; - const lightingModel = builder.context.lightingModel; + updateBefore( frame ) { - const lightPosition = objectViewPosition( light ); - const reflectedLight = builder.context.reflectedLight; + const { renderer } = frame; + const { scene, stereo, renderTarget } = this; - lightingModel.directRectArea( { - lightColor: colorNode, - lightPosition, - halfWidth: this.halfWidth, - halfHeight: this.halfHeight, - reflectedLight, - ltc_1, - ltc_2 - }, builder.stack, builder ); + this._pixelRatio = renderer.getPixelRatio(); - } + this.updateStereoCamera( renderer.coordinateSystem ); - static setLTC( ltc ) { + const size = renderer.getSize( _size$1 ); + this.setSize( size.width, size.height ); - ltcLib = ltc; + const currentRenderTarget = renderer.getRenderTarget(); - } + // left -} + renderer.setRenderTarget( this._renderTargetL ); + renderer.render( scene, stereo.cameraL ); -RectAreaLightNode.type = /*@__PURE__*/ registerNode( 'RectAreaLight', RectAreaLightNode ); + // right -class SpotLightNode extends AnalyticLightNode { + renderer.setRenderTarget( this._renderTargetR ); + renderer.render( scene, stereo.cameraR ); - constructor( light = null ) { + // composite - super( light ); + renderer.setRenderTarget( renderTarget ); + _quadMesh$2.material = this._material; + _quadMesh$2.render( renderer ); - this.coneCosNode = uniform( 0 ); - this.penumbraCosNode = uniform( 0 ); + // restore - this.cutoffDistanceNode = uniform( 0 ); - this.decayExponentNode = uniform( 0 ); + renderer.setRenderTarget( currentRenderTarget ); } - update( frame ) { - - super.update( frame ); - - const { light } = this; - - this.coneCosNode.value = Math.cos( light.angle ); - this.penumbraCosNode.value = Math.cos( light.angle * ( 1 - light.penumbra ) ); + dispose() { - this.cutoffDistanceNode.value = light.distance; - this.decayExponentNode.value = light.decay; + super.dispose(); - } + this._renderTargetL.dispose(); + this._renderTargetR.dispose(); - getSpotAttenuation( angleCosine ) { + if ( this._material !== null ) { - const { coneCosNode, penumbraCosNode } = this; + this._material.dispose(); - return smoothstep( coneCosNode, penumbraCosNode, angleCosine ); + } } - setup( builder ) { +} - super.setup( builder ); +class AnaglyphPassNode extends StereoCompositePassNode { - const lightingModel = builder.context.lightingModel; + static get type() { - const { colorNode, cutoffDistanceNode, decayExponentNode, light } = this; + return 'AnaglyphPassNode'; - const lVector = objectViewPosition( light ).sub( positionView ); // @TODO: Add it into LightNode + } - const lightDirection = lVector.normalize(); - const angleCos = lightDirection.dot( lightTargetDirection( light ) ); - const spotAttenuation = this.getSpotAttenuation( angleCos ); + constructor( scene, camera ) { - const lightDistance = lVector.length(); + super( scene, camera ); - const lightAttenuation = getDistanceAttenuation( { - lightDistance, - cutoffDistance: cutoffDistanceNode, - decayExponent: decayExponentNode - } ); + this.isAnaglyphPassNode = true; - const lightColor = colorNode.mul( spotAttenuation ).mul( lightAttenuation ); + // Dubois matrices from https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.7.6968&rep=rep1&type=pdf#page=4 - const reflectedLight = builder.context.reflectedLight; + this._colorMatrixLeft = uniform( new Matrix3().fromArray( [ + 0.456100, - 0.0400822, - 0.0152161, + 0.500484, - 0.0378246, - 0.0205971, + 0.176381, - 0.0157589, - 0.00546856 + ] ) ); - lightingModel.direct( { - lightDirection, - lightColor, - reflectedLight - }, builder.stack, builder ); + this._colorMatrixRight = uniform( new Matrix3().fromArray( [ + - 0.0434706, 0.378476, - 0.0721527, + - 0.0879388, 0.73364, - 0.112961, + - 0.00155529, - 0.0184503, 1.2264 + ] ) ); } -} - -SpotLightNode.type = /*@__PURE__*/ registerNode( 'SpotLight', SpotLightNode ); - -class IESSpotLightNode extends SpotLightNode { - - getSpotAttenuation( angleCosine ) { - - const iesMap = this.light.iesMap; + setup( builder ) { - let spotAttenuation = null; + const uvNode = uv(); - if ( iesMap && iesMap.isTexture === true ) { + const anaglyph = Fn( () => { - const angle = angleCosine.acos().mul( 1.0 / Math.PI ); + const colorL = this._mapLeft.uv( uvNode ); + const colorR = this._mapRight.uv( uvNode ); - spotAttenuation = texture( iesMap, vec2( angle, 0 ), 0 ).r; + const color = clamp( this._colorMatrixLeft.mul( colorL.rgb ).add( this._colorMatrixRight.mul( colorR.rgb ) ) ); - } else { + return vec4( color.rgb, max$1( colorL.a, colorR.a ) ); - spotAttenuation = super.getSpotAttenuation( angleCosine ); + } ); - } + const material = this._material || ( this._material = new NodeMaterial() ); + material.fragmentNode = anaglyph().context( builder.getSharedContext() ); + material.name = 'Anaglyph'; + material.needsUpdate = true; - return spotAttenuation; + return super.setup( builder ); } } -IESSpotLightNode.type = /*@__PURE__*/ registerNode( 'IESSpotLight', IESSpotLightNode ); +const anaglyphPass = ( scene, camera ) => nodeObject( new AnaglyphPassNode( scene, camera ) ); -class AmbientLightNode extends AnalyticLightNode { +class ParallaxBarrierPassNode extends StereoCompositePassNode { - constructor( light = null ) { + static get type() { - super( light ); + return 'ParallaxBarrierPassNode'; } - setup( { context } ) { + constructor( scene, camera ) { - context.irradiance.addAssign( this.colorNode ); + super( scene, camera ); + + this.isParallaxBarrierPassNode = true; } -} + setup( builder ) { -AmbientLightNode.type = /*@__PURE__*/ registerNode( 'AmbientLight', AmbientLightNode ); + const uvNode = uv(); -class HemisphereLightNode extends AnalyticLightNode { + const parallaxBarrier = Fn( () => { - constructor( light = null ) { + const color = vec4().toVar(); - super( light ); + If( mod( screenCoordinate.y, 2 ).greaterThan( 1 ), () => { - this.lightPositionNode = objectPosition( light ); - this.lightDirectionNode = this.lightPositionNode.normalize(); + color.assign( this._mapLeft.uv( uvNode ) ); - this.groundColorNode = uniform( new Color() ); + } ).Else( () => { - } + color.assign( this._mapRight.uv( uvNode ) ); - update( frame ) { + } ); - const { light } = this; + return color; - super.update( frame ); + } ); - this.lightPositionNode.object3d = light; + const material = this._material || ( this._material = new NodeMaterial() ); + material.fragmentNode = parallaxBarrier().context( builder.getSharedContext() ); + material.needsUpdate = true; - this.groundColorNode.value.copy( light.groundColor ).multiplyScalar( light.intensity ); + return super.setup( builder ); } - setup( builder ) { +} - const { colorNode, groundColorNode, lightDirectionNode } = this; +const parallaxBarrierPass = ( scene, camera ) => nodeObject( new ParallaxBarrierPassNode( scene, camera ) ); - const dotNL = normalView.dot( lightDirectionNode ); - const hemiDiffuseWeight = dotNL.mul( 0.5 ).add( 0.5 ); +class ToonOutlinePassNode extends PassNode { - const irradiance = mix( groundColorNode, colorNode, hemiDiffuseWeight ); + static get type() { - builder.context.irradiance.addAssign( irradiance ); + return 'ToonOutlinePassNode'; } -} - -HemisphereLightNode.type = /*@__PURE__*/ registerNode( 'HemisphereLight', HemisphereLightNode ); - -class LightProbeNode extends AnalyticLightNode { - - constructor( light = null ) { - - super( light ); + constructor( scene, camera, colorNode, thicknessNode, alphaNode ) { - const array = []; + super( PassNode.COLOR, scene, camera ); - for ( let i = 0; i < 9; i ++ ) array.push( new Vector3() ); + this.colorNode = colorNode; + this.thicknessNode = thicknessNode; + this.alphaNode = alphaNode; - this.lightProbe = uniformArray( array ); + this._materialCache = new WeakMap(); } - update( frame ) { + updateBefore( frame ) { - const { light } = this; + const { renderer } = frame; - super.update( frame ); + const currentRenderObjectFunction = renderer.getRenderObjectFunction(); - // + renderer.setRenderObjectFunction( ( object, scene, camera, geometry, material, group, lightsNode ) => { - for ( let i = 0; i < 9; i ++ ) { + // only render outline for supported materials - this.lightProbe.array[ i ].copy( light.sh.coefficients[ i ] ).multiplyScalar( light.intensity ); + if ( material.isMeshToonMaterial || material.isMeshToonNodeMaterial ) { - } + if ( material.wireframe === false ) { - } + const outlineMaterial = this._getOutlineMaterial( material ); + renderer.renderObject( object, scene, camera, geometry, outlineMaterial, group, lightsNode ); - setup( builder ) { + } - const irradiance = shGetIrradianceAt( normalWorld, this.lightProbe ); + } - builder.context.irradiance.addAssign( irradiance ); + // default - } + renderer.renderObject( object, scene, camera, geometry, material, group, lightsNode ); -} + } ); -LightProbeNode.type = /*@__PURE__*/ registerNode( 'LightProbe', LightProbeNode ); + super.updateBefore( frame ); -const shGetIrradianceAt = /*@__PURE__*/ Fn( ( [ normal, shCoefficients ] ) => { + renderer.setRenderObjectFunction( currentRenderObjectFunction ); - // normal is assumed to have unit length + } - const x = normal.x, y = normal.y, z = normal.z; + _createMaterial() { - // band 0 - const result = shCoefficients.element( 0 ).mul( 0.886227 ); + const material = new NodeMaterial(); + material.isMeshToonOutlineMaterial = true; + material.name = 'Toon_Outline'; + material.side = BackSide; - // band 1 - result.addAssign( shCoefficients.element( 1 ).mul( 2.0 * 0.511664 ).mul( y ) ); - result.addAssign( shCoefficients.element( 2 ).mul( 2.0 * 0.511664 ).mul( z ) ); - result.addAssign( shCoefficients.element( 3 ).mul( 2.0 * 0.511664 ).mul( x ) ); + // vertex node - // band 2 - result.addAssign( shCoefficients.element( 4 ).mul( 2.0 * 0.429043 ).mul( x ).mul( y ) ); - result.addAssign( shCoefficients.element( 5 ).mul( 2.0 * 0.429043 ).mul( y ).mul( z ) ); - result.addAssign( shCoefficients.element( 6 ).mul( z.mul( z ).mul( 0.743125 ).sub( 0.247708 ) ) ); - result.addAssign( shCoefficients.element( 7 ).mul( 2.0 * 0.429043 ).mul( x ).mul( z ) ); - result.addAssign( shCoefficients.element( 8 ).mul( 0.429043 ).mul( mul( x, x ).sub( mul( y, y ) ) ) ); + const outlineNormal = normalLocal.negate(); + const mvp = cameraProjectionMatrix.mul( modelViewMatrix ); - return result; + const ratio = float( 1.0 ); // TODO: support outline thickness ratio for each vertex + const pos = mvp.mul( vec4( positionLocal, 1.0 ) ); + const pos2 = mvp.mul( vec4( positionLocal.add( outlineNormal ), 1.0 ) ); + const norm = normalize( pos.sub( pos2 ) ); // NOTE: subtract pos2 from pos because BackSide objectNormal is negative -} ); + material.vertexNode = pos.add( norm.mul( this.thicknessNode ).mul( pos.w ).mul( ratio ) ); -class NodeParser { + // color node - parseFunction( /*source*/ ) { + material.colorNode = vec4( this.colorNode, this.alphaNode ); - console.warn( 'Abstract function.' ); + return material; } -} + _getOutlineMaterial( originalMaterial ) { -class NodeFunction { + let outlineMaterial = this._materialCache.get( originalMaterial ); - constructor( type, inputs, name = '', precision = '' ) { + if ( outlineMaterial === undefined ) { - this.type = type; - this.inputs = inputs; - this.name = name; - this.precision = precision; + outlineMaterial = this._createMaterial(); - } + this._materialCache.set( originalMaterial, outlineMaterial ); - getCode( /*name = this.name*/ ) { + } - console.warn( 'Abstract function.' ); + return outlineMaterial; } } -NodeFunction.isNodeFunction = true; - -const declarationRegexp$1 = /^\s*(highp|mediump|lowp)?\s*([a-z_0-9]+)\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)/i; -const propertiesRegexp$1 = /[a-z_0-9]+/ig; - -const pragmaMain = '#pragma main'; - -const parse$1 = ( source ) => { +const toonOutlinePass = ( scene, camera, color = new Color( 0, 0, 0 ), thickness = 0.003, alpha = 1 ) => nodeObject( new ToonOutlinePassNode( scene, camera, nodeObject( color ), nodeObject( thickness ), nodeObject( alpha ) ) ); - source = source.trim(); - - const pragmaMainIndex = source.indexOf( pragmaMain ); +class ScriptableValueNode extends Node { - const mainCode = pragmaMainIndex !== - 1 ? source.slice( pragmaMainIndex + pragmaMain.length ) : source; + static get type() { - const declaration = mainCode.match( declarationRegexp$1 ); + return 'ScriptableValueNode'; - if ( declaration !== null && declaration.length === 5 ) { + } - // tokenizer + constructor( value = null ) { - const inputsCode = declaration[ 4 ]; - const propsMatches = []; + super(); - let nameMatch = null; + this._value = value; + this._cache = null; - while ( ( nameMatch = propertiesRegexp$1.exec( inputsCode ) ) !== null ) { + this.inputType = null; + this.outpuType = null; - propsMatches.push( nameMatch ); + this.events = new EventDispatcher(); - } + this.isScriptableValueNode = true; - // parser + } - const inputs = []; + get isScriptableOutputNode() { - let i = 0; + return this.outputType !== null; - while ( i < propsMatches.length ) { + } - const isConst = propsMatches[ i ][ 0 ] === 'const'; + set value( val ) { - if ( isConst === true ) { + if ( this._value === val ) return; - i ++; + if ( this._cache && this.inputType === 'URL' && this.value.value instanceof ArrayBuffer ) { - } + URL.revokeObjectURL( this._cache ); - let qualifier = propsMatches[ i ][ 0 ]; + this._cache = null; - if ( qualifier === 'in' || qualifier === 'out' || qualifier === 'inout' ) { + } - i ++; + this._value = val; - } else { + this.events.dispatchEvent( { type: 'change' } ); - qualifier = ''; + this.refresh(); - } + } - const type = propsMatches[ i ++ ][ 0 ]; + get value() { - let count = Number.parseInt( propsMatches[ i ][ 0 ] ); + return this._value; - if ( Number.isNaN( count ) === false ) i ++; - else count = null; + } - const name = propsMatches[ i ++ ][ 0 ]; + refresh() { - inputs.push( new NodeFunctionInput( type, name, count, qualifier, isConst ) ); + this.events.dispatchEvent( { type: 'refresh' } ); - } + } - // + getValue() { - const blockCode = mainCode.substring( declaration[ 0 ].length ); + const value = this.value; - const name = declaration[ 3 ] !== undefined ? declaration[ 3 ] : ''; - const type = declaration[ 2 ]; + if ( value && this._cache === null && this.inputType === 'URL' && value.value instanceof ArrayBuffer ) { - const precision = declaration[ 1 ] !== undefined ? declaration[ 1 ] : ''; + this._cache = URL.createObjectURL( new Blob( [ value.value ] ) ); - const headerCode = pragmaMainIndex !== - 1 ? source.slice( 0, pragmaMainIndex ) : ''; + } else if ( value && value.value !== null && value.value !== undefined && ( + ( ( this.inputType === 'URL' || this.inputType === 'String' ) && typeof value.value === 'string' ) || + ( this.inputType === 'Number' && typeof value.value === 'number' ) || + ( this.inputType === 'Vector2' && value.value.isVector2 ) || + ( this.inputType === 'Vector3' && value.value.isVector3 ) || + ( this.inputType === 'Vector4' && value.value.isVector4 ) || + ( this.inputType === 'Color' && value.value.isColor ) || + ( this.inputType === 'Matrix3' && value.value.isMatrix3 ) || + ( this.inputType === 'Matrix4' && value.value.isMatrix4 ) + ) ) { - return { - type, - inputs, - name, - precision, - inputsCode, - blockCode, - headerCode - }; + return value.value; - } else { + } - throw new Error( 'FunctionNode: Function is not a GLSL code.' ); + return this._cache || value; } -}; - -class GLSLNodeFunction extends NodeFunction { + getNodeType( builder ) { - constructor( source ) { + return this.value && this.value.isNode ? this.value.getNodeType( builder ) : 'float'; - const { type, inputs, name, precision, inputsCode, blockCode, headerCode } = parse$1( source ); + } - super( type, inputs, name, precision ); + setup() { - this.inputsCode = inputsCode; - this.blockCode = blockCode; - this.headerCode = headerCode; + return this.value && this.value.isNode ? this.value : float(); } - getCode( name = this.name ) { - - let code; + serialize( data ) { - const blockCode = this.blockCode; + super.serialize( data ); - if ( blockCode !== '' ) { + if ( this.value !== null ) { - const { type, inputsCode, headerCode, precision } = this; + if ( this.inputType === 'ArrayBuffer' ) { - let declarationCode = `${ type } ${ name } ( ${ inputsCode.trim() } )`; + data.value = arrayBufferToBase64( this.value ); - if ( precision !== '' ) { + } else { - declarationCode = `${ precision } ${ declarationCode }`; + data.value = this.value ? this.value.toJSON( data.meta ).uuid : null; } - code = headerCode + declarationCode + blockCode; - } else { - // interface function - - code = ''; + data.value = null; } - return code; + data.inputType = this.inputType; + data.outputType = this.outputType; } -} + deserialize( data ) { -class GLSLNodeParser extends NodeParser { + super.deserialize( data ); - parseFunction( source ) { + let value = null; - return new GLSLNodeFunction( source ); + if ( data.value !== null ) { - } + if ( data.inputType === 'ArrayBuffer' ) { -} + value = base64ToArrayBuffer( data.value ); -function painterSortStable( a, b ) { + } else if ( data.inputType === 'Texture' ) { - if ( a.groupOrder !== b.groupOrder ) { - - return a.groupOrder - b.groupOrder; - - } else if ( a.renderOrder !== b.renderOrder ) { - - return a.renderOrder - b.renderOrder; + value = data.meta.textures[ data.value ]; - } else if ( a.material.id !== b.material.id ) { + } else { - return a.material.id - b.material.id; + value = data.meta.nodes[ data.value ] || null; - } else if ( a.z !== b.z ) { + } - return a.z - b.z; + } - } else { + this.value = value; - return a.id - b.id; + this.inputType = data.inputType; + this.outputType = data.outputType; } } -function reversePainterSortStable( a, b ) { - - if ( a.groupOrder !== b.groupOrder ) { - - return a.groupOrder - b.groupOrder; +const scriptableValue = /*@__PURE__*/ nodeProxy( ScriptableValueNode ); - } else if ( a.renderOrder !== b.renderOrder ) { +class Resources extends Map { - return a.renderOrder - b.renderOrder; + get( key, callback = null, ...params ) { - } else if ( a.z !== b.z ) { + if ( this.has( key ) ) return super.get( key ); - return b.z - a.z; + if ( callback !== null ) { - } else { + const value = callback( ...params ); + this.set( key, value ); + return value; - return a.id - b.id; + } } } -class RenderList { +class Parameters { - constructor() { + constructor( scriptableNode ) { - this.renderItems = []; - this.renderItemsIndex = 0; + this.scriptableNode = scriptableNode; - this.opaque = []; - this.transparent = []; - this.bundles = []; + } - this.lightsNode = new LightsNode( [] ); - this.lightsArray = []; + get parameters() { - this.occlusionQueryCount = 0; + return this.scriptableNode.parameters; } - begin() { - - this.renderItemsIndex = 0; + get layout() { - this.opaque.length = 0; - this.transparent.length = 0; - this.bundles.length = 0; + return this.scriptableNode.getLayout(); - this.lightsArray.length = 0; + } - this.occlusionQueryCount = 0; + getInputLayout( id ) { - return this; + return this.scriptableNode.getInputLayout( id ); } - getNextRenderItem( object, geometry, material, groupOrder, z, group ) { - - let renderItem = this.renderItems[ this.renderItemsIndex ]; + get( name ) { - if ( renderItem === undefined ) { + const param = this.parameters[ name ]; + const value = param ? param.getValue() : null; - renderItem = { - id: object.id, - object: object, - geometry: geometry, - material: material, - groupOrder: groupOrder, - renderOrder: object.renderOrder, - z: z, - group: group - }; + return value; - this.renderItems[ this.renderItemsIndex ] = renderItem; + } - } else { +} - renderItem.id = object.id; - renderItem.object = object; - renderItem.geometry = geometry; - renderItem.material = material; - renderItem.groupOrder = groupOrder; - renderItem.renderOrder = object.renderOrder; - renderItem.z = z; - renderItem.group = group; +const global = new Resources(); - } +class ScriptableNode extends Node { - this.renderItemsIndex ++; + static get type() { - return renderItem; + return 'ScriptableNode'; } - push( object, geometry, material, groupOrder, z, group ) { - - const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group ); - - if ( object.occlusionTest === true ) this.occlusionQueryCount ++; + constructor( codeNode = null, parameters = {} ) { - ( material.transparent === true || material.transmission > 0 ? this.transparent : this.opaque ).push( renderItem ); + super(); - } + this.codeNode = codeNode; + this.parameters = parameters; - unshift( object, geometry, material, groupOrder, z, group ) { + this._local = new Resources(); + this._output = scriptableValue(); + this._outputs = {}; + this._source = this.source; + this._method = null; + this._object = null; + this._value = null; + this._needsOutputUpdate = true; - const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group ); + this.onRefresh = this.onRefresh.bind( this ); - ( material.transparent === true ? this.transparent : this.opaque ).unshift( renderItem ); + this.isScriptableNode = true; } - pushBundle( group ) { + get source() { - this.bundles.push( group ); + return this.codeNode ? this.codeNode.code : ''; } - pushLight( light ) { + setLocal( name, value ) { - this.lightsArray.push( light ); + return this._local.set( name, value ); } - getLightsNode() { + getLocal( name ) { - return this.lightsNode.fromLights( this.lightsArray ); + return this._local.get( name ); } - sort( customOpaqueSort, customTransparentSort ) { + onRefresh() { - if ( this.opaque.length > 1 ) this.opaque.sort( customOpaqueSort || painterSortStable ); - if ( this.transparent.length > 1 ) this.transparent.sort( customTransparentSort || reversePainterSortStable ); + this._refresh(); } - finish() { - - // update lights - - this.lightsNode.setLights( this.lightsArray ); - - // Clear references from inactive renderItems in the list + getInputLayout( id ) { - for ( let i = this.renderItemsIndex, il = this.renderItems.length; i < il; i ++ ) { + for ( const element of this.getLayout() ) { - const renderItem = this.renderItems[ i ]; + if ( element.inputType && ( element.id === id || element.name === id ) ) { - if ( renderItem.id === null ) break; + return element; - renderItem.id = null; - renderItem.object = null; - renderItem.geometry = null; - renderItem.material = null; - renderItem.groupOrder = null; - renderItem.renderOrder = null; - renderItem.z = null; - renderItem.group = null; + } } } -} + getOutputLayout( id ) { -class RenderLists { + for ( const element of this.getLayout() ) { - constructor() { + if ( element.outputType && ( element.id === id || element.name === id ) ) { - this.lists = new ChainMap(); + return element; + + } + + } } - get( scene, camera ) { + setOutput( name, value ) { - const lists = this.lists; - const keys = [ scene, camera ]; + const outputs = this._outputs; - let list = lists.get( keys ); + if ( outputs[ name ] === undefined ) { - if ( list === undefined ) { + outputs[ name ] = scriptableValue( value ); - list = new RenderList(); - lists.set( keys, list ); + } else { + + outputs[ name ].value = value; } - return list; + return this; } - dispose() { + getOutput( name ) { - this.lists = new ChainMap(); + return this._outputs[ name ]; } -} + getParameter( name ) { -let id = 0; + return this.parameters[ name ]; -class RenderContext { + } - constructor() { + setParameter( name, value ) { - this.id = id ++; + const parameters = this.parameters; - this.color = true; - this.clearColor = true; - this.clearColorValue = { r: 0, g: 0, b: 0, a: 1 }; + if ( value && value.isScriptableNode ) { - this.depth = true; - this.clearDepth = true; - this.clearDepthValue = 1; + this.deleteParameter( name ); - this.stencil = false; - this.clearStencil = true; - this.clearStencilValue = 1; + parameters[ name ] = value; + parameters[ name ].getDefaultOutput().events.addEventListener( 'refresh', this.onRefresh ); - this.viewport = false; - this.viewportValue = new Vector4(); + } else if ( value && value.isScriptableValueNode ) { - this.scissor = false; - this.scissorValue = new Vector4(); + this.deleteParameter( name ); - this.textures = null; - this.depthTexture = null; - this.activeCubeFace = 0; - this.sampleCount = 1; + parameters[ name ] = value; + parameters[ name ].events.addEventListener( 'refresh', this.onRefresh ); - this.width = 0; - this.height = 0; + } else if ( parameters[ name ] === undefined ) { - this.isRenderContext = true; + parameters[ name ] = scriptableValue( value ); + parameters[ name ].events.addEventListener( 'refresh', this.onRefresh ); - } + } else { - getCacheKey() { + parameters[ name ].value = value; - return getCacheKey( this ); + } + + return this; } -} + getValue() { -function getCacheKey( renderContext ) { + return this.getDefaultOutput().getValue(); - const { textures, activeCubeFace } = renderContext; + } - let key = ''; + deleteParameter( name ) { - for ( const texture of textures ) { + let valueNode = this.parameters[ name ]; - key += texture.id + ','; + if ( valueNode ) { - } + if ( valueNode.isScriptableNode ) valueNode = valueNode.getDefaultOutput(); - key += activeCubeFace; + valueNode.events.removeEventListener( 'refresh', this.onRefresh ); - return key; + } -} + return this; -class RenderContexts { + } - constructor() { + clearParameters() { - this.chainMaps = {}; + for ( const name of Object.keys( this.parameters ) ) { - } + this.deleteParameter( name ); - get( scene, camera, renderTarget = null ) { + } - const chainKey = [ scene, camera ]; + this.needsUpdate = true; - let attachmentState; + return this; - if ( renderTarget === null ) { + } - attachmentState = 'default'; + call( name, ...params ) { - } else { + const object = this.getObject(); + const method = object[ name ]; - const format = renderTarget.texture.format; - const count = renderTarget.textures.length; + if ( typeof method === 'function' ) { - attachmentState = `${ count }:${ format }:${ renderTarget.samples }:${ renderTarget.depthBuffer }:${ renderTarget.stencilBuffer }`; + return method( ...params ); } - const chainMap = this.getChainMap( attachmentState ); + } - let renderState = chainMap.get( chainKey ); + async callAsync( name, ...params ) { - if ( renderState === undefined ) { + const object = this.getObject(); + const method = object[ name ]; - renderState = new RenderContext(); + if ( typeof method === 'function' ) { - chainMap.set( chainKey, renderState ); + return method.constructor.name === 'AsyncFunction' ? await method( ...params ) : method( ...params ); } - if ( renderTarget !== null ) renderState.sampleCount = renderTarget.samples === 0 ? 1 : renderTarget.samples; + } - return renderState; + getNodeType( builder ) { + + return this.getDefaultOutputNode().getNodeType( builder ); } - getChainMap( attachmentState ) { + refresh( output = null ) { - return this.chainMaps[ attachmentState ] || ( this.chainMaps[ attachmentState ] = new ChainMap() ); + if ( output !== null ) { - } + this.getOutput( output ).refresh(); - dispose() { + } else { - this.chainMaps = {}; + this._refresh(); + + } } -} + getObject() { -const _size = /*@__PURE__*/ new Vector3(); + if ( this.needsUpdate ) this.dispose(); + if ( this._object !== null ) return this._object; -class Textures extends DataMap { + // - constructor( renderer, backend, info ) { + const refresh = () => this.refresh(); + const setOutput = ( id, value ) => this.setOutput( id, value ); - super(); + const parameters = new Parameters( this ); - this.renderer = renderer; - this.backend = backend; - this.info = info; + const THREE = global.get( 'THREE' ); + const TSL = global.get( 'TSL' ); - } + const method = this.getMethod( this.codeNode ); + const params = [ parameters, this._local, global, refresh, setOutput, THREE, TSL ]; - updateRenderTarget( renderTarget, activeMipmapLevel = 0 ) { + this._object = method( ...params ); - const renderTargetData = this.get( renderTarget ); + const layout = this._object.layout; - const sampleCount = renderTarget.samples === 0 ? 1 : renderTarget.samples; - const depthTextureMips = renderTargetData.depthTextureMips || ( renderTargetData.depthTextureMips = {} ); + if ( layout ) { - const textures = renderTarget.textures; + if ( layout.cache === false ) { - const size = this.getSize( textures[ 0 ] ); + this._local.clear(); - const mipWidth = size.width >> activeMipmapLevel; - const mipHeight = size.height >> activeMipmapLevel; + } - let depthTexture = renderTarget.depthTexture || depthTextureMips[ activeMipmapLevel ]; - let textureNeedsUpdate = false; + // default output + this._output.outputType = layout.outputType || null; - if ( depthTexture === undefined ) { + if ( Array.isArray( layout.elements ) ) { - depthTexture = new DepthTexture(); - depthTexture.format = renderTarget.stencilBuffer ? DepthStencilFormat : DepthFormat; - depthTexture.type = renderTarget.stencilBuffer ? UnsignedInt248Type : UnsignedIntType; // FloatType - depthTexture.image.width = mipWidth; - depthTexture.image.height = mipHeight; + for ( const element of layout.elements ) { - depthTextureMips[ activeMipmapLevel ] = depthTexture; + const id = element.id || element.name; - } + if ( element.inputType ) { - if ( renderTargetData.width !== size.width || size.height !== renderTargetData.height ) { + if ( this.getParameter( id ) === undefined ) this.setParameter( id, null ); - textureNeedsUpdate = true; - depthTexture.needsUpdate = true; + this.getParameter( id ).inputType = element.inputType; - depthTexture.image.width = mipWidth; - depthTexture.image.height = mipHeight; + } - } + if ( element.outputType ) { - renderTargetData.width = size.width; - renderTargetData.height = size.height; - renderTargetData.textures = textures; - renderTargetData.depthTexture = depthTexture; - renderTargetData.depth = renderTarget.depthBuffer; - renderTargetData.stencil = renderTarget.stencilBuffer; - renderTargetData.renderTarget = renderTarget; + if ( this.getOutput( id ) === undefined ) this.setOutput( id, null ); - if ( renderTargetData.sampleCount !== sampleCount ) { + this.getOutput( id ).outputType = element.outputType; - textureNeedsUpdate = true; - depthTexture.needsUpdate = true; + } - renderTargetData.sampleCount = sampleCount; + } + + } } - // + return this._object; - const options = { sampleCount }; + } - for ( let i = 0; i < textures.length; i ++ ) { + deserialize( data ) { - const texture = textures[ i ]; + super.deserialize( data ); - if ( textureNeedsUpdate ) texture.needsUpdate = true; + for ( const name in this.parameters ) { - this.updateTexture( texture, options ); + let valueNode = this.parameters[ name ]; - } + if ( valueNode.isScriptableNode ) valueNode = valueNode.getDefaultOutput(); - this.updateTexture( depthTexture, options ); + valueNode.events.addEventListener( 'refresh', this.onRefresh ); - // dispose handler + } - if ( renderTargetData.initialized !== true ) { + } - renderTargetData.initialized = true; + getLayout() { - // dispose + return this.getObject().layout; - const onDispose = () => { + } - renderTarget.removeEventListener( 'dispose', onDispose ); + getDefaultOutputNode() { - for ( let i = 0; i < textures.length; i ++ ) { + const output = this.getDefaultOutput().value; - this._destroyTexture( textures[ i ] ); + if ( output && output.isNode ) { - } + return output; - this._destroyTexture( depthTexture ); + } - this.delete( renderTarget ); + return float(); - }; + } - renderTarget.addEventListener( 'dispose', onDispose ); + getDefaultOutput() { - } + return this._exec()._output; } - updateTexture( texture, options = {} ) { - - const textureData = this.get( texture ); - if ( textureData.initialized === true && textureData.version === texture.version ) return; + getMethod() { - const isRenderTarget = texture.isRenderTargetTexture || texture.isDepthTexture || texture.isFramebufferTexture; - const backend = this.backend; + if ( this.needsUpdate ) this.dispose(); + if ( this._method !== null ) return this._method; - if ( isRenderTarget && textureData.initialized === true ) { + // - // it's an update + const parametersProps = [ 'parameters', 'local', 'global', 'refresh', 'setOutput', 'THREE', 'TSL' ]; + const interfaceProps = [ 'layout', 'init', 'main', 'dispose' ]; - backend.destroySampler( texture ); - backend.destroyTexture( texture ); + const properties = interfaceProps.join( ', ' ); + const declarations = 'var ' + properties + '; var output = {};\n'; + const returns = '\nreturn { ...output, ' + properties + ' };'; - } + const code = declarations + this.codeNode.code + returns; // - if ( texture.isFramebufferTexture ) { + this._method = new Function( ...parametersProps, code ); - const renderer = this.renderer; - const renderTarget = renderer.getRenderTarget(); + return this._method; - if ( renderTarget ) { + } - texture.type = renderTarget.texture.type; + dispose() { - } else { + if ( this._method === null ) return; - texture.type = UnsignedByteType; + if ( this._object && typeof this._object.dispose === 'function' ) { - } + this._object.dispose(); } - // + this._method = null; + this._object = null; + this._source = null; + this._value = null; + this._needsOutputUpdate = true; + this._output.value = null; + this._outputs = {}; - const { width, height, depth } = this.getSize( texture ); + } - options.width = width; - options.height = height; - options.depth = depth; - options.needsMipmaps = this.needsMipmaps( texture ); - options.levels = options.needsMipmaps ? this.getMipLevels( texture, width, height ) : 1; + setup() { - // + return this.getDefaultOutputNode(); - if ( isRenderTarget || texture.isStorageTexture === true ) { + } - backend.createSampler( texture ); - backend.createTexture( texture, options ); + getCacheKey( force ) { - textureData.generation = texture.version; + const values = [ hashString( this.source ), this.getDefaultOutputNode().getCacheKey( force ) ]; - } else { + for ( const param in this.parameters ) { - const needsCreate = textureData.initialized !== true; + values.push( this.parameters[ param ].getCacheKey( force ) ); - if ( needsCreate ) backend.createSampler( texture ); + } - if ( texture.version > 0 ) { + return hashArray( values ); - const image = texture.image; + } - if ( image === undefined ) { + set needsUpdate( value ) { - console.warn( 'THREE.Renderer: Texture marked for update but image is undefined.' ); - - } else if ( image.complete === false ) { - - console.warn( 'THREE.Renderer: Texture marked for update but image is incomplete.' ); - - } else { + if ( value === true ) this.dispose(); - if ( texture.images ) { + } - const images = []; + get needsUpdate() { - for ( const image of texture.images ) { + return this.source !== this._source; - images.push( image ); + } - } + _exec() { - options.images = images; + if ( this.codeNode === null ) return this; - } else { + if ( this._needsOutputUpdate === true ) { - options.image = image; + this._value = this.call( 'main' ); - } + this._needsOutputUpdate = false; - if ( textureData.isDefaultTexture === undefined || textureData.isDefaultTexture === true ) { + } - backend.createTexture( texture, options ); + this._output.value = this._value; - textureData.isDefaultTexture = false; - textureData.generation = texture.version; + return this; - } + } - if ( texture.source.dataReady === true ) backend.updateTexture( texture, options ); + _refresh() { - if ( options.needsMipmaps && texture.mipmaps.length === 0 ) backend.generateMipmaps( texture ); + this.needsUpdate = true; - } + this._exec(); - } else { + this._output.refresh(); - // async update + } - backend.createDefaultTexture( texture ); +} - textureData.isDefaultTexture = true; - textureData.generation = texture.version; +const scriptable = /*@__PURE__*/ nodeProxy( ScriptableNode ); - } +class FogNode extends Node { - } + static get type() { - // dispose handler + return 'FogNode'; - if ( textureData.initialized !== true ) { + } - textureData.initialized = true; - textureData.generation = texture.version; + constructor( colorNode, factorNode ) { - // + super( 'float' ); - this.info.memory.textures ++; + this.isFogNode = true; - // dispose + this.colorNode = colorNode; + this.factorNode = factorNode; - const onDispose = () => { + } - texture.removeEventListener( 'dispose', onDispose ); + getViewZNode( builder ) { - this._destroyTexture( texture ); + let viewZ; - this.info.memory.textures --; + const getViewZ = builder.context.getViewZ; - }; + if ( getViewZ !== undefined ) { - texture.addEventListener( 'dispose', onDispose ); + viewZ = getViewZ( this ); } - // - - textureData.version = texture.version; + return ( viewZ || positionView.z ).negate(); } - getSize( texture, target = _size ) { - - let image = texture.images ? texture.images[ 0 ] : texture.image; + setup() { - if ( image ) { + return this.factorNode; - if ( image.image !== undefined ) image = image.image; + } - target.width = image.width; - target.height = image.height; - target.depth = texture.isCubeTexture ? 6 : ( image.depth || 1 ); +} - } else { +const fog = /*@__PURE__*/ nodeProxy( FogNode ); - target.width = target.height = target.depth = 1; +class FogRangeNode extends FogNode { - } + static get type() { - return target; + return 'FogRangeNode'; } - getMipLevels( texture, width, height ) { + constructor( colorNode, nearNode, farNode ) { - let mipLevelCount; + super( colorNode ); - if ( texture.isCompressedTexture ) { + this.isFogRangeNode = true; - mipLevelCount = texture.mipmaps.length; + this.nearNode = nearNode; + this.farNode = farNode; - } else { + } - mipLevelCount = Math.floor( Math.log2( Math.max( width, height ) ) ) + 1; + setup( builder ) { - } + const viewZ = this.getViewZNode( builder ); - return mipLevelCount; + return smoothstep( this.nearNode, this.farNode, viewZ ); } - needsMipmaps( texture ) { +} - if ( this.isEnvironmentTexture( texture ) ) return true; +const rangeFog = /*@__PURE__*/ nodeProxy( FogRangeNode ); - return ( texture.isCompressedTexture === true ) || ( ( texture.minFilter !== NearestFilter ) && ( texture.minFilter !== LinearFilter ) ); +class FogExp2Node extends FogNode { + + static get type() { + + return 'FogExp2Node'; } - isEnvironmentTexture( texture ) { + constructor( colorNode, densityNode ) { - const mapping = texture.mapping; + super( colorNode ); - return ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) || ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping ); + this.isFogExp2Node = true; + + this.densityNode = densityNode; } - _destroyTexture( texture ) { + setup( builder ) { - this.backend.destroySampler( texture ); - this.backend.destroyTexture( texture ); + const viewZ = this.getViewZNode( builder ); + const density = this.densityNode; - this.delete( texture ); + return density.mul( density, viewZ, viewZ ).negate().exp().oneMinus(); } } -class Color4 extends Color { +const densityFog = /*@__PURE__*/ nodeProxy( FogExp2Node ); - constructor( r, g, b, a = 1 ) { +let min = null; +let max = null; - super( r, g, b ); +class RangeNode extends Node { - this.a = a; + static get type() { + + return 'RangeNode'; } - set( r, g, b, a = 1 ) { + constructor( minNode = float(), maxNode = float() ) { - this.a = a; + super(); - return super.set( r, g, b ); + this.minNode = minNode; + this.maxNode = maxNode; } - copy( color ) { + getVectorLength( builder ) { - if ( color.a !== undefined ) this.a = color.a; + const minLength = builder.getTypeLength( getValueType( this.minNode.value ) ); + const maxLength = builder.getTypeLength( getValueType( this.maxNode.value ) ); - return super.copy( color ); + return minLength > maxLength ? minLength : maxLength; } - clone() { + getNodeType( builder ) { - return new this.constructor( this.r, this.g, this.b, this.a ); + return builder.object.count > 1 ? builder.getTypeFromLength( this.getVectorLength( builder ) ) : 'float'; } -} + setup( builder ) { -const hash = /*@__PURE__*/ Fn( ( [ seed ] ) => { + const object = builder.object; - // Taken from https://www.shadertoy.com/view/XlGcRh, originally from pcg-random.org + let output = null; - const state = seed.toUint().mul( 747796405 ).add( 2891336453 ); - const word = state.shiftRight( state.shiftRight( 28 ).add( 4 ) ).bitXor( state ).mul( 277803737 ); - const result = word.shiftRight( 22 ).bitXor( word ); + if ( object.count > 1 ) { - return result.toFloat().mul( 1 / 2 ** 32 ); // Convert to range [0, 1) + const minValue = this.minNode.value; + const maxValue = this.maxNode.value; -} ); + const minLength = builder.getTypeLength( getValueType( minValue ) ); + const maxLength = builder.getTypeLength( getValueType( maxValue ) ); -// remapping functions https://iquilezles.org/articles/functions/ -const parabola = ( x, k ) => pow( mul( 4.0, x.mul( sub( 1.0, x ) ) ), k ); -const gain = ( x, k ) => x.lessThan( 0.5 ) ? parabola( x.mul( 2.0 ), k ).div( 2.0 ) : sub( 1.0, parabola( mul( sub( 1.0, x ), 2.0 ), k ).div( 2.0 ) ); -const pcurve = ( x, a, b ) => pow( div( pow( x, a ), add( pow( x, a ), pow( sub( 1.0, x ), b ) ) ), 1.0 / a ); -const sinc = ( x, k ) => sin( PI.mul( k.mul( x ).sub( 1.0 ) ) ).div( PI.mul( k.mul( x ).sub( 1.0 ) ) ); + min = min || new Vector4(); + max = max || new Vector4(); -// https://github.com/cabbibo/glsl-tri-noise-3d + min.setScalar( 0 ); + max.setScalar( 0 ); + if ( minLength === 1 ) min.setScalar( minValue ); + else if ( minValue.isColor ) min.set( minValue.r, minValue.g, minValue.b ); + else min.set( minValue.x, minValue.y, minValue.z || 0, minValue.w || 0 ); -const tri = /*@__PURE__*/ Fn( ( [ x ] ) => { + if ( maxLength === 1 ) max.setScalar( maxValue ); + else if ( maxValue.isColor ) max.set( maxValue.r, maxValue.g, maxValue.b ); + else max.set( maxValue.x, maxValue.y, maxValue.z || 0, maxValue.w || 0 ); - return x.fract().sub( .5 ).abs(); + const stride = 4; -} ).setLayout( { - name: 'tri', - type: 'float', - inputs: [ - { name: 'x', type: 'float' } - ] -} ); + const length = stride * object.count; + const array = new Float32Array( length ); -const tri3 = /*@__PURE__*/ Fn( ( [ p ] ) => { + for ( let i = 0; i < length; i ++ ) { - return vec3( tri( p.z.add( tri( p.y.mul( 1. ) ) ) ), tri( p.z.add( tri( p.x.mul( 1. ) ) ) ), tri( p.y.add( tri( p.x.mul( 1. ) ) ) ) ); + const index = i % stride; -} ).setLayout( { - name: 'tri3', - type: 'vec3', - inputs: [ - { name: 'p', type: 'vec3' } - ] -} ); + const minElementValue = min.getComponent( index ); + const maxElementValue = max.getComponent( index ); -const triNoise3D = /*@__PURE__*/ Fn( ( [ p_immutable, spd, time ] ) => { + array[ i ] = MathUtils.lerp( minElementValue, maxElementValue, Math.random() ); - const p = vec3( p_immutable ).toVar(); - const z = float( 1.4 ).toVar(); - const rz = float( 0.0 ).toVar(); - const bp = vec3( p ).toVar(); + } - Loop( { start: float( 0.0 ), end: float( 3.0 ), type: 'float', condition: '<=' }, () => { + const nodeType = this.getNodeType( builder ); - const dg = vec3( tri3( bp.mul( 2.0 ) ) ).toVar(); - p.addAssign( dg.add( time.mul( float( 0.1 ).mul( spd ) ) ) ); - bp.mulAssign( 1.8 ); - z.mulAssign( 1.5 ); - p.mulAssign( 1.2 ); + if ( object.count <= 4096 ) { - const t = float( tri( p.z.add( tri( p.x.add( tri( p.y ) ) ) ) ) ).toVar(); - rz.addAssign( t.div( z ) ); - bp.addAssign( 0.14 ); + output = buffer( array, 'vec4', object.count ).element( instanceIndex ).convert( nodeType ); - } ); + } else { - return rz; + // TODO: Improve anonymous buffer attribute creation removing this part + const bufferAttribute = new InstancedBufferAttribute( array, 4 ); + builder.geometry.setAttribute( '__range' + this.id, bufferAttribute ); -} ).setLayout( { - name: 'triNoise3D', - type: 'float', - inputs: [ - { name: 'p', type: 'vec3' }, - { name: 'spd', type: 'float' }, - { name: 'time', type: 'float' } - ] -} ); + output = instancedBufferAttribute( bufferAttribute ).convert( nodeType ); -const rotateUV = /*@__PURE__*/ Fn( ( [ uv, rotation, center = vec2( 0.5 ) ] ) => { + } - return rotate( uv.sub( center ), rotation ).add( center ); + } else { -} ); + output = float( 0 ); -const spherizeUV = /*@__PURE__*/ Fn( ( [ uv, strength, center = vec2( 0.5 ) ] ) => { + } - const delta = uv.sub( center ); - const delta2 = delta.dot( delta ); - const delta4 = delta2.mul( delta2 ); - const deltaOffset = delta4.mul( strength ); + return output; - return uv.add( delta.mul( deltaOffset ) ); + } -} ); +} -const billboarding = /*@__PURE__*/ Fn( ( { position = null, horizontal = true, vertical = false } ) => { +const range = /*@__PURE__*/ nodeProxy( RangeNode ); - let worldMatrix; +const BasicShadowMap = Fn( ( { depthTexture, shadowCoord } ) => { - if ( position !== null ) { + return texture( depthTexture, shadowCoord.xy ).compare( shadowCoord.z ); - worldMatrix = modelWorldMatrix.toVar(); - worldMatrix[ 3 ][ 0 ] = position.x; - worldMatrix[ 3 ][ 1 ] = position.y; - worldMatrix[ 3 ][ 2 ] = position.z; +} ); - } else { +const PCFShadowMap = Fn( ( { depthTexture, shadowCoord, shadow } ) => { - worldMatrix = modelWorldMatrix; + const depthCompare = ( uv, compare ) => texture( depthTexture, uv ).compare( compare ); - } + const mapSize = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup ); + const radius = reference( 'radius', 'float', shadow ).setGroup( renderGroup ); - const modelViewMatrix = cameraViewMatrix.mul( worldMatrix ); + const texelSize = vec2( 1 ).div( mapSize ); + const dx0 = texelSize.x.negate().mul( radius ); + const dy0 = texelSize.y.negate().mul( radius ); + const dx1 = texelSize.x.mul( radius ); + const dy1 = texelSize.y.mul( radius ); + const dx2 = dx0.div( 2 ); + const dy2 = dy0.div( 2 ); + const dx3 = dx1.div( 2 ); + const dy3 = dy1.div( 2 ); - if ( defined( horizontal ) ) { + return add( + depthCompare( shadowCoord.xy.add( vec2( dx0, dy0 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( 0, dy0 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx1, dy0 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx2, dy2 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( 0, dy2 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx3, dy2 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx0, 0 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx2, 0 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy, shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx3, 0 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx1, 0 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx2, dy3 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( 0, dy3 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx3, dy3 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx0, dy1 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( 0, dy1 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx1, dy1 ) ), shadowCoord.z ) + ).mul( 1 / 17 ); - modelViewMatrix[ 0 ][ 0 ] = modelWorldMatrix[ 0 ].length(); - modelViewMatrix[ 0 ][ 1 ] = 0; - modelViewMatrix[ 0 ][ 2 ] = 0; +} ); - } +const PCFSoftShadowMap = Fn( ( { depthTexture, shadowCoord, shadow } ) => { - if ( defined( vertical ) ) { + const depthCompare = ( uv, compare ) => texture( depthTexture, uv ).compare( compare ); - modelViewMatrix[ 1 ][ 0 ] = 0; - modelViewMatrix[ 1 ][ 1 ] = modelWorldMatrix[ 1 ].length(); - modelViewMatrix[ 1 ][ 2 ] = 0; + const mapSize = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup ); - } + const texelSize = vec2( 1 ).div( mapSize ); + const dx = texelSize.x; + const dy = texelSize.y; - modelViewMatrix[ 2 ][ 0 ] = 0; - modelViewMatrix[ 2 ][ 1 ] = 0; - modelViewMatrix[ 2 ][ 2 ] = 1; + const uv = shadowCoord.xy; + const f = fract( uv.mul( mapSize ).add( 0.5 ) ); + uv.subAssign( f.mul( texelSize ) ); - return cameraProjectionMatrix.mul( modelViewMatrix ).mul( positionLocal ); + return add( + depthCompare( uv, shadowCoord.z ), + depthCompare( uv.add( vec2( dx, 0 ) ), shadowCoord.z ), + depthCompare( uv.add( vec2( 0, dy ) ), shadowCoord.z ), + depthCompare( uv.add( texelSize ), shadowCoord.z ), + mix( + depthCompare( uv.add( vec2( dx.negate(), 0 ) ), shadowCoord.z ), + depthCompare( uv.add( vec2( dx.mul( 2 ), 0 ) ), shadowCoord.z ), + f.x + ), + mix( + depthCompare( uv.add( vec2( dx.negate(), dy ) ), shadowCoord.z ), + depthCompare( uv.add( vec2( dx.mul( 2 ), dy ) ), shadowCoord.z ), + f.x + ), + mix( + depthCompare( uv.add( vec2( 0, dy.negate() ) ), shadowCoord.z ), + depthCompare( uv.add( vec2( 0, dy.mul( 2 ) ) ), shadowCoord.z ), + f.y + ), + mix( + depthCompare( uv.add( vec2( dx, dy.negate() ) ), shadowCoord.z ), + depthCompare( uv.add( vec2( dx, dy.mul( 2 ) ) ), shadowCoord.z ), + f.y + ), + mix( + mix( + depthCompare( uv.add( vec2( dx.negate(), dy.negate() ) ), shadowCoord.z ), + depthCompare( uv.add( vec2( dx.mul( 2 ), dy.negate() ) ), shadowCoord.z ), + f.x + ), + mix( + depthCompare( uv.add( vec2( dx.negate(), dy.mul( 2 ) ) ), shadowCoord.z ), + depthCompare( uv.add( vec2( dx.mul( 2 ), dy.mul( 2 ) ) ), shadowCoord.z ), + f.x + ), + f.y + ) + ).mul( 1 / 9 ); } ); -const viewportSafeUV = /*@__PURE__*/ Fn( ( [ uv = null ] ) => { +// VSM - const depth = linearDepth(); - const depthDiff = linearDepth( viewportDepthTexture( uv ) ).sub( depth ); - const finalUV = depthDiff.lessThan( 0 ).select( viewportUV, uv ); +const VSMShadowMapNode = Fn( ( { depthTexture, shadowCoord } ) => { - return finalUV; + const occlusion = float( 1 ).toVar(); -} ); + const distribution = texture( depthTexture ).uv( shadowCoord.xy ).rg; -const _matrixCache = new WeakMap(); + const hardShadow = step( shadowCoord.z, distribution.x ); -class VelocityNode extends TempNode { + If( hardShadow.notEqual( float( 1.0 ) ), () => { - constructor() { + const distance = shadowCoord.z.sub( distribution.x ); + const variance = max$1( 0, distribution.y.mul( distribution.y ) ); + let softnessProbability = variance.div( variance.add( distance.mul( distance ) ) ); // Chebeyshevs inequality + softnessProbability = clamp( sub( softnessProbability, 0.3 ).div( 0.95 - 0.3 ) ); + occlusion.assign( clamp( max$1( hardShadow, softnessProbability ) ) ); - super( 'vec2' ); + } ); - this.updateType = NodeUpdateType.OBJECT; - this.updateAfterType = NodeUpdateType.OBJECT; + return occlusion; - this.previousProjectionMatrix = uniform( new Matrix4() ); - this.previousModelViewMatrix = uniform( new Matrix4() ); +} ); - } +const VSMPassVertical = Fn( ( { samples, radius, size, shadowPass } ) => { - update( { camera, object } ) { + const mean = float( 0 ).toVar(); + const squaredMean = float( 0 ).toVar(); - const previousModelMatrix = getPreviousMatrix( object ); - const previousCameraMatrix = getPreviousMatrix( camera ); + const uvStride = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( 2 ).div( samples.sub( 1 ) ) ); + const uvStart = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( - 1 ) ); - this.previousModelViewMatrix.value.copy( previousModelMatrix ); - this.previousProjectionMatrix.value.copy( previousCameraMatrix ); + Loop( { start: int( 0 ), end: int( samples ), type: 'int', condition: '<' }, ( { i } ) => { - } + const uvOffset = uvStart.add( float( i ).mul( uvStride ) ); - updateAfter( { camera, object } ) { + const depth = shadowPass.uv( add( screenCoordinate.xy, vec2( 0, uvOffset ).mul( radius ) ).div( size ) ).x; + mean.addAssign( depth ); + squaredMean.addAssign( depth.mul( depth ) ); - const previousModelMatrix = getPreviousMatrix( object ); - const previousCameraMatrix = getPreviousMatrix( camera ); + } ); - previousModelMatrix.copy( object.modelViewMatrix ); - previousCameraMatrix.copy( camera.projectionMatrix ); + mean.divAssign( samples ); + squaredMean.divAssign( samples ); - } + const std_dev = sqrt( squaredMean.sub( mean.mul( mean ) ) ); + return vec2( mean, std_dev ); - setup( /*builder*/ ) { +} ); - const clipPositionCurrent = cameraProjectionMatrix.mul( modelViewMatrix ).mul( positionLocal ); - const clipPositionPrevious = this.previousProjectionMatrix.mul( this.previousModelViewMatrix ).mul( positionPrevious ); +const VSMPassHorizontal = Fn( ( { samples, radius, size, shadowPass } ) => { - const ndcPositionCurrent = clipPositionCurrent.xy.div( clipPositionCurrent.w ); - const ndcPositionPrevious = clipPositionPrevious.xy.div( clipPositionPrevious.w ); + const mean = float( 0 ).toVar(); + const squaredMean = float( 0 ).toVar(); - const velocity = sub( ndcPositionCurrent, ndcPositionPrevious ); + const uvStride = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( 2 ).div( samples.sub( 1 ) ) ); + const uvStart = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( - 1 ) ); - return velocity; + Loop( { start: int( 0 ), end: int( samples ), type: 'int', condition: '<' }, ( { i } ) => { - } + const uvOffset = uvStart.add( float( i ).mul( uvStride ) ); -} + const distribution = shadowPass.uv( add( screenCoordinate.xy, vec2( uvOffset, 0 ).mul( radius ) ).div( size ) ); + mean.addAssign( distribution.x ); + squaredMean.addAssign( add( distribution.y.mul( distribution.y ), distribution.x.mul( distribution.x ) ) ); -function getPreviousMatrix( object ) { + } ); - let previousMatrix = _matrixCache.get( object ); + mean.divAssign( samples ); + squaredMean.divAssign( samples ); - if ( previousMatrix === undefined ) { + const std_dev = sqrt( squaredMean.sub( mean.mul( mean ) ) ); + return vec2( mean, std_dev ); - previousMatrix = new Matrix4(); - _matrixCache.set( object, previousMatrix ); +} ); - } +const _shadowFilterLib = [ BasicShadowMap, PCFShadowMap, PCFSoftShadowMap, VSMShadowMapNode ]; - return previousMatrix; +// -} +let _overrideMaterial = null; +const _quadMesh$1 = /*@__PURE__*/ new QuadMesh(); -VelocityNode.type = /*@__PURE__*/ registerNode( 'Velocity', VelocityNode ); +class AnalyticLightNode extends LightingNode { -const velocity = /*@__PURE__*/ nodeImmutable( VelocityNode ); + static get type() { -const burn = /*@__PURE__*/ Fn( ( [ base, blend ] ) => { + return 'AnalyticLightNode'; - return min$1( 1.0, base.oneMinus().div( blend ) ).oneMinus(); + } -} ).setLayout( { - name: 'burnBlend', - type: 'vec3', - inputs: [ - { name: 'base', type: 'vec3' }, - { name: 'blend', type: 'vec3' } - ] -} ); + constructor( light = null ) { -const dodge = /*@__PURE__*/ Fn( ( [ base, blend ] ) => { + super(); - return min$1( base.div( blend.oneMinus() ), 1.0 ); + this.updateType = NodeUpdateType.FRAME; -} ).setLayout( { - name: 'dodgeBlend', - type: 'vec3', - inputs: [ - { name: 'base', type: 'vec3' }, - { name: 'blend', type: 'vec3' } - ] -} ); + this.light = light; -const screen = /*@__PURE__*/ Fn( ( [ base, blend ] ) => { + this.color = new Color(); + this.colorNode = uniform( this.color ).setGroup( renderGroup ); - return base.oneMinus().mul( blend.oneMinus() ).oneMinus(); + this.baseColorNode = null; -} ).setLayout( { - name: 'screenBlend', - type: 'vec3', - inputs: [ - { name: 'base', type: 'vec3' }, - { name: 'blend', type: 'vec3' } - ] -} ); + this.shadowMap = null; + this.shadowNode = null; + this.shadowColorNode = null; -const overlay = /*@__PURE__*/ Fn( ( [ base, blend ] ) => { + this.vsmShadowMapVertical = null; + this.vsmShadowMapHorizontal = null; - return mix( base.mul( 2.0 ).mul( blend ), base.oneMinus().mul( 2.0 ).mul( blend.oneMinus() ).oneMinus(), step( 0.5, base ) ); + this.vsmMaterialVertical = null; + this.vsmMaterialHorizontal = null; -} ).setLayout( { - name: 'overlayBlend', - type: 'vec3', - inputs: [ - { name: 'base', type: 'vec3' }, - { name: 'blend', type: 'vec3' } - ] -} ); + this.isAnalyticLightNode = true; -const motionBlur = /*@__PURE__*/ Fn( ( [ inputNode, velocity, numSamples = int( 16 ) ] ) => { + } - const sampleColor = ( uv ) => inputNode.uv( uv ); + getCacheKey() { - const uvs = uv(); + return hash$1( super.getCacheKey(), this.light.id, this.light.castShadow ? 1 : 0 ); - const colorResult = sampleColor( uvs ).toVar(); - const fSamples = float( numSamples ); + } - Loop( { start: int( 1 ), end: numSamples, type: 'int', condition: '<=' }, ( { i } ) => { + getHash() { - const offset = velocity.mul( float( i ).div( fSamples.sub( 1 ) ).sub( 0.5 ) ); - colorResult.addAssign( sampleColor( uvs.add( offset ) ) ); + return this.light.uuid; - } ); + } - colorResult.divAssign( fSamples ); + setupShadow( builder ) { - return colorResult; + const { object, renderer } = builder; -} ); + if ( renderer.shadowMap.enabled === false ) return; -const bleach = /*@__PURE__*/ Fn( ( [ color, opacity = 1 ] ) => { + let shadowColorNode = this.shadowColorNode; - const base = color; - const lum = luminance( base.rgb ); - const blend = vec3( lum ); + if ( shadowColorNode === null ) { - const L = min$1( 1.0, max$1( 0.0, float( 10.0 ).mul( lum.sub( 0.45 ) ) ) ); + if ( _overrideMaterial === null ) { - const result1 = blend.mul( base.rgb ).mul( 2.0 ); - const result2 = float( 2.0 ).mul( blend.oneMinus() ).mul( base.rgb.oneMinus() ).oneMinus(); + _overrideMaterial = new NodeMaterial(); + _overrideMaterial.fragmentNode = vec4( 0, 0, 0, 1 ); + _overrideMaterial.isShadowNodeMaterial = true; // Use to avoid other overrideMaterial override material.fragmentNode unintentionally when using material.shadowNode + _overrideMaterial.name = 'ShadowMaterial'; - const newColor = mix( result1, result2, L ); + } - const A2 = base.a.mul( opacity ); + const shadowMapType = renderer.shadowMap.type; + const shadow = this.light.shadow; - const mixRGB = A2.mul( newColor.rgb ); + const depthTexture = new DepthTexture(); + depthTexture.compareFunction = LessCompare; - mixRGB.addAssign( base.rgb.mul( A2.oneMinus() ) ); + const shadowMap = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height ); + shadowMap.depthTexture = depthTexture; - return vec4( mixRGB, base.a ); + shadow.camera.updateProjectionMatrix(); -} ); + // VSM -const sepia = /*@__PURE__*/ Fn( ( [ color ] ) => { + if ( shadowMapType === VSMShadowMap ) { - const c = vec3( color ); + depthTexture.compareFunction = null; // VSM does not use textureSampleCompare()/texture2DCompare() - // https://github.com/evanw/glfx.js/blob/master/src/filters/adjust/sepia.js + this.vsmShadowMapVertical = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height, { format: RGFormat, type: HalfFloatType } ); + this.vsmShadowMapHorizontal = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height, { format: RGFormat, type: HalfFloatType } ); - return vec4( - dot( c, vec3( 0.393, 0.769, 0.189 ) ), - dot( c, vec3( 0.349, 0.686, 0.168 ) ), - dot( c, vec3( 0.272, 0.534, 0.131 ) ), - color.a - ); + const shadowPassVertical = texture( depthTexture ); + const shadowPassHorizontal = texture( this.vsmShadowMapVertical.texture ); -} ); + const samples = reference( 'blurSamples', 'float', shadow ).setGroup( renderGroup ); + const radius = reference( 'radius', 'float', shadow ).setGroup( renderGroup ); + const size = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup ); -const sRGBToLinear = /*@__PURE__*/ Fn( ( [ color ] ) => { + let material = this.vsmMaterialVertical || ( this.vsmMaterialVertical = new NodeMaterial() ); + material.fragmentNode = VSMPassVertical( { samples, radius, size, shadowPass: shadowPassVertical } ).context( builder.getSharedContext() ); + material.name = 'VSMVertical'; - const a = color.mul( 0.9478672986 ).add( 0.0521327014 ).pow( 2.4 ); - const b = color.mul( 0.0773993808 ); - const factor = color.lessThanEqual( 0.04045 ); + material = this.vsmMaterialHorizontal || ( this.vsmMaterialHorizontal = new NodeMaterial() ); + material.fragmentNode = VSMPassHorizontal( { samples, radius, size, shadowPass: shadowPassHorizontal } ).context( builder.getSharedContext() ); + material.name = 'VSMHorizontal'; - const rgbResult = mix( a, b, factor ); + } - return rgbResult; + // -} ).setLayout( { - name: 'sRGBToLinear', - type: 'vec3', - inputs: [ - { name: 'color', type: 'vec3' } - ] -} ); + const shadowIntensity = reference( 'intensity', 'float', shadow ).setGroup( renderGroup ); + const bias = reference( 'bias', 'float', shadow ).setGroup( renderGroup ); + const normalBias = reference( 'normalBias', 'float', shadow ).setGroup( renderGroup ); -const LinearTosRGB = /*@__PURE__*/ Fn( ( [ color ] ) => { + const position = object.material.shadowPositionNode || positionWorld; - const a = color.pow( 0.41666 ).mul( 1.055 ).sub( 0.055 ); - const b = color.mul( 12.92 ); - const factor = color.lessThanEqual( 0.0031308 ); + let shadowCoord = uniform( shadow.matrix ).setGroup( renderGroup ).mul( position.add( normalWorld.mul( normalBias ) ) ); + shadowCoord = shadowCoord.xyz.div( shadowCoord.w ); - const rgbResult = mix( a, b, factor ); + let coordZ = shadowCoord.z.add( bias ); - return rgbResult; + if ( renderer.coordinateSystem === WebGPUCoordinateSystem ) { -} ).setLayout( { - name: 'LinearTosRGB', - type: 'vec3', - inputs: [ - { name: 'color', type: 'vec3' } - ] -} ); + coordZ = coordZ.mul( 2 ).sub( 1 ); // WebGPU: Convertion [ 0, 1 ] to [ - 1, 1 ] -var ColorSpaceFunctions = /*#__PURE__*/Object.freeze({ - __proto__: null, - LinearTosRGB: LinearTosRGB, - sRGBToLinear: sRGBToLinear -}); + } -// exposure only + shadowCoord = vec3( + shadowCoord.x, + shadowCoord.y.oneMinus(), // follow webgpu standards + coordZ + ); -const LinearToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { + const frustumTest = shadowCoord.x.greaterThanEqual( 0 ) + .and( shadowCoord.x.lessThanEqual( 1 ) ) + .and( shadowCoord.y.greaterThanEqual( 0 ) ) + .and( shadowCoord.y.lessThanEqual( 1 ) ) + .and( shadowCoord.z.lessThanEqual( 1 ) ); - return color.mul( exposure ).clamp(); + // -} ).setLayout( { - name: 'LinearToneMapping', - type: 'vec3', - inputs: [ - { name: 'color', type: 'vec3' }, - { name: 'exposure', type: 'float' } - ] -} ); + const filterFn = shadow.filterNode || _shadowFilterLib[ renderer.shadowMap.type ] || null; -// source: https://www.cs.utah.edu/docs/techreports/2002/pdf/UUCS-02-001.pdf + if ( filterFn === null ) { -const ReinhardToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { + throw new Error( 'THREE.WebGPURenderer: Shadow map type not supported yet.' ); - color = color.mul( exposure ); + } - return color.div( color.add( 1.0 ) ).clamp(); + const shadowColor = texture( shadowMap.texture, shadowCoord ); + const shadowNode = frustumTest.select( filterFn( { depthTexture: ( shadowMapType === VSMShadowMap ) ? this.vsmShadowMapHorizontal.texture : depthTexture, shadowCoord, shadow } ), float( 1 ) ); -} ).setLayout( { - name: 'ReinhardToneMapping', - type: 'vec3', - inputs: [ - { name: 'color', type: 'vec3' }, - { name: 'exposure', type: 'float' } - ] -} ); + this.shadowMap = shadowMap; + this.light.shadow.map = shadowMap; -// source: http://filmicworlds.com/blog/filmic-tonemapping-operators/ + this.shadowNode = shadowNode; + this.shadowColorNode = shadowColorNode = this.colorNode.mul( mix( 1, shadowNode.rgb.mix( shadowColor, 1 ), shadowIntensity.mul( shadowColor.a ) ) ); -const CineonToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { + this.baseColorNode = this.colorNode; - // filmic operator by Jim Hejl and Richard Burgess-Dawson - color = color.mul( exposure ); - color = color.sub( 0.004 ).max( 0.0 ); + } - const a = color.mul( color.mul( 6.2 ).add( 0.5 ) ); - const b = color.mul( color.mul( 6.2 ).add( 1.7 ) ).add( 0.06 ); + // - return a.div( b ).pow( 2.2 ); + this.colorNode = shadowColorNode; -} ).setLayout( { - name: 'CineonToneMapping', - type: 'vec3', - inputs: [ - { name: 'color', type: 'vec3' }, - { name: 'exposure', type: 'float' } - ] -} ); + this.updateBeforeType = NodeUpdateType.RENDER; -// source: https://github.com/selfshadow/ltc_code/blob/master/webgl/shaders/ltc/ltc_blit.fs + } -const RRTAndODTFit = /*@__PURE__*/ Fn( ( [ color ] ) => { + setup( builder ) { - const a = color.mul( color.add( 0.0245786 ) ).sub( 0.000090537 ); - const b = color.mul( color.add( 0.4329510 ).mul( 0.983729 ) ).add( 0.238081 ); + this.colorNode = this.baseColorNode || this.colorNode; - return a.div( b ); + if ( this.light.castShadow ) { -} ); + if ( builder.object.receiveShadow ) { -// source: https://github.com/selfshadow/ltc_code/blob/master/webgl/shaders/ltc/ltc_blit.fs + this.setupShadow( builder ); -const ACESFilmicToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { + } - // sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT - const ACESInputMat = mat3( - 0.59719, 0.35458, 0.04823, - 0.07600, 0.90834, 0.01566, - 0.02840, 0.13383, 0.83777 - ); + } else if ( this.shadowNode !== null ) { - // ODT_SAT => XYZ => D60_2_D65 => sRGB - const ACESOutputMat = mat3( - 1.60475, - 0.53108, - 0.07367, - - 0.10208, 1.10813, - 0.00605, - - 0.00327, - 0.07276, 1.07602 - ); + this.disposeShadow(); - color = color.mul( exposure ).div( 0.6 ); + } - color = ACESInputMat.mul( color ); + } - // Apply RRT and ODT - color = RRTAndODTFit( color ); + updateShadow( frame ) { - color = ACESOutputMat.mul( color ); + const { shadowMap, light } = this; + const { renderer, scene, camera } = frame; - // Clamp to [0, 1] - return color.clamp(); + const shadowType = renderer.shadowMap.type; -} ).setLayout( { - name: 'ACESFilmicToneMapping', - type: 'vec3', - inputs: [ - { name: 'color', type: 'vec3' }, - { name: 'exposure', type: 'float' } - ] -} ); + const depthVersion = shadowMap.depthTexture.version; + this._depthVersionCached = depthVersion; -const LINEAR_REC2020_TO_LINEAR_SRGB = /*@__PURE__*/ mat3( vec3( 1.6605, - 0.1246, - 0.0182 ), vec3( - 0.5876, 1.1329, - 0.1006 ), vec3( - 0.0728, - 0.0083, 1.1187 ) ); -const LINEAR_SRGB_TO_LINEAR_REC2020 = /*@__PURE__*/ mat3( vec3( 0.6274, 0.0691, 0.0164 ), vec3( 0.3293, 0.9195, 0.0880 ), vec3( 0.0433, 0.0113, 0.8956 ) ); + const currentOverrideMaterial = scene.overrideMaterial; -const agxDefaultContrastApprox = /*@__PURE__*/ Fn( ( [ x_immutable ] ) => { + scene.overrideMaterial = _overrideMaterial; - const x = vec3( x_immutable ).toVar(); - const x2 = vec3( x.mul( x ) ).toVar(); - const x4 = vec3( x2.mul( x2 ) ).toVar(); + shadowMap.setSize( light.shadow.mapSize.width, light.shadow.mapSize.height ); - return float( 15.5 ).mul( x4.mul( x2 ) ).sub( mul( 40.14, x4.mul( x ) ) ).add( mul( 31.96, x4 ).sub( mul( 6.868, x2.mul( x ) ) ).add( mul( 0.4298, x2 ).add( mul( 0.1191, x ).sub( 0.00232 ) ) ) ); + light.shadow.updateMatrices( light ); + light.shadow.camera.layers.mask = camera.layers.mask; -} ); + const currentRenderTarget = renderer.getRenderTarget(); + const currentRenderObjectFunction = renderer.getRenderObjectFunction(); -const AgXToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { + renderer.setRenderObjectFunction( ( object, ...params ) => { - const colortone = vec3( color ).toVar(); - const AgXInsetMatrix = mat3( vec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ), vec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ), vec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 ) ); - const AgXOutsetMatrix = mat3( vec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ), vec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ), vec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 ) ); - const AgxMinEv = float( - 12.47393 ); - const AgxMaxEv = float( 4.026069 ); - colortone.mulAssign( exposure ); - colortone.assign( LINEAR_SRGB_TO_LINEAR_REC2020.mul( colortone ) ); - colortone.assign( AgXInsetMatrix.mul( colortone ) ); - colortone.assign( max$1( colortone, 1e-10 ) ); - colortone.assign( log2( colortone ) ); - colortone.assign( colortone.sub( AgxMinEv ).div( AgxMaxEv.sub( AgxMinEv ) ) ); - colortone.assign( clamp( colortone, 0.0, 1.0 ) ); - colortone.assign( agxDefaultContrastApprox( colortone ) ); - colortone.assign( AgXOutsetMatrix.mul( colortone ) ); - colortone.assign( pow( max$1( vec3( 0.0 ), colortone ), vec3( 2.2 ) ) ); - colortone.assign( LINEAR_REC2020_TO_LINEAR_SRGB.mul( colortone ) ); - colortone.assign( clamp( colortone, 0.0, 1.0 ) ); + if ( object.castShadow === true || ( object.receiveShadow && shadowType === VSMShadowMap ) ) { - return colortone; + renderer.renderObject( object, ...params ); -} ).setLayout( { - name: 'AgXToneMapping', - type: 'vec3', - inputs: [ - { name: 'color', type: 'vec3' }, - { name: 'exposure', type: 'float' } - ] -} ); + } -// https://modelviewer.dev/examples/tone-mapping + } ); -const NeutralToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { + renderer.setRenderTarget( shadowMap ); + renderer.render( scene, light.shadow.camera ); - const StartCompression = float( 0.8 - 0.04 ); - const Desaturation = float( 0.15 ); + renderer.setRenderObjectFunction( currentRenderObjectFunction ); - color = color.mul( exposure ); + // vsm blur pass - const x = min$1( color.r, min$1( color.g, color.b ) ); - const offset = select( x.lessThan( 0.08 ), x.sub( mul( 6.25, x.mul( x ) ) ), 0.04 ); + if ( light.isPointLight !== true && shadowType === VSMShadowMap ) { - color.subAssign( offset ); + this.vsmPass( frame, light ); - const peak = max$1( color.r, max$1( color.g, color.b ) ); + } - If( peak.lessThan( StartCompression ), () => { + renderer.setRenderTarget( currentRenderTarget ); - return color; + scene.overrideMaterial = currentOverrideMaterial; - } ); + } - const d = sub( 1, StartCompression ); - const newPeak = sub( 1, d.mul( d ).div( peak.add( d.sub( StartCompression ) ) ) ); - color.mulAssign( newPeak.div( peak ) ); - const g = sub( 1, div( 1, Desaturation.mul( peak.sub( newPeak ) ).add( 1 ) ) ); + vsmPass( frame, light ) { - return mix( color, vec3( newPeak ), g ); + const { renderer } = frame; -} ).setLayout( { - name: 'NeutralToneMapping', - type: 'vec3', - inputs: [ - { name: 'color', type: 'vec3' }, - { name: 'exposure', type: 'float' } - ] -} ); + this.vsmShadowMapVertical.setSize( light.shadow.mapSize.width, light.shadow.mapSize.height ); + this.vsmShadowMapHorizontal.setSize( light.shadow.mapSize.width, light.shadow.mapSize.height ); -var ToneMappingFunctions = /*#__PURE__*/Object.freeze({ - __proto__: null, - ACESFilmicToneMapping: ACESFilmicToneMapping, - AgXToneMapping: AgXToneMapping, - CineonToneMapping: CineonToneMapping, - LinearToneMapping: LinearToneMapping, - NeutralToneMapping: NeutralToneMapping, - ReinhardToneMapping: ReinhardToneMapping -}); + renderer.setRenderTarget( this.vsmShadowMapVertical ); + _quadMesh$1.material = this.vsmMaterialVertical; + _quadMesh$1.render( renderer ); -const checker = /*@__PURE__*/ Fn( ( [ coord = uv() ] ) => { + renderer.setRenderTarget( this.vsmShadowMapHorizontal ); + _quadMesh$1.material = this.vsmMaterialHorizontal; + _quadMesh$1.render( renderer ); - const uv = coord.mul( 2.0 ); + } - const cx = uv.x.floor(); - const cy = uv.y.floor(); - const result = cx.add( cy ).mod( 2.0 ); + disposeShadow() { - return result.sign(); + this.shadowMap.dispose(); + this.shadowMap = null; -} ); + if ( this.vsmShadowMapVertical !== null ) { -// Three.js Transpiler -// https://raw.githubusercontent.com/AcademySoftwareFoundation/MaterialX/main/libraries/stdlib/genglsl/lib/mx_noise.glsl + this.vsmShadowMapVertical.dispose(); + this.vsmShadowMapVertical = null; + this.vsmMaterialVertical.dispose(); + this.vsmMaterialVertical = null; + } -const mx_select = /*@__PURE__*/ Fn( ( [ b_immutable, t_immutable, f_immutable ] ) => { + if ( this.vsmShadowMapHorizontal !== null ) { - const f = float( f_immutable ).toVar(); - const t = float( t_immutable ).toVar(); - const b = bool( b_immutable ).toVar(); + this.vsmShadowMapHorizontal.dispose(); + this.vsmShadowMapHorizontal = null; - return select( b, t, f ); + this.vsmMaterialHorizontal.dispose(); + this.vsmMaterialHorizontal = null; -} ).setLayout( { - name: 'mx_select', - type: 'float', - inputs: [ - { name: 'b', type: 'bool' }, - { name: 't', type: 'float' }, - { name: 'f', type: 'float' } - ] -} ); + } -const mx_negate_if = /*@__PURE__*/ Fn( ( [ val_immutable, b_immutable ] ) => { + this.shadowNode = null; + this.shadowColorNode = null; - const b = bool( b_immutable ).toVar(); - const val = float( val_immutable ).toVar(); + this.baseColorNode = null; - return select( b, val.negate(), val ); + this.updateBeforeType = NodeUpdateType.NONE; -} ).setLayout( { - name: 'mx_negate_if', - type: 'float', - inputs: [ - { name: 'val', type: 'float' }, - { name: 'b', type: 'bool' } - ] -} ); + } -const mx_floor = /*@__PURE__*/ Fn( ( [ x_immutable ] ) => { + updateBefore( frame ) { - const x = float( x_immutable ).toVar(); + const shadow = this.light.shadow; - return int( floor( x ) ); + const needsUpdate = shadow.needsUpdate || shadow.autoUpdate; -} ).setLayout( { - name: 'mx_floor', - type: 'int', - inputs: [ - { name: 'x', type: 'float' } - ] -} ); + if ( needsUpdate ) { -const mx_floorfrac = /*@__PURE__*/ Fn( ( [ x_immutable, i ] ) => { + this.updateShadow( frame ); - const x = float( x_immutable ).toVar(); - i.assign( mx_floor( x ) ); + if ( this.shadowMap.depthTexture.version === this._depthVersionCached ) { - return x.sub( float( i ) ); + shadow.needsUpdate = false; -} ); + } -const mx_bilerp_0 = /*@__PURE__*/ Fn( ( [ v0_immutable, v1_immutable, v2_immutable, v3_immutable, s_immutable, t_immutable ] ) => { + } - const t = float( t_immutable ).toVar(); - const s = float( s_immutable ).toVar(); - const v3 = float( v3_immutable ).toVar(); - const v2 = float( v2_immutable ).toVar(); - const v1 = float( v1_immutable ).toVar(); - const v0 = float( v0_immutable ).toVar(); - const s1 = float( sub( 1.0, s ) ).toVar(); + } - return sub( 1.0, t ).mul( v0.mul( s1 ).add( v1.mul( s ) ) ).add( t.mul( v2.mul( s1 ).add( v3.mul( s ) ) ) ); + update( /*frame*/ ) { -} ).setLayout( { - name: 'mx_bilerp_0', - type: 'float', - inputs: [ - { name: 'v0', type: 'float' }, - { name: 'v1', type: 'float' }, - { name: 'v2', type: 'float' }, - { name: 'v3', type: 'float' }, - { name: 's', type: 'float' }, - { name: 't', type: 'float' } - ] -} ); + const { light } = this; -const mx_bilerp_1 = /*@__PURE__*/ Fn( ( [ v0_immutable, v1_immutable, v2_immutable, v3_immutable, s_immutable, t_immutable ] ) => { + this.color.copy( light.color ).multiplyScalar( light.intensity ); - const t = float( t_immutable ).toVar(); - const s = float( s_immutable ).toVar(); - const v3 = vec3( v3_immutable ).toVar(); - const v2 = vec3( v2_immutable ).toVar(); - const v1 = vec3( v1_immutable ).toVar(); - const v0 = vec3( v0_immutable ).toVar(); - const s1 = float( sub( 1.0, s ) ).toVar(); + } - return sub( 1.0, t ).mul( v0.mul( s1 ).add( v1.mul( s ) ) ).add( t.mul( v2.mul( s1 ).add( v3.mul( s ) ) ) ); +} -} ).setLayout( { - name: 'mx_bilerp_1', - type: 'vec3', - inputs: [ - { name: 'v0', type: 'vec3' }, - { name: 'v1', type: 'vec3' }, - { name: 'v2', type: 'vec3' }, - { name: 'v3', type: 'vec3' }, - { name: 's', type: 'float' }, - { name: 't', type: 'float' } - ] -} ); +const getDistanceAttenuation = /*@__PURE__*/ Fn( ( inputs ) => { -const mx_bilerp = /*@__PURE__*/ overloadingFn( [ mx_bilerp_0, mx_bilerp_1 ] ); + const { lightDistance, cutoffDistance, decayExponent } = inputs; -const mx_trilerp_0 = /*@__PURE__*/ Fn( ( [ v0_immutable, v1_immutable, v2_immutable, v3_immutable, v4_immutable, v5_immutable, v6_immutable, v7_immutable, s_immutable, t_immutable, r_immutable ] ) => { + // based upon Frostbite 3 Moving to Physically-based Rendering + // page 32, equation 26: E[window1] + // https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf + const distanceFalloff = lightDistance.pow( decayExponent ).max( 0.01 ).reciprocal(); - const r = float( r_immutable ).toVar(); - const t = float( t_immutable ).toVar(); - const s = float( s_immutable ).toVar(); - const v7 = float( v7_immutable ).toVar(); - const v6 = float( v6_immutable ).toVar(); - const v5 = float( v5_immutable ).toVar(); - const v4 = float( v4_immutable ).toVar(); - const v3 = float( v3_immutable ).toVar(); - const v2 = float( v2_immutable ).toVar(); - const v1 = float( v1_immutable ).toVar(); - const v0 = float( v0_immutable ).toVar(); - const s1 = float( sub( 1.0, s ) ).toVar(); - const t1 = float( sub( 1.0, t ) ).toVar(); - const r1 = float( sub( 1.0, r ) ).toVar(); + return cutoffDistance.greaterThan( 0 ).select( + distanceFalloff.mul( lightDistance.div( cutoffDistance ).pow4().oneMinus().clamp().pow2() ), + distanceFalloff + ); - return r1.mul( t1.mul( v0.mul( s1 ).add( v1.mul( s ) ) ).add( t.mul( v2.mul( s1 ).add( v3.mul( s ) ) ) ) ).add( r.mul( t1.mul( v4.mul( s1 ).add( v5.mul( s ) ) ).add( t.mul( v6.mul( s1 ).add( v7.mul( s ) ) ) ) ) ); +} ); // validated -} ).setLayout( { - name: 'mx_trilerp_0', - type: 'float', - inputs: [ - { name: 'v0', type: 'float' }, - { name: 'v1', type: 'float' }, - { name: 'v2', type: 'float' }, - { name: 'v3', type: 'float' }, - { name: 'v4', type: 'float' }, - { name: 'v5', type: 'float' }, - { name: 'v6', type: 'float' }, - { name: 'v7', type: 'float' }, - { name: 's', type: 'float' }, - { name: 't', type: 'float' }, - { name: 'r', type: 'float' } - ] -} ); +let uniformsLib; -const mx_trilerp_1 = /*@__PURE__*/ Fn( ( [ v0_immutable, v1_immutable, v2_immutable, v3_immutable, v4_immutable, v5_immutable, v6_immutable, v7_immutable, s_immutable, t_immutable, r_immutable ] ) => { +function getLightData( light ) { - const r = float( r_immutable ).toVar(); - const t = float( t_immutable ).toVar(); - const s = float( s_immutable ).toVar(); - const v7 = vec3( v7_immutable ).toVar(); - const v6 = vec3( v6_immutable ).toVar(); - const v5 = vec3( v5_immutable ).toVar(); - const v4 = vec3( v4_immutable ).toVar(); - const v3 = vec3( v3_immutable ).toVar(); - const v2 = vec3( v2_immutable ).toVar(); - const v1 = vec3( v1_immutable ).toVar(); - const v0 = vec3( v0_immutable ).toVar(); - const s1 = float( sub( 1.0, s ) ).toVar(); - const t1 = float( sub( 1.0, t ) ).toVar(); - const r1 = float( sub( 1.0, r ) ).toVar(); + uniformsLib = uniformsLib || new WeakMap(); - return r1.mul( t1.mul( v0.mul( s1 ).add( v1.mul( s ) ) ).add( t.mul( v2.mul( s1 ).add( v3.mul( s ) ) ) ) ).add( r.mul( t1.mul( v4.mul( s1 ).add( v5.mul( s ) ) ).add( t.mul( v6.mul( s1 ).add( v7.mul( s ) ) ) ) ) ); + let uniforms = uniformsLib.get( light ); -} ).setLayout( { - name: 'mx_trilerp_1', - type: 'vec3', - inputs: [ - { name: 'v0', type: 'vec3' }, - { name: 'v1', type: 'vec3' }, - { name: 'v2', type: 'vec3' }, - { name: 'v3', type: 'vec3' }, - { name: 'v4', type: 'vec3' }, - { name: 'v5', type: 'vec3' }, - { name: 'v6', type: 'vec3' }, - { name: 'v7', type: 'vec3' }, - { name: 's', type: 'float' }, - { name: 't', type: 'float' }, - { name: 'r', type: 'float' } - ] -} ); + if ( uniforms === undefined ) uniformsLib.set( light, uniforms = {} ); -const mx_trilerp = /*@__PURE__*/ overloadingFn( [ mx_trilerp_0, mx_trilerp_1 ] ); + return uniforms; -const mx_gradient_float_0 = /*@__PURE__*/ Fn( ( [ hash_immutable, x_immutable, y_immutable ] ) => { +} - const y = float( y_immutable ).toVar(); - const x = float( x_immutable ).toVar(); - const hash = uint( hash_immutable ).toVar(); - const h = uint( hash.bitAnd( uint( 7 ) ) ).toVar(); - const u = float( mx_select( h.lessThan( uint( 4 ) ), x, y ) ).toVar(); - const v = float( mul( 2.0, mx_select( h.lessThan( uint( 4 ) ), y, x ) ) ).toVar(); +function lightPosition( light ) { - return mx_negate_if( u, bool( h.bitAnd( uint( 1 ) ) ) ).add( mx_negate_if( v, bool( h.bitAnd( uint( 2 ) ) ) ) ); + const data = getLightData( light ); -} ).setLayout( { - name: 'mx_gradient_float_0', - type: 'float', - inputs: [ - { name: 'hash', type: 'uint' }, - { name: 'x', type: 'float' }, - { name: 'y', type: 'float' } - ] -} ); + return data.position || ( data.position = uniform( new Vector3() ).setGroup( renderGroup ).onRenderUpdate( ( _, self ) => self.value.setFromMatrixPosition( light.matrixWorld ) ) ); -const mx_gradient_float_1 = /*@__PURE__*/ Fn( ( [ hash_immutable, x_immutable, y_immutable, z_immutable ] ) => { +} - const z = float( z_immutable ).toVar(); - const y = float( y_immutable ).toVar(); - const x = float( x_immutable ).toVar(); - const hash = uint( hash_immutable ).toVar(); - const h = uint( hash.bitAnd( uint( 15 ) ) ).toVar(); - const u = float( mx_select( h.lessThan( uint( 8 ) ), x, y ) ).toVar(); - const v = float( mx_select( h.lessThan( uint( 4 ) ), y, mx_select( h.equal( uint( 12 ) ).or( h.equal( uint( 14 ) ) ), x, z ) ) ).toVar(); +function lightTargetPosition( light ) { - return mx_negate_if( u, bool( h.bitAnd( uint( 1 ) ) ) ).add( mx_negate_if( v, bool( h.bitAnd( uint( 2 ) ) ) ) ); + const data = getLightData( light ); -} ).setLayout( { - name: 'mx_gradient_float_1', - type: 'float', - inputs: [ - { name: 'hash', type: 'uint' }, - { name: 'x', type: 'float' }, - { name: 'y', type: 'float' }, - { name: 'z', type: 'float' } - ] -} ); + return data.targetPosition || ( data.targetPosition = uniform( new Vector3() ).setGroup( renderGroup ).onRenderUpdate( ( _, self ) => self.value.setFromMatrixPosition( light.target.matrixWorld ) ) ); -const mx_gradient_float = /*@__PURE__*/ overloadingFn( [ mx_gradient_float_0, mx_gradient_float_1 ] ); +} -const mx_gradient_vec3_0 = /*@__PURE__*/ Fn( ( [ hash_immutable, x_immutable, y_immutable ] ) => { +function lightViewPosition( light ) { - const y = float( y_immutable ).toVar(); - const x = float( x_immutable ).toVar(); - const hash = uvec3( hash_immutable ).toVar(); + const data = getLightData( light ); - return vec3( mx_gradient_float( hash.x, x, y ), mx_gradient_float( hash.y, x, y ), mx_gradient_float( hash.z, x, y ) ); + return data.viewPosition || ( data.viewPosition = uniform( new Vector3() ).setGroup( renderGroup ).onRenderUpdate( ( { camera }, self ) => { -} ).setLayout( { - name: 'mx_gradient_vec3_0', - type: 'vec3', - inputs: [ - { name: 'hash', type: 'uvec3' }, - { name: 'x', type: 'float' }, - { name: 'y', type: 'float' } - ] -} ); + self.value = self.value || new Vector3(); + self.value.setFromMatrixPosition( light.matrixWorld ); -const mx_gradient_vec3_1 = /*@__PURE__*/ Fn( ( [ hash_immutable, x_immutable, y_immutable, z_immutable ] ) => { + self.value.applyMatrix4( camera.matrixWorldInverse ); - const z = float( z_immutable ).toVar(); - const y = float( y_immutable ).toVar(); - const x = float( x_immutable ).toVar(); - const hash = uvec3( hash_immutable ).toVar(); + } ) ); - return vec3( mx_gradient_float( hash.x, x, y, z ), mx_gradient_float( hash.y, x, y, z ), mx_gradient_float( hash.z, x, y, z ) ); +} -} ).setLayout( { - name: 'mx_gradient_vec3_1', - type: 'vec3', - inputs: [ - { name: 'hash', type: 'uvec3' }, - { name: 'x', type: 'float' }, - { name: 'y', type: 'float' }, - { name: 'z', type: 'float' } - ] -} ); +const lightTargetDirection = ( light ) => cameraViewMatrix.transformDirection( lightPosition( light ).sub( lightTargetPosition( light ) ) ); -const mx_gradient_vec3 = /*@__PURE__*/ overloadingFn( [ mx_gradient_vec3_0, mx_gradient_vec3_1 ] ); +const hash = /*@__PURE__*/ Fn( ( [ seed ] ) => { -const mx_gradient_scale2d_0 = /*@__PURE__*/ Fn( ( [ v_immutable ] ) => { + // Taken from https://www.shadertoy.com/view/XlGcRh, originally from pcg-random.org - const v = float( v_immutable ).toVar(); + const state = seed.toUint().mul( 747796405 ).add( 2891336453 ); + const word = state.shiftRight( state.shiftRight( 28 ).add( 4 ) ).bitXor( state ).mul( 277803737 ); + const result = word.shiftRight( 22 ).bitXor( word ); - return mul( 0.6616, v ); + return result.toFloat().mul( 1 / 2 ** 32 ); // Convert to range [0, 1) -} ).setLayout( { - name: 'mx_gradient_scale2d_0', - type: 'float', - inputs: [ - { name: 'v', type: 'float' } - ] } ); -const mx_gradient_scale3d_0 = /*@__PURE__*/ Fn( ( [ v_immutable ] ) => { - - const v = float( v_immutable ).toVar(); +// remapping functions https://iquilezles.org/articles/functions/ +const parabola = ( x, k ) => pow( mul( 4.0, x.mul( sub( 1.0, x ) ) ), k ); +const gain = ( x, k ) => x.lessThan( 0.5 ) ? parabola( x.mul( 2.0 ), k ).div( 2.0 ) : sub( 1.0, parabola( mul( sub( 1.0, x ), 2.0 ), k ).div( 2.0 ) ); +const pcurve = ( x, a, b ) => pow( div( pow( x, a ), add( pow( x, a ), pow( sub( 1.0, x ), b ) ) ), 1.0 / a ); +const sinc = ( x, k ) => sin( PI.mul( k.mul( x ).sub( 1.0 ) ) ).div( PI.mul( k.mul( x ).sub( 1.0 ) ) ); - return mul( 0.9820, v ); +// https://github.com/cabbibo/glsl-tri-noise-3d + + +const tri = /*@__PURE__*/ Fn( ( [ x ] ) => { + + return x.fract().sub( .5 ).abs(); } ).setLayout( { - name: 'mx_gradient_scale3d_0', + name: 'tri', type: 'float', inputs: [ - { name: 'v', type: 'float' } + { name: 'x', type: 'float' } ] } ); -const mx_gradient_scale2d_1 = /*@__PURE__*/ Fn( ( [ v_immutable ] ) => { - - const v = vec3( v_immutable ).toVar(); +const tri3 = /*@__PURE__*/ Fn( ( [ p ] ) => { - return mul( 0.6616, v ); + return vec3( tri( p.z.add( tri( p.y.mul( 1. ) ) ) ), tri( p.z.add( tri( p.x.mul( 1. ) ) ) ), tri( p.y.add( tri( p.x.mul( 1. ) ) ) ) ); } ).setLayout( { - name: 'mx_gradient_scale2d_1', + name: 'tri3', type: 'vec3', inputs: [ - { name: 'v', type: 'vec3' } + { name: 'p', type: 'vec3' } ] } ); -const mx_gradient_scale2d = /*@__PURE__*/ overloadingFn( [ mx_gradient_scale2d_0, mx_gradient_scale2d_1 ] ); - -const mx_gradient_scale3d_1 = /*@__PURE__*/ Fn( ( [ v_immutable ] ) => { - - const v = vec3( v_immutable ).toVar(); +const triNoise3D = /*@__PURE__*/ Fn( ( [ p_immutable, spd, time ] ) => { - return mul( 0.9820, v ); + const p = vec3( p_immutable ).toVar(); + const z = float( 1.4 ).toVar(); + const rz = float( 0.0 ).toVar(); + const bp = vec3( p ).toVar(); -} ).setLayout( { - name: 'mx_gradient_scale3d_1', - type: 'vec3', - inputs: [ - { name: 'v', type: 'vec3' } - ] -} ); + Loop( { start: float( 0.0 ), end: float( 3.0 ), type: 'float', condition: '<=' }, () => { -const mx_gradient_scale3d = /*@__PURE__*/ overloadingFn( [ mx_gradient_scale3d_0, mx_gradient_scale3d_1 ] ); + const dg = vec3( tri3( bp.mul( 2.0 ) ) ).toVar(); + p.addAssign( dg.add( time.mul( float( 0.1 ).mul( spd ) ) ) ); + bp.mulAssign( 1.8 ); + z.mulAssign( 1.5 ); + p.mulAssign( 1.2 ); -const mx_rotl32 = /*@__PURE__*/ Fn( ( [ x_immutable, k_immutable ] ) => { + const t = float( tri( p.z.add( tri( p.x.add( tri( p.y ) ) ) ) ) ).toVar(); + rz.addAssign( t.div( z ) ); + bp.addAssign( 0.14 ); - const k = int( k_immutable ).toVar(); - const x = uint( x_immutable ).toVar(); + } ); - return x.shiftLeft( k ).bitOr( x.shiftRight( int( 32 ).sub( k ) ) ); + return rz; } ).setLayout( { - name: 'mx_rotl32', - type: 'uint', + name: 'triNoise3D', + type: 'float', inputs: [ - { name: 'x', type: 'uint' }, - { name: 'k', type: 'int' } + { name: 'p', type: 'vec3' }, + { name: 'spd', type: 'float' }, + { name: 'time', type: 'float' } ] } ); -const mx_bjmix = /*@__PURE__*/ Fn( ( [ a, b, c ] ) => { +const rotateUV = /*@__PURE__*/ Fn( ( [ uv, rotation, center = vec2( 0.5 ) ] ) => { - a.subAssign( c ); - a.bitXorAssign( mx_rotl32( c, int( 4 ) ) ); - c.addAssign( b ); - b.subAssign( a ); - b.bitXorAssign( mx_rotl32( a, int( 6 ) ) ); - a.addAssign( c ); - c.subAssign( b ); - c.bitXorAssign( mx_rotl32( b, int( 8 ) ) ); - b.addAssign( a ); - a.subAssign( c ); - a.bitXorAssign( mx_rotl32( c, int( 16 ) ) ); - c.addAssign( b ); - b.subAssign( a ); - b.bitXorAssign( mx_rotl32( a, int( 19 ) ) ); - a.addAssign( c ); - c.subAssign( b ); - c.bitXorAssign( mx_rotl32( b, int( 4 ) ) ); - b.addAssign( a ); + return rotate( uv.sub( center ), rotation ).add( center ); } ); -const mx_bjfinal = /*@__PURE__*/ Fn( ( [ a_immutable, b_immutable, c_immutable ] ) => { +const spherizeUV = /*@__PURE__*/ Fn( ( [ uv, strength, center = vec2( 0.5 ) ] ) => { - const c = uint( c_immutable ).toVar(); - const b = uint( b_immutable ).toVar(); - const a = uint( a_immutable ).toVar(); - c.bitXorAssign( b ); - c.subAssign( mx_rotl32( b, int( 14 ) ) ); - a.bitXorAssign( c ); - a.subAssign( mx_rotl32( c, int( 11 ) ) ); - b.bitXorAssign( a ); - b.subAssign( mx_rotl32( a, int( 25 ) ) ); - c.bitXorAssign( b ); - c.subAssign( mx_rotl32( b, int( 16 ) ) ); - a.bitXorAssign( c ); - a.subAssign( mx_rotl32( c, int( 4 ) ) ); - b.bitXorAssign( a ); - b.subAssign( mx_rotl32( a, int( 14 ) ) ); - c.bitXorAssign( b ); - c.subAssign( mx_rotl32( b, int( 24 ) ) ); + const delta = uv.sub( center ); + const delta2 = delta.dot( delta ); + const delta4 = delta2.mul( delta2 ); + const deltaOffset = delta4.mul( strength ); - return c; + return uv.add( delta.mul( deltaOffset ) ); -} ).setLayout( { - name: 'mx_bjfinal', - type: 'uint', - inputs: [ - { name: 'a', type: 'uint' }, - { name: 'b', type: 'uint' }, - { name: 'c', type: 'uint' } - ] } ); -const mx_bits_to_01 = /*@__PURE__*/ Fn( ( [ bits_immutable ] ) => { +const billboarding = /*@__PURE__*/ Fn( ( { position = null, horizontal = true, vertical = false } ) => { - const bits = uint( bits_immutable ).toVar(); + let worldMatrix; - return float( bits ).div( float( uint( int( 0xffffffff ) ) ) ); + if ( position !== null ) { -} ).setLayout( { - name: 'mx_bits_to_01', - type: 'float', - inputs: [ - { name: 'bits', type: 'uint' } - ] -} ); + worldMatrix = modelWorldMatrix.toVar(); + worldMatrix[ 3 ][ 0 ] = position.x; + worldMatrix[ 3 ][ 1 ] = position.y; + worldMatrix[ 3 ][ 2 ] = position.z; -const mx_fade = /*@__PURE__*/ Fn( ( [ t_immutable ] ) => { + } else { - const t = float( t_immutable ).toVar(); + worldMatrix = modelWorldMatrix; - return t.mul( t ).mul( t ).mul( t.mul( t.mul( 6.0 ).sub( 15.0 ) ).add( 10.0 ) ); + } -} ).setLayout( { - name: 'mx_fade', - type: 'float', - inputs: [ - { name: 't', type: 'float' } - ] -} ); + const modelViewMatrix = cameraViewMatrix.mul( worldMatrix ); -const mx_hash_int_0 = /*@__PURE__*/ Fn( ( [ x_immutable ] ) => { + if ( defined( horizontal ) ) { - const x = int( x_immutable ).toVar(); - const len = uint( uint( 1 ) ).toVar(); - const seed = uint( uint( int( 0xdeadbeef ) ).add( len.shiftLeft( uint( 2 ) ) ).add( uint( 13 ) ) ).toVar(); + modelViewMatrix[ 0 ][ 0 ] = modelWorldMatrix[ 0 ].length(); + modelViewMatrix[ 0 ][ 1 ] = 0; + modelViewMatrix[ 0 ][ 2 ] = 0; - return mx_bjfinal( seed.add( uint( x ) ), seed, seed ); + } -} ).setLayout( { - name: 'mx_hash_int_0', - type: 'uint', - inputs: [ - { name: 'x', type: 'int' } - ] -} ); + if ( defined( vertical ) ) { -const mx_hash_int_1 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable ] ) => { + modelViewMatrix[ 1 ][ 0 ] = 0; + modelViewMatrix[ 1 ][ 1 ] = modelWorldMatrix[ 1 ].length(); + modelViewMatrix[ 1 ][ 2 ] = 0; - const y = int( y_immutable ).toVar(); - const x = int( x_immutable ).toVar(); - const len = uint( uint( 2 ) ).toVar(); - const a = uint().toVar(), b = uint().toVar(), c = uint().toVar(); - a.assign( b.assign( c.assign( uint( int( 0xdeadbeef ) ).add( len.shiftLeft( uint( 2 ) ) ).add( uint( 13 ) ) ) ) ); - a.addAssign( uint( x ) ); - b.addAssign( uint( y ) ); + } - return mx_bjfinal( a, b, c ); + modelViewMatrix[ 2 ][ 0 ] = 0; + modelViewMatrix[ 2 ][ 1 ] = 0; + modelViewMatrix[ 2 ][ 2 ] = 1; + + return cameraProjectionMatrix.mul( modelViewMatrix ).mul( positionLocal ); -} ).setLayout( { - name: 'mx_hash_int_1', - type: 'uint', - inputs: [ - { name: 'x', type: 'int' }, - { name: 'y', type: 'int' } - ] } ); -const mx_hash_int_2 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable, z_immutable ] ) => { +const viewportSafeUV = /*@__PURE__*/ Fn( ( [ uv = null ] ) => { - const z = int( z_immutable ).toVar(); - const y = int( y_immutable ).toVar(); - const x = int( x_immutable ).toVar(); - const len = uint( uint( 3 ) ).toVar(); - const a = uint().toVar(), b = uint().toVar(), c = uint().toVar(); - a.assign( b.assign( c.assign( uint( int( 0xdeadbeef ) ).add( len.shiftLeft( uint( 2 ) ) ).add( uint( 13 ) ) ) ) ); - a.addAssign( uint( x ) ); - b.addAssign( uint( y ) ); - c.addAssign( uint( z ) ); + const depth = linearDepth(); + const depthDiff = linearDepth( viewportDepthTexture( uv ) ).sub( depth ); + const finalUV = depthDiff.lessThan( 0 ).select( screenUV, uv ); - return mx_bjfinal( a, b, c ); + return finalUV; -} ).setLayout( { - name: 'mx_hash_int_2', - type: 'uint', - inputs: [ - { name: 'x', type: 'int' }, - { name: 'y', type: 'int' }, - { name: 'z', type: 'int' } - ] } ); -const mx_hash_int_3 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable, z_immutable, xx_immutable ] ) => { +const _objectData = new WeakMap(); - const xx = int( xx_immutable ).toVar(); - const z = int( z_immutable ).toVar(); - const y = int( y_immutable ).toVar(); - const x = int( x_immutable ).toVar(); - const len = uint( uint( 4 ) ).toVar(); - const a = uint().toVar(), b = uint().toVar(), c = uint().toVar(); - a.assign( b.assign( c.assign( uint( int( 0xdeadbeef ) ).add( len.shiftLeft( uint( 2 ) ) ).add( uint( 13 ) ) ) ) ); - a.addAssign( uint( x ) ); - b.addAssign( uint( y ) ); - c.addAssign( uint( z ) ); - mx_bjmix( a, b, c ); - a.addAssign( uint( xx ) ); +class VelocityNode extends TempNode { - return mx_bjfinal( a, b, c ); + static get type() { -} ).setLayout( { - name: 'mx_hash_int_3', - type: 'uint', - inputs: [ - { name: 'x', type: 'int' }, - { name: 'y', type: 'int' }, - { name: 'z', type: 'int' }, - { name: 'xx', type: 'int' } - ] -} ); + return 'VelocityNode'; -const mx_hash_int_4 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable, z_immutable, xx_immutable, yy_immutable ] ) => { + } - const yy = int( yy_immutable ).toVar(); - const xx = int( xx_immutable ).toVar(); - const z = int( z_immutable ).toVar(); - const y = int( y_immutable ).toVar(); - const x = int( x_immutable ).toVar(); - const len = uint( uint( 5 ) ).toVar(); - const a = uint().toVar(), b = uint().toVar(), c = uint().toVar(); - a.assign( b.assign( c.assign( uint( int( 0xdeadbeef ) ).add( len.shiftLeft( uint( 2 ) ) ).add( uint( 13 ) ) ) ) ); - a.addAssign( uint( x ) ); - b.addAssign( uint( y ) ); - c.addAssign( uint( z ) ); - mx_bjmix( a, b, c ); - a.addAssign( uint( xx ) ); - b.addAssign( uint( yy ) ); + constructor() { - return mx_bjfinal( a, b, c ); + super( 'vec2' ); -} ).setLayout( { - name: 'mx_hash_int_4', - type: 'uint', - inputs: [ - { name: 'x', type: 'int' }, - { name: 'y', type: 'int' }, - { name: 'z', type: 'int' }, - { name: 'xx', type: 'int' }, - { name: 'yy', type: 'int' } - ] -} ); + this.updateType = NodeUpdateType.OBJECT; + this.updateAfterType = NodeUpdateType.OBJECT; -const mx_hash_int = /*@__PURE__*/ overloadingFn( [ mx_hash_int_0, mx_hash_int_1, mx_hash_int_2, mx_hash_int_3, mx_hash_int_4 ] ); + this.previousModelWorldMatrix = uniform( new Matrix4() ); + this.previousProjectionMatrix = uniform( new Matrix4() ).setGroup( renderGroup ); + this.previousCameraViewMatrix = uniform( new Matrix4() ); -const mx_hash_vec3_0 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable ] ) => { + } - const y = int( y_immutable ).toVar(); - const x = int( x_immutable ).toVar(); - const h = uint( mx_hash_int( x, y ) ).toVar(); - const result = uvec3().toVar(); - result.x.assign( h.bitAnd( int( 0xFF ) ) ); - result.y.assign( h.shiftRight( int( 8 ) ).bitAnd( int( 0xFF ) ) ); - result.z.assign( h.shiftRight( int( 16 ) ).bitAnd( int( 0xFF ) ) ); + update( { frameId, camera, object } ) { - return result; + const previousModelMatrix = getPreviousMatrix( object ); -} ).setLayout( { - name: 'mx_hash_vec3_0', - type: 'uvec3', - inputs: [ - { name: 'x', type: 'int' }, - { name: 'y', type: 'int' } - ] -} ); + this.previousModelWorldMatrix.value.copy( previousModelMatrix ); -const mx_hash_vec3_1 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable, z_immutable ] ) => { + // - const z = int( z_immutable ).toVar(); - const y = int( y_immutable ).toVar(); - const x = int( x_immutable ).toVar(); - const h = uint( mx_hash_int( x, y, z ) ).toVar(); - const result = uvec3().toVar(); - result.x.assign( h.bitAnd( int( 0xFF ) ) ); - result.y.assign( h.shiftRight( int( 8 ) ).bitAnd( int( 0xFF ) ) ); - result.z.assign( h.shiftRight( int( 16 ) ).bitAnd( int( 0xFF ) ) ); + const cameraData = getData( camera ); - return result; + if ( cameraData.frameId !== frameId ) { -} ).setLayout( { - name: 'mx_hash_vec3_1', - type: 'uvec3', - inputs: [ - { name: 'x', type: 'int' }, - { name: 'y', type: 'int' }, - { name: 'z', type: 'int' } - ] -} ); + cameraData.frameId = frameId; -const mx_hash_vec3 = /*@__PURE__*/ overloadingFn( [ mx_hash_vec3_0, mx_hash_vec3_1 ] ); + if ( cameraData.previousProjectionMatrix === undefined ) { -const mx_perlin_noise_float_0 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + cameraData.previousProjectionMatrix = new Matrix4(); + cameraData.previousCameraViewMatrix = new Matrix4(); - const p = vec2( p_immutable ).toVar(); - const X = int().toVar(), Y = int().toVar(); - const fx = float( mx_floorfrac( p.x, X ) ).toVar(); - const fy = float( mx_floorfrac( p.y, Y ) ).toVar(); - const u = float( mx_fade( fx ) ).toVar(); - const v = float( mx_fade( fy ) ).toVar(); - const result = float( mx_bilerp( mx_gradient_float( mx_hash_int( X, Y ), fx, fy ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y ), fx.sub( 1.0 ), fy ), mx_gradient_float( mx_hash_int( X, Y.add( int( 1 ) ) ), fx, fy.sub( 1.0 ) ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y.add( int( 1 ) ) ), fx.sub( 1.0 ), fy.sub( 1.0 ) ), u, v ) ).toVar(); + cameraData.currentProjectionMatrix = new Matrix4(); + cameraData.currentCameraViewMatrix = new Matrix4(); - return mx_gradient_scale2d( result ); + cameraData.previousProjectionMatrix.copy( camera.projectionMatrix ); + cameraData.previousCameraViewMatrix.copy( camera.matrixWorldInverse ); -} ).setLayout( { - name: 'mx_perlin_noise_float_0', - type: 'float', - inputs: [ - { name: 'p', type: 'vec2' } - ] -} ); + } else { -const mx_perlin_noise_float_1 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + cameraData.previousProjectionMatrix.copy( cameraData.currentProjectionMatrix ); + cameraData.previousCameraViewMatrix.copy( cameraData.currentCameraViewMatrix ); - const p = vec3( p_immutable ).toVar(); - const X = int().toVar(), Y = int().toVar(), Z = int().toVar(); - const fx = float( mx_floorfrac( p.x, X ) ).toVar(); - const fy = float( mx_floorfrac( p.y, Y ) ).toVar(); - const fz = float( mx_floorfrac( p.z, Z ) ).toVar(); - const u = float( mx_fade( fx ) ).toVar(); - const v = float( mx_fade( fy ) ).toVar(); - const w = float( mx_fade( fz ) ).toVar(); - const result = float( mx_trilerp( mx_gradient_float( mx_hash_int( X, Y, Z ), fx, fy, fz ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y, Z ), fx.sub( 1.0 ), fy, fz ), mx_gradient_float( mx_hash_int( X, Y.add( int( 1 ) ), Z ), fx, fy.sub( 1.0 ), fz ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y.add( int( 1 ) ), Z ), fx.sub( 1.0 ), fy.sub( 1.0 ), fz ), mx_gradient_float( mx_hash_int( X, Y, Z.add( int( 1 ) ) ), fx, fy, fz.sub( 1.0 ) ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y, Z.add( int( 1 ) ) ), fx.sub( 1.0 ), fy, fz.sub( 1.0 ) ), mx_gradient_float( mx_hash_int( X, Y.add( int( 1 ) ), Z.add( int( 1 ) ) ), fx, fy.sub( 1.0 ), fz.sub( 1.0 ) ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y.add( int( 1 ) ), Z.add( int( 1 ) ) ), fx.sub( 1.0 ), fy.sub( 1.0 ), fz.sub( 1.0 ) ), u, v, w ) ).toVar(); + } - return mx_gradient_scale3d( result ); + cameraData.currentProjectionMatrix.copy( camera.projectionMatrix ); + cameraData.currentCameraViewMatrix.copy( camera.matrixWorldInverse ); -} ).setLayout( { - name: 'mx_perlin_noise_float_1', - type: 'float', - inputs: [ - { name: 'p', type: 'vec3' } - ] -} ); + this.previousProjectionMatrix.value.copy( cameraData.previousProjectionMatrix ); + this.previousCameraViewMatrix.value.copy( cameraData.previousCameraViewMatrix ); -const mx_perlin_noise_float = /*@__PURE__*/ overloadingFn( [ mx_perlin_noise_float_0, mx_perlin_noise_float_1 ] ); + } -const mx_perlin_noise_vec3_0 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + } - const p = vec2( p_immutable ).toVar(); - const X = int().toVar(), Y = int().toVar(); - const fx = float( mx_floorfrac( p.x, X ) ).toVar(); - const fy = float( mx_floorfrac( p.y, Y ) ).toVar(); - const u = float( mx_fade( fx ) ).toVar(); - const v = float( mx_fade( fy ) ).toVar(); - const result = vec3( mx_bilerp( mx_gradient_vec3( mx_hash_vec3( X, Y ), fx, fy ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y ), fx.sub( 1.0 ), fy ), mx_gradient_vec3( mx_hash_vec3( X, Y.add( int( 1 ) ) ), fx, fy.sub( 1.0 ) ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y.add( int( 1 ) ) ), fx.sub( 1.0 ), fy.sub( 1.0 ) ), u, v ) ).toVar(); + updateAfter( { object } ) { - return mx_gradient_scale2d( result ); + getPreviousMatrix( object ).copy( object.matrixWorld ); -} ).setLayout( { - name: 'mx_perlin_noise_vec3_0', - type: 'vec3', - inputs: [ - { name: 'p', type: 'vec2' } - ] -} ); + } -const mx_perlin_noise_vec3_1 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + setup( /*builder*/ ) { - const p = vec3( p_immutable ).toVar(); - const X = int().toVar(), Y = int().toVar(), Z = int().toVar(); - const fx = float( mx_floorfrac( p.x, X ) ).toVar(); - const fy = float( mx_floorfrac( p.y, Y ) ).toVar(); - const fz = float( mx_floorfrac( p.z, Z ) ).toVar(); - const u = float( mx_fade( fx ) ).toVar(); - const v = float( mx_fade( fy ) ).toVar(); - const w = float( mx_fade( fz ) ).toVar(); - const result = vec3( mx_trilerp( mx_gradient_vec3( mx_hash_vec3( X, Y, Z ), fx, fy, fz ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y, Z ), fx.sub( 1.0 ), fy, fz ), mx_gradient_vec3( mx_hash_vec3( X, Y.add( int( 1 ) ), Z ), fx, fy.sub( 1.0 ), fz ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y.add( int( 1 ) ), Z ), fx.sub( 1.0 ), fy.sub( 1.0 ), fz ), mx_gradient_vec3( mx_hash_vec3( X, Y, Z.add( int( 1 ) ) ), fx, fy, fz.sub( 1.0 ) ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y, Z.add( int( 1 ) ) ), fx.sub( 1.0 ), fy, fz.sub( 1.0 ) ), mx_gradient_vec3( mx_hash_vec3( X, Y.add( int( 1 ) ), Z.add( int( 1 ) ) ), fx, fy.sub( 1.0 ), fz.sub( 1.0 ) ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y.add( int( 1 ) ), Z.add( int( 1 ) ) ), fx.sub( 1.0 ), fy.sub( 1.0 ), fz.sub( 1.0 ) ), u, v, w ) ).toVar(); + const previousModelViewMatrix = this.previousCameraViewMatrix.mul( this.previousModelWorldMatrix ); - return mx_gradient_scale3d( result ); + const clipPositionCurrent = cameraProjectionMatrix.mul( modelViewMatrix ).mul( positionLocal ); + const clipPositionPrevious = this.previousProjectionMatrix.mul( previousModelViewMatrix ).mul( positionPrevious ); -} ).setLayout( { - name: 'mx_perlin_noise_vec3_1', - type: 'vec3', - inputs: [ - { name: 'p', type: 'vec3' } - ] -} ); + const ndcPositionCurrent = clipPositionCurrent.xy.div( clipPositionCurrent.w ); + const ndcPositionPrevious = clipPositionPrevious.xy.div( clipPositionPrevious.w ); -const mx_perlin_noise_vec3 = /*@__PURE__*/ overloadingFn( [ mx_perlin_noise_vec3_0, mx_perlin_noise_vec3_1 ] ); + const velocity = sub( ndcPositionCurrent, ndcPositionPrevious ); -const mx_cell_noise_float_0 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + return velocity; - const p = float( p_immutable ).toVar(); - const ix = int( mx_floor( p ) ).toVar(); + } - return mx_bits_to_01( mx_hash_int( ix ) ); +} -} ).setLayout( { - name: 'mx_cell_noise_float_0', - type: 'float', - inputs: [ - { name: 'p', type: 'float' } - ] -} ); +function getData( object ) { -const mx_cell_noise_float_1 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + let objectData = _objectData.get( object ); - const p = vec2( p_immutable ).toVar(); - const ix = int( mx_floor( p.x ) ).toVar(); - const iy = int( mx_floor( p.y ) ).toVar(); + if ( objectData === undefined ) { - return mx_bits_to_01( mx_hash_int( ix, iy ) ); + objectData = {}; + _objectData.set( object, objectData ); -} ).setLayout( { - name: 'mx_cell_noise_float_1', - type: 'float', - inputs: [ - { name: 'p', type: 'vec2' } - ] -} ); + } -const mx_cell_noise_float_2 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + return objectData; - const p = vec3( p_immutable ).toVar(); - const ix = int( mx_floor( p.x ) ).toVar(); - const iy = int( mx_floor( p.y ) ).toVar(); - const iz = int( mx_floor( p.z ) ).toVar(); +} - return mx_bits_to_01( mx_hash_int( ix, iy, iz ) ); +function getPreviousMatrix( object, index = 0 ) { -} ).setLayout( { - name: 'mx_cell_noise_float_2', - type: 'float', - inputs: [ - { name: 'p', type: 'vec3' } - ] -} ); + const objectData = getData( object ); -const mx_cell_noise_float_3 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + let matrix = objectData[ index ]; - const p = vec4( p_immutable ).toVar(); - const ix = int( mx_floor( p.x ) ).toVar(); - const iy = int( mx_floor( p.y ) ).toVar(); - const iz = int( mx_floor( p.z ) ).toVar(); - const iw = int( mx_floor( p.w ) ).toVar(); + if ( matrix === undefined ) { - return mx_bits_to_01( mx_hash_int( ix, iy, iz, iw ) ); + objectData[ index ] = matrix = new Matrix4(); -} ).setLayout( { - name: 'mx_cell_noise_float_3', - type: 'float', - inputs: [ - { name: 'p', type: 'vec4' } - ] -} ); + } -const mx_cell_noise_float$1 = /*@__PURE__*/ overloadingFn( [ mx_cell_noise_float_0, mx_cell_noise_float_1, mx_cell_noise_float_2, mx_cell_noise_float_3 ] ); + return matrix; -const mx_cell_noise_vec3_0 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { +} - const p = float( p_immutable ).toVar(); - const ix = int( mx_floor( p ) ).toVar(); +const velocity = /*@__PURE__*/ nodeImmutable( VelocityNode ); - return vec3( mx_bits_to_01( mx_hash_int( ix, int( 0 ) ) ), mx_bits_to_01( mx_hash_int( ix, int( 1 ) ) ), mx_bits_to_01( mx_hash_int( ix, int( 2 ) ) ) ); +const burn = /*@__PURE__*/ Fn( ( [ base, blend ] ) => { + + return min$1( 1.0, base.oneMinus().div( blend ) ).oneMinus(); } ).setLayout( { - name: 'mx_cell_noise_vec3_0', + name: 'burnBlend', type: 'vec3', inputs: [ - { name: 'p', type: 'float' } + { name: 'base', type: 'vec3' }, + { name: 'blend', type: 'vec3' } ] } ); -const mx_cell_noise_vec3_1 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { - - const p = vec2( p_immutable ).toVar(); - const ix = int( mx_floor( p.x ) ).toVar(); - const iy = int( mx_floor( p.y ) ).toVar(); +const dodge = /*@__PURE__*/ Fn( ( [ base, blend ] ) => { - return vec3( mx_bits_to_01( mx_hash_int( ix, iy, int( 0 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, int( 1 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, int( 2 ) ) ) ); + return min$1( base.div( blend.oneMinus() ), 1.0 ); } ).setLayout( { - name: 'mx_cell_noise_vec3_1', + name: 'dodgeBlend', type: 'vec3', inputs: [ - { name: 'p', type: 'vec2' } + { name: 'base', type: 'vec3' }, + { name: 'blend', type: 'vec3' } ] } ); -const mx_cell_noise_vec3_2 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { - - const p = vec3( p_immutable ).toVar(); - const ix = int( mx_floor( p.x ) ).toVar(); - const iy = int( mx_floor( p.y ) ).toVar(); - const iz = int( mx_floor( p.z ) ).toVar(); +const screen = /*@__PURE__*/ Fn( ( [ base, blend ] ) => { - return vec3( mx_bits_to_01( mx_hash_int( ix, iy, iz, int( 0 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, iz, int( 1 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, iz, int( 2 ) ) ) ); + return base.oneMinus().mul( blend.oneMinus() ).oneMinus(); } ).setLayout( { - name: 'mx_cell_noise_vec3_2', + name: 'screenBlend', type: 'vec3', inputs: [ - { name: 'p', type: 'vec3' } + { name: 'base', type: 'vec3' }, + { name: 'blend', type: 'vec3' } ] } ); -const mx_cell_noise_vec3_3 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { - - const p = vec4( p_immutable ).toVar(); - const ix = int( mx_floor( p.x ) ).toVar(); - const iy = int( mx_floor( p.y ) ).toVar(); - const iz = int( mx_floor( p.z ) ).toVar(); - const iw = int( mx_floor( p.w ) ).toVar(); +const overlay = /*@__PURE__*/ Fn( ( [ base, blend ] ) => { - return vec3( mx_bits_to_01( mx_hash_int( ix, iy, iz, iw, int( 0 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, iz, iw, int( 1 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, iz, iw, int( 2 ) ) ) ); + return mix( base.mul( 2.0 ).mul( blend ), base.oneMinus().mul( 2.0 ).mul( blend.oneMinus() ).oneMinus(), step( 0.5, base ) ); } ).setLayout( { - name: 'mx_cell_noise_vec3_3', + name: 'overlayBlend', type: 'vec3', inputs: [ - { name: 'p', type: 'vec4' } + { name: 'base', type: 'vec3' }, + { name: 'blend', type: 'vec3' } ] } ); -const mx_cell_noise_vec3 = /*@__PURE__*/ overloadingFn( [ mx_cell_noise_vec3_0, mx_cell_noise_vec3_1, mx_cell_noise_vec3_2, mx_cell_noise_vec3_3 ] ); +const motionBlur = /*@__PURE__*/ Fn( ( [ inputNode, velocity, numSamples = int( 16 ) ] ) => { -const mx_fractal_noise_float$1 = /*@__PURE__*/ Fn( ( [ p_immutable, octaves_immutable, lacunarity_immutable, diminish_immutable ] ) => { + const sampleColor = ( uv ) => inputNode.uv( uv ); - const diminish = float( diminish_immutable ).toVar(); - const lacunarity = float( lacunarity_immutable ).toVar(); - const octaves = int( octaves_immutable ).toVar(); - const p = vec3( p_immutable ).toVar(); - const result = float( 0.0 ).toVar(); - const amplitude = float( 1.0 ).toVar(); + const uvs = uv(); - Loop( octaves, () => { + const colorResult = sampleColor( uvs ).toVar(); + const fSamples = float( numSamples ); - result.addAssign( amplitude.mul( mx_perlin_noise_float( p ) ) ); - amplitude.mulAssign( diminish ); - p.mulAssign( lacunarity ); + Loop( { start: int( 1 ), end: numSamples, type: 'int', condition: '<=' }, ( { i } ) => { + + const offset = velocity.mul( float( i ).div( fSamples.sub( 1 ) ).sub( 0.5 ) ); + colorResult.addAssign( sampleColor( uvs.add( offset ) ) ); } ); - return result; + colorResult.divAssign( fSamples ); + + return colorResult; + +} ); + +const bleach = /*@__PURE__*/ Fn( ( [ color, opacity = 1 ] ) => { + + const base = color; + const lum = luminance( base.rgb ); + const blend = vec3( lum ); + + const L = min$1( 1.0, max$1( 0.0, float( 10.0 ).mul( lum.sub( 0.45 ) ) ) ); + + const result1 = blend.mul( base.rgb ).mul( 2.0 ); + const result2 = float( 2.0 ).mul( blend.oneMinus() ).mul( base.rgb.oneMinus() ).oneMinus(); + + const newColor = mix( result1, result2, L ); + + const A2 = base.a.mul( opacity ); + + const mixRGB = A2.mul( newColor.rgb ); + + mixRGB.addAssign( base.rgb.mul( A2.oneMinus() ) ); + + return vec4( mixRGB, base.a ); + +} ); + +const sepia = /*@__PURE__*/ Fn( ( [ color ] ) => { + + const c = vec3( color ); + + // https://github.com/evanw/glfx.js/blob/master/src/filters/adjust/sepia.js + + return vec4( + dot( c, vec3( 0.393, 0.769, 0.189 ) ), + dot( c, vec3( 0.349, 0.686, 0.168 ) ), + dot( c, vec3( 0.272, 0.534, 0.131 ) ), + color.a + ); + +} ); + +const sRGBToLinearSRGB = /*@__PURE__*/ Fn( ( [ color ] ) => { + + const a = color.mul( 0.9478672986 ).add( 0.0521327014 ).pow( 2.4 ); + const b = color.mul( 0.0773993808 ); + const factor = color.lessThanEqual( 0.04045 ); + + const rgbResult = mix( a, b, factor ); + + return rgbResult; } ).setLayout( { - name: 'mx_fractal_noise_float', - type: 'float', + name: 'sRGBToLinearSRGB', + type: 'vec3', inputs: [ - { name: 'p', type: 'vec3' }, - { name: 'octaves', type: 'int' }, - { name: 'lacunarity', type: 'float' }, - { name: 'diminish', type: 'float' } + { name: 'color', type: 'vec3' } ] } ); -const mx_fractal_noise_vec3$1 = /*@__PURE__*/ Fn( ( [ p_immutable, octaves_immutable, lacunarity_immutable, diminish_immutable ] ) => { +const linearSRGBTosRGB = /*@__PURE__*/ Fn( ( [ color ] ) => { - const diminish = float( diminish_immutable ).toVar(); - const lacunarity = float( lacunarity_immutable ).toVar(); - const octaves = int( octaves_immutable ).toVar(); - const p = vec3( p_immutable ).toVar(); - const result = vec3( 0.0 ).toVar(); - const amplitude = float( 1.0 ).toVar(); + const a = color.pow( 0.41666 ).mul( 1.055 ).sub( 0.055 ); + const b = color.mul( 12.92 ); + const factor = color.lessThanEqual( 0.0031308 ); - Loop( octaves, () => { + const rgbResult = mix( a, b, factor ); - result.addAssign( amplitude.mul( mx_perlin_noise_vec3( p ) ) ); - amplitude.mulAssign( diminish ); - p.mulAssign( lacunarity ); + return rgbResult; - } ); +} ).setLayout( { + name: 'linearSRGBTosRGB', + type: 'vec3', + inputs: [ + { name: 'color', type: 'vec3' } + ] +} ); - return result; +// exposure only + +const linearToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { + + return color.mul( exposure ).clamp(); } ).setLayout( { - name: 'mx_fractal_noise_vec3', + name: 'linearToneMapping', type: 'vec3', inputs: [ - { name: 'p', type: 'vec3' }, - { name: 'octaves', type: 'int' }, - { name: 'lacunarity', type: 'float' }, - { name: 'diminish', type: 'float' } + { name: 'color', type: 'vec3' }, + { name: 'exposure', type: 'float' } ] } ); -const mx_fractal_noise_vec2$1 = /*@__PURE__*/ Fn( ( [ p_immutable, octaves_immutable, lacunarity_immutable, diminish_immutable ] ) => { +// source: https://www.cs.utah.edu/docs/techreports/2002/pdf/UUCS-02-001.pdf - const diminish = float( diminish_immutable ).toVar(); - const lacunarity = float( lacunarity_immutable ).toVar(); - const octaves = int( octaves_immutable ).toVar(); - const p = vec3( p_immutable ).toVar(); +const reinhardToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { - return vec2( mx_fractal_noise_float$1( p, octaves, lacunarity, diminish ), mx_fractal_noise_float$1( p.add( vec3( int( 19 ), int( 193 ), int( 17 ) ) ), octaves, lacunarity, diminish ) ); + color = color.mul( exposure ); + + return color.div( color.add( 1.0 ) ).clamp(); } ).setLayout( { - name: 'mx_fractal_noise_vec2', - type: 'vec2', + name: 'reinhardToneMapping', + type: 'vec3', inputs: [ - { name: 'p', type: 'vec3' }, - { name: 'octaves', type: 'int' }, - { name: 'lacunarity', type: 'float' }, - { name: 'diminish', type: 'float' } + { name: 'color', type: 'vec3' }, + { name: 'exposure', type: 'float' } ] } ); -const mx_fractal_noise_vec4$1 = /*@__PURE__*/ Fn( ( [ p_immutable, octaves_immutable, lacunarity_immutable, diminish_immutable ] ) => { +// source: http://filmicworlds.com/blog/filmic-tonemapping-operators/ - const diminish = float( diminish_immutable ).toVar(); - const lacunarity = float( lacunarity_immutable ).toVar(); - const octaves = int( octaves_immutable ).toVar(); - const p = vec3( p_immutable ).toVar(); - const c = vec3( mx_fractal_noise_vec3$1( p, octaves, lacunarity, diminish ) ).toVar(); - const f = float( mx_fractal_noise_float$1( p.add( vec3( int( 19 ), int( 193 ), int( 17 ) ) ), octaves, lacunarity, diminish ) ).toVar(); +const cineonToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { - return vec4( c, f ); + // filmic operator by Jim Hejl and Richard Burgess-Dawson + color = color.mul( exposure ); + color = color.sub( 0.004 ).max( 0.0 ); + + const a = color.mul( color.mul( 6.2 ).add( 0.5 ) ); + const b = color.mul( color.mul( 6.2 ).add( 1.7 ) ).add( 0.06 ); + + return a.div( b ).pow( 2.2 ); } ).setLayout( { - name: 'mx_fractal_noise_vec4', - type: 'vec4', + name: 'cineonToneMapping', + type: 'vec3', inputs: [ - { name: 'p', type: 'vec3' }, - { name: 'octaves', type: 'int' }, - { name: 'lacunarity', type: 'float' }, - { name: 'diminish', type: 'float' } + { name: 'color', type: 'vec3' }, + { name: 'exposure', type: 'float' } ] } ); -const mx_worley_distance_0 = /*@__PURE__*/ Fn( ( [ p_immutable, x_immutable, y_immutable, xoff_immutable, yoff_immutable, jitter_immutable, metric_immutable ] ) => { +// source: https://github.com/selfshadow/ltc_code/blob/master/webgl/shaders/ltc/ltc_blit.fs - const metric = int( metric_immutable ).toVar(); - const jitter = float( jitter_immutable ).toVar(); - const yoff = int( yoff_immutable ).toVar(); - const xoff = int( xoff_immutable ).toVar(); - const y = int( y_immutable ).toVar(); - const x = int( x_immutable ).toVar(); - const p = vec2( p_immutable ).toVar(); - const tmp = vec3( mx_cell_noise_vec3( vec2( x.add( xoff ), y.add( yoff ) ) ) ).toVar(); - const off = vec2( tmp.x, tmp.y ).toVar(); - off.subAssign( 0.5 ); - off.mulAssign( jitter ); - off.addAssign( 0.5 ); - const cellpos = vec2( vec2( float( x ), float( y ) ).add( off ) ).toVar(); - const diff = vec2( cellpos.sub( p ) ).toVar(); +const RRTAndODTFit = /*@__PURE__*/ Fn( ( [ color ] ) => { - If( metric.equal( int( 2 ) ), () => { + const a = color.mul( color.add( 0.0245786 ) ).sub( 0.000090537 ); + const b = color.mul( color.add( 0.4329510 ).mul( 0.983729 ) ).add( 0.238081 ); - return abs( diff.x ).add( abs( diff.y ) ); + return a.div( b ); - } ); +} ); - If( metric.equal( int( 3 ) ), () => { +// source: https://github.com/selfshadow/ltc_code/blob/master/webgl/shaders/ltc/ltc_blit.fs - return max$1( abs( diff.x ), abs( diff.y ) ); +const acesFilmicToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { - } ); + // sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT + const ACESInputMat = mat3( + 0.59719, 0.35458, 0.04823, + 0.07600, 0.90834, 0.01566, + 0.02840, 0.13383, 0.83777 + ); - return dot( diff, diff ); + // ODT_SAT => XYZ => D60_2_D65 => sRGB + const ACESOutputMat = mat3( + 1.60475, - 0.53108, - 0.07367, + - 0.10208, 1.10813, - 0.00605, + - 0.00327, - 0.07276, 1.07602 + ); + + color = color.mul( exposure ).div( 0.6 ); + + color = ACESInputMat.mul( color ); + + // Apply RRT and ODT + color = RRTAndODTFit( color ); + + color = ACESOutputMat.mul( color ); + + // Clamp to [0, 1] + return color.clamp(); } ).setLayout( { - name: 'mx_worley_distance_0', - type: 'float', + name: 'acesFilmicToneMapping', + type: 'vec3', inputs: [ - { name: 'p', type: 'vec2' }, - { name: 'x', type: 'int' }, - { name: 'y', type: 'int' }, - { name: 'xoff', type: 'int' }, - { name: 'yoff', type: 'int' }, - { name: 'jitter', type: 'float' }, - { name: 'metric', type: 'int' } + { name: 'color', type: 'vec3' }, + { name: 'exposure', type: 'float' } ] } ); -const mx_worley_distance_1 = /*@__PURE__*/ Fn( ( [ p_immutable, x_immutable, y_immutable, z_immutable, xoff_immutable, yoff_immutable, zoff_immutable, jitter_immutable, metric_immutable ] ) => { - - const metric = int( metric_immutable ).toVar(); - const jitter = float( jitter_immutable ).toVar(); - const zoff = int( zoff_immutable ).toVar(); - const yoff = int( yoff_immutable ).toVar(); - const xoff = int( xoff_immutable ).toVar(); - const z = int( z_immutable ).toVar(); - const y = int( y_immutable ).toVar(); - const x = int( x_immutable ).toVar(); - const p = vec3( p_immutable ).toVar(); - const off = vec3( mx_cell_noise_vec3( vec3( x.add( xoff ), y.add( yoff ), z.add( zoff ) ) ) ).toVar(); - off.subAssign( 0.5 ); - off.mulAssign( jitter ); - off.addAssign( 0.5 ); - const cellpos = vec3( vec3( float( x ), float( y ), float( z ) ).add( off ) ).toVar(); - const diff = vec3( cellpos.sub( p ) ).toVar(); +const LINEAR_REC2020_TO_LINEAR_SRGB = /*@__PURE__*/ mat3( vec3( 1.6605, - 0.1246, - 0.0182 ), vec3( - 0.5876, 1.1329, - 0.1006 ), vec3( - 0.0728, - 0.0083, 1.1187 ) ); +const LINEAR_SRGB_TO_LINEAR_REC2020 = /*@__PURE__*/ mat3( vec3( 0.6274, 0.0691, 0.0164 ), vec3( 0.3293, 0.9195, 0.0880 ), vec3( 0.0433, 0.0113, 0.8956 ) ); - If( metric.equal( int( 2 ) ), () => { +const agxDefaultContrastApprox = /*@__PURE__*/ Fn( ( [ x_immutable ] ) => { - return abs( diff.x ).add( abs( diff.y ) ).add( abs( diff.z ) ); + const x = vec3( x_immutable ).toVar(); + const x2 = vec3( x.mul( x ) ).toVar(); + const x4 = vec3( x2.mul( x2 ) ).toVar(); - } ); + return float( 15.5 ).mul( x4.mul( x2 ) ).sub( mul( 40.14, x4.mul( x ) ) ).add( mul( 31.96, x4 ).sub( mul( 6.868, x2.mul( x ) ) ).add( mul( 0.4298, x2 ).add( mul( 0.1191, x ).sub( 0.00232 ) ) ) ); - If( metric.equal( int( 3 ) ), () => { +} ); - return max$1( max$1( abs( diff.x ), abs( diff.y ) ), abs( diff.z ) ); +const agxToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { - } ); + const colortone = vec3( color ).toVar(); + const AgXInsetMatrix = mat3( vec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ), vec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ), vec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 ) ); + const AgXOutsetMatrix = mat3( vec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ), vec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ), vec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 ) ); + const AgxMinEv = float( - 12.47393 ); + const AgxMaxEv = float( 4.026069 ); + colortone.mulAssign( exposure ); + colortone.assign( LINEAR_SRGB_TO_LINEAR_REC2020.mul( colortone ) ); + colortone.assign( AgXInsetMatrix.mul( colortone ) ); + colortone.assign( max$1( colortone, 1e-10 ) ); + colortone.assign( log2( colortone ) ); + colortone.assign( colortone.sub( AgxMinEv ).div( AgxMaxEv.sub( AgxMinEv ) ) ); + colortone.assign( clamp( colortone, 0.0, 1.0 ) ); + colortone.assign( agxDefaultContrastApprox( colortone ) ); + colortone.assign( AgXOutsetMatrix.mul( colortone ) ); + colortone.assign( pow( max$1( vec3( 0.0 ), colortone ), vec3( 2.2 ) ) ); + colortone.assign( LINEAR_REC2020_TO_LINEAR_SRGB.mul( colortone ) ); + colortone.assign( clamp( colortone, 0.0, 1.0 ) ); - return dot( diff, diff ); + return colortone; } ).setLayout( { - name: 'mx_worley_distance_1', - type: 'float', + name: 'agxToneMapping', + type: 'vec3', inputs: [ - { name: 'p', type: 'vec3' }, - { name: 'x', type: 'int' }, - { name: 'y', type: 'int' }, - { name: 'z', type: 'int' }, - { name: 'xoff', type: 'int' }, - { name: 'yoff', type: 'int' }, - { name: 'zoff', type: 'int' }, - { name: 'jitter', type: 'float' }, - { name: 'metric', type: 'int' } + { name: 'color', type: 'vec3' }, + { name: 'exposure', type: 'float' } ] } ); -const mx_worley_distance = /*@__PURE__*/ overloadingFn( [ mx_worley_distance_0, mx_worley_distance_1 ] ); - -const mx_worley_noise_float_0 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { +// https://modelviewer.dev/examples/tone-mapping - const metric = int( metric_immutable ).toVar(); - const jitter = float( jitter_immutable ).toVar(); - const p = vec2( p_immutable ).toVar(); - const X = int().toVar(), Y = int().toVar(); - const localpos = vec2( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ) ).toVar(); - const sqdist = float( 1e6 ).toVar(); +const neutralToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { - Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + const StartCompression = float( 0.8 - 0.04 ); + const Desaturation = float( 0.15 ); - Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + color = color.mul( exposure ); - const dist = float( mx_worley_distance( localpos, x, y, X, Y, jitter, metric ) ).toVar(); - sqdist.assign( min$1( sqdist, dist ) ); + const x = min$1( color.r, min$1( color.g, color.b ) ); + const offset = select( x.lessThan( 0.08 ), x.sub( mul( 6.25, x.mul( x ) ) ), 0.04 ); - } ); + color.subAssign( offset ); - } ); + const peak = max$1( color.r, max$1( color.g, color.b ) ); - If( metric.equal( int( 0 ) ), () => { + If( peak.lessThan( StartCompression ), () => { - sqdist.assign( sqrt( sqdist ) ); + return color; } ); - return sqdist; + const d = sub( 1, StartCompression ); + const newPeak = sub( 1, d.mul( d ).div( peak.add( d.sub( StartCompression ) ) ) ); + color.mulAssign( newPeak.div( peak ) ); + const g = sub( 1, div( 1, Desaturation.mul( peak.sub( newPeak ) ).add( 1 ) ) ); + + return mix( color, vec3( newPeak ), g ); } ).setLayout( { - name: 'mx_worley_noise_float_0', - type: 'float', + name: 'neutralToneMapping', + type: 'vec3', inputs: [ - { name: 'p', type: 'vec2' }, - { name: 'jitter', type: 'float' }, - { name: 'metric', type: 'int' } + { name: 'color', type: 'vec3' }, + { name: 'exposure', type: 'float' } ] } ); -const mx_worley_noise_vec2_0 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { +class ComputeBuiltinNode extends Node { - const metric = int( metric_immutable ).toVar(); - const jitter = float( jitter_immutable ).toVar(); - const p = vec2( p_immutable ).toVar(); - const X = int().toVar(), Y = int().toVar(); - const localpos = vec2( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ) ).toVar(); - const sqdist = vec2( 1e6, 1e6 ).toVar(); + static get type() { - Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + return 'ComputeBuiltinNode'; - Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + } - const dist = float( mx_worley_distance( localpos, x, y, X, Y, jitter, metric ) ).toVar(); + constructor( builtinName, nodeType ) { - If( dist.lessThan( sqdist.x ), () => { + super( nodeType ); - sqdist.y.assign( sqdist.x ); - sqdist.x.assign( dist ); + this._builtinName = builtinName; - } ).ElseIf( dist.lessThan( sqdist.y ), () => { + } - sqdist.y.assign( dist ); + getHash( builder ) { - } ); + return this.getBuiltinName( builder ); - } ); + } - } ); + getNodeType( /*builder*/ ) { - If( metric.equal( int( 0 ) ), () => { + return this.nodeType; - sqdist.assign( sqrt( sqdist ) ); + } - } ); + setBuiltinName( builtinName ) { - return sqdist; + this._builtinName = builtinName; -} ).setLayout( { - name: 'mx_worley_noise_vec2_0', - type: 'vec2', - inputs: [ - { name: 'p', type: 'vec2' }, - { name: 'jitter', type: 'float' }, - { name: 'metric', type: 'int' } - ] -} ); + return this; -const mx_worley_noise_vec3_0 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { + } - const metric = int( metric_immutable ).toVar(); - const jitter = float( jitter_immutable ).toVar(); - const p = vec2( p_immutable ).toVar(); - const X = int().toVar(), Y = int().toVar(); - const localpos = vec2( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ) ).toVar(); - const sqdist = vec3( 1e6, 1e6, 1e6 ).toVar(); + getBuiltinName( /*builder*/ ) { - Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + return this._builtinName; - Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + } - const dist = float( mx_worley_distance( localpos, x, y, X, Y, jitter, metric ) ).toVar(); + hasBuiltin( builder ) { - If( dist.lessThan( sqdist.x ), () => { + builder.hasBuiltin( this._builtinName ); - sqdist.z.assign( sqdist.y ); - sqdist.y.assign( sqdist.x ); - sqdist.x.assign( dist ); + } + + generate( builder, output ) { + + const builtinName = this.getBuiltinName( builder ); + const nodeType = this.getNodeType( builder ); + + if ( builder.shaderStage === 'compute' ) { + + return builder.format( builtinName, nodeType, output ); + + } else { + + console.warn( `ComputeBuiltinNode: Compute built-in value ${builtinName} can not be accessed in the ${builder.shaderStage} stage` ); + return builder.generateConst( nodeType ); + + } + + } + + serialize( data ) { + + super.serialize( data ); + + data.global = this.global; + data._builtinName = this._builtinName; + + } + + deserialize( data ) { + + super.deserialize( data ); + + this.global = data.global; + this._builtinName = data._builtinName; + + } + +} + +const computeBuiltin = ( name, nodeType ) => nodeObject( new ComputeBuiltinNode( name, nodeType ) ); + +const numWorkgroups = /*@__PURE__*/ computeBuiltin( 'numWorkgroups', 'uvec3' ); +const workgroupId = /*@__PURE__*/ computeBuiltin( 'workgroupId', 'uvec3' ); +const localId = /*@__PURE__*/ computeBuiltin( 'localId', 'uvec3' ); +const subgroupSize = /*@__PURE__*/ computeBuiltin( 'subgroupSize', 'uint' ); + +class BarrierNode extends Node { + + constructor( scope ) { + + super(); + + this.scope = scope; + + } + + generate( builder ) { + + const { scope } = this; + const { renderer } = builder; + + if ( renderer.backend.isWebGLBackend === true ) { + + builder.addFlowCode( `\t// ${scope}Barrier \n` ); + + } else { + + builder.addLineFlowCode( `${scope}Barrier()`, this ); + + } + + } + +} + +const barrier = nodeProxy( BarrierNode ); + +const workgroupBarrier = () => barrier( 'workgroup' ).append(); +const storageBarrier = () => barrier( 'storage' ).append(); +const textureBarrier = () => barrier( 'texture' ).append(); + +class WorkgroupInfoElementNode extends ArrayElementNode { + + constructor( workgroupInfoNode, indexNode ) { + + super( workgroupInfoNode, indexNode ); + + this.isWorkgroupInfoElementNode = true; + + } + + generate( builder, output ) { + + let snippet; + + const isAssignContext = builder.context.assign; + snippet = super.generate( builder ); + + if ( isAssignContext !== true ) { + + const type = this.getNodeType( builder ); + + snippet = builder.format( snippet, type, output ); + + } + + // TODO: Possibly activate clip distance index on index access rather than from clipping context + + return snippet; + + } + +} + + +class WorkgroupInfoNode extends Node { + + constructor( scope, bufferType, bufferCount = 0 ) { + + super( bufferType ); + + this.bufferType = bufferType; + this.bufferCount = bufferCount; + + this.isWorkgroupInfoNode = true; + + this.scope = scope; + + } + + label( name ) { + + this.name = name; + + return this; + + } + + getHash() { + + return this.uuid; + + } + + setScope( scope ) { + + this.scope = scope; + + return this; + + } + + getInputType( /*builder*/ ) { + + return `${this.scope}Array`; + + } + + element( indexNode ) { + + return nodeObject( new WorkgroupInfoElementNode( this, indexNode ) ); + + } + + generate( builder ) { + + return builder.getScopedArray( this.name || `${this.scope}Array_${this.id}`, this.scope.toLowerCase(), this.bufferType, this.bufferCount ); + + } + +} + +const workgroupArray = ( type, count ) => nodeObject( new WorkgroupInfoNode( 'Workgroup', type, count ) ); + +class AtomicFunctionNode extends TempNode { + + static get type() { + + return 'AtomicFunctionNode'; + + } + + constructor( method, pointerNode, valueNode, storeNode = null ) { + + super( 'uint' ); + + this.method = method; + + this.pointerNode = pointerNode; + this.valueNode = valueNode; + this.storeNode = storeNode; + + } + + getInputType( builder ) { + + return this.pointerNode.getNodeType( builder ); + + } + + getNodeType( builder ) { + + return this.getInputType( builder ); + + } + + generate( builder ) { + + const method = this.method; + + const type = this.getNodeType( builder ); + const inputType = this.getInputType( builder ); + + const a = this.pointerNode; + const b = this.valueNode; + + const params = []; + + params.push( `&${ a.build( builder, inputType ) }` ); + params.push( b.build( builder, inputType ) ); + + const methodSnippet = `${ builder.getMethod( method, type ) }( ${params.join( ', ' )} )`; + + if ( this.storeNode !== null ) { + + const varSnippet = this.storeNode.build( builder, inputType ); + + builder.addLineFlowCode( `${varSnippet} = ${methodSnippet}`, this ); + + } else { + + builder.addLineFlowCode( methodSnippet, this ); + + } + + } + +} + +AtomicFunctionNode.ATOMIC_LOAD = 'atomicLoad'; +AtomicFunctionNode.ATOMIC_STORE = 'atomicStore'; +AtomicFunctionNode.ATOMIC_ADD = 'atomicAdd'; +AtomicFunctionNode.ATOMIC_SUB = 'atomicSub'; +AtomicFunctionNode.ATOMIC_MAX = 'atomicMax'; +AtomicFunctionNode.ATOMIC_MIN = 'atomicMin'; +AtomicFunctionNode.ATOMIC_AND = 'atomicAnd'; +AtomicFunctionNode.ATOMIC_OR = 'atomicOr'; +AtomicFunctionNode.ATOMIC_XOR = 'atomicXor'; + +const atomicNode = nodeProxy( AtomicFunctionNode ); + +const atomicFunc = ( method, pointerNode, valueNode, storeNode ) => { + + const node = atomicNode( method, pointerNode, valueNode, storeNode ); + node.append(); + + return node; + +}; + +const atomicStore = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_STORE, pointerNode, valueNode, storeNode ); +const atomicAdd = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_ADD, pointerNode, valueNode, storeNode ); +const atomicSub = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_SUB, pointerNode, valueNode, storeNode ); +const atomicMax = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_MAX, pointerNode, valueNode, storeNode ); +const atomicMin = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_MIN, pointerNode, valueNode, storeNode ); +const atomicAnd = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_AND, pointerNode, valueNode, storeNode ); +const atomicOr = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_OR, pointerNode, valueNode, storeNode ); +const atomicXor = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_XOR, pointerNode, valueNode, storeNode ); + +const checker = /*@__PURE__*/ Fn( ( [ coord = uv() ] ) => { + + const uv = coord.mul( 2.0 ); + + const cx = uv.x.floor(); + const cy = uv.y.floor(); + const result = cx.add( cy ).mod( 2.0 ); + + return result.sign(); + +} ); + +// Three.js Transpiler +// https://raw.githubusercontent.com/AcademySoftwareFoundation/MaterialX/main/libraries/stdlib/genglsl/lib/mx_noise.glsl + + + +const mx_select = /*@__PURE__*/ Fn( ( [ b_immutable, t_immutable, f_immutable ] ) => { + + const f = float( f_immutable ).toVar(); + const t = float( t_immutable ).toVar(); + const b = bool( b_immutable ).toVar(); + + return select( b, t, f ); + +} ).setLayout( { + name: 'mx_select', + type: 'float', + inputs: [ + { name: 'b', type: 'bool' }, + { name: 't', type: 'float' }, + { name: 'f', type: 'float' } + ] +} ); + +const mx_negate_if = /*@__PURE__*/ Fn( ( [ val_immutable, b_immutable ] ) => { + + const b = bool( b_immutable ).toVar(); + const val = float( val_immutable ).toVar(); + + return select( b, val.negate(), val ); + +} ).setLayout( { + name: 'mx_negate_if', + type: 'float', + inputs: [ + { name: 'val', type: 'float' }, + { name: 'b', type: 'bool' } + ] +} ); + +const mx_floor = /*@__PURE__*/ Fn( ( [ x_immutable ] ) => { + + const x = float( x_immutable ).toVar(); + + return int( floor( x ) ); + +} ).setLayout( { + name: 'mx_floor', + type: 'int', + inputs: [ + { name: 'x', type: 'float' } + ] +} ); + +const mx_floorfrac = /*@__PURE__*/ Fn( ( [ x_immutable, i ] ) => { + + const x = float( x_immutable ).toVar(); + i.assign( mx_floor( x ) ); + + return x.sub( float( i ) ); + +} ); + +const mx_bilerp_0 = /*@__PURE__*/ Fn( ( [ v0_immutable, v1_immutable, v2_immutable, v3_immutable, s_immutable, t_immutable ] ) => { + + const t = float( t_immutable ).toVar(); + const s = float( s_immutable ).toVar(); + const v3 = float( v3_immutable ).toVar(); + const v2 = float( v2_immutable ).toVar(); + const v1 = float( v1_immutable ).toVar(); + const v0 = float( v0_immutable ).toVar(); + const s1 = float( sub( 1.0, s ) ).toVar(); + + return sub( 1.0, t ).mul( v0.mul( s1 ).add( v1.mul( s ) ) ).add( t.mul( v2.mul( s1 ).add( v3.mul( s ) ) ) ); + +} ).setLayout( { + name: 'mx_bilerp_0', + type: 'float', + inputs: [ + { name: 'v0', type: 'float' }, + { name: 'v1', type: 'float' }, + { name: 'v2', type: 'float' }, + { name: 'v3', type: 'float' }, + { name: 's', type: 'float' }, + { name: 't', type: 'float' } + ] +} ); + +const mx_bilerp_1 = /*@__PURE__*/ Fn( ( [ v0_immutable, v1_immutable, v2_immutable, v3_immutable, s_immutable, t_immutable ] ) => { + + const t = float( t_immutable ).toVar(); + const s = float( s_immutable ).toVar(); + const v3 = vec3( v3_immutable ).toVar(); + const v2 = vec3( v2_immutable ).toVar(); + const v1 = vec3( v1_immutable ).toVar(); + const v0 = vec3( v0_immutable ).toVar(); + const s1 = float( sub( 1.0, s ) ).toVar(); + + return sub( 1.0, t ).mul( v0.mul( s1 ).add( v1.mul( s ) ) ).add( t.mul( v2.mul( s1 ).add( v3.mul( s ) ) ) ); + +} ).setLayout( { + name: 'mx_bilerp_1', + type: 'vec3', + inputs: [ + { name: 'v0', type: 'vec3' }, + { name: 'v1', type: 'vec3' }, + { name: 'v2', type: 'vec3' }, + { name: 'v3', type: 'vec3' }, + { name: 's', type: 'float' }, + { name: 't', type: 'float' } + ] +} ); + +const mx_bilerp = /*@__PURE__*/ overloadingFn( [ mx_bilerp_0, mx_bilerp_1 ] ); + +const mx_trilerp_0 = /*@__PURE__*/ Fn( ( [ v0_immutable, v1_immutable, v2_immutable, v3_immutable, v4_immutable, v5_immutable, v6_immutable, v7_immutable, s_immutable, t_immutable, r_immutable ] ) => { + + const r = float( r_immutable ).toVar(); + const t = float( t_immutable ).toVar(); + const s = float( s_immutable ).toVar(); + const v7 = float( v7_immutable ).toVar(); + const v6 = float( v6_immutable ).toVar(); + const v5 = float( v5_immutable ).toVar(); + const v4 = float( v4_immutable ).toVar(); + const v3 = float( v3_immutable ).toVar(); + const v2 = float( v2_immutable ).toVar(); + const v1 = float( v1_immutable ).toVar(); + const v0 = float( v0_immutable ).toVar(); + const s1 = float( sub( 1.0, s ) ).toVar(); + const t1 = float( sub( 1.0, t ) ).toVar(); + const r1 = float( sub( 1.0, r ) ).toVar(); + + return r1.mul( t1.mul( v0.mul( s1 ).add( v1.mul( s ) ) ).add( t.mul( v2.mul( s1 ).add( v3.mul( s ) ) ) ) ).add( r.mul( t1.mul( v4.mul( s1 ).add( v5.mul( s ) ) ).add( t.mul( v6.mul( s1 ).add( v7.mul( s ) ) ) ) ) ); + +} ).setLayout( { + name: 'mx_trilerp_0', + type: 'float', + inputs: [ + { name: 'v0', type: 'float' }, + { name: 'v1', type: 'float' }, + { name: 'v2', type: 'float' }, + { name: 'v3', type: 'float' }, + { name: 'v4', type: 'float' }, + { name: 'v5', type: 'float' }, + { name: 'v6', type: 'float' }, + { name: 'v7', type: 'float' }, + { name: 's', type: 'float' }, + { name: 't', type: 'float' }, + { name: 'r', type: 'float' } + ] +} ); + +const mx_trilerp_1 = /*@__PURE__*/ Fn( ( [ v0_immutable, v1_immutable, v2_immutable, v3_immutable, v4_immutable, v5_immutable, v6_immutable, v7_immutable, s_immutable, t_immutable, r_immutable ] ) => { + + const r = float( r_immutable ).toVar(); + const t = float( t_immutable ).toVar(); + const s = float( s_immutable ).toVar(); + const v7 = vec3( v7_immutable ).toVar(); + const v6 = vec3( v6_immutable ).toVar(); + const v5 = vec3( v5_immutable ).toVar(); + const v4 = vec3( v4_immutable ).toVar(); + const v3 = vec3( v3_immutable ).toVar(); + const v2 = vec3( v2_immutable ).toVar(); + const v1 = vec3( v1_immutable ).toVar(); + const v0 = vec3( v0_immutable ).toVar(); + const s1 = float( sub( 1.0, s ) ).toVar(); + const t1 = float( sub( 1.0, t ) ).toVar(); + const r1 = float( sub( 1.0, r ) ).toVar(); + + return r1.mul( t1.mul( v0.mul( s1 ).add( v1.mul( s ) ) ).add( t.mul( v2.mul( s1 ).add( v3.mul( s ) ) ) ) ).add( r.mul( t1.mul( v4.mul( s1 ).add( v5.mul( s ) ) ).add( t.mul( v6.mul( s1 ).add( v7.mul( s ) ) ) ) ) ); + +} ).setLayout( { + name: 'mx_trilerp_1', + type: 'vec3', + inputs: [ + { name: 'v0', type: 'vec3' }, + { name: 'v1', type: 'vec3' }, + { name: 'v2', type: 'vec3' }, + { name: 'v3', type: 'vec3' }, + { name: 'v4', type: 'vec3' }, + { name: 'v5', type: 'vec3' }, + { name: 'v6', type: 'vec3' }, + { name: 'v7', type: 'vec3' }, + { name: 's', type: 'float' }, + { name: 't', type: 'float' }, + { name: 'r', type: 'float' } + ] +} ); + +const mx_trilerp = /*@__PURE__*/ overloadingFn( [ mx_trilerp_0, mx_trilerp_1 ] ); + +const mx_gradient_float_0 = /*@__PURE__*/ Fn( ( [ hash_immutable, x_immutable, y_immutable ] ) => { + + const y = float( y_immutable ).toVar(); + const x = float( x_immutable ).toVar(); + const hash = uint( hash_immutable ).toVar(); + const h = uint( hash.bitAnd( uint( 7 ) ) ).toVar(); + const u = float( mx_select( h.lessThan( uint( 4 ) ), x, y ) ).toVar(); + const v = float( mul( 2.0, mx_select( h.lessThan( uint( 4 ) ), y, x ) ) ).toVar(); + + return mx_negate_if( u, bool( h.bitAnd( uint( 1 ) ) ) ).add( mx_negate_if( v, bool( h.bitAnd( uint( 2 ) ) ) ) ); + +} ).setLayout( { + name: 'mx_gradient_float_0', + type: 'float', + inputs: [ + { name: 'hash', type: 'uint' }, + { name: 'x', type: 'float' }, + { name: 'y', type: 'float' } + ] +} ); + +const mx_gradient_float_1 = /*@__PURE__*/ Fn( ( [ hash_immutable, x_immutable, y_immutable, z_immutable ] ) => { + + const z = float( z_immutable ).toVar(); + const y = float( y_immutable ).toVar(); + const x = float( x_immutable ).toVar(); + const hash = uint( hash_immutable ).toVar(); + const h = uint( hash.bitAnd( uint( 15 ) ) ).toVar(); + const u = float( mx_select( h.lessThan( uint( 8 ) ), x, y ) ).toVar(); + const v = float( mx_select( h.lessThan( uint( 4 ) ), y, mx_select( h.equal( uint( 12 ) ).or( h.equal( uint( 14 ) ) ), x, z ) ) ).toVar(); + + return mx_negate_if( u, bool( h.bitAnd( uint( 1 ) ) ) ).add( mx_negate_if( v, bool( h.bitAnd( uint( 2 ) ) ) ) ); + +} ).setLayout( { + name: 'mx_gradient_float_1', + type: 'float', + inputs: [ + { name: 'hash', type: 'uint' }, + { name: 'x', type: 'float' }, + { name: 'y', type: 'float' }, + { name: 'z', type: 'float' } + ] +} ); + +const mx_gradient_float = /*@__PURE__*/ overloadingFn( [ mx_gradient_float_0, mx_gradient_float_1 ] ); + +const mx_gradient_vec3_0 = /*@__PURE__*/ Fn( ( [ hash_immutable, x_immutable, y_immutable ] ) => { + + const y = float( y_immutable ).toVar(); + const x = float( x_immutable ).toVar(); + const hash = uvec3( hash_immutable ).toVar(); + + return vec3( mx_gradient_float( hash.x, x, y ), mx_gradient_float( hash.y, x, y ), mx_gradient_float( hash.z, x, y ) ); + +} ).setLayout( { + name: 'mx_gradient_vec3_0', + type: 'vec3', + inputs: [ + { name: 'hash', type: 'uvec3' }, + { name: 'x', type: 'float' }, + { name: 'y', type: 'float' } + ] +} ); + +const mx_gradient_vec3_1 = /*@__PURE__*/ Fn( ( [ hash_immutable, x_immutable, y_immutable, z_immutable ] ) => { + + const z = float( z_immutable ).toVar(); + const y = float( y_immutable ).toVar(); + const x = float( x_immutable ).toVar(); + const hash = uvec3( hash_immutable ).toVar(); + + return vec3( mx_gradient_float( hash.x, x, y, z ), mx_gradient_float( hash.y, x, y, z ), mx_gradient_float( hash.z, x, y, z ) ); + +} ).setLayout( { + name: 'mx_gradient_vec3_1', + type: 'vec3', + inputs: [ + { name: 'hash', type: 'uvec3' }, + { name: 'x', type: 'float' }, + { name: 'y', type: 'float' }, + { name: 'z', type: 'float' } + ] +} ); + +const mx_gradient_vec3 = /*@__PURE__*/ overloadingFn( [ mx_gradient_vec3_0, mx_gradient_vec3_1 ] ); + +const mx_gradient_scale2d_0 = /*@__PURE__*/ Fn( ( [ v_immutable ] ) => { + + const v = float( v_immutable ).toVar(); + + return mul( 0.6616, v ); + +} ).setLayout( { + name: 'mx_gradient_scale2d_0', + type: 'float', + inputs: [ + { name: 'v', type: 'float' } + ] +} ); + +const mx_gradient_scale3d_0 = /*@__PURE__*/ Fn( ( [ v_immutable ] ) => { + + const v = float( v_immutable ).toVar(); + + return mul( 0.9820, v ); + +} ).setLayout( { + name: 'mx_gradient_scale3d_0', + type: 'float', + inputs: [ + { name: 'v', type: 'float' } + ] +} ); + +const mx_gradient_scale2d_1 = /*@__PURE__*/ Fn( ( [ v_immutable ] ) => { + + const v = vec3( v_immutable ).toVar(); + + return mul( 0.6616, v ); + +} ).setLayout( { + name: 'mx_gradient_scale2d_1', + type: 'vec3', + inputs: [ + { name: 'v', type: 'vec3' } + ] +} ); + +const mx_gradient_scale2d = /*@__PURE__*/ overloadingFn( [ mx_gradient_scale2d_0, mx_gradient_scale2d_1 ] ); + +const mx_gradient_scale3d_1 = /*@__PURE__*/ Fn( ( [ v_immutable ] ) => { + + const v = vec3( v_immutable ).toVar(); + + return mul( 0.9820, v ); + +} ).setLayout( { + name: 'mx_gradient_scale3d_1', + type: 'vec3', + inputs: [ + { name: 'v', type: 'vec3' } + ] +} ); + +const mx_gradient_scale3d = /*@__PURE__*/ overloadingFn( [ mx_gradient_scale3d_0, mx_gradient_scale3d_1 ] ); + +const mx_rotl32 = /*@__PURE__*/ Fn( ( [ x_immutable, k_immutable ] ) => { + + const k = int( k_immutable ).toVar(); + const x = uint( x_immutable ).toVar(); + + return x.shiftLeft( k ).bitOr( x.shiftRight( int( 32 ).sub( k ) ) ); + +} ).setLayout( { + name: 'mx_rotl32', + type: 'uint', + inputs: [ + { name: 'x', type: 'uint' }, + { name: 'k', type: 'int' } + ] +} ); + +const mx_bjmix = /*@__PURE__*/ Fn( ( [ a, b, c ] ) => { + + a.subAssign( c ); + a.bitXorAssign( mx_rotl32( c, int( 4 ) ) ); + c.addAssign( b ); + b.subAssign( a ); + b.bitXorAssign( mx_rotl32( a, int( 6 ) ) ); + a.addAssign( c ); + c.subAssign( b ); + c.bitXorAssign( mx_rotl32( b, int( 8 ) ) ); + b.addAssign( a ); + a.subAssign( c ); + a.bitXorAssign( mx_rotl32( c, int( 16 ) ) ); + c.addAssign( b ); + b.subAssign( a ); + b.bitXorAssign( mx_rotl32( a, int( 19 ) ) ); + a.addAssign( c ); + c.subAssign( b ); + c.bitXorAssign( mx_rotl32( b, int( 4 ) ) ); + b.addAssign( a ); + +} ); + +const mx_bjfinal = /*@__PURE__*/ Fn( ( [ a_immutable, b_immutable, c_immutable ] ) => { + + const c = uint( c_immutable ).toVar(); + const b = uint( b_immutable ).toVar(); + const a = uint( a_immutable ).toVar(); + c.bitXorAssign( b ); + c.subAssign( mx_rotl32( b, int( 14 ) ) ); + a.bitXorAssign( c ); + a.subAssign( mx_rotl32( c, int( 11 ) ) ); + b.bitXorAssign( a ); + b.subAssign( mx_rotl32( a, int( 25 ) ) ); + c.bitXorAssign( b ); + c.subAssign( mx_rotl32( b, int( 16 ) ) ); + a.bitXorAssign( c ); + a.subAssign( mx_rotl32( c, int( 4 ) ) ); + b.bitXorAssign( a ); + b.subAssign( mx_rotl32( a, int( 14 ) ) ); + c.bitXorAssign( b ); + c.subAssign( mx_rotl32( b, int( 24 ) ) ); + + return c; + +} ).setLayout( { + name: 'mx_bjfinal', + type: 'uint', + inputs: [ + { name: 'a', type: 'uint' }, + { name: 'b', type: 'uint' }, + { name: 'c', type: 'uint' } + ] +} ); + +const mx_bits_to_01 = /*@__PURE__*/ Fn( ( [ bits_immutable ] ) => { + + const bits = uint( bits_immutable ).toVar(); + + return float( bits ).div( float( uint( int( 0xffffffff ) ) ) ); + +} ).setLayout( { + name: 'mx_bits_to_01', + type: 'float', + inputs: [ + { name: 'bits', type: 'uint' } + ] +} ); + +const mx_fade = /*@__PURE__*/ Fn( ( [ t_immutable ] ) => { + + const t = float( t_immutable ).toVar(); + + return t.mul( t ).mul( t ).mul( t.mul( t.mul( 6.0 ).sub( 15.0 ) ).add( 10.0 ) ); + +} ).setLayout( { + name: 'mx_fade', + type: 'float', + inputs: [ + { name: 't', type: 'float' } + ] +} ); + +const mx_hash_int_0 = /*@__PURE__*/ Fn( ( [ x_immutable ] ) => { + + const x = int( x_immutable ).toVar(); + const len = uint( uint( 1 ) ).toVar(); + const seed = uint( uint( int( 0xdeadbeef ) ).add( len.shiftLeft( uint( 2 ) ) ).add( uint( 13 ) ) ).toVar(); + + return mx_bjfinal( seed.add( uint( x ) ), seed, seed ); + +} ).setLayout( { + name: 'mx_hash_int_0', + type: 'uint', + inputs: [ + { name: 'x', type: 'int' } + ] +} ); + +const mx_hash_int_1 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable ] ) => { + + const y = int( y_immutable ).toVar(); + const x = int( x_immutable ).toVar(); + const len = uint( uint( 2 ) ).toVar(); + const a = uint().toVar(), b = uint().toVar(), c = uint().toVar(); + a.assign( b.assign( c.assign( uint( int( 0xdeadbeef ) ).add( len.shiftLeft( uint( 2 ) ) ).add( uint( 13 ) ) ) ) ); + a.addAssign( uint( x ) ); + b.addAssign( uint( y ) ); + + return mx_bjfinal( a, b, c ); + +} ).setLayout( { + name: 'mx_hash_int_1', + type: 'uint', + inputs: [ + { name: 'x', type: 'int' }, + { name: 'y', type: 'int' } + ] +} ); + +const mx_hash_int_2 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable, z_immutable ] ) => { + + const z = int( z_immutable ).toVar(); + const y = int( y_immutable ).toVar(); + const x = int( x_immutable ).toVar(); + const len = uint( uint( 3 ) ).toVar(); + const a = uint().toVar(), b = uint().toVar(), c = uint().toVar(); + a.assign( b.assign( c.assign( uint( int( 0xdeadbeef ) ).add( len.shiftLeft( uint( 2 ) ) ).add( uint( 13 ) ) ) ) ); + a.addAssign( uint( x ) ); + b.addAssign( uint( y ) ); + c.addAssign( uint( z ) ); + + return mx_bjfinal( a, b, c ); + +} ).setLayout( { + name: 'mx_hash_int_2', + type: 'uint', + inputs: [ + { name: 'x', type: 'int' }, + { name: 'y', type: 'int' }, + { name: 'z', type: 'int' } + ] +} ); + +const mx_hash_int_3 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable, z_immutable, xx_immutable ] ) => { + + const xx = int( xx_immutable ).toVar(); + const z = int( z_immutable ).toVar(); + const y = int( y_immutable ).toVar(); + const x = int( x_immutable ).toVar(); + const len = uint( uint( 4 ) ).toVar(); + const a = uint().toVar(), b = uint().toVar(), c = uint().toVar(); + a.assign( b.assign( c.assign( uint( int( 0xdeadbeef ) ).add( len.shiftLeft( uint( 2 ) ) ).add( uint( 13 ) ) ) ) ); + a.addAssign( uint( x ) ); + b.addAssign( uint( y ) ); + c.addAssign( uint( z ) ); + mx_bjmix( a, b, c ); + a.addAssign( uint( xx ) ); + + return mx_bjfinal( a, b, c ); + +} ).setLayout( { + name: 'mx_hash_int_3', + type: 'uint', + inputs: [ + { name: 'x', type: 'int' }, + { name: 'y', type: 'int' }, + { name: 'z', type: 'int' }, + { name: 'xx', type: 'int' } + ] +} ); + +const mx_hash_int_4 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable, z_immutable, xx_immutable, yy_immutable ] ) => { + + const yy = int( yy_immutable ).toVar(); + const xx = int( xx_immutable ).toVar(); + const z = int( z_immutable ).toVar(); + const y = int( y_immutable ).toVar(); + const x = int( x_immutable ).toVar(); + const len = uint( uint( 5 ) ).toVar(); + const a = uint().toVar(), b = uint().toVar(), c = uint().toVar(); + a.assign( b.assign( c.assign( uint( int( 0xdeadbeef ) ).add( len.shiftLeft( uint( 2 ) ) ).add( uint( 13 ) ) ) ) ); + a.addAssign( uint( x ) ); + b.addAssign( uint( y ) ); + c.addAssign( uint( z ) ); + mx_bjmix( a, b, c ); + a.addAssign( uint( xx ) ); + b.addAssign( uint( yy ) ); + + return mx_bjfinal( a, b, c ); + +} ).setLayout( { + name: 'mx_hash_int_4', + type: 'uint', + inputs: [ + { name: 'x', type: 'int' }, + { name: 'y', type: 'int' }, + { name: 'z', type: 'int' }, + { name: 'xx', type: 'int' }, + { name: 'yy', type: 'int' } + ] +} ); + +const mx_hash_int = /*@__PURE__*/ overloadingFn( [ mx_hash_int_0, mx_hash_int_1, mx_hash_int_2, mx_hash_int_3, mx_hash_int_4 ] ); + +const mx_hash_vec3_0 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable ] ) => { + + const y = int( y_immutable ).toVar(); + const x = int( x_immutable ).toVar(); + const h = uint( mx_hash_int( x, y ) ).toVar(); + const result = uvec3().toVar(); + result.x.assign( h.bitAnd( int( 0xFF ) ) ); + result.y.assign( h.shiftRight( int( 8 ) ).bitAnd( int( 0xFF ) ) ); + result.z.assign( h.shiftRight( int( 16 ) ).bitAnd( int( 0xFF ) ) ); + + return result; + +} ).setLayout( { + name: 'mx_hash_vec3_0', + type: 'uvec3', + inputs: [ + { name: 'x', type: 'int' }, + { name: 'y', type: 'int' } + ] +} ); + +const mx_hash_vec3_1 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable, z_immutable ] ) => { + + const z = int( z_immutable ).toVar(); + const y = int( y_immutable ).toVar(); + const x = int( x_immutable ).toVar(); + const h = uint( mx_hash_int( x, y, z ) ).toVar(); + const result = uvec3().toVar(); + result.x.assign( h.bitAnd( int( 0xFF ) ) ); + result.y.assign( h.shiftRight( int( 8 ) ).bitAnd( int( 0xFF ) ) ); + result.z.assign( h.shiftRight( int( 16 ) ).bitAnd( int( 0xFF ) ) ); + + return result; + +} ).setLayout( { + name: 'mx_hash_vec3_1', + type: 'uvec3', + inputs: [ + { name: 'x', type: 'int' }, + { name: 'y', type: 'int' }, + { name: 'z', type: 'int' } + ] +} ); + +const mx_hash_vec3 = /*@__PURE__*/ overloadingFn( [ mx_hash_vec3_0, mx_hash_vec3_1 ] ); + +const mx_perlin_noise_float_0 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec2( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(); + const fx = float( mx_floorfrac( p.x, X ) ).toVar(); + const fy = float( mx_floorfrac( p.y, Y ) ).toVar(); + const u = float( mx_fade( fx ) ).toVar(); + const v = float( mx_fade( fy ) ).toVar(); + const result = float( mx_bilerp( mx_gradient_float( mx_hash_int( X, Y ), fx, fy ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y ), fx.sub( 1.0 ), fy ), mx_gradient_float( mx_hash_int( X, Y.add( int( 1 ) ) ), fx, fy.sub( 1.0 ) ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y.add( int( 1 ) ) ), fx.sub( 1.0 ), fy.sub( 1.0 ) ), u, v ) ).toVar(); + + return mx_gradient_scale2d( result ); + +} ).setLayout( { + name: 'mx_perlin_noise_float_0', + type: 'float', + inputs: [ + { name: 'p', type: 'vec2' } + ] +} ); + +const mx_perlin_noise_float_1 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec3( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(), Z = int().toVar(); + const fx = float( mx_floorfrac( p.x, X ) ).toVar(); + const fy = float( mx_floorfrac( p.y, Y ) ).toVar(); + const fz = float( mx_floorfrac( p.z, Z ) ).toVar(); + const u = float( mx_fade( fx ) ).toVar(); + const v = float( mx_fade( fy ) ).toVar(); + const w = float( mx_fade( fz ) ).toVar(); + const result = float( mx_trilerp( mx_gradient_float( mx_hash_int( X, Y, Z ), fx, fy, fz ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y, Z ), fx.sub( 1.0 ), fy, fz ), mx_gradient_float( mx_hash_int( X, Y.add( int( 1 ) ), Z ), fx, fy.sub( 1.0 ), fz ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y.add( int( 1 ) ), Z ), fx.sub( 1.0 ), fy.sub( 1.0 ), fz ), mx_gradient_float( mx_hash_int( X, Y, Z.add( int( 1 ) ) ), fx, fy, fz.sub( 1.0 ) ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y, Z.add( int( 1 ) ) ), fx.sub( 1.0 ), fy, fz.sub( 1.0 ) ), mx_gradient_float( mx_hash_int( X, Y.add( int( 1 ) ), Z.add( int( 1 ) ) ), fx, fy.sub( 1.0 ), fz.sub( 1.0 ) ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y.add( int( 1 ) ), Z.add( int( 1 ) ) ), fx.sub( 1.0 ), fy.sub( 1.0 ), fz.sub( 1.0 ) ), u, v, w ) ).toVar(); + + return mx_gradient_scale3d( result ); + +} ).setLayout( { + name: 'mx_perlin_noise_float_1', + type: 'float', + inputs: [ + { name: 'p', type: 'vec3' } + ] +} ); + +const mx_perlin_noise_float = /*@__PURE__*/ overloadingFn( [ mx_perlin_noise_float_0, mx_perlin_noise_float_1 ] ); + +const mx_perlin_noise_vec3_0 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec2( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(); + const fx = float( mx_floorfrac( p.x, X ) ).toVar(); + const fy = float( mx_floorfrac( p.y, Y ) ).toVar(); + const u = float( mx_fade( fx ) ).toVar(); + const v = float( mx_fade( fy ) ).toVar(); + const result = vec3( mx_bilerp( mx_gradient_vec3( mx_hash_vec3( X, Y ), fx, fy ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y ), fx.sub( 1.0 ), fy ), mx_gradient_vec3( mx_hash_vec3( X, Y.add( int( 1 ) ) ), fx, fy.sub( 1.0 ) ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y.add( int( 1 ) ) ), fx.sub( 1.0 ), fy.sub( 1.0 ) ), u, v ) ).toVar(); + + return mx_gradient_scale2d( result ); + +} ).setLayout( { + name: 'mx_perlin_noise_vec3_0', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec2' } + ] +} ); + +const mx_perlin_noise_vec3_1 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec3( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(), Z = int().toVar(); + const fx = float( mx_floorfrac( p.x, X ) ).toVar(); + const fy = float( mx_floorfrac( p.y, Y ) ).toVar(); + const fz = float( mx_floorfrac( p.z, Z ) ).toVar(); + const u = float( mx_fade( fx ) ).toVar(); + const v = float( mx_fade( fy ) ).toVar(); + const w = float( mx_fade( fz ) ).toVar(); + const result = vec3( mx_trilerp( mx_gradient_vec3( mx_hash_vec3( X, Y, Z ), fx, fy, fz ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y, Z ), fx.sub( 1.0 ), fy, fz ), mx_gradient_vec3( mx_hash_vec3( X, Y.add( int( 1 ) ), Z ), fx, fy.sub( 1.0 ), fz ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y.add( int( 1 ) ), Z ), fx.sub( 1.0 ), fy.sub( 1.0 ), fz ), mx_gradient_vec3( mx_hash_vec3( X, Y, Z.add( int( 1 ) ) ), fx, fy, fz.sub( 1.0 ) ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y, Z.add( int( 1 ) ) ), fx.sub( 1.0 ), fy, fz.sub( 1.0 ) ), mx_gradient_vec3( mx_hash_vec3( X, Y.add( int( 1 ) ), Z.add( int( 1 ) ) ), fx, fy.sub( 1.0 ), fz.sub( 1.0 ) ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y.add( int( 1 ) ), Z.add( int( 1 ) ) ), fx.sub( 1.0 ), fy.sub( 1.0 ), fz.sub( 1.0 ) ), u, v, w ) ).toVar(); + + return mx_gradient_scale3d( result ); + +} ).setLayout( { + name: 'mx_perlin_noise_vec3_1', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec3' } + ] +} ); + +const mx_perlin_noise_vec3 = /*@__PURE__*/ overloadingFn( [ mx_perlin_noise_vec3_0, mx_perlin_noise_vec3_1 ] ); + +const mx_cell_noise_float_0 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = float( p_immutable ).toVar(); + const ix = int( mx_floor( p ) ).toVar(); + + return mx_bits_to_01( mx_hash_int( ix ) ); + +} ).setLayout( { + name: 'mx_cell_noise_float_0', + type: 'float', + inputs: [ + { name: 'p', type: 'float' } + ] +} ); + +const mx_cell_noise_float_1 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec2( p_immutable ).toVar(); + const ix = int( mx_floor( p.x ) ).toVar(); + const iy = int( mx_floor( p.y ) ).toVar(); + + return mx_bits_to_01( mx_hash_int( ix, iy ) ); + +} ).setLayout( { + name: 'mx_cell_noise_float_1', + type: 'float', + inputs: [ + { name: 'p', type: 'vec2' } + ] +} ); + +const mx_cell_noise_float_2 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec3( p_immutable ).toVar(); + const ix = int( mx_floor( p.x ) ).toVar(); + const iy = int( mx_floor( p.y ) ).toVar(); + const iz = int( mx_floor( p.z ) ).toVar(); + + return mx_bits_to_01( mx_hash_int( ix, iy, iz ) ); + +} ).setLayout( { + name: 'mx_cell_noise_float_2', + type: 'float', + inputs: [ + { name: 'p', type: 'vec3' } + ] +} ); + +const mx_cell_noise_float_3 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec4( p_immutable ).toVar(); + const ix = int( mx_floor( p.x ) ).toVar(); + const iy = int( mx_floor( p.y ) ).toVar(); + const iz = int( mx_floor( p.z ) ).toVar(); + const iw = int( mx_floor( p.w ) ).toVar(); + + return mx_bits_to_01( mx_hash_int( ix, iy, iz, iw ) ); + +} ).setLayout( { + name: 'mx_cell_noise_float_3', + type: 'float', + inputs: [ + { name: 'p', type: 'vec4' } + ] +} ); + +const mx_cell_noise_float$1 = /*@__PURE__*/ overloadingFn( [ mx_cell_noise_float_0, mx_cell_noise_float_1, mx_cell_noise_float_2, mx_cell_noise_float_3 ] ); + +const mx_cell_noise_vec3_0 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = float( p_immutable ).toVar(); + const ix = int( mx_floor( p ) ).toVar(); + + return vec3( mx_bits_to_01( mx_hash_int( ix, int( 0 ) ) ), mx_bits_to_01( mx_hash_int( ix, int( 1 ) ) ), mx_bits_to_01( mx_hash_int( ix, int( 2 ) ) ) ); + +} ).setLayout( { + name: 'mx_cell_noise_vec3_0', + type: 'vec3', + inputs: [ + { name: 'p', type: 'float' } + ] +} ); + +const mx_cell_noise_vec3_1 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec2( p_immutable ).toVar(); + const ix = int( mx_floor( p.x ) ).toVar(); + const iy = int( mx_floor( p.y ) ).toVar(); + + return vec3( mx_bits_to_01( mx_hash_int( ix, iy, int( 0 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, int( 1 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, int( 2 ) ) ) ); + +} ).setLayout( { + name: 'mx_cell_noise_vec3_1', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec2' } + ] +} ); + +const mx_cell_noise_vec3_2 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec3( p_immutable ).toVar(); + const ix = int( mx_floor( p.x ) ).toVar(); + const iy = int( mx_floor( p.y ) ).toVar(); + const iz = int( mx_floor( p.z ) ).toVar(); + + return vec3( mx_bits_to_01( mx_hash_int( ix, iy, iz, int( 0 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, iz, int( 1 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, iz, int( 2 ) ) ) ); + +} ).setLayout( { + name: 'mx_cell_noise_vec3_2', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec3' } + ] +} ); + +const mx_cell_noise_vec3_3 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec4( p_immutable ).toVar(); + const ix = int( mx_floor( p.x ) ).toVar(); + const iy = int( mx_floor( p.y ) ).toVar(); + const iz = int( mx_floor( p.z ) ).toVar(); + const iw = int( mx_floor( p.w ) ).toVar(); + + return vec3( mx_bits_to_01( mx_hash_int( ix, iy, iz, iw, int( 0 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, iz, iw, int( 1 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, iz, iw, int( 2 ) ) ) ); + +} ).setLayout( { + name: 'mx_cell_noise_vec3_3', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec4' } + ] +} ); + +const mx_cell_noise_vec3 = /*@__PURE__*/ overloadingFn( [ mx_cell_noise_vec3_0, mx_cell_noise_vec3_1, mx_cell_noise_vec3_2, mx_cell_noise_vec3_3 ] ); + +const mx_fractal_noise_float$1 = /*@__PURE__*/ Fn( ( [ p_immutable, octaves_immutable, lacunarity_immutable, diminish_immutable ] ) => { + + const diminish = float( diminish_immutable ).toVar(); + const lacunarity = float( lacunarity_immutable ).toVar(); + const octaves = int( octaves_immutable ).toVar(); + const p = vec3( p_immutable ).toVar(); + const result = float( 0.0 ).toVar(); + const amplitude = float( 1.0 ).toVar(); + + Loop( octaves, () => { + + result.addAssign( amplitude.mul( mx_perlin_noise_float( p ) ) ); + amplitude.mulAssign( diminish ); + p.mulAssign( lacunarity ); + + } ); + + return result; + +} ).setLayout( { + name: 'mx_fractal_noise_float', + type: 'float', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'octaves', type: 'int' }, + { name: 'lacunarity', type: 'float' }, + { name: 'diminish', type: 'float' } + ] +} ); + +const mx_fractal_noise_vec3$1 = /*@__PURE__*/ Fn( ( [ p_immutable, octaves_immutable, lacunarity_immutable, diminish_immutable ] ) => { + + const diminish = float( diminish_immutable ).toVar(); + const lacunarity = float( lacunarity_immutable ).toVar(); + const octaves = int( octaves_immutable ).toVar(); + const p = vec3( p_immutable ).toVar(); + const result = vec3( 0.0 ).toVar(); + const amplitude = float( 1.0 ).toVar(); + + Loop( octaves, () => { + + result.addAssign( amplitude.mul( mx_perlin_noise_vec3( p ) ) ); + amplitude.mulAssign( diminish ); + p.mulAssign( lacunarity ); + + } ); + + return result; + +} ).setLayout( { + name: 'mx_fractal_noise_vec3', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'octaves', type: 'int' }, + { name: 'lacunarity', type: 'float' }, + { name: 'diminish', type: 'float' } + ] +} ); + +const mx_fractal_noise_vec2$1 = /*@__PURE__*/ Fn( ( [ p_immutable, octaves_immutable, lacunarity_immutable, diminish_immutable ] ) => { + + const diminish = float( diminish_immutable ).toVar(); + const lacunarity = float( lacunarity_immutable ).toVar(); + const octaves = int( octaves_immutable ).toVar(); + const p = vec3( p_immutable ).toVar(); + + return vec2( mx_fractal_noise_float$1( p, octaves, lacunarity, diminish ), mx_fractal_noise_float$1( p.add( vec3( int( 19 ), int( 193 ), int( 17 ) ) ), octaves, lacunarity, diminish ) ); + +} ).setLayout( { + name: 'mx_fractal_noise_vec2', + type: 'vec2', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'octaves', type: 'int' }, + { name: 'lacunarity', type: 'float' }, + { name: 'diminish', type: 'float' } + ] +} ); + +const mx_fractal_noise_vec4$1 = /*@__PURE__*/ Fn( ( [ p_immutable, octaves_immutable, lacunarity_immutable, diminish_immutable ] ) => { + + const diminish = float( diminish_immutable ).toVar(); + const lacunarity = float( lacunarity_immutable ).toVar(); + const octaves = int( octaves_immutable ).toVar(); + const p = vec3( p_immutable ).toVar(); + const c = vec3( mx_fractal_noise_vec3$1( p, octaves, lacunarity, diminish ) ).toVar(); + const f = float( mx_fractal_noise_float$1( p.add( vec3( int( 19 ), int( 193 ), int( 17 ) ) ), octaves, lacunarity, diminish ) ).toVar(); + + return vec4( c, f ); + +} ).setLayout( { + name: 'mx_fractal_noise_vec4', + type: 'vec4', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'octaves', type: 'int' }, + { name: 'lacunarity', type: 'float' }, + { name: 'diminish', type: 'float' } + ] +} ); + +const mx_worley_distance_0 = /*@__PURE__*/ Fn( ( [ p_immutable, x_immutable, y_immutable, xoff_immutable, yoff_immutable, jitter_immutable, metric_immutable ] ) => { + + const metric = int( metric_immutable ).toVar(); + const jitter = float( jitter_immutable ).toVar(); + const yoff = int( yoff_immutable ).toVar(); + const xoff = int( xoff_immutable ).toVar(); + const y = int( y_immutable ).toVar(); + const x = int( x_immutable ).toVar(); + const p = vec2( p_immutable ).toVar(); + const tmp = vec3( mx_cell_noise_vec3( vec2( x.add( xoff ), y.add( yoff ) ) ) ).toVar(); + const off = vec2( tmp.x, tmp.y ).toVar(); + off.subAssign( 0.5 ); + off.mulAssign( jitter ); + off.addAssign( 0.5 ); + const cellpos = vec2( vec2( float( x ), float( y ) ).add( off ) ).toVar(); + const diff = vec2( cellpos.sub( p ) ).toVar(); + + If( metric.equal( int( 2 ) ), () => { + + return abs( diff.x ).add( abs( diff.y ) ); + + } ); + + If( metric.equal( int( 3 ) ), () => { + + return max$1( abs( diff.x ), abs( diff.y ) ); + + } ); + + return dot( diff, diff ); + +} ).setLayout( { + name: 'mx_worley_distance_0', + type: 'float', + inputs: [ + { name: 'p', type: 'vec2' }, + { name: 'x', type: 'int' }, + { name: 'y', type: 'int' }, + { name: 'xoff', type: 'int' }, + { name: 'yoff', type: 'int' }, + { name: 'jitter', type: 'float' }, + { name: 'metric', type: 'int' } + ] +} ); + +const mx_worley_distance_1 = /*@__PURE__*/ Fn( ( [ p_immutable, x_immutable, y_immutable, z_immutable, xoff_immutable, yoff_immutable, zoff_immutable, jitter_immutable, metric_immutable ] ) => { + + const metric = int( metric_immutable ).toVar(); + const jitter = float( jitter_immutable ).toVar(); + const zoff = int( zoff_immutable ).toVar(); + const yoff = int( yoff_immutable ).toVar(); + const xoff = int( xoff_immutable ).toVar(); + const z = int( z_immutable ).toVar(); + const y = int( y_immutable ).toVar(); + const x = int( x_immutable ).toVar(); + const p = vec3( p_immutable ).toVar(); + const off = vec3( mx_cell_noise_vec3( vec3( x.add( xoff ), y.add( yoff ), z.add( zoff ) ) ) ).toVar(); + off.subAssign( 0.5 ); + off.mulAssign( jitter ); + off.addAssign( 0.5 ); + const cellpos = vec3( vec3( float( x ), float( y ), float( z ) ).add( off ) ).toVar(); + const diff = vec3( cellpos.sub( p ) ).toVar(); + + If( metric.equal( int( 2 ) ), () => { + + return abs( diff.x ).add( abs( diff.y ) ).add( abs( diff.z ) ); + + } ); + + If( metric.equal( int( 3 ) ), () => { + + return max$1( max$1( abs( diff.x ), abs( diff.y ) ), abs( diff.z ) ); + + } ); + + return dot( diff, diff ); + +} ).setLayout( { + name: 'mx_worley_distance_1', + type: 'float', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'x', type: 'int' }, + { name: 'y', type: 'int' }, + { name: 'z', type: 'int' }, + { name: 'xoff', type: 'int' }, + { name: 'yoff', type: 'int' }, + { name: 'zoff', type: 'int' }, + { name: 'jitter', type: 'float' }, + { name: 'metric', type: 'int' } + ] +} ); + +const mx_worley_distance = /*@__PURE__*/ overloadingFn( [ mx_worley_distance_0, mx_worley_distance_1 ] ); + +const mx_worley_noise_float_0 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { + + const metric = int( metric_immutable ).toVar(); + const jitter = float( jitter_immutable ).toVar(); + const p = vec2( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(); + const localpos = vec2( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ) ).toVar(); + const sqdist = float( 1e6 ).toVar(); + + Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + + const dist = float( mx_worley_distance( localpos, x, y, X, Y, jitter, metric ) ).toVar(); + sqdist.assign( min$1( sqdist, dist ) ); + + } ); + + } ); + + If( metric.equal( int( 0 ) ), () => { + + sqdist.assign( sqrt( sqdist ) ); + + } ); + + return sqdist; + +} ).setLayout( { + name: 'mx_worley_noise_float_0', + type: 'float', + inputs: [ + { name: 'p', type: 'vec2' }, + { name: 'jitter', type: 'float' }, + { name: 'metric', type: 'int' } + ] +} ); + +const mx_worley_noise_vec2_0 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { + + const metric = int( metric_immutable ).toVar(); + const jitter = float( jitter_immutable ).toVar(); + const p = vec2( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(); + const localpos = vec2( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ) ).toVar(); + const sqdist = vec2( 1e6, 1e6 ).toVar(); + + Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + + const dist = float( mx_worley_distance( localpos, x, y, X, Y, jitter, metric ) ).toVar(); + + If( dist.lessThan( sqdist.x ), () => { + + sqdist.y.assign( sqdist.x ); + sqdist.x.assign( dist ); + + } ).ElseIf( dist.lessThan( sqdist.y ), () => { + + sqdist.y.assign( dist ); + + } ); + + } ); + + } ); + + If( metric.equal( int( 0 ) ), () => { + + sqdist.assign( sqrt( sqdist ) ); + + } ); + + return sqdist; + +} ).setLayout( { + name: 'mx_worley_noise_vec2_0', + type: 'vec2', + inputs: [ + { name: 'p', type: 'vec2' }, + { name: 'jitter', type: 'float' }, + { name: 'metric', type: 'int' } + ] +} ); + +const mx_worley_noise_vec3_0 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { + + const metric = int( metric_immutable ).toVar(); + const jitter = float( jitter_immutable ).toVar(); + const p = vec2( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(); + const localpos = vec2( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ) ).toVar(); + const sqdist = vec3( 1e6, 1e6, 1e6 ).toVar(); + + Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + + const dist = float( mx_worley_distance( localpos, x, y, X, Y, jitter, metric ) ).toVar(); + + If( dist.lessThan( sqdist.x ), () => { + + sqdist.z.assign( sqdist.y ); + sqdist.y.assign( sqdist.x ); + sqdist.x.assign( dist ); + + } ).ElseIf( dist.lessThan( sqdist.y ), () => { + + sqdist.z.assign( sqdist.y ); + sqdist.y.assign( dist ); + + } ).ElseIf( dist.lessThan( sqdist.z ), () => { + + sqdist.z.assign( dist ); + + } ); + + } ); + + } ); + + If( metric.equal( int( 0 ) ), () => { + + sqdist.assign( sqrt( sqdist ) ); + + } ); + + return sqdist; + +} ).setLayout( { + name: 'mx_worley_noise_vec3_0', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec2' }, + { name: 'jitter', type: 'float' }, + { name: 'metric', type: 'int' } + ] +} ); + +const mx_worley_noise_float_1 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { + + const metric = int( metric_immutable ).toVar(); + const jitter = float( jitter_immutable ).toVar(); + const p = vec3( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(), Z = int().toVar(); + const localpos = vec3( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ), mx_floorfrac( p.z, Z ) ).toVar(); + const sqdist = float( 1e6 ).toVar(); + + Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'z', condition: '<=' }, ( { z } ) => { + + const dist = float( mx_worley_distance( localpos, x, y, z, X, Y, Z, jitter, metric ) ).toVar(); + sqdist.assign( min$1( sqdist, dist ) ); + + } ); + + } ); + + } ); + + If( metric.equal( int( 0 ) ), () => { + + sqdist.assign( sqrt( sqdist ) ); + + } ); + + return sqdist; + +} ).setLayout( { + name: 'mx_worley_noise_float_1', + type: 'float', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'jitter', type: 'float' }, + { name: 'metric', type: 'int' } + ] +} ); + +const mx_worley_noise_float$1 = /*@__PURE__*/ overloadingFn( [ mx_worley_noise_float_0, mx_worley_noise_float_1 ] ); + +const mx_worley_noise_vec2_1 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { + + const metric = int( metric_immutable ).toVar(); + const jitter = float( jitter_immutable ).toVar(); + const p = vec3( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(), Z = int().toVar(); + const localpos = vec3( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ), mx_floorfrac( p.z, Z ) ).toVar(); + const sqdist = vec2( 1e6, 1e6 ).toVar(); + + Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'z', condition: '<=' }, ( { z } ) => { + + const dist = float( mx_worley_distance( localpos, x, y, z, X, Y, Z, jitter, metric ) ).toVar(); + + If( dist.lessThan( sqdist.x ), () => { + + sqdist.y.assign( sqdist.x ); + sqdist.x.assign( dist ); + + } ).ElseIf( dist.lessThan( sqdist.y ), () => { + + sqdist.y.assign( dist ); + + } ); + + } ); + + } ); + + } ); + + If( metric.equal( int( 0 ) ), () => { + + sqdist.assign( sqrt( sqdist ) ); + + } ); + + return sqdist; + +} ).setLayout( { + name: 'mx_worley_noise_vec2_1', + type: 'vec2', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'jitter', type: 'float' }, + { name: 'metric', type: 'int' } + ] +} ); + +const mx_worley_noise_vec2$1 = /*@__PURE__*/ overloadingFn( [ mx_worley_noise_vec2_0, mx_worley_noise_vec2_1 ] ); + +const mx_worley_noise_vec3_1 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { + + const metric = int( metric_immutable ).toVar(); + const jitter = float( jitter_immutable ).toVar(); + const p = vec3( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(), Z = int().toVar(); + const localpos = vec3( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ), mx_floorfrac( p.z, Z ) ).toVar(); + const sqdist = vec3( 1e6, 1e6, 1e6 ).toVar(); + + Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'z', condition: '<=' }, ( { z } ) => { + + const dist = float( mx_worley_distance( localpos, x, y, z, X, Y, Z, jitter, metric ) ).toVar(); + + If( dist.lessThan( sqdist.x ), () => { + + sqdist.z.assign( sqdist.y ); + sqdist.y.assign( sqdist.x ); + sqdist.x.assign( dist ); + + } ).ElseIf( dist.lessThan( sqdist.y ), () => { + + sqdist.z.assign( sqdist.y ); + sqdist.y.assign( dist ); + + } ).ElseIf( dist.lessThan( sqdist.z ), () => { + + sqdist.z.assign( dist ); + + } ); + + } ); + + } ); + + } ); + + If( metric.equal( int( 0 ) ), () => { + + sqdist.assign( sqrt( sqdist ) ); + + } ); + + return sqdist; + +} ).setLayout( { + name: 'mx_worley_noise_vec3_1', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'jitter', type: 'float' }, + { name: 'metric', type: 'int' } + ] +} ); + +const mx_worley_noise_vec3$1 = /*@__PURE__*/ overloadingFn( [ mx_worley_noise_vec3_0, mx_worley_noise_vec3_1 ] ); + +// Three.js Transpiler +// https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/stdlib/genglsl/lib/mx_hsv.glsl + + +const mx_hsvtorgb = /*@__PURE__*/ Fn( ( [ hsv ] ) => { + + const s = hsv.y; + const v = hsv.z; + + const result = vec3().toVar(); + + If( s.lessThan( 0.0001 ), () => { + + result.assign( vec3( v, v, v ) ); + + } ).Else( () => { + + let h = hsv.x; + h = h.sub( floor( h ) ).mul( 6.0 ).toVar(); // TODO: check what .toVar() is needed in node system cache + const hi = int( trunc( h ) ); + const f = h.sub( float( hi ) ); + const p = v.mul( s.oneMinus() ); + const q = v.mul( s.mul( f ).oneMinus() ); + const t = v.mul( s.mul( f.oneMinus() ).oneMinus() ); + + If( hi.equal( int( 0 ) ), () => { + + result.assign( vec3( v, t, p ) ); + + } ).ElseIf( hi.equal( int( 1 ) ), () => { + + result.assign( vec3( q, v, p ) ); + + } ).ElseIf( hi.equal( int( 2 ) ), () => { + + result.assign( vec3( p, v, t ) ); + + } ).ElseIf( hi.equal( int( 3 ) ), () => { + + result.assign( vec3( p, q, v ) ); + + } ).ElseIf( hi.equal( int( 4 ) ), () => { + + result.assign( vec3( t, p, v ) ); + + } ).Else( () => { + + result.assign( vec3( v, p, q ) ); + + } ); + + } ); + + return result; + +} ).setLayout( { + name: 'mx_hsvtorgb', + type: 'vec3', + inputs: [ + { name: 'hsv', type: 'vec3' } + ] +} ); + +const mx_rgbtohsv = /*@__PURE__*/ Fn( ( [ c_immutable ] ) => { + + const c = vec3( c_immutable ).toVar(); + const r = float( c.x ).toVar(); + const g = float( c.y ).toVar(); + const b = float( c.z ).toVar(); + const mincomp = float( min$1( r, min$1( g, b ) ) ).toVar(); + const maxcomp = float( max$1( r, max$1( g, b ) ) ).toVar(); + const delta = float( maxcomp.sub( mincomp ) ).toVar(); + const h = float().toVar(), s = float().toVar(), v = float().toVar(); + v.assign( maxcomp ); + + If( maxcomp.greaterThan( 0.0 ), () => { + + s.assign( delta.div( maxcomp ) ); + + } ).Else( () => { + + s.assign( 0.0 ); + + } ); + + If( s.lessThanEqual( 0.0 ), () => { + + h.assign( 0.0 ); + + } ).Else( () => { + + If( r.greaterThanEqual( maxcomp ), () => { + + h.assign( g.sub( b ).div( delta ) ); + + } ).ElseIf( g.greaterThanEqual( maxcomp ), () => { + + h.assign( add( 2.0, b.sub( r ).div( delta ) ) ); + + } ).Else( () => { + + h.assign( add( 4.0, r.sub( g ).div( delta ) ) ); + + } ); + + h.mulAssign( 1.0 / 6.0 ); + + If( h.lessThan( 0.0 ), () => { + + h.addAssign( 1.0 ); + + } ); + + } ); + + return vec3( h, s, v ); + +} ).setLayout( { + name: 'mx_rgbtohsv', + type: 'vec3', + inputs: [ + { name: 'c', type: 'vec3' } + ] +} ); + +// Three.js Transpiler +// https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/stdlib/genglsl/lib/mx_transform_color.glsl + + +const mx_srgb_texture_to_lin_rec709 = /*@__PURE__*/ Fn( ( [ color_immutable ] ) => { + + const color = vec3( color_immutable ).toVar(); + const isAbove = bvec3( greaterThan( color, vec3( 0.04045 ) ) ).toVar(); + const linSeg = vec3( color.div( 12.92 ) ).toVar(); + const powSeg = vec3( pow( max$1( color.add( vec3( 0.055 ) ), vec3( 0.0 ) ).div( 1.055 ), vec3( 2.4 ) ) ).toVar(); + + return mix( linSeg, powSeg, isAbove ); + +} ).setLayout( { + name: 'mx_srgb_texture_to_lin_rec709', + type: 'vec3', + inputs: [ + { name: 'color', type: 'vec3' } + ] +} ); + +const mx_aastep = ( threshold, value ) => { + + threshold = float( threshold ); + value = float( value ); + + const afwidth = vec2( value.dFdx(), value.dFdy() ).length().mul( 0.70710678118654757 ); + + return smoothstep( threshold.sub( afwidth ), threshold.add( afwidth ), value ); + +}; + +const _ramp = ( a, b, uv, p ) => mix( a, b, uv[ p ].clamp() ); +const mx_ramplr = ( valuel, valuer, texcoord = uv() ) => _ramp( valuel, valuer, texcoord, 'x' ); +const mx_ramptb = ( valuet, valueb, texcoord = uv() ) => _ramp( valuet, valueb, texcoord, 'y' ); + +const _split = ( a, b, center, uv, p ) => mix( a, b, mx_aastep( center, uv[ p ] ) ); +const mx_splitlr = ( valuel, valuer, center, texcoord = uv() ) => _split( valuel, valuer, center, texcoord, 'x' ); +const mx_splittb = ( valuet, valueb, center, texcoord = uv() ) => _split( valuet, valueb, center, texcoord, 'y' ); + +const mx_transform_uv = ( uv_scale = 1, uv_offset = 0, uv_geo = uv() ) => uv_geo.mul( uv_scale ).add( uv_offset ); + +const mx_safepower = ( in1, in2 = 1 ) => { + + in1 = float( in1 ); + + return in1.abs().pow( in2 ).mul( in1.sign() ); + +}; + +const mx_contrast = ( input, amount = 1, pivot = .5 ) => float( input ).sub( pivot ).mul( amount ).add( pivot ); + +const mx_noise_float = ( texcoord = uv(), amplitude = 1, pivot = 0 ) => mx_perlin_noise_float( texcoord.convert( 'vec2|vec3' ) ).mul( amplitude ).add( pivot ); +//export const mx_noise_vec2 = ( texcoord = uv(), amplitude = 1, pivot = 0 ) => mx_perlin_noise_vec3( texcoord.convert( 'vec2|vec3' ) ).mul( amplitude ).add( pivot ); +const mx_noise_vec3 = ( texcoord = uv(), amplitude = 1, pivot = 0 ) => mx_perlin_noise_vec3( texcoord.convert( 'vec2|vec3' ) ).mul( amplitude ).add( pivot ); +const mx_noise_vec4 = ( texcoord = uv(), amplitude = 1, pivot = 0 ) => { + + texcoord = texcoord.convert( 'vec2|vec3' ); // overloading type + + const noise_vec4 = vec4( mx_perlin_noise_vec3( texcoord ), mx_perlin_noise_float( texcoord.add( vec2( 19, 73 ) ) ) ); + + return noise_vec4.mul( amplitude ).add( pivot ); + +}; + +const mx_worley_noise_float = ( texcoord = uv(), jitter = 1 ) => mx_worley_noise_float$1( texcoord.convert( 'vec2|vec3' ), jitter, int( 1 ) ); +const mx_worley_noise_vec2 = ( texcoord = uv(), jitter = 1 ) => mx_worley_noise_vec2$1( texcoord.convert( 'vec2|vec3' ), jitter, int( 1 ) ); +const mx_worley_noise_vec3 = ( texcoord = uv(), jitter = 1 ) => mx_worley_noise_vec3$1( texcoord.convert( 'vec2|vec3' ), jitter, int( 1 ) ); + +const mx_cell_noise_float = ( texcoord = uv() ) => mx_cell_noise_float$1( texcoord.convert( 'vec2|vec3' ) ); + +const mx_fractal_noise_float = ( position = uv(), octaves = 3, lacunarity = 2, diminish = .5, amplitude = 1 ) => mx_fractal_noise_float$1( position, int( octaves ), lacunarity, diminish ).mul( amplitude ); +const mx_fractal_noise_vec2 = ( position = uv(), octaves = 3, lacunarity = 2, diminish = .5, amplitude = 1 ) => mx_fractal_noise_vec2$1( position, int( octaves ), lacunarity, diminish ).mul( amplitude ); +const mx_fractal_noise_vec3 = ( position = uv(), octaves = 3, lacunarity = 2, diminish = .5, amplitude = 1 ) => mx_fractal_noise_vec3$1( position, int( octaves ), lacunarity, diminish ).mul( amplitude ); +const mx_fractal_noise_vec4 = ( position = uv(), octaves = 3, lacunarity = 2, diminish = .5, amplitude = 1 ) => mx_fractal_noise_vec4$1( position, int( octaves ), lacunarity, diminish ).mul( amplitude ); + +const getShIrradianceAt = /*@__PURE__*/ Fn( ( [ normal, shCoefficients ] ) => { + + // normal is assumed to have unit length + + const x = normal.x, y = normal.y, z = normal.z; + + // band 0 + let result = shCoefficients.element( 0 ).mul( 0.886227 ); + + // band 1 + result = result.add( shCoefficients.element( 1 ).mul( 2.0 * 0.511664 ).mul( y ) ); + result = result.add( shCoefficients.element( 2 ).mul( 2.0 * 0.511664 ).mul( z ) ); + result = result.add( shCoefficients.element( 3 ).mul( 2.0 * 0.511664 ).mul( x ) ); + + // band 2 + result = result.add( shCoefficients.element( 4 ).mul( 2.0 * 0.429043 ).mul( x ).mul( y ) ); + result = result.add( shCoefficients.element( 5 ).mul( 2.0 * 0.429043 ).mul( y ).mul( z ) ); + result = result.add( shCoefficients.element( 6 ).mul( z.mul( z ).mul( 0.743125 ).sub( 0.247708 ) ) ); + result = result.add( shCoefficients.element( 7 ).mul( 2.0 * 0.429043 ).mul( x ).mul( z ) ); + result = result.add( shCoefficients.element( 8 ).mul( 0.429043 ).mul( mul( x, x ).sub( mul( y, y ) ) ) ); + + return result; + +} ); + +class PointLightNode extends AnalyticLightNode { + + static get type() { + + return 'PointLightNode'; + + } + + constructor( light = null ) { + + super( light ); + + this.cutoffDistanceNode = uniform( 0 ).setGroup( renderGroup ); + this.decayExponentNode = uniform( 0 ).setGroup( renderGroup ); + + } + + update( frame ) { + + const { light } = this; + + super.update( frame ); + + this.cutoffDistanceNode.value = light.distance; + this.decayExponentNode.value = light.decay; + + } + + setup( builder ) { + + const { colorNode, cutoffDistanceNode, decayExponentNode, light } = this; + + const lightingModel = builder.context.lightingModel; + + const lVector = lightViewPosition( light ).sub( positionView ); // @TODO: Add it into LightNode + + const lightDirection = lVector.normalize(); + const lightDistance = lVector.length(); + + const lightAttenuation = getDistanceAttenuation( { + lightDistance, + cutoffDistance: cutoffDistanceNode, + decayExponent: decayExponentNode + } ); + + const lightColor = colorNode.mul( lightAttenuation ); + + const reflectedLight = builder.context.reflectedLight; + + lightingModel.direct( { + lightDirection, + lightColor, + reflectedLight + }, builder.stack, builder ); + + } + +} + +class DirectionalLightNode extends AnalyticLightNode { + + static get type() { + + return 'DirectionalLightNode'; + + } + + constructor( light = null ) { + + super( light ); + + } + + setup( builder ) { + + super.setup( builder ); + + const lightingModel = builder.context.lightingModel; + + const lightColor = this.colorNode; + const lightDirection = lightTargetDirection( this.light ); + const reflectedLight = builder.context.reflectedLight; + + lightingModel.direct( { + lightDirection, + lightColor, + reflectedLight + }, builder.stack, builder ); + + } + +} + +const _matrix41 = /*@__PURE__*/ new Matrix4(); +const _matrix42 = /*@__PURE__*/ new Matrix4(); + +let ltcLib = null; + +class RectAreaLightNode extends AnalyticLightNode { + + static get type() { + + return 'RectAreaLightNode'; + + } + + constructor( light = null ) { + + super( light ); + + this.halfHeight = uniform( new Vector3() ).setGroup( renderGroup ); + this.halfWidth = uniform( new Vector3() ).setGroup( renderGroup ); + + } + + update( frame ) { + + super.update( frame ); + + const { light } = this; + + const viewMatrix = frame.camera.matrixWorldInverse; + + _matrix42.identity(); + _matrix41.copy( light.matrixWorld ); + _matrix41.premultiply( viewMatrix ); + _matrix42.extractRotation( _matrix41 ); + + this.halfWidth.value.set( light.width * 0.5, 0.0, 0.0 ); + this.halfHeight.value.set( 0.0, light.height * 0.5, 0.0 ); + + this.halfWidth.value.applyMatrix4( _matrix42 ); + this.halfHeight.value.applyMatrix4( _matrix42 ); + + } + + setup( builder ) { + + super.setup( builder ); + + let ltc_1, ltc_2; + + if ( builder.isAvailable( 'float32Filterable' ) ) { + + ltc_1 = texture( ltcLib.LTC_FLOAT_1 ); + ltc_2 = texture( ltcLib.LTC_FLOAT_2 ); + + } else { + + ltc_1 = texture( ltcLib.LTC_HALF_1 ); + ltc_2 = texture( ltcLib.LTC_HALF_2 ); + + } + + const { colorNode, light } = this; + const lightingModel = builder.context.lightingModel; + + const lightPosition = lightViewPosition( light ); + const reflectedLight = builder.context.reflectedLight; + + lightingModel.directRectArea( { + lightColor: colorNode, + lightPosition, + halfWidth: this.halfWidth, + halfHeight: this.halfHeight, + reflectedLight, + ltc_1, + ltc_2 + }, builder.stack, builder ); + + } + + static setLTC( ltc ) { + + ltcLib = ltc; + + } + +} + +class SpotLightNode extends AnalyticLightNode { + + static get type() { + + return 'SpotLightNode'; + + } + + constructor( light = null ) { + + super( light ); + + this.coneCosNode = uniform( 0 ).setGroup( renderGroup ); + this.penumbraCosNode = uniform( 0 ).setGroup( renderGroup ); + + this.cutoffDistanceNode = uniform( 0 ).setGroup( renderGroup ); + this.decayExponentNode = uniform( 0 ).setGroup( renderGroup ); + + } + + update( frame ) { + + super.update( frame ); + + const { light } = this; + + this.coneCosNode.value = Math.cos( light.angle ); + this.penumbraCosNode.value = Math.cos( light.angle * ( 1 - light.penumbra ) ); + + this.cutoffDistanceNode.value = light.distance; + this.decayExponentNode.value = light.decay; + + } + + getSpotAttenuation( angleCosine ) { + + const { coneCosNode, penumbraCosNode } = this; + + return smoothstep( coneCosNode, penumbraCosNode, angleCosine ); + + } + + setup( builder ) { + + super.setup( builder ); + + const lightingModel = builder.context.lightingModel; + + const { colorNode, cutoffDistanceNode, decayExponentNode, light } = this; + + const lVector = lightViewPosition( light ).sub( positionView ); // @TODO: Add it into LightNode + + const lightDirection = lVector.normalize(); + const angleCos = lightDirection.dot( lightTargetDirection( light ) ); + const spotAttenuation = this.getSpotAttenuation( angleCos ); + + const lightDistance = lVector.length(); + + const lightAttenuation = getDistanceAttenuation( { + lightDistance, + cutoffDistance: cutoffDistanceNode, + decayExponent: decayExponentNode + } ); + + const lightColor = colorNode.mul( spotAttenuation ).mul( lightAttenuation ); + + const reflectedLight = builder.context.reflectedLight; + + lightingModel.direct( { + lightDirection, + lightColor, + reflectedLight + }, builder.stack, builder ); + + } + +} + +class IESSpotLightNode extends SpotLightNode { + + static get type() { + + return 'IESSpotLightNode'; + + } + + getSpotAttenuation( angleCosine ) { + + const iesMap = this.light.iesMap; + + let spotAttenuation = null; + + if ( iesMap && iesMap.isTexture === true ) { + + const angle = angleCosine.acos().mul( 1.0 / Math.PI ); + + spotAttenuation = texture( iesMap, vec2( angle, 0 ), 0 ).r; + + } else { + + spotAttenuation = super.getSpotAttenuation( angleCosine ); + + } + + return spotAttenuation; + + } + +} + +class AmbientLightNode extends AnalyticLightNode { + + static get type() { + + return 'AmbientLightNode'; + + } + + constructor( light = null ) { + + super( light ); + + } + + setup( { context } ) { + + context.irradiance.addAssign( this.colorNode ); + + } + +} + +class HemisphereLightNode extends AnalyticLightNode { + + static get type() { + + return 'HemisphereLightNode'; + + } + + constructor( light = null ) { + + super( light ); + + this.lightPositionNode = lightPosition( light ); + this.lightDirectionNode = this.lightPositionNode.normalize(); + + this.groundColorNode = uniform( new Color() ).setGroup( renderGroup ); + + } + + update( frame ) { + + const { light } = this; + + super.update( frame ); + + this.lightPositionNode.object3d = light; + + this.groundColorNode.value.copy( light.groundColor ).multiplyScalar( light.intensity ); + + } + + setup( builder ) { + + const { colorNode, groundColorNode, lightDirectionNode } = this; + + const dotNL = normalView.dot( lightDirectionNode ); + const hemiDiffuseWeight = dotNL.mul( 0.5 ).add( 0.5 ); + + const irradiance = mix( groundColorNode, colorNode, hemiDiffuseWeight ); + + builder.context.irradiance.addAssign( irradiance ); + + } + +} + +class LightProbeNode extends AnalyticLightNode { + + static get type() { + + return 'LightProbeNode'; + + } + + constructor( light = null ) { + + super( light ); + + const array = []; + + for ( let i = 0; i < 9; i ++ ) array.push( new Vector3() ); + + this.lightProbe = uniformArray( array ); + + } + + update( frame ) { + + const { light } = this; + + super.update( frame ); + + // + + for ( let i = 0; i < 9; i ++ ) { + + this.lightProbe.array[ i ].copy( light.sh.coefficients[ i ] ).multiplyScalar( light.intensity ); + + } + + } + + setup( builder ) { + + const irradiance = getShIrradianceAt( normalWorld, this.lightProbe ); + + builder.context.irradiance.addAssign( irradiance ); + + } + +} + +class NodeParser { + + parseFunction( /*source*/ ) { + + console.warn( 'Abstract function.' ); + + } + +} + +class NodeFunction { + + constructor( type, inputs, name = '', precision = '' ) { + + this.type = type; + this.inputs = inputs; + this.name = name; + this.precision = precision; + + } + + getCode( /*name = this.name*/ ) { + + console.warn( 'Abstract function.' ); + + } + +} + +NodeFunction.isNodeFunction = true; + +const declarationRegexp$1 = /^\s*(highp|mediump|lowp)?\s*([a-z_0-9]+)\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)/i; +const propertiesRegexp$1 = /[a-z_0-9]+/ig; + +const pragmaMain = '#pragma main'; + +const parse$1 = ( source ) => { + + source = source.trim(); + + const pragmaMainIndex = source.indexOf( pragmaMain ); + + const mainCode = pragmaMainIndex !== - 1 ? source.slice( pragmaMainIndex + pragmaMain.length ) : source; + + const declaration = mainCode.match( declarationRegexp$1 ); + + if ( declaration !== null && declaration.length === 5 ) { + + // tokenizer + + const inputsCode = declaration[ 4 ]; + const propsMatches = []; + + let nameMatch = null; + + while ( ( nameMatch = propertiesRegexp$1.exec( inputsCode ) ) !== null ) { + + propsMatches.push( nameMatch ); + + } + + // parser + + const inputs = []; + + let i = 0; + + while ( i < propsMatches.length ) { + + const isConst = propsMatches[ i ][ 0 ] === 'const'; + + if ( isConst === true ) { + + i ++; + + } + + let qualifier = propsMatches[ i ][ 0 ]; + + if ( qualifier === 'in' || qualifier === 'out' || qualifier === 'inout' ) { + + i ++; + + } else { + + qualifier = ''; + + } + + const type = propsMatches[ i ++ ][ 0 ]; + + let count = Number.parseInt( propsMatches[ i ][ 0 ] ); + + if ( Number.isNaN( count ) === false ) i ++; + else count = null; + + const name = propsMatches[ i ++ ][ 0 ]; + + inputs.push( new NodeFunctionInput( type, name, count, qualifier, isConst ) ); + + } + + // + + const blockCode = mainCode.substring( declaration[ 0 ].length ); + + const name = declaration[ 3 ] !== undefined ? declaration[ 3 ] : ''; + const type = declaration[ 2 ]; + + const precision = declaration[ 1 ] !== undefined ? declaration[ 1 ] : ''; + + const headerCode = pragmaMainIndex !== - 1 ? source.slice( 0, pragmaMainIndex ) : ''; + + return { + type, + inputs, + name, + precision, + inputsCode, + blockCode, + headerCode + }; + + } else { + + throw new Error( 'FunctionNode: Function is not a GLSL code.' ); + + } + +}; + +class GLSLNodeFunction extends NodeFunction { + + constructor( source ) { + + const { type, inputs, name, precision, inputsCode, blockCode, headerCode } = parse$1( source ); + + super( type, inputs, name, precision ); + + this.inputsCode = inputsCode; + this.blockCode = blockCode; + this.headerCode = headerCode; + + } + + getCode( name = this.name ) { + + let code; + + const blockCode = this.blockCode; + + if ( blockCode !== '' ) { + + const { type, inputsCode, headerCode, precision } = this; + + let declarationCode = `${ type } ${ name } ( ${ inputsCode.trim() } )`; + + if ( precision !== '' ) { + + declarationCode = `${ precision } ${ declarationCode }`; + + } + + code = headerCode + declarationCode + blockCode; + + } else { + + // interface function + + code = ''; + + } + + return code; + + } + +} + +class GLSLNodeParser extends NodeParser { + + parseFunction( source ) { + + return new GLSLNodeFunction( source ); + + } + +} + +function painterSortStable( a, b ) { + + if ( a.groupOrder !== b.groupOrder ) { + + return a.groupOrder - b.groupOrder; + + } else if ( a.renderOrder !== b.renderOrder ) { + + return a.renderOrder - b.renderOrder; + + } else if ( a.material.id !== b.material.id ) { + + return a.material.id - b.material.id; + + } else if ( a.z !== b.z ) { + + return a.z - b.z; + + } else { + + return a.id - b.id; + + } + +} + +function reversePainterSortStable( a, b ) { + + if ( a.groupOrder !== b.groupOrder ) { + + return a.groupOrder - b.groupOrder; + + } else if ( a.renderOrder !== b.renderOrder ) { + + return a.renderOrder - b.renderOrder; + + } else if ( a.z !== b.z ) { + + return b.z - a.z; + + } else { + + return a.id - b.id; + + } + +} + +class RenderList { + + constructor() { + + this.renderItems = []; + this.renderItemsIndex = 0; + + this.opaque = []; + this.transparent = []; + this.bundles = []; + + this.lightsNode = new LightsNode( [] ); + this.lightsArray = []; + + this.occlusionQueryCount = 0; + + } + + begin() { + + this.renderItemsIndex = 0; + + this.opaque.length = 0; + this.transparent.length = 0; + this.bundles.length = 0; + + this.lightsArray.length = 0; + + this.occlusionQueryCount = 0; + + return this; + + } + + getNextRenderItem( object, geometry, material, groupOrder, z, group ) { + + let renderItem = this.renderItems[ this.renderItemsIndex ]; + + if ( renderItem === undefined ) { + + renderItem = { + id: object.id, + object: object, + geometry: geometry, + material: material, + groupOrder: groupOrder, + renderOrder: object.renderOrder, + z: z, + group: group + }; + + this.renderItems[ this.renderItemsIndex ] = renderItem; + + } else { + + renderItem.id = object.id; + renderItem.object = object; + renderItem.geometry = geometry; + renderItem.material = material; + renderItem.groupOrder = groupOrder; + renderItem.renderOrder = object.renderOrder; + renderItem.z = z; + renderItem.group = group; + + } + + this.renderItemsIndex ++; + + return renderItem; + + } + + push( object, geometry, material, groupOrder, z, group ) { + + const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group ); + + if ( object.occlusionTest === true ) this.occlusionQueryCount ++; + + ( material.transparent === true || material.transmission > 0 ? this.transparent : this.opaque ).push( renderItem ); + + } + + unshift( object, geometry, material, groupOrder, z, group ) { + + const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group ); + + ( material.transparent === true ? this.transparent : this.opaque ).unshift( renderItem ); + + } + + pushBundle( group ) { + + this.bundles.push( group ); + + } + + pushLight( light ) { + + this.lightsArray.push( light ); + + } + + getLightsNode() { + + return this.lightsNode.fromLights( this.lightsArray ); + + } + + sort( customOpaqueSort, customTransparentSort ) { + + if ( this.opaque.length > 1 ) this.opaque.sort( customOpaqueSort || painterSortStable ); + if ( this.transparent.length > 1 ) this.transparent.sort( customTransparentSort || reversePainterSortStable ); + + } + + finish() { + + // update lights + + this.lightsNode.setLights( this.lightsArray ); + + // Clear references from inactive renderItems in the list + + for ( let i = this.renderItemsIndex, il = this.renderItems.length; i < il; i ++ ) { + + const renderItem = this.renderItems[ i ]; + + if ( renderItem.id === null ) break; + + renderItem.id = null; + renderItem.object = null; + renderItem.geometry = null; + renderItem.material = null; + renderItem.groupOrder = null; + renderItem.renderOrder = null; + renderItem.z = null; + renderItem.group = null; + + } + + } + +} + +class RenderLists { + + constructor() { + + this.lists = new ChainMap(); + + } + + get( scene, camera ) { + + const lists = this.lists; + const keys = [ scene, camera ]; + + let list = lists.get( keys ); + + if ( list === undefined ) { + + list = new RenderList(); + lists.set( keys, list ); + + } + + return list; + + } + + dispose() { + + this.lists = new ChainMap(); + + } + +} + +let id = 0; + +class RenderContext { + + constructor() { + + this.id = id ++; + + this.color = true; + this.clearColor = true; + this.clearColorValue = { r: 0, g: 0, b: 0, a: 1 }; + + this.depth = true; + this.clearDepth = true; + this.clearDepthValue = 1; + + this.stencil = false; + this.clearStencil = true; + this.clearStencilValue = 1; + + this.viewport = false; + this.viewportValue = new Vector4(); + + this.scissor = false; + this.scissorValue = new Vector4(); + + this.textures = null; + this.depthTexture = null; + this.activeCubeFace = 0; + this.sampleCount = 1; + + this.width = 0; + this.height = 0; + + this.isRenderContext = true; + + } + + getCacheKey() { + + return getCacheKey( this ); + + } + +} + +function getCacheKey( renderContext ) { + + const { textures, activeCubeFace } = renderContext; + + const values = [ activeCubeFace ]; + + for ( const texture of textures ) { + + values.push( texture.id ); + + } + + return hashArray( values ); + +} + +class RenderContexts { + + constructor() { + + this.chainMaps = {}; + + } + + get( scene, camera, renderTarget = null ) { + + const chainKey = [ scene, camera ]; + + let attachmentState; + + if ( renderTarget === null ) { + + attachmentState = 'default'; + + } else { + + const format = renderTarget.texture.format; + const count = renderTarget.textures.length; + + attachmentState = `${ count }:${ format }:${ renderTarget.samples }:${ renderTarget.depthBuffer }:${ renderTarget.stencilBuffer }`; + + } + + const chainMap = this.getChainMap( attachmentState ); + + let renderState = chainMap.get( chainKey ); + + if ( renderState === undefined ) { + + renderState = new RenderContext(); + + chainMap.set( chainKey, renderState ); + + } + + if ( renderTarget !== null ) renderState.sampleCount = renderTarget.samples === 0 ? 1 : renderTarget.samples; + + return renderState; + + } + + getChainMap( attachmentState ) { + + return this.chainMaps[ attachmentState ] || ( this.chainMaps[ attachmentState ] = new ChainMap() ); + + } + + dispose() { + + this.chainMaps = {}; + + } + +} + +const _size = /*@__PURE__*/ new Vector3(); + +class Textures extends DataMap { + + constructor( renderer, backend, info ) { + + super(); + + this.renderer = renderer; + this.backend = backend; + this.info = info; + + } + + updateRenderTarget( renderTarget, activeMipmapLevel = 0 ) { + + const renderTargetData = this.get( renderTarget ); + + const sampleCount = renderTarget.samples === 0 ? 1 : renderTarget.samples; + const depthTextureMips = renderTargetData.depthTextureMips || ( renderTargetData.depthTextureMips = {} ); + + const textures = renderTarget.textures; + + const size = this.getSize( textures[ 0 ] ); + + const mipWidth = size.width >> activeMipmapLevel; + const mipHeight = size.height >> activeMipmapLevel; + + let depthTexture = renderTarget.depthTexture || depthTextureMips[ activeMipmapLevel ]; + let textureNeedsUpdate = false; + + if ( depthTexture === undefined ) { + + depthTexture = new DepthTexture(); + depthTexture.format = renderTarget.stencilBuffer ? DepthStencilFormat : DepthFormat; + depthTexture.type = renderTarget.stencilBuffer ? UnsignedInt248Type : UnsignedIntType; // FloatType + depthTexture.image.width = mipWidth; + depthTexture.image.height = mipHeight; + + depthTextureMips[ activeMipmapLevel ] = depthTexture; + + } + + if ( renderTargetData.width !== size.width || size.height !== renderTargetData.height ) { + + textureNeedsUpdate = true; + depthTexture.needsUpdate = true; + + depthTexture.image.width = mipWidth; + depthTexture.image.height = mipHeight; + + } + + renderTargetData.width = size.width; + renderTargetData.height = size.height; + renderTargetData.textures = textures; + renderTargetData.depthTexture = depthTexture; + renderTargetData.depth = renderTarget.depthBuffer; + renderTargetData.stencil = renderTarget.stencilBuffer; + renderTargetData.renderTarget = renderTarget; + + if ( renderTargetData.sampleCount !== sampleCount ) { + + textureNeedsUpdate = true; + depthTexture.needsUpdate = true; - } ).ElseIf( dist.lessThan( sqdist.y ), () => { + renderTargetData.sampleCount = sampleCount; - sqdist.z.assign( sqdist.y ); - sqdist.y.assign( dist ); + } - } ).ElseIf( dist.lessThan( sqdist.z ), () => { + // - sqdist.z.assign( dist ); + const options = { sampleCount }; - } ); + for ( let i = 0; i < textures.length; i ++ ) { - } ); + const texture = textures[ i ]; - } ); + if ( textureNeedsUpdate ) texture.needsUpdate = true; - If( metric.equal( int( 0 ) ), () => { + this.updateTexture( texture, options ); - sqdist.assign( sqrt( sqdist ) ); + } - } ); + this.updateTexture( depthTexture, options ); - return sqdist; + // dispose handler -} ).setLayout( { - name: 'mx_worley_noise_vec3_0', - type: 'vec3', - inputs: [ - { name: 'p', type: 'vec2' }, - { name: 'jitter', type: 'float' }, - { name: 'metric', type: 'int' } - ] -} ); + if ( renderTargetData.initialized !== true ) { -const mx_worley_noise_float_1 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { + renderTargetData.initialized = true; - const metric = int( metric_immutable ).toVar(); - const jitter = float( jitter_immutable ).toVar(); - const p = vec3( p_immutable ).toVar(); - const X = int().toVar(), Y = int().toVar(), Z = int().toVar(); - const localpos = vec3( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ), mx_floorfrac( p.z, Z ) ).toVar(); - const sqdist = float( 1e6 ).toVar(); + // dispose - Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + const onDispose = () => { - Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + renderTarget.removeEventListener( 'dispose', onDispose ); - Loop( { start: - 1, end: int( 1 ), name: 'z', condition: '<=' }, ( { z } ) => { + for ( let i = 0; i < textures.length; i ++ ) { - const dist = float( mx_worley_distance( localpos, x, y, z, X, Y, Z, jitter, metric ) ).toVar(); - sqdist.assign( min$1( sqdist, dist ) ); + this._destroyTexture( textures[ i ] ); - } ); + } - } ); + this._destroyTexture( depthTexture ); - } ); + this.delete( renderTarget ); - If( metric.equal( int( 0 ) ), () => { + }; - sqdist.assign( sqrt( sqdist ) ); + renderTarget.addEventListener( 'dispose', onDispose ); - } ); + } - return sqdist; + } -} ).setLayout( { - name: 'mx_worley_noise_float_1', - type: 'float', - inputs: [ - { name: 'p', type: 'vec3' }, - { name: 'jitter', type: 'float' }, - { name: 'metric', type: 'int' } - ] -} ); + updateTexture( texture, options = {} ) { -const mx_worley_noise_float$1 = /*@__PURE__*/ overloadingFn( [ mx_worley_noise_float_0, mx_worley_noise_float_1 ] ); + const textureData = this.get( texture ); + if ( textureData.initialized === true && textureData.version === texture.version ) return; -const mx_worley_noise_vec2_1 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { + const isRenderTarget = texture.isRenderTargetTexture || texture.isDepthTexture || texture.isFramebufferTexture; + const backend = this.backend; - const metric = int( metric_immutable ).toVar(); - const jitter = float( jitter_immutable ).toVar(); - const p = vec3( p_immutable ).toVar(); - const X = int().toVar(), Y = int().toVar(), Z = int().toVar(); - const localpos = vec3( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ), mx_floorfrac( p.z, Z ) ).toVar(); - const sqdist = vec2( 1e6, 1e6 ).toVar(); + if ( isRenderTarget && textureData.initialized === true ) { - Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + // it's an update - Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + backend.destroySampler( texture ); + backend.destroyTexture( texture ); - Loop( { start: - 1, end: int( 1 ), name: 'z', condition: '<=' }, ( { z } ) => { + } - const dist = float( mx_worley_distance( localpos, x, y, z, X, Y, Z, jitter, metric ) ).toVar(); + // - If( dist.lessThan( sqdist.x ), () => { + if ( texture.isFramebufferTexture ) { - sqdist.y.assign( sqdist.x ); - sqdist.x.assign( dist ); + const renderer = this.renderer; + const renderTarget = renderer.getRenderTarget(); - } ).ElseIf( dist.lessThan( sqdist.y ), () => { + if ( renderTarget ) { - sqdist.y.assign( dist ); + texture.type = renderTarget.texture.type; - } ); + } else { - } ); + texture.type = UnsignedByteType; - } ); + } - } ); + } - If( metric.equal( int( 0 ) ), () => { + // - sqdist.assign( sqrt( sqdist ) ); + const { width, height, depth } = this.getSize( texture ); - } ); + options.width = width; + options.height = height; + options.depth = depth; + options.needsMipmaps = this.needsMipmaps( texture ); + options.levels = options.needsMipmaps ? this.getMipLevels( texture, width, height ) : 1; - return sqdist; + // -} ).setLayout( { - name: 'mx_worley_noise_vec2_1', - type: 'vec2', - inputs: [ - { name: 'p', type: 'vec3' }, - { name: 'jitter', type: 'float' }, - { name: 'metric', type: 'int' } - ] -} ); + if ( isRenderTarget || texture.isStorageTexture === true ) { -const mx_worley_noise_vec2$1 = /*@__PURE__*/ overloadingFn( [ mx_worley_noise_vec2_0, mx_worley_noise_vec2_1 ] ); + backend.createSampler( texture ); + backend.createTexture( texture, options ); -const mx_worley_noise_vec3_1 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { + textureData.generation = texture.version; - const metric = int( metric_immutable ).toVar(); - const jitter = float( jitter_immutable ).toVar(); - const p = vec3( p_immutable ).toVar(); - const X = int().toVar(), Y = int().toVar(), Z = int().toVar(); - const localpos = vec3( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ), mx_floorfrac( p.z, Z ) ).toVar(); - const sqdist = vec3( 1e6, 1e6, 1e6 ).toVar(); + } else { - Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + const needsCreate = textureData.initialized !== true; - Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + if ( needsCreate ) backend.createSampler( texture ); - Loop( { start: - 1, end: int( 1 ), name: 'z', condition: '<=' }, ( { z } ) => { + if ( texture.version > 0 ) { - const dist = float( mx_worley_distance( localpos, x, y, z, X, Y, Z, jitter, metric ) ).toVar(); + const image = texture.image; - If( dist.lessThan( sqdist.x ), () => { + if ( image === undefined ) { - sqdist.z.assign( sqdist.y ); - sqdist.y.assign( sqdist.x ); - sqdist.x.assign( dist ); + console.warn( 'THREE.Renderer: Texture marked for update but image is undefined.' ); - } ).ElseIf( dist.lessThan( sqdist.y ), () => { + } else if ( image.complete === false ) { - sqdist.z.assign( sqdist.y ); - sqdist.y.assign( dist ); + console.warn( 'THREE.Renderer: Texture marked for update but image is incomplete.' ); - } ).ElseIf( dist.lessThan( sqdist.z ), () => { + } else { - sqdist.z.assign( dist ); + if ( texture.images ) { - } ); + const images = []; - } ); + for ( const image of texture.images ) { - } ); + images.push( image ); - } ); + } - If( metric.equal( int( 0 ) ), () => { + options.images = images; - sqdist.assign( sqrt( sqdist ) ); + } else { - } ); + options.image = image; - return sqdist; + } -} ).setLayout( { - name: 'mx_worley_noise_vec3_1', - type: 'vec3', - inputs: [ - { name: 'p', type: 'vec3' }, - { name: 'jitter', type: 'float' }, - { name: 'metric', type: 'int' } - ] -} ); + if ( textureData.isDefaultTexture === undefined || textureData.isDefaultTexture === true ) { -const mx_worley_noise_vec3$1 = /*@__PURE__*/ overloadingFn( [ mx_worley_noise_vec3_0, mx_worley_noise_vec3_1 ] ); + backend.createTexture( texture, options ); -// Three.js Transpiler -// https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/stdlib/genglsl/lib/mx_hsv.glsl + textureData.isDefaultTexture = false; + textureData.generation = texture.version; + } -const mx_hsvtorgb = /*@__PURE__*/ Fn( ( [ hsv ] ) => { + if ( texture.source.dataReady === true ) backend.updateTexture( texture, options ); - const s = hsv.y; - const v = hsv.z; + if ( options.needsMipmaps && texture.mipmaps.length === 0 ) backend.generateMipmaps( texture ); - const result = vec3().toVar(); + } - If( s.lessThan( 0.0001 ), () => { + } else { - result.assign( vec3( v, v, v ) ); + // async update - } ).Else( () => { + backend.createDefaultTexture( texture ); - let h = hsv.x; - h = h.sub( floor( h ) ).mul( 6.0 ).toVar(); // TODO: check what .toVar() is needed in node system cache - const hi = int( trunc( h ) ); - const f = h.sub( float( hi ) ); - const p = v.mul( s.oneMinus() ); - const q = v.mul( s.mul( f ).oneMinus() ); - const t = v.mul( s.mul( f.oneMinus() ).oneMinus() ); + textureData.isDefaultTexture = true; + textureData.generation = texture.version; - If( hi.equal( int( 0 ) ), () => { + } - result.assign( vec3( v, t, p ) ); + } - } ).ElseIf( hi.equal( int( 1 ) ), () => { + // dispose handler - result.assign( vec3( q, v, p ) ); + if ( textureData.initialized !== true ) { - } ).ElseIf( hi.equal( int( 2 ) ), () => { + textureData.initialized = true; + textureData.generation = texture.version; - result.assign( vec3( p, v, t ) ); + // - } ).ElseIf( hi.equal( int( 3 ) ), () => { + this.info.memory.textures ++; - result.assign( vec3( p, q, v ) ); + // dispose - } ).ElseIf( hi.equal( int( 4 ) ), () => { + const onDispose = () => { - result.assign( vec3( t, p, v ) ); + texture.removeEventListener( 'dispose', onDispose ); - } ).Else( () => { + this._destroyTexture( texture ); - result.assign( vec3( v, p, q ) ); + this.info.memory.textures --; - } ); + }; - } ); + texture.addEventListener( 'dispose', onDispose ); - return result; + } -} ).setLayout( { - name: 'mx_hsvtorgb', - type: 'vec3', - inputs: [ - { name: 'hsv', type: 'vec3' } - ] -} ); + // -const mx_rgbtohsv = /*@__PURE__*/ Fn( ( [ c_immutable ] ) => { + textureData.version = texture.version; - const c = vec3( c_immutable ).toVar(); - const r = float( c.x ).toVar(); - const g = float( c.y ).toVar(); - const b = float( c.z ).toVar(); - const mincomp = float( min$1( r, min$1( g, b ) ) ).toVar(); - const maxcomp = float( max$1( r, max$1( g, b ) ) ).toVar(); - const delta = float( maxcomp.sub( mincomp ) ).toVar(); - const h = float().toVar(), s = float().toVar(), v = float().toVar(); - v.assign( maxcomp ); + } - If( maxcomp.greaterThan( 0.0 ), () => { + getSize( texture, target = _size ) { - s.assign( delta.div( maxcomp ) ); + let image = texture.images ? texture.images[ 0 ] : texture.image; - } ).Else( () => { + if ( image ) { - s.assign( 0.0 ); + if ( image.image !== undefined ) image = image.image; - } ); + target.width = image.width; + target.height = image.height; + target.depth = texture.isCubeTexture ? 6 : ( image.depth || 1 ); - If( s.lessThanEqual( 0.0 ), () => { + } else { - h.assign( 0.0 ); + target.width = target.height = target.depth = 1; - } ).Else( () => { + } - If( r.greaterThanEqual( maxcomp ), () => { + return target; - h.assign( g.sub( b ).div( delta ) ); + } - } ).ElseIf( g.greaterThanEqual( maxcomp ), () => { + getMipLevels( texture, width, height ) { - h.assign( add( 2.0, b.sub( r ).div( delta ) ) ); + let mipLevelCount; - } ).Else( () => { + if ( texture.isCompressedTexture ) { - h.assign( add( 4.0, r.sub( g ).div( delta ) ) ); + mipLevelCount = texture.mipmaps.length; - } ); + } else { - h.mulAssign( 1.0 / 6.0 ); + mipLevelCount = Math.floor( Math.log2( Math.max( width, height ) ) ) + 1; - If( h.lessThan( 0.0 ), () => { + } - h.addAssign( 1.0 ); + return mipLevelCount; - } ); + } - } ); + needsMipmaps( texture ) { - return vec3( h, s, v ); + if ( this.isEnvironmentTexture( texture ) ) return true; -} ).setLayout( { - name: 'mx_rgbtohsv', - type: 'vec3', - inputs: [ - { name: 'c', type: 'vec3' } - ] -} ); + return ( texture.isCompressedTexture === true ) || ( ( texture.minFilter !== NearestFilter ) && ( texture.minFilter !== LinearFilter ) ); -// Three.js Transpiler -// https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/stdlib/genglsl/lib/mx_transform_color.glsl + } + isEnvironmentTexture( texture ) { -const mx_srgb_texture_to_lin_rec709 = /*@__PURE__*/ Fn( ( [ color_immutable ] ) => { + const mapping = texture.mapping; - const color = vec3( color_immutable ).toVar(); - const isAbove = bvec3( greaterThan( color, vec3( 0.04045 ) ) ).toVar(); - const linSeg = vec3( color.div( 12.92 ) ).toVar(); - const powSeg = vec3( pow( max$1( color.add( vec3( 0.055 ) ), vec3( 0.0 ) ).div( 1.055 ), vec3( 2.4 ) ) ).toVar(); + return ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) || ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping ); - return mix( linSeg, powSeg, isAbove ); + } -} ).setLayout( { - name: 'mx_srgb_texture_to_lin_rec709', - type: 'vec3', - inputs: [ - { name: 'color', type: 'vec3' } - ] -} ); + _destroyTexture( texture ) { -const mx_aastep = ( threshold, value ) => { + this.backend.destroySampler( texture ); + this.backend.destroyTexture( texture ); - threshold = float( threshold ); - value = float( value ); + this.delete( texture ); - const afwidth = vec2( value.dFdx(), value.dFdy() ).length().mul( 0.70710678118654757 ); + } - return smoothstep( threshold.sub( afwidth ), threshold.add( afwidth ), value ); +} -}; +class Color4 extends Color { -const _ramp = ( a, b, uv, p ) => mix( a, b, uv[ p ].clamp() ); -const mx_ramplr = ( valuel, valuer, texcoord = uv() ) => _ramp( valuel, valuer, texcoord, 'x' ); -const mx_ramptb = ( valuet, valueb, texcoord = uv() ) => _ramp( valuet, valueb, texcoord, 'y' ); + constructor( r, g, b, a = 1 ) { -const _split = ( a, b, center, uv, p ) => mix( a, b, mx_aastep( center, uv[ p ] ) ); -const mx_splitlr = ( valuel, valuer, center, texcoord = uv() ) => _split( valuel, valuer, center, texcoord, 'x' ); -const mx_splittb = ( valuet, valueb, center, texcoord = uv() ) => _split( valuet, valueb, center, texcoord, 'y' ); + super( r, g, b ); -const mx_transform_uv = ( uv_scale = 1, uv_offset = 0, uv_geo = uv() ) => uv_geo.mul( uv_scale ).add( uv_offset ); + this.a = a; -const mx_safepower = ( in1, in2 = 1 ) => { + } - in1 = float( in1 ); + set( r, g, b, a = 1 ) { - return in1.abs().pow( in2 ).mul( in1.sign() ); + this.a = a; -}; + return super.set( r, g, b ); -const mx_contrast = ( input, amount = 1, pivot = .5 ) => float( input ).sub( pivot ).mul( amount ).add( pivot ); + } -const mx_noise_float = ( texcoord = uv(), amplitude = 1, pivot = 0 ) => mx_perlin_noise_float( texcoord.convert( 'vec2|vec3' ) ).mul( amplitude ).add( pivot ); -//export const mx_noise_vec2 = ( texcoord = uv(), amplitude = 1, pivot = 0 ) => mx_perlin_noise_vec3( texcoord.convert( 'vec2|vec3' ) ).mul( amplitude ).add( pivot ); -const mx_noise_vec3 = ( texcoord = uv(), amplitude = 1, pivot = 0 ) => mx_perlin_noise_vec3( texcoord.convert( 'vec2|vec3' ) ).mul( amplitude ).add( pivot ); -const mx_noise_vec4 = ( texcoord = uv(), amplitude = 1, pivot = 0 ) => { + copy( color ) { - texcoord = texcoord.convert( 'vec2|vec3' ); // overloading type + if ( color.a !== undefined ) this.a = color.a; - const noise_vec4 = vec4( mx_perlin_noise_vec3( texcoord ), mx_perlin_noise_float( texcoord.add( vec2( 19, 73 ) ) ) ); + return super.copy( color ); - return noise_vec4.mul( amplitude ).add( pivot ); + } -}; + clone() { -const mx_worley_noise_float = ( texcoord = uv(), jitter = 1 ) => mx_worley_noise_float$1( texcoord.convert( 'vec2|vec3' ), jitter, int( 1 ) ); -const mx_worley_noise_vec2 = ( texcoord = uv(), jitter = 1 ) => mx_worley_noise_vec2$1( texcoord.convert( 'vec2|vec3' ), jitter, int( 1 ) ); -const mx_worley_noise_vec3 = ( texcoord = uv(), jitter = 1 ) => mx_worley_noise_vec3$1( texcoord.convert( 'vec2|vec3' ), jitter, int( 1 ) ); + return new this.constructor( this.r, this.g, this.b, this.a ); -const mx_cell_noise_float = ( texcoord = uv() ) => mx_cell_noise_float$1( texcoord.convert( 'vec2|vec3' ) ); + } -const mx_fractal_noise_float = ( position = uv(), octaves = 3, lacunarity = 2, diminish = .5, amplitude = 1 ) => mx_fractal_noise_float$1( position, int( octaves ), lacunarity, diminish ).mul( amplitude ); -const mx_fractal_noise_vec2 = ( position = uv(), octaves = 3, lacunarity = 2, diminish = .5, amplitude = 1 ) => mx_fractal_noise_vec2$1( position, int( octaves ), lacunarity, diminish ).mul( amplitude ); -const mx_fractal_noise_vec3 = ( position = uv(), octaves = 3, lacunarity = 2, diminish = .5, amplitude = 1 ) => mx_fractal_noise_vec3$1( position, int( octaves ), lacunarity, diminish ).mul( amplitude ); -const mx_fractal_noise_vec4 = ( position = uv(), octaves = 3, lacunarity = 2, diminish = .5, amplitude = 1 ) => mx_fractal_noise_vec4$1( position, int( octaves ), lacunarity, diminish ).mul( amplitude ); +} const _clearColor = /*@__PURE__*/ new Color4(); @@ -63266,7 +65288,7 @@ class Background extends DataMap { class NodeBuilderState { - constructor( vertexShader, fragmentShader, computeShader, nodeAttributes, bindings, updateNodes, updateBeforeNodes, updateAfterNodes, instanceBindGroups = true, transforms = [] ) { + constructor( vertexShader, fragmentShader, computeShader, nodeAttributes, bindings, updateNodes, updateBeforeNodes, updateAfterNodes, monitor, transforms = [] ) { this.vertexShader = vertexShader; this.fragmentShader = fragmentShader; @@ -63280,7 +65302,7 @@ class NodeBuilderState { this.updateBeforeNodes = updateBeforeNodes; this.updateAfterNodes = updateAfterNodes; - this.instanceBindGroups = instanceBindGroups; + this.monitor = monitor; this.usedTimes = 0; @@ -63292,7 +65314,7 @@ class NodeBuilderState { for ( const instanceGroup of this.bindings ) { - const shared = this.instanceBindGroups && instanceGroup.bindings[ 0 ].groupNode.shared; + const shared = instanceGroup.bindings[ 0 ].groupNode.shared; if ( shared !== true ) { @@ -63502,7 +65524,7 @@ class Nodes extends DataMap { nodeBuilder.updateNodes, nodeBuilder.updateBeforeNodes, nodeBuilder.updateAfterNodes, - nodeBuilder.instanceBindGroups, + nodeBuilder.monitor, nodeBuilder.transforms ); @@ -63538,15 +65560,17 @@ class Nodes extends DataMap { const environmentNode = this.getEnvironmentNode( scene ); const fogNode = this.getFogNode( scene ); - const cacheKey = []; + const values = []; + + if ( lightsNode ) values.push( lightsNode.getCacheKey( true ) ); + if ( environmentNode ) values.push( environmentNode.getCacheKey() ); + if ( fogNode ) values.push( fogNode.getCacheKey() ); - if ( lightsNode ) cacheKey.push( lightsNode.getCacheKey( true ) ); - if ( environmentNode ) cacheKey.push( environmentNode.getCacheKey() ); - if ( fogNode ) cacheKey.push( fogNode.getCacheKey() ); + values.push( this.renderer.shadowMap.enabled ? 1 : 0 ); cacheKeyData = { callId, - cacheKey: cacheKey.join( ',' ) + cacheKey: hashArray( values ) }; this.callHashCache.set( chain, cacheKeyData ); @@ -63584,9 +65608,9 @@ class Nodes extends DataMap { let backgroundNode = null; - if ( background.isCubeTexture === true || ( background.mapping === EquirectangularReflectionMapping || background.mapping === EquirectangularRefractionMapping ) ) { + if ( background.isCubeTexture === true || ( background.mapping === EquirectangularReflectionMapping || background.mapping === EquirectangularRefractionMapping || background.mapping === CubeUVReflectionMapping ) ) { - if ( scene.backgroundBlurriness > 0 ) { + if ( scene.backgroundBlurriness > 0 || background.mapping === CubeUVReflectionMapping ) { backgroundNode = pmremTexture( background, normalWorld ); @@ -63610,7 +65634,7 @@ class Nodes extends DataMap { } else if ( background.isTexture === true ) { - backgroundNode = texture( background, viewportUV.flipY() ).setUpdateMatrix( true ); + backgroundNode = texture( background, screenUV.flipY() ).setUpdateMatrix( true ); } else if ( background.isColor !== true ) { @@ -63646,11 +65670,18 @@ class Nodes extends DataMap { if ( fog.isFogExp2 ) { - fogNode = densityFog( reference( 'color', 'color', fog ), reference( 'density', 'float', fog ) ); + const color = reference( 'color', 'color', fog ).setGroup( renderGroup ); + const density = reference( 'density', 'float', fog ).setGroup( renderGroup ); + + fogNode = densityFog( color, density ); } else if ( fog.isFog ) { - fogNode = rangeFog( reference( 'color', 'color', fog ), reference( 'near', 'float', fog ), reference( 'far', 'float', fog ) ); + const color = reference( 'color', 'color', fog ).setGroup( renderGroup ); + const near = reference( 'near', 'float', fog ).setGroup( renderGroup ); + const far = reference( 'far', 'float', fog ).setGroup( renderGroup ); + + fogNode = rangeFog( color, near, far ); } else { @@ -63751,7 +65782,7 @@ class Nodes extends DataMap { const renderer = this.renderer; const cacheKey = this.getOutputCacheKey(); - const output = texture( outputTexture, viewportUV ).renderOutput( renderer.toneMapping, renderer.currentColorSpace ); + const output = texture( outputTexture, screenUV ).renderOutput( renderer.toneMapping, renderer.currentColorSpace ); outputNodeMap.set( outputTexture, cacheKey ); @@ -63813,6 +65844,15 @@ class Nodes extends DataMap { } + needsRefresh( renderObject ) { + + const nodeFrame = this.getNodeFrameForRender( renderObject ); + const monitor = renderObject.getMonitor(); + + return monitor.needsRefresh( renderObject, nodeFrame ); + + } + dispose() { super.dispose(); @@ -63997,7 +66037,7 @@ const _drawingBufferSize = /*@__PURE__*/ new Vector2(); const _screen = /*@__PURE__*/ new Vector4(); const _frustum = /*@__PURE__*/ new Frustum(); const _projScreenMatrix = /*@__PURE__*/ new Matrix4(); -const _vector3 = /*@__PURE__*/ new Vector3(); +const _vector4 = /*@__PURE__*/ new Vector4(); class Renderer { @@ -64010,6 +66050,8 @@ class Renderer { const { logarithmicDepthBuffer = false, alpha = true, + depth = true, + stencil = false, antialias = false, samples = 0, getFallback = null @@ -64038,15 +66080,17 @@ class Renderer { this.sortObjects = true; - this.depth = true; - this.stencil = false; + this.depth = depth; + this.stencil = stencil; this.clippingPlanes = []; this.info = new Info(); this.nodes = { - library: new NodeLibrary() + library: new NodeLibrary(), + modelViewMatrix: null, + modelNormalViewMatrix: null }; // internals @@ -64373,20 +66417,21 @@ class Renderer { _renderBundle( bundle, sceneRef, lightsNode ) { - const { object, camera, renderList } = bundle; + const { bundleGroup, camera, renderList } = bundle; const renderContext = this._currentRenderContext; // - const renderBundle = this._bundles.get( object, camera ); + const renderBundle = this._bundles.get( bundleGroup, camera ); const renderBundleData = this.backend.get( renderBundle ); if ( renderBundleData.renderContexts === undefined ) renderBundleData.renderContexts = new Set(); // - const renderBundleNeedsUpdate = renderBundleData.renderContexts.has( renderContext ) === false || object.needsUpdate === true; + const needsUpdate = bundleGroup.version !== renderBundleData.version; + const renderBundleNeedsUpdate = renderBundleData.renderContexts.has( renderContext ) === false || needsUpdate; renderBundleData.renderContexts.add( renderContext ); @@ -64394,7 +66439,7 @@ class Renderer { this.backend.beginBundle( renderContext ); - if ( renderBundleData.renderObjects === undefined || object.needsUpdate === true ) { + if ( renderBundleData.renderObjects === undefined || needsUpdate ) { renderBundleData.renderObjects = []; @@ -64412,27 +66457,26 @@ class Renderer { this.backend.finishBundle( renderContext, renderBundle ); - object.needsUpdate = false; + renderBundleData.version = bundleGroup.version; } else { - const renderObjects = renderBundleData.renderObjects; + const { renderObjects } = renderBundleData; for ( let i = 0, l = renderObjects.length; i < l; i ++ ) { const renderObject = renderObjects[ i ]; - this._nodes.updateBefore( renderObject ); + if ( this._nodes.needsRefresh( renderObject ) ) { - // + this._nodes.updateBefore( renderObject ); - renderObject.object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, renderObject.object.matrixWorld ); - renderObject.object.normalMatrix.getNormalMatrix( renderObject.object.modelViewMatrix ); + this._nodes.updateForRender( renderObject ); + this._bindings.updateForRender( renderObject ); - this._nodes.updateForRender( renderObject ); - this._bindings.updateForRender( renderObject ); + this._nodes.updateAfter( renderObject ); - this._nodes.updateAfter( renderObject ); + } } @@ -64678,10 +66722,12 @@ class Renderer { // process render lists - const opaqueObjects = renderList.opaque; - const transparentObjects = renderList.transparent; - const bundles = renderList.bundles; - const lightsNode = renderList.lightsNode; + const { + bundles, + lightsNode, + transparent: transparentObjects, + opaque: opaqueObjects + } = renderList; if ( bundles.length > 0 ) this._renderBundles( bundles, sceneRef, lightsNode ); if ( this.opaque === true && opaqueObjects.length > 0 ) this._renderObjects( opaqueObjects, camera, sceneRef, lightsNode ); @@ -65208,13 +67254,15 @@ class Renderer { } - copyFramebufferToTexture( framebufferTexture ) { + copyFramebufferToTexture( framebufferTexture, rectangle = null ) { const renderContext = this._currentRenderContext; this._textures.updateTexture( framebufferTexture ); - this.backend.copyFramebufferToTexture( framebufferTexture, renderContext ); + rectangle = rectangle === null ? _vector4.set( 0, 0, framebufferTexture.image.width, framebufferTexture.image.height ) : rectangle; + + this.backend.copyFramebufferToTexture( framebufferTexture, renderContext, rectangle ); } @@ -65228,9 +67276,9 @@ class Renderer { } - readRenderTargetPixelsAsync( renderTarget, x, y, width, height, index = 0 ) { + readRenderTargetPixelsAsync( renderTarget, x, y, width, height, index = 0, faceIndex = 0 ) { - return this.backend.copyTextureToBuffer( renderTarget.textures[ index ], x, y, width, height ); + return this.backend.copyTextureToBuffer( renderTarget.textures[ index ], x, y, width, height, faceIndex ); } @@ -65260,16 +67308,15 @@ class Renderer { if ( this.sortObjects === true ) { - _vector3.setFromMatrixPosition( object.matrixWorld ).applyMatrix4( _projScreenMatrix ); + _vector4.setFromMatrixPosition( object.matrixWorld ).applyMatrix4( _projScreenMatrix ); } - const geometry = object.geometry; - const material = object.material; + const { geometry, material } = object; if ( material.visible ) { - renderList.push( object, geometry, material, groupOrder, _vector3.z, null ); + renderList.push( object, geometry, material, groupOrder, _vector4.z, null ); } @@ -65283,14 +67330,13 @@ class Renderer { if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { - const geometry = object.geometry; - const material = object.material; + const { geometry, material } = object; if ( this.sortObjects === true ) { if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); - _vector3 + _vector4 .copy( geometry.boundingSphere.center ) .applyMatrix4( object.matrixWorld ) .applyMatrix4( _projScreenMatrix ); @@ -65308,7 +67354,7 @@ class Renderer { if ( groupMaterial && groupMaterial.visible ) { - renderList.push( object, geometry, groupMaterial, groupOrder, _vector3.z, group ); + renderList.push( object, geometry, groupMaterial, groupOrder, _vector4.z, group ); } @@ -65316,7 +67362,7 @@ class Renderer { } else if ( material.visible ) { - renderList.push( object, geometry, material, groupOrder, _vector3.z, null ); + renderList.push( object, geometry, material, groupOrder, _vector4.z, null ); } @@ -65326,7 +67372,7 @@ class Renderer { } - if ( object.static === true && this.backend.beginBundle !== undefined ) { + if ( object.isBundleGroup === true && this.backend.beginBundle !== undefined ) { const baseRenderList = renderList; @@ -65336,7 +67382,7 @@ class Renderer { renderList.begin(); baseRenderList.pushBundle( { - object, + bundleGroup: object, camera, renderList, } ); @@ -65536,22 +67582,24 @@ class Renderer { _renderObjectDirect( object, material, scene, camera, lightsNode, group, passId ) { const renderObject = this._objects.get( object, material, scene, camera, lightsNode, this._currentRenderContext, passId ); - renderObject.drawRange = group || object.geometry.drawRange; + renderObject.drawRange = object.geometry.drawRange; + renderObject.group = group; // - this._nodes.updateBefore( renderObject ); + const needsRefresh = this._nodes.needsRefresh( renderObject ); - // + if ( needsRefresh ) { - object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); - object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); + this._nodes.updateBefore( renderObject ); - // + this._geometries.updateForRender( renderObject ); + + this._nodes.updateForRender( renderObject ); + this._bindings.updateForRender( renderObject ); + + } - this._nodes.updateForRender( renderObject ); - this._geometries.updateForRender( renderObject ); - this._bindings.updateForRender( renderObject ); this._pipelines.updateForRender( renderObject ); // @@ -65562,11 +67610,13 @@ class Renderer { renderBundleData.renderObjects.push( renderObject ); + renderObject.bundle = this._currentRenderBundle.scene; + } this.backend.draw( renderObject, this.info ); - this._nodes.updateAfter( renderObject ); + if ( needsRefresh ) this._nodes.updateAfter( renderObject ); } @@ -65578,10 +67628,9 @@ class Renderer { this._nodes.updateBefore( renderObject ); - // + this._geometries.updateForRender( renderObject ); this._nodes.updateForRender( renderObject ); - this._geometries.updateForRender( renderObject ); this._bindings.updateForRender( renderObject ); this._pipelines.getForRender( renderObject, this._compilationPromises ); @@ -65604,85 +67653,6 @@ class Renderer { } -class IESSpotLight extends SpotLight { - - constructor( color, intensity, distance, angle, penumbra, decay ) { - - super( color, intensity, distance, angle, penumbra, decay ); - - this.iesMap = null; - - } - - copy( source, recursive ) { - - super.copy( source, recursive ); - - this.iesMap = source.iesMap; - - return this; - - } - -} - -class StandardNodeLibrary extends NodeLibrary { - - constructor() { - - super(); - - this.addMaterial( MeshPhongNodeMaterial, MeshPhongMaterial ); - this.addMaterial( MeshStandardNodeMaterial, MeshStandardMaterial ); - this.addMaterial( MeshPhysicalNodeMaterial, MeshPhysicalMaterial ); - this.addMaterial( MeshToonNodeMaterial, MeshToonMaterial ); - this.addMaterial( MeshBasicNodeMaterial, MeshBasicMaterial ); - this.addMaterial( MeshLambertNodeMaterial, MeshLambertMaterial ); - this.addMaterial( MeshNormalNodeMaterial, MeshNormalMaterial ); - this.addMaterial( MeshMatcapNodeMaterial, MeshMatcapMaterial ); - this.addMaterial( LineBasicNodeMaterial, LineBasicMaterial ); - this.addMaterial( LineDashedNodeMaterial, LineDashedMaterial ); - this.addMaterial( PointsNodeMaterial, PointsMaterial ); - this.addMaterial( SpriteNodeMaterial, SpriteMaterial ); - this.addMaterial( ShadowNodeMaterial, ShadowMaterial ); - - this.addLight( PointLightNode, PointLight ); - this.addLight( DirectionalLightNode, DirectionalLight ); - this.addLight( RectAreaLightNode, RectAreaLight ); - this.addLight( SpotLightNode, SpotLight ); - this.addLight( AmbientLightNode, AmbientLight ); - this.addLight( HemisphereLightNode, HemisphereLight ); - this.addLight( LightProbeNode, LightProbe ); - this.addLight( IESSpotLightNode, IESSpotLight ); - - this.addToneMapping( LinearToneMapping, LinearToneMapping$1 ); - this.addToneMapping( ReinhardToneMapping, ReinhardToneMapping$1 ); - this.addToneMapping( CineonToneMapping, CineonToneMapping$1 ); - this.addToneMapping( ACESFilmicToneMapping, ACESFilmicToneMapping$1 ); - this.addToneMapping( AgXToneMapping, AgXToneMapping$1 ); - this.addToneMapping( NeutralToneMapping, NeutralToneMapping$1 ); - - this.addColorSpace( LinearTosRGB, getColorSpaceMethod( LinearSRGBColorSpace, SRGBColorSpace ) ); - this.addColorSpace( sRGBToLinear, getColorSpaceMethod( SRGBColorSpace, LinearSRGBColorSpace ) ); - - } - -} - -class StandardRenderer extends Renderer { - - constructor( backend, parameters = {} ) { - - super( backend, parameters ); - - this.isStandardRenderer = true; - - this.nodes.library = new StandardNodeLibrary(); - - } - -} - class Binding { constructor( name = '' ) { @@ -66314,8 +68284,6 @@ class GLSLNodeBuilder extends NodeBuilder { this.transforms = []; this.extensions = {}; - this.instanceBindGroups = false; - this.useComparisonMethod = true; } @@ -66492,7 +68460,7 @@ ${ flowData.code } this.getVarFromNode( node, propertySizeName, 'uint' ); - this.addLineFlowCode( `${ propertySizeName } = uint( textureSize( ${ textureName }, 0 ).x )` ); + this.addLineFlowCode( `${ propertySizeName } = uint( textureSize( ${ textureName }, 0 ).x )`, storageArrayElementNode ); bufferNodeData.propertySizeName = propertySizeName; @@ -66522,7 +68490,7 @@ ${ flowData.code } } - this.addLineFlowCode( `${ propertyName } = ${prefix}(${ snippet })${channel}` ); + this.addLineFlowCode( `${ propertyName } = ${prefix}(${ snippet })${channel}`, storageArrayElementNode ); elementNodeData.propertyName = propertyName; @@ -67112,6 +69080,8 @@ void main() { const shadersData = this.material !== null ? { fragment: {}, vertex: {} } : { compute: {} }; + this.sortBindingGroups(); + for ( const shaderStage in shadersData ) { let flow = '// code\n\n'; @@ -67684,10 +69654,16 @@ class WebGLAttributeUtils { const dstBuffer = new attribute.array.constructor( array.length ); + // Ensure the buffer is bound before reading + gl.bindBuffer( gl.COPY_WRITE_BUFFER, writeBuffer ); + gl.getBufferSubData( gl.COPY_WRITE_BUFFER, 0, dstBuffer ); gl.deleteBuffer( writeBuffer ); + gl.bindBuffer( gl.COPY_READ_BUFFER, null ); + gl.bindBuffer( gl.COPY_WRITE_BUFFER, null ); + return dstBuffer.buffer; } @@ -68211,7 +70187,7 @@ class WebGLState { this.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); - material.alphaToCoverage === true + material.alphaToCoverage === true && this.backend.renderer.samples > 1 ? this.enable( gl.SAMPLE_ALPHA_TO_COVERAGE ) : this.disable( gl.SAMPLE_ALPHA_TO_COVERAGE ); @@ -68348,7 +70324,6 @@ class WebGLState { } - } @@ -68410,10 +70385,8 @@ class WebGLState { boundTexture.type = webglType; boundTexture.texture = webglTexture; - } - } bindBufferBase( target, index, buffer ) { @@ -69412,20 +71385,22 @@ class WebGLTextureUtils { } - copyFramebufferToTexture( texture, renderContext ) { + copyFramebufferToTexture( texture, renderContext, rectangle ) { const { gl } = this; const { state } = this.backend; const { textureGPU } = this.backend.get( texture ); - const width = texture.image.width; - const height = texture.image.height; + const { x, y, z: width, w: height } = rectangle; const requireDrawFrameBuffer = texture.isDepthTexture === true || ( renderContext.renderTarget && renderContext.renderTarget.samples > 0 ); + const srcHeight = renderContext.renderTarget ? renderContext.renderTarget.height : this.backend.gerDrawingBufferSize().y; + if ( requireDrawFrameBuffer ) { + const partial = ( x !== 0 || y !== 0 ); let mask; let attachment; @@ -69447,19 +71422,45 @@ class WebGLTextureUtils { } - const fb = gl.createFramebuffer(); - state.bindFramebuffer( gl.DRAW_FRAMEBUFFER, fb ); + if ( partial ) { + + const renderTargetContextData = this.backend.get( renderContext.renderTarget ); + + const fb = renderTargetContextData.framebuffers[ renderContext.getCacheKey() ]; + const msaaFrameBuffer = renderTargetContextData.msaaFrameBuffer; + + state.bindFramebuffer( gl.DRAW_FRAMEBUFFER, fb ); + state.bindFramebuffer( gl.READ_FRAMEBUFFER, msaaFrameBuffer ); + + const flippedY = srcHeight - y - height; - gl.framebufferTexture2D( gl.DRAW_FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureGPU, 0 ); + gl.blitFramebuffer( x, flippedY, x + width, flippedY + height, x, flippedY, x + width, flippedY + height, mask, gl.NEAREST ); - gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, gl.NEAREST ); + state.bindFramebuffer( gl.READ_FRAMEBUFFER, fb ); - gl.deleteFramebuffer( fb ); + state.bindTexture( gl.TEXTURE_2D, textureGPU ); + + gl.copyTexSubImage2D( gl.TEXTURE_2D, 0, 0, 0, x, flippedY, width, height ); + + state.unbindTexture(); + + } else { + + const fb = gl.createFramebuffer(); + + state.bindFramebuffer( gl.DRAW_FRAMEBUFFER, fb ); + + gl.framebufferTexture2D( gl.DRAW_FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureGPU, 0 ); + gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, gl.NEAREST ); + + gl.deleteFramebuffer( fb ); + + } } else { state.bindTexture( gl.TEXTURE_2D, textureGPU ); - gl.copyTexSubImage2D( gl.TEXTURE_2D, 0, 0, 0, 0, 0, width, height ); + gl.copyTexSubImage2D( gl.TEXTURE_2D, 0, 0, 0, x, srcHeight - height - y, width, height ); state.unbindTexture(); @@ -69526,7 +71527,7 @@ class WebGLTextureUtils { } - async copyTextureToBuffer( texture, x, y, width, height ) { + async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { const { backend, gl } = this; @@ -69535,10 +71536,13 @@ class WebGLTextureUtils { const fb = gl.createFramebuffer(); gl.bindFramebuffer( gl.READ_FRAMEBUFFER, fb ); - gl.framebufferTexture2D( gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, textureGPU, 0 ); + + const target = texture.isCubeTexture ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex : gl.TEXTURE_2D; + + gl.framebufferTexture2D( gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, target, textureGPU, 0 ); const typedArrayType = this._getTypedArrayType( glType ); - const bytesPerTexel = this._getBytesPerTexel( glFormat ); + const bytesPerTexel = this._getBytesPerTexel( glType, glFormat ); const elementCount = width * height; const byteLength = elementCount * bytesPerTexel; @@ -69576,19 +71580,33 @@ class WebGLTextureUtils { if ( glType === gl.UNSIGNED_SHORT ) return Uint16Array; if ( glType === gl.UNSIGNED_INT ) return Uint32Array; + if ( glType === gl.HALF_FLOAT ) return Uint16Array; if ( glType === gl.FLOAT ) return Float32Array; throw new Error( `Unsupported WebGL type: ${glType}` ); } - _getBytesPerTexel( glFormat ) { + _getBytesPerTexel( glType, glFormat ) { const { gl } = this; - if ( glFormat === gl.RGBA ) return 4; - if ( glFormat === gl.RGB ) return 3; - if ( glFormat === gl.ALPHA ) return 1; + let bytesPerComponent = 0; + + if ( glType === gl.UNSIGNED_BYTE ) bytesPerComponent = 1; + + if ( glType === gl.UNSIGNED_SHORT_4_4_4_4 || + glType === gl.UNSIGNED_SHORT_5_5_5_1 || + glType === gl.UNSIGNED_SHORT_5_6_5 || + glType === gl.UNSIGNED_SHORT || + glType === gl.HALF_FLOAT ) bytesPerComponent = 2; + + if ( glType === gl.UNSIGNED_INT || + glType === gl.FLOAT ) bytesPerComponent = 4; + + if ( glFormat === gl.RGBA ) return bytesPerComponent * 4; + if ( glFormat === gl.RGB ) return bytesPerComponent * 3; + if ( glFormat === gl.ALPHA ) return bytesPerComponent; } @@ -69871,6 +71889,7 @@ class WebGLBackend extends Backend { this.disjoint = this.extensions.get( 'EXT_disjoint_timer_query_webgl2' ); this.parallel = this.extensions.get( 'KHR_parallel_shader_compile' ); + this._currentContext = null; } @@ -70406,6 +72425,10 @@ class WebGLBackend extends Backend { const contextData = this.get( context ); + const drawParms = renderObject.getDrawParameters(); + + if ( drawParms === null ) return; + // this._bindUniforms( renderObject.getBindings() ); @@ -70444,10 +72467,6 @@ class WebGLBackend extends Backend { const index = renderObject.getIndex(); - const geometry = renderObject.geometry; - const drawRange = renderObject.drawRange; - const firstVertex = drawRange.start; - // const lastObject = contextData.lastOcclusionObject; @@ -70478,7 +72497,6 @@ class WebGLBackend extends Backend { } // - const renderer = this.bufferRenderer; if ( object.isPoints ) renderer.mode = gl.POINTS; @@ -70502,33 +72520,26 @@ class WebGLBackend extends Backend { // - - let count; + const { vertexCount, instanceCount } = drawParms; + let { firstVertex } = drawParms; renderer.object = object; if ( index !== null ) { + firstVertex *= index.array.BYTES_PER_ELEMENT; + const indexData = this.get( index ); - const indexCount = ( drawRange.count !== Infinity ) ? drawRange.count : index.count; renderer.index = index.count; renderer.type = indexData.type; - count = indexCount; - } else { renderer.index = 0; - const vertexCount = ( drawRange.count !== Infinity ) ? drawRange.count : geometry.attributes.position.count; - - count = vertexCount; - } - const instanceCount = this.getInstanceCount( renderObject ); - if ( object.isBatchedMesh ) { if ( object._multiDrawInstances !== null ) { @@ -70547,11 +72558,11 @@ class WebGLBackend extends Backend { } else if ( instanceCount > 1 ) { - renderer.renderInstances( firstVertex, count, instanceCount ); + renderer.renderInstances( firstVertex, vertexCount, instanceCount ); } else { - renderer.render( firstVertex, count ); + renderer.render( firstVertex, vertexCount ); } // @@ -70605,9 +72616,9 @@ class WebGLBackend extends Backend { } - copyTextureToBuffer( texture, x, y, width, height ) { + copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { - return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height ); + return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height, faceIndex ); } @@ -70923,40 +72934,52 @@ class WebGLBackend extends Backend { updateBindings( bindGroup, bindings ) { - const { state, gl } = this; + if ( ! bindGroup ) return; - let groupIndex = 0; - let textureIndex = 0; + const { gl } = this; - for ( const bindGroup of bindings ) { + const bindingsData = this.get( bindings ); + const bindGroupData = this.get( bindGroup ); - for ( const binding of bindGroup.bindings ) { + if ( bindingsData.textureIndex === undefined ) bindingsData.textureIndex = 0; - if ( binding.isUniformsGroup || binding.isUniformBuffer ) { + if ( bindGroupData.textureIndex === undefined ) { - const bufferGPU = gl.createBuffer(); - const data = binding.buffer; + bindGroupData.textureIndex = bindingsData.textureIndex; - gl.bindBuffer( gl.UNIFORM_BUFFER, bufferGPU ); - gl.bufferData( gl.UNIFORM_BUFFER, data, gl.DYNAMIC_DRAW ); - state.bindBufferBase( gl.UNIFORM_BUFFER, groupIndex, bufferGPU ); + } else { - this.set( binding, { - index: groupIndex ++, - bufferGPU - } ); + // reset textureIndex to match previous mappimgs when rebuilt + bindingsData.textureIndex = bindGroupData.textureIndex; - } else if ( binding.isSampledTexture ) { + } - const { textureGPU, glTextureType } = this.get( binding.texture ); + let i = 0; - this.set( binding, { - index: textureIndex ++, - textureGPU, - glTextureType - } ); + for ( const binding of bindGroup.bindings ) { - } + if ( binding.isUniformsGroup || binding.isUniformBuffer ) { + + const data = binding.buffer; + const bufferGPU = gl.createBuffer(); + + gl.bindBuffer( gl.UNIFORM_BUFFER, bufferGPU ); + gl.bufferData( gl.UNIFORM_BUFFER, data, gl.DYNAMIC_DRAW ); + + this.set( binding, { + index: bindGroup.index * 2 + i ++, + bufferGPU + } ); + + } else if ( binding.isSampledTexture ) { + + const { textureGPU, glTextureType } = this.get( binding.texture ); + + this.set( binding, { + index: bindingsData.textureIndex ++, + textureGPU, + glTextureType + } ); } @@ -71057,9 +73080,9 @@ class WebGLBackend extends Backend { } - copyFramebufferToTexture( texture, renderContext ) { + copyFramebufferToTexture( texture, renderContext, rectangle ) { - this.textureUtils.copyFramebufferToTexture( texture, renderContext ); + this.textureUtils.copyFramebufferToTexture( texture, renderContext, rectangle ); } @@ -71932,6 +73955,8 @@ class WebGPUTextureUtils { const dimension = this._getDimension( texture ); const format = texture.internalFormat || options.format || getFormat( texture, backend.device ); + textureData.format = format; + let sampleCount = options.sampleCount !== undefined ? options.sampleCount : 1; sampleCount = backend.utils.getSampleCount( sampleCount ); @@ -72179,7 +74204,7 @@ class WebGPUTextureUtils { } - async copyTextureToBuffer( texture, x, y, width, height ) { + async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { const device = this.backend.device; @@ -72203,7 +74228,7 @@ class WebGPUTextureUtils { encoder.copyTextureToBuffer( { texture: textureGPU, - origin: { x, y }, + origin: { x, y, z: faceIndex }, }, { buffer: readBuffer, @@ -72602,9 +74627,9 @@ class WebGPUTextureUtils { if ( format === GPUTextureFormat.RG16Sint ) return Int16Array; if ( format === GPUTextureFormat.RGBA16Uint ) return Uint16Array; if ( format === GPUTextureFormat.RGBA16Sint ) return Int16Array; - if ( format === GPUTextureFormat.R16Float ) return Float32Array; - if ( format === GPUTextureFormat.RG16Float ) return Float32Array; - if ( format === GPUTextureFormat.RGBA16Float ) return Float32Array; + if ( format === GPUTextureFormat.R16Float ) return Uint16Array; + if ( format === GPUTextureFormat.RG16Float ) return Uint16Array; + if ( format === GPUTextureFormat.RGBA16Float ) return Uint16Array; if ( format === GPUTextureFormat.R32Uint ) return Uint32Array; @@ -73256,7 +75281,8 @@ fn tsl_repeatWrapping( uv : vec2, dimension : vec2 ) -> vec2 { biquadraticTexture: new CodeNode( ` fn tsl_biquadraticTexture( map : texture_2d, coord : vec2f, level : i32 ) -> vec4f { - let res = vec2f( textureDimensions( map, level ) ); + let iRes = vec2i( textureDimensions( map, level ) ); + let res = vec2f( iRes ); let uvScaled = coord * res; let uvWrapping = ( ( uvScaled % res ) + res ) % res; @@ -73267,10 +75293,10 @@ fn tsl_biquadraticTexture( map : texture_2d, coord : vec2f, level : i32 ) - let iuv = floor( uv ); let f = fract( uv ); - let rg1 = textureLoad( map, vec2i( iuv + vec2( 0.5, 0.5 ) ), level ); - let rg2 = textureLoad( map, vec2i( iuv + vec2( 1.5, 0.5 ) ), level ); - let rg3 = textureLoad( map, vec2i( iuv + vec2( 0.5, 1.5 ) ), level ); - let rg4 = textureLoad( map, vec2i( iuv + vec2( 1.5, 1.5 ) ), level ); + let rg1 = textureLoad( map, vec2i( iuv + vec2( 0.5, 0.5 ) ) % iRes, level ); + let rg2 = textureLoad( map, vec2i( iuv + vec2( 1.5, 0.5 ) ) % iRes, level ); + let rg3 = textureLoad( map, vec2i( iuv + vec2( 0.5, 1.5 ) ) % iRes, level ); + let rg4 = textureLoad( map, vec2i( iuv + vec2( 1.5, 1.5 ) ) % iRes, level ); return mix( mix( rg1, rg2, f.x ), mix( rg3, rg4, f.x ), f.y ); @@ -73311,6 +75337,16 @@ if ( /Windows/g.test( navigator.userAgent ) ) { // +let diagnostics = ''; + +if ( /Firefox/g.test( navigator.userAgent ) !== true ) { + + diagnostics += 'diagnostic( off, derivative_uniformity );\n'; + +} + +// + class WGSLNodeBuilder extends NodeBuilder { constructor( object, renderer ) { @@ -73323,6 +75359,8 @@ class WGSLNodeBuilder extends NodeBuilder { this.directives = {}; + this.scopedArrays = new Map(); + } needsToWorkingColorSpace( texture ) { @@ -73733,6 +75771,12 @@ class WGSLNodeBuilder extends NodeBuilder { } + hasBuiltin( name, shaderStage = this.shaderStage ) { + + return ( this.builtins[ shaderStage ] !== undefined && this.builtins[ shaderStage ].has( name ) ); + + } + getVertexIndex() { if ( this.shaderStage === 'vertex' ) { @@ -73805,11 +75849,19 @@ ${ flowData.code } } + getInvocationSubgroupIndex() { + + this.enableSubGroups(); + + return this.getBuiltin( 'subgroup_invocation_id', 'invocationSubgroupIndex', 'u32', 'attribute' ); + + } + getSubgroupIndex() { this.enableSubGroups(); - return this.getBuiltin( 'subgroup_invocation_id', 'subgroupIndex', 'u32', 'attribute' ); + return this.getBuiltin( 'subgroup_id', 'subgroupIndex', 'u32', 'attribute' ); } @@ -73918,6 +75970,45 @@ ${ flowData.code } } + getScopedArray( name, scope, bufferType, bufferCount ) { + + if ( this.scopedArrays.has( name ) === false ) { + + this.scopedArrays.set( name, { + name, + scope, + bufferType, + bufferCount + } ); + + } + + return name; + + } + + getScopedArrays( shaderStage ) { + + if ( shaderStage !== 'compute' ) { + + return; + + } + + const snippets = []; + + for ( const { name, scope, bufferType, bufferCount } of this.scopedArrays.values() ) { + + const type = this.getType( bufferType ); + + snippets.push( `var<${scope}> ${name}: array< ${type}, ${bufferCount} >;` ); + + } + + return snippets.join( '\n' ); + + } + getAttributes( shaderStage ) { const snippets = []; @@ -73929,6 +76020,13 @@ ${ flowData.code } this.getBuiltin( 'local_invocation_id', 'localId', 'vec3', 'attribute' ); this.getBuiltin( 'num_workgroups', 'numWorkgroups', 'vec3', 'attribute' ); + if ( this.renderer.hasFeature( 'subgroups' ) ) { + + this.enableDirective( 'subgroups', shaderStage ); + this.getBuiltin( 'subgroup_size', 'subgroupSize', 'u32', 'attribute' ); + + } + } if ( shaderStage === 'vertex' || shaderStage === 'compute' ) { @@ -74088,8 +76186,8 @@ ${ flowData.code } for ( const uniform of uniforms ) { - const groundName = uniform.groupNode.name; - const uniformIndexes = this.bindingsIndexes[ groundName ]; + const groupName = uniform.groupNode.name; + const uniformIndexes = this.bindingsIndexes[ groupName ]; if ( uniform.type === 'texture' || uniform.type === 'cubeTexture' || uniform.type === 'storageTexture' || uniform.type === 'texture3D' ) { @@ -74163,7 +76261,8 @@ ${ flowData.code } const bufferCount = bufferNode.bufferCount; const bufferCountSnippet = bufferCount > 0 ? ', ' + bufferCount : ''; - const bufferSnippet = `\t${ uniform.name } : array< ${ bufferType }${ bufferCountSnippet } >\n`; + const bufferTypeSnippet = bufferNode.isAtomic ? `atomic<${bufferType}>` : `${bufferType}`; + const bufferSnippet = `\t${ uniform.name } : array< ${ bufferTypeSnippet }${ bufferCountSnippet } >\n`; const bufferAccessMode = bufferNode.isStorageBufferNode ? `storage, ${ this.getStorageAccess( bufferNode ) }` : 'uniform'; bufferSnippets.push( this._getWGSLStructBinding( 'NodeBuffer_' + bufferNode.id, bufferSnippet, bufferAccessMode, uniformIndexes.binding ++, uniformIndexes.group ) ); @@ -74205,6 +76304,8 @@ ${ flowData.code } const shadersData = this.material !== null ? { fragment: {}, vertex: {} } : { compute: {} }; + this.sortBindingGroups(); + for ( const shaderStage in shadersData ) { const stageData = shadersData[ shaderStage ]; @@ -74215,6 +76316,7 @@ ${ flowData.code } stageData.vars = this.getVars( shaderStage ); stageData.codes = this.getCodes( shaderStage ); stageData.directives = this.getDirectives( shaderStage ); + stageData.scopedArrays = this.getScopedArrays( shaderStage ); // @@ -74406,8 +76508,8 @@ fn main( ${shaderData.attributes} ) -> VaryingsStruct { _getWGSLFragmentCode( shaderData ) { return `${ this.getSignature() } - -diagnostic( off, derivative_uniformity ); +// global +${ diagnostics } // uniforms ${shaderData.uniforms} @@ -74441,6 +76543,9 @@ ${shaderData.directives} // system var instanceIndex : u32; +// locals +${shaderData.scopedArrays} + // uniforms ${shaderData.uniforms} @@ -74518,7 +76623,7 @@ class WebGPUUtils { getTextureFormatGPU( texture ) { - return this.backend.get( texture ).texture.format; + return this.backend.get( texture ).format; } @@ -74836,22 +76941,12 @@ class WebGPUAttributeUtils { const bufferGPU = data.buffer; const size = bufferGPU.size; - let readBufferGPU = data.readBuffer; - let needsUnmap = true; - - if ( readBufferGPU === undefined ) { - - readBufferGPU = device.createBuffer( { - label: attribute.name, - size, - usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ - } ); - - needsUnmap = false; - - data.readBuffer = readBufferGPU; + const readBufferGPU = device.createBuffer( { + label: attribute.name, + size, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ + } ); - } const cmdEncoder = device.createCommandEncoder( {} ); @@ -74863,7 +76958,7 @@ class WebGPUAttributeUtils { size ); - if ( needsUnmap ) readBufferGPU.unmap(); + readBufferGPU.unmap(); const gpuCommands = cmdEncoder.finish(); device.queue.submit( [ gpuCommands ] ); @@ -75345,7 +77440,7 @@ class WebGPUPipelineUtils { }, multisample: { count: sampleCount, - alphaToCoverageEnabled: material.alphaToCoverage + alphaToCoverageEnabled: material.alphaToCoverage && sampleCount > 1 }, layout: device.createPipelineLayout( { bindGroupLayouts @@ -76251,7 +78346,7 @@ class WebGPUBackend extends Backend { renderContextData.descriptor = descriptor; renderContextData.encoder = encoder; renderContextData.currentPass = currentPass; - renderContextData.currentSets = { attributes: {}, pipeline: null, index: null }; + renderContextData.currentSets = { attributes: {}, bindingGroups: [], pipeline: null, index: null }; renderContextData.renderBundles = []; // @@ -76655,13 +78750,17 @@ class WebGPUBackend extends Backend { draw( renderObject, info ) { - const { object, geometry, context, pipeline } = renderObject; + const { object, context, pipeline } = renderObject; const bindings = renderObject.getBindings(); const renderContextData = this.get( context ); const pipelineGPU = this.get( pipeline ).pipeline; const currentSets = renderContextData.currentSets; const passEncoderGPU = renderContextData.currentPass; + const drawParms = renderObject.getDrawParameters(); + + if ( drawParms === null ) return; + // pipeline if ( currentSets.pipeline !== pipelineGPU ) { @@ -76674,12 +78773,19 @@ class WebGPUBackend extends Backend { // bind groups + const currentBindingGroups = currentSets.bindingGroups; + for ( let i = 0, l = bindings.length; i < l; i ++ ) { const bindGroup = bindings[ i ]; const bindingsData = this.get( bindGroup ); - passEncoderGPU.setBindGroup( bindGroup.index, bindingsData.group ); + if ( currentBindingGroups[ bindGroup.index ] !== bindGroup.id ) { + + passEncoderGPU.setBindGroup( bindGroup.index, bindingsData.group ); + currentBindingGroups[ bindGroup.index ] = bindGroup.id; + + } } @@ -76755,12 +78861,6 @@ class WebGPUBackend extends Backend { // draw - const drawRange = renderObject.drawRange; - const firstVertex = drawRange.start; - - const instanceCount = this.getInstanceCount( renderObject ); - if ( instanceCount === 0 ) return; - if ( object.isBatchedMesh === true ) { const starts = object._multiDrawStarts; @@ -76781,16 +78881,15 @@ class WebGPUBackend extends Backend { } else if ( hasIndex === true ) { - const indexCount = ( drawRange.count !== Infinity ) ? drawRange.count : index.count; + const { vertexCount: indexCount, instanceCount, firstVertex: firstIndex } = drawParms; - passEncoderGPU.drawIndexed( indexCount, instanceCount, firstVertex, 0, 0 ); + passEncoderGPU.drawIndexed( indexCount, instanceCount, firstIndex, 0, 0 ); info.update( object, indexCount, instanceCount ); } else { - const positionAttribute = geometry.attributes.position; - const vertexCount = ( drawRange.count !== Infinity ) ? drawRange.count : positionAttribute.count; + const { vertexCount, instanceCount, firstVertex } = drawParms; passEncoderGPU.draw( vertexCount, instanceCount, firstVertex, 0 ); @@ -76883,7 +78982,6 @@ class WebGPUBackend extends Backend { } - // textures createSampler( texture ) { @@ -76928,9 +79026,9 @@ class WebGPUBackend extends Backend { } - copyTextureToBuffer( texture, x, y, width, height ) { + copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { - return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height ); + return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height, faceIndex ); } @@ -77079,7 +79177,7 @@ class WebGPUBackend extends Backend { renderContextData._currentPass = renderContextData.currentPass; renderContextData._currentSets = renderContextData.currentSets; - renderContextData.currentSets = { attributes: {}, pipeline: null, index: null }; + renderContextData.currentSets = { attributes: {}, bindingGroups: [], pipeline: null, index: null }; renderContextData.currentPass = this.pipelineUtils.createBundleEncoder( renderContext ); } @@ -77187,9 +79285,11 @@ class WebGPUBackend extends Backend { let dstX = 0; let dstY = 0; + let dstLayer = 0; let srcX = 0; let srcY = 0; + let srcLayer = 0; let srcWidth = srcTexture.image.width; let srcHeight = srcTexture.image.height; @@ -77198,6 +79298,7 @@ class WebGPUBackend extends Backend { srcX = srcRegion.x; srcY = srcRegion.y; + srcLayer = srcRegion.z || 0; srcWidth = srcRegion.width; srcHeight = srcRegion.height; @@ -77207,6 +79308,7 @@ class WebGPUBackend extends Backend { dstX = dstPosition.x; dstY = dstPosition.y; + dstLayer = dstPosition.z || 0; } @@ -77219,16 +79321,17 @@ class WebGPUBackend extends Backend { { texture: sourceGPU, mipLevel: level, - origin: { x: srcX, y: srcY, z: 0 } + origin: { x: srcX, y: srcY, z: srcLayer } }, { texture: destinationGPU, mipLevel: level, - origin: { x: dstX, y: dstY, z: 0 } + origin: { x: dstX, y: dstY, z: dstLayer } }, [ srcWidth, - srcHeight + srcHeight, + 1 ] ); @@ -77236,7 +79339,7 @@ class WebGPUBackend extends Backend { } - copyFramebufferToTexture( texture, renderContext ) { + copyFramebufferToTexture( texture, renderContext, rectangle ) { const renderContextData = this.get( renderContext ); @@ -77285,14 +79388,14 @@ class WebGPUBackend extends Backend { encoder.copyTextureToTexture( { texture: sourceGPU, - origin: { x: 0, y: 0, z: 0 } + origin: { x: rectangle.x, y: rectangle.y, z: 0 } }, { texture: destinationGPU }, [ - texture.image.width, - texture.image.height + rectangle.z, + rectangle.w ] ); @@ -77308,7 +79411,72 @@ class WebGPUBackend extends Backend { if ( renderContext.stencil ) descriptor.depthStencilAttachment.stencilLoadOp = GPULoadOp.Load; renderContextData.currentPass = encoder.beginRenderPass( descriptor ); - renderContextData.currentSets = { attributes: {}, pipeline: null, index: null }; + renderContextData.currentSets = { attributes: {}, bindingGroups: [], pipeline: null, index: null }; + + } + +} + +class IESSpotLight extends SpotLight { + + constructor( color, intensity, distance, angle, penumbra, decay ) { + + super( color, intensity, distance, angle, penumbra, decay ); + + this.iesMap = null; + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + this.iesMap = source.iesMap; + + return this; + + } + +} + +class StandardNodeLibrary extends NodeLibrary { + + constructor() { + + super(); + + this.addMaterial( MeshPhongNodeMaterial, MeshPhongMaterial ); + this.addMaterial( MeshStandardNodeMaterial, MeshStandardMaterial ); + this.addMaterial( MeshPhysicalNodeMaterial, MeshPhysicalMaterial ); + this.addMaterial( MeshToonNodeMaterial, MeshToonMaterial ); + this.addMaterial( MeshBasicNodeMaterial, MeshBasicMaterial ); + this.addMaterial( MeshLambertNodeMaterial, MeshLambertMaterial ); + this.addMaterial( MeshNormalNodeMaterial, MeshNormalMaterial ); + this.addMaterial( MeshMatcapNodeMaterial, MeshMatcapMaterial ); + this.addMaterial( LineBasicNodeMaterial, LineBasicMaterial ); + this.addMaterial( LineDashedNodeMaterial, LineDashedMaterial ); + this.addMaterial( PointsNodeMaterial, PointsMaterial ); + this.addMaterial( SpriteNodeMaterial, SpriteMaterial ); + this.addMaterial( ShadowNodeMaterial, ShadowMaterial ); + + this.addLight( PointLightNode, PointLight ); + this.addLight( DirectionalLightNode, DirectionalLight ); + this.addLight( RectAreaLightNode, RectAreaLight ); + this.addLight( SpotLightNode, SpotLight ); + this.addLight( AmbientLightNode, AmbientLight ); + this.addLight( HemisphereLightNode, HemisphereLight ); + this.addLight( LightProbeNode, LightProbe ); + this.addLight( IESSpotLightNode, IESSpotLight ); + + this.addToneMapping( linearToneMapping, LinearToneMapping ); + this.addToneMapping( reinhardToneMapping, ReinhardToneMapping ); + this.addToneMapping( cineonToneMapping, CineonToneMapping ); + this.addToneMapping( acesFilmicToneMapping, ACESFilmicToneMapping ); + this.addToneMapping( agxToneMapping, AgXToneMapping ); + this.addToneMapping( neutralToneMapping, NeutralToneMapping ); + + this.addColorSpace( linearSRGBTosRGB, getColorSpaceMethod( LinearSRGBColorSpace, SRGBColorSpace ) ); + this.addColorSpace( sRGBToLinearSRGB, getColorSpaceMethod( SRGBColorSpace, LinearSRGBColorSpace ) ); } @@ -77328,7 +79496,7 @@ const debugHandler = { }; */ -class WebGPURenderer extends StandardRenderer { +class WebGPURenderer extends Renderer { constructor( parameters = {} ) { @@ -77357,12 +79525,37 @@ class WebGPURenderer extends StandardRenderer { //super( new Proxy( backend, debugHandler ) ); super( backend, parameters ); + this.nodes.library = new StandardNodeLibrary(); + this.isWebGPURenderer = true; } } +class BundleGroup extends Group { + + constructor() { + + super(); + + this.isBundleGroup = true; + + this.type = 'BundleGroup'; + + this.static = true; + this.version = 0; + + } + + set needsUpdate( value ) { + + if ( value === true ) this.version ++; + + } + +} + const _material = /*@__PURE__*/ new NodeMaterial(); const _quadMesh = /*@__PURE__*/ new QuadMesh( _material ); @@ -77499,6 +79692,7 @@ class NodeLoader extends Loader { super( manager ); this.textures = {}; + this.nodes = {}; } @@ -77544,7 +79738,7 @@ class NodeLoader extends Loader { const { uuid, type } = nodeJSON; - nodes[ uuid ] = nodeObject( createNodeFromType( type ) ); + nodes[ uuid ] = this.createNodeFromType( type ); nodes[ uuid ].uuid = uuid; } @@ -77570,7 +79764,7 @@ class NodeLoader extends Loader { parse( json ) { - const node = nodeObject( createNodeFromType( json.type ) ); + const node = this.createNodeFromType( json.type ); node.uuid = json.uuid; const nodes = this.parseNodes( json.nodes ); @@ -77593,23 +79787,27 @@ class NodeLoader extends Loader { } -} + setNodes( value ) { -const superFromTypeFunction = MaterialLoader.createMaterialFromType; + this.nodes = value; + return this; -MaterialLoader.createMaterialFromType = function ( type ) { + } - const material = createNodeMaterialFromType( type ); + createNodeFromType( type ) { - if ( material !== undefined ) { + if ( this.nodes[ type ] === undefined ) { - return material; + console.error( 'THREE.NodeLoader: Node type not found:', type ); + return float(); - } + } - return superFromTypeFunction.call( this, type ); + return nodeObject( new this.nodes[ type ]() ); -}; + } + +} class NodeMaterialLoader extends MaterialLoader { @@ -77618,6 +79816,7 @@ class NodeMaterialLoader extends MaterialLoader { super( manager ); this.nodes = {}; + this.nodeMaterials = {}; } @@ -77643,11 +79842,31 @@ class NodeMaterialLoader extends MaterialLoader { setNodes( value ) { this.nodes = value; + return this; + + } + setNodeMaterials( value ) { + + this.nodeMaterials = value; return this; } + createMaterialFromType( type ) { + + const materialClass = this.nodeMaterials[ type ]; + + if ( materialClass !== undefined ) { + + return new materialClass(); + + } + + return super.createMaterialFromType( type ); + + } + } class NodeObjectLoader extends ObjectLoader { @@ -77656,10 +79875,27 @@ class NodeObjectLoader extends ObjectLoader { super( manager ); + this.nodes = {}; + this.nodeMaterials = {}; + this._nodesJSON = null; } + setNodes( value ) { + + this.nodes = value; + return this; + + } + + setNodeMaterials( value ) { + + this.nodeMaterials = value; + return this; + + } + parse( json, onLoad ) { this._nodesJSON = json.nodes; @@ -77677,6 +79913,7 @@ class NodeObjectLoader extends ObjectLoader { if ( json !== undefined ) { const loader = new NodeLoader(); + loader.setNodes( this.nodes ); loader.setTextures( textures ); return loader.parseNodes( json ); @@ -77698,6 +79935,7 @@ class NodeObjectLoader extends ObjectLoader { const loader = new NodeMaterialLoader(); loader.setTextures( textures ); loader.setNodes( nodes ); + loader.setNodeMaterials( this.nodeMaterials ); for ( let i = 0, l = json.length; i < l; i ++ ) { @@ -77737,4 +79975,4 @@ if ( typeof window !== 'undefined' ) { } -export { ACESFilmicToneMapping$1 as ACESFilmicToneMapping, AONode, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AfterImageNode, AgXToneMapping$1 as AgXToneMapping, AlphaFormat, AlwaysCompare, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightNode, AnaglyphPassNode, AnalyticLightNode, AnamorphicNode, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrayElementNode, ArrowHelper, AssignNode, AttachedBindMode, AttributeNode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BRDF_GGX, BRDF_Lambert, BackSide, BasicDepthPacking, BasicEnvironmentNode, BasicShadowMap$1 as BasicShadowMap, BatchNode, BatchedMesh, BloomNode, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxGeometry, BoxHelper, Break, BufferAttribute, BufferAttributeNode, BufferGeometry, BufferGeometryLoader, BufferNode, BumpMapNode, BypassNode, ByteType, Cache, CacheNode, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CineonToneMapping$1 as CineonToneMapping, CircleGeometry, ClampToEdgeWrapping, Clock, CodeNode, Color, ColorKeyframeTrack, ColorManagement, ColorSpaceFunctions, ColorSpaceNode, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ComputeNode, ConeGeometry, ConstNode, ConstantAlphaFactor, ConstantColorFactor, ContextNode, Continue, Controls, ConvertNode, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeTextureNode, CubeUVReflectionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderGeometry, Cylindrical, DFGApprox, D_GGX, Data3DTexture, DataArrayTexture, DataTexture, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DenoiseNode, DepthFormat, DepthOfFieldNode, DepthStencilFormat, DepthTexture, DetachedBindMode, DirectionalLight, DirectionalLightHelper, DirectionalLightNode, Discard, DiscreteInterpolant, DisplayP3ColorSpace, DodecahedronGeometry, DotScreenNode, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EPSILON, EdgesGeometry, EllipseCurve, EnvironmentNode, EqualCompare, EqualDepth, EqualStencilFunc, EquirectUVNode, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExpressionNode, ExtrudeGeometry, FXAANode, F_Schlick, FileLoader, FilmNode, Float16BufferAttribute, Float32BufferAttribute, FloatType, Fn, Fog, FogExp2, FogExp2Node, FogNode, FogRangeNode, FramebufferTexture, FrontFacingNode, FrontSide, Frustum, FunctionCallNode, FunctionNode, FunctionOverloadingNode, GLBufferAttribute, GLSL1, GLSL3, GLSLNodeParser, GTAONode, GaussianBlurNode, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, HemisphereLightNode, IESSpotLight, IESSpotLightNode, INFINITY, IcosahedronGeometry, If, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, IndexNode, InstanceNode, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, InstancedPointsNodeMaterial, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, IrradianceNode, JoinNode, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, Layers, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightNode, LightProbe, LightProbeNode, LightingContextNode, LightingModel, LightingNode, LightsNode, Line, Line2NodeMaterial, Line3, LineBasicMaterial, LineBasicNodeMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineDashedNodeMaterial, LineLoop, LineSegments, LinearDisplayP3ColorSpace, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping$1 as LinearToneMapping, LinearTransfer, Loader, LoaderUtils, LoadingManager, Loop, LoopNode, LoopOnce, LoopPingPong, LoopRepeat, LuminanceAlphaFormat, LuminanceFormat, Lut3DNode, MOUSE, MRTNode, MatcapUVNode, Material, MaterialLoader, MaterialNode, MaterialReferenceNode, MathUtils, Matrix2, Matrix3, Matrix4, MaxEquation, MaxMipLevelNode, Mesh, MeshBasicMaterial, MeshBasicNodeMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshLambertMaterial, MeshLambertNodeMaterial, MeshMatcapMaterial, MeshMatcapNodeMaterial, MeshNormalMaterial, MeshNormalNodeMaterial, MeshPhongMaterial, MeshPhongNodeMaterial, MeshPhysicalMaterial, MeshPhysicalNodeMaterial, MeshSSSNodeMaterial, MeshStandardMaterial, MeshStandardNodeMaterial, MeshToonMaterial, MeshToonNodeMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, ModelNode, ModelViewProjectionNode, MorphNode, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeutralToneMapping$1 as NeutralToneMapping, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, Node, NodeAttribute, NodeBuilder, NodeCache, NodeCode, NodeFrame, NodeFunctionInput, NodeLoader, NodeMaterial, NodeMaterialLoader, NodeObjectLoader, NodeShaderStage, NodeType, NodeUniform, NodeUpdateType, NodeUtils, NodeVar, NodeVarying, NormalAnimationBlendMode, NormalBlending, NormalMapNode, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, Object3DNode, ObjectLoader, ObjectSpaceNormalMap, OctahedronGeometry, OneFactor, OneMinusConstantAlphaFactor, OneMinusConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, OscNode, OutputStructNode, P3Primaries, PCFShadowMap$1 as PCFShadowMap, PCFSoftShadowMap$1 as PCFSoftShadowMap, PI, PI2, PMREMGenerator, PMREMNode, ParallaxBarrierPassNode, ParameterNode, PassNode, Path, PerspectiveCamera, PhongLightingModel, PhysicalLightingModel, PixelationPassNode, Plane, PlaneGeometry, PlaneHelper, PointLight, PointLightHelper, PointLightNode, PointUVNode, Points, PointsMaterial, PointsNodeMaterial, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PostProcessing, PosterizeNode, PropertyBinding, PropertyMixer, PropertyNode, QuadMesh, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBDepthPacking, RGBFormat, RGBIntegerFormat, RGBShiftNode, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGDepthPacking, RGFormat, RGIntegerFormat, RTTNode, RangeNode, RawShaderMaterial, Ray, Raycaster, Rec709Primaries, RectAreaLight, RectAreaLightNode, RedFormat, RedIntegerFormat, ReferenceNode, ReflectorNode, ReinhardToneMapping$1 as ReinhardToneMapping, RemapNode, RenderOutputNode, RenderTarget, RendererReferenceNode, RepeatWrapping, ReplaceStencilOp, Return, ReverseSubtractEquation, RingGeometry, RotateNode, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SRGBColorSpace, SRGBTransfer, SSAAPassNode, Scene, SceneNode, Schlick_to_F0, ScriptableNode, ScriptableValueNode, SetNode, ShaderMaterial, ShaderNode, ShadowMaterial, ShadowNodeMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, SkinningNode, SobelOperatorNode, Source, Sphere, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SplitNode, SpotLight, SpotLightHelper, SpotLightNode, Sprite, SpriteMaterial, SpriteNodeMaterial, SpriteSheetUVNode, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StackNode, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StereoPassNode, StorageArrayElementNode, StorageBufferAttribute, StorageBufferNode, StorageInstancedBufferAttribute, StorageTexture, StorageTextureNode, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TBNViewMatrix, TOUCH, TangentSpaceNormalMap, TempNode, TetrahedronGeometry, Texture, Texture3DNode, TextureLoader, TextureNode, TextureSizeNode, TimerNode, ToneMappingFunctions, ToneMappingNode, TorusGeometry, TorusKnotGeometry, TransitionNode, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TriplanarTexturesNode, TubeGeometry, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform$1 as Uniform, UniformArrayNode, UniformGroupNode, UniformNode, UniformsGroup$1 as UniformsGroup, UnsignedByteType, UnsignedInt248Type, UnsignedInt5999Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, UserDataNode, VSMShadowMap, V_GGX_SmithCorrelated, VarNode, VaryingNode, Vector2, Vector3, Vector4, VectorKeyframeTrack, VertexColorNode, VideoTexture, ViewportDepthNode, ViewportDepthTextureNode, ViewportNode, ViewportSharedTextureNode, ViewportTextureNode, VolumeNodeMaterial, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLCoordinateSystem, WebGLCubeRenderTarget, WebGLMultipleRenderTargets, WebGLRenderTarget, WebGPUCoordinateSystem, WebGPURenderer, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, abs, acos, add, addMethodChaining, addNodeElement, afterImage, all, alphaT, anaglyphPass, anamorphic, and, anisotropy, anisotropyB, anisotropyT, any, ao, append, arrayBuffer, asin, assign, atan, atan2, attenuationColor, attenuationDistance, attribute, backgroundBlurriness, backgroundIntensity, batch, billboarding, bitAnd, bitNot, bitOr, bitXor, bitangentGeometry, bitangentLocal, bitangentView, bitangentWorld, bitcast, bleach, bloom, blur, bool, buffer, bufferAttribute, bumpMap, burn, bvec2, bvec3, bvec4, bypass, cache, call, cameraFar, cameraLogDepth, cameraNear, cameraNormalMatrix, cameraPosition, cameraProjectionMatrix, cameraProjectionMatrixInverse, cameraViewMatrix, cameraWorldMatrix, cbrt, ceil, checker, clamp, clearcoat, clearcoatRoughness, code, color, colorToDirection, compute, cond, context, convert, convertToTexture, cos, createCanvasElement, cross, cubeTexture, dFdx, dFdy, dashSize, defaultBuildStages, defaultShaderStages, defined, degrees, denoise, densityFog, depth, depthPass, difference, diffuseColor, directionToColor, dispersion, distance, div, dodge, dof, dot, dotScreen, drawIndex, dynamicBufferAttribute, element, emissive, equal, equals, equirectUV, exp, exp2, expression, faceDirection, faceForward, film, float, floor, fog, fract, frameGroup, frameId, frontFacing, fwidth, fxaa, gain, gapSize, gaussianBlur, getColorSpaceMethod, getConstNodeType, getCurrentStack, getDirection, getDistanceAttenuation, getGeometryRoughness, getRoughness, getTextureIndex, global, glsl, glslFn, grayscale, greaterThan, greaterThanEqual, hash, hue, instance, instanceIndex, instancedBufferAttribute, instancedDynamicBufferAttribute, int, inverseSqrt, invocationLocalIndex, ior, iridescence, iridescenceIOR, iridescenceThickness, ivec2, ivec3, ivec4, js, label, length, lengthSq, lessThan, lessThanEqual, lightTargetDirection, lightingContext, lights, linearDepth, log, log2, luminance, lut3D, mat2, mat3, mat4, matcapUV, materialAOMap, materialAlphaTest, materialAnisotropy, materialAnisotropyVector, materialClearcoat, materialClearcoatNormal, materialClearcoatRoughness, materialColor, materialDispersion, materialEmissive, materialIridescence, materialIridescenceIOR, materialIridescenceThickness, materialLightMap, materialLineDashOffset, materialLineDashSize, materialLineGapSize, materialLineScale, materialLineWidth, materialMetalness, materialNormal, materialOpacity, materialPointWidth, materialReference, materialReflectivity, materialRefractionRatio, materialRotation, materialRoughness, materialSheen, materialSheenRoughness, materialShininess, materialSpecular, materialSpecularStrength, max$1 as max, maxMipLevel, metalness, min$1 as min, mix, mixElement, mod, modInt, modelDirection, modelNormalMatrix, modelPosition, modelScale, modelViewMatrix, modelViewPosition, modelViewProjection, modelWorldMatrix, modelWorldMatrixInverse, morphReference, motionBlur, mrt, mul, mx_aastep, mx_cell_noise_float, mx_contrast, mx_fractal_noise_float, mx_fractal_noise_vec2, mx_fractal_noise_vec3, mx_fractal_noise_vec4, mx_hsvtorgb, mx_noise_float, mx_noise_vec3, mx_noise_vec4, mx_ramplr, mx_ramptb, mx_rgbtohsv, mx_safepower, mx_splitlr, mx_splittb, mx_srgb_texture_to_lin_rec709, mx_transform_uv, mx_worley_noise_float, mx_worley_noise_vec2, mx_worley_noise_vec3, negate, nodeArray, nodeImmutable, nodeObject, nodeObjects, nodeProxy, normalFlat, normalGeometry, normalLocal, normalMap, normalView, normalWorld, normalize, not, notEqual, objectDirection, objectGroup, objectNormalMatrix, objectPosition, objectScale, objectViewMatrix, objectViewPosition, objectWorldMatrix, oneMinus, or, orthographicDepthToViewZ, oscSawtooth, oscSine, oscSquare, oscTriangle, output, outputStruct, overlay, overloadingFn, parabola, parallaxBarrierPass, parallaxDirection, parallaxUV, parameter, pass, passTexture, pcurve, perspectiveDepthToViewZ, pixelationPass, pmremTexture, pointUV, pointWidth, positionGeometry, positionLocal, positionPrevious, positionView, positionViewDirection, positionWorld, positionWorldDirection, posterize, pow, pow2, pow3, pow4, property, radians, rand, range, rangeFog, reciprocal, reference, referenceBuffer, reflect, reflectVector, reflectView, reflector, refract, refractVector, refractView, registerNode, remainder, remap, remapClamp, renderGroup, renderOutput, rendererReference, rgbShift, rotate, rotateUV, roughness, round, rtt, sampler, saturate, saturation, screen, scriptable, scriptableValue, select, sepia, setCurrentStack, shaderStages, sharedUniformGroup, sheen, sheenRoughness, shiftLeft, shiftRight, shininess, sign, sin, sinc, skinning, skinningReference, smoothstep, smoothstepElement, sobel, specularColor, specularF90, spherizeUV, split, spritesheetUV, sqrt, ssaaPass, stack, step, stereoPass, storage, storageObject, storageTexture, string, sub, tan, tangentGeometry, tangentLocal, tangentView, tangentWorld, temp, texture, texture3D, textureBicubic, textureCubeUV, textureLoad, textureSize, textureStore, thickness, threshold, timerDelta, timerGlobal, timerLocal, toOutputColorSpace, toWorkingColorSpace, toneMapping, toneMappingExposure, transformDirection, transformedBentNormalView, transformedBitangentView, transformedBitangentWorld, transformedClearcoatNormalView, transformedNormalView, transformedNormalWorld, transformedTangentView, transformedTangentWorld, transition, transmission, transpose, tri, tri3, triNoise3D, triplanarTexture, triplanarTextures, trunc, tslFn, uint, uniform, uniformArray, uniformGroup, userData, uv, uvec2, uvec3, uvec4, varying, varyingProperty, vec2, vec3, vec4, vectorComponents, velocity, vertexColor, vertexIndex, vibrance, viewZToOrthographicDepth, viewZToPerspectiveDepth, viewport, viewportBottomLeft, viewportCoordinate, viewportDepthTexture, viewportLinearDepth, viewportMipTexture, viewportResolution, viewportSafeUV, viewportSharedTexture, viewportTexture, viewportTopLeft, viewportUV, wgsl, wgslFn, xor }; +export { ACESFilmicToneMapping, AONode, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AfterImageNode, AgXToneMapping, AlphaFormat, AlwaysCompare, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightNode, AnaglyphPassNode, AnalyticLightNode, AnamorphicNode, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrayElementNode, ArrowHelper, AssignNode, AttachedBindMode, AttributeNode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BRDF_GGX, BRDF_Lambert, BackSide, BasicDepthPacking, BasicEnvironmentNode, BasicShadowMap$1 as BasicShadowMap, BatchNode, BatchedMesh, BloomNode, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxGeometry, BoxHelper, Break, BufferAttribute, BufferAttributeNode, BufferGeometry, BufferGeometryLoader, BufferNode, BumpMapNode, BundleGroup, BypassNode, ByteType, Cache, CacheNode, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CineonToneMapping, CircleGeometry, ClampToEdgeWrapping, Clock, CodeNode, Color, ColorKeyframeTrack, ColorManagement, ColorSpaceNode, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ComputeNode, ConeGeometry, ConstNode, ConstantAlphaFactor, ConstantColorFactor, ContextNode, Continue, Controls, ConvertNode, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeTextureNode, CubeUVReflectionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderGeometry, Cylindrical, DFGApprox, D_GGX, Data3DTexture, DataArrayTexture, DataTexture, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DenoiseNode, DepthFormat, DepthOfFieldNode, DepthStencilFormat, DepthTexture, DetachedBindMode, DirectionalLight, DirectionalLightHelper, DirectionalLightNode, Discard, DiscreteInterpolant, DisplayP3ColorSpace, DodecahedronGeometry, DotScreenNode, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EPSILON, EdgesGeometry, EllipseCurve, EnvironmentNode, EqualCompare, EqualDepth, EqualStencilFunc, EquirectUVNode, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExpressionNode, ExtrudeGeometry, FXAANode, F_Schlick, FileLoader, FilmNode, Float16BufferAttribute, Float32BufferAttribute, FloatType, Fn, Fog, FogExp2, FogExp2Node, FogNode, FogRangeNode, FramebufferTexture, FrontFacingNode, FrontSide, Frustum, FunctionCallNode, FunctionNode, FunctionOverloadingNode, GLBufferAttribute, GLSL1, GLSL3, GLSLNodeParser, GTAONode, GaussianBlurNode, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, HemisphereLightNode, IESSpotLight, IESSpotLightNode, INFINITY, IcosahedronGeometry, If, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, IndexNode, InstanceNode, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, InstancedPointsNodeMaterial, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, IrradianceNode, JoinNode, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, Layers, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, LightProbeNode, LightingContextNode, LightingModel, LightingNode, LightsNode, Line, Line2NodeMaterial, Line3, LineBasicMaterial, LineBasicNodeMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineDashedNodeMaterial, LineLoop, LineSegments, LinearDisplayP3ColorSpace, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, LinearTransfer, Loader, LoaderUtils, LoadingManager, Loop, LoopNode, LoopOnce, LoopPingPong, LoopRepeat, LuminanceAlphaFormat, LuminanceFormat, Lut3DNode, MOUSE, MRTNode, MatcapUVNode, Material, MaterialLoader, MaterialNode, MaterialReferenceNode, MathUtils, Matrix2, Matrix3, Matrix4, MaxEquation, MaxMipLevelNode, Mesh, MeshBasicMaterial, MeshBasicNodeMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshLambertMaterial, MeshLambertNodeMaterial, MeshMatcapMaterial, MeshMatcapNodeMaterial, MeshNormalMaterial, MeshNormalNodeMaterial, MeshPhongMaterial, MeshPhongNodeMaterial, MeshPhysicalMaterial, MeshPhysicalNodeMaterial, MeshSSSNodeMaterial, MeshStandardMaterial, MeshStandardNodeMaterial, MeshToonMaterial, MeshToonNodeMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, ModelNode, ModelViewProjectionNode, MorphNode, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeutralToneMapping, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, Node, NodeAttribute, NodeBuilder, NodeCache, NodeCode, NodeFrame, NodeFunctionInput, NodeLoader, NodeMaterial, NodeMaterialLoader, NodeMaterialObserver, NodeObjectLoader, NodeShaderStage, NodeType, NodeUniform, NodeUpdateType, NodeUtils, NodeVar, NodeVarying, NormalAnimationBlendMode, NormalBlending, NormalMapNode, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, Object3DNode, ObjectLoader, ObjectSpaceNormalMap, OctahedronGeometry, OneFactor, OneMinusConstantAlphaFactor, OneMinusConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, OscNode, OutputStructNode, P3Primaries, PCFShadowMap$1 as PCFShadowMap, PCFSoftShadowMap$1 as PCFSoftShadowMap, PI, PI2, PMREMGenerator, PMREMNode, ParallaxBarrierPassNode, ParameterNode, PassNode, Path, PerspectiveCamera, PhongLightingModel, PhysicalLightingModel, PixelationPassNode, Plane, PlaneGeometry, PlaneHelper, PointLight, PointLightHelper, PointLightNode, PointUVNode, Points, PointsMaterial, PointsNodeMaterial, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PostProcessing, PosterizeNode, PropertyBinding, PropertyMixer, PropertyNode, QuadMesh, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBDepthPacking, RGBFormat, RGBIntegerFormat, RGBShiftNode, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGDepthPacking, RGFormat, RGIntegerFormat, RTTNode, RangeNode, RawShaderMaterial, Ray, Raycaster, Rec709Primaries, RectAreaLight, RectAreaLightNode, RedFormat, RedIntegerFormat, ReferenceNode, ReflectorNode, ReinhardToneMapping, RemapNode, RenderOutputNode, RenderTarget, RendererReferenceNode, RepeatWrapping, ReplaceStencilOp, Return, ReverseSubtractEquation, RingGeometry, RotateNode, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SRGBColorSpace, SRGBTransfer, SSAAPassNode, Scene, SceneNode, Schlick_to_F0, ScreenNode, ScriptableNode, ScriptableValueNode, SetNode, ShaderMaterial, ShaderNode, ShadowMaterial, ShadowNodeMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, SkinningNode, SobelOperatorNode, Source, Sphere, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SplitNode, SpotLight, SpotLightHelper, SpotLightNode, Sprite, SpriteMaterial, SpriteNodeMaterial, SpriteSheetUVNode, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StackNode, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StereoPassNode, StorageArrayElementNode, StorageBufferAttribute, StorageBufferNode, StorageInstancedBufferAttribute, StorageTexture, StorageTextureNode, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TBNViewMatrix, TOUCH, TangentSpaceNormalMap, TempNode, TetrahedronGeometry, Texture, Texture3DNode, TextureLoader, TextureNode, TextureSizeNode, TimerNode, ToneMappingNode, ToonOutlinePassNode, TorusGeometry, TorusKnotGeometry, TransitionNode, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TriplanarTexturesNode, TubeGeometry, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform$1 as Uniform, UniformArrayNode, UniformGroupNode, UniformNode, UniformsGroup$1 as UniformsGroup, UnsignedByteType, UnsignedInt248Type, UnsignedInt5999Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, UserDataNode, VSMShadowMap, V_GGX_SmithCorrelated, VarNode, VaryingNode, Vector2, Vector3, Vector4, VectorKeyframeTrack, VertexColorNode, VideoTexture, ViewportDepthNode, ViewportDepthTextureNode, ViewportSharedTextureNode, ViewportTextureNode, VolumeNodeMaterial, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLCoordinateSystem, WebGLCubeRenderTarget, WebGLMultipleRenderTargets, WebGLRenderTarget, WebGPUCoordinateSystem, WebGPURenderer, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, abs, acesFilmicToneMapping, acos, add, addMethodChaining, addNodeElement, afterImage, agxToneMapping, all, alphaT, anaglyphPass, anamorphic, and, anisotropy, anisotropyB, anisotropyT, any, ao, append, arrayBuffer, asin, assign, atan, atan2, atomicAdd, atomicAnd, atomicFunc, atomicMax, atomicMin, atomicOr, atomicStore, atomicSub, atomicXor, attenuationColor, attenuationDistance, attribute, backgroundBlurriness, backgroundIntensity, batch, billboarding, bitAnd, bitNot, bitOr, bitXor, bitangentGeometry, bitangentLocal, bitangentView, bitangentWorld, bitcast, bleach, bloom, blur, bool, buffer, bufferAttribute, bumpMap, burn, bvec2, bvec3, bvec4, bypass, cache, call, cameraFar, cameraLogDepth, cameraNear, cameraNormalMatrix, cameraPosition, cameraProjectionMatrix, cameraProjectionMatrixInverse, cameraViewMatrix, cameraWorldMatrix, cbrt, ceil, checker, cineonToneMapping, clamp, clearcoat, clearcoatRoughness, code, color, colorSpaceToWorking, colorToDirection, compute, cond, context, convert, convertToTexture, cos, createCanvasElement, cross, cubeTexture, dFdx, dFdy, dashSize, defaultBuildStages, defaultShaderStages, defined, degrees, denoise, densityFog, depth, depthPass, difference, diffuseColor, directionToColor, dispersion, distance, div, dodge, dof, dot, dotScreen, drawIndex, dynamicBufferAttribute, element, emissive, equal, equals, equirectUV, exp, exp2, expression, faceDirection, faceForward, film, float, floor, fog, fract, frameGroup, frameId, frontFacing, fwidth, fxaa, gain, gapSize, gaussianBlur, getColorSpaceMethod, getConstNodeType, getCurrentStack, getDirection, getDistanceAttenuation, getGeometryRoughness, getRoughness, getShIrradianceAt, getTextureIndex, global, glsl, glslFn, grayscale, greaterThan, greaterThanEqual, hash, highPrecisionModelNormalViewMatrix, highPrecisionModelViewMatrix, hue, instance, instanceIndex, instancedBufferAttribute, instancedDynamicBufferAttribute, int, inverseSqrt, invocationLocalIndex, invocationSubgroupIndex, ior, iridescence, iridescenceIOR, iridescenceThickness, ivec2, ivec3, ivec4, js, label, length, lengthSq, lessThan, lessThanEqual, lightPosition, lightTargetDirection, lightTargetPosition, lightViewPosition, lightingContext, lights, linearDepth, linearSRGBTosRGB, linearToneMapping, localId, log, log2, loop, luminance, lut3D, mat2, mat3, mat4, matcapUV, materialAOMap, materialAlphaTest, materialAnisotropy, materialAnisotropyVector, materialAttenuationColor, materialAttenuationDistance, materialClearcoat, materialClearcoatNormal, materialClearcoatRoughness, materialColor, materialDispersion, materialEmissive, materialIOR, materialIridescence, materialIridescenceIOR, materialIridescenceThickness, materialLightMap, materialLineDashOffset, materialLineDashSize, materialLineGapSize, materialLineScale, materialLineWidth, materialMetalness, materialNormal, materialOpacity, materialPointWidth, materialReference, materialReflectivity, materialRefractionRatio, materialRotation, materialRoughness, materialSheen, materialSheenRoughness, materialShininess, materialSpecular, materialSpecularColor, materialSpecularIntensity, materialSpecularStrength, materialThickness, materialTransmission, max$1 as max, maxMipLevel, metalness, min$1 as min, mix, mixElement, mod, modInt, modelDirection, modelNormalMatrix, modelPosition, modelScale, modelViewMatrix, modelViewPosition, modelViewProjection, modelWorldMatrix, modelWorldMatrixInverse, morphReference, motionBlur, mrt, mul, mx_aastep, mx_cell_noise_float, mx_contrast, mx_fractal_noise_float, mx_fractal_noise_vec2, mx_fractal_noise_vec3, mx_fractal_noise_vec4, mx_hsvtorgb, mx_noise_float, mx_noise_vec3, mx_noise_vec4, mx_ramplr, mx_ramptb, mx_rgbtohsv, mx_safepower, mx_splitlr, mx_splittb, mx_srgb_texture_to_lin_rec709, mx_transform_uv, mx_worley_noise_float, mx_worley_noise_vec2, mx_worley_noise_vec3, negate, neutralToneMapping, nodeArray, nodeImmutable, nodeObject, nodeObjects, nodeProxy, normalFlat, normalGeometry, normalLocal, normalMap, normalView, normalWorld, normalize, not, notEqual, numWorkgroups, objectDirection, objectGroup, objectPosition, objectScale, objectViewPosition, objectWorldMatrix, oneMinus, or, orthographicDepthToViewZ, oscSawtooth, oscSine, oscSquare, oscTriangle, output, outputStruct, overlay, overloadingFn, parabola, parallaxBarrierPass, parallaxDirection, parallaxUV, parameter, pass, passTexture, pcurve, perspectiveDepthToViewZ, pixelationPass, pmremTexture, pointUV, pointWidth, positionGeometry, positionLocal, positionPrevious, positionView, positionViewDirection, positionWorld, positionWorldDirection, posterize, pow, pow2, pow3, pow4, property, radians, rand, range, rangeFog, reciprocal, reference, referenceBuffer, reflect, reflectVector, reflectView, reflector, refract, refractVector, refractView, reinhardToneMapping, remainder, remap, remapClamp, renderGroup, renderOutput, rendererReference, rgbShift, rotate, rotateUV, roughness, round, rtt, sRGBToLinearSRGB, sampler, saturate, saturation, screen, screenCoordinate, screenSize, screenUV, scriptable, scriptableValue, select, sepia, setCurrentStack, shaderStages, sharedUniformGroup, sheen, sheenRoughness, shiftLeft, shiftRight, shininess, sign, sin, sinc, skinning, skinningReference, smoothstep, smoothstepElement, sobel, specularColor, specularF90, spherizeUV, split, spritesheetUV, sqrt, ssaaPass, stack, step, stereoPass, storage, storageBarrier, storageObject, storageTexture, string, sub, subgroupIndex, subgroupSize, tan, tangentGeometry, tangentLocal, tangentView, tangentWorld, temp, texture, texture3D, textureBarrier, textureBicubic, textureCubeUV, textureLoad, textureSize, textureStore, thickness, threshold, timerDelta, timerGlobal, timerLocal, toOutputColorSpace, toWorkingColorSpace, toneMapping, toneMappingExposure, toonOutlinePass, transformDirection, transformNormal, transformNormalToView, transformedBentNormalView, transformedBitangentView, transformedBitangentWorld, transformedClearcoatNormalView, transformedNormalView, transformedNormalWorld, transformedTangentView, transformedTangentWorld, transition, transmission, transpose, tri, tri3, triNoise3D, triplanarTexture, triplanarTextures, trunc, tslFn, uint, uniform, uniformArray, uniformGroup, uniforms, userData, uv, uvec2, uvec3, uvec4, varying, varyingProperty, vec2, vec3, vec4, vectorComponents, velocity, vertexColor, vertexIndex, vibrance, viewZToOrthographicDepth, viewZToPerspectiveDepth, viewport, viewportBottomLeft, viewportCoordinate, viewportDepthTexture, viewportLinearDepth, viewportMipTexture, viewportResolution, viewportSafeUV, viewportSharedTexture, viewportSize, viewportTexture, viewportTopLeft, viewportUV, wgsl, wgslFn, workgroupArray, workgroupBarrier, workgroupId, workingToColorSpace, xor }; diff --git a/build/three.webgpu.min.js b/build/three.webgpu.min.js index ae202e426cbca2..36502a3dfb4932 100644 --- a/build/three.webgpu.min.js +++ b/build/three.webgpu.min.js @@ -3,4 +3,4 @@ * Copyright 2010-2024 Three.js Authors * SPDX-License-Identifier: MIT */ -const e="168",t={LEFT:0,MIDDLE:1,RIGHT:2,ROTATE:0,DOLLY:1,PAN:2},s={ROTATE:0,PAN:1,DOLLY_PAN:2,DOLLY_ROTATE:3},i=0,r=1,n=2,o=3,a=0,h=1,l=2,u=3,c=0,d=1,p=2,m=0,g=1,f=2,y=3,x=4,b=5,v=100,T=101,_=102,w=103,S=104,M=200,A=201,N=202,R=203,C=204,E=205,B=206,I=207,P=208,F=209,z=210,U=211,L=212,O=213,V=214,D=0,k=1,G=2,W=3,H=4,j=5,q=6,$=7,X=0,Y=1,J=2,Z=0,K=1,Q=2,ee=3,te=4,se=5,ie=6,re=7,ne="attached",oe="detached",ae=300,he=301,le=302,ue=303,ce=304,de=306,pe=1e3,me=1001,ge=1002,fe=1003,ye=1004,xe=1004,be=1005,ve=1005,Te=1006,_e=1007,we=1007,Se=1008,Me=1008,Ae=1009,Ne=1010,Re=1011,Ce=1012,Ee=1013,Be=1014,Ie=1015,Pe=1016,Fe=1017,ze=1018,Ue=1020,Le=35902,Oe=1021,Ve=1022,De=1023,ke=1024,Ge=1025,We=1026,He=1027,je=1028,qe=1029,$e=1030,Xe=1031,Ye=1032,Je=1033,Ze=33776,Ke=33777,Qe=33778,et=33779,tt=35840,st=35841,it=35842,rt=35843,nt=36196,ot=37492,at=37496,ht=37808,lt=37809,ut=37810,ct=37811,dt=37812,pt=37813,mt=37814,gt=37815,ft=37816,yt=37817,xt=37818,bt=37819,vt=37820,Tt=37821,_t=36492,wt=36494,St=36495,Mt=36283,At=36284,Nt=36285,Rt=36286,Ct=2200,Et=2201,Bt=2202,It=2300,Pt=2301,Ft=2302,zt=2400,Ut=2401,Lt=2402,Ot=2500,Vt=2501,Dt=0,kt=1,Gt=2,Wt=3200,Ht=3201,jt=3202,qt=3203,$t=0,Xt=1,Yt="",Jt="srgb",Zt="srgb-linear",Kt="display-p3",Qt="display-p3-linear",es="linear",ts="srgb",ss="rec709",is="p3",rs=0,ns=7680,os=7681,as=7682,hs=7683,ls=34055,us=34056,cs=5386,ds=512,ps=513,ms=514,gs=515,fs=516,ys=517,xs=518,bs=519,vs=512,Ts=513,_s=514,ws=515,Ss=516,Ms=517,As=518,Ns=519,Rs=35044,Cs=35048,Es=35040,Bs=35045,Is=35049,Ps=35041,Fs=35046,zs=35050,Us=35042,Ls="100",Os="300 es",Vs=2e3,Ds=2001;class ks{addEventListener(e,t){void 0===this._listeners&&(this._listeners={});const s=this._listeners;void 0===s[e]&&(s[e]=[]),-1===s[e].indexOf(t)&&s[e].push(t)}hasEventListener(e,t){if(void 0===this._listeners)return!1;const s=this._listeners;return void 0!==s[e]&&-1!==s[e].indexOf(t)}removeEventListener(e,t){if(void 0===this._listeners)return;const s=this._listeners[e];if(void 0!==s){const e=s.indexOf(t);-1!==e&&s.splice(e,1)}}dispatchEvent(e){if(void 0===this._listeners)return;const t=this._listeners[e.type];if(void 0!==t){e.target=this;const s=t.slice(0);for(let t=0,i=s.length;t>8&255]+Gs[e>>16&255]+Gs[e>>24&255]+"-"+Gs[255&t]+Gs[t>>8&255]+"-"+Gs[t>>16&15|64]+Gs[t>>24&255]+"-"+Gs[63&s|128]+Gs[s>>8&255]+"-"+Gs[s>>16&255]+Gs[s>>24&255]+Gs[255&i]+Gs[i>>8&255]+Gs[i>>16&255]+Gs[i>>24&255]).toLowerCase()}function $s(e,t,s){return Math.max(t,Math.min(s,e))}function Xs(e,t){return(e%t+t)%t}function Ys(e,t,s){return(1-s)*e+s*t}function Js(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return e/4294967295;case Uint16Array:return e/65535;case Uint8Array:return e/255;case Int32Array:return Math.max(e/2147483647,-1);case Int16Array:return Math.max(e/32767,-1);case Int8Array:return Math.max(e/127,-1);default:throw new Error("Invalid component type.")}}function Zs(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return Math.round(4294967295*e);case Uint16Array:return Math.round(65535*e);case Uint8Array:return Math.round(255*e);case Int32Array:return Math.round(2147483647*e);case Int16Array:return Math.round(32767*e);case Int8Array:return Math.round(127*e);default:throw new Error("Invalid component type.")}}const Ks={DEG2RAD:Hs,RAD2DEG:js,generateUUID:qs,clamp:$s,euclideanModulo:Xs,mapLinear:function(e,t,s,i,r){return i+(e-t)*(r-i)/(s-t)},inverseLerp:function(e,t,s){return e!==t?(s-e)/(t-e):0},lerp:Ys,damp:function(e,t,s,i){return Ys(e,t,1-Math.exp(-s*i))},pingpong:function(e,t=1){return t-Math.abs(Xs(e,2*t)-t)},smoothstep:function(e,t,s){return e<=t?0:e>=s?1:(e=(e-t)/(s-t))*e*(3-2*e)},smootherstep:function(e,t,s){return e<=t?0:e>=s?1:(e=(e-t)/(s-t))*e*e*(e*(6*e-15)+10)},randInt:function(e,t){return e+Math.floor(Math.random()*(t-e+1))},randFloat:function(e,t){return e+Math.random()*(t-e)},randFloatSpread:function(e){return e*(.5-Math.random())},seededRandom:function(e){void 0!==e&&(Ws=e);let t=Ws+=1831565813;return t=Math.imul(t^t>>>15,1|t),t^=t+Math.imul(t^t>>>7,61|t),((t^t>>>14)>>>0)/4294967296},degToRad:function(e){return e*Hs},radToDeg:function(e){return e*js},isPowerOfTwo:function(e){return 0==(e&e-1)&&0!==e},ceilPowerOfTwo:function(e){return Math.pow(2,Math.ceil(Math.log(e)/Math.LN2))},floorPowerOfTwo:function(e){return Math.pow(2,Math.floor(Math.log(e)/Math.LN2))},setQuaternionFromProperEuler:function(e,t,s,i,r){const n=Math.cos,o=Math.sin,a=n(s/2),h=o(s/2),l=n((t+i)/2),u=o((t+i)/2),c=n((t-i)/2),d=o((t-i)/2),p=n((i-t)/2),m=o((i-t)/2);switch(r){case"XYX":e.set(a*u,h*c,h*d,a*l);break;case"YZY":e.set(h*d,a*u,h*c,a*l);break;case"ZXZ":e.set(h*c,h*d,a*u,a*l);break;case"XZX":e.set(a*u,h*m,h*p,a*l);break;case"YXY":e.set(h*p,a*u,h*m,a*l);break;case"ZYZ":e.set(h*m,h*p,a*u,a*l);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}},normalize:Zs,denormalize:Js};class Qs{constructor(e=0,t=0){Qs.prototype.isVector2=!0,this.x=e,this.y=t}get width(){return this.x}set width(e){this.x=e}get height(){return this.y}set height(e){this.y=e}set(e,t){return this.x=e,this.y=t,this}setScalar(e){return this.x=e,this.y=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y)}copy(e){return this.x=e.x,this.y=e.y,this}add(e){return this.x+=e.x,this.y+=e.y,this}addScalar(e){return this.x+=e,this.y+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this}subScalar(e){return this.x-=e,this.y-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this}multiply(e){return this.x*=e.x,this.y*=e.y,this}multiplyScalar(e){return this.x*=e,this.y*=e,this}divide(e){return this.x/=e.x,this.y/=e.y,this}divideScalar(e){return this.multiplyScalar(1/e)}applyMatrix3(e){const t=this.x,s=this.y,i=e.elements;return this.x=i[0]*t+i[3]*s+i[6],this.y=i[1]*t+i[4]*s+i[7],this}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this}clampLength(e,t){const s=this.length();return this.divideScalar(s||1).multiplyScalar(Math.max(e,Math.min(t,s)))}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=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.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}angleTo(e){const t=Math.sqrt(this.lengthSq()*e.lengthSq());if(0===t)return Math.PI/2;const s=this.dot(e)/t;return Math.acos($s(s,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){const t=this.x-e.x,s=this.y-e.y;return t*t+s*s}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this}lerpVectors(e,t,s){return this.x=e.x+(t.x-e.x)*s,this.y=e.y+(t.y-e.y)*s,this}equals(e){return e.x===this.x&&e.y===this.y}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this}rotateAround(e,t){const s=Math.cos(t),i=Math.sin(t),r=this.x-e.x,n=this.y-e.y;return this.x=r*s-n*i+e.x,this.y=r*i+n*s+e.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class ei{constructor(e,t,s,i,r,n,o,a,h){ei.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],void 0!==e&&this.set(e,t,s,i,r,n,o,a,h)}set(e,t,s,i,r,n,o,a,h){const l=this.elements;return l[0]=e,l[1]=i,l[2]=o,l[3]=t,l[4]=r,l[5]=a,l[6]=s,l[7]=n,l[8]=h,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(e){const t=this.elements,s=e.elements;return t[0]=s[0],t[1]=s[1],t[2]=s[2],t[3]=s[3],t[4]=s[4],t[5]=s[5],t[6]=s[6],t[7]=s[7],t[8]=s[8],this}extractBasis(e,t,s){return e.setFromMatrix3Column(this,0),t.setFromMatrix3Column(this,1),s.setFromMatrix3Column(this,2),this}setFromMatrix4(e){const t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){const s=e.elements,i=t.elements,r=this.elements,n=s[0],o=s[3],a=s[6],h=s[1],l=s[4],u=s[7],c=s[2],d=s[5],p=s[8],m=i[0],g=i[3],f=i[6],y=i[1],x=i[4],b=i[7],v=i[2],T=i[5],_=i[8];return r[0]=n*m+o*y+a*v,r[3]=n*g+o*x+a*T,r[6]=n*f+o*b+a*_,r[1]=h*m+l*y+u*v,r[4]=h*g+l*x+u*T,r[7]=h*f+l*b+u*_,r[2]=c*m+d*y+p*v,r[5]=c*g+d*x+p*T,r[8]=c*f+d*b+p*_,this}multiplyScalar(e){const t=this.elements;return t[0]*=e,t[3]*=e,t[6]*=e,t[1]*=e,t[4]*=e,t[7]*=e,t[2]*=e,t[5]*=e,t[8]*=e,this}determinant(){const e=this.elements,t=e[0],s=e[1],i=e[2],r=e[3],n=e[4],o=e[5],a=e[6],h=e[7],l=e[8];return t*n*l-t*o*h-s*r*l+s*o*a+i*r*h-i*n*a}invert(){const e=this.elements,t=e[0],s=e[1],i=e[2],r=e[3],n=e[4],o=e[5],a=e[6],h=e[7],l=e[8],u=l*n-o*h,c=o*a-l*r,d=h*r-n*a,p=t*u+s*c+i*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const m=1/p;return e[0]=u*m,e[1]=(i*h-l*s)*m,e[2]=(o*s-i*n)*m,e[3]=c*m,e[4]=(l*t-i*a)*m,e[5]=(i*r-o*t)*m,e[6]=d*m,e[7]=(s*a-h*t)*m,e[8]=(n*t-s*r)*m,this}transpose(){let e;const t=this.elements;return e=t[1],t[1]=t[3],t[3]=e,e=t[2],t[2]=t[6],t[6]=e,e=t[5],t[5]=t[7],t[7]=e,this}getNormalMatrix(e){return this.setFromMatrix4(e).invert().transpose()}transposeIntoArray(e){const t=this.elements;return e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8],this}setUvTransform(e,t,s,i,r,n,o){const a=Math.cos(r),h=Math.sin(r);return this.set(s*a,s*h,-s*(a*n+h*o)+n+e,-i*h,i*a,-i*(-h*n+a*o)+o+t,0,0,1),this}scale(e,t){return this.premultiply(ti.makeScale(e,t)),this}rotate(e){return this.premultiply(ti.makeRotation(-e)),this}translate(e,t){return this.premultiply(ti.makeTranslation(e,t)),this}makeTranslation(e,t){return e.isVector2?this.set(1,0,e.x,0,1,e.y,0,0,1):this.set(1,0,e,0,1,t,0,0,1),this}makeRotation(e){const t=Math.cos(e),s=Math.sin(e);return this.set(t,-s,0,s,t,0,0,0,1),this}makeScale(e,t){return this.set(e,0,0,0,t,0,0,0,1),this}equals(e){const t=this.elements,s=e.elements;for(let e=0;e<9;e++)if(t[e]!==s[e])return!1;return!0}fromArray(e,t=0){for(let s=0;s<9;s++)this.elements[s]=e[s+t];return this}toArray(e=[],t=0){const s=this.elements;return e[t]=s[0],e[t+1]=s[1],e[t+2]=s[2],e[t+3]=s[3],e[t+4]=s[4],e[t+5]=s[5],e[t+6]=s[6],e[t+7]=s[7],e[t+8]=s[8],e}clone(){return(new this.constructor).fromArray(this.elements)}}const ti=new ei;const si={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function ii(e,t){return new si[e](t)}function ri(e){return document.createElementNS("http://www.w3.org/1999/xhtml",e)}function ni(){const e=ri("canvas");return e.style.display="block",e}const oi={};function ai(e){e in oi||(oi[e]=!0,console.warn(e))}const hi=(new ei).set(.8224621,.177538,0,.0331941,.9668058,0,.0170827,.0723974,.9105199),li=(new ei).set(1.2249401,-.2249404,0,-.0420569,1.0420571,0,-.0196376,-.0786361,1.0982735),ui={[Zt]:{transfer:es,primaries:ss,luminanceCoefficients:[.2126,.7152,.0722],toReference:e=>e,fromReference:e=>e},[Jt]:{transfer:ts,primaries:ss,luminanceCoefficients:[.2126,.7152,.0722],toReference:e=>e.convertSRGBToLinear(),fromReference:e=>e.convertLinearToSRGB()},[Qt]:{transfer:es,primaries:is,luminanceCoefficients:[.2289,.6917,.0793],toReference:e=>e.applyMatrix3(li),fromReference:e=>e.applyMatrix3(hi)},[Kt]:{transfer:ts,primaries:is,luminanceCoefficients:[.2289,.6917,.0793],toReference:e=>e.convertSRGBToLinear().applyMatrix3(li),fromReference:e=>e.applyMatrix3(hi).convertLinearToSRGB()}},ci=new Set([Zt,Qt]),di={enabled:!0,_workingColorSpace:Zt,get workingColorSpace(){return this._workingColorSpace},set workingColorSpace(e){if(!ci.has(e))throw new Error(`Unsupported working color space, "${e}".`);this._workingColorSpace=e},convert:function(e,t,s){if(!1===this.enabled||t===s||!t||!s)return e;const i=ui[t].toReference;return(0,ui[s].fromReference)(i(e))},fromWorkingColorSpace:function(e,t){return this.convert(e,this._workingColorSpace,t)},toWorkingColorSpace:function(e,t){return this.convert(e,t,this._workingColorSpace)},getPrimaries:function(e){return ui[e].primaries},getTransfer:function(e){return e===Yt?es:ui[e].transfer},getLuminanceCoefficients:function(e,t=this._workingColorSpace){return e.fromArray(ui[t].luminanceCoefficients)}};function pi(e){return e<.04045?.0773993808*e:Math.pow(.9478672986*e+.0521327014,2.4)}function mi(e){return e<.0031308?12.92*e:1.055*Math.pow(e,.41666)-.055}let gi;class fi{static getDataURL(e){if(/^data:/i.test(e.src))return e.src;if("undefined"==typeof HTMLCanvasElement)return e.src;let t;if(e instanceof HTMLCanvasElement)t=e;else{void 0===gi&&(gi=ri("canvas")),gi.width=e.width,gi.height=e.height;const s=gi.getContext("2d");e instanceof ImageData?s.putImageData(e,0,0):s.drawImage(e,0,0,e.width,e.height),t=gi}return t.width>2048||t.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",e),t.toDataURL("image/jpeg",.6)):t.toDataURL("image/png")}static sRGBToLinear(e){if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap){const t=ri("canvas");t.width=e.width,t.height=e.height;const s=t.getContext("2d");s.drawImage(e,0,0,e.width,e.height);const i=s.getImageData(0,0,e.width,e.height),r=i.data;for(let e=0;e0&&(s.userData=this.userData),t||(e.textures[this.uuid]=s),s}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(e){if(this.mapping!==ae)return e;if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case pe:e.x=e.x-Math.floor(e.x);break;case me:e.x=e.x<0?0:1;break;case ge:1===Math.abs(Math.floor(e.x)%2)?e.x=Math.ceil(e.x)-e.x:e.x=e.x-Math.floor(e.x)}if(e.y<0||e.y>1)switch(this.wrapT){case pe:e.y=e.y-Math.floor(e.y);break;case me:e.y=e.y<0?0:1;break;case ge:1===Math.abs(Math.floor(e.y)%2)?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y)}return this.flipY&&(e.y=1-e.y),e}set needsUpdate(e){!0===e&&(this.version++,this.source.needsUpdate=!0)}set needsPMREMUpdate(e){!0===e&&this.pmremVersion++}}Ti.DEFAULT_IMAGE=null,Ti.DEFAULT_MAPPING=ae,Ti.DEFAULT_ANISOTROPY=1;class _i{constructor(e=0,t=0,s=0,i=1){_i.prototype.isVector4=!0,this.x=e,this.y=t,this.z=s,this.w=i}get width(){return this.z}set width(e){this.z=e}get height(){return this.w}set height(e){this.w=e}set(e,t,s,i){return this.x=e,this.y=t,this.z=s,this.w=i,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this.w=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setW(e){return this.w=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;case 3:this.w=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){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: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=void 0!==e.w?e.w:1,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this.w=e.w+t.w,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this.w+=e.w*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this.w=e.w-t.w,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this.w*=e.w,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this}applyMatrix4(e){const t=this.x,s=this.y,i=this.z,r=this.w,n=e.elements;return this.x=n[0]*t+n[4]*s+n[8]*i+n[12]*r,this.y=n[1]*t+n[5]*s+n[9]*i+n[13]*r,this.z=n[2]*t+n[6]*s+n[10]*i+n[14]*r,this.w=n[3]*t+n[7]*s+n[11]*i+n[15]*r,this}divideScalar(e){return this.multiplyScalar(1/e)}setAxisAngleFromQuaternion(e){this.w=2*Math.acos(e.w);const t=Math.sqrt(1-e.w*e.w);return t<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=e.x/t,this.y=e.y/t,this.z=e.z/t),this}setAxisAngleFromRotationMatrix(e){let t,s,i,r;const n=.01,o=.1,a=e.elements,h=a[0],l=a[4],u=a[8],c=a[1],d=a[5],p=a[9],m=a[2],g=a[6],f=a[10];if(Math.abs(l-c)a&&e>y?ey?a=0?1:-1,i=1-t*t;if(i>Number.EPSILON){const r=Math.sqrt(i),n=Math.atan2(r,t*s);e=Math.sin(e*n)/r,o=Math.sin(o*n)/r}const r=o*s;if(a=a*e+c*r,h=h*e+d*r,l=l*e+p*r,u=u*e+m*r,e===1-o){const e=1/Math.sqrt(a*a+h*h+l*l+u*u);a*=e,h*=e,l*=e,u*=e}}e[t]=a,e[t+1]=h,e[t+2]=l,e[t+3]=u}static multiplyQuaternionsFlat(e,t,s,i,r,n){const o=s[i],a=s[i+1],h=s[i+2],l=s[i+3],u=r[n],c=r[n+1],d=r[n+2],p=r[n+3];return e[t]=o*p+l*u+a*d-h*c,e[t+1]=a*p+l*c+h*u-o*d,e[t+2]=h*p+l*d+o*c-a*u,e[t+3]=l*p-o*u-a*c-h*d,e}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get w(){return this._w}set w(e){this._w=e,this._onChangeCallback()}set(e,t,s,i){return this._x=e,this._y=t,this._z=s,this._w=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this._onChangeCallback(),this}setFromEuler(e,t=!0){const s=e._x,i=e._y,r=e._z,n=e._order,o=Math.cos,a=Math.sin,h=o(s/2),l=o(i/2),u=o(r/2),c=a(s/2),d=a(i/2),p=a(r/2);switch(n){case"XYZ":this._x=c*l*u+h*d*p,this._y=h*d*u-c*l*p,this._z=h*l*p+c*d*u,this._w=h*l*u-c*d*p;break;case"YXZ":this._x=c*l*u+h*d*p,this._y=h*d*u-c*l*p,this._z=h*l*p-c*d*u,this._w=h*l*u+c*d*p;break;case"ZXY":this._x=c*l*u-h*d*p,this._y=h*d*u+c*l*p,this._z=h*l*p+c*d*u,this._w=h*l*u-c*d*p;break;case"ZYX":this._x=c*l*u-h*d*p,this._y=h*d*u+c*l*p,this._z=h*l*p-c*d*u,this._w=h*l*u+c*d*p;break;case"YZX":this._x=c*l*u+h*d*p,this._y=h*d*u+c*l*p,this._z=h*l*p-c*d*u,this._w=h*l*u-c*d*p;break;case"XZY":this._x=c*l*u-h*d*p,this._y=h*d*u-c*l*p,this._z=h*l*p+c*d*u,this._w=h*l*u+c*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+n)}return!0===t&&this._onChangeCallback(),this}setFromAxisAngle(e,t){const s=t/2,i=Math.sin(s);return this._x=e.x*i,this._y=e.y*i,this._z=e.z*i,this._w=Math.cos(s),this._onChangeCallback(),this}setFromRotationMatrix(e){const t=e.elements,s=t[0],i=t[4],r=t[8],n=t[1],o=t[5],a=t[9],h=t[2],l=t[6],u=t[10],c=s+o+u;if(c>0){const e=.5/Math.sqrt(c+1);this._w=.25/e,this._x=(l-a)*e,this._y=(r-h)*e,this._z=(n-i)*e}else if(s>o&&s>u){const e=2*Math.sqrt(1+s-o-u);this._w=(l-a)/e,this._x=.25*e,this._y=(i+n)/e,this._z=(r+h)/e}else if(o>u){const e=2*Math.sqrt(1+o-s-u);this._w=(r-h)/e,this._x=(i+n)/e,this._y=.25*e,this._z=(a+l)/e}else{const e=2*Math.sqrt(1+u-s-o);this._w=(n-i)/e,this._x=(r+h)/e,this._y=(a+l)/e,this._z=.25*e}return this._onChangeCallback(),this}setFromUnitVectors(e,t){let s=e.dot(t)+1;return sMath.abs(e.z)?(this._x=-e.y,this._y=e.x,this._z=0,this._w=s):(this._x=0,this._y=-e.z,this._z=e.y,this._w=s)):(this._x=e.y*t.z-e.z*t.y,this._y=e.z*t.x-e.x*t.z,this._z=e.x*t.y-e.y*t.x,this._w=s),this.normalize()}angleTo(e){return 2*Math.acos(Math.abs($s(this.dot(e),-1,1)))}rotateTowards(e,t){const s=this.angleTo(e);if(0===s)return this;const i=Math.min(1,t/s);return this.slerp(e,i),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(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._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 e=this.length();return 0===e?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x=this._x*e,this._y=this._y*e,this._z=this._z*e,this._w=this._w*e),this._onChangeCallback(),this}multiply(e){return this.multiplyQuaternions(this,e)}premultiply(e){return this.multiplyQuaternions(e,this)}multiplyQuaternions(e,t){const s=e._x,i=e._y,r=e._z,n=e._w,o=t._x,a=t._y,h=t._z,l=t._w;return this._x=s*l+n*o+i*h-r*a,this._y=i*l+n*a+r*o-s*h,this._z=r*l+n*h+s*a-i*o,this._w=n*l-s*o-i*a-r*h,this._onChangeCallback(),this}slerp(e,t){if(0===t)return this;if(1===t)return this.copy(e);const s=this._x,i=this._y,r=this._z,n=this._w;let o=n*e._w+s*e._x+i*e._y+r*e._z;if(o<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,o=-o):this.copy(e),o>=1)return this._w=n,this._x=s,this._y=i,this._z=r,this;const a=1-o*o;if(a<=Number.EPSILON){const e=1-t;return this._w=e*n+t*this._w,this._x=e*s+t*this._x,this._y=e*i+t*this._y,this._z=e*r+t*this._z,this.normalize(),this}const h=Math.sqrt(a),l=Math.atan2(h,o),u=Math.sin((1-t)*l)/h,c=Math.sin(t*l)/h;return this._w=n*u+this._w*c,this._x=s*u+this._x*c,this._y=i*u+this._y*c,this._z=r*u+this._z*c,this._onChangeCallback(),this}slerpQuaternions(e,t,s){return this.copy(e).slerp(t,s)}random(){const e=2*Math.PI*Math.random(),t=2*Math.PI*Math.random(),s=Math.random(),i=Math.sqrt(1-s),r=Math.sqrt(s);return this.set(i*Math.sin(e),i*Math.cos(e),r*Math.sin(t),r*Math.cos(t))}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w}fromArray(e,t=0){return this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e}fromBufferAttribute(e,t){return this._x=e.getX(t),this._y=e.getY(t),this._z=e.getZ(t),this._w=e.getW(t),this._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class Ei{constructor(e=0,t=0,s=0){Ei.prototype.isVector3=!0,this.x=e,this.y=t,this.z=s}set(e,t,s){return void 0===s&&(s=this.z),this.x=e,this.y=t,this.z=s,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this}multiplyVectors(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this}applyEuler(e){return this.applyQuaternion(Ii.setFromEuler(e))}applyAxisAngle(e,t){return this.applyQuaternion(Ii.setFromAxisAngle(e,t))}applyMatrix3(e){const t=this.x,s=this.y,i=this.z,r=e.elements;return this.x=r[0]*t+r[3]*s+r[6]*i,this.y=r[1]*t+r[4]*s+r[7]*i,this.z=r[2]*t+r[5]*s+r[8]*i,this}applyNormalMatrix(e){return this.applyMatrix3(e).normalize()}applyMatrix4(e){const t=this.x,s=this.y,i=this.z,r=e.elements,n=1/(r[3]*t+r[7]*s+r[11]*i+r[15]);return this.x=(r[0]*t+r[4]*s+r[8]*i+r[12])*n,this.y=(r[1]*t+r[5]*s+r[9]*i+r[13])*n,this.z=(r[2]*t+r[6]*s+r[10]*i+r[14])*n,this}applyQuaternion(e){const t=this.x,s=this.y,i=this.z,r=e.x,n=e.y,o=e.z,a=e.w,h=2*(n*i-o*s),l=2*(o*t-r*i),u=2*(r*s-n*t);return this.x=t+a*h+n*u-o*l,this.y=s+a*l+o*h-r*u,this.z=i+a*u+r*l-n*h,this}project(e){return this.applyMatrix4(e.matrixWorldInverse).applyMatrix4(e.projectionMatrix)}unproject(e){return this.applyMatrix4(e.projectionMatrixInverse).applyMatrix4(e.matrixWorld)}transformDirection(e){const t=this.x,s=this.y,i=this.z,r=e.elements;return this.x=r[0]*t+r[4]*s+r[8]*i,this.y=r[1]*t+r[5]*s+r[9]*i,this.z=r[2]*t+r[6]*s+r[10]*i,this.normalize()}divide(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this}divideScalar(e){return this.multiplyScalar(1/e)}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this.z=Math.max(e,Math.min(t,this.z)),this}clampLength(e,t){const s=this.length();return this.divideScalar(s||1).multiplyScalar(Math.max(e,Math.min(t,s)))}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=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(e){return this.x*e.x+this.y*e.y+this.z*e.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(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this}lerpVectors(e,t,s){return this.x=e.x+(t.x-e.x)*s,this.y=e.y+(t.y-e.y)*s,this.z=e.z+(t.z-e.z)*s,this}cross(e){return this.crossVectors(this,e)}crossVectors(e,t){const s=e.x,i=e.y,r=e.z,n=t.x,o=t.y,a=t.z;return this.x=i*a-r*o,this.y=r*n-s*a,this.z=s*o-i*n,this}projectOnVector(e){const t=e.lengthSq();if(0===t)return this.set(0,0,0);const s=e.dot(this)/t;return this.copy(e).multiplyScalar(s)}projectOnPlane(e){return Bi.copy(this).projectOnVector(e),this.sub(Bi)}reflect(e){return this.sub(Bi.copy(e).multiplyScalar(2*this.dot(e)))}angleTo(e){const t=Math.sqrt(this.lengthSq()*e.lengthSq());if(0===t)return Math.PI/2;const s=this.dot(e)/t;return Math.acos($s(s,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){const t=this.x-e.x,s=this.y-e.y,i=this.z-e.z;return t*t+s*s+i*i}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)}setFromSpherical(e){return this.setFromSphericalCoords(e.radius,e.phi,e.theta)}setFromSphericalCoords(e,t,s){const i=Math.sin(t)*e;return this.x=i*Math.sin(s),this.y=Math.cos(t)*e,this.z=i*Math.cos(s),this}setFromCylindrical(e){return this.setFromCylindricalCoords(e.radius,e.theta,e.y)}setFromCylindricalCoords(e,t,s){return this.x=e*Math.sin(t),this.y=s,this.z=e*Math.cos(t),this}setFromMatrixPosition(e){const t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this}setFromMatrixScale(e){const t=this.setFromMatrixColumn(e,0).length(),s=this.setFromMatrixColumn(e,1).length(),i=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=s,this.z=i,this}setFromMatrixColumn(e,t){return this.fromArray(e.elements,4*t)}setFromMatrix3Column(e,t){return this.fromArray(e.elements,3*t)}setFromEuler(e){return this.x=e._x,this.y=e._y,this.z=e._z,this}setFromColor(e){return this.x=e.r,this.y=e.g,this.z=e.b,this}equals(e){return e.x===this.x&&e.y===this.y&&e.z===this.z}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this.z=e[t+2],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const e=Math.random()*Math.PI*2,t=2*Math.random()-1,s=Math.sqrt(1-t*t);return this.x=s*Math.cos(e),this.y=t,this.z=s*Math.sin(e),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const Bi=new Ei,Ii=new Ci;class Pi{constructor(e=new Ei(1/0,1/0,1/0),t=new Ei(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=e,this.max=t}set(e,t){return this.min.copy(e),this.max.copy(t),this}setFromArray(e){this.makeEmpty();for(let t=0,s=e.length;t=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y&&e.z>=this.min.z&&e.z<=this.max.z}containsBox(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z}getParameter(e,t){return t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(e){return e.max.x>=this.min.x&&e.min.x<=this.max.x&&e.max.y>=this.min.y&&e.min.y<=this.max.y&&e.max.z>=this.min.z&&e.min.z<=this.max.z}intersectsSphere(e){return this.clampPoint(e.center,zi),zi.distanceToSquared(e.center)<=e.radius*e.radius}intersectsPlane(e){let t,s;return e.normal.x>0?(t=e.normal.x*this.min.x,s=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,s=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,s+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,s+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,s+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,s+=e.normal.z*this.min.z),t<=-e.constant&&s>=-e.constant}intersectsTriangle(e){if(this.isEmpty())return!1;this.getCenter(Wi),Hi.subVectors(this.max,Wi),Li.subVectors(e.a,Wi),Oi.subVectors(e.b,Wi),Vi.subVectors(e.c,Wi),Di.subVectors(Oi,Li),ki.subVectors(Vi,Oi),Gi.subVectors(Li,Vi);let t=[0,-Di.z,Di.y,0,-ki.z,ki.y,0,-Gi.z,Gi.y,Di.z,0,-Di.x,ki.z,0,-ki.x,Gi.z,0,-Gi.x,-Di.y,Di.x,0,-ki.y,ki.x,0,-Gi.y,Gi.x,0];return!!$i(t,Li,Oi,Vi,Hi)&&(t=[1,0,0,0,1,0,0,0,1],!!$i(t,Li,Oi,Vi,Hi)&&(ji.crossVectors(Di,ki),t=[ji.x,ji.y,ji.z],$i(t,Li,Oi,Vi,Hi)))}clampPoint(e,t){return t.copy(e).clamp(this.min,this.max)}distanceToPoint(e){return this.clampPoint(e,zi).distanceTo(e)}getBoundingSphere(e){return this.isEmpty()?e.makeEmpty():(this.getCenter(e.center),e.radius=.5*this.getSize(zi).length()),e}intersect(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this}union(e){return this.min.min(e.min),this.max.max(e.max),this}applyMatrix4(e){return this.isEmpty()||(Fi[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),Fi[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),Fi[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),Fi[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),Fi[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),Fi[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),Fi[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),Fi[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(Fi)),this}translate(e){return this.min.add(e),this.max.add(e),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}const Fi=[new Ei,new Ei,new Ei,new Ei,new Ei,new Ei,new Ei,new Ei],zi=new Ei,Ui=new Pi,Li=new Ei,Oi=new Ei,Vi=new Ei,Di=new Ei,ki=new Ei,Gi=new Ei,Wi=new Ei,Hi=new Ei,ji=new Ei,qi=new Ei;function $i(e,t,s,i,r){for(let n=0,o=e.length-3;n<=o;n+=3){qi.fromArray(e,n);const o=r.x*Math.abs(qi.x)+r.y*Math.abs(qi.y)+r.z*Math.abs(qi.z),a=t.dot(qi),h=s.dot(qi),l=i.dot(qi);if(Math.max(-Math.max(a,h,l),Math.min(a,h,l))>o)return!1}return!0}const Xi=new Pi,Yi=new Ei,Ji=new Ei;class Zi{constructor(e=new Ei,t=-1){this.isSphere=!0,this.center=e,this.radius=t}set(e,t){return this.center.copy(e),this.radius=t,this}setFromPoints(e,t){const s=this.center;void 0!==t?s.copy(t):Xi.setFromPoints(e).getCenter(s);let i=0;for(let t=0,r=e.length;tthis.radius*this.radius&&(t.sub(this.center).normalize(),t.multiplyScalar(this.radius).add(this.center)),t}getBoundingBox(e){return this.isEmpty()?(e.makeEmpty(),e):(e.set(this.center,this.center),e.expandByScalar(this.radius),e)}applyMatrix4(e){return this.center.applyMatrix4(e),this.radius=this.radius*e.getMaxScaleOnAxis(),this}translate(e){return this.center.add(e),this}expandByPoint(e){if(this.isEmpty())return this.center.copy(e),this.radius=0,this;Yi.subVectors(e,this.center);const t=Yi.lengthSq();if(t>this.radius*this.radius){const e=Math.sqrt(t),s=.5*(e-this.radius);this.center.addScaledVector(Yi,s/e),this.radius+=s}return this}union(e){return e.isEmpty()?this:this.isEmpty()?(this.copy(e),this):(!0===this.center.equals(e.center)?this.radius=Math.max(this.radius,e.radius):(Ji.subVectors(e.center,this.center).setLength(e.radius),this.expandByPoint(Yi.copy(e.center).add(Ji)),this.expandByPoint(Yi.copy(e.center).sub(Ji))),this)}equals(e){return e.center.equals(this.center)&&e.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const Ki=new Ei,Qi=new Ei,er=new Ei,tr=new Ei,sr=new Ei,ir=new Ei,rr=new Ei;class nr{constructor(e=new Ei,t=new Ei(0,0,-1)){this.origin=e,this.direction=t}set(e,t){return this.origin.copy(e),this.direction.copy(t),this}copy(e){return this.origin.copy(e.origin),this.direction.copy(e.direction),this}at(e,t){return t.copy(this.origin).addScaledVector(this.direction,e)}lookAt(e){return this.direction.copy(e).sub(this.origin).normalize(),this}recast(e){return this.origin.copy(this.at(e,Ki)),this}closestPointToPoint(e,t){t.subVectors(e,this.origin);const s=t.dot(this.direction);return s<0?t.copy(this.origin):t.copy(this.origin).addScaledVector(this.direction,s)}distanceToPoint(e){return Math.sqrt(this.distanceSqToPoint(e))}distanceSqToPoint(e){const t=Ki.subVectors(e,this.origin).dot(this.direction);return t<0?this.origin.distanceToSquared(e):(Ki.copy(this.origin).addScaledVector(this.direction,t),Ki.distanceToSquared(e))}distanceSqToSegment(e,t,s,i){Qi.copy(e).add(t).multiplyScalar(.5),er.copy(t).sub(e).normalize(),tr.copy(this.origin).sub(Qi);const r=.5*e.distanceTo(t),n=-this.direction.dot(er),o=tr.dot(this.direction),a=-tr.dot(er),h=tr.lengthSq(),l=Math.abs(1-n*n);let u,c,d,p;if(l>0)if(u=n*a-o,c=n*o-a,p=r*l,u>=0)if(c>=-p)if(c<=p){const e=1/l;u*=e,c*=e,d=u*(u+n*c+2*o)+c*(n*u+c+2*a)+h}else c=r,u=Math.max(0,-(n*c+o)),d=-u*u+c*(c+2*a)+h;else c=-r,u=Math.max(0,-(n*c+o)),d=-u*u+c*(c+2*a)+h;else c<=-p?(u=Math.max(0,-(-n*r+o)),c=u>0?-r:Math.min(Math.max(-r,-a),r),d=-u*u+c*(c+2*a)+h):c<=p?(u=0,c=Math.min(Math.max(-r,-a),r),d=c*(c+2*a)+h):(u=Math.max(0,-(n*r+o)),c=u>0?r:Math.min(Math.max(-r,-a),r),d=-u*u+c*(c+2*a)+h);else c=n>0?-r:r,u=Math.max(0,-(n*c+o)),d=-u*u+c*(c+2*a)+h;return s&&s.copy(this.origin).addScaledVector(this.direction,u),i&&i.copy(Qi).addScaledVector(er,c),d}intersectSphere(e,t){Ki.subVectors(e.center,this.origin);const s=Ki.dot(this.direction),i=Ki.dot(Ki)-s*s,r=e.radius*e.radius;if(i>r)return null;const n=Math.sqrt(r-i),o=s-n,a=s+n;return a<0?null:o<0?this.at(a,t):this.at(o,t)}intersectsSphere(e){return this.distanceSqToPoint(e.center)<=e.radius*e.radius}distanceToPlane(e){const t=e.normal.dot(this.direction);if(0===t)return 0===e.distanceToPoint(this.origin)?0:null;const s=-(this.origin.dot(e.normal)+e.constant)/t;return s>=0?s:null}intersectPlane(e,t){const s=this.distanceToPlane(e);return null===s?null:this.at(s,t)}intersectsPlane(e){const t=e.distanceToPoint(this.origin);if(0===t)return!0;return e.normal.dot(this.direction)*t<0}intersectBox(e,t){let s,i,r,n,o,a;const h=1/this.direction.x,l=1/this.direction.y,u=1/this.direction.z,c=this.origin;return h>=0?(s=(e.min.x-c.x)*h,i=(e.max.x-c.x)*h):(s=(e.max.x-c.x)*h,i=(e.min.x-c.x)*h),l>=0?(r=(e.min.y-c.y)*l,n=(e.max.y-c.y)*l):(r=(e.max.y-c.y)*l,n=(e.min.y-c.y)*l),s>n||r>i?null:((r>s||isNaN(s))&&(s=r),(n=0?(o=(e.min.z-c.z)*u,a=(e.max.z-c.z)*u):(o=(e.max.z-c.z)*u,a=(e.min.z-c.z)*u),s>a||o>i?null:((o>s||s!=s)&&(s=o),(a=0?s:i,t)))}intersectsBox(e){return null!==this.intersectBox(e,Ki)}intersectTriangle(e,t,s,i,r){sr.subVectors(t,e),ir.subVectors(s,e),rr.crossVectors(sr,ir);let n,o=this.direction.dot(rr);if(o>0){if(i)return null;n=1}else{if(!(o<0))return null;n=-1,o=-o}tr.subVectors(this.origin,e);const a=n*this.direction.dot(ir.crossVectors(tr,ir));if(a<0)return null;const h=n*this.direction.dot(sr.cross(tr));if(h<0)return null;if(a+h>o)return null;const l=-n*tr.dot(rr);return l<0?null:this.at(l/o,r)}applyMatrix4(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this}equals(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class or{constructor(e,t,s,i,r,n,o,a,h,l,u,c,d,p,m,g){or.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],void 0!==e&&this.set(e,t,s,i,r,n,o,a,h,l,u,c,d,p,m,g)}set(e,t,s,i,r,n,o,a,h,l,u,c,d,p,m,g){const f=this.elements;return f[0]=e,f[4]=t,f[8]=s,f[12]=i,f[1]=r,f[5]=n,f[9]=o,f[13]=a,f[2]=h,f[6]=l,f[10]=u,f[14]=c,f[3]=d,f[7]=p,f[11]=m,f[15]=g,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 or).fromArray(this.elements)}copy(e){const t=this.elements,s=e.elements;return t[0]=s[0],t[1]=s[1],t[2]=s[2],t[3]=s[3],t[4]=s[4],t[5]=s[5],t[6]=s[6],t[7]=s[7],t[8]=s[8],t[9]=s[9],t[10]=s[10],t[11]=s[11],t[12]=s[12],t[13]=s[13],t[14]=s[14],t[15]=s[15],this}copyPosition(e){const t=this.elements,s=e.elements;return t[12]=s[12],t[13]=s[13],t[14]=s[14],this}setFromMatrix3(e){const t=e.elements;return this.set(t[0],t[3],t[6],0,t[1],t[4],t[7],0,t[2],t[5],t[8],0,0,0,0,1),this}extractBasis(e,t,s){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),s.setFromMatrixColumn(this,2),this}makeBasis(e,t,s){return this.set(e.x,t.x,s.x,0,e.y,t.y,s.y,0,e.z,t.z,s.z,0,0,0,0,1),this}extractRotation(e){const t=this.elements,s=e.elements,i=1/ar.setFromMatrixColumn(e,0).length(),r=1/ar.setFromMatrixColumn(e,1).length(),n=1/ar.setFromMatrixColumn(e,2).length();return t[0]=s[0]*i,t[1]=s[1]*i,t[2]=s[2]*i,t[3]=0,t[4]=s[4]*r,t[5]=s[5]*r,t[6]=s[6]*r,t[7]=0,t[8]=s[8]*n,t[9]=s[9]*n,t[10]=s[10]*n,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromEuler(e){const t=this.elements,s=e.x,i=e.y,r=e.z,n=Math.cos(s),o=Math.sin(s),a=Math.cos(i),h=Math.sin(i),l=Math.cos(r),u=Math.sin(r);if("XYZ"===e.order){const e=n*l,s=n*u,i=o*l,r=o*u;t[0]=a*l,t[4]=-a*u,t[8]=h,t[1]=s+i*h,t[5]=e-r*h,t[9]=-o*a,t[2]=r-e*h,t[6]=i+s*h,t[10]=n*a}else if("YXZ"===e.order){const e=a*l,s=a*u,i=h*l,r=h*u;t[0]=e+r*o,t[4]=i*o-s,t[8]=n*h,t[1]=n*u,t[5]=n*l,t[9]=-o,t[2]=s*o-i,t[6]=r+e*o,t[10]=n*a}else if("ZXY"===e.order){const e=a*l,s=a*u,i=h*l,r=h*u;t[0]=e-r*o,t[4]=-n*u,t[8]=i+s*o,t[1]=s+i*o,t[5]=n*l,t[9]=r-e*o,t[2]=-n*h,t[6]=o,t[10]=n*a}else if("ZYX"===e.order){const e=n*l,s=n*u,i=o*l,r=o*u;t[0]=a*l,t[4]=i*h-s,t[8]=e*h+r,t[1]=a*u,t[5]=r*h+e,t[9]=s*h-i,t[2]=-h,t[6]=o*a,t[10]=n*a}else if("YZX"===e.order){const e=n*a,s=n*h,i=o*a,r=o*h;t[0]=a*l,t[4]=r-e*u,t[8]=i*u+s,t[1]=u,t[5]=n*l,t[9]=-o*l,t[2]=-h*l,t[6]=s*u+i,t[10]=e-r*u}else if("XZY"===e.order){const e=n*a,s=n*h,i=o*a,r=o*h;t[0]=a*l,t[4]=-u,t[8]=h*l,t[1]=e*u+r,t[5]=n*l,t[9]=s*u-i,t[2]=i*u-s,t[6]=o*l,t[10]=r*u+e}return t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromQuaternion(e){return this.compose(lr,e,ur)}lookAt(e,t,s){const i=this.elements;return pr.subVectors(e,t),0===pr.lengthSq()&&(pr.z=1),pr.normalize(),cr.crossVectors(s,pr),0===cr.lengthSq()&&(1===Math.abs(s.z)?pr.x+=1e-4:pr.z+=1e-4,pr.normalize(),cr.crossVectors(s,pr)),cr.normalize(),dr.crossVectors(pr,cr),i[0]=cr.x,i[4]=dr.x,i[8]=pr.x,i[1]=cr.y,i[5]=dr.y,i[9]=pr.y,i[2]=cr.z,i[6]=dr.z,i[10]=pr.z,this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){const s=e.elements,i=t.elements,r=this.elements,n=s[0],o=s[4],a=s[8],h=s[12],l=s[1],u=s[5],c=s[9],d=s[13],p=s[2],m=s[6],g=s[10],f=s[14],y=s[3],x=s[7],b=s[11],v=s[15],T=i[0],_=i[4],w=i[8],S=i[12],M=i[1],A=i[5],N=i[9],R=i[13],C=i[2],E=i[6],B=i[10],I=i[14],P=i[3],F=i[7],z=i[11],U=i[15];return r[0]=n*T+o*M+a*C+h*P,r[4]=n*_+o*A+a*E+h*F,r[8]=n*w+o*N+a*B+h*z,r[12]=n*S+o*R+a*I+h*U,r[1]=l*T+u*M+c*C+d*P,r[5]=l*_+u*A+c*E+d*F,r[9]=l*w+u*N+c*B+d*z,r[13]=l*S+u*R+c*I+d*U,r[2]=p*T+m*M+g*C+f*P,r[6]=p*_+m*A+g*E+f*F,r[10]=p*w+m*N+g*B+f*z,r[14]=p*S+m*R+g*I+f*U,r[3]=y*T+x*M+b*C+v*P,r[7]=y*_+x*A+b*E+v*F,r[11]=y*w+x*N+b*B+v*z,r[15]=y*S+x*R+b*I+v*U,this}multiplyScalar(e){const t=this.elements;return t[0]*=e,t[4]*=e,t[8]*=e,t[12]*=e,t[1]*=e,t[5]*=e,t[9]*=e,t[13]*=e,t[2]*=e,t[6]*=e,t[10]*=e,t[14]*=e,t[3]*=e,t[7]*=e,t[11]*=e,t[15]*=e,this}determinant(){const e=this.elements,t=e[0],s=e[4],i=e[8],r=e[12],n=e[1],o=e[5],a=e[9],h=e[13],l=e[2],u=e[6],c=e[10],d=e[14];return e[3]*(+r*a*u-i*h*u-r*o*c+s*h*c+i*o*d-s*a*d)+e[7]*(+t*a*d-t*h*c+r*n*c-i*n*d+i*h*l-r*a*l)+e[11]*(+t*h*u-t*o*d-r*n*u+s*n*d+r*o*l-s*h*l)+e[15]*(-i*o*l-t*a*u+t*o*c+i*n*u-s*n*c+s*a*l)}transpose(){const e=this.elements;let t;return t=e[1],e[1]=e[4],e[4]=t,t=e[2],e[2]=e[8],e[8]=t,t=e[6],e[6]=e[9],e[9]=t,t=e[3],e[3]=e[12],e[12]=t,t=e[7],e[7]=e[13],e[13]=t,t=e[11],e[11]=e[14],e[14]=t,this}setPosition(e,t,s){const i=this.elements;return e.isVector3?(i[12]=e.x,i[13]=e.y,i[14]=e.z):(i[12]=e,i[13]=t,i[14]=s),this}invert(){const e=this.elements,t=e[0],s=e[1],i=e[2],r=e[3],n=e[4],o=e[5],a=e[6],h=e[7],l=e[8],u=e[9],c=e[10],d=e[11],p=e[12],m=e[13],g=e[14],f=e[15],y=u*g*h-m*c*h+m*a*d-o*g*d-u*a*f+o*c*f,x=p*c*h-l*g*h-p*a*d+n*g*d+l*a*f-n*c*f,b=l*m*h-p*u*h+p*o*d-n*m*d-l*o*f+n*u*f,v=p*u*a-l*m*a-p*o*c+n*m*c+l*o*g-n*u*g,T=t*y+s*x+i*b+r*v;if(0===T)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const _=1/T;return e[0]=y*_,e[1]=(m*c*r-u*g*r-m*i*d+s*g*d+u*i*f-s*c*f)*_,e[2]=(o*g*r-m*a*r+m*i*h-s*g*h-o*i*f+s*a*f)*_,e[3]=(u*a*r-o*c*r-u*i*h+s*c*h+o*i*d-s*a*d)*_,e[4]=x*_,e[5]=(l*g*r-p*c*r+p*i*d-t*g*d-l*i*f+t*c*f)*_,e[6]=(p*a*r-n*g*r-p*i*h+t*g*h+n*i*f-t*a*f)*_,e[7]=(n*c*r-l*a*r+l*i*h-t*c*h-n*i*d+t*a*d)*_,e[8]=b*_,e[9]=(p*u*r-l*m*r-p*s*d+t*m*d+l*s*f-t*u*f)*_,e[10]=(n*m*r-p*o*r+p*s*h-t*m*h-n*s*f+t*o*f)*_,e[11]=(l*o*r-n*u*r-l*s*h+t*u*h+n*s*d-t*o*d)*_,e[12]=v*_,e[13]=(l*m*i-p*u*i+p*s*c-t*m*c-l*s*g+t*u*g)*_,e[14]=(p*o*i-n*m*i-p*s*a+t*m*a+n*s*g-t*o*g)*_,e[15]=(n*u*i-l*o*i+l*s*a-t*u*a-n*s*c+t*o*c)*_,this}scale(e){const t=this.elements,s=e.x,i=e.y,r=e.z;return t[0]*=s,t[4]*=i,t[8]*=r,t[1]*=s,t[5]*=i,t[9]*=r,t[2]*=s,t[6]*=i,t[10]*=r,t[3]*=s,t[7]*=i,t[11]*=r,this}getMaxScaleOnAxis(){const e=this.elements,t=e[0]*e[0]+e[1]*e[1]+e[2]*e[2],s=e[4]*e[4]+e[5]*e[5]+e[6]*e[6],i=e[8]*e[8]+e[9]*e[9]+e[10]*e[10];return Math.sqrt(Math.max(t,s,i))}makeTranslation(e,t,s){return e.isVector3?this.set(1,0,0,e.x,0,1,0,e.y,0,0,1,e.z,0,0,0,1):this.set(1,0,0,e,0,1,0,t,0,0,1,s,0,0,0,1),this}makeRotationX(e){const t=Math.cos(e),s=Math.sin(e);return this.set(1,0,0,0,0,t,-s,0,0,s,t,0,0,0,0,1),this}makeRotationY(e){const t=Math.cos(e),s=Math.sin(e);return this.set(t,0,s,0,0,1,0,0,-s,0,t,0,0,0,0,1),this}makeRotationZ(e){const t=Math.cos(e),s=Math.sin(e);return this.set(t,-s,0,0,s,t,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(e,t){const s=Math.cos(t),i=Math.sin(t),r=1-s,n=e.x,o=e.y,a=e.z,h=r*n,l=r*o;return this.set(h*n+s,h*o-i*a,h*a+i*o,0,h*o+i*a,l*o+s,l*a-i*n,0,h*a-i*o,l*a+i*n,r*a*a+s,0,0,0,0,1),this}makeScale(e,t,s){return this.set(e,0,0,0,0,t,0,0,0,0,s,0,0,0,0,1),this}makeShear(e,t,s,i,r,n){return this.set(1,s,r,0,e,1,n,0,t,i,1,0,0,0,0,1),this}compose(e,t,s){const i=this.elements,r=t._x,n=t._y,o=t._z,a=t._w,h=r+r,l=n+n,u=o+o,c=r*h,d=r*l,p=r*u,m=n*l,g=n*u,f=o*u,y=a*h,x=a*l,b=a*u,v=s.x,T=s.y,_=s.z;return i[0]=(1-(m+f))*v,i[1]=(d+b)*v,i[2]=(p-x)*v,i[3]=0,i[4]=(d-b)*T,i[5]=(1-(c+f))*T,i[6]=(g+y)*T,i[7]=0,i[8]=(p+x)*_,i[9]=(g-y)*_,i[10]=(1-(c+m))*_,i[11]=0,i[12]=e.x,i[13]=e.y,i[14]=e.z,i[15]=1,this}decompose(e,t,s){const i=this.elements;let r=ar.set(i[0],i[1],i[2]).length();const n=ar.set(i[4],i[5],i[6]).length(),o=ar.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),e.x=i[12],e.y=i[13],e.z=i[14],hr.copy(this);const a=1/r,h=1/n,l=1/o;return hr.elements[0]*=a,hr.elements[1]*=a,hr.elements[2]*=a,hr.elements[4]*=h,hr.elements[5]*=h,hr.elements[6]*=h,hr.elements[8]*=l,hr.elements[9]*=l,hr.elements[10]*=l,t.setFromRotationMatrix(hr),s.x=r,s.y=n,s.z=o,this}makePerspective(e,t,s,i,r,n,o=2e3){const a=this.elements,h=2*r/(t-e),l=2*r/(s-i),u=(t+e)/(t-e),c=(s+i)/(s-i);let d,p;if(o===Vs)d=-(n+r)/(n-r),p=-2*n*r/(n-r);else{if(o!==Ds)throw new Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: "+o);d=-n/(n-r),p=-n*r/(n-r)}return a[0]=h,a[4]=0,a[8]=u,a[12]=0,a[1]=0,a[5]=l,a[9]=c,a[13]=0,a[2]=0,a[6]=0,a[10]=d,a[14]=p,a[3]=0,a[7]=0,a[11]=-1,a[15]=0,this}makeOrthographic(e,t,s,i,r,n,o=2e3){const a=this.elements,h=1/(t-e),l=1/(s-i),u=1/(n-r),c=(t+e)*h,d=(s+i)*l;let p,m;if(o===Vs)p=(n+r)*u,m=-2*u;else{if(o!==Ds)throw new Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: "+o);p=r*u,m=-1*u}return a[0]=2*h,a[4]=0,a[8]=0,a[12]=-c,a[1]=0,a[5]=2*l,a[9]=0,a[13]=-d,a[2]=0,a[6]=0,a[10]=m,a[14]=-p,a[3]=0,a[7]=0,a[11]=0,a[15]=1,this}equals(e){const t=this.elements,s=e.elements;for(let e=0;e<16;e++)if(t[e]!==s[e])return!1;return!0}fromArray(e,t=0){for(let s=0;s<16;s++)this.elements[s]=e[s+t];return this}toArray(e=[],t=0){const s=this.elements;return e[t]=s[0],e[t+1]=s[1],e[t+2]=s[2],e[t+3]=s[3],e[t+4]=s[4],e[t+5]=s[5],e[t+6]=s[6],e[t+7]=s[7],e[t+8]=s[8],e[t+9]=s[9],e[t+10]=s[10],e[t+11]=s[11],e[t+12]=s[12],e[t+13]=s[13],e[t+14]=s[14],e[t+15]=s[15],e}}const ar=new Ei,hr=new or,lr=new Ei(0,0,0),ur=new Ei(1,1,1),cr=new Ei,dr=new Ei,pr=new Ei,mr=new or,gr=new Ci;class fr{constructor(e=0,t=0,s=0,i=fr.DEFAULT_ORDER){this.isEuler=!0,this._x=e,this._y=t,this._z=s,this._order=i}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get order(){return this._order}set order(e){this._order=e,this._onChangeCallback()}set(e,t,s,i=this._order){return this._x=e,this._y=t,this._z=s,this._order=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(e){return this._x=e._x,this._y=e._y,this._z=e._z,this._order=e._order,this._onChangeCallback(),this}setFromRotationMatrix(e,t=this._order,s=!0){const i=e.elements,r=i[0],n=i[4],o=i[8],a=i[1],h=i[5],l=i[9],u=i[2],c=i[6],d=i[10];switch(t){case"XYZ":this._y=Math.asin($s(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-l,d),this._z=Math.atan2(-n,r)):(this._x=Math.atan2(c,h),this._z=0);break;case"YXZ":this._x=Math.asin(-$s(l,-1,1)),Math.abs(l)<.9999999?(this._y=Math.atan2(o,d),this._z=Math.atan2(a,h)):(this._y=Math.atan2(-u,r),this._z=0);break;case"ZXY":this._x=Math.asin($s(c,-1,1)),Math.abs(c)<.9999999?(this._y=Math.atan2(-u,d),this._z=Math.atan2(-n,h)):(this._y=0,this._z=Math.atan2(a,r));break;case"ZYX":this._y=Math.asin(-$s(u,-1,1)),Math.abs(u)<.9999999?(this._x=Math.atan2(c,d),this._z=Math.atan2(a,r)):(this._x=0,this._z=Math.atan2(-n,h));break;case"YZX":this._z=Math.asin($s(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(-l,h),this._y=Math.atan2(-u,r)):(this._x=0,this._y=Math.atan2(o,d));break;case"XZY":this._z=Math.asin(-$s(n,-1,1)),Math.abs(n)<.9999999?(this._x=Math.atan2(c,h),this._y=Math.atan2(o,r)):(this._x=Math.atan2(-l,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+t)}return this._order=t,!0===s&&this._onChangeCallback(),this}setFromQuaternion(e,t,s){return mr.makeRotationFromQuaternion(e),this.setFromRotationMatrix(mr,t,s)}setFromVector3(e,t=this._order){return this.set(e.x,e.y,e.z,t)}reorder(e){return gr.setFromEuler(this),this.setFromQuaternion(gr,e)}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._order===this._order}fromArray(e){return this._x=e[0],this._y=e[1],this._z=e[2],void 0!==e[3]&&(this._order=e[3]),this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._order,e}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}fr.DEFAULT_ORDER="XYZ";class yr{constructor(){this.mask=1}set(e){this.mask=(1<>>0}enable(e){this.mask|=1<1){for(let e=0;e1){for(let e=0;e0&&(i.userData=this.userData),i.layers=this.layers.mask,i.matrix=this.matrix.toArray(),i.up=this.up.toArray(),!1===this.matrixAutoUpdate&&(i.matrixAutoUpdate=!1),this.isInstancedMesh&&(i.type="InstancedMesh",i.count=this.count,i.instanceMatrix=this.instanceMatrix.toJSON(),null!==this.instanceColor&&(i.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(i.type="BatchedMesh",i.perObjectFrustumCulled=this.perObjectFrustumCulled,i.sortObjects=this.sortObjects,i.drawRanges=this._drawRanges,i.reservedRanges=this._reservedRanges,i.visibility=this._visibility,i.active=this._active,i.bounds=this._bounds.map((e=>({boxInitialized:e.boxInitialized,boxMin:e.box.min.toArray(),boxMax:e.box.max.toArray(),sphereInitialized:e.sphereInitialized,sphereRadius:e.sphere.radius,sphereCenter:e.sphere.center.toArray()}))),i.maxInstanceCount=this._maxInstanceCount,i.maxVertexCount=this._maxVertexCount,i.maxIndexCount=this._maxIndexCount,i.geometryInitialized=this._geometryInitialized,i.geometryCount=this._geometryCount,i.matricesTexture=this._matricesTexture.toJSON(e),null!==this._colorsTexture&&(i.colorsTexture=this._colorsTexture.toJSON(e)),null!==this.boundingSphere&&(i.boundingSphere={center:i.boundingSphere.center.toArray(),radius:i.boundingSphere.radius}),null!==this.boundingBox&&(i.boundingBox={min:i.boundingBox.min.toArray(),max:i.boundingBox.max.toArray()})),this.isScene)this.background&&(this.background.isColor?i.background=this.background.toJSON():this.background.isTexture&&(i.background=this.background.toJSON(e).uuid)),this.environment&&this.environment.isTexture&&!0!==this.environment.isRenderTargetTexture&&(i.environment=this.environment.toJSON(e).uuid);else if(this.isMesh||this.isLine||this.isPoints){i.geometry=r(e.geometries,this.geometry);const t=this.geometry.parameters;if(void 0!==t&&void 0!==t.shapes){const s=t.shapes;if(Array.isArray(s))for(let t=0,i=s.length;t0){i.children=[];for(let t=0;t0){i.animations=[];for(let t=0;t0&&(s.geometries=t),i.length>0&&(s.materials=i),r.length>0&&(s.textures=r),o.length>0&&(s.images=o),a.length>0&&(s.shapes=a),h.length>0&&(s.skeletons=h),l.length>0&&(s.animations=l),u.length>0&&(s.nodes=u)}return s.object=i,s;function n(e){const t=[];for(const s in e){const i=e[s];delete i.metadata,t.push(i)}return t}}clone(e){return(new this.constructor).copy(this,e)}copy(e,t=!0){if(this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.rotation.order=e.rotation.order,this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldAutoUpdate=e.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=e.matrixWorldNeedsUpdate,this.layers.mask=e.layers.mask,this.visible=e.visible,this.castShadow=e.castShadow,this.receiveShadow=e.receiveShadow,this.frustumCulled=e.frustumCulled,this.renderOrder=e.renderOrder,this.animations=e.animations.slice(),this.userData=JSON.parse(JSON.stringify(e.userData)),!0===t)for(let t=0;t0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(e,t,s,i,r){Fr.subVectors(i,t),zr.subVectors(s,t),Ur.subVectors(e,t);const n=Fr.dot(Fr),o=Fr.dot(zr),a=Fr.dot(Ur),h=zr.dot(zr),l=zr.dot(Ur),u=n*h-o*o;if(0===u)return r.set(0,0,0),null;const c=1/u,d=(h*a-o*l)*c,p=(n*l-o*a)*c;return r.set(1-d-p,p,d)}static containsPoint(e,t,s,i){return null!==this.getBarycoord(e,t,s,i,Lr)&&(Lr.x>=0&&Lr.y>=0&&Lr.x+Lr.y<=1)}static getInterpolation(e,t,s,i,r,n,o,a){return null===this.getBarycoord(e,t,s,i,Lr)?(a.x=0,a.y=0,"z"in a&&(a.z=0),"w"in a&&(a.w=0),null):(a.setScalar(0),a.addScaledVector(r,Lr.x),a.addScaledVector(n,Lr.y),a.addScaledVector(o,Lr.z),a)}static isFrontFacing(e,t,s,i){return Fr.subVectors(s,t),zr.subVectors(e,t),Fr.cross(zr).dot(i)<0}set(e,t,s){return this.a.copy(e),this.b.copy(t),this.c.copy(s),this}setFromPointsAndIndices(e,t,s,i){return this.a.copy(e[t]),this.b.copy(e[s]),this.c.copy(e[i]),this}setFromAttributeAndIndices(e,t,s,i){return this.a.fromBufferAttribute(e,t),this.b.fromBufferAttribute(e,s),this.c.fromBufferAttribute(e,i),this}clone(){return(new this.constructor).copy(this)}copy(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this}getArea(){return Fr.subVectors(this.c,this.b),zr.subVectors(this.a,this.b),.5*Fr.cross(zr).length()}getMidpoint(e){return e.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(e){return Hr.getNormal(this.a,this.b,this.c,e)}getPlane(e){return e.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(e,t){return Hr.getBarycoord(e,this.a,this.b,this.c,t)}getInterpolation(e,t,s,i,r){return Hr.getInterpolation(e,this.a,this.b,this.c,t,s,i,r)}containsPoint(e){return Hr.containsPoint(e,this.a,this.b,this.c)}isFrontFacing(e){return Hr.isFrontFacing(this.a,this.b,this.c,e)}intersectsBox(e){return e.intersectsTriangle(this)}closestPointToPoint(e,t){const s=this.a,i=this.b,r=this.c;let n,o;Or.subVectors(i,s),Vr.subVectors(r,s),kr.subVectors(e,s);const a=Or.dot(kr),h=Vr.dot(kr);if(a<=0&&h<=0)return t.copy(s);Gr.subVectors(e,i);const l=Or.dot(Gr),u=Vr.dot(Gr);if(l>=0&&u<=l)return t.copy(i);const c=a*u-l*h;if(c<=0&&a>=0&&l<=0)return n=a/(a-l),t.copy(s).addScaledVector(Or,n);Wr.subVectors(e,r);const d=Or.dot(Wr),p=Vr.dot(Wr);if(p>=0&&d<=p)return t.copy(r);const m=d*h-a*p;if(m<=0&&h>=0&&p<=0)return o=h/(h-p),t.copy(s).addScaledVector(Vr,o);const g=l*p-d*u;if(g<=0&&u-l>=0&&d-p>=0)return Dr.subVectors(r,i),o=(u-l)/(u-l+(d-p)),t.copy(i).addScaledVector(Dr,o);const f=1/(g+m+c);return n=m*f,o=c*f,t.copy(s).addScaledVector(Or,n).addScaledVector(Vr,o)}equals(e){return e.a.equals(this.a)&&e.b.equals(this.b)&&e.c.equals(this.c)}}const jr={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},qr={h:0,s:0,l:0},$r={h:0,s:0,l:0};function Xr(e,t,s){return s<0&&(s+=1),s>1&&(s-=1),s<1/6?e+6*(t-e)*s:s<.5?t:s<2/3?e+6*(t-e)*(2/3-s):e}class Yr{constructor(e,t,s){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(e,t,s)}set(e,t,s){if(void 0===t&&void 0===s){const t=e;t&&t.isColor?this.copy(t):"number"==typeof t?this.setHex(t):"string"==typeof t&&this.setStyle(t)}else this.setRGB(e,t,s);return this}setScalar(e){return this.r=e,this.g=e,this.b=e,this}setHex(e,t=Jt){return e=Math.floor(e),this.r=(e>>16&255)/255,this.g=(e>>8&255)/255,this.b=(255&e)/255,di.toWorkingColorSpace(this,t),this}setRGB(e,t,s,i=di.workingColorSpace){return this.r=e,this.g=t,this.b=s,di.toWorkingColorSpace(this,i),this}setHSL(e,t,s,i=di.workingColorSpace){if(e=Xs(e,1),t=$s(t,0,1),s=$s(s,0,1),0===t)this.r=this.g=this.b=s;else{const i=s<=.5?s*(1+t):s+t-s*t,r=2*s-i;this.r=Xr(r,i,e+1/3),this.g=Xr(r,i,e),this.b=Xr(r,i,e-1/3)}return di.toWorkingColorSpace(this,i),this}setStyle(e,t=Jt){function s(t){void 0!==t&&parseFloat(t)<1&&console.warn("THREE.Color: Alpha component of "+e+" will be ignored.")}let i;if(i=/^(\w+)\(([^\)]*)\)/.exec(e)){let r;const n=i[1],o=i[2];switch(n){case"rgb":case"rgba":if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return s(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,t);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return s(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,t);break;case"hsl":case"hsla":if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return s(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,t);break;default:console.warn("THREE.Color: Unknown color model "+e)}}else if(i=/^\#([A-Fa-f\d]+)$/.exec(e)){const s=i[1],r=s.length;if(3===r)return this.setRGB(parseInt(s.charAt(0),16)/15,parseInt(s.charAt(1),16)/15,parseInt(s.charAt(2),16)/15,t);if(6===r)return this.setHex(parseInt(s,16),t);console.warn("THREE.Color: Invalid hex color "+e)}else if(e&&e.length>0)return this.setColorName(e,t);return this}setColorName(e,t=Jt){const s=jr[e.toLowerCase()];return void 0!==s?this.setHex(s,t):console.warn("THREE.Color: Unknown color "+e),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(e){return this.r=e.r,this.g=e.g,this.b=e.b,this}copySRGBToLinear(e){return this.r=pi(e.r),this.g=pi(e.g),this.b=pi(e.b),this}copyLinearToSRGB(e){return this.r=mi(e.r),this.g=mi(e.g),this.b=mi(e.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(e=Jt){return di.fromWorkingColorSpace(Jr.copy(this),e),65536*Math.round($s(255*Jr.r,0,255))+256*Math.round($s(255*Jr.g,0,255))+Math.round($s(255*Jr.b,0,255))}getHexString(e=Jt){return("000000"+this.getHex(e).toString(16)).slice(-6)}getHSL(e,t=di.workingColorSpace){di.fromWorkingColorSpace(Jr.copy(this),t);const s=Jr.r,i=Jr.g,r=Jr.b,n=Math.max(s,i,r),o=Math.min(s,i,r);let a,h;const l=(o+n)/2;if(o===n)a=0,h=0;else{const e=n-o;switch(h=l<=.5?e/(n+o):e/(2-n-o),n){case s:a=(i-r)/e+(i0!=e>0&&this.version++,this._alphaTest=e}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(e){if(void 0!==e)for(const t in e){const s=e[t];if(void 0===s){console.warn(`THREE.Material: parameter '${t}' has value of undefined.`);continue}const i=this[t];void 0!==i?i&&i.isColor?i.set(s):i&&i.isVector3&&s&&s.isVector3?i.copy(s):this[t]=s:console.warn(`THREE.Material: '${t}' is not a property of THREE.${this.type}.`)}}toJSON(e){const t=void 0===e||"string"==typeof e;t&&(e={textures:{},images:{}});const s={metadata:{version:4.6,type:"Material",generator:"Material.toJSON"}};function i(e){const t=[];for(const s in e){const i=e[s];delete i.metadata,t.push(i)}return t}if(s.uuid=this.uuid,s.type=this.type,""!==this.name&&(s.name=this.name),this.color&&this.color.isColor&&(s.color=this.color.getHex()),void 0!==this.roughness&&(s.roughness=this.roughness),void 0!==this.metalness&&(s.metalness=this.metalness),void 0!==this.sheen&&(s.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(s.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(s.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(s.emissive=this.emissive.getHex()),void 0!==this.emissiveIntensity&&1!==this.emissiveIntensity&&(s.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(s.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(s.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(s.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(s.shininess=this.shininess),void 0!==this.clearcoat&&(s.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(s.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(s.clearcoatMap=this.clearcoatMap.toJSON(e).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(s.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(e).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(s.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(e).uuid,s.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.dispersion&&(s.dispersion=this.dispersion),void 0!==this.iridescence&&(s.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(s.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(s.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(s.iridescenceMap=this.iridescenceMap.toJSON(e).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(s.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(e).uuid),void 0!==this.anisotropy&&(s.anisotropy=this.anisotropy),void 0!==this.anisotropyRotation&&(s.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(s.anisotropyMap=this.anisotropyMap.toJSON(e).uuid),this.map&&this.map.isTexture&&(s.map=this.map.toJSON(e).uuid),this.matcap&&this.matcap.isTexture&&(s.matcap=this.matcap.toJSON(e).uuid),this.alphaMap&&this.alphaMap.isTexture&&(s.alphaMap=this.alphaMap.toJSON(e).uuid),this.lightMap&&this.lightMap.isTexture&&(s.lightMap=this.lightMap.toJSON(e).uuid,s.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(s.aoMap=this.aoMap.toJSON(e).uuid,s.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(s.bumpMap=this.bumpMap.toJSON(e).uuid,s.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(s.normalMap=this.normalMap.toJSON(e).uuid,s.normalMapType=this.normalMapType,s.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(s.displacementMap=this.displacementMap.toJSON(e).uuid,s.displacementScale=this.displacementScale,s.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(s.roughnessMap=this.roughnessMap.toJSON(e).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(s.metalnessMap=this.metalnessMap.toJSON(e).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(s.emissiveMap=this.emissiveMap.toJSON(e).uuid),this.specularMap&&this.specularMap.isTexture&&(s.specularMap=this.specularMap.toJSON(e).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(s.specularIntensityMap=this.specularIntensityMap.toJSON(e).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(s.specularColorMap=this.specularColorMap.toJSON(e).uuid),this.envMap&&this.envMap.isTexture&&(s.envMap=this.envMap.toJSON(e).uuid,void 0!==this.combine&&(s.combine=this.combine)),void 0!==this.envMapRotation&&(s.envMapRotation=this.envMapRotation.toArray()),void 0!==this.envMapIntensity&&(s.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(s.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(s.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(s.gradientMap=this.gradientMap.toJSON(e).uuid),void 0!==this.transmission&&(s.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(s.transmissionMap=this.transmissionMap.toJSON(e).uuid),void 0!==this.thickness&&(s.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(s.thicknessMap=this.thicknessMap.toJSON(e).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(s.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(s.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(s.size=this.size),null!==this.shadowSide&&(s.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(s.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(s.blending=this.blending),this.side!==c&&(s.side=this.side),!0===this.vertexColors&&(s.vertexColors=!0),this.opacity<1&&(s.opacity=this.opacity),!0===this.transparent&&(s.transparent=!0),this.blendSrc!==C&&(s.blendSrc=this.blendSrc),this.blendDst!==E&&(s.blendDst=this.blendDst),this.blendEquation!==v&&(s.blendEquation=this.blendEquation),null!==this.blendSrcAlpha&&(s.blendSrcAlpha=this.blendSrcAlpha),null!==this.blendDstAlpha&&(s.blendDstAlpha=this.blendDstAlpha),null!==this.blendEquationAlpha&&(s.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&&this.blendColor.isColor&&(s.blendColor=this.blendColor.getHex()),0!==this.blendAlpha&&(s.blendAlpha=this.blendAlpha),3!==this.depthFunc&&(s.depthFunc=this.depthFunc),!1===this.depthTest&&(s.depthTest=this.depthTest),!1===this.depthWrite&&(s.depthWrite=this.depthWrite),!1===this.colorWrite&&(s.colorWrite=this.colorWrite),255!==this.stencilWriteMask&&(s.stencilWriteMask=this.stencilWriteMask),this.stencilFunc!==bs&&(s.stencilFunc=this.stencilFunc),0!==this.stencilRef&&(s.stencilRef=this.stencilRef),255!==this.stencilFuncMask&&(s.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==ns&&(s.stencilFail=this.stencilFail),this.stencilZFail!==ns&&(s.stencilZFail=this.stencilZFail),this.stencilZPass!==ns&&(s.stencilZPass=this.stencilZPass),!0===this.stencilWrite&&(s.stencilWrite=this.stencilWrite),void 0!==this.rotation&&0!==this.rotation&&(s.rotation=this.rotation),!0===this.polygonOffset&&(s.polygonOffset=!0),0!==this.polygonOffsetFactor&&(s.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(s.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(s.linewidth=this.linewidth),void 0!==this.dashSize&&(s.dashSize=this.dashSize),void 0!==this.gapSize&&(s.gapSize=this.gapSize),void 0!==this.scale&&(s.scale=this.scale),!0===this.dithering&&(s.dithering=!0),this.alphaTest>0&&(s.alphaTest=this.alphaTest),!0===this.alphaHash&&(s.alphaHash=!0),!0===this.alphaToCoverage&&(s.alphaToCoverage=!0),!0===this.premultipliedAlpha&&(s.premultipliedAlpha=!0),!0===this.forceSinglePass&&(s.forceSinglePass=!0),!0===this.wireframe&&(s.wireframe=!0),this.wireframeLinewidth>1&&(s.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(s.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(s.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(s.flatShading=!0),!1===this.visible&&(s.visible=!1),!1===this.toneMapped&&(s.toneMapped=!1),!1===this.fog&&(s.fog=!1),Object.keys(this.userData).length>0&&(s.userData=this.userData),t){const t=i(e.textures),r=i(e.images);t.length>0&&(s.textures=t),r.length>0&&(s.images=r)}return s}clone(){return(new this.constructor).copy(this)}copy(e){this.name=e.name,this.blending=e.blending,this.side=e.side,this.vertexColors=e.vertexColors,this.opacity=e.opacity,this.transparent=e.transparent,this.blendSrc=e.blendSrc,this.blendDst=e.blendDst,this.blendEquation=e.blendEquation,this.blendSrcAlpha=e.blendSrcAlpha,this.blendDstAlpha=e.blendDstAlpha,this.blendEquationAlpha=e.blendEquationAlpha,this.blendColor.copy(e.blendColor),this.blendAlpha=e.blendAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.stencilWriteMask=e.stencilWriteMask,this.stencilFunc=e.stencilFunc,this.stencilRef=e.stencilRef,this.stencilFuncMask=e.stencilFuncMask,this.stencilFail=e.stencilFail,this.stencilZFail=e.stencilZFail,this.stencilZPass=e.stencilZPass,this.stencilWrite=e.stencilWrite;const t=e.clippingPlanes;let s=null;if(null!==t){const e=t.length;s=new Array(e);for(let i=0;i!==e;++i)s[i]=t[i].clone()}return this.clippingPlanes=s,this.clipIntersection=e.clipIntersection,this.clipShadows=e.clipShadows,this.shadowSide=e.shadowSide,this.colorWrite=e.colorWrite,this.precision=e.precision,this.polygonOffset=e.polygonOffset,this.polygonOffsetFactor=e.polygonOffsetFactor,this.polygonOffsetUnits=e.polygonOffsetUnits,this.dithering=e.dithering,this.alphaTest=e.alphaTest,this.alphaHash=e.alphaHash,this.alphaToCoverage=e.alphaToCoverage,this.premultipliedAlpha=e.premultipliedAlpha,this.forceSinglePass=e.forceSinglePass,this.visible=e.visible,this.toneMapped=e.toneMapped,this.userData=JSON.parse(JSON.stringify(e.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(e){!0===e&&this.version++}onBuild(){console.warn("Material: onBuild() has been removed.")}}class Qr extends Kr{constructor(e){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new Yr(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.envMapRotation=new fr,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(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.fog=e.fog,this}}const en=tn();function tn(){const e=new ArrayBuffer(4),t=new Float32Array(e),s=new Uint32Array(e),i=new Uint32Array(512),r=new Uint32Array(512);for(let e=0;e<256;++e){const t=e-127;t<-27?(i[e]=0,i[256|e]=32768,r[e]=24,r[256|e]=24):t<-14?(i[e]=1024>>-t-14,i[256|e]=1024>>-t-14|32768,r[e]=-t-1,r[256|e]=-t-1):t<=15?(i[e]=t+15<<10,i[256|e]=t+15<<10|32768,r[e]=13,r[256|e]=13):t<128?(i[e]=31744,i[256|e]=64512,r[e]=24,r[256|e]=24):(i[e]=31744,i[256|e]=64512,r[e]=13,r[256|e]=13)}const n=new Uint32Array(2048),o=new Uint32Array(64),a=new Uint32Array(64);for(let e=1;e<1024;++e){let t=e<<13,s=0;for(;0==(8388608&t);)t<<=1,s-=8388608;t&=-8388609,s+=947912704,n[e]=t|s}for(let e=1024;e<2048;++e)n[e]=939524096+(e-1024<<13);for(let e=1;e<31;++e)o[e]=e<<23;o[31]=1199570944,o[32]=2147483648;for(let e=33;e<63;++e)o[e]=2147483648+(e-32<<23);o[63]=3347054592;for(let e=1;e<64;++e)32!==e&&(a[e]=1024);return{floatView:t,uint32View:s,baseTable:i,shiftTable:r,mantissaTable:n,exponentTable:o,offsetTable:a}}function sn(e){Math.abs(e)>65504&&console.warn("THREE.DataUtils.toHalfFloat(): Value out of range."),e=$s(e,-65504,65504),en.floatView[0]=e;const t=en.uint32View[0],s=t>>23&511;return en.baseTable[s]+((8388607&t)>>en.shiftTable[s])}function rn(e){const t=e>>10;return en.uint32View[0]=en.mantissaTable[en.offsetTable[t]+(1023&e)]+en.exponentTable[t],en.floatView[0]}const nn={toHalfFloat:sn,fromHalfFloat:rn},on=new Ei,an=new Qs;class hn{constructor(e,t,s=!1){if(Array.isArray(e))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=e,this.itemSize=t,this.count=void 0!==e?e.length/t:0,this.normalized=s,this.usage=Rs,this._updateRange={offset:0,count:-1},this.updateRanges=[],this.gpuType=Ie,this.version=0}onUploadCallback(){}set needsUpdate(e){!0===e&&this.version++}get updateRange(){return ai("THREE.BufferAttribute: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead."),this._updateRange}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.name=e.name,this.array=new e.array.constructor(e.array),this.itemSize=e.itemSize,this.count=e.count,this.normalized=e.normalized,this.usage=e.usage,this.gpuType=e.gpuType,this}copyAt(e,t,s){e*=this.itemSize,s*=t.itemSize;for(let i=0,r=this.itemSize;i=0;--t)if(e[t]>=65535)return!0;return!1}(e)?gn:pn)(e,1):this.index=e,this}getAttribute(e){return this.attributes[e]}setAttribute(e,t){return this.attributes[e]=t,this}deleteAttribute(e){return delete this.attributes[e],this}hasAttribute(e){return void 0!==this.attributes[e]}addGroup(e,t,s=0){this.groups.push({start:e,count:t,materialIndex:s})}clearGroups(){this.groups=[]}setDrawRange(e,t){this.drawRange.start=e,this.drawRange.count=t}applyMatrix4(e){const t=this.attributes.position;void 0!==t&&(t.applyMatrix4(e),t.needsUpdate=!0);const s=this.attributes.normal;if(void 0!==s){const t=(new ei).getNormalMatrix(e);s.applyNormalMatrix(t),s.needsUpdate=!0}const i=this.attributes.tangent;return void 0!==i&&(i.transformDirection(e),i.needsUpdate=!0),null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this}applyQuaternion(e){return bn.makeRotationFromQuaternion(e),this.applyMatrix4(bn),this}rotateX(e){return bn.makeRotationX(e),this.applyMatrix4(bn),this}rotateY(e){return bn.makeRotationY(e),this.applyMatrix4(bn),this}rotateZ(e){return bn.makeRotationZ(e),this.applyMatrix4(bn),this}translate(e,t,s){return bn.makeTranslation(e,t,s),this.applyMatrix4(bn),this}scale(e,t,s){return bn.makeScale(e,t,s),this.applyMatrix4(bn),this}lookAt(e){return vn.lookAt(e),vn.updateMatrix(),this.applyMatrix4(vn.matrix),this}center(){return this.computeBoundingBox(),this.boundingBox.getCenter(Tn).negate(),this.translate(Tn.x,Tn.y,Tn.z),this}setFromPoints(e){const t=[];for(let s=0,i=e.length;s0&&(e.userData=this.userData),void 0!==this.parameters){const t=this.parameters;for(const s in t)void 0!==t[s]&&(e[s]=t[s]);return e}e.data={attributes:{}};const t=this.index;null!==t&&(e.data.index={type:t.array.constructor.name,array:Array.prototype.slice.call(t.array)});const s=this.attributes;for(const t in s){const i=s[t];e.data.attributes[t]=i.toJSON(e.data)}const i={};let r=!1;for(const t in this.morphAttributes){const s=this.morphAttributes[t],n=[];for(let t=0,i=s.length;t0&&(i[t]=n,r=!0)}r&&(e.data.morphAttributes=i,e.data.morphTargetsRelative=this.morphTargetsRelative);const n=this.groups;n.length>0&&(e.data.groups=JSON.parse(JSON.stringify(n)));const o=this.boundingSphere;return null!==o&&(e.data.boundingSphere={center:o.center.toArray(),radius:o.radius}),e}clone(){return(new this.constructor).copy(this)}copy(e){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const t={};this.name=e.name;const s=e.index;null!==s&&this.setIndex(s.clone(t));const i=e.attributes;for(const e in i){const s=i[e];this.setAttribute(e,s.clone(t))}const r=e.morphAttributes;for(const e in r){const s=[],i=r[e];for(let e=0,r=i.length;e0){const s=e[t[0]];if(void 0!==s){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=s.length;e(e.far-e.near)**2)return}An.copy(r).invert(),Nn.copy(e.ray).applyMatrix4(An),null!==s.boundingBox&&!1===Nn.intersectsBox(s.boundingBox)||this._computeIntersections(e,t,Nn)}}_computeIntersections(e,t,s){let i;const r=this.geometry,n=this.material,o=r.index,a=r.attributes.position,h=r.attributes.uv,l=r.attributes.uv1,u=r.attributes.normal,c=r.groups,d=r.drawRange;if(null!==o)if(Array.isArray(n))for(let r=0,a=c.length;rs.far?null:{distance:l,point:Gn.clone(),object:e}}(e,t,s,i,En,Bn,In,kn);if(u){r&&(zn.fromBufferAttribute(r,a),Un.fromBufferAttribute(r,h),Ln.fromBufferAttribute(r,l),u.uv=Hr.getInterpolation(kn,En,Bn,In,zn,Un,Ln,new Qs)),n&&(zn.fromBufferAttribute(n,a),Un.fromBufferAttribute(n,h),Ln.fromBufferAttribute(n,l),u.uv1=Hr.getInterpolation(kn,En,Bn,In,zn,Un,Ln,new Qs)),o&&(On.fromBufferAttribute(o,a),Vn.fromBufferAttribute(o,h),Dn.fromBufferAttribute(o,l),u.normal=Hr.getInterpolation(kn,En,Bn,In,On,Vn,Dn,new Ei),u.normal.dot(i.direction)>0&&u.normal.multiplyScalar(-1));const e={a:a,b:h,c:l,normal:new Ei,materialIndex:0};Hr.getNormal(En,Bn,In,e.normal),u.face=e}return u}class jn extends Mn{constructor(e=1,t=1,s=1,i=1,r=1,n=1){super(),this.type="BoxGeometry",this.parameters={width:e,height:t,depth:s,widthSegments:i,heightSegments:r,depthSegments:n};const o=this;i=Math.floor(i),r=Math.floor(r),n=Math.floor(n);const a=[],h=[],l=[],u=[];let c=0,d=0;function p(e,t,s,i,r,n,p,m,g,f,y){const x=n/g,b=p/f,v=n/2,T=p/2,_=m/2,w=g+1,S=f+1;let M=0,A=0;const N=new Ei;for(let n=0;n0?1:-1,l.push(N.x,N.y,N.z),u.push(a/g),u.push(1-n/f),M+=1}}for(let e=0;e0&&(t.defines=this.defines),t.vertexShader=this.vertexShader,t.fragmentShader=this.fragmentShader,t.lights=this.lights,t.clipping=this.clipping;const s={};for(const e in this.extensions)!0===this.extensions[e]&&(s[e]=!0);return Object.keys(s).length>0&&(t.extensions=s),t}}class Xn extends Pr{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new or,this.projectionMatrix=new or,this.projectionMatrixInverse=new or,this.coordinateSystem=Vs}copy(e,t){return super.copy(e,t),this.matrixWorldInverse.copy(e.matrixWorldInverse),this.projectionMatrix.copy(e.projectionMatrix),this.projectionMatrixInverse.copy(e.projectionMatrixInverse),this.coordinateSystem=e.coordinateSystem,this}getWorldDirection(e){return super.getWorldDirection(e).negate()}updateMatrixWorld(e){super.updateMatrixWorld(e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(e,t){super.updateWorldMatrix(e,t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}const Yn=new Ei,Jn=new Qs,Zn=new Qs;class Kn extends Xn{constructor(e=50,t=1,s=.1,i=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=e,this.zoom=1,this.near=s,this.far=i,this.focus=10,this.aspect=t,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(e,t){return super.copy(e,t),this.fov=e.fov,this.zoom=e.zoom,this.near=e.near,this.far=e.far,this.focus=e.focus,this.aspect=e.aspect,this.view=null===e.view?null:Object.assign({},e.view),this.filmGauge=e.filmGauge,this.filmOffset=e.filmOffset,this}setFocalLength(e){const t=.5*this.getFilmHeight()/e;this.fov=2*js*Math.atan(t),this.updateProjectionMatrix()}getFocalLength(){const e=Math.tan(.5*Hs*this.fov);return.5*this.getFilmHeight()/e}getEffectiveFOV(){return 2*js*Math.atan(Math.tan(.5*Hs*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}getViewBounds(e,t,s){Yn.set(-1,-1,.5).applyMatrix4(this.projectionMatrixInverse),t.set(Yn.x,Yn.y).multiplyScalar(-e/Yn.z),Yn.set(1,1,.5).applyMatrix4(this.projectionMatrixInverse),s.set(Yn.x,Yn.y).multiplyScalar(-e/Yn.z)}getViewSize(e,t){return this.getViewBounds(e,Jn,Zn),t.subVectors(Zn,Jn)}setViewOffset(e,t,s,i,r,n){this.aspect=e/t,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=e,this.view.fullHeight=t,this.view.offsetX=s,this.view.offsetY=i,this.view.width=r,this.view.height=n,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const e=this.near;let t=e*Math.tan(.5*Hs*this.fov)/this.zoom,s=2*t,i=this.aspect*s,r=-.5*i;const n=this.view;if(null!==this.view&&this.view.enabled){const e=n.fullWidth,o=n.fullHeight;r+=n.offsetX*i/e,t-=n.offsetY*s/o,i*=n.width/e,s*=n.height/o}const o=this.filmOffset;0!==o&&(r+=e*o/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,t,t-s,e,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(e){const t=super.toJSON(e);return t.object.fov=this.fov,t.object.zoom=this.zoom,t.object.near=this.near,t.object.far=this.far,t.object.focus=this.focus,t.object.aspect=this.aspect,null!==this.view&&(t.object.view=Object.assign({},this.view)),t.object.filmGauge=this.filmGauge,t.object.filmOffset=this.filmOffset,t}}const Qn=-90;class eo extends Pr{constructor(e,t,s){super(),this.type="CubeCamera",this.renderTarget=s,this.coordinateSystem=null,this.activeMipmapLevel=0;const i=new Kn(Qn,1,e,t);i.layers=this.layers,this.add(i);const r=new Kn(Qn,1,e,t);r.layers=this.layers,this.add(r);const n=new Kn(Qn,1,e,t);n.layers=this.layers,this.add(n);const o=new Kn(Qn,1,e,t);o.layers=this.layers,this.add(o);const a=new Kn(Qn,1,e,t);a.layers=this.layers,this.add(a);const h=new Kn(Qn,1,e,t);h.layers=this.layers,this.add(h)}updateCoordinateSystem(){const e=this.coordinateSystem,t=this.children.concat(),[s,i,r,n,o,a]=t;for(const e of t)this.remove(e);if(e===Vs)s.up.set(0,1,0),s.lookAt(1,0,0),i.up.set(0,1,0),i.lookAt(-1,0,0),r.up.set(0,0,-1),r.lookAt(0,1,0),n.up.set(0,0,1),n.lookAt(0,-1,0),o.up.set(0,1,0),o.lookAt(0,0,1),a.up.set(0,1,0),a.lookAt(0,0,-1);else{if(e!==Ds)throw new Error("THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: "+e);s.up.set(0,-1,0),s.lookAt(-1,0,0),i.up.set(0,-1,0),i.lookAt(1,0,0),r.up.set(0,0,1),r.lookAt(0,1,0),n.up.set(0,0,-1),n.lookAt(0,-1,0),o.up.set(0,-1,0),o.lookAt(0,0,1),a.up.set(0,-1,0),a.lookAt(0,0,-1)}for(const e of t)this.add(e),e.updateMatrixWorld()}update(e,t){null===this.parent&&this.updateMatrixWorld();const{renderTarget:s,activeMipmapLevel:i}=this;this.coordinateSystem!==e.coordinateSystem&&(this.coordinateSystem=e.coordinateSystem,this.updateCoordinateSystem());const[r,n,o,a,h,l]=this.children,u=e.getRenderTarget(),c=e.getActiveCubeFace(),d=e.getActiveMipmapLevel(),p=e.xr.enabled;e.xr.enabled=!1;const m=s.texture.generateMipmaps;s.texture.generateMipmaps=!1,e.setRenderTarget(s,0,i),e.render(t,r),e.setRenderTarget(s,1,i),e.render(t,n),e.setRenderTarget(s,2,i),e.render(t,o),e.setRenderTarget(s,3,i),e.render(t,a),e.setRenderTarget(s,4,i),e.render(t,h),s.texture.generateMipmaps=m,e.setRenderTarget(s,5,i),e.render(t,l),e.setRenderTarget(u,c,d),e.xr.enabled=p,s.texture.needsPMREMUpdate=!0}}class to extends Ti{constructor(e,t,s,i,r,n,o,a,h,l){super(e=void 0!==e?e:[],t=void 0!==t?t:he,s,i,r,n,o,a,h,l),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(e){this.image=e}}class so extends Si{constructor(e=1,t={}){super(e,e,t),this.isWebGLCubeRenderTarget=!0;const s={width:e,height:e,depth:1},i=[s,s,s,s,s,s];this.texture=new to(i,t.mapping,t.wrapS,t.wrapT,t.magFilter,t.minFilter,t.format,t.type,t.anisotropy,t.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==t.generateMipmaps&&t.generateMipmaps,this.texture.minFilter=void 0!==t.minFilter?t.minFilter:Te}fromEquirectangularTexture(e,t){this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;const s={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"},i=new jn(5,5,5),r=new $n({name:"CubemapFromEquirect",uniforms:qn(s.uniforms),vertexShader:s.vertexShader,fragmentShader:s.fragmentShader,side:d,blending:m});r.uniforms.tEquirect.value=t;const n=new Wn(i,r),o=t.minFilter;t.minFilter===Se&&(t.minFilter=Te);return new eo(1,10,this).update(e,n),t.minFilter=o,n.geometry.dispose(),n.material.dispose(),this}clear(e,t,s,i){const r=e.getRenderTarget();for(let r=0;r<6;r++)e.setRenderTarget(this,r),e.clear(t,s,i);e.setRenderTarget(r)}}class io{constructor(e,t=25e-5){this.isFogExp2=!0,this.name="",this.color=new Yr(e),this.density=t}clone(){return new io(this.color,this.density)}toJSON(){return{type:"FogExp2",name:this.name,color:this.color.getHex(),density:this.density}}}class ro{constructor(e,t=1,s=1e3){this.isFog=!0,this.name="",this.color=new Yr(e),this.near=t,this.far=s}clone(){return new ro(this.color,this.near,this.far)}toJSON(){return{type:"Fog",name:this.name,color:this.color.getHex(),near:this.near,far:this.far}}}class no extends Pr{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.backgroundRotation=new fr,this.environmentIntensity=1,this.environmentRotation=new fr,this.overrideMaterial=null,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(e,t){return super.copy(e,t),null!==e.background&&(this.background=e.background.clone()),null!==e.environment&&(this.environment=e.environment.clone()),null!==e.fog&&(this.fog=e.fog.clone()),this.backgroundBlurriness=e.backgroundBlurriness,this.backgroundIntensity=e.backgroundIntensity,this.backgroundRotation.copy(e.backgroundRotation),this.environmentIntensity=e.environmentIntensity,this.environmentRotation.copy(e.environmentRotation),null!==e.overrideMaterial&&(this.overrideMaterial=e.overrideMaterial.clone()),this.matrixAutoUpdate=e.matrixAutoUpdate,this}toJSON(e){const t=super.toJSON(e);return null!==this.fog&&(t.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(t.object.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(t.object.backgroundIntensity=this.backgroundIntensity),t.object.backgroundRotation=this.backgroundRotation.toArray(),1!==this.environmentIntensity&&(t.object.environmentIntensity=this.environmentIntensity),t.object.environmentRotation=this.environmentRotation.toArray(),t}}class oo{constructor(e,t){this.isInterleavedBuffer=!0,this.array=e,this.stride=t,this.count=void 0!==e?e.length/t:0,this.usage=Rs,this._updateRange={offset:0,count:-1},this.updateRanges=[],this.version=0,this.uuid=qs()}onUploadCallback(){}set needsUpdate(e){!0===e&&this.version++}get updateRange(){return ai("THREE.InterleavedBuffer: updateRange() is deprecated and will be removed in r169. Use addUpdateRange() instead."),this._updateRange}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.array=new e.array.constructor(e.array),this.count=e.count,this.stride=e.stride,this.usage=e.usage,this}copyAt(e,t,s){e*=this.stride,s*=t.stride;for(let i=0,r=this.stride;ie.far||t.push({distance:a,point:co.clone(),uv:Hr.getInterpolation(co,xo,bo,vo,To,_o,wo,new Qs),face:null,object:this})}copy(e,t){return super.copy(e,t),void 0!==e.center&&this.center.copy(e.center),this.material=e.material,this}}function Mo(e,t,s,i,r,n){go.subVectors(e,s).addScalar(.5).multiply(i),void 0!==r?(fo.x=n*go.x-r*go.y,fo.y=r*go.x+n*go.y):fo.copy(go),e.copy(t),e.x+=fo.x,e.y+=fo.y,e.applyMatrix4(yo)}const Ao=new Ei,No=new Ei;class Ro extends Pr{constructor(){super(),this._currentLevel=0,this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]},isLOD:{value:!0}}),this.autoUpdate=!0}copy(e){super.copy(e,!1);const t=e.levels;for(let e=0,s=t.length;e0){let s,i;for(s=1,i=t.length;s0){Ao.setFromMatrixPosition(this.matrixWorld);const s=e.ray.origin.distanceTo(Ao);this.getObjectForDistance(s).raycast(e,t)}}update(e){const t=this.levels;if(t.length>1){Ao.setFromMatrixPosition(e.matrixWorld),No.setFromMatrixPosition(this.matrixWorld);const s=Ao.distanceTo(No)/e.zoom;let i,r;for(t[0].object.visible=!0,i=1,r=t.length;i=e))break;t[i-1].object.visible=!1,t[i].object.visible=!0}for(this._currentLevel=i-1;i1?null:t.copy(e.start).addScaledVector(s,r)}intersectsLine(e){const t=this.distanceToPoint(e.start),s=this.distanceToPoint(e.end);return t<0&&s>0||s<0&&t>0}intersectsBox(e){return e.intersectsPlane(this)}intersectsSphere(e){return e.intersectsPlane(this)}coplanarPoint(e){return e.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(e,t){const s=t||ta.getNormalMatrix(e),i=this.coplanarPoint(Qo).applyMatrix4(e),r=this.normal.applyMatrix3(s).normalize();return this.constant=-i.dot(r),this}translate(e){return this.constant-=e.dot(this.normal),this}equals(e){return e.normal.equals(this.normal)&&e.constant===this.constant}clone(){return(new this.constructor).copy(this)}}const ia=new Zi,ra=new Ei;class na{constructor(e=new sa,t=new sa,s=new sa,i=new sa,r=new sa,n=new sa){this.planes=[e,t,s,i,r,n]}set(e,t,s,i,r,n){const o=this.planes;return o[0].copy(e),o[1].copy(t),o[2].copy(s),o[3].copy(i),o[4].copy(r),o[5].copy(n),this}copy(e){const t=this.planes;for(let s=0;s<6;s++)t[s].copy(e.planes[s]);return this}setFromProjectionMatrix(e,t=2e3){const s=this.planes,i=e.elements,r=i[0],n=i[1],o=i[2],a=i[3],h=i[4],l=i[5],u=i[6],c=i[7],d=i[8],p=i[9],m=i[10],g=i[11],f=i[12],y=i[13],x=i[14],b=i[15];if(s[0].setComponents(a-r,c-h,g-d,b-f).normalize(),s[1].setComponents(a+r,c+h,g+d,b+f).normalize(),s[2].setComponents(a+n,c+l,g+p,b+y).normalize(),s[3].setComponents(a-n,c-l,g-p,b-y).normalize(),s[4].setComponents(a-o,c-u,g-m,b-x).normalize(),t===Vs)s[5].setComponents(a+o,c+u,g+m,b+x).normalize();else{if(t!==Ds)throw new Error("THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: "+t);s[5].setComponents(o,u,m,x).normalize()}return this}intersectsObject(e){if(void 0!==e.boundingSphere)null===e.boundingSphere&&e.computeBoundingSphere(),ia.copy(e.boundingSphere).applyMatrix4(e.matrixWorld);else{const t=e.geometry;null===t.boundingSphere&&t.computeBoundingSphere(),ia.copy(t.boundingSphere).applyMatrix4(e.matrixWorld)}return this.intersectsSphere(ia)}intersectsSprite(e){return ia.center.set(0,0,0),ia.radius=.7071067811865476,ia.applyMatrix4(e.matrixWorld),this.intersectsSphere(ia)}intersectsSphere(e){const t=this.planes,s=e.center,i=-e.radius;for(let e=0;e<6;e++){if(t[e].distanceToPoint(s)0?e.max.x:e.min.x,ra.y=i.normal.y>0?e.max.y:e.min.y,ra.z=i.normal.z>0?e.max.z:e.min.z,i.distanceToPoint(ra)<0)return!1}return!0}containsPoint(e){const t=this.planes;for(let s=0;s<6;s++)if(t[s].distanceToPoint(e)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function oa(e,t){return e.z-t.z}function aa(e,t){return t.z-e.z}class ha{constructor(){this.index=0,this.pool=[],this.list=[]}push(e,t,s){const i=this.pool,r=this.list;this.index>=i.length&&i.push({start:-1,count:-1,z:-1,index:-1});const n=i[this.index];r.push(n),this.index++,n.start=e.start,n.count=e.count,n.z=t,n.index=s}reset(){this.list.length=0,this.index=0}}const la=new or,ua=new or,ca=new or,da=new Yr(1,1,1),pa=new or,ma=new na,ga=new Pi,fa=new Zi,ya=new Ei,xa=new Ei,ba=new Ei,va=new ha,Ta=new Wn,_a=[];function wa(e,t,s=0){const i=t.itemSize;if(e.isInterleavedBufferAttribute||e.array.constructor!==t.array.constructor){const r=e.count;for(let n=0;n65535?new Uint32Array(i):new Uint16Array(i);t.setIndex(new hn(e,1))}this._geometryInitialized=!0}}_validateGeometry(e){const t=this.geometry;if(Boolean(e.getIndex())!==Boolean(t.getIndex()))throw new Error('BatchedMesh: All geometries must consistently have "index".');for(const s in t.attributes){if(!e.hasAttribute(s))throw new Error(`BatchedMesh: Added geometry missing "${s}". All geometries must have consistent attributes.`);const i=e.getAttribute(s),r=t.getAttribute(s);if(i.itemSize!==r.itemSize||i.normalized!==r.normalized)throw new Error("BatchedMesh: All attributes must have a consistent itemSize and normalized value.")}}setCustomSort(e){return this.customSort=e,this}computeBoundingBox(){null===this.boundingBox&&(this.boundingBox=new Pi);const e=this.boundingBox,t=this._drawInfo;e.makeEmpty();for(let s=0,i=t.length;s=this._maxInstanceCount)throw new Error("BatchedMesh: Maximum item count reached.");this._drawInfo.push({visible:!0,active:!0,geometryIndex:e});const t=this._drawInfo.length-1,s=this._matricesTexture,i=s.image.data;ca.toArray(i,16*t),s.needsUpdate=!0;const r=this._colorsTexture;return r&&(da.toArray(r.image.data,4*t),r.needsUpdate=!0),t}addGeometry(e,t=-1,s=-1){if(this._initializeGeometry(e),this._validateGeometry(e),this._drawInfo.length>=this._maxInstanceCount)throw new Error("BatchedMesh: Maximum item count reached.");const i={vertexStart:-1,vertexCount:-1,indexStart:-1,indexCount:-1};let r=null;const n=this._reservedRanges,o=this._drawRanges,a=this._bounds;0!==this._geometryCount&&(r=n[n.length-1]),i.vertexCount=-1===t?e.getAttribute("position").count:t,i.vertexStart=null===r?0:r.vertexStart+r.vertexCount;const h=e.getIndex(),l=null!==h;if(l&&(i.indexCount=-1===s?h.count:s,i.indexStart=null===r?0:r.indexStart+r.indexCount),-1!==i.indexStart&&i.indexStart+i.indexCount>this._maxIndexCount||i.vertexStart+i.vertexCount>this._maxVertexCount)throw new Error("BatchedMesh: Reserved space request exceeds the maximum buffer size.");const u=this._geometryCount;return this._geometryCount++,n.push(i),o.push({start:l?i.indexStart:i.vertexStart,count:-1}),a.push({boxInitialized:!1,box:new Pi,sphereInitialized:!1,sphere:new Zi}),this.setGeometryAt(u,e),u}setGeometryAt(e,t){if(e>=this._geometryCount)throw new Error("BatchedMesh: Maximum geometry count reached.");this._validateGeometry(t);const s=this.geometry,i=null!==s.getIndex(),r=s.getIndex(),n=t.getIndex(),o=this._reservedRanges[e];if(i&&n.count>o.indexCount||t.attributes.position.count>o.vertexCount)throw new Error("BatchedMesh: Reserved space not large enough for provided geometry.");const a=o.vertexStart,h=o.vertexCount;for(const e in s.attributes){const i=t.getAttribute(e),r=s.getAttribute(e);wa(i,r,a);const n=i.itemSize;for(let e=i.count,t=h;e=this._geometryCount)return null;const s=this._bounds[e],i=s.box,r=this.geometry;if(!1===s.boxInitialized){i.makeEmpty();const t=r.index,n=r.attributes.position,o=this._drawRanges[e];for(let e=o.start,s=o.start+o.count;e=this._geometryCount)return null;const s=this._bounds[e],i=s.sphere,r=this.geometry;if(!1===s.sphereInitialized){i.makeEmpty(),this.getBoundingBoxAt(e,ga),ga.getCenter(i.center);const t=r.index,n=r.attributes.position,o=this._drawRanges[e];let a=0;for(let e=o.start,s=o.start+o.count;e=s.length||!1===s[e].active||(t.toArray(r,16*e),i.needsUpdate=!0),this}getMatrixAt(e,t){const s=this._drawInfo,i=this._matricesTexture.image.data;return e>=s.length||!1===s[e].active?null:t.fromArray(i,16*e)}setColorAt(e,t){null===this._colorsTexture&&this._initColorsTexture();const s=this._colorsTexture,i=this._colorsTexture.image.data,r=this._drawInfo;return e>=r.length||!1===r[e].active||(t.toArray(i,4*e),s.needsUpdate=!0),this}getColorAt(e,t){const s=this._colorsTexture.image.data,i=this._drawInfo;return e>=i.length||!1===i[e].active?null:t.fromArray(s,4*e)}setVisibleAt(e,t){const s=this._drawInfo;return e>=s.length||!1===s[e].active||s[e].visible===t||(s[e].visible=t,this._visibilityChanged=!0),this}getVisibleAt(e){const t=this._drawInfo;return!(e>=t.length||!1===t[e].active)&&t[e].visible}raycast(e,t){const s=this._drawInfo,i=this._drawRanges,r=this.matrixWorld,n=this.geometry;Ta.material=this.material,Ta.geometry.index=n.index,Ta.geometry.attributes=n.attributes,null===Ta.geometry.boundingBox&&(Ta.geometry.boundingBox=new Pi),null===Ta.geometry.boundingSphere&&(Ta.geometry.boundingSphere=new Zi);for(let n=0,o=s.length;n({...e}))),this._reservedRanges=e._reservedRanges.map((e=>({...e}))),this._drawInfo=e._drawInfo.map((e=>({...e}))),this._bounds=e._bounds.map((e=>({boxInitialized:e.boxInitialized,box:e.box.clone(),sphereInitialized:e.sphereInitialized,sphere:e.sphere.clone()}))),this._maxInstanceCount=e._maxInstanceCount,this._maxVertexCount=e._maxVertexCount,this._maxIndexCount=e._maxIndexCount,this._geometryInitialized=e._geometryInitialized,this._geometryCount=e._geometryCount,this._multiDrawCounts=e._multiDrawCounts.slice(),this._multiDrawStarts=e._multiDrawStarts.slice(),this._matricesTexture=e._matricesTexture.clone(),this._matricesTexture.image.data=this._matricesTexture.image.data.slice(),null!==this._colorsTexture&&(this._colorsTexture=e._colorsTexture.clone(),this._colorsTexture.image.data=this._colorsTexture.image.data.slice()),this}dispose(){return this.geometry.dispose(),this._matricesTexture.dispose(),this._matricesTexture=null,this._indirectTexture.dispose(),this._indirectTexture=null,null!==this._colorsTexture&&(this._colorsTexture.dispose(),this._colorsTexture=null),this}onBeforeRender(e,t,s,i,r){if(!this._visibilityChanged&&!this.perObjectFrustumCulled&&!this.sortObjects)return;const n=i.getIndex(),o=null===n?1:n.array.BYTES_PER_ELEMENT,a=this._drawInfo,h=this._multiDrawStarts,l=this._multiDrawCounts,u=this._drawRanges,c=this.perObjectFrustumCulled,d=this._indirectTexture,p=d.image.data;c&&(pa.multiplyMatrices(s.projectionMatrix,s.matrixWorldInverse).multiply(this.matrixWorld),ma.setFromProjectionMatrix(pa,e.coordinateSystem));let m=0;if(this.sortObjects){ua.copy(this.matrixWorld).invert(),ya.setFromMatrixPosition(s.matrixWorld).applyMatrix4(ua),xa.set(0,0,-1).transformDirection(s.matrixWorld).transformDirection(ua);for(let e=0,t=a.length;e0){const s=e[t[0]];if(void 0!==s){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=s.length;ei)return;Ba.applyMatrix4(e.matrixWorld);const a=t.ray.origin.distanceTo(Ba);return at.far?void 0:{distance:a,point:Ia.clone().applyMatrix4(e.matrixWorld),index:r,face:null,faceIndex:null,object:e}}const za=new Ei,Ua=new Ei;class La extends Pa{constructor(e,t){super(e,t),this.isLineSegments=!0,this.type="LineSegments"}computeLineDistances(){const e=this.geometry;if(null===e.index){const t=e.attributes.position,s=[];for(let e=0,i=t.count;e0){const s=e[t[0]];if(void 0!==s){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=s.length;er.far)return;n.push({distance:h,distanceToRay:Math.sqrt(a),point:s,index:t,face:null,object:o})}}class qa extends Pr{constructor(){super(),this.isGroup=!0,this.type="Group"}}class $a extends Ti{constructor(e,t,s,i,r,n,o,a,h){super(e,t,s,i,r,n,o,a,h),this.isVideoTexture=!0,this.minFilter=void 0!==n?n:Te,this.magFilter=void 0!==r?r:Te,this.generateMipmaps=!1;const l=this;"requestVideoFrameCallback"in e&&e.requestVideoFrameCallback((function t(){l.needsUpdate=!0,e.requestVideoFrameCallback(t)}))}clone(){return new this.constructor(this.image).copy(this)}update(){const e=this.image;!1==="requestVideoFrameCallback"in e&&e.readyState>=e.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}class Xa extends Ti{constructor(e,t){super({width:e,height:t}),this.isFramebufferTexture=!0,this.magFilter=fe,this.minFilter=fe,this.generateMipmaps=!1,this.needsUpdate=!0}}class Ya extends Ti{constructor(e,t,s,i,r,n,o,a,h,l,u,c){super(null,n,o,a,h,l,i,r,u,c),this.isCompressedTexture=!0,this.image={width:t,height:s},this.mipmaps=e,this.flipY=!1,this.generateMipmaps=!1}}class Ja extends Ya{constructor(e,t,s,i,r,n){super(e,t,s,r,n),this.isCompressedArrayTexture=!0,this.image.depth=i,this.wrapR=me,this.layerUpdates=new Set}addLayerUpdate(e){this.layerUpdates.add(e)}clearLayerUpdates(){this.layerUpdates.clear()}}class Za extends Ya{constructor(e,t,s){super(void 0,e[0].width,e[0].height,t,s,he),this.isCompressedCubeTexture=!0,this.isCubeTexture=!0,this.image=e}}class Ka extends Ti{constructor(e,t,s,i,r,n,o,a,h){super(e,t,s,i,r,n,o,a,h),this.isCanvasTexture=!0,this.needsUpdate=!0}}class Qa extends Ti{constructor(e,t,s,i,r,n,o,a,h,l=1026){if(l!==We&&l!==He)throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");void 0===s&&l===We&&(s=Be),void 0===s&&l===He&&(s=Ue),super(null,i,r,n,o,a,l,s,h),this.isDepthTexture=!0,this.image={width:e,height:t},this.magFilter=void 0!==o?o:fe,this.minFilter=void 0!==a?a:fe,this.flipY=!1,this.generateMipmaps=!1,this.compareFunction=null}copy(e){return super.copy(e),this.compareFunction=e.compareFunction,this}toJSON(e){const t=super.toJSON(e);return null!==this.compareFunction&&(t.compareFunction=this.compareFunction),t}}class eh{constructor(){this.type="Curve",this.arcLengthDivisions=200}getPoint(){return console.warn("THREE.Curve: .getPoint() not implemented."),null}getPointAt(e,t){const s=this.getUtoTmapping(e);return this.getPoint(s,t)}getPoints(e=5){const t=[];for(let s=0;s<=e;s++)t.push(this.getPoint(s/e));return t}getSpacedPoints(e=5){const t=[];for(let s=0;s<=e;s++)t.push(this.getPointAt(s/e));return t}getLength(){const e=this.getLengths();return e[e.length-1]}getLengths(e=this.arcLengthDivisions){if(this.cacheArcLengths&&this.cacheArcLengths.length===e+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;const t=[];let s,i=this.getPoint(0),r=0;t.push(0);for(let n=1;n<=e;n++)s=this.getPoint(n/e),r+=s.distanceTo(i),t.push(r),i=s;return this.cacheArcLengths=t,t}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(e,t){const s=this.getLengths();let i=0;const r=s.length;let n;n=t||e*s[r-1];let o,a=0,h=r-1;for(;a<=h;)if(i=Math.floor(a+(h-a)/2),o=s[i]-n,o<0)a=i+1;else{if(!(o>0)){h=i;break}h=i-1}if(i=h,s[i]===n)return i/(r-1);const l=s[i];return(i+(n-l)/(s[i+1]-l))/(r-1)}getTangent(e,t){const s=1e-4;let i=e-s,r=e+s;i<0&&(i=0),r>1&&(r=1);const n=this.getPoint(i),o=this.getPoint(r),a=t||(n.isVector2?new Qs:new Ei);return a.copy(o).sub(n).normalize(),a}getTangentAt(e,t){const s=this.getUtoTmapping(e);return this.getTangent(s,t)}computeFrenetFrames(e,t){const s=new Ei,i=[],r=[],n=[],o=new Ei,a=new or;for(let t=0;t<=e;t++){const s=t/e;i[t]=this.getTangentAt(s,new Ei)}r[0]=new Ei,n[0]=new Ei;let h=Number.MAX_VALUE;const l=Math.abs(i[0].x),u=Math.abs(i[0].y),c=Math.abs(i[0].z);l<=h&&(h=l,s.set(1,0,0)),u<=h&&(h=u,s.set(0,1,0)),c<=h&&s.set(0,0,1),o.crossVectors(i[0],s).normalize(),r[0].crossVectors(i[0],o),n[0].crossVectors(i[0],r[0]);for(let t=1;t<=e;t++){if(r[t]=r[t-1].clone(),n[t]=n[t-1].clone(),o.crossVectors(i[t-1],i[t]),o.length()>Number.EPSILON){o.normalize();const e=Math.acos($s(i[t-1].dot(i[t]),-1,1));r[t].applyMatrix4(a.makeRotationAxis(o,e))}n[t].crossVectors(i[t],r[t])}if(!0===t){let t=Math.acos($s(r[0].dot(r[e]),-1,1));t/=e,i[0].dot(o.crossVectors(r[0],r[e]))>0&&(t=-t);for(let s=1;s<=e;s++)r[s].applyMatrix4(a.makeRotationAxis(i[s],t*s)),n[s].crossVectors(i[s],r[s])}return{tangents:i,normals:r,binormals:n}}clone(){return(new this.constructor).copy(this)}copy(e){return this.arcLengthDivisions=e.arcLengthDivisions,this}toJSON(){const e={metadata:{version:4.6,type:"Curve",generator:"Curve.toJSON"}};return e.arcLengthDivisions=this.arcLengthDivisions,e.type=this.type,e}fromJSON(e){return this.arcLengthDivisions=e.arcLengthDivisions,this}}class th extends eh{constructor(e=0,t=0,s=1,i=1,r=0,n=2*Math.PI,o=!1,a=0){super(),this.isEllipseCurve=!0,this.type="EllipseCurve",this.aX=e,this.aY=t,this.xRadius=s,this.yRadius=i,this.aStartAngle=r,this.aEndAngle=n,this.aClockwise=o,this.aRotation=a}getPoint(e,t=new Qs){const s=t,i=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const n=Math.abs(r)i;)r-=i;r0?0:(Math.floor(Math.abs(h)/r)+1)*r:0===l&&h===r-1&&(h=r-2,l=1),this.closed||h>0?o=i[(h-1)%r]:(rh.subVectors(i[0],i[1]).add(i[0]),o=rh);const u=i[h%r],c=i[(h+1)%r];if(this.closed||h+2i.length-2?i.length-1:n+1],u=i[n>i.length-3?i.length-1:n+2];return s.set(lh(o,a.x,h.x,l.x,u.x),lh(o,a.y,h.y,l.y,u.y)),s}copy(e){super.copy(e),this.points=[];for(let t=0,s=e.points.length;t=s){const e=i[r]-s,n=this.curves[r],o=n.getLength(),a=0===o?0:1-e/o;return n.getPointAt(a,t)}r++}return null}getLength(){const e=this.getCurveLengths();return e[e.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 e=[];let t=0;for(let s=0,i=this.curves.length;s1&&!t[t.length-1].equals(t[0])&&t.push(t[0]),t}copy(e){super.copy(e),this.curves=[];for(let t=0,s=e.curves.length;t0){const e=h.getPoint(0);e.equals(this.currentPoint)||this.lineTo(e.x,e.y)}this.curves.push(h);const l=h.getPoint(1);return this.currentPoint.copy(l),this}copy(e){return super.copy(e),this.currentPoint.copy(e.currentPoint),this}toJSON(){const e=super.toJSON();return e.currentPoint=this.currentPoint.toArray(),e}fromJSON(e){return super.fromJSON(e),this.currentPoint.fromArray(e.currentPoint),this}}class _h extends Mn{constructor(e=[new Qs(0,-.5),new Qs(.5,0),new Qs(0,.5)],t=12,s=0,i=2*Math.PI){super(),this.type="LatheGeometry",this.parameters={points:e,segments:t,phiStart:s,phiLength:i},t=Math.floor(t),i=$s(i,0,2*Math.PI);const r=[],n=[],o=[],a=[],h=[],l=1/t,u=new Ei,c=new Qs,d=new Ei,p=new Ei,m=new Ei;let g=0,f=0;for(let t=0;t<=e.length-1;t++)switch(t){case 0:g=e[t+1].x-e[t].x,f=e[t+1].y-e[t].y,d.x=1*f,d.y=-g,d.z=0*f,m.copy(d),d.normalize(),a.push(d.x,d.y,d.z);break;case e.length-1:a.push(m.x,m.y,m.z);break;default:g=e[t+1].x-e[t].x,f=e[t+1].y-e[t].y,d.x=1*f,d.y=-g,d.z=0*f,p.copy(d),d.x+=m.x,d.y+=m.y,d.z+=m.z,d.normalize(),a.push(d.x,d.y,d.z),m.copy(p)}for(let r=0;r<=t;r++){const d=s+r*l*i,p=Math.sin(d),m=Math.cos(d);for(let s=0;s<=e.length-1;s++){u.x=e[s].x*p,u.y=e[s].y,u.z=e[s].x*m,n.push(u.x,u.y,u.z),c.x=r/t,c.y=s/(e.length-1),o.push(c.x,c.y);const i=a[3*s+0]*p,l=a[3*s+1],d=a[3*s+0]*m;h.push(i,l,d)}}for(let s=0;s0&&y(!0),t>0&&y(!1)),this.setIndex(l),this.setAttribute("position",new yn(u,3)),this.setAttribute("normal",new yn(c,3)),this.setAttribute("uv",new yn(d,2))}copy(e){return super.copy(e),this.parameters=Object.assign({},e.parameters),this}static fromJSON(e){return new Mh(e.radiusTop,e.radiusBottom,e.height,e.radialSegments,e.heightSegments,e.openEnded,e.thetaStart,e.thetaLength)}}class Ah extends Mh{constructor(e=1,t=1,s=32,i=1,r=!1,n=0,o=2*Math.PI){super(0,e,t,s,i,r,n,o),this.type="ConeGeometry",this.parameters={radius:e,height:t,radialSegments:s,heightSegments:i,openEnded:r,thetaStart:n,thetaLength:o}}static fromJSON(e){return new Ah(e.radius,e.height,e.radialSegments,e.heightSegments,e.openEnded,e.thetaStart,e.thetaLength)}}class Nh extends Mn{constructor(e=[],t=[],s=1,i=0){super(),this.type="PolyhedronGeometry",this.parameters={vertices:e,indices:t,radius:s,detail:i};const r=[],n=[];function o(e,t,s,i){const r=i+1,n=[];for(let i=0;i<=r;i++){n[i]=[];const o=e.clone().lerp(s,i/r),a=t.clone().lerp(s,i/r),h=r-i;for(let e=0;e<=h;e++)n[i][e]=0===e&&i===r?o:o.clone().lerp(a,e/h)}for(let e=0;e.9&&o<.1&&(t<.2&&(n[e+0]+=1),s<.2&&(n[e+2]+=1),i<.2&&(n[e+4]+=1))}}()}(),this.setAttribute("position",new yn(r,3)),this.setAttribute("normal",new yn(r.slice(),3)),this.setAttribute("uv",new yn(n,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}copy(e){return super.copy(e),this.parameters=Object.assign({},e.parameters),this}static fromJSON(e){return new Nh(e.vertices,e.indices,e.radius,e.details)}}class Rh extends Nh{constructor(e=1,t=0){const s=(1+Math.sqrt(5))/2,i=1/s;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,-i,-s,0,-i,s,0,i,-s,0,i,s,-i,-s,0,-i,s,0,i,-s,0,i,s,0,-s,0,-i,s,0,-i,-s,0,i,s,0,i],[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],e,t),this.type="DodecahedronGeometry",this.parameters={radius:e,detail:t}}static fromJSON(e){return new Rh(e.radius,e.detail)}}const Ch=new Ei,Eh=new Ei,Bh=new Ei,Ih=new Hr;class Ph extends Mn{constructor(e=null,t=1){if(super(),this.type="EdgesGeometry",this.parameters={geometry:e,thresholdAngle:t},null!==e){const s=4,i=Math.pow(10,s),r=Math.cos(Hs*t),n=e.getIndex(),o=e.getAttribute("position"),a=n?n.count:o.count,h=[0,0,0],l=["a","b","c"],u=new Array(3),c={},d=[];for(let e=0;e80*s){a=l=e[0],h=u=e[1];for(let t=s;tl&&(l=c),d>u&&(u=d);p=Math.max(l-a,u-h),p=0!==p?32767/p:0}return Oh(n,o,s,a,h,p,0),o};function Uh(e,t,s,i,r){let n,o;if(r===function(e,t,s,i){let r=0;for(let n=t,o=s-i;n0)for(n=t;n=t;n-=i)o=il(n,e[n],e[n+1],o);return o&&Zh(o,o.next)&&(rl(o),o=o.next),o}function Lh(e,t){if(!e)return e;t||(t=e);let s,i=e;do{if(s=!1,i.steiner||!Zh(i,i.next)&&0!==Jh(i.prev,i,i.next))i=i.next;else{if(rl(i),i=t=i.prev,i===i.next)break;s=!0}}while(s||i!==t);return t}function Oh(e,t,s,i,r,n,o){if(!e)return;!o&&n&&function(e,t,s,i){let r=e;do{0===r.z&&(r.z=qh(r.x,r.y,t,s,i)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==e);r.prevZ.nextZ=null,r.prevZ=null,function(e){let t,s,i,r,n,o,a,h,l=1;do{for(s=e,e=null,n=null,o=0;s;){for(o++,i=s,a=0,t=0;t0||h>0&&i;)0!==a&&(0===h||!i||s.z<=i.z)?(r=s,s=s.nextZ,a--):(r=i,i=i.nextZ,h--),n?n.nextZ=r:e=r,r.prevZ=n,n=r;s=i}n.nextZ=null,l*=2}while(o>1)}(r)}(e,i,r,n);let a,h,l=e;for(;e.prev!==e.next;)if(a=e.prev,h=e.next,n?Dh(e,i,r,n):Vh(e))t.push(a.i/s|0),t.push(e.i/s|0),t.push(h.i/s|0),rl(e),e=h.next,l=h.next;else if((e=h)===l){o?1===o?Oh(e=kh(Lh(e),t,s),t,s,i,r,n,2):2===o&&Gh(e,t,s,i,r,n):Oh(Lh(e),t,s,i,r,n,1);break}}function Vh(e){const t=e.prev,s=e,i=e.next;if(Jh(t,s,i)>=0)return!1;const r=t.x,n=s.x,o=i.x,a=t.y,h=s.y,l=i.y,u=rn?r>o?r:o:n>o?n:o,p=a>h?a>l?a:l:h>l?h:l;let m=i.next;for(;m!==t;){if(m.x>=u&&m.x<=d&&m.y>=c&&m.y<=p&&Xh(r,a,n,h,o,l,m.x,m.y)&&Jh(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function Dh(e,t,s,i){const r=e.prev,n=e,o=e.next;if(Jh(r,n,o)>=0)return!1;const a=r.x,h=n.x,l=o.x,u=r.y,c=n.y,d=o.y,p=ah?a>l?a:l:h>l?h:l,f=u>c?u>d?u:d:c>d?c:d,y=qh(p,m,t,s,i),x=qh(g,f,t,s,i);let b=e.prevZ,v=e.nextZ;for(;b&&b.z>=y&&v&&v.z<=x;){if(b.x>=p&&b.x<=g&&b.y>=m&&b.y<=f&&b!==r&&b!==o&&Xh(a,u,h,c,l,d,b.x,b.y)&&Jh(b.prev,b,b.next)>=0)return!1;if(b=b.prevZ,v.x>=p&&v.x<=g&&v.y>=m&&v.y<=f&&v!==r&&v!==o&&Xh(a,u,h,c,l,d,v.x,v.y)&&Jh(v.prev,v,v.next)>=0)return!1;v=v.nextZ}for(;b&&b.z>=y;){if(b.x>=p&&b.x<=g&&b.y>=m&&b.y<=f&&b!==r&&b!==o&&Xh(a,u,h,c,l,d,b.x,b.y)&&Jh(b.prev,b,b.next)>=0)return!1;b=b.prevZ}for(;v&&v.z<=x;){if(v.x>=p&&v.x<=g&&v.y>=m&&v.y<=f&&v!==r&&v!==o&&Xh(a,u,h,c,l,d,v.x,v.y)&&Jh(v.prev,v,v.next)>=0)return!1;v=v.nextZ}return!0}function kh(e,t,s){let i=e;do{const r=i.prev,n=i.next.next;!Zh(r,n)&&Kh(r,i,i.next,n)&&tl(r,n)&&tl(n,r)&&(t.push(r.i/s|0),t.push(i.i/s|0),t.push(n.i/s|0),rl(i),rl(i.next),i=e=n),i=i.next}while(i!==e);return Lh(i)}function Gh(e,t,s,i,r,n){let o=e;do{let e=o.next.next;for(;e!==o.prev;){if(o.i!==e.i&&Yh(o,e)){let a=sl(o,e);return o=Lh(o,o.next),a=Lh(a,a.next),Oh(o,t,s,i,r,n,0),void Oh(a,t,s,i,r,n,0)}e=e.next}o=o.next}while(o!==e)}function Wh(e,t){return e.x-t.x}function Hh(e,t){const s=function(e,t){let s,i=t,r=-1/0;const n=e.x,o=e.y;do{if(o<=i.y&&o>=i.next.y&&i.next.y!==i.y){const e=i.x+(o-i.y)*(i.next.x-i.x)/(i.next.y-i.y);if(e<=n&&e>r&&(r=e,s=i.x=i.x&&i.x>=h&&n!==i.x&&Xh(os.x||i.x===s.x&&jh(s,i)))&&(s=i,c=u)),i=i.next}while(i!==a);return s}(e,t);if(!s)return t;const i=sl(s,e);return Lh(i,i.next),Lh(s,s.next)}function jh(e,t){return Jh(e.prev,e,t.prev)<0&&Jh(t.next,e,e.next)<0}function qh(e,t,s,i,r){return(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=(e-s)*r|0)|e<<8))|e<<4))|e<<2))|e<<1))|(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=(t-i)*r|0)|t<<8))|t<<4))|t<<2))|t<<1))<<1}function $h(e){let t=e,s=e;do{(t.x=(e-o)*(n-a)&&(e-o)*(i-a)>=(s-o)*(t-a)&&(s-o)*(n-a)>=(r-o)*(i-a)}function Yh(e,t){return e.next.i!==t.i&&e.prev.i!==t.i&&!function(e,t){let s=e;do{if(s.i!==e.i&&s.next.i!==e.i&&s.i!==t.i&&s.next.i!==t.i&&Kh(s,s.next,e,t))return!0;s=s.next}while(s!==e);return!1}(e,t)&&(tl(e,t)&&tl(t,e)&&function(e,t){let s=e,i=!1;const r=(e.x+t.x)/2,n=(e.y+t.y)/2;do{s.y>n!=s.next.y>n&&s.next.y!==s.y&&r<(s.next.x-s.x)*(n-s.y)/(s.next.y-s.y)+s.x&&(i=!i),s=s.next}while(s!==e);return i}(e,t)&&(Jh(e.prev,e,t.prev)||Jh(e,t.prev,t))||Zh(e,t)&&Jh(e.prev,e,e.next)>0&&Jh(t.prev,t,t.next)>0)}function Jh(e,t,s){return(t.y-e.y)*(s.x-t.x)-(t.x-e.x)*(s.y-t.y)}function Zh(e,t){return e.x===t.x&&e.y===t.y}function Kh(e,t,s,i){const r=el(Jh(e,t,s)),n=el(Jh(e,t,i)),o=el(Jh(s,i,e)),a=el(Jh(s,i,t));return r!==n&&o!==a||(!(0!==r||!Qh(e,s,t))||(!(0!==n||!Qh(e,i,t))||(!(0!==o||!Qh(s,e,i))||!(0!==a||!Qh(s,t,i)))))}function Qh(e,t,s){return t.x<=Math.max(e.x,s.x)&&t.x>=Math.min(e.x,s.x)&&t.y<=Math.max(e.y,s.y)&&t.y>=Math.min(e.y,s.y)}function el(e){return e>0?1:e<0?-1:0}function tl(e,t){return Jh(e.prev,e,e.next)<0?Jh(e,t,e.next)>=0&&Jh(e,e.prev,t)>=0:Jh(e,t,e.prev)<0||Jh(e,e.next,t)<0}function sl(e,t){const s=new nl(e.i,e.x,e.y),i=new nl(t.i,t.x,t.y),r=e.next,n=t.prev;return e.next=t,t.prev=e,s.next=r,r.prev=s,i.next=s,s.prev=i,n.next=i,i.prev=n,i}function il(e,t,s,i){const r=new nl(e,t,s);return i?(r.next=i.next,r.prev=i,i.next.prev=r,i.next=r):(r.prev=r,r.next=r),r}function rl(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ)}function nl(e,t,s){this.i=e,this.x=t,this.y=s,this.prev=null,this.next=null,this.z=0,this.prevZ=null,this.nextZ=null,this.steiner=!1}class ol{static area(e){const t=e.length;let s=0;for(let i=t-1,r=0;r2&&e[t-1].equals(e[0])&&e.pop()}function hl(e,t){for(let s=0;sNumber.EPSILON){const c=Math.sqrt(u),d=Math.sqrt(h*h+l*l),p=t.x-a/c,m=t.y+o/c,g=((s.x-l/d-p)*l-(s.y+h/d-m)*h)/(o*l-a*h);i=p+o*g-e.x,r=m+a*g-e.y;const f=i*i+r*r;if(f<=2)return new Qs(i,r);n=Math.sqrt(f/2)}else{let e=!1;o>Number.EPSILON?h>Number.EPSILON&&(e=!0):o<-Number.EPSILON?h<-Number.EPSILON&&(e=!0):Math.sign(a)===Math.sign(l)&&(e=!0),e?(i=-a,r=o,n=Math.sqrt(u)):(i=o,r=a,n=Math.sqrt(u/2))}return new Qs(i/n,r/n)}const B=[];for(let e=0,t=A.length,s=t-1,i=e+1;e=0;e--){const t=e/p,s=u*Math.cos(t*Math.PI/2),i=c*Math.sin(t*Math.PI/2)+d;for(let e=0,t=A.length;e=0;){const i=s;let r=s-1;r<0&&(r=e.length-1);for(let e=0,s=a+2*p;e0)&&d.push(t,r,h),(e!==s-1||a0!=e>0&&this.version++,this._anisotropy=e}get clearcoat(){return this._clearcoat}set clearcoat(e){this._clearcoat>0!=e>0&&this.version++,this._clearcoat=e}get iridescence(){return this._iridescence}set iridescence(e){this._iridescence>0!=e>0&&this.version++,this._iridescence=e}get dispersion(){return this._dispersion}set dispersion(e){this._dispersion>0!=e>0&&this.version++,this._dispersion=e}get sheen(){return this._sheen}set sheen(e){this._sheen>0!=e>0&&this.version++,this._sheen=e}get transmission(){return this._transmission}set transmission(e){this._transmission>0!=e>0&&this.version++,this._transmission=e}copy(e){return super.copy(e),this.defines={STANDARD:"",PHYSICAL:""},this.anisotropy=e.anisotropy,this.anisotropyRotation=e.anisotropyRotation,this.anisotropyMap=e.anisotropyMap,this.clearcoat=e.clearcoat,this.clearcoatMap=e.clearcoatMap,this.clearcoatRoughness=e.clearcoatRoughness,this.clearcoatRoughnessMap=e.clearcoatRoughnessMap,this.clearcoatNormalMap=e.clearcoatNormalMap,this.clearcoatNormalScale.copy(e.clearcoatNormalScale),this.dispersion=e.dispersion,this.ior=e.ior,this.iridescence=e.iridescence,this.iridescenceMap=e.iridescenceMap,this.iridescenceIOR=e.iridescenceIOR,this.iridescenceThicknessRange=[...e.iridescenceThicknessRange],this.iridescenceThicknessMap=e.iridescenceThicknessMap,this.sheen=e.sheen,this.sheenColor.copy(e.sheenColor),this.sheenColorMap=e.sheenColorMap,this.sheenRoughness=e.sheenRoughness,this.sheenRoughnessMap=e.sheenRoughnessMap,this.transmission=e.transmission,this.transmissionMap=e.transmissionMap,this.thickness=e.thickness,this.thicknessMap=e.thicknessMap,this.attenuationDistance=e.attenuationDistance,this.attenuationColor.copy(e.attenuationColor),this.specularIntensity=e.specularIntensity,this.specularIntensityMap=e.specularIntensityMap,this.specularColor.copy(e.specularColor),this.specularColorMap=e.specularColorMap,this}}class Rl extends Kr{constructor(e){super(),this.isMeshPhongMaterial=!0,this.type="MeshPhongMaterial",this.color=new Yr(16777215),this.specular=new Yr(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Yr(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Qs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new fr,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(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.specular.copy(e.specular),this.shininess=e.shininess,this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.emissive.copy(e.emissive),this.emissiveMap=e.emissiveMap,this.emissiveIntensity=e.emissiveIntensity,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.flatShading=e.flatShading,this.fog=e.fog,this}}class Cl extends Kr{constructor(e){super(),this.isMeshToonMaterial=!0,this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new Yr(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Yr(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Qs(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(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.gradientMap=e.gradientMap,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.emissive.copy(e.emissive),this.emissiveMap=e.emissiveMap,this.emissiveIntensity=e.emissiveIntensity,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.alphaMap=e.alphaMap,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.fog=e.fog,this}}class El extends Kr{constructor(e){super(),this.isMeshNormalMaterial=!0,this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Qs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.flatShading=!1,this.setValues(e)}copy(e){return super.copy(e),this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.flatShading=e.flatShading,this}}class Bl extends Kr{constructor(e){super(),this.isMeshLambertMaterial=!0,this.type="MeshLambertMaterial",this.color=new Yr(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Yr(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Qs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new fr,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(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.emissive.copy(e.emissive),this.emissiveMap=e.emissiveMap,this.emissiveIntensity=e.emissiveIntensity,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.flatShading=e.flatShading,this.fog=e.fog,this}}class Il extends Kr{constructor(e){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(e)}copy(e){return super.copy(e),this.depthPacking=e.depthPacking,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this}}class Pl extends Kr{constructor(e){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(e)}copy(e){return super.copy(e),this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this}}class Fl extends Kr{constructor(e){super(),this.isMeshMatcapMaterial=!0,this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new Yr(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Qs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.flatShading=!1,this.fog=!0,this.setValues(e)}copy(e){return super.copy(e),this.defines={MATCAP:""},this.color.copy(e.color),this.matcap=e.matcap,this.map=e.map,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.alphaMap=e.alphaMap,this.flatShading=e.flatShading,this.fog=e.fog,this}}class zl extends Ma{constructor(e){super(),this.isLineDashedMaterial=!0,this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(e)}copy(e){return super.copy(e),this.scale=e.scale,this.dashSize=e.dashSize,this.gapSize=e.gapSize,this}}function Ul(e,t=!1){let s="{";!0===e.isNode&&(s+=e.id,e=e.getSelf());for(const{property:i,childNode:r}of Ll(e))s+=","+i.slice(0,-4)+":"+r.getCacheKey(t);return s+="}",s}function*Ll(e,t=!1){for(const s in e){if(!0===s.startsWith("_"))continue;const i=e[s];if(!0===Array.isArray(i))for(let e=0;ee.charCodeAt(0))).buffer}var Gl=Object.freeze({__proto__:null,arrayBufferToBase64:Dl,base64ToArrayBuffer:kl,getCacheKey:Ul,getNodeChildren:Ll,getValueFromType:Vl,getValueType:Ol});const Wl={VERTEX:"vertex",FRAGMENT:"fragment"},Hl={NONE:"none",FRAME:"frame",RENDER:"render",OBJECT:"object"},jl={BOOLEAN:"bool",INTEGER:"int",FLOAT:"float",VECTOR2:"vec2",VECTOR3:"vec3",VECTOR4:"vec4",MATRIX2:"mat2",MATRIX3:"mat3",MATRIX4:"mat4"},ql=["fragment","vertex"],$l=["setup","analyze","generate"],Xl=[...ql,"compute"],Yl=["x","y","z","w"],Jl=new Map;let Zl=0;class Kl extends ks{constructor(e=null){super(),this.nodeType=e,this.updateType=Hl.NONE,this.updateBeforeType=Hl.NONE,this.updateAfterType=Hl.NONE,this.uuid=Ks.generateUUID(),this.version=0,this._cacheKey=null,this._cacheKeyVersion=0,this.global=!1,this.isNode=!0,Object.defineProperty(this,"id",{value:Zl++})}set needsUpdate(e){!0===e&&this.version++}get type(){return this.constructor.type}onUpdate(e,t){return this.updateType=t,this.update=e.bind(this.getSelf()),this}onFrameUpdate(e){return this.onUpdate(e,Hl.FRAME)}onRenderUpdate(e){return this.onUpdate(e,Hl.RENDER)}onObjectUpdate(e){return this.onUpdate(e,Hl.OBJECT)}onReference(e){return this.updateReference=e.bind(this.getSelf()),this}getSelf(){return this.self||this}updateReference(){return this}isGlobal(){return this.global}*getChildren(){for(const{childNode:e}of Ll(this))yield e}dispose(){this.dispatchEvent({type:"dispose"})}traverse(e){e(this);for(const t of this.getChildren())t.traverse(e)}getCacheKey(e=!1){return!0!==(e=e||this.version!==this._cacheKeyVersion)&&null!==this._cacheKey||(this._cacheKey=Ul(this,e),this._cacheKeyVersion=this.version),this._cacheKey}getScope(){return this}getHash(){return this.uuid}getUpdateType(){return this.updateType}getUpdateBeforeType(){return this.updateBeforeType}getUpdateAfterType(){return this.updateAfterType}getElementType(e){const t=this.getNodeType(e);return e.getElementType(t)}getNodeType(e){const t=e.getNodeProperties(this);return t.outputNode?t.outputNode.getNodeType(e):this.nodeType}getShared(e){const t=this.getHash(e);return e.getNodeFromHash(t)||this}setup(e){const t=e.getNodeProperties(this);let s=0;for(const e of this.getChildren())t["node"+s++]=e;return null}analyze(e){if(1===e.increaseUsage(this)){const t=e.getNodeProperties(this);for(const s of Object.values(t))s&&!0===s.isNode&&s.build(e)}}generate(e,t){const{outputNode:s}=e.getNodeProperties(this);if(s&&!0===s.isNode)return s.build(e,t)}updateBefore(){console.warn("Abstract function.")}updateAfter(){console.warn("Abstract function.")}update(){console.warn("Abstract function.")}build(e,t=null){const s=this.getShared(e);if(this!==s)return s.build(e,t);e.addNode(this),e.addChain(this);let i=null;const r=e.getBuildStage();if("setup"===r){this.updateReference(e);const t=e.getNodeProperties(this);if(!0!==t.initialized){e.stack.nodes.length;t.initialized=!0,t.outputNode=this.setup(e),null!==t.outputNode&&e.stack.nodes.length;for(const s of Object.values(t))s&&!0===s.isNode&&s.build(e)}}else if("analyze"===r)this.analyze(e);else if("generate"===r){if(1===this.generate.length){const s=this.getNodeType(e),r=e.getDataFromNode(this);i=r.snippet,void 0===i&&(i=this.generate(e)||"",r.snippet=i),i=e.format(i,s,t)}else i=this.generate(e,t)||""}return e.removeChain(this),i}getSerializeChildren(){return Ll(this)}serialize(e){const t=this.getSerializeChildren(),s={};for(const{property:i,index:r,childNode:n}of t)void 0!==r?(void 0===s[i]&&(s[i]=Number.isInteger(r)?[]:{}),s[i][r]=n.toJSON(e.meta).uuid):s[i]=n.toJSON(e.meta).uuid;Object.keys(s).length>0&&(e.inputNodes=s)}deserialize(e){if(void 0!==e.inputNodes){const t=e.meta.nodes;for(const s in e.inputNodes)if(Array.isArray(e.inputNodes[s])){const i=[];for(const r of e.inputNodes[s])i.push(t[r]);this[s]=i}else if("object"==typeof e.inputNodes[s]){const i={};for(const r in e.inputNodes[s]){const n=e.inputNodes[s][r];i[r]=t[n]}this[s]=i}else{const i=e.inputNodes[s];this[s]=t[i]}}}toJSON(e){const{uuid:t,type:s}=this,i=void 0===e||"string"==typeof e;i&&(e={textures:{},images:{},nodes:{}});let r=e.nodes[t];function n(e){const t=[];for(const s in e){const i=e[s];delete i.metadata,t.push(i)}return t}if(void 0===r&&(r={uuid:t,type:s,meta:e,metadata:{version:4.6,type:"Node",generator:"Node.toJSON"}},!0!==i&&(e.nodes[r.uuid]=r),this.serialize(r),delete r.meta),i){const t=n(e.textures),s=n(e.images),i=n(e.nodes);t.length>0&&(r.textures=t),s.length>0&&(r.images=s),i.length>0&&(r.nodes=i)}return r}}function Ql(e,t){const s="Node",i=e+s;if("function"!=typeof t)throw new Error(`TSL.Node: Node class ${e} is not a class`);if(Jl.has(i))console.warn(`TSL.Node: Redefinition of node class ${i}`);else{if(e.slice(-4)!==s)return Jl.set(i,t),t.type=i,i;console.warn(`TSL.Node: Node class ${i} should not have '${s}' suffix.`)}}function eu(e){const t=Jl.get(e);if(void 0!==t)return new t}Kl.type=Ql("",Kl);class tu extends Kl{constructor(e,t){super(),this.node=e,this.indexNode=t,this.isArrayElementNode=!0}getNodeType(e){return this.node.getElementType(e)}generate(e){return`${this.node.build(e)}[ ${this.indexNode.build(e,"uint")} ]`}}tu.type=Ql("ArrayElement",tu);class su extends Kl{constructor(e,t){super(),this.node=e,this.convertTo=t}getNodeType(e){const t=this.node.getNodeType(e);let s=null;for(const i of this.convertTo.split("|"))null!==s&&e.getTypeLength(t)!==e.getTypeLength(i)||(s=i);return s}serialize(e){super.serialize(e),e.convertTo=this.convertTo}deserialize(e){super.deserialize(e),this.convertTo=e.convertTo}generate(e,t){const s=this.node,i=this.getNodeType(e),r=s.build(e,i);return e.format(r,i,t)}}su.type=Ql("Convert",su);class iu extends Kl{constructor(e){super(e),this.isTempNode=!0}hasDependencies(e){return e.getDataFromNode(this).usageCount>1}build(e,t){if("generate"===e.getBuildStage()){const s=e.getVectorType(this.getNodeType(e,t)),i=e.getDataFromNode(this);if(void 0!==i.propertyName)return e.format(i.propertyName,s,t);if("void"!==s&&"void"!==t&&this.hasDependencies(e)){const r=super.build(e,s),n=e.getVarFromNode(this,null,s),o=e.getPropertyName(n);return e.addLineFlowCode(`${o} = ${r}`),i.snippet=r,i.propertyName=o,e.format(i.propertyName,s,t)}}return super.build(e,t)}}iu.type=Ql("Temp",iu);class ru extends iu{constructor(e=[],t=null){super(t),this.nodes=e}getNodeType(e){return null!==this.nodeType?e.getVectorType(this.nodeType):e.getTypeFromLength(this.nodes.reduce(((t,s)=>t+e.getTypeLength(s.getNodeType(e))),0))}generate(e,t){const s=this.getNodeType(e),i=this.nodes,r=e.getComponentType(s),n=[];for(const t of i){let s=t.build(e);const i=e.getComponentType(t.getNodeType(e));i!==r&&(s=e.format(s,i,r)),n.push(s)}const o=`${e.getType(s)}( ${n.join(", ")} )`;return e.format(o,s,t)}}ru.type=Ql("Join",ru);const nu=Yl.join("");class ou extends Kl{constructor(e,t="x"){super(),this.node=e,this.components=t,this.isSplitNode=!0}getVectorLength(){let e=this.components.length;for(const t of this.components)e=Math.max(Yl.indexOf(t)+1,e);return e}getComponentType(e){return e.getComponentType(this.node.getNodeType(e))}getNodeType(e){return e.getTypeFromLength(this.components.length,this.getComponentType(e))}generate(e,t){const s=this.node,i=e.getTypeLength(s.getNodeType(e));let r=null;if(i>1){let n=null;this.getVectorLength()>=i&&(n=e.getTypeFromLength(this.getVectorLength(),this.getComponentType(e)));const o=s.build(e,n);r=this.components.length===i&&this.components===nu.slice(0,this.components.length)?e.format(o,n,t):e.format(`${o}.${this.components}`,this.getNodeType(e),t)}else r=s.build(e,t);return r}serialize(e){super.serialize(e),e.components=this.components}deserialize(e){super.deserialize(e),this.components=e.components}}ou.type=Ql("Split",ou);class au extends iu{constructor(e,t,s){super(),this.sourceNode=e,this.components=t,this.targetNode=s}getNodeType(e){return this.sourceNode.getNodeType(e)}generate(e){const{sourceNode:t,components:s,targetNode:i}=this,r=this.getNodeType(e),n=e.getTypeFromLength(s.length),o=i.build(e,n),a=t.build(e,r),h=e.getTypeLength(r),l=[];for(let e=0;ee.replace(/r|s/g,"x").replace(/g|t/g,"y").replace(/b|p/g,"z").replace(/a|q/g,"w"),gu=e=>mu(e).split("").sort().join(""),fu={setup(e,t){const s=t.shift();return e(ku(s),...t)},get(e,t,s){if("string"==typeof t&&void 0===e[t]){if(!0!==e.isStackNode&&"assign"===t)return(...e)=>(cu.assign(s,...e),s);if(du.has(t)){const i=du.get(t);return e.isStackNode?(...e)=>s.add(i(...e)):(...e)=>i(s,...e)}if("self"===t)return e;if(t.endsWith("Assign")&&du.has(t.slice(0,t.length-6))){const i=du.get(t.slice(0,t.length-6));return e.isStackNode?(...e)=>s.assign(e[0],i(...e)):(...e)=>s.assign(i(s,...e))}if(!0===/^[xyzwrgbastpq]{1,4}$/.test(t))return t=mu(t),Du(new ou(s,t));if(!0===/^set[XYZWRGBASTPQ]{1,4}$/.test(t))return t=gu(t.slice(3).toLowerCase()),s=>Du(new au(e,t,s));if(!0===/^flip[XYZWRGBASTPQ]{1,4}$/.test(t))return t=gu(t.slice(4).toLowerCase()),()=>Du(new hu(Du(e),t));if("width"===t||"height"===t||"depth"===t)return"width"===t?t="x":"height"===t?t="y":"depth"===t&&(t="z"),Du(new ou(e,t));if(!0===/^\d+$/.test(t))return Du(new tu(s,new uu(Number(t),"uint")))}return Reflect.get(e,t,s)},set:(e,t,s,i)=>"string"!=typeof t||void 0!==e[t]||!0!==/^[xyzwrgbastpq]{1,4}$/.test(t)&&"width"!==t&&"height"!==t&&"depth"!==t&&!0!==/^\d+$/.test(t)?Reflect.set(e,t,s,i):(i[t].assign(s),!0)},yu=new WeakMap,xu=new WeakMap,bu=function(e,t=null){for(const s in e)e[s]=Du(e[s],t);return e},vu=function(e,t=null){const s=e.length;for(let i=0;iDu(null!==i?Object.assign(e,i):e);return null===t?(...t)=>r(new e(...Gu(t))):null!==s?(s=Du(s),(...i)=>r(new e(t,...Gu(i),s))):(...s)=>r(new e(t,...Gu(s)))},_u=function(e,...t){return Du(new e(...Gu(t)))};class wu extends Kl{constructor(e,t){super(),this.shaderNode=e,this.inputNodes=t}getNodeType(e){return this.shaderNode.nodeType||this.getOutputNode(e).getNodeType(e)}call(e){const{shaderNode:t,inputNodes:s}=this,i=e.getNodeProperties(t);if(i.onceOutput)return i.onceOutput;let r=null;if(t.layout){let i=xu.get(e.constructor);void 0===i&&(i=new WeakMap,xu.set(e.constructor,i));let n=i.get(t);void 0===n&&(n=Du(e.buildFunctionNode(t)),i.set(t,n)),null!==e.currentFunctionNode&&e.currentFunctionNode.includes.push(n),r=Du(n.call(s))}else{const i=t.jsFunc,n=null!==s?i(s,e):i(e);r=Du(n)}return t.once&&(i.onceOutput=r),r}getOutputNode(e){const t=e.getNodeProperties(this);return null===t.outputNode&&(t.outputNode=this.setupOutput(e)),t.outputNode}setup(e){return this.getOutputNode(e)}setupOutput(e){return e.addStack(),e.stack.outputNode=this.call(e),e.removeStack()}generate(e,t){return this.getOutputNode(e).build(e,t)}}class Su extends Kl{constructor(e,t){super(t),this.jsFunc=e,this.layout=null,this.global=!0,this.once=!1}setLayout(e){return this.layout=e,this}call(e=null){return ku(e),Du(new wu(this,e))}setup(){return this.call()}}const Mu=[!1,!0],Au=[0,1,2,3],Nu=[-1,-2],Ru=[.5,1.5,1/3,1e-6,1e6,Math.PI,2*Math.PI,1/Math.PI,2/Math.PI,1/(2*Math.PI),Math.PI/2],Cu=new Map;for(const e of Mu)Cu.set(e,new uu(e));const Eu=new Map;for(const e of Au)Eu.set(e,new uu(e,"uint"));const Bu=new Map([...Eu].map((e=>new uu(e.value,"int"))));for(const e of Nu)Bu.set(e,new uu(e,"int"));const Iu=new Map([...Bu].map((e=>new uu(e.value))));for(const e of Ru)Iu.set(e,new uu(e));for(const e of Ru)Iu.set(-e,new uu(-e));const Pu={bool:Cu,uint:Eu,ints:Bu,float:Iu},Fu=new Map([...Cu,...Iu]),zu=(e,t)=>Fu.has(e)?Fu.get(e):!0===e.isNode?e:new uu(e,t),Uu=function(e,t=null){return(...s)=>{if((0===s.length||!["bool","float","int","uint"].includes(e)&&s.every((e=>"object"!=typeof e)))&&(s=[Vl(e,...s)]),1===s.length&&null!==t&&t.has(s[0]))return Du(t.get(s[0]));if(1===s.length){const t=zu(s[0],e);return(e=>{try{return e.getNodeType()}catch(e){return}})(t)===e?Du(t):Du(new su(t,e))}const i=s.map((e=>zu(e)));return Du(new ru(i,e))}},Lu=e=>"object"==typeof e&&null!==e?e.value:e,Ou=e=>null!=e?e.nodeType||e.convertTo||("string"==typeof e?e:null):null;function Vu(e,t){return new Proxy(new Su(e,t),fu)}const Du=(e,t=null)=>function(e,t=null){const s=Ol(e);if("node"===s){let t=yu.get(e);return void 0===t&&(t=new Proxy(e,fu),yu.set(e,t),yu.set(t,t)),t}return null===t&&("float"===s||"boolean"===s)||s&&"shader"!==s&&"string"!==s?Du(zu(e,t)):"shader"===s?ju(e):e}(e,t),ku=(e,t=null)=>new bu(e,t),Gu=(e,t=null)=>new vu(e,t),Wu=(...e)=>new Tu(...e),Hu=(...e)=>new _u(...e),ju=(e,t)=>{const s=new Vu(e,t),i=(...e)=>{let t;return ku(e),t=e[0]&&e[0].isNode?[...e]:e[0],s.call(t)};return i.shaderNode=s,i.setLayout=e=>(s.setLayout(e),i),i.once=()=>(s.once=!0,i),i},qu=(...e)=>(console.warn("TSL.ShaderNode: tslFn() has been renamed to Fn()."),ju(...e));pu("toGlobal",(e=>(e.global=!0,e)));const $u=e=>{cu=e},Xu=()=>cu,Yu=(...e)=>cu.If(...e);function Ju(e){return cu&&cu.add(e),e}pu("append",Ju);const Zu=new Uu("color"),Ku=new Uu("float",Pu.float),Qu=new Uu("int",Pu.ints),ec=new Uu("uint",Pu.uint),tc=new Uu("bool",Pu.bool),sc=new Uu("vec2"),ic=new Uu("ivec2"),rc=new Uu("uvec2"),nc=new Uu("bvec2"),oc=new Uu("vec3"),ac=new Uu("ivec3"),hc=new Uu("uvec3"),lc=new Uu("bvec3"),uc=new Uu("vec4"),cc=new Uu("ivec4"),dc=new Uu("uvec4"),pc=new Uu("bvec4"),mc=new Uu("mat2"),gc=new Uu("mat3"),fc=new Uu("mat4"),yc=(e="")=>Du(new uu(e,"string")),xc=e=>Du(new uu(e,"ArrayBuffer"));pu("toColor",Zu),pu("toFloat",Ku),pu("toInt",Qu),pu("toUint",ec),pu("toBool",tc),pu("toVec2",sc),pu("toIVec2",ic),pu("toUVec2",rc),pu("toBVec2",nc),pu("toVec3",oc),pu("toIVec3",ac),pu("toUVec3",hc),pu("toBVec3",lc),pu("toVec4",uc),pu("toIVec4",cc),pu("toUVec4",dc),pu("toBVec4",pc),pu("toMat2",mc),pu("toMat3",gc),pu("toMat4",fc);const bc=Wu(tu),vc=(e,t)=>Du(new su(Du(e),t)),Tc=(e,t)=>Du(new ou(Du(e),t));pu("element",bc),pu("convert",vc);class _c extends Kl{constructor(e,t=!1){super("string"),this.name=e,this.version=0,this.shared=t,this.isUniformGroup=!0}set needsUpdate(e){!0===e&&this.version++}serialize(e){super.serialize(e),e.name=this.name,e.version=this.version,e.shared=this.shared}deserialize(e){super.deserialize(e),this.name=e.name,this.version=e.version,this.shared=e.shared}}_c.type=Ql("UniformGroup",_c);const wc=e=>new _c(e),Sc=e=>new _c(e,!0),Mc=Sc("frame"),Ac=Sc("render"),Nc=wc("object");class Rc extends lu{constructor(e,t=null){super(e,t),this.isUniformNode=!0,this.name="",this.groupNode=Nc}label(e){return this.name=e,this}setGroup(e){return this.groupNode=e,this}getGroup(){return this.groupNode}getUniformHash(e){return this.getHash(e)}onUpdate(e,t){const s=this.getSelf();return e=e.bind(s),super.onUpdate((t=>{const i=e(t,s);void 0!==i&&(this.value=i)}),t)}generate(e,t){const s=this.getNodeType(e),i=this.getUniformHash(e);let r=e.getNodeFromHash(i);void 0===r&&(e.setHashNode(this,i),r=this);const n=r.getInputType(e),o=e.getUniformFromNode(r,n,e.shaderStage,this.name||e.context.label),a=e.getPropertyName(o);return void 0!==e.context.label&&delete e.context.label,e.format(a,s,t)}}Rc.type=Ql("Uniform",Rc);const Cc=(e,t)=>{const s=Ou(t||e),i=e&&!0===e.isNode?e.node&&e.node.value||e.value:e;return Du(new Rc(i,s))};class Ec extends Kl{constructor(e,t=null,s=!1){super(e),this.name=t,this.varying=s,this.isPropertyNode=!0}getHash(e){return this.name||super.getHash(e)}isGlobal(){return!0}generate(e){let t;return!0===this.varying?(t=e.getVaryingFromNode(this,this.name),t.needsInterpolation=!0):t=e.getVarFromNode(this,this.name),e.getPropertyName(t)}}Ec.type=Ql("Property",Ec);const Bc=(e,t)=>Du(new Ec(e,t)),Ic=(e,t)=>Du(new Ec(e,t,!0)),Pc=Hu(Ec,"vec4","DiffuseColor"),Fc=Hu(Ec,"vec3","EmissiveColor"),zc=Hu(Ec,"float","Roughness"),Uc=Hu(Ec,"float","Metalness"),Lc=Hu(Ec,"float","Clearcoat"),Oc=Hu(Ec,"float","ClearcoatRoughness"),Vc=Hu(Ec,"vec3","Sheen"),Dc=Hu(Ec,"float","SheenRoughness"),kc=Hu(Ec,"float","Iridescence"),Gc=Hu(Ec,"float","IridescenceIOR"),Wc=Hu(Ec,"float","IridescenceThickness"),Hc=Hu(Ec,"float","AlphaT"),jc=Hu(Ec,"float","Anisotropy"),qc=Hu(Ec,"vec3","AnisotropyT"),$c=Hu(Ec,"vec3","AnisotropyB"),Xc=Hu(Ec,"color","SpecularColor"),Yc=Hu(Ec,"float","SpecularF90"),Jc=Hu(Ec,"float","Shininess"),Zc=Hu(Ec,"vec4","Output"),Kc=Hu(Ec,"float","dashSize"),Qc=Hu(Ec,"float","gapSize"),ed=Hu(Ec,"float","pointWidth"),td=Hu(Ec,"float","IOR"),sd=Hu(Ec,"float","Transmission"),id=Hu(Ec,"float","Thickness"),rd=Hu(Ec,"float","AttenuationDistance"),nd=Hu(Ec,"color","AttenuationColor"),od=Hu(Ec,"float","Dispersion");class ad extends iu{constructor(e,t){super(),this.targetNode=e,this.sourceNode=t}hasDependencies(){return!1}getNodeType(e,t){return"void"!==t?this.targetNode.getNodeType(e):"void"}needsSplitAssign(e){const{targetNode:t}=this;if(!1===e.isAvailable("swizzleAssign")&&t.isSplitNode&&t.components.length>1){const s=e.getTypeLength(t.node.getNodeType(e));return Yl.join("").slice(0,s)!==t.components}return!1}generate(e,t){const{targetNode:s,sourceNode:i}=this,r=this.needsSplitAssign(e),n=s.getNodeType(e),o=s.context({assign:!0}).build(e),a=i.build(e,n),h=i.getNodeType(e),l=e.getDataFromNode(this);let u;if(!0===l.initialized)"void"!==t&&(u=o);else if(r){const i=e.getVarFromNode(this,null,n),r=e.getPropertyName(i);e.addLineFlowCode(`${r} = ${a}`);const h=s.node.context({assign:!0}).build(e);for(let t=0;t(t=t.length>1||t[0]&&!0===t[0].isNode?Gu(t):ku(t[0]),Du(new ld(Du(e),t)));pu("call",ud);class cd extends iu{constructor(e,t,s,...i){if(super(),i.length>0){let r=new cd(e,t,s);for(let t=0;t>"===s||"<<"===s)return e.getIntegerType(n);if("!"===s||"=="===s||"&&"===s||"||"===s||"^^"===s)return"bool";if("<"===s||">"===s||"<="===s||">="===s){const s=t?e.getTypeLength(t):Math.max(e.getTypeLength(n),e.getTypeLength(o));return s>1?`bvec${s}`:"bool"}return"float"===n&&e.isMatrix(o)?o:e.isMatrix(n)&&e.isVector(o)?e.getVectorFromMatrix(n):e.isVector(n)&&e.isMatrix(o)?e.getVectorFromMatrix(o):e.getTypeLength(o)>e.getTypeLength(n)?o:n}generate(e,t){const s=this.op,i=this.aNode,r=this.bNode,n=this.getNodeType(e,t);let o=null,a=null;"void"!==n?(o=i.getNodeType(e),a=void 0!==r?r.getNodeType(e):null,"<"===s||">"===s||"<="===s||">="===s||"=="===s?e.isVector(o)?a=o:o!==a&&(o=a="float"):">>"===s||"<<"===s?(o=n,a=e.changeComponentType(a,"uint")):e.isMatrix(o)&&e.isVector(a)?a=e.getVectorFromMatrix(o):o=e.isVector(o)&&e.isMatrix(a)?e.getVectorFromMatrix(a):a=n):o=a=n;const h=i.build(e,o),l=void 0!==r?r.build(e,a):null,u=e.getTypeLength(t),c=e.getFunctionOperator(s);return"void"!==t?"<"===s&&u>1?e.useComparisonMethod?e.format(`${e.getMethod("lessThan",t)}( ${h}, ${l} )`,n,t):e.format(`( ${h} < ${l} )`,n,t):"<="===s&&u>1?e.useComparisonMethod?e.format(`${e.getMethod("lessThanEqual",t)}( ${h}, ${l} )`,n,t):e.format(`( ${h} <= ${l} )`,n,t):">"===s&&u>1?e.useComparisonMethod?e.format(`${e.getMethod("greaterThan",t)}( ${h}, ${l} )`,n,t):e.format(`( ${h} > ${l} )`,n,t):">="===s&&u>1?e.useComparisonMethod?e.format(`${e.getMethod("greaterThanEqual",t)}( ${h}, ${l} )`,n,t):e.format(`( ${h} >= ${l} )`,n,t):"!"===s||"~"===s?e.format(`(${s}${h})`,o,t):c?e.format(`${c}( ${h}, ${l} )`,n,t):e.format(`( ${h} ${s} ${l} )`,n,t):"void"!==o?c?e.format(`${c}( ${h}, ${l} )`,n,t):e.format(`${h} ${s} ${l}`,n,t):void 0}serialize(e){super.serialize(e),e.op=this.op}deserialize(e){super.deserialize(e),this.op=e.op}}cd.type=Ql("Operator",cd);const dd=Wu(cd,"+"),pd=Wu(cd,"-"),md=Wu(cd,"*"),gd=Wu(cd,"/"),fd=Wu(cd,"%"),yd=Wu(cd,"=="),xd=Wu(cd,"!="),bd=Wu(cd,"<"),vd=Wu(cd,">"),Td=Wu(cd,"<="),_d=Wu(cd,">="),wd=Wu(cd,"&&"),Sd=Wu(cd,"||"),Md=Wu(cd,"!"),Ad=Wu(cd,"^^"),Nd=Wu(cd,"&"),Rd=Wu(cd,"~"),Cd=Wu(cd,"|"),Ed=Wu(cd,"^"),Bd=Wu(cd,"<<"),Id=Wu(cd,">>");pu("add",dd),pu("sub",pd),pu("mul",md),pu("div",gd),pu("modInt",fd),pu("equal",yd),pu("notEqual",xd),pu("lessThan",bd),pu("greaterThan",vd),pu("lessThanEqual",Td),pu("greaterThanEqual",_d),pu("and",wd),pu("or",Sd),pu("not",Md),pu("xor",Ad),pu("bitAnd",Nd),pu("bitNot",Rd),pu("bitOr",Cd),pu("bitXor",Ed),pu("shiftLeft",Bd),pu("shiftRight",Id);const Pd=(...e)=>(console.warn("TSL.OperatorNode: .remainder() has been renamed to .modInt()."),fd(...e));pu("remainder",Pd);class Fd extends iu{constructor(e,t,s=null,i=null){super(),this.method=e,this.aNode=t,this.bNode=s,this.cNode=i}getInputType(e){const t=this.aNode.getNodeType(e),s=this.bNode?this.bNode.getNodeType(e):null,i=this.cNode?this.cNode.getNodeType(e):null,r=e.isMatrix(t)?0:e.getTypeLength(t),n=e.isMatrix(s)?0:e.getTypeLength(s),o=e.isMatrix(i)?0:e.getTypeLength(i);return r>n&&r>o?t:n>o?s:o>r?i:t}getNodeType(e){const t=this.method;return t===Fd.LENGTH||t===Fd.DISTANCE||t===Fd.DOT?"float":t===Fd.CROSS?"vec3":t===Fd.ALL?"bool":t===Fd.EQUALS?e.changeComponentType(this.aNode.getNodeType(e),"bool"):t===Fd.MOD?this.aNode.getNodeType(e):this.getInputType(e)}generate(e,t){const s=this.method,i=this.getNodeType(e),r=this.getInputType(e),n=this.aNode,o=this.bNode,a=this.cNode,h=!0===e.renderer.isWebGLRenderer;if(s===Fd.TRANSFORM_DIRECTION){let s=n,i=o;e.isMatrix(s.getNodeType(e))?i=uc(oc(i),0):s=uc(oc(s),0);const r=md(s,i).xyz;return Kd(r).build(e,t)}if(s===Fd.NEGATE)return e.format("( - "+n.build(e,r)+" )",i,t);if(s===Fd.ONE_MINUS)return pd(1,n).build(e,t);if(s===Fd.RECIPROCAL)return gd(1,n).build(e,t);if(s===Fd.DIFFERENCE)return op(pd(n,o)).build(e,t);{const l=[];return s===Fd.CROSS||s===Fd.MOD?l.push(n.build(e,i),o.build(e,i)):h&&s===Fd.STEP?l.push(n.build(e,1===e.getTypeLength(n.getNodeType(e))?"float":r),o.build(e,r)):h&&(s===Fd.MIN||s===Fd.MAX)||s===Fd.MOD?l.push(n.build(e,r),o.build(e,1===e.getTypeLength(o.getNodeType(e))?"float":r)):s===Fd.REFRACT?l.push(n.build(e,r),o.build(e,r),a.build(e,"float")):s===Fd.MIX?l.push(n.build(e,r),o.build(e,r),a.build(e,1===e.getTypeLength(a.getNodeType(e))?"float":r)):(l.push(n.build(e,r)),null!==o&&l.push(o.build(e,r)),null!==a&&l.push(a.build(e,r))),e.format(`${e.getMethod(s,i)}( ${l.join(", ")} )`,i,t)}}serialize(e){super.serialize(e),e.method=this.method}deserialize(e){super.deserialize(e),this.method=e.method}}Fd.ALL="all",Fd.ANY="any",Fd.EQUALS="equals",Fd.RADIANS="radians",Fd.DEGREES="degrees",Fd.EXP="exp",Fd.EXP2="exp2",Fd.LOG="log",Fd.LOG2="log2",Fd.SQRT="sqrt",Fd.INVERSE_SQRT="inversesqrt",Fd.FLOOR="floor",Fd.CEIL="ceil",Fd.NORMALIZE="normalize",Fd.FRACT="fract",Fd.SIN="sin",Fd.COS="cos",Fd.TAN="tan",Fd.ASIN="asin",Fd.ACOS="acos",Fd.ATAN="atan",Fd.ABS="abs",Fd.SIGN="sign",Fd.LENGTH="length",Fd.NEGATE="negate",Fd.ONE_MINUS="oneMinus",Fd.DFDX="dFdx",Fd.DFDY="dFdy",Fd.ROUND="round",Fd.RECIPROCAL="reciprocal",Fd.TRUNC="trunc",Fd.FWIDTH="fwidth",Fd.BITCAST="bitcast",Fd.TRANSPOSE="transpose",Fd.ATAN2="atan2",Fd.MIN="min",Fd.MAX="max",Fd.MOD="mod",Fd.STEP="step",Fd.REFLECT="reflect",Fd.DISTANCE="distance",Fd.DIFFERENCE="difference",Fd.DOT="dot",Fd.CROSS="cross",Fd.POW="pow",Fd.TRANSFORM_DIRECTION="transformDirection",Fd.MIX="mix",Fd.CLAMP="clamp",Fd.REFRACT="refract",Fd.SMOOTHSTEP="smoothstep",Fd.FACEFORWARD="faceforward",Fd.type=Ql("Math",Fd);const zd=Ku(1e-6),Ud=Ku(1e6),Ld=Ku(Math.PI),Od=Ku(2*Math.PI),Vd=Wu(Fd,Fd.ALL),Dd=Wu(Fd,Fd.ANY),kd=Wu(Fd,Fd.EQUALS),Gd=Wu(Fd,Fd.RADIANS),Wd=Wu(Fd,Fd.DEGREES),Hd=Wu(Fd,Fd.EXP),jd=Wu(Fd,Fd.EXP2),qd=Wu(Fd,Fd.LOG),$d=Wu(Fd,Fd.LOG2),Xd=Wu(Fd,Fd.SQRT),Yd=Wu(Fd,Fd.INVERSE_SQRT),Jd=Wu(Fd,Fd.FLOOR),Zd=Wu(Fd,Fd.CEIL),Kd=Wu(Fd,Fd.NORMALIZE),Qd=Wu(Fd,Fd.FRACT),ep=Wu(Fd,Fd.SIN),tp=Wu(Fd,Fd.COS),sp=Wu(Fd,Fd.TAN),ip=Wu(Fd,Fd.ASIN),rp=Wu(Fd,Fd.ACOS),np=Wu(Fd,Fd.ATAN),op=Wu(Fd,Fd.ABS),ap=Wu(Fd,Fd.SIGN),hp=Wu(Fd,Fd.LENGTH),lp=Wu(Fd,Fd.NEGATE),up=Wu(Fd,Fd.ONE_MINUS),cp=Wu(Fd,Fd.DFDX),dp=Wu(Fd,Fd.DFDY),pp=Wu(Fd,Fd.ROUND),mp=Wu(Fd,Fd.RECIPROCAL),gp=Wu(Fd,Fd.TRUNC),fp=Wu(Fd,Fd.FWIDTH),yp=Wu(Fd,Fd.BITCAST),xp=Wu(Fd,Fd.TRANSPOSE),bp=Wu(Fd,Fd.ATAN2),vp=Wu(Fd,Fd.MIN),Tp=Wu(Fd,Fd.MAX),_p=Wu(Fd,Fd.MOD),wp=Wu(Fd,Fd.STEP),Sp=Wu(Fd,Fd.REFLECT),Mp=Wu(Fd,Fd.DISTANCE),Ap=Wu(Fd,Fd.DIFFERENCE),Np=Wu(Fd,Fd.DOT),Rp=Wu(Fd,Fd.CROSS),Cp=Wu(Fd,Fd.POW),Ep=Wu(Fd,Fd.POW,2),Bp=Wu(Fd,Fd.POW,3),Ip=Wu(Fd,Fd.POW,4),Pp=Wu(Fd,Fd.TRANSFORM_DIRECTION),Fp=e=>md(ap(e),Cp(op(e),1/3)),zp=e=>Np(e,e),Up=Wu(Fd,Fd.MIX),Lp=(e,t=0,s=1)=>Du(new Fd(Fd.CLAMP,Du(e),Du(t),Du(s))),Op=e=>Lp(e),Vp=Wu(Fd,Fd.REFRACT),Dp=Wu(Fd,Fd.SMOOTHSTEP),kp=Wu(Fd,Fd.FACEFORWARD),Gp=ju((([e])=>{const t=Np(e.xy,sc(12.9898,78.233)),s=_p(t,Ld);return Qd(ep(s).mul(43758.5453))})),Wp=(e,t,s)=>Up(t,s,e),Hp=(e,t,s)=>Dp(t,s,e);pu("all",Vd),pu("any",Dd),pu("equals",kd),pu("radians",Gd),pu("degrees",Wd),pu("exp",Hd),pu("exp2",jd),pu("log",qd),pu("log2",$d),pu("sqrt",Xd),pu("inverseSqrt",Yd),pu("floor",Jd),pu("ceil",Zd),pu("normalize",Kd),pu("fract",Qd),pu("sin",ep),pu("cos",tp),pu("tan",sp),pu("asin",ip),pu("acos",rp),pu("atan",np),pu("abs",op),pu("sign",ap),pu("length",hp),pu("lengthSq",zp),pu("negate",lp),pu("oneMinus",up),pu("dFdx",cp),pu("dFdy",dp),pu("round",pp),pu("reciprocal",mp),pu("trunc",gp),pu("fwidth",fp),pu("atan2",bp),pu("min",vp),pu("max",Tp),pu("mod",_p),pu("step",wp),pu("reflect",Sp),pu("distance",Mp),pu("dot",Np),pu("cross",Rp),pu("pow",Cp),pu("pow2",Ep),pu("pow3",Bp),pu("pow4",Ip),pu("transformDirection",Pp),pu("mix",Wp),pu("clamp",Lp),pu("refract",Vp),pu("smoothstep",Hp),pu("faceForward",kp),pu("difference",Ap),pu("saturate",Op),pu("cbrt",Fp),pu("transpose",xp),pu("rand",Gp);class jp extends Kl{constructor(e,t,s=null){super(),this.condNode=e,this.ifNode=t,this.elseNode=s}getNodeType(e){const t=this.ifNode.getNodeType(e);if(null!==this.elseNode){const s=this.elseNode.getNodeType(e);if(e.getTypeLength(s)>e.getTypeLength(t))return s}return t}setup(e){const t=e.getNodeProperties(this);t.condNode=this.condNode.cache(),t.ifNode=this.ifNode.cache(),t.elseNode=this.elseNode?this.elseNode.cache():null}generate(e,t){const s=this.getNodeType(e),i=e.getDataFromNode(this);if(void 0!==i.nodeProperty)return i.nodeProperty;const{condNode:r,ifNode:n,elseNode:o}=e.getNodeProperties(this),a="void"!==t,h=a?Bc(s).build(e):"";i.nodeProperty=h;const l=r.build(e,"bool");e.addFlowCode(`\n${e.tab}if ( ${l} ) {\n\n`).addFlowTab();let u=n.build(e,s);if(u&&(u=a?h+" = "+u+";":"return "+u+";"),e.removeFlowTab().addFlowCode(e.tab+"\t"+u+"\n\n"+e.tab+"}"),null!==o){e.addFlowCode(" else {\n\n").addFlowTab();let t=o.build(e,s);t&&(t=a?h+" = "+t+";":"return "+t+";"),e.removeFlowTab().addFlowCode(e.tab+"\t"+t+"\n\n"+e.tab+"}\n\n")}else e.addFlowCode("\n\n");return e.format(h,s,t)}}jp.type=Ql("Conditional",jp);const qp=Wu(jp);pu("select",qp);const $p=(...e)=>(console.warn("TSL.ConditionalNode: cond() has been renamed to select()."),qp(...e));pu("cond",$p);class Xp extends Kl{constructor(e,t={}){super(),this.isContextNode=!0,this.node=e,this.value=t}getScope(){return this.node.getScope()}getNodeType(e){return this.node.getNodeType(e)}analyze(e){this.node.build(e)}setup(e){const t=e.getContext();e.setContext({...e.context,...this.value});const s=this.node.build(e);return e.setContext(t),s}generate(e,t){const s=e.getContext();e.setContext({...e.context,...this.value});const i=this.node.build(e,t);return e.setContext(s),i}}Xp.type=Ql("Context",Xp);const Yp=Wu(Xp),Jp=(e,t)=>Yp(e,{label:t});pu("context",Yp),pu("label",Jp);class Zp extends Kl{constructor(e,t=null){super(),this.node=e,this.name=t,this.global=!0,this.isVarNode=!0}getHash(e){return this.name||super.getHash(e)}getNodeType(e){return this.node.getNodeType(e)}generate(e){const{node:t,name:s}=this,i=e.getVarFromNode(this,s,e.getVectorType(this.getNodeType(e))),r=e.getPropertyName(i),n=t.build(e,i.type);return e.addLineFlowCode(`${r} = ${n}`),r}}Zp.type=Ql("Var",Zp);const Kp=Wu(Zp);pu("temp",Kp),pu("toVar",((...e)=>Kp(...e).append()));class Qp extends Kl{constructor(e,t=null){super(),this.node=e,this.name=t,this.isVaryingNode=!0}isGlobal(){return!0}getHash(e){return this.name||super.getHash(e)}getNodeType(e){return this.node.getNodeType(e)}setupVarying(e){const t=e.getNodeProperties(this);let s=t.varying;if(void 0===s){const i=this.name,r=this.getNodeType(e);t.varying=s=e.getVaryingFromNode(this,i,r),t.node=this.node}return s.needsInterpolation||(s.needsInterpolation="fragment"===e.shaderStage),s}setup(e){this.setupVarying(e)}analyze(e){return this.setupVarying(e),this.node.analyze(e)}generate(e){const t=e.getNodeProperties(this),s=this.setupVarying(e);if(void 0===t.propertyName){const i=this.getNodeType(e),r=e.getPropertyName(s,Wl.VERTEX);e.flowNodeFromShaderStage(Wl.VERTEX,this.node,i,r),t.propertyName=r}return e.getPropertyName(s)}}Qp.type=Ql("Varying",Qp);const em=Wu(Qp);pu("varying",em);const tm=e=>{let t=null;return e===Zt?t="Linear":e===Jt&&(t="sRGB"),t},sm=(e,t)=>tm(e)+"To"+tm(t);class im extends iu{constructor(e,t=null,s=null){super("vec4"),this.colorNode=e,this.target=t,this.source=s}setup(e){const{renderer:t,context:s}=e,i=this.source||s.outputColorSpace||t.outputColorSpace,r=this.target||s.outputColorSpace||t.outputColorSpace,n=this.colorNode;if(i===r)return n;const o=sm(i,r);let a=null;const h=t.nodes.library.getColorSpaceFunction(o);return null!==h?a=uc(h(n.rgb),n.a):(console.error("ColorSpaceNode: Unsupported Color Space configuration.",o),a=n),a}}im.type=Ql("ColorSpace",im);const rm=(e,t=null)=>Du(new im(Du(e),t,Zt)),nm=(e,t=null)=>Du(new im(Du(e),Zt,t));pu("toOutputColorSpace",rm),pu("toWorkingColorSpace",nm);let om=class extends tu{constructor(e,t){super(e,t),this.referenceNode=e,this.isReferenceElementNode=!0}getNodeType(){return this.referenceNode.uniformType}generate(e){const t=super.generate(e),s=this.referenceNode.getNodeType(),i=this.getNodeType();return e.format(t,s,i)}};class am extends Kl{constructor(e,t,s=null,i=null){super(),this.property=e,this.uniformType=t,this.object=s,this.count=i,this.properties=e.split("."),this.reference=s,this.node=null,this.updateType=Hl.OBJECT}element(e){return Du(new om(this,Du(e)))}setNodeType(e){this.node=Cc(null,e).getSelf()}getNodeType(e){return null===this.node&&this.updateValue(),this.node.getNodeType(e)}getValueFromReference(e=this.reference){const{properties:t}=this;let s=e[t[0]];for(let e=1;eDu(new hm(e,t,s));class um extends iu{constructor(e,t=dm,s=null){super("vec3"),this.toneMapping=e,this.exposureNode=t,this.colorNode=s}getCacheKey(){let e=super.getCacheKey();return e="{toneMapping:"+this.toneMapping+",nodes:"+e+"}",e}setup(e){const t=this.colorNode||e.context.color,s=this.toneMapping;if(0===s)return t;let i=null;const r=e.renderer.nodes.library.getToneMappingFunction(s);return null!==r?i=uc(r(t.rgb,this.exposureNode),t.a):(console.error("ToneMappingNode: Unsupported Tone Mapping configuration.",s),i=t),i}}um.type=Ql("ToneMapping",um);const cm=(e,t,s)=>Du(new um(e,Du(t),Du(s))),dm=lm("toneMappingExposure","float");pu("toneMapping",((e,t,s)=>cm(t,s,e)));class pm extends lu{constructor(e,t=null,s=0,i=0){super(e,t),this.isBufferNode=!0,this.bufferType=t,this.bufferStride=s,this.bufferOffset=i,this.usage=Rs,this.instanced=!1,this.attribute=null,this.global=!0,e&&!0===e.isBufferAttribute&&(this.attribute=e,this.usage=e.usage,this.instanced=e.isInstancedBufferAttribute)}getHash(e){if(0===this.bufferStride&&0===this.bufferOffset){let t=e.globalCache.getData(this.value);return void 0===t&&(t={node:this},e.globalCache.setData(this.value,t)),t.node.uuid}return this.uuid}getNodeType(e){return null===this.bufferType&&(this.bufferType=e.getTypeFromAttribute(this.attribute)),this.bufferType}setup(e){if(null!==this.attribute)return;const t=this.getNodeType(e),s=this.value,i=e.getTypeLength(t),r=this.bufferStride||i,n=this.bufferOffset,o=!0===s.isInterleavedBuffer?s:new oo(s,r),a=new ho(o,i,n);o.setUsage(this.usage),this.attribute=a,this.attribute.isInstancedBufferAttribute=this.instanced}generate(e){const t=this.getNodeType(e),s=e.getBufferAttributeFromNode(this,t),i=e.getPropertyName(s);let r=null;if("vertex"===e.shaderStage||"compute"===e.shaderStage)this.name=i,r=i;else{r=em(this).build(e,t)}return r}getInputType(){return"bufferAttribute"}setUsage(e){return this.usage=e,this.attribute&&!0===this.attribute.isBufferAttribute&&(this.attribute.usage=e),this}setInstanced(e){return this.instanced=e,this}}pm.type=Ql("BufferAttribute",pm);const mm=(e,t,s,i)=>Du(new pm(e,t,s,i)),gm=(e,t,s,i)=>mm(e,t,s,i).setUsage(Cs),fm=(e,t,s,i)=>mm(e,t,s,i).setInstanced(!0),ym=(e,t,s,i)=>gm(e,t,s,i).setInstanced(!0);pu("toAttribute",(e=>mm(e.value)));class xm extends Kl{constructor(e,t,s=[64]){super("void"),this.isComputeNode=!0,this.computeNode=e,this.count=t,this.workgroupSize=s,this.dispatchCount=0,this.version=1,this.updateBeforeType=Hl.OBJECT,this.updateDispatchCount()}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(e){!0===e&&this.version++}updateDispatchCount(){const{count:e,workgroupSize:t}=this;let s=t[0];for(let e=1;eDu(new xm(Du(e),t,s));pu("compute",bm);class vm extends Kl{constructor(e,t=!0){super(),this.node=e,this.parent=t,this.isCacheNode=!0}getNodeType(e){return this.node.getNodeType(e)}build(e,...t){const s=e.getCache(),i=e.getCacheFromNode(this,parent);e.setCache(i);const r=this.node.build(e,...t);return e.setCache(s),r}}vm.type=Ql("Cache",vm);const Tm=(e,...t)=>Du(new vm(Du(e),...t));pu("cache",Tm);class _m extends Kl{constructor(e,t){super(),this.isBypassNode=!0,this.outputNode=e,this.callNode=t}getNodeType(e){return this.outputNode.getNodeType(e)}generate(e){const t=this.callNode.build(e,"void");return""!==t&&e.addLineFlowCode(t),this.outputNode.build(e)}}_m.type=Ql("Bypass",_m);const wm=Wu(_m);pu("bypass",wm);class Sm extends Kl{constructor(e,t,s,i=Ku(0),r=Ku(1)){super(),this.node=e,this.inLowNode=t,this.inHighNode=s,this.outLowNode=i,this.outHighNode=r,this.doClamp=!0}setup(){const{node:e,inLowNode:t,inHighNode:s,outLowNode:i,outHighNode:r,doClamp:n}=this;let o=e.sub(t).div(s.sub(t));return!0===n&&(o=o.clamp()),o.mul(r.sub(i)).add(i)}}Sm.type=Ql("Remap",Sm);const Mm=Wu(Sm,null,null,{doClamp:!1}),Am=Wu(Sm);pu("remap",Mm),pu("remapClamp",Am);class Nm extends Kl{constructor(e="",t="void"){super(t),this.snippet=e}generate(e,t){const s=this.getNodeType(e),i=this.snippet;if("void"!==s)return e.format(`( ${i} )`,s,t);e.addLineFlowCode(i)}}Nm.type=Ql("Expression",Nm);const Rm=Wu(Nm),Cm=e=>(e?qp(e,Rm("discard")):Rm("discard")).append(),Em=()=>Rm("return").append();pu("discard",Cm);class Bm extends iu{constructor(e,t,s){super("vec4"),this.colorNode=e,this.toneMapping=t,this.outputColorSpace=s,this.isRenderOutput=!0}setup({context:e}){let t=this.colorNode||e.color;const s=(null!==this.toneMapping?this.toneMapping:e.toneMapping)||0,i=(null!==this.outputColorSpace?this.outputColorSpace:e.outputColorSpace)||Zt;return 0!==s&&(t=t.toneMapping(s)),i===Jt&&(t=t.toOutputColorSpace(i)),t}}Bm.type=Ql("RenderOutput",Bm);const Im=(e,t=null,s=null)=>Du(new Bm(Du(e),t,s));function Pm(e){console.warn("THREE.TSLBase: AddNodeElement has been removed in favor of tree-shaking. Trying add",e)}pu("renderOutput",Im);class Fm extends Kl{constructor(e,t=null){super(t),this.global=!0,this._attributeName=e}getHash(e){return this.getAttributeName(e)}getNodeType(e){let t=this.nodeType;if(null===t){const s=this.getAttributeName(e);if(e.hasGeometryAttribute(s)){const i=e.geometry.getAttribute(s);t=e.getTypeFromAttribute(i)}else t="float"}return t}setAttributeName(e){return this._attributeName=e,this}getAttributeName(){return this._attributeName}generate(e){const t=this.getAttributeName(e),s=this.getNodeType(e);if(!0===e.hasGeometryAttribute(t)){const i=e.geometry.getAttribute(t),r=e.getTypeFromAttribute(i),n=e.getAttribute(t,r);if("vertex"===e.shaderStage)return e.format(n.name,r,s);return em(this).build(e,s)}return console.warn(`AttributeNode: Vertex attribute "${t}" not found on geometry.`),e.generateConst(s)}serialize(e){super.serialize(e),e.global=this.global,e._attributeName=this._attributeName}deserialize(e){super.deserialize(e),this.global=e.global,this._attributeName=e._attributeName}}Fm.type=Ql("Attribute",Fm);const zm=(e,t)=>Du(new Fm(e,t)),Um=e=>zm("uv"+(e>0?e:""),"vec2");class Lm extends Kl{constructor(e,t=null){super("uvec2"),this.isTextureSizeNode=!0,this.textureNode=e,this.levelNode=t}generate(e,t){const s=this.textureNode.build(e,"property"),i=this.levelNode.build(e,"int");return e.format(`${e.getMethod("textureDimensions")}( ${s}, ${i} )`,this.getNodeType(e),t)}}Lm.type=Ql("TextureSize",Lm);const Om=Wu(Lm);class Vm extends Rc{constructor(e){super(0),this._textureNode=e,this.updateType=Hl.FRAME}get textureNode(){return this._textureNode}get texture(){return this._textureNode.value}update(){const e=this.texture,t=e.images,s=t&&t.length>0?t[0]&&t[0].image||t[0]:e.image;if(s&&void 0!==s.width){const{width:e,height:t}=s;this.value=Math.log2(Math.max(e,t))}}}Vm.type=Ql("MaxMipLevel",Vm);const Dm=Wu(Vm);class km extends Rc{constructor(e,t=null,s=null,i=null){super(e),this.isTextureNode=!0,this.uvNode=t,this.levelNode=s,this.biasNode=i,this.compareNode=null,this.depthNode=null,this.gradNode=null,this.sampler=!0,this.updateMatrix=!1,this.updateType=Hl.NONE,this.referenceNode=null,this._value=e,this._matrixUniform=null,this.setUpdateMatrix(null===t)}set value(e){this.referenceNode?this.referenceNode.value=e:this._value=e}get value(){return this.referenceNode?this.referenceNode.value:this._value}getUniformHash(){return this.value.uuid}getNodeType(){return!0===this.value.isDepthTexture?"float":this.value.type===Be?"uvec4":this.value.type===Ee?"ivec4":"vec4"}getInputType(){return"texture"}getDefaultUV(){return Um(this.value.channel)}updateReference(){return this.value}getTransformedUV(e){return null===this._matrixUniform&&(this._matrixUniform=Cc(this.value.matrix)),this._matrixUniform.mul(oc(e,1)).xy}setUpdateMatrix(e){return this.updateMatrix=e,this.updateType=e?Hl.FRAME:Hl.NONE,this}setupUV(e,t){const s=this.value;return!e.isFlipY()||!0!==s.isRenderTargetTexture&&!0!==s.isFramebufferTexture&&!0!==s.isDepthTexture||(t=t.setY(t.y.oneMinus())),t}setup(e){const t=e.getNodeProperties(this);t.referenceNode=this.referenceNode;let s=this.uvNode;null!==s&&!0!==e.context.forceUVContext||!e.context.getUV||(s=e.context.getUV(this)),s||(s=this.getDefaultUV()),!0===this.updateMatrix&&(s=this.getTransformedUV(s)),s=this.setupUV(e,s);let i=this.levelNode;null===i&&e.context.getTextureLevel&&(i=e.context.getTextureLevel(this)),t.uvNode=s,t.levelNode=i,t.biasNode=this.biasNode,t.compareNode=this.compareNode,t.gradNode=this.gradNode,t.depthNode=this.depthNode}generateUV(e,t){return t.build(e,!0===this.sampler?"vec2":"ivec2")}generateSnippet(e,t,s,i,r,n,o,a){const h=this.value;let l;return l=i?e.generateTextureLevel(h,t,s,i,n):r?e.generateTextureBias(h,t,s,r,n):a?e.generateTextureGrad(h,t,s,a,n):o?e.generateTextureCompare(h,t,s,o,n):!1===this.sampler?e.generateTextureLoad(h,t,s,n):e.generateTexture(h,t,s,n),l}generate(e,t){const s=e.getNodeProperties(this),i=this.value;if(!i||!0!==i.isTexture)throw new Error("TextureNode: Need a three.js texture.");const r=super.generate(e,"property");if("sampler"===t)return r+"_sampler";if(e.isReference(t))return r;{const n=e.getDataFromNode(this);let o=n.propertyName;if(void 0===o){const{uvNode:t,levelNode:i,biasNode:a,compareNode:h,depthNode:l,gradNode:u}=s,c=this.generateUV(e,t),d=i?i.build(e,"float"):null,p=a?a.build(e,"float"):null,m=l?l.build(e,"int"):null,g=h?h.build(e,"float"):null,f=u?[u[0].build(e,"vec2"),u[1].build(e,"vec2")]:null,y=e.getVarFromNode(this);o=e.getPropertyName(y);const x=this.generateSnippet(e,r,c,d,p,m,g,f);e.addLineFlowCode(`${o} = ${x}`),n.snippet=x,n.propertyName=o}let a=o;const h=this.getNodeType(e);return e.needsToWorkingColorSpace(i)&&(a=nm(Rm(a,h),i.colorSpace).setup(e).build(e,h)),e.format(a,h,t)}}setSampler(e){return this.sampler=e,this}getSampler(){return this.sampler}uv(e){const t=this.clone();return t.uvNode=Du(e),t.referenceNode=this.getSelf(),Du(t)}blur(e){const t=this.clone();return t.biasNode=Du(e).mul(Dm(t)),t.referenceNode=this.getSelf(),Du(t)}level(e){const t=this.clone();return t.levelNode=Du(e),t.referenceNode=this.getSelf(),Du(t)}size(e){return Om(this,e)}bias(e){const t=this.clone();return t.biasNode=Du(e),t.referenceNode=this.getSelf(),Du(t)}compare(e){const t=this.clone();return t.compareNode=Du(e),t.referenceNode=this.getSelf(),Du(t)}grad(e,t){const s=this.clone();return s.gradNode=[Du(e),Du(t)],s.referenceNode=this.getSelf(),Du(s)}depth(e){const t=this.clone();return t.depthNode=Du(e),t.referenceNode=this.getSelf(),Du(t)}serialize(e){super.serialize(e),e.value=this.value.toJSON(e.meta).uuid,e.sampler=this.sampler,e.updateMatrix=this.updateMatrix,e.updateType=this.updateType}deserialize(e){super.deserialize(e),this.value=e.meta.textures[e.value],this.sampler=e.sampler,this.updateMatrix=e.updateMatrix,this.updateType=e.updateType}update(){const e=this.value,t=this._matrixUniform;null!==t&&(t.value=e.matrix),!0===e.matrixAutoUpdate&&e.updateMatrix()}clone(){const e=new this.constructor(this.value,this.uvNode,this.levelNode,this.biasNode);return e.sampler=this.sampler,e}}km.type=Ql("Texture",km);const Gm=Wu(km),Wm=(...e)=>Gm(...e).setSampler(!1),Hm=e=>(!0===e.isNode?e:Gm(e)).convert("sampler"),jm=Sc("camera").onRenderUpdate((()=>{jm.needsUpdate=!0})),qm=Cc("float").label("cameraNear").setGroup(jm).onRenderUpdate((({camera:e})=>e.near)),$m=Cc("float").label("cameraFar").setGroup(jm).onRenderUpdate((({camera:e})=>e.far)),Xm=Cc("float").label("cameraLogDepth").setGroup(jm).onRenderUpdate((({camera:e})=>2/(Math.log(e.far+1)/Math.LN2))),Ym=Cc("mat4").label("cameraProjectionMatrix").setGroup(jm).onRenderUpdate((({camera:e})=>e.projectionMatrix)),Jm=Cc("mat4").label("cameraProjectionMatrixInverse").setGroup(jm).onRenderUpdate((({camera:e})=>e.projectionMatrixInverse)),Zm=Cc("mat4").label("cameraViewMatrix").setGroup(jm).onRenderUpdate((({camera:e})=>e.matrixWorldInverse)),Km=Cc("mat4").label("cameraWorldMatrix").setGroup(jm).onRenderUpdate((({camera:e})=>e.matrixWorld)),Qm=Cc("mat3").label("cameraNormalMatrix").setGroup(jm).onRenderUpdate((({camera:e})=>e.normalMatrix)),eg=Cc(new Ei).label("cameraPosition").setGroup(jm).onRenderUpdate((({camera:e},t)=>t.value.setFromMatrixPosition(e.matrixWorld)));class tg extends Kl{constructor(e=tg.VIEW_MATRIX,t=null){super(),this.scope=e,this.object3d=t,this.updateType=Hl.OBJECT,this._uniformNode=new Rc(null)}getNodeType(){const e=this.scope;return e===tg.WORLD_MATRIX||e===tg.VIEW_MATRIX?"mat4":e===tg.NORMAL_MATRIX?"mat3":e===tg.POSITION||e===tg.VIEW_POSITION||e===tg.DIRECTION||e===tg.SCALE?"vec3":void 0}update(e){const t=this.object3d,s=this._uniformNode,i=this.scope;if(i===tg.VIEW_MATRIX)s.value=t.modelViewMatrix;else if(i===tg.NORMAL_MATRIX)s.value=t.normalMatrix;else if(i===tg.WORLD_MATRIX)s.value=t.matrixWorld;else if(i===tg.POSITION)s.value=s.value||new Ei,s.value.setFromMatrixPosition(t.matrixWorld);else if(i===tg.SCALE)s.value=s.value||new Ei,s.value.setFromMatrixScale(t.matrixWorld);else if(i===tg.DIRECTION)s.value=s.value||new Ei,t.getWorldDirection(s.value);else if(i===tg.VIEW_POSITION){const i=e.camera;s.value=s.value||new Ei,s.value.setFromMatrixPosition(t.matrixWorld),s.value.applyMatrix4(i.matrixWorldInverse)}}generate(e){const t=this.scope;return t===tg.WORLD_MATRIX||t===tg.VIEW_MATRIX?this._uniformNode.nodeType="mat4":t===tg.NORMAL_MATRIX?this._uniformNode.nodeType="mat3":t!==tg.POSITION&&t!==tg.VIEW_POSITION&&t!==tg.DIRECTION&&t!==tg.SCALE||(this._uniformNode.nodeType="vec3"),this._uniformNode.build(e)}serialize(e){super.serialize(e),e.scope=this.scope}deserialize(e){super.deserialize(e),this.scope=e.scope}}tg.VIEW_MATRIX="viewMatrix",tg.NORMAL_MATRIX="normalMatrix",tg.WORLD_MATRIX="worldMatrix",tg.POSITION="position",tg.SCALE="scale",tg.VIEW_POSITION="viewPosition",tg.DIRECTION="direction",tg.type=Ql("Object3D",tg);const sg=Wu(tg,tg.DIRECTION),ig=Wu(tg,tg.VIEW_MATRIX),rg=Wu(tg,tg.NORMAL_MATRIX),ng=Wu(tg,tg.WORLD_MATRIX),og=Wu(tg,tg.POSITION),ag=Wu(tg,tg.SCALE),hg=Wu(tg,tg.VIEW_POSITION);class lg extends tg{constructor(e=lg.VIEW_MATRIX){super(e)}update(e){this.object3d=e.object,super.update(e)}}lg.type=Ql("Model",lg);const ug=Hu(lg,lg.DIRECTION),cg=Hu(lg,lg.VIEW_MATRIX).label("modelViewMatrix").toVar("ModelViewMatrix"),dg=Hu(lg,lg.NORMAL_MATRIX),pg=Hu(lg,lg.WORLD_MATRIX),mg=Hu(lg,lg.POSITION),gg=Hu(lg,lg.SCALE),fg=Hu(lg,lg.VIEW_POSITION),yg=Cc(new or).onObjectUpdate((({object:e},t)=>t.value.copy(e.matrixWorld).invert())),xg=zm("position","vec3"),bg=xg.varying("positionLocal"),vg=xg.varying("positionPrevious"),Tg=pg.mul(bg).xyz.varying("v_positionWorld"),_g=bg.transformDirection(pg).varying("v_positionWorldDirection").normalize().toVar("positionWorldDirection"),wg=cg.mul(bg).xyz.varying("v_positionView"),Sg=wg.negate().varying("v_positionViewDirection").normalize().toVar("positionViewDirection");class Mg extends Kl{constructor(){super("bool"),this.isFrontFacingNode=!0}generate(e){const{renderer:t,material:s}=e;return t.coordinateSystem===Vs&&s.side===d?"false":e.getFrontFacing()}}Mg.type=Ql("FrontFacing",Mg);const Ag=Hu(Mg),Ng=Ku(Ag).mul(2).sub(1),Rg=zm("normal","vec3"),Cg=ju((e=>!1===e.geometry.hasAttribute("normal")?(console.warn('TSL.NormalNode: Vertex attribute "normal" not found on geometry.'),oc(0,1,0)):Rg),"vec3").once()().toVar("normalLocal"),Eg=wg.dFdx().cross(wg.dFdy()).normalize().toVar("normalFlat");let Bg=null;const Ig=ju((e=>{let t;return t=!0===e.material.flatShading?Eg:Bg||(Bg=em(dg.mul(Cg),"v_normalView").normalize()),t}),"vec3").once()().toVar("normalView"),Pg=em(Ig.transformDirection(Zm),"v_normalWorld").normalize().toVar("normalWorld"),Fg=ju((e=>e.context.setupNormal()),"vec3").once()().mul(Ng).toVar("transformedNormalView"),zg=Fg.transformDirection(Zm).normalize().toVar("transformedNormalWorld"),Ug=ju((e=>e.context.setupClearcoatNormal()),"vec3").once()().mul(Ng).toVar("transformedClearcoatNormalView"),Lg=Cc(0).onReference((({material:e})=>e)).onRenderUpdate((({material:e})=>e.refractionRatio)),Og=Sg.negate().reflect(Fg),Vg=Sg.negate().refract(Fg,Lg),Dg=Og.transformDirection(Zm).toVar("reflectVector"),kg=Vg.transformDirection(Zm).toVar("reflectVector");class Gg extends km{constructor(e,t=null,s=null,i=null){super(e,t,s,i),this.isCubeTextureNode=!0}getInputType(){return"cubeTexture"}getDefaultUV(){const e=this.value;return e.mapping===he?Dg:e.mapping===le?kg:(console.error('THREE.CubeTextureNode: Mapping "%s" not supported.',e.mapping),oc(0,0,0))}setUpdateMatrix(){}setupUV(e,t){const s=this.value;return e.renderer.coordinateSystem!==Ds&&s.isRenderTargetTexture?t:oc(t.x.negate(),t.yz)}generateUV(e,t){return t.build(e,"vec3")}}Gg.type=Ql("CubeTexture",Gg);const Wg=Wu(Gg);class Hg extends Rc{constructor(e,t,s=0){super(e,t),this.isBufferNode=!0,this.bufferType=t,this.bufferCount=s}getElementType(e){return this.getNodeType(e)}getInputType(){return"buffer"}}Hg.type=Ql("Buffer",Hg);const jg=(e,t,s)=>Du(new Hg(e,t,s));class qg extends tu{constructor(e,t){super(e,t),this.isArrayBufferElementNode=!0}getNodeType(e){return this.node.getElementType(e)}generate(e){const t=super.generate(e),s=this.getNodeType();return e.format(t,"vec4",s)}}class $g extends Hg{constructor(e,t=null){super(null,"vec4"),this.array=e,this.elementType=t,this._elementType=null,this._elementLength=0,this.updateType=Hl.RENDER,this.isArrayBufferNode=!0}getElementType(){return this.elementType||this._elementType}getElementLength(){return this._elementLength}update(){const{array:e,value:t}=this,s=this.getElementLength(),i=this.getElementType();if(1===s)for(let s=0;sDu(new $g(e,t));class Yg extends tu{constructor(e,t){super(e,t),this.referenceNode=e,this.isReferenceElementNode=!0}getNodeType(){return this.referenceNode.uniformType}generate(e){const t=super.generate(e),s=this.referenceNode.getNodeType(),i=this.getNodeType();return e.format(t,s,i)}}class Jg extends Kl{constructor(e,t,s=null,i=null){super(),this.property=e,this.uniformType=t,this.object=s,this.count=i,this.properties=e.split("."),this.reference=s,this.node=null,this.updateType=Hl.OBJECT}element(e){return Du(new Yg(this,Du(e)))}setNodeType(e){let t=null;t=null!==this.count?jg(null,e,this.count):Array.isArray(this.getValueFromReference())?Xg(null,e):"texture"===e?Gm(null):"cubeTexture"===e?Wg(null):Cc(null,e),this.node=t.getSelf()}getNodeType(e){return null===this.node&&this.updateValue(),this.node.getNodeType(e)}getValueFromReference(e=this.reference){const{properties:t}=this;let s=e[t[0]];for(let e=1;eDu(new Jg(e,t,s)),Kg=(e,t,s,i)=>Du(new Jg(e,t,i,s));class Qg extends Jg{constructor(e,t,s=null){super(e,t,s),this.material=s,this.isMaterialReferenceNode=!0}updateReference(e){return this.reference=null!==this.material?this.material:e.material,this.reference}}Qg.type=Ql("MaterialReference",Qg);const ef=(e,t,s)=>Du(new Qg(e,t,s)),tf=ju((e=>(!1===e.geometry.hasAttribute("tangent")&&e.geometry.computeTangents(),zm("tangent","vec4"))))(),sf=tf.xyz.toVar("tangentLocal"),rf=cg.mul(uc(sf,0)).xyz.varying("v_tangentView").normalize().toVar("tangentView"),nf=rf.transformDirection(Zm).varying("v_tangentWorld").normalize().toVar("tangentWorld"),of=rf.toVar("transformedTangentView"),af=of.transformDirection(Zm).normalize().toVar("transformedTangentWorld"),hf=e=>e.mul(tf.w).xyz,lf=em(hf(Rg.cross(tf)),"v_bitangentGeometry").normalize().toVar("bitangentGeometry"),uf=em(hf(Cg.cross(sf)),"v_bitangentLocal").normalize().toVar("bitangentLocal"),cf=em(hf(Ig.cross(rf)),"v_bitangentView").normalize().toVar("bitangentView"),df=em(hf(Pg.cross(nf)),"v_bitangentWorld").normalize().toVar("bitangentWorld"),pf=hf(Fg.cross(of)).normalize().toVar("transformedBitangentView"),mf=pf.transformDirection(Zm).normalize().toVar("transformedBitangentWorld"),gf=gc(rf,cf,Ig),ff=Sg.mul(gf),yf=(e,t)=>e.sub(ff.mul(t)),xf=(()=>{let e=$c.cross(Sg);return e=e.cross($c).normalize(),e=Up(e,Fg,jc.mul(zc.oneMinus()).oneMinus().pow2().pow2()).normalize(),e})(),bf=ju((e=>{const{eye_pos:t,surf_norm:s,mapN:i,uv:r}=e,n=t.dFdx(),o=t.dFdy(),a=r.dFdx(),h=r.dFdy(),l=s,u=o.cross(l),c=l.cross(n),d=u.mul(a.x).add(c.mul(h.x)),p=u.mul(a.y).add(c.mul(h.y)),m=d.dot(d).max(p.dot(p)),g=Ng.mul(m.inverseSqrt());return dd(d.mul(i.x,g),p.mul(i.y,g),l.mul(i.z)).normalize()}));class vf extends iu{constructor(e,t=null){super("vec3"),this.node=e,this.scaleNode=t,this.normalMapType=0}setup(e){const{normalMapType:t,scaleNode:s}=this;let i=this.node.mul(2).sub(1);null!==s&&(i=oc(i.xy.mul(s),i.z));let r=null;if(1===t)r=dg.mul(i).normalize();else if(0===t){r=!0===e.hasGeometryAttribute("tangent")?gf.mul(i).normalize():bf({eye_pos:wg,surf_norm:Ig,mapN:i,uv:Um()})}return r}}vf.type=Ql("NormalMap",vf);const Tf=Wu(vf),_f=ju((({textureNode:e,bumpScale:t})=>{const s=t=>e.cache().context({getUV:e=>t(e.uvNode||Um()),forceUVContext:!0}),i=Ku(s((e=>e)));return sc(Ku(s((e=>e.add(e.dFdx())))).sub(i),Ku(s((e=>e.add(e.dFdy())))).sub(i)).mul(t)})),wf=ju((e=>{const{surf_pos:t,surf_norm:s,dHdxy:i}=e,r=t.dFdx().normalize(),n=s,o=t.dFdy().normalize().cross(n),a=n.cross(r),h=r.dot(o).mul(Ng),l=h.sign().mul(i.x.mul(o).add(i.y.mul(a)));return h.abs().mul(s).sub(l).normalize()}));class Sf extends iu{constructor(e,t=null){super("vec3"),this.textureNode=e,this.scaleNode=t}setup(){const e=null!==this.scaleNode?this.scaleNode:1,t=_f({textureNode:this.textureNode,bumpScale:e});return wf({surf_pos:wg,surf_norm:Ig,dHdxy:t})}}const Mf=Wu(Sf),Af=new Map;class Nf extends Kl{constructor(e){super(),this.scope=e}getCache(e,t){let s=Af.get(e);return void 0===s&&(s=ef(e,t),Af.set(e,s)),s}getFloat(e){return this.getCache(e,"float")}getColor(e){return this.getCache(e,"color")}getTexture(e){return this.getCache("map"===e?"map":e+"Map","texture")}setup(e){const t=e.context.material,s=this.scope;let i=null;if(s===Nf.COLOR){const e=void 0!==t.color?this.getColor(s):oc();i=t.map&&!0===t.map.isTexture?e.mul(this.getTexture("map")):e}else if(s===Nf.OPACITY){const e=this.getFloat(s);i=t.alphaMap&&!0===t.alphaMap.isTexture?e.mul(this.getTexture("alpha")):e}else if(s===Nf.SPECULAR_STRENGTH)i=t.specularMap&&!0===t.specularMap.isTexture?this.getTexture("specular").r:Ku(1);else if(s===Nf.SPECULAR_INTENSITY){const e=this.getFloat(s);i=t.specularMap?e.mul(this.getTexture(s).a):e}else if(s===Nf.SPECULAR_COLOR){const e=this.getColor(s);i=t.specularColorMap&&!0===t.specularColorMap.isTexture?e.mul(this.getTexture(s).rgb):e}else if(s===Nf.ROUGHNESS){const e=this.getFloat(s);i=t.roughnessMap&&!0===t.roughnessMap.isTexture?e.mul(this.getTexture(s).g):e}else if(s===Nf.METALNESS){const e=this.getFloat(s);i=t.metalnessMap&&!0===t.metalnessMap.isTexture?e.mul(this.getTexture(s).b):e}else if(s===Nf.EMISSIVE){const e=this.getFloat("emissiveIntensity"),r=this.getColor(s).mul(e);i=t.emissiveMap&&!0===t.emissiveMap.isTexture?r.mul(this.getTexture(s)):r}else if(s===Nf.NORMAL)i=t.normalMap?Tf(this.getTexture("normal"),this.getCache("normalScale","vec2")):t.bumpMap?Mf(this.getTexture("bump").r,this.getFloat("bumpScale")):Ig;else if(s===Nf.CLEARCOAT){const e=this.getFloat(s);i=t.clearcoatMap&&!0===t.clearcoatMap.isTexture?e.mul(this.getTexture(s).r):e}else if(s===Nf.CLEARCOAT_ROUGHNESS){const e=this.getFloat(s);i=t.clearcoatRoughnessMap&&!0===t.clearcoatRoughnessMap.isTexture?e.mul(this.getTexture(s).r):e}else if(s===Nf.CLEARCOAT_NORMAL)i=t.clearcoatNormalMap?Tf(this.getTexture(s),this.getCache(s+"Scale","vec2")):Ig;else if(s===Nf.SHEEN){const e=this.getColor("sheenColor").mul(this.getFloat("sheen"));i=t.sheenColorMap&&!0===t.sheenColorMap.isTexture?e.mul(this.getTexture("sheenColor").rgb):e}else if(s===Nf.SHEEN_ROUGHNESS){const e=this.getFloat(s);i=t.sheenRoughnessMap&&!0===t.sheenRoughnessMap.isTexture?e.mul(this.getTexture(s).a):e,i=i.clamp(.07,1)}else if(s===Nf.ANISOTROPY)if(t.anisotropyMap&&!0===t.anisotropyMap.isTexture){const e=this.getTexture(s);i=mc(cy.x,cy.y,cy.y.negate(),cy.x).mul(e.rg.mul(2).sub(sc(1)).normalize().mul(e.b))}else i=cy;else if(s===Nf.IRIDESCENCE_THICKNESS){const e=Zg("1","float",t.iridescenceThicknessRange);if(t.iridescenceThicknessMap){const r=Zg("0","float",t.iridescenceThicknessRange);i=e.sub(r).mul(this.getTexture(s).g).add(r)}else i=e}else if(s===Nf.TRANSMISSION){const e=this.getFloat(s);i=t.transmissionMap?e.mul(this.getTexture(s).r):e}else if(s===Nf.THICKNESS){const e=this.getFloat(s);i=t.thicknessMap?e.mul(this.getTexture(s).g):e}else if(s===Nf.IOR)i=this.getFloat(s);else if(s===Nf.LIGHT_MAP)i=this.getTexture(s).rgb.mul(this.getFloat("lightMapIntensity"));else if(s===Nf.AO_MAP)i=this.getTexture(s).r.sub(1).mul(this.getFloat("aoMapIntensity")).add(1);else{const t=this.getNodeType(e);i=this.getCache(s,t)}return i}}Nf.ALPHA_TEST="alphaTest",Nf.COLOR="color",Nf.OPACITY="opacity",Nf.SHININESS="shininess",Nf.SPECULAR="specular",Nf.SPECULAR_STRENGTH="specularStrength",Nf.SPECULAR_INTENSITY="specularIntensity",Nf.SPECULAR_COLOR="specularColor",Nf.REFLECTIVITY="reflectivity",Nf.ROUGHNESS="roughness",Nf.METALNESS="metalness",Nf.NORMAL="normal",Nf.CLEARCOAT="clearcoat",Nf.CLEARCOAT_ROUGHNESS="clearcoatRoughness",Nf.CLEARCOAT_NORMAL="clearcoatNormal",Nf.EMISSIVE="emissive",Nf.ROTATION="rotation",Nf.SHEEN="sheen",Nf.SHEEN_ROUGHNESS="sheenRoughness",Nf.ANISOTROPY="anisotropy",Nf.IRIDESCENCE="iridescence",Nf.IRIDESCENCE_IOR="iridescenceIOR",Nf.IRIDESCENCE_THICKNESS="iridescenceThickness",Nf.IOR="ior",Nf.TRANSMISSION="transmission",Nf.THICKNESS="thickness",Nf.ATTENUATION_DISTANCE="attenuationDistance",Nf.ATTENUATION_COLOR="attenuationColor",Nf.LINE_SCALE="scale",Nf.LINE_DASH_SIZE="dashSize",Nf.LINE_GAP_SIZE="gapSize",Nf.LINE_WIDTH="linewidth",Nf.LINE_DASH_OFFSET="dashOffset",Nf.POINT_WIDTH="pointWidth",Nf.DISPERSION="dispersion",Nf.LIGHT_MAP="light",Nf.AO_MAP="ao",Nf.type=Ql("Material",Nf);const Rf=Hu(Nf,Nf.ALPHA_TEST),Cf=Hu(Nf,Nf.COLOR),Ef=Hu(Nf,Nf.SHININESS),Bf=Hu(Nf,Nf.EMISSIVE),If=Hu(Nf,Nf.OPACITY),Pf=Hu(Nf,Nf.SPECULAR),Ff=Hu(Nf,Nf.SPECULAR_INTENSITY),zf=Hu(Nf,Nf.SPECULAR_COLOR),Uf=Hu(Nf,Nf.SPECULAR_STRENGTH),Lf=Hu(Nf,Nf.REFLECTIVITY),Of=Hu(Nf,Nf.ROUGHNESS),Vf=Hu(Nf,Nf.METALNESS),Df=Hu(Nf,Nf.NORMAL).context({getUV:null}),kf=Hu(Nf,Nf.CLEARCOAT),Gf=Hu(Nf,Nf.CLEARCOAT_ROUGHNESS),Wf=Hu(Nf,Nf.CLEARCOAT_NORMAL).context({getUV:null}),Hf=Hu(Nf,Nf.ROTATION),jf=Hu(Nf,Nf.SHEEN),qf=Hu(Nf,Nf.SHEEN_ROUGHNESS),$f=Hu(Nf,Nf.ANISOTROPY),Xf=Hu(Nf,Nf.IRIDESCENCE),Yf=Hu(Nf,Nf.IRIDESCENCE_IOR),Jf=Hu(Nf,Nf.IRIDESCENCE_THICKNESS),Zf=Hu(Nf,Nf.TRANSMISSION),Kf=Hu(Nf,Nf.THICKNESS),Qf=Hu(Nf,Nf.IOR),ey=Hu(Nf,Nf.ATTENUATION_DISTANCE),ty=Hu(Nf,Nf.ATTENUATION_COLOR),sy=Hu(Nf,Nf.LINE_SCALE),iy=Hu(Nf,Nf.LINE_DASH_SIZE),ry=Hu(Nf,Nf.LINE_GAP_SIZE),ny=Hu(Nf,Nf.LINE_WIDTH),oy=Hu(Nf,Nf.LINE_DASH_OFFSET),ay=Hu(Nf,Nf.POINT_WIDTH),hy=Hu(Nf,Nf.DISPERSION),ly=Hu(Nf,Nf.LIGHT_MAP),uy=Hu(Nf,Nf.AO_MAP);Nf.REFRACTION_RATIO;const cy=Cc(new Qs).onReference((function(e){return e.material})).onRenderUpdate((function({material:e}){this.value.set(e.anisotropy*Math.cos(e.anisotropyRotation),e.anisotropy*Math.sin(e.anisotropyRotation))}));class dy extends iu{constructor(e=null){super("vec4"),this.positionNode=e}setup(e){if("fragment"===e.shaderStage)return em(e.context.mvp);const t=this.positionNode||bg;return Ym.mul(cg).mul(t)}}dy.type=Ql("ModelViewProjection",dy);const py=Wu(dy);class my extends Kl{constructor(e){super("uint"),this.scope=e,this.isInstanceIndexNode=!0}generate(e){const t=this.getNodeType(e),s=this.scope;let i,r;if(s===my.VERTEX)i=e.getVertexIndex();else if(s===my.INSTANCE)i=e.getInstanceIndex();else if(s===my.DRAW)i=e.getDrawIndex();else{if(s!==my.INVOCATION_LOCAL)throw new Error("THREE.IndexNode: Unknown scope: "+s);i=e.getInvocationLocalIndex()}if("vertex"===e.shaderStage||"compute"===e.shaderStage)r=i;else{r=em(this).build(e,t)}return r}}my.VERTEX="vertex",my.INSTANCE="instance",my.INVOCATION_LOCAL="invocationLocal",my.DRAW="draw",my.type=Ql("Index",my);const gy=Hu(my,my.VERTEX),fy=Hu(my,my.INSTANCE),yy=Hu(my,my.INVOCATION_LOCAL),xy=Hu(my,my.DRAW);class by extends oo{constructor(e,t,s=1){super(e,t),this.isInstancedInterleavedBuffer=!0,this.meshPerAttribute=s}copy(e){return super.copy(e),this.meshPerAttribute=e.meshPerAttribute,this}clone(e){const t=super.clone(e);return t.meshPerAttribute=this.meshPerAttribute,t}toJSON(e){const t=super.toJSON(e);return t.isInstancedInterleavedBuffer=!0,t.meshPerAttribute=this.meshPerAttribute,t}}class vy extends Kl{constructor(e){super("void"),this.instanceMesh=e,this.instanceMatrixNode=null,this.instanceColorNode=null,this.updateType=Hl.FRAME,this.buffer=null,this.bufferColor=null}setup(e){let t=this.instanceMatrixNode,s=this.instanceColorNode;const i=this.instanceMesh;if(null===t){const e=i.instanceMatrix;if(i.count<=1e3)t=jg(e.array,"mat4",i.count).element(fy);else{const s=new by(e.array,16,1);this.buffer=s;const i=e.usage===Cs?ym:fm,r=[i(s,"vec4",16,0),i(s,"vec4",16,4),i(s,"vec4",16,8),i(s,"vec4",16,12)];t=fc(...r)}this.instanceMatrixNode=t}const r=i.instanceColor;if(r&&null===s){const e=new Ho(r.array,3),t=r.usage===Cs?ym:fm;this.bufferColor=e,s=oc(t(e,"vec3",3,0)),this.instanceColorNode=s}const n=t.mul(bg).xyz;if(bg.assign(n),e.hasGeometryAttribute("normal")){const e=gc(t),s=Cg.div(oc(e[0].dot(e[0]),e[1].dot(e[1]),e[2].dot(e[2]))),i=e.mul(s).xyz;Cg.assign(i)}null!==this.instanceColorNode&&Ic("vec3","vInstanceColor").assign(this.instanceColorNode)}update(){this.instanceMesh.instanceMatrix.usage!==Cs&&null!=this.buffer&&this.instanceMesh.instanceMatrix.version!==this.buffer.version&&(this.buffer.version=this.instanceMesh.instanceMatrix.version),this.instanceMesh.instanceColor&&this.instanceMesh.instanceColor.usage!==Cs&&null!=this.bufferColor&&this.instanceMesh.instanceColor.version!==this.bufferColor.version&&(this.bufferColor.version=this.instanceMesh.instanceColor.version)}}vy.type=Ql("Instance",vy);const Ty=Wu(vy);class _y extends Kl{constructor(e){super("void"),this.batchMesh=e,this.batchingIdNode=null}setup(e){null===this.batchingIdNode&&(null===e.getDrawIndex()?this.batchingIdNode=fy:this.batchingIdNode=xy);const t=ju((([e])=>{const t=Om(Wm(this.batchMesh._indirectTexture),0),s=Qu(e).modInt(Qu(t)),i=Qu(e).div(Qu(t));return Wm(this.batchMesh._indirectTexture,ic(s,i)).x})).setLayout({name:"getIndirectIndex",type:"uint",inputs:[{name:"id",type:"int"}]}),s=t(Qu(this.batchingIdNode)),i=this.batchMesh._matricesTexture,r=Om(Wm(i),0),n=Ku(s).mul(4).toInt().toVar(),o=n.modInt(r),a=n.div(Qu(r)),h=fc(Wm(i,ic(o,a)),Wm(i,ic(o.add(1),a)),Wm(i,ic(o.add(2),a)),Wm(i,ic(o.add(3),a))),l=this.batchMesh._colorsTexture;if(null!==l){const e=ju((([e])=>{const t=Om(Wm(l),0).x,s=e,i=s.modInt(t),r=s.div(t);return Wm(l,ic(i,r)).rgb})).setLayout({name:"getBatchingColor",type:"vec3",inputs:[{name:"id",type:"int"}]}),t=e(s);Ic("vec3","vBatchColor").assign(t)}const u=gc(h);bg.assign(h.mul(bg));const c=Cg.div(oc(u[0].dot(u[0]),u[1].dot(u[1]),u[2].dot(u[2]))),d=u.mul(c).xyz;Cg.assign(d),e.hasGeometryAttribute("tangent")&&sf.mulAssign(u)}}_y.type=Ql("Batch",_y);const wy=Wu(_y),Sy=new WeakMap;class My extends Kl{constructor(e,t=!1){let s,i,r;super("void"),this.skinnedMesh=e,this.useReference=t,this.updateType=Hl.OBJECT,this.skinIndexNode=zm("skinIndex","uvec4"),this.skinWeightNode=zm("skinWeight","vec4"),t?(s=Zg("bindMatrix","mat4"),i=Zg("bindMatrixInverse","mat4"),r=Kg("skeleton.boneMatrices","mat4",e.skeleton.bones.length)):(s=Cc(e.bindMatrix,"mat4"),i=Cc(e.bindMatrixInverse,"mat4"),r=jg(e.skeleton.boneMatrices,"mat4",e.skeleton.bones.length)),this.bindMatrixNode=s,this.bindMatrixInverseNode=i,this.boneMatricesNode=r,this.previousBoneMatricesNode=null}getSkinnedPosition(e=this.boneMatricesNode,t=bg){const{skinIndexNode:s,skinWeightNode:i,bindMatrixNode:r,bindMatrixInverseNode:n}=this,o=e.element(s.x),a=e.element(s.y),h=e.element(s.z),l=e.element(s.w),u=r.mul(t),c=dd(o.mul(i.x).mul(u),a.mul(i.y).mul(u),h.mul(i.z).mul(u),l.mul(i.w).mul(u));return n.mul(c).xyz}getSkinnedNormal(e=this.boneMatricesNode,t=Cg){const{skinIndexNode:s,skinWeightNode:i,bindMatrixNode:r,bindMatrixInverseNode:n}=this,o=e.element(s.x),a=e.element(s.y),h=e.element(s.z),l=e.element(s.w);let u=dd(i.x.mul(o),i.y.mul(a),i.z.mul(h),i.w.mul(l));return u=n.mul(u).mul(r),u.transformDirection(t).xyz}getPreviousSkinnedPosition(e){const t=e.object;return null===this.previousBoneMatricesNode&&(t.skeleton.previousBoneMatrices=new Float32Array(t.skeleton.boneMatrices),this.previousBoneMatricesNode=Kg("skeleton.previousBoneMatrices","mat4",t.skeleton.bones.length)),this.getSkinnedPosition(this.previousBoneMatricesNode,vg)}needsPreviousBoneMatrices(e){const t=e.renderer.getMRT();return t&&t.has("velocity")}setup(e){this.needsPreviousBoneMatrices(e)&&vg.assign(this.getPreviousSkinnedPosition(e));const t=this.getSkinnedPosition();if(bg.assign(t),e.hasGeometryAttribute("normal")){const t=this.getSkinnedNormal();Cg.assign(t),e.hasGeometryAttribute("tangent")&&sf.assign(t)}}generate(e,t){if("void"!==t)return bg.build(e,t)}update(e){const t=(this.useReference?e.object:this.skinnedMesh).skeleton;Sy.get(t)!==e.frameId&&(Sy.set(t,e.frameId),null!==this.previousBoneMatricesNode&&t.previousBoneMatrices.set(t.boneMatrices),t.update())}}My.type=Ql("Skinning",My);const Ay=e=>Du(new My(e)),Ny=e=>Du(new My(e,!0));class Ry extends Kl{constructor(e=[]){super(),this.params=e}getVarName(e){return String.fromCharCode("i".charCodeAt()+e)}getProperties(e){const t=e.getNodeProperties(this);if(void 0!==t.stackNode)return t;const s={};for(let e=0,t=this.params.length-1;eNumber(n)?">=":"<"));const u={start:r,end:n,condition:h},c=u.start,d=u.end;let p="",m="",g="";l||(l="int"===a||"uint"===a?h.includes("<")?"++":"--":h.includes("<")?"+= 1.":"-= 1."),p+=e.getVar(a,o)+" = "+c,m+=o+" "+h+" "+d,g+=o+" "+l;const f=`for ( ${p}; ${m}; ${g} )`;e.addFlowCode((0===t?"\n":"")+e.tab+f+" {\n\n").addFlowTab()}const r=i.build(e,"void"),n=t.returnsNode?t.returnsNode.build(e):"";e.removeFlowTab().addFlowCode("\n"+e.tab+r);for(let t=0,s=this.params.length-1;tDu(new Ry(Gu(e,"int"))).append(),Ey=()=>Rm("continue").append(),By=()=>Rm("break").append(),Iy=new WeakMap,Py=new _i,Fy=ju((({bufferMap:e,influence:t,stride:s,width:i,depth:r,offset:n})=>{const o=Qu(gy).mul(s).add(n),a=o.div(i),h=o.sub(a.mul(i));return Wm(e,ic(h,a)).depth(r).mul(t)}));class zy extends Kl{constructor(e){super("void"),this.mesh=e,this.morphBaseInfluence=Cc(1),this.updateType=Hl.OBJECT}setup(e){const{geometry:t}=e,s=void 0!==t.morphAttributes.position,i=t.hasAttribute("normal")&&void 0!==t.morphAttributes.normal,r=t.morphAttributes.position||t.morphAttributes.normal||t.morphAttributes.color,n=void 0!==r?r.length:0,{texture:o,stride:a,size:h}=function(e){const t=void 0!==e.morphAttributes.position,s=void 0!==e.morphAttributes.normal,i=void 0!==e.morphAttributes.color,r=e.morphAttributes.position||e.morphAttributes.normal||e.morphAttributes.color,n=void 0!==r?r.length:0;let o=Iy.get(e);if(void 0===o||o.count!==n){void 0!==o&&o.texture.dispose();const a=e.morphAttributes.position||[],h=e.morphAttributes.normal||[],l=e.morphAttributes.color||[];let u=0;!0===t&&(u=1),!0===s&&(u=2),!0===i&&(u=3);let c=e.attributes.position.count*u,d=1;const p=4096;c>p&&(d=Math.ceil(c/p),c=p);const m=new Float32Array(c*d*4*n),g=new Mi(m,c,d,n);g.type=Ie,g.needsUpdate=!0;const f=4*u;for(let x=0;x{const t=Ku(0).toVar();this.mesh.count>1&&null!==this.mesh.morphTexture&&void 0!==this.mesh.morphTexture?t.assign(Wm(this.mesh.morphTexture,ic(Qu(e).add(1),Qu(fy))).r):t.assign(Zg("morphTargetInfluences","float").element(e).toVar()),!0===s&&bg.addAssign(Fy({bufferMap:o,influence:t,stride:a,width:l,depth:e,offset:Qu(0)})),!0===i&&Cg.addAssign(Fy({bufferMap:o,influence:t,stride:a,width:l,depth:e,offset:Qu(1)}))}))}update(){const e=this.morphBaseInfluence;this.mesh.geometry.morphTargetsRelative?e.value=1:e.value=1-this.mesh.morphTargetInfluences.reduce(((e,t)=>e+t),0)}}zy.type=Ql("Morph",zy);const Uy=Wu(zy),Ly=(e,t)=>{for(const s of t)if(s.isAnalyticLightNode&&s.light.id===e)return s;return null};class Oy extends Kl{constructor(e=[]){super("vec3"),this.totalDiffuseNode=oc().toVar("totalDiffuse"),this.totalSpecularNode=oc().toVar("totalSpecular"),this.outgoingLightNode=oc().toVar("outgoingLight"),this._lights=e,this._lightNodes=null,this._lightNodesHash=null,this.global=!0}getHash(e){if(null===this._lightNodesHash){null===this._lightNodes&&this.setupLightsNode(e);const t=[];for(const e of this._lightNodes)t.push(e.getHash());this._lightNodesHash="lights-"+t.join(",")}return this._lightNodesHash}analyze(e){const t=e.getDataFromNode(this);for(const s of t.nodes)s.build(e)}setupLightsNode(e){const t=[],s=this._lightNodes,i=(e=>e.sort(((e,t)=>e.id-t.id)))(this._lights),r=e.renderer.nodes.library;for(const e of i)if(e.isNode)t.push(Du(e));else{let i=null;if(null!==s&&(i=Ly(e.id,s)),null===i){const s=r.getLightNodeClass(e.constructor);if(void 0===s){console.warn(`LightsNode.setupNodeLights: Light node not found for ${e.constructor.name}`);continue}t.push(Du(new s(e)))}}this._lightNodes=t}setup(e){null===this._lightNodes&&this.setupLightsNode(e);const t=e.context,s=t.lightingModel;let i=this.outgoingLightNode;if(s){const{_lightNodes:r,totalDiffuseNode:n,totalSpecularNode:o}=this;t.outgoingLight=i;const a=e.addStack();e.getDataFromNode(this).nodes=a.nodes,s.start(t,a,e);for(const t of r)t.build(e);s.indirect(t,a,e);const{backdrop:h,backdropAlpha:l}=t,{directDiffuse:u,directSpecular:c,indirectDiffuse:d,indirectSpecular:p}=t.reflectedLight;let m=u.add(d);null!==h&&(m=oc(null!==l?l.mix(m,h):h),t.material.transparent=!0),n.assign(m),o.assign(c.add(p)),i.assign(n.add(o)),s.finish(t,a,e),i=i.bypass(e.removeStack())}return i}setLights(e){return this._lights=e,this._lightNodes=null,this._lightNodesHash=null,this}getLights(){return this._lights}}Oy.type=Ql("Lights",Oy);const Vy=Wu(Oy);class Dy extends Kl{constructor(){super("vec3"),this.isLightingNode=!0}generate(){console.warn("Abstract function.")}}Dy.type=Ql("Lighting",Dy);class ky extends Dy{constructor(e=null){super(),this.aoNode=e}setup(e){e.context.ambientOcclusion.mulAssign(this.aoNode)}}ky.type=Ql("AO",ky);class Gy extends Xp{constructor(e,t=null,s=null,i=null){super(e),this.lightingModel=t,this.backdropNode=s,this.backdropAlphaNode=i,this._value=null}getContext(){const{backdropNode:e,backdropAlphaNode:t}=this,s={directDiffuse:oc().toVar("directDiffuse"),directSpecular:oc().toVar("directSpecular"),indirectDiffuse:oc().toVar("indirectDiffuse"),indirectSpecular:oc().toVar("indirectSpecular")};return{radiance:oc().toVar("radiance"),irradiance:oc().toVar("irradiance"),iblIrradiance:oc().toVar("iblIrradiance"),ambientOcclusion:Ku(1).toVar("ambientOcclusion"),reflectedLight:s,backdrop:e,backdropAlpha:t}}setup(e){return this.value=this._value||(this._value=this.getContext()),this.value.lightingModel=this.lightingModel||e.context.lightingModel,super.setup(e)}}Gy.type=Ql("LightingContext",Gy);const Wy=Wu(Gy);class Hy extends Dy{constructor(e){super(),this.node=e}setup(e){e.context.irradiance.addAssign(this.node)}}let jy,qy;Hy.type=Ql("Irradiance",Hy);class $y extends Kl{constructor(e){super(),this.scope=e,this.isViewportNode=!0}getNodeType(){return this.scope===$y.VIEWPORT?"vec4":"vec2"}getUpdateType(){let e=Hl.NONE;return this.scope!==$y.RESOLUTION&&this.scope!==$y.VIEWPORT||(e=Hl.RENDER),this.updateType=e,e}update({renderer:e}){this.scope===$y.VIEWPORT?e.getViewport(qy):e.getDrawingBufferSize(jy)}setup(){const e=this.scope;let t=null;return t=e===$y.RESOLUTION?Cc(jy||(jy=new Qs)):e===$y.VIEWPORT?Cc(qy||(qy=new _i)):sc(Xy.div(Yy)),t}generate(e){if(this.scope===$y.COORDINATE){let t=e.getFragCoord();if(e.isFlipY()){const s=e.getNodeProperties(Yy).outputNode.build(e);t=`${e.getType("vec2")}( ${t}.x, ${s}.y - ${t}.y )`}return t}return super.generate(e)}}$y.COORDINATE="coordinate",$y.RESOLUTION="resolution",$y.VIEWPORT="viewport",$y.UV="uv",$y.type=Ql("Viewport",$y);const Xy=Hu($y,$y.COORDINATE),Yy=Hu($y,$y.RESOLUTION),Jy=Hu($y,$y.VIEWPORT),Zy=Hu($y,$y.UV),Ky=ju((()=>(console.warn('TSL.ViewportNode: "viewportTopLeft" is deprecated. Use "viewportUV" instead.'),Zy)),"vec2").once()(),Qy=ju((()=>(console.warn('TSL.ViewportNode: "viewportBottomLeft" is deprecated. Use "viewportUV.flipY()" instead.'),Zy.flipY())),"vec2").once()(),ex=new Qs;class tx extends km{constructor(e=Zy,t=null,s=null){null===s&&((s=new Xa).minFilter=Se),super(s,e,t),this.generateMipmaps=!1,this.isOutputTextureNode=!0,this.updateBeforeType=Hl.FRAME}updateBefore(e){const t=e.renderer;t.getDrawingBufferSize(ex);const s=this.value;s.image.width===ex.width&&s.image.height===ex.height||(s.image.width=ex.width,s.image.height=ex.height,s.needsUpdate=!0);const i=s.generateMipmaps;s.generateMipmaps=this.generateMipmaps,t.copyFramebufferToTexture(s),s.generateMipmaps=i}clone(){const e=new this.constructor(this.uvNode,this.levelNode,this.value);return e.generateMipmaps=this.generateMipmaps,e}}tx.type=Ql("ViewportTexture",tx);const sx=Wu(tx),ix=Wu(tx,null,null,{generateMipmaps:!0});let rx=null;class nx extends tx{constructor(e=Zy,t=null){null===rx&&(rx=new Qa),super(e,t,rx)}}nx.type=Ql("ViewportDepthTexture",nx);const ox=Wu(nx);class ax extends Kl{constructor(e,t=null){super("float"),this.scope=e,this.valueNode=t,this.isViewportDepthNode=!0}generate(e){const{scope:t}=this;return t===ax.DEPTH_BASE?e.getFragDepth():super.generate(e)}setup({camera:e}){const{scope:t}=this,s=this.valueNode;let i=null;if(t===ax.DEPTH_BASE)null!==s&&(i=dx().assign(s));else if(t===ax.DEPTH)i=e.isPerspectiveCamera?ux(wg.z,qm,$m):hx(wg.z,qm,$m);else if(t===ax.LINEAR_DEPTH)if(null!==s)if(e.isPerspectiveCamera){const e=cx(s,qm,$m);i=hx(e,qm,$m)}else i=s;else i=hx(wg.z,qm,$m);return i}}ax.DEPTH_BASE="depthBase",ax.DEPTH="depth",ax.LINEAR_DEPTH="linearDepth",ax.type=Ql("ViewportDepth",ax);const hx=(e,t,s)=>e.add(t).div(t.sub(s)),lx=(e,t,s)=>t.sub(s).mul(e).sub(t),ux=(e,t,s)=>t.add(e).mul(s).div(s.sub(t).mul(e)),cx=(e,t,s)=>t.mul(s).div(s.sub(t).mul(e).sub(s)),dx=Wu(ax,ax.DEPTH_BASE),px=Hu(ax,ax.DEPTH),mx=Wu(ax,ax.LINEAR_DEPTH),gx=mx(ox());px.assign=e=>dx(e);class fx extends Kl{constructor(e=fx.DEFAULT){super(),this.scope=e}setup(e){super.setup(e);const t=e.clippingContext,{localClipIntersection:s,localClippingCount:i,globalClippingCount:r}=t,n=r+i,o=s?n-i:n;return this.scope===fx.ALPHA_TO_COVERAGE?this.setupAlphaToCoverage(t.planes,n,o):this.setupDefault(t.planes,n,o)}setupAlphaToCoverage(e,t,s){return ju((()=>{const i=Xg(e),r=Bc("float","distanceToPlane"),n=Bc("float","distanceToGradient"),o=Bc("float","clipOpacity");let a;if(o.assign(1),Cy(s,(({i:e})=>{a=i.element(e),r.assign(wg.dot(a.xyz).negate().add(a.w)),n.assign(r.fwidth().div(2)),o.mulAssign(Dp(n.negate(),n,r)),o.equal(0).discard()})),s{a=i.element(t),r.assign(wg.dot(a.xyz).negate().add(a.w)),n.assign(r.fwidth().div(2)),e.mulAssign(Dp(n.negate(),n,r).oneMinus())})),o.mulAssign(e.oneMinus())}Pc.a.mulAssign(o),Pc.a.equal(0).discard()}))()}setupDefault(e,t,s){return ju((()=>{const i=Xg(e);let r;if(Cy(s,(({i:e})=>{r=i.element(e),wg.dot(r.xyz).greaterThan(r.w).discard()})),s{r=i.element(t),e.assign(wg.dot(r.xyz).greaterThan(r.w).and(e))})),e.discard()}}))()}}fx.ALPHA_TO_COVERAGE="alphaToCoverage",fx.DEFAULT="default",fx.type=Ql("Clipping",fx);const yx=new Map;class xx extends Kr{constructor(){super(),this.isNodeMaterial=!0,this.type=this.constructor.type,this.forceSinglePass=!1,this.fog=!0,this.lights=!1,this.lightsNode=null,this.envNode=null,this.aoNode=null,this.colorNode=null,this.normalNode=null,this.opacityNode=null,this.backdropNode=null,this.backdropAlphaNode=null,this.alphaTestNode=null,this.positionNode=null,this.depthNode=null,this.shadowNode=null,this.shadowPositionNode=null,this.outputNode=null,this.mrtNode=null,this.fragmentNode=null,this.vertexNode=null}customProgramCacheKey(){return this.type+Ul(this)}build(e){this.setup(e)}setup(e){let t;e.context.setupNormal=()=>this.setupNormal(e),e.addStack(),e.stack.outputNode=this.vertexNode||this.setupPosition(e),e.addFlow("vertex",e.removeStack()),e.addStack();const s=this.setupClipping(e);if(!0===this.depthWrite&&this.setupDepth(e),null===this.fragmentNode){this.setupDiffuseColor(e),this.setupVariants(e);const i=this.setupLighting(e);null!==s&&e.stack.add(s);const r=uc(i,Pc.a).max(0);t=this.setupOutput(e,r),Zc.assign(t),null!==this.outputNode&&(t=this.outputNode);if(null!==e.renderer.getRenderTarget()){const s=e.renderer.getMRT(),i=this.mrtNode;null!==s?(t=s,null!==i&&(t=s.merge(i))):null!==i&&(t=i)}}else{let s=this.fragmentNode;!0!==s.isOutputStructNode&&(s=uc(s)),t=this.setupOutput(e,s)}e.stack.outputNode=t,e.addFlow("fragment",e.removeStack())}setupClipping(e){if(null===e.clippingContext)return null;const{globalClippingCount:t,localClippingCount:s}=e.clippingContext;let i=null;return(t||s)&&(this.alphaToCoverage?i=Du(new fx(fx.ALPHA_TO_COVERAGE)):e.stack.add(Du(new fx))),i}setupDepth(e){const{renderer:t}=e;let s=this.depthNode;if(null===s){const e=t.getMRT();if(e&&e.has("depth"))s=e.get("depth");else if(!0===t.logarithmicDepthBuffer){s=py().w.add(1).log2().mul(Xm).mul(.5)}}null!==s&&px.assign(s).append()}setupPosition(e){const{object:t}=e,s=t.geometry;if(e.addStack(),(s.morphAttributes.position||s.morphAttributes.normal||s.morphAttributes.color)&&Uy(t).append(),!0===t.isSkinnedMesh&&Ny(t).append(),this.displacementMap){const e=ef("displacementMap","texture"),t=ef("displacementScale","float"),s=ef("displacementBias","float");bg.addAssign(Cg.normalize().mul(e.x.mul(t).add(s)))}t.isBatchedMesh&&wy(t).append(),t.instanceMatrix&&!0===t.instanceMatrix.isInstancedBufferAttribute&&Ty(t).append(),null!==this.positionNode&&bg.assign(this.positionNode);const i=py();return e.context.vertex=e.removeStack(),e.context.mvp=i,i}setupDiffuseColor({object:e,geometry:t}){let s=this.colorNode?uc(this.colorNode):Cf;if(!0===this.vertexColors&&t.hasAttribute("color")&&(s=uc(s.xyz.mul(zm("color","vec3")),s.a)),e.instanceColor){s=Ic("vec3","vInstanceColor").mul(s)}if(e.isBatchedMesh&&e._colorsTexture){s=Ic("vec3","vBatchColor").mul(s)}Pc.assign(s);const i=this.opacityNode?Ku(this.opacityNode):If;if(Pc.a.assign(Pc.a.mul(i)),null!==this.alphaTestNode||this.alphaTest>0){const e=null!==this.alphaTestNode?Ku(this.alphaTestNode):Rf;Pc.a.lessThanEqual(e).discard()}!1===this.transparent&&1===this.blending&&!1===this.alphaToCoverage&&Pc.a.assign(1)}setupVariants(){}setupOutgoingLight(){return!0===this.lights?oc(0):Pc.rgb}setupNormal(){return this.normalNode?oc(this.normalNode):Df}setupEnvironment(){let e=null;return this.envNode?e=this.envNode:this.envMap&&(e=this.envMap.isCubeTexture?ef("envMap","cubeTexture"):ef("envMap","texture")),e}setupLightMap(e){let t=null;return e.material.lightMap&&(t=new Hy(ly)),t}setupLights(e){const t=[],s=this.setupEnvironment(e);s&&s.isLightingNode&&t.push(s);const i=this.setupLightMap(e);if(i&&i.isLightingNode&&t.push(i),null!==this.aoNode||e.material.aoMap){const e=null!==this.aoNode?this.aoNode:uy;t.push(new ky(e))}let r=this.lightsNode||e.lightsNode;return t.length>0&&(r=Vy([...r.getLights(),...t])),r}setupLightingModel(){}setupLighting(e){const{material:t}=e,{backdropNode:s,backdropAlphaNode:i,emissiveNode:r}=this,n=!0===this.lights||null!==this.lightsNode?this.setupLights(e):null;let o=this.setupOutgoingLight(e);if(n&&n.getScope().getLights().length>0){const t=this.setupLightingModel(e);o=Wy(n,t,s,i)}else null!==s&&(o=oc(null!==i?Up(o,s,i):s));return(r&&!0===r.isNode||t.emissive&&!0===t.emissive.isColor)&&(Fc.assign(oc(r||Bf)),o=o.add(Fc)),o}setupOutput(e,t){if(!0===this.fog){const s=e.fogNode;s&&(t=uc(s.mix(t.rgb,s.colorNode),t.a))}return t}setDefaultValues(e){for(const t in e){const s=e[t];void 0===this[t]&&(this[t]=s,s&&s.clone&&(this[t]=s.clone()))}const t=Object.getOwnPropertyDescriptors(e.constructor.prototype);for(const e in t)void 0===Object.getOwnPropertyDescriptor(this.constructor.prototype,e)&&void 0!==t[e].get&&Object.defineProperty(this.constructor.prototype,e,t[e])}toJSON(e){const t=void 0===e||"string"==typeof e;t&&(e={textures:{},images:{},nodes:{}});const s=Kr.prototype.toJSON.call(this,e),i=Ll(this);s.inputNodes={};for(const{property:t,childNode:r}of i)s.inputNodes[t]=r.toJSON(e).uuid;function r(e){const t=[];for(const s in e){const i=e[s];delete i.metadata,t.push(i)}return t}if(t){const t=r(e.textures),i=r(e.images),n=r(e.nodes);t.length>0&&(s.textures=t),i.length>0&&(s.images=i),n.length>0&&(s.nodes=n)}return s}copy(e){return this.lightsNode=e.lightsNode,this.envNode=e.envNode,this.colorNode=e.colorNode,this.normalNode=e.normalNode,this.opacityNode=e.opacityNode,this.backdropNode=e.backdropNode,this.backdropAlphaNode=e.backdropAlphaNode,this.alphaTestNode=e.alphaTestNode,this.positionNode=e.positionNode,this.depthNode=e.depthNode,this.shadowNode=e.shadowNode,this.shadowPositionNode=e.shadowPositionNode,this.outputNode=e.outputNode,this.mrtNode=e.mrtNode,this.fragmentNode=e.fragmentNode,this.vertexNode=e.vertexNode,super.copy(e)}}function bx(e,t){const s="NodeMaterial",i=e+s;if("function"!=typeof t)throw new Error(`THREE.Node: NodeMaterial class "${e}" is not a class.`);if(yx.has(i))console.warn(`THREE.Node: Redefinition of NodeMaterial class "${i}".`);else{if(e.slice(-12)!==s)return yx.set(i,t),t.type=i,i;console.warn(`THREE.NodeMaterial: NodeMaterial class ${i} should not have '${s}' suffix.`)}}xx.type=bx("",xx);const vx=new Va;class Tx extends xx{constructor(e={}){super(),this.lights=!1,this.useAlphaToCoverage=!0,this.useColor=e.vertexColors,this.pointWidth=1,this.pointColorNode=null,this.pointWidthNode=null,this.setDefaultValues(vx),this.setupShaders(),this.setValues(e)}setup(e){this.setupShaders(),super.setup(e)}setupShaders(){const e=this.alphaToCoverage,t=this.useColor;this.vertexNode=ju((()=>{em(sc(),"vUv").assign(Um());const e=zm("instancePosition").xyz,t=Bc("vec4","mvPos");t.assign(cg.mul(uc(e,1)));const s=Jy.z.div(Jy.w),i=Ym.mul(t),r=Bc("vec2","offset");return r.assign(xg.xy),r.mulAssign(this.pointWidthNode?this.pointWidthNode:ay),r.assign(r.div(Jy.z)),r.y.assign(r.y.mul(s)),r.assign(r.mul(i.w)),i.assign(i.add(uc(r,0,0))),i}))(),this.fragmentNode=ju((()=>{const s=em(sc(),"vUv"),i=Bc("float","alpha");i.assign(1);const r=s.x,n=s.y,o=r.mul(r).add(n.mul(n));if(e){const e=Bc("float","dlen");e.assign(o.fwidth()),i.assign(Dp(e.oneMinus(),e.add(1),o).oneMinus())}else o.greaterThan(1).discard();let a;if(this.pointColorNode)a=this.pointColorNode;else if(t){a=zm("instanceColor").mul(Cf)}else a=Cf;return i.mulAssign(If),uc(a,i)}))()}get alphaToCoverage(){return this.useAlphaToCoverage}set alphaToCoverage(e){this.useAlphaToCoverage!==e&&(this.useAlphaToCoverage=e,this.needsUpdate=!0)}}Tx.type=bx("InstancedPoints",Tx);const _x=new Ma;class wx extends xx{constructor(e){super(),this.isLineBasicNodeMaterial=!0,this.lights=!1,this.setDefaultValues(_x),this.setValues(e)}}wx.type=bx("LineBasic",wx);const Sx=new zl;class Mx extends xx{constructor(e){super(),this.isLineDashedNodeMaterial=!0,this.lights=!1,this.setDefaultValues(Sx),this.offsetNode=null,this.dashScaleNode=null,this.dashSizeNode=null,this.gapSizeNode=null,this.setValues(e)}setupVariants(){const e=this.offsetNode,t=this.dashScaleNode?Ku(this.dashScaleNode):sy,s=this.dashSizeNode?Ku(this.dashSizeNode):iy,i=this.dashSizeNode?Ku(this.dashGapNode):ry;Kc.assign(s),Qc.assign(i);const r=em(zm("lineDistance").mul(t));(e?r.add(e):r).mod(Kc.add(Qc)).greaterThan(Kc).discard()}}Mx.type=bx("LineDashed",Mx);const Ax=new zl;class Nx extends xx{constructor(e={}){super(),this.lights=!1,this.setDefaultValues(Ax),this.useAlphaToCoverage=!0,this.useColor=e.vertexColors,this.useDash=e.dashed,this.useWorldUnits=!1,this.dashOffset=0,this.lineWidth=1,this.lineColorNode=null,this.offsetNode=null,this.dashScaleNode=null,this.dashSizeNode=null,this.gapSizeNode=null,this.setValues(e)}setup(e){this.setupShaders(),super.setup(e)}setupShaders(){const e=this.alphaToCoverage,t=this.useColor,s=this.dashed,i=this.worldUnits,r=ju((({start:e,end:t})=>{const s=Ym.element(2).element(2),i=Ym.element(3).element(2).mul(-.5).div(s).sub(e.z).div(t.z.sub(e.z));return uc(Up(e.xyz,t.xyz,i),t.w)}));this.vertexNode=ju((()=>{Ic("vec2","vUv").assign(Um());const e=zm("instanceStart"),t=zm("instanceEnd"),n=Bc("vec4","start"),o=Bc("vec4","end");n.assign(cg.mul(uc(e,1))),o.assign(cg.mul(uc(t,1))),i&&(Ic("vec3","worldStart").assign(n.xyz),Ic("vec3","worldEnd").assign(o.xyz));const a=Jy.z.div(Jy.w),h=Ym.element(2).element(3).equal(-1);Yu(h,(()=>{Yu(n.z.lessThan(0).and(o.z.greaterThan(0)),(()=>{o.assign(r({start:n,end:o}))})).ElseIf(o.z.lessThan(0).and(n.z.greaterThanEqual(0)),(()=>{n.assign(r({start:o,end:n}))}))}));const l=Ym.mul(n),u=Ym.mul(o),c=l.xyz.div(l.w),d=u.xyz.div(u.w),p=d.xy.sub(c.xy).toVar();p.x.assign(p.x.mul(a)),p.assign(p.normalize());const m=uc().toVar();if(i){const e=o.xyz.sub(n.xyz).normalize(),t=Up(n.xyz,o.xyz,.5).normalize(),i=e.cross(t).normalize(),r=e.cross(i),a=Ic("vec4","worldPos");a.assign(xg.y.lessThan(.5).select(n,o));const h=ny.mul(.5);a.addAssign(uc(xg.x.lessThan(0).select(i.mul(h),i.mul(h).negate()),0)),s||(a.addAssign(uc(xg.y.lessThan(.5).select(e.mul(h).negate(),e.mul(h)),0)),a.addAssign(uc(r.mul(h),0)),Yu(xg.y.greaterThan(1).or(xg.y.lessThan(0)),(()=>{a.subAssign(uc(r.mul(2).mul(h),0))}))),m.assign(Ym.mul(a));const l=oc().toVar();l.assign(xg.y.lessThan(.5).select(c,d)),m.z.assign(l.z.mul(m.w))}else{const e=Bc("vec2","offset");e.assign(sc(p.y,p.x.negate())),p.x.assign(p.x.div(a)),e.x.assign(e.x.div(a)),e.assign(xg.x.lessThan(0).select(e.negate(),e)),Yu(xg.y.lessThan(0),(()=>{e.assign(e.sub(p))})).ElseIf(xg.y.greaterThan(1),(()=>{e.assign(e.add(p))})),e.assign(e.mul(ny)),e.assign(e.div(Jy.w)),m.assign(xg.y.lessThan(.5).select(l,u)),e.assign(e.mul(m.w)),m.assign(m.add(uc(e,0,0)))}return m}))();const n=ju((({p1:e,p2:t,p3:s,p4:i})=>{const r=e.sub(s),n=i.sub(s),o=t.sub(e),a=r.dot(n),h=n.dot(o),l=r.dot(o),u=n.dot(n),c=o.dot(o).mul(u).sub(h.mul(h)),d=a.mul(h).sub(l.mul(u)).div(c).clamp(),p=a.add(h.mul(d)).div(u).clamp();return sc(d,p)}));this.fragmentNode=ju((()=>{const r=Ic("vec2","vUv");if(s){const e=this.offsetNode?Ku(this.offsetNodeNode):oy,t=this.dashScaleNode?Ku(this.dashScaleNode):sy,s=this.dashSizeNode?Ku(this.dashSizeNode):iy,i=this.dashSizeNode?Ku(this.dashGapNode):ry;Kc.assign(s),Qc.assign(i);const n=zm("instanceDistanceStart"),o=zm("instanceDistanceEnd"),a=xg.y.lessThan(.5).select(t.mul(n),sy.mul(o)),h=em(a.add(oy)),l=e?h.add(e):h;r.y.lessThan(-1).or(r.y.greaterThan(1)).discard(),l.mod(Kc.add(Qc)).greaterThan(Kc).discard()}const o=Bc("float","alpha");if(o.assign(1),i){const t=Ic("vec3","worldStart"),i=Ic("vec3","worldEnd"),r=Ic("vec4","worldPos").xyz.normalize().mul(1e5),a=i.sub(t),h=n({p1:t,p2:i,p3:oc(0,0,0),p4:r}),l=t.add(a.mul(h.x)),u=r.mul(h.y),c=l.sub(u).length().div(ny);if(!s)if(e){const e=c.fwidth();o.assign(Dp(e.negate().add(.5),e.add(.5),c).oneMinus())}else c.greaterThan(.5).discard()}else if(e){const e=r.x,t=r.y.greaterThan(0).select(r.y.sub(1),r.y.add(1)),s=e.mul(e).add(t.mul(t)),i=Bc("float","dlen");i.assign(s.fwidth()),Yu(r.y.abs().greaterThan(1),(()=>{o.assign(Dp(i.oneMinus(),i.add(1),s).oneMinus())}))}else Yu(r.y.abs().greaterThan(1),(()=>{const e=r.x,t=r.y.greaterThan(0).select(r.y.sub(1),r.y.add(1));e.mul(e).add(t.mul(t)).greaterThan(1).discard()}));let a;if(this.lineColorNode)a=this.lineColorNode;else if(t){const e=zm("instanceColorStart"),t=zm("instanceColorEnd");a=xg.y.lessThan(.5).select(e,t).mul(Cf)}else a=Cf;return uc(a,o)}))()}get worldUnits(){return this.useWorldUnits}set worldUnits(e){this.useWorldUnits!==e&&(this.useWorldUnits=e,this.needsUpdate=!0)}get dashed(){return this.useDash}set dashed(e){this.useDash!==e&&(this.useDash=e,this.needsUpdate=!0)}get alphaToCoverage(){return this.useAlphaToCoverage}set alphaToCoverage(e){this.useAlphaToCoverage!==e&&(this.useAlphaToCoverage=e,this.needsUpdate=!0)}}Nx.type=bx("Line2",Nx);const Rx=e=>Du(e).mul(.5).add(.5),Cx=e=>Du(e).mul(2).sub(1),Ex=new El;class Bx extends xx{constructor(e){super(),this.lights=!1,this.isMeshNormalNodeMaterial=!0,this.setDefaultValues(Ex),this.setValues(e)}setupDiffuseColor(){const e=this.opacityNode?Ku(this.opacityNode):If;Pc.assign(uc(Rx(Fg),e))}}Bx.type=bx("MeshNormal",Bx);class Ix extends iu{constructor(e=_g){super("vec2"),this.dirNode=e}setup(){const e=this.dirNode,t=e.z.atan2(e.x).mul(1/(2*Math.PI)).add(.5),s=e.y.clamp(-1,1).asin().mul(1/Math.PI).add(.5);return sc(t,s)}}Ix.type=Ql("EquirectUV",Ix);const Px=Wu(Ix);class Fx extends so{constructor(e=1,t={}){super(e,t),this.isCubeRenderTarget=!0}fromEquirectangularTexture(e,t){const s=t.minFilter,i=t.generateMipmaps;t.generateMipmaps=!0,this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;const r=new jn(5,5,5),n=Px(_g),o=new xx;o.colorNode=Gm(t,n,0),o.side=d,o.blending=m;const a=new Wn(r,o),h=new no;h.add(a),t.minFilter===Se&&(t.minFilter=Te);const l=new eo(1,10,this),u=e.getMRT();return e.setMRT(null),l.update(e,h),e.setMRT(u),t.minFilter=s,t.currentGenerateMipmaps=i,a.geometry.dispose(),a.material.dispose(),this}}const zx=new WeakMap;class Ux extends iu{constructor(e){super("vec3"),this.envNode=e,this._cubeTexture=null,this._cubeTextureNode=Wg();const t=new to;t.isRenderTargetTexture=!0,this._defaultTexture=t,this.updateBeforeType=Hl.RENDER}updateBefore(e){const{renderer:t,material:s}=e,i=this.envNode;if(i.isTextureNode||i.isMaterialReferenceNode){const e=i.isTextureNode?i.value:s[i.property];if(e&&e.isTexture){const s=e.mapping;if(s===ue||s===ce){if(zx.has(e)){const t=zx.get(e);Ox(t,e.mapping),this._cubeTexture=t}else{const s=e.image;if(function(e){return null!=e&&e.height>0}(s)){const i=new Fx(s.height);i.fromEquirectangularTexture(t,e),Ox(i.texture,e.mapping),this._cubeTexture=i.texture,zx.set(e,i.texture),e.addEventListener("dispose",Lx)}else this._cubeTexture=this._defaultTexture}this._cubeTextureNode.value=this._cubeTexture}else this._cubeTextureNode=this.envNode}}}setup(e){return this.updateBefore(e),this._cubeTextureNode}}function Lx(e){const t=e.target;t.removeEventListener("dispose",Lx);const s=zx.get(t);void 0!==s&&(zx.delete(t),s.dispose())}function Ox(e,t){t===ue?e.mapping=he:t===ce&&(e.mapping=le)}Ux.type=Ql("CubeMap",Ux);const Vx=Wu(Ux);class Dx extends Dy{constructor(e=null){super(),this.envNode=e}setup(e){e.context.environment=Vx(this.envNode)}}Dx.type=Ql("BasicEnvironment",Dx);class kx extends Dy{constructor(e=null){super(),this.lightMapNode=e}setup(e){const t=Ku(1/Math.PI);e.context.irradianceLightMap=this.lightMapNode.mul(t)}}kx.type=Ql("BasicLightMap",kx);class Gx{start(){}finish(){}direct(){}directRectArea(){}indirect(){}ambientOcclusion(){}}class Wx extends Gx{constructor(){super()}indirect(e,t,s){const i=e.ambientOcclusion,r=e.reflectedLight,n=s.context.irradianceLightMap;r.indirectDiffuse.assign(uc(0)),n?r.indirectDiffuse.addAssign(n):r.indirectDiffuse.addAssign(uc(1,1,1,0)),r.indirectDiffuse.mulAssign(i),r.indirectDiffuse.mulAssign(Pc.rgb)}finish(e,t,s){const i=s.material,r=e.outgoingLight,n=s.context.environment;if(n)switch(i.combine){case 0:r.rgb.assign(Up(r.rgb,r.rgb.mul(n.rgb),Uf.mul(Lf)));break;case 1:r.rgb.assign(Up(r.rgb,n.rgb,Uf.mul(Lf)));break;case 2:r.rgb.addAssign(n.rgb.mul(Uf.mul(Lf)));break;default:console.warn("THREE.BasicLightingModel: Unsupported .combine value:",i.combine)}}}const Hx=new Qr;class jx extends xx{constructor(e){super(),this.isMeshBasicNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Hx),this.setValues(e)}setupNormal(){return Ig}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new Dx(t):null}setupLightMap(e){let t=null;return e.material.lightMap&&(t=new kx(ly)),t}setupOutgoingLight(){return Pc.rgb}setupLightingModel(){return new Wx}}jx.type=bx("MeshBasic",jx);const qx=ju((({f0:e,f90:t,dotVH:s})=>{const i=s.mul(-5.55473).sub(6.98316).mul(s).exp2();return e.mul(i.oneMinus()).add(t.mul(i))})),$x=ju((e=>e.diffuseColor.mul(1/Math.PI))),Xx=ju((({dotNH:e})=>Jc.mul(Ku(.5)).add(1).mul(Ku(1/Math.PI)).mul(e.pow(Jc)))),Yx=ju((({lightDirection:e})=>{const t=e.add(Sg).normalize(),s=Fg.dot(t).clamp(),i=Sg.dot(t).clamp(),r=qx({f0:Xc,f90:1,dotVH:i}),n=Ku(.25),o=Xx({dotNH:s});return r.mul(n).mul(o)}));class Jx extends Wx{constructor(e=!0){super(),this.specular=e}direct({lightDirection:e,lightColor:t,reflectedLight:s}){const i=Fg.dot(e).clamp().mul(t);s.directDiffuse.addAssign(i.mul($x({diffuseColor:Pc.rgb}))),!0===this.specular&&s.directSpecular.addAssign(i.mul(Yx({lightDirection:e})).mul(Uf))}indirect({ambientOcclusion:e,irradiance:t,reflectedLight:s}){s.indirectDiffuse.addAssign(t.mul($x({diffuseColor:Pc}))),s.indirectDiffuse.mulAssign(e)}}const Zx=new Bl;class Kx extends xx{constructor(e){super(),this.isMeshLambertNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Zx),this.setValues(e)}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new Dx(t):null}setupLightingModel(){return new Jx(!1)}}Kx.type=bx("MeshLambert",Kx);const Qx=new Rl;class eb extends xx{constructor(e){super(),this.isMeshPhongNodeMaterial=!0,this.lights=!0,this.shininessNode=null,this.specularNode=null,this.setDefaultValues(Qx),this.setValues(e)}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new Dx(t):null}setupLightingModel(){return new Jx}setupVariants(){const e=(this.shininessNode?Ku(this.shininessNode):Ef).max(1e-4);Jc.assign(e);const t=this.specularNode||Pf;Xc.assign(t)}copy(e){return this.shininessNode=e.shininessNode,this.specularNode=e.specularNode,super.copy(e)}}eb.type=bx("MeshPhong",eb);const tb=ju((()=>{const e=Ig.dFdx().abs().max(Ig.dFdy().abs());return e.x.max(e.y).max(e.z)})),sb=ju((e=>{const{roughness:t}=e,s=tb();let i=t.max(.0525);return i=i.add(s),i=i.min(1),i})),ib=ju((({alpha:e,dotNL:t,dotNV:s})=>{const i=e.pow2(),r=t.mul(i.add(i.oneMinus().mul(s.pow2())).sqrt()),n=s.mul(i.add(i.oneMinus().mul(t.pow2())).sqrt());return gd(.5,r.add(n).max(zd))})).setLayout({name:"V_GGX_SmithCorrelated",type:"float",inputs:[{name:"alpha",type:"float"},{name:"dotNL",type:"float"},{name:"dotNV",type:"float"}]}),rb=ju((({alphaT:e,alphaB:t,dotTV:s,dotBV:i,dotTL:r,dotBL:n,dotNV:o,dotNL:a})=>{const h=a.mul(oc(e.mul(s),t.mul(i),o).length()),l=o.mul(oc(e.mul(r),t.mul(n),a).length());return gd(.5,h.add(l)).saturate()})).setLayout({name:"V_GGX_SmithCorrelated_Anisotropic",type:"float",inputs:[{name:"alphaT",type:"float",qualifier:"in"},{name:"alphaB",type:"float",qualifier:"in"},{name:"dotTV",type:"float",qualifier:"in"},{name:"dotBV",type:"float",qualifier:"in"},{name:"dotTL",type:"float",qualifier:"in"},{name:"dotBL",type:"float",qualifier:"in"},{name:"dotNV",type:"float",qualifier:"in"},{name:"dotNL",type:"float",qualifier:"in"}]}),nb=ju((({alpha:e,dotNH:t})=>{const s=e.pow2(),i=t.pow2().mul(s.oneMinus()).oneMinus();return s.div(i.pow2()).mul(1/Math.PI)})).setLayout({name:"D_GGX",type:"float",inputs:[{name:"alpha",type:"float"},{name:"dotNH",type:"float"}]}),ob=Ku(1/Math.PI),ab=ju((({alphaT:e,alphaB:t,dotNH:s,dotTH:i,dotBH:r})=>{const n=e.mul(t),o=oc(t.mul(i),e.mul(r),n.mul(s)),a=o.dot(o),h=n.div(a);return ob.mul(n.mul(h.pow2()))})).setLayout({name:"D_GGX_Anisotropic",type:"float",inputs:[{name:"alphaT",type:"float",qualifier:"in"},{name:"alphaB",type:"float",qualifier:"in"},{name:"dotNH",type:"float",qualifier:"in"},{name:"dotTH",type:"float",qualifier:"in"},{name:"dotBH",type:"float",qualifier:"in"}]}),hb=ju((e=>{const{lightDirection:t,f0:s,f90:i,roughness:r,f:n,USE_IRIDESCENCE:o,USE_ANISOTROPY:a}=e,h=e.normalView||Fg,l=r.pow2(),u=t.add(Sg).normalize(),c=h.dot(t).clamp(),d=h.dot(Sg).clamp(),p=h.dot(u).clamp(),m=Sg.dot(u).clamp();let g,f,y=qx({f0:s,f90:i,dotVH:m});if(Lu(o)&&(y=kc.mix(y,n)),Lu(a)){const e=qc.dot(t),s=qc.dot(Sg),i=qc.dot(u),r=$c.dot(t),n=$c.dot(Sg),o=$c.dot(u);g=rb({alphaT:Hc,alphaB:l,dotTV:s,dotBV:n,dotTL:e,dotBL:r,dotNV:d,dotNL:c}),f=ab({alphaT:Hc,alphaB:l,dotNH:p,dotTH:i,dotBH:o})}else g=ib({alpha:l,dotNL:c,dotNV:d}),f=nb({alpha:l,dotNH:p});return y.mul(g).mul(f)})),lb=ju((({roughness:e,dotNV:t})=>{const s=uc(-1,-.0275,-.572,.022),i=uc(1,.0425,1.04,-.04),r=e.mul(s).add(i),n=r.x.mul(r.x).min(t.mul(-9.28).exp2()).mul(r.x).add(r.y);return sc(-1.04,1.04).mul(n).add(r.zw)})).setLayout({name:"DFGApprox",type:"vec2",inputs:[{name:"roughness",type:"float"},{name:"dotNV",type:"vec3"}]}),ub=ju((e=>{const{dotNV:t,specularColor:s,specularF90:i,roughness:r}=e,n=lb({dotNV:t,roughness:r});return s.mul(n.x).add(i.mul(n.y))})),cb=ju((({f:e,f90:t,dotVH:s})=>{const i=s.oneMinus().saturate(),r=i.mul(i),n=i.mul(r,r).clamp(0,.9999);return e.sub(oc(t).mul(n)).div(n.oneMinus())})).setLayout({name:"Schlick_to_F0",type:"vec3",inputs:[{name:"f",type:"vec3"},{name:"f90",type:"float"},{name:"dotVH",type:"float"}]}),db=ju((({roughness:e,dotNH:t})=>{const s=e.pow2(),i=Ku(1).div(s),r=t.pow2().oneMinus().max(.0078125);return Ku(2).add(i).mul(r.pow(i.mul(.5))).div(2*Math.PI)})).setLayout({name:"D_Charlie",type:"float",inputs:[{name:"roughness",type:"float"},{name:"dotNH",type:"float"}]}),pb=ju((({dotNV:e,dotNL:t})=>Ku(1).div(Ku(4).mul(t.add(e).sub(t.mul(e)))))).setLayout({name:"V_Neubelt",type:"float",inputs:[{name:"dotNV",type:"float"},{name:"dotNL",type:"float"}]}),mb=ju((({lightDirection:e})=>{const t=e.add(Sg).normalize(),s=Fg.dot(e).clamp(),i=Fg.dot(Sg).clamp(),r=Fg.dot(t).clamp(),n=db({roughness:Dc,dotNH:r}),o=pb({dotNV:i,dotNL:s});return Vc.mul(n).mul(o)})),gb=ju((({N:e,V:t,roughness:s})=>{const i=e.dot(t).saturate(),r=sc(s,i.oneMinus().sqrt());return r.assign(r.mul(.984375).add(.0078125)),r})).setLayout({name:"LTC_Uv",type:"vec2",inputs:[{name:"N",type:"vec3"},{name:"V",type:"vec3"},{name:"roughness",type:"float"}]}),fb=ju((({f:e})=>{const t=e.length();return Tp(t.mul(t).add(e.z).div(t.add(1)),0)})).setLayout({name:"LTC_ClippedSphereFormFactor",type:"float",inputs:[{name:"f",type:"vec3"}]}),yb=ju((({v1:e,v2:t})=>{const s=e.dot(t),i=s.abs().toVar(),r=i.mul(.0145206).add(.4965155).mul(i).add(.8543985).toVar(),n=i.add(4.1616724).mul(i).add(3.417594).toVar(),o=r.div(n),a=s.greaterThan(0).select(o,Tp(s.mul(s).oneMinus(),1e-7).inverseSqrt().mul(.5).sub(o));return e.cross(t).mul(a)})).setLayout({name:"LTC_EdgeVectorFormFactor",type:"vec3",inputs:[{name:"v1",type:"vec3"},{name:"v2",type:"vec3"}]}),xb=ju((({N:e,V:t,P:s,mInv:i,p0:r,p1:n,p2:o,p3:a})=>{const h=n.sub(r).toVar(),l=a.sub(r).toVar(),u=h.cross(l),c=oc().toVar();return Yu(u.dot(s.sub(r)).greaterThanEqual(0),(()=>{const h=t.sub(e.mul(t.dot(e))).normalize(),l=e.cross(h).negate(),u=i.mul(gc(h,l,e).transpose()).toVar(),d=u.mul(r.sub(s)).normalize().toVar(),p=u.mul(n.sub(s)).normalize().toVar(),m=u.mul(o.sub(s)).normalize().toVar(),g=u.mul(a.sub(s)).normalize().toVar(),f=oc(0).toVar();f.addAssign(yb({v1:d,v2:p})),f.addAssign(yb({v1:p,v2:m})),f.addAssign(yb({v1:m,v2:g})),f.addAssign(yb({v1:g,v2:d})),c.assign(oc(fb({f:f})))})),c})).setLayout({name:"LTC_Evaluate",type:"vec3",inputs:[{name:"N",type:"vec3"},{name:"V",type:"vec3"},{name:"P",type:"vec3"},{name:"mInv",type:"mat3"},{name:"p0",type:"vec3"},{name:"p1",type:"vec3"},{name:"p2",type:"vec3"},{name:"p3",type:"vec3"}]}),bb=1/6,vb=e=>md(bb,md(e,md(e,e.negate().add(3)).sub(3)).add(1)),Tb=e=>md(bb,md(e,md(e,md(3,e).sub(6))).add(4)),_b=e=>md(bb,md(e,md(e,md(-3,e).add(3)).add(3)).add(1)),wb=e=>md(bb,Cp(e,3)),Sb=e=>vb(e).add(Tb(e)),Mb=e=>_b(e).add(wb(e)),Ab=e=>dd(-1,Tb(e).div(vb(e).add(Tb(e)))),Nb=e=>dd(1,wb(e).div(_b(e).add(wb(e)))),Rb=(e,t,s)=>{const i=e.uvNode,r=md(i,t.zw).add(.5),n=Jd(r),o=Qd(r),a=Sb(o.x),h=Mb(o.x),l=Ab(o.x),u=Nb(o.x),c=Ab(o.y),d=Nb(o.y),p=sc(n.x.add(l),n.y.add(c)).sub(.5).mul(t.xy),m=sc(n.x.add(u),n.y.add(c)).sub(.5).mul(t.xy),g=sc(n.x.add(l),n.y.add(d)).sub(.5).mul(t.xy),f=sc(n.x.add(u),n.y.add(d)).sub(.5).mul(t.xy),y=Sb(o.y).mul(dd(a.mul(e.uv(p).level(s)),h.mul(e.uv(m).level(s)))),x=Mb(o.y).mul(dd(a.mul(e.uv(g).level(s)),h.mul(e.uv(f).level(s))));return y.add(x)},Cb=ju((([e,t=Ku(3)])=>{const s=sc(e.size(Qu(t))),i=sc(e.size(Qu(t.add(1)))),r=gd(1,s),n=gd(1,i),o=Rb(e,uc(r,s),Jd(t)),a=Rb(e,uc(n,i),Zd(t));return Qd(t).mix(o,a)})),Eb=ju((([e,t,s,i,r])=>{const n=oc(Vp(t.negate(),Kd(e),gd(1,i))),o=oc(hp(r[0].xyz),hp(r[1].xyz),hp(r[2].xyz));return Kd(n).mul(s.mul(o))})).setLayout({name:"getVolumeTransmissionRay",type:"vec3",inputs:[{name:"n",type:"vec3"},{name:"v",type:"vec3"},{name:"thickness",type:"float"},{name:"ior",type:"float"},{name:"modelMatrix",type:"mat4"}]}),Bb=ju((([e,t])=>e.mul(Lp(t.mul(2).sub(2),0,1)))).setLayout({name:"applyIorToRoughness",type:"float",inputs:[{name:"roughness",type:"float"},{name:"ior",type:"float"}]}),Ib=ix(),Pb=ju((([e,t,s])=>{const i=Ib.uv(e),r=$d(Ku(Yy.x)).mul(Bb(t,s));return Cb(i,r)})),Fb=ju((([e,t,s])=>(Yu(s.notEqual(0),(()=>{const i=qd(t).negate().div(s);return Hd(i.negate().mul(e))})),oc(1)))).setLayout({name:"volumeAttenuation",type:"vec3",inputs:[{name:"transmissionDistance",type:"float"},{name:"attenuationColor",type:"vec3"},{name:"attenuationDistance",type:"float"}]}),zb=ju((([e,t,s,i,r,n,o,a,h,l,u,c,d,p,m])=>{let g,f;if(m){g=uc().toVar(),f=oc().toVar();const r=u.sub(1).mul(m.mul(.025)),n=oc(u.sub(r),u,u.add(r));Cy({start:0,end:3},(({i:r})=>{const u=n.element(r),m=Eb(e,t,c,u,a),y=o.add(m),x=l.mul(h.mul(uc(y,1))),b=sc(x.xy.div(x.w)).toVar();b.addAssign(1),b.divAssign(2),b.assign(sc(b.x,b.y.oneMinus()));const v=Pb(b,s,u);g.element(r).assign(v.element(r)),g.a.addAssign(v.a),f.element(r).assign(i.element(r).mul(Fb(hp(m),d,p).element(r)))})),g.a.divAssign(3)}else{const r=Eb(e,t,c,u,a),n=o.add(r),m=l.mul(h.mul(uc(n,1))),y=sc(m.xy.div(m.w)).toVar();y.addAssign(1),y.divAssign(2),y.assign(sc(y.x,y.y.oneMinus())),g=Pb(y,s,u),f=i.mul(Fb(hp(r),d,p))}const y=f.rgb.mul(g.rgb),x=e.dot(t).clamp(),b=oc(ub({dotNV:x,specularColor:r,specularF90:n,roughness:s})),v=f.r.add(f.g,f.b).div(3);return uc(b.oneMinus().mul(y),g.a.oneMinus().mul(v).oneMinus())})),Ub=gc(3.2404542,-.969266,.0556434,-1.5371385,1.8760108,-.2040259,-.4985314,.041556,1.0572252),Lb=(e,t)=>e.sub(t).div(e.add(t)).pow2(),Ob=(e,t)=>{const s=e.mul(2*Math.PI*1e-9),i=oc(54856e-17,44201e-17,52481e-17),r=oc(1681e3,1795300,2208400),n=oc(43278e5,93046e5,66121e5),o=Ku(9747e-17*Math.sqrt(2*Math.PI*45282e5)).mul(s.mul(2239900).add(t.x).cos()).mul(s.pow2().mul(-45282e5).exp());let a=i.mul(n.mul(2*Math.PI).sqrt()).mul(r.mul(s).add(t).cos()).mul(s.pow2().negate().mul(n).exp());a=oc(a.x.add(o),a.y,a.z).div(1.0685e-7);return Ub.mul(a)},Vb=ju((({outsideIOR:e,eta2:t,cosTheta1:s,thinFilmThickness:i,baseF0:r})=>{const n=Up(e,t,Dp(0,.03,i)),o=e.div(n).pow2().mul(Ku(1).sub(s.pow2())),a=Ku(1).sub(o).sqrt(),h=Lb(n,e),l=qx({f0:h,f90:1,dotVH:s}),u=l.oneMinus(),c=n.lessThan(e).select(Math.PI,0),d=Ku(Math.PI).sub(c),p=(e=>{const t=e.sqrt();return oc(1).add(t).div(oc(1).sub(t))})(r.clamp(0,.9999)),m=Lb(p,n.toVec3()),g=qx({f0:m,f90:1,dotVH:a}),f=oc(p.x.lessThan(n).select(Math.PI,0),p.y.lessThan(n).select(Math.PI,0),p.z.lessThan(n).select(Math.PI,0)),y=n.mul(i,a,2),x=oc(d).add(f),b=l.mul(g).clamp(1e-5,.9999),v=b.sqrt(),T=u.pow2().mul(g).div(oc(1).sub(b));let _=l.add(T),w=T.sub(u);for(let e=1;e<=2;++e){w=w.mul(v);const t=Ob(Ku(e).mul(y),Ku(e).mul(x)).mul(2);_=_.add(w.mul(t))}return _.max(oc(0))})).setLayout({name:"evalIridescence",type:"vec3",inputs:[{name:"outsideIOR",type:"float"},{name:"eta2",type:"float"},{name:"cosTheta1",type:"float"},{name:"thinFilmThickness",type:"float"},{name:"baseF0",type:"vec3"}]}),Db=ju((({normal:e,viewDir:t,roughness:s})=>{const i=e.dot(t).saturate(),r=s.pow2(),n=qp(s.lessThan(.25),Ku(-339.2).mul(r).add(Ku(161.4).mul(s)).sub(25.9),Ku(-8.48).mul(r).add(Ku(14.3).mul(s)).sub(9.95)),o=qp(s.lessThan(.25),Ku(44).mul(r).sub(Ku(23.7).mul(s)).add(3.26),Ku(1.97).mul(r).sub(Ku(3.27).mul(s)).add(.72));return qp(s.lessThan(.25),0,Ku(.1).mul(s).sub(.025)).add(n.mul(i).add(o).exp()).mul(1/Math.PI).saturate()})),kb=oc(.04),Gb=Ku(1);class Wb extends Gx{constructor(e=!1,t=!1,s=!1,i=!1,r=!1,n=!1){super(),this.clearcoat=e,this.sheen=t,this.iridescence=s,this.anisotropy=i,this.transmission=r,this.dispersion=n,this.clearcoatRadiance=null,this.clearcoatSpecularDirect=null,this.clearcoatSpecularIndirect=null,this.sheenSpecularDirect=null,this.sheenSpecularIndirect=null,this.iridescenceFresnel=null,this.iridescenceF0=null}start(e){if(!0===this.clearcoat&&(this.clearcoatRadiance=oc().toVar("clearcoatRadiance"),this.clearcoatSpecularDirect=oc().toVar("clearcoatSpecularDirect"),this.clearcoatSpecularIndirect=oc().toVar("clearcoatSpecularIndirect")),!0===this.sheen&&(this.sheenSpecularDirect=oc().toVar("sheenSpecularDirect"),this.sheenSpecularIndirect=oc().toVar("sheenSpecularIndirect")),!0===this.iridescence){const e=Fg.dot(Sg).clamp();this.iridescenceFresnel=Vb({outsideIOR:Ku(1),eta2:Gc,cosTheta1:e,thinFilmThickness:Wc,baseF0:Xc}),this.iridescenceF0=cb({f:this.iridescenceFresnel,f90:1,dotVH:e})}if(!0===this.transmission){const t=Tg,s=eg.sub(Tg).normalize(),i=zg;e.backdrop=zb(i,s,zc,Pc,Xc,Yc,t,pg,Zm,Ym,td,id,nd,rd,this.dispersion?od:null),e.backdropAlpha=sd,Pc.a.mulAssign(Up(1,e.backdrop.a,sd))}}computeMultiscattering(e,t,s){const i=Fg.dot(Sg).clamp(),r=lb({roughness:zc,dotNV:i}),n=(this.iridescenceF0?kc.mix(Xc,this.iridescenceF0):Xc).mul(r.x).add(s.mul(r.y)),o=r.x.add(r.y).oneMinus(),a=Xc.add(Xc.oneMinus().mul(.047619)),h=n.mul(a).div(o.mul(a).oneMinus());e.addAssign(n),t.addAssign(h.mul(o))}direct({lightDirection:e,lightColor:t,reflectedLight:s}){const i=Fg.dot(e).clamp().mul(t);if(!0===this.sheen&&this.sheenSpecularDirect.addAssign(i.mul(mb({lightDirection:e}))),!0===this.clearcoat){const s=Ug.dot(e).clamp().mul(t);this.clearcoatSpecularDirect.addAssign(s.mul(hb({lightDirection:e,f0:kb,f90:Gb,roughness:Oc,normalView:Ug})))}s.directDiffuse.addAssign(i.mul($x({diffuseColor:Pc.rgb}))),s.directSpecular.addAssign(i.mul(hb({lightDirection:e,f0:Xc,f90:1,roughness:zc,iridescence:this.iridescence,f:this.iridescenceFresnel,USE_IRIDESCENCE:this.iridescence,USE_ANISOTROPY:this.anisotropy})))}directRectArea({lightColor:e,lightPosition:t,halfWidth:s,halfHeight:i,reflectedLight:r,ltc_1:n,ltc_2:o}){const a=t.add(s).sub(i),h=t.sub(s).sub(i),l=t.sub(s).add(i),u=t.add(s).add(i),c=Fg,d=Sg,p=wg.toVar(),m=gb({N:c,V:d,roughness:zc}),g=n.uv(m).toVar(),f=o.uv(m).toVar(),y=gc(oc(g.x,0,g.y),oc(0,1,0),oc(g.z,0,g.w)).toVar(),x=Xc.mul(f.x).add(Xc.oneMinus().mul(f.y)).toVar();r.directSpecular.addAssign(e.mul(x).mul(xb({N:c,V:d,P:p,mInv:y,p0:a,p1:h,p2:l,p3:u}))),r.directDiffuse.addAssign(e.mul(Pc).mul(xb({N:c,V:d,P:p,mInv:gc(1,0,0,0,1,0,0,0,1),p0:a,p1:h,p2:l,p3:u})))}indirect(e,t,s){this.indirectDiffuse(e,t,s),this.indirectSpecular(e,t,s),this.ambientOcclusion(e,t,s)}indirectDiffuse({irradiance:e,reflectedLight:t}){t.indirectDiffuse.addAssign(e.mul($x({diffuseColor:Pc})))}indirectSpecular({radiance:e,iblIrradiance:t,reflectedLight:s}){if(!0===this.sheen&&this.sheenSpecularIndirect.addAssign(t.mul(Vc,Db({normal:Fg,viewDir:Sg,roughness:Dc}))),!0===this.clearcoat){const e=Ug.dot(Sg).clamp(),t=ub({dotNV:e,specularColor:kb,specularF90:Gb,roughness:Oc});this.clearcoatSpecularIndirect.addAssign(this.clearcoatRadiance.mul(t))}const i=oc().toVar("singleScattering"),r=oc().toVar("multiScattering"),n=t.mul(1/Math.PI);this.computeMultiscattering(i,r,Yc);const o=i.add(r),a=Pc.mul(o.r.max(o.g).max(o.b).oneMinus());s.indirectSpecular.addAssign(e.mul(i)),s.indirectSpecular.addAssign(r.mul(n)),s.indirectDiffuse.addAssign(a.mul(n))}ambientOcclusion({ambientOcclusion:e,reflectedLight:t}){const s=Fg.dot(Sg).clamp().add(e),i=zc.mul(-16).oneMinus().negate().exp2(),r=e.sub(s.pow(i).oneMinus()).clamp();!0===this.clearcoat&&this.clearcoatSpecularIndirect.mulAssign(e),!0===this.sheen&&this.sheenSpecularIndirect.mulAssign(e),t.indirectDiffuse.mulAssign(e),t.indirectSpecular.mulAssign(r)}finish(e){const{outgoingLight:t}=e;if(!0===this.clearcoat){const e=Ug.dot(Sg).clamp(),s=qx({dotVH:e,f0:kb,f90:Gb}),i=t.mul(Lc.mul(s).oneMinus()).add(this.clearcoatSpecularDirect.add(this.clearcoatSpecularIndirect).mul(Lc));t.assign(i)}if(!0===this.sheen){const e=Vc.r.max(Vc.g).max(Vc.b).mul(.157).oneMinus(),s=t.mul(e).add(this.sheenSpecularDirect,this.sheenSpecularIndirect);t.assign(s)}}}const Hb=Ku(1),jb=Ku(-2),qb=Ku(.8),$b=Ku(-1),Xb=Ku(.4),Yb=Ku(2),Jb=Ku(.305),Zb=Ku(3),Kb=Ku(.21),Qb=Ku(4),ev=Ku(4),tv=Ku(16),sv=ju((([e])=>{const t=oc(op(e)).toVar(),s=Ku(-1).toVar();return Yu(t.x.greaterThan(t.z),(()=>{Yu(t.x.greaterThan(t.y),(()=>{s.assign(qp(e.x.greaterThan(0),0,3))})).Else((()=>{s.assign(qp(e.y.greaterThan(0),1,4))}))})).Else((()=>{Yu(t.z.greaterThan(t.y),(()=>{s.assign(qp(e.z.greaterThan(0),2,5))})).Else((()=>{s.assign(qp(e.y.greaterThan(0),1,4))}))})),s})).setLayout({name:"getFace",type:"float",inputs:[{name:"direction",type:"vec3"}]}),iv=ju((([e,t])=>{const s=sc().toVar();return Yu(t.equal(0),(()=>{s.assign(sc(e.z,e.y).div(op(e.x)))})).ElseIf(t.equal(1),(()=>{s.assign(sc(e.x.negate(),e.z.negate()).div(op(e.y)))})).ElseIf(t.equal(2),(()=>{s.assign(sc(e.x.negate(),e.y).div(op(e.z)))})).ElseIf(t.equal(3),(()=>{s.assign(sc(e.z.negate(),e.y).div(op(e.x)))})).ElseIf(t.equal(4),(()=>{s.assign(sc(e.x.negate(),e.z).div(op(e.y)))})).Else((()=>{s.assign(sc(e.x,e.y).div(op(e.z)))})),md(.5,s.add(1))})).setLayout({name:"getUV",type:"vec2",inputs:[{name:"direction",type:"vec3"},{name:"face",type:"float"}]}),rv=ju((([e])=>{const t=Ku(0).toVar();return Yu(e.greaterThanEqual(qb),(()=>{t.assign(Hb.sub(e).mul($b.sub(jb)).div(Hb.sub(qb)).add(jb))})).ElseIf(e.greaterThanEqual(Xb),(()=>{t.assign(qb.sub(e).mul(Yb.sub($b)).div(qb.sub(Xb)).add($b))})).ElseIf(e.greaterThanEqual(Jb),(()=>{t.assign(Xb.sub(e).mul(Zb.sub(Yb)).div(Xb.sub(Jb)).add(Yb))})).ElseIf(e.greaterThanEqual(Kb),(()=>{t.assign(Jb.sub(e).mul(Qb.sub(Zb)).div(Jb.sub(Kb)).add(Zb))})).Else((()=>{t.assign(Ku(-2).mul($d(md(1.16,e))))})),t})).setLayout({name:"roughnessToMip",type:"float",inputs:[{name:"roughness",type:"float"}]}),nv=ju((([e,t])=>{const s=e.toVar();s.assign(md(2,s).sub(1));const i=oc(s,1).toVar();return Yu(t.equal(0),(()=>{i.assign(i.zyx)})).ElseIf(t.equal(1),(()=>{i.assign(i.xzy),i.xz.mulAssign(-1)})).ElseIf(t.equal(2),(()=>{i.x.mulAssign(-1)})).ElseIf(t.equal(3),(()=>{i.assign(i.zyx),i.xz.mulAssign(-1)})).ElseIf(t.equal(4),(()=>{i.assign(i.xzy),i.xy.mulAssign(-1)})).ElseIf(t.equal(5),(()=>{i.z.mulAssign(-1)})),i})).setLayout({name:"getDirection",type:"vec3",inputs:[{name:"uv",type:"vec2"},{name:"face",type:"float"}]}),ov=ju((([e,t,s,i,r,n])=>{const o=Ku(s),a=oc(t),h=Lp(rv(o),jb,n),l=Qd(h),u=Jd(h),c=oc(av(e,a,u,i,r,n)).toVar();return Yu(l.notEqual(0),(()=>{const t=oc(av(e,a,u.add(1),i,r,n)).toVar();c.assign(Up(c,t,l))})),c})),av=ju((([e,t,s,i,r,n])=>{const o=Ku(s).toVar(),a=oc(t),h=Ku(sv(a)).toVar(),l=Ku(Tp(ev.sub(o),0)).toVar();o.assign(Tp(o,ev));const u=Ku(jd(o)).toVar(),c=sc(iv(a,h).mul(u.sub(2)).add(1)).toVar();return Yu(h.greaterThan(2),(()=>{c.y.addAssign(u),h.subAssign(3)})),c.x.addAssign(h.mul(u)),c.x.addAssign(l.mul(md(3,tv))),c.y.addAssign(md(4,jd(n).sub(u))),c.x.mulAssign(i),c.y.mulAssign(r),e.uv(c).grad(sc(),sc())})),hv=ju((({envMap:e,mipInt:t,outputDirection:s,theta:i,axis:r,CUBEUV_TEXEL_WIDTH:n,CUBEUV_TEXEL_HEIGHT:o,CUBEUV_MAX_MIP:a})=>{const h=tp(i),l=s.mul(h).add(r.cross(s).mul(ep(i))).add(r.mul(r.dot(s).mul(h.oneMinus())));return av(e,l,t,n,o,a)})),lv=ju((({n:e,latitudinal:t,poleAxis:s,outputDirection:i,weights:r,samples:n,dTheta:o,mipInt:a,envMap:h,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:u,CUBEUV_MAX_MIP:c})=>{const d=oc(qp(t,s,Rp(s,i))).toVar();Yu(Vd(d.equals(oc(0))),(()=>{d.assign(oc(i.z,0,i.x.negate()))})),d.assign(Kd(d));const p=oc().toVar();return p.addAssign(r.element(Qu(0)).mul(hv({theta:0,axis:d,outputDirection:i,mipInt:a,envMap:h,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:u,CUBEUV_MAX_MIP:c}))),Cy({start:Qu(1),end:e},(({i:e})=>{Yu(e.greaterThanEqual(n),(()=>{By()}));const t=Ku(o.mul(Ku(e))).toVar();p.addAssign(r.element(e).mul(hv({theta:t.mul(-1),axis:d,outputDirection:i,mipInt:a,envMap:h,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:u,CUBEUV_MAX_MIP:c}))),p.addAssign(r.element(e).mul(hv({theta:t,axis:d,outputDirection:i,mipInt:a,envMap:h,CUBEUV_TEXEL_WIDTH:l,CUBEUV_TEXEL_HEIGHT:u,CUBEUV_MAX_MIP:c})))})),uc(p,1)}));let uv=null;const cv=new WeakMap;function dv(e){let t=cv.get(e);if((void 0!==t?t.pmremVersion:-1)!==e.pmremVersion){const s=e.image;if(e.isCubeTexture){if(!function(e){if(null==e)return!1;let t=0;const s=6;for(let i=0;i0}(s))return null;t=uv.fromEquirectangular(e,t)}t.pmremVersion=e.pmremVersion,cv.set(e,t)}return t.texture}class pv extends iu{constructor(e,t=null,s=null){super("vec3"),this._value=e,this._pmrem=null,this.uvNode=t,this.levelNode=s,this._generator=null;const i=new Ti;i.isRenderTargetTexture=!0,this._texture=Gm(i),this._width=Cc(0),this._height=Cc(0),this._maxMip=Cc(0),this.updateBeforeType=Hl.RENDER}set value(e){this._value=e,this._pmrem=null}get value(){return this._value}updateFromTexture(e){const t=function(e){const t=Math.log2(e)-2,s=1/e;return{texelWidth:1/(3*Math.max(Math.pow(2,t),112)),texelHeight:s,maxMip:t}}(e.image.height);this._texture.value=e,this._width.value=t.texelWidth,this._height.value=t.texelHeight,this._maxMip.value=t.maxMip}updateBefore(){let e=this._pmrem;const t=e?e.pmremVersion:-1,s=this._value;t!==s.pmremVersion&&(e=!0===s.isPMREMTexture?s:dv(s),null!==e&&(this._pmrem=e,this.updateFromTexture(e)))}setup(e){null===uv&&(uv=e.createPMREMGenerator()),this.updateBefore(e);let t=this.uvNode;null===t&&e.context.getUV&&(t=e.context.getUV(this));const s=this.value;e.renderer.coordinateSystem===Vs&&!0!==s.isPMREMTexture&&!0===s.isRenderTargetTexture&&(t=oc(t.x.negate(),t.yz));let i=this.levelNode;return null===i&&e.context.getTextureLevel&&(i=e.context.getTextureLevel(this)),ov(this._texture,t,i,this._width,this._height,this._maxMip)}}pv.type=Ql("PMREM",pv);const mv=Wu(pv),gv=new WeakMap;class fv extends Dy{constructor(e=null){super(),this.envNode=e}setup(e){const{material:t}=e;let s=this.envNode;if(s.isTextureNode||s.isMaterialReferenceNode){const e=s.isTextureNode?s.value:t[s.property];let i=gv.get(e);void 0===i&&(i=mv(e),gv.set(e,i)),s=i}const i=t.envMap?Zg("envMapIntensity","float",e.material):Zg("environmentIntensity","float",e.scene),r=!0===t.useAnisotropy||t.anisotropy>0?xf:Fg,n=s.context(yv(zc,r)).mul(i),o=s.context(xv(zg)).mul(Math.PI).mul(i),a=Tm(n),h=Tm(o);e.context.radiance.addAssign(a),e.context.iblIrradiance.addAssign(h);const l=e.context.lightingModel.clearcoatRadiance;if(l){const e=s.context(yv(Oc,Ug)).mul(i),t=Tm(e);l.addAssign(t)}}}fv.type=Ql("Environment",fv);const yv=(e,t)=>{let s=null;return{getUV:()=>(null===s&&(s=Sg.negate().reflect(t),s=e.mul(e).mix(s,t).normalize(),s=s.transformDirection(Zm)),s),getTextureLevel:()=>e}},xv=e=>({getUV:()=>e,getTextureLevel:()=>Ku(1)}),bv=new Al;class vv extends xx{constructor(e){super(),this.isMeshStandardNodeMaterial=!0,this.lights=!0,this.emissiveNode=null,this.metalnessNode=null,this.roughnessNode=null,this.setDefaultValues(bv),this.setValues(e)}setupEnvironment(e){let t=super.setupEnvironment(e);return null===t&&e.environmentNode&&(t=e.environmentNode),t?new fv(t):null}setupLightingModel(){return new Wb}setupSpecular(){const e=Up(oc(.04),Pc.rgb,Uc);Xc.assign(e),Yc.assign(1)}setupVariants(){const e=this.metalnessNode?Ku(this.metalnessNode):Vf;Uc.assign(e);let t=this.roughnessNode?Ku(this.roughnessNode):Of;t=sb({roughness:t}),zc.assign(t),this.setupSpecular(),Pc.assign(uc(Pc.rgb.mul(e.oneMinus()),Pc.a))}copy(e){return this.emissiveNode=e.emissiveNode,this.metalnessNode=e.metalnessNode,this.roughnessNode=e.roughnessNode,super.copy(e)}}vv.type=bx("MeshStandard",vv);const Tv=new Nl;class _v extends vv{constructor(e){super(),this.isMeshPhysicalNodeMaterial=!0,this.clearcoatNode=null,this.clearcoatRoughnessNode=null,this.clearcoatNormalNode=null,this.sheenNode=null,this.sheenRoughnessNode=null,this.iridescenceNode=null,this.iridescenceIORNode=null,this.iridescenceThicknessNode=null,this.specularIntensityNode=null,this.specularColorNode=null,this.iorNode=null,this.transmissionNode=null,this.thicknessNode=null,this.attenuationDistanceNode=null,this.attenuationColorNode=null,this.dispersionNode=null,this.anisotropyNode=null,this.setDefaultValues(Tv),this.setValues(e)}get useClearcoat(){return this.clearcoat>0||null!==this.clearcoatNode}get useIridescence(){return this.iridescence>0||null!==this.iridescenceNode}get useSheen(){return this.sheen>0||null!==this.sheenNode}get useAnisotropy(){return this.anisotropy>0||null!==this.anisotropyNode}get useTransmission(){return this.transmission>0||null!==this.transmissionNode}get useDispersion(){return this.dispersion>0||null!==this.dispersionNode}setupSpecular(){const e=this.iorNode?Ku(this.iorNode):Qf;td.assign(e),Xc.assign(Up(vp(Ep(td.sub(1).div(td.add(1))).mul(zf),oc(1)).mul(Ff),Pc.rgb,Uc)),Yc.assign(Up(Ff,1,Uc))}setupLightingModel(){return new Wb(this.useClearcoat,this.useSheen,this.useIridescence,this.useAnisotropy,this.useTransmission,this.useDispersion)}setupVariants(e){if(super.setupVariants(e),this.useClearcoat){const e=this.clearcoatNode?Ku(this.clearcoatNode):kf,t=this.clearcoatRoughnessNode?Ku(this.clearcoatRoughnessNode):Gf;Lc.assign(e),Oc.assign(sb({roughness:t}))}if(this.useSheen){const e=this.sheenNode?oc(this.sheenNode):jf,t=this.sheenRoughnessNode?Ku(this.sheenRoughnessNode):qf;Vc.assign(e),Dc.assign(t)}if(this.useIridescence){const e=this.iridescenceNode?Ku(this.iridescenceNode):Xf,t=this.iridescenceIORNode?Ku(this.iridescenceIORNode):Yf,s=this.iridescenceThicknessNode?Ku(this.iridescenceThicknessNode):Jf;kc.assign(e),Gc.assign(t),Wc.assign(s)}if(this.useAnisotropy){const e=(this.anisotropyNode?sc(this.anisotropyNode):$f).toVar();jc.assign(e.length()),Yu(jc.equal(0),(()=>{e.assign(sc(1,0))})).Else((()=>{e.divAssign(sc(jc)),jc.assign(jc.saturate())})),Hc.assign(jc.pow2().mix(zc.pow2(),1)),qc.assign(gf[0].mul(e.x).add(gf[1].mul(e.y))),$c.assign(gf[1].mul(e.x).sub(gf[0].mul(e.y)))}if(this.useTransmission){const e=this.transmissionNode?Ku(this.transmissionNode):Zf,t=this.thicknessNode?Ku(this.thicknessNode):Kf,s=this.attenuationDistanceNode?Ku(this.attenuationDistanceNode):ey,i=this.attenuationColorNode?oc(this.attenuationColorNode):ty;if(sd.assign(e),id.assign(t),rd.assign(s),nd.assign(i),this.useDispersion){const e=this.dispersionNode?Ku(this.dispersionNode):hy;od.assign(e)}}}setupClearcoatNormal(){return this.clearcoatNormalNode?oc(this.clearcoatNormalNode):Wf}setup(e){e.context.setupClearcoatNormal=()=>this.setupClearcoatNormal(e),super.setup(e)}copy(e){return this.clearcoatNode=e.clearcoatNode,this.clearcoatRoughnessNode=e.clearcoatRoughnessNode,this.clearcoatNormalNode=e.clearcoatNormalNode,this.sheenNode=e.sheenNode,this.sheenRoughnessNode=e.sheenRoughnessNode,this.iridescenceNode=e.iridescenceNode,this.iridescenceIORNode=e.iridescenceIORNode,this.iridescenceThicknessNode=e.iridescenceThicknessNode,this.specularIntensityNode=e.specularIntensityNode,this.specularColorNode=e.specularColorNode,this.transmissionNode=e.transmissionNode,this.thicknessNode=e.thicknessNode,this.attenuationDistanceNode=e.attenuationDistanceNode,this.attenuationColorNode=e.attenuationColorNode,this.dispersionNode=e.dispersionNode,this.anisotropyNode=e.anisotropyNode,super.copy(e)}}_v.type=bx("MeshPhysical",_v);class wv extends Wb{constructor(e,t,s,i){super(e,t,s),this.useSSS=i}direct({lightDirection:e,lightColor:t,reflectedLight:s},i,r){if(!0===this.useSSS){const i=r.material,{thicknessColorNode:n,thicknessDistortionNode:o,thicknessAmbientNode:a,thicknessAttenuationNode:h,thicknessPowerNode:l,thicknessScaleNode:u}=i,c=e.add(Fg.mul(o)).normalize(),d=Ku(Sg.dot(c.negate()).saturate().pow(l).mul(u)),p=oc(d.add(a).mul(n));s.directDiffuse.addAssign(p.mul(h.mul(t)))}super.direct({lightDirection:e,lightColor:t,reflectedLight:s},i,r)}}class Sv extends _v{constructor(e){super(e),this.thicknessColorNode=null,this.thicknessDistortionNode=Ku(.1),this.thicknessAmbientNode=Ku(0),this.thicknessAttenuationNode=Ku(.1),this.thicknessPowerNode=Ku(2),this.thicknessScaleNode=Ku(10)}get useSSS(){return null!==this.thicknessColorNode}setupLightingModel(){return new wv(this.useClearcoat,this.useSheen,this.useIridescence,this.useSSS)}copy(e){return this.thicknessColorNode=e.thicknessColorNode,this.thicknessDistortionNode=e.thicknessDistortionNode,this.thicknessAmbientNode=e.thicknessAmbientNode,this.thicknessAttenuationNode=e.thicknessAttenuationNode,this.thicknessPowerNode=e.thicknessPowerNode,this.thicknessScaleNode=e.thicknessScaleNode,super.copy(e)}}Sv.type=bx("MeshSSS",Sv);const Mv=ju((({normal:e,lightDirection:t,builder:s})=>{const i=e.dot(t),r=sc(i.mul(.5).add(.5),0);if(s.material.gradientMap){const e=ef("gradientMap","texture").context({getUV:()=>r});return oc(e.r)}{const e=r.fwidth().mul(.5);return Up(oc(.7),oc(1),Dp(Ku(.7).sub(e.x),Ku(.7).add(e.x),r.x))}}));class Av extends Gx{direct({lightDirection:e,lightColor:t,reflectedLight:s},i,r){const n=Mv({normal:Rg,lightDirection:e,builder:r}).mul(t);s.directDiffuse.addAssign(n.mul($x({diffuseColor:Pc.rgb})))}indirect({ambientOcclusion:e,irradiance:t,reflectedLight:s}){s.indirectDiffuse.addAssign(t.mul($x({diffuseColor:Pc}))),s.indirectDiffuse.mulAssign(e)}}const Nv=new Cl;class Rv extends xx{constructor(e){super(),this.isMeshToonNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Nv),this.setValues(e)}setupLightingModel(){return new Av}}Rv.type=bx("MeshToon",Rv);class Cv extends iu{constructor(){super("vec2")}setup(){const e=oc(Sg.z,0,Sg.x.negate()).normalize(),t=Sg.cross(e);return sc(e.dot(Fg),t.dot(Fg)).mul(.495).add(.5)}}Cv.type=Ql("MatcapUV",Cv);const Ev=Hu(Cv),Bv=new Fl;class Iv extends xx{constructor(e){super(),this.lights=!1,this.isMeshMatcapNodeMaterial=!0,this.setDefaultValues(Bv),this.setValues(e)}setupVariants(e){const t=Ev;let s;s=e.material.matcap?ef("matcap","texture").context({getUV:()=>t}):oc(Up(.2,.8,t.y)),Pc.rgb.mulAssign(s.rgb)}}Iv.type=bx("MeshMatcap",Iv);const Pv=new Va;class Fv extends xx{constructor(e){super(),this.isPointsNodeMaterial=!0,this.lights=!1,this.transparent=!0,this.sizeNode=null,this.setDefaultValues(Pv),this.setValues(e)}copy(e){return this.sizeNode=e.sizeNode,super.copy(e)}}Fv.type=bx("Points",Fv);class zv extends iu{constructor(e,t){super(),this.positionNode=e,this.rotationNode=t}getNodeType(e){return this.positionNode.getNodeType(e)}setup(e){const{rotationNode:t,positionNode:s}=this;if("vec2"===this.getNodeType(e)){const e=t.cos(),i=t.sin();return mc(e,i,i.negate(),e).mul(s)}{const e=t,i=fc(uc(1,0,0,0),uc(0,tp(e.x),ep(e.x).negate(),0),uc(0,ep(e.x),tp(e.x),0),uc(0,0,0,1)),r=fc(uc(tp(e.y),0,ep(e.y),0),uc(0,1,0,0),uc(ep(e.y).negate(),0,tp(e.y),0),uc(0,0,0,1)),n=fc(uc(tp(e.z),ep(e.z).negate(),0,0),uc(ep(e.z),tp(e.z),0,0),uc(0,0,1,0),uc(0,0,0,1));return i.mul(r).mul(n).mul(uc(s,1)).xyz}}}zv.type=Ql("Rotate",zv);const Uv=Wu(zv),Lv=new lo;class Ov extends xx{constructor(e){super(),this.isSpriteNodeMaterial=!0,this.lights=!1,this.positionNode=null,this.rotationNode=null,this.scaleNode=null,this.setDefaultValues(Lv),this.setValues(e)}setupPosition({object:e,context:t}){const{positionNode:s,rotationNode:i,scaleNode:r}=this,n=bg;let o=cg.mul(oc(s||0)),a=sc(pg[0].xyz.length(),pg[1].xyz.length());null!==r&&(a=a.mul(r));let h=n.xy;e.center&&!0===e.center.isVector2&&(h=h.sub(Cc(e.center).sub(.5))),h=h.mul(a);const l=Ku(i||Hf),u=Uv(h,l);o=uc(o.xy.add(u),o.zw);const c=Ym.mul(o);return t.vertex=n,c}copy(e){return this.positionNode=e.positionNode,this.rotationNode=e.rotationNode,this.scaleNode=e.scaleNode,super.copy(e)}}Ov.type=bx("Sprite",Ov);class Vv extends Gx{constructor(){super(),this.shadowNode=Ku(1).toVar("shadowMask")}direct({shadowMask:e}){this.shadowNode.mulAssign(e)}finish(e){Pc.a.mulAssign(this.shadowNode.oneMinus()),e.outgoingLight.rgb.assign(Pc.rgb)}}const Dv=new Sl;class kv extends xx{constructor(e){super(),this.isShadowNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Dv),this.setValues(e)}setupLightingModel(){return new Vv}}kv.type=bx("Shadow",kv);const Gv=ju((({texture:e,uv:t})=>{const s=1e-4,i=oc().temp();return Yu(t.x.lessThan(s),(()=>{i.assign(oc(1,0,0))})).ElseIf(t.y.lessThan(s),(()=>{i.assign(oc(0,1,0))})).ElseIf(t.z.lessThan(s),(()=>{i.assign(oc(0,0,1))})).ElseIf(t.x.greaterThan(.9999),(()=>{i.assign(oc(-1,0,0))})).ElseIf(t.y.greaterThan(.9999),(()=>{i.assign(oc(0,-1,0))})).ElseIf(t.z.greaterThan(.9999),(()=>{i.assign(oc(0,0,-1))})).Else((()=>{const s=.01,r=e.uv(t.add(oc(-.01,0,0))).r.sub(e.uv(t.add(oc(s,0,0))).r),n=e.uv(t.add(oc(0,-.01,0))).r.sub(e.uv(t.add(oc(0,s,0))).r),o=e.uv(t.add(oc(0,0,-.01))).r.sub(e.uv(t.add(oc(0,0,s))).r);i.assign(oc(r,n,o))})),i.normalize()}));class Wv extends km{constructor(e,t=null,s=null){super(e,t,s),this.isTexture3DNode=!0}getInputType(){return"texture3D"}getDefaultUV(){return oc(.5,.5,.5)}setUpdateMatrix(){}setupUV(e,t){return t}generateUV(e,t){return t.build(e,"vec3")}normal(e){return Gv({texture:this,uv:e})}}Wv.type=Ql("Texture3D",Wv);const Hv=Wu(Wv);class jv extends xx{constructor(e={}){super(),this.lights=!1,this.isVolumeNodeMaterial=!0,this.testNode=null,this.setValues(e)}setup(e){const t=Hv(this.map,null,0),s=ju((({orig:e,dir:t})=>{const s=oc(-.5),i=oc(.5),r=t.reciprocal(),n=s.sub(e).mul(r),o=i.sub(e).mul(r),a=vp(n,o),h=Tp(n,o),l=Tp(a.x,Tp(a.y,a.z)),u=vp(h.x,vp(h.y,h.z));return sc(l,u)}));this.fragmentNode=ju((()=>{const e=em(oc(yg.mul(uc(eg,1)))),i=em(xg.sub(e)).normalize(),r=Bc("vec2","bounds").assign(s({orig:e,dir:i}));r.x.greaterThan(r.y).discard(),r.assign(sc(Tp(r.x,0),r.y));const n=Bc("vec3","p").assign(e.add(r.x.mul(i))),o=Bc("vec3","inc").assign(oc(i.abs().reciprocal())),a=Bc("float","delta").assign(vp(o.x,vp(o.y,o.z)));a.divAssign(ef("steps","float"));const h=Bc("vec4","ac").assign(uc(ef("base","color"),0));return Cy({type:"float",start:r.x,end:r.y,update:"+= delta"},(()=>{const e=Bc("float","d").assign(t.uv(n.add(.5)).r);null!==this.testNode?this.testNode({map:t,mapValue:e,probe:n,finalColor:h}).append():(h.a.assign(1),By()),n.addAssign(i.mul(a))})),h.a.equal(0).discard(),uc(h)}))(),super.setup(e)}}function qv(e,t,s){return!e||!s&&e.constructor===t?e:"number"==typeof t.BYTES_PER_ELEMENT?new t(e):Array.prototype.slice.call(e)}function $v(e){return ArrayBuffer.isView(e)&&!(e instanceof DataView)}function Xv(e){const t=e.length,s=new Array(t);for(let e=0;e!==t;++e)s[e]=e;return s.sort((function(t,s){return e[t]-e[s]})),s}function Yv(e,t,s){const i=e.length,r=new e.constructor(i);for(let n=0,o=0;o!==i;++n){const i=s[n]*t;for(let s=0;s!==t;++s)r[o++]=e[i+s]}return r}function Jv(e,t,s,i){let r=1,n=e[0];for(;void 0!==n&&void 0===n[i];)n=e[r++];if(void 0===n)return;let o=n[i];if(void 0!==o)if(Array.isArray(o))do{o=n[i],void 0!==o&&(t.push(n.time),s.push.apply(s,o)),n=e[r++]}while(void 0!==n);else if(void 0!==o.toArray)do{o=n[i],void 0!==o&&(t.push(n.time),o.toArray(s,s.length)),n=e[r++]}while(void 0!==n);else do{o=n[i],void 0!==o&&(t.push(n.time),s.push(o)),n=e[r++]}while(void 0!==n)}jv.type=bx("Volume",jv);const Zv={convertArray:qv,isTypedArray:$v,getKeyframeOrder:Xv,sortedArray:Yv,flattenJSON:Jv,subclip:function(e,t,s,i,r=30){const n=e.clone();n.name=t;const o=[];for(let e=0;e=i)){h.push(t.times[e]);for(let s=0;sn.tracks[e].times[0]&&(a=n.tracks[e].times[0]);for(let e=0;e=i.times[c]){const e=c*h+a,t=e+h-a;d=i.values.slice(e,t)}else{const e=i.createInterpolant(),t=a,s=h-a;e.evaluate(n),d=e.resultBuffer.slice(t,s)}if("quaternion"===r){(new Ci).fromArray(d).normalize().conjugate().toArray(d)}const p=o.times.length;for(let e=0;e=r)break e;{const o=t[1];e=r)break t}n=s,s=0}}for(;s>>1;et;)--n;if(++n,0!==r||n!==i){r>=n&&(n=Math.max(n,1),r=n-1);const e=this.getValueSize();this.times=s.slice(r,n),this.values=this.values.slice(r*e,n*e)}return this}validate(){let e=!0;const t=this.getValueSize();t-Math.floor(t)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),e=!1);const s=this.times,i=this.values,r=s.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),e=!1);let n=null;for(let t=0;t!==r;t++){const i=s[t];if("number"==typeof i&&isNaN(i)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,t,i),e=!1;break}if(null!==n&&n>i){console.error("THREE.KeyframeTrack: Out of order keys.",this,t,i,n),e=!1;break}n=i}if(void 0!==i&&$v(i))for(let t=0,s=i.length;t!==s;++t){const s=i[t];if(isNaN(s)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,t,s),e=!1;break}}return e}optimize(){const e=this.times.slice(),t=this.values.slice(),s=this.getValueSize(),i=this.getInterpolation()===Ft,r=e.length-1;let n=1;for(let o=1;o0){e[n]=e[r];for(let e=r*s,i=n*s,o=0;o!==s;++o)t[i+o]=t[e+o];++n}return n!==e.length?(this.times=e.slice(0,n),this.values=t.slice(0,n*s)):(this.times=e,this.values=t),this}clone(){const e=this.times.slice(),t=this.values.slice(),s=new(0,this.constructor)(this.name,e,t);return s.createInterpolant=this.createInterpolant,s}}sT.prototype.TimeBufferType=Float32Array,sT.prototype.ValueBufferType=Float32Array,sT.prototype.DefaultInterpolation=Pt;class iT extends sT{constructor(e,t,s){super(e,t,s)}}iT.prototype.ValueTypeName="bool",iT.prototype.ValueBufferType=Array,iT.prototype.DefaultInterpolation=It,iT.prototype.InterpolantFactoryMethodLinear=void 0,iT.prototype.InterpolantFactoryMethodSmooth=void 0;class rT extends sT{}rT.prototype.ValueTypeName="color";class nT extends sT{}nT.prototype.ValueTypeName="number";class oT extends Kv{constructor(e,t,s,i){super(e,t,s,i)}interpolate_(e,t,s,i){const r=this.resultBuffer,n=this.sampleValues,o=this.valueSize,a=(s-t)/(i-t);let h=e*o;for(let e=h+o;h!==e;h+=4)Ci.slerpFlat(r,0,n,h-o,n,h,a);return r}}class aT extends sT{InterpolantFactoryMethodLinear(e){return new oT(this.times,this.values,this.getValueSize(),e)}}aT.prototype.ValueTypeName="quaternion",aT.prototype.InterpolantFactoryMethodSmooth=void 0;class hT extends sT{constructor(e,t,s){super(e,t,s)}}hT.prototype.ValueTypeName="string",hT.prototype.ValueBufferType=Array,hT.prototype.DefaultInterpolation=It,hT.prototype.InterpolantFactoryMethodLinear=void 0,hT.prototype.InterpolantFactoryMethodSmooth=void 0;class lT extends sT{}lT.prototype.ValueTypeName="vector";class uT{constructor(e="",t=-1,s=[],i=2500){this.name=e,this.tracks=s,this.duration=t,this.blendMode=i,this.uuid=qs(),this.duration<0&&this.resetDuration()}static parse(e){const t=[],s=e.tracks,i=1/(e.fps||1);for(let e=0,r=s.length;e!==r;++e)t.push(cT(s[e]).scale(i));const r=new this(e.name,e.duration,t,e.blendMode);return r.uuid=e.uuid,r}static toJSON(e){const t=[],s=e.tracks,i={name:e.name,duration:e.duration,tracks:t,uuid:e.uuid,blendMode:e.blendMode};for(let e=0,i=s.length;e!==i;++e)t.push(sT.toJSON(s[e]));return i}static CreateFromMorphTargetSequence(e,t,s,i){const r=t.length,n=[];for(let e=0;e1){const e=n[1];let t=i[e];t||(i[e]=t=[]),t.push(s)}}const n=[];for(const e in i)n.push(this.CreateFromMorphTargetSequence(e,i[e],t,s));return n}static parseAnimation(e,t){if(!e)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const s=function(e,t,s,i,r){if(0!==s.length){const n=[],o=[];Jv(s,n,o,i),0!==n.length&&r.push(new e(t,n,o))}},i=[],r=e.name||"default",n=e.fps||30,o=e.blendMode;let a=e.length||-1;const h=e.hierarchy||[];for(let e=0;e{t&&t(r),this.manager.itemEnd(e)}),0),r;if(void 0!==fT[e])return void fT[e].push({onLoad:t,onProgress:s,onError:i});fT[e]=[],fT[e].push({onLoad:t,onProgress:s,onError:i});const n=new Request(e,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"}),o=this.mimeType,a=this.responseType;fetch(n).then((t=>{if(200===t.status||0===t.status){if(0===t.status&&console.warn("THREE.FileLoader: HTTP Status 0 received."),"undefined"==typeof ReadableStream||void 0===t.body||void 0===t.body.getReader)return t;const s=fT[e],i=t.body.getReader(),r=t.headers.get("X-File-Size")||t.headers.get("Content-Length"),n=r?parseInt(r):0,o=0!==n;let a=0;const h=new ReadableStream({start(e){!function t(){i.read().then((({done:i,value:r})=>{if(i)e.close();else{a+=r.byteLength;const i=new ProgressEvent("progress",{lengthComputable:o,loaded:a,total:n});for(let e=0,t=s.length;e{e.error(t)}))}()}});return new Response(h)}throw new yT(`fetch for "${t.url}" responded with ${t.status}: ${t.statusText}`,t)})).then((e=>{switch(a){case"arraybuffer":return e.arrayBuffer();case"blob":return e.blob();case"document":return e.text().then((e=>(new DOMParser).parseFromString(e,o)));case"json":return e.json();default:if(void 0===o)return e.text();{const t=/charset="?([^;"\s]*)"?/i.exec(o),s=t&&t[1]?t[1].toLowerCase():void 0,i=new TextDecoder(s);return e.arrayBuffer().then((e=>i.decode(e)))}}})).then((t=>{dT.add(e,t);const s=fT[e];delete fT[e];for(let e=0,i=s.length;e{const s=fT[e];if(void 0===s)throw this.manager.itemError(e),t;delete fT[e];for(let e=0,i=s.length;e{this.manager.itemEnd(e)})),this.manager.itemStart(e)}setResponseType(e){return this.responseType=e,this}setMimeType(e){return this.mimeType=e,this}}class bT extends gT{constructor(e){super(e)}load(e,t,s,i){const r=this,n=new xT(this.manager);n.setPath(this.path),n.setRequestHeader(this.requestHeader),n.setWithCredentials(this.withCredentials),n.load(e,(function(s){try{t(r.parse(JSON.parse(s)))}catch(t){i?i(t):console.error(t),r.manager.itemError(e)}}),s,i)}parse(e){const t=[];for(let s=0;s0:i.vertexColors=e.vertexColors),void 0!==e.uniforms)for(const t in e.uniforms){const r=e.uniforms[t];switch(i.uniforms[t]={},r.type){case"t":i.uniforms[t].value=s(r.value);break;case"c":i.uniforms[t].value=(new Yr).setHex(r.value);break;case"v2":i.uniforms[t].value=(new Qs).fromArray(r.value);break;case"v3":i.uniforms[t].value=(new Ei).fromArray(r.value);break;case"v4":i.uniforms[t].value=(new _i).fromArray(r.value);break;case"m3":i.uniforms[t].value=(new ei).fromArray(r.value);break;case"m4":i.uniforms[t].value=(new or).fromArray(r.value);break;default:i.uniforms[t].value=r.value}}if(void 0!==e.defines&&(i.defines=e.defines),void 0!==e.vertexShader&&(i.vertexShader=e.vertexShader),void 0!==e.fragmentShader&&(i.fragmentShader=e.fragmentShader),void 0!==e.glslVersion&&(i.glslVersion=e.glslVersion),void 0!==e.extensions)for(const t in e.extensions)i.extensions[t]=e.extensions[t];if(void 0!==e.lights&&(i.lights=e.lights),void 0!==e.clipping&&(i.clipping=e.clipping),void 0!==e.size&&(i.size=e.size),void 0!==e.sizeAttenuation&&(i.sizeAttenuation=e.sizeAttenuation),void 0!==e.map&&(i.map=s(e.map)),void 0!==e.matcap&&(i.matcap=s(e.matcap)),void 0!==e.alphaMap&&(i.alphaMap=s(e.alphaMap)),void 0!==e.bumpMap&&(i.bumpMap=s(e.bumpMap)),void 0!==e.bumpScale&&(i.bumpScale=e.bumpScale),void 0!==e.normalMap&&(i.normalMap=s(e.normalMap)),void 0!==e.normalMapType&&(i.normalMapType=e.normalMapType),void 0!==e.normalScale){let t=e.normalScale;!1===Array.isArray(t)&&(t=[t,t]),i.normalScale=(new Qs).fromArray(t)}return void 0!==e.displacementMap&&(i.displacementMap=s(e.displacementMap)),void 0!==e.displacementScale&&(i.displacementScale=e.displacementScale),void 0!==e.displacementBias&&(i.displacementBias=e.displacementBias),void 0!==e.roughnessMap&&(i.roughnessMap=s(e.roughnessMap)),void 0!==e.metalnessMap&&(i.metalnessMap=s(e.metalnessMap)),void 0!==e.emissiveMap&&(i.emissiveMap=s(e.emissiveMap)),void 0!==e.emissiveIntensity&&(i.emissiveIntensity=e.emissiveIntensity),void 0!==e.specularMap&&(i.specularMap=s(e.specularMap)),void 0!==e.specularIntensityMap&&(i.specularIntensityMap=s(e.specularIntensityMap)),void 0!==e.specularColorMap&&(i.specularColorMap=s(e.specularColorMap)),void 0!==e.envMap&&(i.envMap=s(e.envMap)),void 0!==e.envMapRotation&&i.envMapRotation.fromArray(e.envMapRotation),void 0!==e.envMapIntensity&&(i.envMapIntensity=e.envMapIntensity),void 0!==e.reflectivity&&(i.reflectivity=e.reflectivity),void 0!==e.refractionRatio&&(i.refractionRatio=e.refractionRatio),void 0!==e.lightMap&&(i.lightMap=s(e.lightMap)),void 0!==e.lightMapIntensity&&(i.lightMapIntensity=e.lightMapIntensity),void 0!==e.aoMap&&(i.aoMap=s(e.aoMap)),void 0!==e.aoMapIntensity&&(i.aoMapIntensity=e.aoMapIntensity),void 0!==e.gradientMap&&(i.gradientMap=s(e.gradientMap)),void 0!==e.clearcoatMap&&(i.clearcoatMap=s(e.clearcoatMap)),void 0!==e.clearcoatRoughnessMap&&(i.clearcoatRoughnessMap=s(e.clearcoatRoughnessMap)),void 0!==e.clearcoatNormalMap&&(i.clearcoatNormalMap=s(e.clearcoatNormalMap)),void 0!==e.clearcoatNormalScale&&(i.clearcoatNormalScale=(new Qs).fromArray(e.clearcoatNormalScale)),void 0!==e.iridescenceMap&&(i.iridescenceMap=s(e.iridescenceMap)),void 0!==e.iridescenceThicknessMap&&(i.iridescenceThicknessMap=s(e.iridescenceThicknessMap)),void 0!==e.transmissionMap&&(i.transmissionMap=s(e.transmissionMap)),void 0!==e.thicknessMap&&(i.thicknessMap=s(e.thicknessMap)),void 0!==e.anisotropyMap&&(i.anisotropyMap=s(e.anisotropyMap)),void 0!==e.sheenColorMap&&(i.sheenColorMap=s(e.sheenColorMap)),void 0!==e.sheenRoughnessMap&&(i.sheenRoughnessMap=s(e.sheenRoughnessMap)),i}setTextures(e){return this.textures=e,this}static createMaterialFromType(e){return new{ShadowMaterial:Sl,SpriteMaterial:lo,RawShaderMaterial:Ml,ShaderMaterial:$n,PointsMaterial:Va,MeshPhysicalMaterial:Nl,MeshStandardMaterial:Al,MeshPhongMaterial:Rl,MeshToonMaterial:Cl,MeshNormalMaterial:El,MeshLambertMaterial:Bl,MeshDepthMaterial:Il,MeshDistanceMaterial:Pl,MeshBasicMaterial:Qr,MeshMatcapMaterial:Fl,LineDashedMaterial:zl,LineBasicMaterial:Ma,Material:Kr}[e]}}class qT{static decodeText(e){if(console.warn("THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead."),"undefined"!=typeof TextDecoder)return(new TextDecoder).decode(e);let t="";for(let s=0,i=e.length;s0){const s=new pT(t);r=new TT(s),r.setCrossOrigin(this.crossOrigin);for(let t=0,s=e.length;t0){i=new TT(this.manager),i.setCrossOrigin(this.crossOrigin);for(let t=0,i=e.length;t{const t=new Pi;t.min.fromArray(e.boxMin),t.max.fromArray(e.boxMax);const s=new Zi;return s.radius=e.sphereRadius,s.center.fromArray(e.sphereCenter),{boxInitialized:e.boxInitialized,box:t,sphereInitialized:e.sphereInitialized,sphere:s}})),n._maxInstanceCount=e.maxInstanceCount,n._maxVertexCount=e.maxVertexCount,n._maxIndexCount=e.maxIndexCount,n._geometryInitialized=e.geometryInitialized,n._geometryCount=e.geometryCount,n._matricesTexture=u(e.matricesTexture.uuid),void 0!==e.colorsTexture&&(n._colorsTexture=u(e.colorsTexture.uuid));break;case"LOD":n=new Ro;break;case"Line":n=new Pa(h(e.geometry),l(e.material));break;case"LineLoop":n=new Oa(h(e.geometry),l(e.material));break;case"LineSegments":n=new La(h(e.geometry),l(e.material));break;case"PointCloud":case"Points":n=new Ha(h(e.geometry),l(e.material));break;case"Sprite":n=new So(l(e.material));break;case"Group":n=new qa;break;case"Bone":n=new Vo;break;default:n=new Pr}if(n.uuid=e.uuid,void 0!==e.name&&(n.name=e.name),void 0!==e.matrix?(n.matrix.fromArray(e.matrix),void 0!==e.matrixAutoUpdate&&(n.matrixAutoUpdate=e.matrixAutoUpdate),n.matrixAutoUpdate&&n.matrix.decompose(n.position,n.quaternion,n.scale)):(void 0!==e.position&&n.position.fromArray(e.position),void 0!==e.rotation&&n.rotation.fromArray(e.rotation),void 0!==e.quaternion&&n.quaternion.fromArray(e.quaternion),void 0!==e.scale&&n.scale.fromArray(e.scale)),void 0!==e.up&&n.up.fromArray(e.up),void 0!==e.castShadow&&(n.castShadow=e.castShadow),void 0!==e.receiveShadow&&(n.receiveShadow=e.receiveShadow),e.shadow&&(void 0!==e.shadow.intensity&&(n.shadow.intensity=e.shadow.intensity),void 0!==e.shadow.bias&&(n.shadow.bias=e.shadow.bias),void 0!==e.shadow.normalBias&&(n.shadow.normalBias=e.shadow.normalBias),void 0!==e.shadow.radius&&(n.shadow.radius=e.shadow.radius),void 0!==e.shadow.mapSize&&n.shadow.mapSize.fromArray(e.shadow.mapSize),void 0!==e.shadow.camera&&(n.shadow.camera=this.parseObject(e.shadow.camera))),void 0!==e.visible&&(n.visible=e.visible),void 0!==e.frustumCulled&&(n.frustumCulled=e.frustumCulled),void 0!==e.renderOrder&&(n.renderOrder=e.renderOrder),void 0!==e.userData&&(n.userData=e.userData),void 0!==e.layers&&(n.layers.mask=e.layers),void 0!==e.children){const o=e.children;for(let e=0;e{t&&t(s),r.manager.itemEnd(e)})).catch((e=>{i&&i(e)})):(setTimeout((function(){t&&t(n),r.manager.itemEnd(e)}),0),n);const o={};o.credentials="anonymous"===this.crossOrigin?"same-origin":"include",o.headers=this.requestHeader;const a=fetch(e,o).then((function(e){return e.blob()})).then((function(e){return createImageBitmap(e,Object.assign(r.options,{colorSpaceConversion:"none"}))})).then((function(s){return dT.add(e,s),t&&t(s),r.manager.itemEnd(e),s})).catch((function(t){i&&i(t),dT.remove(e),r.manager.itemError(e),r.manager.itemEnd(e)}));dT.add(e,a),r.manager.itemStart(e)}}let e_;class t_{static getContext(){return void 0===e_&&(e_=new(window.AudioContext||window.webkitAudioContext)),e_}static setContext(e){e_=e}}class s_ extends gT{constructor(e){super(e)}load(e,t,s,i){const r=this,n=new xT(this.manager);function o(t){i?i(t):console.error(t),r.manager.itemError(e)}n.setResponseType("arraybuffer"),n.setPath(this.path),n.setRequestHeader(this.requestHeader),n.setWithCredentials(this.withCredentials),n.load(e,(function(e){try{const s=e.slice(0);t_.getContext().decodeAudioData(s,(function(e){t(e)})).catch(o)}catch(e){o(e)}}),s,i)}}const i_=new or,r_=new or,n_=new or;class o_{constructor(){this.type="StereoCamera",this.aspect=1,this.eyeSep=.064,this.cameraL=new Kn,this.cameraL.layers.enable(1),this.cameraL.matrixAutoUpdate=!1,this.cameraR=new Kn,this.cameraR.layers.enable(2),this.cameraR.matrixAutoUpdate=!1,this._cache={focus:null,fov:null,aspect:null,near:null,far:null,zoom:null,eyeSep:null}}update(e){const t=this._cache;if(t.focus!==e.focus||t.fov!==e.fov||t.aspect!==e.aspect*this.aspect||t.near!==e.near||t.far!==e.far||t.zoom!==e.zoom||t.eyeSep!==this.eyeSep){t.focus=e.focus,t.fov=e.fov,t.aspect=e.aspect*this.aspect,t.near=e.near,t.far=e.far,t.zoom=e.zoom,t.eyeSep=this.eyeSep,n_.copy(e.projectionMatrix);const s=t.eyeSep/2,i=s*t.near/t.focus,r=t.near*Math.tan(Hs*t.fov*.5)/t.zoom;let n,o;r_.elements[12]=-s,i_.elements[12]=s,n=-r*t.aspect+i,o=r*t.aspect+i,n_.elements[0]=2*t.near/(o-n),n_.elements[8]=(o+n)/(o-n),this.cameraL.projectionMatrix.copy(n_),n=-r*t.aspect-i,o=r*t.aspect-i,n_.elements[0]=2*t.near/(o-n),n_.elements[8]=(o+n)/(o-n),this.cameraR.projectionMatrix.copy(n_)}this.cameraL.matrixWorld.copy(e.matrixWorld).multiply(r_),this.cameraR.matrixWorld.copy(e.matrixWorld).multiply(i_)}}class a_ extends Kn{constructor(e=[]){super(),this.isArrayCamera=!0,this.cameras=e}}class h_{constructor(e=!0){this.autoStart=e,this.startTime=0,this.oldTime=0,this.elapsedTime=0,this.running=!1}start(){this.startTime=l_(),this.oldTime=this.startTime,this.elapsedTime=0,this.running=!0}stop(){this.getElapsedTime(),this.running=!1,this.autoStart=!1}getElapsedTime(){return this.getDelta(),this.elapsedTime}getDelta(){let e=0;if(this.autoStart&&!this.running)return this.start(),0;if(this.running){const t=l_();e=(t-this.oldTime)/1e3,this.oldTime=t,this.elapsedTime+=e}return e}}function l_(){return("undefined"==typeof performance?Date:performance).now()}const u_=new Ei,c_=new Ci,d_=new Ei,p_=new Ei;class m_ extends Pr{constructor(){super(),this.type="AudioListener",this.context=t_.getContext(),this.gain=this.context.createGain(),this.gain.connect(this.context.destination),this.filter=null,this.timeDelta=0,this._clock=new h_}getInput(){return this.gain}removeFilter(){return null!==this.filter&&(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination),this.gain.connect(this.context.destination),this.filter=null),this}getFilter(){return this.filter}setFilter(e){return null!==this.filter?(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination)):this.gain.disconnect(this.context.destination),this.filter=e,this.gain.connect(this.filter),this.filter.connect(this.context.destination),this}getMasterVolume(){return this.gain.gain.value}setMasterVolume(e){return this.gain.gain.setTargetAtTime(e,this.context.currentTime,.01),this}updateMatrixWorld(e){super.updateMatrixWorld(e);const t=this.context.listener,s=this.up;if(this.timeDelta=this._clock.getDelta(),this.matrixWorld.decompose(u_,c_,d_),p_.set(0,0,-1).applyQuaternion(c_),t.positionX){const e=this.context.currentTime+this.timeDelta;t.positionX.linearRampToValueAtTime(u_.x,e),t.positionY.linearRampToValueAtTime(u_.y,e),t.positionZ.linearRampToValueAtTime(u_.z,e),t.forwardX.linearRampToValueAtTime(p_.x,e),t.forwardY.linearRampToValueAtTime(p_.y,e),t.forwardZ.linearRampToValueAtTime(p_.z,e),t.upX.linearRampToValueAtTime(s.x,e),t.upY.linearRampToValueAtTime(s.y,e),t.upZ.linearRampToValueAtTime(s.z,e)}else t.setPosition(u_.x,u_.y,u_.z),t.setOrientation(p_.x,p_.y,p_.z,s.x,s.y,s.z)}}class g_ extends Pr{constructor(e){super(),this.type="Audio",this.listener=e,this.context=e.context,this.gain=this.context.createGain(),this.gain.connect(e.getInput()),this.autoplay=!1,this.buffer=null,this.detune=0,this.loop=!1,this.loopStart=0,this.loopEnd=0,this.offset=0,this.duration=void 0,this.playbackRate=1,this.isPlaying=!1,this.hasPlaybackControl=!0,this.source=null,this.sourceType="empty",this._startedAt=0,this._progress=0,this._connected=!1,this.filters=[]}getOutput(){return this.gain}setNodeSource(e){return this.hasPlaybackControl=!1,this.sourceType="audioNode",this.source=e,this.connect(),this}setMediaElementSource(e){return this.hasPlaybackControl=!1,this.sourceType="mediaNode",this.source=this.context.createMediaElementSource(e),this.connect(),this}setMediaStreamSource(e){return this.hasPlaybackControl=!1,this.sourceType="mediaStreamNode",this.source=this.context.createMediaStreamSource(e),this.connect(),this}setBuffer(e){return this.buffer=e,this.sourceType="buffer",this.autoplay&&this.play(),this}play(e=0){if(!0===this.isPlaying)return void console.warn("THREE.Audio: Audio is already playing.");if(!1===this.hasPlaybackControl)return void console.warn("THREE.Audio: this Audio has no playback control.");this._startedAt=this.context.currentTime+e;const t=this.context.createBufferSource();return t.buffer=this.buffer,t.loop=this.loop,t.loopStart=this.loopStart,t.loopEnd=this.loopEnd,t.onended=this.onEnded.bind(this),t.start(this._startedAt,this._progress+this.offset,this.duration),this.isPlaying=!0,this.source=t,this.setDetune(this.detune),this.setPlaybackRate(this.playbackRate),this.connect()}pause(){if(!1!==this.hasPlaybackControl)return!0===this.isPlaying&&(this._progress+=Math.max(this.context.currentTime-this._startedAt,0)*this.playbackRate,!0===this.loop&&(this._progress=this._progress%(this.duration||this.buffer.duration)),this.source.stop(),this.source.onended=null,this.isPlaying=!1),this;console.warn("THREE.Audio: this Audio has no playback control.")}stop(){if(!1!==this.hasPlaybackControl)return this._progress=0,null!==this.source&&(this.source.stop(),this.source.onended=null),this.isPlaying=!1,this;console.warn("THREE.Audio: this Audio has no playback control.")}connect(){if(this.filters.length>0){this.source.connect(this.filters[0]);for(let e=1,t=this.filters.length;e0){this.source.disconnect(this.filters[0]);for(let e=1,t=this.filters.length;e0&&this._mixBufferRegionAdditive(s,i,this._addIndex*t,1,t);for(let e=t,r=t+t;e!==r;++e)if(s[e]!==s[e+t]){o.setValue(s,i);break}}saveOriginalState(){const e=this.binding,t=this.buffer,s=this.valueSize,i=s*this._origIndex;e.getValue(t,i);for(let e=s,r=i;e!==r;++e)t[e]=t[i+e%s];this._setIdentity(),this.cumulativeWeight=0,this.cumulativeWeightAdditive=0}restoreOriginalState(){const e=3*this.valueSize;this.binding.setValue(this.buffer,e)}_setAdditiveIdentityNumeric(){const e=this._addIndex*this.valueSize,t=e+this.valueSize;for(let s=e;s=.5)for(let i=0;i!==r;++i)e[t+i]=e[s+i]}_slerp(e,t,s,i){Ci.slerpFlat(e,t,e,t,e,s,i)}_slerpAdditive(e,t,s,i,r){const n=this._workIndex*r;Ci.multiplyQuaternionsFlat(e,n,e,t,e,s),Ci.slerpFlat(e,t,e,t,e,n,i)}_lerp(e,t,s,i,r){const n=1-i;for(let o=0;o!==r;++o){const r=t+o;e[r]=e[r]*n+e[s+o]*i}}_lerpAdditive(e,t,s,i,r){for(let n=0;n!==r;++n){const r=t+n;e[r]=e[r]+e[s+n]*i}}}const w_="\\[\\]\\.:\\/",S_=new RegExp("["+w_+"]","g"),M_="[^"+w_+"]",A_="[^"+w_.replace("\\.","")+"]",N_=new RegExp("^"+/((?:WC+[\/:])*)/.source.replace("WC",M_)+/(WCOD+)?/.source.replace("WCOD",A_)+/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",M_)+/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",M_)+"$"),R_=["material","materials","bones","map"];class C_{constructor(e,t,s){this.path=t,this.parsedPath=s||C_.parseTrackName(t),this.node=C_.findNode(e,this.parsedPath.nodeName),this.rootNode=e,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(e,t,s){return e&&e.isAnimationObjectGroup?new C_.Composite(e,t,s):new C_(e,t,s)}static sanitizeNodeName(e){return e.replace(/\s/g,"_").replace(S_,"")}static parseTrackName(e){const t=N_.exec(e);if(null===t)throw new Error("PropertyBinding: Cannot parse trackName: "+e);const s={nodeName:t[2],objectName:t[3],objectIndex:t[4],propertyName:t[5],propertyIndex:t[6]},i=s.nodeName&&s.nodeName.lastIndexOf(".");if(void 0!==i&&-1!==i){const e=s.nodeName.substring(i+1);-1!==R_.indexOf(e)&&(s.nodeName=s.nodeName.substring(0,i),s.objectName=e)}if(null===s.propertyName||0===s.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+e);return s}static findNode(e,t){if(void 0===t||""===t||"."===t||-1===t||t===e.name||t===e.uuid)return e;if(e.skeleton){const s=e.skeleton.getBoneByName(t);if(void 0!==s)return s}if(e.children){const s=function(e){for(let i=0;i=r){const n=r++,l=e[n];t[l.uuid]=h,e[h]=l,t[a]=n,e[n]=o;for(let e=0,t=i;e!==t;++e){const t=s[e],i=t[n],r=t[h];t[h]=i,t[n]=r}}}this.nCachedObjects_=r}uncache(){const e=this._objects,t=this._indicesByUUID,s=this._bindings,i=s.length;let r=this.nCachedObjects_,n=e.length;for(let o=0,a=arguments.length;o!==a;++o){const a=arguments[o].uuid,h=t[a];if(void 0!==h)if(delete t[a],h0&&(t[o.uuid]=h),e[h]=o,e.pop();for(let e=0,t=i;e!==t;++e){const t=s[e];t[h]=t[r],t.pop()}}}this.nCachedObjects_=r}subscribe_(e,t){const s=this._bindingsIndicesByPath;let i=s[e];const r=this._bindings;if(void 0!==i)return r[i];const n=this._paths,o=this._parsedPaths,a=this._objects,h=a.length,l=this.nCachedObjects_,u=new Array(h);i=r.length,s[e]=i,n.push(e),o.push(t),r.push(u);for(let s=l,i=a.length;s!==i;++s){const i=a[s];u[s]=new C_(i,e,t)}return u}unsubscribe_(e){const t=this._bindingsIndicesByPath,s=t[e];if(void 0!==s){const i=this._paths,r=this._parsedPaths,n=this._bindings,o=n.length-1,a=n[o];t[e[o]]=s,n[s]=a,n.pop(),r[s]=r[o],r.pop(),i[s]=i[o],i.pop()}}}class B_{constructor(e,t,s=null,i=t.blendMode){this._mixer=e,this._clip=t,this._localRoot=s,this.blendMode=i;const r=t.tracks,n=r.length,o=new Array(n),a={endingStart:zt,endingEnd:zt};for(let e=0;e!==n;++e){const t=r[e].createInterpolant(null);o[e]=t,t.settings=a}this._interpolantSettings=a,this._interpolants=o,this._propertyBindings=new Array(n),this._cacheIndex=null,this._byClipCacheIndex=null,this._timeScaleInterpolant=null,this._weightInterpolant=null,this.loop=2201,this._loopCount=-1,this._startTime=null,this.time=0,this.timeScale=1,this._effectiveTimeScale=1,this.weight=1,this._effectiveWeight=1,this.repetitions=1/0,this.paused=!1,this.enabled=!0,this.clampWhenFinished=!1,this.zeroSlopeAtStart=!0,this.zeroSlopeAtEnd=!0}play(){return this._mixer._activateAction(this),this}stop(){return this._mixer._deactivateAction(this),this.reset()}reset(){return this.paused=!1,this.enabled=!0,this.time=0,this._loopCount=-1,this._startTime=null,this.stopFading().stopWarping()}isRunning(){return this.enabled&&!this.paused&&0!==this.timeScale&&null===this._startTime&&this._mixer._isActiveAction(this)}isScheduled(){return this._mixer._isActiveAction(this)}startAt(e){return this._startTime=e,this}setLoop(e,t){return this.loop=e,this.repetitions=t,this}setEffectiveWeight(e){return this.weight=e,this._effectiveWeight=this.enabled?e:0,this.stopFading()}getEffectiveWeight(){return this._effectiveWeight}fadeIn(e){return this._scheduleFading(e,0,1)}fadeOut(e){return this._scheduleFading(e,1,0)}crossFadeFrom(e,t,s){if(e.fadeOut(t),this.fadeIn(t),s){const s=this._clip.duration,i=e._clip.duration,r=i/s,n=s/i;e.warp(1,r,t),this.warp(n,1,t)}return this}crossFadeTo(e,t,s){return e.crossFadeFrom(this,t,s)}stopFading(){const e=this._weightInterpolant;return null!==e&&(this._weightInterpolant=null,this._mixer._takeBackControlInterpolant(e)),this}setEffectiveTimeScale(e){return this.timeScale=e,this._effectiveTimeScale=this.paused?0:e,this.stopWarping()}getEffectiveTimeScale(){return this._effectiveTimeScale}setDuration(e){return this.timeScale=this._clip.duration/e,this.stopWarping()}syncWith(e){return this.time=e.time,this.timeScale=e.timeScale,this.stopWarping()}halt(e){return this.warp(this._effectiveTimeScale,0,e)}warp(e,t,s){const i=this._mixer,r=i.time,n=this.timeScale;let o=this._timeScaleInterpolant;null===o&&(o=i._lendControlInterpolant(),this._timeScaleInterpolant=o);const a=o.parameterPositions,h=o.sampleValues;return a[0]=r,a[1]=r+s,h[0]=e/n,h[1]=t/n,this}stopWarping(){const e=this._timeScaleInterpolant;return null!==e&&(this._timeScaleInterpolant=null,this._mixer._takeBackControlInterpolant(e)),this}getMixer(){return this._mixer}getClip(){return this._clip}getRoot(){return this._localRoot||this._mixer._root}_update(e,t,s,i){if(!this.enabled)return void this._updateWeight(e);const r=this._startTime;if(null!==r){const i=(e-r)*s;i<0||0===s?t=0:(this._startTime=null,t=s*i)}t*=this._updateTimeScale(e);const n=this._updateTime(t),o=this._updateWeight(e);if(o>0){const e=this._interpolants,t=this._propertyBindings;if(this.blendMode===Vt)for(let s=0,i=e.length;s!==i;++s)e[s].evaluate(n),t[s].accumulateAdditive(o);else for(let s=0,r=e.length;s!==r;++s)e[s].evaluate(n),t[s].accumulate(i,o)}}_updateWeight(e){let t=0;if(this.enabled){t=this.weight;const s=this._weightInterpolant;if(null!==s){const i=s.evaluate(e)[0];t*=i,e>s.parameterPositions[1]&&(this.stopFading(),0===i&&(this.enabled=!1))}}return this._effectiveWeight=t,t}_updateTimeScale(e){let t=0;if(!this.paused){t=this.timeScale;const s=this._timeScaleInterpolant;if(null!==s){t*=s.evaluate(e)[0],e>s.parameterPositions[1]&&(this.stopWarping(),0===t?this.paused=!0:this.timeScale=t)}}return this._effectiveTimeScale=t,t}_updateTime(e){const t=this._clip.duration,s=this.loop;let i=this.time+e,r=this._loopCount;const n=2202===s;if(0===e)return-1===r?i:n&&1==(1&r)?t-i:i;if(2200===s){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));e:{if(i>=t)i=t;else{if(!(i<0)){this.time=i;break e}i=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:e<0?-1:1})}}else{if(-1===r&&(e>=0?(r=0,this._setEndings(!0,0===this.repetitions,n)):this._setEndings(0===this.repetitions,!0,n)),i>=t||i<0){const s=Math.floor(i/t);i-=t*s,r+=Math.abs(s);const o=this.repetitions-r;if(o<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,i=e>0?t:0,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:e>0?1:-1});else{if(1===o){const t=e<0;this._setEndings(t,!t,n)}else this._setEndings(!1,!1,n);this._loopCount=r,this.time=i,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:s})}}else this.time=i;if(n&&1==(1&r))return t-i}return i}_setEndings(e,t,s){const i=this._interpolantSettings;s?(i.endingStart=Ut,i.endingEnd=Ut):(i.endingStart=e?this.zeroSlopeAtStart?Ut:zt:Lt,i.endingEnd=t?this.zeroSlopeAtEnd?Ut:zt:Lt)}_scheduleFading(e,t,s){const i=this._mixer,r=i.time;let n=this._weightInterpolant;null===n&&(n=i._lendControlInterpolant(),this._weightInterpolant=n);const o=n.parameterPositions,a=n.sampleValues;return o[0]=r,a[0]=t,o[1]=r+e,a[1]=s,this}}const I_=new Float32Array(1);class P_ extends ks{constructor(e){super(),this._root=e,this._initMemoryManager(),this._accuIndex=0,this.time=0,this.timeScale=1}_bindAction(e,t){const s=e._localRoot||this._root,i=e._clip.tracks,r=i.length,n=e._propertyBindings,o=e._interpolants,a=s.uuid,h=this._bindingsByRootAndName;let l=h[a];void 0===l&&(l={},h[a]=l);for(let e=0;e!==r;++e){const r=i[e],h=r.name;let u=l[h];if(void 0!==u)++u.referenceCount,n[e]=u;else{if(u=n[e],void 0!==u){null===u._cacheIndex&&(++u.referenceCount,this._addInactiveBinding(u,a,h));continue}const i=t&&t._propertyBindings[e].binding.parsedPath;u=new __(C_.create(s,h,i),r.ValueTypeName,r.getValueSize()),++u.referenceCount,this._addInactiveBinding(u,a,h),n[e]=u}o[e].resultBuffer=u.buffer}}_activateAction(e){if(!this._isActiveAction(e)){if(null===e._cacheIndex){const t=(e._localRoot||this._root).uuid,s=e._clip.uuid,i=this._actionsByClip[s];this._bindAction(e,i&&i.knownActions[0]),this._addInactiveAction(e,s,t)}const t=e._propertyBindings;for(let e=0,s=t.length;e!==s;++e){const s=t[e];0==s.useCount++&&(this._lendBinding(s),s.saveOriginalState())}this._lendAction(e)}}_deactivateAction(e){if(this._isActiveAction(e)){const t=e._propertyBindings;for(let e=0,s=t.length;e!==s;++e){const s=t[e];0==--s.useCount&&(s.restoreOriginalState(),this._takeBackBinding(s))}this._takeBackAction(e)}}_initMemoryManager(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;const e=this;this.stats={actions:{get total(){return e._actions.length},get inUse(){return e._nActiveActions}},bindings:{get total(){return e._bindings.length},get inUse(){return e._nActiveBindings}},controlInterpolants:{get total(){return e._controlInterpolants.length},get inUse(){return e._nActiveControlInterpolants}}}}_isActiveAction(e){const t=e._cacheIndex;return null!==t&&t=0;--t)e[t].stop();return this}update(e){e*=this.timeScale;const t=this._actions,s=this._nActiveActions,i=this.time+=e,r=Math.sign(e),n=this._accuIndex^=1;for(let o=0;o!==s;++o){t[o]._update(i,e,r,n)}const o=this._bindings,a=this._nActiveBindings;for(let e=0;e!==a;++e)o[e].apply(n);return this}setTime(e){this.time=0;for(let e=0;e=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y}containsBox(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y}getParameter(e,t){return t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y))}intersectsBox(e){return e.max.x>=this.min.x&&e.min.x<=this.max.x&&e.max.y>=this.min.y&&e.min.y<=this.max.y}clampPoint(e,t){return t.copy(e).clamp(this.min,this.max)}distanceToPoint(e){return this.clampPoint(e,j_).distanceTo(e)}intersect(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this}union(e){return this.min.min(e.min),this.max.max(e.max),this}translate(e){return this.min.add(e),this.max.add(e),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}const $_=new Ei,X_=new Ei;class Y_{constructor(e=new Ei,t=new Ei){this.start=e,this.end=t}set(e,t){return this.start.copy(e),this.end.copy(t),this}copy(e){return this.start.copy(e.start),this.end.copy(e.end),this}getCenter(e){return e.addVectors(this.start,this.end).multiplyScalar(.5)}delta(e){return e.subVectors(this.end,this.start)}distanceSq(){return this.start.distanceToSquared(this.end)}distance(){return this.start.distanceTo(this.end)}at(e,t){return this.delta(t).multiplyScalar(e).add(this.start)}closestPointToPointParameter(e,t){$_.subVectors(e,this.start),X_.subVectors(this.end,this.start);const s=X_.dot(X_);let i=X_.dot($_)/s;return t&&(i=$s(i,0,1)),i}closestPointToPoint(e,t,s){const i=this.closestPointToPointParameter(e,t);return this.delta(s).multiplyScalar(i).add(this.start)}applyMatrix4(e){return this.start.applyMatrix4(e),this.end.applyMatrix4(e),this}equals(e){return e.start.equals(this.start)&&e.end.equals(this.end)}clone(){return(new this.constructor).copy(this)}}const J_=new Ei;class Z_ extends Pr{constructor(e,t){super(),this.light=e,this.matrixAutoUpdate=!1,this.color=t,this.type="SpotLightHelper";const s=new Mn,i=[0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,-1,0,1,0,0,0,0,1,1,0,0,0,0,-1,1];for(let e=0,t=1,s=32;e1)for(let s=0;s.99999)this.quaternion.set(0,0,0,1);else if(e.y<-.99999)this.quaternion.set(1,0,0,0);else{_w.set(e.z,0,-e.x).normalize();const t=Math.acos(e.y);this.quaternion.setFromAxisAngle(_w,t)}}setLength(e,t=.2*e,s=.2*t){this.line.scale.set(1,Math.max(1e-4,e-t),1),this.line.updateMatrix(),this.cone.scale.set(s,t,s),this.cone.position.y=e,this.cone.updateMatrix()}setColor(e){this.line.material.color.set(e),this.cone.material.color.set(e)}copy(e){return super.copy(e,!1),this.line.copy(e.line),this.cone.copy(e.cone),this}dispose(){this.line.geometry.dispose(),this.line.material.dispose(),this.cone.geometry.dispose(),this.cone.material.dispose()}}class Aw extends La{constructor(e=1){const t=[0,0,0,e,0,0,0,0,0,0,e,0,0,0,0,0,0,e],s=new Mn;s.setAttribute("position",new yn(t,3)),s.setAttribute("color",new yn([1,0,0,1,.6,0,0,1,0,.6,1,0,0,0,1,0,.6,1],3));super(s,new Ma({vertexColors:!0,toneMapped:!1})),this.type="AxesHelper"}setColors(e,t,s){const i=new Yr,r=this.geometry.attributes.color.array;return i.set(e),i.toArray(r,0),i.toArray(r,3),i.set(t),i.toArray(r,6),i.toArray(r,9),i.set(s),i.toArray(r,12),i.toArray(r,15),this.geometry.attributes.color.needsUpdate=!0,this}dispose(){this.geometry.dispose(),this.material.dispose()}}class Nw{constructor(){this.type="ShapePath",this.color=new Yr,this.subPaths=[],this.currentPath=null}moveTo(e,t){return this.currentPath=new Th,this.subPaths.push(this.currentPath),this.currentPath.moveTo(e,t),this}lineTo(e,t){return this.currentPath.lineTo(e,t),this}quadraticCurveTo(e,t,s,i){return this.currentPath.quadraticCurveTo(e,t,s,i),this}bezierCurveTo(e,t,s,i,r,n){return this.currentPath.bezierCurveTo(e,t,s,i,r,n),this}splineThru(e){return this.currentPath.splineThru(e),this}toShapes(e){function t(e,t){const s=t.length;let i=!1;for(let r=s-1,n=0;nNumber.EPSILON){if(h<0&&(s=t[n],a=-a,o=t[r],h=-h),e.yo.y)continue;if(e.y===s.y){if(e.x===s.x)return!0}else{const t=h*(e.x-s.x)-a*(e.y-s.y);if(0===t)return!0;if(t<0)continue;i=!i}}else{if(e.y!==s.y)continue;if(o.x<=e.x&&e.x<=s.x||s.x<=e.x&&e.x<=o.x)return!0}}return i}const s=ol.isClockWise,i=this.subPaths;if(0===i.length)return[];let r,n,o;const a=[];if(1===i.length)return n=i[0],o=new Fh,o.curves=n.curves,a.push(o),a;let h=!s(i[0].getPoints());h=e?!h:h;const l=[],u=[];let c,d,p=[],m=0;u[m]=void 0,p[m]=[];for(let t=0,o=i.length;t1){let e=!1,s=0;for(let e=0,t=u.length;e0&&!1===e&&(p=l)}for(let e=0,t=u.length;e{this.requestId=self.requestAnimationFrame(e),!0===this.info.autoReset&&this.info.reset(),this.nodes.nodeFrame.update(),this.info.frame=this.nodes.nodeFrame.frameId,null!==this.animationLoop&&this.animationLoop(t,s)};e()}dispose(){self.cancelAnimationFrame(this.requestId),this.requestId=null}setAnimationLoop(e){this.animationLoop=e}}class Bw{constructor(){this.weakMap=new WeakMap}get(e){let t=this.weakMap;for(let s=0;s{this.dispose()},this.material.addEventListener("dispose",this.onMaterialDispose)}updateClipping(e){const t=this.material;let s=this.clippingContext;Array.isArray(t.clippingPlanes)?(s!==e&&s||(s=new Pw,this.clippingContext=s),s.update(e,t)):this.clippingContext!==e&&(this.clippingContext=e)}get clippingNeedsUpdate(){return this.clippingContext.version!==this.clippingContextVersion&&(this.clippingContextVersion=this.clippingContext.version,!0)}getNodeBuilderState(){return this._nodeBuilderState||(this._nodeBuilderState=this._nodes.getForRender(this))}getBindings(){return this._bindings||(this._bindings=this.getNodeBuilderState().createBindings())}getIndex(){return this._geometries.getIndex(this)}getChainArray(){return[this.object,this.material,this.context,this.lightsNode]}getAttributes(){if(null!==this.attributes)return this.attributes;const e=this.getNodeBuilderState().nodeAttributes,t=this.geometry,s=[],i=new Set;for(const r of e){const e=r.node&&r.node.attribute?r.node.attribute:t.getAttribute(r.name);if(void 0===e)continue;s.push(e);const n=e.isInterleavedBufferAttribute?e.data:e;i.add(n)}return this.attributes=s,this.vertexBuffers=Array.from(i.values()),s}getVertexBuffers(){return null===this.vertexBuffers&&this.getAttributes(),this.vertexBuffers}getMaterialCacheKey(){const{object:e,material:t}=this;let s=t.customProgramCacheKey();for(const e of function(e){const t=Object.keys(e);let s=Object.getPrototypeOf(e);for(;s;){const e=Object.getOwnPropertyDescriptors(s);for(const s in e)if(void 0!==e[s]){const i=e[s];i&&"function"==typeof i.get&&t.push(s)}s=Object.getPrototypeOf(s)}return t}(t)){if(/^(is[A-Z]|_)|^(visible|version|uuid|name|opacity|userData)$/.test(e))continue;const i=t[e];let r;if(null!==i){const e=typeof i;"number"===e?r=0!==i?"1":"0":"object"===e?(r="{",i.isTexture&&(r+=i.mapping),r+="}"):r=String(i)}else r=String(i);s+=r+","}return s+=this.clippingContext.cacheKey+",",e.skeleton&&(s+=e.skeleton.bones.length+","),e.morphTargetInfluences&&(s+=e.morphTargetInfluences.length+","),e.isBatchedMesh&&(s+=e._matricesTexture.uuid+",",null!==e._colorsTexture&&(s+=e._colorsTexture.uuid+",")),e.count>1&&(s+=e.count+","+e.uuid+","),s}get needsUpdate(){return this.initialNodesCacheKey!==this.getDynamicCacheKey()||this.clippingNeedsUpdate}getDynamicCacheKey(){return this.object.receiveShadow+","+this._nodes.getCacheKey(this.scene,this.lightsNode)}getCacheKey(){return this.getMaterialCacheKey()+","+this.getDynamicCacheKey()}dispose(){this.material.removeEventListener("dispose",this.onMaterialDispose),this.onDispose()}}class Uw{constructor(e,t,s,i,r,n){this.renderer=e,this.nodes=t,this.geometries=s,this.pipelines=i,this.bindings=r,this.info=n,this.chainMaps={}}get(e,t,s,i,r,n,o){const a=this.getChainMap(o),h=[e,t,n,r];let l=a.get(h);return void 0===l?(l=this.createRenderObject(this.nodes,this.geometries,this.renderer,e,t,s,i,r,n,o),a.set(h,l)):(l.updateClipping(n.clippingContext),(l.version!==t.version||l.needsUpdate)&&(l.initialCacheKey!==l.getCacheKey()?(l.dispose(),l=this.get(e,t,s,i,r,n,o)):l.version=t.version)),l}getChainMap(e="default"){return this.chainMaps[e]||(this.chainMaps[e]=new Bw)}dispose(){this.chainMaps={}}createRenderObject(e,t,s,i,r,n,o,a,h,l){const u=this.getChainMap(l),c=new zw(e,t,s,i,r,n,o,a,h);return c.onDispose=()=>{this.pipelines.delete(c),this.bindings.delete(c),this.nodes.delete(c),u.delete(c.getChainArray())},c}}class Lw{constructor(){this.data=new WeakMap}get(e){let t=this.data.get(e);return void 0===t&&(t={},this.data.set(e,t)),t}delete(e){let t;return this.data.has(e)&&(t=this.data.get(e),this.data.delete(e)),t}has(e){return this.data.has(e)}dispose(){this.data=new WeakMap}}const Ow=1,Vw=2,Dw=4,kw=16;class Gw extends Lw{constructor(e){super(),this.backend=e}delete(e){const t=super.delete(e);return void 0!==t&&this.backend.destroyAttribute(e),t}update(e,t){const s=this.get(e);if(void 0===s.version)t===Ow?this.backend.createAttribute(e):t===Vw?this.backend.createIndexAttribute(e):t===Dw&&this.backend.createStorageAttribute(e),s.version=this._getBufferAttribute(e).version;else{const t=this._getBufferAttribute(e);(s.version=0;--t)if(e[t]>=65535)return!0;return!1}(t)?gn:pn)(t,1);return r.version=Ww(e),r}class jw extends Lw{constructor(e,t){super(),this.attributes=e,this.info=t,this.wireframes=new WeakMap,this.attributeCall=new WeakMap}has(e){const t=e.geometry;return super.has(t)&&!0===this.get(t).initialized}updateForRender(e){!1===this.has(e)&&this.initGeometry(e),this.updateAttributes(e)}initGeometry(e){const t=e.geometry;this.get(t).initialized=!0,this.info.memory.geometries++;const s=()=>{this.info.memory.geometries--;const i=t.index,r=e.getAttributes();null!==i&&this.attributes.delete(i);for(const e of r)this.attributes.delete(e);const n=this.wireframes.get(t);void 0!==n&&this.attributes.delete(n),t.removeEventListener("dispose",s)};t.addEventListener("dispose",s)}updateAttributes(e){const t=e.getAttributes();for(const e of t)e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute?this.updateAttribute(e,Dw):this.updateAttribute(e,Ow);const s=this.getIndex(e);null!==s&&this.updateAttribute(s,Vw)}updateAttribute(e,t){const s=this.info.render.calls;e.isInterleavedBufferAttribute?void 0===this.attributeCall.get(e)?(this.attributes.update(e,t),this.attributeCall.set(e,s)):this.attributeCall.get(e.data)!==s&&(this.attributes.update(e,t),this.attributeCall.set(e.data,s),this.attributeCall.set(e,s)):this.attributeCall.get(e)!==s&&(this.attributes.update(e,t),this.attributeCall.set(e,s))}getIndex(e){const{geometry:t,material:s}=e;let i=t.index;if(!0===s.wireframe){const e=this.wireframes;let s=e.get(t);void 0===s?(s=Hw(t),e.set(t,s)):s.version!==Ww(t)&&(this.attributes.delete(s),s=Hw(t),e.set(t,s)),i=s}return i}}class qw{constructor(){this.autoReset=!0,this.frame=0,this.calls=0,this.render={calls:0,frameCalls:0,drawCalls:0,triangles:0,points:0,lines:0,timestamp:0,previousFrameCalls:0,timestampCalls:0},this.compute={calls:0,frameCalls:0,timestamp:0,previousFrameCalls:0,timestampCalls:0},this.memory={geometries:0,textures:0}}update(e,t,s){this.render.drawCalls++,e.isMesh||e.isSprite?this.render.triangles+=s*(t/3):e.isPoints?this.render.points+=s*t:e.isLineSegments?this.render.lines+=s*(t/2):e.isLine?this.render.lines+=s*(t-1):console.error("THREE.WebGPUInfo: Unknown object type.")}updateTimestamp(e,t){0===this[e].timestampCalls&&(this[e].timestamp=0),this[e].timestamp+=t,this[e].timestampCalls++,this[e].timestampCalls>=this[e].previousFrameCalls&&(this[e].timestampCalls=0)}reset(){const e=this.render.frameCalls;this.render.previousFrameCalls=e;const t=this.compute.frameCalls;this.compute.previousFrameCalls=t,this.render.drawCalls=0,this.render.frameCalls=0,this.compute.frameCalls=0,this.render.triangles=0,this.render.points=0,this.render.lines=0}dispose(){this.reset(),this.calls=0,this.render.calls=0,this.compute.calls=0,this.render.timestamp=0,this.compute.timestamp=0,this.memory.geometries=0,this.memory.textures=0}}class $w{constructor(e){this.cacheKey=e,this.usedTimes=0}}class Xw extends $w{constructor(e,t,s){super(e),this.vertexProgram=t,this.fragmentProgram=s}}class Yw extends $w{constructor(e,t){super(e),this.computeProgram=t,this.isComputePipeline=!0}}let Jw=0;class Zw{constructor(e,t,s=null,i=null){this.id=Jw++,this.code=e,this.stage=t,this.transforms=s,this.attributes=i,this.usedTimes=0}}class Kw extends Lw{constructor(e,t){super(),this.backend=e,this.nodes=t,this.bindings=null,this.caches=new Map,this.programs={vertex:new Map,fragment:new Map,compute:new Map}}getForCompute(e,t){const{backend:s}=this,i=this.get(e);if(this._needsComputeUpdate(e)){const r=i.pipeline;r&&(r.usedTimes--,r.computeProgram.usedTimes--);const n=this.nodes.getForCompute(e);let o=this.programs.compute.get(n.computeShader);void 0===o&&(r&&0===r.computeProgram.usedTimes&&this._releaseProgram(r.computeProgram),o=new Zw(n.computeShader,"compute",n.transforms,n.nodeAttributes),this.programs.compute.set(n.computeShader,o),s.createProgram(o));const a=this._getComputeCacheKey(e,o);let h=this.caches.get(a);void 0===h&&(r&&0===r.usedTimes&&this._releasePipeline(r),h=this._getComputePipeline(e,o,a,t)),h.usedTimes++,o.usedTimes++,i.version=e.version,i.pipeline=h}return i.pipeline}getForRender(e,t=null){const{backend:s}=this,i=this.get(e);if(this._needsRenderUpdate(e)){const r=i.pipeline;r&&(r.usedTimes--,r.vertexProgram.usedTimes--,r.fragmentProgram.usedTimes--);const n=e.getNodeBuilderState();let o=this.programs.vertex.get(n.vertexShader);void 0===o&&(r&&0===r.vertexProgram.usedTimes&&this._releaseProgram(r.vertexProgram),o=new Zw(n.vertexShader,"vertex"),this.programs.vertex.set(n.vertexShader,o),s.createProgram(o));let a=this.programs.fragment.get(n.fragmentShader);void 0===a&&(r&&0===r.fragmentProgram.usedTimes&&this._releaseProgram(r.fragmentProgram),a=new Zw(n.fragmentShader,"fragment"),this.programs.fragment.set(n.fragmentShader,a),s.createProgram(a));const h=this._getRenderCacheKey(e,o,a);let l=this.caches.get(h);void 0===l?(r&&0===r.usedTimes&&this._releasePipeline(r),l=this._getRenderPipeline(e,o,a,h,t)):e.pipeline=l,l.usedTimes++,o.usedTimes++,a.usedTimes++,i.pipeline=l}return i.pipeline}delete(e){const t=this.get(e).pipeline;return t&&(t.usedTimes--,0===t.usedTimes&&this._releasePipeline(t),t.isComputePipeline?(t.computeProgram.usedTimes--,0===t.computeProgram.usedTimes&&this._releaseProgram(t.computeProgram)):(t.fragmentProgram.usedTimes--,t.vertexProgram.usedTimes--,0===t.vertexProgram.usedTimes&&this._releaseProgram(t.vertexProgram),0===t.fragmentProgram.usedTimes&&this._releaseProgram(t.fragmentProgram))),super.delete(e)}dispose(){super.dispose(),this.caches=new Map,this.programs={vertex:new Map,fragment:new Map,compute:new Map}}updateForRender(e){this.getForRender(e)}_getComputePipeline(e,t,s,i){s=s||this._getComputeCacheKey(e,t);let r=this.caches.get(s);return void 0===r&&(r=new Yw(s,t),this.caches.set(s,r),this.backend.createComputePipeline(r,i)),r}_getRenderPipeline(e,t,s,i,r){i=i||this._getRenderCacheKey(e,t,s);let n=this.caches.get(i);return void 0===n&&(n=new Xw(i,t,s),this.caches.set(i,n),e.pipeline=n,this.backend.createRenderPipeline(e,r)),n}_getComputeCacheKey(e,t){return e.id+","+t.id}_getRenderCacheKey(e,t,s){return t.id+","+s.id+","+this.backend.getRenderCacheKey(e)}_releasePipeline(e){this.caches.delete(e.cacheKey)}_releaseProgram(e){const t=e.code,s=e.stage;this.programs[s].delete(t)}_needsComputeUpdate(e){const t=this.get(e);return void 0===t.pipeline||t.version!==e.version}_needsRenderUpdate(e){return void 0===this.get(e).pipeline||this.backend.needsRenderUpdate(e)}}class Qw extends Lw{constructor(e,t,s,i,r,n){super(),this.backend=e,this.textures=s,this.pipelines=r,this.attributes=i,this.nodes=t,this.info=n,this.pipelines.bindings=this}getForRender(e){const t=e.getBindings();for(const e of t){const s=this.get(e);void 0===s.bindGroup&&(this._init(e),this.backend.createBindings(e,t),s.bindGroup=e)}return t}getForCompute(e){const t=this.nodes.getForCompute(e).bindings;for(const e of t){const s=this.get(e);void 0===s.bindGroup&&(this._init(e),this.backend.createBindings(e,t),s.bindGroup=e)}return t}updateForCompute(e){this._updateBindings(this.getForCompute(e))}updateForRender(e){this._updateBindings(this.getForRender(e))}_updateBindings(e){for(const t of e)this._update(t,e)}_init(e){for(const t of e.bindings)if(t.isSampledTexture)this.textures.updateTexture(t.texture);else if(t.isStorageBuffer){const e=t.attribute;this.attributes.update(e,Dw)}}_update(e,t){const{backend:s}=this;let i=!1;for(const t of e.bindings){if(t.isNodeUniformsGroup){if(!this.nodes.updateGroup(t))continue}if(t.isUniformBuffer){t.update()&&s.updateBinding(t)}else if(t.isSampler)t.update();else if(t.isSampledTexture){t.needsBindingsUpdate(this.textures.get(t.texture).generation)&&(i=!0);const e=t.update(),r=t.texture;e&&this.textures.updateTexture(r);const n=s.get(r);if(!0===s.isWebGPUBackend&&void 0===n.texture&&void 0===n.externalTexture&&(console.error("Bindings._update: binding should be available:",t,e,r,t.textureNode.value,i),this.textures.updateTexture(r),i=!0),!0===r.isStorageTexture){const e=this.get(r);!0===t.store?e.needsMipmap=!0:!0===r.generateMipmaps&&this.textures.needsMipmaps(r)&&!0===e.needsMipmap&&(this.backend.generateMipmaps(r),e.needsMipmap=!1)}}}!0===i&&this.backend.updateBindings(e,t)}}class eS{constructor(e,t,s=null){this.isNodeAttribute=!0,this.name=e,this.type=t,this.node=s}}class tS{constructor(e,t,s){this.isNodeUniform=!0,this.name=e,this.type=t,this.node=s.getSelf()}get value(){return this.node.value}set value(e){this.node.value=e}get id(){return this.node.id}get groupNode(){return this.node.groupNode}}class sS{constructor(e,t){this.isNodeVar=!0,this.name=e,this.type=t}}class iS extends sS{constructor(e,t){super(e,t),this.needsInterpolation=!1,this.isNodeVarying=!0}}class rS{constructor(e,t,s=""){this.name=e,this.type=t,this.code=s,Object.defineProperty(this,"isNodeCode",{value:!0})}}let nS=0;class oS{constructor(e=null){this.id=nS++,this.nodesData=new WeakMap,this.parent=e}getData(e){let t=this.nodesData.get(e);return void 0===t&&null!==this.parent&&(t=this.parent.getData(e)),t}setData(e,t){this.nodesData.set(e,t)}}class aS extends Ec{constructor(e,t=null){super(e,t),this.isParameterNode=!0}getHash(){return this.uuid}generate(){return this.name}}aS.type=Ql("Parameter",aS);const hS=(e,t)=>Du(new aS(e,t));class lS extends Kl{constructor(e="",t=[],s=""){super("code"),this.isCodeNode=!0,this.code=e,this.language=s,this.includes=t}isGlobal(){return!0}setIncludes(e){return this.includes=e,this}getIncludes(){return this.includes}generate(e){const t=this.getIncludes(e);for(const s of t)s.build(e);const s=e.getCodeFromNode(this,this.getNodeType(e));return s.code=this.code,s.code}serialize(e){super.serialize(e),e.code=this.code,e.language=this.language}deserialize(e){super.deserialize(e),this.code=e.code,this.language=e.language}}lS.type=Ql("Code",lS);const uS=Wu(lS),cS=(e,t)=>uS(e,t,"js"),dS=(e,t)=>uS(e,t,"wgsl"),pS=(e,t)=>uS(e,t,"glsl");class mS extends lS{constructor(e="",t=[],s=""){super(e,t,s)}getNodeType(e){return this.getNodeFunction(e).type}getInputs(e){return this.getNodeFunction(e).inputs}getNodeFunction(e){const t=e.getDataFromNode(this);let s=t.nodeFunction;return void 0===s&&(s=e.parser.parseFunction(this.code),t.nodeFunction=s),s}generate(e,t){super.generate(e);const s=this.getNodeFunction(e),i=s.name,r=s.type,n=e.getCodeFromNode(this,r);""!==i&&(n.name=i);const o=e.getPropertyName(n),a=this.getNodeFunction(e).getCode(o);return n.code=a+"\n","property"===t?o:e.format(`${o}()`,r,t)}}mS.type=Ql("Function",mS);const gS=(e,t=[],s="")=>{for(let e=0;ei.call(...e);return r.functionNode=i,r},fS=(e,t)=>gS(e,t,"glsl"),yS=(e,t)=>gS(e,t,"wgsl");class xS{constructor(e,t){this.name=e,this.value=t,this.boundary=0,this.itemSize=0,this.offset=0}setValue(e){this.value=e}getValue(){return this.value}}class bS extends xS{constructor(e,t=0){super(e,t),this.isNumberUniform=!0,this.boundary=4,this.itemSize=1}}class vS extends xS{constructor(e,t=new Qs){super(e,t),this.isVector2Uniform=!0,this.boundary=8,this.itemSize=2}}class TS extends xS{constructor(e,t=new Ei){super(e,t),this.isVector3Uniform=!0,this.boundary=16,this.itemSize=3}}class _S extends xS{constructor(e,t=new _i){super(e,t),this.isVector4Uniform=!0,this.boundary=16,this.itemSize=4}}class wS extends xS{constructor(e,t=new Yr){super(e,t),this.isColorUniform=!0,this.boundary=16,this.itemSize=3}}class SS extends xS{constructor(e,t=new ei){super(e,t),this.isMatrix3Uniform=!0,this.boundary=48,this.itemSize=12}}class MS extends xS{constructor(e,t=new or){super(e,t),this.isMatrix4Uniform=!0,this.boundary=64,this.itemSize=16}}class AS extends bS{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class NS extends vS{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class RS extends TS{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class CS extends _S{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class ES extends wS{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class BS extends SS{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class IS extends MS{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class PS extends Kl{constructor(e=null){super(),this.nodes=[],this.outputNode=null,this.parent=e,this._currentCond=null,this.isStackNode=!0}getNodeType(e){return this.outputNode?this.outputNode.getNodeType(e):"void"}add(e){return this.nodes.push(e),this}If(e,t){const s=new Vu(t);return this._currentCond=qp(e,s),this.add(this._currentCond)}ElseIf(e,t){const s=new Vu(t),i=qp(e,s);return this._currentCond.elseNode=i,this._currentCond=i,this}Else(e){return this._currentCond.elseNode=new Vu(e),this}build(e,...t){const s=Xu();$u(this);for(const t of this.nodes)t.build(e,"void");return $u(s),this.outputNode?this.outputNode.build(e,...t):super.build(e,...t)}else(...e){return console.warn("TSL.StackNode: .else() has been renamed to .Else()."),this.Else(...e)}elseif(...e){return console.warn("TSL.StackNode: .elseif() has been renamed to .ElseIf()."),this.ElseIf(...e)}}PS.type=Ql("Stack",PS);const FS=Wu(PS),zS=[.125,.215,.35,.446,.526,.582],US=20,LS=new OT(-1,1,1,-1,0,1),OS=new Kn(90,1),VS=new Yr;let DS=null,kS=0,GS=0;const WS=(1+Math.sqrt(5))/2,HS=1/WS,jS=[new Ei(-WS,HS,0),new Ei(WS,HS,0),new Ei(-HS,0,WS),new Ei(HS,0,WS),new Ei(0,WS,-HS),new Ei(0,WS,HS),new Ei(-1,1,-1),new Ei(1,1,-1),new Ei(-1,1,1),new Ei(1,1,1)],qS=[3,1,5,0,4,2],$S=nv(Um(),zm("faceIndex")).normalize(),XS=oc($S.x,$S.y.negate(),$S.z);class YS{constructor(e){this._renderer=e,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._lodMeshes=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._backgroundBox=null}fromScene(e,t=0,s=.1,i=100){DS=this._renderer.getRenderTarget(),kS=this._renderer.getActiveCubeFace(),GS=this._renderer.getActiveMipmapLevel(),this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(e,s,i,r),t>0&&this._blur(r,0,0,t),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(e,t=null){return this._fromTexture(e,t)}fromCubemap(e,t=null){return this._fromTexture(e,t)}compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=QS(),this._compileMaterial(this._cubemapMaterial))}compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=eM(),this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose(),null!==this._backgroundBox&&(this._backgroundBox.geometry.dispose(),this._backgroundBox.material.dispose())}_setSize(e){this._lodMax=Math.floor(Math.log2(e)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let e=0;ee-4?h=zS[a-e+4-1]:0===a&&(h=0),i.push(h);const l=1/(o-2),u=-l,c=1+l,d=[u,u,c,u,c,c,u,u,c,c,u,c],p=6,m=6,g=3,f=2,y=1,x=new Float32Array(g*m*p),b=new Float32Array(f*m*p),v=new Float32Array(y*m*p);for(let e=0;e2?0:-1,i=[t,s,0,t+2/3,s,0,t+2/3,s+1,0,t,s,0,t+2/3,s+1,0,t,s+1,0],r=qS[e];x.set(i,g*m*r),b.set(d,f*m*r);const n=[r,r,r,r,r,r];v.set(n,y*m*r)}const T=new Mn;T.setAttribute("position",new hn(x,g)),T.setAttribute("uv",new hn(b,f)),T.setAttribute("faceIndex",new hn(v,y)),t.push(T),r.push(new Wn(T,null)),n>4&&n--}return{lodPlanes:t,sizeLods:s,sigmas:i,lodMeshes:r}}(i)),this._blurMaterial=function(e,t,s){const i=Xg(new Array(US).fill(0)),r=Cc(new Ei(0,1,0)),n=Cc(0),o=Ku(US),a=Cc(0),h=Cc(1),l=Gm(null),u=Cc(0),c=Ku(1/t),d=Ku(1/s),p=Ku(e),m={n:o,latitudinal:a,weights:i,poleAxis:r,outputDirection:XS,dTheta:n,samples:h,envMap:l,mipInt:u,CUBEUV_TEXEL_WIDTH:c,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:p},g=KS("blur");return g.uniforms=m,g.fragmentNode=lv({...m,latitudinal:a.equal(1)}),g}(i,e,t)}return i}_compileMaterial(e){const t=this._lodMeshes[0];t.material=e,this._renderer.compile(t,LS)}_sceneToCubeUV(e,t,s,i){const r=OS;r.near=t,r.far=s;const n=[-1,1,-1,-1,-1,-1],o=[1,1,1,-1,-1,-1],a=this._renderer,h=a.autoClear;a.getClearColor(VS),a.autoClear=!1;let l=this._backgroundBox;if(null===l){const e=new Qr({name:"PMREM.Background",side:d,depthWrite:!1,depthTest:!1});l=new Wn(new jn,e)}let u=!1;const c=e.background;c?c.isColor&&(l.material.color.copy(c),e.background=null,u=!0):(l.material.color.copy(VS),u=!0),a.setRenderTarget(i),a.clear(),u&&a.render(l,r);for(let t=0;t<6;t++){const s=t%3;0===s?(r.up.set(0,n[t],0),r.lookAt(o[t],0,0)):1===s?(r.up.set(0,0,n[t]),r.lookAt(0,o[t],0)):(r.up.set(0,n[t],0),r.lookAt(0,0,o[t]));const h=this._cubeSize;ZS(i,s*h,t>2?h:0,h,h),a.render(e,r)}a.autoClear=h,e.background=c}_textureToCubeUV(e,t){const s=this._renderer,i=e.mapping===he||e.mapping===le;i?null===this._cubemapMaterial&&(this._cubemapMaterial=QS(e)):null===this._equirectMaterial&&(this._equirectMaterial=eM(e));const r=i?this._cubemapMaterial:this._equirectMaterial;r.fragmentNode.value=e;const n=this._lodMeshes[0];n.material=r;const o=this._cubeSize;ZS(t,0,0,3*o,2*o),s.setRenderTarget(t),s.render(n,LS)}_applyPMREM(e){const t=this._renderer,s=t.autoClear;t.autoClear=!1;const i=this._lodPlanes.length;for(let t=1;tUS&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${m} samples when the maximum is set to 20`);const g=[];let f=0;for(let e=0;ey-4?i-y+4:0),4*(this._cubeSize-x),3*x,2*x),a.setRenderTarget(t),a.render(l,LS)}}function JS(e,t,s){const i=new wi(e,t,s);return i.texture.mapping=306,i.texture.name="PMREM.cubeUv",i.texture.isPMREMTexture=!0,i.scissorTest=!0,i}function ZS(e,t,s,i,r){e.viewport.set(t,s,i,r),e.scissor.set(t,s,i,r)}function KS(e){const t=new xx;return t.depthTest=!1,t.depthWrite=!1,t.blending=m,t.name=`PMREM_${e}`,t}function QS(e){const t=KS("cubemap");return t.fragmentNode=Wg(e,XS),t}function eM(e){const t=KS("equirect");return t.fragmentNode=Gm(e,Px(XS),0),t}let tM=0;class sM{constructor(e="",t=[],s=0,i=[]){this.name=e,this.bindings=t,this.index=s,this.bindingsReference=i,this.id=tM++}}const iM=new WeakMap,rM=new Map([[2,"vec2"],[3,"vec3"],[4,"vec4"],[9,"mat3"],[16,"mat4"]]),nM=new Map([[Int8Array,"int"],[Int16Array,"int"],[Int32Array,"int"],[Uint8Array,"uint"],[Uint16Array,"uint"],[Uint32Array,"uint"],[Float32Array,"float"]]),oM=e=>(e=Number(e))+(e%1?"":".0");class aM{constructor(e,t,s){this.object=e,this.material=e&&e.material||null,this.geometry=e&&e.geometry||null,this.renderer=t,this.parser=s,this.scene=null,this.camera=null,this.nodes=[],this.updateNodes=[],this.updateBeforeNodes=[],this.updateAfterNodes=[],this.hashNodes={},this.lightsNode=null,this.environmentNode=null,this.fogNode=null,this.clippingContext=null,this.vertexShader=null,this.fragmentShader=null,this.computeShader=null,this.flowNodes={vertex:[],fragment:[],compute:[]},this.flowCode={vertex:"",fragment:"",compute:""},this.uniforms={vertex:[],fragment:[],compute:[],index:0},this.structs={vertex:[],fragment:[],compute:[],index:0},this.bindings={vertex:{},fragment:{},compute:{}},this.bindingsIndexes={},this.bindGroups=null,this.attributes=[],this.bufferAttributes=[],this.varyings=[],this.codes={},this.vars={},this.flow={code:""},this.chaining=[],this.stack=FS(),this.stacks=[],this.tab="\t",this.instanceBindGroups=!0,this.currentFunctionNode=null,this.context={material:this.material},this.cache=new oS,this.globalCache=this.cache,this.flowsData=new WeakMap,this.shaderStage=null,this.buildStage=null,this.useComparisonMethod=!1}getBindGroupsCache(){let e=iM.get(this.renderer);return void 0===e&&(e=new Bw,iM.set(this.renderer,e)),e}createRenderTarget(e,t,s){return new wi(e,t,s)}createCubeRenderTarget(e,t){return new Fx(e,t)}createPMREMGenerator(){return new YS(this.renderer)}includes(e){return this.nodes.includes(e)}_getBindGroup(e,t){const s=this.getBindGroupsCache(),i=[];let r,n=!0;for(const e of t)i.push(e),n=n&&!0!==e.groupNode.shared;return n?(r=s.get(i),void 0===r&&(r=new sM(e,i,this.bindingsIndexes[e].group,i),s.set(i,r))):r=new sM(e,i,this.bindingsIndexes[e].group,i),r}getBindGroupArray(e,t){const s=this.bindings[t];let i=s[e];return void 0===i&&(void 0===this.bindingsIndexes[e]&&(this.bindingsIndexes[e]={binding:0,group:Object.keys(this.bindingsIndexes).length}),s[e]=i=[]),i}getBindings(){let e=this.bindGroups;if(null===e){const t={},s=this.bindings;for(const e of Xl)for(const i in s[e]){const r=s[e][i];(t[i]||(t[i]=[])).push(...r)}e=[];for(const s in t){const i=t[s],r=this._getBindGroup(s,i);e.push(r)}this.bindGroups=e}return e}setHashNode(e,t){this.hashNodes[t]=e}addNode(e){!1===this.nodes.includes(e)&&(this.nodes.push(e),this.setHashNode(e,e.getHash(this)))}buildUpdateNodes(){for(const e of this.nodes){const t=e.getUpdateType(),s=e.getUpdateBeforeType(),i=e.getUpdateAfterType();t!==Hl.NONE&&this.updateNodes.push(e.getSelf()),s!==Hl.NONE&&this.updateBeforeNodes.push(e),i!==Hl.NONE&&this.updateAfterNodes.push(e)}}get currentNode(){return this.chaining[this.chaining.length-1]}isFilteredTexture(e){return e.magFilter===Te||e.magFilter===_e||e.magFilter===be||e.magFilter===Se||e.minFilter===Te||e.minFilter===_e||e.minFilter===be||e.minFilter===Se}addChain(e){this.chaining.push(e)}removeChain(e){if(this.chaining.pop()!==e)throw new Error("NodeBuilder: Invalid node chaining!")}getMethod(e){return e}getNodeFromHash(e){return this.hashNodes[e]}addFlow(e,t){return this.flowNodes[e].push(t),t}setContext(e){this.context=e}getContext(){return this.context}getSharedContext(){return this.context,this.context}setCache(e){this.cache=e}getCache(){return this.cache}getCacheFromNode(e,t=!0){const s=this.getDataFromNode(e);return void 0===s.cache&&(s.cache=new oS(t?this.getCache():null)),s.cache}isAvailable(){return!1}getVertexIndex(){console.warn("Abstract function.")}getInstanceIndex(){console.warn("Abstract function.")}getDrawIndex(){console.warn("Abstract function.")}getFrontFacing(){console.warn("Abstract function.")}getFragCoord(){console.warn("Abstract function.")}isFlipY(){return!1}increaseUsage(e){const t=this.getDataFromNode(e);return t.usageCount=void 0===t.usageCount?1:t.usageCount+1,t.usageCount}generateTexture(){console.warn("Abstract function.")}generateTextureLod(){console.warn("Abstract function.")}generateConst(e,t=null){if(null===t&&("float"===e||"int"===e||"uint"===e?t=0:"bool"===e?t=!1:"color"===e?t=new Yr:"vec2"===e?t=new Qs:"vec3"===e?t=new Ei:"vec4"===e&&(t=new _i)),"float"===e)return oM(t);if("int"===e)return`${Math.round(t)}`;if("uint"===e)return t>=0?`${Math.round(t)}u`:"0u";if("bool"===e)return t?"true":"false";if("color"===e)return`${this.getType("vec3")}( ${oM(t.r)}, ${oM(t.g)}, ${oM(t.b)} )`;const s=this.getTypeLength(e),i=this.getComponentType(e),r=e=>this.generateConst(i,e);if(2===s)return`${this.getType(e)}( ${r(t.x)}, ${r(t.y)} )`;if(3===s)return`${this.getType(e)}( ${r(t.x)}, ${r(t.y)}, ${r(t.z)} )`;if(4===s)return`${this.getType(e)}( ${r(t.x)}, ${r(t.y)}, ${r(t.z)}, ${r(t.w)} )`;if(s>4&&t&&(t.isMatrix3||t.isMatrix4))return`${this.getType(e)}( ${t.elements.map(r).join(", ")} )`;if(s>4)return`${this.getType(e)}()`;throw new Error(`NodeBuilder: Type '${e}' not found in generate constant attempt.`)}getType(e){return"color"===e?"vec3":e}hasGeometryAttribute(e){return this.geometry&&void 0!==this.geometry.getAttribute(e)}getAttribute(e,t){const s=this.attributes;for(const t of s)if(t.name===e)return t;const i=new eS(e,t);return s.push(i),i}getPropertyName(e){return e.name}isVector(e){return/vec\d/.test(e)}isMatrix(e){return/mat\d/.test(e)}isReference(e){return"void"===e||"property"===e||"sampler"===e||"texture"===e||"cubeTexture"===e||"storageTexture"===e||"depthTexture"===e||"texture3D"===e}needsToWorkingColorSpace(){return!1}getComponentTypeFromTexture(e){const t=e.type;if(e.isDataTexture){if(t===Ee)return"int";if(t===Be)return"uint"}return"float"}getElementType(e){return"mat2"===e?"vec2":"mat3"===e?"vec3":"mat4"===e?"vec4":this.getComponentType(e)}getComponentType(e){if("float"===(e=this.getVectorType(e))||"bool"===e||"int"===e||"uint"===e)return e;const t=/(b|i|u|)(vec|mat)([2-4])/.exec(e);return null===t?null:"b"===t[1]?"bool":"i"===t[1]?"int":"u"===t[1]?"uint":"float"}getVectorType(e){return"color"===e?"vec3":"texture"===e||"cubeTexture"===e||"storageTexture"===e||"texture3D"===e?"vec4":e}getTypeFromLength(e,t="float"){if(1===e)return t;const s=rM.get(e);return("float"===t?"":t[0])+s}getTypeFromArray(e){return nM.get(e.constructor)}getTypeFromAttribute(e){let t=e;e.isInterleavedBufferAttribute&&(t=e.data);const s=t.array,i=e.itemSize,r=e.normalized;let n;return e instanceof fn||!0===r||(n=this.getTypeFromArray(s)),this.getTypeFromLength(i,n)}getTypeLength(e){const t=this.getVectorType(e),s=/vec([2-4])/.exec(t);return null!==s?Number(s[1]):"float"===t||"bool"===t||"int"===t||"uint"===t?1:!0===/mat2/.test(e)?4:!0===/mat3/.test(e)?9:!0===/mat4/.test(e)?16:0}getVectorFromMatrix(e){return e.replace("mat","vec")}changeComponentType(e,t){return this.getTypeFromLength(this.getTypeLength(e),t)}getIntegerType(e){const t=this.getComponentType(e);return"int"===t||"uint"===t?e:this.changeComponentType(e,"int")}addStack(){return this.stack=FS(this.stack),this.stacks.push(Xu()||this.stack),$u(this.stack),this.stack}removeStack(){const e=this.stack;return this.stack=e.parent,$u(this.stacks.pop()),e}getDataFromNode(e,t=this.shaderStage,s=null){let i=(s=null===s?e.isGlobal(this)?this.globalCache:this.cache:s).getData(e);return void 0===i&&(i={},s.setData(e,i)),void 0===i[t]&&(i[t]={}),i[t]}getNodeProperties(e,t="any"){const s=this.getDataFromNode(e,t);return s.properties||(s.properties={outputNode:null})}getBufferAttributeFromNode(e,t){const s=this.getDataFromNode(e);let i=s.bufferAttribute;if(void 0===i){const r=this.uniforms.index++;i=new eS("nodeAttribute"+r,t,e),this.bufferAttributes.push(i),s.bufferAttribute=i}return i}getStructTypeFromNode(e,t=this.shaderStage){const s=this.getDataFromNode(e,t);if(void 0===s.structType){const i=this.structs.index++;e.name=`StructType${i}`,this.structs[t].push(e),s.structType=e}return e}getUniformFromNode(e,t,s=this.shaderStage,i=null){const r=this.getDataFromNode(e,s,this.globalCache);let n=r.uniform;if(void 0===n){const o=this.uniforms.index++;n=new tS(i||"nodeUniform"+o,t,e),this.uniforms[s].push(n),r.uniform=n}return n}getVarFromNode(e,t=null,s=e.getNodeType(this),i=this.shaderStage){const r=this.getDataFromNode(e,i);let n=r.variable;if(void 0===n){const e=this.vars[i]||(this.vars[i]=[]);null===t&&(t="nodeVar"+e.length),n=new sS(t,s),e.push(n),r.variable=n}return n}getVaryingFromNode(e,t=null,s=e.getNodeType(this)){const i=this.getDataFromNode(e,"any");let r=i.varying;if(void 0===r){const e=this.varyings,n=e.length;null===t&&(t="nodeVarying"+n),r=new iS(t,s),e.push(r),i.varying=r}return r}getCodeFromNode(e,t,s=this.shaderStage){const i=this.getDataFromNode(e);let r=i.code;if(void 0===r){const e=this.codes[s]||(this.codes[s]=[]),n=e.length;r=new rS("nodeCode"+n,t),e.push(r),i.code=r}return r}addLineFlowCode(e){return""===e||(e=this.tab+e,/;\s*$/.test(e)||(e+=";\n"),this.flow.code+=e),this}addFlowCode(e){return this.flow.code+=e,this}addFlowTab(){return this.tab+="\t",this}removeFlowTab(){return this.tab=this.tab.slice(0,-1),this}getFlowData(e){return this.flowsData.get(e)}flowNode(e){const t=e.getNodeType(this),s=this.flowChildNode(e,t);return this.flowsData.set(e,s),s}buildFunctionNode(e){const t=new mS,s=this.currentFunctionNode;return this.currentFunctionNode=t,t.code=this.buildFunctionCode(e),this.currentFunctionNode=s,t}flowShaderNode(e){const t=e.layout,s={[Symbol.iterator](){let e=0;const t=Object.values(this);return{next:()=>({value:t[e],done:e++>=t.length})}}};for(const e of t.inputs)s[e.name]=new aS(e.type,e.name);e.layout=null;const i=e.call(s),r=this.flowStagesNode(i,t.type);return e.layout=t,r}flowStagesNode(e,t=null){const s=this.flow,i=this.vars,r=this.cache,n=this.buildStage,o=this.stack,a={code:""};this.flow=a,this.vars={},this.cache=new oS,this.stack=FS();for(const s of $l)this.setBuildStage(s),a.result=e.build(this,t);return a.vars=this.getVars(this.shaderStage),this.flow=s,this.vars=i,this.cache=r,this.stack=o,this.setBuildStage(n),a}getFunctionOperator(){return null}flowChildNode(e,t=null){const s=this.flow,i={code:""};return this.flow=i,i.result=e.build(this,t),this.flow=s,i}flowNodeFromShaderStage(e,t,s=null,i=null){const r=this.shaderStage;this.setShaderStage(e);const n=this.flowChildNode(t,s);return null!==i&&(n.code+=`${this.tab+i} = ${n.result};\n`),this.flowCode[e]=this.flowCode[e]+n.code,this.setShaderStage(r),n}getAttributesArray(){return this.attributes.concat(this.bufferAttributes)}getAttributes(){console.warn("Abstract function.")}getVaryings(){console.warn("Abstract function.")}getVar(e,t){return`${this.getType(e)} ${t}`}getVars(e){let t="";const s=this.vars[e];if(void 0!==s)for(const e of s)t+=`${this.getVar(e.type,e.name)}; `;return t}getUniforms(){console.warn("Abstract function.")}getCodes(e){const t=this.codes[e];let s="";if(void 0!==t)for(const e of t)s+=e.code+"\n";return s}getHash(){return this.vertexShader+this.fragmentShader+this.computeShader}setShaderStage(e){this.shaderStage=e}getShaderStage(){return this.shaderStage}setBuildStage(e){this.buildStage=e}getBuildStage(){return this.buildStage}buildCode(){console.warn("Abstract function.")}build(){const{object:e,material:t,renderer:s}=this;if(null!==t){let e=s.nodes.library.fromMaterial(t);null===e&&(console.error(`NodeMaterial: Material "${t.type}" is not compatible.`),e=new xx),e.build(this)}else this.addFlow("compute",e);for(const e of $l){this.setBuildStage(e),this.context.vertex&&this.context.vertex.isNode&&this.flowNodeFromShaderStage("vertex",this.context.vertex);for(const t of Xl){this.setShaderStage(t);const s=this.flowNodes[t];for(const t of s)"generate"===e?this.flowNode(t):t.build(this)}}return this.setBuildStage(null),this.setShaderStage(null),this.buildCode(),this.buildUpdateNodes(),this}getNodeUniform(e,t){if("float"===t||"int"===t||"uint"===t)return new AS(e);if("vec2"===t||"ivec2"===t||"uvec2"===t)return new NS(e);if("vec3"===t||"ivec3"===t||"uvec3"===t)return new RS(e);if("vec4"===t||"ivec4"===t||"uvec4"===t)return new CS(e);if("color"===t)return new ES(e);if("mat3"===t)return new BS(e);if("mat4"===t)return new IS(e);throw new Error(`Uniform "${t}" not declared.`)}createNodeMaterial(e="NodeMaterial"){throw new Error(`THREE.NodeBuilder: createNodeMaterial() was deprecated. Use new ${e}() instead.`)}format(e,t,s){if((t=this.getVectorType(t))===(s=this.getVectorType(s))||null===s||this.isReference(s))return e;const i=this.getTypeLength(t),r=this.getTypeLength(s);return 16===i&&9===r?`${this.getType(s)}(${e}[0].xyz, ${e}[1].xyz, ${e}[2].xyz)`:9===i&&4===r?`${this.getType(s)}(${e}[0].xy, ${e}[1].xy)`:i>4||r>4||0===r?e:i===r?`${this.getType(s)}( ${e} )`:i>r?this.format(`${e}.${"xyz".slice(0,r)}`,this.getTypeFromLength(r,this.getComponentType(t)),s):4===r&&i>1?`${this.getType(s)}( ${this.format(e,t,"vec3")}, 1.0 )`:2===i?`${this.getType(s)}( ${this.format(e,t,"vec2")}, 0.0 )`:(1===i&&r>1&&t!==this.getComponentType(s)&&(e=`${this.getType(this.getComponentType(s))}( ${e} )`),`${this.getType(s)}( ${e} )`)}getSignature(){return`// Three.js r${e} - Node System\n`}}class hM{constructor(){this.time=0,this.deltaTime=0,this.frameId=0,this.renderId=0,this.startTime=null,this.updateMap=new WeakMap,this.updateBeforeMap=new WeakMap,this.updateAfterMap=new WeakMap,this.renderer=null,this.material=null,this.camera=null,this.object=null,this.scene=null}_getMaps(e,t){let s=e.get(t);return void 0===s&&(s={renderMap:new WeakMap,frameMap:new WeakMap},e.set(t,s)),s}updateBeforeNode(e){const t=e.getUpdateBeforeType(),s=e.updateReference(this);if(t===Hl.FRAME){const{frameMap:t}=this._getMaps(this.updateBeforeMap,s);t.get(s)!==this.frameId&&!1!==e.updateBefore(this)&&t.set(s,this.frameId)}else if(t===Hl.RENDER){const{renderMap:t}=this._getMaps(this.updateBeforeMap,s);t.get(s)!==this.renderId&&!1!==e.updateBefore(this)&&t.set(s,this.renderId)}else t===Hl.OBJECT&&e.updateBefore(this)}updateAfterNode(e){const t=e.getUpdateAfterType(),s=e.updateReference(this);if(t===Hl.FRAME){const{frameMap:t}=this._getMaps(this.updateAfterMap,s);t.get(s)!==this.frameId&&!1!==e.updateAfter(this)&&t.set(s,this.frameId)}else if(t===Hl.RENDER){const{renderMap:t}=this._getMaps(this.updateAfterMap,s);t.get(s)!==this.renderId&&!1!==e.updateAfter(this)&&t.set(s,this.renderId)}else t===Hl.OBJECT&&e.updateAfter(this)}updateNode(e){const t=e.getUpdateType(),s=e.updateReference(this);if(t===Hl.FRAME){const{frameMap:t}=this._getMaps(this.updateMap,s);t.get(s)!==this.frameId&&!1!==e.update(this)&&t.set(s,this.frameId)}else if(t===Hl.RENDER){const{renderMap:t}=this._getMaps(this.updateMap,s);t.get(s)!==this.renderId&&!1!==e.update(this)&&t.set(s,this.renderId)}else t===Hl.OBJECT&&e.update(this)}update(){this.frameId++,void 0===this.lastTime&&(this.lastTime=performance.now()),this.deltaTime=(performance.now()-this.lastTime)/1e3,this.lastTime=performance.now(),this.time+=this.deltaTime}}class lM{constructor(e,t,s=null,i="",r=!1){this.type=e,this.name=t,this.count=s,this.qualifier=i,this.isConst=r}}lM.isNodeFunctionInput=!0;class uM extends Kl{constructor(e){super(),this.types=e,this.isStructTypeNode=!0}getMemberTypes(){return this.types}}uM.type=Ql("StructType",uM);class cM extends Kl{constructor(...e){super(),this.members=e,this.isOutputStructNode=!0}setup(e){super.setup(e);const t=this.members,s=[];for(let i=0;ir&&(i=s,r=n)}}this._candidateFnCall=s=i(...t)}return s}}fM.type=Ql("FunctionOverloading",fM);const yM=Wu(fM),xM=e=>(...t)=>yM(e,...t);class bM extends Rc{constructor(e=bM.LOCAL,t=1,s=0){super(s),this.scope=e,this.scale=t,this.updateType=Hl.FRAME}update(e){const t=this.scope,s=this.scale;t===bM.LOCAL?this.value+=e.deltaTime*s:t===bM.DELTA?this.value=e.deltaTime*s:t===bM.FRAME?this.value=e.frameId:this.value=e.time*s}serialize(e){super.serialize(e),e.scope=this.scope,e.scale=this.scale}deserialize(e){super.deserialize(e),this.scope=e.scope,this.scale=e.scale}}bM.LOCAL="local",bM.GLOBAL="global",bM.DELTA="delta",bM.FRAME="frame",bM.type=Ql("Timer",bM);const vM=(e,t=0)=>Du(new bM(bM.LOCAL,e,t)),TM=(e,t=0)=>Du(new bM(bM.GLOBAL,e,t)),_M=(e,t=0)=>Du(new bM(bM.DELTA,e,t)),wM=Hu(bM,bM.FRAME).toUint();class SM extends Kl{constructor(e=SM.SINE,t=vM()){super(),this.method=e,this.timeNode=t}getNodeType(e){return this.timeNode.getNodeType(e)}setup(){const e=this.method,t=Du(this.timeNode);let s=null;return e===SM.SINE?s=t.add(.75).mul(2*Math.PI).sin().mul(.5).add(.5):e===SM.SQUARE?s=t.fract().round():e===SM.TRIANGLE?s=t.add(.5).fract().mul(2).sub(1).abs():e===SM.SAWTOOTH&&(s=t.fract()),s}serialize(e){super.serialize(e),e.method=this.method}deserialize(e){super.deserialize(e),this.method=e.method}}SM.SINE="sine",SM.SQUARE="square",SM.TRIANGLE="triangle",SM.SAWTOOTH="sawtooth",SM.type=Ql("Osc",SM);const MM=Wu(SM,SM.SINE),AM=Wu(SM,SM.SQUARE),NM=Wu(SM,SM.TRIANGLE),RM=Wu(SM,SM.SAWTOOTH);class CM extends Kl{constructor(e,t=Um(),s=Ku(0)){super("vec2"),this.countNode=e,this.uvNode=t,this.frameNode=s}setup(){const{frameNode:e,uvNode:t,countNode:s}=this,{width:i,height:r}=s,n=e.mod(i.mul(r)).floor(),o=n.mod(i),a=r.sub(n.add(1).div(i).ceil()),h=s.reciprocal(),l=sc(o,a);return t.add(l).mul(h)}}CM.type=Ql("SpriteSheetUV",CM);const EM=Wu(CM);class BM extends tu{constructor(e,t){super(e,t),this.isStorageArrayElementNode=!0}set storageBufferNode(e){this.node=e}get storageBufferNode(){return this.node}setup(e){return!1===e.isAvailable("storageBuffer")&&(this.node.instanceIndex||!0!==this.node.bufferObject||e.setupPBO(this.node)),super.setup(e)}generate(e,t){let s;const i=e.context.assign;if(!1===e.isAvailable("storageBuffer")){const{node:t}=this;s=t.instanceIndex||!0!==this.node.bufferObject||!0===i?t.build(e):e.generatePBO(this)}else s=super.generate(e);if(!0!==i){const i=this.getNodeType(e);s=e.format(s,i,t)}return s}}BM.type=Ql("StorageArrayElement",BM);const IM=Wu(BM);class PM extends Kl{constructor(e,t=null,s=null,i=Ku(1),r=bg,n=Cg){super("vec4"),this.textureXNode=e,this.textureYNode=t,this.textureZNode=s,this.scaleNode=i,this.positionNode=r,this.normalNode=n}setup(){const{textureXNode:e,textureYNode:t,textureZNode:s,scaleNode:i,positionNode:r,normalNode:n}=this;let o=n.abs().normalize();o=o.div(o.dot(oc(1)));const a=r.yz.mul(i),h=r.zx.mul(i),l=r.xy.mul(i),u=e.value,c=null!==t?t.value:u,d=null!==s?s.value:u,p=Gm(u,a).mul(o.x),m=Gm(c,h).mul(o.y),g=Gm(d,l).mul(o.z);return dd(p,m,g)}}PM.type=Ql("TriplanarTextures",PM);const FM=Wu(PM),zM=(...e)=>FM(...e),UM=new sa,LM=new Ei,OM=new Ei,VM=new Ei,DM=new or,kM=new Ei(0,0,-1),GM=new _i,WM=new Ei,HM=new Ei,jM=new _i,qM=new Qs,$M=new wi,XM=Zy.flipX();let YM=!1;class JM extends km{constructor(e={}){super($M.texture,XM);const{target:t=new Pr,resolution:s=1,generateMipmaps:i=!1,bounces:r=!0}=e;this.target=t,this.resolution=s,this.generateMipmaps=i,this.bounces=r,this.updateBeforeType=r?Hl.RENDER:Hl.FRAME,this.virtualCameras=new WeakMap,this.renderTargets=new WeakMap}_updateResolution(e,t){const s=this.resolution;t.getDrawingBufferSize(qM),e.setSize(Math.round(qM.width*s),Math.round(qM.height*s))}setup(e){return this._updateResolution($M,e.renderer),super.setup(e)}getTextureNode(){return this.textureNode}getVirtualCamera(e){let t=this.virtualCameras.get(e);return void 0===t&&(t=e.clone(),this.virtualCameras.set(e,t)),t}getRenderTarget(e){let t=this.renderTargets.get(e);return void 0===t&&(t=new wi(0,0,{type:Pe}),!0===this.generateMipmaps&&(t.texture.minFilter=1008,t.texture.generateMipmaps=!0),this.renderTargets.set(e,t)),t}updateBefore(e){if(!1===this.bounces&&YM)return!1;YM=!0;const{scene:t,camera:s,renderer:i,material:r}=e,{target:n}=this,o=this.getVirtualCamera(s),a=this.getRenderTarget(o);if(i.getDrawingBufferSize(qM),this._updateResolution(a,i),OM.setFromMatrixPosition(n.matrixWorld),VM.setFromMatrixPosition(s.matrixWorld),DM.extractRotation(n.matrixWorld),LM.set(0,0,1),LM.applyMatrix4(DM),WM.subVectors(OM,VM),WM.dot(LM)>0)return;WM.reflect(LM).negate(),WM.add(OM),DM.extractRotation(s.matrixWorld),kM.set(0,0,-1),kM.applyMatrix4(DM),kM.add(VM),HM.subVectors(OM,kM),HM.reflect(LM).negate(),HM.add(OM),o.coordinateSystem=s.coordinateSystem,o.position.copy(WM),o.up.set(0,1,0),o.up.applyMatrix4(DM),o.up.reflect(LM),o.lookAt(HM),o.near=s.near,o.far=s.far,o.updateMatrixWorld(),o.projectionMatrix.copy(s.projectionMatrix),UM.setFromNormalAndCoplanarPoint(LM,OM),UM.applyMatrix4(o.matrixWorldInverse),GM.set(UM.normal.x,UM.normal.y,UM.normal.z,UM.constant);const h=o.projectionMatrix;jM.x=(Math.sign(GM.x)+h.elements[8])/h.elements[0],jM.y=(Math.sign(GM.y)+h.elements[9])/h.elements[5],jM.z=-1,jM.w=(1+h.elements[10])/h.elements[14],GM.multiplyScalar(1/GM.dot(jM));h.elements[2]=GM.x,h.elements[6]=GM.y,h.elements[10]=GM.z-0,h.elements[14]=GM.w,this.value=a.texture,r.visible=!1;const l=i.getRenderTarget(),u=i.getMRT();i.setMRT(null),i.setRenderTarget(a),i.render(t,o),i.setMRT(u),i.setRenderTarget(l),r.visible=!0,YM=!1}}const ZM=e=>Du(new JM(e));JM.type=Ql("Reflector",JM);const KM=new OT(-1,1,1,-1,0,1);class QM extends Mn{constructor(e=!1){super();const t=!1===e?[0,-1,0,1,2,1]:[0,2,0,0,2,0];this.setAttribute("position",new yn([-1,3,0,-1,-1,0,3,-1,0],3)),this.setAttribute("uv",new yn(t,2))}}const eA=new QM;class tA extends Wn{constructor(e=null){super(eA,e),this.camera=KM,this.isQuadMesh=!0}renderAsync(e){return e.renderAsync(this,KM)}render(e){e.render(this,KM)}}const sA=new Qs;class iA extends km{constructor(e,t=null,s=null,i={type:Pe}){const r=new wi(t,s,i);super(r.texture,Um()),this.node=e,this.width=t,this.height=s,this.renderTarget=r,this.textureNeedsUpdate=!0,this.autoUpdate=!0,this.updateMap=new WeakMap,this._rttNode=null,this._quadMesh=new tA(new xx),this.updateBeforeType=Hl.RENDER}get autoSize(){return null===this.width}setup(e){return this._rttNode=this.node.context(e.getSharedContext()),this._quadMesh.material.name="RTT",this._quadMesh.material.needsUpdate=!0,super.setup(e)}setSize(e,t){this.width=e,this.height=t;const s=e*this.pixelRatio,i=t*this.pixelRatio;this.renderTarget.setSize(s,i),this.textureNeedsUpdate=!0}setPixelRatio(e){this.pixelRatio=e,this.setSize(this.width,this.height)}updateBefore({renderer:e}){if(!1===this.textureNeedsUpdate&&!1===this.autoUpdate)return;if(this.textureNeedsUpdate=!1,!0===this.autoSize){this.pixelRatio=e.getPixelRatio();const t=e.getSize(sA);this.setSize(t.width,t.height)}this._quadMesh.material.fragmentNode=this._rttNode;const t=e.getRenderTarget();e.setRenderTarget(this.renderTarget),this._quadMesh.render(e),e.setRenderTarget(t)}clone(){const e=new km(this.value,this.uvNode,this.levelNode);return e.sampler=this.sampler,e.referenceNode=this,e}}iA.type=Ql("RTT",iA);const rA=(e,...t)=>Du(new iA(Du(e),...t)),nA=(e,...t)=>e.isTextureNode?e:rA(e,...t);class oA extends Fm{constructor(e=0){super(null,"vec4"),this.isVertexColorNode=!0,this.index=e}getAttributeName(){const e=this.index;return"color"+(e>0?e:"")}generate(e){const t=this.getAttributeName(e);let s;return s=!0===e.hasGeometryAttribute(t)?super.generate(e):e.generateConst(this.nodeType,new _i(1,1,1,1)),s}serialize(e){super.serialize(e),e.index=this.index}deserialize(e){super.deserialize(e),this.index=e.index}}oA.type=Ql("VertexColor",oA);const aA=(...e)=>Du(new oA(...e));class hA extends Kl{constructor(){super("vec2"),this.isPointUVNode=!0}generate(){return"vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y )"}}hA.type=Ql("PointUV",hA);const lA=Hu(hA);class uA extends Kl{constructor(e=uA.BACKGROUND_BLURRINESS,t=null){super(),this.scope=e,this.scene=t}setup(e){const t=this.scope,s=null!==this.scene?this.scene:e.scene;let i;return t===uA.BACKGROUND_BLURRINESS?i=Zg("backgroundBlurriness","float",s):t===uA.BACKGROUND_INTENSITY?i=Zg("backgroundIntensity","float",s):console.error("THREE.SceneNode: Unknown scope:",t),i}}uA.BACKGROUND_BLURRINESS="backgroundBlurriness",uA.BACKGROUND_INTENSITY="backgroundIntensity",uA.type=Ql("Scene",uA);const cA=Hu(uA,uA.BACKGROUND_BLURRINESS),dA=Hu(uA,uA.BACKGROUND_INTENSITY),pA="point-list",mA="line-list",gA="line-strip",fA="triangle-list",yA="triangle-strip",xA="never",bA="less",vA="equal",TA="less-equal",_A="greater",wA="not-equal",SA="greater-equal",MA="always",AA="store",NA="load",RA="clear",CA="ccw",EA="none",BA="front",IA="back",PA="uint16",FA="uint32",zA={R8Unorm:"r8unorm",R8Snorm:"r8snorm",R8Uint:"r8uint",R8Sint:"r8sint",R16Uint:"r16uint",R16Sint:"r16sint",R16Float:"r16float",RG8Unorm:"rg8unorm",RG8Snorm:"rg8snorm",RG8Uint:"rg8uint",RG8Sint:"rg8sint",R32Uint:"r32uint",R32Sint:"r32sint",R32Float:"r32float",RG16Uint:"rg16uint",RG16Sint:"rg16sint",RG16Float:"rg16float",RGBA8Unorm:"rgba8unorm",RGBA8UnormSRGB:"rgba8unorm-srgb",RGBA8Snorm:"rgba8snorm",RGBA8Uint:"rgba8uint",RGBA8Sint:"rgba8sint",BGRA8Unorm:"bgra8unorm",BGRA8UnormSRGB:"bgra8unorm-srgb",RGB9E5UFloat:"rgb9e5ufloat",RGB10A2Unorm:"rgb10a2unorm",RG11B10uFloat:"rgb10a2unorm",RG32Uint:"rg32uint",RG32Sint:"rg32sint",RG32Float:"rg32float",RGBA16Uint:"rgba16uint",RGBA16Sint:"rgba16sint",RGBA16Float:"rgba16float",RGBA32Uint:"rgba32uint",RGBA32Sint:"rgba32sint",RGBA32Float:"rgba32float",Stencil8:"stencil8",Depth16Unorm:"depth16unorm",Depth24Plus:"depth24plus",Depth24PlusStencil8:"depth24plus-stencil8",Depth32Float:"depth32float",Depth32FloatStencil8:"depth32float-stencil8",BC1RGBAUnorm:"bc1-rgba-unorm",BC1RGBAUnormSRGB:"bc1-rgba-unorm-srgb",BC2RGBAUnorm:"bc2-rgba-unorm",BC2RGBAUnormSRGB:"bc2-rgba-unorm-srgb",BC3RGBAUnorm:"bc3-rgba-unorm",BC3RGBAUnormSRGB:"bc3-rgba-unorm-srgb",BC4RUnorm:"bc4-r-unorm",BC4RSnorm:"bc4-r-snorm",BC5RGUnorm:"bc5-rg-unorm",BC5RGSnorm:"bc5-rg-snorm",BC6HRGBUFloat:"bc6h-rgb-ufloat",BC6HRGBFloat:"bc6h-rgb-float",BC7RGBAUnorm:"bc7-rgba-unorm",BC7RGBAUnormSRGB:"bc7-rgba-srgb",ETC2RGB8Unorm:"etc2-rgb8unorm",ETC2RGB8UnormSRGB:"etc2-rgb8unorm-srgb",ETC2RGB8A1Unorm:"etc2-rgb8a1unorm",ETC2RGB8A1UnormSRGB:"etc2-rgb8a1unorm-srgb",ETC2RGBA8Unorm:"etc2-rgba8unorm",ETC2RGBA8UnormSRGB:"etc2-rgba8unorm-srgb",EACR11Unorm:"eac-r11unorm",EACR11Snorm:"eac-r11snorm",EACRG11Unorm:"eac-rg11unorm",EACRG11Snorm:"eac-rg11snorm",ASTC4x4Unorm:"astc-4x4-unorm",ASTC4x4UnormSRGB:"astc-4x4-unorm-srgb",ASTC5x4Unorm:"astc-5x4-unorm",ASTC5x4UnormSRGB:"astc-5x4-unorm-srgb",ASTC5x5Unorm:"astc-5x5-unorm",ASTC5x5UnormSRGB:"astc-5x5-unorm-srgb",ASTC6x5Unorm:"astc-6x5-unorm",ASTC6x5UnormSRGB:"astc-6x5-unorm-srgb",ASTC6x6Unorm:"astc-6x6-unorm",ASTC6x6UnormSRGB:"astc-6x6-unorm-srgb",ASTC8x5Unorm:"astc-8x5-unorm",ASTC8x5UnormSRGB:"astc-8x5-unorm-srgb",ASTC8x6Unorm:"astc-8x6-unorm",ASTC8x6UnormSRGB:"astc-8x6-unorm-srgb",ASTC8x8Unorm:"astc-8x8-unorm",ASTC8x8UnormSRGB:"astc-8x8-unorm-srgb",ASTC10x5Unorm:"astc-10x5-unorm",ASTC10x5UnormSRGB:"astc-10x5-unorm-srgb",ASTC10x6Unorm:"astc-10x6-unorm",ASTC10x6UnormSRGB:"astc-10x6-unorm-srgb",ASTC10x8Unorm:"astc-10x8-unorm",ASTC10x8UnormSRGB:"astc-10x8-unorm-srgb",ASTC10x10Unorm:"astc-10x10-unorm",ASTC10x10UnormSRGB:"astc-10x10-unorm-srgb",ASTC12x10Unorm:"astc-12x10-unorm",ASTC12x10UnormSRGB:"astc-12x10-unorm-srgb",ASTC12x12Unorm:"astc-12x12-unorm",ASTC12x12UnormSRGB:"astc-12x12-unorm-srgb"},UA="clamp-to-edge",LA="repeat",OA="mirror-repeat",VA="linear",DA="nearest",kA="zero",GA="one",WA="src",HA="one-minus-src",jA="src-alpha",qA="one-minus-src-alpha",$A="dst",XA="one-minus-dst",YA="dst-alpha",JA="one-minus-dst-alpha",ZA="src-alpha-saturated",KA="constant",QA="one-minus-constant",eN="add",tN="subtract",sN="reverse-subtract",iN="min",rN="max",nN=0,oN=15,aN="keep",hN="zero",lN="replace",uN="invert",cN="increment-clamp",dN="decrement-clamp",pN="increment-wrap",mN="decrement-wrap",gN="storage",fN="read-only-storage",yN="write-only",xN="read-only",bN="float",vN="unfilterable-float",TN="depth",_N="sint",wN="uint",SN="2d",MN="3d",AN="2d",NN="2d-array",RN="cube",CN="3d",EN="all",BN="vertex",IN="instance",PN={DepthClipControl:"depth-clip-control",Depth32FloatStencil8:"depth32float-stencil8",TextureCompressionBC:"texture-compression-bc",TextureCompressionETC2:"texture-compression-etc2",TextureCompressionASTC:"texture-compression-astc",TimestampQuery:"timestamp-query",IndirectFirstInstance:"indirect-first-instance",ShaderF16:"shader-f16",RG11B10UFloat:"rg11b10ufloat-renderable",BGRA8UNormStorage:"bgra8unorm-storage",Float32Filterable:"float32-filterable",ClipDistances:"clip-distances",DualSourceBlending:"dual-source-blending",Subgroups:"subgroups"};class FN extends Hg{constructor(e,t,s=0){super(e,t,s),this.isStorageBufferNode=!0,this.access=gN,this.bufferObject=!1,this.bufferCount=s,this._attribute=null,this._varying=null,this.global=!0,!0!==e.isStorageBufferAttribute&&!0!==e.isStorageInstancedBufferAttribute&&(e.isInstancedBufferAttribute?e.isStorageInstancedBufferAttribute=!0:e.isStorageBufferAttribute=!0)}getHash(e){if(0===this.bufferCount){let t=e.globalCache.getData(this.value);return void 0===t&&(t={node:this},e.globalCache.setData(this.value,t)),t.node.uuid}return this.uuid}getInputType(){return"storageBuffer"}element(e){return IM(this,e)}setBufferObject(e){return this.bufferObject=e,this}setAccess(e){return this.access=e,this}toReadOnly(){return this.setAccess(fN)}generate(e){if(e.isAvailable("storageBuffer"))return super.generate(e);const t=this.getNodeType(e);null===this._attribute&&(this._attribute=mm(this.value),this._varying=em(this._attribute));const s=this._varying.build(e,t);return e.registerTransform(s,this._attribute),s}}FN.type=Ql("StorageBuffer",FN);const zN=(e,t,s)=>Du(new FN(e,t,s)),UN=(e,t,s)=>Du(new FN(e,t,s).setBufferObject(!0));class LN extends km{constructor(e,t,s=null){super(e,t),this.storeNode=s,this.isStorageTextureNode=!0,this.access=yN}getInputType(){return"storageTexture"}setup(e){super.setup(e);e.getNodeProperties(this).storeNode=this.storeNode}setAccess(e){return this.access=e,this}generate(e,t){let s;return s=null!==this.storeNode?this.generateStore(e):super.generate(e,t),s}toReadOnly(){return this.setAccess(xN)}toWriteOnly(){return this.setAccess(yN)}generateStore(e){const t=e.getNodeProperties(this),{uvNode:s,storeNode:i}=t,r=super.generate(e,"property"),n=s.build(e,"uvec2"),o=i.build(e,"vec4"),a=e.generateTextureStore(e,r,n,o);e.addLineFlowCode(a)}}LN.type=Ql("StorageTexture",LN);const ON=Wu(LN),VN=(e,t,s)=>{const i=ON(e,t,s);return null!==s&&i.append(),i};class DN extends Jg{constructor(e,t,s=null){super(e,t,s),this.userData=s}update(e){this.reference=null!==this.userData?this.userData:e.object.userData,super.update(e)}}DN.type=Ql("UserData",DN);const kN=(e,t,s)=>Du(new DN(e,t,s));class GN extends iu{constructor(e,t){super(),this.sourceNode=e,this.stepsNode=t}setup(){const{sourceNode:e,stepsNode:t}=this;return e.mul(t).floor().div(t)}}GN.type=Ql("Posterize",GN);const WN=Wu(GN);let HN=null;class jN extends tx{constructor(e=Zy,t=null){null===HN&&(HN=new Xa),super(e,t,HN)}updateReference(){return this}}jN.type=Ql("ViewportSharedTexture",jN);const qN=Wu(jN),$N=new Qs;class XN extends km{constructor(e,t){super(t),this.passNode=e,this.setUpdateMatrix(!1)}setup(e){return e.object.isQuadMesh&&this.passNode.build(e),super.setup(e)}clone(){return new this.constructor(this.passNode,this.value)}}XN.type=Ql("PassTexture",XN);class YN extends XN{constructor(e,t,s=!1){super(e,null),this.textureName=t,this.previousTexture=s}updateTexture(){this.value=this.previousTexture?this.passNode.getPreviousTexture(this.textureName):this.passNode.getTexture(this.textureName)}setup(e){return this.updateTexture(),super.setup(e)}clone(){return new this.constructor(this.passNode,this.textureName,this.previousTexture)}}YN.type=Ql("PassMultipleTexture",YN);class JN extends iu{constructor(e,t,s,i={}){super("vec4"),this.scope=e,this.scene=t,this.camera=s,this.options=i,this._pixelRatio=1,this._width=1,this._height=1;const r=new Qa;r.isRenderTargetTexture=!0,r.name="depth";const n=new wi(this._width*this._pixelRatio,this._height*this._pixelRatio,{type:Pe,...i});n.texture.name="output",n.depthTexture=r,this.renderTarget=n,this.updateBeforeType=Hl.FRAME,this._textures={output:n.texture,depth:r},this._textureNodes={},this._linearDepthNodes={},this._viewZNodes={},this._previousTextures={},this._previousTextureNodes={},this._cameraNear=Cc(0),this._cameraFar=Cc(0),this._mrt=null,this.isPassNode=!0}setMRT(e){return this._mrt=e,this}getMRT(){return this._mrt}isGlobal(){return!0}getTexture(e){let t=this._textures[e];if(void 0===t){t=this.renderTarget.texture.clone(),t.isRenderTargetTexture=!0,t.name=e,this._textures[e]=t,this.renderTarget.textures.push(t)}return t}getPreviousTexture(e){let t=this._previousTextures[e];return void 0===t&&(t=this.getTexture(e).clone(),t.isRenderTargetTexture=!0,this._previousTextures[e]=t),t}toggleTexture(e){const t=this._previousTextures[e];if(void 0!==t){const s=this._textures[e],i=this.renderTarget.textures.indexOf(s);this.renderTarget.textures[i]=t,this._textures[e]=t,this._previousTextures[e]=s,this._textureNodes[e].updateTexture(),this._previousTextureNodes[e].updateTexture()}}getTextureNode(e="output"){let t=this._textureNodes[e];return void 0===t&&(this._textureNodes[e]=t=Du(new YN(this,e)),this._textureNodes[e].updateTexture()),t}getPreviousTextureNode(e="output"){let t=this._previousTextureNodes[e];return void 0===t&&(void 0===this._textureNodes[e]&&this.getTextureNode(e),this._previousTextureNodes[e]=t=Du(new YN(this,e,!0)),this._previousTextureNodes[e].updateTexture()),t}getViewZNode(e="depth"){let t=this._viewZNodes[e];if(void 0===t){const s=this._cameraNear,i=this._cameraFar;this._viewZNodes[e]=t=cx(this.getTextureNode(e),s,i)}return t}getLinearDepthNode(e="depth"){let t=this._linearDepthNodes[e];if(void 0===t){const s=this._cameraNear,i=this._cameraFar,r=this.getViewZNode(e);this._linearDepthNodes[e]=t=hx(r,s,i)}return t}setup({renderer:e}){return this.renderTarget.samples=void 0===this.options.samples?e.samples:this.options.samples,!0===e.backend.isWebGLBackend&&(this.renderTarget.samples=0),this.renderTarget.depthTexture.isMultisampleRenderTargetTexture=this.renderTarget.samples>1,this.scope===JN.COLOR?this.getTextureNode():this.getLinearDepthNode()}updateBefore(e){const{renderer:t}=e,{scene:s,camera:i}=this;this._pixelRatio=t.getPixelRatio();const r=t.getSize($N);this.setSize(r.width,r.height);const n=t.getRenderTarget(),o=t.getMRT();this._cameraNear.value=i.near,this._cameraFar.value=i.far;for(const e in this._previousTextures)this.toggleTexture(e);t.setRenderTarget(this.renderTarget),t.setMRT(this._mrt),t.render(s,i),t.setRenderTarget(n),t.setMRT(o)}setSize(e,t){this._width=e,this._height=t;const s=this._width*this._pixelRatio,i=this._height*this._pixelRatio;this.renderTarget.setSize(s,i)}setPixelRatio(e){this._pixelRatio=e,this.setSize(this._width,this._height)}dispose(){this.renderTarget.dispose()}}JN.COLOR="color",JN.DEPTH="depth",JN.type=Ql("Pass",JN);const ZN=(e,t,s)=>Du(new JN(JN.COLOR,e,t,s)),KN=(e,t)=>Du(new XN(e,t)),QN=(e,t)=>Du(new JN(JN.DEPTH,e,t)),eR=new tA,tR=new tA;class sR extends iu{constructor(e,t=null,s=2){super("vec4"),this.textureNode=e,this.directionNode=t,this.sigma=s,this._invSize=Cc(new Qs),this._passDirection=Cc(new Qs),this._horizontalRT=new wi,this._horizontalRT.texture.name="GaussianBlurNode.horizontal",this._verticalRT=new wi,this._verticalRT.texture.name="GaussianBlurNode.vertical",this._textureNode=KN(this,this._verticalRT.texture),this.updateBeforeType=Hl.RENDER,this.resolution=new Qs(1,1)}setSize(e,t){e=Math.max(Math.round(e*this.resolution.x),1),t=Math.max(Math.round(t*this.resolution.y),1),this._invSize.value.set(1/e,1/t),this._horizontalRT.setSize(e,t),this._verticalRT.setSize(e,t)}updateBefore(e){const{renderer:t}=e,s=this.textureNode,i=s.value,r=t.getRenderTarget(),n=t.getMRT(),o=s.value;eR.material=this._material,tR.material=this._material,this.setSize(i.image.width,i.image.height);const a=i.type;this._horizontalRT.texture.type=a,this._verticalRT.texture.type=a,t.setMRT(null),t.setRenderTarget(this._horizontalRT),this._passDirection.value.set(1,0),eR.render(t),s.value=this._horizontalRT.texture,t.setRenderTarget(this._verticalRT),this._passDirection.value.set(0,1),tR.render(t),t.setRenderTarget(r),t.setMRT(n),s.value=o}getTextureNode(){return this._textureNode}setup(e){const t=this.textureNode;if(!0!==t.isTextureNode)return console.error("GaussianBlurNode requires a TextureNode."),uc();const s=t.uvNode||Um(),i=sc(this.directionNode||1),r=e=>t.uv(e),n=ju((()=>{const e=3+2*this.sigma,t=this._getCoefficients(e),n=this._invSize,o=i.mul(this._passDirection),a=Ku(t[0]).toVar(),h=uc(r(s).mul(a)).toVar();for(let i=1;iDu(new sR(nA(e),t,s)),rR=new Qs,nR=new tA;class oR extends iu{constructor(e,t=.96){super(e),this.textureNode=e,this.textureNodeOld=Gm(),this.damp=Cc(t),this._compRT=new wi,this._compRT.texture.name="AfterImageNode.comp",this._oldRT=new wi,this._oldRT.texture.name="AfterImageNode.old",this._textureNode=KN(this,this._compRT.texture),this.updateBeforeType=Hl.RENDER}getTextureNode(){return this._textureNode}setSize(e,t){this._compRT.setSize(e,t),this._oldRT.setSize(e,t)}updateBefore(e){const{renderer:t}=e,s=this.textureNode,i=s.value.type;this._compRT.texture.type=i,this._oldRT.texture.type=i,t.getDrawingBufferSize(rR),this.setSize(rR.x,rR.y);const r=t.getRenderTarget(),n=s.value;this.textureNodeOld.value=this._oldRT.texture,t.setRenderTarget(this._compRT),nR.render(t);const o=this._oldRT;this._oldRT=this._compRT,this._compRT=o,t.setRenderTarget(r),s.value=n}setup(e){const t=this.textureNode,s=this.textureNodeOld,i=t.uvNode||Um();s.uvNode=i;const r=ju((([e,t])=>{const s=Ku(t).toVar(),i=uc(e).toVar();return Tp(ap(i.sub(s)),0)})),n=ju((()=>{const e=uc(s),n=uc((e=>t.uv(e))(i));return e.mulAssign(this.damp.mul(r(e,.1))),Tp(n,e)})),o=this._materialComposed||(this._materialComposed=new xx);o.name="AfterImage",o.fragmentNode=n(),nR.material=o;return e.getNodeProperties(this).textureNode=t,this._textureNode}dispose(){this._compRT.dispose(),this._oldRT.dispose()}}const aR=(e,t)=>Du(new oR(nA(e),t)),hR=ju((([e])=>pR(e.rgb))),lR=ju((([e,t=Ku(1)])=>t.mix(pR(e.rgb),e.rgb))),uR=ju((([e,t=Ku(1)])=>{const s=dd(e.r,e.g,e.b).div(3),i=e.r.max(e.g.max(e.b)),r=i.sub(s).mul(t).mul(-3);return Up(e.rgb,i,r)})),cR=ju((([e,t=Ku(1)])=>{const s=oc(.57735,.57735,.57735),i=t.cos();return oc(e.rgb.mul(i).add(s.cross(e.rgb).mul(t.sin()).add(s.mul(Np(s,e.rgb).mul(i.oneMinus())))))})),dR=new Ei,pR=(e,t=oc(...di.getLuminanceCoefficients(dR)))=>Np(e,t),mR=(e,t)=>Up(oc(0),e,pR(e).sub(t).max(0)),gR=new tA;class fR extends iu{constructor(e,t,s,i){super("vec4"),this.textureNode=e,this.tresholdNode=t,this.scaleNode=s,this.colorNode=oc(.1,0,1),this.samples=i,this.resolution=new Qs(1,1),this._renderTarget=new wi,this._renderTarget.texture.name="anamorphic",this._invSize=Cc(new Qs),this._textureNode=KN(this,this._renderTarget.texture),this.updateBeforeType=Hl.RENDER}getTextureNode(){return this._textureNode}setSize(e,t){this._invSize.value.set(1/e,1/t),e=Math.max(Math.round(e*this.resolution.x),1),t=Math.max(Math.round(t*this.resolution.y),1),this._renderTarget.setSize(e,t)}updateBefore(e){const{renderer:t}=e,s=this.textureNode,i=s.value;this._renderTarget.texture.type=i.type;const r=t.getRenderTarget(),n=s.value;gR.material=this._material,this.setSize(i.image.width,i.image.height),t.setRenderTarget(this._renderTarget),gR.render(t),t.setRenderTarget(r),s.value=n}setup(e){const t=this.textureNode,s=t.uvNode||Um(),i=ju((()=>{const e=this.samples,i=Math.floor(e/2),r=oc(0).toVar();return Cy({start:-i,end:i},(({i:e})=>{const n=Ku(e).abs().div(i).oneMinus(),o=(e=>t.uv(e))(sc(s.x.add(this._invSize.x.mul(e).mul(this.scaleNode)),s.y)),a=mR(o,this.tresholdNode).mul(n);r.addAssign(a)})),r.mul(this.colorNode)})),r=this._material||(this._material=new xx);r.name="Anamorphic",r.fragmentNode=i();return e.getNodeProperties(this).textureNode=t,this._textureNode}dispose(){this._renderTarget.dispose()}}const yR=(e,t=.9,s=3,i=32)=>Du(new fR(nA(e),Du(t),Du(s),i));class xR extends iu{constructor(e){super(),this.textureNode=e,this.updateBeforeType=Hl.RENDER,this._invSize=Cc(new Qs)}updateBefore(){const e=this.textureNode.value;this._invSize.value.set(1/e.image.width,1/e.image.height)}setup(){const{textureNode:e}=this,t=e.uvNode||Um(),s=t=>e.uv(t);return ju((()=>{const e=this._invSize,i=gc(-1,-2,-1,0,0,0,1,2,1),r=gc(-1,0,1,-2,0,2,-1,0,1),n=pR(s(t.add(e.mul(sc(-1,-1)))).xyz),o=pR(s(t.add(e.mul(sc(-1,0)))).xyz),a=pR(s(t.add(e.mul(sc(-1,1)))).xyz),h=pR(s(t.add(e.mul(sc(0,-1)))).xyz),l=pR(s(t.add(e.mul(sc(0,0)))).xyz),u=pR(s(t.add(e.mul(sc(0,1)))).xyz),c=pR(s(t.add(e.mul(sc(1,-1)))).xyz),d=pR(s(t.add(e.mul(sc(1,0)))).xyz),p=pR(s(t.add(e.mul(sc(1,1)))).xyz),m=dd(i[0][0].mul(n),i[1][0].mul(h),i[2][0].mul(c),i[0][1].mul(o),i[1][1].mul(l),i[2][1].mul(d),i[0][2].mul(a),i[1][2].mul(u),i[2][2].mul(p)),g=dd(r[0][0].mul(n),r[1][0].mul(h),r[2][0].mul(c),r[0][1].mul(o),r[1][1].mul(l),r[2][1].mul(d),r[0][2].mul(a),r[1][2].mul(u),r[2][2].mul(p)),f=m.mul(m).add(g.mul(g)).sqrt();return uc(oc(f),1)}))()}}xR.type=Ql("SobelOperator",xR);const bR=e=>Du(new xR(nA(e)));class vR extends iu{constructor(e,t,s,i,r){super(),this.textureNode=e,this.viewZNode=t,this.focusNode=s,this.apertureNode=i,this.maxblurNode=r,this._aspect=Cc(0),this.updateBeforeType=Hl.RENDER}updateBefore(){const e=this.textureNode.value;this._aspect.value=e.image.width/e.image.height}setup(){const e=this.textureNode,t=e.uvNode||Um(),s=t=>e.uv(t);return ju((()=>{const e=sc(1,this._aspect),i=this.focusNode.add(this.viewZNode),r=sc(Lp(i.mul(this.apertureNode),this.maxblurNode.negate(),this.maxblurNode)),n=r.mul(.9),o=r.mul(.7),a=r.mul(.4);let h=uc(0);return h=h.add(s(t)),h=h.add(s(t.add(sc(0,.4).mul(e).mul(r)))),h=h.add(s(t.add(sc(.15,.37).mul(e).mul(r)))),h=h.add(s(t.add(sc(.29,.29).mul(e).mul(r)))),h=h.add(s(t.add(sc(-.37,.15).mul(e).mul(r)))),h=h.add(s(t.add(sc(.4,0).mul(e).mul(r)))),h=h.add(s(t.add(sc(.37,-.15).mul(e).mul(r)))),h=h.add(s(t.add(sc(.29,-.29).mul(e).mul(r)))),h=h.add(s(t.add(sc(-.15,-.37).mul(e).mul(r)))),h=h.add(s(t.add(sc(0,-.4).mul(e).mul(r)))),h=h.add(s(t.add(sc(-.15,.37).mul(e).mul(r)))),h=h.add(s(t.add(sc(-.29,.29).mul(e).mul(r)))),h=h.add(s(t.add(sc(.37,.15).mul(e).mul(r)))),h=h.add(s(t.add(sc(-.4,0).mul(e).mul(r)))),h=h.add(s(t.add(sc(-.37,-.15).mul(e).mul(r)))),h=h.add(s(t.add(sc(-.29,-.29).mul(e).mul(r)))),h=h.add(s(t.add(sc(.15,-.37).mul(e).mul(r)))),h=h.add(s(t.add(sc(.15,.37).mul(e).mul(n)))),h=h.add(s(t.add(sc(-.37,.15).mul(e).mul(n)))),h=h.add(s(t.add(sc(.37,-.15).mul(e).mul(n)))),h=h.add(s(t.add(sc(-.15,-.37).mul(e).mul(n)))),h=h.add(s(t.add(sc(-.15,.37).mul(e).mul(n)))),h=h.add(s(t.add(sc(.37,.15).mul(e).mul(n)))),h=h.add(s(t.add(sc(-.37,-.15).mul(e).mul(n)))),h=h.add(s(t.add(sc(.15,-.37).mul(e).mul(n)))),h=h.add(s(t.add(sc(.29,.29).mul(e).mul(o)))),h=h.add(s(t.add(sc(.4,0).mul(e).mul(o)))),h=h.add(s(t.add(sc(.29,-.29).mul(e).mul(o)))),h=h.add(s(t.add(sc(0,-.4).mul(e).mul(o)))),h=h.add(s(t.add(sc(-.29,.29).mul(e).mul(o)))),h=h.add(s(t.add(sc(-.4,0).mul(e).mul(o)))),h=h.add(s(t.add(sc(-.29,-.29).mul(e).mul(o)))),h=h.add(s(t.add(sc(0,.4).mul(e).mul(o)))),h=h.add(s(t.add(sc(.29,.29).mul(e).mul(a)))),h=h.add(s(t.add(sc(.4,0).mul(e).mul(a)))),h=h.add(s(t.add(sc(.29,-.29).mul(e).mul(a)))),h=h.add(s(t.add(sc(0,-.4).mul(e).mul(a)))),h=h.add(s(t.add(sc(-.29,.29).mul(e).mul(a)))),h=h.add(s(t.add(sc(-.4,0).mul(e).mul(a)))),h=h.add(s(t.add(sc(-.29,-.29).mul(e).mul(a)))),h=h.add(s(t.add(sc(0,.4).mul(e).mul(a)))),h=h.div(41),h.a=1,uc(h)}))()}}vR.type=Ql("DepthOfField",vR);const TR=(e,t,s=1,i=.025,r=1)=>Du(new vR(nA(e),Du(t),Du(s),Du(i),Du(r)));class _R extends iu{constructor(e,t=new Qs(.5,.5),s=1.57,i=1){super("vec4"),this.inputNode=e,this.center=Cc(t),this.angle=Cc(s),this.scale=Cc(i)}setup(){const e=this.inputNode,t=ju((()=>{const e=ep(this.angle),t=tp(this.angle),s=Um().mul(Yy).sub(this.center),i=sc(t.mul(s.x).sub(e.mul(s.y)),e.mul(s.x).add(t.mul(s.y))).mul(this.scale);return ep(i.x).mul(ep(i.y)).mul(4)})),s=ju((()=>{const s=e,i=dd(s.r,s.g,s.b).div(3);return uc(oc(i.mul(10).sub(5).add(t())),s.a)}));return s()}}_R.type=Ql("DotScreen",_R);const wR=(e,t,s,i)=>Du(new _R(Du(e),t,s,i));class SR extends iu{constructor(e,t=.005,s=0){super("vec4"),this.textureNode=e,this.amount=Cc(t),this.angle=Cc(s)}setup(){const{textureNode:e}=this,t=e.uvNode||Um(),s=t=>e.uv(t);return ju((()=>{const e=sc(tp(this.angle),ep(this.angle)).mul(this.amount),i=s(t.add(e)),r=s(t),n=s(t.sub(e));return uc(i.r,r.g,n.b,r.a)}))()}}SR.type=Ql("RGBShift",SR);const MR=(e,t,s)=>Du(new SR(nA(e),t,s));class AR extends iu{constructor(e,t=null,s=null){super(),this.inputNode=e,this.intensityNode=t,this.uvNode=s}setup(){const e=this.uvNode||Um(),t=ju((()=>{const t=this.inputNode.rgb,s=Gp(Qd(e.add(vM())));let i=t.add(t.mul(Lp(s.add(.1),0,1)));return null!==this.intensityNode&&(i=Up(t,i,this.intensityNode)),uc(i,this.inputNode.a)}));return t()}}AR.type=Ql("Film",AR);const NR=Wu(AR);class RR extends iu{constructor(e,t,s,i){super(),this.inputNode=e,this.lutNode=t,this.size=Cc(s),this.intensityNode=i}setup(){const{inputNode:e,lutNode:t}=this,s=ju((()=>{const s=e,i=Ku(1).div(this.size),r=Ku(.5).div(this.size),n=oc(r).add(s.rgb.mul(Ku(1).sub(i))),o=uc((e=>t.uv(e))(n).rgb,s.a);return uc(Up(s,o,this.intensityNode))}));return s()}}RR.type=Ql("Lut3D",RR);const CR=(e,t,s,i)=>Du(new RR(Du(e),Du(t),s,Du(i))),ER=new tA,BR=new Yr,IR=new Qs;class PR extends iu{constructor(e,t,s){super(),this.depthNode=e,this.normalNode=t,this.radius=Cc(.25),this.resolution=Cc(new Qs),this.thickness=Cc(1),this.distanceExponent=Cc(1),this.distanceFallOff=Cc(1),this.scale=Cc(1),this.noiseNode=Gm(function(e=5){const t=Math.floor(e)%2==0?Math.floor(e)+1:Math.floor(e),s=function(e){const t=Math.floor(e)%2==0?Math.floor(e)+1:Math.floor(e),s=t*t,i=Array(s).fill(0);let r=Math.floor(t/2),n=t-1;for(let e=1;e<=s;)-1===r&&n===t?(n=t-2,r=0):(n===t&&(n=0),r<0&&(r=t-1)),0===i[r*t+n]?(i[r*t+n]=e++,n++,r--):(n-=2,r++);return i}(t),i=s.length,r=new Uint8Array(4*i);for(let e=0;ethis.depthNode.uv(e).x,i=e=>this.noiseNode.uv(e),r=ju((([e])=>{const t=this.cameraProjectionMatrix.mul(uc(e,1));let i=t.xy.div(t.w).mul(.5).add(.5).toVar();i=sc(i.x,i.y.oneMinus());const r=s(i);return oc(i,r)})),n=ju((([e,t])=>{e=sc(e.x,e.y.oneMinus()).mul(2).sub(1);const s=uc(oc(e,t),1),i=uc(this.cameraProjectionMatrixInverse.mul(s));return i.xyz.div(i.w)})),o=ju((()=>{const e=s(t);e.greaterThanEqual(1).discard();const o=n(t,e),a=this.normalNode.rgb.normalize(),h=this.radius,l=Om(this.noiseNode,0);let u=sc(t.x,t.y.oneMinus());u=u.mul(this.resolution.div(l));const c=i(u),d=c.xyz.mul(2).sub(1),p=oc(d.xy,0).normalize(),m=oc(p.y.mul(-1),p.x,0),g=gc(p,m,oc(0,0,1)),f=this.SAMPLES.lessThan(30).select(3,5),y=dd(this.SAMPLES,f.sub(1)).div(f),x=Ku(0).toVar();return Cy({start:Qu(0),end:f,type:"int",condition:"<"},(({i:e})=>{const t=Ku(e).div(Ku(f)).mul(Ld),s=uc(tp(t),ep(t),0,dd(.5,md(.5,c.w)));s.xyz=Kd(g.mul(s.xyz));const i=Kd(o.xyz.negate()),l=Kd(Rp(s.xyz,i)),u=Rp(l,i),d=Kd(a.sub(l.mul(Np(a,l)))),p=Rp(d,l),m=sc(Np(i,p),Np(i,p.negate())).toVar();Cy({end:y,type:"int",name:"j",condition:"<"},(({j:e})=>{const t=s.xyz.mul(h).mul(s.w).mul(Cp(gd(Ku(e).add(1),Ku(y)),this.distanceExponent)),a=r(o.add(t)),l=n(a.xy,a.z).sub(o);Yu(op(l.z).lessThan(this.thickness),(()=>{const t=Np(i,Kd(l));m.x.addAssign(Tp(0,md(t.sub(m.x),Up(1,Ku(2).div(Ku(e).add(2)),this.distanceFallOff))))}));const u=r(o.sub(t)),c=n(u.xy,u.z).sub(o);Yu(op(c.z).lessThan(this.thickness),(()=>{const t=Np(i,Kd(c));m.y.addAssign(Tp(0,md(t.sub(m.y),Up(1,Ku(2).div(Ku(e).add(2)),this.distanceFallOff))))}))}));const b=Xd(pd(1,m.mul(m))),v=Np(d,u),T=Np(d,i),_=md(.5,rp(m.y).sub(rp(m.x)).add(b.x.mul(m.x).sub(b.y.mul(m.y)))),w=md(.5,pd(2,m.x.mul(m.x)).sub(m.y.mul(m.y))),S=v.mul(_).add(T.mul(w));x.addAssign(S)})),x.assign(Lp(x.div(f),0,1)),x.assign(Cp(x,this.scale)),uc(oc(x),1)})),a=this._material||(this._material=new xx);return a.fragmentNode=o().context(e.getSharedContext()),a.name="GTAO",a.needsUpdate=!0,this._textureNode}dispose(){this._aoRenderTarget.dispose()}}PR.type=Ql("GTAO",PR);const FR=(e,t,s)=>Du(new PR(Du(e),Du(t),s));class zR extends iu{constructor(e,t,s,i,r){super(),this.textureNode=e,this.depthNode=t,this.normalNode=s,this.noiseNode=i,this.cameraProjectionMatrixInverse=Cc(r.projectionMatrixInverse),this.lumaPhi=Cc(5),this.depthPhi=Cc(5),this.normalPhi=Cc(5),this.radius=Cc(5),this.index=Cc(0),this._resolution=Cc(new Qs),this._sampleVectors=Xg(function(e,t,s){const i=function(e,t,s){const i=[];for(let r=0;rthis.textureNode.uv(e),s=e=>this.depthNode.uv(e).x,i=e=>this.normalNode.uv(e),r=e=>this.noiseNode.uv(e),n=ju((([e,t])=>{e=sc(e.x,e.y.oneMinus()).mul(2).sub(1);const s=uc(oc(e,t),1),i=uc(this.cameraProjectionMatrixInverse.mul(s));return i.xyz.div(i.w)})),o=ju((([e,r,o,a])=>{const h=t(a),l=s(a),u=i(a).rgb.normalize(),c=h.rgb,d=n(a,l),p=Np(r,u).toVar(),m=Cp(Tp(p,0),this.normalPhi).toVar(),g=op(pR(c).sub(pR(e))).toVar(),f=Tp(Ku(1).sub(g.div(this.lumaPhi)),0).toVar(),y=op(Np(o.sub(d),r)).toVar(),x=Tp(Ku(1).sub(y.div(this.depthPhi)),0),b=f.mul(x).mul(m);return uc(c.mul(b),b)})),a=ju((([e])=>{const a=s(e),h=i(e).rgb.normalize(),l=t(e);Yu(a.greaterThanEqual(1).or(Np(h,h).equal(0)),(()=>l));const u=oc(l.rgb),c=n(e,a),d=Om(this.noiseNode,0);let p=sc(e.x,e.y.oneMinus());p=p.mul(this._resolution.div(d));const m=r(p),g=ep(m.element(this.index.mod(4).mul(2).mul(Ld))),f=tp(m.element(this.index.mod(4).mul(2).mul(Ld))),y=sc(g,f),x=mc(y.x,y.y.negate(),y.x,y.y),b=Ku(1).toVar(),v=oc(l.rgb).toVar();return Cy({start:Qu(0),end:Qu(16),type:"int",condition:"<"},(({i:t})=>{const s=this._sampleVectors.element(t).toVar(),i=x.mul(s.xy.mul(Ku(1).add(s.z.mul(this.radius.sub(1))))).div(this._resolution).toVar(),r=e.add(i).toVar(),n=o(u,h,c,r);v.addAssign(n.xyz),b.addAssign(n.w)})),Yu(b.greaterThan(Ku(0)),(()=>{v.divAssign(b)})),uc(v,l.a)})).setLayout({name:"denoise",type:"vec4",inputs:[{name:"uv",type:"vec2"}]});return ju((()=>a(e)))()}}zR.type=Ql("Denoise",zR);const UR=(e,t,s,i,r)=>Du(new zR(nA(e),Du(t),Du(s),Du(i),r));class LR extends iu{constructor(e){super(),this.textureNode=e,this.updateBeforeType=Hl.RENDER,this._invSize=Cc(new Qs)}updateBefore(){const e=this.textureNode.value;this._invSize.value.set(1/e.image.width,1/e.image.height)}setup(){const e=this.textureNode.bias(-100),t=e.uvNode||Um(),s=t=>e.uv(t),i=(t,s,i)=>e.uv(t.add(s.mul(i))),r=Qu(5),n=ju((([e,t])=>{const s=uc(t).toVar(),i=uc(e).toVar(),r=uc(op(i.sub(s))).toVar();return Tp(Tp(Tp(r.r,r.g),r.b),r.a)})),o=ju((([e,t,o,a])=>{const h=s(e).toVar(),l=i(e,sc(0,-1),t.xy).toVar(),u=i(e,sc(1,0),t.xy).toVar(),c=i(e,sc(0,1),t.xy).toVar(),d=i(e,sc(-1,0),t.xy).toVar(),p=n(h,c).toVar(),m=n(h,l).toVar(),g=n(h,u).toVar(),f=n(h,d).toVar(),y=Tp(p,Tp(m,Tp(g,f))).toVar();Yu(y.lessThan(o),(()=>h));const x=pd(p.add(m),g.add(f)).toVar();x.mulAssign(a),Yu(op(x).lessThan(.3),(()=>{const s=g.greaterThan(f).select(1,-1).toVar(),r=m.greaterThan(p).select(1,-1).toVar(),o=sc(s,r).toVar(),y=i(e,sc(o.x,o.y),t.xy),b=n(h,y).toVar(),v=i(e,sc(o.x.negate(),o.y.negate()),t.xy),T=n(h,v).toVar();x.assign(T.sub(b)),x.mulAssign(a),Yu(op(x).lessThan(.3),(()=>{const e=c.add(l).add(u).add(d);return Up(h,e.mul(.25),.4)}))}));const b=sc().toVar();Yu(x.lessThanEqual(0),(()=>{c.assign(d),l.assign(u),b.x.assign(0),b.y.assign(t.y)})).Else((()=>{b.x.assign(t.x),b.y.assign(0)}));const v=n(h,c).toVar(),T=n(h,l).toVar();Yu(v.lessThanEqual(T),(()=>{c.assign(l)}));const _=Qu(0).toVar(),w=Qu(0).toVar(),S=Ku(0).toVar(),M=Ku(0).toVar(),A=sc(e).toVar(),N=sc(e).toVar(),R=Qu(0).toVar(),C=Qu(0).toVar();Cy(r,(({i:t})=>{const i=t.add(1).toVar();Yu(_.equal(0),(()=>{S.addAssign(i),A.assign(e.add(b.mul(S)));const r=s(A.xy),o=n(r,h).toVar(),a=n(r,c).toVar();Yu(o.greaterThan(a),(()=>{_.assign(1)})),R.assign(t)})),Yu(w.equal(0),(()=>{M.addAssign(i),N.assign(e.sub(b.mul(M)));const r=s(N.xy),o=n(r,h).toVar(),a=n(r,c).toVar();Yu(o.greaterThan(a),(()=>{w.assign(1)})),C.assign(t)})),Yu(_.equal(1).or(w.equal(1)),(()=>{By()}))})),Yu(_.equal(0).and(w.equal(0)),(()=>h));const E=Ku(1).toVar(),B=Ku(1).toVar();Yu(_.equal(1),(()=>{E.assign(Ku(R).div(Ku(r.sub(1))))})),Yu(w.equal(1),(()=>{B.assign(Ku(C).div(Ku(r.sub(1))))}));const I=vp(E,B);return I.assign(Cp(I,.5)),I.assign(Ku(1).sub(I)),Up(h,c,I.mul(.5))})).setLayout({name:"FxaaPixelShader",type:"vec4",inputs:[{name:"uv",type:"vec2"},{name:"fxaaQualityRcpFrame",type:"vec2"},{name:"fxaaQualityEdgeThreshold",type:"float"},{name:"fxaaQualityinvEdgeThreshold",type:"float"}]});return ju((()=>{const e=Ku(.2),s=Ku(1).div(e);return o(t,this._invSize,e,s)}))()}}LR.type=Ql("FXAA",LR);const OR=e=>Du(new LR(nA(e))),VR=new tA,DR=new Yr(0,0,0),kR=new Yr,GR=new Qs,WR=new Qs(1,0),HR=new Qs(0,1);class jR extends iu{constructor(e,t=1,s=0,i=0){super(),this.inputNode=e,this.strength=Cc(t),this.radius=Cc(s),this.threshold=Cc(i),this.smoothWidth=Cc(.01),this._renderTargetsHorizontal=[],this._renderTargetsVertical=[],this._nMips=5,this._renderTargetBright=new wi(1,1,{type:Pe}),this._renderTargetBright.texture.name="UnrealBloomPass.bright",this._renderTargetBright.texture.generateMipmaps=!1;for(let e=0;e{const e=this.inputNode,t=pR(e.rgb),s=Dp(this.threshold,this.threshold.add(this.smoothWidth),t);return Up(uc(0),e,s)}));this._highPassFilterMaterial=this._highPassFilterMaterial||new xx,this._highPassFilterMaterial.fragmentNode=t().context(e.getSharedContext()),this._highPassFilterMaterial.name="Bloom_highPass",this._highPassFilterMaterial.needsUpdate=!0;const s=[3,5,7,9,11];for(let t=0;t{const s=Ku(1.2).sub(e);return Up(e,s,t)})).setLayout({name:"lerpBloomFactor",type:"float",inputs:[{name:"factor",type:"float"},{name:"radius",type:"float"}]}),o=ju((()=>{const e=n(i.element(0),this.radius).mul(uc(r.element(0),1)).mul(this._textureNodeBlur0),t=n(i.element(1),this.radius).mul(uc(r.element(1),1)).mul(this._textureNodeBlur1),s=n(i.element(2),this.radius).mul(uc(r.element(2),1)).mul(this._textureNodeBlur2),o=n(i.element(3),this.radius).mul(uc(r.element(3),1)).mul(this._textureNodeBlur3),a=n(i.element(4),this.radius).mul(uc(r.element(4),1)).mul(this._textureNodeBlur4);return e.add(t).add(s).add(o).add(a).mul(this.strength)}));return this._compositeMaterial=this._compositeMaterial||new xx,this._compositeMaterial.fragmentNode=o().context(e.getSharedContext()),this._compositeMaterial.name="Bloom_comp",this._compositeMaterial.needsUpdate=!0,this._textureOutput}dispose(){for(let e=0;ei.uv(e),l=ju((()=>{const e=r.element(0).toVar(),s=h(a).rgb.mul(e).toVar();return Cy({start:Qu(1),end:Qu(t),type:"int",condition:"<"},(({i:t})=>{const i=Ku(t),l=r.element(t),u=o.mul(n).mul(i),c=h(a.add(u)).rgb,d=h(a.sub(u)).rgb;s.addAssign(dd(c,d).mul(l)),e.addAssign(Ku(2).mul(l))})),uc(s.div(e),1)})),u=new xx;return u.fragmentNode=l().context(e.getSharedContext()),u.name="Bloom_seperable",u.needsUpdate=!0,u.colorTexture=i,u.direction=o,u.invSize=n,u}}const qR=(e,t,s,i)=>Du(new jR(Du(e),t,s,i));class $R extends iu{constructor(e,t,s,i,r,n){super(),this.textureNodeA=e,this.textureNodeB=t,this.mixTextureNode=s,this.mixRatioNode=i,this.thresholdNode=r,this.useTextureNode=n}setup(){const{textureNodeA:e,textureNodeB:t,mixTextureNode:s,mixRatioNode:i,thresholdNode:r,useTextureNode:n}=this,o=e=>{const t=e.uvNode||Um();return e.uv(t)},a=ju((()=>{const a=o(e),h=o(t),l=uc().toVar();return Yu(n.equal(Qu(1)),(()=>{const e=o(s),t=i.mul(r.mul(2).add(1)).sub(r),n=Lp(pd(e.r,t).mul(Ku(1).div(r)),0,1);l.assign(Up(a,h,n))})).Else((()=>{l.assign(Up(h,a,i))})),l}));return a()}}$R.type=Ql("Transition",$R);const XR=(e,t,s,i=0,r=.1,n=0)=>Du(new $R(nA(e),nA(t),nA(s),Du(i),Du(r),Du(n)));class YR extends iu{constructor(e,t,s,i,r,n){super(),this.textureNode=e,this.depthNode=t,this.normalNode=s,this.pixelSize=i,this.normalEdgeStrength=r,this.depthEdgeStrength=n,this._resolution=Cc(new _i),this.updateBeforeType=Hl.RENDER}updateBefore(){const e=this.textureNode.value,t=e.image.width,s=e.image.height;this._resolution.value.set(t,s,1/t,1/s)}setup(){const{textureNode:e,depthNode:t,normalNode:s}=this,i=e.uvNode||Um(),r=t.uvNode||Um(),n=s.uvNode||Um(),o=(e,s)=>t.uv(r.add(sc(e,s).mul(this._resolution.zw))).r,a=(e,t)=>s.uv(n.add(sc(e,t).mul(this._resolution.zw))).rgb.normalize(),h=(e,t,s,i)=>{const r=o(e,t).sub(s),n=a(e,t),h=oc(1,1,1),l=Np(i.sub(n),h),u=Lp(Dp(-.01,.01,l),0,1),c=Lp(ap(r.mul(.25).add(.0025)),0,1);return Ku(1).sub(Np(i,n)).mul(c).mul(u)},l=ju((()=>{const t=e.uv(i),s=Bc("float","depth"),r=Bc("vec3","normal");Yu(this.depthEdgeStrength.greaterThan(0).or(this.normalEdgeStrength.greaterThan(0)),(()=>{s.assign(o(0,0)),r.assign(a(0,0))}));const n=Bc("float","dei");Yu(this.depthEdgeStrength.greaterThan(0),(()=>{n.assign((e=>{const t=Bc("float","diff");return t.addAssign(Lp(o(1,0).sub(e))),t.addAssign(Lp(o(-1,0).sub(e))),t.addAssign(Lp(o(0,1).sub(e))),t.addAssign(Lp(o(0,-1).sub(e))),Jd(Dp(.01,.02,t).mul(2)).div(2)})(s))}));const l=Bc("float","nei");Yu(this.normalEdgeStrength.greaterThan(0),(()=>{l.assign(((e,t)=>{const s=Bc("float","indicator");return s.addAssign(h(0,-1,e,t)),s.addAssign(h(0,1,e,t)),s.addAssign(h(-1,0,e,t)),s.addAssign(h(1,0,e,t)),wp(.1,s)})(s,r))}));const u=n.greaterThan(0).select(Ku(1).sub(n.mul(this.depthEdgeStrength)),l.mul(this.normalEdgeStrength).add(1));return t.mul(u)}));return l()}}YR.type=Ql("Pixelation",YR);class JR extends JN{constructor(e,t,s=6,i=.3,r=.4){super("color",e,t,{minFilter:fe,magFilter:fe}),this.pixelSize=s,this.normalEdgeStrength=i,this.depthEdgeStrength=r,this.isPixelationPassNode=!0,this._mrt=gM({output:Zc,normal:Ig})}setSize(e,t){const s=this.pixelSize.value?this.pixelSize.value:this.pixelSize,i=Math.floor(e/s),r=Math.floor(t/s);super.setSize(i,r)}setup(){return((e,t,s,i=6,r=.3,n=.4)=>Du(new YR(nA(e),nA(t),nA(s),Du(i),Du(r),Du(n))))(super.getTextureNode("output"),super.getTextureNode("depth"),super.getTextureNode("normal"),this.pixelSize,this.normalEdgeStrength,this.depthEdgeStrength)}}const ZR=(e,t,s,i,r)=>Du(new JR(e,t,s,i,r));JR.type=Ql("PixelationPass",JR);const KR=new Qs;class QR extends JN{constructor(e,t){super(JN.COLOR,e,t),this.isSSAAPassNode=!0,this.sampleLevel=4,this.unbiased=!0,this.clearColor=new Yr(0),this.clearAlpha=0,this._currentClearColor=new Yr,this.sampleWeight=Cc(1),this.sampleRenderTarget=null,this._quadMesh=new tA}updateBefore(e){const{renderer:t}=e,{scene:s,camera:i}=this;this._pixelRatio=t.getPixelRatio();const r=t.getSize(KR);this.setSize(r.width,r.height),this.sampleRenderTarget.setSize(this.renderTarget.width,this.renderTarget.height),t.getClearColor(this._currentClearColor);const n=t.getClearAlpha(),o=t.getRenderTarget(),a=t.getMRT(),h=t.autoClear;this._cameraNear.value=i.near,this._cameraFar.value=i.far,t.setMRT(this.getMRT()),t.autoClear=!1;const l=eC[Math.max(0,Math.min(this.sampleLevel,5))],u=1/l.length,c={fullWidth:this.renderTarget.width,fullHeight:this.renderTarget.height,offsetX:0,offsetY:0,width:this.renderTarget.width,height:this.renderTarget.height},d=Object.assign({},i.view);d.enabled&&Object.assign(c,d);for(let e=0;e=0&&(e[t]=Gm(this.sampleRenderTarget.textures[s]).mul(this.sampleWeight))}t=gM(e)}else t=Gm(this.sampleRenderTarget.texture).mul(this.sampleWeight);return this._quadMesh.material=new xx,this._quadMesh.material.fragmentNode=t,this._quadMesh.material.transparent=!0,this._quadMesh.material.depthTest=!1,this._quadMesh.material.depthWrite=!1,this._quadMesh.material.premultipliedAlpha=!0,this._quadMesh.material.blending=2,this._quadMesh.material.normals=!1,this._quadMesh.material.name="SSAA",super.setup(e)}dispose(){super.dispose(),null!==this.sampleRenderTarget&&this.sampleRenderTarget.dispose()}}QR.type=Ql("SSAAPass",QR);const eC=[[[0,0]],[[4,4],[-4,-4]],[[-2,-6],[6,-2],[-6,2],[2,6]],[[1,-3],[-1,3],[5,1],[-3,-5],[-5,5],[-7,-1],[3,7],[7,-7]],[[1,1],[-1,-3],[-3,2],[4,-1],[-5,-2],[2,5],[5,3],[3,-5],[-2,6],[0,-7],[-4,-6],[-6,4],[-8,0],[7,-4],[6,7],[-7,-8]],[[-4,-7],[-7,-5],[-3,-5],[-5,-4],[-1,-4],[-2,-2],[-6,-1],[-4,0],[-7,1],[-1,2],[-6,3],[-3,3],[-7,6],[-3,6],[-5,7],[-1,7],[5,-7],[1,-6],[6,-5],[4,-4],[2,-3],[7,-2],[1,-1],[4,-1],[2,1],[6,2],[0,4],[4,4],[2,5],[7,5],[5,6],[3,7]]],tC=(e,t)=>Du(new QR(e,t)),sC=new Qs;class iC extends JN{constructor(e,t){super(JN.COLOR,e,t),this.isStereoPassNode=!0,this.stereo=new o_,this.stereo.aspect=.5}updateBefore(e){const{renderer:t}=e,{scene:s,camera:i,stereo:r,renderTarget:n}=this;this._pixelRatio=t.getPixelRatio(),r.cameraL.coordinateSystem=t.coordinateSystem,r.cameraR.coordinateSystem=t.coordinateSystem,r.update(i);const o=t.getSize(sC);this.setSize(o.width,o.height);const a=t.autoClear;t.autoClear=!1;const h=t.getRenderTarget(),l=t.getMRT();this._cameraNear.value=i.near,this._cameraFar.value=i.far;for(const e in this._previousTextures)this.toggleTexture(e);t.setRenderTarget(n),t.setMRT(this._mrt),t.clear(),n.scissorTest=!0,n.scissor.set(0,0,n.width/2,n.height),n.viewport.set(0,0,n.width/2,n.height),t.render(s,r.cameraL),n.scissor.set(n.width/2,0,n.width/2,n.height),n.viewport.set(n.width/2,0,n.width/2,n.height),t.render(s,r.cameraR),n.scissorTest=!1,t.setRenderTarget(h),t.setMRT(l),t.autoClear=a}}iC.type=Ql("StereoPass",iC);const rC=(e,t)=>Du(new iC(e,t)),nC=new Qs,oC=new tA;class aC extends JN{constructor(e,t){super(JN.COLOR,e,t),this.isStereoCompositePassNode=!0,this.stereo=new o_;const s={minFilter:Te,magFilter:fe,type:Pe};this._renderTargetL=new wi(1,1,s),this._renderTargetR=new wi(1,1,s),this._mapLeft=Gm(this._renderTargetL.texture),this._mapRight=Gm(this._renderTargetR.texture),this._material=null}updateStereoCamera(e){this.stereo.cameraL.coordinateSystem=e,this.stereo.cameraR.coordinateSystem=e,this.stereo.update(this.camera)}setSize(e,t){super.setSize(e,t),this._renderTargetL.setSize(this.renderTarget.width,this.renderTarget.height),this._renderTargetR.setSize(this.renderTarget.width,this.renderTarget.height)}updateBefore(e){const{renderer:t}=e,{scene:s,stereo:i,renderTarget:r}=this;this._pixelRatio=t.getPixelRatio(),this.updateStereoCamera(t.coordinateSystem);const n=t.getSize(nC);this.setSize(n.width,n.height);const o=t.getRenderTarget();t.setRenderTarget(this._renderTargetL),t.render(s,i.cameraL),t.setRenderTarget(this._renderTargetR),t.render(s,i.cameraR),t.setRenderTarget(r),oC.material=this._material,oC.render(t),t.setRenderTarget(o)}dispose(){super.dispose(),this._renderTargetL.dispose(),this._renderTargetR.dispose(),null!==this._material&&this._material.dispose()}}aC.type=Ql("StereoCompositePass",aC);class hC extends aC{constructor(e,t){super(e,t),this.isAnaglyphPassNode=!0,this._colorMatrixLeft=Cc((new ei).fromArray([.4561,-.0400822,-.0152161,.500484,-.0378246,-.0205971,.176381,-.0157589,-.00546856])),this._colorMatrixRight=Cc((new ei).fromArray([-.0434706,.378476,-.0721527,-.0879388,.73364,-.112961,-.00155529,-.0184503,1.2264]))}setup(e){const t=Um(),s=ju((()=>{const e=this._mapLeft.uv(t),s=this._mapRight.uv(t),i=Lp(this._colorMatrixLeft.mul(e.rgb).add(this._colorMatrixRight.mul(s.rgb)));return uc(i.rgb,Tp(e.a,s.a))})),i=this._material||(this._material=new xx);return i.fragmentNode=s().context(e.getSharedContext()),i.name="Anaglyph",i.needsUpdate=!0,super.setup(e)}}const lC=(e,t)=>Du(new hC(e,t));class uC extends aC{constructor(e,t){super(e,t),this.isParallaxBarrierPassNode=!0}setup(e){const t=Um(),s=ju((()=>{const e=uc().toVar();return Yu(_p(Xy.y,2).greaterThan(1),(()=>{e.assign(this._mapLeft.uv(t))})).Else((()=>{e.assign(this._mapRight.uv(t))})),e})),i=this._material||(this._material=new xx);return i.fragmentNode=s().context(e.getSharedContext()),i.needsUpdate=!0,super.setup(e)}}uC.type=Ql("ParallaxBarrierPass",uC);const cC=(e,t)=>Du(new uC(e,t));class dC extends Kl{constructor(e=null){super(),this._value=e,this._cache=null,this.inputType=null,this.outpuType=null,this.events=new ks,this.isScriptableValueNode=!0}get isScriptableOutputNode(){return null!==this.outputType}set value(e){this._value!==e&&(this._cache&&"URL"===this.inputType&&this.value.value instanceof ArrayBuffer&&(URL.revokeObjectURL(this._cache),this._cache=null),this._value=e,this.events.dispatchEvent({type:"change"}),this.refresh())}get value(){return this._value}refresh(){this.events.dispatchEvent({type:"refresh"})}getValue(){const e=this.value;if(e&&null===this._cache&&"URL"===this.inputType&&e.value instanceof ArrayBuffer)this._cache=URL.createObjectURL(new Blob([e.value]));else if(e&&null!==e.value&&void 0!==e.value&&(("URL"===this.inputType||"String"===this.inputType)&&"string"==typeof e.value||"Number"===this.inputType&&"number"==typeof e.value||"Vector2"===this.inputType&&e.value.isVector2||"Vector3"===this.inputType&&e.value.isVector3||"Vector4"===this.inputType&&e.value.isVector4||"Color"===this.inputType&&e.value.isColor||"Matrix3"===this.inputType&&e.value.isMatrix3||"Matrix4"===this.inputType&&e.value.isMatrix4))return e.value;return this._cache||e}getNodeType(e){return this.value&&this.value.isNode?this.value.getNodeType(e):"float"}setup(){return this.value&&this.value.isNode?this.value:Ku()}serialize(e){super.serialize(e),null!==this.value?"ArrayBuffer"===this.inputType?e.value=Dl(this.value):e.value=this.value?this.value.toJSON(e.meta).uuid:null:e.value=null,e.inputType=this.inputType,e.outputType=this.outputType}deserialize(e){super.deserialize(e);let t=null;null!==e.value&&(t="ArrayBuffer"===e.inputType?kl(e.value):"Texture"===e.inputType?e.meta.textures[e.value]:e.meta.nodes[e.value]||null),this.value=t,this.inputType=e.inputType,this.outputType=e.outputType}}dC.type=Ql("ScriptableValue",dC);const pC=Wu(dC);class mC extends Map{get(e,t=null,...s){if(this.has(e))return super.get(e);if(null!==t){const i=t(...s);return this.set(e,i),i}}}class gC{constructor(e){this.scriptableNode=e}get parameters(){return this.scriptableNode.parameters}get layout(){return this.scriptableNode.getLayout()}getInputLayout(e){return this.scriptableNode.getInputLayout(e)}get(e){const t=this.parameters[e];return t?t.getValue():null}}const fC=new mC;class yC extends Kl{constructor(e=null,t={}){super(),this.codeNode=e,this.parameters=t,this._local=new mC,this._output=pC(),this._outputs={},this._source=this.source,this._method=null,this._object=null,this._value=null,this._needsOutputUpdate=!0,this.onRefresh=this.onRefresh.bind(this),this.isScriptableNode=!0}get source(){return this.codeNode?this.codeNode.code:""}setLocal(e,t){return this._local.set(e,t)}getLocal(e){return this._local.get(e)}onRefresh(){this._refresh()}getInputLayout(e){for(const t of this.getLayout())if(t.inputType&&(t.id===e||t.name===e))return t}getOutputLayout(e){for(const t of this.getLayout())if(t.outputType&&(t.id===e||t.name===e))return t}setOutput(e,t){const s=this._outputs;return void 0===s[e]?s[e]=pC(t):s[e].value=t,this}getOutput(e){return this._outputs[e]}getParameter(e){return this.parameters[e]}setParameter(e,t){const s=this.parameters;return t&&t.isScriptableNode?(this.deleteParameter(e),s[e]=t,s[e].getDefaultOutput().events.addEventListener("refresh",this.onRefresh)):t&&t.isScriptableValueNode?(this.deleteParameter(e),s[e]=t,s[e].events.addEventListener("refresh",this.onRefresh)):void 0===s[e]?(s[e]=pC(t),s[e].events.addEventListener("refresh",this.onRefresh)):s[e].value=t,this}getValue(){return this.getDefaultOutput().getValue()}deleteParameter(e){let t=this.parameters[e];return t&&(t.isScriptableNode&&(t=t.getDefaultOutput()),t.events.removeEventListener("refresh",this.onRefresh)),this}clearParameters(){for(const e of Object.keys(this.parameters))this.deleteParameter(e);return this.needsUpdate=!0,this}call(e,...t){const s=this.getObject()[e];if("function"==typeof s)return s(...t)}async callAsync(e,...t){const s=this.getObject()[e];if("function"==typeof s)return"AsyncFunction"===s.constructor.name?await s(...t):s(...t)}getNodeType(e){return this.getDefaultOutputNode().getNodeType(e)}refresh(e=null){null!==e?this.getOutput(e).refresh():this._refresh()}getObject(){if(this.needsUpdate&&this.dispose(),null!==this._object)return this._object;const e=new gC(this),t=fC.get("THREE"),s=fC.get("TSL"),i=this.getMethod(this.codeNode),r=[e,this._local,fC,()=>this.refresh(),(e,t)=>this.setOutput(e,t),t,s];this._object=i(...r);const n=this._object.layout;if(n&&(!1===n.cache&&this._local.clear(),this._output.outputType=n.outputType||null,Array.isArray(n.elements)))for(const e of n.elements){const t=e.id||e.name;e.inputType&&(void 0===this.getParameter(t)&&this.setParameter(t,null),this.getParameter(t).inputType=e.inputType),e.outputType&&(void 0===this.getOutput(t)&&this.setOutput(t,null),this.getOutput(t).outputType=e.outputType)}return this._object}deserialize(e){super.deserialize(e);for(const e in this.parameters){let t=this.parameters[e];t.isScriptableNode&&(t=t.getDefaultOutput()),t.events.addEventListener("refresh",this.onRefresh)}}getLayout(){return this.getObject().layout}getDefaultOutputNode(){const e=this.getDefaultOutput().value;return e&&e.isNode?e:Ku()}getDefaultOutput(){return this._exec()._output}getMethod(){if(this.needsUpdate&&this.dispose(),null!==this._method)return this._method;const e=["layout","init","main","dispose"].join(", "),t="\nreturn { ...output, "+e+" };",s="var "+e+"; var output = {};\n"+this.codeNode.code+t;return this._method=new Function(...["parameters","local","global","refresh","setOutput","THREE","TSL"],s),this._method}dispose(){null!==this._method&&(this._object&&"function"==typeof this._object.dispose&&this._object.dispose(),this._method=null,this._object=null,this._source=null,this._value=null,this._needsOutputUpdate=!0,this._output.value=null,this._outputs={})}setup(){return this.getDefaultOutputNode()}getCacheKey(e){const t=[this.source,this.getDefaultOutputNode().getCacheKey(e)];for(const s in this.parameters)t.push(this.parameters[s].getCacheKey(e));return t.join(",")}set needsUpdate(e){!0===e&&this.dispose()}get needsUpdate(){return this.source!==this._source}_exec(){return null===this.codeNode||(!0===this._needsOutputUpdate&&(this._value=this.call("main"),this._needsOutputUpdate=!1),this._output.value=this._value),this}_refresh(){this.needsUpdate=!0,this._exec(),this._output.refresh()}}yC.type=Ql("Scriptable",yC);const xC=Wu(yC);class bC extends Kl{constructor(e,t){super("float"),this.isFogNode=!0,this.colorNode=e,this.factorNode=t}getViewZNode(e){let t;const s=e.context.getViewZ;return void 0!==s&&(t=s(this)),(t||wg.z).negate()}setup(){return this.factorNode}}bC.type=Ql("Fog",bC);const vC=Wu(bC);class TC extends bC{constructor(e,t,s){super(e),this.isFogRangeNode=!0,this.nearNode=t,this.farNode=s}setup(e){const t=this.getViewZNode(e);return Dp(this.nearNode,this.farNode,t)}}TC.type=Ql("FogRange",TC);const _C=Wu(TC);class wC extends bC{constructor(e,t){super(e),this.isFogExp2Node=!0,this.densityNode=t}setup(e){const t=this.getViewZNode(e),s=this.densityNode;return s.mul(s,t,t).negate().exp().oneMinus()}}wC.type=Ql("FogExp2",wC);const SC=Wu(wC);let MC=null,AC=null;class NC extends Kl{constructor(e=Ku(),t=Ku()){super(),this.minNode=e,this.maxNode=t}getVectorLength(e){const t=e.getTypeLength(Ol(this.minNode.value)),s=e.getTypeLength(Ol(this.maxNode.value));return t>s?t:s}getNodeType(e){return e.object.count>1?e.getTypeFromLength(this.getVectorLength(e)):"float"}setup(e){const t=e.object;let s=null;if(t.count>1){const i=this.minNode.value,r=this.maxNode.value,n=e.getTypeLength(Ol(i)),o=e.getTypeLength(Ol(r));MC=MC||new _i,AC=AC||new _i,MC.setScalar(0),AC.setScalar(0),1===n?MC.setScalar(i):i.isColor?MC.set(i.r,i.g,i.b):MC.set(i.x,i.y,i.z||0,i.w||0),1===o?AC.setScalar(r):r.isColor?AC.set(r.r,r.g,r.b):AC.set(r.x,r.y,r.z||0,r.w||0);const a=4,h=a*t.count,l=new Float32Array(h);for(let e=0;eGm(e,t.xy).compare(t.z))),IC=ju((({depthTexture:e,shadowCoord:t,shadow:s})=>{const i=(t,s)=>Gm(e,t).compare(s),r=Zg("mapSize","vec2",s),n=Zg("radius","float",s),o=sc(1).div(r),a=o.x.negate().mul(n),h=o.y.negate().mul(n),l=o.x.mul(n),u=o.y.mul(n),c=a.div(2),d=h.div(2),p=l.div(2),m=u.div(2);return dd(i(t.xy.add(sc(a,h)),t.z),i(t.xy.add(sc(0,h)),t.z),i(t.xy.add(sc(l,h)),t.z),i(t.xy.add(sc(c,d)),t.z),i(t.xy.add(sc(0,d)),t.z),i(t.xy.add(sc(p,d)),t.z),i(t.xy.add(sc(a,0)),t.z),i(t.xy.add(sc(c,0)),t.z),i(t.xy,t.z),i(t.xy.add(sc(p,0)),t.z),i(t.xy.add(sc(l,0)),t.z),i(t.xy.add(sc(c,m)),t.z),i(t.xy.add(sc(0,m)),t.z),i(t.xy.add(sc(p,m)),t.z),i(t.xy.add(sc(a,u)),t.z),i(t.xy.add(sc(0,u)),t.z),i(t.xy.add(sc(l,u)),t.z)).mul(1/17)})),PC=ju((({depthTexture:e,shadowCoord:t,shadow:s})=>{const i=(t,s)=>Gm(e,t).compare(s),r=Zg("mapSize","vec2",s),n=sc(1).div(r),o=n.x,a=n.y,h=t.xy,l=Qd(h.mul(r).add(.5));return h.subAssign(l.mul(n)),dd(i(h,t.z),i(h.add(sc(o,0)),t.z),i(h.add(sc(0,a)),t.z),i(h.add(n),t.z),Up(i(h.add(sc(o.negate(),0)),t.z),i(h.add(sc(o.mul(2),0)),t.z),l.x),Up(i(h.add(sc(o.negate(),a)),t.z),i(h.add(sc(o.mul(2),a)),t.z),l.x),Up(i(h.add(sc(0,a.negate())),t.z),i(h.add(sc(0,a.mul(2))),t.z),l.y),Up(i(h.add(sc(o,a.negate())),t.z),i(h.add(sc(o,a.mul(2))),t.z),l.y),Up(Up(i(h.add(sc(o.negate(),a.negate())),t.z),i(h.add(sc(o.mul(2),a.negate())),t.z),l.x),Up(i(h.add(sc(o.negate(),a.mul(2))),t.z),i(h.add(sc(o.mul(2),a.mul(2))),t.z),l.x),l.y)).mul(1/9)})),FC=[BC,IC,PC];let zC=null;class UC extends Dy{constructor(e=null){super(),this.updateType=Hl.FRAME,this.light=e,this.color=new Yr,this.colorNode=Cc(this.color),this.baseColorNode=null,this.shadowMap=null,this.shadowNode=null,this.shadowColorNode=null,this.isAnalyticLightNode=!0}getCacheKey(){return super.getCacheKey()+"-"+this.light.id+"-"+(this.light.castShadow?"1":"0")}getHash(){return this.light.uuid}setupShadow(e){const{object:t,renderer:s}=e;let i=this.shadowColorNode;if(null===i){null===zC&&(zC=new xx,zC.fragmentNode=uc(0,0,0,1),zC.isShadowNodeMaterial=!0,zC.name="ShadowMaterial");const r=new Qa;r.compareFunction=Ts;const n=this.light.shadow,o=e.createRenderTarget(n.mapSize.width,n.mapSize.height);o.depthTexture=r,n.camera.updateProjectionMatrix();const a=Zg("intensity","float",n),h=Zg("bias","float",n),l=Zg("normalBias","float",n),u=t.material.shadowPositionNode||Tg;let c=Cc(n.matrix).mul(u.add(Pg.mul(l)));c=c.xyz.div(c.w);let d=c.z.add(h);s.coordinateSystem===Ds&&(d=d.mul(2).sub(1)),c=oc(c.x,c.y.oneMinus(),d);const p=c.x.greaterThanEqual(0).and(c.x.lessThanEqual(1)).and(c.y.greaterThanEqual(0)).and(c.y.lessThanEqual(1)).and(c.z.lessThanEqual(1)),m=n.filterNode||FC[s.shadowMap.type]||null;if(null===m)throw new Error("THREE.WebGPURenderer: Shadow map type not supported yet.");const g=Gm(o.texture,c),f=p.select(m({depthTexture:r,shadowCoord:c,shadow:n}),Ku(1));this.shadowMap=o,this.shadowNode=f,this.shadowColorNode=i=this.colorNode.mul(Up(1,f.rgb.mix(g,1),a.mul(g.a))),this.baseColorNode=this.colorNode}this.colorNode=i,this.updateBeforeType=Hl.RENDER}setup(e){this.colorNode=this.baseColorNode||this.colorNode,this.light.castShadow?e.object.receiveShadow&&this.setupShadow(e):null!==this.shadowNode&&this.disposeShadow()}updateShadow(e){const{shadowMap:t,light:s}=this,{renderer:i,scene:r,camera:n}=e,o=t.depthTexture.version;this._depthVersionCached=o;const a=r.overrideMaterial;r.overrideMaterial=zC,t.setSize(s.shadow.mapSize.width,s.shadow.mapSize.height),s.shadow.updateMatrices(s),s.shadow.camera.layers.mask=n.layers.mask;const h=i.getRenderTarget(),l=i.getRenderObjectFunction();i.setRenderObjectFunction(((e,...t)=>{!0===e.castShadow&&i.renderObject(e,...t)})),i.setRenderTarget(t),i.render(r,s.shadow.camera),i.setRenderTarget(h),i.setRenderObjectFunction(l),r.overrideMaterial=a}disposeShadow(){this.shadowMap.dispose(),this.shadowMap=null,this.shadowNode=null,this.shadowColorNode=null,this.baseColorNode=null,this.updateBeforeType=Hl.NONE}updateBefore(e){const t=this.light.shadow;(t.needsUpdate||t.autoUpdate)&&(this.updateShadow(e),this.shadowMap.depthTexture.version===this._depthVersionCached&&(t.needsUpdate=!1))}update(){const{light:e}=this;this.color.copy(e.color).multiplyScalar(e.intensity)}}UC.type=Ql("AnalyticLight",UC);const LC=ju((e=>{const{lightDistance:t,cutoffDistance:s,decayExponent:i}=e,r=t.pow(i).max(.01).reciprocal();return s.greaterThan(0).select(r.mul(t.div(s).pow4().oneMinus().clamp().pow2()),r)}));class OC extends UC{constructor(e=null){super(e),this.cutoffDistanceNode=Cc(0),this.decayExponentNode=Cc(0)}update(e){const{light:t}=this;super.update(e),this.cutoffDistanceNode.value=t.distance,this.decayExponentNode.value=t.decay}setup(e){const{colorNode:t,cutoffDistanceNode:s,decayExponentNode:i,light:r}=this,n=e.context.lightingModel,o=hg(r).sub(wg),a=o.normalize(),h=o.length(),l=LC({lightDistance:h,cutoffDistance:s,decayExponent:i}),u=t.mul(l),c=e.context.reflectedLight;n.direct({lightDirection:a,lightColor:u,reflectedLight:c},e.stack,e)}}OC.type=Ql("PointLight",OC);class VC extends UC{constructor(e=null){super(e)}setup(e){super.setup(e);const t=e.context.lightingModel,s=this.colorNode,i=EC(this.light),r=e.context.reflectedLight;t.direct({lightDirection:i,lightColor:s,reflectedLight:r},e.stack,e)}}VC.type=Ql("DirectionalLight",VC);const DC=new or,kC=new or;let GC=null;class WC extends UC{constructor(e=null){super(e),this.halfHeight=Cc(new Ei),this.halfWidth=Cc(new Ei)}update(e){super.update(e);const{light:t}=this,s=e.camera.matrixWorldInverse;kC.identity(),DC.copy(t.matrixWorld),DC.premultiply(s),kC.extractRotation(DC),this.halfWidth.value.set(.5*t.width,0,0),this.halfHeight.value.set(0,.5*t.height,0),this.halfWidth.value.applyMatrix4(kC),this.halfHeight.value.applyMatrix4(kC)}setup(e){let t,s;super.setup(e),e.isAvailable("float32Filterable")?(t=Gm(GC.LTC_FLOAT_1),s=Gm(GC.LTC_FLOAT_2)):(t=Gm(GC.LTC_HALF_1),s=Gm(GC.LTC_HALF_2));const{colorNode:i,light:r}=this,n=e.context.lightingModel,o=hg(r),a=e.context.reflectedLight;n.directRectArea({lightColor:i,lightPosition:o,halfWidth:this.halfWidth,halfHeight:this.halfHeight,reflectedLight:a,ltc_1:t,ltc_2:s},e.stack,e)}static setLTC(e){GC=e}}WC.type=Ql("RectAreaLight",WC);class HC extends UC{constructor(e=null){super(e),this.coneCosNode=Cc(0),this.penumbraCosNode=Cc(0),this.cutoffDistanceNode=Cc(0),this.decayExponentNode=Cc(0)}update(e){super.update(e);const{light:t}=this;this.coneCosNode.value=Math.cos(t.angle),this.penumbraCosNode.value=Math.cos(t.angle*(1-t.penumbra)),this.cutoffDistanceNode.value=t.distance,this.decayExponentNode.value=t.decay}getSpotAttenuation(e){const{coneCosNode:t,penumbraCosNode:s}=this;return Dp(t,s,e)}setup(e){super.setup(e);const t=e.context.lightingModel,{colorNode:s,cutoffDistanceNode:i,decayExponentNode:r,light:n}=this,o=hg(n).sub(wg),a=o.normalize(),h=a.dot(EC(n)),l=this.getSpotAttenuation(h),u=o.length(),c=LC({lightDistance:u,cutoffDistance:i,decayExponent:r}),d=s.mul(l).mul(c),p=e.context.reflectedLight;t.direct({lightDirection:a,lightColor:d,reflectedLight:p},e.stack,e)}}HC.type=Ql("SpotLight",HC);class jC extends HC{getSpotAttenuation(e){const t=this.light.iesMap;let s=null;if(t&&!0===t.isTexture){const i=e.acos().mul(1/Math.PI);s=Gm(t,sc(i,0),0).r}else s=super.getSpotAttenuation(e);return s}}jC.type=Ql("IESSpotLight",jC);class qC extends UC{constructor(e=null){super(e)}setup({context:e}){e.irradiance.addAssign(this.colorNode)}}qC.type=Ql("AmbientLight",qC);class $C extends UC{constructor(e=null){super(e),this.lightPositionNode=og(e),this.lightDirectionNode=this.lightPositionNode.normalize(),this.groundColorNode=Cc(new Yr)}update(e){const{light:t}=this;super.update(e),this.lightPositionNode.object3d=t,this.groundColorNode.value.copy(t.groundColor).multiplyScalar(t.intensity)}setup(e){const{colorNode:t,groundColorNode:s,lightDirectionNode:i}=this,r=Ig.dot(i).mul(.5).add(.5),n=Up(s,t,r);e.context.irradiance.addAssign(n)}}$C.type=Ql("HemisphereLight",$C);class XC extends UC{constructor(e=null){super(e);const t=[];for(let e=0;e<9;e++)t.push(new Ei);this.lightProbe=Xg(t)}update(e){const{light:t}=this;super.update(e);for(let e=0;e<9;e++)this.lightProbe.array[e].copy(t.sh.coefficients[e]).multiplyScalar(t.intensity)}setup(e){const t=YC(Pg,this.lightProbe);e.context.irradiance.addAssign(t)}}XC.type=Ql("LightProbe",XC);const YC=ju((([e,t])=>{const s=e.x,i=e.y,r=e.z,n=t.element(0).mul(.886227);return n.addAssign(t.element(1).mul(1.023328).mul(i)),n.addAssign(t.element(2).mul(1.023328).mul(r)),n.addAssign(t.element(3).mul(1.023328).mul(s)),n.addAssign(t.element(4).mul(.858086).mul(s).mul(i)),n.addAssign(t.element(5).mul(.858086).mul(i).mul(r)),n.addAssign(t.element(6).mul(r.mul(r).mul(.743125).sub(.247708))),n.addAssign(t.element(7).mul(.858086).mul(s).mul(r)),n.addAssign(t.element(8).mul(.429043).mul(md(s,s).sub(md(i,i)))),n}));class JC{parseFunction(){console.warn("Abstract function.")}}class ZC{constructor(e,t,s="",i=""){this.type=e,this.inputs=t,this.name=s,this.precision=i}getCode(){console.warn("Abstract function.")}}ZC.isNodeFunction=!0;const KC=/^\s*(highp|mediump|lowp)?\s*([a-z_0-9]+)\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)/i,QC=/[a-z_0-9]+/gi,eE="#pragma main";class tE extends ZC{constructor(e){const{type:t,inputs:s,name:i,precision:r,inputsCode:n,blockCode:o,headerCode:a}=(e=>{const t=(e=e.trim()).indexOf(eE),s=-1!==t?e.slice(t+12):e,i=s.match(KC);if(null!==i&&5===i.length){const r=i[4],n=[];let o=null;for(;null!==(o=QC.exec(r));)n.push(o);const a=[];let h=0;for(;h0?this.transparent:this.opaque).push(o)}unshift(e,t,s,i,r,n){const o=this.getNextRenderItem(e,t,s,i,r,n);(!0===s.transparent?this.transparent:this.opaque).unshift(o)}pushBundle(e){this.bundles.push(e)}pushLight(e){this.lightsArray.push(e)}getLightsNode(){return this.lightsNode.fromLights(this.lightsArray)}sort(e,t){this.opaque.length>1&&this.opaque.sort(e||iE),this.transparent.length>1&&this.transparent.sort(t||rE)}finish(){this.lightsNode.setLights(this.lightsArray);for(let e=this.renderItemsIndex,t=this.renderItems.length;e>t,h=o.height>>t;let l=e.depthTexture||r[t],u=!1;void 0===l&&(l=new Qa,l.format=e.stencilBuffer?He:We,l.type=e.stencilBuffer?Ue:Be,l.image.width=a,l.image.height=h,r[t]=l),s.width===o.width&&o.height===s.height||(u=!0,l.needsUpdate=!0,l.image.width=a,l.image.height=h),s.width=o.width,s.height=o.height,s.textures=n,s.depthTexture=l,s.depth=e.depthBuffer,s.stencil=e.stencilBuffer,s.renderTarget=e,s.sampleCount!==i&&(u=!0,l.needsUpdate=!0,s.sampleCount=i);const c={sampleCount:i};for(let e=0;e{e.removeEventListener("dispose",t);for(let e=0;e0){const i=e.image;if(void 0===i)console.warn("THREE.Renderer: Texture marked for update but image is undefined.");else if(!1===i.complete)console.warn("THREE.Renderer: Texture marked for update but image is incomplete.");else{if(e.images){const s=[];for(const t of e.images)s.push(t);t.images=s}else t.image=i;void 0!==s.isDefaultTexture&&!0!==s.isDefaultTexture||(r.createTexture(e,t),s.isDefaultTexture=!1,s.generation=e.version),!0===e.source.dataReady&&r.updateTexture(e,t),t.needsMipmaps&&0===e.mipmaps.length&&r.generateMipmaps(e)}}else r.createDefaultTexture(e),s.isDefaultTexture=!0,s.generation=e.version}if(!0!==s.initialized){s.initialized=!0,s.generation=e.version,this.info.memory.textures++;const t=()=>{e.removeEventListener("dispose",t),this._destroyTexture(e),this.info.memory.textures--};e.addEventListener("dispose",t)}s.version=e.version}getSize(e,t=cE){let s=e.images?e.images[0]:e.image;return s?(void 0!==s.image&&(s=s.image),t.width=s.width,t.height=s.height,t.depth=e.isCubeTexture?6:s.depth||1):t.width=t.height=t.depth=1,t}getMipLevels(e,t,s){let i;return i=e.isCompressedTexture?e.mipmaps.length:Math.floor(Math.log2(Math.max(t,s)))+1,i}needsMipmaps(e){return!!this.isEnvironmentTexture(e)||(!0===e.isCompressedTexture||e.minFilter!==fe&&e.minFilter!==Te)}isEnvironmentTexture(e){const t=e.mapping;return t===ue||t===ce||t===he||t===le}_destroyTexture(e){this.backend.destroySampler(e),this.backend.destroyTexture(e),this.delete(e)}}class pE extends Yr{constructor(e,t,s,i=1){super(e,t,s),this.a=i}set(e,t,s,i=1){return this.a=i,super.set(e,t,s)}copy(e){return void 0!==e.a&&(this.a=e.a),super.copy(e)}clone(){return new this.constructor(this.r,this.g,this.b,this.a)}}const mE=ju((([e])=>{const t=e.toUint().mul(747796405).add(2891336453),s=t.shiftRight(t.shiftRight(28).add(4)).bitXor(t).mul(277803737);return s.shiftRight(22).bitXor(s).toFloat().mul(1/2**32)})),gE=(e,t)=>Cp(md(4,e.mul(pd(1,e))),t),fE=(e,t)=>e.lessThan(.5)?gE(e.mul(2),t).div(2):pd(1,gE(md(pd(1,e),2),t).div(2)),yE=(e,t,s)=>Cp(gd(Cp(e,t),dd(Cp(e,t),Cp(pd(1,e),s))),1/t),xE=(e,t)=>ep(Ld.mul(t.mul(e).sub(1))).div(Ld.mul(t.mul(e).sub(1))),bE=ju((([e])=>e.fract().sub(.5).abs())).setLayout({name:"tri",type:"float",inputs:[{name:"x",type:"float"}]}),vE=ju((([e])=>oc(bE(e.z.add(bE(e.y.mul(1)))),bE(e.z.add(bE(e.x.mul(1)))),bE(e.y.add(bE(e.x.mul(1))))))).setLayout({name:"tri3",type:"vec3",inputs:[{name:"p",type:"vec3"}]}),TE=ju((([e,t,s])=>{const i=oc(e).toVar(),r=Ku(1.4).toVar(),n=Ku(0).toVar(),o=oc(i).toVar();return Cy({start:Ku(0),end:Ku(3),type:"float",condition:"<="},(()=>{const e=oc(vE(o.mul(2))).toVar();i.addAssign(e.add(s.mul(Ku(.1).mul(t)))),o.mulAssign(1.8),r.mulAssign(1.5),i.mulAssign(1.2);const a=Ku(bE(i.z.add(bE(i.x.add(bE(i.y)))))).toVar();n.addAssign(a.div(r)),o.addAssign(.14)})),n})).setLayout({name:"triNoise3D",type:"float",inputs:[{name:"p",type:"vec3"},{name:"spd",type:"float"},{name:"time",type:"float"}]}),_E=ju((([e,t,s=sc(.5)])=>Uv(e.sub(s),t).add(s))),wE=ju((([e,t,s=sc(.5)])=>{const i=e.sub(s),r=i.dot(i),n=r.mul(r).mul(t);return e.add(i.mul(n))})),SE=ju((({position:e=null,horizontal:t=!0,vertical:s=!1})=>{let i;null!==e?(i=pg.toVar(),i[3][0]=e.x,i[3][1]=e.y,i[3][2]=e.z):i=pg;const r=Zm.mul(i);return Lu(t)&&(r[0][0]=pg[0].length(),r[0][1]=0,r[0][2]=0),Lu(s)&&(r[1][0]=0,r[1][1]=pg[1].length(),r[1][2]=0),r[2][0]=0,r[2][1]=0,r[2][2]=1,Ym.mul(r).mul(bg)})),ME=ju((([e=null])=>{const t=mx();return mx(ox(e)).sub(t).lessThan(0).select(Zy,e)})),AE=new WeakMap;class NE extends iu{constructor(){super("vec2"),this.updateType=Hl.OBJECT,this.updateAfterType=Hl.OBJECT,this.previousProjectionMatrix=Cc(new or),this.previousModelViewMatrix=Cc(new or)}update({camera:e,object:t}){const s=RE(t),i=RE(e);this.previousModelViewMatrix.value.copy(s),this.previousProjectionMatrix.value.copy(i)}updateAfter({camera:e,object:t}){const s=RE(t),i=RE(e);s.copy(t.modelViewMatrix),i.copy(e.projectionMatrix)}setup(){const e=Ym.mul(cg).mul(bg),t=this.previousProjectionMatrix.mul(this.previousModelViewMatrix).mul(vg),s=e.xy.div(e.w),i=t.xy.div(t.w);return pd(s,i)}}function RE(e){let t=AE.get(e);return void 0===t&&(t=new or,AE.set(e,t)),t}NE.type=Ql("Velocity",NE);const CE=Hu(NE),EE=ju((([e,t])=>vp(1,e.oneMinus().div(t)).oneMinus())).setLayout({name:"burnBlend",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),BE=ju((([e,t])=>vp(e.div(t.oneMinus()),1))).setLayout({name:"dodgeBlend",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),IE=ju((([e,t])=>e.oneMinus().mul(t.oneMinus()).oneMinus())).setLayout({name:"screenBlend",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),PE=ju((([e,t])=>Up(e.mul(2).mul(t),e.oneMinus().mul(2).mul(t.oneMinus()).oneMinus(),wp(.5,e)))).setLayout({name:"overlayBlend",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),FE=ju((([e,t,s=Qu(16)])=>{const i=t=>e.uv(t),r=Um(),n=i(r).toVar(),o=Ku(s);return Cy({start:Qu(1),end:s,type:"int",condition:"<="},(({i:e})=>{const s=t.mul(Ku(e).div(o.sub(1)).sub(.5));n.addAssign(i(r.add(s)))})),n.divAssign(o),n})),zE=ju((([e,t=1])=>{const s=e,i=pR(s.rgb),r=oc(i),n=vp(1,Tp(0,Ku(10).mul(i.sub(.45)))),o=r.mul(s.rgb).mul(2),a=Ku(2).mul(r.oneMinus()).mul(s.rgb.oneMinus()).oneMinus(),h=Up(o,a,n),l=s.a.mul(t),u=l.mul(h.rgb);return u.addAssign(s.rgb.mul(l.oneMinus())),uc(u,s.a)})),UE=ju((([e])=>{const t=oc(e);return uc(Np(t,oc(.393,.769,.189)),Np(t,oc(.349,.686,.168)),Np(t,oc(.272,.534,.131)),e.a)})),LE=ju((([e])=>{const t=e.mul(.9478672986).add(.0521327014).pow(2.4),s=e.mul(.0773993808),i=e.lessThanEqual(.04045);return Up(t,s,i)})).setLayout({name:"sRGBToLinear",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),OE=ju((([e])=>{const t=e.pow(.41666).mul(1.055).sub(.055),s=e.mul(12.92),i=e.lessThanEqual(.0031308);return Up(t,s,i)})).setLayout({name:"LinearTosRGB",type:"vec3",inputs:[{name:"color",type:"vec3"}]});var VE=Object.freeze({__proto__:null,LinearTosRGB:OE,sRGBToLinear:LE});const DE=ju((([e,t])=>e.mul(t).clamp())).setLayout({name:"LinearToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),kE=ju((([e,t])=>(e=e.mul(t)).div(e.add(1)).clamp())).setLayout({name:"ReinhardToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),GE=ju((([e,t])=>{const s=(e=(e=e.mul(t)).sub(.004).max(0)).mul(e.mul(6.2).add(.5)),i=e.mul(e.mul(6.2).add(1.7)).add(.06);return s.div(i).pow(2.2)})).setLayout({name:"CineonToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),WE=ju((([e])=>{const t=e.mul(e.add(.0245786)).sub(90537e-9),s=e.mul(e.add(.432951).mul(.983729)).add(.238081);return t.div(s)})),HE=ju((([e,t])=>{const s=gc(.59719,.35458,.04823,.076,.90834,.01566,.0284,.13383,.83777),i=gc(1.60475,-.53108,-.07367,-.10208,1.10813,-.00605,-.00327,-.07276,1.07602);return e=e.mul(t).div(.6),e=s.mul(e),e=WE(e),(e=i.mul(e)).clamp()})).setLayout({name:"ACESFilmicToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),jE=gc(oc(1.6605,-.1246,-.0182),oc(-.5876,1.1329,-.1006),oc(-.0728,-.0083,1.1187)),qE=gc(oc(.6274,.0691,.0164),oc(.3293,.9195,.088),oc(.0433,.0113,.8956)),$E=ju((([e])=>{const t=oc(e).toVar(),s=oc(t.mul(t)).toVar(),i=oc(s.mul(s)).toVar();return Ku(15.5).mul(i.mul(s)).sub(md(40.14,i.mul(t))).add(md(31.96,i).sub(md(6.868,s.mul(t))).add(md(.4298,s).add(md(.1191,t).sub(.00232))))})),XE=ju((([e,t])=>{const s=oc(e).toVar(),i=gc(oc(.856627153315983,.137318972929847,.11189821299995),oc(.0951212405381588,.761241990602591,.0767994186031903),oc(.0482516061458583,.101439036467562,.811302368396859)),r=gc(oc(1.1271005818144368,-.1413297634984383,-.14132976349843826),oc(-.11060664309660323,1.157823702216272,-.11060664309660294),oc(-.016493938717834573,-.016493938717834257,1.2519364065950405)),n=Ku(-12.47393),o=Ku(4.026069);return s.mulAssign(t),s.assign(qE.mul(s)),s.assign(i.mul(s)),s.assign(Tp(s,1e-10)),s.assign($d(s)),s.assign(s.sub(n).div(o.sub(n))),s.assign(Lp(s,0,1)),s.assign($E(s)),s.assign(r.mul(s)),s.assign(Cp(Tp(oc(0),s),oc(2.2))),s.assign(jE.mul(s)),s.assign(Lp(s,0,1)),s})).setLayout({name:"AgXToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),YE=ju((([e,t])=>{const s=Ku(.76),i=Ku(.15);e=e.mul(t);const r=vp(e.r,vp(e.g,e.b)),n=qp(r.lessThan(.08),r.sub(md(6.25,r.mul(r))),.04);e.subAssign(n);const o=Tp(e.r,Tp(e.g,e.b));Yu(o.lessThan(s),(()=>e));const a=pd(1,s),h=pd(1,a.mul(a).div(o.add(a.sub(s))));e.mulAssign(h.div(o));const l=pd(1,gd(1,i.mul(o.sub(h)).add(1)));return Up(e,oc(h),l)})).setLayout({name:"NeutralToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]});var JE=Object.freeze({__proto__:null,ACESFilmicToneMapping:HE,AgXToneMapping:XE,CineonToneMapping:GE,LinearToneMapping:DE,NeutralToneMapping:YE,ReinhardToneMapping:kE});const ZE=ju((([e=t()])=>{const t=e.mul(2),s=t.x.floor(),i=t.y.floor();return s.add(i).mod(2).sign()})),KE=ju((([e,t,s])=>{const i=Ku(s).toVar(),r=Ku(t).toVar(),n=tc(e).toVar();return qp(n,r,i)})).setLayout({name:"mx_select",type:"float",inputs:[{name:"b",type:"bool"},{name:"t",type:"float"},{name:"f",type:"float"}]}),QE=ju((([e,t])=>{const s=tc(t).toVar(),i=Ku(e).toVar();return qp(s,i.negate(),i)})).setLayout({name:"mx_negate_if",type:"float",inputs:[{name:"val",type:"float"},{name:"b",type:"bool"}]}),eB=ju((([e])=>{const t=Ku(e).toVar();return Qu(Jd(t))})).setLayout({name:"mx_floor",type:"int",inputs:[{name:"x",type:"float"}]}),tB=ju((([e,t])=>{const s=Ku(e).toVar();return t.assign(eB(s)),s.sub(Ku(t))})),sB=xM([ju((([e,t,s,i,r,n])=>{const o=Ku(n).toVar(),a=Ku(r).toVar(),h=Ku(i).toVar(),l=Ku(s).toVar(),u=Ku(t).toVar(),c=Ku(e).toVar(),d=Ku(pd(1,a)).toVar();return pd(1,o).mul(c.mul(d).add(u.mul(a))).add(o.mul(l.mul(d).add(h.mul(a))))})).setLayout({name:"mx_bilerp_0",type:"float",inputs:[{name:"v0",type:"float"},{name:"v1",type:"float"},{name:"v2",type:"float"},{name:"v3",type:"float"},{name:"s",type:"float"},{name:"t",type:"float"}]}),ju((([e,t,s,i,r,n])=>{const o=Ku(n).toVar(),a=Ku(r).toVar(),h=oc(i).toVar(),l=oc(s).toVar(),u=oc(t).toVar(),c=oc(e).toVar(),d=Ku(pd(1,a)).toVar();return pd(1,o).mul(c.mul(d).add(u.mul(a))).add(o.mul(l.mul(d).add(h.mul(a))))})).setLayout({name:"mx_bilerp_1",type:"vec3",inputs:[{name:"v0",type:"vec3"},{name:"v1",type:"vec3"},{name:"v2",type:"vec3"},{name:"v3",type:"vec3"},{name:"s",type:"float"},{name:"t",type:"float"}]})]),iB=xM([ju((([e,t,s,i,r,n,o,a,h,l,u])=>{const c=Ku(u).toVar(),d=Ku(l).toVar(),p=Ku(h).toVar(),m=Ku(a).toVar(),g=Ku(o).toVar(),f=Ku(n).toVar(),y=Ku(r).toVar(),x=Ku(i).toVar(),b=Ku(s).toVar(),v=Ku(t).toVar(),T=Ku(e).toVar(),_=Ku(pd(1,p)).toVar(),w=Ku(pd(1,d)).toVar();return Ku(pd(1,c)).toVar().mul(w.mul(T.mul(_).add(v.mul(p))).add(d.mul(b.mul(_).add(x.mul(p))))).add(c.mul(w.mul(y.mul(_).add(f.mul(p))).add(d.mul(g.mul(_).add(m.mul(p))))))})).setLayout({name:"mx_trilerp_0",type:"float",inputs:[{name:"v0",type:"float"},{name:"v1",type:"float"},{name:"v2",type:"float"},{name:"v3",type:"float"},{name:"v4",type:"float"},{name:"v5",type:"float"},{name:"v6",type:"float"},{name:"v7",type:"float"},{name:"s",type:"float"},{name:"t",type:"float"},{name:"r",type:"float"}]}),ju((([e,t,s,i,r,n,o,a,h,l,u])=>{const c=Ku(u).toVar(),d=Ku(l).toVar(),p=Ku(h).toVar(),m=oc(a).toVar(),g=oc(o).toVar(),f=oc(n).toVar(),y=oc(r).toVar(),x=oc(i).toVar(),b=oc(s).toVar(),v=oc(t).toVar(),T=oc(e).toVar(),_=Ku(pd(1,p)).toVar(),w=Ku(pd(1,d)).toVar();return Ku(pd(1,c)).toVar().mul(w.mul(T.mul(_).add(v.mul(p))).add(d.mul(b.mul(_).add(x.mul(p))))).add(c.mul(w.mul(y.mul(_).add(f.mul(p))).add(d.mul(g.mul(_).add(m.mul(p))))))})).setLayout({name:"mx_trilerp_1",type:"vec3",inputs:[{name:"v0",type:"vec3"},{name:"v1",type:"vec3"},{name:"v2",type:"vec3"},{name:"v3",type:"vec3"},{name:"v4",type:"vec3"},{name:"v5",type:"vec3"},{name:"v6",type:"vec3"},{name:"v7",type:"vec3"},{name:"s",type:"float"},{name:"t",type:"float"},{name:"r",type:"float"}]})]),rB=ju((([e,t,s])=>{const i=Ku(s).toVar(),r=Ku(t).toVar(),n=ec(e).toVar(),o=ec(n.bitAnd(ec(7))).toVar(),a=Ku(KE(o.lessThan(ec(4)),r,i)).toVar(),h=Ku(md(2,KE(o.lessThan(ec(4)),i,r))).toVar();return QE(a,tc(o.bitAnd(ec(1)))).add(QE(h,tc(o.bitAnd(ec(2)))))})).setLayout({name:"mx_gradient_float_0",type:"float",inputs:[{name:"hash",type:"uint"},{name:"x",type:"float"},{name:"y",type:"float"}]}),nB=ju((([e,t,s,i])=>{const r=Ku(i).toVar(),n=Ku(s).toVar(),o=Ku(t).toVar(),a=ec(e).toVar(),h=ec(a.bitAnd(ec(15))).toVar(),l=Ku(KE(h.lessThan(ec(8)),o,n)).toVar(),u=Ku(KE(h.lessThan(ec(4)),n,KE(h.equal(ec(12)).or(h.equal(ec(14))),o,r))).toVar();return QE(l,tc(h.bitAnd(ec(1)))).add(QE(u,tc(h.bitAnd(ec(2)))))})).setLayout({name:"mx_gradient_float_1",type:"float",inputs:[{name:"hash",type:"uint"},{name:"x",type:"float"},{name:"y",type:"float"},{name:"z",type:"float"}]}),oB=xM([rB,nB]),aB=ju((([e,t,s])=>{const i=Ku(s).toVar(),r=Ku(t).toVar(),n=hc(e).toVar();return oc(oB(n.x,r,i),oB(n.y,r,i),oB(n.z,r,i))})).setLayout({name:"mx_gradient_vec3_0",type:"vec3",inputs:[{name:"hash",type:"uvec3"},{name:"x",type:"float"},{name:"y",type:"float"}]}),hB=ju((([e,t,s,i])=>{const r=Ku(i).toVar(),n=Ku(s).toVar(),o=Ku(t).toVar(),a=hc(e).toVar();return oc(oB(a.x,o,n,r),oB(a.y,o,n,r),oB(a.z,o,n,r))})).setLayout({name:"mx_gradient_vec3_1",type:"vec3",inputs:[{name:"hash",type:"uvec3"},{name:"x",type:"float"},{name:"y",type:"float"},{name:"z",type:"float"}]}),lB=xM([aB,hB]),uB=ju((([e])=>{const t=Ku(e).toVar();return md(.6616,t)})).setLayout({name:"mx_gradient_scale2d_0",type:"float",inputs:[{name:"v",type:"float"}]}),cB=ju((([e])=>{const t=Ku(e).toVar();return md(.982,t)})).setLayout({name:"mx_gradient_scale3d_0",type:"float",inputs:[{name:"v",type:"float"}]}),dB=xM([uB,ju((([e])=>{const t=oc(e).toVar();return md(.6616,t)})).setLayout({name:"mx_gradient_scale2d_1",type:"vec3",inputs:[{name:"v",type:"vec3"}]})]),pB=xM([cB,ju((([e])=>{const t=oc(e).toVar();return md(.982,t)})).setLayout({name:"mx_gradient_scale3d_1",type:"vec3",inputs:[{name:"v",type:"vec3"}]})]),mB=ju((([e,t])=>{const s=Qu(t).toVar(),i=ec(e).toVar();return i.shiftLeft(s).bitOr(i.shiftRight(Qu(32).sub(s)))})).setLayout({name:"mx_rotl32",type:"uint",inputs:[{name:"x",type:"uint"},{name:"k",type:"int"}]}),gB=ju((([e,t,s])=>{e.subAssign(s),e.bitXorAssign(mB(s,Qu(4))),s.addAssign(t),t.subAssign(e),t.bitXorAssign(mB(e,Qu(6))),e.addAssign(s),s.subAssign(t),s.bitXorAssign(mB(t,Qu(8))),t.addAssign(e),e.subAssign(s),e.bitXorAssign(mB(s,Qu(16))),s.addAssign(t),t.subAssign(e),t.bitXorAssign(mB(e,Qu(19))),e.addAssign(s),s.subAssign(t),s.bitXorAssign(mB(t,Qu(4))),t.addAssign(e)})),fB=ju((([e,t,s])=>{const i=ec(s).toVar(),r=ec(t).toVar(),n=ec(e).toVar();return i.bitXorAssign(r),i.subAssign(mB(r,Qu(14))),n.bitXorAssign(i),n.subAssign(mB(i,Qu(11))),r.bitXorAssign(n),r.subAssign(mB(n,Qu(25))),i.bitXorAssign(r),i.subAssign(mB(r,Qu(16))),n.bitXorAssign(i),n.subAssign(mB(i,Qu(4))),r.bitXorAssign(n),r.subAssign(mB(n,Qu(14))),i.bitXorAssign(r),i.subAssign(mB(r,Qu(24))),i})).setLayout({name:"mx_bjfinal",type:"uint",inputs:[{name:"a",type:"uint"},{name:"b",type:"uint"},{name:"c",type:"uint"}]}),yB=ju((([e])=>{const t=ec(e).toVar();return Ku(t).div(Ku(ec(Qu(4294967295))))})).setLayout({name:"mx_bits_to_01",type:"float",inputs:[{name:"bits",type:"uint"}]}),xB=ju((([e])=>{const t=Ku(e).toVar();return t.mul(t).mul(t).mul(t.mul(t.mul(6).sub(15)).add(10))})).setLayout({name:"mx_fade",type:"float",inputs:[{name:"t",type:"float"}]}),bB=xM([ju((([e])=>{const t=Qu(e).toVar(),s=ec(ec(1)).toVar(),i=ec(ec(Qu(3735928559)).add(s.shiftLeft(ec(2))).add(ec(13))).toVar();return fB(i.add(ec(t)),i,i)})).setLayout({name:"mx_hash_int_0",type:"uint",inputs:[{name:"x",type:"int"}]}),ju((([e,t])=>{const s=Qu(t).toVar(),i=Qu(e).toVar(),r=ec(ec(2)).toVar(),n=ec().toVar(),o=ec().toVar(),a=ec().toVar();return n.assign(o.assign(a.assign(ec(Qu(3735928559)).add(r.shiftLeft(ec(2))).add(ec(13))))),n.addAssign(ec(i)),o.addAssign(ec(s)),fB(n,o,a)})).setLayout({name:"mx_hash_int_1",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"}]}),ju((([e,t,s])=>{const i=Qu(s).toVar(),r=Qu(t).toVar(),n=Qu(e).toVar(),o=ec(ec(3)).toVar(),a=ec().toVar(),h=ec().toVar(),l=ec().toVar();return a.assign(h.assign(l.assign(ec(Qu(3735928559)).add(o.shiftLeft(ec(2))).add(ec(13))))),a.addAssign(ec(n)),h.addAssign(ec(r)),l.addAssign(ec(i)),fB(a,h,l)})).setLayout({name:"mx_hash_int_2",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"}]}),ju((([e,t,s,i])=>{const r=Qu(i).toVar(),n=Qu(s).toVar(),o=Qu(t).toVar(),a=Qu(e).toVar(),h=ec(ec(4)).toVar(),l=ec().toVar(),u=ec().toVar(),c=ec().toVar();return l.assign(u.assign(c.assign(ec(Qu(3735928559)).add(h.shiftLeft(ec(2))).add(ec(13))))),l.addAssign(ec(a)),u.addAssign(ec(o)),c.addAssign(ec(n)),gB(l,u,c),l.addAssign(ec(r)),fB(l,u,c)})).setLayout({name:"mx_hash_int_3",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xx",type:"int"}]}),ju((([e,t,s,i,r])=>{const n=Qu(r).toVar(),o=Qu(i).toVar(),a=Qu(s).toVar(),h=Qu(t).toVar(),l=Qu(e).toVar(),u=ec(ec(5)).toVar(),c=ec().toVar(),d=ec().toVar(),p=ec().toVar();return c.assign(d.assign(p.assign(ec(Qu(3735928559)).add(u.shiftLeft(ec(2))).add(ec(13))))),c.addAssign(ec(l)),d.addAssign(ec(h)),p.addAssign(ec(a)),gB(c,d,p),c.addAssign(ec(o)),d.addAssign(ec(n)),fB(c,d,p)})).setLayout({name:"mx_hash_int_4",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xx",type:"int"},{name:"yy",type:"int"}]})]),vB=xM([ju((([e,t])=>{const s=Qu(t).toVar(),i=Qu(e).toVar(),r=ec(bB(i,s)).toVar(),n=hc().toVar();return n.x.assign(r.bitAnd(Qu(255))),n.y.assign(r.shiftRight(Qu(8)).bitAnd(Qu(255))),n.z.assign(r.shiftRight(Qu(16)).bitAnd(Qu(255))),n})).setLayout({name:"mx_hash_vec3_0",type:"uvec3",inputs:[{name:"x",type:"int"},{name:"y",type:"int"}]}),ju((([e,t,s])=>{const i=Qu(s).toVar(),r=Qu(t).toVar(),n=Qu(e).toVar(),o=ec(bB(n,r,i)).toVar(),a=hc().toVar();return a.x.assign(o.bitAnd(Qu(255))),a.y.assign(o.shiftRight(Qu(8)).bitAnd(Qu(255))),a.z.assign(o.shiftRight(Qu(16)).bitAnd(Qu(255))),a})).setLayout({name:"mx_hash_vec3_1",type:"uvec3",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"}]})]),TB=xM([ju((([e])=>{const t=sc(e).toVar(),s=Qu().toVar(),i=Qu().toVar(),r=Ku(tB(t.x,s)).toVar(),n=Ku(tB(t.y,i)).toVar(),o=Ku(xB(r)).toVar(),a=Ku(xB(n)).toVar(),h=Ku(sB(oB(bB(s,i),r,n),oB(bB(s.add(Qu(1)),i),r.sub(1),n),oB(bB(s,i.add(Qu(1))),r,n.sub(1)),oB(bB(s.add(Qu(1)),i.add(Qu(1))),r.sub(1),n.sub(1)),o,a)).toVar();return dB(h)})).setLayout({name:"mx_perlin_noise_float_0",type:"float",inputs:[{name:"p",type:"vec2"}]}),ju((([e])=>{const t=oc(e).toVar(),s=Qu().toVar(),i=Qu().toVar(),r=Qu().toVar(),n=Ku(tB(t.x,s)).toVar(),o=Ku(tB(t.y,i)).toVar(),a=Ku(tB(t.z,r)).toVar(),h=Ku(xB(n)).toVar(),l=Ku(xB(o)).toVar(),u=Ku(xB(a)).toVar(),c=Ku(iB(oB(bB(s,i,r),n,o,a),oB(bB(s.add(Qu(1)),i,r),n.sub(1),o,a),oB(bB(s,i.add(Qu(1)),r),n,o.sub(1),a),oB(bB(s.add(Qu(1)),i.add(Qu(1)),r),n.sub(1),o.sub(1),a),oB(bB(s,i,r.add(Qu(1))),n,o,a.sub(1)),oB(bB(s.add(Qu(1)),i,r.add(Qu(1))),n.sub(1),o,a.sub(1)),oB(bB(s,i.add(Qu(1)),r.add(Qu(1))),n,o.sub(1),a.sub(1)),oB(bB(s.add(Qu(1)),i.add(Qu(1)),r.add(Qu(1))),n.sub(1),o.sub(1),a.sub(1)),h,l,u)).toVar();return pB(c)})).setLayout({name:"mx_perlin_noise_float_1",type:"float",inputs:[{name:"p",type:"vec3"}]})]),_B=xM([ju((([e])=>{const t=sc(e).toVar(),s=Qu().toVar(),i=Qu().toVar(),r=Ku(tB(t.x,s)).toVar(),n=Ku(tB(t.y,i)).toVar(),o=Ku(xB(r)).toVar(),a=Ku(xB(n)).toVar(),h=oc(sB(lB(vB(s,i),r,n),lB(vB(s.add(Qu(1)),i),r.sub(1),n),lB(vB(s,i.add(Qu(1))),r,n.sub(1)),lB(vB(s.add(Qu(1)),i.add(Qu(1))),r.sub(1),n.sub(1)),o,a)).toVar();return dB(h)})).setLayout({name:"mx_perlin_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"vec2"}]}),ju((([e])=>{const t=oc(e).toVar(),s=Qu().toVar(),i=Qu().toVar(),r=Qu().toVar(),n=Ku(tB(t.x,s)).toVar(),o=Ku(tB(t.y,i)).toVar(),a=Ku(tB(t.z,r)).toVar(),h=Ku(xB(n)).toVar(),l=Ku(xB(o)).toVar(),u=Ku(xB(a)).toVar(),c=oc(iB(lB(vB(s,i,r),n,o,a),lB(vB(s.add(Qu(1)),i,r),n.sub(1),o,a),lB(vB(s,i.add(Qu(1)),r),n,o.sub(1),a),lB(vB(s.add(Qu(1)),i.add(Qu(1)),r),n.sub(1),o.sub(1),a),lB(vB(s,i,r.add(Qu(1))),n,o,a.sub(1)),lB(vB(s.add(Qu(1)),i,r.add(Qu(1))),n.sub(1),o,a.sub(1)),lB(vB(s,i.add(Qu(1)),r.add(Qu(1))),n,o.sub(1),a.sub(1)),lB(vB(s.add(Qu(1)),i.add(Qu(1)),r.add(Qu(1))),n.sub(1),o.sub(1),a.sub(1)),h,l,u)).toVar();return pB(c)})).setLayout({name:"mx_perlin_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec3"}]})]),wB=xM([ju((([e])=>{const t=Ku(e).toVar(),s=Qu(eB(t)).toVar();return yB(bB(s))})).setLayout({name:"mx_cell_noise_float_0",type:"float",inputs:[{name:"p",type:"float"}]}),ju((([e])=>{const t=sc(e).toVar(),s=Qu(eB(t.x)).toVar(),i=Qu(eB(t.y)).toVar();return yB(bB(s,i))})).setLayout({name:"mx_cell_noise_float_1",type:"float",inputs:[{name:"p",type:"vec2"}]}),ju((([e])=>{const t=oc(e).toVar(),s=Qu(eB(t.x)).toVar(),i=Qu(eB(t.y)).toVar(),r=Qu(eB(t.z)).toVar();return yB(bB(s,i,r))})).setLayout({name:"mx_cell_noise_float_2",type:"float",inputs:[{name:"p",type:"vec3"}]}),ju((([e])=>{const t=uc(e).toVar(),s=Qu(eB(t.x)).toVar(),i=Qu(eB(t.y)).toVar(),r=Qu(eB(t.z)).toVar(),n=Qu(eB(t.w)).toVar();return yB(bB(s,i,r,n))})).setLayout({name:"mx_cell_noise_float_3",type:"float",inputs:[{name:"p",type:"vec4"}]})]),SB=xM([ju((([e])=>{const t=Ku(e).toVar(),s=Qu(eB(t)).toVar();return oc(yB(bB(s,Qu(0))),yB(bB(s,Qu(1))),yB(bB(s,Qu(2))))})).setLayout({name:"mx_cell_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"float"}]}),ju((([e])=>{const t=sc(e).toVar(),s=Qu(eB(t.x)).toVar(),i=Qu(eB(t.y)).toVar();return oc(yB(bB(s,i,Qu(0))),yB(bB(s,i,Qu(1))),yB(bB(s,i,Qu(2))))})).setLayout({name:"mx_cell_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec2"}]}),ju((([e])=>{const t=oc(e).toVar(),s=Qu(eB(t.x)).toVar(),i=Qu(eB(t.y)).toVar(),r=Qu(eB(t.z)).toVar();return oc(yB(bB(s,i,r,Qu(0))),yB(bB(s,i,r,Qu(1))),yB(bB(s,i,r,Qu(2))))})).setLayout({name:"mx_cell_noise_vec3_2",type:"vec3",inputs:[{name:"p",type:"vec3"}]}),ju((([e])=>{const t=uc(e).toVar(),s=Qu(eB(t.x)).toVar(),i=Qu(eB(t.y)).toVar(),r=Qu(eB(t.z)).toVar(),n=Qu(eB(t.w)).toVar();return oc(yB(bB(s,i,r,n,Qu(0))),yB(bB(s,i,r,n,Qu(1))),yB(bB(s,i,r,n,Qu(2))))})).setLayout({name:"mx_cell_noise_vec3_3",type:"vec3",inputs:[{name:"p",type:"vec4"}]})]),MB=ju((([e,t,s,i])=>{const r=Ku(i).toVar(),n=Ku(s).toVar(),o=Qu(t).toVar(),a=oc(e).toVar(),h=Ku(0).toVar(),l=Ku(1).toVar();return Cy(o,(()=>{h.addAssign(l.mul(TB(a))),l.mulAssign(r),a.mulAssign(n)})),h})).setLayout({name:"mx_fractal_noise_float",type:"float",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),AB=ju((([e,t,s,i])=>{const r=Ku(i).toVar(),n=Ku(s).toVar(),o=Qu(t).toVar(),a=oc(e).toVar(),h=oc(0).toVar(),l=Ku(1).toVar();return Cy(o,(()=>{h.addAssign(l.mul(_B(a))),l.mulAssign(r),a.mulAssign(n)})),h})).setLayout({name:"mx_fractal_noise_vec3",type:"vec3",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),NB=ju((([e,t,s,i])=>{const r=Ku(i).toVar(),n=Ku(s).toVar(),o=Qu(t).toVar(),a=oc(e).toVar();return sc(MB(a,o,n,r),MB(a.add(oc(Qu(19),Qu(193),Qu(17))),o,n,r))})).setLayout({name:"mx_fractal_noise_vec2",type:"vec2",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),RB=ju((([e,t,s,i])=>{const r=Ku(i).toVar(),n=Ku(s).toVar(),o=Qu(t).toVar(),a=oc(e).toVar(),h=oc(AB(a,o,n,r)).toVar(),l=Ku(MB(a.add(oc(Qu(19),Qu(193),Qu(17))),o,n,r)).toVar();return uc(h,l)})).setLayout({name:"mx_fractal_noise_vec4",type:"vec4",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),CB=ju((([e,t,s,i,r,n,o])=>{const a=Qu(o).toVar(),h=Ku(n).toVar(),l=Qu(r).toVar(),u=Qu(i).toVar(),c=Qu(s).toVar(),d=Qu(t).toVar(),p=sc(e).toVar(),m=oc(SB(sc(d.add(u),c.add(l)))).toVar(),g=sc(m.x,m.y).toVar();g.subAssign(.5),g.mulAssign(h),g.addAssign(.5);const f=sc(sc(Ku(d),Ku(c)).add(g)).toVar(),y=sc(f.sub(p)).toVar();return Yu(a.equal(Qu(2)),(()=>op(y.x).add(op(y.y)))),Yu(a.equal(Qu(3)),(()=>Tp(op(y.x),op(y.y)))),Np(y,y)})).setLayout({name:"mx_worley_distance_0",type:"float",inputs:[{name:"p",type:"vec2"},{name:"x",type:"int"},{name:"y",type:"int"},{name:"xoff",type:"int"},{name:"yoff",type:"int"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),EB=xM([CB,ju((([e,t,s,i,r,n,o,a,h])=>{const l=Qu(h).toVar(),u=Ku(a).toVar(),c=Qu(o).toVar(),d=Qu(n).toVar(),p=Qu(r).toVar(),m=Qu(i).toVar(),g=Qu(s).toVar(),f=Qu(t).toVar(),y=oc(e).toVar(),x=oc(SB(oc(f.add(p),g.add(d),m.add(c)))).toVar();x.subAssign(.5),x.mulAssign(u),x.addAssign(.5);const b=oc(oc(Ku(f),Ku(g),Ku(m)).add(x)).toVar(),v=oc(b.sub(y)).toVar();return Yu(l.equal(Qu(2)),(()=>op(v.x).add(op(v.y)).add(op(v.z)))),Yu(l.equal(Qu(3)),(()=>Tp(Tp(op(v.x),op(v.y)),op(v.z)))),Np(v,v)})).setLayout({name:"mx_worley_distance_1",type:"float",inputs:[{name:"p",type:"vec3"},{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xoff",type:"int"},{name:"yoff",type:"int"},{name:"zoff",type:"int"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),BB=ju((([e,t,s])=>{const i=Qu(s).toVar(),r=Ku(t).toVar(),n=sc(e).toVar(),o=Qu().toVar(),a=Qu().toVar(),h=sc(tB(n.x,o),tB(n.y,a)).toVar(),l=Ku(1e6).toVar();return Cy({start:-1,end:Qu(1),name:"x",condition:"<="},(({x:e})=>{Cy({start:-1,end:Qu(1),name:"y",condition:"<="},(({y:t})=>{const s=Ku(EB(h,e,t,o,a,r,i)).toVar();l.assign(vp(l,s))}))})),Yu(i.equal(Qu(0)),(()=>{l.assign(Xd(l))})),l})).setLayout({name:"mx_worley_noise_float_0",type:"float",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),IB=ju((([e,t,s])=>{const i=Qu(s).toVar(),r=Ku(t).toVar(),n=sc(e).toVar(),o=Qu().toVar(),a=Qu().toVar(),h=sc(tB(n.x,o),tB(n.y,a)).toVar(),l=sc(1e6,1e6).toVar();return Cy({start:-1,end:Qu(1),name:"x",condition:"<="},(({x:e})=>{Cy({start:-1,end:Qu(1),name:"y",condition:"<="},(({y:t})=>{const s=Ku(EB(h,e,t,o,a,r,i)).toVar();Yu(s.lessThan(l.x),(()=>{l.y.assign(l.x),l.x.assign(s)})).ElseIf(s.lessThan(l.y),(()=>{l.y.assign(s)}))}))})),Yu(i.equal(Qu(0)),(()=>{l.assign(Xd(l))})),l})).setLayout({name:"mx_worley_noise_vec2_0",type:"vec2",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),PB=ju((([e,t,s])=>{const i=Qu(s).toVar(),r=Ku(t).toVar(),n=sc(e).toVar(),o=Qu().toVar(),a=Qu().toVar(),h=sc(tB(n.x,o),tB(n.y,a)).toVar(),l=oc(1e6,1e6,1e6).toVar();return Cy({start:-1,end:Qu(1),name:"x",condition:"<="},(({x:e})=>{Cy({start:-1,end:Qu(1),name:"y",condition:"<="},(({y:t})=>{const s=Ku(EB(h,e,t,o,a,r,i)).toVar();Yu(s.lessThan(l.x),(()=>{l.z.assign(l.y),l.y.assign(l.x),l.x.assign(s)})).ElseIf(s.lessThan(l.y),(()=>{l.z.assign(l.y),l.y.assign(s)})).ElseIf(s.lessThan(l.z),(()=>{l.z.assign(s)}))}))})),Yu(i.equal(Qu(0)),(()=>{l.assign(Xd(l))})),l})).setLayout({name:"mx_worley_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),FB=xM([BB,ju((([e,t,s])=>{const i=Qu(s).toVar(),r=Ku(t).toVar(),n=oc(e).toVar(),o=Qu().toVar(),a=Qu().toVar(),h=Qu().toVar(),l=oc(tB(n.x,o),tB(n.y,a),tB(n.z,h)).toVar(),u=Ku(1e6).toVar();return Cy({start:-1,end:Qu(1),name:"x",condition:"<="},(({x:e})=>{Cy({start:-1,end:Qu(1),name:"y",condition:"<="},(({y:t})=>{Cy({start:-1,end:Qu(1),name:"z",condition:"<="},(({z:s})=>{const n=Ku(EB(l,e,t,s,o,a,h,r,i)).toVar();u.assign(vp(u,n))}))}))})),Yu(i.equal(Qu(0)),(()=>{u.assign(Xd(u))})),u})).setLayout({name:"mx_worley_noise_float_1",type:"float",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),zB=xM([IB,ju((([e,t,s])=>{const i=Qu(s).toVar(),r=Ku(t).toVar(),n=oc(e).toVar(),o=Qu().toVar(),a=Qu().toVar(),h=Qu().toVar(),l=oc(tB(n.x,o),tB(n.y,a),tB(n.z,h)).toVar(),u=sc(1e6,1e6).toVar();return Cy({start:-1,end:Qu(1),name:"x",condition:"<="},(({x:e})=>{Cy({start:-1,end:Qu(1),name:"y",condition:"<="},(({y:t})=>{Cy({start:-1,end:Qu(1),name:"z",condition:"<="},(({z:s})=>{const n=Ku(EB(l,e,t,s,o,a,h,r,i)).toVar();Yu(n.lessThan(u.x),(()=>{u.y.assign(u.x),u.x.assign(n)})).ElseIf(n.lessThan(u.y),(()=>{u.y.assign(n)}))}))}))})),Yu(i.equal(Qu(0)),(()=>{u.assign(Xd(u))})),u})).setLayout({name:"mx_worley_noise_vec2_1",type:"vec2",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),UB=xM([PB,ju((([e,t,s])=>{const i=Qu(s).toVar(),r=Ku(t).toVar(),n=oc(e).toVar(),o=Qu().toVar(),a=Qu().toVar(),h=Qu().toVar(),l=oc(tB(n.x,o),tB(n.y,a),tB(n.z,h)).toVar(),u=oc(1e6,1e6,1e6).toVar();return Cy({start:-1,end:Qu(1),name:"x",condition:"<="},(({x:e})=>{Cy({start:-1,end:Qu(1),name:"y",condition:"<="},(({y:t})=>{Cy({start:-1,end:Qu(1),name:"z",condition:"<="},(({z:s})=>{const n=Ku(EB(l,e,t,s,o,a,h,r,i)).toVar();Yu(n.lessThan(u.x),(()=>{u.z.assign(u.y),u.y.assign(u.x),u.x.assign(n)})).ElseIf(n.lessThan(u.y),(()=>{u.z.assign(u.y),u.y.assign(n)})).ElseIf(n.lessThan(u.z),(()=>{u.z.assign(n)}))}))}))})),Yu(i.equal(Qu(0)),(()=>{u.assign(Xd(u))})),u})).setLayout({name:"mx_worley_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),LB=ju((([e])=>{const t=e.y,s=e.z,i=oc().toVar();return Yu(t.lessThan(1e-4),(()=>{i.assign(oc(s,s,s))})).Else((()=>{let r=e.x;r=r.sub(Jd(r)).mul(6).toVar();const n=Qu(gp(r)),o=r.sub(Ku(n)),a=s.mul(t.oneMinus()),h=s.mul(t.mul(o).oneMinus()),l=s.mul(t.mul(o.oneMinus()).oneMinus());Yu(n.equal(Qu(0)),(()=>{i.assign(oc(s,l,a))})).ElseIf(n.equal(Qu(1)),(()=>{i.assign(oc(h,s,a))})).ElseIf(n.equal(Qu(2)),(()=>{i.assign(oc(a,s,l))})).ElseIf(n.equal(Qu(3)),(()=>{i.assign(oc(a,h,s))})).ElseIf(n.equal(Qu(4)),(()=>{i.assign(oc(l,a,s))})).Else((()=>{i.assign(oc(s,a,h))}))})),i})).setLayout({name:"mx_hsvtorgb",type:"vec3",inputs:[{name:"hsv",type:"vec3"}]}),OB=ju((([e])=>{const t=oc(e).toVar(),s=Ku(t.x).toVar(),i=Ku(t.y).toVar(),r=Ku(t.z).toVar(),n=Ku(vp(s,vp(i,r))).toVar(),o=Ku(Tp(s,Tp(i,r))).toVar(),a=Ku(o.sub(n)).toVar(),h=Ku().toVar(),l=Ku().toVar(),u=Ku().toVar();return u.assign(o),Yu(o.greaterThan(0),(()=>{l.assign(a.div(o))})).Else((()=>{l.assign(0)})),Yu(l.lessThanEqual(0),(()=>{h.assign(0)})).Else((()=>{Yu(s.greaterThanEqual(o),(()=>{h.assign(i.sub(r).div(a))})).ElseIf(i.greaterThanEqual(o),(()=>{h.assign(dd(2,r.sub(s).div(a)))})).Else((()=>{h.assign(dd(4,s.sub(i).div(a)))})),h.mulAssign(1/6),Yu(h.lessThan(0),(()=>{h.addAssign(1)}))})),oc(h,l,u)})).setLayout({name:"mx_rgbtohsv",type:"vec3",inputs:[{name:"c",type:"vec3"}]}),VB=ju((([e])=>{const t=oc(e).toVar(),s=lc(vd(t,oc(.04045))).toVar(),i=oc(t.div(12.92)).toVar(),r=oc(Cp(Tp(t.add(oc(.055)),oc(0)).div(1.055),oc(2.4))).toVar();return Up(i,r,s)})).setLayout({name:"mx_srgb_texture_to_lin_rec709",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),DB=(e,t)=>{e=Ku(e),t=Ku(t);const s=sc(t.dFdx(),t.dFdy()).length().mul(.7071067811865476);return Dp(e.sub(s),e.add(s),t)},kB=(e,t,s,i)=>Up(e,t,s[i].clamp()),GB=(e,t,s=Um())=>kB(e,t,s,"x"),WB=(e,t,s=Um())=>kB(e,t,s,"y"),HB=(e,t,s,i,r)=>Up(e,t,DB(s,i[r])),jB=(e,t,s,i=Um())=>HB(e,t,s,i,"x"),qB=(e,t,s,i=Um())=>HB(e,t,s,i,"y"),$B=(e=1,t=0,s=Um())=>s.mul(e).add(t),XB=(e,t=1)=>(e=Ku(e)).abs().pow(t).mul(e.sign()),YB=(e,t=1,s=.5)=>Ku(e).sub(s).mul(t).add(s),JB=(e=Um(),t=1,s=0)=>TB(e.convert("vec2|vec3")).mul(t).add(s),ZB=(e=Um(),t=1,s=0)=>_B(e.convert("vec2|vec3")).mul(t).add(s),KB=(e=Um(),t=1,s=0)=>{e=e.convert("vec2|vec3");return uc(_B(e),TB(e.add(sc(19,73)))).mul(t).add(s)},QB=(e=Um(),t=1)=>FB(e.convert("vec2|vec3"),t,Qu(1)),eI=(e=Um(),t=1)=>zB(e.convert("vec2|vec3"),t,Qu(1)),tI=(e=Um(),t=1)=>UB(e.convert("vec2|vec3"),t,Qu(1)),sI=(e=Um())=>wB(e.convert("vec2|vec3")),iI=(e=Um(),t=3,s=2,i=.5,r=1)=>MB(e,Qu(t),s,i).mul(r),rI=(e=Um(),t=3,s=2,i=.5,r=1)=>NB(e,Qu(t),s,i).mul(r),nI=(e=Um(),t=3,s=2,i=.5,r=1)=>AB(e,Qu(t),s,i).mul(r),oI=(e=Um(),t=3,s=2,i=.5,r=1)=>RB(e,Qu(t),s,i).mul(r),aI=new pE;class hI extends Lw{constructor(e,t){super(),this.renderer=e,this.nodes=t}update(e,t,s){const i=this.renderer,r=this.nodes.getBackgroundNode(e)||e.background;let n=!1;if(null===r)i._clearColor.getRGB(aI,Zt),aI.a=i._clearColor.a;else if(!0===r.isColor)r.getRGB(aI,Zt),aI.a=1,n=!0;else if(!0===r.isNode){const s=this.get(e),n=r;aI.copy(i._clearColor);let o=s.backgroundMesh;if(void 0===o){const e=Yp(uc(n).mul(dA),{getUV:()=>Pg,getTextureLevel:()=>cA});let t=py();t=t.setZ(t.w);const i=new xx;i.name="Background.material",i.side=d,i.depthTest=!1,i.depthWrite=!1,i.fog=!1,i.lights=!1,i.vertexNode=t,i.colorNode=e,s.backgroundMeshNode=e,s.backgroundMesh=o=new Wn(new fl(1,32,32),i),o.frustumCulled=!1,o.name="Background.mesh",o.onBeforeRender=function(e,t,s){this.matrixWorld.copyPosition(s.matrixWorld)}}const a=n.getCacheKey();s.backgroundCacheKey!==a&&(s.backgroundMeshNode.node=uc(n).mul(dA),s.backgroundMeshNode.needsUpdate=!0,o.material.needsUpdate=!0,s.backgroundCacheKey=a),t.unshift(o,o.geometry,o.material,0,0,null)}else console.error("THREE.Renderer: Unsupported background configuration.",r);if(!0===i.autoClear||!0===n){aI.multiplyScalar(aI.a);const e=s.clearColorValue;e.r=aI.r,e.g=aI.g,e.b=aI.b,e.a=aI.a,s.depthClearValue=i._clearDepth,s.stencilClearValue=i._clearStencil,s.clearColor=!0===i.autoClearColor,s.clearDepth=!0===i.autoClearDepth,s.clearStencil=!0===i.autoClearStencil}else s.clearColor=!1,s.clearDepth=!1,s.clearStencil=!1}}class lI{constructor(e,t,s,i,r,n,o,a,h=!0,l=[]){this.vertexShader=e,this.fragmentShader=t,this.computeShader=s,this.transforms=l,this.nodeAttributes=i,this.bindings=r,this.updateNodes=n,this.updateBeforeNodes=o,this.updateAfterNodes=a,this.instanceBindGroups=h,this.usedTimes=0}createBindings(){const e=[];for(const t of this.bindings){if(!0!==(this.instanceBindGroups&&t.bindings[0].groupNode.shared)){const s=new sM(t.name,[],t.index,t);e.push(s);for(const e of t.bindings)s.bindings.push(e.clone())}else e.push(t)}return e}}const uI=new WeakMap;class cI extends Lw{constructor(e,t){super(),this.renderer=e,this.backend=t,this.nodeFrame=new hM,this.nodeBuilderCache=new Map,this.callHashCache=new Bw,this.groupsData=new Bw}updateGroup(e){const t=e.groupNode,s=t.name;if(s===Nc.name)return!0;if(s===Ac.name){const t=this.get(e),s=this.nodeFrame.renderId;return t.renderId!==s&&(t.renderId=s,!0)}if(s===Mc.name){const t=this.get(e),s=this.nodeFrame.frameId;return t.frameId!==s&&(t.frameId=s,!0)}const i=[t,e];let r=this.groupsData.get(i);return void 0===r&&this.groupsData.set(i,r={}),r.version!==t.version&&(r.version=t.version,!0)}getForRenderCacheKey(e){return e.initialCacheKey}getForRender(e){const t=this.get(e);let s=t.nodeBuilderState;if(void 0===s){const{nodeBuilderCache:i}=this,r=this.getForRenderCacheKey(e);if(s=i.get(r),void 0===s){const t=this.backend.createNodeBuilder(e.object,this.renderer);t.scene=e.scene,t.material=e.material,t.camera=e.camera,t.context.material=e.material,t.lightsNode=e.lightsNode,t.environmentNode=this.getEnvironmentNode(e.scene),t.fogNode=this.getFogNode(e.scene),t.clippingContext=e.clippingContext,t.build(),s=this._createNodeBuilderState(t),i.set(r,s)}s.usedTimes++,t.nodeBuilderState=s}return s}delete(e){if(e.isRenderObject){const t=this.get(e).nodeBuilderState;t.usedTimes--,0===t.usedTimes&&this.nodeBuilderCache.delete(this.getForRenderCacheKey(e))}return super.delete(e)}getForCompute(e){const t=this.get(e);let s=t.nodeBuilderState;if(void 0===s){const i=this.backend.createNodeBuilder(e,this.renderer);i.build(),s=this._createNodeBuilderState(i),t.nodeBuilderState=s}return s}_createNodeBuilderState(e){return new lI(e.vertexShader,e.fragmentShader,e.computeShader,e.getAttributesArray(),e.getBindings(),e.updateNodes,e.updateBeforeNodes,e.updateAfterNodes,e.instanceBindGroups,e.transforms)}getEnvironmentNode(e){return e.environmentNode||this.get(e).environmentNode||null}getBackgroundNode(e){return e.backgroundNode||this.get(e).backgroundNode||null}getFogNode(e){return e.fogNode||this.get(e).fogNode||null}getCacheKey(e,t){const s=[e,t],i=this.renderer.info.calls;let r=this.callHashCache.get(s);if(void 0===r||r.callId!==i){const n=this.getEnvironmentNode(e),o=this.getFogNode(e),a=[];t&&a.push(t.getCacheKey(!0)),n&&a.push(n.getCacheKey()),o&&a.push(o.getCacheKey()),r={callId:i,cacheKey:a.join(",")},this.callHashCache.set(s,r)}return r.cacheKey}updateScene(e){this.updateEnvironment(e),this.updateFog(e),this.updateBackground(e)}get isToneMappingState(){return!this.renderer.getRenderTarget()}updateBackground(e){const t=this.get(e),s=e.background;if(s){const i=0===e.backgroundBlurriness&&t.backgroundBlurriness>0||e.backgroundBlurriness>0&&0===t.backgroundBlurriness;if(t.background!==s||i){let i=null;if(!0===s.isCubeTexture||s.mapping===ue||s.mapping===ce)if(e.backgroundBlurriness>0)i=mv(s,Pg);else{let e;e=!0===s.isCubeTexture?Wg(s):Gm(s),i=Vx(e)}else!0===s.isTexture?i=Gm(s,Zy.flipY()).setUpdateMatrix(!0):!0!==s.isColor&&console.error("WebGPUNodes: Unsupported background configuration.",s);t.backgroundNode=i,t.background=s,t.backgroundBlurriness=e.backgroundBlurriness}}else t.backgroundNode&&(delete t.backgroundNode,delete t.background)}updateFog(e){const t=this.get(e),s=e.fog;if(s){if(t.fog!==s){let e=null;s.isFogExp2?e=SC(Zg("color","color",s),Zg("density","float",s)):s.isFog?e=_C(Zg("color","color",s),Zg("near","float",s),Zg("far","float",s)):console.error("WebGPUNodes: Unsupported fog configuration.",s),t.fogNode=e,t.fog=s}}else delete t.fogNode,delete t.fog}updateEnvironment(e){const t=this.get(e),s=e.environment;if(s){if(t.environment!==s){let e=null;!0===s.isCubeTexture?e=Wg(s):!0===s.isTexture?e=Gm(s):console.error("Nodes: Unsupported environment configuration.",s),t.environmentNode=e,t.environment=s}}else t.environmentNode&&(delete t.environmentNode,delete t.environment)}getNodeFrame(e=this.renderer,t=null,s=null,i=null,r=null){const n=this.nodeFrame;return n.renderer=e,n.scene=t,n.object=s,n.camera=i,n.material=r,n}getNodeFrameForRender(e){return this.getNodeFrame(e.renderer,e.scene,e.object,e.camera,e.material)}getOutputCacheKey(){const e=this.renderer;return e.toneMapping+","+e.currentColorSpace}hasOutputChange(e){return uI.get(e)!==this.getOutputCacheKey()}getOutputNode(e){const t=this.renderer,s=this.getOutputCacheKey(),i=Gm(e,Zy).renderOutput(t.toneMapping,t.currentColorSpace);return uI.set(e,s),i}updateBefore(e){const t=e.getNodeBuilderState();for(const s of t.updateBeforeNodes)this.getNodeFrameForRender(e).updateBeforeNode(s)}updateAfter(e){const t=e.getNodeBuilderState();for(const s of t.updateAfterNodes)this.getNodeFrameForRender(e).updateAfterNode(s)}updateForCompute(e){const t=this.getNodeFrame(),s=this.getForCompute(e);for(const e of s.updateNodes)t.updateNode(e)}updateForRender(e){const t=this.getNodeFrameForRender(e),s=e.getNodeBuilderState();for(const e of s.updateNodes)t.updateNode(e)}dispose(){super.dispose(),this.nodeFrame=new hM,this.nodeBuilderCache=new Map}}class dI{constructor(e,t){this.scene=e,this.camera=t}clone(){return Object.assign(new this.constructor,this)}}class pI{constructor(){this.lists=new Bw}get(e,t){const s=this.lists,i=[e,t];let r=s.get(i);return void 0===r&&(r=new dI(e,t),s.set(i,r)),r}dispose(){this.lists=new Bw}}class mI{constructor(){this.lightNodes=new WeakMap,this.materialNodes=new Map,this.toneMappingNodes=new Map,this.colorSpaceNodes=new Map}fromMaterial(e){if(e.isNodeMaterial)return e;let t=null;const s=this.getMaterialNodeClass(e.type);if(null!==s){t=new s;for(const s in e)t[s]=e[s]}return t}addColorSpace(e,t){this.addType(e,t,this.colorSpaceNodes)}getColorSpaceFunction(e){return this.colorSpaceNodes.get(e)||null}addToneMapping(e,t){this.addType(e,t,this.toneMappingNodes)}getToneMappingFunction(e){return this.toneMappingNodes.get(e)||null}getMaterialNodeClass(e){return this.materialNodes.get(e)||null}addMaterial(e,t){this.addType(e,t.name,this.materialNodes)}getLightNodeClass(e){return this.lightNodes.get(e)||null}addLight(e,t){this.addClass(e,t,this.lightNodes)}addType(e,t,s){if(s.has(t))console.warn(`Redefinition of node ${t}`);else{if("function"!=typeof e)throw new Error(`Node class ${e.name} is not a class.`);if("function"==typeof t||"object"==typeof t)throw new Error(`Base class ${t} is not a class.`);s.set(t,e)}}addClass(e,t,s){if(s.has(t))console.warn(`Redefinition of node ${t.name}`);else{if("function"!=typeof e)throw new Error(`Node class ${e.name} is not a class.`);if("function"!=typeof t)throw new Error(`Base class ${t.name} is not a class.`);s.set(t,e)}}}const gI=new no,fI=new Qs,yI=new _i,xI=new na,bI=new or,vI=new Ei;class TI{constructor(e,t={}){this.isRenderer=!0;const{logarithmicDepthBuffer:s=!1,alpha:i=!0,antialias:r=!1,samples:n=0,getFallback:o=null}=t;this.domElement=e.getDomElement(),this.backend=e,this.samples=n||!0===r?4:0,this.autoClear=!0,this.autoClearColor=!0,this.autoClearDepth=!0,this.autoClearStencil=!0,this.alpha=i,this.logarithmicDepthBuffer=s,this.outputColorSpace=Jt,this.toneMapping=0,this.toneMappingExposure=1,this.sortObjects=!0,this.depth=!0,this.stencil=!1,this.clippingPlanes=[],this.info=new qw,this.nodes={library:new mI},this._getFallback=o,this._pixelRatio=1,this._width=this.domElement.width,this._height=this.domElement.height,this._viewport=new _i(0,0,this._width,this._height),this._scissor=new _i(0,0,this._width,this._height),this._scissorTest=!1,this._attributes=null,this._geometries=null,this._nodes=null,this._animation=null,this._bindings=null,this._objects=null,this._pipelines=null,this._bundles=null,this._renderLists=null,this._renderContexts=null,this._textures=null,this._background=null,this._quad=new tA(new xx),this._quad.material.type="Renderer_output",this._currentRenderContext=null,this._opaqueSort=null,this._transparentSort=null,this._frameBufferTarget=null;const a=!0===this.alpha?0:1;this._clearColor=new pE(0,0,0,a),this._clearDepth=1,this._clearStencil=0,this._renderTarget=null,this._activeCubeFace=0,this._activeMipmapLevel=0,this._mrt=null,this._renderObjectFunction=null,this._currentRenderObjectFunction=null,this._currentRenderBundle=null,this._handleObjectFunction=this._renderObjectDirect,this._initialized=!1,this._initPromise=null,this._compilationPromises=null,this.transparent=!0,this.opaque=!0,this.shadowMap={enabled:!1,type:1},this.xr={enabled:!1},this.debug={checkShaderErrors:!0,onShaderError:null,getShaderAsync:async(e,t,s)=>{await this.compileAsync(e,t);const i=this._renderLists.get(e,t),r=this._renderContexts.get(e,t,this._renderTarget),n=e.overrideMaterial||s.material,o=this._objects.get(s,n,e,t,i.lightsNode,r),{fragmentShader:a,vertexShader:h}=o.getNodeBuilderState();return{fragmentShader:a,vertexShader:h}}}}async init(){if(this._initialized)throw new Error("Renderer: Backend has already been initialized.");return null!==this._initPromise||(this._initPromise=new Promise((async(e,t)=>{let s=this.backend;try{await s.init(this)}catch(e){if(null===this._getFallback)return void t(e);try{this.backend=s=this._getFallback(e),await s.init(this)}catch(e){return void t(e)}}this._nodes=new cI(this,s),this._animation=new Ew(this._nodes,this.info),this._attributes=new Gw(s),this._background=new hI(this,this._nodes),this._geometries=new jw(this._attributes,this.info),this._textures=new dE(this,s,this.info),this._pipelines=new Kw(s,this._nodes),this._bindings=new Qw(s,this._nodes,this._textures,this._attributes,this._pipelines,this.info),this._objects=new Uw(this,this._nodes,this._geometries,this._pipelines,this._bindings,this.info),this._renderLists=new oE,this._bundles=new pI,this._renderContexts=new uE,this._initialized=!0,e()}))),this._initPromise}get coordinateSystem(){return this.backend.coordinateSystem}async compileAsync(e,t,s=null){!1===this._initialized&&await this.init();const i=this._nodes.nodeFrame,r=i.renderId,n=this._currentRenderContext,o=this._currentRenderObjectFunction,a=this._compilationPromises,h=!0===e.isScene?e:gI;null===s&&(s=e);const l=this._renderTarget,u=this._renderContexts.get(s,t,l),c=this._activeMipmapLevel,d=[];this._currentRenderContext=u,this._currentRenderObjectFunction=this.renderObject,this._handleObjectFunction=this._createObjectPipeline,this._compilationPromises=d,i.renderId++,i.update(),u.depth=this.depth,u.stencil=this.stencil,u.clippingContext||(u.clippingContext=new Pw),u.clippingContext.updateGlobal(this,t),h.onBeforeRender(this,e,t,l);const p=this._renderLists.get(e,t);if(p.begin(),this._projectObject(e,t,0,p),s!==e&&s.traverseVisible((function(e){e.isLight&&e.layers.test(t.layers)&&p.pushLight(e)})),p.finish(),null!==l){this._textures.updateRenderTarget(l,c);const e=this._textures.get(l);u.textures=e.textures,u.depthTexture=e.depthTexture}else u.textures=null,u.depthTexture=null;this._nodes.updateScene(h),this._background.update(h,p,u);const m=p.opaque,g=p.transparent,f=p.lightsNode;!0===this.opaque&&m.length>0&&this._renderObjects(m,t,h,f),!0===this.transparent&&g.length>0&&this._renderObjects(g,t,h,f),i.renderId=r,this._currentRenderContext=n,this._currentRenderObjectFunction=o,this._compilationPromises=a,this._handleObjectFunction=this._renderObjectDirect,await Promise.all(d)}async renderAsync(e,t){!1===this._initialized&&await this.init();const s=this._renderScene(e,t);await this.backend.resolveTimestampAsync(s,"render")}setMRT(e){return this._mrt=e,this}getMRT(){return this._mrt}_renderBundle(e,t,s){const{object:i,camera:r,renderList:n}=e,o=this._currentRenderContext,a=this._bundles.get(i,r),h=this.backend.get(a);void 0===h.renderContexts&&(h.renderContexts=new Set);const l=!1===h.renderContexts.has(o)||!0===i.needsUpdate;if(h.renderContexts.add(o),l){this.backend.beginBundle(o),void 0!==h.renderObjects&&!0!==i.needsUpdate||(h.renderObjects=[]),this._currentRenderBundle=a;const e=n.opaque;e.length>0&&this._renderObjects(e,r,t,s),this._currentRenderBundle=null,this.backend.finishBundle(o,a),i.needsUpdate=!1}else{const e=h.renderObjects;for(let t=0,s=e.length;t>=c,p.viewportValue.height>>=c,p.viewportValue.minDepth=x,p.viewportValue.maxDepth=b,p.viewport=!1===p.viewportValue.equals(yI),p.scissorValue.copy(f).multiplyScalar(y).floor(),p.scissor=this._scissorTest&&!1===p.scissorValue.equals(yI),p.scissorValue.width>>=c,p.scissorValue.height>>=c,p.clippingContext||(p.clippingContext=new Pw),p.clippingContext.updateGlobal(this,t),h.onBeforeRender(this,e,t,d),bI.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),xI.setFromProjectionMatrix(bI,m);const v=this._renderLists.get(e,t);if(v.begin(),this._projectObject(e,t,0,v),v.finish(),!0===this.sortObjects&&v.sort(this._opaqueSort,this._transparentSort),null!==d){this._textures.updateRenderTarget(d,c);const e=this._textures.get(d);p.textures=e.textures,p.depthTexture=e.depthTexture,p.width=e.width,p.height=e.height,p.renderTarget=d,p.depth=d.depthBuffer,p.stencil=d.stencilBuffer}else p.textures=null,p.depthTexture=null,p.width=this.domElement.width,p.height=this.domElement.height,p.depth=this.depth,p.stencil=this.stencil;p.width>>=c,p.height>>=c,p.activeCubeFace=u,p.activeMipmapLevel=c,p.occlusionQueryCount=v.occlusionQueryCount,this._nodes.updateScene(h),this._background.update(h,v,p),this.backend.beginRender(p);const T=v.opaque,_=v.transparent,w=v.bundles,S=v.lightsNode;if(w.length>0&&this._renderBundles(w,h,S),!0===this.opaque&&T.length>0&&this._renderObjects(T,t,h,S),!0===this.transparent&&_.length>0&&this._renderObjects(_,t,h,S),this.backend.finishRender(p),r.renderId=n,this._currentRenderContext=o,this._currentRenderObjectFunction=a,null!==i){this.setRenderTarget(l,u,c);const e=this._quad;this._nodes.hasOutputChange(d.texture)&&(e.material.fragmentNode=this._nodes.getOutputNode(d.texture),e.material.needsUpdate=!0),this._renderScene(e,e.camera,!1)}return h.onAfterRender(this,e,t,d),p}getMaxAnisotropy(){return this.backend.getMaxAnisotropy()}getActiveCubeFace(){return this._activeCubeFace}getActiveMipmapLevel(){return this._activeMipmapLevel}async setAnimationLoop(e){!1===this._initialized&&await this.init(),this._animation.setAnimationLoop(e)}async getArrayBufferAsync(e){return await this.backend.getArrayBufferAsync(e)}getContext(){return this.backend.getContext()}getPixelRatio(){return this._pixelRatio}getDrawingBufferSize(e){return e.set(this._width*this._pixelRatio,this._height*this._pixelRatio).floor()}getSize(e){return e.set(this._width,this._height)}setPixelRatio(e=1){this._pixelRatio=e,this.setSize(this._width,this._height,!1)}setDrawingBufferSize(e,t,s){this._width=e,this._height=t,this._pixelRatio=s,this.domElement.width=Math.floor(e*s),this.domElement.height=Math.floor(t*s),this.setViewport(0,0,e,t),this._initialized&&this.backend.updateSize()}setSize(e,t,s=!0){this._width=e,this._height=t,this.domElement.width=Math.floor(e*this._pixelRatio),this.domElement.height=Math.floor(t*this._pixelRatio),!0===s&&(this.domElement.style.width=e+"px",this.domElement.style.height=t+"px"),this.setViewport(0,0,e,t),this._initialized&&this.backend.updateSize()}setOpaqueSort(e){this._opaqueSort=e}setTransparentSort(e){this._transparentSort=e}getScissor(e){const t=this._scissor;return e.x=t.x,e.y=t.y,e.width=t.width,e.height=t.height,e}setScissor(e,t,s,i){const r=this._scissor;e.isVector4?r.copy(e):r.set(e,t,s,i)}getScissorTest(){return this._scissorTest}setScissorTest(e){this._scissorTest=e,this.backend.setScissorTest(e)}getViewport(e){return e.copy(this._viewport)}setViewport(e,t,s,i,r=0,n=1){const o=this._viewport;e.isVector4?o.copy(e):o.set(e,t,s,i),o.minDepth=r,o.maxDepth=n}getClearColor(e){return e.copy(this._clearColor)}setClearColor(e,t=1){this._clearColor.set(e),this._clearColor.a=t}getClearAlpha(){return this._clearColor.a}setClearAlpha(e){this._clearColor.a=e}getClearDepth(){return this._clearDepth}setClearDepth(e){this._clearDepth=e}getClearStencil(){return this._clearStencil}setClearStencil(e){this._clearStencil=e}isOccluded(e){const t=this._currentRenderContext;return t&&this.backend.isOccluded(t,e)}clear(e=!0,t=!0,s=!0){if(!1===this._initialized)return console.warn("THREE.Renderer: .clear() called before the backend is initialized. Try using .clearAsync() instead."),this.clearAsync(e,t,s);const i=this._renderTarget||this._getFrameBufferTarget();let r=null;if(null!==i&&(this._textures.updateRenderTarget(i),r=this._textures.get(i)),this.backend.clear(e,t,s,r),null!==i&&null===this._renderTarget){const e=this._quad;this._nodes.hasOutputChange(i.texture)&&(e.material.fragmentNode=this._nodes.getOutputNode(i.texture),e.material.needsUpdate=!0),this._renderScene(e,e.camera,!1)}}clearColor(){return this.clear(!0,!1,!1)}clearDepth(){return this.clear(!1,!0,!1)}clearStencil(){return this.clear(!1,!1,!0)}async clearAsync(e=!0,t=!0,s=!0){!1===this._initialized&&await this.init(),this.clear(e,t,s)}clearColorAsync(){return this.clearAsync(!0,!1,!1)}clearDepthAsync(){return this.clearAsync(!1,!0,!1)}clearStencilAsync(){return this.clearAsync(!1,!1,!0)}get currentToneMapping(){return null!==this._renderTarget?0:this.toneMapping}get currentColorSpace(){return null!==this._renderTarget?Zt:this.outputColorSpace}dispose(){this.info.dispose(),this._animation.dispose(),this._objects.dispose(),this._pipelines.dispose(),this._nodes.dispose(),this._bindings.dispose(),this._renderLists.dispose(),this._renderContexts.dispose(),this._textures.dispose(),this.setRenderTarget(null),this.setAnimationLoop(null)}setRenderTarget(e,t=0,s=0){this._renderTarget=e,this._activeCubeFace=t,this._activeMipmapLevel=s}getRenderTarget(){return this._renderTarget}setRenderObjectFunction(e){this._renderObjectFunction=e}getRenderObjectFunction(){return this._renderObjectFunction}async computeAsync(e){!1===this._initialized&&await this.init();const t=this._nodes.nodeFrame,s=t.renderId;this.info.calls++,this.info.compute.calls++,this.info.compute.frameCalls++,t.renderId=this.info.calls;const i=this.backend,r=this._pipelines,n=this._bindings,o=this._nodes,a=Array.isArray(e)?e:[e];if(void 0===a[0]||!0!==a[0].isComputeNode)throw new Error("THREE.Renderer: .compute() expects a ComputeNode.");i.beginCompute(e);for(const t of a){if(!1===r.has(t)){const e=()=>{t.removeEventListener("dispose",e),r.delete(t),n.delete(t),o.delete(t)};t.addEventListener("dispose",e),t.onInit({renderer:this})}o.updateForCompute(t),n.updateForCompute(t);const s=n.getForCompute(t),a=r.getForCompute(t,s);i.compute(e,t,s,a)}i.finishCompute(e),await this.backend.resolveTimestampAsync(e,"compute"),t.renderId=s}async hasFeatureAsync(e){return!1===this._initialized&&await this.init(),this.backend.hasFeature(e)}hasFeature(e){return!1===this._initialized?(console.warn("THREE.Renderer: .hasFeature() called before the backend is initialized. Try using .hasFeatureAsync() instead."),!1):this.backend.hasFeature(e)}copyFramebufferToTexture(e){const t=this._currentRenderContext;this._textures.updateTexture(e),this.backend.copyFramebufferToTexture(e,t)}copyTextureToTexture(e,t,s=null,i=null,r=0){this._textures.updateTexture(e),this._textures.updateTexture(t),this.backend.copyTextureToTexture(e,t,s,i,r)}readRenderTargetPixelsAsync(e,t,s,i,r,n=0){return this.backend.copyTextureToBuffer(e.textures[n],t,s,i,r)}_projectObject(e,t,s,i){if(!1===e.visible)return;if(e.layers.test(t.layers))if(e.isGroup)s=e.renderOrder;else if(e.isLOD)!0===e.autoUpdate&&e.update(t);else if(e.isLight)i.pushLight(e);else if(e.isSprite){if(!e.frustumCulled||xI.intersectsSprite(e)){!0===this.sortObjects&&vI.setFromMatrixPosition(e.matrixWorld).applyMatrix4(bI);const t=e.geometry,r=e.material;r.visible&&i.push(e,t,r,s,vI.z,null)}}else if(e.isLineLoop)console.error("THREE.Renderer: Objects of type THREE.LineLoop are not supported. Please use THREE.Line or THREE.LineSegments.");else if((e.isMesh||e.isLine||e.isPoints)&&(!e.frustumCulled||xI.intersectsObject(e))){const t=e.geometry,r=e.material;if(!0===this.sortObjects&&(null===t.boundingSphere&&t.computeBoundingSphere(),vI.copy(t.boundingSphere.center).applyMatrix4(e.matrixWorld).applyMatrix4(bI)),Array.isArray(r)){const n=t.groups;for(let o=0,a=n.length;o0?i:"";t=`${e.name} {\n\t${s} ${r.name}[${n}];\n};\n`}else{t=`${this.getVectorType(r.type)} ${this.getPropertyName(r,e)};`,n=!0}const o=r.node.precision;if(null!==o&&(t=VI[o]+" "+t),n){t="\t"+t;const e=r.groupNode.name;(i[e]||(i[e]=[])).push(t)}else t="uniform "+t,s.push(t)}let r="";for(const t in i){const s=i[t];r+=this._getGLSLUniformStruct(e+"_"+t,s.join("\n"))+"\n"}return r+=s.join("\n"),r}getTypeFromAttribute(e){let t=super.getTypeFromAttribute(e);if(/^[iu]/.test(t)&&e.gpuType!==Ee){let s=e;e.isInterleavedBufferAttribute&&(s=e.data);const i=s.array;!1==(i instanceof Uint32Array||i instanceof Int32Array)&&(t=t.slice(1))}return t}getAttributes(e){let t="";if("vertex"===e||"compute"===e){const e=this.getAttributesArray();let s=0;for(const i of e)t+=`layout( location = ${s++} ) in ${i.type} ${i.name};\n`}return t}getStructMembers(e){const t=[],s=e.getMemberTypes();for(let e=0;ee*t),1)}u`}getDrawIndex(){return this.renderer.backend.extensions.has("WEBGL_multi_draw")?"uint( gl_DrawID )":null}getFrontFacing(){return"gl_FrontFacing"}getFragCoord(){return"gl_FragCoord.xy"}getFragDepth(){return"gl_FragDepth"}enableExtension(e,t,s=this.shaderStage){const i=this.extensions[s]||(this.extensions[s]=new Map);!1===i.has(e)&&i.set(e,{name:e,behavior:t})}getExtensions(e){const t=[];if("vertex"===e){const t=this.renderer.backend.extensions;this.object.isBatchedMesh&&t.has("WEBGL_multi_draw")&&this.enableExtension("GL_ANGLE_multi_draw","require",e)}const s=this.extensions[e];if(void 0!==s)for(const{name:e,behavior:i}of s.values())t.push(`#extension ${e} : ${i}`);return t.join("\n")}isAvailable(e){let t=DI[e];if(void 0===t){if("float32Filterable"===e){const e=this.renderer.backend.extensions;e.has("OES_texture_float_linear")?(e.get("OES_texture_float_linear"),t=!0):t=!1}DI[e]=t}return t}isFlipY(){return!0}registerTransform(e,t){this.transforms.push({varyingName:e,attributeNode:t})}getTransforms(){const e=this.transforms;let t="";for(let s=0;s0&&(s+="\n"),s+=`\t// flow -> ${n}\n\t`),s+=`${i.code}\n\t`,e===r&&"compute"!==t&&(s+="// result\n\t","vertex"===t?(s+="gl_Position = ",s+=`${i.result};`):"fragment"===t&&(e.outputNode.isOutputStructNode||(s+="fragColor = ",s+=`${i.result};`)))}const n=e[t];n.extensions=this.getExtensions(t),n.uniforms=this.getUniforms(t),n.attributes=this.getAttributes(t),n.varyings=this.getVaryings(t),n.vars=this.getVars(t),n.structs=this.getStructs(t),n.codes=this.getCodes(t),n.transforms=this.getTransforms(t),n.flow=s}null!==this.material?(this.vertexShader=this._getGLSLVertexCode(e.vertex),this.fragmentShader=this._getGLSLFragmentCode(e.fragment)):this.computeShader=this._getGLSLVertexCode(e.compute)}getUniformFromNode(e,t,s,i=null){const r=super.getUniformFromNode(e,t,s,i),n=this.getDataFromNode(e,s,this.globalCache);let o=n.uniformGPU;if(void 0===o){const i=e.groupNode,a=i.name,h=this.getBindGroupArray(a,s);if("texture"===t)o=new zI(r.name,r.node,i),h.push(o);else if("cubeTexture"===t)o=new UI(r.name,r.node,i),h.push(o);else if("texture3D"===t)o=new LI(r.name,r.node,i),h.push(o);else if("buffer"===t){e.name=`NodeBuffer_${e.id}`,r.name=`buffer${e.id}`;const t=new CI(e,i);t.name=e.name,h.push(t),o=t}else{const e=this.uniformGroups[s]||(this.uniformGroups[s]={});let n=e[a];void 0===n&&(n=new II(s+"_"+a,i),e[a]=n,h.push(n)),o=this.getNodeUniform(r,t),n.addUniform(o)}n.uniformGPU=o}return r}}let WI=null,HI=null,jI=null;class qI{constructor(e={}){this.parameters=Object.assign({},e),this.data=new WeakMap,this.renderer=null,this.domElement=null}async init(e){this.renderer=e}begin(){}finish(){}draw(){}createProgram(){}destroyProgram(){}createBindings(){}updateBindings(){}createRenderPipeline(){}createComputePipeline(){}destroyPipeline(){}needsRenderUpdate(){}getRenderCacheKey(){}createNodeBuilder(){}createSampler(){}createDefaultTexture(){}createTexture(){}copyTextureToBuffer(){}createAttribute(){}createIndexAttribute(){}updateAttribute(){}destroyAttribute(){}getContext(){}updateSize(){}resolveTimestampAsync(){}hasFeatureAsync(){}hasFeature(){}getInstanceCount(e){const{object:t,geometry:s}=e;return s.isInstancedBufferGeometry?s.instanceCount:t.count>1?t.count:1}getDrawingBufferSize(){return WI=WI||new Qs,this.renderer.getDrawingBufferSize(WI)}getScissor(){return HI=HI||new _i,this.renderer.getScissor(HI)}setScissorTest(){}getClearColor(){const e=this.renderer;return jI=jI||new pE,e.getClearColor(jI),jI.getRGB(jI,this.renderer.currentColorSpace),jI}getDomElement(){let t=this.domElement;return null===t&&(t=void 0!==this.parameters.canvas?this.parameters.canvas:ni(),"setAttribute"in t&&t.setAttribute("data-engine",`three.js r${e} webgpu`),this.domElement=t),t}set(e,t){this.data.set(e,t)}get(e){let t=this.data.get(e);return void 0===t&&(t={},this.data.set(e,t)),t}has(e){return this.data.has(e)}delete(e){this.data.delete(e)}}let $I=0;class XI{constructor(e,t){this.buffers=[e.bufferGPU,t],this.type=e.type,this.bufferType=e.bufferType,this.pbo=e.pbo,this.byteLength=e.byteLength,this.bytesPerElement=e.BYTES_PER_ELEMENT,this.version=e.version,this.isInteger=e.isInteger,this.activeBufferIndex=0,this.baseId=e.id}get id(){return`${this.baseId}|${this.activeBufferIndex}`}get bufferGPU(){return this.buffers[this.activeBufferIndex]}get transformBuffer(){return this.buffers[1^this.activeBufferIndex]}switchBuffers(){this.activeBufferIndex^=1}}class YI{constructor(e){this.backend=e}createAttribute(e,t){const s=this.backend,{gl:i}=s,r=e.array,n=e.usage||i.STATIC_DRAW,o=e.isInterleavedBufferAttribute?e.data:e,a=s.get(o);let h,l=a.bufferGPU;if(void 0===l&&(l=this._createBuffer(i,t,r,n),a.bufferGPU=l,a.bufferType=t,a.version=o.version),r instanceof Float32Array)h=i.FLOAT;else if(r instanceof Uint16Array)h=e.isFloat16BufferAttribute?i.HALF_FLOAT:i.UNSIGNED_SHORT;else if(r instanceof Int16Array)h=i.SHORT;else if(r instanceof Uint32Array)h=i.UNSIGNED_INT;else if(r instanceof Int32Array)h=i.INT;else if(r instanceof Int8Array)h=i.BYTE;else if(r instanceof Uint8Array)h=i.UNSIGNED_BYTE;else{if(!(r instanceof Uint8ClampedArray))throw new Error("THREE.WebGLBackend: Unsupported buffer data format: "+r);h=i.UNSIGNED_BYTE}let u={bufferGPU:l,bufferType:t,type:h,byteLength:r.byteLength,bytesPerElement:r.BYTES_PER_ELEMENT,version:e.version,pbo:e.pbo,isInteger:h===i.INT||h===i.UNSIGNED_INT||e.gpuType===Ee,id:$I++};if(e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute){const e=this._createBuffer(i,t,r,n);u=new XI(u,e)}s.set(e,u)}updateAttribute(e){const t=this.backend,{gl:s}=t,i=e.array,r=e.isInterleavedBufferAttribute?e.data:e,n=t.get(r),o=n.bufferType,a=e.isInterleavedBufferAttribute?e.data.updateRanges:e.updateRanges;if(s.bindBuffer(o,n.bufferGPU),0===a.length)s.bufferSubData(o,0,i);else{for(let e=0,t=a.length;e{!function r(){const n=e.clientWaitSync(t,e.SYNC_FLUSH_COMMANDS_BIT,0);if(n===e.WAIT_FAILED)return e.deleteSync(t),void i();n!==e.TIMEOUT_EXPIRED?(e.deleteSync(t),s()):requestAnimationFrame(r)}()}))}}let tP,sP,iP,rP=!1;class nP{constructor(e){this.backend=e,this.gl=e.gl,this.extensions=e.extensions,this.defaultTextures={},!1===rP&&(this._init(this.gl),rP=!0)}_init(e){tP={[pe]:e.REPEAT,[me]:e.CLAMP_TO_EDGE,[ge]:e.MIRRORED_REPEAT},sP={[fe]:e.NEAREST,[ye]:e.NEAREST_MIPMAP_NEAREST,[be]:e.NEAREST_MIPMAP_LINEAR,[Te]:e.LINEAR,[_e]:e.LINEAR_MIPMAP_NEAREST,[Se]:e.LINEAR_MIPMAP_LINEAR},iP={512:e.NEVER,519:e.ALWAYS,[Ts]:e.LESS,515:e.LEQUAL,514:e.EQUAL,518:e.GEQUAL,516:e.GREATER,517:e.NOTEQUAL}}filterFallback(e){const{gl:t}=this;return e===fe||e===ye||e===be?t.NEAREST:t.LINEAR}getGLTextureType(e){const{gl:t}=this;let s;return s=!0===e.isCubeTexture?t.TEXTURE_CUBE_MAP:!0===e.isDataArrayTexture||!0===e.isCompressedArrayTexture?t.TEXTURE_2D_ARRAY:!0===e.isData3DTexture?t.TEXTURE_3D:t.TEXTURE_2D,s}getInternalFormat(e,t,s,i,r=!1){const{gl:n,extensions:o}=this;if(null!==e){if(void 0!==n[e])return n[e];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+e+"'")}let a=t;return t===n.RED&&(s===n.FLOAT&&(a=n.R32F),s===n.HALF_FLOAT&&(a=n.R16F),s===n.UNSIGNED_BYTE&&(a=n.R8),s===n.UNSIGNED_SHORT&&(a=n.R16),s===n.UNSIGNED_INT&&(a=n.R32UI),s===n.BYTE&&(a=n.R8I),s===n.SHORT&&(a=n.R16I),s===n.INT&&(a=n.R32I)),t===n.RED_INTEGER&&(s===n.UNSIGNED_BYTE&&(a=n.R8UI),s===n.UNSIGNED_SHORT&&(a=n.R16UI),s===n.UNSIGNED_INT&&(a=n.R32UI),s===n.BYTE&&(a=n.R8I),s===n.SHORT&&(a=n.R16I),s===n.INT&&(a=n.R32I)),t===n.RG&&(s===n.FLOAT&&(a=n.RG32F),s===n.HALF_FLOAT&&(a=n.RG16F),s===n.UNSIGNED_BYTE&&(a=n.RG8),s===n.UNSIGNED_SHORT&&(a=n.RG16),s===n.UNSIGNED_INT&&(a=n.RG32UI),s===n.BYTE&&(a=n.RG8I),s===n.SHORT&&(a=n.RG16I),s===n.INT&&(a=n.RG32I)),t===n.RG_INTEGER&&(s===n.UNSIGNED_BYTE&&(a=n.RG8UI),s===n.UNSIGNED_SHORT&&(a=n.RG16UI),s===n.UNSIGNED_INT&&(a=n.RG32UI),s===n.BYTE&&(a=n.RG8I),s===n.SHORT&&(a=n.RG16I),s===n.INT&&(a=n.RG32I)),t===n.RGB&&(s===n.FLOAT&&(a=n.RGB32F),s===n.HALF_FLOAT&&(a=n.RGB16F),s===n.UNSIGNED_BYTE&&(a=n.RGB8),s===n.UNSIGNED_SHORT&&(a=n.RGB16),s===n.UNSIGNED_INT&&(a=n.RGB32UI),s===n.BYTE&&(a=n.RGB8I),s===n.SHORT&&(a=n.RGB16I),s===n.INT&&(a=n.RGB32I),s===n.UNSIGNED_BYTE&&(a=i===Jt&&!1===r?n.SRGB8:n.RGB8),s===n.UNSIGNED_SHORT_5_6_5&&(a=n.RGB565),s===n.UNSIGNED_SHORT_5_5_5_1&&(a=n.RGB5_A1),s===n.UNSIGNED_SHORT_4_4_4_4&&(a=n.RGB4),s===n.UNSIGNED_INT_5_9_9_9_REV&&(a=n.RGB9_E5)),t===n.RGB_INTEGER&&(s===n.UNSIGNED_BYTE&&(a=n.RGB8UI),s===n.UNSIGNED_SHORT&&(a=n.RGB16UI),s===n.UNSIGNED_INT&&(a=n.RGB32UI),s===n.BYTE&&(a=n.RGB8I),s===n.SHORT&&(a=n.RGB16I),s===n.INT&&(a=n.RGB32I)),t===n.RGBA&&(s===n.FLOAT&&(a=n.RGBA32F),s===n.HALF_FLOAT&&(a=n.RGBA16F),s===n.UNSIGNED_BYTE&&(a=n.RGBA8),s===n.UNSIGNED_SHORT&&(a=n.RGBA16),s===n.UNSIGNED_INT&&(a=n.RGBA32UI),s===n.BYTE&&(a=n.RGBA8I),s===n.SHORT&&(a=n.RGBA16I),s===n.INT&&(a=n.RGBA32I),s===n.UNSIGNED_BYTE&&(a=i===Jt&&!1===r?n.SRGB8_ALPHA8:n.RGBA8),s===n.UNSIGNED_SHORT_4_4_4_4&&(a=n.RGBA4),s===n.UNSIGNED_SHORT_5_5_5_1&&(a=n.RGB5_A1)),t===n.RGBA_INTEGER&&(s===n.UNSIGNED_BYTE&&(a=n.RGBA8UI),s===n.UNSIGNED_SHORT&&(a=n.RGBA16UI),s===n.UNSIGNED_INT&&(a=n.RGBA32UI),s===n.BYTE&&(a=n.RGBA8I),s===n.SHORT&&(a=n.RGBA16I),s===n.INT&&(a=n.RGBA32I)),t===n.DEPTH_COMPONENT&&(s===n.UNSIGNED_INT&&(a=n.DEPTH24_STENCIL8),s===n.FLOAT&&(a=n.DEPTH_COMPONENT32F)),t===n.DEPTH_STENCIL&&s===n.UNSIGNED_INT_24_8&&(a=n.DEPTH24_STENCIL8),a!==n.R16F&&a!==n.R32F&&a!==n.RG16F&&a!==n.RG32F&&a!==n.RGBA16F&&a!==n.RGBA32F||o.get("EXT_color_buffer_float"),a}setTextureParameters(e,t){const{gl:s,extensions:i,backend:r}=this;s.pixelStorei(s.UNPACK_FLIP_Y_WEBGL,t.flipY),s.pixelStorei(s.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),s.pixelStorei(s.UNPACK_ALIGNMENT,t.unpackAlignment),s.pixelStorei(s.UNPACK_COLORSPACE_CONVERSION_WEBGL,s.NONE),s.texParameteri(e,s.TEXTURE_WRAP_S,tP[t.wrapS]),s.texParameteri(e,s.TEXTURE_WRAP_T,tP[t.wrapT]),e!==s.TEXTURE_3D&&e!==s.TEXTURE_2D_ARRAY||s.texParameteri(e,s.TEXTURE_WRAP_R,tP[t.wrapR]),s.texParameteri(e,s.TEXTURE_MAG_FILTER,sP[t.magFilter]);const n=void 0!==t.mipmaps&&t.mipmaps.length>0,o=t.minFilter===Te&&n?Se:t.minFilter;if(s.texParameteri(e,s.TEXTURE_MIN_FILTER,sP[o]),t.compareFunction&&(s.texParameteri(e,s.TEXTURE_COMPARE_MODE,s.COMPARE_REF_TO_TEXTURE),s.texParameteri(e,s.TEXTURE_COMPARE_FUNC,iP[t.compareFunction])),!0===i.has("EXT_texture_filter_anisotropic")){if(t.magFilter===fe)return;if(t.minFilter!==be&&t.minFilter!==Se)return;if(t.type===Ie&&!1===i.has("OES_texture_float_linear"))return;if(t.anisotropy>1){const n=i.get("EXT_texture_filter_anisotropic");s.texParameterf(e,n.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(t.anisotropy,r.getMaxAnisotropy()))}}}createDefaultTexture(e){const{gl:t,backend:s,defaultTextures:i}=this,r=this.getGLTextureType(e);let n=i[r];void 0===n&&(n=t.createTexture(),s.state.bindTexture(r,n),t.texParameteri(r,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(r,t.TEXTURE_MAG_FILTER,t.NEAREST),i[r]=n),s.set(e,{textureGPU:n,glTextureType:r,isDefault:!0})}createTexture(e,t){const{gl:s,backend:i}=this,{levels:r,width:n,height:o,depth:a}=t,h=i.utils.convert(e.format,e.colorSpace),l=i.utils.convert(e.type),u=this.getInternalFormat(e.internalFormat,h,l,e.colorSpace,e.isVideoTexture),c=s.createTexture(),d=this.getGLTextureType(e);i.state.bindTexture(d,c),this.setTextureParameters(d,e),e.isDataArrayTexture||e.isCompressedArrayTexture?s.texStorage3D(s.TEXTURE_2D_ARRAY,r,u,n,o,a):e.isData3DTexture?s.texStorage3D(s.TEXTURE_3D,r,u,n,o,a):e.isVideoTexture||s.texStorage2D(d,r,u,n,o),i.set(e,{textureGPU:c,glTextureType:d,glFormat:h,glType:l,glInternalFormat:u})}copyBufferToTexture(e,t){const{gl:s,backend:i}=this,{textureGPU:r,glTextureType:n,glFormat:o,glType:a}=i.get(t),{width:h,height:l}=t.source.data;s.bindBuffer(s.PIXEL_UNPACK_BUFFER,e),i.state.bindTexture(n,r),s.pixelStorei(s.UNPACK_FLIP_Y_WEBGL,!1),s.pixelStorei(s.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),s.texSubImage2D(n,0,0,0,h,l,o,a,0),s.bindBuffer(s.PIXEL_UNPACK_BUFFER,null),i.state.unbindTexture()}updateTexture(e,t){const{gl:s}=this,{width:i,height:r}=t,{textureGPU:n,glTextureType:o,glFormat:a,glType:h,glInternalFormat:l}=this.backend.get(e);if(e.isRenderTargetTexture||void 0===n)return;const u=e=>e.isDataTexture?e.image.data:e instanceof ImageBitmap||e instanceof OffscreenCanvas||e instanceof HTMLImageElement||e instanceof HTMLCanvasElement?e:e.data;if(this.backend.state.bindTexture(o,n),this.setTextureParameters(o,e),e.isCompressedTexture){const i=e.mipmaps,r=t.image;for(let t=0;t0){let a,h;!0===e.isDepthTexture?(a=s.DEPTH_BUFFER_BIT,h=s.DEPTH_ATTACHMENT,t.stencil&&(a|=s.STENCIL_BUFFER_BIT)):(a=s.COLOR_BUFFER_BIT,h=s.COLOR_ATTACHMENT0);const l=s.createFramebuffer();i.bindFramebuffer(s.DRAW_FRAMEBUFFER,l),s.framebufferTexture2D(s.DRAW_FRAMEBUFFER,h,s.TEXTURE_2D,r,0),s.blitFramebuffer(0,0,n,o,0,0,n,o,a,s.NEAREST),s.deleteFramebuffer(l)}else i.bindTexture(s.TEXTURE_2D,r),s.copyTexSubImage2D(s.TEXTURE_2D,0,0,0,0,0,n,o),i.unbindTexture();e.generateMipmaps&&this.generateMipmaps(e),this.backend._setFramebuffer(t)}setupRenderBufferStorage(e,t){const{gl:s}=this,i=t.renderTarget,{samples:r,depthTexture:n,depthBuffer:o,stencilBuffer:a,width:h,height:l}=i;if(s.bindRenderbuffer(s.RENDERBUFFER,e),o&&!a){let t=s.DEPTH_COMPONENT24;r>0?(n&&n.isDepthTexture&&n.type===s.FLOAT&&(t=s.DEPTH_COMPONENT32F),s.renderbufferStorageMultisample(s.RENDERBUFFER,r,t,h,l)):s.renderbufferStorage(s.RENDERBUFFER,t,h,l),s.framebufferRenderbuffer(s.FRAMEBUFFER,s.DEPTH_ATTACHMENT,s.RENDERBUFFER,e)}else o&&a&&(r>0?s.renderbufferStorageMultisample(s.RENDERBUFFER,r,s.DEPTH24_STENCIL8,h,l):s.renderbufferStorage(s.RENDERBUFFER,s.DEPTH_STENCIL,h,l),s.framebufferRenderbuffer(s.FRAMEBUFFER,s.DEPTH_STENCIL_ATTACHMENT,s.RENDERBUFFER,e))}async copyTextureToBuffer(e,t,s,i,r){const{backend:n,gl:o}=this,{textureGPU:a,glFormat:h,glType:l}=this.backend.get(e),u=o.createFramebuffer();o.bindFramebuffer(o.READ_FRAMEBUFFER,u),o.framebufferTexture2D(o.READ_FRAMEBUFFER,o.COLOR_ATTACHMENT0,o.TEXTURE_2D,a,0);const c=this._getTypedArrayType(l),d=i*r*this._getBytesPerTexel(h),p=o.createBuffer();o.bindBuffer(o.PIXEL_PACK_BUFFER,p),o.bufferData(o.PIXEL_PACK_BUFFER,d,o.STREAM_READ),o.readPixels(t,s,i,r,h,l,0),o.bindBuffer(o.PIXEL_PACK_BUFFER,null),await n.utils._clientWaitAsync();const m=new c(d/c.BYTES_PER_ELEMENT);return o.bindBuffer(o.PIXEL_PACK_BUFFER,p),o.getBufferSubData(o.PIXEL_PACK_BUFFER,0,m),o.bindBuffer(o.PIXEL_PACK_BUFFER,null),o.deleteFramebuffer(u),m}_getTypedArrayType(e){const{gl:t}=this;if(e===t.UNSIGNED_BYTE)return Uint8Array;if(e===t.UNSIGNED_SHORT_4_4_4_4)return Uint16Array;if(e===t.UNSIGNED_SHORT_5_5_5_1)return Uint16Array;if(e===t.UNSIGNED_SHORT_5_6_5)return Uint16Array;if(e===t.UNSIGNED_SHORT)return Uint16Array;if(e===t.UNSIGNED_INT)return Uint32Array;if(e===t.FLOAT)return Float32Array;throw new Error(`Unsupported WebGL type: ${e}`)}_getBytesPerTexel(e){const{gl:t}=this;return e===t.RGBA?4:e===t.RGB?3:e===t.ALPHA?1:void 0}}class oP{constructor(e){this.backend=e,this.gl=this.backend.gl,this.availableExtensions=this.gl.getSupportedExtensions(),this.extensions={}}get(e){let t=this.extensions[e];return void 0===t&&(t=this.gl.getExtension(e),this.extensions[e]=t),t}has(e){return this.availableExtensions.includes(e)}}class aP{constructor(e){this.backend=e,this.maxAnisotropy=null}getMaxAnisotropy(){if(null!==this.maxAnisotropy)return this.maxAnisotropy;const e=this.backend.gl,t=this.backend.extensions;if(!0===t.has("EXT_texture_filter_anisotropic")){const s=t.get("EXT_texture_filter_anisotropic");this.maxAnisotropy=e.getParameter(s.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else this.maxAnisotropy=0;return this.maxAnisotropy}}const hP={WEBGL_multi_draw:"WEBGL_multi_draw",WEBGL_compressed_texture_astc:"texture-compression-astc",WEBGL_compressed_texture_etc:"texture-compression-etc2",WEBGL_compressed_texture_etc1:"texture-compression-etc1",WEBGL_compressed_texture_pvrtc:"texture-compression-pvrtc",WEBKIT_WEBGL_compressed_texture_pvrtc:"texture-compression-pvrtc",WEBGL_compressed_texture_s3tc:"texture-compression-bc",EXT_texture_compression_bptc:"texture-compression-bptc",EXT_disjoint_timer_query_webgl2:"timestamp-query"};class lP{constructor(e){this.gl=e.gl,this.extensions=e.extensions,this.info=e.renderer.info,this.mode=null,this.index=0,this.type=null,this.object=null}render(e,t){const{gl:s,mode:i,object:r,type:n,info:o,index:a}=this;0!==a?s.drawElements(i,t,n,e):s.drawArrays(i,e,t),o.update(r,t,i,1)}renderInstances(e,t,s){const{gl:i,mode:r,type:n,index:o,object:a,info:h}=this;0!==s&&(0!==o?i.drawElementsInstanced(r,t,n,e,s):i.drawArraysInstanced(r,e,t,s),h.update(a,t,r,s))}renderMultiDraw(e,t,s){const{extensions:i,mode:r,object:n,info:o}=this;if(0===s)return;const a=i.get("WEBGL_multi_draw");if(null===a)for(let i=0;i0)){const e=t.queryQueue.shift();this.initTimestampQuery(e)}}async resolveTimestampAsync(e,t="render"){if(!this.disjoint||!this.trackTimestamp)return;const s=this.get(e);s.gpuQueries||(s.gpuQueries=[]);for(let e=0;e0&&(s.currentOcclusionQueries=s.occlusionQueries,s.currentOcclusionQueryObjects=s.occlusionQueryObjects,s.lastOcclusionObject=null,s.occlusionQueries=new Array(i),s.occlusionQueryObjects=new Array(i),s.occlusionQueryIndex=0)}finishRender(e){const{gl:t,state:s}=this,i=this.get(e),r=i.previousContext,n=e.occlusionQueryCount;n>0&&(n>i.occlusionQueryIndex&&t.endQuery(t.ANY_SAMPLES_PASSED),this.resolveOccludedAsync(e));const o=e.textures;if(null!==o)for(let e=0;e0){const r=i.framebuffers[e.getCacheKey()],n=t.COLOR_BUFFER_BIT,o=i.msaaFrameBuffer,a=e.textures;s.bindFramebuffer(t.READ_FRAMEBUFFER,o),s.bindFramebuffer(t.DRAW_FRAMEBUFFER,r);for(let s=0;s{let o=0;for(let t=0;t0&&e.add(i[t]),s[t]=null,r.deleteQuery(n),o++))}o1?f.renderInstances(m,y,x):f.render(m,y),o.bindVertexArray(null)}needsRenderUpdate(){return!1}getRenderCacheKey(){return""}createDefaultTexture(e){this.textureUtils.createDefaultTexture(e)}createTexture(e,t){this.textureUtils.createTexture(e,t)}updateTexture(e,t){this.textureUtils.updateTexture(e,t)}generateMipmaps(e){this.textureUtils.generateMipmaps(e)}destroyTexture(e){this.textureUtils.destroyTexture(e)}copyTextureToBuffer(e,t,s,i,r){return this.textureUtils.copyTextureToBuffer(e,t,s,i,r)}createSampler(){}destroySampler(){}createNodeBuilder(e,t){return new GI(e,t)}createProgram(e){const t=this.gl,{stage:s,code:i}=e,r="fragment"===s?t.createShader(t.FRAGMENT_SHADER):t.createShader(t.VERTEX_SHADER);t.shaderSource(r,i),t.compileShader(r),this.set(e,{shaderGPU:r})}destroyProgram(){console.warn("Abstract class.")}createRenderPipeline(e,t){const s=this.gl,i=e.pipeline,{fragmentProgram:r,vertexProgram:n}=i,o=s.createProgram(),a=this.get(r).shaderGPU,h=this.get(n).shaderGPU;if(s.attachShader(o,a),s.attachShader(o,h),s.linkProgram(o),this.set(i,{programGPU:o,fragmentShader:a,vertexShader:h}),null!==t&&this.parallel){const r=new Promise((t=>{const r=this.parallel,n=()=>{s.getProgramParameter(o,r.COMPLETION_STATUS_KHR)?(this._completeCompile(e,i),t()):requestAnimationFrame(n)};n()}));t.push(r)}else this._completeCompile(e,i)}_handleSource(e,t){const s=e.split("\n"),i=[],r=Math.max(t-6,0),n=Math.min(t+6,s.length);for(let e=r;e":" "} ${r}: ${s[e]}`)}return i.join("\n")}_getShaderErrors(e,t,s){const i=e.getShaderParameter(t,e.COMPILE_STATUS),r=e.getShaderInfoLog(t).trim();if(i&&""===r)return"";const n=/ERROR: 0:(\d+)/.exec(r);if(n){const i=parseInt(n[1]);return s.toUpperCase()+"\n\n"+r+"\n\n"+this._handleSource(e.getShaderSource(t),i)}return r}_logProgramError(e,t,s){if(this.renderer.debug.checkShaderErrors){const i=this.gl,r=i.getProgramInfoLog(e).trim();if(!1===i.getProgramParameter(e,i.LINK_STATUS))if("function"==typeof this.renderer.debug.onShaderError)this.renderer.debug.onShaderError(i,e,s,t);else{const n=this._getShaderErrors(i,s,"vertex"),o=this._getShaderErrors(i,t,"fragment");console.error("THREE.WebGLProgram: Shader Error "+i.getError()+" - VALIDATE_STATUS "+i.getProgramParameter(e,i.VALIDATE_STATUS)+"\n\nProgram Info Log: "+r+"\n"+n+"\n"+o)}else""!==r&&console.warn("THREE.WebGLProgram: Program Info Log:",r)}}_completeCompile(e,t){const{state:s,gl:i}=this,r=this.get(t),{programGPU:n,fragmentShader:o,vertexShader:a}=r;!1===i.getProgramParameter(n,i.LINK_STATUS)&&this._logProgramError(n,o,a),s.useProgram(n);const h=e.getBindings();this._setupBindings(h,n),this.set(t,{programGPU:n})}createComputePipeline(e,t){const{state:s,gl:i}=this,r={stage:"fragment",code:"#version 300 es\nprecision highp float;\nvoid main() {}"};this.createProgram(r);const{computeProgram:n}=e,o=i.createProgram(),a=this.get(r).shaderGPU,h=this.get(n).shaderGPU,l=n.transforms,u=[],c=[];for(let e=0;ehP[t]===e)),s=this.extensions;for(let e=0;e0){if(void 0===u){const i=[];u=t.createFramebuffer(),s.bindFramebuffer(t.FRAMEBUFFER,u);const r=[],l=e.textures;for(let s=0;s,\n\t@location( 0 ) vTex : vec2\n};\n\n@vertex\nfn main( @builtin( vertex_index ) vertexIndex : u32 ) -> VarysStruct {\n\n\tvar Varys : VarysStruct;\n\n\tvar pos = array< vec2, 4 >(\n\t\tvec2( -1.0, 1.0 ),\n\t\tvec2( 1.0, 1.0 ),\n\t\tvec2( -1.0, -1.0 ),\n\t\tvec2( 1.0, -1.0 )\n\t);\n\n\tvar tex = array< vec2, 4 >(\n\t\tvec2( 0.0, 0.0 ),\n\t\tvec2( 1.0, 0.0 ),\n\t\tvec2( 0.0, 1.0 ),\n\t\tvec2( 1.0, 1.0 )\n\t);\n\n\tVarys.vTex = tex[ vertexIndex ];\n\tVarys.Position = vec4( pos[ vertexIndex ], 0.0, 1.0 );\n\n\treturn Varys;\n\n}\n"}),this.mipmapFragmentShaderModule=e.createShaderModule({label:"mipmapFragment",code:"\n@group( 0 ) @binding( 0 )\nvar imgSampler : sampler;\n\n@group( 0 ) @binding( 1 )\nvar img : texture_2d;\n\n@fragment\nfn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 {\n\n\treturn textureSample( img, imgSampler, vTex );\n\n}\n"}),this.flipYFragmentShaderModule=e.createShaderModule({label:"flipYFragment",code:"\n@group( 0 ) @binding( 0 )\nvar imgSampler : sampler;\n\n@group( 0 ) @binding( 1 )\nvar img : texture_2d;\n\n@fragment\nfn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 {\n\n\treturn textureSample( img, imgSampler, vec2( vTex.x, 1.0 - vTex.y ) );\n\n}\n"})}getTransferPipeline(e){let t=this.transferPipelines[e];return void 0===t&&(t=this.device.createRenderPipeline({label:`mipmap-${e}`,vertex:{module:this.mipmapVertexShaderModule,entryPoint:"main"},fragment:{module:this.mipmapFragmentShaderModule,entryPoint:"main",targets:[{format:e}]},primitive:{topology:yA,stripIndexFormat:FA},layout:"auto"}),this.transferPipelines[e]=t),t}getFlipYPipeline(e){let t=this.flipYPipelines[e];return void 0===t&&(t=this.device.createRenderPipeline({label:`flipY-${e}`,vertex:{module:this.mipmapVertexShaderModule,entryPoint:"main"},fragment:{module:this.flipYFragmentShaderModule,entryPoint:"main",targets:[{format:e}]},primitive:{topology:yA,stripIndexFormat:FA},layout:"auto"}),this.flipYPipelines[e]=t),t}flipY(e,t,s=0){const i=t.format,{width:r,height:n}=t.size,o=this.getTransferPipeline(i),a=this.getFlipYPipeline(i),h=this.device.createTexture({size:{width:r,height:n,depthOrArrayLayers:1},format:i,usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING}),l=e.createView({baseMipLevel:0,mipLevelCount:1,dimension:AN,baseArrayLayer:s}),u=h.createView({baseMipLevel:0,mipLevelCount:1,dimension:AN,baseArrayLayer:0}),c=this.device.createCommandEncoder({}),d=(e,t,s)=>{const i=e.getBindGroupLayout(0),r=this.device.createBindGroup({layout:i,entries:[{binding:0,resource:this.flipYSampler},{binding:1,resource:t}]}),n=c.beginRenderPass({colorAttachments:[{view:s,loadOp:RA,storeOp:AA,clearValue:[0,0,0,0]}]});n.setPipeline(e),n.setBindGroup(0,r),n.draw(4,1,0,0),n.end()};d(o,l,u),d(a,u,l),this.device.queue.submit([c.finish()]),h.destroy()}generateMipmaps(e,t,s=0){const i=this.get(e);void 0===i.useCount&&(i.useCount=0,i.layers=[]);const r=i.layers[s]||this._mipmapCreateBundles(e,t,s),n=this.device.createCommandEncoder({});this._mipmapRunBundles(n,r),this.device.queue.submit([n.finish()]),0!==i.useCount&&(i.layers[s]=r),i.useCount++}_mipmapCreateBundles(e,t,s){const i=this.getTransferPipeline(t.format),r=i.getBindGroupLayout(0);let n=e.createView({baseMipLevel:0,mipLevelCount:1,dimension:AN,baseArrayLayer:s});const o=[];for(let a=1;a1&&!e.isMultisampleRenderTargetTexture){const e=Object.assign({},p);e.label=e.label+"-msaa",e.sampleCount=u,i.msaaTexture=s.device.createTexture(e)}i.initialized=!0,i.textureDescriptorGPU=p}destroyTexture(e){const t=this.backend,s=t.get(e);s.texture.destroy(),void 0!==s.msaaTexture&&s.msaaTexture.destroy(),t.delete(e)}destroySampler(e){delete this.backend.get(e).sampler}generateMipmaps(e){const t=this.backend.get(e);if(e.isCubeTexture)for(let e=0;e<6;e++)this._generateMipmaps(t.texture,t.textureDescriptorGPU,e);else{const s=e.image.depth||1;for(let e=0;e1;for(let o=0;o]*\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/i,_P=/([a-z_0-9]+)\s*:\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/gi,wP={f32:"float",i32:"int",u32:"uint",bool:"bool","vec2":"vec2","vec2":"ivec2","vec2":"uvec2","vec2":"bvec2",vec2f:"vec2",vec2i:"ivec2",vec2u:"uvec2",vec2b:"bvec2","vec3":"vec3","vec3":"ivec3","vec3":"uvec3","vec3":"bvec3",vec3f:"vec3",vec3i:"ivec3",vec3u:"uvec3",vec3b:"bvec3","vec4":"vec4","vec4":"ivec4","vec4":"uvec4","vec4":"bvec4",vec4f:"vec4",vec4i:"ivec4",vec4u:"uvec4",vec4b:"bvec4","mat2x2":"mat2",mat2x2f:"mat2","mat3x3":"mat3",mat3x3f:"mat3","mat4x4":"mat4",mat4x4f:"mat4",sampler:"sampler",texture_1d:"texture",texture_2d:"texture",texture_2d_array:"texture",texture_multisampled_2d:"cubeTexture",texture_depth_2d:"depthTexture",texture_3d:"texture3D",texture_cube:"cubeTexture",texture_cube_array:"cubeTexture",texture_storage_1d:"storageTexture",texture_storage_2d:"storageTexture",texture_storage_2d_array:"storageTexture",texture_storage_3d:"storageTexture"};class SP extends ZC{constructor(e){const{type:t,inputs:s,name:i,inputsCode:r,blockCode:n,outputType:o}=(e=>{const t=(e=e.trim()).match(TP);if(null!==t&&4===t.length){const s=t[2],i=[];let r=null;for(;null!==(r=_P.exec(s));)i.push({name:r[1],type:r[2]});const n=[];for(let e=0;e "+this.outputType:"";return`fn ${e} ( ${this.inputsCode.trim()} ) ${t}`+this.blockCode}}class MP extends JC{parseFunction(e){return new SP(e)}}const AP=self.GPUShaderStage,NP={vertex:AP?AP.VERTEX:1,fragment:AP?AP.FRAGMENT:2,compute:AP?AP.COMPUTE:4},RP={instance:!0,swizzleAssign:!1,storageBuffer:!0},CP={"^^":"tsl_xor"},EP={float:"f32",int:"i32",uint:"u32",bool:"bool",color:"vec3",vec2:"vec2",ivec2:"vec2",uvec2:"vec2",bvec2:"vec2",vec3:"vec3",ivec3:"vec3",uvec3:"vec3",bvec3:"vec3",vec4:"vec4",ivec4:"vec4",uvec4:"vec4",bvec4:"vec4",mat2:"mat2x2",imat2:"mat2x2",umat2:"mat2x2",bmat2:"mat2x2",mat3:"mat3x3",imat3:"mat3x3",umat3:"mat3x3",bmat3:"mat3x3",mat4:"mat4x4",imat4:"mat4x4",umat4:"mat4x4",bmat4:"mat4x4"},BP={tsl_xor:new lS("fn tsl_xor( a : bool, b : bool ) -> bool { return ( a || b ) && !( a && b ); }"),mod_float:new lS("fn tsl_mod_float( x : f32, y : f32 ) -> f32 { return x - y * floor( x / y ); }"),mod_vec2:new lS("fn tsl_mod_vec2( x : vec2f, y : vec2f ) -> vec2f { return x - y * floor( x / y ); }"),mod_vec3:new lS("fn tsl_mod_vec3( x : vec3f, y : vec3f ) -> vec3f { return x - y * floor( x / y ); }"),mod_vec4:new lS("fn tsl_mod_vec4( x : vec4f, y : vec4f ) -> vec4f { return x - y * floor( x / y ); }"),equals_bool:new lS("fn tsl_equals_bool( a : bool, b : bool ) -> bool { return a == b; }"),equals_bvec2:new lS("fn tsl_equals_bvec2( a : vec2f, b : vec2f ) -> vec2 { return vec2( a.x == b.x, a.y == b.y ); }"),equals_bvec3:new lS("fn tsl_equals_bvec3( a : vec3f, b : vec3f ) -> vec3 { return vec3( a.x == b.x, a.y == b.y, a.z == b.z ); }"),equals_bvec4:new lS("fn tsl_equals_bvec4( a : vec4f, b : vec4f ) -> vec4 { return vec4( a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w ); }"),repeatWrapping:new lS("\nfn tsl_repeatWrapping( uv : vec2, dimension : vec2 ) -> vec2 {\n\n\tlet uvScaled = vec2( uv * vec2( dimension ) );\n\n\treturn ( ( uvScaled % dimension ) + dimension ) % dimension;\n\n}\n"),biquadraticTexture:new lS("\nfn tsl_biquadraticTexture( map : texture_2d, coord : vec2f, level : i32 ) -> vec4f {\n\n\tlet res = vec2f( textureDimensions( map, level ) );\n\n\tlet uvScaled = coord * res;\n\tlet uvWrapping = ( ( uvScaled % res ) + res ) % res;\n\n\t// https://www.shadertoy.com/view/WtyXRy\n\n\tlet uv = uvWrapping - 0.5;\n\tlet iuv = floor( uv );\n\tlet f = fract( uv );\n\n\tlet rg1 = textureLoad( map, vec2i( iuv + vec2( 0.5, 0.5 ) ), level );\n\tlet rg2 = textureLoad( map, vec2i( iuv + vec2( 1.5, 0.5 ) ), level );\n\tlet rg3 = textureLoad( map, vec2i( iuv + vec2( 0.5, 1.5 ) ), level );\n\tlet rg4 = textureLoad( map, vec2i( iuv + vec2( 1.5, 1.5 ) ), level );\n\n\treturn mix( mix( rg1, rg2, f.x ), mix( rg3, rg4, f.x ), f.y );\n\n}\n")},IP={dFdx:"dpdx",dFdy:"- dpdy",mod_float:"tsl_mod_float",mod_vec2:"tsl_mod_vec2",mod_vec3:"tsl_mod_vec3",mod_vec4:"tsl_mod_vec4",equals_bool:"tsl_equals_bool",equals_bvec2:"tsl_equals_bvec2",equals_bvec3:"tsl_equals_bvec3",equals_bvec4:"tsl_equals_bvec4",inversesqrt:"inverseSqrt",bitcast:"bitcast"};/Windows/g.test(navigator.userAgent)&&(BP.pow_float=new lS("fn tsl_pow_float( a : f32, b : f32 ) -> f32 { return select( -pow( -a, b ), pow( a, b ), a > 0.0 ); }"),BP.pow_vec2=new lS("fn tsl_pow_vec2( a : vec2f, b : vec2f ) -> vec2f { return vec2f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ) ); }",[BP.pow_float]),BP.pow_vec3=new lS("fn tsl_pow_vec3( a : vec3f, b : vec3f ) -> vec3f { return vec3f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ), tsl_pow_float( a.z, b.z ) ); }",[BP.pow_float]),BP.pow_vec4=new lS("fn tsl_pow_vec4( a : vec4f, b : vec4f ) -> vec4f { return vec4f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ), tsl_pow_float( a.z, b.z ), tsl_pow_float( a.w, b.w ) ); }",[BP.pow_float]),IP.pow_float="tsl_pow_float",IP.pow_vec2="tsl_pow_vec2",IP.pow_vec3="tsl_pow_vec3",IP.pow_vec4="tsl_pow_vec4");class PP extends aM{constructor(e,t){super(e,t,new MP),this.uniformGroups={},this.builtins={},this.directives={}}needsToWorkingColorSpace(e){return!0===e.isVideoTexture&&e.colorSpace!==Yt}_generateTextureSample(e,t,s,i,r=this.shaderStage){return"fragment"===r?i?`textureSample( ${t}, ${t}_sampler, ${s}, ${i} )`:`textureSample( ${t}, ${t}_sampler, ${s} )`:this.isFilteredTexture(e)?this.generateFilteredTexture(e,t,s):this.generateTextureLod(e,t,s,"0")}_generateVideoSample(e,t,s=this.shaderStage){if("fragment"===s)return`textureSampleBaseClampToEdge( ${e}, ${e}_sampler, vec2( ${t}.x, 1.0 - ${t}.y ) )`;console.error(`WebGPURenderer: THREE.VideoTexture does not support ${s} shader.`)}_generateTextureSampleLevel(e,t,s,i,r,n=this.shaderStage){return"fragment"===n&&!1===this.isUnfilterable(e)?`textureSampleLevel( ${t}, ${t}_sampler, ${s}, ${i} )`:this.isFilteredTexture(e)?this.generateFilteredTexture(e,t,s,i):this.generateTextureLod(e,t,s,i)}generateFilteredTexture(e,t,s,i="0"){return this._include("biquadraticTexture"),`tsl_biquadraticTexture( ${t}, ${s}, i32( ${i} ) )`}generateTextureLod(e,t,s,i="0"){this._include("repeatWrapping");return`textureLoad( ${t}, tsl_repeatWrapping( ${s}, ${!0===e.isMultisampleRenderTargetTexture?`textureDimensions( ${t} )`:`textureDimensions( ${t}, 0 )`} ), i32( ${i} ) )`}generateTextureLoad(e,t,s,i,r="0u"){return i?`textureLoad( ${t}, ${s}, ${i}, ${r} )`:`textureLoad( ${t}, ${s}, ${r} )`}generateTextureStore(e,t,s,i){return`textureStore( ${t}, ${s}, ${i} )`}isUnfilterable(e){return"float"!==this.getComponentTypeFromTexture(e)||!this.isAvailable("float32Filterable")&&!0===e.isDataTexture&&e.type===Ie||!0===e.isMultisampleRenderTargetTexture}generateTexture(e,t,s,i,r=this.shaderStage){let n=null;return n=!0===e.isVideoTexture?this._generateVideoSample(t,s,r):this.isUnfilterable(e)?this.generateTextureLod(e,t,s,"0",i,r):this._generateTextureSample(e,t,s,i,r),n}generateTextureGrad(e,t,s,i,r,n=this.shaderStage){if("fragment"===n)return`textureSampleGrad( ${t}, ${t}_sampler, ${s}, ${i[0]}, ${i[1]} )`;console.error(`WebGPURenderer: THREE.TextureNode.gradient() does not support ${n} shader.`)}generateTextureCompare(e,t,s,i,r,n=this.shaderStage){if("fragment"===n)return`textureSampleCompare( ${t}, ${t}_sampler, ${s}, ${i} )`;console.error(`WebGPURenderer: THREE.DepthTexture.compareFunction() does not support ${n} shader.`)}generateTextureLevel(e,t,s,i,r,n=this.shaderStage){let o=null;return o=!0===e.isVideoTexture?this._generateVideoSample(t,s,n):this._generateTextureSampleLevel(e,t,s,i,r,n),o}generateTextureBias(e,t,s,i,r,n=this.shaderStage){if("fragment"===n)return`textureSampleBias( ${t}, ${t}_sampler, ${s}, ${i} )`;console.error(`WebGPURenderer: THREE.TextureNode.biasNode does not support ${n} shader.`)}getPropertyName(e,t=this.shaderStage){if(!0===e.isNodeVarying&&!0===e.needsInterpolation){if("vertex"===t)return`varyings.${e.name}`}else if(!0===e.isNodeUniform){const t=e.name,s=e.type;return"texture"===s||"cubeTexture"===s||"storageTexture"===s||"texture3D"===s?t:"buffer"===s||"storageBuffer"===s?`NodeBuffer_${e.id}.${t}`:e.groupNode.name+"."+t}return super.getPropertyName(e)}getOutputStructName(){return"output"}_getUniformGroupCount(e){return Object.keys(this.uniforms[e]).length}getFunctionOperator(e){const t=CP[e];return void 0!==t?(this._include(t),t):null}getStorageAccess(e){if(e.isStorageTextureNode)switch(e.access){case xN:return"read";case yN:return"write";default:return"read_write"}else switch(e.access){case gN:return"read_write";case fN:return"read";default:return"write"}}getUniformFromNode(e,t,s,i=null){const r=super.getUniformFromNode(e,t,s,i),n=this.getDataFromNode(e,s,this.globalCache);if(void 0===n.uniformGPU){let i;const o=e.groupNode,a=o.name,h=this.getBindGroupArray(a,s);if("texture"===t||"cubeTexture"===t||"storageTexture"===t||"texture3D"===t){let n=null;if("texture"===t||"storageTexture"===t?n=new zI(r.name,r.node,o,e.access?e.access:null):"cubeTexture"===t?n=new UI(r.name,r.node,o,e.access?e.access:null):"texture3D"===t&&(n=new LI(r.name,r.node,o,e.access?e.access:null)),n.store=!0===e.isStorageTextureNode,n.setVisibility(NP[s]),"fragment"===s&&!1===this.isUnfilterable(e.value)&&!1===n.store){const e=new dP(`${r.name}_sampler`,r.node,o);e.setVisibility(NP[s]),h.push(e,n),i=[e,n]}else h.push(n),i=[n]}else if("buffer"===t||"storageBuffer"===t){const r=new("storageBuffer"===t?gP:CI)(e,o);r.setVisibility(NP[s]),h.push(r),i=r}else{const e=this.uniformGroups[s]||(this.uniformGroups[s]={});let n=e[a];void 0===n&&(n=new II(a,o),n.setVisibility(NP[s]),e[a]=n,h.push(n)),i=this.getNodeUniform(r,t),n.addUniform(i)}n.uniformGPU=i}return r}getBuiltin(e,t,s,i=this.shaderStage){const r=this.builtins[i]||(this.builtins[i]=new Map);return!1===r.has(e)&&r.set(e,{name:e,property:t,type:s}),t}getVertexIndex(){return"vertex"===this.shaderStage?this.getBuiltin("vertex_index","vertexIndex","u32","attribute"):"vertexIndex"}buildFunctionCode(e){const t=e.layout,s=this.flowShaderNode(e),i=[];for(const e of t.inputs)i.push(e.name+" : "+this.getType(e.type));let r=`fn ${t.name}( ${i.join(", ")} ) -> ${this.getType(t.type)} {\n${s.vars}\n${s.code}\n`;return s.result&&(r+=`\treturn ${s.result};\n`),r+="\n}\n",r}getInstanceIndex(){return"vertex"===this.shaderStage?this.getBuiltin("instance_index","instanceIndex","u32","attribute"):"instanceIndex"}getInvocationLocalIndex(){return this.getBuiltin("local_invocation_index","invocationLocalIndex","u32","attribute")}getSubgroupSize(){return this.enableSubGroups(),this.getBuiltin("subgroup_size","subgroupSize","u32","attribute")}getSubgroupIndex(){return this.enableSubGroups(),this.getBuiltin("subgroup_invocation_id","subgroupIndex","u32","attribute")}getDrawIndex(){return null}getFrontFacing(){return this.getBuiltin("front_facing","isFront","bool")}getFragCoord(){return this.getBuiltin("position","fragCoord","vec4")+".xy"}getFragDepth(){return"output."+this.getBuiltin("frag_depth","depth","f32","output")}isFlipY(){return!1}enableDirective(e,t=this.shaderStage){(this.directives[t]||(this.directives[t]=new Set)).add(e)}getDirectives(e){const t=[],s=this.directives[e];if(void 0!==s)for(const e of s)t.push(`enable ${e};`);return t.join("\n")}enableSubGroups(){this.enableDirective("subgroups")}enableSubgroupsF16(){this.enableDirective("subgroups-f16")}enableClipDistances(){this.enableDirective("clip_distances")}enableShaderF16(){this.enableDirective("f16")}enableDualSourceBlending(){this.enableDirective("dual_source_blending")}getBuiltins(e){const t=[],s=this.builtins[e];if(void 0!==s)for(const{name:e,property:i,type:r}of s.values())t.push(`@builtin( ${e} ) ${i} : ${r}`);return t.join(",\n\t")}getAttributes(e){const t=[];if("compute"===e&&(this.getBuiltin("global_invocation_id","id","vec3","attribute"),this.getBuiltin("workgroup_id","workgroupId","vec3","attribute"),this.getBuiltin("local_invocation_id","localId","vec3","attribute"),this.getBuiltin("num_workgroups","numWorkgroups","vec3","attribute")),"vertex"===e||"compute"===e){const e=this.getBuiltins("attribute");e&&t.push(e);const s=this.getAttributesArray();for(let e=0,i=s.length;e`)}const i=this.getBuiltins("output");return i&&t.push("\t"+i),t.join(",\n")}getStructs(e){const t=[],s=this.structs[e];for(let e=0,i=s.length;e output : ${r};\n\n`)}return t.join("\n\n")}getVar(e,t){return`var ${t} : ${this.getType(e)}`}getVars(e){const t=[],s=this.vars[e];if(void 0!==s)for(const e of s)t.push(`\t${this.getVar(e.type,e.name)};`);return`\n${t.join("\n")}\n`}getVaryings(e){const t=[];if("vertex"===e&&this.getBuiltin("position","Vertex","vec4","vertex"),"vertex"===e||"fragment"===e){const s=this.varyings,i=this.vars[e];for(let r=0;r";else if(!0===t.isDataArrayTexture||!0===t.isCompressedArrayTexture)i="texture_2d_array";else if(!0===t.isDepthTexture)i=`texture_depth${n}_2d`;else if(!0===t.isVideoTexture)i="texture_external";else if(!0===t.isData3DTexture)i="texture_3d";else if(!0===r.node.isStorageTextureNode){i=`texture_storage_2d<${vP(t)}, ${this.getStorageAccess(r.node)}>`}else{i=`texture${n}_2d<${this.getComponentTypeFromTexture(t).charAt(0)}32>`}s.push(`@binding( ${o.binding++} ) @group( ${o.group} ) var ${r.name} : ${i};`)}else if("buffer"===r.type||"storageBuffer"===r.type){const e=r.node,t=this.getType(e.bufferType),s=e.bufferCount,n=s>0?", "+s:"",a=`\t${r.name} : array< ${t}${n} >\n`,h=e.isStorageBufferNode?`storage, ${this.getStorageAccess(e)}`:"uniform";i.push(this._getWGSLStructBinding("NodeBuffer_"+e.id,a,h,o.binding++,o.group))}else{const e=this.getType(this.getVectorType(r.type)),t=r.groupNode.name;(n[t]||(n[t]={index:o.binding++,id:o.group,snippets:[]})).snippets.push(`\t${r.name} : ${e}`)}}for(const e in n){const t=n[e];r.push(this._getWGSLStructBinding(e,t.snippets.join(",\n"),"uniform",t.index,t.id))}let o=s.join("\n");return o+=i.join("\n"),o+=r.join("\n"),o}buildCode(){const e=null!==this.material?{fragment:{},vertex:{}}:{compute:{}};for(const t in e){const s=e[t];s.uniforms=this.getUniforms(t),s.attributes=this.getAttributes(t),s.varyings=this.getVaryings(t),s.structs=this.getStructs(t),s.vars=this.getVars(t),s.codes=this.getCodes(t),s.directives=this.getDirectives(t);let i="// code\n\n";i+=this.flowCode[t];const r=this.flowNodes[t],n=r[r.length-1],o=n.outputNode,a=void 0!==o&&!0===o.isOutputStructNode;for(const e of r){const r=this.getFlowData(e),h=e.name;if(h&&(i.length>0&&(i+="\n"),i+=`\t// flow -> ${h}\n\t`),i+=`${r.code}\n\t`,e===n&&"compute"!==t)if(i+="// result\n\n\t","vertex"===t)i+=`varyings.Vertex = ${r.result};`;else if("fragment"===t)if(a)s.returnType=o.nodeType,i+=`return ${r.result};`;else{let e="\t@location(0) color: vec4";const t=this.getBuiltins("output");t&&(e+=",\n\t"+t),s.returnType="OutputStruct",s.structs+=this._getWGSLStruct("OutputStruct",e),s.structs+="\nvar output : OutputStruct;\n\n",i+=`output.color = ${r.result};\n\n\treturn output;`}}s.flow=i}null!==this.material?(this.vertexShader=this._getWGSLVertexCode(e.vertex),this.fragmentShader=this._getWGSLFragmentCode(e.fragment)):this.computeShader=this._getWGSLComputeCode(e.compute,(this.object.workgroupSize||[64]).join(", "))}getMethod(e,t=null){let s;return null!==t&&(s=this._getWGSLMethod(e+"_"+t)),void 0===s&&(s=this._getWGSLMethod(e)),s||e}getType(e){return EP[e]||e}isAvailable(e){let t=RP[e];return void 0===t&&("float32Filterable"===e&&(t=this.renderer.hasFeature("float32-filterable")),RP[e]=t),t}_getWGSLMethod(e){return void 0!==BP[e]&&this._include(e),IP[e]}_include(e){const t=BP[e];return t.build(this),null!==this.currentFunctionNode&&this.currentFunctionNode.includes.push(t),t}_getWGSLVertexCode(e){return`${this.getSignature()}\n// directives\n${e.directives}\n\n// uniforms\n${e.uniforms}\n\n// varyings\n${e.varyings}\nvar varyings : VaryingsStruct;\n\n// codes\n${e.codes}\n\n@vertex\nfn main( ${e.attributes} ) -> VaryingsStruct {\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n\treturn varyings;\n\n}\n`}_getWGSLFragmentCode(e){return`${this.getSignature()}\n\ndiagnostic( off, derivative_uniformity );\n\n// uniforms\n${e.uniforms}\n\n// structs\n${e.structs}\n\n// codes\n${e.codes}\n\n@fragment\nfn main( ${e.varyings} ) -> ${e.returnType} {\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n}\n`}_getWGSLComputeCode(e,t){return`${this.getSignature()}\n// directives\n${e.directives}\n\n// system\nvar instanceIndex : u32;\n\n// uniforms\n${e.uniforms}\n\n// codes\n${e.codes}\n\n@compute @workgroup_size( ${t} )\nfn main( ${e.attributes} ) {\n\n\t// system\n\tinstanceIndex = id.x + id.y * numWorkgroups.x * u32(${t}) + id.z * numWorkgroups.x * numWorkgroups.y * u32(${t});\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n}\n`}_getWGSLStruct(e,t){return`\nstruct ${e} {\n${t}\n};`}_getWGSLStructBinding(e,t,s,i=0,r=0){const n=e+"Struct";return`${this._getWGSLStruct(n,t)}\n@binding( ${i} ) @group( ${r} )\nvar<${s}> ${e} : ${n};`}}class FP{constructor(e){this.backend=e}getCurrentDepthStencilFormat(e){let t;return null!==e.depthTexture?t=this.getTextureFormatGPU(e.depthTexture):e.depth&&e.stencil?t=zA.Depth24PlusStencil8:e.depth&&(t=zA.Depth24Plus),t}getTextureFormatGPU(e){return this.backend.get(e).texture.format}getCurrentColorFormat(e){let t;return t=null!==e.textures?this.getTextureFormatGPU(e.textures[0]):this.getPreferredCanvasFormat(),t}getCurrentColorSpace(e){return null!==e.textures?e.textures[0].colorSpace:this.backend.renderer.outputColorSpace}getPrimitiveTopology(e,t){return e.isPoints?pA:e.isLineSegments||e.isMesh&&!0===t.wireframe?mA:e.isLine?gA:e.isMesh?fA:void 0}getSampleCount(e){let t=1;return e>1&&(t=Math.pow(2,Math.floor(Math.log2(e))),2===t&&(t=4)),t}getSampleCountRenderContext(e){return null!==e.textures?this.getSampleCount(e.sampleCount):this.getSampleCount(this.backend.renderer.samples)}getPreferredCanvasFormat(){return navigator.userAgent.includes("Quest")?zA.BGRA8Unorm:navigator.gpu.getPreferredCanvasFormat()}}const zP=new Map([[Int8Array,["sint8","snorm8"]],[Uint8Array,["uint8","unorm8"]],[Int16Array,["sint16","snorm16"]],[Uint16Array,["uint16","unorm16"]],[Int32Array,["sint32","snorm32"]],[Uint32Array,["uint32","unorm32"]],[Float32Array,["float32"]]]),UP=new Map([[fn,["float16"]]]),LP=new Map([[Int32Array,"sint32"],[Int16Array,"sint32"],[Uint32Array,"uint32"],[Uint16Array,"uint32"],[Float32Array,"float32"]]);class OP{constructor(e){this.backend=e}createAttribute(e,t){const s=this._getBufferAttribute(e),i=this.backend,r=i.get(s);let n=r.buffer;if(void 0===n){const o=i.device;let a=s.array;if(!1===e.normalized&&(a.constructor===Int16Array||a.constructor===Uint16Array)){const e=new Uint32Array(a.length);for(let t=0;t{l.createRenderPipelineAsync(M).then((t=>{c.pipeline=t,e()}))}));t.push(e)}}createBundleEncoder(e){const t=this.backend,{utils:s,device:i}=t,r=s.getCurrentDepthStencilFormat(e),n={label:"renderBundleEncoder",colorFormats:[s.getCurrentColorFormat(e)],depthStencilFormat:r,sampleCount:this._getSampleCount(e)};return i.createRenderBundleEncoder(n)}createComputePipeline(e,t){const s=this.backend,i=s.device,r=s.get(e.computeProgram).module,n=s.get(e),o=[];for(const e of t){const t=s.get(e);o.push(t.layout)}n.pipeline=i.createComputePipeline({compute:r,layout:i.createPipelineLayout({bindGroupLayouts:o})})}_getBlending(e){let t,s;const i=e.blending,r=e.blendSrc,n=e.blendDst,o=e.blendEquation;if(5===i){const i=null!==e.blendSrcAlpha?e.blendSrcAlpha:r,a=null!==e.blendDstAlpha?e.blendDstAlpha:n,h=null!==e.blendEquationAlpha?e.blendEquationAlpha:o;t={srcFactor:this._getBlendFactor(r),dstFactor:this._getBlendFactor(n),operation:this._getBlendOperation(o)},s={srcFactor:this._getBlendFactor(i),dstFactor:this._getBlendFactor(a),operation:this._getBlendOperation(h)}}else{const r=(e,i,r,n)=>{t={srcFactor:e,dstFactor:i,operation:eN},s={srcFactor:r,dstFactor:n,operation:eN}};if(e.premultipliedAlpha)switch(i){case 1:r(GA,qA,GA,qA);break;case 2:r(GA,GA,GA,GA);break;case 3:r(kA,HA,kA,GA);break;case 4:r(kA,WA,kA,jA)}else switch(i){case 1:r(jA,qA,GA,qA);break;case 2:r(jA,GA,jA,GA);break;case 3:r(kA,HA,kA,GA);break;case 4:r(kA,WA,kA,WA)}}if(void 0!==t&&void 0!==s)return{color:t,alpha:s};console.error("THREE.WebGPURenderer: Invalid blending: ",i)}_getBlendFactor(e){let t;switch(e){case 200:t=kA;break;case 201:t=GA;break;case 202:t=WA;break;case 203:t=HA;break;case C:t=jA;break;case E:t=qA;break;case 208:t=$A;break;case 209:t=XA;break;case 206:t=YA;break;case 207:t=JA;break;case 210:t=ZA;break;case 211:t=KA;break;case 212:t=QA;break;default:console.error("THREE.WebGPURenderer: Blend factor not supported.",e)}return t}_getStencilCompare(e){let t;const s=e.stencilFunc;switch(s){case 512:t=xA;break;case bs:t=MA;break;case 513:t=bA;break;case 515:t=TA;break;case 514:t=vA;break;case 518:t=SA;break;case 516:t=_A;break;case 517:t=wA;break;default:console.error("THREE.WebGPURenderer: Invalid stencil function.",s)}return t}_getStencilOperation(e){let t;switch(e){case ns:t=aN;break;case 0:t=hN;break;case 7681:t=lN;break;case 5386:t=uN;break;case 7682:t=cN;break;case 7683:t=dN;break;case 34055:t=pN;break;case 34056:t=mN;break;default:console.error("THREE.WebGPURenderer: Invalid stencil operation.",t)}return t}_getBlendOperation(e){let t;switch(e){case v:t=eN;break;case 101:t=tN;break;case 102:t=sN;break;case 103:t=iN;break;case 104:t=rN;break;default:console.error("THREE.WebGPUPipelineUtils: Blend equation not supported.",e)}return t}_getPrimitiveState(e,t,s){const i={},r=this.backend.utils;switch(i.topology=r.getPrimitiveTopology(e,s),null!==t.index&&!0===e.isLine&&!0!==e.isLineSegments&&(i.stripIndexFormat=t.index.array instanceof Uint16Array?PA:FA),s.side){case c:i.frontFace=CA,i.cullMode=IA;break;case d:i.frontFace=CA,i.cullMode=BA;break;case 2:i.frontFace=CA,i.cullMode=EA;break;default:console.error("THREE.WebGPUPipelineUtils: Unknown material.side value.",s.side)}return i}_getColorWriteMask(e){return!0===e.colorWrite?oN:nN}_getDepthCompare(e){let t;if(!1===e.depthTest)t=MA;else{const s=e.depthFunc;switch(s){case 0:t=xA;break;case 1:t=MA;break;case 2:t=bA;break;case 3:t=TA;break;case 4:t=vA;break;case 5:t=SA;break;case 6:t=_A;break;case 7:t=wA;break;default:console.error("THREE.WebGPUPipelineUtils: Invalid depth function.",s)}}return t}}class kP extends qI{constructor(e={}){super(e),this.isWebGPUBackend=!0,this.parameters.alpha=void 0===e.alpha||e.alpha,this.parameters.requiredLimits=void 0===e.requiredLimits?{}:e.requiredLimits,this.trackTimestamp=!0===e.trackTimestamp,this.device=null,this.context=null,this.colorBuffer=null,this.defaultRenderPassdescriptor=null,this.utils=new FP(this),this.attributeUtils=new OP(this),this.bindingUtils=new VP(this),this.pipelineUtils=new DP(this),this.textureUtils=new bP(this),this.occludedResolveCache=new Map}async init(e){await super.init(e);const t=this.parameters;let s;if(void 0===t.device){const e={powerPreference:t.powerPreference},i=await navigator.gpu.requestAdapter(e);if(null===i)throw new Error("WebGPUBackend: Unable to create WebGPU adapter.");const r=Object.values(PN),n=[];for(const e of r)i.features.has(e)&&n.push(e);const o={requiredFeatures:n,requiredLimits:t.requiredLimits};s=await i.requestDevice(o)}else s=t.device;const i=void 0!==t.context?t.context:e.domElement.getContext("webgpu");this.device=s,this.context=i;const r=t.alpha?"premultiplied":"opaque";this.trackTimestamp=this.trackTimestamp&&this.hasFeature(PN.TimestampQuery),this.context.configure({device:this.device,format:this.utils.getPreferredCanvasFormat(),usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.COPY_SRC,alphaMode:r}),this.updateSize()}get coordinateSystem(){return Ds}async getArrayBufferAsync(e){return await this.attributeUtils.getArrayBufferAsync(e)}getContext(){return this.context}_getDefaultRenderPassDescriptor(){let e=this.defaultRenderPassdescriptor;if(null===e){const t=this.renderer;e={colorAttachments:[{view:null}],depthStencilAttachment:{view:this.textureUtils.getDepthBuffer(t.depth,t.stencil).createView()}};const s=e.colorAttachments[0];this.renderer.samples>0?s.view=this.colorBuffer.createView():s.resolveTarget=void 0,this.defaultRenderPassdescriptor=e}const t=e.colorAttachments[0];return this.renderer.samples>0?t.resolveTarget=this.context.getCurrentTexture().createView():t.view=this.context.getCurrentTexture().createView(),e}_getRenderPassDescriptor(e){const t=e.renderTarget,s=this.get(t);let i=s.descriptors;if(void 0===i||s.width!==t.width||s.height!==t.height||s.activeMipmapLevel!==t.activeMipmapLevel||s.samples!==t.samples){i={},s.descriptors=i;const e=()=>{t.removeEventListener("dispose",e),this.delete(t)};t.addEventListener("dispose",e)}const r=e.getCacheKey();let n=i[r];if(void 0===n){const o=e.textures,a=[];for(let t=0;t0&&(t.currentOcclusionQuerySet&&t.currentOcclusionQuerySet.destroy(),t.currentOcclusionQueryBuffer&&t.currentOcclusionQueryBuffer.destroy(),t.currentOcclusionQuerySet=t.occlusionQuerySet,t.currentOcclusionQueryBuffer=t.occlusionQueryBuffer,t.currentOcclusionQueryObjects=t.occlusionQueryObjects,r=s.createQuerySet({type:"occlusion",count:i}),t.occlusionQuerySet=r,t.occlusionQueryIndex=0,t.occlusionQueryObjects=new Array(i),t.lastOcclusionObject=null),n=null===e.textures?this._getDefaultRenderPassDescriptor():this._getRenderPassDescriptor(e),this.initTimestampQuery(e,n),n.occlusionQuerySet=r;const o=n.depthStencilAttachment;if(null!==e.textures){const t=n.colorAttachments;for(let s=0;s0&&t.currentPass.executeBundles(t.renderBundles),s>t.occlusionQueryIndex&&t.currentPass.endOcclusionQuery(),t.currentPass.end(),s>0){const i=8*s;let r=this.occludedResolveCache.get(i);void 0===r&&(r=this.device.createBuffer({size:i,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),this.occludedResolveCache.set(i,r));const n=this.device.createBuffer({size:i,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});t.encoder.resolveQuerySet(t.occlusionQuerySet,0,s,r,0),t.encoder.copyBufferToBuffer(r,0,n,0,i),t.occlusionQueryBuffer=n,this.resolveOccludedAsync(e)}if(this.prepareTimestampBuffer(e,t.encoder),this.device.queue.submit([t.encoder.finish()]),null!==e.textures){const t=e.textures;for(let e=0;eo?(h.x=Math.min(t.dispatchCount,o),h.y=Math.ceil(t.dispatchCount/o)):h.x=t.dispatchCount,r.dispatchWorkgroups(h.x,h.y,h.z)}finishCompute(e){const t=this.get(e);t.passEncoderGPU.end(),this.prepareTimestampBuffer(e,t.cmdEncoderGPU),this.device.queue.submit([t.cmdEncoderGPU.finish()])}draw(e,t){const{object:s,geometry:i,context:r,pipeline:n}=e,o=e.getBindings(),a=this.get(r),h=this.get(n).pipeline,l=a.currentSets,u=a.currentPass;l.pipeline!==h&&(u.setPipeline(h),l.pipeline=h);for(let e=0,t=o.length;e1?0:s;u.drawIndexed(t[s],i,e[s]/n,0,o)}}else if(!0===d){const e=m.count!==1/0?m.count:c.count;u.drawIndexed(e,f,g,0,0),t.update(s,e,f)}else{const e=i.attributes.position,r=m.count!==1/0?m.count:e.count;u.draw(r,f,g,0),t.update(s,r,f)}}needsRenderUpdate(e){const t=this.get(e),{object:s,material:i}=e,r=this.utils,n=r.getSampleCountRenderContext(e.context),o=r.getCurrentColorSpace(e.context),a=r.getCurrentColorFormat(e.context),h=r.getCurrentDepthStencilFormat(e.context),l=r.getPrimitiveTopology(s,i);let u=!1;return t.material===i&&t.materialVersion===i.version&&t.transparent===i.transparent&&t.blending===i.blending&&t.premultipliedAlpha===i.premultipliedAlpha&&t.blendSrc===i.blendSrc&&t.blendDst===i.blendDst&&t.blendEquation===i.blendEquation&&t.blendSrcAlpha===i.blendSrcAlpha&&t.blendDstAlpha===i.blendDstAlpha&&t.blendEquationAlpha===i.blendEquationAlpha&&t.colorWrite===i.colorWrite&&t.depthWrite===i.depthWrite&&t.depthTest===i.depthTest&&t.depthFunc===i.depthFunc&&t.stencilWrite===i.stencilWrite&&t.stencilFunc===i.stencilFunc&&t.stencilFail===i.stencilFail&&t.stencilZFail===i.stencilZFail&&t.stencilZPass===i.stencilZPass&&t.stencilFuncMask===i.stencilFuncMask&&t.stencilWriteMask===i.stencilWriteMask&&t.side===i.side&&t.alphaToCoverage===i.alphaToCoverage&&t.sampleCount===n&&t.colorSpace===o&&t.colorFormat===a&&t.depthStencilFormat===h&&t.primitiveTopology===l&&t.clippingContextCacheKey===e.clippingContext.cacheKey||(t.material=i,t.materialVersion=i.version,t.transparent=i.transparent,t.blending=i.blending,t.premultipliedAlpha=i.premultipliedAlpha,t.blendSrc=i.blendSrc,t.blendDst=i.blendDst,t.blendEquation=i.blendEquation,t.blendSrcAlpha=i.blendSrcAlpha,t.blendDstAlpha=i.blendDstAlpha,t.blendEquationAlpha=i.blendEquationAlpha,t.colorWrite=i.colorWrite,t.depthWrite=i.depthWrite,t.depthTest=i.depthTest,t.depthFunc=i.depthFunc,t.stencilWrite=i.stencilWrite,t.stencilFunc=i.stencilFunc,t.stencilFail=i.stencilFail,t.stencilZFail=i.stencilZFail,t.stencilZPass=i.stencilZPass,t.stencilFuncMask=i.stencilFuncMask,t.stencilWriteMask=i.stencilWriteMask,t.side=i.side,t.alphaToCoverage=i.alphaToCoverage,t.sampleCount=n,t.colorSpace=o,t.colorFormat=a,t.depthStencilFormat=h,t.primitiveTopology=l,t.clippingContextCacheKey=e.clippingContext.cacheKey,u=!0),u}getRenderCacheKey(e){const{object:t,material:s}=e,i=this.utils,r=e.context;return[s.transparent,s.blending,s.premultipliedAlpha,s.blendSrc,s.blendDst,s.blendEquation,s.blendSrcAlpha,s.blendDstAlpha,s.blendEquationAlpha,s.colorWrite,s.depthWrite,s.depthTest,s.depthFunc,s.stencilWrite,s.stencilFunc,s.stencilFail,s.stencilZFail,s.stencilZPass,s.stencilFuncMask,s.stencilWriteMask,s.side,i.getSampleCountRenderContext(r),i.getCurrentColorSpace(r),i.getCurrentColorFormat(r),i.getCurrentDepthStencilFormat(r),i.getPrimitiveTopology(t,s),e.clippingContext.cacheKey].join()}createSampler(e){this.textureUtils.createSampler(e)}destroySampler(e){this.textureUtils.destroySampler(e)}createDefaultTexture(e){this.textureUtils.createDefaultTexture(e)}createTexture(e,t){this.textureUtils.createTexture(e,t)}updateTexture(e,t){this.textureUtils.updateTexture(e,t)}generateMipmaps(e){this.textureUtils.generateMipmaps(e)}destroyTexture(e){this.textureUtils.destroyTexture(e)}copyTextureToBuffer(e,t,s,i,r){return this.textureUtils.copyTextureToBuffer(e,t,s,i,r)}initTimestampQuery(e,t){if(!this.trackTimestamp)return;const s=this.get(e);if(!s.timeStampQuerySet){const e=this.device.createQuerySet({type:"timestamp",count:2}),i={querySet:e,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1};Object.assign(t,{timestampWrites:i}),s.timeStampQuerySet=e}}prepareTimestampBuffer(e,t){if(!this.trackTimestamp)return;const s=this.get(e),i=2*BigInt64Array.BYTES_PER_ELEMENT;void 0===s.currentTimestampQueryBuffers&&(s.currentTimestampQueryBuffers={resolveBuffer:this.device.createBuffer({label:"timestamp resolve buffer",size:i,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),resultBuffer:this.device.createBuffer({label:"timestamp result buffer",size:i,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),isMappingPending:!1});const{resolveBuffer:r,resultBuffer:n,isMappingPending:o}=s.currentTimestampQueryBuffers;!0!==o&&(t.resolveQuerySet(s.timeStampQuerySet,0,2,r,0),t.copyBufferToBuffer(r,0,n,0,i))}async resolveTimestampAsync(e,t="render"){if(!this.trackTimestamp)return;const s=this.get(e);if(void 0===s.currentTimestampQueryBuffers)return;const{resultBuffer:i,isMappingPending:r}=s.currentTimestampQueryBuffers;!0!==r&&(s.currentTimestampQueryBuffers.isMappingPending=!0,i.mapAsync(GPUMapMode.READ).then((()=>{const e=new BigUint64Array(i.getMappedRange()),r=Number(e[1]-e[0])/1e6;this.renderer.info.updateTimestamp(t,r),i.unmap(),s.currentTimestampQueryBuffers.isMappingPending=!1})))}createNodeBuilder(e,t){return new PP(e,t)}createProgram(e){this.get(e).module={module:this.device.createShaderModule({code:e.code,label:e.stage}),entryPoint:"main"}}destroyProgram(e){this.delete(e)}createRenderPipeline(e,t){this.pipelineUtils.createRenderPipeline(e,t)}createComputePipeline(e,t){this.pipelineUtils.createComputePipeline(e,t)}beginBundle(e){const t=this.get(e);t._currentPass=t.currentPass,t._currentSets=t.currentSets,t.currentSets={attributes:{},pipeline:null,index:null},t.currentPass=this.pipelineUtils.createBundleEncoder(e)}finishBundle(e,t){const s=this.get(e),i=s.currentPass.finish();this.get(t).bundleGPU=i,s.currentSets=s._currentSets,s.currentPass=s._currentPass}addBundle(e,t){this.get(e).renderBundles.push(this.get(t).bundleGPU)}createBindings(e){this.bindingUtils.createBindings(e)}updateBindings(e){this.bindingUtils.createBindings(e)}updateBinding(e){this.bindingUtils.updateBinding(e)}createIndexAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.INDEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createStorageAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.STORAGE|GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}updateAttribute(e){this.attributeUtils.updateAttribute(e)}destroyAttribute(e){this.attributeUtils.destroyAttribute(e)}updateSize(){this.colorBuffer=this.textureUtils.getColorBuffer(),this.defaultRenderPassdescriptor=null}getMaxAnisotropy(){return 16}hasFeature(e){return this.device.features.has(e)}copyTextureToTexture(e,t,s=null,i=null,r=0){let n=0,o=0,a=0,h=0,l=e.image.width,u=e.image.height;null!==s&&(a=s.x,h=s.y,l=s.width,u=s.height),null!==i&&(n=i.x,o=i.y);const c=this.device.createCommandEncoder({label:"copyTextureToTexture_"+e.id+"_"+t.id}),d=this.get(e).texture,p=this.get(t).texture;c.copyTextureToTexture({texture:d,mipLevel:r,origin:{x:a,y:h,z:0}},{texture:p,mipLevel:r,origin:{x:n,y:o,z:0}},[l,u]),this.device.queue.submit([c.finish()])}copyFramebufferToTexture(e,t){const s=this.get(t),{encoder:i,descriptor:r}=s;let n=null;n=t.renderTarget?e.isDepthTexture?this.get(t.depthTexture).texture:this.get(t.textures[0]).texture:e.isDepthTexture?this.textureUtils.getDepthBuffer(t.depth,t.stencil):this.context.getCurrentTexture();const o=this.get(e).texture;if(n.format===o.format){s.currentPass.end(),i.copyTextureToTexture({texture:n,origin:{x:0,y:0,z:0}},{texture:o},[e.image.width,e.image.height]),e.generateMipmaps&&this.textureUtils.generateMipmaps(e);for(let e=0;e(console.warn("THREE.WebGPURenderer: WebGPU is not available, running under WebGL2 backend."),new uP(e)));super(new t(e),e),this.isWebGPURenderer=!0}}const WP=new xx,HP=new tA(WP);class jP{constructor(e,t=uc(0,0,1,1)){this.renderer=e,this.outputNode=t,this.outputColorTransform=!0,this.needsUpdate=!0,WP.name="PostProcessing"}render(){this.update();const e=this.renderer,t=e.toneMapping,s=e.outputColorSpace;e.toneMapping=0,e.outputColorSpace=Zt,HP.render(e),e.toneMapping=t,e.outputColorSpace=s}update(){if(!0===this.needsUpdate){const e=this.renderer,t=e.toneMapping,s=e.outputColorSpace;HP.material.fragmentNode=!0===this.outputColorTransform?Im(this.outputNode,t,s):this.outputNode.context({toneMapping:t,outputColorSpace:s}),HP.material.needsUpdate=!0,this.needsUpdate=!1}}async renderAsync(){this.update();const e=this.renderer,t=e.toneMapping,s=e.outputColorSpace;e.toneMapping=0,e.outputColorSpace=Zt,await HP.renderAsync(e),e.toneMapping=t,e.outputColorSpace=s}}class qP extends Ti{constructor(e=1,t=1){super(),this.image={width:e,height:t},this.magFilter=Te,this.minFilter=Te,this.isStorageTexture=!0}}class $P extends hn{constructor(e,t,s=Float32Array){!1===ArrayBuffer.isView(e)&&(e=new s(e*t)),super(e,t),this.isStorageBufferAttribute=!0}}class XP extends Ho{constructor(e,t,s=Float32Array){!1===ArrayBuffer.isView(e)&&(e=new s(e*t)),super(e,t),this.isStorageInstancedBufferAttribute=!0}}class YP extends gT{constructor(e){super(e),this.textures={}}load(e,t,s,i){const r=new xT(this.manager);r.setPath(this.path),r.setRequestHeader(this.requestHeader),r.setWithCredentials(this.withCredentials),r.load(e,(s=>{try{t(this.parse(JSON.parse(s)))}catch(t){i?i(t):console.error(t),this.manager.itemError(e)}}),s,i)}parseNodes(e){const t={};if(void 0!==e){for(const s of e){const{uuid:e,type:i}=s;t[e]=Du(eu(i)),t[e].uuid=e}const s={nodes:t,textures:this.textures};for(const i of e){i.meta=s;t[i.uuid].deserialize(i),delete i.meta}}return t}parse(e){const t=Du(eu(e.type));t.uuid=e.uuid;const s={nodes:this.parseNodes(e.nodes),textures:this.textures};return e.meta=s,t.deserialize(e),delete e.meta,t}setTextures(e){return this.textures=e,this}}const JP=jT.createMaterialFromType;jT.createMaterialFromType=function(e){const t=function(e){const t=yx.get(e);if(void 0!==t)return new t}(e);return void 0!==t?t:JP.call(this,e)};class ZP extends jT{constructor(e){super(e),this.nodes={}}parse(e){const t=super.parse(e),s=this.nodes,i=e.inputNodes;for(const e in i){const r=i[e];t[e]=s[r]}return t}setNodes(e){return this.nodes=e,this}}class KP extends YT{constructor(e){super(e),this._nodesJSON=null}parse(e,t){this._nodesJSON=e.nodes;const s=super.parse(e,t);return this._nodesJSON=null,s}parseNodes(e,t){if(void 0!==e){const s=new YP;return s.setTextures(t),s.parseNodes(e)}return{}}parseMaterials(e,t){const s={};if(void 0!==e){const i=this.parseNodes(this._nodesJSON,t),r=new ZP;r.setTextures(t),r.setNodes(i);for(let t=0,i=e.length;t>8&255]+Gs[e>>16&255]+Gs[e>>24&255]+"-"+Gs[255&t]+Gs[t>>8&255]+"-"+Gs[t>>16&15|64]+Gs[t>>24&255]+"-"+Gs[63&s|128]+Gs[s>>8&255]+"-"+Gs[s>>16&255]+Gs[s>>24&255]+Gs[255&i]+Gs[i>>8&255]+Gs[i>>16&255]+Gs[i>>24&255]).toLowerCase()}function $s(e,t,s){return Math.max(t,Math.min(s,e))}function Xs(e,t){return(e%t+t)%t}function Ys(e,t,s){return(1-s)*e+s*t}function Zs(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return e/4294967295;case Uint16Array:return e/65535;case Uint8Array:return e/255;case Int32Array:return Math.max(e/2147483647,-1);case Int16Array:return Math.max(e/32767,-1);case Int8Array:return Math.max(e/127,-1);default:throw new Error("Invalid component type.")}}function Js(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return Math.round(4294967295*e);case Uint16Array:return Math.round(65535*e);case Uint8Array:return Math.round(255*e);case Int32Array:return Math.round(2147483647*e);case Int16Array:return Math.round(32767*e);case Int8Array:return Math.round(127*e);default:throw new Error("Invalid component type.")}}const Ks={DEG2RAD:js,RAD2DEG:Hs,generateUUID:qs,clamp:$s,euclideanModulo:Xs,mapLinear:function(e,t,s,i,r){return i+(e-t)*(r-i)/(s-t)},inverseLerp:function(e,t,s){return e!==t?(s-e)/(t-e):0},lerp:Ys,damp:function(e,t,s,i){return Ys(e,t,1-Math.exp(-s*i))},pingpong:function(e,t=1){return t-Math.abs(Xs(e,2*t)-t)},smoothstep:function(e,t,s){return e<=t?0:e>=s?1:(e=(e-t)/(s-t))*e*(3-2*e)},smootherstep:function(e,t,s){return e<=t?0:e>=s?1:(e=(e-t)/(s-t))*e*e*(e*(6*e-15)+10)},randInt:function(e,t){return e+Math.floor(Math.random()*(t-e+1))},randFloat:function(e,t){return e+Math.random()*(t-e)},randFloatSpread:function(e){return e*(.5-Math.random())},seededRandom:function(e){void 0!==e&&(Ws=e);let t=Ws+=1831565813;return t=Math.imul(t^t>>>15,1|t),t^=t+Math.imul(t^t>>>7,61|t),((t^t>>>14)>>>0)/4294967296},degToRad:function(e){return e*js},radToDeg:function(e){return e*Hs},isPowerOfTwo:function(e){return 0==(e&e-1)&&0!==e},ceilPowerOfTwo:function(e){return Math.pow(2,Math.ceil(Math.log(e)/Math.LN2))},floorPowerOfTwo:function(e){return Math.pow(2,Math.floor(Math.log(e)/Math.LN2))},setQuaternionFromProperEuler:function(e,t,s,i,r){const n=Math.cos,o=Math.sin,a=n(s/2),h=o(s/2),u=n((t+i)/2),l=o((t+i)/2),c=n((t-i)/2),d=o((t-i)/2),p=n((i-t)/2),m=o((i-t)/2);switch(r){case"XYX":e.set(a*l,h*c,h*d,a*u);break;case"YZY":e.set(h*d,a*l,h*c,a*u);break;case"ZXZ":e.set(h*c,h*d,a*l,a*u);break;case"XZX":e.set(a*l,h*m,h*p,a*u);break;case"YXY":e.set(h*p,a*l,h*m,a*u);break;case"ZYZ":e.set(h*m,h*p,a*l,a*u);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}},normalize:Js,denormalize:Zs};class Qs{constructor(e=0,t=0){Qs.prototype.isVector2=!0,this.x=e,this.y=t}get width(){return this.x}set width(e){this.x=e}get height(){return this.y}set height(e){this.y=e}set(e,t){return this.x=e,this.y=t,this}setScalar(e){return this.x=e,this.y=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y)}copy(e){return this.x=e.x,this.y=e.y,this}add(e){return this.x+=e.x,this.y+=e.y,this}addScalar(e){return this.x+=e,this.y+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this}subScalar(e){return this.x-=e,this.y-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this}multiply(e){return this.x*=e.x,this.y*=e.y,this}multiplyScalar(e){return this.x*=e,this.y*=e,this}divide(e){return this.x/=e.x,this.y/=e.y,this}divideScalar(e){return this.multiplyScalar(1/e)}applyMatrix3(e){const t=this.x,s=this.y,i=e.elements;return this.x=i[0]*t+i[3]*s+i[6],this.y=i[1]*t+i[4]*s+i[7],this}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this}clampLength(e,t){const s=this.length();return this.divideScalar(s||1).multiplyScalar(Math.max(e,Math.min(t,s)))}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=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.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}angleTo(e){const t=Math.sqrt(this.lengthSq()*e.lengthSq());if(0===t)return Math.PI/2;const s=this.dot(e)/t;return Math.acos($s(s,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){const t=this.x-e.x,s=this.y-e.y;return t*t+s*s}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this}lerpVectors(e,t,s){return this.x=e.x+(t.x-e.x)*s,this.y=e.y+(t.y-e.y)*s,this}equals(e){return e.x===this.x&&e.y===this.y}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this}rotateAround(e,t){const s=Math.cos(t),i=Math.sin(t),r=this.x-e.x,n=this.y-e.y;return this.x=r*s-n*i+e.x,this.y=r*i+n*s+e.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class ei{constructor(e,t,s,i,r,n,o,a,h){ei.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],void 0!==e&&this.set(e,t,s,i,r,n,o,a,h)}set(e,t,s,i,r,n,o,a,h){const u=this.elements;return u[0]=e,u[1]=i,u[2]=o,u[3]=t,u[4]=r,u[5]=a,u[6]=s,u[7]=n,u[8]=h,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(e){const t=this.elements,s=e.elements;return t[0]=s[0],t[1]=s[1],t[2]=s[2],t[3]=s[3],t[4]=s[4],t[5]=s[5],t[6]=s[6],t[7]=s[7],t[8]=s[8],this}extractBasis(e,t,s){return e.setFromMatrix3Column(this,0),t.setFromMatrix3Column(this,1),s.setFromMatrix3Column(this,2),this}setFromMatrix4(e){const t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){const s=e.elements,i=t.elements,r=this.elements,n=s[0],o=s[3],a=s[6],h=s[1],u=s[4],l=s[7],c=s[2],d=s[5],p=s[8],m=i[0],g=i[3],f=i[6],y=i[1],x=i[4],b=i[7],v=i[2],T=i[5],_=i[8];return r[0]=n*m+o*y+a*v,r[3]=n*g+o*x+a*T,r[6]=n*f+o*b+a*_,r[1]=h*m+u*y+l*v,r[4]=h*g+u*x+l*T,r[7]=h*f+u*b+l*_,r[2]=c*m+d*y+p*v,r[5]=c*g+d*x+p*T,r[8]=c*f+d*b+p*_,this}multiplyScalar(e){const t=this.elements;return t[0]*=e,t[3]*=e,t[6]*=e,t[1]*=e,t[4]*=e,t[7]*=e,t[2]*=e,t[5]*=e,t[8]*=e,this}determinant(){const e=this.elements,t=e[0],s=e[1],i=e[2],r=e[3],n=e[4],o=e[5],a=e[6],h=e[7],u=e[8];return t*n*u-t*o*h-s*r*u+s*o*a+i*r*h-i*n*a}invert(){const e=this.elements,t=e[0],s=e[1],i=e[2],r=e[3],n=e[4],o=e[5],a=e[6],h=e[7],u=e[8],l=u*n-o*h,c=o*a-u*r,d=h*r-n*a,p=t*l+s*c+i*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const m=1/p;return e[0]=l*m,e[1]=(i*h-u*s)*m,e[2]=(o*s-i*n)*m,e[3]=c*m,e[4]=(u*t-i*a)*m,e[5]=(i*r-o*t)*m,e[6]=d*m,e[7]=(s*a-h*t)*m,e[8]=(n*t-s*r)*m,this}transpose(){let e;const t=this.elements;return e=t[1],t[1]=t[3],t[3]=e,e=t[2],t[2]=t[6],t[6]=e,e=t[5],t[5]=t[7],t[7]=e,this}getNormalMatrix(e){return this.setFromMatrix4(e).invert().transpose()}transposeIntoArray(e){const t=this.elements;return e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8],this}setUvTransform(e,t,s,i,r,n,o){const a=Math.cos(r),h=Math.sin(r);return this.set(s*a,s*h,-s*(a*n+h*o)+n+e,-i*h,i*a,-i*(-h*n+a*o)+o+t,0,0,1),this}scale(e,t){return this.premultiply(ti.makeScale(e,t)),this}rotate(e){return this.premultiply(ti.makeRotation(-e)),this}translate(e,t){return this.premultiply(ti.makeTranslation(e,t)),this}makeTranslation(e,t){return e.isVector2?this.set(1,0,e.x,0,1,e.y,0,0,1):this.set(1,0,e,0,1,t,0,0,1),this}makeRotation(e){const t=Math.cos(e),s=Math.sin(e);return this.set(t,-s,0,s,t,0,0,0,1),this}makeScale(e,t){return this.set(e,0,0,0,t,0,0,0,1),this}equals(e){const t=this.elements,s=e.elements;for(let e=0;e<9;e++)if(t[e]!==s[e])return!1;return!0}fromArray(e,t=0){for(let s=0;s<9;s++)this.elements[s]=e[s+t];return this}toArray(e=[],t=0){const s=this.elements;return e[t]=s[0],e[t+1]=s[1],e[t+2]=s[2],e[t+3]=s[3],e[t+4]=s[4],e[t+5]=s[5],e[t+6]=s[6],e[t+7]=s[7],e[t+8]=s[8],e}clone(){return(new this.constructor).fromArray(this.elements)}}const ti=new ei;const si={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function ii(e,t){return new si[e](t)}function ri(e){return document.createElementNS("http://www.w3.org/1999/xhtml",e)}function ni(){const e=ri("canvas");return e.style.display="block",e}const oi={};const ai=(new ei).set(.8224621,.177538,0,.0331941,.9668058,0,.0170827,.0723974,.9105199),hi=(new ei).set(1.2249401,-.2249404,0,-.0420569,1.0420571,0,-.0196376,-.0786361,1.0982735),ui={[Jt]:{transfer:es,primaries:ss,luminanceCoefficients:[.2126,.7152,.0722],toReference:e=>e,fromReference:e=>e},[Zt]:{transfer:ts,primaries:ss,luminanceCoefficients:[.2126,.7152,.0722],toReference:e=>e.convertSRGBToLinear(),fromReference:e=>e.convertLinearToSRGB()},[Qt]:{transfer:es,primaries:is,luminanceCoefficients:[.2289,.6917,.0793],toReference:e=>e.applyMatrix3(hi),fromReference:e=>e.applyMatrix3(ai)},[Kt]:{transfer:ts,primaries:is,luminanceCoefficients:[.2289,.6917,.0793],toReference:e=>e.convertSRGBToLinear().applyMatrix3(hi),fromReference:e=>e.applyMatrix3(ai).convertLinearToSRGB()}},li=new Set([Jt,Qt]),ci={enabled:!0,_workingColorSpace:Jt,get workingColorSpace(){return this._workingColorSpace},set workingColorSpace(e){if(!li.has(e))throw new Error(`Unsupported working color space, "${e}".`);this._workingColorSpace=e},convert:function(e,t,s){if(!1===this.enabled||t===s||!t||!s)return e;const i=ui[t].toReference;return(0,ui[s].fromReference)(i(e))},fromWorkingColorSpace:function(e,t){return this.convert(e,this._workingColorSpace,t)},toWorkingColorSpace:function(e,t){return this.convert(e,t,this._workingColorSpace)},getPrimaries:function(e){return ui[e].primaries},getTransfer:function(e){return e===Yt?es:ui[e].transfer},getLuminanceCoefficients:function(e,t=this._workingColorSpace){return e.fromArray(ui[t].luminanceCoefficients)}};function di(e){return e<.04045?.0773993808*e:Math.pow(.9478672986*e+.0521327014,2.4)}function pi(e){return e<.0031308?12.92*e:1.055*Math.pow(e,.41666)-.055}let mi;class gi{static getDataURL(e){if(/^data:/i.test(e.src))return e.src;if("undefined"==typeof HTMLCanvasElement)return e.src;let t;if(e instanceof HTMLCanvasElement)t=e;else{void 0===mi&&(mi=ri("canvas")),mi.width=e.width,mi.height=e.height;const s=mi.getContext("2d");e instanceof ImageData?s.putImageData(e,0,0):s.drawImage(e,0,0,e.width,e.height),t=mi}return t.width>2048||t.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",e),t.toDataURL("image/jpeg",.6)):t.toDataURL("image/png")}static sRGBToLinear(e){if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap){const t=ri("canvas");t.width=e.width,t.height=e.height;const s=t.getContext("2d");s.drawImage(e,0,0,e.width,e.height);const i=s.getImageData(0,0,e.width,e.height),r=i.data;for(let e=0;e0&&(s.userData=this.userData),t||(e.textures[this.uuid]=s),s}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(e){if(this.mapping!==ae)return e;if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case pe:e.x=e.x-Math.floor(e.x);break;case me:e.x=e.x<0?0:1;break;case ge:1===Math.abs(Math.floor(e.x)%2)?e.x=Math.ceil(e.x)-e.x:e.x=e.x-Math.floor(e.x)}if(e.y<0||e.y>1)switch(this.wrapT){case pe:e.y=e.y-Math.floor(e.y);break;case me:e.y=e.y<0?0:1;break;case ge:1===Math.abs(Math.floor(e.y)%2)?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y)}return this.flipY&&(e.y=1-e.y),e}set needsUpdate(e){!0===e&&(this.version++,this.source.needsUpdate=!0)}set needsPMREMUpdate(e){!0===e&&this.pmremVersion++}}vi.DEFAULT_IMAGE=null,vi.DEFAULT_MAPPING=ae,vi.DEFAULT_ANISOTROPY=1;class Ti{constructor(e=0,t=0,s=0,i=1){Ti.prototype.isVector4=!0,this.x=e,this.y=t,this.z=s,this.w=i}get width(){return this.z}set width(e){this.z=e}get height(){return this.w}set height(e){this.w=e}set(e,t,s,i){return this.x=e,this.y=t,this.z=s,this.w=i,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this.w=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setW(e){return this.w=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;case 3:this.w=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){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: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=void 0!==e.w?e.w:1,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this.w=e.w+t.w,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this.w+=e.w*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this.w=e.w-t.w,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this.w*=e.w,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this}applyMatrix4(e){const t=this.x,s=this.y,i=this.z,r=this.w,n=e.elements;return this.x=n[0]*t+n[4]*s+n[8]*i+n[12]*r,this.y=n[1]*t+n[5]*s+n[9]*i+n[13]*r,this.z=n[2]*t+n[6]*s+n[10]*i+n[14]*r,this.w=n[3]*t+n[7]*s+n[11]*i+n[15]*r,this}divideScalar(e){return this.multiplyScalar(1/e)}setAxisAngleFromQuaternion(e){this.w=2*Math.acos(e.w);const t=Math.sqrt(1-e.w*e.w);return t<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=e.x/t,this.y=e.y/t,this.z=e.z/t),this}setAxisAngleFromRotationMatrix(e){let t,s,i,r;const n=.01,o=.1,a=e.elements,h=a[0],u=a[4],l=a[8],c=a[1],d=a[5],p=a[9],m=a[2],g=a[6],f=a[10];if(Math.abs(u-c)a&&e>y?ey?a=0?1:-1,i=1-t*t;if(i>Number.EPSILON){const r=Math.sqrt(i),n=Math.atan2(r,t*s);e=Math.sin(e*n)/r,o=Math.sin(o*n)/r}const r=o*s;if(a=a*e+c*r,h=h*e+d*r,u=u*e+p*r,l=l*e+m*r,e===1-o){const e=1/Math.sqrt(a*a+h*h+u*u+l*l);a*=e,h*=e,u*=e,l*=e}}e[t]=a,e[t+1]=h,e[t+2]=u,e[t+3]=l}static multiplyQuaternionsFlat(e,t,s,i,r,n){const o=s[i],a=s[i+1],h=s[i+2],u=s[i+3],l=r[n],c=r[n+1],d=r[n+2],p=r[n+3];return e[t]=o*p+u*l+a*d-h*c,e[t+1]=a*p+u*c+h*l-o*d,e[t+2]=h*p+u*d+o*c-a*l,e[t+3]=u*p-o*l-a*c-h*d,e}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get w(){return this._w}set w(e){this._w=e,this._onChangeCallback()}set(e,t,s,i){return this._x=e,this._y=t,this._z=s,this._w=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this._onChangeCallback(),this}setFromEuler(e,t=!0){const s=e._x,i=e._y,r=e._z,n=e._order,o=Math.cos,a=Math.sin,h=o(s/2),u=o(i/2),l=o(r/2),c=a(s/2),d=a(i/2),p=a(r/2);switch(n){case"XYZ":this._x=c*u*l+h*d*p,this._y=h*d*l-c*u*p,this._z=h*u*p+c*d*l,this._w=h*u*l-c*d*p;break;case"YXZ":this._x=c*u*l+h*d*p,this._y=h*d*l-c*u*p,this._z=h*u*p-c*d*l,this._w=h*u*l+c*d*p;break;case"ZXY":this._x=c*u*l-h*d*p,this._y=h*d*l+c*u*p,this._z=h*u*p+c*d*l,this._w=h*u*l-c*d*p;break;case"ZYX":this._x=c*u*l-h*d*p,this._y=h*d*l+c*u*p,this._z=h*u*p-c*d*l,this._w=h*u*l+c*d*p;break;case"YZX":this._x=c*u*l+h*d*p,this._y=h*d*l+c*u*p,this._z=h*u*p-c*d*l,this._w=h*u*l-c*d*p;break;case"XZY":this._x=c*u*l-h*d*p,this._y=h*d*l-c*u*p,this._z=h*u*p+c*d*l,this._w=h*u*l+c*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+n)}return!0===t&&this._onChangeCallback(),this}setFromAxisAngle(e,t){const s=t/2,i=Math.sin(s);return this._x=e.x*i,this._y=e.y*i,this._z=e.z*i,this._w=Math.cos(s),this._onChangeCallback(),this}setFromRotationMatrix(e){const t=e.elements,s=t[0],i=t[4],r=t[8],n=t[1],o=t[5],a=t[9],h=t[2],u=t[6],l=t[10],c=s+o+l;if(c>0){const e=.5/Math.sqrt(c+1);this._w=.25/e,this._x=(u-a)*e,this._y=(r-h)*e,this._z=(n-i)*e}else if(s>o&&s>l){const e=2*Math.sqrt(1+s-o-l);this._w=(u-a)/e,this._x=.25*e,this._y=(i+n)/e,this._z=(r+h)/e}else if(o>l){const e=2*Math.sqrt(1+o-s-l);this._w=(r-h)/e,this._x=(i+n)/e,this._y=.25*e,this._z=(a+u)/e}else{const e=2*Math.sqrt(1+l-s-o);this._w=(n-i)/e,this._x=(r+h)/e,this._y=(a+u)/e,this._z=.25*e}return this._onChangeCallback(),this}setFromUnitVectors(e,t){let s=e.dot(t)+1;return sMath.abs(e.z)?(this._x=-e.y,this._y=e.x,this._z=0,this._w=s):(this._x=0,this._y=-e.z,this._z=e.y,this._w=s)):(this._x=e.y*t.z-e.z*t.y,this._y=e.z*t.x-e.x*t.z,this._z=e.x*t.y-e.y*t.x,this._w=s),this.normalize()}angleTo(e){return 2*Math.acos(Math.abs($s(this.dot(e),-1,1)))}rotateTowards(e,t){const s=this.angleTo(e);if(0===s)return this;const i=Math.min(1,t/s);return this.slerp(e,i),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(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._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 e=this.length();return 0===e?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x=this._x*e,this._y=this._y*e,this._z=this._z*e,this._w=this._w*e),this._onChangeCallback(),this}multiply(e){return this.multiplyQuaternions(this,e)}premultiply(e){return this.multiplyQuaternions(e,this)}multiplyQuaternions(e,t){const s=e._x,i=e._y,r=e._z,n=e._w,o=t._x,a=t._y,h=t._z,u=t._w;return this._x=s*u+n*o+i*h-r*a,this._y=i*u+n*a+r*o-s*h,this._z=r*u+n*h+s*a-i*o,this._w=n*u-s*o-i*a-r*h,this._onChangeCallback(),this}slerp(e,t){if(0===t)return this;if(1===t)return this.copy(e);const s=this._x,i=this._y,r=this._z,n=this._w;let o=n*e._w+s*e._x+i*e._y+r*e._z;if(o<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,o=-o):this.copy(e),o>=1)return this._w=n,this._x=s,this._y=i,this._z=r,this;const a=1-o*o;if(a<=Number.EPSILON){const e=1-t;return this._w=e*n+t*this._w,this._x=e*s+t*this._x,this._y=e*i+t*this._y,this._z=e*r+t*this._z,this.normalize(),this}const h=Math.sqrt(a),u=Math.atan2(h,o),l=Math.sin((1-t)*u)/h,c=Math.sin(t*u)/h;return this._w=n*l+this._w*c,this._x=s*l+this._x*c,this._y=i*l+this._y*c,this._z=r*l+this._z*c,this._onChangeCallback(),this}slerpQuaternions(e,t,s){return this.copy(e).slerp(t,s)}random(){const e=2*Math.PI*Math.random(),t=2*Math.PI*Math.random(),s=Math.random(),i=Math.sqrt(1-s),r=Math.sqrt(s);return this.set(i*Math.sin(e),i*Math.cos(e),r*Math.sin(t),r*Math.cos(t))}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w}fromArray(e,t=0){return this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e}fromBufferAttribute(e,t){return this._x=e.getX(t),this._y=e.getY(t),this._z=e.getZ(t),this._w=e.getW(t),this._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class Ri{constructor(e=0,t=0,s=0){Ri.prototype.isVector3=!0,this.x=e,this.y=t,this.z=s}set(e,t,s){return void 0===s&&(s=this.z),this.x=e,this.y=t,this.z=s,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this}multiplyVectors(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this}applyEuler(e){return this.applyQuaternion(Bi.setFromEuler(e))}applyAxisAngle(e,t){return this.applyQuaternion(Bi.setFromAxisAngle(e,t))}applyMatrix3(e){const t=this.x,s=this.y,i=this.z,r=e.elements;return this.x=r[0]*t+r[3]*s+r[6]*i,this.y=r[1]*t+r[4]*s+r[7]*i,this.z=r[2]*t+r[5]*s+r[8]*i,this}applyNormalMatrix(e){return this.applyMatrix3(e).normalize()}applyMatrix4(e){const t=this.x,s=this.y,i=this.z,r=e.elements,n=1/(r[3]*t+r[7]*s+r[11]*i+r[15]);return this.x=(r[0]*t+r[4]*s+r[8]*i+r[12])*n,this.y=(r[1]*t+r[5]*s+r[9]*i+r[13])*n,this.z=(r[2]*t+r[6]*s+r[10]*i+r[14])*n,this}applyQuaternion(e){const t=this.x,s=this.y,i=this.z,r=e.x,n=e.y,o=e.z,a=e.w,h=2*(n*i-o*s),u=2*(o*t-r*i),l=2*(r*s-n*t);return this.x=t+a*h+n*l-o*u,this.y=s+a*u+o*h-r*l,this.z=i+a*l+r*u-n*h,this}project(e){return this.applyMatrix4(e.matrixWorldInverse).applyMatrix4(e.projectionMatrix)}unproject(e){return this.applyMatrix4(e.projectionMatrixInverse).applyMatrix4(e.matrixWorld)}transformDirection(e){const t=this.x,s=this.y,i=this.z,r=e.elements;return this.x=r[0]*t+r[4]*s+r[8]*i,this.y=r[1]*t+r[5]*s+r[9]*i,this.z=r[2]*t+r[6]*s+r[10]*i,this.normalize()}divide(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this}divideScalar(e){return this.multiplyScalar(1/e)}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this.z=Math.max(e,Math.min(t,this.z)),this}clampLength(e,t){const s=this.length();return this.divideScalar(s||1).multiplyScalar(Math.max(e,Math.min(t,s)))}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=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(e){return this.x*e.x+this.y*e.y+this.z*e.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(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this}lerpVectors(e,t,s){return this.x=e.x+(t.x-e.x)*s,this.y=e.y+(t.y-e.y)*s,this.z=e.z+(t.z-e.z)*s,this}cross(e){return this.crossVectors(this,e)}crossVectors(e,t){const s=e.x,i=e.y,r=e.z,n=t.x,o=t.y,a=t.z;return this.x=i*a-r*o,this.y=r*n-s*a,this.z=s*o-i*n,this}projectOnVector(e){const t=e.lengthSq();if(0===t)return this.set(0,0,0);const s=e.dot(this)/t;return this.copy(e).multiplyScalar(s)}projectOnPlane(e){return Ei.copy(this).projectOnVector(e),this.sub(Ei)}reflect(e){return this.sub(Ei.copy(e).multiplyScalar(2*this.dot(e)))}angleTo(e){const t=Math.sqrt(this.lengthSq()*e.lengthSq());if(0===t)return Math.PI/2;const s=this.dot(e)/t;return Math.acos($s(s,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){const t=this.x-e.x,s=this.y-e.y,i=this.z-e.z;return t*t+s*s+i*i}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)}setFromSpherical(e){return this.setFromSphericalCoords(e.radius,e.phi,e.theta)}setFromSphericalCoords(e,t,s){const i=Math.sin(t)*e;return this.x=i*Math.sin(s),this.y=Math.cos(t)*e,this.z=i*Math.cos(s),this}setFromCylindrical(e){return this.setFromCylindricalCoords(e.radius,e.theta,e.y)}setFromCylindricalCoords(e,t,s){return this.x=e*Math.sin(t),this.y=s,this.z=e*Math.cos(t),this}setFromMatrixPosition(e){const t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this}setFromMatrixScale(e){const t=this.setFromMatrixColumn(e,0).length(),s=this.setFromMatrixColumn(e,1).length(),i=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=s,this.z=i,this}setFromMatrixColumn(e,t){return this.fromArray(e.elements,4*t)}setFromMatrix3Column(e,t){return this.fromArray(e.elements,3*t)}setFromEuler(e){return this.x=e._x,this.y=e._y,this.z=e._z,this}setFromColor(e){return this.x=e.r,this.y=e.g,this.z=e.b,this}equals(e){return e.x===this.x&&e.y===this.y&&e.z===this.z}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this.z=e[t+2],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const e=Math.random()*Math.PI*2,t=2*Math.random()-1,s=Math.sqrt(1-t*t);return this.x=s*Math.cos(e),this.y=t,this.z=s*Math.sin(e),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const Ei=new Ri,Bi=new Ci;class Ii{constructor(e=new Ri(1/0,1/0,1/0),t=new Ri(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=e,this.max=t}set(e,t){return this.min.copy(e),this.max.copy(t),this}setFromArray(e){this.makeEmpty();for(let t=0,s=e.length;t=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y&&e.z>=this.min.z&&e.z<=this.max.z}containsBox(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z}getParameter(e,t){return t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(e){return e.max.x>=this.min.x&&e.min.x<=this.max.x&&e.max.y>=this.min.y&&e.min.y<=this.max.y&&e.max.z>=this.min.z&&e.min.z<=this.max.z}intersectsSphere(e){return this.clampPoint(e.center,Fi),Fi.distanceToSquared(e.center)<=e.radius*e.radius}intersectsPlane(e){let t,s;return e.normal.x>0?(t=e.normal.x*this.min.x,s=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,s=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,s+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,s+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,s+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,s+=e.normal.z*this.min.z),t<=-e.constant&&s>=-e.constant}intersectsTriangle(e){if(this.isEmpty())return!1;this.getCenter(Gi),Wi.subVectors(this.max,Gi),Ui.subVectors(e.a,Gi),Oi.subVectors(e.b,Gi),Li.subVectors(e.c,Gi),Vi.subVectors(Oi,Ui),Di.subVectors(Li,Oi),ki.subVectors(Ui,Li);let t=[0,-Vi.z,Vi.y,0,-Di.z,Di.y,0,-ki.z,ki.y,Vi.z,0,-Vi.x,Di.z,0,-Di.x,ki.z,0,-ki.x,-Vi.y,Vi.x,0,-Di.y,Di.x,0,-ki.y,ki.x,0];return!!qi(t,Ui,Oi,Li,Wi)&&(t=[1,0,0,0,1,0,0,0,1],!!qi(t,Ui,Oi,Li,Wi)&&(ji.crossVectors(Vi,Di),t=[ji.x,ji.y,ji.z],qi(t,Ui,Oi,Li,Wi)))}clampPoint(e,t){return t.copy(e).clamp(this.min,this.max)}distanceToPoint(e){return this.clampPoint(e,Fi).distanceTo(e)}getBoundingSphere(e){return this.isEmpty()?e.makeEmpty():(this.getCenter(e.center),e.radius=.5*this.getSize(Fi).length()),e}intersect(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this}union(e){return this.min.min(e.min),this.max.max(e.max),this}applyMatrix4(e){return this.isEmpty()||(Pi[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),Pi[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),Pi[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),Pi[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),Pi[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),Pi[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),Pi[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),Pi[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(Pi)),this}translate(e){return this.min.add(e),this.max.add(e),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}const Pi=[new Ri,new Ri,new Ri,new Ri,new Ri,new Ri,new Ri,new Ri],Fi=new Ri,zi=new Ii,Ui=new Ri,Oi=new Ri,Li=new Ri,Vi=new Ri,Di=new Ri,ki=new Ri,Gi=new Ri,Wi=new Ri,ji=new Ri,Hi=new Ri;function qi(e,t,s,i,r){for(let n=0,o=e.length-3;n<=o;n+=3){Hi.fromArray(e,n);const o=r.x*Math.abs(Hi.x)+r.y*Math.abs(Hi.y)+r.z*Math.abs(Hi.z),a=t.dot(Hi),h=s.dot(Hi),u=i.dot(Hi);if(Math.max(-Math.max(a,h,u),Math.min(a,h,u))>o)return!1}return!0}const $i=new Ii,Xi=new Ri,Yi=new Ri;class Zi{constructor(e=new Ri,t=-1){this.isSphere=!0,this.center=e,this.radius=t}set(e,t){return this.center.copy(e),this.radius=t,this}setFromPoints(e,t){const s=this.center;void 0!==t?s.copy(t):$i.setFromPoints(e).getCenter(s);let i=0;for(let t=0,r=e.length;tthis.radius*this.radius&&(t.sub(this.center).normalize(),t.multiplyScalar(this.radius).add(this.center)),t}getBoundingBox(e){return this.isEmpty()?(e.makeEmpty(),e):(e.set(this.center,this.center),e.expandByScalar(this.radius),e)}applyMatrix4(e){return this.center.applyMatrix4(e),this.radius=this.radius*e.getMaxScaleOnAxis(),this}translate(e){return this.center.add(e),this}expandByPoint(e){if(this.isEmpty())return this.center.copy(e),this.radius=0,this;Xi.subVectors(e,this.center);const t=Xi.lengthSq();if(t>this.radius*this.radius){const e=Math.sqrt(t),s=.5*(e-this.radius);this.center.addScaledVector(Xi,s/e),this.radius+=s}return this}union(e){return e.isEmpty()?this:this.isEmpty()?(this.copy(e),this):(!0===this.center.equals(e.center)?this.radius=Math.max(this.radius,e.radius):(Yi.subVectors(e.center,this.center).setLength(e.radius),this.expandByPoint(Xi.copy(e.center).add(Yi)),this.expandByPoint(Xi.copy(e.center).sub(Yi))),this)}equals(e){return e.center.equals(this.center)&&e.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const Ji=new Ri,Ki=new Ri,Qi=new Ri,er=new Ri,tr=new Ri,sr=new Ri,ir=new Ri;class rr{constructor(e=new Ri,t=new Ri(0,0,-1)){this.origin=e,this.direction=t}set(e,t){return this.origin.copy(e),this.direction.copy(t),this}copy(e){return this.origin.copy(e.origin),this.direction.copy(e.direction),this}at(e,t){return t.copy(this.origin).addScaledVector(this.direction,e)}lookAt(e){return this.direction.copy(e).sub(this.origin).normalize(),this}recast(e){return this.origin.copy(this.at(e,Ji)),this}closestPointToPoint(e,t){t.subVectors(e,this.origin);const s=t.dot(this.direction);return s<0?t.copy(this.origin):t.copy(this.origin).addScaledVector(this.direction,s)}distanceToPoint(e){return Math.sqrt(this.distanceSqToPoint(e))}distanceSqToPoint(e){const t=Ji.subVectors(e,this.origin).dot(this.direction);return t<0?this.origin.distanceToSquared(e):(Ji.copy(this.origin).addScaledVector(this.direction,t),Ji.distanceToSquared(e))}distanceSqToSegment(e,t,s,i){Ki.copy(e).add(t).multiplyScalar(.5),Qi.copy(t).sub(e).normalize(),er.copy(this.origin).sub(Ki);const r=.5*e.distanceTo(t),n=-this.direction.dot(Qi),o=er.dot(this.direction),a=-er.dot(Qi),h=er.lengthSq(),u=Math.abs(1-n*n);let l,c,d,p;if(u>0)if(l=n*a-o,c=n*o-a,p=r*u,l>=0)if(c>=-p)if(c<=p){const e=1/u;l*=e,c*=e,d=l*(l+n*c+2*o)+c*(n*l+c+2*a)+h}else c=r,l=Math.max(0,-(n*c+o)),d=-l*l+c*(c+2*a)+h;else c=-r,l=Math.max(0,-(n*c+o)),d=-l*l+c*(c+2*a)+h;else c<=-p?(l=Math.max(0,-(-n*r+o)),c=l>0?-r:Math.min(Math.max(-r,-a),r),d=-l*l+c*(c+2*a)+h):c<=p?(l=0,c=Math.min(Math.max(-r,-a),r),d=c*(c+2*a)+h):(l=Math.max(0,-(n*r+o)),c=l>0?r:Math.min(Math.max(-r,-a),r),d=-l*l+c*(c+2*a)+h);else c=n>0?-r:r,l=Math.max(0,-(n*c+o)),d=-l*l+c*(c+2*a)+h;return s&&s.copy(this.origin).addScaledVector(this.direction,l),i&&i.copy(Ki).addScaledVector(Qi,c),d}intersectSphere(e,t){Ji.subVectors(e.center,this.origin);const s=Ji.dot(this.direction),i=Ji.dot(Ji)-s*s,r=e.radius*e.radius;if(i>r)return null;const n=Math.sqrt(r-i),o=s-n,a=s+n;return a<0?null:o<0?this.at(a,t):this.at(o,t)}intersectsSphere(e){return this.distanceSqToPoint(e.center)<=e.radius*e.radius}distanceToPlane(e){const t=e.normal.dot(this.direction);if(0===t)return 0===e.distanceToPoint(this.origin)?0:null;const s=-(this.origin.dot(e.normal)+e.constant)/t;return s>=0?s:null}intersectPlane(e,t){const s=this.distanceToPlane(e);return null===s?null:this.at(s,t)}intersectsPlane(e){const t=e.distanceToPoint(this.origin);if(0===t)return!0;return e.normal.dot(this.direction)*t<0}intersectBox(e,t){let s,i,r,n,o,a;const h=1/this.direction.x,u=1/this.direction.y,l=1/this.direction.z,c=this.origin;return h>=0?(s=(e.min.x-c.x)*h,i=(e.max.x-c.x)*h):(s=(e.max.x-c.x)*h,i=(e.min.x-c.x)*h),u>=0?(r=(e.min.y-c.y)*u,n=(e.max.y-c.y)*u):(r=(e.max.y-c.y)*u,n=(e.min.y-c.y)*u),s>n||r>i?null:((r>s||isNaN(s))&&(s=r),(n=0?(o=(e.min.z-c.z)*l,a=(e.max.z-c.z)*l):(o=(e.max.z-c.z)*l,a=(e.min.z-c.z)*l),s>a||o>i?null:((o>s||s!=s)&&(s=o),(a=0?s:i,t)))}intersectsBox(e){return null!==this.intersectBox(e,Ji)}intersectTriangle(e,t,s,i,r){tr.subVectors(t,e),sr.subVectors(s,e),ir.crossVectors(tr,sr);let n,o=this.direction.dot(ir);if(o>0){if(i)return null;n=1}else{if(!(o<0))return null;n=-1,o=-o}er.subVectors(this.origin,e);const a=n*this.direction.dot(sr.crossVectors(er,sr));if(a<0)return null;const h=n*this.direction.dot(tr.cross(er));if(h<0)return null;if(a+h>o)return null;const u=-n*er.dot(ir);return u<0?null:this.at(u/o,r)}applyMatrix4(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this}equals(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class nr{constructor(e,t,s,i,r,n,o,a,h,u,l,c,d,p,m,g){nr.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],void 0!==e&&this.set(e,t,s,i,r,n,o,a,h,u,l,c,d,p,m,g)}set(e,t,s,i,r,n,o,a,h,u,l,c,d,p,m,g){const f=this.elements;return f[0]=e,f[4]=t,f[8]=s,f[12]=i,f[1]=r,f[5]=n,f[9]=o,f[13]=a,f[2]=h,f[6]=u,f[10]=l,f[14]=c,f[3]=d,f[7]=p,f[11]=m,f[15]=g,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 nr).fromArray(this.elements)}copy(e){const t=this.elements,s=e.elements;return t[0]=s[0],t[1]=s[1],t[2]=s[2],t[3]=s[3],t[4]=s[4],t[5]=s[5],t[6]=s[6],t[7]=s[7],t[8]=s[8],t[9]=s[9],t[10]=s[10],t[11]=s[11],t[12]=s[12],t[13]=s[13],t[14]=s[14],t[15]=s[15],this}copyPosition(e){const t=this.elements,s=e.elements;return t[12]=s[12],t[13]=s[13],t[14]=s[14],this}setFromMatrix3(e){const t=e.elements;return this.set(t[0],t[3],t[6],0,t[1],t[4],t[7],0,t[2],t[5],t[8],0,0,0,0,1),this}extractBasis(e,t,s){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),s.setFromMatrixColumn(this,2),this}makeBasis(e,t,s){return this.set(e.x,t.x,s.x,0,e.y,t.y,s.y,0,e.z,t.z,s.z,0,0,0,0,1),this}extractRotation(e){const t=this.elements,s=e.elements,i=1/or.setFromMatrixColumn(e,0).length(),r=1/or.setFromMatrixColumn(e,1).length(),n=1/or.setFromMatrixColumn(e,2).length();return t[0]=s[0]*i,t[1]=s[1]*i,t[2]=s[2]*i,t[3]=0,t[4]=s[4]*r,t[5]=s[5]*r,t[6]=s[6]*r,t[7]=0,t[8]=s[8]*n,t[9]=s[9]*n,t[10]=s[10]*n,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromEuler(e){const t=this.elements,s=e.x,i=e.y,r=e.z,n=Math.cos(s),o=Math.sin(s),a=Math.cos(i),h=Math.sin(i),u=Math.cos(r),l=Math.sin(r);if("XYZ"===e.order){const e=n*u,s=n*l,i=o*u,r=o*l;t[0]=a*u,t[4]=-a*l,t[8]=h,t[1]=s+i*h,t[5]=e-r*h,t[9]=-o*a,t[2]=r-e*h,t[6]=i+s*h,t[10]=n*a}else if("YXZ"===e.order){const e=a*u,s=a*l,i=h*u,r=h*l;t[0]=e+r*o,t[4]=i*o-s,t[8]=n*h,t[1]=n*l,t[5]=n*u,t[9]=-o,t[2]=s*o-i,t[6]=r+e*o,t[10]=n*a}else if("ZXY"===e.order){const e=a*u,s=a*l,i=h*u,r=h*l;t[0]=e-r*o,t[4]=-n*l,t[8]=i+s*o,t[1]=s+i*o,t[5]=n*u,t[9]=r-e*o,t[2]=-n*h,t[6]=o,t[10]=n*a}else if("ZYX"===e.order){const e=n*u,s=n*l,i=o*u,r=o*l;t[0]=a*u,t[4]=i*h-s,t[8]=e*h+r,t[1]=a*l,t[5]=r*h+e,t[9]=s*h-i,t[2]=-h,t[6]=o*a,t[10]=n*a}else if("YZX"===e.order){const e=n*a,s=n*h,i=o*a,r=o*h;t[0]=a*u,t[4]=r-e*l,t[8]=i*l+s,t[1]=l,t[5]=n*u,t[9]=-o*u,t[2]=-h*u,t[6]=s*l+i,t[10]=e-r*l}else if("XZY"===e.order){const e=n*a,s=n*h,i=o*a,r=o*h;t[0]=a*u,t[4]=-l,t[8]=h*u,t[1]=e*l+r,t[5]=n*u,t[9]=s*l-i,t[2]=i*l-s,t[6]=o*u,t[10]=r*l+e}return t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromQuaternion(e){return this.compose(hr,e,ur)}lookAt(e,t,s){const i=this.elements;return dr.subVectors(e,t),0===dr.lengthSq()&&(dr.z=1),dr.normalize(),lr.crossVectors(s,dr),0===lr.lengthSq()&&(1===Math.abs(s.z)?dr.x+=1e-4:dr.z+=1e-4,dr.normalize(),lr.crossVectors(s,dr)),lr.normalize(),cr.crossVectors(dr,lr),i[0]=lr.x,i[4]=cr.x,i[8]=dr.x,i[1]=lr.y,i[5]=cr.y,i[9]=dr.y,i[2]=lr.z,i[6]=cr.z,i[10]=dr.z,this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){const s=e.elements,i=t.elements,r=this.elements,n=s[0],o=s[4],a=s[8],h=s[12],u=s[1],l=s[5],c=s[9],d=s[13],p=s[2],m=s[6],g=s[10],f=s[14],y=s[3],x=s[7],b=s[11],v=s[15],T=i[0],_=i[4],w=i[8],S=i[12],M=i[1],N=i[5],A=i[9],C=i[13],R=i[2],E=i[6],B=i[10],I=i[14],P=i[3],F=i[7],z=i[11],U=i[15];return r[0]=n*T+o*M+a*R+h*P,r[4]=n*_+o*N+a*E+h*F,r[8]=n*w+o*A+a*B+h*z,r[12]=n*S+o*C+a*I+h*U,r[1]=u*T+l*M+c*R+d*P,r[5]=u*_+l*N+c*E+d*F,r[9]=u*w+l*A+c*B+d*z,r[13]=u*S+l*C+c*I+d*U,r[2]=p*T+m*M+g*R+f*P,r[6]=p*_+m*N+g*E+f*F,r[10]=p*w+m*A+g*B+f*z,r[14]=p*S+m*C+g*I+f*U,r[3]=y*T+x*M+b*R+v*P,r[7]=y*_+x*N+b*E+v*F,r[11]=y*w+x*A+b*B+v*z,r[15]=y*S+x*C+b*I+v*U,this}multiplyScalar(e){const t=this.elements;return t[0]*=e,t[4]*=e,t[8]*=e,t[12]*=e,t[1]*=e,t[5]*=e,t[9]*=e,t[13]*=e,t[2]*=e,t[6]*=e,t[10]*=e,t[14]*=e,t[3]*=e,t[7]*=e,t[11]*=e,t[15]*=e,this}determinant(){const e=this.elements,t=e[0],s=e[4],i=e[8],r=e[12],n=e[1],o=e[5],a=e[9],h=e[13],u=e[2],l=e[6],c=e[10],d=e[14];return e[3]*(+r*a*l-i*h*l-r*o*c+s*h*c+i*o*d-s*a*d)+e[7]*(+t*a*d-t*h*c+r*n*c-i*n*d+i*h*u-r*a*u)+e[11]*(+t*h*l-t*o*d-r*n*l+s*n*d+r*o*u-s*h*u)+e[15]*(-i*o*u-t*a*l+t*o*c+i*n*l-s*n*c+s*a*u)}transpose(){const e=this.elements;let t;return t=e[1],e[1]=e[4],e[4]=t,t=e[2],e[2]=e[8],e[8]=t,t=e[6],e[6]=e[9],e[9]=t,t=e[3],e[3]=e[12],e[12]=t,t=e[7],e[7]=e[13],e[13]=t,t=e[11],e[11]=e[14],e[14]=t,this}setPosition(e,t,s){const i=this.elements;return e.isVector3?(i[12]=e.x,i[13]=e.y,i[14]=e.z):(i[12]=e,i[13]=t,i[14]=s),this}invert(){const e=this.elements,t=e[0],s=e[1],i=e[2],r=e[3],n=e[4],o=e[5],a=e[6],h=e[7],u=e[8],l=e[9],c=e[10],d=e[11],p=e[12],m=e[13],g=e[14],f=e[15],y=l*g*h-m*c*h+m*a*d-o*g*d-l*a*f+o*c*f,x=p*c*h-u*g*h-p*a*d+n*g*d+u*a*f-n*c*f,b=u*m*h-p*l*h+p*o*d-n*m*d-u*o*f+n*l*f,v=p*l*a-u*m*a-p*o*c+n*m*c+u*o*g-n*l*g,T=t*y+s*x+i*b+r*v;if(0===T)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const _=1/T;return e[0]=y*_,e[1]=(m*c*r-l*g*r-m*i*d+s*g*d+l*i*f-s*c*f)*_,e[2]=(o*g*r-m*a*r+m*i*h-s*g*h-o*i*f+s*a*f)*_,e[3]=(l*a*r-o*c*r-l*i*h+s*c*h+o*i*d-s*a*d)*_,e[4]=x*_,e[5]=(u*g*r-p*c*r+p*i*d-t*g*d-u*i*f+t*c*f)*_,e[6]=(p*a*r-n*g*r-p*i*h+t*g*h+n*i*f-t*a*f)*_,e[7]=(n*c*r-u*a*r+u*i*h-t*c*h-n*i*d+t*a*d)*_,e[8]=b*_,e[9]=(p*l*r-u*m*r-p*s*d+t*m*d+u*s*f-t*l*f)*_,e[10]=(n*m*r-p*o*r+p*s*h-t*m*h-n*s*f+t*o*f)*_,e[11]=(u*o*r-n*l*r-u*s*h+t*l*h+n*s*d-t*o*d)*_,e[12]=v*_,e[13]=(u*m*i-p*l*i+p*s*c-t*m*c-u*s*g+t*l*g)*_,e[14]=(p*o*i-n*m*i-p*s*a+t*m*a+n*s*g-t*o*g)*_,e[15]=(n*l*i-u*o*i+u*s*a-t*l*a-n*s*c+t*o*c)*_,this}scale(e){const t=this.elements,s=e.x,i=e.y,r=e.z;return t[0]*=s,t[4]*=i,t[8]*=r,t[1]*=s,t[5]*=i,t[9]*=r,t[2]*=s,t[6]*=i,t[10]*=r,t[3]*=s,t[7]*=i,t[11]*=r,this}getMaxScaleOnAxis(){const e=this.elements,t=e[0]*e[0]+e[1]*e[1]+e[2]*e[2],s=e[4]*e[4]+e[5]*e[5]+e[6]*e[6],i=e[8]*e[8]+e[9]*e[9]+e[10]*e[10];return Math.sqrt(Math.max(t,s,i))}makeTranslation(e,t,s){return e.isVector3?this.set(1,0,0,e.x,0,1,0,e.y,0,0,1,e.z,0,0,0,1):this.set(1,0,0,e,0,1,0,t,0,0,1,s,0,0,0,1),this}makeRotationX(e){const t=Math.cos(e),s=Math.sin(e);return this.set(1,0,0,0,0,t,-s,0,0,s,t,0,0,0,0,1),this}makeRotationY(e){const t=Math.cos(e),s=Math.sin(e);return this.set(t,0,s,0,0,1,0,0,-s,0,t,0,0,0,0,1),this}makeRotationZ(e){const t=Math.cos(e),s=Math.sin(e);return this.set(t,-s,0,0,s,t,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(e,t){const s=Math.cos(t),i=Math.sin(t),r=1-s,n=e.x,o=e.y,a=e.z,h=r*n,u=r*o;return this.set(h*n+s,h*o-i*a,h*a+i*o,0,h*o+i*a,u*o+s,u*a-i*n,0,h*a-i*o,u*a+i*n,r*a*a+s,0,0,0,0,1),this}makeScale(e,t,s){return this.set(e,0,0,0,0,t,0,0,0,0,s,0,0,0,0,1),this}makeShear(e,t,s,i,r,n){return this.set(1,s,r,0,e,1,n,0,t,i,1,0,0,0,0,1),this}compose(e,t,s){const i=this.elements,r=t._x,n=t._y,o=t._z,a=t._w,h=r+r,u=n+n,l=o+o,c=r*h,d=r*u,p=r*l,m=n*u,g=n*l,f=o*l,y=a*h,x=a*u,b=a*l,v=s.x,T=s.y,_=s.z;return i[0]=(1-(m+f))*v,i[1]=(d+b)*v,i[2]=(p-x)*v,i[3]=0,i[4]=(d-b)*T,i[5]=(1-(c+f))*T,i[6]=(g+y)*T,i[7]=0,i[8]=(p+x)*_,i[9]=(g-y)*_,i[10]=(1-(c+m))*_,i[11]=0,i[12]=e.x,i[13]=e.y,i[14]=e.z,i[15]=1,this}decompose(e,t,s){const i=this.elements;let r=or.set(i[0],i[1],i[2]).length();const n=or.set(i[4],i[5],i[6]).length(),o=or.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),e.x=i[12],e.y=i[13],e.z=i[14],ar.copy(this);const a=1/r,h=1/n,u=1/o;return ar.elements[0]*=a,ar.elements[1]*=a,ar.elements[2]*=a,ar.elements[4]*=h,ar.elements[5]*=h,ar.elements[6]*=h,ar.elements[8]*=u,ar.elements[9]*=u,ar.elements[10]*=u,t.setFromRotationMatrix(ar),s.x=r,s.y=n,s.z=o,this}makePerspective(e,t,s,i,r,n,o=2e3){const a=this.elements,h=2*r/(t-e),u=2*r/(s-i),l=(t+e)/(t-e),c=(s+i)/(s-i);let d,p;if(o===Vs)d=-(n+r)/(n-r),p=-2*n*r/(n-r);else{if(o!==Ds)throw new Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: "+o);d=-n/(n-r),p=-n*r/(n-r)}return a[0]=h,a[4]=0,a[8]=l,a[12]=0,a[1]=0,a[5]=u,a[9]=c,a[13]=0,a[2]=0,a[6]=0,a[10]=d,a[14]=p,a[3]=0,a[7]=0,a[11]=-1,a[15]=0,this}makeOrthographic(e,t,s,i,r,n,o=2e3){const a=this.elements,h=1/(t-e),u=1/(s-i),l=1/(n-r),c=(t+e)*h,d=(s+i)*u;let p,m;if(o===Vs)p=(n+r)*l,m=-2*l;else{if(o!==Ds)throw new Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: "+o);p=r*l,m=-1*l}return a[0]=2*h,a[4]=0,a[8]=0,a[12]=-c,a[1]=0,a[5]=2*u,a[9]=0,a[13]=-d,a[2]=0,a[6]=0,a[10]=m,a[14]=-p,a[3]=0,a[7]=0,a[11]=0,a[15]=1,this}equals(e){const t=this.elements,s=e.elements;for(let e=0;e<16;e++)if(t[e]!==s[e])return!1;return!0}fromArray(e,t=0){for(let s=0;s<16;s++)this.elements[s]=e[s+t];return this}toArray(e=[],t=0){const s=this.elements;return e[t]=s[0],e[t+1]=s[1],e[t+2]=s[2],e[t+3]=s[3],e[t+4]=s[4],e[t+5]=s[5],e[t+6]=s[6],e[t+7]=s[7],e[t+8]=s[8],e[t+9]=s[9],e[t+10]=s[10],e[t+11]=s[11],e[t+12]=s[12],e[t+13]=s[13],e[t+14]=s[14],e[t+15]=s[15],e}}const or=new Ri,ar=new nr,hr=new Ri(0,0,0),ur=new Ri(1,1,1),lr=new Ri,cr=new Ri,dr=new Ri,pr=new nr,mr=new Ci;class gr{constructor(e=0,t=0,s=0,i=gr.DEFAULT_ORDER){this.isEuler=!0,this._x=e,this._y=t,this._z=s,this._order=i}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get order(){return this._order}set order(e){this._order=e,this._onChangeCallback()}set(e,t,s,i=this._order){return this._x=e,this._y=t,this._z=s,this._order=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(e){return this._x=e._x,this._y=e._y,this._z=e._z,this._order=e._order,this._onChangeCallback(),this}setFromRotationMatrix(e,t=this._order,s=!0){const i=e.elements,r=i[0],n=i[4],o=i[8],a=i[1],h=i[5],u=i[9],l=i[2],c=i[6],d=i[10];switch(t){case"XYZ":this._y=Math.asin($s(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-u,d),this._z=Math.atan2(-n,r)):(this._x=Math.atan2(c,h),this._z=0);break;case"YXZ":this._x=Math.asin(-$s(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(o,d),this._z=Math.atan2(a,h)):(this._y=Math.atan2(-l,r),this._z=0);break;case"ZXY":this._x=Math.asin($s(c,-1,1)),Math.abs(c)<.9999999?(this._y=Math.atan2(-l,d),this._z=Math.atan2(-n,h)):(this._y=0,this._z=Math.atan2(a,r));break;case"ZYX":this._y=Math.asin(-$s(l,-1,1)),Math.abs(l)<.9999999?(this._x=Math.atan2(c,d),this._z=Math.atan2(a,r)):(this._x=0,this._z=Math.atan2(-n,h));break;case"YZX":this._z=Math.asin($s(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(-u,h),this._y=Math.atan2(-l,r)):(this._x=0,this._y=Math.atan2(o,d));break;case"XZY":this._z=Math.asin(-$s(n,-1,1)),Math.abs(n)<.9999999?(this._x=Math.atan2(c,h),this._y=Math.atan2(o,r)):(this._x=Math.atan2(-u,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+t)}return this._order=t,!0===s&&this._onChangeCallback(),this}setFromQuaternion(e,t,s){return pr.makeRotationFromQuaternion(e),this.setFromRotationMatrix(pr,t,s)}setFromVector3(e,t=this._order){return this.set(e.x,e.y,e.z,t)}reorder(e){return mr.setFromEuler(this),this.setFromQuaternion(mr,e)}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._order===this._order}fromArray(e){return this._x=e[0],this._y=e[1],this._z=e[2],void 0!==e[3]&&(this._order=e[3]),this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._order,e}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}gr.DEFAULT_ORDER="XYZ";class fr{constructor(){this.mask=1}set(e){this.mask=(1<>>0}enable(e){this.mask|=1<1){for(let e=0;e1){for(let e=0;e0&&(i.userData=this.userData),i.layers=this.layers.mask,i.matrix=this.matrix.toArray(),i.up=this.up.toArray(),!1===this.matrixAutoUpdate&&(i.matrixAutoUpdate=!1),this.isInstancedMesh&&(i.type="InstancedMesh",i.count=this.count,i.instanceMatrix=this.instanceMatrix.toJSON(),null!==this.instanceColor&&(i.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(i.type="BatchedMesh",i.perObjectFrustumCulled=this.perObjectFrustumCulled,i.sortObjects=this.sortObjects,i.drawRanges=this._drawRanges,i.reservedRanges=this._reservedRanges,i.visibility=this._visibility,i.active=this._active,i.bounds=this._bounds.map((e=>({boxInitialized:e.boxInitialized,boxMin:e.box.min.toArray(),boxMax:e.box.max.toArray(),sphereInitialized:e.sphereInitialized,sphereRadius:e.sphere.radius,sphereCenter:e.sphere.center.toArray()}))),i.maxInstanceCount=this._maxInstanceCount,i.maxVertexCount=this._maxVertexCount,i.maxIndexCount=this._maxIndexCount,i.geometryInitialized=this._geometryInitialized,i.geometryCount=this._geometryCount,i.matricesTexture=this._matricesTexture.toJSON(e),null!==this._colorsTexture&&(i.colorsTexture=this._colorsTexture.toJSON(e)),null!==this.boundingSphere&&(i.boundingSphere={center:i.boundingSphere.center.toArray(),radius:i.boundingSphere.radius}),null!==this.boundingBox&&(i.boundingBox={min:i.boundingBox.min.toArray(),max:i.boundingBox.max.toArray()})),this.isScene)this.background&&(this.background.isColor?i.background=this.background.toJSON():this.background.isTexture&&(i.background=this.background.toJSON(e).uuid)),this.environment&&this.environment.isTexture&&!0!==this.environment.isRenderTargetTexture&&(i.environment=this.environment.toJSON(e).uuid);else if(this.isMesh||this.isLine||this.isPoints){i.geometry=r(e.geometries,this.geometry);const t=this.geometry.parameters;if(void 0!==t&&void 0!==t.shapes){const s=t.shapes;if(Array.isArray(s))for(let t=0,i=s.length;t0){i.children=[];for(let t=0;t0){i.animations=[];for(let t=0;t0&&(s.geometries=t),i.length>0&&(s.materials=i),r.length>0&&(s.textures=r),o.length>0&&(s.images=o),a.length>0&&(s.shapes=a),h.length>0&&(s.skeletons=h),u.length>0&&(s.animations=u),l.length>0&&(s.nodes=l)}return s.object=i,s;function n(e){const t=[];for(const s in e){const i=e[s];delete i.metadata,t.push(i)}return t}}clone(e){return(new this.constructor).copy(this,e)}copy(e,t=!0){if(this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.rotation.order=e.rotation.order,this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldAutoUpdate=e.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=e.matrixWorldNeedsUpdate,this.layers.mask=e.layers.mask,this.visible=e.visible,this.castShadow=e.castShadow,this.receiveShadow=e.receiveShadow,this.frustumCulled=e.frustumCulled,this.renderOrder=e.renderOrder,this.animations=e.animations.slice(),this.userData=JSON.parse(JSON.stringify(e.userData)),!0===t)for(let t=0;t0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(e,t,s,i,r){Pr.subVectors(i,t),Fr.subVectors(s,t),zr.subVectors(e,t);const n=Pr.dot(Pr),o=Pr.dot(Fr),a=Pr.dot(zr),h=Fr.dot(Fr),u=Fr.dot(zr),l=n*h-o*o;if(0===l)return r.set(0,0,0),null;const c=1/l,d=(h*a-o*u)*c,p=(n*u-o*a)*c;return r.set(1-d-p,p,d)}static containsPoint(e,t,s,i){return null!==this.getBarycoord(e,t,s,i,Ur)&&(Ur.x>=0&&Ur.y>=0&&Ur.x+Ur.y<=1)}static getInterpolation(e,t,s,i,r,n,o,a){return null===this.getBarycoord(e,t,s,i,Ur)?(a.x=0,a.y=0,"z"in a&&(a.z=0),"w"in a&&(a.w=0),null):(a.setScalar(0),a.addScaledVector(r,Ur.x),a.addScaledVector(n,Ur.y),a.addScaledVector(o,Ur.z),a)}static getInterpolatedAttribute(e,t,s,i,r,n){return Wr.setScalar(0),jr.setScalar(0),Hr.setScalar(0),Wr.fromBufferAttribute(e,t),jr.fromBufferAttribute(e,s),Hr.fromBufferAttribute(e,i),n.setScalar(0),n.addScaledVector(Wr,r.x),n.addScaledVector(jr,r.y),n.addScaledVector(Hr,r.z),n}static isFrontFacing(e,t,s,i){return Pr.subVectors(s,t),Fr.subVectors(e,t),Pr.cross(Fr).dot(i)<0}set(e,t,s){return this.a.copy(e),this.b.copy(t),this.c.copy(s),this}setFromPointsAndIndices(e,t,s,i){return this.a.copy(e[t]),this.b.copy(e[s]),this.c.copy(e[i]),this}setFromAttributeAndIndices(e,t,s,i){return this.a.fromBufferAttribute(e,t),this.b.fromBufferAttribute(e,s),this.c.fromBufferAttribute(e,i),this}clone(){return(new this.constructor).copy(this)}copy(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this}getArea(){return Pr.subVectors(this.c,this.b),Fr.subVectors(this.a,this.b),.5*Pr.cross(Fr).length()}getMidpoint(e){return e.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(e){return qr.getNormal(this.a,this.b,this.c,e)}getPlane(e){return e.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(e,t){return qr.getBarycoord(e,this.a,this.b,this.c,t)}getInterpolation(e,t,s,i,r){return qr.getInterpolation(e,this.a,this.b,this.c,t,s,i,r)}containsPoint(e){return qr.containsPoint(e,this.a,this.b,this.c)}isFrontFacing(e){return qr.isFrontFacing(this.a,this.b,this.c,e)}intersectsBox(e){return e.intersectsTriangle(this)}closestPointToPoint(e,t){const s=this.a,i=this.b,r=this.c;let n,o;Or.subVectors(i,s),Lr.subVectors(r,s),Dr.subVectors(e,s);const a=Or.dot(Dr),h=Lr.dot(Dr);if(a<=0&&h<=0)return t.copy(s);kr.subVectors(e,i);const u=Or.dot(kr),l=Lr.dot(kr);if(u>=0&&l<=u)return t.copy(i);const c=a*l-u*h;if(c<=0&&a>=0&&u<=0)return n=a/(a-u),t.copy(s).addScaledVector(Or,n);Gr.subVectors(e,r);const d=Or.dot(Gr),p=Lr.dot(Gr);if(p>=0&&d<=p)return t.copy(r);const m=d*h-a*p;if(m<=0&&h>=0&&p<=0)return o=h/(h-p),t.copy(s).addScaledVector(Lr,o);const g=u*p-d*l;if(g<=0&&l-u>=0&&d-p>=0)return Vr.subVectors(r,i),o=(l-u)/(l-u+(d-p)),t.copy(i).addScaledVector(Vr,o);const f=1/(g+m+c);return n=m*f,o=c*f,t.copy(s).addScaledVector(Or,n).addScaledVector(Lr,o)}equals(e){return e.a.equals(this.a)&&e.b.equals(this.b)&&e.c.equals(this.c)}}const $r={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},Xr={h:0,s:0,l:0},Yr={h:0,s:0,l:0};function Zr(e,t,s){return s<0&&(s+=1),s>1&&(s-=1),s<1/6?e+6*(t-e)*s:s<.5?t:s<2/3?e+6*(t-e)*(2/3-s):e}class Jr{constructor(e,t,s){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(e,t,s)}set(e,t,s){if(void 0===t&&void 0===s){const t=e;t&&t.isColor?this.copy(t):"number"==typeof t?this.setHex(t):"string"==typeof t&&this.setStyle(t)}else this.setRGB(e,t,s);return this}setScalar(e){return this.r=e,this.g=e,this.b=e,this}setHex(e,t=Zt){return e=Math.floor(e),this.r=(e>>16&255)/255,this.g=(e>>8&255)/255,this.b=(255&e)/255,ci.toWorkingColorSpace(this,t),this}setRGB(e,t,s,i=ci.workingColorSpace){return this.r=e,this.g=t,this.b=s,ci.toWorkingColorSpace(this,i),this}setHSL(e,t,s,i=ci.workingColorSpace){if(e=Xs(e,1),t=$s(t,0,1),s=$s(s,0,1),0===t)this.r=this.g=this.b=s;else{const i=s<=.5?s*(1+t):s+t-s*t,r=2*s-i;this.r=Zr(r,i,e+1/3),this.g=Zr(r,i,e),this.b=Zr(r,i,e-1/3)}return ci.toWorkingColorSpace(this,i),this}setStyle(e,t=Zt){function s(t){void 0!==t&&parseFloat(t)<1&&console.warn("THREE.Color: Alpha component of "+e+" will be ignored.")}let i;if(i=/^(\w+)\(([^\)]*)\)/.exec(e)){let r;const n=i[1],o=i[2];switch(n){case"rgb":case"rgba":if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return s(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,t);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return s(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,t);break;case"hsl":case"hsla":if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return s(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,t);break;default:console.warn("THREE.Color: Unknown color model "+e)}}else if(i=/^\#([A-Fa-f\d]+)$/.exec(e)){const s=i[1],r=s.length;if(3===r)return this.setRGB(parseInt(s.charAt(0),16)/15,parseInt(s.charAt(1),16)/15,parseInt(s.charAt(2),16)/15,t);if(6===r)return this.setHex(parseInt(s,16),t);console.warn("THREE.Color: Invalid hex color "+e)}else if(e&&e.length>0)return this.setColorName(e,t);return this}setColorName(e,t=Zt){const s=$r[e.toLowerCase()];return void 0!==s?this.setHex(s,t):console.warn("THREE.Color: Unknown color "+e),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(e){return this.r=e.r,this.g=e.g,this.b=e.b,this}copySRGBToLinear(e){return this.r=di(e.r),this.g=di(e.g),this.b=di(e.b),this}copyLinearToSRGB(e){return this.r=pi(e.r),this.g=pi(e.g),this.b=pi(e.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(e=Zt){return ci.fromWorkingColorSpace(Kr.copy(this),e),65536*Math.round($s(255*Kr.r,0,255))+256*Math.round($s(255*Kr.g,0,255))+Math.round($s(255*Kr.b,0,255))}getHexString(e=Zt){return("000000"+this.getHex(e).toString(16)).slice(-6)}getHSL(e,t=ci.workingColorSpace){ci.fromWorkingColorSpace(Kr.copy(this),t);const s=Kr.r,i=Kr.g,r=Kr.b,n=Math.max(s,i,r),o=Math.min(s,i,r);let a,h;const u=(o+n)/2;if(o===n)a=0,h=0;else{const e=n-o;switch(h=u<=.5?e/(n+o):e/(2-n-o),n){case s:a=(i-r)/e+(i0!=e>0&&this.version++,this._alphaTest=e}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(e){if(void 0!==e)for(const t in e){const s=e[t];if(void 0===s){console.warn(`THREE.Material: parameter '${t}' has value of undefined.`);continue}const i=this[t];void 0!==i?i&&i.isColor?i.set(s):i&&i.isVector3&&s&&s.isVector3?i.copy(s):this[t]=s:console.warn(`THREE.Material: '${t}' is not a property of THREE.${this.type}.`)}}toJSON(e){const t=void 0===e||"string"==typeof e;t&&(e={textures:{},images:{}});const s={metadata:{version:4.6,type:"Material",generator:"Material.toJSON"}};function i(e){const t=[];for(const s in e){const i=e[s];delete i.metadata,t.push(i)}return t}if(s.uuid=this.uuid,s.type=this.type,""!==this.name&&(s.name=this.name),this.color&&this.color.isColor&&(s.color=this.color.getHex()),void 0!==this.roughness&&(s.roughness=this.roughness),void 0!==this.metalness&&(s.metalness=this.metalness),void 0!==this.sheen&&(s.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(s.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(s.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(s.emissive=this.emissive.getHex()),void 0!==this.emissiveIntensity&&1!==this.emissiveIntensity&&(s.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(s.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(s.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(s.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(s.shininess=this.shininess),void 0!==this.clearcoat&&(s.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(s.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(s.clearcoatMap=this.clearcoatMap.toJSON(e).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(s.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(e).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(s.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(e).uuid,s.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.dispersion&&(s.dispersion=this.dispersion),void 0!==this.iridescence&&(s.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(s.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(s.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(s.iridescenceMap=this.iridescenceMap.toJSON(e).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(s.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(e).uuid),void 0!==this.anisotropy&&(s.anisotropy=this.anisotropy),void 0!==this.anisotropyRotation&&(s.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(s.anisotropyMap=this.anisotropyMap.toJSON(e).uuid),this.map&&this.map.isTexture&&(s.map=this.map.toJSON(e).uuid),this.matcap&&this.matcap.isTexture&&(s.matcap=this.matcap.toJSON(e).uuid),this.alphaMap&&this.alphaMap.isTexture&&(s.alphaMap=this.alphaMap.toJSON(e).uuid),this.lightMap&&this.lightMap.isTexture&&(s.lightMap=this.lightMap.toJSON(e).uuid,s.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(s.aoMap=this.aoMap.toJSON(e).uuid,s.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(s.bumpMap=this.bumpMap.toJSON(e).uuid,s.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(s.normalMap=this.normalMap.toJSON(e).uuid,s.normalMapType=this.normalMapType,s.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(s.displacementMap=this.displacementMap.toJSON(e).uuid,s.displacementScale=this.displacementScale,s.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(s.roughnessMap=this.roughnessMap.toJSON(e).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(s.metalnessMap=this.metalnessMap.toJSON(e).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(s.emissiveMap=this.emissiveMap.toJSON(e).uuid),this.specularMap&&this.specularMap.isTexture&&(s.specularMap=this.specularMap.toJSON(e).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(s.specularIntensityMap=this.specularIntensityMap.toJSON(e).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(s.specularColorMap=this.specularColorMap.toJSON(e).uuid),this.envMap&&this.envMap.isTexture&&(s.envMap=this.envMap.toJSON(e).uuid,void 0!==this.combine&&(s.combine=this.combine)),void 0!==this.envMapRotation&&(s.envMapRotation=this.envMapRotation.toArray()),void 0!==this.envMapIntensity&&(s.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(s.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(s.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(s.gradientMap=this.gradientMap.toJSON(e).uuid),void 0!==this.transmission&&(s.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(s.transmissionMap=this.transmissionMap.toJSON(e).uuid),void 0!==this.thickness&&(s.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(s.thicknessMap=this.thicknessMap.toJSON(e).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(s.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(s.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(s.size=this.size),null!==this.shadowSide&&(s.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(s.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(s.blending=this.blending),this.side!==c&&(s.side=this.side),!0===this.vertexColors&&(s.vertexColors=!0),this.opacity<1&&(s.opacity=this.opacity),!0===this.transparent&&(s.transparent=!0),this.blendSrc!==R&&(s.blendSrc=this.blendSrc),this.blendDst!==E&&(s.blendDst=this.blendDst),this.blendEquation!==v&&(s.blendEquation=this.blendEquation),null!==this.blendSrcAlpha&&(s.blendSrcAlpha=this.blendSrcAlpha),null!==this.blendDstAlpha&&(s.blendDstAlpha=this.blendDstAlpha),null!==this.blendEquationAlpha&&(s.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&&this.blendColor.isColor&&(s.blendColor=this.blendColor.getHex()),0!==this.blendAlpha&&(s.blendAlpha=this.blendAlpha),3!==this.depthFunc&&(s.depthFunc=this.depthFunc),!1===this.depthTest&&(s.depthTest=this.depthTest),!1===this.depthWrite&&(s.depthWrite=this.depthWrite),!1===this.colorWrite&&(s.colorWrite=this.colorWrite),255!==this.stencilWriteMask&&(s.stencilWriteMask=this.stencilWriteMask),this.stencilFunc!==bs&&(s.stencilFunc=this.stencilFunc),0!==this.stencilRef&&(s.stencilRef=this.stencilRef),255!==this.stencilFuncMask&&(s.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==ns&&(s.stencilFail=this.stencilFail),this.stencilZFail!==ns&&(s.stencilZFail=this.stencilZFail),this.stencilZPass!==ns&&(s.stencilZPass=this.stencilZPass),!0===this.stencilWrite&&(s.stencilWrite=this.stencilWrite),void 0!==this.rotation&&0!==this.rotation&&(s.rotation=this.rotation),!0===this.polygonOffset&&(s.polygonOffset=!0),0!==this.polygonOffsetFactor&&(s.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(s.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(s.linewidth=this.linewidth),void 0!==this.dashSize&&(s.dashSize=this.dashSize),void 0!==this.gapSize&&(s.gapSize=this.gapSize),void 0!==this.scale&&(s.scale=this.scale),!0===this.dithering&&(s.dithering=!0),this.alphaTest>0&&(s.alphaTest=this.alphaTest),!0===this.alphaHash&&(s.alphaHash=!0),!0===this.alphaToCoverage&&(s.alphaToCoverage=!0),!0===this.premultipliedAlpha&&(s.premultipliedAlpha=!0),!0===this.forceSinglePass&&(s.forceSinglePass=!0),!0===this.wireframe&&(s.wireframe=!0),this.wireframeLinewidth>1&&(s.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(s.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(s.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(s.flatShading=!0),!1===this.visible&&(s.visible=!1),!1===this.toneMapped&&(s.toneMapped=!1),!1===this.fog&&(s.fog=!1),Object.keys(this.userData).length>0&&(s.userData=this.userData),t){const t=i(e.textures),r=i(e.images);t.length>0&&(s.textures=t),r.length>0&&(s.images=r)}return s}clone(){return(new this.constructor).copy(this)}copy(e){this.name=e.name,this.blending=e.blending,this.side=e.side,this.vertexColors=e.vertexColors,this.opacity=e.opacity,this.transparent=e.transparent,this.blendSrc=e.blendSrc,this.blendDst=e.blendDst,this.blendEquation=e.blendEquation,this.blendSrcAlpha=e.blendSrcAlpha,this.blendDstAlpha=e.blendDstAlpha,this.blendEquationAlpha=e.blendEquationAlpha,this.blendColor.copy(e.blendColor),this.blendAlpha=e.blendAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.stencilWriteMask=e.stencilWriteMask,this.stencilFunc=e.stencilFunc,this.stencilRef=e.stencilRef,this.stencilFuncMask=e.stencilFuncMask,this.stencilFail=e.stencilFail,this.stencilZFail=e.stencilZFail,this.stencilZPass=e.stencilZPass,this.stencilWrite=e.stencilWrite;const t=e.clippingPlanes;let s=null;if(null!==t){const e=t.length;s=new Array(e);for(let i=0;i!==e;++i)s[i]=t[i].clone()}return this.clippingPlanes=s,this.clipIntersection=e.clipIntersection,this.clipShadows=e.clipShadows,this.shadowSide=e.shadowSide,this.colorWrite=e.colorWrite,this.precision=e.precision,this.polygonOffset=e.polygonOffset,this.polygonOffsetFactor=e.polygonOffsetFactor,this.polygonOffsetUnits=e.polygonOffsetUnits,this.dithering=e.dithering,this.alphaTest=e.alphaTest,this.alphaHash=e.alphaHash,this.alphaToCoverage=e.alphaToCoverage,this.premultipliedAlpha=e.premultipliedAlpha,this.forceSinglePass=e.forceSinglePass,this.visible=e.visible,this.toneMapped=e.toneMapped,this.userData=JSON.parse(JSON.stringify(e.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(e){!0===e&&this.version++}onBuild(){console.warn("Material: onBuild() has been removed.")}}class tn extends en{constructor(e){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new Jr(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.envMapRotation=new gr,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(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.fog=e.fog,this}}const sn=rn();function rn(){const e=new ArrayBuffer(4),t=new Float32Array(e),s=new Uint32Array(e),i=new Uint32Array(512),r=new Uint32Array(512);for(let e=0;e<256;++e){const t=e-127;t<-27?(i[e]=0,i[256|e]=32768,r[e]=24,r[256|e]=24):t<-14?(i[e]=1024>>-t-14,i[256|e]=1024>>-t-14|32768,r[e]=-t-1,r[256|e]=-t-1):t<=15?(i[e]=t+15<<10,i[256|e]=t+15<<10|32768,r[e]=13,r[256|e]=13):t<128?(i[e]=31744,i[256|e]=64512,r[e]=24,r[256|e]=24):(i[e]=31744,i[256|e]=64512,r[e]=13,r[256|e]=13)}const n=new Uint32Array(2048),o=new Uint32Array(64),a=new Uint32Array(64);for(let e=1;e<1024;++e){let t=e<<13,s=0;for(;0==(8388608&t);)t<<=1,s-=8388608;t&=-8388609,s+=947912704,n[e]=t|s}for(let e=1024;e<2048;++e)n[e]=939524096+(e-1024<<13);for(let e=1;e<31;++e)o[e]=e<<23;o[31]=1199570944,o[32]=2147483648;for(let e=33;e<63;++e)o[e]=2147483648+(e-32<<23);o[63]=3347054592;for(let e=1;e<64;++e)32!==e&&(a[e]=1024);return{floatView:t,uint32View:s,baseTable:i,shiftTable:r,mantissaTable:n,exponentTable:o,offsetTable:a}}function nn(e){Math.abs(e)>65504&&console.warn("THREE.DataUtils.toHalfFloat(): Value out of range."),e=$s(e,-65504,65504),sn.floatView[0]=e;const t=sn.uint32View[0],s=t>>23&511;return sn.baseTable[s]+((8388607&t)>>sn.shiftTable[s])}function on(e){const t=e>>10;return sn.uint32View[0]=sn.mantissaTable[sn.offsetTable[t]+(1023&e)]+sn.exponentTable[t],sn.floatView[0]}const an={toHalfFloat:nn,fromHalfFloat:on},hn=new Ri,un=new Qs;class ln{constructor(e,t,s=!1){if(Array.isArray(e))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=e,this.itemSize=t,this.count=void 0!==e?e.length/t:0,this.normalized=s,this.usage=Cs,this.updateRanges=[],this.gpuType=Ie,this.version=0}onUploadCallback(){}set needsUpdate(e){!0===e&&this.version++}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.name=e.name,this.array=new e.array.constructor(e.array),this.itemSize=e.itemSize,this.count=e.count,this.normalized=e.normalized,this.usage=e.usage,this.gpuType=e.gpuType,this}copyAt(e,t,s){e*=this.itemSize,s*=t.itemSize;for(let i=0,r=this.itemSize;i=0;--t)if(e[t]>=65535)return!0;return!1}(e)?yn:gn)(e,1):this.index=e,this}getAttribute(e){return this.attributes[e]}setAttribute(e,t){return this.attributes[e]=t,this}deleteAttribute(e){return delete this.attributes[e],this}hasAttribute(e){return void 0!==this.attributes[e]}addGroup(e,t,s=0){this.groups.push({start:e,count:t,materialIndex:s})}clearGroups(){this.groups=[]}setDrawRange(e,t){this.drawRange.start=e,this.drawRange.count=t}applyMatrix4(e){const t=this.attributes.position;void 0!==t&&(t.applyMatrix4(e),t.needsUpdate=!0);const s=this.attributes.normal;if(void 0!==s){const t=(new ei).getNormalMatrix(e);s.applyNormalMatrix(t),s.needsUpdate=!0}const i=this.attributes.tangent;return void 0!==i&&(i.transformDirection(e),i.needsUpdate=!0),null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this}applyQuaternion(e){return Tn.makeRotationFromQuaternion(e),this.applyMatrix4(Tn),this}rotateX(e){return Tn.makeRotationX(e),this.applyMatrix4(Tn),this}rotateY(e){return Tn.makeRotationY(e),this.applyMatrix4(Tn),this}rotateZ(e){return Tn.makeRotationZ(e),this.applyMatrix4(Tn),this}translate(e,t,s){return Tn.makeTranslation(e,t,s),this.applyMatrix4(Tn),this}scale(e,t,s){return Tn.makeScale(e,t,s),this.applyMatrix4(Tn),this}lookAt(e){return _n.lookAt(e),_n.updateMatrix(),this.applyMatrix4(_n.matrix),this}center(){return this.computeBoundingBox(),this.boundingBox.getCenter(wn).negate(),this.translate(wn.x,wn.y,wn.z),this}setFromPoints(e){const t=[];for(let s=0,i=e.length;s0&&(e.userData=this.userData),void 0!==this.parameters){const t=this.parameters;for(const s in t)void 0!==t[s]&&(e[s]=t[s]);return e}e.data={attributes:{}};const t=this.index;null!==t&&(e.data.index={type:t.array.constructor.name,array:Array.prototype.slice.call(t.array)});const s=this.attributes;for(const t in s){const i=s[t];e.data.attributes[t]=i.toJSON(e.data)}const i={};let r=!1;for(const t in this.morphAttributes){const s=this.morphAttributes[t],n=[];for(let t=0,i=s.length;t0&&(i[t]=n,r=!0)}r&&(e.data.morphAttributes=i,e.data.morphTargetsRelative=this.morphTargetsRelative);const n=this.groups;n.length>0&&(e.data.groups=JSON.parse(JSON.stringify(n)));const o=this.boundingSphere;return null!==o&&(e.data.boundingSphere={center:o.center.toArray(),radius:o.radius}),e}clone(){return(new this.constructor).copy(this)}copy(e){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const t={};this.name=e.name;const s=e.index;null!==s&&this.setIndex(s.clone(t));const i=e.attributes;for(const e in i){const s=i[e];this.setAttribute(e,s.clone(t))}const r=e.morphAttributes;for(const e in r){const s=[],i=r[e];for(let e=0,r=i.length;e0){const s=e[t[0]];if(void 0!==s){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=s.length;e(e.far-e.near)**2)return}Cn.copy(r).invert(),Rn.copy(e.ray).applyMatrix4(Cn),null!==s.boundingBox&&!1===Rn.intersectsBox(s.boundingBox)||this._computeIntersections(e,t,Rn)}}_computeIntersections(e,t,s){let i;const r=this.geometry,n=this.material,o=r.index,a=r.attributes.position,h=r.attributes.uv,u=r.attributes.uv1,l=r.attributes.normal,c=r.groups,d=r.drawRange;if(null!==o)if(Array.isArray(n))for(let r=0,a=c.length;rs.far?null:{distance:u,point:Ln.clone(),object:e}}(e,t,s,i,In,Pn,Fn,On);if(l){const e=new Ri;qr.getBarycoord(On,In,Pn,Fn,e),r&&(l.uv=qr.getInterpolatedAttribute(r,a,h,u,e,new Qs)),n&&(l.uv1=qr.getInterpolatedAttribute(n,a,h,u,e,new Qs)),o&&(l.normal=qr.getInterpolatedAttribute(o,a,h,u,e,new Ri),l.normal.dot(i.direction)>0&&l.normal.multiplyScalar(-1));const t={a:a,b:h,c:u,normal:new Ri,materialIndex:0};qr.getNormal(In,Pn,Fn,t.normal),l.face=t,l.barycoord=e}return l}class kn extends An{constructor(e=1,t=1,s=1,i=1,r=1,n=1){super(),this.type="BoxGeometry",this.parameters={width:e,height:t,depth:s,widthSegments:i,heightSegments:r,depthSegments:n};const o=this;i=Math.floor(i),r=Math.floor(r),n=Math.floor(n);const a=[],h=[],u=[],l=[];let c=0,d=0;function p(e,t,s,i,r,n,p,m,g,f,y){const x=n/g,b=p/f,v=n/2,T=p/2,_=m/2,w=g+1,S=f+1;let M=0,N=0;const A=new Ri;for(let n=0;n0?1:-1,u.push(A.x,A.y,A.z),l.push(a/g),l.push(1-n/f),M+=1}}for(let e=0;e0&&(t.defines=this.defines),t.vertexShader=this.vertexShader,t.fragmentShader=this.fragmentShader,t.lights=this.lights,t.clipping=this.clipping;const s={};for(const e in this.extensions)!0===this.extensions[e]&&(s[e]=!0);return Object.keys(s).length>0&&(t.extensions=s),t}}class jn extends Ir{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new nr,this.projectionMatrix=new nr,this.projectionMatrixInverse=new nr,this.coordinateSystem=Vs}copy(e,t){return super.copy(e,t),this.matrixWorldInverse.copy(e.matrixWorldInverse),this.projectionMatrix.copy(e.projectionMatrix),this.projectionMatrixInverse.copy(e.projectionMatrixInverse),this.coordinateSystem=e.coordinateSystem,this}getWorldDirection(e){return super.getWorldDirection(e).negate()}updateMatrixWorld(e){super.updateMatrixWorld(e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(e,t){super.updateWorldMatrix(e,t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}const Hn=new Ri,qn=new Qs,$n=new Qs;class Xn extends jn{constructor(e=50,t=1,s=.1,i=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=e,this.zoom=1,this.near=s,this.far=i,this.focus=10,this.aspect=t,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(e,t){return super.copy(e,t),this.fov=e.fov,this.zoom=e.zoom,this.near=e.near,this.far=e.far,this.focus=e.focus,this.aspect=e.aspect,this.view=null===e.view?null:Object.assign({},e.view),this.filmGauge=e.filmGauge,this.filmOffset=e.filmOffset,this}setFocalLength(e){const t=.5*this.getFilmHeight()/e;this.fov=2*Hs*Math.atan(t),this.updateProjectionMatrix()}getFocalLength(){const e=Math.tan(.5*js*this.fov);return.5*this.getFilmHeight()/e}getEffectiveFOV(){return 2*Hs*Math.atan(Math.tan(.5*js*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}getViewBounds(e,t,s){Hn.set(-1,-1,.5).applyMatrix4(this.projectionMatrixInverse),t.set(Hn.x,Hn.y).multiplyScalar(-e/Hn.z),Hn.set(1,1,.5).applyMatrix4(this.projectionMatrixInverse),s.set(Hn.x,Hn.y).multiplyScalar(-e/Hn.z)}getViewSize(e,t){return this.getViewBounds(e,qn,$n),t.subVectors($n,qn)}setViewOffset(e,t,s,i,r,n){this.aspect=e/t,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=e,this.view.fullHeight=t,this.view.offsetX=s,this.view.offsetY=i,this.view.width=r,this.view.height=n,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const e=this.near;let t=e*Math.tan(.5*js*this.fov)/this.zoom,s=2*t,i=this.aspect*s,r=-.5*i;const n=this.view;if(null!==this.view&&this.view.enabled){const e=n.fullWidth,o=n.fullHeight;r+=n.offsetX*i/e,t-=n.offsetY*s/o,i*=n.width/e,s*=n.height/o}const o=this.filmOffset;0!==o&&(r+=e*o/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,t,t-s,e,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(e){const t=super.toJSON(e);return t.object.fov=this.fov,t.object.zoom=this.zoom,t.object.near=this.near,t.object.far=this.far,t.object.focus=this.focus,t.object.aspect=this.aspect,null!==this.view&&(t.object.view=Object.assign({},this.view)),t.object.filmGauge=this.filmGauge,t.object.filmOffset=this.filmOffset,t}}const Yn=-90;class Zn extends Ir{constructor(e,t,s){super(),this.type="CubeCamera",this.renderTarget=s,this.coordinateSystem=null,this.activeMipmapLevel=0;const i=new Xn(Yn,1,e,t);i.layers=this.layers,this.add(i);const r=new Xn(Yn,1,e,t);r.layers=this.layers,this.add(r);const n=new Xn(Yn,1,e,t);n.layers=this.layers,this.add(n);const o=new Xn(Yn,1,e,t);o.layers=this.layers,this.add(o);const a=new Xn(Yn,1,e,t);a.layers=this.layers,this.add(a);const h=new Xn(Yn,1,e,t);h.layers=this.layers,this.add(h)}updateCoordinateSystem(){const e=this.coordinateSystem,t=this.children.concat(),[s,i,r,n,o,a]=t;for(const e of t)this.remove(e);if(e===Vs)s.up.set(0,1,0),s.lookAt(1,0,0),i.up.set(0,1,0),i.lookAt(-1,0,0),r.up.set(0,0,-1),r.lookAt(0,1,0),n.up.set(0,0,1),n.lookAt(0,-1,0),o.up.set(0,1,0),o.lookAt(0,0,1),a.up.set(0,1,0),a.lookAt(0,0,-1);else{if(e!==Ds)throw new Error("THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: "+e);s.up.set(0,-1,0),s.lookAt(-1,0,0),i.up.set(0,-1,0),i.lookAt(1,0,0),r.up.set(0,0,1),r.lookAt(0,1,0),n.up.set(0,0,-1),n.lookAt(0,-1,0),o.up.set(0,-1,0),o.lookAt(0,0,1),a.up.set(0,-1,0),a.lookAt(0,0,-1)}for(const e of t)this.add(e),e.updateMatrixWorld()}update(e,t){null===this.parent&&this.updateMatrixWorld();const{renderTarget:s,activeMipmapLevel:i}=this;this.coordinateSystem!==e.coordinateSystem&&(this.coordinateSystem=e.coordinateSystem,this.updateCoordinateSystem());const[r,n,o,a,h,u]=this.children,l=e.getRenderTarget(),c=e.getActiveCubeFace(),d=e.getActiveMipmapLevel(),p=e.xr.enabled;e.xr.enabled=!1;const m=s.texture.generateMipmaps;s.texture.generateMipmaps=!1,e.setRenderTarget(s,0,i),e.render(t,r),e.setRenderTarget(s,1,i),e.render(t,n),e.setRenderTarget(s,2,i),e.render(t,o),e.setRenderTarget(s,3,i),e.render(t,a),e.setRenderTarget(s,4,i),e.render(t,h),s.texture.generateMipmaps=m,e.setRenderTarget(s,5,i),e.render(t,u),e.setRenderTarget(l,c,d),e.xr.enabled=p,s.texture.needsPMREMUpdate=!0}}class Jn extends vi{constructor(e,t,s,i,r,n,o,a,h,u){super(e=void 0!==e?e:[],t=void 0!==t?t:he,s,i,r,n,o,a,h,u),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(e){this.image=e}}class Kn extends wi{constructor(e=1,t={}){super(e,e,t),this.isWebGLCubeRenderTarget=!0;const s={width:e,height:e,depth:1},i=[s,s,s,s,s,s];this.texture=new Jn(i,t.mapping,t.wrapS,t.wrapT,t.magFilter,t.minFilter,t.format,t.type,t.anisotropy,t.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==t.generateMipmaps&&t.generateMipmaps,this.texture.minFilter=void 0!==t.minFilter?t.minFilter:Te}fromEquirectangularTexture(e,t){this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;const s={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"},i=new kn(5,5,5),r=new Wn({name:"CubemapFromEquirect",uniforms:Gn(s.uniforms),vertexShader:s.vertexShader,fragmentShader:s.fragmentShader,side:d,blending:m});r.uniforms.tEquirect.value=t;const n=new Vn(i,r),o=t.minFilter;t.minFilter===Se&&(t.minFilter=Te);return new Zn(1,10,this).update(e,n),t.minFilter=o,n.geometry.dispose(),n.material.dispose(),this}clear(e,t,s,i){const r=e.getRenderTarget();for(let r=0;r<6;r++)e.setRenderTarget(this,r),e.clear(t,s,i);e.setRenderTarget(r)}}class Qn{constructor(e,t=25e-5){this.isFogExp2=!0,this.name="",this.color=new Jr(e),this.density=t}clone(){return new Qn(this.color,this.density)}toJSON(){return{type:"FogExp2",name:this.name,color:this.color.getHex(),density:this.density}}}class eo{constructor(e,t=1,s=1e3){this.isFog=!0,this.name="",this.color=new Jr(e),this.near=t,this.far=s}clone(){return new eo(this.color,this.near,this.far)}toJSON(){return{type:"Fog",name:this.name,color:this.color.getHex(),near:this.near,far:this.far}}}class to extends Ir{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.backgroundRotation=new gr,this.environmentIntensity=1,this.environmentRotation=new gr,this.overrideMaterial=null,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(e,t){return super.copy(e,t),null!==e.background&&(this.background=e.background.clone()),null!==e.environment&&(this.environment=e.environment.clone()),null!==e.fog&&(this.fog=e.fog.clone()),this.backgroundBlurriness=e.backgroundBlurriness,this.backgroundIntensity=e.backgroundIntensity,this.backgroundRotation.copy(e.backgroundRotation),this.environmentIntensity=e.environmentIntensity,this.environmentRotation.copy(e.environmentRotation),null!==e.overrideMaterial&&(this.overrideMaterial=e.overrideMaterial.clone()),this.matrixAutoUpdate=e.matrixAutoUpdate,this}toJSON(e){const t=super.toJSON(e);return null!==this.fog&&(t.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(t.object.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(t.object.backgroundIntensity=this.backgroundIntensity),t.object.backgroundRotation=this.backgroundRotation.toArray(),1!==this.environmentIntensity&&(t.object.environmentIntensity=this.environmentIntensity),t.object.environmentRotation=this.environmentRotation.toArray(),t}}class so{constructor(e,t){this.isInterleavedBuffer=!0,this.array=e,this.stride=t,this.count=void 0!==e?e.length/t:0,this.usage=Cs,this.updateRanges=[],this.version=0,this.uuid=qs()}onUploadCallback(){}set needsUpdate(e){!0===e&&this.version++}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.array=new e.array.constructor(e.array),this.count=e.count,this.stride=e.stride,this.usage=e.usage,this}copyAt(e,t,s){e*=this.stride,s*=t.stride;for(let i=0,r=this.stride;ie.far||t.push({distance:a,point:ao.clone(),uv:qr.getInterpolation(ao,mo,go,fo,yo,xo,bo,new Qs),face:null,object:this})}copy(e,t){return super.copy(e,t),void 0!==e.center&&this.center.copy(e.center),this.material=e.material,this}}function To(e,t,s,i,r,n){lo.subVectors(e,s).addScalar(.5).multiply(i),void 0!==r?(co.x=n*lo.x-r*lo.y,co.y=r*lo.x+n*lo.y):co.copy(lo),e.copy(t),e.x+=co.x,e.y+=co.y,e.applyMatrix4(po)}const _o=new Ri,wo=new Ri;class So extends Ir{constructor(){super(),this._currentLevel=0,this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]},isLOD:{value:!0}}),this.autoUpdate=!0}copy(e){super.copy(e,!1);const t=e.levels;for(let e=0,s=t.length;e0){let s,i;for(s=1,i=t.length;s0){_o.setFromMatrixPosition(this.matrixWorld);const s=e.ray.origin.distanceTo(_o);this.getObjectForDistance(s).raycast(e,t)}}update(e){const t=this.levels;if(t.length>1){_o.setFromMatrixPosition(e.matrixWorld),wo.setFromMatrixPosition(this.matrixWorld);const s=_o.distanceTo(wo)/e.zoom;let i,r;for(t[0].object.visible=!0,i=1,r=t.length;i=e))break;t[i-1].object.visible=!1,t[i].object.visible=!0}for(this._currentLevel=i-1;i1?null:t.copy(e.start).addScaledVector(s,r)}intersectsLine(e){const t=this.distanceToPoint(e.start),s=this.distanceToPoint(e.end);return t<0&&s>0||s<0&&t>0}intersectsBox(e){return e.intersectsPlane(this)}intersectsSphere(e){return e.intersectsPlane(this)}coplanarPoint(e){return e.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(e,t){const s=t||Jo.getNormalMatrix(e),i=this.coplanarPoint(Yo).applyMatrix4(e),r=this.normal.applyMatrix3(s).normalize();return this.constant=-i.dot(r),this}translate(e){return this.constant-=e.dot(this.normal),this}equals(e){return e.normal.equals(this.normal)&&e.constant===this.constant}clone(){return(new this.constructor).copy(this)}}const Qo=new Zi,ea=new Ri;class ta{constructor(e=new Ko,t=new Ko,s=new Ko,i=new Ko,r=new Ko,n=new Ko){this.planes=[e,t,s,i,r,n]}set(e,t,s,i,r,n){const o=this.planes;return o[0].copy(e),o[1].copy(t),o[2].copy(s),o[3].copy(i),o[4].copy(r),o[5].copy(n),this}copy(e){const t=this.planes;for(let s=0;s<6;s++)t[s].copy(e.planes[s]);return this}setFromProjectionMatrix(e,t=2e3){const s=this.planes,i=e.elements,r=i[0],n=i[1],o=i[2],a=i[3],h=i[4],u=i[5],l=i[6],c=i[7],d=i[8],p=i[9],m=i[10],g=i[11],f=i[12],y=i[13],x=i[14],b=i[15];if(s[0].setComponents(a-r,c-h,g-d,b-f).normalize(),s[1].setComponents(a+r,c+h,g+d,b+f).normalize(),s[2].setComponents(a+n,c+u,g+p,b+y).normalize(),s[3].setComponents(a-n,c-u,g-p,b-y).normalize(),s[4].setComponents(a-o,c-l,g-m,b-x).normalize(),t===Vs)s[5].setComponents(a+o,c+l,g+m,b+x).normalize();else{if(t!==Ds)throw new Error("THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: "+t);s[5].setComponents(o,l,m,x).normalize()}return this}intersectsObject(e){if(void 0!==e.boundingSphere)null===e.boundingSphere&&e.computeBoundingSphere(),Qo.copy(e.boundingSphere).applyMatrix4(e.matrixWorld);else{const t=e.geometry;null===t.boundingSphere&&t.computeBoundingSphere(),Qo.copy(t.boundingSphere).applyMatrix4(e.matrixWorld)}return this.intersectsSphere(Qo)}intersectsSprite(e){return Qo.center.set(0,0,0),Qo.radius=.7071067811865476,Qo.applyMatrix4(e.matrixWorld),this.intersectsSphere(Qo)}intersectsSphere(e){const t=this.planes,s=e.center,i=-e.radius;for(let e=0;e<6;e++){if(t[e].distanceToPoint(s)0?e.max.x:e.min.x,ea.y=i.normal.y>0?e.max.y:e.min.y,ea.z=i.normal.z>0?e.max.z:e.min.z,i.distanceToPoint(ea)<0)return!1}return!0}containsPoint(e){const t=this.planes;for(let s=0;s<6;s++)if(t[s].distanceToPoint(e)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function sa(e,t){return e.z-t.z}function ia(e,t){return t.z-e.z}class ra{constructor(){this.index=0,this.pool=[],this.list=[]}push(e,t,s){const i=this.pool,r=this.list;this.index>=i.length&&i.push({start:-1,count:-1,z:-1,index:-1});const n=i[this.index];r.push(n),this.index++,n.start=e.start,n.count=e.count,n.z=t,n.index=s}reset(){this.list.length=0,this.index=0}}const na=new nr,oa=new nr,aa=new nr,ha=new Jr(1,1,1),ua=new nr,la=new ta,ca=new Ii,da=new Zi,pa=new Ri,ma=new Ri,ga=new Ri,fa=new ra,ya=new Vn,xa=[];function ba(e,t,s=0){const i=t.itemSize;if(e.isInterleavedBufferAttribute||e.array.constructor!==t.array.constructor){const r=e.count;for(let n=0;n65535?new Uint32Array(i):new Uint16Array(i);t.setIndex(new ln(e,1))}this._geometryInitialized=!0}}_validateGeometry(e){const t=this.geometry;if(Boolean(e.getIndex())!==Boolean(t.getIndex()))throw new Error('BatchedMesh: All geometries must consistently have "index".');for(const s in t.attributes){if(!e.hasAttribute(s))throw new Error(`BatchedMesh: Added geometry missing "${s}". All geometries must have consistent attributes.`);const i=e.getAttribute(s),r=t.getAttribute(s);if(i.itemSize!==r.itemSize||i.normalized!==r.normalized)throw new Error("BatchedMesh: All attributes must have a consistent itemSize and normalized value.")}}setCustomSort(e){return this.customSort=e,this}computeBoundingBox(){null===this.boundingBox&&(this.boundingBox=new Ii);const e=this.boundingBox,t=this._drawInfo;e.makeEmpty();for(let s=0,i=t.length;s=this.maxInstanceCount&&0===this._availableInstanceIds.length)throw new Error("BatchedMesh: Maximum item count reached.");const t={visible:!0,active:!0,geometryIndex:e};let s=null;this._availableInstanceIds.length>0?(s=this._availableInstanceIds.pop(),this._drawInfo[s]=t):(s=this._drawInfo.length,this._drawInfo.push(t));const i=this._matricesTexture,r=i.image.data;aa.toArray(r,16*s),i.needsUpdate=!0;const n=this._colorsTexture;return n&&(ha.toArray(n.image.data,4*s),n.needsUpdate=!0),s}addGeometry(e,t=-1,s=-1){if(this._initializeGeometry(e),this._validateGeometry(e),this._drawInfo.length>=this._maxInstanceCount)throw new Error("BatchedMesh: Maximum item count reached.");const i={vertexStart:-1,vertexCount:-1,indexStart:-1,indexCount:-1};let r=null;const n=this._reservedRanges,o=this._drawRanges,a=this._bounds;0!==this._geometryCount&&(r=n[n.length-1]),i.vertexCount=-1===t?e.getAttribute("position").count:t,i.vertexStart=null===r?0:r.vertexStart+r.vertexCount;const h=e.getIndex(),u=null!==h;if(u&&(i.indexCount=-1===s?h.count:s,i.indexStart=null===r?0:r.indexStart+r.indexCount),-1!==i.indexStart&&i.indexStart+i.indexCount>this._maxIndexCount||i.vertexStart+i.vertexCount>this._maxVertexCount)throw new Error("BatchedMesh: Reserved space request exceeds the maximum buffer size.");const l=this._geometryCount;return this._geometryCount++,n.push(i),o.push({start:u?i.indexStart:i.vertexStart,count:-1}),a.push({boxInitialized:!1,box:new Ii,sphereInitialized:!1,sphere:new Zi}),this.setGeometryAt(l,e),l}setGeometryAt(e,t){if(e>=this._geometryCount)throw new Error("BatchedMesh: Maximum geometry count reached.");this._validateGeometry(t);const s=this.geometry,i=null!==s.getIndex(),r=s.getIndex(),n=t.getIndex(),o=this._reservedRanges[e];if(i&&n.count>o.indexCount||t.attributes.position.count>o.vertexCount)throw new Error("BatchedMesh: Reserved space not large enough for provided geometry.");const a=o.vertexStart,h=o.vertexCount;for(const e in s.attributes){const i=t.getAttribute(e),r=s.getAttribute(e);ba(i,r,a);const n=i.itemSize;for(let e=i.count,t=h;e=t.length||!1===t[e].active||(t[e].active=!1,this._availableInstanceIds.push(e),this._visibilityChanged=!0),this}getBoundingBoxAt(e,t){if(e>=this._geometryCount)return null;const s=this._bounds[e],i=s.box,r=this.geometry;if(!1===s.boxInitialized){i.makeEmpty();const t=r.index,n=r.attributes.position,o=this._drawRanges[e];for(let e=o.start,s=o.start+o.count;e=this._geometryCount)return null;const s=this._bounds[e],i=s.sphere,r=this.geometry;if(!1===s.sphereInitialized){i.makeEmpty(),this.getBoundingBoxAt(e,ca),ca.getCenter(i.center);const t=r.index,n=r.attributes.position,o=this._drawRanges[e];let a=0;for(let e=o.start,s=o.start+o.count;e=s.length||!1===s[e].active||(t.toArray(r,16*e),i.needsUpdate=!0),this}getMatrixAt(e,t){const s=this._drawInfo,i=this._matricesTexture.image.data;return e>=s.length||!1===s[e].active?null:t.fromArray(i,16*e)}setColorAt(e,t){null===this._colorsTexture&&this._initColorsTexture();const s=this._colorsTexture,i=this._colorsTexture.image.data,r=this._drawInfo;return e>=r.length||!1===r[e].active||(t.toArray(i,4*e),s.needsUpdate=!0),this}getColorAt(e,t){const s=this._colorsTexture.image.data,i=this._drawInfo;return e>=i.length||!1===i[e].active?null:t.fromArray(s,4*e)}setVisibleAt(e,t){const s=this._drawInfo;return e>=s.length||!1===s[e].active||s[e].visible===t||(s[e].visible=t,this._visibilityChanged=!0),this}getVisibleAt(e){const t=this._drawInfo;return!(e>=t.length||!1===t[e].active)&&t[e].visible}setGeometryIdAt(e,t){const s=this._drawInfo;return e>=s.length||!1===s[e].active||t<0||t>=this._geometryCount?null:(s[e].geometryIndex=t,this)}getGeometryIdAt(e){const t=this._drawInfo;return e>=t.length||!1===t[e].active?-1:t[e].geometryIndex}getGeometryRangeAt(e,t={}){if(e<0||e>=this._geometryCount)return null;const s=this._drawRanges[e];return t.start=s.start,t.count=s.count,t}raycast(e,t){const s=this._drawInfo,i=this._drawRanges,r=this.matrixWorld,n=this.geometry;ya.material=this.material,ya.geometry.index=n.index,ya.geometry.attributes=n.attributes,null===ya.geometry.boundingBox&&(ya.geometry.boundingBox=new Ii),null===ya.geometry.boundingSphere&&(ya.geometry.boundingSphere=new Zi);for(let n=0,o=s.length;n({...e}))),this._reservedRanges=e._reservedRanges.map((e=>({...e}))),this._drawInfo=e._drawInfo.map((e=>({...e}))),this._bounds=e._bounds.map((e=>({boxInitialized:e.boxInitialized,box:e.box.clone(),sphereInitialized:e.sphereInitialized,sphere:e.sphere.clone()}))),this._maxInstanceCount=e._maxInstanceCount,this._maxVertexCount=e._maxVertexCount,this._maxIndexCount=e._maxIndexCount,this._geometryInitialized=e._geometryInitialized,this._geometryCount=e._geometryCount,this._multiDrawCounts=e._multiDrawCounts.slice(),this._multiDrawStarts=e._multiDrawStarts.slice(),this._matricesTexture=e._matricesTexture.clone(),this._matricesTexture.image.data=this._matricesTexture.image.data.slice(),null!==this._colorsTexture&&(this._colorsTexture=e._colorsTexture.clone(),this._colorsTexture.image.data=this._colorsTexture.image.data.slice()),this}dispose(){return this.geometry.dispose(),this._matricesTexture.dispose(),this._matricesTexture=null,this._indirectTexture.dispose(),this._indirectTexture=null,null!==this._colorsTexture&&(this._colorsTexture.dispose(),this._colorsTexture=null),this}onBeforeRender(e,t,s,i,r){if(!this._visibilityChanged&&!this.perObjectFrustumCulled&&!this.sortObjects)return;const n=i.getIndex(),o=null===n?1:n.array.BYTES_PER_ELEMENT,a=this._drawInfo,h=this._multiDrawStarts,u=this._multiDrawCounts,l=this._drawRanges,c=this.perObjectFrustumCulled,d=this._indirectTexture,p=d.image.data;c&&(ua.multiplyMatrices(s.projectionMatrix,s.matrixWorldInverse).multiply(this.matrixWorld),la.setFromProjectionMatrix(ua,e.coordinateSystem));let m=0;if(this.sortObjects){oa.copy(this.matrixWorld).invert(),pa.setFromMatrixPosition(s.matrixWorld).applyMatrix4(oa),ma.set(0,0,-1).transformDirection(s.matrixWorld).transformDirection(oa);for(let e=0,t=a.length;e0){const s=e[t[0]];if(void 0!==s){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=s.length;ei)return;Aa.applyMatrix4(e.matrixWorld);const a=t.ray.origin.distanceTo(Aa);return at.far?void 0:{distance:a,point:Ca.clone().applyMatrix4(e.matrixWorld),index:r,face:null,faceIndex:null,barycoord:null,object:e}}const Ba=new Ri,Ia=new Ri;class Pa extends Ra{constructor(e,t){super(e,t),this.isLineSegments=!0,this.type="LineSegments"}computeLineDistances(){const e=this.geometry;if(null===e.index){const t=e.attributes.position,s=[];for(let e=0,i=t.count;e0){const s=e[t[0]];if(void 0!==s){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=s.length;er.far)return;n.push({distance:h,distanceToRay:Math.sqrt(a),point:s,index:t,face:null,faceIndex:null,barycoord:null,object:o})}}class Ga extends Ir{constructor(){super(),this.isGroup=!0,this.type="Group"}}class Wa extends vi{constructor(e,t,s,i,r,n,o,a,h){super(e,t,s,i,r,n,o,a,h),this.isVideoTexture=!0,this.minFilter=void 0!==n?n:Te,this.magFilter=void 0!==r?r:Te,this.generateMipmaps=!1;const u=this;"requestVideoFrameCallback"in e&&e.requestVideoFrameCallback((function t(){u.needsUpdate=!0,e.requestVideoFrameCallback(t)}))}clone(){return new this.constructor(this.image).copy(this)}update(){const e=this.image;!1==="requestVideoFrameCallback"in e&&e.readyState>=e.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}class ja extends vi{constructor(e,t){super({width:e,height:t}),this.isFramebufferTexture=!0,this.magFilter=fe,this.minFilter=fe,this.generateMipmaps=!1,this.needsUpdate=!0}}class Ha extends vi{constructor(e,t,s,i,r,n,o,a,h,u,l,c){super(null,n,o,a,h,u,i,r,l,c),this.isCompressedTexture=!0,this.image={width:t,height:s},this.mipmaps=e,this.flipY=!1,this.generateMipmaps=!1}}class qa extends Ha{constructor(e,t,s,i,r,n){super(e,t,s,r,n),this.isCompressedArrayTexture=!0,this.image.depth=i,this.wrapR=me,this.layerUpdates=new Set}addLayerUpdate(e){this.layerUpdates.add(e)}clearLayerUpdates(){this.layerUpdates.clear()}}class $a extends Ha{constructor(e,t,s){super(void 0,e[0].width,e[0].height,t,s,he),this.isCompressedCubeTexture=!0,this.isCubeTexture=!0,this.image=e}}class Xa extends vi{constructor(e,t,s,i,r,n,o,a,h){super(e,t,s,i,r,n,o,a,h),this.isCanvasTexture=!0,this.needsUpdate=!0}}class Ya extends vi{constructor(e,t,s,i,r,n,o,a,h,u=1026){if(u!==We&&u!==je)throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");void 0===s&&u===We&&(s=Be),void 0===s&&u===je&&(s=Ue),super(null,i,r,n,o,a,u,s,h),this.isDepthTexture=!0,this.image={width:e,height:t},this.magFilter=void 0!==o?o:fe,this.minFilter=void 0!==a?a:fe,this.flipY=!1,this.generateMipmaps=!1,this.compareFunction=null}copy(e){return super.copy(e),this.compareFunction=e.compareFunction,this}toJSON(e){const t=super.toJSON(e);return null!==this.compareFunction&&(t.compareFunction=this.compareFunction),t}}class Za{constructor(){this.type="Curve",this.arcLengthDivisions=200}getPoint(){return console.warn("THREE.Curve: .getPoint() not implemented."),null}getPointAt(e,t){const s=this.getUtoTmapping(e);return this.getPoint(s,t)}getPoints(e=5){const t=[];for(let s=0;s<=e;s++)t.push(this.getPoint(s/e));return t}getSpacedPoints(e=5){const t=[];for(let s=0;s<=e;s++)t.push(this.getPointAt(s/e));return t}getLength(){const e=this.getLengths();return e[e.length-1]}getLengths(e=this.arcLengthDivisions){if(this.cacheArcLengths&&this.cacheArcLengths.length===e+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;const t=[];let s,i=this.getPoint(0),r=0;t.push(0);for(let n=1;n<=e;n++)s=this.getPoint(n/e),r+=s.distanceTo(i),t.push(r),i=s;return this.cacheArcLengths=t,t}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(e,t){const s=this.getLengths();let i=0;const r=s.length;let n;n=t||e*s[r-1];let o,a=0,h=r-1;for(;a<=h;)if(i=Math.floor(a+(h-a)/2),o=s[i]-n,o<0)a=i+1;else{if(!(o>0)){h=i;break}h=i-1}if(i=h,s[i]===n)return i/(r-1);const u=s[i];return(i+(n-u)/(s[i+1]-u))/(r-1)}getTangent(e,t){const s=1e-4;let i=e-s,r=e+s;i<0&&(i=0),r>1&&(r=1);const n=this.getPoint(i),o=this.getPoint(r),a=t||(n.isVector2?new Qs:new Ri);return a.copy(o).sub(n).normalize(),a}getTangentAt(e,t){const s=this.getUtoTmapping(e);return this.getTangent(s,t)}computeFrenetFrames(e,t){const s=new Ri,i=[],r=[],n=[],o=new Ri,a=new nr;for(let t=0;t<=e;t++){const s=t/e;i[t]=this.getTangentAt(s,new Ri)}r[0]=new Ri,n[0]=new Ri;let h=Number.MAX_VALUE;const u=Math.abs(i[0].x),l=Math.abs(i[0].y),c=Math.abs(i[0].z);u<=h&&(h=u,s.set(1,0,0)),l<=h&&(h=l,s.set(0,1,0)),c<=h&&s.set(0,0,1),o.crossVectors(i[0],s).normalize(),r[0].crossVectors(i[0],o),n[0].crossVectors(i[0],r[0]);for(let t=1;t<=e;t++){if(r[t]=r[t-1].clone(),n[t]=n[t-1].clone(),o.crossVectors(i[t-1],i[t]),o.length()>Number.EPSILON){o.normalize();const e=Math.acos($s(i[t-1].dot(i[t]),-1,1));r[t].applyMatrix4(a.makeRotationAxis(o,e))}n[t].crossVectors(i[t],r[t])}if(!0===t){let t=Math.acos($s(r[0].dot(r[e]),-1,1));t/=e,i[0].dot(o.crossVectors(r[0],r[e]))>0&&(t=-t);for(let s=1;s<=e;s++)r[s].applyMatrix4(a.makeRotationAxis(i[s],t*s)),n[s].crossVectors(i[s],r[s])}return{tangents:i,normals:r,binormals:n}}clone(){return(new this.constructor).copy(this)}copy(e){return this.arcLengthDivisions=e.arcLengthDivisions,this}toJSON(){const e={metadata:{version:4.6,type:"Curve",generator:"Curve.toJSON"}};return e.arcLengthDivisions=this.arcLengthDivisions,e.type=this.type,e}fromJSON(e){return this.arcLengthDivisions=e.arcLengthDivisions,this}}class Ja extends Za{constructor(e=0,t=0,s=1,i=1,r=0,n=2*Math.PI,o=!1,a=0){super(),this.isEllipseCurve=!0,this.type="EllipseCurve",this.aX=e,this.aY=t,this.xRadius=s,this.yRadius=i,this.aStartAngle=r,this.aEndAngle=n,this.aClockwise=o,this.aRotation=a}getPoint(e,t=new Qs){const s=t,i=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const n=Math.abs(r)i;)r-=i;r0?0:(Math.floor(Math.abs(h)/r)+1)*r:0===u&&h===r-1&&(h=r-2,u=1),this.closed||h>0?o=i[(h-1)%r]:(eh.subVectors(i[0],i[1]).add(i[0]),o=eh);const l=i[h%r],c=i[(h+1)%r];if(this.closed||h+2i.length-2?i.length-1:n+1],l=i[n>i.length-3?i.length-1:n+2];return s.set(nh(o,a.x,h.x,u.x,l.x),nh(o,a.y,h.y,u.y,l.y)),s}copy(e){super.copy(e),this.points=[];for(let t=0,s=e.points.length;t=s){const e=i[r]-s,n=this.curves[r],o=n.getLength(),a=0===o?0:1-e/o;return n.getPointAt(a,t)}r++}return null}getLength(){const e=this.getCurveLengths();return e[e.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 e=[];let t=0;for(let s=0,i=this.curves.length;s1&&!t[t.length-1].equals(t[0])&&t.push(t[0]),t}copy(e){super.copy(e),this.curves=[];for(let t=0,s=e.curves.length;t0){const e=h.getPoint(0);e.equals(this.currentPoint)||this.lineTo(e.x,e.y)}this.curves.push(h);const u=h.getPoint(1);return this.currentPoint.copy(u),this}copy(e){return super.copy(e),this.currentPoint.copy(e.currentPoint),this}toJSON(){const e=super.toJSON();return e.currentPoint=this.currentPoint.toArray(),e}fromJSON(e){return super.fromJSON(e),this.currentPoint.fromArray(e.currentPoint),this}}class xh extends An{constructor(e=[new Qs(0,-.5),new Qs(.5,0),new Qs(0,.5)],t=12,s=0,i=2*Math.PI){super(),this.type="LatheGeometry",this.parameters={points:e,segments:t,phiStart:s,phiLength:i},t=Math.floor(t),i=$s(i,0,2*Math.PI);const r=[],n=[],o=[],a=[],h=[],u=1/t,l=new Ri,c=new Qs,d=new Ri,p=new Ri,m=new Ri;let g=0,f=0;for(let t=0;t<=e.length-1;t++)switch(t){case 0:g=e[t+1].x-e[t].x,f=e[t+1].y-e[t].y,d.x=1*f,d.y=-g,d.z=0*f,m.copy(d),d.normalize(),a.push(d.x,d.y,d.z);break;case e.length-1:a.push(m.x,m.y,m.z);break;default:g=e[t+1].x-e[t].x,f=e[t+1].y-e[t].y,d.x=1*f,d.y=-g,d.z=0*f,p.copy(d),d.x+=m.x,d.y+=m.y,d.z+=m.z,d.normalize(),a.push(d.x,d.y,d.z),m.copy(p)}for(let r=0;r<=t;r++){const d=s+r*u*i,p=Math.sin(d),m=Math.cos(d);for(let s=0;s<=e.length-1;s++){l.x=e[s].x*p,l.y=e[s].y,l.z=e[s].x*m,n.push(l.x,l.y,l.z),c.x=r/t,c.y=s/(e.length-1),o.push(c.x,c.y);const i=a[3*s+0]*p,u=a[3*s+1],d=a[3*s+0]*m;h.push(i,u,d)}}for(let s=0;s0&&(u.push(r,n,a),x+=3),t>0&&(u.push(n,o,a),x+=3)}h.addGroup(f,x,0),f+=x}(),!1===n&&(e>0&&y(!0),t>0&&y(!1)),this.setIndex(u),this.setAttribute("position",new bn(l,3)),this.setAttribute("normal",new bn(c,3)),this.setAttribute("uv",new bn(d,2))}copy(e){return super.copy(e),this.parameters=Object.assign({},e.parameters),this}static fromJSON(e){return new Th(e.radiusTop,e.radiusBottom,e.height,e.radialSegments,e.heightSegments,e.openEnded,e.thetaStart,e.thetaLength)}}class _h extends Th{constructor(e=1,t=1,s=32,i=1,r=!1,n=0,o=2*Math.PI){super(0,e,t,s,i,r,n,o),this.type="ConeGeometry",this.parameters={radius:e,height:t,radialSegments:s,heightSegments:i,openEnded:r,thetaStart:n,thetaLength:o}}static fromJSON(e){return new _h(e.radius,e.height,e.radialSegments,e.heightSegments,e.openEnded,e.thetaStart,e.thetaLength)}}class wh extends An{constructor(e=[],t=[],s=1,i=0){super(),this.type="PolyhedronGeometry",this.parameters={vertices:e,indices:t,radius:s,detail:i};const r=[],n=[];function o(e,t,s,i){const r=i+1,n=[];for(let i=0;i<=r;i++){n[i]=[];const o=e.clone().lerp(s,i/r),a=t.clone().lerp(s,i/r),h=r-i;for(let e=0;e<=h;e++)n[i][e]=0===e&&i===r?o:o.clone().lerp(a,e/h)}for(let e=0;e.9&&o<.1&&(t<.2&&(n[e+0]+=1),s<.2&&(n[e+2]+=1),i<.2&&(n[e+4]+=1))}}()}(),this.setAttribute("position",new bn(r,3)),this.setAttribute("normal",new bn(r.slice(),3)),this.setAttribute("uv",new bn(n,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}copy(e){return super.copy(e),this.parameters=Object.assign({},e.parameters),this}static fromJSON(e){return new wh(e.vertices,e.indices,e.radius,e.details)}}class Sh extends wh{constructor(e=1,t=0){const s=(1+Math.sqrt(5))/2,i=1/s;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,-i,-s,0,-i,s,0,i,-s,0,i,s,-i,-s,0,-i,s,0,i,-s,0,i,s,0,-s,0,-i,s,0,-i,-s,0,i,s,0,i],[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],e,t),this.type="DodecahedronGeometry",this.parameters={radius:e,detail:t}}static fromJSON(e){return new Sh(e.radius,e.detail)}}const Mh=new Ri,Nh=new Ri,Ah=new Ri,Ch=new qr;class Rh extends An{constructor(e=null,t=1){if(super(),this.type="EdgesGeometry",this.parameters={geometry:e,thresholdAngle:t},null!==e){const s=4,i=Math.pow(10,s),r=Math.cos(js*t),n=e.getIndex(),o=e.getAttribute("position"),a=n?n.count:o.count,h=[0,0,0],u=["a","b","c"],l=new Array(3),c={},d=[];for(let e=0;e80*s){a=u=e[0],h=l=e[1];for(let t=s;tu&&(u=c),d>l&&(l=d);p=Math.max(u-a,l-h),p=0!==p?32767/p:0}return Fh(n,o,s,a,h,p,0),o};function Ih(e,t,s,i,r){let n,o;if(r===function(e,t,s,i){let r=0;for(let n=t,o=s-i;n0)for(n=t;n=t;n-=i)o=Qh(n,e[n],e[n+1],o);return o&&$h(o,o.next)&&(eu(o),o=o.next),o}function Ph(e,t){if(!e)return e;t||(t=e);let s,i=e;do{if(s=!1,i.steiner||!$h(i,i.next)&&0!==qh(i.prev,i,i.next))i=i.next;else{if(eu(i),i=t=i.prev,i===i.next)break;s=!0}}while(s||i!==t);return t}function Fh(e,t,s,i,r,n,o){if(!e)return;!o&&n&&function(e,t,s,i){let r=e;do{0===r.z&&(r.z=Gh(r.x,r.y,t,s,i)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==e);r.prevZ.nextZ=null,r.prevZ=null,function(e){let t,s,i,r,n,o,a,h,u=1;do{for(s=e,e=null,n=null,o=0;s;){for(o++,i=s,a=0,t=0;t0||h>0&&i;)0!==a&&(0===h||!i||s.z<=i.z)?(r=s,s=s.nextZ,a--):(r=i,i=i.nextZ,h--),n?n.nextZ=r:e=r,r.prevZ=n,n=r;s=i}n.nextZ=null,u*=2}while(o>1)}(r)}(e,i,r,n);let a,h,u=e;for(;e.prev!==e.next;)if(a=e.prev,h=e.next,n?Uh(e,i,r,n):zh(e))t.push(a.i/s|0),t.push(e.i/s|0),t.push(h.i/s|0),eu(e),e=h.next,u=h.next;else if((e=h)===u){o?1===o?Fh(e=Oh(Ph(e),t,s),t,s,i,r,n,2):2===o&&Lh(e,t,s,i,r,n):Fh(Ph(e),t,s,i,r,n,1);break}}function zh(e){const t=e.prev,s=e,i=e.next;if(qh(t,s,i)>=0)return!1;const r=t.x,n=s.x,o=i.x,a=t.y,h=s.y,u=i.y,l=rn?r>o?r:o:n>o?n:o,p=a>h?a>u?a:u:h>u?h:u;let m=i.next;for(;m!==t;){if(m.x>=l&&m.x<=d&&m.y>=c&&m.y<=p&&jh(r,a,n,h,o,u,m.x,m.y)&&qh(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function Uh(e,t,s,i){const r=e.prev,n=e,o=e.next;if(qh(r,n,o)>=0)return!1;const a=r.x,h=n.x,u=o.x,l=r.y,c=n.y,d=o.y,p=ah?a>u?a:u:h>u?h:u,f=l>c?l>d?l:d:c>d?c:d,y=Gh(p,m,t,s,i),x=Gh(g,f,t,s,i);let b=e.prevZ,v=e.nextZ;for(;b&&b.z>=y&&v&&v.z<=x;){if(b.x>=p&&b.x<=g&&b.y>=m&&b.y<=f&&b!==r&&b!==o&&jh(a,l,h,c,u,d,b.x,b.y)&&qh(b.prev,b,b.next)>=0)return!1;if(b=b.prevZ,v.x>=p&&v.x<=g&&v.y>=m&&v.y<=f&&v!==r&&v!==o&&jh(a,l,h,c,u,d,v.x,v.y)&&qh(v.prev,v,v.next)>=0)return!1;v=v.nextZ}for(;b&&b.z>=y;){if(b.x>=p&&b.x<=g&&b.y>=m&&b.y<=f&&b!==r&&b!==o&&jh(a,l,h,c,u,d,b.x,b.y)&&qh(b.prev,b,b.next)>=0)return!1;b=b.prevZ}for(;v&&v.z<=x;){if(v.x>=p&&v.x<=g&&v.y>=m&&v.y<=f&&v!==r&&v!==o&&jh(a,l,h,c,u,d,v.x,v.y)&&qh(v.prev,v,v.next)>=0)return!1;v=v.nextZ}return!0}function Oh(e,t,s){let i=e;do{const r=i.prev,n=i.next.next;!$h(r,n)&&Xh(r,i,i.next,n)&&Jh(r,n)&&Jh(n,r)&&(t.push(r.i/s|0),t.push(i.i/s|0),t.push(n.i/s|0),eu(i),eu(i.next),i=e=n),i=i.next}while(i!==e);return Ph(i)}function Lh(e,t,s,i,r,n){let o=e;do{let e=o.next.next;for(;e!==o.prev;){if(o.i!==e.i&&Hh(o,e)){let a=Kh(o,e);return o=Ph(o,o.next),a=Ph(a,a.next),Fh(o,t,s,i,r,n,0),void Fh(a,t,s,i,r,n,0)}e=e.next}o=o.next}while(o!==e)}function Vh(e,t){return e.x-t.x}function Dh(e,t){const s=function(e,t){let s,i=t,r=-1/0;const n=e.x,o=e.y;do{if(o<=i.y&&o>=i.next.y&&i.next.y!==i.y){const e=i.x+(o-i.y)*(i.next.x-i.x)/(i.next.y-i.y);if(e<=n&&e>r&&(r=e,s=i.x=i.x&&i.x>=h&&n!==i.x&&jh(os.x||i.x===s.x&&kh(s,i)))&&(s=i,c=l)),i=i.next}while(i!==a);return s}(e,t);if(!s)return t;const i=Kh(s,e);return Ph(i,i.next),Ph(s,s.next)}function kh(e,t){return qh(e.prev,e,t.prev)<0&&qh(t.next,e,e.next)<0}function Gh(e,t,s,i,r){return(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=(e-s)*r|0)|e<<8))|e<<4))|e<<2))|e<<1))|(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=(t-i)*r|0)|t<<8))|t<<4))|t<<2))|t<<1))<<1}function Wh(e){let t=e,s=e;do{(t.x=(e-o)*(n-a)&&(e-o)*(i-a)>=(s-o)*(t-a)&&(s-o)*(n-a)>=(r-o)*(i-a)}function Hh(e,t){return e.next.i!==t.i&&e.prev.i!==t.i&&!function(e,t){let s=e;do{if(s.i!==e.i&&s.next.i!==e.i&&s.i!==t.i&&s.next.i!==t.i&&Xh(s,s.next,e,t))return!0;s=s.next}while(s!==e);return!1}(e,t)&&(Jh(e,t)&&Jh(t,e)&&function(e,t){let s=e,i=!1;const r=(e.x+t.x)/2,n=(e.y+t.y)/2;do{s.y>n!=s.next.y>n&&s.next.y!==s.y&&r<(s.next.x-s.x)*(n-s.y)/(s.next.y-s.y)+s.x&&(i=!i),s=s.next}while(s!==e);return i}(e,t)&&(qh(e.prev,e,t.prev)||qh(e,t.prev,t))||$h(e,t)&&qh(e.prev,e,e.next)>0&&qh(t.prev,t,t.next)>0)}function qh(e,t,s){return(t.y-e.y)*(s.x-t.x)-(t.x-e.x)*(s.y-t.y)}function $h(e,t){return e.x===t.x&&e.y===t.y}function Xh(e,t,s,i){const r=Zh(qh(e,t,s)),n=Zh(qh(e,t,i)),o=Zh(qh(s,i,e)),a=Zh(qh(s,i,t));return r!==n&&o!==a||(!(0!==r||!Yh(e,s,t))||(!(0!==n||!Yh(e,i,t))||(!(0!==o||!Yh(s,e,i))||!(0!==a||!Yh(s,t,i)))))}function Yh(e,t,s){return t.x<=Math.max(e.x,s.x)&&t.x>=Math.min(e.x,s.x)&&t.y<=Math.max(e.y,s.y)&&t.y>=Math.min(e.y,s.y)}function Zh(e){return e>0?1:e<0?-1:0}function Jh(e,t){return qh(e.prev,e,e.next)<0?qh(e,t,e.next)>=0&&qh(e,e.prev,t)>=0:qh(e,t,e.prev)<0||qh(e,e.next,t)<0}function Kh(e,t){const s=new tu(e.i,e.x,e.y),i=new tu(t.i,t.x,t.y),r=e.next,n=t.prev;return e.next=t,t.prev=e,s.next=r,r.prev=s,i.next=s,s.prev=i,n.next=i,i.prev=n,i}function Qh(e,t,s,i){const r=new tu(e,t,s);return i?(r.next=i.next,r.prev=i,i.next.prev=r,i.next=r):(r.prev=r,r.next=r),r}function eu(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ)}function tu(e,t,s){this.i=e,this.x=t,this.y=s,this.prev=null,this.next=null,this.z=0,this.prevZ=null,this.nextZ=null,this.steiner=!1}class su{static area(e){const t=e.length;let s=0;for(let i=t-1,r=0;r2&&e[t-1].equals(e[0])&&e.pop()}function ru(e,t){for(let s=0;sNumber.EPSILON){const c=Math.sqrt(l),d=Math.sqrt(h*h+u*u),p=t.x-a/c,m=t.y+o/c,g=((s.x-u/d-p)*u-(s.y+h/d-m)*h)/(o*u-a*h);i=p+o*g-e.x,r=m+a*g-e.y;const f=i*i+r*r;if(f<=2)return new Qs(i,r);n=Math.sqrt(f/2)}else{let e=!1;o>Number.EPSILON?h>Number.EPSILON&&(e=!0):o<-Number.EPSILON?h<-Number.EPSILON&&(e=!0):Math.sign(a)===Math.sign(u)&&(e=!0),e?(i=-a,r=o,n=Math.sqrt(l)):(i=o,r=a,n=Math.sqrt(l/2))}return new Qs(i/n,r/n)}const B=[];for(let e=0,t=N.length,s=t-1,i=e+1;e=0;e--){const t=e/p,s=l*Math.cos(t*Math.PI/2),i=c*Math.sin(t*Math.PI/2)+d;for(let e=0,t=N.length;e=0;){const i=s;let r=s-1;r<0&&(r=e.length-1);for(let e=0,s=a+2*p;e0)&&d.push(t,r,h),(e!==s-1||a0!=e>0&&this.version++,this._anisotropy=e}get clearcoat(){return this._clearcoat}set clearcoat(e){this._clearcoat>0!=e>0&&this.version++,this._clearcoat=e}get iridescence(){return this._iridescence}set iridescence(e){this._iridescence>0!=e>0&&this.version++,this._iridescence=e}get dispersion(){return this._dispersion}set dispersion(e){this._dispersion>0!=e>0&&this.version++,this._dispersion=e}get sheen(){return this._sheen}set sheen(e){this._sheen>0!=e>0&&this.version++,this._sheen=e}get transmission(){return this._transmission}set transmission(e){this._transmission>0!=e>0&&this.version++,this._transmission=e}copy(e){return super.copy(e),this.defines={STANDARD:"",PHYSICAL:""},this.anisotropy=e.anisotropy,this.anisotropyRotation=e.anisotropyRotation,this.anisotropyMap=e.anisotropyMap,this.clearcoat=e.clearcoat,this.clearcoatMap=e.clearcoatMap,this.clearcoatRoughness=e.clearcoatRoughness,this.clearcoatRoughnessMap=e.clearcoatRoughnessMap,this.clearcoatNormalMap=e.clearcoatNormalMap,this.clearcoatNormalScale.copy(e.clearcoatNormalScale),this.dispersion=e.dispersion,this.ior=e.ior,this.iridescence=e.iridescence,this.iridescenceMap=e.iridescenceMap,this.iridescenceIOR=e.iridescenceIOR,this.iridescenceThicknessRange=[...e.iridescenceThicknessRange],this.iridescenceThicknessMap=e.iridescenceThicknessMap,this.sheen=e.sheen,this.sheenColor.copy(e.sheenColor),this.sheenColorMap=e.sheenColorMap,this.sheenRoughness=e.sheenRoughness,this.sheenRoughnessMap=e.sheenRoughnessMap,this.transmission=e.transmission,this.transmissionMap=e.transmissionMap,this.thickness=e.thickness,this.thicknessMap=e.thicknessMap,this.attenuationDistance=e.attenuationDistance,this.attenuationColor.copy(e.attenuationColor),this.specularIntensity=e.specularIntensity,this.specularIntensityMap=e.specularIntensityMap,this.specularColor.copy(e.specularColor),this.specularColorMap=e.specularColorMap,this}}class Su extends en{constructor(e){super(),this.isMeshPhongMaterial=!0,this.type="MeshPhongMaterial",this.color=new Jr(16777215),this.specular=new Jr(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Jr(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Qs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new gr,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(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.specular.copy(e.specular),this.shininess=e.shininess,this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.emissive.copy(e.emissive),this.emissiveMap=e.emissiveMap,this.emissiveIntensity=e.emissiveIntensity,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.flatShading=e.flatShading,this.fog=e.fog,this}}class Mu extends en{constructor(e){super(),this.isMeshToonMaterial=!0,this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new Jr(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Jr(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Qs(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(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.gradientMap=e.gradientMap,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.emissive.copy(e.emissive),this.emissiveMap=e.emissiveMap,this.emissiveIntensity=e.emissiveIntensity,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.alphaMap=e.alphaMap,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.fog=e.fog,this}}class Nu extends en{constructor(e){super(),this.isMeshNormalMaterial=!0,this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Qs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.flatShading=!1,this.setValues(e)}copy(e){return super.copy(e),this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.flatShading=e.flatShading,this}}class Au extends en{constructor(e){super(),this.isMeshLambertMaterial=!0,this.type="MeshLambertMaterial",this.color=new Jr(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Jr(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Qs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new gr,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(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.emissive.copy(e.emissive),this.emissiveMap=e.emissiveMap,this.emissiveIntensity=e.emissiveIntensity,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.flatShading=e.flatShading,this.fog=e.fog,this}}class Cu extends en{constructor(e){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(e)}copy(e){return super.copy(e),this.depthPacking=e.depthPacking,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this}}class Ru extends en{constructor(e){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(e)}copy(e){return super.copy(e),this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this}}class Eu extends en{constructor(e){super(),this.isMeshMatcapMaterial=!0,this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new Jr(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Qs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.flatShading=!1,this.fog=!0,this.setValues(e)}copy(e){return super.copy(e),this.defines={MATCAP:""},this.color.copy(e.color),this.matcap=e.matcap,this.map=e.map,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.alphaMap=e.alphaMap,this.flatShading=e.flatShading,this.fog=e.fog,this}}class Bu extends Ta{constructor(e){super(),this.isLineDashedMaterial=!0,this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(e)}copy(e){return super.copy(e),this.scale=e.scale,this.dashSize=e.dashSize,this.gapSize=e.gapSize,this}}function Iu(e,t,s){return!e||!s&&e.constructor===t?e:"number"==typeof t.BYTES_PER_ELEMENT?new t(e):Array.prototype.slice.call(e)}function Pu(e){return ArrayBuffer.isView(e)&&!(e instanceof DataView)}function Fu(e){const t=e.length,s=new Array(t);for(let e=0;e!==t;++e)s[e]=e;return s.sort((function(t,s){return e[t]-e[s]})),s}function zu(e,t,s){const i=e.length,r=new e.constructor(i);for(let n=0,o=0;o!==i;++n){const i=s[n]*t;for(let s=0;s!==t;++s)r[o++]=e[i+s]}return r}function Uu(e,t,s,i){let r=1,n=e[0];for(;void 0!==n&&void 0===n[i];)n=e[r++];if(void 0===n)return;let o=n[i];if(void 0!==o)if(Array.isArray(o))do{o=n[i],void 0!==o&&(t.push(n.time),s.push.apply(s,o)),n=e[r++]}while(void 0!==n);else if(void 0!==o.toArray)do{o=n[i],void 0!==o&&(t.push(n.time),o.toArray(s,s.length)),n=e[r++]}while(void 0!==n);else do{o=n[i],void 0!==o&&(t.push(n.time),s.push(o)),n=e[r++]}while(void 0!==n)}const Ou={convertArray:Iu,isTypedArray:Pu,getKeyframeOrder:Fu,sortedArray:zu,flattenJSON:Uu,subclip:function(e,t,s,i,r=30){const n=e.clone();n.name=t;const o=[];for(let e=0;e=i)){h.push(t.times[e]);for(let s=0;sn.tracks[e].times[0]&&(a=n.tracks[e].times[0]);for(let e=0;e=i.times[c]){const e=c*h+a,t=e+h-a;d=i.values.slice(e,t)}else{const e=i.createInterpolant(),t=a,s=h-a;e.evaluate(n),d=e.resultBuffer.slice(t,s)}if("quaternion"===r){(new Ci).fromArray(d).normalize().conjugate().toArray(d)}const p=o.times.length;for(let e=0;e=r)break e;{const o=t[1];e=r)break t}n=s,s=0}}for(;s>>1;et;)--n;if(++n,0!==r||n!==i){r>=n&&(n=Math.max(n,1),r=n-1);const e=this.getValueSize();this.times=s.slice(r,n),this.values=this.values.slice(r*e,n*e)}return this}validate(){let e=!0;const t=this.getValueSize();t-Math.floor(t)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),e=!1);const s=this.times,i=this.values,r=s.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),e=!1);let n=null;for(let t=0;t!==r;t++){const i=s[t];if("number"==typeof i&&isNaN(i)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,t,i),e=!1;break}if(null!==n&&n>i){console.error("THREE.KeyframeTrack: Out of order keys.",this,t,i,n),e=!1;break}n=i}if(void 0!==i&&Pu(i))for(let t=0,s=i.length;t!==s;++t){const s=i[t];if(isNaN(s)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,t,s),e=!1;break}}return e}optimize(){const e=this.times.slice(),t=this.values.slice(),s=this.getValueSize(),i=this.getInterpolation()===Ft,r=e.length-1;let n=1;for(let o=1;o0){e[n]=e[r];for(let e=r*s,i=n*s,o=0;o!==s;++o)t[i+o]=t[e+o];++n}return n!==e.length?(this.times=e.slice(0,n),this.values=t.slice(0,n*s)):(this.times=e,this.values=t),this}clone(){const e=this.times.slice(),t=this.values.slice(),s=new(0,this.constructor)(this.name,e,t);return s.createInterpolant=this.createInterpolant,s}}Gu.prototype.TimeBufferType=Float32Array,Gu.prototype.ValueBufferType=Float32Array,Gu.prototype.DefaultInterpolation=Pt;class Wu extends Gu{constructor(e,t,s){super(e,t,s)}}Wu.prototype.ValueTypeName="bool",Wu.prototype.ValueBufferType=Array,Wu.prototype.DefaultInterpolation=It,Wu.prototype.InterpolantFactoryMethodLinear=void 0,Wu.prototype.InterpolantFactoryMethodSmooth=void 0;class ju extends Gu{}ju.prototype.ValueTypeName="color";class Hu extends Gu{}Hu.prototype.ValueTypeName="number";class qu extends Lu{constructor(e,t,s,i){super(e,t,s,i)}interpolate_(e,t,s,i){const r=this.resultBuffer,n=this.sampleValues,o=this.valueSize,a=(s-t)/(i-t);let h=e*o;for(let e=h+o;h!==e;h+=4)Ci.slerpFlat(r,0,n,h-o,n,h,a);return r}}class $u extends Gu{InterpolantFactoryMethodLinear(e){return new qu(this.times,this.values,this.getValueSize(),e)}}$u.prototype.ValueTypeName="quaternion",$u.prototype.InterpolantFactoryMethodSmooth=void 0;class Xu extends Gu{constructor(e,t,s){super(e,t,s)}}Xu.prototype.ValueTypeName="string",Xu.prototype.ValueBufferType=Array,Xu.prototype.DefaultInterpolation=It,Xu.prototype.InterpolantFactoryMethodLinear=void 0,Xu.prototype.InterpolantFactoryMethodSmooth=void 0;class Yu extends Gu{}Yu.prototype.ValueTypeName="vector";class Zu{constructor(e="",t=-1,s=[],i=2500){this.name=e,this.tracks=s,this.duration=t,this.blendMode=i,this.uuid=qs(),this.duration<0&&this.resetDuration()}static parse(e){const t=[],s=e.tracks,i=1/(e.fps||1);for(let e=0,r=s.length;e!==r;++e)t.push(Ju(s[e]).scale(i));const r=new this(e.name,e.duration,t,e.blendMode);return r.uuid=e.uuid,r}static toJSON(e){const t=[],s=e.tracks,i={name:e.name,duration:e.duration,tracks:t,uuid:e.uuid,blendMode:e.blendMode};for(let e=0,i=s.length;e!==i;++e)t.push(Gu.toJSON(s[e]));return i}static CreateFromMorphTargetSequence(e,t,s,i){const r=t.length,n=[];for(let e=0;e1){const e=n[1];let t=i[e];t||(i[e]=t=[]),t.push(s)}}const n=[];for(const e in i)n.push(this.CreateFromMorphTargetSequence(e,i[e],t,s));return n}static parseAnimation(e,t){if(!e)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const s=function(e,t,s,i,r){if(0!==s.length){const n=[],o=[];Uu(s,n,o,i),0!==n.length&&r.push(new e(t,n,o))}},i=[],r=e.name||"default",n=e.fps||30,o=e.blendMode;let a=e.length||-1;const h=e.hierarchy||[];for(let e=0;e{t&&t(r),this.manager.itemEnd(e)}),0),r;if(void 0!==sl[e])return void sl[e].push({onLoad:t,onProgress:s,onError:i});sl[e]=[],sl[e].push({onLoad:t,onProgress:s,onError:i});const n=new Request(e,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"}),o=this.mimeType,a=this.responseType;fetch(n).then((t=>{if(200===t.status||0===t.status){if(0===t.status&&console.warn("THREE.FileLoader: HTTP Status 0 received."),"undefined"==typeof ReadableStream||void 0===t.body||void 0===t.body.getReader)return t;const s=sl[e],i=t.body.getReader(),r=t.headers.get("X-File-Size")||t.headers.get("Content-Length"),n=r?parseInt(r):0,o=0!==n;let a=0;const h=new ReadableStream({start(e){!function t(){i.read().then((({done:i,value:r})=>{if(i)e.close();else{a+=r.byteLength;const i=new ProgressEvent("progress",{lengthComputable:o,loaded:a,total:n});for(let e=0,t=s.length;e{e.error(t)}))}()}});return new Response(h)}throw new il(`fetch for "${t.url}" responded with ${t.status}: ${t.statusText}`,t)})).then((e=>{switch(a){case"arraybuffer":return e.arrayBuffer();case"blob":return e.blob();case"document":return e.text().then((e=>(new DOMParser).parseFromString(e,o)));case"json":return e.json();default:if(void 0===o)return e.text();{const t=/charset="?([^;"\s]*)"?/i.exec(o),s=t&&t[1]?t[1].toLowerCase():void 0,i=new TextDecoder(s);return e.arrayBuffer().then((e=>i.decode(e)))}}})).then((t=>{Ku.add(e,t);const s=sl[e];delete sl[e];for(let e=0,i=s.length;e{const s=sl[e];if(void 0===s)throw this.manager.itemError(e),t;delete sl[e];for(let e=0,i=s.length;e{this.manager.itemEnd(e)})),this.manager.itemStart(e)}setResponseType(e){return this.responseType=e,this}setMimeType(e){return this.mimeType=e,this}}class nl extends tl{constructor(e){super(e)}load(e,t,s,i){const r=this,n=new rl(this.manager);n.setPath(this.path),n.setRequestHeader(this.requestHeader),n.setWithCredentials(this.withCredentials),n.load(e,(function(s){try{t(r.parse(JSON.parse(s)))}catch(t){i?i(t):console.error(t),r.manager.itemError(e)}}),s,i)}parse(e){const t=[];for(let s=0;s0:i.vertexColors=e.vertexColors),void 0!==e.uniforms)for(const t in e.uniforms){const r=e.uniforms[t];switch(i.uniforms[t]={},r.type){case"t":i.uniforms[t].value=s(r.value);break;case"c":i.uniforms[t].value=(new Jr).setHex(r.value);break;case"v2":i.uniforms[t].value=(new Qs).fromArray(r.value);break;case"v3":i.uniforms[t].value=(new Ri).fromArray(r.value);break;case"v4":i.uniforms[t].value=(new Ti).fromArray(r.value);break;case"m3":i.uniforms[t].value=(new ei).fromArray(r.value);break;case"m4":i.uniforms[t].value=(new nr).fromArray(r.value);break;default:i.uniforms[t].value=r.value}}if(void 0!==e.defines&&(i.defines=e.defines),void 0!==e.vertexShader&&(i.vertexShader=e.vertexShader),void 0!==e.fragmentShader&&(i.fragmentShader=e.fragmentShader),void 0!==e.glslVersion&&(i.glslVersion=e.glslVersion),void 0!==e.extensions)for(const t in e.extensions)i.extensions[t]=e.extensions[t];if(void 0!==e.lights&&(i.lights=e.lights),void 0!==e.clipping&&(i.clipping=e.clipping),void 0!==e.size&&(i.size=e.size),void 0!==e.sizeAttenuation&&(i.sizeAttenuation=e.sizeAttenuation),void 0!==e.map&&(i.map=s(e.map)),void 0!==e.matcap&&(i.matcap=s(e.matcap)),void 0!==e.alphaMap&&(i.alphaMap=s(e.alphaMap)),void 0!==e.bumpMap&&(i.bumpMap=s(e.bumpMap)),void 0!==e.bumpScale&&(i.bumpScale=e.bumpScale),void 0!==e.normalMap&&(i.normalMap=s(e.normalMap)),void 0!==e.normalMapType&&(i.normalMapType=e.normalMapType),void 0!==e.normalScale){let t=e.normalScale;!1===Array.isArray(t)&&(t=[t,t]),i.normalScale=(new Qs).fromArray(t)}return void 0!==e.displacementMap&&(i.displacementMap=s(e.displacementMap)),void 0!==e.displacementScale&&(i.displacementScale=e.displacementScale),void 0!==e.displacementBias&&(i.displacementBias=e.displacementBias),void 0!==e.roughnessMap&&(i.roughnessMap=s(e.roughnessMap)),void 0!==e.metalnessMap&&(i.metalnessMap=s(e.metalnessMap)),void 0!==e.emissiveMap&&(i.emissiveMap=s(e.emissiveMap)),void 0!==e.emissiveIntensity&&(i.emissiveIntensity=e.emissiveIntensity),void 0!==e.specularMap&&(i.specularMap=s(e.specularMap)),void 0!==e.specularIntensityMap&&(i.specularIntensityMap=s(e.specularIntensityMap)),void 0!==e.specularColorMap&&(i.specularColorMap=s(e.specularColorMap)),void 0!==e.envMap&&(i.envMap=s(e.envMap)),void 0!==e.envMapRotation&&i.envMapRotation.fromArray(e.envMapRotation),void 0!==e.envMapIntensity&&(i.envMapIntensity=e.envMapIntensity),void 0!==e.reflectivity&&(i.reflectivity=e.reflectivity),void 0!==e.refractionRatio&&(i.refractionRatio=e.refractionRatio),void 0!==e.lightMap&&(i.lightMap=s(e.lightMap)),void 0!==e.lightMapIntensity&&(i.lightMapIntensity=e.lightMapIntensity),void 0!==e.aoMap&&(i.aoMap=s(e.aoMap)),void 0!==e.aoMapIntensity&&(i.aoMapIntensity=e.aoMapIntensity),void 0!==e.gradientMap&&(i.gradientMap=s(e.gradientMap)),void 0!==e.clearcoatMap&&(i.clearcoatMap=s(e.clearcoatMap)),void 0!==e.clearcoatRoughnessMap&&(i.clearcoatRoughnessMap=s(e.clearcoatRoughnessMap)),void 0!==e.clearcoatNormalMap&&(i.clearcoatNormalMap=s(e.clearcoatNormalMap)),void 0!==e.clearcoatNormalScale&&(i.clearcoatNormalScale=(new Qs).fromArray(e.clearcoatNormalScale)),void 0!==e.iridescenceMap&&(i.iridescenceMap=s(e.iridescenceMap)),void 0!==e.iridescenceThicknessMap&&(i.iridescenceThicknessMap=s(e.iridescenceThicknessMap)),void 0!==e.transmissionMap&&(i.transmissionMap=s(e.transmissionMap)),void 0!==e.thicknessMap&&(i.thicknessMap=s(e.thicknessMap)),void 0!==e.anisotropyMap&&(i.anisotropyMap=s(e.anisotropyMap)),void 0!==e.sheenColorMap&&(i.sheenColorMap=s(e.sheenColorMap)),void 0!==e.sheenRoughnessMap&&(i.sheenRoughnessMap=s(e.sheenRoughnessMap)),i}setTextures(e){return this.textures=e,this}createMaterialFromType(e){return Bl.createMaterialFromType(e)}static createMaterialFromType(e){return new{ShadowMaterial:vu,SpriteMaterial:no,RawShaderMaterial:Tu,ShaderMaterial:Wn,PointsMaterial:za,MeshPhysicalMaterial:wu,MeshStandardMaterial:_u,MeshPhongMaterial:Su,MeshToonMaterial:Mu,MeshNormalMaterial:Nu,MeshLambertMaterial:Au,MeshDepthMaterial:Cu,MeshDistanceMaterial:Ru,MeshBasicMaterial:tn,MeshMatcapMaterial:Eu,LineDashedMaterial:Bu,LineBasicMaterial:Ta,Material:en}[e]}}class Il{static decodeText(e){if(console.warn("THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead."),"undefined"!=typeof TextDecoder)return(new TextDecoder).decode(e);let t="";for(let s=0,i=e.length;s0){const s=new Qu(t);r=new al(s),r.setCrossOrigin(this.crossOrigin);for(let t=0,s=e.length;t0){i=new al(this.manager),i.setCrossOrigin(this.crossOrigin);for(let t=0,i=e.length;t{const t=new Ii;t.min.fromArray(e.boxMin),t.max.fromArray(e.boxMax);const s=new Zi;return s.radius=e.sphereRadius,s.center.fromArray(e.sphereCenter),{boxInitialized:e.boxInitialized,box:t,sphereInitialized:e.sphereInitialized,sphere:s}})),n._maxInstanceCount=e.maxInstanceCount,n._maxVertexCount=e.maxVertexCount,n._maxIndexCount=e.maxIndexCount,n._geometryInitialized=e.geometryInitialized,n._geometryCount=e.geometryCount,n._matricesTexture=l(e.matricesTexture.uuid),void 0!==e.colorsTexture&&(n._colorsTexture=l(e.colorsTexture.uuid));break;case"LOD":n=new So;break;case"Line":n=new Ra(h(e.geometry),u(e.material));break;case"LineLoop":n=new Fa(h(e.geometry),u(e.material));break;case"LineSegments":n=new Pa(h(e.geometry),u(e.material));break;case"PointCloud":case"Points":n=new Da(h(e.geometry),u(e.material));break;case"Sprite":n=new vo(u(e.material));break;case"Group":n=new Ga;break;case"Bone":n=new zo;break;default:n=new Ir}if(n.uuid=e.uuid,void 0!==e.name&&(n.name=e.name),void 0!==e.matrix?(n.matrix.fromArray(e.matrix),void 0!==e.matrixAutoUpdate&&(n.matrixAutoUpdate=e.matrixAutoUpdate),n.matrixAutoUpdate&&n.matrix.decompose(n.position,n.quaternion,n.scale)):(void 0!==e.position&&n.position.fromArray(e.position),void 0!==e.rotation&&n.rotation.fromArray(e.rotation),void 0!==e.quaternion&&n.quaternion.fromArray(e.quaternion),void 0!==e.scale&&n.scale.fromArray(e.scale)),void 0!==e.up&&n.up.fromArray(e.up),void 0!==e.castShadow&&(n.castShadow=e.castShadow),void 0!==e.receiveShadow&&(n.receiveShadow=e.receiveShadow),e.shadow&&(void 0!==e.shadow.intensity&&(n.shadow.intensity=e.shadow.intensity),void 0!==e.shadow.bias&&(n.shadow.bias=e.shadow.bias),void 0!==e.shadow.normalBias&&(n.shadow.normalBias=e.shadow.normalBias),void 0!==e.shadow.radius&&(n.shadow.radius=e.shadow.radius),void 0!==e.shadow.mapSize&&n.shadow.mapSize.fromArray(e.shadow.mapSize),void 0!==e.shadow.camera&&(n.shadow.camera=this.parseObject(e.shadow.camera))),void 0!==e.visible&&(n.visible=e.visible),void 0!==e.frustumCulled&&(n.frustumCulled=e.frustumCulled),void 0!==e.renderOrder&&(n.renderOrder=e.renderOrder),void 0!==e.userData&&(n.userData=e.userData),void 0!==e.layers&&(n.layers.mask=e.layers),void 0!==e.children){const o=e.children;for(let e=0;e{t&&t(s),r.manager.itemEnd(e)})).catch((e=>{i&&i(e)})):(setTimeout((function(){t&&t(n),r.manager.itemEnd(e)}),0),n);const o={};o.credentials="anonymous"===this.crossOrigin?"same-origin":"include",o.headers=this.requestHeader;const a=fetch(e,o).then((function(e){return e.blob()})).then((function(e){return createImageBitmap(e,Object.assign(r.options,{colorSpaceConversion:"none"}))})).then((function(s){return Ku.add(e,s),t&&t(s),r.manager.itemEnd(e),s})).catch((function(t){i&&i(t),Ku.remove(e),r.manager.itemError(e),r.manager.itemEnd(e)}));Ku.add(e,a),r.manager.itemStart(e)}}let Dl;class kl{static getContext(){return void 0===Dl&&(Dl=new(window.AudioContext||window.webkitAudioContext)),Dl}static setContext(e){Dl=e}}class Gl extends tl{constructor(e){super(e)}load(e,t,s,i){const r=this,n=new rl(this.manager);function o(t){i?i(t):console.error(t),r.manager.itemError(e)}n.setResponseType("arraybuffer"),n.setPath(this.path),n.setRequestHeader(this.requestHeader),n.setWithCredentials(this.withCredentials),n.load(e,(function(e){try{const s=e.slice(0);kl.getContext().decodeAudioData(s,(function(e){t(e)})).catch(o)}catch(e){o(e)}}),s,i)}}const Wl=new nr,jl=new nr,Hl=new nr;class ql{constructor(){this.type="StereoCamera",this.aspect=1,this.eyeSep=.064,this.cameraL=new Xn,this.cameraL.layers.enable(1),this.cameraL.matrixAutoUpdate=!1,this.cameraR=new Xn,this.cameraR.layers.enable(2),this.cameraR.matrixAutoUpdate=!1,this._cache={focus:null,fov:null,aspect:null,near:null,far:null,zoom:null,eyeSep:null}}update(e){const t=this._cache;if(t.focus!==e.focus||t.fov!==e.fov||t.aspect!==e.aspect*this.aspect||t.near!==e.near||t.far!==e.far||t.zoom!==e.zoom||t.eyeSep!==this.eyeSep){t.focus=e.focus,t.fov=e.fov,t.aspect=e.aspect*this.aspect,t.near=e.near,t.far=e.far,t.zoom=e.zoom,t.eyeSep=this.eyeSep,Hl.copy(e.projectionMatrix);const s=t.eyeSep/2,i=s*t.near/t.focus,r=t.near*Math.tan(js*t.fov*.5)/t.zoom;let n,o;jl.elements[12]=-s,Wl.elements[12]=s,n=-r*t.aspect+i,o=r*t.aspect+i,Hl.elements[0]=2*t.near/(o-n),Hl.elements[8]=(o+n)/(o-n),this.cameraL.projectionMatrix.copy(Hl),n=-r*t.aspect-i,o=r*t.aspect-i,Hl.elements[0]=2*t.near/(o-n),Hl.elements[8]=(o+n)/(o-n),this.cameraR.projectionMatrix.copy(Hl)}this.cameraL.matrixWorld.copy(e.matrixWorld).multiply(jl),this.cameraR.matrixWorld.copy(e.matrixWorld).multiply(Wl)}}class $l extends Xn{constructor(e=[]){super(),this.isArrayCamera=!0,this.cameras=e}}class Xl{constructor(e=!0){this.autoStart=e,this.startTime=0,this.oldTime=0,this.elapsedTime=0,this.running=!1}start(){this.startTime=Yl(),this.oldTime=this.startTime,this.elapsedTime=0,this.running=!0}stop(){this.getElapsedTime(),this.running=!1,this.autoStart=!1}getElapsedTime(){return this.getDelta(),this.elapsedTime}getDelta(){let e=0;if(this.autoStart&&!this.running)return this.start(),0;if(this.running){const t=Yl();e=(t-this.oldTime)/1e3,this.oldTime=t,this.elapsedTime+=e}return e}}function Yl(){return performance.now()}const Zl=new Ri,Jl=new Ci,Kl=new Ri,Ql=new Ri;class ec extends Ir{constructor(){super(),this.type="AudioListener",this.context=kl.getContext(),this.gain=this.context.createGain(),this.gain.connect(this.context.destination),this.filter=null,this.timeDelta=0,this._clock=new Xl}getInput(){return this.gain}removeFilter(){return null!==this.filter&&(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination),this.gain.connect(this.context.destination),this.filter=null),this}getFilter(){return this.filter}setFilter(e){return null!==this.filter?(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination)):this.gain.disconnect(this.context.destination),this.filter=e,this.gain.connect(this.filter),this.filter.connect(this.context.destination),this}getMasterVolume(){return this.gain.gain.value}setMasterVolume(e){return this.gain.gain.setTargetAtTime(e,this.context.currentTime,.01),this}updateMatrixWorld(e){super.updateMatrixWorld(e);const t=this.context.listener,s=this.up;if(this.timeDelta=this._clock.getDelta(),this.matrixWorld.decompose(Zl,Jl,Kl),Ql.set(0,0,-1).applyQuaternion(Jl),t.positionX){const e=this.context.currentTime+this.timeDelta;t.positionX.linearRampToValueAtTime(Zl.x,e),t.positionY.linearRampToValueAtTime(Zl.y,e),t.positionZ.linearRampToValueAtTime(Zl.z,e),t.forwardX.linearRampToValueAtTime(Ql.x,e),t.forwardY.linearRampToValueAtTime(Ql.y,e),t.forwardZ.linearRampToValueAtTime(Ql.z,e),t.upX.linearRampToValueAtTime(s.x,e),t.upY.linearRampToValueAtTime(s.y,e),t.upZ.linearRampToValueAtTime(s.z,e)}else t.setPosition(Zl.x,Zl.y,Zl.z),t.setOrientation(Ql.x,Ql.y,Ql.z,s.x,s.y,s.z)}}class tc extends Ir{constructor(e){super(),this.type="Audio",this.listener=e,this.context=e.context,this.gain=this.context.createGain(),this.gain.connect(e.getInput()),this.autoplay=!1,this.buffer=null,this.detune=0,this.loop=!1,this.loopStart=0,this.loopEnd=0,this.offset=0,this.duration=void 0,this.playbackRate=1,this.isPlaying=!1,this.hasPlaybackControl=!0,this.source=null,this.sourceType="empty",this._startedAt=0,this._progress=0,this._connected=!1,this.filters=[]}getOutput(){return this.gain}setNodeSource(e){return this.hasPlaybackControl=!1,this.sourceType="audioNode",this.source=e,this.connect(),this}setMediaElementSource(e){return this.hasPlaybackControl=!1,this.sourceType="mediaNode",this.source=this.context.createMediaElementSource(e),this.connect(),this}setMediaStreamSource(e){return this.hasPlaybackControl=!1,this.sourceType="mediaStreamNode",this.source=this.context.createMediaStreamSource(e),this.connect(),this}setBuffer(e){return this.buffer=e,this.sourceType="buffer",this.autoplay&&this.play(),this}play(e=0){if(!0===this.isPlaying)return void console.warn("THREE.Audio: Audio is already playing.");if(!1===this.hasPlaybackControl)return void console.warn("THREE.Audio: this Audio has no playback control.");this._startedAt=this.context.currentTime+e;const t=this.context.createBufferSource();return t.buffer=this.buffer,t.loop=this.loop,t.loopStart=this.loopStart,t.loopEnd=this.loopEnd,t.onended=this.onEnded.bind(this),t.start(this._startedAt,this._progress+this.offset,this.duration),this.isPlaying=!0,this.source=t,this.setDetune(this.detune),this.setPlaybackRate(this.playbackRate),this.connect()}pause(){if(!1!==this.hasPlaybackControl)return!0===this.isPlaying&&(this._progress+=Math.max(this.context.currentTime-this._startedAt,0)*this.playbackRate,!0===this.loop&&(this._progress=this._progress%(this.duration||this.buffer.duration)),this.source.stop(),this.source.onended=null,this.isPlaying=!1),this;console.warn("THREE.Audio: this Audio has no playback control.")}stop(e=0){if(!1!==this.hasPlaybackControl)return this._progress=0,null!==this.source&&(this.source.stop(this.context.currentTime+e),this.source.onended=null),this.isPlaying=!1,this;console.warn("THREE.Audio: this Audio has no playback control.")}connect(){if(this.filters.length>0){this.source.connect(this.filters[0]);for(let e=1,t=this.filters.length;e0){this.source.disconnect(this.filters[0]);for(let e=1,t=this.filters.length;e0&&this._mixBufferRegionAdditive(s,i,this._addIndex*t,1,t);for(let e=t,r=t+t;e!==r;++e)if(s[e]!==s[e+t]){o.setValue(s,i);break}}saveOriginalState(){const e=this.binding,t=this.buffer,s=this.valueSize,i=s*this._origIndex;e.getValue(t,i);for(let e=s,r=i;e!==r;++e)t[e]=t[i+e%s];this._setIdentity(),this.cumulativeWeight=0,this.cumulativeWeightAdditive=0}restoreOriginalState(){const e=3*this.valueSize;this.binding.setValue(this.buffer,e)}_setAdditiveIdentityNumeric(){const e=this._addIndex*this.valueSize,t=e+this.valueSize;for(let s=e;s=.5)for(let i=0;i!==r;++i)e[t+i]=e[s+i]}_slerp(e,t,s,i){Ci.slerpFlat(e,t,e,t,e,s,i)}_slerpAdditive(e,t,s,i,r){const n=this._workIndex*r;Ci.multiplyQuaternionsFlat(e,n,e,t,e,s),Ci.slerpFlat(e,t,e,t,e,n,i)}_lerp(e,t,s,i,r){const n=1-i;for(let o=0;o!==r;++o){const r=t+o;e[r]=e[r]*n+e[s+o]*i}}_lerpAdditive(e,t,s,i,r){for(let n=0;n!==r;++n){const r=t+n;e[r]=e[r]+e[s+n]*i}}}const uc="\\[\\]\\.:\\/",lc=new RegExp("["+uc+"]","g"),cc="[^"+uc+"]",dc="[^"+uc.replace("\\.","")+"]",pc=new RegExp("^"+/((?:WC+[\/:])*)/.source.replace("WC",cc)+/(WCOD+)?/.source.replace("WCOD",dc)+/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",cc)+/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",cc)+"$"),mc=["material","materials","bones","map"];class gc{constructor(e,t,s){this.path=t,this.parsedPath=s||gc.parseTrackName(t),this.node=gc.findNode(e,this.parsedPath.nodeName),this.rootNode=e,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(e,t,s){return e&&e.isAnimationObjectGroup?new gc.Composite(e,t,s):new gc(e,t,s)}static sanitizeNodeName(e){return e.replace(/\s/g,"_").replace(lc,"")}static parseTrackName(e){const t=pc.exec(e);if(null===t)throw new Error("PropertyBinding: Cannot parse trackName: "+e);const s={nodeName:t[2],objectName:t[3],objectIndex:t[4],propertyName:t[5],propertyIndex:t[6]},i=s.nodeName&&s.nodeName.lastIndexOf(".");if(void 0!==i&&-1!==i){const e=s.nodeName.substring(i+1);-1!==mc.indexOf(e)&&(s.nodeName=s.nodeName.substring(0,i),s.objectName=e)}if(null===s.propertyName||0===s.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+e);return s}static findNode(e,t){if(void 0===t||""===t||"."===t||-1===t||t===e.name||t===e.uuid)return e;if(e.skeleton){const s=e.skeleton.getBoneByName(t);if(void 0!==s)return s}if(e.children){const s=function(e){for(let i=0;i=r){const n=r++,u=e[n];t[u.uuid]=h,e[h]=u,t[a]=n,e[n]=o;for(let e=0,t=i;e!==t;++e){const t=s[e],i=t[n],r=t[h];t[h]=i,t[n]=r}}}this.nCachedObjects_=r}uncache(){const e=this._objects,t=this._indicesByUUID,s=this._bindings,i=s.length;let r=this.nCachedObjects_,n=e.length;for(let o=0,a=arguments.length;o!==a;++o){const a=arguments[o].uuid,h=t[a];if(void 0!==h)if(delete t[a],h0&&(t[o.uuid]=h),e[h]=o,e.pop();for(let e=0,t=i;e!==t;++e){const t=s[e];t[h]=t[r],t.pop()}}}this.nCachedObjects_=r}subscribe_(e,t){const s=this._bindingsIndicesByPath;let i=s[e];const r=this._bindings;if(void 0!==i)return r[i];const n=this._paths,o=this._parsedPaths,a=this._objects,h=a.length,u=this.nCachedObjects_,l=new Array(h);i=r.length,s[e]=i,n.push(e),o.push(t),r.push(l);for(let s=u,i=a.length;s!==i;++s){const i=a[s];l[s]=new gc(i,e,t)}return l}unsubscribe_(e){const t=this._bindingsIndicesByPath,s=t[e];if(void 0!==s){const i=this._paths,r=this._parsedPaths,n=this._bindings,o=n.length-1,a=n[o];t[e[o]]=s,n[s]=a,n.pop(),r[s]=r[o],r.pop(),i[s]=i[o],i.pop()}}}class yc{constructor(e,t,s=null,i=t.blendMode){this._mixer=e,this._clip=t,this._localRoot=s,this.blendMode=i;const r=t.tracks,n=r.length,o=new Array(n),a={endingStart:zt,endingEnd:zt};for(let e=0;e!==n;++e){const t=r[e].createInterpolant(null);o[e]=t,t.settings=a}this._interpolantSettings=a,this._interpolants=o,this._propertyBindings=new Array(n),this._cacheIndex=null,this._byClipCacheIndex=null,this._timeScaleInterpolant=null,this._weightInterpolant=null,this.loop=2201,this._loopCount=-1,this._startTime=null,this.time=0,this.timeScale=1,this._effectiveTimeScale=1,this.weight=1,this._effectiveWeight=1,this.repetitions=1/0,this.paused=!1,this.enabled=!0,this.clampWhenFinished=!1,this.zeroSlopeAtStart=!0,this.zeroSlopeAtEnd=!0}play(){return this._mixer._activateAction(this),this}stop(){return this._mixer._deactivateAction(this),this.reset()}reset(){return this.paused=!1,this.enabled=!0,this.time=0,this._loopCount=-1,this._startTime=null,this.stopFading().stopWarping()}isRunning(){return this.enabled&&!this.paused&&0!==this.timeScale&&null===this._startTime&&this._mixer._isActiveAction(this)}isScheduled(){return this._mixer._isActiveAction(this)}startAt(e){return this._startTime=e,this}setLoop(e,t){return this.loop=e,this.repetitions=t,this}setEffectiveWeight(e){return this.weight=e,this._effectiveWeight=this.enabled?e:0,this.stopFading()}getEffectiveWeight(){return this._effectiveWeight}fadeIn(e){return this._scheduleFading(e,0,1)}fadeOut(e){return this._scheduleFading(e,1,0)}crossFadeFrom(e,t,s){if(e.fadeOut(t),this.fadeIn(t),s){const s=this._clip.duration,i=e._clip.duration,r=i/s,n=s/i;e.warp(1,r,t),this.warp(n,1,t)}return this}crossFadeTo(e,t,s){return e.crossFadeFrom(this,t,s)}stopFading(){const e=this._weightInterpolant;return null!==e&&(this._weightInterpolant=null,this._mixer._takeBackControlInterpolant(e)),this}setEffectiveTimeScale(e){return this.timeScale=e,this._effectiveTimeScale=this.paused?0:e,this.stopWarping()}getEffectiveTimeScale(){return this._effectiveTimeScale}setDuration(e){return this.timeScale=this._clip.duration/e,this.stopWarping()}syncWith(e){return this.time=e.time,this.timeScale=e.timeScale,this.stopWarping()}halt(e){return this.warp(this._effectiveTimeScale,0,e)}warp(e,t,s){const i=this._mixer,r=i.time,n=this.timeScale;let o=this._timeScaleInterpolant;null===o&&(o=i._lendControlInterpolant(),this._timeScaleInterpolant=o);const a=o.parameterPositions,h=o.sampleValues;return a[0]=r,a[1]=r+s,h[0]=e/n,h[1]=t/n,this}stopWarping(){const e=this._timeScaleInterpolant;return null!==e&&(this._timeScaleInterpolant=null,this._mixer._takeBackControlInterpolant(e)),this}getMixer(){return this._mixer}getClip(){return this._clip}getRoot(){return this._localRoot||this._mixer._root}_update(e,t,s,i){if(!this.enabled)return void this._updateWeight(e);const r=this._startTime;if(null!==r){const i=(e-r)*s;i<0||0===s?t=0:(this._startTime=null,t=s*i)}t*=this._updateTimeScale(e);const n=this._updateTime(t),o=this._updateWeight(e);if(o>0){const e=this._interpolants,t=this._propertyBindings;if(this.blendMode===Vt)for(let s=0,i=e.length;s!==i;++s)e[s].evaluate(n),t[s].accumulateAdditive(o);else for(let s=0,r=e.length;s!==r;++s)e[s].evaluate(n),t[s].accumulate(i,o)}}_updateWeight(e){let t=0;if(this.enabled){t=this.weight;const s=this._weightInterpolant;if(null!==s){const i=s.evaluate(e)[0];t*=i,e>s.parameterPositions[1]&&(this.stopFading(),0===i&&(this.enabled=!1))}}return this._effectiveWeight=t,t}_updateTimeScale(e){let t=0;if(!this.paused){t=this.timeScale;const s=this._timeScaleInterpolant;if(null!==s){t*=s.evaluate(e)[0],e>s.parameterPositions[1]&&(this.stopWarping(),0===t?this.paused=!0:this.timeScale=t)}}return this._effectiveTimeScale=t,t}_updateTime(e){const t=this._clip.duration,s=this.loop;let i=this.time+e,r=this._loopCount;const n=2202===s;if(0===e)return-1===r?i:n&&1==(1&r)?t-i:i;if(2200===s){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));e:{if(i>=t)i=t;else{if(!(i<0)){this.time=i;break e}i=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:e<0?-1:1})}}else{if(-1===r&&(e>=0?(r=0,this._setEndings(!0,0===this.repetitions,n)):this._setEndings(0===this.repetitions,!0,n)),i>=t||i<0){const s=Math.floor(i/t);i-=t*s,r+=Math.abs(s);const o=this.repetitions-r;if(o<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,i=e>0?t:0,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:e>0?1:-1});else{if(1===o){const t=e<0;this._setEndings(t,!t,n)}else this._setEndings(!1,!1,n);this._loopCount=r,this.time=i,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:s})}}else this.time=i;if(n&&1==(1&r))return t-i}return i}_setEndings(e,t,s){const i=this._interpolantSettings;s?(i.endingStart=Ut,i.endingEnd=Ut):(i.endingStart=e?this.zeroSlopeAtStart?Ut:zt:Ot,i.endingEnd=t?this.zeroSlopeAtEnd?Ut:zt:Ot)}_scheduleFading(e,t,s){const i=this._mixer,r=i.time;let n=this._weightInterpolant;null===n&&(n=i._lendControlInterpolant(),this._weightInterpolant=n);const o=n.parameterPositions,a=n.sampleValues;return o[0]=r,a[0]=t,o[1]=r+e,a[1]=s,this}}const xc=new Float32Array(1);class bc extends ks{constructor(e){super(),this._root=e,this._initMemoryManager(),this._accuIndex=0,this.time=0,this.timeScale=1}_bindAction(e,t){const s=e._localRoot||this._root,i=e._clip.tracks,r=i.length,n=e._propertyBindings,o=e._interpolants,a=s.uuid,h=this._bindingsByRootAndName;let u=h[a];void 0===u&&(u={},h[a]=u);for(let e=0;e!==r;++e){const r=i[e],h=r.name;let l=u[h];if(void 0!==l)++l.referenceCount,n[e]=l;else{if(l=n[e],void 0!==l){null===l._cacheIndex&&(++l.referenceCount,this._addInactiveBinding(l,a,h));continue}const i=t&&t._propertyBindings[e].binding.parsedPath;l=new hc(gc.create(s,h,i),r.ValueTypeName,r.getValueSize()),++l.referenceCount,this._addInactiveBinding(l,a,h),n[e]=l}o[e].resultBuffer=l.buffer}}_activateAction(e){if(!this._isActiveAction(e)){if(null===e._cacheIndex){const t=(e._localRoot||this._root).uuid,s=e._clip.uuid,i=this._actionsByClip[s];this._bindAction(e,i&&i.knownActions[0]),this._addInactiveAction(e,s,t)}const t=e._propertyBindings;for(let e=0,s=t.length;e!==s;++e){const s=t[e];0==s.useCount++&&(this._lendBinding(s),s.saveOriginalState())}this._lendAction(e)}}_deactivateAction(e){if(this._isActiveAction(e)){const t=e._propertyBindings;for(let e=0,s=t.length;e!==s;++e){const s=t[e];0==--s.useCount&&(s.restoreOriginalState(),this._takeBackBinding(s))}this._takeBackAction(e)}}_initMemoryManager(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;const e=this;this.stats={actions:{get total(){return e._actions.length},get inUse(){return e._nActiveActions}},bindings:{get total(){return e._bindings.length},get inUse(){return e._nActiveBindings}},controlInterpolants:{get total(){return e._controlInterpolants.length},get inUse(){return e._nActiveControlInterpolants}}}}_isActiveAction(e){const t=e._cacheIndex;return null!==t&&t=0;--t)e[t].stop();return this}update(e){e*=this.timeScale;const t=this._actions,s=this._nActiveActions,i=this.time+=e,r=Math.sign(e),n=this._accuIndex^=1;for(let o=0;o!==s;++o){t[o]._update(i,e,r,n)}const o=this._bindings,a=this._nActiveBindings;for(let e=0;e!==a;++e)o[e].apply(n);return this}setTime(e){this.time=0;for(let e=0;e=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y}containsBox(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y}getParameter(e,t){return t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y))}intersectsBox(e){return e.max.x>=this.min.x&&e.min.x<=this.max.x&&e.max.y>=this.min.y&&e.min.y<=this.max.y}clampPoint(e,t){return t.copy(e).clamp(this.min,this.max)}distanceToPoint(e){return this.clampPoint(e,Ic).distanceTo(e)}intersect(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this}union(e){return this.min.min(e.min),this.max.max(e.max),this}translate(e){return this.min.add(e),this.max.add(e),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}const Fc=new Ri,zc=new Ri;class Uc{constructor(e=new Ri,t=new Ri){this.start=e,this.end=t}set(e,t){return this.start.copy(e),this.end.copy(t),this}copy(e){return this.start.copy(e.start),this.end.copy(e.end),this}getCenter(e){return e.addVectors(this.start,this.end).multiplyScalar(.5)}delta(e){return e.subVectors(this.end,this.start)}distanceSq(){return this.start.distanceToSquared(this.end)}distance(){return this.start.distanceTo(this.end)}at(e,t){return this.delta(t).multiplyScalar(e).add(this.start)}closestPointToPointParameter(e,t){Fc.subVectors(e,this.start),zc.subVectors(this.end,this.start);const s=zc.dot(zc);let i=zc.dot(Fc)/s;return t&&(i=$s(i,0,1)),i}closestPointToPoint(e,t,s){const i=this.closestPointToPointParameter(e,t);return this.delta(s).multiplyScalar(i).add(this.start)}applyMatrix4(e){return this.start.applyMatrix4(e),this.end.applyMatrix4(e),this}equals(e){return e.start.equals(this.start)&&e.end.equals(this.end)}clone(){return(new this.constructor).copy(this)}}const Oc=new Ri;class Lc extends Ir{constructor(e,t){super(),this.light=e,this.matrixAutoUpdate=!1,this.color=t,this.type="SpotLightHelper";const s=new An,i=[0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,-1,0,1,0,0,0,0,1,1,0,0,0,0,-1,1];for(let e=0,t=1,s=32;e1)for(let s=0;s.99999)this.quaternion.set(0,0,0,1);else if(e.y<-.99999)this.quaternion.set(1,0,0,0);else{ud.set(e.z,0,-e.x).normalize();const t=Math.acos(e.y);this.quaternion.setFromAxisAngle(ud,t)}}setLength(e,t=.2*e,s=.2*t){this.line.scale.set(1,Math.max(1e-4,e-t),1),this.line.updateMatrix(),this.cone.scale.set(s,t,s),this.cone.position.y=e,this.cone.updateMatrix()}setColor(e){this.line.material.color.set(e),this.cone.material.color.set(e)}copy(e){return super.copy(e,!1),this.line.copy(e.line),this.cone.copy(e.cone),this}dispose(){this.line.geometry.dispose(),this.line.material.dispose(),this.cone.geometry.dispose(),this.cone.material.dispose()}}class pd extends Pa{constructor(e=1){const t=[0,0,0,e,0,0,0,0,0,0,e,0,0,0,0,0,0,e],s=new An;s.setAttribute("position",new bn(t,3)),s.setAttribute("color",new bn([1,0,0,1,.6,0,0,1,0,.6,1,0,0,0,1,0,.6,1],3));super(s,new Ta({vertexColors:!0,toneMapped:!1})),this.type="AxesHelper"}setColors(e,t,s){const i=new Jr,r=this.geometry.attributes.color.array;return i.set(e),i.toArray(r,0),i.toArray(r,3),i.set(t),i.toArray(r,6),i.toArray(r,9),i.set(s),i.toArray(r,12),i.toArray(r,15),this.geometry.attributes.color.needsUpdate=!0,this}dispose(){this.geometry.dispose(),this.material.dispose()}}class md{constructor(){this.type="ShapePath",this.color=new Jr,this.subPaths=[],this.currentPath=null}moveTo(e,t){return this.currentPath=new yh,this.subPaths.push(this.currentPath),this.currentPath.moveTo(e,t),this}lineTo(e,t){return this.currentPath.lineTo(e,t),this}quadraticCurveTo(e,t,s,i){return this.currentPath.quadraticCurveTo(e,t,s,i),this}bezierCurveTo(e,t,s,i,r,n){return this.currentPath.bezierCurveTo(e,t,s,i,r,n),this}splineThru(e){return this.currentPath.splineThru(e),this}toShapes(e){function t(e,t){const s=t.length;let i=!1;for(let r=s-1,n=0;nNumber.EPSILON){if(h<0&&(s=t[n],a=-a,o=t[r],h=-h),e.yo.y)continue;if(e.y===s.y){if(e.x===s.x)return!0}else{const t=h*(e.x-s.x)-a*(e.y-s.y);if(0===t)return!0;if(t<0)continue;i=!i}}else{if(e.y!==s.y)continue;if(o.x<=e.x&&e.x<=s.x||s.x<=e.x&&e.x<=o.x)return!0}}return i}const s=su.isClockWise,i=this.subPaths;if(0===i.length)return[];let r,n,o;const a=[];if(1===i.length)return n=i[0],o=new Eh,o.curves=n.curves,a.push(o),a;let h=!s(i[0].getPoints());h=e?!h:h;const u=[],l=[];let c,d,p=[],m=0;l[m]=void 0,p[m]=[];for(let t=0,o=i.length;t1){let e=!1,s=0;for(let e=0,t=l.length;e0&&!1===e&&(p=u)}for(let e=0,t=l.length;e>>16,2246822507),s^=Math.imul(i^i>>>13,3266489909),i=Math.imul(i^i>>>16,2246822507),i^=Math.imul(s^s>>>13,3266489909),4294967296*(2097151&i)+(s>>>0)}const vd=e=>bd(e),Td=e=>bd(e),_d=(...e)=>bd(e);function wd(e,t=!1){const s=[];!0===e.isNode&&(s.push(e.id),e=e.getSelf());for(const{property:i,childNode:r}of Sd(e))s.push(s,bd(i.slice(0,-4)),r.getCacheKey(t));return bd(s)}function*Sd(e,t=!1){for(const s in e){if(!0===s.startsWith("_"))continue;const i=e[s];if(!0===Array.isArray(i))for(let e=0;ee.charCodeAt(0))).buffer}var Rd=Object.freeze({__proto__:null,arrayBufferToBase64:Ad,base64ToArrayBuffer:Cd,getCacheKey:wd,getNodeChildren:Sd,getValueFromType:Nd,getValueType:Md,hash:_d,hashArray:Td,hashString:vd});const Ed={VERTEX:"vertex",FRAGMENT:"fragment"},Bd={NONE:"none",FRAME:"frame",RENDER:"render",OBJECT:"object"},Id={BOOLEAN:"bool",INTEGER:"int",FLOAT:"float",VECTOR2:"vec2",VECTOR3:"vec3",VECTOR4:"vec4",MATRIX2:"mat2",MATRIX3:"mat3",MATRIX4:"mat4"},Pd=["fragment","vertex"],Fd=["setup","analyze","generate"],zd=[...Pd,"compute"],Ud=["x","y","z","w"];let Od=0;class Ld extends ks{static get type(){return"Node"}constructor(e=null){super(),this.nodeType=e,this.updateType=Bd.NONE,this.updateBeforeType=Bd.NONE,this.updateAfterType=Bd.NONE,this.uuid=Ks.generateUUID(),this.version=0,this._cacheKey=null,this._cacheKeyVersion=0,this.global=!1,this.isNode=!0,Object.defineProperty(this,"id",{value:Od++})}set needsUpdate(e){!0===e&&this.version++}get type(){return this.constructor.type}onUpdate(e,t){return this.updateType=t,this.update=e.bind(this.getSelf()),this}onFrameUpdate(e){return this.onUpdate(e,Bd.FRAME)}onRenderUpdate(e){return this.onUpdate(e,Bd.RENDER)}onObjectUpdate(e){return this.onUpdate(e,Bd.OBJECT)}onReference(e){return this.updateReference=e.bind(this.getSelf()),this}getSelf(){return this.self||this}updateReference(){return this}isGlobal(){return this.global}*getChildren(){for(const{childNode:e}of Sd(this))yield e}dispose(){this.dispatchEvent({type:"dispose"})}traverse(e){e(this);for(const t of this.getChildren())t.traverse(e)}getCacheKey(e=!1){return!0!==(e=e||this.version!==this._cacheKeyVersion)&&null!==this._cacheKey||(this._cacheKey=wd(this,e),this._cacheKeyVersion=this.version),this._cacheKey}getScope(){return this}getHash(){return this.uuid}getUpdateType(){return this.updateType}getUpdateBeforeType(){return this.updateBeforeType}getUpdateAfterType(){return this.updateAfterType}getElementType(e){const t=this.getNodeType(e);return e.getElementType(t)}getNodeType(e){const t=e.getNodeProperties(this);return t.outputNode?t.outputNode.getNodeType(e):this.nodeType}getShared(e){const t=this.getHash(e);return e.getNodeFromHash(t)||this}setup(e){const t=e.getNodeProperties(this);let s=0;for(const e of this.getChildren())t["node"+s++]=e;return null}analyze(e){if(1===e.increaseUsage(this)){const t=e.getNodeProperties(this);for(const s of Object.values(t))s&&!0===s.isNode&&s.build(e)}}generate(e,t){const{outputNode:s}=e.getNodeProperties(this);if(s&&!0===s.isNode)return s.build(e,t)}updateBefore(){console.warn("Abstract function.")}updateAfter(){console.warn("Abstract function.")}update(){console.warn("Abstract function.")}build(e,t=null){const s=this.getShared(e);if(this!==s)return s.build(e,t);e.addNode(this),e.addChain(this);let i=null;const r=e.getBuildStage();if("setup"===r){this.updateReference(e);const t=e.getNodeProperties(this);if(!0!==t.initialized){e.stack.nodes.length;t.initialized=!0,t.outputNode=this.setup(e),null!==t.outputNode&&e.stack.nodes.length;for(const s of Object.values(t))s&&!0===s.isNode&&s.build(e)}}else if("analyze"===r)this.analyze(e);else if("generate"===r){if(1===this.generate.length){const s=this.getNodeType(e),r=e.getDataFromNode(this);i=r.snippet,void 0===i?(i=this.generate(e)||"",r.snippet=i):void 0!==r.flowCodes&&void 0!==e.context.nodeBlock&&e.addFlowCodeHierarchy(this,e.context.nodeBlock),i=e.format(i,s,t)}else i=this.generate(e,t)||""}return e.removeChain(this),i}getSerializeChildren(){return Sd(this)}serialize(e){const t=this.getSerializeChildren(),s={};for(const{property:i,index:r,childNode:n}of t)void 0!==r?(void 0===s[i]&&(s[i]=Number.isInteger(r)?[]:{}),s[i][r]=n.toJSON(e.meta).uuid):s[i]=n.toJSON(e.meta).uuid;Object.keys(s).length>0&&(e.inputNodes=s)}deserialize(e){if(void 0!==e.inputNodes){const t=e.meta.nodes;for(const s in e.inputNodes)if(Array.isArray(e.inputNodes[s])){const i=[];for(const r of e.inputNodes[s])i.push(t[r]);this[s]=i}else if("object"==typeof e.inputNodes[s]){const i={};for(const r in e.inputNodes[s]){const n=e.inputNodes[s][r];i[r]=t[n]}this[s]=i}else{const i=e.inputNodes[s];this[s]=t[i]}}}toJSON(e){const{uuid:t,type:s}=this,i=void 0===e||"string"==typeof e;i&&(e={textures:{},images:{},nodes:{}});let r=e.nodes[t];function n(e){const t=[];for(const s in e){const i=e[s];delete i.metadata,t.push(i)}return t}if(void 0===r&&(r={uuid:t,type:s,meta:e,metadata:{version:4.6,type:"Node",generator:"Node.toJSON"}},!0!==i&&(e.nodes[r.uuid]=r),this.serialize(r),delete r.meta),i){const t=n(e.textures),s=n(e.images),i=n(e.nodes);t.length>0&&(r.textures=t),s.length>0&&(r.images=s),i.length>0&&(r.nodes=i)}return r}}class Vd extends Ld{static get type(){return"ArrayElementNode"}constructor(e,t){super(),this.node=e,this.indexNode=t,this.isArrayElementNode=!0}getNodeType(e){return this.node.getElementType(e)}generate(e){return`${this.node.build(e)}[ ${this.indexNode.build(e,"uint")} ]`}}class Dd extends Ld{static get type(){return"ConvertNode"}constructor(e,t){super(),this.node=e,this.convertTo=t}getNodeType(e){const t=this.node.getNodeType(e);let s=null;for(const i of this.convertTo.split("|"))null!==s&&e.getTypeLength(t)!==e.getTypeLength(i)||(s=i);return s}serialize(e){super.serialize(e),e.convertTo=this.convertTo}deserialize(e){super.deserialize(e),this.convertTo=e.convertTo}generate(e,t){const s=this.node,i=this.getNodeType(e),r=s.build(e,i);return e.format(r,i,t)}}class kd extends Ld{static get type(){return"TempNode"}constructor(e){super(e),this.isTempNode=!0}hasDependencies(e){return e.getDataFromNode(this).usageCount>1}build(e,t){if("generate"===e.getBuildStage()){const s=e.getVectorType(this.getNodeType(e,t)),i=e.getDataFromNode(this);if(void 0!==i.propertyName)return e.format(i.propertyName,s,t);if("void"!==s&&"void"!==t&&this.hasDependencies(e)){const r=super.build(e,s),n=e.getVarFromNode(this,null,s),o=e.getPropertyName(n);return e.addLineFlowCode(`${o} = ${r}`,this),i.snippet=r,i.propertyName=o,e.format(i.propertyName,s,t)}}return super.build(e,t)}}class Gd extends kd{static get type(){return"JoinNode"}constructor(e=[],t=null){super(t),this.nodes=e}getNodeType(e){return null!==this.nodeType?e.getVectorType(this.nodeType):e.getTypeFromLength(this.nodes.reduce(((t,s)=>t+e.getTypeLength(s.getNodeType(e))),0))}generate(e,t){const s=this.getNodeType(e),i=this.nodes,r=e.getComponentType(s),n=[];for(const t of i){let s=t.build(e);const i=e.getComponentType(t.getNodeType(e));i!==r&&(s=e.format(s,i,r)),n.push(s)}const o=`${e.getType(s)}( ${n.join(", ")} )`;return e.format(o,s,t)}}const Wd=Ud.join("");class jd extends Ld{static get type(){return"SplitNode"}constructor(e,t="x"){super(),this.node=e,this.components=t,this.isSplitNode=!0}getVectorLength(){let e=this.components.length;for(const t of this.components)e=Math.max(Ud.indexOf(t)+1,e);return e}getComponentType(e){return e.getComponentType(this.node.getNodeType(e))}getNodeType(e){return e.getTypeFromLength(this.components.length,this.getComponentType(e))}generate(e,t){const s=this.node,i=e.getTypeLength(s.getNodeType(e));let r=null;if(i>1){let n=null;this.getVectorLength()>=i&&(n=e.getTypeFromLength(this.getVectorLength(),this.getComponentType(e)));const o=s.build(e,n);r=this.components.length===i&&this.components===Wd.slice(0,this.components.length)?e.format(o,n,t):e.format(`${o}.${this.components}`,this.getNodeType(e),t)}else r=s.build(e,t);return r}serialize(e){super.serialize(e),e.components=this.components}deserialize(e){super.deserialize(e),this.components=e.components}}class Hd extends kd{static get type(){return"SetNode"}constructor(e,t,s){super(),this.sourceNode=e,this.components=t,this.targetNode=s}getNodeType(e){return this.sourceNode.getNodeType(e)}generate(e){const{sourceNode:t,components:s,targetNode:i}=this,r=this.getNodeType(e),n=e.getTypeFromLength(s.length,i.getNodeType(e)),o=i.build(e,n),a=t.build(e,r),h=e.getTypeLength(r),u=[];for(let e=0;ee.replace(/r|s/g,"x").replace(/g|t/g,"y").replace(/b|p/g,"z").replace(/a|q/g,"w"),Qd=e=>Kd(e).split("").sort().join(""),ep={setup(e,t){const s=t.shift();return e(Mp(s),...t)},get(e,t,s){if("string"==typeof t&&void 0===e[t]){if(!0!==e.isStackNode&&"assign"===t)return(...e)=>(Yd.assign(s,...e),s);if(Zd.has(t)){const i=Zd.get(t);return e.isStackNode?(...e)=>s.add(i(...e)):(...e)=>i(s,...e)}if("self"===t)return e;if(t.endsWith("Assign")&&Zd.has(t.slice(0,t.length-6))){const i=Zd.get(t.slice(0,t.length-6));return e.isStackNode?(...e)=>s.assign(e[0],i(...e)):(...e)=>s.assign(i(s,...e))}if(!0===/^[xyzwrgbastpq]{1,4}$/.test(t))return t=Kd(t),Sp(new jd(s,t));if(!0===/^set[XYZWRGBASTPQ]{1,4}$/.test(t))return t=Qd(t.slice(3).toLowerCase()),s=>Sp(new Hd(e,t,s));if(!0===/^flip[XYZWRGBASTPQ]{1,4}$/.test(t))return t=Qd(t.slice(4).toLowerCase()),()=>Sp(new qd(Sp(e),t));if("width"===t||"height"===t||"depth"===t)return"width"===t?t="x":"height"===t?t="y":"depth"===t&&(t="z"),Sp(new jd(e,t));if(!0===/^\d+$/.test(t))return Sp(new Vd(s,new Xd(Number(t),"uint")))}return Reflect.get(e,t,s)},set:(e,t,s,i)=>"string"!=typeof t||void 0!==e[t]||!0!==/^[xyzwrgbastpq]{1,4}$/.test(t)&&"width"!==t&&"height"!==t&&"depth"!==t&&!0!==/^\d+$/.test(t)?Reflect.set(e,t,s,i):(i[t].assign(s),!0)},tp=new WeakMap,sp=new WeakMap,ip=function(e,t=null){for(const s in e)e[s]=Sp(e[s],t);return e},rp=function(e,t=null){const s=e.length;for(let i=0;iSp(null!==i?Object.assign(e,i):e);return null===t?(...t)=>r(new e(...Np(t))):null!==s?(s=Sp(s),(...i)=>r(new e(t,...Np(i),s))):(...s)=>r(new e(t,...Np(s)))},op=function(e,...t){return Sp(new e(...Np(t)))};class ap extends Ld{constructor(e,t){super(),this.shaderNode=e,this.inputNodes=t}getNodeType(e){return this.shaderNode.nodeType||this.getOutputNode(e).getNodeType(e)}call(e){const{shaderNode:t,inputNodes:s}=this,i=e.getNodeProperties(t);if(i.onceOutput)return i.onceOutput;let r=null;if(t.layout){let i=sp.get(e.constructor);void 0===i&&(i=new WeakMap,sp.set(e.constructor,i));let n=i.get(t);void 0===n&&(n=Sp(e.buildFunctionNode(t)),i.set(t,n)),null!==e.currentFunctionNode&&e.currentFunctionNode.includes.push(n),r=Sp(n.call(s))}else{const i=t.jsFunc,n=null!==s?i(s,e):i(e);r=Sp(n)}return t.once&&(i.onceOutput=r),r}getOutputNode(e){const t=e.getNodeProperties(this);return null===t.outputNode&&(t.outputNode=this.setupOutput(e)),t.outputNode}setup(e){return this.getOutputNode(e)}setupOutput(e){return e.addStack(),e.stack.outputNode=this.call(e),e.removeStack()}generate(e,t){return this.getOutputNode(e).build(e,t)}}class hp extends Ld{constructor(e,t){super(t),this.jsFunc=e,this.layout=null,this.global=!0,this.once=!1}setLayout(e){return this.layout=e,this}call(e=null){return Mp(e),Sp(new ap(this,e))}setup(){return this.call()}}const up=[!1,!0],lp=[0,1,2,3],cp=[-1,-2],dp=[.5,1.5,1/3,1e-6,1e6,Math.PI,2*Math.PI,1/Math.PI,2/Math.PI,1/(2*Math.PI),Math.PI/2],pp=new Map;for(const e of up)pp.set(e,new Xd(e));const mp=new Map;for(const e of lp)mp.set(e,new Xd(e,"uint"));const gp=new Map([...mp].map((e=>new Xd(e.value,"int"))));for(const e of cp)gp.set(e,new Xd(e,"int"));const fp=new Map([...gp].map((e=>new Xd(e.value))));for(const e of dp)fp.set(e,new Xd(e));for(const e of dp)fp.set(-e,new Xd(-e));const yp={bool:pp,uint:mp,ints:gp,float:fp},xp=new Map([...pp,...fp]),bp=(e,t)=>xp.has(e)?xp.get(e):!0===e.isNode?e:new Xd(e,t),vp=function(e,t=null){return(...s)=>{if((0===s.length||!["bool","float","int","uint"].includes(e)&&s.every((e=>"object"!=typeof e)))&&(s=[Nd(e,...s)]),1===s.length&&null!==t&&t.has(s[0]))return Sp(t.get(s[0]));if(1===s.length){const t=bp(s[0],e);return(e=>{try{return e.getNodeType()}catch(e){return}})(t)===e?Sp(t):Sp(new Dd(t,e))}const i=s.map((e=>bp(e)));return Sp(new Gd(i,e))}},Tp=e=>"object"==typeof e&&null!==e?e.value:e,_p=e=>null!=e?e.nodeType||e.convertTo||("string"==typeof e?e:null):null;function wp(e,t){return new Proxy(new hp(e,t),ep)}const Sp=(e,t=null)=>function(e,t=null){const s=Md(e);if("node"===s){let t=tp.get(e);return void 0===t&&(t=new Proxy(e,ep),tp.set(e,t),tp.set(t,t)),t}return null===t&&("float"===s||"boolean"===s)||s&&"shader"!==s&&"string"!==s?Sp(bp(e,t)):"shader"===s?Rp(e):e}(e,t),Mp=(e,t=null)=>new ip(e,t),Np=(e,t=null)=>new rp(e,t),Ap=(...e)=>new np(...e),Cp=(...e)=>new op(...e),Rp=(e,t)=>{const s=new wp(e,t),i=(...e)=>{let t;return Mp(e),t=e[0]&&e[0].isNode?[...e]:e[0],s.call(t)};return i.shaderNode=s,i.setLayout=e=>(s.setLayout(e),i),i.once=()=>(s.once=!0,i),i},Ep=(...e)=>(console.warn("TSL.ShaderNode: tslFn() has been renamed to Fn()."),Rp(...e));Jd("toGlobal",(e=>(e.global=!0,e)));const Bp=e=>{Yd=e},Ip=()=>Yd,Pp=(...e)=>Yd.If(...e);function Fp(e){return Yd&&Yd.add(e),e}Jd("append",Fp);const zp=new vp("color"),Up=new vp("float",yp.float),Op=new vp("int",yp.ints),Lp=new vp("uint",yp.uint),Vp=new vp("bool",yp.bool),Dp=new vp("vec2"),kp=new vp("ivec2"),Gp=new vp("uvec2"),Wp=new vp("bvec2"),jp=new vp("vec3"),Hp=new vp("ivec3"),qp=new vp("uvec3"),$p=new vp("bvec3"),Xp=new vp("vec4"),Yp=new vp("ivec4"),Zp=new vp("uvec4"),Jp=new vp("bvec4"),Kp=new vp("mat2"),Qp=new vp("mat3"),em=new vp("mat4"),tm=(e="")=>Sp(new Xd(e,"string")),sm=e=>Sp(new Xd(e,"ArrayBuffer"));Jd("toColor",zp),Jd("toFloat",Up),Jd("toInt",Op),Jd("toUint",Lp),Jd("toBool",Vp),Jd("toVec2",Dp),Jd("toIVec2",kp),Jd("toUVec2",Gp),Jd("toBVec2",Wp),Jd("toVec3",jp),Jd("toIVec3",Hp),Jd("toUVec3",qp),Jd("toBVec3",$p),Jd("toVec4",Xp),Jd("toIVec4",Yp),Jd("toUVec4",Zp),Jd("toBVec4",Jp),Jd("toMat2",Kp),Jd("toMat3",Qp),Jd("toMat4",em);const im=Ap(Vd),rm=(e,t)=>Sp(new Dd(Sp(e),t)),nm=(e,t)=>Sp(new jd(Sp(e),t));Jd("element",im),Jd("convert",rm);class om extends Ld{static get type(){return"UniformGroupNode"}constructor(e,t=!1,s=1){super("string"),this.name=e,this.version=0,this.shared=t,this.order=s,this.isUniformGroup=!0}set needsUpdate(e){!0===e&&this.version++}serialize(e){super.serialize(e),e.name=this.name,e.version=this.version,e.shared=this.shared}deserialize(e){super.deserialize(e),this.name=e.name,this.version=e.version,this.shared=e.shared}}const am=e=>new om(e),hm=(e,t=0)=>new om(e,!0,t),um=hm("frame"),lm=hm("render"),cm=am("object");class dm extends $d{static get type(){return"UniformNode"}constructor(e,t=null){super(e,t),this.isUniformNode=!0,this.name="",this.groupNode=cm}label(e){return this.name=e,this}setGroup(e){return this.groupNode=e,this}getGroup(){return this.groupNode}getUniformHash(e){return this.getHash(e)}onUpdate(e,t){const s=this.getSelf();return e=e.bind(s),super.onUpdate((t=>{const i=e(t,s);void 0!==i&&(this.value=i)}),t)}generate(e,t){const s=this.getNodeType(e),i=this.getUniformHash(e);let r=e.getNodeFromHash(i);void 0===r&&(e.setHashNode(this,i),r=this);const n=r.getInputType(e),o=e.getUniformFromNode(r,n,e.shaderStage,this.name||e.context.label),a=e.getPropertyName(o);return void 0!==e.context.label&&delete e.context.label,e.format(a,s,t)}}const pm=(e,t)=>{const s=_p(t||e),i=e&&!0===e.isNode?e.node&&e.node.value||e.value:e;return Sp(new dm(i,s))};class mm extends Ld{static get type(){return"PropertyNode"}constructor(e,t=null,s=!1){super(e),this.name=t,this.varying=s,this.isPropertyNode=!0}getHash(e){return this.name||super.getHash(e)}isGlobal(){return!0}generate(e){let t;return!0===this.varying?(t=e.getVaryingFromNode(this,this.name),t.needsInterpolation=!0):t=e.getVarFromNode(this,this.name),e.getPropertyName(t)}}const gm=(e,t)=>Sp(new mm(e,t)),fm=(e,t)=>Sp(new mm(e,t,!0)),ym=Cp(mm,"vec4","DiffuseColor"),xm=Cp(mm,"vec3","EmissiveColor"),bm=Cp(mm,"float","Roughness"),vm=Cp(mm,"float","Metalness"),Tm=Cp(mm,"float","Clearcoat"),_m=Cp(mm,"float","ClearcoatRoughness"),wm=Cp(mm,"vec3","Sheen"),Sm=Cp(mm,"float","SheenRoughness"),Mm=Cp(mm,"float","Iridescence"),Nm=Cp(mm,"float","IridescenceIOR"),Am=Cp(mm,"float","IridescenceThickness"),Cm=Cp(mm,"float","AlphaT"),Rm=Cp(mm,"float","Anisotropy"),Em=Cp(mm,"vec3","AnisotropyT"),Bm=Cp(mm,"vec3","AnisotropyB"),Im=Cp(mm,"color","SpecularColor"),Pm=Cp(mm,"float","SpecularF90"),Fm=Cp(mm,"float","Shininess"),zm=Cp(mm,"vec4","Output"),Um=Cp(mm,"float","dashSize"),Om=Cp(mm,"float","gapSize"),Lm=Cp(mm,"float","pointWidth"),Vm=Cp(mm,"float","IOR"),Dm=Cp(mm,"float","Transmission"),km=Cp(mm,"float","Thickness"),Gm=Cp(mm,"float","AttenuationDistance"),Wm=Cp(mm,"color","AttenuationColor"),jm=Cp(mm,"float","Dispersion");class Hm extends kd{static get type(){return"AssignNode"}constructor(e,t){super(),this.targetNode=e,this.sourceNode=t}hasDependencies(){return!1}getNodeType(e,t){return"void"!==t?this.targetNode.getNodeType(e):"void"}needsSplitAssign(e){const{targetNode:t}=this;if(!1===e.isAvailable("swizzleAssign")&&t.isSplitNode&&t.components.length>1){const s=e.getTypeLength(t.node.getNodeType(e));return Ud.join("").slice(0,s)!==t.components}return!1}generate(e,t){const{targetNode:s,sourceNode:i}=this,r=this.needsSplitAssign(e),n=s.getNodeType(e),o=s.context({assign:!0}).build(e),a=i.build(e,n),h=i.getNodeType(e),u=e.getDataFromNode(this);let l;if(!0===u.initialized)"void"!==t&&(l=o);else if(r){const i=e.getVarFromNode(this,null,n),r=e.getPropertyName(i);e.addLineFlowCode(`${r} = ${a}`,this);const h=s.node.context({assign:!0}).build(e);for(let t=0;t(t=t.length>1||t[0]&&!0===t[0].isNode?Np(t):Mp(t[0]),Sp(new $m(Sp(e),t)));Jd("call",Xm);class Ym extends kd{static get type(){return"OperatorNode"}constructor(e,t,s,...i){if(super(),i.length>0){let r=new Ym(e,t,s);for(let t=0;t>"===s||"<<"===s)return e.getIntegerType(n);if("!"===s||"=="===s||"&&"===s||"||"===s||"^^"===s)return"bool";if("<"===s||">"===s||"<="===s||">="===s){const s=t?e.getTypeLength(t):Math.max(e.getTypeLength(n),e.getTypeLength(o));return s>1?`bvec${s}`:"bool"}return"float"===n&&e.isMatrix(o)?o:e.isMatrix(n)&&e.isVector(o)?e.getVectorFromMatrix(n):e.isVector(n)&&e.isMatrix(o)?e.getVectorFromMatrix(o):e.getTypeLength(o)>e.getTypeLength(n)?o:n}generate(e,t){const s=this.op,i=this.aNode,r=this.bNode,n=this.getNodeType(e,t);let o=null,a=null;"void"!==n?(o=i.getNodeType(e),a=void 0!==r?r.getNodeType(e):null,"<"===s||">"===s||"<="===s||">="===s||"=="===s?e.isVector(o)?a=o:o!==a&&(o=a="float"):">>"===s||"<<"===s?(o=n,a=e.changeComponentType(a,"uint")):e.isMatrix(o)&&e.isVector(a)?a=e.getVectorFromMatrix(o):o=e.isVector(o)&&e.isMatrix(a)?e.getVectorFromMatrix(a):a=n):o=a=n;const h=i.build(e,o),u=void 0!==r?r.build(e,a):null,l=e.getTypeLength(t),c=e.getFunctionOperator(s);return"void"!==t?"<"===s&&l>1?e.useComparisonMethod?e.format(`${e.getMethod("lessThan",t)}( ${h}, ${u} )`,n,t):e.format(`( ${h} < ${u} )`,n,t):"<="===s&&l>1?e.useComparisonMethod?e.format(`${e.getMethod("lessThanEqual",t)}( ${h}, ${u} )`,n,t):e.format(`( ${h} <= ${u} )`,n,t):">"===s&&l>1?e.useComparisonMethod?e.format(`${e.getMethod("greaterThan",t)}( ${h}, ${u} )`,n,t):e.format(`( ${h} > ${u} )`,n,t):">="===s&&l>1?e.useComparisonMethod?e.format(`${e.getMethod("greaterThanEqual",t)}( ${h}, ${u} )`,n,t):e.format(`( ${h} >= ${u} )`,n,t):"!"===s||"~"===s?e.format(`(${s}${h})`,o,t):c?e.format(`${c}( ${h}, ${u} )`,n,t):e.format(`( ${h} ${s} ${u} )`,n,t):"void"!==o?c?e.format(`${c}( ${h}, ${u} )`,n,t):e.format(`${h} ${s} ${u}`,n,t):void 0}serialize(e){super.serialize(e),e.op=this.op}deserialize(e){super.deserialize(e),this.op=e.op}}const Zm=Ap(Ym,"+"),Jm=Ap(Ym,"-"),Km=Ap(Ym,"*"),Qm=Ap(Ym,"/"),eg=Ap(Ym,"%"),tg=Ap(Ym,"=="),sg=Ap(Ym,"!="),ig=Ap(Ym,"<"),rg=Ap(Ym,">"),ng=Ap(Ym,"<="),og=Ap(Ym,">="),ag=Ap(Ym,"&&"),hg=Ap(Ym,"||"),ug=Ap(Ym,"!"),lg=Ap(Ym,"^^"),cg=Ap(Ym,"&"),dg=Ap(Ym,"~"),pg=Ap(Ym,"|"),mg=Ap(Ym,"^"),gg=Ap(Ym,"<<"),fg=Ap(Ym,">>");Jd("add",Zm),Jd("sub",Jm),Jd("mul",Km),Jd("div",Qm),Jd("modInt",eg),Jd("equal",tg),Jd("notEqual",sg),Jd("lessThan",ig),Jd("greaterThan",rg),Jd("lessThanEqual",ng),Jd("greaterThanEqual",og),Jd("and",ag),Jd("or",hg),Jd("not",ug),Jd("xor",lg),Jd("bitAnd",cg),Jd("bitNot",dg),Jd("bitOr",pg),Jd("bitXor",mg),Jd("shiftLeft",gg),Jd("shiftRight",fg);const yg=(...e)=>(console.warn("TSL.OperatorNode: .remainder() has been renamed to .modInt()."),eg(...e));Jd("remainder",yg);class xg extends kd{static get type(){return"MathNode"}constructor(e,t,s=null,i=null){super(),this.method=e,this.aNode=t,this.bNode=s,this.cNode=i}getInputType(e){const t=this.aNode.getNodeType(e),s=this.bNode?this.bNode.getNodeType(e):null,i=this.cNode?this.cNode.getNodeType(e):null,r=e.isMatrix(t)?0:e.getTypeLength(t),n=e.isMatrix(s)?0:e.getTypeLength(s),o=e.isMatrix(i)?0:e.getTypeLength(i);return r>n&&r>o?t:n>o?s:o>r?i:t}getNodeType(e){const t=this.method;return t===xg.LENGTH||t===xg.DISTANCE||t===xg.DOT?"float":t===xg.CROSS?"vec3":t===xg.ALL?"bool":t===xg.EQUALS?e.changeComponentType(this.aNode.getNodeType(e),"bool"):t===xg.MOD?this.aNode.getNodeType(e):this.getInputType(e)}generate(e,t){const s=this.method,i=this.getNodeType(e),r=this.getInputType(e),n=this.aNode,o=this.bNode,a=this.cNode,h=!0===e.renderer.isWebGLRenderer;if(s===xg.TRANSFORM_DIRECTION){let s=n,i=o;e.isMatrix(s.getNodeType(e))?i=Xp(jp(i),0):s=Xp(jp(s),0);const r=Km(s,i).xyz;return Ug(r).build(e,t)}if(s===xg.NEGATE)return e.format("( - "+n.build(e,r)+" )",i,t);if(s===xg.ONE_MINUS)return Jm(1,n).build(e,t);if(s===xg.RECIPROCAL)return Qm(1,n).build(e,t);if(s===xg.DIFFERENCE)return jg(Jm(n,o)).build(e,t);{const u=[];return s===xg.CROSS||s===xg.MOD?u.push(n.build(e,i),o.build(e,i)):h&&s===xg.STEP?u.push(n.build(e,1===e.getTypeLength(n.getNodeType(e))?"float":r),o.build(e,r)):h&&(s===xg.MIN||s===xg.MAX)||s===xg.MOD?u.push(n.build(e,r),o.build(e,1===e.getTypeLength(o.getNodeType(e))?"float":r)):s===xg.REFRACT?u.push(n.build(e,r),o.build(e,r),a.build(e,"float")):s===xg.MIX?u.push(n.build(e,r),o.build(e,r),a.build(e,1===e.getTypeLength(a.getNodeType(e))?"float":r)):(u.push(n.build(e,r)),null!==o&&u.push(o.build(e,r)),null!==a&&u.push(a.build(e,r))),e.format(`${e.getMethod(s,i)}( ${u.join(", ")} )`,i,t)}}serialize(e){super.serialize(e),e.method=this.method}deserialize(e){super.deserialize(e),this.method=e.method}}xg.ALL="all",xg.ANY="any",xg.EQUALS="equals",xg.RADIANS="radians",xg.DEGREES="degrees",xg.EXP="exp",xg.EXP2="exp2",xg.LOG="log",xg.LOG2="log2",xg.SQRT="sqrt",xg.INVERSE_SQRT="inversesqrt",xg.FLOOR="floor",xg.CEIL="ceil",xg.NORMALIZE="normalize",xg.FRACT="fract",xg.SIN="sin",xg.COS="cos",xg.TAN="tan",xg.ASIN="asin",xg.ACOS="acos",xg.ATAN="atan",xg.ABS="abs",xg.SIGN="sign",xg.LENGTH="length",xg.NEGATE="negate",xg.ONE_MINUS="oneMinus",xg.DFDX="dFdx",xg.DFDY="dFdy",xg.ROUND="round",xg.RECIPROCAL="reciprocal",xg.TRUNC="trunc",xg.FWIDTH="fwidth",xg.BITCAST="bitcast",xg.TRANSPOSE="transpose",xg.ATAN2="atan2",xg.MIN="min",xg.MAX="max",xg.MOD="mod",xg.STEP="step",xg.REFLECT="reflect",xg.DISTANCE="distance",xg.DIFFERENCE="difference",xg.DOT="dot",xg.CROSS="cross",xg.POW="pow",xg.TRANSFORM_DIRECTION="transformDirection",xg.MIX="mix",xg.CLAMP="clamp",xg.REFRACT="refract",xg.SMOOTHSTEP="smoothstep",xg.FACEFORWARD="faceforward";const bg=Up(1e-6),vg=Up(1e6),Tg=Up(Math.PI),_g=Up(2*Math.PI),wg=Ap(xg,xg.ALL),Sg=Ap(xg,xg.ANY),Mg=Ap(xg,xg.EQUALS),Ng=Ap(xg,xg.RADIANS),Ag=Ap(xg,xg.DEGREES),Cg=Ap(xg,xg.EXP),Rg=Ap(xg,xg.EXP2),Eg=Ap(xg,xg.LOG),Bg=Ap(xg,xg.LOG2),Ig=Ap(xg,xg.SQRT),Pg=Ap(xg,xg.INVERSE_SQRT),Fg=Ap(xg,xg.FLOOR),zg=Ap(xg,xg.CEIL),Ug=Ap(xg,xg.NORMALIZE),Og=Ap(xg,xg.FRACT),Lg=Ap(xg,xg.SIN),Vg=Ap(xg,xg.COS),Dg=Ap(xg,xg.TAN),kg=Ap(xg,xg.ASIN),Gg=Ap(xg,xg.ACOS),Wg=Ap(xg,xg.ATAN),jg=Ap(xg,xg.ABS),Hg=Ap(xg,xg.SIGN),qg=Ap(xg,xg.LENGTH),$g=Ap(xg,xg.NEGATE),Xg=Ap(xg,xg.ONE_MINUS),Yg=Ap(xg,xg.DFDX),Zg=Ap(xg,xg.DFDY),Jg=Ap(xg,xg.ROUND),Kg=Ap(xg,xg.RECIPROCAL),Qg=Ap(xg,xg.TRUNC),ef=Ap(xg,xg.FWIDTH),tf=Ap(xg,xg.BITCAST),sf=Ap(xg,xg.TRANSPOSE),rf=Ap(xg,xg.ATAN2),nf=Ap(xg,xg.MIN),of=Ap(xg,xg.MAX),af=Ap(xg,xg.MOD),hf=Ap(xg,xg.STEP),uf=Ap(xg,xg.REFLECT),lf=Ap(xg,xg.DISTANCE),cf=Ap(xg,xg.DIFFERENCE),df=Ap(xg,xg.DOT),pf=Ap(xg,xg.CROSS),mf=Ap(xg,xg.POW),gf=Ap(xg,xg.POW,2),ff=Ap(xg,xg.POW,3),yf=Ap(xg,xg.POW,4),xf=Ap(xg,xg.TRANSFORM_DIRECTION),bf=e=>Km(Hg(e),mf(jg(e),1/3)),vf=e=>df(e,e),Tf=Ap(xg,xg.MIX),_f=(e,t=0,s=1)=>Sp(new xg(xg.CLAMP,Sp(e),Sp(t),Sp(s))),wf=e=>_f(e),Sf=Ap(xg,xg.REFRACT),Mf=Ap(xg,xg.SMOOTHSTEP),Nf=Ap(xg,xg.FACEFORWARD),Af=Rp((([e])=>{const t=df(e.xy,Dp(12.9898,78.233)),s=af(t,Tg);return Og(Lg(s).mul(43758.5453))})),Cf=(e,t,s)=>Tf(t,s,e),Rf=(e,t,s)=>Mf(t,s,e);Jd("all",wg),Jd("any",Sg),Jd("equals",Mg),Jd("radians",Ng),Jd("degrees",Ag),Jd("exp",Cg),Jd("exp2",Rg),Jd("log",Eg),Jd("log2",Bg),Jd("sqrt",Ig),Jd("inverseSqrt",Pg),Jd("floor",Fg),Jd("ceil",zg),Jd("normalize",Ug),Jd("fract",Og),Jd("sin",Lg),Jd("cos",Vg),Jd("tan",Dg),Jd("asin",kg),Jd("acos",Gg),Jd("atan",Wg),Jd("abs",jg),Jd("sign",Hg),Jd("length",qg),Jd("lengthSq",vf),Jd("negate",$g),Jd("oneMinus",Xg),Jd("dFdx",Yg),Jd("dFdy",Zg),Jd("round",Jg),Jd("reciprocal",Kg),Jd("trunc",Qg),Jd("fwidth",ef),Jd("atan2",rf),Jd("min",nf),Jd("max",of),Jd("mod",af),Jd("step",hf),Jd("reflect",uf),Jd("distance",lf),Jd("dot",df),Jd("cross",pf),Jd("pow",mf),Jd("pow2",gf),Jd("pow3",ff),Jd("pow4",yf),Jd("transformDirection",xf),Jd("mix",Cf),Jd("clamp",_f),Jd("refract",Sf),Jd("smoothstep",Rf),Jd("faceForward",Nf),Jd("difference",cf),Jd("saturate",wf),Jd("cbrt",bf),Jd("transpose",sf),Jd("rand",Af);class Ef extends Ld{static get type(){return"ConditionalNode"}constructor(e,t,s=null){super(),this.condNode=e,this.ifNode=t,this.elseNode=s}getNodeType(e){const t=this.ifNode.getNodeType(e);if(null!==this.elseNode){const s=this.elseNode.getNodeType(e);if(e.getTypeLength(s)>e.getTypeLength(t))return s}return t}setup(e){const t=this.condNode.cache(),s=this.ifNode.cache(),i=this.elseNode?this.elseNode.cache():null,r=e.context.nodeBlock;e.getDataFromNode(s).parentNodeBlock=r,null!==i&&(e.getDataFromNode(i).parentNodeBlock=r);const n=e.getNodeProperties(this);n.condNode=t,n.ifNode=s.context({nodeBlock:s}),n.elseNode=i?i.context({nodeBlock:i}):null}generate(e,t){const s=this.getNodeType(e),i=e.getDataFromNode(this);if(void 0!==i.nodeProperty)return i.nodeProperty;const{condNode:r,ifNode:n,elseNode:o}=e.getNodeProperties(this),a="void"!==t,h=a?gm(s).build(e):"";i.nodeProperty=h;const u=r.build(e,"bool");e.addFlowCode(`\n${e.tab}if ( ${u} ) {\n\n`).addFlowTab();let l=n.build(e,s);if(l&&(l=a?h+" = "+l+";":"return "+l+";"),e.removeFlowTab().addFlowCode(e.tab+"\t"+l+"\n\n"+e.tab+"}"),null!==o){e.addFlowCode(" else {\n\n").addFlowTab();let t=o.build(e,s);t&&(t=a?h+" = "+t+";":"return "+t+";"),e.removeFlowTab().addFlowCode(e.tab+"\t"+t+"\n\n"+e.tab+"}\n\n")}else e.addFlowCode("\n\n");return e.format(h,s,t)}}const Bf=Ap(Ef);Jd("select",Bf);const If=(...e)=>(console.warn("TSL.ConditionalNode: cond() has been renamed to select()."),Bf(...e));Jd("cond",If);class Pf extends Ld{static get type(){return"ContextNode"}constructor(e,t={}){super(),this.isContextNode=!0,this.node=e,this.value=t}getScope(){return this.node.getScope()}getNodeType(e){return this.node.getNodeType(e)}analyze(e){this.node.build(e)}setup(e){const t=e.getContext();e.setContext({...e.context,...this.value});const s=this.node.build(e);return e.setContext(t),s}generate(e,t){const s=e.getContext();e.setContext({...e.context,...this.value});const i=this.node.build(e,t);return e.setContext(s),i}}const Ff=Ap(Pf),zf=(e,t)=>Ff(e,{label:t});Jd("context",Ff),Jd("label",zf);class Uf extends Ld{static get type(){return"VarNode"}constructor(e,t=null){super(),this.node=e,this.name=t,this.global=!0,this.isVarNode=!0}getHash(e){return this.name||super.getHash(e)}getNodeType(e){return this.node.getNodeType(e)}generate(e){const{node:t,name:s}=this,i=e.getVarFromNode(this,s,e.getVectorType(this.getNodeType(e))),r=e.getPropertyName(i),n=t.build(e,i.type);return e.addLineFlowCode(`${r} = ${n}`,this),r}}const Of=Ap(Uf);Jd("temp",Of),Jd("toVar",((...e)=>Of(...e).append()));class Lf extends Ld{static get type(){return"VaryingNode"}constructor(e,t=null){super(),this.node=e,this.name=t,this.isVaryingNode=!0}isGlobal(){return!0}getHash(e){return this.name||super.getHash(e)}getNodeType(e){return this.node.getNodeType(e)}setupVarying(e){const t=e.getNodeProperties(this);let s=t.varying;if(void 0===s){const i=this.name,r=this.getNodeType(e);t.varying=s=e.getVaryingFromNode(this,i,r),t.node=this.node}return s.needsInterpolation||(s.needsInterpolation="fragment"===e.shaderStage),s}setup(e){this.setupVarying(e)}analyze(e){return this.setupVarying(e),this.node.analyze(e)}generate(e){const t=e.getNodeProperties(this),s=this.setupVarying(e);if(void 0===t.propertyName){const i=this.getNodeType(e),r=e.getPropertyName(s,Ed.VERTEX);e.flowNodeFromShaderStage(Ed.VERTEX,this.node,i,r),t.propertyName=r}return e.getPropertyName(s)}}const Vf=Ap(Lf);Jd("varying",Vf);const Df="WorkingColorSpace",kf="OutputColorSpace";function Gf(e){let t=null;return e===Jt?t="Linear":e===Zt&&(t="sRGB"),t}function Wf(e,t){return Gf(e)+"To"+Gf(t)}class jf extends kd{static get type(){return"ColorSpaceNode"}constructor(e,t,s){super("vec4"),this.colorNode=e,this.source=t,this.target=s}getColorSpace(e,t){return t===Df?ci.workingColorSpace:t===kf?e.context.outputColorSpace||e.renderer.outputColorSpace:t}setup(e){const{renderer:t}=e,{colorNode:s}=this,i=this.getColorSpace(e,this.source),r=this.getColorSpace(e,this.target);if(i===r)return s;const n=Wf(i,r);let o=null;const a=t.nodes.library.getColorSpaceFunction(n);return null!==a?o=Xp(a(s.rgb),s.a):(console.error("ColorSpaceNode: Unsupported Color Space configuration.",n),o=s),o}}const Hf=e=>Sp(new jf(Sp(e),Df,kf)),qf=e=>Sp(new jf(Sp(e),kf,Df)),$f=(e,t)=>Sp(new jf(Sp(e),Df,t)),Xf=(e,t)=>Sp(new jf(Sp(e),t,Df));Jd("toOutputColorSpace",Hf),Jd("toWorkingColorSpace",qf),Jd("workingToColorSpace",$f),Jd("colorSpaceToWorking",Xf);let Yf=class extends Vd{static get type(){return"ReferenceElementNode"}constructor(e,t){super(e,t),this.referenceNode=e,this.isReferenceElementNode=!0}getNodeType(){return this.referenceNode.uniformType}generate(e){const t=super.generate(e),s=this.referenceNode.getNodeType(),i=this.getNodeType();return e.format(t,s,i)}};class Zf extends Ld{static get type(){return"ReferenceBaseNode"}constructor(e,t,s=null,i=null){super(),this.property=e,this.uniformType=t,this.object=s,this.count=i,this.properties=e.split("."),this.reference=s,this.node=null,this.group=null,this.updateType=Bd.OBJECT}setGroup(e){return this.group=e,this}element(e){return Sp(new Yf(this,Sp(e)))}setNodeType(e){const t=pm(null,e).getSelf();null!==this.group&&t.setGroup(this.group),this.node=t}getNodeType(e){return null===this.node&&(this.updateReference(e),this.updateValue()),this.node.getNodeType(e)}getValueFromReference(e=this.reference){const{properties:t}=this;let s=e[t[0]];for(let e=1;eSp(new Jf(e,t,s));class Qf extends kd{static get type(){return"ToneMappingNode"}constructor(e,t=ty,s=null){super("vec3"),this.toneMapping=e,this.exposureNode=t,this.colorNode=s}getCacheKey(){return _d(super.getCacheKey(),this.toneMapping)}setup(e){const t=this.colorNode||e.context.color,s=this.toneMapping;if(0===s)return t;let i=null;const r=e.renderer.nodes.library.getToneMappingFunction(s);return null!==r?i=Xp(r(t.rgb,this.exposureNode),t.a):(console.error("ToneMappingNode: Unsupported Tone Mapping configuration.",s),i=t),i}}const ey=(e,t,s)=>Sp(new Qf(e,Sp(t),Sp(s))),ty=Kf("toneMappingExposure","float");Jd("toneMapping",((e,t,s)=>ey(t,s,e)));class sy extends $d{static get type(){return"BufferAttributeNode"}constructor(e,t=null,s=0,i=0){super(e,t),this.isBufferNode=!0,this.bufferType=t,this.bufferStride=s,this.bufferOffset=i,this.usage=Cs,this.instanced=!1,this.attribute=null,this.global=!0,e&&!0===e.isBufferAttribute&&(this.attribute=e,this.usage=e.usage,this.instanced=e.isInstancedBufferAttribute)}getHash(e){if(0===this.bufferStride&&0===this.bufferOffset){let t=e.globalCache.getData(this.value);return void 0===t&&(t={node:this},e.globalCache.setData(this.value,t)),t.node.uuid}return this.uuid}getNodeType(e){return null===this.bufferType&&(this.bufferType=e.getTypeFromAttribute(this.attribute)),this.bufferType}setup(e){if(null!==this.attribute)return;const t=this.getNodeType(e),s=this.value,i=e.getTypeLength(t),r=this.bufferStride||i,n=this.bufferOffset,o=!0===s.isInterleavedBuffer?s:new so(s,r),a=new ro(o,i,n);o.setUsage(this.usage),this.attribute=a,this.attribute.isInstancedBufferAttribute=this.instanced}generate(e){const t=this.getNodeType(e),s=e.getBufferAttributeFromNode(this,t),i=e.getPropertyName(s);let r=null;if("vertex"===e.shaderStage||"compute"===e.shaderStage)this.name=i,r=i;else{r=Vf(this).build(e,t)}return r}getInputType(){return"bufferAttribute"}setUsage(e){return this.usage=e,this.attribute&&!0===this.attribute.isBufferAttribute&&(this.attribute.usage=e),this}setInstanced(e){return this.instanced=e,this}}const iy=(e,t,s,i)=>Sp(new sy(e,t,s,i)),ry=(e,t,s,i)=>iy(e,t,s,i).setUsage(Rs),ny=(e,t,s,i)=>iy(e,t,s,i).setInstanced(!0),oy=(e,t,s,i)=>ry(e,t,s,i).setInstanced(!0);Jd("toAttribute",(e=>iy(e.value)));class ay extends Ld{static get type(){return"ComputeNode"}constructor(e,t,s=[64]){super("void"),this.isComputeNode=!0,this.computeNode=e,this.count=t,this.workgroupSize=s,this.dispatchCount=0,this.version=1,this.updateBeforeType=Bd.OBJECT,this.updateDispatchCount()}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(e){!0===e&&this.version++}updateDispatchCount(){const{count:e,workgroupSize:t}=this;let s=t[0];for(let e=1;eSp(new ay(Sp(e),t,s));Jd("compute",hy);class uy extends Ld{static get type(){return"CacheNode"}constructor(e,t=!0){super(),this.node=e,this.parent=t,this.isCacheNode=!0}getNodeType(e){return this.node.getNodeType(e)}build(e,...t){const s=e.getCache(),i=e.getCacheFromNode(this,this.parent);e.setCache(i);const r=this.node.build(e,...t);return e.setCache(s),r}}const ly=(e,...t)=>Sp(new uy(Sp(e),...t));Jd("cache",ly);class cy extends Ld{static get type(){return"BypassNode"}constructor(e,t){super(),this.isBypassNode=!0,this.outputNode=e,this.callNode=t}getNodeType(e){return this.outputNode.getNodeType(e)}generate(e){const t=this.callNode.build(e,"void");return""!==t&&e.addLineFlowCode(t,this),this.outputNode.build(e)}}const dy=Ap(cy);Jd("bypass",dy);class py extends Ld{static get type(){return"RemapNode"}constructor(e,t,s,i=Up(0),r=Up(1)){super(),this.node=e,this.inLowNode=t,this.inHighNode=s,this.outLowNode=i,this.outHighNode=r,this.doClamp=!0}setup(){const{node:e,inLowNode:t,inHighNode:s,outLowNode:i,outHighNode:r,doClamp:n}=this;let o=e.sub(t).div(s.sub(t));return!0===n&&(o=o.clamp()),o.mul(r.sub(i)).add(i)}}const my=Ap(py,null,null,{doClamp:!1}),gy=Ap(py);Jd("remap",my),Jd("remapClamp",gy);class fy extends Ld{static get type(){return"ExpressionNode"}constructor(e="",t="void"){super(t),this.snippet=e}generate(e,t){const s=this.getNodeType(e),i=this.snippet;if("void"!==s)return e.format(`( ${i} )`,s,t);e.addLineFlowCode(i,this)}}const yy=Ap(fy),xy=e=>(e?Bf(e,yy("discard")):yy("discard")).append(),by=()=>yy("return").append();Jd("discard",xy);class vy extends kd{static get type(){return"RenderOutputNode"}constructor(e,t,s){super("vec4"),this.colorNode=e,this.toneMapping=t,this.outputColorSpace=s,this.isRenderOutput=!0}setup({context:e}){let t=this.colorNode||e.color;const s=(null!==this.toneMapping?this.toneMapping:e.toneMapping)||0,i=(null!==this.outputColorSpace?this.outputColorSpace:e.outputColorSpace)||Yt;return 0!==s&&(t=t.toneMapping(s)),i!==Yt&&i!==ci.workingColorSpace&&(t=t.workingToColorSpace(i)),t}}const Ty=(e,t=null,s=null)=>Sp(new vy(Sp(e),t,s));function _y(e){console.warn("THREE.TSLBase: AddNodeElement has been removed in favor of tree-shaking. Trying add",e)}Jd("renderOutput",Ty);class wy extends Ld{static get type(){return"AttributeNode"}constructor(e,t=null){super(t),this.global=!0,this._attributeName=e}getHash(e){return this.getAttributeName(e)}getNodeType(e){let t=this.nodeType;if(null===t){const s=this.getAttributeName(e);if(e.hasGeometryAttribute(s)){const i=e.geometry.getAttribute(s);t=e.getTypeFromAttribute(i)}else t="float"}return t}setAttributeName(e){return this._attributeName=e,this}getAttributeName(){return this._attributeName}generate(e){const t=this.getAttributeName(e),s=this.getNodeType(e);if(!0===e.hasGeometryAttribute(t)){const i=e.geometry.getAttribute(t),r=e.getTypeFromAttribute(i),n=e.getAttribute(t,r);if("vertex"===e.shaderStage)return e.format(n.name,r,s);return Vf(this).build(e,s)}return console.warn(`AttributeNode: Vertex attribute "${t}" not found on geometry.`),e.generateConst(s)}serialize(e){super.serialize(e),e.global=this.global,e._attributeName=this._attributeName}deserialize(e){super.deserialize(e),this.global=e.global,this._attributeName=e._attributeName}}const Sy=(e,t)=>Sp(new wy(e,t)),My=e=>Sy("uv"+(e>0?e:""),"vec2");class Ny extends Ld{static get type(){return"TextureSizeNode"}constructor(e,t=null){super("uvec2"),this.isTextureSizeNode=!0,this.textureNode=e,this.levelNode=t}generate(e,t){const s=this.textureNode.build(e,"property"),i=null===this.levelNode?"0":this.levelNode.build(e,"int");return e.format(`${e.getMethod("textureDimensions")}( ${s}, ${i} )`,this.getNodeType(e),t)}}const Ay=Ap(Ny);class Cy extends dm{static get type(){return"MaxMipLevelNode"}constructor(e){super(0),this._textureNode=e,this.updateType=Bd.FRAME}get textureNode(){return this._textureNode}get texture(){return this._textureNode.value}update(){const e=this.texture,t=e.images,s=t&&t.length>0?t[0]&&t[0].image||t[0]:e.image;if(s&&void 0!==s.width){const{width:e,height:t}=s;this.value=Math.log2(Math.max(e,t))}}}const Ry=Ap(Cy);class Ey extends dm{static get type(){return"TextureNode"}constructor(e,t=null,s=null,i=null){super(e),this.isTextureNode=!0,this.uvNode=t,this.levelNode=s,this.biasNode=i,this.compareNode=null,this.depthNode=null,this.gradNode=null,this.sampler=!0,this.updateMatrix=!1,this.updateType=Bd.NONE,this.referenceNode=null,this._value=e,this._matrixUniform=null,this.setUpdateMatrix(null===t)}set value(e){this.referenceNode?this.referenceNode.value=e:this._value=e}get value(){return this.referenceNode?this.referenceNode.value:this._value}getUniformHash(){return this.value.uuid}getNodeType(){return!0===this.value.isDepthTexture?"float":this.value.type===Be?"uvec4":this.value.type===Ee?"ivec4":"vec4"}getInputType(){return"texture"}getDefaultUV(){return My(this.value.channel)}updateReference(){return this.value}getTransformedUV(e){return null===this._matrixUniform&&(this._matrixUniform=pm(this.value.matrix)),this._matrixUniform.mul(jp(e,1)).xy}setUpdateMatrix(e){return this.updateMatrix=e,this.updateType=e?Bd.FRAME:Bd.NONE,this}setupUV(e,t){const s=this.value;return!e.isFlipY()||!0!==s.isRenderTargetTexture&&!0!==s.isFramebufferTexture&&!0!==s.isDepthTexture||(t=this.sampler?t.flipY():t.setY(Op(Ay(this,this.levelNode).y).sub(t.y).sub(1))),t}setup(e){const t=e.getNodeProperties(this);t.referenceNode=this.referenceNode;let s=this.uvNode;null!==s&&!0!==e.context.forceUVContext||!e.context.getUV||(s=e.context.getUV(this)),s||(s=this.getDefaultUV()),!0===this.updateMatrix&&(s=this.getTransformedUV(s)),s=this.setupUV(e,s);let i=this.levelNode;null===i&&e.context.getTextureLevel&&(i=e.context.getTextureLevel(this)),t.uvNode=s,t.levelNode=i,t.biasNode=this.biasNode,t.compareNode=this.compareNode,t.gradNode=this.gradNode,t.depthNode=this.depthNode}generateUV(e,t){return t.build(e,!0===this.sampler?"vec2":"ivec2")}generateSnippet(e,t,s,i,r,n,o,a){const h=this.value;let u;return u=i?e.generateTextureLevel(h,t,s,i,n):r?e.generateTextureBias(h,t,s,r,n):a?e.generateTextureGrad(h,t,s,a,n):o?e.generateTextureCompare(h,t,s,o,n):!1===this.sampler?e.generateTextureLoad(h,t,s,n):e.generateTexture(h,t,s,n),u}generate(e,t){const s=e.getNodeProperties(this),i=this.value;if(!i||!0!==i.isTexture)throw new Error("TextureNode: Need a three.js texture.");const r=super.generate(e,"property");if("sampler"===t)return r+"_sampler";if(e.isReference(t))return r;{const n=e.getDataFromNode(this);let o=n.propertyName;if(void 0===o){const{uvNode:t,levelNode:i,biasNode:a,compareNode:h,depthNode:u,gradNode:l}=s,c=this.generateUV(e,t),d=i?i.build(e,"float"):null,p=a?a.build(e,"float"):null,m=u?u.build(e,"int"):null,g=h?h.build(e,"float"):null,f=l?[l[0].build(e,"vec2"),l[1].build(e,"vec2")]:null,y=e.getVarFromNode(this);o=e.getPropertyName(y);const x=this.generateSnippet(e,r,c,d,p,m,g,f);e.addLineFlowCode(`${o} = ${x}`,this),n.snippet=x,n.propertyName=o}let a=o;const h=this.getNodeType(e);return e.needsToWorkingColorSpace(i)&&(a=Xf(yy(a,h),i.colorSpace).setup(e).build(e,h)),e.format(a,h,t)}}setSampler(e){return this.sampler=e,this}getSampler(){return this.sampler}uv(e){const t=this.clone();return t.uvNode=Sp(e),t.referenceNode=this.getSelf(),Sp(t)}blur(e){const t=this.clone();return t.biasNode=Sp(e).mul(Ry(t)),t.referenceNode=this.getSelf(),Sp(t)}level(e){const t=this.clone();return t.levelNode=Sp(e),t.referenceNode=this.getSelf(),Sp(t)}size(e){return Ay(this,e)}bias(e){const t=this.clone();return t.biasNode=Sp(e),t.referenceNode=this.getSelf(),Sp(t)}compare(e){const t=this.clone();return t.compareNode=Sp(e),t.referenceNode=this.getSelf(),Sp(t)}grad(e,t){const s=this.clone();return s.gradNode=[Sp(e),Sp(t)],s.referenceNode=this.getSelf(),Sp(s)}depth(e){const t=this.clone();return t.depthNode=Sp(e),t.referenceNode=this.getSelf(),Sp(t)}serialize(e){super.serialize(e),e.value=this.value.toJSON(e.meta).uuid,e.sampler=this.sampler,e.updateMatrix=this.updateMatrix,e.updateType=this.updateType}deserialize(e){super.deserialize(e),this.value=e.meta.textures[e.value],this.sampler=e.sampler,this.updateMatrix=e.updateMatrix,this.updateType=e.updateType}update(){const e=this.value,t=this._matrixUniform;null!==t&&(t.value=e.matrix),!0===e.matrixAutoUpdate&&e.updateMatrix()}clone(){const e=new this.constructor(this.value,this.uvNode,this.levelNode,this.biasNode);return e.sampler=this.sampler,e}}const By=Ap(Ey),Iy=(...e)=>By(...e).setSampler(!1),Py=e=>(!0===e.isNode?e:By(e)).convert("sampler"),Fy=pm("float").label("cameraNear").setGroup(lm).onRenderUpdate((({camera:e})=>e.near)),zy=pm("float").label("cameraFar").setGroup(lm).onRenderUpdate((({camera:e})=>e.far)),Uy=pm("float").label("cameraLogDepth").setGroup(lm).onRenderUpdate((({camera:e})=>2/(Math.log(e.far+1)/Math.LN2))),Oy=pm("mat4").label("cameraProjectionMatrix").setGroup(lm).onRenderUpdate((({camera:e})=>e.projectionMatrix)),Ly=pm("mat4").label("cameraProjectionMatrixInverse").setGroup(lm).onRenderUpdate((({camera:e})=>e.projectionMatrixInverse)),Vy=pm("mat4").label("cameraViewMatrix").setGroup(lm).onRenderUpdate((({camera:e})=>e.matrixWorldInverse)),Dy=pm("mat4").label("cameraWorldMatrix").setGroup(lm).onRenderUpdate((({camera:e})=>e.matrixWorld)),ky=pm("mat3").label("cameraNormalMatrix").setGroup(lm).onRenderUpdate((({camera:e})=>e.normalMatrix)),Gy=pm(new Ri).label("cameraPosition").setGroup(lm).onRenderUpdate((({camera:e},t)=>t.value.setFromMatrixPosition(e.matrixWorld)));class Wy extends Ld{static get type(){return"Object3DNode"}constructor(e,t=null){super(),this.scope=e,this.object3d=t,this.updateType=Bd.OBJECT,this._uniformNode=new dm(null)}getNodeType(){const e=this.scope;return e===Wy.WORLD_MATRIX?"mat4":e===Wy.POSITION||e===Wy.VIEW_POSITION||e===Wy.DIRECTION||e===Wy.SCALE?"vec3":void 0}update(e){const t=this.object3d,s=this._uniformNode,i=this.scope;if(i===Wy.WORLD_MATRIX)s.value=t.matrixWorld;else if(i===Wy.POSITION)s.value=s.value||new Ri,s.value.setFromMatrixPosition(t.matrixWorld);else if(i===Wy.SCALE)s.value=s.value||new Ri,s.value.setFromMatrixScale(t.matrixWorld);else if(i===Wy.DIRECTION)s.value=s.value||new Ri,t.getWorldDirection(s.value);else if(i===Wy.VIEW_POSITION){const i=e.camera;s.value=s.value||new Ri,s.value.setFromMatrixPosition(t.matrixWorld),s.value.applyMatrix4(i.matrixWorldInverse)}}generate(e){const t=this.scope;return t===Wy.WORLD_MATRIX?this._uniformNode.nodeType="mat4":t!==Wy.POSITION&&t!==Wy.VIEW_POSITION&&t!==Wy.DIRECTION&&t!==Wy.SCALE||(this._uniformNode.nodeType="vec3"),this._uniformNode.build(e)}serialize(e){super.serialize(e),e.scope=this.scope}deserialize(e){super.deserialize(e),this.scope=e.scope}}Wy.WORLD_MATRIX="worldMatrix",Wy.POSITION="position",Wy.SCALE="scale",Wy.VIEW_POSITION="viewPosition",Wy.DIRECTION="direction";const jy=Ap(Wy,Wy.DIRECTION),Hy=Ap(Wy,Wy.WORLD_MATRIX),qy=Ap(Wy,Wy.POSITION),$y=Ap(Wy,Wy.SCALE),Xy=Ap(Wy,Wy.VIEW_POSITION);class Yy extends Wy{static get type(){return"ModelNode"}constructor(e){super(e)}update(e){this.object3d=e.object,super.update(e)}}const Zy=Cp(Yy,Yy.DIRECTION),Jy=Cp(Yy,Yy.WORLD_MATRIX),Ky=Cp(Yy,Yy.POSITION),Qy=Cp(Yy,Yy.SCALE),ex=Cp(Yy,Yy.VIEW_POSITION),tx=pm(new ei).onObjectUpdate((({object:e},t)=>t.value.getNormalMatrix(e.matrixWorld))),sx=pm(new nr).onObjectUpdate((({object:e},t)=>t.value.copy(e.matrixWorld).invert())),ix=Vy.mul(Jy).toVar("modelViewMatrix"),rx=Rp((e=>(e.context.isHighPrecisionModelViewMatrix=!0,pm("mat4").onObjectUpdate((({object:e,camera:t})=>e.modelViewMatrix.multiplyMatrices(t.matrixWorldInverse,e.matrixWorld)))))).once()().toVar("highPrecisionModelViewMatrix"),nx=Rp((e=>{const t=e.context.isHighPrecisionModelViewMatrix;return pm("mat3").onObjectUpdate((({object:e,camera:s})=>(!0!==t&&e.modelViewMatrix.multiplyMatrices(s.matrixWorldInverse,e.matrixWorld),e.normalMatrix.getNormalMatrix(e.modelViewMatrix))))})).once()().toVar("highPrecisionModelNormalMatrix"),ox=Sy("position","vec3"),ax=ox.varying("positionLocal"),hx=ox.varying("positionPrevious"),ux=Jy.mul(ax).xyz.varying("v_positionWorld"),lx=ax.transformDirection(Jy).varying("v_positionWorldDirection").normalize().toVar("positionWorldDirection"),cx=ix.mul(ax).xyz.varying("v_positionView"),dx=cx.negate().varying("v_positionViewDirection").normalize().toVar("positionViewDirection");class px extends Ld{static get type(){return"FrontFacingNode"}constructor(){super("bool"),this.isFrontFacingNode=!0}generate(e){const{renderer:t,material:s}=e;return t.coordinateSystem===Vs&&s.side===d?"false":e.getFrontFacing()}}const mx=Cp(px),gx=Up(mx).mul(2).sub(1),fx=Sy("normal","vec3"),yx=Rp((e=>!1===e.geometry.hasAttribute("normal")?(console.warn('TSL.NormalNode: Vertex attribute "normal" not found on geometry.'),jp(0,1,0)):fx),"vec3").once()().toVar("normalLocal"),xx=cx.dFdx().cross(cx.dFdy()).normalize().toVar("normalFlat"),bx=Rp((e=>{let t;return t=!0===e.material.flatShading?xx:Vf(Mx(yx),"v_normalView").normalize(),t}),"vec3").once()().toVar("normalView"),vx=Vf(bx.transformDirection(Vy),"v_normalWorld").normalize().toVar("normalWorld"),Tx=Rp((e=>e.context.setupNormal()),"vec3").once()().mul(gx).toVar("transformedNormalView"),_x=Tx.transformDirection(Vy).toVar("transformedNormalWorld"),wx=Rp((e=>e.context.setupClearcoatNormal()),"vec3").once()().mul(gx).toVar("transformedClearcoatNormalView"),Sx=Rp((([e,t=Jy])=>{const s=Qp(t),i=e.div(jp(s[0].dot(s[0]),s[1].dot(s[1]),s[2].dot(s[2])));return s.mul(i).xyz})),Mx=Rp((([e],t)=>{const s=t.renderer.nodes.modelNormalViewMatrix;if(null!==s)return s.transformDirection(e);const i=tx.mul(e);return Vy.transformDirection(i)})),Nx=pm(0).onReference((({material:e})=>e)).onRenderUpdate((({material:e})=>e.refractionRatio)),Ax=dx.negate().reflect(Tx),Cx=dx.negate().refract(Tx,Nx),Rx=Ax.transformDirection(Vy).toVar("reflectVector"),Ex=Cx.transformDirection(Vy).toVar("reflectVector");class Bx extends Ey{static get type(){return"CubeTextureNode"}constructor(e,t=null,s=null,i=null){super(e,t,s,i),this.isCubeTextureNode=!0}getInputType(){return"cubeTexture"}getDefaultUV(){const e=this.value;return e.mapping===he?Rx:e.mapping===ue?Ex:(console.error('THREE.CubeTextureNode: Mapping "%s" not supported.',e.mapping),jp(0,0,0))}setUpdateMatrix(){}setupUV(e,t){const s=this.value;return e.renderer.coordinateSystem!==Ds&&s.isRenderTargetTexture?t:jp(t.x.negate(),t.yz)}generateUV(e,t){return t.build(e,"vec3")}}const Ix=Ap(Bx);class Px extends dm{static get type(){return"BufferNode"}constructor(e,t,s=0){super(e,t),this.isBufferNode=!0,this.bufferType=t,this.bufferCount=s}getElementType(e){return this.getNodeType(e)}getInputType(){return"buffer"}}const Fx=(e,t,s)=>Sp(new Px(e,t,s));class zx extends Vd{static get type(){return"UniformArrayElementNode"}constructor(e,t){super(e,t),this.isArrayBufferElementNode=!0}generate(e){const t=super.generate(e),s=this.getNodeType();return e.format(t,"vec4",s)}}class Ux extends Px{static get type(){return"UniformArrayNode"}constructor(e,t=null){super(null,"vec4"),this.array=e,this.elementType=t,this._elementType=null,this._elementLength=0,this.updateType=Bd.RENDER,this.isArrayBufferNode=!0}getElementType(){return this.elementType||this._elementType}getElementLength(){return this._elementLength}update(){const{array:e,value:t}=this,s=this.getElementLength(),i=this.getElementType();if(1===s)for(let s=0;sSp(new Ux(e,t)),Lx=(e,t)=>(console.warn("TSL.UniformArrayNode: uniforms() has been renamed to uniformArray()."),Sp(new Ux(e,t)));class Vx extends Vd{static get type(){return"ReferenceElementNode"}constructor(e,t){super(e,t),this.referenceNode=e,this.isReferenceElementNode=!0}getNodeType(){return this.referenceNode.uniformType}generate(e){const t=super.generate(e),s=this.referenceNode.getNodeType(),i=this.getNodeType();return e.format(t,s,i)}}class Dx extends Ld{static get type(){return"ReferenceNode"}constructor(e,t,s=null,i=null){super(),this.property=e,this.uniformType=t,this.object=s,this.count=i,this.properties=e.split("."),this.reference=s,this.node=null,this.group=null,this.name=null,this.updateType=Bd.OBJECT}element(e){return Sp(new Vx(this,Sp(e)))}setGroup(e){return this.group=e,this}label(e){return this.name=e,this}setNodeType(e){let t=null;t=null!==this.count?Fx(null,e,this.count):Array.isArray(this.getValueFromReference())?Ox(null,e):"texture"===e?By(null):"cubeTexture"===e?Ix(null):pm(null,e),null!==this.group&&t.setGroup(this.group),null!==this.name&&t.label(this.name),this.node=t.getSelf()}getNodeType(e){return null===this.node&&(this.updateReference(e),this.updateValue()),this.node.getNodeType(e)}getValueFromReference(e=this.reference){const{properties:t}=this;let s=e[t[0]];for(let e=1;eSp(new Dx(e,t,s)),Gx=(e,t,s,i)=>Sp(new Dx(e,t,i,s));class Wx extends Dx{static get type(){return"MaterialReferenceNode"}constructor(e,t,s=null){super(e,t,s),this.material=s,this.isMaterialReferenceNode=!0}updateReference(e){return this.reference=null!==this.material?this.material:e.material,this.reference}}const jx=(e,t,s)=>Sp(new Wx(e,t,s)),Hx=Rp((e=>(!1===e.geometry.hasAttribute("tangent")&&e.geometry.computeTangents(),Sy("tangent","vec4"))))(),qx=Hx.xyz.toVar("tangentLocal"),$x=ix.mul(Xp(qx,0)).xyz.varying("v_tangentView").normalize().toVar("tangentView"),Xx=$x.transformDirection(Vy).varying("v_tangentWorld").normalize().toVar("tangentWorld"),Yx=$x.toVar("transformedTangentView"),Zx=Yx.transformDirection(Vy).normalize().toVar("transformedTangentWorld"),Jx=e=>e.mul(Hx.w).xyz,Kx=Vf(Jx(fx.cross(Hx)),"v_bitangentGeometry").normalize().toVar("bitangentGeometry"),Qx=Vf(Jx(yx.cross(qx)),"v_bitangentLocal").normalize().toVar("bitangentLocal"),eb=Vf(Jx(bx.cross($x)),"v_bitangentView").normalize().toVar("bitangentView"),tb=Vf(Jx(vx.cross(Xx)),"v_bitangentWorld").normalize().toVar("bitangentWorld"),sb=Jx(Tx.cross(Yx)).normalize().toVar("transformedBitangentView"),ib=sb.transformDirection(Vy).normalize().toVar("transformedBitangentWorld"),rb=Qp($x,eb,bx),nb=dx.mul(rb),ob=(e,t)=>e.sub(nb.mul(t)),ab=(()=>{let e=Bm.cross(dx);return e=e.cross(Bm).normalize(),e=Tf(e,Tx,Rm.mul(bm.oneMinus()).oneMinus().pow2().pow2()).normalize(),e})(),hb=Rp((e=>{const{eye_pos:t,surf_norm:s,mapN:i,uv:r}=e,n=t.dFdx(),o=t.dFdy(),a=r.dFdx(),h=r.dFdy(),u=s,l=o.cross(u),c=u.cross(n),d=l.mul(a.x).add(c.mul(h.x)),p=l.mul(a.y).add(c.mul(h.y)),m=d.dot(d).max(p.dot(p)),g=gx.mul(m.inverseSqrt());return Zm(d.mul(i.x,g),p.mul(i.y,g),u.mul(i.z)).normalize()}));class ub extends kd{static get type(){return"NormalMapNode"}constructor(e,t=null){super("vec3"),this.node=e,this.scaleNode=t,this.normalMapType=0}setup(e){const{normalMapType:t,scaleNode:s}=this;let i=this.node.mul(2).sub(1);null!==s&&(i=jp(i.xy.mul(s),i.z));let r=null;if(1===t)r=Mx(i);else if(0===t){r=!0===e.hasGeometryAttribute("tangent")?rb.mul(i).normalize():hb({eye_pos:cx,surf_norm:bx,mapN:i,uv:My()})}return r}}const lb=Ap(ub),cb=Rp((({textureNode:e,bumpScale:t})=>{const s=t=>e.cache().context({getUV:e=>t(e.uvNode||My()),forceUVContext:!0}),i=Up(s((e=>e)));return Dp(Up(s((e=>e.add(e.dFdx())))).sub(i),Up(s((e=>e.add(e.dFdy())))).sub(i)).mul(t)})),db=Rp((e=>{const{surf_pos:t,surf_norm:s,dHdxy:i}=e,r=t.dFdx().normalize(),n=s,o=t.dFdy().normalize().cross(n),a=n.cross(r),h=r.dot(o).mul(gx),u=h.sign().mul(i.x.mul(o).add(i.y.mul(a)));return h.abs().mul(s).sub(u).normalize()}));class pb extends kd{static get type(){return"BumpMapNode"}constructor(e,t=null){super("vec3"),this.textureNode=e,this.scaleNode=t}setup(){const e=null!==this.scaleNode?this.scaleNode:1,t=cb({textureNode:this.textureNode,bumpScale:e});return db({surf_pos:cx,surf_norm:bx,dHdxy:t})}}const mb=Ap(pb),gb=new Map;class fb extends Ld{static get type(){return"MaterialNode"}constructor(e){super(),this.scope=e}getCache(e,t){let s=gb.get(e);return void 0===s&&(s=jx(e,t),gb.set(e,s)),s}getFloat(e){return this.getCache(e,"float")}getColor(e){return this.getCache(e,"color")}getTexture(e){return this.getCache("map"===e?"map":e+"Map","texture")}setup(e){const t=e.context.material,s=this.scope;let i=null;if(s===fb.COLOR){const e=void 0!==t.color?this.getColor(s):jp();i=t.map&&!0===t.map.isTexture?e.mul(this.getTexture("map")):e}else if(s===fb.OPACITY){const e=this.getFloat(s);i=t.alphaMap&&!0===t.alphaMap.isTexture?e.mul(this.getTexture("alpha")):e}else if(s===fb.SPECULAR_STRENGTH)i=t.specularMap&&!0===t.specularMap.isTexture?this.getTexture("specular").r:Up(1);else if(s===fb.SPECULAR_INTENSITY){const e=this.getFloat(s);i=t.specularMap?e.mul(this.getTexture(s).a):e}else if(s===fb.SPECULAR_COLOR){const e=this.getColor(s);i=t.specularColorMap&&!0===t.specularColorMap.isTexture?e.mul(this.getTexture(s).rgb):e}else if(s===fb.ROUGHNESS){const e=this.getFloat(s);i=t.roughnessMap&&!0===t.roughnessMap.isTexture?e.mul(this.getTexture(s).g):e}else if(s===fb.METALNESS){const e=this.getFloat(s);i=t.metalnessMap&&!0===t.metalnessMap.isTexture?e.mul(this.getTexture(s).b):e}else if(s===fb.EMISSIVE){const e=this.getFloat("emissiveIntensity"),r=this.getColor(s).mul(e);i=t.emissiveMap&&!0===t.emissiveMap.isTexture?r.mul(this.getTexture(s)):r}else if(s===fb.NORMAL)t.normalMap?(i=lb(this.getTexture("normal"),this.getCache("normalScale","vec2")),i.normalMapType=t.normalMapType):i=t.bumpMap?mb(this.getTexture("bump").r,this.getFloat("bumpScale")):bx;else if(s===fb.CLEARCOAT){const e=this.getFloat(s);i=t.clearcoatMap&&!0===t.clearcoatMap.isTexture?e.mul(this.getTexture(s).r):e}else if(s===fb.CLEARCOAT_ROUGHNESS){const e=this.getFloat(s);i=t.clearcoatRoughnessMap&&!0===t.clearcoatRoughnessMap.isTexture?e.mul(this.getTexture(s).r):e}else if(s===fb.CLEARCOAT_NORMAL)i=t.clearcoatNormalMap?lb(this.getTexture(s),this.getCache(s+"Scale","vec2")):bx;else if(s===fb.SHEEN){const e=this.getColor("sheenColor").mul(this.getFloat("sheen"));i=t.sheenColorMap&&!0===t.sheenColorMap.isTexture?e.mul(this.getTexture("sheenColor").rgb):e}else if(s===fb.SHEEN_ROUGHNESS){const e=this.getFloat(s);i=t.sheenRoughnessMap&&!0===t.sheenRoughnessMap.isTexture?e.mul(this.getTexture(s).a):e,i=i.clamp(.07,1)}else if(s===fb.ANISOTROPY)if(t.anisotropyMap&&!0===t.anisotropyMap.isTexture){const e=this.getTexture(s);i=Kp(ev.x,ev.y,ev.y.negate(),ev.x).mul(e.rg.mul(2).sub(Dp(1)).normalize().mul(e.b))}else i=ev;else if(s===fb.IRIDESCENCE_THICKNESS){const e=kx("1","float",t.iridescenceThicknessRange);if(t.iridescenceThicknessMap){const r=kx("0","float",t.iridescenceThicknessRange);i=e.sub(r).mul(this.getTexture(s).g).add(r)}else i=e}else if(s===fb.TRANSMISSION){const e=this.getFloat(s);i=t.transmissionMap?e.mul(this.getTexture(s).r):e}else if(s===fb.THICKNESS){const e=this.getFloat(s);i=t.thicknessMap?e.mul(this.getTexture(s).g):e}else if(s===fb.IOR)i=this.getFloat(s);else if(s===fb.LIGHT_MAP)i=this.getTexture(s).rgb.mul(this.getFloat("lightMapIntensity"));else if(s===fb.AO_MAP)i=this.getTexture(s).r.sub(1).mul(this.getFloat("aoMapIntensity")).add(1);else{const t=this.getNodeType(e);i=this.getCache(s,t)}return i}}fb.ALPHA_TEST="alphaTest",fb.COLOR="color",fb.OPACITY="opacity",fb.SHININESS="shininess",fb.SPECULAR="specular",fb.SPECULAR_STRENGTH="specularStrength",fb.SPECULAR_INTENSITY="specularIntensity",fb.SPECULAR_COLOR="specularColor",fb.REFLECTIVITY="reflectivity",fb.ROUGHNESS="roughness",fb.METALNESS="metalness",fb.NORMAL="normal",fb.CLEARCOAT="clearcoat",fb.CLEARCOAT_ROUGHNESS="clearcoatRoughness",fb.CLEARCOAT_NORMAL="clearcoatNormal",fb.EMISSIVE="emissive",fb.ROTATION="rotation",fb.SHEEN="sheen",fb.SHEEN_ROUGHNESS="sheenRoughness",fb.ANISOTROPY="anisotropy",fb.IRIDESCENCE="iridescence",fb.IRIDESCENCE_IOR="iridescenceIOR",fb.IRIDESCENCE_THICKNESS="iridescenceThickness",fb.IOR="ior",fb.TRANSMISSION="transmission",fb.THICKNESS="thickness",fb.ATTENUATION_DISTANCE="attenuationDistance",fb.ATTENUATION_COLOR="attenuationColor",fb.LINE_SCALE="scale",fb.LINE_DASH_SIZE="dashSize",fb.LINE_GAP_SIZE="gapSize",fb.LINE_WIDTH="linewidth",fb.LINE_DASH_OFFSET="dashOffset",fb.POINT_WIDTH="pointWidth",fb.DISPERSION="dispersion",fb.LIGHT_MAP="light",fb.AO_MAP="ao";const yb=Cp(fb,fb.ALPHA_TEST),xb=Cp(fb,fb.COLOR),bb=Cp(fb,fb.SHININESS),vb=Cp(fb,fb.EMISSIVE),Tb=Cp(fb,fb.OPACITY),_b=Cp(fb,fb.SPECULAR),wb=Cp(fb,fb.SPECULAR_INTENSITY),Sb=Cp(fb,fb.SPECULAR_COLOR),Mb=Cp(fb,fb.SPECULAR_STRENGTH),Nb=Cp(fb,fb.REFLECTIVITY),Ab=Cp(fb,fb.ROUGHNESS),Cb=Cp(fb,fb.METALNESS),Rb=Cp(fb,fb.NORMAL).context({getUV:null}),Eb=Cp(fb,fb.CLEARCOAT),Bb=Cp(fb,fb.CLEARCOAT_ROUGHNESS),Ib=Cp(fb,fb.CLEARCOAT_NORMAL).context({getUV:null}),Pb=Cp(fb,fb.ROTATION),Fb=Cp(fb,fb.SHEEN),zb=Cp(fb,fb.SHEEN_ROUGHNESS),Ub=Cp(fb,fb.ANISOTROPY),Ob=Cp(fb,fb.IRIDESCENCE),Lb=Cp(fb,fb.IRIDESCENCE_IOR),Vb=Cp(fb,fb.IRIDESCENCE_THICKNESS),Db=Cp(fb,fb.TRANSMISSION),kb=Cp(fb,fb.THICKNESS),Gb=Cp(fb,fb.IOR),Wb=Cp(fb,fb.ATTENUATION_DISTANCE),jb=Cp(fb,fb.ATTENUATION_COLOR),Hb=Cp(fb,fb.LINE_SCALE),qb=Cp(fb,fb.LINE_DASH_SIZE),$b=Cp(fb,fb.LINE_GAP_SIZE),Xb=Cp(fb,fb.LINE_WIDTH),Yb=Cp(fb,fb.LINE_DASH_OFFSET),Zb=Cp(fb,fb.POINT_WIDTH),Jb=Cp(fb,fb.DISPERSION),Kb=Cp(fb,fb.LIGHT_MAP),Qb=Cp(fb,fb.AO_MAP),ev=pm(new Qs).onReference((function(e){return e.material})).onRenderUpdate((function({material:e}){this.value.set(e.anisotropy*Math.cos(e.anisotropyRotation),e.anisotropy*Math.sin(e.anisotropyRotation))}));class tv extends kd{static get type(){return"ModelViewProjectionNode"}constructor(e=null){super("vec4"),this.positionNode=e}setup(e){if("fragment"===e.shaderStage)return Vf(e.context.mvp);const t=this.positionNode||ax,s=e.renderer.nodes.modelViewMatrix||ix;return Oy.mul(s).mul(t)}}const sv=Ap(tv);class iv extends Ld{static get type(){return"IndexNode"}constructor(e){super("uint"),this.scope=e,this.isInstanceIndexNode=!0}generate(e){const t=this.getNodeType(e),s=this.scope;let i,r;if(s===iv.VERTEX)i=e.getVertexIndex();else if(s===iv.INSTANCE)i=e.getInstanceIndex();else if(s===iv.DRAW)i=e.getDrawIndex();else if(s===iv.INVOCATION_LOCAL)i=e.getInvocationLocalIndex();else if(s===iv.INVOCATION_SUBGROUP)i=e.getInvocationSubgroupIndex();else{if(s!==iv.SUBGROUP)throw new Error("THREE.IndexNode: Unknown scope: "+s);i=e.getSubgroupIndex()}if("vertex"===e.shaderStage||"compute"===e.shaderStage)r=i;else{r=Vf(this).build(e,t)}return r}}iv.VERTEX="vertex",iv.INSTANCE="instance",iv.SUBGROUP="subgroup",iv.INVOCATION_LOCAL="invocationLocal",iv.INVOCATION_SUBGROUP="invocationSubgroup",iv.DRAW="draw";const rv=Cp(iv,iv.VERTEX),nv=Cp(iv,iv.INSTANCE),ov=Cp(iv,iv.SUBGROUP),av=Cp(iv,iv.INVOCATION_SUBGROUP),hv=Cp(iv,iv.INVOCATION_LOCAL),uv=Cp(iv,iv.DRAW);class lv extends Ld{static get type(){return"InstanceNode"}constructor(e){super("void"),this.instanceMesh=e,this.instanceMatrixNode=null,this.instanceColorNode=null,this.updateType=Bd.FRAME,this.buffer=null,this.bufferColor=null}setup(e){let t=this.instanceMatrixNode,s=this.instanceColorNode;const i=this.instanceMesh;if(null===t){const e=i.instanceMatrix;if(i.count<=1e3)t=Fx(e.array,"mat4",Math.max(i.count,1)).element(nv);else{const s=new wc(e.array,16,1);this.buffer=s;const i=e.usage===Rs?oy:ny,r=[i(s,"vec4",16,0),i(s,"vec4",16,4),i(s,"vec4",16,8),i(s,"vec4",16,12)];t=em(...r)}this.instanceMatrixNode=t}const r=i.instanceColor;if(r&&null===s){const e=new Do(r.array,3),t=r.usage===Rs?oy:ny;this.bufferColor=e,s=jp(t(e,"vec3",3,0)),this.instanceColorNode=s}const n=t.mul(ax).xyz;if(ax.assign(n),e.hasGeometryAttribute("normal")){const e=Sx(yx,t);yx.assign(e)}null!==this.instanceColorNode&&fm("vec3","vInstanceColor").assign(this.instanceColorNode)}update(){this.instanceMesh.instanceMatrix.usage!==Rs&&null!=this.buffer&&this.instanceMesh.instanceMatrix.version!==this.buffer.version&&(this.buffer.version=this.instanceMesh.instanceMatrix.version),this.instanceMesh.instanceColor&&this.instanceMesh.instanceColor.usage!==Rs&&null!=this.bufferColor&&this.instanceMesh.instanceColor.version!==this.bufferColor.version&&(this.bufferColor.version=this.instanceMesh.instanceColor.version)}}const cv=Ap(lv);class dv extends Ld{static get type(){return"BatchNode"}constructor(e){super("void"),this.batchMesh=e,this.batchingIdNode=null}setup(e){null===this.batchingIdNode&&(null===e.getDrawIndex()?this.batchingIdNode=nv:this.batchingIdNode=uv);const t=Rp((([e])=>{const t=Ay(Iy(this.batchMesh._indirectTexture),0),s=Op(e).modInt(Op(t)),i=Op(e).div(Op(t));return Iy(this.batchMesh._indirectTexture,kp(s,i)).x})).setLayout({name:"getIndirectIndex",type:"uint",inputs:[{name:"id",type:"int"}]}),s=t(Op(this.batchingIdNode)),i=this.batchMesh._matricesTexture,r=Ay(Iy(i),0),n=Up(s).mul(4).toInt().toVar(),o=n.modInt(r),a=n.div(Op(r)),h=em(Iy(i,kp(o,a)),Iy(i,kp(o.add(1),a)),Iy(i,kp(o.add(2),a)),Iy(i,kp(o.add(3),a))),u=this.batchMesh._colorsTexture;if(null!==u){const e=Rp((([e])=>{const t=Ay(Iy(u),0).x,s=e,i=s.modInt(t),r=s.div(t);return Iy(u,kp(i,r)).rgb})).setLayout({name:"getBatchingColor",type:"vec3",inputs:[{name:"id",type:"int"}]}),t=e(s);fm("vec3","vBatchColor").assign(t)}const l=Qp(h);ax.assign(h.mul(ax));const c=yx.div(jp(l[0].dot(l[0]),l[1].dot(l[1]),l[2].dot(l[2]))),d=l.mul(c).xyz;yx.assign(d),e.hasGeometryAttribute("tangent")&&qx.mulAssign(l)}}const pv=Ap(dv),mv=new WeakMap;class gv extends Ld{static get type(){return"SkinningNode"}constructor(e,t=!1){let s,i,r;super("void"),this.skinnedMesh=e,this.useReference=t,this.updateType=Bd.OBJECT,this.skinIndexNode=Sy("skinIndex","uvec4"),this.skinWeightNode=Sy("skinWeight","vec4"),t?(s=kx("bindMatrix","mat4"),i=kx("bindMatrixInverse","mat4"),r=Gx("skeleton.boneMatrices","mat4",e.skeleton.bones.length)):(s=pm(e.bindMatrix,"mat4"),i=pm(e.bindMatrixInverse,"mat4"),r=Fx(e.skeleton.boneMatrices,"mat4",e.skeleton.bones.length)),this.bindMatrixNode=s,this.bindMatrixInverseNode=i,this.boneMatricesNode=r,this.previousBoneMatricesNode=null}getSkinnedPosition(e=this.boneMatricesNode,t=ax){const{skinIndexNode:s,skinWeightNode:i,bindMatrixNode:r,bindMatrixInverseNode:n}=this,o=e.element(s.x),a=e.element(s.y),h=e.element(s.z),u=e.element(s.w),l=r.mul(t),c=Zm(o.mul(i.x).mul(l),a.mul(i.y).mul(l),h.mul(i.z).mul(l),u.mul(i.w).mul(l));return n.mul(c).xyz}getSkinnedNormal(e=this.boneMatricesNode,t=yx){const{skinIndexNode:s,skinWeightNode:i,bindMatrixNode:r,bindMatrixInverseNode:n}=this,o=e.element(s.x),a=e.element(s.y),h=e.element(s.z),u=e.element(s.w);let l=Zm(i.x.mul(o),i.y.mul(a),i.z.mul(h),i.w.mul(u));return l=n.mul(l).mul(r),l.transformDirection(t).xyz}getPreviousSkinnedPosition(e){const t=e.object;return null===this.previousBoneMatricesNode&&(t.skeleton.previousBoneMatrices=new Float32Array(t.skeleton.boneMatrices),this.previousBoneMatricesNode=Gx("skeleton.previousBoneMatrices","mat4",t.skeleton.bones.length)),this.getSkinnedPosition(this.previousBoneMatricesNode,hx)}needsPreviousBoneMatrices(e){const t=e.renderer.getMRT();return t&&t.has("velocity")}setup(e){this.needsPreviousBoneMatrices(e)&&hx.assign(this.getPreviousSkinnedPosition(e));const t=this.getSkinnedPosition();if(ax.assign(t),e.hasGeometryAttribute("normal")){const t=this.getSkinnedNormal();yx.assign(t),e.hasGeometryAttribute("tangent")&&qx.assign(t)}}generate(e,t){if("void"!==t)return ax.build(e,t)}update(e){const t=(this.useReference?e.object:this.skinnedMesh).skeleton;mv.get(t)!==e.frameId&&(mv.set(t,e.frameId),null!==this.previousBoneMatricesNode&&t.previousBoneMatrices.set(t.boneMatrices),t.update())}}const fv=e=>Sp(new gv(e)),yv=e=>Sp(new gv(e,!0));class xv extends Ld{static get type(){return"LoopNode"}constructor(e=[]){super(),this.params=e}getVarName(e){return String.fromCharCode("i".charCodeAt()+e)}getProperties(e){const t=e.getNodeProperties(this);if(void 0!==t.stackNode)return t;const s={};for(let e=0,t=this.params.length-1;eNumber(n)?">=":"<"));const l={start:r,end:n,condition:h},c=l.start,d=l.end;let p="",m="",g="";u||(u="int"===a||"uint"===a?h.includes("<")?"++":"--":h.includes("<")?"+= 1.":"-= 1."),p+=e.getVar(a,o)+" = "+c,m+=o+" "+h+" "+d,g+=o+" "+u;const f=`for ( ${p}; ${m}; ${g} )`;e.addFlowCode((0===t?"\n":"")+e.tab+f+" {\n\n").addFlowTab()}const r=i.build(e,"void"),n=t.returnsNode?t.returnsNode.build(e):"";e.removeFlowTab().addFlowCode("\n"+e.tab+r);for(let t=0,s=this.params.length-1;tSp(new xv(Np(e,"int"))).append(),vv=()=>yy("continue").append(),Tv=()=>yy("break").append(),_v=(...e)=>(console.warn("TSL.LoopNode: loop() has been renamed to Loop()."),bv(...e)),wv=new WeakMap,Sv=new Ti,Mv=Rp((({bufferMap:e,influence:t,stride:s,width:i,depth:r,offset:n})=>{const o=Op(rv).mul(s).add(n),a=o.div(i),h=o.sub(a.mul(i));return Iy(e,kp(h,a)).depth(r).mul(t)}));class Nv extends Ld{static get type(){return"MorphNode"}constructor(e){super("void"),this.mesh=e,this.morphBaseInfluence=pm(1),this.updateType=Bd.OBJECT}setup(e){const{geometry:t}=e,s=void 0!==t.morphAttributes.position,i=t.hasAttribute("normal")&&void 0!==t.morphAttributes.normal,r=t.morphAttributes.position||t.morphAttributes.normal||t.morphAttributes.color,n=void 0!==r?r.length:0,{texture:o,stride:a,size:h}=function(e){const t=void 0!==e.morphAttributes.position,s=void 0!==e.morphAttributes.normal,i=void 0!==e.morphAttributes.color,r=e.morphAttributes.position||e.morphAttributes.normal||e.morphAttributes.color,n=void 0!==r?r.length:0;let o=wv.get(e);if(void 0===o||o.count!==n){void 0!==o&&o.texture.dispose();const a=e.morphAttributes.position||[],h=e.morphAttributes.normal||[],u=e.morphAttributes.color||[];let l=0;!0===t&&(l=1),!0===s&&(l=2),!0===i&&(l=3);let c=e.attributes.position.count*l,d=1;const p=4096;c>p&&(d=Math.ceil(c/p),c=p);const m=new Float32Array(c*d*4*n),g=new Si(m,c,d,n);g.type=Ie,g.needsUpdate=!0;const f=4*l;for(let x=0;x{const t=Up(0).toVar();this.mesh.count>1&&null!==this.mesh.morphTexture&&void 0!==this.mesh.morphTexture?t.assign(Iy(this.mesh.morphTexture,kp(Op(e).add(1),Op(nv))).r):t.assign(kx("morphTargetInfluences","float").element(e).toVar()),!0===s&&ax.addAssign(Mv({bufferMap:o,influence:t,stride:a,width:u,depth:e,offset:Op(0)})),!0===i&&yx.addAssign(Mv({bufferMap:o,influence:t,stride:a,width:u,depth:e,offset:Op(1)}))}))}update(){const e=this.morphBaseInfluence;this.mesh.geometry.morphTargetsRelative?e.value=1:e.value=1-this.mesh.morphTargetInfluences.reduce(((e,t)=>e+t),0)}}const Av=Ap(Nv),Cv=(e,t)=>{for(const s of t)if(s.isAnalyticLightNode&&s.light.id===e)return s;return null},Rv=new WeakMap;class Ev extends Ld{static get type(){return"LightsNode"}constructor(e=[]){super("vec3"),this.totalDiffuseNode=jp().toVar("totalDiffuse"),this.totalSpecularNode=jp().toVar("totalSpecular"),this.outgoingLightNode=jp().toVar("outgoingLight"),this._lights=e,this._lightNodes=null,this._lightNodesHash=null,this.global=!0}getHash(e){if(null===this._lightNodesHash){null===this._lightNodes&&this.setupLightsNode(e);const t=[];for(const e of this._lightNodes)t.push(e.getHash());this._lightNodesHash="lights-"+t.join(",")}return this._lightNodesHash}analyze(e){const t=e.getDataFromNode(this);for(const s of t.nodes)s.build(e)}setupLightsNode(e){const t=[],s=this._lightNodes,i=(e=>e.sort(((e,t)=>e.id-t.id)))(this._lights),r=e.renderer.nodes.library;for(const e of i)if(e.isNode)t.push(Sp(e));else{let i=null;if(null!==s&&(i=Cv(e.id,s)),null===i){const s=r.getLightNodeClass(e.constructor);if(null===s){console.warn(`LightsNode.setupNodeLights: Light node not found for ${e.constructor.name}`);continue}let i=null;Rv.has(e)?i=Rv.get(e):(i=new s(e),Rv.set(e,i)),t.push(i)}}this._lightNodes=t}setup(e){null===this._lightNodes&&this.setupLightsNode(e);const t=e.context,s=t.lightingModel;let i=this.outgoingLightNode;if(s){const{_lightNodes:r,totalDiffuseNode:n,totalSpecularNode:o}=this;t.outgoingLight=i;const a=e.addStack();e.getDataFromNode(this).nodes=a.nodes,s.start(t,a,e);for(const t of r)t.build(e);s.indirect(t,a,e);const{backdrop:h,backdropAlpha:u}=t,{directDiffuse:l,directSpecular:c,indirectDiffuse:d,indirectSpecular:p}=t.reflectedLight;let m=l.add(d);null!==h&&(m=jp(null!==u?u.mix(m,h):h),t.material.transparent=!0),n.assign(m),o.assign(c.add(p)),i.assign(n.add(o)),s.finish(t,a,e),i=i.bypass(e.removeStack())}return i}setLights(e){return this._lights=e,this._lightNodes=null,this._lightNodesHash=null,this}getLights(){return this._lights}}const Bv=Ap(Ev);class Iv extends Ld{static get type(){return"LightingNode"}constructor(){super("vec3"),this.isLightingNode=!0}generate(){console.warn("Abstract function.")}}class Pv extends Iv{static get type(){return"AONode"}constructor(e=null){super(),this.aoNode=e}setup(e){e.context.ambientOcclusion.mulAssign(this.aoNode)}}class Fv extends Pf{static get type(){return"LightingContextNode"}constructor(e,t=null,s=null,i=null){super(e),this.lightingModel=t,this.backdropNode=s,this.backdropAlphaNode=i,this._value=null}getContext(){const{backdropNode:e,backdropAlphaNode:t}=this,s={directDiffuse:jp().toVar("directDiffuse"),directSpecular:jp().toVar("directSpecular"),indirectDiffuse:jp().toVar("indirectDiffuse"),indirectSpecular:jp().toVar("indirectSpecular")};return{radiance:jp().toVar("radiance"),irradiance:jp().toVar("irradiance"),iblIrradiance:jp().toVar("iblIrradiance"),ambientOcclusion:Up(1).toVar("ambientOcclusion"),reflectedLight:s,backdrop:e,backdropAlpha:t}}setup(e){return this.value=this._value||(this._value=this.getContext()),this.value.lightingModel=this.lightingModel||e.context.lightingModel,super.setup(e)}}const zv=Ap(Fv);class Uv extends Iv{static get type(){return"IrradianceNode"}constructor(e){super(),this.node=e}setup(e){e.context.irradiance.addAssign(this.node)}}let Ov,Lv;class Vv extends Ld{static get type(){return"ScreenNode"}constructor(e){super(),this.scope=e,this.isViewportNode=!0}getNodeType(){return this.scope===Vv.VIEWPORT?"vec4":"vec2"}getUpdateType(){let e=Bd.NONE;return this.scope!==Vv.SIZE&&this.scope!==Vv.VIEWPORT||(e=Bd.RENDER),this.updateType=e,e}update({renderer:e}){const t=e.getRenderTarget();this.scope===Vv.VIEWPORT?null!==t?Lv.copy(t.viewport):(e.getViewport(Lv),Lv.multiplyScalar(e.getPixelRatio())):null!==t?(Ov.width=t.width,Ov.height=t.height):e.getDrawingBufferSize(Ov)}setup(){const e=this.scope;let t=null;return t=e===Vv.SIZE?pm(Ov||(Ov=new Qs)):e===Vv.VIEWPORT?pm(Lv||(Lv=new Ti)):Dp(Gv.div(kv)),t}generate(e){if(this.scope===Vv.COORDINATE){let t=e.getFragCoord();if(e.isFlipY()){const s=e.getNodeProperties(kv).outputNode.build(e);t=`${e.getType("vec2")}( ${t}.x, ${s}.y - ${t}.y )`}return t}return super.generate(e)}}Vv.COORDINATE="coordinate",Vv.VIEWPORT="viewport",Vv.SIZE="size",Vv.UV="uv";const Dv=Cp(Vv,Vv.UV),kv=Cp(Vv,Vv.SIZE),Gv=Cp(Vv,Vv.COORDINATE),Wv=Cp(Vv,Vv.VIEWPORT),jv=Wv.zw,Hv=Gv.sub(Wv.xy),qv=Hv.div(jv),$v=Rp((()=>(console.warn('TSL.ViewportNode: "viewportResolution" is deprecated. Use "screenSize" instead.'),kv)),"vec2").once()(),Xv=Rp((()=>(console.warn('TSL.ViewportNode: "viewportTopLeft" is deprecated. Use "screenUV" instead.'),Dv)),"vec2").once()(),Yv=Rp((()=>(console.warn('TSL.ViewportNode: "viewportBottomLeft" is deprecated. Use "screenUV.flipY()" instead.'),Dv.flipY())),"vec2").once()(),Zv=new Qs;class Jv extends Ey{static get type(){return"ViewportTextureNode"}constructor(e=Dv,t=null,s=null){null===s&&((s=new ja).minFilter=Se),super(s,e,t),this.generateMipmaps=!1,this.isOutputTextureNode=!0,this.updateBeforeType=Bd.FRAME}updateBefore(e){const t=e.renderer;t.getDrawingBufferSize(Zv);const s=this.value;s.image.width===Zv.width&&s.image.height===Zv.height||(s.image.width=Zv.width,s.image.height=Zv.height,s.needsUpdate=!0);const i=s.generateMipmaps;s.generateMipmaps=this.generateMipmaps,t.copyFramebufferToTexture(s),s.generateMipmaps=i}clone(){const e=new this.constructor(this.uvNode,this.levelNode,this.value);return e.generateMipmaps=this.generateMipmaps,e}}const Kv=Ap(Jv),Qv=Ap(Jv,null,null,{generateMipmaps:!0});let eT=null;class tT extends Jv{static get type(){return"ViewportDepthTextureNode"}constructor(e=Dv,t=null){null===eT&&(eT=new Ya),super(e,t,eT)}}const sT=Ap(tT);class iT extends Ld{static get type(){return"ViewportDepthNode"}constructor(e,t=null){super("float"),this.scope=e,this.valueNode=t,this.isViewportDepthNode=!0}generate(e){const{scope:t}=this;return t===iT.DEPTH_BASE?e.getFragDepth():super.generate(e)}setup({camera:e}){const{scope:t}=this,s=this.valueNode;let i=null;if(t===iT.DEPTH_BASE)null!==s&&(i=hT().assign(s));else if(t===iT.DEPTH)i=e.isPerspectiveCamera?oT(cx.z,Fy,zy):rT(cx.z,Fy,zy);else if(t===iT.LINEAR_DEPTH)if(null!==s)if(e.isPerspectiveCamera){const e=aT(s,Fy,zy);i=rT(e,Fy,zy)}else i=s;else i=rT(cx.z,Fy,zy);return i}}iT.DEPTH_BASE="depthBase",iT.DEPTH="depth",iT.LINEAR_DEPTH="linearDepth";const rT=(e,t,s)=>e.add(t).div(t.sub(s)),nT=(e,t,s)=>t.sub(s).mul(e).sub(t),oT=(e,t,s)=>t.add(e).mul(s).div(s.sub(t).mul(e)),aT=(e,t,s)=>t.mul(s).div(s.sub(t).mul(e).sub(s)),hT=Ap(iT,iT.DEPTH_BASE),uT=Cp(iT,iT.DEPTH),lT=Ap(iT,iT.LINEAR_DEPTH),cT=lT(sT());uT.assign=e=>hT(e);class dT extends Ld{static get type(){return"ClippingNode"}constructor(e=dT.DEFAULT){super(),this.scope=e}setup(e){super.setup(e);const t=e.clippingContext,{localClipIntersection:s,localClippingCount:i,globalClippingCount:r}=t,n=r+i,o=s?n-i:n;return this.scope===dT.ALPHA_TO_COVERAGE?this.setupAlphaToCoverage(t.planes,n,o):this.setupDefault(t.planes,n,o)}setupAlphaToCoverage(e,t,s){return Rp((()=>{const i=Ox(e),r=gm("float","distanceToPlane"),n=gm("float","distanceToGradient"),o=gm("float","clipOpacity");let a;if(o.assign(1),bv(s,(({i:e})=>{a=i.element(e),r.assign(cx.dot(a.xyz).negate().add(a.w)),n.assign(r.fwidth().div(2)),o.mulAssign(Mf(n.negate(),n,r)),o.equal(0).discard()})),s{a=i.element(t),r.assign(cx.dot(a.xyz).negate().add(a.w)),n.assign(r.fwidth().div(2)),e.mulAssign(Mf(n.negate(),n,r).oneMinus())})),o.mulAssign(e.oneMinus())}ym.a.mulAssign(o),ym.a.equal(0).discard()}))()}setupDefault(e,t,s){return Rp((()=>{const i=Ox(e);let r;if(bv(s,(({i:e})=>{r=i.element(e),cx.dot(r.xyz).greaterThan(r.w).discard()})),s{r=i.element(t),e.assign(cx.dot(r.xyz).greaterThan(r.w).and(e))})),e.discard()}}))()}}dT.ALPHA_TO_COVERAGE="alphaToCoverage",dT.DEFAULT="default";class pT extends en{static get type(){return"NodeMaterial"}constructor(){super(),this.isNodeMaterial=!0,this.type=this.constructor.type,this.forceSinglePass=!1,this.fog=!0,this.lights=!1,this.lightsNode=null,this.envNode=null,this.aoNode=null,this.colorNode=null,this.normalNode=null,this.opacityNode=null,this.backdropNode=null,this.backdropAlphaNode=null,this.alphaTestNode=null,this.positionNode=null,this.depthNode=null,this.shadowNode=null,this.shadowPositionNode=null,this.outputNode=null,this.mrtNode=null,this.fragmentNode=null,this.vertexNode=null}customProgramCacheKey(){return this.type+wd(this)}build(e){this.setup(e)}setupObserver(e){return new xd(e)}setup(e){let t;e.context.setupNormal=()=>this.setupNormal(e),e.addStack(),e.stack.outputNode=this.vertexNode||this.setupPosition(e),e.addFlow("vertex",e.removeStack()),e.addStack();const s=this.setupClipping(e);if(!0===this.depthWrite&&this.setupDepth(e),null===this.fragmentNode){this.setupDiffuseColor(e),this.setupVariants(e);const i=this.setupLighting(e);null!==s&&e.stack.add(s);const r=Xp(i,ym.a).max(0);t=this.setupOutput(e,r),zm.assign(t),null!==this.outputNode&&(t=this.outputNode);if(null!==e.renderer.getRenderTarget()){const s=e.renderer.getMRT(),i=this.mrtNode;null!==s?(t=s,null!==i&&(t=s.merge(i))):null!==i&&(t=i)}}else{let s=this.fragmentNode;!0!==s.isOutputStructNode&&(s=Xp(s)),t=this.setupOutput(e,s)}e.stack.outputNode=t,e.addFlow("fragment",e.removeStack()),e.monitor=this.setupObserver(e)}setupClipping(e){if(null===e.clippingContext)return null;const{globalClippingCount:t,localClippingCount:s}=e.clippingContext;let i=null;if(t||s){const t=e.renderer.samples;this.alphaToCoverage&&t>1?i=Sp(new dT(dT.ALPHA_TO_COVERAGE)):e.stack.add(Sp(new dT))}return i}setupDepth(e){const{renderer:t}=e;let s=this.depthNode;if(null===s){const e=t.getMRT();if(e&&e.has("depth"))s=e.get("depth");else if(!0===t.logarithmicDepthBuffer){s=sv().w.add(1).log2().mul(Uy).mul(.5)}}null!==s&&uT.assign(s).append()}setupPosition(e){const{object:t}=e,s=t.geometry;if(e.addStack(),(s.morphAttributes.position||s.morphAttributes.normal||s.morphAttributes.color)&&Av(t).append(),!0===t.isSkinnedMesh&&yv(t).append(),this.displacementMap){const e=jx("displacementMap","texture"),t=jx("displacementScale","float"),s=jx("displacementBias","float");ax.addAssign(yx.normalize().mul(e.x.mul(t).add(s)))}t.isBatchedMesh&&pv(t).append(),t.instanceMatrix&&!0===t.instanceMatrix.isInstancedBufferAttribute&&cv(t).append(),null!==this.positionNode&&ax.assign(this.positionNode);const i=sv();return e.context.vertex=e.removeStack(),e.context.mvp=i,i}setupDiffuseColor({object:e,geometry:t}){let s=this.colorNode?Xp(this.colorNode):xb;if(!0===this.vertexColors&&t.hasAttribute("color")&&(s=Xp(s.xyz.mul(Sy("color","vec3")),s.a)),e.instanceColor){s=fm("vec3","vInstanceColor").mul(s)}if(e.isBatchedMesh&&e._colorsTexture){s=fm("vec3","vBatchColor").mul(s)}ym.assign(s);const i=this.opacityNode?Up(this.opacityNode):Tb;if(ym.a.assign(ym.a.mul(i)),null!==this.alphaTestNode||this.alphaTest>0){const e=null!==this.alphaTestNode?Up(this.alphaTestNode):yb;ym.a.lessThanEqual(e).discard()}!1===this.transparent&&1===this.blending&&!1===this.alphaToCoverage&&ym.a.assign(1)}setupVariants(){}setupOutgoingLight(){return!0===this.lights?jp(0):ym.rgb}setupNormal(){return this.normalNode?jp(this.normalNode):Rb}setupEnvironment(){let e=null;return this.envNode?e=this.envNode:this.envMap&&(e=this.envMap.isCubeTexture?jx("envMap","cubeTexture"):jx("envMap","texture")),e}setupLightMap(e){let t=null;return e.material.lightMap&&(t=new Uv(Kb)),t}setupLights(e){const t=[],s=this.setupEnvironment(e);s&&s.isLightingNode&&t.push(s);const i=this.setupLightMap(e);if(i&&i.isLightingNode&&t.push(i),null!==this.aoNode||e.material.aoMap){const e=null!==this.aoNode?this.aoNode:Qb;t.push(new Pv(e))}let r=this.lightsNode||e.lightsNode;return t.length>0&&(r=Bv([...r.getLights(),...t])),r}setupLightingModel(){}setupLighting(e){const{material:t}=e,{backdropNode:s,backdropAlphaNode:i,emissiveNode:r}=this,n=!0===this.lights||null!==this.lightsNode?this.setupLights(e):null;let o=this.setupOutgoingLight(e);if(n&&n.getScope().getLights().length>0){const t=this.setupLightingModel(e);o=zv(n,t,s,i)}else null!==s&&(o=jp(null!==i?Tf(o,s,i):s));return(r&&!0===r.isNode||t.emissive&&!0===t.emissive.isColor)&&(xm.assign(jp(r||vb)),o=o.add(xm)),o}setupOutput(e,t){if(!0===this.fog){const s=e.fogNode;s&&(t=Xp(s.mix(t.rgb,s.colorNode),t.a))}return t}setDefaultValues(e){for(const t in e){const s=e[t];void 0===this[t]&&(this[t]=s,s&&s.clone&&(this[t]=s.clone()))}const t=Object.getOwnPropertyDescriptors(e.constructor.prototype);for(const e in t)void 0===Object.getOwnPropertyDescriptor(this.constructor.prototype,e)&&void 0!==t[e].get&&Object.defineProperty(this.constructor.prototype,e,t[e])}toJSON(e){const t=void 0===e||"string"==typeof e;t&&(e={textures:{},images:{},nodes:{}});const s=en.prototype.toJSON.call(this,e),i=Sd(this);s.inputNodes={};for(const{property:t,childNode:r}of i)s.inputNodes[t]=r.toJSON(e).uuid;function r(e){const t=[];for(const s in e){const i=e[s];delete i.metadata,t.push(i)}return t}if(t){const t=r(e.textures),i=r(e.images),n=r(e.nodes);t.length>0&&(s.textures=t),i.length>0&&(s.images=i),n.length>0&&(s.nodes=n)}return s}copy(e){return this.lightsNode=e.lightsNode,this.envNode=e.envNode,this.colorNode=e.colorNode,this.normalNode=e.normalNode,this.opacityNode=e.opacityNode,this.backdropNode=e.backdropNode,this.backdropAlphaNode=e.backdropAlphaNode,this.alphaTestNode=e.alphaTestNode,this.positionNode=e.positionNode,this.depthNode=e.depthNode,this.shadowNode=e.shadowNode,this.shadowPositionNode=e.shadowPositionNode,this.outputNode=e.outputNode,this.mrtNode=e.mrtNode,this.fragmentNode=e.fragmentNode,this.vertexNode=e.vertexNode,super.copy(e)}}const mT=new za;class gT extends pT{static get type(){return"InstancedPointsNodeMaterial"}constructor(e={}){super(),this.lights=!1,this.useAlphaToCoverage=!0,this.useColor=e.vertexColors,this.pointWidth=1,this.pointColorNode=null,this.pointWidthNode=null,this.setDefaultValues(mT),this.setValues(e)}setup(e){this.setupShaders(e),super.setup(e)}setupShaders({renderer:e}){const t=this.alphaToCoverage,s=this.useColor;this.vertexNode=Rp((()=>{const e=Sy("instancePosition").xyz,t=Xp(ix.mul(Xp(e,1))),s=Wv.z.div(Wv.w),i=Oy.mul(t),r=ox.xy.toVar();return r.mulAssign(this.pointWidthNode?this.pointWidthNode:Zb),r.assign(r.div(Wv.z)),r.y.assign(r.y.mul(s)),r.assign(r.mul(i.w)),i.addAssign(Xp(r,0,0)),i}))(),this.fragmentNode=Rp((()=>{const i=Up(1).toVar(),r=vf(My().mul(2).sub(1));if(t&&e.samples>1){const e=Up(r.fwidth()).toVar();i.assign(Mf(e.oneMinus(),e.add(1),r).oneMinus())}else r.greaterThan(1).discard();let n;if(this.pointColorNode)n=this.pointColorNode;else if(s){n=Sy("instanceColor").mul(xb)}else n=xb;return i.mulAssign(Tb),Xp(n,i)}))()}get alphaToCoverage(){return this.useAlphaToCoverage}set alphaToCoverage(e){this.useAlphaToCoverage!==e&&(this.useAlphaToCoverage=e,this.needsUpdate=!0)}}const fT=new Ta;class yT extends pT{static get type(){return"LineBasicNodeMaterial"}constructor(e){super(),this.isLineBasicNodeMaterial=!0,this.lights=!1,this.setDefaultValues(fT),this.setValues(e)}}const xT=new Bu;class bT extends pT{static get type(){return"LineDashedNodeMaterial"}constructor(e){super(),this.isLineDashedNodeMaterial=!0,this.lights=!1,this.setDefaultValues(xT),this.offsetNode=null,this.dashScaleNode=null,this.dashSizeNode=null,this.gapSizeNode=null,this.setValues(e)}setupVariants(){const e=this.offsetNode,t=this.dashScaleNode?Up(this.dashScaleNode):Hb,s=this.dashSizeNode?Up(this.dashSizeNode):qb,i=this.dashSizeNode?Up(this.dashGapNode):$b;Um.assign(s),Om.assign(i);const r=Vf(Sy("lineDistance").mul(t));(e?r.add(e):r).mod(Um.add(Om)).greaterThan(Um).discard()}}const vT=new Bu;class TT extends pT{static get type(){return"Line2NodeMaterial"}constructor(e={}){super(),this.lights=!1,this.setDefaultValues(vT),this.useAlphaToCoverage=!0,this.useColor=e.vertexColors,this.useDash=e.dashed,this.useWorldUnits=!1,this.dashOffset=0,this.lineWidth=1,this.lineColorNode=null,this.offsetNode=null,this.dashScaleNode=null,this.dashSizeNode=null,this.gapSizeNode=null,this.setValues(e)}setup(e){this.setupShaders(e),super.setup(e)}setupShaders({renderer:e}){const t=this.alphaToCoverage,s=this.useColor,i=this.dashed,r=this.worldUnits,n=Rp((({start:e,end:t})=>{const s=Oy.element(2).element(2),i=Oy.element(3).element(2).mul(-.5).div(s).sub(e.z).div(t.z.sub(e.z));return Xp(Tf(e.xyz,t.xyz,i),t.w)})).setLayout({name:"trimSegment",type:"vec4",inputs:[{name:"start",type:"vec4"},{name:"end",type:"vec4"}]});this.vertexNode=Rp((()=>{const e=Sy("instanceStart"),t=Sy("instanceEnd"),s=Xp(ix.mul(Xp(e,1))).toVar("start"),o=Xp(ix.mul(Xp(t,1))).toVar("end");r&&(fm("vec3","worldStart").assign(s.xyz),fm("vec3","worldEnd").assign(o.xyz));const a=Wv.z.div(Wv.w),h=Oy.element(2).element(3).equal(-1);Pp(h,(()=>{Pp(s.z.lessThan(0).and(o.z.greaterThan(0)),(()=>{o.assign(n({start:s,end:o}))})).ElseIf(o.z.lessThan(0).and(s.z.greaterThanEqual(0)),(()=>{s.assign(n({start:o,end:s}))}))}));const u=Oy.mul(s),l=Oy.mul(o),c=u.xyz.div(u.w),d=l.xyz.div(l.w),p=d.xy.sub(c.xy).toVar();p.x.assign(p.x.mul(a)),p.assign(p.normalize());const m=Xp().toVar();if(r){const e=o.xyz.sub(s.xyz).normalize(),t=Tf(s.xyz,o.xyz,.5).normalize(),r=e.cross(t).normalize(),n=e.cross(r),a=fm("vec4","worldPos");a.assign(ox.y.lessThan(.5).select(s,o));const h=Xb.mul(.5);a.addAssign(Xp(ox.x.lessThan(0).select(r.mul(h),r.mul(h).negate()),0)),i||(a.addAssign(Xp(ox.y.lessThan(.5).select(e.mul(h).negate(),e.mul(h)),0)),a.addAssign(Xp(n.mul(h),0)),Pp(ox.y.greaterThan(1).or(ox.y.lessThan(0)),(()=>{a.subAssign(Xp(n.mul(2).mul(h),0))}))),m.assign(Oy.mul(a));const u=jp().toVar();u.assign(ox.y.lessThan(.5).select(c,d)),m.z.assign(u.z.mul(m.w))}else{const e=Dp(p.y,p.x.negate()).toVar("offset");p.x.assign(p.x.div(a)),e.x.assign(e.x.div(a)),e.assign(ox.x.lessThan(0).select(e.negate(),e)),Pp(ox.y.lessThan(0),(()=>{e.assign(e.sub(p))})).ElseIf(ox.y.greaterThan(1),(()=>{e.assign(e.add(p))})),e.assign(e.mul(Xb)),e.assign(e.div(Wv.w)),m.assign(ox.y.lessThan(.5).select(u,l)),e.assign(e.mul(m.w)),m.assign(m.add(Xp(e,0,0)))}return m}))();const o=Rp((({p1:e,p2:t,p3:s,p4:i})=>{const r=e.sub(s),n=i.sub(s),o=t.sub(e),a=r.dot(n),h=n.dot(o),u=r.dot(o),l=n.dot(n),c=o.dot(o).mul(l).sub(h.mul(h)),d=a.mul(h).sub(u.mul(l)).div(c).clamp(),p=a.add(h.mul(d)).div(l).clamp();return Dp(d,p)}));this.fragmentNode=Rp((()=>{const n=My();if(i){const e=this.offsetNode?Up(this.offsetNodeNode):Yb,t=this.dashScaleNode?Up(this.dashScaleNode):Hb,s=this.dashSizeNode?Up(this.dashSizeNode):qb,i=this.dashSizeNode?Up(this.dashGapNode):$b;Um.assign(s),Om.assign(i);const r=Sy("instanceDistanceStart"),o=Sy("instanceDistanceEnd"),a=ox.y.lessThan(.5).select(t.mul(r),Hb.mul(o)),h=Vf(a.add(Yb)),u=e?h.add(e):h;n.y.lessThan(-1).or(n.y.greaterThan(1)).discard(),u.mod(Um.add(Om)).greaterThan(Um).discard()}const a=Up(1).toVar("alpha");if(r){const s=fm("vec3","worldStart"),r=fm("vec3","worldEnd"),n=fm("vec4","worldPos").xyz.normalize().mul(1e5),h=r.sub(s),u=o({p1:s,p2:r,p3:jp(0,0,0),p4:n}),l=s.add(h.mul(u.x)),c=n.mul(u.y),d=l.sub(c).length().div(Xb);if(!i)if(t&&e.samples>1){const e=d.fwidth();a.assign(Mf(e.negate().add(.5),e.add(.5),d).oneMinus())}else d.greaterThan(.5).discard()}else if(t&&e.samples>1){const e=n.x,t=n.y.greaterThan(0).select(n.y.sub(1),n.y.add(1)),s=e.mul(e).add(t.mul(t)),i=Up(s.fwidth()).toVar("dlen");Pp(n.y.abs().greaterThan(1),(()=>{a.assign(Mf(i.oneMinus(),i.add(1),s).oneMinus())}))}else Pp(n.y.abs().greaterThan(1),(()=>{const e=n.x,t=n.y.greaterThan(0).select(n.y.sub(1),n.y.add(1));e.mul(e).add(t.mul(t)).greaterThan(1).discard()}));let h;if(this.lineColorNode)h=this.lineColorNode;else if(s){const e=Sy("instanceColorStart"),t=Sy("instanceColorEnd");h=ox.y.lessThan(.5).select(e,t).mul(xb)}else h=xb;return Xp(h,a)}))()}get worldUnits(){return this.useWorldUnits}set worldUnits(e){this.useWorldUnits!==e&&(this.useWorldUnits=e,this.needsUpdate=!0)}get dashed(){return this.useDash}set dashed(e){this.useDash!==e&&(this.useDash=e,this.needsUpdate=!0)}get alphaToCoverage(){return this.useAlphaToCoverage}set alphaToCoverage(e){this.useAlphaToCoverage!==e&&(this.useAlphaToCoverage=e,this.needsUpdate=!0)}}const _T=e=>Sp(e).mul(.5).add(.5),wT=e=>Sp(e).mul(2).sub(1),ST=new Nu;class MT extends pT{static get type(){return"MeshNormalNodeMaterial"}constructor(e){super(),this.lights=!1,this.isMeshNormalNodeMaterial=!0,this.setDefaultValues(ST),this.setValues(e)}setupDiffuseColor(){const e=this.opacityNode?Up(this.opacityNode):Tb;ym.assign(Xp(_T(Tx),e))}}class NT extends kd{static get type(){return"EquirectUVNode"}constructor(e=lx){super("vec2"),this.dirNode=e}setup(){const e=this.dirNode,t=e.z.atan2(e.x).mul(1/(2*Math.PI)).add(.5),s=e.y.clamp(-1,1).asin().mul(1/Math.PI).add(.5);return Dp(t,s)}}const AT=Ap(NT);class CT extends Kn{constructor(e=1,t={}){super(e,t),this.isCubeRenderTarget=!0}fromEquirectangularTexture(e,t){const s=t.minFilter,i=t.generateMipmaps;t.generateMipmaps=!0,this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;const r=new kn(5,5,5),n=AT(lx),o=new pT;o.colorNode=By(t,n,0),o.side=d,o.blending=m;const a=new Vn(r,o),h=new to;h.add(a),t.minFilter===Se&&(t.minFilter=Te);const u=new Zn(1,10,this),l=e.getMRT();return e.setMRT(null),u.update(e,h),e.setMRT(l),t.minFilter=s,t.currentGenerateMipmaps=i,a.geometry.dispose(),a.material.dispose(),this}}const RT=new WeakMap;class ET extends kd{static get type(){return"CubeMapNode"}constructor(e){super("vec3"),this.envNode=e,this._cubeTexture=null,this._cubeTextureNode=Ix();const t=new Jn;t.isRenderTargetTexture=!0,this._defaultTexture=t,this.updateBeforeType=Bd.RENDER}updateBefore(e){const{renderer:t,material:s}=e,i=this.envNode;if(i.isTextureNode||i.isMaterialReferenceNode){const e=i.isTextureNode?i.value:s[i.property];if(e&&e.isTexture){const s=e.mapping;if(s===le||s===ce){if(RT.has(e)){const t=RT.get(e);IT(t,e.mapping),this._cubeTexture=t}else{const s=e.image;if(function(e){return null!=e&&e.height>0}(s)){const i=new CT(s.height);i.fromEquirectangularTexture(t,e),IT(i.texture,e.mapping),this._cubeTexture=i.texture,RT.set(e,i.texture),e.addEventListener("dispose",BT)}else this._cubeTexture=this._defaultTexture}this._cubeTextureNode.value=this._cubeTexture}else this._cubeTextureNode=this.envNode}}}setup(e){return this.updateBefore(e),this._cubeTextureNode}}function BT(e){const t=e.target;t.removeEventListener("dispose",BT);const s=RT.get(t);void 0!==s&&(RT.delete(t),s.dispose())}function IT(e,t){t===le?e.mapping=he:t===ce&&(e.mapping=ue)}const PT=Ap(ET);class FT extends Iv{static get type(){return"BasicEnvironmentNode"}constructor(e=null){super(),this.envNode=e}setup(e){e.context.environment=PT(this.envNode)}}class zT extends Iv{static get type(){return"BasicLightMapNode"}constructor(e=null){super(),this.lightMapNode=e}setup(e){const t=Up(1/Math.PI);e.context.irradianceLightMap=this.lightMapNode.mul(t)}}class UT{start(){}finish(){}direct(){}directRectArea(){}indirect(){}ambientOcclusion(){}}class OT extends UT{constructor(){super()}indirect(e,t,s){const i=e.ambientOcclusion,r=e.reflectedLight,n=s.context.irradianceLightMap;r.indirectDiffuse.assign(Xp(0)),n?r.indirectDiffuse.addAssign(n):r.indirectDiffuse.addAssign(Xp(1,1,1,0)),r.indirectDiffuse.mulAssign(i),r.indirectDiffuse.mulAssign(ym.rgb)}finish(e,t,s){const i=s.material,r=e.outgoingLight,n=s.context.environment;if(n)switch(i.combine){case 0:r.rgb.assign(Tf(r.rgb,r.rgb.mul(n.rgb),Mb.mul(Nb)));break;case 1:r.rgb.assign(Tf(r.rgb,n.rgb,Mb.mul(Nb)));break;case 2:r.rgb.addAssign(n.rgb.mul(Mb.mul(Nb)));break;default:console.warn("THREE.BasicLightingModel: Unsupported .combine value:",i.combine)}}}const LT=new tn;class VT extends pT{static get type(){return"MeshBasicNodeMaterial"}constructor(e){super(),this.isMeshBasicNodeMaterial=!0,this.lights=!0,this.setDefaultValues(LT),this.setValues(e)}setupNormal(){return bx}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new FT(t):null}setupLightMap(e){let t=null;return e.material.lightMap&&(t=new zT(Kb)),t}setupOutgoingLight(){return ym.rgb}setupLightingModel(){return new OT}}const DT=Rp((({f0:e,f90:t,dotVH:s})=>{const i=s.mul(-5.55473).sub(6.98316).mul(s).exp2();return e.mul(i.oneMinus()).add(t.mul(i))})),kT=Rp((e=>e.diffuseColor.mul(1/Math.PI))),GT=Rp((({dotNH:e})=>Fm.mul(Up(.5)).add(1).mul(Up(1/Math.PI)).mul(e.pow(Fm)))),WT=Rp((({lightDirection:e})=>{const t=e.add(dx).normalize(),s=Tx.dot(t).clamp(),i=dx.dot(t).clamp(),r=DT({f0:Im,f90:1,dotVH:i}),n=Up(.25),o=GT({dotNH:s});return r.mul(n).mul(o)}));class jT extends OT{constructor(e=!0){super(),this.specular=e}direct({lightDirection:e,lightColor:t,reflectedLight:s}){const i=Tx.dot(e).clamp().mul(t);s.directDiffuse.addAssign(i.mul(kT({diffuseColor:ym.rgb}))),!0===this.specular&&s.directSpecular.addAssign(i.mul(WT({lightDirection:e})).mul(Mb))}indirect({ambientOcclusion:e,irradiance:t,reflectedLight:s}){s.indirectDiffuse.addAssign(t.mul(kT({diffuseColor:ym}))),s.indirectDiffuse.mulAssign(e)}}const HT=new Au;class qT extends pT{static get type(){return"MeshLambertNodeMaterial"}constructor(e){super(),this.isMeshLambertNodeMaterial=!0,this.lights=!0,this.setDefaultValues(HT),this.setValues(e)}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new FT(t):null}setupLightingModel(){return new jT(!1)}}const $T=new Su;class XT extends pT{static get type(){return"MeshPhongNodeMaterial"}constructor(e){super(),this.isMeshPhongNodeMaterial=!0,this.lights=!0,this.shininessNode=null,this.specularNode=null,this.setDefaultValues($T),this.setValues(e)}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new FT(t):null}setupLightingModel(){return new jT}setupVariants(){const e=(this.shininessNode?Up(this.shininessNode):bb).max(1e-4);Fm.assign(e);const t=this.specularNode||_b;Im.assign(t)}copy(e){return this.shininessNode=e.shininessNode,this.specularNode=e.specularNode,super.copy(e)}}const YT=Rp((()=>{const e=bx.dFdx().abs().max(bx.dFdy().abs());return e.x.max(e.y).max(e.z)})),ZT=Rp((e=>{const{roughness:t}=e,s=YT();let i=t.max(.0525);return i=i.add(s),i=i.min(1),i})),JT=Rp((({alpha:e,dotNL:t,dotNV:s})=>{const i=e.pow2(),r=t.mul(i.add(i.oneMinus().mul(s.pow2())).sqrt()),n=s.mul(i.add(i.oneMinus().mul(t.pow2())).sqrt());return Qm(.5,r.add(n).max(bg))})).setLayout({name:"V_GGX_SmithCorrelated",type:"float",inputs:[{name:"alpha",type:"float"},{name:"dotNL",type:"float"},{name:"dotNV",type:"float"}]}),KT=Rp((({alphaT:e,alphaB:t,dotTV:s,dotBV:i,dotTL:r,dotBL:n,dotNV:o,dotNL:a})=>{const h=a.mul(jp(e.mul(s),t.mul(i),o).length()),u=o.mul(jp(e.mul(r),t.mul(n),a).length());return Qm(.5,h.add(u)).saturate()})).setLayout({name:"V_GGX_SmithCorrelated_Anisotropic",type:"float",inputs:[{name:"alphaT",type:"float",qualifier:"in"},{name:"alphaB",type:"float",qualifier:"in"},{name:"dotTV",type:"float",qualifier:"in"},{name:"dotBV",type:"float",qualifier:"in"},{name:"dotTL",type:"float",qualifier:"in"},{name:"dotBL",type:"float",qualifier:"in"},{name:"dotNV",type:"float",qualifier:"in"},{name:"dotNL",type:"float",qualifier:"in"}]}),QT=Rp((({alpha:e,dotNH:t})=>{const s=e.pow2(),i=t.pow2().mul(s.oneMinus()).oneMinus();return s.div(i.pow2()).mul(1/Math.PI)})).setLayout({name:"D_GGX",type:"float",inputs:[{name:"alpha",type:"float"},{name:"dotNH",type:"float"}]}),e_=Up(1/Math.PI),t_=Rp((({alphaT:e,alphaB:t,dotNH:s,dotTH:i,dotBH:r})=>{const n=e.mul(t),o=jp(t.mul(i),e.mul(r),n.mul(s)),a=o.dot(o),h=n.div(a);return e_.mul(n.mul(h.pow2()))})).setLayout({name:"D_GGX_Anisotropic",type:"float",inputs:[{name:"alphaT",type:"float",qualifier:"in"},{name:"alphaB",type:"float",qualifier:"in"},{name:"dotNH",type:"float",qualifier:"in"},{name:"dotTH",type:"float",qualifier:"in"},{name:"dotBH",type:"float",qualifier:"in"}]}),s_=Rp((e=>{const{lightDirection:t,f0:s,f90:i,roughness:r,f:n,USE_IRIDESCENCE:o,USE_ANISOTROPY:a}=e,h=e.normalView||Tx,u=r.pow2(),l=t.add(dx).normalize(),c=h.dot(t).clamp(),d=h.dot(dx).clamp(),p=h.dot(l).clamp(),m=dx.dot(l).clamp();let g,f,y=DT({f0:s,f90:i,dotVH:m});if(Tp(o)&&(y=Mm.mix(y,n)),Tp(a)){const e=Em.dot(t),s=Em.dot(dx),i=Em.dot(l),r=Bm.dot(t),n=Bm.dot(dx),o=Bm.dot(l);g=KT({alphaT:Cm,alphaB:u,dotTV:s,dotBV:n,dotTL:e,dotBL:r,dotNV:d,dotNL:c}),f=t_({alphaT:Cm,alphaB:u,dotNH:p,dotTH:i,dotBH:o})}else g=JT({alpha:u,dotNL:c,dotNV:d}),f=QT({alpha:u,dotNH:p});return y.mul(g).mul(f)})),i_=Rp((({roughness:e,dotNV:t})=>{const s=Xp(-1,-.0275,-.572,.022),i=Xp(1,.0425,1.04,-.04),r=e.mul(s).add(i),n=r.x.mul(r.x).min(t.mul(-9.28).exp2()).mul(r.x).add(r.y);return Dp(-1.04,1.04).mul(n).add(r.zw)})).setLayout({name:"DFGApprox",type:"vec2",inputs:[{name:"roughness",type:"float"},{name:"dotNV",type:"vec3"}]}),r_=Rp((e=>{const{dotNV:t,specularColor:s,specularF90:i,roughness:r}=e,n=i_({dotNV:t,roughness:r});return s.mul(n.x).add(i.mul(n.y))})),n_=Rp((({f:e,f90:t,dotVH:s})=>{const i=s.oneMinus().saturate(),r=i.mul(i),n=i.mul(r,r).clamp(0,.9999);return e.sub(jp(t).mul(n)).div(n.oneMinus())})).setLayout({name:"Schlick_to_F0",type:"vec3",inputs:[{name:"f",type:"vec3"},{name:"f90",type:"float"},{name:"dotVH",type:"float"}]}),o_=Rp((({roughness:e,dotNH:t})=>{const s=e.pow2(),i=Up(1).div(s),r=t.pow2().oneMinus().max(.0078125);return Up(2).add(i).mul(r.pow(i.mul(.5))).div(2*Math.PI)})).setLayout({name:"D_Charlie",type:"float",inputs:[{name:"roughness",type:"float"},{name:"dotNH",type:"float"}]}),a_=Rp((({dotNV:e,dotNL:t})=>Up(1).div(Up(4).mul(t.add(e).sub(t.mul(e)))))).setLayout({name:"V_Neubelt",type:"float",inputs:[{name:"dotNV",type:"float"},{name:"dotNL",type:"float"}]}),h_=Rp((({lightDirection:e})=>{const t=e.add(dx).normalize(),s=Tx.dot(e).clamp(),i=Tx.dot(dx).clamp(),r=Tx.dot(t).clamp(),n=o_({roughness:Sm,dotNH:r}),o=a_({dotNV:i,dotNL:s});return wm.mul(n).mul(o)})),u_=Rp((({N:e,V:t,roughness:s})=>{const i=e.dot(t).saturate(),r=Dp(s,i.oneMinus().sqrt());return r.assign(r.mul(.984375).add(.0078125)),r})).setLayout({name:"LTC_Uv",type:"vec2",inputs:[{name:"N",type:"vec3"},{name:"V",type:"vec3"},{name:"roughness",type:"float"}]}),l_=Rp((({f:e})=>{const t=e.length();return of(t.mul(t).add(e.z).div(t.add(1)),0)})).setLayout({name:"LTC_ClippedSphereFormFactor",type:"float",inputs:[{name:"f",type:"vec3"}]}),c_=Rp((({v1:e,v2:t})=>{const s=e.dot(t),i=s.abs().toVar(),r=i.mul(.0145206).add(.4965155).mul(i).add(.8543985).toVar(),n=i.add(4.1616724).mul(i).add(3.417594).toVar(),o=r.div(n),a=s.greaterThan(0).select(o,of(s.mul(s).oneMinus(),1e-7).inverseSqrt().mul(.5).sub(o));return e.cross(t).mul(a)})).setLayout({name:"LTC_EdgeVectorFormFactor",type:"vec3",inputs:[{name:"v1",type:"vec3"},{name:"v2",type:"vec3"}]}),d_=Rp((({N:e,V:t,P:s,mInv:i,p0:r,p1:n,p2:o,p3:a})=>{const h=n.sub(r).toVar(),u=a.sub(r).toVar(),l=h.cross(u),c=jp().toVar();return Pp(l.dot(s.sub(r)).greaterThanEqual(0),(()=>{const h=t.sub(e.mul(t.dot(e))).normalize(),u=e.cross(h).negate(),l=i.mul(Qp(h,u,e).transpose()).toVar(),d=l.mul(r.sub(s)).normalize().toVar(),p=l.mul(n.sub(s)).normalize().toVar(),m=l.mul(o.sub(s)).normalize().toVar(),g=l.mul(a.sub(s)).normalize().toVar(),f=jp(0).toVar();f.addAssign(c_({v1:d,v2:p})),f.addAssign(c_({v1:p,v2:m})),f.addAssign(c_({v1:m,v2:g})),f.addAssign(c_({v1:g,v2:d})),c.assign(jp(l_({f:f})))})),c})).setLayout({name:"LTC_Evaluate",type:"vec3",inputs:[{name:"N",type:"vec3"},{name:"V",type:"vec3"},{name:"P",type:"vec3"},{name:"mInv",type:"mat3"},{name:"p0",type:"vec3"},{name:"p1",type:"vec3"},{name:"p2",type:"vec3"},{name:"p3",type:"vec3"}]}),p_=1/6,m_=e=>Km(p_,Km(e,Km(e,e.negate().add(3)).sub(3)).add(1)),g_=e=>Km(p_,Km(e,Km(e,Km(3,e).sub(6))).add(4)),f_=e=>Km(p_,Km(e,Km(e,Km(-3,e).add(3)).add(3)).add(1)),y_=e=>Km(p_,mf(e,3)),x_=e=>m_(e).add(g_(e)),b_=e=>f_(e).add(y_(e)),v_=e=>Zm(-1,g_(e).div(m_(e).add(g_(e)))),T_=e=>Zm(1,y_(e).div(f_(e).add(y_(e)))),__=(e,t,s)=>{const i=e.uvNode,r=Km(i,t.zw).add(.5),n=Fg(r),o=Og(r),a=x_(o.x),h=b_(o.x),u=v_(o.x),l=T_(o.x),c=v_(o.y),d=T_(o.y),p=Dp(n.x.add(u),n.y.add(c)).sub(.5).mul(t.xy),m=Dp(n.x.add(l),n.y.add(c)).sub(.5).mul(t.xy),g=Dp(n.x.add(u),n.y.add(d)).sub(.5).mul(t.xy),f=Dp(n.x.add(l),n.y.add(d)).sub(.5).mul(t.xy),y=x_(o.y).mul(Zm(a.mul(e.uv(p).level(s)),h.mul(e.uv(m).level(s)))),x=b_(o.y).mul(Zm(a.mul(e.uv(g).level(s)),h.mul(e.uv(f).level(s))));return y.add(x)},w_=Rp((([e,t=Up(3)])=>{const s=Dp(e.size(Op(t))),i=Dp(e.size(Op(t.add(1)))),r=Qm(1,s),n=Qm(1,i),o=__(e,Xp(r,s),Fg(t)),a=__(e,Xp(n,i),zg(t));return Og(t).mix(o,a)})),S_=Rp((([e,t,s,i,r])=>{const n=jp(Sf(t.negate(),Ug(e),Qm(1,i))),o=jp(qg(r[0].xyz),qg(r[1].xyz),qg(r[2].xyz));return Ug(n).mul(s.mul(o))})).setLayout({name:"getVolumeTransmissionRay",type:"vec3",inputs:[{name:"n",type:"vec3"},{name:"v",type:"vec3"},{name:"thickness",type:"float"},{name:"ior",type:"float"},{name:"modelMatrix",type:"mat4"}]}),M_=Rp((([e,t])=>e.mul(_f(t.mul(2).sub(2),0,1)))).setLayout({name:"applyIorToRoughness",type:"float",inputs:[{name:"roughness",type:"float"},{name:"ior",type:"float"}]}),N_=Qv(),A_=Rp((([e,t,s])=>{const i=N_.uv(e),r=Bg(Up(kv.x)).mul(M_(t,s));return w_(i,r)})),C_=Rp((([e,t,s])=>(Pp(s.notEqual(0),(()=>{const i=Eg(t).negate().div(s);return Cg(i.negate().mul(e))})),jp(1)))).setLayout({name:"volumeAttenuation",type:"vec3",inputs:[{name:"transmissionDistance",type:"float"},{name:"attenuationColor",type:"vec3"},{name:"attenuationDistance",type:"float"}]}),R_=Rp((([e,t,s,i,r,n,o,a,h,u,l,c,d,p,m])=>{let g,f;if(m){g=Xp().toVar(),f=jp().toVar();const r=l.sub(1).mul(m.mul(.025)),n=jp(l.sub(r),l,l.add(r));bv({start:0,end:3},(({i:r})=>{const l=n.element(r),m=S_(e,t,c,l,a),y=o.add(m),x=u.mul(h.mul(Xp(y,1))),b=Dp(x.xy.div(x.w)).toVar();b.addAssign(1),b.divAssign(2),b.assign(Dp(b.x,b.y.oneMinus()));const v=A_(b,s,l);g.element(r).assign(v.element(r)),g.a.addAssign(v.a),f.element(r).assign(i.element(r).mul(C_(qg(m),d,p).element(r)))})),g.a.divAssign(3)}else{const r=S_(e,t,c,l,a),n=o.add(r),m=u.mul(h.mul(Xp(n,1))),y=Dp(m.xy.div(m.w)).toVar();y.addAssign(1),y.divAssign(2),y.assign(Dp(y.x,y.y.oneMinus())),g=A_(y,s,l),f=i.mul(C_(qg(r),d,p))}const y=f.rgb.mul(g.rgb),x=e.dot(t).clamp(),b=jp(r_({dotNV:x,specularColor:r,specularF90:n,roughness:s})),v=f.r.add(f.g,f.b).div(3);return Xp(b.oneMinus().mul(y),g.a.oneMinus().mul(v).oneMinus())})),E_=Qp(3.2404542,-.969266,.0556434,-1.5371385,1.8760108,-.2040259,-.4985314,.041556,1.0572252),B_=(e,t)=>e.sub(t).div(e.add(t)).pow2(),I_=(e,t)=>{const s=e.mul(2*Math.PI*1e-9),i=jp(54856e-17,44201e-17,52481e-17),r=jp(1681e3,1795300,2208400),n=jp(43278e5,93046e5,66121e5),o=Up(9747e-17*Math.sqrt(2*Math.PI*45282e5)).mul(s.mul(2239900).add(t.x).cos()).mul(s.pow2().mul(-45282e5).exp());let a=i.mul(n.mul(2*Math.PI).sqrt()).mul(r.mul(s).add(t).cos()).mul(s.pow2().negate().mul(n).exp());a=jp(a.x.add(o),a.y,a.z).div(1.0685e-7);return E_.mul(a)},P_=Rp((({outsideIOR:e,eta2:t,cosTheta1:s,thinFilmThickness:i,baseF0:r})=>{const n=Tf(e,t,Mf(0,.03,i)),o=e.div(n).pow2().mul(Up(1).sub(s.pow2())),a=Up(1).sub(o).sqrt(),h=B_(n,e),u=DT({f0:h,f90:1,dotVH:s}),l=u.oneMinus(),c=n.lessThan(e).select(Math.PI,0),d=Up(Math.PI).sub(c),p=(e=>{const t=e.sqrt();return jp(1).add(t).div(jp(1).sub(t))})(r.clamp(0,.9999)),m=B_(p,n.toVec3()),g=DT({f0:m,f90:1,dotVH:a}),f=jp(p.x.lessThan(n).select(Math.PI,0),p.y.lessThan(n).select(Math.PI,0),p.z.lessThan(n).select(Math.PI,0)),y=n.mul(i,a,2),x=jp(d).add(f),b=u.mul(g).clamp(1e-5,.9999),v=b.sqrt(),T=l.pow2().mul(g).div(jp(1).sub(b));let _=u.add(T),w=T.sub(l);for(let e=1;e<=2;++e){w=w.mul(v);const t=I_(Up(e).mul(y),Up(e).mul(x)).mul(2);_=_.add(w.mul(t))}return _.max(jp(0))})).setLayout({name:"evalIridescence",type:"vec3",inputs:[{name:"outsideIOR",type:"float"},{name:"eta2",type:"float"},{name:"cosTheta1",type:"float"},{name:"thinFilmThickness",type:"float"},{name:"baseF0",type:"vec3"}]}),F_=Rp((({normal:e,viewDir:t,roughness:s})=>{const i=e.dot(t).saturate(),r=s.pow2(),n=Bf(s.lessThan(.25),Up(-339.2).mul(r).add(Up(161.4).mul(s)).sub(25.9),Up(-8.48).mul(r).add(Up(14.3).mul(s)).sub(9.95)),o=Bf(s.lessThan(.25),Up(44).mul(r).sub(Up(23.7).mul(s)).add(3.26),Up(1.97).mul(r).sub(Up(3.27).mul(s)).add(.72));return Bf(s.lessThan(.25),0,Up(.1).mul(s).sub(.025)).add(n.mul(i).add(o).exp()).mul(1/Math.PI).saturate()})),z_=jp(.04),U_=Up(1);class O_ extends UT{constructor(e=!1,t=!1,s=!1,i=!1,r=!1,n=!1){super(),this.clearcoat=e,this.sheen=t,this.iridescence=s,this.anisotropy=i,this.transmission=r,this.dispersion=n,this.clearcoatRadiance=null,this.clearcoatSpecularDirect=null,this.clearcoatSpecularIndirect=null,this.sheenSpecularDirect=null,this.sheenSpecularIndirect=null,this.iridescenceFresnel=null,this.iridescenceF0=null}start(e){if(!0===this.clearcoat&&(this.clearcoatRadiance=jp().toVar("clearcoatRadiance"),this.clearcoatSpecularDirect=jp().toVar("clearcoatSpecularDirect"),this.clearcoatSpecularIndirect=jp().toVar("clearcoatSpecularIndirect")),!0===this.sheen&&(this.sheenSpecularDirect=jp().toVar("sheenSpecularDirect"),this.sheenSpecularIndirect=jp().toVar("sheenSpecularIndirect")),!0===this.iridescence){const e=Tx.dot(dx).clamp();this.iridescenceFresnel=P_({outsideIOR:Up(1),eta2:Nm,cosTheta1:e,thinFilmThickness:Am,baseF0:Im}),this.iridescenceF0=n_({f:this.iridescenceFresnel,f90:1,dotVH:e})}if(!0===this.transmission){const t=ux,s=Gy.sub(ux).normalize(),i=_x;e.backdrop=R_(i,s,bm,ym,Im,Pm,t,Jy,Vy,Oy,Vm,km,Wm,Gm,this.dispersion?jm:null),e.backdropAlpha=Dm,ym.a.mulAssign(Tf(1,e.backdrop.a,Dm))}}computeMultiscattering(e,t,s){const i=Tx.dot(dx).clamp(),r=i_({roughness:bm,dotNV:i}),n=(this.iridescenceF0?Mm.mix(Im,this.iridescenceF0):Im).mul(r.x).add(s.mul(r.y)),o=r.x.add(r.y).oneMinus(),a=Im.add(Im.oneMinus().mul(.047619)),h=n.mul(a).div(o.mul(a).oneMinus());e.addAssign(n),t.addAssign(h.mul(o))}direct({lightDirection:e,lightColor:t,reflectedLight:s}){const i=Tx.dot(e).clamp().mul(t);if(!0===this.sheen&&this.sheenSpecularDirect.addAssign(i.mul(h_({lightDirection:e}))),!0===this.clearcoat){const s=wx.dot(e).clamp().mul(t);this.clearcoatSpecularDirect.addAssign(s.mul(s_({lightDirection:e,f0:z_,f90:U_,roughness:_m,normalView:wx})))}s.directDiffuse.addAssign(i.mul(kT({diffuseColor:ym.rgb}))),s.directSpecular.addAssign(i.mul(s_({lightDirection:e,f0:Im,f90:1,roughness:bm,iridescence:this.iridescence,f:this.iridescenceFresnel,USE_IRIDESCENCE:this.iridescence,USE_ANISOTROPY:this.anisotropy})))}directRectArea({lightColor:e,lightPosition:t,halfWidth:s,halfHeight:i,reflectedLight:r,ltc_1:n,ltc_2:o}){const a=t.add(s).sub(i),h=t.sub(s).sub(i),u=t.sub(s).add(i),l=t.add(s).add(i),c=Tx,d=dx,p=cx.toVar(),m=u_({N:c,V:d,roughness:bm}),g=n.uv(m).toVar(),f=o.uv(m).toVar(),y=Qp(jp(g.x,0,g.y),jp(0,1,0),jp(g.z,0,g.w)).toVar(),x=Im.mul(f.x).add(Im.oneMinus().mul(f.y)).toVar();r.directSpecular.addAssign(e.mul(x).mul(d_({N:c,V:d,P:p,mInv:y,p0:a,p1:h,p2:u,p3:l}))),r.directDiffuse.addAssign(e.mul(ym).mul(d_({N:c,V:d,P:p,mInv:Qp(1,0,0,0,1,0,0,0,1),p0:a,p1:h,p2:u,p3:l})))}indirect(e,t,s){this.indirectDiffuse(e,t,s),this.indirectSpecular(e,t,s),this.ambientOcclusion(e,t,s)}indirectDiffuse({irradiance:e,reflectedLight:t}){t.indirectDiffuse.addAssign(e.mul(kT({diffuseColor:ym})))}indirectSpecular({radiance:e,iblIrradiance:t,reflectedLight:s}){if(!0===this.sheen&&this.sheenSpecularIndirect.addAssign(t.mul(wm,F_({normal:Tx,viewDir:dx,roughness:Sm}))),!0===this.clearcoat){const e=wx.dot(dx).clamp(),t=r_({dotNV:e,specularColor:z_,specularF90:U_,roughness:_m});this.clearcoatSpecularIndirect.addAssign(this.clearcoatRadiance.mul(t))}const i=jp().toVar("singleScattering"),r=jp().toVar("multiScattering"),n=t.mul(1/Math.PI);this.computeMultiscattering(i,r,Pm);const o=i.add(r),a=ym.mul(o.r.max(o.g).max(o.b).oneMinus());s.indirectSpecular.addAssign(e.mul(i)),s.indirectSpecular.addAssign(r.mul(n)),s.indirectDiffuse.addAssign(a.mul(n))}ambientOcclusion({ambientOcclusion:e,reflectedLight:t}){const s=Tx.dot(dx).clamp().add(e),i=bm.mul(-16).oneMinus().negate().exp2(),r=e.sub(s.pow(i).oneMinus()).clamp();!0===this.clearcoat&&this.clearcoatSpecularIndirect.mulAssign(e),!0===this.sheen&&this.sheenSpecularIndirect.mulAssign(e),t.indirectDiffuse.mulAssign(e),t.indirectSpecular.mulAssign(r)}finish(e){const{outgoingLight:t}=e;if(!0===this.clearcoat){const e=wx.dot(dx).clamp(),s=DT({dotVH:e,f0:z_,f90:U_}),i=t.mul(Tm.mul(s).oneMinus()).add(this.clearcoatSpecularDirect.add(this.clearcoatSpecularIndirect).mul(Tm));t.assign(i)}if(!0===this.sheen){const e=wm.r.max(wm.g).max(wm.b).mul(.157).oneMinus(),s=t.mul(e).add(this.sheenSpecularDirect,this.sheenSpecularIndirect);t.assign(s)}}}const L_=Up(1),V_=Up(-2),D_=Up(.8),k_=Up(-1),G_=Up(.4),W_=Up(2),j_=Up(.305),H_=Up(3),q_=Up(.21),$_=Up(4),X_=Up(4),Y_=Up(16),Z_=Rp((([e])=>{const t=jp(jg(e)).toVar(),s=Up(-1).toVar();return Pp(t.x.greaterThan(t.z),(()=>{Pp(t.x.greaterThan(t.y),(()=>{s.assign(Bf(e.x.greaterThan(0),0,3))})).Else((()=>{s.assign(Bf(e.y.greaterThan(0),1,4))}))})).Else((()=>{Pp(t.z.greaterThan(t.y),(()=>{s.assign(Bf(e.z.greaterThan(0),2,5))})).Else((()=>{s.assign(Bf(e.y.greaterThan(0),1,4))}))})),s})).setLayout({name:"getFace",type:"float",inputs:[{name:"direction",type:"vec3"}]}),J_=Rp((([e,t])=>{const s=Dp().toVar();return Pp(t.equal(0),(()=>{s.assign(Dp(e.z,e.y).div(jg(e.x)))})).ElseIf(t.equal(1),(()=>{s.assign(Dp(e.x.negate(),e.z.negate()).div(jg(e.y)))})).ElseIf(t.equal(2),(()=>{s.assign(Dp(e.x.negate(),e.y).div(jg(e.z)))})).ElseIf(t.equal(3),(()=>{s.assign(Dp(e.z.negate(),e.y).div(jg(e.x)))})).ElseIf(t.equal(4),(()=>{s.assign(Dp(e.x.negate(),e.z).div(jg(e.y)))})).Else((()=>{s.assign(Dp(e.x,e.y).div(jg(e.z)))})),Km(.5,s.add(1))})).setLayout({name:"getUV",type:"vec2",inputs:[{name:"direction",type:"vec3"},{name:"face",type:"float"}]}),K_=Rp((([e])=>{const t=Up(0).toVar();return Pp(e.greaterThanEqual(D_),(()=>{t.assign(L_.sub(e).mul(k_.sub(V_)).div(L_.sub(D_)).add(V_))})).ElseIf(e.greaterThanEqual(G_),(()=>{t.assign(D_.sub(e).mul(W_.sub(k_)).div(D_.sub(G_)).add(k_))})).ElseIf(e.greaterThanEqual(j_),(()=>{t.assign(G_.sub(e).mul(H_.sub(W_)).div(G_.sub(j_)).add(W_))})).ElseIf(e.greaterThanEqual(q_),(()=>{t.assign(j_.sub(e).mul($_.sub(H_)).div(j_.sub(q_)).add(H_))})).Else((()=>{t.assign(Up(-2).mul(Bg(Km(1.16,e))))})),t})).setLayout({name:"roughnessToMip",type:"float",inputs:[{name:"roughness",type:"float"}]}),Q_=Rp((([e,t])=>{const s=e.toVar();s.assign(Km(2,s).sub(1));const i=jp(s,1).toVar();return Pp(t.equal(0),(()=>{i.assign(i.zyx)})).ElseIf(t.equal(1),(()=>{i.assign(i.xzy),i.xz.mulAssign(-1)})).ElseIf(t.equal(2),(()=>{i.x.mulAssign(-1)})).ElseIf(t.equal(3),(()=>{i.assign(i.zyx),i.xz.mulAssign(-1)})).ElseIf(t.equal(4),(()=>{i.assign(i.xzy),i.xy.mulAssign(-1)})).ElseIf(t.equal(5),(()=>{i.z.mulAssign(-1)})),i})).setLayout({name:"getDirection",type:"vec3",inputs:[{name:"uv",type:"vec2"},{name:"face",type:"float"}]}),ew=Rp((([e,t,s,i,r,n])=>{const o=Up(s),a=jp(t),h=_f(K_(o),V_,n),u=Og(h),l=Fg(h),c=jp(tw(e,a,l,i,r,n)).toVar();return Pp(u.notEqual(0),(()=>{const t=jp(tw(e,a,l.add(1),i,r,n)).toVar();c.assign(Tf(c,t,u))})),c})),tw=Rp((([e,t,s,i,r,n])=>{const o=Up(s).toVar(),a=jp(t),h=Up(Z_(a)).toVar(),u=Up(of(X_.sub(o),0)).toVar();o.assign(of(o,X_));const l=Up(Rg(o)).toVar(),c=Dp(J_(a,h).mul(l.sub(2)).add(1)).toVar();return Pp(h.greaterThan(2),(()=>{c.y.addAssign(l),h.subAssign(3)})),c.x.addAssign(h.mul(l)),c.x.addAssign(u.mul(Km(3,Y_))),c.y.addAssign(Km(4,Rg(n).sub(l))),c.x.mulAssign(i),c.y.mulAssign(r),e.uv(c).grad(Dp(),Dp())})),sw=Rp((({envMap:e,mipInt:t,outputDirection:s,theta:i,axis:r,CUBEUV_TEXEL_WIDTH:n,CUBEUV_TEXEL_HEIGHT:o,CUBEUV_MAX_MIP:a})=>{const h=Vg(i),u=s.mul(h).add(r.cross(s).mul(Lg(i))).add(r.mul(r.dot(s).mul(h.oneMinus())));return tw(e,u,t,n,o,a)})),iw=Rp((({n:e,latitudinal:t,poleAxis:s,outputDirection:i,weights:r,samples:n,dTheta:o,mipInt:a,envMap:h,CUBEUV_TEXEL_WIDTH:u,CUBEUV_TEXEL_HEIGHT:l,CUBEUV_MAX_MIP:c})=>{const d=jp(Bf(t,s,pf(s,i))).toVar();Pp(wg(d.equals(jp(0))),(()=>{d.assign(jp(i.z,0,i.x.negate()))})),d.assign(Ug(d));const p=jp().toVar();return p.addAssign(r.element(Op(0)).mul(sw({theta:0,axis:d,outputDirection:i,mipInt:a,envMap:h,CUBEUV_TEXEL_WIDTH:u,CUBEUV_TEXEL_HEIGHT:l,CUBEUV_MAX_MIP:c}))),bv({start:Op(1),end:e},(({i:e})=>{Pp(e.greaterThanEqual(n),(()=>{Tv()}));const t=Up(o.mul(Up(e))).toVar();p.addAssign(r.element(e).mul(sw({theta:t.mul(-1),axis:d,outputDirection:i,mipInt:a,envMap:h,CUBEUV_TEXEL_WIDTH:u,CUBEUV_TEXEL_HEIGHT:l,CUBEUV_MAX_MIP:c}))),p.addAssign(r.element(e).mul(sw({theta:t,axis:d,outputDirection:i,mipInt:a,envMap:h,CUBEUV_TEXEL_WIDTH:u,CUBEUV_TEXEL_HEIGHT:l,CUBEUV_MAX_MIP:c})))})),Xp(p,1)}));let rw=null;const nw=new WeakMap;function ow(e){let t=nw.get(e);if((void 0!==t?t.pmremVersion:-1)!==e.pmremVersion){const s=e.image;if(e.isCubeTexture){if(!function(e){if(null==e)return!1;let t=0;const s=6;for(let i=0;i0}(s))return null;t=rw.fromEquirectangular(e,t)}t.pmremVersion=e.pmremVersion,nw.set(e,t)}return t.texture}class aw extends kd{static get type(){return"PMREMNode"}constructor(e,t=null,s=null){super("vec3"),this._value=e,this._pmrem=null,this.uvNode=t,this.levelNode=s,this._generator=null;const i=new vi;i.isRenderTargetTexture=!0,this._texture=By(i),this._width=pm(0),this._height=pm(0),this._maxMip=pm(0),this.updateBeforeType=Bd.RENDER}set value(e){this._value=e,this._pmrem=null}get value(){return this._value}updateFromTexture(e){const t=function(e){const t=Math.log2(e)-2,s=1/e;return{texelWidth:1/(3*Math.max(Math.pow(2,t),112)),texelHeight:s,maxMip:t}}(e.image.height);this._texture.value=e,this._width.value=t.texelWidth,this._height.value=t.texelHeight,this._maxMip.value=t.maxMip}updateBefore(){let e=this._pmrem;const t=e?e.pmremVersion:-1,s=this._value;t!==s.pmremVersion&&(e=!0===s.isPMREMTexture?s:ow(s),null!==e&&(this._pmrem=e,this.updateFromTexture(e)))}setup(e){null===rw&&(rw=e.createPMREMGenerator()),this.updateBefore(e);let t=this.uvNode;null===t&&e.context.getUV&&(t=e.context.getUV(this));const s=this.value;e.renderer.coordinateSystem===Vs&&!0!==s.isPMREMTexture&&!0===s.isRenderTargetTexture&&(t=jp(t.x.negate(),t.yz));let i=this.levelNode;return null===i&&e.context.getTextureLevel&&(i=e.context.getTextureLevel(this)),ew(this._texture,t,i,this._width,this._height,this._maxMip)}}const hw=Ap(aw),uw=new WeakMap;class lw extends Iv{static get type(){return"EnvironmentNode"}constructor(e=null){super(),this.envNode=e}setup(e){const{material:t}=e;let s=this.envNode;if(s.isTextureNode||s.isMaterialReferenceNode){const e=s.isTextureNode?s.value:t[s.property];let i=uw.get(e);void 0===i&&(i=hw(e),uw.set(e,i)),s=i}const i=t.envMap?kx("envMapIntensity","float",e.material):kx("environmentIntensity","float",e.scene),r=!0===t.useAnisotropy||t.anisotropy>0?ab:Tx,n=s.context(cw(bm,r)).mul(i),o=s.context(dw(_x)).mul(Math.PI).mul(i),a=ly(n),h=ly(o);e.context.radiance.addAssign(a),e.context.iblIrradiance.addAssign(h);const u=e.context.lightingModel.clearcoatRadiance;if(u){const e=s.context(cw(_m,wx)).mul(i),t=ly(e);u.addAssign(t)}}}const cw=(e,t)=>{let s=null;return{getUV:()=>(null===s&&(s=dx.negate().reflect(t),s=e.mul(e).mix(s,t).normalize(),s=s.transformDirection(Vy)),s),getTextureLevel:()=>e}},dw=e=>({getUV:()=>e,getTextureLevel:()=>Up(1)}),pw=new _u;class mw extends pT{static get type(){return"MeshStandardNodeMaterial"}constructor(e){super(),this.isMeshStandardNodeMaterial=!0,this.lights=!0,this.emissiveNode=null,this.metalnessNode=null,this.roughnessNode=null,this.setDefaultValues(pw),this.setValues(e)}setupEnvironment(e){let t=super.setupEnvironment(e);return null===t&&e.environmentNode&&(t=e.environmentNode),t?new lw(t):null}setupLightingModel(){return new O_}setupSpecular(){const e=Tf(jp(.04),ym.rgb,vm);Im.assign(e),Pm.assign(1)}setupVariants(){const e=this.metalnessNode?Up(this.metalnessNode):Cb;vm.assign(e);let t=this.roughnessNode?Up(this.roughnessNode):Ab;t=ZT({roughness:t}),bm.assign(t),this.setupSpecular(),ym.assign(Xp(ym.rgb.mul(e.oneMinus()),ym.a))}copy(e){return this.emissiveNode=e.emissiveNode,this.metalnessNode=e.metalnessNode,this.roughnessNode=e.roughnessNode,super.copy(e)}}const gw=new wu;class fw extends mw{static get type(){return"MeshPhysicalNodeMaterial"}constructor(e){super(),this.isMeshPhysicalNodeMaterial=!0,this.clearcoatNode=null,this.clearcoatRoughnessNode=null,this.clearcoatNormalNode=null,this.sheenNode=null,this.sheenRoughnessNode=null,this.iridescenceNode=null,this.iridescenceIORNode=null,this.iridescenceThicknessNode=null,this.specularIntensityNode=null,this.specularColorNode=null,this.iorNode=null,this.transmissionNode=null,this.thicknessNode=null,this.attenuationDistanceNode=null,this.attenuationColorNode=null,this.dispersionNode=null,this.anisotropyNode=null,this.setDefaultValues(gw),this.setValues(e)}get useClearcoat(){return this.clearcoat>0||null!==this.clearcoatNode}get useIridescence(){return this.iridescence>0||null!==this.iridescenceNode}get useSheen(){return this.sheen>0||null!==this.sheenNode}get useAnisotropy(){return this.anisotropy>0||null!==this.anisotropyNode}get useTransmission(){return this.transmission>0||null!==this.transmissionNode}get useDispersion(){return this.dispersion>0||null!==this.dispersionNode}setupSpecular(){const e=this.iorNode?Up(this.iorNode):Gb;Vm.assign(e),Im.assign(Tf(nf(gf(Vm.sub(1).div(Vm.add(1))).mul(Sb),jp(1)).mul(wb),ym.rgb,vm)),Pm.assign(Tf(wb,1,vm))}setupLightingModel(){return new O_(this.useClearcoat,this.useSheen,this.useIridescence,this.useAnisotropy,this.useTransmission,this.useDispersion)}setupVariants(e){if(super.setupVariants(e),this.useClearcoat){const e=this.clearcoatNode?Up(this.clearcoatNode):Eb,t=this.clearcoatRoughnessNode?Up(this.clearcoatRoughnessNode):Bb;Tm.assign(e),_m.assign(ZT({roughness:t}))}if(this.useSheen){const e=this.sheenNode?jp(this.sheenNode):Fb,t=this.sheenRoughnessNode?Up(this.sheenRoughnessNode):zb;wm.assign(e),Sm.assign(t)}if(this.useIridescence){const e=this.iridescenceNode?Up(this.iridescenceNode):Ob,t=this.iridescenceIORNode?Up(this.iridescenceIORNode):Lb,s=this.iridescenceThicknessNode?Up(this.iridescenceThicknessNode):Vb;Mm.assign(e),Nm.assign(t),Am.assign(s)}if(this.useAnisotropy){const e=(this.anisotropyNode?Dp(this.anisotropyNode):Ub).toVar();Rm.assign(e.length()),Pp(Rm.equal(0),(()=>{e.assign(Dp(1,0))})).Else((()=>{e.divAssign(Dp(Rm)),Rm.assign(Rm.saturate())})),Cm.assign(Rm.pow2().mix(bm.pow2(),1)),Em.assign(rb[0].mul(e.x).add(rb[1].mul(e.y))),Bm.assign(rb[1].mul(e.x).sub(rb[0].mul(e.y)))}if(this.useTransmission){const e=this.transmissionNode?Up(this.transmissionNode):Db,t=this.thicknessNode?Up(this.thicknessNode):kb,s=this.attenuationDistanceNode?Up(this.attenuationDistanceNode):Wb,i=this.attenuationColorNode?jp(this.attenuationColorNode):jb;if(Dm.assign(e),km.assign(t),Gm.assign(s),Wm.assign(i),this.useDispersion){const e=this.dispersionNode?Up(this.dispersionNode):Jb;jm.assign(e)}}}setupClearcoatNormal(){return this.clearcoatNormalNode?jp(this.clearcoatNormalNode):Ib}setup(e){e.context.setupClearcoatNormal=()=>this.setupClearcoatNormal(e),super.setup(e)}copy(e){return this.clearcoatNode=e.clearcoatNode,this.clearcoatRoughnessNode=e.clearcoatRoughnessNode,this.clearcoatNormalNode=e.clearcoatNormalNode,this.sheenNode=e.sheenNode,this.sheenRoughnessNode=e.sheenRoughnessNode,this.iridescenceNode=e.iridescenceNode,this.iridescenceIORNode=e.iridescenceIORNode,this.iridescenceThicknessNode=e.iridescenceThicknessNode,this.specularIntensityNode=e.specularIntensityNode,this.specularColorNode=e.specularColorNode,this.transmissionNode=e.transmissionNode,this.thicknessNode=e.thicknessNode,this.attenuationDistanceNode=e.attenuationDistanceNode,this.attenuationColorNode=e.attenuationColorNode,this.dispersionNode=e.dispersionNode,this.anisotropyNode=e.anisotropyNode,super.copy(e)}}class yw extends O_{constructor(e,t,s,i){super(e,t,s),this.useSSS=i}direct({lightDirection:e,lightColor:t,reflectedLight:s},i,r){if(!0===this.useSSS){const i=r.material,{thicknessColorNode:n,thicknessDistortionNode:o,thicknessAmbientNode:a,thicknessAttenuationNode:h,thicknessPowerNode:u,thicknessScaleNode:l}=i,c=e.add(Tx.mul(o)).normalize(),d=Up(dx.dot(c.negate()).saturate().pow(u).mul(l)),p=jp(d.add(a).mul(n));s.directDiffuse.addAssign(p.mul(h.mul(t)))}super.direct({lightDirection:e,lightColor:t,reflectedLight:s},i,r)}}class xw extends fw{static get type(){return"MeshSSSNodeMaterial"}constructor(e){super(e),this.thicknessColorNode=null,this.thicknessDistortionNode=Up(.1),this.thicknessAmbientNode=Up(0),this.thicknessAttenuationNode=Up(.1),this.thicknessPowerNode=Up(2),this.thicknessScaleNode=Up(10)}get useSSS(){return null!==this.thicknessColorNode}setupLightingModel(){return new yw(this.useClearcoat,this.useSheen,this.useIridescence,this.useSSS)}copy(e){return this.thicknessColorNode=e.thicknessColorNode,this.thicknessDistortionNode=e.thicknessDistortionNode,this.thicknessAmbientNode=e.thicknessAmbientNode,this.thicknessAttenuationNode=e.thicknessAttenuationNode,this.thicknessPowerNode=e.thicknessPowerNode,this.thicknessScaleNode=e.thicknessScaleNode,super.copy(e)}}const bw=Rp((({normal:e,lightDirection:t,builder:s})=>{const i=e.dot(t),r=Dp(i.mul(.5).add(.5),0);if(s.material.gradientMap){const e=jx("gradientMap","texture").context({getUV:()=>r});return jp(e.r)}{const e=r.fwidth().mul(.5);return Tf(jp(.7),jp(1),Mf(Up(.7).sub(e.x),Up(.7).add(e.x),r.x))}}));class vw extends UT{direct({lightDirection:e,lightColor:t,reflectedLight:s},i,r){const n=bw({normal:fx,lightDirection:e,builder:r}).mul(t);s.directDiffuse.addAssign(n.mul(kT({diffuseColor:ym.rgb})))}indirect({ambientOcclusion:e,irradiance:t,reflectedLight:s}){s.indirectDiffuse.addAssign(t.mul(kT({diffuseColor:ym}))),s.indirectDiffuse.mulAssign(e)}}const Tw=new Mu;class _w extends pT{static get type(){return"MeshToonNodeMaterial"}constructor(e){super(),this.isMeshToonNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Tw),this.setValues(e)}setupLightingModel(){return new vw}}class ww extends kd{static get type(){return"MatcapUVNode"}constructor(){super("vec2")}setup(){const e=jp(dx.z,0,dx.x.negate()).normalize(),t=dx.cross(e);return Dp(e.dot(Tx),t.dot(Tx)).mul(.495).add(.5)}}const Sw=Cp(ww),Mw=new Eu;class Nw extends pT{static get type(){return"MeshMatcapNodeMaterial"}constructor(e){super(),this.lights=!1,this.isMeshMatcapNodeMaterial=!0,this.setDefaultValues(Mw),this.setValues(e)}setupVariants(e){const t=Sw;let s;s=e.material.matcap?jx("matcap","texture").context({getUV:()=>t}):jp(Tf(.2,.8,t.y)),ym.rgb.mulAssign(s.rgb)}}const Aw=new za;class Cw extends pT{static get type(){return"PointsNodeMaterial"}constructor(e){super(),this.isPointsNodeMaterial=!0,this.lights=!1,this.transparent=!0,this.sizeNode=null,this.setDefaultValues(Aw),this.setValues(e)}copy(e){return this.sizeNode=e.sizeNode,super.copy(e)}}class Rw extends kd{static get type(){return"RotateNode"}constructor(e,t){super(),this.positionNode=e,this.rotationNode=t}getNodeType(e){return this.positionNode.getNodeType(e)}setup(e){const{rotationNode:t,positionNode:s}=this;if("vec2"===this.getNodeType(e)){const e=t.cos(),i=t.sin();return Kp(e,i,i.negate(),e).mul(s)}{const e=t,i=em(Xp(1,0,0,0),Xp(0,Vg(e.x),Lg(e.x).negate(),0),Xp(0,Lg(e.x),Vg(e.x),0),Xp(0,0,0,1)),r=em(Xp(Vg(e.y),0,Lg(e.y),0),Xp(0,1,0,0),Xp(Lg(e.y).negate(),0,Vg(e.y),0),Xp(0,0,0,1)),n=em(Xp(Vg(e.z),Lg(e.z).negate(),0,0),Xp(Lg(e.z),Vg(e.z),0,0),Xp(0,0,1,0),Xp(0,0,0,1));return i.mul(r).mul(n).mul(Xp(s,1)).xyz}}}const Ew=Ap(Rw),Bw=new no;class Iw extends pT{static get type(){return"SpriteNodeMaterial"}constructor(e){super(),this.isSpriteNodeMaterial=!0,this.lights=!1,this._useSizeAttenuation=!0,this.positionNode=null,this.rotationNode=null,this.scaleNode=null,this.setDefaultValues(Bw),this.setValues(e)}setupPosition({object:e,camera:t,context:s}){const i=this.sizeAttenuation,{positionNode:r,rotationNode:n,scaleNode:o}=this,a=ax;let h=ix.mul(jp(r||0)),u=Dp(Jy[0].xyz.length(),Jy[1].xyz.length());null!==o&&(u=u.mul(o)),!i&&t.isPerspectiveCamera&&(u=u.mul(h.z.negate()));let l=a.xy;if(e.center&&!0===e.center.isVector2){const e=((e,t,s)=>Sp(new Zf(e,t,s)))("center","vec2");l=l.sub(e.sub(.5))}l=l.mul(u);const c=Up(n||Pb),d=Ew(l,c);h=Xp(h.xy.add(d),h.zw);const p=Oy.mul(h);return s.vertex=a,p}copy(e){return this.positionNode=e.positionNode,this.rotationNode=e.rotationNode,this.scaleNode=e.scaleNode,super.copy(e)}get sizeAttenuation(){return this._useSizeAttenuation}set sizeAttenuation(e){this._useSizeAttenuation!==e&&(this._useSizeAttenuation=e,this.needsUpdate=!0)}}class Pw extends UT{constructor(){super(),this.shadowNode=Up(1).toVar("shadowMask")}direct({shadowMask:e}){this.shadowNode.mulAssign(e)}finish(e){ym.a.mulAssign(this.shadowNode.oneMinus()),e.outgoingLight.rgb.assign(ym.rgb)}}const Fw=new vu;class zw extends pT{static get type(){return"ShadowNodeMaterial"}constructor(e){super(),this.isShadowNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Fw),this.setValues(e)}setupLightingModel(){return new Pw}}const Uw=Rp((({texture:e,uv:t})=>{const s=1e-4,i=jp().toVar();return Pp(t.x.lessThan(s),(()=>{i.assign(jp(1,0,0))})).ElseIf(t.y.lessThan(s),(()=>{i.assign(jp(0,1,0))})).ElseIf(t.z.lessThan(s),(()=>{i.assign(jp(0,0,1))})).ElseIf(t.x.greaterThan(.9999),(()=>{i.assign(jp(-1,0,0))})).ElseIf(t.y.greaterThan(.9999),(()=>{i.assign(jp(0,-1,0))})).ElseIf(t.z.greaterThan(.9999),(()=>{i.assign(jp(0,0,-1))})).Else((()=>{const s=.01,r=e.uv(t.add(jp(-.01,0,0))).r.sub(e.uv(t.add(jp(s,0,0))).r),n=e.uv(t.add(jp(0,-.01,0))).r.sub(e.uv(t.add(jp(0,s,0))).r),o=e.uv(t.add(jp(0,0,-.01))).r.sub(e.uv(t.add(jp(0,0,s))).r);i.assign(jp(r,n,o))})),i.normalize()}));class Ow extends Ey{static get type(){return"Texture3DNode"}constructor(e,t=null,s=null){super(e,t,s),this.isTexture3DNode=!0}getInputType(){return"texture3D"}getDefaultUV(){return jp(.5,.5,.5)}setUpdateMatrix(){}setupUV(e,t){return t}generateUV(e,t){return t.build(e,"vec3")}normal(e){return Uw({texture:this,uv:e})}}const Lw=Ap(Ow);class Vw extends pT{static get type(){return"VolumeNodeMaterial"}constructor(e={}){super(),this.lights=!1,this.isVolumeNodeMaterial=!0,this.testNode=null,this.setValues(e)}setup(e){const t=Lw(this.map,null,0),s=Rp((({orig:e,dir:t})=>{const s=jp(-.5),i=jp(.5),r=t.reciprocal(),n=s.sub(e).mul(r),o=i.sub(e).mul(r),a=nf(n,o),h=of(n,o),u=of(a.x,of(a.y,a.z)),l=nf(h.x,nf(h.y,h.z));return Dp(u,l)}));this.fragmentNode=Rp((()=>{const e=Vf(jp(sx.mul(Xp(Gy,1)))),i=Vf(ox.sub(e)).normalize(),r=Dp(s({orig:e,dir:i})).toVar();r.x.greaterThan(r.y).discard(),r.assign(Dp(of(r.x,0),r.y));const n=jp(e.add(r.x.mul(i))).toVar(),o=jp(i.abs().reciprocal()).toVar(),a=Up(nf(o.x,nf(o.y,o.z))).toVar("delta");a.divAssign(jx("steps","float"));const h=Xp(jx("base","color"),0).toVar();return bv({type:"float",start:r.x,end:r.y,update:"+= delta"},(()=>{const e=gm("float","d").assign(t.uv(n.add(.5)).r);null!==this.testNode?this.testNode({map:t,mapValue:e,probe:n,finalColor:h}).append():(h.a.assign(1),Tv()),n.addAssign(i.mul(a))})),h.a.equal(0).discard(),Xp(h)}))(),super.setup(e)}}class Dw{constructor(e,t){this.nodes=e,this.info=t,this.animationLoop=null,this.requestId=null,this._init()}_init(){const e=(t,s)=>{this.requestId=self.requestAnimationFrame(e),!0===this.info.autoReset&&this.info.reset(),this.nodes.nodeFrame.update(),this.info.frame=this.nodes.nodeFrame.frameId,null!==this.animationLoop&&this.animationLoop(t,s)};e()}dispose(){self.cancelAnimationFrame(this.requestId),this.requestId=null}setAnimationLoop(e){this.animationLoop=e}}class kw{constructor(){this.weakMap=new WeakMap}get(e){let t=this.weakMap;for(let s=0;s{this.dispose()},this.material.addEventListener("dispose",this.onMaterialDispose)}updateClipping(e){const t=this.material;let s=this.clippingContext;Array.isArray(t.clippingPlanes)?(s!==e&&s||(s=new Ww,this.clippingContext=s),s.update(e,t)):this.clippingContext!==e&&(this.clippingContext=e)}get clippingNeedsUpdate(){return this.clippingContext.version!==this.clippingContextVersion&&(this.clippingContextVersion=this.clippingContext.version,!0)}getNodeBuilderState(){return this._nodeBuilderState||(this._nodeBuilderState=this._nodes.getForRender(this))}getMonitor(){return this._monitor||(this._monitor=this.getNodeBuilderState().monitor)}getBindings(){return this._bindings||(this._bindings=this.getNodeBuilderState().createBindings())}getIndex(){return this._geometries.getIndex(this)}getChainArray(){return[this.object,this.material,this.context,this.lightsNode]}getAttributes(){if(null!==this.attributes)return this.attributes;const e=this.getNodeBuilderState().nodeAttributes,t=this.geometry,s=[],i=new Set;for(const r of e){const e=r.node&&r.node.attribute?r.node.attribute:t.getAttribute(r.name);if(void 0===e)continue;s.push(e);const n=e.isInterleavedBufferAttribute?e.data:e;i.add(n)}return this.attributes=s,this.vertexBuffers=Array.from(i.values()),s}getVertexBuffers(){return null===this.vertexBuffers&&this.getAttributes(),this.vertexBuffers}getDrawParameters(){const{object:e,material:t,geometry:s,group:i,drawRange:r}=this,n=this.drawParams||(this.drawParams={vertexCount:0,firstVertex:0,instanceCount:0,firstInstance:0}),o=this.getIndex(),a=null!==o,h=s.isInstancedBufferGeometry?s.instanceCount:e.count>1?e.count:1;if(0===h)return null;if(n.instanceCount=h,!0===e.isBatchedMesh)return n;let u=1;!0!==t.wireframe||e.isPoints||e.isLineSegments||e.isLine||e.isLineLoop||(u=2);let l=r.start*u,c=(r.start+r.count)*u;null!==i&&(l=Math.max(l,i.start*u),c=Math.min(c,(i.start+i.count)*u));const d=!0===a?o.count:s.attributes.position.count;l=Math.max(l,0),c=Math.min(c,d);const p=c-l;return p<0||p===1/0?null:(n.vertexCount=p,n.firstVertex=l,n)}getGeometryCacheKey(){const{geometry:e}=this;let t="";for(const s of Object.keys(e.attributes).sort()){const i=e.attributes[s];t+=s+",",i.data&&(t+=i.data.stride+","),i.offset&&(t+=i.offset+","),i.itemSize&&(t+=i.itemSize+","),i.normalized&&(t+="n,")}return e.index&&(t+="index,"),t}getMaterialCacheKey(){const{object:e,material:t}=this;let s=t.customProgramCacheKey();for(const e of function(e){const t=Object.keys(e);let s=Object.getPrototypeOf(e);for(;s;){const e=Object.getOwnPropertyDescriptors(s);for(const s in e)if(void 0!==e[s]){const i=e[s];i&&"function"==typeof i.get&&t.push(s)}s=Object.getPrototypeOf(s)}return t}(t)){if(/^(is[A-Z]|_)|^(visible|version|uuid|name|opacity|userData)$/.test(e))continue;const i=t[e];let r;if(null!==i){const e=typeof i;"number"===e?r=0!==i?"1":"0":"object"===e?(r="{",i.isTexture&&(r+=i.mapping),r+="}"):r=String(i)}else r=String(i);s+=r+","}return s+=this.clippingContext.cacheKey+",",e.geometry&&(s+=this.getGeometryCacheKey()),e.skeleton&&(s+=e.skeleton.bones.length+","),e.morphTargetInfluences&&(s+=e.morphTargetInfluences.length+","),e.isBatchedMesh&&(s+=e._matricesTexture.uuid+",",null!==e._colorsTexture&&(s+=e._colorsTexture.uuid+",")),e.count>1&&(s+=e.uuid+","),vd(s)}get needsUpdate(){return this.initialNodesCacheKey!==this.getDynamicCacheKey()||this.clippingNeedsUpdate}getDynamicCacheKey(){let e=this._nodes.getCacheKey(this.scene,this.lightsNode);return this.object.receiveShadow&&(e+=1),e}getCacheKey(){return this.getMaterialCacheKey()+this.getDynamicCacheKey()}dispose(){this.material.removeEventListener("dispose",this.onMaterialDispose),this.onDispose()}}const qw=[];class $w{constructor(e,t,s,i,r,n){this.renderer=e,this.nodes=t,this.geometries=s,this.pipelines=i,this.bindings=r,this.info=n,this.chainMaps={}}get(e,t,s,i,r,n,o){const a=this.getChainMap(o);qw[0]=e,qw[1]=t,qw[2]=n,qw[3]=r;let h=a.get(qw);return void 0===h?(h=this.createRenderObject(this.nodes,this.geometries,this.renderer,e,t,s,i,r,n,o),a.set(qw,h)):(h.updateClipping(n.clippingContext),(h.version!==t.version||h.needsUpdate)&&(h.initialCacheKey!==h.getCacheKey()?(h.dispose(),h=this.get(e,t,s,i,r,n,o)):h.version=t.version)),h}getChainMap(e="default"){return this.chainMaps[e]||(this.chainMaps[e]=new kw)}dispose(){this.chainMaps={}}createRenderObject(e,t,s,i,r,n,o,a,h,u){const l=this.getChainMap(u),c=new Hw(e,t,s,i,r,n,o,a,h);return c.onDispose=()=>{this.pipelines.delete(c),this.bindings.delete(c),this.nodes.delete(c),l.delete(c.getChainArray())},c}}class Xw{constructor(){this.data=new WeakMap}get(e){let t=this.data.get(e);return void 0===t&&(t={},this.data.set(e,t)),t}delete(e){let t;return this.data.has(e)&&(t=this.data.get(e),this.data.delete(e)),t}has(e){return this.data.has(e)}dispose(){this.data=new WeakMap}}const Yw=1,Zw=2,Jw=4,Kw=16;class Qw extends Xw{constructor(e){super(),this.backend=e}delete(e){const t=super.delete(e);return void 0!==t&&this.backend.destroyAttribute(e),t}update(e,t){const s=this.get(e);if(void 0===s.version)t===Yw?this.backend.createAttribute(e):t===Zw?this.backend.createIndexAttribute(e):t===Jw&&this.backend.createStorageAttribute(e),s.version=this._getBufferAttribute(e).version;else{const t=this._getBufferAttribute(e);(s.version=0;--t)if(e[t]>=65535)return!0;return!1}(t)?yn:gn)(t,1);return r.version=eS(e),r}class sS extends Xw{constructor(e,t){super(),this.attributes=e,this.info=t,this.wireframes=new WeakMap,this.attributeCall=new WeakMap}has(e){const t=e.geometry;return super.has(t)&&!0===this.get(t).initialized}updateForRender(e){!1===this.has(e)&&this.initGeometry(e),this.updateAttributes(e)}initGeometry(e){const t=e.geometry;this.get(t).initialized=!0,this.info.memory.geometries++;const s=()=>{this.info.memory.geometries--;const i=t.index,r=e.getAttributes();null!==i&&this.attributes.delete(i);for(const e of r)this.attributes.delete(e);const n=this.wireframes.get(t);void 0!==n&&this.attributes.delete(n),t.removeEventListener("dispose",s)};t.addEventListener("dispose",s)}updateAttributes(e){const t=e.getAttributes();for(const e of t)e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute?this.updateAttribute(e,Jw):this.updateAttribute(e,Yw);const s=this.getIndex(e);null!==s&&this.updateAttribute(s,Zw)}updateAttribute(e,t){const s=this.info.render.calls;e.isInterleavedBufferAttribute?void 0===this.attributeCall.get(e)?(this.attributes.update(e,t),this.attributeCall.set(e,s)):this.attributeCall.get(e.data)!==s&&(this.attributes.update(e,t),this.attributeCall.set(e.data,s),this.attributeCall.set(e,s)):this.attributeCall.get(e)!==s&&(this.attributes.update(e,t),this.attributeCall.set(e,s))}getIndex(e){const{geometry:t,material:s}=e;let i=t.index;if(!0===s.wireframe){const e=this.wireframes;let s=e.get(t);void 0===s?(s=tS(t),e.set(t,s)):s.version!==eS(t)&&(this.attributes.delete(s),s=tS(t),e.set(t,s)),i=s}return i}}class iS{constructor(){this.autoReset=!0,this.frame=0,this.calls=0,this.render={calls:0,frameCalls:0,drawCalls:0,triangles:0,points:0,lines:0,timestamp:0,previousFrameCalls:0,timestampCalls:0},this.compute={calls:0,frameCalls:0,timestamp:0,previousFrameCalls:0,timestampCalls:0},this.memory={geometries:0,textures:0}}update(e,t,s){this.render.drawCalls++,e.isMesh||e.isSprite?this.render.triangles+=s*(t/3):e.isPoints?this.render.points+=s*t:e.isLineSegments?this.render.lines+=s*(t/2):e.isLine?this.render.lines+=s*(t-1):console.error("THREE.WebGPUInfo: Unknown object type.")}updateTimestamp(e,t){0===this[e].timestampCalls&&(this[e].timestamp=0),this[e].timestamp+=t,this[e].timestampCalls++,this[e].timestampCalls>=this[e].previousFrameCalls&&(this[e].timestampCalls=0)}reset(){const e=this.render.frameCalls;this.render.previousFrameCalls=e;const t=this.compute.frameCalls;this.compute.previousFrameCalls=t,this.render.drawCalls=0,this.render.frameCalls=0,this.compute.frameCalls=0,this.render.triangles=0,this.render.points=0,this.render.lines=0}dispose(){this.reset(),this.calls=0,this.render.calls=0,this.compute.calls=0,this.render.timestamp=0,this.compute.timestamp=0,this.memory.geometries=0,this.memory.textures=0}}class rS{constructor(e){this.cacheKey=e,this.usedTimes=0}}class nS extends rS{constructor(e,t,s){super(e),this.vertexProgram=t,this.fragmentProgram=s}}class oS extends rS{constructor(e,t){super(e),this.computeProgram=t,this.isComputePipeline=!0}}let aS=0;class hS{constructor(e,t,s=null,i=null){this.id=aS++,this.code=e,this.stage=t,this.transforms=s,this.attributes=i,this.usedTimes=0}}class uS extends Xw{constructor(e,t){super(),this.backend=e,this.nodes=t,this.bindings=null,this.caches=new Map,this.programs={vertex:new Map,fragment:new Map,compute:new Map}}getForCompute(e,t){const{backend:s}=this,i=this.get(e);if(this._needsComputeUpdate(e)){const r=i.pipeline;r&&(r.usedTimes--,r.computeProgram.usedTimes--);const n=this.nodes.getForCompute(e);let o=this.programs.compute.get(n.computeShader);void 0===o&&(r&&0===r.computeProgram.usedTimes&&this._releaseProgram(r.computeProgram),o=new hS(n.computeShader,"compute",n.transforms,n.nodeAttributes),this.programs.compute.set(n.computeShader,o),s.createProgram(o));const a=this._getComputeCacheKey(e,o);let h=this.caches.get(a);void 0===h&&(r&&0===r.usedTimes&&this._releasePipeline(r),h=this._getComputePipeline(e,o,a,t)),h.usedTimes++,o.usedTimes++,i.version=e.version,i.pipeline=h}return i.pipeline}getForRender(e,t=null){const{backend:s}=this,i=this.get(e);if(this._needsRenderUpdate(e)){const r=i.pipeline;r&&(r.usedTimes--,r.vertexProgram.usedTimes--,r.fragmentProgram.usedTimes--);const n=e.getNodeBuilderState();let o=this.programs.vertex.get(n.vertexShader);void 0===o&&(r&&0===r.vertexProgram.usedTimes&&this._releaseProgram(r.vertexProgram),o=new hS(n.vertexShader,"vertex"),this.programs.vertex.set(n.vertexShader,o),s.createProgram(o));let a=this.programs.fragment.get(n.fragmentShader);void 0===a&&(r&&0===r.fragmentProgram.usedTimes&&this._releaseProgram(r.fragmentProgram),a=new hS(n.fragmentShader,"fragment"),this.programs.fragment.set(n.fragmentShader,a),s.createProgram(a));const h=this._getRenderCacheKey(e,o,a);let u=this.caches.get(h);void 0===u?(r&&0===r.usedTimes&&this._releasePipeline(r),u=this._getRenderPipeline(e,o,a,h,t)):e.pipeline=u,u.usedTimes++,o.usedTimes++,a.usedTimes++,i.pipeline=u}return i.pipeline}delete(e){const t=this.get(e).pipeline;return t&&(t.usedTimes--,0===t.usedTimes&&this._releasePipeline(t),t.isComputePipeline?(t.computeProgram.usedTimes--,0===t.computeProgram.usedTimes&&this._releaseProgram(t.computeProgram)):(t.fragmentProgram.usedTimes--,t.vertexProgram.usedTimes--,0===t.vertexProgram.usedTimes&&this._releaseProgram(t.vertexProgram),0===t.fragmentProgram.usedTimes&&this._releaseProgram(t.fragmentProgram))),super.delete(e)}dispose(){super.dispose(),this.caches=new Map,this.programs={vertex:new Map,fragment:new Map,compute:new Map}}updateForRender(e){this.getForRender(e)}_getComputePipeline(e,t,s,i){s=s||this._getComputeCacheKey(e,t);let r=this.caches.get(s);return void 0===r&&(r=new oS(s,t),this.caches.set(s,r),this.backend.createComputePipeline(r,i)),r}_getRenderPipeline(e,t,s,i,r){i=i||this._getRenderCacheKey(e,t,s);let n=this.caches.get(i);return void 0===n&&(n=new nS(i,t,s),this.caches.set(i,n),e.pipeline=n,this.backend.createRenderPipeline(e,r)),n}_getComputeCacheKey(e,t){return e.id+","+t.id}_getRenderCacheKey(e,t,s){return t.id+","+s.id+","+this.backend.getRenderCacheKey(e)}_releasePipeline(e){this.caches.delete(e.cacheKey)}_releaseProgram(e){const t=e.code,s=e.stage;this.programs[s].delete(t)}_needsComputeUpdate(e){const t=this.get(e);return void 0===t.pipeline||t.version!==e.version}_needsRenderUpdate(e){return void 0===this.get(e).pipeline||this.backend.needsRenderUpdate(e)}}class lS extends Xw{constructor(e,t,s,i,r,n){super(),this.backend=e,this.textures=s,this.pipelines=r,this.attributes=i,this.nodes=t,this.info=n,this.pipelines.bindings=this}getForRender(e){const t=e.getBindings();for(const e of t){const s=this.get(e);void 0===s.bindGroup&&(this._init(e),this.backend.createBindings(e,t),s.bindGroup=e)}return t}getForCompute(e){const t=this.nodes.getForCompute(e).bindings;for(const e of t){const s=this.get(e);void 0===s.bindGroup&&(this._init(e),this.backend.createBindings(e,t),s.bindGroup=e)}return t}updateForCompute(e){this._updateBindings(this.getForCompute(e))}updateForRender(e){this._updateBindings(this.getForRender(e))}_updateBindings(e){for(const t of e)this._update(t,e)}_init(e){for(const t of e.bindings)if(t.isSampledTexture)this.textures.updateTexture(t.texture);else if(t.isStorageBuffer){const e=t.attribute;this.attributes.update(e,Jw)}}_update(e,t){const{backend:s}=this;let i=!1;for(const t of e.bindings){if(t.isNodeUniformsGroup){if(!this.nodes.updateGroup(t))continue}if(t.isUniformBuffer){t.update()&&s.updateBinding(t)}else if(t.isSampler)t.update();else if(t.isSampledTexture){t.needsBindingsUpdate(this.textures.get(t.texture).generation)&&(i=!0);const e=t.update(),r=t.texture;e&&this.textures.updateTexture(r);const n=s.get(r);if(!0===s.isWebGPUBackend&&void 0===n.texture&&void 0===n.externalTexture&&(console.error("Bindings._update: binding should be available:",t,e,r,t.textureNode.value,i),this.textures.updateTexture(r),i=!0),!0===r.isStorageTexture){const e=this.get(r);!0===t.store?e.needsMipmap=!0:!0===r.generateMipmaps&&this.textures.needsMipmaps(r)&&!0===e.needsMipmap&&(this.backend.generateMipmaps(r),e.needsMipmap=!1)}}}!0===i&&this.backend.updateBindings(e,t)}}class cS{constructor(e,t,s=null){this.isNodeAttribute=!0,this.name=e,this.type=t,this.node=s}}class dS{constructor(e,t,s){this.isNodeUniform=!0,this.name=e,this.type=t,this.node=s.getSelf()}get value(){return this.node.value}set value(e){this.node.value=e}get id(){return this.node.id}get groupNode(){return this.node.groupNode}}class pS{constructor(e,t){this.isNodeVar=!0,this.name=e,this.type=t}}class mS extends pS{constructor(e,t){super(e,t),this.needsInterpolation=!1,this.isNodeVarying=!0}}class gS{constructor(e,t,s=""){this.name=e,this.type=t,this.code=s,Object.defineProperty(this,"isNodeCode",{value:!0})}}let fS=0;class yS{constructor(e=null){this.id=fS++,this.nodesData=new WeakMap,this.parent=e}getData(e){let t=this.nodesData.get(e);return void 0===t&&null!==this.parent&&(t=this.parent.getData(e)),t}setData(e,t){this.nodesData.set(e,t)}}class xS extends mm{static get type(){return"ParameterNode"}constructor(e,t=null){super(e,t),this.isParameterNode=!0}getHash(){return this.uuid}generate(){return this.name}}const bS=(e,t)=>Sp(new xS(e,t));class vS extends Ld{static get type(){return"CodeNode"}constructor(e="",t=[],s=""){super("code"),this.isCodeNode=!0,this.code=e,this.language=s,this.includes=t}isGlobal(){return!0}setIncludes(e){return this.includes=e,this}getIncludes(){return this.includes}generate(e){const t=this.getIncludes(e);for(const s of t)s.build(e);const s=e.getCodeFromNode(this,this.getNodeType(e));return s.code=this.code,s.code}serialize(e){super.serialize(e),e.code=this.code,e.language=this.language}deserialize(e){super.deserialize(e),this.code=e.code,this.language=e.language}}const TS=Ap(vS),_S=(e,t)=>TS(e,t,"js"),wS=(e,t)=>TS(e,t,"wgsl"),SS=(e,t)=>TS(e,t,"glsl");class MS extends vS{static get type(){return"FunctionNode"}constructor(e="",t=[],s=""){super(e,t,s)}getNodeType(e){return this.getNodeFunction(e).type}getInputs(e){return this.getNodeFunction(e).inputs}getNodeFunction(e){const t=e.getDataFromNode(this);let s=t.nodeFunction;return void 0===s&&(s=e.parser.parseFunction(this.code),t.nodeFunction=s),s}generate(e,t){super.generate(e);const s=this.getNodeFunction(e),i=s.name,r=s.type,n=e.getCodeFromNode(this,r);""!==i&&(n.name=i);const o=e.getPropertyName(n),a=this.getNodeFunction(e).getCode(o);return n.code=a+"\n","property"===t?o:e.format(`${o}()`,r,t)}}const NS=(e,t=[],s="")=>{for(let e=0;ei.call(...e);return r.functionNode=i,r},AS=(e,t)=>NS(e,t,"glsl"),CS=(e,t)=>NS(e,t,"wgsl");class RS{constructor(e,t){this.name=e,this.value=t,this.boundary=0,this.itemSize=0,this.offset=0}setValue(e){this.value=e}getValue(){return this.value}}class ES extends RS{constructor(e,t=0){super(e,t),this.isNumberUniform=!0,this.boundary=4,this.itemSize=1}}class BS extends RS{constructor(e,t=new Qs){super(e,t),this.isVector2Uniform=!0,this.boundary=8,this.itemSize=2}}class IS extends RS{constructor(e,t=new Ri){super(e,t),this.isVector3Uniform=!0,this.boundary=16,this.itemSize=3}}class PS extends RS{constructor(e,t=new Ti){super(e,t),this.isVector4Uniform=!0,this.boundary=16,this.itemSize=4}}class FS extends RS{constructor(e,t=new Jr){super(e,t),this.isColorUniform=!0,this.boundary=16,this.itemSize=3}}class zS extends RS{constructor(e,t=new ei){super(e,t),this.isMatrix3Uniform=!0,this.boundary=48,this.itemSize=12}}class US extends RS{constructor(e,t=new nr){super(e,t),this.isMatrix4Uniform=!0,this.boundary=64,this.itemSize=16}}class OS extends ES{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class LS extends BS{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class VS extends IS{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class DS extends PS{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class kS extends FS{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class GS extends zS{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class WS extends US{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class jS extends Ld{static get type(){return"StackNode"}constructor(e=null){super(),this.nodes=[],this.outputNode=null,this.parent=e,this._currentCond=null,this.isStackNode=!0}getNodeType(e){return this.outputNode?this.outputNode.getNodeType(e):"void"}add(e){return this.nodes.push(e),this}If(e,t){const s=new wp(t);return this._currentCond=Bf(e,s),this.add(this._currentCond)}ElseIf(e,t){const s=new wp(t),i=Bf(e,s);return this._currentCond.elseNode=i,this._currentCond=i,this}Else(e){return this._currentCond.elseNode=new wp(e),this}build(e,...t){const s=Ip();Bp(this);for(const t of this.nodes)t.build(e,"void");return Bp(s),this.outputNode?this.outputNode.build(e,...t):super.build(e,...t)}else(...e){return console.warn("TSL.StackNode: .else() has been renamed to .Else()."),this.Else(...e)}elseif(...e){return console.warn("TSL.StackNode: .elseif() has been renamed to .ElseIf()."),this.ElseIf(...e)}}const HS=Ap(jS),qS=[.125,.215,.35,.446,.526,.582],$S=20,XS=new Sl(-1,1,1,-1,0,1),YS=new Xn(90,1),ZS=new Jr;let JS=null,KS=0,QS=0;const eM=(1+Math.sqrt(5))/2,tM=1/eM,sM=[new Ri(-eM,tM,0),new Ri(eM,tM,0),new Ri(-tM,0,eM),new Ri(tM,0,eM),new Ri(0,eM,-tM),new Ri(0,eM,tM),new Ri(-1,1,-1),new Ri(1,1,-1),new Ri(-1,1,1),new Ri(1,1,1)],iM=[3,1,5,0,4,2],rM=Q_(My(),Sy("faceIndex")).normalize(),nM=jp(rM.x,rM.y.negate(),rM.z);class oM{constructor(e){this._renderer=e,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._lodMeshes=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._backgroundBox=null}fromScene(e,t=0,s=.1,i=100){JS=this._renderer.getRenderTarget(),KS=this._renderer.getActiveCubeFace(),QS=this._renderer.getActiveMipmapLevel(),this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(e,s,i,r),t>0&&this._blur(r,0,0,t),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(e,t=null){return this._fromTexture(e,t)}fromCubemap(e,t=null){return this._fromTexture(e,t)}async compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=lM(),await this._compileMaterial(this._cubemapMaterial))}async compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=cM(),await this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose(),null!==this._backgroundBox&&(this._backgroundBox.geometry.dispose(),this._backgroundBox.material.dispose())}_setSize(e){this._lodMax=Math.floor(Math.log2(e)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let e=0;ee-4?h=qS[a-e+4-1]:0===a&&(h=0),i.push(h);const u=1/(o-2),l=-u,c=1+u,d=[l,l,c,l,c,c,l,l,c,c,l,c],p=6,m=6,g=3,f=2,y=1,x=new Float32Array(g*m*p),b=new Float32Array(f*m*p),v=new Float32Array(y*m*p);for(let e=0;e2?0:-1,i=[t,s,0,t+2/3,s,0,t+2/3,s+1,0,t,s,0,t+2/3,s+1,0,t,s+1,0],r=iM[e];x.set(i,g*m*r),b.set(d,f*m*r);const n=[r,r,r,r,r,r];v.set(n,y*m*r)}const T=new An;T.setAttribute("position",new ln(x,g)),T.setAttribute("uv",new ln(b,f)),T.setAttribute("faceIndex",new ln(v,y)),t.push(T),r.push(new Vn(T,null)),n>4&&n--}return{lodPlanes:t,sizeLods:s,sigmas:i,lodMeshes:r}}(i)),this._blurMaterial=function(e,t,s){const i=Ox(new Array($S).fill(0)),r=pm(new Ri(0,1,0)),n=pm(0),o=Up($S),a=pm(0),h=pm(1),u=By(null),l=pm(0),c=Up(1/t),d=Up(1/s),p=Up(e),m={n:o,latitudinal:a,weights:i,poleAxis:r,outputDirection:nM,dTheta:n,samples:h,envMap:u,mipInt:l,CUBEUV_TEXEL_WIDTH:c,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:p},g=uM("blur");return g.uniforms=m,g.fragmentNode=iw({...m,latitudinal:a.equal(1)}),g}(i,e,t)}return i}async _compileMaterial(e){const t=new Vn(this._lodPlanes[0],e);await this._renderer.compile(t,XS)}_sceneToCubeUV(e,t,s,i){const r=YS;r.near=t,r.far=s;const n=[-1,1,-1,-1,-1,-1],o=[1,1,1,-1,-1,-1],a=this._renderer,h=a.autoClear;a.getClearColor(ZS),a.autoClear=!1;let u=this._backgroundBox;if(null===u){const e=new tn({name:"PMREM.Background",side:d,depthWrite:!1,depthTest:!1});u=new Vn(new kn,e)}let l=!1;const c=e.background;c?c.isColor&&(u.material.color.copy(c),e.background=null,l=!0):(u.material.color.copy(ZS),l=!0),a.setRenderTarget(i),a.clear(),l&&a.render(u,r);for(let t=0;t<6;t++){const s=t%3;0===s?(r.up.set(0,n[t],0),r.lookAt(o[t],0,0)):1===s?(r.up.set(0,0,n[t]),r.lookAt(0,o[t],0)):(r.up.set(0,n[t],0),r.lookAt(0,0,o[t]));const h=this._cubeSize;hM(i,s*h,t>2?h:0,h,h),a.render(e,r)}a.autoClear=h,e.background=c}_textureToCubeUV(e,t){const s=this._renderer,i=e.mapping===he||e.mapping===ue;i?null===this._cubemapMaterial&&(this._cubemapMaterial=lM(e)):null===this._equirectMaterial&&(this._equirectMaterial=cM(e));const r=i?this._cubemapMaterial:this._equirectMaterial;r.fragmentNode.value=e;const n=this._lodMeshes[0];n.material=r;const o=this._cubeSize;hM(t,0,0,3*o,2*o),s.setRenderTarget(t),s.render(n,XS)}_applyPMREM(e){const t=this._renderer,s=t.autoClear;t.autoClear=!1;const i=this._lodPlanes.length;for(let t=1;t$S&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${m} samples when the maximum is set to 20`);const g=[];let f=0;for(let e=0;e<$S;++e){const t=e/p,s=Math.exp(-t*t/2);g.push(s),0===e?f+=s:ey-4?i-y+4:0),4*(this._cubeSize-x),3*x,2*x),a.setRenderTarget(t),a.render(u,XS)}}function aM(e,t,s){const i=new _i(e,t,s);return i.texture.mapping=de,i.texture.name="PMREM.cubeUv",i.texture.isPMREMTexture=!0,i.scissorTest=!0,i}function hM(e,t,s,i,r){e.viewport.set(t,s,i,r),e.scissor.set(t,s,i,r)}function uM(e){const t=new pT;return t.depthTest=!1,t.depthWrite=!1,t.blending=m,t.name=`PMREM_${e}`,t}function lM(e){const t=uM("cubemap");return t.fragmentNode=Ix(e,nM),t}function cM(e){const t=uM("equirect");return t.fragmentNode=By(e,AT(nM),0),t}let dM=0;class pM{constructor(e="",t=[],s=0,i=[]){this.name=e,this.bindings=t,this.index=s,this.bindingsReference=i,this.id=dM++}}const mM=new WeakMap,gM=new Map([[2,"vec2"],[3,"vec3"],[4,"vec4"],[9,"mat3"],[16,"mat4"]]),fM=new Map([[Int8Array,"int"],[Int16Array,"int"],[Int32Array,"int"],[Uint8Array,"uint"],[Uint16Array,"uint"],[Uint32Array,"uint"],[Float32Array,"float"]]),yM=e=>(e=Number(e))+(e%1?"":".0");class xM{constructor(e,t,s){this.object=e,this.material=e&&e.material||null,this.geometry=e&&e.geometry||null,this.renderer=t,this.parser=s,this.scene=null,this.camera=null,this.nodes=[],this.updateNodes=[],this.updateBeforeNodes=[],this.updateAfterNodes=[],this.hashNodes={},this.monitor=null,this.lightsNode=null,this.environmentNode=null,this.fogNode=null,this.clippingContext=null,this.vertexShader=null,this.fragmentShader=null,this.computeShader=null,this.flowNodes={vertex:[],fragment:[],compute:[]},this.flowCode={vertex:"",fragment:"",compute:""},this.uniforms={vertex:[],fragment:[],compute:[],index:0},this.structs={vertex:[],fragment:[],compute:[],index:0},this.bindings={vertex:{},fragment:{},compute:{}},this.bindingsIndexes={},this.bindGroups=null,this.attributes=[],this.bufferAttributes=[],this.varyings=[],this.codes={},this.vars={},this.flow={code:""},this.chaining=[],this.stack=HS(),this.stacks=[],this.tab="\t",this.currentFunctionNode=null,this.context={material:this.material},this.cache=new yS,this.globalCache=this.cache,this.flowsData=new WeakMap,this.shaderStage=null,this.buildStage=null,this.useComparisonMethod=!1}getBindGroupsCache(){let e=mM.get(this.renderer);return void 0===e&&(e=new kw,mM.set(this.renderer,e)),e}createRenderTarget(e,t,s){return new _i(e,t,s)}createCubeRenderTarget(e,t){return new CT(e,t)}createPMREMGenerator(){return new oM(this.renderer)}includes(e){return this.nodes.includes(e)}_getBindGroup(e,t){const s=this.getBindGroupsCache(),i=[];let r,n=!0;for(const e of t)i.push(e),n=n&&!0!==e.groupNode.shared;return n?(r=s.get(i),void 0===r&&(r=new pM(e,i,this.bindingsIndexes[e].group,i),s.set(i,r))):r=new pM(e,i,this.bindingsIndexes[e].group,i),r}getBindGroupArray(e,t){const s=this.bindings[t];let i=s[e];return void 0===i&&(void 0===this.bindingsIndexes[e]&&(this.bindingsIndexes[e]={binding:0,group:Object.keys(this.bindingsIndexes).length}),s[e]=i=[]),i}getBindings(){let e=this.bindGroups;if(null===e){const t={},s=this.bindings;for(const e of zd)for(const i in s[e]){const r=s[e][i];(t[i]||(t[i]=[])).push(...r)}e=[];for(const s in t){const i=t[s],r=this._getBindGroup(s,i);e.push(r)}this.bindGroups=e}return e}sortBindingGroups(){const e=this.getBindings();e.sort(((e,t)=>e.bindings[0].groupNode.order-t.bindings[0].groupNode.order));for(let t=0;t=0?`${Math.round(t)}u`:"0u";if("bool"===e)return t?"true":"false";if("color"===e)return`${this.getType("vec3")}( ${yM(t.r)}, ${yM(t.g)}, ${yM(t.b)} )`;const s=this.getTypeLength(e),i=this.getComponentType(e),r=e=>this.generateConst(i,e);if(2===s)return`${this.getType(e)}( ${r(t.x)}, ${r(t.y)} )`;if(3===s)return`${this.getType(e)}( ${r(t.x)}, ${r(t.y)}, ${r(t.z)} )`;if(4===s)return`${this.getType(e)}( ${r(t.x)}, ${r(t.y)}, ${r(t.z)}, ${r(t.w)} )`;if(s>4&&t&&(t.isMatrix3||t.isMatrix4))return`${this.getType(e)}( ${t.elements.map(r).join(", ")} )`;if(s>4)return`${this.getType(e)}()`;throw new Error(`NodeBuilder: Type '${e}' not found in generate constant attempt.`)}getType(e){return"color"===e?"vec3":e}hasGeometryAttribute(e){return this.geometry&&void 0!==this.geometry.getAttribute(e)}getAttribute(e,t){const s=this.attributes;for(const t of s)if(t.name===e)return t;const i=new cS(e,t);return s.push(i),i}getPropertyName(e){return e.name}isVector(e){return/vec\d/.test(e)}isMatrix(e){return/mat\d/.test(e)}isReference(e){return"void"===e||"property"===e||"sampler"===e||"texture"===e||"cubeTexture"===e||"storageTexture"===e||"depthTexture"===e||"texture3D"===e}needsToWorkingColorSpace(){return!1}getComponentTypeFromTexture(e){const t=e.type;if(e.isDataTexture){if(t===Ee)return"int";if(t===Be)return"uint"}return"float"}getElementType(e){return"mat2"===e?"vec2":"mat3"===e?"vec3":"mat4"===e?"vec4":this.getComponentType(e)}getComponentType(e){if("float"===(e=this.getVectorType(e))||"bool"===e||"int"===e||"uint"===e)return e;const t=/(b|i|u|)(vec|mat)([2-4])/.exec(e);return null===t?null:"b"===t[1]?"bool":"i"===t[1]?"int":"u"===t[1]?"uint":"float"}getVectorType(e){return"color"===e?"vec3":"texture"===e||"cubeTexture"===e||"storageTexture"===e||"texture3D"===e?"vec4":e}getTypeFromLength(e,t="float"){if(1===e)return t;const s=gM.get(e);return("float"===t?"":t[0])+s}getTypeFromArray(e){return fM.get(e.constructor)}getTypeFromAttribute(e){let t=e;e.isInterleavedBufferAttribute&&(t=e.data);const s=t.array,i=e.itemSize,r=e.normalized;let n;return e instanceof xn||!0===r||(n=this.getTypeFromArray(s)),this.getTypeFromLength(i,n)}getTypeLength(e){const t=this.getVectorType(e),s=/vec([2-4])/.exec(t);return null!==s?Number(s[1]):"float"===t||"bool"===t||"int"===t||"uint"===t?1:!0===/mat2/.test(e)?4:!0===/mat3/.test(e)?9:!0===/mat4/.test(e)?16:0}getVectorFromMatrix(e){return e.replace("mat","vec")}changeComponentType(e,t){return this.getTypeFromLength(this.getTypeLength(e),t)}getIntegerType(e){const t=this.getComponentType(e);return"int"===t||"uint"===t?e:this.changeComponentType(e,"int")}addStack(){return this.stack=HS(this.stack),this.stacks.push(Ip()||this.stack),Bp(this.stack),this.stack}removeStack(){const e=this.stack;return this.stack=e.parent,Bp(this.stacks.pop()),e}getDataFromNode(e,t=this.shaderStage,s=null){let i=(s=null===s?e.isGlobal(this)?this.globalCache:this.cache:s).getData(e);return void 0===i&&(i={},s.setData(e,i)),void 0===i[t]&&(i[t]={}),i[t]}getNodeProperties(e,t="any"){const s=this.getDataFromNode(e,t);return s.properties||(s.properties={outputNode:null})}getBufferAttributeFromNode(e,t){const s=this.getDataFromNode(e);let i=s.bufferAttribute;if(void 0===i){const r=this.uniforms.index++;i=new cS("nodeAttribute"+r,t,e),this.bufferAttributes.push(i),s.bufferAttribute=i}return i}getStructTypeFromNode(e,t=this.shaderStage){const s=this.getDataFromNode(e,t);if(void 0===s.structType){const i=this.structs.index++;e.name=`StructType${i}`,this.structs[t].push(e),s.structType=e}return e}getUniformFromNode(e,t,s=this.shaderStage,i=null){const r=this.getDataFromNode(e,s,this.globalCache);let n=r.uniform;if(void 0===n){const o=this.uniforms.index++;n=new dS(i||"nodeUniform"+o,t,e),this.uniforms[s].push(n),r.uniform=n}return n}getVarFromNode(e,t=null,s=e.getNodeType(this),i=this.shaderStage){const r=this.getDataFromNode(e,i);let n=r.variable;if(void 0===n){const e=this.vars[i]||(this.vars[i]=[]);null===t&&(t="nodeVar"+e.length),n=new pS(t,s),e.push(n),r.variable=n}return n}getVaryingFromNode(e,t=null,s=e.getNodeType(this)){const i=this.getDataFromNode(e,"any");let r=i.varying;if(void 0===r){const e=this.varyings,n=e.length;null===t&&(t="nodeVarying"+n),r=new mS(t,s),e.push(r),i.varying=r}return r}getCodeFromNode(e,t,s=this.shaderStage){const i=this.getDataFromNode(e);let r=i.code;if(void 0===r){const e=this.codes[s]||(this.codes[s]=[]),n=e.length;r=new gS("nodeCode"+n,t),e.push(r),i.code=r}return r}addFlowCodeHierarchy(e,t){const{flowCodes:s,flowCodeBlock:i}=this.getDataFromNode(e);let r=!0,n=t;for(;n;){if(!0===i.get(n)){r=!1;break}n=this.getDataFromNode(n).parentNodeBlock}if(r)for(const e of s)this.addLineFlowCode(e)}addLineFlowCodeBlock(e,t,s){const i=this.getDataFromNode(e),r=i.flowCodes||(i.flowCodes=[]),n=i.flowCodeBlock||(i.flowCodeBlock=new WeakMap);r.push(t),n.set(s,!0)}addLineFlowCode(e,t=null){return""===e||(null!==t&&this.context.nodeBlock&&this.addLineFlowCodeBlock(t,e,this.context.nodeBlock),e=this.tab+e,/;\s*$/.test(e)||(e+=";\n"),this.flow.code+=e),this}addFlowCode(e){return this.flow.code+=e,this}addFlowTab(){return this.tab+="\t",this}removeFlowTab(){return this.tab=this.tab.slice(0,-1),this}getFlowData(e){return this.flowsData.get(e)}flowNode(e){const t=e.getNodeType(this),s=this.flowChildNode(e,t);return this.flowsData.set(e,s),s}buildFunctionNode(e){const t=new MS,s=this.currentFunctionNode;return this.currentFunctionNode=t,t.code=this.buildFunctionCode(e),this.currentFunctionNode=s,t}flowShaderNode(e){const t=e.layout,s={[Symbol.iterator](){let e=0;const t=Object.values(this);return{next:()=>({value:t[e],done:e++>=t.length})}}};for(const e of t.inputs)s[e.name]=new xS(e.type,e.name);e.layout=null;const i=e.call(s),r=this.flowStagesNode(i,t.type);return e.layout=t,r}flowStagesNode(e,t=null){const s=this.flow,i=this.vars,r=this.cache,n=this.buildStage,o=this.stack,a={code:""};this.flow=a,this.vars={},this.cache=new yS,this.stack=HS();for(const s of Fd)this.setBuildStage(s),a.result=e.build(this,t);return a.vars=this.getVars(this.shaderStage),this.flow=s,this.vars=i,this.cache=r,this.stack=o,this.setBuildStage(n),a}getFunctionOperator(){return null}flowChildNode(e,t=null){const s=this.flow,i={code:""};return this.flow=i,i.result=e.build(this,t),this.flow=s,i}flowNodeFromShaderStage(e,t,s=null,i=null){const r=this.shaderStage;this.setShaderStage(e);const n=this.flowChildNode(t,s);return null!==i&&(n.code+=`${this.tab+i} = ${n.result};\n`),this.flowCode[e]=this.flowCode[e]+n.code,this.setShaderStage(r),n}getAttributesArray(){return this.attributes.concat(this.bufferAttributes)}getAttributes(){console.warn("Abstract function.")}getVaryings(){console.warn("Abstract function.")}getVar(e,t){return`${this.getType(e)} ${t}`}getVars(e){let t="";const s=this.vars[e];if(void 0!==s)for(const e of s)t+=`${this.getVar(e.type,e.name)}; `;return t}getUniforms(){console.warn("Abstract function.")}getCodes(e){const t=this.codes[e];let s="";if(void 0!==t)for(const e of t)s+=e.code+"\n";return s}getHash(){return this.vertexShader+this.fragmentShader+this.computeShader}setShaderStage(e){this.shaderStage=e}getShaderStage(){return this.shaderStage}setBuildStage(e){this.buildStage=e}getBuildStage(){return this.buildStage}buildCode(){console.warn("Abstract function.")}build(){const{object:e,material:t,renderer:s}=this;if(null!==t){let e=s.nodes.library.fromMaterial(t);null===e&&(console.error(`NodeMaterial: Material "${t.type}" is not compatible.`),e=new pT),e.build(this)}else this.addFlow("compute",e);for(const e of Fd){this.setBuildStage(e),this.context.vertex&&this.context.vertex.isNode&&this.flowNodeFromShaderStage("vertex",this.context.vertex);for(const t of zd){this.setShaderStage(t);const s=this.flowNodes[t];for(const t of s)"generate"===e?this.flowNode(t):t.build(this)}}return this.setBuildStage(null),this.setShaderStage(null),this.buildCode(),this.buildUpdateNodes(),this}getNodeUniform(e,t){if("float"===t||"int"===t||"uint"===t)return new OS(e);if("vec2"===t||"ivec2"===t||"uvec2"===t)return new LS(e);if("vec3"===t||"ivec3"===t||"uvec3"===t)return new VS(e);if("vec4"===t||"ivec4"===t||"uvec4"===t)return new DS(e);if("color"===t)return new kS(e);if("mat3"===t)return new GS(e);if("mat4"===t)return new WS(e);throw new Error(`Uniform "${t}" not declared.`)}createNodeMaterial(e="NodeMaterial"){throw new Error(`THREE.NodeBuilder: createNodeMaterial() was deprecated. Use new ${e}() instead.`)}format(e,t,s){if((t=this.getVectorType(t))===(s=this.getVectorType(s))||null===s||this.isReference(s))return e;const i=this.getTypeLength(t),r=this.getTypeLength(s);return 16===i&&9===r?`${this.getType(s)}(${e}[0].xyz, ${e}[1].xyz, ${e}[2].xyz)`:9===i&&4===r?`${this.getType(s)}(${e}[0].xy, ${e}[1].xy)`:i>4||r>4||0===r?e:i===r?`${this.getType(s)}( ${e} )`:i>r?this.format(`${e}.${"xyz".slice(0,r)}`,this.getTypeFromLength(r,this.getComponentType(t)),s):4===r&&i>1?`${this.getType(s)}( ${this.format(e,t,"vec3")}, 1.0 )`:2===i?`${this.getType(s)}( ${this.format(e,t,"vec2")}, 0.0 )`:(1===i&&r>1&&t!==this.getComponentType(s)&&(e=`${this.getType(this.getComponentType(s))}( ${e} )`),`${this.getType(s)}( ${e} )`)}getSignature(){return`// Three.js r${e} - Node System\n`}}class bM{constructor(){this.time=0,this.deltaTime=0,this.frameId=0,this.renderId=0,this.startTime=null,this.updateMap=new WeakMap,this.updateBeforeMap=new WeakMap,this.updateAfterMap=new WeakMap,this.renderer=null,this.material=null,this.camera=null,this.object=null,this.scene=null}_getMaps(e,t){let s=e.get(t);return void 0===s&&(s={renderMap:new WeakMap,frameMap:new WeakMap},e.set(t,s)),s}updateBeforeNode(e){const t=e.getUpdateBeforeType(),s=e.updateReference(this);if(t===Bd.FRAME){const{frameMap:t}=this._getMaps(this.updateBeforeMap,s);t.get(s)!==this.frameId&&!1!==e.updateBefore(this)&&t.set(s,this.frameId)}else if(t===Bd.RENDER){const{renderMap:t}=this._getMaps(this.updateBeforeMap,s);t.get(s)!==this.renderId&&!1!==e.updateBefore(this)&&t.set(s,this.renderId)}else t===Bd.OBJECT&&e.updateBefore(this)}updateAfterNode(e){const t=e.getUpdateAfterType(),s=e.updateReference(this);if(t===Bd.FRAME){const{frameMap:t}=this._getMaps(this.updateAfterMap,s);t.get(s)!==this.frameId&&!1!==e.updateAfter(this)&&t.set(s,this.frameId)}else if(t===Bd.RENDER){const{renderMap:t}=this._getMaps(this.updateAfterMap,s);t.get(s)!==this.renderId&&!1!==e.updateAfter(this)&&t.set(s,this.renderId)}else t===Bd.OBJECT&&e.updateAfter(this)}updateNode(e){const t=e.getUpdateType(),s=e.updateReference(this);if(t===Bd.FRAME){const{frameMap:t}=this._getMaps(this.updateMap,s);t.get(s)!==this.frameId&&!1!==e.update(this)&&t.set(s,this.frameId)}else if(t===Bd.RENDER){const{renderMap:t}=this._getMaps(this.updateMap,s);t.get(s)!==this.renderId&&!1!==e.update(this)&&t.set(s,this.renderId)}else t===Bd.OBJECT&&e.update(this)}update(){this.frameId++,void 0===this.lastTime&&(this.lastTime=performance.now()),this.deltaTime=(performance.now()-this.lastTime)/1e3,this.lastTime=performance.now(),this.time+=this.deltaTime}}class vM{constructor(e,t,s=null,i="",r=!1){this.type=e,this.name=t,this.count=s,this.qualifier=i,this.isConst=r}}vM.isNodeFunctionInput=!0;class TM extends Ld{static get type(){return"StructTypeNode"}constructor(e){super(),this.types=e,this.isStructTypeNode=!0}getMemberTypes(){return this.types}}class _M extends Ld{static get type(){return"OutputStructNode"}constructor(...e){super(),this.members=e,this.isOutputStructNode=!0}setup(e){super.setup(e);const t=this.members,s=[];for(let i=0;ir&&(i=s,r=n)}}this._candidateFnCall=s=i(...t)}return s}}const CM=Ap(AM),RM=e=>(...t)=>CM(e,...t);class EM extends dm{static get type(){return"TimerNode"}constructor(e=EM.LOCAL,t=1,s=0){super(s),this.scope=e,this.scale=t,this.updateType=Bd.FRAME}update(e){const t=this.scope,s=this.scale;t===EM.LOCAL?this.value+=e.deltaTime*s:t===EM.DELTA?this.value=e.deltaTime*s:t===EM.FRAME?this.value=e.frameId:this.value=e.time*s}serialize(e){super.serialize(e),e.scope=this.scope,e.scale=this.scale}deserialize(e){super.deserialize(e),this.scope=e.scope,this.scale=e.scale}}EM.LOCAL="local",EM.GLOBAL="global",EM.DELTA="delta",EM.FRAME="frame";const BM=(e,t=0)=>Sp(new EM(EM.LOCAL,e,t)),IM=(e,t=0)=>Sp(new EM(EM.GLOBAL,e,t)),PM=(e,t=0)=>Sp(new EM(EM.DELTA,e,t)),FM=Cp(EM,EM.FRAME).toUint();class zM extends Ld{static get type(){return"OscNode"}constructor(e=zM.SINE,t=BM()){super(),this.method=e,this.timeNode=t}getNodeType(e){return this.timeNode.getNodeType(e)}setup(){const e=this.method,t=Sp(this.timeNode);let s=null;return e===zM.SINE?s=t.add(.75).mul(2*Math.PI).sin().mul(.5).add(.5):e===zM.SQUARE?s=t.fract().round():e===zM.TRIANGLE?s=t.add(.5).fract().mul(2).sub(1).abs():e===zM.SAWTOOTH&&(s=t.fract()),s}serialize(e){super.serialize(e),e.method=this.method}deserialize(e){super.deserialize(e),this.method=e.method}}zM.SINE="sine",zM.SQUARE="square",zM.TRIANGLE="triangle",zM.SAWTOOTH="sawtooth";const UM=Ap(zM,zM.SINE),OM=Ap(zM,zM.SQUARE),LM=Ap(zM,zM.TRIANGLE),VM=Ap(zM,zM.SAWTOOTH);class DM extends Ld{static get type(){return"SpriteSheetUVNode"}constructor(e,t=My(),s=Up(0)){super("vec2"),this.countNode=e,this.uvNode=t,this.frameNode=s}setup(){const{frameNode:e,uvNode:t,countNode:s}=this,{width:i,height:r}=s,n=e.mod(i.mul(r)).floor(),o=n.mod(i),a=r.sub(n.add(1).div(i).ceil()),h=s.reciprocal(),u=Dp(o,a);return t.add(u).mul(h)}}const kM=Ap(DM);class GM extends Vd{static get type(){return"StorageArrayElementNode"}constructor(e,t){super(e,t),this.isStorageArrayElementNode=!0}set storageBufferNode(e){this.node=e}get storageBufferNode(){return this.node}setup(e){return!1===e.isAvailable("storageBuffer")&&!0===this.node.bufferObject&&e.setupPBO(this.node),super.setup(e)}generate(e,t){let s;const i=e.context.assign;if(s=!1===e.isAvailable("storageBuffer")?!0===this.node.bufferObject&&!0!==i?e.generatePBO(this):this.node.build(e):super.generate(e),!0!==i){const i=this.getNodeType(e);s=e.format(s,i,t)}return s}}const WM=Ap(GM);class jM extends Ld{static get type(){return"TriplanarTexturesNode"}constructor(e,t=null,s=null,i=Up(1),r=ax,n=yx){super("vec4"),this.textureXNode=e,this.textureYNode=t,this.textureZNode=s,this.scaleNode=i,this.positionNode=r,this.normalNode=n}setup(){const{textureXNode:e,textureYNode:t,textureZNode:s,scaleNode:i,positionNode:r,normalNode:n}=this;let o=n.abs().normalize();o=o.div(o.dot(jp(1)));const a=r.yz.mul(i),h=r.zx.mul(i),u=r.xy.mul(i),l=e.value,c=null!==t?t.value:l,d=null!==s?s.value:l,p=By(l,a).mul(o.x),m=By(c,h).mul(o.y),g=By(d,u).mul(o.z);return Zm(p,m,g)}}const HM=Ap(jM),qM=(...e)=>HM(...e),$M=new Ko,XM=new Ri,YM=new Ri,ZM=new Ri,JM=new nr,KM=new Ri(0,0,-1),QM=new Ti,eN=new Ri,tN=new Ri,sN=new Ti,iN=new Qs,rN=new _i,nN=Dv.flipX();let oN=!1;class aN extends Ey{static get type(){return"ReflectorNode"}constructor(e={}){super(rN.texture,nN);const{target:t=new Ir,resolution:s=1,generateMipmaps:i=!1,bounces:r=!0}=e;this.target=t,this.resolution=s,this.generateMipmaps=i,this.bounces=r,this.updateBeforeType=r?Bd.RENDER:Bd.FRAME,this.virtualCameras=new WeakMap,this.renderTargets=new WeakMap}_updateResolution(e,t){const s=this.resolution;t.getDrawingBufferSize(iN),e.setSize(Math.round(iN.width*s),Math.round(iN.height*s))}setup(e){return this._updateResolution(rN,e.renderer),super.setup(e)}getTextureNode(){return this.textureNode}getVirtualCamera(e){let t=this.virtualCameras.get(e);return void 0===t&&(t=e.clone(),this.virtualCameras.set(e,t)),t}getRenderTarget(e){let t=this.renderTargets.get(e);return void 0===t&&(t=new _i(0,0,{type:Pe}),!0===this.generateMipmaps&&(t.texture.minFilter=1008,t.texture.generateMipmaps=!0),this.renderTargets.set(e,t)),t}updateBefore(e){if(!1===this.bounces&&oN)return!1;oN=!0;const{scene:t,camera:s,renderer:i,material:r}=e,{target:n}=this,o=this.getVirtualCamera(s),a=this.getRenderTarget(o);if(i.getDrawingBufferSize(iN),this._updateResolution(a,i),YM.setFromMatrixPosition(n.matrixWorld),ZM.setFromMatrixPosition(s.matrixWorld),JM.extractRotation(n.matrixWorld),XM.set(0,0,1),XM.applyMatrix4(JM),eN.subVectors(YM,ZM),eN.dot(XM)>0)return;eN.reflect(XM).negate(),eN.add(YM),JM.extractRotation(s.matrixWorld),KM.set(0,0,-1),KM.applyMatrix4(JM),KM.add(ZM),tN.subVectors(YM,KM),tN.reflect(XM).negate(),tN.add(YM),o.coordinateSystem=s.coordinateSystem,o.position.copy(eN),o.up.set(0,1,0),o.up.applyMatrix4(JM),o.up.reflect(XM),o.lookAt(tN),o.near=s.near,o.far=s.far,o.updateMatrixWorld(),o.projectionMatrix.copy(s.projectionMatrix),$M.setFromNormalAndCoplanarPoint(XM,YM),$M.applyMatrix4(o.matrixWorldInverse),QM.set($M.normal.x,$M.normal.y,$M.normal.z,$M.constant);const h=o.projectionMatrix;sN.x=(Math.sign(QM.x)+h.elements[8])/h.elements[0],sN.y=(Math.sign(QM.y)+h.elements[9])/h.elements[5],sN.z=-1,sN.w=(1+h.elements[10])/h.elements[14],QM.multiplyScalar(1/QM.dot(sN));h.elements[2]=QM.x,h.elements[6]=QM.y,h.elements[10]=QM.z-0,h.elements[14]=QM.w,this.value=a.texture,r.visible=!1;const u=i.getRenderTarget(),l=i.getMRT();i.setMRT(null),i.setRenderTarget(a),i.render(t,o),i.setMRT(l),i.setRenderTarget(u),r.visible=!0,oN=!1}}const hN=e=>Sp(new aN(e)),uN=new Sl(-1,1,1,-1,0,1);class lN extends An{constructor(e=!1){super();const t=!1===e?[0,-1,0,1,2,1]:[0,2,0,0,2,0];this.setAttribute("position",new bn([-1,3,0,-1,-1,0,3,-1,0],3)),this.setAttribute("uv",new bn(t,2))}}const cN=new lN;class dN extends Vn{constructor(e=null){super(cN,e),this.camera=uN,this.isQuadMesh=!0}renderAsync(e){return e.renderAsync(this,uN)}render(e){e.render(this,uN)}}const pN=new Qs;class mN extends Ey{static get type(){return"RTTNode"}constructor(e,t=null,s=null,i={type:Pe}){const r=new _i(t,s,i);super(r.texture,My()),this.node=e,this.width=t,this.height=s,this.renderTarget=r,this.textureNeedsUpdate=!0,this.autoUpdate=!0,this.updateMap=new WeakMap,this._rttNode=null,this._quadMesh=new dN(new pT),this.updateBeforeType=Bd.RENDER}get autoSize(){return null===this.width}setup(e){return this._rttNode=this.node.context(e.getSharedContext()),this._quadMesh.material.name="RTT",this._quadMesh.material.needsUpdate=!0,super.setup(e)}setSize(e,t){this.width=e,this.height=t;const s=e*this.pixelRatio,i=t*this.pixelRatio;this.renderTarget.setSize(s,i),this.textureNeedsUpdate=!0}setPixelRatio(e){this.pixelRatio=e,this.setSize(this.width,this.height)}updateBefore({renderer:e}){if(!1===this.textureNeedsUpdate&&!1===this.autoUpdate)return;if(this.textureNeedsUpdate=!1,!0===this.autoSize){this.pixelRatio=e.getPixelRatio();const t=e.getSize(pN);this.setSize(t.width,t.height)}this._quadMesh.material.fragmentNode=this._rttNode;const t=e.getRenderTarget();e.setRenderTarget(this.renderTarget),this._quadMesh.render(e),e.setRenderTarget(t)}clone(){const e=new Ey(this.value,this.uvNode,this.levelNode);return e.sampler=this.sampler,e.referenceNode=this,e}}const gN=(e,...t)=>Sp(new mN(Sp(e),...t)),fN=(e,...t)=>e.isTextureNode?e:gN(e,...t);class yN extends wy{static get type(){return"VertexColorNode"}constructor(e=0){super(null,"vec4"),this.isVertexColorNode=!0,this.index=e}getAttributeName(){const e=this.index;return"color"+(e>0?e:"")}generate(e){const t=this.getAttributeName(e);let s;return s=!0===e.hasGeometryAttribute(t)?super.generate(e):e.generateConst(this.nodeType,new Ti(1,1,1,1)),s}serialize(e){super.serialize(e),e.index=this.index}deserialize(e){super.deserialize(e),this.index=e.index}}const xN=(...e)=>Sp(new yN(...e));class bN extends Ld{static get type(){return"PointUVNode"}constructor(){super("vec2"),this.isPointUVNode=!0}generate(){return"vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y )"}}const vN=Cp(bN);class TN extends Ld{static get type(){return"SceneNode"}constructor(e=TN.BACKGROUND_BLURRINESS,t=null){super(),this.scope=e,this.scene=t}setup(e){const t=this.scope,s=null!==this.scene?this.scene:e.scene;let i;return t===TN.BACKGROUND_BLURRINESS?i=kx("backgroundBlurriness","float",s):t===TN.BACKGROUND_INTENSITY?i=kx("backgroundIntensity","float",s):console.error("THREE.SceneNode: Unknown scope:",t),i}}TN.BACKGROUND_BLURRINESS="backgroundBlurriness",TN.BACKGROUND_INTENSITY="backgroundIntensity";const _N=Cp(TN,TN.BACKGROUND_BLURRINESS),wN=Cp(TN,TN.BACKGROUND_INTENSITY),SN="point-list",MN="line-list",NN="line-strip",AN="triangle-list",CN="triangle-strip",RN="never",EN="less",BN="equal",IN="less-equal",PN="greater",FN="not-equal",zN="greater-equal",UN="always",ON="store",LN="load",VN="clear",DN="ccw",kN="none",GN="front",WN="back",jN="uint16",HN="uint32",qN={R8Unorm:"r8unorm",R8Snorm:"r8snorm",R8Uint:"r8uint",R8Sint:"r8sint",R16Uint:"r16uint",R16Sint:"r16sint",R16Float:"r16float",RG8Unorm:"rg8unorm",RG8Snorm:"rg8snorm",RG8Uint:"rg8uint",RG8Sint:"rg8sint",R32Uint:"r32uint",R32Sint:"r32sint",R32Float:"r32float",RG16Uint:"rg16uint",RG16Sint:"rg16sint",RG16Float:"rg16float",RGBA8Unorm:"rgba8unorm",RGBA8UnormSRGB:"rgba8unorm-srgb",RGBA8Snorm:"rgba8snorm",RGBA8Uint:"rgba8uint",RGBA8Sint:"rgba8sint",BGRA8Unorm:"bgra8unorm",BGRA8UnormSRGB:"bgra8unorm-srgb",RGB9E5UFloat:"rgb9e5ufloat",RGB10A2Unorm:"rgb10a2unorm",RG11B10uFloat:"rgb10a2unorm",RG32Uint:"rg32uint",RG32Sint:"rg32sint",RG32Float:"rg32float",RGBA16Uint:"rgba16uint",RGBA16Sint:"rgba16sint",RGBA16Float:"rgba16float",RGBA32Uint:"rgba32uint",RGBA32Sint:"rgba32sint",RGBA32Float:"rgba32float",Stencil8:"stencil8",Depth16Unorm:"depth16unorm",Depth24Plus:"depth24plus",Depth24PlusStencil8:"depth24plus-stencil8",Depth32Float:"depth32float",Depth32FloatStencil8:"depth32float-stencil8",BC1RGBAUnorm:"bc1-rgba-unorm",BC1RGBAUnormSRGB:"bc1-rgba-unorm-srgb",BC2RGBAUnorm:"bc2-rgba-unorm",BC2RGBAUnormSRGB:"bc2-rgba-unorm-srgb",BC3RGBAUnorm:"bc3-rgba-unorm",BC3RGBAUnormSRGB:"bc3-rgba-unorm-srgb",BC4RUnorm:"bc4-r-unorm",BC4RSnorm:"bc4-r-snorm",BC5RGUnorm:"bc5-rg-unorm",BC5RGSnorm:"bc5-rg-snorm",BC6HRGBUFloat:"bc6h-rgb-ufloat",BC6HRGBFloat:"bc6h-rgb-float",BC7RGBAUnorm:"bc7-rgba-unorm",BC7RGBAUnormSRGB:"bc7-rgba-srgb",ETC2RGB8Unorm:"etc2-rgb8unorm",ETC2RGB8UnormSRGB:"etc2-rgb8unorm-srgb",ETC2RGB8A1Unorm:"etc2-rgb8a1unorm",ETC2RGB8A1UnormSRGB:"etc2-rgb8a1unorm-srgb",ETC2RGBA8Unorm:"etc2-rgba8unorm",ETC2RGBA8UnormSRGB:"etc2-rgba8unorm-srgb",EACR11Unorm:"eac-r11unorm",EACR11Snorm:"eac-r11snorm",EACRG11Unorm:"eac-rg11unorm",EACRG11Snorm:"eac-rg11snorm",ASTC4x4Unorm:"astc-4x4-unorm",ASTC4x4UnormSRGB:"astc-4x4-unorm-srgb",ASTC5x4Unorm:"astc-5x4-unorm",ASTC5x4UnormSRGB:"astc-5x4-unorm-srgb",ASTC5x5Unorm:"astc-5x5-unorm",ASTC5x5UnormSRGB:"astc-5x5-unorm-srgb",ASTC6x5Unorm:"astc-6x5-unorm",ASTC6x5UnormSRGB:"astc-6x5-unorm-srgb",ASTC6x6Unorm:"astc-6x6-unorm",ASTC6x6UnormSRGB:"astc-6x6-unorm-srgb",ASTC8x5Unorm:"astc-8x5-unorm",ASTC8x5UnormSRGB:"astc-8x5-unorm-srgb",ASTC8x6Unorm:"astc-8x6-unorm",ASTC8x6UnormSRGB:"astc-8x6-unorm-srgb",ASTC8x8Unorm:"astc-8x8-unorm",ASTC8x8UnormSRGB:"astc-8x8-unorm-srgb",ASTC10x5Unorm:"astc-10x5-unorm",ASTC10x5UnormSRGB:"astc-10x5-unorm-srgb",ASTC10x6Unorm:"astc-10x6-unorm",ASTC10x6UnormSRGB:"astc-10x6-unorm-srgb",ASTC10x8Unorm:"astc-10x8-unorm",ASTC10x8UnormSRGB:"astc-10x8-unorm-srgb",ASTC10x10Unorm:"astc-10x10-unorm",ASTC10x10UnormSRGB:"astc-10x10-unorm-srgb",ASTC12x10Unorm:"astc-12x10-unorm",ASTC12x10UnormSRGB:"astc-12x10-unorm-srgb",ASTC12x12Unorm:"astc-12x12-unorm",ASTC12x12UnormSRGB:"astc-12x12-unorm-srgb"},$N="clamp-to-edge",XN="repeat",YN="mirror-repeat",ZN="linear",JN="nearest",KN="zero",QN="one",eA="src",tA="one-minus-src",sA="src-alpha",iA="one-minus-src-alpha",rA="dst",nA="one-minus-dst",oA="dst-alpha",aA="one-minus-dst-alpha",hA="src-alpha-saturated",uA="constant",lA="one-minus-constant",cA="add",dA="subtract",pA="reverse-subtract",mA="min",gA="max",fA=0,yA=15,xA="keep",bA="zero",vA="replace",TA="invert",_A="increment-clamp",wA="decrement-clamp",SA="increment-wrap",MA="decrement-wrap",NA="storage",AA="read-only-storage",CA="write-only",RA="read-only",EA="float",BA="unfilterable-float",IA="depth",PA="sint",FA="uint",zA="2d",UA="3d",OA="2d",LA="2d-array",VA="cube",DA="3d",kA="all",GA="vertex",WA="instance",jA={DepthClipControl:"depth-clip-control",Depth32FloatStencil8:"depth32float-stencil8",TextureCompressionBC:"texture-compression-bc",TextureCompressionETC2:"texture-compression-etc2",TextureCompressionASTC:"texture-compression-astc",TimestampQuery:"timestamp-query",IndirectFirstInstance:"indirect-first-instance",ShaderF16:"shader-f16",RG11B10UFloat:"rg11b10ufloat-renderable",BGRA8UNormStorage:"bgra8unorm-storage",Float32Filterable:"float32-filterable",ClipDistances:"clip-distances",DualSourceBlending:"dual-source-blending",Subgroups:"subgroups"};class HA extends Px{static get type(){return"StorageBufferNode"}constructor(e,t,s=0){super(e,t,s),this.isStorageBufferNode=!0,this.access=NA,this.isAtomic=!1,this.bufferObject=!1,this.bufferCount=s,this._attribute=null,this._varying=null,this.global=!0,!0!==e.isStorageBufferAttribute&&!0!==e.isStorageInstancedBufferAttribute&&(e.isInstancedBufferAttribute?e.isStorageInstancedBufferAttribute=!0:e.isStorageBufferAttribute=!0)}getHash(e){if(0===this.bufferCount){let t=e.globalCache.getData(this.value);return void 0===t&&(t={node:this},e.globalCache.setData(this.value,t)),t.node.uuid}return this.uuid}getInputType(){return"storageBuffer"}element(e){return WM(this,e)}setBufferObject(e){return this.bufferObject=e,this}setAccess(e){return this.access=e,this}toReadOnly(){return this.setAccess(AA)}setAtomic(e){return this.isAtomic=e,this}toAtomic(){return this.setAtomic(!0)}generate(e){if(e.isAvailable("storageBuffer"))return super.generate(e);const t=this.getNodeType(e);null===this._attribute&&(this._attribute=iy(this.value),this._varying=Vf(this._attribute));const s=this._varying.build(e,t);return e.registerTransform(s,this._attribute),s}}const qA=(e,t,s)=>Sp(new HA(e,t,s)),$A=(e,t,s)=>Sp(new HA(e,t,s).setBufferObject(!0));class XA extends Ey{static get type(){return"StorageTextureNode"}constructor(e,t,s=null){super(e,t),this.storeNode=s,this.isStorageTextureNode=!0,this.access=CA}getInputType(){return"storageTexture"}setup(e){super.setup(e);e.getNodeProperties(this).storeNode=this.storeNode}setAccess(e){return this.access=e,this}generate(e,t){let s;return s=null!==this.storeNode?this.generateStore(e):super.generate(e,t),s}toReadOnly(){return this.setAccess(RA)}toWriteOnly(){return this.setAccess(CA)}generateStore(e){const t=e.getNodeProperties(this),{uvNode:s,storeNode:i}=t,r=super.generate(e,"property"),n=s.build(e,"uvec2"),o=i.build(e,"vec4"),a=e.generateTextureStore(e,r,n,o);e.addLineFlowCode(a,this)}}const YA=Ap(XA),ZA=(e,t,s)=>{const i=YA(e,t,s);return null!==s&&i.append(),i};class JA extends Dx{static get type(){return"UserDataNode"}constructor(e,t,s=null){super(e,t,s),this.userData=s}updateReference(e){return this.reference=null!==this.userData?this.userData:e.object.userData,this.reference}}const KA=(e,t,s)=>Sp(new JA(e,t,s));class QA extends kd{static get type(){return"PosterizeNode"}constructor(e,t){super(),this.sourceNode=e,this.stepsNode=t}setup(){const{sourceNode:e,stepsNode:t}=this;return e.mul(t).floor().div(t)}}const eC=Ap(QA);let tC=null;class sC extends Jv{static get type(){return"ViewportSharedTextureNode"}constructor(e=Dv,t=null){null===tC&&(tC=new ja),super(e,t,tC)}updateReference(){return this}}const iC=Ap(sC),rC=new Qs;class nC extends Ey{static get type(){return"PassTextureNode"}constructor(e,t){super(t),this.passNode=e,this.setUpdateMatrix(!1)}setup(e){return e.object.isQuadMesh&&this.passNode.build(e),super.setup(e)}clone(){return new this.constructor(this.passNode,this.value)}}class oC extends nC{static get type(){return"PassMultipleTextureNode"}constructor(e,t,s=!1){super(e,null),this.textureName=t,this.previousTexture=s}updateTexture(){this.value=this.previousTexture?this.passNode.getPreviousTexture(this.textureName):this.passNode.getTexture(this.textureName)}setup(e){return this.updateTexture(),super.setup(e)}clone(){return new this.constructor(this.passNode,this.textureName,this.previousTexture)}}class aC extends kd{static get type(){return"PassNode"}constructor(e,t,s,i={}){super("vec4"),this.scope=e,this.scene=t,this.camera=s,this.options=i,this._pixelRatio=1,this._width=1,this._height=1;const r=new Ya;r.isRenderTargetTexture=!0,r.name="depth";const n=new _i(this._width*this._pixelRatio,this._height*this._pixelRatio,{type:Pe,...i});n.texture.name="output",n.depthTexture=r,this.renderTarget=n,this.updateBeforeType=Bd.FRAME,this._textures={output:n.texture,depth:r},this._textureNodes={},this._linearDepthNodes={},this._viewZNodes={},this._previousTextures={},this._previousTextureNodes={},this._cameraNear=pm(0),this._cameraFar=pm(0),this._mrt=null,this.isPassNode=!0}setMRT(e){return this._mrt=e,this}getMRT(){return this._mrt}isGlobal(){return!0}getTexture(e){let t=this._textures[e];if(void 0===t){t=this.renderTarget.texture.clone(),t.isRenderTargetTexture=!0,t.name=e,this._textures[e]=t,this.renderTarget.textures.push(t)}return t}getPreviousTexture(e){let t=this._previousTextures[e];return void 0===t&&(t=this.getTexture(e).clone(),t.isRenderTargetTexture=!0,this._previousTextures[e]=t),t}toggleTexture(e){const t=this._previousTextures[e];if(void 0!==t){const s=this._textures[e],i=this.renderTarget.textures.indexOf(s);this.renderTarget.textures[i]=t,this._textures[e]=t,this._previousTextures[e]=s,this._textureNodes[e].updateTexture(),this._previousTextureNodes[e].updateTexture()}}getTextureNode(e="output"){let t=this._textureNodes[e];return void 0===t&&(this._textureNodes[e]=t=Sp(new oC(this,e)),this._textureNodes[e].updateTexture()),t}getPreviousTextureNode(e="output"){let t=this._previousTextureNodes[e];return void 0===t&&(void 0===this._textureNodes[e]&&this.getTextureNode(e),this._previousTextureNodes[e]=t=Sp(new oC(this,e,!0)),this._previousTextureNodes[e].updateTexture()),t}getViewZNode(e="depth"){let t=this._viewZNodes[e];if(void 0===t){const s=this._cameraNear,i=this._cameraFar;this._viewZNodes[e]=t=aT(this.getTextureNode(e),s,i)}return t}getLinearDepthNode(e="depth"){let t=this._linearDepthNodes[e];if(void 0===t){const s=this._cameraNear,i=this._cameraFar,r=this.getViewZNode(e);this._linearDepthNodes[e]=t=rT(r,s,i)}return t}setup({renderer:e}){return this.renderTarget.samples=void 0===this.options.samples?e.samples:this.options.samples,!0===e.backend.isWebGLBackend&&(this.renderTarget.samples=0),this.renderTarget.depthTexture.isMultisampleRenderTargetTexture=this.renderTarget.samples>1,this.scope===aC.COLOR?this.getTextureNode():this.getLinearDepthNode()}updateBefore(e){const{renderer:t}=e,{scene:s,camera:i}=this;this._pixelRatio=t.getPixelRatio();const r=t.getSize(rC);this.setSize(r.width,r.height);const n=t.getRenderTarget(),o=t.getMRT();this._cameraNear.value=i.near,this._cameraFar.value=i.far;for(const e in this._previousTextures)this.toggleTexture(e);t.setRenderTarget(this.renderTarget),t.setMRT(this._mrt),t.render(s,i),t.setRenderTarget(n),t.setMRT(o)}setSize(e,t){this._width=e,this._height=t;const s=this._width*this._pixelRatio,i=this._height*this._pixelRatio;this.renderTarget.setSize(s,i)}setPixelRatio(e){this._pixelRatio=e,this.setSize(this._width,this._height)}dispose(){this.renderTarget.dispose()}}aC.COLOR="color",aC.DEPTH="depth";const hC=(e,t,s)=>Sp(new aC(aC.COLOR,e,t,s)),uC=(e,t)=>Sp(new nC(e,t)),lC=(e,t)=>Sp(new aC(aC.DEPTH,e,t)),cC=new dN,dC=new dN;class pC extends kd{static get type(){return"GaussianBlurNode"}constructor(e,t=null,s=2){super("vec4"),this.textureNode=e,this.directionNode=t,this.sigma=s,this._invSize=pm(new Qs),this._passDirection=pm(new Qs),this._horizontalRT=new _i,this._horizontalRT.texture.name="GaussianBlurNode.horizontal",this._verticalRT=new _i,this._verticalRT.texture.name="GaussianBlurNode.vertical",this._textureNode=uC(this,this._verticalRT.texture),this.updateBeforeType=Bd.RENDER,this.resolution=new Qs(1,1)}setSize(e,t){e=Math.max(Math.round(e*this.resolution.x),1),t=Math.max(Math.round(t*this.resolution.y),1),this._invSize.value.set(1/e,1/t),this._horizontalRT.setSize(e,t),this._verticalRT.setSize(e,t)}updateBefore(e){const{renderer:t}=e,s=this.textureNode,i=s.value,r=t.getRenderTarget(),n=t.getMRT(),o=s.value;cC.material=this._material,dC.material=this._material,this.setSize(i.image.width,i.image.height);const a=i.type;this._horizontalRT.texture.type=a,this._verticalRT.texture.type=a,t.setMRT(null),t.setRenderTarget(this._horizontalRT),this._passDirection.value.set(1,0),cC.render(t),s.value=this._horizontalRT.texture,t.setRenderTarget(this._verticalRT),this._passDirection.value.set(0,1),dC.render(t),t.setRenderTarget(r),t.setMRT(n),s.value=o}getTextureNode(){return this._textureNode}setup(e){const t=this.textureNode;if(!0!==t.isTextureNode)return console.error("GaussianBlurNode requires a TextureNode."),Xp();const s=t.uvNode||My(),i=Dp(this.directionNode||1),r=e=>t.uv(e),n=Rp((()=>{const e=3+2*this.sigma,t=this._getCoefficients(e),n=this._invSize,o=i.mul(this._passDirection),a=Up(t[0]).toVar(),h=Xp(r(s).mul(a)).toVar();for(let i=1;iSp(new pC(fN(e),t,s)),gC=new Qs,fC=new dN;class yC extends kd{static get type(){return"AfterImageNode"}constructor(e,t=.96){super(e),this.textureNode=e,this.textureNodeOld=By(),this.damp=pm(t),this._compRT=new _i,this._compRT.texture.name="AfterImageNode.comp",this._oldRT=new _i,this._oldRT.texture.name="AfterImageNode.old",this._textureNode=uC(this,this._compRT.texture),this.updateBeforeType=Bd.RENDER}getTextureNode(){return this._textureNode}setSize(e,t){this._compRT.setSize(e,t),this._oldRT.setSize(e,t)}updateBefore(e){const{renderer:t}=e,s=this.textureNode,i=s.value.type;this._compRT.texture.type=i,this._oldRT.texture.type=i,t.getDrawingBufferSize(gC),this.setSize(gC.x,gC.y);const r=t.getRenderTarget(),n=s.value;this.textureNodeOld.value=this._oldRT.texture,t.setRenderTarget(this._compRT),fC.render(t);const o=this._oldRT;this._oldRT=this._compRT,this._compRT=o,t.setRenderTarget(r),s.value=n}setup(e){const t=this.textureNode,s=this.textureNodeOld,i=t.uvNode||My();s.uvNode=i;const r=Rp((([e,t])=>{const s=Up(t).toVar(),i=Xp(e).toVar();return of(Hg(i.sub(s)),0)})),n=Rp((()=>{const e=Xp(s),n=Xp((e=>t.uv(e))(i));return e.mulAssign(this.damp.mul(r(e,.1))),of(n,e)})),o=this._materialComposed||(this._materialComposed=new pT);o.name="AfterImage",o.fragmentNode=n(),fC.material=o;return e.getNodeProperties(this).textureNode=t,this._textureNode}dispose(){this._compRT.dispose(),this._oldRT.dispose()}}const xC=(e,t)=>Sp(new yC(fN(e),t)),bC=Rp((([e])=>SC(e.rgb))),vC=Rp((([e,t=Up(1)])=>t.mix(SC(e.rgb),e.rgb))),TC=Rp((([e,t=Up(1)])=>{const s=Zm(e.r,e.g,e.b).div(3),i=e.r.max(e.g.max(e.b)),r=i.sub(s).mul(t).mul(-3);return Tf(e.rgb,i,r)})),_C=Rp((([e,t=Up(1)])=>{const s=jp(.57735,.57735,.57735),i=t.cos();return jp(e.rgb.mul(i).add(s.cross(e.rgb).mul(t.sin()).add(s.mul(df(s,e.rgb).mul(i.oneMinus())))))})),wC=new Ri,SC=(e,t=jp(...ci.getLuminanceCoefficients(wC)))=>df(e,t),MC=(e,t)=>Tf(jp(0),e,SC(e).sub(t).max(0)),NC=new dN;class AC extends kd{static get type(){return"AnamorphicNode"}constructor(e,t,s,i){super("vec4"),this.textureNode=e,this.tresholdNode=t,this.scaleNode=s,this.colorNode=jp(.1,0,1),this.samples=i,this.resolution=new Qs(1,1),this._renderTarget=new _i,this._renderTarget.texture.name="anamorphic",this._invSize=pm(new Qs),this._textureNode=uC(this,this._renderTarget.texture),this.updateBeforeType=Bd.RENDER}getTextureNode(){return this._textureNode}setSize(e,t){this._invSize.value.set(1/e,1/t),e=Math.max(Math.round(e*this.resolution.x),1),t=Math.max(Math.round(t*this.resolution.y),1),this._renderTarget.setSize(e,t)}updateBefore(e){const{renderer:t}=e,s=this.textureNode,i=s.value;this._renderTarget.texture.type=i.type;const r=t.getRenderTarget(),n=s.value;NC.material=this._material,this.setSize(i.image.width,i.image.height),t.setRenderTarget(this._renderTarget),NC.render(t),t.setRenderTarget(r),s.value=n}setup(e){const t=this.textureNode,s=t.uvNode||My(),i=Rp((()=>{const e=this.samples,i=Math.floor(e/2),r=jp(0).toVar();return bv({start:-i,end:i},(({i:e})=>{const n=Up(e).abs().div(i).oneMinus(),o=(e=>t.uv(e))(Dp(s.x.add(this._invSize.x.mul(e).mul(this.scaleNode)),s.y)),a=MC(o,this.tresholdNode).mul(n);r.addAssign(a)})),r.mul(this.colorNode)})),r=this._material||(this._material=new pT);r.name="Anamorphic",r.fragmentNode=i();return e.getNodeProperties(this).textureNode=t,this._textureNode}dispose(){this._renderTarget.dispose()}}const CC=(e,t=.9,s=3,i=32)=>Sp(new AC(fN(e),Sp(t),Sp(s),i));class RC extends kd{static get type(){return"SobelOperatorNode"}constructor(e){super(),this.textureNode=e,this.updateBeforeType=Bd.RENDER,this._invSize=pm(new Qs)}updateBefore(){const e=this.textureNode.value;this._invSize.value.set(1/e.image.width,1/e.image.height)}setup(){const{textureNode:e}=this,t=e.uvNode||My(),s=t=>e.uv(t);return Rp((()=>{const e=this._invSize,i=Qp(-1,-2,-1,0,0,0,1,2,1),r=Qp(-1,0,1,-2,0,2,-1,0,1),n=SC(s(t.add(e.mul(Dp(-1,-1)))).xyz),o=SC(s(t.add(e.mul(Dp(-1,0)))).xyz),a=SC(s(t.add(e.mul(Dp(-1,1)))).xyz),h=SC(s(t.add(e.mul(Dp(0,-1)))).xyz),u=SC(s(t.add(e.mul(Dp(0,0)))).xyz),l=SC(s(t.add(e.mul(Dp(0,1)))).xyz),c=SC(s(t.add(e.mul(Dp(1,-1)))).xyz),d=SC(s(t.add(e.mul(Dp(1,0)))).xyz),p=SC(s(t.add(e.mul(Dp(1,1)))).xyz),m=Zm(i[0][0].mul(n),i[1][0].mul(h),i[2][0].mul(c),i[0][1].mul(o),i[1][1].mul(u),i[2][1].mul(d),i[0][2].mul(a),i[1][2].mul(l),i[2][2].mul(p)),g=Zm(r[0][0].mul(n),r[1][0].mul(h),r[2][0].mul(c),r[0][1].mul(o),r[1][1].mul(u),r[2][1].mul(d),r[0][2].mul(a),r[1][2].mul(l),r[2][2].mul(p)),f=m.mul(m).add(g.mul(g)).sqrt();return Xp(jp(f),1)}))()}}const EC=e=>Sp(new RC(fN(e)));class BC extends kd{static get type(){return"DepthOfFieldNode"}constructor(e,t,s,i,r){super(),this.textureNode=e,this.viewZNode=t,this.focusNode=s,this.apertureNode=i,this.maxblurNode=r,this._aspect=pm(0),this.updateBeforeType=Bd.RENDER}updateBefore(){const e=this.textureNode.value;this._aspect.value=e.image.width/e.image.height}setup(){const e=this.textureNode,t=e.uvNode||My(),s=t=>e.uv(t);return Rp((()=>{const e=Dp(1,this._aspect),i=this.focusNode.add(this.viewZNode),r=Dp(_f(i.mul(this.apertureNode),this.maxblurNode.negate(),this.maxblurNode)),n=r.mul(.9),o=r.mul(.7),a=r.mul(.4);let h=Xp(0);return h=h.add(s(t)),h=h.add(s(t.add(Dp(0,.4).mul(e).mul(r)))),h=h.add(s(t.add(Dp(.15,.37).mul(e).mul(r)))),h=h.add(s(t.add(Dp(.29,.29).mul(e).mul(r)))),h=h.add(s(t.add(Dp(-.37,.15).mul(e).mul(r)))),h=h.add(s(t.add(Dp(.4,0).mul(e).mul(r)))),h=h.add(s(t.add(Dp(.37,-.15).mul(e).mul(r)))),h=h.add(s(t.add(Dp(.29,-.29).mul(e).mul(r)))),h=h.add(s(t.add(Dp(-.15,-.37).mul(e).mul(r)))),h=h.add(s(t.add(Dp(0,-.4).mul(e).mul(r)))),h=h.add(s(t.add(Dp(-.15,.37).mul(e).mul(r)))),h=h.add(s(t.add(Dp(-.29,.29).mul(e).mul(r)))),h=h.add(s(t.add(Dp(.37,.15).mul(e).mul(r)))),h=h.add(s(t.add(Dp(-.4,0).mul(e).mul(r)))),h=h.add(s(t.add(Dp(-.37,-.15).mul(e).mul(r)))),h=h.add(s(t.add(Dp(-.29,-.29).mul(e).mul(r)))),h=h.add(s(t.add(Dp(.15,-.37).mul(e).mul(r)))),h=h.add(s(t.add(Dp(.15,.37).mul(e).mul(n)))),h=h.add(s(t.add(Dp(-.37,.15).mul(e).mul(n)))),h=h.add(s(t.add(Dp(.37,-.15).mul(e).mul(n)))),h=h.add(s(t.add(Dp(-.15,-.37).mul(e).mul(n)))),h=h.add(s(t.add(Dp(-.15,.37).mul(e).mul(n)))),h=h.add(s(t.add(Dp(.37,.15).mul(e).mul(n)))),h=h.add(s(t.add(Dp(-.37,-.15).mul(e).mul(n)))),h=h.add(s(t.add(Dp(.15,-.37).mul(e).mul(n)))),h=h.add(s(t.add(Dp(.29,.29).mul(e).mul(o)))),h=h.add(s(t.add(Dp(.4,0).mul(e).mul(o)))),h=h.add(s(t.add(Dp(.29,-.29).mul(e).mul(o)))),h=h.add(s(t.add(Dp(0,-.4).mul(e).mul(o)))),h=h.add(s(t.add(Dp(-.29,.29).mul(e).mul(o)))),h=h.add(s(t.add(Dp(-.4,0).mul(e).mul(o)))),h=h.add(s(t.add(Dp(-.29,-.29).mul(e).mul(o)))),h=h.add(s(t.add(Dp(0,.4).mul(e).mul(o)))),h=h.add(s(t.add(Dp(.29,.29).mul(e).mul(a)))),h=h.add(s(t.add(Dp(.4,0).mul(e).mul(a)))),h=h.add(s(t.add(Dp(.29,-.29).mul(e).mul(a)))),h=h.add(s(t.add(Dp(0,-.4).mul(e).mul(a)))),h=h.add(s(t.add(Dp(-.29,.29).mul(e).mul(a)))),h=h.add(s(t.add(Dp(-.4,0).mul(e).mul(a)))),h=h.add(s(t.add(Dp(-.29,-.29).mul(e).mul(a)))),h=h.add(s(t.add(Dp(0,.4).mul(e).mul(a)))),h=h.div(41),h.a=1,Xp(h)}))()}}const IC=(e,t,s=1,i=.025,r=1)=>Sp(new BC(fN(e),Sp(t),Sp(s),Sp(i),Sp(r)));class PC extends kd{static get type(){return"DotScreenNode"}constructor(e,t=new Qs(.5,.5),s=1.57,i=1){super("vec4"),this.inputNode=e,this.center=pm(t),this.angle=pm(s),this.scale=pm(i)}setup(){const e=this.inputNode,t=Rp((()=>{const e=Lg(this.angle),t=Vg(this.angle),s=My().mul(kv).sub(this.center),i=Dp(t.mul(s.x).sub(e.mul(s.y)),e.mul(s.x).add(t.mul(s.y))).mul(this.scale);return Lg(i.x).mul(Lg(i.y)).mul(4)})),s=Rp((()=>{const s=e,i=Zm(s.r,s.g,s.b).div(3);return Xp(jp(i.mul(10).sub(5).add(t())),s.a)}));return s()}}const FC=(e,t,s,i)=>Sp(new PC(Sp(e),t,s,i));class zC extends kd{static get type(){return"RGBShiftNode"}constructor(e,t=.005,s=0){super("vec4"),this.textureNode=e,this.amount=pm(t),this.angle=pm(s)}setup(){const{textureNode:e}=this,t=e.uvNode||My(),s=t=>e.uv(t);return Rp((()=>{const e=Dp(Vg(this.angle),Lg(this.angle)).mul(this.amount),i=s(t.add(e)),r=s(t),n=s(t.sub(e));return Xp(i.r,r.g,n.b,r.a)}))()}}const UC=(e,t,s)=>Sp(new zC(fN(e),t,s));class OC extends kd{static get type(){return"FilmNode"}constructor(e,t=null,s=null){super(),this.inputNode=e,this.intensityNode=t,this.uvNode=s}setup(){const e=this.uvNode||My(),t=Rp((()=>{const t=this.inputNode.rgb,s=Af(Og(e.add(BM())));let i=t.add(t.mul(_f(s.add(.1),0,1)));return null!==this.intensityNode&&(i=Tf(t,i,this.intensityNode)),Xp(i,this.inputNode.a)}));return t()}}const LC=Ap(OC);class VC extends kd{static get type(){return"Lut3DNode"}constructor(e,t,s,i){super(),this.inputNode=e,this.lutNode=t,this.size=pm(s),this.intensityNode=i}setup(){const{inputNode:e,lutNode:t}=this,s=Rp((()=>{const s=e,i=Up(1).div(this.size),r=Up(.5).div(this.size),n=jp(r).add(s.rgb.mul(Up(1).sub(i))),o=Xp((e=>t.uv(e))(n).rgb,s.a);return Xp(Tf(s,o,this.intensityNode))}));return s()}}const DC=(e,t,s,i)=>Sp(new VC(Sp(e),Sp(t),s,Sp(i))),kC=new dN,GC=new Jr,WC=new Qs;class jC extends kd{static get type(){return"GTAONode"}constructor(e,t,s){super(),this.depthNode=e,this.normalNode=t,this.radius=pm(.25),this.resolution=pm(new Qs),this.thickness=pm(1),this.distanceExponent=pm(1),this.distanceFallOff=pm(1),this.scale=pm(1),this.noiseNode=By(function(e=5){const t=Math.floor(e)%2==0?Math.floor(e)+1:Math.floor(e),s=function(e){const t=Math.floor(e)%2==0?Math.floor(e)+1:Math.floor(e),s=t*t,i=Array(s).fill(0);let r=Math.floor(t/2),n=t-1;for(let e=1;e<=s;)-1===r&&n===t?(n=t-2,r=0):(n===t&&(n=0),r<0&&(r=t-1)),0===i[r*t+n]?(i[r*t+n]=e++,n++,r--):(n-=2,r++);return i}(t),i=s.length,r=new Uint8Array(4*i);for(let e=0;ethis.depthNode.uv(e).x,i=e=>this.noiseNode.uv(e),r=Rp((([e])=>{const t=this.cameraProjectionMatrix.mul(Xp(e,1));let i=t.xy.div(t.w).mul(.5).add(.5).toVar();i=Dp(i.x,i.y.oneMinus());const r=s(i);return jp(i,r)})),n=Rp((([e,t])=>{e=Dp(e.x,e.y.oneMinus()).mul(2).sub(1);const s=Xp(jp(e,t),1),i=Xp(this.cameraProjectionMatrixInverse.mul(s));return i.xyz.div(i.w)})),o=Rp((()=>{const e=s(t);e.greaterThanEqual(1).discard();const o=n(t,e),a=this.normalNode.rgb.normalize(),h=this.radius,u=Ay(this.noiseNode,0);let l=Dp(t.x,t.y.oneMinus());l=l.mul(this.resolution.div(u));const c=i(l),d=c.xyz.mul(2).sub(1),p=jp(d.xy,0).normalize(),m=jp(p.y.mul(-1),p.x,0),g=Qp(p,m,jp(0,0,1)),f=this.SAMPLES.lessThan(30).select(3,5),y=Zm(this.SAMPLES,f.sub(1)).div(f),x=Up(0).toVar();return bv({start:Op(0),end:f,type:"int",condition:"<"},(({i:e})=>{const t=Up(e).div(Up(f)).mul(Tg),s=Xp(Vg(t),Lg(t),0,Zm(.5,Km(.5,c.w)));s.xyz=Ug(g.mul(s.xyz));const i=Ug(o.xyz.negate()),u=Ug(pf(s.xyz,i)),l=pf(u,i),d=Ug(a.sub(u.mul(df(a,u)))),p=pf(d,u),m=Dp(df(i,p),df(i,p.negate())).toVar();bv({end:y,type:"int",name:"j",condition:"<"},(({j:e})=>{const t=s.xyz.mul(h).mul(s.w).mul(mf(Qm(Up(e).add(1),Up(y)),this.distanceExponent)),a=r(o.add(t)),u=n(a.xy,a.z).sub(o);Pp(jg(u.z).lessThan(this.thickness),(()=>{const t=df(i,Ug(u));m.x.addAssign(of(0,Km(t.sub(m.x),Tf(1,Up(2).div(Up(e).add(2)),this.distanceFallOff))))}));const l=r(o.sub(t)),c=n(l.xy,l.z).sub(o);Pp(jg(c.z).lessThan(this.thickness),(()=>{const t=df(i,Ug(c));m.y.addAssign(of(0,Km(t.sub(m.y),Tf(1,Up(2).div(Up(e).add(2)),this.distanceFallOff))))}))}));const b=Ig(Jm(1,m.mul(m))),v=df(d,l),T=df(d,i),_=Km(.5,Gg(m.y).sub(Gg(m.x)).add(b.x.mul(m.x).sub(b.y.mul(m.y)))),w=Km(.5,Jm(2,m.x.mul(m.x)).sub(m.y.mul(m.y))),S=v.mul(_).add(T.mul(w));x.addAssign(S)})),x.assign(_f(x.div(f),0,1)),x.assign(mf(x,this.scale)),Xp(jp(x),1)})),a=this._material||(this._material=new pT);return a.fragmentNode=o().context(e.getSharedContext()),a.name="GTAO",a.needsUpdate=!0,this._textureNode}dispose(){this._aoRenderTarget.dispose()}}const HC=(e,t,s)=>Sp(new jC(Sp(e),Sp(t),s));class qC extends kd{static get type(){return"DenoiseNode"}constructor(e,t,s,i,r){super(),this.textureNode=e,this.depthNode=t,this.normalNode=s,this.noiseNode=i,this.cameraProjectionMatrixInverse=pm(r.projectionMatrixInverse),this.lumaPhi=pm(5),this.depthPhi=pm(5),this.normalPhi=pm(5),this.radius=pm(5),this.index=pm(0),this._resolution=pm(new Qs),this._sampleVectors=Ox(function(e,t,s){const i=function(e,t,s){const i=[];for(let r=0;rthis.textureNode.uv(e),s=e=>this.depthNode.uv(e).x,i=e=>this.normalNode.uv(e),r=e=>this.noiseNode.uv(e),n=Rp((([e,t])=>{e=Dp(e.x,e.y.oneMinus()).mul(2).sub(1);const s=Xp(jp(e,t),1),i=Xp(this.cameraProjectionMatrixInverse.mul(s));return i.xyz.div(i.w)})),o=Rp((([e,r,o,a])=>{const h=t(a),u=s(a),l=i(a).rgb.normalize(),c=h.rgb,d=n(a,u),p=df(r,l).toVar(),m=mf(of(p,0),this.normalPhi).toVar(),g=jg(SC(c).sub(SC(e))).toVar(),f=of(Up(1).sub(g.div(this.lumaPhi)),0).toVar(),y=jg(df(o.sub(d),r)).toVar(),x=of(Up(1).sub(y.div(this.depthPhi)),0),b=f.mul(x).mul(m);return Xp(c.mul(b),b)})),a=Rp((([e])=>{const a=s(e),h=i(e).rgb.normalize(),u=t(e);Pp(a.greaterThanEqual(1).or(df(h,h).equal(0)),(()=>u));const l=jp(u.rgb),c=n(e,a),d=Ay(this.noiseNode,0);let p=Dp(e.x,e.y.oneMinus());p=p.mul(this._resolution.div(d));const m=r(p),g=Lg(m.element(this.index.mod(4).mul(2).mul(Tg))),f=Vg(m.element(this.index.mod(4).mul(2).mul(Tg))),y=Dp(g,f),x=Kp(y.x,y.y.negate(),y.x,y.y),b=Up(1).toVar(),v=jp(u.rgb).toVar();return bv({start:Op(0),end:Op(16),type:"int",condition:"<"},(({i:t})=>{const s=this._sampleVectors.element(t).toVar(),i=x.mul(s.xy.mul(Up(1).add(s.z.mul(this.radius.sub(1))))).div(this._resolution).toVar(),r=e.add(i).toVar(),n=o(l,h,c,r);v.addAssign(n.xyz),b.addAssign(n.w)})),Pp(b.greaterThan(Up(0)),(()=>{v.divAssign(b)})),Xp(v,u.a)})).setLayout({name:"denoise",type:"vec4",inputs:[{name:"uv",type:"vec2"}]});return Rp((()=>a(e)))()}}const $C=(e,t,s,i,r)=>Sp(new qC(fN(e),Sp(t),Sp(s),Sp(i),r));class XC extends kd{static get type(){return"FXAANode"}constructor(e){super(),this.textureNode=e,this.updateBeforeType=Bd.RENDER,this._invSize=pm(new Qs)}updateBefore(){const e=this.textureNode.value;this._invSize.value.set(1/e.image.width,1/e.image.height)}setup(){const e=this.textureNode.bias(-100),t=e.uvNode||My(),s=t=>e.uv(t),i=(t,s,i)=>e.uv(t.add(s.mul(i))),r=Op(5),n=Rp((([e,t])=>{const s=Xp(t).toVar(),i=Xp(e).toVar(),r=Xp(jg(i.sub(s))).toVar();return of(of(of(r.r,r.g),r.b),r.a)})),o=Rp((([e,t,o,a])=>{const h=s(e).toVar(),u=i(e,Dp(0,-1),t.xy).toVar(),l=i(e,Dp(1,0),t.xy).toVar(),c=i(e,Dp(0,1),t.xy).toVar(),d=i(e,Dp(-1,0),t.xy).toVar(),p=n(h,c).toVar(),m=n(h,u).toVar(),g=n(h,l).toVar(),f=n(h,d).toVar(),y=of(p,of(m,of(g,f))).toVar();Pp(y.lessThan(o),(()=>h));const x=Jm(p.add(m),g.add(f)).toVar();x.mulAssign(a),Pp(jg(x).lessThan(.3),(()=>{const s=g.greaterThan(f).select(1,-1).toVar(),r=m.greaterThan(p).select(1,-1).toVar(),o=Dp(s,r).toVar(),y=i(e,Dp(o.x,o.y),t.xy),b=n(h,y).toVar(),v=i(e,Dp(o.x.negate(),o.y.negate()),t.xy),T=n(h,v).toVar();x.assign(T.sub(b)),x.mulAssign(a),Pp(jg(x).lessThan(.3),(()=>{const e=c.add(u).add(l).add(d);return Tf(h,e.mul(.25),.4)}))}));const b=Dp().toVar();Pp(x.lessThanEqual(0),(()=>{c.assign(d),u.assign(l),b.x.assign(0),b.y.assign(t.y)})).Else((()=>{b.x.assign(t.x),b.y.assign(0)}));const v=n(h,c).toVar(),T=n(h,u).toVar();Pp(v.lessThanEqual(T),(()=>{c.assign(u)}));const _=Op(0).toVar(),w=Op(0).toVar(),S=Up(0).toVar(),M=Up(0).toVar(),N=Dp(e).toVar(),A=Dp(e).toVar(),C=Op(0).toVar(),R=Op(0).toVar();bv(r,(({i:t})=>{const i=t.add(1).toVar();Pp(_.equal(0),(()=>{S.addAssign(i),N.assign(e.add(b.mul(S)));const r=s(N.xy),o=n(r,h).toVar(),a=n(r,c).toVar();Pp(o.greaterThan(a),(()=>{_.assign(1)})),C.assign(t)})),Pp(w.equal(0),(()=>{M.addAssign(i),A.assign(e.sub(b.mul(M)));const r=s(A.xy),o=n(r,h).toVar(),a=n(r,c).toVar();Pp(o.greaterThan(a),(()=>{w.assign(1)})),R.assign(t)})),Pp(_.equal(1).or(w.equal(1)),(()=>{Tv()}))})),Pp(_.equal(0).and(w.equal(0)),(()=>h));const E=Up(1).toVar(),B=Up(1).toVar();Pp(_.equal(1),(()=>{E.assign(Up(C).div(Up(r.sub(1))))})),Pp(w.equal(1),(()=>{B.assign(Up(R).div(Up(r.sub(1))))}));const I=nf(E,B);return I.assign(mf(I,.5)),I.assign(Up(1).sub(I)),Tf(h,c,I.mul(.5))})).setLayout({name:"FxaaPixelShader",type:"vec4",inputs:[{name:"uv",type:"vec2"},{name:"fxaaQualityRcpFrame",type:"vec2"},{name:"fxaaQualityEdgeThreshold",type:"float"},{name:"fxaaQualityinvEdgeThreshold",type:"float"}]});return Rp((()=>{const e=Up(.2),s=Up(1).div(e);return o(t,this._invSize,e,s)}))()}}const YC=e=>Sp(new XC(fN(e))),ZC=new dN,JC=new Jr(0,0,0),KC=new Jr,QC=new Qs,eR=new Qs(1,0),tR=new Qs(0,1);class sR extends kd{static get type(){return"BloomNode"}constructor(e,t=1,s=0,i=0){super(),this.inputNode=e,this.strength=pm(t),this.radius=pm(s),this.threshold=pm(i),this.smoothWidth=pm(.01),this._renderTargetsHorizontal=[],this._renderTargetsVertical=[],this._nMips=5,this._renderTargetBright=new _i(1,1,{type:Pe}),this._renderTargetBright.texture.name="UnrealBloomPass.bright",this._renderTargetBright.texture.generateMipmaps=!1;for(let e=0;e{const e=this.inputNode,t=SC(e.rgb),s=Mf(this.threshold,this.threshold.add(this.smoothWidth),t);return Tf(Xp(0),e,s)}));this._highPassFilterMaterial=this._highPassFilterMaterial||new pT,this._highPassFilterMaterial.fragmentNode=t().context(e.getSharedContext()),this._highPassFilterMaterial.name="Bloom_highPass",this._highPassFilterMaterial.needsUpdate=!0;const s=[3,5,7,9,11];for(let t=0;t{const s=Up(1.2).sub(e);return Tf(e,s,t)})).setLayout({name:"lerpBloomFactor",type:"float",inputs:[{name:"factor",type:"float"},{name:"radius",type:"float"}]}),o=Rp((()=>{const e=n(i.element(0),this.radius).mul(Xp(r.element(0),1)).mul(this._textureNodeBlur0),t=n(i.element(1),this.radius).mul(Xp(r.element(1),1)).mul(this._textureNodeBlur1),s=n(i.element(2),this.radius).mul(Xp(r.element(2),1)).mul(this._textureNodeBlur2),o=n(i.element(3),this.radius).mul(Xp(r.element(3),1)).mul(this._textureNodeBlur3),a=n(i.element(4),this.radius).mul(Xp(r.element(4),1)).mul(this._textureNodeBlur4);return e.add(t).add(s).add(o).add(a).mul(this.strength)}));return this._compositeMaterial=this._compositeMaterial||new pT,this._compositeMaterial.fragmentNode=o().context(e.getSharedContext()),this._compositeMaterial.name="Bloom_comp",this._compositeMaterial.needsUpdate=!0,this._textureOutput}dispose(){for(let e=0;ei.uv(e),u=Rp((()=>{const e=r.element(0).toVar(),s=h(a).rgb.mul(e).toVar();return bv({start:Op(1),end:Op(t),type:"int",condition:"<"},(({i:t})=>{const i=Up(t),u=r.element(t),l=o.mul(n).mul(i),c=h(a.add(l)).rgb,d=h(a.sub(l)).rgb;s.addAssign(Zm(c,d).mul(u)),e.addAssign(Up(2).mul(u))})),Xp(s.div(e),1)})),l=new pT;return l.fragmentNode=u().context(e.getSharedContext()),l.name="Bloom_seperable",l.needsUpdate=!0,l.colorTexture=i,l.direction=o,l.invSize=n,l}}const iR=(e,t,s,i)=>Sp(new sR(Sp(e),t,s,i));class rR extends kd{static get type(){return"TransitionNode"}constructor(e,t,s,i,r,n){super(),this.textureNodeA=e,this.textureNodeB=t,this.mixTextureNode=s,this.mixRatioNode=i,this.thresholdNode=r,this.useTextureNode=n}setup(){const{textureNodeA:e,textureNodeB:t,mixTextureNode:s,mixRatioNode:i,thresholdNode:r,useTextureNode:n}=this,o=e=>{const t=e.uvNode||My();return e.uv(t)},a=Rp((()=>{const a=o(e),h=o(t),u=Xp().toVar();return Pp(n.equal(Op(1)),(()=>{const e=o(s),t=i.mul(r.mul(2).add(1)).sub(r),n=_f(Jm(e.r,t).mul(Up(1).div(r)),0,1);u.assign(Tf(a,h,n))})).Else((()=>{u.assign(Tf(h,a,i))})),u}));return a()}}const nR=(e,t,s,i=0,r=.1,n=0)=>Sp(new rR(fN(e),fN(t),fN(s),Sp(i),Sp(r),Sp(n)));class oR extends kd{static get type(){return"PixelationNode"}constructor(e,t,s,i,r,n){super(),this.textureNode=e,this.depthNode=t,this.normalNode=s,this.pixelSize=i,this.normalEdgeStrength=r,this.depthEdgeStrength=n,this._resolution=pm(new Ti),this.updateBeforeType=Bd.RENDER}updateBefore(){const e=this.textureNode.value,t=e.image.width,s=e.image.height;this._resolution.value.set(t,s,1/t,1/s)}setup(){const{textureNode:e,depthNode:t,normalNode:s}=this,i=e.uvNode||My(),r=t.uvNode||My(),n=s.uvNode||My(),o=(e,s)=>t.uv(r.add(Dp(e,s).mul(this._resolution.zw))).r,a=(e,t)=>s.uv(n.add(Dp(e,t).mul(this._resolution.zw))).rgb.normalize(),h=(e,t,s,i)=>{const r=o(e,t).sub(s),n=a(e,t),h=jp(1,1,1),u=df(i.sub(n),h),l=_f(Mf(-.01,.01,u),0,1),c=_f(Hg(r.mul(.25).add(.0025)),0,1);return Up(1).sub(df(i,n)).mul(c).mul(l)},u=Rp((()=>{const t=e.uv(i),s=gm("float","depth"),r=gm("vec3","normal");Pp(this.depthEdgeStrength.greaterThan(0).or(this.normalEdgeStrength.greaterThan(0)),(()=>{s.assign(o(0,0)),r.assign(a(0,0))}));const n=gm("float","dei");Pp(this.depthEdgeStrength.greaterThan(0),(()=>{n.assign((e=>{const t=gm("float","diff");return t.addAssign(_f(o(1,0).sub(e))),t.addAssign(_f(o(-1,0).sub(e))),t.addAssign(_f(o(0,1).sub(e))),t.addAssign(_f(o(0,-1).sub(e))),Fg(Mf(.01,.02,t).mul(2)).div(2)})(s))}));const u=gm("float","nei");Pp(this.normalEdgeStrength.greaterThan(0),(()=>{u.assign(((e,t)=>{const s=gm("float","indicator");return s.addAssign(h(0,-1,e,t)),s.addAssign(h(0,1,e,t)),s.addAssign(h(-1,0,e,t)),s.addAssign(h(1,0,e,t)),hf(.1,s)})(s,r))}));const l=n.greaterThan(0).select(Up(1).sub(n.mul(this.depthEdgeStrength)),u.mul(this.normalEdgeStrength).add(1));return t.mul(l)}));return u()}}class aR extends aC{static get type(){return"PixelationPassNode"}constructor(e,t,s=6,i=.3,r=.4){super("color",e,t,{minFilter:fe,magFilter:fe}),this.pixelSize=s,this.normalEdgeStrength=i,this.depthEdgeStrength=r,this.isPixelationPassNode=!0,this._mrt=NM({output:zm,normal:bx})}setSize(e,t){const s=this.pixelSize.value?this.pixelSize.value:this.pixelSize,i=Math.floor(e/s),r=Math.floor(t/s);super.setSize(i,r)}setup(){return((e,t,s,i=6,r=.3,n=.4)=>Sp(new oR(fN(e),fN(t),fN(s),Sp(i),Sp(r),Sp(n))))(super.getTextureNode("output"),super.getTextureNode("depth"),super.getTextureNode("normal"),this.pixelSize,this.normalEdgeStrength,this.depthEdgeStrength)}}const hR=(e,t,s,i,r)=>Sp(new aR(e,t,s,i,r)),uR=new Qs;class lR extends aC{static get type(){return"SSAAPassNode"}constructor(e,t){super(aC.COLOR,e,t),this.isSSAAPassNode=!0,this.sampleLevel=4,this.unbiased=!0,this.clearColor=new Jr(0),this.clearAlpha=0,this._currentClearColor=new Jr,this.sampleWeight=pm(1),this.sampleRenderTarget=null,this._quadMesh=new dN}updateBefore(e){const{renderer:t}=e,{scene:s,camera:i}=this;this._pixelRatio=t.getPixelRatio();const r=t.getSize(uR);this.setSize(r.width,r.height),this.sampleRenderTarget.setSize(this.renderTarget.width,this.renderTarget.height),t.getClearColor(this._currentClearColor);const n=t.getClearAlpha(),o=t.getRenderTarget(),a=t.getMRT(),h=t.autoClear;this._cameraNear.value=i.near,this._cameraFar.value=i.far,t.setMRT(this.getMRT()),t.autoClear=!1;const u=cR[Math.max(0,Math.min(this.sampleLevel,5))],l=1/u.length,c={fullWidth:this.renderTarget.width,fullHeight:this.renderTarget.height,offsetX:0,offsetY:0,width:this.renderTarget.width,height:this.renderTarget.height},d=Object.assign({},i.view);d.enabled&&Object.assign(c,d);for(let e=0;e=0&&(e[t]=By(this.sampleRenderTarget.textures[s]).mul(this.sampleWeight))}t=NM(e)}else t=By(this.sampleRenderTarget.texture).mul(this.sampleWeight);return this._quadMesh.material=new pT,this._quadMesh.material.fragmentNode=t,this._quadMesh.material.transparent=!0,this._quadMesh.material.depthTest=!1,this._quadMesh.material.depthWrite=!1,this._quadMesh.material.premultipliedAlpha=!0,this._quadMesh.material.blending=2,this._quadMesh.material.normals=!1,this._quadMesh.material.name="SSAA",super.setup(e)}dispose(){super.dispose(),null!==this.sampleRenderTarget&&this.sampleRenderTarget.dispose()}}const cR=[[[0,0]],[[4,4],[-4,-4]],[[-2,-6],[6,-2],[-6,2],[2,6]],[[1,-3],[-1,3],[5,1],[-3,-5],[-5,5],[-7,-1],[3,7],[7,-7]],[[1,1],[-1,-3],[-3,2],[4,-1],[-5,-2],[2,5],[5,3],[3,-5],[-2,6],[0,-7],[-4,-6],[-6,4],[-8,0],[7,-4],[6,7],[-7,-8]],[[-4,-7],[-7,-5],[-3,-5],[-5,-4],[-1,-4],[-2,-2],[-6,-1],[-4,0],[-7,1],[-1,2],[-6,3],[-3,3],[-7,6],[-3,6],[-5,7],[-1,7],[5,-7],[1,-6],[6,-5],[4,-4],[2,-3],[7,-2],[1,-1],[4,-1],[2,1],[6,2],[0,4],[4,4],[2,5],[7,5],[5,6],[3,7]]],dR=(e,t)=>Sp(new lR(e,t)),pR=new Qs;class mR extends aC{static get type(){return"StereoPassNode"}constructor(e,t){super(aC.COLOR,e,t),this.isStereoPassNode=!0,this.stereo=new ql,this.stereo.aspect=.5}updateBefore(e){const{renderer:t}=e,{scene:s,camera:i,stereo:r,renderTarget:n}=this;this._pixelRatio=t.getPixelRatio(),r.cameraL.coordinateSystem=t.coordinateSystem,r.cameraR.coordinateSystem=t.coordinateSystem,r.update(i);const o=t.getSize(pR);this.setSize(o.width,o.height);const a=t.autoClear;t.autoClear=!1;const h=t.getRenderTarget(),u=t.getMRT();this._cameraNear.value=i.near,this._cameraFar.value=i.far;for(const e in this._previousTextures)this.toggleTexture(e);t.setRenderTarget(n),t.setMRT(this._mrt),t.clear(),n.scissorTest=!0,n.scissor.set(0,0,n.width/2,n.height),n.viewport.set(0,0,n.width/2,n.height),t.render(s,r.cameraL),n.scissor.set(n.width/2,0,n.width/2,n.height),n.viewport.set(n.width/2,0,n.width/2,n.height),t.render(s,r.cameraR),n.scissorTest=!1,t.setRenderTarget(h),t.setMRT(u),t.autoClear=a}}const gR=(e,t)=>Sp(new mR(e,t)),fR=new Qs,yR=new dN;class xR extends aC{static get type(){return"StereoCompositePassNode"}constructor(e,t){super(aC.COLOR,e,t),this.isStereoCompositePassNode=!0,this.stereo=new ql;const s={minFilter:Te,magFilter:fe,type:Pe};this._renderTargetL=new _i(1,1,s),this._renderTargetR=new _i(1,1,s),this._mapLeft=By(this._renderTargetL.texture),this._mapRight=By(this._renderTargetR.texture),this._material=null}updateStereoCamera(e){this.stereo.cameraL.coordinateSystem=e,this.stereo.cameraR.coordinateSystem=e,this.stereo.update(this.camera)}setSize(e,t){super.setSize(e,t),this._renderTargetL.setSize(this.renderTarget.width,this.renderTarget.height),this._renderTargetR.setSize(this.renderTarget.width,this.renderTarget.height)}updateBefore(e){const{renderer:t}=e,{scene:s,stereo:i,renderTarget:r}=this;this._pixelRatio=t.getPixelRatio(),this.updateStereoCamera(t.coordinateSystem);const n=t.getSize(fR);this.setSize(n.width,n.height);const o=t.getRenderTarget();t.setRenderTarget(this._renderTargetL),t.render(s,i.cameraL),t.setRenderTarget(this._renderTargetR),t.render(s,i.cameraR),t.setRenderTarget(r),yR.material=this._material,yR.render(t),t.setRenderTarget(o)}dispose(){super.dispose(),this._renderTargetL.dispose(),this._renderTargetR.dispose(),null!==this._material&&this._material.dispose()}}class bR extends xR{static get type(){return"AnaglyphPassNode"}constructor(e,t){super(e,t),this.isAnaglyphPassNode=!0,this._colorMatrixLeft=pm((new ei).fromArray([.4561,-.0400822,-.0152161,.500484,-.0378246,-.0205971,.176381,-.0157589,-.00546856])),this._colorMatrixRight=pm((new ei).fromArray([-.0434706,.378476,-.0721527,-.0879388,.73364,-.112961,-.00155529,-.0184503,1.2264]))}setup(e){const t=My(),s=Rp((()=>{const e=this._mapLeft.uv(t),s=this._mapRight.uv(t),i=_f(this._colorMatrixLeft.mul(e.rgb).add(this._colorMatrixRight.mul(s.rgb)));return Xp(i.rgb,of(e.a,s.a))})),i=this._material||(this._material=new pT);return i.fragmentNode=s().context(e.getSharedContext()),i.name="Anaglyph",i.needsUpdate=!0,super.setup(e)}}const vR=(e,t)=>Sp(new bR(e,t));class TR extends xR{static get type(){return"ParallaxBarrierPassNode"}constructor(e,t){super(e,t),this.isParallaxBarrierPassNode=!0}setup(e){const t=My(),s=Rp((()=>{const e=Xp().toVar();return Pp(af(Gv.y,2).greaterThan(1),(()=>{e.assign(this._mapLeft.uv(t))})).Else((()=>{e.assign(this._mapRight.uv(t))})),e})),i=this._material||(this._material=new pT);return i.fragmentNode=s().context(e.getSharedContext()),i.needsUpdate=!0,super.setup(e)}}const _R=(e,t)=>Sp(new TR(e,t));class wR extends aC{static get type(){return"ToonOutlinePassNode"}constructor(e,t,s,i,r){super(aC.COLOR,e,t),this.colorNode=s,this.thicknessNode=i,this.alphaNode=r,this._materialCache=new WeakMap}updateBefore(e){const{renderer:t}=e,s=t.getRenderObjectFunction();t.setRenderObjectFunction(((e,s,i,r,n,o,a)=>{if((n.isMeshToonMaterial||n.isMeshToonNodeMaterial)&&!1===n.wireframe){const h=this._getOutlineMaterial(n);t.renderObject(e,s,i,r,h,o,a)}t.renderObject(e,s,i,r,n,o,a)})),super.updateBefore(e),t.setRenderObjectFunction(s)}_createMaterial(){const e=new pT;e.isMeshToonOutlineMaterial=!0,e.name="Toon_Outline",e.side=d;const t=yx.negate(),s=Oy.mul(ix),i=Up(1),r=s.mul(Xp(ax,1)),n=s.mul(Xp(ax.add(t),1)),o=Ug(r.sub(n));return e.vertexNode=r.add(o.mul(this.thicknessNode).mul(r.w).mul(i)),e.colorNode=Xp(this.colorNode,this.alphaNode),e}_getOutlineMaterial(e){let t=this._materialCache.get(e);return void 0===t&&(t=this._createMaterial(),this._materialCache.set(e,t)),t}}const SR=(e,t,s=new Jr(0,0,0),i=.003,r=1)=>Sp(new wR(e,t,Sp(s),Sp(i),Sp(r)));class MR extends Ld{static get type(){return"ScriptableValueNode"}constructor(e=null){super(),this._value=e,this._cache=null,this.inputType=null,this.outpuType=null,this.events=new ks,this.isScriptableValueNode=!0}get isScriptableOutputNode(){return null!==this.outputType}set value(e){this._value!==e&&(this._cache&&"URL"===this.inputType&&this.value.value instanceof ArrayBuffer&&(URL.revokeObjectURL(this._cache),this._cache=null),this._value=e,this.events.dispatchEvent({type:"change"}),this.refresh())}get value(){return this._value}refresh(){this.events.dispatchEvent({type:"refresh"})}getValue(){const e=this.value;if(e&&null===this._cache&&"URL"===this.inputType&&e.value instanceof ArrayBuffer)this._cache=URL.createObjectURL(new Blob([e.value]));else if(e&&null!==e.value&&void 0!==e.value&&(("URL"===this.inputType||"String"===this.inputType)&&"string"==typeof e.value||"Number"===this.inputType&&"number"==typeof e.value||"Vector2"===this.inputType&&e.value.isVector2||"Vector3"===this.inputType&&e.value.isVector3||"Vector4"===this.inputType&&e.value.isVector4||"Color"===this.inputType&&e.value.isColor||"Matrix3"===this.inputType&&e.value.isMatrix3||"Matrix4"===this.inputType&&e.value.isMatrix4))return e.value;return this._cache||e}getNodeType(e){return this.value&&this.value.isNode?this.value.getNodeType(e):"float"}setup(){return this.value&&this.value.isNode?this.value:Up()}serialize(e){super.serialize(e),null!==this.value?"ArrayBuffer"===this.inputType?e.value=Ad(this.value):e.value=this.value?this.value.toJSON(e.meta).uuid:null:e.value=null,e.inputType=this.inputType,e.outputType=this.outputType}deserialize(e){super.deserialize(e);let t=null;null!==e.value&&(t="ArrayBuffer"===e.inputType?Cd(e.value):"Texture"===e.inputType?e.meta.textures[e.value]:e.meta.nodes[e.value]||null),this.value=t,this.inputType=e.inputType,this.outputType=e.outputType}}const NR=Ap(MR);class AR extends Map{get(e,t=null,...s){if(this.has(e))return super.get(e);if(null!==t){const i=t(...s);return this.set(e,i),i}}}class CR{constructor(e){this.scriptableNode=e}get parameters(){return this.scriptableNode.parameters}get layout(){return this.scriptableNode.getLayout()}getInputLayout(e){return this.scriptableNode.getInputLayout(e)}get(e){const t=this.parameters[e];return t?t.getValue():null}}const RR=new AR;class ER extends Ld{static get type(){return"ScriptableNode"}constructor(e=null,t={}){super(),this.codeNode=e,this.parameters=t,this._local=new AR,this._output=NR(),this._outputs={},this._source=this.source,this._method=null,this._object=null,this._value=null,this._needsOutputUpdate=!0,this.onRefresh=this.onRefresh.bind(this),this.isScriptableNode=!0}get source(){return this.codeNode?this.codeNode.code:""}setLocal(e,t){return this._local.set(e,t)}getLocal(e){return this._local.get(e)}onRefresh(){this._refresh()}getInputLayout(e){for(const t of this.getLayout())if(t.inputType&&(t.id===e||t.name===e))return t}getOutputLayout(e){for(const t of this.getLayout())if(t.outputType&&(t.id===e||t.name===e))return t}setOutput(e,t){const s=this._outputs;return void 0===s[e]?s[e]=NR(t):s[e].value=t,this}getOutput(e){return this._outputs[e]}getParameter(e){return this.parameters[e]}setParameter(e,t){const s=this.parameters;return t&&t.isScriptableNode?(this.deleteParameter(e),s[e]=t,s[e].getDefaultOutput().events.addEventListener("refresh",this.onRefresh)):t&&t.isScriptableValueNode?(this.deleteParameter(e),s[e]=t,s[e].events.addEventListener("refresh",this.onRefresh)):void 0===s[e]?(s[e]=NR(t),s[e].events.addEventListener("refresh",this.onRefresh)):s[e].value=t,this}getValue(){return this.getDefaultOutput().getValue()}deleteParameter(e){let t=this.parameters[e];return t&&(t.isScriptableNode&&(t=t.getDefaultOutput()),t.events.removeEventListener("refresh",this.onRefresh)),this}clearParameters(){for(const e of Object.keys(this.parameters))this.deleteParameter(e);return this.needsUpdate=!0,this}call(e,...t){const s=this.getObject()[e];if("function"==typeof s)return s(...t)}async callAsync(e,...t){const s=this.getObject()[e];if("function"==typeof s)return"AsyncFunction"===s.constructor.name?await s(...t):s(...t)}getNodeType(e){return this.getDefaultOutputNode().getNodeType(e)}refresh(e=null){null!==e?this.getOutput(e).refresh():this._refresh()}getObject(){if(this.needsUpdate&&this.dispose(),null!==this._object)return this._object;const e=new CR(this),t=RR.get("THREE"),s=RR.get("TSL"),i=this.getMethod(this.codeNode),r=[e,this._local,RR,()=>this.refresh(),(e,t)=>this.setOutput(e,t),t,s];this._object=i(...r);const n=this._object.layout;if(n&&(!1===n.cache&&this._local.clear(),this._output.outputType=n.outputType||null,Array.isArray(n.elements)))for(const e of n.elements){const t=e.id||e.name;e.inputType&&(void 0===this.getParameter(t)&&this.setParameter(t,null),this.getParameter(t).inputType=e.inputType),e.outputType&&(void 0===this.getOutput(t)&&this.setOutput(t,null),this.getOutput(t).outputType=e.outputType)}return this._object}deserialize(e){super.deserialize(e);for(const e in this.parameters){let t=this.parameters[e];t.isScriptableNode&&(t=t.getDefaultOutput()),t.events.addEventListener("refresh",this.onRefresh)}}getLayout(){return this.getObject().layout}getDefaultOutputNode(){const e=this.getDefaultOutput().value;return e&&e.isNode?e:Up()}getDefaultOutput(){return this._exec()._output}getMethod(){if(this.needsUpdate&&this.dispose(),null!==this._method)return this._method;const e=["layout","init","main","dispose"].join(", "),t="\nreturn { ...output, "+e+" };",s="var "+e+"; var output = {};\n"+this.codeNode.code+t;return this._method=new Function(...["parameters","local","global","refresh","setOutput","THREE","TSL"],s),this._method}dispose(){null!==this._method&&(this._object&&"function"==typeof this._object.dispose&&this._object.dispose(),this._method=null,this._object=null,this._source=null,this._value=null,this._needsOutputUpdate=!0,this._output.value=null,this._outputs={})}setup(){return this.getDefaultOutputNode()}getCacheKey(e){const t=[vd(this.source),this.getDefaultOutputNode().getCacheKey(e)];for(const s in this.parameters)t.push(this.parameters[s].getCacheKey(e));return Td(t)}set needsUpdate(e){!0===e&&this.dispose()}get needsUpdate(){return this.source!==this._source}_exec(){return null===this.codeNode||(!0===this._needsOutputUpdate&&(this._value=this.call("main"),this._needsOutputUpdate=!1),this._output.value=this._value),this}_refresh(){this.needsUpdate=!0,this._exec(),this._output.refresh()}}const BR=Ap(ER);class IR extends Ld{static get type(){return"FogNode"}constructor(e,t){super("float"),this.isFogNode=!0,this.colorNode=e,this.factorNode=t}getViewZNode(e){let t;const s=e.context.getViewZ;return void 0!==s&&(t=s(this)),(t||cx.z).negate()}setup(){return this.factorNode}}const PR=Ap(IR);class FR extends IR{static get type(){return"FogRangeNode"}constructor(e,t,s){super(e),this.isFogRangeNode=!0,this.nearNode=t,this.farNode=s}setup(e){const t=this.getViewZNode(e);return Mf(this.nearNode,this.farNode,t)}}const zR=Ap(FR);class UR extends IR{static get type(){return"FogExp2Node"}constructor(e,t){super(e),this.isFogExp2Node=!0,this.densityNode=t}setup(e){const t=this.getViewZNode(e),s=this.densityNode;return s.mul(s,t,t).negate().exp().oneMinus()}}const OR=Ap(UR);let LR=null,VR=null;class DR extends Ld{static get type(){return"RangeNode"}constructor(e=Up(),t=Up()){super(),this.minNode=e,this.maxNode=t}getVectorLength(e){const t=e.getTypeLength(Md(this.minNode.value)),s=e.getTypeLength(Md(this.maxNode.value));return t>s?t:s}getNodeType(e){return e.object.count>1?e.getTypeFromLength(this.getVectorLength(e)):"float"}setup(e){const t=e.object;let s=null;if(t.count>1){const i=this.minNode.value,r=this.maxNode.value,n=e.getTypeLength(Md(i)),o=e.getTypeLength(Md(r));LR=LR||new Ti,VR=VR||new Ti,LR.setScalar(0),VR.setScalar(0),1===n?LR.setScalar(i):i.isColor?LR.set(i.r,i.g,i.b):LR.set(i.x,i.y,i.z||0,i.w||0),1===o?VR.setScalar(r):r.isColor?VR.set(r.r,r.g,r.b):VR.set(r.x,r.y,r.z||0,r.w||0);const a=4,h=a*t.count,u=new Float32Array(h);for(let e=0;eBy(e,t.xy).compare(t.z))),WR=Rp((({depthTexture:e,shadowCoord:t,shadow:s})=>{const i=(t,s)=>By(e,t).compare(s),r=kx("mapSize","vec2",s).setGroup(lm),n=kx("radius","float",s).setGroup(lm),o=Dp(1).div(r),a=o.x.negate().mul(n),h=o.y.negate().mul(n),u=o.x.mul(n),l=o.y.mul(n),c=a.div(2),d=h.div(2),p=u.div(2),m=l.div(2);return Zm(i(t.xy.add(Dp(a,h)),t.z),i(t.xy.add(Dp(0,h)),t.z),i(t.xy.add(Dp(u,h)),t.z),i(t.xy.add(Dp(c,d)),t.z),i(t.xy.add(Dp(0,d)),t.z),i(t.xy.add(Dp(p,d)),t.z),i(t.xy.add(Dp(a,0)),t.z),i(t.xy.add(Dp(c,0)),t.z),i(t.xy,t.z),i(t.xy.add(Dp(p,0)),t.z),i(t.xy.add(Dp(u,0)),t.z),i(t.xy.add(Dp(c,m)),t.z),i(t.xy.add(Dp(0,m)),t.z),i(t.xy.add(Dp(p,m)),t.z),i(t.xy.add(Dp(a,l)),t.z),i(t.xy.add(Dp(0,l)),t.z),i(t.xy.add(Dp(u,l)),t.z)).mul(1/17)})),jR=Rp((({depthTexture:e,shadowCoord:t,shadow:s})=>{const i=(t,s)=>By(e,t).compare(s),r=kx("mapSize","vec2",s).setGroup(lm),n=Dp(1).div(r),o=n.x,a=n.y,h=t.xy,u=Og(h.mul(r).add(.5));return h.subAssign(u.mul(n)),Zm(i(h,t.z),i(h.add(Dp(o,0)),t.z),i(h.add(Dp(0,a)),t.z),i(h.add(n),t.z),Tf(i(h.add(Dp(o.negate(),0)),t.z),i(h.add(Dp(o.mul(2),0)),t.z),u.x),Tf(i(h.add(Dp(o.negate(),a)),t.z),i(h.add(Dp(o.mul(2),a)),t.z),u.x),Tf(i(h.add(Dp(0,a.negate())),t.z),i(h.add(Dp(0,a.mul(2))),t.z),u.y),Tf(i(h.add(Dp(o,a.negate())),t.z),i(h.add(Dp(o,a.mul(2))),t.z),u.y),Tf(Tf(i(h.add(Dp(o.negate(),a.negate())),t.z),i(h.add(Dp(o.mul(2),a.negate())),t.z),u.x),Tf(i(h.add(Dp(o.negate(),a.mul(2))),t.z),i(h.add(Dp(o.mul(2),a.mul(2))),t.z),u.x),u.y)).mul(1/9)})),HR=Rp((({depthTexture:e,shadowCoord:t})=>{const s=Up(1).toVar(),i=By(e).uv(t.xy).rg,r=hf(t.z,i.x);return Pp(r.notEqual(Up(1)),(()=>{const e=t.z.sub(i.x),n=of(0,i.y.mul(i.y));let o=n.div(n.add(e.mul(e)));o=_f(Jm(o,.3).div(.95-.3)),s.assign(_f(of(r,o)))})),s})),qR=Rp((({samples:e,radius:t,size:s,shadowPass:i})=>{const r=Up(0).toVar(),n=Up(0).toVar(),o=e.lessThanEqual(Up(1)).select(Up(0),Up(2).div(e.sub(1))),a=e.lessThanEqual(Up(1)).select(Up(0),Up(-1));bv({start:Op(0),end:Op(e),type:"int",condition:"<"},(({i:e})=>{const h=a.add(Up(e).mul(o)),u=i.uv(Zm(Gv.xy,Dp(0,h).mul(t)).div(s)).x;r.addAssign(u),n.addAssign(u.mul(u))})),r.divAssign(e),n.divAssign(e);const h=Ig(n.sub(r.mul(r)));return Dp(r,h)})),$R=Rp((({samples:e,radius:t,size:s,shadowPass:i})=>{const r=Up(0).toVar(),n=Up(0).toVar(),o=e.lessThanEqual(Up(1)).select(Up(0),Up(2).div(e.sub(1))),a=e.lessThanEqual(Up(1)).select(Up(0),Up(-1));bv({start:Op(0),end:Op(e),type:"int",condition:"<"},(({i:e})=>{const h=a.add(Up(e).mul(o)),u=i.uv(Zm(Gv.xy,Dp(h,0).mul(t)).div(s));r.addAssign(u.x),n.addAssign(Zm(u.y.mul(u.y),u.x.mul(u.x)))})),r.divAssign(e),n.divAssign(e);const h=Ig(n.sub(r.mul(r)));return Dp(r,h)})),XR=[GR,WR,jR,HR];let YR=null;const ZR=new dN;class JR extends Iv{static get type(){return"AnalyticLightNode"}constructor(e=null){super(),this.updateType=Bd.FRAME,this.light=e,this.color=new Jr,this.colorNode=pm(this.color).setGroup(lm),this.baseColorNode=null,this.shadowMap=null,this.shadowNode=null,this.shadowColorNode=null,this.vsmShadowMapVertical=null,this.vsmShadowMapHorizontal=null,this.vsmMaterialVertical=null,this.vsmMaterialHorizontal=null,this.isAnalyticLightNode=!0}getCacheKey(){return _d(super.getCacheKey(),this.light.id,this.light.castShadow?1:0)}getHash(){return this.light.uuid}setupShadow(e){const{object:t,renderer:s}=e;if(!1===s.shadowMap.enabled)return;let i=this.shadowColorNode;if(null===i){null===YR&&(YR=new pT,YR.fragmentNode=Xp(0,0,0,1),YR.isShadowNodeMaterial=!0,YR.name="ShadowMaterial");const r=s.shadowMap.type,n=this.light.shadow,o=new Ya;o.compareFunction=Ts;const a=e.createRenderTarget(n.mapSize.width,n.mapSize.height);if(a.depthTexture=o,n.camera.updateProjectionMatrix(),3===r){o.compareFunction=null,this.vsmShadowMapVertical=e.createRenderTarget(n.mapSize.width,n.mapSize.height,{format:$e,type:Pe}),this.vsmShadowMapHorizontal=e.createRenderTarget(n.mapSize.width,n.mapSize.height,{format:$e,type:Pe});const t=By(o),s=By(this.vsmShadowMapVertical.texture),i=kx("blurSamples","float",n).setGroup(lm),r=kx("radius","float",n).setGroup(lm),a=kx("mapSize","vec2",n).setGroup(lm);let h=this.vsmMaterialVertical||(this.vsmMaterialVertical=new pT);h.fragmentNode=qR({samples:i,radius:r,size:a,shadowPass:t}).context(e.getSharedContext()),h.name="VSMVertical",h=this.vsmMaterialHorizontal||(this.vsmMaterialHorizontal=new pT),h.fragmentNode=$R({samples:i,radius:r,size:a,shadowPass:s}).context(e.getSharedContext()),h.name="VSMHorizontal"}const h=kx("intensity","float",n).setGroup(lm),u=kx("bias","float",n).setGroup(lm),l=kx("normalBias","float",n).setGroup(lm),c=t.material.shadowPositionNode||ux;let d=pm(n.matrix).setGroup(lm).mul(c.add(vx.mul(l)));d=d.xyz.div(d.w);let p=d.z.add(u);s.coordinateSystem===Ds&&(p=p.mul(2).sub(1)),d=jp(d.x,d.y.oneMinus(),p);const m=d.x.greaterThanEqual(0).and(d.x.lessThanEqual(1)).and(d.y.greaterThanEqual(0)).and(d.y.lessThanEqual(1)).and(d.z.lessThanEqual(1)),g=n.filterNode||XR[s.shadowMap.type]||null;if(null===g)throw new Error("THREE.WebGPURenderer: Shadow map type not supported yet.");const f=By(a.texture,d),y=m.select(g({depthTexture:3===r?this.vsmShadowMapHorizontal.texture:o,shadowCoord:d,shadow:n}),Up(1));this.shadowMap=a,this.light.shadow.map=a,this.shadowNode=y,this.shadowColorNode=i=this.colorNode.mul(Tf(1,y.rgb.mix(f,1),h.mul(f.a))),this.baseColorNode=this.colorNode}this.colorNode=i,this.updateBeforeType=Bd.RENDER}setup(e){this.colorNode=this.baseColorNode||this.colorNode,this.light.castShadow?e.object.receiveShadow&&this.setupShadow(e):null!==this.shadowNode&&this.disposeShadow()}updateShadow(e){const{shadowMap:t,light:s}=this,{renderer:i,scene:r,camera:n}=e,o=i.shadowMap.type,a=t.depthTexture.version;this._depthVersionCached=a;const h=r.overrideMaterial;r.overrideMaterial=YR,t.setSize(s.shadow.mapSize.width,s.shadow.mapSize.height),s.shadow.updateMatrices(s),s.shadow.camera.layers.mask=n.layers.mask;const u=i.getRenderTarget(),l=i.getRenderObjectFunction();i.setRenderObjectFunction(((e,...t)=>{(!0===e.castShadow||e.receiveShadow&&3===o)&&i.renderObject(e,...t)})),i.setRenderTarget(t),i.render(r,s.shadow.camera),i.setRenderObjectFunction(l),!0!==s.isPointLight&&3===o&&this.vsmPass(e,s),i.setRenderTarget(u),r.overrideMaterial=h}vsmPass(e,t){const{renderer:s}=e;this.vsmShadowMapVertical.setSize(t.shadow.mapSize.width,t.shadow.mapSize.height),this.vsmShadowMapHorizontal.setSize(t.shadow.mapSize.width,t.shadow.mapSize.height),s.setRenderTarget(this.vsmShadowMapVertical),ZR.material=this.vsmMaterialVertical,ZR.render(s),s.setRenderTarget(this.vsmShadowMapHorizontal),ZR.material=this.vsmMaterialHorizontal,ZR.render(s)}disposeShadow(){this.shadowMap.dispose(),this.shadowMap=null,null!==this.vsmShadowMapVertical&&(this.vsmShadowMapVertical.dispose(),this.vsmShadowMapVertical=null,this.vsmMaterialVertical.dispose(),this.vsmMaterialVertical=null),null!==this.vsmShadowMapHorizontal&&(this.vsmShadowMapHorizontal.dispose(),this.vsmShadowMapHorizontal=null,this.vsmMaterialHorizontal.dispose(),this.vsmMaterialHorizontal=null),this.shadowNode=null,this.shadowColorNode=null,this.baseColorNode=null,this.updateBeforeType=Bd.NONE}updateBefore(e){const t=this.light.shadow;(t.needsUpdate||t.autoUpdate)&&(this.updateShadow(e),this.shadowMap.depthTexture.version===this._depthVersionCached&&(t.needsUpdate=!1))}update(){const{light:e}=this;this.color.copy(e.color).multiplyScalar(e.intensity)}}const KR=Rp((e=>{const{lightDistance:t,cutoffDistance:s,decayExponent:i}=e,r=t.pow(i).max(.01).reciprocal();return s.greaterThan(0).select(r.mul(t.div(s).pow4().oneMinus().clamp().pow2()),r)}));let QR;function eE(e){QR=QR||new WeakMap;let t=QR.get(e);return void 0===t&&QR.set(e,t={}),t}function tE(e){const t=eE(e);return t.position||(t.position=pm(new Ri).setGroup(lm).onRenderUpdate(((t,s)=>s.value.setFromMatrixPosition(e.matrixWorld))))}function sE(e){const t=eE(e);return t.targetPosition||(t.targetPosition=pm(new Ri).setGroup(lm).onRenderUpdate(((t,s)=>s.value.setFromMatrixPosition(e.target.matrixWorld))))}function iE(e){const t=eE(e);return t.viewPosition||(t.viewPosition=pm(new Ri).setGroup(lm).onRenderUpdate((({camera:t},s)=>{s.value=s.value||new Ri,s.value.setFromMatrixPosition(e.matrixWorld),s.value.applyMatrix4(t.matrixWorldInverse)})))}const rE=e=>Vy.transformDirection(tE(e).sub(sE(e))),nE=Rp((([e])=>{const t=e.toUint().mul(747796405).add(2891336453),s=t.shiftRight(t.shiftRight(28).add(4)).bitXor(t).mul(277803737);return s.shiftRight(22).bitXor(s).toFloat().mul(1/2**32)})),oE=(e,t)=>mf(Km(4,e.mul(Jm(1,e))),t),aE=(e,t)=>e.lessThan(.5)?oE(e.mul(2),t).div(2):Jm(1,oE(Km(Jm(1,e),2),t).div(2)),hE=(e,t,s)=>mf(Qm(mf(e,t),Zm(mf(e,t),mf(Jm(1,e),s))),1/t),uE=(e,t)=>Lg(Tg.mul(t.mul(e).sub(1))).div(Tg.mul(t.mul(e).sub(1))),lE=Rp((([e])=>e.fract().sub(.5).abs())).setLayout({name:"tri",type:"float",inputs:[{name:"x",type:"float"}]}),cE=Rp((([e])=>jp(lE(e.z.add(lE(e.y.mul(1)))),lE(e.z.add(lE(e.x.mul(1)))),lE(e.y.add(lE(e.x.mul(1))))))).setLayout({name:"tri3",type:"vec3",inputs:[{name:"p",type:"vec3"}]}),dE=Rp((([e,t,s])=>{const i=jp(e).toVar(),r=Up(1.4).toVar(),n=Up(0).toVar(),o=jp(i).toVar();return bv({start:Up(0),end:Up(3),type:"float",condition:"<="},(()=>{const e=jp(cE(o.mul(2))).toVar();i.addAssign(e.add(s.mul(Up(.1).mul(t)))),o.mulAssign(1.8),r.mulAssign(1.5),i.mulAssign(1.2);const a=Up(lE(i.z.add(lE(i.x.add(lE(i.y)))))).toVar();n.addAssign(a.div(r)),o.addAssign(.14)})),n})).setLayout({name:"triNoise3D",type:"float",inputs:[{name:"p",type:"vec3"},{name:"spd",type:"float"},{name:"time",type:"float"}]}),pE=Rp((([e,t,s=Dp(.5)])=>Ew(e.sub(s),t).add(s))),mE=Rp((([e,t,s=Dp(.5)])=>{const i=e.sub(s),r=i.dot(i),n=r.mul(r).mul(t);return e.add(i.mul(n))})),gE=Rp((({position:e=null,horizontal:t=!0,vertical:s=!1})=>{let i;null!==e?(i=Jy.toVar(),i[3][0]=e.x,i[3][1]=e.y,i[3][2]=e.z):i=Jy;const r=Vy.mul(i);return Tp(t)&&(r[0][0]=Jy[0].length(),r[0][1]=0,r[0][2]=0),Tp(s)&&(r[1][0]=0,r[1][1]=Jy[1].length(),r[1][2]=0),r[2][0]=0,r[2][1]=0,r[2][2]=1,Oy.mul(r).mul(ax)})),fE=Rp((([e=null])=>{const t=lT();return lT(sT(e)).sub(t).lessThan(0).select(Dv,e)})),yE=new WeakMap;class xE extends kd{static get type(){return"VelocityNode"}constructor(){super("vec2"),this.updateType=Bd.OBJECT,this.updateAfterType=Bd.OBJECT,this.previousModelWorldMatrix=pm(new nr),this.previousProjectionMatrix=pm(new nr).setGroup(lm),this.previousCameraViewMatrix=pm(new nr)}update({frameId:e,camera:t,object:s}){const i=vE(s);this.previousModelWorldMatrix.value.copy(i);const r=bE(t);r.frameId!==e&&(r.frameId=e,void 0===r.previousProjectionMatrix?(r.previousProjectionMatrix=new nr,r.previousCameraViewMatrix=new nr,r.currentProjectionMatrix=new nr,r.currentCameraViewMatrix=new nr,r.previousProjectionMatrix.copy(t.projectionMatrix),r.previousCameraViewMatrix.copy(t.matrixWorldInverse)):(r.previousProjectionMatrix.copy(r.currentProjectionMatrix),r.previousCameraViewMatrix.copy(r.currentCameraViewMatrix)),r.currentProjectionMatrix.copy(t.projectionMatrix),r.currentCameraViewMatrix.copy(t.matrixWorldInverse),this.previousProjectionMatrix.value.copy(r.previousProjectionMatrix),this.previousCameraViewMatrix.value.copy(r.previousCameraViewMatrix))}updateAfter({object:e}){vE(e).copy(e.matrixWorld)}setup(){const e=this.previousCameraViewMatrix.mul(this.previousModelWorldMatrix),t=Oy.mul(ix).mul(ax),s=this.previousProjectionMatrix.mul(e).mul(hx),i=t.xy.div(t.w),r=s.xy.div(s.w);return Jm(i,r)}}function bE(e){let t=yE.get(e);return void 0===t&&(t={},yE.set(e,t)),t}function vE(e,t=0){const s=bE(e);let i=s[t];return void 0===i&&(s[t]=i=new nr),i}const TE=Cp(xE),_E=Rp((([e,t])=>nf(1,e.oneMinus().div(t)).oneMinus())).setLayout({name:"burnBlend",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),wE=Rp((([e,t])=>nf(e.div(t.oneMinus()),1))).setLayout({name:"dodgeBlend",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),SE=Rp((([e,t])=>e.oneMinus().mul(t.oneMinus()).oneMinus())).setLayout({name:"screenBlend",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),ME=Rp((([e,t])=>Tf(e.mul(2).mul(t),e.oneMinus().mul(2).mul(t.oneMinus()).oneMinus(),hf(.5,e)))).setLayout({name:"overlayBlend",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),NE=Rp((([e,t,s=Op(16)])=>{const i=t=>e.uv(t),r=My(),n=i(r).toVar(),o=Up(s);return bv({start:Op(1),end:s,type:"int",condition:"<="},(({i:e})=>{const s=t.mul(Up(e).div(o.sub(1)).sub(.5));n.addAssign(i(r.add(s)))})),n.divAssign(o),n})),AE=Rp((([e,t=1])=>{const s=e,i=SC(s.rgb),r=jp(i),n=nf(1,of(0,Up(10).mul(i.sub(.45)))),o=r.mul(s.rgb).mul(2),a=Up(2).mul(r.oneMinus()).mul(s.rgb.oneMinus()).oneMinus(),h=Tf(o,a,n),u=s.a.mul(t),l=u.mul(h.rgb);return l.addAssign(s.rgb.mul(u.oneMinus())),Xp(l,s.a)})),CE=Rp((([e])=>{const t=jp(e);return Xp(df(t,jp(.393,.769,.189)),df(t,jp(.349,.686,.168)),df(t,jp(.272,.534,.131)),e.a)})),RE=Rp((([e])=>{const t=e.mul(.9478672986).add(.0521327014).pow(2.4),s=e.mul(.0773993808),i=e.lessThanEqual(.04045);return Tf(t,s,i)})).setLayout({name:"sRGBToLinearSRGB",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),EE=Rp((([e])=>{const t=e.pow(.41666).mul(1.055).sub(.055),s=e.mul(12.92),i=e.lessThanEqual(.0031308);return Tf(t,s,i)})).setLayout({name:"linearSRGBTosRGB",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),BE=Rp((([e,t])=>e.mul(t).clamp())).setLayout({name:"linearToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),IE=Rp((([e,t])=>(e=e.mul(t)).div(e.add(1)).clamp())).setLayout({name:"reinhardToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),PE=Rp((([e,t])=>{const s=(e=(e=e.mul(t)).sub(.004).max(0)).mul(e.mul(6.2).add(.5)),i=e.mul(e.mul(6.2).add(1.7)).add(.06);return s.div(i).pow(2.2)})).setLayout({name:"cineonToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),FE=Rp((([e])=>{const t=e.mul(e.add(.0245786)).sub(90537e-9),s=e.mul(e.add(.432951).mul(.983729)).add(.238081);return t.div(s)})),zE=Rp((([e,t])=>{const s=Qp(.59719,.35458,.04823,.076,.90834,.01566,.0284,.13383,.83777),i=Qp(1.60475,-.53108,-.07367,-.10208,1.10813,-.00605,-.00327,-.07276,1.07602);return e=e.mul(t).div(.6),e=s.mul(e),e=FE(e),(e=i.mul(e)).clamp()})).setLayout({name:"acesFilmicToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),UE=Qp(jp(1.6605,-.1246,-.0182),jp(-.5876,1.1329,-.1006),jp(-.0728,-.0083,1.1187)),OE=Qp(jp(.6274,.0691,.0164),jp(.3293,.9195,.088),jp(.0433,.0113,.8956)),LE=Rp((([e])=>{const t=jp(e).toVar(),s=jp(t.mul(t)).toVar(),i=jp(s.mul(s)).toVar();return Up(15.5).mul(i.mul(s)).sub(Km(40.14,i.mul(t))).add(Km(31.96,i).sub(Km(6.868,s.mul(t))).add(Km(.4298,s).add(Km(.1191,t).sub(.00232))))})),VE=Rp((([e,t])=>{const s=jp(e).toVar(),i=Qp(jp(.856627153315983,.137318972929847,.11189821299995),jp(.0951212405381588,.761241990602591,.0767994186031903),jp(.0482516061458583,.101439036467562,.811302368396859)),r=Qp(jp(1.1271005818144368,-.1413297634984383,-.14132976349843826),jp(-.11060664309660323,1.157823702216272,-.11060664309660294),jp(-.016493938717834573,-.016493938717834257,1.2519364065950405)),n=Up(-12.47393),o=Up(4.026069);return s.mulAssign(t),s.assign(OE.mul(s)),s.assign(i.mul(s)),s.assign(of(s,1e-10)),s.assign(Bg(s)),s.assign(s.sub(n).div(o.sub(n))),s.assign(_f(s,0,1)),s.assign(LE(s)),s.assign(r.mul(s)),s.assign(mf(of(jp(0),s),jp(2.2))),s.assign(UE.mul(s)),s.assign(_f(s,0,1)),s})).setLayout({name:"agxToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),DE=Rp((([e,t])=>{const s=Up(.76),i=Up(.15);e=e.mul(t);const r=nf(e.r,nf(e.g,e.b)),n=Bf(r.lessThan(.08),r.sub(Km(6.25,r.mul(r))),.04);e.subAssign(n);const o=of(e.r,of(e.g,e.b));Pp(o.lessThan(s),(()=>e));const a=Jm(1,s),h=Jm(1,a.mul(a).div(o.add(a.sub(s))));e.mulAssign(h.div(o));const u=Jm(1,Qm(1,i.mul(o.sub(h)).add(1)));return Tf(e,jp(h),u)})).setLayout({name:"neutralToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]});class kE extends Ld{static get type(){return"ComputeBuiltinNode"}constructor(e,t){super(t),this._builtinName=e}getHash(e){return this.getBuiltinName(e)}getNodeType(){return this.nodeType}setBuiltinName(e){return this._builtinName=e,this}getBuiltinName(){return this._builtinName}hasBuiltin(e){e.hasBuiltin(this._builtinName)}generate(e,t){const s=this.getBuiltinName(e),i=this.getNodeType(e);return"compute"===e.shaderStage?e.format(s,i,t):(console.warn(`ComputeBuiltinNode: Compute built-in value ${s} can not be accessed in the ${e.shaderStage} stage`),e.generateConst(i))}serialize(e){super.serialize(e),e.global=this.global,e._builtinName=this._builtinName}deserialize(e){super.deserialize(e),this.global=e.global,this._builtinName=e._builtinName}}const GE=(e,t)=>Sp(new kE(e,t)),WE=GE("numWorkgroups","uvec3"),jE=GE("workgroupId","uvec3"),HE=GE("localId","uvec3"),qE=GE("subgroupSize","uint");const $E=Ap(class extends Ld{constructor(e){super(),this.scope=e}generate(e){const{scope:t}=this,{renderer:s}=e;!0===s.backend.isWebGLBackend?e.addFlowCode(`\t// ${t}Barrier \n`):e.addLineFlowCode(`${t}Barrier()`,this)}}),XE=()=>$E("workgroup").append(),YE=()=>$E("storage").append(),ZE=()=>$E("texture").append();class JE extends Vd{constructor(e,t){super(e,t),this.isWorkgroupInfoElementNode=!0}generate(e,t){let s;const i=e.context.assign;if(s=super.generate(e),!0!==i){const i=this.getNodeType(e);s=e.format(s,i,t)}return s}}class KE extends Ld{constructor(e,t,s=0){super(t),this.bufferType=t,this.bufferCount=s,this.isWorkgroupInfoNode=!0,this.scope=e}label(e){return this.name=e,this}getHash(){return this.uuid}setScope(e){return this.scope=e,this}getInputType(){return`${this.scope}Array`}element(e){return Sp(new JE(this,e))}generate(e){return e.getScopedArray(this.name||`${this.scope}Array_${this.id}`,this.scope.toLowerCase(),this.bufferType,this.bufferCount)}}const QE=(e,t)=>Sp(new KE("Workgroup",e,t));class eB extends kd{static get type(){return"AtomicFunctionNode"}constructor(e,t,s,i=null){super("uint"),this.method=e,this.pointerNode=t,this.valueNode=s,this.storeNode=i}getInputType(e){return this.pointerNode.getNodeType(e)}getNodeType(e){return this.getInputType(e)}generate(e){const t=this.method,s=this.getNodeType(e),i=this.getInputType(e),r=this.pointerNode,n=this.valueNode,o=[];o.push(`&${r.build(e,i)}`),o.push(n.build(e,i));const a=`${e.getMethod(t,s)}( ${o.join(", ")} )`;if(null!==this.storeNode){const t=this.storeNode.build(e,i);e.addLineFlowCode(`${t} = ${a}`,this)}else e.addLineFlowCode(a,this)}}eB.ATOMIC_LOAD="atomicLoad",eB.ATOMIC_STORE="atomicStore",eB.ATOMIC_ADD="atomicAdd",eB.ATOMIC_SUB="atomicSub",eB.ATOMIC_MAX="atomicMax",eB.ATOMIC_MIN="atomicMin",eB.ATOMIC_AND="atomicAnd",eB.ATOMIC_OR="atomicOr",eB.ATOMIC_XOR="atomicXor";const tB=Ap(eB),sB=(e,t,s,i)=>{const r=tB(e,t,s,i);return r.append(),r},iB=(e,t,s=null)=>sB(eB.ATOMIC_STORE,e,t,s),rB=(e,t,s=null)=>sB(eB.ATOMIC_ADD,e,t,s),nB=(e,t,s=null)=>sB(eB.ATOMIC_SUB,e,t,s),oB=(e,t,s=null)=>sB(eB.ATOMIC_MAX,e,t,s),aB=(e,t,s=null)=>sB(eB.ATOMIC_MIN,e,t,s),hB=(e,t,s=null)=>sB(eB.ATOMIC_AND,e,t,s),uB=(e,t,s=null)=>sB(eB.ATOMIC_OR,e,t,s),lB=(e,t,s=null)=>sB(eB.ATOMIC_XOR,e,t,s),cB=Rp((([e=t()])=>{const t=e.mul(2),s=t.x.floor(),i=t.y.floor();return s.add(i).mod(2).sign()})),dB=Rp((([e,t,s])=>{const i=Up(s).toVar(),r=Up(t).toVar(),n=Vp(e).toVar();return Bf(n,r,i)})).setLayout({name:"mx_select",type:"float",inputs:[{name:"b",type:"bool"},{name:"t",type:"float"},{name:"f",type:"float"}]}),pB=Rp((([e,t])=>{const s=Vp(t).toVar(),i=Up(e).toVar();return Bf(s,i.negate(),i)})).setLayout({name:"mx_negate_if",type:"float",inputs:[{name:"val",type:"float"},{name:"b",type:"bool"}]}),mB=Rp((([e])=>{const t=Up(e).toVar();return Op(Fg(t))})).setLayout({name:"mx_floor",type:"int",inputs:[{name:"x",type:"float"}]}),gB=Rp((([e,t])=>{const s=Up(e).toVar();return t.assign(mB(s)),s.sub(Up(t))})),fB=RM([Rp((([e,t,s,i,r,n])=>{const o=Up(n).toVar(),a=Up(r).toVar(),h=Up(i).toVar(),u=Up(s).toVar(),l=Up(t).toVar(),c=Up(e).toVar(),d=Up(Jm(1,a)).toVar();return Jm(1,o).mul(c.mul(d).add(l.mul(a))).add(o.mul(u.mul(d).add(h.mul(a))))})).setLayout({name:"mx_bilerp_0",type:"float",inputs:[{name:"v0",type:"float"},{name:"v1",type:"float"},{name:"v2",type:"float"},{name:"v3",type:"float"},{name:"s",type:"float"},{name:"t",type:"float"}]}),Rp((([e,t,s,i,r,n])=>{const o=Up(n).toVar(),a=Up(r).toVar(),h=jp(i).toVar(),u=jp(s).toVar(),l=jp(t).toVar(),c=jp(e).toVar(),d=Up(Jm(1,a)).toVar();return Jm(1,o).mul(c.mul(d).add(l.mul(a))).add(o.mul(u.mul(d).add(h.mul(a))))})).setLayout({name:"mx_bilerp_1",type:"vec3",inputs:[{name:"v0",type:"vec3"},{name:"v1",type:"vec3"},{name:"v2",type:"vec3"},{name:"v3",type:"vec3"},{name:"s",type:"float"},{name:"t",type:"float"}]})]),yB=RM([Rp((([e,t,s,i,r,n,o,a,h,u,l])=>{const c=Up(l).toVar(),d=Up(u).toVar(),p=Up(h).toVar(),m=Up(a).toVar(),g=Up(o).toVar(),f=Up(n).toVar(),y=Up(r).toVar(),x=Up(i).toVar(),b=Up(s).toVar(),v=Up(t).toVar(),T=Up(e).toVar(),_=Up(Jm(1,p)).toVar(),w=Up(Jm(1,d)).toVar();return Up(Jm(1,c)).toVar().mul(w.mul(T.mul(_).add(v.mul(p))).add(d.mul(b.mul(_).add(x.mul(p))))).add(c.mul(w.mul(y.mul(_).add(f.mul(p))).add(d.mul(g.mul(_).add(m.mul(p))))))})).setLayout({name:"mx_trilerp_0",type:"float",inputs:[{name:"v0",type:"float"},{name:"v1",type:"float"},{name:"v2",type:"float"},{name:"v3",type:"float"},{name:"v4",type:"float"},{name:"v5",type:"float"},{name:"v6",type:"float"},{name:"v7",type:"float"},{name:"s",type:"float"},{name:"t",type:"float"},{name:"r",type:"float"}]}),Rp((([e,t,s,i,r,n,o,a,h,u,l])=>{const c=Up(l).toVar(),d=Up(u).toVar(),p=Up(h).toVar(),m=jp(a).toVar(),g=jp(o).toVar(),f=jp(n).toVar(),y=jp(r).toVar(),x=jp(i).toVar(),b=jp(s).toVar(),v=jp(t).toVar(),T=jp(e).toVar(),_=Up(Jm(1,p)).toVar(),w=Up(Jm(1,d)).toVar();return Up(Jm(1,c)).toVar().mul(w.mul(T.mul(_).add(v.mul(p))).add(d.mul(b.mul(_).add(x.mul(p))))).add(c.mul(w.mul(y.mul(_).add(f.mul(p))).add(d.mul(g.mul(_).add(m.mul(p))))))})).setLayout({name:"mx_trilerp_1",type:"vec3",inputs:[{name:"v0",type:"vec3"},{name:"v1",type:"vec3"},{name:"v2",type:"vec3"},{name:"v3",type:"vec3"},{name:"v4",type:"vec3"},{name:"v5",type:"vec3"},{name:"v6",type:"vec3"},{name:"v7",type:"vec3"},{name:"s",type:"float"},{name:"t",type:"float"},{name:"r",type:"float"}]})]),xB=Rp((([e,t,s])=>{const i=Up(s).toVar(),r=Up(t).toVar(),n=Lp(e).toVar(),o=Lp(n.bitAnd(Lp(7))).toVar(),a=Up(dB(o.lessThan(Lp(4)),r,i)).toVar(),h=Up(Km(2,dB(o.lessThan(Lp(4)),i,r))).toVar();return pB(a,Vp(o.bitAnd(Lp(1)))).add(pB(h,Vp(o.bitAnd(Lp(2)))))})).setLayout({name:"mx_gradient_float_0",type:"float",inputs:[{name:"hash",type:"uint"},{name:"x",type:"float"},{name:"y",type:"float"}]}),bB=Rp((([e,t,s,i])=>{const r=Up(i).toVar(),n=Up(s).toVar(),o=Up(t).toVar(),a=Lp(e).toVar(),h=Lp(a.bitAnd(Lp(15))).toVar(),u=Up(dB(h.lessThan(Lp(8)),o,n)).toVar(),l=Up(dB(h.lessThan(Lp(4)),n,dB(h.equal(Lp(12)).or(h.equal(Lp(14))),o,r))).toVar();return pB(u,Vp(h.bitAnd(Lp(1)))).add(pB(l,Vp(h.bitAnd(Lp(2)))))})).setLayout({name:"mx_gradient_float_1",type:"float",inputs:[{name:"hash",type:"uint"},{name:"x",type:"float"},{name:"y",type:"float"},{name:"z",type:"float"}]}),vB=RM([xB,bB]),TB=Rp((([e,t,s])=>{const i=Up(s).toVar(),r=Up(t).toVar(),n=qp(e).toVar();return jp(vB(n.x,r,i),vB(n.y,r,i),vB(n.z,r,i))})).setLayout({name:"mx_gradient_vec3_0",type:"vec3",inputs:[{name:"hash",type:"uvec3"},{name:"x",type:"float"},{name:"y",type:"float"}]}),_B=Rp((([e,t,s,i])=>{const r=Up(i).toVar(),n=Up(s).toVar(),o=Up(t).toVar(),a=qp(e).toVar();return jp(vB(a.x,o,n,r),vB(a.y,o,n,r),vB(a.z,o,n,r))})).setLayout({name:"mx_gradient_vec3_1",type:"vec3",inputs:[{name:"hash",type:"uvec3"},{name:"x",type:"float"},{name:"y",type:"float"},{name:"z",type:"float"}]}),wB=RM([TB,_B]),SB=Rp((([e])=>{const t=Up(e).toVar();return Km(.6616,t)})).setLayout({name:"mx_gradient_scale2d_0",type:"float",inputs:[{name:"v",type:"float"}]}),MB=Rp((([e])=>{const t=Up(e).toVar();return Km(.982,t)})).setLayout({name:"mx_gradient_scale3d_0",type:"float",inputs:[{name:"v",type:"float"}]}),NB=RM([SB,Rp((([e])=>{const t=jp(e).toVar();return Km(.6616,t)})).setLayout({name:"mx_gradient_scale2d_1",type:"vec3",inputs:[{name:"v",type:"vec3"}]})]),AB=RM([MB,Rp((([e])=>{const t=jp(e).toVar();return Km(.982,t)})).setLayout({name:"mx_gradient_scale3d_1",type:"vec3",inputs:[{name:"v",type:"vec3"}]})]),CB=Rp((([e,t])=>{const s=Op(t).toVar(),i=Lp(e).toVar();return i.shiftLeft(s).bitOr(i.shiftRight(Op(32).sub(s)))})).setLayout({name:"mx_rotl32",type:"uint",inputs:[{name:"x",type:"uint"},{name:"k",type:"int"}]}),RB=Rp((([e,t,s])=>{e.subAssign(s),e.bitXorAssign(CB(s,Op(4))),s.addAssign(t),t.subAssign(e),t.bitXorAssign(CB(e,Op(6))),e.addAssign(s),s.subAssign(t),s.bitXorAssign(CB(t,Op(8))),t.addAssign(e),e.subAssign(s),e.bitXorAssign(CB(s,Op(16))),s.addAssign(t),t.subAssign(e),t.bitXorAssign(CB(e,Op(19))),e.addAssign(s),s.subAssign(t),s.bitXorAssign(CB(t,Op(4))),t.addAssign(e)})),EB=Rp((([e,t,s])=>{const i=Lp(s).toVar(),r=Lp(t).toVar(),n=Lp(e).toVar();return i.bitXorAssign(r),i.subAssign(CB(r,Op(14))),n.bitXorAssign(i),n.subAssign(CB(i,Op(11))),r.bitXorAssign(n),r.subAssign(CB(n,Op(25))),i.bitXorAssign(r),i.subAssign(CB(r,Op(16))),n.bitXorAssign(i),n.subAssign(CB(i,Op(4))),r.bitXorAssign(n),r.subAssign(CB(n,Op(14))),i.bitXorAssign(r),i.subAssign(CB(r,Op(24))),i})).setLayout({name:"mx_bjfinal",type:"uint",inputs:[{name:"a",type:"uint"},{name:"b",type:"uint"},{name:"c",type:"uint"}]}),BB=Rp((([e])=>{const t=Lp(e).toVar();return Up(t).div(Up(Lp(Op(4294967295))))})).setLayout({name:"mx_bits_to_01",type:"float",inputs:[{name:"bits",type:"uint"}]}),IB=Rp((([e])=>{const t=Up(e).toVar();return t.mul(t).mul(t).mul(t.mul(t.mul(6).sub(15)).add(10))})).setLayout({name:"mx_fade",type:"float",inputs:[{name:"t",type:"float"}]}),PB=RM([Rp((([e])=>{const t=Op(e).toVar(),s=Lp(Lp(1)).toVar(),i=Lp(Lp(Op(3735928559)).add(s.shiftLeft(Lp(2))).add(Lp(13))).toVar();return EB(i.add(Lp(t)),i,i)})).setLayout({name:"mx_hash_int_0",type:"uint",inputs:[{name:"x",type:"int"}]}),Rp((([e,t])=>{const s=Op(t).toVar(),i=Op(e).toVar(),r=Lp(Lp(2)).toVar(),n=Lp().toVar(),o=Lp().toVar(),a=Lp().toVar();return n.assign(o.assign(a.assign(Lp(Op(3735928559)).add(r.shiftLeft(Lp(2))).add(Lp(13))))),n.addAssign(Lp(i)),o.addAssign(Lp(s)),EB(n,o,a)})).setLayout({name:"mx_hash_int_1",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"}]}),Rp((([e,t,s])=>{const i=Op(s).toVar(),r=Op(t).toVar(),n=Op(e).toVar(),o=Lp(Lp(3)).toVar(),a=Lp().toVar(),h=Lp().toVar(),u=Lp().toVar();return a.assign(h.assign(u.assign(Lp(Op(3735928559)).add(o.shiftLeft(Lp(2))).add(Lp(13))))),a.addAssign(Lp(n)),h.addAssign(Lp(r)),u.addAssign(Lp(i)),EB(a,h,u)})).setLayout({name:"mx_hash_int_2",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"}]}),Rp((([e,t,s,i])=>{const r=Op(i).toVar(),n=Op(s).toVar(),o=Op(t).toVar(),a=Op(e).toVar(),h=Lp(Lp(4)).toVar(),u=Lp().toVar(),l=Lp().toVar(),c=Lp().toVar();return u.assign(l.assign(c.assign(Lp(Op(3735928559)).add(h.shiftLeft(Lp(2))).add(Lp(13))))),u.addAssign(Lp(a)),l.addAssign(Lp(o)),c.addAssign(Lp(n)),RB(u,l,c),u.addAssign(Lp(r)),EB(u,l,c)})).setLayout({name:"mx_hash_int_3",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xx",type:"int"}]}),Rp((([e,t,s,i,r])=>{const n=Op(r).toVar(),o=Op(i).toVar(),a=Op(s).toVar(),h=Op(t).toVar(),u=Op(e).toVar(),l=Lp(Lp(5)).toVar(),c=Lp().toVar(),d=Lp().toVar(),p=Lp().toVar();return c.assign(d.assign(p.assign(Lp(Op(3735928559)).add(l.shiftLeft(Lp(2))).add(Lp(13))))),c.addAssign(Lp(u)),d.addAssign(Lp(h)),p.addAssign(Lp(a)),RB(c,d,p),c.addAssign(Lp(o)),d.addAssign(Lp(n)),EB(c,d,p)})).setLayout({name:"mx_hash_int_4",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xx",type:"int"},{name:"yy",type:"int"}]})]),FB=RM([Rp((([e,t])=>{const s=Op(t).toVar(),i=Op(e).toVar(),r=Lp(PB(i,s)).toVar(),n=qp().toVar();return n.x.assign(r.bitAnd(Op(255))),n.y.assign(r.shiftRight(Op(8)).bitAnd(Op(255))),n.z.assign(r.shiftRight(Op(16)).bitAnd(Op(255))),n})).setLayout({name:"mx_hash_vec3_0",type:"uvec3",inputs:[{name:"x",type:"int"},{name:"y",type:"int"}]}),Rp((([e,t,s])=>{const i=Op(s).toVar(),r=Op(t).toVar(),n=Op(e).toVar(),o=Lp(PB(n,r,i)).toVar(),a=qp().toVar();return a.x.assign(o.bitAnd(Op(255))),a.y.assign(o.shiftRight(Op(8)).bitAnd(Op(255))),a.z.assign(o.shiftRight(Op(16)).bitAnd(Op(255))),a})).setLayout({name:"mx_hash_vec3_1",type:"uvec3",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"}]})]),zB=RM([Rp((([e])=>{const t=Dp(e).toVar(),s=Op().toVar(),i=Op().toVar(),r=Up(gB(t.x,s)).toVar(),n=Up(gB(t.y,i)).toVar(),o=Up(IB(r)).toVar(),a=Up(IB(n)).toVar(),h=Up(fB(vB(PB(s,i),r,n),vB(PB(s.add(Op(1)),i),r.sub(1),n),vB(PB(s,i.add(Op(1))),r,n.sub(1)),vB(PB(s.add(Op(1)),i.add(Op(1))),r.sub(1),n.sub(1)),o,a)).toVar();return NB(h)})).setLayout({name:"mx_perlin_noise_float_0",type:"float",inputs:[{name:"p",type:"vec2"}]}),Rp((([e])=>{const t=jp(e).toVar(),s=Op().toVar(),i=Op().toVar(),r=Op().toVar(),n=Up(gB(t.x,s)).toVar(),o=Up(gB(t.y,i)).toVar(),a=Up(gB(t.z,r)).toVar(),h=Up(IB(n)).toVar(),u=Up(IB(o)).toVar(),l=Up(IB(a)).toVar(),c=Up(yB(vB(PB(s,i,r),n,o,a),vB(PB(s.add(Op(1)),i,r),n.sub(1),o,a),vB(PB(s,i.add(Op(1)),r),n,o.sub(1),a),vB(PB(s.add(Op(1)),i.add(Op(1)),r),n.sub(1),o.sub(1),a),vB(PB(s,i,r.add(Op(1))),n,o,a.sub(1)),vB(PB(s.add(Op(1)),i,r.add(Op(1))),n.sub(1),o,a.sub(1)),vB(PB(s,i.add(Op(1)),r.add(Op(1))),n,o.sub(1),a.sub(1)),vB(PB(s.add(Op(1)),i.add(Op(1)),r.add(Op(1))),n.sub(1),o.sub(1),a.sub(1)),h,u,l)).toVar();return AB(c)})).setLayout({name:"mx_perlin_noise_float_1",type:"float",inputs:[{name:"p",type:"vec3"}]})]),UB=RM([Rp((([e])=>{const t=Dp(e).toVar(),s=Op().toVar(),i=Op().toVar(),r=Up(gB(t.x,s)).toVar(),n=Up(gB(t.y,i)).toVar(),o=Up(IB(r)).toVar(),a=Up(IB(n)).toVar(),h=jp(fB(wB(FB(s,i),r,n),wB(FB(s.add(Op(1)),i),r.sub(1),n),wB(FB(s,i.add(Op(1))),r,n.sub(1)),wB(FB(s.add(Op(1)),i.add(Op(1))),r.sub(1),n.sub(1)),o,a)).toVar();return NB(h)})).setLayout({name:"mx_perlin_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"vec2"}]}),Rp((([e])=>{const t=jp(e).toVar(),s=Op().toVar(),i=Op().toVar(),r=Op().toVar(),n=Up(gB(t.x,s)).toVar(),o=Up(gB(t.y,i)).toVar(),a=Up(gB(t.z,r)).toVar(),h=Up(IB(n)).toVar(),u=Up(IB(o)).toVar(),l=Up(IB(a)).toVar(),c=jp(yB(wB(FB(s,i,r),n,o,a),wB(FB(s.add(Op(1)),i,r),n.sub(1),o,a),wB(FB(s,i.add(Op(1)),r),n,o.sub(1),a),wB(FB(s.add(Op(1)),i.add(Op(1)),r),n.sub(1),o.sub(1),a),wB(FB(s,i,r.add(Op(1))),n,o,a.sub(1)),wB(FB(s.add(Op(1)),i,r.add(Op(1))),n.sub(1),o,a.sub(1)),wB(FB(s,i.add(Op(1)),r.add(Op(1))),n,o.sub(1),a.sub(1)),wB(FB(s.add(Op(1)),i.add(Op(1)),r.add(Op(1))),n.sub(1),o.sub(1),a.sub(1)),h,u,l)).toVar();return AB(c)})).setLayout({name:"mx_perlin_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec3"}]})]),OB=RM([Rp((([e])=>{const t=Up(e).toVar(),s=Op(mB(t)).toVar();return BB(PB(s))})).setLayout({name:"mx_cell_noise_float_0",type:"float",inputs:[{name:"p",type:"float"}]}),Rp((([e])=>{const t=Dp(e).toVar(),s=Op(mB(t.x)).toVar(),i=Op(mB(t.y)).toVar();return BB(PB(s,i))})).setLayout({name:"mx_cell_noise_float_1",type:"float",inputs:[{name:"p",type:"vec2"}]}),Rp((([e])=>{const t=jp(e).toVar(),s=Op(mB(t.x)).toVar(),i=Op(mB(t.y)).toVar(),r=Op(mB(t.z)).toVar();return BB(PB(s,i,r))})).setLayout({name:"mx_cell_noise_float_2",type:"float",inputs:[{name:"p",type:"vec3"}]}),Rp((([e])=>{const t=Xp(e).toVar(),s=Op(mB(t.x)).toVar(),i=Op(mB(t.y)).toVar(),r=Op(mB(t.z)).toVar(),n=Op(mB(t.w)).toVar();return BB(PB(s,i,r,n))})).setLayout({name:"mx_cell_noise_float_3",type:"float",inputs:[{name:"p",type:"vec4"}]})]),LB=RM([Rp((([e])=>{const t=Up(e).toVar(),s=Op(mB(t)).toVar();return jp(BB(PB(s,Op(0))),BB(PB(s,Op(1))),BB(PB(s,Op(2))))})).setLayout({name:"mx_cell_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"float"}]}),Rp((([e])=>{const t=Dp(e).toVar(),s=Op(mB(t.x)).toVar(),i=Op(mB(t.y)).toVar();return jp(BB(PB(s,i,Op(0))),BB(PB(s,i,Op(1))),BB(PB(s,i,Op(2))))})).setLayout({name:"mx_cell_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec2"}]}),Rp((([e])=>{const t=jp(e).toVar(),s=Op(mB(t.x)).toVar(),i=Op(mB(t.y)).toVar(),r=Op(mB(t.z)).toVar();return jp(BB(PB(s,i,r,Op(0))),BB(PB(s,i,r,Op(1))),BB(PB(s,i,r,Op(2))))})).setLayout({name:"mx_cell_noise_vec3_2",type:"vec3",inputs:[{name:"p",type:"vec3"}]}),Rp((([e])=>{const t=Xp(e).toVar(),s=Op(mB(t.x)).toVar(),i=Op(mB(t.y)).toVar(),r=Op(mB(t.z)).toVar(),n=Op(mB(t.w)).toVar();return jp(BB(PB(s,i,r,n,Op(0))),BB(PB(s,i,r,n,Op(1))),BB(PB(s,i,r,n,Op(2))))})).setLayout({name:"mx_cell_noise_vec3_3",type:"vec3",inputs:[{name:"p",type:"vec4"}]})]),VB=Rp((([e,t,s,i])=>{const r=Up(i).toVar(),n=Up(s).toVar(),o=Op(t).toVar(),a=jp(e).toVar(),h=Up(0).toVar(),u=Up(1).toVar();return bv(o,(()=>{h.addAssign(u.mul(zB(a))),u.mulAssign(r),a.mulAssign(n)})),h})).setLayout({name:"mx_fractal_noise_float",type:"float",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),DB=Rp((([e,t,s,i])=>{const r=Up(i).toVar(),n=Up(s).toVar(),o=Op(t).toVar(),a=jp(e).toVar(),h=jp(0).toVar(),u=Up(1).toVar();return bv(o,(()=>{h.addAssign(u.mul(UB(a))),u.mulAssign(r),a.mulAssign(n)})),h})).setLayout({name:"mx_fractal_noise_vec3",type:"vec3",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),kB=Rp((([e,t,s,i])=>{const r=Up(i).toVar(),n=Up(s).toVar(),o=Op(t).toVar(),a=jp(e).toVar();return Dp(VB(a,o,n,r),VB(a.add(jp(Op(19),Op(193),Op(17))),o,n,r))})).setLayout({name:"mx_fractal_noise_vec2",type:"vec2",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),GB=Rp((([e,t,s,i])=>{const r=Up(i).toVar(),n=Up(s).toVar(),o=Op(t).toVar(),a=jp(e).toVar(),h=jp(DB(a,o,n,r)).toVar(),u=Up(VB(a.add(jp(Op(19),Op(193),Op(17))),o,n,r)).toVar();return Xp(h,u)})).setLayout({name:"mx_fractal_noise_vec4",type:"vec4",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),WB=Rp((([e,t,s,i,r,n,o])=>{const a=Op(o).toVar(),h=Up(n).toVar(),u=Op(r).toVar(),l=Op(i).toVar(),c=Op(s).toVar(),d=Op(t).toVar(),p=Dp(e).toVar(),m=jp(LB(Dp(d.add(l),c.add(u)))).toVar(),g=Dp(m.x,m.y).toVar();g.subAssign(.5),g.mulAssign(h),g.addAssign(.5);const f=Dp(Dp(Up(d),Up(c)).add(g)).toVar(),y=Dp(f.sub(p)).toVar();return Pp(a.equal(Op(2)),(()=>jg(y.x).add(jg(y.y)))),Pp(a.equal(Op(3)),(()=>of(jg(y.x),jg(y.y)))),df(y,y)})).setLayout({name:"mx_worley_distance_0",type:"float",inputs:[{name:"p",type:"vec2"},{name:"x",type:"int"},{name:"y",type:"int"},{name:"xoff",type:"int"},{name:"yoff",type:"int"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),jB=RM([WB,Rp((([e,t,s,i,r,n,o,a,h])=>{const u=Op(h).toVar(),l=Up(a).toVar(),c=Op(o).toVar(),d=Op(n).toVar(),p=Op(r).toVar(),m=Op(i).toVar(),g=Op(s).toVar(),f=Op(t).toVar(),y=jp(e).toVar(),x=jp(LB(jp(f.add(p),g.add(d),m.add(c)))).toVar();x.subAssign(.5),x.mulAssign(l),x.addAssign(.5);const b=jp(jp(Up(f),Up(g),Up(m)).add(x)).toVar(),v=jp(b.sub(y)).toVar();return Pp(u.equal(Op(2)),(()=>jg(v.x).add(jg(v.y)).add(jg(v.z)))),Pp(u.equal(Op(3)),(()=>of(of(jg(v.x),jg(v.y)),jg(v.z)))),df(v,v)})).setLayout({name:"mx_worley_distance_1",type:"float",inputs:[{name:"p",type:"vec3"},{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xoff",type:"int"},{name:"yoff",type:"int"},{name:"zoff",type:"int"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),HB=Rp((([e,t,s])=>{const i=Op(s).toVar(),r=Up(t).toVar(),n=Dp(e).toVar(),o=Op().toVar(),a=Op().toVar(),h=Dp(gB(n.x,o),gB(n.y,a)).toVar(),u=Up(1e6).toVar();return bv({start:-1,end:Op(1),name:"x",condition:"<="},(({x:e})=>{bv({start:-1,end:Op(1),name:"y",condition:"<="},(({y:t})=>{const s=Up(jB(h,e,t,o,a,r,i)).toVar();u.assign(nf(u,s))}))})),Pp(i.equal(Op(0)),(()=>{u.assign(Ig(u))})),u})).setLayout({name:"mx_worley_noise_float_0",type:"float",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),qB=Rp((([e,t,s])=>{const i=Op(s).toVar(),r=Up(t).toVar(),n=Dp(e).toVar(),o=Op().toVar(),a=Op().toVar(),h=Dp(gB(n.x,o),gB(n.y,a)).toVar(),u=Dp(1e6,1e6).toVar();return bv({start:-1,end:Op(1),name:"x",condition:"<="},(({x:e})=>{bv({start:-1,end:Op(1),name:"y",condition:"<="},(({y:t})=>{const s=Up(jB(h,e,t,o,a,r,i)).toVar();Pp(s.lessThan(u.x),(()=>{u.y.assign(u.x),u.x.assign(s)})).ElseIf(s.lessThan(u.y),(()=>{u.y.assign(s)}))}))})),Pp(i.equal(Op(0)),(()=>{u.assign(Ig(u))})),u})).setLayout({name:"mx_worley_noise_vec2_0",type:"vec2",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),$B=Rp((([e,t,s])=>{const i=Op(s).toVar(),r=Up(t).toVar(),n=Dp(e).toVar(),o=Op().toVar(),a=Op().toVar(),h=Dp(gB(n.x,o),gB(n.y,a)).toVar(),u=jp(1e6,1e6,1e6).toVar();return bv({start:-1,end:Op(1),name:"x",condition:"<="},(({x:e})=>{bv({start:-1,end:Op(1),name:"y",condition:"<="},(({y:t})=>{const s=Up(jB(h,e,t,o,a,r,i)).toVar();Pp(s.lessThan(u.x),(()=>{u.z.assign(u.y),u.y.assign(u.x),u.x.assign(s)})).ElseIf(s.lessThan(u.y),(()=>{u.z.assign(u.y),u.y.assign(s)})).ElseIf(s.lessThan(u.z),(()=>{u.z.assign(s)}))}))})),Pp(i.equal(Op(0)),(()=>{u.assign(Ig(u))})),u})).setLayout({name:"mx_worley_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),XB=RM([HB,Rp((([e,t,s])=>{const i=Op(s).toVar(),r=Up(t).toVar(),n=jp(e).toVar(),o=Op().toVar(),a=Op().toVar(),h=Op().toVar(),u=jp(gB(n.x,o),gB(n.y,a),gB(n.z,h)).toVar(),l=Up(1e6).toVar();return bv({start:-1,end:Op(1),name:"x",condition:"<="},(({x:e})=>{bv({start:-1,end:Op(1),name:"y",condition:"<="},(({y:t})=>{bv({start:-1,end:Op(1),name:"z",condition:"<="},(({z:s})=>{const n=Up(jB(u,e,t,s,o,a,h,r,i)).toVar();l.assign(nf(l,n))}))}))})),Pp(i.equal(Op(0)),(()=>{l.assign(Ig(l))})),l})).setLayout({name:"mx_worley_noise_float_1",type:"float",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),YB=RM([qB,Rp((([e,t,s])=>{const i=Op(s).toVar(),r=Up(t).toVar(),n=jp(e).toVar(),o=Op().toVar(),a=Op().toVar(),h=Op().toVar(),u=jp(gB(n.x,o),gB(n.y,a),gB(n.z,h)).toVar(),l=Dp(1e6,1e6).toVar();return bv({start:-1,end:Op(1),name:"x",condition:"<="},(({x:e})=>{bv({start:-1,end:Op(1),name:"y",condition:"<="},(({y:t})=>{bv({start:-1,end:Op(1),name:"z",condition:"<="},(({z:s})=>{const n=Up(jB(u,e,t,s,o,a,h,r,i)).toVar();Pp(n.lessThan(l.x),(()=>{l.y.assign(l.x),l.x.assign(n)})).ElseIf(n.lessThan(l.y),(()=>{l.y.assign(n)}))}))}))})),Pp(i.equal(Op(0)),(()=>{l.assign(Ig(l))})),l})).setLayout({name:"mx_worley_noise_vec2_1",type:"vec2",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),ZB=RM([$B,Rp((([e,t,s])=>{const i=Op(s).toVar(),r=Up(t).toVar(),n=jp(e).toVar(),o=Op().toVar(),a=Op().toVar(),h=Op().toVar(),u=jp(gB(n.x,o),gB(n.y,a),gB(n.z,h)).toVar(),l=jp(1e6,1e6,1e6).toVar();return bv({start:-1,end:Op(1),name:"x",condition:"<="},(({x:e})=>{bv({start:-1,end:Op(1),name:"y",condition:"<="},(({y:t})=>{bv({start:-1,end:Op(1),name:"z",condition:"<="},(({z:s})=>{const n=Up(jB(u,e,t,s,o,a,h,r,i)).toVar();Pp(n.lessThan(l.x),(()=>{l.z.assign(l.y),l.y.assign(l.x),l.x.assign(n)})).ElseIf(n.lessThan(l.y),(()=>{l.z.assign(l.y),l.y.assign(n)})).ElseIf(n.lessThan(l.z),(()=>{l.z.assign(n)}))}))}))})),Pp(i.equal(Op(0)),(()=>{l.assign(Ig(l))})),l})).setLayout({name:"mx_worley_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),JB=Rp((([e])=>{const t=e.y,s=e.z,i=jp().toVar();return Pp(t.lessThan(1e-4),(()=>{i.assign(jp(s,s,s))})).Else((()=>{let r=e.x;r=r.sub(Fg(r)).mul(6).toVar();const n=Op(Qg(r)),o=r.sub(Up(n)),a=s.mul(t.oneMinus()),h=s.mul(t.mul(o).oneMinus()),u=s.mul(t.mul(o.oneMinus()).oneMinus());Pp(n.equal(Op(0)),(()=>{i.assign(jp(s,u,a))})).ElseIf(n.equal(Op(1)),(()=>{i.assign(jp(h,s,a))})).ElseIf(n.equal(Op(2)),(()=>{i.assign(jp(a,s,u))})).ElseIf(n.equal(Op(3)),(()=>{i.assign(jp(a,h,s))})).ElseIf(n.equal(Op(4)),(()=>{i.assign(jp(u,a,s))})).Else((()=>{i.assign(jp(s,a,h))}))})),i})).setLayout({name:"mx_hsvtorgb",type:"vec3",inputs:[{name:"hsv",type:"vec3"}]}),KB=Rp((([e])=>{const t=jp(e).toVar(),s=Up(t.x).toVar(),i=Up(t.y).toVar(),r=Up(t.z).toVar(),n=Up(nf(s,nf(i,r))).toVar(),o=Up(of(s,of(i,r))).toVar(),a=Up(o.sub(n)).toVar(),h=Up().toVar(),u=Up().toVar(),l=Up().toVar();return l.assign(o),Pp(o.greaterThan(0),(()=>{u.assign(a.div(o))})).Else((()=>{u.assign(0)})),Pp(u.lessThanEqual(0),(()=>{h.assign(0)})).Else((()=>{Pp(s.greaterThanEqual(o),(()=>{h.assign(i.sub(r).div(a))})).ElseIf(i.greaterThanEqual(o),(()=>{h.assign(Zm(2,r.sub(s).div(a)))})).Else((()=>{h.assign(Zm(4,s.sub(i).div(a)))})),h.mulAssign(1/6),Pp(h.lessThan(0),(()=>{h.addAssign(1)}))})),jp(h,u,l)})).setLayout({name:"mx_rgbtohsv",type:"vec3",inputs:[{name:"c",type:"vec3"}]}),QB=Rp((([e])=>{const t=jp(e).toVar(),s=$p(rg(t,jp(.04045))).toVar(),i=jp(t.div(12.92)).toVar(),r=jp(mf(of(t.add(jp(.055)),jp(0)).div(1.055),jp(2.4))).toVar();return Tf(i,r,s)})).setLayout({name:"mx_srgb_texture_to_lin_rec709",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),eI=(e,t)=>{e=Up(e),t=Up(t);const s=Dp(t.dFdx(),t.dFdy()).length().mul(.7071067811865476);return Mf(e.sub(s),e.add(s),t)},tI=(e,t,s,i)=>Tf(e,t,s[i].clamp()),sI=(e,t,s=My())=>tI(e,t,s,"x"),iI=(e,t,s=My())=>tI(e,t,s,"y"),rI=(e,t,s,i,r)=>Tf(e,t,eI(s,i[r])),nI=(e,t,s,i=My())=>rI(e,t,s,i,"x"),oI=(e,t,s,i=My())=>rI(e,t,s,i,"y"),aI=(e=1,t=0,s=My())=>s.mul(e).add(t),hI=(e,t=1)=>(e=Up(e)).abs().pow(t).mul(e.sign()),uI=(e,t=1,s=.5)=>Up(e).sub(s).mul(t).add(s),lI=(e=My(),t=1,s=0)=>zB(e.convert("vec2|vec3")).mul(t).add(s),cI=(e=My(),t=1,s=0)=>UB(e.convert("vec2|vec3")).mul(t).add(s),dI=(e=My(),t=1,s=0)=>{e=e.convert("vec2|vec3");return Xp(UB(e),zB(e.add(Dp(19,73)))).mul(t).add(s)},pI=(e=My(),t=1)=>XB(e.convert("vec2|vec3"),t,Op(1)),mI=(e=My(),t=1)=>YB(e.convert("vec2|vec3"),t,Op(1)),gI=(e=My(),t=1)=>ZB(e.convert("vec2|vec3"),t,Op(1)),fI=(e=My())=>OB(e.convert("vec2|vec3")),yI=(e=My(),t=3,s=2,i=.5,r=1)=>VB(e,Op(t),s,i).mul(r),xI=(e=My(),t=3,s=2,i=.5,r=1)=>kB(e,Op(t),s,i).mul(r),bI=(e=My(),t=3,s=2,i=.5,r=1)=>DB(e,Op(t),s,i).mul(r),vI=(e=My(),t=3,s=2,i=.5,r=1)=>GB(e,Op(t),s,i).mul(r),TI=Rp((([e,t])=>{const s=e.x,i=e.y,r=e.z;let n=t.element(0).mul(.886227);return n=n.add(t.element(1).mul(1.023328).mul(i)),n=n.add(t.element(2).mul(1.023328).mul(r)),n=n.add(t.element(3).mul(1.023328).mul(s)),n=n.add(t.element(4).mul(.858086).mul(s).mul(i)),n=n.add(t.element(5).mul(.858086).mul(i).mul(r)),n=n.add(t.element(6).mul(r.mul(r).mul(.743125).sub(.247708))),n=n.add(t.element(7).mul(.858086).mul(s).mul(r)),n=n.add(t.element(8).mul(.429043).mul(Km(s,s).sub(Km(i,i)))),n}));class _I extends JR{static get type(){return"PointLightNode"}constructor(e=null){super(e),this.cutoffDistanceNode=pm(0).setGroup(lm),this.decayExponentNode=pm(0).setGroup(lm)}update(e){const{light:t}=this;super.update(e),this.cutoffDistanceNode.value=t.distance,this.decayExponentNode.value=t.decay}setup(e){const{colorNode:t,cutoffDistanceNode:s,decayExponentNode:i,light:r}=this,n=e.context.lightingModel,o=iE(r).sub(cx),a=o.normalize(),h=o.length(),u=KR({lightDistance:h,cutoffDistance:s,decayExponent:i}),l=t.mul(u),c=e.context.reflectedLight;n.direct({lightDirection:a,lightColor:l,reflectedLight:c},e.stack,e)}}class wI extends JR{static get type(){return"DirectionalLightNode"}constructor(e=null){super(e)}setup(e){super.setup(e);const t=e.context.lightingModel,s=this.colorNode,i=rE(this.light),r=e.context.reflectedLight;t.direct({lightDirection:i,lightColor:s,reflectedLight:r},e.stack,e)}}const SI=new nr,MI=new nr;let NI=null;class AI extends JR{static get type(){return"RectAreaLightNode"}constructor(e=null){super(e),this.halfHeight=pm(new Ri).setGroup(lm),this.halfWidth=pm(new Ri).setGroup(lm)}update(e){super.update(e);const{light:t}=this,s=e.camera.matrixWorldInverse;MI.identity(),SI.copy(t.matrixWorld),SI.premultiply(s),MI.extractRotation(SI),this.halfWidth.value.set(.5*t.width,0,0),this.halfHeight.value.set(0,.5*t.height,0),this.halfWidth.value.applyMatrix4(MI),this.halfHeight.value.applyMatrix4(MI)}setup(e){let t,s;super.setup(e),e.isAvailable("float32Filterable")?(t=By(NI.LTC_FLOAT_1),s=By(NI.LTC_FLOAT_2)):(t=By(NI.LTC_HALF_1),s=By(NI.LTC_HALF_2));const{colorNode:i,light:r}=this,n=e.context.lightingModel,o=iE(r),a=e.context.reflectedLight;n.directRectArea({lightColor:i,lightPosition:o,halfWidth:this.halfWidth,halfHeight:this.halfHeight,reflectedLight:a,ltc_1:t,ltc_2:s},e.stack,e)}static setLTC(e){NI=e}}class CI extends JR{static get type(){return"SpotLightNode"}constructor(e=null){super(e),this.coneCosNode=pm(0).setGroup(lm),this.penumbraCosNode=pm(0).setGroup(lm),this.cutoffDistanceNode=pm(0).setGroup(lm),this.decayExponentNode=pm(0).setGroup(lm)}update(e){super.update(e);const{light:t}=this;this.coneCosNode.value=Math.cos(t.angle),this.penumbraCosNode.value=Math.cos(t.angle*(1-t.penumbra)),this.cutoffDistanceNode.value=t.distance,this.decayExponentNode.value=t.decay}getSpotAttenuation(e){const{coneCosNode:t,penumbraCosNode:s}=this;return Mf(t,s,e)}setup(e){super.setup(e);const t=e.context.lightingModel,{colorNode:s,cutoffDistanceNode:i,decayExponentNode:r,light:n}=this,o=iE(n).sub(cx),a=o.normalize(),h=a.dot(rE(n)),u=this.getSpotAttenuation(h),l=o.length(),c=KR({lightDistance:l,cutoffDistance:i,decayExponent:r}),d=s.mul(u).mul(c),p=e.context.reflectedLight;t.direct({lightDirection:a,lightColor:d,reflectedLight:p},e.stack,e)}}class RI extends CI{static get type(){return"IESSpotLightNode"}getSpotAttenuation(e){const t=this.light.iesMap;let s=null;if(t&&!0===t.isTexture){const i=e.acos().mul(1/Math.PI);s=By(t,Dp(i,0),0).r}else s=super.getSpotAttenuation(e);return s}}class EI extends JR{static get type(){return"AmbientLightNode"}constructor(e=null){super(e)}setup({context:e}){e.irradiance.addAssign(this.colorNode)}}class BI extends JR{static get type(){return"HemisphereLightNode"}constructor(e=null){super(e),this.lightPositionNode=tE(e),this.lightDirectionNode=this.lightPositionNode.normalize(),this.groundColorNode=pm(new Jr).setGroup(lm)}update(e){const{light:t}=this;super.update(e),this.lightPositionNode.object3d=t,this.groundColorNode.value.copy(t.groundColor).multiplyScalar(t.intensity)}setup(e){const{colorNode:t,groundColorNode:s,lightDirectionNode:i}=this,r=bx.dot(i).mul(.5).add(.5),n=Tf(s,t,r);e.context.irradiance.addAssign(n)}}class II extends JR{static get type(){return"LightProbeNode"}constructor(e=null){super(e);const t=[];for(let e=0;e<9;e++)t.push(new Ri);this.lightProbe=Ox(t)}update(e){const{light:t}=this;super.update(e);for(let e=0;e<9;e++)this.lightProbe.array[e].copy(t.sh.coefficients[e]).multiplyScalar(t.intensity)}setup(e){const t=TI(vx,this.lightProbe);e.context.irradiance.addAssign(t)}}class PI{parseFunction(){console.warn("Abstract function.")}}class FI{constructor(e,t,s="",i=""){this.type=e,this.inputs=t,this.name=s,this.precision=i}getCode(){console.warn("Abstract function.")}}FI.isNodeFunction=!0;const zI=/^\s*(highp|mediump|lowp)?\s*([a-z_0-9]+)\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)/i,UI=/[a-z_0-9]+/gi,OI="#pragma main";class LI extends FI{constructor(e){const{type:t,inputs:s,name:i,precision:r,inputsCode:n,blockCode:o,headerCode:a}=(e=>{const t=(e=e.trim()).indexOf(OI),s=-1!==t?e.slice(t+12):e,i=s.match(zI);if(null!==i&&5===i.length){const r=i[4],n=[];let o=null;for(;null!==(o=UI.exec(r));)n.push(o);const a=[];let h=0;for(;h0?this.transparent:this.opaque).push(o)}unshift(e,t,s,i,r,n){const o=this.getNextRenderItem(e,t,s,i,r,n);(!0===s.transparent?this.transparent:this.opaque).unshift(o)}pushBundle(e){this.bundles.push(e)}pushLight(e){this.lightsArray.push(e)}getLightsNode(){return this.lightsNode.fromLights(this.lightsArray)}sort(e,t){this.opaque.length>1&&this.opaque.sort(e||DI),this.transparent.length>1&&this.transparent.sort(t||kI)}finish(){this.lightsNode.setLights(this.lightsArray);for(let e=this.renderItemsIndex,t=this.renderItems.length;e>t,h=o.height>>t;let u=e.depthTexture||r[t],l=!1;void 0===u&&(u=new Ya,u.format=e.stencilBuffer?je:We,u.type=e.stencilBuffer?Ue:Be,u.image.width=a,u.image.height=h,r[t]=u),s.width===o.width&&o.height===s.height||(l=!0,u.needsUpdate=!0,u.image.width=a,u.image.height=h),s.width=o.width,s.height=o.height,s.textures=n,s.depthTexture=u,s.depth=e.depthBuffer,s.stencil=e.stencilBuffer,s.renderTarget=e,s.sampleCount!==i&&(l=!0,u.needsUpdate=!0,s.sampleCount=i);const c={sampleCount:i};for(let e=0;e{e.removeEventListener("dispose",t);for(let e=0;e0){const i=e.image;if(void 0===i)console.warn("THREE.Renderer: Texture marked for update but image is undefined.");else if(!1===i.complete)console.warn("THREE.Renderer: Texture marked for update but image is incomplete.");else{if(e.images){const s=[];for(const t of e.images)s.push(t);t.images=s}else t.image=i;void 0!==s.isDefaultTexture&&!0!==s.isDefaultTexture||(r.createTexture(e,t),s.isDefaultTexture=!1,s.generation=e.version),!0===e.source.dataReady&&r.updateTexture(e,t),t.needsMipmaps&&0===e.mipmaps.length&&r.generateMipmaps(e)}}else r.createDefaultTexture(e),s.isDefaultTexture=!0,s.generation=e.version}if(!0!==s.initialized){s.initialized=!0,s.generation=e.version,this.info.memory.textures++;const t=()=>{e.removeEventListener("dispose",t),this._destroyTexture(e),this.info.memory.textures--};e.addEventListener("dispose",t)}s.version=e.version}getSize(e,t=XI){let s=e.images?e.images[0]:e.image;return s?(void 0!==s.image&&(s=s.image),t.width=s.width,t.height=s.height,t.depth=e.isCubeTexture?6:s.depth||1):t.width=t.height=t.depth=1,t}getMipLevels(e,t,s){let i;return i=e.isCompressedTexture?e.mipmaps.length:Math.floor(Math.log2(Math.max(t,s)))+1,i}needsMipmaps(e){return!!this.isEnvironmentTexture(e)||(!0===e.isCompressedTexture||e.minFilter!==fe&&e.minFilter!==Te)}isEnvironmentTexture(e){const t=e.mapping;return t===le||t===ce||t===he||t===ue}_destroyTexture(e){this.backend.destroySampler(e),this.backend.destroyTexture(e),this.delete(e)}}class ZI extends Jr{constructor(e,t,s,i=1){super(e,t,s),this.a=i}set(e,t,s,i=1){return this.a=i,super.set(e,t,s)}copy(e){return void 0!==e.a&&(this.a=e.a),super.copy(e)}clone(){return new this.constructor(this.r,this.g,this.b,this.a)}}const JI=new ZI;class KI extends Xw{constructor(e,t){super(),this.renderer=e,this.nodes=t}update(e,t,s){const i=this.renderer,r=this.nodes.getBackgroundNode(e)||e.background;let n=!1;if(null===r)i._clearColor.getRGB(JI,Jt),JI.a=i._clearColor.a;else if(!0===r.isColor)r.getRGB(JI,Jt),JI.a=1,n=!0;else if(!0===r.isNode){const s=this.get(e),n=r;JI.copy(i._clearColor);let o=s.backgroundMesh;if(void 0===o){const e=Ff(Xp(n).mul(wN),{getUV:()=>vx,getTextureLevel:()=>_N});let t=sv();t=t.setZ(t.w);const i=new pT;i.name="Background.material",i.side=d,i.depthTest=!1,i.depthWrite=!1,i.fog=!1,i.lights=!1,i.vertexNode=t,i.colorNode=e,s.backgroundMeshNode=e,s.backgroundMesh=o=new Vn(new du(1,32,32),i),o.frustumCulled=!1,o.name="Background.mesh",o.onBeforeRender=function(e,t,s){this.matrixWorld.copyPosition(s.matrixWorld)}}const a=n.getCacheKey();s.backgroundCacheKey!==a&&(s.backgroundMeshNode.node=Xp(n).mul(wN),s.backgroundMeshNode.needsUpdate=!0,o.material.needsUpdate=!0,s.backgroundCacheKey=a),t.unshift(o,o.geometry,o.material,0,0,null)}else console.error("THREE.Renderer: Unsupported background configuration.",r);if(!0===i.autoClear||!0===n){JI.multiplyScalar(JI.a);const e=s.clearColorValue;e.r=JI.r,e.g=JI.g,e.b=JI.b,e.a=JI.a,s.depthClearValue=i._clearDepth,s.stencilClearValue=i._clearStencil,s.clearColor=!0===i.autoClearColor,s.clearDepth=!0===i.autoClearDepth,s.clearStencil=!0===i.autoClearStencil}else s.clearColor=!1,s.clearDepth=!1,s.clearStencil=!1}}class QI{constructor(e,t,s,i,r,n,o,a,h,u=[]){this.vertexShader=e,this.fragmentShader=t,this.computeShader=s,this.transforms=u,this.nodeAttributes=i,this.bindings=r,this.updateNodes=n,this.updateBeforeNodes=o,this.updateAfterNodes=a,this.monitor=h,this.usedTimes=0}createBindings(){const e=[];for(const t of this.bindings){if(!0!==t.bindings[0].groupNode.shared){const s=new pM(t.name,[],t.index,t);e.push(s);for(const e of t.bindings)s.bindings.push(e.clone())}else e.push(t)}return e}}const eP=new WeakMap;class tP extends Xw{constructor(e,t){super(),this.renderer=e,this.backend=t,this.nodeFrame=new bM,this.nodeBuilderCache=new Map,this.callHashCache=new kw,this.groupsData=new kw}updateGroup(e){const t=e.groupNode,s=t.name;if(s===cm.name)return!0;if(s===lm.name){const t=this.get(e),s=this.nodeFrame.renderId;return t.renderId!==s&&(t.renderId=s,!0)}if(s===um.name){const t=this.get(e),s=this.nodeFrame.frameId;return t.frameId!==s&&(t.frameId=s,!0)}const i=[t,e];let r=this.groupsData.get(i);return void 0===r&&this.groupsData.set(i,r={}),r.version!==t.version&&(r.version=t.version,!0)}getForRenderCacheKey(e){return e.initialCacheKey}getForRender(e){const t=this.get(e);let s=t.nodeBuilderState;if(void 0===s){const{nodeBuilderCache:i}=this,r=this.getForRenderCacheKey(e);if(s=i.get(r),void 0===s){const t=this.backend.createNodeBuilder(e.object,this.renderer);t.scene=e.scene,t.material=e.material,t.camera=e.camera,t.context.material=e.material,t.lightsNode=e.lightsNode,t.environmentNode=this.getEnvironmentNode(e.scene),t.fogNode=this.getFogNode(e.scene),t.clippingContext=e.clippingContext,t.build(),s=this._createNodeBuilderState(t),i.set(r,s)}s.usedTimes++,t.nodeBuilderState=s}return s}delete(e){if(e.isRenderObject){const t=this.get(e).nodeBuilderState;t.usedTimes--,0===t.usedTimes&&this.nodeBuilderCache.delete(this.getForRenderCacheKey(e))}return super.delete(e)}getForCompute(e){const t=this.get(e);let s=t.nodeBuilderState;if(void 0===s){const i=this.backend.createNodeBuilder(e,this.renderer);i.build(),s=this._createNodeBuilderState(i),t.nodeBuilderState=s}return s}_createNodeBuilderState(e){return new QI(e.vertexShader,e.fragmentShader,e.computeShader,e.getAttributesArray(),e.getBindings(),e.updateNodes,e.updateBeforeNodes,e.updateAfterNodes,e.monitor,e.transforms)}getEnvironmentNode(e){return e.environmentNode||this.get(e).environmentNode||null}getBackgroundNode(e){return e.backgroundNode||this.get(e).backgroundNode||null}getFogNode(e){return e.fogNode||this.get(e).fogNode||null}getCacheKey(e,t){const s=[e,t],i=this.renderer.info.calls;let r=this.callHashCache.get(s);if(void 0===r||r.callId!==i){const n=this.getEnvironmentNode(e),o=this.getFogNode(e),a=[];t&&a.push(t.getCacheKey(!0)),n&&a.push(n.getCacheKey()),o&&a.push(o.getCacheKey()),a.push(this.renderer.shadowMap.enabled?1:0),r={callId:i,cacheKey:Td(a)},this.callHashCache.set(s,r)}return r.cacheKey}updateScene(e){this.updateEnvironment(e),this.updateFog(e),this.updateBackground(e)}get isToneMappingState(){return!this.renderer.getRenderTarget()}updateBackground(e){const t=this.get(e),s=e.background;if(s){const i=0===e.backgroundBlurriness&&t.backgroundBlurriness>0||e.backgroundBlurriness>0&&0===t.backgroundBlurriness;if(t.background!==s||i){let i=null;if(!0===s.isCubeTexture||s.mapping===le||s.mapping===ce||s.mapping===de)if(e.backgroundBlurriness>0||s.mapping===de)i=hw(s,vx);else{let e;e=!0===s.isCubeTexture?Ix(s):By(s),i=PT(e)}else!0===s.isTexture?i=By(s,Dv.flipY()).setUpdateMatrix(!0):!0!==s.isColor&&console.error("WebGPUNodes: Unsupported background configuration.",s);t.backgroundNode=i,t.background=s,t.backgroundBlurriness=e.backgroundBlurriness}}else t.backgroundNode&&(delete t.backgroundNode,delete t.background)}updateFog(e){const t=this.get(e),s=e.fog;if(s){if(t.fog!==s){let e=null;if(s.isFogExp2){const t=kx("color","color",s).setGroup(lm),i=kx("density","float",s).setGroup(lm);e=OR(t,i)}else if(s.isFog){const t=kx("color","color",s).setGroup(lm),i=kx("near","float",s).setGroup(lm),r=kx("far","float",s).setGroup(lm);e=zR(t,i,r)}else console.error("WebGPUNodes: Unsupported fog configuration.",s);t.fogNode=e,t.fog=s}}else delete t.fogNode,delete t.fog}updateEnvironment(e){const t=this.get(e),s=e.environment;if(s){if(t.environment!==s){let e=null;!0===s.isCubeTexture?e=Ix(s):!0===s.isTexture?e=By(s):console.error("Nodes: Unsupported environment configuration.",s),t.environmentNode=e,t.environment=s}}else t.environmentNode&&(delete t.environmentNode,delete t.environment)}getNodeFrame(e=this.renderer,t=null,s=null,i=null,r=null){const n=this.nodeFrame;return n.renderer=e,n.scene=t,n.object=s,n.camera=i,n.material=r,n}getNodeFrameForRender(e){return this.getNodeFrame(e.renderer,e.scene,e.object,e.camera,e.material)}getOutputCacheKey(){const e=this.renderer;return e.toneMapping+","+e.currentColorSpace}hasOutputChange(e){return eP.get(e)!==this.getOutputCacheKey()}getOutputNode(e){const t=this.renderer,s=this.getOutputCacheKey(),i=By(e,Dv).renderOutput(t.toneMapping,t.currentColorSpace);return eP.set(e,s),i}updateBefore(e){const t=e.getNodeBuilderState();for(const s of t.updateBeforeNodes)this.getNodeFrameForRender(e).updateBeforeNode(s)}updateAfter(e){const t=e.getNodeBuilderState();for(const s of t.updateAfterNodes)this.getNodeFrameForRender(e).updateAfterNode(s)}updateForCompute(e){const t=this.getNodeFrame(),s=this.getForCompute(e);for(const e of s.updateNodes)t.updateNode(e)}updateForRender(e){const t=this.getNodeFrameForRender(e),s=e.getNodeBuilderState();for(const e of s.updateNodes)t.updateNode(e)}needsRefresh(e){const t=this.getNodeFrameForRender(e);return e.getMonitor().needsRefresh(e,t)}dispose(){super.dispose(),this.nodeFrame=new bM,this.nodeBuilderCache=new Map}}class sP{constructor(e,t){this.scene=e,this.camera=t}clone(){return Object.assign(new this.constructor,this)}}class iP{constructor(){this.lists=new kw}get(e,t){const s=this.lists,i=[e,t];let r=s.get(i);return void 0===r&&(r=new sP(e,t),s.set(i,r)),r}dispose(){this.lists=new kw}}class rP{constructor(){this.lightNodes=new WeakMap,this.materialNodes=new Map,this.toneMappingNodes=new Map,this.colorSpaceNodes=new Map}fromMaterial(e){if(e.isNodeMaterial)return e;let t=null;const s=this.getMaterialNodeClass(e.type);if(null!==s){t=new s;for(const s in e)t[s]=e[s]}return t}addColorSpace(e,t){this.addType(e,t,this.colorSpaceNodes)}getColorSpaceFunction(e){return this.colorSpaceNodes.get(e)||null}addToneMapping(e,t){this.addType(e,t,this.toneMappingNodes)}getToneMappingFunction(e){return this.toneMappingNodes.get(e)||null}getMaterialNodeClass(e){return this.materialNodes.get(e)||null}addMaterial(e,t){this.addType(e,t.name,this.materialNodes)}getLightNodeClass(e){return this.lightNodes.get(e)||null}addLight(e,t){this.addClass(e,t,this.lightNodes)}addType(e,t,s){if(s.has(t))console.warn(`Redefinition of node ${t}`);else{if("function"!=typeof e)throw new Error(`Node class ${e.name} is not a class.`);if("function"==typeof t||"object"==typeof t)throw new Error(`Base class ${t} is not a class.`);s.set(t,e)}}addClass(e,t,s){if(s.has(t))console.warn(`Redefinition of node ${t.name}`);else{if("function"!=typeof e)throw new Error(`Node class ${e.name} is not a class.`);if("function"!=typeof t)throw new Error(`Base class ${t.name} is not a class.`);s.set(t,e)}}}const nP=new to,oP=new Qs,aP=new Ti,hP=new ta,uP=new nr,lP=new Ti;class cP{constructor(e,t={}){this.isRenderer=!0;const{logarithmicDepthBuffer:s=!1,alpha:i=!0,depth:r=!0,stencil:n=!1,antialias:o=!1,samples:a=0,getFallback:h=null}=t;this.domElement=e.getDomElement(),this.backend=e,this.samples=a||!0===o?4:0,this.autoClear=!0,this.autoClearColor=!0,this.autoClearDepth=!0,this.autoClearStencil=!0,this.alpha=i,this.logarithmicDepthBuffer=s,this.outputColorSpace=Zt,this.toneMapping=0,this.toneMappingExposure=1,this.sortObjects=!0,this.depth=r,this.stencil=n,this.clippingPlanes=[],this.info=new iS,this.nodes={library:new rP,modelViewMatrix:null,modelNormalViewMatrix:null},this._getFallback=h,this._pixelRatio=1,this._width=this.domElement.width,this._height=this.domElement.height,this._viewport=new Ti(0,0,this._width,this._height),this._scissor=new Ti(0,0,this._width,this._height),this._scissorTest=!1,this._attributes=null,this._geometries=null,this._nodes=null,this._animation=null,this._bindings=null,this._objects=null,this._pipelines=null,this._bundles=null,this._renderLists=null,this._renderContexts=null,this._textures=null,this._background=null,this._quad=new dN(new pT),this._quad.material.type="Renderer_output",this._currentRenderContext=null,this._opaqueSort=null,this._transparentSort=null,this._frameBufferTarget=null;const u=!0===this.alpha?0:1;this._clearColor=new ZI(0,0,0,u),this._clearDepth=1,this._clearStencil=0,this._renderTarget=null,this._activeCubeFace=0,this._activeMipmapLevel=0,this._mrt=null,this._renderObjectFunction=null,this._currentRenderObjectFunction=null,this._currentRenderBundle=null,this._handleObjectFunction=this._renderObjectDirect,this._initialized=!1,this._initPromise=null,this._compilationPromises=null,this.transparent=!0,this.opaque=!0,this.shadowMap={enabled:!1,type:1},this.xr={enabled:!1},this.debug={checkShaderErrors:!0,onShaderError:null,getShaderAsync:async(e,t,s)=>{await this.compileAsync(e,t);const i=this._renderLists.get(e,t),r=this._renderContexts.get(e,t,this._renderTarget),n=e.overrideMaterial||s.material,o=this._objects.get(s,n,e,t,i.lightsNode,r),{fragmentShader:a,vertexShader:h}=o.getNodeBuilderState();return{fragmentShader:a,vertexShader:h}}}}async init(){if(this._initialized)throw new Error("Renderer: Backend has already been initialized.");return null!==this._initPromise||(this._initPromise=new Promise((async(e,t)=>{let s=this.backend;try{await s.init(this)}catch(e){if(null===this._getFallback)return void t(e);try{this.backend=s=this._getFallback(e),await s.init(this)}catch(e){return void t(e)}}this._nodes=new tP(this,s),this._animation=new Dw(this._nodes,this.info),this._attributes=new Qw(s),this._background=new KI(this,this._nodes),this._geometries=new sS(this._attributes,this.info),this._textures=new YI(this,s,this.info),this._pipelines=new uS(s,this._nodes),this._bindings=new lS(s,this._nodes,this._textures,this._attributes,this._pipelines,this.info),this._objects=new $w(this,this._nodes,this._geometries,this._pipelines,this._bindings,this.info),this._renderLists=new WI,this._bundles=new iP,this._renderContexts=new $I,this._initialized=!0,e()}))),this._initPromise}get coordinateSystem(){return this.backend.coordinateSystem}async compileAsync(e,t,s=null){!1===this._initialized&&await this.init();const i=this._nodes.nodeFrame,r=i.renderId,n=this._currentRenderContext,o=this._currentRenderObjectFunction,a=this._compilationPromises,h=!0===e.isScene?e:nP;null===s&&(s=e);const u=this._renderTarget,l=this._renderContexts.get(s,t,u),c=this._activeMipmapLevel,d=[];this._currentRenderContext=l,this._currentRenderObjectFunction=this.renderObject,this._handleObjectFunction=this._createObjectPipeline,this._compilationPromises=d,i.renderId++,i.update(),l.depth=this.depth,l.stencil=this.stencil,l.clippingContext||(l.clippingContext=new Ww),l.clippingContext.updateGlobal(this,t),h.onBeforeRender(this,e,t,u);const p=this._renderLists.get(e,t);if(p.begin(),this._projectObject(e,t,0,p),s!==e&&s.traverseVisible((function(e){e.isLight&&e.layers.test(t.layers)&&p.pushLight(e)})),p.finish(),null!==u){this._textures.updateRenderTarget(u,c);const e=this._textures.get(u);l.textures=e.textures,l.depthTexture=e.depthTexture}else l.textures=null,l.depthTexture=null;this._nodes.updateScene(h),this._background.update(h,p,l);const m=p.opaque,g=p.transparent,f=p.lightsNode;!0===this.opaque&&m.length>0&&this._renderObjects(m,t,h,f),!0===this.transparent&&g.length>0&&this._renderObjects(g,t,h,f),i.renderId=r,this._currentRenderContext=n,this._currentRenderObjectFunction=o,this._compilationPromises=a,this._handleObjectFunction=this._renderObjectDirect,await Promise.all(d)}async renderAsync(e,t){!1===this._initialized&&await this.init();const s=this._renderScene(e,t);await this.backend.resolveTimestampAsync(s,"render")}setMRT(e){return this._mrt=e,this}getMRT(){return this._mrt}_renderBundle(e,t,s){const{bundleGroup:i,camera:r,renderList:n}=e,o=this._currentRenderContext,a=this._bundles.get(i,r),h=this.backend.get(a);void 0===h.renderContexts&&(h.renderContexts=new Set);const u=i.version!==h.version,l=!1===h.renderContexts.has(o)||u;if(h.renderContexts.add(o),l){this.backend.beginBundle(o),(void 0===h.renderObjects||u)&&(h.renderObjects=[]),this._currentRenderBundle=a;const e=n.opaque;e.length>0&&this._renderObjects(e,r,t,s),this._currentRenderBundle=null,this.backend.finishBundle(o,a),h.version=i.version}else{const{renderObjects:e}=h;for(let t=0,s=e.length;t>=c,p.viewportValue.height>>=c,p.viewportValue.minDepth=x,p.viewportValue.maxDepth=b,p.viewport=!1===p.viewportValue.equals(aP),p.scissorValue.copy(f).multiplyScalar(y).floor(),p.scissor=this._scissorTest&&!1===p.scissorValue.equals(aP),p.scissorValue.width>>=c,p.scissorValue.height>>=c,p.clippingContext||(p.clippingContext=new Ww),p.clippingContext.updateGlobal(this,t),h.onBeforeRender(this,e,t,d),uP.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),hP.setFromProjectionMatrix(uP,m);const v=this._renderLists.get(e,t);if(v.begin(),this._projectObject(e,t,0,v),v.finish(),!0===this.sortObjects&&v.sort(this._opaqueSort,this._transparentSort),null!==d){this._textures.updateRenderTarget(d,c);const e=this._textures.get(d);p.textures=e.textures,p.depthTexture=e.depthTexture,p.width=e.width,p.height=e.height,p.renderTarget=d,p.depth=d.depthBuffer,p.stencil=d.stencilBuffer}else p.textures=null,p.depthTexture=null,p.width=this.domElement.width,p.height=this.domElement.height,p.depth=this.depth,p.stencil=this.stencil;p.width>>=c,p.height>>=c,p.activeCubeFace=l,p.activeMipmapLevel=c,p.occlusionQueryCount=v.occlusionQueryCount,this._nodes.updateScene(h),this._background.update(h,v,p),this.backend.beginRender(p);const{bundles:T,lightsNode:_,transparent:w,opaque:S}=v;if(T.length>0&&this._renderBundles(T,h,_),!0===this.opaque&&S.length>0&&this._renderObjects(S,t,h,_),!0===this.transparent&&w.length>0&&this._renderObjects(w,t,h,_),this.backend.finishRender(p),r.renderId=n,this._currentRenderContext=o,this._currentRenderObjectFunction=a,null!==i){this.setRenderTarget(u,l,c);const e=this._quad;this._nodes.hasOutputChange(d.texture)&&(e.material.fragmentNode=this._nodes.getOutputNode(d.texture),e.material.needsUpdate=!0),this._renderScene(e,e.camera,!1)}return h.onAfterRender(this,e,t,d),p}getMaxAnisotropy(){return this.backend.getMaxAnisotropy()}getActiveCubeFace(){return this._activeCubeFace}getActiveMipmapLevel(){return this._activeMipmapLevel}async setAnimationLoop(e){!1===this._initialized&&await this.init(),this._animation.setAnimationLoop(e)}async getArrayBufferAsync(e){return await this.backend.getArrayBufferAsync(e)}getContext(){return this.backend.getContext()}getPixelRatio(){return this._pixelRatio}getDrawingBufferSize(e){return e.set(this._width*this._pixelRatio,this._height*this._pixelRatio).floor()}getSize(e){return e.set(this._width,this._height)}setPixelRatio(e=1){this._pixelRatio=e,this.setSize(this._width,this._height,!1)}setDrawingBufferSize(e,t,s){this._width=e,this._height=t,this._pixelRatio=s,this.domElement.width=Math.floor(e*s),this.domElement.height=Math.floor(t*s),this.setViewport(0,0,e,t),this._initialized&&this.backend.updateSize()}setSize(e,t,s=!0){this._width=e,this._height=t,this.domElement.width=Math.floor(e*this._pixelRatio),this.domElement.height=Math.floor(t*this._pixelRatio),!0===s&&(this.domElement.style.width=e+"px",this.domElement.style.height=t+"px"),this.setViewport(0,0,e,t),this._initialized&&this.backend.updateSize()}setOpaqueSort(e){this._opaqueSort=e}setTransparentSort(e){this._transparentSort=e}getScissor(e){const t=this._scissor;return e.x=t.x,e.y=t.y,e.width=t.width,e.height=t.height,e}setScissor(e,t,s,i){const r=this._scissor;e.isVector4?r.copy(e):r.set(e,t,s,i)}getScissorTest(){return this._scissorTest}setScissorTest(e){this._scissorTest=e,this.backend.setScissorTest(e)}getViewport(e){return e.copy(this._viewport)}setViewport(e,t,s,i,r=0,n=1){const o=this._viewport;e.isVector4?o.copy(e):o.set(e,t,s,i),o.minDepth=r,o.maxDepth=n}getClearColor(e){return e.copy(this._clearColor)}setClearColor(e,t=1){this._clearColor.set(e),this._clearColor.a=t}getClearAlpha(){return this._clearColor.a}setClearAlpha(e){this._clearColor.a=e}getClearDepth(){return this._clearDepth}setClearDepth(e){this._clearDepth=e}getClearStencil(){return this._clearStencil}setClearStencil(e){this._clearStencil=e}isOccluded(e){const t=this._currentRenderContext;return t&&this.backend.isOccluded(t,e)}clear(e=!0,t=!0,s=!0){if(!1===this._initialized)return console.warn("THREE.Renderer: .clear() called before the backend is initialized. Try using .clearAsync() instead."),this.clearAsync(e,t,s);const i=this._renderTarget||this._getFrameBufferTarget();let r=null;if(null!==i&&(this._textures.updateRenderTarget(i),r=this._textures.get(i)),this.backend.clear(e,t,s,r),null!==i&&null===this._renderTarget){const e=this._quad;this._nodes.hasOutputChange(i.texture)&&(e.material.fragmentNode=this._nodes.getOutputNode(i.texture),e.material.needsUpdate=!0),this._renderScene(e,e.camera,!1)}}clearColor(){return this.clear(!0,!1,!1)}clearDepth(){return this.clear(!1,!0,!1)}clearStencil(){return this.clear(!1,!1,!0)}async clearAsync(e=!0,t=!0,s=!0){!1===this._initialized&&await this.init(),this.clear(e,t,s)}clearColorAsync(){return this.clearAsync(!0,!1,!1)}clearDepthAsync(){return this.clearAsync(!1,!0,!1)}clearStencilAsync(){return this.clearAsync(!1,!1,!0)}get currentToneMapping(){return null!==this._renderTarget?0:this.toneMapping}get currentColorSpace(){return null!==this._renderTarget?Jt:this.outputColorSpace}dispose(){this.info.dispose(),this._animation.dispose(),this._objects.dispose(),this._pipelines.dispose(),this._nodes.dispose(),this._bindings.dispose(),this._renderLists.dispose(),this._renderContexts.dispose(),this._textures.dispose(),this.setRenderTarget(null),this.setAnimationLoop(null)}setRenderTarget(e,t=0,s=0){this._renderTarget=e,this._activeCubeFace=t,this._activeMipmapLevel=s}getRenderTarget(){return this._renderTarget}setRenderObjectFunction(e){this._renderObjectFunction=e}getRenderObjectFunction(){return this._renderObjectFunction}async computeAsync(e){!1===this._initialized&&await this.init();const t=this._nodes.nodeFrame,s=t.renderId;this.info.calls++,this.info.compute.calls++,this.info.compute.frameCalls++,t.renderId=this.info.calls;const i=this.backend,r=this._pipelines,n=this._bindings,o=this._nodes,a=Array.isArray(e)?e:[e];if(void 0===a[0]||!0!==a[0].isComputeNode)throw new Error("THREE.Renderer: .compute() expects a ComputeNode.");i.beginCompute(e);for(const t of a){if(!1===r.has(t)){const e=()=>{t.removeEventListener("dispose",e),r.delete(t),n.delete(t),o.delete(t)};t.addEventListener("dispose",e),t.onInit({renderer:this})}o.updateForCompute(t),n.updateForCompute(t);const s=n.getForCompute(t),a=r.getForCompute(t,s);i.compute(e,t,s,a)}i.finishCompute(e),await this.backend.resolveTimestampAsync(e,"compute"),t.renderId=s}async hasFeatureAsync(e){return!1===this._initialized&&await this.init(),this.backend.hasFeature(e)}hasFeature(e){return!1===this._initialized?(console.warn("THREE.Renderer: .hasFeature() called before the backend is initialized. Try using .hasFeatureAsync() instead."),!1):this.backend.hasFeature(e)}copyFramebufferToTexture(e,t=null){const s=this._currentRenderContext;this._textures.updateTexture(e),t=null===t?lP.set(0,0,e.image.width,e.image.height):t,this.backend.copyFramebufferToTexture(e,s,t)}copyTextureToTexture(e,t,s=null,i=null,r=0){this._textures.updateTexture(e),this._textures.updateTexture(t),this.backend.copyTextureToTexture(e,t,s,i,r)}readRenderTargetPixelsAsync(e,t,s,i,r,n=0,o=0){return this.backend.copyTextureToBuffer(e.textures[n],t,s,i,r,o)}_projectObject(e,t,s,i){if(!1===e.visible)return;if(e.layers.test(t.layers))if(e.isGroup)s=e.renderOrder;else if(e.isLOD)!0===e.autoUpdate&&e.update(t);else if(e.isLight)i.pushLight(e);else if(e.isSprite){if(!e.frustumCulled||hP.intersectsSprite(e)){!0===this.sortObjects&&lP.setFromMatrixPosition(e.matrixWorld).applyMatrix4(uP);const{geometry:t,material:r}=e;r.visible&&i.push(e,t,r,s,lP.z,null)}}else if(e.isLineLoop)console.error("THREE.Renderer: Objects of type THREE.LineLoop are not supported. Please use THREE.Line or THREE.LineSegments.");else if((e.isMesh||e.isLine||e.isPoints)&&(!e.frustumCulled||hP.intersectsObject(e))){const{geometry:t,material:r}=e;if(!0===this.sortObjects&&(null===t.boundingSphere&&t.computeBoundingSphere(),lP.copy(t.boundingSphere.center).applyMatrix4(e.matrixWorld).applyMatrix4(uP)),Array.isArray(r)){const n=t.groups;for(let o=0,a=n.length;o0?i:"";t=`${e.name} {\n\t${s} ${r.name}[${n}];\n};\n`}else{t=`${this.getVectorType(r.type)} ${this.getPropertyName(r,e)};`,n=!0}const o=r.node.precision;if(null!==o&&(t=NP[o]+" "+t),n){t="\t"+t;const e=r.groupNode.name;(i[e]||(i[e]=[])).push(t)}else t="uniform "+t,s.push(t)}let r="";for(const t in i){const s=i[t];r+=this._getGLSLUniformStruct(e+"_"+t,s.join("\n"))+"\n"}return r+=s.join("\n"),r}getTypeFromAttribute(e){let t=super.getTypeFromAttribute(e);if(/^[iu]/.test(t)&&e.gpuType!==Ee){let s=e;e.isInterleavedBufferAttribute&&(s=e.data);const i=s.array;!1==(i instanceof Uint32Array||i instanceof Int32Array)&&(t=t.slice(1))}return t}getAttributes(e){let t="";if("vertex"===e||"compute"===e){const e=this.getAttributesArray();let s=0;for(const i of e)t+=`layout( location = ${s++} ) in ${i.type} ${i.name};\n`}return t}getStructMembers(e){const t=[],s=e.getMemberTypes();for(let e=0;ee*t),1)}u`}getDrawIndex(){return this.renderer.backend.extensions.has("WEBGL_multi_draw")?"uint( gl_DrawID )":null}getFrontFacing(){return"gl_FrontFacing"}getFragCoord(){return"gl_FragCoord.xy"}getFragDepth(){return"gl_FragDepth"}enableExtension(e,t,s=this.shaderStage){const i=this.extensions[s]||(this.extensions[s]=new Map);!1===i.has(e)&&i.set(e,{name:e,behavior:t})}getExtensions(e){const t=[];if("vertex"===e){const t=this.renderer.backend.extensions;this.object.isBatchedMesh&&t.has("WEBGL_multi_draw")&&this.enableExtension("GL_ANGLE_multi_draw","require",e)}const s=this.extensions[e];if(void 0!==s)for(const{name:e,behavior:i}of s.values())t.push(`#extension ${e} : ${i}`);return t.join("\n")}isAvailable(e){let t=AP[e];if(void 0===t){if("float32Filterable"===e){const e=this.renderer.backend.extensions;e.has("OES_texture_float_linear")?(e.get("OES_texture_float_linear"),t=!0):t=!1}AP[e]=t}return t}isFlipY(){return!0}registerTransform(e,t){this.transforms.push({varyingName:e,attributeNode:t})}getTransforms(){const e=this.transforms;let t="";for(let s=0;s0&&(s+="\n"),s+=`\t// flow -> ${n}\n\t`),s+=`${i.code}\n\t`,e===r&&"compute"!==t&&(s+="// result\n\t","vertex"===t?(s+="gl_Position = ",s+=`${i.result};`):"fragment"===t&&(e.outputNode.isOutputStructNode||(s+="fragColor = ",s+=`${i.result};`)))}const n=e[t];n.extensions=this.getExtensions(t),n.uniforms=this.getUniforms(t),n.attributes=this.getAttributes(t),n.varyings=this.getVaryings(t),n.vars=this.getVars(t),n.structs=this.getStructs(t),n.codes=this.getCodes(t),n.transforms=this.getTransforms(t),n.flow=s}null!==this.material?(this.vertexShader=this._getGLSLVertexCode(e.vertex),this.fragmentShader=this._getGLSLFragmentCode(e.fragment)):this.computeShader=this._getGLSLVertexCode(e.compute)}getUniformFromNode(e,t,s,i=null){const r=super.getUniformFromNode(e,t,s,i),n=this.getDataFromNode(e,s,this.globalCache);let o=n.uniformGPU;if(void 0===o){const i=e.groupNode,a=i.name,h=this.getBindGroupArray(a,s);if("texture"===t)o=new _P(r.name,r.node,i),h.push(o);else if("cubeTexture"===t)o=new wP(r.name,r.node,i),h.push(o);else if("texture3D"===t)o=new SP(r.name,r.node,i),h.push(o);else if("buffer"===t){e.name=`NodeBuffer_${e.id}`,r.name=`buffer${e.id}`;const t=new fP(e,i);t.name=e.name,h.push(t),o=t}else{const e=this.uniformGroups[s]||(this.uniformGroups[s]={});let n=e[a];void 0===n&&(n=new bP(s+"_"+a,i),e[a]=n,h.push(n)),o=this.getNodeUniform(r,t),n.addUniform(o)}n.uniformGPU=o}return r}}let EP=null,BP=null,IP=null;class PP{constructor(e={}){this.parameters=Object.assign({},e),this.data=new WeakMap,this.renderer=null,this.domElement=null}async init(e){this.renderer=e}begin(){}finish(){}draw(){}createProgram(){}destroyProgram(){}createBindings(){}updateBindings(){}createRenderPipeline(){}createComputePipeline(){}destroyPipeline(){}needsRenderUpdate(){}getRenderCacheKey(){}createNodeBuilder(){}createSampler(){}createDefaultTexture(){}createTexture(){}copyTextureToBuffer(){}createAttribute(){}createIndexAttribute(){}updateAttribute(){}destroyAttribute(){}getContext(){}updateSize(){}resolveTimestampAsync(){}hasFeatureAsync(){}hasFeature(){}getInstanceCount(e){const{object:t,geometry:s}=e;return s.isInstancedBufferGeometry?s.instanceCount:t.count>1?t.count:1}getDrawingBufferSize(){return EP=EP||new Qs,this.renderer.getDrawingBufferSize(EP)}getScissor(){return BP=BP||new Ti,this.renderer.getScissor(BP)}setScissorTest(){}getClearColor(){const e=this.renderer;return IP=IP||new ZI,e.getClearColor(IP),IP.getRGB(IP,this.renderer.currentColorSpace),IP}getDomElement(){let t=this.domElement;return null===t&&(t=void 0!==this.parameters.canvas?this.parameters.canvas:ni(),"setAttribute"in t&&t.setAttribute("data-engine",`three.js r${e} webgpu`),this.domElement=t),t}set(e,t){this.data.set(e,t)}get(e){let t=this.data.get(e);return void 0===t&&(t={},this.data.set(e,t)),t}has(e){return this.data.has(e)}delete(e){this.data.delete(e)}}let FP=0;class zP{constructor(e,t){this.buffers=[e.bufferGPU,t],this.type=e.type,this.bufferType=e.bufferType,this.pbo=e.pbo,this.byteLength=e.byteLength,this.bytesPerElement=e.BYTES_PER_ELEMENT,this.version=e.version,this.isInteger=e.isInteger,this.activeBufferIndex=0,this.baseId=e.id}get id(){return`${this.baseId}|${this.activeBufferIndex}`}get bufferGPU(){return this.buffers[this.activeBufferIndex]}get transformBuffer(){return this.buffers[1^this.activeBufferIndex]}switchBuffers(){this.activeBufferIndex^=1}}class UP{constructor(e){this.backend=e}createAttribute(e,t){const s=this.backend,{gl:i}=s,r=e.array,n=e.usage||i.STATIC_DRAW,o=e.isInterleavedBufferAttribute?e.data:e,a=s.get(o);let h,u=a.bufferGPU;if(void 0===u&&(u=this._createBuffer(i,t,r,n),a.bufferGPU=u,a.bufferType=t,a.version=o.version),r instanceof Float32Array)h=i.FLOAT;else if(r instanceof Uint16Array)h=e.isFloat16BufferAttribute?i.HALF_FLOAT:i.UNSIGNED_SHORT;else if(r instanceof Int16Array)h=i.SHORT;else if(r instanceof Uint32Array)h=i.UNSIGNED_INT;else if(r instanceof Int32Array)h=i.INT;else if(r instanceof Int8Array)h=i.BYTE;else if(r instanceof Uint8Array)h=i.UNSIGNED_BYTE;else{if(!(r instanceof Uint8ClampedArray))throw new Error("THREE.WebGLBackend: Unsupported buffer data format: "+r);h=i.UNSIGNED_BYTE}let l={bufferGPU:u,bufferType:t,type:h,byteLength:r.byteLength,bytesPerElement:r.BYTES_PER_ELEMENT,version:e.version,pbo:e.pbo,isInteger:h===i.INT||h===i.UNSIGNED_INT||e.gpuType===Ee,id:FP++};if(e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute){const e=this._createBuffer(i,t,r,n);l=new zP(l,e)}s.set(e,l)}updateAttribute(e){const t=this.backend,{gl:s}=t,i=e.array,r=e.isInterleavedBufferAttribute?e.data:e,n=t.get(r),o=n.bufferType,a=e.isInterleavedBufferAttribute?e.data.updateRanges:e.updateRanges;if(s.bindBuffer(o,n.bufferGPU),0===a.length)s.bufferSubData(o,0,i);else{for(let e=0,t=a.length;e1?this.enable(s.SAMPLE_ALPHA_TO_COVERAGE):this.disable(s.SAMPLE_ALPHA_TO_COVERAGE)}setPolygonOffset(e,t,s){const{gl:i}=this;e?(this.enable(i.POLYGON_OFFSET_FILL),this.currentPolygonOffsetFactor===t&&this.currentPolygonOffsetUnits===s||(i.polygonOffset(t,s),this.currentPolygonOffsetFactor=t,this.currentPolygonOffsetUnits=s)):this.disable(i.POLYGON_OFFSET_FILL)}useProgram(e){return this.currentProgram!==e&&(this.gl.useProgram(e),this.currentProgram=e,!0)}bindFramebuffer(e,t){const{gl:s,currentBoundFramebuffers:i}=this;return i[e]!==t&&(s.bindFramebuffer(e,t),i[e]=t,e===s.DRAW_FRAMEBUFFER&&(i[s.FRAMEBUFFER]=t),e===s.FRAMEBUFFER&&(i[s.DRAW_FRAMEBUFFER]=t),!0)}drawBuffers(e,t){const{gl:s}=this;let i=[],r=!1;if(null!==e.textures){i=this.currentDrawbuffers.get(t),void 0===i&&(i=[],this.currentDrawbuffers.set(t,i));const n=e.textures;if(i.length!==n.length||i[0]!==s.COLOR_ATTACHMENT0){for(let e=0,t=n.length;e{!function r(){const n=e.clientWaitSync(t,e.SYNC_FLUSH_COMMANDS_BIT,0);if(n===e.WAIT_FAILED)return e.deleteSync(t),void i();n!==e.TIMEOUT_EXPIRED?(e.deleteSync(t),s()):requestAnimationFrame(r)}()}))}}let GP,WP,jP,HP=!1;class qP{constructor(e){this.backend=e,this.gl=e.gl,this.extensions=e.extensions,this.defaultTextures={},!1===HP&&(this._init(this.gl),HP=!0)}_init(e){GP={[pe]:e.REPEAT,[me]:e.CLAMP_TO_EDGE,[ge]:e.MIRRORED_REPEAT},WP={[fe]:e.NEAREST,[ye]:e.NEAREST_MIPMAP_NEAREST,[be]:e.NEAREST_MIPMAP_LINEAR,[Te]:e.LINEAR,[_e]:e.LINEAR_MIPMAP_NEAREST,[Se]:e.LINEAR_MIPMAP_LINEAR},jP={512:e.NEVER,519:e.ALWAYS,[Ts]:e.LESS,515:e.LEQUAL,514:e.EQUAL,518:e.GEQUAL,516:e.GREATER,517:e.NOTEQUAL}}filterFallback(e){const{gl:t}=this;return e===fe||e===ye||e===be?t.NEAREST:t.LINEAR}getGLTextureType(e){const{gl:t}=this;let s;return s=!0===e.isCubeTexture?t.TEXTURE_CUBE_MAP:!0===e.isDataArrayTexture||!0===e.isCompressedArrayTexture?t.TEXTURE_2D_ARRAY:!0===e.isData3DTexture?t.TEXTURE_3D:t.TEXTURE_2D,s}getInternalFormat(e,t,s,i,r=!1){const{gl:n,extensions:o}=this;if(null!==e){if(void 0!==n[e])return n[e];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+e+"'")}let a=t;return t===n.RED&&(s===n.FLOAT&&(a=n.R32F),s===n.HALF_FLOAT&&(a=n.R16F),s===n.UNSIGNED_BYTE&&(a=n.R8),s===n.UNSIGNED_SHORT&&(a=n.R16),s===n.UNSIGNED_INT&&(a=n.R32UI),s===n.BYTE&&(a=n.R8I),s===n.SHORT&&(a=n.R16I),s===n.INT&&(a=n.R32I)),t===n.RED_INTEGER&&(s===n.UNSIGNED_BYTE&&(a=n.R8UI),s===n.UNSIGNED_SHORT&&(a=n.R16UI),s===n.UNSIGNED_INT&&(a=n.R32UI),s===n.BYTE&&(a=n.R8I),s===n.SHORT&&(a=n.R16I),s===n.INT&&(a=n.R32I)),t===n.RG&&(s===n.FLOAT&&(a=n.RG32F),s===n.HALF_FLOAT&&(a=n.RG16F),s===n.UNSIGNED_BYTE&&(a=n.RG8),s===n.UNSIGNED_SHORT&&(a=n.RG16),s===n.UNSIGNED_INT&&(a=n.RG32UI),s===n.BYTE&&(a=n.RG8I),s===n.SHORT&&(a=n.RG16I),s===n.INT&&(a=n.RG32I)),t===n.RG_INTEGER&&(s===n.UNSIGNED_BYTE&&(a=n.RG8UI),s===n.UNSIGNED_SHORT&&(a=n.RG16UI),s===n.UNSIGNED_INT&&(a=n.RG32UI),s===n.BYTE&&(a=n.RG8I),s===n.SHORT&&(a=n.RG16I),s===n.INT&&(a=n.RG32I)),t===n.RGB&&(s===n.FLOAT&&(a=n.RGB32F),s===n.HALF_FLOAT&&(a=n.RGB16F),s===n.UNSIGNED_BYTE&&(a=n.RGB8),s===n.UNSIGNED_SHORT&&(a=n.RGB16),s===n.UNSIGNED_INT&&(a=n.RGB32UI),s===n.BYTE&&(a=n.RGB8I),s===n.SHORT&&(a=n.RGB16I),s===n.INT&&(a=n.RGB32I),s===n.UNSIGNED_BYTE&&(a=i===Zt&&!1===r?n.SRGB8:n.RGB8),s===n.UNSIGNED_SHORT_5_6_5&&(a=n.RGB565),s===n.UNSIGNED_SHORT_5_5_5_1&&(a=n.RGB5_A1),s===n.UNSIGNED_SHORT_4_4_4_4&&(a=n.RGB4),s===n.UNSIGNED_INT_5_9_9_9_REV&&(a=n.RGB9_E5)),t===n.RGB_INTEGER&&(s===n.UNSIGNED_BYTE&&(a=n.RGB8UI),s===n.UNSIGNED_SHORT&&(a=n.RGB16UI),s===n.UNSIGNED_INT&&(a=n.RGB32UI),s===n.BYTE&&(a=n.RGB8I),s===n.SHORT&&(a=n.RGB16I),s===n.INT&&(a=n.RGB32I)),t===n.RGBA&&(s===n.FLOAT&&(a=n.RGBA32F),s===n.HALF_FLOAT&&(a=n.RGBA16F),s===n.UNSIGNED_BYTE&&(a=n.RGBA8),s===n.UNSIGNED_SHORT&&(a=n.RGBA16),s===n.UNSIGNED_INT&&(a=n.RGBA32UI),s===n.BYTE&&(a=n.RGBA8I),s===n.SHORT&&(a=n.RGBA16I),s===n.INT&&(a=n.RGBA32I),s===n.UNSIGNED_BYTE&&(a=i===Zt&&!1===r?n.SRGB8_ALPHA8:n.RGBA8),s===n.UNSIGNED_SHORT_4_4_4_4&&(a=n.RGBA4),s===n.UNSIGNED_SHORT_5_5_5_1&&(a=n.RGB5_A1)),t===n.RGBA_INTEGER&&(s===n.UNSIGNED_BYTE&&(a=n.RGBA8UI),s===n.UNSIGNED_SHORT&&(a=n.RGBA16UI),s===n.UNSIGNED_INT&&(a=n.RGBA32UI),s===n.BYTE&&(a=n.RGBA8I),s===n.SHORT&&(a=n.RGBA16I),s===n.INT&&(a=n.RGBA32I)),t===n.DEPTH_COMPONENT&&(s===n.UNSIGNED_INT&&(a=n.DEPTH24_STENCIL8),s===n.FLOAT&&(a=n.DEPTH_COMPONENT32F)),t===n.DEPTH_STENCIL&&s===n.UNSIGNED_INT_24_8&&(a=n.DEPTH24_STENCIL8),a!==n.R16F&&a!==n.R32F&&a!==n.RG16F&&a!==n.RG32F&&a!==n.RGBA16F&&a!==n.RGBA32F||o.get("EXT_color_buffer_float"),a}setTextureParameters(e,t){const{gl:s,extensions:i,backend:r}=this;s.pixelStorei(s.UNPACK_FLIP_Y_WEBGL,t.flipY),s.pixelStorei(s.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),s.pixelStorei(s.UNPACK_ALIGNMENT,t.unpackAlignment),s.pixelStorei(s.UNPACK_COLORSPACE_CONVERSION_WEBGL,s.NONE),s.texParameteri(e,s.TEXTURE_WRAP_S,GP[t.wrapS]),s.texParameteri(e,s.TEXTURE_WRAP_T,GP[t.wrapT]),e!==s.TEXTURE_3D&&e!==s.TEXTURE_2D_ARRAY||s.texParameteri(e,s.TEXTURE_WRAP_R,GP[t.wrapR]),s.texParameteri(e,s.TEXTURE_MAG_FILTER,WP[t.magFilter]);const n=void 0!==t.mipmaps&&t.mipmaps.length>0,o=t.minFilter===Te&&n?Se:t.minFilter;if(s.texParameteri(e,s.TEXTURE_MIN_FILTER,WP[o]),t.compareFunction&&(s.texParameteri(e,s.TEXTURE_COMPARE_MODE,s.COMPARE_REF_TO_TEXTURE),s.texParameteri(e,s.TEXTURE_COMPARE_FUNC,jP[t.compareFunction])),!0===i.has("EXT_texture_filter_anisotropic")){if(t.magFilter===fe)return;if(t.minFilter!==be&&t.minFilter!==Se)return;if(t.type===Ie&&!1===i.has("OES_texture_float_linear"))return;if(t.anisotropy>1){const n=i.get("EXT_texture_filter_anisotropic");s.texParameterf(e,n.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(t.anisotropy,r.getMaxAnisotropy()))}}}createDefaultTexture(e){const{gl:t,backend:s,defaultTextures:i}=this,r=this.getGLTextureType(e);let n=i[r];void 0===n&&(n=t.createTexture(),s.state.bindTexture(r,n),t.texParameteri(r,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(r,t.TEXTURE_MAG_FILTER,t.NEAREST),i[r]=n),s.set(e,{textureGPU:n,glTextureType:r,isDefault:!0})}createTexture(e,t){const{gl:s,backend:i}=this,{levels:r,width:n,height:o,depth:a}=t,h=i.utils.convert(e.format,e.colorSpace),u=i.utils.convert(e.type),l=this.getInternalFormat(e.internalFormat,h,u,e.colorSpace,e.isVideoTexture),c=s.createTexture(),d=this.getGLTextureType(e);i.state.bindTexture(d,c),this.setTextureParameters(d,e),e.isDataArrayTexture||e.isCompressedArrayTexture?s.texStorage3D(s.TEXTURE_2D_ARRAY,r,l,n,o,a):e.isData3DTexture?s.texStorage3D(s.TEXTURE_3D,r,l,n,o,a):e.isVideoTexture||s.texStorage2D(d,r,l,n,o),i.set(e,{textureGPU:c,glTextureType:d,glFormat:h,glType:u,glInternalFormat:l})}copyBufferToTexture(e,t){const{gl:s,backend:i}=this,{textureGPU:r,glTextureType:n,glFormat:o,glType:a}=i.get(t),{width:h,height:u}=t.source.data;s.bindBuffer(s.PIXEL_UNPACK_BUFFER,e),i.state.bindTexture(n,r),s.pixelStorei(s.UNPACK_FLIP_Y_WEBGL,!1),s.pixelStorei(s.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),s.texSubImage2D(n,0,0,0,h,u,o,a,0),s.bindBuffer(s.PIXEL_UNPACK_BUFFER,null),i.state.unbindTexture()}updateTexture(e,t){const{gl:s}=this,{width:i,height:r}=t,{textureGPU:n,glTextureType:o,glFormat:a,glType:h,glInternalFormat:u}=this.backend.get(e);if(e.isRenderTargetTexture||void 0===n)return;const l=e=>e.isDataTexture?e.image.data:e instanceof ImageBitmap||e instanceof OffscreenCanvas||e instanceof HTMLImageElement||e instanceof HTMLCanvasElement?e:e.data;if(this.backend.state.bindTexture(o,n),this.setTextureParameters(o,e),e.isCompressedTexture){const i=e.mipmaps,r=t.image;for(let t=0;t0,c=t.renderTarget?t.renderTarget.height:this.backend.gerDrawingBufferSize().y;if(l){const s=0!==o||0!==a;let l,d;if(!0===e.isDepthTexture?(l=i.DEPTH_BUFFER_BIT,d=i.DEPTH_ATTACHMENT,t.stencil&&(l|=i.STENCIL_BUFFER_BIT)):(l=i.COLOR_BUFFER_BIT,d=i.COLOR_ATTACHMENT0),s){const e=this.backend.get(t.renderTarget),s=e.framebuffers[t.getCacheKey()],d=e.msaaFrameBuffer;r.bindFramebuffer(i.DRAW_FRAMEBUFFER,s),r.bindFramebuffer(i.READ_FRAMEBUFFER,d);const p=c-a-u;i.blitFramebuffer(o,p,o+h,p+u,o,p,o+h,p+u,l,i.NEAREST),r.bindFramebuffer(i.READ_FRAMEBUFFER,s),r.bindTexture(i.TEXTURE_2D,n),i.copyTexSubImage2D(i.TEXTURE_2D,0,0,0,o,p,h,u),r.unbindTexture()}else{const e=i.createFramebuffer();r.bindFramebuffer(i.DRAW_FRAMEBUFFER,e),i.framebufferTexture2D(i.DRAW_FRAMEBUFFER,d,i.TEXTURE_2D,n,0),i.blitFramebuffer(0,0,h,u,0,0,h,u,l,i.NEAREST),i.deleteFramebuffer(e)}}else r.bindTexture(i.TEXTURE_2D,n),i.copyTexSubImage2D(i.TEXTURE_2D,0,0,0,o,c-u-a,h,u),r.unbindTexture();e.generateMipmaps&&this.generateMipmaps(e),this.backend._setFramebuffer(t)}setupRenderBufferStorage(e,t){const{gl:s}=this,i=t.renderTarget,{samples:r,depthTexture:n,depthBuffer:o,stencilBuffer:a,width:h,height:u}=i;if(s.bindRenderbuffer(s.RENDERBUFFER,e),o&&!a){let t=s.DEPTH_COMPONENT24;r>0?(n&&n.isDepthTexture&&n.type===s.FLOAT&&(t=s.DEPTH_COMPONENT32F),s.renderbufferStorageMultisample(s.RENDERBUFFER,r,t,h,u)):s.renderbufferStorage(s.RENDERBUFFER,t,h,u),s.framebufferRenderbuffer(s.FRAMEBUFFER,s.DEPTH_ATTACHMENT,s.RENDERBUFFER,e)}else o&&a&&(r>0?s.renderbufferStorageMultisample(s.RENDERBUFFER,r,s.DEPTH24_STENCIL8,h,u):s.renderbufferStorage(s.RENDERBUFFER,s.DEPTH_STENCIL,h,u),s.framebufferRenderbuffer(s.FRAMEBUFFER,s.DEPTH_STENCIL_ATTACHMENT,s.RENDERBUFFER,e))}async copyTextureToBuffer(e,t,s,i,r,n){const{backend:o,gl:a}=this,{textureGPU:h,glFormat:u,glType:l}=this.backend.get(e),c=a.createFramebuffer();a.bindFramebuffer(a.READ_FRAMEBUFFER,c);const d=e.isCubeTexture?a.TEXTURE_CUBE_MAP_POSITIVE_X+n:a.TEXTURE_2D;a.framebufferTexture2D(a.READ_FRAMEBUFFER,a.COLOR_ATTACHMENT0,d,h,0);const p=this._getTypedArrayType(l),m=i*r*this._getBytesPerTexel(l,u),g=a.createBuffer();a.bindBuffer(a.PIXEL_PACK_BUFFER,g),a.bufferData(a.PIXEL_PACK_BUFFER,m,a.STREAM_READ),a.readPixels(t,s,i,r,u,l,0),a.bindBuffer(a.PIXEL_PACK_BUFFER,null),await o.utils._clientWaitAsync();const f=new p(m/p.BYTES_PER_ELEMENT);return a.bindBuffer(a.PIXEL_PACK_BUFFER,g),a.getBufferSubData(a.PIXEL_PACK_BUFFER,0,f),a.bindBuffer(a.PIXEL_PACK_BUFFER,null),a.deleteFramebuffer(c),f}_getTypedArrayType(e){const{gl:t}=this;if(e===t.UNSIGNED_BYTE)return Uint8Array;if(e===t.UNSIGNED_SHORT_4_4_4_4)return Uint16Array;if(e===t.UNSIGNED_SHORT_5_5_5_1)return Uint16Array;if(e===t.UNSIGNED_SHORT_5_6_5)return Uint16Array;if(e===t.UNSIGNED_SHORT)return Uint16Array;if(e===t.UNSIGNED_INT)return Uint32Array;if(e===t.HALF_FLOAT)return Uint16Array;if(e===t.FLOAT)return Float32Array;throw new Error(`Unsupported WebGL type: ${e}`)}_getBytesPerTexel(e,t){const{gl:s}=this;let i=0;return e===s.UNSIGNED_BYTE&&(i=1),e!==s.UNSIGNED_SHORT_4_4_4_4&&e!==s.UNSIGNED_SHORT_5_5_5_1&&e!==s.UNSIGNED_SHORT_5_6_5&&e!==s.UNSIGNED_SHORT&&e!==s.HALF_FLOAT||(i=2),e!==s.UNSIGNED_INT&&e!==s.FLOAT||(i=4),t===s.RGBA?4*i:t===s.RGB?3*i:t===s.ALPHA?i:void 0}}class $P{constructor(e){this.backend=e,this.gl=this.backend.gl,this.availableExtensions=this.gl.getSupportedExtensions(),this.extensions={}}get(e){let t=this.extensions[e];return void 0===t&&(t=this.gl.getExtension(e),this.extensions[e]=t),t}has(e){return this.availableExtensions.includes(e)}}class XP{constructor(e){this.backend=e,this.maxAnisotropy=null}getMaxAnisotropy(){if(null!==this.maxAnisotropy)return this.maxAnisotropy;const e=this.backend.gl,t=this.backend.extensions;if(!0===t.has("EXT_texture_filter_anisotropic")){const s=t.get("EXT_texture_filter_anisotropic");this.maxAnisotropy=e.getParameter(s.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else this.maxAnisotropy=0;return this.maxAnisotropy}}const YP={WEBGL_multi_draw:"WEBGL_multi_draw",WEBGL_compressed_texture_astc:"texture-compression-astc",WEBGL_compressed_texture_etc:"texture-compression-etc2",WEBGL_compressed_texture_etc1:"texture-compression-etc1",WEBGL_compressed_texture_pvrtc:"texture-compression-pvrtc",WEBKIT_WEBGL_compressed_texture_pvrtc:"texture-compression-pvrtc",WEBGL_compressed_texture_s3tc:"texture-compression-bc",EXT_texture_compression_bptc:"texture-compression-bptc",EXT_disjoint_timer_query_webgl2:"timestamp-query"};class ZP{constructor(e){this.gl=e.gl,this.extensions=e.extensions,this.info=e.renderer.info,this.mode=null,this.index=0,this.type=null,this.object=null}render(e,t){const{gl:s,mode:i,object:r,type:n,info:o,index:a}=this;0!==a?s.drawElements(i,t,n,e):s.drawArrays(i,e,t),o.update(r,t,i,1)}renderInstances(e,t,s){const{gl:i,mode:r,type:n,index:o,object:a,info:h}=this;0!==s&&(0!==o?i.drawElementsInstanced(r,t,n,e,s):i.drawArraysInstanced(r,e,t,s),h.update(a,t,r,s))}renderMultiDraw(e,t,s){const{extensions:i,mode:r,object:n,info:o}=this;if(0===s)return;const a=i.get("WEBGL_multi_draw");if(null===a)for(let i=0;i0)){const e=t.queryQueue.shift();this.initTimestampQuery(e)}}async resolveTimestampAsync(e,t="render"){if(!this.disjoint||!this.trackTimestamp)return;const s=this.get(e);s.gpuQueries||(s.gpuQueries=[]);for(let e=0;e0&&(s.currentOcclusionQueries=s.occlusionQueries,s.currentOcclusionQueryObjects=s.occlusionQueryObjects,s.lastOcclusionObject=null,s.occlusionQueries=new Array(i),s.occlusionQueryObjects=new Array(i),s.occlusionQueryIndex=0)}finishRender(e){const{gl:t,state:s}=this,i=this.get(e),r=i.previousContext,n=e.occlusionQueryCount;n>0&&(n>i.occlusionQueryIndex&&t.endQuery(t.ANY_SAMPLES_PASSED),this.resolveOccludedAsync(e));const o=e.textures;if(null!==o)for(let e=0;e0){const r=i.framebuffers[e.getCacheKey()],n=t.COLOR_BUFFER_BIT,o=i.msaaFrameBuffer,a=e.textures;s.bindFramebuffer(t.READ_FRAMEBUFFER,o),s.bindFramebuffer(t.DRAW_FRAMEBUFFER,r);for(let s=0;s{let o=0;for(let t=0;t0&&e.add(i[t]),s[t]=null,r.deleteQuery(n),o++))}o1?m.renderInstances(y,g,f):m.render(y,g),o.bindVertexArray(null)}needsRenderUpdate(){return!1}getRenderCacheKey(){return""}createDefaultTexture(e){this.textureUtils.createDefaultTexture(e)}createTexture(e,t){this.textureUtils.createTexture(e,t)}updateTexture(e,t){this.textureUtils.updateTexture(e,t)}generateMipmaps(e){this.textureUtils.generateMipmaps(e)}destroyTexture(e){this.textureUtils.destroyTexture(e)}copyTextureToBuffer(e,t,s,i,r,n){return this.textureUtils.copyTextureToBuffer(e,t,s,i,r,n)}createSampler(){}destroySampler(){}createNodeBuilder(e,t){return new RP(e,t)}createProgram(e){const t=this.gl,{stage:s,code:i}=e,r="fragment"===s?t.createShader(t.FRAGMENT_SHADER):t.createShader(t.VERTEX_SHADER);t.shaderSource(r,i),t.compileShader(r),this.set(e,{shaderGPU:r})}destroyProgram(){console.warn("Abstract class.")}createRenderPipeline(e,t){const s=this.gl,i=e.pipeline,{fragmentProgram:r,vertexProgram:n}=i,o=s.createProgram(),a=this.get(r).shaderGPU,h=this.get(n).shaderGPU;if(s.attachShader(o,a),s.attachShader(o,h),s.linkProgram(o),this.set(i,{programGPU:o,fragmentShader:a,vertexShader:h}),null!==t&&this.parallel){const r=new Promise((t=>{const r=this.parallel,n=()=>{s.getProgramParameter(o,r.COMPLETION_STATUS_KHR)?(this._completeCompile(e,i),t()):requestAnimationFrame(n)};n()}));t.push(r)}else this._completeCompile(e,i)}_handleSource(e,t){const s=e.split("\n"),i=[],r=Math.max(t-6,0),n=Math.min(t+6,s.length);for(let e=r;e":" "} ${r}: ${s[e]}`)}return i.join("\n")}_getShaderErrors(e,t,s){const i=e.getShaderParameter(t,e.COMPILE_STATUS),r=e.getShaderInfoLog(t).trim();if(i&&""===r)return"";const n=/ERROR: 0:(\d+)/.exec(r);if(n){const i=parseInt(n[1]);return s.toUpperCase()+"\n\n"+r+"\n\n"+this._handleSource(e.getShaderSource(t),i)}return r}_logProgramError(e,t,s){if(this.renderer.debug.checkShaderErrors){const i=this.gl,r=i.getProgramInfoLog(e).trim();if(!1===i.getProgramParameter(e,i.LINK_STATUS))if("function"==typeof this.renderer.debug.onShaderError)this.renderer.debug.onShaderError(i,e,s,t);else{const n=this._getShaderErrors(i,s,"vertex"),o=this._getShaderErrors(i,t,"fragment");console.error("THREE.WebGLProgram: Shader Error "+i.getError()+" - VALIDATE_STATUS "+i.getProgramParameter(e,i.VALIDATE_STATUS)+"\n\nProgram Info Log: "+r+"\n"+n+"\n"+o)}else""!==r&&console.warn("THREE.WebGLProgram: Program Info Log:",r)}}_completeCompile(e,t){const{state:s,gl:i}=this,r=this.get(t),{programGPU:n,fragmentShader:o,vertexShader:a}=r;!1===i.getProgramParameter(n,i.LINK_STATUS)&&this._logProgramError(n,o,a),s.useProgram(n);const h=e.getBindings();this._setupBindings(h,n),this.set(t,{programGPU:n})}createComputePipeline(e,t){const{state:s,gl:i}=this,r={stage:"fragment",code:"#version 300 es\nprecision highp float;\nvoid main() {}"};this.createProgram(r);const{computeProgram:n}=e,o=i.createProgram(),a=this.get(r).shaderGPU,h=this.get(n).shaderGPU,u=n.transforms,l=[],c=[];for(let e=0;eYP[t]===e)),s=this.extensions;for(let e=0;e0){if(void 0===l){const i=[];l=t.createFramebuffer(),s.bindFramebuffer(t.FRAMEBUFFER,l);const r=[],u=e.textures;for(let s=0;s,\n\t@location( 0 ) vTex : vec2\n};\n\n@vertex\nfn main( @builtin( vertex_index ) vertexIndex : u32 ) -> VarysStruct {\n\n\tvar Varys : VarysStruct;\n\n\tvar pos = array< vec2, 4 >(\n\t\tvec2( -1.0, 1.0 ),\n\t\tvec2( 1.0, 1.0 ),\n\t\tvec2( -1.0, -1.0 ),\n\t\tvec2( 1.0, -1.0 )\n\t);\n\n\tvar tex = array< vec2, 4 >(\n\t\tvec2( 0.0, 0.0 ),\n\t\tvec2( 1.0, 0.0 ),\n\t\tvec2( 0.0, 1.0 ),\n\t\tvec2( 1.0, 1.0 )\n\t);\n\n\tVarys.vTex = tex[ vertexIndex ];\n\tVarys.Position = vec4( pos[ vertexIndex ], 0.0, 1.0 );\n\n\treturn Varys;\n\n}\n"}),this.mipmapFragmentShaderModule=e.createShaderModule({label:"mipmapFragment",code:"\n@group( 0 ) @binding( 0 )\nvar imgSampler : sampler;\n\n@group( 0 ) @binding( 1 )\nvar img : texture_2d;\n\n@fragment\nfn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 {\n\n\treturn textureSample( img, imgSampler, vTex );\n\n}\n"}),this.flipYFragmentShaderModule=e.createShaderModule({label:"flipYFragment",code:"\n@group( 0 ) @binding( 0 )\nvar imgSampler : sampler;\n\n@group( 0 ) @binding( 1 )\nvar img : texture_2d;\n\n@fragment\nfn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 {\n\n\treturn textureSample( img, imgSampler, vec2( vTex.x, 1.0 - vTex.y ) );\n\n}\n"})}getTransferPipeline(e){let t=this.transferPipelines[e];return void 0===t&&(t=this.device.createRenderPipeline({label:`mipmap-${e}`,vertex:{module:this.mipmapVertexShaderModule,entryPoint:"main"},fragment:{module:this.mipmapFragmentShaderModule,entryPoint:"main",targets:[{format:e}]},primitive:{topology:CN,stripIndexFormat:HN},layout:"auto"}),this.transferPipelines[e]=t),t}getFlipYPipeline(e){let t=this.flipYPipelines[e];return void 0===t&&(t=this.device.createRenderPipeline({label:`flipY-${e}`,vertex:{module:this.mipmapVertexShaderModule,entryPoint:"main"},fragment:{module:this.flipYFragmentShaderModule,entryPoint:"main",targets:[{format:e}]},primitive:{topology:CN,stripIndexFormat:HN},layout:"auto"}),this.flipYPipelines[e]=t),t}flipY(e,t,s=0){const i=t.format,{width:r,height:n}=t.size,o=this.getTransferPipeline(i),a=this.getFlipYPipeline(i),h=this.device.createTexture({size:{width:r,height:n,depthOrArrayLayers:1},format:i,usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING}),u=e.createView({baseMipLevel:0,mipLevelCount:1,dimension:OA,baseArrayLayer:s}),l=h.createView({baseMipLevel:0,mipLevelCount:1,dimension:OA,baseArrayLayer:0}),c=this.device.createCommandEncoder({}),d=(e,t,s)=>{const i=e.getBindGroupLayout(0),r=this.device.createBindGroup({layout:i,entries:[{binding:0,resource:this.flipYSampler},{binding:1,resource:t}]}),n=c.beginRenderPass({colorAttachments:[{view:s,loadOp:VN,storeOp:ON,clearValue:[0,0,0,0]}]});n.setPipeline(e),n.setBindGroup(0,r),n.draw(4,1,0,0),n.end()};d(o,u,l),d(a,l,u),this.device.queue.submit([c.finish()]),h.destroy()}generateMipmaps(e,t,s=0){const i=this.get(e);void 0===i.useCount&&(i.useCount=0,i.layers=[]);const r=i.layers[s]||this._mipmapCreateBundles(e,t,s),n=this.device.createCommandEncoder({});this._mipmapRunBundles(n,r),this.device.queue.submit([n.finish()]),0!==i.useCount&&(i.layers[s]=r),i.useCount++}_mipmapCreateBundles(e,t,s){const i=this.getTransferPipeline(t.format),r=i.getBindGroupLayout(0);let n=e.createView({baseMipLevel:0,mipLevelCount:1,dimension:OA,baseArrayLayer:s});const o=[];for(let a=1;a1&&!e.isMultisampleRenderTargetTexture){const e=Object.assign({},p);e.label=e.label+"-msaa",e.sampleCount=l,i.msaaTexture=s.device.createTexture(e)}i.initialized=!0,i.textureDescriptorGPU=p}destroyTexture(e){const t=this.backend,s=t.get(e);s.texture.destroy(),void 0!==s.msaaTexture&&s.msaaTexture.destroy(),t.delete(e)}destroySampler(e){delete this.backend.get(e).sampler}generateMipmaps(e){const t=this.backend.get(e);if(e.isCubeTexture)for(let e=0;e<6;e++)this._generateMipmaps(t.texture,t.textureDescriptorGPU,e);else{const s=e.image.depth||1;for(let e=0;e1;for(let o=0;o]*\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/i,uF=/([a-z_0-9]+)\s*:\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/gi,lF={f32:"float",i32:"int",u32:"uint",bool:"bool","vec2":"vec2","vec2":"ivec2","vec2":"uvec2","vec2":"bvec2",vec2f:"vec2",vec2i:"ivec2",vec2u:"uvec2",vec2b:"bvec2","vec3":"vec3","vec3":"ivec3","vec3":"uvec3","vec3":"bvec3",vec3f:"vec3",vec3i:"ivec3",vec3u:"uvec3",vec3b:"bvec3","vec4":"vec4","vec4":"ivec4","vec4":"uvec4","vec4":"bvec4",vec4f:"vec4",vec4i:"ivec4",vec4u:"uvec4",vec4b:"bvec4","mat2x2":"mat2",mat2x2f:"mat2","mat3x3":"mat3",mat3x3f:"mat3","mat4x4":"mat4",mat4x4f:"mat4",sampler:"sampler",texture_1d:"texture",texture_2d:"texture",texture_2d_array:"texture",texture_multisampled_2d:"cubeTexture",texture_depth_2d:"depthTexture",texture_3d:"texture3D",texture_cube:"cubeTexture",texture_cube_array:"cubeTexture",texture_storage_1d:"storageTexture",texture_storage_2d:"storageTexture",texture_storage_2d_array:"storageTexture",texture_storage_3d:"storageTexture"};class cF extends FI{constructor(e){const{type:t,inputs:s,name:i,inputsCode:r,blockCode:n,outputType:o}=(e=>{const t=(e=e.trim()).match(hF);if(null!==t&&4===t.length){const s=t[2],i=[];let r=null;for(;null!==(r=uF.exec(s));)i.push({name:r[1],type:r[2]});const n=[];for(let e=0;e "+this.outputType:"";return`fn ${e} ( ${this.inputsCode.trim()} ) ${t}`+this.blockCode}}class dF extends PI{parseFunction(e){return new cF(e)}}const pF=self.GPUShaderStage,mF={vertex:pF?pF.VERTEX:1,fragment:pF?pF.FRAGMENT:2,compute:pF?pF.COMPUTE:4},gF={instance:!0,swizzleAssign:!1,storageBuffer:!0},fF={"^^":"tsl_xor"},yF={float:"f32",int:"i32",uint:"u32",bool:"bool",color:"vec3",vec2:"vec2",ivec2:"vec2",uvec2:"vec2",bvec2:"vec2",vec3:"vec3",ivec3:"vec3",uvec3:"vec3",bvec3:"vec3",vec4:"vec4",ivec4:"vec4",uvec4:"vec4",bvec4:"vec4",mat2:"mat2x2",imat2:"mat2x2",umat2:"mat2x2",bmat2:"mat2x2",mat3:"mat3x3",imat3:"mat3x3",umat3:"mat3x3",bmat3:"mat3x3",mat4:"mat4x4",imat4:"mat4x4",umat4:"mat4x4",bmat4:"mat4x4"},xF={tsl_xor:new vS("fn tsl_xor( a : bool, b : bool ) -> bool { return ( a || b ) && !( a && b ); }"),mod_float:new vS("fn tsl_mod_float( x : f32, y : f32 ) -> f32 { return x - y * floor( x / y ); }"),mod_vec2:new vS("fn tsl_mod_vec2( x : vec2f, y : vec2f ) -> vec2f { return x - y * floor( x / y ); }"),mod_vec3:new vS("fn tsl_mod_vec3( x : vec3f, y : vec3f ) -> vec3f { return x - y * floor( x / y ); }"),mod_vec4:new vS("fn tsl_mod_vec4( x : vec4f, y : vec4f ) -> vec4f { return x - y * floor( x / y ); }"),equals_bool:new vS("fn tsl_equals_bool( a : bool, b : bool ) -> bool { return a == b; }"),equals_bvec2:new vS("fn tsl_equals_bvec2( a : vec2f, b : vec2f ) -> vec2 { return vec2( a.x == b.x, a.y == b.y ); }"),equals_bvec3:new vS("fn tsl_equals_bvec3( a : vec3f, b : vec3f ) -> vec3 { return vec3( a.x == b.x, a.y == b.y, a.z == b.z ); }"),equals_bvec4:new vS("fn tsl_equals_bvec4( a : vec4f, b : vec4f ) -> vec4 { return vec4( a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w ); }"),repeatWrapping:new vS("\nfn tsl_repeatWrapping( uv : vec2, dimension : vec2 ) -> vec2 {\n\n\tlet uvScaled = vec2( uv * vec2( dimension ) );\n\n\treturn ( ( uvScaled % dimension ) + dimension ) % dimension;\n\n}\n"),biquadraticTexture:new vS("\nfn tsl_biquadraticTexture( map : texture_2d, coord : vec2f, level : i32 ) -> vec4f {\n\n\tlet iRes = vec2i( textureDimensions( map, level ) );\n\tlet res = vec2f( iRes );\n\n\tlet uvScaled = coord * res;\n\tlet uvWrapping = ( ( uvScaled % res ) + res ) % res;\n\n\t// https://www.shadertoy.com/view/WtyXRy\n\n\tlet uv = uvWrapping - 0.5;\n\tlet iuv = floor( uv );\n\tlet f = fract( uv );\n\n\tlet rg1 = textureLoad( map, vec2i( iuv + vec2( 0.5, 0.5 ) ) % iRes, level );\n\tlet rg2 = textureLoad( map, vec2i( iuv + vec2( 1.5, 0.5 ) ) % iRes, level );\n\tlet rg3 = textureLoad( map, vec2i( iuv + vec2( 0.5, 1.5 ) ) % iRes, level );\n\tlet rg4 = textureLoad( map, vec2i( iuv + vec2( 1.5, 1.5 ) ) % iRes, level );\n\n\treturn mix( mix( rg1, rg2, f.x ), mix( rg3, rg4, f.x ), f.y );\n\n}\n")},bF={dFdx:"dpdx",dFdy:"- dpdy",mod_float:"tsl_mod_float",mod_vec2:"tsl_mod_vec2",mod_vec3:"tsl_mod_vec3",mod_vec4:"tsl_mod_vec4",equals_bool:"tsl_equals_bool",equals_bvec2:"tsl_equals_bvec2",equals_bvec3:"tsl_equals_bvec3",equals_bvec4:"tsl_equals_bvec4",inversesqrt:"inverseSqrt",bitcast:"bitcast"};/Windows/g.test(navigator.userAgent)&&(xF.pow_float=new vS("fn tsl_pow_float( a : f32, b : f32 ) -> f32 { return select( -pow( -a, b ), pow( a, b ), a > 0.0 ); }"),xF.pow_vec2=new vS("fn tsl_pow_vec2( a : vec2f, b : vec2f ) -> vec2f { return vec2f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ) ); }",[xF.pow_float]),xF.pow_vec3=new vS("fn tsl_pow_vec3( a : vec3f, b : vec3f ) -> vec3f { return vec3f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ), tsl_pow_float( a.z, b.z ) ); }",[xF.pow_float]),xF.pow_vec4=new vS("fn tsl_pow_vec4( a : vec4f, b : vec4f ) -> vec4f { return vec4f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ), tsl_pow_float( a.z, b.z ), tsl_pow_float( a.w, b.w ) ); }",[xF.pow_float]),bF.pow_float="tsl_pow_float",bF.pow_vec2="tsl_pow_vec2",bF.pow_vec3="tsl_pow_vec3",bF.pow_vec4="tsl_pow_vec4");let vF="";!0!==/Firefox/g.test(navigator.userAgent)&&(vF+="diagnostic( off, derivative_uniformity );\n");class TF extends xM{constructor(e,t){super(e,t,new dF),this.uniformGroups={},this.builtins={},this.directives={},this.scopedArrays=new Map}needsToWorkingColorSpace(e){return!0===e.isVideoTexture&&e.colorSpace!==Yt}_generateTextureSample(e,t,s,i,r=this.shaderStage){return"fragment"===r?i?`textureSample( ${t}, ${t}_sampler, ${s}, ${i} )`:`textureSample( ${t}, ${t}_sampler, ${s} )`:this.isFilteredTexture(e)?this.generateFilteredTexture(e,t,s):this.generateTextureLod(e,t,s,"0")}_generateVideoSample(e,t,s=this.shaderStage){if("fragment"===s)return`textureSampleBaseClampToEdge( ${e}, ${e}_sampler, vec2( ${t}.x, 1.0 - ${t}.y ) )`;console.error(`WebGPURenderer: THREE.VideoTexture does not support ${s} shader.`)}_generateTextureSampleLevel(e,t,s,i,r,n=this.shaderStage){return"fragment"===n&&!1===this.isUnfilterable(e)?`textureSampleLevel( ${t}, ${t}_sampler, ${s}, ${i} )`:this.isFilteredTexture(e)?this.generateFilteredTexture(e,t,s,i):this.generateTextureLod(e,t,s,i)}generateFilteredTexture(e,t,s,i="0"){return this._include("biquadraticTexture"),`tsl_biquadraticTexture( ${t}, ${s}, i32( ${i} ) )`}generateTextureLod(e,t,s,i="0"){this._include("repeatWrapping");return`textureLoad( ${t}, tsl_repeatWrapping( ${s}, ${!0===e.isMultisampleRenderTargetTexture?`textureDimensions( ${t} )`:`textureDimensions( ${t}, 0 )`} ), i32( ${i} ) )`}generateTextureLoad(e,t,s,i,r="0u"){return i?`textureLoad( ${t}, ${s}, ${i}, ${r} )`:`textureLoad( ${t}, ${s}, ${r} )`}generateTextureStore(e,t,s,i){return`textureStore( ${t}, ${s}, ${i} )`}isUnfilterable(e){return"float"!==this.getComponentTypeFromTexture(e)||!this.isAvailable("float32Filterable")&&!0===e.isDataTexture&&e.type===Ie||!0===e.isMultisampleRenderTargetTexture}generateTexture(e,t,s,i,r=this.shaderStage){let n=null;return n=!0===e.isVideoTexture?this._generateVideoSample(t,s,r):this.isUnfilterable(e)?this.generateTextureLod(e,t,s,"0",i,r):this._generateTextureSample(e,t,s,i,r),n}generateTextureGrad(e,t,s,i,r,n=this.shaderStage){if("fragment"===n)return`textureSampleGrad( ${t}, ${t}_sampler, ${s}, ${i[0]}, ${i[1]} )`;console.error(`WebGPURenderer: THREE.TextureNode.gradient() does not support ${n} shader.`)}generateTextureCompare(e,t,s,i,r,n=this.shaderStage){if("fragment"===n)return`textureSampleCompare( ${t}, ${t}_sampler, ${s}, ${i} )`;console.error(`WebGPURenderer: THREE.DepthTexture.compareFunction() does not support ${n} shader.`)}generateTextureLevel(e,t,s,i,r,n=this.shaderStage){let o=null;return o=!0===e.isVideoTexture?this._generateVideoSample(t,s,n):this._generateTextureSampleLevel(e,t,s,i,r,n),o}generateTextureBias(e,t,s,i,r,n=this.shaderStage){if("fragment"===n)return`textureSampleBias( ${t}, ${t}_sampler, ${s}, ${i} )`;console.error(`WebGPURenderer: THREE.TextureNode.biasNode does not support ${n} shader.`)}getPropertyName(e,t=this.shaderStage){if(!0===e.isNodeVarying&&!0===e.needsInterpolation){if("vertex"===t)return`varyings.${e.name}`}else if(!0===e.isNodeUniform){const t=e.name,s=e.type;return"texture"===s||"cubeTexture"===s||"storageTexture"===s||"texture3D"===s?t:"buffer"===s||"storageBuffer"===s?`NodeBuffer_${e.id}.${t}`:e.groupNode.name+"."+t}return super.getPropertyName(e)}getOutputStructName(){return"output"}_getUniformGroupCount(e){return Object.keys(this.uniforms[e]).length}getFunctionOperator(e){const t=fF[e];return void 0!==t?(this._include(t),t):null}getStorageAccess(e){if(e.isStorageTextureNode)switch(e.access){case RA:return"read";case CA:return"write";default:return"read_write"}else switch(e.access){case NA:return"read_write";case AA:return"read";default:return"write"}}getUniformFromNode(e,t,s,i=null){const r=super.getUniformFromNode(e,t,s,i),n=this.getDataFromNode(e,s,this.globalCache);if(void 0===n.uniformGPU){let i;const o=e.groupNode,a=o.name,h=this.getBindGroupArray(a,s);if("texture"===t||"cubeTexture"===t||"storageTexture"===t||"texture3D"===t){let n=null;if("texture"===t||"storageTexture"===t?n=new _P(r.name,r.node,o,e.access?e.access:null):"cubeTexture"===t?n=new wP(r.name,r.node,o,e.access?e.access:null):"texture3D"===t&&(n=new SP(r.name,r.node,o,e.access?e.access:null)),n.store=!0===e.isStorageTextureNode,n.setVisibility(mF[s]),"fragment"===s&&!1===this.isUnfilterable(e.value)&&!1===n.store){const e=new QP(`${r.name}_sampler`,r.node,o);e.setVisibility(mF[s]),h.push(e,n),i=[e,n]}else h.push(n),i=[n]}else if("buffer"===t||"storageBuffer"===t){const r=new("storageBuffer"===t?sF:fP)(e,o);r.setVisibility(mF[s]),h.push(r),i=r}else{const e=this.uniformGroups[s]||(this.uniformGroups[s]={});let n=e[a];void 0===n&&(n=new bP(a,o),n.setVisibility(mF[s]),e[a]=n,h.push(n)),i=this.getNodeUniform(r,t),n.addUniform(i)}n.uniformGPU=i}return r}getBuiltin(e,t,s,i=this.shaderStage){const r=this.builtins[i]||(this.builtins[i]=new Map);return!1===r.has(e)&&r.set(e,{name:e,property:t,type:s}),t}hasBuiltin(e,t=this.shaderStage){return void 0!==this.builtins[t]&&this.builtins[t].has(e)}getVertexIndex(){return"vertex"===this.shaderStage?this.getBuiltin("vertex_index","vertexIndex","u32","attribute"):"vertexIndex"}buildFunctionCode(e){const t=e.layout,s=this.flowShaderNode(e),i=[];for(const e of t.inputs)i.push(e.name+" : "+this.getType(e.type));let r=`fn ${t.name}( ${i.join(", ")} ) -> ${this.getType(t.type)} {\n${s.vars}\n${s.code}\n`;return s.result&&(r+=`\treturn ${s.result};\n`),r+="\n}\n",r}getInstanceIndex(){return"vertex"===this.shaderStage?this.getBuiltin("instance_index","instanceIndex","u32","attribute"):"instanceIndex"}getInvocationLocalIndex(){return this.getBuiltin("local_invocation_index","invocationLocalIndex","u32","attribute")}getSubgroupSize(){return this.enableSubGroups(),this.getBuiltin("subgroup_size","subgroupSize","u32","attribute")}getInvocationSubgroupIndex(){return this.enableSubGroups(),this.getBuiltin("subgroup_invocation_id","invocationSubgroupIndex","u32","attribute")}getSubgroupIndex(){return this.enableSubGroups(),this.getBuiltin("subgroup_id","subgroupIndex","u32","attribute")}getDrawIndex(){return null}getFrontFacing(){return this.getBuiltin("front_facing","isFront","bool")}getFragCoord(){return this.getBuiltin("position","fragCoord","vec4")+".xy"}getFragDepth(){return"output."+this.getBuiltin("frag_depth","depth","f32","output")}isFlipY(){return!1}enableDirective(e,t=this.shaderStage){(this.directives[t]||(this.directives[t]=new Set)).add(e)}getDirectives(e){const t=[],s=this.directives[e];if(void 0!==s)for(const e of s)t.push(`enable ${e};`);return t.join("\n")}enableSubGroups(){this.enableDirective("subgroups")}enableSubgroupsF16(){this.enableDirective("subgroups-f16")}enableClipDistances(){this.enableDirective("clip_distances")}enableShaderF16(){this.enableDirective("f16")}enableDualSourceBlending(){this.enableDirective("dual_source_blending")}getBuiltins(e){const t=[],s=this.builtins[e];if(void 0!==s)for(const{name:e,property:i,type:r}of s.values())t.push(`@builtin( ${e} ) ${i} : ${r}`);return t.join(",\n\t")}getScopedArray(e,t,s,i){return!1===this.scopedArrays.has(e)&&this.scopedArrays.set(e,{name:e,scope:t,bufferType:s,bufferCount:i}),e}getScopedArrays(e){if("compute"!==e)return;const t=[];for(const{name:e,scope:s,bufferType:i,bufferCount:r}of this.scopedArrays.values()){const n=this.getType(i);t.push(`var<${s}> ${e}: array< ${n}, ${r} >;`)}return t.join("\n")}getAttributes(e){const t=[];if("compute"===e&&(this.getBuiltin("global_invocation_id","id","vec3","attribute"),this.getBuiltin("workgroup_id","workgroupId","vec3","attribute"),this.getBuiltin("local_invocation_id","localId","vec3","attribute"),this.getBuiltin("num_workgroups","numWorkgroups","vec3","attribute"),this.renderer.hasFeature("subgroups")&&(this.enableDirective("subgroups",e),this.getBuiltin("subgroup_size","subgroupSize","u32","attribute"))),"vertex"===e||"compute"===e){const e=this.getBuiltins("attribute");e&&t.push(e);const s=this.getAttributesArray();for(let e=0,i=s.length;e`)}const i=this.getBuiltins("output");return i&&t.push("\t"+i),t.join(",\n")}getStructs(e){const t=[],s=this.structs[e];for(let e=0,i=s.length;e output : ${r};\n\n`)}return t.join("\n\n")}getVar(e,t){return`var ${t} : ${this.getType(e)}`}getVars(e){const t=[],s=this.vars[e];if(void 0!==s)for(const e of s)t.push(`\t${this.getVar(e.type,e.name)};`);return`\n${t.join("\n")}\n`}getVaryings(e){const t=[];if("vertex"===e&&this.getBuiltin("position","Vertex","vec4","vertex"),"vertex"===e||"fragment"===e){const s=this.varyings,i=this.vars[e];for(let r=0;r";else if(!0===t.isDataArrayTexture||!0===t.isCompressedArrayTexture)i="texture_2d_array";else if(!0===t.isDepthTexture)i=`texture_depth${n}_2d`;else if(!0===t.isVideoTexture)i="texture_external";else if(!0===t.isData3DTexture)i="texture_3d";else if(!0===r.node.isStorageTextureNode){i=`texture_storage_2d<${aF(t)}, ${this.getStorageAccess(r.node)}>`}else{i=`texture${n}_2d<${this.getComponentTypeFromTexture(t).charAt(0)}32>`}s.push(`@binding( ${o.binding++} ) @group( ${o.group} ) var ${r.name} : ${i};`)}else if("buffer"===r.type||"storageBuffer"===r.type){const e=r.node,t=this.getType(e.bufferType),s=e.bufferCount,n=s>0?", "+s:"",a=e.isAtomic?`atomic<${t}>`:`${t}`,h=`\t${r.name} : array< ${a}${n} >\n`,u=e.isStorageBufferNode?`storage, ${this.getStorageAccess(e)}`:"uniform";i.push(this._getWGSLStructBinding("NodeBuffer_"+e.id,h,u,o.binding++,o.group))}else{const e=this.getType(this.getVectorType(r.type)),t=r.groupNode.name;(n[t]||(n[t]={index:o.binding++,id:o.group,snippets:[]})).snippets.push(`\t${r.name} : ${e}`)}}for(const e in n){const t=n[e];r.push(this._getWGSLStructBinding(e,t.snippets.join(",\n"),"uniform",t.index,t.id))}let o=s.join("\n");return o+=i.join("\n"),o+=r.join("\n"),o}buildCode(){const e=null!==this.material?{fragment:{},vertex:{}}:{compute:{}};this.sortBindingGroups();for(const t in e){const s=e[t];s.uniforms=this.getUniforms(t),s.attributes=this.getAttributes(t),s.varyings=this.getVaryings(t),s.structs=this.getStructs(t),s.vars=this.getVars(t),s.codes=this.getCodes(t),s.directives=this.getDirectives(t),s.scopedArrays=this.getScopedArrays(t);let i="// code\n\n";i+=this.flowCode[t];const r=this.flowNodes[t],n=r[r.length-1],o=n.outputNode,a=void 0!==o&&!0===o.isOutputStructNode;for(const e of r){const r=this.getFlowData(e),h=e.name;if(h&&(i.length>0&&(i+="\n"),i+=`\t// flow -> ${h}\n\t`),i+=`${r.code}\n\t`,e===n&&"compute"!==t)if(i+="// result\n\n\t","vertex"===t)i+=`varyings.Vertex = ${r.result};`;else if("fragment"===t)if(a)s.returnType=o.nodeType,i+=`return ${r.result};`;else{let e="\t@location(0) color: vec4";const t=this.getBuiltins("output");t&&(e+=",\n\t"+t),s.returnType="OutputStruct",s.structs+=this._getWGSLStruct("OutputStruct",e),s.structs+="\nvar output : OutputStruct;\n\n",i+=`output.color = ${r.result};\n\n\treturn output;`}}s.flow=i}null!==this.material?(this.vertexShader=this._getWGSLVertexCode(e.vertex),this.fragmentShader=this._getWGSLFragmentCode(e.fragment)):this.computeShader=this._getWGSLComputeCode(e.compute,(this.object.workgroupSize||[64]).join(", "))}getMethod(e,t=null){let s;return null!==t&&(s=this._getWGSLMethod(e+"_"+t)),void 0===s&&(s=this._getWGSLMethod(e)),s||e}getType(e){return yF[e]||e}isAvailable(e){let t=gF[e];return void 0===t&&("float32Filterable"===e&&(t=this.renderer.hasFeature("float32-filterable")),gF[e]=t),t}_getWGSLMethod(e){return void 0!==xF[e]&&this._include(e),bF[e]}_include(e){const t=xF[e];return t.build(this),null!==this.currentFunctionNode&&this.currentFunctionNode.includes.push(t),t}_getWGSLVertexCode(e){return`${this.getSignature()}\n// directives\n${e.directives}\n\n// uniforms\n${e.uniforms}\n\n// varyings\n${e.varyings}\nvar varyings : VaryingsStruct;\n\n// codes\n${e.codes}\n\n@vertex\nfn main( ${e.attributes} ) -> VaryingsStruct {\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n\treturn varyings;\n\n}\n`}_getWGSLFragmentCode(e){return`${this.getSignature()}\n// global\n${vF}\n\n// uniforms\n${e.uniforms}\n\n// structs\n${e.structs}\n\n// codes\n${e.codes}\n\n@fragment\nfn main( ${e.varyings} ) -> ${e.returnType} {\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n}\n`}_getWGSLComputeCode(e,t){return`${this.getSignature()}\n// directives\n${e.directives}\n\n// system\nvar instanceIndex : u32;\n\n// locals\n${e.scopedArrays}\n\n// uniforms\n${e.uniforms}\n\n// codes\n${e.codes}\n\n@compute @workgroup_size( ${t} )\nfn main( ${e.attributes} ) {\n\n\t// system\n\tinstanceIndex = id.x + id.y * numWorkgroups.x * u32(${t}) + id.z * numWorkgroups.x * numWorkgroups.y * u32(${t});\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n}\n`}_getWGSLStruct(e,t){return`\nstruct ${e} {\n${t}\n};`}_getWGSLStructBinding(e,t,s,i=0,r=0){const n=e+"Struct";return`${this._getWGSLStruct(n,t)}\n@binding( ${i} ) @group( ${r} )\nvar<${s}> ${e} : ${n};`}}class _F{constructor(e){this.backend=e}getCurrentDepthStencilFormat(e){let t;return null!==e.depthTexture?t=this.getTextureFormatGPU(e.depthTexture):e.depth&&e.stencil?t=qN.Depth24PlusStencil8:e.depth&&(t=qN.Depth24Plus),t}getTextureFormatGPU(e){return this.backend.get(e).format}getCurrentColorFormat(e){let t;return t=null!==e.textures?this.getTextureFormatGPU(e.textures[0]):this.getPreferredCanvasFormat(),t}getCurrentColorSpace(e){return null!==e.textures?e.textures[0].colorSpace:this.backend.renderer.outputColorSpace}getPrimitiveTopology(e,t){return e.isPoints?SN:e.isLineSegments||e.isMesh&&!0===t.wireframe?MN:e.isLine?NN:e.isMesh?AN:void 0}getSampleCount(e){let t=1;return e>1&&(t=Math.pow(2,Math.floor(Math.log2(e))),2===t&&(t=4)),t}getSampleCountRenderContext(e){return null!==e.textures?this.getSampleCount(e.sampleCount):this.getSampleCount(this.backend.renderer.samples)}getPreferredCanvasFormat(){return navigator.userAgent.includes("Quest")?qN.BGRA8Unorm:navigator.gpu.getPreferredCanvasFormat()}}const wF=new Map([[Int8Array,["sint8","snorm8"]],[Uint8Array,["uint8","unorm8"]],[Int16Array,["sint16","snorm16"]],[Uint16Array,["uint16","unorm16"]],[Int32Array,["sint32","snorm32"]],[Uint32Array,["uint32","unorm32"]],[Float32Array,["float32"]]]),SF=new Map([[xn,["float16"]]]),MF=new Map([[Int32Array,"sint32"],[Int16Array,"sint32"],[Uint32Array,"uint32"],[Uint16Array,"uint32"],[Float32Array,"float32"]]);class NF{constructor(e){this.backend=e}createAttribute(e,t){const s=this._getBufferAttribute(e),i=this.backend,r=i.get(s);let n=r.buffer;if(void 0===n){const o=i.device;let a=s.array;if(!1===e.normalized&&(a.constructor===Int16Array||a.constructor===Uint16Array)){const e=new Uint32Array(a.length);for(let t=0;t1},layout:u.createPipelineLayout({bindGroupLayouts:d})};if(null===t)c.pipeline=u.createRenderPipeline(M);else{const e=new Promise((e=>{u.createRenderPipelineAsync(M).then((t=>{c.pipeline=t,e()}))}));t.push(e)}}createBundleEncoder(e){const t=this.backend,{utils:s,device:i}=t,r=s.getCurrentDepthStencilFormat(e),n={label:"renderBundleEncoder",colorFormats:[s.getCurrentColorFormat(e)],depthStencilFormat:r,sampleCount:this._getSampleCount(e)};return i.createRenderBundleEncoder(n)}createComputePipeline(e,t){const s=this.backend,i=s.device,r=s.get(e.computeProgram).module,n=s.get(e),o=[];for(const e of t){const t=s.get(e);o.push(t.layout)}n.pipeline=i.createComputePipeline({compute:r,layout:i.createPipelineLayout({bindGroupLayouts:o})})}_getBlending(e){let t,s;const i=e.blending,r=e.blendSrc,n=e.blendDst,o=e.blendEquation;if(5===i){const i=null!==e.blendSrcAlpha?e.blendSrcAlpha:r,a=null!==e.blendDstAlpha?e.blendDstAlpha:n,h=null!==e.blendEquationAlpha?e.blendEquationAlpha:o;t={srcFactor:this._getBlendFactor(r),dstFactor:this._getBlendFactor(n),operation:this._getBlendOperation(o)},s={srcFactor:this._getBlendFactor(i),dstFactor:this._getBlendFactor(a),operation:this._getBlendOperation(h)}}else{const r=(e,i,r,n)=>{t={srcFactor:e,dstFactor:i,operation:cA},s={srcFactor:r,dstFactor:n,operation:cA}};if(e.premultipliedAlpha)switch(i){case 1:r(QN,iA,QN,iA);break;case 2:r(QN,QN,QN,QN);break;case 3:r(KN,tA,KN,QN);break;case 4:r(KN,eA,KN,sA)}else switch(i){case 1:r(sA,iA,QN,iA);break;case 2:r(sA,QN,sA,QN);break;case 3:r(KN,tA,KN,QN);break;case 4:r(KN,eA,KN,eA)}}if(void 0!==t&&void 0!==s)return{color:t,alpha:s};console.error("THREE.WebGPURenderer: Invalid blending: ",i)}_getBlendFactor(e){let t;switch(e){case 200:t=KN;break;case 201:t=QN;break;case 202:t=eA;break;case 203:t=tA;break;case R:t=sA;break;case E:t=iA;break;case 208:t=rA;break;case 209:t=nA;break;case 206:t=oA;break;case 207:t=aA;break;case 210:t=hA;break;case 211:t=uA;break;case 212:t=lA;break;default:console.error("THREE.WebGPURenderer: Blend factor not supported.",e)}return t}_getStencilCompare(e){let t;const s=e.stencilFunc;switch(s){case 512:t=RN;break;case bs:t=UN;break;case 513:t=EN;break;case 515:t=IN;break;case 514:t=BN;break;case 518:t=zN;break;case 516:t=PN;break;case 517:t=FN;break;default:console.error("THREE.WebGPURenderer: Invalid stencil function.",s)}return t}_getStencilOperation(e){let t;switch(e){case ns:t=xA;break;case 0:t=bA;break;case 7681:t=vA;break;case 5386:t=TA;break;case 7682:t=_A;break;case 7683:t=wA;break;case 34055:t=SA;break;case 34056:t=MA;break;default:console.error("THREE.WebGPURenderer: Invalid stencil operation.",t)}return t}_getBlendOperation(e){let t;switch(e){case v:t=cA;break;case 101:t=dA;break;case 102:t=pA;break;case 103:t=mA;break;case 104:t=gA;break;default:console.error("THREE.WebGPUPipelineUtils: Blend equation not supported.",e)}return t}_getPrimitiveState(e,t,s){const i={},r=this.backend.utils;switch(i.topology=r.getPrimitiveTopology(e,s),null!==t.index&&!0===e.isLine&&!0!==e.isLineSegments&&(i.stripIndexFormat=t.index.array instanceof Uint16Array?jN:HN),s.side){case c:i.frontFace=DN,i.cullMode=WN;break;case d:i.frontFace=DN,i.cullMode=GN;break;case 2:i.frontFace=DN,i.cullMode=kN;break;default:console.error("THREE.WebGPUPipelineUtils: Unknown material.side value.",s.side)}return i}_getColorWriteMask(e){return!0===e.colorWrite?yA:fA}_getDepthCompare(e){let t;if(!1===e.depthTest)t=UN;else{const s=e.depthFunc;switch(s){case 0:t=RN;break;case 1:t=UN;break;case 2:t=EN;break;case 3:t=IN;break;case 4:t=BN;break;case 5:t=zN;break;case 6:t=PN;break;case 7:t=FN;break;default:console.error("THREE.WebGPUPipelineUtils: Invalid depth function.",s)}}return t}}class RF extends PP{constructor(e={}){super(e),this.isWebGPUBackend=!0,this.parameters.alpha=void 0===e.alpha||e.alpha,this.parameters.requiredLimits=void 0===e.requiredLimits?{}:e.requiredLimits,this.trackTimestamp=!0===e.trackTimestamp,this.device=null,this.context=null,this.colorBuffer=null,this.defaultRenderPassdescriptor=null,this.utils=new _F(this),this.attributeUtils=new NF(this),this.bindingUtils=new AF(this),this.pipelineUtils=new CF(this),this.textureUtils=new oF(this),this.occludedResolveCache=new Map}async init(e){await super.init(e);const t=this.parameters;let s;if(void 0===t.device){const e={powerPreference:t.powerPreference},i=await navigator.gpu.requestAdapter(e);if(null===i)throw new Error("WebGPUBackend: Unable to create WebGPU adapter.");const r=Object.values(jA),n=[];for(const e of r)i.features.has(e)&&n.push(e);const o={requiredFeatures:n,requiredLimits:t.requiredLimits};s=await i.requestDevice(o)}else s=t.device;const i=void 0!==t.context?t.context:e.domElement.getContext("webgpu");this.device=s,this.context=i;const r=t.alpha?"premultiplied":"opaque";this.trackTimestamp=this.trackTimestamp&&this.hasFeature(jA.TimestampQuery),this.context.configure({device:this.device,format:this.utils.getPreferredCanvasFormat(),usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.COPY_SRC,alphaMode:r}),this.updateSize()}get coordinateSystem(){return Ds}async getArrayBufferAsync(e){return await this.attributeUtils.getArrayBufferAsync(e)}getContext(){return this.context}_getDefaultRenderPassDescriptor(){let e=this.defaultRenderPassdescriptor;if(null===e){const t=this.renderer;e={colorAttachments:[{view:null}],depthStencilAttachment:{view:this.textureUtils.getDepthBuffer(t.depth,t.stencil).createView()}};const s=e.colorAttachments[0];this.renderer.samples>0?s.view=this.colorBuffer.createView():s.resolveTarget=void 0,this.defaultRenderPassdescriptor=e}const t=e.colorAttachments[0];return this.renderer.samples>0?t.resolveTarget=this.context.getCurrentTexture().createView():t.view=this.context.getCurrentTexture().createView(),e}_getRenderPassDescriptor(e){const t=e.renderTarget,s=this.get(t);let i=s.descriptors;if(void 0===i||s.width!==t.width||s.height!==t.height||s.activeMipmapLevel!==t.activeMipmapLevel||s.samples!==t.samples){i={},s.descriptors=i;const e=()=>{t.removeEventListener("dispose",e),this.delete(t)};t.addEventListener("dispose",e)}const r=e.getCacheKey();let n=i[r];if(void 0===n){const o=e.textures,a=[];for(let t=0;t0&&(t.currentOcclusionQuerySet&&t.currentOcclusionQuerySet.destroy(),t.currentOcclusionQueryBuffer&&t.currentOcclusionQueryBuffer.destroy(),t.currentOcclusionQuerySet=t.occlusionQuerySet,t.currentOcclusionQueryBuffer=t.occlusionQueryBuffer,t.currentOcclusionQueryObjects=t.occlusionQueryObjects,r=s.createQuerySet({type:"occlusion",count:i}),t.occlusionQuerySet=r,t.occlusionQueryIndex=0,t.occlusionQueryObjects=new Array(i),t.lastOcclusionObject=null),n=null===e.textures?this._getDefaultRenderPassDescriptor():this._getRenderPassDescriptor(e),this.initTimestampQuery(e,n),n.occlusionQuerySet=r;const o=n.depthStencilAttachment;if(null!==e.textures){const t=n.colorAttachments;for(let s=0;s0&&t.currentPass.executeBundles(t.renderBundles),s>t.occlusionQueryIndex&&t.currentPass.endOcclusionQuery(),t.currentPass.end(),s>0){const i=8*s;let r=this.occludedResolveCache.get(i);void 0===r&&(r=this.device.createBuffer({size:i,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),this.occludedResolveCache.set(i,r));const n=this.device.createBuffer({size:i,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});t.encoder.resolveQuerySet(t.occlusionQuerySet,0,s,r,0),t.encoder.copyBufferToBuffer(r,0,n,0,i),t.occlusionQueryBuffer=n,this.resolveOccludedAsync(e)}if(this.prepareTimestampBuffer(e,t.encoder),this.device.queue.submit([t.encoder.finish()]),null!==e.textures){const t=e.textures;for(let e=0;eo?(h.x=Math.min(t.dispatchCount,o),h.y=Math.ceil(t.dispatchCount/o)):h.x=t.dispatchCount,r.dispatchWorkgroups(h.x,h.y,h.z)}finishCompute(e){const t=this.get(e);t.passEncoderGPU.end(),this.prepareTimestampBuffer(e,t.cmdEncoderGPU),this.device.queue.submit([t.cmdEncoderGPU.finish()])}draw(e,t){const{object:s,context:i,pipeline:r}=e,n=e.getBindings(),o=this.get(i),a=this.get(r).pipeline,h=o.currentSets,u=o.currentPass,l=e.getDrawParameters();if(null===l)return;h.pipeline!==a&&(u.setPipeline(a),h.pipeline=a);const c=h.bindingGroups;for(let e=0,t=n.length;e1?0:s;u.drawIndexed(t[s],i,e[s]/n,0,o)}}else if(!0===p){const{vertexCount:e,instanceCount:i,firstVertex:r}=l;u.drawIndexed(e,i,r,0,0),t.update(s,e,i)}else{const{vertexCount:e,instanceCount:i,firstVertex:r}=l;u.draw(e,i,r,0),t.update(s,e,i)}}needsRenderUpdate(e){const t=this.get(e),{object:s,material:i}=e,r=this.utils,n=r.getSampleCountRenderContext(e.context),o=r.getCurrentColorSpace(e.context),a=r.getCurrentColorFormat(e.context),h=r.getCurrentDepthStencilFormat(e.context),u=r.getPrimitiveTopology(s,i);let l=!1;return t.material===i&&t.materialVersion===i.version&&t.transparent===i.transparent&&t.blending===i.blending&&t.premultipliedAlpha===i.premultipliedAlpha&&t.blendSrc===i.blendSrc&&t.blendDst===i.blendDst&&t.blendEquation===i.blendEquation&&t.blendSrcAlpha===i.blendSrcAlpha&&t.blendDstAlpha===i.blendDstAlpha&&t.blendEquationAlpha===i.blendEquationAlpha&&t.colorWrite===i.colorWrite&&t.depthWrite===i.depthWrite&&t.depthTest===i.depthTest&&t.depthFunc===i.depthFunc&&t.stencilWrite===i.stencilWrite&&t.stencilFunc===i.stencilFunc&&t.stencilFail===i.stencilFail&&t.stencilZFail===i.stencilZFail&&t.stencilZPass===i.stencilZPass&&t.stencilFuncMask===i.stencilFuncMask&&t.stencilWriteMask===i.stencilWriteMask&&t.side===i.side&&t.alphaToCoverage===i.alphaToCoverage&&t.sampleCount===n&&t.colorSpace===o&&t.colorFormat===a&&t.depthStencilFormat===h&&t.primitiveTopology===u&&t.clippingContextCacheKey===e.clippingContext.cacheKey||(t.material=i,t.materialVersion=i.version,t.transparent=i.transparent,t.blending=i.blending,t.premultipliedAlpha=i.premultipliedAlpha,t.blendSrc=i.blendSrc,t.blendDst=i.blendDst,t.blendEquation=i.blendEquation,t.blendSrcAlpha=i.blendSrcAlpha,t.blendDstAlpha=i.blendDstAlpha,t.blendEquationAlpha=i.blendEquationAlpha,t.colorWrite=i.colorWrite,t.depthWrite=i.depthWrite,t.depthTest=i.depthTest,t.depthFunc=i.depthFunc,t.stencilWrite=i.stencilWrite,t.stencilFunc=i.stencilFunc,t.stencilFail=i.stencilFail,t.stencilZFail=i.stencilZFail,t.stencilZPass=i.stencilZPass,t.stencilFuncMask=i.stencilFuncMask,t.stencilWriteMask=i.stencilWriteMask,t.side=i.side,t.alphaToCoverage=i.alphaToCoverage,t.sampleCount=n,t.colorSpace=o,t.colorFormat=a,t.depthStencilFormat=h,t.primitiveTopology=u,t.clippingContextCacheKey=e.clippingContext.cacheKey,l=!0),l}getRenderCacheKey(e){const{object:t,material:s}=e,i=this.utils,r=e.context;return[s.transparent,s.blending,s.premultipliedAlpha,s.blendSrc,s.blendDst,s.blendEquation,s.blendSrcAlpha,s.blendDstAlpha,s.blendEquationAlpha,s.colorWrite,s.depthWrite,s.depthTest,s.depthFunc,s.stencilWrite,s.stencilFunc,s.stencilFail,s.stencilZFail,s.stencilZPass,s.stencilFuncMask,s.stencilWriteMask,s.side,i.getSampleCountRenderContext(r),i.getCurrentColorSpace(r),i.getCurrentColorFormat(r),i.getCurrentDepthStencilFormat(r),i.getPrimitiveTopology(t,s),e.clippingContext.cacheKey].join()}createSampler(e){this.textureUtils.createSampler(e)}destroySampler(e){this.textureUtils.destroySampler(e)}createDefaultTexture(e){this.textureUtils.createDefaultTexture(e)}createTexture(e,t){this.textureUtils.createTexture(e,t)}updateTexture(e,t){this.textureUtils.updateTexture(e,t)}generateMipmaps(e){this.textureUtils.generateMipmaps(e)}destroyTexture(e){this.textureUtils.destroyTexture(e)}copyTextureToBuffer(e,t,s,i,r,n){return this.textureUtils.copyTextureToBuffer(e,t,s,i,r,n)}initTimestampQuery(e,t){if(!this.trackTimestamp)return;const s=this.get(e);if(!s.timeStampQuerySet){const e=this.device.createQuerySet({type:"timestamp",count:2}),i={querySet:e,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1};Object.assign(t,{timestampWrites:i}),s.timeStampQuerySet=e}}prepareTimestampBuffer(e,t){if(!this.trackTimestamp)return;const s=this.get(e),i=2*BigInt64Array.BYTES_PER_ELEMENT;void 0===s.currentTimestampQueryBuffers&&(s.currentTimestampQueryBuffers={resolveBuffer:this.device.createBuffer({label:"timestamp resolve buffer",size:i,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),resultBuffer:this.device.createBuffer({label:"timestamp result buffer",size:i,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),isMappingPending:!1});const{resolveBuffer:r,resultBuffer:n,isMappingPending:o}=s.currentTimestampQueryBuffers;!0!==o&&(t.resolveQuerySet(s.timeStampQuerySet,0,2,r,0),t.copyBufferToBuffer(r,0,n,0,i))}async resolveTimestampAsync(e,t="render"){if(!this.trackTimestamp)return;const s=this.get(e);if(void 0===s.currentTimestampQueryBuffers)return;const{resultBuffer:i,isMappingPending:r}=s.currentTimestampQueryBuffers;!0!==r&&(s.currentTimestampQueryBuffers.isMappingPending=!0,i.mapAsync(GPUMapMode.READ).then((()=>{const e=new BigUint64Array(i.getMappedRange()),r=Number(e[1]-e[0])/1e6;this.renderer.info.updateTimestamp(t,r),i.unmap(),s.currentTimestampQueryBuffers.isMappingPending=!1})))}createNodeBuilder(e,t){return new TF(e,t)}createProgram(e){this.get(e).module={module:this.device.createShaderModule({code:e.code,label:e.stage}),entryPoint:"main"}}destroyProgram(e){this.delete(e)}createRenderPipeline(e,t){this.pipelineUtils.createRenderPipeline(e,t)}createComputePipeline(e,t){this.pipelineUtils.createComputePipeline(e,t)}beginBundle(e){const t=this.get(e);t._currentPass=t.currentPass,t._currentSets=t.currentSets,t.currentSets={attributes:{},bindingGroups:[],pipeline:null,index:null},t.currentPass=this.pipelineUtils.createBundleEncoder(e)}finishBundle(e,t){const s=this.get(e),i=s.currentPass.finish();this.get(t).bundleGPU=i,s.currentSets=s._currentSets,s.currentPass=s._currentPass}addBundle(e,t){this.get(e).renderBundles.push(this.get(t).bundleGPU)}createBindings(e){this.bindingUtils.createBindings(e)}updateBindings(e){this.bindingUtils.createBindings(e)}updateBinding(e){this.bindingUtils.updateBinding(e)}createIndexAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.INDEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createStorageAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.STORAGE|GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}updateAttribute(e){this.attributeUtils.updateAttribute(e)}destroyAttribute(e){this.attributeUtils.destroyAttribute(e)}updateSize(){this.colorBuffer=this.textureUtils.getColorBuffer(),this.defaultRenderPassdescriptor=null}getMaxAnisotropy(){return 16}hasFeature(e){return this.device.features.has(e)}copyTextureToTexture(e,t,s=null,i=null,r=0){let n=0,o=0,a=0,h=0,u=0,l=0,c=e.image.width,d=e.image.height;null!==s&&(h=s.x,u=s.y,l=s.z||0,c=s.width,d=s.height),null!==i&&(n=i.x,o=i.y,a=i.z||0);const p=this.device.createCommandEncoder({label:"copyTextureToTexture_"+e.id+"_"+t.id}),m=this.get(e).texture,g=this.get(t).texture;p.copyTextureToTexture({texture:m,mipLevel:r,origin:{x:h,y:u,z:l}},{texture:g,mipLevel:r,origin:{x:n,y:o,z:a}},[c,d,1]),this.device.queue.submit([p.finish()])}copyFramebufferToTexture(e,t,s){const i=this.get(t),{encoder:r,descriptor:n}=i;let o=null;o=t.renderTarget?e.isDepthTexture?this.get(t.depthTexture).texture:this.get(t.textures[0]).texture:e.isDepthTexture?this.textureUtils.getDepthBuffer(t.depth,t.stencil):this.context.getCurrentTexture();const a=this.get(e).texture;if(o.format===a.format){i.currentPass.end(),r.copyTextureToTexture({texture:o,origin:{x:s.x,y:s.y,z:0}},{texture:a},[s.z,s.w]),e.generateMipmaps&&this.textureUtils.generateMipmaps(e);for(let e=0;e(console.warn("THREE.WebGPURenderer: WebGPU is not available, running under WebGL2 backend."),new JP(e)));super(new t(e),e),this.nodes.library=new BF,this.isWebGPURenderer=!0}}class PF extends Ga{constructor(){super(),this.isBundleGroup=!0,this.type="BundleGroup",this.static=!0,this.version=0}set needsUpdate(e){!0===e&&this.version++}}const FF=new pT,zF=new dN(FF);class UF{constructor(e,t=Xp(0,0,1,1)){this.renderer=e,this.outputNode=t,this.outputColorTransform=!0,this.needsUpdate=!0,FF.name="PostProcessing"}render(){this.update();const e=this.renderer,t=e.toneMapping,s=e.outputColorSpace;e.toneMapping=0,e.outputColorSpace=Jt,zF.render(e),e.toneMapping=t,e.outputColorSpace=s}update(){if(!0===this.needsUpdate){const e=this.renderer,t=e.toneMapping,s=e.outputColorSpace;zF.material.fragmentNode=!0===this.outputColorTransform?Ty(this.outputNode,t,s):this.outputNode.context({toneMapping:t,outputColorSpace:s}),zF.material.needsUpdate=!0,this.needsUpdate=!1}}async renderAsync(){this.update();const e=this.renderer,t=e.toneMapping,s=e.outputColorSpace;e.toneMapping=0,e.outputColorSpace=Jt,await zF.renderAsync(e),e.toneMapping=t,e.outputColorSpace=s}}class OF extends vi{constructor(e=1,t=1){super(),this.image={width:e,height:t},this.magFilter=Te,this.minFilter=Te,this.isStorageTexture=!0}}class LF extends ln{constructor(e,t,s=Float32Array){!1===ArrayBuffer.isView(e)&&(e=new s(e*t)),super(e,t),this.isStorageBufferAttribute=!0}}class VF extends Do{constructor(e,t,s=Float32Array){!1===ArrayBuffer.isView(e)&&(e=new s(e*t)),super(e,t),this.isStorageInstancedBufferAttribute=!0}}class DF extends tl{constructor(e){super(e),this.textures={},this.nodes={}}load(e,t,s,i){const r=new rl(this.manager);r.setPath(this.path),r.setRequestHeader(this.requestHeader),r.setWithCredentials(this.withCredentials),r.load(e,(s=>{try{t(this.parse(JSON.parse(s)))}catch(t){i?i(t):console.error(t),this.manager.itemError(e)}}),s,i)}parseNodes(e){const t={};if(void 0!==e){for(const s of e){const{uuid:e,type:i}=s;t[e]=this.createNodeFromType(i),t[e].uuid=e}const s={nodes:t,textures:this.textures};for(const i of e){i.meta=s;t[i.uuid].deserialize(i),delete i.meta}}return t}parse(e){const t=this.createNodeFromType(e.type);t.uuid=e.uuid;const s={nodes:this.parseNodes(e.nodes),textures:this.textures};return e.meta=s,t.deserialize(e),delete e.meta,t}setTextures(e){return this.textures=e,this}setNodes(e){return this.nodes=e,this}createNodeFromType(e){return void 0===this.nodes[e]?(console.error("THREE.NodeLoader: Node type not found:",e),Up()):Sp(new this.nodes[e])}}class kF extends Bl{constructor(e){super(e),this.nodes={},this.nodeMaterials={}}parse(e){const t=super.parse(e),s=this.nodes,i=e.inputNodes;for(const e in i){const r=i[e];t[e]=s[r]}return t}setNodes(e){return this.nodes=e,this}setNodeMaterials(e){return this.nodeMaterials=e,this}createMaterialFromType(e){const t=this.nodeMaterials[e];return void 0!==t?new t:super.createMaterialFromType(e)}}class GF extends zl{constructor(e){super(e),this.nodes={},this.nodeMaterials={},this._nodesJSON=null}setNodes(e){return this.nodes=e,this}setNodeMaterials(e){return this.nodeMaterials=e,this}parse(e,t){this._nodesJSON=e.nodes;const s=super.parse(e,t);return this._nodesJSON=null,s}parseNodes(e,t){if(void 0!==e){const s=new DF;return s.setNodes(this.nodes),s.setTextures(t),s.parseNodes(e)}return{}}parseMaterials(e,t){const s={};if(void 0!==e){const i=this.parseNodes(this._nodesJSON,t),r=new kF;r.setTextures(t),r.setNodes(i),r.setNodeMaterials(this.nodeMaterials);for(let t=0,i=e.length;t> 8 & 0xff ] + _lut[ d0 >> 16 & 0xff ] + _lut[ d0 >> 24 & 0xff ] + '-' + + _lut[ d1 & 0xff ] + _lut[ d1 >> 8 & 0xff ] + '-' + _lut[ d1 >> 16 & 0x0f | 0x40 ] + _lut[ d1 >> 24 & 0xff ] + '-' + + _lut[ d2 & 0x3f | 0x80 ] + _lut[ d2 >> 8 & 0xff ] + '-' + _lut[ d2 >> 16 & 0xff ] + _lut[ d2 >> 24 & 0xff ] + + _lut[ d3 & 0xff ] + _lut[ d3 >> 8 & 0xff ] + _lut[ d3 >> 16 & 0xff ] + _lut[ d3 >> 24 & 0xff ]; + + // .toLowerCase() here flattens concatenated strings to save heap memory space. + return uuid.toLowerCase(); + +} + +function clamp$1( value, min, max ) { + + return Math.max( min, Math.min( max, value ) ); + +} + +// compute euclidean modulo of m % n +// https://en.wikipedia.org/wiki/Modulo_operation +function euclideanModulo( n, m ) { + + return ( ( n % m ) + m ) % m; + +} + +// Linear mapping from range to range +function mapLinear( x, a1, a2, b1, b2 ) { + + return b1 + ( x - a1 ) * ( b2 - b1 ) / ( a2 - a1 ); + +} + +// https://www.gamedev.net/tutorials/programming/general-and-gameplay-programming/inverse-lerp-a-super-useful-yet-often-overlooked-function-r5230/ +function inverseLerp( x, y, value ) { + + if ( x !== y ) { + + return ( value - x ) / ( y - x ); + + } else { + + return 0; + + } + +} + +// https://en.wikipedia.org/wiki/Linear_interpolation +function lerp( x, y, t ) { + + return ( 1 - t ) * x + t * y; + +} + +// http://www.rorydriscoll.com/2016/03/07/frame-rate-independent-damping-using-lerp/ +function damp( x, y, lambda, dt ) { + + return lerp( x, y, 1 - Math.exp( - lambda * dt ) ); + +} + +// https://www.desmos.com/calculator/vcsjnyz7x4 +function pingpong( x, length = 1 ) { + + return length - Math.abs( euclideanModulo( x, length * 2 ) - length ); + +} + +// http://en.wikipedia.org/wiki/Smoothstep +function smoothstep$1( x, min, max ) { + + if ( x <= min ) return 0; + if ( x >= max ) return 1; + + x = ( x - min ) / ( max - min ); + + return x * x * ( 3 - 2 * x ); + +} + +function smootherstep( x, min, max ) { + + if ( x <= min ) return 0; + if ( x >= max ) return 1; + + x = ( x - min ) / ( max - min ); + + return x * x * x * ( x * ( x * 6 - 15 ) + 10 ); + +} + +// Random integer from interval +function randInt( low, high ) { + + return low + Math.floor( Math.random() * ( high - low + 1 ) ); + +} + +// Random float from interval +function randFloat( low, high ) { + + return low + Math.random() * ( high - low ); + +} + +// Random float from <-range/2, range/2> interval +function randFloatSpread( range ) { + + return range * ( 0.5 - Math.random() ); + +} + +// Deterministic pseudo-random float in the interval [ 0, 1 ] +function seededRandom( s ) { + + if ( s !== undefined ) _seed = s; + + // Mulberry32 generator + + let t = _seed += 0x6D2B79F5; + + t = Math.imul( t ^ t >>> 15, t | 1 ); + + t ^= t + Math.imul( t ^ t >>> 7, t | 61 ); + + return ( ( t ^ t >>> 14 ) >>> 0 ) / 4294967296; + +} + +function degToRad( degrees ) { + + return degrees * DEG2RAD; + +} + +function radToDeg( radians ) { + + return radians * RAD2DEG; + +} + +function isPowerOfTwo( value ) { + + return ( value & ( value - 1 ) ) === 0 && value !== 0; + +} + +function ceilPowerOfTwo( value ) { + + return Math.pow( 2, Math.ceil( Math.log( value ) / Math.LN2 ) ); + +} + +function floorPowerOfTwo( value ) { + + return Math.pow( 2, Math.floor( Math.log( value ) / Math.LN2 ) ); + +} + +function setQuaternionFromProperEuler( q, a, b, c, order ) { + + // Intrinsic Proper Euler Angles - see https://en.wikipedia.org/wiki/Euler_angles + + // rotations are applied to the axes in the order specified by 'order' + // rotation by angle 'a' is applied first, then by angle 'b', then by angle 'c' + // angles are in radians + + const cos = Math.cos; + const sin = Math.sin; + + const c2 = cos( b / 2 ); + const s2 = sin( b / 2 ); + + const c13 = cos( ( a + c ) / 2 ); + const s13 = sin( ( a + c ) / 2 ); + + const c1_3 = cos( ( a - c ) / 2 ); + const s1_3 = sin( ( a - c ) / 2 ); + + const c3_1 = cos( ( c - a ) / 2 ); + const s3_1 = sin( ( c - a ) / 2 ); + + switch ( order ) { + + case 'XYX': + q.set( c2 * s13, s2 * c1_3, s2 * s1_3, c2 * c13 ); + break; + + case 'YZY': + q.set( s2 * s1_3, c2 * s13, s2 * c1_3, c2 * c13 ); + break; + + case 'ZXZ': + q.set( s2 * c1_3, s2 * s1_3, c2 * s13, c2 * c13 ); + break; + + case 'XZX': + q.set( c2 * s13, s2 * s3_1, s2 * c3_1, c2 * c13 ); + break; + + case 'YXY': + q.set( s2 * c3_1, c2 * s13, s2 * s3_1, c2 * c13 ); + break; + + case 'ZYZ': + q.set( s2 * s3_1, s2 * c3_1, c2 * s13, c2 * c13 ); + break; + + default: + console.warn( 'THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: ' + order ); + + } + +} + +function denormalize( value, array ) { + + switch ( array.constructor ) { + + case Float32Array: + + return value; + + case Uint32Array: + + return value / 4294967295.0; + + case Uint16Array: + + return value / 65535.0; + + case Uint8Array: + + return value / 255.0; + + case Int32Array: + + return Math.max( value / 2147483647.0, - 1.0 ); + + case Int16Array: + + return Math.max( value / 32767.0, - 1.0 ); + + case Int8Array: + + return Math.max( value / 127.0, - 1.0 ); + + default: + + throw new Error( 'Invalid component type.' ); + + } + +} + +function normalize$1( value, array ) { + + switch ( array.constructor ) { + + case Float32Array: + + return value; + + case Uint32Array: + + return Math.round( value * 4294967295.0 ); + + case Uint16Array: + + return Math.round( value * 65535.0 ); + + case Uint8Array: + + return Math.round( value * 255.0 ); + + case Int32Array: + + return Math.round( value * 2147483647.0 ); + + case Int16Array: + + return Math.round( value * 32767.0 ); + + case Int8Array: + + return Math.round( value * 127.0 ); + + default: + + throw new Error( 'Invalid component type.' ); + + } + +} + +const MathUtils = { + DEG2RAD: DEG2RAD, + RAD2DEG: RAD2DEG, + generateUUID: generateUUID, + clamp: clamp$1, + euclideanModulo: euclideanModulo, + mapLinear: mapLinear, + inverseLerp: inverseLerp, + lerp: lerp, + damp: damp, + pingpong: pingpong, + smoothstep: smoothstep$1, + smootherstep: smootherstep, + randInt: randInt, + randFloat: randFloat, + randFloatSpread: randFloatSpread, + seededRandom: seededRandom, + degToRad: degToRad, + radToDeg: radToDeg, + isPowerOfTwo: isPowerOfTwo, + ceilPowerOfTwo: ceilPowerOfTwo, + floorPowerOfTwo: floorPowerOfTwo, + setQuaternionFromProperEuler: setQuaternionFromProperEuler, + normalize: normalize$1, + denormalize: denormalize +}; + +class Vector2 { + + constructor( x = 0, y = 0 ) { + + Vector2.prototype.isVector2 = true; + + this.x = x; + this.y = y; + + } + + get width() { + + return this.x; + + } + + set width( value ) { + + this.x = value; + + } + + get height() { + + return this.y; + + } + + set height( value ) { + + this.y = value; + + } + + set( x, y ) { + + this.x = x; + this.y = y; + + return this; + + } + + setScalar( scalar ) { + + this.x = scalar; + this.y = scalar; + + return this; + + } + + setX( x ) { + + this.x = x; + + return this; + + } + + setY( y ) { + + this.y = y; + + return this; + + } + + setComponent( index, value ) { + + switch ( index ) { + + case 0: this.x = value; break; + case 1: this.y = value; break; + default: throw new Error( 'index is out of range: ' + index ); + + } + + return this; + + } + + getComponent( index ) { + + switch ( index ) { + + case 0: return this.x; + case 1: return this.y; + default: throw new Error( 'index is out of range: ' + index ); + + } + + } + + clone() { + + return new this.constructor( this.x, this.y ); + + } + + copy( v ) { + + this.x = v.x; + this.y = v.y; + + return this; + + } + + add( v ) { + + this.x += v.x; + this.y += v.y; + + return this; + + } + + addScalar( s ) { + + this.x += s; + this.y += s; + + return this; + + } + + addVectors( a, b ) { + + this.x = a.x + b.x; + this.y = a.y + b.y; + + return this; + + } + + addScaledVector( v, s ) { + + this.x += v.x * s; + this.y += v.y * s; + + return this; + + } + + sub( v ) { + + this.x -= v.x; + this.y -= v.y; + + return this; + + } + + subScalar( s ) { + + this.x -= s; + this.y -= s; + + return this; + + } + + subVectors( a, b ) { + + this.x = a.x - b.x; + this.y = a.y - b.y; + + return this; + + } + + multiply( v ) { + + this.x *= v.x; + this.y *= v.y; + + return this; + + } + + multiplyScalar( scalar ) { + + this.x *= scalar; + this.y *= scalar; + + return this; + + } + + divide( v ) { + + this.x /= v.x; + this.y /= v.y; + + return this; + + } + + divideScalar( scalar ) { + + return this.multiplyScalar( 1 / scalar ); + + } + + applyMatrix3( m ) { + + const x = this.x, y = this.y; + const e = m.elements; + + this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ]; + this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ]; + + return this; + + } + + min( v ) { + + this.x = Math.min( this.x, v.x ); + this.y = Math.min( this.y, v.y ); + + return this; + + } + + max( v ) { + + this.x = Math.max( this.x, v.x ); + this.y = Math.max( this.y, v.y ); + + return this; + + } + + clamp( min, max ) { + + // assumes min < max, componentwise + + this.x = Math.max( min.x, Math.min( max.x, this.x ) ); + this.y = Math.max( min.y, Math.min( max.y, this.y ) ); + + return this; + + } + + clampScalar( minVal, maxVal ) { + + this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); + this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); + + return this; + + } + + clampLength( min, max ) { + + const length = this.length(); + + return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); + + } + + floor() { + + this.x = Math.floor( this.x ); + this.y = Math.floor( this.y ); + + return this; + + } + + ceil() { + + this.x = Math.ceil( this.x ); + this.y = Math.ceil( this.y ); + + return this; + + } + + round() { + + this.x = Math.round( this.x ); + this.y = Math.round( this.y ); + + return this; + + } + + roundToZero() { + + this.x = Math.trunc( this.x ); + this.y = Math.trunc( this.y ); + + return this; + + } + + negate() { + + this.x = - this.x; + this.y = - this.y; + + return this; + + } + + dot( v ) { + + return this.x * v.x + this.y * v.y; + + } + + cross( v ) { + + return this.x * v.y - this.y * v.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() { + + // computes the angle in radians with respect to the positive x-axis + + const angle = Math.atan2( - this.y, - this.x ) + Math.PI; + + return angle; + + } + + angleTo( v ) { + + const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); + + if ( denominator === 0 ) return Math.PI / 2; + + const theta = this.dot( v ) / denominator; + + // clamp, to handle numerical problems + + return Math.acos( clamp$1( theta, - 1, 1 ) ); + + } + + distanceTo( v ) { + + return Math.sqrt( this.distanceToSquared( v ) ); + + } + + distanceToSquared( v ) { + + const dx = this.x - v.x, dy = this.y - v.y; + return dx * dx + dy * dy; + + } + + manhattanDistanceTo( v ) { + + return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ); + + } + + setLength( length ) { + + return this.normalize().multiplyScalar( length ); + + } + + lerp( v, alpha ) { + + this.x += ( v.x - this.x ) * alpha; + this.y += ( v.y - this.y ) * alpha; + + return this; + + } + + lerpVectors( v1, v2, alpha ) { + + this.x = v1.x + ( v2.x - v1.x ) * alpha; + this.y = v1.y + ( v2.y - v1.y ) * alpha; + + return this; + + } + + equals( v ) { + + return ( ( v.x === this.x ) && ( v.y === this.y ) ); + + } + + fromArray( array, offset = 0 ) { + + this.x = array[ offset ]; + this.y = array[ offset + 1 ]; + + return this; + + } + + toArray( array = [], offset = 0 ) { + + array[ offset ] = this.x; + array[ offset + 1 ] = this.y; + + return array; + + } + + fromBufferAttribute( attribute, index ) { + + this.x = attribute.getX( index ); + this.y = attribute.getY( index ); + + return this; + + } + + rotateAround( center, angle ) { + + const c = Math.cos( angle ), s = Math.sin( angle ); + + const x = this.x - center.x; + const y = this.y - center.y; + + this.x = x * c - y * s + center.x; + this.y = x * s + y * c + center.y; + + return this; + + } + + random() { + + this.x = Math.random(); + this.y = Math.random(); + + return this; + + } + + *[ Symbol.iterator ]() { + + yield this.x; + yield this.y; + + } + +} + +class Matrix3 { + + constructor( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { + + Matrix3.prototype.isMatrix3 = true; + + this.elements = [ + + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 + + ]; + + if ( n11 !== undefined ) { + + this.set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ); + + } + + } + + set( n11, n12, n13, n21, n22, n23, n31, n32, n33 ) { + + const te = this.elements; + + te[ 0 ] = n11; te[ 1 ] = n21; te[ 2 ] = n31; + te[ 3 ] = n12; te[ 4 ] = n22; te[ 5 ] = n32; + te[ 6 ] = n13; te[ 7 ] = n23; te[ 8 ] = n33; + + return this; + + } + + identity() { + + this.set( + + 1, 0, 0, + 0, 1, 0, + 0, 0, 1 + + ); + + return this; + + } + + copy( m ) { + + const te = this.elements; + const me = m.elements; + + te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; + te[ 3 ] = me[ 3 ]; te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; + te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; te[ 8 ] = me[ 8 ]; + + return this; + + } + + extractBasis( xAxis, yAxis, zAxis ) { + + xAxis.setFromMatrix3Column( this, 0 ); + yAxis.setFromMatrix3Column( this, 1 ); + zAxis.setFromMatrix3Column( this, 2 ); + + return this; + + } + + setFromMatrix4( m ) { + + const me = m.elements; + + this.set( + + me[ 0 ], me[ 4 ], me[ 8 ], + me[ 1 ], me[ 5 ], me[ 9 ], + me[ 2 ], me[ 6 ], me[ 10 ] + + ); + + return this; + + } + + multiply( m ) { + + return this.multiplyMatrices( this, m ); + + } + + premultiply( m ) { + + return this.multiplyMatrices( m, this ); + + } + + multiplyMatrices( a, b ) { + + const ae = a.elements; + const be = b.elements; + const te = this.elements; + + const a11 = ae[ 0 ], a12 = ae[ 3 ], a13 = ae[ 6 ]; + const a21 = ae[ 1 ], a22 = ae[ 4 ], a23 = ae[ 7 ]; + const a31 = ae[ 2 ], a32 = ae[ 5 ], a33 = ae[ 8 ]; + + const b11 = be[ 0 ], b12 = be[ 3 ], b13 = be[ 6 ]; + const b21 = be[ 1 ], b22 = be[ 4 ], b23 = be[ 7 ]; + const b31 = be[ 2 ], b32 = be[ 5 ], b33 = be[ 8 ]; + + te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31; + te[ 3 ] = a11 * b12 + a12 * b22 + a13 * b32; + te[ 6 ] = a11 * b13 + a12 * b23 + a13 * b33; + + te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31; + te[ 4 ] = a21 * b12 + a22 * b22 + a23 * b32; + te[ 7 ] = a21 * b13 + a22 * b23 + a23 * b33; + + te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31; + te[ 5 ] = a31 * b12 + a32 * b22 + a33 * b32; + te[ 8 ] = a31 * b13 + a32 * b23 + a33 * b33; + + return this; + + } + + multiplyScalar( s ) { + + const te = this.elements; + + te[ 0 ] *= s; te[ 3 ] *= s; te[ 6 ] *= s; + te[ 1 ] *= s; te[ 4 ] *= s; te[ 7 ] *= s; + te[ 2 ] *= s; te[ 5 ] *= s; te[ 8 ] *= s; + + return this; + + } + + determinant() { + + const te = this.elements; + + const a = te[ 0 ], b = te[ 1 ], c = te[ 2 ], + d = te[ 3 ], e = te[ 4 ], f = te[ 5 ], + g = te[ 6 ], h = te[ 7 ], i = te[ 8 ]; + + return a * e * i - a * f * h - b * d * i + b * f * g + c * d * h - c * e * g; + + } + + invert() { + + const te = this.elements, + + n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], + n12 = te[ 3 ], n22 = te[ 4 ], n32 = te[ 5 ], + n13 = te[ 6 ], n23 = te[ 7 ], n33 = te[ 8 ], + + t11 = n33 * n22 - n32 * n23, + t12 = n32 * n13 - n33 * n12, + t13 = n23 * n12 - n22 * n13, + + det = n11 * t11 + n21 * t12 + n31 * t13; + + if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + + const detInv = 1 / det; + + te[ 0 ] = t11 * detInv; + te[ 1 ] = ( n31 * n23 - n33 * n21 ) * detInv; + te[ 2 ] = ( n32 * n21 - n31 * n22 ) * detInv; + + te[ 3 ] = t12 * detInv; + te[ 4 ] = ( n33 * n11 - n31 * n13 ) * detInv; + te[ 5 ] = ( n31 * n12 - n32 * n11 ) * detInv; + + te[ 6 ] = t13 * detInv; + te[ 7 ] = ( n21 * n13 - n23 * n11 ) * detInv; + te[ 8 ] = ( n22 * n11 - n21 * n12 ) * detInv; + + return this; + + } + + transpose() { + + let tmp; + const m = this.elements; + + tmp = m[ 1 ]; m[ 1 ] = m[ 3 ]; m[ 3 ] = tmp; + tmp = m[ 2 ]; m[ 2 ] = m[ 6 ]; m[ 6 ] = tmp; + tmp = m[ 5 ]; m[ 5 ] = m[ 7 ]; m[ 7 ] = tmp; + + return this; + + } + + getNormalMatrix( matrix4 ) { + + return this.setFromMatrix4( matrix4 ).invert().transpose(); + + } + + transposeIntoArray( r ) { + + const m = this.elements; + + r[ 0 ] = m[ 0 ]; + r[ 1 ] = m[ 3 ]; + r[ 2 ] = m[ 6 ]; + r[ 3 ] = m[ 1 ]; + r[ 4 ] = m[ 4 ]; + r[ 5 ] = m[ 7 ]; + r[ 6 ] = m[ 2 ]; + r[ 7 ] = m[ 5 ]; + r[ 8 ] = m[ 8 ]; + + return this; + + } + + setUvTransform( tx, ty, sx, sy, rotation, cx, cy ) { + + const c = Math.cos( rotation ); + const s = Math.sin( rotation ); + + this.set( + sx * c, sx * s, - sx * ( c * cx + s * cy ) + cx + tx, + - sy * s, sy * c, - sy * ( - s * cx + c * cy ) + cy + ty, + 0, 0, 1 + ); + + return this; + + } + + // + + scale( sx, sy ) { + + this.premultiply( _m3.makeScale( sx, sy ) ); + + return this; + + } + + rotate( theta ) { + + this.premultiply( _m3.makeRotation( - theta ) ); + + return this; + + } + + translate( tx, ty ) { + + this.premultiply( _m3.makeTranslation( tx, ty ) ); + + return this; + + } + + // for 2D Transforms + + makeTranslation( x, y ) { + + if ( x.isVector2 ) { + + this.set( + + 1, 0, x.x, + 0, 1, x.y, + 0, 0, 1 + + ); + + } else { + + this.set( + + 1, 0, x, + 0, 1, y, + 0, 0, 1 + + ); + + } + + return this; + + } + + makeRotation( theta ) { + + // counterclockwise + + const c = Math.cos( theta ); + const s = Math.sin( theta ); + + this.set( + + c, - s, 0, + s, c, 0, + 0, 0, 1 + + ); + + return this; + + } + + makeScale( x, y ) { + + this.set( + + x, 0, 0, + 0, y, 0, + 0, 0, 1 + + ); + + return this; + + } + + // + + equals( matrix ) { + + const te = this.elements; + const me = matrix.elements; + + for ( let i = 0; i < 9; i ++ ) { + + if ( te[ i ] !== me[ i ] ) return false; + + } + + return true; + + } + + fromArray( array, offset = 0 ) { + + for ( let i = 0; i < 9; i ++ ) { + + this.elements[ i ] = array[ i + offset ]; + + } + + return this; + + } + + toArray( array = [], offset = 0 ) { + + const te = this.elements; + + array[ offset ] = te[ 0 ]; + array[ offset + 1 ] = te[ 1 ]; + array[ offset + 2 ] = te[ 2 ]; + + array[ offset + 3 ] = te[ 3 ]; + array[ offset + 4 ] = te[ 4 ]; + array[ offset + 5 ] = te[ 5 ]; + + array[ offset + 6 ] = te[ 6 ]; + array[ offset + 7 ] = te[ 7 ]; + array[ offset + 8 ] = te[ 8 ]; + + return array; + + } + + clone() { + + return new this.constructor().fromArray( this.elements ); + + } + +} + +const _m3 = /*@__PURE__*/ new Matrix3(); + +function arrayNeedsUint32$1( array ) { + + // assumes larger values usually on last + + for ( let i = array.length - 1; i >= 0; -- i ) { + + if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565 + + } + + return false; + +} + +const TYPED_ARRAYS = { + Int8Array: Int8Array, + Uint8Array: Uint8Array, + Uint8ClampedArray: Uint8ClampedArray, + Int16Array: Int16Array, + Uint16Array: Uint16Array, + Int32Array: Int32Array, + Uint32Array: Uint32Array, + Float32Array: Float32Array, + Float64Array: Float64Array +}; + +function getTypedArray( type, buffer ) { + + return new TYPED_ARRAYS[ type ]( buffer ); + +} + +function createElementNS( name ) { + + return document.createElementNS( 'http://www.w3.org/1999/xhtml', name ); + +} + +function createCanvasElement() { + + const canvas = createElementNS( 'canvas' ); + canvas.style.display = 'block'; + return canvas; + +} + +const _cache$2 = {}; + +function warnOnce( message ) { + + if ( message in _cache$2 ) return; + + _cache$2[ message ] = true; + + console.warn( message ); + +} + +/** + * Matrices converting P3 <-> Rec. 709 primaries, without gamut mapping + * or clipping. Based on W3C specifications for sRGB and Display P3, + * and ICC specifications for the D50 connection space. Values in/out + * are _linear_ sRGB and _linear_ Display P3. + * + * Note that both sRGB and Display P3 use the sRGB transfer functions. + * + * Reference: + * - http://www.russellcottrell.com/photo/matrixCalculator.htm + */ + +const LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 = /*@__PURE__*/ new Matrix3().set( + 0.8224621, 0.177538, 0.0, + 0.0331941, 0.9668058, 0.0, + 0.0170827, 0.0723974, 0.9105199, +); + +const LINEAR_DISPLAY_P3_TO_LINEAR_SRGB = /*@__PURE__*/ new Matrix3().set( + 1.2249401, - 0.2249404, 0.0, + - 0.0420569, 1.0420571, 0.0, + - 0.0196376, - 0.0786361, 1.0982735 +); + +/** + * Defines supported color spaces by transfer function and primaries, + * and provides conversions to/from the Linear-sRGB reference space. + */ +const COLOR_SPACES = { + [ LinearSRGBColorSpace ]: { + transfer: LinearTransfer, + primaries: Rec709Primaries, + luminanceCoefficients: [ 0.2126, 0.7152, 0.0722 ], + toReference: ( color ) => color, + fromReference: ( color ) => color, + }, + [ SRGBColorSpace ]: { + transfer: SRGBTransfer, + primaries: Rec709Primaries, + luminanceCoefficients: [ 0.2126, 0.7152, 0.0722 ], + toReference: ( color ) => color.convertSRGBToLinear(), + fromReference: ( color ) => color.convertLinearToSRGB(), + }, + [ LinearDisplayP3ColorSpace ]: { + transfer: LinearTransfer, + primaries: P3Primaries, + luminanceCoefficients: [ 0.2289, 0.6917, 0.0793 ], + toReference: ( color ) => color.applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ), + fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ), + }, + [ DisplayP3ColorSpace ]: { + transfer: SRGBTransfer, + primaries: P3Primaries, + luminanceCoefficients: [ 0.2289, 0.6917, 0.0793 ], + toReference: ( color ) => color.convertSRGBToLinear().applyMatrix3( LINEAR_DISPLAY_P3_TO_LINEAR_SRGB ), + fromReference: ( color ) => color.applyMatrix3( LINEAR_SRGB_TO_LINEAR_DISPLAY_P3 ).convertLinearToSRGB(), + }, +}; + +const SUPPORTED_WORKING_COLOR_SPACES = new Set( [ LinearSRGBColorSpace, LinearDisplayP3ColorSpace ] ); + +const ColorManagement = { + + enabled: true, + + _workingColorSpace: LinearSRGBColorSpace, + + get workingColorSpace() { + + return this._workingColorSpace; + + }, + + set workingColorSpace( colorSpace ) { + + if ( ! SUPPORTED_WORKING_COLOR_SPACES.has( colorSpace ) ) { + + throw new Error( `Unsupported working color space, "${ colorSpace }".` ); + + } + + this._workingColorSpace = colorSpace; + + }, + + convert: function ( color, sourceColorSpace, targetColorSpace ) { + + if ( this.enabled === false || sourceColorSpace === targetColorSpace || ! sourceColorSpace || ! targetColorSpace ) { + + return color; + + } + + const sourceToReference = COLOR_SPACES[ sourceColorSpace ].toReference; + const targetFromReference = COLOR_SPACES[ targetColorSpace ].fromReference; + + return targetFromReference( sourceToReference( color ) ); + + }, + + fromWorkingColorSpace: function ( color, targetColorSpace ) { + + return this.convert( color, this._workingColorSpace, targetColorSpace ); + + }, + + toWorkingColorSpace: function ( color, sourceColorSpace ) { + + return this.convert( color, sourceColorSpace, this._workingColorSpace ); + + }, + + getPrimaries: function ( colorSpace ) { + + return COLOR_SPACES[ colorSpace ].primaries; + + }, + + getTransfer: function ( colorSpace ) { + + if ( colorSpace === NoColorSpace ) return LinearTransfer; + + return COLOR_SPACES[ colorSpace ].transfer; + + }, + + getLuminanceCoefficients: function ( target, colorSpace = this._workingColorSpace ) { + + return target.fromArray( COLOR_SPACES[ colorSpace ].luminanceCoefficients ); + + }, + +}; + + +function SRGBToLinear( c ) { + + return ( c < 0.04045 ) ? c * 0.0773993808 : Math.pow( c * 0.9478672986 + 0.0521327014, 2.4 ); + +} + +function LinearToSRGB( c ) { + + return ( c < 0.0031308 ) ? c * 12.92 : 1.055 * ( Math.pow( c, 0.41666 ) ) - 0.055; + +} + +let _canvas; + +class ImageUtils { + + static getDataURL( image ) { + + if ( /^data:/i.test( image.src ) ) { + + return image.src; + + } + + if ( typeof HTMLCanvasElement === 'undefined' ) { + + return image.src; + + } + + let canvas; + + if ( image instanceof HTMLCanvasElement ) { + + canvas = image; + + } else { + + if ( _canvas === undefined ) _canvas = createElementNS( 'canvas' ); + + _canvas.width = image.width; + _canvas.height = image.height; + + const context = _canvas.getContext( '2d' ); + + if ( image instanceof ImageData ) { + + context.putImageData( image, 0, 0 ); + + } else { + + context.drawImage( image, 0, 0, image.width, image.height ); + + } + + canvas = _canvas; + + } + + if ( canvas.width > 2048 || canvas.height > 2048 ) { + + console.warn( 'THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons', image ); + + return canvas.toDataURL( 'image/jpeg', 0.6 ); + + } else { + + return canvas.toDataURL( 'image/png' ); + + } + + } + + static sRGBToLinear( image ) { + + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { + + const canvas = createElementNS( 'canvas' ); + + canvas.width = image.width; + canvas.height = image.height; + + const context = canvas.getContext( '2d' ); + context.drawImage( image, 0, 0, image.width, image.height ); + + const imageData = context.getImageData( 0, 0, image.width, image.height ); + const data = imageData.data; + + for ( let i = 0; i < data.length; i ++ ) { + + data[ i ] = SRGBToLinear( data[ i ] / 255 ) * 255; + + } + + context.putImageData( imageData, 0, 0 ); + + return canvas; + + } else if ( image.data ) { + + const data = image.data.slice( 0 ); + + for ( let i = 0; i < data.length; i ++ ) { + + if ( data instanceof Uint8Array || data instanceof Uint8ClampedArray ) { + + data[ i ] = Math.floor( SRGBToLinear( data[ i ] / 255 ) * 255 ); + + } else { + + // assuming float + + data[ i ] = SRGBToLinear( data[ i ] ); + + } + + } + + return { + data: data, + width: image.width, + height: image.height + }; + + } else { + + console.warn( 'THREE.ImageUtils.sRGBToLinear(): Unsupported image type. No color space conversion applied.' ); + return image; + + } + + } + +} + +let _sourceId = 0; + +class Source { + + constructor( data = null ) { + + this.isSource = true; + + Object.defineProperty( this, 'id', { value: _sourceId ++ } ); + + this.uuid = generateUUID(); + + this.data = data; + this.dataReady = true; + + this.version = 0; + + } + + set needsUpdate( value ) { + + if ( value === true ) this.version ++; + + } + + toJSON( meta ) { + + const isRootObject = ( meta === undefined || typeof meta === 'string' ); + + if ( ! isRootObject && meta.images[ this.uuid ] !== undefined ) { + + return meta.images[ this.uuid ]; + + } + + const output = { + uuid: this.uuid, + url: '' + }; + + const data = this.data; + + if ( data !== null ) { + + let url; + + if ( Array.isArray( data ) ) { + + // cube texture + + url = []; + + for ( let i = 0, l = data.length; i < l; i ++ ) { + + if ( data[ i ].isDataTexture ) { + + url.push( serializeImage( data[ i ].image ) ); + + } else { + + url.push( serializeImage( data[ i ] ) ); + + } + + } + + } else { + + // texture + + url = serializeImage( data ); + + } + + output.url = url; + + } + + if ( ! isRootObject ) { + + meta.images[ this.uuid ] = output; + + } + + return output; + + } + +} + +function serializeImage( image ) { + + if ( ( typeof HTMLImageElement !== 'undefined' && image instanceof HTMLImageElement ) || + ( typeof HTMLCanvasElement !== 'undefined' && image instanceof HTMLCanvasElement ) || + ( typeof ImageBitmap !== 'undefined' && image instanceof ImageBitmap ) ) { + + // default images + + return ImageUtils.getDataURL( image ); + + } else { + + if ( image.data ) { + + // images of DataTexture + + return { + data: Array.from( image.data ), + width: image.width, + height: image.height, + type: image.data.constructor.name + }; + + } else { + + console.warn( 'THREE.Texture: Unable to serialize Texture.' ); + return {}; + + } + + } + +} + +let _textureId = 0; + +class Texture extends EventDispatcher { + + constructor( image = Texture.DEFAULT_IMAGE, mapping = Texture.DEFAULT_MAPPING, wrapS = ClampToEdgeWrapping, wrapT = ClampToEdgeWrapping, magFilter = LinearFilter, minFilter = LinearMipmapLinearFilter, format = RGBAFormat, type = UnsignedByteType, anisotropy = Texture.DEFAULT_ANISOTROPY, colorSpace = NoColorSpace ) { + + super(); + + this.isTexture = true; + + Object.defineProperty( this, 'id', { value: _textureId ++ } ); + + this.uuid = generateUUID(); + + this.name = ''; + + this.source = new Source( image ); + this.mipmaps = []; + + this.mapping = mapping; + this.channel = 0; + + this.wrapS = wrapS; + this.wrapT = wrapT; + + this.magFilter = magFilter; + this.minFilter = minFilter; + + this.anisotropy = anisotropy; + + this.format = format; + this.internalFormat = null; + this.type = type; + + this.offset = new Vector2( 0, 0 ); + this.repeat = new Vector2( 1, 1 ); + this.center = new Vector2( 0, 0 ); + this.rotation = 0; + + this.matrixAutoUpdate = true; + this.matrix = new Matrix3(); + + this.generateMipmaps = true; + this.premultiplyAlpha = false; + this.flipY = true; + this.unpackAlignment = 4; // valid values: 1, 2, 4, 8 (see http://www.khronos.org/opengles/sdk/docs/man/xhtml/glPixelStorei.xml) + + this.colorSpace = colorSpace; + + this.userData = {}; + + this.version = 0; + this.onUpdate = null; + + this.isRenderTargetTexture = false; // indicates whether a texture belongs to a render target or not + this.pmremVersion = 0; // indicates whether this texture should be processed by PMREMGenerator or not (only relevant for render target textures) + + } + + get image() { + + return this.source.data; + + } + + set image( value = null ) { + + this.source.data = value; + + } + + updateMatrix() { + + this.matrix.setUvTransform( this.offset.x, this.offset.y, this.repeat.x, this.repeat.y, this.rotation, this.center.x, this.center.y ); + + } + + clone() { + + return new this.constructor().copy( this ); + + } + + copy( source ) { + + this.name = source.name; + + this.source = source.source; + this.mipmaps = source.mipmaps.slice( 0 ); + + this.mapping = source.mapping; + this.channel = source.channel; + + this.wrapS = source.wrapS; + this.wrapT = source.wrapT; + + this.magFilter = source.magFilter; + this.minFilter = source.minFilter; + + this.anisotropy = source.anisotropy; + + this.format = source.format; + this.internalFormat = source.internalFormat; + this.type = source.type; + + this.offset.copy( source.offset ); + this.repeat.copy( source.repeat ); + this.center.copy( source.center ); + this.rotation = source.rotation; + + this.matrixAutoUpdate = source.matrixAutoUpdate; + this.matrix.copy( source.matrix ); + + this.generateMipmaps = source.generateMipmaps; + this.premultiplyAlpha = source.premultiplyAlpha; + this.flipY = source.flipY; + this.unpackAlignment = source.unpackAlignment; + this.colorSpace = source.colorSpace; + + this.userData = JSON.parse( JSON.stringify( source.userData ) ); + + this.needsUpdate = true; + + return this; + + } + + toJSON( meta ) { + + const isRootObject = ( meta === undefined || typeof meta === 'string' ); + + if ( ! isRootObject && meta.textures[ this.uuid ] !== undefined ) { + + return meta.textures[ this.uuid ]; + + } + + const output = { + + metadata: { + version: 4.6, + type: 'Texture', + generator: 'Texture.toJSON' + }, + + uuid: this.uuid, + name: this.name, + + image: this.source.toJSON( meta ).uuid, + + mapping: this.mapping, + channel: this.channel, + + repeat: [ this.repeat.x, this.repeat.y ], + offset: [ this.offset.x, this.offset.y ], + center: [ this.center.x, this.center.y ], + rotation: this.rotation, + + wrap: [ this.wrapS, this.wrapT ], + + format: this.format, + internalFormat: this.internalFormat, + type: this.type, + colorSpace: this.colorSpace, + + minFilter: this.minFilter, + magFilter: this.magFilter, + anisotropy: this.anisotropy, + + flipY: this.flipY, + + generateMipmaps: this.generateMipmaps, + premultiplyAlpha: this.premultiplyAlpha, + unpackAlignment: this.unpackAlignment + + }; + + if ( Object.keys( this.userData ).length > 0 ) output.userData = this.userData; + + if ( ! isRootObject ) { + + meta.textures[ this.uuid ] = output; + + } + + return output; + + } + + dispose() { + + this.dispatchEvent( { type: 'dispose' } ); + + } + + transformUv( uv ) { + + if ( this.mapping !== UVMapping ) return uv; + + uv.applyMatrix3( this.matrix ); + + if ( uv.x < 0 || uv.x > 1 ) { + + switch ( this.wrapS ) { + + case RepeatWrapping: + + uv.x = uv.x - Math.floor( uv.x ); + break; + + case ClampToEdgeWrapping: + + uv.x = uv.x < 0 ? 0 : 1; + break; + + case MirroredRepeatWrapping: + + if ( Math.abs( Math.floor( uv.x ) % 2 ) === 1 ) { + + uv.x = Math.ceil( uv.x ) - uv.x; + + } else { + + uv.x = uv.x - Math.floor( uv.x ); + + } + + break; + + } + + } + + if ( uv.y < 0 || uv.y > 1 ) { + + switch ( this.wrapT ) { + + case RepeatWrapping: + + uv.y = uv.y - Math.floor( uv.y ); + break; + + case ClampToEdgeWrapping: + + uv.y = uv.y < 0 ? 0 : 1; + break; + + case MirroredRepeatWrapping: + + if ( Math.abs( Math.floor( uv.y ) % 2 ) === 1 ) { + + uv.y = Math.ceil( uv.y ) - uv.y; + + } else { + + uv.y = uv.y - Math.floor( uv.y ); + + } + + break; + + } + + } + + if ( this.flipY ) { + + uv.y = 1 - uv.y; + + } + + return uv; + + } + + set needsUpdate( value ) { + + if ( value === true ) { + + this.version ++; + this.source.needsUpdate = true; + + } + + } + + set needsPMREMUpdate( value ) { + + if ( value === true ) { + + this.pmremVersion ++; + + } + + } + +} + +Texture.DEFAULT_IMAGE = null; +Texture.DEFAULT_MAPPING = UVMapping; +Texture.DEFAULT_ANISOTROPY = 1; + +class Vector4 { + + constructor( x = 0, y = 0, z = 0, w = 1 ) { + + Vector4.prototype.isVector4 = true; + + this.x = x; + this.y = y; + this.z = z; + this.w = w; + + } + + get width() { + + return this.z; + + } + + set width( value ) { + + this.z = value; + + } + + get height() { + + return this.w; + + } + + set height( value ) { + + this.w = value; + + } + + set( x, y, z, w ) { + + this.x = x; + this.y = y; + this.z = z; + this.w = w; + + return this; + + } + + setScalar( scalar ) { + + this.x = scalar; + this.y = scalar; + this.z = scalar; + this.w = scalar; + + return this; + + } + + setX( x ) { + + this.x = x; + + return this; + + } + + setY( y ) { + + this.y = y; + + return this; + + } + + setZ( z ) { + + this.z = z; + + return this; + + } + + setW( w ) { + + this.w = w; + + return this; + + } + + setComponent( index, value ) { + + switch ( index ) { + + case 0: this.x = value; break; + case 1: this.y = value; break; + case 2: this.z = value; break; + case 3: this.w = value; break; + default: throw new Error( 'index is out of range: ' + index ); + + } + + return this; + + } + + getComponent( index ) { + + switch ( index ) { + + 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: ' + index ); + + } + + } + + clone() { + + return new this.constructor( this.x, this.y, this.z, this.w ); + + } + + copy( v ) { + + this.x = v.x; + this.y = v.y; + this.z = v.z; + this.w = ( v.w !== undefined ) ? v.w : 1; + + return this; + + } + + add( v ) { + + this.x += v.x; + this.y += v.y; + this.z += v.z; + this.w += v.w; + + return this; + + } + + addScalar( s ) { + + this.x += s; + this.y += s; + this.z += s; + this.w += s; + + return this; + + } + + addVectors( a, b ) { + + this.x = a.x + b.x; + this.y = a.y + b.y; + this.z = a.z + b.z; + this.w = a.w + b.w; + + return this; + + } + + addScaledVector( v, s ) { + + this.x += v.x * s; + this.y += v.y * s; + this.z += v.z * s; + this.w += v.w * s; + + return this; + + } + + sub( v ) { + + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + this.w -= v.w; + + return this; + + } + + subScalar( s ) { + + this.x -= s; + this.y -= s; + this.z -= s; + this.w -= s; + + return this; + + } + + subVectors( a, b ) { + + this.x = a.x - b.x; + this.y = a.y - b.y; + this.z = a.z - b.z; + this.w = a.w - b.w; + + return this; + + } + + multiply( v ) { + + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; + this.w *= v.w; + + return this; + + } + + multiplyScalar( scalar ) { + + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; + this.w *= scalar; + + return this; + + } + + applyMatrix4( m ) { + + const x = this.x, y = this.y, z = this.z, w = this.w; + const e = m.elements; + + this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] * w; + this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] * w; + this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] * w; + this.w = e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] * w; + + return this; + + } + + divideScalar( scalar ) { + + return this.multiplyScalar( 1 / scalar ); + + } + + setAxisAngleFromQuaternion( q ) { + + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToAngle/index.htm + + // q is assumed to be normalized + + this.w = 2 * Math.acos( q.w ); + + const s = Math.sqrt( 1 - q.w * q.w ); + + if ( s < 0.0001 ) { + + this.x = 1; + this.y = 0; + this.z = 0; + + } else { + + this.x = q.x / s; + this.y = q.y / s; + this.z = q.z / s; + + } + + return this; + + } + + setAxisAngleFromRotationMatrix( m ) { + + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToAngle/index.htm + + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + + let angle, x, y, z; // variables for result + const epsilon = 0.01, // margin to allow for rounding errors + epsilon2 = 0.1, // margin to distinguish between 0 and 180 degrees + + te = m.elements, + + m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], + m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], + m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; + + if ( ( Math.abs( m12 - m21 ) < epsilon ) && + ( Math.abs( m13 - m31 ) < epsilon ) && + ( Math.abs( m23 - m32 ) < epsilon ) ) { + + // singularity found + // first check for identity matrix which must have +1 for all terms + // in leading diagonal and zero in other terms + + if ( ( Math.abs( m12 + m21 ) < epsilon2 ) && + ( Math.abs( m13 + m31 ) < epsilon2 ) && + ( Math.abs( m23 + m32 ) < epsilon2 ) && + ( Math.abs( m11 + m22 + m33 - 3 ) < epsilon2 ) ) { + + // this singularity is identity matrix so angle = 0 + + this.set( 1, 0, 0, 0 ); + + return this; // zero angle, arbitrary axis + + } + + // otherwise this singularity is angle = 180 + + angle = Math.PI; + + const xx = ( m11 + 1 ) / 2; + const yy = ( m22 + 1 ) / 2; + const zz = ( m33 + 1 ) / 2; + const xy = ( m12 + m21 ) / 4; + const xz = ( m13 + m31 ) / 4; + const yz = ( m23 + m32 ) / 4; + + if ( ( xx > yy ) && ( xx > zz ) ) { + + // m11 is the largest diagonal term + + if ( xx < epsilon ) { + + x = 0; + y = 0.707106781; + z = 0.707106781; + + } else { + + x = Math.sqrt( xx ); + y = xy / x; + z = xz / x; + + } + + } else if ( yy > zz ) { + + // m22 is the largest diagonal term + + if ( yy < epsilon ) { + + x = 0.707106781; + y = 0; + z = 0.707106781; + + } else { + + y = Math.sqrt( yy ); + x = xy / y; + z = yz / y; + + } + + } else { + + // m33 is the largest diagonal term so base result on this + + if ( zz < epsilon ) { + + x = 0.707106781; + y = 0.707106781; + z = 0; + + } else { + + z = Math.sqrt( zz ); + x = xz / z; + y = yz / z; + + } + + } + + this.set( x, y, z, angle ); + + return this; // return 180 deg rotation + + } + + // as we have reached here there are no singularities so we can handle normally + + let s = Math.sqrt( ( m32 - m23 ) * ( m32 - m23 ) + + ( m13 - m31 ) * ( m13 - m31 ) + + ( m21 - m12 ) * ( m21 - m12 ) ); // used to normalize + + if ( Math.abs( s ) < 0.001 ) s = 1; + + // prevent divide by zero, should not happen if matrix is orthogonal and should be + // caught by singularity test above, but I've left it in just in case + + this.x = ( m32 - m23 ) / s; + this.y = ( m13 - m31 ) / s; + this.z = ( m21 - m12 ) / s; + this.w = Math.acos( ( m11 + m22 + m33 - 1 ) / 2 ); + + return this; + + } + + setFromMatrixPosition( m ) { + + const e = m.elements; + + this.x = e[ 12 ]; + this.y = e[ 13 ]; + this.z = e[ 14 ]; + this.w = e[ 15 ]; + + return this; + + } + + min( v ) { + + this.x = Math.min( this.x, v.x ); + this.y = Math.min( this.y, v.y ); + this.z = Math.min( this.z, v.z ); + this.w = Math.min( this.w, v.w ); + + return this; + + } + + max( v ) { + + this.x = Math.max( this.x, v.x ); + this.y = Math.max( this.y, v.y ); + this.z = Math.max( this.z, v.z ); + this.w = Math.max( this.w, v.w ); + + return this; + + } + + clamp( min, max ) { + + // assumes min < max, componentwise + + this.x = Math.max( min.x, Math.min( max.x, this.x ) ); + this.y = Math.max( min.y, Math.min( max.y, this.y ) ); + this.z = Math.max( min.z, Math.min( max.z, this.z ) ); + this.w = Math.max( min.w, Math.min( max.w, this.w ) ); + + return this; + + } + + clampScalar( minVal, maxVal ) { + + this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); + this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); + this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); + this.w = Math.max( minVal, Math.min( maxVal, this.w ) ); + + return this; + + } + + clampLength( min, max ) { + + const length = this.length(); + + return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); + + } + + floor() { + + this.x = Math.floor( this.x ); + this.y = Math.floor( this.y ); + this.z = Math.floor( this.z ); + this.w = Math.floor( this.w ); + + return this; + + } + + ceil() { + + this.x = Math.ceil( this.x ); + this.y = Math.ceil( this.y ); + this.z = Math.ceil( this.z ); + this.w = Math.ceil( this.w ); + + return this; + + } + + round() { + + this.x = Math.round( this.x ); + this.y = Math.round( this.y ); + this.z = Math.round( this.z ); + this.w = Math.round( this.w ); + + return this; + + } + + roundToZero() { + + this.x = Math.trunc( this.x ); + this.y = Math.trunc( this.y ); + this.z = Math.trunc( this.z ); + this.w = Math.trunc( this.w ); + + return this; + + } + + negate() { + + this.x = - this.x; + this.y = - this.y; + this.z = - this.z; + this.w = - this.w; + + return this; + + } + + dot( v ) { + + return this.x * v.x + this.y * v.y + this.z * v.z + this.w * v.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 ); + + } + + manhattanLength() { + + return Math.abs( this.x ) + Math.abs( this.y ) + Math.abs( this.z ) + Math.abs( this.w ); + + } + + normalize() { + + return this.divideScalar( this.length() || 1 ); + + } + + setLength( length ) { + + return this.normalize().multiplyScalar( length ); + + } + + lerp( v, alpha ) { + + this.x += ( v.x - this.x ) * alpha; + this.y += ( v.y - this.y ) * alpha; + this.z += ( v.z - this.z ) * alpha; + this.w += ( v.w - this.w ) * alpha; + + return this; + + } + + lerpVectors( v1, v2, alpha ) { + + this.x = v1.x + ( v2.x - v1.x ) * alpha; + this.y = v1.y + ( v2.y - v1.y ) * alpha; + this.z = v1.z + ( v2.z - v1.z ) * alpha; + this.w = v1.w + ( v2.w - v1.w ) * alpha; + + return this; + + } + + equals( v ) { + + return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) && ( v.w === this.w ) ); + + } + + fromArray( array, offset = 0 ) { + + this.x = array[ offset ]; + this.y = array[ offset + 1 ]; + this.z = array[ offset + 2 ]; + this.w = array[ offset + 3 ]; + + return this; + + } + + toArray( array = [], offset = 0 ) { + + array[ offset ] = this.x; + array[ offset + 1 ] = this.y; + array[ offset + 2 ] = this.z; + array[ offset + 3 ] = this.w; + + return array; + + } + + fromBufferAttribute( attribute, index ) { + + this.x = attribute.getX( index ); + this.y = attribute.getY( index ); + this.z = attribute.getZ( index ); + this.w = attribute.getW( index ); + + return this; + + } + + random() { + + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); + this.w = Math.random(); + + return this; + + } + + *[ Symbol.iterator ]() { + + yield this.x; + yield this.y; + yield this.z; + yield this.w; + + } + +} + +/* + In options, we can specify: + * Texture parameters for an auto-generated target texture + * depthBuffer/stencilBuffer: Booleans to indicate if we should generate these buffers +*/ +class RenderTarget extends EventDispatcher { + + constructor( width = 1, height = 1, options = {} ) { + + super(); + + this.isRenderTarget = true; + + this.width = width; + this.height = height; + this.depth = 1; + + this.scissor = new Vector4( 0, 0, width, height ); + this.scissorTest = false; + + this.viewport = new Vector4( 0, 0, width, height ); + + const image = { width: width, height: height, depth: 1 }; + + options = Object.assign( { + generateMipmaps: false, + internalFormat: null, + minFilter: LinearFilter, + depthBuffer: true, + stencilBuffer: false, + resolveDepthBuffer: true, + resolveStencilBuffer: true, + depthTexture: null, + samples: 0, + count: 1 + }, options ); + + const texture = new Texture( image, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); + + texture.flipY = false; + texture.generateMipmaps = options.generateMipmaps; + texture.internalFormat = options.internalFormat; + + this.textures = []; + + const count = options.count; + for ( let i = 0; i < count; i ++ ) { + + this.textures[ i ] = texture.clone(); + this.textures[ i ].isRenderTargetTexture = true; + + } + + this.depthBuffer = options.depthBuffer; + this.stencilBuffer = options.stencilBuffer; + + this.resolveDepthBuffer = options.resolveDepthBuffer; + this.resolveStencilBuffer = options.resolveStencilBuffer; + + this.depthTexture = options.depthTexture; + + this.samples = options.samples; + + } + + get texture() { + + return this.textures[ 0 ]; + + } + + set texture( value ) { + + this.textures[ 0 ] = value; + + } + + setSize( width, height, depth = 1 ) { + + if ( this.width !== width || this.height !== height || this.depth !== depth ) { + + this.width = width; + this.height = height; + this.depth = depth; + + for ( let i = 0, il = this.textures.length; i < il; i ++ ) { + + this.textures[ i ].image.width = width; + this.textures[ i ].image.height = height; + this.textures[ i ].image.depth = depth; + + } + + this.dispose(); + + } + + this.viewport.set( 0, 0, width, height ); + this.scissor.set( 0, 0, width, height ); + + } + + clone() { + + return new this.constructor().copy( this ); + + } + + copy( source ) { + + this.width = source.width; + this.height = source.height; + this.depth = source.depth; + + this.scissor.copy( source.scissor ); + this.scissorTest = source.scissorTest; + + this.viewport.copy( source.viewport ); + + this.textures.length = 0; + + for ( let i = 0, il = source.textures.length; i < il; i ++ ) { + + this.textures[ i ] = source.textures[ i ].clone(); + this.textures[ i ].isRenderTargetTexture = true; + + } + + // ensure image object is not shared, see #20328 + + const image = Object.assign( {}, source.texture.image ); + this.texture.source = new Source( image ); + + this.depthBuffer = source.depthBuffer; + this.stencilBuffer = source.stencilBuffer; + + this.resolveDepthBuffer = source.resolveDepthBuffer; + this.resolveStencilBuffer = source.resolveStencilBuffer; + + if ( source.depthTexture !== null ) this.depthTexture = source.depthTexture.clone(); + + this.samples = source.samples; + + return this; + + } + + dispose() { + + this.dispatchEvent( { type: 'dispose' } ); + + } + +} + +class WebGLRenderTarget extends RenderTarget { + + constructor( width = 1, height = 1, options = {} ) { + + super( width, height, options ); + + this.isWebGLRenderTarget = true; + + } + +} + +class DataArrayTexture extends Texture { + + constructor( data = null, width = 1, height = 1, depth = 1 ) { + + super( null ); + + this.isDataArrayTexture = true; + + this.image = { data, width, height, depth }; + + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; + + this.wrapR = ClampToEdgeWrapping; + + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; + + this.layerUpdates = new Set(); + + } + + addLayerUpdate( layerIndex ) { + + this.layerUpdates.add( layerIndex ); + + } + + clearLayerUpdates() { + + this.layerUpdates.clear(); + + } + +} + +class WebGLArrayRenderTarget extends WebGLRenderTarget { + + constructor( width = 1, height = 1, depth = 1, options = {} ) { + + super( width, height, options ); + + this.isWebGLArrayRenderTarget = true; + + this.depth = depth; + + this.texture = new DataArrayTexture( null, width, height, depth ); + + this.texture.isRenderTargetTexture = true; + + } + +} + +class Data3DTexture extends Texture { + + constructor( data = null, width = 1, height = 1, depth = 1 ) { + + // We're going to add .setXXX() methods for setting properties later. + // Users can still set in DataTexture3D directly. + // + // const texture = new THREE.DataTexture3D( data, width, height, depth ); + // texture.anisotropy = 16; + // + // See #14839 + + super( null ); + + this.isData3DTexture = true; + + this.image = { data, width, height, depth }; + + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; + + this.wrapR = ClampToEdgeWrapping; + + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; + + } + +} + +class WebGL3DRenderTarget extends WebGLRenderTarget { + + constructor( width = 1, height = 1, depth = 1, options = {} ) { + + super( width, height, options ); + + this.isWebGL3DRenderTarget = true; + + this.depth = depth; + + this.texture = new Data3DTexture( null, width, height, depth ); + + this.texture.isRenderTargetTexture = true; + + } + +} + +class Quaternion { + + constructor( x = 0, y = 0, z = 0, w = 1 ) { + + this.isQuaternion = true; + + this._x = x; + this._y = y; + this._z = z; + this._w = w; + + } + + static slerpFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1, t ) { + + // fuzz-free, array-based Quaternion SLERP operation + + let x0 = src0[ srcOffset0 + 0 ], + y0 = src0[ srcOffset0 + 1 ], + z0 = src0[ srcOffset0 + 2 ], + w0 = src0[ srcOffset0 + 3 ]; + + const x1 = src1[ srcOffset1 + 0 ], + y1 = src1[ srcOffset1 + 1 ], + z1 = src1[ srcOffset1 + 2 ], + w1 = src1[ srcOffset1 + 3 ]; + + if ( t === 0 ) { + + dst[ dstOffset + 0 ] = x0; + dst[ dstOffset + 1 ] = y0; + dst[ dstOffset + 2 ] = z0; + dst[ dstOffset + 3 ] = w0; + return; + + } + + if ( t === 1 ) { + + dst[ dstOffset + 0 ] = x1; + dst[ dstOffset + 1 ] = y1; + dst[ dstOffset + 2 ] = z1; + dst[ dstOffset + 3 ] = w1; + return; + + } + + if ( w0 !== w1 || x0 !== x1 || y0 !== y1 || z0 !== z1 ) { + + let s = 1 - t; + const cos = x0 * x1 + y0 * y1 + z0 * z1 + w0 * w1, + dir = ( cos >= 0 ? 1 : - 1 ), + sqrSin = 1 - cos * cos; + + // Skip the Slerp for tiny steps to avoid numeric problems: + if ( sqrSin > Number.EPSILON ) { + + const sin = Math.sqrt( sqrSin ), + len = Math.atan2( sin, cos * dir ); + + s = Math.sin( s * len ) / sin; + t = Math.sin( t * len ) / sin; + + } + + const tDir = t * dir; + + x0 = x0 * s + x1 * tDir; + y0 = y0 * s + y1 * tDir; + z0 = z0 * s + z1 * tDir; + w0 = w0 * s + w1 * tDir; + + // Normalize in case we just did a lerp: + if ( s === 1 - t ) { + + const f = 1 / Math.sqrt( x0 * x0 + y0 * y0 + z0 * z0 + w0 * w0 ); + + x0 *= f; + y0 *= f; + z0 *= f; + w0 *= f; + + } + + } + + dst[ dstOffset ] = x0; + dst[ dstOffset + 1 ] = y0; + dst[ dstOffset + 2 ] = z0; + dst[ dstOffset + 3 ] = w0; + + } + + static multiplyQuaternionsFlat( dst, dstOffset, src0, srcOffset0, src1, srcOffset1 ) { + + const x0 = src0[ srcOffset0 ]; + const y0 = src0[ srcOffset0 + 1 ]; + const z0 = src0[ srcOffset0 + 2 ]; + const w0 = src0[ srcOffset0 + 3 ]; + + const x1 = src1[ srcOffset1 ]; + const y1 = src1[ srcOffset1 + 1 ]; + const z1 = src1[ srcOffset1 + 2 ]; + const w1 = src1[ srcOffset1 + 3 ]; + + dst[ dstOffset ] = x0 * w1 + w0 * x1 + y0 * z1 - z0 * y1; + dst[ dstOffset + 1 ] = y0 * w1 + w0 * y1 + z0 * x1 - x0 * z1; + dst[ dstOffset + 2 ] = z0 * w1 + w0 * z1 + x0 * y1 - y0 * x1; + dst[ dstOffset + 3 ] = w0 * w1 - x0 * x1 - y0 * y1 - z0 * z1; + + return dst; + + } + + get x() { + + return this._x; + + } + + set x( value ) { + + this._x = value; + this._onChangeCallback(); + + } + + get y() { + + return this._y; + + } + + set y( value ) { + + this._y = value; + this._onChangeCallback(); + + } + + get z() { + + return this._z; + + } + + set z( value ) { + + this._z = value; + this._onChangeCallback(); + + } + + get w() { + + return this._w; + + } + + set w( value ) { + + this._w = value; + this._onChangeCallback(); + + } + + set( x, y, z, w ) { + + this._x = x; + this._y = y; + this._z = z; + this._w = w; + + this._onChangeCallback(); + + return this; + + } + + clone() { + + return new this.constructor( this._x, this._y, this._z, this._w ); + + } + + copy( quaternion ) { + + this._x = quaternion.x; + this._y = quaternion.y; + this._z = quaternion.z; + this._w = quaternion.w; + + this._onChangeCallback(); + + return this; + + } + + setFromEuler( euler, update = true ) { + + const x = euler._x, y = euler._y, z = euler._z, order = euler._order; + + // http://www.mathworks.com/matlabcentral/fileexchange/ + // 20696-function-to-convert-between-dcm-euler-angles-quaternions-and-euler-vectors/ + // content/SpinCalc.m + + const cos = Math.cos; + const sin = Math.sin; + + const c1 = cos( x / 2 ); + const c2 = cos( y / 2 ); + const c3 = cos( z / 2 ); + + const s1 = sin( x / 2 ); + const s2 = sin( y / 2 ); + const s3 = sin( z / 2 ); + + switch ( order ) { + + case 'XYZ': + 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; + break; + + case 'YXZ': + 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; + break; + + case 'ZXY': + 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; + break; + + case 'ZYX': + 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; + break; + + case 'YZX': + 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; + break; + + case 'XZY': + 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; + break; + + default: + console.warn( 'THREE.Quaternion: .setFromEuler() encountered an unknown order: ' + order ); + + } + + if ( update === true ) this._onChangeCallback(); + + return this; + + } + + setFromAxisAngle( axis, angle ) { + + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/angleToQuaternion/index.htm + + // assumes axis is normalized + + const 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 ); + + this._onChangeCallback(); + + return this; + + } + + setFromRotationMatrix( m ) { + + // http://www.euclideanspace.com/maths/geometry/rotations/conversions/matrixToQuaternion/index.htm + + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + + const te = m.elements, + + m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ], + m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ], + m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ], + + trace = m11 + m22 + m33; + + if ( trace > 0 ) { + + const s = 0.5 / Math.sqrt( trace + 1.0 ); + + this._w = 0.25 / s; + this._x = ( m32 - m23 ) * s; + this._y = ( m13 - m31 ) * s; + this._z = ( m21 - m12 ) * s; + + } else if ( m11 > m22 && m11 > m33 ) { + + const s = 2.0 * Math.sqrt( 1.0 + m11 - m22 - m33 ); + + this._w = ( m32 - m23 ) / s; + this._x = 0.25 * s; + this._y = ( m12 + m21 ) / s; + this._z = ( m13 + m31 ) / s; + + } else if ( m22 > m33 ) { + + const s = 2.0 * Math.sqrt( 1.0 + m22 - m11 - m33 ); + + this._w = ( m13 - m31 ) / s; + this._x = ( m12 + m21 ) / s; + this._y = 0.25 * s; + this._z = ( m23 + m32 ) / s; + + } else { + + const s = 2.0 * Math.sqrt( 1.0 + m33 - m11 - m22 ); + + this._w = ( m21 - m12 ) / s; + this._x = ( m13 + m31 ) / s; + this._y = ( m23 + m32 ) / s; + this._z = 0.25 * s; + + } + + this._onChangeCallback(); + + return this; + + } + + setFromUnitVectors( vFrom, vTo ) { + + // assumes direction vectors vFrom and vTo are normalized + + let r = vFrom.dot( vTo ) + 1; + + if ( r < Number.EPSILON ) { + + // vFrom and vTo point in opposite directions + + r = 0; + + if ( Math.abs( vFrom.x ) > Math.abs( vFrom.z ) ) { + + this._x = - vFrom.y; + this._y = vFrom.x; + this._z = 0; + this._w = r; + + } else { + + this._x = 0; + this._y = - vFrom.z; + this._z = vFrom.y; + this._w = r; + + } + + } else { + + // crossVectors( vFrom, vTo ); // inlined to avoid cyclic dependency on Vector3 + + this._x = vFrom.y * vTo.z - vFrom.z * vTo.y; + this._y = vFrom.z * vTo.x - vFrom.x * vTo.z; + this._z = vFrom.x * vTo.y - vFrom.y * vTo.x; + this._w = r; + + } + + return this.normalize(); + + } + + angleTo( q ) { + + return 2 * Math.acos( Math.abs( clamp$1( this.dot( q ), - 1, 1 ) ) ); + + } + + rotateTowards( q, step ) { + + const angle = this.angleTo( q ); + + if ( angle === 0 ) return this; + + const t = Math.min( 1, step / angle ); + + this.slerp( q, t ); + + return this; + + } + + identity() { + + return this.set( 0, 0, 0, 1 ); + + } + + invert() { + + // quaternion is assumed to have unit length + + return this.conjugate(); + + } + + conjugate() { + + this._x *= - 1; + this._y *= - 1; + this._z *= - 1; + + this._onChangeCallback(); + + return this; + + } + + dot( v ) { + + return this._x * v._x + this._y * v._y + this._z * v._z + this._w * v._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 l = this.length(); + + 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; + + } + + this._onChangeCallback(); + + return this; + + } + + multiply( q ) { + + return this.multiplyQuaternions( this, q ); + + } + + premultiply( q ) { + + return this.multiplyQuaternions( q, this ); + + } + + multiplyQuaternions( a, b ) { + + // from http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/code/index.htm + + const qax = a._x, qay = a._y, qaz = a._z, qaw = a._w; + const 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; + + this._onChangeCallback(); + + return this; + + } + + slerp( qb, t ) { + + if ( t === 0 ) return this; + if ( t === 1 ) return this.copy( qb ); + + const x = this._x, y = this._y, z = this._z, w = this._w; + + // http://www.euclideanspace.com/maths/algebra/realNormedAlgebra/quaternions/slerp/ + + let 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; + + } + + const sqrSinHalfTheta = 1.0 - cosHalfTheta * cosHalfTheta; + + if ( sqrSinHalfTheta <= Number.EPSILON ) { + + const s = 1 - t; + this._w = s * w + t * this._w; + this._x = s * x + t * this._x; + this._y = s * y + t * this._y; + this._z = s * z + t * this._z; + + this.normalize(); // normalize calls _onChangeCallback() + + return this; + + } + + const sinHalfTheta = Math.sqrt( sqrSinHalfTheta ); + const halfTheta = Math.atan2( sinHalfTheta, cosHalfTheta ); + const 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 ); + + this._onChangeCallback(); + + return this; + + } + + slerpQuaternions( qa, qb, t ) { + + return this.copy( qa ).slerp( qb, t ); + + } + + random() { + + // sets this quaternion to a uniform random unit quaternnion + + // Ken Shoemake + // Uniform random rotations + // D. Kirk, editor, Graphics Gems III, pages 124-132. Academic Press, New York, 1992. + + const theta1 = 2 * Math.PI * Math.random(); + const theta2 = 2 * Math.PI * Math.random(); + + const x0 = Math.random(); + const r1 = Math.sqrt( 1 - x0 ); + const r2 = Math.sqrt( x0 ); + + return this.set( + r1 * Math.sin( theta1 ), + r1 * Math.cos( theta1 ), + r2 * Math.sin( theta2 ), + r2 * Math.cos( theta2 ), + ); + + } + + equals( quaternion ) { + + return ( quaternion._x === this._x ) && ( quaternion._y === this._y ) && ( quaternion._z === this._z ) && ( quaternion._w === this._w ); + + } + + fromArray( array, offset = 0 ) { + + this._x = array[ offset ]; + this._y = array[ offset + 1 ]; + this._z = array[ offset + 2 ]; + this._w = array[ offset + 3 ]; + + this._onChangeCallback(); + + return this; + + } + + toArray( array = [], offset = 0 ) { + + array[ offset ] = this._x; + array[ offset + 1 ] = this._y; + array[ offset + 2 ] = this._z; + array[ offset + 3 ] = this._w; + + return array; + + } + + fromBufferAttribute( attribute, index ) { + + this._x = attribute.getX( index ); + this._y = attribute.getY( index ); + this._z = attribute.getZ( index ); + this._w = attribute.getW( index ); + + this._onChangeCallback(); + + return this; + + } + + toJSON() { + + return this.toArray(); + + } + + _onChange( callback ) { + + this._onChangeCallback = callback; + + return this; + + } + + _onChangeCallback() {} + + *[ Symbol.iterator ]() { + + yield this._x; + yield this._y; + yield this._z; + yield this._w; + + } + +} + +class Vector3 { + + constructor( x = 0, y = 0, z = 0 ) { + + Vector3.prototype.isVector3 = true; + + this.x = x; + this.y = y; + this.z = z; + + } + + set( x, y, z ) { + + if ( z === undefined ) z = this.z; // sprite.scale.set(x,y) + + this.x = x; + this.y = y; + this.z = z; + + return this; + + } + + setScalar( scalar ) { + + this.x = scalar; + this.y = scalar; + this.z = scalar; + + return this; + + } + + setX( x ) { + + this.x = x; + + return this; + + } + + setY( y ) { + + this.y = y; + + return this; + + } + + setZ( z ) { + + this.z = z; + + return this; + + } + + setComponent( index, value ) { + + switch ( index ) { + + case 0: this.x = value; break; + case 1: this.y = value; break; + case 2: this.z = value; break; + default: throw new Error( 'index is out of range: ' + index ); + + } + + return this; + + } + + getComponent( index ) { + + switch ( index ) { + + case 0: return this.x; + case 1: return this.y; + case 2: return this.z; + default: throw new Error( 'index is out of range: ' + index ); + + } + + } + + clone() { + + return new this.constructor( this.x, this.y, this.z ); + + } + + copy( v ) { + + this.x = v.x; + this.y = v.y; + this.z = v.z; + + return this; + + } + + add( v ) { + + this.x += v.x; + this.y += v.y; + this.z += v.z; + + return this; + + } + + addScalar( s ) { + + this.x += s; + this.y += s; + this.z += s; + + return this; + + } + + addVectors( a, b ) { + + this.x = a.x + b.x; + this.y = a.y + b.y; + this.z = a.z + b.z; + + return this; + + } + + addScaledVector( v, s ) { + + this.x += v.x * s; + this.y += v.y * s; + this.z += v.z * s; + + return this; + + } + + sub( v ) { + + this.x -= v.x; + this.y -= v.y; + this.z -= v.z; + + return this; + + } + + subScalar( s ) { + + this.x -= s; + this.y -= s; + this.z -= s; + + return this; + + } + + subVectors( a, b ) { + + this.x = a.x - b.x; + this.y = a.y - b.y; + this.z = a.z - b.z; + + return this; + + } + + multiply( v ) { + + this.x *= v.x; + this.y *= v.y; + this.z *= v.z; + + return this; + + } + + multiplyScalar( scalar ) { + + this.x *= scalar; + this.y *= scalar; + this.z *= scalar; + + return this; + + } + + multiplyVectors( a, b ) { + + this.x = a.x * b.x; + this.y = a.y * b.y; + this.z = a.z * b.z; + + return this; + + } + + applyEuler( euler ) { + + return this.applyQuaternion( _quaternion$4.setFromEuler( euler ) ); + + } + + applyAxisAngle( axis, angle ) { + + return this.applyQuaternion( _quaternion$4.setFromAxisAngle( axis, angle ) ); + + } + + applyMatrix3( m ) { + + const x = this.x, y = this.y, z = this.z; + const e = m.elements; + + this.x = e[ 0 ] * x + e[ 3 ] * y + e[ 6 ] * z; + this.y = e[ 1 ] * x + e[ 4 ] * y + e[ 7 ] * z; + this.z = e[ 2 ] * x + e[ 5 ] * y + e[ 8 ] * z; + + return this; + + } + + applyNormalMatrix( m ) { + + return this.applyMatrix3( m ).normalize(); + + } + + applyMatrix4( m ) { + + const x = this.x, y = this.y, z = this.z; + const e = m.elements; + + const w = 1 / ( e[ 3 ] * x + e[ 7 ] * y + e[ 11 ] * z + e[ 15 ] ); + + this.x = ( e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z + e[ 12 ] ) * w; + this.y = ( e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z + e[ 13 ] ) * w; + this.z = ( e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z + e[ 14 ] ) * w; + + return this; + + } + + applyQuaternion( q ) { + + // quaternion q is assumed to have unit length + + const vx = this.x, vy = this.y, vz = this.z; + const qx = q.x, qy = q.y, qz = q.z, qw = q.w; + + // t = 2 * cross( q.xyz, v ); + const tx = 2 * ( qy * vz - qz * vy ); + const ty = 2 * ( qz * vx - qx * vz ); + const tz = 2 * ( qx * vy - qy * vx ); + + // v + q.w * t + cross( q.xyz, t ); + this.x = vx + qw * tx + qy * tz - qz * ty; + this.y = vy + qw * ty + qz * tx - qx * tz; + this.z = vz + qw * tz + qx * ty - qy * tx; + + return this; + + } + + project( camera ) { + + return this.applyMatrix4( camera.matrixWorldInverse ).applyMatrix4( camera.projectionMatrix ); + + } + + unproject( camera ) { + + return this.applyMatrix4( camera.projectionMatrixInverse ).applyMatrix4( camera.matrixWorld ); + + } + + transformDirection( m ) { + + // input: THREE.Matrix4 affine matrix + // vector interpreted as a direction + + const x = this.x, y = this.y, z = this.z; + const e = m.elements; + + this.x = e[ 0 ] * x + e[ 4 ] * y + e[ 8 ] * z; + this.y = e[ 1 ] * x + e[ 5 ] * y + e[ 9 ] * z; + this.z = e[ 2 ] * x + e[ 6 ] * y + e[ 10 ] * z; + + return this.normalize(); + + } + + divide( v ) { + + this.x /= v.x; + this.y /= v.y; + this.z /= v.z; + + return this; + + } + + divideScalar( scalar ) { + + return this.multiplyScalar( 1 / scalar ); + + } + + min( v ) { + + this.x = Math.min( this.x, v.x ); + this.y = Math.min( this.y, v.y ); + this.z = Math.min( this.z, v.z ); + + return this; + + } + + max( v ) { + + this.x = Math.max( this.x, v.x ); + this.y = Math.max( this.y, v.y ); + this.z = Math.max( this.z, v.z ); + + return this; + + } + + clamp( min, max ) { + + // assumes min < max, componentwise + + this.x = Math.max( min.x, Math.min( max.x, this.x ) ); + this.y = Math.max( min.y, Math.min( max.y, this.y ) ); + this.z = Math.max( min.z, Math.min( max.z, this.z ) ); + + return this; + + } + + clampScalar( minVal, maxVal ) { + + this.x = Math.max( minVal, Math.min( maxVal, this.x ) ); + this.y = Math.max( minVal, Math.min( maxVal, this.y ) ); + this.z = Math.max( minVal, Math.min( maxVal, this.z ) ); + + return this; + + } + + clampLength( min, max ) { + + const length = this.length(); + + return this.divideScalar( length || 1 ).multiplyScalar( Math.max( min, Math.min( max, length ) ) ); + + } + + floor() { + + this.x = Math.floor( this.x ); + this.y = Math.floor( this.y ); + this.z = Math.floor( this.z ); + + return this; + + } + + ceil() { + + this.x = Math.ceil( this.x ); + this.y = Math.ceil( this.y ); + this.z = Math.ceil( this.z ); + + return this; + + } + + round() { + + this.x = Math.round( this.x ); + this.y = Math.round( this.y ); + this.z = Math.round( this.z ); + + return this; + + } + + roundToZero() { + + this.x = Math.trunc( this.x ); + this.y = Math.trunc( this.y ); + this.z = Math.trunc( this.z ); + + return this; + + } + + negate() { + + this.x = - this.x; + this.y = - this.y; + this.z = - this.z; + + return this; + + } + + dot( v ) { + + return this.x * v.x + this.y * v.y + this.z * v.z; + + } + + // TODO lengthSquared? + + 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( length ) { + + return this.normalize().multiplyScalar( length ); + + } + + lerp( v, alpha ) { + + this.x += ( v.x - this.x ) * alpha; + this.y += ( v.y - this.y ) * alpha; + this.z += ( v.z - this.z ) * alpha; + + return this; + + } + + lerpVectors( v1, v2, alpha ) { + + this.x = v1.x + ( v2.x - v1.x ) * alpha; + this.y = v1.y + ( v2.y - v1.y ) * alpha; + this.z = v1.z + ( v2.z - v1.z ) * alpha; + + return this; + + } + + cross( v ) { + + return this.crossVectors( this, v ); + + } + + crossVectors( a, b ) { + + const ax = a.x, ay = a.y, az = a.z; + const 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; + + } + + projectOnVector( v ) { + + const denominator = v.lengthSq(); + + if ( denominator === 0 ) return this.set( 0, 0, 0 ); + + const scalar = v.dot( this ) / denominator; + + return this.copy( v ).multiplyScalar( scalar ); + + } + + projectOnPlane( planeNormal ) { + + _vector$c.copy( this ).projectOnVector( planeNormal ); + + return this.sub( _vector$c ); + + } + + reflect( normal ) { + + // reflect incident vector off plane orthogonal to normal + // normal is assumed to have unit length + + return this.sub( _vector$c.copy( normal ).multiplyScalar( 2 * this.dot( normal ) ) ); + + } + + angleTo( v ) { + + const denominator = Math.sqrt( this.lengthSq() * v.lengthSq() ); + + if ( denominator === 0 ) return Math.PI / 2; + + const theta = this.dot( v ) / denominator; + + // clamp, to handle numerical problems + + return Math.acos( clamp$1( theta, - 1, 1 ) ); + + } + + distanceTo( v ) { + + return Math.sqrt( this.distanceToSquared( v ) ); + + } + + distanceToSquared( v ) { + + const dx = this.x - v.x, dy = this.y - v.y, dz = this.z - v.z; + + return dx * dx + dy * dy + dz * dz; + + } + + manhattanDistanceTo( v ) { + + return Math.abs( this.x - v.x ) + Math.abs( this.y - v.y ) + Math.abs( this.z - v.z ); + + } + + setFromSpherical( s ) { + + return this.setFromSphericalCoords( s.radius, s.phi, s.theta ); + + } + + setFromSphericalCoords( radius, phi, theta ) { + + const sinPhiRadius = Math.sin( phi ) * radius; + + this.x = sinPhiRadius * Math.sin( theta ); + this.y = Math.cos( phi ) * radius; + this.z = sinPhiRadius * Math.cos( theta ); + + return this; + + } + + setFromCylindrical( c ) { + + return this.setFromCylindricalCoords( c.radius, c.theta, c.y ); + + } + + setFromCylindricalCoords( radius, theta, y ) { + + this.x = radius * Math.sin( theta ); + this.y = y; + this.z = radius * Math.cos( theta ); + + return this; + + } + + setFromMatrixPosition( m ) { + + const e = m.elements; + + this.x = e[ 12 ]; + this.y = e[ 13 ]; + this.z = e[ 14 ]; + + return this; + + } + + setFromMatrixScale( m ) { + + const sx = this.setFromMatrixColumn( m, 0 ).length(); + const sy = this.setFromMatrixColumn( m, 1 ).length(); + const sz = this.setFromMatrixColumn( m, 2 ).length(); + + this.x = sx; + this.y = sy; + this.z = sz; + + return this; + + } + + setFromMatrixColumn( m, index ) { + + return this.fromArray( m.elements, index * 4 ); + + } + + setFromMatrix3Column( m, index ) { + + return this.fromArray( m.elements, index * 3 ); + + } + + setFromEuler( e ) { + + this.x = e._x; + this.y = e._y; + this.z = e._z; + + return this; + + } + + setFromColor( c ) { + + this.x = c.r; + this.y = c.g; + this.z = c.b; + + return this; + + } + + equals( v ) { + + return ( ( v.x === this.x ) && ( v.y === this.y ) && ( v.z === this.z ) ); + + } + + fromArray( array, offset = 0 ) { + + this.x = array[ offset ]; + this.y = array[ offset + 1 ]; + this.z = array[ offset + 2 ]; + + return this; + + } + + toArray( array = [], offset = 0 ) { + + array[ offset ] = this.x; + array[ offset + 1 ] = this.y; + array[ offset + 2 ] = this.z; + + return array; + + } + + fromBufferAttribute( attribute, index ) { + + this.x = attribute.getX( index ); + this.y = attribute.getY( index ); + this.z = attribute.getZ( index ); + + return this; + + } + + random() { + + this.x = Math.random(); + this.y = Math.random(); + this.z = Math.random(); + + return this; + + } + + randomDirection() { + + // https://mathworld.wolfram.com/SpherePointPicking.html + + const theta = Math.random() * Math.PI * 2; + const u = Math.random() * 2 - 1; + const c = Math.sqrt( 1 - u * u ); + + this.x = c * Math.cos( theta ); + this.y = u; + this.z = c * Math.sin( theta ); + + return this; + + } + + *[ Symbol.iterator ]() { + + yield this.x; + yield this.y; + yield this.z; + + } + +} + +const _vector$c = /*@__PURE__*/ new Vector3(); +const _quaternion$4 = /*@__PURE__*/ new Quaternion(); + +class Box3 { + + constructor( min = new Vector3( + Infinity, + Infinity, + Infinity ), max = new Vector3( - Infinity, - Infinity, - Infinity ) ) { + + this.isBox3 = true; + + this.min = min; + this.max = max; + + } + + set( min, max ) { + + this.min.copy( min ); + this.max.copy( max ); + + return this; + + } + + setFromArray( array ) { + + this.makeEmpty(); + + for ( let i = 0, il = array.length; i < il; i += 3 ) { + + this.expandByPoint( _vector$b.fromArray( array, i ) ); + + } + + return this; + + } + + setFromBufferAttribute( attribute ) { + + this.makeEmpty(); + + for ( let i = 0, il = attribute.count; i < il; i ++ ) { + + this.expandByPoint( _vector$b.fromBufferAttribute( attribute, i ) ); + + } + + return this; + + } + + setFromPoints( points ) { + + this.makeEmpty(); + + for ( let i = 0, il = points.length; i < il; i ++ ) { + + this.expandByPoint( points[ i ] ); + + } + + return this; + + } + + setFromCenterAndSize( center, size ) { + + const halfSize = _vector$b.copy( size ).multiplyScalar( 0.5 ); + + this.min.copy( center ).sub( halfSize ); + this.max.copy( center ).add( halfSize ); + + return this; + + } + + setFromObject( object, precise = false ) { + + this.makeEmpty(); + + return this.expandByObject( object, precise ); + + } + + clone() { + + return new this.constructor().copy( this ); + + } + + copy( box ) { + + this.min.copy( box.min ); + this.max.copy( box.max ); + + return this; + + } + + makeEmpty() { + + this.min.x = this.min.y = this.min.z = + Infinity; + this.max.x = this.max.y = this.max.z = - Infinity; + + return this; + + } + + isEmpty() { + + // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes + + return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ) || ( this.max.z < this.min.z ); + + } + + getCenter( target ) { + + return this.isEmpty() ? target.set( 0, 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); + + } + + getSize( target ) { + + return this.isEmpty() ? target.set( 0, 0, 0 ) : target.subVectors( this.max, this.min ); + + } + + expandByPoint( point ) { + + this.min.min( point ); + this.max.max( point ); + + return this; + + } + + expandByVector( vector ) { + + this.min.sub( vector ); + this.max.add( vector ); + + return this; + + } + + expandByScalar( scalar ) { + + this.min.addScalar( - scalar ); + this.max.addScalar( scalar ); + + return this; + + } + + expandByObject( object, precise = false ) { + + // Computes the world-axis-aligned bounding box of an object (including its children), + // accounting for both the object's, and children's, world transforms + + object.updateWorldMatrix( false, false ); + + const geometry = object.geometry; + + if ( geometry !== undefined ) { + + const positionAttribute = geometry.getAttribute( 'position' ); + + // precise AABB computation based on vertex data requires at least a position attribute. + // instancing isn't supported so far and uses the normal (conservative) code path. + + if ( precise === true && positionAttribute !== undefined && object.isInstancedMesh !== true ) { + + for ( let i = 0, l = positionAttribute.count; i < l; i ++ ) { + + if ( object.isMesh === true ) { + + object.getVertexPosition( i, _vector$b ); + + } else { + + _vector$b.fromBufferAttribute( positionAttribute, i ); + + } + + _vector$b.applyMatrix4( object.matrixWorld ); + this.expandByPoint( _vector$b ); + + } + + } else { + + if ( object.boundingBox !== undefined ) { + + // object-level bounding box + + if ( object.boundingBox === null ) { + + object.computeBoundingBox(); + + } + + _box$4.copy( object.boundingBox ); + + + } else { + + // geometry-level bounding box + + if ( geometry.boundingBox === null ) { + + geometry.computeBoundingBox(); + + } + + _box$4.copy( geometry.boundingBox ); + + } + + _box$4.applyMatrix4( object.matrixWorld ); + + this.union( _box$4 ); + + } + + } + + const children = object.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { + + this.expandByObject( children[ i ], precise ); + + } + + return this; + + } + + containsPoint( point ) { + + return point.x >= this.min.x && point.x <= this.max.x && + point.y >= this.min.y && point.y <= this.max.y && + point.z >= this.min.z && point.z <= this.max.z; + + } + + containsBox( box ) { + + return this.min.x <= box.min.x && box.max.x <= this.max.x && + this.min.y <= box.min.y && box.max.y <= this.max.y && + this.min.z <= box.min.z && box.max.z <= this.max.z; + + } + + getParameter( point, target ) { + + // This can potentially have a divide by zero if the box + // has a size dimension of 0. + + return target.set( + ( point.x - this.min.x ) / ( this.max.x - this.min.x ), + ( point.y - this.min.y ) / ( this.max.y - this.min.y ), + ( point.z - this.min.z ) / ( this.max.z - this.min.z ) + ); + + } + + intersectsBox( box ) { + + // using 6 splitting planes to rule out intersections. + return box.max.x >= this.min.x && box.min.x <= this.max.x && + box.max.y >= this.min.y && box.min.y <= this.max.y && + box.max.z >= this.min.z && box.min.z <= this.max.z; + + } + + intersectsSphere( sphere ) { + + // Find the point on the AABB closest to the sphere center. + this.clampPoint( sphere.center, _vector$b ); + + // If that point is inside the sphere, the AABB and sphere intersect. + return _vector$b.distanceToSquared( sphere.center ) <= ( sphere.radius * sphere.radius ); + + } + + intersectsPlane( plane ) { + + // We compute the minimum and maximum dot product values. If those values + // are on the same side (back or front) of the plane, then there is no intersection. + + let min, max; + + if ( plane.normal.x > 0 ) { + + min = plane.normal.x * this.min.x; + max = plane.normal.x * this.max.x; + + } else { + + min = plane.normal.x * this.max.x; + max = plane.normal.x * this.min.x; + + } + + if ( plane.normal.y > 0 ) { + + min += plane.normal.y * this.min.y; + max += plane.normal.y * this.max.y; + + } else { + + min += plane.normal.y * this.max.y; + max += plane.normal.y * this.min.y; + + } + + if ( plane.normal.z > 0 ) { + + min += plane.normal.z * this.min.z; + max += plane.normal.z * this.max.z; + + } else { + + min += plane.normal.z * this.max.z; + max += plane.normal.z * this.min.z; + + } + + return ( min <= - plane.constant && max >= - plane.constant ); + + } + + intersectsTriangle( triangle ) { + + if ( this.isEmpty() ) { + + return false; + + } + + // compute box center and extents + this.getCenter( _center ); + _extents.subVectors( this.max, _center ); + + // translate triangle to aabb origin + _v0$2.subVectors( triangle.a, _center ); + _v1$7.subVectors( triangle.b, _center ); + _v2$4.subVectors( triangle.c, _center ); + + // compute edge vectors for triangle + _f0.subVectors( _v1$7, _v0$2 ); + _f1.subVectors( _v2$4, _v1$7 ); + _f2.subVectors( _v0$2, _v2$4 ); + + // test against axes that are given by cross product combinations of the edges of the triangle and the edges of the aabb + // make an axis testing of each of the 3 sides of the aabb against each of the 3 sides of the triangle = 9 axis of separation + // axis_ij = u_i x f_j (u0, u1, u2 = face normals of aabb = x,y,z axes vectors since aabb is axis aligned) + let axes = [ + 0, - _f0.z, _f0.y, 0, - _f1.z, _f1.y, 0, - _f2.z, _f2.y, + _f0.z, 0, - _f0.x, _f1.z, 0, - _f1.x, _f2.z, 0, - _f2.x, + - _f0.y, _f0.x, 0, - _f1.y, _f1.x, 0, - _f2.y, _f2.x, 0 + ]; + if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) { + + return false; + + } + + // test 3 face normals from the aabb + axes = [ 1, 0, 0, 0, 1, 0, 0, 0, 1 ]; + if ( ! satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ) ) { + + return false; + + } + + // finally testing the face normal of the triangle + // use already existing triangle edge vectors here + _triangleNormal.crossVectors( _f0, _f1 ); + axes = [ _triangleNormal.x, _triangleNormal.y, _triangleNormal.z ]; + + return satForAxes( axes, _v0$2, _v1$7, _v2$4, _extents ); + + } + + clampPoint( point, target ) { + + return target.copy( point ).clamp( this.min, this.max ); + + } + + distanceToPoint( point ) { + + return this.clampPoint( point, _vector$b ).distanceTo( point ); + + } + + getBoundingSphere( target ) { + + if ( this.isEmpty() ) { + + target.makeEmpty(); + + } else { + + this.getCenter( target.center ); + + target.radius = this.getSize( _vector$b ).length() * 0.5; + + } + + return target; + + } + + intersect( box ) { + + this.min.max( box.min ); + this.max.min( box.max ); + + // ensure that if there is no overlap, the result is fully empty, not slightly empty with non-inf/+inf values that will cause subsequence intersects to erroneously return valid values. + if ( this.isEmpty() ) this.makeEmpty(); + + return this; + + } + + union( box ) { + + this.min.min( box.min ); + this.max.max( box.max ); + + return this; + + } + + applyMatrix4( matrix ) { + + // transform of empty box is an empty box. + if ( this.isEmpty() ) return this; + + // NOTE: I am using a binary pattern to specify all 2^3 combinations below + _points[ 0 ].set( this.min.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 000 + _points[ 1 ].set( this.min.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 001 + _points[ 2 ].set( this.min.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 010 + _points[ 3 ].set( this.min.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 011 + _points[ 4 ].set( this.max.x, this.min.y, this.min.z ).applyMatrix4( matrix ); // 100 + _points[ 5 ].set( this.max.x, this.min.y, this.max.z ).applyMatrix4( matrix ); // 101 + _points[ 6 ].set( this.max.x, this.max.y, this.min.z ).applyMatrix4( matrix ); // 110 + _points[ 7 ].set( this.max.x, this.max.y, this.max.z ).applyMatrix4( matrix ); // 111 + + this.setFromPoints( _points ); + + return this; + + } + + translate( offset ) { + + this.min.add( offset ); + this.max.add( offset ); + + return this; + + } + + equals( box ) { + + return box.min.equals( this.min ) && box.max.equals( this.max ); + + } + +} + +const _points = [ + /*@__PURE__*/ new Vector3(), + /*@__PURE__*/ new Vector3(), + /*@__PURE__*/ new Vector3(), + /*@__PURE__*/ new Vector3(), + /*@__PURE__*/ new Vector3(), + /*@__PURE__*/ new Vector3(), + /*@__PURE__*/ new Vector3(), + /*@__PURE__*/ new Vector3() +]; + +const _vector$b = /*@__PURE__*/ new Vector3(); + +const _box$4 = /*@__PURE__*/ new Box3(); + +// triangle centered vertices + +const _v0$2 = /*@__PURE__*/ new Vector3(); +const _v1$7 = /*@__PURE__*/ new Vector3(); +const _v2$4 = /*@__PURE__*/ new Vector3(); + +// triangle edge vectors + +const _f0 = /*@__PURE__*/ new Vector3(); +const _f1 = /*@__PURE__*/ new Vector3(); +const _f2 = /*@__PURE__*/ new Vector3(); + +const _center = /*@__PURE__*/ new Vector3(); +const _extents = /*@__PURE__*/ new Vector3(); +const _triangleNormal = /*@__PURE__*/ new Vector3(); +const _testAxis = /*@__PURE__*/ new Vector3(); + +function satForAxes( axes, v0, v1, v2, extents ) { + + for ( let i = 0, j = axes.length - 3; i <= j; i += 3 ) { + + _testAxis.fromArray( axes, i ); + // project the aabb onto the separating axis + const r = extents.x * Math.abs( _testAxis.x ) + extents.y * Math.abs( _testAxis.y ) + extents.z * Math.abs( _testAxis.z ); + // project all 3 vertices of the triangle onto the separating axis + const p0 = v0.dot( _testAxis ); + const p1 = v1.dot( _testAxis ); + const p2 = v2.dot( _testAxis ); + // actual test, basically see if either of the most extreme of the triangle points intersects r + if ( Math.max( - Math.max( p0, p1, p2 ), Math.min( p0, p1, p2 ) ) > r ) { + + // points of the projected triangle are outside the projected half-length of the aabb + // the axis is separating and we can exit + return false; + + } + + } + + return true; + +} + +const _box$3 = /*@__PURE__*/ new Box3(); +const _v1$6 = /*@__PURE__*/ new Vector3(); +const _v2$3 = /*@__PURE__*/ new Vector3(); + +class Sphere { + + constructor( center = new Vector3(), radius = - 1 ) { + + this.isSphere = true; + + this.center = center; + this.radius = radius; + + } + + set( center, radius ) { + + this.center.copy( center ); + this.radius = radius; + + return this; + + } + + setFromPoints( points, optionalCenter ) { + + const center = this.center; + + if ( optionalCenter !== undefined ) { + + center.copy( optionalCenter ); + + } else { + + _box$3.setFromPoints( points ).getCenter( center ); + + } + + let maxRadiusSq = 0; + + for ( let i = 0, il = points.length; i < il; i ++ ) { + + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( points[ i ] ) ); + + } + + this.radius = Math.sqrt( maxRadiusSq ); + + return this; + + } + + copy( sphere ) { + + this.center.copy( sphere.center ); + this.radius = sphere.radius; + + return this; + + } + + isEmpty() { + + return ( this.radius < 0 ); + + } + + makeEmpty() { + + this.center.set( 0, 0, 0 ); + this.radius = - 1; + + return this; + + } + + containsPoint( point ) { + + return ( point.distanceToSquared( this.center ) <= ( this.radius * this.radius ) ); + + } + + distanceToPoint( point ) { + + return ( point.distanceTo( this.center ) - this.radius ); + + } + + intersectsSphere( sphere ) { + + const radiusSum = this.radius + sphere.radius; + + return sphere.center.distanceToSquared( this.center ) <= ( radiusSum * radiusSum ); + + } + + intersectsBox( box ) { + + return box.intersectsSphere( this ); + + } + + intersectsPlane( plane ) { + + return Math.abs( plane.distanceToPoint( this.center ) ) <= this.radius; + + } + + clampPoint( point, target ) { + + const deltaLengthSq = this.center.distanceToSquared( point ); + + target.copy( point ); + + if ( deltaLengthSq > ( this.radius * this.radius ) ) { + + target.sub( this.center ).normalize(); + target.multiplyScalar( this.radius ).add( this.center ); + + } + + return target; + + } + + getBoundingBox( target ) { + + if ( this.isEmpty() ) { + + // Empty sphere produces empty bounding box + target.makeEmpty(); + return target; + + } + + target.set( this.center, this.center ); + target.expandByScalar( this.radius ); + + return target; + + } + + applyMatrix4( matrix ) { + + this.center.applyMatrix4( matrix ); + this.radius = this.radius * matrix.getMaxScaleOnAxis(); + + return this; + + } + + translate( offset ) { + + this.center.add( offset ); + + return this; + + } + + expandByPoint( point ) { + + if ( this.isEmpty() ) { + + this.center.copy( point ); + + this.radius = 0; + + return this; + + } + + _v1$6.subVectors( point, this.center ); + + const lengthSq = _v1$6.lengthSq(); + + if ( lengthSq > ( this.radius * this.radius ) ) { + + // calculate the minimal sphere + + const length = Math.sqrt( lengthSq ); + + const delta = ( length - this.radius ) * 0.5; + + this.center.addScaledVector( _v1$6, delta / length ); + + this.radius += delta; + + } + + return this; + + } + + union( sphere ) { + + if ( sphere.isEmpty() ) { + + return this; + + } + + if ( this.isEmpty() ) { + + this.copy( sphere ); + + return this; + + } + + if ( this.center.equals( sphere.center ) === true ) { + + this.radius = Math.max( this.radius, sphere.radius ); + + } else { + + _v2$3.subVectors( sphere.center, this.center ).setLength( sphere.radius ); + + this.expandByPoint( _v1$6.copy( sphere.center ).add( _v2$3 ) ); + + this.expandByPoint( _v1$6.copy( sphere.center ).sub( _v2$3 ) ); + + } + + return this; + + } + + equals( sphere ) { + + return sphere.center.equals( this.center ) && ( sphere.radius === this.radius ); + + } + + clone() { + + return new this.constructor().copy( this ); + + } + +} + +const _vector$a = /*@__PURE__*/ new Vector3(); +const _segCenter = /*@__PURE__*/ new Vector3(); +const _segDir = /*@__PURE__*/ new Vector3(); +const _diff = /*@__PURE__*/ new Vector3(); + +const _edge1 = /*@__PURE__*/ new Vector3(); +const _edge2 = /*@__PURE__*/ new Vector3(); +const _normal$2 = /*@__PURE__*/ new Vector3(); + +class Ray { + + constructor( origin = new Vector3(), direction = new Vector3( 0, 0, - 1 ) ) { + + this.origin = origin; + this.direction = direction; + + } + + set( origin, direction ) { + + this.origin.copy( origin ); + this.direction.copy( direction ); + + return this; + + } + + copy( ray ) { + + this.origin.copy( ray.origin ); + this.direction.copy( ray.direction ); + + return this; + + } + + at( t, target ) { + + return target.copy( this.origin ).addScaledVector( this.direction, t ); + + } + + lookAt( v ) { + + this.direction.copy( v ).sub( this.origin ).normalize(); + + return this; + + } + + recast( t ) { + + this.origin.copy( this.at( t, _vector$a ) ); + + return this; + + } + + closestPointToPoint( point, target ) { + + target.subVectors( point, this.origin ); + + const directionDistance = target.dot( this.direction ); + + if ( directionDistance < 0 ) { + + return target.copy( this.origin ); + + } + + return target.copy( this.origin ).addScaledVector( this.direction, directionDistance ); + + } + + distanceToPoint( point ) { + + return Math.sqrt( this.distanceSqToPoint( point ) ); + + } + + distanceSqToPoint( point ) { + + const directionDistance = _vector$a.subVectors( point, this.origin ).dot( this.direction ); + + // point behind the ray + + if ( directionDistance < 0 ) { + + return this.origin.distanceToSquared( point ); + + } + + _vector$a.copy( this.origin ).addScaledVector( this.direction, directionDistance ); + + return _vector$a.distanceToSquared( point ); + + } + + distanceSqToSegment( v0, v1, optionalPointOnRay, optionalPointOnSegment ) { + + // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteDistRaySegment.h + // It returns the min distance between the ray and the segment + // defined by v0 and v1 + // It can also set two optional targets : + // - The closest point on the ray + // - The closest point on the segment + + _segCenter.copy( v0 ).add( v1 ).multiplyScalar( 0.5 ); + _segDir.copy( v1 ).sub( v0 ).normalize(); + _diff.copy( this.origin ).sub( _segCenter ); + + const segExtent = v0.distanceTo( v1 ) * 0.5; + const a01 = - this.direction.dot( _segDir ); + const b0 = _diff.dot( this.direction ); + const b1 = - _diff.dot( _segDir ); + const c = _diff.lengthSq(); + const det = Math.abs( 1 - a01 * a01 ); + let s0, s1, sqrDist, extDet; + + if ( det > 0 ) { + + // The ray and segment are not parallel. + + s0 = a01 * b1 - b0; + s1 = a01 * b0 - b1; + extDet = segExtent * det; + + if ( s0 >= 0 ) { + + if ( s1 >= - extDet ) { + + if ( s1 <= extDet ) { + + // region 0 + // Minimum at interior points of ray and segment. + + const invDet = 1 / det; + s0 *= invDet; + s1 *= invDet; + sqrDist = s0 * ( s0 + a01 * s1 + 2 * b0 ) + s1 * ( a01 * s0 + s1 + 2 * b1 ) + c; + + } else { + + // region 1 + + s1 = segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + + } + + } else { + + // region 5 + + s1 = - segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + + } + + } else { + + if ( s1 <= - extDet ) { + + // region 4 + + s0 = Math.max( 0, - ( - a01 * segExtent + b0 ) ); + s1 = ( s0 > 0 ) ? - segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + + } else if ( s1 <= extDet ) { + + // region 3 + + s0 = 0; + s1 = Math.min( Math.max( - segExtent, - b1 ), segExtent ); + sqrDist = s1 * ( s1 + 2 * b1 ) + c; + + } else { + + // region 2 + + s0 = Math.max( 0, - ( a01 * segExtent + b0 ) ); + s1 = ( s0 > 0 ) ? segExtent : Math.min( Math.max( - segExtent, - b1 ), segExtent ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + + } + + } + + } else { + + // Ray and segment are parallel. + + s1 = ( a01 > 0 ) ? - segExtent : segExtent; + s0 = Math.max( 0, - ( a01 * s1 + b0 ) ); + sqrDist = - s0 * s0 + s1 * ( s1 + 2 * b1 ) + c; + + } + + if ( optionalPointOnRay ) { + + optionalPointOnRay.copy( this.origin ).addScaledVector( this.direction, s0 ); + + } + + if ( optionalPointOnSegment ) { + + optionalPointOnSegment.copy( _segCenter ).addScaledVector( _segDir, s1 ); + + } + + return sqrDist; + + } + + intersectSphere( sphere, target ) { + + _vector$a.subVectors( sphere.center, this.origin ); + const tca = _vector$a.dot( this.direction ); + const d2 = _vector$a.dot( _vector$a ) - tca * tca; + const radius2 = sphere.radius * sphere.radius; + + if ( d2 > radius2 ) return null; + + const thc = Math.sqrt( radius2 - d2 ); + + // t0 = first intersect point - entrance on front of sphere + const t0 = tca - thc; + + // t1 = second intersect point - exit point on back of sphere + const t1 = tca + thc; + + // test to see if t1 is behind the ray - if so, return null + if ( t1 < 0 ) return null; + + // test to see if t0 is behind the ray: + // if it is, the ray is inside the sphere, so return the second exit point scaled by t1, + // in order to always return an intersect point that is in front of the ray. + if ( t0 < 0 ) return this.at( t1, target ); + + // else t0 is in front of the ray, so return the first collision point scaled by t0 + return this.at( t0, target ); + + } + + intersectsSphere( sphere ) { + + return this.distanceSqToPoint( sphere.center ) <= ( sphere.radius * sphere.radius ); + + } + + distanceToPlane( plane ) { + + const denominator = plane.normal.dot( this.direction ); + + if ( denominator === 0 ) { + + // line is coplanar, return origin + if ( plane.distanceToPoint( this.origin ) === 0 ) { + + return 0; + + } + + // Null is preferable to undefined since undefined means.... it is undefined + + return null; + + } + + const t = - ( this.origin.dot( plane.normal ) + plane.constant ) / denominator; + + // Return if the ray never intersects the plane + + return t >= 0 ? t : null; + + } + + intersectPlane( plane, target ) { + + const t = this.distanceToPlane( plane ); + + if ( t === null ) { + + return null; + + } + + return this.at( t, target ); + + } + + intersectsPlane( plane ) { + + // check if the ray lies on the plane first + + const distToPoint = plane.distanceToPoint( this.origin ); + + if ( distToPoint === 0 ) { + + return true; + + } + + const denominator = plane.normal.dot( this.direction ); + + if ( denominator * distToPoint < 0 ) { + + return true; + + } + + // ray origin is behind the plane (and is pointing behind it) + + return false; + + } + + intersectBox( box, target ) { + + let tmin, tmax, tymin, tymax, tzmin, tzmax; + + const invdirx = 1 / this.direction.x, + invdiry = 1 / this.direction.y, + invdirz = 1 / this.direction.z; + + const origin = this.origin; + + if ( invdirx >= 0 ) { + + tmin = ( box.min.x - origin.x ) * invdirx; + tmax = ( box.max.x - origin.x ) * invdirx; + + } else { + + tmin = ( box.max.x - origin.x ) * invdirx; + tmax = ( box.min.x - origin.x ) * invdirx; + + } + + if ( invdiry >= 0 ) { + + tymin = ( box.min.y - origin.y ) * invdiry; + tymax = ( box.max.y - origin.y ) * invdiry; + + } else { + + tymin = ( box.max.y - origin.y ) * invdiry; + tymax = ( box.min.y - origin.y ) * invdiry; + + } + + if ( ( tmin > tymax ) || ( tymin > tmax ) ) return null; + + if ( tymin > tmin || isNaN( tmin ) ) tmin = tymin; + + if ( tymax < tmax || isNaN( tmax ) ) tmax = tymax; + + if ( invdirz >= 0 ) { + + tzmin = ( box.min.z - origin.z ) * invdirz; + tzmax = ( box.max.z - origin.z ) * invdirz; + + } else { + + tzmin = ( box.max.z - origin.z ) * invdirz; + tzmax = ( box.min.z - origin.z ) * invdirz; + + } + + if ( ( tmin > tzmax ) || ( tzmin > tmax ) ) return null; + + if ( tzmin > tmin || tmin !== tmin ) tmin = tzmin; + + if ( tzmax < tmax || tmax !== tmax ) tmax = tzmax; + + //return point closest to the ray (positive side) + + if ( tmax < 0 ) return null; + + return this.at( tmin >= 0 ? tmin : tmax, target ); + + } + + intersectsBox( box ) { + + return this.intersectBox( box, _vector$a ) !== null; + + } + + intersectTriangle( a, b, c, backfaceCulling, target ) { + + // Compute the offset origin, edges, and normal. + + // from https://github.com/pmjoniak/GeometricTools/blob/master/GTEngine/Include/Mathematics/GteIntrRay3Triangle3.h + + _edge1.subVectors( b, a ); + _edge2.subVectors( c, a ); + _normal$2.crossVectors( _edge1, _edge2 ); + + // Solve Q + t*D = b1*E1 + b2*E2 (Q = kDiff, D = ray direction, + // E1 = kEdge1, E2 = kEdge2, N = Cross(E1,E2)) by + // |Dot(D,N)|*b1 = sign(Dot(D,N))*Dot(D,Cross(Q,E2)) + // |Dot(D,N)|*b2 = sign(Dot(D,N))*Dot(D,Cross(E1,Q)) + // |Dot(D,N)|*t = -sign(Dot(D,N))*Dot(Q,N) + let DdN = this.direction.dot( _normal$2 ); + let sign; + + if ( DdN > 0 ) { + + if ( backfaceCulling ) return null; + sign = 1; + + } else if ( DdN < 0 ) { + + sign = - 1; + DdN = - DdN; + + } else { + + return null; + + } + + _diff.subVectors( this.origin, a ); + const DdQxE2 = sign * this.direction.dot( _edge2.crossVectors( _diff, _edge2 ) ); + + // b1 < 0, no intersection + if ( DdQxE2 < 0 ) { + + return null; + + } + + const DdE1xQ = sign * this.direction.dot( _edge1.cross( _diff ) ); + + // b2 < 0, no intersection + if ( DdE1xQ < 0 ) { + + return null; + + } + + // b1+b2 > 1, no intersection + if ( DdQxE2 + DdE1xQ > DdN ) { + + return null; + + } + + // Line intersects triangle, check if ray does. + const QdN = - sign * _diff.dot( _normal$2 ); + + // t < 0, no intersection + if ( QdN < 0 ) { + + return null; + + } + + // Ray intersects triangle. + return this.at( QdN / DdN, target ); + + } + + applyMatrix4( matrix4 ) { + + this.origin.applyMatrix4( matrix4 ); + this.direction.transformDirection( matrix4 ); + + return this; + + } + + equals( ray ) { + + return ray.origin.equals( this.origin ) && ray.direction.equals( this.direction ); + + } + + clone() { + + return new this.constructor().copy( this ); + + } + +} + +class Matrix4 { + + constructor( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { + + Matrix4.prototype.isMatrix4 = true; + + this.elements = [ + + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + + ]; + + if ( n11 !== undefined ) { + + this.set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ); + + } + + } + + set( n11, n12, n13, n14, n21, n22, n23, n24, n31, n32, n33, n34, n41, n42, n43, n44 ) { + + const te = this.elements; + + te[ 0 ] = n11; te[ 4 ] = n12; te[ 8 ] = n13; te[ 12 ] = n14; + te[ 1 ] = n21; te[ 5 ] = n22; te[ 9 ] = n23; te[ 13 ] = n24; + te[ 2 ] = n31; te[ 6 ] = n32; te[ 10 ] = n33; te[ 14 ] = n34; + te[ 3 ] = n41; te[ 7 ] = n42; te[ 11 ] = n43; te[ 15 ] = n44; + + return this; + + } + + identity() { + + this.set( + + 1, 0, 0, 0, + 0, 1, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + + ); + + return this; + + } + + clone() { + + return new Matrix4().fromArray( this.elements ); + + } + + copy( m ) { + + const te = this.elements; + const me = m.elements; + + te[ 0 ] = me[ 0 ]; te[ 1 ] = me[ 1 ]; te[ 2 ] = me[ 2 ]; te[ 3 ] = me[ 3 ]; + te[ 4 ] = me[ 4 ]; te[ 5 ] = me[ 5 ]; te[ 6 ] = me[ 6 ]; te[ 7 ] = me[ 7 ]; + te[ 8 ] = me[ 8 ]; te[ 9 ] = me[ 9 ]; te[ 10 ] = me[ 10 ]; te[ 11 ] = me[ 11 ]; + te[ 12 ] = me[ 12 ]; te[ 13 ] = me[ 13 ]; te[ 14 ] = me[ 14 ]; te[ 15 ] = me[ 15 ]; + + return this; + + } + + copyPosition( m ) { + + const te = this.elements, me = m.elements; + + te[ 12 ] = me[ 12 ]; + te[ 13 ] = me[ 13 ]; + te[ 14 ] = me[ 14 ]; + + return this; + + } + + setFromMatrix3( m ) { + + const me = m.elements; + + this.set( + + me[ 0 ], me[ 3 ], me[ 6 ], 0, + me[ 1 ], me[ 4 ], me[ 7 ], 0, + me[ 2 ], me[ 5 ], me[ 8 ], 0, + 0, 0, 0, 1 + + ); + + return this; + + } + + extractBasis( xAxis, yAxis, zAxis ) { + + xAxis.setFromMatrixColumn( this, 0 ); + yAxis.setFromMatrixColumn( this, 1 ); + zAxis.setFromMatrixColumn( this, 2 ); + + return this; + + } + + makeBasis( xAxis, yAxis, zAxis ) { + + this.set( + xAxis.x, yAxis.x, zAxis.x, 0, + xAxis.y, yAxis.y, zAxis.y, 0, + xAxis.z, yAxis.z, zAxis.z, 0, + 0, 0, 0, 1 + ); + + return this; + + } + + extractRotation( m ) { + + // this method does not support reflection matrices + + const te = this.elements; + const me = m.elements; + + const scaleX = 1 / _v1$5.setFromMatrixColumn( m, 0 ).length(); + const scaleY = 1 / _v1$5.setFromMatrixColumn( m, 1 ).length(); + const scaleZ = 1 / _v1$5.setFromMatrixColumn( m, 2 ).length(); + + te[ 0 ] = me[ 0 ] * scaleX; + te[ 1 ] = me[ 1 ] * scaleX; + te[ 2 ] = me[ 2 ] * scaleX; + te[ 3 ] = 0; + + te[ 4 ] = me[ 4 ] * scaleY; + te[ 5 ] = me[ 5 ] * scaleY; + te[ 6 ] = me[ 6 ] * scaleY; + te[ 7 ] = 0; + + te[ 8 ] = me[ 8 ] * scaleZ; + te[ 9 ] = me[ 9 ] * scaleZ; + te[ 10 ] = me[ 10 ] * scaleZ; + te[ 11 ] = 0; + + te[ 12 ] = 0; + te[ 13 ] = 0; + te[ 14 ] = 0; + te[ 15 ] = 1; + + return this; + + } + + makeRotationFromEuler( euler ) { + + const te = this.elements; + + const x = euler.x, y = euler.y, z = euler.z; + const a = Math.cos( x ), b = Math.sin( x ); + const c = Math.cos( y ), d = Math.sin( y ); + const e = Math.cos( z ), f = Math.sin( z ); + + if ( euler.order === 'XYZ' ) { + + const ae = a * e, af = a * f, be = b * e, bf = b * f; + + te[ 0 ] = c * e; + te[ 4 ] = - c * f; + te[ 8 ] = d; + + te[ 1 ] = af + be * d; + te[ 5 ] = ae - bf * d; + te[ 9 ] = - b * c; + + te[ 2 ] = bf - ae * d; + te[ 6 ] = be + af * d; + te[ 10 ] = a * c; + + } else if ( euler.order === 'YXZ' ) { + + const ce = c * e, cf = c * f, de = d * e, df = d * f; + + te[ 0 ] = ce + df * b; + te[ 4 ] = de * b - cf; + te[ 8 ] = a * d; + + te[ 1 ] = a * f; + te[ 5 ] = a * e; + te[ 9 ] = - b; + + te[ 2 ] = cf * b - de; + te[ 6 ] = df + ce * b; + te[ 10 ] = a * c; + + } else if ( euler.order === 'ZXY' ) { + + const ce = c * e, cf = c * f, de = d * e, df = d * f; + + te[ 0 ] = ce - df * b; + te[ 4 ] = - a * f; + te[ 8 ] = de + cf * b; + + te[ 1 ] = cf + de * b; + te[ 5 ] = a * e; + te[ 9 ] = df - ce * b; + + te[ 2 ] = - a * d; + te[ 6 ] = b; + te[ 10 ] = a * c; + + } else if ( euler.order === 'ZYX' ) { + + const ae = a * e, af = a * f, be = b * e, bf = b * f; + + te[ 0 ] = c * e; + te[ 4 ] = be * d - af; + te[ 8 ] = ae * d + bf; + + te[ 1 ] = c * f; + te[ 5 ] = bf * d + ae; + te[ 9 ] = af * d - be; + + te[ 2 ] = - d; + te[ 6 ] = b * c; + te[ 10 ] = a * c; + + } else if ( euler.order === 'YZX' ) { + + const ac = a * c, ad = a * d, bc = b * c, bd = b * d; + + te[ 0 ] = c * e; + te[ 4 ] = bd - ac * f; + te[ 8 ] = bc * f + ad; + + te[ 1 ] = f; + te[ 5 ] = a * e; + te[ 9 ] = - b * e; + + te[ 2 ] = - d * e; + te[ 6 ] = ad * f + bc; + te[ 10 ] = ac - bd * f; + + } else if ( euler.order === 'XZY' ) { + + const ac = a * c, ad = a * d, bc = b * c, bd = b * d; + + te[ 0 ] = c * e; + te[ 4 ] = - f; + te[ 8 ] = d * e; + + te[ 1 ] = ac * f + bd; + te[ 5 ] = a * e; + te[ 9 ] = ad * f - bc; + + te[ 2 ] = bc * f - ad; + te[ 6 ] = b * e; + te[ 10 ] = bd * f + ac; + + } + + // bottom row + te[ 3 ] = 0; + te[ 7 ] = 0; + te[ 11 ] = 0; + + // last column + te[ 12 ] = 0; + te[ 13 ] = 0; + te[ 14 ] = 0; + te[ 15 ] = 1; + + return this; + + } + + makeRotationFromQuaternion( q ) { + + return this.compose( _zero, q, _one ); + + } + + lookAt( eye, target, up ) { + + const te = this.elements; + + _z.subVectors( eye, target ); + + if ( _z.lengthSq() === 0 ) { + + // eye and target are in the same position + + _z.z = 1; + + } + + _z.normalize(); + _x.crossVectors( up, _z ); + + if ( _x.lengthSq() === 0 ) { + + // up and z are parallel + + if ( Math.abs( up.z ) === 1 ) { + + _z.x += 0.0001; + + } else { + + _z.z += 0.0001; + + } + + _z.normalize(); + _x.crossVectors( up, _z ); + + } + + _x.normalize(); + _y.crossVectors( _z, _x ); + + te[ 0 ] = _x.x; te[ 4 ] = _y.x; te[ 8 ] = _z.x; + te[ 1 ] = _x.y; te[ 5 ] = _y.y; te[ 9 ] = _z.y; + te[ 2 ] = _x.z; te[ 6 ] = _y.z; te[ 10 ] = _z.z; + + return this; + + } + + multiply( m ) { + + return this.multiplyMatrices( this, m ); + + } + + premultiply( m ) { + + return this.multiplyMatrices( m, this ); + + } + + multiplyMatrices( a, b ) { + + const ae = a.elements; + const be = b.elements; + const te = this.elements; + + const a11 = ae[ 0 ], a12 = ae[ 4 ], a13 = ae[ 8 ], a14 = ae[ 12 ]; + const a21 = ae[ 1 ], a22 = ae[ 5 ], a23 = ae[ 9 ], a24 = ae[ 13 ]; + const a31 = ae[ 2 ], a32 = ae[ 6 ], a33 = ae[ 10 ], a34 = ae[ 14 ]; + const a41 = ae[ 3 ], a42 = ae[ 7 ], a43 = ae[ 11 ], a44 = ae[ 15 ]; + + const b11 = be[ 0 ], b12 = be[ 4 ], b13 = be[ 8 ], b14 = be[ 12 ]; + const b21 = be[ 1 ], b22 = be[ 5 ], b23 = be[ 9 ], b24 = be[ 13 ]; + const b31 = be[ 2 ], b32 = be[ 6 ], b33 = be[ 10 ], b34 = be[ 14 ]; + const b41 = be[ 3 ], b42 = be[ 7 ], b43 = be[ 11 ], b44 = be[ 15 ]; + + te[ 0 ] = a11 * b11 + a12 * b21 + a13 * b31 + a14 * b41; + te[ 4 ] = a11 * b12 + a12 * b22 + a13 * b32 + a14 * b42; + te[ 8 ] = a11 * b13 + a12 * b23 + a13 * b33 + a14 * b43; + te[ 12 ] = a11 * b14 + a12 * b24 + a13 * b34 + a14 * b44; + + te[ 1 ] = a21 * b11 + a22 * b21 + a23 * b31 + a24 * b41; + te[ 5 ] = a21 * b12 + a22 * b22 + a23 * b32 + a24 * b42; + te[ 9 ] = a21 * b13 + a22 * b23 + a23 * b33 + a24 * b43; + te[ 13 ] = a21 * b14 + a22 * b24 + a23 * b34 + a24 * b44; + + te[ 2 ] = a31 * b11 + a32 * b21 + a33 * b31 + a34 * b41; + te[ 6 ] = a31 * b12 + a32 * b22 + a33 * b32 + a34 * b42; + te[ 10 ] = a31 * b13 + a32 * b23 + a33 * b33 + a34 * b43; + te[ 14 ] = a31 * b14 + a32 * b24 + a33 * b34 + a34 * b44; + + te[ 3 ] = a41 * b11 + a42 * b21 + a43 * b31 + a44 * b41; + te[ 7 ] = a41 * b12 + a42 * b22 + a43 * b32 + a44 * b42; + te[ 11 ] = a41 * b13 + a42 * b23 + a43 * b33 + a44 * b43; + te[ 15 ] = a41 * b14 + a42 * b24 + a43 * b34 + a44 * b44; + + return this; + + } + + multiplyScalar( s ) { + + const te = this.elements; + + te[ 0 ] *= s; te[ 4 ] *= s; te[ 8 ] *= s; te[ 12 ] *= s; + te[ 1 ] *= s; te[ 5 ] *= s; te[ 9 ] *= s; te[ 13 ] *= s; + te[ 2 ] *= s; te[ 6 ] *= s; te[ 10 ] *= s; te[ 14 ] *= s; + te[ 3 ] *= s; te[ 7 ] *= s; te[ 11 ] *= s; te[ 15 ] *= s; + + return this; + + } + + determinant() { + + const te = this.elements; + + const n11 = te[ 0 ], n12 = te[ 4 ], n13 = te[ 8 ], n14 = te[ 12 ]; + const n21 = te[ 1 ], n22 = te[ 5 ], n23 = te[ 9 ], n24 = te[ 13 ]; + const n31 = te[ 2 ], n32 = te[ 6 ], n33 = te[ 10 ], n34 = te[ 14 ]; + const n41 = te[ 3 ], n42 = te[ 7 ], n43 = te[ 11 ], n44 = te[ 15 ]; + + //TODO: make this more efficient + //( based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm ) + + return ( + n41 * ( + + n14 * n23 * n32 + - n13 * n24 * n32 + - n14 * n22 * n33 + + n12 * n24 * n33 + + n13 * n22 * n34 + - n12 * n23 * n34 + ) + + n42 * ( + + n11 * n23 * n34 + - n11 * n24 * n33 + + n14 * n21 * n33 + - n13 * n21 * n34 + + n13 * n24 * n31 + - n14 * n23 * n31 + ) + + n43 * ( + + n11 * n24 * n32 + - n11 * n22 * n34 + - n14 * n21 * n32 + + n12 * n21 * n34 + + n14 * n22 * n31 + - n12 * n24 * n31 + ) + + n44 * ( + - n13 * n22 * n31 + - n11 * n23 * n32 + + n11 * n22 * n33 + + n13 * n21 * n32 + - n12 * n21 * n33 + + n12 * n23 * n31 + ) + + ); + + } + + transpose() { + + const te = this.elements; + let tmp; + + tmp = te[ 1 ]; te[ 1 ] = te[ 4 ]; te[ 4 ] = tmp; + tmp = te[ 2 ]; te[ 2 ] = te[ 8 ]; te[ 8 ] = tmp; + tmp = te[ 6 ]; te[ 6 ] = te[ 9 ]; te[ 9 ] = tmp; + + tmp = te[ 3 ]; te[ 3 ] = te[ 12 ]; te[ 12 ] = tmp; + tmp = te[ 7 ]; te[ 7 ] = te[ 13 ]; te[ 13 ] = tmp; + tmp = te[ 11 ]; te[ 11 ] = te[ 14 ]; te[ 14 ] = tmp; + + return this; + + } + + setPosition( x, y, z ) { + + const te = this.elements; + + if ( x.isVector3 ) { + + te[ 12 ] = x.x; + te[ 13 ] = x.y; + te[ 14 ] = x.z; + + } else { + + te[ 12 ] = x; + te[ 13 ] = y; + te[ 14 ] = z; + + } + + return this; + + } + + invert() { + + // based on http://www.euclideanspace.com/maths/algebra/matrix/functions/inverse/fourD/index.htm + const te = this.elements, + + n11 = te[ 0 ], n21 = te[ 1 ], n31 = te[ 2 ], n41 = te[ 3 ], + n12 = te[ 4 ], n22 = te[ 5 ], n32 = te[ 6 ], n42 = te[ 7 ], + n13 = te[ 8 ], n23 = te[ 9 ], n33 = te[ 10 ], n43 = te[ 11 ], + n14 = te[ 12 ], n24 = te[ 13 ], n34 = te[ 14 ], n44 = te[ 15 ], + + t11 = n23 * n34 * n42 - n24 * n33 * n42 + n24 * n32 * n43 - n22 * n34 * n43 - n23 * n32 * n44 + n22 * n33 * n44, + t12 = n14 * n33 * n42 - n13 * n34 * n42 - n14 * n32 * n43 + n12 * n34 * n43 + n13 * n32 * n44 - n12 * n33 * n44, + t13 = n13 * n24 * n42 - n14 * n23 * n42 + n14 * n22 * n43 - n12 * n24 * n43 - n13 * n22 * n44 + n12 * n23 * n44, + t14 = n14 * n23 * n32 - n13 * n24 * n32 - n14 * n22 * n33 + n12 * n24 * n33 + n13 * n22 * n34 - n12 * n23 * n34; + + const det = n11 * t11 + n21 * t12 + n31 * t13 + n41 * t14; + + if ( det === 0 ) return this.set( 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ); + + const detInv = 1 / det; + + te[ 0 ] = t11 * detInv; + te[ 1 ] = ( n24 * n33 * n41 - n23 * n34 * n41 - n24 * n31 * n43 + n21 * n34 * n43 + n23 * n31 * n44 - n21 * n33 * n44 ) * detInv; + te[ 2 ] = ( n22 * n34 * n41 - n24 * n32 * n41 + n24 * n31 * n42 - n21 * n34 * n42 - n22 * n31 * n44 + n21 * n32 * n44 ) * detInv; + te[ 3 ] = ( n23 * n32 * n41 - n22 * n33 * n41 - n23 * n31 * n42 + n21 * n33 * n42 + n22 * n31 * n43 - n21 * n32 * n43 ) * detInv; + + te[ 4 ] = t12 * detInv; + te[ 5 ] = ( n13 * n34 * n41 - n14 * n33 * n41 + n14 * n31 * n43 - n11 * n34 * n43 - n13 * n31 * n44 + n11 * n33 * n44 ) * detInv; + te[ 6 ] = ( n14 * n32 * n41 - n12 * n34 * n41 - n14 * n31 * n42 + n11 * n34 * n42 + n12 * n31 * n44 - n11 * n32 * n44 ) * detInv; + te[ 7 ] = ( n12 * n33 * n41 - n13 * n32 * n41 + n13 * n31 * n42 - n11 * n33 * n42 - n12 * n31 * n43 + n11 * n32 * n43 ) * detInv; + + te[ 8 ] = t13 * detInv; + te[ 9 ] = ( n14 * n23 * n41 - n13 * n24 * n41 - n14 * n21 * n43 + n11 * n24 * n43 + n13 * n21 * n44 - n11 * n23 * n44 ) * detInv; + te[ 10 ] = ( n12 * n24 * n41 - n14 * n22 * n41 + n14 * n21 * n42 - n11 * n24 * n42 - n12 * n21 * n44 + n11 * n22 * n44 ) * detInv; + te[ 11 ] = ( n13 * n22 * n41 - n12 * n23 * n41 - n13 * n21 * n42 + n11 * n23 * n42 + n12 * n21 * n43 - n11 * n22 * n43 ) * detInv; + + te[ 12 ] = t14 * detInv; + te[ 13 ] = ( n13 * n24 * n31 - n14 * n23 * n31 + n14 * n21 * n33 - n11 * n24 * n33 - n13 * n21 * n34 + n11 * n23 * n34 ) * detInv; + te[ 14 ] = ( n14 * n22 * n31 - n12 * n24 * n31 - n14 * n21 * n32 + n11 * n24 * n32 + n12 * n21 * n34 - n11 * n22 * n34 ) * detInv; + te[ 15 ] = ( n12 * n23 * n31 - n13 * n22 * n31 + n13 * n21 * n32 - n11 * n23 * n32 - n12 * n21 * n33 + n11 * n22 * n33 ) * detInv; + + return this; + + } + + scale( v ) { + + const te = this.elements; + const x = v.x, y = v.y, z = v.z; + + te[ 0 ] *= x; te[ 4 ] *= y; te[ 8 ] *= z; + te[ 1 ] *= x; te[ 5 ] *= y; te[ 9 ] *= z; + te[ 2 ] *= x; te[ 6 ] *= y; te[ 10 ] *= z; + te[ 3 ] *= x; te[ 7 ] *= y; te[ 11 ] *= z; + + return this; + + } + + getMaxScaleOnAxis() { + + const te = this.elements; + + const scaleXSq = te[ 0 ] * te[ 0 ] + te[ 1 ] * te[ 1 ] + te[ 2 ] * te[ 2 ]; + const scaleYSq = te[ 4 ] * te[ 4 ] + te[ 5 ] * te[ 5 ] + te[ 6 ] * te[ 6 ]; + const scaleZSq = te[ 8 ] * te[ 8 ] + te[ 9 ] * te[ 9 ] + te[ 10 ] * te[ 10 ]; + + return Math.sqrt( Math.max( scaleXSq, scaleYSq, scaleZSq ) ); + + } + + makeTranslation( x, y, z ) { + + if ( x.isVector3 ) { + + this.set( + + 1, 0, 0, x.x, + 0, 1, 0, x.y, + 0, 0, 1, x.z, + 0, 0, 0, 1 + + ); + + } else { + + this.set( + + 1, 0, 0, x, + 0, 1, 0, y, + 0, 0, 1, z, + 0, 0, 0, 1 + + ); + + } + + return this; + + } + + makeRotationX( theta ) { + + const c = Math.cos( theta ), s = Math.sin( theta ); + + this.set( + + 1, 0, 0, 0, + 0, c, - s, 0, + 0, s, c, 0, + 0, 0, 0, 1 + + ); + + return this; + + } + + makeRotationY( theta ) { + + const c = Math.cos( theta ), s = Math.sin( theta ); + + this.set( + + c, 0, s, 0, + 0, 1, 0, 0, + - s, 0, c, 0, + 0, 0, 0, 1 + + ); + + return this; + + } + + makeRotationZ( theta ) { + + const c = Math.cos( theta ), s = Math.sin( theta ); + + this.set( + + c, - s, 0, 0, + s, c, 0, 0, + 0, 0, 1, 0, + 0, 0, 0, 1 + + ); + + return this; + + } + + makeRotationAxis( axis, angle ) { + + // Based on http://www.gamedev.net/reference/articles/article1199.asp + + const c = Math.cos( angle ); + const s = Math.sin( angle ); + const t = 1 - c; + const x = axis.x, y = axis.y, z = axis.z; + const tx = t * x, ty = t * y; + + this.set( + + tx * x + c, tx * y - s * z, tx * z + s * y, 0, + tx * y + s * z, ty * y + c, ty * z - s * x, 0, + tx * z - s * y, ty * z + s * x, t * z * z + c, 0, + 0, 0, 0, 1 + + ); + + return this; + + } + + makeScale( x, y, z ) { + + this.set( + + x, 0, 0, 0, + 0, y, 0, 0, + 0, 0, z, 0, + 0, 0, 0, 1 + + ); + + return this; + + } + + makeShear( xy, xz, yx, yz, zx, zy ) { + + this.set( + + 1, yx, zx, 0, + xy, 1, zy, 0, + xz, yz, 1, 0, + 0, 0, 0, 1 + + ); + + return this; + + } + + compose( position, quaternion, scale ) { + + const te = this.elements; + + const x = quaternion._x, y = quaternion._y, z = quaternion._z, w = quaternion._w; + const x2 = x + x, y2 = y + y, z2 = z + z; + const xx = x * x2, xy = x * y2, xz = x * z2; + const yy = y * y2, yz = y * z2, zz = z * z2; + const wx = w * x2, wy = w * y2, wz = w * z2; + + const sx = scale.x, sy = scale.y, sz = scale.z; + + te[ 0 ] = ( 1 - ( yy + zz ) ) * sx; + te[ 1 ] = ( xy + wz ) * sx; + te[ 2 ] = ( xz - wy ) * sx; + te[ 3 ] = 0; + + te[ 4 ] = ( xy - wz ) * sy; + te[ 5 ] = ( 1 - ( xx + zz ) ) * sy; + te[ 6 ] = ( yz + wx ) * sy; + te[ 7 ] = 0; + + te[ 8 ] = ( xz + wy ) * sz; + te[ 9 ] = ( yz - wx ) * sz; + te[ 10 ] = ( 1 - ( xx + yy ) ) * sz; + te[ 11 ] = 0; + + te[ 12 ] = position.x; + te[ 13 ] = position.y; + te[ 14 ] = position.z; + te[ 15 ] = 1; + + return this; + + } + + decompose( position, quaternion, scale ) { + + const te = this.elements; + + let sx = _v1$5.set( te[ 0 ], te[ 1 ], te[ 2 ] ).length(); + const sy = _v1$5.set( te[ 4 ], te[ 5 ], te[ 6 ] ).length(); + const sz = _v1$5.set( te[ 8 ], te[ 9 ], te[ 10 ] ).length(); + + // if determine is negative, we need to invert one scale + const det = this.determinant(); + if ( det < 0 ) sx = - sx; + + position.x = te[ 12 ]; + position.y = te[ 13 ]; + position.z = te[ 14 ]; + + // scale the rotation part + _m1$2.copy( this ); + + const invSX = 1 / sx; + const invSY = 1 / sy; + const invSZ = 1 / sz; + + _m1$2.elements[ 0 ] *= invSX; + _m1$2.elements[ 1 ] *= invSX; + _m1$2.elements[ 2 ] *= invSX; + + _m1$2.elements[ 4 ] *= invSY; + _m1$2.elements[ 5 ] *= invSY; + _m1$2.elements[ 6 ] *= invSY; + + _m1$2.elements[ 8 ] *= invSZ; + _m1$2.elements[ 9 ] *= invSZ; + _m1$2.elements[ 10 ] *= invSZ; + + quaternion.setFromRotationMatrix( _m1$2 ); + + scale.x = sx; + scale.y = sy; + scale.z = sz; + + return this; + + } + + makePerspective( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) { + + const te = this.elements; + const x = 2 * near / ( right - left ); + const y = 2 * near / ( top - bottom ); + + const a = ( right + left ) / ( right - left ); + const b = ( top + bottom ) / ( top - bottom ); + + let c, d; + + if ( coordinateSystem === WebGLCoordinateSystem ) { + + c = - ( far + near ) / ( far - near ); + d = ( - 2 * far * near ) / ( far - near ); + + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { + + c = - far / ( far - near ); + d = ( - far * near ) / ( far - near ); + + } else { + + throw new Error( 'THREE.Matrix4.makePerspective(): Invalid coordinate system: ' + coordinateSystem ); + + } + + te[ 0 ] = x; te[ 4 ] = 0; te[ 8 ] = a; te[ 12 ] = 0; + te[ 1 ] = 0; te[ 5 ] = y; te[ 9 ] = b; te[ 13 ] = 0; + te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = c; te[ 14 ] = d; + te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = - 1; te[ 15 ] = 0; + + return this; + + } + + makeOrthographic( left, right, top, bottom, near, far, coordinateSystem = WebGLCoordinateSystem ) { + + const te = this.elements; + const w = 1.0 / ( right - left ); + const h = 1.0 / ( top - bottom ); + const p = 1.0 / ( far - near ); + + const x = ( right + left ) * w; + const y = ( top + bottom ) * h; + + let z, zInv; + + if ( coordinateSystem === WebGLCoordinateSystem ) { + + z = ( far + near ) * p; + zInv = - 2 * p; + + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { + + z = near * p; + zInv = - 1 * p; + + } else { + + throw new Error( 'THREE.Matrix4.makeOrthographic(): Invalid coordinate system: ' + coordinateSystem ); + + } + + te[ 0 ] = 2 * w; te[ 4 ] = 0; te[ 8 ] = 0; te[ 12 ] = - x; + te[ 1 ] = 0; te[ 5 ] = 2 * h; te[ 9 ] = 0; te[ 13 ] = - y; + te[ 2 ] = 0; te[ 6 ] = 0; te[ 10 ] = zInv; te[ 14 ] = - z; + te[ 3 ] = 0; te[ 7 ] = 0; te[ 11 ] = 0; te[ 15 ] = 1; + + return this; + + } + + equals( matrix ) { + + const te = this.elements; + const me = matrix.elements; + + for ( let i = 0; i < 16; i ++ ) { + + if ( te[ i ] !== me[ i ] ) return false; + + } + + return true; + + } + + fromArray( array, offset = 0 ) { + + for ( let i = 0; i < 16; i ++ ) { + + this.elements[ i ] = array[ i + offset ]; + + } + + return this; + + } + + toArray( array = [], offset = 0 ) { + + const te = this.elements; + + array[ offset ] = te[ 0 ]; + array[ offset + 1 ] = te[ 1 ]; + array[ offset + 2 ] = te[ 2 ]; + array[ offset + 3 ] = te[ 3 ]; + + array[ offset + 4 ] = te[ 4 ]; + array[ offset + 5 ] = te[ 5 ]; + array[ offset + 6 ] = te[ 6 ]; + array[ offset + 7 ] = te[ 7 ]; + + array[ offset + 8 ] = te[ 8 ]; + array[ offset + 9 ] = te[ 9 ]; + array[ offset + 10 ] = te[ 10 ]; + array[ offset + 11 ] = te[ 11 ]; + + array[ offset + 12 ] = te[ 12 ]; + array[ offset + 13 ] = te[ 13 ]; + array[ offset + 14 ] = te[ 14 ]; + array[ offset + 15 ] = te[ 15 ]; + + return array; + + } + +} + +const _v1$5 = /*@__PURE__*/ new Vector3(); +const _m1$2 = /*@__PURE__*/ new Matrix4(); +const _zero = /*@__PURE__*/ new Vector3( 0, 0, 0 ); +const _one = /*@__PURE__*/ new Vector3( 1, 1, 1 ); +const _x = /*@__PURE__*/ new Vector3(); +const _y = /*@__PURE__*/ new Vector3(); +const _z = /*@__PURE__*/ new Vector3(); + +const _matrix$2 = /*@__PURE__*/ new Matrix4(); +const _quaternion$3 = /*@__PURE__*/ new Quaternion(); + +class Euler { + + constructor( x = 0, y = 0, z = 0, order = Euler.DEFAULT_ORDER ) { + + this.isEuler = true; + + this._x = x; + this._y = y; + this._z = z; + this._order = order; + + } + + get x() { + + return this._x; + + } + + set x( value ) { + + this._x = value; + this._onChangeCallback(); + + } + + get y() { + + return this._y; + + } + + set y( value ) { + + this._y = value; + this._onChangeCallback(); + + } + + get z() { + + return this._z; + + } + + set z( value ) { + + this._z = value; + this._onChangeCallback(); + + } + + get order() { + + return this._order; + + } + + set order( value ) { + + this._order = value; + this._onChangeCallback(); + + } + + set( x, y, z, order = this._order ) { + + this._x = x; + this._y = y; + this._z = z; + this._order = order; + + this._onChangeCallback(); + + return this; + + } + + clone() { + + return new this.constructor( this._x, this._y, this._z, this._order ); + + } + + copy( euler ) { + + this._x = euler._x; + this._y = euler._y; + this._z = euler._z; + this._order = euler._order; + + this._onChangeCallback(); + + return this; + + } + + setFromRotationMatrix( m, order = this._order, update = true ) { + + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + + const te = m.elements; + const m11 = te[ 0 ], m12 = te[ 4 ], m13 = te[ 8 ]; + const m21 = te[ 1 ], m22 = te[ 5 ], m23 = te[ 9 ]; + const m31 = te[ 2 ], m32 = te[ 6 ], m33 = te[ 10 ]; + + switch ( order ) { + + case 'XYZ': + + this._y = Math.asin( clamp$1( m13, - 1, 1 ) ); + + if ( Math.abs( m13 ) < 0.9999999 ) { + + this._x = Math.atan2( - m23, m33 ); + this._z = Math.atan2( - m12, m11 ); + + } else { + + this._x = Math.atan2( m32, m22 ); + this._z = 0; + + } + + break; + + case 'YXZ': + + this._x = Math.asin( - clamp$1( m23, - 1, 1 ) ); + + if ( Math.abs( m23 ) < 0.9999999 ) { + + this._y = Math.atan2( m13, m33 ); + this._z = Math.atan2( m21, m22 ); + + } else { + + this._y = Math.atan2( - m31, m11 ); + this._z = 0; + + } + + break; + + case 'ZXY': + + this._x = Math.asin( clamp$1( m32, - 1, 1 ) ); + + if ( Math.abs( m32 ) < 0.9999999 ) { + + this._y = Math.atan2( - m31, m33 ); + this._z = Math.atan2( - m12, m22 ); + + } else { + + this._y = 0; + this._z = Math.atan2( m21, m11 ); + + } + + break; + + case 'ZYX': + + this._y = Math.asin( - clamp$1( m31, - 1, 1 ) ); + + if ( Math.abs( m31 ) < 0.9999999 ) { + + this._x = Math.atan2( m32, m33 ); + this._z = Math.atan2( m21, m11 ); + + } else { + + this._x = 0; + this._z = Math.atan2( - m12, m22 ); + + } + + break; + + case 'YZX': + + this._z = Math.asin( clamp$1( m21, - 1, 1 ) ); + + if ( Math.abs( m21 ) < 0.9999999 ) { + + this._x = Math.atan2( - m23, m22 ); + this._y = Math.atan2( - m31, m11 ); + + } else { + + this._x = 0; + this._y = Math.atan2( m13, m33 ); + + } + + break; + + case 'XZY': + + this._z = Math.asin( - clamp$1( m12, - 1, 1 ) ); + + if ( Math.abs( m12 ) < 0.9999999 ) { + + this._x = Math.atan2( m32, m22 ); + this._y = Math.atan2( m13, m11 ); + + } else { + + this._x = Math.atan2( - m23, m33 ); + this._y = 0; + + } + + break; + + default: + + console.warn( 'THREE.Euler: .setFromRotationMatrix() encountered an unknown order: ' + order ); + + } + + this._order = order; + + if ( update === true ) this._onChangeCallback(); + + return this; + + } + + setFromQuaternion( q, order, update ) { + + _matrix$2.makeRotationFromQuaternion( q ); + + return this.setFromRotationMatrix( _matrix$2, order, update ); + + } + + setFromVector3( v, order = this._order ) { + + return this.set( v.x, v.y, v.z, order ); + + } + + reorder( newOrder ) { + + // WARNING: this discards revolution information -bhouston + + _quaternion$3.setFromEuler( this ); + + return this.setFromQuaternion( _quaternion$3, newOrder ); + + } + + equals( euler ) { + + return ( euler._x === this._x ) && ( euler._y === this._y ) && ( euler._z === this._z ) && ( euler._order === this._order ); + + } + + fromArray( array ) { + + this._x = array[ 0 ]; + this._y = array[ 1 ]; + this._z = array[ 2 ]; + if ( array[ 3 ] !== undefined ) this._order = array[ 3 ]; + + this._onChangeCallback(); + + return this; + + } + + toArray( array = [], offset = 0 ) { + + array[ offset ] = this._x; + array[ offset + 1 ] = this._y; + array[ offset + 2 ] = this._z; + array[ offset + 3 ] = this._order; + + return array; + + } + + _onChange( callback ) { + + this._onChangeCallback = callback; + + return this; + + } + + _onChangeCallback() {} + + *[ Symbol.iterator ]() { + + yield this._x; + yield this._y; + yield this._z; + yield this._order; + + } + +} + +Euler.DEFAULT_ORDER = 'XYZ'; + +class Layers { + + constructor() { + + this.mask = 1 | 0; + + } + + set( channel ) { + + this.mask = ( 1 << channel | 0 ) >>> 0; + + } + + enable( channel ) { + + this.mask |= 1 << channel | 0; + + } + + enableAll() { + + this.mask = 0xffffffff | 0; + + } + + toggle( channel ) { + + this.mask ^= 1 << channel | 0; + + } + + disable( channel ) { + + this.mask &= ~ ( 1 << channel | 0 ); + + } + + disableAll() { + + this.mask = 0; + + } + + test( layers ) { + + return ( this.mask & layers.mask ) !== 0; + + } + + isEnabled( channel ) { + + return ( this.mask & ( 1 << channel | 0 ) ) !== 0; + + } + +} + +let _object3DId = 0; + +const _v1$4 = /*@__PURE__*/ new Vector3(); +const _q1 = /*@__PURE__*/ new Quaternion(); +const _m1$1 = /*@__PURE__*/ new Matrix4(); +const _target$1 = /*@__PURE__*/ new Vector3(); + +const _position$3 = /*@__PURE__*/ new Vector3(); +const _scale$2 = /*@__PURE__*/ new Vector3(); +const _quaternion$2 = /*@__PURE__*/ new Quaternion(); + +const _xAxis = /*@__PURE__*/ new Vector3( 1, 0, 0 ); +const _yAxis = /*@__PURE__*/ new Vector3( 0, 1, 0 ); +const _zAxis = /*@__PURE__*/ new Vector3( 0, 0, 1 ); + +const _addedEvent = { type: 'added' }; +const _removedEvent = { type: 'removed' }; + +const _childaddedEvent = { type: 'childadded', child: null }; +const _childremovedEvent = { type: 'childremoved', child: null }; + +class Object3D extends EventDispatcher { + + constructor() { + + super(); + + this.isObject3D = true; + + Object.defineProperty( this, 'id', { value: _object3DId ++ } ); + + this.uuid = generateUUID(); + + this.name = ''; + this.type = 'Object3D'; + + this.parent = null; + this.children = []; + + this.up = Object3D.DEFAULT_UP.clone(); + + const position = new Vector3(); + const rotation = new Euler(); + const quaternion = new Quaternion(); + const scale = new Vector3( 1, 1, 1 ); + + function onRotationChange() { + + quaternion.setFromEuler( rotation, false ); + + } + + function onQuaternionChange() { + + rotation.setFromQuaternion( quaternion, undefined, false ); + + } + + rotation._onChange( onRotationChange ); + quaternion._onChange( onQuaternionChange ); + + Object.defineProperties( this, { + position: { + configurable: true, + enumerable: true, + value: position + }, + rotation: { + configurable: true, + enumerable: true, + value: rotation + }, + quaternion: { + configurable: true, + enumerable: true, + value: quaternion + }, + scale: { + configurable: true, + enumerable: true, + value: scale + }, + modelViewMatrix: { + value: new Matrix4() + }, + normalMatrix: { + value: new Matrix3() + } + } ); + + this.matrix = new Matrix4(); + this.matrixWorld = new Matrix4(); + + this.matrixAutoUpdate = Object3D.DEFAULT_MATRIX_AUTO_UPDATE; + + this.matrixWorldAutoUpdate = Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE; // checked by the renderer + this.matrixWorldNeedsUpdate = false; + + this.layers = new Layers(); + this.visible = true; + + this.castShadow = false; + this.receiveShadow = false; + + this.frustumCulled = true; + this.renderOrder = 0; + + this.animations = []; + + this.userData = {}; + + } + + onBeforeShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {} + + onAfterShadow( /* renderer, object, camera, shadowCamera, geometry, depthMaterial, group */ ) {} + + onBeforeRender( /* renderer, scene, camera, geometry, material, group */ ) {} + + onAfterRender( /* renderer, scene, camera, geometry, material, group */ ) {} + + applyMatrix4( matrix ) { + + if ( this.matrixAutoUpdate ) this.updateMatrix(); + + this.matrix.premultiply( matrix ); + + this.matrix.decompose( this.position, this.quaternion, this.scale ); + + } + + applyQuaternion( q ) { + + this.quaternion.premultiply( q ); + + return this; + + } + + setRotationFromAxisAngle( axis, angle ) { + + // assumes axis is normalized + + this.quaternion.setFromAxisAngle( axis, angle ); + + } + + setRotationFromEuler( euler ) { + + this.quaternion.setFromEuler( euler, true ); + + } + + setRotationFromMatrix( m ) { + + // assumes the upper 3x3 of m is a pure rotation matrix (i.e, unscaled) + + this.quaternion.setFromRotationMatrix( m ); + + } + + setRotationFromQuaternion( q ) { + + // assumes q is normalized + + this.quaternion.copy( q ); + + } + + rotateOnAxis( axis, angle ) { + + // rotate object on axis in object space + // axis is assumed to be normalized + + _q1.setFromAxisAngle( axis, angle ); + + this.quaternion.multiply( _q1 ); + + return this; + + } + + rotateOnWorldAxis( axis, angle ) { + + // rotate object on axis in world space + // axis is assumed to be normalized + // method assumes no rotated parent + + _q1.setFromAxisAngle( axis, angle ); + + this.quaternion.premultiply( _q1 ); + + return this; + + } + + rotateX( angle ) { + + return this.rotateOnAxis( _xAxis, angle ); + + } + + rotateY( angle ) { + + return this.rotateOnAxis( _yAxis, angle ); + + } + + rotateZ( angle ) { + + return this.rotateOnAxis( _zAxis, angle ); + + } + + translateOnAxis( axis, distance ) { + + // translate object by distance along axis in object space + // axis is assumed to be normalized + + _v1$4.copy( axis ).applyQuaternion( this.quaternion ); + + this.position.add( _v1$4.multiplyScalar( distance ) ); + + return this; + + } + + translateX( distance ) { + + return this.translateOnAxis( _xAxis, distance ); + + } + + translateY( distance ) { + + return this.translateOnAxis( _yAxis, distance ); + + } + + translateZ( distance ) { + + return this.translateOnAxis( _zAxis, distance ); + + } + + localToWorld( vector ) { + + this.updateWorldMatrix( true, false ); + + return vector.applyMatrix4( this.matrixWorld ); + + } + + worldToLocal( vector ) { + + this.updateWorldMatrix( true, false ); + + return vector.applyMatrix4( _m1$1.copy( this.matrixWorld ).invert() ); + + } + + lookAt( x, y, z ) { + + // This method does not support objects having non-uniformly-scaled parent(s) + + if ( x.isVector3 ) { + + _target$1.copy( x ); + + } else { + + _target$1.set( x, y, z ); + + } + + const parent = this.parent; + + this.updateWorldMatrix( true, false ); + + _position$3.setFromMatrixPosition( this.matrixWorld ); + + if ( this.isCamera || this.isLight ) { + + _m1$1.lookAt( _position$3, _target$1, this.up ); + + } else { + + _m1$1.lookAt( _target$1, _position$3, this.up ); + + } + + this.quaternion.setFromRotationMatrix( _m1$1 ); + + if ( parent ) { + + _m1$1.extractRotation( parent.matrixWorld ); + _q1.setFromRotationMatrix( _m1$1 ); + this.quaternion.premultiply( _q1.invert() ); + + } + + } + + add( object ) { + + if ( arguments.length > 1 ) { + + for ( let i = 0; i < arguments.length; i ++ ) { + + this.add( arguments[ i ] ); + + } + + return this; + + } + + if ( object === this ) { + + console.error( 'THREE.Object3D.add: object can\'t be added as a child of itself.', object ); + return this; + + } + + if ( object && object.isObject3D ) { + + object.removeFromParent(); + object.parent = this; + this.children.push( object ); + + object.dispatchEvent( _addedEvent ); + + _childaddedEvent.child = object; + this.dispatchEvent( _childaddedEvent ); + _childaddedEvent.child = null; + + } else { + + console.error( 'THREE.Object3D.add: object not an instance of THREE.Object3D.', object ); + + } + + return this; + + } + + remove( object ) { + + if ( arguments.length > 1 ) { + + for ( let i = 0; i < arguments.length; i ++ ) { + + this.remove( arguments[ i ] ); + + } + + return this; + + } + + const index = this.children.indexOf( object ); + + if ( index !== - 1 ) { + + object.parent = null; + this.children.splice( index, 1 ); + + object.dispatchEvent( _removedEvent ); + + _childremovedEvent.child = object; + this.dispatchEvent( _childremovedEvent ); + _childremovedEvent.child = null; + + } + + return this; + + } + + removeFromParent() { + + const parent = this.parent; + + if ( parent !== null ) { + + parent.remove( this ); + + } + + return this; + + } + + clear() { + + return this.remove( ... this.children ); + + } + + attach( object ) { + + // adds object as a child of this, while maintaining the object's world transform + + // Note: This method does not support scene graphs having non-uniformly-scaled nodes(s) + + this.updateWorldMatrix( true, false ); + + _m1$1.copy( this.matrixWorld ).invert(); + + if ( object.parent !== null ) { + + object.parent.updateWorldMatrix( true, false ); + + _m1$1.multiply( object.parent.matrixWorld ); + + } + + object.applyMatrix4( _m1$1 ); + + object.removeFromParent(); + object.parent = this; + this.children.push( object ); + + object.updateWorldMatrix( false, true ); + + object.dispatchEvent( _addedEvent ); + + _childaddedEvent.child = object; + this.dispatchEvent( _childaddedEvent ); + _childaddedEvent.child = null; + + return this; + + } + + getObjectById( id ) { + + return this.getObjectByProperty( 'id', id ); + + } + + getObjectByName( name ) { + + return this.getObjectByProperty( 'name', name ); + + } + + getObjectByProperty( name, value ) { + + if ( this[ name ] === value ) return this; + + for ( let i = 0, l = this.children.length; i < l; i ++ ) { + + const child = this.children[ i ]; + const object = child.getObjectByProperty( name, value ); + + if ( object !== undefined ) { + + return object; + + } + + } + + return undefined; + + } + + getObjectsByProperty( name, value, result = [] ) { + + if ( this[ name ] === value ) result.push( this ); + + const children = this.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { + + children[ i ].getObjectsByProperty( name, value, result ); + + } + + return result; + + } + + getWorldPosition( target ) { + + this.updateWorldMatrix( true, false ); + + return target.setFromMatrixPosition( this.matrixWorld ); + + } + + getWorldQuaternion( target ) { + + this.updateWorldMatrix( true, false ); + + this.matrixWorld.decompose( _position$3, target, _scale$2 ); + + return target; + + } + + getWorldScale( target ) { + + this.updateWorldMatrix( true, false ); + + this.matrixWorld.decompose( _position$3, _quaternion$2, target ); + + return target; + + } + + getWorldDirection( target ) { + + this.updateWorldMatrix( true, false ); + + const e = this.matrixWorld.elements; + + return target.set( e[ 8 ], e[ 9 ], e[ 10 ] ).normalize(); + + } + + raycast( /* raycaster, intersects */ ) {} + + traverse( callback ) { + + callback( this ); + + const children = this.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { + + children[ i ].traverse( callback ); + + } + + } + + traverseVisible( callback ) { + + if ( this.visible === false ) return; + + callback( this ); + + const children = this.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { + + children[ i ].traverseVisible( callback ); + + } + + } + + traverseAncestors( callback ) { + + const parent = this.parent; + + if ( parent !== null ) { + + callback( parent ); + + parent.traverseAncestors( callback ); + + } + + } + + updateMatrix() { + + this.matrix.compose( this.position, this.quaternion, this.scale ); + + this.matrixWorldNeedsUpdate = true; + + } + + updateMatrixWorld( force ) { + + if ( this.matrixAutoUpdate ) this.updateMatrix(); + + if ( this.matrixWorldNeedsUpdate || force ) { + + if ( this.matrixWorldAutoUpdate === true ) { + + if ( this.parent === null ) { + + this.matrixWorld.copy( this.matrix ); + + } else { + + this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); + + } + + } + + this.matrixWorldNeedsUpdate = false; + + force = true; + + } + + // make sure descendants are updated if required + + const children = this.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { + + const child = children[ i ]; + + child.updateMatrixWorld( force ); + + } + + } + + updateWorldMatrix( updateParents, updateChildren ) { + + const parent = this.parent; + + if ( updateParents === true && parent !== null ) { + + parent.updateWorldMatrix( true, false ); + + } + + if ( this.matrixAutoUpdate ) this.updateMatrix(); + + if ( this.matrixWorldAutoUpdate === true ) { + + if ( this.parent === null ) { + + this.matrixWorld.copy( this.matrix ); + + } else { + + this.matrixWorld.multiplyMatrices( this.parent.matrixWorld, this.matrix ); + + } + + } + + // make sure descendants are updated + + if ( updateChildren === true ) { + + const children = this.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { + + const child = children[ i ]; + + child.updateWorldMatrix( false, true ); + + } + + } + + } + + toJSON( meta ) { + + // meta is a string when called from JSON.stringify + const isRootObject = ( meta === undefined || typeof meta === 'string' ); + + const output = {}; + + // meta is a hash used to collect geometries, materials. + // not providing it implies that this is the root object + // being serialized. + if ( isRootObject ) { + + // initialize meta obj + meta = { + geometries: {}, + materials: {}, + textures: {}, + images: {}, + shapes: {}, + skeletons: {}, + animations: {}, + nodes: {} + }; + + output.metadata = { + version: 4.6, + type: 'Object', + generator: 'Object3D.toJSON' + }; + + } + + // standard Object3D serialization + + const object = {}; + + object.uuid = this.uuid; + object.type = this.type; + + if ( this.name !== '' ) object.name = this.name; + if ( this.castShadow === true ) object.castShadow = true; + if ( this.receiveShadow === true ) object.receiveShadow = true; + if ( this.visible === false ) object.visible = false; + if ( this.frustumCulled === false ) object.frustumCulled = false; + if ( this.renderOrder !== 0 ) object.renderOrder = this.renderOrder; + if ( Object.keys( this.userData ).length > 0 ) object.userData = this.userData; + + object.layers = this.layers.mask; + object.matrix = this.matrix.toArray(); + object.up = this.up.toArray(); + + if ( this.matrixAutoUpdate === false ) object.matrixAutoUpdate = false; + + // object specific properties + + if ( this.isInstancedMesh ) { + + object.type = 'InstancedMesh'; + object.count = this.count; + object.instanceMatrix = this.instanceMatrix.toJSON(); + if ( this.instanceColor !== null ) object.instanceColor = this.instanceColor.toJSON(); + + } + + if ( this.isBatchedMesh ) { + + object.type = 'BatchedMesh'; + object.perObjectFrustumCulled = this.perObjectFrustumCulled; + object.sortObjects = this.sortObjects; + + object.drawRanges = this._drawRanges; + object.reservedRanges = this._reservedRanges; + + object.visibility = this._visibility; + object.active = this._active; + object.bounds = this._bounds.map( bound => ( { + boxInitialized: bound.boxInitialized, + boxMin: bound.box.min.toArray(), + boxMax: bound.box.max.toArray(), + + sphereInitialized: bound.sphereInitialized, + sphereRadius: bound.sphere.radius, + sphereCenter: bound.sphere.center.toArray() + } ) ); + + object.maxInstanceCount = this._maxInstanceCount; + object.maxVertexCount = this._maxVertexCount; + object.maxIndexCount = this._maxIndexCount; + + object.geometryInitialized = this._geometryInitialized; + object.geometryCount = this._geometryCount; + + object.matricesTexture = this._matricesTexture.toJSON( meta ); + + if ( this._colorsTexture !== null ) object.colorsTexture = this._colorsTexture.toJSON( meta ); + + if ( this.boundingSphere !== null ) { + + object.boundingSphere = { + center: object.boundingSphere.center.toArray(), + radius: object.boundingSphere.radius + }; + + } + + if ( this.boundingBox !== null ) { + + object.boundingBox = { + min: object.boundingBox.min.toArray(), + max: object.boundingBox.max.toArray() + }; + + } + + } + + // + + function serialize( library, element ) { + + if ( library[ element.uuid ] === undefined ) { + + library[ element.uuid ] = element.toJSON( meta ); + + } + + return element.uuid; + + } + + if ( this.isScene ) { + + if ( this.background ) { + + if ( this.background.isColor ) { + + object.background = this.background.toJSON(); + + } else if ( this.background.isTexture ) { + + object.background = this.background.toJSON( meta ).uuid; + + } + + } + + if ( this.environment && this.environment.isTexture && this.environment.isRenderTargetTexture !== true ) { + + object.environment = this.environment.toJSON( meta ).uuid; + + } + + } else if ( this.isMesh || this.isLine || this.isPoints ) { + + object.geometry = serialize( meta.geometries, this.geometry ); + + const parameters = this.geometry.parameters; + + if ( parameters !== undefined && parameters.shapes !== undefined ) { + + const shapes = parameters.shapes; + + if ( Array.isArray( shapes ) ) { + + for ( let i = 0, l = shapes.length; i < l; i ++ ) { + + const shape = shapes[ i ]; + + serialize( meta.shapes, shape ); + + } + + } else { + + serialize( meta.shapes, shapes ); + + } + + } + + } + + if ( this.isSkinnedMesh ) { + + object.bindMode = this.bindMode; + object.bindMatrix = this.bindMatrix.toArray(); + + if ( this.skeleton !== undefined ) { + + serialize( meta.skeletons, this.skeleton ); + + object.skeleton = this.skeleton.uuid; + + } + + } + + if ( this.material !== undefined ) { + + if ( Array.isArray( this.material ) ) { + + const uuids = []; + + for ( let i = 0, l = this.material.length; i < l; i ++ ) { + + uuids.push( serialize( meta.materials, this.material[ i ] ) ); + + } + + object.material = uuids; + + } else { + + object.material = serialize( meta.materials, this.material ); + + } + + } + + // + + if ( this.children.length > 0 ) { + + object.children = []; + + for ( let i = 0; i < this.children.length; i ++ ) { + + object.children.push( this.children[ i ].toJSON( meta ).object ); + + } + + } + + // + + if ( this.animations.length > 0 ) { + + object.animations = []; + + for ( let i = 0; i < this.animations.length; i ++ ) { + + const animation = this.animations[ i ]; + + object.animations.push( serialize( meta.animations, animation ) ); + + } + + } + + if ( isRootObject ) { + + const geometries = extractFromCache( meta.geometries ); + const materials = extractFromCache( meta.materials ); + const textures = extractFromCache( meta.textures ); + const images = extractFromCache( meta.images ); + const shapes = extractFromCache( meta.shapes ); + const skeletons = extractFromCache( meta.skeletons ); + const animations = extractFromCache( meta.animations ); + const nodes = extractFromCache( meta.nodes ); + + if ( geometries.length > 0 ) output.geometries = geometries; + if ( materials.length > 0 ) output.materials = materials; + if ( textures.length > 0 ) output.textures = textures; + if ( images.length > 0 ) output.images = images; + if ( shapes.length > 0 ) output.shapes = shapes; + if ( skeletons.length > 0 ) output.skeletons = skeletons; + if ( animations.length > 0 ) output.animations = animations; + if ( nodes.length > 0 ) output.nodes = nodes; + + } + + output.object = object; + + return output; + + // extract data from the cache hash + // remove metadata on each item + // and return as array + function extractFromCache( cache ) { + + const values = []; + for ( const key in cache ) { + + const data = cache[ key ]; + delete data.metadata; + values.push( data ); + + } + + return values; + + } + + } + + clone( recursive ) { + + return new this.constructor().copy( this, recursive ); + + } + + copy( source, recursive = true ) { + + this.name = source.name; + + this.up.copy( source.up ); + + this.position.copy( source.position ); + this.rotation.order = source.rotation.order; + this.quaternion.copy( source.quaternion ); + this.scale.copy( source.scale ); + + this.matrix.copy( source.matrix ); + this.matrixWorld.copy( source.matrixWorld ); + + this.matrixAutoUpdate = source.matrixAutoUpdate; + + this.matrixWorldAutoUpdate = source.matrixWorldAutoUpdate; + this.matrixWorldNeedsUpdate = source.matrixWorldNeedsUpdate; + + this.layers.mask = source.layers.mask; + this.visible = source.visible; + + this.castShadow = source.castShadow; + this.receiveShadow = source.receiveShadow; + + this.frustumCulled = source.frustumCulled; + this.renderOrder = source.renderOrder; + + this.animations = source.animations.slice(); + + this.userData = JSON.parse( JSON.stringify( source.userData ) ); + + if ( recursive === true ) { + + for ( let i = 0; i < source.children.length; i ++ ) { + + const child = source.children[ i ]; + this.add( child.clone() ); + + } + + } + + return this; + + } + +} + +Object3D.DEFAULT_UP = /*@__PURE__*/ new Vector3( 0, 1, 0 ); +Object3D.DEFAULT_MATRIX_AUTO_UPDATE = true; +Object3D.DEFAULT_MATRIX_WORLD_AUTO_UPDATE = true; + +const _v0$1 = /*@__PURE__*/ new Vector3(); +const _v1$3 = /*@__PURE__*/ new Vector3(); +const _v2$2 = /*@__PURE__*/ new Vector3(); +const _v3$2 = /*@__PURE__*/ new Vector3(); + +const _vab = /*@__PURE__*/ new Vector3(); +const _vac = /*@__PURE__*/ new Vector3(); +const _vbc = /*@__PURE__*/ new Vector3(); +const _vap = /*@__PURE__*/ new Vector3(); +const _vbp = /*@__PURE__*/ new Vector3(); +const _vcp = /*@__PURE__*/ new Vector3(); + +const _v40 = /*@__PURE__*/ new Vector4(); +const _v41 = /*@__PURE__*/ new Vector4(); +const _v42 = /*@__PURE__*/ new Vector4(); + +class Triangle { + + constructor( a = new Vector3(), b = new Vector3(), c = new Vector3() ) { + + this.a = a; + this.b = b; + this.c = c; + + } + + static getNormal( a, b, c, target ) { + + target.subVectors( c, b ); + _v0$1.subVectors( a, b ); + target.cross( _v0$1 ); + + const targetLengthSq = target.lengthSq(); + if ( targetLengthSq > 0 ) { + + return target.multiplyScalar( 1 / Math.sqrt( targetLengthSq ) ); + + } + + return target.set( 0, 0, 0 ); + + } + + // static/instance method to calculate barycentric coordinates + // based on: http://www.blackpawn.com/texts/pointinpoly/default.html + static getBarycoord( point, a, b, c, target ) { + + _v0$1.subVectors( c, a ); + _v1$3.subVectors( b, a ); + _v2$2.subVectors( point, a ); + + const dot00 = _v0$1.dot( _v0$1 ); + const dot01 = _v0$1.dot( _v1$3 ); + const dot02 = _v0$1.dot( _v2$2 ); + const dot11 = _v1$3.dot( _v1$3 ); + const dot12 = _v1$3.dot( _v2$2 ); + + const denom = ( dot00 * dot11 - dot01 * dot01 ); + + // collinear or singular triangle + if ( denom === 0 ) { + + target.set( 0, 0, 0 ); + return null; + + } + + const invDenom = 1 / denom; + const u = ( dot11 * dot02 - dot01 * dot12 ) * invDenom; + const v = ( dot00 * dot12 - dot01 * dot02 ) * invDenom; + + // barycentric coordinates must always sum to 1 + return target.set( 1 - u - v, v, u ); + + } + + static containsPoint( point, a, b, c ) { + + // if the triangle is degenerate then we can't contain a point + if ( this.getBarycoord( point, a, b, c, _v3$2 ) === null ) { + + return false; + + } + + return ( _v3$2.x >= 0 ) && ( _v3$2.y >= 0 ) && ( ( _v3$2.x + _v3$2.y ) <= 1 ); + + } + + static getInterpolation( point, p1, p2, p3, v1, v2, v3, target ) { + + if ( this.getBarycoord( point, p1, p2, p3, _v3$2 ) === null ) { + + target.x = 0; + target.y = 0; + if ( 'z' in target ) target.z = 0; + if ( 'w' in target ) target.w = 0; + return null; + + } + + target.setScalar( 0 ); + target.addScaledVector( v1, _v3$2.x ); + target.addScaledVector( v2, _v3$2.y ); + target.addScaledVector( v3, _v3$2.z ); + + return target; + + } + + static getInterpolatedAttribute( attr, i1, i2, i3, barycoord, target ) { + + _v40.setScalar( 0 ); + _v41.setScalar( 0 ); + _v42.setScalar( 0 ); + + _v40.fromBufferAttribute( attr, i1 ); + _v41.fromBufferAttribute( attr, i2 ); + _v42.fromBufferAttribute( attr, i3 ); + + target.setScalar( 0 ); + target.addScaledVector( _v40, barycoord.x ); + target.addScaledVector( _v41, barycoord.y ); + target.addScaledVector( _v42, barycoord.z ); + + return target; + + } + + static isFrontFacing( a, b, c, direction ) { + + _v0$1.subVectors( c, b ); + _v1$3.subVectors( a, b ); + + // strictly front facing + return ( _v0$1.cross( _v1$3 ).dot( direction ) < 0 ) ? true : false; + + } + + set( a, b, c ) { + + this.a.copy( a ); + this.b.copy( b ); + this.c.copy( c ); + + return this; + + } + + setFromPointsAndIndices( points, i0, i1, i2 ) { + + this.a.copy( points[ i0 ] ); + this.b.copy( points[ i1 ] ); + this.c.copy( points[ i2 ] ); + + return this; + + } + + setFromAttributeAndIndices( attribute, i0, i1, i2 ) { + + this.a.fromBufferAttribute( attribute, i0 ); + this.b.fromBufferAttribute( attribute, i1 ); + this.c.fromBufferAttribute( attribute, i2 ); + + return this; + + } + + clone() { + + return new this.constructor().copy( this ); + + } + + copy( triangle ) { + + this.a.copy( triangle.a ); + this.b.copy( triangle.b ); + this.c.copy( triangle.c ); + + return this; + + } + + getArea() { + + _v0$1.subVectors( this.c, this.b ); + _v1$3.subVectors( this.a, this.b ); + + return _v0$1.cross( _v1$3 ).length() * 0.5; + + } + + getMidpoint( target ) { + + return target.addVectors( this.a, this.b ).add( this.c ).multiplyScalar( 1 / 3 ); + + } + + getNormal( target ) { + + return Triangle.getNormal( this.a, this.b, this.c, target ); + + } + + getPlane( target ) { + + return target.setFromCoplanarPoints( this.a, this.b, this.c ); + + } + + getBarycoord( point, target ) { + + return Triangle.getBarycoord( point, this.a, this.b, this.c, target ); + + } + + getInterpolation( point, v1, v2, v3, target ) { + + return Triangle.getInterpolation( point, this.a, this.b, this.c, v1, v2, v3, target ); + + } + + containsPoint( point ) { + + return Triangle.containsPoint( point, this.a, this.b, this.c ); + + } + + isFrontFacing( direction ) { + + return Triangle.isFrontFacing( this.a, this.b, this.c, direction ); + + } + + intersectsBox( box ) { + + return box.intersectsTriangle( this ); + + } + + closestPointToPoint( p, target ) { + + const a = this.a, b = this.b, c = this.c; + let v, w; + + // algorithm thanks to Real-Time Collision Detection by Christer Ericson, + // published by Morgan Kaufmann Publishers, (c) 2005 Elsevier Inc., + // under the accompanying license; see chapter 5.1.5 for detailed explanation. + // basically, we're distinguishing which of the voronoi regions of the triangle + // the point lies in with the minimum amount of redundant computation. + + _vab.subVectors( b, a ); + _vac.subVectors( c, a ); + _vap.subVectors( p, a ); + const d1 = _vab.dot( _vap ); + const d2 = _vac.dot( _vap ); + if ( d1 <= 0 && d2 <= 0 ) { + + // vertex region of A; barycentric coords (1, 0, 0) + return target.copy( a ); + + } + + _vbp.subVectors( p, b ); + const d3 = _vab.dot( _vbp ); + const d4 = _vac.dot( _vbp ); + if ( d3 >= 0 && d4 <= d3 ) { + + // vertex region of B; barycentric coords (0, 1, 0) + return target.copy( b ); + + } + + const vc = d1 * d4 - d3 * d2; + if ( vc <= 0 && d1 >= 0 && d3 <= 0 ) { + + v = d1 / ( d1 - d3 ); + // edge region of AB; barycentric coords (1-v, v, 0) + return target.copy( a ).addScaledVector( _vab, v ); + + } + + _vcp.subVectors( p, c ); + const d5 = _vab.dot( _vcp ); + const d6 = _vac.dot( _vcp ); + if ( d6 >= 0 && d5 <= d6 ) { + + // vertex region of C; barycentric coords (0, 0, 1) + return target.copy( c ); + + } + + const vb = d5 * d2 - d1 * d6; + if ( vb <= 0 && d2 >= 0 && d6 <= 0 ) { + + w = d2 / ( d2 - d6 ); + // edge region of AC; barycentric coords (1-w, 0, w) + return target.copy( a ).addScaledVector( _vac, w ); + + } + + const va = d3 * d6 - d5 * d4; + if ( va <= 0 && ( d4 - d3 ) >= 0 && ( d5 - d6 ) >= 0 ) { + + _vbc.subVectors( c, b ); + w = ( d4 - d3 ) / ( ( d4 - d3 ) + ( d5 - d6 ) ); + // edge region of BC; barycentric coords (0, 1-w, w) + return target.copy( b ).addScaledVector( _vbc, w ); // edge region of BC + + } + + // face region + const denom = 1 / ( va + vb + vc ); + // u = va * denom + v = vb * denom; + w = vc * denom; + + return target.copy( a ).addScaledVector( _vab, v ).addScaledVector( _vac, w ); + + } + + equals( triangle ) { + + return triangle.a.equals( this.a ) && triangle.b.equals( this.b ) && triangle.c.equals( this.c ); + + } + +} + +const _colorKeywords = { 'aliceblue': 0xF0F8FF, 'antiquewhite': 0xFAEBD7, 'aqua': 0x00FFFF, 'aquamarine': 0x7FFFD4, 'azure': 0xF0FFFF, + 'beige': 0xF5F5DC, 'bisque': 0xFFE4C4, 'black': 0x000000, 'blanchedalmond': 0xFFEBCD, 'blue': 0x0000FF, 'blueviolet': 0x8A2BE2, + 'brown': 0xA52A2A, 'burlywood': 0xDEB887, 'cadetblue': 0x5F9EA0, 'chartreuse': 0x7FFF00, 'chocolate': 0xD2691E, 'coral': 0xFF7F50, + 'cornflowerblue': 0x6495ED, 'cornsilk': 0xFFF8DC, 'crimson': 0xDC143C, 'cyan': 0x00FFFF, 'darkblue': 0x00008B, 'darkcyan': 0x008B8B, + 'darkgoldenrod': 0xB8860B, 'darkgray': 0xA9A9A9, 'darkgreen': 0x006400, 'darkgrey': 0xA9A9A9, 'darkkhaki': 0xBDB76B, 'darkmagenta': 0x8B008B, + 'darkolivegreen': 0x556B2F, 'darkorange': 0xFF8C00, 'darkorchid': 0x9932CC, 'darkred': 0x8B0000, 'darksalmon': 0xE9967A, 'darkseagreen': 0x8FBC8F, + 'darkslateblue': 0x483D8B, 'darkslategray': 0x2F4F4F, 'darkslategrey': 0x2F4F4F, 'darkturquoise': 0x00CED1, 'darkviolet': 0x9400D3, + 'deeppink': 0xFF1493, 'deepskyblue': 0x00BFFF, 'dimgray': 0x696969, 'dimgrey': 0x696969, 'dodgerblue': 0x1E90FF, 'firebrick': 0xB22222, + 'floralwhite': 0xFFFAF0, 'forestgreen': 0x228B22, 'fuchsia': 0xFF00FF, 'gainsboro': 0xDCDCDC, 'ghostwhite': 0xF8F8FF, 'gold': 0xFFD700, + 'goldenrod': 0xDAA520, 'gray': 0x808080, 'green': 0x008000, 'greenyellow': 0xADFF2F, 'grey': 0x808080, 'honeydew': 0xF0FFF0, 'hotpink': 0xFF69B4, + 'indianred': 0xCD5C5C, 'indigo': 0x4B0082, 'ivory': 0xFFFFF0, 'khaki': 0xF0E68C, 'lavender': 0xE6E6FA, 'lavenderblush': 0xFFF0F5, 'lawngreen': 0x7CFC00, + 'lemonchiffon': 0xFFFACD, 'lightblue': 0xADD8E6, 'lightcoral': 0xF08080, 'lightcyan': 0xE0FFFF, 'lightgoldenrodyellow': 0xFAFAD2, 'lightgray': 0xD3D3D3, + 'lightgreen': 0x90EE90, 'lightgrey': 0xD3D3D3, 'lightpink': 0xFFB6C1, 'lightsalmon': 0xFFA07A, 'lightseagreen': 0x20B2AA, 'lightskyblue': 0x87CEFA, + 'lightslategray': 0x778899, 'lightslategrey': 0x778899, 'lightsteelblue': 0xB0C4DE, 'lightyellow': 0xFFFFE0, 'lime': 0x00FF00, 'limegreen': 0x32CD32, + 'linen': 0xFAF0E6, 'magenta': 0xFF00FF, 'maroon': 0x800000, 'mediumaquamarine': 0x66CDAA, 'mediumblue': 0x0000CD, 'mediumorchid': 0xBA55D3, + 'mediumpurple': 0x9370DB, 'mediumseagreen': 0x3CB371, 'mediumslateblue': 0x7B68EE, 'mediumspringgreen': 0x00FA9A, 'mediumturquoise': 0x48D1CC, + 'mediumvioletred': 0xC71585, 'midnightblue': 0x191970, 'mintcream': 0xF5FFFA, 'mistyrose': 0xFFE4E1, 'moccasin': 0xFFE4B5, 'navajowhite': 0xFFDEAD, + 'navy': 0x000080, 'oldlace': 0xFDF5E6, 'olive': 0x808000, 'olivedrab': 0x6B8E23, 'orange': 0xFFA500, 'orangered': 0xFF4500, 'orchid': 0xDA70D6, + 'palegoldenrod': 0xEEE8AA, 'palegreen': 0x98FB98, 'paleturquoise': 0xAFEEEE, 'palevioletred': 0xDB7093, 'papayawhip': 0xFFEFD5, 'peachpuff': 0xFFDAB9, + 'peru': 0xCD853F, 'pink': 0xFFC0CB, 'plum': 0xDDA0DD, 'powderblue': 0xB0E0E6, 'purple': 0x800080, 'rebeccapurple': 0x663399, 'red': 0xFF0000, 'rosybrown': 0xBC8F8F, + 'royalblue': 0x4169E1, 'saddlebrown': 0x8B4513, 'salmon': 0xFA8072, 'sandybrown': 0xF4A460, 'seagreen': 0x2E8B57, 'seashell': 0xFFF5EE, + 'sienna': 0xA0522D, 'silver': 0xC0C0C0, 'skyblue': 0x87CEEB, 'slateblue': 0x6A5ACD, 'slategray': 0x708090, 'slategrey': 0x708090, 'snow': 0xFFFAFA, + 'springgreen': 0x00FF7F, 'steelblue': 0x4682B4, 'tan': 0xD2B48C, 'teal': 0x008080, 'thistle': 0xD8BFD8, 'tomato': 0xFF6347, 'turquoise': 0x40E0D0, + 'violet': 0xEE82EE, 'wheat': 0xF5DEB3, 'white': 0xFFFFFF, 'whitesmoke': 0xF5F5F5, 'yellow': 0xFFFF00, 'yellowgreen': 0x9ACD32 }; + +const _hslA = { h: 0, s: 0, l: 0 }; +const _hslB = { h: 0, s: 0, l: 0 }; + +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 ) * 6 * ( 2 / 3 - t ); + return p; + +} + +class Color { + + constructor( r, g, b ) { + + this.isColor = true; + + this.r = 1; + this.g = 1; + this.b = 1; + + return this.set( r, g, b ); + + } + + set( r, g, b ) { + + if ( g === undefined && b === undefined ) { + + // r is THREE.Color, hex or string + + const value = r; + + if ( value && value.isColor ) { + + this.copy( value ); + + } else if ( typeof value === 'number' ) { + + this.setHex( value ); + + } else if ( typeof value === 'string' ) { + + this.setStyle( value ); + + } + + } else { + + this.setRGB( r, g, b ); + + } + + return this; + + } + + setScalar( scalar ) { + + this.r = scalar; + this.g = scalar; + this.b = scalar; + + return this; + + } + + setHex( hex, colorSpace = SRGBColorSpace ) { + + hex = Math.floor( hex ); + + this.r = ( hex >> 16 & 255 ) / 255; + this.g = ( hex >> 8 & 255 ) / 255; + this.b = ( hex & 255 ) / 255; + + ColorManagement.toWorkingColorSpace( this, colorSpace ); + + return this; + + } + + setRGB( r, g, b, colorSpace = ColorManagement.workingColorSpace ) { + + this.r = r; + this.g = g; + this.b = b; + + ColorManagement.toWorkingColorSpace( this, colorSpace ); + + return this; + + } + + setHSL( h, s, l, colorSpace = ColorManagement.workingColorSpace ) { + + // h,s,l ranges are in 0.0 - 1.0 + h = euclideanModulo( h, 1 ); + s = clamp$1( s, 0, 1 ); + l = clamp$1( l, 0, 1 ); + + if ( s === 0 ) { + + this.r = this.g = this.b = l; + + } else { + + const p = l <= 0.5 ? l * ( 1 + s ) : l + s - ( l * s ); + const q = ( 2 * l ) - p; + + this.r = hue2rgb( q, p, h + 1 / 3 ); + this.g = hue2rgb( q, p, h ); + this.b = hue2rgb( q, p, h - 1 / 3 ); + + } + + ColorManagement.toWorkingColorSpace( this, colorSpace ); + + return this; + + } + + setStyle( style, colorSpace = SRGBColorSpace ) { + + function handleAlpha( string ) { + + if ( string === undefined ) return; + + if ( parseFloat( string ) < 1 ) { + + console.warn( 'THREE.Color: Alpha component of ' + style + ' will be ignored.' ); + + } + + } + + + let m; + + if ( m = /^(\w+)\(([^\)]*)\)/.exec( style ) ) { + + // rgb / hsl + + let color; + const name = m[ 1 ]; + const components = m[ 2 ]; + + switch ( name ) { + + case 'rgb': + case 'rgba': + + if ( color = /^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { + + // rgb(255,0,0) rgba(255,0,0,0.5) + + handleAlpha( color[ 4 ] ); + + return this.setRGB( + Math.min( 255, parseInt( color[ 1 ], 10 ) ) / 255, + Math.min( 255, parseInt( color[ 2 ], 10 ) ) / 255, + Math.min( 255, parseInt( color[ 3 ], 10 ) ) / 255, + colorSpace + ); + + } + + if ( color = /^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { + + // rgb(100%,0%,0%) rgba(100%,0%,0%,0.5) + + handleAlpha( color[ 4 ] ); + + return this.setRGB( + Math.min( 100, parseInt( color[ 1 ], 10 ) ) / 100, + Math.min( 100, parseInt( color[ 2 ], 10 ) ) / 100, + Math.min( 100, parseInt( color[ 3 ], 10 ) ) / 100, + colorSpace + ); + + } + + break; + + case 'hsl': + case 'hsla': + + if ( color = /^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec( components ) ) { + + // hsl(120,50%,50%) hsla(120,50%,50%,0.5) + + handleAlpha( color[ 4 ] ); + + return this.setHSL( + parseFloat( color[ 1 ] ) / 360, + parseFloat( color[ 2 ] ) / 100, + parseFloat( color[ 3 ] ) / 100, + colorSpace + ); + + } + + break; + + default: + + console.warn( 'THREE.Color: Unknown color model ' + style ); + + } + + } else if ( m = /^\#([A-Fa-f\d]+)$/.exec( style ) ) { + + // hex color + + const hex = m[ 1 ]; + const size = hex.length; + + if ( size === 3 ) { + + // #ff0 + return this.setRGB( + parseInt( hex.charAt( 0 ), 16 ) / 15, + parseInt( hex.charAt( 1 ), 16 ) / 15, + parseInt( hex.charAt( 2 ), 16 ) / 15, + colorSpace + ); + + } else if ( size === 6 ) { + + // #ff0000 + return this.setHex( parseInt( hex, 16 ), colorSpace ); + + } else { + + console.warn( 'THREE.Color: Invalid hex color ' + style ); + + } + + } else if ( style && style.length > 0 ) { + + return this.setColorName( style, colorSpace ); + + } + + return this; + + } + + setColorName( style, colorSpace = SRGBColorSpace ) { + + // color keywords + const hex = _colorKeywords[ style.toLowerCase() ]; + + if ( hex !== undefined ) { + + // red + this.setHex( hex, colorSpace ); + + } else { + + // unknown color + console.warn( 'THREE.Color: Unknown color ' + style ); + + } + + return this; + + } + + clone() { + + return new this.constructor( this.r, this.g, this.b ); + + } + + copy( color ) { + + this.r = color.r; + this.g = color.g; + this.b = color.b; + + return this; + + } + + copySRGBToLinear( color ) { + + this.r = SRGBToLinear( color.r ); + this.g = SRGBToLinear( color.g ); + this.b = SRGBToLinear( color.b ); + + return this; + + } + + copyLinearToSRGB( color ) { + + this.r = LinearToSRGB( color.r ); + this.g = LinearToSRGB( color.g ); + this.b = LinearToSRGB( color.b ); + + return this; + + } + + convertSRGBToLinear() { + + this.copySRGBToLinear( this ); + + return this; + + } + + convertLinearToSRGB() { + + this.copyLinearToSRGB( this ); + + return this; + + } + + getHex( colorSpace = SRGBColorSpace ) { + + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); + + return Math.round( clamp$1( _color.r * 255, 0, 255 ) ) * 65536 + Math.round( clamp$1( _color.g * 255, 0, 255 ) ) * 256 + Math.round( clamp$1( _color.b * 255, 0, 255 ) ); + + } + + getHexString( colorSpace = SRGBColorSpace ) { + + return ( '000000' + this.getHex( colorSpace ).toString( 16 ) ).slice( - 6 ); + + } + + getHSL( target, colorSpace = ColorManagement.workingColorSpace ) { + + // h,s,l ranges are in 0.0 - 1.0 + + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); + + const r = _color.r, g = _color.g, b = _color.b; + + const max = Math.max( r, g, b ); + const min = Math.min( r, g, b ); + + let hue, saturation; + const lightness = ( min + max ) / 2.0; + + if ( min === max ) { + + hue = 0; + saturation = 0; + + } else { + + const delta = max - min; + + saturation = lightness <= 0.5 ? delta / ( max + min ) : delta / ( 2 - max - min ); + + switch ( max ) { + + case r: hue = ( g - b ) / delta + ( g < b ? 6 : 0 ); break; + case g: hue = ( b - r ) / delta + 2; break; + case b: hue = ( r - g ) / delta + 4; break; + + } + + hue /= 6; + + } + + target.h = hue; + target.s = saturation; + target.l = lightness; + + return target; + + } + + getRGB( target, colorSpace = ColorManagement.workingColorSpace ) { + + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); + + target.r = _color.r; + target.g = _color.g; + target.b = _color.b; + + return target; + + } + + getStyle( colorSpace = SRGBColorSpace ) { + + ColorManagement.fromWorkingColorSpace( _color.copy( this ), colorSpace ); + + const r = _color.r, g = _color.g, b = _color.b; + + if ( colorSpace !== SRGBColorSpace ) { + + // Requires CSS Color Module Level 4 (https://www.w3.org/TR/css-color-4/). + return `color(${ colorSpace } ${ r.toFixed( 3 ) } ${ g.toFixed( 3 ) } ${ b.toFixed( 3 ) })`; + + } + + return `rgb(${ Math.round( r * 255 ) },${ Math.round( g * 255 ) },${ Math.round( b * 255 ) })`; + + } + + offsetHSL( h, s, l ) { + + this.getHSL( _hslA ); + + return this.setHSL( _hslA.h + h, _hslA.s + s, _hslA.l + l ); + + } + + add( color ) { + + this.r += color.r; + this.g += color.g; + this.b += color.b; + + return this; + + } + + addColors( color1, color2 ) { + + this.r = color1.r + color2.r; + this.g = color1.g + color2.g; + this.b = color1.b + color2.b; + + return this; + + } + + addScalar( s ) { + + this.r += s; + this.g += s; + this.b += s; + + return this; + + } + + sub( color ) { + + this.r = Math.max( 0, this.r - color.r ); + this.g = Math.max( 0, this.g - color.g ); + this.b = Math.max( 0, this.b - color.b ); + + return this; + + } + + multiply( color ) { + + this.r *= color.r; + this.g *= color.g; + this.b *= color.b; + + return this; + + } + + multiplyScalar( s ) { + + this.r *= s; + this.g *= s; + this.b *= s; + + return this; + + } + + lerp( color, alpha ) { + + this.r += ( color.r - this.r ) * alpha; + this.g += ( color.g - this.g ) * alpha; + this.b += ( color.b - this.b ) * alpha; + + return this; + + } + + lerpColors( color1, color2, alpha ) { + + this.r = color1.r + ( color2.r - color1.r ) * alpha; + this.g = color1.g + ( color2.g - color1.g ) * alpha; + this.b = color1.b + ( color2.b - color1.b ) * alpha; + + return this; + + } + + lerpHSL( color, alpha ) { + + this.getHSL( _hslA ); + color.getHSL( _hslB ); + + const h = lerp( _hslA.h, _hslB.h, alpha ); + const s = lerp( _hslA.s, _hslB.s, alpha ); + const l = lerp( _hslA.l, _hslB.l, alpha ); + + this.setHSL( h, s, l ); + + return this; + + } + + setFromVector3( v ) { + + this.r = v.x; + this.g = v.y; + this.b = v.z; + + return this; + + } + + applyMatrix3( m ) { + + const r = this.r, g = this.g, b = this.b; + const e = m.elements; + + this.r = e[ 0 ] * r + e[ 3 ] * g + e[ 6 ] * b; + this.g = e[ 1 ] * r + e[ 4 ] * g + e[ 7 ] * b; + this.b = e[ 2 ] * r + e[ 5 ] * g + e[ 8 ] * b; + + return this; + + } + + equals( c ) { + + return ( c.r === this.r ) && ( c.g === this.g ) && ( c.b === this.b ); + + } + + fromArray( array, offset = 0 ) { + + this.r = array[ offset ]; + this.g = array[ offset + 1 ]; + this.b = array[ offset + 2 ]; + + return this; + + } + + toArray( array = [], offset = 0 ) { + + array[ offset ] = this.r; + array[ offset + 1 ] = this.g; + array[ offset + 2 ] = this.b; + + return array; + + } + + fromBufferAttribute( attribute, index ) { + + this.r = attribute.getX( index ); + this.g = attribute.getY( index ); + this.b = attribute.getZ( index ); + + return this; + + } + + toJSON() { + + return this.getHex(); + + } + + *[ Symbol.iterator ]() { + + yield this.r; + yield this.g; + yield this.b; + + } + +} + +const _color = /*@__PURE__*/ new Color(); + +Color.NAMES = _colorKeywords; + +let _materialId = 0; + +class Material extends EventDispatcher { + + constructor() { + + super(); + + this.isMaterial = true; + + Object.defineProperty( this, 'id', { value: _materialId ++ } ); + + this.uuid = generateUUID(); + + this.name = ''; + this.type = 'Material'; + + this.blending = NormalBlending; + this.side = FrontSide; + this.vertexColors = false; + + this.opacity = 1; + this.transparent = false; + this.alphaHash = false; + + this.blendSrc = SrcAlphaFactor; + this.blendDst = OneMinusSrcAlphaFactor; + this.blendEquation = AddEquation; + this.blendSrcAlpha = null; + this.blendDstAlpha = null; + this.blendEquationAlpha = null; + this.blendColor = new Color( 0, 0, 0 ); + this.blendAlpha = 0; + + this.depthFunc = LessEqualDepth; + this.depthTest = true; + this.depthWrite = true; + + this.stencilWriteMask = 0xff; + this.stencilFunc = AlwaysStencilFunc; + this.stencilRef = 0; + this.stencilFuncMask = 0xff; + this.stencilFail = KeepStencilOp; + this.stencilZFail = KeepStencilOp; + this.stencilZPass = KeepStencilOp; + this.stencilWrite = false; + + this.clippingPlanes = null; + this.clipIntersection = false; + this.clipShadows = false; + + this.shadowSide = null; + + this.colorWrite = true; + + this.precision = null; // override the renderer's default precision for this material + + this.polygonOffset = false; + this.polygonOffsetFactor = 0; + this.polygonOffsetUnits = 0; + + this.dithering = false; + + this.alphaToCoverage = false; + this.premultipliedAlpha = false; + this.forceSinglePass = false; + + this.visible = true; + + this.toneMapped = true; + + this.userData = {}; + + this.version = 0; + + this._alphaTest = 0; + + } + + get alphaTest() { + + return this._alphaTest; + + } + + set alphaTest( value ) { + + if ( this._alphaTest > 0 !== value > 0 ) { + + this.version ++; + + } + + this._alphaTest = value; + + } + + // onBeforeRender and onBeforeCompile only supported in WebGLRenderer + + onBeforeRender( /* renderer, scene, camera, geometry, object, group */ ) {} + + onBeforeCompile( /* shaderobject, renderer */ ) {} + + customProgramCacheKey() { + + return this.onBeforeCompile.toString(); + + } + + setValues( values ) { + + if ( values === undefined ) return; + + for ( const key in values ) { + + const newValue = values[ key ]; + + if ( newValue === undefined ) { + + console.warn( `THREE.Material: parameter '${ key }' has value of undefined.` ); + continue; + + } + + const currentValue = this[ key ]; + + if ( currentValue === undefined ) { + + console.warn( `THREE.Material: '${ key }' is not a property of THREE.${ this.type }.` ); + continue; + + } + + if ( currentValue && currentValue.isColor ) { + + currentValue.set( newValue ); + + } else if ( ( currentValue && currentValue.isVector3 ) && ( newValue && newValue.isVector3 ) ) { + + currentValue.copy( newValue ); + + } else { + + this[ key ] = newValue; + + } + + } + + } + + toJSON( meta ) { + + const isRootObject = ( meta === undefined || typeof meta === 'string' ); + + if ( isRootObject ) { + + meta = { + textures: {}, + images: {} + }; + + } + + const data = { + metadata: { + version: 4.6, + type: 'Material', + generator: 'Material.toJSON' + } + }; + + // standard Material serialization + data.uuid = this.uuid; + data.type = this.type; + + if ( this.name !== '' ) data.name = this.name; + + if ( this.color && this.color.isColor ) data.color = this.color.getHex(); + + if ( this.roughness !== undefined ) data.roughness = this.roughness; + if ( this.metalness !== undefined ) data.metalness = this.metalness; + + if ( this.sheen !== undefined ) data.sheen = this.sheen; + if ( this.sheenColor && this.sheenColor.isColor ) data.sheenColor = this.sheenColor.getHex(); + if ( this.sheenRoughness !== undefined ) data.sheenRoughness = this.sheenRoughness; + if ( this.emissive && this.emissive.isColor ) data.emissive = this.emissive.getHex(); + if ( this.emissiveIntensity !== undefined && this.emissiveIntensity !== 1 ) data.emissiveIntensity = this.emissiveIntensity; + + if ( this.specular && this.specular.isColor ) data.specular = this.specular.getHex(); + if ( this.specularIntensity !== undefined ) data.specularIntensity = this.specularIntensity; + if ( this.specularColor && this.specularColor.isColor ) data.specularColor = this.specularColor.getHex(); + if ( this.shininess !== undefined ) data.shininess = this.shininess; + if ( this.clearcoat !== undefined ) data.clearcoat = this.clearcoat; + if ( this.clearcoatRoughness !== undefined ) data.clearcoatRoughness = this.clearcoatRoughness; + + if ( this.clearcoatMap && this.clearcoatMap.isTexture ) { + + data.clearcoatMap = this.clearcoatMap.toJSON( meta ).uuid; + + } + + if ( this.clearcoatRoughnessMap && this.clearcoatRoughnessMap.isTexture ) { + + data.clearcoatRoughnessMap = this.clearcoatRoughnessMap.toJSON( meta ).uuid; + + } + + if ( this.clearcoatNormalMap && this.clearcoatNormalMap.isTexture ) { + + data.clearcoatNormalMap = this.clearcoatNormalMap.toJSON( meta ).uuid; + data.clearcoatNormalScale = this.clearcoatNormalScale.toArray(); + + } + + if ( this.dispersion !== undefined ) data.dispersion = this.dispersion; + + if ( this.iridescence !== undefined ) data.iridescence = this.iridescence; + if ( this.iridescenceIOR !== undefined ) data.iridescenceIOR = this.iridescenceIOR; + if ( this.iridescenceThicknessRange !== undefined ) data.iridescenceThicknessRange = this.iridescenceThicknessRange; + + if ( this.iridescenceMap && this.iridescenceMap.isTexture ) { + + data.iridescenceMap = this.iridescenceMap.toJSON( meta ).uuid; + + } + + if ( this.iridescenceThicknessMap && this.iridescenceThicknessMap.isTexture ) { + + data.iridescenceThicknessMap = this.iridescenceThicknessMap.toJSON( meta ).uuid; + + } + + if ( this.anisotropy !== undefined ) data.anisotropy = this.anisotropy; + if ( this.anisotropyRotation !== undefined ) data.anisotropyRotation = this.anisotropyRotation; + + if ( this.anisotropyMap && this.anisotropyMap.isTexture ) { + + data.anisotropyMap = this.anisotropyMap.toJSON( meta ).uuid; + + } + + if ( this.map && this.map.isTexture ) data.map = this.map.toJSON( meta ).uuid; + if ( this.matcap && this.matcap.isTexture ) data.matcap = this.matcap.toJSON( meta ).uuid; + if ( this.alphaMap && this.alphaMap.isTexture ) data.alphaMap = this.alphaMap.toJSON( meta ).uuid; + + if ( this.lightMap && this.lightMap.isTexture ) { + + data.lightMap = this.lightMap.toJSON( meta ).uuid; + data.lightMapIntensity = this.lightMapIntensity; + + } + + if ( this.aoMap && this.aoMap.isTexture ) { + + data.aoMap = this.aoMap.toJSON( meta ).uuid; + data.aoMapIntensity = this.aoMapIntensity; + + } + + if ( this.bumpMap && this.bumpMap.isTexture ) { + + data.bumpMap = this.bumpMap.toJSON( meta ).uuid; + data.bumpScale = this.bumpScale; + + } + + if ( this.normalMap && this.normalMap.isTexture ) { + + data.normalMap = this.normalMap.toJSON( meta ).uuid; + data.normalMapType = this.normalMapType; + data.normalScale = this.normalScale.toArray(); + + } + + if ( this.displacementMap && this.displacementMap.isTexture ) { + + data.displacementMap = this.displacementMap.toJSON( meta ).uuid; + data.displacementScale = this.displacementScale; + data.displacementBias = this.displacementBias; + + } + + if ( this.roughnessMap && this.roughnessMap.isTexture ) data.roughnessMap = this.roughnessMap.toJSON( meta ).uuid; + if ( this.metalnessMap && this.metalnessMap.isTexture ) data.metalnessMap = this.metalnessMap.toJSON( meta ).uuid; + + if ( this.emissiveMap && this.emissiveMap.isTexture ) data.emissiveMap = this.emissiveMap.toJSON( meta ).uuid; + if ( this.specularMap && this.specularMap.isTexture ) data.specularMap = this.specularMap.toJSON( meta ).uuid; + if ( this.specularIntensityMap && this.specularIntensityMap.isTexture ) data.specularIntensityMap = this.specularIntensityMap.toJSON( meta ).uuid; + if ( this.specularColorMap && this.specularColorMap.isTexture ) data.specularColorMap = this.specularColorMap.toJSON( meta ).uuid; + + if ( this.envMap && this.envMap.isTexture ) { + + data.envMap = this.envMap.toJSON( meta ).uuid; + + if ( this.combine !== undefined ) data.combine = this.combine; + + } + + if ( this.envMapRotation !== undefined ) data.envMapRotation = this.envMapRotation.toArray(); + if ( this.envMapIntensity !== undefined ) data.envMapIntensity = this.envMapIntensity; + if ( this.reflectivity !== undefined ) data.reflectivity = this.reflectivity; + if ( this.refractionRatio !== undefined ) data.refractionRatio = this.refractionRatio; + + if ( this.gradientMap && this.gradientMap.isTexture ) { + + data.gradientMap = this.gradientMap.toJSON( meta ).uuid; + + } + + if ( this.transmission !== undefined ) data.transmission = this.transmission; + if ( this.transmissionMap && this.transmissionMap.isTexture ) data.transmissionMap = this.transmissionMap.toJSON( meta ).uuid; + if ( this.thickness !== undefined ) data.thickness = this.thickness; + if ( this.thicknessMap && this.thicknessMap.isTexture ) data.thicknessMap = this.thicknessMap.toJSON( meta ).uuid; + if ( this.attenuationDistance !== undefined && this.attenuationDistance !== Infinity ) data.attenuationDistance = this.attenuationDistance; + if ( this.attenuationColor !== undefined ) data.attenuationColor = this.attenuationColor.getHex(); + + if ( this.size !== undefined ) data.size = this.size; + if ( this.shadowSide !== null ) data.shadowSide = this.shadowSide; + if ( this.sizeAttenuation !== undefined ) data.sizeAttenuation = this.sizeAttenuation; + + if ( this.blending !== NormalBlending ) data.blending = this.blending; + if ( this.side !== FrontSide ) data.side = this.side; + if ( this.vertexColors === true ) data.vertexColors = true; + + if ( this.opacity < 1 ) data.opacity = this.opacity; + if ( this.transparent === true ) data.transparent = true; + + if ( this.blendSrc !== SrcAlphaFactor ) data.blendSrc = this.blendSrc; + if ( this.blendDst !== OneMinusSrcAlphaFactor ) data.blendDst = this.blendDst; + if ( this.blendEquation !== AddEquation ) data.blendEquation = this.blendEquation; + if ( this.blendSrcAlpha !== null ) data.blendSrcAlpha = this.blendSrcAlpha; + if ( this.blendDstAlpha !== null ) data.blendDstAlpha = this.blendDstAlpha; + if ( this.blendEquationAlpha !== null ) data.blendEquationAlpha = this.blendEquationAlpha; + if ( this.blendColor && this.blendColor.isColor ) data.blendColor = this.blendColor.getHex(); + if ( this.blendAlpha !== 0 ) data.blendAlpha = this.blendAlpha; + + if ( this.depthFunc !== LessEqualDepth ) data.depthFunc = this.depthFunc; + if ( this.depthTest === false ) data.depthTest = this.depthTest; + if ( this.depthWrite === false ) data.depthWrite = this.depthWrite; + if ( this.colorWrite === false ) data.colorWrite = this.colorWrite; + + if ( this.stencilWriteMask !== 0xff ) data.stencilWriteMask = this.stencilWriteMask; + if ( this.stencilFunc !== AlwaysStencilFunc ) data.stencilFunc = this.stencilFunc; + if ( this.stencilRef !== 0 ) data.stencilRef = this.stencilRef; + if ( this.stencilFuncMask !== 0xff ) data.stencilFuncMask = this.stencilFuncMask; + if ( this.stencilFail !== KeepStencilOp ) data.stencilFail = this.stencilFail; + if ( this.stencilZFail !== KeepStencilOp ) data.stencilZFail = this.stencilZFail; + if ( this.stencilZPass !== KeepStencilOp ) data.stencilZPass = this.stencilZPass; + if ( this.stencilWrite === true ) data.stencilWrite = this.stencilWrite; + + // rotation (SpriteMaterial) + if ( this.rotation !== undefined && this.rotation !== 0 ) data.rotation = this.rotation; + + if ( this.polygonOffset === true ) data.polygonOffset = true; + if ( this.polygonOffsetFactor !== 0 ) data.polygonOffsetFactor = this.polygonOffsetFactor; + if ( this.polygonOffsetUnits !== 0 ) data.polygonOffsetUnits = this.polygonOffsetUnits; + + if ( this.linewidth !== undefined && this.linewidth !== 1 ) data.linewidth = this.linewidth; + if ( this.dashSize !== undefined ) data.dashSize = this.dashSize; + if ( this.gapSize !== undefined ) data.gapSize = this.gapSize; + if ( this.scale !== undefined ) data.scale = this.scale; + + if ( this.dithering === true ) data.dithering = true; + + if ( this.alphaTest > 0 ) data.alphaTest = this.alphaTest; + if ( this.alphaHash === true ) data.alphaHash = true; + if ( this.alphaToCoverage === true ) data.alphaToCoverage = true; + if ( this.premultipliedAlpha === true ) data.premultipliedAlpha = true; + if ( this.forceSinglePass === true ) data.forceSinglePass = true; + + if ( this.wireframe === true ) data.wireframe = true; + if ( this.wireframeLinewidth > 1 ) data.wireframeLinewidth = this.wireframeLinewidth; + if ( this.wireframeLinecap !== 'round' ) data.wireframeLinecap = this.wireframeLinecap; + if ( this.wireframeLinejoin !== 'round' ) data.wireframeLinejoin = this.wireframeLinejoin; + + if ( this.flatShading === true ) data.flatShading = true; + + if ( this.visible === false ) data.visible = false; + + if ( this.toneMapped === false ) data.toneMapped = false; + + if ( this.fog === false ) data.fog = false; + + if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; + + // TODO: Copied from Object3D.toJSON + + function extractFromCache( cache ) { + + const values = []; + + for ( const key in cache ) { + + const data = cache[ key ]; + delete data.metadata; + values.push( data ); + + } + + return values; + + } + + if ( isRootObject ) { + + const textures = extractFromCache( meta.textures ); + const images = extractFromCache( meta.images ); + + if ( textures.length > 0 ) data.textures = textures; + if ( images.length > 0 ) data.images = images; + + } + + return data; + + } + + clone() { + + return new this.constructor().copy( this ); + + } + + copy( source ) { + + this.name = source.name; + + this.blending = source.blending; + this.side = source.side; + this.vertexColors = source.vertexColors; + + this.opacity = source.opacity; + this.transparent = source.transparent; + + this.blendSrc = source.blendSrc; + this.blendDst = source.blendDst; + this.blendEquation = source.blendEquation; + this.blendSrcAlpha = source.blendSrcAlpha; + this.blendDstAlpha = source.blendDstAlpha; + this.blendEquationAlpha = source.blendEquationAlpha; + this.blendColor.copy( source.blendColor ); + this.blendAlpha = source.blendAlpha; + + this.depthFunc = source.depthFunc; + this.depthTest = source.depthTest; + this.depthWrite = source.depthWrite; + + this.stencilWriteMask = source.stencilWriteMask; + this.stencilFunc = source.stencilFunc; + this.stencilRef = source.stencilRef; + this.stencilFuncMask = source.stencilFuncMask; + this.stencilFail = source.stencilFail; + this.stencilZFail = source.stencilZFail; + this.stencilZPass = source.stencilZPass; + this.stencilWrite = source.stencilWrite; + + const srcPlanes = source.clippingPlanes; + let dstPlanes = null; + + if ( srcPlanes !== null ) { + + const n = srcPlanes.length; + dstPlanes = new Array( n ); + + for ( let i = 0; i !== n; ++ i ) { + + dstPlanes[ i ] = srcPlanes[ i ].clone(); + + } + + } + + this.clippingPlanes = dstPlanes; + this.clipIntersection = source.clipIntersection; + this.clipShadows = source.clipShadows; + + this.shadowSide = source.shadowSide; + + this.colorWrite = source.colorWrite; + + this.precision = source.precision; + + this.polygonOffset = source.polygonOffset; + this.polygonOffsetFactor = source.polygonOffsetFactor; + this.polygonOffsetUnits = source.polygonOffsetUnits; + + this.dithering = source.dithering; + + this.alphaTest = source.alphaTest; + this.alphaHash = source.alphaHash; + this.alphaToCoverage = source.alphaToCoverage; + this.premultipliedAlpha = source.premultipliedAlpha; + this.forceSinglePass = source.forceSinglePass; + + this.visible = source.visible; + + this.toneMapped = source.toneMapped; + + this.userData = JSON.parse( JSON.stringify( source.userData ) ); + + return this; + + } + + dispose() { + + this.dispatchEvent( { type: 'dispose' } ); + + } + + set needsUpdate( value ) { + + if ( value === true ) this.version ++; + + } + + onBuild( /* shaderobject, renderer */ ) { + + console.warn( 'Material: onBuild() has been removed.' ); // @deprecated, r166 + + } + +} + +class MeshBasicMaterial extends Material { + + constructor( parameters ) { + + super(); + + this.isMeshBasicMaterial = true; + + this.type = 'MeshBasicMaterial'; + + this.color = new Color( 0xffffff ); // emissive + + this.map = null; + + this.lightMap = null; + this.lightMapIntensity = 1.0; + + this.aoMap = null; + this.aoMapIntensity = 1.0; + + this.specularMap = null; + + this.alphaMap = null; + + this.envMap = null; + this.envMapRotation = new Euler(); + this.combine = MultiplyOperation; + this.reflectivity = 1; + this.refractionRatio = 0.98; + + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = 'round'; + this.wireframeLinejoin = 'round'; + + this.fog = true; + + this.setValues( parameters ); + + } + + copy( source ) { + + super.copy( source ); + + this.color.copy( source.color ); + + this.map = source.map; + + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; + + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; + + this.specularMap = source.specularMap; + + this.alphaMap = source.alphaMap; + + this.envMap = source.envMap; + this.envMapRotation.copy( source.envMapRotation ); + this.combine = source.combine; + this.reflectivity = source.reflectivity; + this.refractionRatio = source.refractionRatio; + + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; + + this.fog = source.fog; + + return this; + + } + +} + +// Fast Half Float Conversions, http://www.fox-toolkit.org/ftp/fasthalffloatconversion.pdf + +const _tables = /*@__PURE__*/ _generateTables(); + +function _generateTables() { + + // float32 to float16 helpers + + const buffer = new ArrayBuffer( 4 ); + const floatView = new Float32Array( buffer ); + const uint32View = new Uint32Array( buffer ); + + const baseTable = new Uint32Array( 512 ); + const shiftTable = new Uint32Array( 512 ); + + for ( let i = 0; i < 256; ++ i ) { + + const e = i - 127; + + // very small number (0, -0) + + if ( e < - 27 ) { + + baseTable[ i ] = 0x0000; + baseTable[ i | 0x100 ] = 0x8000; + shiftTable[ i ] = 24; + shiftTable[ i | 0x100 ] = 24; + + // small number (denorm) + + } else if ( e < - 14 ) { + + baseTable[ i ] = 0x0400 >> ( - e - 14 ); + baseTable[ i | 0x100 ] = ( 0x0400 >> ( - e - 14 ) ) | 0x8000; + shiftTable[ i ] = - e - 1; + shiftTable[ i | 0x100 ] = - e - 1; + + // normal number + + } else if ( e <= 15 ) { + + baseTable[ i ] = ( e + 15 ) << 10; + baseTable[ i | 0x100 ] = ( ( e + 15 ) << 10 ) | 0x8000; + shiftTable[ i ] = 13; + shiftTable[ i | 0x100 ] = 13; + + // large number (Infinity, -Infinity) + + } else if ( e < 128 ) { + + baseTable[ i ] = 0x7c00; + baseTable[ i | 0x100 ] = 0xfc00; + shiftTable[ i ] = 24; + shiftTable[ i | 0x100 ] = 24; + + // stay (NaN, Infinity, -Infinity) + + } else { + + baseTable[ i ] = 0x7c00; + baseTable[ i | 0x100 ] = 0xfc00; + shiftTable[ i ] = 13; + shiftTable[ i | 0x100 ] = 13; + + } + + } + + // float16 to float32 helpers + + const mantissaTable = new Uint32Array( 2048 ); + const exponentTable = new Uint32Array( 64 ); + const offsetTable = new Uint32Array( 64 ); + + for ( let i = 1; i < 1024; ++ i ) { + + let m = i << 13; // zero pad mantissa bits + let e = 0; // zero exponent + + // normalized + while ( ( m & 0x00800000 ) === 0 ) { + + m <<= 1; + e -= 0x00800000; // decrement exponent + + } + + m &= ~ 0x00800000; // clear leading 1 bit + e += 0x38800000; // adjust bias + + mantissaTable[ i ] = m | e; + + } + + for ( let i = 1024; i < 2048; ++ i ) { + + mantissaTable[ i ] = 0x38000000 + ( ( i - 1024 ) << 13 ); + + } + + for ( let i = 1; i < 31; ++ i ) { + + exponentTable[ i ] = i << 23; + + } + + exponentTable[ 31 ] = 0x47800000; + exponentTable[ 32 ] = 0x80000000; + + for ( let i = 33; i < 63; ++ i ) { + + exponentTable[ i ] = 0x80000000 + ( ( i - 32 ) << 23 ); + + } + + exponentTable[ 63 ] = 0xc7800000; + + for ( let i = 1; i < 64; ++ i ) { + + if ( i !== 32 ) { + + offsetTable[ i ] = 1024; + + } + + } + + return { + floatView: floatView, + uint32View: uint32View, + baseTable: baseTable, + shiftTable: shiftTable, + mantissaTable: mantissaTable, + exponentTable: exponentTable, + offsetTable: offsetTable + }; + +} + +// float32 to float16 + +function toHalfFloat( val ) { + + if ( Math.abs( val ) > 65504 ) console.warn( 'THREE.DataUtils.toHalfFloat(): Value out of range.' ); + + val = clamp$1( val, - 65504, 65504 ); + + _tables.floatView[ 0 ] = val; + const f = _tables.uint32View[ 0 ]; + const e = ( f >> 23 ) & 0x1ff; + return _tables.baseTable[ e ] + ( ( f & 0x007fffff ) >> _tables.shiftTable[ e ] ); + +} + +// float16 to float32 + +function fromHalfFloat( val ) { + + const m = val >> 10; + _tables.uint32View[ 0 ] = _tables.mantissaTable[ _tables.offsetTable[ m ] + ( val & 0x3ff ) ] + _tables.exponentTable[ m ]; + return _tables.floatView[ 0 ]; + +} + +const DataUtils = { + toHalfFloat: toHalfFloat, + fromHalfFloat: fromHalfFloat, +}; + +const _vector$9 = /*@__PURE__*/ new Vector3(); +const _vector2$1 = /*@__PURE__*/ new Vector2(); + +class BufferAttribute { + + constructor( array, itemSize, normalized = false ) { + + if ( Array.isArray( array ) ) { + + throw new TypeError( 'THREE.BufferAttribute: array should be a Typed Array.' ); + + } + + this.isBufferAttribute = true; + + this.name = ''; + + this.array = array; + this.itemSize = itemSize; + this.count = array !== undefined ? array.length / itemSize : 0; + this.normalized = normalized; + + this.usage = StaticDrawUsage; + this.updateRanges = []; + this.gpuType = FloatType; + + this.version = 0; + + } + + onUploadCallback() {} + + set needsUpdate( value ) { + + if ( value === true ) this.version ++; + + } + + setUsage( value ) { + + this.usage = value; + + return this; + + } + + addUpdateRange( start, count ) { + + this.updateRanges.push( { start, count } ); + + } + + clearUpdateRanges() { + + this.updateRanges.length = 0; + + } + + copy( source ) { + + this.name = source.name; + this.array = new source.array.constructor( source.array ); + this.itemSize = source.itemSize; + this.count = source.count; + this.normalized = source.normalized; + + this.usage = source.usage; + this.gpuType = source.gpuType; + + return this; + + } + + copyAt( index1, attribute, index2 ) { + + index1 *= this.itemSize; + index2 *= attribute.itemSize; + + for ( let i = 0, l = this.itemSize; i < l; i ++ ) { + + this.array[ index1 + i ] = attribute.array[ index2 + i ]; + + } + + return this; + + } + + copyArray( array ) { + + this.array.set( array ); + + return this; + + } + + applyMatrix3( m ) { + + if ( this.itemSize === 2 ) { + + for ( let i = 0, l = this.count; i < l; i ++ ) { + + _vector2$1.fromBufferAttribute( this, i ); + _vector2$1.applyMatrix3( m ); + + this.setXY( i, _vector2$1.x, _vector2$1.y ); + + } + + } else if ( this.itemSize === 3 ) { + + for ( let i = 0, l = this.count; i < l; i ++ ) { + + _vector$9.fromBufferAttribute( this, i ); + _vector$9.applyMatrix3( m ); + + this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); + + } + + } + + return this; + + } + + applyMatrix4( m ) { + + for ( let i = 0, l = this.count; i < l; i ++ ) { + + _vector$9.fromBufferAttribute( this, i ); + + _vector$9.applyMatrix4( m ); + + this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); + + } + + return this; + + } + + applyNormalMatrix( m ) { + + for ( let i = 0, l = this.count; i < l; i ++ ) { + + _vector$9.fromBufferAttribute( this, i ); + + _vector$9.applyNormalMatrix( m ); + + this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); + + } + + return this; + + } + + transformDirection( m ) { + + for ( let i = 0, l = this.count; i < l; i ++ ) { + + _vector$9.fromBufferAttribute( this, i ); + + _vector$9.transformDirection( m ); + + this.setXYZ( i, _vector$9.x, _vector$9.y, _vector$9.z ); + + } + + return this; + + } + + set( value, offset = 0 ) { + + // Matching BufferAttribute constructor, do not normalize the array. + this.array.set( value, offset ); + + return this; + + } + + getComponent( index, component ) { + + let value = this.array[ index * this.itemSize + component ]; + + if ( this.normalized ) value = denormalize( value, this.array ); + + return value; + + } + + setComponent( index, component, value ) { + + if ( this.normalized ) value = normalize$1( value, this.array ); + + this.array[ index * this.itemSize + component ] = value; + + return this; + + } + + getX( index ) { + + let x = this.array[ index * this.itemSize ]; + + if ( this.normalized ) x = denormalize( x, this.array ); + + return x; + + } + + setX( index, x ) { + + if ( this.normalized ) x = normalize$1( x, this.array ); + + this.array[ index * this.itemSize ] = x; + + return this; + + } + + getY( index ) { + + let y = this.array[ index * this.itemSize + 1 ]; + + if ( this.normalized ) y = denormalize( y, this.array ); + + return y; + + } + + setY( index, y ) { + + if ( this.normalized ) y = normalize$1( y, this.array ); + + this.array[ index * this.itemSize + 1 ] = y; + + return this; + + } + + getZ( index ) { + + let z = this.array[ index * this.itemSize + 2 ]; + + if ( this.normalized ) z = denormalize( z, this.array ); + + return z; + + } + + setZ( index, z ) { + + if ( this.normalized ) z = normalize$1( z, this.array ); + + this.array[ index * this.itemSize + 2 ] = z; + + return this; + + } + + getW( index ) { + + let w = this.array[ index * this.itemSize + 3 ]; + + if ( this.normalized ) w = denormalize( w, this.array ); + + return w; + + } + + setW( index, w ) { + + if ( this.normalized ) w = normalize$1( w, this.array ); + + this.array[ index * this.itemSize + 3 ] = w; + + return this; + + } + + setXY( index, x, y ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize$1( x, this.array ); + y = normalize$1( y, this.array ); + + } + + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; + + return this; + + } + + setXYZ( index, x, y, z ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize$1( x, this.array ); + y = normalize$1( y, this.array ); + z = normalize$1( z, this.array ); + + } + + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; + this.array[ index + 2 ] = z; + + return this; + + } + + setXYZW( index, x, y, z, w ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize$1( x, this.array ); + y = normalize$1( y, this.array ); + z = normalize$1( z, this.array ); + w = normalize$1( w, this.array ); + + } + + this.array[ index + 0 ] = x; + this.array[ index + 1 ] = y; + this.array[ index + 2 ] = z; + this.array[ index + 3 ] = w; + + return this; + + } + + onUpload( callback ) { + + this.onUploadCallback = callback; + + return this; + + } + + clone() { + + return new this.constructor( this.array, this.itemSize ).copy( this ); + + } + + toJSON() { + + const data = { + itemSize: this.itemSize, + type: this.array.constructor.name, + array: Array.from( this.array ), + normalized: this.normalized + }; + + if ( this.name !== '' ) data.name = this.name; + if ( this.usage !== StaticDrawUsage ) data.usage = this.usage; + + return data; + + } + +} + +// + +class Int8BufferAttribute extends BufferAttribute { + + constructor( array, itemSize, normalized ) { + + super( new Int8Array( array ), itemSize, normalized ); + + } + +} + +class Uint8BufferAttribute extends BufferAttribute { + + constructor( array, itemSize, normalized ) { + + super( new Uint8Array( array ), itemSize, normalized ); + + } + +} + +class Uint8ClampedBufferAttribute extends BufferAttribute { + + constructor( array, itemSize, normalized ) { + + super( new Uint8ClampedArray( array ), itemSize, normalized ); + + } + +} + +class Int16BufferAttribute extends BufferAttribute { + + constructor( array, itemSize, normalized ) { + + super( new Int16Array( array ), itemSize, normalized ); + + } + +} + +class Uint16BufferAttribute extends BufferAttribute { + + constructor( array, itemSize, normalized ) { + + super( new Uint16Array( array ), itemSize, normalized ); + + } + +} + +class Int32BufferAttribute extends BufferAttribute { + + constructor( array, itemSize, normalized ) { + + super( new Int32Array( array ), itemSize, normalized ); + + } + +} + +class Uint32BufferAttribute extends BufferAttribute { + + constructor( array, itemSize, normalized ) { + + super( new Uint32Array( array ), itemSize, normalized ); + + } + +} + +class Float16BufferAttribute extends BufferAttribute { + + constructor( array, itemSize, normalized ) { + + super( new Uint16Array( array ), itemSize, normalized ); + + this.isFloat16BufferAttribute = true; + + } + + getX( index ) { + + let x = fromHalfFloat( this.array[ index * this.itemSize ] ); + + if ( this.normalized ) x = denormalize( x, this.array ); + + return x; + + } + + setX( index, x ) { + + if ( this.normalized ) x = normalize$1( x, this.array ); + + this.array[ index * this.itemSize ] = toHalfFloat( x ); + + return this; + + } + + getY( index ) { + + let y = fromHalfFloat( this.array[ index * this.itemSize + 1 ] ); + + if ( this.normalized ) y = denormalize( y, this.array ); + + return y; + + } + + setY( index, y ) { + + if ( this.normalized ) y = normalize$1( y, this.array ); + + this.array[ index * this.itemSize + 1 ] = toHalfFloat( y ); + + return this; + + } + + getZ( index ) { + + let z = fromHalfFloat( this.array[ index * this.itemSize + 2 ] ); + + if ( this.normalized ) z = denormalize( z, this.array ); + + return z; + + } + + setZ( index, z ) { + + if ( this.normalized ) z = normalize$1( z, this.array ); + + this.array[ index * this.itemSize + 2 ] = toHalfFloat( z ); + + return this; + + } + + getW( index ) { + + let w = fromHalfFloat( this.array[ index * this.itemSize + 3 ] ); + + if ( this.normalized ) w = denormalize( w, this.array ); + + return w; + + } + + setW( index, w ) { + + if ( this.normalized ) w = normalize$1( w, this.array ); + + this.array[ index * this.itemSize + 3 ] = toHalfFloat( w ); + + return this; + + } + + setXY( index, x, y ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize$1( x, this.array ); + y = normalize$1( y, this.array ); + + } + + this.array[ index + 0 ] = toHalfFloat( x ); + this.array[ index + 1 ] = toHalfFloat( y ); + + return this; + + } + + setXYZ( index, x, y, z ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize$1( x, this.array ); + y = normalize$1( y, this.array ); + z = normalize$1( z, this.array ); + + } + + this.array[ index + 0 ] = toHalfFloat( x ); + this.array[ index + 1 ] = toHalfFloat( y ); + this.array[ index + 2 ] = toHalfFloat( z ); + + return this; + + } + + setXYZW( index, x, y, z, w ) { + + index *= this.itemSize; + + if ( this.normalized ) { + + x = normalize$1( x, this.array ); + y = normalize$1( y, this.array ); + z = normalize$1( z, this.array ); + w = normalize$1( w, this.array ); + + } + + this.array[ index + 0 ] = toHalfFloat( x ); + this.array[ index + 1 ] = toHalfFloat( y ); + this.array[ index + 2 ] = toHalfFloat( z ); + this.array[ index + 3 ] = toHalfFloat( w ); + + return this; + + } + +} + + +class Float32BufferAttribute extends BufferAttribute { + + constructor( array, itemSize, normalized ) { + + super( new Float32Array( array ), itemSize, normalized ); + + } + +} + +let _id$9 = 0; + +const _m1 = /*@__PURE__*/ new Matrix4(); +const _obj = /*@__PURE__*/ new Object3D(); +const _offset = /*@__PURE__*/ new Vector3(); +const _box$2 = /*@__PURE__*/ new Box3(); +const _boxMorphTargets = /*@__PURE__*/ new Box3(); +const _vector$8 = /*@__PURE__*/ new Vector3(); + +class BufferGeometry extends EventDispatcher { + + constructor() { + + super(); + + this.isBufferGeometry = true; + + Object.defineProperty( this, 'id', { value: _id$9 ++ } ); + + this.uuid = generateUUID(); + + this.name = ''; + this.type = 'BufferGeometry'; + + this.index = null; + this.attributes = {}; + + this.morphAttributes = {}; + this.morphTargetsRelative = false; + + this.groups = []; + + this.boundingBox = null; + this.boundingSphere = null; + + this.drawRange = { start: 0, count: Infinity }; + + this.userData = {}; + + } + + getIndex() { + + return this.index; + + } + + setIndex( index ) { + + if ( Array.isArray( index ) ) { + + this.index = new ( arrayNeedsUint32$1( index ) ? Uint32BufferAttribute : Uint16BufferAttribute )( index, 1 ); + + } else { + + this.index = index; + + } + + return this; + + } + + getAttribute( name ) { + + return this.attributes[ name ]; + + } + + setAttribute( name, attribute ) { + + this.attributes[ name ] = attribute; + + return this; + + } + + deleteAttribute( name ) { + + delete this.attributes[ name ]; + + return this; + + } + + hasAttribute( name ) { + + return this.attributes[ name ] !== undefined; + + } + + addGroup( start, count, materialIndex = 0 ) { + + this.groups.push( { + + start: start, + count: count, + materialIndex: materialIndex + + } ); + + } + + clearGroups() { + + this.groups = []; + + } + + setDrawRange( start, count ) { + + this.drawRange.start = start; + this.drawRange.count = count; + + } + + applyMatrix4( matrix ) { + + const position = this.attributes.position; + + if ( position !== undefined ) { + + position.applyMatrix4( matrix ); + + position.needsUpdate = true; + + } + + const normal = this.attributes.normal; + + if ( normal !== undefined ) { + + const normalMatrix = new Matrix3().getNormalMatrix( matrix ); + + normal.applyNormalMatrix( normalMatrix ); + + normal.needsUpdate = true; + + } + + const tangent = this.attributes.tangent; + + if ( tangent !== undefined ) { + + tangent.transformDirection( matrix ); + + tangent.needsUpdate = true; + + } + + if ( this.boundingBox !== null ) { + + this.computeBoundingBox(); + + } + + if ( this.boundingSphere !== null ) { + + this.computeBoundingSphere(); + + } + + return this; + + } + + applyQuaternion( q ) { + + _m1.makeRotationFromQuaternion( q ); + + this.applyMatrix4( _m1 ); + + return this; + + } + + rotateX( angle ) { + + // rotate geometry around world x-axis + + _m1.makeRotationX( angle ); + + this.applyMatrix4( _m1 ); + + return this; + + } + + rotateY( angle ) { + + // rotate geometry around world y-axis + + _m1.makeRotationY( angle ); + + this.applyMatrix4( _m1 ); + + return this; + + } + + rotateZ( angle ) { + + // rotate geometry around world z-axis + + _m1.makeRotationZ( angle ); + + this.applyMatrix4( _m1 ); + + return this; + + } + + translate( x, y, z ) { + + // translate geometry + + _m1.makeTranslation( x, y, z ); + + this.applyMatrix4( _m1 ); + + return this; + + } + + scale( x, y, z ) { + + // scale geometry + + _m1.makeScale( x, y, z ); + + this.applyMatrix4( _m1 ); + + return this; + + } + + lookAt( vector ) { + + _obj.lookAt( vector ); + + _obj.updateMatrix(); + + this.applyMatrix4( _obj.matrix ); + + return this; + + } + + center() { + + this.computeBoundingBox(); + + this.boundingBox.getCenter( _offset ).negate(); + + this.translate( _offset.x, _offset.y, _offset.z ); + + return this; + + } + + setFromPoints( points ) { + + const position = []; + + for ( let i = 0, l = points.length; i < l; i ++ ) { + + const point = points[ i ]; + position.push( point.x, point.y, point.z || 0 ); + + } + + this.setAttribute( 'position', new Float32BufferAttribute( position, 3 ) ); + + return this; + + } + + computeBoundingBox() { + + if ( this.boundingBox === null ) { + + this.boundingBox = new Box3(); + + } + + const position = this.attributes.position; + const morphAttributesPosition = this.morphAttributes.position; + + if ( position && position.isGLBufferAttribute ) { + + console.error( 'THREE.BufferGeometry.computeBoundingBox(): GLBufferAttribute requires a manual bounding box.', this ); + + this.boundingBox.set( + new Vector3( - Infinity, - Infinity, - Infinity ), + new Vector3( + Infinity, + Infinity, + Infinity ) + ); + + return; + + } + + if ( position !== undefined ) { + + this.boundingBox.setFromBufferAttribute( position ); + + // process morph attributes if present + + if ( morphAttributesPosition ) { + + for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { + + const morphAttribute = morphAttributesPosition[ i ]; + _box$2.setFromBufferAttribute( morphAttribute ); + + if ( this.morphTargetsRelative ) { + + _vector$8.addVectors( this.boundingBox.min, _box$2.min ); + this.boundingBox.expandByPoint( _vector$8 ); + + _vector$8.addVectors( this.boundingBox.max, _box$2.max ); + this.boundingBox.expandByPoint( _vector$8 ); + + } else { + + this.boundingBox.expandByPoint( _box$2.min ); + this.boundingBox.expandByPoint( _box$2.max ); + + } + + } + + } + + } else { + + this.boundingBox.makeEmpty(); + + } + + if ( isNaN( this.boundingBox.min.x ) || isNaN( this.boundingBox.min.y ) || isNaN( this.boundingBox.min.z ) ) { + + console.error( 'THREE.BufferGeometry.computeBoundingBox(): Computed min/max have NaN values. The "position" attribute is likely to have NaN values.', this ); + + } + + } + + computeBoundingSphere() { + + if ( this.boundingSphere === null ) { + + this.boundingSphere = new Sphere(); + + } + + const position = this.attributes.position; + const morphAttributesPosition = this.morphAttributes.position; + + if ( position && position.isGLBufferAttribute ) { + + console.error( 'THREE.BufferGeometry.computeBoundingSphere(): GLBufferAttribute requires a manual bounding sphere.', this ); + + this.boundingSphere.set( new Vector3(), Infinity ); + + return; + + } + + if ( position ) { + + // first, find the center of the bounding sphere + + const center = this.boundingSphere.center; + + _box$2.setFromBufferAttribute( position ); + + // process morph attributes if present + + if ( morphAttributesPosition ) { + + for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { + + const morphAttribute = morphAttributesPosition[ i ]; + _boxMorphTargets.setFromBufferAttribute( morphAttribute ); + + if ( this.morphTargetsRelative ) { + + _vector$8.addVectors( _box$2.min, _boxMorphTargets.min ); + _box$2.expandByPoint( _vector$8 ); + + _vector$8.addVectors( _box$2.max, _boxMorphTargets.max ); + _box$2.expandByPoint( _vector$8 ); + + } else { + + _box$2.expandByPoint( _boxMorphTargets.min ); + _box$2.expandByPoint( _boxMorphTargets.max ); + + } + + } + + } + + _box$2.getCenter( center ); + + // second, try to find a boundingSphere with a radius smaller than the + // boundingSphere of the boundingBox: sqrt(3) smaller in the best case + + let maxRadiusSq = 0; + + for ( let i = 0, il = position.count; i < il; i ++ ) { + + _vector$8.fromBufferAttribute( position, i ); + + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); + + } + + // process morph attributes if present + + if ( morphAttributesPosition ) { + + for ( let i = 0, il = morphAttributesPosition.length; i < il; i ++ ) { + + const morphAttribute = morphAttributesPosition[ i ]; + const morphTargetsRelative = this.morphTargetsRelative; + + for ( let j = 0, jl = morphAttribute.count; j < jl; j ++ ) { + + _vector$8.fromBufferAttribute( morphAttribute, j ); + + if ( morphTargetsRelative ) { + + _offset.fromBufferAttribute( position, j ); + _vector$8.add( _offset ); + + } + + maxRadiusSq = Math.max( maxRadiusSq, center.distanceToSquared( _vector$8 ) ); + + } + + } + + } + + this.boundingSphere.radius = Math.sqrt( maxRadiusSq ); + + if ( isNaN( this.boundingSphere.radius ) ) { + + console.error( 'THREE.BufferGeometry.computeBoundingSphere(): Computed radius is NaN. The "position" attribute is likely to have NaN values.', this ); + + } + + } + + } + + computeTangents() { + + const index = this.index; + const attributes = this.attributes; + + // based on http://www.terathon.com/code/tangent.html + // (per vertex tangents) + + if ( index === null || + attributes.position === undefined || + attributes.normal === undefined || + attributes.uv === undefined ) { + + console.error( 'THREE.BufferGeometry: .computeTangents() failed. Missing required attributes (index, position, normal or uv)' ); + return; + + } + + const positionAttribute = attributes.position; + const normalAttribute = attributes.normal; + const uvAttribute = attributes.uv; + + if ( this.hasAttribute( 'tangent' ) === false ) { + + this.setAttribute( 'tangent', new BufferAttribute( new Float32Array( 4 * positionAttribute.count ), 4 ) ); + + } + + const tangentAttribute = this.getAttribute( 'tangent' ); + + const tan1 = [], tan2 = []; + + for ( let i = 0; i < positionAttribute.count; i ++ ) { + + tan1[ i ] = new Vector3(); + tan2[ i ] = new Vector3(); + + } + + const vA = new Vector3(), + vB = new Vector3(), + vC = new Vector3(), + + uvA = new Vector2(), + uvB = new Vector2(), + uvC = new Vector2(), + + sdir = new Vector3(), + tdir = new Vector3(); + + function handleTriangle( a, b, c ) { + + vA.fromBufferAttribute( positionAttribute, a ); + vB.fromBufferAttribute( positionAttribute, b ); + vC.fromBufferAttribute( positionAttribute, c ); + + uvA.fromBufferAttribute( uvAttribute, a ); + uvB.fromBufferAttribute( uvAttribute, b ); + uvC.fromBufferAttribute( uvAttribute, c ); + + vB.sub( vA ); + vC.sub( vA ); + + uvB.sub( uvA ); + uvC.sub( uvA ); + + const r = 1.0 / ( uvB.x * uvC.y - uvC.x * uvB.y ); + + // silently ignore degenerate uv triangles having coincident or colinear vertices + + if ( ! isFinite( r ) ) return; + + sdir.copy( vB ).multiplyScalar( uvC.y ).addScaledVector( vC, - uvB.y ).multiplyScalar( r ); + tdir.copy( vC ).multiplyScalar( uvB.x ).addScaledVector( vB, - uvC.x ).multiplyScalar( r ); + + tan1[ a ].add( sdir ); + tan1[ b ].add( sdir ); + tan1[ c ].add( sdir ); + + tan2[ a ].add( tdir ); + tan2[ b ].add( tdir ); + tan2[ c ].add( tdir ); + + } + + let groups = this.groups; + + if ( groups.length === 0 ) { + + groups = [ { + start: 0, + count: index.count + } ]; + + } + + for ( let i = 0, il = groups.length; i < il; ++ i ) { + + const group = groups[ i ]; + + const start = group.start; + const count = group.count; + + for ( let j = start, jl = start + count; j < jl; j += 3 ) { + + handleTriangle( + index.getX( j + 0 ), + index.getX( j + 1 ), + index.getX( j + 2 ) + ); + + } + + } + + const tmp = new Vector3(), tmp2 = new Vector3(); + const n = new Vector3(), n2 = new Vector3(); + + function handleVertex( v ) { + + n.fromBufferAttribute( normalAttribute, v ); + n2.copy( n ); + + const t = tan1[ v ]; + + // Gram-Schmidt orthogonalize + + tmp.copy( t ); + tmp.sub( n.multiplyScalar( n.dot( t ) ) ).normalize(); + + // Calculate handedness + + tmp2.crossVectors( n2, t ); + const test = tmp2.dot( tan2[ v ] ); + const w = ( test < 0.0 ) ? - 1.0 : 1.0; + + tangentAttribute.setXYZW( v, tmp.x, tmp.y, tmp.z, w ); + + } + + for ( let i = 0, il = groups.length; i < il; ++ i ) { + + const group = groups[ i ]; + + const start = group.start; + const count = group.count; + + for ( let j = start, jl = start + count; j < jl; j += 3 ) { + + handleVertex( index.getX( j + 0 ) ); + handleVertex( index.getX( j + 1 ) ); + handleVertex( index.getX( j + 2 ) ); + + } + + } + + } + + computeVertexNormals() { + + const index = this.index; + const positionAttribute = this.getAttribute( 'position' ); + + if ( positionAttribute !== undefined ) { + + let normalAttribute = this.getAttribute( 'normal' ); + + if ( normalAttribute === undefined ) { + + normalAttribute = new BufferAttribute( new Float32Array( positionAttribute.count * 3 ), 3 ); + this.setAttribute( 'normal', normalAttribute ); + + } else { + + // reset existing normals to zero + + for ( let i = 0, il = normalAttribute.count; i < il; i ++ ) { + + normalAttribute.setXYZ( i, 0, 0, 0 ); + + } + + } + + const pA = new Vector3(), pB = new Vector3(), pC = new Vector3(); + const nA = new Vector3(), nB = new Vector3(), nC = new Vector3(); + const cb = new Vector3(), ab = new Vector3(); + + // indexed elements + + if ( index ) { + + for ( let i = 0, il = index.count; i < il; i += 3 ) { + + const vA = index.getX( i + 0 ); + const vB = index.getX( i + 1 ); + const vC = index.getX( i + 2 ); + + pA.fromBufferAttribute( positionAttribute, vA ); + pB.fromBufferAttribute( positionAttribute, vB ); + pC.fromBufferAttribute( positionAttribute, vC ); + + cb.subVectors( pC, pB ); + ab.subVectors( pA, pB ); + cb.cross( ab ); + + nA.fromBufferAttribute( normalAttribute, vA ); + nB.fromBufferAttribute( normalAttribute, vB ); + nC.fromBufferAttribute( normalAttribute, vC ); + + nA.add( cb ); + nB.add( cb ); + nC.add( cb ); + + normalAttribute.setXYZ( vA, nA.x, nA.y, nA.z ); + normalAttribute.setXYZ( vB, nB.x, nB.y, nB.z ); + normalAttribute.setXYZ( vC, nC.x, nC.y, nC.z ); + + } + + } else { + + // non-indexed elements (unconnected triangle soup) + + for ( let i = 0, il = positionAttribute.count; i < il; i += 3 ) { + + pA.fromBufferAttribute( positionAttribute, i + 0 ); + pB.fromBufferAttribute( positionAttribute, i + 1 ); + pC.fromBufferAttribute( positionAttribute, i + 2 ); + + cb.subVectors( pC, pB ); + ab.subVectors( pA, pB ); + cb.cross( ab ); + + normalAttribute.setXYZ( i + 0, cb.x, cb.y, cb.z ); + normalAttribute.setXYZ( i + 1, cb.x, cb.y, cb.z ); + normalAttribute.setXYZ( i + 2, cb.x, cb.y, cb.z ); + + } + + } + + this.normalizeNormals(); + + normalAttribute.needsUpdate = true; + + } + + } + + normalizeNormals() { + + const normals = this.attributes.normal; + + for ( let i = 0, il = normals.count; i < il; i ++ ) { + + _vector$8.fromBufferAttribute( normals, i ); + + _vector$8.normalize(); + + normals.setXYZ( i, _vector$8.x, _vector$8.y, _vector$8.z ); + + } + + } + + toNonIndexed() { + + function convertBufferAttribute( attribute, indices ) { + + const array = attribute.array; + const itemSize = attribute.itemSize; + const normalized = attribute.normalized; + + const array2 = new array.constructor( indices.length * itemSize ); + + let index = 0, index2 = 0; + + for ( let i = 0, l = indices.length; i < l; i ++ ) { + + if ( attribute.isInterleavedBufferAttribute ) { + + index = indices[ i ] * attribute.data.stride + attribute.offset; + + } else { + + index = indices[ i ] * itemSize; + + } + + for ( let j = 0; j < itemSize; j ++ ) { + + array2[ index2 ++ ] = array[ index ++ ]; + + } + + } + + return new BufferAttribute( array2, itemSize, normalized ); + + } + + // + + if ( this.index === null ) { + + console.warn( 'THREE.BufferGeometry.toNonIndexed(): BufferGeometry is already non-indexed.' ); + return this; + + } + + const geometry2 = new BufferGeometry(); + + const indices = this.index.array; + const attributes = this.attributes; + + // attributes + + for ( const name in attributes ) { + + const attribute = attributes[ name ]; + + const newAttribute = convertBufferAttribute( attribute, indices ); + + geometry2.setAttribute( name, newAttribute ); + + } + + // morph attributes + + const morphAttributes = this.morphAttributes; + + for ( const name in morphAttributes ) { + + const morphArray = []; + const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes + + for ( let i = 0, il = morphAttribute.length; i < il; i ++ ) { + + const attribute = morphAttribute[ i ]; + + const newAttribute = convertBufferAttribute( attribute, indices ); + + morphArray.push( newAttribute ); + + } + + geometry2.morphAttributes[ name ] = morphArray; + + } + + geometry2.morphTargetsRelative = this.morphTargetsRelative; + + // groups + + const groups = this.groups; + + for ( let i = 0, l = groups.length; i < l; i ++ ) { + + const group = groups[ i ]; + geometry2.addGroup( group.start, group.count, group.materialIndex ); + + } + + return geometry2; + + } + + toJSON() { + + const data = { + metadata: { + version: 4.6, + type: 'BufferGeometry', + generator: 'BufferGeometry.toJSON' + } + }; + + // standard BufferGeometry serialization + + data.uuid = this.uuid; + data.type = this.type; + if ( this.name !== '' ) data.name = this.name; + if ( Object.keys( this.userData ).length > 0 ) data.userData = this.userData; + + if ( this.parameters !== undefined ) { + + const parameters = this.parameters; + + for ( const key in parameters ) { + + if ( parameters[ key ] !== undefined ) data[ key ] = parameters[ key ]; + + } + + return data; + + } + + // for simplicity the code assumes attributes are not shared across geometries, see #15811 + + data.data = { attributes: {} }; + + const index = this.index; + + if ( index !== null ) { + + data.data.index = { + type: index.array.constructor.name, + array: Array.prototype.slice.call( index.array ) + }; + + } + + const attributes = this.attributes; + + for ( const key in attributes ) { + + const attribute = attributes[ key ]; + + data.data.attributes[ key ] = attribute.toJSON( data.data ); + + } + + const morphAttributes = {}; + let hasMorphAttributes = false; + + for ( const key in this.morphAttributes ) { + + const attributeArray = this.morphAttributes[ key ]; + + const array = []; + + for ( let i = 0, il = attributeArray.length; i < il; i ++ ) { + + const attribute = attributeArray[ i ]; + + array.push( attribute.toJSON( data.data ) ); + + } + + if ( array.length > 0 ) { + + morphAttributes[ key ] = array; + + hasMorphAttributes = true; + + } + + } + + if ( hasMorphAttributes ) { + + data.data.morphAttributes = morphAttributes; + data.data.morphTargetsRelative = this.morphTargetsRelative; + + } + + const groups = this.groups; + + if ( groups.length > 0 ) { + + data.data.groups = JSON.parse( JSON.stringify( groups ) ); + + } + + const boundingSphere = this.boundingSphere; + + if ( boundingSphere !== null ) { + + data.data.boundingSphere = { + center: boundingSphere.center.toArray(), + radius: boundingSphere.radius + }; + + } + + return data; + + } + + clone() { + + return new this.constructor().copy( this ); + + } + + copy( source ) { + + // reset + + this.index = null; + this.attributes = {}; + this.morphAttributes = {}; + this.groups = []; + this.boundingBox = null; + this.boundingSphere = null; + + // used for storing cloned, shared data + + const data = {}; + + // name + + this.name = source.name; + + // index + + const index = source.index; + + if ( index !== null ) { + + this.setIndex( index.clone( data ) ); + + } + + // attributes + + const attributes = source.attributes; + + for ( const name in attributes ) { + + const attribute = attributes[ name ]; + this.setAttribute( name, attribute.clone( data ) ); + + } + + // morph attributes + + const morphAttributes = source.morphAttributes; + + for ( const name in morphAttributes ) { + + const array = []; + const morphAttribute = morphAttributes[ name ]; // morphAttribute: array of Float32BufferAttributes + + for ( let i = 0, l = morphAttribute.length; i < l; i ++ ) { + + array.push( morphAttribute[ i ].clone( data ) ); + + } + + this.morphAttributes[ name ] = array; + + } + + this.morphTargetsRelative = source.morphTargetsRelative; + + // groups + + const groups = source.groups; + + for ( let i = 0, l = groups.length; i < l; i ++ ) { + + const group = groups[ i ]; + this.addGroup( group.start, group.count, group.materialIndex ); + + } + + // bounding box + + const boundingBox = source.boundingBox; + + if ( boundingBox !== null ) { + + this.boundingBox = boundingBox.clone(); + + } + + // bounding sphere + + const boundingSphere = source.boundingSphere; + + if ( boundingSphere !== null ) { + + this.boundingSphere = boundingSphere.clone(); + + } + + // draw range + + this.drawRange.start = source.drawRange.start; + this.drawRange.count = source.drawRange.count; + + // user data + + this.userData = source.userData; + + return this; + + } + + dispose() { + + this.dispatchEvent( { type: 'dispose' } ); + + } + +} + +const _inverseMatrix$3 = /*@__PURE__*/ new Matrix4(); +const _ray$3 = /*@__PURE__*/ new Ray(); +const _sphere$6 = /*@__PURE__*/ new Sphere(); +const _sphereHitAt = /*@__PURE__*/ new Vector3(); + +const _vA$1 = /*@__PURE__*/ new Vector3(); +const _vB$1 = /*@__PURE__*/ new Vector3(); +const _vC$1 = /*@__PURE__*/ new Vector3(); + +const _tempA = /*@__PURE__*/ new Vector3(); +const _morphA = /*@__PURE__*/ new Vector3(); + +const _intersectionPoint = /*@__PURE__*/ new Vector3(); +const _intersectionPointWorld = /*@__PURE__*/ new Vector3(); + +class Mesh extends Object3D { + + constructor( geometry = new BufferGeometry(), material = new MeshBasicMaterial() ) { + + super(); + + this.isMesh = true; + + this.type = 'Mesh'; + + this.geometry = geometry; + this.material = material; + + this.updateMorphTargets(); + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + if ( source.morphTargetInfluences !== undefined ) { + + this.morphTargetInfluences = source.morphTargetInfluences.slice(); + + } + + if ( source.morphTargetDictionary !== undefined ) { + + this.morphTargetDictionary = Object.assign( {}, source.morphTargetDictionary ); + + } + + this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; + this.geometry = source.geometry; + + return this; + + } + + updateMorphTargets() { + + const geometry = this.geometry; + + const morphAttributes = geometry.morphAttributes; + const keys = Object.keys( morphAttributes ); + + if ( keys.length > 0 ) { + + const morphAttribute = morphAttributes[ keys[ 0 ] ]; + + if ( morphAttribute !== undefined ) { + + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; + + for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { + + const name = morphAttribute[ m ].name || String( m ); + + this.morphTargetInfluences.push( 0 ); + this.morphTargetDictionary[ name ] = m; + + } + + } + + } + + } + + getVertexPosition( index, target ) { + + const geometry = this.geometry; + const position = geometry.attributes.position; + const morphPosition = geometry.morphAttributes.position; + const morphTargetsRelative = geometry.morphTargetsRelative; + + target.fromBufferAttribute( position, index ); + + const morphInfluences = this.morphTargetInfluences; + + if ( morphPosition && morphInfluences ) { + + _morphA.set( 0, 0, 0 ); + + for ( let i = 0, il = morphPosition.length; i < il; i ++ ) { + + const influence = morphInfluences[ i ]; + const morphAttribute = morphPosition[ i ]; + + if ( influence === 0 ) continue; + + _tempA.fromBufferAttribute( morphAttribute, index ); + + if ( morphTargetsRelative ) { + + _morphA.addScaledVector( _tempA, influence ); + + } else { + + _morphA.addScaledVector( _tempA.sub( target ), influence ); + + } + + } + + target.add( _morphA ); + + } + + return target; + + } + + raycast( raycaster, intersects ) { + + const geometry = this.geometry; + const material = this.material; + const matrixWorld = this.matrixWorld; + + if ( material === undefined ) return; + + // test with bounding sphere in world space + + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + + _sphere$6.copy( geometry.boundingSphere ); + _sphere$6.applyMatrix4( matrixWorld ); + + // check distance from ray origin to bounding sphere + + _ray$3.copy( raycaster.ray ).recast( raycaster.near ); + + if ( _sphere$6.containsPoint( _ray$3.origin ) === false ) { + + if ( _ray$3.intersectSphere( _sphere$6, _sphereHitAt ) === null ) return; + + if ( _ray$3.origin.distanceToSquared( _sphereHitAt ) > ( raycaster.far - raycaster.near ) ** 2 ) return; + + } + + // convert ray to local space of mesh + + _inverseMatrix$3.copy( matrixWorld ).invert(); + _ray$3.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$3 ); + + // test with bounding box in local space + + if ( geometry.boundingBox !== null ) { + + if ( _ray$3.intersectsBox( geometry.boundingBox ) === false ) return; + + } + + // test for intersections with geometry + + this._computeIntersections( raycaster, intersects, _ray$3 ); + + } + + _computeIntersections( raycaster, intersects, rayLocalSpace ) { + + let intersection; + + const geometry = this.geometry; + const material = this.material; + + const index = geometry.index; + const position = geometry.attributes.position; + const uv = geometry.attributes.uv; + const uv1 = geometry.attributes.uv1; + const normal = geometry.attributes.normal; + const groups = geometry.groups; + const drawRange = geometry.drawRange; + + if ( index !== null ) { + + // indexed buffer geometry + + if ( Array.isArray( material ) ) { + + for ( let i = 0, il = groups.length; i < il; i ++ ) { + + const group = groups[ i ]; + const groupMaterial = material[ group.materialIndex ]; + + const start = Math.max( group.start, drawRange.start ); + const end = Math.min( index.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) ); + + for ( let j = start, jl = end; j < jl; j += 3 ) { + + const a = index.getX( j ); + const b = index.getX( j + 1 ); + const c = index.getX( j + 2 ); + + intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); + + if ( intersection ) { + + intersection.faceIndex = Math.floor( j / 3 ); // triangle number in indexed buffer semantics + intersection.face.materialIndex = group.materialIndex; + intersects.push( intersection ); + + } + + } + + } + + } else { + + const start = Math.max( 0, drawRange.start ); + const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); + + for ( let i = start, il = end; i < il; i += 3 ) { + + const a = index.getX( i ); + const b = index.getX( i + 1 ); + const c = index.getX( i + 2 ); + + intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); + + if ( intersection ) { + + intersection.faceIndex = Math.floor( i / 3 ); // triangle number in indexed buffer semantics + intersects.push( intersection ); + + } + + } + + } + + } else if ( position !== undefined ) { + + // non-indexed buffer geometry + + if ( Array.isArray( material ) ) { + + for ( let i = 0, il = groups.length; i < il; i ++ ) { + + const group = groups[ i ]; + const groupMaterial = material[ group.materialIndex ]; + + const start = Math.max( group.start, drawRange.start ); + const end = Math.min( position.count, Math.min( ( group.start + group.count ), ( drawRange.start + drawRange.count ) ) ); + + for ( let j = start, jl = end; j < jl; j += 3 ) { + + const a = j; + const b = j + 1; + const c = j + 2; + + intersection = checkGeometryIntersection( this, groupMaterial, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); + + if ( intersection ) { + + intersection.faceIndex = Math.floor( j / 3 ); // triangle number in non-indexed buffer semantics + intersection.face.materialIndex = group.materialIndex; + intersects.push( intersection ); + + } + + } + + } + + } else { + + const start = Math.max( 0, drawRange.start ); + const end = Math.min( position.count, ( drawRange.start + drawRange.count ) ); + + for ( let i = start, il = end; i < il; i += 3 ) { + + const a = i; + const b = i + 1; + const c = i + 2; + + intersection = checkGeometryIntersection( this, material, raycaster, rayLocalSpace, uv, uv1, normal, a, b, c ); + + if ( intersection ) { + + intersection.faceIndex = Math.floor( i / 3 ); // triangle number in non-indexed buffer semantics + intersects.push( intersection ); + + } + + } + + } + + } + + } + +} + +function checkIntersection$1( object, material, raycaster, ray, pA, pB, pC, point ) { + + let intersect; + + if ( material.side === BackSide ) { + + intersect = ray.intersectTriangle( pC, pB, pA, true, point ); + + } else { + + intersect = ray.intersectTriangle( pA, pB, pC, ( material.side === FrontSide ), point ); + + } + + if ( intersect === null ) return null; + + _intersectionPointWorld.copy( point ); + _intersectionPointWorld.applyMatrix4( object.matrixWorld ); + + const distance = raycaster.ray.origin.distanceTo( _intersectionPointWorld ); + + if ( distance < raycaster.near || distance > raycaster.far ) return null; + + return { + distance: distance, + point: _intersectionPointWorld.clone(), + object: object + }; + +} + +function checkGeometryIntersection( object, material, raycaster, ray, uv, uv1, normal, a, b, c ) { + + object.getVertexPosition( a, _vA$1 ); + object.getVertexPosition( b, _vB$1 ); + object.getVertexPosition( c, _vC$1 ); + + const intersection = checkIntersection$1( object, material, raycaster, ray, _vA$1, _vB$1, _vC$1, _intersectionPoint ); + + if ( intersection ) { + + const barycoord = new Vector3(); + Triangle.getBarycoord( _intersectionPoint, _vA$1, _vB$1, _vC$1, barycoord ); + + if ( uv ) { + + intersection.uv = Triangle.getInterpolatedAttribute( uv, a, b, c, barycoord, new Vector2() ); + + } + + if ( uv1 ) { + + intersection.uv1 = Triangle.getInterpolatedAttribute( uv1, a, b, c, barycoord, new Vector2() ); + + } + + if ( normal ) { + + intersection.normal = Triangle.getInterpolatedAttribute( normal, a, b, c, barycoord, new Vector3() ); + + if ( intersection.normal.dot( ray.direction ) > 0 ) { + + intersection.normal.multiplyScalar( - 1 ); + + } + + } + + const face = { + a: a, + b: b, + c: c, + normal: new Vector3(), + materialIndex: 0 + }; + + Triangle.getNormal( _vA$1, _vB$1, _vC$1, face.normal ); + + intersection.face = face; + intersection.barycoord = barycoord; + + } + + return intersection; + +} + +class BoxGeometry extends BufferGeometry { + + constructor( width = 1, height = 1, depth = 1, widthSegments = 1, heightSegments = 1, depthSegments = 1 ) { + + super(); + + this.type = 'BoxGeometry'; + + this.parameters = { + width: width, + height: height, + depth: depth, + widthSegments: widthSegments, + heightSegments: heightSegments, + depthSegments: depthSegments + }; + + const scope = this; + + // segments + + widthSegments = Math.floor( widthSegments ); + heightSegments = Math.floor( heightSegments ); + depthSegments = Math.floor( depthSegments ); + + // buffers + + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + + // helper variables + + let numberOfVertices = 0; + let groupStart = 0; + + // build each side of the box geometry + + buildPlane( 'z', 'y', 'x', - 1, - 1, depth, height, width, depthSegments, heightSegments, 0 ); // px + buildPlane( 'z', 'y', 'x', 1, - 1, depth, height, - width, depthSegments, heightSegments, 1 ); // nx + buildPlane( 'x', 'z', 'y', 1, 1, width, depth, height, widthSegments, depthSegments, 2 ); // py + buildPlane( 'x', 'z', 'y', 1, - 1, width, depth, - height, widthSegments, depthSegments, 3 ); // ny + buildPlane( 'x', 'y', 'z', 1, - 1, width, height, depth, widthSegments, heightSegments, 4 ); // pz + buildPlane( 'x', 'y', 'z', - 1, - 1, width, height, - depth, widthSegments, heightSegments, 5 ); // nz + + // build geometry + + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + + function buildPlane( u, v, w, udir, vdir, width, height, depth, gridX, gridY, materialIndex ) { + + const segmentWidth = width / gridX; + const segmentHeight = height / gridY; + + const widthHalf = width / 2; + const heightHalf = height / 2; + const depthHalf = depth / 2; + + const gridX1 = gridX + 1; + const gridY1 = gridY + 1; + + let vertexCounter = 0; + let groupCount = 0; + + const vector = new Vector3(); + + // generate vertices, normals and uvs + + for ( let iy = 0; iy < gridY1; iy ++ ) { + + const y = iy * segmentHeight - heightHalf; + + for ( let ix = 0; ix < gridX1; ix ++ ) { + + const x = ix * segmentWidth - widthHalf; + + // set values to correct vector component + + vector[ u ] = x * udir; + vector[ v ] = y * vdir; + vector[ w ] = depthHalf; + + // now apply vector to vertex buffer + + vertices.push( vector.x, vector.y, vector.z ); + + // set values to correct vector component + + vector[ u ] = 0; + vector[ v ] = 0; + vector[ w ] = depth > 0 ? 1 : - 1; + + // now apply vector to normal buffer + + normals.push( vector.x, vector.y, vector.z ); + + // uvs + + uvs.push( ix / gridX ); + uvs.push( 1 - ( iy / gridY ) ); + + // counters + + vertexCounter += 1; + + } + + } + + // indices + + // 1. you need three indices to draw a single face + // 2. a single segment consists of two faces + // 3. so we need to generate six (2*3) indices per segment + + for ( let iy = 0; iy < gridY; iy ++ ) { + + for ( let ix = 0; ix < gridX; ix ++ ) { + + const a = numberOfVertices + ix + gridX1 * iy; + const b = numberOfVertices + ix + gridX1 * ( iy + 1 ); + const c = numberOfVertices + ( ix + 1 ) + gridX1 * ( iy + 1 ); + const d = numberOfVertices + ( ix + 1 ) + gridX1 * iy; + + // faces + + indices.push( a, b, d ); + indices.push( b, c, d ); + + // increase counter + + groupCount += 6; + + } + + } + + // add a group to the geometry. this will ensure multi material support + + scope.addGroup( groupStart, groupCount, materialIndex ); + + // calculate new start value for groups + + groupStart += groupCount; + + // update total number of vertices + + numberOfVertices += vertexCounter; + + } + + } + + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + + static fromJSON( data ) { + + return new BoxGeometry( data.width, data.height, data.depth, data.widthSegments, data.heightSegments, data.depthSegments ); + + } + +} + +/** + * Uniform Utilities + */ + +function cloneUniforms( src ) { + + const dst = {}; + + for ( const u in src ) { + + dst[ u ] = {}; + + for ( const p in src[ u ] ) { + + const property = src[ u ][ p ]; + + if ( property && ( property.isColor || + property.isMatrix3 || property.isMatrix4 || + property.isVector2 || property.isVector3 || property.isVector4 || + property.isTexture || property.isQuaternion ) ) { + + if ( property.isRenderTargetTexture ) { + + console.warn( 'UniformsUtils: Textures of render targets cannot be cloned via cloneUniforms() or mergeUniforms().' ); + dst[ u ][ p ] = null; + + } else { + + dst[ u ][ p ] = property.clone(); + + } + + } else if ( Array.isArray( property ) ) { + + dst[ u ][ p ] = property.slice(); + + } else { + + dst[ u ][ p ] = property; + + } + + } + + } + + return dst; + +} + +function cloneUniformsGroups( src ) { + + const dst = []; + + for ( let u = 0; u < src.length; u ++ ) { + + dst.push( src[ u ].clone() ); + + } + + return dst; + +} + +var default_vertex = /* glsl */` +void main() { + gl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 ); +} +`; + +var default_fragment = /* glsl */` +void main() { + gl_FragColor = vec4( 1.0, 0.0, 0.0, 1.0 ); +} +`; + +class ShaderMaterial extends Material { + + constructor( parameters ) { + + super(); + + this.isShaderMaterial = true; + + this.type = 'ShaderMaterial'; + + this.defines = {}; + this.uniforms = {}; + this.uniformsGroups = []; + + this.vertexShader = default_vertex; + this.fragmentShader = default_fragment; + + this.linewidth = 1; + + this.wireframe = false; + this.wireframeLinewidth = 1; + + this.fog = false; // set to use scene fog + this.lights = false; // set to use scene lights + this.clipping = false; // set to use user-defined clipping planes + + this.forceSinglePass = true; + + this.extensions = { + clipCullDistance: false, // set to use vertex shader clipping + multiDraw: false // set to use vertex shader multi_draw / enable gl_DrawID + }; + + // When rendered geometry doesn't include these attributes but the material does, + // use these default values in WebGL. This avoids errors when buffer data is missing. + this.defaultAttributeValues = { + 'color': [ 1, 1, 1 ], + 'uv': [ 0, 0 ], + 'uv1': [ 0, 0 ] + }; + + this.index0AttributeName = undefined; + this.uniformsNeedUpdate = false; + + this.glslVersion = null; + + if ( parameters !== undefined ) { + + this.setValues( parameters ); + + } + + } + + copy( source ) { + + super.copy( source ); + + this.fragmentShader = source.fragmentShader; + this.vertexShader = source.vertexShader; + + this.uniforms = cloneUniforms( source.uniforms ); + this.uniformsGroups = cloneUniformsGroups( source.uniformsGroups ); + + this.defines = Object.assign( {}, source.defines ); + + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + + this.fog = source.fog; + this.lights = source.lights; + this.clipping = source.clipping; + + this.extensions = Object.assign( {}, source.extensions ); + + this.glslVersion = source.glslVersion; + + return this; + + } + + toJSON( meta ) { + + const data = super.toJSON( meta ); + + data.glslVersion = this.glslVersion; + data.uniforms = {}; + + for ( const name in this.uniforms ) { + + const uniform = this.uniforms[ name ]; + const value = uniform.value; + + if ( value && value.isTexture ) { + + data.uniforms[ name ] = { + type: 't', + value: value.toJSON( meta ).uuid + }; + + } else if ( value && value.isColor ) { + + data.uniforms[ name ] = { + type: 'c', + value: value.getHex() + }; + + } else if ( value && value.isVector2 ) { + + data.uniforms[ name ] = { + type: 'v2', + value: value.toArray() + }; + + } else if ( value && value.isVector3 ) { + + data.uniforms[ name ] = { + type: 'v3', + value: value.toArray() + }; + + } else if ( value && value.isVector4 ) { + + data.uniforms[ name ] = { + type: 'v4', + value: value.toArray() + }; + + } else if ( value && value.isMatrix3 ) { + + data.uniforms[ name ] = { + type: 'm3', + value: value.toArray() + }; + + } else if ( value && value.isMatrix4 ) { + + data.uniforms[ name ] = { + type: 'm4', + value: value.toArray() + }; + + } else { + + data.uniforms[ name ] = { + value: value + }; + + // note: the array variants v2v, v3v, v4v, m4v and tv are not supported so far + + } + + } + + if ( Object.keys( this.defines ).length > 0 ) data.defines = this.defines; + + data.vertexShader = this.vertexShader; + data.fragmentShader = this.fragmentShader; + + data.lights = this.lights; + data.clipping = this.clipping; + + const extensions = {}; + + for ( const key in this.extensions ) { + + if ( this.extensions[ key ] === true ) extensions[ key ] = true; + + } + + if ( Object.keys( extensions ).length > 0 ) data.extensions = extensions; + + return data; + + } + +} + +class Camera extends Object3D { + + constructor() { + + super(); + + this.isCamera = true; + + this.type = 'Camera'; + + this.matrixWorldInverse = new Matrix4(); + + this.projectionMatrix = new Matrix4(); + this.projectionMatrixInverse = new Matrix4(); + + this.coordinateSystem = WebGLCoordinateSystem; + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + this.matrixWorldInverse.copy( source.matrixWorldInverse ); + + this.projectionMatrix.copy( source.projectionMatrix ); + this.projectionMatrixInverse.copy( source.projectionMatrixInverse ); + + this.coordinateSystem = source.coordinateSystem; + + return this; + + } + + getWorldDirection( target ) { + + return super.getWorldDirection( target ).negate(); + + } + + updateMatrixWorld( force ) { + + super.updateMatrixWorld( force ); + + this.matrixWorldInverse.copy( this.matrixWorld ).invert(); + + } + + updateWorldMatrix( updateParents, updateChildren ) { + + super.updateWorldMatrix( updateParents, updateChildren ); + + this.matrixWorldInverse.copy( this.matrixWorld ).invert(); + + } + + clone() { + + return new this.constructor().copy( this ); + + } + +} + +const _v3$1 = /*@__PURE__*/ new Vector3(); +const _minTarget = /*@__PURE__*/ new Vector2(); +const _maxTarget = /*@__PURE__*/ new Vector2(); + + +class PerspectiveCamera extends Camera { + + constructor( fov = 50, aspect = 1, near = 0.1, far = 2000 ) { + + super(); + + this.isPerspectiveCamera = true; + + this.type = 'PerspectiveCamera'; + + this.fov = fov; + this.zoom = 1; + + this.near = near; + this.far = far; + this.focus = 10; + + this.aspect = aspect; + this.view = null; + + this.filmGauge = 35; // width of the film (default in millimeters) + this.filmOffset = 0; // horizontal film offset (same unit as gauge) + + this.updateProjectionMatrix(); + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + this.fov = source.fov; + this.zoom = source.zoom; + + this.near = source.near; + this.far = source.far; + this.focus = source.focus; + + this.aspect = source.aspect; + this.view = source.view === null ? null : Object.assign( {}, source.view ); + + this.filmGauge = source.filmGauge; + this.filmOffset = source.filmOffset; + + return this; + + } + + /** + * Sets the FOV by focal length in respect to the current .filmGauge. + * + * The default film gauge is 35, so that the focal length can be specified for + * a 35mm (full frame) camera. + * + * Values for focal length and film gauge must have the same unit. + */ + setFocalLength( focalLength ) { + + /** see {@link http://www.bobatkins.com/photography/technical/field_of_view.html} */ + const vExtentSlope = 0.5 * this.getFilmHeight() / focalLength; + + this.fov = RAD2DEG * 2 * Math.atan( vExtentSlope ); + this.updateProjectionMatrix(); + + } + + /** + * Calculates the focal length from the current .fov and .filmGauge. + */ + getFocalLength() { + + const vExtentSlope = Math.tan( DEG2RAD * 0.5 * this.fov ); + + return 0.5 * this.getFilmHeight() / vExtentSlope; + + } + + getEffectiveFOV() { + + return RAD2DEG * 2 * Math.atan( + Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom ); + + } + + getFilmWidth() { + + // film not completely covered in portrait format (aspect < 1) + return this.filmGauge * Math.min( this.aspect, 1 ); + + } + + getFilmHeight() { + + // film not completely covered in landscape format (aspect > 1) + return this.filmGauge / Math.max( this.aspect, 1 ); + + } + + /** + * Computes the 2D bounds of the camera's viewable rectangle at a given distance along the viewing direction. + * Sets minTarget and maxTarget to the coordinates of the lower-left and upper-right corners of the view rectangle. + */ + getViewBounds( distance, minTarget, maxTarget ) { + + _v3$1.set( - 1, - 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse ); + + minTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z ); + + _v3$1.set( 1, 1, 0.5 ).applyMatrix4( this.projectionMatrixInverse ); + + maxTarget.set( _v3$1.x, _v3$1.y ).multiplyScalar( - distance / _v3$1.z ); + + } + + /** + * Computes the width and height of the camera's viewable rectangle at a given distance along the viewing direction. + * Copies the result into the target Vector2, where x is width and y is height. + */ + getViewSize( distance, target ) { + + this.getViewBounds( distance, _minTarget, _maxTarget ); + + return target.subVectors( _maxTarget, _minTarget ); + + } + + /** + * Sets an offset in a larger frustum. This is useful for multi-window or + * multi-monitor/multi-machine setups. + * + * For example, if you have 3x2 monitors and each monitor is 1920x1080 and + * the monitors are in grid like this + * + * +---+---+---+ + * | A | B | C | + * +---+---+---+ + * | D | E | F | + * +---+---+---+ + * + * then for each monitor you would call it like this + * + * const w = 1920; + * const h = 1080; + * const fullWidth = w * 3; + * const fullHeight = h * 2; + * + * --A-- + * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 0, w, h ); + * --B-- + * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 0, w, h ); + * --C-- + * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 0, w, h ); + * --D-- + * camera.setViewOffset( fullWidth, fullHeight, w * 0, h * 1, w, h ); + * --E-- + * camera.setViewOffset( fullWidth, fullHeight, w * 1, h * 1, w, h ); + * --F-- + * camera.setViewOffset( fullWidth, fullHeight, w * 2, h * 1, w, h ); + * + * Note there is no reason monitors have to be the same size or in a grid. + */ + setViewOffset( fullWidth, fullHeight, x, y, width, height ) { + + this.aspect = fullWidth / fullHeight; + + if ( this.view === null ) { + + this.view = { + enabled: true, + fullWidth: 1, + fullHeight: 1, + offsetX: 0, + offsetY: 0, + width: 1, + height: 1 + }; + + } + + this.view.enabled = true; + this.view.fullWidth = fullWidth; + this.view.fullHeight = fullHeight; + this.view.offsetX = x; + this.view.offsetY = y; + this.view.width = width; + this.view.height = height; + + this.updateProjectionMatrix(); + + } + + clearViewOffset() { + + if ( this.view !== null ) { + + this.view.enabled = false; + + } + + this.updateProjectionMatrix(); + + } + + updateProjectionMatrix() { + + const near = this.near; + let top = near * Math.tan( DEG2RAD * 0.5 * this.fov ) / this.zoom; + let height = 2 * top; + let width = this.aspect * height; + let left = - 0.5 * width; + const view = this.view; + + if ( this.view !== null && this.view.enabled ) { + + const fullWidth = view.fullWidth, + fullHeight = view.fullHeight; + + left += view.offsetX * width / fullWidth; + top -= view.offsetY * height / fullHeight; + width *= view.width / fullWidth; + height *= view.height / fullHeight; + + } + + const skew = this.filmOffset; + if ( skew !== 0 ) left += near * skew / this.getFilmWidth(); + + this.projectionMatrix.makePerspective( left, left + width, top, top - height, near, this.far, this.coordinateSystem ); + + this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); + + } + + toJSON( meta ) { + + const data = super.toJSON( meta ); + + data.object.fov = this.fov; + data.object.zoom = this.zoom; + + data.object.near = this.near; + data.object.far = this.far; + data.object.focus = this.focus; + + data.object.aspect = this.aspect; + + if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); + + data.object.filmGauge = this.filmGauge; + data.object.filmOffset = this.filmOffset; + + return data; + + } + +} + +const fov = - 90; // negative fov is not an error +const aspect = 1; + +class CubeCamera extends Object3D { + + constructor( near, far, renderTarget ) { + + super(); + + this.type = 'CubeCamera'; + + this.renderTarget = renderTarget; + this.coordinateSystem = null; + this.activeMipmapLevel = 0; + + const cameraPX = new PerspectiveCamera( fov, aspect, near, far ); + cameraPX.layers = this.layers; + this.add( cameraPX ); + + const cameraNX = new PerspectiveCamera( fov, aspect, near, far ); + cameraNX.layers = this.layers; + this.add( cameraNX ); + + const cameraPY = new PerspectiveCamera( fov, aspect, near, far ); + cameraPY.layers = this.layers; + this.add( cameraPY ); + + const cameraNY = new PerspectiveCamera( fov, aspect, near, far ); + cameraNY.layers = this.layers; + this.add( cameraNY ); + + const cameraPZ = new PerspectiveCamera( fov, aspect, near, far ); + cameraPZ.layers = this.layers; + this.add( cameraPZ ); + + const cameraNZ = new PerspectiveCamera( fov, aspect, near, far ); + cameraNZ.layers = this.layers; + this.add( cameraNZ ); + + } + + updateCoordinateSystem() { + + const coordinateSystem = this.coordinateSystem; + + const cameras = this.children.concat(); + + const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = cameras; + + for ( const camera of cameras ) this.remove( camera ); + + if ( coordinateSystem === WebGLCoordinateSystem ) { + + cameraPX.up.set( 0, 1, 0 ); + cameraPX.lookAt( 1, 0, 0 ); + + cameraNX.up.set( 0, 1, 0 ); + cameraNX.lookAt( - 1, 0, 0 ); + + cameraPY.up.set( 0, 0, - 1 ); + cameraPY.lookAt( 0, 1, 0 ); + + cameraNY.up.set( 0, 0, 1 ); + cameraNY.lookAt( 0, - 1, 0 ); + + cameraPZ.up.set( 0, 1, 0 ); + cameraPZ.lookAt( 0, 0, 1 ); + + cameraNZ.up.set( 0, 1, 0 ); + cameraNZ.lookAt( 0, 0, - 1 ); + + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { + + cameraPX.up.set( 0, - 1, 0 ); + cameraPX.lookAt( - 1, 0, 0 ); + + cameraNX.up.set( 0, - 1, 0 ); + cameraNX.lookAt( 1, 0, 0 ); + + cameraPY.up.set( 0, 0, 1 ); + cameraPY.lookAt( 0, 1, 0 ); + + cameraNY.up.set( 0, 0, - 1 ); + cameraNY.lookAt( 0, - 1, 0 ); + + cameraPZ.up.set( 0, - 1, 0 ); + cameraPZ.lookAt( 0, 0, 1 ); + + cameraNZ.up.set( 0, - 1, 0 ); + cameraNZ.lookAt( 0, 0, - 1 ); + + } else { + + throw new Error( 'THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: ' + coordinateSystem ); + + } + + for ( const camera of cameras ) { + + this.add( camera ); + + camera.updateMatrixWorld(); + + } + + } + + update( renderer, scene ) { + + if ( this.parent === null ) this.updateMatrixWorld(); + + const { renderTarget, activeMipmapLevel } = this; + + if ( this.coordinateSystem !== renderer.coordinateSystem ) { + + this.coordinateSystem = renderer.coordinateSystem; + + this.updateCoordinateSystem(); + + } + + const [ cameraPX, cameraNX, cameraPY, cameraNY, cameraPZ, cameraNZ ] = this.children; + + const currentRenderTarget = renderer.getRenderTarget(); + const currentActiveCubeFace = renderer.getActiveCubeFace(); + const currentActiveMipmapLevel = renderer.getActiveMipmapLevel(); + + const currentXrEnabled = renderer.xr.enabled; + + renderer.xr.enabled = false; + + const generateMipmaps = renderTarget.texture.generateMipmaps; + + renderTarget.texture.generateMipmaps = false; + + renderer.setRenderTarget( renderTarget, 0, activeMipmapLevel ); + renderer.render( scene, cameraPX ); + + renderer.setRenderTarget( renderTarget, 1, activeMipmapLevel ); + renderer.render( scene, cameraNX ); + + renderer.setRenderTarget( renderTarget, 2, activeMipmapLevel ); + renderer.render( scene, cameraPY ); + + renderer.setRenderTarget( renderTarget, 3, activeMipmapLevel ); + renderer.render( scene, cameraNY ); + + renderer.setRenderTarget( renderTarget, 4, activeMipmapLevel ); + renderer.render( scene, cameraPZ ); + + // mipmaps are generated during the last call of render() + // at this point, all sides of the cube render target are defined + + renderTarget.texture.generateMipmaps = generateMipmaps; + + renderer.setRenderTarget( renderTarget, 5, activeMipmapLevel ); + renderer.render( scene, cameraNZ ); + + renderer.setRenderTarget( currentRenderTarget, currentActiveCubeFace, currentActiveMipmapLevel ); + + renderer.xr.enabled = currentXrEnabled; + + renderTarget.texture.needsPMREMUpdate = true; + + } + +} + +class CubeTexture extends Texture { + + constructor( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ) { + + images = images !== undefined ? images : []; + mapping = mapping !== undefined ? mapping : CubeReflectionMapping; + + super( images, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); + + this.isCubeTexture = true; + + this.flipY = false; + + } + + get images() { + + return this.image; + + } + + set images( value ) { + + this.image = value; + + } + +} + +class WebGLCubeRenderTarget extends WebGLRenderTarget { + + constructor( size = 1, options = {} ) { + + super( size, size, options ); + + this.isWebGLCubeRenderTarget = true; + + const image = { width: size, height: size, depth: 1 }; + const images = [ image, image, image, image, image, image ]; + + this.texture = new CubeTexture( images, options.mapping, options.wrapS, options.wrapT, options.magFilter, options.minFilter, options.format, options.type, options.anisotropy, options.colorSpace ); + + // By convention -- likely based on the RenderMan spec from the 1990's -- cube maps are specified by WebGL (and three.js) + // in a coordinate system in which positive-x is to the right when looking up the positive-z axis -- in other words, + // in a left-handed coordinate system. By continuing this convention, preexisting cube maps continued to render correctly. + + // three.js uses a right-handed coordinate system. So environment maps used in three.js appear to have px and nx swapped + // and the flag isRenderTargetTexture controls this conversion. The flip is not required when using WebGLCubeRenderTarget.texture + // as a cube texture (this is detected when isRenderTargetTexture is set to true for cube textures). + + this.texture.isRenderTargetTexture = true; + + this.texture.generateMipmaps = options.generateMipmaps !== undefined ? options.generateMipmaps : false; + this.texture.minFilter = options.minFilter !== undefined ? options.minFilter : LinearFilter; + + } + + fromEquirectangularTexture( renderer, texture ) { + + this.texture.type = texture.type; + this.texture.colorSpace = texture.colorSpace; + + this.texture.generateMipmaps = texture.generateMipmaps; + this.texture.minFilter = texture.minFilter; + this.texture.magFilter = texture.magFilter; + + const shader = { + + uniforms: { + tEquirect: { value: null }, + }, + + vertexShader: /* glsl */` + + varying vec3 vWorldDirection; + + vec3 transformDirection( in vec3 dir, in mat4 matrix ) { + + return normalize( ( matrix * vec4( dir, 0.0 ) ).xyz ); + + } + + void main() { + + vWorldDirection = transformDirection( position, modelMatrix ); + + #include + #include + + } + `, + + fragmentShader: /* glsl */` + + uniform sampler2D tEquirect; + + varying vec3 vWorldDirection; + + #include + + void main() { + + vec3 direction = normalize( vWorldDirection ); + + vec2 sampleUV = equirectUv( direction ); + + gl_FragColor = texture2D( tEquirect, sampleUV ); + + } + ` + }; + + const geometry = new BoxGeometry( 5, 5, 5 ); + + const material = new ShaderMaterial( { + + name: 'CubemapFromEquirect', + + uniforms: cloneUniforms( shader.uniforms ), + vertexShader: shader.vertexShader, + fragmentShader: shader.fragmentShader, + side: BackSide, + blending: NoBlending + + } ); + + material.uniforms.tEquirect.value = texture; + + const mesh = new Mesh( geometry, material ); + + const currentMinFilter = texture.minFilter; + + // Avoid blurred poles + if ( texture.minFilter === LinearMipmapLinearFilter ) texture.minFilter = LinearFilter; + + const camera = new CubeCamera( 1, 10, this ); + camera.update( renderer, mesh ); + + texture.minFilter = currentMinFilter; + + mesh.geometry.dispose(); + mesh.material.dispose(); + + return this; + + } + + clear( renderer, color, depth, stencil ) { + + const currentRenderTarget = renderer.getRenderTarget(); + + for ( let i = 0; i < 6; i ++ ) { + + renderer.setRenderTarget( this, i ); + + renderer.clear( color, depth, stencil ); + + } + + renderer.setRenderTarget( currentRenderTarget ); + + } + +} + +class FogExp2 { + + constructor( color, density = 0.00025 ) { + + this.isFogExp2 = true; + + this.name = ''; + + this.color = new Color( color ); + this.density = density; + + } + + clone() { + + return new FogExp2( this.color, this.density ); + + } + + toJSON( /* meta */ ) { + + return { + type: 'FogExp2', + name: this.name, + color: this.color.getHex(), + density: this.density + }; + + } + +} + +class Fog { + + constructor( color, near = 1, far = 1000 ) { + + this.isFog = true; + + this.name = ''; + + this.color = new Color( color ); + + this.near = near; + this.far = far; + + } + + clone() { + + return new Fog( this.color, this.near, this.far ); + + } + + toJSON( /* meta */ ) { + + return { + type: 'Fog', + name: this.name, + color: this.color.getHex(), + near: this.near, + far: this.far + }; + + } + +} + +class Scene extends Object3D { + + constructor() { + + super(); + + this.isScene = true; + + this.type = 'Scene'; + + this.background = null; + this.environment = null; + this.fog = null; + + this.backgroundBlurriness = 0; + this.backgroundIntensity = 1; + this.backgroundRotation = new Euler(); + + this.environmentIntensity = 1; + this.environmentRotation = new Euler(); + + this.overrideMaterial = null; + + if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { + + __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'observe', { detail: this } ) ); + + } + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + if ( source.background !== null ) this.background = source.background.clone(); + if ( source.environment !== null ) this.environment = source.environment.clone(); + if ( source.fog !== null ) this.fog = source.fog.clone(); + + this.backgroundBlurriness = source.backgroundBlurriness; + this.backgroundIntensity = source.backgroundIntensity; + this.backgroundRotation.copy( source.backgroundRotation ); + + this.environmentIntensity = source.environmentIntensity; + this.environmentRotation.copy( source.environmentRotation ); + + if ( source.overrideMaterial !== null ) this.overrideMaterial = source.overrideMaterial.clone(); + + this.matrixAutoUpdate = source.matrixAutoUpdate; + + return this; + + } + + toJSON( meta ) { + + const data = super.toJSON( meta ); + + if ( this.fog !== null ) data.object.fog = this.fog.toJSON(); + + if ( this.backgroundBlurriness > 0 ) data.object.backgroundBlurriness = this.backgroundBlurriness; + if ( this.backgroundIntensity !== 1 ) data.object.backgroundIntensity = this.backgroundIntensity; + data.object.backgroundRotation = this.backgroundRotation.toArray(); + + if ( this.environmentIntensity !== 1 ) data.object.environmentIntensity = this.environmentIntensity; + data.object.environmentRotation = this.environmentRotation.toArray(); + + return data; + + } + +} + +class InterleavedBuffer { + + constructor( array, stride ) { + + this.isInterleavedBuffer = true; + + this.array = array; + this.stride = stride; + this.count = array !== undefined ? array.length / stride : 0; + + this.usage = StaticDrawUsage; + this.updateRanges = []; + + this.version = 0; + + this.uuid = generateUUID(); + + } + + onUploadCallback() {} + + set needsUpdate( value ) { + + if ( value === true ) this.version ++; + + } + + setUsage( value ) { + + this.usage = value; + + return this; + + } + + addUpdateRange( start, count ) { + + this.updateRanges.push( { start, count } ); + + } + + clearUpdateRanges() { + + this.updateRanges.length = 0; + + } + + copy( source ) { + + this.array = new source.array.constructor( source.array ); + this.count = source.count; + this.stride = source.stride; + this.usage = source.usage; + + return this; + + } + + copyAt( index1, attribute, index2 ) { + + index1 *= this.stride; + index2 *= attribute.stride; + + for ( let i = 0, l = this.stride; i < l; i ++ ) { + + this.array[ index1 + i ] = attribute.array[ index2 + i ]; + + } + + return this; + + } + + set( value, offset = 0 ) { + + this.array.set( value, offset ); + + return this; + + } + + clone( data ) { + + if ( data.arrayBuffers === undefined ) { + + data.arrayBuffers = {}; + + } + + if ( this.array.buffer._uuid === undefined ) { + + this.array.buffer._uuid = generateUUID(); + + } + + if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) { + + data.arrayBuffers[ this.array.buffer._uuid ] = this.array.slice( 0 ).buffer; + + } + + const array = new this.array.constructor( data.arrayBuffers[ this.array.buffer._uuid ] ); + + const ib = new this.constructor( array, this.stride ); + ib.setUsage( this.usage ); + + return ib; + + } + + onUpload( callback ) { + + this.onUploadCallback = callback; + + return this; + + } + + toJSON( data ) { + + if ( data.arrayBuffers === undefined ) { + + data.arrayBuffers = {}; + + } + + // generate UUID for array buffer if necessary + + if ( this.array.buffer._uuid === undefined ) { + + this.array.buffer._uuid = generateUUID(); + + } + + if ( data.arrayBuffers[ this.array.buffer._uuid ] === undefined ) { + + data.arrayBuffers[ this.array.buffer._uuid ] = Array.from( new Uint32Array( this.array.buffer ) ); + + } + + // + + return { + uuid: this.uuid, + buffer: this.array.buffer._uuid, + type: this.array.constructor.name, + stride: this.stride + }; + + } + +} + +const _vector$7 = /*@__PURE__*/ new Vector3(); + +class InterleavedBufferAttribute { + + constructor( interleavedBuffer, itemSize, offset, normalized = false ) { + + this.isInterleavedBufferAttribute = true; + + this.name = ''; + + this.data = interleavedBuffer; + this.itemSize = itemSize; + this.offset = offset; + + this.normalized = normalized; + + } + + get count() { + + return this.data.count; + + } + + get array() { + + return this.data.array; + + } + + set needsUpdate( value ) { + + this.data.needsUpdate = value; + + } + + applyMatrix4( m ) { + + for ( let i = 0, l = this.data.count; i < l; i ++ ) { + + _vector$7.fromBufferAttribute( this, i ); + + _vector$7.applyMatrix4( m ); + + this.setXYZ( i, _vector$7.x, _vector$7.y, _vector$7.z ); + + } + + return this; + + } + + applyNormalMatrix( m ) { + + for ( let i = 0, l = this.count; i < l; i ++ ) { + + _vector$7.fromBufferAttribute( this, i ); + + _vector$7.applyNormalMatrix( m ); + + this.setXYZ( i, _vector$7.x, _vector$7.y, _vector$7.z ); + + } + + return this; + + } + + transformDirection( m ) { + + for ( let i = 0, l = this.count; i < l; i ++ ) { + + _vector$7.fromBufferAttribute( this, i ); + + _vector$7.transformDirection( m ); + + this.setXYZ( i, _vector$7.x, _vector$7.y, _vector$7.z ); + + } + + return this; + + } + + getComponent( index, component ) { + + let value = this.array[ index * this.data.stride + this.offset + component ]; + + if ( this.normalized ) value = denormalize( value, this.array ); + + return value; + + } + + setComponent( index, component, value ) { + + if ( this.normalized ) value = normalize$1( value, this.array ); + + this.data.array[ index * this.data.stride + this.offset + component ] = value; + + return this; + + } + + setX( index, x ) { + + if ( this.normalized ) x = normalize$1( x, this.array ); + + this.data.array[ index * this.data.stride + this.offset ] = x; + + return this; + + } + + setY( index, y ) { + + if ( this.normalized ) y = normalize$1( y, this.array ); + + this.data.array[ index * this.data.stride + this.offset + 1 ] = y; + + return this; + + } + + setZ( index, z ) { + + if ( this.normalized ) z = normalize$1( z, this.array ); + + this.data.array[ index * this.data.stride + this.offset + 2 ] = z; + + return this; + + } + + setW( index, w ) { + + if ( this.normalized ) w = normalize$1( w, this.array ); + + this.data.array[ index * this.data.stride + this.offset + 3 ] = w; + + return this; + + } + + getX( index ) { + + let x = this.data.array[ index * this.data.stride + this.offset ]; + + if ( this.normalized ) x = denormalize( x, this.array ); + + return x; + + } + + getY( index ) { + + let y = this.data.array[ index * this.data.stride + this.offset + 1 ]; + + if ( this.normalized ) y = denormalize( y, this.array ); + + return y; + + } + + getZ( index ) { + + let z = this.data.array[ index * this.data.stride + this.offset + 2 ]; + + if ( this.normalized ) z = denormalize( z, this.array ); + + return z; + + } + + getW( index ) { + + let w = this.data.array[ index * this.data.stride + this.offset + 3 ]; + + if ( this.normalized ) w = denormalize( w, this.array ); + + return w; + + } + + setXY( index, x, y ) { + + index = index * this.data.stride + this.offset; + + if ( this.normalized ) { + + x = normalize$1( x, this.array ); + y = normalize$1( y, this.array ); + + } + + this.data.array[ index + 0 ] = x; + this.data.array[ index + 1 ] = y; + + return this; + + } + + setXYZ( index, x, y, z ) { + + index = index * this.data.stride + this.offset; + + if ( this.normalized ) { + + x = normalize$1( x, this.array ); + y = normalize$1( y, this.array ); + z = normalize$1( z, this.array ); + + } + + this.data.array[ index + 0 ] = x; + this.data.array[ index + 1 ] = y; + this.data.array[ index + 2 ] = z; + + return this; + + } + + setXYZW( index, x, y, z, w ) { + + index = index * this.data.stride + this.offset; + + if ( this.normalized ) { + + x = normalize$1( x, this.array ); + y = normalize$1( y, this.array ); + z = normalize$1( z, this.array ); + w = normalize$1( w, this.array ); + + } + + this.data.array[ index + 0 ] = x; + this.data.array[ index + 1 ] = y; + this.data.array[ index + 2 ] = z; + this.data.array[ index + 3 ] = w; + + return this; + + } + + clone( data ) { + + if ( data === undefined ) { + + console.log( 'THREE.InterleavedBufferAttribute.clone(): Cloning an interleaved buffer attribute will de-interleave buffer data.' ); + + const array = []; + + for ( let i = 0; i < this.count; i ++ ) { + + const index = i * this.data.stride + this.offset; + + for ( let j = 0; j < this.itemSize; j ++ ) { + + array.push( this.data.array[ index + j ] ); + + } + + } + + return new BufferAttribute( new this.array.constructor( array ), this.itemSize, this.normalized ); + + } else { + + if ( data.interleavedBuffers === undefined ) { + + data.interleavedBuffers = {}; + + } + + if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) { + + data.interleavedBuffers[ this.data.uuid ] = this.data.clone( data ); + + } + + return new InterleavedBufferAttribute( data.interleavedBuffers[ this.data.uuid ], this.itemSize, this.offset, this.normalized ); + + } + + } + + toJSON( data ) { + + if ( data === undefined ) { + + console.log( 'THREE.InterleavedBufferAttribute.toJSON(): Serializing an interleaved buffer attribute will de-interleave buffer data.' ); + + const array = []; + + for ( let i = 0; i < this.count; i ++ ) { + + const index = i * this.data.stride + this.offset; + + for ( let j = 0; j < this.itemSize; j ++ ) { + + array.push( this.data.array[ index + j ] ); + + } + + } + + // de-interleave data and save it as an ordinary buffer attribute for now + + return { + itemSize: this.itemSize, + type: this.array.constructor.name, + array: array, + normalized: this.normalized + }; + + } else { + + // save as true interleaved attribute + + if ( data.interleavedBuffers === undefined ) { + + data.interleavedBuffers = {}; + + } + + if ( data.interleavedBuffers[ this.data.uuid ] === undefined ) { + + data.interleavedBuffers[ this.data.uuid ] = this.data.toJSON( data ); + + } + + return { + isInterleavedBufferAttribute: true, + itemSize: this.itemSize, + data: this.data.uuid, + offset: this.offset, + normalized: this.normalized + }; + + } + + } + +} + +class SpriteMaterial extends Material { + + constructor( parameters ) { + + super(); + + this.isSpriteMaterial = true; + + this.type = 'SpriteMaterial'; + + this.color = new Color( 0xffffff ); + + this.map = null; + + this.alphaMap = null; + + this.rotation = 0; + + this.sizeAttenuation = true; + + this.transparent = true; + + this.fog = true; + + this.setValues( parameters ); + + } + + copy( source ) { + + super.copy( source ); + + this.color.copy( source.color ); + + this.map = source.map; + + this.alphaMap = source.alphaMap; + + this.rotation = source.rotation; + + this.sizeAttenuation = source.sizeAttenuation; + + this.fog = source.fog; + + return this; + + } + +} + +let _geometry$1; + +const _intersectPoint = /*@__PURE__*/ new Vector3(); +const _worldScale = /*@__PURE__*/ new Vector3(); +const _mvPosition = /*@__PURE__*/ new Vector3(); + +const _alignedPosition = /*@__PURE__*/ new Vector2(); +const _rotatedPosition = /*@__PURE__*/ new Vector2(); +const _viewWorldMatrix = /*@__PURE__*/ new Matrix4(); + +const _vA = /*@__PURE__*/ new Vector3(); +const _vB = /*@__PURE__*/ new Vector3(); +const _vC = /*@__PURE__*/ new Vector3(); + +const _uvA = /*@__PURE__*/ new Vector2(); +const _uvB = /*@__PURE__*/ new Vector2(); +const _uvC = /*@__PURE__*/ new Vector2(); + +class Sprite extends Object3D { + + constructor( material = new SpriteMaterial() ) { + + super(); + + this.isSprite = true; + + this.type = 'Sprite'; + + if ( _geometry$1 === undefined ) { + + _geometry$1 = new BufferGeometry(); + + const float32Array = new Float32Array( [ + - 0.5, - 0.5, 0, 0, 0, + 0.5, - 0.5, 0, 1, 0, + 0.5, 0.5, 0, 1, 1, + - 0.5, 0.5, 0, 0, 1 + ] ); + + const interleavedBuffer = new InterleavedBuffer( float32Array, 5 ); + + _geometry$1.setIndex( [ 0, 1, 2, 0, 2, 3 ] ); + _geometry$1.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) ); + _geometry$1.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) ); + + } + + this.geometry = _geometry$1; + this.material = material; + + this.center = new Vector2( 0.5, 0.5 ); + + } + + raycast( raycaster, intersects ) { + + if ( raycaster.camera === null ) { + + console.error( 'THREE.Sprite: "Raycaster.camera" needs to be set in order to raycast against sprites.' ); + + } + + _worldScale.setFromMatrixScale( this.matrixWorld ); + + _viewWorldMatrix.copy( raycaster.camera.matrixWorld ); + this.modelViewMatrix.multiplyMatrices( raycaster.camera.matrixWorldInverse, this.matrixWorld ); + + _mvPosition.setFromMatrixPosition( this.modelViewMatrix ); + + if ( raycaster.camera.isPerspectiveCamera && this.material.sizeAttenuation === false ) { + + _worldScale.multiplyScalar( - _mvPosition.z ); + + } + + const rotation = this.material.rotation; + let sin, cos; + + if ( rotation !== 0 ) { + + cos = Math.cos( rotation ); + sin = Math.sin( rotation ); + + } + + const center = this.center; + + transformVertex( _vA.set( - 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); + transformVertex( _vB.set( 0.5, - 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); + transformVertex( _vC.set( 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); + + _uvA.set( 0, 0 ); + _uvB.set( 1, 0 ); + _uvC.set( 1, 1 ); + + // check first triangle + let intersect = raycaster.ray.intersectTriangle( _vA, _vB, _vC, false, _intersectPoint ); + + if ( intersect === null ) { + + // check second triangle + transformVertex( _vB.set( - 0.5, 0.5, 0 ), _mvPosition, center, _worldScale, sin, cos ); + _uvB.set( 0, 1 ); + + intersect = raycaster.ray.intersectTriangle( _vA, _vC, _vB, false, _intersectPoint ); + if ( intersect === null ) { + + return; + + } + + } + + const distance = raycaster.ray.origin.distanceTo( _intersectPoint ); + + if ( distance < raycaster.near || distance > raycaster.far ) return; + + intersects.push( { + + distance: distance, + point: _intersectPoint.clone(), + uv: Triangle.getInterpolation( _intersectPoint, _vA, _vB, _vC, _uvA, _uvB, _uvC, new Vector2() ), + face: null, + object: this + + } ); + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + if ( source.center !== undefined ) this.center.copy( source.center ); + + this.material = source.material; + + return this; + + } + +} + +function transformVertex( vertexPosition, mvPosition, center, scale, sin, cos ) { + + // compute position in camera space + _alignedPosition.subVectors( vertexPosition, center ).addScalar( 0.5 ).multiply( scale ); + + // to check if rotation is not zero + if ( sin !== undefined ) { + + _rotatedPosition.x = ( cos * _alignedPosition.x ) - ( sin * _alignedPosition.y ); + _rotatedPosition.y = ( sin * _alignedPosition.x ) + ( cos * _alignedPosition.y ); + + } else { + + _rotatedPosition.copy( _alignedPosition ); + + } + + + vertexPosition.copy( mvPosition ); + vertexPosition.x += _rotatedPosition.x; + vertexPosition.y += _rotatedPosition.y; + + // transform to world space + vertexPosition.applyMatrix4( _viewWorldMatrix ); + +} + +const _v1$2 = /*@__PURE__*/ new Vector3(); +const _v2$1 = /*@__PURE__*/ new Vector3(); + +class LOD extends Object3D { + + constructor() { + + super(); + + this._currentLevel = 0; + + this.type = 'LOD'; + + Object.defineProperties( this, { + levels: { + enumerable: true, + value: [] + }, + isLOD: { + value: true, + } + } ); + + this.autoUpdate = true; + + } + + copy( source ) { + + super.copy( source, false ); + + const levels = source.levels; + + for ( let i = 0, l = levels.length; i < l; i ++ ) { + + const level = levels[ i ]; + + this.addLevel( level.object.clone(), level.distance, level.hysteresis ); + + } + + this.autoUpdate = source.autoUpdate; + + return this; + + } + + addLevel( object, distance = 0, hysteresis = 0 ) { + + distance = Math.abs( distance ); + + const levels = this.levels; + + let l; + + for ( l = 0; l < levels.length; l ++ ) { + + if ( distance < levels[ l ].distance ) { + + break; + + } + + } + + levels.splice( l, 0, { distance: distance, hysteresis: hysteresis, object: object } ); + + this.add( object ); + + return this; + + } + + removeLevel( distance ) { + + const levels = this.levels; + + for ( let i = 0; i < levels.length; i ++ ) { + + if ( levels[ i ].distance === distance ) { + + const removedElements = levels.splice( i, 1 ); + this.remove( removedElements[ 0 ].object ); + + return true; + + } + + } + + return false; + + } + + getCurrentLevel() { + + return this._currentLevel; + + } + + + + getObjectForDistance( distance ) { + + const levels = this.levels; + + if ( levels.length > 0 ) { + + let i, l; + + for ( i = 1, l = levels.length; i < l; i ++ ) { + + let levelDistance = levels[ i ].distance; + + if ( levels[ i ].object.visible ) { + + levelDistance -= levelDistance * levels[ i ].hysteresis; + + } + + if ( distance < levelDistance ) { + + break; + + } + + } + + return levels[ i - 1 ].object; + + } + + return null; + + } + + raycast( raycaster, intersects ) { + + const levels = this.levels; + + if ( levels.length > 0 ) { + + _v1$2.setFromMatrixPosition( this.matrixWorld ); + + const distance = raycaster.ray.origin.distanceTo( _v1$2 ); + + this.getObjectForDistance( distance ).raycast( raycaster, intersects ); + + } + + } + + update( camera ) { + + const levels = this.levels; + + if ( levels.length > 1 ) { + + _v1$2.setFromMatrixPosition( camera.matrixWorld ); + _v2$1.setFromMatrixPosition( this.matrixWorld ); + + const distance = _v1$2.distanceTo( _v2$1 ) / camera.zoom; + + levels[ 0 ].object.visible = true; + + let i, l; + + for ( i = 1, l = levels.length; i < l; i ++ ) { + + let levelDistance = levels[ i ].distance; + + if ( levels[ i ].object.visible ) { + + levelDistance -= levelDistance * levels[ i ].hysteresis; + + } + + if ( distance >= levelDistance ) { + + levels[ i - 1 ].object.visible = false; + levels[ i ].object.visible = true; + + } else { + + break; + + } + + } + + this._currentLevel = i - 1; + + for ( ; i < l; i ++ ) { + + levels[ i ].object.visible = false; + + } + + } + + } + + toJSON( meta ) { + + const data = super.toJSON( meta ); + + if ( this.autoUpdate === false ) data.object.autoUpdate = false; + + data.object.levels = []; + + const levels = this.levels; + + for ( let i = 0, l = levels.length; i < l; i ++ ) { + + const level = levels[ i ]; + + data.object.levels.push( { + object: level.object.uuid, + distance: level.distance, + hysteresis: level.hysteresis + } ); + + } + + return data; + + } + +} + +const _basePosition = /*@__PURE__*/ new Vector3(); + +const _skinIndex = /*@__PURE__*/ new Vector4(); +const _skinWeight = /*@__PURE__*/ new Vector4(); + +const _vector3 = /*@__PURE__*/ new Vector3(); +const _matrix4 = /*@__PURE__*/ new Matrix4(); +const _vertex = /*@__PURE__*/ new Vector3(); + +const _sphere$5 = /*@__PURE__*/ new Sphere(); +const _inverseMatrix$2 = /*@__PURE__*/ new Matrix4(); +const _ray$2 = /*@__PURE__*/ new Ray(); + +class SkinnedMesh extends Mesh { + + constructor( geometry, material ) { + + super( geometry, material ); + + this.isSkinnedMesh = true; + + this.type = 'SkinnedMesh'; + + this.bindMode = AttachedBindMode; + this.bindMatrix = new Matrix4(); + this.bindMatrixInverse = new Matrix4(); + + this.boundingBox = null; + this.boundingSphere = null; + + } + + computeBoundingBox() { + + const geometry = this.geometry; + + if ( this.boundingBox === null ) { + + this.boundingBox = new Box3(); + + } + + this.boundingBox.makeEmpty(); + + const positionAttribute = geometry.getAttribute( 'position' ); + + for ( let i = 0; i < positionAttribute.count; i ++ ) { + + this.getVertexPosition( i, _vertex ); + this.boundingBox.expandByPoint( _vertex ); + + } + + } + + computeBoundingSphere() { + + const geometry = this.geometry; + + if ( this.boundingSphere === null ) { + + this.boundingSphere = new Sphere(); + + } + + this.boundingSphere.makeEmpty(); + + const positionAttribute = geometry.getAttribute( 'position' ); + + for ( let i = 0; i < positionAttribute.count; i ++ ) { + + this.getVertexPosition( i, _vertex ); + this.boundingSphere.expandByPoint( _vertex ); + + } + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + this.bindMode = source.bindMode; + this.bindMatrix.copy( source.bindMatrix ); + this.bindMatrixInverse.copy( source.bindMatrixInverse ); + + this.skeleton = source.skeleton; + + if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); + if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); + + return this; + + } + + raycast( raycaster, intersects ) { + + const material = this.material; + const matrixWorld = this.matrixWorld; + + if ( material === undefined ) return; + + // test with bounding sphere in world space + + if ( this.boundingSphere === null ) this.computeBoundingSphere(); + + _sphere$5.copy( this.boundingSphere ); + _sphere$5.applyMatrix4( matrixWorld ); + + if ( raycaster.ray.intersectsSphere( _sphere$5 ) === false ) return; + + // convert ray to local space of skinned mesh + + _inverseMatrix$2.copy( matrixWorld ).invert(); + _ray$2.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$2 ); + + // test with bounding box in local space + + if ( this.boundingBox !== null ) { + + if ( _ray$2.intersectsBox( this.boundingBox ) === false ) return; + + } + + // test for intersections with geometry + + this._computeIntersections( raycaster, intersects, _ray$2 ); + + } + + getVertexPosition( index, target ) { + + super.getVertexPosition( index, target ); + + this.applyBoneTransform( index, target ); + + return target; + + } + + bind( skeleton, bindMatrix ) { + + this.skeleton = skeleton; + + if ( bindMatrix === undefined ) { + + this.updateMatrixWorld( true ); + + this.skeleton.calculateInverses(); + + bindMatrix = this.matrixWorld; + + } + + this.bindMatrix.copy( bindMatrix ); + this.bindMatrixInverse.copy( bindMatrix ).invert(); + + } + + pose() { + + this.skeleton.pose(); + + } + + normalizeSkinWeights() { + + const vector = new Vector4(); + + const skinWeight = this.geometry.attributes.skinWeight; + + for ( let i = 0, l = skinWeight.count; i < l; i ++ ) { + + vector.fromBufferAttribute( skinWeight, i ); + + const scale = 1.0 / vector.manhattanLength(); + + if ( scale !== Infinity ) { + + vector.multiplyScalar( scale ); + + } else { + + vector.set( 1, 0, 0, 0 ); // do something reasonable + + } + + skinWeight.setXYZW( i, vector.x, vector.y, vector.z, vector.w ); + + } + + } + + updateMatrixWorld( force ) { + + super.updateMatrixWorld( force ); + + if ( this.bindMode === AttachedBindMode ) { + + this.bindMatrixInverse.copy( this.matrixWorld ).invert(); + + } else if ( this.bindMode === DetachedBindMode ) { + + this.bindMatrixInverse.copy( this.bindMatrix ).invert(); + + } else { + + console.warn( 'THREE.SkinnedMesh: Unrecognized bindMode: ' + this.bindMode ); + + } + + } + + applyBoneTransform( index, vector ) { + + const skeleton = this.skeleton; + const geometry = this.geometry; + + _skinIndex.fromBufferAttribute( geometry.attributes.skinIndex, index ); + _skinWeight.fromBufferAttribute( geometry.attributes.skinWeight, index ); + + _basePosition.copy( vector ).applyMatrix4( this.bindMatrix ); + + vector.set( 0, 0, 0 ); + + for ( let i = 0; i < 4; i ++ ) { + + const weight = _skinWeight.getComponent( i ); + + if ( weight !== 0 ) { + + const boneIndex = _skinIndex.getComponent( i ); + + _matrix4.multiplyMatrices( skeleton.bones[ boneIndex ].matrixWorld, skeleton.boneInverses[ boneIndex ] ); + + vector.addScaledVector( _vector3.copy( _basePosition ).applyMatrix4( _matrix4 ), weight ); + + } + + } + + return vector.applyMatrix4( this.bindMatrixInverse ); + + } + +} + +class Bone extends Object3D { + + constructor() { + + super(); + + this.isBone = true; + + this.type = 'Bone'; + + } + +} + +class DataTexture extends Texture { + + constructor( data = null, width = 1, height = 1, format, type, mapping, wrapS, wrapT, magFilter = NearestFilter, minFilter = NearestFilter, anisotropy, colorSpace ) { + + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); + + this.isDataTexture = true; + + this.image = { data: data, width: width, height: height }; + + this.generateMipmaps = false; + this.flipY = false; + this.unpackAlignment = 1; + + } + +} + +const _offsetMatrix = /*@__PURE__*/ new Matrix4(); +const _identityMatrix$1 = /*@__PURE__*/ new Matrix4(); + +class Skeleton { + + constructor( bones = [], boneInverses = [] ) { + + this.uuid = generateUUID(); + + this.bones = bones.slice( 0 ); + this.boneInverses = boneInverses; + this.boneMatrices = null; + + this.boneTexture = null; + + this.init(); + + } + + init() { + + const bones = this.bones; + const boneInverses = this.boneInverses; + + this.boneMatrices = new Float32Array( bones.length * 16 ); + + // calculate inverse bone matrices if necessary + + if ( boneInverses.length === 0 ) { + + this.calculateInverses(); + + } else { + + // handle special case + + if ( bones.length !== boneInverses.length ) { + + console.warn( 'THREE.Skeleton: Number of inverse bone matrices does not match amount of bones.' ); + + this.boneInverses = []; + + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { + + this.boneInverses.push( new Matrix4() ); + + } + + } + + } + + } + + calculateInverses() { + + this.boneInverses.length = 0; + + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { + + const inverse = new Matrix4(); + + if ( this.bones[ i ] ) { + + inverse.copy( this.bones[ i ].matrixWorld ).invert(); + + } + + this.boneInverses.push( inverse ); + + } + + } + + pose() { + + // recover the bind-time world matrices + + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { + + const bone = this.bones[ i ]; + + if ( bone ) { + + bone.matrixWorld.copy( this.boneInverses[ i ] ).invert(); + + } + + } + + // compute the local matrices, positions, rotations and scales + + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { + + const bone = this.bones[ i ]; + + if ( bone ) { + + if ( bone.parent && bone.parent.isBone ) { + + bone.matrix.copy( bone.parent.matrixWorld ).invert(); + bone.matrix.multiply( bone.matrixWorld ); + + } else { + + bone.matrix.copy( bone.matrixWorld ); + + } + + bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); + + } + + } + + } + + update() { + + const bones = this.bones; + const boneInverses = this.boneInverses; + const boneMatrices = this.boneMatrices; + const boneTexture = this.boneTexture; + + // flatten bone matrices to array + + for ( let i = 0, il = bones.length; i < il; i ++ ) { + + // compute the offset between the current and the original transform + + const matrix = bones[ i ] ? bones[ i ].matrixWorld : _identityMatrix$1; + + _offsetMatrix.multiplyMatrices( matrix, boneInverses[ i ] ); + _offsetMatrix.toArray( boneMatrices, i * 16 ); + + } + + if ( boneTexture !== null ) { + + boneTexture.needsUpdate = true; + + } + + } + + clone() { + + return new Skeleton( this.bones, this.boneInverses ); + + } + + computeBoneTexture() { + + // layout (1 matrix = 4 pixels) + // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) + // with 8x8 pixel texture max 16 bones * 4 pixels = (8 * 8) + // 16x16 pixel texture max 64 bones * 4 pixels = (16 * 16) + // 32x32 pixel texture max 256 bones * 4 pixels = (32 * 32) + // 64x64 pixel texture max 1024 bones * 4 pixels = (64 * 64) + + let size = Math.sqrt( this.bones.length * 4 ); // 4 pixels needed for 1 matrix + size = Math.ceil( size / 4 ) * 4; + size = Math.max( size, 4 ); + + const boneMatrices = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel + boneMatrices.set( this.boneMatrices ); // copy current values + + const boneTexture = new DataTexture( boneMatrices, size, size, RGBAFormat, FloatType ); + boneTexture.needsUpdate = true; + + this.boneMatrices = boneMatrices; + this.boneTexture = boneTexture; + + return this; + + } + + getBoneByName( name ) { + + for ( let i = 0, il = this.bones.length; i < il; i ++ ) { + + const bone = this.bones[ i ]; + + if ( bone.name === name ) { + + return bone; + + } + + } + + return undefined; + + } + + dispose( ) { + + if ( this.boneTexture !== null ) { + + this.boneTexture.dispose(); + + this.boneTexture = null; + + } + + } + + fromJSON( json, bones ) { + + this.uuid = json.uuid; + + for ( let i = 0, l = json.bones.length; i < l; i ++ ) { + + const uuid = json.bones[ i ]; + let bone = bones[ uuid ]; + + if ( bone === undefined ) { + + console.warn( 'THREE.Skeleton: No bone found with UUID:', uuid ); + bone = new Bone(); + + } + + this.bones.push( bone ); + this.boneInverses.push( new Matrix4().fromArray( json.boneInverses[ i ] ) ); + + } + + this.init(); + + return this; + + } + + toJSON() { + + const data = { + metadata: { + version: 4.6, + type: 'Skeleton', + generator: 'Skeleton.toJSON' + }, + bones: [], + boneInverses: [] + }; + + data.uuid = this.uuid; + + const bones = this.bones; + const boneInverses = this.boneInverses; + + for ( let i = 0, l = bones.length; i < l; i ++ ) { + + const bone = bones[ i ]; + data.bones.push( bone.uuid ); + + const boneInverse = boneInverses[ i ]; + data.boneInverses.push( boneInverse.toArray() ); + + } + + return data; + + } + +} + +class InstancedBufferAttribute extends BufferAttribute { + + constructor( array, itemSize, normalized, meshPerAttribute = 1 ) { + + super( array, itemSize, normalized ); + + this.isInstancedBufferAttribute = true; + + this.meshPerAttribute = meshPerAttribute; + + } + + copy( source ) { + + super.copy( source ); + + this.meshPerAttribute = source.meshPerAttribute; + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + data.meshPerAttribute = this.meshPerAttribute; + + data.isInstancedBufferAttribute = true; + + return data; + + } + +} + +const _instanceLocalMatrix = /*@__PURE__*/ new Matrix4(); +const _instanceWorldMatrix = /*@__PURE__*/ new Matrix4(); + +const _instanceIntersects = []; + +const _box3 = /*@__PURE__*/ new Box3(); +const _identity = /*@__PURE__*/ new Matrix4(); +const _mesh$1 = /*@__PURE__*/ new Mesh(); +const _sphere$4 = /*@__PURE__*/ new Sphere(); + +class InstancedMesh extends Mesh { + + constructor( geometry, material, count ) { + + super( geometry, material ); + + this.isInstancedMesh = true; + + this.instanceMatrix = new InstancedBufferAttribute( new Float32Array( count * 16 ), 16 ); + this.instanceColor = null; + this.morphTexture = null; + + this.count = count; + + this.boundingBox = null; + this.boundingSphere = null; + + for ( let i = 0; i < count; i ++ ) { + + this.setMatrixAt( i, _identity ); + + } + + } + + computeBoundingBox() { + + const geometry = this.geometry; + const count = this.count; + + if ( this.boundingBox === null ) { + + this.boundingBox = new Box3(); + + } + + if ( geometry.boundingBox === null ) { + + geometry.computeBoundingBox(); + + } + + this.boundingBox.makeEmpty(); + + for ( let i = 0; i < count; i ++ ) { + + this.getMatrixAt( i, _instanceLocalMatrix ); + + _box3.copy( geometry.boundingBox ).applyMatrix4( _instanceLocalMatrix ); + + this.boundingBox.union( _box3 ); + + } + + } + + computeBoundingSphere() { + + const geometry = this.geometry; + const count = this.count; + + if ( this.boundingSphere === null ) { + + this.boundingSphere = new Sphere(); + + } + + if ( geometry.boundingSphere === null ) { + + geometry.computeBoundingSphere(); + + } + + this.boundingSphere.makeEmpty(); + + for ( let i = 0; i < count; i ++ ) { + + this.getMatrixAt( i, _instanceLocalMatrix ); + + _sphere$4.copy( geometry.boundingSphere ).applyMatrix4( _instanceLocalMatrix ); + + this.boundingSphere.union( _sphere$4 ); + + } + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + this.instanceMatrix.copy( source.instanceMatrix ); + + if ( source.morphTexture !== null ) this.morphTexture = source.morphTexture.clone(); + if ( source.instanceColor !== null ) this.instanceColor = source.instanceColor.clone(); + + this.count = source.count; + + if ( source.boundingBox !== null ) this.boundingBox = source.boundingBox.clone(); + if ( source.boundingSphere !== null ) this.boundingSphere = source.boundingSphere.clone(); + + return this; + + } + + getColorAt( index, color ) { + + color.fromArray( this.instanceColor.array, index * 3 ); + + } + + getMatrixAt( index, matrix ) { + + matrix.fromArray( this.instanceMatrix.array, index * 16 ); + + } + + getMorphAt( index, object ) { + + const objectInfluences = object.morphTargetInfluences; + + const array = this.morphTexture.source.data.data; + + const len = objectInfluences.length + 1; // All influences + the baseInfluenceSum + + const dataIndex = index * len + 1; // Skip the baseInfluenceSum at the beginning + + for ( let i = 0; i < objectInfluences.length; i ++ ) { + + objectInfluences[ i ] = array[ dataIndex + i ]; + + } + + } + + raycast( raycaster, intersects ) { + + const matrixWorld = this.matrixWorld; + const raycastTimes = this.count; + + _mesh$1.geometry = this.geometry; + _mesh$1.material = this.material; + + if ( _mesh$1.material === undefined ) return; + + // test with bounding sphere first + + if ( this.boundingSphere === null ) this.computeBoundingSphere(); + + _sphere$4.copy( this.boundingSphere ); + _sphere$4.applyMatrix4( matrixWorld ); + + if ( raycaster.ray.intersectsSphere( _sphere$4 ) === false ) return; + + // now test each instance + + for ( let instanceId = 0; instanceId < raycastTimes; instanceId ++ ) { + + // calculate the world matrix for each instance + + this.getMatrixAt( instanceId, _instanceLocalMatrix ); + + _instanceWorldMatrix.multiplyMatrices( matrixWorld, _instanceLocalMatrix ); + + // the mesh represents this single instance + + _mesh$1.matrixWorld = _instanceWorldMatrix; + + _mesh$1.raycast( raycaster, _instanceIntersects ); + + // process the result of raycast + + for ( let i = 0, l = _instanceIntersects.length; i < l; i ++ ) { + + const intersect = _instanceIntersects[ i ]; + intersect.instanceId = instanceId; + intersect.object = this; + intersects.push( intersect ); + + } + + _instanceIntersects.length = 0; + + } + + } + + setColorAt( index, color ) { + + if ( this.instanceColor === null ) { + + this.instanceColor = new InstancedBufferAttribute( new Float32Array( this.instanceMatrix.count * 3 ).fill( 1 ), 3 ); + + } + + color.toArray( this.instanceColor.array, index * 3 ); + + } + + setMatrixAt( index, matrix ) { + + matrix.toArray( this.instanceMatrix.array, index * 16 ); + + } + + setMorphAt( index, object ) { + + const objectInfluences = object.morphTargetInfluences; + + const len = objectInfluences.length + 1; // morphBaseInfluence + all influences + + if ( this.morphTexture === null ) { + + this.morphTexture = new DataTexture( new Float32Array( len * this.count ), len, this.count, RedFormat, FloatType ); + + } + + const array = this.morphTexture.source.data.data; + + let morphInfluencesSum = 0; + + for ( let i = 0; i < objectInfluences.length; i ++ ) { + + morphInfluencesSum += objectInfluences[ i ]; + + } + + const morphBaseInfluence = this.geometry.morphTargetsRelative ? 1 : 1 - morphInfluencesSum; + + const dataIndex = len * index; + + array[ dataIndex ] = morphBaseInfluence; + + array.set( objectInfluences, dataIndex + 1 ); + + } + + updateMorphTargets() { + + } + + dispose() { + + this.dispatchEvent( { type: 'dispose' } ); + + if ( this.morphTexture !== null ) { + + this.morphTexture.dispose(); + this.morphTexture = null; + + } + + return this; + + } + +} + +const _vector1 = /*@__PURE__*/ new Vector3(); +const _vector2 = /*@__PURE__*/ new Vector3(); +const _normalMatrix = /*@__PURE__*/ new Matrix3(); + +class Plane { + + constructor( normal = new Vector3( 1, 0, 0 ), constant = 0 ) { + + this.isPlane = true; + + // normal is assumed to be normalized + + this.normal = normal; + this.constant = constant; + + } + + set( normal, constant ) { + + this.normal.copy( normal ); + this.constant = constant; + + return this; + + } + + setComponents( x, y, z, w ) { + + this.normal.set( x, y, z ); + this.constant = w; + + return this; + + } + + setFromNormalAndCoplanarPoint( normal, point ) { + + this.normal.copy( normal ); + this.constant = - point.dot( this.normal ); + + return this; + + } + + setFromCoplanarPoints( a, b, c ) { + + const normal = _vector1.subVectors( c, b ).cross( _vector2.subVectors( a, b ) ).normalize(); + + // Q: should an error be thrown if normal is zero (e.g. degenerate plane)? + + this.setFromNormalAndCoplanarPoint( normal, a ); + + return this; + + } + + copy( plane ) { + + this.normal.copy( plane.normal ); + this.constant = plane.constant; + + return this; + + } + + normalize() { + + // Note: will lead to a divide by zero if the plane is invalid. + + const inverseNormalLength = 1.0 / this.normal.length(); + this.normal.multiplyScalar( inverseNormalLength ); + this.constant *= inverseNormalLength; + + return this; + + } + + negate() { + + this.constant *= - 1; + this.normal.negate(); + + return this; + + } + + distanceToPoint( point ) { + + return this.normal.dot( point ) + this.constant; + + } + + distanceToSphere( sphere ) { + + return this.distanceToPoint( sphere.center ) - sphere.radius; + + } + + projectPoint( point, target ) { + + return target.copy( point ).addScaledVector( this.normal, - this.distanceToPoint( point ) ); + + } + + intersectLine( line, target ) { + + const direction = line.delta( _vector1 ); + + const denominator = this.normal.dot( direction ); + + if ( denominator === 0 ) { + + // line is coplanar, return origin + if ( this.distanceToPoint( line.start ) === 0 ) { + + return target.copy( line.start ); + + } + + // Unsure if this is the correct method to handle this case. + return null; + + } + + const t = - ( line.start.dot( this.normal ) + this.constant ) / denominator; + + if ( t < 0 || t > 1 ) { + + return null; + + } + + return target.copy( line.start ).addScaledVector( direction, t ); + + } + + intersectsLine( line ) { + + // Note: this tests if a line intersects the plane, not whether it (or its end-points) are coplanar with it. + + const startSign = this.distanceToPoint( line.start ); + const endSign = this.distanceToPoint( line.end ); + + return ( startSign < 0 && endSign > 0 ) || ( endSign < 0 && startSign > 0 ); + + } + + intersectsBox( box ) { + + return box.intersectsPlane( this ); + + } + + intersectsSphere( sphere ) { + + return sphere.intersectsPlane( this ); + + } + + coplanarPoint( target ) { + + return target.copy( this.normal ).multiplyScalar( - this.constant ); + + } + + applyMatrix4( matrix, optionalNormalMatrix ) { + + const normalMatrix = optionalNormalMatrix || _normalMatrix.getNormalMatrix( matrix ); + + const referencePoint = this.coplanarPoint( _vector1 ).applyMatrix4( matrix ); + + const normal = this.normal.applyMatrix3( normalMatrix ).normalize(); + + this.constant = - referencePoint.dot( normal ); + + return this; + + } + + translate( offset ) { + + this.constant -= offset.dot( this.normal ); + + return this; + + } + + equals( plane ) { + + return plane.normal.equals( this.normal ) && ( plane.constant === this.constant ); + + } + + clone() { + + return new this.constructor().copy( this ); + + } + +} + +const _sphere$3 = /*@__PURE__*/ new Sphere(); +const _vector$6 = /*@__PURE__*/ new Vector3(); + +class Frustum { + + constructor( p0 = new Plane(), p1 = new Plane(), p2 = new Plane(), p3 = new Plane(), p4 = new Plane(), p5 = new Plane() ) { + + this.planes = [ p0, p1, p2, p3, p4, p5 ]; + + } + + set( p0, p1, p2, p3, p4, p5 ) { + + const planes = this.planes; + + planes[ 0 ].copy( p0 ); + planes[ 1 ].copy( p1 ); + planes[ 2 ].copy( p2 ); + planes[ 3 ].copy( p3 ); + planes[ 4 ].copy( p4 ); + planes[ 5 ].copy( p5 ); + + return this; + + } + + copy( frustum ) { + + const planes = this.planes; + + for ( let i = 0; i < 6; i ++ ) { + + planes[ i ].copy( frustum.planes[ i ] ); + + } + + return this; + + } + + setFromProjectionMatrix( m, coordinateSystem = WebGLCoordinateSystem ) { + + const planes = this.planes; + const me = m.elements; + const me0 = me[ 0 ], me1 = me[ 1 ], me2 = me[ 2 ], me3 = me[ 3 ]; + const me4 = me[ 4 ], me5 = me[ 5 ], me6 = me[ 6 ], me7 = me[ 7 ]; + const me8 = me[ 8 ], me9 = me[ 9 ], me10 = me[ 10 ], me11 = me[ 11 ]; + const me12 = me[ 12 ], me13 = me[ 13 ], me14 = me[ 14 ], me15 = me[ 15 ]; + + planes[ 0 ].setComponents( me3 - me0, me7 - me4, me11 - me8, me15 - me12 ).normalize(); + planes[ 1 ].setComponents( me3 + me0, me7 + me4, me11 + me8, me15 + me12 ).normalize(); + planes[ 2 ].setComponents( me3 + me1, me7 + me5, me11 + me9, me15 + me13 ).normalize(); + planes[ 3 ].setComponents( me3 - me1, me7 - me5, me11 - me9, me15 - me13 ).normalize(); + planes[ 4 ].setComponents( me3 - me2, me7 - me6, me11 - me10, me15 - me14 ).normalize(); + + if ( coordinateSystem === WebGLCoordinateSystem ) { + + planes[ 5 ].setComponents( me3 + me2, me7 + me6, me11 + me10, me15 + me14 ).normalize(); + + } else if ( coordinateSystem === WebGPUCoordinateSystem ) { + + planes[ 5 ].setComponents( me2, me6, me10, me14 ).normalize(); + + } else { + + throw new Error( 'THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: ' + coordinateSystem ); + + } + + return this; + + } + + intersectsObject( object ) { + + if ( object.boundingSphere !== undefined ) { + + if ( object.boundingSphere === null ) object.computeBoundingSphere(); + + _sphere$3.copy( object.boundingSphere ).applyMatrix4( object.matrixWorld ); + + } else { + + const geometry = object.geometry; + + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + + _sphere$3.copy( geometry.boundingSphere ).applyMatrix4( object.matrixWorld ); + + } + + return this.intersectsSphere( _sphere$3 ); + + } + + intersectsSprite( sprite ) { + + _sphere$3.center.set( 0, 0, 0 ); + _sphere$3.radius = 0.7071067811865476; + _sphere$3.applyMatrix4( sprite.matrixWorld ); + + return this.intersectsSphere( _sphere$3 ); + + } + + intersectsSphere( sphere ) { + + const planes = this.planes; + const center = sphere.center; + const negRadius = - sphere.radius; + + for ( let i = 0; i < 6; i ++ ) { + + const distance = planes[ i ].distanceToPoint( center ); + + if ( distance < negRadius ) { + + return false; + + } + + } + + return true; + + } + + intersectsBox( box ) { + + const planes = this.planes; + + for ( let i = 0; i < 6; i ++ ) { + + const plane = planes[ i ]; + + // corner at max distance + + _vector$6.x = plane.normal.x > 0 ? box.max.x : box.min.x; + _vector$6.y = plane.normal.y > 0 ? box.max.y : box.min.y; + _vector$6.z = plane.normal.z > 0 ? box.max.z : box.min.z; + + if ( plane.distanceToPoint( _vector$6 ) < 0 ) { + + return false; + + } + + } + + return true; + + } + + containsPoint( point ) { + + const planes = this.planes; + + for ( let i = 0; i < 6; i ++ ) { + + if ( planes[ i ].distanceToPoint( point ) < 0 ) { + + return false; + + } + + } + + return true; + + } + + clone() { + + return new this.constructor().copy( this ); + + } + +} + +function sortOpaque( a, b ) { + + return a.z - b.z; + +} + +function sortTransparent( a, b ) { + + return b.z - a.z; + +} + +class MultiDrawRenderList { + + constructor() { + + this.index = 0; + this.pool = []; + this.list = []; + + } + + push( drawRange, z, index ) { + + const pool = this.pool; + const list = this.list; + if ( this.index >= pool.length ) { + + pool.push( { + + start: - 1, + count: - 1, + z: - 1, + index: - 1, + + } ); + + } + + const item = pool[ this.index ]; + list.push( item ); + this.index ++; + + item.start = drawRange.start; + item.count = drawRange.count; + item.z = z; + item.index = index; + + } + + reset() { + + this.list.length = 0; + this.index = 0; + + } + +} + +const _matrix$1 = /*@__PURE__*/ new Matrix4(); +const _invMatrixWorld = /*@__PURE__*/ new Matrix4(); +const _identityMatrix = /*@__PURE__*/ new Matrix4(); +const _whiteColor = /*@__PURE__*/ new Color( 1, 1, 1 ); +const _projScreenMatrix$3 = /*@__PURE__*/ new Matrix4(); +const _frustum$1 = /*@__PURE__*/ new Frustum(); +const _box$1 = /*@__PURE__*/ new Box3(); +const _sphere$2 = /*@__PURE__*/ new Sphere(); +const _vector$5 = /*@__PURE__*/ new Vector3(); +const _forward = /*@__PURE__*/ new Vector3(); +const _temp = /*@__PURE__*/ new Vector3(); +const _renderList = /*@__PURE__*/ new MultiDrawRenderList(); +const _mesh = /*@__PURE__*/ new Mesh(); +const _batchIntersects = []; + +// @TODO: SkinnedMesh support? +// @TODO: geometry.groups support? +// @TODO: geometry.drawRange support? +// @TODO: geometry.morphAttributes support? +// @TODO: Support uniform parameter per geometry +// @TODO: Add an "optimize" function to pack geometry and remove data gaps + +// copies data from attribute "src" into "target" starting at "targetOffset" +function copyAttributeData( src, target, targetOffset = 0 ) { + + const itemSize = target.itemSize; + if ( src.isInterleavedBufferAttribute || src.array.constructor !== target.array.constructor ) { + + // use the component getters and setters if the array data cannot + // be copied directly + const vertexCount = src.count; + for ( let i = 0; i < vertexCount; i ++ ) { + + for ( let c = 0; c < itemSize; c ++ ) { + + target.setComponent( i + targetOffset, c, src.getComponent( i, c ) ); + + } + + } + + } else { + + // faster copy approach using typed array set function + target.array.set( src.array, targetOffset * itemSize ); + + } + + target.needsUpdate = true; + +} + +class BatchedMesh extends Mesh { + + get maxInstanceCount() { + + return this._maxInstanceCount; + + } + + constructor( maxInstanceCount, maxVertexCount, maxIndexCount = maxVertexCount * 2, material ) { + + super( new BufferGeometry(), material ); + + this.isBatchedMesh = true; + this.perObjectFrustumCulled = true; + this.sortObjects = true; + this.boundingBox = null; + this.boundingSphere = null; + this.customSort = null; + + // stores visible, active, and geometry id per object + this._drawInfo = []; + + // instance ids that have been set as inactive, and are available to be overwritten + this._availableInstanceIds = []; + + // geometry information + this._drawRanges = []; + this._reservedRanges = []; + this._bounds = []; + + this._maxInstanceCount = maxInstanceCount; + this._maxVertexCount = maxVertexCount; + this._maxIndexCount = maxIndexCount; + + this._geometryInitialized = false; + this._geometryCount = 0; + this._multiDrawCounts = new Int32Array( maxInstanceCount ); + this._multiDrawStarts = new Int32Array( maxInstanceCount ); + this._multiDrawCount = 0; + this._multiDrawInstances = null; + this._visibilityChanged = true; + + // Local matrix per geometry by using data texture + this._matricesTexture = null; + this._indirectTexture = null; + this._colorsTexture = null; + + this._initMatricesTexture(); + this._initIndirectTexture(); + + } + + _initMatricesTexture() { + + // layout (1 matrix = 4 pixels) + // RGBA RGBA RGBA RGBA (=> column1, column2, column3, column4) + // with 8x8 pixel texture max 16 matrices * 4 pixels = (8 * 8) + // 16x16 pixel texture max 64 matrices * 4 pixels = (16 * 16) + // 32x32 pixel texture max 256 matrices * 4 pixels = (32 * 32) + // 64x64 pixel texture max 1024 matrices * 4 pixels = (64 * 64) + + let size = Math.sqrt( this._maxInstanceCount * 4 ); // 4 pixels needed for 1 matrix + size = Math.ceil( size / 4 ) * 4; + size = Math.max( size, 4 ); + + const matricesArray = new Float32Array( size * size * 4 ); // 4 floats per RGBA pixel + const matricesTexture = new DataTexture( matricesArray, size, size, RGBAFormat, FloatType ); + + this._matricesTexture = matricesTexture; + + } + + _initIndirectTexture() { + + let size = Math.sqrt( this._maxInstanceCount ); + size = Math.ceil( size ); + + const indirectArray = new Uint32Array( size * size ); + const indirectTexture = new DataTexture( indirectArray, size, size, RedIntegerFormat, UnsignedIntType ); + + this._indirectTexture = indirectTexture; + + } + + _initColorsTexture() { + + let size = Math.sqrt( this._maxInstanceCount ); + size = Math.ceil( size ); + + // 4 floats per RGBA pixel initialized to white + const colorsArray = new Float32Array( size * size * 4 ).fill( 1 ); + const colorsTexture = new DataTexture( colorsArray, size, size, RGBAFormat, FloatType ); + colorsTexture.colorSpace = ColorManagement.workingColorSpace; + + this._colorsTexture = colorsTexture; + + } + + _initializeGeometry( reference ) { + + const geometry = this.geometry; + const maxVertexCount = this._maxVertexCount; + const maxIndexCount = this._maxIndexCount; + if ( this._geometryInitialized === false ) { + + for ( const attributeName in reference.attributes ) { + + const srcAttribute = reference.getAttribute( attributeName ); + const { array, itemSize, normalized } = srcAttribute; + + const dstArray = new array.constructor( maxVertexCount * itemSize ); + const dstAttribute = new BufferAttribute( dstArray, itemSize, normalized ); + + geometry.setAttribute( attributeName, dstAttribute ); + + } + + if ( reference.getIndex() !== null ) { + + // Reserve last u16 index for primitive restart. + const indexArray = maxVertexCount > 65535 + ? new Uint32Array( maxIndexCount ) + : new Uint16Array( maxIndexCount ); + + geometry.setIndex( new BufferAttribute( indexArray, 1 ) ); + + } + + this._geometryInitialized = true; + + } + + } + + // Make sure the geometry is compatible with the existing combined geometry attributes + _validateGeometry( geometry ) { + + // check to ensure the geometries are using consistent attributes and indices + const batchGeometry = this.geometry; + if ( Boolean( geometry.getIndex() ) !== Boolean( batchGeometry.getIndex() ) ) { + + throw new Error( 'BatchedMesh: All geometries must consistently have "index".' ); + + } + + for ( const attributeName in batchGeometry.attributes ) { + + if ( ! geometry.hasAttribute( attributeName ) ) { + + throw new Error( `BatchedMesh: Added geometry missing "${ attributeName }". All geometries must have consistent attributes.` ); + + } + + const srcAttribute = geometry.getAttribute( attributeName ); + const dstAttribute = batchGeometry.getAttribute( attributeName ); + if ( srcAttribute.itemSize !== dstAttribute.itemSize || srcAttribute.normalized !== dstAttribute.normalized ) { + + throw new Error( 'BatchedMesh: All attributes must have a consistent itemSize and normalized value.' ); + + } + + } + + } + + setCustomSort( func ) { + + this.customSort = func; + return this; + + } + + computeBoundingBox() { + + if ( this.boundingBox === null ) { + + this.boundingBox = new Box3(); + + } + + const boundingBox = this.boundingBox; + const drawInfo = this._drawInfo; + + boundingBox.makeEmpty(); + for ( let i = 0, l = drawInfo.length; i < l; i ++ ) { + + if ( drawInfo[ i ].active === false ) continue; + + const geometryId = drawInfo[ i ].geometryIndex; + this.getMatrixAt( i, _matrix$1 ); + this.getBoundingBoxAt( geometryId, _box$1 ).applyMatrix4( _matrix$1 ); + boundingBox.union( _box$1 ); + + } + + } + + computeBoundingSphere() { + + if ( this.boundingSphere === null ) { + + this.boundingSphere = new Sphere(); + + } + + const boundingSphere = this.boundingSphere; + const drawInfo = this._drawInfo; + + boundingSphere.makeEmpty(); + for ( let i = 0, l = drawInfo.length; i < l; i ++ ) { + + if ( drawInfo[ i ].active === false ) continue; + + const geometryId = drawInfo[ i ].geometryIndex; + this.getMatrixAt( i, _matrix$1 ); + this.getBoundingSphereAt( geometryId, _sphere$2 ).applyMatrix4( _matrix$1 ); + boundingSphere.union( _sphere$2 ); + + } + + } + + addInstance( geometryId ) { + + const atCapacity = this._drawInfo.length >= this.maxInstanceCount; + + // ensure we're not over geometry + if ( atCapacity && this._availableInstanceIds.length === 0 ) { + + throw new Error( 'BatchedMesh: Maximum item count reached.' ); + + } + + const instanceDrawInfo = { + visible: true, + active: true, + geometryIndex: geometryId, + }; + + let drawId = null; + + // Prioritize using previously freed instance ids + if ( this._availableInstanceIds.length > 0 ) { + + drawId = this._availableInstanceIds.pop(); + this._drawInfo[ drawId ] = instanceDrawInfo; + + } else { + + drawId = this._drawInfo.length; + this._drawInfo.push( instanceDrawInfo ); + + } + + const matricesTexture = this._matricesTexture; + const matricesArray = matricesTexture.image.data; + _identityMatrix.toArray( matricesArray, drawId * 16 ); + matricesTexture.needsUpdate = true; + + const colorsTexture = this._colorsTexture; + if ( colorsTexture ) { + + _whiteColor.toArray( colorsTexture.image.data, drawId * 4 ); + colorsTexture.needsUpdate = true; + + } + + return drawId; + + } + + addGeometry( geometry, vertexCount = - 1, indexCount = - 1 ) { + + this._initializeGeometry( geometry ); + + this._validateGeometry( geometry ); + + // ensure we're not over geometry + if ( this._drawInfo.length >= this._maxInstanceCount ) { + + throw new Error( 'BatchedMesh: Maximum item count reached.' ); + + } + + // get the necessary range fo the geometry + const reservedRange = { + vertexStart: - 1, + vertexCount: - 1, + indexStart: - 1, + indexCount: - 1, + }; + + let lastRange = null; + const reservedRanges = this._reservedRanges; + const drawRanges = this._drawRanges; + const bounds = this._bounds; + if ( this._geometryCount !== 0 ) { + + lastRange = reservedRanges[ reservedRanges.length - 1 ]; + + } + + if ( vertexCount === - 1 ) { + + reservedRange.vertexCount = geometry.getAttribute( 'position' ).count; + + } else { + + reservedRange.vertexCount = vertexCount; + + } + + if ( lastRange === null ) { + + reservedRange.vertexStart = 0; + + } else { + + reservedRange.vertexStart = lastRange.vertexStart + lastRange.vertexCount; + + } + + const index = geometry.getIndex(); + const hasIndex = index !== null; + if ( hasIndex ) { + + if ( indexCount === - 1 ) { + + reservedRange.indexCount = index.count; + + } else { + + reservedRange.indexCount = indexCount; + + } + + if ( lastRange === null ) { + + reservedRange.indexStart = 0; + + } else { + + reservedRange.indexStart = lastRange.indexStart + lastRange.indexCount; + + } + + } + + if ( + reservedRange.indexStart !== - 1 && + reservedRange.indexStart + reservedRange.indexCount > this._maxIndexCount || + reservedRange.vertexStart + reservedRange.vertexCount > this._maxVertexCount + ) { + + throw new Error( 'BatchedMesh: Reserved space request exceeds the maximum buffer size.' ); + + } + + // update id + const geometryId = this._geometryCount; + this._geometryCount ++; + + // add the reserved range and draw range objects + reservedRanges.push( reservedRange ); + drawRanges.push( { + start: hasIndex ? reservedRange.indexStart : reservedRange.vertexStart, + count: - 1 + } ); + bounds.push( { + boxInitialized: false, + box: new Box3(), + + sphereInitialized: false, + sphere: new Sphere() + } ); + + // update the geometry + this.setGeometryAt( geometryId, geometry ); + + return geometryId; + + } + + setGeometryAt( geometryId, geometry ) { + + if ( geometryId >= this._geometryCount ) { + + throw new Error( 'BatchedMesh: Maximum geometry count reached.' ); + + } + + this._validateGeometry( geometry ); + + const batchGeometry = this.geometry; + const hasIndex = batchGeometry.getIndex() !== null; + const dstIndex = batchGeometry.getIndex(); + const srcIndex = geometry.getIndex(); + const reservedRange = this._reservedRanges[ geometryId ]; + if ( + hasIndex && + srcIndex.count > reservedRange.indexCount || + geometry.attributes.position.count > reservedRange.vertexCount + ) { + + throw new Error( 'BatchedMesh: Reserved space not large enough for provided geometry.' ); + + } + + // copy geometry over + const vertexStart = reservedRange.vertexStart; + const vertexCount = reservedRange.vertexCount; + for ( const attributeName in batchGeometry.attributes ) { + + // copy attribute data + const srcAttribute = geometry.getAttribute( attributeName ); + const dstAttribute = batchGeometry.getAttribute( attributeName ); + copyAttributeData( srcAttribute, dstAttribute, vertexStart ); + + // fill the rest in with zeroes + const itemSize = srcAttribute.itemSize; + for ( let i = srcAttribute.count, l = vertexCount; i < l; i ++ ) { + + const index = vertexStart + i; + for ( let c = 0; c < itemSize; c ++ ) { + + dstAttribute.setComponent( index, c, 0 ); + + } + + } + + dstAttribute.needsUpdate = true; + dstAttribute.addUpdateRange( vertexStart * itemSize, vertexCount * itemSize ); + + } + + // copy index + if ( hasIndex ) { + + const indexStart = reservedRange.indexStart; + + // copy index data over + for ( let i = 0; i < srcIndex.count; i ++ ) { + + dstIndex.setX( indexStart + i, vertexStart + srcIndex.getX( i ) ); + + } + + // fill the rest in with zeroes + for ( let i = srcIndex.count, l = reservedRange.indexCount; i < l; i ++ ) { + + dstIndex.setX( indexStart + i, vertexStart ); + + } + + dstIndex.needsUpdate = true; + dstIndex.addUpdateRange( indexStart, reservedRange.indexCount ); + + } + + // store the bounding boxes + const bound = this._bounds[ geometryId ]; + if ( geometry.boundingBox !== null ) { + + bound.box.copy( geometry.boundingBox ); + bound.boxInitialized = true; + + } else { + + bound.boxInitialized = false; + + } + + if ( geometry.boundingSphere !== null ) { + + bound.sphere.copy( geometry.boundingSphere ); + bound.sphereInitialized = true; + + } else { + + bound.sphereInitialized = false; + + } + + // set drawRange count + const drawRange = this._drawRanges[ geometryId ]; + const posAttr = geometry.getAttribute( 'position' ); + drawRange.count = hasIndex ? srcIndex.count : posAttr.count; + this._visibilityChanged = true; + + return geometryId; + + } + + /* + deleteGeometry( geometryId ) { + + // TODO: delete geometry and associated instances + + } + */ + + deleteInstance( instanceId ) { + + const drawInfo = this._drawInfo; + if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { + + return this; + + } + + drawInfo[ instanceId ].active = false; + this._availableInstanceIds.push( instanceId ); + this._visibilityChanged = true; + + return this; + + } + + // get bounding box and compute it if it doesn't exist + getBoundingBoxAt( geometryId, target ) { + + if ( geometryId >= this._geometryCount ) { + + return null; + + } + + // compute bounding box + const bound = this._bounds[ geometryId ]; + const box = bound.box; + const geometry = this.geometry; + if ( bound.boxInitialized === false ) { + + box.makeEmpty(); + + const index = geometry.index; + const position = geometry.attributes.position; + const drawRange = this._drawRanges[ geometryId ]; + for ( let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i ++ ) { + + let iv = i; + if ( index ) { + + iv = index.getX( iv ); + + } + + box.expandByPoint( _vector$5.fromBufferAttribute( position, iv ) ); + + } + + bound.boxInitialized = true; + + } + + target.copy( box ); + return target; + + } + + // get bounding sphere and compute it if it doesn't exist + getBoundingSphereAt( geometryId, target ) { + + if ( geometryId >= this._geometryCount ) { + + return null; + + } + + // compute bounding sphere + const bound = this._bounds[ geometryId ]; + const sphere = bound.sphere; + const geometry = this.geometry; + if ( bound.sphereInitialized === false ) { + + sphere.makeEmpty(); + + this.getBoundingBoxAt( geometryId, _box$1 ); + _box$1.getCenter( sphere.center ); + + const index = geometry.index; + const position = geometry.attributes.position; + const drawRange = this._drawRanges[ geometryId ]; + + let maxRadiusSq = 0; + for ( let i = drawRange.start, l = drawRange.start + drawRange.count; i < l; i ++ ) { + + let iv = i; + if ( index ) { + + iv = index.getX( iv ); + + } + + _vector$5.fromBufferAttribute( position, iv ); + maxRadiusSq = Math.max( maxRadiusSq, sphere.center.distanceToSquared( _vector$5 ) ); + + } + + sphere.radius = Math.sqrt( maxRadiusSq ); + bound.sphereInitialized = true; + + } + + target.copy( sphere ); + return target; + + } + + setMatrixAt( instanceId, matrix ) { + + // @TODO: Map geometryId to index of the arrays because + // optimize() can make geometryId mismatch the index + + const drawInfo = this._drawInfo; + const matricesTexture = this._matricesTexture; + const matricesArray = this._matricesTexture.image.data; + if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { + + return this; + + } + + matrix.toArray( matricesArray, instanceId * 16 ); + matricesTexture.needsUpdate = true; + + return this; + + } + + getMatrixAt( instanceId, matrix ) { + + const drawInfo = this._drawInfo; + const matricesArray = this._matricesTexture.image.data; + if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { + + return null; + + } + + return matrix.fromArray( matricesArray, instanceId * 16 ); + + } + + setColorAt( instanceId, color ) { + + if ( this._colorsTexture === null ) { + + this._initColorsTexture(); + + } + + // @TODO: Map id to index of the arrays because + // optimize() can make id mismatch the index + + const colorsTexture = this._colorsTexture; + const colorsArray = this._colorsTexture.image.data; + const drawInfo = this._drawInfo; + if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { + + return this; + + } + + color.toArray( colorsArray, instanceId * 4 ); + colorsTexture.needsUpdate = true; + + return this; + + } + + getColorAt( instanceId, color ) { + + const colorsArray = this._colorsTexture.image.data; + const drawInfo = this._drawInfo; + if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { + + return null; + + } + + return color.fromArray( colorsArray, instanceId * 4 ); + + } + + setVisibleAt( instanceId, value ) { + + // if the geometry is out of range, not active, or visibility state + // does not change then return early + const drawInfo = this._drawInfo; + if ( + instanceId >= drawInfo.length || + drawInfo[ instanceId ].active === false || + drawInfo[ instanceId ].visible === value + ) { + + return this; + + } + + drawInfo[ instanceId ].visible = value; + this._visibilityChanged = true; + + return this; + + } + + getVisibleAt( instanceId ) { + + // return early if the geometry is out of range or not active + const drawInfo = this._drawInfo; + if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { + + return false; + + } + + return drawInfo[ instanceId ].visible; + + } + + setGeometryIdAt( instanceId, geometryId ) { + + // return early if the geometry is out of range or not active + const drawInfo = this._drawInfo; + if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { + + return null; + + } + + // check if the provided geometryId is within the valid range + if ( geometryId < 0 || geometryId >= this._geometryCount ) { + + return null; + + } + + drawInfo[ instanceId ].geometryIndex = geometryId; + + return this; + + } + + getGeometryIdAt( instanceId ) { + + const drawInfo = this._drawInfo; + if ( instanceId >= drawInfo.length || drawInfo[ instanceId ].active === false ) { + + return - 1; + + } + + return drawInfo[ instanceId ].geometryIndex; + + } + + getGeometryRangeAt( geometryId, target = {} ) { + + if ( geometryId < 0 || geometryId >= this._geometryCount ) { + + return null; + + } + + const drawRange = this._drawRanges[ geometryId ]; + + target.start = drawRange.start; + target.count = drawRange.count; + + return target; + + } + + raycast( raycaster, intersects ) { + + const drawInfo = this._drawInfo; + const drawRanges = this._drawRanges; + const matrixWorld = this.matrixWorld; + const batchGeometry = this.geometry; + + // iterate over each geometry + _mesh.material = this.material; + _mesh.geometry.index = batchGeometry.index; + _mesh.geometry.attributes = batchGeometry.attributes; + if ( _mesh.geometry.boundingBox === null ) { + + _mesh.geometry.boundingBox = new Box3(); + + } + + if ( _mesh.geometry.boundingSphere === null ) { + + _mesh.geometry.boundingSphere = new Sphere(); + + } + + for ( let i = 0, l = drawInfo.length; i < l; i ++ ) { + + if ( ! drawInfo[ i ].visible || ! drawInfo[ i ].active ) { + + continue; + + } + + const geometryId = drawInfo[ i ].geometryIndex; + const drawRange = drawRanges[ geometryId ]; + _mesh.geometry.setDrawRange( drawRange.start, drawRange.count ); + + // ge the intersects + this.getMatrixAt( i, _mesh.matrixWorld ).premultiply( matrixWorld ); + this.getBoundingBoxAt( geometryId, _mesh.geometry.boundingBox ); + this.getBoundingSphereAt( geometryId, _mesh.geometry.boundingSphere ); + _mesh.raycast( raycaster, _batchIntersects ); + + // add batch id to the intersects + for ( let j = 0, l = _batchIntersects.length; j < l; j ++ ) { + + const intersect = _batchIntersects[ j ]; + intersect.object = this; + intersect.batchId = i; + intersects.push( intersect ); + + } + + _batchIntersects.length = 0; + + } + + _mesh.material = null; + _mesh.geometry.index = null; + _mesh.geometry.attributes = {}; + _mesh.geometry.setDrawRange( 0, Infinity ); + + } + + copy( source ) { + + super.copy( source ); + + this.geometry = source.geometry.clone(); + this.perObjectFrustumCulled = source.perObjectFrustumCulled; + this.sortObjects = source.sortObjects; + this.boundingBox = source.boundingBox !== null ? source.boundingBox.clone() : null; + this.boundingSphere = source.boundingSphere !== null ? source.boundingSphere.clone() : null; + + this._drawRanges = source._drawRanges.map( range => ( { ...range } ) ); + this._reservedRanges = source._reservedRanges.map( range => ( { ...range } ) ); + + this._drawInfo = source._drawInfo.map( inf => ( { ...inf } ) ); + this._bounds = source._bounds.map( bound => ( { + boxInitialized: bound.boxInitialized, + box: bound.box.clone(), + + sphereInitialized: bound.sphereInitialized, + sphere: bound.sphere.clone() + } ) ); + + this._maxInstanceCount = source._maxInstanceCount; + this._maxVertexCount = source._maxVertexCount; + this._maxIndexCount = source._maxIndexCount; + + this._geometryInitialized = source._geometryInitialized; + this._geometryCount = source._geometryCount; + this._multiDrawCounts = source._multiDrawCounts.slice(); + this._multiDrawStarts = source._multiDrawStarts.slice(); + + this._matricesTexture = source._matricesTexture.clone(); + this._matricesTexture.image.data = this._matricesTexture.image.data.slice(); + + if ( this._colorsTexture !== null ) { + + this._colorsTexture = source._colorsTexture.clone(); + this._colorsTexture.image.data = this._colorsTexture.image.data.slice(); + + } + + return this; + + } + + dispose() { + + // Assuming the geometry is not shared with other meshes + this.geometry.dispose(); + + this._matricesTexture.dispose(); + this._matricesTexture = null; + + this._indirectTexture.dispose(); + this._indirectTexture = null; + + if ( this._colorsTexture !== null ) { + + this._colorsTexture.dispose(); + this._colorsTexture = null; + + } + + return this; + + } + + onBeforeRender( renderer, scene, camera, geometry, material/*, _group*/ ) { + + // if visibility has not changed and frustum culling and object sorting is not required + // then skip iterating over all items + if ( ! this._visibilityChanged && ! this.perObjectFrustumCulled && ! this.sortObjects ) { + + return; + + } + + // the indexed version of the multi draw function requires specifying the start + // offset in bytes. + const index = geometry.getIndex(); + const bytesPerElement = index === null ? 1 : index.array.BYTES_PER_ELEMENT; + + const drawInfo = this._drawInfo; + const multiDrawStarts = this._multiDrawStarts; + const multiDrawCounts = this._multiDrawCounts; + const drawRanges = this._drawRanges; + const perObjectFrustumCulled = this.perObjectFrustumCulled; + const indirectTexture = this._indirectTexture; + const indirectArray = indirectTexture.image.data; + + // prepare the frustum in the local frame + if ( perObjectFrustumCulled ) { + + _projScreenMatrix$3 + .multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ) + .multiply( this.matrixWorld ); + _frustum$1.setFromProjectionMatrix( + _projScreenMatrix$3, + renderer.coordinateSystem + ); + + } + + let count = 0; + if ( this.sortObjects ) { + + // get the camera position in the local frame + _invMatrixWorld.copy( this.matrixWorld ).invert(); + _vector$5.setFromMatrixPosition( camera.matrixWorld ).applyMatrix4( _invMatrixWorld ); + _forward.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ).transformDirection( _invMatrixWorld ); + + for ( let i = 0, l = drawInfo.length; i < l; i ++ ) { + + if ( drawInfo[ i ].visible && drawInfo[ i ].active ) { + + const geometryId = drawInfo[ i ].geometryIndex; + + // get the bounds in world space + this.getMatrixAt( i, _matrix$1 ); + this.getBoundingSphereAt( geometryId, _sphere$2 ).applyMatrix4( _matrix$1 ); + + // determine whether the batched geometry is within the frustum + let culled = false; + if ( perObjectFrustumCulled ) { + + culled = ! _frustum$1.intersectsSphere( _sphere$2 ); + + } + + if ( ! culled ) { + + // get the distance from camera used for sorting + const z = _temp.subVectors( _sphere$2.center, _vector$5 ).dot( _forward ); + _renderList.push( drawRanges[ geometryId ], z, i ); + + } + + } + + } + + // Sort the draw ranges and prep for rendering + const list = _renderList.list; + const customSort = this.customSort; + if ( customSort === null ) { + + list.sort( material.transparent ? sortTransparent : sortOpaque ); + + } else { + + customSort.call( this, list, camera ); + + } + + for ( let i = 0, l = list.length; i < l; i ++ ) { + + const item = list[ i ]; + multiDrawStarts[ count ] = item.start * bytesPerElement; + multiDrawCounts[ count ] = item.count; + indirectArray[ count ] = item.index; + count ++; + + } + + _renderList.reset(); + + } else { + + for ( let i = 0, l = drawInfo.length; i < l; i ++ ) { + + if ( drawInfo[ i ].visible && drawInfo[ i ].active ) { + + const geometryId = drawInfo[ i ].geometryIndex; + + // determine whether the batched geometry is within the frustum + let culled = false; + if ( perObjectFrustumCulled ) { + + // get the bounds in world space + this.getMatrixAt( i, _matrix$1 ); + this.getBoundingSphereAt( geometryId, _sphere$2 ).applyMatrix4( _matrix$1 ); + culled = ! _frustum$1.intersectsSphere( _sphere$2 ); + + } + + if ( ! culled ) { + + const range = drawRanges[ geometryId ]; + multiDrawStarts[ count ] = range.start * bytesPerElement; + multiDrawCounts[ count ] = range.count; + indirectArray[ count ] = i; + count ++; + + } + + } + + } + + } + + indirectTexture.needsUpdate = true; + this._multiDrawCount = count; + this._visibilityChanged = false; + + } + + onBeforeShadow( renderer, object, camera, shadowCamera, geometry, depthMaterial/* , group */ ) { + + this.onBeforeRender( renderer, null, shadowCamera, geometry, depthMaterial ); + + } + +} + +class LineBasicMaterial extends Material { + + constructor( parameters ) { + + super(); + + this.isLineBasicMaterial = true; + + this.type = 'LineBasicMaterial'; + + this.color = new Color( 0xffffff ); + + this.map = null; + + this.linewidth = 1; + this.linecap = 'round'; + this.linejoin = 'round'; + + this.fog = true; + + this.setValues( parameters ); + + } + + + copy( source ) { + + super.copy( source ); + + this.color.copy( source.color ); + + this.map = source.map; + + this.linewidth = source.linewidth; + this.linecap = source.linecap; + this.linejoin = source.linejoin; + + this.fog = source.fog; + + return this; + + } + +} + +const _vStart = /*@__PURE__*/ new Vector3(); +const _vEnd = /*@__PURE__*/ new Vector3(); + +const _inverseMatrix$1 = /*@__PURE__*/ new Matrix4(); +const _ray$1 = /*@__PURE__*/ new Ray(); +const _sphere$1 = /*@__PURE__*/ new Sphere(); + +const _intersectPointOnRay = /*@__PURE__*/ new Vector3(); +const _intersectPointOnSegment = /*@__PURE__*/ new Vector3(); + +class Line extends Object3D { + + constructor( geometry = new BufferGeometry(), material = new LineBasicMaterial() ) { + + super(); + + this.isLine = true; + + this.type = 'Line'; + + this.geometry = geometry; + this.material = material; + + this.updateMorphTargets(); + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; + this.geometry = source.geometry; + + return this; + + } + + computeLineDistances() { + + const geometry = this.geometry; + + // we assume non-indexed geometry + + if ( geometry.index === null ) { + + const positionAttribute = geometry.attributes.position; + const lineDistances = [ 0 ]; + + for ( let i = 1, l = positionAttribute.count; i < l; i ++ ) { + + _vStart.fromBufferAttribute( positionAttribute, i - 1 ); + _vEnd.fromBufferAttribute( positionAttribute, i ); + + lineDistances[ i ] = lineDistances[ i - 1 ]; + lineDistances[ i ] += _vStart.distanceTo( _vEnd ); + + } + + geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); + + } else { + + console.warn( 'THREE.Line.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); + + } + + return this; + + } + + raycast( raycaster, intersects ) { + + const geometry = this.geometry; + const matrixWorld = this.matrixWorld; + const threshold = raycaster.params.Line.threshold; + const drawRange = geometry.drawRange; + + // Checking boundingSphere distance to ray + + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + + _sphere$1.copy( geometry.boundingSphere ); + _sphere$1.applyMatrix4( matrixWorld ); + _sphere$1.radius += threshold; + + if ( raycaster.ray.intersectsSphere( _sphere$1 ) === false ) return; + + // + + _inverseMatrix$1.copy( matrixWorld ).invert(); + _ray$1.copy( raycaster.ray ).applyMatrix4( _inverseMatrix$1 ); + + const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); + const localThresholdSq = localThreshold * localThreshold; + + const step = this.isLineSegments ? 2 : 1; + + const index = geometry.index; + const attributes = geometry.attributes; + const positionAttribute = attributes.position; + + if ( index !== null ) { + + const start = Math.max( 0, drawRange.start ); + const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); + + for ( let i = start, l = end - 1; i < l; i += step ) { + + const a = index.getX( i ); + const b = index.getX( i + 1 ); + + const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, a, b ); + + if ( intersect ) { + + intersects.push( intersect ); + + } + + } + + if ( this.isLineLoop ) { + + const a = index.getX( end - 1 ); + const b = index.getX( start ); + + const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, a, b ); + + if ( intersect ) { + + intersects.push( intersect ); + + } + + } + + } else { + + const start = Math.max( 0, drawRange.start ); + const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) ); + + for ( let i = start, l = end - 1; i < l; i += step ) { + + const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, i, i + 1 ); + + if ( intersect ) { + + intersects.push( intersect ); + + } + + } + + if ( this.isLineLoop ) { + + const intersect = checkIntersection( this, raycaster, _ray$1, localThresholdSq, end - 1, start ); + + if ( intersect ) { + + intersects.push( intersect ); + + } + + } + + } + + } + + updateMorphTargets() { + + const geometry = this.geometry; + + const morphAttributes = geometry.morphAttributes; + const keys = Object.keys( morphAttributes ); + + if ( keys.length > 0 ) { + + const morphAttribute = morphAttributes[ keys[ 0 ] ]; + + if ( morphAttribute !== undefined ) { + + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; + + for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { + + const name = morphAttribute[ m ].name || String( m ); + + this.morphTargetInfluences.push( 0 ); + this.morphTargetDictionary[ name ] = m; + + } + + } + + } + + } + +} + +function checkIntersection( object, raycaster, ray, thresholdSq, a, b ) { + + const positionAttribute = object.geometry.attributes.position; + + _vStart.fromBufferAttribute( positionAttribute, a ); + _vEnd.fromBufferAttribute( positionAttribute, b ); + + const distSq = ray.distanceSqToSegment( _vStart, _vEnd, _intersectPointOnRay, _intersectPointOnSegment ); + + if ( distSq > thresholdSq ) return; + + _intersectPointOnRay.applyMatrix4( object.matrixWorld ); // Move back to world space for distance calculation + + const distance = raycaster.ray.origin.distanceTo( _intersectPointOnRay ); + + if ( distance < raycaster.near || distance > raycaster.far ) return; + + return { + + distance: distance, + // What do we want? intersection point on the ray or on the segment?? + // point: raycaster.ray.at( distance ), + point: _intersectPointOnSegment.clone().applyMatrix4( object.matrixWorld ), + index: a, + face: null, + faceIndex: null, + barycoord: null, + object: object + + }; + +} + +const _start = /*@__PURE__*/ new Vector3(); +const _end = /*@__PURE__*/ new Vector3(); + +class LineSegments extends Line { + + constructor( geometry, material ) { + + super( geometry, material ); + + this.isLineSegments = true; + + this.type = 'LineSegments'; + + } + + computeLineDistances() { + + const geometry = this.geometry; + + // we assume non-indexed geometry + + if ( geometry.index === null ) { + + const positionAttribute = geometry.attributes.position; + const lineDistances = []; + + for ( let i = 0, l = positionAttribute.count; i < l; i += 2 ) { + + _start.fromBufferAttribute( positionAttribute, i ); + _end.fromBufferAttribute( positionAttribute, i + 1 ); + + lineDistances[ i ] = ( i === 0 ) ? 0 : lineDistances[ i - 1 ]; + lineDistances[ i + 1 ] = lineDistances[ i ] + _start.distanceTo( _end ); + + } + + geometry.setAttribute( 'lineDistance', new Float32BufferAttribute( lineDistances, 1 ) ); + + } else { + + console.warn( 'THREE.LineSegments.computeLineDistances(): Computation only possible with non-indexed BufferGeometry.' ); + + } + + return this; + + } + +} + +class LineLoop extends Line { + + constructor( geometry, material ) { + + super( geometry, material ); + + this.isLineLoop = true; + + this.type = 'LineLoop'; + + } + +} + +class PointsMaterial extends Material { + + constructor( parameters ) { + + super(); + + this.isPointsMaterial = true; + + this.type = 'PointsMaterial'; + + this.color = new Color( 0xffffff ); + + this.map = null; + + this.alphaMap = null; + + this.size = 1; + this.sizeAttenuation = true; + + this.fog = true; + + this.setValues( parameters ); + + } + + copy( source ) { + + super.copy( source ); + + this.color.copy( source.color ); + + this.map = source.map; + + this.alphaMap = source.alphaMap; + + this.size = source.size; + this.sizeAttenuation = source.sizeAttenuation; + + this.fog = source.fog; + + return this; + + } + +} + +const _inverseMatrix = /*@__PURE__*/ new Matrix4(); +const _ray = /*@__PURE__*/ new Ray(); +const _sphere = /*@__PURE__*/ new Sphere(); +const _position$2 = /*@__PURE__*/ new Vector3(); + +class Points extends Object3D { + + constructor( geometry = new BufferGeometry(), material = new PointsMaterial() ) { + + super(); + + this.isPoints = true; + + this.type = 'Points'; + + this.geometry = geometry; + this.material = material; + + this.updateMorphTargets(); + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + this.material = Array.isArray( source.material ) ? source.material.slice() : source.material; + this.geometry = source.geometry; + + return this; + + } + + raycast( raycaster, intersects ) { + + const geometry = this.geometry; + const matrixWorld = this.matrixWorld; + const threshold = raycaster.params.Points.threshold; + const drawRange = geometry.drawRange; + + // Checking boundingSphere distance to ray + + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + + _sphere.copy( geometry.boundingSphere ); + _sphere.applyMatrix4( matrixWorld ); + _sphere.radius += threshold; + + if ( raycaster.ray.intersectsSphere( _sphere ) === false ) return; + + // + + _inverseMatrix.copy( matrixWorld ).invert(); + _ray.copy( raycaster.ray ).applyMatrix4( _inverseMatrix ); + + const localThreshold = threshold / ( ( this.scale.x + this.scale.y + this.scale.z ) / 3 ); + const localThresholdSq = localThreshold * localThreshold; + + const index = geometry.index; + const attributes = geometry.attributes; + const positionAttribute = attributes.position; + + if ( index !== null ) { + + const start = Math.max( 0, drawRange.start ); + const end = Math.min( index.count, ( drawRange.start + drawRange.count ) ); + + for ( let i = start, il = end; i < il; i ++ ) { + + const a = index.getX( i ); + + _position$2.fromBufferAttribute( positionAttribute, a ); + + testPoint( _position$2, a, localThresholdSq, matrixWorld, raycaster, intersects, this ); + + } + + } else { + + const start = Math.max( 0, drawRange.start ); + const end = Math.min( positionAttribute.count, ( drawRange.start + drawRange.count ) ); + + for ( let i = start, l = end; i < l; i ++ ) { + + _position$2.fromBufferAttribute( positionAttribute, i ); + + testPoint( _position$2, i, localThresholdSq, matrixWorld, raycaster, intersects, this ); + + } + + } + + } + + updateMorphTargets() { + + const geometry = this.geometry; + + const morphAttributes = geometry.morphAttributes; + const keys = Object.keys( morphAttributes ); + + if ( keys.length > 0 ) { + + const morphAttribute = morphAttributes[ keys[ 0 ] ]; + + if ( morphAttribute !== undefined ) { + + this.morphTargetInfluences = []; + this.morphTargetDictionary = {}; + + for ( let m = 0, ml = morphAttribute.length; m < ml; m ++ ) { + + const name = morphAttribute[ m ].name || String( m ); + + this.morphTargetInfluences.push( 0 ); + this.morphTargetDictionary[ name ] = m; + + } + + } + + } + + } + +} + +function testPoint( point, index, localThresholdSq, matrixWorld, raycaster, intersects, object ) { + + const rayPointDistanceSq = _ray.distanceSqToPoint( point ); + + if ( rayPointDistanceSq < localThresholdSq ) { + + const intersectPoint = new Vector3(); + + _ray.closestPointToPoint( point, intersectPoint ); + intersectPoint.applyMatrix4( matrixWorld ); + + const distance = raycaster.ray.origin.distanceTo( intersectPoint ); + + if ( distance < raycaster.near || distance > raycaster.far ) return; + + intersects.push( { + + distance: distance, + distanceToRay: Math.sqrt( rayPointDistanceSq ), + point: intersectPoint, + index: index, + face: null, + faceIndex: null, + barycoord: null, + object: object + + } ); + + } + +} + +class Group extends Object3D { + + constructor() { + + super(); + + this.isGroup = true; + + this.type = 'Group'; + + } + +} + +class VideoTexture extends Texture { + + constructor( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { + + super( video, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); + + this.isVideoTexture = true; + + this.minFilter = minFilter !== undefined ? minFilter : LinearFilter; + this.magFilter = magFilter !== undefined ? magFilter : LinearFilter; + + this.generateMipmaps = false; + + const scope = this; + + function updateVideo() { + + scope.needsUpdate = true; + video.requestVideoFrameCallback( updateVideo ); + + } + + if ( 'requestVideoFrameCallback' in video ) { + + video.requestVideoFrameCallback( updateVideo ); + + } + + } + + clone() { + + return new this.constructor( this.image ).copy( this ); + + } + + update() { + + const video = this.image; + const hasVideoFrameCallback = 'requestVideoFrameCallback' in video; + + if ( hasVideoFrameCallback === false && video.readyState >= video.HAVE_CURRENT_DATA ) { + + this.needsUpdate = true; + + } + + } + +} + +class FramebufferTexture extends Texture { + + constructor( width, height ) { + + super( { width, height } ); + + this.isFramebufferTexture = true; + + this.magFilter = NearestFilter; + this.minFilter = NearestFilter; + + this.generateMipmaps = false; + + this.needsUpdate = true; + + } + +} + +class CompressedTexture extends Texture { + + constructor( mipmaps, width, height, format, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, colorSpace ) { + + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy, colorSpace ); + + this.isCompressedTexture = true; + + this.image = { width: width, height: height }; + this.mipmaps = mipmaps; + + // no flipping for cube textures + // (also flipping doesn't work for compressed textures ) + + this.flipY = false; + + // can't generate mipmaps for compressed textures + // mips must be embedded in DDS files + + this.generateMipmaps = false; + + } + +} + +class CompressedArrayTexture extends CompressedTexture { + + constructor( mipmaps, width, height, depth, format, type ) { + + super( mipmaps, width, height, format, type ); + + this.isCompressedArrayTexture = true; + this.image.depth = depth; + this.wrapR = ClampToEdgeWrapping; + + this.layerUpdates = new Set(); + + } + + addLayerUpdate( layerIndex ) { + + this.layerUpdates.add( layerIndex ); + + } + + clearLayerUpdates() { + + this.layerUpdates.clear(); + + } + +} + +class CompressedCubeTexture extends CompressedTexture { + + constructor( images, format, type ) { + + super( undefined, images[ 0 ].width, images[ 0 ].height, format, type, CubeReflectionMapping ); + + this.isCompressedCubeTexture = true; + this.isCubeTexture = true; + + this.image = images; + + } + +} + +class CanvasTexture extends Texture { + + constructor( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ) { + + super( canvas, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); + + this.isCanvasTexture = true; + + this.needsUpdate = true; + + } + +} + +class DepthTexture extends Texture { + + constructor( width, height, type, mapping, wrapS, wrapT, magFilter, minFilter, anisotropy, format = DepthFormat ) { + + if ( format !== DepthFormat && format !== DepthStencilFormat ) { + + throw new Error( 'DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat' ); + + } + + if ( type === undefined && format === DepthFormat ) type = UnsignedIntType; + if ( type === undefined && format === DepthStencilFormat ) type = UnsignedInt248Type; + + super( null, mapping, wrapS, wrapT, magFilter, minFilter, format, type, anisotropy ); + + this.isDepthTexture = true; + + this.image = { width: width, height: height }; + + this.magFilter = magFilter !== undefined ? magFilter : NearestFilter; + this.minFilter = minFilter !== undefined ? minFilter : NearestFilter; + + this.flipY = false; + this.generateMipmaps = false; + + this.compareFunction = null; + + } + + + copy( source ) { + + super.copy( source ); + + this.compareFunction = source.compareFunction; + + return this; + + } + + toJSON( meta ) { + + const data = super.toJSON( meta ); + + if ( this.compareFunction !== null ) data.compareFunction = this.compareFunction; + + return data; + + } + +} + +/** + * Extensible curve object. + * + * Some common of curve methods: + * .getPoint( t, optionalTarget ), .getTangent( t, optionalTarget ) + * .getPointAt( u, optionalTarget ), .getTangentAt( u, optionalTarget ) + * .getPoints(), .getSpacedPoints() + * .getLength() + * .updateArcLengths() + * + * This following curves inherit from THREE.Curve: + * + * -- 2D curves -- + * THREE.ArcCurve + * THREE.CubicBezierCurve + * THREE.EllipseCurve + * THREE.LineCurve + * THREE.QuadraticBezierCurve + * THREE.SplineCurve + * + * -- 3D curves -- + * THREE.CatmullRomCurve3 + * THREE.CubicBezierCurve3 + * THREE.LineCurve3 + * THREE.QuadraticBezierCurve3 + * + * A series of curves can be represented as a THREE.CurvePath. + * + **/ + +class Curve { + + constructor() { + + this.type = 'Curve'; + + this.arcLengthDivisions = 200; + + } + + // Virtual base class method to overwrite and implement in subclasses + // - t [0 .. 1] + + getPoint( /* t, optionalTarget */ ) { + + console.warn( 'THREE.Curve: .getPoint() not implemented.' ); + return null; + + } + + // Get point at relative position in curve according to arc length + // - u [0 .. 1] + + getPointAt( u, optionalTarget ) { + + const t = this.getUtoTmapping( u ); + return this.getPoint( t, optionalTarget ); + + } + + // Get sequence of points using getPoint( t ) + + getPoints( divisions = 5 ) { + + const points = []; + + for ( let d = 0; d <= divisions; d ++ ) { + + points.push( this.getPoint( d / divisions ) ); + + } + + return points; + + } + + // Get sequence of points using getPointAt( u ) + + getSpacedPoints( divisions = 5 ) { + + const points = []; + + for ( let d = 0; d <= divisions; d ++ ) { + + points.push( this.getPointAt( d / divisions ) ); + + } + + return points; + + } + + // Get total curve arc length + + getLength() { + + const lengths = this.getLengths(); + return lengths[ lengths.length - 1 ]; + + } + + // Get list of cumulative segment lengths + + getLengths( divisions = this.arcLengthDivisions ) { + + if ( this.cacheArcLengths && + ( this.cacheArcLengths.length === divisions + 1 ) && + ! this.needsUpdate ) { + + return this.cacheArcLengths; + + } + + this.needsUpdate = false; + + const cache = []; + let current, last = this.getPoint( 0 ); + let sum = 0; + + cache.push( 0 ); + + for ( let p = 1; p <= divisions; p ++ ) { + + current = this.getPoint( p / divisions ); + sum += current.distanceTo( last ); + cache.push( sum ); + last = current; + + } + + this.cacheArcLengths = cache; + + return cache; // { sums: cache, sum: sum }; Sum is in the last element. + + } + + updateArcLengths() { + + this.needsUpdate = true; + this.getLengths(); + + } + + // Given u ( 0 .. 1 ), get a t to find p. This gives you points which are equidistant + + getUtoTmapping( u, distance ) { + + const arcLengths = this.getLengths(); + + let i = 0; + const il = arcLengths.length; + + let targetArcLength; // The targeted u distance value to get + + if ( distance ) { + + targetArcLength = distance; + + } else { + + targetArcLength = u * arcLengths[ il - 1 ]; + + } + + // binary search for the index with largest value smaller than target u distance + + let low = 0, high = il - 1, comparison; + + while ( low <= high ) { + + i = Math.floor( low + ( high - low ) / 2 ); // less likely to overflow, though probably not issue here, JS doesn't really have integers, all numbers are floats + + comparison = arcLengths[ i ] - targetArcLength; + + if ( comparison < 0 ) { + + low = i + 1; + + } else if ( comparison > 0 ) { + + high = i - 1; + + } else { + + high = i; + break; + + // DONE + + } + + } + + i = high; + + if ( arcLengths[ i ] === targetArcLength ) { + + return i / ( il - 1 ); + + } + + // we could get finer grain at lengths, or use simple interpolation between two points + + const lengthBefore = arcLengths[ i ]; + const lengthAfter = arcLengths[ i + 1 ]; + + const segmentLength = lengthAfter - lengthBefore; + + // determine where we are between the 'before' and 'after' points + + const segmentFraction = ( targetArcLength - lengthBefore ) / segmentLength; + + // add that fractional amount to t + + const t = ( i + segmentFraction ) / ( il - 1 ); + + return t; + + } + + // Returns a unit vector tangent at t + // In case any sub curve does not implement its tangent derivation, + // 2 points a small delta apart will be used to find its gradient + // which seems to give a reasonable approximation + + getTangent( t, optionalTarget ) { + + const delta = 0.0001; + let t1 = t - delta; + let t2 = t + delta; + + // Capping in case of danger + + if ( t1 < 0 ) t1 = 0; + if ( t2 > 1 ) t2 = 1; + + const pt1 = this.getPoint( t1 ); + const pt2 = this.getPoint( t2 ); + + const tangent = optionalTarget || ( ( pt1.isVector2 ) ? new Vector2() : new Vector3() ); + + tangent.copy( pt2 ).sub( pt1 ).normalize(); + + return tangent; + + } + + getTangentAt( u, optionalTarget ) { + + const t = this.getUtoTmapping( u ); + return this.getTangent( t, optionalTarget ); + + } + + computeFrenetFrames( segments, closed ) { + + // see http://www.cs.indiana.edu/pub/techreports/TR425.pdf + + const normal = new Vector3(); + + const tangents = []; + const normals = []; + const binormals = []; + + const vec = new Vector3(); + const mat = new Matrix4(); + + // compute the tangent vectors for each segment on the curve + + for ( let i = 0; i <= segments; i ++ ) { + + const u = i / segments; + + tangents[ i ] = this.getTangentAt( u, new Vector3() ); + + } + + // select an initial normal vector perpendicular to the first tangent vector, + // and in the direction of the minimum tangent xyz component + + normals[ 0 ] = new Vector3(); + binormals[ 0 ] = new Vector3(); + let min = Number.MAX_VALUE; + const tx = Math.abs( tangents[ 0 ].x ); + const ty = Math.abs( tangents[ 0 ].y ); + const tz = Math.abs( tangents[ 0 ].z ); + + if ( tx <= min ) { + + min = tx; + normal.set( 1, 0, 0 ); + + } + + if ( ty <= min ) { + + min = ty; + normal.set( 0, 1, 0 ); + + } + + if ( tz <= min ) { + + normal.set( 0, 0, 1 ); + + } + + vec.crossVectors( tangents[ 0 ], normal ).normalize(); + + normals[ 0 ].crossVectors( tangents[ 0 ], vec ); + binormals[ 0 ].crossVectors( tangents[ 0 ], normals[ 0 ] ); + + + // compute the slowly-varying normal and binormal vectors for each segment on the curve + + for ( let i = 1; i <= segments; i ++ ) { + + normals[ i ] = normals[ i - 1 ].clone(); + + binormals[ i ] = binormals[ i - 1 ].clone(); + + vec.crossVectors( tangents[ i - 1 ], tangents[ i ] ); + + if ( vec.length() > Number.EPSILON ) { + + vec.normalize(); + + const theta = Math.acos( clamp$1( tangents[ i - 1 ].dot( tangents[ i ] ), - 1, 1 ) ); // clamp for floating pt errors + + normals[ i ].applyMatrix4( mat.makeRotationAxis( vec, theta ) ); + + } + + binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); + + } + + // if the curve is closed, postprocess the vectors so the first and last normal vectors are the same + + if ( closed === true ) { + + let theta = Math.acos( clamp$1( normals[ 0 ].dot( normals[ segments ] ), - 1, 1 ) ); + theta /= segments; + + if ( tangents[ 0 ].dot( vec.crossVectors( normals[ 0 ], normals[ segments ] ) ) > 0 ) { + + theta = - theta; + + } + + for ( let i = 1; i <= segments; i ++ ) { + + // twist a little... + normals[ i ].applyMatrix4( mat.makeRotationAxis( tangents[ i ], theta * i ) ); + binormals[ i ].crossVectors( tangents[ i ], normals[ i ] ); + + } + + } + + return { + tangents: tangents, + normals: normals, + binormals: binormals + }; + + } + + clone() { + + return new this.constructor().copy( this ); + + } + + copy( source ) { + + this.arcLengthDivisions = source.arcLengthDivisions; + + return this; + + } + + toJSON() { + + const data = { + metadata: { + version: 4.6, + type: 'Curve', + generator: 'Curve.toJSON' + } + }; + + data.arcLengthDivisions = this.arcLengthDivisions; + data.type = this.type; + + return data; + + } + + fromJSON( json ) { + + this.arcLengthDivisions = json.arcLengthDivisions; + + return this; + + } + +} + +class EllipseCurve extends Curve { + + constructor( aX = 0, aY = 0, xRadius = 1, yRadius = 1, aStartAngle = 0, aEndAngle = Math.PI * 2, aClockwise = false, aRotation = 0 ) { + + super(); + + this.isEllipseCurve = true; + + this.type = 'EllipseCurve'; + + this.aX = aX; + this.aY = aY; + + this.xRadius = xRadius; + this.yRadius = yRadius; + + this.aStartAngle = aStartAngle; + this.aEndAngle = aEndAngle; + + this.aClockwise = aClockwise; + + this.aRotation = aRotation; + + } + + getPoint( t, optionalTarget = new Vector2() ) { + + const point = optionalTarget; + + const twoPi = Math.PI * 2; + let deltaAngle = this.aEndAngle - this.aStartAngle; + const samePoints = Math.abs( deltaAngle ) < Number.EPSILON; + + // ensures that deltaAngle is 0 .. 2 PI + while ( deltaAngle < 0 ) deltaAngle += twoPi; + while ( deltaAngle > twoPi ) deltaAngle -= twoPi; + + if ( deltaAngle < Number.EPSILON ) { + + if ( samePoints ) { + + deltaAngle = 0; + + } else { + + deltaAngle = twoPi; + + } + + } + + if ( this.aClockwise === true && ! samePoints ) { + + if ( deltaAngle === twoPi ) { + + deltaAngle = - twoPi; + + } else { + + deltaAngle = deltaAngle - twoPi; + + } + + } + + const angle = this.aStartAngle + t * deltaAngle; + let x = this.aX + this.xRadius * Math.cos( angle ); + let y = this.aY + this.yRadius * Math.sin( angle ); + + if ( this.aRotation !== 0 ) { + + const cos = Math.cos( this.aRotation ); + const sin = Math.sin( this.aRotation ); + + const tx = x - this.aX; + const ty = y - this.aY; + + // Rotate the point about the center of the ellipse. + x = tx * cos - ty * sin + this.aX; + y = tx * sin + ty * cos + this.aY; + + } + + return point.set( x, y ); + + } + + copy( source ) { + + super.copy( source ); + + this.aX = source.aX; + this.aY = source.aY; + + this.xRadius = source.xRadius; + this.yRadius = source.yRadius; + + this.aStartAngle = source.aStartAngle; + this.aEndAngle = source.aEndAngle; + + this.aClockwise = source.aClockwise; + + this.aRotation = source.aRotation; + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + data.aX = this.aX; + data.aY = this.aY; + + data.xRadius = this.xRadius; + data.yRadius = this.yRadius; + + data.aStartAngle = this.aStartAngle; + data.aEndAngle = this.aEndAngle; + + data.aClockwise = this.aClockwise; + + data.aRotation = this.aRotation; + + return data; + + } + + fromJSON( json ) { + + super.fromJSON( json ); + + this.aX = json.aX; + this.aY = json.aY; + + this.xRadius = json.xRadius; + this.yRadius = json.yRadius; + + this.aStartAngle = json.aStartAngle; + this.aEndAngle = json.aEndAngle; + + this.aClockwise = json.aClockwise; + + this.aRotation = json.aRotation; + + return this; + + } + +} + +class ArcCurve extends EllipseCurve { + + constructor( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { + + super( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); + + this.isArcCurve = true; + + this.type = 'ArcCurve'; + + } + +} + +/** + * Centripetal CatmullRom Curve - which is useful for avoiding + * cusps and self-intersections in non-uniform catmull rom curves. + * http://www.cemyuksel.com/research/catmullrom_param/catmullrom.pdf + * + * curve.type accepts centripetal(default), chordal and catmullrom + * curve.tension is used for catmullrom which defaults to 0.5 + */ + + +/* +Based on an optimized c++ solution in + - http://stackoverflow.com/questions/9489736/catmull-rom-curve-with-no-cusps-and-no-self-intersections/ + - http://ideone.com/NoEbVM + +This CubicPoly class could be used for reusing some variables and calculations, +but for three.js curve use, it could be possible inlined and flatten into a single function call +which can be placed in CurveUtils. +*/ + +function CubicPoly() { + + let c0 = 0, c1 = 0, c2 = 0, c3 = 0; + + /* + * Compute coefficients for a cubic polynomial + * p(s) = c0 + c1*s + c2*s^2 + c3*s^3 + * such that + * p(0) = x0, p(1) = x1 + * and + * p'(0) = t0, p'(1) = t1. + */ + function init( x0, x1, t0, t1 ) { + + c0 = x0; + c1 = t0; + c2 = - 3 * x0 + 3 * x1 - 2 * t0 - t1; + c3 = 2 * x0 - 2 * x1 + t0 + t1; + + } + + return { + + initCatmullRom: function ( x0, x1, x2, x3, tension ) { + + init( x1, x2, tension * ( x2 - x0 ), tension * ( x3 - x1 ) ); + + }, + + initNonuniformCatmullRom: function ( x0, x1, x2, x3, dt0, dt1, dt2 ) { + + // compute tangents when parameterized in [t1,t2] + let t1 = ( x1 - x0 ) / dt0 - ( x2 - x0 ) / ( dt0 + dt1 ) + ( x2 - x1 ) / dt1; + let t2 = ( x2 - x1 ) / dt1 - ( x3 - x1 ) / ( dt1 + dt2 ) + ( x3 - x2 ) / dt2; + + // rescale tangents for parametrization in [0,1] + t1 *= dt1; + t2 *= dt1; + + init( x1, x2, t1, t2 ); + + }, + + calc: function ( t ) { + + const t2 = t * t; + const t3 = t2 * t; + return c0 + c1 * t + c2 * t2 + c3 * t3; + + } + + }; + +} + +// + +const tmp = /*@__PURE__*/ new Vector3(); +const px = /*@__PURE__*/ new CubicPoly(); +const py = /*@__PURE__*/ new CubicPoly(); +const pz = /*@__PURE__*/ new CubicPoly(); + +class CatmullRomCurve3 extends Curve { + + constructor( points = [], closed = false, curveType = 'centripetal', tension = 0.5 ) { + + super(); + + this.isCatmullRomCurve3 = true; + + this.type = 'CatmullRomCurve3'; + + this.points = points; + this.closed = closed; + this.curveType = curveType; + this.tension = tension; + + } + + getPoint( t, optionalTarget = new Vector3() ) { + + const point = optionalTarget; + + const points = this.points; + const l = points.length; + + const p = ( l - ( this.closed ? 0 : 1 ) ) * t; + let intPoint = Math.floor( p ); + let weight = p - intPoint; + + if ( this.closed ) { + + intPoint += intPoint > 0 ? 0 : ( Math.floor( Math.abs( intPoint ) / l ) + 1 ) * l; + + } else if ( weight === 0 && intPoint === l - 1 ) { + + intPoint = l - 2; + weight = 1; + + } + + let p0, p3; // 4 points (p1 & p2 defined below) + + if ( this.closed || intPoint > 0 ) { + + p0 = points[ ( intPoint - 1 ) % l ]; + + } else { + + // extrapolate first point + tmp.subVectors( points[ 0 ], points[ 1 ] ).add( points[ 0 ] ); + p0 = tmp; + + } + + const p1 = points[ intPoint % l ]; + const p2 = points[ ( intPoint + 1 ) % l ]; + + if ( this.closed || intPoint + 2 < l ) { + + p3 = points[ ( intPoint + 2 ) % l ]; + + } else { + + // extrapolate last point + tmp.subVectors( points[ l - 1 ], points[ l - 2 ] ).add( points[ l - 1 ] ); + p3 = tmp; + + } + + if ( this.curveType === 'centripetal' || this.curveType === 'chordal' ) { + + // init Centripetal / Chordal Catmull-Rom + const pow = this.curveType === 'chordal' ? 0.5 : 0.25; + let dt0 = Math.pow( p0.distanceToSquared( p1 ), pow ); + let dt1 = Math.pow( p1.distanceToSquared( p2 ), pow ); + let dt2 = Math.pow( p2.distanceToSquared( p3 ), pow ); + + // safety check for repeated points + if ( dt1 < 1e-4 ) dt1 = 1.0; + if ( dt0 < 1e-4 ) dt0 = dt1; + if ( dt2 < 1e-4 ) dt2 = dt1; + + px.initNonuniformCatmullRom( p0.x, p1.x, p2.x, p3.x, dt0, dt1, dt2 ); + py.initNonuniformCatmullRom( p0.y, p1.y, p2.y, p3.y, dt0, dt1, dt2 ); + pz.initNonuniformCatmullRom( p0.z, p1.z, p2.z, p3.z, dt0, dt1, dt2 ); + + } else if ( this.curveType === 'catmullrom' ) { + + px.initCatmullRom( p0.x, p1.x, p2.x, p3.x, this.tension ); + py.initCatmullRom( p0.y, p1.y, p2.y, p3.y, this.tension ); + pz.initCatmullRom( p0.z, p1.z, p2.z, p3.z, this.tension ); + + } + + point.set( + px.calc( weight ), + py.calc( weight ), + pz.calc( weight ) + ); + + return point; + + } + + copy( source ) { + + super.copy( source ); + + this.points = []; + + for ( let i = 0, l = source.points.length; i < l; i ++ ) { + + const point = source.points[ i ]; + + this.points.push( point.clone() ); + + } + + this.closed = source.closed; + this.curveType = source.curveType; + this.tension = source.tension; + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + data.points = []; + + for ( let i = 0, l = this.points.length; i < l; i ++ ) { + + const point = this.points[ i ]; + data.points.push( point.toArray() ); + + } + + data.closed = this.closed; + data.curveType = this.curveType; + data.tension = this.tension; + + return data; + + } + + fromJSON( json ) { + + super.fromJSON( json ); + + this.points = []; + + for ( let i = 0, l = json.points.length; i < l; i ++ ) { + + const point = json.points[ i ]; + this.points.push( new Vector3().fromArray( point ) ); + + } + + this.closed = json.closed; + this.curveType = json.curveType; + this.tension = json.tension; + + return this; + + } + +} + +/** + * Bezier Curves formulas obtained from + * https://en.wikipedia.org/wiki/B%C3%A9zier_curve + */ + +function CatmullRom( t, p0, p1, p2, p3 ) { + + const v0 = ( p2 - p0 ) * 0.5; + const v1 = ( p3 - p1 ) * 0.5; + const t2 = t * t; + const t3 = t * t2; + return ( 2 * p1 - 2 * p2 + v0 + v1 ) * t3 + ( - 3 * p1 + 3 * p2 - 2 * v0 - v1 ) * t2 + v0 * t + p1; + +} + +// + +function QuadraticBezierP0( t, p ) { + + const k = 1 - t; + return k * k * p; + +} + +function QuadraticBezierP1( t, p ) { + + return 2 * ( 1 - t ) * t * p; + +} + +function QuadraticBezierP2( t, p ) { + + return t * t * p; + +} + +function QuadraticBezier( t, p0, p1, p2 ) { + + return QuadraticBezierP0( t, p0 ) + QuadraticBezierP1( t, p1 ) + + QuadraticBezierP2( t, p2 ); + +} + +// + +function CubicBezierP0( t, p ) { + + const k = 1 - t; + return k * k * k * p; + +} + +function CubicBezierP1( t, p ) { + + const k = 1 - t; + return 3 * k * k * t * p; + +} + +function CubicBezierP2( t, p ) { + + return 3 * ( 1 - t ) * t * t * p; + +} + +function CubicBezierP3( t, p ) { + + return t * t * t * p; + +} + +function CubicBezier( t, p0, p1, p2, p3 ) { + + return CubicBezierP0( t, p0 ) + CubicBezierP1( t, p1 ) + CubicBezierP2( t, p2 ) + + CubicBezierP3( t, p3 ); + +} + +class CubicBezierCurve extends Curve { + + constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2(), v3 = new Vector2() ) { + + super(); + + this.isCubicBezierCurve = true; + + this.type = 'CubicBezierCurve'; + + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + + } + + getPoint( t, optionalTarget = new Vector2() ) { + + const point = optionalTarget; + + const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; + + point.set( + CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), + CubicBezier( t, v0.y, v1.y, v2.y, v3.y ) + ); + + return point; + + } + + copy( source ) { + + super.copy( source ); + + this.v0.copy( source.v0 ); + this.v1.copy( source.v1 ); + this.v2.copy( source.v2 ); + this.v3.copy( source.v3 ); + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + data.v0 = this.v0.toArray(); + data.v1 = this.v1.toArray(); + data.v2 = this.v2.toArray(); + data.v3 = this.v3.toArray(); + + return data; + + } + + fromJSON( json ) { + + super.fromJSON( json ); + + this.v0.fromArray( json.v0 ); + this.v1.fromArray( json.v1 ); + this.v2.fromArray( json.v2 ); + this.v3.fromArray( json.v3 ); + + return this; + + } + +} + +class CubicBezierCurve3 extends Curve { + + constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3(), v3 = new Vector3() ) { + + super(); + + this.isCubicBezierCurve3 = true; + + this.type = 'CubicBezierCurve3'; + + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + this.v3 = v3; + + } + + getPoint( t, optionalTarget = new Vector3() ) { + + const point = optionalTarget; + + const v0 = this.v0, v1 = this.v1, v2 = this.v2, v3 = this.v3; + + point.set( + CubicBezier( t, v0.x, v1.x, v2.x, v3.x ), + CubicBezier( t, v0.y, v1.y, v2.y, v3.y ), + CubicBezier( t, v0.z, v1.z, v2.z, v3.z ) + ); + + return point; + + } + + copy( source ) { + + super.copy( source ); + + this.v0.copy( source.v0 ); + this.v1.copy( source.v1 ); + this.v2.copy( source.v2 ); + this.v3.copy( source.v3 ); + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + data.v0 = this.v0.toArray(); + data.v1 = this.v1.toArray(); + data.v2 = this.v2.toArray(); + data.v3 = this.v3.toArray(); + + return data; + + } + + fromJSON( json ) { + + super.fromJSON( json ); + + this.v0.fromArray( json.v0 ); + this.v1.fromArray( json.v1 ); + this.v2.fromArray( json.v2 ); + this.v3.fromArray( json.v3 ); + + return this; + + } + +} + +class LineCurve extends Curve { + + constructor( v1 = new Vector2(), v2 = new Vector2() ) { + + super(); + + this.isLineCurve = true; + + this.type = 'LineCurve'; + + this.v1 = v1; + this.v2 = v2; + + } + + getPoint( t, optionalTarget = new Vector2() ) { + + const point = optionalTarget; + + if ( t === 1 ) { + + point.copy( this.v2 ); + + } else { + + point.copy( this.v2 ).sub( this.v1 ); + point.multiplyScalar( t ).add( this.v1 ); + + } + + return point; + + } + + // Line curve is linear, so we can overwrite default getPointAt + getPointAt( u, optionalTarget ) { + + return this.getPoint( u, optionalTarget ); + + } + + getTangent( t, optionalTarget = new Vector2() ) { + + return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); + + } + + getTangentAt( u, optionalTarget ) { + + return this.getTangent( u, optionalTarget ); + + } + + copy( source ) { + + super.copy( source ); + + this.v1.copy( source.v1 ); + this.v2.copy( source.v2 ); + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + data.v1 = this.v1.toArray(); + data.v2 = this.v2.toArray(); + + return data; + + } + + fromJSON( json ) { + + super.fromJSON( json ); + + this.v1.fromArray( json.v1 ); + this.v2.fromArray( json.v2 ); + + return this; + + } + +} + +class LineCurve3 extends Curve { + + constructor( v1 = new Vector3(), v2 = new Vector3() ) { + + super(); + + this.isLineCurve3 = true; + + this.type = 'LineCurve3'; + + this.v1 = v1; + this.v2 = v2; + + } + + getPoint( t, optionalTarget = new Vector3() ) { + + const point = optionalTarget; + + if ( t === 1 ) { + + point.copy( this.v2 ); + + } else { + + point.copy( this.v2 ).sub( this.v1 ); + point.multiplyScalar( t ).add( this.v1 ); + + } + + return point; + + } + + // Line curve is linear, so we can overwrite default getPointAt + getPointAt( u, optionalTarget ) { + + return this.getPoint( u, optionalTarget ); + + } + + getTangent( t, optionalTarget = new Vector3() ) { + + return optionalTarget.subVectors( this.v2, this.v1 ).normalize(); + + } + + getTangentAt( u, optionalTarget ) { + + return this.getTangent( u, optionalTarget ); + + } + + copy( source ) { + + super.copy( source ); + + this.v1.copy( source.v1 ); + this.v2.copy( source.v2 ); + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + data.v1 = this.v1.toArray(); + data.v2 = this.v2.toArray(); + + return data; + + } + + fromJSON( json ) { + + super.fromJSON( json ); + + this.v1.fromArray( json.v1 ); + this.v2.fromArray( json.v2 ); + + return this; + + } + +} + +class QuadraticBezierCurve extends Curve { + + constructor( v0 = new Vector2(), v1 = new Vector2(), v2 = new Vector2() ) { + + super(); + + this.isQuadraticBezierCurve = true; + + this.type = 'QuadraticBezierCurve'; + + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + + } + + getPoint( t, optionalTarget = new Vector2() ) { + + const point = optionalTarget; + + const v0 = this.v0, v1 = this.v1, v2 = this.v2; + + point.set( + QuadraticBezier( t, v0.x, v1.x, v2.x ), + QuadraticBezier( t, v0.y, v1.y, v2.y ) + ); + + return point; + + } + + copy( source ) { + + super.copy( source ); + + this.v0.copy( source.v0 ); + this.v1.copy( source.v1 ); + this.v2.copy( source.v2 ); + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + data.v0 = this.v0.toArray(); + data.v1 = this.v1.toArray(); + data.v2 = this.v2.toArray(); + + return data; + + } + + fromJSON( json ) { + + super.fromJSON( json ); + + this.v0.fromArray( json.v0 ); + this.v1.fromArray( json.v1 ); + this.v2.fromArray( json.v2 ); + + return this; + + } + +} + +class QuadraticBezierCurve3 extends Curve { + + constructor( v0 = new Vector3(), v1 = new Vector3(), v2 = new Vector3() ) { + + super(); + + this.isQuadraticBezierCurve3 = true; + + this.type = 'QuadraticBezierCurve3'; + + this.v0 = v0; + this.v1 = v1; + this.v2 = v2; + + } + + getPoint( t, optionalTarget = new Vector3() ) { + + const point = optionalTarget; + + const v0 = this.v0, v1 = this.v1, v2 = this.v2; + + point.set( + QuadraticBezier( t, v0.x, v1.x, v2.x ), + QuadraticBezier( t, v0.y, v1.y, v2.y ), + QuadraticBezier( t, v0.z, v1.z, v2.z ) + ); + + return point; + + } + + copy( source ) { + + super.copy( source ); + + this.v0.copy( source.v0 ); + this.v1.copy( source.v1 ); + this.v2.copy( source.v2 ); + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + data.v0 = this.v0.toArray(); + data.v1 = this.v1.toArray(); + data.v2 = this.v2.toArray(); + + return data; + + } + + fromJSON( json ) { + + super.fromJSON( json ); + + this.v0.fromArray( json.v0 ); + this.v1.fromArray( json.v1 ); + this.v2.fromArray( json.v2 ); + + return this; + + } + +} + +class SplineCurve extends Curve { + + constructor( points = [] ) { + + super(); + + this.isSplineCurve = true; + + this.type = 'SplineCurve'; + + this.points = points; + + } + + getPoint( t, optionalTarget = new Vector2() ) { + + const point = optionalTarget; + + const points = this.points; + const p = ( points.length - 1 ) * t; + + const intPoint = Math.floor( p ); + const weight = p - intPoint; + + const p0 = points[ intPoint === 0 ? intPoint : intPoint - 1 ]; + const p1 = points[ intPoint ]; + const p2 = points[ intPoint > points.length - 2 ? points.length - 1 : intPoint + 1 ]; + const p3 = points[ intPoint > points.length - 3 ? points.length - 1 : intPoint + 2 ]; + + point.set( + CatmullRom( weight, p0.x, p1.x, p2.x, p3.x ), + CatmullRom( weight, p0.y, p1.y, p2.y, p3.y ) + ); + + return point; + + } + + copy( source ) { + + super.copy( source ); + + this.points = []; + + for ( let i = 0, l = source.points.length; i < l; i ++ ) { + + const point = source.points[ i ]; + + this.points.push( point.clone() ); + + } + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + data.points = []; + + for ( let i = 0, l = this.points.length; i < l; i ++ ) { + + const point = this.points[ i ]; + data.points.push( point.toArray() ); + + } + + return data; + + } + + fromJSON( json ) { + + super.fromJSON( json ); + + this.points = []; + + for ( let i = 0, l = json.points.length; i < l; i ++ ) { + + const point = json.points[ i ]; + this.points.push( new Vector2().fromArray( point ) ); + + } + + return this; + + } + +} + +var Curves = /*#__PURE__*/Object.freeze({ + __proto__: null, + ArcCurve: ArcCurve, + CatmullRomCurve3: CatmullRomCurve3, + CubicBezierCurve: CubicBezierCurve, + CubicBezierCurve3: CubicBezierCurve3, + EllipseCurve: EllipseCurve, + LineCurve: LineCurve, + LineCurve3: LineCurve3, + QuadraticBezierCurve: QuadraticBezierCurve, + QuadraticBezierCurve3: QuadraticBezierCurve3, + SplineCurve: SplineCurve +}); + +/************************************************************** + * Curved Path - a curve path is simply a array of connected + * curves, but retains the api of a curve + **************************************************************/ + +class CurvePath extends Curve { + + constructor() { + + super(); + + this.type = 'CurvePath'; + + this.curves = []; + this.autoClose = false; // Automatically closes the path + + } + + add( curve ) { + + this.curves.push( curve ); + + } + + closePath() { + + // Add a line curve if start and end of lines are not connected + const startPoint = this.curves[ 0 ].getPoint( 0 ); + const endPoint = this.curves[ this.curves.length - 1 ].getPoint( 1 ); + + if ( ! startPoint.equals( endPoint ) ) { + + const lineType = ( startPoint.isVector2 === true ) ? 'LineCurve' : 'LineCurve3'; + this.curves.push( new Curves[ lineType ]( endPoint, startPoint ) ); + + } + + return this; + + } + + // To get accurate point with reference to + // entire path distance at time t, + // following has to be done: + + // 1. Length of each sub path have to be known + // 2. Locate and identify type of curve + // 3. Get t for the curve + // 4. Return curve.getPointAt(t') + + getPoint( t, optionalTarget ) { + + const d = t * this.getLength(); + const curveLengths = this.getCurveLengths(); + let i = 0; + + // To think about boundaries points. + + while ( i < curveLengths.length ) { + + if ( curveLengths[ i ] >= d ) { + + const diff = curveLengths[ i ] - d; + const curve = this.curves[ i ]; + + const segmentLength = curve.getLength(); + const u = segmentLength === 0 ? 0 : 1 - diff / segmentLength; + + return curve.getPointAt( u, optionalTarget ); + + } + + i ++; + + } + + return null; + + // loop where sum != 0, sum > d , sum+1 1 && ! points[ points.length - 1 ].equals( points[ 0 ] ) ) { + + points.push( points[ 0 ] ); + + } + + return points; + + } + + copy( source ) { + + super.copy( source ); + + this.curves = []; + + for ( let i = 0, l = source.curves.length; i < l; i ++ ) { + + const curve = source.curves[ i ]; + + this.curves.push( curve.clone() ); + + } + + this.autoClose = source.autoClose; + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + data.autoClose = this.autoClose; + data.curves = []; + + for ( let i = 0, l = this.curves.length; i < l; i ++ ) { + + const curve = this.curves[ i ]; + data.curves.push( curve.toJSON() ); + + } + + return data; + + } + + fromJSON( json ) { + + super.fromJSON( json ); + + this.autoClose = json.autoClose; + this.curves = []; + + for ( let i = 0, l = json.curves.length; i < l; i ++ ) { + + const curve = json.curves[ i ]; + this.curves.push( new Curves[ curve.type ]().fromJSON( curve ) ); + + } + + return this; + + } + +} + +class Path extends CurvePath { + + constructor( points ) { + + super(); + + this.type = 'Path'; + + this.currentPoint = new Vector2(); + + if ( points ) { + + this.setFromPoints( points ); + + } + + } + + setFromPoints( points ) { + + this.moveTo( points[ 0 ].x, points[ 0 ].y ); + + for ( let i = 1, l = points.length; i < l; i ++ ) { + + this.lineTo( points[ i ].x, points[ i ].y ); + + } + + return this; + + } + + moveTo( x, y ) { + + this.currentPoint.set( x, y ); // TODO consider referencing vectors instead of copying? + + return this; + + } + + lineTo( x, y ) { + + const curve = new LineCurve( this.currentPoint.clone(), new Vector2( x, y ) ); + this.curves.push( curve ); + + this.currentPoint.set( x, y ); + + return this; + + } + + quadraticCurveTo( aCPx, aCPy, aX, aY ) { + + const curve = new QuadraticBezierCurve( + this.currentPoint.clone(), + new Vector2( aCPx, aCPy ), + new Vector2( aX, aY ) + ); + + this.curves.push( curve ); + + this.currentPoint.set( aX, aY ); + + return this; + + } + + bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { + + const curve = new CubicBezierCurve( + this.currentPoint.clone(), + new Vector2( aCP1x, aCP1y ), + new Vector2( aCP2x, aCP2y ), + new Vector2( aX, aY ) + ); + + this.curves.push( curve ); + + this.currentPoint.set( aX, aY ); + + return this; + + } + + splineThru( pts /*Array of Vector*/ ) { + + const npts = [ this.currentPoint.clone() ].concat( pts ); + + const curve = new SplineCurve( npts ); + this.curves.push( curve ); + + this.currentPoint.copy( pts[ pts.length - 1 ] ); + + return this; + + } + + arc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { + + const x0 = this.currentPoint.x; + const y0 = this.currentPoint.y; + + this.absarc( aX + x0, aY + y0, aRadius, + aStartAngle, aEndAngle, aClockwise ); + + return this; + + } + + absarc( aX, aY, aRadius, aStartAngle, aEndAngle, aClockwise ) { + + this.absellipse( aX, aY, aRadius, aRadius, aStartAngle, aEndAngle, aClockwise ); + + return this; + + } + + ellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { + + const x0 = this.currentPoint.x; + const y0 = this.currentPoint.y; + + this.absellipse( aX + x0, aY + y0, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); + + return this; + + } + + absellipse( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ) { + + const curve = new EllipseCurve( aX, aY, xRadius, yRadius, aStartAngle, aEndAngle, aClockwise, aRotation ); + + if ( this.curves.length > 0 ) { + + // if a previous curve is present, attempt to join + const firstPoint = curve.getPoint( 0 ); + + if ( ! firstPoint.equals( this.currentPoint ) ) { + + this.lineTo( firstPoint.x, firstPoint.y ); + + } + + } + + this.curves.push( curve ); + + const lastPoint = curve.getPoint( 1 ); + this.currentPoint.copy( lastPoint ); + + return this; + + } + + copy( source ) { + + super.copy( source ); + + this.currentPoint.copy( source.currentPoint ); + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + data.currentPoint = this.currentPoint.toArray(); + + return data; + + } + + fromJSON( json ) { + + super.fromJSON( json ); + + this.currentPoint.fromArray( json.currentPoint ); + + return this; + + } + +} + +class LatheGeometry extends BufferGeometry { + + constructor( points = [ new Vector2( 0, - 0.5 ), new Vector2( 0.5, 0 ), new Vector2( 0, 0.5 ) ], segments = 12, phiStart = 0, phiLength = Math.PI * 2 ) { + + super(); + + this.type = 'LatheGeometry'; + + this.parameters = { + points: points, + segments: segments, + phiStart: phiStart, + phiLength: phiLength + }; + + segments = Math.floor( segments ); + + // clamp phiLength so it's in range of [ 0, 2PI ] + + phiLength = clamp$1( phiLength, 0, Math.PI * 2 ); + + // buffers + + const indices = []; + const vertices = []; + const uvs = []; + const initNormals = []; + const normals = []; + + // helper variables + + const inverseSegments = 1.0 / segments; + const vertex = new Vector3(); + const uv = new Vector2(); + const normal = new Vector3(); + const curNormal = new Vector3(); + const prevNormal = new Vector3(); + let dx = 0; + let dy = 0; + + // pre-compute normals for initial "meridian" + + for ( let j = 0; j <= ( points.length - 1 ); j ++ ) { + + switch ( j ) { + + case 0: // special handling for 1st vertex on path + + dx = points[ j + 1 ].x - points[ j ].x; + dy = points[ j + 1 ].y - points[ j ].y; + + normal.x = dy * 1.0; + normal.y = - dx; + normal.z = dy * 0.0; + + prevNormal.copy( normal ); + + normal.normalize(); + + initNormals.push( normal.x, normal.y, normal.z ); + + break; + + case ( points.length - 1 ): // special handling for last Vertex on path + + initNormals.push( prevNormal.x, prevNormal.y, prevNormal.z ); + + break; + + default: // default handling for all vertices in between + + dx = points[ j + 1 ].x - points[ j ].x; + dy = points[ j + 1 ].y - points[ j ].y; + + normal.x = dy * 1.0; + normal.y = - dx; + normal.z = dy * 0.0; + + curNormal.copy( normal ); + + normal.x += prevNormal.x; + normal.y += prevNormal.y; + normal.z += prevNormal.z; + + normal.normalize(); + + initNormals.push( normal.x, normal.y, normal.z ); + + prevNormal.copy( curNormal ); + + } + + } + + // generate vertices, uvs and normals + + for ( let i = 0; i <= segments; i ++ ) { + + const phi = phiStart + i * inverseSegments * phiLength; + + const sin = Math.sin( phi ); + const cos = Math.cos( phi ); + + for ( let j = 0; j <= ( points.length - 1 ); j ++ ) { + + // vertex + + vertex.x = points[ j ].x * sin; + vertex.y = points[ j ].y; + vertex.z = points[ j ].x * cos; + + vertices.push( vertex.x, vertex.y, vertex.z ); + + // uv + + uv.x = i / segments; + uv.y = j / ( points.length - 1 ); + + uvs.push( uv.x, uv.y ); + + // normal + + const x = initNormals[ 3 * j + 0 ] * sin; + const y = initNormals[ 3 * j + 1 ]; + const z = initNormals[ 3 * j + 0 ] * cos; + + normals.push( x, y, z ); + + } + + } + + // indices + + for ( let i = 0; i < segments; i ++ ) { + + for ( let j = 0; j < ( points.length - 1 ); j ++ ) { + + const base = j + i * points.length; + + const a = base; + const b = base + points.length; + const c = base + points.length + 1; + const d = base + 1; + + // faces + + indices.push( a, b, d ); + indices.push( c, d, b ); + + } + + } + + // build geometry + + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + + } + + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + + static fromJSON( data ) { + + return new LatheGeometry( data.points, data.segments, data.phiStart, data.phiLength ); + + } + +} + +class CapsuleGeometry extends LatheGeometry { + + constructor( radius = 1, length = 1, capSegments = 4, radialSegments = 8 ) { + + const path = new Path(); + path.absarc( 0, - length / 2, radius, Math.PI * 1.5, 0 ); + path.absarc( 0, length / 2, radius, 0, Math.PI * 0.5 ); + + super( path.getPoints( capSegments ), radialSegments ); + + this.type = 'CapsuleGeometry'; + + this.parameters = { + radius: radius, + length: length, + capSegments: capSegments, + radialSegments: radialSegments, + }; + + } + + static fromJSON( data ) { + + return new CapsuleGeometry( data.radius, data.length, data.capSegments, data.radialSegments ); + + } + +} + +class CircleGeometry extends BufferGeometry { + + constructor( radius = 1, segments = 32, thetaStart = 0, thetaLength = Math.PI * 2 ) { + + super(); + + this.type = 'CircleGeometry'; + + this.parameters = { + radius: radius, + segments: segments, + thetaStart: thetaStart, + thetaLength: thetaLength + }; + + segments = Math.max( 3, segments ); + + // buffers + + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + + // helper variables + + const vertex = new Vector3(); + const uv = new Vector2(); + + // center point + + vertices.push( 0, 0, 0 ); + normals.push( 0, 0, 1 ); + uvs.push( 0.5, 0.5 ); + + for ( let s = 0, i = 3; s <= segments; s ++, i += 3 ) { + + const segment = thetaStart + s / segments * thetaLength; + + // vertex + + vertex.x = radius * Math.cos( segment ); + vertex.y = radius * Math.sin( segment ); + + vertices.push( vertex.x, vertex.y, vertex.z ); + + // normal + + normals.push( 0, 0, 1 ); + + // uvs + + uv.x = ( vertices[ i ] / radius + 1 ) / 2; + uv.y = ( vertices[ i + 1 ] / radius + 1 ) / 2; + + uvs.push( uv.x, uv.y ); + + } + + // indices + + for ( let i = 1; i <= segments; i ++ ) { + + indices.push( i, i + 1, 0 ); + + } + + // build geometry + + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + + } + + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + + static fromJSON( data ) { + + return new CircleGeometry( data.radius, data.segments, data.thetaStart, data.thetaLength ); + + } + +} + +class CylinderGeometry extends BufferGeometry { + + constructor( radiusTop = 1, radiusBottom = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) { + + super(); + + this.type = 'CylinderGeometry'; + + this.parameters = { + radiusTop: radiusTop, + radiusBottom: radiusBottom, + height: height, + radialSegments: radialSegments, + heightSegments: heightSegments, + openEnded: openEnded, + thetaStart: thetaStart, + thetaLength: thetaLength + }; + + const scope = this; + + radialSegments = Math.floor( radialSegments ); + heightSegments = Math.floor( heightSegments ); + + // buffers + + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + + // helper variables + + let index = 0; + const indexArray = []; + const halfHeight = height / 2; + let groupStart = 0; + + // generate geometry + + generateTorso(); + + if ( openEnded === false ) { + + if ( radiusTop > 0 ) generateCap( true ); + if ( radiusBottom > 0 ) generateCap( false ); + + } + + // build geometry + + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + + function generateTorso() { + + const normal = new Vector3(); + const vertex = new Vector3(); + + let groupCount = 0; + + // this will be used to calculate the normal + const slope = ( radiusBottom - radiusTop ) / height; + + // generate vertices, normals and uvs + + for ( let y = 0; y <= heightSegments; y ++ ) { + + const indexRow = []; + + const v = y / heightSegments; + + // calculate the radius of the current row + + const radius = v * ( radiusBottom - radiusTop ) + radiusTop; + + for ( let x = 0; x <= radialSegments; x ++ ) { + + const u = x / radialSegments; + + const theta = u * thetaLength + thetaStart; + + const sinTheta = Math.sin( theta ); + const cosTheta = Math.cos( theta ); + + // vertex + + vertex.x = radius * sinTheta; + vertex.y = - v * height + halfHeight; + vertex.z = radius * cosTheta; + vertices.push( vertex.x, vertex.y, vertex.z ); + + // normal + + normal.set( sinTheta, slope, cosTheta ).normalize(); + normals.push( normal.x, normal.y, normal.z ); + + // uv + + uvs.push( u, 1 - v ); + + // save index of vertex in respective row + + indexRow.push( index ++ ); + + } + + // now save vertices of the row in our index array + + indexArray.push( indexRow ); + + } + + // generate indices + + for ( let x = 0; x < radialSegments; x ++ ) { + + for ( let y = 0; y < heightSegments; y ++ ) { + + // we use the index array to access the correct indices + + const a = indexArray[ y ][ x ]; + const b = indexArray[ y + 1 ][ x ]; + const c = indexArray[ y + 1 ][ x + 1 ]; + const d = indexArray[ y ][ x + 1 ]; + + // faces + + if ( radiusTop > 0 ) { + + indices.push( a, b, d ); + groupCount += 3; + + } + + if ( radiusBottom > 0 ) { + + indices.push( b, c, d ); + groupCount += 3; + + } + + } + + } + + // add a group to the geometry. this will ensure multi material support + + scope.addGroup( groupStart, groupCount, 0 ); + + // calculate new start value for groups + + groupStart += groupCount; + + } + + function generateCap( top ) { + + // save the index of the first center vertex + const centerIndexStart = index; + + const uv = new Vector2(); + const vertex = new Vector3(); + + let groupCount = 0; + + const radius = ( top === true ) ? radiusTop : radiusBottom; + const sign = ( top === true ) ? 1 : - 1; + + // first we generate the center vertex data of the cap. + // because the geometry needs one set of uvs per face, + // we must generate a center vertex per face/segment + + for ( let x = 1; x <= radialSegments; x ++ ) { + + // vertex + + vertices.push( 0, halfHeight * sign, 0 ); + + // normal + + normals.push( 0, sign, 0 ); + + // uv + + uvs.push( 0.5, 0.5 ); + + // increase index + + index ++; + + } + + // save the index of the last center vertex + const centerIndexEnd = index; + + // now we generate the surrounding vertices, normals and uvs + + for ( let x = 0; x <= radialSegments; x ++ ) { + + const u = x / radialSegments; + const theta = u * thetaLength + thetaStart; + + const cosTheta = Math.cos( theta ); + const sinTheta = Math.sin( theta ); + + // vertex + + vertex.x = radius * sinTheta; + vertex.y = halfHeight * sign; + vertex.z = radius * cosTheta; + vertices.push( vertex.x, vertex.y, vertex.z ); + + // normal + + normals.push( 0, sign, 0 ); + + // uv + + uv.x = ( cosTheta * 0.5 ) + 0.5; + uv.y = ( sinTheta * 0.5 * sign ) + 0.5; + uvs.push( uv.x, uv.y ); + + // increase index + + index ++; + + } + + // generate indices + + for ( let x = 0; x < radialSegments; x ++ ) { + + const c = centerIndexStart + x; + const i = centerIndexEnd + x; + + if ( top === true ) { + + // face top + + indices.push( i, i + 1, c ); + + } else { + + // face bottom + + indices.push( i + 1, i, c ); + + } + + groupCount += 3; + + } + + // add a group to the geometry. this will ensure multi material support + + scope.addGroup( groupStart, groupCount, top === true ? 1 : 2 ); + + // calculate new start value for groups + + groupStart += groupCount; + + } + + } + + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + + static fromJSON( data ) { + + return new CylinderGeometry( data.radiusTop, data.radiusBottom, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); + + } + +} + +class ConeGeometry extends CylinderGeometry { + + constructor( radius = 1, height = 1, radialSegments = 32, heightSegments = 1, openEnded = false, thetaStart = 0, thetaLength = Math.PI * 2 ) { + + super( 0, radius, height, radialSegments, heightSegments, openEnded, thetaStart, thetaLength ); + + this.type = 'ConeGeometry'; + + this.parameters = { + radius: radius, + height: height, + radialSegments: radialSegments, + heightSegments: heightSegments, + openEnded: openEnded, + thetaStart: thetaStart, + thetaLength: thetaLength + }; + + } + + static fromJSON( data ) { + + return new ConeGeometry( data.radius, data.height, data.radialSegments, data.heightSegments, data.openEnded, data.thetaStart, data.thetaLength ); + + } + +} + +class PolyhedronGeometry extends BufferGeometry { + + constructor( vertices = [], indices = [], radius = 1, detail = 0 ) { + + super(); + + this.type = 'PolyhedronGeometry'; + + this.parameters = { + vertices: vertices, + indices: indices, + radius: radius, + detail: detail + }; + + // default buffer data + + const vertexBuffer = []; + const uvBuffer = []; + + // the subdivision creates the vertex buffer data + + subdivide( detail ); + + // all vertices should lie on a conceptual sphere with a given radius + + applyRadius( radius ); + + // finally, create the uv data + + generateUVs(); + + // build non-indexed geometry + + this.setAttribute( 'position', new Float32BufferAttribute( vertexBuffer, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( vertexBuffer.slice(), 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvBuffer, 2 ) ); + + if ( detail === 0 ) { + + this.computeVertexNormals(); // flat normals + + } else { + + this.normalizeNormals(); // smooth normals + + } + + // helper functions + + function subdivide( detail ) { + + const a = new Vector3(); + const b = new Vector3(); + const c = new Vector3(); + + // iterate over all faces and apply a subdivision with the given detail value + + for ( let i = 0; i < indices.length; i += 3 ) { + + // get the vertices of the face + + getVertexByIndex( indices[ i + 0 ], a ); + getVertexByIndex( indices[ i + 1 ], b ); + getVertexByIndex( indices[ i + 2 ], c ); + + // perform subdivision + + subdivideFace( a, b, c, detail ); + + } + + } + + function subdivideFace( a, b, c, detail ) { + + const cols = detail + 1; + + // we use this multidimensional array as a data structure for creating the subdivision + + const v = []; + + // construct all of the vertices for this subdivision + + for ( let i = 0; i <= cols; i ++ ) { + + v[ i ] = []; + + const aj = a.clone().lerp( c, i / cols ); + const bj = b.clone().lerp( c, i / cols ); + + const rows = cols - i; + + for ( let j = 0; j <= rows; j ++ ) { + + if ( j === 0 && i === cols ) { + + v[ i ][ j ] = aj; + + } else { + + v[ i ][ j ] = aj.clone().lerp( bj, j / rows ); + + } + + } + + } + + // construct all of the faces + + for ( let i = 0; i < cols; i ++ ) { + + for ( let j = 0; j < 2 * ( cols - i ) - 1; j ++ ) { + + const k = Math.floor( j / 2 ); + + if ( j % 2 === 0 ) { + + pushVertex( v[ i ][ k + 1 ] ); + pushVertex( v[ i + 1 ][ k ] ); + pushVertex( v[ i ][ k ] ); + + } else { + + pushVertex( v[ i ][ k + 1 ] ); + pushVertex( v[ i + 1 ][ k + 1 ] ); + pushVertex( v[ i + 1 ][ k ] ); + + } + + } + + } + + } + + function applyRadius( radius ) { + + const vertex = new Vector3(); + + // iterate over the entire buffer and apply the radius to each vertex + + for ( let i = 0; i < vertexBuffer.length; i += 3 ) { + + vertex.x = vertexBuffer[ i + 0 ]; + vertex.y = vertexBuffer[ i + 1 ]; + vertex.z = vertexBuffer[ i + 2 ]; + + vertex.normalize().multiplyScalar( radius ); + + vertexBuffer[ i + 0 ] = vertex.x; + vertexBuffer[ i + 1 ] = vertex.y; + vertexBuffer[ i + 2 ] = vertex.z; + + } + + } + + function generateUVs() { + + const vertex = new Vector3(); + + for ( let i = 0; i < vertexBuffer.length; i += 3 ) { + + vertex.x = vertexBuffer[ i + 0 ]; + vertex.y = vertexBuffer[ i + 1 ]; + vertex.z = vertexBuffer[ i + 2 ]; + + const u = azimuth( vertex ) / 2 / Math.PI + 0.5; + const v = inclination( vertex ) / Math.PI + 0.5; + uvBuffer.push( u, 1 - v ); + + } + + correctUVs(); + + correctSeam(); + + } + + function correctSeam() { + + // handle case when face straddles the seam, see #3269 + + for ( let i = 0; i < uvBuffer.length; i += 6 ) { + + // uv data of a single face + + const x0 = uvBuffer[ i + 0 ]; + const x1 = uvBuffer[ i + 2 ]; + const x2 = uvBuffer[ i + 4 ]; + + const max = Math.max( x0, x1, x2 ); + const min = Math.min( x0, x1, x2 ); + + // 0.9 is somewhat arbitrary + + if ( max > 0.9 && min < 0.1 ) { + + if ( x0 < 0.2 ) uvBuffer[ i + 0 ] += 1; + if ( x1 < 0.2 ) uvBuffer[ i + 2 ] += 1; + if ( x2 < 0.2 ) uvBuffer[ i + 4 ] += 1; + + } + + } + + } + + function pushVertex( vertex ) { + + vertexBuffer.push( vertex.x, vertex.y, vertex.z ); + + } + + function getVertexByIndex( index, vertex ) { + + const stride = index * 3; + + vertex.x = vertices[ stride + 0 ]; + vertex.y = vertices[ stride + 1 ]; + vertex.z = vertices[ stride + 2 ]; + + } + + function correctUVs() { + + const a = new Vector3(); + const b = new Vector3(); + const c = new Vector3(); + + const centroid = new Vector3(); + + const uvA = new Vector2(); + const uvB = new Vector2(); + const uvC = new Vector2(); + + for ( let i = 0, j = 0; i < vertexBuffer.length; i += 9, j += 6 ) { + + a.set( vertexBuffer[ i + 0 ], vertexBuffer[ i + 1 ], vertexBuffer[ i + 2 ] ); + b.set( vertexBuffer[ i + 3 ], vertexBuffer[ i + 4 ], vertexBuffer[ i + 5 ] ); + c.set( vertexBuffer[ i + 6 ], vertexBuffer[ i + 7 ], vertexBuffer[ i + 8 ] ); + + uvA.set( uvBuffer[ j + 0 ], uvBuffer[ j + 1 ] ); + uvB.set( uvBuffer[ j + 2 ], uvBuffer[ j + 3 ] ); + uvC.set( uvBuffer[ j + 4 ], uvBuffer[ j + 5 ] ); + + centroid.copy( a ).add( b ).add( c ).divideScalar( 3 ); + + const azi = azimuth( centroid ); + + correctUV( uvA, j + 0, a, azi ); + correctUV( uvB, j + 2, b, azi ); + correctUV( uvC, j + 4, c, azi ); + + } + + } + + function correctUV( uv, stride, vector, azimuth ) { + + if ( ( azimuth < 0 ) && ( uv.x === 1 ) ) { + + uvBuffer[ stride ] = uv.x - 1; + + } + + if ( ( vector.x === 0 ) && ( vector.z === 0 ) ) { + + uvBuffer[ stride ] = azimuth / 2 / Math.PI + 0.5; + + } + + } + + // Angle around the Y axis, counter-clockwise when looking from above. + + function azimuth( vector ) { + + return Math.atan2( vector.z, - vector.x ); + + } + + + // Angle above the XZ plane. + + function inclination( vector ) { + + return Math.atan2( - vector.y, Math.sqrt( ( vector.x * vector.x ) + ( vector.z * vector.z ) ) ); + + } + + } + + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + + static fromJSON( data ) { + + return new PolyhedronGeometry( data.vertices, data.indices, data.radius, data.details ); + + } + +} + +class DodecahedronGeometry extends PolyhedronGeometry { + + constructor( radius = 1, detail = 0 ) { + + const t = ( 1 + Math.sqrt( 5 ) ) / 2; + const r = 1 / t; + + const vertices = [ + + // (±1, ±1, ±1) + - 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, ±1/φ, ±φ) + 0, - r, - t, 0, - r, t, + 0, r, - t, 0, r, t, + + // (±1/φ, ±φ, 0) + - r, - t, 0, - r, t, 0, + r, - t, 0, r, t, 0, + + // (±φ, 0, ±1/φ) + - t, 0, - r, t, 0, - r, + - t, 0, r, t, 0, r + ]; + + const indices = [ + 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 + ]; + + super( vertices, indices, radius, detail ); + + this.type = 'DodecahedronGeometry'; + + this.parameters = { + radius: radius, + detail: detail + }; + + } + + static fromJSON( data ) { + + return new DodecahedronGeometry( data.radius, data.detail ); + + } + +} + +const _v0 = /*@__PURE__*/ new Vector3(); +const _v1$1 = /*@__PURE__*/ new Vector3(); +const _normal$1 = /*@__PURE__*/ new Vector3(); +const _triangle = /*@__PURE__*/ new Triangle(); + +class EdgesGeometry extends BufferGeometry { + + constructor( geometry = null, thresholdAngle = 1 ) { + + super(); + + this.type = 'EdgesGeometry'; + + this.parameters = { + geometry: geometry, + thresholdAngle: thresholdAngle + }; + + if ( geometry !== null ) { + + const precisionPoints = 4; + const precision = Math.pow( 10, precisionPoints ); + const thresholdDot = Math.cos( DEG2RAD * thresholdAngle ); + + const indexAttr = geometry.getIndex(); + const positionAttr = geometry.getAttribute( 'position' ); + const indexCount = indexAttr ? indexAttr.count : positionAttr.count; + + const indexArr = [ 0, 0, 0 ]; + const vertKeys = [ 'a', 'b', 'c' ]; + const hashes = new Array( 3 ); + + const edgeData = {}; + const vertices = []; + for ( let i = 0; i < indexCount; i += 3 ) { + + if ( indexAttr ) { + + indexArr[ 0 ] = indexAttr.getX( i ); + indexArr[ 1 ] = indexAttr.getX( i + 1 ); + indexArr[ 2 ] = indexAttr.getX( i + 2 ); + + } else { + + indexArr[ 0 ] = i; + indexArr[ 1 ] = i + 1; + indexArr[ 2 ] = i + 2; + + } + + const { a, b, c } = _triangle; + a.fromBufferAttribute( positionAttr, indexArr[ 0 ] ); + b.fromBufferAttribute( positionAttr, indexArr[ 1 ] ); + c.fromBufferAttribute( positionAttr, indexArr[ 2 ] ); + _triangle.getNormal( _normal$1 ); + + // create hashes for the edge from the vertices + hashes[ 0 ] = `${ Math.round( a.x * precision ) },${ Math.round( a.y * precision ) },${ Math.round( a.z * precision ) }`; + hashes[ 1 ] = `${ Math.round( b.x * precision ) },${ Math.round( b.y * precision ) },${ Math.round( b.z * precision ) }`; + hashes[ 2 ] = `${ Math.round( c.x * precision ) },${ Math.round( c.y * precision ) },${ Math.round( c.z * precision ) }`; + + // skip degenerate triangles + if ( hashes[ 0 ] === hashes[ 1 ] || hashes[ 1 ] === hashes[ 2 ] || hashes[ 2 ] === hashes[ 0 ] ) { + + continue; + + } + + // iterate over every edge + for ( let j = 0; j < 3; j ++ ) { + + // get the first and next vertex making up the edge + const jNext = ( j + 1 ) % 3; + const vecHash0 = hashes[ j ]; + const vecHash1 = hashes[ jNext ]; + const v0 = _triangle[ vertKeys[ j ] ]; + const v1 = _triangle[ vertKeys[ jNext ] ]; + + const hash = `${ vecHash0 }_${ vecHash1 }`; + const reverseHash = `${ vecHash1 }_${ vecHash0 }`; + + if ( reverseHash in edgeData && edgeData[ reverseHash ] ) { + + // if we found a sibling edge add it into the vertex array if + // it meets the angle threshold and delete the edge from the map. + if ( _normal$1.dot( edgeData[ reverseHash ].normal ) <= thresholdDot ) { + + vertices.push( v0.x, v0.y, v0.z ); + vertices.push( v1.x, v1.y, v1.z ); + + } + + edgeData[ reverseHash ] = null; + + } else if ( ! ( hash in edgeData ) ) { + + // if we've already got an edge here then skip adding a new one + edgeData[ hash ] = { + + index0: indexArr[ j ], + index1: indexArr[ jNext ], + normal: _normal$1.clone(), + + }; + + } + + } + + } + + // iterate over all remaining, unmatched edges and add them to the vertex array + for ( const key in edgeData ) { + + if ( edgeData[ key ] ) { + + const { index0, index1 } = edgeData[ key ]; + _v0.fromBufferAttribute( positionAttr, index0 ); + _v1$1.fromBufferAttribute( positionAttr, index1 ); + + vertices.push( _v0.x, _v0.y, _v0.z ); + vertices.push( _v1$1.x, _v1$1.y, _v1$1.z ); + + } + + } + + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + + } + + } + + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + +} + +class Shape extends Path { + + constructor( points ) { + + super( points ); + + this.uuid = generateUUID(); + + this.type = 'Shape'; + + this.holes = []; + + } + + getPointsHoles( divisions ) { + + const holesPts = []; + + for ( let i = 0, l = this.holes.length; i < l; i ++ ) { + + holesPts[ i ] = this.holes[ i ].getPoints( divisions ); + + } + + return holesPts; + + } + + // get points of shape and holes (keypoints based on segments parameter) + + extractPoints( divisions ) { + + return { + + shape: this.getPoints( divisions ), + holes: this.getPointsHoles( divisions ) + + }; + + } + + copy( source ) { + + super.copy( source ); + + this.holes = []; + + for ( let i = 0, l = source.holes.length; i < l; i ++ ) { + + const hole = source.holes[ i ]; + + this.holes.push( hole.clone() ); + + } + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + data.uuid = this.uuid; + data.holes = []; + + for ( let i = 0, l = this.holes.length; i < l; i ++ ) { + + const hole = this.holes[ i ]; + data.holes.push( hole.toJSON() ); + + } + + return data; + + } + + fromJSON( json ) { + + super.fromJSON( json ); + + this.uuid = json.uuid; + this.holes = []; + + for ( let i = 0, l = json.holes.length; i < l; i ++ ) { + + const hole = json.holes[ i ]; + this.holes.push( new Path().fromJSON( hole ) ); + + } + + return this; + + } + +} + +/** + * Port from https://github.com/mapbox/earcut (v2.2.4) + */ + +const Earcut = { + + triangulate: function ( data, holeIndices, dim = 2 ) { + + const hasHoles = holeIndices && holeIndices.length; + const outerLen = hasHoles ? holeIndices[ 0 ] * dim : data.length; + let outerNode = linkedList( data, 0, outerLen, dim, true ); + const triangles = []; + + if ( ! outerNode || outerNode.next === outerNode.prev ) return triangles; + + let minX, minY, maxX, maxY, x, y, invSize; + + if ( hasHoles ) outerNode = eliminateHoles( data, holeIndices, outerNode, dim ); + + // if the shape is not too simple, we'll use z-order curve hash later; calculate polygon bbox + if ( data.length > 80 * dim ) { + + minX = maxX = data[ 0 ]; + minY = maxY = data[ 1 ]; + + for ( let i = dim; i < outerLen; i += dim ) { + + x = data[ i ]; + y = data[ i + 1 ]; + if ( x < minX ) minX = x; + if ( y < minY ) minY = y; + if ( x > maxX ) maxX = x; + if ( y > maxY ) maxY = y; + + } + + // minX, minY and invSize are later used to transform coords into integers for z-order calculation + invSize = Math.max( maxX - minX, maxY - minY ); + invSize = invSize !== 0 ? 32767 / invSize : 0; + + } + + earcutLinked( outerNode, triangles, dim, minX, minY, invSize, 0 ); + + return triangles; + + } + +}; + +// create a circular doubly linked list from polygon points in the specified winding order +function linkedList( data, start, end, dim, clockwise ) { + + let i, last; + + if ( clockwise === ( signedArea( data, start, end, dim ) > 0 ) ) { + + for ( i = start; i < end; i += dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last ); + + } else { + + for ( i = end - dim; i >= start; i -= dim ) last = insertNode( i, data[ i ], data[ i + 1 ], last ); + + } + + if ( last && equals$1( last, last.next ) ) { + + removeNode( last ); + last = last.next; + + } + + return last; + +} + +// eliminate colinear or duplicate points +function filterPoints( start, end ) { + + if ( ! start ) return start; + if ( ! end ) end = start; + + let p = start, + again; + do { + + again = false; + + if ( ! p.steiner && ( equals$1( p, p.next ) || area( p.prev, p, p.next ) === 0 ) ) { + + removeNode( p ); + p = end = p.prev; + if ( p === p.next ) break; + again = true; + + } else { + + p = p.next; + + } + + } while ( again || p !== end ); + + return end; + +} + +// main ear slicing loop which triangulates a polygon (given as a linked list) +function earcutLinked( ear, triangles, dim, minX, minY, invSize, pass ) { + + if ( ! ear ) return; + + // interlink polygon nodes in z-order + if ( ! pass && invSize ) indexCurve( ear, minX, minY, invSize ); + + let stop = ear, + prev, next; + + // iterate through ears, slicing them one by one + while ( ear.prev !== ear.next ) { + + prev = ear.prev; + next = ear.next; + + if ( invSize ? isEarHashed( ear, minX, minY, invSize ) : isEar( ear ) ) { + + // cut off the triangle + triangles.push( prev.i / dim | 0 ); + triangles.push( ear.i / dim | 0 ); + triangles.push( next.i / dim | 0 ); + + removeNode( ear ); + + // skipping the next vertex leads to less sliver triangles + ear = next.next; + stop = next.next; + + continue; + + } + + ear = next; + + // if we looped through the whole remaining polygon and can't find any more ears + if ( ear === stop ) { + + // try filtering points and slicing again + if ( ! pass ) { + + earcutLinked( filterPoints( ear ), triangles, dim, minX, minY, invSize, 1 ); + + // if this didn't work, try curing all small self-intersections locally + + } else if ( pass === 1 ) { + + ear = cureLocalIntersections( filterPoints( ear ), triangles, dim ); + earcutLinked( ear, triangles, dim, minX, minY, invSize, 2 ); + + // as a last resort, try splitting the remaining polygon into two + + } else if ( pass === 2 ) { + + splitEarcut( ear, triangles, dim, minX, minY, invSize ); + + } + + break; + + } + + } + +} + +// check whether a polygon node forms a valid ear with adjacent nodes +function isEar( ear ) { + + const a = ear.prev, + b = ear, + c = ear.next; + + if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear + + // now make sure we don't have other points inside the potential ear + const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y; + + // triangle bbox; min & max are calculated like this for speed + const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ), + y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ), + x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ), + y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy ); + + let p = c.next; + while ( p !== a ) { + + if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && + pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && + area( p.prev, p, p.next ) >= 0 ) return false; + p = p.next; + + } + + return true; + +} + +function isEarHashed( ear, minX, minY, invSize ) { + + const a = ear.prev, + b = ear, + c = ear.next; + + if ( area( a, b, c ) >= 0 ) return false; // reflex, can't be an ear + + const ax = a.x, bx = b.x, cx = c.x, ay = a.y, by = b.y, cy = c.y; + + // triangle bbox; min & max are calculated like this for speed + const x0 = ax < bx ? ( ax < cx ? ax : cx ) : ( bx < cx ? bx : cx ), + y0 = ay < by ? ( ay < cy ? ay : cy ) : ( by < cy ? by : cy ), + x1 = ax > bx ? ( ax > cx ? ax : cx ) : ( bx > cx ? bx : cx ), + y1 = ay > by ? ( ay > cy ? ay : cy ) : ( by > cy ? by : cy ); + + // z-order range for the current triangle bbox; + const minZ = zOrder( x0, y0, minX, minY, invSize ), + maxZ = zOrder( x1, y1, minX, minY, invSize ); + + let p = ear.prevZ, + n = ear.nextZ; + + // look for points inside the triangle in both directions + while ( p && p.z >= minZ && n && n.z <= maxZ ) { + + if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && + pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false; + p = p.prevZ; + + if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && + pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false; + n = n.nextZ; + + } + + // look for remaining points in decreasing z-order + while ( p && p.z >= minZ ) { + + if ( p.x >= x0 && p.x <= x1 && p.y >= y0 && p.y <= y1 && p !== a && p !== c && + pointInTriangle( ax, ay, bx, by, cx, cy, p.x, p.y ) && area( p.prev, p, p.next ) >= 0 ) return false; + p = p.prevZ; + + } + + // look for remaining points in increasing z-order + while ( n && n.z <= maxZ ) { + + if ( n.x >= x0 && n.x <= x1 && n.y >= y0 && n.y <= y1 && n !== a && n !== c && + pointInTriangle( ax, ay, bx, by, cx, cy, n.x, n.y ) && area( n.prev, n, n.next ) >= 0 ) return false; + n = n.nextZ; + + } + + return true; + +} + +// go through all polygon nodes and cure small local self-intersections +function cureLocalIntersections( start, triangles, dim ) { + + let p = start; + do { + + const a = p.prev, + b = p.next.next; + + if ( ! equals$1( a, b ) && intersects( a, p, p.next, b ) && locallyInside( a, b ) && locallyInside( b, a ) ) { + + triangles.push( a.i / dim | 0 ); + triangles.push( p.i / dim | 0 ); + triangles.push( b.i / dim | 0 ); + + // remove two nodes involved + removeNode( p ); + removeNode( p.next ); + + p = start = b; + + } + + p = p.next; + + } while ( p !== start ); + + return filterPoints( p ); + +} + +// try splitting polygon into two and triangulate them independently +function splitEarcut( start, triangles, dim, minX, minY, invSize ) { + + // look for a valid diagonal that divides the polygon into two + let a = start; + do { + + let b = a.next.next; + while ( b !== a.prev ) { + + if ( a.i !== b.i && isValidDiagonal( a, b ) ) { + + // split the polygon in two by the diagonal + let c = splitPolygon( a, b ); + + // filter colinear points around the cuts + a = filterPoints( a, a.next ); + c = filterPoints( c, c.next ); + + // run earcut on each half + earcutLinked( a, triangles, dim, minX, minY, invSize, 0 ); + earcutLinked( c, triangles, dim, minX, minY, invSize, 0 ); + return; + + } + + b = b.next; + + } + + a = a.next; + + } while ( a !== start ); + +} + +// link every hole into the outer loop, producing a single-ring polygon without holes +function eliminateHoles( data, holeIndices, outerNode, dim ) { + + const queue = []; + let i, len, start, end, list; + + for ( i = 0, len = holeIndices.length; i < len; i ++ ) { + + start = holeIndices[ i ] * dim; + end = i < len - 1 ? holeIndices[ i + 1 ] * dim : data.length; + list = linkedList( data, start, end, dim, false ); + if ( list === list.next ) list.steiner = true; + queue.push( getLeftmost( list ) ); + + } + + queue.sort( compareX ); + + // process holes from left to right + for ( i = 0; i < queue.length; i ++ ) { + + outerNode = eliminateHole( queue[ i ], outerNode ); + + } + + return outerNode; + +} + +function compareX( a, b ) { + + return a.x - b.x; + +} + +// find a bridge between vertices that connects hole with an outer ring and link it +function eliminateHole( hole, outerNode ) { + + const bridge = findHoleBridge( hole, outerNode ); + if ( ! bridge ) { + + return outerNode; + + } + + const bridgeReverse = splitPolygon( bridge, hole ); + + // filter collinear points around the cuts + filterPoints( bridgeReverse, bridgeReverse.next ); + return filterPoints( bridge, bridge.next ); + +} + +// David Eberly's algorithm for finding a bridge between hole and outer polygon +function findHoleBridge( hole, outerNode ) { + + let p = outerNode, + qx = - Infinity, + m; + + const hx = hole.x, hy = hole.y; + + // find a segment intersected by a ray from the hole's leftmost point to the left; + // segment's endpoint with lesser x will be potential connection point + do { + + if ( hy <= p.y && hy >= p.next.y && p.next.y !== p.y ) { + + const x = p.x + ( hy - p.y ) * ( p.next.x - p.x ) / ( p.next.y - p.y ); + if ( x <= hx && x > qx ) { + + qx = x; + m = p.x < p.next.x ? p : p.next; + if ( x === hx ) return m; // hole touches outer segment; pick leftmost endpoint + + } + + } + + p = p.next; + + } while ( p !== outerNode ); + + if ( ! m ) return null; + + // look for points inside the triangle of hole point, segment intersection and endpoint; + // if there are no points found, we have a valid connection; + // otherwise choose the point of the minimum angle with the ray as connection point + + const stop = m, + mx = m.x, + my = m.y; + let tanMin = Infinity, tan; + + p = m; + + do { + + if ( hx >= p.x && p.x >= mx && hx !== p.x && + pointInTriangle( hy < my ? hx : qx, hy, mx, my, hy < my ? qx : hx, hy, p.x, p.y ) ) { + + tan = Math.abs( hy - p.y ) / ( hx - p.x ); // tangential + + if ( locallyInside( p, hole ) && ( tan < tanMin || ( tan === tanMin && ( p.x > m.x || ( p.x === m.x && sectorContainsSector( m, p ) ) ) ) ) ) { + + m = p; + tanMin = tan; + + } + + } + + p = p.next; + + } while ( p !== stop ); + + return m; + +} + +// whether sector in vertex m contains sector in vertex p in the same coordinates +function sectorContainsSector( m, p ) { + + return area( m.prev, m, p.prev ) < 0 && area( p.next, m, m.next ) < 0; + +} + +// interlink polygon nodes in z-order +function indexCurve( start, minX, minY, invSize ) { + + let p = start; + do { + + if ( p.z === 0 ) p.z = zOrder( p.x, p.y, minX, minY, invSize ); + p.prevZ = p.prev; + p.nextZ = p.next; + p = p.next; + + } while ( p !== start ); + + p.prevZ.nextZ = null; + p.prevZ = null; + + sortLinked( p ); + +} + +// Simon Tatham's linked list merge sort algorithm +// http://www.chiark.greenend.org.uk/~sgtatham/algorithms/listsort.html +function sortLinked( list ) { + + let i, p, q, e, tail, numMerges, pSize, qSize, + inSize = 1; + + do { + + p = list; + list = null; + tail = null; + numMerges = 0; + + while ( p ) { + + numMerges ++; + q = p; + pSize = 0; + for ( i = 0; i < inSize; i ++ ) { + + pSize ++; + q = q.nextZ; + if ( ! q ) break; + + } + + qSize = inSize; + + while ( pSize > 0 || ( qSize > 0 && q ) ) { + + if ( pSize !== 0 && ( qSize === 0 || ! q || p.z <= q.z ) ) { + + e = p; + p = p.nextZ; + pSize --; + + } else { + + e = q; + q = q.nextZ; + qSize --; + + } + + if ( tail ) tail.nextZ = e; + else list = e; + + e.prevZ = tail; + tail = e; + + } + + p = q; + + } + + tail.nextZ = null; + inSize *= 2; + + } while ( numMerges > 1 ); + + return list; + +} + +// z-order of a point given coords and inverse of the longer side of data bbox +function zOrder( x, y, minX, minY, invSize ) { + + // coords are transformed into non-negative 15-bit integer range + x = ( x - minX ) * invSize | 0; + y = ( y - minY ) * invSize | 0; + + x = ( x | ( x << 8 ) ) & 0x00FF00FF; + x = ( x | ( x << 4 ) ) & 0x0F0F0F0F; + x = ( x | ( x << 2 ) ) & 0x33333333; + x = ( x | ( x << 1 ) ) & 0x55555555; + + y = ( y | ( y << 8 ) ) & 0x00FF00FF; + y = ( y | ( y << 4 ) ) & 0x0F0F0F0F; + y = ( y | ( y << 2 ) ) & 0x33333333; + y = ( y | ( y << 1 ) ) & 0x55555555; + + return x | ( y << 1 ); + +} + +// find the leftmost node of a polygon ring +function getLeftmost( start ) { + + let p = start, + leftmost = start; + do { + + if ( p.x < leftmost.x || ( p.x === leftmost.x && p.y < leftmost.y ) ) leftmost = p; + p = p.next; + + } while ( p !== start ); + + return leftmost; + +} + +// check if a point lies within a convex triangle +function pointInTriangle( ax, ay, bx, by, cx, cy, px, py ) { + + return ( cx - px ) * ( ay - py ) >= ( ax - px ) * ( cy - py ) && + ( ax - px ) * ( by - py ) >= ( bx - px ) * ( ay - py ) && + ( bx - px ) * ( cy - py ) >= ( cx - px ) * ( by - py ); + +} + +// check if a diagonal between two polygon nodes is valid (lies in polygon interior) +function isValidDiagonal( a, b ) { + + return a.next.i !== b.i && a.prev.i !== b.i && ! intersectsPolygon( a, b ) && // dones't intersect other edges + ( locallyInside( a, b ) && locallyInside( b, a ) && middleInside( a, b ) && // locally visible + ( area( a.prev, a, b.prev ) || area( a, b.prev, b ) ) || // does not create opposite-facing sectors + equals$1( a, b ) && area( a.prev, a, a.next ) > 0 && area( b.prev, b, b.next ) > 0 ); // special zero-length case + +} + +// signed area of a triangle +function area( p, q, r ) { + + return ( q.y - p.y ) * ( r.x - q.x ) - ( q.x - p.x ) * ( r.y - q.y ); + +} + +// check if two points are equal +function equals$1( p1, p2 ) { + + return p1.x === p2.x && p1.y === p2.y; + +} + +// check if two segments intersect +function intersects( p1, q1, p2, q2 ) { + + const o1 = sign$1( area( p1, q1, p2 ) ); + const o2 = sign$1( area( p1, q1, q2 ) ); + const o3 = sign$1( area( p2, q2, p1 ) ); + const o4 = sign$1( area( p2, q2, q1 ) ); + + if ( o1 !== o2 && o3 !== o4 ) return true; // general case + + if ( o1 === 0 && onSegment( p1, p2, q1 ) ) return true; // p1, q1 and p2 are collinear and p2 lies on p1q1 + if ( o2 === 0 && onSegment( p1, q2, q1 ) ) return true; // p1, q1 and q2 are collinear and q2 lies on p1q1 + if ( o3 === 0 && onSegment( p2, p1, q2 ) ) return true; // p2, q2 and p1 are collinear and p1 lies on p2q2 + if ( o4 === 0 && onSegment( p2, q1, q2 ) ) return true; // p2, q2 and q1 are collinear and q1 lies on p2q2 + + return false; + +} + +// for collinear points p, q, r, check if point q lies on segment pr +function onSegment( p, q, r ) { + + return q.x <= Math.max( p.x, r.x ) && q.x >= Math.min( p.x, r.x ) && q.y <= Math.max( p.y, r.y ) && q.y >= Math.min( p.y, r.y ); + +} + +function sign$1( num ) { + + return num > 0 ? 1 : num < 0 ? - 1 : 0; + +} + +// check if a polygon diagonal intersects any polygon segments +function intersectsPolygon( a, b ) { + + let p = a; + do { + + if ( p.i !== a.i && p.next.i !== a.i && p.i !== b.i && p.next.i !== b.i && + intersects( p, p.next, a, b ) ) return true; + p = p.next; + + } while ( p !== a ); + + return false; + +} + +// check if a polygon diagonal is locally inside the polygon +function locallyInside( a, b ) { + + return area( a.prev, a, a.next ) < 0 ? + area( a, b, a.next ) >= 0 && area( a, a.prev, b ) >= 0 : + area( a, b, a.prev ) < 0 || area( a, a.next, b ) < 0; + +} + +// check if the middle point of a polygon diagonal is inside the polygon +function middleInside( a, b ) { + + let p = a, + inside = false; + const px = ( a.x + b.x ) / 2, + py = ( a.y + b.y ) / 2; + do { + + if ( ( ( p.y > py ) !== ( p.next.y > py ) ) && p.next.y !== p.y && + ( px < ( p.next.x - p.x ) * ( py - p.y ) / ( p.next.y - p.y ) + p.x ) ) + inside = ! inside; + p = p.next; + + } while ( p !== a ); + + return inside; + +} + +// link two polygon vertices with a bridge; if the vertices belong to the same ring, it splits polygon into two; +// if one belongs to the outer ring and another to a hole, it merges it into a single ring +function splitPolygon( a, b ) { + + const a2 = new Node$1( a.i, a.x, a.y ), + b2 = new Node$1( b.i, b.x, b.y ), + an = a.next, + bp = b.prev; + + a.next = b; + b.prev = a; + + a2.next = an; + an.prev = a2; + + b2.next = a2; + a2.prev = b2; + + bp.next = b2; + b2.prev = bp; + + return b2; + +} + +// create a node and optionally link it with previous one (in a circular doubly linked list) +function insertNode( i, x, y, last ) { + + const p = new Node$1( i, x, y ); + + if ( ! last ) { + + p.prev = p; + p.next = p; + + } else { + + p.next = last.next; + p.prev = last; + last.next.prev = p; + last.next = p; + + } + + return p; + +} + +function removeNode( p ) { + + p.next.prev = p.prev; + p.prev.next = p.next; + + if ( p.prevZ ) p.prevZ.nextZ = p.nextZ; + if ( p.nextZ ) p.nextZ.prevZ = p.prevZ; + +} + +function Node$1( i, x, y ) { + + // vertex index in coordinates array + this.i = i; + + // vertex coordinates + this.x = x; + this.y = y; + + // previous and next vertex nodes in a polygon ring + this.prev = null; + this.next = null; + + // z-order curve value + this.z = 0; + + // previous and next nodes in z-order + this.prevZ = null; + this.nextZ = null; + + // indicates whether this is a steiner point + this.steiner = false; + +} + +function signedArea( data, start, end, dim ) { + + let sum = 0; + for ( let i = start, j = end - dim; i < end; i += dim ) { + + sum += ( data[ j ] - data[ i ] ) * ( data[ i + 1 ] + data[ j + 1 ] ); + j = i; + + } + + return sum; + +} + +class ShapeUtils { + + // calculate area of the contour polygon + + static area( contour ) { + + const n = contour.length; + let a = 0.0; + + for ( let p = n - 1, q = 0; q < n; p = q ++ ) { + + a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y; + + } + + return a * 0.5; + + } + + static isClockWise( pts ) { + + return ShapeUtils.area( pts ) < 0; + + } + + static triangulateShape( contour, holes ) { + + const vertices = []; // flat array of vertices like [ x0,y0, x1,y1, x2,y2, ... ] + const holeIndices = []; // array of hole indices + const faces = []; // final array of vertex indices like [ [ a,b,d ], [ b,c,d ] ] + + removeDupEndPts( contour ); + addContour( vertices, contour ); + + // + + let holeIndex = contour.length; + + holes.forEach( removeDupEndPts ); + + for ( let i = 0; i < holes.length; i ++ ) { + + holeIndices.push( holeIndex ); + holeIndex += holes[ i ].length; + addContour( vertices, holes[ i ] ); + + } + + // + + const triangles = Earcut.triangulate( vertices, holeIndices ); + + // + + for ( let i = 0; i < triangles.length; i += 3 ) { + + faces.push( triangles.slice( i, i + 3 ) ); + + } + + return faces; + + } + +} + +function removeDupEndPts( points ) { + + const l = points.length; + + if ( l > 2 && points[ l - 1 ].equals( points[ 0 ] ) ) { + + points.pop(); + + } + +} + +function addContour( vertices, contour ) { + + for ( let i = 0; i < contour.length; i ++ ) { + + vertices.push( contour[ i ].x ); + vertices.push( contour[ i ].y ); + + } + +} + +/** + * Creates extruded geometry from a path shape. + * + * parameters = { + * + * curveSegments: , // number of points on the curves + * steps: , // number of points for z-side extrusions / used for subdividing segments of extrude spline too + * depth: , // Depth to extrude the shape + * + * bevelEnabled: , // turn on bevel + * bevelThickness: , // how deep into the original shape bevel goes + * bevelSize: , // how far from shape outline (including bevelOffset) is bevel + * bevelOffset: , // how far from shape outline does bevel start + * bevelSegments: , // number of bevel layers + * + * extrudePath: // curve to extrude shape along + * + * UVGenerator: // object that provides UV generator functions + * + * } + */ + + +class ExtrudeGeometry extends BufferGeometry { + + constructor( shapes = new Shape( [ new Vector2( 0.5, 0.5 ), new Vector2( - 0.5, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), options = {} ) { + + super(); + + this.type = 'ExtrudeGeometry'; + + this.parameters = { + shapes: shapes, + options: options + }; + + shapes = Array.isArray( shapes ) ? shapes : [ shapes ]; + + const scope = this; + + const verticesArray = []; + const uvArray = []; + + for ( let i = 0, l = shapes.length; i < l; i ++ ) { + + const shape = shapes[ i ]; + addShape( shape ); + + } + + // build geometry + + this.setAttribute( 'position', new Float32BufferAttribute( verticesArray, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvArray, 2 ) ); + + this.computeVertexNormals(); + + // functions + + function addShape( shape ) { + + const placeholder = []; + + // options + + const curveSegments = options.curveSegments !== undefined ? options.curveSegments : 12; + const steps = options.steps !== undefined ? options.steps : 1; + const depth = options.depth !== undefined ? options.depth : 1; + + let bevelEnabled = options.bevelEnabled !== undefined ? options.bevelEnabled : true; + let bevelThickness = options.bevelThickness !== undefined ? options.bevelThickness : 0.2; + let bevelSize = options.bevelSize !== undefined ? options.bevelSize : bevelThickness - 0.1; + let bevelOffset = options.bevelOffset !== undefined ? options.bevelOffset : 0; + let bevelSegments = options.bevelSegments !== undefined ? options.bevelSegments : 3; + + const extrudePath = options.extrudePath; + + const uvgen = options.UVGenerator !== undefined ? options.UVGenerator : WorldUVGenerator; + + // + + let extrudePts, extrudeByPath = false; + let splineTube, binormal, normal, position2; + + if ( extrudePath ) { + + extrudePts = extrudePath.getSpacedPoints( steps ); + + extrudeByPath = true; + bevelEnabled = false; // bevels not supported for path extrusion + + // SETUP TNB variables + + // TODO1 - have a .isClosed in spline? + + splineTube = extrudePath.computeFrenetFrames( steps, false ); + + // console.log(splineTube, 'splineTube', splineTube.normals.length, 'steps', steps, 'extrudePts', extrudePts.length); + + binormal = new Vector3(); + normal = new Vector3(); + position2 = new Vector3(); + + } + + // Safeguards if bevels are not enabled + + if ( ! bevelEnabled ) { + + bevelSegments = 0; + bevelThickness = 0; + bevelSize = 0; + bevelOffset = 0; + + } + + // Variables initialization + + const shapePoints = shape.extractPoints( curveSegments ); + + let vertices = shapePoints.shape; + const holes = shapePoints.holes; + + const reverse = ! ShapeUtils.isClockWise( vertices ); + + if ( reverse ) { + + vertices = vertices.reverse(); + + // Maybe we should also check if holes are in the opposite direction, just to be safe ... + + for ( let h = 0, hl = holes.length; h < hl; h ++ ) { + + const ahole = holes[ h ]; + + if ( ShapeUtils.isClockWise( ahole ) ) { + + holes[ h ] = ahole.reverse(); + + } + + } + + } + + + const faces = ShapeUtils.triangulateShape( vertices, holes ); + + /* Vertices */ + + const contour = vertices; // vertices has all points but contour has only points of circumference + + for ( let h = 0, hl = holes.length; h < hl; h ++ ) { + + const ahole = holes[ h ]; + + vertices = vertices.concat( ahole ); + + } + + + function scalePt2( pt, vec, size ) { + + if ( ! vec ) console.error( 'THREE.ExtrudeGeometry: vec does not exist' ); + + return pt.clone().addScaledVector( vec, size ); + + } + + const vlen = vertices.length, flen = faces.length; + + + // Find directions for point movement + + + function getBevelVec( inPt, inPrev, inNext ) { + + // computes for inPt the corresponding point inPt' on a new contour + // shifted by 1 unit (length of normalized vector) to the left + // if we walk along contour clockwise, this new contour is outside the old one + // + // inPt' is the intersection of the two lines parallel to the two + // adjacent edges of inPt at a distance of 1 unit on the left side. + + let v_trans_x, v_trans_y, shrink_by; // resulting translation vector for inPt + + // good reading for geometry algorithms (here: line-line intersection) + // http://geomalgorithms.com/a05-_intersect-1.html + + const v_prev_x = inPt.x - inPrev.x, + v_prev_y = inPt.y - inPrev.y; + const v_next_x = inNext.x - inPt.x, + v_next_y = inNext.y - inPt.y; + + const v_prev_lensq = ( v_prev_x * v_prev_x + v_prev_y * v_prev_y ); + + // check for collinear edges + const collinear0 = ( v_prev_x * v_next_y - v_prev_y * v_next_x ); + + if ( Math.abs( collinear0 ) > Number.EPSILON ) { + + // not collinear + + // length of vectors for normalizing + + const v_prev_len = Math.sqrt( v_prev_lensq ); + const v_next_len = Math.sqrt( v_next_x * v_next_x + v_next_y * v_next_y ); + + // shift adjacent points by unit vectors to the left + + const ptPrevShift_x = ( inPrev.x - v_prev_y / v_prev_len ); + const ptPrevShift_y = ( inPrev.y + v_prev_x / v_prev_len ); + + const ptNextShift_x = ( inNext.x - v_next_y / v_next_len ); + const ptNextShift_y = ( inNext.y + v_next_x / v_next_len ); + + // scaling factor for v_prev to intersection point + + const sf = ( ( ptNextShift_x - ptPrevShift_x ) * v_next_y - + ( ptNextShift_y - ptPrevShift_y ) * v_next_x ) / + ( v_prev_x * v_next_y - v_prev_y * v_next_x ); + + // vector from inPt to intersection point + + v_trans_x = ( ptPrevShift_x + v_prev_x * sf - inPt.x ); + v_trans_y = ( ptPrevShift_y + v_prev_y * sf - inPt.y ); + + // Don't normalize!, otherwise sharp corners become ugly + // but prevent crazy spikes + const v_trans_lensq = ( v_trans_x * v_trans_x + v_trans_y * v_trans_y ); + if ( v_trans_lensq <= 2 ) { + + return new Vector2( v_trans_x, v_trans_y ); + + } else { + + shrink_by = Math.sqrt( v_trans_lensq / 2 ); + + } + + } else { + + // handle special case of collinear edges + + let direction_eq = false; // assumes: opposite + + if ( v_prev_x > Number.EPSILON ) { + + if ( v_next_x > Number.EPSILON ) { + + direction_eq = true; + + } + + } else { + + if ( v_prev_x < - Number.EPSILON ) { + + if ( v_next_x < - Number.EPSILON ) { + + direction_eq = true; + + } + + } else { + + if ( Math.sign( v_prev_y ) === Math.sign( v_next_y ) ) { + + direction_eq = true; + + } + + } + + } + + if ( direction_eq ) { + + // console.log("Warning: lines are a straight sequence"); + v_trans_x = - v_prev_y; + v_trans_y = v_prev_x; + shrink_by = Math.sqrt( v_prev_lensq ); + + } else { + + // console.log("Warning: lines are a straight spike"); + v_trans_x = v_prev_x; + v_trans_y = v_prev_y; + shrink_by = Math.sqrt( v_prev_lensq / 2 ); + + } + + } + + return new Vector2( v_trans_x / shrink_by, v_trans_y / shrink_by ); + + } + + + const contourMovements = []; + + for ( let i = 0, il = contour.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { + + if ( j === il ) j = 0; + if ( k === il ) k = 0; + + // (j)---(i)---(k) + // console.log('i,j,k', i, j , k) + + contourMovements[ i ] = getBevelVec( contour[ i ], contour[ j ], contour[ k ] ); + + } + + const holesMovements = []; + let oneHoleMovements, verticesMovements = contourMovements.concat(); + + for ( let h = 0, hl = holes.length; h < hl; h ++ ) { + + const ahole = holes[ h ]; + + oneHoleMovements = []; + + for ( let i = 0, il = ahole.length, j = il - 1, k = i + 1; i < il; i ++, j ++, k ++ ) { + + if ( j === il ) j = 0; + if ( k === il ) k = 0; + + // (j)---(i)---(k) + oneHoleMovements[ i ] = getBevelVec( ahole[ i ], ahole[ j ], ahole[ k ] ); + + } + + holesMovements.push( oneHoleMovements ); + verticesMovements = verticesMovements.concat( oneHoleMovements ); + + } + + + // Loop bevelSegments, 1 for the front, 1 for the back + + for ( let b = 0; b < bevelSegments; b ++ ) { + + //for ( b = bevelSegments; b > 0; b -- ) { + + const t = b / bevelSegments; + const z = bevelThickness * Math.cos( t * Math.PI / 2 ); + const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset; + + // contract shape + + for ( let i = 0, il = contour.length; i < il; i ++ ) { + + const vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); + + v( vert.x, vert.y, - z ); + + } + + // expand holes + + for ( let h = 0, hl = holes.length; h < hl; h ++ ) { + + const ahole = holes[ h ]; + oneHoleMovements = holesMovements[ h ]; + + for ( let i = 0, il = ahole.length; i < il; i ++ ) { + + const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); + + v( vert.x, vert.y, - z ); + + } + + } + + } + + const bs = bevelSize + bevelOffset; + + // Back facing vertices + + for ( let i = 0; i < vlen; i ++ ) { + + const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; + + if ( ! extrudeByPath ) { + + v( vert.x, vert.y, 0 ); + + } else { + + // v( vert.x, vert.y + extrudePts[ 0 ].y, extrudePts[ 0 ].x ); + + normal.copy( splineTube.normals[ 0 ] ).multiplyScalar( vert.x ); + binormal.copy( splineTube.binormals[ 0 ] ).multiplyScalar( vert.y ); + + position2.copy( extrudePts[ 0 ] ).add( normal ).add( binormal ); + + v( position2.x, position2.y, position2.z ); + + } + + } + + // Add stepped vertices... + // Including front facing vertices + + for ( let s = 1; s <= steps; s ++ ) { + + for ( let i = 0; i < vlen; i ++ ) { + + const vert = bevelEnabled ? scalePt2( vertices[ i ], verticesMovements[ i ], bs ) : vertices[ i ]; + + if ( ! extrudeByPath ) { + + v( vert.x, vert.y, depth / steps * s ); + + } else { + + // v( vert.x, vert.y + extrudePts[ s - 1 ].y, extrudePts[ s - 1 ].x ); + + normal.copy( splineTube.normals[ s ] ).multiplyScalar( vert.x ); + binormal.copy( splineTube.binormals[ s ] ).multiplyScalar( vert.y ); + + position2.copy( extrudePts[ s ] ).add( normal ).add( binormal ); + + v( position2.x, position2.y, position2.z ); + + } + + } + + } + + + // Add bevel segments planes + + //for ( b = 1; b <= bevelSegments; b ++ ) { + for ( let b = bevelSegments - 1; b >= 0; b -- ) { + + const t = b / bevelSegments; + const z = bevelThickness * Math.cos( t * Math.PI / 2 ); + const bs = bevelSize * Math.sin( t * Math.PI / 2 ) + bevelOffset; + + // contract shape + + for ( let i = 0, il = contour.length; i < il; i ++ ) { + + const vert = scalePt2( contour[ i ], contourMovements[ i ], bs ); + v( vert.x, vert.y, depth + z ); + + } + + // expand holes + + for ( let h = 0, hl = holes.length; h < hl; h ++ ) { + + const ahole = holes[ h ]; + oneHoleMovements = holesMovements[ h ]; + + for ( let i = 0, il = ahole.length; i < il; i ++ ) { + + const vert = scalePt2( ahole[ i ], oneHoleMovements[ i ], bs ); + + if ( ! extrudeByPath ) { + + v( vert.x, vert.y, depth + z ); + + } else { + + v( vert.x, vert.y + extrudePts[ steps - 1 ].y, extrudePts[ steps - 1 ].x + z ); + + } + + } + + } + + } + + /* Faces */ + + // Top and bottom faces + + buildLidFaces(); + + // Sides faces + + buildSideFaces(); + + + ///// Internal functions + + function buildLidFaces() { + + const start = verticesArray.length / 3; + + if ( bevelEnabled ) { + + let layer = 0; // steps + 1 + let offset = vlen * layer; + + // Bottom faces + + for ( let i = 0; i < flen; i ++ ) { + + const face = faces[ i ]; + f3( face[ 2 ] + offset, face[ 1 ] + offset, face[ 0 ] + offset ); + + } + + layer = steps + bevelSegments * 2; + offset = vlen * layer; + + // Top faces + + for ( let i = 0; i < flen; i ++ ) { + + const face = faces[ i ]; + f3( face[ 0 ] + offset, face[ 1 ] + offset, face[ 2 ] + offset ); + + } + + } else { + + // Bottom faces + + for ( let i = 0; i < flen; i ++ ) { + + const face = faces[ i ]; + f3( face[ 2 ], face[ 1 ], face[ 0 ] ); + + } + + // Top faces + + for ( let i = 0; i < flen; i ++ ) { + + const face = faces[ i ]; + f3( face[ 0 ] + vlen * steps, face[ 1 ] + vlen * steps, face[ 2 ] + vlen * steps ); + + } + + } + + scope.addGroup( start, verticesArray.length / 3 - start, 0 ); + + } + + // Create faces for the z-sides of the shape + + function buildSideFaces() { + + const start = verticesArray.length / 3; + let layeroffset = 0; + sidewalls( contour, layeroffset ); + layeroffset += contour.length; + + for ( let h = 0, hl = holes.length; h < hl; h ++ ) { + + const ahole = holes[ h ]; + sidewalls( ahole, layeroffset ); + + //, true + layeroffset += ahole.length; + + } + + + scope.addGroup( start, verticesArray.length / 3 - start, 1 ); + + + } + + function sidewalls( contour, layeroffset ) { + + let i = contour.length; + + while ( -- i >= 0 ) { + + const j = i; + let k = i - 1; + if ( k < 0 ) k = contour.length - 1; + + //console.log('b', i,j, i-1, k,vertices.length); + + for ( let s = 0, sl = ( steps + bevelSegments * 2 ); s < sl; s ++ ) { + + const slen1 = vlen * s; + const slen2 = vlen * ( s + 1 ); + + const a = layeroffset + j + slen1, + b = layeroffset + k + slen1, + c = layeroffset + k + slen2, + d = layeroffset + j + slen2; + + f4( a, b, c, d ); + + } + + } + + } + + function v( x, y, z ) { + + placeholder.push( x ); + placeholder.push( y ); + placeholder.push( z ); + + } + + + function f3( a, b, c ) { + + addVertex( a ); + addVertex( b ); + addVertex( c ); + + const nextIndex = verticesArray.length / 3; + const uvs = uvgen.generateTopUV( scope, verticesArray, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); + + addUV( uvs[ 0 ] ); + addUV( uvs[ 1 ] ); + addUV( uvs[ 2 ] ); + + } + + function f4( a, b, c, d ) { + + addVertex( a ); + addVertex( b ); + addVertex( d ); + + addVertex( b ); + addVertex( c ); + addVertex( d ); + + + const nextIndex = verticesArray.length / 3; + const uvs = uvgen.generateSideWallUV( scope, verticesArray, nextIndex - 6, nextIndex - 3, nextIndex - 2, nextIndex - 1 ); + + addUV( uvs[ 0 ] ); + addUV( uvs[ 1 ] ); + addUV( uvs[ 3 ] ); + + addUV( uvs[ 1 ] ); + addUV( uvs[ 2 ] ); + addUV( uvs[ 3 ] ); + + } + + function addVertex( index ) { + + verticesArray.push( placeholder[ index * 3 + 0 ] ); + verticesArray.push( placeholder[ index * 3 + 1 ] ); + verticesArray.push( placeholder[ index * 3 + 2 ] ); + + } + + + function addUV( vector2 ) { + + uvArray.push( vector2.x ); + uvArray.push( vector2.y ); + + } + + } + + } + + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + const shapes = this.parameters.shapes; + const options = this.parameters.options; + + return toJSON$1( shapes, options, data ); + + } + + static fromJSON( data, shapes ) { + + const geometryShapes = []; + + for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) { + + const shape = shapes[ data.shapes[ j ] ]; + + geometryShapes.push( shape ); + + } + + const extrudePath = data.options.extrudePath; + + if ( extrudePath !== undefined ) { + + data.options.extrudePath = new Curves[ extrudePath.type ]().fromJSON( extrudePath ); + + } + + return new ExtrudeGeometry( geometryShapes, data.options ); + + } + +} + +const WorldUVGenerator = { + + generateTopUV: function ( geometry, vertices, indexA, indexB, indexC ) { + + const a_x = vertices[ indexA * 3 ]; + const a_y = vertices[ indexA * 3 + 1 ]; + const b_x = vertices[ indexB * 3 ]; + const b_y = vertices[ indexB * 3 + 1 ]; + const c_x = vertices[ indexC * 3 ]; + const c_y = vertices[ indexC * 3 + 1 ]; + + return [ + new Vector2( a_x, a_y ), + new Vector2( b_x, b_y ), + new Vector2( c_x, c_y ) + ]; + + }, + + generateSideWallUV: function ( geometry, vertices, indexA, indexB, indexC, indexD ) { + + const a_x = vertices[ indexA * 3 ]; + const a_y = vertices[ indexA * 3 + 1 ]; + const a_z = vertices[ indexA * 3 + 2 ]; + const b_x = vertices[ indexB * 3 ]; + const b_y = vertices[ indexB * 3 + 1 ]; + const b_z = vertices[ indexB * 3 + 2 ]; + const c_x = vertices[ indexC * 3 ]; + const c_y = vertices[ indexC * 3 + 1 ]; + const c_z = vertices[ indexC * 3 + 2 ]; + const d_x = vertices[ indexD * 3 ]; + const d_y = vertices[ indexD * 3 + 1 ]; + const d_z = vertices[ indexD * 3 + 2 ]; + + if ( Math.abs( a_y - b_y ) < Math.abs( a_x - b_x ) ) { + + return [ + new Vector2( a_x, 1 - a_z ), + new Vector2( b_x, 1 - b_z ), + new Vector2( c_x, 1 - c_z ), + new Vector2( d_x, 1 - d_z ) + ]; + + } else { + + return [ + new Vector2( a_y, 1 - a_z ), + new Vector2( b_y, 1 - b_z ), + new Vector2( c_y, 1 - c_z ), + new Vector2( d_y, 1 - d_z ) + ]; + + } + + } + +}; + +function toJSON$1( shapes, options, data ) { + + data.shapes = []; + + if ( Array.isArray( shapes ) ) { + + for ( let i = 0, l = shapes.length; i < l; i ++ ) { + + const shape = shapes[ i ]; + + data.shapes.push( shape.uuid ); + + } + + } else { + + data.shapes.push( shapes.uuid ); + + } + + data.options = Object.assign( {}, options ); + + if ( options.extrudePath !== undefined ) data.options.extrudePath = options.extrudePath.toJSON(); + + return data; + +} + +class IcosahedronGeometry extends PolyhedronGeometry { + + constructor( radius = 1, detail = 0 ) { + + const t = ( 1 + Math.sqrt( 5 ) ) / 2; + + const vertices = [ + - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, 0, + 0, - 1, t, 0, 1, t, 0, - 1, - t, 0, 1, - t, + t, 0, - 1, t, 0, 1, - t, 0, - 1, - t, 0, 1 + ]; + + const indices = [ + 0, 11, 5, 0, 5, 1, 0, 1, 7, 0, 7, 10, 0, 10, 11, + 1, 5, 9, 5, 11, 4, 11, 10, 2, 10, 7, 6, 7, 1, 8, + 3, 9, 4, 3, 4, 2, 3, 2, 6, 3, 6, 8, 3, 8, 9, + 4, 9, 5, 2, 4, 11, 6, 2, 10, 8, 6, 7, 9, 8, 1 + ]; + + super( vertices, indices, radius, detail ); + + this.type = 'IcosahedronGeometry'; + + this.parameters = { + radius: radius, + detail: detail + }; + + } + + static fromJSON( data ) { + + return new IcosahedronGeometry( data.radius, data.detail ); + + } + +} + +class OctahedronGeometry extends PolyhedronGeometry { + + constructor( radius = 1, detail = 0 ) { + + const vertices = [ + 1, 0, 0, - 1, 0, 0, 0, 1, 0, + 0, - 1, 0, 0, 0, 1, 0, 0, - 1 + ]; + + const indices = [ + 0, 2, 4, 0, 4, 3, 0, 3, 5, + 0, 5, 2, 1, 2, 5, 1, 5, 3, + 1, 3, 4, 1, 4, 2 + ]; + + super( vertices, indices, radius, detail ); + + this.type = 'OctahedronGeometry'; + + this.parameters = { + radius: radius, + detail: detail + }; + + } + + static fromJSON( data ) { + + return new OctahedronGeometry( data.radius, data.detail ); + + } + +} + +class PlaneGeometry extends BufferGeometry { + + constructor( width = 1, height = 1, widthSegments = 1, heightSegments = 1 ) { + + super(); + + this.type = 'PlaneGeometry'; + + this.parameters = { + width: width, + height: height, + widthSegments: widthSegments, + heightSegments: heightSegments + }; + + const width_half = width / 2; + const height_half = height / 2; + + const gridX = Math.floor( widthSegments ); + const gridY = Math.floor( heightSegments ); + + const gridX1 = gridX + 1; + const gridY1 = gridY + 1; + + const segment_width = width / gridX; + const segment_height = height / gridY; + + // + + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + + for ( let iy = 0; iy < gridY1; iy ++ ) { + + const y = iy * segment_height - height_half; + + for ( let ix = 0; ix < gridX1; ix ++ ) { + + const x = ix * segment_width - width_half; + + vertices.push( x, - y, 0 ); + + normals.push( 0, 0, 1 ); + + uvs.push( ix / gridX ); + uvs.push( 1 - ( iy / gridY ) ); + + } + + } + + for ( let iy = 0; iy < gridY; iy ++ ) { + + for ( let ix = 0; ix < gridX; ix ++ ) { + + const a = ix + gridX1 * iy; + const b = ix + gridX1 * ( iy + 1 ); + const c = ( ix + 1 ) + gridX1 * ( iy + 1 ); + const d = ( ix + 1 ) + gridX1 * iy; + + indices.push( a, b, d ); + indices.push( b, c, d ); + + } + + } + + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + + } + + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + + static fromJSON( data ) { + + return new PlaneGeometry( data.width, data.height, data.widthSegments, data.heightSegments ); + + } + +} + +class RingGeometry extends BufferGeometry { + + constructor( innerRadius = 0.5, outerRadius = 1, thetaSegments = 32, phiSegments = 1, thetaStart = 0, thetaLength = Math.PI * 2 ) { + + super(); + + this.type = 'RingGeometry'; + + this.parameters = { + innerRadius: innerRadius, + outerRadius: outerRadius, + thetaSegments: thetaSegments, + phiSegments: phiSegments, + thetaStart: thetaStart, + thetaLength: thetaLength + }; + + thetaSegments = Math.max( 3, thetaSegments ); + phiSegments = Math.max( 1, phiSegments ); + + // buffers + + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + + // some helper variables + + let radius = innerRadius; + const radiusStep = ( ( outerRadius - innerRadius ) / phiSegments ); + const vertex = new Vector3(); + const uv = new Vector2(); + + // generate vertices, normals and uvs + + for ( let j = 0; j <= phiSegments; j ++ ) { + + for ( let i = 0; i <= thetaSegments; i ++ ) { + + // values are generate from the inside of the ring to the outside + + const segment = thetaStart + i / thetaSegments * thetaLength; + + // vertex + + vertex.x = radius * Math.cos( segment ); + vertex.y = radius * Math.sin( segment ); + + vertices.push( vertex.x, vertex.y, vertex.z ); + + // normal + + normals.push( 0, 0, 1 ); + + // uv + + uv.x = ( vertex.x / outerRadius + 1 ) / 2; + uv.y = ( vertex.y / outerRadius + 1 ) / 2; + + uvs.push( uv.x, uv.y ); + + } + + // increase the radius for next row of vertices + + radius += radiusStep; + + } + + // indices + + for ( let j = 0; j < phiSegments; j ++ ) { + + const thetaSegmentLevel = j * ( thetaSegments + 1 ); + + for ( let i = 0; i < thetaSegments; i ++ ) { + + const segment = i + thetaSegmentLevel; + + const a = segment; + const b = segment + thetaSegments + 1; + const c = segment + thetaSegments + 2; + const d = segment + 1; + + // faces + + indices.push( a, b, d ); + indices.push( b, c, d ); + + } + + } + + // build geometry + + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + + } + + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + + static fromJSON( data ) { + + return new RingGeometry( data.innerRadius, data.outerRadius, data.thetaSegments, data.phiSegments, data.thetaStart, data.thetaLength ); + + } + +} + +class ShapeGeometry extends BufferGeometry { + + constructor( shapes = new Shape( [ new Vector2( 0, 0.5 ), new Vector2( - 0.5, - 0.5 ), new Vector2( 0.5, - 0.5 ) ] ), curveSegments = 12 ) { + + super(); + + this.type = 'ShapeGeometry'; + + this.parameters = { + shapes: shapes, + curveSegments: curveSegments + }; + + // buffers + + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + + // helper variables + + let groupStart = 0; + let groupCount = 0; + + // allow single and array values for "shapes" parameter + + if ( Array.isArray( shapes ) === false ) { + + addShape( shapes ); + + } else { + + for ( let i = 0; i < shapes.length; i ++ ) { + + addShape( shapes[ i ] ); + + this.addGroup( groupStart, groupCount, i ); // enables MultiMaterial support + + groupStart += groupCount; + groupCount = 0; + + } + + } + + // build geometry + + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + + + // helper functions + + function addShape( shape ) { + + const indexOffset = vertices.length / 3; + const points = shape.extractPoints( curveSegments ); + + let shapeVertices = points.shape; + const shapeHoles = points.holes; + + // check direction of vertices + + if ( ShapeUtils.isClockWise( shapeVertices ) === false ) { + + shapeVertices = shapeVertices.reverse(); + + } + + for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) { + + const shapeHole = shapeHoles[ i ]; + + if ( ShapeUtils.isClockWise( shapeHole ) === true ) { + + shapeHoles[ i ] = shapeHole.reverse(); + + } + + } + + const faces = ShapeUtils.triangulateShape( shapeVertices, shapeHoles ); + + // join vertices of inner and outer paths to a single array + + for ( let i = 0, l = shapeHoles.length; i < l; i ++ ) { + + const shapeHole = shapeHoles[ i ]; + shapeVertices = shapeVertices.concat( shapeHole ); + + } + + // vertices, normals, uvs + + for ( let i = 0, l = shapeVertices.length; i < l; i ++ ) { + + const vertex = shapeVertices[ i ]; + + vertices.push( vertex.x, vertex.y, 0 ); + normals.push( 0, 0, 1 ); + uvs.push( vertex.x, vertex.y ); // world uvs + + } + + // indices + + for ( let i = 0, l = faces.length; i < l; i ++ ) { + + const face = faces[ i ]; + + const a = face[ 0 ] + indexOffset; + const b = face[ 1 ] + indexOffset; + const c = face[ 2 ] + indexOffset; + + indices.push( a, b, c ); + groupCount += 3; + + } + + } + + } + + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + const shapes = this.parameters.shapes; + + return toJSON( shapes, data ); + + } + + static fromJSON( data, shapes ) { + + const geometryShapes = []; + + for ( let j = 0, jl = data.shapes.length; j < jl; j ++ ) { + + const shape = shapes[ data.shapes[ j ] ]; + + geometryShapes.push( shape ); + + } + + return new ShapeGeometry( geometryShapes, data.curveSegments ); + + } + +} + +function toJSON( shapes, data ) { + + data.shapes = []; + + if ( Array.isArray( shapes ) ) { + + for ( let i = 0, l = shapes.length; i < l; i ++ ) { + + const shape = shapes[ i ]; + + data.shapes.push( shape.uuid ); + + } + + } else { + + data.shapes.push( shapes.uuid ); + + } + + return data; + +} + +class SphereGeometry extends BufferGeometry { + + constructor( radius = 1, widthSegments = 32, heightSegments = 16, phiStart = 0, phiLength = Math.PI * 2, thetaStart = 0, thetaLength = Math.PI ) { + + super(); + + this.type = 'SphereGeometry'; + + this.parameters = { + radius: radius, + widthSegments: widthSegments, + heightSegments: heightSegments, + phiStart: phiStart, + phiLength: phiLength, + thetaStart: thetaStart, + thetaLength: thetaLength + }; + + widthSegments = Math.max( 3, Math.floor( widthSegments ) ); + heightSegments = Math.max( 2, Math.floor( heightSegments ) ); + + const thetaEnd = Math.min( thetaStart + thetaLength, Math.PI ); + + let index = 0; + const grid = []; + + const vertex = new Vector3(); + const normal = new Vector3(); + + // buffers + + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + + // generate vertices, normals and uvs + + for ( let iy = 0; iy <= heightSegments; iy ++ ) { + + const verticesRow = []; + + const v = iy / heightSegments; + + // special case for the poles + + let uOffset = 0; + + if ( iy === 0 && thetaStart === 0 ) { + + uOffset = 0.5 / widthSegments; + + } else if ( iy === heightSegments && thetaEnd === Math.PI ) { + + uOffset = - 0.5 / widthSegments; + + } + + for ( let ix = 0; ix <= widthSegments; ix ++ ) { + + const u = ix / widthSegments; + + // vertex + + vertex.x = - radius * Math.cos( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); + vertex.y = radius * Math.cos( thetaStart + v * thetaLength ); + vertex.z = radius * Math.sin( phiStart + u * phiLength ) * Math.sin( thetaStart + v * thetaLength ); + + vertices.push( vertex.x, vertex.y, vertex.z ); + + // normal + + normal.copy( vertex ).normalize(); + normals.push( normal.x, normal.y, normal.z ); + + // uv + + uvs.push( u + uOffset, 1 - v ); + + verticesRow.push( index ++ ); + + } + + grid.push( verticesRow ); + + } + + // indices + + for ( let iy = 0; iy < heightSegments; iy ++ ) { + + for ( let ix = 0; ix < widthSegments; ix ++ ) { + + const a = grid[ iy ][ ix + 1 ]; + const b = grid[ iy ][ ix ]; + const c = grid[ iy + 1 ][ ix ]; + const d = grid[ iy + 1 ][ ix + 1 ]; + + if ( iy !== 0 || thetaStart > 0 ) indices.push( a, b, d ); + if ( iy !== heightSegments - 1 || thetaEnd < Math.PI ) indices.push( b, c, d ); + + } + + } + + // build geometry + + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + + } + + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + + static fromJSON( data ) { + + return new SphereGeometry( data.radius, data.widthSegments, data.heightSegments, data.phiStart, data.phiLength, data.thetaStart, data.thetaLength ); + + } + +} + +class TetrahedronGeometry extends PolyhedronGeometry { + + constructor( radius = 1, detail = 0 ) { + + const vertices = [ + 1, 1, 1, - 1, - 1, 1, - 1, 1, - 1, 1, - 1, - 1 + ]; + + const indices = [ + 2, 1, 0, 0, 3, 2, 1, 3, 0, 2, 3, 1 + ]; + + super( vertices, indices, radius, detail ); + + this.type = 'TetrahedronGeometry'; + + this.parameters = { + radius: radius, + detail: detail + }; + + } + + static fromJSON( data ) { + + return new TetrahedronGeometry( data.radius, data.detail ); + + } + +} + +class TorusGeometry extends BufferGeometry { + + constructor( radius = 1, tube = 0.4, radialSegments = 12, tubularSegments = 48, arc = Math.PI * 2 ) { + + super(); + + this.type = 'TorusGeometry'; + + this.parameters = { + radius: radius, + tube: tube, + radialSegments: radialSegments, + tubularSegments: tubularSegments, + arc: arc + }; + + radialSegments = Math.floor( radialSegments ); + tubularSegments = Math.floor( tubularSegments ); + + // buffers + + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + + // helper variables + + const center = new Vector3(); + const vertex = new Vector3(); + const normal = new Vector3(); + + // generate vertices, normals and uvs + + for ( let j = 0; j <= radialSegments; j ++ ) { + + for ( let i = 0; i <= tubularSegments; i ++ ) { + + const u = i / tubularSegments * arc; + const v = j / radialSegments * Math.PI * 2; + + // vertex + + vertex.x = ( radius + tube * Math.cos( v ) ) * Math.cos( u ); + vertex.y = ( radius + tube * Math.cos( v ) ) * Math.sin( u ); + vertex.z = tube * Math.sin( v ); + + vertices.push( vertex.x, vertex.y, vertex.z ); + + // normal + + center.x = radius * Math.cos( u ); + center.y = radius * Math.sin( u ); + normal.subVectors( vertex, center ).normalize(); + + normals.push( normal.x, normal.y, normal.z ); + + // uv + + uvs.push( i / tubularSegments ); + uvs.push( j / radialSegments ); + + } + + } + + // generate indices + + for ( let j = 1; j <= radialSegments; j ++ ) { + + for ( let i = 1; i <= tubularSegments; i ++ ) { + + // indices + + const a = ( tubularSegments + 1 ) * j + i - 1; + const b = ( tubularSegments + 1 ) * ( j - 1 ) + i - 1; + const c = ( tubularSegments + 1 ) * ( j - 1 ) + i; + const d = ( tubularSegments + 1 ) * j + i; + + // faces + + indices.push( a, b, d ); + indices.push( b, c, d ); + + } + + } + + // build geometry + + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + + } + + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + + static fromJSON( data ) { + + return new TorusGeometry( data.radius, data.tube, data.radialSegments, data.tubularSegments, data.arc ); + + } + +} + +class TorusKnotGeometry extends BufferGeometry { + + constructor( radius = 1, tube = 0.4, tubularSegments = 64, radialSegments = 8, p = 2, q = 3 ) { + + super(); + + this.type = 'TorusKnotGeometry'; + + this.parameters = { + radius: radius, + tube: tube, + tubularSegments: tubularSegments, + radialSegments: radialSegments, + p: p, + q: q + }; + + tubularSegments = Math.floor( tubularSegments ); + radialSegments = Math.floor( radialSegments ); + + // buffers + + const indices = []; + const vertices = []; + const normals = []; + const uvs = []; + + // helper variables + + const vertex = new Vector3(); + const normal = new Vector3(); + + const P1 = new Vector3(); + const P2 = new Vector3(); + + const B = new Vector3(); + const T = new Vector3(); + const N = new Vector3(); + + // generate vertices, normals and uvs + + for ( let i = 0; i <= tubularSegments; ++ i ) { + + // the radian "u" is used to calculate the position on the torus curve of the current tubular segment + + const u = i / tubularSegments * p * Math.PI * 2; + + // now we calculate two points. P1 is our current position on the curve, P2 is a little farther ahead. + // these points are used to create a special "coordinate space", which is necessary to calculate the correct vertex positions + + calculatePositionOnCurve( u, p, q, radius, P1 ); + calculatePositionOnCurve( u + 0.01, p, q, radius, P2 ); + + // calculate orthonormal basis + + T.subVectors( P2, P1 ); + N.addVectors( P2, P1 ); + B.crossVectors( T, N ); + N.crossVectors( B, T ); + + // normalize B, N. T can be ignored, we don't use it + + B.normalize(); + N.normalize(); + + for ( let j = 0; j <= radialSegments; ++ j ) { + + // now calculate the vertices. they are nothing more than an extrusion of the torus curve. + // because we extrude a shape in the xy-plane, there is no need to calculate a z-value. + + const v = j / radialSegments * Math.PI * 2; + const cx = - tube * Math.cos( v ); + const cy = tube * Math.sin( v ); + + // now calculate the final vertex position. + // first we orient the extrusion with our basis vectors, then we add it to the current position on the curve + + vertex.x = P1.x + ( cx * N.x + cy * B.x ); + vertex.y = P1.y + ( cx * N.y + cy * B.y ); + vertex.z = P1.z + ( cx * N.z + cy * B.z ); + + vertices.push( vertex.x, vertex.y, vertex.z ); + + // normal (P1 is always the center/origin of the extrusion, thus we can use it to calculate the normal) + + normal.subVectors( vertex, P1 ).normalize(); + + normals.push( normal.x, normal.y, normal.z ); + + // uv + + uvs.push( i / tubularSegments ); + uvs.push( j / radialSegments ); + + } + + } + + // generate indices + + for ( let j = 1; j <= tubularSegments; j ++ ) { + + for ( let i = 1; i <= radialSegments; i ++ ) { + + // indices + + const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); + const b = ( radialSegments + 1 ) * j + ( i - 1 ); + const c = ( radialSegments + 1 ) * j + i; + const d = ( radialSegments + 1 ) * ( j - 1 ) + i; + + // faces + + indices.push( a, b, d ); + indices.push( b, c, d ); + + } + + } + + // build geometry + + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + + // this function calculates the current position on the torus curve + + function calculatePositionOnCurve( u, p, q, radius, position ) { + + const cu = Math.cos( u ); + const su = Math.sin( u ); + const quOverP = q / p * u; + const cs = Math.cos( quOverP ); + + position.x = radius * ( 2 + cs ) * 0.5 * cu; + position.y = radius * ( 2 + cs ) * su * 0.5; + position.z = radius * Math.sin( quOverP ) * 0.5; + + } + + } + + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + + static fromJSON( data ) { + + return new TorusKnotGeometry( data.radius, data.tube, data.tubularSegments, data.radialSegments, data.p, data.q ); + + } + +} + +class TubeGeometry extends BufferGeometry { + + constructor( path = new QuadraticBezierCurve3( new Vector3( - 1, - 1, 0 ), new Vector3( - 1, 1, 0 ), new Vector3( 1, 1, 0 ) ), tubularSegments = 64, radius = 1, radialSegments = 8, closed = false ) { + + super(); + + this.type = 'TubeGeometry'; + + this.parameters = { + path: path, + tubularSegments: tubularSegments, + radius: radius, + radialSegments: radialSegments, + closed: closed + }; + + const frames = path.computeFrenetFrames( tubularSegments, closed ); + + // expose internals + + this.tangents = frames.tangents; + this.normals = frames.normals; + this.binormals = frames.binormals; + + // helper variables + + const vertex = new Vector3(); + const normal = new Vector3(); + const uv = new Vector2(); + let P = new Vector3(); + + // buffer + + const vertices = []; + const normals = []; + const uvs = []; + const indices = []; + + // create buffer data + + generateBufferData(); + + // build geometry + + this.setIndex( indices ); + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + this.setAttribute( 'normal', new Float32BufferAttribute( normals, 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uvs, 2 ) ); + + // functions + + function generateBufferData() { + + for ( let i = 0; i < tubularSegments; i ++ ) { + + generateSegment( i ); + + } + + // if the geometry is not closed, generate the last row of vertices and normals + // at the regular position on the given path + // + // if the geometry is closed, duplicate the first row of vertices and normals (uvs will differ) + + generateSegment( ( closed === false ) ? tubularSegments : 0 ); + + // uvs are generated in a separate function. + // this makes it easy compute correct values for closed geometries + + generateUVs(); + + // finally create faces + + generateIndices(); + + } + + function generateSegment( i ) { + + // we use getPointAt to sample evenly distributed points from the given path + + P = path.getPointAt( i / tubularSegments, P ); + + // retrieve corresponding normal and binormal + + const N = frames.normals[ i ]; + const B = frames.binormals[ i ]; + + // generate normals and vertices for the current segment + + for ( let j = 0; j <= radialSegments; j ++ ) { + + const v = j / radialSegments * Math.PI * 2; + + const sin = Math.sin( v ); + const cos = - Math.cos( v ); + + // normal + + normal.x = ( cos * N.x + sin * B.x ); + normal.y = ( cos * N.y + sin * B.y ); + normal.z = ( cos * N.z + sin * B.z ); + normal.normalize(); + + normals.push( normal.x, normal.y, normal.z ); + + // vertex + + vertex.x = P.x + radius * normal.x; + vertex.y = P.y + radius * normal.y; + vertex.z = P.z + radius * normal.z; + + vertices.push( vertex.x, vertex.y, vertex.z ); + + } + + } + + function generateIndices() { + + for ( let j = 1; j <= tubularSegments; j ++ ) { + + for ( let i = 1; i <= radialSegments; i ++ ) { + + const a = ( radialSegments + 1 ) * ( j - 1 ) + ( i - 1 ); + const b = ( radialSegments + 1 ) * j + ( i - 1 ); + const c = ( radialSegments + 1 ) * j + i; + const d = ( radialSegments + 1 ) * ( j - 1 ) + i; + + // faces + + indices.push( a, b, d ); + indices.push( b, c, d ); + + } + + } + + } + + function generateUVs() { + + for ( let i = 0; i <= tubularSegments; i ++ ) { + + for ( let j = 0; j <= radialSegments; j ++ ) { + + uv.x = i / tubularSegments; + uv.y = j / radialSegments; + + uvs.push( uv.x, uv.y ); + + } + + } + + } + + } + + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + data.path = this.parameters.path.toJSON(); + + return data; + + } + + static fromJSON( data ) { + + // This only works for built-in curves (e.g. CatmullRomCurve3). + // User defined curves or instances of CurvePath will not be deserialized. + return new TubeGeometry( + new Curves[ data.path.type ]().fromJSON( data.path ), + data.tubularSegments, + data.radius, + data.radialSegments, + data.closed + ); + + } + +} + +class WireframeGeometry extends BufferGeometry { + + constructor( geometry = null ) { + + super(); + + this.type = 'WireframeGeometry'; + + this.parameters = { + geometry: geometry + }; + + if ( geometry !== null ) { + + // buffer + + const vertices = []; + const edges = new Set(); + + // helper variables + + const start = new Vector3(); + const end = new Vector3(); + + if ( geometry.index !== null ) { + + // indexed BufferGeometry + + const position = geometry.attributes.position; + const indices = geometry.index; + let groups = geometry.groups; + + if ( groups.length === 0 ) { + + groups = [ { start: 0, count: indices.count, materialIndex: 0 } ]; + + } + + // create a data structure that contains all edges without duplicates + + for ( let o = 0, ol = groups.length; o < ol; ++ o ) { + + const group = groups[ o ]; + + const groupStart = group.start; + const groupCount = group.count; + + for ( let i = groupStart, l = ( groupStart + groupCount ); i < l; i += 3 ) { + + for ( let j = 0; j < 3; j ++ ) { + + const index1 = indices.getX( i + j ); + const index2 = indices.getX( i + ( j + 1 ) % 3 ); + + start.fromBufferAttribute( position, index1 ); + end.fromBufferAttribute( position, index2 ); + + if ( isUniqueEdge( start, end, edges ) === true ) { + + vertices.push( start.x, start.y, start.z ); + vertices.push( end.x, end.y, end.z ); + + } + + } + + } + + } + + } else { + + // non-indexed BufferGeometry + + const position = geometry.attributes.position; + + for ( let i = 0, l = ( position.count / 3 ); i < l; i ++ ) { + + for ( let j = 0; j < 3; j ++ ) { + + // three edges per triangle, an edge is represented as (index1, index2) + // e.g. the first triangle has the following edges: (0,1),(1,2),(2,0) + + const index1 = 3 * i + j; + const index2 = 3 * i + ( ( j + 1 ) % 3 ); + + start.fromBufferAttribute( position, index1 ); + end.fromBufferAttribute( position, index2 ); + + if ( isUniqueEdge( start, end, edges ) === true ) { + + vertices.push( start.x, start.y, start.z ); + vertices.push( end.x, end.y, end.z ); + + } + + } + + } + + } + + // build geometry + + this.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + + } + + } + + copy( source ) { + + super.copy( source ); + + this.parameters = Object.assign( {}, source.parameters ); + + return this; + + } + +} + +function isUniqueEdge( start, end, edges ) { + + const hash1 = `${start.x},${start.y},${start.z}-${end.x},${end.y},${end.z}`; + const hash2 = `${end.x},${end.y},${end.z}-${start.x},${start.y},${start.z}`; // coincident edge + + if ( edges.has( hash1 ) === true || edges.has( hash2 ) === true ) { + + return false; + + } else { + + edges.add( hash1 ); + edges.add( hash2 ); + return true; + + } + +} + +var Geometries$1 = /*#__PURE__*/Object.freeze({ + __proto__: null, + BoxGeometry: BoxGeometry, + CapsuleGeometry: CapsuleGeometry, + CircleGeometry: CircleGeometry, + ConeGeometry: ConeGeometry, + CylinderGeometry: CylinderGeometry, + DodecahedronGeometry: DodecahedronGeometry, + EdgesGeometry: EdgesGeometry, + ExtrudeGeometry: ExtrudeGeometry, + IcosahedronGeometry: IcosahedronGeometry, + LatheGeometry: LatheGeometry, + OctahedronGeometry: OctahedronGeometry, + PlaneGeometry: PlaneGeometry, + PolyhedronGeometry: PolyhedronGeometry, + RingGeometry: RingGeometry, + ShapeGeometry: ShapeGeometry, + SphereGeometry: SphereGeometry, + TetrahedronGeometry: TetrahedronGeometry, + TorusGeometry: TorusGeometry, + TorusKnotGeometry: TorusKnotGeometry, + TubeGeometry: TubeGeometry, + WireframeGeometry: WireframeGeometry +}); + +class ShadowMaterial extends Material { + + constructor( parameters ) { + + super(); + + this.isShadowMaterial = true; + + this.type = 'ShadowMaterial'; + + this.color = new Color( 0x000000 ); + this.transparent = true; + + this.fog = true; + + this.setValues( parameters ); + + } + + copy( source ) { + + super.copy( source ); + + this.color.copy( source.color ); + + this.fog = source.fog; + + return this; + + } + +} + +class RawShaderMaterial extends ShaderMaterial { + + constructor( parameters ) { + + super( parameters ); + + this.isRawShaderMaterial = true; + + this.type = 'RawShaderMaterial'; + + } + +} + +class MeshStandardMaterial extends Material { + + constructor( parameters ) { + + super(); + + this.isMeshStandardMaterial = true; + + this.defines = { 'STANDARD': '' }; + + this.type = 'MeshStandardMaterial'; + + this.color = new Color( 0xffffff ); // diffuse + this.roughness = 1.0; + this.metalness = 0.0; + + this.map = null; + + this.lightMap = null; + this.lightMapIntensity = 1.0; + + this.aoMap = null; + this.aoMapIntensity = 1.0; + + this.emissive = new Color( 0x000000 ); + this.emissiveIntensity = 1.0; + this.emissiveMap = null; + + this.bumpMap = null; + this.bumpScale = 1; + + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap; + this.normalScale = new Vector2( 1, 1 ); + + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + + this.roughnessMap = null; + + this.metalnessMap = null; + + this.alphaMap = null; + + this.envMap = null; + this.envMapRotation = new Euler(); + this.envMapIntensity = 1.0; + + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = 'round'; + this.wireframeLinejoin = 'round'; + + this.flatShading = false; + + this.fog = true; + + this.setValues( parameters ); + + } + + copy( source ) { + + super.copy( source ); + + this.defines = { 'STANDARD': '' }; + + this.color.copy( source.color ); + this.roughness = source.roughness; + this.metalness = source.metalness; + + this.map = source.map; + + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; + + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; + + this.emissive.copy( source.emissive ); + this.emissiveMap = source.emissiveMap; + this.emissiveIntensity = source.emissiveIntensity; + + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; + + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy( source.normalScale ); + + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + + this.roughnessMap = source.roughnessMap; + + this.metalnessMap = source.metalnessMap; + + this.alphaMap = source.alphaMap; + + this.envMap = source.envMap; + this.envMapRotation.copy( source.envMapRotation ); + this.envMapIntensity = source.envMapIntensity; + + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; + + this.flatShading = source.flatShading; + + this.fog = source.fog; + + return this; + + } + +} + +class MeshPhysicalMaterial extends MeshStandardMaterial { + + constructor( parameters ) { + + super(); + + this.isMeshPhysicalMaterial = true; + + this.defines = { + + 'STANDARD': '', + 'PHYSICAL': '' + + }; + + this.type = 'MeshPhysicalMaterial'; + + this.anisotropyRotation = 0; + this.anisotropyMap = null; + + this.clearcoatMap = null; + this.clearcoatRoughness = 0.0; + this.clearcoatRoughnessMap = null; + this.clearcoatNormalScale = new Vector2( 1, 1 ); + this.clearcoatNormalMap = null; + + this.ior = 1.5; + + Object.defineProperty( this, 'reflectivity', { + get: function () { + + return ( clamp$1( 2.5 * ( this.ior - 1 ) / ( this.ior + 1 ), 0, 1 ) ); + + }, + set: function ( reflectivity ) { + + this.ior = ( 1 + 0.4 * reflectivity ) / ( 1 - 0.4 * reflectivity ); + + } + } ); + + this.iridescenceMap = null; + this.iridescenceIOR = 1.3; + this.iridescenceThicknessRange = [ 100, 400 ]; + this.iridescenceThicknessMap = null; + + this.sheenColor = new Color( 0x000000 ); + this.sheenColorMap = null; + this.sheenRoughness = 1.0; + this.sheenRoughnessMap = null; + + this.transmissionMap = null; + + this.thickness = 0; + this.thicknessMap = null; + this.attenuationDistance = Infinity; + this.attenuationColor = new Color( 1, 1, 1 ); + + this.specularIntensity = 1.0; + this.specularIntensityMap = null; + this.specularColor = new Color( 1, 1, 1 ); + this.specularColorMap = null; + + this._anisotropy = 0; + this._clearcoat = 0; + this._dispersion = 0; + this._iridescence = 0; + this._sheen = 0.0; + this._transmission = 0; + + this.setValues( parameters ); + + } + + get anisotropy() { + + return this._anisotropy; + + } + + set anisotropy( value ) { + + if ( this._anisotropy > 0 !== value > 0 ) { + + this.version ++; + + } + + this._anisotropy = value; + + } + + get clearcoat() { + + return this._clearcoat; + + } + + set clearcoat( value ) { + + if ( this._clearcoat > 0 !== value > 0 ) { + + this.version ++; + + } + + this._clearcoat = value; + + } + + get iridescence() { + + return this._iridescence; + + } + + set iridescence( value ) { + + if ( this._iridescence > 0 !== value > 0 ) { + + this.version ++; + + } + + this._iridescence = value; + + } + + get dispersion() { + + return this._dispersion; + + } + + set dispersion( value ) { + + if ( this._dispersion > 0 !== value > 0 ) { + + this.version ++; + + } + + this._dispersion = value; + + } + + get sheen() { + + return this._sheen; + + } + + set sheen( value ) { + + if ( this._sheen > 0 !== value > 0 ) { + + this.version ++; + + } + + this._sheen = value; + + } + + get transmission() { + + return this._transmission; + + } + + set transmission( value ) { + + if ( this._transmission > 0 !== value > 0 ) { + + this.version ++; + + } + + this._transmission = value; + + } + + copy( source ) { + + super.copy( source ); + + this.defines = { + + 'STANDARD': '', + 'PHYSICAL': '' + + }; + + this.anisotropy = source.anisotropy; + this.anisotropyRotation = source.anisotropyRotation; + this.anisotropyMap = source.anisotropyMap; + + this.clearcoat = source.clearcoat; + this.clearcoatMap = source.clearcoatMap; + this.clearcoatRoughness = source.clearcoatRoughness; + this.clearcoatRoughnessMap = source.clearcoatRoughnessMap; + this.clearcoatNormalMap = source.clearcoatNormalMap; + this.clearcoatNormalScale.copy( source.clearcoatNormalScale ); + + this.dispersion = source.dispersion; + this.ior = source.ior; + + this.iridescence = source.iridescence; + this.iridescenceMap = source.iridescenceMap; + this.iridescenceIOR = source.iridescenceIOR; + this.iridescenceThicknessRange = [ ...source.iridescenceThicknessRange ]; + this.iridescenceThicknessMap = source.iridescenceThicknessMap; + + this.sheen = source.sheen; + this.sheenColor.copy( source.sheenColor ); + this.sheenColorMap = source.sheenColorMap; + this.sheenRoughness = source.sheenRoughness; + this.sheenRoughnessMap = source.sheenRoughnessMap; + + this.transmission = source.transmission; + this.transmissionMap = source.transmissionMap; + + this.thickness = source.thickness; + this.thicknessMap = source.thicknessMap; + this.attenuationDistance = source.attenuationDistance; + this.attenuationColor.copy( source.attenuationColor ); + + this.specularIntensity = source.specularIntensity; + this.specularIntensityMap = source.specularIntensityMap; + this.specularColor.copy( source.specularColor ); + this.specularColorMap = source.specularColorMap; + + return this; + + } + +} + +class MeshPhongMaterial extends Material { + + constructor( parameters ) { + + super(); + + this.isMeshPhongMaterial = true; + + this.type = 'MeshPhongMaterial'; + + this.color = new Color( 0xffffff ); // diffuse + this.specular = new Color( 0x111111 ); + this.shininess = 30; + + this.map = null; + + this.lightMap = null; + this.lightMapIntensity = 1.0; + + this.aoMap = null; + this.aoMapIntensity = 1.0; + + this.emissive = new Color( 0x000000 ); + this.emissiveIntensity = 1.0; + this.emissiveMap = null; + + this.bumpMap = null; + this.bumpScale = 1; + + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap; + this.normalScale = new Vector2( 1, 1 ); + + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + + this.specularMap = null; + + this.alphaMap = null; + + this.envMap = null; + this.envMapRotation = new Euler(); + this.combine = MultiplyOperation; + this.reflectivity = 1; + this.refractionRatio = 0.98; + + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = 'round'; + this.wireframeLinejoin = 'round'; + + this.flatShading = false; + + this.fog = true; + + this.setValues( parameters ); + + } + + copy( source ) { + + super.copy( source ); + + this.color.copy( source.color ); + this.specular.copy( source.specular ); + this.shininess = source.shininess; + + this.map = source.map; + + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; + + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; + + this.emissive.copy( source.emissive ); + this.emissiveMap = source.emissiveMap; + this.emissiveIntensity = source.emissiveIntensity; + + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; + + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy( source.normalScale ); + + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + + this.specularMap = source.specularMap; + + this.alphaMap = source.alphaMap; + + this.envMap = source.envMap; + this.envMapRotation.copy( source.envMapRotation ); + this.combine = source.combine; + this.reflectivity = source.reflectivity; + this.refractionRatio = source.refractionRatio; + + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; + + this.flatShading = source.flatShading; + + this.fog = source.fog; + + return this; + + } + +} + +class MeshToonMaterial extends Material { + + constructor( parameters ) { + + super(); + + this.isMeshToonMaterial = true; + + this.defines = { 'TOON': '' }; + + this.type = 'MeshToonMaterial'; + + this.color = new Color( 0xffffff ); + + this.map = null; + this.gradientMap = null; + + this.lightMap = null; + this.lightMapIntensity = 1.0; + + this.aoMap = null; + this.aoMapIntensity = 1.0; + + this.emissive = new Color( 0x000000 ); + this.emissiveIntensity = 1.0; + this.emissiveMap = null; + + this.bumpMap = null; + this.bumpScale = 1; + + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap; + this.normalScale = new Vector2( 1, 1 ); + + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + + this.alphaMap = null; + + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = 'round'; + this.wireframeLinejoin = 'round'; + + this.fog = true; + + this.setValues( parameters ); + + } + + copy( source ) { + + super.copy( source ); + + this.color.copy( source.color ); + + this.map = source.map; + this.gradientMap = source.gradientMap; + + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; + + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; + + this.emissive.copy( source.emissive ); + this.emissiveMap = source.emissiveMap; + this.emissiveIntensity = source.emissiveIntensity; + + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; + + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy( source.normalScale ); + + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + + this.alphaMap = source.alphaMap; + + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; + + this.fog = source.fog; + + return this; + + } + +} + +class MeshNormalMaterial extends Material { + + constructor( parameters ) { + + super(); + + this.isMeshNormalMaterial = true; + + this.type = 'MeshNormalMaterial'; + + this.bumpMap = null; + this.bumpScale = 1; + + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap; + this.normalScale = new Vector2( 1, 1 ); + + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + + this.wireframe = false; + this.wireframeLinewidth = 1; + + this.flatShading = false; + + this.setValues( parameters ); + + } + + copy( source ) { + + super.copy( source ); + + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; + + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy( source.normalScale ); + + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + + this.flatShading = source.flatShading; + + return this; + + } + +} + +class MeshLambertMaterial extends Material { + + constructor( parameters ) { + + super(); + + this.isMeshLambertMaterial = true; + + this.type = 'MeshLambertMaterial'; + + this.color = new Color( 0xffffff ); // diffuse + + this.map = null; + + this.lightMap = null; + this.lightMapIntensity = 1.0; + + this.aoMap = null; + this.aoMapIntensity = 1.0; + + this.emissive = new Color( 0x000000 ); + this.emissiveIntensity = 1.0; + this.emissiveMap = null; + + this.bumpMap = null; + this.bumpScale = 1; + + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap; + this.normalScale = new Vector2( 1, 1 ); + + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + + this.specularMap = null; + + this.alphaMap = null; + + this.envMap = null; + this.envMapRotation = new Euler(); + this.combine = MultiplyOperation; + this.reflectivity = 1; + this.refractionRatio = 0.98; + + this.wireframe = false; + this.wireframeLinewidth = 1; + this.wireframeLinecap = 'round'; + this.wireframeLinejoin = 'round'; + + this.flatShading = false; + + this.fog = true; + + this.setValues( parameters ); + + } + + copy( source ) { + + super.copy( source ); + + this.color.copy( source.color ); + + this.map = source.map; + + this.lightMap = source.lightMap; + this.lightMapIntensity = source.lightMapIntensity; + + this.aoMap = source.aoMap; + this.aoMapIntensity = source.aoMapIntensity; + + this.emissive.copy( source.emissive ); + this.emissiveMap = source.emissiveMap; + this.emissiveIntensity = source.emissiveIntensity; + + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; + + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy( source.normalScale ); + + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + + this.specularMap = source.specularMap; + + this.alphaMap = source.alphaMap; + + this.envMap = source.envMap; + this.envMapRotation.copy( source.envMapRotation ); + this.combine = source.combine; + this.reflectivity = source.reflectivity; + this.refractionRatio = source.refractionRatio; + + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + this.wireframeLinecap = source.wireframeLinecap; + this.wireframeLinejoin = source.wireframeLinejoin; + + this.flatShading = source.flatShading; + + this.fog = source.fog; + + return this; + + } + +} + +class MeshDepthMaterial extends Material { + + constructor( parameters ) { + + super(); + + this.isMeshDepthMaterial = true; + + this.type = 'MeshDepthMaterial'; + + this.depthPacking = BasicDepthPacking; + + this.map = null; + + this.alphaMap = null; + + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + + this.wireframe = false; + this.wireframeLinewidth = 1; + + this.setValues( parameters ); + + } + + copy( source ) { + + super.copy( source ); + + this.depthPacking = source.depthPacking; + + this.map = source.map; + + this.alphaMap = source.alphaMap; + + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + + this.wireframe = source.wireframe; + this.wireframeLinewidth = source.wireframeLinewidth; + + return this; + + } + +} + +class MeshDistanceMaterial extends Material { + + constructor( parameters ) { + + super(); + + this.isMeshDistanceMaterial = true; + + this.type = 'MeshDistanceMaterial'; + + this.map = null; + + this.alphaMap = null; + + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + + this.setValues( parameters ); + + } + + copy( source ) { + + super.copy( source ); + + this.map = source.map; + + this.alphaMap = source.alphaMap; + + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + + return this; + + } + +} + +class MeshMatcapMaterial extends Material { + + constructor( parameters ) { + + super(); + + this.isMeshMatcapMaterial = true; + + this.defines = { 'MATCAP': '' }; + + this.type = 'MeshMatcapMaterial'; + + this.color = new Color( 0xffffff ); // diffuse + + this.matcap = null; + + this.map = null; + + this.bumpMap = null; + this.bumpScale = 1; + + this.normalMap = null; + this.normalMapType = TangentSpaceNormalMap; + this.normalScale = new Vector2( 1, 1 ); + + this.displacementMap = null; + this.displacementScale = 1; + this.displacementBias = 0; + + this.alphaMap = null; + + this.flatShading = false; + + this.fog = true; + + this.setValues( parameters ); + + } + + + copy( source ) { + + super.copy( source ); + + this.defines = { 'MATCAP': '' }; + + this.color.copy( source.color ); + + this.matcap = source.matcap; + + this.map = source.map; + + this.bumpMap = source.bumpMap; + this.bumpScale = source.bumpScale; + + this.normalMap = source.normalMap; + this.normalMapType = source.normalMapType; + this.normalScale.copy( source.normalScale ); + + this.displacementMap = source.displacementMap; + this.displacementScale = source.displacementScale; + this.displacementBias = source.displacementBias; + + this.alphaMap = source.alphaMap; + + this.flatShading = source.flatShading; + + this.fog = source.fog; + + return this; + + } + +} + +class LineDashedMaterial extends LineBasicMaterial { + + constructor( parameters ) { + + super(); + + this.isLineDashedMaterial = true; + + this.type = 'LineDashedMaterial'; + + this.scale = 1; + this.dashSize = 3; + this.gapSize = 1; + + this.setValues( parameters ); + + } + + copy( source ) { + + super.copy( source ); + + this.scale = source.scale; + this.dashSize = source.dashSize; + this.gapSize = source.gapSize; + + return this; + + } + +} + +// converts an array to a specific type +function convertArray( array, type, forceClone ) { + + if ( ! array || // let 'undefined' and 'null' pass + ! forceClone && array.constructor === type ) return array; + + if ( typeof type.BYTES_PER_ELEMENT === 'number' ) { + + return new type( array ); // create typed array + + } + + return Array.prototype.slice.call( array ); // create Array + +} + +function isTypedArray( object ) { + + return ArrayBuffer.isView( object ) && + ! ( object instanceof DataView ); + +} + +// returns an array by which times and values can be sorted +function getKeyframeOrder( times ) { + + function compareTime( i, j ) { + + return times[ i ] - times[ j ]; + + } + + const n = times.length; + const result = new Array( n ); + for ( let i = 0; i !== n; ++ i ) result[ i ] = i; + + result.sort( compareTime ); + + return result; + +} + +// uses the array previously returned by 'getKeyframeOrder' to sort data +function sortedArray( values, stride, order ) { + + const nValues = values.length; + const result = new values.constructor( nValues ); + + for ( let i = 0, dstOffset = 0; dstOffset !== nValues; ++ i ) { + + const srcOffset = order[ i ] * stride; + + for ( let j = 0; j !== stride; ++ j ) { + + result[ dstOffset ++ ] = values[ srcOffset + j ]; + + } + + } + + return result; + +} + +// function for parsing AOS keyframe formats +function flattenJSON( jsonKeys, times, values, valuePropertyName ) { + + let i = 1, key = jsonKeys[ 0 ]; + + while ( key !== undefined && key[ valuePropertyName ] === undefined ) { + + key = jsonKeys[ i ++ ]; + + } + + if ( key === undefined ) return; // no data + + let value = key[ valuePropertyName ]; + if ( value === undefined ) return; // no data + + if ( Array.isArray( value ) ) { + + do { + + value = key[ valuePropertyName ]; + + if ( value !== undefined ) { + + times.push( key.time ); + values.push.apply( values, value ); // push all elements + + } + + key = jsonKeys[ i ++ ]; + + } while ( key !== undefined ); + + } else if ( value.toArray !== undefined ) { + + // ...assume THREE.Math-ish + + do { + + value = key[ valuePropertyName ]; + + if ( value !== undefined ) { + + times.push( key.time ); + value.toArray( values, values.length ); + + } + + key = jsonKeys[ i ++ ]; + + } while ( key !== undefined ); + + } else { + + // otherwise push as-is + + do { + + value = key[ valuePropertyName ]; + + if ( value !== undefined ) { + + times.push( key.time ); + values.push( value ); + + } + + key = jsonKeys[ i ++ ]; + + } while ( key !== undefined ); + + } + +} + +function subclip( sourceClip, name, startFrame, endFrame, fps = 30 ) { + + const clip = sourceClip.clone(); + + clip.name = name; + + const tracks = []; + + for ( let i = 0; i < clip.tracks.length; ++ i ) { + + const track = clip.tracks[ i ]; + const valueSize = track.getValueSize(); + + const times = []; + const values = []; + + for ( let j = 0; j < track.times.length; ++ j ) { + + const frame = track.times[ j ] * fps; + + if ( frame < startFrame || frame >= endFrame ) continue; + + times.push( track.times[ j ] ); + + for ( let k = 0; k < valueSize; ++ k ) { + + values.push( track.values[ j * valueSize + k ] ); + + } + + } + + if ( times.length === 0 ) continue; + + track.times = convertArray( times, track.times.constructor ); + track.values = convertArray( values, track.values.constructor ); + + tracks.push( track ); + + } + + clip.tracks = tracks; + + // find minimum .times value across all tracks in the trimmed clip + + let minStartTime = Infinity; + + for ( let i = 0; i < clip.tracks.length; ++ i ) { + + if ( minStartTime > clip.tracks[ i ].times[ 0 ] ) { + + minStartTime = clip.tracks[ i ].times[ 0 ]; + + } + + } + + // shift all tracks such that clip begins at t=0 + + for ( let i = 0; i < clip.tracks.length; ++ i ) { + + clip.tracks[ i ].shift( - 1 * minStartTime ); + + } + + clip.resetDuration(); + + return clip; + +} + +function makeClipAdditive( targetClip, referenceFrame = 0, referenceClip = targetClip, fps = 30 ) { + + if ( fps <= 0 ) fps = 30; + + const numTracks = referenceClip.tracks.length; + const referenceTime = referenceFrame / fps; + + // Make each track's values relative to the values at the reference frame + for ( let i = 0; i < numTracks; ++ i ) { + + const referenceTrack = referenceClip.tracks[ i ]; + const referenceTrackType = referenceTrack.ValueTypeName; + + // Skip this track if it's non-numeric + if ( referenceTrackType === 'bool' || referenceTrackType === 'string' ) continue; + + // Find the track in the target clip whose name and type matches the reference track + const targetTrack = targetClip.tracks.find( function ( track ) { + + return track.name === referenceTrack.name + && track.ValueTypeName === referenceTrackType; + + } ); + + if ( targetTrack === undefined ) continue; + + let referenceOffset = 0; + const referenceValueSize = referenceTrack.getValueSize(); + + if ( referenceTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) { + + referenceOffset = referenceValueSize / 3; + + } + + let targetOffset = 0; + const targetValueSize = targetTrack.getValueSize(); + + if ( targetTrack.createInterpolant.isInterpolantFactoryMethodGLTFCubicSpline ) { + + targetOffset = targetValueSize / 3; + + } + + const lastIndex = referenceTrack.times.length - 1; + let referenceValue; + + // Find the value to subtract out of the track + if ( referenceTime <= referenceTrack.times[ 0 ] ) { + + // Reference frame is earlier than the first keyframe, so just use the first keyframe + const startIndex = referenceOffset; + const endIndex = referenceValueSize - referenceOffset; + referenceValue = referenceTrack.values.slice( startIndex, endIndex ); + + } else if ( referenceTime >= referenceTrack.times[ lastIndex ] ) { + + // Reference frame is after the last keyframe, so just use the last keyframe + const startIndex = lastIndex * referenceValueSize + referenceOffset; + const endIndex = startIndex + referenceValueSize - referenceOffset; + referenceValue = referenceTrack.values.slice( startIndex, endIndex ); + + } else { + + // Interpolate to the reference value + const interpolant = referenceTrack.createInterpolant(); + const startIndex = referenceOffset; + const endIndex = referenceValueSize - referenceOffset; + interpolant.evaluate( referenceTime ); + referenceValue = interpolant.resultBuffer.slice( startIndex, endIndex ); + + } + + // Conjugate the quaternion + if ( referenceTrackType === 'quaternion' ) { + + const referenceQuat = new Quaternion().fromArray( referenceValue ).normalize().conjugate(); + referenceQuat.toArray( referenceValue ); + + } + + // Subtract the reference value from all of the track values + + const numTimes = targetTrack.times.length; + for ( let j = 0; j < numTimes; ++ j ) { + + const valueStart = j * targetValueSize + targetOffset; + + if ( referenceTrackType === 'quaternion' ) { + + // Multiply the conjugate for quaternion track types + Quaternion.multiplyQuaternionsFlat( + targetTrack.values, + valueStart, + referenceValue, + 0, + targetTrack.values, + valueStart + ); + + } else { + + const valueEnd = targetValueSize - targetOffset * 2; + + // Subtract each value for all other numeric track types + for ( let k = 0; k < valueEnd; ++ k ) { + + targetTrack.values[ valueStart + k ] -= referenceValue[ k ]; + + } + + } + + } + + } + + targetClip.blendMode = AdditiveAnimationBlendMode; + + return targetClip; + +} + +const AnimationUtils = { + convertArray: convertArray, + isTypedArray: isTypedArray, + getKeyframeOrder: getKeyframeOrder, + sortedArray: sortedArray, + flattenJSON: flattenJSON, + subclip: subclip, + makeClipAdditive: makeClipAdditive +}; + +/** + * Abstract base class of interpolants over parametric samples. + * + * The parameter domain is one dimensional, typically the time or a path + * along a curve defined by the data. + * + * The sample values can have any dimensionality and derived classes may + * apply special interpretations to the data. + * + * This class provides the interval seek in a Template Method, deferring + * the actual interpolation to derived classes. + * + * Time complexity is O(1) for linear access crossing at most two points + * and O(log N) for random access, where N is the number of positions. + * + * References: + * + * http://www.oodesign.com/template-method-pattern.html + * + */ + +class Interpolant { + + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + + this.parameterPositions = parameterPositions; + this._cachedIndex = 0; + + this.resultBuffer = resultBuffer !== undefined ? + resultBuffer : new sampleValues.constructor( sampleSize ); + this.sampleValues = sampleValues; + this.valueSize = sampleSize; + + this.settings = null; + this.DefaultSettings_ = {}; + + } + + evaluate( t ) { + + const pp = this.parameterPositions; + let i1 = this._cachedIndex, + t1 = pp[ i1 ], + t0 = pp[ i1 - 1 ]; + + validate_interval: { + + seek: { + + let right; + + linear_scan: { + + //- See http://jsperf.com/comparison-to-undefined/3 + //- slower code: + //- + //- if ( t >= t1 || t1 === undefined ) { + forward_scan: if ( ! ( t < t1 ) ) { + + for ( let giveUpAt = i1 + 2; ; ) { + + if ( t1 === undefined ) { + + if ( t < t0 ) break forward_scan; + + // after end + + i1 = pp.length; + this._cachedIndex = i1; + return this.copySampleValue_( i1 - 1 ); + + } + + if ( i1 === giveUpAt ) break; // this loop + + t0 = t1; + t1 = pp[ ++ i1 ]; + + if ( t < t1 ) { + + // we have arrived at the sought interval + break seek; + + } + + } + + // prepare binary search on the right side of the index + right = pp.length; + break linear_scan; + + } + + //- slower code: + //- if ( t < t0 || t0 === undefined ) { + if ( ! ( t >= t0 ) ) { + + // looping? + + const t1global = pp[ 1 ]; + + if ( t < t1global ) { + + i1 = 2; // + 1, using the scan for the details + t0 = t1global; + + } + + // linear reverse scan + + for ( let giveUpAt = i1 - 2; ; ) { + + if ( t0 === undefined ) { + + // before start + + this._cachedIndex = 0; + return this.copySampleValue_( 0 ); + + } + + if ( i1 === giveUpAt ) break; // this loop + + t1 = t0; + t0 = pp[ -- i1 - 1 ]; + + if ( t >= t0 ) { + + // we have arrived at the sought interval + break seek; + + } + + } + + // prepare binary search on the left side of the index + right = i1; + i1 = 0; + break linear_scan; + + } + + // the interval is valid + + break validate_interval; + + } // linear scan + + // binary search + + while ( i1 < right ) { + + const mid = ( i1 + right ) >>> 1; + + if ( t < pp[ mid ] ) { + + right = mid; + + } else { + + i1 = mid + 1; + + } + + } + + t1 = pp[ i1 ]; + t0 = pp[ i1 - 1 ]; + + // check boundary cases, again + + if ( t0 === undefined ) { + + this._cachedIndex = 0; + return this.copySampleValue_( 0 ); + + } + + if ( t1 === undefined ) { + + i1 = pp.length; + this._cachedIndex = i1; + return this.copySampleValue_( i1 - 1 ); + + } + + } // seek + + this._cachedIndex = i1; + + this.intervalChanged_( i1, t0, t1 ); + + } // validate_interval + + return this.interpolate_( i1, t0, t, t1 ); + + } + + getSettings_() { + + return this.settings || this.DefaultSettings_; + + } + + copySampleValue_( index ) { + + // copies a sample value to the result buffer + + const result = this.resultBuffer, + values = this.sampleValues, + stride = this.valueSize, + offset = index * stride; + + for ( let i = 0; i !== stride; ++ i ) { + + result[ i ] = values[ offset + i ]; + + } + + return result; + + } + + // Template methods for derived classes: + + interpolate_( /* i1, t0, t, t1 */ ) { + + throw new Error( 'call to abstract method' ); + // implementations shall return this.resultBuffer + + } + + intervalChanged_( /* i1, t0, t1 */ ) { + + // empty + + } + +} + +/** + * Fast and simple cubic spline interpolant. + * + * It was derived from a Hermitian construction setting the first derivative + * at each sample position to the linear slope between neighboring positions + * over their parameter interval. + */ + +class CubicInterpolant extends Interpolant { + + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); + + this._weightPrev = - 0; + this._offsetPrev = - 0; + this._weightNext = - 0; + this._offsetNext = - 0; + + this.DefaultSettings_ = { + + endingStart: ZeroCurvatureEnding, + endingEnd: ZeroCurvatureEnding + + }; + + } + + intervalChanged_( i1, t0, t1 ) { + + const pp = this.parameterPositions; + let iPrev = i1 - 2, + iNext = i1 + 1, + + tPrev = pp[ iPrev ], + tNext = pp[ iNext ]; + + if ( tPrev === undefined ) { + + switch ( this.getSettings_().endingStart ) { + + case ZeroSlopeEnding: + + // f'(t0) = 0 + iPrev = i1; + tPrev = 2 * t0 - t1; + + break; + + case WrapAroundEnding: + + // use the other end of the curve + iPrev = pp.length - 2; + tPrev = t0 + pp[ iPrev ] - pp[ iPrev + 1 ]; + + break; + + default: // ZeroCurvatureEnding + + // f''(t0) = 0 a.k.a. Natural Spline + iPrev = i1; + tPrev = t1; + + } + + } + + if ( tNext === undefined ) { + + switch ( this.getSettings_().endingEnd ) { + + case ZeroSlopeEnding: + + // f'(tN) = 0 + iNext = i1; + tNext = 2 * t1 - t0; + + break; + + case WrapAroundEnding: + + // use the other end of the curve + iNext = 1; + tNext = t1 + pp[ 1 ] - pp[ 0 ]; + + break; + + default: // ZeroCurvatureEnding + + // f''(tN) = 0, a.k.a. Natural Spline + iNext = i1 - 1; + tNext = t0; + + } + + } + + const halfDt = ( t1 - t0 ) * 0.5, + stride = this.valueSize; + + this._weightPrev = halfDt / ( t0 - tPrev ); + this._weightNext = halfDt / ( tNext - t1 ); + this._offsetPrev = iPrev * stride; + this._offsetNext = iNext * stride; + + } + + interpolate_( i1, t0, t, t1 ) { + + const result = this.resultBuffer, + values = this.sampleValues, + stride = this.valueSize, + + o1 = i1 * stride, o0 = o1 - stride, + oP = this._offsetPrev, oN = this._offsetNext, + wP = this._weightPrev, wN = this._weightNext, + + p = ( t - t0 ) / ( t1 - t0 ), + pp = p * p, + ppp = pp * p; + + // evaluate polynomials + + const sP = - wP * ppp + 2 * wP * pp - wP * p; + const s0 = ( 1 + wP ) * ppp + ( - 1.5 - 2 * wP ) * pp + ( - 0.5 + wP ) * p + 1; + const s1 = ( - 1 - wN ) * ppp + ( 1.5 + wN ) * pp + 0.5 * p; + const sN = wN * ppp - wN * pp; + + // combine data linearly + + for ( let i = 0; i !== stride; ++ i ) { + + result[ i ] = + sP * values[ oP + i ] + + s0 * values[ o0 + i ] + + s1 * values[ o1 + i ] + + sN * values[ oN + i ]; + + } + + return result; + + } + +} + +class LinearInterpolant extends Interpolant { + + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); + + } + + interpolate_( i1, t0, t, t1 ) { + + const result = this.resultBuffer, + values = this.sampleValues, + stride = this.valueSize, + + offset1 = i1 * stride, + offset0 = offset1 - stride, + + weight1 = ( t - t0 ) / ( t1 - t0 ), + weight0 = 1 - weight1; + + for ( let i = 0; i !== stride; ++ i ) { + + result[ i ] = + values[ offset0 + i ] * weight0 + + values[ offset1 + i ] * weight1; + + } + + return result; + + } + +} + +/** + * + * Interpolant that evaluates to the sample value at the position preceding + * the parameter. + */ + +class DiscreteInterpolant extends Interpolant { + + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); + + } + + interpolate_( i1 /*, t0, t, t1 */ ) { + + return this.copySampleValue_( i1 - 1 ); + + } + +} + +class KeyframeTrack { + + constructor( name, times, values, interpolation ) { + + if ( name === undefined ) throw new Error( 'THREE.KeyframeTrack: track name is undefined' ); + if ( times === undefined || times.length === 0 ) throw new Error( 'THREE.KeyframeTrack: no keyframes in track named ' + name ); + + this.name = name; + + this.times = convertArray( times, this.TimeBufferType ); + this.values = convertArray( values, this.ValueBufferType ); + + this.setInterpolation( interpolation || this.DefaultInterpolation ); + + } + + // Serialization (in static context, because of constructor invocation + // and automatic invocation of .toJSON): + + static toJSON( track ) { + + const trackType = track.constructor; + + let json; + + // derived classes can define a static toJSON method + if ( trackType.toJSON !== this.toJSON ) { + + json = trackType.toJSON( track ); + + } else { + + // by default, we assume the data can be serialized as-is + json = { + + 'name': track.name, + 'times': convertArray( track.times, Array ), + 'values': convertArray( track.values, Array ) + + }; + + const interpolation = track.getInterpolation(); + + if ( interpolation !== track.DefaultInterpolation ) { + + json.interpolation = interpolation; + + } + + } + + json.type = track.ValueTypeName; // mandatory + + return json; + + } + + InterpolantFactoryMethodDiscrete( result ) { + + return new DiscreteInterpolant( this.times, this.values, this.getValueSize(), result ); + + } + + InterpolantFactoryMethodLinear( result ) { + + return new LinearInterpolant( this.times, this.values, this.getValueSize(), result ); + + } + + InterpolantFactoryMethodSmooth( result ) { + + return new CubicInterpolant( this.times, this.values, this.getValueSize(), result ); + + } + + setInterpolation( interpolation ) { + + let factoryMethod; + + switch ( interpolation ) { + + case InterpolateDiscrete: + + factoryMethod = this.InterpolantFactoryMethodDiscrete; + + break; + + case InterpolateLinear: + + factoryMethod = this.InterpolantFactoryMethodLinear; + + break; + + case InterpolateSmooth: + + factoryMethod = this.InterpolantFactoryMethodSmooth; + + break; + + } + + if ( factoryMethod === undefined ) { + + const message = 'unsupported interpolation for ' + + this.ValueTypeName + ' keyframe track named ' + this.name; + + if ( this.createInterpolant === undefined ) { + + // fall back to default, unless the default itself is messed up + if ( interpolation !== this.DefaultInterpolation ) { + + this.setInterpolation( this.DefaultInterpolation ); + + } else { + + throw new Error( message ); // fatal, in this case + + } + + } + + console.warn( 'THREE.KeyframeTrack:', message ); + return this; + + } + + this.createInterpolant = factoryMethod; + + return this; + + } + + getInterpolation() { + + switch ( this.createInterpolant ) { + + case this.InterpolantFactoryMethodDiscrete: + + return InterpolateDiscrete; + + case this.InterpolantFactoryMethodLinear: + + return InterpolateLinear; + + case this.InterpolantFactoryMethodSmooth: + + return InterpolateSmooth; + + } + + } + + getValueSize() { + + return this.values.length / this.times.length; + + } + + // move all keyframes either forwards or backwards in time + shift( timeOffset ) { + + if ( timeOffset !== 0.0 ) { + + const times = this.times; + + for ( let i = 0, n = times.length; i !== n; ++ i ) { + + times[ i ] += timeOffset; + + } + + } + + return this; + + } + + // scale all keyframe times by a factor (useful for frame <-> seconds conversions) + scale( timeScale ) { + + if ( timeScale !== 1.0 ) { + + const times = this.times; + + for ( let i = 0, n = times.length; i !== n; ++ i ) { + + times[ i ] *= timeScale; + + } + + } + + return this; + + } + + // removes keyframes before and after animation without changing any values within the range [startTime, endTime]. + // IMPORTANT: We do not shift around keys to the start of the track time, because for interpolated keys this will change their values + trim( startTime, endTime ) { + + const times = this.times, + nKeys = times.length; + + let from = 0, + to = nKeys - 1; + + while ( from !== nKeys && times[ from ] < startTime ) { + + ++ from; + + } + + while ( to !== - 1 && times[ to ] > endTime ) { + + -- to; + + } + + ++ to; // inclusive -> exclusive bound + + if ( from !== 0 || to !== nKeys ) { + + // empty tracks are forbidden, so keep at least one keyframe + if ( from >= to ) { + + to = Math.max( to, 1 ); + from = to - 1; + + } + + const stride = this.getValueSize(); + this.times = times.slice( from, to ); + this.values = this.values.slice( from * stride, to * stride ); + + } + + return this; + + } + + // ensure we do not get a GarbageInGarbageOut situation, make sure tracks are at least minimally viable + validate() { + + let valid = true; + + const valueSize = this.getValueSize(); + if ( valueSize - Math.floor( valueSize ) !== 0 ) { + + console.error( 'THREE.KeyframeTrack: Invalid value size in track.', this ); + valid = false; + + } + + const times = this.times, + values = this.values, + + nKeys = times.length; + + if ( nKeys === 0 ) { + + console.error( 'THREE.KeyframeTrack: Track is empty.', this ); + valid = false; + + } + + let prevTime = null; + + for ( let i = 0; i !== nKeys; i ++ ) { + + const currTime = times[ i ]; + + if ( typeof currTime === 'number' && isNaN( currTime ) ) { + + console.error( 'THREE.KeyframeTrack: Time is not a valid number.', this, i, currTime ); + valid = false; + break; + + } + + if ( prevTime !== null && prevTime > currTime ) { + + console.error( 'THREE.KeyframeTrack: Out of order keys.', this, i, currTime, prevTime ); + valid = false; + break; + + } + + prevTime = currTime; + + } + + if ( values !== undefined ) { + + if ( isTypedArray( values ) ) { + + for ( let i = 0, n = values.length; i !== n; ++ i ) { + + const value = values[ i ]; + + if ( isNaN( value ) ) { + + console.error( 'THREE.KeyframeTrack: Value is not a valid number.', this, i, value ); + valid = false; + break; + + } + + } + + } + + } + + return valid; + + } + + // removes equivalent sequential keys as common in morph target sequences + // (0,0,0,0,1,1,1,0,0,0,0,0,0,0) --> (0,0,1,1,0,0) + optimize() { + + // times or values may be shared with other tracks, so overwriting is unsafe + const times = this.times.slice(), + values = this.values.slice(), + stride = this.getValueSize(), + + smoothInterpolation = this.getInterpolation() === InterpolateSmooth, + + lastIndex = times.length - 1; + + let writeIndex = 1; + + for ( let i = 1; i < lastIndex; ++ i ) { + + let keep = false; + + const time = times[ i ]; + const timeNext = times[ i + 1 ]; + + // remove adjacent keyframes scheduled at the same time + + if ( time !== timeNext && ( i !== 1 || time !== times[ 0 ] ) ) { + + if ( ! smoothInterpolation ) { + + // remove unnecessary keyframes same as their neighbors + + const offset = i * stride, + offsetP = offset - stride, + offsetN = offset + stride; + + for ( let j = 0; j !== stride; ++ j ) { + + const value = values[ offset + j ]; + + if ( value !== values[ offsetP + j ] || + value !== values[ offsetN + j ] ) { + + keep = true; + break; + + } + + } + + } else { + + keep = true; + + } + + } + + // in-place compaction + + if ( keep ) { + + if ( i !== writeIndex ) { + + times[ writeIndex ] = times[ i ]; + + const readOffset = i * stride, + writeOffset = writeIndex * stride; + + for ( let j = 0; j !== stride; ++ j ) { + + values[ writeOffset + j ] = values[ readOffset + j ]; + + } + + } + + ++ writeIndex; + + } + + } + + // flush last keyframe (compaction looks ahead) + + if ( lastIndex > 0 ) { + + times[ writeIndex ] = times[ lastIndex ]; + + for ( let readOffset = lastIndex * stride, writeOffset = writeIndex * stride, j = 0; j !== stride; ++ j ) { + + values[ writeOffset + j ] = values[ readOffset + j ]; + + } + + ++ writeIndex; + + } + + if ( writeIndex !== times.length ) { + + this.times = times.slice( 0, writeIndex ); + this.values = values.slice( 0, writeIndex * stride ); + + } else { + + this.times = times; + this.values = values; + + } + + return this; + + } + + clone() { + + const times = this.times.slice(); + const values = this.values.slice(); + + const TypedKeyframeTrack = this.constructor; + const track = new TypedKeyframeTrack( this.name, times, values ); + + // Interpolant argument to constructor is not saved, so copy the factory method directly. + track.createInterpolant = this.createInterpolant; + + return track; + + } + +} + +KeyframeTrack.prototype.TimeBufferType = Float32Array; +KeyframeTrack.prototype.ValueBufferType = Float32Array; +KeyframeTrack.prototype.DefaultInterpolation = InterpolateLinear; + +/** + * A Track of Boolean keyframe values. + */ +class BooleanKeyframeTrack extends KeyframeTrack { + + // No interpolation parameter because only InterpolateDiscrete is valid. + constructor( name, times, values ) { + + super( name, times, values ); + + } + +} + +BooleanKeyframeTrack.prototype.ValueTypeName = 'bool'; +BooleanKeyframeTrack.prototype.ValueBufferType = Array; +BooleanKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; +BooleanKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; +BooleanKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; + +/** + * A Track of keyframe values that represent color. + */ +class ColorKeyframeTrack extends KeyframeTrack {} + +ColorKeyframeTrack.prototype.ValueTypeName = 'color'; + +/** + * A Track of numeric keyframe values. + */ +class NumberKeyframeTrack extends KeyframeTrack {} + +NumberKeyframeTrack.prototype.ValueTypeName = 'number'; + +/** + * Spherical linear unit quaternion interpolant. + */ + +class QuaternionLinearInterpolant extends Interpolant { + + constructor( parameterPositions, sampleValues, sampleSize, resultBuffer ) { + + super( parameterPositions, sampleValues, sampleSize, resultBuffer ); + + } + + interpolate_( i1, t0, t, t1 ) { + + const result = this.resultBuffer, + values = this.sampleValues, + stride = this.valueSize, + + alpha = ( t - t0 ) / ( t1 - t0 ); + + let offset = i1 * stride; + + for ( let end = offset + stride; offset !== end; offset += 4 ) { + + Quaternion.slerpFlat( result, 0, values, offset - stride, values, offset, alpha ); + + } + + return result; + + } + +} + +/** + * A Track of quaternion keyframe values. + */ +class QuaternionKeyframeTrack extends KeyframeTrack { + + InterpolantFactoryMethodLinear( result ) { + + return new QuaternionLinearInterpolant( this.times, this.values, this.getValueSize(), result ); + + } + +} + +QuaternionKeyframeTrack.prototype.ValueTypeName = 'quaternion'; +// ValueBufferType is inherited +// DefaultInterpolation is inherited; +QuaternionKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; + +/** + * A Track that interpolates Strings + */ +class StringKeyframeTrack extends KeyframeTrack { + + // No interpolation parameter because only InterpolateDiscrete is valid. + constructor( name, times, values ) { + + super( name, times, values ); + + } + +} + +StringKeyframeTrack.prototype.ValueTypeName = 'string'; +StringKeyframeTrack.prototype.ValueBufferType = Array; +StringKeyframeTrack.prototype.DefaultInterpolation = InterpolateDiscrete; +StringKeyframeTrack.prototype.InterpolantFactoryMethodLinear = undefined; +StringKeyframeTrack.prototype.InterpolantFactoryMethodSmooth = undefined; + +/** + * A Track of vectored keyframe values. + */ +class VectorKeyframeTrack extends KeyframeTrack {} + +VectorKeyframeTrack.prototype.ValueTypeName = 'vector'; + +class AnimationClip { + + constructor( name = '', duration = - 1, tracks = [], blendMode = NormalAnimationBlendMode ) { + + this.name = name; + this.tracks = tracks; + this.duration = duration; + this.blendMode = blendMode; + + this.uuid = generateUUID(); + + // this means it should figure out its duration by scanning the tracks + if ( this.duration < 0 ) { + + this.resetDuration(); + + } + + } + + + static parse( json ) { + + const tracks = [], + jsonTracks = json.tracks, + frameTime = 1.0 / ( json.fps || 1.0 ); + + for ( let i = 0, n = jsonTracks.length; i !== n; ++ i ) { + + tracks.push( parseKeyframeTrack( jsonTracks[ i ] ).scale( frameTime ) ); + + } + + const clip = new this( json.name, json.duration, tracks, json.blendMode ); + clip.uuid = json.uuid; + + return clip; + + } + + static toJSON( clip ) { + + const tracks = [], + clipTracks = clip.tracks; + + const json = { + + 'name': clip.name, + 'duration': clip.duration, + 'tracks': tracks, + 'uuid': clip.uuid, + 'blendMode': clip.blendMode + + }; + + for ( let i = 0, n = clipTracks.length; i !== n; ++ i ) { + + tracks.push( KeyframeTrack.toJSON( clipTracks[ i ] ) ); + + } + + return json; + + } + + static CreateFromMorphTargetSequence( name, morphTargetSequence, fps, noLoop ) { + + const numMorphTargets = morphTargetSequence.length; + const tracks = []; + + for ( let i = 0; i < numMorphTargets; i ++ ) { + + let times = []; + let values = []; + + times.push( + ( i + numMorphTargets - 1 ) % numMorphTargets, + i, + ( i + 1 ) % numMorphTargets ); + + values.push( 0, 1, 0 ); + + const order = getKeyframeOrder( times ); + times = sortedArray( times, 1, order ); + values = sortedArray( values, 1, order ); + + // if there is a key at the first frame, duplicate it as the + // last frame as well for perfect loop. + if ( ! noLoop && times[ 0 ] === 0 ) { + + times.push( numMorphTargets ); + values.push( values[ 0 ] ); + + } + + tracks.push( + new NumberKeyframeTrack( + '.morphTargetInfluences[' + morphTargetSequence[ i ].name + ']', + times, values + ).scale( 1.0 / fps ) ); + + } + + return new this( name, - 1, tracks ); + + } + + static findByName( objectOrClipArray, name ) { + + let clipArray = objectOrClipArray; + + if ( ! Array.isArray( objectOrClipArray ) ) { + + const o = objectOrClipArray; + clipArray = o.geometry && o.geometry.animations || o.animations; + + } + + for ( let i = 0; i < clipArray.length; i ++ ) { + + if ( clipArray[ i ].name === name ) { + + return clipArray[ i ]; + + } + + } + + return null; + + } + + static CreateClipsFromMorphTargetSequences( morphTargets, fps, noLoop ) { + + const animationToMorphTargets = {}; + + // tested with https://regex101.com/ on trick sequences + // such flamingo_flyA_003, flamingo_run1_003, crdeath0059 + const pattern = /^([\w-]*?)([\d]+)$/; + + // sort morph target names into animation groups based + // patterns like Walk_001, Walk_002, Run_001, Run_002 + for ( let i = 0, il = morphTargets.length; i < il; i ++ ) { + + const morphTarget = morphTargets[ i ]; + const parts = morphTarget.name.match( pattern ); + + if ( parts && parts.length > 1 ) { + + const name = parts[ 1 ]; + + let animationMorphTargets = animationToMorphTargets[ name ]; + + if ( ! animationMorphTargets ) { + + animationToMorphTargets[ name ] = animationMorphTargets = []; + + } + + animationMorphTargets.push( morphTarget ); + + } + + } + + const clips = []; + + for ( const name in animationToMorphTargets ) { + + clips.push( this.CreateFromMorphTargetSequence( name, animationToMorphTargets[ name ], fps, noLoop ) ); + + } + + return clips; + + } + + // parse the animation.hierarchy format + static parseAnimation( animation, bones ) { + + if ( ! animation ) { + + console.error( 'THREE.AnimationClip: No animation in JSONLoader data.' ); + return null; + + } + + const addNonemptyTrack = function ( trackType, trackName, animationKeys, propertyName, destTracks ) { + + // only return track if there are actually keys. + if ( animationKeys.length !== 0 ) { + + const times = []; + const values = []; + + flattenJSON( animationKeys, times, values, propertyName ); + + // empty keys are filtered out, so check again + if ( times.length !== 0 ) { + + destTracks.push( new trackType( trackName, times, values ) ); + + } + + } + + }; + + const tracks = []; + + const clipName = animation.name || 'default'; + const fps = animation.fps || 30; + const blendMode = animation.blendMode; + + // automatic length determination in AnimationClip. + let duration = animation.length || - 1; + + const hierarchyTracks = animation.hierarchy || []; + + for ( let h = 0; h < hierarchyTracks.length; h ++ ) { + + const animationKeys = hierarchyTracks[ h ].keys; + + // skip empty tracks + if ( ! animationKeys || animationKeys.length === 0 ) continue; + + // process morph targets + if ( animationKeys[ 0 ].morphTargets ) { + + // figure out all morph targets used in this track + const morphTargetNames = {}; + + let k; + + for ( k = 0; k < animationKeys.length; k ++ ) { + + if ( animationKeys[ k ].morphTargets ) { + + for ( let m = 0; m < animationKeys[ k ].morphTargets.length; m ++ ) { + + morphTargetNames[ animationKeys[ k ].morphTargets[ m ] ] = - 1; + + } + + } + + } + + // create a track for each morph target with all zero + // morphTargetInfluences except for the keys in which + // the morphTarget is named. + for ( const morphTargetName in morphTargetNames ) { + + const times = []; + const values = []; + + for ( let m = 0; m !== animationKeys[ k ].morphTargets.length; ++ m ) { + + const animationKey = animationKeys[ k ]; + + times.push( animationKey.time ); + values.push( ( animationKey.morphTarget === morphTargetName ) ? 1 : 0 ); + + } + + tracks.push( new NumberKeyframeTrack( '.morphTargetInfluence[' + morphTargetName + ']', times, values ) ); + + } + + duration = morphTargetNames.length * fps; + + } else { + + // ...assume skeletal animation + + const boneName = '.bones[' + bones[ h ].name + ']'; + + addNonemptyTrack( + VectorKeyframeTrack, boneName + '.position', + animationKeys, 'pos', tracks ); + + addNonemptyTrack( + QuaternionKeyframeTrack, boneName + '.quaternion', + animationKeys, 'rot', tracks ); + + addNonemptyTrack( + VectorKeyframeTrack, boneName + '.scale', + animationKeys, 'scl', tracks ); + + } + + } + + if ( tracks.length === 0 ) { + + return null; + + } + + const clip = new this( clipName, duration, tracks, blendMode ); + + return clip; + + } + + resetDuration() { + + const tracks = this.tracks; + let duration = 0; + + for ( let i = 0, n = tracks.length; i !== n; ++ i ) { + + const track = this.tracks[ i ]; + + duration = Math.max( duration, track.times[ track.times.length - 1 ] ); + + } + + this.duration = duration; + + return this; + + } + + trim() { + + for ( let i = 0; i < this.tracks.length; i ++ ) { + + this.tracks[ i ].trim( 0, this.duration ); + + } + + return this; + + } + + validate() { + + let valid = true; + + for ( let i = 0; i < this.tracks.length; i ++ ) { + + valid = valid && this.tracks[ i ].validate(); + + } + + return valid; + + } + + optimize() { + + for ( let i = 0; i < this.tracks.length; i ++ ) { + + this.tracks[ i ].optimize(); + + } + + return this; + + } + + clone() { + + const tracks = []; + + for ( let i = 0; i < this.tracks.length; i ++ ) { + + tracks.push( this.tracks[ i ].clone() ); + + } + + return new this.constructor( this.name, this.duration, tracks, this.blendMode ); + + } + + toJSON() { + + return this.constructor.toJSON( this ); + + } + +} + +function getTrackTypeForValueTypeName( typeName ) { + + switch ( typeName.toLowerCase() ) { + + case 'scalar': + case 'double': + case 'float': + case 'number': + case 'integer': + + return NumberKeyframeTrack; + + case 'vector': + case 'vector2': + case 'vector3': + case 'vector4': + + return VectorKeyframeTrack; + + case 'color': + + return ColorKeyframeTrack; + + case 'quaternion': + + return QuaternionKeyframeTrack; + + case 'bool': + case 'boolean': + + return BooleanKeyframeTrack; + + case 'string': + + return StringKeyframeTrack; + + } + + throw new Error( 'THREE.KeyframeTrack: Unsupported typeName: ' + typeName ); + +} + +function parseKeyframeTrack( json ) { + + if ( json.type === undefined ) { + + throw new Error( 'THREE.KeyframeTrack: track type undefined, can not parse' ); + + } + + const trackType = getTrackTypeForValueTypeName( json.type ); + + if ( json.times === undefined ) { + + const times = [], values = []; + + flattenJSON( json.keys, times, values, 'value' ); + + json.times = times; + json.values = values; + + } + + // derived classes can define a static parse method + if ( trackType.parse !== undefined ) { + + return trackType.parse( json ); + + } else { + + // by default, we assume a constructor compatible with the base + return new trackType( json.name, json.times, json.values, json.interpolation ); + + } + +} + +const Cache = { + + enabled: false, + + files: {}, + + add: function ( key, file ) { + + if ( this.enabled === false ) return; + + // console.log( 'THREE.Cache', 'Adding key:', key ); + + this.files[ key ] = file; + + }, + + get: function ( key ) { + + if ( this.enabled === false ) return; + + // console.log( 'THREE.Cache', 'Checking key:', key ); + + return this.files[ key ]; + + }, + + remove: function ( key ) { + + delete this.files[ key ]; + + }, + + clear: function () { + + this.files = {}; + + } + +}; + +class LoadingManager { + + constructor( onLoad, onProgress, onError ) { + + const scope = this; + + let isLoading = false; + let itemsLoaded = 0; + let itemsTotal = 0; + let urlModifier = undefined; + const handlers = []; + + // Refer to #5689 for the reason why we don't set .onStart + // in the constructor + + this.onStart = undefined; + this.onLoad = onLoad; + this.onProgress = onProgress; + this.onError = onError; + + this.itemStart = function ( url ) { + + itemsTotal ++; + + if ( isLoading === false ) { + + if ( scope.onStart !== undefined ) { + + scope.onStart( url, itemsLoaded, itemsTotal ); + + } + + } + + isLoading = true; + + }; + + this.itemEnd = function ( url ) { + + itemsLoaded ++; + + if ( scope.onProgress !== undefined ) { + + scope.onProgress( url, itemsLoaded, itemsTotal ); + + } + + if ( itemsLoaded === itemsTotal ) { + + isLoading = false; + + if ( scope.onLoad !== undefined ) { + + scope.onLoad(); + + } + + } + + }; + + this.itemError = function ( url ) { + + if ( scope.onError !== undefined ) { + + scope.onError( url ); + + } + + }; + + this.resolveURL = function ( url ) { + + if ( urlModifier ) { + + return urlModifier( url ); + + } + + return url; + + }; + + this.setURLModifier = function ( transform ) { + + urlModifier = transform; + + return this; + + }; + + this.addHandler = function ( regex, loader ) { + + handlers.push( regex, loader ); + + return this; + + }; + + this.removeHandler = function ( regex ) { + + const index = handlers.indexOf( regex ); + + if ( index !== - 1 ) { + + handlers.splice( index, 2 ); + + } + + return this; + + }; + + this.getHandler = function ( file ) { + + for ( let i = 0, l = handlers.length; i < l; i += 2 ) { + + const regex = handlers[ i ]; + const loader = handlers[ i + 1 ]; + + if ( regex.global ) regex.lastIndex = 0; // see #17920 + + if ( regex.test( file ) ) { + + return loader; + + } + + } + + return null; + + }; + + } + +} + +const DefaultLoadingManager = /*@__PURE__*/ new LoadingManager(); + +class Loader { + + constructor( manager ) { + + this.manager = ( manager !== undefined ) ? manager : DefaultLoadingManager; + + this.crossOrigin = 'anonymous'; + this.withCredentials = false; + this.path = ''; + this.resourcePath = ''; + this.requestHeader = {}; + + } + + load( /* url, onLoad, onProgress, onError */ ) {} + + loadAsync( url, onProgress ) { + + const scope = this; + + return new Promise( function ( resolve, reject ) { + + scope.load( url, resolve, onProgress, reject ); + + } ); + + } + + parse( /* data */ ) {} + + setCrossOrigin( crossOrigin ) { + + this.crossOrigin = crossOrigin; + return this; + + } + + setWithCredentials( value ) { + + this.withCredentials = value; + return this; + + } + + setPath( path ) { + + this.path = path; + return this; + + } + + setResourcePath( resourcePath ) { + + this.resourcePath = resourcePath; + return this; + + } + + setRequestHeader( requestHeader ) { + + this.requestHeader = requestHeader; + return this; + + } + +} + +Loader.DEFAULT_MATERIAL_NAME = '__DEFAULT'; + +const loading = {}; + +class HttpError extends Error { + + constructor( message, response ) { + + super( message ); + this.response = response; + + } + +} + +class FileLoader extends Loader { + + constructor( manager ) { + + super( manager ); + + } + + load( url, onLoad, onProgress, onError ) { + + if ( url === undefined ) url = ''; + + if ( this.path !== undefined ) url = this.path + url; + + url = this.manager.resolveURL( url ); + + const cached = Cache.get( url ); + + if ( cached !== undefined ) { + + this.manager.itemStart( url ); + + setTimeout( () => { + + if ( onLoad ) onLoad( cached ); + + this.manager.itemEnd( url ); + + }, 0 ); + + return cached; + + } + + // Check if request is duplicate + + if ( loading[ url ] !== undefined ) { + + loading[ url ].push( { + + onLoad: onLoad, + onProgress: onProgress, + onError: onError + + } ); + + return; + + } + + // Initialise array for duplicate requests + loading[ url ] = []; + + loading[ url ].push( { + onLoad: onLoad, + onProgress: onProgress, + onError: onError, + } ); + + // create request + const req = new Request( url, { + headers: new Headers( this.requestHeader ), + credentials: this.withCredentials ? 'include' : 'same-origin', + // An abort controller could be added within a future PR + } ); + + // record states ( avoid data race ) + const mimeType = this.mimeType; + const responseType = this.responseType; + + // start the fetch + fetch( req ) + .then( response => { + + if ( response.status === 200 || response.status === 0 ) { + + // Some browsers return HTTP Status 0 when using non-http protocol + // e.g. 'file://' or 'data://'. Handle as success. + + if ( response.status === 0 ) { + + console.warn( 'THREE.FileLoader: HTTP Status 0 received.' ); + + } + + // Workaround: Checking if response.body === undefined for Alipay browser #23548 + + if ( typeof ReadableStream === 'undefined' || response.body === undefined || response.body.getReader === undefined ) { + + return response; + + } + + const callbacks = loading[ url ]; + const reader = response.body.getReader(); + + // Nginx needs X-File-Size check + // https://serverfault.com/questions/482875/why-does-nginx-remove-content-length-header-for-chunked-content + const contentLength = response.headers.get( 'X-File-Size' ) || response.headers.get( 'Content-Length' ); + const total = contentLength ? parseInt( contentLength ) : 0; + const lengthComputable = total !== 0; + let loaded = 0; + + // periodically read data into the new stream tracking while download progress + const stream = new ReadableStream( { + start( controller ) { + + readData(); + + function readData() { + + reader.read().then( ( { done, value } ) => { + + if ( done ) { + + controller.close(); + + } else { + + loaded += value.byteLength; + + const event = new ProgressEvent( 'progress', { lengthComputable, loaded, total } ); + for ( let i = 0, il = callbacks.length; i < il; i ++ ) { + + const callback = callbacks[ i ]; + if ( callback.onProgress ) callback.onProgress( event ); + + } + + controller.enqueue( value ); + readData(); + + } + + }, ( e ) => { + + controller.error( e ); + + } ); + + } + + } + + } ); + + return new Response( stream ); + + } else { + + throw new HttpError( `fetch for "${response.url}" responded with ${response.status}: ${response.statusText}`, response ); + + } + + } ) + .then( response => { + + switch ( responseType ) { + + case 'arraybuffer': + + return response.arrayBuffer(); + + case 'blob': + + return response.blob(); + + case 'document': + + return response.text() + .then( text => { + + const parser = new DOMParser(); + return parser.parseFromString( text, mimeType ); + + } ); + + case 'json': + + return response.json(); + + default: + + if ( mimeType === undefined ) { + + return response.text(); + + } else { + + // sniff encoding + const re = /charset="?([^;"\s]*)"?/i; + const exec = re.exec( mimeType ); + const label = exec && exec[ 1 ] ? exec[ 1 ].toLowerCase() : undefined; + const decoder = new TextDecoder( label ); + return response.arrayBuffer().then( ab => decoder.decode( ab ) ); + + } + + } + + } ) + .then( data => { + + // Add to cache only on HTTP success, so that we do not cache + // error response bodies as proper responses to requests. + Cache.add( url, data ); + + const callbacks = loading[ url ]; + delete loading[ url ]; + + for ( let i = 0, il = callbacks.length; i < il; i ++ ) { + + const callback = callbacks[ i ]; + if ( callback.onLoad ) callback.onLoad( data ); + + } + + } ) + .catch( err => { + + // Abort errors and other errors are handled the same + + const callbacks = loading[ url ]; + + if ( callbacks === undefined ) { + + // When onLoad was called and url was deleted in `loading` + this.manager.itemError( url ); + throw err; + + } + + delete loading[ url ]; + + for ( let i = 0, il = callbacks.length; i < il; i ++ ) { + + const callback = callbacks[ i ]; + if ( callback.onError ) callback.onError( err ); + + } + + this.manager.itemError( url ); + + } ) + .finally( () => { + + this.manager.itemEnd( url ); + + } ); + + this.manager.itemStart( url ); + + } + + setResponseType( value ) { + + this.responseType = value; + return this; + + } + + setMimeType( value ) { + + this.mimeType = value; + return this; + + } + +} + +class AnimationLoader extends Loader { + + constructor( manager ) { + + super( manager ); + + } + + load( url, onLoad, onProgress, onError ) { + + const scope = this; + + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + loader.load( url, function ( text ) { + + try { + + onLoad( scope.parse( JSON.parse( text ) ) ); + + } catch ( e ) { + + if ( onError ) { + + onError( e ); + + } else { + + console.error( e ); + + } + + scope.manager.itemError( url ); + + } + + }, onProgress, onError ); + + } + + parse( json ) { + + const animations = []; + + for ( let i = 0; i < json.length; i ++ ) { + + const clip = AnimationClip.parse( json[ i ] ); + + animations.push( clip ); + + } + + return animations; + + } + +} + +/** + * Abstract Base class to block based textures loader (dds, pvr, ...) + * + * Sub classes have to implement the parse() method which will be used in load(). + */ + +class CompressedTextureLoader extends Loader { + + constructor( manager ) { + + super( manager ); + + } + + load( url, onLoad, onProgress, onError ) { + + const scope = this; + + const images = []; + + const texture = new CompressedTexture(); + + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setResponseType( 'arraybuffer' ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( scope.withCredentials ); + + let loaded = 0; + + function loadTexture( i ) { + + loader.load( url[ i ], function ( buffer ) { + + const texDatas = scope.parse( buffer, true ); + + images[ i ] = { + width: texDatas.width, + height: texDatas.height, + format: texDatas.format, + mipmaps: texDatas.mipmaps + }; + + loaded += 1; + + if ( loaded === 6 ) { + + if ( texDatas.mipmapCount === 1 ) texture.minFilter = LinearFilter; + + texture.image = images; + texture.format = texDatas.format; + texture.needsUpdate = true; + + if ( onLoad ) onLoad( texture ); + + } + + }, onProgress, onError ); + + } + + if ( Array.isArray( url ) ) { + + for ( let i = 0, il = url.length; i < il; ++ i ) { + + loadTexture( i ); + + } + + } else { + + // compressed cubemap texture stored in a single DDS file + + loader.load( url, function ( buffer ) { + + const texDatas = scope.parse( buffer, true ); + + if ( texDatas.isCubemap ) { + + const faces = texDatas.mipmaps.length / texDatas.mipmapCount; + + for ( let f = 0; f < faces; f ++ ) { + + images[ f ] = { mipmaps: [] }; + + for ( let i = 0; i < texDatas.mipmapCount; i ++ ) { + + images[ f ].mipmaps.push( texDatas.mipmaps[ f * texDatas.mipmapCount + i ] ); + images[ f ].format = texDatas.format; + images[ f ].width = texDatas.width; + images[ f ].height = texDatas.height; + + } + + } + + texture.image = images; + + } else { + + texture.image.width = texDatas.width; + texture.image.height = texDatas.height; + texture.mipmaps = texDatas.mipmaps; + + } + + if ( texDatas.mipmapCount === 1 ) { + + texture.minFilter = LinearFilter; + + } + + texture.format = texDatas.format; + texture.needsUpdate = true; + + if ( onLoad ) onLoad( texture ); + + }, onProgress, onError ); + + } + + return texture; + + } + +} + +class ImageLoader extends Loader { + + constructor( manager ) { + + super( manager ); + + } + + load( url, onLoad, onProgress, onError ) { + + if ( this.path !== undefined ) url = this.path + url; + + url = this.manager.resolveURL( url ); + + const scope = this; + + const cached = Cache.get( url ); + + if ( cached !== undefined ) { + + scope.manager.itemStart( url ); + + setTimeout( function () { + + if ( onLoad ) onLoad( cached ); + + scope.manager.itemEnd( url ); + + }, 0 ); + + return cached; + + } + + const image = createElementNS( 'img' ); + + function onImageLoad() { + + removeEventListeners(); + + Cache.add( url, this ); + + if ( onLoad ) onLoad( this ); + + scope.manager.itemEnd( url ); + + } + + function onImageError( event ) { + + removeEventListeners(); + + if ( onError ) onError( event ); + + scope.manager.itemError( url ); + scope.manager.itemEnd( url ); + + } + + function removeEventListeners() { + + image.removeEventListener( 'load', onImageLoad, false ); + image.removeEventListener( 'error', onImageError, false ); + + } + + image.addEventListener( 'load', onImageLoad, false ); + image.addEventListener( 'error', onImageError, false ); + + if ( url.slice( 0, 5 ) !== 'data:' ) { + + if ( this.crossOrigin !== undefined ) image.crossOrigin = this.crossOrigin; + + } + + scope.manager.itemStart( url ); + + image.src = url; + + return image; + + } + +} + +class CubeTextureLoader extends Loader { + + constructor( manager ) { + + super( manager ); + + } + + load( urls, onLoad, onProgress, onError ) { + + const texture = new CubeTexture(); + texture.colorSpace = SRGBColorSpace; + + const loader = new ImageLoader( this.manager ); + loader.setCrossOrigin( this.crossOrigin ); + loader.setPath( this.path ); + + let loaded = 0; + + function loadTexture( i ) { + + loader.load( urls[ i ], function ( image ) { + + texture.images[ i ] = image; + + loaded ++; + + if ( loaded === 6 ) { + + texture.needsUpdate = true; + + if ( onLoad ) onLoad( texture ); + + } + + }, undefined, onError ); + + } + + for ( let i = 0; i < urls.length; ++ i ) { + + loadTexture( i ); + + } + + return texture; + + } + +} + +/** + * Abstract Base class to load generic binary textures formats (rgbe, hdr, ...) + * + * Sub classes have to implement the parse() method which will be used in load(). + */ + +class DataTextureLoader extends Loader { + + constructor( manager ) { + + super( manager ); + + } + + load( url, onLoad, onProgress, onError ) { + + const scope = this; + + const texture = new DataTexture(); + + const loader = new FileLoader( this.manager ); + loader.setResponseType( 'arraybuffer' ); + loader.setRequestHeader( this.requestHeader ); + loader.setPath( this.path ); + loader.setWithCredentials( scope.withCredentials ); + loader.load( url, function ( buffer ) { + + let texData; + + try { + + texData = scope.parse( buffer ); + + } catch ( error ) { + + if ( onError !== undefined ) { + + onError( error ); + + } else { + + console.error( error ); + return; + + } + + } + + if ( texData.image !== undefined ) { + + texture.image = texData.image; + + } else if ( texData.data !== undefined ) { + + texture.image.width = texData.width; + texture.image.height = texData.height; + texture.image.data = texData.data; + + } + + texture.wrapS = texData.wrapS !== undefined ? texData.wrapS : ClampToEdgeWrapping; + texture.wrapT = texData.wrapT !== undefined ? texData.wrapT : ClampToEdgeWrapping; + + texture.magFilter = texData.magFilter !== undefined ? texData.magFilter : LinearFilter; + texture.minFilter = texData.minFilter !== undefined ? texData.minFilter : LinearFilter; + + texture.anisotropy = texData.anisotropy !== undefined ? texData.anisotropy : 1; + + if ( texData.colorSpace !== undefined ) { + + texture.colorSpace = texData.colorSpace; + + } + + if ( texData.flipY !== undefined ) { + + texture.flipY = texData.flipY; + + } + + if ( texData.format !== undefined ) { + + texture.format = texData.format; + + } + + if ( texData.type !== undefined ) { + + texture.type = texData.type; + + } + + if ( texData.mipmaps !== undefined ) { + + texture.mipmaps = texData.mipmaps; + texture.minFilter = LinearMipmapLinearFilter; // presumably... + + } + + if ( texData.mipmapCount === 1 ) { + + texture.minFilter = LinearFilter; + + } + + if ( texData.generateMipmaps !== undefined ) { + + texture.generateMipmaps = texData.generateMipmaps; + + } + + texture.needsUpdate = true; + + if ( onLoad ) onLoad( texture, texData ); + + }, onProgress, onError ); + + + return texture; + + } + +} + +class TextureLoader extends Loader { + + constructor( manager ) { + + super( manager ); + + } + + load( url, onLoad, onProgress, onError ) { + + const texture = new Texture(); + + const loader = new ImageLoader( this.manager ); + loader.setCrossOrigin( this.crossOrigin ); + loader.setPath( this.path ); + + loader.load( url, function ( image ) { + + texture.image = image; + texture.needsUpdate = true; + + if ( onLoad !== undefined ) { + + onLoad( texture ); + + } + + }, onProgress, onError ); + + return texture; + + } + +} + +class Light extends Object3D { + + constructor( color, intensity = 1 ) { + + super(); + + this.isLight = true; + + this.type = 'Light'; + + this.color = new Color( color ); + this.intensity = intensity; + + } + + dispose() { + + // Empty here in base class; some subclasses override. + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + this.color.copy( source.color ); + this.intensity = source.intensity; + + return this; + + } + + toJSON( meta ) { + + const data = super.toJSON( meta ); + + data.object.color = this.color.getHex(); + data.object.intensity = this.intensity; + + if ( this.groundColor !== undefined ) data.object.groundColor = this.groundColor.getHex(); + + if ( this.distance !== undefined ) data.object.distance = this.distance; + if ( this.angle !== undefined ) data.object.angle = this.angle; + if ( this.decay !== undefined ) data.object.decay = this.decay; + if ( this.penumbra !== undefined ) data.object.penumbra = this.penumbra; + + if ( this.shadow !== undefined ) data.object.shadow = this.shadow.toJSON(); + if ( this.target !== undefined ) data.object.target = this.target.uuid; + + return data; + + } + +} + +class HemisphereLight extends Light { + + constructor( skyColor, groundColor, intensity ) { + + super( skyColor, intensity ); + + this.isHemisphereLight = true; + + this.type = 'HemisphereLight'; + + this.position.copy( Object3D.DEFAULT_UP ); + this.updateMatrix(); + + this.groundColor = new Color( groundColor ); + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + this.groundColor.copy( source.groundColor ); + + return this; + + } + +} + +const _projScreenMatrix$2 = /*@__PURE__*/ new Matrix4(); +const _lightPositionWorld$1 = /*@__PURE__*/ new Vector3(); +const _lookTarget$1 = /*@__PURE__*/ new Vector3(); + +class LightShadow { + + constructor( camera ) { + + this.camera = camera; + + this.intensity = 1; + + this.bias = 0; + this.normalBias = 0; + this.radius = 1; + this.blurSamples = 8; + + this.mapSize = new Vector2( 512, 512 ); + + this.map = null; + this.mapPass = null; + this.matrix = new Matrix4(); + + this.autoUpdate = true; + this.needsUpdate = false; + + this._frustum = new Frustum(); + this._frameExtents = new Vector2( 1, 1 ); + + this._viewportCount = 1; + + this._viewports = [ + + new Vector4( 0, 0, 1, 1 ) + + ]; + + } + + getViewportCount() { + + return this._viewportCount; + + } + + getFrustum() { + + return this._frustum; + + } + + updateMatrices( light ) { + + const shadowCamera = this.camera; + const shadowMatrix = this.matrix; + + _lightPositionWorld$1.setFromMatrixPosition( light.matrixWorld ); + shadowCamera.position.copy( _lightPositionWorld$1 ); + + _lookTarget$1.setFromMatrixPosition( light.target.matrixWorld ); + shadowCamera.lookAt( _lookTarget$1 ); + shadowCamera.updateMatrixWorld(); + + _projScreenMatrix$2.multiplyMatrices( shadowCamera.projectionMatrix, shadowCamera.matrixWorldInverse ); + this._frustum.setFromProjectionMatrix( _projScreenMatrix$2 ); + + shadowMatrix.set( + 0.5, 0.0, 0.0, 0.5, + 0.0, 0.5, 0.0, 0.5, + 0.0, 0.0, 0.5, 0.5, + 0.0, 0.0, 0.0, 1.0 + ); + + shadowMatrix.multiply( _projScreenMatrix$2 ); + + } + + getViewport( viewportIndex ) { + + return this._viewports[ viewportIndex ]; + + } + + getFrameExtents() { + + return this._frameExtents; + + } + + dispose() { + + if ( this.map ) { + + this.map.dispose(); + + } + + if ( this.mapPass ) { + + this.mapPass.dispose(); + + } + + } + + copy( source ) { + + this.camera = source.camera.clone(); + + this.intensity = source.intensity; + + this.bias = source.bias; + this.radius = source.radius; + + this.mapSize.copy( source.mapSize ); + + return this; + + } + + clone() { + + return new this.constructor().copy( this ); + + } + + toJSON() { + + const object = {}; + + if ( this.intensity !== 1 ) object.intensity = this.intensity; + if ( this.bias !== 0 ) object.bias = this.bias; + if ( this.normalBias !== 0 ) object.normalBias = this.normalBias; + if ( this.radius !== 1 ) object.radius = this.radius; + if ( this.mapSize.x !== 512 || this.mapSize.y !== 512 ) object.mapSize = this.mapSize.toArray(); + + object.camera = this.camera.toJSON( false ).object; + delete object.camera.matrix; + + return object; + + } + +} + +class SpotLightShadow extends LightShadow { + + constructor() { + + super( new PerspectiveCamera( 50, 1, 0.5, 500 ) ); + + this.isSpotLightShadow = true; + + this.focus = 1; + + } + + updateMatrices( light ) { + + const camera = this.camera; + + const fov = RAD2DEG * 2 * light.angle * this.focus; + const aspect = this.mapSize.width / this.mapSize.height; + const far = light.distance || camera.far; + + if ( fov !== camera.fov || aspect !== camera.aspect || far !== camera.far ) { + + camera.fov = fov; + camera.aspect = aspect; + camera.far = far; + camera.updateProjectionMatrix(); + + } + + super.updateMatrices( light ); + + } + + copy( source ) { + + super.copy( source ); + + this.focus = source.focus; + + return this; + + } + +} + +class SpotLight extends Light { + + constructor( color, intensity, distance = 0, angle = Math.PI / 3, penumbra = 0, decay = 2 ) { + + super( color, intensity ); + + this.isSpotLight = true; + + this.type = 'SpotLight'; + + this.position.copy( Object3D.DEFAULT_UP ); + this.updateMatrix(); + + this.target = new Object3D(); + + this.distance = distance; + this.angle = angle; + this.penumbra = penumbra; + this.decay = decay; + + this.map = null; + + this.shadow = new SpotLightShadow(); + + } + + get power() { + + // compute the light's luminous power (in lumens) from its intensity (in candela) + // by convention for a spotlight, luminous power (lm) = π * luminous intensity (cd) + return this.intensity * Math.PI; + + } + + set power( power ) { + + // set the light's intensity (in candela) from the desired luminous power (in lumens) + this.intensity = power / Math.PI; + + } + + dispose() { + + this.shadow.dispose(); + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + this.distance = source.distance; + this.angle = source.angle; + this.penumbra = source.penumbra; + this.decay = source.decay; + + this.target = source.target.clone(); + + this.shadow = source.shadow.clone(); + + return this; + + } + +} + +const _projScreenMatrix$1 = /*@__PURE__*/ new Matrix4(); +const _lightPositionWorld = /*@__PURE__*/ new Vector3(); +const _lookTarget = /*@__PURE__*/ new Vector3(); + +class PointLightShadow extends LightShadow { + + constructor() { + + super( new PerspectiveCamera( 90, 1, 0.5, 500 ) ); + + this.isPointLightShadow = true; + + this._frameExtents = new Vector2( 4, 2 ); + + this._viewportCount = 6; + + this._viewports = [ + // These viewports map a cube-map onto a 2D texture with the + // following orientation: + // + // xzXZ + // y Y + // + // X - Positive x direction + // x - Negative x direction + // Y - Positive y direction + // y - Negative y direction + // Z - Positive z direction + // z - Negative z direction + + // positive X + new Vector4( 2, 1, 1, 1 ), + // negative X + new Vector4( 0, 1, 1, 1 ), + // positive Z + new Vector4( 3, 1, 1, 1 ), + // negative Z + new Vector4( 1, 1, 1, 1 ), + // positive Y + new Vector4( 3, 0, 1, 1 ), + // negative Y + new Vector4( 1, 0, 1, 1 ) + ]; + + this._cubeDirections = [ + new Vector3( 1, 0, 0 ), new Vector3( - 1, 0, 0 ), new Vector3( 0, 0, 1 ), + new Vector3( 0, 0, - 1 ), new Vector3( 0, 1, 0 ), new Vector3( 0, - 1, 0 ) + ]; + + this._cubeUps = [ + new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), new Vector3( 0, 1, 0 ), + new Vector3( 0, 1, 0 ), new Vector3( 0, 0, 1 ), new Vector3( 0, 0, - 1 ) + ]; + + } + + updateMatrices( light, viewportIndex = 0 ) { + + const camera = this.camera; + const shadowMatrix = this.matrix; + + const far = light.distance || camera.far; + + if ( far !== camera.far ) { + + camera.far = far; + camera.updateProjectionMatrix(); + + } + + _lightPositionWorld.setFromMatrixPosition( light.matrixWorld ); + camera.position.copy( _lightPositionWorld ); + + _lookTarget.copy( camera.position ); + _lookTarget.add( this._cubeDirections[ viewportIndex ] ); + camera.up.copy( this._cubeUps[ viewportIndex ] ); + camera.lookAt( _lookTarget ); + camera.updateMatrixWorld(); + + shadowMatrix.makeTranslation( - _lightPositionWorld.x, - _lightPositionWorld.y, - _lightPositionWorld.z ); + + _projScreenMatrix$1.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); + this._frustum.setFromProjectionMatrix( _projScreenMatrix$1 ); + + } + +} + +class PointLight extends Light { + + constructor( color, intensity, distance = 0, decay = 2 ) { + + super( color, intensity ); + + this.isPointLight = true; + + this.type = 'PointLight'; + + this.distance = distance; + this.decay = decay; + + this.shadow = new PointLightShadow(); + + } + + get power() { + + // compute the light's luminous power (in lumens) from its intensity (in candela) + // for an isotropic light source, luminous power (lm) = 4 π luminous intensity (cd) + return this.intensity * 4 * Math.PI; + + } + + set power( power ) { + + // set the light's intensity (in candela) from the desired luminous power (in lumens) + this.intensity = power / ( 4 * Math.PI ); + + } + + dispose() { + + this.shadow.dispose(); + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + this.distance = source.distance; + this.decay = source.decay; + + this.shadow = source.shadow.clone(); + + return this; + + } + +} + +class OrthographicCamera extends Camera { + + constructor( left = - 1, right = 1, top = 1, bottom = - 1, near = 0.1, far = 2000 ) { + + super(); + + this.isOrthographicCamera = true; + + this.type = 'OrthographicCamera'; + + this.zoom = 1; + this.view = null; + + this.left = left; + this.right = right; + this.top = top; + this.bottom = bottom; + + this.near = near; + this.far = far; + + this.updateProjectionMatrix(); + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + this.left = source.left; + this.right = source.right; + this.top = source.top; + this.bottom = source.bottom; + this.near = source.near; + this.far = source.far; + + this.zoom = source.zoom; + this.view = source.view === null ? null : Object.assign( {}, source.view ); + + return this; + + } + + setViewOffset( fullWidth, fullHeight, x, y, width, height ) { + + if ( this.view === null ) { + + this.view = { + enabled: true, + fullWidth: 1, + fullHeight: 1, + offsetX: 0, + offsetY: 0, + width: 1, + height: 1 + }; + + } + + this.view.enabled = true; + this.view.fullWidth = fullWidth; + this.view.fullHeight = fullHeight; + this.view.offsetX = x; + this.view.offsetY = y; + this.view.width = width; + this.view.height = height; + + this.updateProjectionMatrix(); + + } + + clearViewOffset() { + + if ( this.view !== null ) { + + this.view.enabled = false; + + } + + this.updateProjectionMatrix(); + + } + + updateProjectionMatrix() { + + const dx = ( this.right - this.left ) / ( 2 * this.zoom ); + const dy = ( this.top - this.bottom ) / ( 2 * this.zoom ); + const cx = ( this.right + this.left ) / 2; + const cy = ( this.top + this.bottom ) / 2; + + let left = cx - dx; + let right = cx + dx; + let top = cy + dy; + let bottom = cy - dy; + + if ( this.view !== null && this.view.enabled ) { + + const scaleW = ( this.right - this.left ) / this.view.fullWidth / this.zoom; + const scaleH = ( this.top - this.bottom ) / this.view.fullHeight / this.zoom; + + left += scaleW * this.view.offsetX; + right = left + scaleW * this.view.width; + top -= scaleH * this.view.offsetY; + bottom = top - scaleH * this.view.height; + + } + + this.projectionMatrix.makeOrthographic( left, right, top, bottom, this.near, this.far, this.coordinateSystem ); + + this.projectionMatrixInverse.copy( this.projectionMatrix ).invert(); + + } + + toJSON( meta ) { + + const data = super.toJSON( meta ); + + data.object.zoom = this.zoom; + data.object.left = this.left; + data.object.right = this.right; + data.object.top = this.top; + data.object.bottom = this.bottom; + data.object.near = this.near; + data.object.far = this.far; + + if ( this.view !== null ) data.object.view = Object.assign( {}, this.view ); + + return data; + + } + +} + +class DirectionalLightShadow extends LightShadow { + + constructor() { + + super( new OrthographicCamera( - 5, 5, 5, - 5, 0.5, 500 ) ); + + this.isDirectionalLightShadow = true; + + } + +} + +class DirectionalLight extends Light { + + constructor( color, intensity ) { + + super( color, intensity ); + + this.isDirectionalLight = true; + + this.type = 'DirectionalLight'; + + this.position.copy( Object3D.DEFAULT_UP ); + this.updateMatrix(); + + this.target = new Object3D(); + + this.shadow = new DirectionalLightShadow(); + + } + + dispose() { + + this.shadow.dispose(); + + } + + copy( source ) { + + super.copy( source ); + + this.target = source.target.clone(); + this.shadow = source.shadow.clone(); + + return this; + + } + +} + +class AmbientLight extends Light { + + constructor( color, intensity ) { + + super( color, intensity ); + + this.isAmbientLight = true; + + this.type = 'AmbientLight'; + + } + +} + +class RectAreaLight extends Light { + + constructor( color, intensity, width = 10, height = 10 ) { + + super( color, intensity ); + + this.isRectAreaLight = true; + + this.type = 'RectAreaLight'; + + this.width = width; + this.height = height; + + } + + get power() { + + // compute the light's luminous power (in lumens) from its intensity (in nits) + return this.intensity * this.width * this.height * Math.PI; + + } + + set power( power ) { + + // set the light's intensity (in nits) from the desired luminous power (in lumens) + this.intensity = power / ( this.width * this.height * Math.PI ); + + } + + copy( source ) { + + super.copy( source ); + + this.width = source.width; + this.height = source.height; + + return this; + + } + + toJSON( meta ) { + + const data = super.toJSON( meta ); + + data.object.width = this.width; + data.object.height = this.height; + + return data; + + } + +} + +/** + * Primary reference: + * https://graphics.stanford.edu/papers/envmap/envmap.pdf + * + * Secondary reference: + * https://www.ppsloan.org/publications/StupidSH36.pdf + */ + +// 3-band SH defined by 9 coefficients + +class SphericalHarmonics3 { + + constructor() { + + this.isSphericalHarmonics3 = true; + + this.coefficients = []; + + for ( let i = 0; i < 9; i ++ ) { + + this.coefficients.push( new Vector3() ); + + } + + } + + set( coefficients ) { + + for ( let i = 0; i < 9; i ++ ) { + + this.coefficients[ i ].copy( coefficients[ i ] ); + + } + + return this; + + } + + zero() { + + for ( let i = 0; i < 9; i ++ ) { + + this.coefficients[ i ].set( 0, 0, 0 ); + + } + + return this; + + } + + // get the radiance in the direction of the normal + // target is a Vector3 + getAt( normal, target ) { + + // normal is assumed to be unit length + + const x = normal.x, y = normal.y, z = normal.z; + + const coeff = this.coefficients; + + // band 0 + target.copy( coeff[ 0 ] ).multiplyScalar( 0.282095 ); + + // band 1 + target.addScaledVector( coeff[ 1 ], 0.488603 * y ); + target.addScaledVector( coeff[ 2 ], 0.488603 * z ); + target.addScaledVector( coeff[ 3 ], 0.488603 * x ); + + // band 2 + target.addScaledVector( coeff[ 4 ], 1.092548 * ( x * y ) ); + target.addScaledVector( coeff[ 5 ], 1.092548 * ( y * z ) ); + target.addScaledVector( coeff[ 6 ], 0.315392 * ( 3.0 * z * z - 1.0 ) ); + target.addScaledVector( coeff[ 7 ], 1.092548 * ( x * z ) ); + target.addScaledVector( coeff[ 8 ], 0.546274 * ( x * x - y * y ) ); + + return target; + + } + + // get the irradiance (radiance convolved with cosine lobe) in the direction of the normal + // target is a Vector3 + // https://graphics.stanford.edu/papers/envmap/envmap.pdf + getIrradianceAt( normal, target ) { + + // normal is assumed to be unit length + + const x = normal.x, y = normal.y, z = normal.z; + + const coeff = this.coefficients; + + // band 0 + target.copy( coeff[ 0 ] ).multiplyScalar( 0.886227 ); // π * 0.282095 + + // band 1 + target.addScaledVector( coeff[ 1 ], 2.0 * 0.511664 * y ); // ( 2 * π / 3 ) * 0.488603 + target.addScaledVector( coeff[ 2 ], 2.0 * 0.511664 * z ); + target.addScaledVector( coeff[ 3 ], 2.0 * 0.511664 * x ); + + // band 2 + target.addScaledVector( coeff[ 4 ], 2.0 * 0.429043 * x * y ); // ( π / 4 ) * 1.092548 + target.addScaledVector( coeff[ 5 ], 2.0 * 0.429043 * y * z ); + target.addScaledVector( coeff[ 6 ], 0.743125 * z * z - 0.247708 ); // ( π / 4 ) * 0.315392 * 3 + target.addScaledVector( coeff[ 7 ], 2.0 * 0.429043 * x * z ); + target.addScaledVector( coeff[ 8 ], 0.429043 * ( x * x - y * y ) ); // ( π / 4 ) * 0.546274 + + return target; + + } + + add( sh ) { + + for ( let i = 0; i < 9; i ++ ) { + + this.coefficients[ i ].add( sh.coefficients[ i ] ); + + } + + return this; + + } + + addScaledSH( sh, s ) { + + for ( let i = 0; i < 9; i ++ ) { + + this.coefficients[ i ].addScaledVector( sh.coefficients[ i ], s ); + + } + + return this; + + } + + scale( s ) { + + for ( let i = 0; i < 9; i ++ ) { + + this.coefficients[ i ].multiplyScalar( s ); + + } + + return this; + + } + + lerp( sh, alpha ) { + + for ( let i = 0; i < 9; i ++ ) { + + this.coefficients[ i ].lerp( sh.coefficients[ i ], alpha ); + + } + + return this; + + } + + equals( sh ) { + + for ( let i = 0; i < 9; i ++ ) { + + if ( ! this.coefficients[ i ].equals( sh.coefficients[ i ] ) ) { + + return false; + + } + + } + + return true; + + } + + copy( sh ) { + + return this.set( sh.coefficients ); + + } + + clone() { + + return new this.constructor().copy( this ); + + } + + fromArray( array, offset = 0 ) { + + const coefficients = this.coefficients; + + for ( let i = 0; i < 9; i ++ ) { + + coefficients[ i ].fromArray( array, offset + ( i * 3 ) ); + + } + + return this; + + } + + toArray( array = [], offset = 0 ) { + + const coefficients = this.coefficients; + + for ( let i = 0; i < 9; i ++ ) { + + coefficients[ i ].toArray( array, offset + ( i * 3 ) ); + + } + + return array; + + } + + // evaluate the basis functions + // shBasis is an Array[ 9 ] + static getBasisAt( normal, shBasis ) { + + // normal is assumed to be unit length + + const x = normal.x, y = normal.y, z = normal.z; + + // band 0 + shBasis[ 0 ] = 0.282095; + + // band 1 + shBasis[ 1 ] = 0.488603 * y; + shBasis[ 2 ] = 0.488603 * z; + shBasis[ 3 ] = 0.488603 * x; + + // band 2 + shBasis[ 4 ] = 1.092548 * x * y; + shBasis[ 5 ] = 1.092548 * y * z; + shBasis[ 6 ] = 0.315392 * ( 3 * z * z - 1 ); + shBasis[ 7 ] = 1.092548 * x * z; + shBasis[ 8 ] = 0.546274 * ( x * x - y * y ); + + } + +} + +class LightProbe extends Light { + + constructor( sh = new SphericalHarmonics3(), intensity = 1 ) { + + super( undefined, intensity ); + + this.isLightProbe = true; + + this.sh = sh; + + } + + copy( source ) { + + super.copy( source ); + + this.sh.copy( source.sh ); + + return this; + + } + + fromJSON( json ) { + + this.intensity = json.intensity; // TODO: Move this bit to Light.fromJSON(); + this.sh.fromArray( json.sh ); + + return this; + + } + + toJSON( meta ) { + + const data = super.toJSON( meta ); + + data.object.sh = this.sh.toArray(); + + return data; + + } + +} + +class MaterialLoader extends Loader { + + constructor( manager ) { + + super( manager ); + this.textures = {}; + + } + + load( url, onLoad, onProgress, onError ) { + + const scope = this; + + const loader = new FileLoader( scope.manager ); + loader.setPath( scope.path ); + loader.setRequestHeader( scope.requestHeader ); + loader.setWithCredentials( scope.withCredentials ); + loader.load( url, function ( text ) { + + try { + + onLoad( scope.parse( JSON.parse( text ) ) ); + + } catch ( e ) { + + if ( onError ) { + + onError( e ); + + } else { + + console.error( e ); + + } + + scope.manager.itemError( url ); + + } + + }, onProgress, onError ); + + } + + parse( json ) { + + const textures = this.textures; + + function getTexture( name ) { + + if ( textures[ name ] === undefined ) { + + console.warn( 'THREE.MaterialLoader: Undefined texture', name ); + + } + + return textures[ name ]; + + } + + const material = this.createMaterialFromType( json.type ); + + if ( json.uuid !== undefined ) material.uuid = json.uuid; + if ( json.name !== undefined ) material.name = json.name; + if ( json.color !== undefined && material.color !== undefined ) material.color.setHex( json.color ); + if ( json.roughness !== undefined ) material.roughness = json.roughness; + if ( json.metalness !== undefined ) material.metalness = json.metalness; + if ( json.sheen !== undefined ) material.sheen = json.sheen; + if ( json.sheenColor !== undefined ) material.sheenColor = new Color().setHex( json.sheenColor ); + if ( json.sheenRoughness !== undefined ) material.sheenRoughness = json.sheenRoughness; + if ( json.emissive !== undefined && material.emissive !== undefined ) material.emissive.setHex( json.emissive ); + if ( json.specular !== undefined && material.specular !== undefined ) material.specular.setHex( json.specular ); + if ( json.specularIntensity !== undefined ) material.specularIntensity = json.specularIntensity; + if ( json.specularColor !== undefined && material.specularColor !== undefined ) material.specularColor.setHex( json.specularColor ); + if ( json.shininess !== undefined ) material.shininess = json.shininess; + if ( json.clearcoat !== undefined ) material.clearcoat = json.clearcoat; + if ( json.clearcoatRoughness !== undefined ) material.clearcoatRoughness = json.clearcoatRoughness; + if ( json.dispersion !== undefined ) material.dispersion = json.dispersion; + if ( json.iridescence !== undefined ) material.iridescence = json.iridescence; + if ( json.iridescenceIOR !== undefined ) material.iridescenceIOR = json.iridescenceIOR; + if ( json.iridescenceThicknessRange !== undefined ) material.iridescenceThicknessRange = json.iridescenceThicknessRange; + if ( json.transmission !== undefined ) material.transmission = json.transmission; + if ( json.thickness !== undefined ) material.thickness = json.thickness; + if ( json.attenuationDistance !== undefined ) material.attenuationDistance = json.attenuationDistance; + if ( json.attenuationColor !== undefined && material.attenuationColor !== undefined ) material.attenuationColor.setHex( json.attenuationColor ); + if ( json.anisotropy !== undefined ) material.anisotropy = json.anisotropy; + if ( json.anisotropyRotation !== undefined ) material.anisotropyRotation = json.anisotropyRotation; + if ( json.fog !== undefined ) material.fog = json.fog; + if ( json.flatShading !== undefined ) material.flatShading = json.flatShading; + if ( json.blending !== undefined ) material.blending = json.blending; + if ( json.combine !== undefined ) material.combine = json.combine; + if ( json.side !== undefined ) material.side = json.side; + if ( json.shadowSide !== undefined ) material.shadowSide = json.shadowSide; + if ( json.opacity !== undefined ) material.opacity = json.opacity; + if ( json.transparent !== undefined ) material.transparent = json.transparent; + if ( json.alphaTest !== undefined ) material.alphaTest = json.alphaTest; + if ( json.alphaHash !== undefined ) material.alphaHash = json.alphaHash; + if ( json.depthFunc !== undefined ) material.depthFunc = json.depthFunc; + if ( json.depthTest !== undefined ) material.depthTest = json.depthTest; + if ( json.depthWrite !== undefined ) material.depthWrite = json.depthWrite; + if ( json.colorWrite !== undefined ) material.colorWrite = json.colorWrite; + if ( json.blendSrc !== undefined ) material.blendSrc = json.blendSrc; + if ( json.blendDst !== undefined ) material.blendDst = json.blendDst; + if ( json.blendEquation !== undefined ) material.blendEquation = json.blendEquation; + if ( json.blendSrcAlpha !== undefined ) material.blendSrcAlpha = json.blendSrcAlpha; + if ( json.blendDstAlpha !== undefined ) material.blendDstAlpha = json.blendDstAlpha; + if ( json.blendEquationAlpha !== undefined ) material.blendEquationAlpha = json.blendEquationAlpha; + if ( json.blendColor !== undefined && material.blendColor !== undefined ) material.blendColor.setHex( json.blendColor ); + if ( json.blendAlpha !== undefined ) material.blendAlpha = json.blendAlpha; + if ( json.stencilWriteMask !== undefined ) material.stencilWriteMask = json.stencilWriteMask; + if ( json.stencilFunc !== undefined ) material.stencilFunc = json.stencilFunc; + if ( json.stencilRef !== undefined ) material.stencilRef = json.stencilRef; + if ( json.stencilFuncMask !== undefined ) material.stencilFuncMask = json.stencilFuncMask; + if ( json.stencilFail !== undefined ) material.stencilFail = json.stencilFail; + if ( json.stencilZFail !== undefined ) material.stencilZFail = json.stencilZFail; + if ( json.stencilZPass !== undefined ) material.stencilZPass = json.stencilZPass; + if ( json.stencilWrite !== undefined ) material.stencilWrite = json.stencilWrite; + + if ( json.wireframe !== undefined ) material.wireframe = json.wireframe; + if ( json.wireframeLinewidth !== undefined ) material.wireframeLinewidth = json.wireframeLinewidth; + if ( json.wireframeLinecap !== undefined ) material.wireframeLinecap = json.wireframeLinecap; + if ( json.wireframeLinejoin !== undefined ) material.wireframeLinejoin = json.wireframeLinejoin; + + if ( json.rotation !== undefined ) material.rotation = json.rotation; + + if ( json.linewidth !== undefined ) material.linewidth = json.linewidth; + if ( json.dashSize !== undefined ) material.dashSize = json.dashSize; + if ( json.gapSize !== undefined ) material.gapSize = json.gapSize; + if ( json.scale !== undefined ) material.scale = json.scale; + + if ( json.polygonOffset !== undefined ) material.polygonOffset = json.polygonOffset; + if ( json.polygonOffsetFactor !== undefined ) material.polygonOffsetFactor = json.polygonOffsetFactor; + if ( json.polygonOffsetUnits !== undefined ) material.polygonOffsetUnits = json.polygonOffsetUnits; + + if ( json.dithering !== undefined ) material.dithering = json.dithering; + + if ( json.alphaToCoverage !== undefined ) material.alphaToCoverage = json.alphaToCoverage; + if ( json.premultipliedAlpha !== undefined ) material.premultipliedAlpha = json.premultipliedAlpha; + if ( json.forceSinglePass !== undefined ) material.forceSinglePass = json.forceSinglePass; + + if ( json.visible !== undefined ) material.visible = json.visible; + + if ( json.toneMapped !== undefined ) material.toneMapped = json.toneMapped; + + if ( json.userData !== undefined ) material.userData = json.userData; + + if ( json.vertexColors !== undefined ) { + + if ( typeof json.vertexColors === 'number' ) { + + material.vertexColors = ( json.vertexColors > 0 ) ? true : false; + + } else { + + material.vertexColors = json.vertexColors; + + } + + } + + // Shader Material + + if ( json.uniforms !== undefined ) { + + for ( const name in json.uniforms ) { + + const uniform = json.uniforms[ name ]; + + material.uniforms[ name ] = {}; + + switch ( uniform.type ) { + + case 't': + material.uniforms[ name ].value = getTexture( uniform.value ); + break; + + case 'c': + material.uniforms[ name ].value = new Color().setHex( uniform.value ); + break; + + case 'v2': + material.uniforms[ name ].value = new Vector2().fromArray( uniform.value ); + break; + + case 'v3': + material.uniforms[ name ].value = new Vector3().fromArray( uniform.value ); + break; + + case 'v4': + material.uniforms[ name ].value = new Vector4().fromArray( uniform.value ); + break; + + case 'm3': + material.uniforms[ name ].value = new Matrix3().fromArray( uniform.value ); + break; + + case 'm4': + material.uniforms[ name ].value = new Matrix4().fromArray( uniform.value ); + break; + + default: + material.uniforms[ name ].value = uniform.value; + + } + + } + + } + + if ( json.defines !== undefined ) material.defines = json.defines; + if ( json.vertexShader !== undefined ) material.vertexShader = json.vertexShader; + if ( json.fragmentShader !== undefined ) material.fragmentShader = json.fragmentShader; + if ( json.glslVersion !== undefined ) material.glslVersion = json.glslVersion; + + if ( json.extensions !== undefined ) { + + for ( const key in json.extensions ) { + + material.extensions[ key ] = json.extensions[ key ]; + + } + + } + + if ( json.lights !== undefined ) material.lights = json.lights; + if ( json.clipping !== undefined ) material.clipping = json.clipping; + + // for PointsMaterial + + if ( json.size !== undefined ) material.size = json.size; + if ( json.sizeAttenuation !== undefined ) material.sizeAttenuation = json.sizeAttenuation; + + // maps + + if ( json.map !== undefined ) material.map = getTexture( json.map ); + if ( json.matcap !== undefined ) material.matcap = getTexture( json.matcap ); + + if ( json.alphaMap !== undefined ) material.alphaMap = getTexture( json.alphaMap ); + + if ( json.bumpMap !== undefined ) material.bumpMap = getTexture( json.bumpMap ); + if ( json.bumpScale !== undefined ) material.bumpScale = json.bumpScale; + + if ( json.normalMap !== undefined ) material.normalMap = getTexture( json.normalMap ); + if ( json.normalMapType !== undefined ) material.normalMapType = json.normalMapType; + if ( json.normalScale !== undefined ) { + + let normalScale = json.normalScale; + + if ( Array.isArray( normalScale ) === false ) { + + // Blender exporter used to export a scalar. See #7459 + + normalScale = [ normalScale, normalScale ]; + + } + + material.normalScale = new Vector2().fromArray( normalScale ); + + } + + if ( json.displacementMap !== undefined ) material.displacementMap = getTexture( json.displacementMap ); + if ( json.displacementScale !== undefined ) material.displacementScale = json.displacementScale; + if ( json.displacementBias !== undefined ) material.displacementBias = json.displacementBias; + + if ( json.roughnessMap !== undefined ) material.roughnessMap = getTexture( json.roughnessMap ); + if ( json.metalnessMap !== undefined ) material.metalnessMap = getTexture( json.metalnessMap ); + + if ( json.emissiveMap !== undefined ) material.emissiveMap = getTexture( json.emissiveMap ); + if ( json.emissiveIntensity !== undefined ) material.emissiveIntensity = json.emissiveIntensity; + + if ( json.specularMap !== undefined ) material.specularMap = getTexture( json.specularMap ); + if ( json.specularIntensityMap !== undefined ) material.specularIntensityMap = getTexture( json.specularIntensityMap ); + if ( json.specularColorMap !== undefined ) material.specularColorMap = getTexture( json.specularColorMap ); + + if ( json.envMap !== undefined ) material.envMap = getTexture( json.envMap ); + if ( json.envMapRotation !== undefined ) material.envMapRotation.fromArray( json.envMapRotation ); + if ( json.envMapIntensity !== undefined ) material.envMapIntensity = json.envMapIntensity; + + if ( json.reflectivity !== undefined ) material.reflectivity = json.reflectivity; + if ( json.refractionRatio !== undefined ) material.refractionRatio = json.refractionRatio; + + if ( json.lightMap !== undefined ) material.lightMap = getTexture( json.lightMap ); + if ( json.lightMapIntensity !== undefined ) material.lightMapIntensity = json.lightMapIntensity; + + if ( json.aoMap !== undefined ) material.aoMap = getTexture( json.aoMap ); + if ( json.aoMapIntensity !== undefined ) material.aoMapIntensity = json.aoMapIntensity; + + if ( json.gradientMap !== undefined ) material.gradientMap = getTexture( json.gradientMap ); + + if ( json.clearcoatMap !== undefined ) material.clearcoatMap = getTexture( json.clearcoatMap ); + if ( json.clearcoatRoughnessMap !== undefined ) material.clearcoatRoughnessMap = getTexture( json.clearcoatRoughnessMap ); + if ( json.clearcoatNormalMap !== undefined ) material.clearcoatNormalMap = getTexture( json.clearcoatNormalMap ); + if ( json.clearcoatNormalScale !== undefined ) material.clearcoatNormalScale = new Vector2().fromArray( json.clearcoatNormalScale ); + + if ( json.iridescenceMap !== undefined ) material.iridescenceMap = getTexture( json.iridescenceMap ); + if ( json.iridescenceThicknessMap !== undefined ) material.iridescenceThicknessMap = getTexture( json.iridescenceThicknessMap ); + + if ( json.transmissionMap !== undefined ) material.transmissionMap = getTexture( json.transmissionMap ); + if ( json.thicknessMap !== undefined ) material.thicknessMap = getTexture( json.thicknessMap ); + + if ( json.anisotropyMap !== undefined ) material.anisotropyMap = getTexture( json.anisotropyMap ); + + if ( json.sheenColorMap !== undefined ) material.sheenColorMap = getTexture( json.sheenColorMap ); + if ( json.sheenRoughnessMap !== undefined ) material.sheenRoughnessMap = getTexture( json.sheenRoughnessMap ); + + return material; + + } + + setTextures( value ) { + + this.textures = value; + return this; + + } + + createMaterialFromType( type ) { + + return MaterialLoader.createMaterialFromType( type ); + + } + + static createMaterialFromType( type ) { + + const materialLib = { + ShadowMaterial, + SpriteMaterial, + RawShaderMaterial, + ShaderMaterial, + PointsMaterial, + MeshPhysicalMaterial, + MeshStandardMaterial, + MeshPhongMaterial, + MeshToonMaterial, + MeshNormalMaterial, + MeshLambertMaterial, + MeshDepthMaterial, + MeshDistanceMaterial, + MeshBasicMaterial, + MeshMatcapMaterial, + LineDashedMaterial, + LineBasicMaterial, + Material + }; + + return new materialLib[ type ](); + + } + +} + +class LoaderUtils { + + static decodeText( array ) { // @deprecated, r165 + + console.warn( 'THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead.' ); + + if ( typeof TextDecoder !== 'undefined' ) { + + return new TextDecoder().decode( array ); + + } + + // Avoid the String.fromCharCode.apply(null, array) shortcut, which + // throws a "maximum call stack size exceeded" error for large arrays. + + let s = ''; + + for ( let i = 0, il = array.length; i < il; i ++ ) { + + // Implicitly assumes little-endian. + s += String.fromCharCode( array[ i ] ); + + } + + try { + + // merges multi-byte utf-8 characters. + + return decodeURIComponent( escape( s ) ); + + } catch ( e ) { // see #16358 + + return s; + + } + + } + + static extractUrlBase( url ) { + + const index = url.lastIndexOf( '/' ); + + if ( index === - 1 ) return './'; + + return url.slice( 0, index + 1 ); + + } + + static resolveURL( url, path ) { + + // Invalid URL + if ( typeof url !== 'string' || url === '' ) return ''; + + // Host Relative URL + if ( /^https?:\/\//i.test( path ) && /^\//.test( url ) ) { + + path = path.replace( /(^https?:\/\/[^\/]+).*/i, '$1' ); + + } + + // Absolute URL http://,https://,// + if ( /^(https?:)?\/\//i.test( url ) ) return url; + + // Data URI + if ( /^data:.*,.*$/i.test( url ) ) return url; + + // Blob URL + if ( /^blob:.*$/i.test( url ) ) return url; + + // Relative URL + return path + url; + + } + +} + +class InstancedBufferGeometry extends BufferGeometry { + + constructor() { + + super(); + + this.isInstancedBufferGeometry = true; + + this.type = 'InstancedBufferGeometry'; + this.instanceCount = Infinity; + + } + + copy( source ) { + + super.copy( source ); + + this.instanceCount = source.instanceCount; + + return this; + + } + + toJSON() { + + const data = super.toJSON(); + + data.instanceCount = this.instanceCount; + + data.isInstancedBufferGeometry = true; + + return data; + + } + +} + +class BufferGeometryLoader extends Loader { + + constructor( manager ) { + + super( manager ); + + } + + load( url, onLoad, onProgress, onError ) { + + const scope = this; + + const loader = new FileLoader( scope.manager ); + loader.setPath( scope.path ); + loader.setRequestHeader( scope.requestHeader ); + loader.setWithCredentials( scope.withCredentials ); + loader.load( url, function ( text ) { + + try { + + onLoad( scope.parse( JSON.parse( text ) ) ); + + } catch ( e ) { + + if ( onError ) { + + onError( e ); + + } else { + + console.error( e ); + + } + + scope.manager.itemError( url ); + + } + + }, onProgress, onError ); + + } + + parse( json ) { + + const interleavedBufferMap = {}; + const arrayBufferMap = {}; + + function getInterleavedBuffer( json, uuid ) { + + if ( interleavedBufferMap[ uuid ] !== undefined ) return interleavedBufferMap[ uuid ]; + + const interleavedBuffers = json.interleavedBuffers; + const interleavedBuffer = interleavedBuffers[ uuid ]; + + const buffer = getArrayBuffer( json, interleavedBuffer.buffer ); + + const array = getTypedArray( interleavedBuffer.type, buffer ); + const ib = new InterleavedBuffer( array, interleavedBuffer.stride ); + ib.uuid = interleavedBuffer.uuid; + + interleavedBufferMap[ uuid ] = ib; + + return ib; + + } + + function getArrayBuffer( json, uuid ) { + + if ( arrayBufferMap[ uuid ] !== undefined ) return arrayBufferMap[ uuid ]; + + const arrayBuffers = json.arrayBuffers; + const arrayBuffer = arrayBuffers[ uuid ]; + + const ab = new Uint32Array( arrayBuffer ).buffer; + + arrayBufferMap[ uuid ] = ab; + + return ab; + + } + + const geometry = json.isInstancedBufferGeometry ? new InstancedBufferGeometry() : new BufferGeometry(); + + const index = json.data.index; + + if ( index !== undefined ) { + + const typedArray = getTypedArray( index.type, index.array ); + geometry.setIndex( new BufferAttribute( typedArray, 1 ) ); + + } + + const attributes = json.data.attributes; + + for ( const key in attributes ) { + + const attribute = attributes[ key ]; + let bufferAttribute; + + if ( attribute.isInterleavedBufferAttribute ) { + + const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data ); + bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized ); + + } else { + + const typedArray = getTypedArray( attribute.type, attribute.array ); + const bufferAttributeConstr = attribute.isInstancedBufferAttribute ? InstancedBufferAttribute : BufferAttribute; + bufferAttribute = new bufferAttributeConstr( typedArray, attribute.itemSize, attribute.normalized ); + + } + + if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name; + if ( attribute.usage !== undefined ) bufferAttribute.setUsage( attribute.usage ); + + geometry.setAttribute( key, bufferAttribute ); + + } + + const morphAttributes = json.data.morphAttributes; + + if ( morphAttributes ) { + + for ( const key in morphAttributes ) { + + const attributeArray = morphAttributes[ key ]; + + const array = []; + + for ( let i = 0, il = attributeArray.length; i < il; i ++ ) { + + const attribute = attributeArray[ i ]; + let bufferAttribute; + + if ( attribute.isInterleavedBufferAttribute ) { + + const interleavedBuffer = getInterleavedBuffer( json.data, attribute.data ); + bufferAttribute = new InterleavedBufferAttribute( interleavedBuffer, attribute.itemSize, attribute.offset, attribute.normalized ); + + } else { + + const typedArray = getTypedArray( attribute.type, attribute.array ); + bufferAttribute = new BufferAttribute( typedArray, attribute.itemSize, attribute.normalized ); + + } + + if ( attribute.name !== undefined ) bufferAttribute.name = attribute.name; + array.push( bufferAttribute ); + + } + + geometry.morphAttributes[ key ] = array; + + } + + } + + const morphTargetsRelative = json.data.morphTargetsRelative; + + if ( morphTargetsRelative ) { + + geometry.morphTargetsRelative = true; + + } + + const groups = json.data.groups || json.data.drawcalls || json.data.offsets; + + if ( groups !== undefined ) { + + for ( let i = 0, n = groups.length; i !== n; ++ i ) { + + const group = groups[ i ]; + + geometry.addGroup( group.start, group.count, group.materialIndex ); + + } + + } + + const boundingSphere = json.data.boundingSphere; + + if ( boundingSphere !== undefined ) { + + const center = new Vector3(); + + if ( boundingSphere.center !== undefined ) { + + center.fromArray( boundingSphere.center ); + + } + + geometry.boundingSphere = new Sphere( center, boundingSphere.radius ); + + } + + if ( json.name ) geometry.name = json.name; + if ( json.userData ) geometry.userData = json.userData; + + return geometry; + + } + +} + +class ObjectLoader extends Loader { + + constructor( manager ) { + + super( manager ); + + } + + load( url, onLoad, onProgress, onError ) { + + const scope = this; + + const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; + this.resourcePath = this.resourcePath || path; + + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + loader.load( url, function ( text ) { + + let json = null; + + try { + + json = JSON.parse( text ); + + } catch ( error ) { + + if ( onError !== undefined ) onError( error ); + + console.error( 'THREE:ObjectLoader: Can\'t parse ' + url + '.', error.message ); + + return; + + } + + const metadata = json.metadata; + + if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { + + if ( onError !== undefined ) onError( new Error( 'THREE.ObjectLoader: Can\'t load ' + url ) ); + + console.error( 'THREE.ObjectLoader: Can\'t load ' + url ); + return; + + } + + scope.parse( json, onLoad ); + + }, onProgress, onError ); + + } + + async loadAsync( url, onProgress ) { + + const scope = this; + + const path = ( this.path === '' ) ? LoaderUtils.extractUrlBase( url ) : this.path; + this.resourcePath = this.resourcePath || path; + + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + + const text = await loader.loadAsync( url, onProgress ); + + const json = JSON.parse( text ); + + const metadata = json.metadata; + + if ( metadata === undefined || metadata.type === undefined || metadata.type.toLowerCase() === 'geometry' ) { + + throw new Error( 'THREE.ObjectLoader: Can\'t load ' + url ); + + } + + return await scope.parseAsync( json ); + + } + + parse( json, onLoad ) { + + const animations = this.parseAnimations( json.animations ); + const shapes = this.parseShapes( json.shapes ); + const geometries = this.parseGeometries( json.geometries, shapes ); + + const images = this.parseImages( json.images, function () { + + if ( onLoad !== undefined ) onLoad( object ); + + } ); + + const textures = this.parseTextures( json.textures, images ); + const materials = this.parseMaterials( json.materials, textures ); + + const object = this.parseObject( json.object, geometries, materials, textures, animations ); + const skeletons = this.parseSkeletons( json.skeletons, object ); + + this.bindSkeletons( object, skeletons ); + this.bindLightTargets( object ); + + // + + if ( onLoad !== undefined ) { + + let hasImages = false; + + for ( const uuid in images ) { + + if ( images[ uuid ].data instanceof HTMLImageElement ) { + + hasImages = true; + break; + + } + + } + + if ( hasImages === false ) onLoad( object ); + + } + + return object; + + } + + async parseAsync( json ) { + + const animations = this.parseAnimations( json.animations ); + const shapes = this.parseShapes( json.shapes ); + const geometries = this.parseGeometries( json.geometries, shapes ); + + const images = await this.parseImagesAsync( json.images ); + + const textures = this.parseTextures( json.textures, images ); + const materials = this.parseMaterials( json.materials, textures ); + + const object = this.parseObject( json.object, geometries, materials, textures, animations ); + const skeletons = this.parseSkeletons( json.skeletons, object ); + + this.bindSkeletons( object, skeletons ); + this.bindLightTargets( object ); + + return object; + + } + + parseShapes( json ) { + + const shapes = {}; + + if ( json !== undefined ) { + + for ( let i = 0, l = json.length; i < l; i ++ ) { + + const shape = new Shape().fromJSON( json[ i ] ); + + shapes[ shape.uuid ] = shape; + + } + + } + + return shapes; + + } + + parseSkeletons( json, object ) { + + const skeletons = {}; + const bones = {}; + + // generate bone lookup table + + object.traverse( function ( child ) { + + if ( child.isBone ) bones[ child.uuid ] = child; + + } ); + + // create skeletons + + if ( json !== undefined ) { + + for ( let i = 0, l = json.length; i < l; i ++ ) { + + const skeleton = new Skeleton().fromJSON( json[ i ], bones ); + + skeletons[ skeleton.uuid ] = skeleton; + + } + + } + + return skeletons; + + } + + parseGeometries( json, shapes ) { + + const geometries = {}; + + if ( json !== undefined ) { + + const bufferGeometryLoader = new BufferGeometryLoader(); + + for ( let i = 0, l = json.length; i < l; i ++ ) { + + let geometry; + const data = json[ i ]; + + switch ( data.type ) { + + case 'BufferGeometry': + case 'InstancedBufferGeometry': + + geometry = bufferGeometryLoader.parse( data ); + break; + + default: + + if ( data.type in Geometries$1 ) { + + geometry = Geometries$1[ data.type ].fromJSON( data, shapes ); + + } else { + + console.warn( `THREE.ObjectLoader: Unsupported geometry type "${ data.type }"` ); + + } + + } + + geometry.uuid = data.uuid; + + if ( data.name !== undefined ) geometry.name = data.name; + if ( data.userData !== undefined ) geometry.userData = data.userData; + + geometries[ data.uuid ] = geometry; + + } + + } + + return geometries; + + } + + parseMaterials( json, textures ) { + + const cache = {}; // MultiMaterial + const materials = {}; + + if ( json !== undefined ) { + + const loader = new MaterialLoader(); + loader.setTextures( textures ); + + for ( let i = 0, l = json.length; i < l; i ++ ) { + + const data = json[ i ]; + + if ( cache[ data.uuid ] === undefined ) { + + cache[ data.uuid ] = loader.parse( data ); + + } + + materials[ data.uuid ] = cache[ data.uuid ]; + + } + + } + + return materials; + + } + + parseAnimations( json ) { + + const animations = {}; + + if ( json !== undefined ) { + + for ( let i = 0; i < json.length; i ++ ) { + + const data = json[ i ]; + + const clip = AnimationClip.parse( data ); + + animations[ clip.uuid ] = clip; + + } + + } + + return animations; + + } + + parseImages( json, onLoad ) { + + const scope = this; + const images = {}; + + let loader; + + function loadImage( url ) { + + scope.manager.itemStart( url ); + + return loader.load( url, function () { + + scope.manager.itemEnd( url ); + + }, undefined, function () { + + scope.manager.itemError( url ); + scope.manager.itemEnd( url ); + + } ); + + } + + function deserializeImage( image ) { + + if ( typeof image === 'string' ) { + + const url = image; + + const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url; + + return loadImage( path ); + + } else { + + if ( image.data ) { + + return { + data: getTypedArray( image.type, image.data ), + width: image.width, + height: image.height + }; + + } else { + + return null; + + } + + } + + } + + if ( json !== undefined && json.length > 0 ) { + + const manager = new LoadingManager( onLoad ); + + loader = new ImageLoader( manager ); + loader.setCrossOrigin( this.crossOrigin ); + + for ( let i = 0, il = json.length; i < il; i ++ ) { + + const image = json[ i ]; + const url = image.url; + + if ( Array.isArray( url ) ) { + + // load array of images e.g CubeTexture + + const imageArray = []; + + for ( let j = 0, jl = url.length; j < jl; j ++ ) { + + const currentUrl = url[ j ]; + + const deserializedImage = deserializeImage( currentUrl ); + + if ( deserializedImage !== null ) { + + if ( deserializedImage instanceof HTMLImageElement ) { + + imageArray.push( deserializedImage ); + + } else { + + // special case: handle array of data textures for cube textures + + imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) ); + + } + + } + + } + + images[ image.uuid ] = new Source( imageArray ); + + } else { + + // load single image + + const deserializedImage = deserializeImage( image.url ); + images[ image.uuid ] = new Source( deserializedImage ); + + + } + + } + + } + + return images; + + } + + async parseImagesAsync( json ) { + + const scope = this; + const images = {}; + + let loader; + + async function deserializeImage( image ) { + + if ( typeof image === 'string' ) { + + const url = image; + + const path = /^(\/\/)|([a-z]+:(\/\/)?)/i.test( url ) ? url : scope.resourcePath + url; + + return await loader.loadAsync( path ); + + } else { + + if ( image.data ) { + + return { + data: getTypedArray( image.type, image.data ), + width: image.width, + height: image.height + }; + + } else { + + return null; + + } + + } + + } + + if ( json !== undefined && json.length > 0 ) { + + loader = new ImageLoader( this.manager ); + loader.setCrossOrigin( this.crossOrigin ); + + for ( let i = 0, il = json.length; i < il; i ++ ) { + + const image = json[ i ]; + const url = image.url; + + if ( Array.isArray( url ) ) { + + // load array of images e.g CubeTexture + + const imageArray = []; + + for ( let j = 0, jl = url.length; j < jl; j ++ ) { + + const currentUrl = url[ j ]; + + const deserializedImage = await deserializeImage( currentUrl ); + + if ( deserializedImage !== null ) { + + if ( deserializedImage instanceof HTMLImageElement ) { + + imageArray.push( deserializedImage ); + + } else { + + // special case: handle array of data textures for cube textures + + imageArray.push( new DataTexture( deserializedImage.data, deserializedImage.width, deserializedImage.height ) ); + + } + + } + + } + + images[ image.uuid ] = new Source( imageArray ); + + } else { + + // load single image + + const deserializedImage = await deserializeImage( image.url ); + images[ image.uuid ] = new Source( deserializedImage ); + + } + + } + + } + + return images; + + } + + parseTextures( json, images ) { + + function parseConstant( value, type ) { + + if ( typeof value === 'number' ) return value; + + console.warn( 'THREE.ObjectLoader.parseTexture: Constant should be in numeric form.', value ); + + return type[ value ]; + + } + + const textures = {}; + + if ( json !== undefined ) { + + for ( let i = 0, l = json.length; i < l; i ++ ) { + + const data = json[ i ]; + + if ( data.image === undefined ) { + + console.warn( 'THREE.ObjectLoader: No "image" specified for', data.uuid ); + + } + + if ( images[ data.image ] === undefined ) { + + console.warn( 'THREE.ObjectLoader: Undefined image', data.image ); + + } + + const source = images[ data.image ]; + const image = source.data; + + let texture; + + if ( Array.isArray( image ) ) { + + texture = new CubeTexture(); + + if ( image.length === 6 ) texture.needsUpdate = true; + + } else { + + if ( image && image.data ) { + + texture = new DataTexture(); + + } else { + + texture = new Texture(); + + } + + if ( image ) texture.needsUpdate = true; // textures can have undefined image data + + } + + texture.source = source; + + texture.uuid = data.uuid; + + if ( data.name !== undefined ) texture.name = data.name; + + if ( data.mapping !== undefined ) texture.mapping = parseConstant( data.mapping, TEXTURE_MAPPING ); + if ( data.channel !== undefined ) texture.channel = data.channel; + + if ( data.offset !== undefined ) texture.offset.fromArray( data.offset ); + if ( data.repeat !== undefined ) texture.repeat.fromArray( data.repeat ); + if ( data.center !== undefined ) texture.center.fromArray( data.center ); + if ( data.rotation !== undefined ) texture.rotation = data.rotation; + + if ( data.wrap !== undefined ) { + + texture.wrapS = parseConstant( data.wrap[ 0 ], TEXTURE_WRAPPING ); + texture.wrapT = parseConstant( data.wrap[ 1 ], TEXTURE_WRAPPING ); + + } + + if ( data.format !== undefined ) texture.format = data.format; + if ( data.internalFormat !== undefined ) texture.internalFormat = data.internalFormat; + if ( data.type !== undefined ) texture.type = data.type; + if ( data.colorSpace !== undefined ) texture.colorSpace = data.colorSpace; + + if ( data.minFilter !== undefined ) texture.minFilter = parseConstant( data.minFilter, TEXTURE_FILTER ); + if ( data.magFilter !== undefined ) texture.magFilter = parseConstant( data.magFilter, TEXTURE_FILTER ); + if ( data.anisotropy !== undefined ) texture.anisotropy = data.anisotropy; + + if ( data.flipY !== undefined ) texture.flipY = data.flipY; + + if ( data.generateMipmaps !== undefined ) texture.generateMipmaps = data.generateMipmaps; + if ( data.premultiplyAlpha !== undefined ) texture.premultiplyAlpha = data.premultiplyAlpha; + if ( data.unpackAlignment !== undefined ) texture.unpackAlignment = data.unpackAlignment; + if ( data.compareFunction !== undefined ) texture.compareFunction = data.compareFunction; + + if ( data.userData !== undefined ) texture.userData = data.userData; + + textures[ data.uuid ] = texture; + + } + + } + + return textures; + + } + + parseObject( data, geometries, materials, textures, animations ) { + + let object; + + function getGeometry( name ) { + + if ( geometries[ name ] === undefined ) { + + console.warn( 'THREE.ObjectLoader: Undefined geometry', name ); + + } + + return geometries[ name ]; + + } + + function getMaterial( name ) { + + if ( name === undefined ) return undefined; + + if ( Array.isArray( name ) ) { + + const array = []; + + for ( let i = 0, l = name.length; i < l; i ++ ) { + + const uuid = name[ i ]; + + if ( materials[ uuid ] === undefined ) { + + console.warn( 'THREE.ObjectLoader: Undefined material', uuid ); + + } + + array.push( materials[ uuid ] ); + + } + + return array; + + } + + if ( materials[ name ] === undefined ) { + + console.warn( 'THREE.ObjectLoader: Undefined material', name ); + + } + + return materials[ name ]; + + } + + function getTexture( uuid ) { + + if ( textures[ uuid ] === undefined ) { + + console.warn( 'THREE.ObjectLoader: Undefined texture', uuid ); + + } + + return textures[ uuid ]; + + } + + let geometry, material; + + switch ( data.type ) { + + case 'Scene': + + object = new Scene(); + + if ( data.background !== undefined ) { + + if ( Number.isInteger( data.background ) ) { + + object.background = new Color( data.background ); + + } else { + + object.background = getTexture( data.background ); + + } + + } + + if ( data.environment !== undefined ) { + + object.environment = getTexture( data.environment ); + + } + + if ( data.fog !== undefined ) { + + if ( data.fog.type === 'Fog' ) { + + object.fog = new Fog( data.fog.color, data.fog.near, data.fog.far ); + + } else if ( data.fog.type === 'FogExp2' ) { + + object.fog = new FogExp2( data.fog.color, data.fog.density ); + + } + + if ( data.fog.name !== '' ) { + + object.fog.name = data.fog.name; + + } + + } + + if ( data.backgroundBlurriness !== undefined ) object.backgroundBlurriness = data.backgroundBlurriness; + if ( data.backgroundIntensity !== undefined ) object.backgroundIntensity = data.backgroundIntensity; + if ( data.backgroundRotation !== undefined ) object.backgroundRotation.fromArray( data.backgroundRotation ); + + if ( data.environmentIntensity !== undefined ) object.environmentIntensity = data.environmentIntensity; + if ( data.environmentRotation !== undefined ) object.environmentRotation.fromArray( data.environmentRotation ); + + break; + + case 'PerspectiveCamera': + + object = new PerspectiveCamera( data.fov, data.aspect, data.near, data.far ); + + if ( data.focus !== undefined ) object.focus = data.focus; + if ( data.zoom !== undefined ) object.zoom = data.zoom; + if ( data.filmGauge !== undefined ) object.filmGauge = data.filmGauge; + if ( data.filmOffset !== undefined ) object.filmOffset = data.filmOffset; + if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); + + break; + + case 'OrthographicCamera': + + object = new OrthographicCamera( data.left, data.right, data.top, data.bottom, data.near, data.far ); + + if ( data.zoom !== undefined ) object.zoom = data.zoom; + if ( data.view !== undefined ) object.view = Object.assign( {}, data.view ); + + break; + + case 'AmbientLight': + + object = new AmbientLight( data.color, data.intensity ); + + break; + + case 'DirectionalLight': + + object = new DirectionalLight( data.color, data.intensity ); + object.target = data.target || ''; + + break; + + case 'PointLight': + + object = new PointLight( data.color, data.intensity, data.distance, data.decay ); + + break; + + case 'RectAreaLight': + + object = new RectAreaLight( data.color, data.intensity, data.width, data.height ); + + break; + + case 'SpotLight': + + object = new SpotLight( data.color, data.intensity, data.distance, data.angle, data.penumbra, data.decay ); + object.target = data.target || ''; + + break; + + case 'HemisphereLight': + + object = new HemisphereLight( data.color, data.groundColor, data.intensity ); + + break; + + case 'LightProbe': + + object = new LightProbe().fromJSON( data ); + + break; + + case 'SkinnedMesh': + + geometry = getGeometry( data.geometry ); + material = getMaterial( data.material ); + + object = new SkinnedMesh( geometry, material ); + + if ( data.bindMode !== undefined ) object.bindMode = data.bindMode; + if ( data.bindMatrix !== undefined ) object.bindMatrix.fromArray( data.bindMatrix ); + if ( data.skeleton !== undefined ) object.skeleton = data.skeleton; + + break; + + case 'Mesh': + + geometry = getGeometry( data.geometry ); + material = getMaterial( data.material ); + + object = new Mesh( geometry, material ); + + break; + + case 'InstancedMesh': + + geometry = getGeometry( data.geometry ); + material = getMaterial( data.material ); + const count = data.count; + const instanceMatrix = data.instanceMatrix; + const instanceColor = data.instanceColor; + + object = new InstancedMesh( geometry, material, count ); + object.instanceMatrix = new InstancedBufferAttribute( new Float32Array( instanceMatrix.array ), 16 ); + if ( instanceColor !== undefined ) object.instanceColor = new InstancedBufferAttribute( new Float32Array( instanceColor.array ), instanceColor.itemSize ); + + break; + + case 'BatchedMesh': + + geometry = getGeometry( data.geometry ); + material = getMaterial( data.material ); + + object = new BatchedMesh( data.maxInstanceCount, data.maxVertexCount, data.maxIndexCount, material ); + object.geometry = geometry; + object.perObjectFrustumCulled = data.perObjectFrustumCulled; + object.sortObjects = data.sortObjects; + + object._drawRanges = data.drawRanges; + object._reservedRanges = data.reservedRanges; + + object._visibility = data.visibility; + object._active = data.active; + object._bounds = data.bounds.map( bound => { + + const box = new Box3(); + box.min.fromArray( bound.boxMin ); + box.max.fromArray( bound.boxMax ); + + const sphere = new Sphere(); + sphere.radius = bound.sphereRadius; + sphere.center.fromArray( bound.sphereCenter ); + + return { + boxInitialized: bound.boxInitialized, + box: box, + + sphereInitialized: bound.sphereInitialized, + sphere: sphere + }; + + } ); + + object._maxInstanceCount = data.maxInstanceCount; + object._maxVertexCount = data.maxVertexCount; + object._maxIndexCount = data.maxIndexCount; + + object._geometryInitialized = data.geometryInitialized; + object._geometryCount = data.geometryCount; + + object._matricesTexture = getTexture( data.matricesTexture.uuid ); + if ( data.colorsTexture !== undefined ) object._colorsTexture = getTexture( data.colorsTexture.uuid ); + + break; + + case 'LOD': + + object = new LOD(); + + break; + + case 'Line': + + object = new Line( getGeometry( data.geometry ), getMaterial( data.material ) ); + + break; + + case 'LineLoop': + + object = new LineLoop( getGeometry( data.geometry ), getMaterial( data.material ) ); + + break; + + case 'LineSegments': + + object = new LineSegments( getGeometry( data.geometry ), getMaterial( data.material ) ); + + break; + + case 'PointCloud': + case 'Points': + + object = new Points( getGeometry( data.geometry ), getMaterial( data.material ) ); + + break; + + case 'Sprite': + + object = new Sprite( getMaterial( data.material ) ); + + break; + + case 'Group': + + object = new Group(); + + break; + + case 'Bone': + + object = new Bone(); + + break; + + default: + + object = new Object3D(); + + } + + object.uuid = data.uuid; + + if ( data.name !== undefined ) object.name = data.name; + + if ( data.matrix !== undefined ) { + + object.matrix.fromArray( data.matrix ); + + if ( data.matrixAutoUpdate !== undefined ) object.matrixAutoUpdate = data.matrixAutoUpdate; + if ( object.matrixAutoUpdate ) object.matrix.decompose( object.position, object.quaternion, object.scale ); + + } else { + + if ( data.position !== undefined ) object.position.fromArray( data.position ); + if ( data.rotation !== undefined ) object.rotation.fromArray( data.rotation ); + if ( data.quaternion !== undefined ) object.quaternion.fromArray( data.quaternion ); + if ( data.scale !== undefined ) object.scale.fromArray( data.scale ); + + } + + if ( data.up !== undefined ) object.up.fromArray( data.up ); + + if ( data.castShadow !== undefined ) object.castShadow = data.castShadow; + if ( data.receiveShadow !== undefined ) object.receiveShadow = data.receiveShadow; + + if ( data.shadow ) { + + if ( data.shadow.intensity !== undefined ) object.shadow.intensity = data.shadow.intensity; + if ( data.shadow.bias !== undefined ) object.shadow.bias = data.shadow.bias; + if ( data.shadow.normalBias !== undefined ) object.shadow.normalBias = data.shadow.normalBias; + if ( data.shadow.radius !== undefined ) object.shadow.radius = data.shadow.radius; + if ( data.shadow.mapSize !== undefined ) object.shadow.mapSize.fromArray( data.shadow.mapSize ); + if ( data.shadow.camera !== undefined ) object.shadow.camera = this.parseObject( data.shadow.camera ); + + } + + if ( data.visible !== undefined ) object.visible = data.visible; + if ( data.frustumCulled !== undefined ) object.frustumCulled = data.frustumCulled; + if ( data.renderOrder !== undefined ) object.renderOrder = data.renderOrder; + if ( data.userData !== undefined ) object.userData = data.userData; + if ( data.layers !== undefined ) object.layers.mask = data.layers; + + if ( data.children !== undefined ) { + + const children = data.children; + + for ( let i = 0; i < children.length; i ++ ) { + + object.add( this.parseObject( children[ i ], geometries, materials, textures, animations ) ); + + } + + } + + if ( data.animations !== undefined ) { + + const objectAnimations = data.animations; + + for ( let i = 0; i < objectAnimations.length; i ++ ) { + + const uuid = objectAnimations[ i ]; + + object.animations.push( animations[ uuid ] ); + + } + + } + + if ( data.type === 'LOD' ) { + + if ( data.autoUpdate !== undefined ) object.autoUpdate = data.autoUpdate; + + const levels = data.levels; + + for ( let l = 0; l < levels.length; l ++ ) { + + const level = levels[ l ]; + const child = object.getObjectByProperty( 'uuid', level.object ); + + if ( child !== undefined ) { + + object.addLevel( child, level.distance, level.hysteresis ); + + } + + } + + } + + return object; + + } + + bindSkeletons( object, skeletons ) { + + if ( Object.keys( skeletons ).length === 0 ) return; + + object.traverse( function ( child ) { + + if ( child.isSkinnedMesh === true && child.skeleton !== undefined ) { + + const skeleton = skeletons[ child.skeleton ]; + + if ( skeleton === undefined ) { + + console.warn( 'THREE.ObjectLoader: No skeleton found with UUID:', child.skeleton ); + + } else { + + child.bind( skeleton, child.bindMatrix ); + + } + + } + + } ); + + } + + bindLightTargets( object ) { + + object.traverse( function ( child ) { + + if ( child.isDirectionalLight || child.isSpotLight ) { + + const uuid = child.target; + + const target = object.getObjectByProperty( 'uuid', uuid ); + + if ( target !== undefined ) { + + child.target = target; + + } else { + + child.target = new Object3D(); + + } + + } + + } ); + + } + +} + +const TEXTURE_MAPPING = { + UVMapping: UVMapping, + CubeReflectionMapping: CubeReflectionMapping, + CubeRefractionMapping: CubeRefractionMapping, + EquirectangularReflectionMapping: EquirectangularReflectionMapping, + EquirectangularRefractionMapping: EquirectangularRefractionMapping, + CubeUVReflectionMapping: CubeUVReflectionMapping +}; + +const TEXTURE_WRAPPING = { + RepeatWrapping: RepeatWrapping, + ClampToEdgeWrapping: ClampToEdgeWrapping, + MirroredRepeatWrapping: MirroredRepeatWrapping +}; + +const TEXTURE_FILTER = { + NearestFilter: NearestFilter, + NearestMipmapNearestFilter: NearestMipmapNearestFilter, + NearestMipmapLinearFilter: NearestMipmapLinearFilter, + LinearFilter: LinearFilter, + LinearMipmapNearestFilter: LinearMipmapNearestFilter, + LinearMipmapLinearFilter: LinearMipmapLinearFilter +}; + +class ImageBitmapLoader extends Loader { + + constructor( manager ) { + + super( manager ); + + this.isImageBitmapLoader = true; + + if ( typeof createImageBitmap === 'undefined' ) { + + console.warn( 'THREE.ImageBitmapLoader: createImageBitmap() not supported.' ); + + } + + if ( typeof fetch === 'undefined' ) { + + console.warn( 'THREE.ImageBitmapLoader: fetch() not supported.' ); + + } + + this.options = { premultiplyAlpha: 'none' }; + + } + + setOptions( options ) { + + this.options = options; + + return this; + + } + + load( url, onLoad, onProgress, onError ) { + + if ( url === undefined ) url = ''; + + if ( this.path !== undefined ) url = this.path + url; + + url = this.manager.resolveURL( url ); + + const scope = this; + + const cached = Cache.get( url ); + + if ( cached !== undefined ) { + + scope.manager.itemStart( url ); + + // If cached is a promise, wait for it to resolve + if ( cached.then ) { + + cached.then( imageBitmap => { + + if ( onLoad ) onLoad( imageBitmap ); + + scope.manager.itemEnd( url ); + + } ).catch( e => { + + if ( onError ) onError( e ); + + } ); + return; + + } + + // If cached is not a promise (i.e., it's already an imageBitmap) + setTimeout( function () { + + if ( onLoad ) onLoad( cached ); + + scope.manager.itemEnd( url ); + + }, 0 ); + + return cached; + + } + + const fetchOptions = {}; + fetchOptions.credentials = ( this.crossOrigin === 'anonymous' ) ? 'same-origin' : 'include'; + fetchOptions.headers = this.requestHeader; + + const promise = fetch( url, fetchOptions ).then( function ( res ) { + + return res.blob(); + + } ).then( function ( blob ) { + + return createImageBitmap( blob, Object.assign( scope.options, { colorSpaceConversion: 'none' } ) ); + + } ).then( function ( imageBitmap ) { + + Cache.add( url, imageBitmap ); + + if ( onLoad ) onLoad( imageBitmap ); + + scope.manager.itemEnd( url ); + + return imageBitmap; + + } ).catch( function ( e ) { + + if ( onError ) onError( e ); + + Cache.remove( url ); + + scope.manager.itemError( url ); + scope.manager.itemEnd( url ); + + } ); + + Cache.add( url, promise ); + scope.manager.itemStart( url ); + + } + +} + +let _context; + +class AudioContext { + + static getContext() { + + if ( _context === undefined ) { + + _context = new ( window.AudioContext || window.webkitAudioContext )(); + + } + + return _context; + + } + + static setContext( value ) { + + _context = value; + + } + +} + +class AudioLoader extends Loader { + + constructor( manager ) { + + super( manager ); + + } + + load( url, onLoad, onProgress, onError ) { + + const scope = this; + + const loader = new FileLoader( this.manager ); + loader.setResponseType( 'arraybuffer' ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + loader.load( url, function ( buffer ) { + + try { + + // Create a copy of the buffer. The `decodeAudioData` method + // detaches the buffer when complete, preventing reuse. + const bufferCopy = buffer.slice( 0 ); + + const context = AudioContext.getContext(); + context.decodeAudioData( bufferCopy, function ( audioBuffer ) { + + onLoad( audioBuffer ); + + } ).catch( handleError ); + + } catch ( e ) { + + handleError( e ); + + } + + }, onProgress, onError ); + + function handleError( e ) { + + if ( onError ) { + + onError( e ); + + } else { + + console.error( e ); + + } + + scope.manager.itemError( url ); + + } + + } + +} + +const _eyeRight = /*@__PURE__*/ new Matrix4(); +const _eyeLeft = /*@__PURE__*/ new Matrix4(); +const _projectionMatrix = /*@__PURE__*/ new Matrix4(); + +class StereoCamera { + + constructor() { + + this.type = 'StereoCamera'; + + this.aspect = 1; + + this.eyeSep = 0.064; + + this.cameraL = new PerspectiveCamera(); + this.cameraL.layers.enable( 1 ); + this.cameraL.matrixAutoUpdate = false; + + this.cameraR = new PerspectiveCamera(); + this.cameraR.layers.enable( 2 ); + this.cameraR.matrixAutoUpdate = false; + + this._cache = { + focus: null, + fov: null, + aspect: null, + near: null, + far: null, + zoom: null, + eyeSep: null + }; + + } + + update( camera ) { + + const cache = this._cache; + + const needsUpdate = cache.focus !== camera.focus || cache.fov !== camera.fov || + cache.aspect !== camera.aspect * this.aspect || cache.near !== camera.near || + cache.far !== camera.far || cache.zoom !== camera.zoom || cache.eyeSep !== this.eyeSep; + + if ( needsUpdate ) { + + cache.focus = camera.focus; + cache.fov = camera.fov; + cache.aspect = camera.aspect * this.aspect; + cache.near = camera.near; + cache.far = camera.far; + cache.zoom = camera.zoom; + cache.eyeSep = this.eyeSep; + + // Off-axis stereoscopic effect based on + // http://paulbourke.net/stereographics/stereorender/ + + _projectionMatrix.copy( camera.projectionMatrix ); + const eyeSepHalf = cache.eyeSep / 2; + const eyeSepOnProjection = eyeSepHalf * cache.near / cache.focus; + const ymax = ( cache.near * Math.tan( DEG2RAD * cache.fov * 0.5 ) ) / cache.zoom; + let xmin, xmax; + + // translate xOffset + + _eyeLeft.elements[ 12 ] = - eyeSepHalf; + _eyeRight.elements[ 12 ] = eyeSepHalf; + + // for left eye + + xmin = - ymax * cache.aspect + eyeSepOnProjection; + xmax = ymax * cache.aspect + eyeSepOnProjection; + + _projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin ); + _projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); + + this.cameraL.projectionMatrix.copy( _projectionMatrix ); + + // for right eye + + xmin = - ymax * cache.aspect - eyeSepOnProjection; + xmax = ymax * cache.aspect - eyeSepOnProjection; + + _projectionMatrix.elements[ 0 ] = 2 * cache.near / ( xmax - xmin ); + _projectionMatrix.elements[ 8 ] = ( xmax + xmin ) / ( xmax - xmin ); + + this.cameraR.projectionMatrix.copy( _projectionMatrix ); + + } + + this.cameraL.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeLeft ); + this.cameraR.matrixWorld.copy( camera.matrixWorld ).multiply( _eyeRight ); + + } + +} + +class ArrayCamera extends PerspectiveCamera { + + constructor( array = [] ) { + + super(); + + this.isArrayCamera = true; + + this.cameras = array; + + } + +} + +class Clock { + + constructor( autoStart = true ) { + + this.autoStart = autoStart; + + this.startTime = 0; + this.oldTime = 0; + this.elapsedTime = 0; + + this.running = false; + + } + + start() { + + this.startTime = now(); + + this.oldTime = this.startTime; + this.elapsedTime = 0; + this.running = true; + + } + + stop() { + + this.getElapsedTime(); + this.running = false; + this.autoStart = false; + + } + + getElapsedTime() { + + this.getDelta(); + return this.elapsedTime; + + } + + getDelta() { + + let diff = 0; + + if ( this.autoStart && ! this.running ) { + + this.start(); + return 0; + + } + + if ( this.running ) { + + const newTime = now(); + + diff = ( newTime - this.oldTime ) / 1000; + this.oldTime = newTime; + + this.elapsedTime += diff; + + } + + return diff; + + } + +} + +function now() { + + return performance.now(); + +} + +const _position$1 = /*@__PURE__*/ new Vector3(); +const _quaternion$1 = /*@__PURE__*/ new Quaternion(); +const _scale$1 = /*@__PURE__*/ new Vector3(); +const _orientation$1 = /*@__PURE__*/ new Vector3(); + +class AudioListener extends Object3D { + + constructor() { + + super(); + + this.type = 'AudioListener'; + + this.context = AudioContext.getContext(); + + this.gain = this.context.createGain(); + this.gain.connect( this.context.destination ); + + this.filter = null; + + this.timeDelta = 0; + + // private + + this._clock = new Clock(); + + } + + getInput() { + + return this.gain; + + } + + removeFilter() { + + if ( this.filter !== null ) { + + this.gain.disconnect( this.filter ); + this.filter.disconnect( this.context.destination ); + this.gain.connect( this.context.destination ); + this.filter = null; + + } + + return this; + + } + + getFilter() { + + return this.filter; + + } + + setFilter( value ) { + + if ( this.filter !== null ) { + + this.gain.disconnect( this.filter ); + this.filter.disconnect( this.context.destination ); + + } else { + + this.gain.disconnect( this.context.destination ); + + } + + this.filter = value; + this.gain.connect( this.filter ); + this.filter.connect( this.context.destination ); + + return this; + + } + + getMasterVolume() { + + return this.gain.gain.value; + + } + + setMasterVolume( value ) { + + this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 ); + + return this; + + } + + updateMatrixWorld( force ) { + + super.updateMatrixWorld( force ); + + const listener = this.context.listener; + const up = this.up; + + this.timeDelta = this._clock.getDelta(); + + this.matrixWorld.decompose( _position$1, _quaternion$1, _scale$1 ); + + _orientation$1.set( 0, 0, - 1 ).applyQuaternion( _quaternion$1 ); + + if ( listener.positionX ) { + + // code path for Chrome (see #14393) + + const endTime = this.context.currentTime + this.timeDelta; + + listener.positionX.linearRampToValueAtTime( _position$1.x, endTime ); + listener.positionY.linearRampToValueAtTime( _position$1.y, endTime ); + listener.positionZ.linearRampToValueAtTime( _position$1.z, endTime ); + listener.forwardX.linearRampToValueAtTime( _orientation$1.x, endTime ); + listener.forwardY.linearRampToValueAtTime( _orientation$1.y, endTime ); + listener.forwardZ.linearRampToValueAtTime( _orientation$1.z, endTime ); + listener.upX.linearRampToValueAtTime( up.x, endTime ); + listener.upY.linearRampToValueAtTime( up.y, endTime ); + listener.upZ.linearRampToValueAtTime( up.z, endTime ); + + } else { + + listener.setPosition( _position$1.x, _position$1.y, _position$1.z ); + listener.setOrientation( _orientation$1.x, _orientation$1.y, _orientation$1.z, up.x, up.y, up.z ); + + } + + } + +} + +class Audio extends Object3D { + + constructor( listener ) { + + super(); + + this.type = 'Audio'; + + this.listener = listener; + this.context = listener.context; + + this.gain = this.context.createGain(); + this.gain.connect( listener.getInput() ); + + this.autoplay = false; + + this.buffer = null; + this.detune = 0; + this.loop = false; + this.loopStart = 0; + this.loopEnd = 0; + this.offset = 0; + this.duration = undefined; + this.playbackRate = 1; + this.isPlaying = false; + this.hasPlaybackControl = true; + this.source = null; + this.sourceType = 'empty'; + + this._startedAt = 0; + this._progress = 0; + this._connected = false; + + this.filters = []; + + } + + getOutput() { + + return this.gain; + + } + + setNodeSource( audioNode ) { + + this.hasPlaybackControl = false; + this.sourceType = 'audioNode'; + this.source = audioNode; + this.connect(); + + return this; + + } + + setMediaElementSource( mediaElement ) { + + this.hasPlaybackControl = false; + this.sourceType = 'mediaNode'; + this.source = this.context.createMediaElementSource( mediaElement ); + this.connect(); + + return this; + + } + + setMediaStreamSource( mediaStream ) { + + this.hasPlaybackControl = false; + this.sourceType = 'mediaStreamNode'; + this.source = this.context.createMediaStreamSource( mediaStream ); + this.connect(); + + return this; + + } + + setBuffer( audioBuffer ) { + + this.buffer = audioBuffer; + this.sourceType = 'buffer'; + + if ( this.autoplay ) this.play(); + + return this; + + } + + play( delay = 0 ) { + + if ( this.isPlaying === true ) { + + console.warn( 'THREE.Audio: Audio is already playing.' ); + return; + + } + + if ( this.hasPlaybackControl === false ) { + + console.warn( 'THREE.Audio: this Audio has no playback control.' ); + return; + + } + + this._startedAt = this.context.currentTime + delay; + + const source = this.context.createBufferSource(); + source.buffer = this.buffer; + source.loop = this.loop; + source.loopStart = this.loopStart; + source.loopEnd = this.loopEnd; + source.onended = this.onEnded.bind( this ); + source.start( this._startedAt, this._progress + this.offset, this.duration ); + + this.isPlaying = true; + + this.source = source; + + this.setDetune( this.detune ); + this.setPlaybackRate( this.playbackRate ); + + return this.connect(); + + } + + pause() { + + if ( this.hasPlaybackControl === false ) { + + console.warn( 'THREE.Audio: this Audio has no playback control.' ); + return; + + } + + if ( this.isPlaying === true ) { + + // update current progress + + this._progress += Math.max( this.context.currentTime - this._startedAt, 0 ) * this.playbackRate; + + if ( this.loop === true ) { + + // ensure _progress does not exceed duration with looped audios + + this._progress = this._progress % ( this.duration || this.buffer.duration ); + + } + + this.source.stop(); + this.source.onended = null; + + this.isPlaying = false; + + } + + return this; + + } + + stop( delay = 0 ) { + + if ( this.hasPlaybackControl === false ) { + + console.warn( 'THREE.Audio: this Audio has no playback control.' ); + return; + + } + + this._progress = 0; + + if ( this.source !== null ) { + + this.source.stop( this.context.currentTime + delay ); + this.source.onended = null; + + } + + this.isPlaying = false; + + return this; + + } + + connect() { + + if ( this.filters.length > 0 ) { + + this.source.connect( this.filters[ 0 ] ); + + for ( let i = 1, l = this.filters.length; i < l; i ++ ) { + + this.filters[ i - 1 ].connect( this.filters[ i ] ); + + } + + this.filters[ this.filters.length - 1 ].connect( this.getOutput() ); + + } else { + + this.source.connect( this.getOutput() ); + + } + + this._connected = true; + + return this; + + } + + disconnect() { + + if ( this._connected === false ) { + + return; + + } + + if ( this.filters.length > 0 ) { + + this.source.disconnect( this.filters[ 0 ] ); + + for ( let i = 1, l = this.filters.length; i < l; i ++ ) { + + this.filters[ i - 1 ].disconnect( this.filters[ i ] ); + + } + + this.filters[ this.filters.length - 1 ].disconnect( this.getOutput() ); + + } else { + + this.source.disconnect( this.getOutput() ); + + } + + this._connected = false; + + return this; + + } + + getFilters() { + + return this.filters; + + } + + setFilters( value ) { + + if ( ! value ) value = []; + + if ( this._connected === true ) { + + this.disconnect(); + this.filters = value.slice(); + this.connect(); + + } else { + + this.filters = value.slice(); + + } + + return this; + + } + + setDetune( value ) { + + this.detune = value; + + if ( this.isPlaying === true && this.source.detune !== undefined ) { + + this.source.detune.setTargetAtTime( this.detune, this.context.currentTime, 0.01 ); + + } + + return this; + + } + + getDetune() { + + return this.detune; + + } + + getFilter() { + + return this.getFilters()[ 0 ]; + + } + + setFilter( filter ) { + + return this.setFilters( filter ? [ filter ] : [] ); + + } + + setPlaybackRate( value ) { + + if ( this.hasPlaybackControl === false ) { + + console.warn( 'THREE.Audio: this Audio has no playback control.' ); + return; + + } + + this.playbackRate = value; + + if ( this.isPlaying === true ) { + + this.source.playbackRate.setTargetAtTime( this.playbackRate, this.context.currentTime, 0.01 ); + + } + + return this; + + } + + getPlaybackRate() { + + return this.playbackRate; + + } + + onEnded() { + + this.isPlaying = false; + + } + + getLoop() { + + if ( this.hasPlaybackControl === false ) { + + console.warn( 'THREE.Audio: this Audio has no playback control.' ); + return false; + + } + + return this.loop; + + } + + setLoop( value ) { + + if ( this.hasPlaybackControl === false ) { + + console.warn( 'THREE.Audio: this Audio has no playback control.' ); + return; + + } + + this.loop = value; + + if ( this.isPlaying === true ) { + + this.source.loop = this.loop; + + } + + return this; + + } + + setLoopStart( value ) { + + this.loopStart = value; + + return this; + + } + + setLoopEnd( value ) { + + this.loopEnd = value; + + return this; + + } + + getVolume() { + + return this.gain.gain.value; + + } + + setVolume( value ) { + + this.gain.gain.setTargetAtTime( value, this.context.currentTime, 0.01 ); + + return this; + + } + +} + +const _position = /*@__PURE__*/ new Vector3(); +const _quaternion = /*@__PURE__*/ new Quaternion(); +const _scale = /*@__PURE__*/ new Vector3(); +const _orientation = /*@__PURE__*/ new Vector3(); + +class PositionalAudio extends Audio { + + constructor( listener ) { + + super( listener ); + + this.panner = this.context.createPanner(); + this.panner.panningModel = 'HRTF'; + this.panner.connect( this.gain ); + + } + + connect() { + + super.connect(); + + this.panner.connect( this.gain ); + + } + + disconnect() { + + super.disconnect(); + + this.panner.disconnect( this.gain ); + + } + + getOutput() { + + return this.panner; + + } + + getRefDistance() { + + return this.panner.refDistance; + + } + + setRefDistance( value ) { + + this.panner.refDistance = value; + + return this; + + } + + getRolloffFactor() { + + return this.panner.rolloffFactor; + + } + + setRolloffFactor( value ) { + + this.panner.rolloffFactor = value; + + return this; + + } + + getDistanceModel() { + + return this.panner.distanceModel; + + } + + setDistanceModel( value ) { + + this.panner.distanceModel = value; + + return this; + + } + + getMaxDistance() { + + return this.panner.maxDistance; + + } + + setMaxDistance( value ) { + + this.panner.maxDistance = value; + + return this; + + } + + setDirectionalCone( coneInnerAngle, coneOuterAngle, coneOuterGain ) { + + this.panner.coneInnerAngle = coneInnerAngle; + this.panner.coneOuterAngle = coneOuterAngle; + this.panner.coneOuterGain = coneOuterGain; + + return this; + + } + + updateMatrixWorld( force ) { + + super.updateMatrixWorld( force ); + + if ( this.hasPlaybackControl === true && this.isPlaying === false ) return; + + this.matrixWorld.decompose( _position, _quaternion, _scale ); + + _orientation.set( 0, 0, 1 ).applyQuaternion( _quaternion ); + + const panner = this.panner; + + if ( panner.positionX ) { + + // code path for Chrome and Firefox (see #14393) + + const endTime = this.context.currentTime + this.listener.timeDelta; + + panner.positionX.linearRampToValueAtTime( _position.x, endTime ); + panner.positionY.linearRampToValueAtTime( _position.y, endTime ); + panner.positionZ.linearRampToValueAtTime( _position.z, endTime ); + panner.orientationX.linearRampToValueAtTime( _orientation.x, endTime ); + panner.orientationY.linearRampToValueAtTime( _orientation.y, endTime ); + panner.orientationZ.linearRampToValueAtTime( _orientation.z, endTime ); + + } else { + + panner.setPosition( _position.x, _position.y, _position.z ); + panner.setOrientation( _orientation.x, _orientation.y, _orientation.z ); + + } + + } + +} + +class AudioAnalyser { + + constructor( audio, fftSize = 2048 ) { + + this.analyser = audio.context.createAnalyser(); + this.analyser.fftSize = fftSize; + + this.data = new Uint8Array( this.analyser.frequencyBinCount ); + + audio.getOutput().connect( this.analyser ); + + } + + + getFrequencyData() { + + this.analyser.getByteFrequencyData( this.data ); + + return this.data; + + } + + getAverageFrequency() { + + let value = 0; + const data = this.getFrequencyData(); + + for ( let i = 0; i < data.length; i ++ ) { + + value += data[ i ]; + + } + + return value / data.length; + + } + +} + +class PropertyMixer { + + constructor( binding, typeName, valueSize ) { + + this.binding = binding; + this.valueSize = valueSize; + + let mixFunction, + mixFunctionAdditive, + setIdentity; + + // buffer layout: [ incoming | accu0 | accu1 | orig | addAccu | (optional work) ] + // + // interpolators can use .buffer as their .result + // the data then goes to 'incoming' + // + // 'accu0' and 'accu1' are used frame-interleaved for + // the cumulative result and are compared to detect + // changes + // + // 'orig' stores the original state of the property + // + // 'add' is used for additive cumulative results + // + // 'work' is optional and is only present for quaternion types. It is used + // to store intermediate quaternion multiplication results + + switch ( typeName ) { + + case 'quaternion': + mixFunction = this._slerp; + mixFunctionAdditive = this._slerpAdditive; + setIdentity = this._setAdditiveIdentityQuaternion; + + this.buffer = new Float64Array( valueSize * 6 ); + this._workIndex = 5; + break; + + case 'string': + case 'bool': + mixFunction = this._select; + + // Use the regular mix function and for additive on these types, + // additive is not relevant for non-numeric types + mixFunctionAdditive = this._select; + + setIdentity = this._setAdditiveIdentityOther; + + this.buffer = new Array( valueSize * 5 ); + break; + + default: + mixFunction = this._lerp; + mixFunctionAdditive = this._lerpAdditive; + setIdentity = this._setAdditiveIdentityNumeric; + + this.buffer = new Float64Array( valueSize * 5 ); + + } + + this._mixBufferRegion = mixFunction; + this._mixBufferRegionAdditive = mixFunctionAdditive; + this._setIdentity = setIdentity; + this._origIndex = 3; + this._addIndex = 4; + + this.cumulativeWeight = 0; + this.cumulativeWeightAdditive = 0; + + this.useCount = 0; + this.referenceCount = 0; + + } + + // accumulate data in the 'incoming' region into 'accu' + accumulate( accuIndex, weight ) { + + // note: happily accumulating nothing when weight = 0, the caller knows + // the weight and shouldn't have made the call in the first place + + const buffer = this.buffer, + stride = this.valueSize, + offset = accuIndex * stride + stride; + + let currentWeight = this.cumulativeWeight; + + if ( currentWeight === 0 ) { + + // accuN := incoming * weight + + for ( let i = 0; i !== stride; ++ i ) { + + buffer[ offset + i ] = buffer[ i ]; + + } + + currentWeight = weight; + + } else { + + // accuN := accuN + incoming * weight + + currentWeight += weight; + const mix = weight / currentWeight; + this._mixBufferRegion( buffer, offset, 0, mix, stride ); + + } + + this.cumulativeWeight = currentWeight; + + } + + // accumulate data in the 'incoming' region into 'add' + accumulateAdditive( weight ) { + + const buffer = this.buffer, + stride = this.valueSize, + offset = stride * this._addIndex; + + if ( this.cumulativeWeightAdditive === 0 ) { + + // add = identity + + this._setIdentity(); + + } + + // add := add + incoming * weight + + this._mixBufferRegionAdditive( buffer, offset, 0, weight, stride ); + this.cumulativeWeightAdditive += weight; + + } + + // apply the state of 'accu' to the binding when accus differ + apply( accuIndex ) { + + const stride = this.valueSize, + buffer = this.buffer, + offset = accuIndex * stride + stride, + + weight = this.cumulativeWeight, + weightAdditive = this.cumulativeWeightAdditive, + + binding = this.binding; + + this.cumulativeWeight = 0; + this.cumulativeWeightAdditive = 0; + + if ( weight < 1 ) { + + // accuN := accuN + original * ( 1 - cumulativeWeight ) + + const originalValueOffset = stride * this._origIndex; + + this._mixBufferRegion( + buffer, offset, originalValueOffset, 1 - weight, stride ); + + } + + if ( weightAdditive > 0 ) { + + // accuN := accuN + additive accuN + + this._mixBufferRegionAdditive( buffer, offset, this._addIndex * stride, 1, stride ); + + } + + for ( let i = stride, e = stride + stride; i !== e; ++ i ) { + + if ( buffer[ i ] !== buffer[ i + stride ] ) { + + // value has changed -> update scene graph + + binding.setValue( buffer, offset ); + break; + + } + + } + + } + + // remember the state of the bound property and copy it to both accus + saveOriginalState() { + + const binding = this.binding; + + const buffer = this.buffer, + stride = this.valueSize, + + originalValueOffset = stride * this._origIndex; + + binding.getValue( buffer, originalValueOffset ); + + // accu[0..1] := orig -- initially detect changes against the original + for ( let i = stride, e = originalValueOffset; i !== e; ++ i ) { + + buffer[ i ] = buffer[ originalValueOffset + ( i % stride ) ]; + + } + + // Add to identity for additive + this._setIdentity(); + + this.cumulativeWeight = 0; + this.cumulativeWeightAdditive = 0; + + } + + // apply the state previously taken via 'saveOriginalState' to the binding + restoreOriginalState() { + + const originalValueOffset = this.valueSize * 3; + this.binding.setValue( this.buffer, originalValueOffset ); + + } + + _setAdditiveIdentityNumeric() { + + const startIndex = this._addIndex * this.valueSize; + const endIndex = startIndex + this.valueSize; + + for ( let i = startIndex; i < endIndex; i ++ ) { + + this.buffer[ i ] = 0; + + } + + } + + _setAdditiveIdentityQuaternion() { + + this._setAdditiveIdentityNumeric(); + this.buffer[ this._addIndex * this.valueSize + 3 ] = 1; + + } + + _setAdditiveIdentityOther() { + + const startIndex = this._origIndex * this.valueSize; + const targetIndex = this._addIndex * this.valueSize; + + for ( let i = 0; i < this.valueSize; i ++ ) { + + this.buffer[ targetIndex + i ] = this.buffer[ startIndex + i ]; + + } + + } + + + // mix functions + + _select( buffer, dstOffset, srcOffset, t, stride ) { + + if ( t >= 0.5 ) { + + for ( let i = 0; i !== stride; ++ i ) { + + buffer[ dstOffset + i ] = buffer[ srcOffset + i ]; + + } + + } + + } + + _slerp( buffer, dstOffset, srcOffset, t ) { + + Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, srcOffset, t ); + + } + + _slerpAdditive( buffer, dstOffset, srcOffset, t, stride ) { + + const workOffset = this._workIndex * stride; + + // Store result in intermediate buffer offset + Quaternion.multiplyQuaternionsFlat( buffer, workOffset, buffer, dstOffset, buffer, srcOffset ); + + // Slerp to the intermediate result + Quaternion.slerpFlat( buffer, dstOffset, buffer, dstOffset, buffer, workOffset, t ); + + } + + _lerp( buffer, dstOffset, srcOffset, t, stride ) { + + const s = 1 - t; + + for ( let i = 0; i !== stride; ++ i ) { + + const j = dstOffset + i; + + buffer[ j ] = buffer[ j ] * s + buffer[ srcOffset + i ] * t; + + } + + } + + _lerpAdditive( buffer, dstOffset, srcOffset, t, stride ) { + + for ( let i = 0; i !== stride; ++ i ) { + + const j = dstOffset + i; + + buffer[ j ] = buffer[ j ] + buffer[ srcOffset + i ] * t; + + } + + } + +} + +// Characters [].:/ are reserved for track binding syntax. +const _RESERVED_CHARS_RE = '\\[\\]\\.:\\/'; +const _reservedRe = new RegExp( '[' + _RESERVED_CHARS_RE + ']', 'g' ); + +// Attempts to allow node names from any language. ES5's `\w` regexp matches +// only latin characters, and the unicode \p{L} is not yet supported. So +// instead, we exclude reserved characters and match everything else. +const _wordChar = '[^' + _RESERVED_CHARS_RE + ']'; +const _wordCharOrDot = '[^' + _RESERVED_CHARS_RE.replace( '\\.', '' ) + ']'; + +// Parent directories, delimited by '/' or ':'. Currently unused, but must +// be matched to parse the rest of the track name. +const _directoryRe = /*@__PURE__*/ /((?:WC+[\/:])*)/.source.replace( 'WC', _wordChar ); + +// Target node. May contain word characters (a-zA-Z0-9_) and '.' or '-'. +const _nodeRe = /*@__PURE__*/ /(WCOD+)?/.source.replace( 'WCOD', _wordCharOrDot ); + +// Object on target node, and accessor. May not contain reserved +// characters. Accessor may contain any character except closing bracket. +const _objectRe = /*@__PURE__*/ /(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace( 'WC', _wordChar ); + +// Property and accessor. May not contain reserved characters. Accessor may +// contain any non-bracket characters. +const _propertyRe = /*@__PURE__*/ /\.(WC+)(?:\[(.+)\])?/.source.replace( 'WC', _wordChar ); + +const _trackRe = new RegExp( '' + + '^' + + _directoryRe + + _nodeRe + + _objectRe + + _propertyRe + + '$' +); + +const _supportedObjectNames = [ 'material', 'materials', 'bones', 'map' ]; + +class Composite { + + constructor( targetGroup, path, optionalParsedPath ) { + + const parsedPath = optionalParsedPath || PropertyBinding.parseTrackName( path ); + + this._targetGroup = targetGroup; + this._bindings = targetGroup.subscribe_( path, parsedPath ); + + } + + getValue( array, offset ) { + + this.bind(); // bind all binding + + const firstValidIndex = this._targetGroup.nCachedObjects_, + binding = this._bindings[ firstValidIndex ]; + + // and only call .getValue on the first + if ( binding !== undefined ) binding.getValue( array, offset ); + + } + + setValue( array, offset ) { + + const bindings = this._bindings; + + for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { + + bindings[ i ].setValue( array, offset ); + + } + + } + + bind() { + + const bindings = this._bindings; + + for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { + + bindings[ i ].bind(); + + } + + } + + unbind() { + + const bindings = this._bindings; + + for ( let i = this._targetGroup.nCachedObjects_, n = bindings.length; i !== n; ++ i ) { + + bindings[ i ].unbind(); + + } + + } + +} + +// Note: This class uses a State pattern on a per-method basis: +// 'bind' sets 'this.getValue' / 'setValue' and shadows the +// prototype version of these methods with one that represents +// the bound state. When the property is not found, the methods +// become no-ops. +class PropertyBinding { + + constructor( rootNode, path, parsedPath ) { + + this.path = path; + this.parsedPath = parsedPath || PropertyBinding.parseTrackName( path ); + + this.node = PropertyBinding.findNode( rootNode, this.parsedPath.nodeName ); + + this.rootNode = rootNode; + + // initial state of these methods that calls 'bind' + this.getValue = this._getValue_unbound; + this.setValue = this._setValue_unbound; + + } + + + static create( root, path, parsedPath ) { + + if ( ! ( root && root.isAnimationObjectGroup ) ) { + + return new PropertyBinding( root, path, parsedPath ); + + } else { + + return new PropertyBinding.Composite( root, path, parsedPath ); + + } + + } + + /** + * Replaces spaces with underscores and removes unsupported characters from + * node names, to ensure compatibility with parseTrackName(). + * + * @param {string} name Node name to be sanitized. + * @return {string} + */ + static sanitizeNodeName( name ) { + + return name.replace( /\s/g, '_' ).replace( _reservedRe, '' ); + + } + + static parseTrackName( trackName ) { + + const matches = _trackRe.exec( trackName ); + + if ( matches === null ) { + + throw new Error( 'PropertyBinding: Cannot parse trackName: ' + trackName ); + + } + + const results = { + // directoryName: matches[ 1 ], // (tschw) currently unused + nodeName: matches[ 2 ], + objectName: matches[ 3 ], + objectIndex: matches[ 4 ], + propertyName: matches[ 5 ], // required + propertyIndex: matches[ 6 ] + }; + + const lastDot = results.nodeName && results.nodeName.lastIndexOf( '.' ); + + if ( lastDot !== undefined && lastDot !== - 1 ) { + + const objectName = results.nodeName.substring( lastDot + 1 ); + + // Object names must be checked against an allowlist. Otherwise, there + // is no way to parse 'foo.bar.baz': 'baz' must be a property, but + // 'bar' could be the objectName, or part of a nodeName (which can + // include '.' characters). + if ( _supportedObjectNames.indexOf( objectName ) !== - 1 ) { + + results.nodeName = results.nodeName.substring( 0, lastDot ); + results.objectName = objectName; + + } + + } + + if ( results.propertyName === null || results.propertyName.length === 0 ) { + + throw new Error( 'PropertyBinding: can not parse propertyName from trackName: ' + trackName ); + + } + + return results; + + } + + static findNode( root, nodeName ) { + + if ( nodeName === undefined || nodeName === '' || nodeName === '.' || nodeName === - 1 || nodeName === root.name || nodeName === root.uuid ) { + + return root; + + } + + // search into skeleton bones. + if ( root.skeleton ) { + + const bone = root.skeleton.getBoneByName( nodeName ); + + if ( bone !== undefined ) { + + return bone; + + } + + } + + // search into node subtree. + if ( root.children ) { + + const searchNodeSubtree = function ( children ) { + + for ( let i = 0; i < children.length; i ++ ) { + + const childNode = children[ i ]; + + if ( childNode.name === nodeName || childNode.uuid === nodeName ) { + + return childNode; + + } + + const result = searchNodeSubtree( childNode.children ); + + if ( result ) return result; + + } + + return null; + + }; + + const subTreeNode = searchNodeSubtree( root.children ); + + if ( subTreeNode ) { + + return subTreeNode; + + } + + } + + return null; + + } + + // these are used to "bind" a nonexistent property + _getValue_unavailable() {} + _setValue_unavailable() {} + + // Getters + + _getValue_direct( buffer, offset ) { + + buffer[ offset ] = this.targetObject[ this.propertyName ]; + + } + + _getValue_array( buffer, offset ) { + + const source = this.resolvedProperty; + + for ( let i = 0, n = source.length; i !== n; ++ i ) { + + buffer[ offset ++ ] = source[ i ]; + + } + + } + + _getValue_arrayElement( buffer, offset ) { + + buffer[ offset ] = this.resolvedProperty[ this.propertyIndex ]; + + } + + _getValue_toArray( buffer, offset ) { + + this.resolvedProperty.toArray( buffer, offset ); + + } + + // Direct + + _setValue_direct( buffer, offset ) { + + this.targetObject[ this.propertyName ] = buffer[ offset ]; + + } + + _setValue_direct_setNeedsUpdate( buffer, offset ) { + + this.targetObject[ this.propertyName ] = buffer[ offset ]; + this.targetObject.needsUpdate = true; + + } + + _setValue_direct_setMatrixWorldNeedsUpdate( buffer, offset ) { + + this.targetObject[ this.propertyName ] = buffer[ offset ]; + this.targetObject.matrixWorldNeedsUpdate = true; + + } + + // EntireArray + + _setValue_array( buffer, offset ) { + + const dest = this.resolvedProperty; + + for ( let i = 0, n = dest.length; i !== n; ++ i ) { + + dest[ i ] = buffer[ offset ++ ]; + + } + + } + + _setValue_array_setNeedsUpdate( buffer, offset ) { + + const dest = this.resolvedProperty; + + for ( let i = 0, n = dest.length; i !== n; ++ i ) { + + dest[ i ] = buffer[ offset ++ ]; + + } + + this.targetObject.needsUpdate = true; + + } + + _setValue_array_setMatrixWorldNeedsUpdate( buffer, offset ) { + + const dest = this.resolvedProperty; + + for ( let i = 0, n = dest.length; i !== n; ++ i ) { + + dest[ i ] = buffer[ offset ++ ]; + + } + + this.targetObject.matrixWorldNeedsUpdate = true; + + } + + // ArrayElement + + _setValue_arrayElement( buffer, offset ) { + + this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; + + } + + _setValue_arrayElement_setNeedsUpdate( buffer, offset ) { + + this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; + this.targetObject.needsUpdate = true; + + } + + _setValue_arrayElement_setMatrixWorldNeedsUpdate( buffer, offset ) { + + this.resolvedProperty[ this.propertyIndex ] = buffer[ offset ]; + this.targetObject.matrixWorldNeedsUpdate = true; + + } + + // HasToFromArray + + _setValue_fromArray( buffer, offset ) { + + this.resolvedProperty.fromArray( buffer, offset ); + + } + + _setValue_fromArray_setNeedsUpdate( buffer, offset ) { + + this.resolvedProperty.fromArray( buffer, offset ); + this.targetObject.needsUpdate = true; + + } + + _setValue_fromArray_setMatrixWorldNeedsUpdate( buffer, offset ) { + + this.resolvedProperty.fromArray( buffer, offset ); + this.targetObject.matrixWorldNeedsUpdate = true; + + } + + _getValue_unbound( targetArray, offset ) { + + this.bind(); + this.getValue( targetArray, offset ); + + } + + _setValue_unbound( sourceArray, offset ) { + + this.bind(); + this.setValue( sourceArray, offset ); + + } + + // create getter / setter pair for a property in the scene graph + bind() { + + let targetObject = this.node; + const parsedPath = this.parsedPath; + + const objectName = parsedPath.objectName; + const propertyName = parsedPath.propertyName; + let propertyIndex = parsedPath.propertyIndex; + + if ( ! targetObject ) { + + targetObject = PropertyBinding.findNode( this.rootNode, parsedPath.nodeName ); + + this.node = targetObject; + + } + + // set fail state so we can just 'return' on error + this.getValue = this._getValue_unavailable; + this.setValue = this._setValue_unavailable; + + // ensure there is a value node + if ( ! targetObject ) { + + console.warn( 'THREE.PropertyBinding: No target node found for track: ' + this.path + '.' ); + return; + + } + + if ( objectName ) { + + let objectIndex = parsedPath.objectIndex; + + // special cases were we need to reach deeper into the hierarchy to get the face materials.... + switch ( objectName ) { + + case 'materials': + + if ( ! targetObject.material ) { + + console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); + return; + + } + + if ( ! targetObject.material.materials ) { + + console.error( 'THREE.PropertyBinding: Can not bind to material.materials as node.material does not have a materials array.', this ); + return; + + } + + targetObject = targetObject.material.materials; + + break; + + case 'bones': + + if ( ! targetObject.skeleton ) { + + console.error( 'THREE.PropertyBinding: Can not bind to bones as node does not have a skeleton.', this ); + return; + + } + + // potential future optimization: skip this if propertyIndex is already an integer + // and convert the integer string to a true integer. + + targetObject = targetObject.skeleton.bones; + + // support resolving morphTarget names into indices. + for ( let i = 0; i < targetObject.length; i ++ ) { + + if ( targetObject[ i ].name === objectIndex ) { + + objectIndex = i; + break; + + } + + } + + break; + + case 'map': + + if ( 'map' in targetObject ) { + + targetObject = targetObject.map; + break; + + } + + if ( ! targetObject.material ) { + + console.error( 'THREE.PropertyBinding: Can not bind to material as node does not have a material.', this ); + return; + + } + + if ( ! targetObject.material.map ) { + + console.error( 'THREE.PropertyBinding: Can not bind to material.map as node.material does not have a map.', this ); + return; + + } + + targetObject = targetObject.material.map; + break; + + default: + + if ( targetObject[ objectName ] === undefined ) { + + console.error( 'THREE.PropertyBinding: Can not bind to objectName of node undefined.', this ); + return; + + } + + targetObject = targetObject[ objectName ]; + + } + + + if ( objectIndex !== undefined ) { + + if ( targetObject[ objectIndex ] === undefined ) { + + console.error( 'THREE.PropertyBinding: Trying to bind to objectIndex of objectName, but is undefined.', this, targetObject ); + return; + + } + + targetObject = targetObject[ objectIndex ]; + + } + + } + + // resolve property + const nodeProperty = targetObject[ propertyName ]; + + if ( nodeProperty === undefined ) { + + const nodeName = parsedPath.nodeName; + + console.error( 'THREE.PropertyBinding: Trying to update property for track: ' + nodeName + + '.' + propertyName + ' but it wasn\'t found.', targetObject ); + return; + + } + + // determine versioning scheme + let versioning = this.Versioning.None; + + this.targetObject = targetObject; + + if ( targetObject.needsUpdate !== undefined ) { // material + + versioning = this.Versioning.NeedsUpdate; + + } else if ( targetObject.matrixWorldNeedsUpdate !== undefined ) { // node transform + + versioning = this.Versioning.MatrixWorldNeedsUpdate; + + } + + // determine how the property gets bound + let bindingType = this.BindingType.Direct; + + if ( propertyIndex !== undefined ) { + + // access a sub element of the property array (only primitives are supported right now) + + if ( propertyName === 'morphTargetInfluences' ) { + + // potential optimization, skip this if propertyIndex is already an integer, and convert the integer string to a true integer. + + // support resolving morphTarget names into indices. + if ( ! targetObject.geometry ) { + + console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.', this ); + return; + + } + + if ( ! targetObject.geometry.morphAttributes ) { + + console.error( 'THREE.PropertyBinding: Can not bind to morphTargetInfluences because node does not have a geometry.morphAttributes.', this ); + return; + + } + + if ( targetObject.morphTargetDictionary[ propertyIndex ] !== undefined ) { + + propertyIndex = targetObject.morphTargetDictionary[ propertyIndex ]; + + } + + } + + bindingType = this.BindingType.ArrayElement; + + this.resolvedProperty = nodeProperty; + this.propertyIndex = propertyIndex; + + } else if ( nodeProperty.fromArray !== undefined && nodeProperty.toArray !== undefined ) { + + // must use copy for Object3D.Euler/Quaternion + + bindingType = this.BindingType.HasFromToArray; + + this.resolvedProperty = nodeProperty; + + } else if ( Array.isArray( nodeProperty ) ) { + + bindingType = this.BindingType.EntireArray; + + this.resolvedProperty = nodeProperty; + + } else { + + this.propertyName = propertyName; + + } + + // select getter / setter + this.getValue = this.GetterByBindingType[ bindingType ]; + this.setValue = this.SetterByBindingTypeAndVersioning[ bindingType ][ versioning ]; + + } + + unbind() { + + this.node = null; + + // back to the prototype version of getValue / setValue + // note: avoiding to mutate the shape of 'this' via 'delete' + this.getValue = this._getValue_unbound; + this.setValue = this._setValue_unbound; + + } + +} + +PropertyBinding.Composite = Composite; + +PropertyBinding.prototype.BindingType = { + Direct: 0, + EntireArray: 1, + ArrayElement: 2, + HasFromToArray: 3 +}; + +PropertyBinding.prototype.Versioning = { + None: 0, + NeedsUpdate: 1, + MatrixWorldNeedsUpdate: 2 +}; + +PropertyBinding.prototype.GetterByBindingType = [ + + PropertyBinding.prototype._getValue_direct, + PropertyBinding.prototype._getValue_array, + PropertyBinding.prototype._getValue_arrayElement, + PropertyBinding.prototype._getValue_toArray, + +]; + +PropertyBinding.prototype.SetterByBindingTypeAndVersioning = [ + + [ + // Direct + PropertyBinding.prototype._setValue_direct, + PropertyBinding.prototype._setValue_direct_setNeedsUpdate, + PropertyBinding.prototype._setValue_direct_setMatrixWorldNeedsUpdate, + + ], [ + + // EntireArray + + PropertyBinding.prototype._setValue_array, + PropertyBinding.prototype._setValue_array_setNeedsUpdate, + PropertyBinding.prototype._setValue_array_setMatrixWorldNeedsUpdate, + + ], [ + + // ArrayElement + PropertyBinding.prototype._setValue_arrayElement, + PropertyBinding.prototype._setValue_arrayElement_setNeedsUpdate, + PropertyBinding.prototype._setValue_arrayElement_setMatrixWorldNeedsUpdate, + + ], [ + + // HasToFromArray + PropertyBinding.prototype._setValue_fromArray, + PropertyBinding.prototype._setValue_fromArray_setNeedsUpdate, + PropertyBinding.prototype._setValue_fromArray_setMatrixWorldNeedsUpdate, + + ] + +]; + +/** + * + * A group of objects that receives a shared animation state. + * + * Usage: + * + * - Add objects you would otherwise pass as 'root' to the + * constructor or the .clipAction method of AnimationMixer. + * + * - Instead pass this object as 'root'. + * + * - You can also add and remove objects later when the mixer + * is running. + * + * Note: + * + * Objects of this class appear as one object to the mixer, + * so cache control of the individual objects must be done + * on the group. + * + * Limitation: + * + * - The animated properties must be compatible among the + * all objects in the group. + * + * - A single property can either be controlled through a + * target group or directly, but not both. + */ + +class AnimationObjectGroup { + + constructor() { + + this.isAnimationObjectGroup = true; + + this.uuid = generateUUID(); + + // cached objects followed by the active ones + this._objects = Array.prototype.slice.call( arguments ); + + this.nCachedObjects_ = 0; // threshold + // note: read by PropertyBinding.Composite + + const indices = {}; + this._indicesByUUID = indices; // for bookkeeping + + for ( let i = 0, n = arguments.length; i !== n; ++ i ) { + + indices[ arguments[ i ].uuid ] = i; + + } + + this._paths = []; // inside: string + this._parsedPaths = []; // inside: { we don't care, here } + this._bindings = []; // inside: Array< PropertyBinding > + this._bindingsIndicesByPath = {}; // inside: indices in these arrays + + const scope = this; + + this.stats = { + + objects: { + get total() { + + return scope._objects.length; + + }, + get inUse() { + + return this.total - scope.nCachedObjects_; + + } + }, + get bindingsPerObject() { + + return scope._bindings.length; + + } + + }; + + } + + add() { + + const objects = this._objects, + indicesByUUID = this._indicesByUUID, + paths = this._paths, + parsedPaths = this._parsedPaths, + bindings = this._bindings, + nBindings = bindings.length; + + let knownObject = undefined, + nObjects = objects.length, + nCachedObjects = this.nCachedObjects_; + + for ( let i = 0, n = arguments.length; i !== n; ++ i ) { + + const object = arguments[ i ], + uuid = object.uuid; + let index = indicesByUUID[ uuid ]; + + if ( index === undefined ) { + + // unknown object -> add it to the ACTIVE region + + index = nObjects ++; + indicesByUUID[ uuid ] = index; + objects.push( object ); + + // accounting is done, now do the same for all bindings + + for ( let j = 0, m = nBindings; j !== m; ++ j ) { + + bindings[ j ].push( new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ) ); + + } + + } else if ( index < nCachedObjects ) { + + knownObject = objects[ index ]; + + // move existing object to the ACTIVE region + + const firstActiveIndex = -- nCachedObjects, + lastCachedObject = objects[ firstActiveIndex ]; + + indicesByUUID[ lastCachedObject.uuid ] = index; + objects[ index ] = lastCachedObject; + + indicesByUUID[ uuid ] = firstActiveIndex; + objects[ firstActiveIndex ] = object; + + // accounting is done, now do the same for all bindings + + for ( let j = 0, m = nBindings; j !== m; ++ j ) { + + const bindingsForPath = bindings[ j ], + lastCached = bindingsForPath[ firstActiveIndex ]; + + let binding = bindingsForPath[ index ]; + + bindingsForPath[ index ] = lastCached; + + if ( binding === undefined ) { + + // since we do not bother to create new bindings + // for objects that are cached, the binding may + // or may not exist + + binding = new PropertyBinding( object, paths[ j ], parsedPaths[ j ] ); + + } + + bindingsForPath[ firstActiveIndex ] = binding; + + } + + } else if ( objects[ index ] !== knownObject ) { + + console.error( 'THREE.AnimationObjectGroup: Different objects with the same UUID ' + + 'detected. Clean the caches or recreate your infrastructure when reloading scenes.' ); + + } // else the object is already where we want it to be + + } // for arguments + + this.nCachedObjects_ = nCachedObjects; + + } + + remove() { + + const objects = this._objects, + indicesByUUID = this._indicesByUUID, + bindings = this._bindings, + nBindings = bindings.length; + + let nCachedObjects = this.nCachedObjects_; + + for ( let i = 0, n = arguments.length; i !== n; ++ i ) { + + const object = arguments[ i ], + uuid = object.uuid, + index = indicesByUUID[ uuid ]; + + if ( index !== undefined && index >= nCachedObjects ) { + + // move existing object into the CACHED region + + const lastCachedIndex = nCachedObjects ++, + firstActiveObject = objects[ lastCachedIndex ]; + + indicesByUUID[ firstActiveObject.uuid ] = index; + objects[ index ] = firstActiveObject; + + indicesByUUID[ uuid ] = lastCachedIndex; + objects[ lastCachedIndex ] = object; + + // accounting is done, now do the same for all bindings + + for ( let j = 0, m = nBindings; j !== m; ++ j ) { + + const bindingsForPath = bindings[ j ], + firstActive = bindingsForPath[ lastCachedIndex ], + binding = bindingsForPath[ index ]; + + bindingsForPath[ index ] = firstActive; + bindingsForPath[ lastCachedIndex ] = binding; + + } + + } + + } // for arguments + + this.nCachedObjects_ = nCachedObjects; + + } + + // remove & forget + uncache() { + + const objects = this._objects, + indicesByUUID = this._indicesByUUID, + bindings = this._bindings, + nBindings = bindings.length; + + let nCachedObjects = this.nCachedObjects_, + nObjects = objects.length; + + for ( let i = 0, n = arguments.length; i !== n; ++ i ) { + + const object = arguments[ i ], + uuid = object.uuid, + index = indicesByUUID[ uuid ]; + + if ( index !== undefined ) { + + delete indicesByUUID[ uuid ]; + + if ( index < nCachedObjects ) { + + // object is cached, shrink the CACHED region + + const firstActiveIndex = -- nCachedObjects, + lastCachedObject = objects[ firstActiveIndex ], + lastIndex = -- nObjects, + lastObject = objects[ lastIndex ]; + + // last cached object takes this object's place + indicesByUUID[ lastCachedObject.uuid ] = index; + objects[ index ] = lastCachedObject; + + // last object goes to the activated slot and pop + indicesByUUID[ lastObject.uuid ] = firstActiveIndex; + objects[ firstActiveIndex ] = lastObject; + objects.pop(); + + // accounting is done, now do the same for all bindings + + for ( let j = 0, m = nBindings; j !== m; ++ j ) { + + const bindingsForPath = bindings[ j ], + lastCached = bindingsForPath[ firstActiveIndex ], + last = bindingsForPath[ lastIndex ]; + + bindingsForPath[ index ] = lastCached; + bindingsForPath[ firstActiveIndex ] = last; + bindingsForPath.pop(); + + } + + } else { + + // object is active, just swap with the last and pop + + const lastIndex = -- nObjects, + lastObject = objects[ lastIndex ]; + + if ( lastIndex > 0 ) { + + indicesByUUID[ lastObject.uuid ] = index; + + } + + objects[ index ] = lastObject; + objects.pop(); + + // accounting is done, now do the same for all bindings + + for ( let j = 0, m = nBindings; j !== m; ++ j ) { + + const bindingsForPath = bindings[ j ]; + + bindingsForPath[ index ] = bindingsForPath[ lastIndex ]; + bindingsForPath.pop(); + + } + + } // cached or active + + } // if object is known + + } // for arguments + + this.nCachedObjects_ = nCachedObjects; + + } + + // Internal interface used by befriended PropertyBinding.Composite: + + subscribe_( path, parsedPath ) { + + // returns an array of bindings for the given path that is changed + // according to the contained objects in the group + + const indicesByPath = this._bindingsIndicesByPath; + let index = indicesByPath[ path ]; + const bindings = this._bindings; + + if ( index !== undefined ) return bindings[ index ]; + + const paths = this._paths, + parsedPaths = this._parsedPaths, + objects = this._objects, + nObjects = objects.length, + nCachedObjects = this.nCachedObjects_, + bindingsForPath = new Array( nObjects ); + + index = bindings.length; + + indicesByPath[ path ] = index; + + paths.push( path ); + parsedPaths.push( parsedPath ); + bindings.push( bindingsForPath ); + + for ( let i = nCachedObjects, n = objects.length; i !== n; ++ i ) { + + const object = objects[ i ]; + bindingsForPath[ i ] = new PropertyBinding( object, path, parsedPath ); + + } + + return bindingsForPath; + + } + + unsubscribe_( path ) { + + // tells the group to forget about a property path and no longer + // update the array previously obtained with 'subscribe_' + + const indicesByPath = this._bindingsIndicesByPath, + index = indicesByPath[ path ]; + + if ( index !== undefined ) { + + const paths = this._paths, + parsedPaths = this._parsedPaths, + bindings = this._bindings, + lastBindingsIndex = bindings.length - 1, + lastBindings = bindings[ lastBindingsIndex ], + lastBindingsPath = path[ lastBindingsIndex ]; + + indicesByPath[ lastBindingsPath ] = index; + + bindings[ index ] = lastBindings; + bindings.pop(); + + parsedPaths[ index ] = parsedPaths[ lastBindingsIndex ]; + parsedPaths.pop(); + + paths[ index ] = paths[ lastBindingsIndex ]; + paths.pop(); + + } + + } + +} + +class AnimationAction { + + constructor( mixer, clip, localRoot = null, blendMode = clip.blendMode ) { + + this._mixer = mixer; + this._clip = clip; + this._localRoot = localRoot; + this.blendMode = blendMode; + + const tracks = clip.tracks, + nTracks = tracks.length, + interpolants = new Array( nTracks ); + + const interpolantSettings = { + endingStart: ZeroCurvatureEnding, + endingEnd: ZeroCurvatureEnding + }; + + for ( let i = 0; i !== nTracks; ++ i ) { + + const interpolant = tracks[ i ].createInterpolant( null ); + interpolants[ i ] = interpolant; + interpolant.settings = interpolantSettings; + + } + + this._interpolantSettings = interpolantSettings; + + this._interpolants = interpolants; // bound by the mixer + + // inside: PropertyMixer (managed by the mixer) + this._propertyBindings = new Array( nTracks ); + + this._cacheIndex = null; // for the memory manager + this._byClipCacheIndex = null; // for the memory manager + + this._timeScaleInterpolant = null; + this._weightInterpolant = null; + + this.loop = LoopRepeat; + this._loopCount = - 1; + + // global mixer time when the action is to be started + // it's set back to 'null' upon start of the action + this._startTime = null; + + // scaled local time of the action + // gets clamped or wrapped to 0..clip.duration according to loop + this.time = 0; + + this.timeScale = 1; + this._effectiveTimeScale = 1; + + this.weight = 1; + this._effectiveWeight = 1; + + this.repetitions = Infinity; // no. of repetitions when looping + + this.paused = false; // true -> zero effective time scale + this.enabled = true; // false -> zero effective weight + + this.clampWhenFinished = false;// keep feeding the last frame? + + this.zeroSlopeAtStart = true;// for smooth interpolation w/o separate + this.zeroSlopeAtEnd = true;// clips for start, loop and end + + } + + // State & Scheduling + + play() { + + this._mixer._activateAction( this ); + + return this; + + } + + stop() { + + this._mixer._deactivateAction( this ); + + return this.reset(); + + } + + reset() { + + this.paused = false; + this.enabled = true; + + this.time = 0; // restart clip + this._loopCount = - 1;// forget previous loops + this._startTime = null;// forget scheduling + + return this.stopFading().stopWarping(); + + } + + isRunning() { + + return this.enabled && ! this.paused && this.timeScale !== 0 && + this._startTime === null && this._mixer._isActiveAction( this ); + + } + + // return true when play has been called + isScheduled() { + + return this._mixer._isActiveAction( this ); + + } + + startAt( time ) { + + this._startTime = time; + + return this; + + } + + setLoop( mode, repetitions ) { + + this.loop = mode; + this.repetitions = repetitions; + + return this; + + } + + // Weight + + // set the weight stopping any scheduled fading + // although .enabled = false yields an effective weight of zero, this + // method does *not* change .enabled, because it would be confusing + setEffectiveWeight( weight ) { + + this.weight = weight; + + // note: same logic as when updated at runtime + this._effectiveWeight = this.enabled ? weight : 0; + + return this.stopFading(); + + } + + // return the weight considering fading and .enabled + getEffectiveWeight() { + + return this._effectiveWeight; + + } + + fadeIn( duration ) { + + return this._scheduleFading( duration, 0, 1 ); + + } + + fadeOut( duration ) { + + return this._scheduleFading( duration, 1, 0 ); + + } + + crossFadeFrom( fadeOutAction, duration, warp ) { + + fadeOutAction.fadeOut( duration ); + this.fadeIn( duration ); + + if ( warp ) { + + const fadeInDuration = this._clip.duration, + fadeOutDuration = fadeOutAction._clip.duration, + + startEndRatio = fadeOutDuration / fadeInDuration, + endStartRatio = fadeInDuration / fadeOutDuration; + + fadeOutAction.warp( 1.0, startEndRatio, duration ); + this.warp( endStartRatio, 1.0, duration ); + + } + + return this; + + } + + crossFadeTo( fadeInAction, duration, warp ) { + + return fadeInAction.crossFadeFrom( this, duration, warp ); + + } + + stopFading() { + + const weightInterpolant = this._weightInterpolant; + + if ( weightInterpolant !== null ) { + + this._weightInterpolant = null; + this._mixer._takeBackControlInterpolant( weightInterpolant ); + + } + + return this; + + } + + // Time Scale Control + + // set the time scale stopping any scheduled warping + // although .paused = true yields an effective time scale of zero, this + // method does *not* change .paused, because it would be confusing + setEffectiveTimeScale( timeScale ) { + + this.timeScale = timeScale; + this._effectiveTimeScale = this.paused ? 0 : timeScale; + + return this.stopWarping(); + + } + + // return the time scale considering warping and .paused + getEffectiveTimeScale() { + + return this._effectiveTimeScale; + + } + + setDuration( duration ) { + + this.timeScale = this._clip.duration / duration; + + return this.stopWarping(); + + } + + syncWith( action ) { + + this.time = action.time; + this.timeScale = action.timeScale; + + return this.stopWarping(); + + } + + halt( duration ) { + + return this.warp( this._effectiveTimeScale, 0, duration ); + + } + + warp( startTimeScale, endTimeScale, duration ) { + + const mixer = this._mixer, + now = mixer.time, + timeScale = this.timeScale; + + let interpolant = this._timeScaleInterpolant; + + if ( interpolant === null ) { + + interpolant = mixer._lendControlInterpolant(); + this._timeScaleInterpolant = interpolant; + + } + + const times = interpolant.parameterPositions, + values = interpolant.sampleValues; + + times[ 0 ] = now; + times[ 1 ] = now + duration; + + values[ 0 ] = startTimeScale / timeScale; + values[ 1 ] = endTimeScale / timeScale; + + return this; + + } + + stopWarping() { + + const timeScaleInterpolant = this._timeScaleInterpolant; + + if ( timeScaleInterpolant !== null ) { + + this._timeScaleInterpolant = null; + this._mixer._takeBackControlInterpolant( timeScaleInterpolant ); + + } + + return this; + + } + + // Object Accessors + + getMixer() { + + return this._mixer; + + } + + getClip() { + + return this._clip; + + } + + getRoot() { + + return this._localRoot || this._mixer._root; + + } + + // Interna + + _update( time, deltaTime, timeDirection, accuIndex ) { + + // called by the mixer + + if ( ! this.enabled ) { + + // call ._updateWeight() to update ._effectiveWeight + + this._updateWeight( time ); + return; + + } + + const startTime = this._startTime; + + if ( startTime !== null ) { + + // check for scheduled start of action + + const timeRunning = ( time - startTime ) * timeDirection; + if ( timeRunning < 0 || timeDirection === 0 ) { + + deltaTime = 0; + + } else { + + + this._startTime = null; // unschedule + deltaTime = timeDirection * timeRunning; + + } + + } + + // apply time scale and advance time + + deltaTime *= this._updateTimeScale( time ); + const clipTime = this._updateTime( deltaTime ); + + // note: _updateTime may disable the action resulting in + // an effective weight of 0 + + const weight = this._updateWeight( time ); + + if ( weight > 0 ) { + + const interpolants = this._interpolants; + const propertyMixers = this._propertyBindings; + + switch ( this.blendMode ) { + + case AdditiveAnimationBlendMode: + + for ( let j = 0, m = interpolants.length; j !== m; ++ j ) { + + interpolants[ j ].evaluate( clipTime ); + propertyMixers[ j ].accumulateAdditive( weight ); + + } + + break; + + case NormalAnimationBlendMode: + default: + + for ( let j = 0, m = interpolants.length; j !== m; ++ j ) { + + interpolants[ j ].evaluate( clipTime ); + propertyMixers[ j ].accumulate( accuIndex, weight ); + + } + + } + + } + + } + + _updateWeight( time ) { + + let weight = 0; + + if ( this.enabled ) { + + weight = this.weight; + const interpolant = this._weightInterpolant; + + if ( interpolant !== null ) { + + const interpolantValue = interpolant.evaluate( time )[ 0 ]; + + weight *= interpolantValue; + + if ( time > interpolant.parameterPositions[ 1 ] ) { + + this.stopFading(); + + if ( interpolantValue === 0 ) { + + // faded out, disable + this.enabled = false; + + } + + } + + } + + } + + this._effectiveWeight = weight; + return weight; + + } + + _updateTimeScale( time ) { + + let timeScale = 0; + + if ( ! this.paused ) { + + timeScale = this.timeScale; + + const interpolant = this._timeScaleInterpolant; + + if ( interpolant !== null ) { + + const interpolantValue = interpolant.evaluate( time )[ 0 ]; + + timeScale *= interpolantValue; + + if ( time > interpolant.parameterPositions[ 1 ] ) { + + this.stopWarping(); + + if ( timeScale === 0 ) { + + // motion has halted, pause + this.paused = true; + + } else { + + // warp done - apply final time scale + this.timeScale = timeScale; + + } + + } + + } + + } + + this._effectiveTimeScale = timeScale; + return timeScale; + + } + + _updateTime( deltaTime ) { + + const duration = this._clip.duration; + const loop = this.loop; + + let time = this.time + deltaTime; + let loopCount = this._loopCount; + + const pingPong = ( loop === LoopPingPong ); + + if ( deltaTime === 0 ) { + + if ( loopCount === - 1 ) return time; + + return ( pingPong && ( loopCount & 1 ) === 1 ) ? duration - time : time; + + } + + if ( loop === LoopOnce ) { + + if ( loopCount === - 1 ) { + + // just started + + this._loopCount = 0; + this._setEndings( true, true, false ); + + } + + handle_stop: { + + if ( time >= duration ) { + + time = duration; + + } else if ( time < 0 ) { + + time = 0; + + } else { + + this.time = time; + + break handle_stop; + + } + + if ( this.clampWhenFinished ) this.paused = true; + else this.enabled = false; + + this.time = time; + + this._mixer.dispatchEvent( { + type: 'finished', action: this, + direction: deltaTime < 0 ? - 1 : 1 + } ); + + } + + } else { // repetitive Repeat or PingPong + + if ( loopCount === - 1 ) { + + // just started + + if ( deltaTime >= 0 ) { + + loopCount = 0; + + this._setEndings( true, this.repetitions === 0, pingPong ); + + } else { + + // when looping in reverse direction, the initial + // transition through zero counts as a repetition, + // so leave loopCount at -1 + + this._setEndings( this.repetitions === 0, true, pingPong ); + + } + + } + + if ( time >= duration || time < 0 ) { + + // wrap around + + const loopDelta = Math.floor( time / duration ); // signed + time -= duration * loopDelta; + + loopCount += Math.abs( loopDelta ); + + const pending = this.repetitions - loopCount; + + if ( pending <= 0 ) { + + // have to stop (switch state, clamp time, fire event) + + if ( this.clampWhenFinished ) this.paused = true; + else this.enabled = false; + + time = deltaTime > 0 ? duration : 0; + + this.time = time; + + this._mixer.dispatchEvent( { + type: 'finished', action: this, + direction: deltaTime > 0 ? 1 : - 1 + } ); + + } else { + + // keep running + + if ( pending === 1 ) { + + // entering the last round + + const atStart = deltaTime < 0; + this._setEndings( atStart, ! atStart, pingPong ); + + } else { + + this._setEndings( false, false, pingPong ); + + } + + this._loopCount = loopCount; + + this.time = time; + + this._mixer.dispatchEvent( { + type: 'loop', action: this, loopDelta: loopDelta + } ); + + } + + } else { + + this.time = time; + + } + + if ( pingPong && ( loopCount & 1 ) === 1 ) { + + // invert time for the "pong round" + + return duration - time; + + } + + } + + return time; + + } + + _setEndings( atStart, atEnd, pingPong ) { + + const settings = this._interpolantSettings; + + if ( pingPong ) { + + settings.endingStart = ZeroSlopeEnding; + settings.endingEnd = ZeroSlopeEnding; + + } else { + + // assuming for LoopOnce atStart == atEnd == true + + if ( atStart ) { + + settings.endingStart = this.zeroSlopeAtStart ? ZeroSlopeEnding : ZeroCurvatureEnding; + + } else { + + settings.endingStart = WrapAroundEnding; + + } + + if ( atEnd ) { + + settings.endingEnd = this.zeroSlopeAtEnd ? ZeroSlopeEnding : ZeroCurvatureEnding; + + } else { + + settings.endingEnd = WrapAroundEnding; + + } + + } + + } + + _scheduleFading( duration, weightNow, weightThen ) { + + const mixer = this._mixer, now = mixer.time; + let interpolant = this._weightInterpolant; + + if ( interpolant === null ) { + + interpolant = mixer._lendControlInterpolant(); + this._weightInterpolant = interpolant; + + } + + const times = interpolant.parameterPositions, + values = interpolant.sampleValues; + + times[ 0 ] = now; + values[ 0 ] = weightNow; + times[ 1 ] = now + duration; + values[ 1 ] = weightThen; + + return this; + + } + +} + +const _controlInterpolantsResultBuffer = new Float32Array( 1 ); + + +class AnimationMixer extends EventDispatcher { + + constructor( root ) { + + super(); + + this._root = root; + this._initMemoryManager(); + this._accuIndex = 0; + this.time = 0; + this.timeScale = 1.0; + + } + + _bindAction( action, prototypeAction ) { + + const root = action._localRoot || this._root, + tracks = action._clip.tracks, + nTracks = tracks.length, + bindings = action._propertyBindings, + interpolants = action._interpolants, + rootUuid = root.uuid, + bindingsByRoot = this._bindingsByRootAndName; + + let bindingsByName = bindingsByRoot[ rootUuid ]; + + if ( bindingsByName === undefined ) { + + bindingsByName = {}; + bindingsByRoot[ rootUuid ] = bindingsByName; + + } + + for ( let i = 0; i !== nTracks; ++ i ) { + + const track = tracks[ i ], + trackName = track.name; + + let binding = bindingsByName[ trackName ]; + + if ( binding !== undefined ) { + + ++ binding.referenceCount; + bindings[ i ] = binding; + + } else { + + binding = bindings[ i ]; + + if ( binding !== undefined ) { + + // existing binding, make sure the cache knows + + if ( binding._cacheIndex === null ) { + + ++ binding.referenceCount; + this._addInactiveBinding( binding, rootUuid, trackName ); + + } + + continue; + + } + + const path = prototypeAction && prototypeAction. + _propertyBindings[ i ].binding.parsedPath; + + binding = new PropertyMixer( + PropertyBinding.create( root, trackName, path ), + track.ValueTypeName, track.getValueSize() ); + + ++ binding.referenceCount; + this._addInactiveBinding( binding, rootUuid, trackName ); + + bindings[ i ] = binding; + + } + + interpolants[ i ].resultBuffer = binding.buffer; + + } + + } + + _activateAction( action ) { + + if ( ! this._isActiveAction( action ) ) { + + if ( action._cacheIndex === null ) { + + // this action has been forgotten by the cache, but the user + // appears to be still using it -> rebind + + const rootUuid = ( action._localRoot || this._root ).uuid, + clipUuid = action._clip.uuid, + actionsForClip = this._actionsByClip[ clipUuid ]; + + this._bindAction( action, + actionsForClip && actionsForClip.knownActions[ 0 ] ); + + this._addInactiveAction( action, clipUuid, rootUuid ); + + } + + const bindings = action._propertyBindings; + + // increment reference counts / sort out state + for ( let i = 0, n = bindings.length; i !== n; ++ i ) { + + const binding = bindings[ i ]; + + if ( binding.useCount ++ === 0 ) { + + this._lendBinding( binding ); + binding.saveOriginalState(); + + } + + } + + this._lendAction( action ); + + } + + } + + _deactivateAction( action ) { + + if ( this._isActiveAction( action ) ) { + + const bindings = action._propertyBindings; + + // decrement reference counts / sort out state + for ( let i = 0, n = bindings.length; i !== n; ++ i ) { + + const binding = bindings[ i ]; + + if ( -- binding.useCount === 0 ) { + + binding.restoreOriginalState(); + this._takeBackBinding( binding ); + + } + + } + + this._takeBackAction( action ); + + } + + } + + // Memory manager + + _initMemoryManager() { + + this._actions = []; // 'nActiveActions' followed by inactive ones + this._nActiveActions = 0; + + this._actionsByClip = {}; + // inside: + // { + // knownActions: Array< AnimationAction > - used as prototypes + // actionByRoot: AnimationAction - lookup + // } + + + this._bindings = []; // 'nActiveBindings' followed by inactive ones + this._nActiveBindings = 0; + + this._bindingsByRootAndName = {}; // inside: Map< name, PropertyMixer > + + + this._controlInterpolants = []; // same game as above + this._nActiveControlInterpolants = 0; + + const scope = this; + + this.stats = { + + actions: { + get total() { + + return scope._actions.length; + + }, + get inUse() { + + return scope._nActiveActions; + + } + }, + bindings: { + get total() { + + return scope._bindings.length; + + }, + get inUse() { + + return scope._nActiveBindings; + + } + }, + controlInterpolants: { + get total() { + + return scope._controlInterpolants.length; + + }, + get inUse() { + + return scope._nActiveControlInterpolants; + + } + } + + }; + + } + + // Memory management for AnimationAction objects + + _isActiveAction( action ) { + + const index = action._cacheIndex; + return index !== null && index < this._nActiveActions; + + } + + _addInactiveAction( action, clipUuid, rootUuid ) { + + const actions = this._actions, + actionsByClip = this._actionsByClip; + + let actionsForClip = actionsByClip[ clipUuid ]; + + if ( actionsForClip === undefined ) { + + actionsForClip = { + + knownActions: [ action ], + actionByRoot: {} + + }; + + action._byClipCacheIndex = 0; + + actionsByClip[ clipUuid ] = actionsForClip; + + } else { + + const knownActions = actionsForClip.knownActions; + + action._byClipCacheIndex = knownActions.length; + knownActions.push( action ); + + } + + action._cacheIndex = actions.length; + actions.push( action ); + + actionsForClip.actionByRoot[ rootUuid ] = action; + + } + + _removeInactiveAction( action ) { + + const actions = this._actions, + lastInactiveAction = actions[ actions.length - 1 ], + cacheIndex = action._cacheIndex; + + lastInactiveAction._cacheIndex = cacheIndex; + actions[ cacheIndex ] = lastInactiveAction; + actions.pop(); + + action._cacheIndex = null; + + + const clipUuid = action._clip.uuid, + actionsByClip = this._actionsByClip, + actionsForClip = actionsByClip[ clipUuid ], + knownActionsForClip = actionsForClip.knownActions, + + lastKnownAction = + knownActionsForClip[ knownActionsForClip.length - 1 ], + + byClipCacheIndex = action._byClipCacheIndex; + + lastKnownAction._byClipCacheIndex = byClipCacheIndex; + knownActionsForClip[ byClipCacheIndex ] = lastKnownAction; + knownActionsForClip.pop(); + + action._byClipCacheIndex = null; + + + const actionByRoot = actionsForClip.actionByRoot, + rootUuid = ( action._localRoot || this._root ).uuid; + + delete actionByRoot[ rootUuid ]; + + if ( knownActionsForClip.length === 0 ) { + + delete actionsByClip[ clipUuid ]; + + } + + this._removeInactiveBindingsForAction( action ); + + } + + _removeInactiveBindingsForAction( action ) { + + const bindings = action._propertyBindings; + + for ( let i = 0, n = bindings.length; i !== n; ++ i ) { + + const binding = bindings[ i ]; + + if ( -- binding.referenceCount === 0 ) { + + this._removeInactiveBinding( binding ); + + } + + } + + } + + _lendAction( action ) { + + // [ active actions | inactive actions ] + // [ active actions >| inactive actions ] + // s a + // <-swap-> + // a s + + const actions = this._actions, + prevIndex = action._cacheIndex, + + lastActiveIndex = this._nActiveActions ++, + + firstInactiveAction = actions[ lastActiveIndex ]; + + action._cacheIndex = lastActiveIndex; + actions[ lastActiveIndex ] = action; + + firstInactiveAction._cacheIndex = prevIndex; + actions[ prevIndex ] = firstInactiveAction; + + } + + _takeBackAction( action ) { + + // [ active actions | inactive actions ] + // [ active actions |< inactive actions ] + // a s + // <-swap-> + // s a + + const actions = this._actions, + prevIndex = action._cacheIndex, + + firstInactiveIndex = -- this._nActiveActions, + + lastActiveAction = actions[ firstInactiveIndex ]; + + action._cacheIndex = firstInactiveIndex; + actions[ firstInactiveIndex ] = action; + + lastActiveAction._cacheIndex = prevIndex; + actions[ prevIndex ] = lastActiveAction; + + } + + // Memory management for PropertyMixer objects + + _addInactiveBinding( binding, rootUuid, trackName ) { + + const bindingsByRoot = this._bindingsByRootAndName, + bindings = this._bindings; + + let bindingByName = bindingsByRoot[ rootUuid ]; + + if ( bindingByName === undefined ) { + + bindingByName = {}; + bindingsByRoot[ rootUuid ] = bindingByName; + + } + + bindingByName[ trackName ] = binding; + + binding._cacheIndex = bindings.length; + bindings.push( binding ); + + } + + _removeInactiveBinding( binding ) { + + const bindings = this._bindings, + propBinding = binding.binding, + rootUuid = propBinding.rootNode.uuid, + trackName = propBinding.path, + bindingsByRoot = this._bindingsByRootAndName, + bindingByName = bindingsByRoot[ rootUuid ], + + lastInactiveBinding = bindings[ bindings.length - 1 ], + cacheIndex = binding._cacheIndex; + + lastInactiveBinding._cacheIndex = cacheIndex; + bindings[ cacheIndex ] = lastInactiveBinding; + bindings.pop(); + + delete bindingByName[ trackName ]; + + if ( Object.keys( bindingByName ).length === 0 ) { + + delete bindingsByRoot[ rootUuid ]; + + } + + } + + _lendBinding( binding ) { + + const bindings = this._bindings, + prevIndex = binding._cacheIndex, + + lastActiveIndex = this._nActiveBindings ++, + + firstInactiveBinding = bindings[ lastActiveIndex ]; + + binding._cacheIndex = lastActiveIndex; + bindings[ lastActiveIndex ] = binding; + + firstInactiveBinding._cacheIndex = prevIndex; + bindings[ prevIndex ] = firstInactiveBinding; + + } + + _takeBackBinding( binding ) { + + const bindings = this._bindings, + prevIndex = binding._cacheIndex, + + firstInactiveIndex = -- this._nActiveBindings, + + lastActiveBinding = bindings[ firstInactiveIndex ]; + + binding._cacheIndex = firstInactiveIndex; + bindings[ firstInactiveIndex ] = binding; + + lastActiveBinding._cacheIndex = prevIndex; + bindings[ prevIndex ] = lastActiveBinding; + + } + + + // Memory management of Interpolants for weight and time scale + + _lendControlInterpolant() { + + const interpolants = this._controlInterpolants, + lastActiveIndex = this._nActiveControlInterpolants ++; + + let interpolant = interpolants[ lastActiveIndex ]; + + if ( interpolant === undefined ) { + + interpolant = new LinearInterpolant( + new Float32Array( 2 ), new Float32Array( 2 ), + 1, _controlInterpolantsResultBuffer ); + + interpolant.__cacheIndex = lastActiveIndex; + interpolants[ lastActiveIndex ] = interpolant; + + } + + return interpolant; + + } + + _takeBackControlInterpolant( interpolant ) { + + const interpolants = this._controlInterpolants, + prevIndex = interpolant.__cacheIndex, + + firstInactiveIndex = -- this._nActiveControlInterpolants, + + lastActiveInterpolant = interpolants[ firstInactiveIndex ]; + + interpolant.__cacheIndex = firstInactiveIndex; + interpolants[ firstInactiveIndex ] = interpolant; + + lastActiveInterpolant.__cacheIndex = prevIndex; + interpolants[ prevIndex ] = lastActiveInterpolant; + + } + + // return an action for a clip optionally using a custom root target + // object (this method allocates a lot of dynamic memory in case a + // previously unknown clip/root combination is specified) + clipAction( clip, optionalRoot, blendMode ) { + + const root = optionalRoot || this._root, + rootUuid = root.uuid; + + let clipObject = typeof clip === 'string' ? AnimationClip.findByName( root, clip ) : clip; + + const clipUuid = clipObject !== null ? clipObject.uuid : clip; + + const actionsForClip = this._actionsByClip[ clipUuid ]; + let prototypeAction = null; + + if ( blendMode === undefined ) { + + if ( clipObject !== null ) { + + blendMode = clipObject.blendMode; + + } else { + + blendMode = NormalAnimationBlendMode; + + } + + } + + if ( actionsForClip !== undefined ) { + + const existingAction = actionsForClip.actionByRoot[ rootUuid ]; + + if ( existingAction !== undefined && existingAction.blendMode === blendMode ) { + + return existingAction; + + } + + // we know the clip, so we don't have to parse all + // the bindings again but can just copy + prototypeAction = actionsForClip.knownActions[ 0 ]; + + // also, take the clip from the prototype action + if ( clipObject === null ) + clipObject = prototypeAction._clip; + + } + + // clip must be known when specified via string + if ( clipObject === null ) return null; + + // allocate all resources required to run it + const newAction = new AnimationAction( this, clipObject, optionalRoot, blendMode ); + + this._bindAction( newAction, prototypeAction ); + + // and make the action known to the memory manager + this._addInactiveAction( newAction, clipUuid, rootUuid ); + + return newAction; + + } + + // get an existing action + existingAction( clip, optionalRoot ) { + + const root = optionalRoot || this._root, + rootUuid = root.uuid, + + clipObject = typeof clip === 'string' ? + AnimationClip.findByName( root, clip ) : clip, + + clipUuid = clipObject ? clipObject.uuid : clip, + + actionsForClip = this._actionsByClip[ clipUuid ]; + + if ( actionsForClip !== undefined ) { + + return actionsForClip.actionByRoot[ rootUuid ] || null; + + } + + return null; + + } + + // deactivates all previously scheduled actions + stopAllAction() { + + const actions = this._actions, + nActions = this._nActiveActions; + + for ( let i = nActions - 1; i >= 0; -- i ) { + + actions[ i ].stop(); + + } + + return this; + + } + + // advance the time and update apply the animation + update( deltaTime ) { + + deltaTime *= this.timeScale; + + const actions = this._actions, + nActions = this._nActiveActions, + + time = this.time += deltaTime, + timeDirection = Math.sign( deltaTime ), + + accuIndex = this._accuIndex ^= 1; + + // run active actions + + for ( let i = 0; i !== nActions; ++ i ) { + + const action = actions[ i ]; + + action._update( time, deltaTime, timeDirection, accuIndex ); + + } + + // update scene graph + + const bindings = this._bindings, + nBindings = this._nActiveBindings; + + for ( let i = 0; i !== nBindings; ++ i ) { + + bindings[ i ].apply( accuIndex ); + + } + + return this; + + } + + // Allows you to seek to a specific time in an animation. + setTime( timeInSeconds ) { + + this.time = 0; // Zero out time attribute for AnimationMixer object; + for ( let i = 0; i < this._actions.length; i ++ ) { + + this._actions[ i ].time = 0; // Zero out time attribute for all associated AnimationAction objects. + + } + + return this.update( timeInSeconds ); // Update used to set exact time. Returns "this" AnimationMixer object. + + } + + // return this mixer's root target object + getRoot() { + + return this._root; + + } + + // free all resources specific to a particular clip + uncacheClip( clip ) { + + const actions = this._actions, + clipUuid = clip.uuid, + actionsByClip = this._actionsByClip, + actionsForClip = actionsByClip[ clipUuid ]; + + if ( actionsForClip !== undefined ) { + + // note: just calling _removeInactiveAction would mess up the + // iteration state and also require updating the state we can + // just throw away + + const actionsToRemove = actionsForClip.knownActions; + + for ( let i = 0, n = actionsToRemove.length; i !== n; ++ i ) { + + const action = actionsToRemove[ i ]; + + this._deactivateAction( action ); + + const cacheIndex = action._cacheIndex, + lastInactiveAction = actions[ actions.length - 1 ]; + + action._cacheIndex = null; + action._byClipCacheIndex = null; + + lastInactiveAction._cacheIndex = cacheIndex; + actions[ cacheIndex ] = lastInactiveAction; + actions.pop(); + + this._removeInactiveBindingsForAction( action ); + + } + + delete actionsByClip[ clipUuid ]; + + } + + } + + // free all resources specific to a particular root target object + uncacheRoot( root ) { + + const rootUuid = root.uuid, + actionsByClip = this._actionsByClip; + + for ( const clipUuid in actionsByClip ) { + + const actionByRoot = actionsByClip[ clipUuid ].actionByRoot, + action = actionByRoot[ rootUuid ]; + + if ( action !== undefined ) { + + this._deactivateAction( action ); + this._removeInactiveAction( action ); + + } + + } + + const bindingsByRoot = this._bindingsByRootAndName, + bindingByName = bindingsByRoot[ rootUuid ]; + + if ( bindingByName !== undefined ) { + + for ( const trackName in bindingByName ) { + + const binding = bindingByName[ trackName ]; + binding.restoreOriginalState(); + this._removeInactiveBinding( binding ); + + } + + } + + } + + // remove a targeted clip from the cache + uncacheAction( clip, optionalRoot ) { + + const action = this.existingAction( clip, optionalRoot ); + + if ( action !== null ) { + + this._deactivateAction( action ); + this._removeInactiveAction( action ); + + } + + } + +} + +let Uniform$1 = class Uniform { + + constructor( value ) { + + this.value = value; + + } + + clone() { + + return new Uniform( this.value.clone === undefined ? this.value : this.value.clone() ); + + } + +}; + +let _id$8 = 0; + +let UniformsGroup$1 = class UniformsGroup extends EventDispatcher { + + constructor() { + + super(); + + this.isUniformsGroup = true; + + Object.defineProperty( this, 'id', { value: _id$8 ++ } ); + + this.name = ''; + + this.usage = StaticDrawUsage; + this.uniforms = []; + + } + + add( uniform ) { + + this.uniforms.push( uniform ); + + return this; + + } + + remove( uniform ) { + + const index = this.uniforms.indexOf( uniform ); + + if ( index !== - 1 ) this.uniforms.splice( index, 1 ); + + return this; + + } + + setName( name ) { + + this.name = name; + + return this; + + } + + setUsage( value ) { + + this.usage = value; + + return this; + + } + + dispose() { + + this.dispatchEvent( { type: 'dispose' } ); + + return this; + + } + + copy( source ) { + + this.name = source.name; + this.usage = source.usage; + + const uniformsSource = source.uniforms; + + this.uniforms.length = 0; + + for ( let i = 0, l = uniformsSource.length; i < l; i ++ ) { + + const uniforms = Array.isArray( uniformsSource[ i ] ) ? uniformsSource[ i ] : [ uniformsSource[ i ] ]; + + for ( let j = 0; j < uniforms.length; j ++ ) { + + this.uniforms.push( uniforms[ j ].clone() ); + + } + + } + + return this; + + } + + clone() { + + return new this.constructor().copy( this ); + + } + +}; + +class InstancedInterleavedBuffer extends InterleavedBuffer { + + constructor( array, stride, meshPerAttribute = 1 ) { + + super( array, stride ); + + this.isInstancedInterleavedBuffer = true; + + this.meshPerAttribute = meshPerAttribute; + + } + + copy( source ) { + + super.copy( source ); + + this.meshPerAttribute = source.meshPerAttribute; + + return this; + + } + + clone( data ) { + + const ib = super.clone( data ); + + ib.meshPerAttribute = this.meshPerAttribute; + + return ib; + + } + + toJSON( data ) { + + const json = super.toJSON( data ); + + json.isInstancedInterleavedBuffer = true; + json.meshPerAttribute = this.meshPerAttribute; + + return json; + + } + +} + +class GLBufferAttribute { + + constructor( buffer, type, itemSize, elementSize, count ) { + + this.isGLBufferAttribute = true; + + this.name = ''; + + this.buffer = buffer; + this.type = type; + this.itemSize = itemSize; + this.elementSize = elementSize; + this.count = count; + + this.version = 0; + + } + + set needsUpdate( value ) { + + if ( value === true ) this.version ++; + + } + + setBuffer( buffer ) { + + this.buffer = buffer; + + return this; + + } + + setType( type, elementSize ) { + + this.type = type; + this.elementSize = elementSize; + + return this; + + } + + setItemSize( itemSize ) { + + this.itemSize = itemSize; + + return this; + + } + + setCount( count ) { + + this.count = count; + + return this; + + } + +} + +const _matrix = /*@__PURE__*/ new Matrix4(); + +class Raycaster { + + constructor( origin, direction, near = 0, far = Infinity ) { + + this.ray = new Ray( origin, direction ); + // direction is assumed to be normalized (for accurate distance calculations) + + this.near = near; + this.far = far; + this.camera = null; + this.layers = new Layers(); + + this.params = { + Mesh: {}, + Line: { threshold: 1 }, + LOD: {}, + Points: { threshold: 1 }, + Sprite: {} + }; + + } + + set( origin, direction ) { + + // direction is assumed to be normalized (for accurate distance calculations) + + this.ray.set( origin, direction ); + + } + + setFromCamera( coords, camera ) { + + if ( camera.isPerspectiveCamera ) { + + this.ray.origin.setFromMatrixPosition( camera.matrixWorld ); + this.ray.direction.set( coords.x, coords.y, 0.5 ).unproject( camera ).sub( this.ray.origin ).normalize(); + this.camera = camera; + + } else if ( camera.isOrthographicCamera ) { + + this.ray.origin.set( coords.x, coords.y, ( camera.near + camera.far ) / ( camera.near - camera.far ) ).unproject( camera ); // set origin in plane of camera + this.ray.direction.set( 0, 0, - 1 ).transformDirection( camera.matrixWorld ); + this.camera = camera; + + } else { + + console.error( 'THREE.Raycaster: Unsupported camera type: ' + camera.type ); + + } + + } + + setFromXRController( controller ) { + + _matrix.identity().extractRotation( controller.matrixWorld ); + + this.ray.origin.setFromMatrixPosition( controller.matrixWorld ); + this.ray.direction.set( 0, 0, - 1 ).applyMatrix4( _matrix ); + + return this; + + } + + intersectObject( object, recursive = true, intersects = [] ) { + + intersect( object, this, intersects, recursive ); + + intersects.sort( ascSort ); + + return intersects; + + } + + intersectObjects( objects, recursive = true, intersects = [] ) { + + for ( let i = 0, l = objects.length; i < l; i ++ ) { + + intersect( objects[ i ], this, intersects, recursive ); + + } + + intersects.sort( ascSort ); + + return intersects; + + } + +} + +function ascSort( a, b ) { + + return a.distance - b.distance; + +} + +function intersect( object, raycaster, intersects, recursive ) { + + let propagate = true; + + if ( object.layers.test( raycaster.layers ) ) { + + const result = object.raycast( raycaster, intersects ); + + if ( result === false ) propagate = false; + + } + + if ( propagate === true && recursive === true ) { + + const children = object.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { + + intersect( children[ i ], raycaster, intersects, true ); + + } + + } + +} + +/** + * Ref: https://en.wikipedia.org/wiki/Spherical_coordinate_system + * + * phi (the polar angle) is measured from the positive y-axis. The positive y-axis is up. + * theta (the azimuthal angle) is measured from the positive z-axis. + */ +class Spherical { + + constructor( radius = 1, phi = 0, theta = 0 ) { + + this.radius = radius; + this.phi = phi; // polar angle + this.theta = theta; // azimuthal angle + + return this; + + } + + set( radius, phi, theta ) { + + this.radius = radius; + this.phi = phi; + this.theta = theta; + + return this; + + } + + copy( other ) { + + this.radius = other.radius; + this.phi = other.phi; + this.theta = other.theta; + + return this; + + } + + // restrict phi to be between EPS and PI-EPS + makeSafe() { + + const EPS = 0.000001; + this.phi = Math.max( EPS, Math.min( Math.PI - EPS, this.phi ) ); + + return this; + + } + + setFromVector3( v ) { + + return this.setFromCartesianCoords( v.x, v.y, v.z ); + + } + + setFromCartesianCoords( x, y, z ) { + + this.radius = Math.sqrt( x * x + y * y + z * z ); + + if ( this.radius === 0 ) { + + this.theta = 0; + this.phi = 0; + + } else { + + this.theta = Math.atan2( x, z ); + this.phi = Math.acos( clamp$1( y / this.radius, - 1, 1 ) ); + + } + + return this; + + } + + clone() { + + return new this.constructor().copy( this ); + + } + +} + +/** + * Ref: https://en.wikipedia.org/wiki/Cylindrical_coordinate_system + */ + +class Cylindrical { + + constructor( radius = 1, theta = 0, y = 0 ) { + + this.radius = radius; // distance from the origin to a point in the x-z plane + this.theta = theta; // counterclockwise angle in the x-z plane measured in radians from the positive z-axis + this.y = y; // height above the x-z plane + + return this; + + } + + set( radius, theta, y ) { + + this.radius = radius; + this.theta = theta; + this.y = y; + + return this; + + } + + copy( other ) { + + this.radius = other.radius; + this.theta = other.theta; + this.y = other.y; + + return this; + + } + + setFromVector3( v ) { + + return this.setFromCartesianCoords( v.x, v.y, v.z ); + + } + + setFromCartesianCoords( x, y, z ) { + + this.radius = Math.sqrt( x * x + z * z ); + this.theta = Math.atan2( x, z ); + this.y = y; + + return this; + + } + + clone() { + + return new this.constructor().copy( this ); + + } + +} + +class Matrix2 { + + constructor( n11, n12, n21, n22 ) { + + Matrix2.prototype.isMatrix2 = true; + + this.elements = [ + 1, 0, + 0, 1, + ]; + + if ( n11 !== undefined ) { + + this.set( n11, n12, n21, n22 ); + + } + + } + + identity() { + + this.set( + 1, 0, + 0, 1, + ); + + return this; + + } + + fromArray( array, offset = 0 ) { + + for ( let i = 0; i < 4; i ++ ) { + + this.elements[ i ] = array[ i + offset ]; + + } + + return this; + + } + + set( n11, n12, n21, n22 ) { + + const te = this.elements; + + te[ 0 ] = n11; te[ 2 ] = n12; + te[ 1 ] = n21; te[ 3 ] = n22; + + return this; + + } + +} + +const _vector$4 = /*@__PURE__*/ new Vector2(); + +class Box2 { + + constructor( min = new Vector2( + Infinity, + Infinity ), max = new Vector2( - Infinity, - Infinity ) ) { + + this.isBox2 = true; + + this.min = min; + this.max = max; + + } + + set( min, max ) { + + this.min.copy( min ); + this.max.copy( max ); + + return this; + + } + + setFromPoints( points ) { + + this.makeEmpty(); + + for ( let i = 0, il = points.length; i < il; i ++ ) { + + this.expandByPoint( points[ i ] ); + + } + + return this; + + } + + setFromCenterAndSize( center, size ) { + + const halfSize = _vector$4.copy( size ).multiplyScalar( 0.5 ); + this.min.copy( center ).sub( halfSize ); + this.max.copy( center ).add( halfSize ); + + return this; + + } + + clone() { + + return new this.constructor().copy( this ); + + } + + copy( box ) { + + this.min.copy( box.min ); + this.max.copy( box.max ); + + return this; + + } + + makeEmpty() { + + this.min.x = this.min.y = + Infinity; + this.max.x = this.max.y = - Infinity; + + return this; + + } + + isEmpty() { + + // this is a more robust check for empty than ( volume <= 0 ) because volume can get positive with two negative axes + + return ( this.max.x < this.min.x ) || ( this.max.y < this.min.y ); + + } + + getCenter( target ) { + + return this.isEmpty() ? target.set( 0, 0 ) : target.addVectors( this.min, this.max ).multiplyScalar( 0.5 ); + + } + + getSize( target ) { + + return this.isEmpty() ? target.set( 0, 0 ) : target.subVectors( this.max, this.min ); + + } + + expandByPoint( point ) { + + this.min.min( point ); + this.max.max( point ); + + return this; + + } + + expandByVector( vector ) { + + this.min.sub( vector ); + this.max.add( vector ); + + return this; + + } + + expandByScalar( scalar ) { + + this.min.addScalar( - scalar ); + this.max.addScalar( scalar ); + + return this; + + } + + containsPoint( point ) { + + return point.x >= this.min.x && point.x <= this.max.x && + point.y >= this.min.y && point.y <= this.max.y; + + } + + containsBox( box ) { + + return this.min.x <= box.min.x && box.max.x <= this.max.x && + this.min.y <= box.min.y && box.max.y <= this.max.y; + + } + + getParameter( point, target ) { + + // This can potentially have a divide by zero if the box + // has a size dimension of 0. + + return target.set( + ( point.x - this.min.x ) / ( this.max.x - this.min.x ), + ( point.y - this.min.y ) / ( this.max.y - this.min.y ) + ); + + } + + intersectsBox( box ) { + + // using 4 splitting planes to rule out intersections + + return box.max.x >= this.min.x && box.min.x <= this.max.x && + box.max.y >= this.min.y && box.min.y <= this.max.y; + + } + + clampPoint( point, target ) { + + return target.copy( point ).clamp( this.min, this.max ); + + } + + distanceToPoint( point ) { + + return this.clampPoint( point, _vector$4 ).distanceTo( point ); + + } + + intersect( box ) { + + this.min.max( box.min ); + this.max.min( box.max ); + + if ( this.isEmpty() ) this.makeEmpty(); + + return this; + + } + + union( box ) { + + this.min.min( box.min ); + this.max.max( box.max ); + + return this; + + } + + translate( offset ) { + + this.min.add( offset ); + this.max.add( offset ); + + return this; + + } + + equals( box ) { + + return box.min.equals( this.min ) && box.max.equals( this.max ); + + } + +} + +const _startP = /*@__PURE__*/ new Vector3(); +const _startEnd = /*@__PURE__*/ new Vector3(); + +class Line3 { + + constructor( start = new Vector3(), end = new Vector3() ) { + + this.start = start; + this.end = end; + + } + + set( start, end ) { + + this.start.copy( start ); + this.end.copy( end ); + + return this; + + } + + copy( line ) { + + this.start.copy( line.start ); + this.end.copy( line.end ); + + return this; + + } + + getCenter( target ) { + + return target.addVectors( this.start, this.end ).multiplyScalar( 0.5 ); + + } + + delta( target ) { + + return target.subVectors( this.end, this.start ); + + } + + distanceSq() { + + return this.start.distanceToSquared( this.end ); + + } + + distance() { + + return this.start.distanceTo( this.end ); + + } + + at( t, target ) { + + return this.delta( target ).multiplyScalar( t ).add( this.start ); + + } + + closestPointToPointParameter( point, clampToLine ) { + + _startP.subVectors( point, this.start ); + _startEnd.subVectors( this.end, this.start ); + + const startEnd2 = _startEnd.dot( _startEnd ); + const startEnd_startP = _startEnd.dot( _startP ); + + let t = startEnd_startP / startEnd2; + + if ( clampToLine ) { + + t = clamp$1( t, 0, 1 ); + + } + + return t; + + } + + closestPointToPoint( point, clampToLine, target ) { + + const t = this.closestPointToPointParameter( point, clampToLine ); + + return this.delta( target ).multiplyScalar( t ).add( this.start ); + + } + + applyMatrix4( matrix ) { + + this.start.applyMatrix4( matrix ); + this.end.applyMatrix4( matrix ); + + return this; + + } + + equals( line ) { + + return line.start.equals( this.start ) && line.end.equals( this.end ); + + } + + clone() { + + return new this.constructor().copy( this ); + + } + +} + +const _vector$3 = /*@__PURE__*/ new Vector3(); + +class SpotLightHelper extends Object3D { + + constructor( light, color ) { + + super(); + + this.light = light; + + this.matrixAutoUpdate = false; + + this.color = color; + + this.type = 'SpotLightHelper'; + + const geometry = new BufferGeometry(); + + const positions = [ + 0, 0, 0, 0, 0, 1, + 0, 0, 0, 1, 0, 1, + 0, 0, 0, - 1, 0, 1, + 0, 0, 0, 0, 1, 1, + 0, 0, 0, 0, - 1, 1 + ]; + + for ( let i = 0, j = 1, l = 32; i < l; i ++, j ++ ) { + + const p1 = ( i / l ) * Math.PI * 2; + const p2 = ( j / l ) * Math.PI * 2; + + positions.push( + Math.cos( p1 ), Math.sin( p1 ), 1, + Math.cos( p2 ), Math.sin( p2 ), 1 + ); + + } + + geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + + const material = new LineBasicMaterial( { fog: false, toneMapped: false } ); + + this.cone = new LineSegments( geometry, material ); + this.add( this.cone ); + + this.update(); + + } + + dispose() { + + this.cone.geometry.dispose(); + this.cone.material.dispose(); + + } + + update() { + + this.light.updateWorldMatrix( true, false ); + this.light.target.updateWorldMatrix( true, false ); + + // update the local matrix based on the parent and light target transforms + if ( this.parent ) { + + this.parent.updateWorldMatrix( true ); + + this.matrix + .copy( this.parent.matrixWorld ) + .invert() + .multiply( this.light.matrixWorld ); + + } else { + + this.matrix.copy( this.light.matrixWorld ); + + } + + this.matrixWorld.copy( this.light.matrixWorld ); + + const coneLength = this.light.distance ? this.light.distance : 1000; + const coneWidth = coneLength * Math.tan( this.light.angle ); + + this.cone.scale.set( coneWidth, coneWidth, coneLength ); + + _vector$3.setFromMatrixPosition( this.light.target.matrixWorld ); + + this.cone.lookAt( _vector$3 ); + + if ( this.color !== undefined ) { + + this.cone.material.color.set( this.color ); + + } else { + + this.cone.material.color.copy( this.light.color ); + + } + + } + +} + +const _vector$2 = /*@__PURE__*/ new Vector3(); +const _boneMatrix = /*@__PURE__*/ new Matrix4(); +const _matrixWorldInv = /*@__PURE__*/ new Matrix4(); + + +class SkeletonHelper extends LineSegments { + + constructor( object ) { + + const bones = getBoneList( object ); + + const geometry = new BufferGeometry(); + + const vertices = []; + const colors = []; + + const color1 = new Color( 0, 0, 1 ); + const color2 = new Color( 0, 1, 0 ); + + for ( let i = 0; i < bones.length; i ++ ) { + + const bone = bones[ i ]; + + if ( bone.parent && bone.parent.isBone ) { + + vertices.push( 0, 0, 0 ); + vertices.push( 0, 0, 0 ); + colors.push( color1.r, color1.g, color1.b ); + colors.push( color2.r, color2.g, color2.b ); + + } + + } + + geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + + const material = new LineBasicMaterial( { vertexColors: true, depthTest: false, depthWrite: false, toneMapped: false, transparent: true } ); + + super( geometry, material ); + + this.isSkeletonHelper = true; + + this.type = 'SkeletonHelper'; + + this.root = object; + this.bones = bones; + + this.matrix = object.matrixWorld; + this.matrixAutoUpdate = false; + + } + + updateMatrixWorld( force ) { + + const bones = this.bones; + + const geometry = this.geometry; + const position = geometry.getAttribute( 'position' ); + + _matrixWorldInv.copy( this.root.matrixWorld ).invert(); + + for ( let i = 0, j = 0; i < bones.length; i ++ ) { + + const bone = bones[ i ]; + + if ( bone.parent && bone.parent.isBone ) { + + _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.matrixWorld ); + _vector$2.setFromMatrixPosition( _boneMatrix ); + position.setXYZ( j, _vector$2.x, _vector$2.y, _vector$2.z ); + + _boneMatrix.multiplyMatrices( _matrixWorldInv, bone.parent.matrixWorld ); + _vector$2.setFromMatrixPosition( _boneMatrix ); + position.setXYZ( j + 1, _vector$2.x, _vector$2.y, _vector$2.z ); + + j += 2; + + } + + } + + geometry.getAttribute( 'position' ).needsUpdate = true; + + super.updateMatrixWorld( force ); + + } + + dispose() { + + this.geometry.dispose(); + this.material.dispose(); + + } + +} + + +function getBoneList( object ) { + + const boneList = []; + + if ( object.isBone === true ) { + + boneList.push( object ); + + } + + for ( let i = 0; i < object.children.length; i ++ ) { + + boneList.push.apply( boneList, getBoneList( object.children[ i ] ) ); + + } + + return boneList; + +} + +class PointLightHelper extends Mesh { + + constructor( light, sphereSize, color ) { + + const geometry = new SphereGeometry( sphereSize, 4, 2 ); + const material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } ); + + super( geometry, material ); + + this.light = light; + + this.color = color; + + this.type = 'PointLightHelper'; + + this.matrix = this.light.matrixWorld; + this.matrixAutoUpdate = false; + + this.update(); + + + /* + // TODO: delete this comment? + const distanceGeometry = new THREE.IcosahedronGeometry( 1, 2 ); + const distanceMaterial = new THREE.MeshBasicMaterial( { color: hexColor, fog: false, wireframe: true, opacity: 0.1, transparent: true } ); + + this.lightSphere = new THREE.Mesh( bulbGeometry, bulbMaterial ); + this.lightDistance = new THREE.Mesh( distanceGeometry, distanceMaterial ); + + const d = light.distance; + + if ( d === 0.0 ) { + + this.lightDistance.visible = false; + + } else { + + this.lightDistance.scale.set( d, d, d ); + + } + + this.add( this.lightDistance ); + */ + + } + + dispose() { + + this.geometry.dispose(); + this.material.dispose(); + + } + + update() { + + this.light.updateWorldMatrix( true, false ); + + if ( this.color !== undefined ) { + + this.material.color.set( this.color ); + + } else { + + this.material.color.copy( this.light.color ); + + } + + /* + const d = this.light.distance; + + if ( d === 0.0 ) { + + this.lightDistance.visible = false; + + } else { + + this.lightDistance.visible = true; + this.lightDistance.scale.set( d, d, d ); + + } + */ + + } + +} + +const _vector$1 = /*@__PURE__*/ new Vector3(); +const _color1 = /*@__PURE__*/ new Color(); +const _color2 = /*@__PURE__*/ new Color(); + +class HemisphereLightHelper extends Object3D { + + constructor( light, size, color ) { + + super(); + + this.light = light; + + this.matrix = light.matrixWorld; + this.matrixAutoUpdate = false; + + this.color = color; + + this.type = 'HemisphereLightHelper'; + + const geometry = new OctahedronGeometry( size ); + geometry.rotateY( Math.PI * 0.5 ); + + this.material = new MeshBasicMaterial( { wireframe: true, fog: false, toneMapped: false } ); + if ( this.color === undefined ) this.material.vertexColors = true; + + const position = geometry.getAttribute( 'position' ); + const colors = new Float32Array( position.count * 3 ); + + geometry.setAttribute( 'color', new BufferAttribute( colors, 3 ) ); + + this.add( new Mesh( geometry, this.material ) ); + + this.update(); + + } + + dispose() { + + this.children[ 0 ].geometry.dispose(); + this.children[ 0 ].material.dispose(); + + } + + update() { + + const mesh = this.children[ 0 ]; + + if ( this.color !== undefined ) { + + this.material.color.set( this.color ); + + } else { + + const colors = mesh.geometry.getAttribute( 'color' ); + + _color1.copy( this.light.color ); + _color2.copy( this.light.groundColor ); + + for ( let i = 0, l = colors.count; i < l; i ++ ) { + + const color = ( i < ( l / 2 ) ) ? _color1 : _color2; + + colors.setXYZ( i, color.r, color.g, color.b ); + + } + + colors.needsUpdate = true; + + } + + this.light.updateWorldMatrix( true, false ); + + mesh.lookAt( _vector$1.setFromMatrixPosition( this.light.matrixWorld ).negate() ); + + } + +} + +class GridHelper extends LineSegments { + + constructor( size = 10, divisions = 10, color1 = 0x444444, color2 = 0x888888 ) { + + color1 = new Color( color1 ); + color2 = new Color( color2 ); + + const center = divisions / 2; + const step = size / divisions; + const halfSize = size / 2; + + const vertices = [], colors = []; + + for ( let i = 0, j = 0, k = - halfSize; i <= divisions; i ++, k += step ) { + + vertices.push( - halfSize, 0, k, halfSize, 0, k ); + vertices.push( k, 0, - halfSize, k, 0, halfSize ); + + const color = i === center ? color1 : color2; + + color.toArray( colors, j ); j += 3; + color.toArray( colors, j ); j += 3; + color.toArray( colors, j ); j += 3; + color.toArray( colors, j ); j += 3; + + } + + const geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + + const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); + + super( geometry, material ); + + this.type = 'GridHelper'; + + } + + dispose() { + + this.geometry.dispose(); + this.material.dispose(); + + } + +} + +class PolarGridHelper extends LineSegments { + + constructor( radius = 10, sectors = 16, rings = 8, divisions = 64, color1 = 0x444444, color2 = 0x888888 ) { + + color1 = new Color( color1 ); + color2 = new Color( color2 ); + + const vertices = []; + const colors = []; + + // create the sectors + + if ( sectors > 1 ) { + + for ( let i = 0; i < sectors; i ++ ) { + + const v = ( i / sectors ) * ( Math.PI * 2 ); + + const x = Math.sin( v ) * radius; + const z = Math.cos( v ) * radius; + + vertices.push( 0, 0, 0 ); + vertices.push( x, 0, z ); + + const color = ( i & 1 ) ? color1 : color2; + + colors.push( color.r, color.g, color.b ); + colors.push( color.r, color.g, color.b ); + + } + + } + + // create the rings + + for ( let i = 0; i < rings; i ++ ) { + + const color = ( i & 1 ) ? color1 : color2; + + const r = radius - ( radius / rings * i ); + + for ( let j = 0; j < divisions; j ++ ) { + + // first vertex + + let v = ( j / divisions ) * ( Math.PI * 2 ); + + let x = Math.sin( v ) * r; + let z = Math.cos( v ) * r; + + vertices.push( x, 0, z ); + colors.push( color.r, color.g, color.b ); + + // second vertex + + v = ( ( j + 1 ) / divisions ) * ( Math.PI * 2 ); + + x = Math.sin( v ) * r; + z = Math.cos( v ) * r; + + vertices.push( x, 0, z ); + colors.push( color.r, color.g, color.b ); + + } + + } + + const geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + + const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); + + super( geometry, material ); + + this.type = 'PolarGridHelper'; + + } + + dispose() { + + this.geometry.dispose(); + this.material.dispose(); + + } + +} + +const _v1 = /*@__PURE__*/ new Vector3(); +const _v2 = /*@__PURE__*/ new Vector3(); +const _v3 = /*@__PURE__*/ new Vector3(); + +class DirectionalLightHelper extends Object3D { + + constructor( light, size, color ) { + + super(); + + this.light = light; + + this.matrix = light.matrixWorld; + this.matrixAutoUpdate = false; + + this.color = color; + + this.type = 'DirectionalLightHelper'; + + if ( size === undefined ) size = 1; + + let geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new Float32BufferAttribute( [ + - size, size, 0, + size, size, 0, + size, - size, 0, + - size, - size, 0, + - size, size, 0 + ], 3 ) ); + + const material = new LineBasicMaterial( { fog: false, toneMapped: false } ); + + this.lightPlane = new Line( geometry, material ); + this.add( this.lightPlane ); + + geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 0, 1 ], 3 ) ); + + this.targetLine = new Line( geometry, material ); + this.add( this.targetLine ); + + this.update(); + + } + + dispose() { + + this.lightPlane.geometry.dispose(); + this.lightPlane.material.dispose(); + this.targetLine.geometry.dispose(); + this.targetLine.material.dispose(); + + } + + update() { + + this.light.updateWorldMatrix( true, false ); + this.light.target.updateWorldMatrix( true, false ); + + _v1.setFromMatrixPosition( this.light.matrixWorld ); + _v2.setFromMatrixPosition( this.light.target.matrixWorld ); + _v3.subVectors( _v2, _v1 ); + + this.lightPlane.lookAt( _v2 ); + + if ( this.color !== undefined ) { + + this.lightPlane.material.color.set( this.color ); + this.targetLine.material.color.set( this.color ); + + } else { + + this.lightPlane.material.color.copy( this.light.color ); + this.targetLine.material.color.copy( this.light.color ); + + } + + this.targetLine.lookAt( _v2 ); + this.targetLine.scale.z = _v3.length(); + + } + +} + +const _vector = /*@__PURE__*/ new Vector3(); +const _camera$1 = /*@__PURE__*/ new Camera(); + +/** + * - shows frustum, line of sight and up of the camera + * - suitable for fast updates + * - based on frustum visualization in lightgl.js shadowmap example + * https://github.com/evanw/lightgl.js/blob/master/tests/shadowmap.html + */ + +class CameraHelper extends LineSegments { + + constructor( camera ) { + + const geometry = new BufferGeometry(); + const material = new LineBasicMaterial( { color: 0xffffff, vertexColors: true, toneMapped: false } ); + + const vertices = []; + const colors = []; + + const pointMap = {}; + + // near + + addLine( 'n1', 'n2' ); + addLine( 'n2', 'n4' ); + addLine( 'n4', 'n3' ); + addLine( 'n3', 'n1' ); + + // far + + addLine( 'f1', 'f2' ); + addLine( 'f2', 'f4' ); + addLine( 'f4', 'f3' ); + addLine( 'f3', 'f1' ); + + // sides + + addLine( 'n1', 'f1' ); + addLine( 'n2', 'f2' ); + addLine( 'n3', 'f3' ); + addLine( 'n4', 'f4' ); + + // cone + + addLine( 'p', 'n1' ); + addLine( 'p', 'n2' ); + addLine( 'p', 'n3' ); + addLine( 'p', 'n4' ); + + // up + + addLine( 'u1', 'u2' ); + addLine( 'u2', 'u3' ); + addLine( 'u3', 'u1' ); + + // target + + addLine( 'c', 't' ); + addLine( 'p', 'c' ); + + // cross + + addLine( 'cn1', 'cn2' ); + addLine( 'cn3', 'cn4' ); + + addLine( 'cf1', 'cf2' ); + addLine( 'cf3', 'cf4' ); + + function addLine( a, b ) { + + addPoint( a ); + addPoint( b ); + + } + + function addPoint( id ) { + + vertices.push( 0, 0, 0 ); + colors.push( 0, 0, 0 ); + + if ( pointMap[ id ] === undefined ) { + + pointMap[ id ] = []; + + } + + pointMap[ id ].push( ( vertices.length / 3 ) - 1 ); + + } + + geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + + super( geometry, material ); + + this.type = 'CameraHelper'; + + this.camera = camera; + if ( this.camera.updateProjectionMatrix ) this.camera.updateProjectionMatrix(); + + this.matrix = camera.matrixWorld; + this.matrixAutoUpdate = false; + + this.pointMap = pointMap; + + this.update(); + + // colors + + const colorFrustum = new Color( 0xffaa00 ); + const colorCone = new Color( 0xff0000 ); + const colorUp = new Color( 0x00aaff ); + const colorTarget = new Color( 0xffffff ); + const colorCross = new Color( 0x333333 ); + + this.setColors( colorFrustum, colorCone, colorUp, colorTarget, colorCross ); + + } + + setColors( frustum, cone, up, target, cross ) { + + const geometry = this.geometry; + + const colorAttribute = geometry.getAttribute( 'color' ); + + // near + + colorAttribute.setXYZ( 0, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 1, frustum.r, frustum.g, frustum.b ); // n1, n2 + colorAttribute.setXYZ( 2, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 3, frustum.r, frustum.g, frustum.b ); // n2, n4 + colorAttribute.setXYZ( 4, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 5, frustum.r, frustum.g, frustum.b ); // n4, n3 + colorAttribute.setXYZ( 6, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 7, frustum.r, frustum.g, frustum.b ); // n3, n1 + + // far + + colorAttribute.setXYZ( 8, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 9, frustum.r, frustum.g, frustum.b ); // f1, f2 + colorAttribute.setXYZ( 10, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 11, frustum.r, frustum.g, frustum.b ); // f2, f4 + colorAttribute.setXYZ( 12, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 13, frustum.r, frustum.g, frustum.b ); // f4, f3 + colorAttribute.setXYZ( 14, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 15, frustum.r, frustum.g, frustum.b ); // f3, f1 + + // sides + + colorAttribute.setXYZ( 16, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 17, frustum.r, frustum.g, frustum.b ); // n1, f1 + colorAttribute.setXYZ( 18, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 19, frustum.r, frustum.g, frustum.b ); // n2, f2 + colorAttribute.setXYZ( 20, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 21, frustum.r, frustum.g, frustum.b ); // n3, f3 + colorAttribute.setXYZ( 22, frustum.r, frustum.g, frustum.b ); colorAttribute.setXYZ( 23, frustum.r, frustum.g, frustum.b ); // n4, f4 + + // cone + + colorAttribute.setXYZ( 24, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 25, cone.r, cone.g, cone.b ); // p, n1 + colorAttribute.setXYZ( 26, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 27, cone.r, cone.g, cone.b ); // p, n2 + colorAttribute.setXYZ( 28, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 29, cone.r, cone.g, cone.b ); // p, n3 + colorAttribute.setXYZ( 30, cone.r, cone.g, cone.b ); colorAttribute.setXYZ( 31, cone.r, cone.g, cone.b ); // p, n4 + + // up + + colorAttribute.setXYZ( 32, up.r, up.g, up.b ); colorAttribute.setXYZ( 33, up.r, up.g, up.b ); // u1, u2 + colorAttribute.setXYZ( 34, up.r, up.g, up.b ); colorAttribute.setXYZ( 35, up.r, up.g, up.b ); // u2, u3 + colorAttribute.setXYZ( 36, up.r, up.g, up.b ); colorAttribute.setXYZ( 37, up.r, up.g, up.b ); // u3, u1 + + // target + + colorAttribute.setXYZ( 38, target.r, target.g, target.b ); colorAttribute.setXYZ( 39, target.r, target.g, target.b ); // c, t + colorAttribute.setXYZ( 40, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 41, cross.r, cross.g, cross.b ); // p, c + + // cross + + colorAttribute.setXYZ( 42, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 43, cross.r, cross.g, cross.b ); // cn1, cn2 + colorAttribute.setXYZ( 44, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 45, cross.r, cross.g, cross.b ); // cn3, cn4 + + colorAttribute.setXYZ( 46, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 47, cross.r, cross.g, cross.b ); // cf1, cf2 + colorAttribute.setXYZ( 48, cross.r, cross.g, cross.b ); colorAttribute.setXYZ( 49, cross.r, cross.g, cross.b ); // cf3, cf4 + + colorAttribute.needsUpdate = true; + + } + + update() { + + const geometry = this.geometry; + const pointMap = this.pointMap; + + const w = 1, h = 1; + + // we need just camera projection matrix inverse + // world matrix must be identity + + _camera$1.projectionMatrixInverse.copy( this.camera.projectionMatrixInverse ); + + // center / target + + setPoint( 'c', pointMap, geometry, _camera$1, 0, 0, - 1 ); + setPoint( 't', pointMap, geometry, _camera$1, 0, 0, 1 ); + + // near + + setPoint( 'n1', pointMap, geometry, _camera$1, - w, - h, - 1 ); + setPoint( 'n2', pointMap, geometry, _camera$1, w, - h, - 1 ); + setPoint( 'n3', pointMap, geometry, _camera$1, - w, h, - 1 ); + setPoint( 'n4', pointMap, geometry, _camera$1, w, h, - 1 ); + + // far + + setPoint( 'f1', pointMap, geometry, _camera$1, - w, - h, 1 ); + setPoint( 'f2', pointMap, geometry, _camera$1, w, - h, 1 ); + setPoint( 'f3', pointMap, geometry, _camera$1, - w, h, 1 ); + setPoint( 'f4', pointMap, geometry, _camera$1, w, h, 1 ); + + // up + + setPoint( 'u1', pointMap, geometry, _camera$1, w * 0.7, h * 1.1, - 1 ); + setPoint( 'u2', pointMap, geometry, _camera$1, - w * 0.7, h * 1.1, - 1 ); + setPoint( 'u3', pointMap, geometry, _camera$1, 0, h * 2, - 1 ); + + // cross + + setPoint( 'cf1', pointMap, geometry, _camera$1, - w, 0, 1 ); + setPoint( 'cf2', pointMap, geometry, _camera$1, w, 0, 1 ); + setPoint( 'cf3', pointMap, geometry, _camera$1, 0, - h, 1 ); + setPoint( 'cf4', pointMap, geometry, _camera$1, 0, h, 1 ); + + setPoint( 'cn1', pointMap, geometry, _camera$1, - w, 0, - 1 ); + setPoint( 'cn2', pointMap, geometry, _camera$1, w, 0, - 1 ); + setPoint( 'cn3', pointMap, geometry, _camera$1, 0, - h, - 1 ); + setPoint( 'cn4', pointMap, geometry, _camera$1, 0, h, - 1 ); + + geometry.getAttribute( 'position' ).needsUpdate = true; + + } + + dispose() { + + this.geometry.dispose(); + this.material.dispose(); + + } + +} + + +function setPoint( point, pointMap, geometry, camera, x, y, z ) { + + _vector.set( x, y, z ).unproject( camera ); + + const points = pointMap[ point ]; + + if ( points !== undefined ) { + + const position = geometry.getAttribute( 'position' ); + + for ( let i = 0, l = points.length; i < l; i ++ ) { + + position.setXYZ( points[ i ], _vector.x, _vector.y, _vector.z ); + + } + + } + +} + +const _box = /*@__PURE__*/ new Box3(); + +class BoxHelper extends LineSegments { + + constructor( object, color = 0xffff00 ) { + + const indices = 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 ] ); + const positions = new Float32Array( 8 * 3 ); + + const geometry = new BufferGeometry(); + geometry.setIndex( new BufferAttribute( indices, 1 ) ); + geometry.setAttribute( 'position', new BufferAttribute( positions, 3 ) ); + + super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); + + this.object = object; + this.type = 'BoxHelper'; + + this.matrixAutoUpdate = false; + + this.update(); + + } + + update( object ) { + + if ( object !== undefined ) { + + console.warn( 'THREE.BoxHelper: .update() has no longer arguments.' ); + + } + + if ( this.object !== undefined ) { + + _box.setFromObject( this.object ); + + } + + if ( _box.isEmpty() ) return; + + const min = _box.min; + const max = _box.max; + + /* + 5____4 + 1/___0/| + | 6__|_7 + 2/___3/ + + 0: max.x, max.y, max.z + 1: min.x, max.y, max.z + 2: min.x, min.y, max.z + 3: max.x, min.y, max.z + 4: max.x, max.y, min.z + 5: min.x, max.y, min.z + 6: min.x, min.y, min.z + 7: max.x, min.y, min.z + */ + + const position = this.geometry.attributes.position; + const array = position.array; + + array[ 0 ] = max.x; array[ 1 ] = max.y; array[ 2 ] = max.z; + array[ 3 ] = min.x; array[ 4 ] = max.y; array[ 5 ] = max.z; + array[ 6 ] = min.x; array[ 7 ] = min.y; array[ 8 ] = max.z; + array[ 9 ] = max.x; array[ 10 ] = min.y; array[ 11 ] = max.z; + array[ 12 ] = max.x; array[ 13 ] = max.y; array[ 14 ] = min.z; + array[ 15 ] = min.x; array[ 16 ] = max.y; array[ 17 ] = min.z; + array[ 18 ] = min.x; array[ 19 ] = min.y; array[ 20 ] = min.z; + array[ 21 ] = max.x; array[ 22 ] = min.y; array[ 23 ] = min.z; + + position.needsUpdate = true; + + this.geometry.computeBoundingSphere(); + + } + + setFromObject( object ) { + + this.object = object; + this.update(); + + return this; + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + this.object = source.object; + + return this; + + } + + dispose() { + + this.geometry.dispose(); + this.material.dispose(); + + } + +} + +class Box3Helper extends LineSegments { + + constructor( box, color = 0xffff00 ) { + + const indices = 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 ] ); + + const positions = [ 1, 1, 1, - 1, 1, 1, - 1, - 1, 1, 1, - 1, 1, 1, 1, - 1, - 1, 1, - 1, - 1, - 1, - 1, 1, - 1, - 1 ]; + + const geometry = new BufferGeometry(); + + geometry.setIndex( new BufferAttribute( indices, 1 ) ); + + geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + + super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); + + this.box = box; + + this.type = 'Box3Helper'; + + this.geometry.computeBoundingSphere(); + + } + + updateMatrixWorld( force ) { + + const box = this.box; + + if ( box.isEmpty() ) return; + + box.getCenter( this.position ); + + box.getSize( this.scale ); + + this.scale.multiplyScalar( 0.5 ); + + super.updateMatrixWorld( force ); + + } + + dispose() { + + this.geometry.dispose(); + this.material.dispose(); + + } + +} + +class PlaneHelper extends Line { + + constructor( plane, size = 1, hex = 0xffff00 ) { + + const color = hex; + + const positions = [ 1, - 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, - 1, 0, 1, 1, 0 ]; + + const geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new Float32BufferAttribute( positions, 3 ) ); + geometry.computeBoundingSphere(); + + super( geometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); + + this.type = 'PlaneHelper'; + + this.plane = plane; + + this.size = size; + + const positions2 = [ 1, 1, 0, - 1, 1, 0, - 1, - 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ]; + + const geometry2 = new BufferGeometry(); + geometry2.setAttribute( 'position', new Float32BufferAttribute( positions2, 3 ) ); + geometry2.computeBoundingSphere(); + + this.add( new Mesh( geometry2, new MeshBasicMaterial( { color: color, opacity: 0.2, transparent: true, depthWrite: false, toneMapped: false } ) ) ); + + } + + updateMatrixWorld( force ) { + + this.position.set( 0, 0, 0 ); + + this.scale.set( 0.5 * this.size, 0.5 * this.size, 1 ); + + this.lookAt( this.plane.normal ); + + this.translateZ( - this.plane.constant ); + + super.updateMatrixWorld( force ); + + } + + dispose() { + + this.geometry.dispose(); + this.material.dispose(); + this.children[ 0 ].geometry.dispose(); + this.children[ 0 ].material.dispose(); + + } + +} + +const _axis = /*@__PURE__*/ new Vector3(); +let _lineGeometry, _coneGeometry; + +class ArrowHelper extends Object3D { + + // dir is assumed to be normalized + + constructor( dir = new Vector3( 0, 0, 1 ), origin = new Vector3( 0, 0, 0 ), length = 1, color = 0xffff00, headLength = length * 0.2, headWidth = headLength * 0.2 ) { + + super(); + + this.type = 'ArrowHelper'; + + if ( _lineGeometry === undefined ) { + + _lineGeometry = new BufferGeometry(); + _lineGeometry.setAttribute( 'position', new Float32BufferAttribute( [ 0, 0, 0, 0, 1, 0 ], 3 ) ); + + _coneGeometry = new CylinderGeometry( 0, 0.5, 1, 5, 1 ); + _coneGeometry.translate( 0, - 0.5, 0 ); + + } + + this.position.copy( origin ); + + this.line = new Line( _lineGeometry, new LineBasicMaterial( { color: color, toneMapped: false } ) ); + this.line.matrixAutoUpdate = false; + this.add( this.line ); + + this.cone = new Mesh( _coneGeometry, new MeshBasicMaterial( { color: color, toneMapped: false } ) ); + this.cone.matrixAutoUpdate = false; + this.add( this.cone ); + + this.setDirection( dir ); + this.setLength( length, headLength, headWidth ); + + } + + setDirection( dir ) { + + // dir is assumed to be normalized + + if ( dir.y > 0.99999 ) { + + this.quaternion.set( 0, 0, 0, 1 ); + + } else if ( dir.y < - 0.99999 ) { + + this.quaternion.set( 1, 0, 0, 0 ); + + } else { + + _axis.set( dir.z, 0, - dir.x ).normalize(); + + const radians = Math.acos( dir.y ); + + this.quaternion.setFromAxisAngle( _axis, radians ); + + } + + } + + setLength( length, headLength = length * 0.2, headWidth = headLength * 0.2 ) { + + this.line.scale.set( 1, Math.max( 0.0001, length - headLength ), 1 ); // see #17458 + this.line.updateMatrix(); + + this.cone.scale.set( headWidth, headLength, headWidth ); + this.cone.position.y = length; + this.cone.updateMatrix(); + + } + + setColor( color ) { + + this.line.material.color.set( color ); + this.cone.material.color.set( color ); + + } + + copy( source ) { + + super.copy( source, false ); + + this.line.copy( source.line ); + this.cone.copy( source.cone ); + + return this; + + } + + dispose() { + + this.line.geometry.dispose(); + this.line.material.dispose(); + this.cone.geometry.dispose(); + this.cone.material.dispose(); + + } + +} + +class AxesHelper extends LineSegments { + + constructor( size = 1 ) { + + const vertices = [ + 0, 0, 0, size, 0, 0, + 0, 0, 0, 0, size, 0, + 0, 0, 0, 0, 0, size + ]; + + const colors = [ + 1, 0, 0, 1, 0.6, 0, + 0, 1, 0, 0.6, 1, 0, + 0, 0, 1, 0, 0.6, 1 + ]; + + const geometry = new BufferGeometry(); + geometry.setAttribute( 'position', new Float32BufferAttribute( vertices, 3 ) ); + geometry.setAttribute( 'color', new Float32BufferAttribute( colors, 3 ) ); + + const material = new LineBasicMaterial( { vertexColors: true, toneMapped: false } ); + + super( geometry, material ); + + this.type = 'AxesHelper'; + + } + + setColors( xAxisColor, yAxisColor, zAxisColor ) { + + const color = new Color(); + const array = this.geometry.attributes.color.array; + + color.set( xAxisColor ); + color.toArray( array, 0 ); + color.toArray( array, 3 ); + + color.set( yAxisColor ); + color.toArray( array, 6 ); + color.toArray( array, 9 ); + + color.set( zAxisColor ); + color.toArray( array, 12 ); + color.toArray( array, 15 ); + + this.geometry.attributes.color.needsUpdate = true; + + return this; + + } + + dispose() { + + this.geometry.dispose(); + this.material.dispose(); + + } + +} + +class ShapePath { + + constructor() { + + this.type = 'ShapePath'; + + this.color = new Color(); + + this.subPaths = []; + this.currentPath = null; + + } + + moveTo( x, y ) { + + this.currentPath = new Path(); + this.subPaths.push( this.currentPath ); + this.currentPath.moveTo( x, y ); + + return this; + + } + + lineTo( x, y ) { + + this.currentPath.lineTo( x, y ); + + return this; + + } + + quadraticCurveTo( aCPx, aCPy, aX, aY ) { + + this.currentPath.quadraticCurveTo( aCPx, aCPy, aX, aY ); + + return this; + + } + + bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ) { + + this.currentPath.bezierCurveTo( aCP1x, aCP1y, aCP2x, aCP2y, aX, aY ); + + return this; + + } + + splineThru( pts ) { + + this.currentPath.splineThru( pts ); + + return this; + + } + + toShapes( isCCW ) { + + function toShapesNoHoles( inSubpaths ) { + + const shapes = []; + + for ( let i = 0, l = inSubpaths.length; i < l; i ++ ) { + + const tmpPath = inSubpaths[ i ]; + + const tmpShape = new Shape(); + tmpShape.curves = tmpPath.curves; + + shapes.push( tmpShape ); + + } + + return shapes; + + } + + function isPointInsidePolygon( inPt, inPolygon ) { + + const polyLen = inPolygon.length; + + // inPt on polygon contour => immediate success or + // toggling of inside/outside at every single! intersection point of an edge + // with the horizontal line through inPt, left of inPt + // not counting lowerY endpoints of edges and whole edges on that line + let inside = false; + for ( let p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) { + + let edgeLowPt = inPolygon[ p ]; + let edgeHighPt = inPolygon[ q ]; + + let edgeDx = edgeHighPt.x - edgeLowPt.x; + let edgeDy = edgeHighPt.y - edgeLowPt.y; + + if ( Math.abs( edgeDy ) > Number.EPSILON ) { + + // not parallel + if ( edgeDy < 0 ) { + + edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx; + edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy; + + } + + if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue; + + if ( inPt.y === edgeLowPt.y ) { + + if ( inPt.x === edgeLowPt.x ) return true; // inPt is on contour ? + // continue; // no intersection or edgeLowPt => doesn't count !!! + + } else { + + const perpEdge = edgeDy * ( inPt.x - edgeLowPt.x ) - edgeDx * ( inPt.y - edgeLowPt.y ); + if ( perpEdge === 0 ) return true; // inPt is on contour ? + if ( perpEdge < 0 ) continue; + inside = ! inside; // true intersection left of inPt + + } + + } else { + + // parallel or collinear + if ( inPt.y !== edgeLowPt.y ) continue; // parallel + // edge lies on the same horizontal line as inPt + if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) || + ( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour ! + // continue; + + } + + } + + return inside; + + } + + const isClockWise = ShapeUtils.isClockWise; + + const subPaths = this.subPaths; + if ( subPaths.length === 0 ) return []; + + let solid, tmpPath, tmpShape; + const shapes = []; + + if ( subPaths.length === 1 ) { + + tmpPath = subPaths[ 0 ]; + tmpShape = new Shape(); + tmpShape.curves = tmpPath.curves; + shapes.push( tmpShape ); + return shapes; + + } + + let holesFirst = ! isClockWise( subPaths[ 0 ].getPoints() ); + holesFirst = isCCW ? ! holesFirst : holesFirst; + + // console.log("Holes first", holesFirst); + + const betterShapeHoles = []; + const newShapes = []; + let newShapeHoles = []; + let mainIdx = 0; + let tmpPoints; + + newShapes[ mainIdx ] = undefined; + newShapeHoles[ mainIdx ] = []; + + for ( let i = 0, l = subPaths.length; i < l; i ++ ) { + + tmpPath = subPaths[ i ]; + tmpPoints = tmpPath.getPoints(); + solid = isClockWise( tmpPoints ); + solid = isCCW ? ! solid : solid; + + if ( solid ) { + + if ( ( ! holesFirst ) && ( newShapes[ mainIdx ] ) ) mainIdx ++; + + newShapes[ mainIdx ] = { s: new Shape(), p: tmpPoints }; + newShapes[ mainIdx ].s.curves = tmpPath.curves; + + if ( holesFirst ) mainIdx ++; + newShapeHoles[ mainIdx ] = []; + + //console.log('cw', i); + + } else { + + newShapeHoles[ mainIdx ].push( { h: tmpPath, p: tmpPoints[ 0 ] } ); + + //console.log('ccw', i); + + } + + } + + // only Holes? -> probably all Shapes with wrong orientation + if ( ! newShapes[ 0 ] ) return toShapesNoHoles( subPaths ); + + + if ( newShapes.length > 1 ) { + + let ambiguous = false; + let toChange = 0; + + for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { + + betterShapeHoles[ sIdx ] = []; + + } + + for ( let sIdx = 0, sLen = newShapes.length; sIdx < sLen; sIdx ++ ) { + + const sho = newShapeHoles[ sIdx ]; + + for ( let hIdx = 0; hIdx < sho.length; hIdx ++ ) { + + const ho = sho[ hIdx ]; + let hole_unassigned = true; + + for ( let s2Idx = 0; s2Idx < newShapes.length; s2Idx ++ ) { + + if ( isPointInsidePolygon( ho.p, newShapes[ s2Idx ].p ) ) { + + if ( sIdx !== s2Idx ) toChange ++; + + if ( hole_unassigned ) { + + hole_unassigned = false; + betterShapeHoles[ s2Idx ].push( ho ); + + } else { + + ambiguous = true; + + } + + } + + } + + if ( hole_unassigned ) { + + betterShapeHoles[ sIdx ].push( ho ); + + } + + } + + } + + if ( toChange > 0 && ambiguous === false ) { + + newShapeHoles = betterShapeHoles; + + } + + } + + let tmpHoles; + + for ( let i = 0, il = newShapes.length; i < il; i ++ ) { + + tmpShape = newShapes[ i ].s; + shapes.push( tmpShape ); + tmpHoles = newShapeHoles[ i ]; + + for ( let j = 0, jl = tmpHoles.length; j < jl; j ++ ) { + + tmpShape.holes.push( tmpHoles[ j ].h ); + + } + + } + + //console.log("shape", shapes); + + return shapes; + + } + +} + +class Controls extends EventDispatcher { + + constructor( object, domElement = null ) { + + super(); + + this.object = object; + this.domElement = domElement; + + this.enabled = true; + + this.state = - 1; + + this.keys = {}; + this.mouseButtons = { LEFT: null, MIDDLE: null, RIGHT: null }; + this.touches = { ONE: null, TWO: null }; + + } + + connect() {} + + disconnect() {} + + dispose() {} + + update( /* delta */ ) {} + +} + +class WebGLMultipleRenderTargets extends WebGLRenderTarget { // @deprecated, r162 + + constructor( width = 1, height = 1, count = 1, options = {} ) { + + console.warn( 'THREE.WebGLMultipleRenderTargets has been deprecated and will be removed in r172. Use THREE.WebGLRenderTarget and set the "count" parameter to enable MRT.' ); + + super( width, height, { ...options, count } ); + + this.isWebGLMultipleRenderTargets = true; + + } + + get texture() { + + return this.textures; + + } + +} + +const refreshUniforms = [ + 'alphaMap', + 'alphaTest', + 'anisotropy', + 'anisotropyMap', + 'anisotropyRotation', + 'aoMap', + 'attenuationColor', + 'attenuationDistance', + 'bumpMap', + 'clearcoat', + 'clearcoatMap', + 'clearcoatNormalMap', + 'clearcoatNormalScale', + 'clearcoatRoughness', + 'color', + 'dispersion', + 'displacementMap', + 'emissive', + 'emissiveMap', + 'envMap', + 'gradientMap', + 'ior', + 'iridescence', + 'iridescenceIOR', + 'iridescenceMap', + 'iridescenceThicknessMap', + 'lightMap', + 'map', + 'matcap', + 'metalness', + 'metalnessMap', + 'normalMap', + 'normalScale', + 'opacity', + 'roughness', + 'roughnessMap', + 'sheen', + 'sheenColor', + 'sheenColorMap', + 'sheenRoughnessMap', + 'shininess', + 'specular', + 'specularColor', + 'specularColorMap', + 'specularIntensity', + 'specularIntensityMap', + 'specularMap', + 'thickness', + 'transmission', + 'transmissionMap' +]; + +class NodeMaterialObserver { + + constructor( builder ) { + + this.renderObjects = new WeakMap(); + this.hasNode = this.containsNode( builder ); + this.hasAnimation = builder.object.isSkinnedMesh === true; + this.refreshUniforms = refreshUniforms; + this.renderId = 0; + + } + + firstInitialization( renderObject ) { + + const hasInitialized = this.renderObjects.has( renderObject ); + + if ( hasInitialized === false ) { + + this.getRenderObjectData( renderObject ); + + return true; + + } + + return false; + + } + + getRenderObjectData( renderObject ) { + + let data = this.renderObjects.get( renderObject ); + + if ( data === undefined ) { + + data = { + material: this.getMaterialData( renderObject.material ), + worldMatrix: renderObject.object.matrixWorld.clone() + }; + + if ( renderObject.object.center ) { + + data.center = renderObject.object.center.clone(); + + } + + if ( renderObject.object.morphTargetInfluences ) { + + data.morphTargetInfluences = renderObject.object.morphTargetInfluences.slice(); + + } + + if ( renderObject.bundle !== null ) { + + data.version = renderObject.bundle.version; + + } + + this.renderObjects.set( renderObject, data ); + + } + + return data; + + } + + containsNode( builder ) { + + const material = builder.material; + + for ( const property in material ) { + + if ( material[ property ] && material[ property ].isNode ) + return true; + + } + + if ( builder.renderer.nodes.modelViewMatrix !== null || builder.renderer.nodes.modelNormalViewMatrix !== null ) + return true; + + return false; + + } + + getMaterialData( material ) { + + const data = {}; + + for ( const property of this.refreshUniforms ) { + + const value = material[ property ]; + + if ( value === null || value === undefined ) continue; + + if ( typeof value === 'object' && value.clone !== undefined ) { + + if ( value.isTexture === true ) { + + data[ property ] = { id: value.id, version: value.version }; + + } else { + + data[ property ] = value.clone(); + + } + + } else { + + data[ property ] = value; + + } + + } + + return data; + + } + + equals( renderObject ) { + + const { object, material } = renderObject; + + const renderObjectData = this.getRenderObjectData( renderObject ); + + // world matrix + + if ( renderObjectData.worldMatrix.equals( object.matrixWorld ) !== true ) { + + renderObjectData.worldMatrix.copy( object.matrixWorld ); + + return false; + + } + + // material + + const materialData = renderObjectData.material; + + for ( const property in materialData ) { + + const value = materialData[ property ]; + const mtlValue = material[ property ]; + + if ( value.equals !== undefined ) { + + if ( value.equals( mtlValue ) === false ) { + + value.copy( mtlValue ); + + return false; + + } + + } else if ( mtlValue.isTexture === true ) { + + if ( value.id !== mtlValue.id || value.version !== mtlValue.version ) { + + value.id = mtlValue.id; + value.version = mtlValue.version; + + return false; + + } + + } else if ( value !== mtlValue ) { + + materialData[ property ] = mtlValue; + + return false; + + } + + } + + // morph targets + + if ( renderObjectData.morphTargetInfluences ) { + + let morphChanged = false; + + for ( let i = 0; i < renderObjectData.morphTargetInfluences.length; i ++ ) { + + if ( renderObjectData.morphTargetInfluences[ i ] !== object.morphTargetInfluences[ i ] ) { + + morphChanged = true; + + } + + } + + if ( morphChanged ) return true; + + } + + // center + + if ( renderObjectData.center ) { + + if ( renderObjectData.center.equals( object.center ) === false ) { + + renderObjectData.center.copy( object.center ); + + return true; + + } + + } + + // bundle + + if ( renderObject.bundle !== null ) { + + renderObjectData.version = renderObject.bundle.version; + + } + + return true; + + } + + needsRefresh( renderObject, nodeFrame ) { + + if ( this.hasNode || this.hasAnimation || this.firstInitialization( renderObject ) ) + return true; + + const { renderId } = nodeFrame; + + if ( this.renderId !== renderId ) { + + this.renderId = renderId; + + return true; + + } + + const isStatic = renderObject.object.static === true; + const isBundle = renderObject.bundle !== null && renderObject.bundle.static === true && this.getRenderObjectData( renderObject ).version === renderObject.bundle.version; + + if ( isStatic || isBundle ) + return false; + + const notEqual = this.equals( renderObject ) !== true; + + return notEqual; + + } + +} + +// cyrb53 (c) 2018 bryc (github.com/bryc). License: Public domain. Attribution appreciated. +// A fast and simple 64-bit (or 53-bit) string hash function with decent collision resistance. +// Largely inspired by MurmurHash2/3, but with a focus on speed/simplicity. +// See https://stackoverflow.com/questions/7616461/generate-a-hash-from-string-in-javascript/52171480#52171480 +// https://github.com/bryc/code/blob/master/jshash/experimental/cyrb53.js +function cyrb53( value, seed = 0 ) { + + let h1 = 0xdeadbeef ^ seed, h2 = 0x41c6ce57 ^ seed; + + if ( value instanceof Array ) { + + for ( let i = 0, val; i < value.length; i ++ ) { + + val = value[ i ]; + h1 = Math.imul( h1 ^ val, 2654435761 ); + h2 = Math.imul( h2 ^ val, 1597334677 ); + + } + + } else { + + for ( let i = 0, ch; i < value.length; i ++ ) { + + ch = value.charCodeAt( i ); + h1 = Math.imul( h1 ^ ch, 2654435761 ); + h2 = Math.imul( h2 ^ ch, 1597334677 ); + + } + + } + + h1 = Math.imul( h1 ^ ( h1 >>> 16 ), 2246822507 ); + h1 ^= Math.imul( h2 ^ ( h2 >>> 13 ), 3266489909 ); + h2 = Math.imul( h2 ^ ( h2 >>> 16 ), 2246822507 ); + h2 ^= Math.imul( h1 ^ ( h1 >>> 13 ), 3266489909 ); + + return 4294967296 * ( 2097151 & h2 ) + ( h1 >>> 0 ); + +} + +const hashString = ( str ) => cyrb53( str ); +const hashArray = ( array ) => cyrb53( array ); +const hash$1 = ( ...params ) => cyrb53( params ); + +function getCacheKey$1( object, force = false ) { + + const values = []; + + if ( object.isNode === true ) { + + values.push( object.id ); + object = object.getSelf(); + + } + + for ( const { property, childNode } of getNodeChildren( object ) ) { + + values.push( values, cyrb53( property.slice( 0, - 4 ) ), childNode.getCacheKey( force ) ); + + } + + return cyrb53( values ); + +} + +function* getNodeChildren( node, toJSON = false ) { + + for ( const property in node ) { + + // Ignore private properties. + if ( property.startsWith( '_' ) === true ) continue; + + const object = node[ property ]; + + if ( Array.isArray( object ) === true ) { + + for ( let i = 0; i < object.length; i ++ ) { + + const child = object[ i ]; + + if ( child && ( child.isNode === true || toJSON && typeof child.toJSON === 'function' ) ) { + + yield { property, index: i, childNode: child }; + + } + + } + + } else if ( object && object.isNode === true ) { + + yield { property, childNode: object }; + + } else if ( typeof object === 'object' ) { + + for ( const subProperty in object ) { + + const child = object[ subProperty ]; + + if ( child && ( child.isNode === true || toJSON && typeof child.toJSON === 'function' ) ) { + + yield { property, index: subProperty, childNode: child }; + + } + + } + + } + + } + +} + +function getValueType( value ) { + + if ( value === undefined || value === null ) return null; + + const typeOf = typeof value; + + if ( value.isNode === true ) { + + return 'node'; + + } else if ( typeOf === 'number' ) { + + return 'float'; + + } else if ( typeOf === 'boolean' ) { + + return 'bool'; + + } else if ( typeOf === 'string' ) { + + return 'string'; + + } else if ( typeOf === 'function' ) { + + return 'shader'; + + } else if ( value.isVector2 === true ) { + + return 'vec2'; + + } else if ( value.isVector3 === true ) { + + return 'vec3'; + + } else if ( value.isVector4 === true ) { + + return 'vec4'; + + } else if ( value.isMatrix3 === true ) { + + return 'mat3'; + + } else if ( value.isMatrix4 === true ) { + + return 'mat4'; + + } else if ( value.isColor === true ) { + + return 'color'; + + } else if ( value instanceof ArrayBuffer ) { + + return 'ArrayBuffer'; + + } + + return null; + +} + +function getValueFromType( type, ...params ) { + + const last4 = type ? type.slice( - 4 ) : undefined; + + if ( params.length === 1 ) { // ensure same behaviour as in NodeBuilder.format() + + if ( last4 === 'vec2' ) params = [ params[ 0 ], params[ 0 ] ]; + else if ( last4 === 'vec3' ) params = [ params[ 0 ], params[ 0 ], params[ 0 ] ]; + else if ( last4 === 'vec4' ) params = [ params[ 0 ], params[ 0 ], params[ 0 ], params[ 0 ] ]; + + } + + if ( type === 'color' ) { + + return new Color( ...params ); + + } else if ( last4 === 'vec2' ) { + + return new Vector2( ...params ); + + } else if ( last4 === 'vec3' ) { + + return new Vector3( ...params ); + + } else if ( last4 === 'vec4' ) { + + return new Vector4( ...params ); + + } else if ( last4 === 'mat3' ) { + + return new Matrix3( ...params ); + + } else if ( last4 === 'mat4' ) { + + return new Matrix4( ...params ); + + } else if ( type === 'bool' ) { + + return params[ 0 ] || false; + + } else if ( ( type === 'float' ) || ( type === 'int' ) || ( type === 'uint' ) ) { + + return params[ 0 ] || 0; + + } else if ( type === 'string' ) { + + return params[ 0 ] || ''; + + } else if ( type === 'ArrayBuffer' ) { + + return base64ToArrayBuffer( params[ 0 ] ); + + } + + return null; + +} + +function arrayBufferToBase64( arrayBuffer ) { + + let chars = ''; + + const array = new Uint8Array( arrayBuffer ); + + for ( let i = 0; i < array.length; i ++ ) { + + chars += String.fromCharCode( array[ i ] ); + + } + + return btoa( chars ); + +} + +function base64ToArrayBuffer( base64 ) { + + return Uint8Array.from( atob( base64 ), c => c.charCodeAt( 0 ) ).buffer; + +} + +var NodeUtils = /*#__PURE__*/Object.freeze({ + __proto__: null, + arrayBufferToBase64: arrayBufferToBase64, + base64ToArrayBuffer: base64ToArrayBuffer, + getCacheKey: getCacheKey$1, + getNodeChildren: getNodeChildren, + getValueFromType: getValueFromType, + getValueType: getValueType, + hash: hash$1, + hashArray: hashArray, + hashString: hashString +}); + +const NodeShaderStage = { + VERTEX: 'vertex', + FRAGMENT: 'fragment' +}; + +const NodeUpdateType = { + NONE: 'none', + FRAME: 'frame', + RENDER: 'render', + OBJECT: 'object' +}; + +const NodeType = { + BOOLEAN: 'bool', + INTEGER: 'int', + FLOAT: 'float', + VECTOR2: 'vec2', + VECTOR3: 'vec3', + VECTOR4: 'vec4', + MATRIX2: 'mat2', + MATRIX3: 'mat3', + MATRIX4: 'mat4' +}; + +const defaultShaderStages = [ 'fragment', 'vertex' ]; +const defaultBuildStages = [ 'setup', 'analyze', 'generate' ]; +const shaderStages = [ ...defaultShaderStages, 'compute' ]; +const vectorComponents = [ 'x', 'y', 'z', 'w' ]; + +let _nodeId = 0; + +class Node extends EventDispatcher { + + static get type() { + + return 'Node'; + + } + + constructor( nodeType = null ) { + + super(); + + this.nodeType = nodeType; + + this.updateType = NodeUpdateType.NONE; + this.updateBeforeType = NodeUpdateType.NONE; + this.updateAfterType = NodeUpdateType.NONE; + + this.uuid = MathUtils.generateUUID(); + + this.version = 0; + + this._cacheKey = null; + this._cacheKeyVersion = 0; + + this.global = false; + + this.isNode = true; + + Object.defineProperty( this, 'id', { value: _nodeId ++ } ); + + } + + set needsUpdate( value ) { + + if ( value === true ) { + + this.version ++; + + } + + } + + get type() { + + return this.constructor.type; + + } + + onUpdate( callback, updateType ) { + + this.updateType = updateType; + this.update = callback.bind( this.getSelf() ); + + return this; + + } + + onFrameUpdate( callback ) { + + return this.onUpdate( callback, NodeUpdateType.FRAME ); + + } + + onRenderUpdate( callback ) { + + return this.onUpdate( callback, NodeUpdateType.RENDER ); + + } + + onObjectUpdate( callback ) { + + return this.onUpdate( callback, NodeUpdateType.OBJECT ); + + } + + onReference( callback ) { + + this.updateReference = callback.bind( this.getSelf() ); + + return this; + + } + + getSelf() { + + // Returns non-node object. + + return this.self || this; + + } + + updateReference( /*state*/ ) { + + return this; + + } + + isGlobal( /*builder*/ ) { + + return this.global; + + } + + * getChildren() { + + for ( const { childNode } of getNodeChildren( this ) ) { + + yield childNode; + + } + + } + + dispose() { + + this.dispatchEvent( { type: 'dispose' } ); + + } + + traverse( callback ) { + + callback( this ); + + for ( const childNode of this.getChildren() ) { + + childNode.traverse( callback ); + + } + + } + + getCacheKey( force = false ) { + + force = force || this.version !== this._cacheKeyVersion; + + if ( force === true || this._cacheKey === null ) { + + this._cacheKey = getCacheKey$1( this, force ); + this._cacheKeyVersion = this.version; + + } + + return this._cacheKey; + + } + + getScope() { + + return this; + + } + + getHash( /*builder*/ ) { + + return this.uuid; + + } + + getUpdateType() { + + return this.updateType; + + } + + getUpdateBeforeType() { + + return this.updateBeforeType; + + } + + getUpdateAfterType() { + + return this.updateAfterType; + + } + + getElementType( builder ) { + + const type = this.getNodeType( builder ); + const elementType = builder.getElementType( type ); + + return elementType; + + } + + getNodeType( builder ) { + + const nodeProperties = builder.getNodeProperties( this ); + + if ( nodeProperties.outputNode ) { + + return nodeProperties.outputNode.getNodeType( builder ); + + } + + return this.nodeType; + + } + + getShared( builder ) { + + const hash = this.getHash( builder ); + const nodeFromHash = builder.getNodeFromHash( hash ); + + return nodeFromHash || this; + + } + + setup( builder ) { + + const nodeProperties = builder.getNodeProperties( this ); + + let index = 0; + + for ( const childNode of this.getChildren() ) { + + nodeProperties[ 'node' + index ++ ] = childNode; + + } + + // return a outputNode if exists + return null; + + } + + analyze( builder ) { + + const usageCount = builder.increaseUsage( this ); + + if ( usageCount === 1 ) { + + // node flow children + + const nodeProperties = builder.getNodeProperties( this ); + + for ( const childNode of Object.values( nodeProperties ) ) { + + if ( childNode && childNode.isNode === true ) { + + childNode.build( builder ); + + } + + } + + } + + } + + generate( builder, output ) { + + const { outputNode } = builder.getNodeProperties( this ); + + if ( outputNode && outputNode.isNode === true ) { + + return outputNode.build( builder, output ); + + } + + } + + updateBefore( /*frame*/ ) { + + console.warn( 'Abstract function.' ); + + } + + updateAfter( /*frame*/ ) { + + console.warn( 'Abstract function.' ); + + } + + update( /*frame*/ ) { + + console.warn( 'Abstract function.' ); + + } + + build( builder, output = null ) { + + const refNode = this.getShared( builder ); + + if ( this !== refNode ) { + + return refNode.build( builder, output ); + + } + + builder.addNode( this ); + builder.addChain( this ); + + /* Build stages expected results: + - "setup" -> Node + - "analyze" -> null + - "generate" -> String + */ + let result = null; + + const buildStage = builder.getBuildStage(); + + if ( buildStage === 'setup' ) { + + this.updateReference( builder ); + + const properties = builder.getNodeProperties( this ); + + if ( properties.initialized !== true ) { + + const stackNodesBeforeSetup = builder.stack.nodes.length; + + properties.initialized = true; + properties.outputNode = this.setup( builder ); + + if ( properties.outputNode !== null && builder.stack.nodes.length !== stackNodesBeforeSetup ) ; + + for ( const childNode of Object.values( properties ) ) { + + if ( childNode && childNode.isNode === true ) { + + childNode.build( builder ); + + } + + } + + } + + } else if ( buildStage === 'analyze' ) { + + this.analyze( builder ); + + } else if ( buildStage === 'generate' ) { + + const isGenerateOnce = this.generate.length === 1; + + if ( isGenerateOnce ) { + + const type = this.getNodeType( builder ); + const nodeData = builder.getDataFromNode( this ); + + result = nodeData.snippet; + + if ( result === undefined ) { + + result = this.generate( builder ) || ''; + + nodeData.snippet = result; + + } else if ( nodeData.flowCodes !== undefined && builder.context.nodeBlock !== undefined ) { + + builder.addFlowCodeHierarchy( this, builder.context.nodeBlock ); + + } + + result = builder.format( result, type, output ); + + } else { + + result = this.generate( builder, output ) || ''; + + } + + } + + builder.removeChain( this ); + + return result; + + } + + getSerializeChildren() { + + return getNodeChildren( this ); + + } + + serialize( json ) { + + const nodeChildren = this.getSerializeChildren(); + + const inputNodes = {}; + + for ( const { property, index, childNode } of nodeChildren ) { + + if ( index !== undefined ) { + + if ( inputNodes[ property ] === undefined ) { + + inputNodes[ property ] = Number.isInteger( index ) ? [] : {}; + + } + + inputNodes[ property ][ index ] = childNode.toJSON( json.meta ).uuid; + + } else { + + inputNodes[ property ] = childNode.toJSON( json.meta ).uuid; + + } + + } + + if ( Object.keys( inputNodes ).length > 0 ) { + + json.inputNodes = inputNodes; + + } + + } + + deserialize( json ) { + + if ( json.inputNodes !== undefined ) { + + const nodes = json.meta.nodes; + + for ( const property in json.inputNodes ) { + + if ( Array.isArray( json.inputNodes[ property ] ) ) { + + const inputArray = []; + + for ( const uuid of json.inputNodes[ property ] ) { + + inputArray.push( nodes[ uuid ] ); + + } + + this[ property ] = inputArray; + + } else if ( typeof json.inputNodes[ property ] === 'object' ) { + + const inputObject = {}; + + for ( const subProperty in json.inputNodes[ property ] ) { + + const uuid = json.inputNodes[ property ][ subProperty ]; + + inputObject[ subProperty ] = nodes[ uuid ]; + + } + + this[ property ] = inputObject; + + } else { + + const uuid = json.inputNodes[ property ]; + + this[ property ] = nodes[ uuid ]; + + } + + } + + } + + } + + toJSON( meta ) { + + const { uuid, type } = this; + const isRoot = ( meta === undefined || typeof meta === 'string' ); + + if ( isRoot ) { + + meta = { + textures: {}, + images: {}, + nodes: {} + }; + + } + + // serialize + + let data = meta.nodes[ uuid ]; + + if ( data === undefined ) { + + data = { + uuid, + type, + meta, + metadata: { + version: 4.6, + type: 'Node', + generator: 'Node.toJSON' + } + }; + + if ( isRoot !== true ) meta.nodes[ data.uuid ] = data; + + this.serialize( data ); + + delete data.meta; + + } + + // TODO: Copied from Object3D.toJSON + + function extractFromCache( cache ) { + + const values = []; + + for ( const key in cache ) { + + const data = cache[ key ]; + delete data.metadata; + values.push( data ); + + } + + return values; + + } + + if ( isRoot ) { + + const textures = extractFromCache( meta.textures ); + const images = extractFromCache( meta.images ); + const nodes = extractFromCache( meta.nodes ); + + if ( textures.length > 0 ) data.textures = textures; + if ( images.length > 0 ) data.images = images; + if ( nodes.length > 0 ) data.nodes = nodes; + + } + + return data; + + } + +} + +class ArrayElementNode extends Node { + + static get type() { + + return 'ArrayElementNode'; + + } // @TODO: If extending from TempNode it breaks webgpu_compute + + constructor( node, indexNode ) { + + super(); + + this.node = node; + this.indexNode = indexNode; + + this.isArrayElementNode = true; + + } + + getNodeType( builder ) { + + return this.node.getElementType( builder ); + + } + + generate( builder ) { + + const nodeSnippet = this.node.build( builder ); + const indexSnippet = this.indexNode.build( builder, 'uint' ); + + return `${nodeSnippet}[ ${indexSnippet} ]`; + + } + +} + +class ConvertNode extends Node { + + static get type() { + + return 'ConvertNode'; + + } + + constructor( node, convertTo ) { + + super(); + + this.node = node; + this.convertTo = convertTo; + + } + + getNodeType( builder ) { + + const requestType = this.node.getNodeType( builder ); + + let convertTo = null; + + for ( const overloadingType of this.convertTo.split( '|' ) ) { + + if ( convertTo === null || builder.getTypeLength( requestType ) === builder.getTypeLength( overloadingType ) ) { + + convertTo = overloadingType; + + } + + } + + return convertTo; + + } + + serialize( data ) { + + super.serialize( data ); + + data.convertTo = this.convertTo; + + } + + deserialize( data ) { + + super.deserialize( data ); + + this.convertTo = data.convertTo; + + } + + generate( builder, output ) { + + const node = this.node; + const type = this.getNodeType( builder ); + + const snippet = node.build( builder, type ); + + return builder.format( snippet, type, output ); + + } + +} + +class TempNode extends Node { + + static get type() { + + return 'TempNode'; + + } + + constructor( type ) { + + super( type ); + + this.isTempNode = true; + + } + + hasDependencies( builder ) { + + return builder.getDataFromNode( this ).usageCount > 1; + + } + + build( builder, output ) { + + const buildStage = builder.getBuildStage(); + + if ( buildStage === 'generate' ) { + + const type = builder.getVectorType( this.getNodeType( builder, output ) ); + const nodeData = builder.getDataFromNode( this ); + + if ( nodeData.propertyName !== undefined ) { + + return builder.format( nodeData.propertyName, type, output ); + + } else if ( type !== 'void' && output !== 'void' && this.hasDependencies( builder ) ) { + + const snippet = super.build( builder, type ); + + const nodeVar = builder.getVarFromNode( this, null, type ); + const propertyName = builder.getPropertyName( nodeVar ); + + builder.addLineFlowCode( `${propertyName} = ${snippet}`, this ); + + nodeData.snippet = snippet; + nodeData.propertyName = propertyName; + + return builder.format( nodeData.propertyName, type, output ); + + } + + } + + return super.build( builder, output ); + + } + +} + +class JoinNode extends TempNode { + + static get type() { + + return 'JoinNode'; + + } + + constructor( nodes = [], nodeType = null ) { + + super( nodeType ); + + this.nodes = nodes; + + } + + getNodeType( builder ) { + + if ( this.nodeType !== null ) { + + return builder.getVectorType( this.nodeType ); + + } + + return builder.getTypeFromLength( this.nodes.reduce( ( count, cur ) => count + builder.getTypeLength( cur.getNodeType( builder ) ), 0 ) ); + + } + + generate( builder, output ) { + + const type = this.getNodeType( builder ); + const nodes = this.nodes; + + const primitiveType = builder.getComponentType( type ); + + const snippetValues = []; + + for ( const input of nodes ) { + + let inputSnippet = input.build( builder ); + + const inputPrimitiveType = builder.getComponentType( input.getNodeType( builder ) ); + + if ( inputPrimitiveType !== primitiveType ) { + + inputSnippet = builder.format( inputSnippet, inputPrimitiveType, primitiveType ); + + } + + snippetValues.push( inputSnippet ); + + } + + const snippet = `${ builder.getType( type ) }( ${ snippetValues.join( ', ' ) } )`; + + return builder.format( snippet, type, output ); + + } + +} + +const stringVectorComponents = vectorComponents.join( '' ); + +class SplitNode extends Node { + + static get type() { + + return 'SplitNode'; + + } + + constructor( node, components = 'x' ) { + + super(); + + this.node = node; + this.components = components; + + this.isSplitNode = true; + + } + + getVectorLength() { + + let vectorLength = this.components.length; + + for ( const c of this.components ) { + + vectorLength = Math.max( vectorComponents.indexOf( c ) + 1, vectorLength ); + + } + + return vectorLength; + + } + + getComponentType( builder ) { + + return builder.getComponentType( this.node.getNodeType( builder ) ); + + } + + getNodeType( builder ) { + + return builder.getTypeFromLength( this.components.length, this.getComponentType( builder ) ); + + } + + generate( builder, output ) { + + const node = this.node; + const nodeTypeLength = builder.getTypeLength( node.getNodeType( builder ) ); + + let snippet = null; + + if ( nodeTypeLength > 1 ) { + + let type = null; + + const componentsLength = this.getVectorLength(); + + if ( componentsLength >= nodeTypeLength ) { + + // needed expand the input node + + type = builder.getTypeFromLength( this.getVectorLength(), this.getComponentType( builder ) ); + + } + + const nodeSnippet = node.build( builder, type ); + + if ( this.components.length === nodeTypeLength && this.components === stringVectorComponents.slice( 0, this.components.length ) ) { + + // unnecessary swizzle + + snippet = builder.format( nodeSnippet, type, output ); + + } else { + + snippet = builder.format( `${nodeSnippet}.${this.components}`, this.getNodeType( builder ), output ); + + } + + } else { + + // ignore .components if .node returns float/integer + + snippet = node.build( builder, output ); + + } + + return snippet; + + } + + serialize( data ) { + + super.serialize( data ); + + data.components = this.components; + + } + + deserialize( data ) { + + super.deserialize( data ); + + this.components = data.components; + + } + +} + +class SetNode extends TempNode { + + static get type() { + + return 'SetNode'; + + } + + constructor( sourceNode, components, targetNode ) { + + super(); + + this.sourceNode = sourceNode; + this.components = components; + this.targetNode = targetNode; + + } + + getNodeType( builder ) { + + return this.sourceNode.getNodeType( builder ); + + } + + generate( builder ) { + + const { sourceNode, components, targetNode } = this; + + const sourceType = this.getNodeType( builder ); + const targetType = builder.getTypeFromLength( components.length, targetNode.getNodeType( builder ) ); + + const targetSnippet = targetNode.build( builder, targetType ); + const sourceSnippet = sourceNode.build( builder, sourceType ); + + const length = builder.getTypeLength( sourceType ); + const snippetValues = []; + + for ( let i = 0; i < length; i ++ ) { + + const component = vectorComponents[ i ]; + + if ( component === components[ 0 ] ) { + + snippetValues.push( targetSnippet ); + + i += components.length - 1; + + } else { + + snippetValues.push( sourceSnippet + '.' + component ); + + } + + } + + return `${ builder.getType( sourceType ) }( ${ snippetValues.join( ', ' ) } )`; + + } + +} + +class FlipNode extends TempNode { + + static get type() { + + return 'FlipNode'; + + } + + constructor( sourceNode, components ) { + + super(); + + this.sourceNode = sourceNode; + this.components = components; + + } + + getNodeType( builder ) { + + return this.sourceNode.getNodeType( builder ); + + } + + generate( builder ) { + + const { components, sourceNode } = this; + + const sourceType = this.getNodeType( builder ); + const sourceSnippet = sourceNode.build( builder ); + + const sourceCache = builder.getVarFromNode( this ); + const sourceProperty = builder.getPropertyName( sourceCache ); + + builder.addLineFlowCode( sourceProperty + ' = ' + sourceSnippet, this ); + + const length = builder.getTypeLength( sourceType ); + const snippetValues = []; + + let componentIndex = 0; + + for ( let i = 0; i < length; i ++ ) { + + const component = vectorComponents[ i ]; + + if ( component === components[ componentIndex ] ) { + + snippetValues.push( '1.0 - ' + ( sourceProperty + '.' + component ) ); + + componentIndex ++; + + } else { + + snippetValues.push( sourceProperty + '.' + component ); + + } + + } + + return `${ builder.getType( sourceType ) }( ${ snippetValues.join( ', ' ) } )`; + + } + +} + +class InputNode extends Node { + + static get type() { + + return 'InputNode'; + + } + + constructor( value, nodeType = null ) { + + super( nodeType ); + + this.isInputNode = true; + + this.value = value; + this.precision = null; + + } + + getNodeType( /*builder*/ ) { + + if ( this.nodeType === null ) { + + return getValueType( this.value ); + + } + + return this.nodeType; + + } + + getInputType( builder ) { + + return this.getNodeType( builder ); + + } + + setPrecision( precision ) { + + this.precision = precision; + + return this; + + } + + serialize( data ) { + + super.serialize( data ); + + data.value = this.value; + + if ( this.value && this.value.toArray ) data.value = this.value.toArray(); + + data.valueType = getValueType( this.value ); + data.nodeType = this.nodeType; + + if ( data.valueType === 'ArrayBuffer' ) data.value = arrayBufferToBase64( data.value ); + + data.precision = this.precision; + + } + + deserialize( data ) { + + super.deserialize( data ); + + this.nodeType = data.nodeType; + this.value = Array.isArray( data.value ) ? getValueFromType( data.valueType, ...data.value ) : data.value; + + this.precision = data.precision || null; + + if ( this.value && this.value.fromArray ) this.value = this.value.fromArray( data.value ); + + } + + generate( /*builder, output*/ ) { + + console.warn( 'Abstract function.' ); + + } + +} + +class ConstNode extends InputNode { + + static get type() { + + return 'ConstNode'; + + } + + constructor( value, nodeType = null ) { + + super( value, nodeType ); + + this.isConstNode = true; + + } + + generateConst( builder ) { + + return builder.generateConst( this.getNodeType( builder ), this.value ); + + } + + generate( builder, output ) { + + const type = this.getNodeType( builder ); + + return builder.format( this.generateConst( builder ), type, output ); + + } + +} + +// + +let currentStack = null; + +const NodeElements = new Map(); + +function addMethodChaining( name, nodeElement ) { + + if ( NodeElements.has( name ) ) { + + console.warn( `Redefinition of method chaining ${ name }` ); + return; + + } + + if ( typeof nodeElement !== 'function' ) throw new Error( `Node element ${ name } is not a function` ); + + NodeElements.set( name, nodeElement ); + +} + +const parseSwizzle = ( props ) => props.replace( /r|s/g, 'x' ).replace( /g|t/g, 'y' ).replace( /b|p/g, 'z' ).replace( /a|q/g, 'w' ); +const parseSwizzleAndSort = ( props ) => parseSwizzle( props ).split( '' ).sort().join( '' ); + +const shaderNodeHandler = { + + setup( NodeClosure, params ) { + + const inputs = params.shift(); + + return NodeClosure( nodeObjects( inputs ), ...params ); + + }, + + get( node, prop, nodeObj ) { + + if ( typeof prop === 'string' && node[ prop ] === undefined ) { + + if ( node.isStackNode !== true && prop === 'assign' ) { + + return ( ...params ) => { + + currentStack.assign( nodeObj, ...params ); + + return nodeObj; + + }; + + } else if ( NodeElements.has( prop ) ) { + + const nodeElement = NodeElements.get( prop ); + + return node.isStackNode ? ( ...params ) => nodeObj.add( nodeElement( ...params ) ) : ( ...params ) => nodeElement( nodeObj, ...params ); + + } else if ( prop === 'self' ) { + + return node; + + } else if ( prop.endsWith( 'Assign' ) && NodeElements.has( prop.slice( 0, prop.length - 'Assign'.length ) ) ) { + + const nodeElement = NodeElements.get( prop.slice( 0, prop.length - 'Assign'.length ) ); + + return node.isStackNode ? ( ...params ) => nodeObj.assign( params[ 0 ], nodeElement( ...params ) ) : ( ...params ) => nodeObj.assign( nodeElement( nodeObj, ...params ) ); + + } else if ( /^[xyzwrgbastpq]{1,4}$/.test( prop ) === true ) { + + // accessing properties ( swizzle ) + + prop = parseSwizzle( prop ); + + return nodeObject( new SplitNode( nodeObj, prop ) ); + + } else if ( /^set[XYZWRGBASTPQ]{1,4}$/.test( prop ) === true ) { + + // set properties ( swizzle ) and sort to xyzw sequence + + prop = parseSwizzleAndSort( prop.slice( 3 ).toLowerCase() ); + + return ( value ) => nodeObject( new SetNode( node, prop, value ) ); + + } else if ( /^flip[XYZWRGBASTPQ]{1,4}$/.test( prop ) === true ) { + + // set properties ( swizzle ) and sort to xyzw sequence + + prop = parseSwizzleAndSort( prop.slice( 4 ).toLowerCase() ); + + return () => nodeObject( new FlipNode( nodeObject( node ), prop ) ); + + } else if ( prop === 'width' || prop === 'height' || prop === 'depth' ) { + + // accessing property + + if ( prop === 'width' ) prop = 'x'; + else if ( prop === 'height' ) prop = 'y'; + else if ( prop === 'depth' ) prop = 'z'; + + return nodeObject( new SplitNode( node, prop ) ); + + } else if ( /^\d+$/.test( prop ) === true ) { + + // accessing array + + return nodeObject( new ArrayElementNode( nodeObj, new ConstNode( Number( prop ), 'uint' ) ) ); + + } + + } + + return Reflect.get( node, prop, nodeObj ); + + }, + + set( node, prop, value, nodeObj ) { + + if ( typeof prop === 'string' && node[ prop ] === undefined ) { + + // setting properties + + if ( /^[xyzwrgbastpq]{1,4}$/.test( prop ) === true || prop === 'width' || prop === 'height' || prop === 'depth' || /^\d+$/.test( prop ) === true ) { + + nodeObj[ prop ].assign( value ); + + return true; + + } + + } + + return Reflect.set( node, prop, value, nodeObj ); + + } + +}; + +const nodeObjectsCacheMap = new WeakMap(); +const nodeBuilderFunctionsCacheMap = new WeakMap(); + +const ShaderNodeObject = function ( obj, altType = null ) { + + const type = getValueType( obj ); + + if ( type === 'node' ) { + + let nodeObject = nodeObjectsCacheMap.get( obj ); + + if ( nodeObject === undefined ) { + + nodeObject = new Proxy( obj, shaderNodeHandler ); + + nodeObjectsCacheMap.set( obj, nodeObject ); + nodeObjectsCacheMap.set( nodeObject, nodeObject ); + + } + + return nodeObject; + + } else if ( ( altType === null && ( type === 'float' || type === 'boolean' ) ) || ( type && type !== 'shader' && type !== 'string' ) ) { + + return nodeObject( getConstNode( obj, altType ) ); + + } else if ( type === 'shader' ) { + + return Fn( obj ); + + } + + return obj; + +}; + +const ShaderNodeObjects = function ( objects, altType = null ) { + + for ( const name in objects ) { + + objects[ name ] = nodeObject( objects[ name ], altType ); + + } + + return objects; + +}; + +const ShaderNodeArray = function ( array, altType = null ) { + + const len = array.length; + + for ( let i = 0; i < len; i ++ ) { + + array[ i ] = nodeObject( array[ i ], altType ); + + } + + return array; + +}; + +const ShaderNodeProxy = function ( NodeClass, scope = null, factor = null, settings = null ) { + + const assignNode = ( node ) => nodeObject( settings !== null ? Object.assign( node, settings ) : node ); + + if ( scope === null ) { + + return ( ...params ) => { + + return assignNode( new NodeClass( ...nodeArray( params ) ) ); + + }; + + } else if ( factor !== null ) { + + factor = nodeObject( factor ); + + return ( ...params ) => { + + return assignNode( new NodeClass( scope, ...nodeArray( params ), factor ) ); + + }; + + } else { + + return ( ...params ) => { + + return assignNode( new NodeClass( scope, ...nodeArray( params ) ) ); + + }; + + } + +}; + +const ShaderNodeImmutable = function ( NodeClass, ...params ) { + + return nodeObject( new NodeClass( ...nodeArray( params ) ) ); + +}; + +class ShaderCallNodeInternal extends Node { + + constructor( shaderNode, inputNodes ) { + + super(); + + this.shaderNode = shaderNode; + this.inputNodes = inputNodes; + + } + + getNodeType( builder ) { + + return this.shaderNode.nodeType || this.getOutputNode( builder ).getNodeType( builder ); + + } + + call( builder ) { + + const { shaderNode, inputNodes } = this; + + const properties = builder.getNodeProperties( shaderNode ); + if ( properties.onceOutput ) return properties.onceOutput; + + // + + let result = null; + + if ( shaderNode.layout ) { + + let functionNodesCacheMap = nodeBuilderFunctionsCacheMap.get( builder.constructor ); + + if ( functionNodesCacheMap === undefined ) { + + functionNodesCacheMap = new WeakMap(); + + nodeBuilderFunctionsCacheMap.set( builder.constructor, functionNodesCacheMap ); + + } + + let functionNode = functionNodesCacheMap.get( shaderNode ); + + if ( functionNode === undefined ) { + + functionNode = nodeObject( builder.buildFunctionNode( shaderNode ) ); + + functionNodesCacheMap.set( shaderNode, functionNode ); + + } + + if ( builder.currentFunctionNode !== null ) { + + builder.currentFunctionNode.includes.push( functionNode ); + + } + + result = nodeObject( functionNode.call( inputNodes ) ); + + } else { + + const jsFunc = shaderNode.jsFunc; + const outputNode = inputNodes !== null ? jsFunc( inputNodes, builder ) : jsFunc( builder ); + + result = nodeObject( outputNode ); + + } + + if ( shaderNode.once ) { + + properties.onceOutput = result; + + } + + return result; + + } + + getOutputNode( builder ) { + + const properties = builder.getNodeProperties( this ); + + if ( properties.outputNode === null ) { + + properties.outputNode = this.setupOutput( builder ); + + } + + return properties.outputNode; + + } + + setup( builder ) { + + return this.getOutputNode( builder ); + + } + + setupOutput( builder ) { + + builder.addStack(); + + builder.stack.outputNode = this.call( builder ); + + return builder.removeStack(); + + } + + generate( builder, output ) { + + const outputNode = this.getOutputNode( builder ); + + return outputNode.build( builder, output ); + + } + +} + +class ShaderNodeInternal extends Node { + + constructor( jsFunc, nodeType ) { + + super( nodeType ); + + this.jsFunc = jsFunc; + this.layout = null; + + this.global = true; + + this.once = false; + + } + + setLayout( layout ) { + + this.layout = layout; + + return this; + + } + + call( inputs = null ) { + + nodeObjects( inputs ); + + return nodeObject( new ShaderCallNodeInternal( this, inputs ) ); + + } + + setup() { + + return this.call(); + + } + +} + +const bools = [ false, true ]; +const uints = [ 0, 1, 2, 3 ]; +const ints = [ - 1, - 2 ]; +const floats = [ 0.5, 1.5, 1 / 3, 1e-6, 1e6, Math.PI, Math.PI * 2, 1 / Math.PI, 2 / Math.PI, 1 / ( Math.PI * 2 ), Math.PI / 2 ]; + +const boolsCacheMap = new Map(); +for ( const bool of bools ) boolsCacheMap.set( bool, new ConstNode( bool ) ); + +const uintsCacheMap = new Map(); +for ( const uint of uints ) uintsCacheMap.set( uint, new ConstNode( uint, 'uint' ) ); + +const intsCacheMap = new Map( [ ...uintsCacheMap ].map( el => new ConstNode( el.value, 'int' ) ) ); +for ( const int of ints ) intsCacheMap.set( int, new ConstNode( int, 'int' ) ); + +const floatsCacheMap = new Map( [ ...intsCacheMap ].map( el => new ConstNode( el.value ) ) ); +for ( const float of floats ) floatsCacheMap.set( float, new ConstNode( float ) ); +for ( const float of floats ) floatsCacheMap.set( - float, new ConstNode( - float ) ); + +const cacheMaps = { bool: boolsCacheMap, uint: uintsCacheMap, ints: intsCacheMap, float: floatsCacheMap }; + +const constNodesCacheMap = new Map( [ ...boolsCacheMap, ...floatsCacheMap ] ); + +const getConstNode = ( value, type ) => { + + if ( constNodesCacheMap.has( value ) ) { + + return constNodesCacheMap.get( value ); + + } else if ( value.isNode === true ) { + + return value; + + } else { + + return new ConstNode( value, type ); + + } + +}; + +const safeGetNodeType = ( node ) => { + + try { + + return node.getNodeType(); + + } catch ( _ ) { + + return undefined; + + } + +}; + +const ConvertType = function ( type, cacheMap = null ) { + + return ( ...params ) => { + + if ( params.length === 0 || ( ! [ 'bool', 'float', 'int', 'uint' ].includes( type ) && params.every( param => typeof param !== 'object' ) ) ) { + + params = [ getValueFromType( type, ...params ) ]; + + } + + if ( params.length === 1 && cacheMap !== null && cacheMap.has( params[ 0 ] ) ) { + + return nodeObject( cacheMap.get( params[ 0 ] ) ); + + } + + if ( params.length === 1 ) { + + const node = getConstNode( params[ 0 ], type ); + if ( safeGetNodeType( node ) === type ) return nodeObject( node ); + return nodeObject( new ConvertNode( node, type ) ); + + } + + const nodes = params.map( param => getConstNode( param ) ); + return nodeObject( new JoinNode( nodes, type ) ); + + }; + +}; + +// exports + +const defined = ( v ) => typeof v === 'object' && v !== null ? v.value : v; // TODO: remove boolean conversion and defined function + +// utils + +const getConstNodeType = ( value ) => ( value !== undefined && value !== null ) ? ( value.nodeType || value.convertTo || ( typeof value === 'string' ? value : null ) ) : null; + +// shader node base + +function ShaderNode( jsFunc, nodeType ) { + + return new Proxy( new ShaderNodeInternal( jsFunc, nodeType ), shaderNodeHandler ); + +} + +const nodeObject = ( val, altType = null ) => /* new */ ShaderNodeObject( val, altType ); +const nodeObjects = ( val, altType = null ) => new ShaderNodeObjects( val, altType ); +const nodeArray = ( val, altType = null ) => new ShaderNodeArray( val, altType ); +const nodeProxy = ( ...params ) => new ShaderNodeProxy( ...params ); +const nodeImmutable = ( ...params ) => new ShaderNodeImmutable( ...params ); + +const Fn = ( jsFunc, nodeType ) => { + + const shaderNode = new ShaderNode( jsFunc, nodeType ); + + const fn = ( ...params ) => { + + let inputs; + + nodeObjects( params ); + + if ( params[ 0 ] && params[ 0 ].isNode ) { + + inputs = [ ...params ]; + + } else { + + inputs = params[ 0 ]; + + } + + return shaderNode.call( inputs ); + + }; + + fn.shaderNode = shaderNode; + + fn.setLayout = ( layout ) => { + + shaderNode.setLayout( layout ); + + return fn; + + }; + + fn.once = () => { + + shaderNode.once = true; + + return fn; + + }; + + return fn; + +}; + +const tslFn = ( ...params ) => { // @deprecated, r168 + + console.warn( 'TSL.ShaderNode: tslFn() has been renamed to Fn().' ); + return Fn( ...params ); + +}; + +// + +addMethodChaining( 'toGlobal', ( node ) => { + + node.global = true; + + return node; + +} ); + +// + +const setCurrentStack = ( stack ) => { + + currentStack = stack; + +}; + +const getCurrentStack = () => currentStack; + +const If = ( ...params ) => currentStack.If( ...params ); + +function append( node ) { + + if ( currentStack ) currentStack.add( node ); + + return node; + +} + +addMethodChaining( 'append', append ); + +// types + +const color = new ConvertType( 'color' ); + +const float = new ConvertType( 'float', cacheMaps.float ); +const int = new ConvertType( 'int', cacheMaps.ints ); +const uint = new ConvertType( 'uint', cacheMaps.uint ); +const bool = new ConvertType( 'bool', cacheMaps.bool ); + +const vec2 = new ConvertType( 'vec2' ); +const ivec2 = new ConvertType( 'ivec2' ); +const uvec2 = new ConvertType( 'uvec2' ); +const bvec2 = new ConvertType( 'bvec2' ); + +const vec3 = new ConvertType( 'vec3' ); +const ivec3 = new ConvertType( 'ivec3' ); +const uvec3 = new ConvertType( 'uvec3' ); +const bvec3 = new ConvertType( 'bvec3' ); + +const vec4 = new ConvertType( 'vec4' ); +const ivec4 = new ConvertType( 'ivec4' ); +const uvec4 = new ConvertType( 'uvec4' ); +const bvec4 = new ConvertType( 'bvec4' ); + +const mat2 = new ConvertType( 'mat2' ); +const mat3 = new ConvertType( 'mat3' ); +const mat4 = new ConvertType( 'mat4' ); + +const string = ( value = '' ) => nodeObject( new ConstNode( value, 'string' ) ); +const arrayBuffer = ( value ) => nodeObject( new ConstNode( value, 'ArrayBuffer' ) ); + +addMethodChaining( 'toColor', color ); +addMethodChaining( 'toFloat', float ); +addMethodChaining( 'toInt', int ); +addMethodChaining( 'toUint', uint ); +addMethodChaining( 'toBool', bool ); +addMethodChaining( 'toVec2', vec2 ); +addMethodChaining( 'toIVec2', ivec2 ); +addMethodChaining( 'toUVec2', uvec2 ); +addMethodChaining( 'toBVec2', bvec2 ); +addMethodChaining( 'toVec3', vec3 ); +addMethodChaining( 'toIVec3', ivec3 ); +addMethodChaining( 'toUVec3', uvec3 ); +addMethodChaining( 'toBVec3', bvec3 ); +addMethodChaining( 'toVec4', vec4 ); +addMethodChaining( 'toIVec4', ivec4 ); +addMethodChaining( 'toUVec4', uvec4 ); +addMethodChaining( 'toBVec4', bvec4 ); +addMethodChaining( 'toMat2', mat2 ); +addMethodChaining( 'toMat3', mat3 ); +addMethodChaining( 'toMat4', mat4 ); + +// basic nodes + +const element = /*@__PURE__*/ nodeProxy( ArrayElementNode ); +const convert = ( node, types ) => nodeObject( new ConvertNode( nodeObject( node ), types ) ); +const split = ( node, channels ) => nodeObject( new SplitNode( nodeObject( node ), channels ) ); + +addMethodChaining( 'element', element ); +addMethodChaining( 'convert', convert ); + +class UniformGroupNode extends Node { + + static get type() { + + return 'UniformGroupNode'; + + } + + constructor( name, shared = false, order = 1 ) { + + super( 'string' ); + + this.name = name; + this.version = 0; + + this.shared = shared; + this.order = order; + this.isUniformGroup = true; + + } + + set needsUpdate( value ) { + + if ( value === true ) this.version ++; + + } + + serialize( data ) { + + super.serialize( data ); + + data.name = this.name; + data.version = this.version; + data.shared = this.shared; + + } + + deserialize( data ) { + + super.deserialize( data ); + + this.name = data.name; + this.version = data.version; + this.shared = data.shared; + + } + +} + +const uniformGroup = ( name ) => new UniformGroupNode( name ); +const sharedUniformGroup = ( name, order = 0 ) => new UniformGroupNode( name, true, order ); + +const frameGroup = /*@__PURE__*/ sharedUniformGroup( 'frame' ); +const renderGroup = /*@__PURE__*/ sharedUniformGroup( 'render' ); +const objectGroup = /*@__PURE__*/ uniformGroup( 'object' ); + +class UniformNode extends InputNode { + + static get type() { + + return 'UniformNode'; + + } + + constructor( value, nodeType = null ) { + + super( value, nodeType ); + + this.isUniformNode = true; + + this.name = ''; + this.groupNode = objectGroup; + + } + + label( name ) { + + this.name = name; + + return this; + + } + + setGroup( group ) { + + this.groupNode = group; + + return this; + + } + + getGroup() { + + return this.groupNode; + + } + + getUniformHash( builder ) { + + return this.getHash( builder ); + + } + + onUpdate( callback, updateType ) { + + const self = this.getSelf(); + + callback = callback.bind( self ); + + return super.onUpdate( ( frame ) => { + + const value = callback( frame, self ); + + if ( value !== undefined ) { + + this.value = value; + + } + + }, updateType ); + + } + + generate( builder, output ) { + + const type = this.getNodeType( builder ); + + const hash = this.getUniformHash( builder ); + + let sharedNode = builder.getNodeFromHash( hash ); + + if ( sharedNode === undefined ) { + + builder.setHashNode( this, hash ); + + sharedNode = this; + + } + + const sharedNodeType = sharedNode.getInputType( builder ); + + const nodeUniform = builder.getUniformFromNode( sharedNode, sharedNodeType, builder.shaderStage, this.name || builder.context.label ); + const propertyName = builder.getPropertyName( nodeUniform ); + + if ( builder.context.label !== undefined ) delete builder.context.label; + + return builder.format( propertyName, type, output ); + + } + +} + +const uniform = ( arg1, arg2 ) => { + + const nodeType = getConstNodeType( arg2 || arg1 ); + + // @TODO: get ConstNode from .traverse() in the future + const value = ( arg1 && arg1.isNode === true ) ? ( arg1.node && arg1.node.value ) || arg1.value : arg1; + + return nodeObject( new UniformNode( value, nodeType ) ); + +}; + +class PropertyNode extends Node { + + static get type() { + + return 'PropertyNode'; + + } + + constructor( nodeType, name = null, varying = false ) { + + super( nodeType ); + + this.name = name; + this.varying = varying; + + this.isPropertyNode = true; + + } + + getHash( builder ) { + + return this.name || super.getHash( builder ); + + } + + isGlobal( /*builder*/ ) { + + return true; + + } + + generate( builder ) { + + let nodeVar; + + if ( this.varying === true ) { + + nodeVar = builder.getVaryingFromNode( this, this.name ); + nodeVar.needsInterpolation = true; + + } else { + + nodeVar = builder.getVarFromNode( this, this.name ); + + } + + return builder.getPropertyName( nodeVar ); + + } + +} + +const property = ( type, name ) => nodeObject( new PropertyNode( type, name ) ); +const varyingProperty = ( type, name ) => nodeObject( new PropertyNode( type, name, true ) ); + +const diffuseColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec4', 'DiffuseColor' ); +const emissive = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'EmissiveColor' ); +const roughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Roughness' ); +const metalness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Metalness' ); +const clearcoat = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Clearcoat' ); +const clearcoatRoughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'ClearcoatRoughness' ); +const sheen = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'Sheen' ); +const sheenRoughness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'SheenRoughness' ); +const iridescence = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Iridescence' ); +const iridescenceIOR = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IridescenceIOR' ); +const iridescenceThickness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IridescenceThickness' ); +const alphaT = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'AlphaT' ); +const anisotropy = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Anisotropy' ); +const anisotropyT = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'AnisotropyT' ); +const anisotropyB = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec3', 'AnisotropyB' ); +const specularColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'color', 'SpecularColor' ); +const specularF90 = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'SpecularF90' ); +const shininess = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Shininess' ); +const output = /*@__PURE__*/ nodeImmutable( PropertyNode, 'vec4', 'Output' ); +const dashSize = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'dashSize' ); +const gapSize = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'gapSize' ); +const pointWidth = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'pointWidth' ); +const ior = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'IOR' ); +const transmission = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Transmission' ); +const thickness = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Thickness' ); +const attenuationDistance = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'AttenuationDistance' ); +const attenuationColor = /*@__PURE__*/ nodeImmutable( PropertyNode, 'color', 'AttenuationColor' ); +const dispersion = /*@__PURE__*/ nodeImmutable( PropertyNode, 'float', 'Dispersion' ); + +class AssignNode extends TempNode { + + static get type() { + + return 'AssignNode'; + + } + + constructor( targetNode, sourceNode ) { + + super(); + + this.targetNode = targetNode; + this.sourceNode = sourceNode; + + } + + hasDependencies() { + + return false; + + } + + getNodeType( builder, output ) { + + return output !== 'void' ? this.targetNode.getNodeType( builder ) : 'void'; + + } + + needsSplitAssign( builder ) { + + const { targetNode } = this; + + if ( builder.isAvailable( 'swizzleAssign' ) === false && targetNode.isSplitNode && targetNode.components.length > 1 ) { + + const targetLength = builder.getTypeLength( targetNode.node.getNodeType( builder ) ); + const assignDiferentVector = vectorComponents.join( '' ).slice( 0, targetLength ) !== targetNode.components; + + return assignDiferentVector; + + } + + return false; + + } + + generate( builder, output ) { + + const { targetNode, sourceNode } = this; + + const needsSplitAssign = this.needsSplitAssign( builder ); + + const targetType = targetNode.getNodeType( builder ); + + const target = targetNode.context( { assign: true } ).build( builder ); + const source = sourceNode.build( builder, targetType ); + + const sourceType = sourceNode.getNodeType( builder ); + + const nodeData = builder.getDataFromNode( this ); + + // + + let snippet; + + if ( nodeData.initialized === true ) { + + if ( output !== 'void' ) { + + snippet = target; + + } + + } else if ( needsSplitAssign ) { + + const sourceVar = builder.getVarFromNode( this, null, targetType ); + const sourceProperty = builder.getPropertyName( sourceVar ); + + builder.addLineFlowCode( `${ sourceProperty } = ${ source }`, this ); + + const targetRoot = targetNode.node.context( { assign: true } ).build( builder ); + + for ( let i = 0; i < targetNode.components.length; i ++ ) { + + const component = targetNode.components[ i ]; + + builder.addLineFlowCode( `${ targetRoot }.${ component } = ${ sourceProperty }[ ${ i } ]`, this ); + + } + + if ( output !== 'void' ) { + + snippet = target; + + } + + } else { + + snippet = `${ target } = ${ source }`; + + if ( output === 'void' || sourceType === 'void' ) { + + builder.addLineFlowCode( snippet, this ); + + if ( output !== 'void' ) { + + snippet = target; + + } + + } + + } + + nodeData.initialized = true; + + return builder.format( snippet, targetType, output ); + + } + +} + +const assign = /*@__PURE__*/ nodeProxy( AssignNode ); + +addMethodChaining( 'assign', assign ); + +class FunctionCallNode extends TempNode { + + static get type() { + + return 'FunctionCallNode'; + + } + + constructor( functionNode = null, parameters = {} ) { + + super(); + + this.functionNode = functionNode; + this.parameters = parameters; + + } + + setParameters( parameters ) { + + this.parameters = parameters; + + return this; + + } + + getParameters() { + + return this.parameters; + + } + + getNodeType( builder ) { + + return this.functionNode.getNodeType( builder ); + + } + + generate( builder ) { + + const params = []; + + const functionNode = this.functionNode; + + const inputs = functionNode.getInputs( builder ); + const parameters = this.parameters; + + if ( Array.isArray( parameters ) ) { + + for ( let i = 0; i < parameters.length; i ++ ) { + + const inputNode = inputs[ i ]; + const node = parameters[ i ]; + + params.push( node.build( builder, inputNode.type ) ); + + } + + } else { + + for ( const inputNode of inputs ) { + + const node = parameters[ inputNode.name ]; + + if ( node !== undefined ) { + + params.push( node.build( builder, inputNode.type ) ); + + } else { + + throw new Error( `FunctionCallNode: Input '${inputNode.name}' not found in FunctionNode.` ); + + } + + } + + } + + const functionName = functionNode.build( builder, 'property' ); + + return `${functionName}( ${params.join( ', ' )} )`; + + } + +} + +const call = ( func, ...params ) => { + + params = params.length > 1 || ( params[ 0 ] && params[ 0 ].isNode === true ) ? nodeArray( params ) : nodeObjects( params[ 0 ] ); + + return nodeObject( new FunctionCallNode( nodeObject( func ), params ) ); + +}; + +addMethodChaining( 'call', call ); + +class OperatorNode extends TempNode { + + static get type() { + + return 'OperatorNode'; + + } + + constructor( op, aNode, bNode, ...params ) { + + super(); + + if ( params.length > 0 ) { + + let finalOp = new OperatorNode( op, aNode, bNode ); + + for ( let i = 0; i < params.length - 1; i ++ ) { + + finalOp = new OperatorNode( op, finalOp, params[ i ] ); + + } + + aNode = finalOp; + bNode = params[ params.length - 1 ]; + + } + + this.op = op; + this.aNode = aNode; + this.bNode = bNode; + + } + + getNodeType( builder, output ) { + + const op = this.op; + + const aNode = this.aNode; + const bNode = this.bNode; + + const typeA = aNode.getNodeType( builder ); + const typeB = typeof bNode !== 'undefined' ? bNode.getNodeType( builder ) : null; + + if ( typeA === 'void' || typeB === 'void' ) { + + return 'void'; + + } else if ( op === '%' ) { + + return typeA; + + } else if ( op === '~' || op === '&' || op === '|' || op === '^' || op === '>>' || op === '<<' ) { + + return builder.getIntegerType( typeA ); + + } else if ( op === '!' || op === '==' || op === '&&' || op === '||' || op === '^^' ) { + + return 'bool'; + + } else if ( op === '<' || op === '>' || op === '<=' || op === '>=' ) { + + const typeLength = output ? builder.getTypeLength( output ) : Math.max( builder.getTypeLength( typeA ), builder.getTypeLength( typeB ) ); + + return typeLength > 1 ? `bvec${ typeLength }` : 'bool'; + + } else { + + if ( typeA === 'float' && builder.isMatrix( typeB ) ) { + + return typeB; + + } else if ( builder.isMatrix( typeA ) && builder.isVector( typeB ) ) { + + // matrix x vector + + return builder.getVectorFromMatrix( typeA ); + + } else if ( builder.isVector( typeA ) && builder.isMatrix( typeB ) ) { + + // vector x matrix + + return builder.getVectorFromMatrix( typeB ); + + } else if ( builder.getTypeLength( typeB ) > builder.getTypeLength( typeA ) ) { + + // anytype x anytype: use the greater length vector + + return typeB; + + } + + return typeA; + + } + + } + + generate( builder, output ) { + + const op = this.op; + + const aNode = this.aNode; + const bNode = this.bNode; + + const type = this.getNodeType( builder, output ); + + let typeA = null; + let typeB = null; + + if ( type !== 'void' ) { + + typeA = aNode.getNodeType( builder ); + typeB = typeof bNode !== 'undefined' ? bNode.getNodeType( builder ) : null; + + if ( op === '<' || op === '>' || op === '<=' || op === '>=' || op === '==' ) { + + if ( builder.isVector( typeA ) ) { + + typeB = typeA; + + } else if ( typeA !== typeB ) { + + typeA = typeB = 'float'; + + } + + } else if ( op === '>>' || op === '<<' ) { + + typeA = type; + typeB = builder.changeComponentType( typeB, 'uint' ); + + } else if ( builder.isMatrix( typeA ) && builder.isVector( typeB ) ) { + + // matrix x vector + + typeB = builder.getVectorFromMatrix( typeA ); + + } else if ( builder.isVector( typeA ) && builder.isMatrix( typeB ) ) { + + // vector x matrix + + typeA = builder.getVectorFromMatrix( typeB ); + + } else { + + // anytype x anytype + + typeA = typeB = type; + + } + + } else { + + typeA = typeB = type; + + } + + const a = aNode.build( builder, typeA ); + const b = typeof bNode !== 'undefined' ? bNode.build( builder, typeB ) : null; + + const outputLength = builder.getTypeLength( output ); + const fnOpSnippet = builder.getFunctionOperator( op ); + + if ( output !== 'void' ) { + + if ( op === '<' && outputLength > 1 ) { + + if ( builder.useComparisonMethod ) { + + return builder.format( `${ builder.getMethod( 'lessThan', output ) }( ${ a }, ${ b } )`, type, output ); + + } else { + + return builder.format( `( ${ a } < ${ b } )`, type, output ); + + } + + } else if ( op === '<=' && outputLength > 1 ) { + + if ( builder.useComparisonMethod ) { + + return builder.format( `${ builder.getMethod( 'lessThanEqual', output ) }( ${ a }, ${ b } )`, type, output ); + + } else { + + return builder.format( `( ${ a } <= ${ b } )`, type, output ); + + } + + } else if ( op === '>' && outputLength > 1 ) { + + if ( builder.useComparisonMethod ) { + + return builder.format( `${ builder.getMethod( 'greaterThan', output ) }( ${ a }, ${ b } )`, type, output ); + + } else { + + return builder.format( `( ${ a } > ${ b } )`, type, output ); + + } + + } else if ( op === '>=' && outputLength > 1 ) { + + if ( builder.useComparisonMethod ) { + + return builder.format( `${ builder.getMethod( 'greaterThanEqual', output ) }( ${ a }, ${ b } )`, type, output ); + + } else { + + return builder.format( `( ${ a } >= ${ b } )`, type, output ); + + } + + } else if ( op === '!' || op === '~' ) { + + return builder.format( `(${op}${a})`, typeA, output ); + + } else if ( fnOpSnippet ) { + + return builder.format( `${ fnOpSnippet }( ${ a }, ${ b } )`, type, output ); + + } else { + + return builder.format( `( ${ a } ${ op } ${ b } )`, type, output ); + + } + + } else if ( typeA !== 'void' ) { + + if ( fnOpSnippet ) { + + return builder.format( `${ fnOpSnippet }( ${ a }, ${ b } )`, type, output ); + + } else { + + return builder.format( `${ a } ${ op } ${ b }`, type, output ); + + } + + } + + } + + serialize( data ) { + + super.serialize( data ); + + data.op = this.op; + + } + + deserialize( data ) { + + super.deserialize( data ); + + this.op = data.op; + + } + +} + +const add = /*@__PURE__*/ nodeProxy( OperatorNode, '+' ); +const sub = /*@__PURE__*/ nodeProxy( OperatorNode, '-' ); +const mul = /*@__PURE__*/ nodeProxy( OperatorNode, '*' ); +const div = /*@__PURE__*/ nodeProxy( OperatorNode, '/' ); +const modInt = /*@__PURE__*/ nodeProxy( OperatorNode, '%' ); +const equal = /*@__PURE__*/ nodeProxy( OperatorNode, '==' ); +const notEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '!=' ); +const lessThan = /*@__PURE__*/ nodeProxy( OperatorNode, '<' ); +const greaterThan = /*@__PURE__*/ nodeProxy( OperatorNode, '>' ); +const lessThanEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '<=' ); +const greaterThanEqual = /*@__PURE__*/ nodeProxy( OperatorNode, '>=' ); +const and = /*@__PURE__*/ nodeProxy( OperatorNode, '&&' ); +const or = /*@__PURE__*/ nodeProxy( OperatorNode, '||' ); +const not = /*@__PURE__*/ nodeProxy( OperatorNode, '!' ); +const xor = /*@__PURE__*/ nodeProxy( OperatorNode, '^^' ); +const bitAnd = /*@__PURE__*/ nodeProxy( OperatorNode, '&' ); +const bitNot = /*@__PURE__*/ nodeProxy( OperatorNode, '~' ); +const bitOr = /*@__PURE__*/ nodeProxy( OperatorNode, '|' ); +const bitXor = /*@__PURE__*/ nodeProxy( OperatorNode, '^' ); +const shiftLeft = /*@__PURE__*/ nodeProxy( OperatorNode, '<<' ); +const shiftRight = /*@__PURE__*/ nodeProxy( OperatorNode, '>>' ); + +addMethodChaining( 'add', add ); +addMethodChaining( 'sub', sub ); +addMethodChaining( 'mul', mul ); +addMethodChaining( 'div', div ); +addMethodChaining( 'modInt', modInt ); +addMethodChaining( 'equal', equal ); +addMethodChaining( 'notEqual', notEqual ); +addMethodChaining( 'lessThan', lessThan ); +addMethodChaining( 'greaterThan', greaterThan ); +addMethodChaining( 'lessThanEqual', lessThanEqual ); +addMethodChaining( 'greaterThanEqual', greaterThanEqual ); +addMethodChaining( 'and', and ); +addMethodChaining( 'or', or ); +addMethodChaining( 'not', not ); +addMethodChaining( 'xor', xor ); +addMethodChaining( 'bitAnd', bitAnd ); +addMethodChaining( 'bitNot', bitNot ); +addMethodChaining( 'bitOr', bitOr ); +addMethodChaining( 'bitXor', bitXor ); +addMethodChaining( 'shiftLeft', shiftLeft ); +addMethodChaining( 'shiftRight', shiftRight ); + + +const remainder = ( ...params ) => { // @deprecated, r168 + + console.warn( 'TSL.OperatorNode: .remainder() has been renamed to .modInt().' ); + return modInt( ...params ); + +}; + +addMethodChaining( 'remainder', remainder ); + +class MathNode extends TempNode { + + static get type() { + + return 'MathNode'; + + } + + constructor( method, aNode, bNode = null, cNode = null ) { + + super(); + + this.method = method; + + this.aNode = aNode; + this.bNode = bNode; + this.cNode = cNode; + + } + + getInputType( builder ) { + + const aType = this.aNode.getNodeType( builder ); + const bType = this.bNode ? this.bNode.getNodeType( builder ) : null; + const cType = this.cNode ? this.cNode.getNodeType( builder ) : null; + + const aLen = builder.isMatrix( aType ) ? 0 : builder.getTypeLength( aType ); + const bLen = builder.isMatrix( bType ) ? 0 : builder.getTypeLength( bType ); + const cLen = builder.isMatrix( cType ) ? 0 : builder.getTypeLength( cType ); + + if ( aLen > bLen && aLen > cLen ) { + + return aType; + + } else if ( bLen > cLen ) { + + return bType; + + } else if ( cLen > aLen ) { + + return cType; + + } + + return aType; + + } + + getNodeType( builder ) { + + const method = this.method; + + if ( method === MathNode.LENGTH || method === MathNode.DISTANCE || method === MathNode.DOT ) { + + return 'float'; + + } else if ( method === MathNode.CROSS ) { + + return 'vec3'; + + } else if ( method === MathNode.ALL ) { + + return 'bool'; + + } else if ( method === MathNode.EQUALS ) { + + return builder.changeComponentType( this.aNode.getNodeType( builder ), 'bool' ); + + } else if ( method === MathNode.MOD ) { + + return this.aNode.getNodeType( builder ); + + } else { + + return this.getInputType( builder ); + + } + + } + + generate( builder, output ) { + + const method = this.method; + + const type = this.getNodeType( builder ); + const inputType = this.getInputType( builder ); + + const a = this.aNode; + const b = this.bNode; + const c = this.cNode; + + const isWebGL = builder.renderer.isWebGLRenderer === true; + + if ( method === MathNode.TRANSFORM_DIRECTION ) { + + // dir can be either a direction vector or a normal vector + // upper-left 3x3 of matrix is assumed to be orthogonal + + let tA = a; + let tB = b; + + if ( builder.isMatrix( tA.getNodeType( builder ) ) ) { + + tB = vec4( vec3( tB ), 0.0 ); + + } else { + + tA = vec4( vec3( tA ), 0.0 ); + + } + + const mulNode = mul( tA, tB ).xyz; + + return normalize( mulNode ).build( builder, output ); + + } else if ( method === MathNode.NEGATE ) { + + return builder.format( '( - ' + a.build( builder, inputType ) + ' )', type, output ); + + } else if ( method === MathNode.ONE_MINUS ) { + + return sub( 1.0, a ).build( builder, output ); + + } else if ( method === MathNode.RECIPROCAL ) { + + return div( 1.0, a ).build( builder, output ); + + } else if ( method === MathNode.DIFFERENCE ) { + + return abs( sub( a, b ) ).build( builder, output ); + + } else { + + const params = []; + + if ( method === MathNode.CROSS || method === MathNode.MOD ) { + + params.push( + a.build( builder, type ), + b.build( builder, type ) + ); + + } else if ( isWebGL && method === MathNode.STEP ) { + + params.push( + a.build( builder, builder.getTypeLength( a.getNodeType( builder ) ) === 1 ? 'float' : inputType ), + b.build( builder, inputType ) + ); + + } else if ( ( isWebGL && ( method === MathNode.MIN || method === MathNode.MAX ) ) || method === MathNode.MOD ) { + + params.push( + a.build( builder, inputType ), + b.build( builder, builder.getTypeLength( b.getNodeType( builder ) ) === 1 ? 'float' : inputType ) + ); + + } else if ( method === MathNode.REFRACT ) { + + params.push( + a.build( builder, inputType ), + b.build( builder, inputType ), + c.build( builder, 'float' ) + ); + + } else if ( method === MathNode.MIX ) { + + params.push( + a.build( builder, inputType ), + b.build( builder, inputType ), + c.build( builder, builder.getTypeLength( c.getNodeType( builder ) ) === 1 ? 'float' : inputType ) + ); + + } else { + + params.push( a.build( builder, inputType ) ); + if ( b !== null ) params.push( b.build( builder, inputType ) ); + if ( c !== null ) params.push( c.build( builder, inputType ) ); + + } + + return builder.format( `${ builder.getMethod( method, type ) }( ${params.join( ', ' )} )`, type, output ); + + } + + } + + serialize( data ) { + + super.serialize( data ); + + data.method = this.method; + + } + + deserialize( data ) { + + super.deserialize( data ); + + this.method = data.method; + + } + +} + +// 1 input + +MathNode.ALL = 'all'; +MathNode.ANY = 'any'; +MathNode.EQUALS = 'equals'; + +MathNode.RADIANS = 'radians'; +MathNode.DEGREES = 'degrees'; +MathNode.EXP = 'exp'; +MathNode.EXP2 = 'exp2'; +MathNode.LOG = 'log'; +MathNode.LOG2 = 'log2'; +MathNode.SQRT = 'sqrt'; +MathNode.INVERSE_SQRT = 'inversesqrt'; +MathNode.FLOOR = 'floor'; +MathNode.CEIL = 'ceil'; +MathNode.NORMALIZE = 'normalize'; +MathNode.FRACT = 'fract'; +MathNode.SIN = 'sin'; +MathNode.COS = 'cos'; +MathNode.TAN = 'tan'; +MathNode.ASIN = 'asin'; +MathNode.ACOS = 'acos'; +MathNode.ATAN = 'atan'; +MathNode.ABS = 'abs'; +MathNode.SIGN = 'sign'; +MathNode.LENGTH = 'length'; +MathNode.NEGATE = 'negate'; +MathNode.ONE_MINUS = 'oneMinus'; +MathNode.DFDX = 'dFdx'; +MathNode.DFDY = 'dFdy'; +MathNode.ROUND = 'round'; +MathNode.RECIPROCAL = 'reciprocal'; +MathNode.TRUNC = 'trunc'; +MathNode.FWIDTH = 'fwidth'; +MathNode.BITCAST = 'bitcast'; +MathNode.TRANSPOSE = 'transpose'; + +// 2 inputs + +MathNode.ATAN2 = 'atan2'; +MathNode.MIN = 'min'; +MathNode.MAX = 'max'; +MathNode.MOD = 'mod'; +MathNode.STEP = 'step'; +MathNode.REFLECT = 'reflect'; +MathNode.DISTANCE = 'distance'; +MathNode.DIFFERENCE = 'difference'; +MathNode.DOT = 'dot'; +MathNode.CROSS = 'cross'; +MathNode.POW = 'pow'; +MathNode.TRANSFORM_DIRECTION = 'transformDirection'; + +// 3 inputs + +MathNode.MIX = 'mix'; +MathNode.CLAMP = 'clamp'; +MathNode.REFRACT = 'refract'; +MathNode.SMOOTHSTEP = 'smoothstep'; +MathNode.FACEFORWARD = 'faceforward'; + +const EPSILON = /*@__PURE__*/ float( 1e-6 ); +const INFINITY = /*@__PURE__*/ float( 1e6 ); +const PI = /*@__PURE__*/ float( Math.PI ); +const PI2 = /*@__PURE__*/ float( Math.PI * 2 ); + +const all = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ALL ); +const any = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ANY ); +const equals = /*@__PURE__*/ nodeProxy( MathNode, MathNode.EQUALS ); + +const radians = /*@__PURE__*/ nodeProxy( MathNode, MathNode.RADIANS ); +const degrees = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DEGREES ); +const exp = /*@__PURE__*/ nodeProxy( MathNode, MathNode.EXP ); +const exp2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.EXP2 ); +const log = /*@__PURE__*/ nodeProxy( MathNode, MathNode.LOG ); +const log2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.LOG2 ); +const sqrt = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SQRT ); +const inverseSqrt = /*@__PURE__*/ nodeProxy( MathNode, MathNode.INVERSE_SQRT ); +const floor = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FLOOR ); +const ceil = /*@__PURE__*/ nodeProxy( MathNode, MathNode.CEIL ); +const normalize = /*@__PURE__*/ nodeProxy( MathNode, MathNode.NORMALIZE ); +const fract = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FRACT ); +const sin = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SIN ); +const cos = /*@__PURE__*/ nodeProxy( MathNode, MathNode.COS ); +const tan = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TAN ); +const asin = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ASIN ); +const acos = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ACOS ); +const atan = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ATAN ); +const abs = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ABS ); +const sign = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SIGN ); +const length = /*@__PURE__*/ nodeProxy( MathNode, MathNode.LENGTH ); +const negate = /*@__PURE__*/ nodeProxy( MathNode, MathNode.NEGATE ); +const oneMinus = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ONE_MINUS ); +const dFdx = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DFDX ); +const dFdy = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DFDY ); +const round = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ROUND ); +const reciprocal = /*@__PURE__*/ nodeProxy( MathNode, MathNode.RECIPROCAL ); +const trunc = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TRUNC ); +const fwidth = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FWIDTH ); +const bitcast = /*@__PURE__*/ nodeProxy( MathNode, MathNode.BITCAST ); +const transpose = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TRANSPOSE ); + +const atan2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.ATAN2 ); +const min$1 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MIN ); +const max$1 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MAX ); +const mod = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MOD ); +const step = /*@__PURE__*/ nodeProxy( MathNode, MathNode.STEP ); +const reflect = /*@__PURE__*/ nodeProxy( MathNode, MathNode.REFLECT ); +const distance = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DISTANCE ); +const difference = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DIFFERENCE ); +const dot = /*@__PURE__*/ nodeProxy( MathNode, MathNode.DOT ); +const cross = /*@__PURE__*/ nodeProxy( MathNode, MathNode.CROSS ); +const pow = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW ); +const pow2 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW, 2 ); +const pow3 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW, 3 ); +const pow4 = /*@__PURE__*/ nodeProxy( MathNode, MathNode.POW, 4 ); +const transformDirection = /*@__PURE__*/ nodeProxy( MathNode, MathNode.TRANSFORM_DIRECTION ); + +const cbrt = ( a ) => mul( sign( a ), pow( abs( a ), 1.0 / 3.0 ) ); +const lengthSq = ( a ) => dot( a, a ); +const mix = /*@__PURE__*/ nodeProxy( MathNode, MathNode.MIX ); +const clamp = ( value, low = 0, high = 1 ) => nodeObject( new MathNode( MathNode.CLAMP, nodeObject( value ), nodeObject( low ), nodeObject( high ) ) ); +const saturate = ( value ) => clamp( value ); +const refract = /*@__PURE__*/ nodeProxy( MathNode, MathNode.REFRACT ); +const smoothstep = /*@__PURE__*/ nodeProxy( MathNode, MathNode.SMOOTHSTEP ); +const faceForward = /*@__PURE__*/ nodeProxy( MathNode, MathNode.FACEFORWARD ); + +const rand = /*@__PURE__*/ Fn( ( [ uv ] ) => { + + const a = 12.9898, b = 78.233, c = 43758.5453; + const dt = dot( uv.xy, vec2( a, b ) ), sn = mod( dt, PI ); + + return fract( sin( sn ).mul( c ) ); + +} ); + +const mixElement = ( t, e1, e2 ) => mix( e1, e2, t ); +const smoothstepElement = ( x, low, high ) => smoothstep( low, high, x ); + +addMethodChaining( 'all', all ); +addMethodChaining( 'any', any ); +addMethodChaining( 'equals', equals ); + +addMethodChaining( 'radians', radians ); +addMethodChaining( 'degrees', degrees ); +addMethodChaining( 'exp', exp ); +addMethodChaining( 'exp2', exp2 ); +addMethodChaining( 'log', log ); +addMethodChaining( 'log2', log2 ); +addMethodChaining( 'sqrt', sqrt ); +addMethodChaining( 'inverseSqrt', inverseSqrt ); +addMethodChaining( 'floor', floor ); +addMethodChaining( 'ceil', ceil ); +addMethodChaining( 'normalize', normalize ); +addMethodChaining( 'fract', fract ); +addMethodChaining( 'sin', sin ); +addMethodChaining( 'cos', cos ); +addMethodChaining( 'tan', tan ); +addMethodChaining( 'asin', asin ); +addMethodChaining( 'acos', acos ); +addMethodChaining( 'atan', atan ); +addMethodChaining( 'abs', abs ); +addMethodChaining( 'sign', sign ); +addMethodChaining( 'length', length ); +addMethodChaining( 'lengthSq', lengthSq ); +addMethodChaining( 'negate', negate ); +addMethodChaining( 'oneMinus', oneMinus ); +addMethodChaining( 'dFdx', dFdx ); +addMethodChaining( 'dFdy', dFdy ); +addMethodChaining( 'round', round ); +addMethodChaining( 'reciprocal', reciprocal ); +addMethodChaining( 'trunc', trunc ); +addMethodChaining( 'fwidth', fwidth ); +addMethodChaining( 'atan2', atan2 ); +addMethodChaining( 'min', min$1 ); +addMethodChaining( 'max', max$1 ); +addMethodChaining( 'mod', mod ); +addMethodChaining( 'step', step ); +addMethodChaining( 'reflect', reflect ); +addMethodChaining( 'distance', distance ); +addMethodChaining( 'dot', dot ); +addMethodChaining( 'cross', cross ); +addMethodChaining( 'pow', pow ); +addMethodChaining( 'pow2', pow2 ); +addMethodChaining( 'pow3', pow3 ); +addMethodChaining( 'pow4', pow4 ); +addMethodChaining( 'transformDirection', transformDirection ); +addMethodChaining( 'mix', mixElement ); +addMethodChaining( 'clamp', clamp ); +addMethodChaining( 'refract', refract ); +addMethodChaining( 'smoothstep', smoothstepElement ); +addMethodChaining( 'faceForward', faceForward ); +addMethodChaining( 'difference', difference ); +addMethodChaining( 'saturate', saturate ); +addMethodChaining( 'cbrt', cbrt ); +addMethodChaining( 'transpose', transpose ); +addMethodChaining( 'rand', rand ); + +class ConditionalNode extends Node { + + static get type() { + + return 'ConditionalNode'; + + } + + constructor( condNode, ifNode, elseNode = null ) { + + super(); + + this.condNode = condNode; + + this.ifNode = ifNode; + this.elseNode = elseNode; + + } + + getNodeType( builder ) { + + const ifType = this.ifNode.getNodeType( builder ); + + if ( this.elseNode !== null ) { + + const elseType = this.elseNode.getNodeType( builder ); + + if ( builder.getTypeLength( elseType ) > builder.getTypeLength( ifType ) ) { + + return elseType; + + } + + } + + return ifType; + + } + + setup( builder ) { + + const condNode = this.condNode.cache(); + const ifNode = this.ifNode.cache(); + const elseNode = this.elseNode ? this.elseNode.cache() : null; + + // + + const currentNodeBlock = builder.context.nodeBlock; + + builder.getDataFromNode( ifNode ).parentNodeBlock = currentNodeBlock; + if ( elseNode !== null ) builder.getDataFromNode( elseNode ).parentNodeBlock = currentNodeBlock; + + // + + const properties = builder.getNodeProperties( this ); + properties.condNode = condNode; + properties.ifNode = ifNode.context( { nodeBlock: ifNode } ); + properties.elseNode = elseNode ? elseNode.context( { nodeBlock: elseNode } ) : null; + + } + + generate( builder, output ) { + + const type = this.getNodeType( builder ); + + const nodeData = builder.getDataFromNode( this ); + + if ( nodeData.nodeProperty !== undefined ) { + + return nodeData.nodeProperty; + + } + + const { condNode, ifNode, elseNode } = builder.getNodeProperties( this ); + + const needsOutput = output !== 'void'; + const nodeProperty = needsOutput ? property( type ).build( builder ) : ''; + + nodeData.nodeProperty = nodeProperty; + + const nodeSnippet = condNode.build( builder, 'bool' ); + + builder.addFlowCode( `\n${ builder.tab }if ( ${ nodeSnippet } ) {\n\n` ).addFlowTab(); + + let ifSnippet = ifNode.build( builder, type ); + + if ( ifSnippet ) { + + if ( needsOutput ) { + + ifSnippet = nodeProperty + ' = ' + ifSnippet + ';'; + + } else { + + ifSnippet = 'return ' + ifSnippet + ';'; + + } + + } + + builder.removeFlowTab().addFlowCode( builder.tab + '\t' + ifSnippet + '\n\n' + builder.tab + '}' ); + + if ( elseNode !== null ) { + + builder.addFlowCode( ' else {\n\n' ).addFlowTab(); + + let elseSnippet = elseNode.build( builder, type ); + + if ( elseSnippet ) { + + if ( needsOutput ) { + + elseSnippet = nodeProperty + ' = ' + elseSnippet + ';'; + + } else { + + elseSnippet = 'return ' + elseSnippet + ';'; + + } + + } + + builder.removeFlowTab().addFlowCode( builder.tab + '\t' + elseSnippet + '\n\n' + builder.tab + '}\n\n' ); + + } else { + + builder.addFlowCode( '\n\n' ); + + } + + return builder.format( nodeProperty, type, output ); + + } + +} + +const select = /*@__PURE__*/ nodeProxy( ConditionalNode ); + +addMethodChaining( 'select', select ); + +// + +const cond = ( ...params ) => { // @deprecated, r168 + + console.warn( 'TSL.ConditionalNode: cond() has been renamed to select().' ); + return select( ...params ); + +}; + +addMethodChaining( 'cond', cond ); + +class ContextNode extends Node { + + static get type() { + + return 'ContextNode'; + + } + + constructor( node, value = {} ) { + + super(); + + this.isContextNode = true; + + this.node = node; + this.value = value; + + } + + getScope() { + + return this.node.getScope(); + + } + + getNodeType( builder ) { + + return this.node.getNodeType( builder ); + + } + + analyze( builder ) { + + this.node.build( builder ); + + } + + setup( builder ) { + + const previousContext = builder.getContext(); + + builder.setContext( { ...builder.context, ...this.value } ); + + const node = this.node.build( builder ); + + builder.setContext( previousContext ); + + return node; + + } + + generate( builder, output ) { + + const previousContext = builder.getContext(); + + builder.setContext( { ...builder.context, ...this.value } ); + + const snippet = this.node.build( builder, output ); + + builder.setContext( previousContext ); + + return snippet; + + } + +} + +const context = /*@__PURE__*/ nodeProxy( ContextNode ); +const label = ( node, name ) => context( node, { label: name } ); + +addMethodChaining( 'context', context ); +addMethodChaining( 'label', label ); + +class VarNode extends Node { + + static get type() { + + return 'VarNode'; + + } + + constructor( node, name = null ) { + + super(); + + this.node = node; + this.name = name; + + this.global = true; + + this.isVarNode = true; + + } + + getHash( builder ) { + + return this.name || super.getHash( builder ); + + } + + getNodeType( builder ) { + + return this.node.getNodeType( builder ); + + } + + generate( builder ) { + + const { node, name } = this; + + const nodeVar = builder.getVarFromNode( this, name, builder.getVectorType( this.getNodeType( builder ) ) ); + + const propertyName = builder.getPropertyName( nodeVar ); + + const snippet = node.build( builder, nodeVar.type ); + + builder.addLineFlowCode( `${propertyName} = ${snippet}`, this ); + + return propertyName; + + } + +} + +const temp = /*@__PURE__*/ nodeProxy( VarNode ); + +addMethodChaining( 'temp', temp ); // @TODO: Will be removed in the future +addMethodChaining( 'toVar', ( ...params ) => temp( ...params ).append() ); + +class VaryingNode extends Node { + + static get type() { + + return 'VaryingNode'; + + } + + constructor( node, name = null ) { + + super(); + + this.node = node; + this.name = name; + + this.isVaryingNode = true; + + } + + isGlobal() { + + return true; + + } + + getHash( builder ) { + + return this.name || super.getHash( builder ); + + } + + getNodeType( builder ) { + + // VaryingNode is auto type + + return this.node.getNodeType( builder ); + + } + + setupVarying( builder ) { + + const properties = builder.getNodeProperties( this ); + + let varying = properties.varying; + + if ( varying === undefined ) { + + const name = this.name; + const type = this.getNodeType( builder ); + + properties.varying = varying = builder.getVaryingFromNode( this, name, type ); + properties.node = this.node; + + } + + // this property can be used to check if the varying can be optimized for a variable + varying.needsInterpolation || ( varying.needsInterpolation = ( builder.shaderStage === 'fragment' ) ); + + return varying; + + } + + setup( builder ) { + + this.setupVarying( builder ); + + } + + analyze( builder ) { + + this.setupVarying( builder ); + + return this.node.analyze( builder ); + + } + + generate( builder ) { + + const properties = builder.getNodeProperties( this ); + const varying = this.setupVarying( builder ); + + if ( properties.propertyName === undefined ) { + + const type = this.getNodeType( builder ); + const propertyName = builder.getPropertyName( varying, NodeShaderStage.VERTEX ); + + // force node run in vertex stage + builder.flowNodeFromShaderStage( NodeShaderStage.VERTEX, this.node, type, propertyName ); + + properties.propertyName = propertyName; + + } + + return builder.getPropertyName( varying ); + + } + +} + +const varying = /*@__PURE__*/ nodeProxy( VaryingNode ); + +addMethodChaining( 'varying', varying ); + +const WORKING_COLOR_SPACE = 'WorkingColorSpace'; +const OUTPUT_COLOR_SPACE = 'OutputColorSpace'; + +function getColorSpaceName( colorSpace ) { + + let method = null; + + if ( colorSpace === LinearSRGBColorSpace ) { + + method = 'Linear'; + + } else if ( colorSpace === SRGBColorSpace ) { + + method = 'sRGB'; + + } + + return method; + +} + +function getColorSpaceMethod( source, target ) { + + return getColorSpaceName( source ) + 'To' + getColorSpaceName( target ); + +} + +class ColorSpaceNode extends TempNode { + + static get type() { + + return 'ColorSpaceNode'; + + } + + constructor( colorNode, source, target ) { + + super( 'vec4' ); + + this.colorNode = colorNode; + this.source = source; + this.target = target; + + } + + getColorSpace( builder, colorSpace ) { + + if ( colorSpace === WORKING_COLOR_SPACE ) { + + return ColorManagement.workingColorSpace; + + } else if ( colorSpace === OUTPUT_COLOR_SPACE ) { + + return builder.context.outputColorSpace || builder.renderer.outputColorSpace; + + } + + return colorSpace; + + } + + setup( builder ) { + + const { renderer } = builder; + const { colorNode } = this; + + const source = this.getColorSpace( builder, this.source ); + const target = this.getColorSpace( builder, this.target ); + + if ( source === target ) return colorNode; + + const colorSpace = getColorSpaceMethod( source, target ); + + let outputNode = null; + + const colorSpaceFn = renderer.nodes.library.getColorSpaceFunction( colorSpace ); + + if ( colorSpaceFn !== null ) { + + outputNode = vec4( colorSpaceFn( colorNode.rgb ), colorNode.a ); + + } else { + + console.error( 'ColorSpaceNode: Unsupported Color Space configuration.', colorSpace ); + + outputNode = colorNode; + + } + + return outputNode; + + } + +} + +const toOutputColorSpace = ( node ) => nodeObject( new ColorSpaceNode( nodeObject( node ), WORKING_COLOR_SPACE, OUTPUT_COLOR_SPACE ) ); +const toWorkingColorSpace = ( node ) => nodeObject( new ColorSpaceNode( nodeObject( node ), OUTPUT_COLOR_SPACE, WORKING_COLOR_SPACE ) ); + +const workingToColorSpace = ( node, colorSpace ) => nodeObject( new ColorSpaceNode( nodeObject( node ), WORKING_COLOR_SPACE, colorSpace ) ); +const colorSpaceToWorking = ( node, colorSpace ) => nodeObject( new ColorSpaceNode( nodeObject( node ), colorSpace, WORKING_COLOR_SPACE ) ); + +addMethodChaining( 'toOutputColorSpace', toOutputColorSpace ); +addMethodChaining( 'toWorkingColorSpace', toWorkingColorSpace ); + +addMethodChaining( 'workingToColorSpace', workingToColorSpace ); +addMethodChaining( 'colorSpaceToWorking', colorSpaceToWorking ); + +let ReferenceElementNode$1 = class ReferenceElementNode extends ArrayElementNode { + + static get type() { + + return 'ReferenceElementNode'; + + } + + constructor( referenceNode, indexNode ) { + + super( referenceNode, indexNode ); + + this.referenceNode = referenceNode; + + this.isReferenceElementNode = true; + + } + + getNodeType() { + + return this.referenceNode.uniformType; + + } + + generate( builder ) { + + const snippet = super.generate( builder ); + const arrayType = this.referenceNode.getNodeType(); + const elementType = this.getNodeType(); + + return builder.format( snippet, arrayType, elementType ); + + } + +}; + +class ReferenceBaseNode extends Node { + + static get type() { + + return 'ReferenceBaseNode'; + + } + + constructor( property, uniformType, object = null, count = null ) { + + super(); + + this.property = property; + this.uniformType = uniformType; + this.object = object; + this.count = count; + + this.properties = property.split( '.' ); + this.reference = object; + this.node = null; + this.group = null; + + this.updateType = NodeUpdateType.OBJECT; + + } + + setGroup( group ) { + + this.group = group; + + return this; + + } + + element( indexNode ) { + + return nodeObject( new ReferenceElementNode$1( this, nodeObject( indexNode ) ) ); + + } + + setNodeType( uniformType ) { + + const node = uniform( null, uniformType ).getSelf(); + + if ( this.group !== null ) { + + node.setGroup( this.group ); + + } + + this.node = node; + + } + + getNodeType( builder ) { + + if ( this.node === null ) { + + this.updateReference( builder ); + this.updateValue(); + + } + + return this.node.getNodeType( builder ); + + } + + getValueFromReference( object = this.reference ) { + + const { properties } = this; + + let value = object[ properties[ 0 ] ]; + + for ( let i = 1; i < properties.length; i ++ ) { + + value = value[ properties[ i ] ]; + + } + + return value; + + } + + updateReference( state ) { + + this.reference = this.object !== null ? this.object : state.object; + + return this.reference; + + } + + setup() { + + this.updateValue(); + + return this.node; + + } + + update( /*frame*/ ) { + + this.updateValue(); + + } + + updateValue() { + + if ( this.node === null ) this.setNodeType( this.uniformType ); + + const value = this.getValueFromReference(); + + if ( Array.isArray( value ) ) { + + this.node.array = value; + + } else { + + this.node.value = value; + + } + + } + +} + +const reference$1 = ( name, type, object ) => nodeObject( new ReferenceBaseNode( name, type, object ) ); + +class RendererReferenceNode extends ReferenceBaseNode { + + static get type() { + + return 'RendererReferenceNode'; + + } + + constructor( property, inputType, renderer = null ) { + + super( property, inputType, renderer ); + + this.renderer = renderer; + + this.setGroup( renderGroup ); + + } + + updateReference( state ) { + + this.reference = this.renderer !== null ? this.renderer : state.renderer; + + return this.reference; + + } + +} + +const rendererReference = ( name, type, renderer ) => nodeObject( new RendererReferenceNode( name, type, renderer ) ); + +class ToneMappingNode extends TempNode { + + static get type() { + + return 'ToneMappingNode'; + + } + + constructor( toneMapping, exposureNode = toneMappingExposure, colorNode = null ) { + + super( 'vec3' ); + + this.toneMapping = toneMapping; + + this.exposureNode = exposureNode; + this.colorNode = colorNode; + + } + + getCacheKey() { + + return hash$1( super.getCacheKey(), this.toneMapping ); + + } + + setup( builder ) { + + const colorNode = this.colorNode || builder.context.color; + const toneMapping = this.toneMapping; + + if ( toneMapping === NoToneMapping ) return colorNode; + + let outputNode = null; + + const toneMappingFn = builder.renderer.nodes.library.getToneMappingFunction( toneMapping ); + + if ( toneMappingFn !== null ) { + + outputNode = vec4( toneMappingFn( colorNode.rgb, this.exposureNode ), colorNode.a ); + + } else { + + console.error( 'ToneMappingNode: Unsupported Tone Mapping configuration.', toneMapping ); + + outputNode = colorNode; + + } + + return outputNode; + + } + +} + +const toneMapping = ( mapping, exposure, color ) => nodeObject( new ToneMappingNode( mapping, nodeObject( exposure ), nodeObject( color ) ) ); +const toneMappingExposure = /*@__PURE__*/ rendererReference( 'toneMappingExposure', 'float' ); + +addMethodChaining( 'toneMapping', ( color, mapping, exposure ) => toneMapping( mapping, exposure, color ) ); + +class BufferAttributeNode extends InputNode { + + static get type() { + + return 'BufferAttributeNode'; + + } + + constructor( value, bufferType = null, bufferStride = 0, bufferOffset = 0 ) { + + super( value, bufferType ); + + this.isBufferNode = true; + + this.bufferType = bufferType; + this.bufferStride = bufferStride; + this.bufferOffset = bufferOffset; + + this.usage = StaticDrawUsage; + this.instanced = false; + + this.attribute = null; + + this.global = true; + + if ( value && value.isBufferAttribute === true ) { + + this.attribute = value; + this.usage = value.usage; + this.instanced = value.isInstancedBufferAttribute; + + } + + } + + getHash( builder ) { + + if ( this.bufferStride === 0 && this.bufferOffset === 0 ) { + + let bufferData = builder.globalCache.getData( this.value ); + + if ( bufferData === undefined ) { + + bufferData = { + node: this + }; + + builder.globalCache.setData( this.value, bufferData ); + + } + + return bufferData.node.uuid; + + } + + return this.uuid; + + } + + getNodeType( builder ) { + + if ( this.bufferType === null ) { + + this.bufferType = builder.getTypeFromAttribute( this.attribute ); + + } + + return this.bufferType; + + } + + setup( builder ) { + + if ( this.attribute !== null ) return; + + const type = this.getNodeType( builder ); + const array = this.value; + const itemSize = builder.getTypeLength( type ); + const stride = this.bufferStride || itemSize; + const offset = this.bufferOffset; + + const buffer = array.isInterleavedBuffer === true ? array : new InterleavedBuffer( array, stride ); + const bufferAttribute = new InterleavedBufferAttribute( buffer, itemSize, offset ); + + buffer.setUsage( this.usage ); + + this.attribute = bufferAttribute; + this.attribute.isInstancedBufferAttribute = this.instanced; // @TODO: Add a possible: InstancedInterleavedBufferAttribute + + } + + generate( builder ) { + + const nodeType = this.getNodeType( builder ); + + const nodeAttribute = builder.getBufferAttributeFromNode( this, nodeType ); + const propertyName = builder.getPropertyName( nodeAttribute ); + + let output = null; + + if ( builder.shaderStage === 'vertex' || builder.shaderStage === 'compute' ) { + + this.name = propertyName; + + output = propertyName; + + } else { + + const nodeVarying = varying( this ); + + output = nodeVarying.build( builder, nodeType ); + + } + + return output; + + } + + getInputType( /*builder*/ ) { + + return 'bufferAttribute'; + + } + + setUsage( value ) { + + this.usage = value; + + if ( this.attribute && this.attribute.isBufferAttribute === true ) { + + this.attribute.usage = value; + + } + + return this; + + } + + setInstanced( value ) { + + this.instanced = value; + + return this; + + } + +} + +const bufferAttribute = ( array, type, stride, offset ) => nodeObject( new BufferAttributeNode( array, type, stride, offset ) ); +const dynamicBufferAttribute = ( array, type, stride, offset ) => bufferAttribute( array, type, stride, offset ).setUsage( DynamicDrawUsage ); + +const instancedBufferAttribute = ( array, type, stride, offset ) => bufferAttribute( array, type, stride, offset ).setInstanced( true ); +const instancedDynamicBufferAttribute = ( array, type, stride, offset ) => dynamicBufferAttribute( array, type, stride, offset ).setInstanced( true ); + +addMethodChaining( 'toAttribute', ( bufferNode ) => bufferAttribute( bufferNode.value ) ); + +class ComputeNode extends Node { + + static get type() { + + return 'ComputeNode'; + + } + + constructor( computeNode, count, workgroupSize = [ 64 ] ) { + + super( 'void' ); + + this.isComputeNode = true; + + this.computeNode = computeNode; + + this.count = count; + this.workgroupSize = workgroupSize; + this.dispatchCount = 0; + + this.version = 1; + this.updateBeforeType = NodeUpdateType.OBJECT; + + this.updateDispatchCount(); + + } + + dispose() { + + this.dispatchEvent( { type: 'dispose' } ); + + } + + set needsUpdate( value ) { + + if ( value === true ) this.version ++; + + } + + updateDispatchCount() { + + const { count, workgroupSize } = this; + + let size = workgroupSize[ 0 ]; + + for ( let i = 1; i < workgroupSize.length; i ++ ) + size *= workgroupSize[ i ]; + + this.dispatchCount = Math.ceil( count / size ); + + } + + onInit() { } + + updateBefore( { renderer } ) { + + renderer.compute( this ); + + } + + generate( builder ) { + + const { shaderStage } = builder; + + if ( shaderStage === 'compute' ) { + + const snippet = this.computeNode.build( builder, 'void' ); + + if ( snippet !== '' ) { + + builder.addLineFlowCode( snippet, this ); + + } + + } + + } + +} + +const compute = ( node, count, workgroupSize ) => nodeObject( new ComputeNode( nodeObject( node ), count, workgroupSize ) ); + +addMethodChaining( 'compute', compute ); + +class CacheNode extends Node { + + static get type() { + + return 'CacheNode'; + + } + + constructor( node, parent = true ) { + + super(); + + this.node = node; + this.parent = parent; + + this.isCacheNode = true; + + } + + getNodeType( builder ) { + + return this.node.getNodeType( builder ); + + } + + build( builder, ...params ) { + + const previousCache = builder.getCache(); + const cache = builder.getCacheFromNode( this, this.parent ); + + builder.setCache( cache ); + + const data = this.node.build( builder, ...params ); + + builder.setCache( previousCache ); + + return data; + + } + +} + +const cache = ( node, ...params ) => nodeObject( new CacheNode( nodeObject( node ), ...params ) ); + +addMethodChaining( 'cache', cache ); + +class BypassNode extends Node { + + static get type() { + + return 'BypassNode'; + + } + + constructor( returnNode, callNode ) { + + super(); + + this.isBypassNode = true; + + this.outputNode = returnNode; + this.callNode = callNode; + + } + + getNodeType( builder ) { + + return this.outputNode.getNodeType( builder ); + + } + + generate( builder ) { + + const snippet = this.callNode.build( builder, 'void' ); + + if ( snippet !== '' ) { + + builder.addLineFlowCode( snippet, this ); + + } + + return this.outputNode.build( builder ); + + } + +} + +const bypass = /*@__PURE__*/ nodeProxy( BypassNode ); + +addMethodChaining( 'bypass', bypass ); + +class RemapNode extends Node { + + static get type() { + + return 'RemapNode'; + + } + + constructor( node, inLowNode, inHighNode, outLowNode = float( 0 ), outHighNode = float( 1 ) ) { + + super(); + + this.node = node; + this.inLowNode = inLowNode; + this.inHighNode = inHighNode; + this.outLowNode = outLowNode; + this.outHighNode = outHighNode; + + this.doClamp = true; + + } + + setup() { + + const { node, inLowNode, inHighNode, outLowNode, outHighNode, doClamp } = this; + + let t = node.sub( inLowNode ).div( inHighNode.sub( inLowNode ) ); + + if ( doClamp === true ) t = t.clamp(); + + return t.mul( outHighNode.sub( outLowNode ) ).add( outLowNode ); + + } + +} + +const remap = /*@__PURE__*/ nodeProxy( RemapNode, null, null, { doClamp: false } ); +const remapClamp = /*@__PURE__*/ nodeProxy( RemapNode ); + +addMethodChaining( 'remap', remap ); +addMethodChaining( 'remapClamp', remapClamp ); + +class ExpressionNode extends Node { + + static get type() { + + return 'ExpressionNode'; + + } + + constructor( snippet = '', nodeType = 'void' ) { + + super( nodeType ); + + this.snippet = snippet; + + } + + generate( builder, output ) { + + const type = this.getNodeType( builder ); + const snippet = this.snippet; + + if ( type === 'void' ) { + + builder.addLineFlowCode( snippet, this ); + + } else { + + return builder.format( `( ${ snippet } )`, type, output ); + + } + + } + +} + +const expression = /*@__PURE__*/ nodeProxy( ExpressionNode ); + +const Discard = ( conditional ) => ( conditional ? select( conditional, expression( 'discard' ) ) : expression( 'discard' ) ).append(); +const Return = () => expression( 'return' ).append(); + +addMethodChaining( 'discard', Discard ); + +class RenderOutputNode extends TempNode { + + static get type() { + + return 'RenderOutputNode'; + + } + + constructor( colorNode, toneMapping, outputColorSpace ) { + + super( 'vec4' ); + + this.colorNode = colorNode; + this.toneMapping = toneMapping; + this.outputColorSpace = outputColorSpace; + + this.isRenderOutput = true; + + } + + setup( { context } ) { + + let outputNode = this.colorNode || context.color; + + // tone mapping + + const toneMapping = ( this.toneMapping !== null ? this.toneMapping : context.toneMapping ) || NoToneMapping; + const outputColorSpace = ( this.outputColorSpace !== null ? this.outputColorSpace : context.outputColorSpace ) || NoColorSpace; + + if ( toneMapping !== NoToneMapping ) { + + outputNode = outputNode.toneMapping( toneMapping ); + + } + + // working to output color space + + if ( outputColorSpace !== NoColorSpace && outputColorSpace !== ColorManagement.workingColorSpace ) { + + outputNode = outputNode.workingToColorSpace( outputColorSpace ); + + } + + return outputNode; + + } + +} + +const renderOutput = ( color, toneMapping = null, outputColorSpace = null ) => nodeObject( new RenderOutputNode( nodeObject( color ), toneMapping, outputColorSpace ) ); + +addMethodChaining( 'renderOutput', renderOutput ); + +// Non-PURE exports list, side-effects are required here. +// TSL Base Syntax + + +function addNodeElement( name/*, nodeElement*/ ) { + + console.warn( 'THREE.TSLBase: AddNodeElement has been removed in favor of tree-shaking. Trying add', name ); + +} + +class AttributeNode extends Node { + + static get type() { + + return 'AttributeNode'; + + } + + constructor( attributeName, nodeType = null ) { + + super( nodeType ); + + this.global = true; + + this._attributeName = attributeName; + + } + + getHash( builder ) { + + return this.getAttributeName( builder ); + + } + + getNodeType( builder ) { + + let nodeType = this.nodeType; + + if ( nodeType === null ) { + + const attributeName = this.getAttributeName( builder ); + + if ( builder.hasGeometryAttribute( attributeName ) ) { + + const attribute = builder.geometry.getAttribute( attributeName ); + + nodeType = builder.getTypeFromAttribute( attribute ); + + } else { + + nodeType = 'float'; + + } + + } + + return nodeType; + + } + + setAttributeName( attributeName ) { + + this._attributeName = attributeName; + + return this; + + } + + getAttributeName( /*builder*/ ) { + + return this._attributeName; + + } + + generate( builder ) { + + const attributeName = this.getAttributeName( builder ); + const nodeType = this.getNodeType( builder ); + const geometryAttribute = builder.hasGeometryAttribute( attributeName ); + + if ( geometryAttribute === true ) { + + const attribute = builder.geometry.getAttribute( attributeName ); + const attributeType = builder.getTypeFromAttribute( attribute ); + + const nodeAttribute = builder.getAttribute( attributeName, attributeType ); + + if ( builder.shaderStage === 'vertex' ) { + + return builder.format( nodeAttribute.name, attributeType, nodeType ); + + } else { + + const nodeVarying = varying( this ); + + return nodeVarying.build( builder, nodeType ); + + } + + } else { + + console.warn( `AttributeNode: Vertex attribute "${ attributeName }" not found on geometry.` ); + + return builder.generateConst( nodeType ); + + } + + } + + serialize( data ) { + + super.serialize( data ); + + data.global = this.global; + data._attributeName = this._attributeName; + + } + + deserialize( data ) { + + super.deserialize( data ); + + this.global = data.global; + this._attributeName = data._attributeName; + + } + +} + +const attribute = ( name, nodeType ) => nodeObject( new AttributeNode( name, nodeType ) ); + +const uv = ( index ) => attribute( 'uv' + ( index > 0 ? index : '' ), 'vec2' ); + +class TextureSizeNode extends Node { + + static get type() { + + return 'TextureSizeNode'; + + } + + constructor( textureNode, levelNode = null ) { + + super( 'uvec2' ); + + this.isTextureSizeNode = true; + + this.textureNode = textureNode; + this.levelNode = levelNode; + + } + + generate( builder, output ) { + + const textureProperty = this.textureNode.build( builder, 'property' ); + const level = this.levelNode === null ? '0' : this.levelNode.build( builder, 'int' ); + + return builder.format( `${ builder.getMethod( 'textureDimensions' ) }( ${ textureProperty }, ${ level } )`, this.getNodeType( builder ), output ); + + } + +} + +const textureSize = /*@__PURE__*/ nodeProxy( TextureSizeNode ); + +class MaxMipLevelNode extends UniformNode { + + static get type() { + + return 'MaxMipLevelNode'; + + } + + constructor( textureNode ) { + + super( 0 ); + + this._textureNode = textureNode; + + this.updateType = NodeUpdateType.FRAME; + + } + + get textureNode() { + + return this._textureNode; + + } + + get texture() { + + return this._textureNode.value; + + } + + update() { + + const texture = this.texture; + const images = texture.images; + const image = ( images && images.length > 0 ) ? ( ( images[ 0 ] && images[ 0 ].image ) || images[ 0 ] ) : texture.image; + + if ( image && image.width !== undefined ) { + + const { width, height } = image; + + this.value = Math.log2( Math.max( width, height ) ); + + } + + } + +} + +const maxMipLevel = /*@__PURE__*/ nodeProxy( MaxMipLevelNode ); + +class TextureNode extends UniformNode { + + static get type() { + + return 'TextureNode'; + + } + + constructor( value, uvNode = null, levelNode = null, biasNode = null ) { + + super( value ); + + this.isTextureNode = true; + + this.uvNode = uvNode; + this.levelNode = levelNode; + this.biasNode = biasNode; + this.compareNode = null; + this.depthNode = null; + this.gradNode = null; + + this.sampler = true; + this.updateMatrix = false; + this.updateType = NodeUpdateType.NONE; + + this.referenceNode = null; + + this._value = value; + this._matrixUniform = null; + + this.setUpdateMatrix( uvNode === null ); + + } + + set value( value ) { + + if ( this.referenceNode ) { + + this.referenceNode.value = value; + + } else { + + this._value = value; + + } + + } + + get value() { + + return this.referenceNode ? this.referenceNode.value : this._value; + + } + + getUniformHash( /*builder*/ ) { + + return this.value.uuid; + + } + + getNodeType( /*builder*/ ) { + + if ( this.value.isDepthTexture === true ) return 'float'; + + if ( this.value.type === UnsignedIntType ) { + + return 'uvec4'; + + } else if ( this.value.type === IntType ) { + + return 'ivec4'; + + } + + return 'vec4'; + + } + + getInputType( /*builder*/ ) { + + return 'texture'; + + } + + getDefaultUV() { + + return uv( this.value.channel ); + + } + + updateReference( /*state*/ ) { + + return this.value; + + } + + getTransformedUV( uvNode ) { + + if ( this._matrixUniform === null ) this._matrixUniform = uniform( this.value.matrix ); + + return this._matrixUniform.mul( vec3( uvNode, 1 ) ).xy; + + } + + setUpdateMatrix( value ) { + + this.updateMatrix = value; + this.updateType = value ? NodeUpdateType.FRAME : NodeUpdateType.NONE; + + return this; + + } + + setupUV( builder, uvNode ) { + + const texture = this.value; + + if ( builder.isFlipY() && ( texture.isRenderTargetTexture === true || texture.isFramebufferTexture === true || texture.isDepthTexture === true ) ) { + + if ( this.sampler ) { + + uvNode = uvNode.flipY(); + + } else { + + uvNode = uvNode.setY( int( textureSize( this, this.levelNode ).y ).sub( uvNode.y ).sub( 1 ) ); + + } + + } + + return uvNode; + + } + + setup( builder ) { + + const properties = builder.getNodeProperties( this ); + properties.referenceNode = this.referenceNode; + + // + + let uvNode = this.uvNode; + + if ( ( uvNode === null || builder.context.forceUVContext === true ) && builder.context.getUV ) { + + uvNode = builder.context.getUV( this ); + + } + + if ( ! uvNode ) uvNode = this.getDefaultUV(); + + if ( this.updateMatrix === true ) { + + uvNode = this.getTransformedUV( uvNode ); + + } + + uvNode = this.setupUV( builder, uvNode ); + + // + + let levelNode = this.levelNode; + + if ( levelNode === null && builder.context.getTextureLevel ) { + + levelNode = builder.context.getTextureLevel( this ); + + } + + // + + properties.uvNode = uvNode; + properties.levelNode = levelNode; + properties.biasNode = this.biasNode; + properties.compareNode = this.compareNode; + properties.gradNode = this.gradNode; + properties.depthNode = this.depthNode; + + } + + generateUV( builder, uvNode ) { + + return uvNode.build( builder, this.sampler === true ? 'vec2' : 'ivec2' ); + + } + + generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, biasSnippet, depthSnippet, compareSnippet, gradSnippet ) { + + const texture = this.value; + + let snippet; + + if ( levelSnippet ) { + + snippet = builder.generateTextureLevel( texture, textureProperty, uvSnippet, levelSnippet, depthSnippet ); + + } else if ( biasSnippet ) { + + snippet = builder.generateTextureBias( texture, textureProperty, uvSnippet, biasSnippet, depthSnippet ); + + } else if ( gradSnippet ) { + + snippet = builder.generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet, depthSnippet ); + + } else if ( compareSnippet ) { + + snippet = builder.generateTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, depthSnippet ); + + } else if ( this.sampler === false ) { + + snippet = builder.generateTextureLoad( texture, textureProperty, uvSnippet, depthSnippet ); + + } else { + + snippet = builder.generateTexture( texture, textureProperty, uvSnippet, depthSnippet ); + + } + + return snippet; + + } + + generate( builder, output ) { + + const properties = builder.getNodeProperties( this ); + + const texture = this.value; + + if ( ! texture || texture.isTexture !== true ) { + + throw new Error( 'TextureNode: Need a three.js texture.' ); + + } + + const textureProperty = super.generate( builder, 'property' ); + + if ( output === 'sampler' ) { + + return textureProperty + '_sampler'; + + } else if ( builder.isReference( output ) ) { + + return textureProperty; + + } else { + + const nodeData = builder.getDataFromNode( this ); + + let propertyName = nodeData.propertyName; + + if ( propertyName === undefined ) { + + const { uvNode, levelNode, biasNode, compareNode, depthNode, gradNode } = properties; + + const uvSnippet = this.generateUV( builder, uvNode ); + const levelSnippet = levelNode ? levelNode.build( builder, 'float' ) : null; + const biasSnippet = biasNode ? biasNode.build( builder, 'float' ) : null; + const depthSnippet = depthNode ? depthNode.build( builder, 'int' ) : null; + const compareSnippet = compareNode ? compareNode.build( builder, 'float' ) : null; + const gradSnippet = gradNode ? [ gradNode[ 0 ].build( builder, 'vec2' ), gradNode[ 1 ].build( builder, 'vec2' ) ] : null; + + const nodeVar = builder.getVarFromNode( this ); + + propertyName = builder.getPropertyName( nodeVar ); + + const snippet = this.generateSnippet( builder, textureProperty, uvSnippet, levelSnippet, biasSnippet, depthSnippet, compareSnippet, gradSnippet ); + + builder.addLineFlowCode( `${propertyName} = ${snippet}`, this ); + + nodeData.snippet = snippet; + nodeData.propertyName = propertyName; + + } + + let snippet = propertyName; + const nodeType = this.getNodeType( builder ); + + if ( builder.needsToWorkingColorSpace( texture ) ) { + + snippet = colorSpaceToWorking( expression( snippet, nodeType ), texture.colorSpace ).setup( builder ).build( builder, nodeType ); + + } + + return builder.format( snippet, nodeType, output ); + + } + + } + + setSampler( value ) { + + this.sampler = value; + + return this; + + } + + getSampler() { + + return this.sampler; + + } + + // @TODO: Move to TSL + + uv( uvNode ) { + + const textureNode = this.clone(); + textureNode.uvNode = nodeObject( uvNode ); + textureNode.referenceNode = this.getSelf(); + + return nodeObject( textureNode ); + + } + + blur( amountNode ) { + + const textureNode = this.clone(); + textureNode.biasNode = nodeObject( amountNode ).mul( maxMipLevel( textureNode ) ); + textureNode.referenceNode = this.getSelf(); + + return nodeObject( textureNode ); + + } + + level( levelNode ) { + + const textureNode = this.clone(); + textureNode.levelNode = nodeObject( levelNode ); + textureNode.referenceNode = this.getSelf(); + + return nodeObject( textureNode ); + + } + + size( levelNode ) { + + return textureSize( this, levelNode ); + + } + + bias( biasNode ) { + + const textureNode = this.clone(); + textureNode.biasNode = nodeObject( biasNode ); + textureNode.referenceNode = this.getSelf(); + + return nodeObject( textureNode ); + + } + + compare( compareNode ) { + + const textureNode = this.clone(); + textureNode.compareNode = nodeObject( compareNode ); + textureNode.referenceNode = this.getSelf(); + + return nodeObject( textureNode ); + + } + + grad( gradNodeX, gradNodeY ) { + + const textureNode = this.clone(); + textureNode.gradNode = [ nodeObject( gradNodeX ), nodeObject( gradNodeY ) ]; + textureNode.referenceNode = this.getSelf(); + + return nodeObject( textureNode ); + + } + + depth( depthNode ) { + + const textureNode = this.clone(); + textureNode.depthNode = nodeObject( depthNode ); + textureNode.referenceNode = this.getSelf(); + + return nodeObject( textureNode ); + + } + + // -- + + serialize( data ) { + + super.serialize( data ); + + data.value = this.value.toJSON( data.meta ).uuid; + data.sampler = this.sampler; + data.updateMatrix = this.updateMatrix; + data.updateType = this.updateType; + + } + + deserialize( data ) { + + super.deserialize( data ); + + this.value = data.meta.textures[ data.value ]; + this.sampler = data.sampler; + this.updateMatrix = data.updateMatrix; + this.updateType = data.updateType; + + } + + update() { + + const texture = this.value; + const matrixUniform = this._matrixUniform; + + if ( matrixUniform !== null ) matrixUniform.value = texture.matrix; + + if ( texture.matrixAutoUpdate === true ) { + + texture.updateMatrix(); + + } + + } + + clone() { + + const newNode = new this.constructor( this.value, this.uvNode, this.levelNode, this.biasNode ); + newNode.sampler = this.sampler; + + return newNode; + + } + +} + +const texture = /*@__PURE__*/ nodeProxy( TextureNode ); +const textureLoad = ( ...params ) => texture( ...params ).setSampler( false ); + +//export const textureLevel = ( value, uv, level ) => texture( value, uv ).level( level ); + +const sampler = ( aTexture ) => ( aTexture.isNode === true ? aTexture : texture( aTexture ) ).convert( 'sampler' ); + +const cameraNear = /*@__PURE__*/ uniform( 'float' ).label( 'cameraNear' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.near ); +const cameraFar = /*@__PURE__*/ uniform( 'float' ).label( 'cameraFar' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.far ); +const cameraLogDepth = /*@__PURE__*/ uniform( 'float' ).label( 'cameraLogDepth' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => 2.0 / ( Math.log( camera.far + 1.0 ) / Math.LN2 ) ); +const cameraProjectionMatrix = /*@__PURE__*/ uniform( 'mat4' ).label( 'cameraProjectionMatrix' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.projectionMatrix ); +const cameraProjectionMatrixInverse = /*@__PURE__*/ uniform( 'mat4' ).label( 'cameraProjectionMatrixInverse' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.projectionMatrixInverse ); +const cameraViewMatrix = /*@__PURE__*/ uniform( 'mat4' ).label( 'cameraViewMatrix' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.matrixWorldInverse ); +const cameraWorldMatrix = /*@__PURE__*/ uniform( 'mat4' ).label( 'cameraWorldMatrix' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.matrixWorld ); +const cameraNormalMatrix = /*@__PURE__*/ uniform( 'mat3' ).label( 'cameraNormalMatrix' ).setGroup( renderGroup ).onRenderUpdate( ( { camera } ) => camera.normalMatrix ); +const cameraPosition = /*@__PURE__*/ uniform( new Vector3() ).label( 'cameraPosition' ).setGroup( renderGroup ).onRenderUpdate( ( { camera }, self ) => self.value.setFromMatrixPosition( camera.matrixWorld ) ); + +class Object3DNode extends Node { + + static get type() { + + return 'Object3DNode'; + + } + + constructor( scope, object3d = null ) { + + super(); + + this.scope = scope; + this.object3d = object3d; + + this.updateType = NodeUpdateType.OBJECT; + + this._uniformNode = new UniformNode( null ); + + } + + getNodeType() { + + const scope = this.scope; + + if ( scope === Object3DNode.WORLD_MATRIX ) { + + return 'mat4'; + + } else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION || scope === Object3DNode.SCALE ) { + + return 'vec3'; + + } + + } + + update( frame ) { + + const object = this.object3d; + const uniformNode = this._uniformNode; + const scope = this.scope; + + if ( scope === Object3DNode.WORLD_MATRIX ) { + + uniformNode.value = object.matrixWorld; + + } else if ( scope === Object3DNode.POSITION ) { + + uniformNode.value = uniformNode.value || new Vector3(); + + uniformNode.value.setFromMatrixPosition( object.matrixWorld ); + + } else if ( scope === Object3DNode.SCALE ) { + + uniformNode.value = uniformNode.value || new Vector3(); + + uniformNode.value.setFromMatrixScale( object.matrixWorld ); + + } else if ( scope === Object3DNode.DIRECTION ) { + + uniformNode.value = uniformNode.value || new Vector3(); + + object.getWorldDirection( uniformNode.value ); + + } else if ( scope === Object3DNode.VIEW_POSITION ) { + + const camera = frame.camera; + + uniformNode.value = uniformNode.value || new Vector3(); + uniformNode.value.setFromMatrixPosition( object.matrixWorld ); + + uniformNode.value.applyMatrix4( camera.matrixWorldInverse ); + + } + + } + + generate( builder ) { + + const scope = this.scope; + + if ( scope === Object3DNode.WORLD_MATRIX ) { + + this._uniformNode.nodeType = 'mat4'; + + } else if ( scope === Object3DNode.POSITION || scope === Object3DNode.VIEW_POSITION || scope === Object3DNode.DIRECTION || scope === Object3DNode.SCALE ) { + + this._uniformNode.nodeType = 'vec3'; + + } + + return this._uniformNode.build( builder ); + + } + + serialize( data ) { + + super.serialize( data ); + + data.scope = this.scope; + + } + + deserialize( data ) { + + super.deserialize( data ); + + this.scope = data.scope; + + } + +} + +Object3DNode.WORLD_MATRIX = 'worldMatrix'; +Object3DNode.POSITION = 'position'; +Object3DNode.SCALE = 'scale'; +Object3DNode.VIEW_POSITION = 'viewPosition'; +Object3DNode.DIRECTION = 'direction'; + +const objectDirection = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.DIRECTION ); +const objectWorldMatrix = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.WORLD_MATRIX ); +const objectPosition = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.POSITION ); +const objectScale = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.SCALE ); +const objectViewPosition = /*@__PURE__*/ nodeProxy( Object3DNode, Object3DNode.VIEW_POSITION ); + +class ModelNode extends Object3DNode { + + static get type() { + + return 'ModelNode'; + + } + + constructor( scope ) { + + super( scope ); + + } + + update( frame ) { + + this.object3d = frame.object; + + super.update( frame ); + + } + +} + +const modelDirection = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.DIRECTION ); +const modelWorldMatrix = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.WORLD_MATRIX ); +const modelPosition = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.POSITION ); +const modelScale = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.SCALE ); +const modelViewPosition = /*@__PURE__*/ nodeImmutable( ModelNode, ModelNode.VIEW_POSITION ); +const modelNormalMatrix = /*@__PURE__*/ uniform( new Matrix3() ).onObjectUpdate( ( { object }, self ) => self.value.getNormalMatrix( object.matrixWorld ) ); +const modelWorldMatrixInverse = /*@__PURE__*/ uniform( new Matrix4() ).onObjectUpdate( ( { object }, self ) => self.value.copy( object.matrixWorld ).invert() ); +const modelViewMatrix = /*@__PURE__*/ cameraViewMatrix.mul( modelWorldMatrix ).toVar( 'modelViewMatrix' ); + +const highPrecisionModelViewMatrix = /*@__PURE__*/ ( Fn( ( builder ) => { + + builder.context.isHighPrecisionModelViewMatrix = true; + + return uniform( 'mat4' ).onObjectUpdate( ( { object, camera } ) => { + + return object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); + + } ); + +} ).once() )().toVar( 'highPrecisionModelViewMatrix' ); + +const highPrecisionModelNormalViewMatrix = /*@__PURE__*/ ( Fn( ( builder ) => { + + const isHighPrecisionModelViewMatrix = builder.context.isHighPrecisionModelViewMatrix; + + return uniform( 'mat3' ).onObjectUpdate( ( { object, camera } ) => { + + if ( isHighPrecisionModelViewMatrix !== true ) { + + object.modelViewMatrix.multiplyMatrices( camera.matrixWorldInverse, object.matrixWorld ); + + } + + return object.normalMatrix.getNormalMatrix( object.modelViewMatrix ); + + } ); + +} ).once() )().toVar( 'highPrecisionModelNormalMatrix' ); + +const positionGeometry = /*@__PURE__*/ attribute( 'position', 'vec3' ); +const positionLocal = /*@__PURE__*/ positionGeometry.varying( 'positionLocal' ); +const positionPrevious = /*@__PURE__*/ positionGeometry.varying( 'positionPrevious' ); +const positionWorld = /*@__PURE__*/ modelWorldMatrix.mul( positionLocal ).xyz.varying( 'v_positionWorld' ); +const positionWorldDirection = /*@__PURE__*/ positionLocal.transformDirection( modelWorldMatrix ).varying( 'v_positionWorldDirection' ).normalize().toVar( 'positionWorldDirection' ); +const positionView = /*@__PURE__*/ modelViewMatrix.mul( positionLocal ).xyz.varying( 'v_positionView' ); +const positionViewDirection = /*@__PURE__*/ positionView.negate().varying( 'v_positionViewDirection' ).normalize().toVar( 'positionViewDirection' ); + +class FrontFacingNode extends Node { + + static get type() { + + return 'FrontFacingNode'; + + } + + constructor() { + + super( 'bool' ); + + this.isFrontFacingNode = true; + + } + + generate( builder ) { + + const { renderer, material } = builder; + + if ( renderer.coordinateSystem === WebGLCoordinateSystem ) { + + if ( material.side === BackSide ) { + + return 'false'; + + } + + } + + return builder.getFrontFacing(); + + } + +} + +const frontFacing = /*@__PURE__*/ nodeImmutable( FrontFacingNode ); +const faceDirection = /*@__PURE__*/ float( frontFacing ).mul( 2.0 ).sub( 1.0 ); + +const normalGeometry = /*@__PURE__*/ attribute( 'normal', 'vec3' ); + +const normalLocal = /*@__PURE__*/ ( Fn( ( builder ) => { + + if ( builder.geometry.hasAttribute( 'normal' ) === false ) { + + console.warn( 'TSL.NormalNode: Vertex attribute "normal" not found on geometry.' ); + + return vec3( 0, 1, 0 ); + + } + + return normalGeometry; + +}, 'vec3' ).once() )().toVar( 'normalLocal' ); + +const normalFlat = /*@__PURE__*/ positionView.dFdx().cross( positionView.dFdy() ).normalize().toVar( 'normalFlat' ); + +const normalView = /*@__PURE__*/ ( Fn( ( builder ) => { + + let node; + + if ( builder.material.flatShading === true ) { + + node = normalFlat; + + } else { + + node = varying( transformNormalToView( normalLocal ), 'v_normalView' ).normalize(); + + } + + return node; + +}, 'vec3' ).once() )().toVar( 'normalView' ); + +const normalWorld = /*@__PURE__*/ varying( normalView.transformDirection( cameraViewMatrix ), 'v_normalWorld' ).normalize().toVar( 'normalWorld' ); + +const transformedNormalView = /*@__PURE__*/ ( Fn( ( builder ) => { + + return builder.context.setupNormal(); + +}, 'vec3' ).once() )().mul( faceDirection ).toVar( 'transformedNormalView' ); + + +const transformedNormalWorld = /*@__PURE__*/ transformedNormalView.transformDirection( cameraViewMatrix ).toVar( 'transformedNormalWorld' ); + +const transformedClearcoatNormalView = /*@__PURE__*/ ( Fn( ( builder ) => { + + return builder.context.setupClearcoatNormal(); + +}, 'vec3' ).once() )().mul( faceDirection ).toVar( 'transformedClearcoatNormalView' ); + +const transformNormal = /*@__PURE__*/ Fn( ( [ normal, matrix = modelWorldMatrix ] ) => { + + const m = mat3( matrix ); + + const transformedNormal = normal.div( vec3( m[ 0 ].dot( m[ 0 ] ), m[ 1 ].dot( m[ 1 ] ), m[ 2 ].dot( m[ 2 ] ) ) ); + + return m.mul( transformedNormal ).xyz; + +} ); + +const transformNormalToView = /*@__PURE__*/ Fn( ( [ normal ], builder ) => { + + const modelNormalViewMatrix = builder.renderer.nodes.modelNormalViewMatrix; + + if ( modelNormalViewMatrix !== null ) { + + return modelNormalViewMatrix.transformDirection( normal ); + + } + + // + + const transformedNormal = modelNormalMatrix.mul( normal ); + + return cameraViewMatrix.transformDirection( transformedNormal ); + +} ); + +const materialRefractionRatio = /*@__PURE__*/ uniform( 0 ).onReference( ( { material } ) => material ).onRenderUpdate( ( { material } ) => material.refractionRatio ); + +const reflectView = /*@__PURE__*/ positionViewDirection.negate().reflect( transformedNormalView ); +const refractView = /*@__PURE__*/ positionViewDirection.negate().refract( transformedNormalView, materialRefractionRatio ); + +const reflectVector = /*@__PURE__*/ reflectView.transformDirection( cameraViewMatrix ).toVar( 'reflectVector' ); +const refractVector = /*@__PURE__*/ refractView.transformDirection( cameraViewMatrix ).toVar( 'reflectVector' ); + +class CubeTextureNode extends TextureNode { + + static get type() { + + return 'CubeTextureNode'; + + } + + constructor( value, uvNode = null, levelNode = null, biasNode = null ) { + + super( value, uvNode, levelNode, biasNode ); + + this.isCubeTextureNode = true; + + } + + getInputType( /*builder*/ ) { + + return 'cubeTexture'; + + } + + getDefaultUV() { + + const texture = this.value; + + if ( texture.mapping === CubeReflectionMapping ) { + + return reflectVector; + + } else if ( texture.mapping === CubeRefractionMapping ) { + + return refractVector; + + } else { + + console.error( 'THREE.CubeTextureNode: Mapping "%s" not supported.', texture.mapping ); + + return vec3( 0, 0, 0 ); + + } + + } + + setUpdateMatrix( /*updateMatrix*/ ) { } // Ignore .updateMatrix for CubeTextureNode + + setupUV( builder, uvNode ) { + + const texture = this.value; + + if ( builder.renderer.coordinateSystem === WebGPUCoordinateSystem || ! texture.isRenderTargetTexture ) { + + return vec3( uvNode.x.negate(), uvNode.yz ); + + } else { + + return uvNode; + + } + + } + + generateUV( builder, cubeUV ) { + + return cubeUV.build( builder, 'vec3' ); + + } + +} + +const cubeTexture = /*@__PURE__*/ nodeProxy( CubeTextureNode ); + +class BufferNode extends UniformNode { + + static get type() { + + return 'BufferNode'; + + } + + constructor( value, bufferType, bufferCount = 0 ) { + + super( value, bufferType ); + + this.isBufferNode = true; + + this.bufferType = bufferType; + this.bufferCount = bufferCount; + + } + + getElementType( builder ) { + + return this.getNodeType( builder ); + + } + + getInputType( /*builder*/ ) { + + return 'buffer'; + + } + +} + +const buffer = ( value, type, count ) => nodeObject( new BufferNode( value, type, count ) ); + +class UniformArrayElementNode extends ArrayElementNode { + + static get type() { + + return 'UniformArrayElementNode'; + + } + + constructor( arrayBuffer, indexNode ) { + + super( arrayBuffer, indexNode ); + + this.isArrayBufferElementNode = true; + + } + + generate( builder ) { + + const snippet = super.generate( builder ); + const type = this.getNodeType(); + + return builder.format( snippet, 'vec4', type ); + + } + +} + +class UniformArrayNode extends BufferNode { + + static get type() { + + return 'UniformArrayNode'; + + } + + constructor( value, elementType = null ) { + + super( null, 'vec4' ); + + this.array = value; + this.elementType = elementType; + + this._elementType = null; + this._elementLength = 0; + + this.updateType = NodeUpdateType.RENDER; + + this.isArrayBufferNode = true; + + } + + getElementType() { + + return this.elementType || this._elementType; + + } + + getElementLength() { + + return this._elementLength; + + } + + update( /*frame*/ ) { + + const { array, value } = this; + + const elementLength = this.getElementLength(); + const elementType = this.getElementType(); + + if ( elementLength === 1 ) { + + for ( let i = 0; i < array.length; i ++ ) { + + const index = i * 4; + + value[ index ] = array[ i ]; + + } + + } else if ( elementType === 'color' ) { + + for ( let i = 0; i < array.length; i ++ ) { + + const index = i * 4; + const vector = array[ i ]; + + value[ index ] = vector.r; + value[ index + 1 ] = vector.g; + value[ index + 2 ] = vector.b || 0; + //value[ index + 3 ] = vector.a || 0; + + } + + } else { + + for ( let i = 0; i < array.length; i ++ ) { + + const index = i * 4; + const vector = array[ i ]; + + value[ index ] = vector.x; + value[ index + 1 ] = vector.y; + value[ index + 2 ] = vector.z || 0; + value[ index + 3 ] = vector.w || 0; + + } + + } + + } + + setup( builder ) { + + const length = this.array.length; + + this._elementType = this.elementType === null ? getValueType( this.array[ 0 ] ) : this.elementType; + this._elementLength = builder.getTypeLength( this._elementType ); + + let arrayType = Float32Array; + + if ( this._elementType.charAt( 0 ) === 'i' ) arrayType = Int32Array; + else if ( this._elementType.charAt( 0 ) === 'u' ) arrayType = Uint32Array; + + this.value = new arrayType( length * 4 ); + this.bufferCount = length; + this.bufferType = builder.changeComponentType( 'vec4', builder.getComponentType( this._elementType ) ); + + return super.setup( builder ); + + } + + element( indexNode ) { + + return nodeObject( new UniformArrayElementNode( this, nodeObject( indexNode ) ) ); + + } + +} + +const uniformArray = ( values, nodeType ) => nodeObject( new UniformArrayNode( values, nodeType ) ); + +// + +const uniforms = ( values, nodeType ) => { // @deprecated, r168 + + console.warn( 'TSL.UniformArrayNode: uniforms() has been renamed to uniformArray().' ); + return nodeObject( new UniformArrayNode( values, nodeType ) ); + +}; + +class ReferenceElementNode extends ArrayElementNode { + + static get type() { + + return 'ReferenceElementNode'; + + } + + constructor( referenceNode, indexNode ) { + + super( referenceNode, indexNode ); + + this.referenceNode = referenceNode; + + this.isReferenceElementNode = true; + + } + + getNodeType() { + + return this.referenceNode.uniformType; + + } + + generate( builder ) { + + const snippet = super.generate( builder ); + const arrayType = this.referenceNode.getNodeType(); + const elementType = this.getNodeType(); + + return builder.format( snippet, arrayType, elementType ); + + } + +} + +// TODO: Extends this from ReferenceBaseNode +class ReferenceNode extends Node { + + static get type() { + + return 'ReferenceNode'; + + } + + constructor( property, uniformType, object = null, count = null ) { + + super(); + + this.property = property; + this.uniformType = uniformType; + this.object = object; + this.count = count; + + this.properties = property.split( '.' ); + this.reference = object; + this.node = null; + this.group = null; + this.name = null; + + this.updateType = NodeUpdateType.OBJECT; + + } + + element( indexNode ) { + + return nodeObject( new ReferenceElementNode( this, nodeObject( indexNode ) ) ); + + } + + setGroup( group ) { + + this.group = group; + + return this; + + } + + label( name ) { + + this.name = name; + + return this; + + } + + setNodeType( uniformType ) { + + let node = null; + + if ( this.count !== null ) { + + node = buffer( null, uniformType, this.count ); + + } else if ( Array.isArray( this.getValueFromReference() ) ) { + + node = uniformArray( null, uniformType ); + + } else if ( uniformType === 'texture' ) { + + node = texture( null ); + + } else if ( uniformType === 'cubeTexture' ) { + + node = cubeTexture( null ); + + } else { + + node = uniform( null, uniformType ); + + } + + if ( this.group !== null ) { + + node.setGroup( this.group ); + + } + + if ( this.name !== null ) node.label( this.name ); + + this.node = node.getSelf(); + + } + + getNodeType( builder ) { + + if ( this.node === null ) { + + this.updateReference( builder ); + this.updateValue(); + + } + + return this.node.getNodeType( builder ); + + } + + getValueFromReference( object = this.reference ) { + + const { properties } = this; + + let value = object[ properties[ 0 ] ]; + + for ( let i = 1; i < properties.length; i ++ ) { + + value = value[ properties[ i ] ]; + + } + + return value; + + } + + updateReference( state ) { + + this.reference = this.object !== null ? this.object : state.object; + + return this.reference; + + } + + setup() { + + this.updateValue(); + + return this.node; + + } + + update( /*frame*/ ) { + + this.updateValue(); + + } + + updateValue() { + + if ( this.node === null ) this.setNodeType( this.uniformType ); + + const value = this.getValueFromReference(); + + if ( Array.isArray( value ) ) { + + this.node.array = value; + + } else { + + this.node.value = value; + + } + + } + +} + +const reference = ( name, type, object ) => nodeObject( new ReferenceNode( name, type, object ) ); +const referenceBuffer = ( name, type, count, object ) => nodeObject( new ReferenceNode( name, type, object, count ) ); + +class MaterialReferenceNode extends ReferenceNode { + + static get type() { + + return 'MaterialReferenceNode'; + + } + + constructor( property, inputType, material = null ) { + + super( property, inputType, material ); + + this.material = material; + + //this.updateType = NodeUpdateType.RENDER; + + this.isMaterialReferenceNode = true; + + } + + /*setNodeType( node ) { + + super.setNodeType( node ); + + this.node.groupNode = renderGroup; + + }*/ + + updateReference( state ) { + + this.reference = this.material !== null ? this.material : state.material; + + return this.reference; + + } + +} + +const materialReference = ( name, type, material ) => nodeObject( new MaterialReferenceNode( name, type, material ) ); + +const tangentGeometry = /*@__PURE__*/ Fn( ( builder ) => { + + if ( builder.geometry.hasAttribute( 'tangent' ) === false ) { + + builder.geometry.computeTangents(); + + } + + return attribute( 'tangent', 'vec4' ); + +} )(); + +const tangentLocal = /*@__PURE__*/ tangentGeometry.xyz.toVar( 'tangentLocal' ); +const tangentView = /*@__PURE__*/ modelViewMatrix.mul( vec4( tangentLocal, 0 ) ).xyz.varying( 'v_tangentView' ).normalize().toVar( 'tangentView' ); +const tangentWorld = /*@__PURE__*/ tangentView.transformDirection( cameraViewMatrix ).varying( 'v_tangentWorld' ).normalize().toVar( 'tangentWorld' ); +const transformedTangentView = /*@__PURE__*/ tangentView.toVar( 'transformedTangentView' ); +const transformedTangentWorld = /*@__PURE__*/ transformedTangentView.transformDirection( cameraViewMatrix ).normalize().toVar( 'transformedTangentWorld' ); + +const getBitangent = ( crossNormalTangent ) => crossNormalTangent.mul( tangentGeometry.w ).xyz; + +const bitangentGeometry = /*@__PURE__*/ varying( getBitangent( normalGeometry.cross( tangentGeometry ) ), 'v_bitangentGeometry' ).normalize().toVar( 'bitangentGeometry' ); +const bitangentLocal = /*@__PURE__*/ varying( getBitangent( normalLocal.cross( tangentLocal ) ), 'v_bitangentLocal' ).normalize().toVar( 'bitangentLocal' ); +const bitangentView = /*@__PURE__*/ varying( getBitangent( normalView.cross( tangentView ) ), 'v_bitangentView' ).normalize().toVar( 'bitangentView' ); +const bitangentWorld = /*@__PURE__*/ varying( getBitangent( normalWorld.cross( tangentWorld ) ), 'v_bitangentWorld' ).normalize().toVar( 'bitangentWorld' ); +const transformedBitangentView = /*@__PURE__*/ getBitangent( transformedNormalView.cross( transformedTangentView ) ).normalize().toVar( 'transformedBitangentView' ); +const transformedBitangentWorld = /*@__PURE__*/ transformedBitangentView.transformDirection( cameraViewMatrix ).normalize().toVar( 'transformedBitangentWorld' ); + +const TBNViewMatrix = /*@__PURE__*/ mat3( tangentView, bitangentView, normalView ); + +const parallaxDirection = /*@__PURE__*/ positionViewDirection.mul( TBNViewMatrix )/*.normalize()*/; +const parallaxUV = ( uv, scale ) => uv.sub( parallaxDirection.mul( scale ) ); + +const transformedBentNormalView = /*@__PURE__*/ ( () => { + + // https://google.github.io/filament/Filament.md.html#lighting/imagebasedlights/anisotropy + + let bentNormal = anisotropyB.cross( positionViewDirection ); + bentNormal = bentNormal.cross( anisotropyB ).normalize(); + bentNormal = mix( bentNormal, transformedNormalView, anisotropy.mul( roughness.oneMinus() ).oneMinus().pow2().pow2() ).normalize(); + + return bentNormal; + + +} )(); + +// Normal Mapping Without Precomputed Tangents +// http://www.thetenthplanet.de/archives/1180 + +const perturbNormal2Arb = /*@__PURE__*/ Fn( ( inputs ) => { + + const { eye_pos, surf_norm, mapN, uv } = inputs; + + const q0 = eye_pos.dFdx(); + const q1 = eye_pos.dFdy(); + const st0 = uv.dFdx(); + const st1 = uv.dFdy(); + + const N = surf_norm; // normalized + + const q1perp = q1.cross( N ); + const q0perp = N.cross( q0 ); + + const T = q1perp.mul( st0.x ).add( q0perp.mul( st1.x ) ); + const B = q1perp.mul( st0.y ).add( q0perp.mul( st1.y ) ); + + const det = T.dot( T ).max( B.dot( B ) ); + const scale = faceDirection.mul( det.inverseSqrt() ); + + return add( T.mul( mapN.x, scale ), B.mul( mapN.y, scale ), N.mul( mapN.z ) ).normalize(); + +} ); + +class NormalMapNode extends TempNode { + + static get type() { + + return 'NormalMapNode'; + + } + + constructor( node, scaleNode = null ) { + + super( 'vec3' ); + + this.node = node; + this.scaleNode = scaleNode; + + this.normalMapType = TangentSpaceNormalMap; + + } + + setup( builder ) { + + const { normalMapType, scaleNode } = this; + + let normalMap = this.node.mul( 2.0 ).sub( 1.0 ); + + if ( scaleNode !== null ) { + + normalMap = vec3( normalMap.xy.mul( scaleNode ), normalMap.z ); + + } + + let outputNode = null; + + if ( normalMapType === ObjectSpaceNormalMap ) { + + outputNode = transformNormalToView( normalMap ); + + } else if ( normalMapType === TangentSpaceNormalMap ) { + + const tangent = builder.hasGeometryAttribute( 'tangent' ); + + if ( tangent === true ) { + + outputNode = TBNViewMatrix.mul( normalMap ).normalize(); + + } else { + + outputNode = perturbNormal2Arb( { + eye_pos: positionView, + surf_norm: normalView, + mapN: normalMap, + uv: uv() + } ); + + } + + } + + return outputNode; + + } + +} + +const normalMap = /*@__PURE__*/ nodeProxy( NormalMapNode ); + +// Bump Mapping Unparametrized Surfaces on the GPU by Morten S. Mikkelsen +// https://mmikk.github.io/papers3d/mm_sfgrad_bump.pdf + +const dHdxy_fwd = Fn( ( { textureNode, bumpScale } ) => { + + // It's used to preserve the same TextureNode instance + const sampleTexture = ( callback ) => textureNode.cache().context( { getUV: ( texNode ) => callback( texNode.uvNode || uv() ), forceUVContext: true } ); + + const Hll = float( sampleTexture( ( uvNode ) => uvNode ) ); + + return vec2( + float( sampleTexture( ( uvNode ) => uvNode.add( uvNode.dFdx() ) ) ).sub( Hll ), + float( sampleTexture( ( uvNode ) => uvNode.add( uvNode.dFdy() ) ) ).sub( Hll ) + ).mul( bumpScale ); + +} ); + +// Evaluate the derivative of the height w.r.t. screen-space using forward differencing (listing 2) + +const perturbNormalArb = Fn( ( inputs ) => { + + const { surf_pos, surf_norm, dHdxy } = inputs; + + // normalize is done to ensure that the bump map looks the same regardless of the texture's scale + const vSigmaX = surf_pos.dFdx().normalize(); + const vSigmaY = surf_pos.dFdy().normalize(); + const vN = surf_norm; // normalized + + const R1 = vSigmaY.cross( vN ); + const R2 = vN.cross( vSigmaX ); + + const fDet = vSigmaX.dot( R1 ).mul( faceDirection ); + + const vGrad = fDet.sign().mul( dHdxy.x.mul( R1 ).add( dHdxy.y.mul( R2 ) ) ); + + return fDet.abs().mul( surf_norm ).sub( vGrad ).normalize(); + +} ); + +class BumpMapNode extends TempNode { + + static get type() { + + return 'BumpMapNode'; + + } + + constructor( textureNode, scaleNode = null ) { + + super( 'vec3' ); + + this.textureNode = textureNode; + this.scaleNode = scaleNode; + + } + + setup() { + + const bumpScale = this.scaleNode !== null ? this.scaleNode : 1; + const dHdxy = dHdxy_fwd( { textureNode: this.textureNode, bumpScale } ); + + return perturbNormalArb( { + surf_pos: positionView, + surf_norm: normalView, + dHdxy + } ); + + } + +} + +const bumpMap = /*@__PURE__*/ nodeProxy( BumpMapNode ); + +const _propertyCache = new Map(); + +class MaterialNode extends Node { + + static get type() { + + return 'MaterialNode'; + + } + + constructor( scope ) { + + super(); + + this.scope = scope; + + } + + getCache( property, type ) { + + let node = _propertyCache.get( property ); + + if ( node === undefined ) { + + node = materialReference( property, type ); + + _propertyCache.set( property, node ); + + } + + return node; + + } + + getFloat( property ) { + + return this.getCache( property, 'float' ); + + } + + getColor( property ) { + + return this.getCache( property, 'color' ); + + } + + getTexture( property ) { + + return this.getCache( property === 'map' ? 'map' : property + 'Map', 'texture' ); + + } + + setup( builder ) { + + const material = builder.context.material; + const scope = this.scope; + + let node = null; + + if ( scope === MaterialNode.COLOR ) { + + const colorNode = material.color !== undefined ? this.getColor( scope ) : vec3(); + + if ( material.map && material.map.isTexture === true ) { + + node = colorNode.mul( this.getTexture( 'map' ) ); + + } else { + + node = colorNode; + + } + + } else if ( scope === MaterialNode.OPACITY ) { + + const opacityNode = this.getFloat( scope ); + + if ( material.alphaMap && material.alphaMap.isTexture === true ) { + + node = opacityNode.mul( this.getTexture( 'alpha' ) ); + + } else { + + node = opacityNode; + + } + + } else if ( scope === MaterialNode.SPECULAR_STRENGTH ) { + + if ( material.specularMap && material.specularMap.isTexture === true ) { + + node = this.getTexture( 'specular' ).r; + + } else { + + node = float( 1 ); + + } + + } else if ( scope === MaterialNode.SPECULAR_INTENSITY ) { + + const specularIntensity = this.getFloat( scope ); + + if ( material.specularMap ) { + + node = specularIntensity.mul( this.getTexture( scope ).a ); + + } else { + + node = specularIntensity; + + } + + } else if ( scope === MaterialNode.SPECULAR_COLOR ) { + + const specularColorNode = this.getColor( scope ); + + if ( material.specularColorMap && material.specularColorMap.isTexture === true ) { + + node = specularColorNode.mul( this.getTexture( scope ).rgb ); + + } else { + + node = specularColorNode; + + } + + } else if ( scope === MaterialNode.ROUGHNESS ) { // TODO: cleanup similar branches + + const roughnessNode = this.getFloat( scope ); + + if ( material.roughnessMap && material.roughnessMap.isTexture === true ) { + + node = roughnessNode.mul( this.getTexture( scope ).g ); + + } else { + + node = roughnessNode; + + } + + } else if ( scope === MaterialNode.METALNESS ) { + + const metalnessNode = this.getFloat( scope ); + + if ( material.metalnessMap && material.metalnessMap.isTexture === true ) { + + node = metalnessNode.mul( this.getTexture( scope ).b ); + + } else { + + node = metalnessNode; + + } + + } else if ( scope === MaterialNode.EMISSIVE ) { + + const emissiveIntensityNode = this.getFloat( 'emissiveIntensity' ); + const emissiveNode = this.getColor( scope ).mul( emissiveIntensityNode ); + + if ( material.emissiveMap && material.emissiveMap.isTexture === true ) { + + node = emissiveNode.mul( this.getTexture( scope ) ); + + } else { + + node = emissiveNode; + + } + + } else if ( scope === MaterialNode.NORMAL ) { + + if ( material.normalMap ) { + + node = normalMap( this.getTexture( 'normal' ), this.getCache( 'normalScale', 'vec2' ) ); + node.normalMapType = material.normalMapType; + + } else if ( material.bumpMap ) { + + node = bumpMap( this.getTexture( 'bump' ).r, this.getFloat( 'bumpScale' ) ); + + } else { + + node = normalView; + + } + + } else if ( scope === MaterialNode.CLEARCOAT ) { + + const clearcoatNode = this.getFloat( scope ); + + if ( material.clearcoatMap && material.clearcoatMap.isTexture === true ) { + + node = clearcoatNode.mul( this.getTexture( scope ).r ); + + } else { + + node = clearcoatNode; + + } + + } else if ( scope === MaterialNode.CLEARCOAT_ROUGHNESS ) { + + const clearcoatRoughnessNode = this.getFloat( scope ); + + if ( material.clearcoatRoughnessMap && material.clearcoatRoughnessMap.isTexture === true ) { + + node = clearcoatRoughnessNode.mul( this.getTexture( scope ).r ); + + } else { + + node = clearcoatRoughnessNode; + + } + + } else if ( scope === MaterialNode.CLEARCOAT_NORMAL ) { + + if ( material.clearcoatNormalMap ) { + + node = normalMap( this.getTexture( scope ), this.getCache( scope + 'Scale', 'vec2' ) ); + + } else { + + node = normalView; + + } + + } else if ( scope === MaterialNode.SHEEN ) { + + const sheenNode = this.getColor( 'sheenColor' ).mul( this.getFloat( 'sheen' ) ); // Move this mul() to CPU + + if ( material.sheenColorMap && material.sheenColorMap.isTexture === true ) { + + node = sheenNode.mul( this.getTexture( 'sheenColor' ).rgb ); + + } else { + + node = sheenNode; + + } + + } else if ( scope === MaterialNode.SHEEN_ROUGHNESS ) { + + const sheenRoughnessNode = this.getFloat( scope ); + + if ( material.sheenRoughnessMap && material.sheenRoughnessMap.isTexture === true ) { + + node = sheenRoughnessNode.mul( this.getTexture( scope ).a ); + + } else { + + node = sheenRoughnessNode; + + } + + node = node.clamp( 0.07, 1.0 ); + + } else if ( scope === MaterialNode.ANISOTROPY ) { + + if ( material.anisotropyMap && material.anisotropyMap.isTexture === true ) { + + const anisotropyPolar = this.getTexture( scope ); + const anisotropyMat = mat2( materialAnisotropyVector.x, materialAnisotropyVector.y, materialAnisotropyVector.y.negate(), materialAnisotropyVector.x ); + + node = anisotropyMat.mul( anisotropyPolar.rg.mul( 2.0 ).sub( vec2( 1.0 ) ).normalize().mul( anisotropyPolar.b ) ); + + } else { + + node = materialAnisotropyVector; + + } + + } else if ( scope === MaterialNode.IRIDESCENCE_THICKNESS ) { + + const iridescenceThicknessMaximum = reference( '1', 'float', material.iridescenceThicknessRange ); + + if ( material.iridescenceThicknessMap ) { + + const iridescenceThicknessMinimum = reference( '0', 'float', material.iridescenceThicknessRange ); + + node = iridescenceThicknessMaximum.sub( iridescenceThicknessMinimum ).mul( this.getTexture( scope ).g ).add( iridescenceThicknessMinimum ); + + } else { + + node = iridescenceThicknessMaximum; + + } + + } else if ( scope === MaterialNode.TRANSMISSION ) { + + const transmissionNode = this.getFloat( scope ); + + if ( material.transmissionMap ) { + + node = transmissionNode.mul( this.getTexture( scope ).r ); + + } else { + + node = transmissionNode; + + } + + } else if ( scope === MaterialNode.THICKNESS ) { + + const thicknessNode = this.getFloat( scope ); + + if ( material.thicknessMap ) { + + node = thicknessNode.mul( this.getTexture( scope ).g ); + + } else { + + node = thicknessNode; + + } + + } else if ( scope === MaterialNode.IOR ) { + + node = this.getFloat( scope ); + + } else if ( scope === MaterialNode.LIGHT_MAP ) { + + node = this.getTexture( scope ).rgb.mul( this.getFloat( 'lightMapIntensity' ) ); + + } else if ( scope === MaterialNode.AO_MAP ) { + + node = this.getTexture( scope ).r.sub( 1.0 ).mul( this.getFloat( 'aoMapIntensity' ) ).add( 1.0 ); + + } else { + + const outputType = this.getNodeType( builder ); + + node = this.getCache( scope, outputType ); + + } + + return node; + + } + +} + +MaterialNode.ALPHA_TEST = 'alphaTest'; +MaterialNode.COLOR = 'color'; +MaterialNode.OPACITY = 'opacity'; +MaterialNode.SHININESS = 'shininess'; +MaterialNode.SPECULAR = 'specular'; +MaterialNode.SPECULAR_STRENGTH = 'specularStrength'; +MaterialNode.SPECULAR_INTENSITY = 'specularIntensity'; +MaterialNode.SPECULAR_COLOR = 'specularColor'; +MaterialNode.REFLECTIVITY = 'reflectivity'; +MaterialNode.ROUGHNESS = 'roughness'; +MaterialNode.METALNESS = 'metalness'; +MaterialNode.NORMAL = 'normal'; +MaterialNode.CLEARCOAT = 'clearcoat'; +MaterialNode.CLEARCOAT_ROUGHNESS = 'clearcoatRoughness'; +MaterialNode.CLEARCOAT_NORMAL = 'clearcoatNormal'; +MaterialNode.EMISSIVE = 'emissive'; +MaterialNode.ROTATION = 'rotation'; +MaterialNode.SHEEN = 'sheen'; +MaterialNode.SHEEN_ROUGHNESS = 'sheenRoughness'; +MaterialNode.ANISOTROPY = 'anisotropy'; +MaterialNode.IRIDESCENCE = 'iridescence'; +MaterialNode.IRIDESCENCE_IOR = 'iridescenceIOR'; +MaterialNode.IRIDESCENCE_THICKNESS = 'iridescenceThickness'; +MaterialNode.IOR = 'ior'; +MaterialNode.TRANSMISSION = 'transmission'; +MaterialNode.THICKNESS = 'thickness'; +MaterialNode.ATTENUATION_DISTANCE = 'attenuationDistance'; +MaterialNode.ATTENUATION_COLOR = 'attenuationColor'; +MaterialNode.LINE_SCALE = 'scale'; +MaterialNode.LINE_DASH_SIZE = 'dashSize'; +MaterialNode.LINE_GAP_SIZE = 'gapSize'; +MaterialNode.LINE_WIDTH = 'linewidth'; +MaterialNode.LINE_DASH_OFFSET = 'dashOffset'; +MaterialNode.POINT_WIDTH = 'pointWidth'; +MaterialNode.DISPERSION = 'dispersion'; +MaterialNode.LIGHT_MAP = 'light'; +MaterialNode.AO_MAP = 'ao'; + +const materialAlphaTest = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ALPHA_TEST ); +const materialColor = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.COLOR ); +const materialShininess = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SHININESS ); +const materialEmissive = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.EMISSIVE ); +const materialOpacity = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.OPACITY ); +const materialSpecular = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR ); + +const materialSpecularIntensity = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR_INTENSITY ); +const materialSpecularColor = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR_COLOR ); + +const materialSpecularStrength = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SPECULAR_STRENGTH ); +const materialReflectivity = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.REFLECTIVITY ); +const materialRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ROUGHNESS ); +const materialMetalness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.METALNESS ); +const materialNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.NORMAL ).context( { getUV: null } ); +const materialClearcoat = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT ); +const materialClearcoatRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_ROUGHNESS ); +const materialClearcoatNormal = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.CLEARCOAT_NORMAL ).context( { getUV: null } ); +const materialRotation = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ROTATION ); +const materialSheen = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SHEEN ); +const materialSheenRoughness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.SHEEN_ROUGHNESS ); +const materialAnisotropy = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ANISOTROPY ); +const materialIridescence = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE ); +const materialIridescenceIOR = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE_IOR ); +const materialIridescenceThickness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.IRIDESCENCE_THICKNESS ); +const materialTransmission = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.TRANSMISSION ); +const materialThickness = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.THICKNESS ); +const materialIOR = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.IOR ); +const materialAttenuationDistance = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ATTENUATION_DISTANCE ); +const materialAttenuationColor = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.ATTENUATION_COLOR ); +const materialLineScale = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_SCALE ); +const materialLineDashSize = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_DASH_SIZE ); +const materialLineGapSize = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_GAP_SIZE ); +const materialLineWidth = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_WIDTH ); +const materialLineDashOffset = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LINE_DASH_OFFSET ); +const materialPointWidth = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.POINT_WIDTH ); +const materialDispersion = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.DISPERSION ); +const materialLightMap = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.LIGHT_MAP ); +const materialAOMap = /*@__PURE__*/ nodeImmutable( MaterialNode, MaterialNode.AO_MAP ); +const materialAnisotropyVector = /*@__PURE__*/ uniform( new Vector2() ).onReference( function ( frame ) { + + return frame.material; + +} ).onRenderUpdate( function ( { material } ) { + + this.value.set( material.anisotropy * Math.cos( material.anisotropyRotation ), material.anisotropy * Math.sin( material.anisotropyRotation ) ); + +} ); + +class ModelViewProjectionNode extends TempNode { + + static get type() { + + return 'ModelViewProjectionNode'; + + } + + constructor( positionNode = null ) { + + super( 'vec4' ); + + this.positionNode = positionNode; + + } + + setup( builder ) { + + if ( builder.shaderStage === 'fragment' ) { + + return varying( builder.context.mvp ); + + } + + const position = this.positionNode || positionLocal; + const viewMatrix = builder.renderer.nodes.modelViewMatrix || modelViewMatrix; + + return cameraProjectionMatrix.mul( viewMatrix ).mul( position ); + + } + +} + +const modelViewProjection = /*@__PURE__*/ nodeProxy( ModelViewProjectionNode ); + +class IndexNode extends Node { + + static get type() { + + return 'IndexNode'; + + } + + constructor( scope ) { + + super( 'uint' ); + + this.scope = scope; + + this.isInstanceIndexNode = true; + + } + + generate( builder ) { + + const nodeType = this.getNodeType( builder ); + const scope = this.scope; + + let propertyName; + + if ( scope === IndexNode.VERTEX ) { + + // The index of a vertex within a mesh. + propertyName = builder.getVertexIndex(); + + } else if ( scope === IndexNode.INSTANCE ) { + + // The index of either a mesh instance or an invocation of a compute shader. + propertyName = builder.getInstanceIndex(); + + } else if ( scope === IndexNode.DRAW ) { + + // The index of a draw call. + propertyName = builder.getDrawIndex(); + + } else if ( scope === IndexNode.INVOCATION_LOCAL ) { + + // The index of a compute invocation within the scope of a workgroup load. + propertyName = builder.getInvocationLocalIndex(); + + } else if ( scope === IndexNode.INVOCATION_SUBGROUP ) { + + // The index of a compute invocation within the scope of a subgroup. + propertyName = builder.getInvocationSubgroupIndex(); + + } else if ( scope === IndexNode.SUBGROUP ) { + + // The index of the subgroup the current compute invocation belongs to. + propertyName = builder.getSubgroupIndex(); + + } else { + + throw new Error( 'THREE.IndexNode: Unknown scope: ' + scope ); + + } + + let output; + + if ( builder.shaderStage === 'vertex' || builder.shaderStage === 'compute' ) { + + output = propertyName; + + } else { + + const nodeVarying = varying( this ); + + output = nodeVarying.build( builder, nodeType ); + + } + + return output; + + } + +} + +IndexNode.VERTEX = 'vertex'; +IndexNode.INSTANCE = 'instance'; +IndexNode.SUBGROUP = 'subgroup'; +IndexNode.INVOCATION_LOCAL = 'invocationLocal'; +IndexNode.INVOCATION_SUBGROUP = 'invocationSubgroup'; +IndexNode.DRAW = 'draw'; + +const vertexIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.VERTEX ); +const instanceIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.INSTANCE ); +const subgroupIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.SUBGROUP ); +const invocationSubgroupIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.INVOCATION_SUBGROUP ); +const invocationLocalIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.INVOCATION_LOCAL ); +const drawIndex = /*@__PURE__*/ nodeImmutable( IndexNode, IndexNode.DRAW ); + +class InstanceNode extends Node { + + static get type() { + + return 'InstanceNode'; + + } + + constructor( instanceMesh ) { + + super( 'void' ); + + this.instanceMesh = instanceMesh; + + this.instanceMatrixNode = null; + + this.instanceColorNode = null; + + this.updateType = NodeUpdateType.FRAME; + + this.buffer = null; + this.bufferColor = null; + + } + + setup( builder ) { + + let instanceMatrixNode = this.instanceMatrixNode; + let instanceColorNode = this.instanceColorNode; + + const instanceMesh = this.instanceMesh; + + if ( instanceMatrixNode === null ) { + + const instanceAttribute = instanceMesh.instanceMatrix; + + // Both WebGPU and WebGL backends have UBO max limited to 64kb. Matrix count number bigger than 1000 ( 16 * 4 * 1000 = 64kb ) will fallback to attribute. + + if ( instanceMesh.count <= 1000 ) { + + instanceMatrixNode = buffer( instanceAttribute.array, 'mat4', Math.max( instanceMesh.count, 1 ) ).element( instanceIndex ); + + } else { + + const buffer = new InstancedInterleavedBuffer( instanceAttribute.array, 16, 1 ); + + this.buffer = buffer; + + const bufferFn = instanceAttribute.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute; + + const instanceBuffers = [ + // F.Signature -> bufferAttribute( array, type, stride, offset ) + bufferFn( buffer, 'vec4', 16, 0 ), + bufferFn( buffer, 'vec4', 16, 4 ), + bufferFn( buffer, 'vec4', 16, 8 ), + bufferFn( buffer, 'vec4', 16, 12 ) + ]; + + instanceMatrixNode = mat4( ...instanceBuffers ); + + } + + this.instanceMatrixNode = instanceMatrixNode; + + } + + const instanceColorAttribute = instanceMesh.instanceColor; + + if ( instanceColorAttribute && instanceColorNode === null ) { + + const buffer = new InstancedBufferAttribute( instanceColorAttribute.array, 3 ); + + const bufferFn = instanceColorAttribute.usage === DynamicDrawUsage ? instancedDynamicBufferAttribute : instancedBufferAttribute; + + this.bufferColor = buffer; + + instanceColorNode = vec3( bufferFn( buffer, 'vec3', 3, 0 ) ); + + this.instanceColorNode = instanceColorNode; + + } + + // POSITION + + const instancePosition = instanceMatrixNode.mul( positionLocal ).xyz; + positionLocal.assign( instancePosition ); + + // NORMAL + + if ( builder.hasGeometryAttribute( 'normal' ) ) { + + const instanceNormal = transformNormal( normalLocal, instanceMatrixNode ); + + // ASSIGNS + + normalLocal.assign( instanceNormal ); + + } + + // COLOR + + if ( this.instanceColorNode !== null ) { + + varyingProperty( 'vec3', 'vInstanceColor' ).assign( this.instanceColorNode ); + + } + + } + + update( /*frame*/ ) { + + if ( this.instanceMesh.instanceMatrix.usage !== DynamicDrawUsage && this.buffer != null && this.instanceMesh.instanceMatrix.version !== this.buffer.version ) { + + this.buffer.version = this.instanceMesh.instanceMatrix.version; + + } + + if ( this.instanceMesh.instanceColor && this.instanceMesh.instanceColor.usage !== DynamicDrawUsage && this.bufferColor != null && this.instanceMesh.instanceColor.version !== this.bufferColor.version ) { + + this.bufferColor.version = this.instanceMesh.instanceColor.version; + + } + + } + +} + +const instance = /*@__PURE__*/ nodeProxy( InstanceNode ); + +class BatchNode extends Node { + + static get type() { + + return 'BatchNode'; + + } + + constructor( batchMesh ) { + + super( 'void' ); + + this.batchMesh = batchMesh; + + + this.batchingIdNode = null; + + } + + setup( builder ) { + + // POSITION + + if ( this.batchingIdNode === null ) { + + if ( builder.getDrawIndex() === null ) { + + this.batchingIdNode = instanceIndex; + + } else { + + this.batchingIdNode = drawIndex; + + } + + } + + const getIndirectIndex = Fn( ( [ id ] ) => { + + const size = textureSize( textureLoad( this.batchMesh._indirectTexture ), 0 ); + const x = int( id ).modInt( int( size ) ); + const y = int( id ).div( int( size ) ); + return textureLoad( this.batchMesh._indirectTexture, ivec2( x, y ) ).x; + + } ).setLayout( { + name: 'getIndirectIndex', + type: 'uint', + inputs: [ + { name: 'id', type: 'int' } + ] + } ); + + const indirectId = getIndirectIndex( int( this.batchingIdNode ) ); + + const matricesTexture = this.batchMesh._matricesTexture; + + const size = textureSize( textureLoad( matricesTexture ), 0 ); + const j = float( indirectId ).mul( 4 ).toInt().toVar(); + + const x = j.modInt( size ); + const y = j.div( int( size ) ); + const batchingMatrix = mat4( + textureLoad( matricesTexture, ivec2( x, y ) ), + textureLoad( matricesTexture, ivec2( x.add( 1 ), y ) ), + textureLoad( matricesTexture, ivec2( x.add( 2 ), y ) ), + textureLoad( matricesTexture, ivec2( x.add( 3 ), y ) ) + ); + + + const colorsTexture = this.batchMesh._colorsTexture; + + if ( colorsTexture !== null ) { + + const getBatchingColor = Fn( ( [ id ] ) => { + + const size = textureSize( textureLoad( colorsTexture ), 0 ).x; + const j = id; + const x = j.modInt( size ); + const y = j.div( size ); + return textureLoad( colorsTexture, ivec2( x, y ) ).rgb; + + } ).setLayout( { + name: 'getBatchingColor', + type: 'vec3', + inputs: [ + { name: 'id', type: 'int' } + ] + } ); + + const color = getBatchingColor( indirectId ); + + varyingProperty( 'vec3', 'vBatchColor' ).assign( color ); + + } + + const bm = mat3( batchingMatrix ); + + positionLocal.assign( batchingMatrix.mul( positionLocal ) ); + + const transformedNormal = normalLocal.div( vec3( bm[ 0 ].dot( bm[ 0 ] ), bm[ 1 ].dot( bm[ 1 ] ), bm[ 2 ].dot( bm[ 2 ] ) ) ); + + const batchingNormal = bm.mul( transformedNormal ).xyz; + + normalLocal.assign( batchingNormal ); + + if ( builder.hasGeometryAttribute( 'tangent' ) ) { + + tangentLocal.mulAssign( bm ); + + } + + } + +} + +const batch = /*@__PURE__*/ nodeProxy( BatchNode ); + +const _frameId = new WeakMap(); + +class SkinningNode extends Node { + + static get type() { + + return 'SkinningNode'; + + } + + constructor( skinnedMesh, useReference = false ) { + + super( 'void' ); + + this.skinnedMesh = skinnedMesh; + this.useReference = useReference; + + this.updateType = NodeUpdateType.OBJECT; + + // + + this.skinIndexNode = attribute( 'skinIndex', 'uvec4' ); + this.skinWeightNode = attribute( 'skinWeight', 'vec4' ); + + let bindMatrixNode, bindMatrixInverseNode, boneMatricesNode; + + if ( useReference ) { + + bindMatrixNode = reference( 'bindMatrix', 'mat4' ); + bindMatrixInverseNode = reference( 'bindMatrixInverse', 'mat4' ); + boneMatricesNode = referenceBuffer( 'skeleton.boneMatrices', 'mat4', skinnedMesh.skeleton.bones.length ); + + } else { + + bindMatrixNode = uniform( skinnedMesh.bindMatrix, 'mat4' ); + bindMatrixInverseNode = uniform( skinnedMesh.bindMatrixInverse, 'mat4' ); + boneMatricesNode = buffer( skinnedMesh.skeleton.boneMatrices, 'mat4', skinnedMesh.skeleton.bones.length ); + + } + + this.bindMatrixNode = bindMatrixNode; + this.bindMatrixInverseNode = bindMatrixInverseNode; + this.boneMatricesNode = boneMatricesNode; + this.previousBoneMatricesNode = null; + + } + + getSkinnedPosition( boneMatrices = this.boneMatricesNode, position = positionLocal ) { + + const { skinIndexNode, skinWeightNode, bindMatrixNode, bindMatrixInverseNode } = this; + + const boneMatX = boneMatrices.element( skinIndexNode.x ); + const boneMatY = boneMatrices.element( skinIndexNode.y ); + const boneMatZ = boneMatrices.element( skinIndexNode.z ); + const boneMatW = boneMatrices.element( skinIndexNode.w ); + + // POSITION + + const skinVertex = bindMatrixNode.mul( position ); + + const skinned = add( + boneMatX.mul( skinWeightNode.x ).mul( skinVertex ), + boneMatY.mul( skinWeightNode.y ).mul( skinVertex ), + boneMatZ.mul( skinWeightNode.z ).mul( skinVertex ), + boneMatW.mul( skinWeightNode.w ).mul( skinVertex ) + ); + + return bindMatrixInverseNode.mul( skinned ).xyz; + + } + + getSkinnedNormal( boneMatrices = this.boneMatricesNode, normal = normalLocal ) { + + const { skinIndexNode, skinWeightNode, bindMatrixNode, bindMatrixInverseNode } = this; + + const boneMatX = boneMatrices.element( skinIndexNode.x ); + const boneMatY = boneMatrices.element( skinIndexNode.y ); + const boneMatZ = boneMatrices.element( skinIndexNode.z ); + const boneMatW = boneMatrices.element( skinIndexNode.w ); + + // NORMAL + + let skinMatrix = add( + skinWeightNode.x.mul( boneMatX ), + skinWeightNode.y.mul( boneMatY ), + skinWeightNode.z.mul( boneMatZ ), + skinWeightNode.w.mul( boneMatW ) + ); + + skinMatrix = bindMatrixInverseNode.mul( skinMatrix ).mul( bindMatrixNode ); + + return skinMatrix.transformDirection( normal ).xyz; + + } + + getPreviousSkinnedPosition( builder ) { + + const skinnedMesh = builder.object; + + if ( this.previousBoneMatricesNode === null ) { + + skinnedMesh.skeleton.previousBoneMatrices = new Float32Array( skinnedMesh.skeleton.boneMatrices ); + + this.previousBoneMatricesNode = referenceBuffer( 'skeleton.previousBoneMatrices', 'mat4', skinnedMesh.skeleton.bones.length ); + + } + + return this.getSkinnedPosition( this.previousBoneMatricesNode, positionPrevious ); + + } + + needsPreviousBoneMatrices( builder ) { + + const mrt = builder.renderer.getMRT(); + + return mrt && mrt.has( 'velocity' ); + + } + + setup( builder ) { + + if ( this.needsPreviousBoneMatrices( builder ) ) { + + positionPrevious.assign( this.getPreviousSkinnedPosition( builder ) ); + + } + + const skinPosition = this.getSkinnedPosition(); + + + positionLocal.assign( skinPosition ); + + if ( builder.hasGeometryAttribute( 'normal' ) ) { + + const skinNormal = this.getSkinnedNormal(); + + normalLocal.assign( skinNormal ); + + if ( builder.hasGeometryAttribute( 'tangent' ) ) { + + tangentLocal.assign( skinNormal ); + + } + + } + + } + + generate( builder, output ) { + + if ( output !== 'void' ) { + + return positionLocal.build( builder, output ); + + } + + } + + update( frame ) { + + const object = this.useReference ? frame.object : this.skinnedMesh; + const skeleton = object.skeleton; + + if ( _frameId.get( skeleton ) === frame.frameId ) return; + + _frameId.set( skeleton, frame.frameId ); + + if ( this.previousBoneMatricesNode !== null ) skeleton.previousBoneMatrices.set( skeleton.boneMatrices ); + + skeleton.update(); + + } + +} + +const skinning = ( skinnedMesh ) => nodeObject( new SkinningNode( skinnedMesh ) ); +const skinningReference = ( skinnedMesh ) => nodeObject( new SkinningNode( skinnedMesh, true ) ); + +class LoopNode extends Node { + + static get type() { + + return 'LoopNode'; + + } + + constructor( params = [] ) { + + super(); + + this.params = params; + + } + + getVarName( index ) { + + return String.fromCharCode( 'i'.charCodeAt() + index ); + + } + + getProperties( builder ) { + + const properties = builder.getNodeProperties( this ); + + if ( properties.stackNode !== undefined ) return properties; + + // + + const inputs = {}; + + for ( let i = 0, l = this.params.length - 1; i < l; i ++ ) { + + const param = this.params[ i ]; + + const name = ( param.isNode !== true && param.name ) || this.getVarName( i ); + const type = ( param.isNode !== true && param.type ) || 'int'; + + inputs[ name ] = expression( name, type ); + + } + + const stack = builder.addStack(); // TODO: cache() it + + properties.returnsNode = this.params[ this.params.length - 1 ]( inputs, stack, builder ); + properties.stackNode = stack; + + builder.removeStack(); + + return properties; + + } + + getNodeType( builder ) { + + const { returnsNode } = this.getProperties( builder ); + + return returnsNode ? returnsNode.getNodeType( builder ) : 'void'; + + } + + setup( builder ) { + + // setup properties + + this.getProperties( builder ); + + } + + generate( builder ) { + + const properties = this.getProperties( builder ); + + const params = this.params; + const stackNode = properties.stackNode; + + for ( let i = 0, l = params.length - 1; i < l; i ++ ) { + + const param = params[ i ]; + + let start = null, end = null, name = null, type = null, condition = null, update = null; + + if ( param.isNode ) { + + type = 'int'; + name = this.getVarName( i ); + start = '0'; + end = param.build( builder, type ); + condition = '<'; + + } else { + + type = param.type || 'int'; + name = param.name || this.getVarName( i ); + start = param.start; + end = param.end; + condition = param.condition; + update = param.update; + + if ( typeof start === 'number' ) start = start.toString(); + else if ( start && start.isNode ) start = start.build( builder, type ); + + if ( typeof end === 'number' ) end = end.toString(); + else if ( end && end.isNode ) end = end.build( builder, type ); + + if ( start !== undefined && end === undefined ) { + + start = start + ' - 1'; + end = '0'; + condition = '>='; + + } else if ( end !== undefined && start === undefined ) { + + start = '0'; + condition = '<'; + + } + + if ( condition === undefined ) { + + if ( Number( start ) > Number( end ) ) { + + condition = '>='; + + } else { + + condition = '<'; + + } + + } + + } + + const internalParam = { start, end, condition }; + + // + + const startSnippet = internalParam.start; + const endSnippet = internalParam.end; + + let declarationSnippet = ''; + let conditionalSnippet = ''; + let updateSnippet = ''; + + if ( ! update ) { + + if ( type === 'int' || type === 'uint' ) { + + if ( condition.includes( '<' ) ) update = '++'; + else update = '--'; + + } else { + + if ( condition.includes( '<' ) ) update = '+= 1.'; + else update = '-= 1.'; + + } + + } + + declarationSnippet += builder.getVar( type, name ) + ' = ' + startSnippet; + + conditionalSnippet += name + ' ' + condition + ' ' + endSnippet; + updateSnippet += name + ' ' + update; + + const forSnippet = `for ( ${ declarationSnippet }; ${ conditionalSnippet }; ${ updateSnippet } )`; + + builder.addFlowCode( ( i === 0 ? '\n' : '' ) + builder.tab + forSnippet + ' {\n\n' ).addFlowTab(); + + } + + const stackSnippet = stackNode.build( builder, 'void' ); + + const returnsSnippet = properties.returnsNode ? properties.returnsNode.build( builder ) : ''; + + builder.removeFlowTab().addFlowCode( '\n' + builder.tab + stackSnippet ); + + for ( let i = 0, l = this.params.length - 1; i < l; i ++ ) { + + builder.addFlowCode( ( i === 0 ? '' : builder.tab ) + '}\n\n' ).removeFlowTab(); + + } + + builder.addFlowTab(); + + return returnsSnippet; + + } + +} + +const Loop = ( ...params ) => nodeObject( new LoopNode( nodeArray( params, 'int' ) ) ).append(); +const Continue = () => expression( 'continue' ).append(); +const Break = () => expression( 'break' ).append(); + +// + +const loop = ( ...params ) => { // @deprecated, r168 + + console.warn( 'TSL.LoopNode: loop() has been renamed to Loop().' ); + return Loop( ...params ); + +}; + +const _morphTextures = /*@__PURE__*/ new WeakMap(); +const _morphVec4 = /*@__PURE__*/ new Vector4(); + +const getMorph = /*@__PURE__*/ Fn( ( { bufferMap, influence, stride, width, depth, offset } ) => { + + const texelIndex = int( vertexIndex ).mul( stride ).add( offset ); + + const y = texelIndex.div( width ); + const x = texelIndex.sub( y.mul( width ) ); + + const bufferAttrib = textureLoad( bufferMap, ivec2( x, y ) ).depth( depth ); + + return bufferAttrib.mul( influence ); + +} ); + +function getEntry( geometry ) { + + const hasMorphPosition = geometry.morphAttributes.position !== undefined; + const hasMorphNormals = geometry.morphAttributes.normal !== undefined; + const hasMorphColors = geometry.morphAttributes.color !== undefined; + + // instead of using attributes, the WebGL 2 code path encodes morph targets + // into an array of data textures. Each layer represents a single morph target. + + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; + + let entry = _morphTextures.get( geometry ); + + if ( entry === undefined || entry.count !== morphTargetsCount ) { + + if ( entry !== undefined ) entry.texture.dispose(); + + const morphTargets = geometry.morphAttributes.position || []; + const morphNormals = geometry.morphAttributes.normal || []; + const morphColors = geometry.morphAttributes.color || []; + + let vertexDataCount = 0; + + if ( hasMorphPosition === true ) vertexDataCount = 1; + if ( hasMorphNormals === true ) vertexDataCount = 2; + if ( hasMorphColors === true ) vertexDataCount = 3; + + let width = geometry.attributes.position.count * vertexDataCount; + let height = 1; + + const maxTextureSize = 4096; // @TODO: Use 'capabilities.maxTextureSize' + + if ( width > maxTextureSize ) { + + height = Math.ceil( width / maxTextureSize ); + width = maxTextureSize; + + } + + const buffer = new Float32Array( width * height * 4 * morphTargetsCount ); + + const bufferTexture = new DataArrayTexture( buffer, width, height, morphTargetsCount ); + bufferTexture.type = FloatType; + bufferTexture.needsUpdate = true; + + // fill buffer + + const vertexDataStride = vertexDataCount * 4; + + for ( let i = 0; i < morphTargetsCount; i ++ ) { + + const morphTarget = morphTargets[ i ]; + const morphNormal = morphNormals[ i ]; + const morphColor = morphColors[ i ]; + + const offset = width * height * 4 * i; + + for ( let j = 0; j < morphTarget.count; j ++ ) { + + const stride = j * vertexDataStride; + + if ( hasMorphPosition === true ) { + + _morphVec4.fromBufferAttribute( morphTarget, j ); + + buffer[ offset + stride + 0 ] = _morphVec4.x; + buffer[ offset + stride + 1 ] = _morphVec4.y; + buffer[ offset + stride + 2 ] = _morphVec4.z; + buffer[ offset + stride + 3 ] = 0; + + } + + if ( hasMorphNormals === true ) { + + _morphVec4.fromBufferAttribute( morphNormal, j ); + + buffer[ offset + stride + 4 ] = _morphVec4.x; + buffer[ offset + stride + 5 ] = _morphVec4.y; + buffer[ offset + stride + 6 ] = _morphVec4.z; + buffer[ offset + stride + 7 ] = 0; + + } + + if ( hasMorphColors === true ) { + + _morphVec4.fromBufferAttribute( morphColor, j ); + + buffer[ offset + stride + 8 ] = _morphVec4.x; + buffer[ offset + stride + 9 ] = _morphVec4.y; + buffer[ offset + stride + 10 ] = _morphVec4.z; + buffer[ offset + stride + 11 ] = ( morphColor.itemSize === 4 ) ? _morphVec4.w : 1; + + } + + } + + } + + entry = { + count: morphTargetsCount, + texture: bufferTexture, + stride: vertexDataCount, + size: new Vector2( width, height ) + }; + + _morphTextures.set( geometry, entry ); + + function disposeTexture() { + + bufferTexture.dispose(); + + _morphTextures.delete( geometry ); + + geometry.removeEventListener( 'dispose', disposeTexture ); + + } + + geometry.addEventListener( 'dispose', disposeTexture ); + + } + + return entry; + +} + + +class MorphNode extends Node { + + static get type() { + + return 'MorphNode'; + + } + + constructor( mesh ) { + + super( 'void' ); + + this.mesh = mesh; + this.morphBaseInfluence = uniform( 1 ); + + this.updateType = NodeUpdateType.OBJECT; + + } + + setup( builder ) { + + const { geometry } = builder; + + const hasMorphPosition = geometry.morphAttributes.position !== undefined; + const hasMorphNormals = geometry.hasAttribute( 'normal' ) && geometry.morphAttributes.normal !== undefined; + + const morphAttribute = geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color; + const morphTargetsCount = ( morphAttribute !== undefined ) ? morphAttribute.length : 0; + + // nodes + + const { texture: bufferMap, stride, size } = getEntry( geometry ); + + if ( hasMorphPosition === true ) positionLocal.mulAssign( this.morphBaseInfluence ); + if ( hasMorphNormals === true ) normalLocal.mulAssign( this.morphBaseInfluence ); + + const width = int( size.width ); + + Loop( morphTargetsCount, ( { i } ) => { + + const influence = float( 0 ).toVar(); + + if ( this.mesh.count > 1 && ( this.mesh.morphTexture !== null && this.mesh.morphTexture !== undefined ) ) { + + influence.assign( textureLoad( this.mesh.morphTexture, ivec2( int( i ).add( 1 ), int( instanceIndex ) ) ).r ); + + } else { + + influence.assign( reference( 'morphTargetInfluences', 'float' ).element( i ).toVar() ); + + } + + if ( hasMorphPosition === true ) { + + positionLocal.addAssign( getMorph( { + bufferMap, + influence, + stride, + width, + depth: i, + offset: int( 0 ) + } ) ); + + } + + if ( hasMorphNormals === true ) { + + normalLocal.addAssign( getMorph( { + bufferMap, + influence, + stride, + width, + depth: i, + offset: int( 1 ) + } ) ); + + } + + } ); + + } + + update() { + + const morphBaseInfluence = this.morphBaseInfluence; + + if ( this.mesh.geometry.morphTargetsRelative ) { + + morphBaseInfluence.value = 1; + + } else { + + morphBaseInfluence.value = 1 - this.mesh.morphTargetInfluences.reduce( ( a, b ) => a + b, 0 ); + + } + + } + +} + +const morphReference = /*@__PURE__*/ nodeProxy( MorphNode ); + +const sortLights = ( lights ) => { + + return lights.sort( ( a, b ) => a.id - b.id ); + +}; + +const getLightNodeById = ( id, lightNodes ) => { + + for ( const lightNode of lightNodes ) { + + if ( lightNode.isAnalyticLightNode && lightNode.light.id === id ) { + + return lightNode; + + } + + } + + return null; + +}; + +const _lightsNodeRef = /*@__PURE__*/ new WeakMap(); + +class LightsNode extends Node { + + static get type() { + + return 'LightsNode'; + + } + + constructor( lights = [] ) { + + super( 'vec3' ); + + this.totalDiffuseNode = vec3().toVar( 'totalDiffuse' ); + this.totalSpecularNode = vec3().toVar( 'totalSpecular' ); + + this.outgoingLightNode = vec3().toVar( 'outgoingLight' ); + + this._lights = lights; + + this._lightNodes = null; + this._lightNodesHash = null; + + this.global = true; + + } + + getHash( builder ) { + + if ( this._lightNodesHash === null ) { + + if ( this._lightNodes === null ) this.setupLightsNode( builder ); + + const hash = []; + + for ( const lightNode of this._lightNodes ) { + + hash.push( lightNode.getHash() ); + + } + + this._lightNodesHash = 'lights-' + hash.join( ',' ); + + } + + return this._lightNodesHash; + + } + + analyze( builder ) { + + const properties = builder.getDataFromNode( this ); + + for ( const node of properties.nodes ) { + + node.build( builder ); + + } + + } + + setupLightsNode( builder ) { + + const lightNodes = []; + + const previousLightNodes = this._lightNodes; + + const lights = sortLights( this._lights ); + const nodeLibrary = builder.renderer.nodes.library; + + for ( const light of lights ) { + + if ( light.isNode ) { + + lightNodes.push( nodeObject( light ) ); + + } else { + + let lightNode = null; + + if ( previousLightNodes !== null ) { + + lightNode = getLightNodeById( light.id, previousLightNodes ); // resuse existing light node + + } + + if ( lightNode === null ) { + + const lightNodeClass = nodeLibrary.getLightNodeClass( light.constructor ); + + if ( lightNodeClass === null ) { + + console.warn( `LightsNode.setupNodeLights: Light node not found for ${ light.constructor.name }` ); + continue; + + } + + let lightNode = null; + + if ( ! _lightsNodeRef.has( light ) ) { + + lightNode = new lightNodeClass( light ); + _lightsNodeRef.set( light, lightNode ); + + } else { + + lightNode = _lightsNodeRef.get( light ); + + } + + lightNodes.push( lightNode ); + + } + + } + + } + + this._lightNodes = lightNodes; + + } + + setup( builder ) { + + if ( this._lightNodes === null ) this.setupLightsNode( builder ); + + const context = builder.context; + const lightingModel = context.lightingModel; + + let outgoingLightNode = this.outgoingLightNode; + + if ( lightingModel ) { + + const { _lightNodes, totalDiffuseNode, totalSpecularNode } = this; + + context.outgoingLight = outgoingLightNode; + + const stack = builder.addStack(); + + // + + const properties = builder.getDataFromNode( this ); + properties.nodes = stack.nodes; + + // + + lightingModel.start( context, stack, builder ); + + // lights + + for ( const lightNode of _lightNodes ) { + + lightNode.build( builder ); + + } + + // + + lightingModel.indirect( context, stack, builder ); + + // + + const { backdrop, backdropAlpha } = context; + const { directDiffuse, directSpecular, indirectDiffuse, indirectSpecular } = context.reflectedLight; + + let totalDiffuse = directDiffuse.add( indirectDiffuse ); + + if ( backdrop !== null ) { + + if ( backdropAlpha !== null ) { + + totalDiffuse = vec3( backdropAlpha.mix( totalDiffuse, backdrop ) ); + + } else { + + totalDiffuse = vec3( backdrop ); + + } + + context.material.transparent = true; + + } + + totalDiffuseNode.assign( totalDiffuse ); + totalSpecularNode.assign( directSpecular.add( indirectSpecular ) ); + + outgoingLightNode.assign( totalDiffuseNode.add( totalSpecularNode ) ); + + // + + lightingModel.finish( context, stack, builder ); + + // + + outgoingLightNode = outgoingLightNode.bypass( builder.removeStack() ); + + } + + return outgoingLightNode; + + } + + setLights( lights ) { + + this._lights = lights; + + this._lightNodes = null; + this._lightNodesHash = null; + + return this; + + } + + getLights() { + + return this._lights; + + } + +} + +const lights = /*@__PURE__*/ nodeProxy( LightsNode ); + +class LightingNode extends Node { + + static get type() { + + return 'LightingNode'; + + } + + constructor() { + + super( 'vec3' ); + + this.isLightingNode = true; + + } + + generate( /*builder*/ ) { + + console.warn( 'Abstract function.' ); + + } + +} + +class AONode extends LightingNode { + + static get type() { + + return 'AONode'; + + } + + constructor( aoNode = null ) { + + super(); + + this.aoNode = aoNode; + + } + + setup( builder ) { + + builder.context.ambientOcclusion.mulAssign( this.aoNode ); + + } + +} + +class LightingContextNode extends ContextNode { + + static get type() { + + return 'LightingContextNode'; + + } + + constructor( node, lightingModel = null, backdropNode = null, backdropAlphaNode = null ) { + + super( node ); + + this.lightingModel = lightingModel; + this.backdropNode = backdropNode; + this.backdropAlphaNode = backdropAlphaNode; + + this._value = null; + + } + + getContext() { + + const { backdropNode, backdropAlphaNode } = this; + + const directDiffuse = vec3().toVar( 'directDiffuse' ), + directSpecular = vec3().toVar( 'directSpecular' ), + indirectDiffuse = vec3().toVar( 'indirectDiffuse' ), + indirectSpecular = vec3().toVar( 'indirectSpecular' ); + + const reflectedLight = { + directDiffuse, + directSpecular, + indirectDiffuse, + indirectSpecular + }; + + const context = { + radiance: vec3().toVar( 'radiance' ), + irradiance: vec3().toVar( 'irradiance' ), + iblIrradiance: vec3().toVar( 'iblIrradiance' ), + ambientOcclusion: float( 1 ).toVar( 'ambientOcclusion' ), + reflectedLight, + backdrop: backdropNode, + backdropAlpha: backdropAlphaNode + }; + + return context; + + } + + setup( builder ) { + + this.value = this._value || ( this._value = this.getContext() ); + this.value.lightingModel = this.lightingModel || builder.context.lightingModel; + + return super.setup( builder ); + + } + +} + +const lightingContext = /*@__PURE__*/ nodeProxy( LightingContextNode ); + +class IrradianceNode extends LightingNode { + + static get type() { + + return 'IrradianceNode'; + + } + + constructor( node ) { + + super(); + + this.node = node; + + } + + setup( builder ) { + + builder.context.irradiance.addAssign( this.node ); + + } + +} + +let screenSizeVec, viewportVec; + +class ScreenNode extends Node { + + static get type() { + + return 'ScreenNode'; + + } + + constructor( scope ) { + + super(); + + this.scope = scope; + + this.isViewportNode = true; + + } + + getNodeType() { + + if ( this.scope === ScreenNode.VIEWPORT ) return 'vec4'; + else return 'vec2'; + + } + + getUpdateType() { + + let updateType = NodeUpdateType.NONE; + + if ( this.scope === ScreenNode.SIZE || this.scope === ScreenNode.VIEWPORT ) { + + updateType = NodeUpdateType.RENDER; + + } + + this.updateType = updateType; + + return updateType; + + } + + update( { renderer } ) { + + const renderTarget = renderer.getRenderTarget(); + + if ( this.scope === ScreenNode.VIEWPORT ) { + + if ( renderTarget !== null ) { + + viewportVec.copy( renderTarget.viewport ); + + } else { + + renderer.getViewport( viewportVec ); + + viewportVec.multiplyScalar( renderer.getPixelRatio() ); + + } + + } else { + + if ( renderTarget !== null ) { + + screenSizeVec.width = renderTarget.width; + screenSizeVec.height = renderTarget.height; + + } else { + + renderer.getDrawingBufferSize( screenSizeVec ); + + } + + } + + } + + setup( /*builder*/ ) { + + const scope = this.scope; + + let output = null; + + if ( scope === ScreenNode.SIZE ) { + + output = uniform( screenSizeVec || ( screenSizeVec = new Vector2() ) ); + + } else if ( scope === ScreenNode.VIEWPORT ) { + + output = uniform( viewportVec || ( viewportVec = new Vector4() ) ); + + } else { + + output = vec2( screenCoordinate.div( screenSize ) ); + + } + + return output; + + } + + generate( builder ) { + + if ( this.scope === ScreenNode.COORDINATE ) { + + let coord = builder.getFragCoord(); + + if ( builder.isFlipY() ) { + + // follow webgpu standards + + const size = builder.getNodeProperties( screenSize ).outputNode.build( builder ); + + coord = `${ builder.getType( 'vec2' ) }( ${ coord }.x, ${ size }.y - ${ coord }.y )`; + + } + + return coord; + + } + + return super.generate( builder ); + + } + +} + +ScreenNode.COORDINATE = 'coordinate'; +ScreenNode.VIEWPORT = 'viewport'; +ScreenNode.SIZE = 'size'; +ScreenNode.UV = 'uv'; + +// Screen + +const screenUV = /*@__PURE__*/ nodeImmutable( ScreenNode, ScreenNode.UV ); +const screenSize = /*@__PURE__*/ nodeImmutable( ScreenNode, ScreenNode.SIZE ); +const screenCoordinate = /*@__PURE__*/ nodeImmutable( ScreenNode, ScreenNode.COORDINATE ); + +// Viewport + +const viewport = /*@__PURE__*/ nodeImmutable( ScreenNode, ScreenNode.VIEWPORT ); +const viewportSize = viewport.zw; +const viewportCoordinate = /*@__PURE__*/ screenCoordinate.sub( viewport.xy ); +const viewportUV = /*@__PURE__*/ viewportCoordinate.div( viewportSize ); + +// Deprecated + +const viewportResolution = /*@__PURE__*/ ( Fn( () => { // @deprecated, r169 + + console.warn( 'TSL.ViewportNode: "viewportResolution" is deprecated. Use "screenSize" instead.' ); + + return screenSize; + +}, 'vec2' ).once() )(); + +const viewportTopLeft = /*@__PURE__*/ ( Fn( () => { // @deprecated, r168 + + console.warn( 'TSL.ViewportNode: "viewportTopLeft" is deprecated. Use "screenUV" instead.' ); + + return screenUV; + +}, 'vec2' ).once() )(); + +const viewportBottomLeft = /*@__PURE__*/ ( Fn( () => { // @deprecated, r168 + + console.warn( 'TSL.ViewportNode: "viewportBottomLeft" is deprecated. Use "screenUV.flipY()" instead.' ); + + return screenUV.flipY(); + +}, 'vec2' ).once() )(); + +const _size$a = /*@__PURE__*/ new Vector2(); + +class ViewportTextureNode extends TextureNode { + + static get type() { + + return 'ViewportTextureNode'; + + } + + constructor( uvNode = screenUV, levelNode = null, framebufferTexture = null ) { + + if ( framebufferTexture === null ) { + + framebufferTexture = new FramebufferTexture(); + framebufferTexture.minFilter = LinearMipmapLinearFilter; + + } + + super( framebufferTexture, uvNode, levelNode ); + + this.generateMipmaps = false; + + this.isOutputTextureNode = true; + + this.updateBeforeType = NodeUpdateType.FRAME; + + } + + updateBefore( frame ) { + + const renderer = frame.renderer; + renderer.getDrawingBufferSize( _size$a ); + + // + + const framebufferTexture = this.value; + + if ( framebufferTexture.image.width !== _size$a.width || framebufferTexture.image.height !== _size$a.height ) { + + framebufferTexture.image.width = _size$a.width; + framebufferTexture.image.height = _size$a.height; + framebufferTexture.needsUpdate = true; + + } + + // + + const currentGenerateMipmaps = framebufferTexture.generateMipmaps; + framebufferTexture.generateMipmaps = this.generateMipmaps; + + renderer.copyFramebufferToTexture( framebufferTexture ); + + framebufferTexture.generateMipmaps = currentGenerateMipmaps; + + } + + clone() { + + const viewportTextureNode = new this.constructor( this.uvNode, this.levelNode, this.value ); + viewportTextureNode.generateMipmaps = this.generateMipmaps; + + return viewportTextureNode; + + } + +} + +const viewportTexture = /*@__PURE__*/ nodeProxy( ViewportTextureNode ); +const viewportMipTexture = /*@__PURE__*/ nodeProxy( ViewportTextureNode, null, null, { generateMipmaps: true } ); + +let sharedDepthbuffer = null; + +class ViewportDepthTextureNode extends ViewportTextureNode { + + static get type() { + + return 'ViewportDepthTextureNode'; + + } + + constructor( uvNode = screenUV, levelNode = null ) { + + if ( sharedDepthbuffer === null ) { + + sharedDepthbuffer = new DepthTexture(); + + } + + super( uvNode, levelNode, sharedDepthbuffer ); + + } + +} + +const viewportDepthTexture = /*@__PURE__*/ nodeProxy( ViewportDepthTextureNode ); + +class ViewportDepthNode extends Node { + + static get type() { + + return 'ViewportDepthNode'; + + } + + constructor( scope, valueNode = null ) { + + super( 'float' ); + + this.scope = scope; + this.valueNode = valueNode; + + this.isViewportDepthNode = true; + + } + + generate( builder ) { + + const { scope } = this; + + if ( scope === ViewportDepthNode.DEPTH_BASE ) { + + return builder.getFragDepth(); + + } + + return super.generate( builder ); + + } + + setup( { camera } ) { + + const { scope } = this; + const value = this.valueNode; + + let node = null; + + if ( scope === ViewportDepthNode.DEPTH_BASE ) { + + if ( value !== null ) { + + node = depthBase().assign( value ); + + } + + } else if ( scope === ViewportDepthNode.DEPTH ) { + + if ( camera.isPerspectiveCamera ) { + + node = viewZToPerspectiveDepth( positionView.z, cameraNear, cameraFar ); + + } else { + + node = viewZToOrthographicDepth( positionView.z, cameraNear, cameraFar ); + + } + + } else if ( scope === ViewportDepthNode.LINEAR_DEPTH ) { + + if ( value !== null ) { + + if ( camera.isPerspectiveCamera ) { + + const viewZ = perspectiveDepthToViewZ( value, cameraNear, cameraFar ); + + node = viewZToOrthographicDepth( viewZ, cameraNear, cameraFar ); + + } else { + + node = value; + + } + + } else { + + node = viewZToOrthographicDepth( positionView.z, cameraNear, cameraFar ); + + } + + } + + return node; + + } + +} + +ViewportDepthNode.DEPTH_BASE = 'depthBase'; +ViewportDepthNode.DEPTH = 'depth'; +ViewportDepthNode.LINEAR_DEPTH = 'linearDepth'; + +// NOTE: viewZ, the z-coordinate in camera space, is negative for points in front of the camera + +// -near maps to 0; -far maps to 1 +const viewZToOrthographicDepth = ( viewZ, near, far ) => viewZ.add( near ).div( near.sub( far ) ); + +// maps orthographic depth in [ 0, 1 ] to viewZ +const orthographicDepthToViewZ = ( depth, near, far ) => near.sub( far ).mul( depth ).sub( near ); + +// NOTE: https://twitter.com/gonnavis/status/1377183786949959682 + +// -near maps to 0; -far maps to 1 +const viewZToPerspectiveDepth = ( viewZ, near, far ) => near.add( viewZ ).mul( far ).div( far.sub( near ).mul( viewZ ) ); + +// maps perspective depth in [ 0, 1 ] to viewZ +const perspectiveDepthToViewZ = ( depth, near, far ) => near.mul( far ).div( far.sub( near ).mul( depth ).sub( far ) ); + +const depthBase = /*@__PURE__*/ nodeProxy( ViewportDepthNode, ViewportDepthNode.DEPTH_BASE ); + +const depth = /*@__PURE__*/ nodeImmutable( ViewportDepthNode, ViewportDepthNode.DEPTH ); +const linearDepth = /*@__PURE__*/ nodeProxy( ViewportDepthNode, ViewportDepthNode.LINEAR_DEPTH ); +const viewportLinearDepth = /*@__PURE__*/ linearDepth( viewportDepthTexture() ); + +depth.assign = ( value ) => depthBase( value ); + +class ClippingNode extends Node { + + static get type() { + + return 'ClippingNode'; + + } + + constructor( scope = ClippingNode.DEFAULT ) { + + super(); + + this.scope = scope; + + } + + setup( builder ) { + + super.setup( builder ); + + const clippingContext = builder.clippingContext; + const { localClipIntersection, localClippingCount, globalClippingCount } = clippingContext; + + const numClippingPlanes = globalClippingCount + localClippingCount; + const numUnionClippingPlanes = localClipIntersection ? numClippingPlanes - localClippingCount : numClippingPlanes; + + if ( this.scope === ClippingNode.ALPHA_TO_COVERAGE ) { + + return this.setupAlphaToCoverage( clippingContext.planes, numClippingPlanes, numUnionClippingPlanes ); + + } else { + + return this.setupDefault( clippingContext.planes, numClippingPlanes, numUnionClippingPlanes ); + + } + + } + + setupAlphaToCoverage( planes, numClippingPlanes, numUnionClippingPlanes ) { + + return Fn( () => { + + const clippingPlanes = uniformArray( planes ); + + const distanceToPlane = property( 'float', 'distanceToPlane' ); + const distanceGradient = property( 'float', 'distanceToGradient' ); + + const clipOpacity = property( 'float', 'clipOpacity' ); + + clipOpacity.assign( 1 ); + + let plane; + + Loop( numUnionClippingPlanes, ( { i } ) => { + + plane = clippingPlanes.element( i ); + + distanceToPlane.assign( positionView.dot( plane.xyz ).negate().add( plane.w ) ); + distanceGradient.assign( distanceToPlane.fwidth().div( 2.0 ) ); + + clipOpacity.mulAssign( smoothstep( distanceGradient.negate(), distanceGradient, distanceToPlane ) ); + + clipOpacity.equal( 0.0 ).discard(); + + } ); + + if ( numUnionClippingPlanes < numClippingPlanes ) { + + const unionClipOpacity = property( 'float', 'unionclipOpacity' ); + + unionClipOpacity.assign( 1 ); + + Loop( { start: numUnionClippingPlanes, end: numClippingPlanes }, ( { i } ) => { + + plane = clippingPlanes.element( i ); + + distanceToPlane.assign( positionView.dot( plane.xyz ).negate().add( plane.w ) ); + distanceGradient.assign( distanceToPlane.fwidth().div( 2.0 ) ); + + unionClipOpacity.mulAssign( smoothstep( distanceGradient.negate(), distanceGradient, distanceToPlane ).oneMinus() ); + + } ); + + clipOpacity.mulAssign( unionClipOpacity.oneMinus() ); + + } + + diffuseColor.a.mulAssign( clipOpacity ); + + diffuseColor.a.equal( 0.0 ).discard(); + + } )(); + + } + + setupDefault( planes, numClippingPlanes, numUnionClippingPlanes ) { + + return Fn( () => { + + const clippingPlanes = uniformArray( planes ); + + let plane; + + Loop( numUnionClippingPlanes, ( { i } ) => { + + plane = clippingPlanes.element( i ); + positionView.dot( plane.xyz ).greaterThan( plane.w ).discard(); + + } ); + + if ( numUnionClippingPlanes < numClippingPlanes ) { + + const clipped = property( 'bool', 'clipped' ); + + clipped.assign( true ); + + Loop( { start: numUnionClippingPlanes, end: numClippingPlanes }, ( { i } ) => { + + plane = clippingPlanes.element( i ); + clipped.assign( positionView.dot( plane.xyz ).greaterThan( plane.w ).and( clipped ) ); + + } ); + + clipped.discard(); + + } + + } )(); + + } + +} + +ClippingNode.ALPHA_TO_COVERAGE = 'alphaToCoverage'; +ClippingNode.DEFAULT = 'default'; + +const clipping = () => nodeObject( new ClippingNode() ); + +const clippingAlpha = () => nodeObject( new ClippingNode( ClippingNode.ALPHA_TO_COVERAGE ) ); + +class NodeMaterial extends Material { + + static get type() { + + return 'NodeMaterial'; + + } + + constructor() { + + super(); + + this.isNodeMaterial = true; + + this.type = this.constructor.type; + + this.forceSinglePass = false; + + this.fog = true; + this.lights = false; + + this.lightsNode = null; + this.envNode = null; + this.aoNode = null; + + this.colorNode = null; + this.normalNode = null; + this.opacityNode = null; + this.backdropNode = null; + this.backdropAlphaNode = null; + this.alphaTestNode = null; + + this.positionNode = null; + + this.depthNode = null; + this.shadowNode = null; + this.shadowPositionNode = null; + + this.outputNode = null; + this.mrtNode = null; + + this.fragmentNode = null; + this.vertexNode = null; + + } + + customProgramCacheKey() { + + return this.type + getCacheKey$1( this ); + + } + + build( builder ) { + + this.setup( builder ); + + } + + setupObserver( builder ) { + + return new NodeMaterialObserver( builder ); + + } + + setup( builder ) { + + builder.context.setupNormal = () => this.setupNormal( builder ); + + // < VERTEX STAGE > + + builder.addStack(); + + builder.stack.outputNode = this.vertexNode || this.setupPosition( builder ); + + builder.addFlow( 'vertex', builder.removeStack() ); + + // < FRAGMENT STAGE > + + builder.addStack(); + + let resultNode; + + const clippingNode = this.setupClipping( builder ); + + if ( this.depthWrite === true ) this.setupDepth( builder ); + + if ( this.fragmentNode === null ) { + + this.setupDiffuseColor( builder ); + this.setupVariants( builder ); + + const outgoingLightNode = this.setupLighting( builder ); + + if ( clippingNode !== null ) builder.stack.add( clippingNode ); + + // force unsigned floats - useful for RenderTargets + + const basicOutput = vec4( outgoingLightNode, diffuseColor.a ).max( 0 ); + + resultNode = this.setupOutput( builder, basicOutput ); + + // OUTPUT NODE + + output.assign( resultNode ); + + // + + if ( this.outputNode !== null ) resultNode = this.outputNode; + + // MRT + + const renderTarget = builder.renderer.getRenderTarget(); + + if ( renderTarget !== null ) { + + const mrt = builder.renderer.getMRT(); + const materialMRT = this.mrtNode; + + if ( mrt !== null ) { + + resultNode = mrt; + + if ( materialMRT !== null ) { + + resultNode = mrt.merge( materialMRT ); + + } + + } else if ( materialMRT !== null ) { + + resultNode = materialMRT; + + } + + } + + } else { + + let fragmentNode = this.fragmentNode; + + if ( fragmentNode.isOutputStructNode !== true ) { + + fragmentNode = vec4( fragmentNode ); + + } + + resultNode = this.setupOutput( builder, fragmentNode ); + + } + + builder.stack.outputNode = resultNode; + + builder.addFlow( 'fragment', builder.removeStack() ); + + // < MONITOR > + + builder.monitor = this.setupObserver( builder ); + + } + + setupClipping( builder ) { + + if ( builder.clippingContext === null ) return null; + + const { globalClippingCount, localClippingCount } = builder.clippingContext; + + let result = null; + + if ( globalClippingCount || localClippingCount ) { + + const samples = builder.renderer.samples; + + if ( this.alphaToCoverage && samples > 1 ) { + + // to be added to flow when the color/alpha value has been determined + result = clippingAlpha(); + + } else { + + builder.stack.add( clipping() ); + + } + + } + + return result; + + } + + setupDepth( builder ) { + + const { renderer } = builder; + + // Depth + + let depthNode = this.depthNode; + + if ( depthNode === null ) { + + const mrt = renderer.getMRT(); + + if ( mrt && mrt.has( 'depth' ) ) { + + depthNode = mrt.get( 'depth' ); + + } else if ( renderer.logarithmicDepthBuffer === true ) { + + const fragDepth = modelViewProjection().w.add( 1 ); + + depthNode = fragDepth.log2().mul( cameraLogDepth ).mul( 0.5 ); + + } + + } + + if ( depthNode !== null ) { + + depth.assign( depthNode ).append(); + + } + + } + + setupPosition( builder ) { + + const { object } = builder; + const geometry = object.geometry; + + builder.addStack(); + + // Vertex + + if ( geometry.morphAttributes.position || geometry.morphAttributes.normal || geometry.morphAttributes.color ) { + + morphReference( object ).append(); + + } + + if ( object.isSkinnedMesh === true ) { + + skinningReference( object ).append(); + + } + + if ( this.displacementMap ) { + + const displacementMap = materialReference( 'displacementMap', 'texture' ); + const displacementScale = materialReference( 'displacementScale', 'float' ); + const displacementBias = materialReference( 'displacementBias', 'float' ); + + positionLocal.addAssign( normalLocal.normalize().mul( ( displacementMap.x.mul( displacementScale ).add( displacementBias ) ) ) ); + + } + + if ( object.isBatchedMesh ) { + + batch( object ).append(); + + } + + if ( ( object.instanceMatrix && object.instanceMatrix.isInstancedBufferAttribute === true ) ) { + + instance( object ).append(); + + } + + if ( this.positionNode !== null ) { + + positionLocal.assign( this.positionNode ); + + } + + const mvp = modelViewProjection(); + + builder.context.vertex = builder.removeStack(); + builder.context.mvp = mvp; + + return mvp; + + } + + setupDiffuseColor( { object, geometry } ) { + + let colorNode = this.colorNode ? vec4( this.colorNode ) : materialColor; + + // VERTEX COLORS + + if ( this.vertexColors === true && geometry.hasAttribute( 'color' ) ) { + + colorNode = vec4( colorNode.xyz.mul( attribute( 'color', 'vec3' ) ), colorNode.a ); + + } + + // Instanced colors + + if ( object.instanceColor ) { + + const instanceColor = varyingProperty( 'vec3', 'vInstanceColor' ); + + colorNode = instanceColor.mul( colorNode ); + + } + + if ( object.isBatchedMesh && object._colorsTexture ) { + + const batchColor = varyingProperty( 'vec3', 'vBatchColor' ); + + colorNode = batchColor.mul( colorNode ); + + } + + + // COLOR + + diffuseColor.assign( colorNode ); + + // OPACITY + + const opacityNode = this.opacityNode ? float( this.opacityNode ) : materialOpacity; + diffuseColor.a.assign( diffuseColor.a.mul( opacityNode ) ); + + // ALPHA TEST + + if ( this.alphaTestNode !== null || this.alphaTest > 0 ) { + + const alphaTestNode = this.alphaTestNode !== null ? float( this.alphaTestNode ) : materialAlphaTest; + + diffuseColor.a.lessThanEqual( alphaTestNode ).discard(); + + } + + if ( this.transparent === false && this.blending === NormalBlending && this.alphaToCoverage === false ) { + + diffuseColor.a.assign( 1.0 ); + + } + + } + + setupVariants( /*builder*/ ) { + + // Interface function. + + } + + setupOutgoingLight() { + + return ( this.lights === true ) ? vec3( 0 ) : diffuseColor.rgb; + + } + + setupNormal() { + + return this.normalNode ? vec3( this.normalNode ) : materialNormal; + + } + + setupEnvironment( /*builder*/ ) { + + let node = null; + + if ( this.envNode ) { + + node = this.envNode; + + } else if ( this.envMap ) { + + node = this.envMap.isCubeTexture ? materialReference( 'envMap', 'cubeTexture' ) : materialReference( 'envMap', 'texture' ); + + } + + return node; + + } + + setupLightMap( builder ) { + + let node = null; + + if ( builder.material.lightMap ) { + + node = new IrradianceNode( materialLightMap ); + + } + + return node; + + } + + setupLights( builder ) { + + const materialLightsNode = []; + + // + + const envNode = this.setupEnvironment( builder ); + + if ( envNode && envNode.isLightingNode ) { + + materialLightsNode.push( envNode ); + + } + + const lightMapNode = this.setupLightMap( builder ); + + if ( lightMapNode && lightMapNode.isLightingNode ) { + + materialLightsNode.push( lightMapNode ); + + } + + if ( this.aoNode !== null || builder.material.aoMap ) { + + const aoNode = this.aoNode !== null ? this.aoNode : materialAOMap; + + materialLightsNode.push( new AONode( aoNode ) ); + + } + + let lightsN = this.lightsNode || builder.lightsNode; + + if ( materialLightsNode.length > 0 ) { + + lightsN = lights( [ ...lightsN.getLights(), ...materialLightsNode ] ); + + } + + return lightsN; + + } + + setupLightingModel( /*builder*/ ) { + + // Interface function. + + } + + setupLighting( builder ) { + + const { material } = builder; + const { backdropNode, backdropAlphaNode, emissiveNode } = this; + + // OUTGOING LIGHT + + const lights = this.lights === true || this.lightsNode !== null; + + const lightsNode = lights ? this.setupLights( builder ) : null; + + let outgoingLightNode = this.setupOutgoingLight( builder ); + + if ( lightsNode && lightsNode.getScope().getLights().length > 0 ) { + + const lightingModel = this.setupLightingModel( builder ); + + outgoingLightNode = lightingContext( lightsNode, lightingModel, backdropNode, backdropAlphaNode ); + + } else if ( backdropNode !== null ) { + + outgoingLightNode = vec3( backdropAlphaNode !== null ? mix( outgoingLightNode, backdropNode, backdropAlphaNode ) : backdropNode ); + + } + + // EMISSIVE + + if ( ( emissiveNode && emissiveNode.isNode === true ) || ( material.emissive && material.emissive.isColor === true ) ) { + + emissive.assign( vec3( emissiveNode ? emissiveNode : materialEmissive ) ); + + outgoingLightNode = outgoingLightNode.add( emissive ); + + } + + return outgoingLightNode; + + } + + setupOutput( builder, outputNode ) { + + // FOG + + if ( this.fog === true ) { + + const fogNode = builder.fogNode; + + if ( fogNode ) outputNode = vec4( fogNode.mix( outputNode.rgb, fogNode.colorNode ), outputNode.a ); + + } + + return outputNode; + + } + + setDefaultValues( material ) { + + // This approach is to reuse the native refreshUniforms* + // and turn available the use of features like transmission and environment in core + + for ( const property in material ) { + + const value = material[ property ]; + + if ( this[ property ] === undefined ) { + + this[ property ] = value; + + if ( value && value.clone ) this[ property ] = value.clone(); + + } + + } + + const descriptors = Object.getOwnPropertyDescriptors( material.constructor.prototype ); + + for ( const key in descriptors ) { + + if ( Object.getOwnPropertyDescriptor( this.constructor.prototype, key ) === undefined && + descriptors[ key ].get !== undefined ) { + + Object.defineProperty( this.constructor.prototype, key, descriptors[ key ] ); + + } + + } + + } + + toJSON( meta ) { + + const isRoot = ( meta === undefined || typeof meta === 'string' ); + + if ( isRoot ) { + + meta = { + textures: {}, + images: {}, + nodes: {} + }; + + } + + const data = Material.prototype.toJSON.call( this, meta ); + const nodeChildren = getNodeChildren( this ); + + data.inputNodes = {}; + + for ( const { property, childNode } of nodeChildren ) { + + data.inputNodes[ property ] = childNode.toJSON( meta ).uuid; + + } + + // TODO: Copied from Object3D.toJSON + + function extractFromCache( cache ) { + + const values = []; + + for ( const key in cache ) { + + const data = cache[ key ]; + delete data.metadata; + values.push( data ); + + } + + return values; + + } + + if ( isRoot ) { + + const textures = extractFromCache( meta.textures ); + const images = extractFromCache( meta.images ); + const nodes = extractFromCache( meta.nodes ); + + if ( textures.length > 0 ) data.textures = textures; + if ( images.length > 0 ) data.images = images; + if ( nodes.length > 0 ) data.nodes = nodes; + + } + + return data; + + } + + copy( source ) { + + this.lightsNode = source.lightsNode; + this.envNode = source.envNode; + + this.colorNode = source.colorNode; + this.normalNode = source.normalNode; + this.opacityNode = source.opacityNode; + this.backdropNode = source.backdropNode; + this.backdropAlphaNode = source.backdropAlphaNode; + this.alphaTestNode = source.alphaTestNode; + + this.positionNode = source.positionNode; + + this.depthNode = source.depthNode; + this.shadowNode = source.shadowNode; + this.shadowPositionNode = source.shadowPositionNode; + + this.outputNode = source.outputNode; + this.mrtNode = source.mrtNode; + + this.fragmentNode = source.fragmentNode; + this.vertexNode = source.vertexNode; + + return super.copy( source ); + + } + +} + +const _defaultValues$e = /*@__PURE__*/ new PointsMaterial(); + +class InstancedPointsNodeMaterial extends NodeMaterial { + + static get type() { + + return 'InstancedPointsNodeMaterial'; + + } + + constructor( params = {} ) { + + super(); + + this.lights = false; + + this.useAlphaToCoverage = true; + + this.useColor = params.vertexColors; + + this.pointWidth = 1; + + this.pointColorNode = null; + + this.pointWidthNode = null; + + this.setDefaultValues( _defaultValues$e ); + + this.setValues( params ); + + } + + setup( builder ) { + + this.setupShaders( builder ); + + super.setup( builder ); + + } + + setupShaders( { renderer } ) { + + const useAlphaToCoverage = this.alphaToCoverage; + const useColor = this.useColor; + + this.vertexNode = Fn( () => { + + const instancePosition = attribute( 'instancePosition' ).xyz; + + // camera space + const mvPos = vec4( modelViewMatrix.mul( vec4( instancePosition, 1.0 ) ) ); + + const aspect = viewport.z.div( viewport.w ); + + // clip space + const clipPos = cameraProjectionMatrix.mul( mvPos ); + + // offset in ndc space + const offset = positionGeometry.xy.toVar(); + + offset.mulAssign( this.pointWidthNode ? this.pointWidthNode : materialPointWidth ); + + offset.assign( offset.div( viewport.z ) ); + offset.y.assign( offset.y.mul( aspect ) ); + + // back to clip space + offset.assign( offset.mul( clipPos.w ) ); + + //clipPos.xy += offset; + clipPos.addAssign( vec4( offset, 0, 0 ) ); + + return clipPos; + + } )(); + + this.fragmentNode = Fn( () => { + + const alpha = float( 1 ).toVar(); + + const len2 = lengthSq( uv().mul( 2 ).sub( 1 ) ); + + if ( useAlphaToCoverage && renderer.samples > 1 ) { + + const dlen = float( len2.fwidth() ).toVar(); + + alpha.assign( smoothstep( dlen.oneMinus(), dlen.add( 1 ), len2 ).oneMinus() ); + + } else { + + len2.greaterThan( 1.0 ).discard(); + + } + + let pointColorNode; + + if ( this.pointColorNode ) { + + pointColorNode = this.pointColorNode; + + } else { + + if ( useColor ) { + + const instanceColor = attribute( 'instanceColor' ); + + pointColorNode = instanceColor.mul( materialColor ); + + } else { + + pointColorNode = materialColor; + + } + + } + + alpha.mulAssign( materialOpacity ); + + return vec4( pointColorNode, alpha ); + + } )(); + + } + + get alphaToCoverage() { + + return this.useAlphaToCoverage; + + } + + set alphaToCoverage( value ) { + + if ( this.useAlphaToCoverage !== value ) { + + this.useAlphaToCoverage = value; + this.needsUpdate = true; + + } + + } + +} + +const _defaultValues$d = /*@__PURE__*/ new LineBasicMaterial(); + +class LineBasicNodeMaterial extends NodeMaterial { + + static get type() { + + return 'LineBasicNodeMaterial'; + + } + + constructor( parameters ) { + + super(); + + this.isLineBasicNodeMaterial = true; + + this.lights = false; + + this.setDefaultValues( _defaultValues$d ); + + this.setValues( parameters ); + + } + +} + +const _defaultValues$c = /*@__PURE__*/ new LineDashedMaterial(); + +class LineDashedNodeMaterial extends NodeMaterial { + + static get type() { + + return 'LineDashedNodeMaterial'; + + } + + constructor( parameters ) { + + super(); + + this.isLineDashedNodeMaterial = true; + + this.lights = false; + + this.setDefaultValues( _defaultValues$c ); + + this.offsetNode = null; + this.dashScaleNode = null; + this.dashSizeNode = null; + this.gapSizeNode = null; + + this.setValues( parameters ); + + } + + setupVariants() { + + const offsetNode = this.offsetNode; + const dashScaleNode = this.dashScaleNode ? float( this.dashScaleNode ) : materialLineScale; + const dashSizeNode = this.dashSizeNode ? float( this.dashSizeNode ) : materialLineDashSize; + const gapSizeNode = this.dashSizeNode ? float( this.dashGapNode ) : materialLineGapSize; + + dashSize.assign( dashSizeNode ); + gapSize.assign( gapSizeNode ); + + const vLineDistance = varying( attribute( 'lineDistance' ).mul( dashScaleNode ) ); + const vLineDistanceOffset = offsetNode ? vLineDistance.add( offsetNode ) : vLineDistance; + + vLineDistanceOffset.mod( dashSize.add( gapSize ) ).greaterThan( dashSize ).discard(); + + } + +} + +const _defaultValues$b = /*@__PURE__*/ new LineDashedMaterial(); + +class Line2NodeMaterial extends NodeMaterial { + + static get type() { + + return 'Line2NodeMaterial'; + + } + + constructor( params = {} ) { + + super(); + + this.lights = false; + + this.setDefaultValues( _defaultValues$b ); + + this.useAlphaToCoverage = true; + this.useColor = params.vertexColors; + this.useDash = params.dashed; + this.useWorldUnits = false; + + this.dashOffset = 0; + this.lineWidth = 1; + + this.lineColorNode = null; + + this.offsetNode = null; + this.dashScaleNode = null; + this.dashSizeNode = null; + this.gapSizeNode = null; + + this.setValues( params ); + + } + + setup( builder ) { + + this.setupShaders( builder ); + + super.setup( builder ); + + } + + setupShaders( { renderer } ) { + + const useAlphaToCoverage = this.alphaToCoverage; + const useColor = this.useColor; + const useDash = this.dashed; + const useWorldUnits = this.worldUnits; + + const trimSegment = Fn( ( { start, end } ) => { + + const a = cameraProjectionMatrix.element( 2 ).element( 2 ); // 3nd entry in 3th column + const b = cameraProjectionMatrix.element( 3 ).element( 2 ); // 3nd entry in 4th column + const nearEstimate = b.mul( - 0.5 ).div( a ); + + const alpha = nearEstimate.sub( start.z ).div( end.z.sub( start.z ) ); + + return vec4( mix( start.xyz, end.xyz, alpha ), end.w ); + + } ).setLayout( { + name: 'trimSegment', + type: 'vec4', + inputs: [ + { name: 'start', type: 'vec4' }, + { name: 'end', type: 'vec4' } + ] + } ); + + this.vertexNode = Fn( () => { + + const instanceStart = attribute( 'instanceStart' ); + const instanceEnd = attribute( 'instanceEnd' ); + + // camera space + + const start = vec4( modelViewMatrix.mul( vec4( instanceStart, 1.0 ) ) ).toVar( 'start' ); + const end = vec4( modelViewMatrix.mul( vec4( instanceEnd, 1.0 ) ) ).toVar( 'end' ); + + if ( useWorldUnits ) { + + varyingProperty( 'vec3', 'worldStart' ).assign( start.xyz ); + varyingProperty( 'vec3', 'worldEnd' ).assign( end.xyz ); + + } + + const aspect = viewport.z.div( viewport.w ); + + // special case for perspective projection, and segments that terminate either in, or behind, the camera plane + // clearly the gpu firmware has a way of addressing this issue when projecting into ndc space + // but we need to perform ndc-space calculations in the shader, so we must address this issue directly + // perhaps there is a more elegant solution -- WestLangley + + const perspective = cameraProjectionMatrix.element( 2 ).element( 3 ).equal( - 1.0 ); // 4th entry in the 3rd column + + If( perspective, () => { + + If( start.z.lessThan( 0.0 ).and( end.z.greaterThan( 0.0 ) ), () => { + + end.assign( trimSegment( { start: start, end: end } ) ); + + } ).ElseIf( end.z.lessThan( 0.0 ).and( start.z.greaterThanEqual( 0.0 ) ), () => { + + start.assign( trimSegment( { start: end, end: start } ) ); + + } ); + + } ); + + // clip space + const clipStart = cameraProjectionMatrix.mul( start ); + const clipEnd = cameraProjectionMatrix.mul( end ); + + // ndc space + const ndcStart = clipStart.xyz.div( clipStart.w ); + const ndcEnd = clipEnd.xyz.div( clipEnd.w ); + + // direction + const dir = ndcEnd.xy.sub( ndcStart.xy ).toVar(); + + // account for clip-space aspect ratio + dir.x.assign( dir.x.mul( aspect ) ); + dir.assign( dir.normalize() ); + + const clip = vec4().toVar(); + + if ( useWorldUnits ) { + + // get the offset direction as perpendicular to the view vector + + const worldDir = end.xyz.sub( start.xyz ).normalize(); + const tmpFwd = mix( start.xyz, end.xyz, 0.5 ).normalize(); + const worldUp = worldDir.cross( tmpFwd ).normalize(); + const worldFwd = worldDir.cross( worldUp ); + + const worldPos = varyingProperty( 'vec4', 'worldPos' ); + + worldPos.assign( positionGeometry.y.lessThan( 0.5 ).select( start, end ) ); + + // height offset + const hw = materialLineWidth.mul( 0.5 ); + worldPos.addAssign( vec4( positionGeometry.x.lessThan( 0.0 ).select( worldUp.mul( hw ), worldUp.mul( hw ).negate() ), 0 ) ); + + // don't extend the line if we're rendering dashes because we + // won't be rendering the endcaps + if ( ! useDash ) { + + // cap extension + worldPos.addAssign( vec4( positionGeometry.y.lessThan( 0.5 ).select( worldDir.mul( hw ).negate(), worldDir.mul( hw ) ), 0 ) ); + + // add width to the box + worldPos.addAssign( vec4( worldFwd.mul( hw ), 0 ) ); + + // endcaps + If( positionGeometry.y.greaterThan( 1.0 ).or( positionGeometry.y.lessThan( 0.0 ) ), () => { + + worldPos.subAssign( vec4( worldFwd.mul( 2.0 ).mul( hw ), 0 ) ); + + } ); + + } + + // project the worldpos + clip.assign( cameraProjectionMatrix.mul( worldPos ) ); + + // shift the depth of the projected points so the line + // segments overlap neatly + const clipPose = vec3().toVar(); + + clipPose.assign( positionGeometry.y.lessThan( 0.5 ).select( ndcStart, ndcEnd ) ); + clip.z.assign( clipPose.z.mul( clip.w ) ); + + } else { + + const offset = vec2( dir.y, dir.x.negate() ).toVar( 'offset' ); + + // undo aspect ratio adjustment + dir.x.assign( dir.x.div( aspect ) ); + offset.x.assign( offset.x.div( aspect ) ); + + // sign flip + offset.assign( positionGeometry.x.lessThan( 0.0 ).select( offset.negate(), offset ) ); + + // endcaps + If( positionGeometry.y.lessThan( 0.0 ), () => { + + offset.assign( offset.sub( dir ) ); + + } ).ElseIf( positionGeometry.y.greaterThan( 1.0 ), () => { + + offset.assign( offset.add( dir ) ); + + } ); + + // adjust for linewidth + offset.assign( offset.mul( materialLineWidth ) ); + + // adjust for clip-space to screen-space conversion // maybe resolution should be based on viewport ... + offset.assign( offset.div( viewport.w ) ); + + // select end + clip.assign( positionGeometry.y.lessThan( 0.5 ).select( clipStart, clipEnd ) ); + + // back to clip space + offset.assign( offset.mul( clip.w ) ); + + clip.assign( clip.add( vec4( offset, 0, 0 ) ) ); + + } + + return clip; + + } )(); + + const closestLineToLine = Fn( ( { p1, p2, p3, p4 } ) => { + + const p13 = p1.sub( p3 ); + const p43 = p4.sub( p3 ); + + const p21 = p2.sub( p1 ); + + const d1343 = p13.dot( p43 ); + const d4321 = p43.dot( p21 ); + const d1321 = p13.dot( p21 ); + const d4343 = p43.dot( p43 ); + const d2121 = p21.dot( p21 ); + + const denom = d2121.mul( d4343 ).sub( d4321.mul( d4321 ) ); + const numer = d1343.mul( d4321 ).sub( d1321.mul( d4343 ) ); + + const mua = numer.div( denom ).clamp(); + const mub = d1343.add( d4321.mul( mua ) ).div( d4343 ).clamp(); + + return vec2( mua, mub ); + + } ); + + this.fragmentNode = Fn( () => { + + const vUv = uv(); + + if ( useDash ) { + + const offsetNode = this.offsetNode ? float( this.offsetNodeNode ) : materialLineDashOffset; + const dashScaleNode = this.dashScaleNode ? float( this.dashScaleNode ) : materialLineScale; + const dashSizeNode = this.dashSizeNode ? float( this.dashSizeNode ) : materialLineDashSize; + const gapSizeNode = this.dashSizeNode ? float( this.dashGapNode ) : materialLineGapSize; + + dashSize.assign( dashSizeNode ); + gapSize.assign( gapSizeNode ); + + const instanceDistanceStart = attribute( 'instanceDistanceStart' ); + const instanceDistanceEnd = attribute( 'instanceDistanceEnd' ); + + const lineDistance = positionGeometry.y.lessThan( 0.5 ).select( dashScaleNode.mul( instanceDistanceStart ), materialLineScale.mul( instanceDistanceEnd ) ); + + const vLineDistance = varying( lineDistance.add( materialLineDashOffset ) ); + const vLineDistanceOffset = offsetNode ? vLineDistance.add( offsetNode ) : vLineDistance; + + vUv.y.lessThan( - 1.0 ).or( vUv.y.greaterThan( 1.0 ) ).discard(); // discard endcaps + vLineDistanceOffset.mod( dashSize.add( gapSize ) ).greaterThan( dashSize ).discard(); // todo - FIX + + } + + const alpha = float( 1 ).toVar( 'alpha' ); + + if ( useWorldUnits ) { + + const worldStart = varyingProperty( 'vec3', 'worldStart' ); + const worldEnd = varyingProperty( 'vec3', 'worldEnd' ); + + // Find the closest points on the view ray and the line segment + const rayEnd = varyingProperty( 'vec4', 'worldPos' ).xyz.normalize().mul( 1e5 ); + const lineDir = worldEnd.sub( worldStart ); + const params = closestLineToLine( { p1: worldStart, p2: worldEnd, p3: vec3( 0.0, 0.0, 0.0 ), p4: rayEnd } ); + + const p1 = worldStart.add( lineDir.mul( params.x ) ); + const p2 = rayEnd.mul( params.y ); + const delta = p1.sub( p2 ); + const len = delta.length(); + const norm = len.div( materialLineWidth ); + + if ( ! useDash ) { + + if ( useAlphaToCoverage && renderer.samples > 1 ) { + + const dnorm = norm.fwidth(); + alpha.assign( smoothstep( dnorm.negate().add( 0.5 ), dnorm.add( 0.5 ), norm ).oneMinus() ); + + } else { + + norm.greaterThan( 0.5 ).discard(); + + } + + } + + } else { + + // round endcaps + + if ( useAlphaToCoverage && renderer.samples > 1 ) { + + const a = vUv.x; + const b = vUv.y.greaterThan( 0.0 ).select( vUv.y.sub( 1.0 ), vUv.y.add( 1.0 ) ); + + const len2 = a.mul( a ).add( b.mul( b ) ); + + const dlen = float( len2.fwidth() ).toVar( 'dlen' ); + + If( vUv.y.abs().greaterThan( 1.0 ), () => { + + alpha.assign( smoothstep( dlen.oneMinus(), dlen.add( 1 ), len2 ).oneMinus() ); + + } ); + + } else { + + If( vUv.y.abs().greaterThan( 1.0 ), () => { + + const a = vUv.x; + const b = vUv.y.greaterThan( 0.0 ).select( vUv.y.sub( 1.0 ), vUv.y.add( 1.0 ) ); + const len2 = a.mul( a ).add( b.mul( b ) ); + + len2.greaterThan( 1.0 ).discard(); + + } ); + + } + + } + + let lineColorNode; + + if ( this.lineColorNode ) { + + lineColorNode = this.lineColorNode; + + } else { + + if ( useColor ) { + + const instanceColorStart = attribute( 'instanceColorStart' ); + const instanceColorEnd = attribute( 'instanceColorEnd' ); + + const instanceColor = positionGeometry.y.lessThan( 0.5 ).select( instanceColorStart, instanceColorEnd ); + + lineColorNode = instanceColor.mul( materialColor ); + + } else { + + lineColorNode = materialColor; + + } + + } + + return vec4( lineColorNode, alpha ); + + } )(); + + } + + + get worldUnits() { + + return this.useWorldUnits; + + } + + set worldUnits( value ) { + + if ( this.useWorldUnits !== value ) { + + this.useWorldUnits = value; + this.needsUpdate = true; + + } + + } + + + get dashed() { + + return this.useDash; + + } + + set dashed( value ) { + + if ( this.useDash !== value ) { + + this.useDash = value; + this.needsUpdate = true; + + } + + } + + + get alphaToCoverage() { + + return this.useAlphaToCoverage; + + } + + set alphaToCoverage( value ) { + + if ( this.useAlphaToCoverage !== value ) { + + this.useAlphaToCoverage = value; + this.needsUpdate = true; + + } + + } + +} + +const directionToColor = ( node ) => nodeObject( node ).mul( 0.5 ).add( 0.5 ); +const colorToDirection = ( node ) => nodeObject( node ).mul( 2.0 ).sub( 1 ); + +const _defaultValues$a = /*@__PURE__*/ new MeshNormalMaterial(); + +class MeshNormalNodeMaterial extends NodeMaterial { + + static get type() { + + return 'MeshNormalNodeMaterial'; + + } + + constructor( parameters ) { + + super(); + + this.lights = false; + + this.isMeshNormalNodeMaterial = true; + + this.setDefaultValues( _defaultValues$a ); + + this.setValues( parameters ); + + } + + setupDiffuseColor() { + + const opacityNode = this.opacityNode ? float( this.opacityNode ) : materialOpacity; + + diffuseColor.assign( vec4( directionToColor( transformedNormalView ), opacityNode ) ); + + } + +} + +class EquirectUVNode extends TempNode { + + static get type() { + + return 'EquirectUVNode'; + + } + + constructor( dirNode = positionWorldDirection ) { + + super( 'vec2' ); + + this.dirNode = dirNode; + + } + + setup() { + + const dir = this.dirNode; + + const u = dir.z.atan2( dir.x ).mul( 1 / ( Math.PI * 2 ) ).add( 0.5 ); + const v = dir.y.clamp( - 1.0, 1.0 ).asin().mul( 1 / Math.PI ).add( 0.5 ); + + return vec2( u, v ); + + } + +} + +const equirectUV = /*@__PURE__*/ nodeProxy( EquirectUVNode ); + +// @TODO: Consider rename WebGLCubeRenderTarget to just CubeRenderTarget + +class CubeRenderTarget extends WebGLCubeRenderTarget { + + constructor( size = 1, options = {} ) { + + super( size, options ); + + this.isCubeRenderTarget = true; + + } + + fromEquirectangularTexture( renderer, texture$1 ) { + + const currentMinFilter = texture$1.minFilter; + const currentGenerateMipmaps = texture$1.generateMipmaps; + + texture$1.generateMipmaps = true; + + this.texture.type = texture$1.type; + this.texture.colorSpace = texture$1.colorSpace; + + this.texture.generateMipmaps = texture$1.generateMipmaps; + this.texture.minFilter = texture$1.minFilter; + this.texture.magFilter = texture$1.magFilter; + + const geometry = new BoxGeometry( 5, 5, 5 ); + + const uvNode = equirectUV( positionWorldDirection ); + + const material = new NodeMaterial(); + material.colorNode = texture( texture$1, uvNode, 0 ); + material.side = BackSide; + material.blending = NoBlending; + + const mesh = new Mesh( geometry, material ); + + const scene = new Scene(); + scene.add( mesh ); + + // Avoid blurred poles + if ( texture$1.minFilter === LinearMipmapLinearFilter ) texture$1.minFilter = LinearFilter; + + const camera = new CubeCamera( 1, 10, this ); + + const currentMRT = renderer.getMRT(); + renderer.setMRT( null ); + + camera.update( renderer, scene ); + + renderer.setMRT( currentMRT ); + + texture$1.minFilter = currentMinFilter; + texture$1.currentGenerateMipmaps = currentGenerateMipmaps; + + mesh.geometry.dispose(); + mesh.material.dispose(); + + return this; + + } + +} + +const _cache$1 = new WeakMap(); + +class CubeMapNode extends TempNode { + + static get type() { + + return 'CubeMapNode'; + + } + + constructor( envNode ) { + + super( 'vec3' ); + + this.envNode = envNode; + + this._cubeTexture = null; + this._cubeTextureNode = cubeTexture(); + + const defaultTexture = new CubeTexture(); + defaultTexture.isRenderTargetTexture = true; + + this._defaultTexture = defaultTexture; + + this.updateBeforeType = NodeUpdateType.RENDER; + + } + + updateBefore( frame ) { + + const { renderer, material } = frame; + + const envNode = this.envNode; + + if ( envNode.isTextureNode || envNode.isMaterialReferenceNode ) { + + const texture = ( envNode.isTextureNode ) ? envNode.value : material[ envNode.property ]; + + if ( texture && texture.isTexture ) { + + const mapping = texture.mapping; + + if ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) { + + // check for converted cubemap map + + if ( _cache$1.has( texture ) ) { + + const cubeMap = _cache$1.get( texture ); + + mapTextureMapping( cubeMap, texture.mapping ); + this._cubeTexture = cubeMap; + + } else { + + // create cube map from equirectangular map + + const image = texture.image; + + if ( isEquirectangularMapReady$1( image ) ) { + + const renderTarget = new CubeRenderTarget( image.height ); + renderTarget.fromEquirectangularTexture( renderer, texture ); + + mapTextureMapping( renderTarget.texture, texture.mapping ); + this._cubeTexture = renderTarget.texture; + + _cache$1.set( texture, renderTarget.texture ); + + texture.addEventListener( 'dispose', onTextureDispose ); + + } else { + + // default cube texture as fallback when equirectangular texture is not yet loaded + + this._cubeTexture = this._defaultTexture; + + } + + } + + // + + this._cubeTextureNode.value = this._cubeTexture; + + } else { + + // envNode already refers to a cube map + + this._cubeTextureNode = this.envNode; + + } + + } + + } + + } + + setup( builder ) { + + this.updateBefore( builder ); + + return this._cubeTextureNode; + + } + +} + +function isEquirectangularMapReady$1( image ) { + + if ( image === null || image === undefined ) return false; + + return image.height > 0; + +} + +function onTextureDispose( event ) { + + const texture = event.target; + + texture.removeEventListener( 'dispose', onTextureDispose ); + + const renderTarget = _cache$1.get( texture ); + + if ( renderTarget !== undefined ) { + + _cache$1.delete( texture ); + + renderTarget.dispose(); + + } + +} + +function mapTextureMapping( texture, mapping ) { + + if ( mapping === EquirectangularReflectionMapping ) { + + texture.mapping = CubeReflectionMapping; + + } else if ( mapping === EquirectangularRefractionMapping ) { + + texture.mapping = CubeRefractionMapping; + + } + +} + +const cubeMapNode = /*@__PURE__*/ nodeProxy( CubeMapNode ); + +class BasicEnvironmentNode extends LightingNode { + + static get type() { + + return 'BasicEnvironmentNode'; + + } + + constructor( envNode = null ) { + + super(); + + this.envNode = envNode; + + } + + setup( builder ) { + + // environment property is used in the finish() method of BasicLightingModel + + builder.context.environment = cubeMapNode( this.envNode ); + + } + +} + +class BasicLightMapNode extends LightingNode { + + static get type() { + + return 'BasicLightMapNode'; + + } + + constructor( lightMapNode = null ) { + + super(); + + this.lightMapNode = lightMapNode; + + } + + setup( builder ) { + + // irradianceLightMap property is used in the indirectDiffuse() method of BasicLightingModel + + const RECIPROCAL_PI = float( 1 / Math.PI ); + + builder.context.irradianceLightMap = this.lightMapNode.mul( RECIPROCAL_PI ); + + } + +} + +class LightingModel { + + start( /*input, stack, builder*/ ) { } + + finish( /*input, stack, builder*/ ) { } + + direct( /*input, stack, builder*/ ) { } + + directRectArea( /*input, stack, builder*/ ) {} + + indirect( /*input, stack, builder*/ ) { } + + ambientOcclusion( /*input, stack, builder*/ ) { } + +} + +class BasicLightingModel extends LightingModel { + + constructor() { + + super(); + + } + + indirect( context, stack, builder ) { + + const ambientOcclusion = context.ambientOcclusion; + const reflectedLight = context.reflectedLight; + const irradianceLightMap = builder.context.irradianceLightMap; + + reflectedLight.indirectDiffuse.assign( vec4( 0.0 ) ); + + // accumulation (baked indirect lighting only) + + if ( irradianceLightMap ) { + + reflectedLight.indirectDiffuse.addAssign( irradianceLightMap ); + + } else { + + reflectedLight.indirectDiffuse.addAssign( vec4( 1.0, 1.0, 1.0, 0.0 ) ); + + } + + // modulation + + reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion ); + + reflectedLight.indirectDiffuse.mulAssign( diffuseColor.rgb ); + + } + + finish( context, stack, builder ) { + + const material = builder.material; + const outgoingLight = context.outgoingLight; + const envNode = builder.context.environment; + + if ( envNode ) { + + switch ( material.combine ) { + + case MultiplyOperation: + outgoingLight.rgb.assign( mix( outgoingLight.rgb, outgoingLight.rgb.mul( envNode.rgb ), materialSpecularStrength.mul( materialReflectivity ) ) ); + break; + + case MixOperation: + outgoingLight.rgb.assign( mix( outgoingLight.rgb, envNode.rgb, materialSpecularStrength.mul( materialReflectivity ) ) ); + break; + + case AddOperation: + outgoingLight.rgb.addAssign( envNode.rgb.mul( materialSpecularStrength.mul( materialReflectivity ) ) ); + break; + + default: + console.warn( 'THREE.BasicLightingModel: Unsupported .combine value:', material.combine ); + break; + + } + + } + + } + +} + +const _defaultValues$9 = /*@__PURE__*/ new MeshBasicMaterial(); + +class MeshBasicNodeMaterial extends NodeMaterial { + + static get type() { + + return 'MeshBasicNodeMaterial'; + + } + + constructor( parameters ) { + + super(); + + this.isMeshBasicNodeMaterial = true; + + this.lights = true; + + this.setDefaultValues( _defaultValues$9 ); + + this.setValues( parameters ); + + } + + setupNormal() { + + return normalView; // see #28839 + + } + + setupEnvironment( builder ) { + + const envNode = super.setupEnvironment( builder ); + + return envNode ? new BasicEnvironmentNode( envNode ) : null; + + } + + setupLightMap( builder ) { + + let node = null; + + if ( builder.material.lightMap ) { + + node = new BasicLightMapNode( materialLightMap ); + + } + + return node; + + } + + setupOutgoingLight() { + + return diffuseColor.rgb; + + } + + setupLightingModel() { + + return new BasicLightingModel(); + + } + +} + +const F_Schlick = /*@__PURE__*/ Fn( ( { f0, f90, dotVH } ) => { + + // Original approximation by Christophe Schlick '94 + // float fresnel = pow( 1.0 - dotVH, 5.0 ); + + // Optimized variant (presented by Epic at SIGGRAPH '13) + // https://cdn2.unrealengine.com/Resources/files/2013SiggraphPresentationsNotes-26915738.pdf + const fresnel = dotVH.mul( - 5.55473 ).sub( 6.98316 ).mul( dotVH ).exp2(); + + return f0.mul( fresnel.oneMinus() ).add( f90.mul( fresnel ) ); + +} ); // validated + +const BRDF_Lambert = /*@__PURE__*/ Fn( ( inputs ) => { + + return inputs.diffuseColor.mul( 1 / Math.PI ); // punctual light + +} ); // validated + +const G_BlinnPhong_Implicit = () => float( 0.25 ); + +const D_BlinnPhong = /*@__PURE__*/ Fn( ( { dotNH } ) => { + + return shininess.mul( float( 0.5 ) ).add( 1.0 ).mul( float( 1 / Math.PI ) ).mul( dotNH.pow( shininess ) ); + +} ); + +const BRDF_BlinnPhong = /*@__PURE__*/ Fn( ( { lightDirection } ) => { + + const halfDir = lightDirection.add( positionViewDirection ).normalize(); + + const dotNH = transformedNormalView.dot( halfDir ).clamp(); + const dotVH = positionViewDirection.dot( halfDir ).clamp(); + + const F = F_Schlick( { f0: specularColor, f90: 1.0, dotVH } ); + const G = G_BlinnPhong_Implicit(); + const D = D_BlinnPhong( { dotNH } ); + + return F.mul( G ).mul( D ); + +} ); + +class PhongLightingModel extends BasicLightingModel { + + constructor( specular = true ) { + + super(); + + this.specular = specular; + + } + + direct( { lightDirection, lightColor, reflectedLight } ) { + + const dotNL = transformedNormalView.dot( lightDirection ).clamp(); + const irradiance = dotNL.mul( lightColor ); + + reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) ); + + if ( this.specular === true ) { + + reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_BlinnPhong( { lightDirection } ) ).mul( materialSpecularStrength ) ); + + } + + } + + indirect( { ambientOcclusion, irradiance, reflectedLight } ) { + + reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) ); + + reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion ); + + } + +} + +const _defaultValues$8 = /*@__PURE__*/ new MeshLambertMaterial(); + +class MeshLambertNodeMaterial extends NodeMaterial { + + static get type() { + + return 'MeshLambertNodeMaterial'; + + } + + constructor( parameters ) { + + super(); + + this.isMeshLambertNodeMaterial = true; + + this.lights = true; + + this.setDefaultValues( _defaultValues$8 ); + + this.setValues( parameters ); + + } + + setupEnvironment( builder ) { + + const envNode = super.setupEnvironment( builder ); + + return envNode ? new BasicEnvironmentNode( envNode ) : null; + + } + + setupLightingModel( /*builder*/ ) { + + return new PhongLightingModel( false ); // ( specular ) -> force lambert + + } + +} + +const _defaultValues$7 = /*@__PURE__*/ new MeshPhongMaterial(); + +class MeshPhongNodeMaterial extends NodeMaterial { + + static get type() { + + return 'MeshPhongNodeMaterial'; + + } + + constructor( parameters ) { + + super(); + + this.isMeshPhongNodeMaterial = true; + + this.lights = true; + + this.shininessNode = null; + this.specularNode = null; + + this.setDefaultValues( _defaultValues$7 ); + + this.setValues( parameters ); + + } + + setupEnvironment( builder ) { + + const envNode = super.setupEnvironment( builder ); + + return envNode ? new BasicEnvironmentNode( envNode ) : null; + + } + + setupLightingModel( /*builder*/ ) { + + return new PhongLightingModel(); + + } + + setupVariants() { + + // SHININESS + + const shininessNode = ( this.shininessNode ? float( this.shininessNode ) : materialShininess ).max( 1e-4 ); // to prevent pow( 0.0, 0.0 ) + + shininess.assign( shininessNode ); + + // SPECULAR COLOR + + const specularNode = this.specularNode || materialSpecular; + + specularColor.assign( specularNode ); + + } + + copy( source ) { + + this.shininessNode = source.shininessNode; + this.specularNode = source.specularNode; + + return super.copy( source ); + + } + +} + +const getGeometryRoughness = /*@__PURE__*/ Fn( () => { + + const dxy = normalView.dFdx().abs().max( normalView.dFdy().abs() ); + const geometryRoughness = dxy.x.max( dxy.y ).max( dxy.z ); + + return geometryRoughness; + +} ); + +const getRoughness = /*@__PURE__*/ Fn( ( inputs ) => { + + const { roughness } = inputs; + + const geometryRoughness = getGeometryRoughness(); + + let roughnessFactor = roughness.max( 0.0525 ); // 0.0525 corresponds to the base mip of a 256 cubemap. + roughnessFactor = roughnessFactor.add( geometryRoughness ); + roughnessFactor = roughnessFactor.min( 1.0 ); + + return roughnessFactor; + +} ); + +// Moving Frostbite to Physically Based Rendering 3.0 - page 12, listing 2 +// https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf +const V_GGX_SmithCorrelated = /*@__PURE__*/ Fn( ( { alpha, dotNL, dotNV } ) => { + + const a2 = alpha.pow2(); + + const gv = dotNL.mul( a2.add( a2.oneMinus().mul( dotNV.pow2() ) ).sqrt() ); + const gl = dotNV.mul( a2.add( a2.oneMinus().mul( dotNL.pow2() ) ).sqrt() ); + + return div( 0.5, gv.add( gl ).max( EPSILON ) ); + +} ).setLayout( { + name: 'V_GGX_SmithCorrelated', + type: 'float', + inputs: [ + { name: 'alpha', type: 'float' }, + { name: 'dotNL', type: 'float' }, + { name: 'dotNV', type: 'float' } + ] +} ); // validated + +// https://google.github.io/filament/Filament.md.html#materialsystem/anisotropicmodel/anisotropicspecularbrdf + +const V_GGX_SmithCorrelated_Anisotropic = /*@__PURE__*/ Fn( ( { alphaT, alphaB, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL } ) => { + + const gv = dotNL.mul( vec3( alphaT.mul( dotTV ), alphaB.mul( dotBV ), dotNV ).length() ); + const gl = dotNV.mul( vec3( alphaT.mul( dotTL ), alphaB.mul( dotBL ), dotNL ).length() ); + const v = div( 0.5, gv.add( gl ) ); + + return v.saturate(); + +} ).setLayout( { + name: 'V_GGX_SmithCorrelated_Anisotropic', + type: 'float', + inputs: [ + { name: 'alphaT', type: 'float', qualifier: 'in' }, + { name: 'alphaB', type: 'float', qualifier: 'in' }, + { name: 'dotTV', type: 'float', qualifier: 'in' }, + { name: 'dotBV', type: 'float', qualifier: 'in' }, + { name: 'dotTL', type: 'float', qualifier: 'in' }, + { name: 'dotBL', type: 'float', qualifier: 'in' }, + { name: 'dotNV', type: 'float', qualifier: 'in' }, + { name: 'dotNL', type: 'float', qualifier: 'in' } + ] +} ); + +// Microfacet Models for Refraction through Rough Surfaces - equation (33) +// http://graphicrants.blogspot.com/2013/08/specular-brdf-reference.html +// alpha is "roughness squared" in Disney’s reparameterization +const D_GGX = /*@__PURE__*/ Fn( ( { alpha, dotNH } ) => { + + const a2 = alpha.pow2(); + + const denom = dotNH.pow2().mul( a2.oneMinus() ).oneMinus(); // avoid alpha = 0 with dotNH = 1 + + return a2.div( denom.pow2() ).mul( 1 / Math.PI ); + +} ).setLayout( { + name: 'D_GGX', + type: 'float', + inputs: [ + { name: 'alpha', type: 'float' }, + { name: 'dotNH', type: 'float' } + ] +} ); // validated + +const RECIPROCAL_PI = /*@__PURE__*/ float( 1 / Math.PI ); + +// https://google.github.io/filament/Filament.md.html#materialsystem/anisotropicmodel/anisotropicspecularbrdf + +const D_GGX_Anisotropic = /*@__PURE__*/ Fn( ( { alphaT, alphaB, dotNH, dotTH, dotBH } ) => { + + const a2 = alphaT.mul( alphaB ); + const v = vec3( alphaB.mul( dotTH ), alphaT.mul( dotBH ), a2.mul( dotNH ) ); + const v2 = v.dot( v ); + const w2 = a2.div( v2 ); + + return RECIPROCAL_PI.mul( a2.mul( w2.pow2() ) ); + +} ).setLayout( { + name: 'D_GGX_Anisotropic', + type: 'float', + inputs: [ + { name: 'alphaT', type: 'float', qualifier: 'in' }, + { name: 'alphaB', type: 'float', qualifier: 'in' }, + { name: 'dotNH', type: 'float', qualifier: 'in' }, + { name: 'dotTH', type: 'float', qualifier: 'in' }, + { name: 'dotBH', type: 'float', qualifier: 'in' } + ] +} ); + +// GGX Distribution, Schlick Fresnel, GGX_SmithCorrelated Visibility +const BRDF_GGX = /*@__PURE__*/ Fn( ( inputs ) => { + + const { lightDirection, f0, f90, roughness, f, USE_IRIDESCENCE, USE_ANISOTROPY } = inputs; + + const normalView = inputs.normalView || transformedNormalView; + + const alpha = roughness.pow2(); // UE4's roughness + + const halfDir = lightDirection.add( positionViewDirection ).normalize(); + + const dotNL = normalView.dot( lightDirection ).clamp(); + const dotNV = normalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV + const dotNH = normalView.dot( halfDir ).clamp(); + const dotVH = positionViewDirection.dot( halfDir ).clamp(); + + let F = F_Schlick( { f0, f90, dotVH } ); + let V, D; + + if ( defined( USE_IRIDESCENCE ) ) { + + F = iridescence.mix( F, f ); + + } + + if ( defined( USE_ANISOTROPY ) ) { + + const dotTL = anisotropyT.dot( lightDirection ); + const dotTV = anisotropyT.dot( positionViewDirection ); + const dotTH = anisotropyT.dot( halfDir ); + const dotBL = anisotropyB.dot( lightDirection ); + const dotBV = anisotropyB.dot( positionViewDirection ); + const dotBH = anisotropyB.dot( halfDir ); + + V = V_GGX_SmithCorrelated_Anisotropic( { alphaT, alphaB: alpha, dotTV, dotBV, dotTL, dotBL, dotNV, dotNL } ); + D = D_GGX_Anisotropic( { alphaT, alphaB: alpha, dotNH, dotTH, dotBH } ); + + } else { + + V = V_GGX_SmithCorrelated( { alpha, dotNL, dotNV } ); + D = D_GGX( { alpha, dotNH } ); + + } + + return F.mul( V ).mul( D ); + +} ); // validated + +// Analytical approximation of the DFG LUT, one half of the +// split-sum approximation used in indirect specular lighting. +// via 'environmentBRDF' from "Physically Based Shading on Mobile" +// https://www.unrealengine.com/blog/physically-based-shading-on-mobile +const DFGApprox = /*@__PURE__*/ Fn( ( { roughness, dotNV } ) => { + + const c0 = vec4( - 1, - 0.0275, - 0.572, 0.022 ); + + const c1 = vec4( 1, 0.0425, 1.04, - 0.04 ); + + const r = roughness.mul( c0 ).add( c1 ); + + const a004 = r.x.mul( r.x ).min( dotNV.mul( - 9.28 ).exp2() ).mul( r.x ).add( r.y ); + + const fab = vec2( - 1.04, 1.04 ).mul( a004 ).add( r.zw ); + + return fab; + +} ).setLayout( { + name: 'DFGApprox', + type: 'vec2', + inputs: [ + { name: 'roughness', type: 'float' }, + { name: 'dotNV', type: 'vec3' } + ] +} ); + +const EnvironmentBRDF = /*@__PURE__*/ Fn( ( inputs ) => { + + const { dotNV, specularColor, specularF90, roughness } = inputs; + + const fab = DFGApprox( { dotNV, roughness } ); + return specularColor.mul( fab.x ).add( specularF90.mul( fab.y ) ); + +} ); + +const Schlick_to_F0 = /*@__PURE__*/ Fn( ( { f, f90, dotVH } ) => { + + const x = dotVH.oneMinus().saturate(); + const x2 = x.mul( x ); + const x5 = x.mul( x2, x2 ).clamp( 0, .9999 ); + + return f.sub( vec3( f90 ).mul( x5 ) ).div( x5.oneMinus() ); + +} ).setLayout( { + name: 'Schlick_to_F0', + type: 'vec3', + inputs: [ + { name: 'f', type: 'vec3' }, + { name: 'f90', type: 'float' }, + { name: 'dotVH', type: 'float' } + ] +} ); + +// https://github.com/google/filament/blob/master/shaders/src/brdf.fs +const D_Charlie = /*@__PURE__*/ Fn( ( { roughness, dotNH } ) => { + + const alpha = roughness.pow2(); + + // Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF" + const invAlpha = float( 1.0 ).div( alpha ); + const cos2h = dotNH.pow2(); + const sin2h = cos2h.oneMinus().max( 0.0078125 ); // 2^(-14/2), so sin2h^2 > 0 in fp16 + + return float( 2.0 ).add( invAlpha ).mul( sin2h.pow( invAlpha.mul( 0.5 ) ) ).div( 2.0 * Math.PI ); + +} ).setLayout( { + name: 'D_Charlie', + type: 'float', + inputs: [ + { name: 'roughness', type: 'float' }, + { name: 'dotNH', type: 'float' } + ] +} ); + +// https://github.com/google/filament/blob/master/shaders/src/brdf.fs +const V_Neubelt = /*@__PURE__*/ Fn( ( { dotNV, dotNL } ) => { + + // Neubelt and Pettineo 2013, "Crafting a Next-gen Material Pipeline for The Order: 1886" + return float( 1.0 ).div( float( 4.0 ).mul( dotNL.add( dotNV ).sub( dotNL.mul( dotNV ) ) ) ); + +} ).setLayout( { + name: 'V_Neubelt', + type: 'float', + inputs: [ + { name: 'dotNV', type: 'float' }, + { name: 'dotNL', type: 'float' } + ] +} ); + +const BRDF_Sheen = /*@__PURE__*/ Fn( ( { lightDirection } ) => { + + const halfDir = lightDirection.add( positionViewDirection ).normalize(); + + const dotNL = transformedNormalView.dot( lightDirection ).clamp(); + const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); + const dotNH = transformedNormalView.dot( halfDir ).clamp(); + + const D = D_Charlie( { roughness: sheenRoughness, dotNH } ); + const V = V_Neubelt( { dotNV, dotNL } ); + + return sheen.mul( D ).mul( V ); + +} ); + +// Rect Area Light + +// Real-Time Polygonal-Light Shading with Linearly Transformed Cosines +// by Eric Heitz, Jonathan Dupuy, Stephen Hill and David Neubelt +// code: https://github.com/selfshadow/ltc_code/ + +const LTC_Uv = /*@__PURE__*/ Fn( ( { N, V, roughness } ) => { + + const LUT_SIZE = 64.0; + const LUT_SCALE = ( LUT_SIZE - 1.0 ) / LUT_SIZE; + const LUT_BIAS = 0.5 / LUT_SIZE; + + const dotNV = N.dot( V ).saturate(); + + // texture parameterized by sqrt( GGX alpha ) and sqrt( 1 - cos( theta ) ) + const uv = vec2( roughness, dotNV.oneMinus().sqrt() ); + + uv.assign( uv.mul( LUT_SCALE ).add( LUT_BIAS ) ); + + return uv; + +} ).setLayout( { + name: 'LTC_Uv', + type: 'vec2', + inputs: [ + { name: 'N', type: 'vec3' }, + { name: 'V', type: 'vec3' }, + { name: 'roughness', type: 'float' } + ] +} ); + +const LTC_ClippedSphereFormFactor = /*@__PURE__*/ Fn( ( { f } ) => { + + // Real-Time Area Lighting: a Journey from Research to Production (p.102) + // An approximation of the form factor of a horizon-clipped rectangle. + + const l = f.length(); + + return max$1( l.mul( l ).add( f.z ).div( l.add( 1.0 ) ), 0 ); + +} ).setLayout( { + name: 'LTC_ClippedSphereFormFactor', + type: 'float', + inputs: [ + { name: 'f', type: 'vec3' } + ] +} ); + +const LTC_EdgeVectorFormFactor = /*@__PURE__*/ Fn( ( { v1, v2 } ) => { + + const x = v1.dot( v2 ); + const y = x.abs().toVar(); + + // rational polynomial approximation to theta / sin( theta ) / 2PI + const a = y.mul( 0.0145206 ).add( 0.4965155 ).mul( y ).add( 0.8543985 ).toVar(); + const b = y.add( 4.1616724 ).mul( y ).add( 3.4175940 ).toVar(); + const v = a.div( b ); + + const theta_sintheta = x.greaterThan( 0.0 ).select( v, max$1( x.mul( x ).oneMinus(), 1e-7 ).inverseSqrt().mul( 0.5 ).sub( v ) ); + + return v1.cross( v2 ).mul( theta_sintheta ); + +} ).setLayout( { + name: 'LTC_EdgeVectorFormFactor', + type: 'vec3', + inputs: [ + { name: 'v1', type: 'vec3' }, + { name: 'v2', type: 'vec3' } + ] +} ); + +const LTC_Evaluate = /*@__PURE__*/ Fn( ( { N, V, P, mInv, p0, p1, p2, p3 } ) => { + + // bail if point is on back side of plane of light + // assumes ccw winding order of light vertices + const v1 = p1.sub( p0 ).toVar(); + const v2 = p3.sub( p0 ).toVar(); + + const lightNormal = v1.cross( v2 ); + const result = vec3().toVar(); + + If( lightNormal.dot( P.sub( p0 ) ).greaterThanEqual( 0.0 ), () => { + + // construct orthonormal basis around N + const T1 = V.sub( N.mul( V.dot( N ) ) ).normalize(); + const T2 = N.cross( T1 ).negate(); // negated from paper; possibly due to a different handedness of world coordinate system + + // compute transform + const mat = mInv.mul( mat3( T1, T2, N ).transpose() ).toVar(); + + // transform rect + // & project rect onto sphere + const coords0 = mat.mul( p0.sub( P ) ).normalize().toVar(); + const coords1 = mat.mul( p1.sub( P ) ).normalize().toVar(); + const coords2 = mat.mul( p2.sub( P ) ).normalize().toVar(); + const coords3 = mat.mul( p3.sub( P ) ).normalize().toVar(); + + // calculate vector form factor + const vectorFormFactor = vec3( 0 ).toVar(); + vectorFormFactor.addAssign( LTC_EdgeVectorFormFactor( { v1: coords0, v2: coords1 } ) ); + vectorFormFactor.addAssign( LTC_EdgeVectorFormFactor( { v1: coords1, v2: coords2 } ) ); + vectorFormFactor.addAssign( LTC_EdgeVectorFormFactor( { v1: coords2, v2: coords3 } ) ); + vectorFormFactor.addAssign( LTC_EdgeVectorFormFactor( { v1: coords3, v2: coords0 } ) ); + + // adjust for horizon clipping + result.assign( vec3( LTC_ClippedSphereFormFactor( { f: vectorFormFactor } ) ) ); + + } ); + + return result; + +} ).setLayout( { + name: 'LTC_Evaluate', + type: 'vec3', + inputs: [ + { name: 'N', type: 'vec3' }, + { name: 'V', type: 'vec3' }, + { name: 'P', type: 'vec3' }, + { name: 'mInv', type: 'mat3' }, + { name: 'p0', type: 'vec3' }, + { name: 'p1', type: 'vec3' }, + { name: 'p2', type: 'vec3' }, + { name: 'p3', type: 'vec3' } + ] +} ); + +// Mipped Bicubic Texture Filtering by N8 +// https://www.shadertoy.com/view/Dl2SDW + +const bC = 1.0 / 6.0; + +const w0 = ( a ) => mul( bC, mul( a, mul( a, a.negate().add( 3.0 ) ).sub( 3.0 ) ).add( 1.0 ) ); + +const w1 = ( a ) => mul( bC, mul( a, mul( a, mul( 3.0, a ).sub( 6.0 ) ) ).add( 4.0 ) ); + +const w2 = ( a ) => mul( bC, mul( a, mul( a, mul( - 3.0, a ).add( 3.0 ) ).add( 3.0 ) ).add( 1.0 ) ); + +const w3 = ( a ) => mul( bC, pow( a, 3 ) ); + +const g0 = ( a ) => w0( a ).add( w1( a ) ); + +const g1 = ( a ) => w2( a ).add( w3( a ) ); + +// h0 and h1 are the two offset functions +const h0 = ( a ) => add( - 1.0, w1( a ).div( w0( a ).add( w1( a ) ) ) ); + +const h1 = ( a ) => add( 1.0, w3( a ).div( w2( a ).add( w3( a ) ) ) ); + +const bicubic = ( textureNode, texelSize, lod ) => { + + const uv = textureNode.uvNode; + const uvScaled = mul( uv, texelSize.zw ).add( 0.5 ); + + const iuv = floor( uvScaled ); + const fuv = fract( uvScaled ); + + const g0x = g0( fuv.x ); + const g1x = g1( fuv.x ); + const h0x = h0( fuv.x ); + const h1x = h1( fuv.x ); + const h0y = h0( fuv.y ); + const h1y = h1( fuv.y ); + + const p0 = vec2( iuv.x.add( h0x ), iuv.y.add( h0y ) ).sub( 0.5 ).mul( texelSize.xy ); + const p1 = vec2( iuv.x.add( h1x ), iuv.y.add( h0y ) ).sub( 0.5 ).mul( texelSize.xy ); + const p2 = vec2( iuv.x.add( h0x ), iuv.y.add( h1y ) ).sub( 0.5 ).mul( texelSize.xy ); + const p3 = vec2( iuv.x.add( h1x ), iuv.y.add( h1y ) ).sub( 0.5 ).mul( texelSize.xy ); + + const a = g0( fuv.y ).mul( add( g0x.mul( textureNode.uv( p0 ).level( lod ) ), g1x.mul( textureNode.uv( p1 ).level( lod ) ) ) ); + const b = g1( fuv.y ).mul( add( g0x.mul( textureNode.uv( p2 ).level( lod ) ), g1x.mul( textureNode.uv( p3 ).level( lod ) ) ) ); + + return a.add( b ); + +}; + +const textureBicubic = /*@__PURE__*/ Fn( ( [ textureNode, lodNode = float( 3 ) ] ) => { + + const fLodSize = vec2( textureNode.size( int( lodNode ) ) ); + const cLodSize = vec2( textureNode.size( int( lodNode.add( 1.0 ) ) ) ); + const fLodSizeInv = div( 1.0, fLodSize ); + const cLodSizeInv = div( 1.0, cLodSize ); + const fSample = bicubic( textureNode, vec4( fLodSizeInv, fLodSize ), floor( lodNode ) ); + const cSample = bicubic( textureNode, vec4( cLodSizeInv, cLodSize ), ceil( lodNode ) ); + + return fract( lodNode ).mix( fSample, cSample ); + +} ); + +// +// Transmission +// + +const getVolumeTransmissionRay = /*@__PURE__*/ Fn( ( [ n, v, thickness, ior, modelMatrix ] ) => { + + // Direction of refracted light. + const refractionVector = vec3( refract( v.negate(), normalize( n ), div( 1.0, ior ) ) ); + + // Compute rotation-independant scaling of the model matrix. + const modelScale = vec3( + length( modelMatrix[ 0 ].xyz ), + length( modelMatrix[ 1 ].xyz ), + length( modelMatrix[ 2 ].xyz ) + ); + + // The thickness is specified in local space. + return normalize( refractionVector ).mul( thickness.mul( modelScale ) ); + +} ).setLayout( { + name: 'getVolumeTransmissionRay', + type: 'vec3', + inputs: [ + { name: 'n', type: 'vec3' }, + { name: 'v', type: 'vec3' }, + { name: 'thickness', type: 'float' }, + { name: 'ior', type: 'float' }, + { name: 'modelMatrix', type: 'mat4' } + ] +} ); + +const applyIorToRoughness = /*@__PURE__*/ Fn( ( [ roughness, ior ] ) => { + + // Scale roughness with IOR so that an IOR of 1.0 results in no microfacet refraction and + // an IOR of 1.5 results in the default amount of microfacet refraction. + return roughness.mul( clamp( ior.mul( 2.0 ).sub( 2.0 ), 0.0, 1.0 ) ); + +} ).setLayout( { + name: 'applyIorToRoughness', + type: 'float', + inputs: [ + { name: 'roughness', type: 'float' }, + { name: 'ior', type: 'float' } + ] +} ); + +const singleViewportMipTexture = /*@__PURE__*/ viewportMipTexture(); + +const getTransmissionSample = /*@__PURE__*/ Fn( ( [ fragCoord, roughness, ior ] ) => { + + const transmissionSample = singleViewportMipTexture.uv( fragCoord ); + //const transmissionSample = viewportMipTexture( fragCoord ); + + const lod = log2( float( screenSize.x ) ).mul( applyIorToRoughness( roughness, ior ) ); + + return textureBicubic( transmissionSample, lod ); + +} ); + +const volumeAttenuation = /*@__PURE__*/ Fn( ( [ transmissionDistance, attenuationColor, attenuationDistance ] ) => { + + If( attenuationDistance.notEqual( 0 ), () => { + + // Compute light attenuation using Beer's law. + const attenuationCoefficient = log( attenuationColor ).negate().div( attenuationDistance ); + const transmittance = exp( attenuationCoefficient.negate().mul( transmissionDistance ) ); + + return transmittance; + + } ); + + // Attenuation distance is +∞, i.e. the transmitted color is not attenuated at all. + return vec3( 1.0 ); + +} ).setLayout( { + name: 'volumeAttenuation', + type: 'vec3', + inputs: [ + { name: 'transmissionDistance', type: 'float' }, + { name: 'attenuationColor', type: 'vec3' }, + { name: 'attenuationDistance', type: 'float' } + ] +} ); + +const getIBLVolumeRefraction = /*@__PURE__*/ Fn( ( [ n, v, roughness, diffuseColor, specularColor, specularF90, position, modelMatrix, viewMatrix, projMatrix, ior, thickness, attenuationColor, attenuationDistance, dispersion ] ) => { + + let transmittedLight, transmittance; + + if ( dispersion ) { + + transmittedLight = vec4().toVar(); + transmittance = vec3().toVar(); + + const halfSpread = ior.sub( 1.0 ).mul( dispersion.mul( 0.025 ) ); + const iors = vec3( ior.sub( halfSpread ), ior, ior.add( halfSpread ) ); + + Loop( { start: 0, end: 3 }, ( { i } ) => { + + const ior = iors.element( i ); + + const transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); + const refractedRayExit = position.add( transmissionRay ); + + // Project refracted vector on the framebuffer, while mapping to normalized device coordinates. + const ndcPos = projMatrix.mul( viewMatrix.mul( vec4( refractedRayExit, 1.0 ) ) ); + const refractionCoords = vec2( ndcPos.xy.div( ndcPos.w ) ).toVar(); + refractionCoords.addAssign( 1.0 ); + refractionCoords.divAssign( 2.0 ); + refractionCoords.assign( vec2( refractionCoords.x, refractionCoords.y.oneMinus() ) ); // webgpu + + // Sample framebuffer to get pixel the refracted ray hits. + const transmissionSample = getTransmissionSample( refractionCoords, roughness, ior ); + + transmittedLight.element( i ).assign( transmissionSample.element( i ) ); + transmittedLight.a.addAssign( transmissionSample.a ); + + transmittance.element( i ).assign( diffuseColor.element( i ).mul( volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ).element( i ) ) ); + + } ); + + transmittedLight.a.divAssign( 3.0 ); + + } else { + + const transmissionRay = getVolumeTransmissionRay( n, v, thickness, ior, modelMatrix ); + const refractedRayExit = position.add( transmissionRay ); + + // Project refracted vector on the framebuffer, while mapping to normalized device coordinates. + const ndcPos = projMatrix.mul( viewMatrix.mul( vec4( refractedRayExit, 1.0 ) ) ); + const refractionCoords = vec2( ndcPos.xy.div( ndcPos.w ) ).toVar(); + refractionCoords.addAssign( 1.0 ); + refractionCoords.divAssign( 2.0 ); + refractionCoords.assign( vec2( refractionCoords.x, refractionCoords.y.oneMinus() ) ); // webgpu + + // Sample framebuffer to get pixel the refracted ray hits. + transmittedLight = getTransmissionSample( refractionCoords, roughness, ior ); + transmittance = diffuseColor.mul( volumeAttenuation( length( transmissionRay ), attenuationColor, attenuationDistance ) ); + + } + + const attenuatedColor = transmittance.rgb.mul( transmittedLight.rgb ); + const dotNV = n.dot( v ).clamp(); + + // Get the specular component. + const F = vec3( EnvironmentBRDF( { // n, v, specularColor, specularF90, roughness + dotNV, + specularColor, + specularF90, + roughness + } ) ); + + // As less light is transmitted, the opacity should be increased. This simple approximation does a decent job + // of modulating a CSS background, and has no effect when the buffer is opaque, due to a solid object or clear color. + const transmittanceFactor = transmittance.r.add( transmittance.g, transmittance.b ).div( 3.0 ); + + return vec4( F.oneMinus().mul( attenuatedColor ), transmittedLight.a.oneMinus().mul( transmittanceFactor ).oneMinus() ); + +} ); + +// +// Iridescence +// + +// XYZ to linear-sRGB color space +const XYZ_TO_REC709 = /*@__PURE__*/ mat3( + 3.2404542, - 0.9692660, 0.0556434, + - 1.5371385, 1.8760108, - 0.2040259, + - 0.4985314, 0.0415560, 1.0572252 +); + +// Assume air interface for top +// Note: We don't handle the case fresnel0 == 1 +const Fresnel0ToIor = ( fresnel0 ) => { + + const sqrtF0 = fresnel0.sqrt(); + return vec3( 1.0 ).add( sqrtF0 ).div( vec3( 1.0 ).sub( sqrtF0 ) ); + +}; + +// ior is a value between 1.0 and 3.0. 1.0 is air interface +const IorToFresnel0 = ( transmittedIor, incidentIor ) => { + + return transmittedIor.sub( incidentIor ).div( transmittedIor.add( incidentIor ) ).pow2(); + +}; + +// Fresnel equations for dielectric/dielectric interfaces. +// Ref: https://belcour.github.io/blog/research/2017/05/01/brdf-thin-film.html +// Evaluation XYZ sensitivity curves in Fourier space +const evalSensitivity = ( OPD, shift ) => { + + const phase = OPD.mul( 2.0 * Math.PI * 1.0e-9 ); + const val = vec3( 5.4856e-13, 4.4201e-13, 5.2481e-13 ); + const pos = vec3( 1.6810e+06, 1.7953e+06, 2.2084e+06 ); + const VAR = vec3( 4.3278e+09, 9.3046e+09, 6.6121e+09 ); + + const x = float( 9.7470e-14 * Math.sqrt( 2.0 * Math.PI * 4.5282e+09 ) ).mul( phase.mul( 2.2399e+06 ).add( shift.x ).cos() ).mul( phase.pow2().mul( - 4.5282e+09 ).exp() ); + + let xyz = val.mul( VAR.mul( 2.0 * Math.PI ).sqrt() ).mul( pos.mul( phase ).add( shift ).cos() ).mul( phase.pow2().negate().mul( VAR ).exp() ); + xyz = vec3( xyz.x.add( x ), xyz.y, xyz.z ).div( 1.0685e-7 ); + + const rgb = XYZ_TO_REC709.mul( xyz ); + + return rgb; + +}; + +const evalIridescence = /*@__PURE__*/ Fn( ( { outsideIOR, eta2, cosTheta1, thinFilmThickness, baseF0 } ) => { + + // Force iridescenceIOR -> outsideIOR when thinFilmThickness -> 0.0 + const iridescenceIOR = mix( outsideIOR, eta2, smoothstep( 0.0, 0.03, thinFilmThickness ) ); + // Evaluate the cosTheta on the base layer (Snell law) + const sinTheta2Sq = outsideIOR.div( iridescenceIOR ).pow2().mul( float( 1 ).sub( cosTheta1.pow2() ) ); + + // Handle TIR: + const cosTheta2Sq = float( 1 ).sub( sinTheta2Sq ); + /*if ( cosTheta2Sq < 0.0 ) { + + return vec3( 1.0 ); + + }*/ + + const cosTheta2 = cosTheta2Sq.sqrt(); + + // First interface + const R0 = IorToFresnel0( iridescenceIOR, outsideIOR ); + const R12 = F_Schlick( { f0: R0, f90: 1.0, dotVH: cosTheta1 } ); + //const R21 = R12; + const T121 = R12.oneMinus(); + const phi12 = iridescenceIOR.lessThan( outsideIOR ).select( Math.PI, 0.0 ); + const phi21 = float( Math.PI ).sub( phi12 ); + + // Second interface + const baseIOR = Fresnel0ToIor( baseF0.clamp( 0.0, 0.9999 ) ); // guard against 1.0 + const R1 = IorToFresnel0( baseIOR, iridescenceIOR.toVec3() ); + const R23 = F_Schlick( { f0: R1, f90: 1.0, dotVH: cosTheta2 } ); + const phi23 = vec3( + baseIOR.x.lessThan( iridescenceIOR ).select( Math.PI, 0.0 ), + baseIOR.y.lessThan( iridescenceIOR ).select( Math.PI, 0.0 ), + baseIOR.z.lessThan( iridescenceIOR ).select( Math.PI, 0.0 ) + ); + + // Phase shift + const OPD = iridescenceIOR.mul( thinFilmThickness, cosTheta2, 2.0 ); + const phi = vec3( phi21 ).add( phi23 ); + + // Compound terms + const R123 = R12.mul( R23 ).clamp( 1e-5, 0.9999 ); + const r123 = R123.sqrt(); + const Rs = T121.pow2().mul( R23 ).div( vec3( 1.0 ).sub( R123 ) ); + + // Reflectance term for m = 0 (DC term amplitude) + const C0 = R12.add( Rs ); + let I = C0; + + // Reflectance term for m > 0 (pairs of diracs) + let Cm = Rs.sub( T121 ); + for ( let m = 1; m <= 2; ++ m ) { + + Cm = Cm.mul( r123 ); + const Sm = evalSensitivity( float( m ).mul( OPD ), float( m ).mul( phi ) ).mul( 2.0 ); + I = I.add( Cm.mul( Sm ) ); + + } + + // Since out of gamut colors might be produced, negative color values are clamped to 0. + return I.max( vec3( 0.0 ) ); + +} ).setLayout( { + name: 'evalIridescence', + type: 'vec3', + inputs: [ + { name: 'outsideIOR', type: 'float' }, + { name: 'eta2', type: 'float' }, + { name: 'cosTheta1', type: 'float' }, + { name: 'thinFilmThickness', type: 'float' }, + { name: 'baseF0', type: 'vec3' } + ] +} ); + +// +// Sheen +// + +// This is a curve-fit approxmation to the "Charlie sheen" BRDF integrated over the hemisphere from +// Estevez and Kulla 2017, "Production Friendly Microfacet Sheen BRDF". The analysis can be found +// in the Sheen section of https://drive.google.com/file/d/1T0D1VSyR4AllqIJTQAraEIzjlb5h4FKH/view?usp=sharing +const IBLSheenBRDF = /*@__PURE__*/ Fn( ( { normal, viewDir, roughness } ) => { + + const dotNV = normal.dot( viewDir ).saturate(); + + const r2 = roughness.pow2(); + + const a = select( + roughness.lessThan( 0.25 ), + float( - 339.2 ).mul( r2 ).add( float( 161.4 ).mul( roughness ) ).sub( 25.9 ), + float( - 8.48 ).mul( r2 ).add( float( 14.3 ).mul( roughness ) ).sub( 9.95 ) + ); + + const b = select( + roughness.lessThan( 0.25 ), + float( 44.0 ).mul( r2 ).sub( float( 23.7 ).mul( roughness ) ).add( 3.26 ), + float( 1.97 ).mul( r2 ).sub( float( 3.27 ).mul( roughness ) ).add( 0.72 ) + ); + + const DG = select( roughness.lessThan( 0.25 ), 0.0, float( 0.1 ).mul( roughness ).sub( 0.025 ) ).add( a.mul( dotNV ).add( b ).exp() ); + + return DG.mul( 1.0 / Math.PI ).saturate(); + +} ); + +const clearcoatF0 = vec3( 0.04 ); +const clearcoatF90 = float( 1 ); + +// + +class PhysicalLightingModel extends LightingModel { + + constructor( clearcoat = false, sheen = false, iridescence = false, anisotropy = false, transmission = false, dispersion = false ) { + + super(); + + this.clearcoat = clearcoat; + this.sheen = sheen; + this.iridescence = iridescence; + this.anisotropy = anisotropy; + this.transmission = transmission; + this.dispersion = dispersion; + + this.clearcoatRadiance = null; + this.clearcoatSpecularDirect = null; + this.clearcoatSpecularIndirect = null; + this.sheenSpecularDirect = null; + this.sheenSpecularIndirect = null; + this.iridescenceFresnel = null; + this.iridescenceF0 = null; + + } + + start( context ) { + + if ( this.clearcoat === true ) { + + this.clearcoatRadiance = vec3().toVar( 'clearcoatRadiance' ); + this.clearcoatSpecularDirect = vec3().toVar( 'clearcoatSpecularDirect' ); + this.clearcoatSpecularIndirect = vec3().toVar( 'clearcoatSpecularIndirect' ); + + } + + if ( this.sheen === true ) { + + this.sheenSpecularDirect = vec3().toVar( 'sheenSpecularDirect' ); + this.sheenSpecularIndirect = vec3().toVar( 'sheenSpecularIndirect' ); + + } + + if ( this.iridescence === true ) { + + const dotNVi = transformedNormalView.dot( positionViewDirection ).clamp(); + + this.iridescenceFresnel = evalIridescence( { + outsideIOR: float( 1.0 ), + eta2: iridescenceIOR, + cosTheta1: dotNVi, + thinFilmThickness: iridescenceThickness, + baseF0: specularColor + } ); + + this.iridescenceF0 = Schlick_to_F0( { f: this.iridescenceFresnel, f90: 1.0, dotVH: dotNVi } ); + + } + + if ( this.transmission === true ) { + + const position = positionWorld; + const v = cameraPosition.sub( positionWorld ).normalize(); // TODO: Create Node for this, same issue in MaterialX + const n = transformedNormalWorld; + + context.backdrop = getIBLVolumeRefraction( + n, + v, + roughness, + diffuseColor, + specularColor, + specularF90, // specularF90 + position, // positionWorld + modelWorldMatrix, // modelMatrix + cameraViewMatrix, // viewMatrix + cameraProjectionMatrix, // projMatrix + ior, + thickness, + attenuationColor, + attenuationDistance, + this.dispersion ? dispersion : null + ); + + context.backdropAlpha = transmission; + + diffuseColor.a.mulAssign( mix( 1, context.backdrop.a, transmission ) ); + + } + + } + + // Fdez-Agüera's "Multiple-Scattering Microfacet Model for Real-Time Image Based Lighting" + // Approximates multiscattering in order to preserve energy. + // http://www.jcgt.org/published/0008/01/03/ + + computeMultiscattering( singleScatter, multiScatter, specularF90 ) { + + const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV + + const fab = DFGApprox( { roughness, dotNV } ); + + const Fr = this.iridescenceF0 ? iridescence.mix( specularColor, this.iridescenceF0 ) : specularColor; + + const FssEss = Fr.mul( fab.x ).add( specularF90.mul( fab.y ) ); + + const Ess = fab.x.add( fab.y ); + const Ems = Ess.oneMinus(); + + const Favg = specularColor.add( specularColor.oneMinus().mul( 0.047619 ) ); // 1/21 + const Fms = FssEss.mul( Favg ).div( Ems.mul( Favg ).oneMinus() ); + + singleScatter.addAssign( FssEss ); + multiScatter.addAssign( Fms.mul( Ems ) ); + + } + + direct( { lightDirection, lightColor, reflectedLight } ) { + + const dotNL = transformedNormalView.dot( lightDirection ).clamp(); + const irradiance = dotNL.mul( lightColor ); + + if ( this.sheen === true ) { + + this.sheenSpecularDirect.addAssign( irradiance.mul( BRDF_Sheen( { lightDirection } ) ) ); + + } + + if ( this.clearcoat === true ) { + + const dotNLcc = transformedClearcoatNormalView.dot( lightDirection ).clamp(); + const ccIrradiance = dotNLcc.mul( lightColor ); + + this.clearcoatSpecularDirect.addAssign( ccIrradiance.mul( BRDF_GGX( { lightDirection, f0: clearcoatF0, f90: clearcoatF90, roughness: clearcoatRoughness, normalView: transformedClearcoatNormalView } ) ) ); + + } + + reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) ); + + reflectedLight.directSpecular.addAssign( irradiance.mul( BRDF_GGX( { lightDirection, f0: specularColor, f90: 1, roughness, iridescence: this.iridescence, f: this.iridescenceFresnel, USE_IRIDESCENCE: this.iridescence, USE_ANISOTROPY: this.anisotropy } ) ) ); + + } + + directRectArea( { lightColor, lightPosition, halfWidth, halfHeight, reflectedLight, ltc_1, ltc_2 } ) { + + const p0 = lightPosition.add( halfWidth ).sub( halfHeight ); // counterclockwise; light shines in local neg z direction + const p1 = lightPosition.sub( halfWidth ).sub( halfHeight ); + const p2 = lightPosition.sub( halfWidth ).add( halfHeight ); + const p3 = lightPosition.add( halfWidth ).add( halfHeight ); + + const N = transformedNormalView; + const V = positionViewDirection; + const P = positionView.toVar(); + + const uv = LTC_Uv( { N, V, roughness } ); + + const t1 = ltc_1.uv( uv ).toVar(); + const t2 = ltc_2.uv( uv ).toVar(); + + const mInv = mat3( + vec3( t1.x, 0, t1.y ), + vec3( 0, 1, 0 ), + vec3( t1.z, 0, t1.w ) + ).toVar(); + + // LTC Fresnel Approximation by Stephen Hill + // http://blog.selfshadow.com/publications/s2016-advances/s2016_ltc_fresnel.pdf + const fresnel = specularColor.mul( t2.x ).add( specularColor.oneMinus().mul( t2.y ) ).toVar(); + + reflectedLight.directSpecular.addAssign( lightColor.mul( fresnel ).mul( LTC_Evaluate( { N, V, P, mInv, p0, p1, p2, p3 } ) ) ); + + reflectedLight.directDiffuse.addAssign( lightColor.mul( diffuseColor ).mul( LTC_Evaluate( { N, V, P, mInv: mat3( 1, 0, 0, 0, 1, 0, 0, 0, 1 ), p0, p1, p2, p3 } ) ) ); + + } + + indirect( context, stack, builder ) { + + this.indirectDiffuse( context, stack, builder ); + this.indirectSpecular( context, stack, builder ); + this.ambientOcclusion( context, stack, builder ); + + } + + indirectDiffuse( { irradiance, reflectedLight } ) { + + reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) ); + + } + + indirectSpecular( { radiance, iblIrradiance, reflectedLight } ) { + + if ( this.sheen === true ) { + + this.sheenSpecularIndirect.addAssign( iblIrradiance.mul( + sheen, + IBLSheenBRDF( { + normal: transformedNormalView, + viewDir: positionViewDirection, + roughness: sheenRoughness + } ) + ) ); + + } + + if ( this.clearcoat === true ) { + + const dotNVcc = transformedClearcoatNormalView.dot( positionViewDirection ).clamp(); + + const clearcoatEnv = EnvironmentBRDF( { + dotNV: dotNVcc, + specularColor: clearcoatF0, + specularF90: clearcoatF90, + roughness: clearcoatRoughness + } ); + + this.clearcoatSpecularIndirect.addAssign( this.clearcoatRadiance.mul( clearcoatEnv ) ); + + } + + // Both indirect specular and indirect diffuse light accumulate here + + const singleScattering = vec3().toVar( 'singleScattering' ); + const multiScattering = vec3().toVar( 'multiScattering' ); + const cosineWeightedIrradiance = iblIrradiance.mul( 1 / Math.PI ); + + this.computeMultiscattering( singleScattering, multiScattering, specularF90 ); + + const totalScattering = singleScattering.add( multiScattering ); + + const diffuse = diffuseColor.mul( totalScattering.r.max( totalScattering.g ).max( totalScattering.b ).oneMinus() ); + + reflectedLight.indirectSpecular.addAssign( radiance.mul( singleScattering ) ); + reflectedLight.indirectSpecular.addAssign( multiScattering.mul( cosineWeightedIrradiance ) ); + + reflectedLight.indirectDiffuse.addAssign( diffuse.mul( cosineWeightedIrradiance ) ); + + } + + ambientOcclusion( { ambientOcclusion, reflectedLight } ) { + + const dotNV = transformedNormalView.dot( positionViewDirection ).clamp(); // @ TODO: Move to core dotNV + + const aoNV = dotNV.add( ambientOcclusion ); + const aoExp = roughness.mul( - 16.0 ).oneMinus().negate().exp2(); + + const aoNode = ambientOcclusion.sub( aoNV.pow( aoExp ).oneMinus() ).clamp(); + + if ( this.clearcoat === true ) { + + this.clearcoatSpecularIndirect.mulAssign( ambientOcclusion ); + + } + + if ( this.sheen === true ) { + + this.sheenSpecularIndirect.mulAssign( ambientOcclusion ); + + } + + reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion ); + reflectedLight.indirectSpecular.mulAssign( aoNode ); + + } + + finish( context ) { + + const { outgoingLight } = context; + + if ( this.clearcoat === true ) { + + const dotNVcc = transformedClearcoatNormalView.dot( positionViewDirection ).clamp(); + + const Fcc = F_Schlick( { + dotVH: dotNVcc, + f0: clearcoatF0, + f90: clearcoatF90 + } ); + + const clearcoatLight = outgoingLight.mul( clearcoat.mul( Fcc ).oneMinus() ).add( this.clearcoatSpecularDirect.add( this.clearcoatSpecularIndirect ).mul( clearcoat ) ); + + outgoingLight.assign( clearcoatLight ); + + } + + if ( this.sheen === true ) { + + const sheenEnergyComp = sheen.r.max( sheen.g ).max( sheen.b ).mul( 0.157 ).oneMinus(); + const sheenLight = outgoingLight.mul( sheenEnergyComp ).add( this.sheenSpecularDirect, this.sheenSpecularIndirect ); + + outgoingLight.assign( sheenLight ); + + } + + } + +} + +// These defines must match with PMREMGenerator + +const cubeUV_r0 = /*@__PURE__*/ float( 1.0 ); +const cubeUV_m0 = /*@__PURE__*/ float( - 2.0 ); +const cubeUV_r1 = /*@__PURE__*/ float( 0.8 ); +const cubeUV_m1 = /*@__PURE__*/ float( - 1.0 ); +const cubeUV_r4 = /*@__PURE__*/ float( 0.4 ); +const cubeUV_m4 = /*@__PURE__*/ float( 2.0 ); +const cubeUV_r5 = /*@__PURE__*/ float( 0.305 ); +const cubeUV_m5 = /*@__PURE__*/ float( 3.0 ); +const cubeUV_r6 = /*@__PURE__*/ float( 0.21 ); +const cubeUV_m6 = /*@__PURE__*/ float( 4.0 ); + +const cubeUV_minMipLevel = /*@__PURE__*/ float( 4.0 ); +const cubeUV_minTileSize = /*@__PURE__*/ float( 16.0 ); + +// These shader functions convert between the UV coordinates of a single face of +// a cubemap, the 0-5 integer index of a cube face, and the direction vector for +// sampling a textureCube (not generally normalized ). + +const getFace = /*@__PURE__*/ Fn( ( [ direction ] ) => { + + const absDirection = vec3( abs( direction ) ).toVar(); + const face = float( - 1.0 ).toVar(); + + If( absDirection.x.greaterThan( absDirection.z ), () => { + + If( absDirection.x.greaterThan( absDirection.y ), () => { + + face.assign( select( direction.x.greaterThan( 0.0 ), 0.0, 3.0 ) ); + + } ).Else( () => { + + face.assign( select( direction.y.greaterThan( 0.0 ), 1.0, 4.0 ) ); + + } ); + + } ).Else( () => { + + If( absDirection.z.greaterThan( absDirection.y ), () => { + + face.assign( select( direction.z.greaterThan( 0.0 ), 2.0, 5.0 ) ); + + } ).Else( () => { + + face.assign( select( direction.y.greaterThan( 0.0 ), 1.0, 4.0 ) ); + + } ); + + } ); + + return face; + +} ).setLayout( { + name: 'getFace', + type: 'float', + inputs: [ + { name: 'direction', type: 'vec3' } + ] +} ); + +// RH coordinate system; PMREM face-indexing convention +const getUV = /*@__PURE__*/ Fn( ( [ direction, face ] ) => { + + const uv = vec2().toVar(); + + If( face.equal( 0.0 ), () => { + + uv.assign( vec2( direction.z, direction.y ).div( abs( direction.x ) ) ); // pos x + + } ).ElseIf( face.equal( 1.0 ), () => { + + uv.assign( vec2( direction.x.negate(), direction.z.negate() ).div( abs( direction.y ) ) ); // pos y + + } ).ElseIf( face.equal( 2.0 ), () => { + + uv.assign( vec2( direction.x.negate(), direction.y ).div( abs( direction.z ) ) ); // pos z + + } ).ElseIf( face.equal( 3.0 ), () => { + + uv.assign( vec2( direction.z.negate(), direction.y ).div( abs( direction.x ) ) ); // neg x + + } ).ElseIf( face.equal( 4.0 ), () => { + + uv.assign( vec2( direction.x.negate(), direction.z ).div( abs( direction.y ) ) ); // neg y + + } ).Else( () => { + + uv.assign( vec2( direction.x, direction.y ).div( abs( direction.z ) ) ); // neg z + + } ); + + return mul( 0.5, uv.add( 1.0 ) ); + +} ).setLayout( { + name: 'getUV', + type: 'vec2', + inputs: [ + { name: 'direction', type: 'vec3' }, + { name: 'face', type: 'float' } + ] +} ); + +const roughnessToMip = /*@__PURE__*/ Fn( ( [ roughness ] ) => { + + const mip = float( 0.0 ).toVar(); + + If( roughness.greaterThanEqual( cubeUV_r1 ), () => { + + mip.assign( cubeUV_r0.sub( roughness ).mul( cubeUV_m1.sub( cubeUV_m0 ) ).div( cubeUV_r0.sub( cubeUV_r1 ) ).add( cubeUV_m0 ) ); + + } ).ElseIf( roughness.greaterThanEqual( cubeUV_r4 ), () => { + + mip.assign( cubeUV_r1.sub( roughness ).mul( cubeUV_m4.sub( cubeUV_m1 ) ).div( cubeUV_r1.sub( cubeUV_r4 ) ).add( cubeUV_m1 ) ); + + } ).ElseIf( roughness.greaterThanEqual( cubeUV_r5 ), () => { + + mip.assign( cubeUV_r4.sub( roughness ).mul( cubeUV_m5.sub( cubeUV_m4 ) ).div( cubeUV_r4.sub( cubeUV_r5 ) ).add( cubeUV_m4 ) ); + + } ).ElseIf( roughness.greaterThanEqual( cubeUV_r6 ), () => { + + mip.assign( cubeUV_r5.sub( roughness ).mul( cubeUV_m6.sub( cubeUV_m5 ) ).div( cubeUV_r5.sub( cubeUV_r6 ) ).add( cubeUV_m5 ) ); + + } ).Else( () => { + + mip.assign( float( - 2.0 ).mul( log2( mul( 1.16, roughness ) ) ) ); // 1.16 = 1.79^0.25 + + } ); + + return mip; + +} ).setLayout( { + name: 'roughnessToMip', + type: 'float', + inputs: [ + { name: 'roughness', type: 'float' } + ] +} ); + +// RH coordinate system; PMREM face-indexing convention +const getDirection = /*@__PURE__*/ Fn( ( [ uv_immutable, face ] ) => { + + const uv = uv_immutable.toVar(); + uv.assign( mul( 2.0, uv ).sub( 1.0 ) ); + const direction = vec3( uv, 1.0 ).toVar(); + + If( face.equal( 0.0 ), () => { + + direction.assign( direction.zyx ); // ( 1, v, u ) pos x + + } ).ElseIf( face.equal( 1.0 ), () => { + + direction.assign( direction.xzy ); + direction.xz.mulAssign( - 1.0 ); // ( -u, 1, -v ) pos y + + } ).ElseIf( face.equal( 2.0 ), () => { + + direction.x.mulAssign( - 1.0 ); // ( -u, v, 1 ) pos z + + } ).ElseIf( face.equal( 3.0 ), () => { + + direction.assign( direction.zyx ); + direction.xz.mulAssign( - 1.0 ); // ( -1, v, -u ) neg x + + } ).ElseIf( face.equal( 4.0 ), () => { + + direction.assign( direction.xzy ); + direction.xy.mulAssign( - 1.0 ); // ( -u, -1, v ) neg y + + } ).ElseIf( face.equal( 5.0 ), () => { + + direction.z.mulAssign( - 1.0 ); // ( u, v, -1 ) neg zS + + } ); + + return direction; + +} ).setLayout( { + name: 'getDirection', + type: 'vec3', + inputs: [ + { name: 'uv', type: 'vec2' }, + { name: 'face', type: 'float' } + ] +} ); + +// + +const textureCubeUV = /*@__PURE__*/ Fn( ( [ envMap, sampleDir_immutable, roughness_immutable, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP ] ) => { + + const roughness = float( roughness_immutable ); + const sampleDir = vec3( sampleDir_immutable ); + + const mip = clamp( roughnessToMip( roughness ), cubeUV_m0, CUBEUV_MAX_MIP ); + const mipF = fract( mip ); + const mipInt = floor( mip ); + const color0 = vec3( bilinearCubeUV( envMap, sampleDir, mipInt, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP ) ).toVar(); + + If( mipF.notEqual( 0.0 ), () => { + + const color1 = vec3( bilinearCubeUV( envMap, sampleDir, mipInt.add( 1.0 ), CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP ) ).toVar(); + + color0.assign( mix( color0, color1, mipF ) ); + + } ); + + return color0; + +} ); + +const bilinearCubeUV = /*@__PURE__*/ Fn( ( [ envMap, direction_immutable, mipInt_immutable, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP ] ) => { + + const mipInt = float( mipInt_immutable ).toVar(); + const direction = vec3( direction_immutable ); + const face = float( getFace( direction ) ).toVar(); + const filterInt = float( max$1( cubeUV_minMipLevel.sub( mipInt ), 0.0 ) ).toVar(); + mipInt.assign( max$1( mipInt, cubeUV_minMipLevel ) ); + const faceSize = float( exp2( mipInt ) ).toVar(); + const uv = vec2( getUV( direction, face ).mul( faceSize.sub( 2.0 ) ).add( 1.0 ) ).toVar(); + + If( face.greaterThan( 2.0 ), () => { + + uv.y.addAssign( faceSize ); + face.subAssign( 3.0 ); + + } ); + + uv.x.addAssign( face.mul( faceSize ) ); + uv.x.addAssign( filterInt.mul( mul( 3.0, cubeUV_minTileSize ) ) ); + uv.y.addAssign( mul( 4.0, exp2( CUBEUV_MAX_MIP ).sub( faceSize ) ) ); + uv.x.mulAssign( CUBEUV_TEXEL_WIDTH ); + uv.y.mulAssign( CUBEUV_TEXEL_HEIGHT ); + + return envMap.uv( uv ).grad( vec2(), vec2() ); // disable anisotropic filtering + +} ); + +const getSample = /*@__PURE__*/ Fn( ( { envMap, mipInt, outputDirection, theta, axis, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP } ) => { + + const cosTheta = cos( theta ); + + // Rodrigues' axis-angle rotation + const sampleDirection = outputDirection.mul( cosTheta ) + .add( axis.cross( outputDirection ).mul( sin( theta ) ) ) + .add( axis.mul( axis.dot( outputDirection ).mul( cosTheta.oneMinus() ) ) ); + + return bilinearCubeUV( envMap, sampleDirection, mipInt, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP ); + +} ); + +const blur = /*@__PURE__*/ Fn( ( { n, latitudinal, poleAxis, outputDirection, weights, samples, dTheta, mipInt, envMap, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP } ) => { + + const axis = vec3( select( latitudinal, poleAxis, cross( poleAxis, outputDirection ) ) ).toVar(); + + If( all( axis.equals( vec3( 0.0 ) ) ), () => { + + axis.assign( vec3( outputDirection.z, 0.0, outputDirection.x.negate() ) ); + + } ); + + axis.assign( normalize( axis ) ); + + const gl_FragColor = vec3().toVar(); + gl_FragColor.addAssign( weights.element( int( 0 ) ).mul( getSample( { theta: 0.0, axis, outputDirection, mipInt, envMap, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP } ) ) ); + + Loop( { start: int( 1 ), end: n }, ( { i } ) => { + + If( i.greaterThanEqual( samples ), () => { + + Break(); + + } ); + + const theta = float( dTheta.mul( float( i ) ) ).toVar(); + gl_FragColor.addAssign( weights.element( i ).mul( getSample( { theta: theta.mul( - 1.0 ), axis, outputDirection, mipInt, envMap, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP } ) ) ); + gl_FragColor.addAssign( weights.element( i ).mul( getSample( { theta, axis, outputDirection, mipInt, envMap, CUBEUV_TEXEL_WIDTH, CUBEUV_TEXEL_HEIGHT, CUBEUV_MAX_MIP } ) ) ); + + } ); + + return vec4( gl_FragColor, 1 ); + +} ); + +let _generator = null; + +const _cache = new WeakMap(); + +function _generateCubeUVSize( imageHeight ) { + + const maxMip = Math.log2( imageHeight ) - 2; + + const texelHeight = 1.0 / imageHeight; + + const texelWidth = 1.0 / ( 3 * Math.max( Math.pow( 2, maxMip ), 7 * 16 ) ); + + return { texelWidth, texelHeight, maxMip }; + +} + +function _getPMREMFromTexture( texture ) { + + let cacheTexture = _cache.get( texture ); + + const pmremVersion = cacheTexture !== undefined ? cacheTexture.pmremVersion : - 1; + + if ( pmremVersion !== texture.pmremVersion ) { + + const image = texture.image; + + if ( texture.isCubeTexture ) { + + if ( isCubeMapReady( image ) ) { + + cacheTexture = _generator.fromCubemap( texture, cacheTexture ); + + } else { + + return null; + + } + + + } else { + + if ( isEquirectangularMapReady( image ) ) { + + cacheTexture = _generator.fromEquirectangular( texture, cacheTexture ); + + } else { + + return null; + + } + + } + + cacheTexture.pmremVersion = texture.pmremVersion; + + _cache.set( texture, cacheTexture ); + + } + + return cacheTexture.texture; + +} + +class PMREMNode extends TempNode { + + static get type() { + + return 'PMREMNode'; + + } + + constructor( value, uvNode = null, levelNode = null ) { + + super( 'vec3' ); + + this._value = value; + this._pmrem = null; + + this.uvNode = uvNode; + this.levelNode = levelNode; + + this._generator = null; + + const defaultTexture = new Texture(); + defaultTexture.isRenderTargetTexture = true; + + this._texture = texture( defaultTexture ); + + this._width = uniform( 0 ); + this._height = uniform( 0 ); + this._maxMip = uniform( 0 ); + + this.updateBeforeType = NodeUpdateType.RENDER; + + } + + set value( value ) { + + this._value = value; + this._pmrem = null; + + } + + get value() { + + return this._value; + + } + + updateFromTexture( texture ) { + + const cubeUVSize = _generateCubeUVSize( texture.image.height ); + + this._texture.value = texture; + this._width.value = cubeUVSize.texelWidth; + this._height.value = cubeUVSize.texelHeight; + this._maxMip.value = cubeUVSize.maxMip; + + } + + updateBefore() { + + let pmrem = this._pmrem; + + const pmremVersion = pmrem ? pmrem.pmremVersion : - 1; + const texture = this._value; + + if ( pmremVersion !== texture.pmremVersion ) { + + if ( texture.isPMREMTexture === true ) { + + pmrem = texture; + + } else { + + pmrem = _getPMREMFromTexture( texture ); + + } + + if ( pmrem !== null ) { + + this._pmrem = pmrem; + + this.updateFromTexture( pmrem ); + + } + + } + + } + + setup( builder ) { + + if ( _generator === null ) { + + _generator = builder.createPMREMGenerator(); + + } + + // + + this.updateBefore( builder ); + + // + + let uvNode = this.uvNode; + + if ( uvNode === null && builder.context.getUV ) { + + uvNode = builder.context.getUV( this ); + + } + + // + + const texture = this.value; + + if ( builder.renderer.coordinateSystem === WebGLCoordinateSystem && texture.isPMREMTexture !== true && texture.isRenderTargetTexture === true ) { + + uvNode = vec3( uvNode.x.negate(), uvNode.yz ); + + } + + // + + let levelNode = this.levelNode; + + if ( levelNode === null && builder.context.getTextureLevel ) { + + levelNode = builder.context.getTextureLevel( this ); + + } + + // + + return textureCubeUV( this._texture, uvNode, levelNode, this._width, this._height, this._maxMip ); + + } + +} + +function isCubeMapReady( image ) { + + if ( image === null || image === undefined ) return false; + + let count = 0; + const length = 6; + + for ( let i = 0; i < length; i ++ ) { + + if ( image[ i ] !== undefined ) count ++; + + } + + return count === length; + + +} + +function isEquirectangularMapReady( image ) { + + if ( image === null || image === undefined ) return false; + + return image.height > 0; + +} + +const pmremTexture = /*@__PURE__*/ nodeProxy( PMREMNode ); + +const _envNodeCache = new WeakMap(); + +class EnvironmentNode extends LightingNode { + + static get type() { + + return 'EnvironmentNode'; + + } + + constructor( envNode = null ) { + + super(); + + this.envNode = envNode; + + } + + setup( builder ) { + + const { material } = builder; + + let envNode = this.envNode; + + if ( envNode.isTextureNode || envNode.isMaterialReferenceNode ) { + + const value = ( envNode.isTextureNode ) ? envNode.value : material[ envNode.property ]; + + let cacheEnvNode = _envNodeCache.get( value ); + + if ( cacheEnvNode === undefined ) { + + cacheEnvNode = pmremTexture( value ); + + _envNodeCache.set( value, cacheEnvNode ); + + } + + envNode = cacheEnvNode; + + } + + // + + const envMap = material.envMap; + const intensity = envMap ? reference( 'envMapIntensity', 'float', builder.material ) : reference( 'environmentIntensity', 'float', builder.scene ); // @TODO: Add materialEnvIntensity in MaterialNode + + const useAnisotropy = material.useAnisotropy === true || material.anisotropy > 0; + const radianceNormalView = useAnisotropy ? transformedBentNormalView : transformedNormalView; + + const radiance = envNode.context( createRadianceContext( roughness, radianceNormalView ) ).mul( intensity ); + const irradiance = envNode.context( createIrradianceContext( transformedNormalWorld ) ).mul( Math.PI ).mul( intensity ); + + const isolateRadiance = cache( radiance ); + const isolateIrradiance = cache( irradiance ); + + // + + builder.context.radiance.addAssign( isolateRadiance ); + + builder.context.iblIrradiance.addAssign( isolateIrradiance ); + + // + + const clearcoatRadiance = builder.context.lightingModel.clearcoatRadiance; + + if ( clearcoatRadiance ) { + + const clearcoatRadianceContext = envNode.context( createRadianceContext( clearcoatRoughness, transformedClearcoatNormalView ) ).mul( intensity ); + const isolateClearcoatRadiance = cache( clearcoatRadianceContext ); + + clearcoatRadiance.addAssign( isolateClearcoatRadiance ); + + } + + } + +} + +const createRadianceContext = ( roughnessNode, normalViewNode ) => { + + let reflectVec = null; + + return { + getUV: () => { + + if ( reflectVec === null ) { + + reflectVec = positionViewDirection.negate().reflect( normalViewNode ); + + // Mixing the reflection with the normal is more accurate and keeps rough objects from gathering light from behind their tangent plane. + reflectVec = roughnessNode.mul( roughnessNode ).mix( reflectVec, normalViewNode ).normalize(); + + reflectVec = reflectVec.transformDirection( cameraViewMatrix ); + + } + + return reflectVec; + + }, + getTextureLevel: () => { + + return roughnessNode; + + } + }; + +}; + +const createIrradianceContext = ( normalWorldNode ) => { + + return { + getUV: () => { + + return normalWorldNode; + + }, + getTextureLevel: () => { + + return float( 1.0 ); + + } + }; + +}; + +const _defaultValues$6 = /*@__PURE__*/ new MeshStandardMaterial(); + +class MeshStandardNodeMaterial extends NodeMaterial { + + static get type() { + + return 'MeshStandardNodeMaterial'; + + } + + constructor( parameters ) { + + super(); + + this.isMeshStandardNodeMaterial = true; + + this.lights = true; + + this.emissiveNode = null; + + this.metalnessNode = null; + this.roughnessNode = null; + + this.setDefaultValues( _defaultValues$6 ); + + this.setValues( parameters ); + + } + + setupEnvironment( builder ) { + + let envNode = super.setupEnvironment( builder ); + + if ( envNode === null && builder.environmentNode ) { + + envNode = builder.environmentNode; + + } + + return envNode ? new EnvironmentNode( envNode ) : null; + + } + + setupLightingModel( /*builder*/ ) { + + return new PhysicalLightingModel(); + + } + + setupSpecular() { + + const specularColorNode = mix( vec3( 0.04 ), diffuseColor.rgb, metalness ); + + specularColor.assign( specularColorNode ); + specularF90.assign( 1.0 ); + + } + + setupVariants() { + + // METALNESS + + const metalnessNode = this.metalnessNode ? float( this.metalnessNode ) : materialMetalness; + + metalness.assign( metalnessNode ); + + // ROUGHNESS + + let roughnessNode = this.roughnessNode ? float( this.roughnessNode ) : materialRoughness; + roughnessNode = getRoughness( { roughness: roughnessNode } ); + + roughness.assign( roughnessNode ); + + // SPECULAR COLOR + + this.setupSpecular(); + + // DIFFUSE COLOR + + diffuseColor.assign( vec4( diffuseColor.rgb.mul( metalnessNode.oneMinus() ), diffuseColor.a ) ); + + } + + copy( source ) { + + this.emissiveNode = source.emissiveNode; + + this.metalnessNode = source.metalnessNode; + this.roughnessNode = source.roughnessNode; + + return super.copy( source ); + + } + +} + +const _defaultValues$5 = /*@__PURE__*/ new MeshPhysicalMaterial(); + +class MeshPhysicalNodeMaterial extends MeshStandardNodeMaterial { + + static get type() { + + return 'MeshPhysicalNodeMaterial'; + + } + + constructor( parameters ) { + + super(); + + this.isMeshPhysicalNodeMaterial = true; + + this.clearcoatNode = null; + this.clearcoatRoughnessNode = null; + this.clearcoatNormalNode = null; + + this.sheenNode = null; + this.sheenRoughnessNode = null; + + this.iridescenceNode = null; + this.iridescenceIORNode = null; + this.iridescenceThicknessNode = null; + + this.specularIntensityNode = null; + this.specularColorNode = null; + + this.iorNode = null; + this.transmissionNode = null; + this.thicknessNode = null; + this.attenuationDistanceNode = null; + this.attenuationColorNode = null; + this.dispersionNode = null; + + this.anisotropyNode = null; + + this.setDefaultValues( _defaultValues$5 ); + + this.setValues( parameters ); + + } + + get useClearcoat() { + + return this.clearcoat > 0 || this.clearcoatNode !== null; + + } + + get useIridescence() { + + return this.iridescence > 0 || this.iridescenceNode !== null; + + } + + get useSheen() { + + return this.sheen > 0 || this.sheenNode !== null; + + } + + get useAnisotropy() { + + return this.anisotropy > 0 || this.anisotropyNode !== null; + + } + + get useTransmission() { + + return this.transmission > 0 || this.transmissionNode !== null; + + } + + get useDispersion() { + + return this.dispersion > 0 || this.dispersionNode !== null; + + } + + setupSpecular() { + + const iorNode = this.iorNode ? float( this.iorNode ) : materialIOR; + + ior.assign( iorNode ); + specularColor.assign( mix( min$1( pow2( ior.sub( 1.0 ).div( ior.add( 1.0 ) ) ).mul( materialSpecularColor ), vec3( 1.0 ) ).mul( materialSpecularIntensity ), diffuseColor.rgb, metalness ) ); + specularF90.assign( mix( materialSpecularIntensity, 1.0, metalness ) ); + + } + + setupLightingModel( /*builder*/ ) { + + return new PhysicalLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useAnisotropy, this.useTransmission, this.useDispersion ); + + } + + setupVariants( builder ) { + + super.setupVariants( builder ); + + // CLEARCOAT + + if ( this.useClearcoat ) { + + const clearcoatNode = this.clearcoatNode ? float( this.clearcoatNode ) : materialClearcoat; + const clearcoatRoughnessNode = this.clearcoatRoughnessNode ? float( this.clearcoatRoughnessNode ) : materialClearcoatRoughness; + + clearcoat.assign( clearcoatNode ); + clearcoatRoughness.assign( getRoughness( { roughness: clearcoatRoughnessNode } ) ); + + } + + // SHEEN + + if ( this.useSheen ) { + + const sheenNode = this.sheenNode ? vec3( this.sheenNode ) : materialSheen; + const sheenRoughnessNode = this.sheenRoughnessNode ? float( this.sheenRoughnessNode ) : materialSheenRoughness; + + sheen.assign( sheenNode ); + sheenRoughness.assign( sheenRoughnessNode ); + + } + + // IRIDESCENCE + + if ( this.useIridescence ) { + + const iridescenceNode = this.iridescenceNode ? float( this.iridescenceNode ) : materialIridescence; + const iridescenceIORNode = this.iridescenceIORNode ? float( this.iridescenceIORNode ) : materialIridescenceIOR; + const iridescenceThicknessNode = this.iridescenceThicknessNode ? float( this.iridescenceThicknessNode ) : materialIridescenceThickness; + + iridescence.assign( iridescenceNode ); + iridescenceIOR.assign( iridescenceIORNode ); + iridescenceThickness.assign( iridescenceThicknessNode ); + + } + + // ANISOTROPY + + if ( this.useAnisotropy ) { + + const anisotropyV = ( this.anisotropyNode ? vec2( this.anisotropyNode ) : materialAnisotropy ).toVar(); + + anisotropy.assign( anisotropyV.length() ); + + If( anisotropy.equal( 0.0 ), () => { + + anisotropyV.assign( vec2( 1.0, 0.0 ) ); + + } ).Else( () => { + + anisotropyV.divAssign( vec2( anisotropy ) ); + anisotropy.assign( anisotropy.saturate() ); + + } ); + + // Roughness along the anisotropy bitangent is the material roughness, while the tangent roughness increases with anisotropy. + alphaT.assign( anisotropy.pow2().mix( roughness.pow2(), 1.0 ) ); + + anisotropyT.assign( TBNViewMatrix[ 0 ].mul( anisotropyV.x ).add( TBNViewMatrix[ 1 ].mul( anisotropyV.y ) ) ); + anisotropyB.assign( TBNViewMatrix[ 1 ].mul( anisotropyV.x ).sub( TBNViewMatrix[ 0 ].mul( anisotropyV.y ) ) ); + + } + + // TRANSMISSION + + if ( this.useTransmission ) { + + const transmissionNode = this.transmissionNode ? float( this.transmissionNode ) : materialTransmission; + const thicknessNode = this.thicknessNode ? float( this.thicknessNode ) : materialThickness; + const attenuationDistanceNode = this.attenuationDistanceNode ? float( this.attenuationDistanceNode ) : materialAttenuationDistance; + const attenuationColorNode = this.attenuationColorNode ? vec3( this.attenuationColorNode ) : materialAttenuationColor; + + transmission.assign( transmissionNode ); + thickness.assign( thicknessNode ); + attenuationDistance.assign( attenuationDistanceNode ); + attenuationColor.assign( attenuationColorNode ); + + if ( this.useDispersion ) { + + const dispersionNode = this.dispersionNode ? float( this.dispersionNode ) : materialDispersion; + + dispersion.assign( dispersionNode ); + + } + + } + + } + + setupClearcoatNormal() { + + return this.clearcoatNormalNode ? vec3( this.clearcoatNormalNode ) : materialClearcoatNormal; + + } + + setup( builder ) { + + builder.context.setupClearcoatNormal = () => this.setupClearcoatNormal( builder ); + + super.setup( builder ); + + } + + copy( source ) { + + this.clearcoatNode = source.clearcoatNode; + this.clearcoatRoughnessNode = source.clearcoatRoughnessNode; + this.clearcoatNormalNode = source.clearcoatNormalNode; + + this.sheenNode = source.sheenNode; + this.sheenRoughnessNode = source.sheenRoughnessNode; + + this.iridescenceNode = source.iridescenceNode; + this.iridescenceIORNode = source.iridescenceIORNode; + this.iridescenceThicknessNode = source.iridescenceThicknessNode; + + this.specularIntensityNode = source.specularIntensityNode; + this.specularColorNode = source.specularColorNode; + + this.transmissionNode = source.transmissionNode; + this.thicknessNode = source.thicknessNode; + this.attenuationDistanceNode = source.attenuationDistanceNode; + this.attenuationColorNode = source.attenuationColorNode; + this.dispersionNode = source.dispersionNode; + + this.anisotropyNode = source.anisotropyNode; + + return super.copy( source ); + + } + +} + +class SSSLightingModel extends PhysicalLightingModel { + + constructor( useClearcoat, useSheen, useIridescence, useSSS ) { + + super( useClearcoat, useSheen, useIridescence ); + + this.useSSS = useSSS; + + } + + direct( { lightDirection, lightColor, reflectedLight }, stack, builder ) { + + if ( this.useSSS === true ) { + + const material = builder.material; + + const { thicknessColorNode, thicknessDistortionNode, thicknessAmbientNode, thicknessAttenuationNode, thicknessPowerNode, thicknessScaleNode } = material; + + const scatteringHalf = lightDirection.add( transformedNormalView.mul( thicknessDistortionNode ) ).normalize(); + const scatteringDot = float( positionViewDirection.dot( scatteringHalf.negate() ).saturate().pow( thicknessPowerNode ).mul( thicknessScaleNode ) ); + const scatteringIllu = vec3( scatteringDot.add( thicknessAmbientNode ).mul( thicknessColorNode ) ); + + reflectedLight.directDiffuse.addAssign( scatteringIllu.mul( thicknessAttenuationNode.mul( lightColor ) ) ); + + } + + super.direct( { lightDirection, lightColor, reflectedLight }, stack, builder ); + + } + +} + +class MeshSSSNodeMaterial extends MeshPhysicalNodeMaterial { + + static get type() { + + return 'MeshSSSNodeMaterial'; + + } + + constructor( parameters ) { + + super( parameters ); + + this.thicknessColorNode = null; + this.thicknessDistortionNode = float( 0.1 ); + this.thicknessAmbientNode = float( 0.0 ); + this.thicknessAttenuationNode = float( .1 ); + this.thicknessPowerNode = float( 2.0 ); + this.thicknessScaleNode = float( 10.0 ); + + } + + get useSSS() { + + return this.thicknessColorNode !== null; + + } + + setupLightingModel( /*builder*/ ) { + + return new SSSLightingModel( this.useClearcoat, this.useSheen, this.useIridescence, this.useSSS ); + + } + + copy( source ) { + + this.thicknessColorNode = source.thicknessColorNode; + this.thicknessDistortionNode = source.thicknessDistortionNode; + this.thicknessAmbientNode = source.thicknessAmbientNode; + this.thicknessAttenuationNode = source.thicknessAttenuationNode; + this.thicknessPowerNode = source.thicknessPowerNode; + this.thicknessScaleNode = source.thicknessScaleNode; + + return super.copy( source ); + + } + +} + +const getGradientIrradiance = /*@__PURE__*/ Fn( ( { normal, lightDirection, builder } ) => { + + // dotNL will be from -1.0 to 1.0 + const dotNL = normal.dot( lightDirection ); + const coord = vec2( dotNL.mul( 0.5 ).add( 0.5 ), 0.0 ); + + if ( builder.material.gradientMap ) { + + const gradientMap = materialReference( 'gradientMap', 'texture' ).context( { getUV: () => coord } ); + + return vec3( gradientMap.r ); + + } else { + + const fw = coord.fwidth().mul( 0.5 ); + + return mix( vec3( 0.7 ), vec3( 1.0 ), smoothstep( float( 0.7 ).sub( fw.x ), float( 0.7 ).add( fw.x ), coord.x ) ); + + } + +} ); + +class ToonLightingModel extends LightingModel { + + direct( { lightDirection, lightColor, reflectedLight }, stack, builder ) { + + const irradiance = getGradientIrradiance( { normal: normalGeometry, lightDirection, builder } ).mul( lightColor ); + + reflectedLight.directDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor: diffuseColor.rgb } ) ) ); + + } + + indirect( { ambientOcclusion, irradiance, reflectedLight } ) { + + reflectedLight.indirectDiffuse.addAssign( irradiance.mul( BRDF_Lambert( { diffuseColor } ) ) ); + + reflectedLight.indirectDiffuse.mulAssign( ambientOcclusion ); + + } + +} + +const _defaultValues$4 = /*@__PURE__*/ new MeshToonMaterial(); + +class MeshToonNodeMaterial extends NodeMaterial { + + static get type() { + + return 'MeshToonNodeMaterial'; + + } + + constructor( parameters ) { + + super(); + + this.isMeshToonNodeMaterial = true; + + this.lights = true; + + this.setDefaultValues( _defaultValues$4 ); + + this.setValues( parameters ); + + } + + setupLightingModel( /*builder*/ ) { + + return new ToonLightingModel(); + + } + +} + +class MatcapUVNode extends TempNode { + + static get type() { + + return 'MatcapUVNode'; + + } + + constructor() { + + super( 'vec2' ); + + } + + setup() { + + const x = vec3( positionViewDirection.z, 0, positionViewDirection.x.negate() ).normalize(); + const y = positionViewDirection.cross( x ); + + return vec2( x.dot( transformedNormalView ), y.dot( transformedNormalView ) ).mul( 0.495 ).add( 0.5 ); // 0.495 to remove artifacts caused by undersized matcap disks + + } + +} + +const matcapUV = /*@__PURE__*/ nodeImmutable( MatcapUVNode ); + +const _defaultValues$3 = /*@__PURE__*/ new MeshMatcapMaterial(); + +class MeshMatcapNodeMaterial extends NodeMaterial { + + static get type() { + + return 'MeshMatcapNodeMaterial'; + + } + + constructor( parameters ) { + + super(); + + this.lights = false; + + this.isMeshMatcapNodeMaterial = true; + + this.setDefaultValues( _defaultValues$3 ); + + this.setValues( parameters ); + + } + + setupVariants( builder ) { + + const uv = matcapUV; + + let matcapColor; + + if ( builder.material.matcap ) { + + matcapColor = materialReference( 'matcap', 'texture' ).context( { getUV: () => uv } ); + + } else { + + matcapColor = vec3( mix( 0.2, 0.8, uv.y ) ); // default if matcap is missing + + } + + diffuseColor.rgb.mulAssign( matcapColor.rgb ); + + } + +} + +const _defaultValues$2 = /*@__PURE__*/ new PointsMaterial(); + +class PointsNodeMaterial extends NodeMaterial { + + static get type() { + + return 'PointsNodeMaterial'; + + } + + constructor( parameters ) { + + super(); + + this.isPointsNodeMaterial = true; + + this.lights = false; + this.transparent = true; + + this.sizeNode = null; + + this.setDefaultValues( _defaultValues$2 ); + + this.setValues( parameters ); + + } + + copy( source ) { + + this.sizeNode = source.sizeNode; + + return super.copy( source ); + + } + +} + +class RotateNode extends TempNode { + + static get type() { + + return 'RotateNode'; + + } + + constructor( positionNode, rotationNode ) { + + super(); + + this.positionNode = positionNode; + this.rotationNode = rotationNode; + + } + + getNodeType( builder ) { + + return this.positionNode.getNodeType( builder ); + + } + + setup( builder ) { + + const { rotationNode, positionNode } = this; + + const nodeType = this.getNodeType( builder ); + + if ( nodeType === 'vec2' ) { + + const cosAngle = rotationNode.cos(); + const sinAngle = rotationNode.sin(); + + const rotationMatrix = mat2( + cosAngle, sinAngle, + sinAngle.negate(), cosAngle + ); + + return rotationMatrix.mul( positionNode ); + + } else { + + const rotation = rotationNode; + const rotationXMatrix = mat4( vec4( 1.0, 0.0, 0.0, 0.0 ), vec4( 0.0, cos( rotation.x ), sin( rotation.x ).negate(), 0.0 ), vec4( 0.0, sin( rotation.x ), cos( rotation.x ), 0.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) ); + const rotationYMatrix = mat4( vec4( cos( rotation.y ), 0.0, sin( rotation.y ), 0.0 ), vec4( 0.0, 1.0, 0.0, 0.0 ), vec4( sin( rotation.y ).negate(), 0.0, cos( rotation.y ), 0.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) ); + const rotationZMatrix = mat4( vec4( cos( rotation.z ), sin( rotation.z ).negate(), 0.0, 0.0 ), vec4( sin( rotation.z ), cos( rotation.z ), 0.0, 0.0 ), vec4( 0.0, 0.0, 1.0, 0.0 ), vec4( 0.0, 0.0, 0.0, 1.0 ) ); + + return rotationXMatrix.mul( rotationYMatrix ).mul( rotationZMatrix ).mul( vec4( positionNode, 1.0 ) ).xyz; + + } + + } + +} + +const rotate = /*@__PURE__*/ nodeProxy( RotateNode ); + +const _defaultValues$1 = /*@__PURE__*/ new SpriteMaterial(); + +class SpriteNodeMaterial extends NodeMaterial { + + static get type() { + + return 'SpriteNodeMaterial'; + + } + + constructor( parameters ) { + + super(); + + this.isSpriteNodeMaterial = true; + + this.lights = false; + this._useSizeAttenuation = true; + + this.positionNode = null; + this.rotationNode = null; + this.scaleNode = null; + + this.setDefaultValues( _defaultValues$1 ); + + this.setValues( parameters ); + + } + + setupPosition( { object, camera, context } ) { + + const sizeAttenuation = this.sizeAttenuation; + + // < VERTEX STAGE > + + const { positionNode, rotationNode, scaleNode } = this; + + const vertex = positionLocal; + + let mvPosition = modelViewMatrix.mul( vec3( positionNode || 0 ) ); + + let scale = vec2( modelWorldMatrix[ 0 ].xyz.length(), modelWorldMatrix[ 1 ].xyz.length() ); + + if ( scaleNode !== null ) { + + scale = scale.mul( scaleNode ); + + } + + + if ( ! sizeAttenuation && camera.isPerspectiveCamera ) { + + scale = scale.mul( mvPosition.z.negate() ); + + } + + let alignedPosition = vertex.xy; + + if ( object.center && object.center.isVector2 === true ) { + + const center = reference$1( 'center', 'vec2' ); + + alignedPosition = alignedPosition.sub( center.sub( 0.5 ) ); + + } + + alignedPosition = alignedPosition.mul( scale ); + + const rotation = float( rotationNode || materialRotation ); + + const rotatedPosition = rotate( alignedPosition, rotation ); + + mvPosition = vec4( mvPosition.xy.add( rotatedPosition ), mvPosition.zw ); + + const modelViewProjection = cameraProjectionMatrix.mul( mvPosition ); + + context.vertex = vertex; + + return modelViewProjection; + + } + + copy( source ) { + + this.positionNode = source.positionNode; + this.rotationNode = source.rotationNode; + this.scaleNode = source.scaleNode; + + return super.copy( source ); + + } + + get sizeAttenuation() { + + return this._useSizeAttenuation; + + } + + set sizeAttenuation( value ) { + + if ( this._useSizeAttenuation !== value ) { + + this._useSizeAttenuation = value; + this.needsUpdate = true; + + } + + } + +} + +class ShadowMaskModel extends LightingModel { + + constructor() { + + super(); + + this.shadowNode = float( 1 ).toVar( 'shadowMask' ); + + } + + direct( { shadowMask } ) { + + this.shadowNode.mulAssign( shadowMask ); + + } + + finish( context ) { + + diffuseColor.a.mulAssign( this.shadowNode.oneMinus() ); + + context.outgoingLight.rgb.assign( diffuseColor.rgb ); // TODO: Optimize LightsNode to avoid this assignment + + } + +} + +const _defaultValues = /*@__PURE__*/ new ShadowMaterial(); + +class ShadowNodeMaterial extends NodeMaterial { + + static get type() { + + return 'ShadowNodeMaterial'; + + } + + constructor( parameters ) { + + super(); + + this.isShadowNodeMaterial = true; + + this.lights = true; + + this.setDefaultValues( _defaultValues ); + + this.setValues( parameters ); + + } + + setupLightingModel( /*builder*/ ) { + + return new ShadowMaskModel(); + + } + +} + +const normal = Fn( ( { texture, uv } ) => { + + const epsilon = 0.0001; + + const ret = vec3().toVar(); + + If( uv.x.lessThan( epsilon ), () => { + + ret.assign( vec3( 1, 0, 0 ) ); + + } ).ElseIf( uv.y.lessThan( epsilon ), () => { + + ret.assign( vec3( 0, 1, 0 ) ); + + } ).ElseIf( uv.z.lessThan( epsilon ), () => { + + ret.assign( vec3( 0, 0, 1 ) ); + + } ).ElseIf( uv.x.greaterThan( 1 - epsilon ), () => { + + ret.assign( vec3( - 1, 0, 0 ) ); + + } ).ElseIf( uv.y.greaterThan( 1 - epsilon ), () => { + + ret.assign( vec3( 0, - 1, 0 ) ); + + } ).ElseIf( uv.z.greaterThan( 1 - epsilon ), () => { + + ret.assign( vec3( 0, 0, - 1 ) ); + + } ).Else( () => { + + const step = 0.01; + + const x = texture.uv( uv.add( vec3( - step, 0.0, 0.0 ) ) ).r.sub( texture.uv( uv.add( vec3( step, 0.0, 0.0 ) ) ).r ); + const y = texture.uv( uv.add( vec3( 0.0, - step, 0.0 ) ) ).r.sub( texture.uv( uv.add( vec3( 0.0, step, 0.0 ) ) ).r ); + const z = texture.uv( uv.add( vec3( 0.0, 0.0, - step ) ) ).r.sub( texture.uv( uv.add( vec3( 0.0, 0.0, step ) ) ).r ); + + ret.assign( vec3( x, y, z ) ); + + } ); + + return ret.normalize(); + +} ); + + +class Texture3DNode extends TextureNode { + + static get type() { + + return 'Texture3DNode'; + + } + + constructor( value, uvNode = null, levelNode = null ) { + + super( value, uvNode, levelNode ); + + this.isTexture3DNode = true; + + } + + getInputType( /*builder*/ ) { + + return 'texture3D'; + + } + + getDefaultUV() { + + return vec3( 0.5, 0.5, 0.5 ); + + } + + setUpdateMatrix( /*updateMatrix*/ ) { } // Ignore .updateMatrix for 3d TextureNode + + setupUV( builder, uvNode ) { + + return uvNode; + + } + + generateUV( builder, uvNode ) { + + return uvNode.build( builder, 'vec3' ); + + } + + normal( uvNode ) { + + return normal( { texture: this, uv: uvNode } ); + + } + +} + +const texture3D = /*@__PURE__*/ nodeProxy( Texture3DNode ); + +class VolumeNodeMaterial extends NodeMaterial { + + static get type() { + + return 'VolumeNodeMaterial'; + + } + + constructor( params = {} ) { + + super(); + + this.lights = false; + this.isVolumeNodeMaterial = true; + this.testNode = null; + + this.setValues( params ); + + } + + setup( builder ) { + + const map = texture3D( this.map, null, 0 ); + + const hitBox = Fn( ( { orig, dir } ) => { + + const box_min = vec3( - 0.5 ); + const box_max = vec3( 0.5 ); + + const inv_dir = dir.reciprocal(); + + const tmin_tmp = box_min.sub( orig ).mul( inv_dir ); + const tmax_tmp = box_max.sub( orig ).mul( inv_dir ); + + const tmin = min$1( tmin_tmp, tmax_tmp ); + const tmax = max$1( tmin_tmp, tmax_tmp ); + + const t0 = max$1( tmin.x, max$1( tmin.y, tmin.z ) ); + const t1 = min$1( tmax.x, min$1( tmax.y, tmax.z ) ); + + return vec2( t0, t1 ); + + } ); + + this.fragmentNode = Fn( () => { + + const vOrigin = varying( vec3( modelWorldMatrixInverse.mul( vec4( cameraPosition, 1.0 ) ) ) ); + const vDirection = varying( positionGeometry.sub( vOrigin ) ); + + const rayDir = vDirection.normalize(); + const bounds = vec2( hitBox( { orig: vOrigin, dir: rayDir } ) ).toVar(); + + bounds.x.greaterThan( bounds.y ).discard(); + + bounds.assign( vec2( max$1( bounds.x, 0.0 ), bounds.y ) ); + + const p = vec3( vOrigin.add( bounds.x.mul( rayDir ) ) ).toVar(); + const inc = vec3( rayDir.abs().reciprocal() ).toVar(); + const delta = float( min$1( inc.x, min$1( inc.y, inc.z ) ) ).toVar( 'delta' ); // used 'delta' name in loop + + delta.divAssign( materialReference( 'steps', 'float' ) ); + + const ac = vec4( materialReference( 'base', 'color' ), 0.0 ).toVar(); + + Loop( { type: 'float', start: bounds.x, end: bounds.y, update: '+= delta' }, () => { + + const d = property( 'float', 'd' ).assign( map.uv( p.add( 0.5 ) ).r ); + + if ( this.testNode !== null ) { + + this.testNode( { map: map, mapValue: d, probe: p, finalColor: ac } ).append(); + + } else { + + // default to show surface of mesh + ac.a.assign( 1 ); + Break(); + + } + + p.addAssign( rayDir.mul( delta ) ); + + } ); + + ac.a.equal( 0 ).discard(); + + return vec4( ac ); + + } )(); + + super.setup( builder ); + + } + +} + +class Animation { + + constructor( nodes, info ) { + + this.nodes = nodes; + this.info = info; + + this.animationLoop = null; + this.requestId = null; + + this._init(); + + } + + _init() { + + const update = ( time, frame ) => { + + this.requestId = self.requestAnimationFrame( update ); + + if ( this.info.autoReset === true ) this.info.reset(); + + this.nodes.nodeFrame.update(); + + this.info.frame = this.nodes.nodeFrame.frameId; + + if ( this.animationLoop !== null ) this.animationLoop( time, frame ); + + }; + + update(); + + } + + dispose() { + + self.cancelAnimationFrame( this.requestId ); + this.requestId = null; + + } + + setAnimationLoop( callback ) { + + this.animationLoop = callback; + + } + +} + +class ChainMap { + + constructor() { + + this.weakMap = new WeakMap(); + + } + + get( keys ) { + + let map = this.weakMap; + + for ( let i = 0; i < keys.length; i ++ ) { + + map = map.get( keys[ i ] ); + + if ( map === undefined ) return undefined; + + } + + return map.get( keys[ keys.length - 1 ] ); + + } + + set( keys, value ) { + + let map = this.weakMap; + + for ( let i = 0; i < keys.length; i ++ ) { + + const key = keys[ i ]; + + if ( map.has( key ) === false ) map.set( key, new WeakMap() ); + + map = map.get( key ); + + } + + return map.set( keys[ keys.length - 1 ], value ); + + } + + delete( keys ) { + + let map = this.weakMap; + + for ( let i = 0; i < keys.length; i ++ ) { + + map = map.get( keys[ i ] ); + + if ( map === undefined ) return false; + + } + + return map.delete( keys[ keys.length - 1 ] ); + + } + +} + +const _plane = /*@__PURE__*/ new Plane(); + +class ClippingContext { + + constructor() { + + this.version = 0; + + this.globalClippingCount = 0; + + this.localClippingCount = 0; + this.localClippingEnabled = false; + this.localClipIntersection = false; + + this.planes = []; + + this.parentVersion = 0; + this.viewNormalMatrix = new Matrix3(); + this.cacheKey = 0; + + } + + projectPlanes( source, offset ) { + + const l = source.length; + const planes = this.planes; + + for ( let i = 0; i < l; i ++ ) { + + _plane.copy( source[ i ] ).applyMatrix4( this.viewMatrix, this.viewNormalMatrix ); + + const v = planes[ offset + i ]; + const normal = _plane.normal; + + v.x = - normal.x; + v.y = - normal.y; + v.z = - normal.z; + v.w = _plane.constant; + + } + + } + + updateGlobal( renderer, camera ) { + + const rendererClippingPlanes = renderer.clippingPlanes; + this.viewMatrix = camera.matrixWorldInverse; + + this.viewNormalMatrix.getNormalMatrix( this.viewMatrix ); + + let update = false; + + if ( Array.isArray( rendererClippingPlanes ) && rendererClippingPlanes.length !== 0 ) { + + const l = rendererClippingPlanes.length; + + if ( l !== this.globalClippingCount ) { + + const planes = []; + + for ( let i = 0; i < l; i ++ ) { + + planes.push( new Vector4() ); + + } + + this.globalClippingCount = l; + this.planes = planes; + + update = true; + + } + + this.projectPlanes( rendererClippingPlanes, 0 ); + + } else if ( this.globalClippingCount !== 0 ) { + + this.globalClippingCount = 0; + this.planes = []; + update = true; + + } + + if ( renderer.localClippingEnabled !== this.localClippingEnabled ) { + + this.localClippingEnabled = renderer.localClippingEnabled; + update = true; + + } + + if ( update ) { + + this.version ++; + this.cacheKey = hash$1( this.globalClippingCount, this.localClippingEnabled === true ? 1 : 0 ); + + } + + } + + update( parent, material ) { + + let update = false; + + if ( this !== parent && parent.version !== this.parentVersion ) { + + this.globalClippingCount = material.isShadowNodeMaterial ? 0 : parent.globalClippingCount; + this.localClippingEnabled = parent.localClippingEnabled; + this.planes = Array.from( parent.planes ); + this.parentVersion = parent.version; + this.viewMatrix = parent.viewMatrix; + this.viewNormalMatrix = parent.viewNormalMatrix; + + update = true; + + } + + if ( this.localClippingEnabled ) { + + const localClippingPlanes = material.clippingPlanes; + + if ( ( Array.isArray( localClippingPlanes ) && localClippingPlanes.length !== 0 ) ) { + + const l = localClippingPlanes.length; + const planes = this.planes; + const offset = this.globalClippingCount; + + if ( update || l !== this.localClippingCount ) { + + planes.length = offset + l; + + for ( let i = 0; i < l; i ++ ) { + + planes[ offset + i ] = new Vector4(); + + } + + this.localClippingCount = l; + update = true; + + } + + this.projectPlanes( localClippingPlanes, offset ); + + + } else if ( this.localClippingCount !== 0 ) { + + this.localClippingCount = 0; + update = true; + + } + + if ( this.localClipIntersection !== material.clipIntersection ) { + + this.localClipIntersection = material.clipIntersection; + update = true; + + } + + } + + if ( update ) { + + this.version += parent.version; + this.cacheKey = hash$1( parent.cacheKey, this.localClippingCount, this.localClipIntersection === true ? 1 : 0 ); + + } + + } + +} + +let _id$7 = 0; + +function getKeys( obj ) { + + const keys = Object.keys( obj ); + + let proto = Object.getPrototypeOf( obj ); + + while ( proto ) { + + const descriptors = Object.getOwnPropertyDescriptors( proto ); + + for ( const key in descriptors ) { + + if ( descriptors[ key ] !== undefined ) { + + const descriptor = descriptors[ key ]; + + if ( descriptor && typeof descriptor.get === 'function' ) { + + keys.push( key ); + + } + + } + + } + + proto = Object.getPrototypeOf( proto ); + + } + + return keys; + +} + +class RenderObject { + + constructor( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext ) { + + this._nodes = nodes; + this._geometries = geometries; + + this.id = _id$7 ++; + + this.renderer = renderer; + this.object = object; + this.material = material; + this.scene = scene; + this.camera = camera; + this.lightsNode = lightsNode; + this.context = renderContext; + + this.geometry = object.geometry; + this.version = material.version; + + this.drawRange = null; + + this.attributes = null; + this.pipeline = null; + this.vertexBuffers = null; + this.drawParams = null; + + this.bundle = null; + + this.updateClipping( renderContext.clippingContext ); + + this.clippingContextVersion = this.clippingContext.version; + + this.initialNodesCacheKey = this.getDynamicCacheKey(); + this.initialCacheKey = this.getCacheKey(); + + this._nodeBuilderState = null; + this._bindings = null; + this._monitor = null; + + this.onDispose = null; + + this.isRenderObject = true; + + this.onMaterialDispose = () => { + + this.dispose(); + + }; + + this.material.addEventListener( 'dispose', this.onMaterialDispose ); + + } + + updateClipping( parent ) { + + const material = this.material; + + let clippingContext = this.clippingContext; + + if ( Array.isArray( material.clippingPlanes ) ) { + + if ( clippingContext === parent || ! clippingContext ) { + + clippingContext = new ClippingContext(); + this.clippingContext = clippingContext; + + } + + clippingContext.update( parent, material ); + + } else if ( this.clippingContext !== parent ) { + + this.clippingContext = parent; + + } + + } + + get clippingNeedsUpdate() { + + if ( this.clippingContext.version === this.clippingContextVersion ) return false; + + this.clippingContextVersion = this.clippingContext.version; + + return true; + + } + + getNodeBuilderState() { + + return this._nodeBuilderState || ( this._nodeBuilderState = this._nodes.getForRender( this ) ); + + } + + getMonitor() { + + return this._monitor || ( this._monitor = this.getNodeBuilderState().monitor ); + + } + + getBindings() { + + return this._bindings || ( this._bindings = this.getNodeBuilderState().createBindings() ); + + } + + getIndex() { + + return this._geometries.getIndex( this ); + + } + + getChainArray() { + + return [ this.object, this.material, this.context, this.lightsNode ]; + + } + + getAttributes() { + + if ( this.attributes !== null ) return this.attributes; + + const nodeAttributes = this.getNodeBuilderState().nodeAttributes; + const geometry = this.geometry; + + const attributes = []; + const vertexBuffers = new Set(); + + for ( const nodeAttribute of nodeAttributes ) { + + const attribute = nodeAttribute.node && nodeAttribute.node.attribute ? nodeAttribute.node.attribute : geometry.getAttribute( nodeAttribute.name ); + + if ( attribute === undefined ) continue; + + attributes.push( attribute ); + + const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute; + vertexBuffers.add( bufferAttribute ); + + } + + this.attributes = attributes; + this.vertexBuffers = Array.from( vertexBuffers.values() ); + + return attributes; + + } + + getVertexBuffers() { + + if ( this.vertexBuffers === null ) this.getAttributes(); + + return this.vertexBuffers; + + } + + getDrawParameters() { + + const { object, material, geometry, group, drawRange } = this; + + const drawParams = this.drawParams || ( this.drawParams = { + vertexCount: 0, + firstVertex: 0, + instanceCount: 0, + firstInstance: 0 + } ); + + const index = this.getIndex(); + const hasIndex = ( index !== null ); + const instanceCount = geometry.isInstancedBufferGeometry ? geometry.instanceCount : ( object.count > 1 ? object.count : 1 ); + + if ( instanceCount === 0 ) return null; + + drawParams.instanceCount = instanceCount; + + if ( object.isBatchedMesh === true ) return drawParams; + + let rangeFactor = 1; + + if ( material.wireframe === true && ! object.isPoints && ! object.isLineSegments && ! object.isLine && ! object.isLineLoop ) { + + rangeFactor = 2; + + } + + let firstVertex = drawRange.start * rangeFactor; + let lastVertex = ( drawRange.start + drawRange.count ) * rangeFactor; + + if ( group !== null ) { + + firstVertex = Math.max( firstVertex, group.start * rangeFactor ); + lastVertex = Math.min( lastVertex, ( group.start + group.count ) * rangeFactor ); + + } + + const itemCount = hasIndex === true ? index.count : geometry.attributes.position.count; + + firstVertex = Math.max( firstVertex, 0 ); + lastVertex = Math.min( lastVertex, itemCount ); + + const count = lastVertex - firstVertex; + + if ( count < 0 || count === Infinity ) return null; + + drawParams.vertexCount = count; + drawParams.firstVertex = firstVertex; + + return drawParams; + + } + + getGeometryCacheKey() { + + const { geometry } = this; + + let cacheKey = ''; + + for ( const name of Object.keys( geometry.attributes ).sort() ) { + + const attribute = geometry.attributes[ name ]; + + cacheKey += name + ','; + + if ( attribute.data ) cacheKey += attribute.data.stride + ','; + if ( attribute.offset ) cacheKey += attribute.offset + ','; + if ( attribute.itemSize ) cacheKey += attribute.itemSize + ','; + if ( attribute.normalized ) cacheKey += 'n,'; + + } + + if ( geometry.index ) { + + cacheKey += 'index,'; + + } + + return cacheKey; + + } + + getMaterialCacheKey() { + + const { object, material } = this; + + let cacheKey = material.customProgramCacheKey(); + + for ( const property of getKeys( material ) ) { + + if ( /^(is[A-Z]|_)|^(visible|version|uuid|name|opacity|userData)$/.test( property ) ) continue; + + const value = material[ property ]; + + let valueKey; + + if ( value !== null ) { + + // some material values require a formatting + + const type = typeof value; + + if ( type === 'number' ) { + + valueKey = value !== 0 ? '1' : '0'; // Convert to on/off, important for clearcoat, transmission, etc + + } else if ( type === 'object' ) { + + valueKey = '{'; + + if ( value.isTexture ) { + + valueKey += value.mapping; + + } + + valueKey += '}'; + + } else { + + valueKey = String( value ); + + } + + } else { + + valueKey = String( value ); + + } + + cacheKey += /*property + ':' +*/ valueKey + ','; + + } + + cacheKey += this.clippingContext.cacheKey + ','; + + if ( object.geometry ) { + + cacheKey += this.getGeometryCacheKey(); + + } + + if ( object.skeleton ) { + + cacheKey += object.skeleton.bones.length + ','; + + } + + if ( object.morphTargetInfluences ) { + + cacheKey += object.morphTargetInfluences.length + ','; + + } + + if ( object.isBatchedMesh ) { + + cacheKey += object._matricesTexture.uuid + ','; + + if ( object._colorsTexture !== null ) { + + cacheKey += object._colorsTexture.uuid + ','; + + } + + } + + if ( object.count > 1 ) { + + // TODO: https://github.com/mrdoob/three.js/pull/29066#issuecomment-2269400850 + + cacheKey += object.uuid + ','; + + } + + return hashString( cacheKey ); + + } + + get needsUpdate() { + + return /*this.object.static !== true &&*/ ( this.initialNodesCacheKey !== this.getDynamicCacheKey() || this.clippingNeedsUpdate ); + + } + + getDynamicCacheKey() { + + // Environment Nodes Cache Key + + let cacheKey = this._nodes.getCacheKey( this.scene, this.lightsNode ); + + if ( this.object.receiveShadow ) { + + cacheKey += 1; + + } + + return cacheKey; + + } + + getCacheKey() { + + return this.getMaterialCacheKey() + this.getDynamicCacheKey(); + + } + + dispose() { + + this.material.removeEventListener( 'dispose', this.onMaterialDispose ); + + this.onDispose(); + + } + +} + +const chainArray = []; + +class RenderObjects { + + constructor( renderer, nodes, geometries, pipelines, bindings, info ) { + + this.renderer = renderer; + this.nodes = nodes; + this.geometries = geometries; + this.pipelines = pipelines; + this.bindings = bindings; + this.info = info; + + this.chainMaps = {}; + + } + + get( object, material, scene, camera, lightsNode, renderContext, passId ) { + + const chainMap = this.getChainMap( passId ); + + // reuse chainArray + chainArray[ 0 ] = object; + chainArray[ 1 ] = material; + chainArray[ 2 ] = renderContext; + chainArray[ 3 ] = lightsNode; + + let renderObject = chainMap.get( chainArray ); + + if ( renderObject === undefined ) { + + renderObject = this.createRenderObject( this.nodes, this.geometries, this.renderer, object, material, scene, camera, lightsNode, renderContext, passId ); + + chainMap.set( chainArray, renderObject ); + + } else { + + renderObject.updateClipping( renderContext.clippingContext ); + + if ( renderObject.version !== material.version || renderObject.needsUpdate ) { + + if ( renderObject.initialCacheKey !== renderObject.getCacheKey() ) { + + renderObject.dispose(); + + renderObject = this.get( object, material, scene, camera, lightsNode, renderContext, passId ); + + } else { + + renderObject.version = material.version; + + } + + } + + } + + return renderObject; + + } + + getChainMap( passId = 'default' ) { + + return this.chainMaps[ passId ] || ( this.chainMaps[ passId ] = new ChainMap() ); + + } + + dispose() { + + this.chainMaps = {}; + + } + + createRenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext, passId ) { + + const chainMap = this.getChainMap( passId ); + + const renderObject = new RenderObject( nodes, geometries, renderer, object, material, scene, camera, lightsNode, renderContext ); + + renderObject.onDispose = () => { + + this.pipelines.delete( renderObject ); + this.bindings.delete( renderObject ); + this.nodes.delete( renderObject ); + + chainMap.delete( renderObject.getChainArray() ); + + }; + + return renderObject; + + } + + +} + +class DataMap { + + constructor() { + + this.data = new WeakMap(); + + } + + get( object ) { + + let map = this.data.get( object ); + + if ( map === undefined ) { + + map = {}; + this.data.set( object, map ); + + } + + return map; + + } + + delete( object ) { + + let map; + + if ( this.data.has( object ) ) { + + map = this.data.get( object ); + + this.data.delete( object ); + + } + + return map; + + } + + has( object ) { + + return this.data.has( object ); + + } + + dispose() { + + this.data = new WeakMap(); + + } + +} + +const AttributeType = { + VERTEX: 1, + INDEX: 2, + STORAGE: 4 +}; + +// size of a chunk in bytes (STD140 layout) + +const GPU_CHUNK_BYTES = 16; + +// @TODO: Move to src/constants.js + +const BlendColorFactor = 211; +const OneMinusBlendColorFactor = 212; + +class Attributes extends DataMap { + + constructor( backend ) { + + super(); + + this.backend = backend; + + } + + delete( attribute ) { + + const attributeData = super.delete( attribute ); + + if ( attributeData !== undefined ) { + + this.backend.destroyAttribute( attribute ); + + } + + return attributeData; + + } + + update( attribute, type ) { + + const data = this.get( attribute ); + + if ( data.version === undefined ) { + + if ( type === AttributeType.VERTEX ) { + + this.backend.createAttribute( attribute ); + + } else if ( type === AttributeType.INDEX ) { + + this.backend.createIndexAttribute( attribute ); + + } else if ( type === AttributeType.STORAGE ) { + + this.backend.createStorageAttribute( attribute ); + + } + + data.version = this._getBufferAttribute( attribute ).version; + + } else { + + const bufferAttribute = this._getBufferAttribute( attribute ); + + if ( data.version < bufferAttribute.version || bufferAttribute.usage === DynamicDrawUsage ) { + + this.backend.updateAttribute( attribute ); + + data.version = bufferAttribute.version; + + } + + } + + } + + _getBufferAttribute( attribute ) { + + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; + + return attribute; + + } + +} + +function arrayNeedsUint32( array ) { + + // assumes larger values usually on last + + for ( let i = array.length - 1; i >= 0; -- i ) { + + if ( array[ i ] >= 65535 ) return true; // account for PRIMITIVE_RESTART_FIXED_INDEX, #24565 + + } + + return false; + +} + +function getWireframeVersion( geometry ) { + + return ( geometry.index !== null ) ? geometry.index.version : geometry.attributes.position.version; + +} + +function getWireframeIndex( geometry ) { + + const indices = []; + + const geometryIndex = geometry.index; + const geometryPosition = geometry.attributes.position; + + if ( geometryIndex !== null ) { + + const array = geometryIndex.array; + + for ( let i = 0, l = array.length; i < l; i += 3 ) { + + const a = array[ i + 0 ]; + const b = array[ i + 1 ]; + const c = array[ i + 2 ]; + + indices.push( a, b, b, c, c, a ); + + } + + } else { + + const array = geometryPosition.array; + + for ( let i = 0, l = ( array.length / 3 ) - 1; i < l; i += 3 ) { + + const a = i + 0; + const b = i + 1; + const c = i + 2; + + indices.push( a, b, b, c, c, a ); + + } + + } + + const attribute = new ( arrayNeedsUint32( indices ) ? Uint32BufferAttribute : Uint16BufferAttribute )( indices, 1 ); + attribute.version = getWireframeVersion( geometry ); + + return attribute; + +} + +class Geometries extends DataMap { + + constructor( attributes, info ) { + + super(); + + this.attributes = attributes; + this.info = info; + + this.wireframes = new WeakMap(); + + this.attributeCall = new WeakMap(); + + } + + has( renderObject ) { + + const geometry = renderObject.geometry; + + return super.has( geometry ) && this.get( geometry ).initialized === true; + + } + + updateForRender( renderObject ) { + + if ( this.has( renderObject ) === false ) this.initGeometry( renderObject ); + + this.updateAttributes( renderObject ); + + } + + initGeometry( renderObject ) { + + const geometry = renderObject.geometry; + const geometryData = this.get( geometry ); + + geometryData.initialized = true; + + this.info.memory.geometries ++; + + const onDispose = () => { + + this.info.memory.geometries --; + + const index = geometry.index; + const geometryAttributes = renderObject.getAttributes(); + + if ( index !== null ) { + + this.attributes.delete( index ); + + } + + for ( const geometryAttribute of geometryAttributes ) { + + this.attributes.delete( geometryAttribute ); + + } + + const wireframeAttribute = this.wireframes.get( geometry ); + + if ( wireframeAttribute !== undefined ) { + + this.attributes.delete( wireframeAttribute ); + + } + + geometry.removeEventListener( 'dispose', onDispose ); + + }; + + geometry.addEventListener( 'dispose', onDispose ); + + } + + updateAttributes( renderObject ) { + + const attributes = renderObject.getAttributes(); + + for ( const attribute of attributes ) { + + if ( attribute.isStorageBufferAttribute || attribute.isStorageInstancedBufferAttribute ) { + + this.updateAttribute( attribute, AttributeType.STORAGE ); + + } else { + + this.updateAttribute( attribute, AttributeType.VERTEX ); + + } + + } + + const index = this.getIndex( renderObject ); + + if ( index !== null ) { + + this.updateAttribute( index, AttributeType.INDEX ); + + } + + } + + updateAttribute( attribute, type ) { + + const callId = this.info.render.calls; + + if ( ! attribute.isInterleavedBufferAttribute ) { + + if ( this.attributeCall.get( attribute ) !== callId ) { + + this.attributes.update( attribute, type ); + + this.attributeCall.set( attribute, callId ); + + } + + } else { + + if ( this.attributeCall.get( attribute ) === undefined ) { + + this.attributes.update( attribute, type ); + + this.attributeCall.set( attribute, callId ); + + } else if ( this.attributeCall.get( attribute.data ) !== callId ) { + + this.attributes.update( attribute, type ); + + this.attributeCall.set( attribute.data, callId ); + + this.attributeCall.set( attribute, callId ); + + } + + } + + } + + getIndex( renderObject ) { + + const { geometry, material } = renderObject; + + let index = geometry.index; + + if ( material.wireframe === true ) { + + const wireframes = this.wireframes; + + let wireframeAttribute = wireframes.get( geometry ); + + if ( wireframeAttribute === undefined ) { + + wireframeAttribute = getWireframeIndex( geometry ); + + wireframes.set( geometry, wireframeAttribute ); + + } else if ( wireframeAttribute.version !== getWireframeVersion( geometry ) ) { + + this.attributes.delete( wireframeAttribute ); + + wireframeAttribute = getWireframeIndex( geometry ); + + wireframes.set( geometry, wireframeAttribute ); + + } + + index = wireframeAttribute; + + } + + return index; + + } + +} + +class Info { + + constructor() { + + this.autoReset = true; + + this.frame = 0; + this.calls = 0; + + this.render = { + calls: 0, + frameCalls: 0, + drawCalls: 0, + triangles: 0, + points: 0, + lines: 0, + timestamp: 0, + previousFrameCalls: 0, + timestampCalls: 0 + }; + + this.compute = { + calls: 0, + frameCalls: 0, + timestamp: 0, + previousFrameCalls: 0, + timestampCalls: 0 + }; + + this.memory = { + geometries: 0, + textures: 0 + }; + + } + + update( object, count, instanceCount ) { + + this.render.drawCalls ++; + + if ( object.isMesh || object.isSprite ) { + + this.render.triangles += instanceCount * ( count / 3 ); + + } else if ( object.isPoints ) { + + this.render.points += instanceCount * count; + + } else if ( object.isLineSegments ) { + + this.render.lines += instanceCount * ( count / 2 ); + + } else if ( object.isLine ) { + + this.render.lines += instanceCount * ( count - 1 ); + + } else { + + console.error( 'THREE.WebGPUInfo: Unknown object type.' ); + + } + + } + + updateTimestamp( type, time ) { + + if ( this[ type ].timestampCalls === 0 ) { + + this[ type ].timestamp = 0; + + } + + + this[ type ].timestamp += time; + + this[ type ].timestampCalls ++; + + + if ( this[ type ].timestampCalls >= this[ type ].previousFrameCalls ) { + + this[ type ].timestampCalls = 0; + + } + + + } + + reset() { + + const previousRenderFrameCalls = this.render.frameCalls; + this.render.previousFrameCalls = previousRenderFrameCalls; + + const previousComputeFrameCalls = this.compute.frameCalls; + this.compute.previousFrameCalls = previousComputeFrameCalls; + + + this.render.drawCalls = 0; + this.render.frameCalls = 0; + this.compute.frameCalls = 0; + + this.render.triangles = 0; + this.render.points = 0; + this.render.lines = 0; + + + } + + dispose() { + + this.reset(); + + this.calls = 0; + + this.render.calls = 0; + this.compute.calls = 0; + + this.render.timestamp = 0; + this.compute.timestamp = 0; + this.memory.geometries = 0; + this.memory.textures = 0; + + } + +} + +class Pipeline { + + constructor( cacheKey ) { + + this.cacheKey = cacheKey; + + this.usedTimes = 0; + + } + +} + +class RenderPipeline extends Pipeline { + + constructor( cacheKey, vertexProgram, fragmentProgram ) { + + super( cacheKey ); + + this.vertexProgram = vertexProgram; + this.fragmentProgram = fragmentProgram; + + } + +} + +class ComputePipeline extends Pipeline { + + constructor( cacheKey, computeProgram ) { + + super( cacheKey ); + + this.computeProgram = computeProgram; + + this.isComputePipeline = true; + + } + +} + +let _id$6 = 0; + +class ProgrammableStage { + + constructor( code, type, transforms = null, attributes = null ) { + + this.id = _id$6 ++; + + this.code = code; + this.stage = type; + this.transforms = transforms; + this.attributes = attributes; + + this.usedTimes = 0; + + } + +} + +class Pipelines extends DataMap { + + constructor( backend, nodes ) { + + super(); + + this.backend = backend; + this.nodes = nodes; + + this.bindings = null; // set by the bindings + + this.caches = new Map(); + this.programs = { + vertex: new Map(), + fragment: new Map(), + compute: new Map() + }; + + } + + getForCompute( computeNode, bindings ) { + + const { backend } = this; + + const data = this.get( computeNode ); + + if ( this._needsComputeUpdate( computeNode ) ) { + + const previousPipeline = data.pipeline; + + if ( previousPipeline ) { + + previousPipeline.usedTimes --; + previousPipeline.computeProgram.usedTimes --; + + } + + // get shader + + const nodeBuilderState = this.nodes.getForCompute( computeNode ); + + // programmable stage + + let stageCompute = this.programs.compute.get( nodeBuilderState.computeShader ); + + if ( stageCompute === undefined ) { + + if ( previousPipeline && previousPipeline.computeProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.computeProgram ); + + stageCompute = new ProgrammableStage( nodeBuilderState.computeShader, 'compute', nodeBuilderState.transforms, nodeBuilderState.nodeAttributes ); + this.programs.compute.set( nodeBuilderState.computeShader, stageCompute ); + + backend.createProgram( stageCompute ); + + } + + // determine compute pipeline + + const cacheKey = this._getComputeCacheKey( computeNode, stageCompute ); + + let pipeline = this.caches.get( cacheKey ); + + if ( pipeline === undefined ) { + + if ( previousPipeline && previousPipeline.usedTimes === 0 ) this._releasePipeline( previousPipeline ); + + pipeline = this._getComputePipeline( computeNode, stageCompute, cacheKey, bindings ); + + } + + // keep track of all used times + + pipeline.usedTimes ++; + stageCompute.usedTimes ++; + + // + + data.version = computeNode.version; + data.pipeline = pipeline; + + } + + return data.pipeline; + + } + + getForRender( renderObject, promises = null ) { + + const { backend } = this; + + const data = this.get( renderObject ); + + if ( this._needsRenderUpdate( renderObject ) ) { + + const previousPipeline = data.pipeline; + + if ( previousPipeline ) { + + previousPipeline.usedTimes --; + previousPipeline.vertexProgram.usedTimes --; + previousPipeline.fragmentProgram.usedTimes --; + + } + + // get shader + + const nodeBuilderState = renderObject.getNodeBuilderState(); + + // programmable stages + + let stageVertex = this.programs.vertex.get( nodeBuilderState.vertexShader ); + + if ( stageVertex === undefined ) { + + if ( previousPipeline && previousPipeline.vertexProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.vertexProgram ); + + stageVertex = new ProgrammableStage( nodeBuilderState.vertexShader, 'vertex' ); + this.programs.vertex.set( nodeBuilderState.vertexShader, stageVertex ); + + backend.createProgram( stageVertex ); + + } + + let stageFragment = this.programs.fragment.get( nodeBuilderState.fragmentShader ); + + if ( stageFragment === undefined ) { + + if ( previousPipeline && previousPipeline.fragmentProgram.usedTimes === 0 ) this._releaseProgram( previousPipeline.fragmentProgram ); + + stageFragment = new ProgrammableStage( nodeBuilderState.fragmentShader, 'fragment' ); + this.programs.fragment.set( nodeBuilderState.fragmentShader, stageFragment ); + + backend.createProgram( stageFragment ); + + } + + // determine render pipeline + + const cacheKey = this._getRenderCacheKey( renderObject, stageVertex, stageFragment ); + + let pipeline = this.caches.get( cacheKey ); + + if ( pipeline === undefined ) { + + if ( previousPipeline && previousPipeline.usedTimes === 0 ) this._releasePipeline( previousPipeline ); + + pipeline = this._getRenderPipeline( renderObject, stageVertex, stageFragment, cacheKey, promises ); + + } else { + + renderObject.pipeline = pipeline; + + } + + // keep track of all used times + + pipeline.usedTimes ++; + stageVertex.usedTimes ++; + stageFragment.usedTimes ++; + + // + + data.pipeline = pipeline; + + } + + return data.pipeline; + + } + + delete( object ) { + + const pipeline = this.get( object ).pipeline; + + if ( pipeline ) { + + // pipeline + + pipeline.usedTimes --; + + if ( pipeline.usedTimes === 0 ) this._releasePipeline( pipeline ); + + // programs + + if ( pipeline.isComputePipeline ) { + + pipeline.computeProgram.usedTimes --; + + if ( pipeline.computeProgram.usedTimes === 0 ) this._releaseProgram( pipeline.computeProgram ); + + } else { + + pipeline.fragmentProgram.usedTimes --; + pipeline.vertexProgram.usedTimes --; + + if ( pipeline.vertexProgram.usedTimes === 0 ) this._releaseProgram( pipeline.vertexProgram ); + if ( pipeline.fragmentProgram.usedTimes === 0 ) this._releaseProgram( pipeline.fragmentProgram ); + + } + + } + + return super.delete( object ); + + } + + dispose() { + + super.dispose(); + + this.caches = new Map(); + this.programs = { + vertex: new Map(), + fragment: new Map(), + compute: new Map() + }; + + } + + updateForRender( renderObject ) { + + this.getForRender( renderObject ); + + } + + _getComputePipeline( computeNode, stageCompute, cacheKey, bindings ) { + + // check for existing pipeline + + cacheKey = cacheKey || this._getComputeCacheKey( computeNode, stageCompute ); + + let pipeline = this.caches.get( cacheKey ); + + if ( pipeline === undefined ) { + + pipeline = new ComputePipeline( cacheKey, stageCompute ); + + this.caches.set( cacheKey, pipeline ); + + this.backend.createComputePipeline( pipeline, bindings ); + + } + + return pipeline; + + } + + _getRenderPipeline( renderObject, stageVertex, stageFragment, cacheKey, promises ) { + + // check for existing pipeline + + cacheKey = cacheKey || this._getRenderCacheKey( renderObject, stageVertex, stageFragment ); + + let pipeline = this.caches.get( cacheKey ); + + if ( pipeline === undefined ) { + + pipeline = new RenderPipeline( cacheKey, stageVertex, stageFragment ); + + this.caches.set( cacheKey, pipeline ); + + renderObject.pipeline = pipeline; + + this.backend.createRenderPipeline( renderObject, promises ); + + } + + return pipeline; + + } + + _getComputeCacheKey( computeNode, stageCompute ) { + + return computeNode.id + ',' + stageCompute.id; + + } + + _getRenderCacheKey( renderObject, stageVertex, stageFragment ) { + + return stageVertex.id + ',' + stageFragment.id + ',' + this.backend.getRenderCacheKey( renderObject ); + + } + + _releasePipeline( pipeline ) { + + this.caches.delete( pipeline.cacheKey ); + + } + + _releaseProgram( program ) { + + const code = program.code; + const stage = program.stage; + + this.programs[ stage ].delete( code ); + + } + + _needsComputeUpdate( computeNode ) { + + const data = this.get( computeNode ); + + return data.pipeline === undefined || data.version !== computeNode.version; + + } + + _needsRenderUpdate( renderObject ) { + + const data = this.get( renderObject ); + + return data.pipeline === undefined || this.backend.needsRenderUpdate( renderObject ); + + } + +} + +class Bindings extends DataMap { + + constructor( backend, nodes, textures, attributes, pipelines, info ) { + + super(); + + this.backend = backend; + this.textures = textures; + this.pipelines = pipelines; + this.attributes = attributes; + this.nodes = nodes; + this.info = info; + + this.pipelines.bindings = this; // assign bindings to pipelines + + } + + getForRender( renderObject ) { + + const bindings = renderObject.getBindings(); + + for ( const bindGroup of bindings ) { + + const groupData = this.get( bindGroup ); + + if ( groupData.bindGroup === undefined ) { + + // each object defines an array of bindings (ubos, textures, samplers etc.) + + this._init( bindGroup ); + + this.backend.createBindings( bindGroup, bindings ); + + groupData.bindGroup = bindGroup; + + } + + } + + return bindings; + + } + + getForCompute( computeNode ) { + + const bindings = this.nodes.getForCompute( computeNode ).bindings; + + for ( const bindGroup of bindings ) { + + const groupData = this.get( bindGroup ); + + if ( groupData.bindGroup === undefined ) { + + this._init( bindGroup ); + + this.backend.createBindings( bindGroup, bindings ); + + groupData.bindGroup = bindGroup; + + } + + } + + return bindings; + + } + + updateForCompute( computeNode ) { + + this._updateBindings( this.getForCompute( computeNode ) ); + + } + + updateForRender( renderObject ) { + + this._updateBindings( this.getForRender( renderObject ) ); + + } + + _updateBindings( bindings ) { + + for ( const bindGroup of bindings ) { + + this._update( bindGroup, bindings ); + + } + + } + + _init( bindGroup ) { + + for ( const binding of bindGroup.bindings ) { + + if ( binding.isSampledTexture ) { + + this.textures.updateTexture( binding.texture ); + + } else if ( binding.isStorageBuffer ) { + + const attribute = binding.attribute; + + this.attributes.update( attribute, AttributeType.STORAGE ); + + } + + } + + } + + _update( bindGroup, bindings ) { + + const { backend } = this; + + let needsBindingsUpdate = false; + + // iterate over all bindings and check if buffer updates or a new binding group is required + + for ( const binding of bindGroup.bindings ) { + + if ( binding.isNodeUniformsGroup ) { + + const updated = this.nodes.updateGroup( binding ); + + if ( ! updated ) continue; + + } + + if ( binding.isUniformBuffer ) { + + const updated = binding.update(); + + if ( updated ) { + + backend.updateBinding( binding ); + + } + + } else if ( binding.isSampler ) { + + binding.update(); + + } else if ( binding.isSampledTexture ) { + + if ( binding.needsBindingsUpdate( this.textures.get( binding.texture ).generation ) ) needsBindingsUpdate = true; + + const updated = binding.update(); + + const texture = binding.texture; + + if ( updated ) { + + this.textures.updateTexture( texture ); + + } + + const textureData = backend.get( texture ); + + if ( backend.isWebGPUBackend === true && textureData.texture === undefined && textureData.externalTexture === undefined ) { + + // TODO: Remove this once we found why updated === false isn't bound to a texture in the WebGPU backend + console.error( 'Bindings._update: binding should be available:', binding, updated, texture, binding.textureNode.value, needsBindingsUpdate ); + + this.textures.updateTexture( texture ); + needsBindingsUpdate = true; + + } + + if ( texture.isStorageTexture === true ) { + + const textureData = this.get( texture ); + + if ( binding.store === true ) { + + textureData.needsMipmap = true; + + } else if ( texture.generateMipmaps === true && this.textures.needsMipmaps( texture ) && textureData.needsMipmap === true ) { + + this.backend.generateMipmaps( texture ); + + textureData.needsMipmap = false; + + } + + } + + } + + } + + if ( needsBindingsUpdate === true ) { + + this.backend.updateBindings( bindGroup, bindings ); + + } + + } + +} + +class NodeAttribute { + + constructor( name, type, node = null ) { + + this.isNodeAttribute = true; + + this.name = name; + this.type = type; + this.node = node; + + } + +} + +class NodeUniform { + + constructor( name, type, node ) { + + this.isNodeUniform = true; + + this.name = name; + this.type = type; + this.node = node.getSelf(); + + } + + get value() { + + return this.node.value; + + } + + set value( val ) { + + this.node.value = val; + + } + + get id() { + + return this.node.id; + + } + + get groupNode() { + + return this.node.groupNode; + + } + +} + +class NodeVar { + + constructor( name, type ) { + + this.isNodeVar = true; + + this.name = name; + this.type = type; + + } + +} + +class NodeVarying extends NodeVar { + + constructor( name, type ) { + + super( name, type ); + + this.needsInterpolation = false; + + this.isNodeVarying = true; + + } + +} + +class NodeCode { + + constructor( name, type, code = '' ) { + + this.name = name; + this.type = type; + this.code = code; + + Object.defineProperty( this, 'isNodeCode', { value: true } ); + + } + +} + +let id$1 = 0; + +class NodeCache { + + constructor( parent = null ) { + + this.id = id$1 ++; + this.nodesData = new WeakMap(); + + this.parent = parent; + + } + + getData( node ) { + + let data = this.nodesData.get( node ); + + if ( data === undefined && this.parent !== null ) { + + data = this.parent.getData( node ); + + } + + return data; + + } + + setData( node, data ) { + + this.nodesData.set( node, data ); + + } + +} + +class ParameterNode extends PropertyNode { + + static get type() { + + return 'ParameterNode'; + + } + + constructor( nodeType, name = null ) { + + super( nodeType, name ); + + this.isParameterNode = true; + + } + + getHash() { + + return this.uuid; + + } + + generate() { + + return this.name; + + } + +} + +const parameter = ( type, name ) => nodeObject( new ParameterNode( type, name ) ); + +class CodeNode extends Node { + + static get type() { + + return 'CodeNode'; + + } + + constructor( code = '', includes = [], language = '' ) { + + super( 'code' ); + + this.isCodeNode = true; + + this.code = code; + this.language = language; + + this.includes = includes; + + } + + isGlobal() { + + return true; + + } + + setIncludes( includes ) { + + this.includes = includes; + + return this; + + } + + getIncludes( /*builder*/ ) { + + return this.includes; + + } + + generate( builder ) { + + const includes = this.getIncludes( builder ); + + for ( const include of includes ) { + + include.build( builder ); + + } + + const nodeCode = builder.getCodeFromNode( this, this.getNodeType( builder ) ); + nodeCode.code = this.code; + + return nodeCode.code; + + } + + serialize( data ) { + + super.serialize( data ); + + data.code = this.code; + data.language = this.language; + + } + + deserialize( data ) { + + super.deserialize( data ); + + this.code = data.code; + this.language = data.language; + + } + +} + +const code = /*@__PURE__*/ nodeProxy( CodeNode ); + +const js = ( src, includes ) => code( src, includes, 'js' ); +const wgsl = ( src, includes ) => code( src, includes, 'wgsl' ); +const glsl = ( src, includes ) => code( src, includes, 'glsl' ); + +class FunctionNode extends CodeNode { + + static get type() { + + return 'FunctionNode'; + + } + + constructor( code = '', includes = [], language = '' ) { + + super( code, includes, language ); + + } + + getNodeType( builder ) { + + return this.getNodeFunction( builder ).type; + + } + + getInputs( builder ) { + + return this.getNodeFunction( builder ).inputs; + + } + + getNodeFunction( builder ) { + + const nodeData = builder.getDataFromNode( this ); + + let nodeFunction = nodeData.nodeFunction; + + if ( nodeFunction === undefined ) { + + nodeFunction = builder.parser.parseFunction( this.code ); + + nodeData.nodeFunction = nodeFunction; + + } + + return nodeFunction; + + } + + generate( builder, output ) { + + super.generate( builder ); + + const nodeFunction = this.getNodeFunction( builder ); + + const name = nodeFunction.name; + const type = nodeFunction.type; + + const nodeCode = builder.getCodeFromNode( this, type ); + + if ( name !== '' ) { + + // use a custom property name + + nodeCode.name = name; + + } + + const propertyName = builder.getPropertyName( nodeCode ); + + const code = this.getNodeFunction( builder ).getCode( propertyName ); + + nodeCode.code = code + '\n'; + + if ( output === 'property' ) { + + return propertyName; + + } else { + + return builder.format( `${ propertyName }()`, type, output ); + + } + + } + +} + +const nativeFn = ( code, includes = [], language = '' ) => { + + for ( let i = 0; i < includes.length; i ++ ) { + + const include = includes[ i ]; + + // TSL Function: glslFn, wgslFn + + if ( typeof include === 'function' ) { + + includes[ i ] = include.functionNode; + + } + + } + + const functionNode = nodeObject( new FunctionNode( code, includes, language ) ); + + const fn = ( ...params ) => functionNode.call( ...params ); + fn.functionNode = functionNode; + + return fn; + +}; + +const glslFn = ( code, includes ) => nativeFn( code, includes, 'glsl' ); +const wgslFn = ( code, includes ) => nativeFn( code, includes, 'wgsl' ); + +class Uniform { + + constructor( name, value ) { + + this.name = name; + this.value = value; + + this.boundary = 0; // used to build the uniform buffer according to the STD140 layout + this.itemSize = 0; + + this.offset = 0; // this property is set by WebGPUUniformsGroup and marks the start position in the uniform buffer + + } + + setValue( value ) { + + this.value = value; + + } + + getValue() { + + return this.value; + + } + +} + +class NumberUniform extends Uniform { + + constructor( name, value = 0 ) { + + super( name, value ); + + this.isNumberUniform = true; + + this.boundary = 4; + this.itemSize = 1; + + } + +} + +class Vector2Uniform extends Uniform { + + constructor( name, value = new Vector2() ) { + + super( name, value ); + + this.isVector2Uniform = true; + + this.boundary = 8; + this.itemSize = 2; + + } + +} + +class Vector3Uniform extends Uniform { + + constructor( name, value = new Vector3() ) { + + super( name, value ); + + this.isVector3Uniform = true; + + this.boundary = 16; + this.itemSize = 3; + + } + +} + +class Vector4Uniform extends Uniform { + + constructor( name, value = new Vector4() ) { + + super( name, value ); + + this.isVector4Uniform = true; + + this.boundary = 16; + this.itemSize = 4; + + } + +} + +class ColorUniform extends Uniform { + + constructor( name, value = new Color() ) { + + super( name, value ); + + this.isColorUniform = true; + + this.boundary = 16; + this.itemSize = 3; + + } + +} + +class Matrix3Uniform extends Uniform { + + constructor( name, value = new Matrix3() ) { + + super( name, value ); + + this.isMatrix3Uniform = true; + + this.boundary = 48; + this.itemSize = 12; + + } + +} + +class Matrix4Uniform extends Uniform { + + constructor( name, value = new Matrix4() ) { + + super( name, value ); + + this.isMatrix4Uniform = true; + + this.boundary = 64; + this.itemSize = 16; + + } + +} + +class NumberNodeUniform extends NumberUniform { + + constructor( nodeUniform ) { + + super( nodeUniform.name, nodeUniform.value ); + + this.nodeUniform = nodeUniform; + + } + + getValue() { + + return this.nodeUniform.value; + + } + +} + +class Vector2NodeUniform extends Vector2Uniform { + + constructor( nodeUniform ) { + + super( nodeUniform.name, nodeUniform.value ); + + this.nodeUniform = nodeUniform; + + } + + getValue() { + + return this.nodeUniform.value; + + } + +} + +class Vector3NodeUniform extends Vector3Uniform { + + constructor( nodeUniform ) { + + super( nodeUniform.name, nodeUniform.value ); + + this.nodeUniform = nodeUniform; + + } + + getValue() { + + return this.nodeUniform.value; + + } + +} + +class Vector4NodeUniform extends Vector4Uniform { + + constructor( nodeUniform ) { + + super( nodeUniform.name, nodeUniform.value ); + + this.nodeUniform = nodeUniform; + + } + + getValue() { + + return this.nodeUniform.value; + + } + +} + +class ColorNodeUniform extends ColorUniform { + + constructor( nodeUniform ) { + + super( nodeUniform.name, nodeUniform.value ); + + this.nodeUniform = nodeUniform; + + } + + getValue() { + + return this.nodeUniform.value; + + } + +} + +class Matrix3NodeUniform extends Matrix3Uniform { + + constructor( nodeUniform ) { + + super( nodeUniform.name, nodeUniform.value ); + + this.nodeUniform = nodeUniform; + + } + + getValue() { + + return this.nodeUniform.value; + + } + +} + +class Matrix4NodeUniform extends Matrix4Uniform { + + constructor( nodeUniform ) { + + super( nodeUniform.name, nodeUniform.value ); + + this.nodeUniform = nodeUniform; + + } + + getValue() { + + return this.nodeUniform.value; + + } + +} + +class StackNode extends Node { + + static get type() { + + return 'StackNode'; + + } + + constructor( parent = null ) { + + super(); + + this.nodes = []; + this.outputNode = null; + + this.parent = parent; + + this._currentCond = null; + + this.isStackNode = true; + + } + + getNodeType( builder ) { + + return this.outputNode ? this.outputNode.getNodeType( builder ) : 'void'; + + } + + add( node ) { + + this.nodes.push( node ); + + return this; + + } + + If( boolNode, method ) { + + const methodNode = new ShaderNode( method ); + this._currentCond = select( boolNode, methodNode ); + + return this.add( this._currentCond ); + + } + + ElseIf( boolNode, method ) { + + const methodNode = new ShaderNode( method ); + const ifNode = select( boolNode, methodNode ); + + this._currentCond.elseNode = ifNode; + this._currentCond = ifNode; + + return this; + + } + + Else( method ) { + + this._currentCond.elseNode = new ShaderNode( method ); + + return this; + + } + + build( builder, ...params ) { + + const previousStack = getCurrentStack(); + + setCurrentStack( this ); + + for ( const node of this.nodes ) { + + node.build( builder, 'void' ); + + } + + setCurrentStack( previousStack ); + + return this.outputNode ? this.outputNode.build( builder, ...params ) : super.build( builder, ...params ); + + } + + // + + else( ...params ) { // @deprecated, r168 + + console.warn( 'TSL.StackNode: .else() has been renamed to .Else().' ); + return this.Else( ...params ); + + } + + elseif( ...params ) { // @deprecated, r168 + + console.warn( 'TSL.StackNode: .elseif() has been renamed to .ElseIf().' ); + return this.ElseIf( ...params ); + + } + +} + +const stack = /*@__PURE__*/ nodeProxy( StackNode ); + +const LOD_MIN = 4; + +// The standard deviations (radians) associated with the extra mips. These are +// chosen to approximate a Trowbridge-Reitz distribution function times the +// geometric shadowing function. These sigma values squared must match the +// variance #defines in cube_uv_reflection_fragment.glsl.js. +const EXTRA_LOD_SIGMA = [ 0.125, 0.215, 0.35, 0.446, 0.526, 0.582 ]; + +// The maximum length of the blur for loop. Smaller sigmas will use fewer +// samples and exit early, but not recompile the shader. +const MAX_SAMPLES = 20; + +const _flatCamera = /*@__PURE__*/ new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); +const _cubeCamera = /*@__PURE__*/ new PerspectiveCamera( 90, 1 ); +const _clearColor$2 = /*@__PURE__*/ new Color(); +let _oldTarget = null; +let _oldActiveCubeFace = 0; +let _oldActiveMipmapLevel = 0; + +// Golden Ratio +const PHI = ( 1 + Math.sqrt( 5 ) ) / 2; +const INV_PHI = 1 / PHI; + +// Vertices of a dodecahedron (except the opposites, which represent the +// same axis), used as axis directions evenly spread on a sphere. +const _axisDirections = [ + /*@__PURE__*/ new Vector3( - PHI, INV_PHI, 0 ), + /*@__PURE__*/ new Vector3( PHI, INV_PHI, 0 ), + /*@__PURE__*/ new Vector3( - INV_PHI, 0, PHI ), + /*@__PURE__*/ new Vector3( INV_PHI, 0, PHI ), + /*@__PURE__*/ new Vector3( 0, PHI, - INV_PHI ), + /*@__PURE__*/ new Vector3( 0, PHI, INV_PHI ), + /*@__PURE__*/ new Vector3( - 1, 1, - 1 ), + /*@__PURE__*/ new Vector3( 1, 1, - 1 ), + /*@__PURE__*/ new Vector3( - 1, 1, 1 ), + /*@__PURE__*/ new Vector3( 1, 1, 1 ) +]; + +// + +// WebGPU Face indices +const _faceLib = [ + 3, 1, 5, + 0, 4, 2 +]; + +const direction = getDirection( uv(), attribute( 'faceIndex' ) ).normalize(); +const outputDirection = vec3( direction.x, direction.y.negate(), direction.z ); + +/** + * This class generates a Prefiltered, Mipmapped Radiance Environment Map + * (PMREM) from a cubeMap environment texture. This allows different levels of + * blur to be quickly accessed based on material roughness. It is packed into a + * special CubeUV format that allows us to perform custom interpolation so that + * we can support nonlinear formats such as RGBE. Unlike a traditional mipmap + * chain, it only goes down to the LOD_MIN level (above), and then creates extra + * even more filtered 'mips' at the same LOD_MIN resolution, associated with + * higher roughness levels. In this way we maintain resolution to smoothly + * interpolate diffuse lighting while limiting sampling computation. + * + * Paper: Fast, Accurate Image-Based Lighting + * https://drive.google.com/file/d/15y8r_UpKlU9SvV4ILb0C3qCPecS8pvLz/view +*/ + +class PMREMGenerator { + + constructor( renderer ) { + + this._renderer = renderer; + this._pingPongRenderTarget = null; + + this._lodMax = 0; + this._cubeSize = 0; + this._lodPlanes = []; + this._sizeLods = []; + this._sigmas = []; + this._lodMeshes = []; + + this._blurMaterial = null; + this._cubemapMaterial = null; + this._equirectMaterial = null; + this._backgroundBox = null; + + } + + /** + * Generates a PMREM from a supplied Scene, which can be faster than using an + * image if networking bandwidth is low. Optional sigma specifies a blur radius + * in radians to be applied to the scene before PMREM generation. Optional near + * and far planes ensure the scene is rendered in its entirety (the cubeCamera + * is placed at the origin). + */ + fromScene( scene, sigma = 0, near = 0.1, far = 100 ) { + + _oldTarget = this._renderer.getRenderTarget(); + _oldActiveCubeFace = this._renderer.getActiveCubeFace(); + _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); + + this._setSize( 256 ); + + const cubeUVRenderTarget = this._allocateTargets(); + cubeUVRenderTarget.depthBuffer = true; + + this._sceneToCubeUV( scene, near, far, cubeUVRenderTarget ); + + if ( sigma > 0 ) { + + this._blur( cubeUVRenderTarget, 0, 0, sigma ); + + } + + this._applyPMREM( cubeUVRenderTarget ); + + this._cleanup( cubeUVRenderTarget ); + + return cubeUVRenderTarget; + + } + + /** + * Generates a PMREM from an equirectangular texture, which can be either LDR + * or HDR. The ideal input image size is 1k (1024 x 512), + * as this matches best with the 256 x 256 cubemap output. + */ + fromEquirectangular( equirectangular, renderTarget = null ) { + + return this._fromTexture( equirectangular, renderTarget ); + + } + + /** + * Generates a PMREM from an cubemap texture, which can be either LDR + * or HDR. The ideal input cube size is 256 x 256, + * as this matches best with the 256 x 256 cubemap output. + */ + fromCubemap( cubemap, renderTarget = null ) { + + return this._fromTexture( cubemap, renderTarget ); + + } + + /** + * Pre-compiles the cubemap shader. You can get faster start-up by invoking this method during + * your texture's network fetch for increased concurrency. + */ + async compileCubemapShader() { + + if ( this._cubemapMaterial === null ) { + + this._cubemapMaterial = _getCubemapMaterial(); + await this._compileMaterial( this._cubemapMaterial ); + + } + + } + + /** + * Pre-compiles the equirectangular shader. You can get faster start-up by invoking this method during + * your texture's network fetch for increased concurrency. + */ + async compileEquirectangularShader() { + + if ( this._equirectMaterial === null ) { + + this._equirectMaterial = _getEquirectMaterial(); + await this._compileMaterial( this._equirectMaterial ); + + } + + } + + /** + * Disposes of the PMREMGenerator's internal memory. Note that PMREMGenerator is a static class, + * so you should not need more than one PMREMGenerator object. If you do, calling dispose() on + * one of them will cause any others to also become unusable. + */ + dispose() { + + this._dispose(); + + if ( this._cubemapMaterial !== null ) this._cubemapMaterial.dispose(); + if ( this._equirectMaterial !== null ) this._equirectMaterial.dispose(); + if ( this._backgroundBox !== null ) { + + this._backgroundBox.geometry.dispose(); + this._backgroundBox.material.dispose(); + + } + + } + + // private interface + + _setSize( cubeSize ) { + + this._lodMax = Math.floor( Math.log2( cubeSize ) ); + this._cubeSize = Math.pow( 2, this._lodMax ); + + } + + _dispose() { + + if ( this._blurMaterial !== null ) this._blurMaterial.dispose(); + + if ( this._pingPongRenderTarget !== null ) this._pingPongRenderTarget.dispose(); + + for ( let i = 0; i < this._lodPlanes.length; i ++ ) { + + this._lodPlanes[ i ].dispose(); + + } + + } + + _cleanup( outputTarget ) { + + this._renderer.setRenderTarget( _oldTarget, _oldActiveCubeFace, _oldActiveMipmapLevel ); + outputTarget.scissorTest = false; + _setViewport( outputTarget, 0, 0, outputTarget.width, outputTarget.height ); + + } + + _fromTexture( texture, renderTarget ) { + + if ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ) { + + this._setSize( texture.image.length === 0 ? 16 : ( texture.image[ 0 ].width || texture.image[ 0 ].image.width ) ); + + } else { // Equirectangular + + this._setSize( texture.image.width / 4 ); + + } + + _oldTarget = this._renderer.getRenderTarget(); + _oldActiveCubeFace = this._renderer.getActiveCubeFace(); + _oldActiveMipmapLevel = this._renderer.getActiveMipmapLevel(); + + const cubeUVRenderTarget = renderTarget || this._allocateTargets(); + this._textureToCubeUV( texture, cubeUVRenderTarget ); + this._applyPMREM( cubeUVRenderTarget ); + this._cleanup( cubeUVRenderTarget ); + + return cubeUVRenderTarget; + + } + + _allocateTargets() { + + const width = 3 * Math.max( this._cubeSize, 16 * 7 ); + const height = 4 * this._cubeSize; + + const params = { + magFilter: LinearFilter, + minFilter: LinearFilter, + generateMipmaps: false, + type: HalfFloatType, + format: RGBAFormat, + colorSpace: LinearSRGBColorSpace, + //depthBuffer: false + }; + + const cubeUVRenderTarget = _createRenderTarget( width, height, params ); + + if ( this._pingPongRenderTarget === null || this._pingPongRenderTarget.width !== width || this._pingPongRenderTarget.height !== height ) { + + if ( this._pingPongRenderTarget !== null ) { + + this._dispose(); + + } + + this._pingPongRenderTarget = _createRenderTarget( width, height, params ); + + const { _lodMax } = this; + ( { sizeLods: this._sizeLods, lodPlanes: this._lodPlanes, sigmas: this._sigmas, lodMeshes: this._lodMeshes } = _createPlanes( _lodMax ) ); + + this._blurMaterial = _getBlurShader( _lodMax, width, height ); + + } + + return cubeUVRenderTarget; + + } + + async _compileMaterial( material ) { + + const tmpMesh = new Mesh( this._lodPlanes[ 0 ], material ); + await this._renderer.compile( tmpMesh, _flatCamera ); + + } + + _sceneToCubeUV( scene, near, far, cubeUVRenderTarget ) { + + const cubeCamera = _cubeCamera; + cubeCamera.near = near; + cubeCamera.far = far; + + // px, py, pz, nx, ny, nz + const upSign = [ - 1, 1, - 1, - 1, - 1, - 1 ]; + const forwardSign = [ 1, 1, 1, - 1, - 1, - 1 ]; + + const renderer = this._renderer; + + const originalAutoClear = renderer.autoClear; + + renderer.getClearColor( _clearColor$2 ); + + renderer.autoClear = false; + + let backgroundBox = this._backgroundBox; + + if ( backgroundBox === null ) { + + const backgroundMaterial = new MeshBasicMaterial( { + name: 'PMREM.Background', + side: BackSide, + depthWrite: false, + depthTest: false + } ); + + backgroundBox = new Mesh( new BoxGeometry(), backgroundMaterial ); + + } + + let useSolidColor = false; + const background = scene.background; + + if ( background ) { + + if ( background.isColor ) { + + backgroundBox.material.color.copy( background ); + scene.background = null; + useSolidColor = true; + + } + + } else { + + backgroundBox.material.color.copy( _clearColor$2 ); + useSolidColor = true; + + } + + renderer.setRenderTarget( cubeUVRenderTarget ); + + renderer.clear(); + + if ( useSolidColor ) { + + renderer.render( backgroundBox, cubeCamera ); + + } + + for ( let i = 0; i < 6; i ++ ) { + + const col = i % 3; + + if ( col === 0 ) { + + cubeCamera.up.set( 0, upSign[ i ], 0 ); + cubeCamera.lookAt( forwardSign[ i ], 0, 0 ); + + } else if ( col === 1 ) { + + cubeCamera.up.set( 0, 0, upSign[ i ] ); + cubeCamera.lookAt( 0, forwardSign[ i ], 0 ); + + } else { + + cubeCamera.up.set( 0, upSign[ i ], 0 ); + cubeCamera.lookAt( 0, 0, forwardSign[ i ] ); + + } + + const size = this._cubeSize; + + _setViewport( cubeUVRenderTarget, col * size, i > 2 ? size : 0, size, size ); + + renderer.render( scene, cubeCamera ); + + } + + renderer.autoClear = originalAutoClear; + scene.background = background; + + } + + _textureToCubeUV( texture, cubeUVRenderTarget ) { + + const renderer = this._renderer; + + const isCubeTexture = ( texture.mapping === CubeReflectionMapping || texture.mapping === CubeRefractionMapping ); + + if ( isCubeTexture ) { + + if ( this._cubemapMaterial === null ) { + + this._cubemapMaterial = _getCubemapMaterial( texture ); + + } + + } else { + + if ( this._equirectMaterial === null ) { + + this._equirectMaterial = _getEquirectMaterial( texture ); + + } + + } + + const material = isCubeTexture ? this._cubemapMaterial : this._equirectMaterial; + material.fragmentNode.value = texture; + + const mesh = this._lodMeshes[ 0 ]; + mesh.material = material; + + const size = this._cubeSize; + + _setViewport( cubeUVRenderTarget, 0, 0, 3 * size, 2 * size ); + + renderer.setRenderTarget( cubeUVRenderTarget ); + renderer.render( mesh, _flatCamera ); + + } + + _applyPMREM( cubeUVRenderTarget ) { + + const renderer = this._renderer; + const autoClear = renderer.autoClear; + renderer.autoClear = false; + const n = this._lodPlanes.length; + + for ( let i = 1; i < n; i ++ ) { + + const sigma = Math.sqrt( this._sigmas[ i ] * this._sigmas[ i ] - this._sigmas[ i - 1 ] * this._sigmas[ i - 1 ] ); + + const poleAxis = _axisDirections[ ( n - i - 1 ) % _axisDirections.length ]; + + this._blur( cubeUVRenderTarget, i - 1, i, sigma, poleAxis ); + + } + + renderer.autoClear = autoClear; + + } + + /** + * This is a two-pass Gaussian blur for a cubemap. Normally this is done + * vertically and horizontally, but this breaks down on a cube. Here we apply + * the blur latitudinally (around the poles), and then longitudinally (towards + * the poles) to approximate the orthogonally-separable blur. It is least + * accurate at the poles, but still does a decent job. + */ + _blur( cubeUVRenderTarget, lodIn, lodOut, sigma, poleAxis ) { + + const pingPongRenderTarget = this._pingPongRenderTarget; + + this._halfBlur( + cubeUVRenderTarget, + pingPongRenderTarget, + lodIn, + lodOut, + sigma, + 'latitudinal', + poleAxis ); + + this._halfBlur( + pingPongRenderTarget, + cubeUVRenderTarget, + lodOut, + lodOut, + sigma, + 'longitudinal', + poleAxis ); + + } + + _halfBlur( targetIn, targetOut, lodIn, lodOut, sigmaRadians, direction, poleAxis ) { + + const renderer = this._renderer; + const blurMaterial = this._blurMaterial; + + if ( direction !== 'latitudinal' && direction !== 'longitudinal' ) { + + console.error( 'blur direction must be either latitudinal or longitudinal!' ); + + } + + // Number of standard deviations at which to cut off the discrete approximation. + const STANDARD_DEVIATIONS = 3; + + const blurMesh = this._lodMeshes[ lodOut ]; + blurMesh.material = blurMaterial; + + const blurUniforms = blurMaterial.uniforms; + + const pixels = this._sizeLods[ lodIn ] - 1; + const radiansPerPixel = isFinite( sigmaRadians ) ? Math.PI / ( 2 * pixels ) : 2 * Math.PI / ( 2 * MAX_SAMPLES - 1 ); + const sigmaPixels = sigmaRadians / radiansPerPixel; + const samples = isFinite( sigmaRadians ) ? 1 + Math.floor( STANDARD_DEVIATIONS * sigmaPixels ) : MAX_SAMPLES; + + if ( samples > MAX_SAMPLES ) { + + console.warn( `sigmaRadians, ${ + sigmaRadians}, is too large and will clip, as it requested ${ + samples} samples when the maximum is set to ${MAX_SAMPLES}` ); + + } + + const weights = []; + let sum = 0; + + for ( let i = 0; i < MAX_SAMPLES; ++ i ) { + + const x = i / sigmaPixels; + const weight = Math.exp( - x * x / 2 ); + weights.push( weight ); + + if ( i === 0 ) { + + sum += weight; + + } else if ( i < samples ) { + + sum += 2 * weight; + + } + + } + + for ( let i = 0; i < weights.length; i ++ ) { + + weights[ i ] = weights[ i ] / sum; + + } + + targetIn.texture.frame = ( targetIn.texture.frame || 0 ) + 1; + + blurUniforms.envMap.value = targetIn.texture; + blurUniforms.samples.value = samples; + blurUniforms.weights.array = weights; + blurUniforms.latitudinal.value = direction === 'latitudinal' ? 1 : 0; + + if ( poleAxis ) { + + blurUniforms.poleAxis.value = poleAxis; + + } + + const { _lodMax } = this; + blurUniforms.dTheta.value = radiansPerPixel; + blurUniforms.mipInt.value = _lodMax - lodIn; + + const outputSize = this._sizeLods[ lodOut ]; + const x = 3 * outputSize * ( lodOut > _lodMax - LOD_MIN ? lodOut - _lodMax + LOD_MIN : 0 ); + const y = 4 * ( this._cubeSize - outputSize ); + + _setViewport( targetOut, x, y, 3 * outputSize, 2 * outputSize ); + renderer.setRenderTarget( targetOut ); + renderer.render( blurMesh, _flatCamera ); + + } + +} + +function _createPlanes( lodMax ) { + + const lodPlanes = []; + const sizeLods = []; + const sigmas = []; + const lodMeshes = []; + + let lod = lodMax; + + const totalLods = lodMax - LOD_MIN + 1 + EXTRA_LOD_SIGMA.length; + + for ( let i = 0; i < totalLods; i ++ ) { + + const sizeLod = Math.pow( 2, lod ); + sizeLods.push( sizeLod ); + let sigma = 1.0 / sizeLod; + + if ( i > lodMax - LOD_MIN ) { + + sigma = EXTRA_LOD_SIGMA[ i - lodMax + LOD_MIN - 1 ]; + + } else if ( i === 0 ) { + + sigma = 0; + + } + + sigmas.push( sigma ); + + const texelSize = 1.0 / ( sizeLod - 2 ); + const min = - texelSize; + const max = 1 + texelSize; + const uv1 = [ min, min, max, min, max, max, min, min, max, max, min, max ]; + + const cubeFaces = 6; + const vertices = 6; + const positionSize = 3; + const uvSize = 2; + const faceIndexSize = 1; + + const position = new Float32Array( positionSize * vertices * cubeFaces ); + const uv = new Float32Array( uvSize * vertices * cubeFaces ); + const faceIndex = new Float32Array( faceIndexSize * vertices * cubeFaces ); + + for ( let face = 0; face < cubeFaces; face ++ ) { + + const x = ( face % 3 ) * 2 / 3 - 1; + const y = face > 2 ? 0 : - 1; + const coordinates = [ + x, y, 0, + x + 2 / 3, y, 0, + x + 2 / 3, y + 1, 0, + x, y, 0, + x + 2 / 3, y + 1, 0, + x, y + 1, 0 + ]; + + const faceIdx = _faceLib[ face ]; + position.set( coordinates, positionSize * vertices * faceIdx ); + uv.set( uv1, uvSize * vertices * faceIdx ); + const fill = [ faceIdx, faceIdx, faceIdx, faceIdx, faceIdx, faceIdx ]; + faceIndex.set( fill, faceIndexSize * vertices * faceIdx ); + + } + + const planes = new BufferGeometry(); + planes.setAttribute( 'position', new BufferAttribute( position, positionSize ) ); + planes.setAttribute( 'uv', new BufferAttribute( uv, uvSize ) ); + planes.setAttribute( 'faceIndex', new BufferAttribute( faceIndex, faceIndexSize ) ); + lodPlanes.push( planes ); + lodMeshes.push( new Mesh( planes, null ) ); + + if ( lod > LOD_MIN ) { + + lod --; + + } + + } + + return { lodPlanes, sizeLods, sigmas, lodMeshes }; + +} + +function _createRenderTarget( width, height, params ) { + + const cubeUVRenderTarget = new RenderTarget( width, height, params ); + cubeUVRenderTarget.texture.mapping = CubeUVReflectionMapping; + cubeUVRenderTarget.texture.name = 'PMREM.cubeUv'; + cubeUVRenderTarget.texture.isPMREMTexture = true; + cubeUVRenderTarget.scissorTest = true; + return cubeUVRenderTarget; + +} + +function _setViewport( target, x, y, width, height ) { + + target.viewport.set( x, y, width, height ); + target.scissor.set( x, y, width, height ); + +} + +function _getMaterial( type ) { + + const material = new NodeMaterial(); + material.depthTest = false; + material.depthWrite = false; + material.blending = NoBlending; + material.name = `PMREM_${ type }`; + + return material; + +} + +function _getBlurShader( lodMax, width, height ) { + + const weights = uniformArray( new Array( MAX_SAMPLES ).fill( 0 ) ); + const poleAxis = uniform( new Vector3( 0, 1, 0 ) ); + const dTheta = uniform( 0 ); + const n = float( MAX_SAMPLES ); + const latitudinal = uniform( 0 ); // false, bool + const samples = uniform( 1 ); // int + const envMap = texture( null ); + const mipInt = uniform( 0 ); // int + const CUBEUV_TEXEL_WIDTH = float( 1 / width ); + const CUBEUV_TEXEL_HEIGHT = float( 1 / height ); + const CUBEUV_MAX_MIP = float( lodMax ); + + const materialUniforms = { + n, + latitudinal, + weights, + poleAxis, + outputDirection, + dTheta, + samples, + envMap, + mipInt, + CUBEUV_TEXEL_WIDTH, + CUBEUV_TEXEL_HEIGHT, + CUBEUV_MAX_MIP + }; + + const material = _getMaterial( 'blur' ); + material.uniforms = materialUniforms; // TODO: Move to outside of the material + material.fragmentNode = blur( { ...materialUniforms, latitudinal: latitudinal.equal( 1 ) } ); + + return material; + +} + +function _getCubemapMaterial( envTexture ) { + + const material = _getMaterial( 'cubemap' ); + material.fragmentNode = cubeTexture( envTexture, outputDirection ); + + return material; + +} + +function _getEquirectMaterial( envTexture ) { + + const material = _getMaterial( 'equirect' ); + material.fragmentNode = texture( envTexture, equirectUV( outputDirection ), 0 ); + + return material; + +} + +let _id$5 = 0; + +class BindGroup { + + constructor( name = '', bindings = [], index = 0, bindingsReference = [] ) { + + this.name = name; + this.bindings = bindings; + this.index = index; + this.bindingsReference = bindingsReference; + + this.id = _id$5 ++; + + } + +} + +const rendererCache = new WeakMap(); + +const typeFromLength = new Map( [ + [ 2, 'vec2' ], + [ 3, 'vec3' ], + [ 4, 'vec4' ], + [ 9, 'mat3' ], + [ 16, 'mat4' ] +] ); + +const typeFromArray = new Map( [ + [ Int8Array, 'int' ], + [ Int16Array, 'int' ], + [ Int32Array, 'int' ], + [ Uint8Array, 'uint' ], + [ Uint16Array, 'uint' ], + [ Uint32Array, 'uint' ], + [ Float32Array, 'float' ] +] ); + +const toFloat = ( value ) => { + + value = Number( value ); + + return value + ( value % 1 ? '' : '.0' ); + +}; + +class NodeBuilder { + + constructor( object, renderer, parser ) { + + this.object = object; + this.material = ( object && object.material ) || null; + this.geometry = ( object && object.geometry ) || null; + this.renderer = renderer; + this.parser = parser; + this.scene = null; + this.camera = null; + + this.nodes = []; + this.updateNodes = []; + this.updateBeforeNodes = []; + this.updateAfterNodes = []; + this.hashNodes = {}; + + this.monitor = null; + + this.lightsNode = null; + this.environmentNode = null; + this.fogNode = null; + + this.clippingContext = null; + + this.vertexShader = null; + this.fragmentShader = null; + this.computeShader = null; + + this.flowNodes = { vertex: [], fragment: [], compute: [] }; + this.flowCode = { vertex: '', fragment: '', compute: '' }; + this.uniforms = { vertex: [], fragment: [], compute: [], index: 0 }; + this.structs = { vertex: [], fragment: [], compute: [], index: 0 }; + this.bindings = { vertex: {}, fragment: {}, compute: {} }; + this.bindingsIndexes = {}; + this.bindGroups = null; + this.attributes = []; + this.bufferAttributes = []; + this.varyings = []; + this.codes = {}; + this.vars = {}; + this.flow = { code: '' }; + this.chaining = []; + this.stack = stack(); + this.stacks = []; + this.tab = '\t'; + + this.currentFunctionNode = null; + + this.context = { + material: this.material + }; + + this.cache = new NodeCache(); + this.globalCache = this.cache; + + this.flowsData = new WeakMap(); + + this.shaderStage = null; + this.buildStage = null; + + this.useComparisonMethod = false; + + } + + getBindGroupsCache() { + + let bindGroupsCache = rendererCache.get( this.renderer ); + + if ( bindGroupsCache === undefined ) { + + bindGroupsCache = new ChainMap(); + + rendererCache.set( this.renderer, bindGroupsCache ); + + } + + return bindGroupsCache; + + } + + createRenderTarget( width, height, options ) { + + return new RenderTarget( width, height, options ); + + } + + createCubeRenderTarget( size, options ) { + + return new CubeRenderTarget( size, options ); + + } + + createPMREMGenerator() { + + // TODO: Move Materials.js to outside of the Nodes.js in order to remove this function and improve tree-shaking support + + return new PMREMGenerator( this.renderer ); + + } + + includes( node ) { + + return this.nodes.includes( node ); + + } + + _getBindGroup( groupName, bindings ) { + + const bindGroupsCache = this.getBindGroupsCache(); + + // + + const bindingsArray = []; + + let sharedGroup = true; + + for ( const binding of bindings ) { + + bindingsArray.push( binding ); + + sharedGroup = sharedGroup && binding.groupNode.shared !== true; + + } + + // + + let bindGroup; + + if ( sharedGroup ) { + + bindGroup = bindGroupsCache.get( bindingsArray ); + + if ( bindGroup === undefined ) { + + bindGroup = new BindGroup( groupName, bindingsArray, this.bindingsIndexes[ groupName ].group, bindingsArray ); + + bindGroupsCache.set( bindingsArray, bindGroup ); + + } + + } else { + + bindGroup = new BindGroup( groupName, bindingsArray, this.bindingsIndexes[ groupName ].group, bindingsArray ); + + } + + return bindGroup; + + } + + getBindGroupArray( groupName, shaderStage ) { + + const bindings = this.bindings[ shaderStage ]; + + let bindGroup = bindings[ groupName ]; + + if ( bindGroup === undefined ) { + + if ( this.bindingsIndexes[ groupName ] === undefined ) { + + this.bindingsIndexes[ groupName ] = { binding: 0, group: Object.keys( this.bindingsIndexes ).length }; + + } + + bindings[ groupName ] = bindGroup = []; + + } + + return bindGroup; + + } + + getBindings() { + + let bindingsGroups = this.bindGroups; + + if ( bindingsGroups === null ) { + + const groups = {}; + const bindings = this.bindings; + + for ( const shaderStage of shaderStages ) { + + for ( const groupName in bindings[ shaderStage ] ) { + + const uniforms = bindings[ shaderStage ][ groupName ]; + + const groupUniforms = groups[ groupName ] || ( groups[ groupName ] = [] ); + groupUniforms.push( ...uniforms ); + + } + + } + + bindingsGroups = []; + + for ( const groupName in groups ) { + + const group = groups[ groupName ]; + + const bindingsGroup = this._getBindGroup( groupName, group ); + + bindingsGroups.push( bindingsGroup ); + + } + + this.bindGroups = bindingsGroups; + + } + + return bindingsGroups; + + } + + sortBindingGroups() { + + const bindingsGroups = this.getBindings(); + + bindingsGroups.sort( ( a, b ) => ( a.bindings[ 0 ].groupNode.order - b.bindings[ 0 ].groupNode.order ) ); + + for ( let i = 0; i < bindingsGroups.length; i ++ ) { + + const bindingGroup = bindingsGroups[ i ]; + this.bindingsIndexes[ bindingGroup.name ].group = i; + + bindingGroup.index = i; + + } + + } + + setHashNode( node, hash ) { + + this.hashNodes[ hash ] = node; + + } + + addNode( node ) { + + if ( this.nodes.includes( node ) === false ) { + + this.nodes.push( node ); + + this.setHashNode( node, node.getHash( this ) ); + + } + + } + + buildUpdateNodes() { + + for ( const node of this.nodes ) { + + const updateType = node.getUpdateType(); + const updateBeforeType = node.getUpdateBeforeType(); + const updateAfterType = node.getUpdateAfterType(); + + if ( updateType !== NodeUpdateType.NONE ) { + + this.updateNodes.push( node.getSelf() ); + + } + + if ( updateBeforeType !== NodeUpdateType.NONE ) { + + this.updateBeforeNodes.push( node.getSelf() ); + + } + + if ( updateAfterType !== NodeUpdateType.NONE ) { + + this.updateAfterNodes.push( node.getSelf() ); + + } + + } + + } + + get currentNode() { + + return this.chaining[ this.chaining.length - 1 ]; + + } + + isFilteredTexture( texture ) { + + return ( texture.magFilter === LinearFilter || texture.magFilter === LinearMipmapNearestFilter || texture.magFilter === NearestMipmapLinearFilter || texture.magFilter === LinearMipmapLinearFilter || + texture.minFilter === LinearFilter || texture.minFilter === LinearMipmapNearestFilter || texture.minFilter === NearestMipmapLinearFilter || texture.minFilter === LinearMipmapLinearFilter ); + + } + + addChain( node ) { + + /* + if ( this.chaining.indexOf( node ) !== - 1 ) { + + console.warn( 'Recursive node: ', node ); + + } + */ + + this.chaining.push( node ); + + } + + removeChain( node ) { + + const lastChain = this.chaining.pop(); + + if ( lastChain !== node ) { + + throw new Error( 'NodeBuilder: Invalid node chaining!' ); + + } + + } + + getMethod( method ) { + + return method; + + } + + getNodeFromHash( hash ) { + + return this.hashNodes[ hash ]; + + } + + addFlow( shaderStage, node ) { + + this.flowNodes[ shaderStage ].push( node ); + + return node; + + } + + setContext( context ) { + + this.context = context; + + } + + getContext() { + + return this.context; + + } + + getSharedContext() { + + ({ ...this.context }); + + return this.context; + + } + + setCache( cache ) { + + this.cache = cache; + + } + + getCache() { + + return this.cache; + + } + + getCacheFromNode( node, parent = true ) { + + const data = this.getDataFromNode( node ); + if ( data.cache === undefined ) data.cache = new NodeCache( parent ? this.getCache() : null ); + + return data.cache; + + } + + isAvailable( /*name*/ ) { + + return false; + + } + + getVertexIndex() { + + console.warn( 'Abstract function.' ); + + } + + getInstanceIndex() { + + console.warn( 'Abstract function.' ); + + } + + getDrawIndex() { + + console.warn( 'Abstract function.' ); + + } + + getFrontFacing() { + + console.warn( 'Abstract function.' ); + + } + + getFragCoord() { + + console.warn( 'Abstract function.' ); + + } + + isFlipY() { + + return false; + + } + + increaseUsage( node ) { + + const nodeData = this.getDataFromNode( node ); + nodeData.usageCount = nodeData.usageCount === undefined ? 1 : nodeData.usageCount + 1; + + return nodeData.usageCount; + + } + + generateTexture( /* texture, textureProperty, uvSnippet */ ) { + + console.warn( 'Abstract function.' ); + + } + + generateTextureLod( /* texture, textureProperty, uvSnippet, levelSnippet */ ) { + + console.warn( 'Abstract function.' ); + + } + + generateConst( type, value = null ) { + + if ( value === null ) { + + if ( type === 'float' || type === 'int' || type === 'uint' ) value = 0; + else if ( type === 'bool' ) value = false; + else if ( type === 'color' ) value = new Color(); + else if ( type === 'vec2' ) value = new Vector2(); + else if ( type === 'vec3' ) value = new Vector3(); + else if ( type === 'vec4' ) value = new Vector4(); + + } + + if ( type === 'float' ) return toFloat( value ); + if ( type === 'int' ) return `${ Math.round( value ) }`; + if ( type === 'uint' ) return value >= 0 ? `${ Math.round( value ) }u` : '0u'; + if ( type === 'bool' ) return value ? 'true' : 'false'; + if ( type === 'color' ) return `${ this.getType( 'vec3' ) }( ${ toFloat( value.r ) }, ${ toFloat( value.g ) }, ${ toFloat( value.b ) } )`; + + const typeLength = this.getTypeLength( type ); + + const componentType = this.getComponentType( type ); + + const generateConst = value => this.generateConst( componentType, value ); + + if ( typeLength === 2 ) { + + return `${ this.getType( type ) }( ${ generateConst( value.x ) }, ${ generateConst( value.y ) } )`; + + } else if ( typeLength === 3 ) { + + return `${ this.getType( type ) }( ${ generateConst( value.x ) }, ${ generateConst( value.y ) }, ${ generateConst( value.z ) } )`; + + } else if ( typeLength === 4 ) { + + return `${ this.getType( type ) }( ${ generateConst( value.x ) }, ${ generateConst( value.y ) }, ${ generateConst( value.z ) }, ${ generateConst( value.w ) } )`; + + } else if ( typeLength > 4 && value && ( value.isMatrix3 || value.isMatrix4 ) ) { + + return `${ this.getType( type ) }( ${ value.elements.map( generateConst ).join( ', ' ) } )`; + + } else if ( typeLength > 4 ) { + + return `${ this.getType( type ) }()`; + + } + + throw new Error( `NodeBuilder: Type '${type}' not found in generate constant attempt.` ); + + } + + getType( type ) { + + if ( type === 'color' ) return 'vec3'; + + return type; + + } + + hasGeometryAttribute( name ) { + + return this.geometry && this.geometry.getAttribute( name ) !== undefined; + + } + + getAttribute( name, type ) { + + const attributes = this.attributes; + + // find attribute + + for ( const attribute of attributes ) { + + if ( attribute.name === name ) { + + return attribute; + + } + + } + + // create a new if no exist + + const attribute = new NodeAttribute( name, type ); + + attributes.push( attribute ); + + return attribute; + + } + + getPropertyName( node/*, shaderStage*/ ) { + + return node.name; + + } + + isVector( type ) { + + return /vec\d/.test( type ); + + } + + isMatrix( type ) { + + return /mat\d/.test( type ); + + } + + isReference( type ) { + + return type === 'void' || type === 'property' || type === 'sampler' || type === 'texture' || type === 'cubeTexture' || type === 'storageTexture' || type === 'depthTexture' || type === 'texture3D'; + + } + + needsToWorkingColorSpace( /*texture*/ ) { + + return false; + + } + + getComponentTypeFromTexture( texture ) { + + const type = texture.type; + + if ( texture.isDataTexture ) { + + if ( type === IntType ) return 'int'; + if ( type === UnsignedIntType ) return 'uint'; + + } + + return 'float'; + + } + + getElementType( type ) { + + if ( type === 'mat2' ) return 'vec2'; + if ( type === 'mat3' ) return 'vec3'; + if ( type === 'mat4' ) return 'vec4'; + + return this.getComponentType( type ); + + } + + getComponentType( type ) { + + type = this.getVectorType( type ); + + if ( type === 'float' || type === 'bool' || type === 'int' || type === 'uint' ) return type; + + const componentType = /(b|i|u|)(vec|mat)([2-4])/.exec( type ); + + if ( componentType === null ) return null; + + if ( componentType[ 1 ] === 'b' ) return 'bool'; + if ( componentType[ 1 ] === 'i' ) return 'int'; + if ( componentType[ 1 ] === 'u' ) return 'uint'; + + return 'float'; + + } + + getVectorType( type ) { + + if ( type === 'color' ) return 'vec3'; + if ( type === 'texture' || type === 'cubeTexture' || type === 'storageTexture' || type === 'texture3D' ) return 'vec4'; + + return type; + + } + + getTypeFromLength( length, componentType = 'float' ) { + + if ( length === 1 ) return componentType; + + const baseType = typeFromLength.get( length ); + const prefix = componentType === 'float' ? '' : componentType[ 0 ]; + + return prefix + baseType; + + } + + getTypeFromArray( array ) { + + return typeFromArray.get( array.constructor ); + + } + + getTypeFromAttribute( attribute ) { + + let dataAttribute = attribute; + + if ( attribute.isInterleavedBufferAttribute ) dataAttribute = attribute.data; + + const array = dataAttribute.array; + const itemSize = attribute.itemSize; + const normalized = attribute.normalized; + + let arrayType; + + if ( ! ( attribute instanceof Float16BufferAttribute ) && normalized !== true ) { + + arrayType = this.getTypeFromArray( array ); + + } + + return this.getTypeFromLength( itemSize, arrayType ); + + } + + getTypeLength( type ) { + + const vecType = this.getVectorType( type ); + const vecNum = /vec([2-4])/.exec( vecType ); + + if ( vecNum !== null ) return Number( vecNum[ 1 ] ); + if ( vecType === 'float' || vecType === 'bool' || vecType === 'int' || vecType === 'uint' ) return 1; + if ( /mat2/.test( type ) === true ) return 4; + if ( /mat3/.test( type ) === true ) return 9; + if ( /mat4/.test( type ) === true ) return 16; + + return 0; + + } + + getVectorFromMatrix( type ) { + + return type.replace( 'mat', 'vec' ); + + } + + changeComponentType( type, newComponentType ) { + + return this.getTypeFromLength( this.getTypeLength( type ), newComponentType ); + + } + + getIntegerType( type ) { + + const componentType = this.getComponentType( type ); + + if ( componentType === 'int' || componentType === 'uint' ) return type; + + return this.changeComponentType( type, 'int' ); + + } + + addStack() { + + this.stack = stack( this.stack ); + + this.stacks.push( getCurrentStack() || this.stack ); + setCurrentStack( this.stack ); + + return this.stack; + + } + + removeStack() { + + const lastStack = this.stack; + this.stack = lastStack.parent; + + setCurrentStack( this.stacks.pop() ); + + return lastStack; + + } + + getDataFromNode( node, shaderStage = this.shaderStage, cache = null ) { + + cache = cache === null ? ( node.isGlobal( this ) ? this.globalCache : this.cache ) : cache; + + let nodeData = cache.getData( node ); + + if ( nodeData === undefined ) { + + nodeData = {}; + + cache.setData( node, nodeData ); + + } + + if ( nodeData[ shaderStage ] === undefined ) nodeData[ shaderStage ] = {}; + + return nodeData[ shaderStage ]; + + } + + getNodeProperties( node, shaderStage = 'any' ) { + + const nodeData = this.getDataFromNode( node, shaderStage ); + + return nodeData.properties || ( nodeData.properties = { outputNode: null } ); + + } + + getBufferAttributeFromNode( node, type ) { + + const nodeData = this.getDataFromNode( node ); + + let bufferAttribute = nodeData.bufferAttribute; + + if ( bufferAttribute === undefined ) { + + const index = this.uniforms.index ++; + + bufferAttribute = new NodeAttribute( 'nodeAttribute' + index, type, node ); + + this.bufferAttributes.push( bufferAttribute ); + + nodeData.bufferAttribute = bufferAttribute; + + } + + return bufferAttribute; + + } + + getStructTypeFromNode( node, shaderStage = this.shaderStage ) { + + const nodeData = this.getDataFromNode( node, shaderStage ); + + if ( nodeData.structType === undefined ) { + + const index = this.structs.index ++; + + node.name = `StructType${ index }`; + this.structs[ shaderStage ].push( node ); + + nodeData.structType = node; + + } + + return node; + + } + + getUniformFromNode( node, type, shaderStage = this.shaderStage, name = null ) { + + const nodeData = this.getDataFromNode( node, shaderStage, this.globalCache ); + + let nodeUniform = nodeData.uniform; + + if ( nodeUniform === undefined ) { + + const index = this.uniforms.index ++; + + nodeUniform = new NodeUniform( name || ( 'nodeUniform' + index ), type, node ); + + this.uniforms[ shaderStage ].push( nodeUniform ); + + nodeData.uniform = nodeUniform; + + } + + return nodeUniform; + + } + + getVarFromNode( node, name = null, type = node.getNodeType( this ), shaderStage = this.shaderStage ) { + + const nodeData = this.getDataFromNode( node, shaderStage ); + + let nodeVar = nodeData.variable; + + if ( nodeVar === undefined ) { + + const vars = this.vars[ shaderStage ] || ( this.vars[ shaderStage ] = [] ); + + if ( name === null ) name = 'nodeVar' + vars.length; + + nodeVar = new NodeVar( name, type ); + + vars.push( nodeVar ); + + nodeData.variable = nodeVar; + + } + + return nodeVar; + + } + + getVaryingFromNode( node, name = null, type = node.getNodeType( this ) ) { + + const nodeData = this.getDataFromNode( node, 'any' ); + + let nodeVarying = nodeData.varying; + + if ( nodeVarying === undefined ) { + + const varyings = this.varyings; + const index = varyings.length; + + if ( name === null ) name = 'nodeVarying' + index; + + nodeVarying = new NodeVarying( name, type ); + + varyings.push( nodeVarying ); + + nodeData.varying = nodeVarying; + + } + + return nodeVarying; + + } + + getCodeFromNode( node, type, shaderStage = this.shaderStage ) { + + const nodeData = this.getDataFromNode( node ); + + let nodeCode = nodeData.code; + + if ( nodeCode === undefined ) { + + const codes = this.codes[ shaderStage ] || ( this.codes[ shaderStage ] = [] ); + const index = codes.length; + + nodeCode = new NodeCode( 'nodeCode' + index, type ); + + codes.push( nodeCode ); + + nodeData.code = nodeCode; + + } + + return nodeCode; + + } + + addFlowCodeHierarchy( node, nodeBlock ) { + + const { flowCodes, flowCodeBlock } = this.getDataFromNode( node ); + + let needsFlowCode = true; + let nodeBlockHierarchy = nodeBlock; + + while ( nodeBlockHierarchy ) { + + if ( flowCodeBlock.get( nodeBlockHierarchy ) === true ) { + + needsFlowCode = false; + break; + + } + + nodeBlockHierarchy = this.getDataFromNode( nodeBlockHierarchy ).parentNodeBlock; + + } + + if ( needsFlowCode ) { + + for ( const flowCode of flowCodes ) { + + this.addLineFlowCode( flowCode ); + + } + + } + + } + + addLineFlowCodeBlock( node, code, nodeBlock ) { + + const nodeData = this.getDataFromNode( node ); + const flowCodes = nodeData.flowCodes || ( nodeData.flowCodes = [] ); + const codeBlock = nodeData.flowCodeBlock || ( nodeData.flowCodeBlock = new WeakMap() ); + + flowCodes.push( code ); + codeBlock.set( nodeBlock, true ); + + } + + addLineFlowCode( code, node = null ) { + + if ( code === '' ) return this; + + if ( node !== null && this.context.nodeBlock ) { + + this.addLineFlowCodeBlock( node, code, this.context.nodeBlock ); + + } + + code = this.tab + code; + + if ( ! /;\s*$/.test( code ) ) { + + code = code + ';\n'; + + } + + this.flow.code += code; + + return this; + + } + + addFlowCode( code ) { + + this.flow.code += code; + + return this; + + } + + addFlowTab() { + + this.tab += '\t'; + + return this; + + } + + removeFlowTab() { + + this.tab = this.tab.slice( 0, - 1 ); + + return this; + + } + + getFlowData( node/*, shaderStage*/ ) { + + return this.flowsData.get( node ); + + } + + flowNode( node ) { + + const output = node.getNodeType( this ); + + const flowData = this.flowChildNode( node, output ); + + this.flowsData.set( node, flowData ); + + return flowData; + + } + + buildFunctionNode( shaderNode ) { + + const fn = new FunctionNode(); + + const previous = this.currentFunctionNode; + + this.currentFunctionNode = fn; + + fn.code = this.buildFunctionCode( shaderNode ); + + this.currentFunctionNode = previous; + + return fn; + + } + + flowShaderNode( shaderNode ) { + + const layout = shaderNode.layout; + + const inputs = { + [ Symbol.iterator ]() { + + let index = 0; + const values = Object.values( this ); + return { + next: () => ( { + value: values[ index ], + done: index ++ >= values.length + } ) + }; + + } + }; + + for ( const input of layout.inputs ) { + + inputs[ input.name ] = new ParameterNode( input.type, input.name ); + + } + + // + + shaderNode.layout = null; + + const callNode = shaderNode.call( inputs ); + const flowData = this.flowStagesNode( callNode, layout.type ); + + shaderNode.layout = layout; + + return flowData; + + } + + flowStagesNode( node, output = null ) { + + const previousFlow = this.flow; + const previousVars = this.vars; + const previousCache = this.cache; + const previousBuildStage = this.buildStage; + const previousStack = this.stack; + + const flow = { + code: '' + }; + + this.flow = flow; + this.vars = {}; + this.cache = new NodeCache(); + this.stack = stack(); + + for ( const buildStage of defaultBuildStages ) { + + this.setBuildStage( buildStage ); + + flow.result = node.build( this, output ); + + } + + flow.vars = this.getVars( this.shaderStage ); + + this.flow = previousFlow; + this.vars = previousVars; + this.cache = previousCache; + this.stack = previousStack; + + this.setBuildStage( previousBuildStage ); + + return flow; + + } + + getFunctionOperator() { + + return null; + + } + + flowChildNode( node, output = null ) { + + const previousFlow = this.flow; + + const flow = { + code: '' + }; + + this.flow = flow; + + flow.result = node.build( this, output ); + + this.flow = previousFlow; + + return flow; + + } + + flowNodeFromShaderStage( shaderStage, node, output = null, propertyName = null ) { + + const previousShaderStage = this.shaderStage; + + this.setShaderStage( shaderStage ); + + const flowData = this.flowChildNode( node, output ); + + if ( propertyName !== null ) { + + flowData.code += `${ this.tab + propertyName } = ${ flowData.result };\n`; + + } + + this.flowCode[ shaderStage ] = this.flowCode[ shaderStage ] + flowData.code; + + this.setShaderStage( previousShaderStage ); + + return flowData; + + } + + getAttributesArray() { + + return this.attributes.concat( this.bufferAttributes ); + + } + + getAttributes( /*shaderStage*/ ) { + + console.warn( 'Abstract function.' ); + + } + + getVaryings( /*shaderStage*/ ) { + + console.warn( 'Abstract function.' ); + + } + + getVar( type, name ) { + + return `${ this.getType( type ) } ${ name }`; + + } + + getVars( shaderStage ) { + + let snippet = ''; + + const vars = this.vars[ shaderStage ]; + + if ( vars !== undefined ) { + + for ( const variable of vars ) { + + snippet += `${ this.getVar( variable.type, variable.name ) }; `; + + } + + } + + return snippet; + + } + + getUniforms( /*shaderStage*/ ) { + + console.warn( 'Abstract function.' ); + + } + + getCodes( shaderStage ) { + + const codes = this.codes[ shaderStage ]; + + let code = ''; + + if ( codes !== undefined ) { + + for ( const nodeCode of codes ) { + + code += nodeCode.code + '\n'; + + } + + } + + return code; + + } + + getHash() { + + return this.vertexShader + this.fragmentShader + this.computeShader; + + } + + setShaderStage( shaderStage ) { + + this.shaderStage = shaderStage; + + } + + getShaderStage() { + + return this.shaderStage; + + } + + setBuildStage( buildStage ) { + + this.buildStage = buildStage; + + } + + getBuildStage() { + + return this.buildStage; + + } + + buildCode() { + + console.warn( 'Abstract function.' ); + + } + + build() { + + const { object, material, renderer } = this; + + if ( material !== null ) { + + let nodeMaterial = renderer.nodes.library.fromMaterial( material ); + + if ( nodeMaterial === null ) { + + console.error( `NodeMaterial: Material "${ material.type }" is not compatible.` ); + + nodeMaterial = new NodeMaterial(); + + } + + nodeMaterial.build( this ); + + } else { + + this.addFlow( 'compute', object ); + + } + + // setup() -> stage 1: create possible new nodes and returns an output reference node + // analyze() -> stage 2: analyze nodes to possible optimization and validation + // generate() -> stage 3: generate shader + + for ( const buildStage of defaultBuildStages ) { + + this.setBuildStage( buildStage ); + + if ( this.context.vertex && this.context.vertex.isNode ) { + + this.flowNodeFromShaderStage( 'vertex', this.context.vertex ); + + } + + for ( const shaderStage of shaderStages ) { + + this.setShaderStage( shaderStage ); + + const flowNodes = this.flowNodes[ shaderStage ]; + + for ( const node of flowNodes ) { + + if ( buildStage === 'generate' ) { + + this.flowNode( node ); + + } else { + + node.build( this ); + + } + + } + + } + + } + + this.setBuildStage( null ); + this.setShaderStage( null ); + + // stage 4: build code for a specific output + + this.buildCode(); + this.buildUpdateNodes(); + + return this; + + } + + getNodeUniform( uniformNode, type ) { + + if ( type === 'float' || type === 'int' || type === 'uint' ) return new NumberNodeUniform( uniformNode ); + if ( type === 'vec2' || type === 'ivec2' || type === 'uvec2' ) return new Vector2NodeUniform( uniformNode ); + if ( type === 'vec3' || type === 'ivec3' || type === 'uvec3' ) return new Vector3NodeUniform( uniformNode ); + if ( type === 'vec4' || type === 'ivec4' || type === 'uvec4' ) return new Vector4NodeUniform( uniformNode ); + if ( type === 'color' ) return new ColorNodeUniform( uniformNode ); + if ( type === 'mat3' ) return new Matrix3NodeUniform( uniformNode ); + if ( type === 'mat4' ) return new Matrix4NodeUniform( uniformNode ); + + throw new Error( `Uniform "${type}" not declared.` ); + + } + + createNodeMaterial( type = 'NodeMaterial' ) { // @deprecated, r168 + + throw new Error( `THREE.NodeBuilder: createNodeMaterial() was deprecated. Use new ${ type }() instead.` ); + + } + + format( snippet, fromType, toType ) { + + fromType = this.getVectorType( fromType ); + toType = this.getVectorType( toType ); + + if ( fromType === toType || toType === null || this.isReference( toType ) ) { + + return snippet; + + } + + const fromTypeLength = this.getTypeLength( fromType ); + const toTypeLength = this.getTypeLength( toType ); + + if ( fromTypeLength === 16 && toTypeLength === 9 ) { + + return `${ this.getType( toType ) }(${ snippet }[0].xyz, ${ snippet }[1].xyz, ${ snippet }[2].xyz)`; + + } + + if ( fromTypeLength === 9 && toTypeLength === 4 ) { + + return `${ this.getType( toType ) }(${ snippet }[0].xy, ${ snippet }[1].xy)`; + + } + + + if ( fromTypeLength > 4 ) { // fromType is matrix-like + + // @TODO: ignore for now + + return snippet; + + } + + if ( toTypeLength > 4 || toTypeLength === 0 ) { // toType is matrix-like or unknown + + // @TODO: ignore for now + + return snippet; + + } + + if ( fromTypeLength === toTypeLength ) { + + return `${ this.getType( toType ) }( ${ snippet } )`; + + } + + if ( fromTypeLength > toTypeLength ) { + + return this.format( `${ snippet }.${ 'xyz'.slice( 0, toTypeLength ) }`, this.getTypeFromLength( toTypeLength, this.getComponentType( fromType ) ), toType ); + + } + + if ( toTypeLength === 4 && fromTypeLength > 1 ) { // toType is vec4-like + + return `${ this.getType( toType ) }( ${ this.format( snippet, fromType, 'vec3' ) }, 1.0 )`; + + } + + if ( fromTypeLength === 2 ) { // fromType is vec2-like and toType is vec3-like + + return `${ this.getType( toType ) }( ${ this.format( snippet, fromType, 'vec2' ) }, 0.0 )`; + + } + + if ( fromTypeLength === 1 && toTypeLength > 1 && fromType !== this.getComponentType( toType ) ) { // fromType is float-like + + // convert a number value to vector type, e.g: + // vec3( 1u ) -> vec3( float( 1u ) ) + + snippet = `${ this.getType( this.getComponentType( toType ) ) }( ${ snippet } )`; + + } + + return `${ this.getType( toType ) }( ${ snippet } )`; // fromType is float-like + + } + + getSignature() { + + return `// Three.js r${ REVISION } - Node System\n`; + + } + +} + +class NodeFrame { + + constructor() { + + this.time = 0; + this.deltaTime = 0; + + this.frameId = 0; + this.renderId = 0; + + this.startTime = null; + + this.updateMap = new WeakMap(); + this.updateBeforeMap = new WeakMap(); + this.updateAfterMap = new WeakMap(); + + this.renderer = null; + this.material = null; + this.camera = null; + this.object = null; + this.scene = null; + + } + + _getMaps( referenceMap, nodeRef ) { + + let maps = referenceMap.get( nodeRef ); + + if ( maps === undefined ) { + + maps = { + renderMap: new WeakMap(), + frameMap: new WeakMap() + }; + + referenceMap.set( nodeRef, maps ); + + } + + return maps; + + } + + updateBeforeNode( node ) { + + const updateType = node.getUpdateBeforeType(); + const reference = node.updateReference( this ); + + if ( updateType === NodeUpdateType.FRAME ) { + + const { frameMap } = this._getMaps( this.updateBeforeMap, reference ); + + if ( frameMap.get( reference ) !== this.frameId ) { + + if ( node.updateBefore( this ) !== false ) { + + frameMap.set( reference, this.frameId ); + + } + + } + + } else if ( updateType === NodeUpdateType.RENDER ) { + + const { renderMap } = this._getMaps( this.updateBeforeMap, reference ); + + if ( renderMap.get( reference ) !== this.renderId ) { + + if ( node.updateBefore( this ) !== false ) { + + renderMap.set( reference, this.renderId ); + + } + + } + + } else if ( updateType === NodeUpdateType.OBJECT ) { + + node.updateBefore( this ); + + } + + } + + updateAfterNode( node ) { + + const updateType = node.getUpdateAfterType(); + const reference = node.updateReference( this ); + + if ( updateType === NodeUpdateType.FRAME ) { + + const { frameMap } = this._getMaps( this.updateAfterMap, reference ); + + if ( frameMap.get( reference ) !== this.frameId ) { + + if ( node.updateAfter( this ) !== false ) { + + frameMap.set( reference, this.frameId ); + + } + + } + + } else if ( updateType === NodeUpdateType.RENDER ) { + + const { renderMap } = this._getMaps( this.updateAfterMap, reference ); + + if ( renderMap.get( reference ) !== this.renderId ) { + + if ( node.updateAfter( this ) !== false ) { + + renderMap.set( reference, this.renderId ); + + } + + } + + } else if ( updateType === NodeUpdateType.OBJECT ) { + + node.updateAfter( this ); + + } + + } + + updateNode( node ) { + + const updateType = node.getUpdateType(); + const reference = node.updateReference( this ); + + if ( updateType === NodeUpdateType.FRAME ) { + + const { frameMap } = this._getMaps( this.updateMap, reference ); + + if ( frameMap.get( reference ) !== this.frameId ) { + + if ( node.update( this ) !== false ) { + + frameMap.set( reference, this.frameId ); + + } + + } + + } else if ( updateType === NodeUpdateType.RENDER ) { + + const { renderMap } = this._getMaps( this.updateMap, reference ); + + if ( renderMap.get( reference ) !== this.renderId ) { + + if ( node.update( this ) !== false ) { + + renderMap.set( reference, this.renderId ); + + } + + } + + } else if ( updateType === NodeUpdateType.OBJECT ) { + + node.update( this ); + + } + + } + + update() { + + this.frameId ++; + + if ( this.lastTime === undefined ) this.lastTime = performance.now(); + + this.deltaTime = ( performance.now() - this.lastTime ) / 1000; + + this.lastTime = performance.now(); + + this.time += this.deltaTime; + + } + +} + +class NodeFunctionInput { + + constructor( type, name, count = null, qualifier = '', isConst = false ) { + + this.type = type; + this.name = name; + this.count = count; + this.qualifier = qualifier; + this.isConst = isConst; + + } + +} + +NodeFunctionInput.isNodeFunctionInput = true; + +class StructTypeNode extends Node { + + static get type() { + + return 'StructTypeNode'; + + } + + constructor( types ) { + + super(); + + this.types = types; + this.isStructTypeNode = true; + + } + + getMemberTypes() { + + return this.types; + + } + +} + +class OutputStructNode extends Node { + + static get type() { + + return 'OutputStructNode'; + + } + + constructor( ...members ) { + + super(); + + this.members = members; + + this.isOutputStructNode = true; + + } + + setup( builder ) { + + super.setup( builder ); + + const members = this.members; + const types = []; + + for ( let i = 0; i < members.length; i ++ ) { + + types.push( members[ i ].getNodeType( builder ) ); + + } + + this.nodeType = builder.getStructTypeFromNode( new StructTypeNode( types ) ).name; + + } + + generate( builder, output ) { + + const propertyName = builder.getOutputStructName(); + const members = this.members; + + const structPrefix = propertyName !== '' ? propertyName + '.' : ''; + + for ( let i = 0; i < members.length; i ++ ) { + + const snippet = members[ i ].build( builder, output ); + + builder.addLineFlowCode( `${ structPrefix }m${ i } = ${ snippet }`, this ); + + } + + return propertyName; + + } + +} + +const outputStruct = /*@__PURE__*/ nodeProxy( OutputStructNode ); + +function getTextureIndex( textures, name ) { + + for ( let i = 0; i < textures.length; i ++ ) { + + if ( textures[ i ].name === name ) { + + return i; + + } + + } + + return - 1; + +} + +class MRTNode extends OutputStructNode { + + static get type() { + + return 'MRTNode'; + + } + + constructor( outputNodes ) { + + super(); + + this.outputNodes = outputNodes; + + this.isMRTNode = true; + + } + + has( name ) { + + return this.outputNodes[ name ] !== undefined; + + } + + get( name ) { + + return this.outputNodes[ name ]; + + } + + merge( mrtNode ) { + + const outputs = { ...this.outputNodes, ...mrtNode.outputNodes }; + + return mrt( outputs ); + + } + + setup( builder ) { + + const outputNodes = this.outputNodes; + const mrt = builder.renderer.getRenderTarget(); + + const members = []; + + const textures = mrt.textures; + + for ( const name in outputNodes ) { + + const index = getTextureIndex( textures, name ); + + members[ index ] = vec4( outputNodes[ name ] ); + + } + + this.members = members; + + return super.setup( builder ); + + } + +} + +const mrt = /*@__PURE__*/ nodeProxy( MRTNode ); + +class FunctionOverloadingNode extends Node { + + static get type() { + + return 'FunctionOverloadingNode'; + + } + + constructor( functionNodes = [], ...parametersNodes ) { + + super(); + + this.functionNodes = functionNodes; + this.parametersNodes = parametersNodes; + + this._candidateFnCall = null; + + this.global = true; + + } + + getNodeType() { + + return this.functionNodes[ 0 ].shaderNode.layout.type; + + } + + setup( builder ) { + + const params = this.parametersNodes; + + let candidateFnCall = this._candidateFnCall; + + if ( candidateFnCall === null ) { + + let candidateFn = null; + let candidateScore = - 1; + + for ( const functionNode of this.functionNodes ) { + + const shaderNode = functionNode.shaderNode; + const layout = shaderNode.layout; + + if ( layout === null ) { + + throw new Error( 'FunctionOverloadingNode: FunctionNode must be a layout.' ); + + } + + const inputs = layout.inputs; + + if ( params.length === inputs.length ) { + + let score = 0; + + for ( let i = 0; i < params.length; i ++ ) { + + const param = params[ i ]; + const input = inputs[ i ]; + + if ( param.getNodeType( builder ) === input.type ) { + + score ++; + + } else { + + score = 0; + + } + + } + + if ( score > candidateScore ) { + + candidateFn = functionNode; + candidateScore = score; + + } + + } + + } + + this._candidateFnCall = candidateFnCall = candidateFn( ...params ); + + } + + return candidateFnCall; + + } + +} + +const overloadingBaseFn = /*@__PURE__*/ nodeProxy( FunctionOverloadingNode ); + +const overloadingFn = ( functionNodes ) => ( ...params ) => overloadingBaseFn( functionNodes, ...params ); + +class TimerNode extends UniformNode { + + static get type() { + + return 'TimerNode'; + + } + + constructor( scope = TimerNode.LOCAL, scale = 1, value = 0 ) { + + super( value ); + + this.scope = scope; + this.scale = scale; + + this.updateType = NodeUpdateType.FRAME; + + } + /* + @TODO: + getNodeType( builder ) { + + const scope = this.scope; + + if ( scope === TimerNode.FRAME ) { + + return 'uint'; + + } + + return 'float'; + + } +*/ + update( frame ) { + + const scope = this.scope; + const scale = this.scale; + + if ( scope === TimerNode.LOCAL ) { + + this.value += frame.deltaTime * scale; + + } else if ( scope === TimerNode.DELTA ) { + + this.value = frame.deltaTime * scale; + + } else if ( scope === TimerNode.FRAME ) { + + this.value = frame.frameId; + + } else { + + // global + + this.value = frame.time * scale; + + } + + } + + serialize( data ) { + + super.serialize( data ); + + data.scope = this.scope; + data.scale = this.scale; + + } + + deserialize( data ) { + + super.deserialize( data ); + + this.scope = data.scope; + this.scale = data.scale; + + } + +} + +TimerNode.LOCAL = 'local'; +TimerNode.GLOBAL = 'global'; +TimerNode.DELTA = 'delta'; +TimerNode.FRAME = 'frame'; + +// @TODO: add support to use node in timeScale +const timerLocal = ( timeScale, value = 0 ) => nodeObject( new TimerNode( TimerNode.LOCAL, timeScale, value ) ); +const timerGlobal = ( timeScale, value = 0 ) => nodeObject( new TimerNode( TimerNode.GLOBAL, timeScale, value ) ); +const timerDelta = ( timeScale, value = 0 ) => nodeObject( new TimerNode( TimerNode.DELTA, timeScale, value ) ); +const frameId = /*@__PURE__*/ nodeImmutable( TimerNode, TimerNode.FRAME ).toUint(); + +class OscNode extends Node { + + static get type() { + + return 'OscNode'; + + } + + constructor( method = OscNode.SINE, timeNode = timerLocal() ) { + + super(); + + this.method = method; + this.timeNode = timeNode; + + } + + getNodeType( builder ) { + + return this.timeNode.getNodeType( builder ); + + } + + setup() { + + const method = this.method; + const timeNode = nodeObject( this.timeNode ); + + let outputNode = null; + + if ( method === OscNode.SINE ) { + + outputNode = timeNode.add( 0.75 ).mul( Math.PI * 2 ).sin().mul( 0.5 ).add( 0.5 ); + + } else if ( method === OscNode.SQUARE ) { + + outputNode = timeNode.fract().round(); + + } else if ( method === OscNode.TRIANGLE ) { + + outputNode = timeNode.add( 0.5 ).fract().mul( 2 ).sub( 1 ).abs(); + + } else if ( method === OscNode.SAWTOOTH ) { + + outputNode = timeNode.fract(); + + } + + return outputNode; + + } + + serialize( data ) { + + super.serialize( data ); + + data.method = this.method; + + } + + deserialize( data ) { + + super.deserialize( data ); + + this.method = data.method; + + } + +} + +OscNode.SINE = 'sine'; +OscNode.SQUARE = 'square'; +OscNode.TRIANGLE = 'triangle'; +OscNode.SAWTOOTH = 'sawtooth'; + +const oscSine = /*@__PURE__*/ nodeProxy( OscNode, OscNode.SINE ); +const oscSquare = /*@__PURE__*/ nodeProxy( OscNode, OscNode.SQUARE ); +const oscTriangle = /*@__PURE__*/ nodeProxy( OscNode, OscNode.TRIANGLE ); +const oscSawtooth = /*@__PURE__*/ nodeProxy( OscNode, OscNode.SAWTOOTH ); + +class SpriteSheetUVNode extends Node { + + static get type() { + + return 'SpriteSheetUVNode'; + + } + + constructor( countNode, uvNode = uv(), frameNode = float( 0 ) ) { + + super( 'vec2' ); + + this.countNode = countNode; + this.uvNode = uvNode; + this.frameNode = frameNode; + + } + + setup() { + + const { frameNode, uvNode, countNode } = this; + + const { width, height } = countNode; + + const frameNum = frameNode.mod( width.mul( height ) ).floor(); + + const column = frameNum.mod( width ); + const row = height.sub( frameNum.add( 1 ).div( width ).ceil() ); + + const scale = countNode.reciprocal(); + const uvFrameOffset = vec2( column, row ); + + return uvNode.add( uvFrameOffset ).mul( scale ); + + } + +} + +const spritesheetUV = /*@__PURE__*/ nodeProxy( SpriteSheetUVNode ); + +class StorageArrayElementNode extends ArrayElementNode { + + static get type() { + + return 'StorageArrayElementNode'; + + } + + constructor( storageBufferNode, indexNode ) { + + super( storageBufferNode, indexNode ); + + this.isStorageArrayElementNode = true; + + } + + set storageBufferNode( value ) { + + this.node = value; + + } + + get storageBufferNode() { + + return this.node; + + } + + setup( builder ) { + + if ( builder.isAvailable( 'storageBuffer' ) === false ) { + + if ( this.node.bufferObject === true ) { + + builder.setupPBO( this.node ); + + } + + } + + return super.setup( builder ); + + } + + generate( builder, output ) { + + let snippet; + + const isAssignContext = builder.context.assign; + + // + + if ( builder.isAvailable( 'storageBuffer' ) === false ) { + + if ( this.node.bufferObject === true && isAssignContext !== true ) { + + snippet = builder.generatePBO( this ); + + } else { + + snippet = this.node.build( builder ); + + } + + } else { + + snippet = super.generate( builder ); + + } + + if ( isAssignContext !== true ) { + + const type = this.getNodeType( builder ); + + snippet = builder.format( snippet, type, output ); + + } + + return snippet; + + } + +} + +const storageElement = /*@__PURE__*/ nodeProxy( StorageArrayElementNode ); + +class TriplanarTexturesNode extends Node { + + static get type() { + + return 'TriplanarTexturesNode'; + + } + + constructor( textureXNode, textureYNode = null, textureZNode = null, scaleNode = float( 1 ), positionNode = positionLocal, normalNode = normalLocal ) { + + super( 'vec4' ); + + this.textureXNode = textureXNode; + this.textureYNode = textureYNode; + this.textureZNode = textureZNode; + + this.scaleNode = scaleNode; + + this.positionNode = positionNode; + this.normalNode = normalNode; + + } + + setup() { + + const { textureXNode, textureYNode, textureZNode, scaleNode, positionNode, normalNode } = this; + + // Ref: https://github.com/keijiro/StandardTriplanar + + // Blending factor of triplanar mapping + let bf = normalNode.abs().normalize(); + bf = bf.div( bf.dot( vec3( 1.0 ) ) ); + + // Triplanar mapping + const tx = positionNode.yz.mul( scaleNode ); + const ty = positionNode.zx.mul( scaleNode ); + const tz = positionNode.xy.mul( scaleNode ); + + // Base color + const textureX = textureXNode.value; + const textureY = textureYNode !== null ? textureYNode.value : textureX; + const textureZ = textureZNode !== null ? textureZNode.value : textureX; + + const cx = texture( textureX, tx ).mul( bf.x ); + const cy = texture( textureY, ty ).mul( bf.y ); + const cz = texture( textureZ, tz ).mul( bf.z ); + + return add( cx, cy, cz ); + + } + +} + +const triplanarTextures = /*@__PURE__*/ nodeProxy( TriplanarTexturesNode ); +const triplanarTexture = ( ...params ) => triplanarTextures( ...params ); + +const _reflectorPlane = new Plane(); +const _normal = new Vector3(); +const _reflectorWorldPosition = new Vector3(); +const _cameraWorldPosition = new Vector3(); +const _rotationMatrix = new Matrix4(); +const _lookAtPosition = new Vector3( 0, 0, - 1 ); +const clipPlane = new Vector4(); + +const _view = new Vector3(); +const _target = new Vector3(); +const _q = new Vector4(); + +const _size$9 = new Vector2(); + +const _defaultRT = new RenderTarget(); +const _defaultUV = screenUV.flipX(); + +let _inReflector = false; + +class ReflectorNode extends TextureNode { + + static get type() { + + return 'ReflectorNode'; + + } + + constructor( parameters = {} ) { + + super( _defaultRT.texture, _defaultUV ); + + const { + target = new Object3D(), + resolution = 1, + generateMipmaps = false, + bounces = true + } = parameters; + + // + + this.target = target; + this.resolution = resolution; + this.generateMipmaps = generateMipmaps; + this.bounces = bounces; + + this.updateBeforeType = bounces ? NodeUpdateType.RENDER : NodeUpdateType.FRAME; + + this.virtualCameras = new WeakMap(); + this.renderTargets = new WeakMap(); + + + } + + _updateResolution( renderTarget, renderer ) { + + const resolution = this.resolution; + + renderer.getDrawingBufferSize( _size$9 ); + + renderTarget.setSize( Math.round( _size$9.width * resolution ), Math.round( _size$9.height * resolution ) ); + + } + + setup( builder ) { + + this._updateResolution( _defaultRT, builder.renderer ); + + return super.setup( builder ); + + } + + getTextureNode() { + + return this.textureNode; + + } + + getVirtualCamera( camera ) { + + let virtualCamera = this.virtualCameras.get( camera ); + + if ( virtualCamera === undefined ) { + + virtualCamera = camera.clone(); + + this.virtualCameras.set( camera, virtualCamera ); + + } + + return virtualCamera; + + } + + getRenderTarget( camera ) { + + let renderTarget = this.renderTargets.get( camera ); + + if ( renderTarget === undefined ) { + + renderTarget = new RenderTarget( 0, 0, { type: HalfFloatType } ); + + if ( this.generateMipmaps === true ) { + + renderTarget.texture.minFilter = LinearMipMapLinearFilter; + renderTarget.texture.generateMipmaps = true; + + } + + this.renderTargets.set( camera, renderTarget ); + + } + + return renderTarget; + + } + + updateBefore( frame ) { + + if ( this.bounces === false && _inReflector ) return false; + + _inReflector = true; + + const { scene, camera, renderer, material } = frame; + const { target } = this; + + const virtualCamera = this.getVirtualCamera( camera ); + const renderTarget = this.getRenderTarget( virtualCamera ); + + renderer.getDrawingBufferSize( _size$9 ); + + this._updateResolution( renderTarget, renderer ); + + // + + _reflectorWorldPosition.setFromMatrixPosition( target.matrixWorld ); + _cameraWorldPosition.setFromMatrixPosition( camera.matrixWorld ); + + _rotationMatrix.extractRotation( target.matrixWorld ); + + _normal.set( 0, 0, 1 ); + _normal.applyMatrix4( _rotationMatrix ); + + _view.subVectors( _reflectorWorldPosition, _cameraWorldPosition ); + + // Avoid rendering when reflector is facing away + + if ( _view.dot( _normal ) > 0 ) return; + + _view.reflect( _normal ).negate(); + _view.add( _reflectorWorldPosition ); + + _rotationMatrix.extractRotation( camera.matrixWorld ); + + _lookAtPosition.set( 0, 0, - 1 ); + _lookAtPosition.applyMatrix4( _rotationMatrix ); + _lookAtPosition.add( _cameraWorldPosition ); + + _target.subVectors( _reflectorWorldPosition, _lookAtPosition ); + _target.reflect( _normal ).negate(); + _target.add( _reflectorWorldPosition ); + + // + + virtualCamera.coordinateSystem = camera.coordinateSystem; + virtualCamera.position.copy( _view ); + virtualCamera.up.set( 0, 1, 0 ); + virtualCamera.up.applyMatrix4( _rotationMatrix ); + virtualCamera.up.reflect( _normal ); + virtualCamera.lookAt( _target ); + + virtualCamera.near = camera.near; + virtualCamera.far = camera.far; + + virtualCamera.updateMatrixWorld(); + virtualCamera.projectionMatrix.copy( camera.projectionMatrix ); + + // Now update projection matrix with new clip plane, implementing code from: http://www.terathon.com/code/oblique.html + // Paper explaining this technique: http://www.terathon.com/lengyel/Lengyel-Oblique.pdf + _reflectorPlane.setFromNormalAndCoplanarPoint( _normal, _reflectorWorldPosition ); + _reflectorPlane.applyMatrix4( virtualCamera.matrixWorldInverse ); + + clipPlane.set( _reflectorPlane.normal.x, _reflectorPlane.normal.y, _reflectorPlane.normal.z, _reflectorPlane.constant ); + + const projectionMatrix = virtualCamera.projectionMatrix; + + _q.x = ( Math.sign( clipPlane.x ) + projectionMatrix.elements[ 8 ] ) / projectionMatrix.elements[ 0 ]; + _q.y = ( Math.sign( clipPlane.y ) + projectionMatrix.elements[ 9 ] ) / projectionMatrix.elements[ 5 ]; + _q.z = - 1.0; + _q.w = ( 1.0 + projectionMatrix.elements[ 10 ] ) / projectionMatrix.elements[ 14 ]; + + // Calculate the scaled plane vector + clipPlane.multiplyScalar( 1.0 / clipPlane.dot( _q ) ); + + const clipBias = 0; + + // Replacing the third row of the projection matrix + projectionMatrix.elements[ 2 ] = clipPlane.x; + projectionMatrix.elements[ 6 ] = clipPlane.y; + projectionMatrix.elements[ 10 ] = clipPlane.z - clipBias; + projectionMatrix.elements[ 14 ] = clipPlane.w; + + // + + this.value = renderTarget.texture; + + material.visible = false; + + const currentRenderTarget = renderer.getRenderTarget(); + const currentMRT = renderer.getMRT(); + + renderer.setMRT( null ); + renderer.setRenderTarget( renderTarget ); + + renderer.render( scene, virtualCamera ); + + renderer.setMRT( currentMRT ); + renderer.setRenderTarget( currentRenderTarget ); + + material.visible = true; + + _inReflector = false; + + } + +} + +const reflector = ( parameters ) => nodeObject( new ReflectorNode( parameters ) ); + +// Helper for passes that need to fill the viewport with a single quad. + +const _camera = /*@__PURE__*/ new OrthographicCamera( - 1, 1, 1, - 1, 0, 1 ); + +// https://github.com/mrdoob/three.js/pull/21358 + +class QuadGeometry extends BufferGeometry { + + constructor( flipY = false ) { + + super(); + + const uv = flipY === false ? [ 0, - 1, 0, 1, 2, 1 ] : [ 0, 2, 0, 0, 2, 0 ]; + + this.setAttribute( 'position', new Float32BufferAttribute( [ - 1, 3, 0, - 1, - 1, 0, 3, - 1, 0 ], 3 ) ); + this.setAttribute( 'uv', new Float32BufferAttribute( uv, 2 ) ); + + } + +} + +const _geometry = /*@__PURE__*/ new QuadGeometry(); + +class QuadMesh extends Mesh { + + constructor( material = null ) { + + super( _geometry, material ); + + this.camera = _camera; + + this.isQuadMesh = true; + + } + + renderAsync( renderer ) { + + return renderer.renderAsync( this, _camera ); + + } + + render( renderer ) { + + renderer.render( this, _camera ); + + } + +} + +const _size$8 = /*@__PURE__*/ new Vector2(); + +class RTTNode extends TextureNode { + + static get type() { + + return 'RTTNode'; + + } + + constructor( node, width = null, height = null, options = { type: HalfFloatType } ) { + + const renderTarget = new RenderTarget( width, height, options ); + + super( renderTarget.texture, uv() ); + + this.node = node; + this.width = width; + this.height = height; + + this.renderTarget = renderTarget; + + this.textureNeedsUpdate = true; + this.autoUpdate = true; + + this.updateMap = new WeakMap(); + + this._rttNode = null; + this._quadMesh = new QuadMesh( new NodeMaterial() ); + + this.updateBeforeType = NodeUpdateType.RENDER; + + } + + get autoSize() { + + return this.width === null; + + } + + setup( builder ) { + + this._rttNode = this.node.context( builder.getSharedContext() ); + this._quadMesh.material.name = 'RTT'; + this._quadMesh.material.needsUpdate = true; + + return super.setup( builder ); + + } + + setSize( width, height ) { + + this.width = width; + this.height = height; + + const effectiveWidth = width * this.pixelRatio; + const effectiveHeight = height * this.pixelRatio; + + this.renderTarget.setSize( effectiveWidth, effectiveHeight ); + + this.textureNeedsUpdate = true; + + } + + setPixelRatio( pixelRatio ) { + + this.pixelRatio = pixelRatio; + + this.setSize( this.width, this.height ); + + } + + updateBefore( { renderer } ) { + + if ( this.textureNeedsUpdate === false && this.autoUpdate === false ) return; + + this.textureNeedsUpdate = false; + + // + + if ( this.autoSize === true ) { + + this.pixelRatio = renderer.getPixelRatio(); + + const size = renderer.getSize( _size$8 ); + + this.setSize( size.width, size.height ); + + } + + // + + this._quadMesh.material.fragmentNode = this._rttNode; + + // + + const currentRenderTarget = renderer.getRenderTarget(); + + renderer.setRenderTarget( this.renderTarget ); + + this._quadMesh.render( renderer ); + + renderer.setRenderTarget( currentRenderTarget ); + + } + + clone() { + + const newNode = new TextureNode( this.value, this.uvNode, this.levelNode ); + newNode.sampler = this.sampler; + newNode.referenceNode = this; + + return newNode; + + } + +} + +const rtt = ( node, ...params ) => nodeObject( new RTTNode( nodeObject( node ), ...params ) ); +const convertToTexture = ( node, ...params ) => node.isTextureNode ? node : rtt( node, ...params ); + +class VertexColorNode extends AttributeNode { + + static get type() { + + return 'VertexColorNode'; + + } + + constructor( index = 0 ) { + + super( null, 'vec4' ); + + this.isVertexColorNode = true; + + this.index = index; + + } + + getAttributeName( /*builder*/ ) { + + const index = this.index; + + return 'color' + ( index > 0 ? index : '' ); + + } + + generate( builder ) { + + const attributeName = this.getAttributeName( builder ); + const geometryAttribute = builder.hasGeometryAttribute( attributeName ); + + let result; + + if ( geometryAttribute === true ) { + + result = super.generate( builder ); + + } else { + + // Vertex color fallback should be white + result = builder.generateConst( this.nodeType, new Vector4( 1, 1, 1, 1 ) ); + + } + + return result; + + } + + serialize( data ) { + + super.serialize( data ); + + data.index = this.index; + + } + + deserialize( data ) { + + super.deserialize( data ); + + this.index = data.index; + + } + +} + +const vertexColor = ( ...params ) => nodeObject( new VertexColorNode( ...params ) ); + +class PointUVNode extends Node { + + static get type() { + + return 'PointUVNode'; + + } + + constructor() { + + super( 'vec2' ); + + this.isPointUVNode = true; + + } + + generate( /*builder*/ ) { + + return 'vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y )'; + + } + +} + +const pointUV = /*@__PURE__*/ nodeImmutable( PointUVNode ); + +class SceneNode extends Node { + + static get type() { + + return 'SceneNode'; + + } + + constructor( scope = SceneNode.BACKGROUND_BLURRINESS, scene = null ) { + + super(); + + this.scope = scope; + this.scene = scene; + + } + + setup( builder ) { + + const scope = this.scope; + const scene = this.scene !== null ? this.scene : builder.scene; + + let output; + + if ( scope === SceneNode.BACKGROUND_BLURRINESS ) { + + output = reference( 'backgroundBlurriness', 'float', scene ); + + } else if ( scope === SceneNode.BACKGROUND_INTENSITY ) { + + output = reference( 'backgroundIntensity', 'float', scene ); + + } else { + + console.error( 'THREE.SceneNode: Unknown scope:', scope ); + + } + + return output; + + } + +} + +SceneNode.BACKGROUND_BLURRINESS = 'backgroundBlurriness'; +SceneNode.BACKGROUND_INTENSITY = 'backgroundIntensity'; + +const backgroundBlurriness = /*@__PURE__*/ nodeImmutable( SceneNode, SceneNode.BACKGROUND_BLURRINESS ); +const backgroundIntensity = /*@__PURE__*/ nodeImmutable( SceneNode, SceneNode.BACKGROUND_INTENSITY ); + +const GPUPrimitiveTopology = { + PointList: 'point-list', + LineList: 'line-list', + LineStrip: 'line-strip', + TriangleList: 'triangle-list', + TriangleStrip: 'triangle-strip', +}; + +const GPUCompareFunction = { + Never: 'never', + Less: 'less', + Equal: 'equal', + LessEqual: 'less-equal', + Greater: 'greater', + NotEqual: 'not-equal', + GreaterEqual: 'greater-equal', + Always: 'always' +}; + +const GPUStoreOp = { + Store: 'store', + Discard: 'discard' +}; + +const GPULoadOp = { + Load: 'load', + Clear: 'clear' +}; + +const GPUFrontFace = { + CCW: 'ccw', + CW: 'cw' +}; + +const GPUCullMode = { + None: 'none', + Front: 'front', + Back: 'back' +}; + +const GPUIndexFormat = { + Uint16: 'uint16', + Uint32: 'uint32' +}; + +const GPUTextureFormat = { + + // 8-bit formats + + R8Unorm: 'r8unorm', + R8Snorm: 'r8snorm', + R8Uint: 'r8uint', + R8Sint: 'r8sint', + + // 16-bit formats + + R16Uint: 'r16uint', + R16Sint: 'r16sint', + R16Float: 'r16float', + RG8Unorm: 'rg8unorm', + RG8Snorm: 'rg8snorm', + RG8Uint: 'rg8uint', + RG8Sint: 'rg8sint', + + // 32-bit formats + + R32Uint: 'r32uint', + R32Sint: 'r32sint', + R32Float: 'r32float', + RG16Uint: 'rg16uint', + RG16Sint: 'rg16sint', + RG16Float: 'rg16float', + RGBA8Unorm: 'rgba8unorm', + RGBA8UnormSRGB: 'rgba8unorm-srgb', + RGBA8Snorm: 'rgba8snorm', + RGBA8Uint: 'rgba8uint', + RGBA8Sint: 'rgba8sint', + BGRA8Unorm: 'bgra8unorm', + BGRA8UnormSRGB: 'bgra8unorm-srgb', + // Packed 32-bit formats + RGB9E5UFloat: 'rgb9e5ufloat', + RGB10A2Unorm: 'rgb10a2unorm', + RG11B10uFloat: 'rgb10a2unorm', + + // 64-bit formats + + RG32Uint: 'rg32uint', + RG32Sint: 'rg32sint', + RG32Float: 'rg32float', + RGBA16Uint: 'rgba16uint', + RGBA16Sint: 'rgba16sint', + RGBA16Float: 'rgba16float', + + // 128-bit formats + + RGBA32Uint: 'rgba32uint', + RGBA32Sint: 'rgba32sint', + RGBA32Float: 'rgba32float', + + // Depth and stencil formats + + Stencil8: 'stencil8', + Depth16Unorm: 'depth16unorm', + Depth24Plus: 'depth24plus', + Depth24PlusStencil8: 'depth24plus-stencil8', + Depth32Float: 'depth32float', + + // 'depth32float-stencil8' extension + + Depth32FloatStencil8: 'depth32float-stencil8', + + // BC compressed formats usable if 'texture-compression-bc' is both + // supported by the device/user agent and enabled in requestDevice. + + BC1RGBAUnorm: 'bc1-rgba-unorm', + BC1RGBAUnormSRGB: 'bc1-rgba-unorm-srgb', + BC2RGBAUnorm: 'bc2-rgba-unorm', + BC2RGBAUnormSRGB: 'bc2-rgba-unorm-srgb', + BC3RGBAUnorm: 'bc3-rgba-unorm', + BC3RGBAUnormSRGB: 'bc3-rgba-unorm-srgb', + BC4RUnorm: 'bc4-r-unorm', + BC4RSnorm: 'bc4-r-snorm', + BC5RGUnorm: 'bc5-rg-unorm', + BC5RGSnorm: 'bc5-rg-snorm', + BC6HRGBUFloat: 'bc6h-rgb-ufloat', + BC6HRGBFloat: 'bc6h-rgb-float', + BC7RGBAUnorm: 'bc7-rgba-unorm', + BC7RGBAUnormSRGB: 'bc7-rgba-srgb', + + // ETC2 compressed formats usable if 'texture-compression-etc2' is both + // supported by the device/user agent and enabled in requestDevice. + + ETC2RGB8Unorm: 'etc2-rgb8unorm', + ETC2RGB8UnormSRGB: 'etc2-rgb8unorm-srgb', + ETC2RGB8A1Unorm: 'etc2-rgb8a1unorm', + ETC2RGB8A1UnormSRGB: 'etc2-rgb8a1unorm-srgb', + ETC2RGBA8Unorm: 'etc2-rgba8unorm', + ETC2RGBA8UnormSRGB: 'etc2-rgba8unorm-srgb', + EACR11Unorm: 'eac-r11unorm', + EACR11Snorm: 'eac-r11snorm', + EACRG11Unorm: 'eac-rg11unorm', + EACRG11Snorm: 'eac-rg11snorm', + + // ASTC compressed formats usable if 'texture-compression-astc' is both + // supported by the device/user agent and enabled in requestDevice. + + ASTC4x4Unorm: 'astc-4x4-unorm', + ASTC4x4UnormSRGB: 'astc-4x4-unorm-srgb', + ASTC5x4Unorm: 'astc-5x4-unorm', + ASTC5x4UnormSRGB: 'astc-5x4-unorm-srgb', + ASTC5x5Unorm: 'astc-5x5-unorm', + ASTC5x5UnormSRGB: 'astc-5x5-unorm-srgb', + ASTC6x5Unorm: 'astc-6x5-unorm', + ASTC6x5UnormSRGB: 'astc-6x5-unorm-srgb', + ASTC6x6Unorm: 'astc-6x6-unorm', + ASTC6x6UnormSRGB: 'astc-6x6-unorm-srgb', + ASTC8x5Unorm: 'astc-8x5-unorm', + ASTC8x5UnormSRGB: 'astc-8x5-unorm-srgb', + ASTC8x6Unorm: 'astc-8x6-unorm', + ASTC8x6UnormSRGB: 'astc-8x6-unorm-srgb', + ASTC8x8Unorm: 'astc-8x8-unorm', + ASTC8x8UnormSRGB: 'astc-8x8-unorm-srgb', + ASTC10x5Unorm: 'astc-10x5-unorm', + ASTC10x5UnormSRGB: 'astc-10x5-unorm-srgb', + ASTC10x6Unorm: 'astc-10x6-unorm', + ASTC10x6UnormSRGB: 'astc-10x6-unorm-srgb', + ASTC10x8Unorm: 'astc-10x8-unorm', + ASTC10x8UnormSRGB: 'astc-10x8-unorm-srgb', + ASTC10x10Unorm: 'astc-10x10-unorm', + ASTC10x10UnormSRGB: 'astc-10x10-unorm-srgb', + ASTC12x10Unorm: 'astc-12x10-unorm', + ASTC12x10UnormSRGB: 'astc-12x10-unorm-srgb', + ASTC12x12Unorm: 'astc-12x12-unorm', + ASTC12x12UnormSRGB: 'astc-12x12-unorm-srgb', + +}; + +const GPUAddressMode = { + ClampToEdge: 'clamp-to-edge', + Repeat: 'repeat', + MirrorRepeat: 'mirror-repeat' +}; + +const GPUFilterMode = { + Linear: 'linear', + Nearest: 'nearest' +}; + +const GPUBlendFactor = { + Zero: 'zero', + One: 'one', + Src: 'src', + OneMinusSrc: 'one-minus-src', + SrcAlpha: 'src-alpha', + OneMinusSrcAlpha: 'one-minus-src-alpha', + Dst: 'dst', + OneMinusDstColor: 'one-minus-dst', + DstAlpha: 'dst-alpha', + OneMinusDstAlpha: 'one-minus-dst-alpha', + SrcAlphaSaturated: 'src-alpha-saturated', + Constant: 'constant', + OneMinusConstant: 'one-minus-constant' +}; + +const GPUBlendOperation = { + Add: 'add', + Subtract: 'subtract', + ReverseSubtract: 'reverse-subtract', + Min: 'min', + Max: 'max' +}; + +const GPUColorWriteFlags = { + None: 0, + Red: 0x1, + Green: 0x2, + Blue: 0x4, + Alpha: 0x8, + All: 0xF +}; + +const GPUStencilOperation = { + Keep: 'keep', + Zero: 'zero', + Replace: 'replace', + Invert: 'invert', + IncrementClamp: 'increment-clamp', + DecrementClamp: 'decrement-clamp', + IncrementWrap: 'increment-wrap', + DecrementWrap: 'decrement-wrap' +}; + +const GPUBufferBindingType = { + Uniform: 'uniform', + Storage: 'storage', + ReadOnlyStorage: 'read-only-storage' +}; + +const GPUStorageTextureAccess = { + WriteOnly: 'write-only', + ReadOnly: 'read-only', + ReadWrite: 'read-write', +}; + +const GPUTextureSampleType = { + Float: 'float', + UnfilterableFloat: 'unfilterable-float', + Depth: 'depth', + SInt: 'sint', + UInt: 'uint' +}; + +const GPUTextureDimension = { + OneD: '1d', + TwoD: '2d', + ThreeD: '3d' +}; + +const GPUTextureViewDimension = { + OneD: '1d', + TwoD: '2d', + TwoDArray: '2d-array', + Cube: 'cube', + CubeArray: 'cube-array', + ThreeD: '3d' +}; + +const GPUTextureAspect = { + All: 'all', + StencilOnly: 'stencil-only', + DepthOnly: 'depth-only' +}; + +const GPUInputStepMode = { + Vertex: 'vertex', + Instance: 'instance' +}; + +const GPUFeatureName = { + DepthClipControl: 'depth-clip-control', + Depth32FloatStencil8: 'depth32float-stencil8', + TextureCompressionBC: 'texture-compression-bc', + TextureCompressionETC2: 'texture-compression-etc2', + TextureCompressionASTC: 'texture-compression-astc', + TimestampQuery: 'timestamp-query', + IndirectFirstInstance: 'indirect-first-instance', + ShaderF16: 'shader-f16', + RG11B10UFloat: 'rg11b10ufloat-renderable', + BGRA8UNormStorage: 'bgra8unorm-storage', + Float32Filterable: 'float32-filterable', + ClipDistances: 'clip-distances', + DualSourceBlending: 'dual-source-blending', + Subgroups: 'subgroups' +}; + +class StorageBufferNode extends BufferNode { + + static get type() { + + return 'StorageBufferNode'; + + } + + constructor( value, bufferType, bufferCount = 0 ) { + + super( value, bufferType, bufferCount ); + + this.isStorageBufferNode = true; + + this.access = GPUBufferBindingType.Storage; + this.isAtomic = false; + + this.bufferObject = false; + this.bufferCount = bufferCount; + + this._attribute = null; + this._varying = null; + + this.global = true; + + if ( value.isStorageBufferAttribute !== true && value.isStorageInstancedBufferAttribute !== true ) { + + // TOOD: Improve it, possibly adding a new property to the BufferAttribute to identify it as a storage buffer read-only attribute in Renderer + + if ( value.isInstancedBufferAttribute ) value.isStorageInstancedBufferAttribute = true; + else value.isStorageBufferAttribute = true; + + } + + } + + getHash( builder ) { + + if ( this.bufferCount === 0 ) { + + let bufferData = builder.globalCache.getData( this.value ); + + if ( bufferData === undefined ) { + + bufferData = { + node: this + }; + + builder.globalCache.setData( this.value, bufferData ); + + } + + return bufferData.node.uuid; + + } + + return this.uuid; + + } + + getInputType( /*builder*/ ) { + + return 'storageBuffer'; + + } + + element( indexNode ) { + + return storageElement( this, indexNode ); + + } + + setBufferObject( value ) { + + this.bufferObject = value; + + return this; + + } + + setAccess( value ) { + + this.access = value; + + return this; + + } + + toReadOnly() { + + return this.setAccess( GPUBufferBindingType.ReadOnlyStorage ); + + } + + setAtomic( value ) { + + this.isAtomic = value; + + return this; + + } + + toAtomic() { + + return this.setAtomic( true ); + + } + + generate( builder ) { + + if ( builder.isAvailable( 'storageBuffer' ) ) { + + return super.generate( builder ); + + } + + const nodeType = this.getNodeType( builder ); + + if ( this._attribute === null ) { + + this._attribute = bufferAttribute( this.value ); + this._varying = varying( this._attribute ); + + } + + + const output = this._varying.build( builder, nodeType ); + + builder.registerTransform( output, this._attribute ); + + return output; + + } + +} + +// Read-Write Storage +const storage = ( value, type, count ) => nodeObject( new StorageBufferNode( value, type, count ) ); +const storageObject = ( value, type, count ) => nodeObject( new StorageBufferNode( value, type, count ).setBufferObject( true ) ); + +class StorageTextureNode extends TextureNode { + + static get type() { + + return 'StorageTextureNode'; + + } + + constructor( value, uvNode, storeNode = null ) { + + super( value, uvNode ); + + this.storeNode = storeNode; + + this.isStorageTextureNode = true; + + this.access = GPUStorageTextureAccess.WriteOnly; + + } + + getInputType( /*builder*/ ) { + + return 'storageTexture'; + + } + + setup( builder ) { + + super.setup( builder ); + + const properties = builder.getNodeProperties( this ); + properties.storeNode = this.storeNode; + + } + + setAccess( value ) { + + this.access = value; + return this; + + } + + generate( builder, output ) { + + let snippet; + + if ( this.storeNode !== null ) { + + snippet = this.generateStore( builder ); + + } else { + + snippet = super.generate( builder, output ); + + } + + return snippet; + + } + + toReadOnly() { + + return this.setAccess( GPUStorageTextureAccess.ReadOnly ); + + } + + toWriteOnly() { + + return this.setAccess( GPUStorageTextureAccess.WriteOnly ); + + } + + generateStore( builder ) { + + const properties = builder.getNodeProperties( this ); + + const { uvNode, storeNode } = properties; + + const textureProperty = super.generate( builder, 'property' ); + const uvSnippet = uvNode.build( builder, 'uvec2' ); + const storeSnippet = storeNode.build( builder, 'vec4' ); + + const snippet = builder.generateTextureStore( builder, textureProperty, uvSnippet, storeSnippet ); + + builder.addLineFlowCode( snippet, this ); + + } + +} + +const storageTexture = /*@__PURE__*/ nodeProxy( StorageTextureNode ); + +const textureStore = ( value, uvNode, storeNode ) => { + + const node = storageTexture( value, uvNode, storeNode ); + + if ( storeNode !== null ) node.append(); + + return node; + +}; + +class UserDataNode extends ReferenceNode { + + static get type() { + + return 'UserDataNode'; + + } + + constructor( property, inputType, userData = null ) { + + super( property, inputType, userData ); + + this.userData = userData; + + } + + updateReference( state ) { + + this.reference = this.userData !== null ? this.userData : state.object.userData; + + return this.reference; + + } + +} + +const userData = ( name, inputType, userData ) => nodeObject( new UserDataNode( name, inputType, userData ) ); + +class PosterizeNode extends TempNode { + + static get type() { + + return 'PosterizeNode'; + + } + + constructor( sourceNode, stepsNode ) { + + super(); + + this.sourceNode = sourceNode; + this.stepsNode = stepsNode; + + } + + setup() { + + const { sourceNode, stepsNode } = this; + + return sourceNode.mul( stepsNode ).floor().div( stepsNode ); + + } + +} + +const posterize = /*@__PURE__*/ nodeProxy( PosterizeNode ); + +let _sharedFramebuffer = null; + +class ViewportSharedTextureNode extends ViewportTextureNode { + + static get type() { + + return 'ViewportSharedTextureNode'; + + } + + constructor( uvNode = screenUV, levelNode = null ) { + + if ( _sharedFramebuffer === null ) { + + _sharedFramebuffer = new FramebufferTexture(); + + } + + super( uvNode, levelNode, _sharedFramebuffer ); + + } + + updateReference() { + + return this; + + } + +} + +const viewportSharedTexture = /*@__PURE__*/ nodeProxy( ViewportSharedTextureNode ); + +const _size$7 = /*@__PURE__*/ new Vector2(); + +class PassTextureNode extends TextureNode { + + static get type() { + + return 'PassTextureNode'; + + } + + constructor( passNode, texture ) { + + super( texture ); + + this.passNode = passNode; + + this.setUpdateMatrix( false ); + + } + + setup( builder ) { + + if ( builder.object.isQuadMesh ) this.passNode.build( builder ); + + return super.setup( builder ); + + } + + clone() { + + return new this.constructor( this.passNode, this.value ); + + } + +} + +class PassMultipleTextureNode extends PassTextureNode { + + static get type() { + + return 'PassMultipleTextureNode'; + + } + + constructor( passNode, textureName, previousTexture = false ) { + + super( passNode, null ); + + this.textureName = textureName; + this.previousTexture = previousTexture; + + } + + updateTexture() { + + this.value = this.previousTexture ? this.passNode.getPreviousTexture( this.textureName ) : this.passNode.getTexture( this.textureName ); + + } + + setup( builder ) { + + this.updateTexture(); + + return super.setup( builder ); + + } + + clone() { + + return new this.constructor( this.passNode, this.textureName, this.previousTexture ); + + } + +} + +class PassNode extends TempNode { + + static get type() { + + return 'PassNode'; + + } + + constructor( scope, scene, camera, options = {} ) { + + super( 'vec4' ); + + this.scope = scope; + this.scene = scene; + this.camera = camera; + this.options = options; + + this._pixelRatio = 1; + this._width = 1; + this._height = 1; + + const depthTexture = new DepthTexture(); + depthTexture.isRenderTargetTexture = true; + //depthTexture.type = FloatType; + depthTexture.name = 'depth'; + + const renderTarget = new RenderTarget( this._width * this._pixelRatio, this._height * this._pixelRatio, { type: HalfFloatType, ...options, } ); + renderTarget.texture.name = 'output'; + renderTarget.depthTexture = depthTexture; + + this.renderTarget = renderTarget; + + this.updateBeforeType = NodeUpdateType.FRAME; + + this._textures = { + output: renderTarget.texture, + depth: depthTexture + }; + + this._textureNodes = {}; + this._linearDepthNodes = {}; + this._viewZNodes = {}; + + this._previousTextures = {}; + this._previousTextureNodes = {}; + + this._cameraNear = uniform( 0 ); + this._cameraFar = uniform( 0 ); + + this._mrt = null; + + this.isPassNode = true; + + } + + setMRT( mrt ) { + + this._mrt = mrt; + + return this; + + } + + getMRT() { + + return this._mrt; + + } + + isGlobal() { + + return true; + + } + + getTexture( name ) { + + let texture = this._textures[ name ]; + + if ( texture === undefined ) { + + const refTexture = this.renderTarget.texture; + + texture = refTexture.clone(); + texture.isRenderTargetTexture = true; + texture.name = name; + + this._textures[ name ] = texture; + + this.renderTarget.textures.push( texture ); + + } + + return texture; + + } + + getPreviousTexture( name ) { + + let texture = this._previousTextures[ name ]; + + if ( texture === undefined ) { + + texture = this.getTexture( name ).clone(); + texture.isRenderTargetTexture = true; + + this._previousTextures[ name ] = texture; + + } + + return texture; + + } + + toggleTexture( name ) { + + const prevTexture = this._previousTextures[ name ]; + + if ( prevTexture !== undefined ) { + + const texture = this._textures[ name ]; + + const index = this.renderTarget.textures.indexOf( texture ); + this.renderTarget.textures[ index ] = prevTexture; + + this._textures[ name ] = prevTexture; + this._previousTextures[ name ] = texture; + + this._textureNodes[ name ].updateTexture(); + this._previousTextureNodes[ name ].updateTexture(); + + } + + } + + getTextureNode( name = 'output' ) { + + let textureNode = this._textureNodes[ name ]; + + if ( textureNode === undefined ) { + + this._textureNodes[ name ] = textureNode = nodeObject( new PassMultipleTextureNode( this, name ) ); + this._textureNodes[ name ].updateTexture(); + + } + + return textureNode; + + } + + getPreviousTextureNode( name = 'output' ) { + + let textureNode = this._previousTextureNodes[ name ]; + + if ( textureNode === undefined ) { + + if ( this._textureNodes[ name ] === undefined ) this.getTextureNode( name ); + + this._previousTextureNodes[ name ] = textureNode = nodeObject( new PassMultipleTextureNode( this, name, true ) ); + this._previousTextureNodes[ name ].updateTexture(); + + } + + return textureNode; + + } + + getViewZNode( name = 'depth' ) { + + let viewZNode = this._viewZNodes[ name ]; + + if ( viewZNode === undefined ) { + + const cameraNear = this._cameraNear; + const cameraFar = this._cameraFar; + + this._viewZNodes[ name ] = viewZNode = perspectiveDepthToViewZ( this.getTextureNode( name ), cameraNear, cameraFar ); + + } + + return viewZNode; + + } + + getLinearDepthNode( name = 'depth' ) { + + let linearDepthNode = this._linearDepthNodes[ name ]; + + if ( linearDepthNode === undefined ) { + + const cameraNear = this._cameraNear; + const cameraFar = this._cameraFar; + const viewZNode = this.getViewZNode( name ); + + // TODO: just if ( builder.camera.isPerspectiveCamera ) + + this._linearDepthNodes[ name ] = linearDepthNode = viewZToOrthographicDepth( viewZNode, cameraNear, cameraFar ); + + } + + return linearDepthNode; + + } + + setup( { renderer } ) { + + this.renderTarget.samples = this.options.samples === undefined ? renderer.samples : this.options.samples; + + // Disable MSAA for WebGL backend for now + if ( renderer.backend.isWebGLBackend === true ) { + + this.renderTarget.samples = 0; + + } + + this.renderTarget.depthTexture.isMultisampleRenderTargetTexture = this.renderTarget.samples > 1; + + return this.scope === PassNode.COLOR ? this.getTextureNode() : this.getLinearDepthNode(); + + } + + updateBefore( frame ) { + + const { renderer } = frame; + const { scene, camera } = this; + + this._pixelRatio = renderer.getPixelRatio(); + + const size = renderer.getSize( _size$7 ); + + this.setSize( size.width, size.height ); + + const currentRenderTarget = renderer.getRenderTarget(); + const currentMRT = renderer.getMRT(); + + this._cameraNear.value = camera.near; + this._cameraFar.value = camera.far; + + for ( const name in this._previousTextures ) { + + this.toggleTexture( name ); + + } + + renderer.setRenderTarget( this.renderTarget ); + renderer.setMRT( this._mrt ); + + renderer.render( scene, camera ); + + renderer.setRenderTarget( currentRenderTarget ); + renderer.setMRT( currentMRT ); + + } + + setSize( width, height ) { + + this._width = width; + this._height = height; + + const effectiveWidth = this._width * this._pixelRatio; + const effectiveHeight = this._height * this._pixelRatio; + + this.renderTarget.setSize( effectiveWidth, effectiveHeight ); + + } + + setPixelRatio( pixelRatio ) { + + this._pixelRatio = pixelRatio; + + this.setSize( this._width, this._height ); + + } + + dispose() { + + this.renderTarget.dispose(); + + } + + +} + +PassNode.COLOR = 'color'; +PassNode.DEPTH = 'depth'; + +const pass = ( scene, camera, options ) => nodeObject( new PassNode( PassNode.COLOR, scene, camera, options ) ); +const passTexture = ( pass, texture ) => nodeObject( new PassTextureNode( pass, texture ) ); +const depthPass = ( scene, camera ) => nodeObject( new PassNode( PassNode.DEPTH, scene, camera ) ); + +// WebGPU: The use of a single QuadMesh for both gaussian blur passes results in a single RenderObject with a SampledTexture binding that +// alternates between source textures and triggers creation of new BindGroups and BindGroupLayouts every frame. + +const _quadMesh1 = /*@__PURE__*/ new QuadMesh(); +const _quadMesh2 = /*@__PURE__*/ new QuadMesh(); + +class GaussianBlurNode extends TempNode { + + static get type() { + + return 'GaussianBlurNode'; + + } + + constructor( textureNode, directionNode = null, sigma = 2 ) { + + super( 'vec4' ); + + this.textureNode = textureNode; + this.directionNode = directionNode; + this.sigma = sigma; + + this._invSize = uniform( new Vector2() ); + this._passDirection = uniform( new Vector2() ); + + this._horizontalRT = new RenderTarget(); + this._horizontalRT.texture.name = 'GaussianBlurNode.horizontal'; + this._verticalRT = new RenderTarget(); + this._verticalRT.texture.name = 'GaussianBlurNode.vertical'; + + this._textureNode = passTexture( this, this._verticalRT.texture ); + + this.updateBeforeType = NodeUpdateType.RENDER; + + this.resolution = new Vector2( 1, 1 ); + + } + + setSize( width, height ) { + + width = Math.max( Math.round( width * this.resolution.x ), 1 ); + height = Math.max( Math.round( height * this.resolution.y ), 1 ); + + this._invSize.value.set( 1 / width, 1 / height ); + this._horizontalRT.setSize( width, height ); + this._verticalRT.setSize( width, height ); + + } + + updateBefore( frame ) { + + const { renderer } = frame; + + const textureNode = this.textureNode; + const map = textureNode.value; + + const currentRenderTarget = renderer.getRenderTarget(); + const currentMRT = renderer.getMRT(); + + const currentTexture = textureNode.value; + + _quadMesh1.material = this._material; + _quadMesh2.material = this._material; + + this.setSize( map.image.width, map.image.height ); + + const textureType = map.type; + + this._horizontalRT.texture.type = textureType; + this._verticalRT.texture.type = textureType; + + // clear + + renderer.setMRT( null ); + + // horizontal + + renderer.setRenderTarget( this._horizontalRT ); + + this._passDirection.value.set( 1, 0 ); + + _quadMesh1.render( renderer ); + + // vertical + + textureNode.value = this._horizontalRT.texture; + renderer.setRenderTarget( this._verticalRT ); + + this._passDirection.value.set( 0, 1 ); + + _quadMesh2.render( renderer ); + + // restore + + renderer.setRenderTarget( currentRenderTarget ); + renderer.setMRT( currentMRT ); + textureNode.value = currentTexture; + + } + + getTextureNode() { + + return this._textureNode; + + } + + setup( builder ) { + + const textureNode = this.textureNode; + + if ( textureNode.isTextureNode !== true ) { + + console.error( 'GaussianBlurNode requires a TextureNode.' ); + + return vec4(); + + } + + // + + const uvNode = textureNode.uvNode || uv(); + const directionNode = vec2( this.directionNode || 1 ); + + const sampleTexture = ( uv ) => textureNode.uv( uv ); + + const blur = Fn( () => { + + const kernelSize = 3 + ( 2 * this.sigma ); + const gaussianCoefficients = this._getCoefficients( kernelSize ); + + const invSize = this._invSize; + const direction = directionNode.mul( this._passDirection ); + + const weightSum = float( gaussianCoefficients[ 0 ] ).toVar(); + const diffuseSum = vec4( sampleTexture( uvNode ).mul( weightSum ) ).toVar(); + + for ( let i = 1; i < kernelSize; i ++ ) { + + const x = float( i ); + const w = float( gaussianCoefficients[ i ] ); + + const uvOffset = vec2( direction.mul( invSize.mul( x ) ) ).toVar(); + + const sample1 = vec4( sampleTexture( uvNode.add( uvOffset ) ) ); + const sample2 = vec4( sampleTexture( uvNode.sub( uvOffset ) ) ); + + diffuseSum.addAssign( sample1.add( sample2 ).mul( w ) ); + weightSum.addAssign( mul( 2.0, w ) ); + + } + + return diffuseSum.div( weightSum ); + + } ); + + // + + const material = this._material || ( this._material = new NodeMaterial() ); + material.fragmentNode = blur().context( builder.getSharedContext() ); + material.name = 'Gaussian_blur'; + material.needsUpdate = true; + + // + + const properties = builder.getNodeProperties( this ); + properties.textureNode = textureNode; + + // + + return this._textureNode; + + } + + dispose() { + + this._horizontalRT.dispose(); + this._verticalRT.dispose(); + + } + + _getCoefficients( kernelRadius ) { + + const coefficients = []; + + for ( let i = 0; i < kernelRadius; i ++ ) { + + coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius ); + + } + + return coefficients; + + } + +} + +const gaussianBlur = ( node, directionNode, sigma ) => nodeObject( new GaussianBlurNode( convertToTexture( node ), directionNode, sigma ) ); + +const _size$6 = /*@__PURE__*/ new Vector2(); + +const _quadMeshComp = /*@__PURE__*/ new QuadMesh(); + +class AfterImageNode extends TempNode { + + static get type() { + + return 'AfterImageNode'; + + } + + constructor( textureNode, damp = 0.96 ) { + + super( textureNode ); + + this.textureNode = textureNode; + this.textureNodeOld = texture(); + this.damp = uniform( damp ); + + this._compRT = new RenderTarget(); + this._compRT.texture.name = 'AfterImageNode.comp'; + + this._oldRT = new RenderTarget(); + this._oldRT.texture.name = 'AfterImageNode.old'; + + this._textureNode = passTexture( this, this._compRT.texture ); + + this.updateBeforeType = NodeUpdateType.RENDER; + + } + + getTextureNode() { + + return this._textureNode; + + } + + setSize( width, height ) { + + this._compRT.setSize( width, height ); + this._oldRT.setSize( width, height ); + + } + + updateBefore( frame ) { + + const { renderer } = frame; + + const textureNode = this.textureNode; + const map = textureNode.value; + + const textureType = map.type; + + this._compRT.texture.type = textureType; + this._oldRT.texture.type = textureType; + + renderer.getDrawingBufferSize( _size$6 ); + + this.setSize( _size$6.x, _size$6.y ); + + const currentRenderTarget = renderer.getRenderTarget(); + const currentTexture = textureNode.value; + + this.textureNodeOld.value = this._oldRT.texture; + + // comp + renderer.setRenderTarget( this._compRT ); + _quadMeshComp.render( renderer ); + + // Swap the textures + const temp = this._oldRT; + this._oldRT = this._compRT; + this._compRT = temp; + + renderer.setRenderTarget( currentRenderTarget ); + textureNode.value = currentTexture; + + } + + setup( builder ) { + + const textureNode = this.textureNode; + const textureNodeOld = this.textureNodeOld; + + // + + const uvNode = textureNode.uvNode || uv(); + + textureNodeOld.uvNode = uvNode; + + const sampleTexture = ( uv ) => textureNode.uv( uv ); + + const when_gt = Fn( ( [ x_immutable, y_immutable ] ) => { + + const y = float( y_immutable ).toVar(); + const x = vec4( x_immutable ).toVar(); + + return max$1( sign( x.sub( y ) ), 0.0 ); + + } ); + + const afterImg = Fn( () => { + + const texelOld = vec4( textureNodeOld ); + const texelNew = vec4( sampleTexture( uvNode ) ); + + texelOld.mulAssign( this.damp.mul( when_gt( texelOld, 0.1 ) ) ); + return max$1( texelNew, texelOld ); + + } ); + + // + + const materialComposed = this._materialComposed || ( this._materialComposed = new NodeMaterial() ); + materialComposed.name = 'AfterImage'; + materialComposed.fragmentNode = afterImg(); + + _quadMeshComp.material = materialComposed; + + // + + const properties = builder.getNodeProperties( this ); + properties.textureNode = textureNode; + + // + + return this._textureNode; + + } + + dispose() { + + this._compRT.dispose(); + this._oldRT.dispose(); + + } + +} + +const afterImage = ( node, damp ) => nodeObject( new AfterImageNode( convertToTexture( node ), damp ) ); + +const grayscale = /*@__PURE__*/ Fn( ( [ color ] ) => { + + return luminance( color.rgb ); + +} ); + +const saturation = /*@__PURE__*/ Fn( ( [ color, adjustment = float( 1 ) ] ) => { + + return adjustment.mix( luminance( color.rgb ), color.rgb ); + +} ); + +const vibrance = /*@__PURE__*/ Fn( ( [ color, adjustment = float( 1 ) ] ) => { + + const average = add( color.r, color.g, color.b ).div( 3.0 ); + + const mx = color.r.max( color.g.max( color.b ) ); + const amt = mx.sub( average ).mul( adjustment ).mul( - 3.0 ); + + return mix( color.rgb, mx, amt ); + +} ); + +const hue = /*@__PURE__*/ Fn( ( [ color, adjustment = float( 1 ) ] ) => { + + const k = vec3( 0.57735, 0.57735, 0.57735 ); + + const cosAngle = adjustment.cos(); + + return vec3( color.rgb.mul( cosAngle ).add( k.cross( color.rgb ).mul( adjustment.sin() ).add( k.mul( dot( k, color.rgb ).mul( cosAngle.oneMinus() ) ) ) ) ); + +} ); + +const _luminanceCoefficients = /*@__PURE__*/ new Vector3(); +const luminance = ( + color, + luminanceCoefficients = vec3( ... ColorManagement.getLuminanceCoefficients( _luminanceCoefficients ) ) +) => dot( color, luminanceCoefficients ); + +const threshold = ( color, threshold ) => mix( vec3( 0.0 ), color, luminance( color ).sub( threshold ).max( 0 ) ); + +const _quadMesh$5 = /*@__PURE__*/ new QuadMesh(); + +class AnamorphicNode extends TempNode { + + static get type() { + + return 'AnamorphicNode'; + + } + + constructor( textureNode, tresholdNode, scaleNode, samples ) { + + super( 'vec4' ); + + this.textureNode = textureNode; + this.tresholdNode = tresholdNode; + this.scaleNode = scaleNode; + this.colorNode = vec3( 0.1, 0.0, 1.0 ); + this.samples = samples; + this.resolution = new Vector2( 1, 1 ); + + this._renderTarget = new RenderTarget(); + this._renderTarget.texture.name = 'anamorphic'; + + this._invSize = uniform( new Vector2() ); + + this._textureNode = passTexture( this, this._renderTarget.texture ); + + this.updateBeforeType = NodeUpdateType.RENDER; + + } + + getTextureNode() { + + return this._textureNode; + + } + + setSize( width, height ) { + + this._invSize.value.set( 1 / width, 1 / height ); + + width = Math.max( Math.round( width * this.resolution.x ), 1 ); + height = Math.max( Math.round( height * this.resolution.y ), 1 ); + + this._renderTarget.setSize( width, height ); + + } + + updateBefore( frame ) { + + const { renderer } = frame; + + const textureNode = this.textureNode; + const map = textureNode.value; + + this._renderTarget.texture.type = map.type; + + const currentRenderTarget = renderer.getRenderTarget(); + const currentTexture = textureNode.value; + + _quadMesh$5.material = this._material; + + this.setSize( map.image.width, map.image.height ); + + // render + + renderer.setRenderTarget( this._renderTarget ); + + _quadMesh$5.render( renderer ); + + // restore + + renderer.setRenderTarget( currentRenderTarget ); + textureNode.value = currentTexture; + + } + + setup( builder ) { + + const textureNode = this.textureNode; + const uvNode = textureNode.uvNode || uv(); + + const sampleTexture = ( uv ) => textureNode.uv( uv ); + + const anamorph = Fn( () => { + + const samples = this.samples; + const halfSamples = Math.floor( samples / 2 ); + + const total = vec3( 0 ).toVar(); + + Loop( { start: - halfSamples, end: halfSamples }, ( { i } ) => { + + const softness = float( i ).abs().div( halfSamples ).oneMinus(); + + const uv = vec2( uvNode.x.add( this._invSize.x.mul( i ).mul( this.scaleNode ) ), uvNode.y ); + const color = sampleTexture( uv ); + const pass = threshold( color, this.tresholdNode ).mul( softness ); + + total.addAssign( pass ); + + } ); + + return total.mul( this.colorNode ); + + } ); + + // + + const material = this._material || ( this._material = new NodeMaterial() ); + material.name = 'Anamorphic'; + material.fragmentNode = anamorph(); + + // + + const properties = builder.getNodeProperties( this ); + properties.textureNode = textureNode; + + // + + return this._textureNode; + + } + + dispose() { + + this._renderTarget.dispose(); + + } + +} + +const anamorphic = ( node, threshold = .9, scale = 3, samples = 32 ) => nodeObject( new AnamorphicNode( convertToTexture( node ), nodeObject( threshold ), nodeObject( scale ), samples ) ); + +class SobelOperatorNode extends TempNode { + + static get type() { + + return 'SobelOperatorNode'; + + } + + constructor( textureNode ) { + + super(); + + this.textureNode = textureNode; + + this.updateBeforeType = NodeUpdateType.RENDER; + + this._invSize = uniform( new Vector2() ); + + } + + updateBefore() { + + const map = this.textureNode.value; + + this._invSize.value.set( 1 / map.image.width, 1 / map.image.height ); + + } + + setup() { + + const { textureNode } = this; + + const uvNode = textureNode.uvNode || uv(); + + const sampleTexture = ( uv ) => textureNode.uv( uv ); + + const sobel = Fn( () => { + + // Sobel Edge Detection (see https://youtu.be/uihBwtPIBxM) + + const texel = this._invSize; + + // kernel definition (in glsl matrices are filled in column-major order) + + const Gx = mat3( - 1, - 2, - 1, 0, 0, 0, 1, 2, 1 ); // x direction kernel + const Gy = mat3( - 1, 0, 1, - 2, 0, 2, - 1, 0, 1 ); // y direction kernel + + // fetch the 3x3 neighbourhood of a fragment + + // first column + + const tx0y0 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( - 1, - 1 ) ) ) ).xyz ); + const tx0y1 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( - 1, 0 ) ) ) ).xyz ); + const tx0y2 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( - 1, 1 ) ) ) ).xyz ); + + // second column + + const tx1y0 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 0, - 1 ) ) ) ).xyz ); + const tx1y1 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 0, 0 ) ) ) ).xyz ); + const tx1y2 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 0, 1 ) ) ) ).xyz ); + + // third column + + const tx2y0 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 1, - 1 ) ) ) ).xyz ); + const tx2y1 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 1, 0 ) ) ) ).xyz ); + const tx2y2 = luminance( sampleTexture( uvNode.add( texel.mul( vec2( 1, 1 ) ) ) ).xyz ); + + // gradient value in x direction + + const valueGx = add( + Gx[ 0 ][ 0 ].mul( tx0y0 ), + Gx[ 1 ][ 0 ].mul( tx1y0 ), + Gx[ 2 ][ 0 ].mul( tx2y0 ), + Gx[ 0 ][ 1 ].mul( tx0y1 ), + Gx[ 1 ][ 1 ].mul( tx1y1 ), + Gx[ 2 ][ 1 ].mul( tx2y1 ), + Gx[ 0 ][ 2 ].mul( tx0y2 ), + Gx[ 1 ][ 2 ].mul( tx1y2 ), + Gx[ 2 ][ 2 ].mul( tx2y2 ) + ); + + + // gradient value in y direction + + const valueGy = add( + Gy[ 0 ][ 0 ].mul( tx0y0 ), + Gy[ 1 ][ 0 ].mul( tx1y0 ), + Gy[ 2 ][ 0 ].mul( tx2y0 ), + Gy[ 0 ][ 1 ].mul( tx0y1 ), + Gy[ 1 ][ 1 ].mul( tx1y1 ), + Gy[ 2 ][ 1 ].mul( tx2y1 ), + Gy[ 0 ][ 2 ].mul( tx0y2 ), + Gy[ 1 ][ 2 ].mul( tx1y2 ), + Gy[ 2 ][ 2 ].mul( tx2y2 ) + ); + + // magnitute of the total gradient + + const G = valueGx.mul( valueGx ).add( valueGy.mul( valueGy ) ).sqrt(); + + return vec4( vec3( G ), 1 ); + + } ); + + const outputNode = sobel(); + + return outputNode; + + } + +} + +const sobel = ( node ) => nodeObject( new SobelOperatorNode( convertToTexture( node ) ) ); + +class DepthOfFieldNode extends TempNode { + + static get type() { + + return 'DepthOfFieldNode'; + + } + + constructor( textureNode, viewZNode, focusNode, apertureNode, maxblurNode ) { + + super(); + + this.textureNode = textureNode; + this.viewZNode = viewZNode; + + this.focusNode = focusNode; + this.apertureNode = apertureNode; + this.maxblurNode = maxblurNode; + + this._aspect = uniform( 0 ); + + this.updateBeforeType = NodeUpdateType.RENDER; + + } + + updateBefore() { + + const map = this.textureNode.value; + + this._aspect.value = map.image.width / map.image.height; + + } + + setup() { + + const textureNode = this.textureNode; + const uvNode = textureNode.uvNode || uv(); + + const sampleTexture = ( uv ) => textureNode.uv( uv ); + + const dof = Fn( () => { + + const aspectcorrect = vec2( 1.0, this._aspect ); + + const factor = this.focusNode.add( this.viewZNode ); + + const dofblur = vec2( clamp( factor.mul( this.apertureNode ), this.maxblurNode.negate(), this.maxblurNode ) ); + + const dofblur9 = dofblur.mul( 0.9 ); + const dofblur7 = dofblur.mul( 0.7 ); + const dofblur4 = dofblur.mul( 0.4 ); + + let col = vec4( 0.0 ); + + col = col.add( sampleTexture( uvNode ) ); + + col = col.add( sampleTexture( uvNode.add( vec2( 0.0, 0.4 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.15, 0.37 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.37, 0.15 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.40, 0.0 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.37, - 0.15 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.15, - 0.37 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.0, - 0.4 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.15, 0.37 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.37, 0.15 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.4, 0.0 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.37, - 0.15 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.15, - 0.37 ).mul( aspectcorrect ).mul( dofblur ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.15, 0.37 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.37, 0.15 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.37, - 0.15 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.15, - 0.37 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.15, 0.37 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.37, 0.15 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.37, - 0.15 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.15, - 0.37 ).mul( aspectcorrect ).mul( dofblur9 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.40, 0.0 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.0, - 0.4 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.4, 0.0 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.0, 0.4 ).mul( aspectcorrect ).mul( dofblur7 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.4, 0.0 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.0, - 0.4 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, 0.29 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.4, 0.0 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( - 0.29, - 0.29 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); + col = col.add( sampleTexture( uvNode.add( vec2( 0.0, 0.4 ).mul( aspectcorrect ).mul( dofblur4 ) ) ) ); + + col = col.div( 41 ); + col.a = 1; + + return vec4( col ); + + + } ); + + const outputNode = dof(); + + return outputNode; + + } + +} + +const dof = ( node, viewZNode, focus = 1, aperture = 0.025, maxblur = 1 ) => nodeObject( new DepthOfFieldNode( convertToTexture( node ), nodeObject( viewZNode ), nodeObject( focus ), nodeObject( aperture ), nodeObject( maxblur ) ) ); + +class DotScreenNode extends TempNode { + + static get type() { + + return 'DotScreenNode'; + + } + + constructor( inputNode, center = new Vector2( 0.5, 0.5 ), angle = 1.57, scale = 1 ) { + + super( 'vec4' ); + + this.inputNode = inputNode; + this.center = uniform( center ); + this.angle = uniform( angle ); + this.scale = uniform( scale ); + + } + + setup() { + + const inputNode = this.inputNode; + + const pattern = Fn( () => { + + const s = sin( this.angle ); + const c = cos( this.angle ); + + const tex = uv().mul( screenSize ).sub( this.center ); + const point = vec2( c.mul( tex.x ).sub( s.mul( tex.y ) ), s.mul( tex.x ).add( c.mul( tex.y ) ) ).mul( this.scale ); + + return sin( point.x ).mul( sin( point.y ) ).mul( 4 ); + + } ); + + const dotScreen = Fn( () => { + + const color = inputNode; + + const average = add( color.r, color.g, color.b ).div( 3 ); + + return vec4( vec3( average.mul( 10 ).sub( 5 ).add( pattern() ) ), color.a ); + + } ); + + const outputNode = dotScreen(); + + return outputNode; + + } + +} + +const dotScreen = ( node, center, angle, scale ) => nodeObject( new DotScreenNode( nodeObject( node ), center, angle, scale ) ); + +class RGBShiftNode extends TempNode { + + static get type() { + + return 'RGBShiftNode'; + + } + + constructor( textureNode, amount = 0.005, angle = 0 ) { + + super( 'vec4' ); + + this.textureNode = textureNode; + this.amount = uniform( amount ); + this.angle = uniform( angle ); + + } + + setup() { + + const { textureNode } = this; + + const uvNode = textureNode.uvNode || uv(); + + const sampleTexture = ( uv ) => textureNode.uv( uv ); + + const rgbShift = Fn( () => { + + const offset = vec2( cos( this.angle ), sin( this.angle ) ).mul( this.amount ); + const cr = sampleTexture( uvNode.add( offset ) ); + const cga = sampleTexture( uvNode ); + const cb = sampleTexture( uvNode.sub( offset ) ); + + return vec4( cr.r, cga.g, cb.b, cga.a ); + + } ); + + return rgbShift(); + + } + +} + +const rgbShift = ( node, amount, angle ) => nodeObject( new RGBShiftNode( convertToTexture( node ), amount, angle ) ); + +class FilmNode extends TempNode { + + static get type() { + + return 'FilmNode'; + + } + + constructor( inputNode, intensityNode = null, uvNode = null ) { + + super(); + + this.inputNode = inputNode; + this.intensityNode = intensityNode; + this.uvNode = uvNode; + + } + + setup() { + + const uvNode = this.uvNode || uv(); + + const film = Fn( () => { + + const base = this.inputNode.rgb; + const noise = rand( fract( uvNode.add( timerLocal() ) ) ); + + let color = base.add( base.mul( clamp( noise.add( 0.1 ), 0, 1 ) ) ); + + if ( this.intensityNode !== null ) { + + color = mix( base, color, this.intensityNode ); + + } + + return vec4( color, this.inputNode.a ); + + } ); + + const outputNode = film(); + + return outputNode; + + } + +} + +const film = /*@__PURE__*/ nodeProxy( FilmNode ); + +class Lut3DNode extends TempNode { + + static get type() { + + return 'Lut3DNode'; + + } + + constructor( inputNode, lutNode, size, intensityNode ) { + + super(); + + this.inputNode = inputNode; + this.lutNode = lutNode; + this.size = uniform( size ); + this.intensityNode = intensityNode; + + } + + setup() { + + const { inputNode, lutNode } = this; + + const sampleLut = ( uv ) => lutNode.uv( uv ); + + const lut3D = Fn( () => { + + const base = inputNode; + + // pull the sample in by half a pixel so the sample begins at the center of the edge pixels. + + const pixelWidth = float( 1.0 ).div( this.size ); + const halfPixelWidth = float( 0.5 ).div( this.size ); + const uvw = vec3( halfPixelWidth ).add( base.rgb.mul( float( 1.0 ).sub( pixelWidth ) ) ); + + const lutValue = vec4( sampleLut( uvw ).rgb, base.a ); + + return vec4( mix( base, lutValue, this.intensityNode ) ); + + } ); + + const outputNode = lut3D(); + + return outputNode; + + } + +} + +const lut3D = ( node, lut, size, intensity ) => nodeObject( new Lut3DNode( nodeObject( node ), nodeObject( lut ), size, nodeObject( intensity ) ) ); + +const _quadMesh$4 = /*@__PURE__*/ new QuadMesh(); +const _currentClearColor$1 = /*@__PURE__*/ new Color(); +const _size$5 = /*@__PURE__*/ new Vector2(); + +class GTAONode extends TempNode { + + static get type() { + + return 'GTAONode'; + + } + + constructor( depthNode, normalNode, camera ) { + + super(); + + this.depthNode = depthNode; + this.normalNode = normalNode; + + this.radius = uniform( 0.25 ); + this.resolution = uniform( new Vector2() ); + this.thickness = uniform( 1 ); + this.distanceExponent = uniform( 1 ); + this.distanceFallOff = uniform( 1 ); + this.scale = uniform( 1 ); + this.noiseNode = texture( generateMagicSquareNoise() ); + + this.cameraProjectionMatrix = uniform( camera.projectionMatrix ); + this.cameraProjectionMatrixInverse = uniform( camera.projectionMatrixInverse ); + + this.SAMPLES = uniform( 16 ); + + this._aoRenderTarget = new RenderTarget(); + this._aoRenderTarget.texture.name = 'GTAONode.AO'; + + this._material = null; + this._textureNode = passTexture( this, this._aoRenderTarget.texture ); + + this.updateBeforeType = NodeUpdateType.FRAME; + + } + + getTextureNode() { + + return this._textureNode; + + } + + setSize( width, height ) { + + this.resolution.value.set( width, height ); + this._aoRenderTarget.setSize( width, height ); + + } + + updateBefore( frame ) { + + const { renderer } = frame; + + const size = renderer.getDrawingBufferSize( _size$5 ); + + const currentRenderTarget = renderer.getRenderTarget(); + const currentMRT = renderer.getMRT(); + renderer.getClearColor( _currentClearColor$1 ); + const currentClearAlpha = renderer.getClearAlpha(); + + _quadMesh$4.material = this._material; + + this.setSize( size.width, size.height ); + + // clear + + renderer.setMRT( null ); + renderer.setClearColor( 0xffffff, 1 ); + + // ao + + renderer.setRenderTarget( this._aoRenderTarget ); + _quadMesh$4.render( renderer ); + + // restore + + renderer.setRenderTarget( currentRenderTarget ); + renderer.setMRT( currentMRT ); + renderer.setClearColor( _currentClearColor$1, currentClearAlpha ); + + } + + setup( builder ) { + + const uvNode = uv(); + + const sampleDepth = ( uv ) => this.depthNode.uv( uv ).x; + const sampleNoise = ( uv ) => this.noiseNode.uv( uv ); + + const getSceneUvAndDepth = Fn( ( [ sampleViewPos ] )=> { + + const sampleClipPos = this.cameraProjectionMatrix.mul( vec4( sampleViewPos, 1.0 ) ); + let sampleUv = sampleClipPos.xy.div( sampleClipPos.w ).mul( 0.5 ).add( 0.5 ).toVar(); + sampleUv = vec2( sampleUv.x, sampleUv.y.oneMinus() ); + const sampleSceneDepth = sampleDepth( sampleUv ); + return vec3( sampleUv, sampleSceneDepth ); + + } ); + + const getViewPosition = Fn( ( [ screenPosition, depth ] ) => { + + screenPosition = vec2( screenPosition.x, screenPosition.y.oneMinus() ).mul( 2.0 ).sub( 1.0 ); + + const clipSpacePosition = vec4( vec3( screenPosition, depth ), 1.0 ); + const viewSpacePosition = vec4( this.cameraProjectionMatrixInverse.mul( clipSpacePosition ) ); + + return viewSpacePosition.xyz.div( viewSpacePosition.w ); + + } ); + + const ao = Fn( () => { + + const depth = sampleDepth( uvNode ); + + depth.greaterThanEqual( 1.0 ).discard(); + + const viewPosition = getViewPosition( uvNode, depth ); + const viewNormal = this.normalNode.rgb.normalize(); + + const radiusToUse = this.radius; + + const noiseResolution = textureSize( this.noiseNode, 0 ); + let noiseUv = vec2( uvNode.x, uvNode.y.oneMinus() ); + noiseUv = noiseUv.mul( this.resolution.div( noiseResolution ) ); + const noiseTexel = sampleNoise( noiseUv ); + const randomVec = noiseTexel.xyz.mul( 2.0 ).sub( 1.0 ); + const tangent = vec3( randomVec.xy, 0.0 ).normalize(); + const bitangent = vec3( tangent.y.mul( - 1.0 ), tangent.x, 0.0 ); + const kernelMatrix = mat3( tangent, bitangent, vec3( 0.0, 0.0, 1.0 ) ); + + const DIRECTIONS = this.SAMPLES.lessThan( 30 ).select( 3, 5 ); + const STEPS = add( this.SAMPLES, DIRECTIONS.sub( 1 ) ).div( DIRECTIONS ); + + const ao = float( 0 ).toVar(); + + Loop( { start: int( 0 ), end: DIRECTIONS, type: 'int', condition: '<' }, ( { i } ) => { + + const angle = float( i ).div( float( DIRECTIONS ) ).mul( PI ); + const sampleDir = vec4( cos( angle ), sin( angle ), 0., add( 0.5, mul( 0.5, noiseTexel.w ) ) ); + sampleDir.xyz = normalize( kernelMatrix.mul( sampleDir.xyz ) ); + + const viewDir = normalize( viewPosition.xyz.negate() ); + const sliceBitangent = normalize( cross( sampleDir.xyz, viewDir ) ); + const sliceTangent = cross( sliceBitangent, viewDir ); + const normalInSlice = normalize( viewNormal.sub( sliceBitangent.mul( dot( viewNormal, sliceBitangent ) ) ) ); + + const tangentToNormalInSlice = cross( normalInSlice, sliceBitangent ); + const cosHorizons = vec2( dot( viewDir, tangentToNormalInSlice ), dot( viewDir, tangentToNormalInSlice.negate() ) ).toVar(); + + Loop( { end: STEPS, type: 'int', name: 'j', condition: '<' }, ( { j } ) => { + + const sampleViewOffset = sampleDir.xyz.mul( radiusToUse ).mul( sampleDir.w ).mul( pow( div( float( j ).add( 1.0 ), float( STEPS ) ), this.distanceExponent ) ); + + // x + + const sampleSceneUvDepthX = getSceneUvAndDepth( viewPosition.add( sampleViewOffset ) ); + const sampleSceneViewPositionX = getViewPosition( sampleSceneUvDepthX.xy, sampleSceneUvDepthX.z ); + const viewDeltaX = sampleSceneViewPositionX.sub( viewPosition ); + + If( abs( viewDeltaX.z ).lessThan( this.thickness ), () => { + + const sampleCosHorizon = dot( viewDir, normalize( viewDeltaX ) ); + cosHorizons.x.addAssign( max$1( 0, mul( sampleCosHorizon.sub( cosHorizons.x ), mix( 1.0, float( 2.0 ).div( float( j ).add( 2 ) ), this.distanceFallOff ) ) ) ); + + } ); + + // y + + const sampleSceneUvDepthY = getSceneUvAndDepth( viewPosition.sub( sampleViewOffset ) ); + const sampleSceneViewPositionY = getViewPosition( sampleSceneUvDepthY.xy, sampleSceneUvDepthY.z ); + const viewDeltaY = sampleSceneViewPositionY.sub( viewPosition ); + + If( abs( viewDeltaY.z ).lessThan( this.thickness ), () => { + + const sampleCosHorizon = dot( viewDir, normalize( viewDeltaY ) ); + cosHorizons.y.addAssign( max$1( 0, mul( sampleCosHorizon.sub( cosHorizons.y ), mix( 1.0, float( 2.0 ).div( float( j ).add( 2 ) ), this.distanceFallOff ) ) ) ); + + } ); + + } ); + + const sinHorizons = sqrt( sub( 1.0, cosHorizons.mul( cosHorizons ) ) ); + const nx = dot( normalInSlice, sliceTangent ); + const ny = dot( normalInSlice, viewDir ); + const nxb = mul( 0.5, acos( cosHorizons.y ).sub( acos( cosHorizons.x ) ).add( sinHorizons.x.mul( cosHorizons.x ).sub( sinHorizons.y.mul( cosHorizons.y ) ) ) ); + const nyb = mul( 0.5, sub( 2.0, cosHorizons.x.mul( cosHorizons.x ) ).sub( cosHorizons.y.mul( cosHorizons.y ) ) ); + const occlusion = nx.mul( nxb ).add( ny.mul( nyb ) ); + ao.addAssign( occlusion ); + + } ); + + ao.assign( clamp( ao.div( DIRECTIONS ), 0, 1 ) ); + ao.assign( pow( ao, this.scale ) ); + + return vec4( vec3( ao ), 1.0 ); + + } ); + + const material = this._material || ( this._material = new NodeMaterial() ); + material.fragmentNode = ao().context( builder.getSharedContext() ); + material.name = 'GTAO'; + material.needsUpdate = true; + + // + + return this._textureNode; + + } + + dispose() { + + this._aoRenderTarget.dispose(); + + } + +} + +function generateMagicSquareNoise( size = 5 ) { + + const noiseSize = Math.floor( size ) % 2 === 0 ? Math.floor( size ) + 1 : Math.floor( size ); + const magicSquare = generateMagicSquare( noiseSize ); + const noiseSquareSize = magicSquare.length; + const data = new Uint8Array( noiseSquareSize * 4 ); + + for ( let inx = 0; inx < noiseSquareSize; ++ inx ) { + + const iAng = magicSquare[ inx ]; + const angle = ( 2 * Math.PI * iAng ) / noiseSquareSize; + const randomVec = new Vector3( + Math.cos( angle ), + Math.sin( angle ), + 0 + ).normalize(); + data[ inx * 4 ] = ( randomVec.x * 0.5 + 0.5 ) * 255; + data[ inx * 4 + 1 ] = ( randomVec.y * 0.5 + 0.5 ) * 255; + data[ inx * 4 + 2 ] = 127; + data[ inx * 4 + 3 ] = 255; + + } + + const noiseTexture = new DataTexture( data, noiseSize, noiseSize ); + noiseTexture.wrapS = RepeatWrapping; + noiseTexture.wrapT = RepeatWrapping; + noiseTexture.needsUpdate = true; + + return noiseTexture; + +} + +function generateMagicSquare( size ) { + + const noiseSize = Math.floor( size ) % 2 === 0 ? Math.floor( size ) + 1 : Math.floor( size ); + const noiseSquareSize = noiseSize * noiseSize; + const magicSquare = Array( noiseSquareSize ).fill( 0 ); + let i = Math.floor( noiseSize / 2 ); + let j = noiseSize - 1; + + for ( let num = 1; num <= noiseSquareSize; ) { + + if ( i === - 1 && j === noiseSize ) { + + j = noiseSize - 2; + i = 0; + + } else { + + if ( j === noiseSize ) { + + j = 0; + + } + + if ( i < 0 ) { + + i = noiseSize - 1; + + } + + } + + if ( magicSquare[ i * noiseSize + j ] !== 0 ) { + + j -= 2; + i ++; + continue; + + } else { + + magicSquare[ i * noiseSize + j ] = num ++; + + } + + j ++; + i --; + + } + + return magicSquare; + +} + +const ao = ( depthNode, normalNode, camera ) => nodeObject( new GTAONode( nodeObject( depthNode ), nodeObject( normalNode ), camera ) ); + +class DenoiseNode extends TempNode { + + static get type() { + + return 'DenoiseNode'; + + } + + constructor( textureNode, depthNode, normalNode, noiseNode, camera ) { + + super(); + + this.textureNode = textureNode; + this.depthNode = depthNode; + this.normalNode = normalNode; + this.noiseNode = noiseNode; + + this.cameraProjectionMatrixInverse = uniform( camera.projectionMatrixInverse ); + this.lumaPhi = uniform( 5 ); + this.depthPhi = uniform( 5 ); + this.normalPhi = uniform( 5 ); + this.radius = uniform( 5 ); + this.index = uniform( 0 ); + + this._resolution = uniform( new Vector2() ); + this._sampleVectors = uniformArray( generatePdSamplePointInitializer( 16, 2, 1 ) ); + + this.updateBeforeType = NodeUpdateType.RENDER; + + } + + updateBefore() { + + const map = this.textureNode.value; + + this._resolution.value.set( map.image.width, map.image.height ); + + } + + setup() { + + const uvNode = uv(); + + const sampleTexture = ( uv ) => this.textureNode.uv( uv ); + const sampleDepth = ( uv ) => this.depthNode.uv( uv ).x; + const sampleNormal = ( uv ) => this.normalNode.uv( uv ); + const sampleNoise = ( uv ) => this.noiseNode.uv( uv ); + + const getViewPosition = Fn( ( [ screenPosition, depth ] ) => { + + screenPosition = vec2( screenPosition.x, screenPosition.y.oneMinus() ).mul( 2.0 ).sub( 1.0 ); + + const clipSpacePosition = vec4( vec3( screenPosition, depth ), 1.0 ); + const viewSpacePosition = vec4( this.cameraProjectionMatrixInverse.mul( clipSpacePosition ) ); + + return viewSpacePosition.xyz.div( viewSpacePosition.w ); + + } ); + + const denoiseSample = Fn( ( [ center, viewNormal, viewPosition, sampleUv ] ) => { + + const texel = sampleTexture( sampleUv ); + const depth = sampleDepth( sampleUv ); + const normal = sampleNormal( sampleUv ).rgb.normalize(); + const neighborColor = texel.rgb; + const viewPos = getViewPosition( sampleUv, depth ); + + const normalDiff = dot( viewNormal, normal ).toVar(); + const normalSimilarity = pow( max$1( normalDiff, 0 ), this.normalPhi ).toVar(); + const lumaDiff = abs( luminance( neighborColor ).sub( luminance( center ) ) ).toVar(); + const lumaSimilarity = max$1( float( 1.0 ).sub( lumaDiff.div( this.lumaPhi ) ), 0 ).toVar(); + const depthDiff = abs( dot( viewPosition.sub( viewPos ), viewNormal ) ).toVar(); + const depthSimilarity = max$1( float( 1.0 ).sub( depthDiff.div( this.depthPhi ) ), 0 ); + const w = lumaSimilarity.mul( depthSimilarity ).mul( normalSimilarity ); + + return vec4( neighborColor.mul( w ), w ); + + } ); + + const denoise = Fn( ( [ uvNode ] ) => { + + const depth = sampleDepth( uvNode ); + const viewNormal = sampleNormal( uvNode ).rgb.normalize(); + + const texel = sampleTexture( uvNode ); + + If( depth.greaterThanEqual( 1.0 ).or( dot( viewNormal, viewNormal ).equal( 0.0 ) ), () => { + + return texel; + + } ); + + const center = vec3( texel.rgb ); + + const viewPosition = getViewPosition( uvNode, depth ); + + const noiseResolution = textureSize( this.noiseNode, 0 ); + let noiseUv = vec2( uvNode.x, uvNode.y.oneMinus() ); + noiseUv = noiseUv.mul( this._resolution.div( noiseResolution ) ); + const noiseTexel = sampleNoise( noiseUv ); + + const x = sin( noiseTexel.element( this.index.mod( 4 ).mul( 2 ).mul( PI ) ) ); + const y = cos( noiseTexel.element( this.index.mod( 4 ).mul( 2 ).mul( PI ) ) ); + + const noiseVec = vec2( x, y ); + const rotationMatrix = mat2( noiseVec.x, noiseVec.y.negate(), noiseVec.x, noiseVec.y ); + + const totalWeight = float( 1.0 ).toVar(); + const denoised = vec3( texel.rgb ).toVar(); + + Loop( { start: int( 0 ), end: int( 16 ), type: 'int', condition: '<' }, ( { i } ) => { + + const sampleDir = this._sampleVectors.element( i ).toVar(); + const offset = rotationMatrix.mul( sampleDir.xy.mul( float( 1.0 ).add( sampleDir.z.mul( this.radius.sub( 1 ) ) ) ) ).div( this._resolution ).toVar(); + const sampleUv = uvNode.add( offset ).toVar(); + + const result = denoiseSample( center, viewNormal, viewPosition, sampleUv ); + + denoised.addAssign( result.xyz ); + totalWeight.addAssign( result.w ); + + } ); + + If( totalWeight.greaterThan( float( 0 ) ), () => { + + denoised.divAssign( totalWeight ); + + } ); + + return vec4( denoised, texel.a ); + + } ).setLayout( { + name: 'denoise', + type: 'vec4', + inputs: [ + { name: 'uv', type: 'vec2' } + ] + } ); + + const output = Fn( () => { + + return denoise( uvNode ); + + } ); + + const outputNode = output(); + + return outputNode; + + } + +} + +function generatePdSamplePointInitializer( samples, rings, radiusExponent ) { + + const poissonDisk = generateDenoiseSamples( samples, rings, radiusExponent ); + + const array = []; + + for ( let i = 0; i < samples; i ++ ) { + + const sample = poissonDisk[ i ]; + array.push( sample ); + + } + + return array; + +} + +function generateDenoiseSamples( numSamples, numRings, radiusExponent ) { + + const samples = []; + + for ( let i = 0; i < numSamples; i ++ ) { + + const angle = 2 * Math.PI * numRings * i / numSamples; + const radius = Math.pow( i / ( numSamples - 1 ), radiusExponent ); + samples.push( new Vector3( Math.cos( angle ), Math.sin( angle ), radius ) ); + + } + + return samples; + +} + +const denoise = ( node, depthNode, normalNode, noiseNode, camera ) => nodeObject( new DenoiseNode( convertToTexture( node ), nodeObject( depthNode ), nodeObject( normalNode ), nodeObject( noiseNode ), camera ) ); + +class FXAANode extends TempNode { + + static get type() { + + return 'FXAANode'; + + } + + constructor( textureNode ) { + + super(); + + this.textureNode = textureNode; + + this.updateBeforeType = NodeUpdateType.RENDER; + + this._invSize = uniform( new Vector2() ); + + } + + updateBefore() { + + const map = this.textureNode.value; + + this._invSize.value.set( 1 / map.image.width, 1 / map.image.height ); + + } + + setup() { + + const textureNode = this.textureNode.bias( - 100 ); + const uvNode = textureNode.uvNode || uv(); + + // FXAA 3.11 implementation by NVIDIA, ported to WebGL by Agost Biro (biro@archilogic.com) + + //---------------------------------------------------------------------------------- + // File: es3-kepler\FXAA\assets\shaders/FXAA_DefaultES.frag + // SDK Version: v3.00 + // Email: gameworks@nvidia.com + // Site: http://developer.nvidia.com/ + // + // Copyright (c) 2014-2015, NVIDIA CORPORATION. All rights reserved. + // + // Redistribution and use in source and binary forms, with or without + // modification, are permitted provided that the following conditions + // are met: + // * Redistributions of source code must retain the above copyright + // notice, this list of conditions and the following disclaimer. + // * Redistributions in binary form must reproduce the above copyright + // notice, this list of conditions and the following disclaimer in the + // documentation and/or other materials provided with the distribution. + // * Neither the name of NVIDIA CORPORATION nor the names of its + // contributors may be used to endorse or promote products derived + // from this software without specific prior written permission. + // + // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + // PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + // CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + // EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + // PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY + // OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + // + //---------------------------------------------------------------------------------- + + const FxaaTexTop = ( p ) => textureNode.uv( p ); + const FxaaTexOff = ( p, o, r ) => textureNode.uv( p.add( o.mul( r ) ) ); + + const NUM_SAMPLES = int( 5 ); + + const contrast = Fn( ( [ a_immutable, b_immutable ] ) => { + + // assumes colors have premultipliedAlpha, so that the calculated color contrast is scaled by alpha + + const b = vec4( b_immutable ).toVar(); + const a = vec4( a_immutable ).toVar(); + const diff = vec4( abs( a.sub( b ) ) ).toVar(); + + return max$1( max$1( max$1( diff.r, diff.g ), diff.b ), diff.a ); + + } ); + + // FXAA3 QUALITY - PC + + const FxaaPixelShader = Fn( ( [ uv, fxaaQualityRcpFrame, fxaaQualityEdgeThreshold, fxaaQualityinvEdgeThreshold ] ) => { + + const rgbaM = FxaaTexTop( uv ).toVar(); + const rgbaS = FxaaTexOff( uv, vec2( 0.0, - 1.0 ), fxaaQualityRcpFrame.xy ).toVar(); + const rgbaE = FxaaTexOff( uv, vec2( 1.0, 0.0 ), fxaaQualityRcpFrame.xy ).toVar(); + const rgbaN = FxaaTexOff( uv, vec2( 0.0, 1.0 ), fxaaQualityRcpFrame.xy ).toVar(); + const rgbaW = FxaaTexOff( uv, vec2( - 1.0, 0.0 ), fxaaQualityRcpFrame.xy ).toVar(); + // . S . + // W M E + // . N . + + const contrastN = contrast( rgbaM, rgbaN ).toVar(); + const contrastS = contrast( rgbaM, rgbaS ).toVar(); + const contrastE = contrast( rgbaM, rgbaE ).toVar(); + const contrastW = contrast( rgbaM, rgbaW ).toVar(); + + const maxValue = max$1( contrastN, max$1( contrastS, max$1( contrastE, contrastW ) ) ).toVar(); + + // . 0 . + // 0 0 0 + // . 0 . + + If( maxValue.lessThan( fxaaQualityEdgeThreshold ), () => { + + return rgbaM; // assuming define FXAA_DISCARD is always 0 + + } ); + + // + + const relativeVContrast = sub( contrastN.add( contrastS ), ( contrastE.add( contrastW ) ) ).toVar(); + relativeVContrast.mulAssign( fxaaQualityinvEdgeThreshold ); + + // 45 deg edge detection and corners of objects, aka V/H contrast is too similar + + If( abs( relativeVContrast ).lessThan( 0.3 ), () => { + + // locate the edge + + const x = contrastE.greaterThan( contrastW ).select( 1, - 1 ).toVar(); + const y = contrastS.greaterThan( contrastN ).select( 1, - 1 ).toVar(); + + const dirToEdge = vec2( x, y ).toVar(); + // . 2 . . 1 . + // 1 0 2 ~= 0 0 1 + // . 1 . . 0 . + + // tap 2 pixels and see which ones are "outside" the edge, to + // determine if the edge is vertical or horizontal + + const rgbaAlongH = FxaaTexOff( uv, vec2( dirToEdge.x, dirToEdge.y ), fxaaQualityRcpFrame.xy ); + const matchAlongH = contrast( rgbaM, rgbaAlongH ).toVar(); + // . 1 . + // 0 0 1 + // . 0 H + + const rgbaAlongV = FxaaTexOff( uv, vec2( dirToEdge.x.negate(), dirToEdge.y.negate() ), fxaaQualityRcpFrame.xy ); + const matchAlongV = contrast( rgbaM, rgbaAlongV ).toVar(); + // V 1 . + // 0 0 1 + // . 0 . + + relativeVContrast.assign( matchAlongV.sub( matchAlongH ) ); + relativeVContrast.mulAssign( fxaaQualityinvEdgeThreshold ); + + If( abs( relativeVContrast ).lessThan( 0.3 ), () => { // 45 deg edge + + // 1 1 . + // 0 0 1 + // . 0 1 + + // do a simple blur + const sum = rgbaN.add( rgbaS ).add( rgbaE ).add( rgbaW ); + return mix( rgbaM, sum.mul( 0.25 ), 0.4 ); + + } ); + + } ); + + const offNP = vec2().toVar(); + + If( relativeVContrast.lessThanEqual( 0 ), () => { + + rgbaN.assign( rgbaW ); + rgbaS.assign( rgbaE ); + + // . 0 . 1 + // 1 0 1 -> 0 + // . 0 . 1 + + offNP.x.assign( 0 ); + offNP.y.assign( fxaaQualityRcpFrame.y ); + + } ).Else( () => { + + offNP.x.assign( fxaaQualityRcpFrame.x ); + offNP.y.assign( 0 ); + + } ); + + const mn = contrast( rgbaM, rgbaN ).toVar(); + const ms = contrast( rgbaM, rgbaS ).toVar(); + + If( mn.lessThanEqual( ms ), () => { + + rgbaN.assign( rgbaS ); + + } ); + + const doneN = int( 0 ).toVar(); + const doneP = int( 0 ).toVar(); + + const nDist = float( 0 ).toVar(); + const pDist = float( 0 ).toVar(); + + const posN = vec2( uv ).toVar(); + const posP = vec2( uv ).toVar(); + + const iterationsUsedN = int( 0 ).toVar(); + const iterationsUsedP = int( 0 ).toVar(); + + Loop( NUM_SAMPLES, ( { i } ) => { + + const increment = i.add( 1 ).toVar(); + + If( doneN.equal( 0 ), () => { + + nDist.addAssign( increment ); + posN.assign( uv.add( offNP.mul( nDist ) ) ); + const rgbaEndN = FxaaTexTop( posN.xy ); + + const nm = contrast( rgbaEndN, rgbaM ).toVar(); + const nn = contrast( rgbaEndN, rgbaN ).toVar(); + + If( nm.greaterThan( nn ), () => { + + doneN.assign( 1 ); + + } ); + + iterationsUsedN.assign( i ); + + } ); + + If( doneP.equal( 0 ), () => { + + pDist.addAssign( increment ); + posP.assign( uv.sub( offNP.mul( pDist ) ) ); + const rgbaEndP = FxaaTexTop( posP.xy ); + + const pm = contrast( rgbaEndP, rgbaM ).toVar(); + const pn = contrast( rgbaEndP, rgbaN ).toVar(); + + If( pm.greaterThan( pn ), () => { + + doneP.assign( 1 ); + + } ); + + iterationsUsedP.assign( i ); + + } ); + + If( doneN.equal( 1 ).or( doneP.equal( 1 ) ), () => { + + Break(); + + } ); + + } ); + + If( doneN.equal( 0 ).and( doneP.equal( 0 ) ), () => { + + return rgbaM; // failed to find end of edge + + } ); + + const distN = float( 1 ).toVar(); + const distP = float( 1 ).toVar(); + + If( doneN.equal( 1 ), () => { + + distN.assign( float( iterationsUsedN ).div( float( NUM_SAMPLES.sub( 1 ) ) ) ); + + } ); + + If( doneP.equal( 1 ), () => { + + distP.assign( float( iterationsUsedP ).div( float( NUM_SAMPLES.sub( 1 ) ) ) ); + + } ); + + const dist = min$1( distN, distP ); + + // hacky way of reduces blurriness of mostly diagonal edges + // but reduces AA quality + dist.assign( pow( dist, 0.5 ) ); + dist.assign( float( 1 ).sub( dist ) ); + + return mix( rgbaM, rgbaN, dist.mul( 0.5 ) ); + + } ).setLayout( { + name: 'FxaaPixelShader', + type: 'vec4', + inputs: [ + { name: 'uv', type: 'vec2' }, + { name: 'fxaaQualityRcpFrame', type: 'vec2' }, + { name: 'fxaaQualityEdgeThreshold', type: 'float' }, + { name: 'fxaaQualityinvEdgeThreshold', type: 'float' }, + ] + } ); + + const fxaa = Fn( () => { + + const edgeDetectionQuality = float( 0.2 ); + const invEdgeDetectionQuality = float( 1 ).div( edgeDetectionQuality ); + + return FxaaPixelShader( uvNode, this._invSize, edgeDetectionQuality, invEdgeDetectionQuality ); + + } ); + + const outputNode = fxaa(); + + return outputNode; + + } + +} + +const fxaa = ( node ) => nodeObject( new FXAANode( convertToTexture( node ) ) ); + +const _quadMesh$3 = /*@__PURE__*/ new QuadMesh(); + +const _clearColor$1 = /*@__PURE__*/ new Color( 0, 0, 0 ); +const _currentClearColor = /*@__PURE__*/ new Color(); +const _size$4 = /*@__PURE__*/ new Vector2(); + +const _BlurDirectionX = /*@__PURE__*/ new Vector2( 1.0, 0.0 ); +const _BlurDirectionY = /*@__PURE__*/ new Vector2( 0.0, 1.0 ); + +class BloomNode extends TempNode { + + static get type() { + + return 'BloomNode'; + + } + + constructor( inputNode, strength = 1, radius = 0, threshold = 0 ) { + + super(); + + this.inputNode = inputNode; + this.strength = uniform( strength ); + this.radius = uniform( radius ); + this.threshold = uniform( threshold ); + + this.smoothWidth = uniform( 0.01 ); + + // + + this._renderTargetsHorizontal = []; + this._renderTargetsVertical = []; + this._nMips = 5; + + // render targets + + this._renderTargetBright = new RenderTarget( 1, 1, { type: HalfFloatType } ); + this._renderTargetBright.texture.name = 'UnrealBloomPass.bright'; + this._renderTargetBright.texture.generateMipmaps = false; + + for ( let i = 0; i < this._nMips; i ++ ) { + + const renderTargetHorizontal = new RenderTarget( 1, 1, { type: HalfFloatType } ); + + renderTargetHorizontal.texture.name = 'UnrealBloomPass.h' + i; + renderTargetHorizontal.texture.generateMipmaps = false; + + this._renderTargetsHorizontal.push( renderTargetHorizontal ); + + const renderTargetVertical = new RenderTarget( 1, 1, { type: HalfFloatType } ); + + renderTargetVertical.texture.name = 'UnrealBloomPass.v' + i; + renderTargetVertical.texture.generateMipmaps = false; + + this._renderTargetsVertical.push( renderTargetVertical ); + + } + + // materials + + this._compositeMaterial = null; + this._highPassFilterMaterial = null; + this._separableBlurMaterials = []; + + // pass and texture nodes + + this._textureNodeBright = texture( this._renderTargetBright.texture ); + this._textureNodeBlur0 = texture( this._renderTargetsVertical[ 0 ].texture ); + this._textureNodeBlur1 = texture( this._renderTargetsVertical[ 1 ].texture ); + this._textureNodeBlur2 = texture( this._renderTargetsVertical[ 2 ].texture ); + this._textureNodeBlur3 = texture( this._renderTargetsVertical[ 3 ].texture ); + this._textureNodeBlur4 = texture( this._renderTargetsVertical[ 4 ].texture ); + + this._textureOutput = passTexture( this, this._renderTargetsHorizontal[ 0 ].texture ); + + this.updateBeforeType = NodeUpdateType.FRAME; + + } + + getTextureNode() { + + return this._textureOutput; + + } + + setSize( width, height ) { + + let resx = Math.round( width / 2 ); + let resy = Math.round( height / 2 ); + + this._renderTargetBright.setSize( resx, resy ); + + for ( let i = 0; i < this._nMips; i ++ ) { + + this._renderTargetsHorizontal[ i ].setSize( resx, resy ); + this._renderTargetsVertical[ i ].setSize( resx, resy ); + + this._separableBlurMaterials[ i ].invSize.value.set( 1 / resx, 1 / resy ); + + resx = Math.round( resx / 2 ); + resy = Math.round( resy / 2 ); + + } + + } + + updateBefore( frame ) { + + const { renderer } = frame; + + const size = renderer.getDrawingBufferSize( _size$4 ); + this.setSize( size.width, size.height ); + + const currentRenderTarget = renderer.getRenderTarget(); + const currentMRT = renderer.getMRT(); + renderer.getClearColor( _currentClearColor ); + const currentClearAlpha = renderer.getClearAlpha(); + + this.setSize( size.width, size.height ); + + renderer.setMRT( null ); + renderer.setClearColor( _clearColor$1, 0 ); + + // 1. Extract Bright Areas + + renderer.setRenderTarget( this._renderTargetBright ); + _quadMesh$3.material = this._highPassFilterMaterial; + _quadMesh$3.render( renderer ); + + // 2. Blur All the mips progressively + + let inputRenderTarget = this._renderTargetBright; + + for ( let i = 0; i < this._nMips; i ++ ) { + + _quadMesh$3.material = this._separableBlurMaterials[ i ]; + + this._separableBlurMaterials[ i ].colorTexture.value = inputRenderTarget.texture; + this._separableBlurMaterials[ i ].direction.value = _BlurDirectionX; + renderer.setRenderTarget( this._renderTargetsHorizontal[ i ] ); + renderer.clear(); + _quadMesh$3.render( renderer ); + + this._separableBlurMaterials[ i ].colorTexture.value = this._renderTargetsHorizontal[ i ].texture; + this._separableBlurMaterials[ i ].direction.value = _BlurDirectionY; + renderer.setRenderTarget( this._renderTargetsVertical[ i ] ); + renderer.clear(); + _quadMesh$3.render( renderer ); + + inputRenderTarget = this._renderTargetsVertical[ i ]; + + } + + // 3. Composite All the mips + + renderer.setRenderTarget( this._renderTargetsHorizontal[ 0 ] ); + renderer.clear(); + _quadMesh$3.material = this._compositeMaterial; + _quadMesh$3.render( renderer ); + + // restore + + renderer.setRenderTarget( currentRenderTarget ); + renderer.setMRT( currentMRT ); + renderer.setClearColor( _currentClearColor, currentClearAlpha ); + + } + + setup( builder ) { + + // luminosity high pass material + + const luminosityHighPass = Fn( () => { + + const texel = this.inputNode; + const v = luminance( texel.rgb ); + + const alpha = smoothstep( this.threshold, this.threshold.add( this.smoothWidth ), v ); + + return mix( vec4( 0 ), texel, alpha ); + + } ); + + this._highPassFilterMaterial = this._highPassFilterMaterial || new NodeMaterial(); + this._highPassFilterMaterial.fragmentNode = luminosityHighPass().context( builder.getSharedContext() ); + this._highPassFilterMaterial.name = 'Bloom_highPass'; + this._highPassFilterMaterial.needsUpdate = true; + + // gaussian blur materials + + const kernelSizeArray = [ 3, 5, 7, 9, 11 ]; + + for ( let i = 0; i < this._nMips; i ++ ) { + + this._separableBlurMaterials.push( this._getSeperableBlurMaterial( builder, kernelSizeArray[ i ] ) ); + + } + + // composite material + + const bloomFactors = uniformArray( [ 1.0, 0.8, 0.6, 0.4, 0.2 ] ); + const bloomTintColors = uniformArray( [ new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ), new Vector3( 1, 1, 1 ) ] ); + + const lerpBloomFactor = Fn( ( [ factor, radius ] ) => { + + const mirrorFactor = float( 1.2 ).sub( factor ); + return mix( factor, mirrorFactor, radius ); + + } ).setLayout( { + name: 'lerpBloomFactor', + type: 'float', + inputs: [ + { name: 'factor', type: 'float' }, + { name: 'radius', type: 'float' }, + ] + } ); + + + const compositePass = Fn( () => { + + const color0 = lerpBloomFactor( bloomFactors.element( 0 ), this.radius ).mul( vec4( bloomTintColors.element( 0 ), 1.0 ) ).mul( this._textureNodeBlur0 ); + const color1 = lerpBloomFactor( bloomFactors.element( 1 ), this.radius ).mul( vec4( bloomTintColors.element( 1 ), 1.0 ) ).mul( this._textureNodeBlur1 ); + const color2 = lerpBloomFactor( bloomFactors.element( 2 ), this.radius ).mul( vec4( bloomTintColors.element( 2 ), 1.0 ) ).mul( this._textureNodeBlur2 ); + const color3 = lerpBloomFactor( bloomFactors.element( 3 ), this.radius ).mul( vec4( bloomTintColors.element( 3 ), 1.0 ) ).mul( this._textureNodeBlur3 ); + const color4 = lerpBloomFactor( bloomFactors.element( 4 ), this.radius ).mul( vec4( bloomTintColors.element( 4 ), 1.0 ) ).mul( this._textureNodeBlur4 ); + + const sum = color0.add( color1 ).add( color2 ).add( color3 ).add( color4 ); + + return sum.mul( this.strength ); + + } ); + + this._compositeMaterial = this._compositeMaterial || new NodeMaterial(); + this._compositeMaterial.fragmentNode = compositePass().context( builder.getSharedContext() ); + this._compositeMaterial.name = 'Bloom_comp'; + this._compositeMaterial.needsUpdate = true; + + // + + return this._textureOutput; + + } + + dispose() { + + for ( let i = 0; i < this._renderTargetsHorizontal.length; i ++ ) { + + this._renderTargetsHorizontal[ i ].dispose(); + + } + + for ( let i = 0; i < this._renderTargetsVertical.length; i ++ ) { + + this._renderTargetsVertical[ i ].dispose(); + + } + + this._renderTargetBright.dispose(); + + } + + _getSeperableBlurMaterial( builder, kernelRadius ) { + + const coefficients = []; + + for ( let i = 0; i < kernelRadius; i ++ ) { + + coefficients.push( 0.39894 * Math.exp( - 0.5 * i * i / ( kernelRadius * kernelRadius ) ) / kernelRadius ); + + } + + // + + const colorTexture = texture(); + const gaussianCoefficients = uniformArray( coefficients ); + const invSize = uniform( new Vector2() ); + const direction = uniform( new Vector2( 0.5, 0.5 ) ); + + const uvNode = uv(); + const sampleTexel = ( uv ) => colorTexture.uv( uv ); + + const seperableBlurPass = Fn( () => { + + const weightSum = gaussianCoefficients.element( 0 ).toVar(); + const diffuseSum = sampleTexel( uvNode ).rgb.mul( weightSum ).toVar(); + + Loop( { start: int( 1 ), end: int( kernelRadius ), type: 'int', condition: '<' }, ( { i } ) => { + + const x = float( i ); + const w = gaussianCoefficients.element( i ); + const uvOffset = direction.mul( invSize ).mul( x ); + const sample1 = sampleTexel( uvNode.add( uvOffset ) ).rgb; + const sample2 = sampleTexel( uvNode.sub( uvOffset ) ).rgb; + diffuseSum.addAssign( add( sample1, sample2 ).mul( w ) ); + weightSum.addAssign( float( 2.0 ).mul( w ) ); + + } ); + + return vec4( diffuseSum.div( weightSum ), 1.0 ); + + } ); + + const seperableBlurMaterial = new NodeMaterial(); + seperableBlurMaterial.fragmentNode = seperableBlurPass().context( builder.getSharedContext() ); + seperableBlurMaterial.name = 'Bloom_seperable'; + seperableBlurMaterial.needsUpdate = true; + + // uniforms + seperableBlurMaterial.colorTexture = colorTexture; + seperableBlurMaterial.direction = direction; + seperableBlurMaterial.invSize = invSize; + + return seperableBlurMaterial; + + } + +} + +const bloom = ( node, strength, radius, threshold ) => nodeObject( new BloomNode( nodeObject( node ), strength, radius, threshold ) ); + +class TransitionNode extends TempNode { + + static get type() { + + return 'TransitionNode'; + + } + + constructor( textureNodeA, textureNodeB, mixTextureNode, mixRatioNode, thresholdNode, useTextureNode ) { + + super(); + + // Input textures + + this.textureNodeA = textureNodeA; + this.textureNodeB = textureNodeB; + this.mixTextureNode = mixTextureNode; + + // Uniforms + + this.mixRatioNode = mixRatioNode; + this.thresholdNode = thresholdNode; + this.useTextureNode = useTextureNode; + + } + + setup() { + + const { textureNodeA, textureNodeB, mixTextureNode, mixRatioNode, thresholdNode, useTextureNode } = this; + + const sampleTexture = ( textureNode ) => { + + const uvNodeTexture = textureNode.uvNode || uv(); + return textureNode.uv( uvNodeTexture ); + + }; + + const transition = Fn( () => { + + const texelOne = sampleTexture( textureNodeA ); + const texelTwo = sampleTexture( textureNodeB ); + + const color = vec4().toVar(); + + If( useTextureNode.equal( int( 1 ) ), () => { + + const transitionTexel = sampleTexture( mixTextureNode ); + const r = mixRatioNode.mul( thresholdNode.mul( 2.0 ).add( 1.0 ) ).sub( thresholdNode ); + const mixf = clamp( sub( transitionTexel.r, r ).mul( float( 1.0 ).div( thresholdNode ) ), 0.0, 1.0 ); + + color.assign( mix( texelOne, texelTwo, mixf ) ); + + } ).Else( () => { + + color.assign( mix( texelTwo, texelOne, mixRatioNode ) ); + + } ); + + return color; + + } ); + + const outputNode = transition(); + + return outputNode; + + } + +} + +const transition = ( nodeA, nodeB, mixTexture, mixRatio = 0.0, threshold = 0.1, useTexture = 0 ) => nodeObject( new TransitionNode( convertToTexture( nodeA ), convertToTexture( nodeB ), convertToTexture( mixTexture ), nodeObject( mixRatio ), nodeObject( threshold ), nodeObject( useTexture ) ) ); + +class PixelationNode extends TempNode { + + static get type() { + + return 'PixelationNode'; + + } + + constructor( textureNode, depthNode, normalNode, pixelSize, normalEdgeStrength, depthEdgeStrength ) { + + super(); + + // Input textures + + this.textureNode = textureNode; + this.depthNode = depthNode; + this.normalNode = normalNode; + + // Input uniforms + + this.pixelSize = pixelSize; + this.normalEdgeStrength = normalEdgeStrength; + this.depthEdgeStrength = depthEdgeStrength; + + // Private uniforms + + this._resolution = uniform( new Vector4() ); + + this.updateBeforeType = NodeUpdateType.RENDER; + + } + + updateBefore() { + + const map = this.textureNode.value; + + const width = map.image.width; + const height = map.image.height; + + this._resolution.value.set( width, height, 1 / width, 1 / height ); + + } + + setup() { + + const { textureNode, depthNode, normalNode } = this; + + const uvNodeTexture = textureNode.uvNode || uv(); + const uvNodeDepth = depthNode.uvNode || uv(); + const uvNodeNormal = normalNode.uvNode || uv(); + + const sampleTexture = () => textureNode.uv( uvNodeTexture ); + + const sampleDepth = ( x, y ) => depthNode.uv( uvNodeDepth.add( vec2( x, y ).mul( this._resolution.zw ) ) ).r; + + const sampleNormal = ( x, y ) => normalNode.uv( uvNodeNormal.add( vec2( x, y ).mul( this._resolution.zw ) ) ).rgb.normalize(); + + const depthEdgeIndicator = ( depth ) => { + + const diff = property( 'float', 'diff' ); + diff.addAssign( clamp( sampleDepth( 1, 0 ).sub( depth ) ) ); + diff.addAssign( clamp( sampleDepth( - 1, 0 ).sub( depth ) ) ); + diff.addAssign( clamp( sampleDepth( 0, 1 ).sub( depth ) ) ); + diff.addAssign( clamp( sampleDepth( 0, - 1 ).sub( depth ) ) ); + + return floor( smoothstep( 0.01, 0.02, diff ).mul( 2 ) ).div( 2 ); + + }; + + const neighborNormalEdgeIndicator = ( x, y, depth, normal ) => { + + const depthDiff = sampleDepth( x, y ).sub( depth ); + const neighborNormal = sampleNormal( x, y ); + + // Edge pixels should yield to faces who's normals are closer to the bias normal. + + const normalEdgeBias = vec3( 1, 1, 1 ); // This should probably be a parameter. + const normalDiff = dot( normal.sub( neighborNormal ), normalEdgeBias ); + const normalIndicator = clamp( smoothstep( - 0.01, 0.01, normalDiff ), 0.0, 1.0 ); + + // Only the shallower pixel should detect the normal edge. + + const depthIndicator = clamp( sign( depthDiff.mul( .25 ).add( .0025 ) ), 0.0, 1.0 ); + + return float( 1.0 ).sub( dot( normal, neighborNormal ) ).mul( depthIndicator ).mul( normalIndicator ); + + }; + + const normalEdgeIndicator = ( depth, normal ) => { + + const indicator = property( 'float', 'indicator' ); + + indicator.addAssign( neighborNormalEdgeIndicator( 0, - 1, depth, normal ) ); + indicator.addAssign( neighborNormalEdgeIndicator( 0, 1, depth, normal ) ); + indicator.addAssign( neighborNormalEdgeIndicator( - 1, 0, depth, normal ) ); + indicator.addAssign( neighborNormalEdgeIndicator( 1, 0, depth, normal ) ); + + return step( 0.1, indicator ); + + }; + + const pixelation = Fn( () => { + + const texel = sampleTexture(); + + const depth = property( 'float', 'depth' ); + const normal = property( 'vec3', 'normal' ); + + If( this.depthEdgeStrength.greaterThan( 0.0 ).or( this.normalEdgeStrength.greaterThan( 0.0 ) ), () => { + + depth.assign( sampleDepth( 0, 0 ) ); + normal.assign( sampleNormal( 0, 0 ) ); + + } ); + + const dei = property( 'float', 'dei' ); + + If( this.depthEdgeStrength.greaterThan( 0.0 ), () => { + + dei.assign( depthEdgeIndicator( depth ) ); + + } ); + + const nei = property( 'float', 'nei' ); + + If( this.normalEdgeStrength.greaterThan( 0.0 ), () => { + + nei.assign( normalEdgeIndicator( depth, normal ) ); + + } ); + + const strength = dei.greaterThan( 0 ).select( float( 1.0 ).sub( dei.mul( this.depthEdgeStrength ) ), nei.mul( this.normalEdgeStrength ).add( 1 ) ); + + return texel.mul( strength ); + + } ); + + const outputNode = pixelation(); + + return outputNode; + + } + +} + +const pixelation = ( node, depthNode, normalNode, pixelSize = 6, normalEdgeStrength = 0.3, depthEdgeStrength = 0.4 ) => nodeObject( new PixelationNode( convertToTexture( node ), convertToTexture( depthNode ), convertToTexture( normalNode ), nodeObject( pixelSize ), nodeObject( normalEdgeStrength ), nodeObject( depthEdgeStrength ) ) ); + +class PixelationPassNode extends PassNode { + + static get type() { + + return 'PixelationPassNode'; + + } + + constructor( scene, camera, pixelSize = 6, normalEdgeStrength = 0.3, depthEdgeStrength = 0.4 ) { + + super( 'color', scene, camera, { minFilter: NearestFilter, magFilter: NearestFilter } ); + + this.pixelSize = pixelSize; + this.normalEdgeStrength = normalEdgeStrength; + this.depthEdgeStrength = depthEdgeStrength; + + this.isPixelationPassNode = true; + + this._mrt = mrt( { + output: output, + normal: normalView + } ); + + } + + setSize( width, height ) { + + const pixelSize = this.pixelSize.value ? this.pixelSize.value : this.pixelSize; + + const adjustedWidth = Math.floor( width / pixelSize ); + const adjustedHeight = Math.floor( height / pixelSize ); + + super.setSize( adjustedWidth, adjustedHeight ); + + } + + setup() { + + const color = super.getTextureNode( 'output' ); + const depth = super.getTextureNode( 'depth' ); + const normal = super.getTextureNode( 'normal' ); + + return pixelation( color, depth, normal, this.pixelSize, this.normalEdgeStrength, this.depthEdgeStrength ); + + } + +} + +const pixelationPass = ( scene, camera, pixelSize, normalEdgeStrength, depthEdgeStrength ) => nodeObject( new PixelationPassNode( scene, camera, pixelSize, normalEdgeStrength, depthEdgeStrength ) ); + +const _size$3 = /*@__PURE__*/ new Vector2(); + +/** +* +* Supersample Anti-Aliasing Render Pass +* +* This manual approach to SSAA re-renders the scene ones for each sample with camera jitter and accumulates the results. +* +* References: https://en.wikipedia.org/wiki/Supersampling +* +*/ + +class SSAAPassNode extends PassNode { + + static get type() { + + return 'SSAAPassNode'; + + } + + constructor( scene, camera ) { + + super( PassNode.COLOR, scene, camera ); + + this.isSSAAPassNode = true; + + this.sampleLevel = 4; // specified as n, where the number of samples is 2^n, so sampleLevel = 4, is 2^4 samples, 16. + this.unbiased = true; + this.clearColor = new Color( 0x000000 ); + this.clearAlpha = 0; + + this._currentClearColor = new Color(); + + this.sampleWeight = uniform( 1 ); + + this.sampleRenderTarget = null; + + this._quadMesh = new QuadMesh(); + + } + + updateBefore( frame ) { + + const { renderer } = frame; + const { scene, camera } = this; + + this._pixelRatio = renderer.getPixelRatio(); + + const size = renderer.getSize( _size$3 ); + + this.setSize( size.width, size.height ); + this.sampleRenderTarget.setSize( this.renderTarget.width, this.renderTarget.height ); + + // save current renderer settings + + renderer.getClearColor( this._currentClearColor ); + const currentClearAlpha = renderer.getClearAlpha(); + const currentRenderTarget = renderer.getRenderTarget(); + const currentMRT = renderer.getMRT(); + const currentAutoClear = renderer.autoClear; + + // + + this._cameraNear.value = camera.near; + this._cameraFar.value = camera.far; + + renderer.setMRT( this.getMRT() ); + renderer.autoClear = false; + + const jitterOffsets = _JitterVectors[ Math.max( 0, Math.min( this.sampleLevel, 5 ) ) ]; + + const baseSampleWeight = 1.0 / jitterOffsets.length; + const roundingRange = 1 / 32; + + const viewOffset = { + + fullWidth: this.renderTarget.width, + fullHeight: this.renderTarget.height, + offsetX: 0, + offsetY: 0, + width: this.renderTarget.width, + height: this.renderTarget.height + + }; + + const originalViewOffset = Object.assign( {}, camera.view ); + + if ( originalViewOffset.enabled ) Object.assign( viewOffset, originalViewOffset ); + + // render the scene multiple times, each slightly jitter offset from the last and accumulate the results. + + for ( let i = 0; i < jitterOffsets.length; i ++ ) { + + const jitterOffset = jitterOffsets[ i ]; + + if ( camera.setViewOffset ) { + + camera.setViewOffset( + + viewOffset.fullWidth, viewOffset.fullHeight, + + viewOffset.offsetX + jitterOffset[ 0 ] * 0.0625, viewOffset.offsetY + jitterOffset[ 1 ] * 0.0625, // 0.0625 = 1 / 16 + + viewOffset.width, viewOffset.height + + ); + + } + + this.sampleWeight.value = baseSampleWeight; + + if ( this.unbiased ) { + + // the theory is that equal weights for each sample lead to an accumulation of rounding errors. + // The following equation varies the sampleWeight per sample so that it is uniformly distributed + // across a range of values whose rounding errors cancel each other out. + + const uniformCenteredDistribution = ( - 0.5 + ( i + 0.5 ) / jitterOffsets.length ); + this.sampleWeight.value += roundingRange * uniformCenteredDistribution; + + } + + renderer.setClearColor( this.clearColor, this.clearAlpha ); + renderer.setRenderTarget( this.sampleRenderTarget ); + renderer.clear(); + renderer.render( scene, camera ); + + // accumulation + + renderer.setRenderTarget( this.renderTarget ); + + if ( i === 0 ) { + + renderer.setClearColor( 0x000000, 0.0 ); + renderer.clear(); + + } + + this._quadMesh.render( renderer ); + + } + + renderer.copyTextureToTexture( this.sampleRenderTarget.depthTexture, this.renderTarget.depthTexture ); + + // restore + + if ( camera.setViewOffset && originalViewOffset.enabled ) { + + camera.setViewOffset( + + originalViewOffset.fullWidth, originalViewOffset.fullHeight, + + originalViewOffset.offsetX, originalViewOffset.offsetY, + + originalViewOffset.width, originalViewOffset.height + + ); + + } else if ( camera.clearViewOffset ) { + + camera.clearViewOffset(); + + } + + renderer.setRenderTarget( currentRenderTarget ); + renderer.setMRT( currentMRT ); + + renderer.autoClear = currentAutoClear; + renderer.setClearColor( this._currentClearColor, currentClearAlpha ); + + } + + setup( builder ) { + + if ( this.sampleRenderTarget === null ) { + + this.sampleRenderTarget = this.renderTarget.clone(); + + } + + let sampleTexture; + + const passMRT = this.getMRT(); + + if ( passMRT !== null ) { + + const outputs = {}; + + for ( const name in passMRT.outputNodes ) { + + const index = getTextureIndex( this.sampleRenderTarget.textures, name ); + + if ( index >= 0 ) { + + outputs[ name ] = texture( this.sampleRenderTarget.textures[ index ] ).mul( this.sampleWeight ); + + } + + } + + sampleTexture = mrt( outputs ); + + } else { + + sampleTexture = texture( this.sampleRenderTarget.texture ).mul( this.sampleWeight ); + + } + + this._quadMesh.material = new NodeMaterial(); + this._quadMesh.material.fragmentNode = sampleTexture; + this._quadMesh.material.transparent = true; + this._quadMesh.material.depthTest = false; + this._quadMesh.material.depthWrite = false; + this._quadMesh.material.premultipliedAlpha = true; + this._quadMesh.material.blending = AdditiveBlending; + this._quadMesh.material.normals = false; + this._quadMesh.material.name = 'SSAA'; + + return super.setup( builder ); + + } + + dispose() { + + super.dispose(); + + if ( this.sampleRenderTarget !== null ) { + + this.sampleRenderTarget.dispose(); + + } + + } + +} + +// These jitter vectors are specified in integers because it is easier. +// I am assuming a [-8,8) integer grid, but it needs to be mapped onto [-0.5,0.5) +// before being used, thus these integers need to be scaled by 1/16. +// +// Sample patterns reference: https://msdn.microsoft.com/en-us/library/windows/desktop/ff476218%28v=vs.85%29.aspx?f=255&MSPPError=-2147217396 +const _JitterVectors = [ + [ + [ 0, 0 ] + ], + [ + [ 4, 4 ], [ - 4, - 4 ] + ], + [ + [ - 2, - 6 ], [ 6, - 2 ], [ - 6, 2 ], [ 2, 6 ] + ], + [ + [ 1, - 3 ], [ - 1, 3 ], [ 5, 1 ], [ - 3, - 5 ], + [ - 5, 5 ], [ - 7, - 1 ], [ 3, 7 ], [ 7, - 7 ] + ], + [ + [ 1, 1 ], [ - 1, - 3 ], [ - 3, 2 ], [ 4, - 1 ], + [ - 5, - 2 ], [ 2, 5 ], [ 5, 3 ], [ 3, - 5 ], + [ - 2, 6 ], [ 0, - 7 ], [ - 4, - 6 ], [ - 6, 4 ], + [ - 8, 0 ], [ 7, - 4 ], [ 6, 7 ], [ - 7, - 8 ] + ], + [ + [ - 4, - 7 ], [ - 7, - 5 ], [ - 3, - 5 ], [ - 5, - 4 ], + [ - 1, - 4 ], [ - 2, - 2 ], [ - 6, - 1 ], [ - 4, 0 ], + [ - 7, 1 ], [ - 1, 2 ], [ - 6, 3 ], [ - 3, 3 ], + [ - 7, 6 ], [ - 3, 6 ], [ - 5, 7 ], [ - 1, 7 ], + [ 5, - 7 ], [ 1, - 6 ], [ 6, - 5 ], [ 4, - 4 ], + [ 2, - 3 ], [ 7, - 2 ], [ 1, - 1 ], [ 4, - 1 ], + [ 2, 1 ], [ 6, 2 ], [ 0, 4 ], [ 4, 4 ], + [ 2, 5 ], [ 7, 5 ], [ 5, 6 ], [ 3, 7 ] + ] +]; + +const ssaaPass = ( scene, camera ) => nodeObject( new SSAAPassNode( scene, camera ) ); + +const _size$2 = /*@__PURE__*/ new Vector2(); + +class StereoPassNode extends PassNode { + + static get type() { + + return 'StereoPassNode'; + + } + + constructor( scene, camera ) { + + super( PassNode.COLOR, scene, camera ); + + this.isStereoPassNode = true; + + this.stereo = new StereoCamera(); + this.stereo.aspect = 0.5; + + } + + updateBefore( frame ) { + + const { renderer } = frame; + const { scene, camera, stereo, renderTarget } = this; + + this._pixelRatio = renderer.getPixelRatio(); + + stereo.cameraL.coordinateSystem = renderer.coordinateSystem; + stereo.cameraR.coordinateSystem = renderer.coordinateSystem; + stereo.update( camera ); + + const size = renderer.getSize( _size$2 ); + this.setSize( size.width, size.height ); + + const currentAutoClear = renderer.autoClear; + renderer.autoClear = false; + + const currentRenderTarget = renderer.getRenderTarget(); + const currentMRT = renderer.getMRT(); + + this._cameraNear.value = camera.near; + this._cameraFar.value = camera.far; + + for ( const name in this._previousTextures ) { + + this.toggleTexture( name ); + + } + + renderer.setRenderTarget( renderTarget ); + renderer.setMRT( this._mrt ); + renderer.clear(); + + renderTarget.scissorTest = true; + + renderTarget.scissor.set( 0, 0, renderTarget.width / 2, renderTarget.height ); + renderTarget.viewport.set( 0, 0, renderTarget.width / 2, renderTarget.height ); + renderer.render( scene, stereo.cameraL ); + + renderTarget.scissor.set( renderTarget.width / 2, 0, renderTarget.width / 2, renderTarget.height ); + renderTarget.viewport.set( renderTarget.width / 2, 0, renderTarget.width / 2, renderTarget.height ); + renderer.render( scene, stereo.cameraR ); + + renderTarget.scissorTest = false; + + renderer.setRenderTarget( currentRenderTarget ); + renderer.setMRT( currentMRT ); + + renderer.autoClear = currentAutoClear; + + } + +} + +const stereoPass = ( scene, camera ) => nodeObject( new StereoPassNode( scene, camera ) ); + +const _size$1 = /*@__PURE__*/ new Vector2(); +const _quadMesh$2 = /*@__PURE__*/ new QuadMesh(); + +class StereoCompositePassNode extends PassNode { + + static get type() { + + return 'StereoCompositePassNode'; + + } + + constructor( scene, camera ) { + + super( PassNode.COLOR, scene, camera ); + + this.isStereoCompositePassNode = true; + + this.stereo = new StereoCamera(); + const _params = { minFilter: LinearFilter, magFilter: NearestFilter, type: HalfFloatType }; + + this._renderTargetL = new RenderTarget( 1, 1, _params ); + this._renderTargetR = new RenderTarget( 1, 1, _params ); + + this._mapLeft = texture( this._renderTargetL.texture ); + this._mapRight = texture( this._renderTargetR.texture ); + + this._material = null; + + } + + updateStereoCamera( coordinateSystem ) { + + this.stereo.cameraL.coordinateSystem = coordinateSystem; + this.stereo.cameraR.coordinateSystem = coordinateSystem; + this.stereo.update( this.camera ); + + } + + setSize( width, height ) { + + super.setSize( width, height ); + + this._renderTargetL.setSize( this.renderTarget.width, this.renderTarget.height ); + this._renderTargetR.setSize( this.renderTarget.width, this.renderTarget.height ); + + } + + updateBefore( frame ) { + + const { renderer } = frame; + const { scene, stereo, renderTarget } = this; + + this._pixelRatio = renderer.getPixelRatio(); + + this.updateStereoCamera( renderer.coordinateSystem ); + + const size = renderer.getSize( _size$1 ); + this.setSize( size.width, size.height ); + + const currentRenderTarget = renderer.getRenderTarget(); + + // left + + renderer.setRenderTarget( this._renderTargetL ); + renderer.render( scene, stereo.cameraL ); + + // right + + renderer.setRenderTarget( this._renderTargetR ); + renderer.render( scene, stereo.cameraR ); + + // composite + + renderer.setRenderTarget( renderTarget ); + _quadMesh$2.material = this._material; + _quadMesh$2.render( renderer ); + + // restore + + renderer.setRenderTarget( currentRenderTarget ); + + } + + dispose() { + + super.dispose(); + + this._renderTargetL.dispose(); + this._renderTargetR.dispose(); + + if ( this._material !== null ) { + + this._material.dispose(); + + } + + } + +} + +class AnaglyphPassNode extends StereoCompositePassNode { + + static get type() { + + return 'AnaglyphPassNode'; + + } + + constructor( scene, camera ) { + + super( scene, camera ); + + this.isAnaglyphPassNode = true; + + // Dubois matrices from https://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.7.6968&rep=rep1&type=pdf#page=4 + + this._colorMatrixLeft = uniform( new Matrix3().fromArray( [ + 0.456100, - 0.0400822, - 0.0152161, + 0.500484, - 0.0378246, - 0.0205971, + 0.176381, - 0.0157589, - 0.00546856 + ] ) ); + + this._colorMatrixRight = uniform( new Matrix3().fromArray( [ + - 0.0434706, 0.378476, - 0.0721527, + - 0.0879388, 0.73364, - 0.112961, + - 0.00155529, - 0.0184503, 1.2264 + ] ) ); + + } + + setup( builder ) { + + const uvNode = uv(); + + const anaglyph = Fn( () => { + + const colorL = this._mapLeft.uv( uvNode ); + const colorR = this._mapRight.uv( uvNode ); + + const color = clamp( this._colorMatrixLeft.mul( colorL.rgb ).add( this._colorMatrixRight.mul( colorR.rgb ) ) ); + + return vec4( color.rgb, max$1( colorL.a, colorR.a ) ); + + } ); + + const material = this._material || ( this._material = new NodeMaterial() ); + material.fragmentNode = anaglyph().context( builder.getSharedContext() ); + material.name = 'Anaglyph'; + material.needsUpdate = true; + + return super.setup( builder ); + + } + +} + +const anaglyphPass = ( scene, camera ) => nodeObject( new AnaglyphPassNode( scene, camera ) ); + +class ParallaxBarrierPassNode extends StereoCompositePassNode { + + static get type() { + + return 'ParallaxBarrierPassNode'; + + } + + constructor( scene, camera ) { + + super( scene, camera ); + + this.isParallaxBarrierPassNode = true; + + } + + setup( builder ) { + + const uvNode = uv(); + + const parallaxBarrier = Fn( () => { + + const color = vec4().toVar(); + + If( mod( screenCoordinate.y, 2 ).greaterThan( 1 ), () => { + + color.assign( this._mapLeft.uv( uvNode ) ); + + } ).Else( () => { + + color.assign( this._mapRight.uv( uvNode ) ); + + } ); + + return color; + + } ); + + const material = this._material || ( this._material = new NodeMaterial() ); + material.fragmentNode = parallaxBarrier().context( builder.getSharedContext() ); + material.needsUpdate = true; + + return super.setup( builder ); + + } + +} + +const parallaxBarrierPass = ( scene, camera ) => nodeObject( new ParallaxBarrierPassNode( scene, camera ) ); + +class ToonOutlinePassNode extends PassNode { + + static get type() { + + return 'ToonOutlinePassNode'; + + } + + constructor( scene, camera, colorNode, thicknessNode, alphaNode ) { + + super( PassNode.COLOR, scene, camera ); + + this.colorNode = colorNode; + this.thicknessNode = thicknessNode; + this.alphaNode = alphaNode; + + this._materialCache = new WeakMap(); + + } + + updateBefore( frame ) { + + const { renderer } = frame; + + const currentRenderObjectFunction = renderer.getRenderObjectFunction(); + + renderer.setRenderObjectFunction( ( object, scene, camera, geometry, material, group, lightsNode ) => { + + // only render outline for supported materials + + if ( material.isMeshToonMaterial || material.isMeshToonNodeMaterial ) { + + if ( material.wireframe === false ) { + + const outlineMaterial = this._getOutlineMaterial( material ); + renderer.renderObject( object, scene, camera, geometry, outlineMaterial, group, lightsNode ); + + } + + } + + // default + + renderer.renderObject( object, scene, camera, geometry, material, group, lightsNode ); + + } ); + + super.updateBefore( frame ); + + renderer.setRenderObjectFunction( currentRenderObjectFunction ); + + } + + _createMaterial() { + + const material = new NodeMaterial(); + material.isMeshToonOutlineMaterial = true; + material.name = 'Toon_Outline'; + material.side = BackSide; + + // vertex node + + const outlineNormal = normalLocal.negate(); + const mvp = cameraProjectionMatrix.mul( modelViewMatrix ); + + const ratio = float( 1.0 ); // TODO: support outline thickness ratio for each vertex + const pos = mvp.mul( vec4( positionLocal, 1.0 ) ); + const pos2 = mvp.mul( vec4( positionLocal.add( outlineNormal ), 1.0 ) ); + const norm = normalize( pos.sub( pos2 ) ); // NOTE: subtract pos2 from pos because BackSide objectNormal is negative + + material.vertexNode = pos.add( norm.mul( this.thicknessNode ).mul( pos.w ).mul( ratio ) ); + + // color node + + material.colorNode = vec4( this.colorNode, this.alphaNode ); + + return material; + + } + + _getOutlineMaterial( originalMaterial ) { + + let outlineMaterial = this._materialCache.get( originalMaterial ); + + if ( outlineMaterial === undefined ) { + + outlineMaterial = this._createMaterial(); + + this._materialCache.set( originalMaterial, outlineMaterial ); + + } + + return outlineMaterial; + + } + +} + +const toonOutlinePass = ( scene, camera, color = new Color( 0, 0, 0 ), thickness = 0.003, alpha = 1 ) => nodeObject( new ToonOutlinePassNode( scene, camera, nodeObject( color ), nodeObject( thickness ), nodeObject( alpha ) ) ); + +class ScriptableValueNode extends Node { + + static get type() { + + return 'ScriptableValueNode'; + + } + + constructor( value = null ) { + + super(); + + this._value = value; + this._cache = null; + + this.inputType = null; + this.outpuType = null; + + this.events = new EventDispatcher(); + + this.isScriptableValueNode = true; + + } + + get isScriptableOutputNode() { + + return this.outputType !== null; + + } + + set value( val ) { + + if ( this._value === val ) return; + + if ( this._cache && this.inputType === 'URL' && this.value.value instanceof ArrayBuffer ) { + + URL.revokeObjectURL( this._cache ); + + this._cache = null; + + } + + this._value = val; + + this.events.dispatchEvent( { type: 'change' } ); + + this.refresh(); + + } + + get value() { + + return this._value; + + } + + refresh() { + + this.events.dispatchEvent( { type: 'refresh' } ); + + } + + getValue() { + + const value = this.value; + + if ( value && this._cache === null && this.inputType === 'URL' && value.value instanceof ArrayBuffer ) { + + this._cache = URL.createObjectURL( new Blob( [ value.value ] ) ); + + } else if ( value && value.value !== null && value.value !== undefined && ( + ( ( this.inputType === 'URL' || this.inputType === 'String' ) && typeof value.value === 'string' ) || + ( this.inputType === 'Number' && typeof value.value === 'number' ) || + ( this.inputType === 'Vector2' && value.value.isVector2 ) || + ( this.inputType === 'Vector3' && value.value.isVector3 ) || + ( this.inputType === 'Vector4' && value.value.isVector4 ) || + ( this.inputType === 'Color' && value.value.isColor ) || + ( this.inputType === 'Matrix3' && value.value.isMatrix3 ) || + ( this.inputType === 'Matrix4' && value.value.isMatrix4 ) + ) ) { + + return value.value; + + } + + return this._cache || value; + + } + + getNodeType( builder ) { + + return this.value && this.value.isNode ? this.value.getNodeType( builder ) : 'float'; + + } + + setup() { + + return this.value && this.value.isNode ? this.value : float(); + + } + + serialize( data ) { + + super.serialize( data ); + + if ( this.value !== null ) { + + if ( this.inputType === 'ArrayBuffer' ) { + + data.value = arrayBufferToBase64( this.value ); + + } else { + + data.value = this.value ? this.value.toJSON( data.meta ).uuid : null; + + } + + } else { + + data.value = null; + + } + + data.inputType = this.inputType; + data.outputType = this.outputType; + + } + + deserialize( data ) { + + super.deserialize( data ); + + let value = null; + + if ( data.value !== null ) { + + if ( data.inputType === 'ArrayBuffer' ) { + + value = base64ToArrayBuffer( data.value ); + + } else if ( data.inputType === 'Texture' ) { + + value = data.meta.textures[ data.value ]; + + } else { + + value = data.meta.nodes[ data.value ] || null; + + } + + } + + this.value = value; + + this.inputType = data.inputType; + this.outputType = data.outputType; + + } + +} + +const scriptableValue = /*@__PURE__*/ nodeProxy( ScriptableValueNode ); + +class Resources extends Map { + + get( key, callback = null, ...params ) { + + if ( this.has( key ) ) return super.get( key ); + + if ( callback !== null ) { + + const value = callback( ...params ); + this.set( key, value ); + return value; + + } + + } + +} + +class Parameters { + + constructor( scriptableNode ) { + + this.scriptableNode = scriptableNode; + + } + + get parameters() { + + return this.scriptableNode.parameters; + + } + + get layout() { + + return this.scriptableNode.getLayout(); + + } + + getInputLayout( id ) { + + return this.scriptableNode.getInputLayout( id ); + + } + + get( name ) { + + const param = this.parameters[ name ]; + const value = param ? param.getValue() : null; + + return value; + + } + +} + +const global = new Resources(); + +class ScriptableNode extends Node { + + static get type() { + + return 'ScriptableNode'; + + } + + constructor( codeNode = null, parameters = {} ) { + + super(); + + this.codeNode = codeNode; + this.parameters = parameters; + + this._local = new Resources(); + this._output = scriptableValue(); + this._outputs = {}; + this._source = this.source; + this._method = null; + this._object = null; + this._value = null; + this._needsOutputUpdate = true; + + this.onRefresh = this.onRefresh.bind( this ); + + this.isScriptableNode = true; + + } + + get source() { + + return this.codeNode ? this.codeNode.code : ''; + + } + + setLocal( name, value ) { + + return this._local.set( name, value ); + + } + + getLocal( name ) { + + return this._local.get( name ); + + } + + onRefresh() { + + this._refresh(); + + } + + getInputLayout( id ) { + + for ( const element of this.getLayout() ) { + + if ( element.inputType && ( element.id === id || element.name === id ) ) { + + return element; + + } + + } + + } + + getOutputLayout( id ) { + + for ( const element of this.getLayout() ) { + + if ( element.outputType && ( element.id === id || element.name === id ) ) { + + return element; + + } + + } + + } + + setOutput( name, value ) { + + const outputs = this._outputs; + + if ( outputs[ name ] === undefined ) { + + outputs[ name ] = scriptableValue( value ); + + } else { + + outputs[ name ].value = value; + + } + + return this; + + } + + getOutput( name ) { + + return this._outputs[ name ]; + + } + + getParameter( name ) { + + return this.parameters[ name ]; + + } + + setParameter( name, value ) { + + const parameters = this.parameters; + + if ( value && value.isScriptableNode ) { + + this.deleteParameter( name ); + + parameters[ name ] = value; + parameters[ name ].getDefaultOutput().events.addEventListener( 'refresh', this.onRefresh ); + + } else if ( value && value.isScriptableValueNode ) { + + this.deleteParameter( name ); + + parameters[ name ] = value; + parameters[ name ].events.addEventListener( 'refresh', this.onRefresh ); + + } else if ( parameters[ name ] === undefined ) { + + parameters[ name ] = scriptableValue( value ); + parameters[ name ].events.addEventListener( 'refresh', this.onRefresh ); + + } else { + + parameters[ name ].value = value; + + } + + return this; + + } + + getValue() { + + return this.getDefaultOutput().getValue(); + + } + + deleteParameter( name ) { + + let valueNode = this.parameters[ name ]; + + if ( valueNode ) { + + if ( valueNode.isScriptableNode ) valueNode = valueNode.getDefaultOutput(); + + valueNode.events.removeEventListener( 'refresh', this.onRefresh ); + + } + + return this; + + } + + clearParameters() { + + for ( const name of Object.keys( this.parameters ) ) { + + this.deleteParameter( name ); + + } + + this.needsUpdate = true; + + return this; + + } + + call( name, ...params ) { + + const object = this.getObject(); + const method = object[ name ]; + + if ( typeof method === 'function' ) { + + return method( ...params ); + + } + + } + + async callAsync( name, ...params ) { + + const object = this.getObject(); + const method = object[ name ]; + + if ( typeof method === 'function' ) { + + return method.constructor.name === 'AsyncFunction' ? await method( ...params ) : method( ...params ); + + } + + } + + getNodeType( builder ) { + + return this.getDefaultOutputNode().getNodeType( builder ); + + } + + refresh( output = null ) { + + if ( output !== null ) { + + this.getOutput( output ).refresh(); + + } else { + + this._refresh(); + + } + + } + + getObject() { + + if ( this.needsUpdate ) this.dispose(); + if ( this._object !== null ) return this._object; + + // + + const refresh = () => this.refresh(); + const setOutput = ( id, value ) => this.setOutput( id, value ); + + const parameters = new Parameters( this ); + + const THREE = global.get( 'THREE' ); + const TSL = global.get( 'TSL' ); + + const method = this.getMethod( this.codeNode ); + const params = [ parameters, this._local, global, refresh, setOutput, THREE, TSL ]; + + this._object = method( ...params ); + + const layout = this._object.layout; + + if ( layout ) { + + if ( layout.cache === false ) { + + this._local.clear(); + + } + + // default output + this._output.outputType = layout.outputType || null; + + if ( Array.isArray( layout.elements ) ) { + + for ( const element of layout.elements ) { + + const id = element.id || element.name; + + if ( element.inputType ) { + + if ( this.getParameter( id ) === undefined ) this.setParameter( id, null ); + + this.getParameter( id ).inputType = element.inputType; + + } + + if ( element.outputType ) { + + if ( this.getOutput( id ) === undefined ) this.setOutput( id, null ); + + this.getOutput( id ).outputType = element.outputType; + + } + + } + + } + + } + + return this._object; + + } + + deserialize( data ) { + + super.deserialize( data ); + + for ( const name in this.parameters ) { + + let valueNode = this.parameters[ name ]; + + if ( valueNode.isScriptableNode ) valueNode = valueNode.getDefaultOutput(); + + valueNode.events.addEventListener( 'refresh', this.onRefresh ); + + } + + } + + getLayout() { + + return this.getObject().layout; + + } + + getDefaultOutputNode() { + + const output = this.getDefaultOutput().value; + + if ( output && output.isNode ) { + + return output; + + } + + return float(); + + } + + getDefaultOutput() { + + return this._exec()._output; + + } + + getMethod() { + + if ( this.needsUpdate ) this.dispose(); + if ( this._method !== null ) return this._method; + + // + + const parametersProps = [ 'parameters', 'local', 'global', 'refresh', 'setOutput', 'THREE', 'TSL' ]; + const interfaceProps = [ 'layout', 'init', 'main', 'dispose' ]; + + const properties = interfaceProps.join( ', ' ); + const declarations = 'var ' + properties + '; var output = {};\n'; + const returns = '\nreturn { ...output, ' + properties + ' };'; + + const code = declarations + this.codeNode.code + returns; + + // + + this._method = new Function( ...parametersProps, code ); + + return this._method; + + } + + dispose() { + + if ( this._method === null ) return; + + if ( this._object && typeof this._object.dispose === 'function' ) { + + this._object.dispose(); + + } + + this._method = null; + this._object = null; + this._source = null; + this._value = null; + this._needsOutputUpdate = true; + this._output.value = null; + this._outputs = {}; + + } + + setup() { + + return this.getDefaultOutputNode(); + + } + + getCacheKey( force ) { + + const values = [ hashString( this.source ), this.getDefaultOutputNode().getCacheKey( force ) ]; + + for ( const param in this.parameters ) { + + values.push( this.parameters[ param ].getCacheKey( force ) ); + + } + + return hashArray( values ); + + } + + set needsUpdate( value ) { + + if ( value === true ) this.dispose(); + + } + + get needsUpdate() { + + return this.source !== this._source; + + } + + _exec() { + + if ( this.codeNode === null ) return this; + + if ( this._needsOutputUpdate === true ) { + + this._value = this.call( 'main' ); + + this._needsOutputUpdate = false; + + } + + this._output.value = this._value; + + return this; + + } + + _refresh() { + + this.needsUpdate = true; + + this._exec(); + + this._output.refresh(); + + } + +} + +const scriptable = /*@__PURE__*/ nodeProxy( ScriptableNode ); + +class FogNode extends Node { + + static get type() { + + return 'FogNode'; + + } + + constructor( colorNode, factorNode ) { + + super( 'float' ); + + this.isFogNode = true; + + this.colorNode = colorNode; + this.factorNode = factorNode; + + } + + getViewZNode( builder ) { + + let viewZ; + + const getViewZ = builder.context.getViewZ; + + if ( getViewZ !== undefined ) { + + viewZ = getViewZ( this ); + + } + + return ( viewZ || positionView.z ).negate(); + + } + + setup() { + + return this.factorNode; + + } + +} + +const fog = /*@__PURE__*/ nodeProxy( FogNode ); + +class FogRangeNode extends FogNode { + + static get type() { + + return 'FogRangeNode'; + + } + + constructor( colorNode, nearNode, farNode ) { + + super( colorNode ); + + this.isFogRangeNode = true; + + this.nearNode = nearNode; + this.farNode = farNode; + + } + + setup( builder ) { + + const viewZ = this.getViewZNode( builder ); + + return smoothstep( this.nearNode, this.farNode, viewZ ); + + } + +} + +const rangeFog = /*@__PURE__*/ nodeProxy( FogRangeNode ); + +class FogExp2Node extends FogNode { + + static get type() { + + return 'FogExp2Node'; + + } + + constructor( colorNode, densityNode ) { + + super( colorNode ); + + this.isFogExp2Node = true; + + this.densityNode = densityNode; + + } + + setup( builder ) { + + const viewZ = this.getViewZNode( builder ); + const density = this.densityNode; + + return density.mul( density, viewZ, viewZ ).negate().exp().oneMinus(); + + } + +} + +const densityFog = /*@__PURE__*/ nodeProxy( FogExp2Node ); + +let min = null; +let max = null; + +class RangeNode extends Node { + + static get type() { + + return 'RangeNode'; + + } + + constructor( minNode = float(), maxNode = float() ) { + + super(); + + this.minNode = minNode; + this.maxNode = maxNode; + + } + + getVectorLength( builder ) { + + const minLength = builder.getTypeLength( getValueType( this.minNode.value ) ); + const maxLength = builder.getTypeLength( getValueType( this.maxNode.value ) ); + + return minLength > maxLength ? minLength : maxLength; + + } + + getNodeType( builder ) { + + return builder.object.count > 1 ? builder.getTypeFromLength( this.getVectorLength( builder ) ) : 'float'; + + } + + setup( builder ) { + + const object = builder.object; + + let output = null; + + if ( object.count > 1 ) { + + const minValue = this.minNode.value; + const maxValue = this.maxNode.value; + + const minLength = builder.getTypeLength( getValueType( minValue ) ); + const maxLength = builder.getTypeLength( getValueType( maxValue ) ); + + min = min || new Vector4(); + max = max || new Vector4(); + + min.setScalar( 0 ); + max.setScalar( 0 ); + + if ( minLength === 1 ) min.setScalar( minValue ); + else if ( minValue.isColor ) min.set( minValue.r, minValue.g, minValue.b ); + else min.set( minValue.x, minValue.y, minValue.z || 0, minValue.w || 0 ); + + if ( maxLength === 1 ) max.setScalar( maxValue ); + else if ( maxValue.isColor ) max.set( maxValue.r, maxValue.g, maxValue.b ); + else max.set( maxValue.x, maxValue.y, maxValue.z || 0, maxValue.w || 0 ); + + const stride = 4; + + const length = stride * object.count; + const array = new Float32Array( length ); + + for ( let i = 0; i < length; i ++ ) { + + const index = i % stride; + + const minElementValue = min.getComponent( index ); + const maxElementValue = max.getComponent( index ); + + array[ i ] = MathUtils.lerp( minElementValue, maxElementValue, Math.random() ); + + } + + const nodeType = this.getNodeType( builder ); + + if ( object.count <= 4096 ) { + + output = buffer( array, 'vec4', object.count ).element( instanceIndex ).convert( nodeType ); + + } else { + + // TODO: Improve anonymous buffer attribute creation removing this part + const bufferAttribute = new InstancedBufferAttribute( array, 4 ); + builder.geometry.setAttribute( '__range' + this.id, bufferAttribute ); + + output = instancedBufferAttribute( bufferAttribute ).convert( nodeType ); + + } + + } else { + + output = float( 0 ); + + } + + return output; + + } + +} + +const range = /*@__PURE__*/ nodeProxy( RangeNode ); + +const BasicShadowMap = Fn( ( { depthTexture, shadowCoord } ) => { + + return texture( depthTexture, shadowCoord.xy ).compare( shadowCoord.z ); + +} ); + +const PCFShadowMap = Fn( ( { depthTexture, shadowCoord, shadow } ) => { + + const depthCompare = ( uv, compare ) => texture( depthTexture, uv ).compare( compare ); + + const mapSize = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup ); + const radius = reference( 'radius', 'float', shadow ).setGroup( renderGroup ); + + const texelSize = vec2( 1 ).div( mapSize ); + const dx0 = texelSize.x.negate().mul( radius ); + const dy0 = texelSize.y.negate().mul( radius ); + const dx1 = texelSize.x.mul( radius ); + const dy1 = texelSize.y.mul( radius ); + const dx2 = dx0.div( 2 ); + const dy2 = dy0.div( 2 ); + const dx3 = dx1.div( 2 ); + const dy3 = dy1.div( 2 ); + + return add( + depthCompare( shadowCoord.xy.add( vec2( dx0, dy0 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( 0, dy0 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx1, dy0 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx2, dy2 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( 0, dy2 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx3, dy2 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx0, 0 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx2, 0 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy, shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx3, 0 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx1, 0 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx2, dy3 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( 0, dy3 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx3, dy3 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx0, dy1 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( 0, dy1 ) ), shadowCoord.z ), + depthCompare( shadowCoord.xy.add( vec2( dx1, dy1 ) ), shadowCoord.z ) + ).mul( 1 / 17 ); + +} ); + +const PCFSoftShadowMap = Fn( ( { depthTexture, shadowCoord, shadow } ) => { + + const depthCompare = ( uv, compare ) => texture( depthTexture, uv ).compare( compare ); + + const mapSize = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup ); + + const texelSize = vec2( 1 ).div( mapSize ); + const dx = texelSize.x; + const dy = texelSize.y; + + const uv = shadowCoord.xy; + const f = fract( uv.mul( mapSize ).add( 0.5 ) ); + uv.subAssign( f.mul( texelSize ) ); + + return add( + depthCompare( uv, shadowCoord.z ), + depthCompare( uv.add( vec2( dx, 0 ) ), shadowCoord.z ), + depthCompare( uv.add( vec2( 0, dy ) ), shadowCoord.z ), + depthCompare( uv.add( texelSize ), shadowCoord.z ), + mix( + depthCompare( uv.add( vec2( dx.negate(), 0 ) ), shadowCoord.z ), + depthCompare( uv.add( vec2( dx.mul( 2 ), 0 ) ), shadowCoord.z ), + f.x + ), + mix( + depthCompare( uv.add( vec2( dx.negate(), dy ) ), shadowCoord.z ), + depthCompare( uv.add( vec2( dx.mul( 2 ), dy ) ), shadowCoord.z ), + f.x + ), + mix( + depthCompare( uv.add( vec2( 0, dy.negate() ) ), shadowCoord.z ), + depthCompare( uv.add( vec2( 0, dy.mul( 2 ) ) ), shadowCoord.z ), + f.y + ), + mix( + depthCompare( uv.add( vec2( dx, dy.negate() ) ), shadowCoord.z ), + depthCompare( uv.add( vec2( dx, dy.mul( 2 ) ) ), shadowCoord.z ), + f.y + ), + mix( + mix( + depthCompare( uv.add( vec2( dx.negate(), dy.negate() ) ), shadowCoord.z ), + depthCompare( uv.add( vec2( dx.mul( 2 ), dy.negate() ) ), shadowCoord.z ), + f.x + ), + mix( + depthCompare( uv.add( vec2( dx.negate(), dy.mul( 2 ) ) ), shadowCoord.z ), + depthCompare( uv.add( vec2( dx.mul( 2 ), dy.mul( 2 ) ) ), shadowCoord.z ), + f.x + ), + f.y + ) + ).mul( 1 / 9 ); + +} ); + +// VSM + +const VSMShadowMapNode = Fn( ( { depthTexture, shadowCoord } ) => { + + const occlusion = float( 1 ).toVar(); + + const distribution = texture( depthTexture ).uv( shadowCoord.xy ).rg; + + const hardShadow = step( shadowCoord.z, distribution.x ); + + If( hardShadow.notEqual( float( 1.0 ) ), () => { + + const distance = shadowCoord.z.sub( distribution.x ); + const variance = max$1( 0, distribution.y.mul( distribution.y ) ); + let softnessProbability = variance.div( variance.add( distance.mul( distance ) ) ); // Chebeyshevs inequality + softnessProbability = clamp( sub( softnessProbability, 0.3 ).div( 0.95 - 0.3 ) ); + occlusion.assign( clamp( max$1( hardShadow, softnessProbability ) ) ); + + } ); + + return occlusion; + +} ); + +const VSMPassVertical = Fn( ( { samples, radius, size, shadowPass } ) => { + + const mean = float( 0 ).toVar(); + const squaredMean = float( 0 ).toVar(); + + const uvStride = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( 2 ).div( samples.sub( 1 ) ) ); + const uvStart = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( - 1 ) ); + + Loop( { start: int( 0 ), end: int( samples ), type: 'int', condition: '<' }, ( { i } ) => { + + const uvOffset = uvStart.add( float( i ).mul( uvStride ) ); + + const depth = shadowPass.uv( add( screenCoordinate.xy, vec2( 0, uvOffset ).mul( radius ) ).div( size ) ).x; + mean.addAssign( depth ); + squaredMean.addAssign( depth.mul( depth ) ); + + } ); + + mean.divAssign( samples ); + squaredMean.divAssign( samples ); + + const std_dev = sqrt( squaredMean.sub( mean.mul( mean ) ) ); + return vec2( mean, std_dev ); + +} ); + +const VSMPassHorizontal = Fn( ( { samples, radius, size, shadowPass } ) => { + + const mean = float( 0 ).toVar(); + const squaredMean = float( 0 ).toVar(); + + const uvStride = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( 2 ).div( samples.sub( 1 ) ) ); + const uvStart = samples.lessThanEqual( float( 1 ) ).select( float( 0 ), float( - 1 ) ); + + Loop( { start: int( 0 ), end: int( samples ), type: 'int', condition: '<' }, ( { i } ) => { + + const uvOffset = uvStart.add( float( i ).mul( uvStride ) ); + + const distribution = shadowPass.uv( add( screenCoordinate.xy, vec2( uvOffset, 0 ).mul( radius ) ).div( size ) ); + mean.addAssign( distribution.x ); + squaredMean.addAssign( add( distribution.y.mul( distribution.y ), distribution.x.mul( distribution.x ) ) ); + + } ); + + mean.divAssign( samples ); + squaredMean.divAssign( samples ); + + const std_dev = sqrt( squaredMean.sub( mean.mul( mean ) ) ); + return vec2( mean, std_dev ); + +} ); + +const _shadowFilterLib = [ BasicShadowMap, PCFShadowMap, PCFSoftShadowMap, VSMShadowMapNode ]; + +// + +let _overrideMaterial = null; +const _quadMesh$1 = /*@__PURE__*/ new QuadMesh(); + +class AnalyticLightNode extends LightingNode { + + static get type() { + + return 'AnalyticLightNode'; + + } + + constructor( light = null ) { + + super(); + + this.updateType = NodeUpdateType.FRAME; + + this.light = light; + + this.color = new Color(); + this.colorNode = uniform( this.color ).setGroup( renderGroup ); + + this.baseColorNode = null; + + this.shadowMap = null; + this.shadowNode = null; + this.shadowColorNode = null; + + this.vsmShadowMapVertical = null; + this.vsmShadowMapHorizontal = null; + + this.vsmMaterialVertical = null; + this.vsmMaterialHorizontal = null; + + this.isAnalyticLightNode = true; + + } + + getCacheKey() { + + return hash$1( super.getCacheKey(), this.light.id, this.light.castShadow ? 1 : 0 ); + + } + + getHash() { + + return this.light.uuid; + + } + + setupShadow( builder ) { + + const { object, renderer } = builder; + + if ( renderer.shadowMap.enabled === false ) return; + + let shadowColorNode = this.shadowColorNode; + + if ( shadowColorNode === null ) { + + if ( _overrideMaterial === null ) { + + _overrideMaterial = new NodeMaterial(); + _overrideMaterial.fragmentNode = vec4( 0, 0, 0, 1 ); + _overrideMaterial.isShadowNodeMaterial = true; // Use to avoid other overrideMaterial override material.fragmentNode unintentionally when using material.shadowNode + _overrideMaterial.name = 'ShadowMaterial'; + + } + + const shadowMapType = renderer.shadowMap.type; + const shadow = this.light.shadow; + + const depthTexture = new DepthTexture(); + depthTexture.compareFunction = LessCompare; + + const shadowMap = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height ); + shadowMap.depthTexture = depthTexture; + + shadow.camera.updateProjectionMatrix(); + + // VSM + + if ( shadowMapType === VSMShadowMap ) { + + depthTexture.compareFunction = null; // VSM does not use textureSampleCompare()/texture2DCompare() + + this.vsmShadowMapVertical = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height, { format: RGFormat, type: HalfFloatType } ); + this.vsmShadowMapHorizontal = builder.createRenderTarget( shadow.mapSize.width, shadow.mapSize.height, { format: RGFormat, type: HalfFloatType } ); + + const shadowPassVertical = texture( depthTexture ); + const shadowPassHorizontal = texture( this.vsmShadowMapVertical.texture ); + + const samples = reference( 'blurSamples', 'float', shadow ).setGroup( renderGroup ); + const radius = reference( 'radius', 'float', shadow ).setGroup( renderGroup ); + const size = reference( 'mapSize', 'vec2', shadow ).setGroup( renderGroup ); + + let material = this.vsmMaterialVertical || ( this.vsmMaterialVertical = new NodeMaterial() ); + material.fragmentNode = VSMPassVertical( { samples, radius, size, shadowPass: shadowPassVertical } ).context( builder.getSharedContext() ); + material.name = 'VSMVertical'; + + material = this.vsmMaterialHorizontal || ( this.vsmMaterialHorizontal = new NodeMaterial() ); + material.fragmentNode = VSMPassHorizontal( { samples, radius, size, shadowPass: shadowPassHorizontal } ).context( builder.getSharedContext() ); + material.name = 'VSMHorizontal'; + + } + + // + + const shadowIntensity = reference( 'intensity', 'float', shadow ).setGroup( renderGroup ); + const bias = reference( 'bias', 'float', shadow ).setGroup( renderGroup ); + const normalBias = reference( 'normalBias', 'float', shadow ).setGroup( renderGroup ); + + const position = object.material.shadowPositionNode || positionWorld; + + let shadowCoord = uniform( shadow.matrix ).setGroup( renderGroup ).mul( position.add( normalWorld.mul( normalBias ) ) ); + shadowCoord = shadowCoord.xyz.div( shadowCoord.w ); + + let coordZ = shadowCoord.z.add( bias ); + + if ( renderer.coordinateSystem === WebGPUCoordinateSystem ) { + + coordZ = coordZ.mul( 2 ).sub( 1 ); // WebGPU: Convertion [ 0, 1 ] to [ - 1, 1 ] + + } + + shadowCoord = vec3( + shadowCoord.x, + shadowCoord.y.oneMinus(), // follow webgpu standards + coordZ + ); + + const frustumTest = shadowCoord.x.greaterThanEqual( 0 ) + .and( shadowCoord.x.lessThanEqual( 1 ) ) + .and( shadowCoord.y.greaterThanEqual( 0 ) ) + .and( shadowCoord.y.lessThanEqual( 1 ) ) + .and( shadowCoord.z.lessThanEqual( 1 ) ); + + // + + const filterFn = shadow.filterNode || _shadowFilterLib[ renderer.shadowMap.type ] || null; + + if ( filterFn === null ) { + + throw new Error( 'THREE.WebGPURenderer: Shadow map type not supported yet.' ); + + } + + const shadowColor = texture( shadowMap.texture, shadowCoord ); + const shadowNode = frustumTest.select( filterFn( { depthTexture: ( shadowMapType === VSMShadowMap ) ? this.vsmShadowMapHorizontal.texture : depthTexture, shadowCoord, shadow } ), float( 1 ) ); + + this.shadowMap = shadowMap; + this.light.shadow.map = shadowMap; + + this.shadowNode = shadowNode; + this.shadowColorNode = shadowColorNode = this.colorNode.mul( mix( 1, shadowNode.rgb.mix( shadowColor, 1 ), shadowIntensity.mul( shadowColor.a ) ) ); + + this.baseColorNode = this.colorNode; + + } + + // + + this.colorNode = shadowColorNode; + + this.updateBeforeType = NodeUpdateType.RENDER; + + } + + setup( builder ) { + + this.colorNode = this.baseColorNode || this.colorNode; + + if ( this.light.castShadow ) { + + if ( builder.object.receiveShadow ) { + + this.setupShadow( builder ); + + } + + } else if ( this.shadowNode !== null ) { + + this.disposeShadow(); + + } + + } + + updateShadow( frame ) { + + const { shadowMap, light } = this; + const { renderer, scene, camera } = frame; + + const shadowType = renderer.shadowMap.type; + + const depthVersion = shadowMap.depthTexture.version; + this._depthVersionCached = depthVersion; + + const currentOverrideMaterial = scene.overrideMaterial; + + scene.overrideMaterial = _overrideMaterial; + + shadowMap.setSize( light.shadow.mapSize.width, light.shadow.mapSize.height ); + + light.shadow.updateMatrices( light ); + light.shadow.camera.layers.mask = camera.layers.mask; + + const currentRenderTarget = renderer.getRenderTarget(); + const currentRenderObjectFunction = renderer.getRenderObjectFunction(); + + renderer.setRenderObjectFunction( ( object, ...params ) => { + + if ( object.castShadow === true || ( object.receiveShadow && shadowType === VSMShadowMap ) ) { + + renderer.renderObject( object, ...params ); + + } + + } ); + + renderer.setRenderTarget( shadowMap ); + renderer.render( scene, light.shadow.camera ); + + renderer.setRenderObjectFunction( currentRenderObjectFunction ); + + // vsm blur pass + + if ( light.isPointLight !== true && shadowType === VSMShadowMap ) { + + this.vsmPass( frame, light ); + + } + + renderer.setRenderTarget( currentRenderTarget ); + + scene.overrideMaterial = currentOverrideMaterial; + + } + + vsmPass( frame, light ) { + + const { renderer } = frame; + + this.vsmShadowMapVertical.setSize( light.shadow.mapSize.width, light.shadow.mapSize.height ); + this.vsmShadowMapHorizontal.setSize( light.shadow.mapSize.width, light.shadow.mapSize.height ); + + renderer.setRenderTarget( this.vsmShadowMapVertical ); + _quadMesh$1.material = this.vsmMaterialVertical; + _quadMesh$1.render( renderer ); + + renderer.setRenderTarget( this.vsmShadowMapHorizontal ); + _quadMesh$1.material = this.vsmMaterialHorizontal; + _quadMesh$1.render( renderer ); + + } + + disposeShadow() { + + this.shadowMap.dispose(); + this.shadowMap = null; + + if ( this.vsmShadowMapVertical !== null ) { + + this.vsmShadowMapVertical.dispose(); + this.vsmShadowMapVertical = null; + + this.vsmMaterialVertical.dispose(); + this.vsmMaterialVertical = null; + + } + + if ( this.vsmShadowMapHorizontal !== null ) { + + this.vsmShadowMapHorizontal.dispose(); + this.vsmShadowMapHorizontal = null; + + this.vsmMaterialHorizontal.dispose(); + this.vsmMaterialHorizontal = null; + + } + + this.shadowNode = null; + this.shadowColorNode = null; + + this.baseColorNode = null; + + this.updateBeforeType = NodeUpdateType.NONE; + + } + + updateBefore( frame ) { + + const shadow = this.light.shadow; + + const needsUpdate = shadow.needsUpdate || shadow.autoUpdate; + + if ( needsUpdate ) { + + this.updateShadow( frame ); + + if ( this.shadowMap.depthTexture.version === this._depthVersionCached ) { + + shadow.needsUpdate = false; + + } + + } + + } + + update( /*frame*/ ) { + + const { light } = this; + + this.color.copy( light.color ).multiplyScalar( light.intensity ); + + } + +} + +const getDistanceAttenuation = /*@__PURE__*/ Fn( ( inputs ) => { + + const { lightDistance, cutoffDistance, decayExponent } = inputs; + + // based upon Frostbite 3 Moving to Physically-based Rendering + // page 32, equation 26: E[window1] + // https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf + const distanceFalloff = lightDistance.pow( decayExponent ).max( 0.01 ).reciprocal(); + + return cutoffDistance.greaterThan( 0 ).select( + distanceFalloff.mul( lightDistance.div( cutoffDistance ).pow4().oneMinus().clamp().pow2() ), + distanceFalloff + ); + +} ); // validated + +let uniformsLib; + +function getLightData( light ) { + + uniformsLib = uniformsLib || new WeakMap(); + + let uniforms = uniformsLib.get( light ); + + if ( uniforms === undefined ) uniformsLib.set( light, uniforms = {} ); + + return uniforms; + +} + +function lightPosition( light ) { + + const data = getLightData( light ); + + return data.position || ( data.position = uniform( new Vector3() ).setGroup( renderGroup ).onRenderUpdate( ( _, self ) => self.value.setFromMatrixPosition( light.matrixWorld ) ) ); + +} + +function lightTargetPosition( light ) { + + const data = getLightData( light ); + + return data.targetPosition || ( data.targetPosition = uniform( new Vector3() ).setGroup( renderGroup ).onRenderUpdate( ( _, self ) => self.value.setFromMatrixPosition( light.target.matrixWorld ) ) ); + +} + +function lightViewPosition( light ) { + + const data = getLightData( light ); + + return data.viewPosition || ( data.viewPosition = uniform( new Vector3() ).setGroup( renderGroup ).onRenderUpdate( ( { camera }, self ) => { + + self.value = self.value || new Vector3(); + self.value.setFromMatrixPosition( light.matrixWorld ); + + self.value.applyMatrix4( camera.matrixWorldInverse ); + + } ) ); + +} + +const lightTargetDirection = ( light ) => cameraViewMatrix.transformDirection( lightPosition( light ).sub( lightTargetPosition( light ) ) ); + +const hash = /*@__PURE__*/ Fn( ( [ seed ] ) => { + + // Taken from https://www.shadertoy.com/view/XlGcRh, originally from pcg-random.org + + const state = seed.toUint().mul( 747796405 ).add( 2891336453 ); + const word = state.shiftRight( state.shiftRight( 28 ).add( 4 ) ).bitXor( state ).mul( 277803737 ); + const result = word.shiftRight( 22 ).bitXor( word ); + + return result.toFloat().mul( 1 / 2 ** 32 ); // Convert to range [0, 1) + +} ); + +// remapping functions https://iquilezles.org/articles/functions/ +const parabola = ( x, k ) => pow( mul( 4.0, x.mul( sub( 1.0, x ) ) ), k ); +const gain = ( x, k ) => x.lessThan( 0.5 ) ? parabola( x.mul( 2.0 ), k ).div( 2.0 ) : sub( 1.0, parabola( mul( sub( 1.0, x ), 2.0 ), k ).div( 2.0 ) ); +const pcurve = ( x, a, b ) => pow( div( pow( x, a ), add( pow( x, a ), pow( sub( 1.0, x ), b ) ) ), 1.0 / a ); +const sinc = ( x, k ) => sin( PI.mul( k.mul( x ).sub( 1.0 ) ) ).div( PI.mul( k.mul( x ).sub( 1.0 ) ) ); + +// https://github.com/cabbibo/glsl-tri-noise-3d + + +const tri = /*@__PURE__*/ Fn( ( [ x ] ) => { + + return x.fract().sub( .5 ).abs(); + +} ).setLayout( { + name: 'tri', + type: 'float', + inputs: [ + { name: 'x', type: 'float' } + ] +} ); + +const tri3 = /*@__PURE__*/ Fn( ( [ p ] ) => { + + return vec3( tri( p.z.add( tri( p.y.mul( 1. ) ) ) ), tri( p.z.add( tri( p.x.mul( 1. ) ) ) ), tri( p.y.add( tri( p.x.mul( 1. ) ) ) ) ); + +} ).setLayout( { + name: 'tri3', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec3' } + ] +} ); + +const triNoise3D = /*@__PURE__*/ Fn( ( [ p_immutable, spd, time ] ) => { + + const p = vec3( p_immutable ).toVar(); + const z = float( 1.4 ).toVar(); + const rz = float( 0.0 ).toVar(); + const bp = vec3( p ).toVar(); + + Loop( { start: float( 0.0 ), end: float( 3.0 ), type: 'float', condition: '<=' }, () => { + + const dg = vec3( tri3( bp.mul( 2.0 ) ) ).toVar(); + p.addAssign( dg.add( time.mul( float( 0.1 ).mul( spd ) ) ) ); + bp.mulAssign( 1.8 ); + z.mulAssign( 1.5 ); + p.mulAssign( 1.2 ); + + const t = float( tri( p.z.add( tri( p.x.add( tri( p.y ) ) ) ) ) ).toVar(); + rz.addAssign( t.div( z ) ); + bp.addAssign( 0.14 ); + + } ); + + return rz; + +} ).setLayout( { + name: 'triNoise3D', + type: 'float', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'spd', type: 'float' }, + { name: 'time', type: 'float' } + ] +} ); + +const rotateUV = /*@__PURE__*/ Fn( ( [ uv, rotation, center = vec2( 0.5 ) ] ) => { + + return rotate( uv.sub( center ), rotation ).add( center ); + +} ); + +const spherizeUV = /*@__PURE__*/ Fn( ( [ uv, strength, center = vec2( 0.5 ) ] ) => { + + const delta = uv.sub( center ); + const delta2 = delta.dot( delta ); + const delta4 = delta2.mul( delta2 ); + const deltaOffset = delta4.mul( strength ); + + return uv.add( delta.mul( deltaOffset ) ); + +} ); + +const billboarding = /*@__PURE__*/ Fn( ( { position = null, horizontal = true, vertical = false } ) => { + + let worldMatrix; + + if ( position !== null ) { + + worldMatrix = modelWorldMatrix.toVar(); + worldMatrix[ 3 ][ 0 ] = position.x; + worldMatrix[ 3 ][ 1 ] = position.y; + worldMatrix[ 3 ][ 2 ] = position.z; + + } else { + + worldMatrix = modelWorldMatrix; + + } + + const modelViewMatrix = cameraViewMatrix.mul( worldMatrix ); + + if ( defined( horizontal ) ) { + + modelViewMatrix[ 0 ][ 0 ] = modelWorldMatrix[ 0 ].length(); + modelViewMatrix[ 0 ][ 1 ] = 0; + modelViewMatrix[ 0 ][ 2 ] = 0; + + } + + if ( defined( vertical ) ) { + + modelViewMatrix[ 1 ][ 0 ] = 0; + modelViewMatrix[ 1 ][ 1 ] = modelWorldMatrix[ 1 ].length(); + modelViewMatrix[ 1 ][ 2 ] = 0; + + } + + modelViewMatrix[ 2 ][ 0 ] = 0; + modelViewMatrix[ 2 ][ 1 ] = 0; + modelViewMatrix[ 2 ][ 2 ] = 1; + + return cameraProjectionMatrix.mul( modelViewMatrix ).mul( positionLocal ); + +} ); + +const viewportSafeUV = /*@__PURE__*/ Fn( ( [ uv = null ] ) => { + + const depth = linearDepth(); + const depthDiff = linearDepth( viewportDepthTexture( uv ) ).sub( depth ); + const finalUV = depthDiff.lessThan( 0 ).select( screenUV, uv ); + + return finalUV; + +} ); + +const _objectData = new WeakMap(); + +class VelocityNode extends TempNode { + + static get type() { + + return 'VelocityNode'; + + } + + constructor() { + + super( 'vec2' ); + + this.updateType = NodeUpdateType.OBJECT; + this.updateAfterType = NodeUpdateType.OBJECT; + + this.previousModelWorldMatrix = uniform( new Matrix4() ); + this.previousProjectionMatrix = uniform( new Matrix4() ).setGroup( renderGroup ); + this.previousCameraViewMatrix = uniform( new Matrix4() ); + + } + + update( { frameId, camera, object } ) { + + const previousModelMatrix = getPreviousMatrix( object ); + + this.previousModelWorldMatrix.value.copy( previousModelMatrix ); + + // + + const cameraData = getData( camera ); + + if ( cameraData.frameId !== frameId ) { + + cameraData.frameId = frameId; + + if ( cameraData.previousProjectionMatrix === undefined ) { + + cameraData.previousProjectionMatrix = new Matrix4(); + cameraData.previousCameraViewMatrix = new Matrix4(); + + cameraData.currentProjectionMatrix = new Matrix4(); + cameraData.currentCameraViewMatrix = new Matrix4(); + + cameraData.previousProjectionMatrix.copy( camera.projectionMatrix ); + cameraData.previousCameraViewMatrix.copy( camera.matrixWorldInverse ); + + } else { + + cameraData.previousProjectionMatrix.copy( cameraData.currentProjectionMatrix ); + cameraData.previousCameraViewMatrix.copy( cameraData.currentCameraViewMatrix ); + + } + + cameraData.currentProjectionMatrix.copy( camera.projectionMatrix ); + cameraData.currentCameraViewMatrix.copy( camera.matrixWorldInverse ); + + this.previousProjectionMatrix.value.copy( cameraData.previousProjectionMatrix ); + this.previousCameraViewMatrix.value.copy( cameraData.previousCameraViewMatrix ); + + } + + } + + updateAfter( { object } ) { + + getPreviousMatrix( object ).copy( object.matrixWorld ); + + } + + setup( /*builder*/ ) { + + const previousModelViewMatrix = this.previousCameraViewMatrix.mul( this.previousModelWorldMatrix ); + + const clipPositionCurrent = cameraProjectionMatrix.mul( modelViewMatrix ).mul( positionLocal ); + const clipPositionPrevious = this.previousProjectionMatrix.mul( previousModelViewMatrix ).mul( positionPrevious ); + + const ndcPositionCurrent = clipPositionCurrent.xy.div( clipPositionCurrent.w ); + const ndcPositionPrevious = clipPositionPrevious.xy.div( clipPositionPrevious.w ); + + const velocity = sub( ndcPositionCurrent, ndcPositionPrevious ); + + return velocity; + + } + +} + +function getData( object ) { + + let objectData = _objectData.get( object ); + + if ( objectData === undefined ) { + + objectData = {}; + _objectData.set( object, objectData ); + + } + + return objectData; + +} + +function getPreviousMatrix( object, index = 0 ) { + + const objectData = getData( object ); + + let matrix = objectData[ index ]; + + if ( matrix === undefined ) { + + objectData[ index ] = matrix = new Matrix4(); + + } + + return matrix; + +} + +const velocity = /*@__PURE__*/ nodeImmutable( VelocityNode ); + +const burn = /*@__PURE__*/ Fn( ( [ base, blend ] ) => { + + return min$1( 1.0, base.oneMinus().div( blend ) ).oneMinus(); + +} ).setLayout( { + name: 'burnBlend', + type: 'vec3', + inputs: [ + { name: 'base', type: 'vec3' }, + { name: 'blend', type: 'vec3' } + ] +} ); + +const dodge = /*@__PURE__*/ Fn( ( [ base, blend ] ) => { + + return min$1( base.div( blend.oneMinus() ), 1.0 ); + +} ).setLayout( { + name: 'dodgeBlend', + type: 'vec3', + inputs: [ + { name: 'base', type: 'vec3' }, + { name: 'blend', type: 'vec3' } + ] +} ); + +const screen = /*@__PURE__*/ Fn( ( [ base, blend ] ) => { + + return base.oneMinus().mul( blend.oneMinus() ).oneMinus(); + +} ).setLayout( { + name: 'screenBlend', + type: 'vec3', + inputs: [ + { name: 'base', type: 'vec3' }, + { name: 'blend', type: 'vec3' } + ] +} ); + +const overlay = /*@__PURE__*/ Fn( ( [ base, blend ] ) => { + + return mix( base.mul( 2.0 ).mul( blend ), base.oneMinus().mul( 2.0 ).mul( blend.oneMinus() ).oneMinus(), step( 0.5, base ) ); + +} ).setLayout( { + name: 'overlayBlend', + type: 'vec3', + inputs: [ + { name: 'base', type: 'vec3' }, + { name: 'blend', type: 'vec3' } + ] +} ); + +const motionBlur = /*@__PURE__*/ Fn( ( [ inputNode, velocity, numSamples = int( 16 ) ] ) => { + + const sampleColor = ( uv ) => inputNode.uv( uv ); + + const uvs = uv(); + + const colorResult = sampleColor( uvs ).toVar(); + const fSamples = float( numSamples ); + + Loop( { start: int( 1 ), end: numSamples, type: 'int', condition: '<=' }, ( { i } ) => { + + const offset = velocity.mul( float( i ).div( fSamples.sub( 1 ) ).sub( 0.5 ) ); + colorResult.addAssign( sampleColor( uvs.add( offset ) ) ); + + } ); + + colorResult.divAssign( fSamples ); + + return colorResult; + +} ); + +const bleach = /*@__PURE__*/ Fn( ( [ color, opacity = 1 ] ) => { + + const base = color; + const lum = luminance( base.rgb ); + const blend = vec3( lum ); + + const L = min$1( 1.0, max$1( 0.0, float( 10.0 ).mul( lum.sub( 0.45 ) ) ) ); + + const result1 = blend.mul( base.rgb ).mul( 2.0 ); + const result2 = float( 2.0 ).mul( blend.oneMinus() ).mul( base.rgb.oneMinus() ).oneMinus(); + + const newColor = mix( result1, result2, L ); + + const A2 = base.a.mul( opacity ); + + const mixRGB = A2.mul( newColor.rgb ); + + mixRGB.addAssign( base.rgb.mul( A2.oneMinus() ) ); + + return vec4( mixRGB, base.a ); + +} ); + +const sepia = /*@__PURE__*/ Fn( ( [ color ] ) => { + + const c = vec3( color ); + + // https://github.com/evanw/glfx.js/blob/master/src/filters/adjust/sepia.js + + return vec4( + dot( c, vec3( 0.393, 0.769, 0.189 ) ), + dot( c, vec3( 0.349, 0.686, 0.168 ) ), + dot( c, vec3( 0.272, 0.534, 0.131 ) ), + color.a + ); + +} ); + +const sRGBToLinearSRGB = /*@__PURE__*/ Fn( ( [ color ] ) => { + + const a = color.mul( 0.9478672986 ).add( 0.0521327014 ).pow( 2.4 ); + const b = color.mul( 0.0773993808 ); + const factor = color.lessThanEqual( 0.04045 ); + + const rgbResult = mix( a, b, factor ); + + return rgbResult; + +} ).setLayout( { + name: 'sRGBToLinearSRGB', + type: 'vec3', + inputs: [ + { name: 'color', type: 'vec3' } + ] +} ); + +const linearSRGBTosRGB = /*@__PURE__*/ Fn( ( [ color ] ) => { + + const a = color.pow( 0.41666 ).mul( 1.055 ).sub( 0.055 ); + const b = color.mul( 12.92 ); + const factor = color.lessThanEqual( 0.0031308 ); + + const rgbResult = mix( a, b, factor ); + + return rgbResult; + +} ).setLayout( { + name: 'linearSRGBTosRGB', + type: 'vec3', + inputs: [ + { name: 'color', type: 'vec3' } + ] +} ); + +// exposure only + +const linearToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { + + return color.mul( exposure ).clamp(); + +} ).setLayout( { + name: 'linearToneMapping', + type: 'vec3', + inputs: [ + { name: 'color', type: 'vec3' }, + { name: 'exposure', type: 'float' } + ] +} ); + +// source: https://www.cs.utah.edu/docs/techreports/2002/pdf/UUCS-02-001.pdf + +const reinhardToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { + + color = color.mul( exposure ); + + return color.div( color.add( 1.0 ) ).clamp(); + +} ).setLayout( { + name: 'reinhardToneMapping', + type: 'vec3', + inputs: [ + { name: 'color', type: 'vec3' }, + { name: 'exposure', type: 'float' } + ] +} ); + +// source: http://filmicworlds.com/blog/filmic-tonemapping-operators/ + +const cineonToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { + + // filmic operator by Jim Hejl and Richard Burgess-Dawson + color = color.mul( exposure ); + color = color.sub( 0.004 ).max( 0.0 ); + + const a = color.mul( color.mul( 6.2 ).add( 0.5 ) ); + const b = color.mul( color.mul( 6.2 ).add( 1.7 ) ).add( 0.06 ); + + return a.div( b ).pow( 2.2 ); + +} ).setLayout( { + name: 'cineonToneMapping', + type: 'vec3', + inputs: [ + { name: 'color', type: 'vec3' }, + { name: 'exposure', type: 'float' } + ] +} ); + +// source: https://github.com/selfshadow/ltc_code/blob/master/webgl/shaders/ltc/ltc_blit.fs + +const RRTAndODTFit = /*@__PURE__*/ Fn( ( [ color ] ) => { + + const a = color.mul( color.add( 0.0245786 ) ).sub( 0.000090537 ); + const b = color.mul( color.add( 0.4329510 ).mul( 0.983729 ) ).add( 0.238081 ); + + return a.div( b ); + +} ); + +// source: https://github.com/selfshadow/ltc_code/blob/master/webgl/shaders/ltc/ltc_blit.fs + +const acesFilmicToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { + + // sRGB => XYZ => D65_2_D60 => AP1 => RRT_SAT + const ACESInputMat = mat3( + 0.59719, 0.35458, 0.04823, + 0.07600, 0.90834, 0.01566, + 0.02840, 0.13383, 0.83777 + ); + + // ODT_SAT => XYZ => D60_2_D65 => sRGB + const ACESOutputMat = mat3( + 1.60475, - 0.53108, - 0.07367, + - 0.10208, 1.10813, - 0.00605, + - 0.00327, - 0.07276, 1.07602 + ); + + color = color.mul( exposure ).div( 0.6 ); + + color = ACESInputMat.mul( color ); + + // Apply RRT and ODT + color = RRTAndODTFit( color ); + + color = ACESOutputMat.mul( color ); + + // Clamp to [0, 1] + return color.clamp(); + +} ).setLayout( { + name: 'acesFilmicToneMapping', + type: 'vec3', + inputs: [ + { name: 'color', type: 'vec3' }, + { name: 'exposure', type: 'float' } + ] +} ); + +const LINEAR_REC2020_TO_LINEAR_SRGB = /*@__PURE__*/ mat3( vec3( 1.6605, - 0.1246, - 0.0182 ), vec3( - 0.5876, 1.1329, - 0.1006 ), vec3( - 0.0728, - 0.0083, 1.1187 ) ); +const LINEAR_SRGB_TO_LINEAR_REC2020 = /*@__PURE__*/ mat3( vec3( 0.6274, 0.0691, 0.0164 ), vec3( 0.3293, 0.9195, 0.0880 ), vec3( 0.0433, 0.0113, 0.8956 ) ); + +const agxDefaultContrastApprox = /*@__PURE__*/ Fn( ( [ x_immutable ] ) => { + + const x = vec3( x_immutable ).toVar(); + const x2 = vec3( x.mul( x ) ).toVar(); + const x4 = vec3( x2.mul( x2 ) ).toVar(); + + return float( 15.5 ).mul( x4.mul( x2 ) ).sub( mul( 40.14, x4.mul( x ) ) ).add( mul( 31.96, x4 ).sub( mul( 6.868, x2.mul( x ) ) ).add( mul( 0.4298, x2 ).add( mul( 0.1191, x ).sub( 0.00232 ) ) ) ); + +} ); + +const agxToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { + + const colortone = vec3( color ).toVar(); + const AgXInsetMatrix = mat3( vec3( 0.856627153315983, 0.137318972929847, 0.11189821299995 ), vec3( 0.0951212405381588, 0.761241990602591, 0.0767994186031903 ), vec3( 0.0482516061458583, 0.101439036467562, 0.811302368396859 ) ); + const AgXOutsetMatrix = mat3( vec3( 1.1271005818144368, - 0.1413297634984383, - 0.14132976349843826 ), vec3( - 0.11060664309660323, 1.157823702216272, - 0.11060664309660294 ), vec3( - 0.016493938717834573, - 0.016493938717834257, 1.2519364065950405 ) ); + const AgxMinEv = float( - 12.47393 ); + const AgxMaxEv = float( 4.026069 ); + colortone.mulAssign( exposure ); + colortone.assign( LINEAR_SRGB_TO_LINEAR_REC2020.mul( colortone ) ); + colortone.assign( AgXInsetMatrix.mul( colortone ) ); + colortone.assign( max$1( colortone, 1e-10 ) ); + colortone.assign( log2( colortone ) ); + colortone.assign( colortone.sub( AgxMinEv ).div( AgxMaxEv.sub( AgxMinEv ) ) ); + colortone.assign( clamp( colortone, 0.0, 1.0 ) ); + colortone.assign( agxDefaultContrastApprox( colortone ) ); + colortone.assign( AgXOutsetMatrix.mul( colortone ) ); + colortone.assign( pow( max$1( vec3( 0.0 ), colortone ), vec3( 2.2 ) ) ); + colortone.assign( LINEAR_REC2020_TO_LINEAR_SRGB.mul( colortone ) ); + colortone.assign( clamp( colortone, 0.0, 1.0 ) ); + + return colortone; + +} ).setLayout( { + name: 'agxToneMapping', + type: 'vec3', + inputs: [ + { name: 'color', type: 'vec3' }, + { name: 'exposure', type: 'float' } + ] +} ); + +// https://modelviewer.dev/examples/tone-mapping + +const neutralToneMapping = /*@__PURE__*/ Fn( ( [ color, exposure ] ) => { + + const StartCompression = float( 0.8 - 0.04 ); + const Desaturation = float( 0.15 ); + + color = color.mul( exposure ); + + const x = min$1( color.r, min$1( color.g, color.b ) ); + const offset = select( x.lessThan( 0.08 ), x.sub( mul( 6.25, x.mul( x ) ) ), 0.04 ); + + color.subAssign( offset ); + + const peak = max$1( color.r, max$1( color.g, color.b ) ); + + If( peak.lessThan( StartCompression ), () => { + + return color; + + } ); + + const d = sub( 1, StartCompression ); + const newPeak = sub( 1, d.mul( d ).div( peak.add( d.sub( StartCompression ) ) ) ); + color.mulAssign( newPeak.div( peak ) ); + const g = sub( 1, div( 1, Desaturation.mul( peak.sub( newPeak ) ).add( 1 ) ) ); + + return mix( color, vec3( newPeak ), g ); + +} ).setLayout( { + name: 'neutralToneMapping', + type: 'vec3', + inputs: [ + { name: 'color', type: 'vec3' }, + { name: 'exposure', type: 'float' } + ] +} ); + +class ComputeBuiltinNode extends Node { + + static get type() { + + return 'ComputeBuiltinNode'; + + } + + constructor( builtinName, nodeType ) { + + super( nodeType ); + + this._builtinName = builtinName; + + } + + getHash( builder ) { + + return this.getBuiltinName( builder ); + + } + + getNodeType( /*builder*/ ) { + + return this.nodeType; + + } + + setBuiltinName( builtinName ) { + + this._builtinName = builtinName; + + return this; + + } + + getBuiltinName( /*builder*/ ) { + + return this._builtinName; + + } + + hasBuiltin( builder ) { + + builder.hasBuiltin( this._builtinName ); + + } + + generate( builder, output ) { + + const builtinName = this.getBuiltinName( builder ); + const nodeType = this.getNodeType( builder ); + + if ( builder.shaderStage === 'compute' ) { + + return builder.format( builtinName, nodeType, output ); + + } else { + + console.warn( `ComputeBuiltinNode: Compute built-in value ${builtinName} can not be accessed in the ${builder.shaderStage} stage` ); + return builder.generateConst( nodeType ); + + } + + } + + serialize( data ) { + + super.serialize( data ); + + data.global = this.global; + data._builtinName = this._builtinName; + + } + + deserialize( data ) { + + super.deserialize( data ); + + this.global = data.global; + this._builtinName = data._builtinName; + + } + +} + +const computeBuiltin = ( name, nodeType ) => nodeObject( new ComputeBuiltinNode( name, nodeType ) ); + +const numWorkgroups = /*@__PURE__*/ computeBuiltin( 'numWorkgroups', 'uvec3' ); +const workgroupId = /*@__PURE__*/ computeBuiltin( 'workgroupId', 'uvec3' ); +const localId = /*@__PURE__*/ computeBuiltin( 'localId', 'uvec3' ); +const subgroupSize = /*@__PURE__*/ computeBuiltin( 'subgroupSize', 'uint' ); + +class BarrierNode extends Node { + + constructor( scope ) { + + super(); + + this.scope = scope; + + } + + generate( builder ) { + + const { scope } = this; + const { renderer } = builder; + + if ( renderer.backend.isWebGLBackend === true ) { + + builder.addFlowCode( `\t// ${scope}Barrier \n` ); + + } else { + + builder.addLineFlowCode( `${scope}Barrier()`, this ); + + } + + } + +} + +const barrier = nodeProxy( BarrierNode ); + +const workgroupBarrier = () => barrier( 'workgroup' ).append(); +const storageBarrier = () => barrier( 'storage' ).append(); +const textureBarrier = () => barrier( 'texture' ).append(); + +class WorkgroupInfoElementNode extends ArrayElementNode { + + constructor( workgroupInfoNode, indexNode ) { + + super( workgroupInfoNode, indexNode ); + + this.isWorkgroupInfoElementNode = true; + + } + + generate( builder, output ) { + + let snippet; + + const isAssignContext = builder.context.assign; + snippet = super.generate( builder ); + + if ( isAssignContext !== true ) { + + const type = this.getNodeType( builder ); + + snippet = builder.format( snippet, type, output ); + + } + + // TODO: Possibly activate clip distance index on index access rather than from clipping context + + return snippet; + + } + +} + + +class WorkgroupInfoNode extends Node { + + constructor( scope, bufferType, bufferCount = 0 ) { + + super( bufferType ); + + this.bufferType = bufferType; + this.bufferCount = bufferCount; + + this.isWorkgroupInfoNode = true; + + this.scope = scope; + + } + + label( name ) { + + this.name = name; + + return this; + + } + + getHash() { + + return this.uuid; + + } + + setScope( scope ) { + + this.scope = scope; + + return this; + + } + + getInputType( /*builder*/ ) { + + return `${this.scope}Array`; + + } + + element( indexNode ) { + + return nodeObject( new WorkgroupInfoElementNode( this, indexNode ) ); + + } + + generate( builder ) { + + return builder.getScopedArray( this.name || `${this.scope}Array_${this.id}`, this.scope.toLowerCase(), this.bufferType, this.bufferCount ); + + } + +} + +const workgroupArray = ( type, count ) => nodeObject( new WorkgroupInfoNode( 'Workgroup', type, count ) ); + +class AtomicFunctionNode extends TempNode { + + static get type() { + + return 'AtomicFunctionNode'; + + } + + constructor( method, pointerNode, valueNode, storeNode = null ) { + + super( 'uint' ); + + this.method = method; + + this.pointerNode = pointerNode; + this.valueNode = valueNode; + this.storeNode = storeNode; + + } + + getInputType( builder ) { + + return this.pointerNode.getNodeType( builder ); + + } + + getNodeType( builder ) { + + return this.getInputType( builder ); + + } + + generate( builder ) { + + const method = this.method; + + const type = this.getNodeType( builder ); + const inputType = this.getInputType( builder ); + + const a = this.pointerNode; + const b = this.valueNode; + + const params = []; + + params.push( `&${ a.build( builder, inputType ) }` ); + params.push( b.build( builder, inputType ) ); + + const methodSnippet = `${ builder.getMethod( method, type ) }( ${params.join( ', ' )} )`; + + if ( this.storeNode !== null ) { + + const varSnippet = this.storeNode.build( builder, inputType ); + + builder.addLineFlowCode( `${varSnippet} = ${methodSnippet}`, this ); + + } else { + + builder.addLineFlowCode( methodSnippet, this ); + + } + + } + +} + +AtomicFunctionNode.ATOMIC_LOAD = 'atomicLoad'; +AtomicFunctionNode.ATOMIC_STORE = 'atomicStore'; +AtomicFunctionNode.ATOMIC_ADD = 'atomicAdd'; +AtomicFunctionNode.ATOMIC_SUB = 'atomicSub'; +AtomicFunctionNode.ATOMIC_MAX = 'atomicMax'; +AtomicFunctionNode.ATOMIC_MIN = 'atomicMin'; +AtomicFunctionNode.ATOMIC_AND = 'atomicAnd'; +AtomicFunctionNode.ATOMIC_OR = 'atomicOr'; +AtomicFunctionNode.ATOMIC_XOR = 'atomicXor'; + +const atomicNode = nodeProxy( AtomicFunctionNode ); + +const atomicFunc = ( method, pointerNode, valueNode, storeNode ) => { + + const node = atomicNode( method, pointerNode, valueNode, storeNode ); + node.append(); + + return node; + +}; + +const atomicStore = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_STORE, pointerNode, valueNode, storeNode ); +const atomicAdd = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_ADD, pointerNode, valueNode, storeNode ); +const atomicSub = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_SUB, pointerNode, valueNode, storeNode ); +const atomicMax = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_MAX, pointerNode, valueNode, storeNode ); +const atomicMin = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_MIN, pointerNode, valueNode, storeNode ); +const atomicAnd = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_AND, pointerNode, valueNode, storeNode ); +const atomicOr = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_OR, pointerNode, valueNode, storeNode ); +const atomicXor = ( pointerNode, valueNode, storeNode = null ) => atomicFunc( AtomicFunctionNode.ATOMIC_XOR, pointerNode, valueNode, storeNode ); + +const checker = /*@__PURE__*/ Fn( ( [ coord = uv() ] ) => { + + const uv = coord.mul( 2.0 ); + + const cx = uv.x.floor(); + const cy = uv.y.floor(); + const result = cx.add( cy ).mod( 2.0 ); + + return result.sign(); + +} ); + +// Three.js Transpiler +// https://raw.githubusercontent.com/AcademySoftwareFoundation/MaterialX/main/libraries/stdlib/genglsl/lib/mx_noise.glsl + + + +const mx_select = /*@__PURE__*/ Fn( ( [ b_immutable, t_immutable, f_immutable ] ) => { + + const f = float( f_immutable ).toVar(); + const t = float( t_immutable ).toVar(); + const b = bool( b_immutable ).toVar(); + + return select( b, t, f ); + +} ).setLayout( { + name: 'mx_select', + type: 'float', + inputs: [ + { name: 'b', type: 'bool' }, + { name: 't', type: 'float' }, + { name: 'f', type: 'float' } + ] +} ); + +const mx_negate_if = /*@__PURE__*/ Fn( ( [ val_immutable, b_immutable ] ) => { + + const b = bool( b_immutable ).toVar(); + const val = float( val_immutable ).toVar(); + + return select( b, val.negate(), val ); + +} ).setLayout( { + name: 'mx_negate_if', + type: 'float', + inputs: [ + { name: 'val', type: 'float' }, + { name: 'b', type: 'bool' } + ] +} ); + +const mx_floor = /*@__PURE__*/ Fn( ( [ x_immutable ] ) => { + + const x = float( x_immutable ).toVar(); + + return int( floor( x ) ); + +} ).setLayout( { + name: 'mx_floor', + type: 'int', + inputs: [ + { name: 'x', type: 'float' } + ] +} ); + +const mx_floorfrac = /*@__PURE__*/ Fn( ( [ x_immutable, i ] ) => { + + const x = float( x_immutable ).toVar(); + i.assign( mx_floor( x ) ); + + return x.sub( float( i ) ); + +} ); + +const mx_bilerp_0 = /*@__PURE__*/ Fn( ( [ v0_immutable, v1_immutable, v2_immutable, v3_immutable, s_immutable, t_immutable ] ) => { + + const t = float( t_immutable ).toVar(); + const s = float( s_immutable ).toVar(); + const v3 = float( v3_immutable ).toVar(); + const v2 = float( v2_immutable ).toVar(); + const v1 = float( v1_immutable ).toVar(); + const v0 = float( v0_immutable ).toVar(); + const s1 = float( sub( 1.0, s ) ).toVar(); + + return sub( 1.0, t ).mul( v0.mul( s1 ).add( v1.mul( s ) ) ).add( t.mul( v2.mul( s1 ).add( v3.mul( s ) ) ) ); + +} ).setLayout( { + name: 'mx_bilerp_0', + type: 'float', + inputs: [ + { name: 'v0', type: 'float' }, + { name: 'v1', type: 'float' }, + { name: 'v2', type: 'float' }, + { name: 'v3', type: 'float' }, + { name: 's', type: 'float' }, + { name: 't', type: 'float' } + ] +} ); + +const mx_bilerp_1 = /*@__PURE__*/ Fn( ( [ v0_immutable, v1_immutable, v2_immutable, v3_immutable, s_immutable, t_immutable ] ) => { + + const t = float( t_immutable ).toVar(); + const s = float( s_immutable ).toVar(); + const v3 = vec3( v3_immutable ).toVar(); + const v2 = vec3( v2_immutable ).toVar(); + const v1 = vec3( v1_immutable ).toVar(); + const v0 = vec3( v0_immutable ).toVar(); + const s1 = float( sub( 1.0, s ) ).toVar(); + + return sub( 1.0, t ).mul( v0.mul( s1 ).add( v1.mul( s ) ) ).add( t.mul( v2.mul( s1 ).add( v3.mul( s ) ) ) ); + +} ).setLayout( { + name: 'mx_bilerp_1', + type: 'vec3', + inputs: [ + { name: 'v0', type: 'vec3' }, + { name: 'v1', type: 'vec3' }, + { name: 'v2', type: 'vec3' }, + { name: 'v3', type: 'vec3' }, + { name: 's', type: 'float' }, + { name: 't', type: 'float' } + ] +} ); + +const mx_bilerp = /*@__PURE__*/ overloadingFn( [ mx_bilerp_0, mx_bilerp_1 ] ); + +const mx_trilerp_0 = /*@__PURE__*/ Fn( ( [ v0_immutable, v1_immutable, v2_immutable, v3_immutable, v4_immutable, v5_immutable, v6_immutable, v7_immutable, s_immutable, t_immutable, r_immutable ] ) => { + + const r = float( r_immutable ).toVar(); + const t = float( t_immutable ).toVar(); + const s = float( s_immutable ).toVar(); + const v7 = float( v7_immutable ).toVar(); + const v6 = float( v6_immutable ).toVar(); + const v5 = float( v5_immutable ).toVar(); + const v4 = float( v4_immutable ).toVar(); + const v3 = float( v3_immutable ).toVar(); + const v2 = float( v2_immutable ).toVar(); + const v1 = float( v1_immutable ).toVar(); + const v0 = float( v0_immutable ).toVar(); + const s1 = float( sub( 1.0, s ) ).toVar(); + const t1 = float( sub( 1.0, t ) ).toVar(); + const r1 = float( sub( 1.0, r ) ).toVar(); + + return r1.mul( t1.mul( v0.mul( s1 ).add( v1.mul( s ) ) ).add( t.mul( v2.mul( s1 ).add( v3.mul( s ) ) ) ) ).add( r.mul( t1.mul( v4.mul( s1 ).add( v5.mul( s ) ) ).add( t.mul( v6.mul( s1 ).add( v7.mul( s ) ) ) ) ) ); + +} ).setLayout( { + name: 'mx_trilerp_0', + type: 'float', + inputs: [ + { name: 'v0', type: 'float' }, + { name: 'v1', type: 'float' }, + { name: 'v2', type: 'float' }, + { name: 'v3', type: 'float' }, + { name: 'v4', type: 'float' }, + { name: 'v5', type: 'float' }, + { name: 'v6', type: 'float' }, + { name: 'v7', type: 'float' }, + { name: 's', type: 'float' }, + { name: 't', type: 'float' }, + { name: 'r', type: 'float' } + ] +} ); + +const mx_trilerp_1 = /*@__PURE__*/ Fn( ( [ v0_immutable, v1_immutable, v2_immutable, v3_immutable, v4_immutable, v5_immutable, v6_immutable, v7_immutable, s_immutable, t_immutable, r_immutable ] ) => { + + const r = float( r_immutable ).toVar(); + const t = float( t_immutable ).toVar(); + const s = float( s_immutable ).toVar(); + const v7 = vec3( v7_immutable ).toVar(); + const v6 = vec3( v6_immutable ).toVar(); + const v5 = vec3( v5_immutable ).toVar(); + const v4 = vec3( v4_immutable ).toVar(); + const v3 = vec3( v3_immutable ).toVar(); + const v2 = vec3( v2_immutable ).toVar(); + const v1 = vec3( v1_immutable ).toVar(); + const v0 = vec3( v0_immutable ).toVar(); + const s1 = float( sub( 1.0, s ) ).toVar(); + const t1 = float( sub( 1.0, t ) ).toVar(); + const r1 = float( sub( 1.0, r ) ).toVar(); + + return r1.mul( t1.mul( v0.mul( s1 ).add( v1.mul( s ) ) ).add( t.mul( v2.mul( s1 ).add( v3.mul( s ) ) ) ) ).add( r.mul( t1.mul( v4.mul( s1 ).add( v5.mul( s ) ) ).add( t.mul( v6.mul( s1 ).add( v7.mul( s ) ) ) ) ) ); + +} ).setLayout( { + name: 'mx_trilerp_1', + type: 'vec3', + inputs: [ + { name: 'v0', type: 'vec3' }, + { name: 'v1', type: 'vec3' }, + { name: 'v2', type: 'vec3' }, + { name: 'v3', type: 'vec3' }, + { name: 'v4', type: 'vec3' }, + { name: 'v5', type: 'vec3' }, + { name: 'v6', type: 'vec3' }, + { name: 'v7', type: 'vec3' }, + { name: 's', type: 'float' }, + { name: 't', type: 'float' }, + { name: 'r', type: 'float' } + ] +} ); + +const mx_trilerp = /*@__PURE__*/ overloadingFn( [ mx_trilerp_0, mx_trilerp_1 ] ); + +const mx_gradient_float_0 = /*@__PURE__*/ Fn( ( [ hash_immutable, x_immutable, y_immutable ] ) => { + + const y = float( y_immutable ).toVar(); + const x = float( x_immutable ).toVar(); + const hash = uint( hash_immutable ).toVar(); + const h = uint( hash.bitAnd( uint( 7 ) ) ).toVar(); + const u = float( mx_select( h.lessThan( uint( 4 ) ), x, y ) ).toVar(); + const v = float( mul( 2.0, mx_select( h.lessThan( uint( 4 ) ), y, x ) ) ).toVar(); + + return mx_negate_if( u, bool( h.bitAnd( uint( 1 ) ) ) ).add( mx_negate_if( v, bool( h.bitAnd( uint( 2 ) ) ) ) ); + +} ).setLayout( { + name: 'mx_gradient_float_0', + type: 'float', + inputs: [ + { name: 'hash', type: 'uint' }, + { name: 'x', type: 'float' }, + { name: 'y', type: 'float' } + ] +} ); + +const mx_gradient_float_1 = /*@__PURE__*/ Fn( ( [ hash_immutable, x_immutable, y_immutable, z_immutable ] ) => { + + const z = float( z_immutable ).toVar(); + const y = float( y_immutable ).toVar(); + const x = float( x_immutable ).toVar(); + const hash = uint( hash_immutable ).toVar(); + const h = uint( hash.bitAnd( uint( 15 ) ) ).toVar(); + const u = float( mx_select( h.lessThan( uint( 8 ) ), x, y ) ).toVar(); + const v = float( mx_select( h.lessThan( uint( 4 ) ), y, mx_select( h.equal( uint( 12 ) ).or( h.equal( uint( 14 ) ) ), x, z ) ) ).toVar(); + + return mx_negate_if( u, bool( h.bitAnd( uint( 1 ) ) ) ).add( mx_negate_if( v, bool( h.bitAnd( uint( 2 ) ) ) ) ); + +} ).setLayout( { + name: 'mx_gradient_float_1', + type: 'float', + inputs: [ + { name: 'hash', type: 'uint' }, + { name: 'x', type: 'float' }, + { name: 'y', type: 'float' }, + { name: 'z', type: 'float' } + ] +} ); + +const mx_gradient_float = /*@__PURE__*/ overloadingFn( [ mx_gradient_float_0, mx_gradient_float_1 ] ); + +const mx_gradient_vec3_0 = /*@__PURE__*/ Fn( ( [ hash_immutable, x_immutable, y_immutable ] ) => { + + const y = float( y_immutable ).toVar(); + const x = float( x_immutable ).toVar(); + const hash = uvec3( hash_immutable ).toVar(); + + return vec3( mx_gradient_float( hash.x, x, y ), mx_gradient_float( hash.y, x, y ), mx_gradient_float( hash.z, x, y ) ); + +} ).setLayout( { + name: 'mx_gradient_vec3_0', + type: 'vec3', + inputs: [ + { name: 'hash', type: 'uvec3' }, + { name: 'x', type: 'float' }, + { name: 'y', type: 'float' } + ] +} ); + +const mx_gradient_vec3_1 = /*@__PURE__*/ Fn( ( [ hash_immutable, x_immutable, y_immutable, z_immutable ] ) => { + + const z = float( z_immutable ).toVar(); + const y = float( y_immutable ).toVar(); + const x = float( x_immutable ).toVar(); + const hash = uvec3( hash_immutable ).toVar(); + + return vec3( mx_gradient_float( hash.x, x, y, z ), mx_gradient_float( hash.y, x, y, z ), mx_gradient_float( hash.z, x, y, z ) ); + +} ).setLayout( { + name: 'mx_gradient_vec3_1', + type: 'vec3', + inputs: [ + { name: 'hash', type: 'uvec3' }, + { name: 'x', type: 'float' }, + { name: 'y', type: 'float' }, + { name: 'z', type: 'float' } + ] +} ); + +const mx_gradient_vec3 = /*@__PURE__*/ overloadingFn( [ mx_gradient_vec3_0, mx_gradient_vec3_1 ] ); + +const mx_gradient_scale2d_0 = /*@__PURE__*/ Fn( ( [ v_immutable ] ) => { + + const v = float( v_immutable ).toVar(); + + return mul( 0.6616, v ); + +} ).setLayout( { + name: 'mx_gradient_scale2d_0', + type: 'float', + inputs: [ + { name: 'v', type: 'float' } + ] +} ); + +const mx_gradient_scale3d_0 = /*@__PURE__*/ Fn( ( [ v_immutable ] ) => { + + const v = float( v_immutable ).toVar(); + + return mul( 0.9820, v ); + +} ).setLayout( { + name: 'mx_gradient_scale3d_0', + type: 'float', + inputs: [ + { name: 'v', type: 'float' } + ] +} ); + +const mx_gradient_scale2d_1 = /*@__PURE__*/ Fn( ( [ v_immutable ] ) => { + + const v = vec3( v_immutable ).toVar(); + + return mul( 0.6616, v ); + +} ).setLayout( { + name: 'mx_gradient_scale2d_1', + type: 'vec3', + inputs: [ + { name: 'v', type: 'vec3' } + ] +} ); + +const mx_gradient_scale2d = /*@__PURE__*/ overloadingFn( [ mx_gradient_scale2d_0, mx_gradient_scale2d_1 ] ); + +const mx_gradient_scale3d_1 = /*@__PURE__*/ Fn( ( [ v_immutable ] ) => { + + const v = vec3( v_immutable ).toVar(); + + return mul( 0.9820, v ); + +} ).setLayout( { + name: 'mx_gradient_scale3d_1', + type: 'vec3', + inputs: [ + { name: 'v', type: 'vec3' } + ] +} ); + +const mx_gradient_scale3d = /*@__PURE__*/ overloadingFn( [ mx_gradient_scale3d_0, mx_gradient_scale3d_1 ] ); + +const mx_rotl32 = /*@__PURE__*/ Fn( ( [ x_immutable, k_immutable ] ) => { + + const k = int( k_immutable ).toVar(); + const x = uint( x_immutable ).toVar(); + + return x.shiftLeft( k ).bitOr( x.shiftRight( int( 32 ).sub( k ) ) ); + +} ).setLayout( { + name: 'mx_rotl32', + type: 'uint', + inputs: [ + { name: 'x', type: 'uint' }, + { name: 'k', type: 'int' } + ] +} ); + +const mx_bjmix = /*@__PURE__*/ Fn( ( [ a, b, c ] ) => { + + a.subAssign( c ); + a.bitXorAssign( mx_rotl32( c, int( 4 ) ) ); + c.addAssign( b ); + b.subAssign( a ); + b.bitXorAssign( mx_rotl32( a, int( 6 ) ) ); + a.addAssign( c ); + c.subAssign( b ); + c.bitXorAssign( mx_rotl32( b, int( 8 ) ) ); + b.addAssign( a ); + a.subAssign( c ); + a.bitXorAssign( mx_rotl32( c, int( 16 ) ) ); + c.addAssign( b ); + b.subAssign( a ); + b.bitXorAssign( mx_rotl32( a, int( 19 ) ) ); + a.addAssign( c ); + c.subAssign( b ); + c.bitXorAssign( mx_rotl32( b, int( 4 ) ) ); + b.addAssign( a ); + +} ); + +const mx_bjfinal = /*@__PURE__*/ Fn( ( [ a_immutable, b_immutable, c_immutable ] ) => { + + const c = uint( c_immutable ).toVar(); + const b = uint( b_immutable ).toVar(); + const a = uint( a_immutable ).toVar(); + c.bitXorAssign( b ); + c.subAssign( mx_rotl32( b, int( 14 ) ) ); + a.bitXorAssign( c ); + a.subAssign( mx_rotl32( c, int( 11 ) ) ); + b.bitXorAssign( a ); + b.subAssign( mx_rotl32( a, int( 25 ) ) ); + c.bitXorAssign( b ); + c.subAssign( mx_rotl32( b, int( 16 ) ) ); + a.bitXorAssign( c ); + a.subAssign( mx_rotl32( c, int( 4 ) ) ); + b.bitXorAssign( a ); + b.subAssign( mx_rotl32( a, int( 14 ) ) ); + c.bitXorAssign( b ); + c.subAssign( mx_rotl32( b, int( 24 ) ) ); + + return c; + +} ).setLayout( { + name: 'mx_bjfinal', + type: 'uint', + inputs: [ + { name: 'a', type: 'uint' }, + { name: 'b', type: 'uint' }, + { name: 'c', type: 'uint' } + ] +} ); + +const mx_bits_to_01 = /*@__PURE__*/ Fn( ( [ bits_immutable ] ) => { + + const bits = uint( bits_immutable ).toVar(); + + return float( bits ).div( float( uint( int( 0xffffffff ) ) ) ); + +} ).setLayout( { + name: 'mx_bits_to_01', + type: 'float', + inputs: [ + { name: 'bits', type: 'uint' } + ] +} ); + +const mx_fade = /*@__PURE__*/ Fn( ( [ t_immutable ] ) => { + + const t = float( t_immutable ).toVar(); + + return t.mul( t ).mul( t ).mul( t.mul( t.mul( 6.0 ).sub( 15.0 ) ).add( 10.0 ) ); + +} ).setLayout( { + name: 'mx_fade', + type: 'float', + inputs: [ + { name: 't', type: 'float' } + ] +} ); + +const mx_hash_int_0 = /*@__PURE__*/ Fn( ( [ x_immutable ] ) => { + + const x = int( x_immutable ).toVar(); + const len = uint( uint( 1 ) ).toVar(); + const seed = uint( uint( int( 0xdeadbeef ) ).add( len.shiftLeft( uint( 2 ) ) ).add( uint( 13 ) ) ).toVar(); + + return mx_bjfinal( seed.add( uint( x ) ), seed, seed ); + +} ).setLayout( { + name: 'mx_hash_int_0', + type: 'uint', + inputs: [ + { name: 'x', type: 'int' } + ] +} ); + +const mx_hash_int_1 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable ] ) => { + + const y = int( y_immutable ).toVar(); + const x = int( x_immutable ).toVar(); + const len = uint( uint( 2 ) ).toVar(); + const a = uint().toVar(), b = uint().toVar(), c = uint().toVar(); + a.assign( b.assign( c.assign( uint( int( 0xdeadbeef ) ).add( len.shiftLeft( uint( 2 ) ) ).add( uint( 13 ) ) ) ) ); + a.addAssign( uint( x ) ); + b.addAssign( uint( y ) ); + + return mx_bjfinal( a, b, c ); + +} ).setLayout( { + name: 'mx_hash_int_1', + type: 'uint', + inputs: [ + { name: 'x', type: 'int' }, + { name: 'y', type: 'int' } + ] +} ); + +const mx_hash_int_2 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable, z_immutable ] ) => { + + const z = int( z_immutable ).toVar(); + const y = int( y_immutable ).toVar(); + const x = int( x_immutable ).toVar(); + const len = uint( uint( 3 ) ).toVar(); + const a = uint().toVar(), b = uint().toVar(), c = uint().toVar(); + a.assign( b.assign( c.assign( uint( int( 0xdeadbeef ) ).add( len.shiftLeft( uint( 2 ) ) ).add( uint( 13 ) ) ) ) ); + a.addAssign( uint( x ) ); + b.addAssign( uint( y ) ); + c.addAssign( uint( z ) ); + + return mx_bjfinal( a, b, c ); + +} ).setLayout( { + name: 'mx_hash_int_2', + type: 'uint', + inputs: [ + { name: 'x', type: 'int' }, + { name: 'y', type: 'int' }, + { name: 'z', type: 'int' } + ] +} ); + +const mx_hash_int_3 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable, z_immutable, xx_immutable ] ) => { + + const xx = int( xx_immutable ).toVar(); + const z = int( z_immutable ).toVar(); + const y = int( y_immutable ).toVar(); + const x = int( x_immutable ).toVar(); + const len = uint( uint( 4 ) ).toVar(); + const a = uint().toVar(), b = uint().toVar(), c = uint().toVar(); + a.assign( b.assign( c.assign( uint( int( 0xdeadbeef ) ).add( len.shiftLeft( uint( 2 ) ) ).add( uint( 13 ) ) ) ) ); + a.addAssign( uint( x ) ); + b.addAssign( uint( y ) ); + c.addAssign( uint( z ) ); + mx_bjmix( a, b, c ); + a.addAssign( uint( xx ) ); + + return mx_bjfinal( a, b, c ); + +} ).setLayout( { + name: 'mx_hash_int_3', + type: 'uint', + inputs: [ + { name: 'x', type: 'int' }, + { name: 'y', type: 'int' }, + { name: 'z', type: 'int' }, + { name: 'xx', type: 'int' } + ] +} ); + +const mx_hash_int_4 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable, z_immutable, xx_immutable, yy_immutable ] ) => { + + const yy = int( yy_immutable ).toVar(); + const xx = int( xx_immutable ).toVar(); + const z = int( z_immutable ).toVar(); + const y = int( y_immutable ).toVar(); + const x = int( x_immutable ).toVar(); + const len = uint( uint( 5 ) ).toVar(); + const a = uint().toVar(), b = uint().toVar(), c = uint().toVar(); + a.assign( b.assign( c.assign( uint( int( 0xdeadbeef ) ).add( len.shiftLeft( uint( 2 ) ) ).add( uint( 13 ) ) ) ) ); + a.addAssign( uint( x ) ); + b.addAssign( uint( y ) ); + c.addAssign( uint( z ) ); + mx_bjmix( a, b, c ); + a.addAssign( uint( xx ) ); + b.addAssign( uint( yy ) ); + + return mx_bjfinal( a, b, c ); + +} ).setLayout( { + name: 'mx_hash_int_4', + type: 'uint', + inputs: [ + { name: 'x', type: 'int' }, + { name: 'y', type: 'int' }, + { name: 'z', type: 'int' }, + { name: 'xx', type: 'int' }, + { name: 'yy', type: 'int' } + ] +} ); + +const mx_hash_int = /*@__PURE__*/ overloadingFn( [ mx_hash_int_0, mx_hash_int_1, mx_hash_int_2, mx_hash_int_3, mx_hash_int_4 ] ); + +const mx_hash_vec3_0 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable ] ) => { + + const y = int( y_immutable ).toVar(); + const x = int( x_immutable ).toVar(); + const h = uint( mx_hash_int( x, y ) ).toVar(); + const result = uvec3().toVar(); + result.x.assign( h.bitAnd( int( 0xFF ) ) ); + result.y.assign( h.shiftRight( int( 8 ) ).bitAnd( int( 0xFF ) ) ); + result.z.assign( h.shiftRight( int( 16 ) ).bitAnd( int( 0xFF ) ) ); + + return result; + +} ).setLayout( { + name: 'mx_hash_vec3_0', + type: 'uvec3', + inputs: [ + { name: 'x', type: 'int' }, + { name: 'y', type: 'int' } + ] +} ); + +const mx_hash_vec3_1 = /*@__PURE__*/ Fn( ( [ x_immutable, y_immutable, z_immutable ] ) => { + + const z = int( z_immutable ).toVar(); + const y = int( y_immutable ).toVar(); + const x = int( x_immutable ).toVar(); + const h = uint( mx_hash_int( x, y, z ) ).toVar(); + const result = uvec3().toVar(); + result.x.assign( h.bitAnd( int( 0xFF ) ) ); + result.y.assign( h.shiftRight( int( 8 ) ).bitAnd( int( 0xFF ) ) ); + result.z.assign( h.shiftRight( int( 16 ) ).bitAnd( int( 0xFF ) ) ); + + return result; + +} ).setLayout( { + name: 'mx_hash_vec3_1', + type: 'uvec3', + inputs: [ + { name: 'x', type: 'int' }, + { name: 'y', type: 'int' }, + { name: 'z', type: 'int' } + ] +} ); + +const mx_hash_vec3 = /*@__PURE__*/ overloadingFn( [ mx_hash_vec3_0, mx_hash_vec3_1 ] ); + +const mx_perlin_noise_float_0 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec2( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(); + const fx = float( mx_floorfrac( p.x, X ) ).toVar(); + const fy = float( mx_floorfrac( p.y, Y ) ).toVar(); + const u = float( mx_fade( fx ) ).toVar(); + const v = float( mx_fade( fy ) ).toVar(); + const result = float( mx_bilerp( mx_gradient_float( mx_hash_int( X, Y ), fx, fy ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y ), fx.sub( 1.0 ), fy ), mx_gradient_float( mx_hash_int( X, Y.add( int( 1 ) ) ), fx, fy.sub( 1.0 ) ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y.add( int( 1 ) ) ), fx.sub( 1.0 ), fy.sub( 1.0 ) ), u, v ) ).toVar(); + + return mx_gradient_scale2d( result ); + +} ).setLayout( { + name: 'mx_perlin_noise_float_0', + type: 'float', + inputs: [ + { name: 'p', type: 'vec2' } + ] +} ); + +const mx_perlin_noise_float_1 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec3( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(), Z = int().toVar(); + const fx = float( mx_floorfrac( p.x, X ) ).toVar(); + const fy = float( mx_floorfrac( p.y, Y ) ).toVar(); + const fz = float( mx_floorfrac( p.z, Z ) ).toVar(); + const u = float( mx_fade( fx ) ).toVar(); + const v = float( mx_fade( fy ) ).toVar(); + const w = float( mx_fade( fz ) ).toVar(); + const result = float( mx_trilerp( mx_gradient_float( mx_hash_int( X, Y, Z ), fx, fy, fz ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y, Z ), fx.sub( 1.0 ), fy, fz ), mx_gradient_float( mx_hash_int( X, Y.add( int( 1 ) ), Z ), fx, fy.sub( 1.0 ), fz ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y.add( int( 1 ) ), Z ), fx.sub( 1.0 ), fy.sub( 1.0 ), fz ), mx_gradient_float( mx_hash_int( X, Y, Z.add( int( 1 ) ) ), fx, fy, fz.sub( 1.0 ) ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y, Z.add( int( 1 ) ) ), fx.sub( 1.0 ), fy, fz.sub( 1.0 ) ), mx_gradient_float( mx_hash_int( X, Y.add( int( 1 ) ), Z.add( int( 1 ) ) ), fx, fy.sub( 1.0 ), fz.sub( 1.0 ) ), mx_gradient_float( mx_hash_int( X.add( int( 1 ) ), Y.add( int( 1 ) ), Z.add( int( 1 ) ) ), fx.sub( 1.0 ), fy.sub( 1.0 ), fz.sub( 1.0 ) ), u, v, w ) ).toVar(); + + return mx_gradient_scale3d( result ); + +} ).setLayout( { + name: 'mx_perlin_noise_float_1', + type: 'float', + inputs: [ + { name: 'p', type: 'vec3' } + ] +} ); + +const mx_perlin_noise_float = /*@__PURE__*/ overloadingFn( [ mx_perlin_noise_float_0, mx_perlin_noise_float_1 ] ); + +const mx_perlin_noise_vec3_0 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec2( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(); + const fx = float( mx_floorfrac( p.x, X ) ).toVar(); + const fy = float( mx_floorfrac( p.y, Y ) ).toVar(); + const u = float( mx_fade( fx ) ).toVar(); + const v = float( mx_fade( fy ) ).toVar(); + const result = vec3( mx_bilerp( mx_gradient_vec3( mx_hash_vec3( X, Y ), fx, fy ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y ), fx.sub( 1.0 ), fy ), mx_gradient_vec3( mx_hash_vec3( X, Y.add( int( 1 ) ) ), fx, fy.sub( 1.0 ) ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y.add( int( 1 ) ) ), fx.sub( 1.0 ), fy.sub( 1.0 ) ), u, v ) ).toVar(); + + return mx_gradient_scale2d( result ); + +} ).setLayout( { + name: 'mx_perlin_noise_vec3_0', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec2' } + ] +} ); + +const mx_perlin_noise_vec3_1 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec3( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(), Z = int().toVar(); + const fx = float( mx_floorfrac( p.x, X ) ).toVar(); + const fy = float( mx_floorfrac( p.y, Y ) ).toVar(); + const fz = float( mx_floorfrac( p.z, Z ) ).toVar(); + const u = float( mx_fade( fx ) ).toVar(); + const v = float( mx_fade( fy ) ).toVar(); + const w = float( mx_fade( fz ) ).toVar(); + const result = vec3( mx_trilerp( mx_gradient_vec3( mx_hash_vec3( X, Y, Z ), fx, fy, fz ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y, Z ), fx.sub( 1.0 ), fy, fz ), mx_gradient_vec3( mx_hash_vec3( X, Y.add( int( 1 ) ), Z ), fx, fy.sub( 1.0 ), fz ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y.add( int( 1 ) ), Z ), fx.sub( 1.0 ), fy.sub( 1.0 ), fz ), mx_gradient_vec3( mx_hash_vec3( X, Y, Z.add( int( 1 ) ) ), fx, fy, fz.sub( 1.0 ) ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y, Z.add( int( 1 ) ) ), fx.sub( 1.0 ), fy, fz.sub( 1.0 ) ), mx_gradient_vec3( mx_hash_vec3( X, Y.add( int( 1 ) ), Z.add( int( 1 ) ) ), fx, fy.sub( 1.0 ), fz.sub( 1.0 ) ), mx_gradient_vec3( mx_hash_vec3( X.add( int( 1 ) ), Y.add( int( 1 ) ), Z.add( int( 1 ) ) ), fx.sub( 1.0 ), fy.sub( 1.0 ), fz.sub( 1.0 ) ), u, v, w ) ).toVar(); + + return mx_gradient_scale3d( result ); + +} ).setLayout( { + name: 'mx_perlin_noise_vec3_1', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec3' } + ] +} ); + +const mx_perlin_noise_vec3 = /*@__PURE__*/ overloadingFn( [ mx_perlin_noise_vec3_0, mx_perlin_noise_vec3_1 ] ); + +const mx_cell_noise_float_0 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = float( p_immutable ).toVar(); + const ix = int( mx_floor( p ) ).toVar(); + + return mx_bits_to_01( mx_hash_int( ix ) ); + +} ).setLayout( { + name: 'mx_cell_noise_float_0', + type: 'float', + inputs: [ + { name: 'p', type: 'float' } + ] +} ); + +const mx_cell_noise_float_1 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec2( p_immutable ).toVar(); + const ix = int( mx_floor( p.x ) ).toVar(); + const iy = int( mx_floor( p.y ) ).toVar(); + + return mx_bits_to_01( mx_hash_int( ix, iy ) ); + +} ).setLayout( { + name: 'mx_cell_noise_float_1', + type: 'float', + inputs: [ + { name: 'p', type: 'vec2' } + ] +} ); + +const mx_cell_noise_float_2 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec3( p_immutable ).toVar(); + const ix = int( mx_floor( p.x ) ).toVar(); + const iy = int( mx_floor( p.y ) ).toVar(); + const iz = int( mx_floor( p.z ) ).toVar(); + + return mx_bits_to_01( mx_hash_int( ix, iy, iz ) ); + +} ).setLayout( { + name: 'mx_cell_noise_float_2', + type: 'float', + inputs: [ + { name: 'p', type: 'vec3' } + ] +} ); + +const mx_cell_noise_float_3 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec4( p_immutable ).toVar(); + const ix = int( mx_floor( p.x ) ).toVar(); + const iy = int( mx_floor( p.y ) ).toVar(); + const iz = int( mx_floor( p.z ) ).toVar(); + const iw = int( mx_floor( p.w ) ).toVar(); + + return mx_bits_to_01( mx_hash_int( ix, iy, iz, iw ) ); + +} ).setLayout( { + name: 'mx_cell_noise_float_3', + type: 'float', + inputs: [ + { name: 'p', type: 'vec4' } + ] +} ); + +const mx_cell_noise_float$1 = /*@__PURE__*/ overloadingFn( [ mx_cell_noise_float_0, mx_cell_noise_float_1, mx_cell_noise_float_2, mx_cell_noise_float_3 ] ); + +const mx_cell_noise_vec3_0 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = float( p_immutable ).toVar(); + const ix = int( mx_floor( p ) ).toVar(); + + return vec3( mx_bits_to_01( mx_hash_int( ix, int( 0 ) ) ), mx_bits_to_01( mx_hash_int( ix, int( 1 ) ) ), mx_bits_to_01( mx_hash_int( ix, int( 2 ) ) ) ); + +} ).setLayout( { + name: 'mx_cell_noise_vec3_0', + type: 'vec3', + inputs: [ + { name: 'p', type: 'float' } + ] +} ); + +const mx_cell_noise_vec3_1 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec2( p_immutable ).toVar(); + const ix = int( mx_floor( p.x ) ).toVar(); + const iy = int( mx_floor( p.y ) ).toVar(); + + return vec3( mx_bits_to_01( mx_hash_int( ix, iy, int( 0 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, int( 1 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, int( 2 ) ) ) ); + +} ).setLayout( { + name: 'mx_cell_noise_vec3_1', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec2' } + ] +} ); + +const mx_cell_noise_vec3_2 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec3( p_immutable ).toVar(); + const ix = int( mx_floor( p.x ) ).toVar(); + const iy = int( mx_floor( p.y ) ).toVar(); + const iz = int( mx_floor( p.z ) ).toVar(); + + return vec3( mx_bits_to_01( mx_hash_int( ix, iy, iz, int( 0 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, iz, int( 1 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, iz, int( 2 ) ) ) ); + +} ).setLayout( { + name: 'mx_cell_noise_vec3_2', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec3' } + ] +} ); + +const mx_cell_noise_vec3_3 = /*@__PURE__*/ Fn( ( [ p_immutable ] ) => { + + const p = vec4( p_immutable ).toVar(); + const ix = int( mx_floor( p.x ) ).toVar(); + const iy = int( mx_floor( p.y ) ).toVar(); + const iz = int( mx_floor( p.z ) ).toVar(); + const iw = int( mx_floor( p.w ) ).toVar(); + + return vec3( mx_bits_to_01( mx_hash_int( ix, iy, iz, iw, int( 0 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, iz, iw, int( 1 ) ) ), mx_bits_to_01( mx_hash_int( ix, iy, iz, iw, int( 2 ) ) ) ); + +} ).setLayout( { + name: 'mx_cell_noise_vec3_3', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec4' } + ] +} ); + +const mx_cell_noise_vec3 = /*@__PURE__*/ overloadingFn( [ mx_cell_noise_vec3_0, mx_cell_noise_vec3_1, mx_cell_noise_vec3_2, mx_cell_noise_vec3_3 ] ); + +const mx_fractal_noise_float$1 = /*@__PURE__*/ Fn( ( [ p_immutable, octaves_immutable, lacunarity_immutable, diminish_immutable ] ) => { + + const diminish = float( diminish_immutable ).toVar(); + const lacunarity = float( lacunarity_immutable ).toVar(); + const octaves = int( octaves_immutable ).toVar(); + const p = vec3( p_immutable ).toVar(); + const result = float( 0.0 ).toVar(); + const amplitude = float( 1.0 ).toVar(); + + Loop( octaves, () => { + + result.addAssign( amplitude.mul( mx_perlin_noise_float( p ) ) ); + amplitude.mulAssign( diminish ); + p.mulAssign( lacunarity ); + + } ); + + return result; + +} ).setLayout( { + name: 'mx_fractal_noise_float', + type: 'float', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'octaves', type: 'int' }, + { name: 'lacunarity', type: 'float' }, + { name: 'diminish', type: 'float' } + ] +} ); + +const mx_fractal_noise_vec3$1 = /*@__PURE__*/ Fn( ( [ p_immutable, octaves_immutable, lacunarity_immutable, diminish_immutable ] ) => { + + const diminish = float( diminish_immutable ).toVar(); + const lacunarity = float( lacunarity_immutable ).toVar(); + const octaves = int( octaves_immutable ).toVar(); + const p = vec3( p_immutable ).toVar(); + const result = vec3( 0.0 ).toVar(); + const amplitude = float( 1.0 ).toVar(); + + Loop( octaves, () => { + + result.addAssign( amplitude.mul( mx_perlin_noise_vec3( p ) ) ); + amplitude.mulAssign( diminish ); + p.mulAssign( lacunarity ); + + } ); + + return result; + +} ).setLayout( { + name: 'mx_fractal_noise_vec3', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'octaves', type: 'int' }, + { name: 'lacunarity', type: 'float' }, + { name: 'diminish', type: 'float' } + ] +} ); + +const mx_fractal_noise_vec2$1 = /*@__PURE__*/ Fn( ( [ p_immutable, octaves_immutable, lacunarity_immutable, diminish_immutable ] ) => { + + const diminish = float( diminish_immutable ).toVar(); + const lacunarity = float( lacunarity_immutable ).toVar(); + const octaves = int( octaves_immutable ).toVar(); + const p = vec3( p_immutable ).toVar(); + + return vec2( mx_fractal_noise_float$1( p, octaves, lacunarity, diminish ), mx_fractal_noise_float$1( p.add( vec3( int( 19 ), int( 193 ), int( 17 ) ) ), octaves, lacunarity, diminish ) ); + +} ).setLayout( { + name: 'mx_fractal_noise_vec2', + type: 'vec2', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'octaves', type: 'int' }, + { name: 'lacunarity', type: 'float' }, + { name: 'diminish', type: 'float' } + ] +} ); + +const mx_fractal_noise_vec4$1 = /*@__PURE__*/ Fn( ( [ p_immutable, octaves_immutable, lacunarity_immutable, diminish_immutable ] ) => { + + const diminish = float( diminish_immutable ).toVar(); + const lacunarity = float( lacunarity_immutable ).toVar(); + const octaves = int( octaves_immutable ).toVar(); + const p = vec3( p_immutable ).toVar(); + const c = vec3( mx_fractal_noise_vec3$1( p, octaves, lacunarity, diminish ) ).toVar(); + const f = float( mx_fractal_noise_float$1( p.add( vec3( int( 19 ), int( 193 ), int( 17 ) ) ), octaves, lacunarity, diminish ) ).toVar(); + + return vec4( c, f ); + +} ).setLayout( { + name: 'mx_fractal_noise_vec4', + type: 'vec4', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'octaves', type: 'int' }, + { name: 'lacunarity', type: 'float' }, + { name: 'diminish', type: 'float' } + ] +} ); + +const mx_worley_distance_0 = /*@__PURE__*/ Fn( ( [ p_immutable, x_immutable, y_immutable, xoff_immutable, yoff_immutable, jitter_immutable, metric_immutable ] ) => { + + const metric = int( metric_immutable ).toVar(); + const jitter = float( jitter_immutable ).toVar(); + const yoff = int( yoff_immutable ).toVar(); + const xoff = int( xoff_immutable ).toVar(); + const y = int( y_immutable ).toVar(); + const x = int( x_immutable ).toVar(); + const p = vec2( p_immutable ).toVar(); + const tmp = vec3( mx_cell_noise_vec3( vec2( x.add( xoff ), y.add( yoff ) ) ) ).toVar(); + const off = vec2( tmp.x, tmp.y ).toVar(); + off.subAssign( 0.5 ); + off.mulAssign( jitter ); + off.addAssign( 0.5 ); + const cellpos = vec2( vec2( float( x ), float( y ) ).add( off ) ).toVar(); + const diff = vec2( cellpos.sub( p ) ).toVar(); + + If( metric.equal( int( 2 ) ), () => { + + return abs( diff.x ).add( abs( diff.y ) ); + + } ); + + If( metric.equal( int( 3 ) ), () => { + + return max$1( abs( diff.x ), abs( diff.y ) ); + + } ); + + return dot( diff, diff ); + +} ).setLayout( { + name: 'mx_worley_distance_0', + type: 'float', + inputs: [ + { name: 'p', type: 'vec2' }, + { name: 'x', type: 'int' }, + { name: 'y', type: 'int' }, + { name: 'xoff', type: 'int' }, + { name: 'yoff', type: 'int' }, + { name: 'jitter', type: 'float' }, + { name: 'metric', type: 'int' } + ] +} ); + +const mx_worley_distance_1 = /*@__PURE__*/ Fn( ( [ p_immutable, x_immutable, y_immutable, z_immutable, xoff_immutable, yoff_immutable, zoff_immutable, jitter_immutable, metric_immutable ] ) => { + + const metric = int( metric_immutable ).toVar(); + const jitter = float( jitter_immutable ).toVar(); + const zoff = int( zoff_immutable ).toVar(); + const yoff = int( yoff_immutable ).toVar(); + const xoff = int( xoff_immutable ).toVar(); + const z = int( z_immutable ).toVar(); + const y = int( y_immutable ).toVar(); + const x = int( x_immutable ).toVar(); + const p = vec3( p_immutable ).toVar(); + const off = vec3( mx_cell_noise_vec3( vec3( x.add( xoff ), y.add( yoff ), z.add( zoff ) ) ) ).toVar(); + off.subAssign( 0.5 ); + off.mulAssign( jitter ); + off.addAssign( 0.5 ); + const cellpos = vec3( vec3( float( x ), float( y ), float( z ) ).add( off ) ).toVar(); + const diff = vec3( cellpos.sub( p ) ).toVar(); + + If( metric.equal( int( 2 ) ), () => { + + return abs( diff.x ).add( abs( diff.y ) ).add( abs( diff.z ) ); + + } ); + + If( metric.equal( int( 3 ) ), () => { + + return max$1( max$1( abs( diff.x ), abs( diff.y ) ), abs( diff.z ) ); + + } ); + + return dot( diff, diff ); + +} ).setLayout( { + name: 'mx_worley_distance_1', + type: 'float', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'x', type: 'int' }, + { name: 'y', type: 'int' }, + { name: 'z', type: 'int' }, + { name: 'xoff', type: 'int' }, + { name: 'yoff', type: 'int' }, + { name: 'zoff', type: 'int' }, + { name: 'jitter', type: 'float' }, + { name: 'metric', type: 'int' } + ] +} ); + +const mx_worley_distance = /*@__PURE__*/ overloadingFn( [ mx_worley_distance_0, mx_worley_distance_1 ] ); + +const mx_worley_noise_float_0 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { + + const metric = int( metric_immutable ).toVar(); + const jitter = float( jitter_immutable ).toVar(); + const p = vec2( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(); + const localpos = vec2( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ) ).toVar(); + const sqdist = float( 1e6 ).toVar(); + + Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + + const dist = float( mx_worley_distance( localpos, x, y, X, Y, jitter, metric ) ).toVar(); + sqdist.assign( min$1( sqdist, dist ) ); + + } ); + + } ); + + If( metric.equal( int( 0 ) ), () => { + + sqdist.assign( sqrt( sqdist ) ); + + } ); + + return sqdist; + +} ).setLayout( { + name: 'mx_worley_noise_float_0', + type: 'float', + inputs: [ + { name: 'p', type: 'vec2' }, + { name: 'jitter', type: 'float' }, + { name: 'metric', type: 'int' } + ] +} ); + +const mx_worley_noise_vec2_0 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { + + const metric = int( metric_immutable ).toVar(); + const jitter = float( jitter_immutable ).toVar(); + const p = vec2( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(); + const localpos = vec2( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ) ).toVar(); + const sqdist = vec2( 1e6, 1e6 ).toVar(); + + Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + + const dist = float( mx_worley_distance( localpos, x, y, X, Y, jitter, metric ) ).toVar(); + + If( dist.lessThan( sqdist.x ), () => { + + sqdist.y.assign( sqdist.x ); + sqdist.x.assign( dist ); + + } ).ElseIf( dist.lessThan( sqdist.y ), () => { + + sqdist.y.assign( dist ); + + } ); + + } ); + + } ); + + If( metric.equal( int( 0 ) ), () => { + + sqdist.assign( sqrt( sqdist ) ); + + } ); + + return sqdist; + +} ).setLayout( { + name: 'mx_worley_noise_vec2_0', + type: 'vec2', + inputs: [ + { name: 'p', type: 'vec2' }, + { name: 'jitter', type: 'float' }, + { name: 'metric', type: 'int' } + ] +} ); + +const mx_worley_noise_vec3_0 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { + + const metric = int( metric_immutable ).toVar(); + const jitter = float( jitter_immutable ).toVar(); + const p = vec2( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(); + const localpos = vec2( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ) ).toVar(); + const sqdist = vec3( 1e6, 1e6, 1e6 ).toVar(); + + Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + + const dist = float( mx_worley_distance( localpos, x, y, X, Y, jitter, metric ) ).toVar(); + + If( dist.lessThan( sqdist.x ), () => { + + sqdist.z.assign( sqdist.y ); + sqdist.y.assign( sqdist.x ); + sqdist.x.assign( dist ); + + } ).ElseIf( dist.lessThan( sqdist.y ), () => { + + sqdist.z.assign( sqdist.y ); + sqdist.y.assign( dist ); + + } ).ElseIf( dist.lessThan( sqdist.z ), () => { + + sqdist.z.assign( dist ); + + } ); + + } ); + + } ); + + If( metric.equal( int( 0 ) ), () => { + + sqdist.assign( sqrt( sqdist ) ); + + } ); + + return sqdist; + +} ).setLayout( { + name: 'mx_worley_noise_vec3_0', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec2' }, + { name: 'jitter', type: 'float' }, + { name: 'metric', type: 'int' } + ] +} ); + +const mx_worley_noise_float_1 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { + + const metric = int( metric_immutable ).toVar(); + const jitter = float( jitter_immutable ).toVar(); + const p = vec3( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(), Z = int().toVar(); + const localpos = vec3( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ), mx_floorfrac( p.z, Z ) ).toVar(); + const sqdist = float( 1e6 ).toVar(); + + Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'z', condition: '<=' }, ( { z } ) => { + + const dist = float( mx_worley_distance( localpos, x, y, z, X, Y, Z, jitter, metric ) ).toVar(); + sqdist.assign( min$1( sqdist, dist ) ); + + } ); + + } ); + + } ); + + If( metric.equal( int( 0 ) ), () => { + + sqdist.assign( sqrt( sqdist ) ); + + } ); + + return sqdist; + +} ).setLayout( { + name: 'mx_worley_noise_float_1', + type: 'float', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'jitter', type: 'float' }, + { name: 'metric', type: 'int' } + ] +} ); + +const mx_worley_noise_float$1 = /*@__PURE__*/ overloadingFn( [ mx_worley_noise_float_0, mx_worley_noise_float_1 ] ); + +const mx_worley_noise_vec2_1 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { + + const metric = int( metric_immutable ).toVar(); + const jitter = float( jitter_immutable ).toVar(); + const p = vec3( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(), Z = int().toVar(); + const localpos = vec3( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ), mx_floorfrac( p.z, Z ) ).toVar(); + const sqdist = vec2( 1e6, 1e6 ).toVar(); + + Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'z', condition: '<=' }, ( { z } ) => { + + const dist = float( mx_worley_distance( localpos, x, y, z, X, Y, Z, jitter, metric ) ).toVar(); + + If( dist.lessThan( sqdist.x ), () => { + + sqdist.y.assign( sqdist.x ); + sqdist.x.assign( dist ); + + } ).ElseIf( dist.lessThan( sqdist.y ), () => { + + sqdist.y.assign( dist ); + + } ); + + } ); + + } ); + + } ); + + If( metric.equal( int( 0 ) ), () => { + + sqdist.assign( sqrt( sqdist ) ); + + } ); + + return sqdist; + +} ).setLayout( { + name: 'mx_worley_noise_vec2_1', + type: 'vec2', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'jitter', type: 'float' }, + { name: 'metric', type: 'int' } + ] +} ); + +const mx_worley_noise_vec2$1 = /*@__PURE__*/ overloadingFn( [ mx_worley_noise_vec2_0, mx_worley_noise_vec2_1 ] ); + +const mx_worley_noise_vec3_1 = /*@__PURE__*/ Fn( ( [ p_immutable, jitter_immutable, metric_immutable ] ) => { + + const metric = int( metric_immutable ).toVar(); + const jitter = float( jitter_immutable ).toVar(); + const p = vec3( p_immutable ).toVar(); + const X = int().toVar(), Y = int().toVar(), Z = int().toVar(); + const localpos = vec3( mx_floorfrac( p.x, X ), mx_floorfrac( p.y, Y ), mx_floorfrac( p.z, Z ) ).toVar(); + const sqdist = vec3( 1e6, 1e6, 1e6 ).toVar(); + + Loop( { start: - 1, end: int( 1 ), name: 'x', condition: '<=' }, ( { x } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'y', condition: '<=' }, ( { y } ) => { + + Loop( { start: - 1, end: int( 1 ), name: 'z', condition: '<=' }, ( { z } ) => { + + const dist = float( mx_worley_distance( localpos, x, y, z, X, Y, Z, jitter, metric ) ).toVar(); + + If( dist.lessThan( sqdist.x ), () => { + + sqdist.z.assign( sqdist.y ); + sqdist.y.assign( sqdist.x ); + sqdist.x.assign( dist ); + + } ).ElseIf( dist.lessThan( sqdist.y ), () => { + + sqdist.z.assign( sqdist.y ); + sqdist.y.assign( dist ); + + } ).ElseIf( dist.lessThan( sqdist.z ), () => { + + sqdist.z.assign( dist ); + + } ); + + } ); + + } ); + + } ); + + If( metric.equal( int( 0 ) ), () => { + + sqdist.assign( sqrt( sqdist ) ); + + } ); + + return sqdist; + +} ).setLayout( { + name: 'mx_worley_noise_vec3_1', + type: 'vec3', + inputs: [ + { name: 'p', type: 'vec3' }, + { name: 'jitter', type: 'float' }, + { name: 'metric', type: 'int' } + ] +} ); + +const mx_worley_noise_vec3$1 = /*@__PURE__*/ overloadingFn( [ mx_worley_noise_vec3_0, mx_worley_noise_vec3_1 ] ); + +// Three.js Transpiler +// https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/stdlib/genglsl/lib/mx_hsv.glsl + + +const mx_hsvtorgb = /*@__PURE__*/ Fn( ( [ hsv ] ) => { + + const s = hsv.y; + const v = hsv.z; + + const result = vec3().toVar(); + + If( s.lessThan( 0.0001 ), () => { + + result.assign( vec3( v, v, v ) ); + + } ).Else( () => { + + let h = hsv.x; + h = h.sub( floor( h ) ).mul( 6.0 ).toVar(); // TODO: check what .toVar() is needed in node system cache + const hi = int( trunc( h ) ); + const f = h.sub( float( hi ) ); + const p = v.mul( s.oneMinus() ); + const q = v.mul( s.mul( f ).oneMinus() ); + const t = v.mul( s.mul( f.oneMinus() ).oneMinus() ); + + If( hi.equal( int( 0 ) ), () => { + + result.assign( vec3( v, t, p ) ); + + } ).ElseIf( hi.equal( int( 1 ) ), () => { + + result.assign( vec3( q, v, p ) ); + + } ).ElseIf( hi.equal( int( 2 ) ), () => { + + result.assign( vec3( p, v, t ) ); + + } ).ElseIf( hi.equal( int( 3 ) ), () => { + + result.assign( vec3( p, q, v ) ); + + } ).ElseIf( hi.equal( int( 4 ) ), () => { + + result.assign( vec3( t, p, v ) ); + + } ).Else( () => { + + result.assign( vec3( v, p, q ) ); + + } ); + + } ); + + return result; + +} ).setLayout( { + name: 'mx_hsvtorgb', + type: 'vec3', + inputs: [ + { name: 'hsv', type: 'vec3' } + ] +} ); + +const mx_rgbtohsv = /*@__PURE__*/ Fn( ( [ c_immutable ] ) => { + + const c = vec3( c_immutable ).toVar(); + const r = float( c.x ).toVar(); + const g = float( c.y ).toVar(); + const b = float( c.z ).toVar(); + const mincomp = float( min$1( r, min$1( g, b ) ) ).toVar(); + const maxcomp = float( max$1( r, max$1( g, b ) ) ).toVar(); + const delta = float( maxcomp.sub( mincomp ) ).toVar(); + const h = float().toVar(), s = float().toVar(), v = float().toVar(); + v.assign( maxcomp ); + + If( maxcomp.greaterThan( 0.0 ), () => { + + s.assign( delta.div( maxcomp ) ); + + } ).Else( () => { + + s.assign( 0.0 ); + + } ); + + If( s.lessThanEqual( 0.0 ), () => { + + h.assign( 0.0 ); + + } ).Else( () => { + + If( r.greaterThanEqual( maxcomp ), () => { + + h.assign( g.sub( b ).div( delta ) ); + + } ).ElseIf( g.greaterThanEqual( maxcomp ), () => { + + h.assign( add( 2.0, b.sub( r ).div( delta ) ) ); + + } ).Else( () => { + + h.assign( add( 4.0, r.sub( g ).div( delta ) ) ); + + } ); + + h.mulAssign( 1.0 / 6.0 ); + + If( h.lessThan( 0.0 ), () => { + + h.addAssign( 1.0 ); + + } ); + + } ); + + return vec3( h, s, v ); + +} ).setLayout( { + name: 'mx_rgbtohsv', + type: 'vec3', + inputs: [ + { name: 'c', type: 'vec3' } + ] +} ); + +// Three.js Transpiler +// https://github.com/AcademySoftwareFoundation/MaterialX/blob/main/libraries/stdlib/genglsl/lib/mx_transform_color.glsl + + +const mx_srgb_texture_to_lin_rec709 = /*@__PURE__*/ Fn( ( [ color_immutable ] ) => { + + const color = vec3( color_immutable ).toVar(); + const isAbove = bvec3( greaterThan( color, vec3( 0.04045 ) ) ).toVar(); + const linSeg = vec3( color.div( 12.92 ) ).toVar(); + const powSeg = vec3( pow( max$1( color.add( vec3( 0.055 ) ), vec3( 0.0 ) ).div( 1.055 ), vec3( 2.4 ) ) ).toVar(); + + return mix( linSeg, powSeg, isAbove ); + +} ).setLayout( { + name: 'mx_srgb_texture_to_lin_rec709', + type: 'vec3', + inputs: [ + { name: 'color', type: 'vec3' } + ] +} ); + +const mx_aastep = ( threshold, value ) => { + + threshold = float( threshold ); + value = float( value ); + + const afwidth = vec2( value.dFdx(), value.dFdy() ).length().mul( 0.70710678118654757 ); + + return smoothstep( threshold.sub( afwidth ), threshold.add( afwidth ), value ); + +}; + +const _ramp = ( a, b, uv, p ) => mix( a, b, uv[ p ].clamp() ); +const mx_ramplr = ( valuel, valuer, texcoord = uv() ) => _ramp( valuel, valuer, texcoord, 'x' ); +const mx_ramptb = ( valuet, valueb, texcoord = uv() ) => _ramp( valuet, valueb, texcoord, 'y' ); + +const _split = ( a, b, center, uv, p ) => mix( a, b, mx_aastep( center, uv[ p ] ) ); +const mx_splitlr = ( valuel, valuer, center, texcoord = uv() ) => _split( valuel, valuer, center, texcoord, 'x' ); +const mx_splittb = ( valuet, valueb, center, texcoord = uv() ) => _split( valuet, valueb, center, texcoord, 'y' ); + +const mx_transform_uv = ( uv_scale = 1, uv_offset = 0, uv_geo = uv() ) => uv_geo.mul( uv_scale ).add( uv_offset ); + +const mx_safepower = ( in1, in2 = 1 ) => { + + in1 = float( in1 ); + + return in1.abs().pow( in2 ).mul( in1.sign() ); + +}; + +const mx_contrast = ( input, amount = 1, pivot = .5 ) => float( input ).sub( pivot ).mul( amount ).add( pivot ); + +const mx_noise_float = ( texcoord = uv(), amplitude = 1, pivot = 0 ) => mx_perlin_noise_float( texcoord.convert( 'vec2|vec3' ) ).mul( amplitude ).add( pivot ); +//export const mx_noise_vec2 = ( texcoord = uv(), amplitude = 1, pivot = 0 ) => mx_perlin_noise_vec3( texcoord.convert( 'vec2|vec3' ) ).mul( amplitude ).add( pivot ); +const mx_noise_vec3 = ( texcoord = uv(), amplitude = 1, pivot = 0 ) => mx_perlin_noise_vec3( texcoord.convert( 'vec2|vec3' ) ).mul( amplitude ).add( pivot ); +const mx_noise_vec4 = ( texcoord = uv(), amplitude = 1, pivot = 0 ) => { + + texcoord = texcoord.convert( 'vec2|vec3' ); // overloading type + + const noise_vec4 = vec4( mx_perlin_noise_vec3( texcoord ), mx_perlin_noise_float( texcoord.add( vec2( 19, 73 ) ) ) ); + + return noise_vec4.mul( amplitude ).add( pivot ); + +}; + +const mx_worley_noise_float = ( texcoord = uv(), jitter = 1 ) => mx_worley_noise_float$1( texcoord.convert( 'vec2|vec3' ), jitter, int( 1 ) ); +const mx_worley_noise_vec2 = ( texcoord = uv(), jitter = 1 ) => mx_worley_noise_vec2$1( texcoord.convert( 'vec2|vec3' ), jitter, int( 1 ) ); +const mx_worley_noise_vec3 = ( texcoord = uv(), jitter = 1 ) => mx_worley_noise_vec3$1( texcoord.convert( 'vec2|vec3' ), jitter, int( 1 ) ); + +const mx_cell_noise_float = ( texcoord = uv() ) => mx_cell_noise_float$1( texcoord.convert( 'vec2|vec3' ) ); + +const mx_fractal_noise_float = ( position = uv(), octaves = 3, lacunarity = 2, diminish = .5, amplitude = 1 ) => mx_fractal_noise_float$1( position, int( octaves ), lacunarity, diminish ).mul( amplitude ); +const mx_fractal_noise_vec2 = ( position = uv(), octaves = 3, lacunarity = 2, diminish = .5, amplitude = 1 ) => mx_fractal_noise_vec2$1( position, int( octaves ), lacunarity, diminish ).mul( amplitude ); +const mx_fractal_noise_vec3 = ( position = uv(), octaves = 3, lacunarity = 2, diminish = .5, amplitude = 1 ) => mx_fractal_noise_vec3$1( position, int( octaves ), lacunarity, diminish ).mul( amplitude ); +const mx_fractal_noise_vec4 = ( position = uv(), octaves = 3, lacunarity = 2, diminish = .5, amplitude = 1 ) => mx_fractal_noise_vec4$1( position, int( octaves ), lacunarity, diminish ).mul( amplitude ); + +const getShIrradianceAt = /*@__PURE__*/ Fn( ( [ normal, shCoefficients ] ) => { + + // normal is assumed to have unit length + + const x = normal.x, y = normal.y, z = normal.z; + + // band 0 + let result = shCoefficients.element( 0 ).mul( 0.886227 ); + + // band 1 + result = result.add( shCoefficients.element( 1 ).mul( 2.0 * 0.511664 ).mul( y ) ); + result = result.add( shCoefficients.element( 2 ).mul( 2.0 * 0.511664 ).mul( z ) ); + result = result.add( shCoefficients.element( 3 ).mul( 2.0 * 0.511664 ).mul( x ) ); + + // band 2 + result = result.add( shCoefficients.element( 4 ).mul( 2.0 * 0.429043 ).mul( x ).mul( y ) ); + result = result.add( shCoefficients.element( 5 ).mul( 2.0 * 0.429043 ).mul( y ).mul( z ) ); + result = result.add( shCoefficients.element( 6 ).mul( z.mul( z ).mul( 0.743125 ).sub( 0.247708 ) ) ); + result = result.add( shCoefficients.element( 7 ).mul( 2.0 * 0.429043 ).mul( x ).mul( z ) ); + result = result.add( shCoefficients.element( 8 ).mul( 0.429043 ).mul( mul( x, x ).sub( mul( y, y ) ) ) ); + + return result; + +} ); + +class PointLightNode extends AnalyticLightNode { + + static get type() { + + return 'PointLightNode'; + + } + + constructor( light = null ) { + + super( light ); + + this.cutoffDistanceNode = uniform( 0 ).setGroup( renderGroup ); + this.decayExponentNode = uniform( 0 ).setGroup( renderGroup ); + + } + + update( frame ) { + + const { light } = this; + + super.update( frame ); + + this.cutoffDistanceNode.value = light.distance; + this.decayExponentNode.value = light.decay; + + } + + setup( builder ) { + + const { colorNode, cutoffDistanceNode, decayExponentNode, light } = this; + + const lightingModel = builder.context.lightingModel; + + const lVector = lightViewPosition( light ).sub( positionView ); // @TODO: Add it into LightNode + + const lightDirection = lVector.normalize(); + const lightDistance = lVector.length(); + + const lightAttenuation = getDistanceAttenuation( { + lightDistance, + cutoffDistance: cutoffDistanceNode, + decayExponent: decayExponentNode + } ); + + const lightColor = colorNode.mul( lightAttenuation ); + + const reflectedLight = builder.context.reflectedLight; + + lightingModel.direct( { + lightDirection, + lightColor, + reflectedLight + }, builder.stack, builder ); + + } + +} + +class DirectionalLightNode extends AnalyticLightNode { + + static get type() { + + return 'DirectionalLightNode'; + + } + + constructor( light = null ) { + + super( light ); + + } + + setup( builder ) { + + super.setup( builder ); + + const lightingModel = builder.context.lightingModel; + + const lightColor = this.colorNode; + const lightDirection = lightTargetDirection( this.light ); + const reflectedLight = builder.context.reflectedLight; + + lightingModel.direct( { + lightDirection, + lightColor, + reflectedLight + }, builder.stack, builder ); + + } + +} + +const _matrix41 = /*@__PURE__*/ new Matrix4(); +const _matrix42 = /*@__PURE__*/ new Matrix4(); + +let ltcLib = null; + +class RectAreaLightNode extends AnalyticLightNode { + + static get type() { + + return 'RectAreaLightNode'; + + } + + constructor( light = null ) { + + super( light ); + + this.halfHeight = uniform( new Vector3() ).setGroup( renderGroup ); + this.halfWidth = uniform( new Vector3() ).setGroup( renderGroup ); + + } + + update( frame ) { + + super.update( frame ); + + const { light } = this; + + const viewMatrix = frame.camera.matrixWorldInverse; + + _matrix42.identity(); + _matrix41.copy( light.matrixWorld ); + _matrix41.premultiply( viewMatrix ); + _matrix42.extractRotation( _matrix41 ); + + this.halfWidth.value.set( light.width * 0.5, 0.0, 0.0 ); + this.halfHeight.value.set( 0.0, light.height * 0.5, 0.0 ); + + this.halfWidth.value.applyMatrix4( _matrix42 ); + this.halfHeight.value.applyMatrix4( _matrix42 ); + + } + + setup( builder ) { + + super.setup( builder ); + + let ltc_1, ltc_2; + + if ( builder.isAvailable( 'float32Filterable' ) ) { + + ltc_1 = texture( ltcLib.LTC_FLOAT_1 ); + ltc_2 = texture( ltcLib.LTC_FLOAT_2 ); + + } else { + + ltc_1 = texture( ltcLib.LTC_HALF_1 ); + ltc_2 = texture( ltcLib.LTC_HALF_2 ); + + } + + const { colorNode, light } = this; + const lightingModel = builder.context.lightingModel; + + const lightPosition = lightViewPosition( light ); + const reflectedLight = builder.context.reflectedLight; + + lightingModel.directRectArea( { + lightColor: colorNode, + lightPosition, + halfWidth: this.halfWidth, + halfHeight: this.halfHeight, + reflectedLight, + ltc_1, + ltc_2 + }, builder.stack, builder ); + + } + + static setLTC( ltc ) { + + ltcLib = ltc; + + } + +} + +class SpotLightNode extends AnalyticLightNode { + + static get type() { + + return 'SpotLightNode'; + + } + + constructor( light = null ) { + + super( light ); + + this.coneCosNode = uniform( 0 ).setGroup( renderGroup ); + this.penumbraCosNode = uniform( 0 ).setGroup( renderGroup ); + + this.cutoffDistanceNode = uniform( 0 ).setGroup( renderGroup ); + this.decayExponentNode = uniform( 0 ).setGroup( renderGroup ); + + } + + update( frame ) { + + super.update( frame ); + + const { light } = this; + + this.coneCosNode.value = Math.cos( light.angle ); + this.penumbraCosNode.value = Math.cos( light.angle * ( 1 - light.penumbra ) ); + + this.cutoffDistanceNode.value = light.distance; + this.decayExponentNode.value = light.decay; + + } + + getSpotAttenuation( angleCosine ) { + + const { coneCosNode, penumbraCosNode } = this; + + return smoothstep( coneCosNode, penumbraCosNode, angleCosine ); + + } + + setup( builder ) { + + super.setup( builder ); + + const lightingModel = builder.context.lightingModel; + + const { colorNode, cutoffDistanceNode, decayExponentNode, light } = this; + + const lVector = lightViewPosition( light ).sub( positionView ); // @TODO: Add it into LightNode + + const lightDirection = lVector.normalize(); + const angleCos = lightDirection.dot( lightTargetDirection( light ) ); + const spotAttenuation = this.getSpotAttenuation( angleCos ); + + const lightDistance = lVector.length(); + + const lightAttenuation = getDistanceAttenuation( { + lightDistance, + cutoffDistance: cutoffDistanceNode, + decayExponent: decayExponentNode + } ); + + const lightColor = colorNode.mul( spotAttenuation ).mul( lightAttenuation ); + + const reflectedLight = builder.context.reflectedLight; + + lightingModel.direct( { + lightDirection, + lightColor, + reflectedLight + }, builder.stack, builder ); + + } + +} + +class IESSpotLightNode extends SpotLightNode { + + static get type() { + + return 'IESSpotLightNode'; + + } + + getSpotAttenuation( angleCosine ) { + + const iesMap = this.light.iesMap; + + let spotAttenuation = null; + + if ( iesMap && iesMap.isTexture === true ) { + + const angle = angleCosine.acos().mul( 1.0 / Math.PI ); + + spotAttenuation = texture( iesMap, vec2( angle, 0 ), 0 ).r; + + } else { + + spotAttenuation = super.getSpotAttenuation( angleCosine ); + + } + + return spotAttenuation; + + } + +} + +class AmbientLightNode extends AnalyticLightNode { + + static get type() { + + return 'AmbientLightNode'; + + } + + constructor( light = null ) { + + super( light ); + + } + + setup( { context } ) { + + context.irradiance.addAssign( this.colorNode ); + + } + +} + +class HemisphereLightNode extends AnalyticLightNode { + + static get type() { + + return 'HemisphereLightNode'; + + } + + constructor( light = null ) { + + super( light ); + + this.lightPositionNode = lightPosition( light ); + this.lightDirectionNode = this.lightPositionNode.normalize(); + + this.groundColorNode = uniform( new Color() ).setGroup( renderGroup ); + + } + + update( frame ) { + + const { light } = this; + + super.update( frame ); + + this.lightPositionNode.object3d = light; + + this.groundColorNode.value.copy( light.groundColor ).multiplyScalar( light.intensity ); + + } + + setup( builder ) { + + const { colorNode, groundColorNode, lightDirectionNode } = this; + + const dotNL = normalView.dot( lightDirectionNode ); + const hemiDiffuseWeight = dotNL.mul( 0.5 ).add( 0.5 ); + + const irradiance = mix( groundColorNode, colorNode, hemiDiffuseWeight ); + + builder.context.irradiance.addAssign( irradiance ); + + } + +} + +class LightProbeNode extends AnalyticLightNode { + + static get type() { + + return 'LightProbeNode'; + + } + + constructor( light = null ) { + + super( light ); + + const array = []; + + for ( let i = 0; i < 9; i ++ ) array.push( new Vector3() ); + + this.lightProbe = uniformArray( array ); + + } + + update( frame ) { + + const { light } = this; + + super.update( frame ); + + // + + for ( let i = 0; i < 9; i ++ ) { + + this.lightProbe.array[ i ].copy( light.sh.coefficients[ i ] ).multiplyScalar( light.intensity ); + + } + + } + + setup( builder ) { + + const irradiance = getShIrradianceAt( normalWorld, this.lightProbe ); + + builder.context.irradiance.addAssign( irradiance ); + + } + +} + +class NodeParser { + + parseFunction( /*source*/ ) { + + console.warn( 'Abstract function.' ); + + } + +} + +class NodeFunction { + + constructor( type, inputs, name = '', precision = '' ) { + + this.type = type; + this.inputs = inputs; + this.name = name; + this.precision = precision; + + } + + getCode( /*name = this.name*/ ) { + + console.warn( 'Abstract function.' ); + + } + +} + +NodeFunction.isNodeFunction = true; + +const declarationRegexp$1 = /^\s*(highp|mediump|lowp)?\s*([a-z_0-9]+)\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)/i; +const propertiesRegexp$1 = /[a-z_0-9]+/ig; + +const pragmaMain = '#pragma main'; + +const parse$1 = ( source ) => { + + source = source.trim(); + + const pragmaMainIndex = source.indexOf( pragmaMain ); + + const mainCode = pragmaMainIndex !== - 1 ? source.slice( pragmaMainIndex + pragmaMain.length ) : source; + + const declaration = mainCode.match( declarationRegexp$1 ); + + if ( declaration !== null && declaration.length === 5 ) { + + // tokenizer + + const inputsCode = declaration[ 4 ]; + const propsMatches = []; + + let nameMatch = null; + + while ( ( nameMatch = propertiesRegexp$1.exec( inputsCode ) ) !== null ) { + + propsMatches.push( nameMatch ); + + } + + // parser + + const inputs = []; + + let i = 0; + + while ( i < propsMatches.length ) { + + const isConst = propsMatches[ i ][ 0 ] === 'const'; + + if ( isConst === true ) { + + i ++; + + } + + let qualifier = propsMatches[ i ][ 0 ]; + + if ( qualifier === 'in' || qualifier === 'out' || qualifier === 'inout' ) { + + i ++; + + } else { + + qualifier = ''; + + } + + const type = propsMatches[ i ++ ][ 0 ]; + + let count = Number.parseInt( propsMatches[ i ][ 0 ] ); + + if ( Number.isNaN( count ) === false ) i ++; + else count = null; + + const name = propsMatches[ i ++ ][ 0 ]; + + inputs.push( new NodeFunctionInput( type, name, count, qualifier, isConst ) ); + + } + + // + + const blockCode = mainCode.substring( declaration[ 0 ].length ); + + const name = declaration[ 3 ] !== undefined ? declaration[ 3 ] : ''; + const type = declaration[ 2 ]; + + const precision = declaration[ 1 ] !== undefined ? declaration[ 1 ] : ''; + + const headerCode = pragmaMainIndex !== - 1 ? source.slice( 0, pragmaMainIndex ) : ''; + + return { + type, + inputs, + name, + precision, + inputsCode, + blockCode, + headerCode + }; + + } else { + + throw new Error( 'FunctionNode: Function is not a GLSL code.' ); + + } + +}; + +class GLSLNodeFunction extends NodeFunction { + + constructor( source ) { + + const { type, inputs, name, precision, inputsCode, blockCode, headerCode } = parse$1( source ); + + super( type, inputs, name, precision ); + + this.inputsCode = inputsCode; + this.blockCode = blockCode; + this.headerCode = headerCode; + + } + + getCode( name = this.name ) { + + let code; + + const blockCode = this.blockCode; + + if ( blockCode !== '' ) { + + const { type, inputsCode, headerCode, precision } = this; + + let declarationCode = `${ type } ${ name } ( ${ inputsCode.trim() } )`; + + if ( precision !== '' ) { + + declarationCode = `${ precision } ${ declarationCode }`; + + } + + code = headerCode + declarationCode + blockCode; + + } else { + + // interface function + + code = ''; + + } + + return code; + + } + +} + +class GLSLNodeParser extends NodeParser { + + parseFunction( source ) { + + return new GLSLNodeFunction( source ); + + } + +} + +function painterSortStable( a, b ) { + + if ( a.groupOrder !== b.groupOrder ) { + + return a.groupOrder - b.groupOrder; + + } else if ( a.renderOrder !== b.renderOrder ) { + + return a.renderOrder - b.renderOrder; + + } else if ( a.material.id !== b.material.id ) { + + return a.material.id - b.material.id; + + } else if ( a.z !== b.z ) { + + return a.z - b.z; + + } else { + + return a.id - b.id; + + } + +} + +function reversePainterSortStable( a, b ) { + + if ( a.groupOrder !== b.groupOrder ) { + + return a.groupOrder - b.groupOrder; + + } else if ( a.renderOrder !== b.renderOrder ) { + + return a.renderOrder - b.renderOrder; + + } else if ( a.z !== b.z ) { + + return b.z - a.z; + + } else { + + return a.id - b.id; + + } + +} + +class RenderList { + + constructor() { + + this.renderItems = []; + this.renderItemsIndex = 0; + + this.opaque = []; + this.transparent = []; + this.bundles = []; + + this.lightsNode = new LightsNode( [] ); + this.lightsArray = []; + + this.occlusionQueryCount = 0; + + } + + begin() { + + this.renderItemsIndex = 0; + + this.opaque.length = 0; + this.transparent.length = 0; + this.bundles.length = 0; + + this.lightsArray.length = 0; + + this.occlusionQueryCount = 0; + + return this; + + } + + getNextRenderItem( object, geometry, material, groupOrder, z, group ) { + + let renderItem = this.renderItems[ this.renderItemsIndex ]; + + if ( renderItem === undefined ) { + + renderItem = { + id: object.id, + object: object, + geometry: geometry, + material: material, + groupOrder: groupOrder, + renderOrder: object.renderOrder, + z: z, + group: group + }; + + this.renderItems[ this.renderItemsIndex ] = renderItem; + + } else { + + renderItem.id = object.id; + renderItem.object = object; + renderItem.geometry = geometry; + renderItem.material = material; + renderItem.groupOrder = groupOrder; + renderItem.renderOrder = object.renderOrder; + renderItem.z = z; + renderItem.group = group; + + } + + this.renderItemsIndex ++; + + return renderItem; + + } + + push( object, geometry, material, groupOrder, z, group ) { + + const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group ); + + if ( object.occlusionTest === true ) this.occlusionQueryCount ++; + + ( material.transparent === true || material.transmission > 0 ? this.transparent : this.opaque ).push( renderItem ); + + } + + unshift( object, geometry, material, groupOrder, z, group ) { + + const renderItem = this.getNextRenderItem( object, geometry, material, groupOrder, z, group ); + + ( material.transparent === true ? this.transparent : this.opaque ).unshift( renderItem ); + + } + + pushBundle( group ) { + + this.bundles.push( group ); + + } + + pushLight( light ) { + + this.lightsArray.push( light ); + + } + + getLightsNode() { + + return this.lightsNode.fromLights( this.lightsArray ); + + } + + sort( customOpaqueSort, customTransparentSort ) { + + if ( this.opaque.length > 1 ) this.opaque.sort( customOpaqueSort || painterSortStable ); + if ( this.transparent.length > 1 ) this.transparent.sort( customTransparentSort || reversePainterSortStable ); + + } + + finish() { + + // update lights + + this.lightsNode.setLights( this.lightsArray ); + + // Clear references from inactive renderItems in the list + + for ( let i = this.renderItemsIndex, il = this.renderItems.length; i < il; i ++ ) { + + const renderItem = this.renderItems[ i ]; + + if ( renderItem.id === null ) break; + + renderItem.id = null; + renderItem.object = null; + renderItem.geometry = null; + renderItem.material = null; + renderItem.groupOrder = null; + renderItem.renderOrder = null; + renderItem.z = null; + renderItem.group = null; + + } + + } + +} + +class RenderLists { + + constructor() { + + this.lists = new ChainMap(); + + } + + get( scene, camera ) { + + const lists = this.lists; + const keys = [ scene, camera ]; + + let list = lists.get( keys ); + + if ( list === undefined ) { + + list = new RenderList(); + lists.set( keys, list ); + + } + + return list; + + } + + dispose() { + + this.lists = new ChainMap(); + + } + +} + +let id = 0; + +class RenderContext { + + constructor() { + + this.id = id ++; + + this.color = true; + this.clearColor = true; + this.clearColorValue = { r: 0, g: 0, b: 0, a: 1 }; + + this.depth = true; + this.clearDepth = true; + this.clearDepthValue = 1; + + this.stencil = false; + this.clearStencil = true; + this.clearStencilValue = 1; + + this.viewport = false; + this.viewportValue = new Vector4(); + + this.scissor = false; + this.scissorValue = new Vector4(); + + this.textures = null; + this.depthTexture = null; + this.activeCubeFace = 0; + this.sampleCount = 1; + + this.width = 0; + this.height = 0; + + this.isRenderContext = true; + + } + + getCacheKey() { + + return getCacheKey( this ); + + } + +} + +function getCacheKey( renderContext ) { + + const { textures, activeCubeFace } = renderContext; + + const values = [ activeCubeFace ]; + + for ( const texture of textures ) { + + values.push( texture.id ); + + } + + return hashArray( values ); + +} + +class RenderContexts { + + constructor() { + + this.chainMaps = {}; + + } + + get( scene, camera, renderTarget = null ) { + + const chainKey = [ scene, camera ]; + + let attachmentState; + + if ( renderTarget === null ) { + + attachmentState = 'default'; + + } else { + + const format = renderTarget.texture.format; + const count = renderTarget.textures.length; + + attachmentState = `${ count }:${ format }:${ renderTarget.samples }:${ renderTarget.depthBuffer }:${ renderTarget.stencilBuffer }`; + + } + + const chainMap = this.getChainMap( attachmentState ); + + let renderState = chainMap.get( chainKey ); + + if ( renderState === undefined ) { + + renderState = new RenderContext(); + + chainMap.set( chainKey, renderState ); + + } + + if ( renderTarget !== null ) renderState.sampleCount = renderTarget.samples === 0 ? 1 : renderTarget.samples; + + return renderState; + + } + + getChainMap( attachmentState ) { + + return this.chainMaps[ attachmentState ] || ( this.chainMaps[ attachmentState ] = new ChainMap() ); + + } + + dispose() { + + this.chainMaps = {}; + + } + +} + +const _size = /*@__PURE__*/ new Vector3(); + +class Textures extends DataMap { + + constructor( renderer, backend, info ) { + + super(); + + this.renderer = renderer; + this.backend = backend; + this.info = info; + + } + + updateRenderTarget( renderTarget, activeMipmapLevel = 0 ) { + + const renderTargetData = this.get( renderTarget ); + + const sampleCount = renderTarget.samples === 0 ? 1 : renderTarget.samples; + const depthTextureMips = renderTargetData.depthTextureMips || ( renderTargetData.depthTextureMips = {} ); + + const textures = renderTarget.textures; + + const size = this.getSize( textures[ 0 ] ); + + const mipWidth = size.width >> activeMipmapLevel; + const mipHeight = size.height >> activeMipmapLevel; + + let depthTexture = renderTarget.depthTexture || depthTextureMips[ activeMipmapLevel ]; + let textureNeedsUpdate = false; + + if ( depthTexture === undefined ) { + + depthTexture = new DepthTexture(); + depthTexture.format = renderTarget.stencilBuffer ? DepthStencilFormat : DepthFormat; + depthTexture.type = renderTarget.stencilBuffer ? UnsignedInt248Type : UnsignedIntType; // FloatType + depthTexture.image.width = mipWidth; + depthTexture.image.height = mipHeight; + + depthTextureMips[ activeMipmapLevel ] = depthTexture; + + } + + if ( renderTargetData.width !== size.width || size.height !== renderTargetData.height ) { + + textureNeedsUpdate = true; + depthTexture.needsUpdate = true; + + depthTexture.image.width = mipWidth; + depthTexture.image.height = mipHeight; + + } + + renderTargetData.width = size.width; + renderTargetData.height = size.height; + renderTargetData.textures = textures; + renderTargetData.depthTexture = depthTexture; + renderTargetData.depth = renderTarget.depthBuffer; + renderTargetData.stencil = renderTarget.stencilBuffer; + renderTargetData.renderTarget = renderTarget; + + if ( renderTargetData.sampleCount !== sampleCount ) { + + textureNeedsUpdate = true; + depthTexture.needsUpdate = true; + + renderTargetData.sampleCount = sampleCount; + + } + + // + + const options = { sampleCount }; + + for ( let i = 0; i < textures.length; i ++ ) { + + const texture = textures[ i ]; + + if ( textureNeedsUpdate ) texture.needsUpdate = true; + + this.updateTexture( texture, options ); + + } + + this.updateTexture( depthTexture, options ); + + // dispose handler + + if ( renderTargetData.initialized !== true ) { + + renderTargetData.initialized = true; + + // dispose + + const onDispose = () => { + + renderTarget.removeEventListener( 'dispose', onDispose ); + + for ( let i = 0; i < textures.length; i ++ ) { + + this._destroyTexture( textures[ i ] ); + + } + + this._destroyTexture( depthTexture ); + + this.delete( renderTarget ); + + }; + + renderTarget.addEventListener( 'dispose', onDispose ); + + } + + } + + updateTexture( texture, options = {} ) { + + const textureData = this.get( texture ); + if ( textureData.initialized === true && textureData.version === texture.version ) return; + + const isRenderTarget = texture.isRenderTargetTexture || texture.isDepthTexture || texture.isFramebufferTexture; + const backend = this.backend; + + if ( isRenderTarget && textureData.initialized === true ) { + + // it's an update + + backend.destroySampler( texture ); + backend.destroyTexture( texture ); + + } + + // + + if ( texture.isFramebufferTexture ) { + + const renderer = this.renderer; + const renderTarget = renderer.getRenderTarget(); + + if ( renderTarget ) { + + texture.type = renderTarget.texture.type; + + } else { + + texture.type = UnsignedByteType; + + } + + } + + // + + const { width, height, depth } = this.getSize( texture ); + + options.width = width; + options.height = height; + options.depth = depth; + options.needsMipmaps = this.needsMipmaps( texture ); + options.levels = options.needsMipmaps ? this.getMipLevels( texture, width, height ) : 1; + + // + + if ( isRenderTarget || texture.isStorageTexture === true ) { + + backend.createSampler( texture ); + backend.createTexture( texture, options ); + + textureData.generation = texture.version; + + } else { + + const needsCreate = textureData.initialized !== true; + + if ( needsCreate ) backend.createSampler( texture ); + + if ( texture.version > 0 ) { + + const image = texture.image; + + if ( image === undefined ) { + + console.warn( 'THREE.Renderer: Texture marked for update but image is undefined.' ); + + } else if ( image.complete === false ) { + + console.warn( 'THREE.Renderer: Texture marked for update but image is incomplete.' ); + + } else { + + if ( texture.images ) { + + const images = []; + + for ( const image of texture.images ) { + + images.push( image ); + + } + + options.images = images; + + } else { + + options.image = image; + + } + + if ( textureData.isDefaultTexture === undefined || textureData.isDefaultTexture === true ) { + + backend.createTexture( texture, options ); + + textureData.isDefaultTexture = false; + textureData.generation = texture.version; + + } + + if ( texture.source.dataReady === true ) backend.updateTexture( texture, options ); + + if ( options.needsMipmaps && texture.mipmaps.length === 0 ) backend.generateMipmaps( texture ); + + } + + } else { + + // async update + + backend.createDefaultTexture( texture ); + + textureData.isDefaultTexture = true; + textureData.generation = texture.version; + + } + + } + + // dispose handler + + if ( textureData.initialized !== true ) { + + textureData.initialized = true; + textureData.generation = texture.version; + + // + + this.info.memory.textures ++; + + // dispose + + const onDispose = () => { + + texture.removeEventListener( 'dispose', onDispose ); + + this._destroyTexture( texture ); + + this.info.memory.textures --; + + }; + + texture.addEventListener( 'dispose', onDispose ); + + } + + // + + textureData.version = texture.version; + + } + + getSize( texture, target = _size ) { + + let image = texture.images ? texture.images[ 0 ] : texture.image; + + if ( image ) { + + if ( image.image !== undefined ) image = image.image; + + target.width = image.width; + target.height = image.height; + target.depth = texture.isCubeTexture ? 6 : ( image.depth || 1 ); + + } else { + + target.width = target.height = target.depth = 1; + + } + + return target; + + } + + getMipLevels( texture, width, height ) { + + let mipLevelCount; + + if ( texture.isCompressedTexture ) { + + mipLevelCount = texture.mipmaps.length; + + } else { + + mipLevelCount = Math.floor( Math.log2( Math.max( width, height ) ) ) + 1; + + } + + return mipLevelCount; + + } + + needsMipmaps( texture ) { + + if ( this.isEnvironmentTexture( texture ) ) return true; + + return ( texture.isCompressedTexture === true ) || ( ( texture.minFilter !== NearestFilter ) && ( texture.minFilter !== LinearFilter ) ); + + } + + isEnvironmentTexture( texture ) { + + const mapping = texture.mapping; + + return ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) || ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping ); + + } + + _destroyTexture( texture ) { + + this.backend.destroySampler( texture ); + this.backend.destroyTexture( texture ); + + this.delete( texture ); + + } + +} + +class Color4 extends Color { + + constructor( r, g, b, a = 1 ) { + + super( r, g, b ); + + this.a = a; + + } + + set( r, g, b, a = 1 ) { + + this.a = a; + + return super.set( r, g, b ); + + } + + copy( color ) { + + if ( color.a !== undefined ) this.a = color.a; + + return super.copy( color ); + + } + + clone() { + + return new this.constructor( this.r, this.g, this.b, this.a ); + + } + +} + +const _clearColor = /*@__PURE__*/ new Color4(); + +class Background extends DataMap { + + constructor( renderer, nodes ) { + + super(); + + this.renderer = renderer; + this.nodes = nodes; + + } + + update( scene, renderList, renderContext ) { + + const renderer = this.renderer; + const background = this.nodes.getBackgroundNode( scene ) || scene.background; + + let forceClear = false; + + if ( background === null ) { + + // no background settings, use clear color configuration from the renderer + + renderer._clearColor.getRGB( _clearColor, LinearSRGBColorSpace ); + _clearColor.a = renderer._clearColor.a; + + } else if ( background.isColor === true ) { + + // background is an opaque color + + background.getRGB( _clearColor, LinearSRGBColorSpace ); + _clearColor.a = 1; + + forceClear = true; + + } else if ( background.isNode === true ) { + + const sceneData = this.get( scene ); + const backgroundNode = background; + + _clearColor.copy( renderer._clearColor ); + + let backgroundMesh = sceneData.backgroundMesh; + + if ( backgroundMesh === undefined ) { + + const backgroundMeshNode = context( vec4( backgroundNode ).mul( backgroundIntensity ), { + // @TODO: Add Texture2D support using node context + getUV: () => normalWorld, + getTextureLevel: () => backgroundBlurriness + } ); + + let viewProj = modelViewProjection(); + viewProj = viewProj.setZ( viewProj.w ); + + const nodeMaterial = new NodeMaterial(); + nodeMaterial.name = 'Background.material'; + nodeMaterial.side = BackSide; + nodeMaterial.depthTest = false; + nodeMaterial.depthWrite = false; + nodeMaterial.fog = false; + nodeMaterial.lights = false; + nodeMaterial.vertexNode = viewProj; + nodeMaterial.colorNode = backgroundMeshNode; + + sceneData.backgroundMeshNode = backgroundMeshNode; + sceneData.backgroundMesh = backgroundMesh = new Mesh( new SphereGeometry( 1, 32, 32 ), nodeMaterial ); + backgroundMesh.frustumCulled = false; + backgroundMesh.name = 'Background.mesh'; + + backgroundMesh.onBeforeRender = function ( renderer, scene, camera ) { + + this.matrixWorld.copyPosition( camera.matrixWorld ); + + }; + + } + + const backgroundCacheKey = backgroundNode.getCacheKey(); + + if ( sceneData.backgroundCacheKey !== backgroundCacheKey ) { + + sceneData.backgroundMeshNode.node = vec4( backgroundNode ).mul( backgroundIntensity ); + sceneData.backgroundMeshNode.needsUpdate = true; + + backgroundMesh.material.needsUpdate = true; + + sceneData.backgroundCacheKey = backgroundCacheKey; + + } + + renderList.unshift( backgroundMesh, backgroundMesh.geometry, backgroundMesh.material, 0, 0, null ); + + } else { + + console.error( 'THREE.Renderer: Unsupported background configuration.', background ); + + } + + // + + if ( renderer.autoClear === true || forceClear === true ) { + + _clearColor.multiplyScalar( _clearColor.a ); + + const clearColorValue = renderContext.clearColorValue; + + clearColorValue.r = _clearColor.r; + clearColorValue.g = _clearColor.g; + clearColorValue.b = _clearColor.b; + clearColorValue.a = _clearColor.a; + + renderContext.depthClearValue = renderer._clearDepth; + renderContext.stencilClearValue = renderer._clearStencil; + + renderContext.clearColor = renderer.autoClearColor === true; + renderContext.clearDepth = renderer.autoClearDepth === true; + renderContext.clearStencil = renderer.autoClearStencil === true; + + } else { + + renderContext.clearColor = false; + renderContext.clearDepth = false; + renderContext.clearStencil = false; + + } + + } + +} + +class NodeBuilderState { + + constructor( vertexShader, fragmentShader, computeShader, nodeAttributes, bindings, updateNodes, updateBeforeNodes, updateAfterNodes, monitor, transforms = [] ) { + + this.vertexShader = vertexShader; + this.fragmentShader = fragmentShader; + this.computeShader = computeShader; + this.transforms = transforms; + + this.nodeAttributes = nodeAttributes; + this.bindings = bindings; + + this.updateNodes = updateNodes; + this.updateBeforeNodes = updateBeforeNodes; + this.updateAfterNodes = updateAfterNodes; + + this.monitor = monitor; + + this.usedTimes = 0; + + } + + createBindings() { + + const bindings = []; + + for ( const instanceGroup of this.bindings ) { + + const shared = instanceGroup.bindings[ 0 ].groupNode.shared; + + if ( shared !== true ) { + + const bindingsGroup = new BindGroup( instanceGroup.name, [], instanceGroup.index, instanceGroup ); + bindings.push( bindingsGroup ); + + for ( const instanceBinding of instanceGroup.bindings ) { + + bindingsGroup.bindings.push( instanceBinding.clone() ); + + } + + } else { + + bindings.push( instanceGroup ); + + } + + } + + return bindings; + + } + +} + +const outputNodeMap = new WeakMap(); + +class Nodes extends DataMap { + + constructor( renderer, backend ) { + + super(); + + this.renderer = renderer; + this.backend = backend; + this.nodeFrame = new NodeFrame(); + this.nodeBuilderCache = new Map(); + this.callHashCache = new ChainMap(); + this.groupsData = new ChainMap(); + + } + + updateGroup( nodeUniformsGroup ) { + + const groupNode = nodeUniformsGroup.groupNode; + const name = groupNode.name; + + // objectGroup is every updated + + if ( name === objectGroup.name ) return true; + + // renderGroup is updated once per render/compute call + + if ( name === renderGroup.name ) { + + const uniformsGroupData = this.get( nodeUniformsGroup ); + const renderId = this.nodeFrame.renderId; + + if ( uniformsGroupData.renderId !== renderId ) { + + uniformsGroupData.renderId = renderId; + + return true; + + } + + return false; + + } + + // frameGroup is updated once per frame + + if ( name === frameGroup.name ) { + + const uniformsGroupData = this.get( nodeUniformsGroup ); + const frameId = this.nodeFrame.frameId; + + if ( uniformsGroupData.frameId !== frameId ) { + + uniformsGroupData.frameId = frameId; + + return true; + + } + + return false; + + } + + // other groups are updated just when groupNode.needsUpdate is true + + const groupChain = [ groupNode, nodeUniformsGroup ]; + + let groupData = this.groupsData.get( groupChain ); + if ( groupData === undefined ) this.groupsData.set( groupChain, groupData = {} ); + + if ( groupData.version !== groupNode.version ) { + + groupData.version = groupNode.version; + + return true; + + } + + return false; + + } + + getForRenderCacheKey( renderObject ) { + + return renderObject.initialCacheKey; + + } + + getForRender( renderObject ) { + + const renderObjectData = this.get( renderObject ); + + let nodeBuilderState = renderObjectData.nodeBuilderState; + + if ( nodeBuilderState === undefined ) { + + const { nodeBuilderCache } = this; + + const cacheKey = this.getForRenderCacheKey( renderObject ); + + nodeBuilderState = nodeBuilderCache.get( cacheKey ); + + if ( nodeBuilderState === undefined ) { + + const nodeBuilder = this.backend.createNodeBuilder( renderObject.object, this.renderer ); + nodeBuilder.scene = renderObject.scene; + nodeBuilder.material = renderObject.material; + nodeBuilder.camera = renderObject.camera; + nodeBuilder.context.material = renderObject.material; + nodeBuilder.lightsNode = renderObject.lightsNode; + nodeBuilder.environmentNode = this.getEnvironmentNode( renderObject.scene ); + nodeBuilder.fogNode = this.getFogNode( renderObject.scene ); + nodeBuilder.clippingContext = renderObject.clippingContext; + nodeBuilder.build(); + + nodeBuilderState = this._createNodeBuilderState( nodeBuilder ); + + nodeBuilderCache.set( cacheKey, nodeBuilderState ); + + } + + nodeBuilderState.usedTimes ++; + + renderObjectData.nodeBuilderState = nodeBuilderState; + + } + + return nodeBuilderState; + + } + + delete( object ) { + + if ( object.isRenderObject ) { + + const nodeBuilderState = this.get( object ).nodeBuilderState; + nodeBuilderState.usedTimes --; + + if ( nodeBuilderState.usedTimes === 0 ) { + + this.nodeBuilderCache.delete( this.getForRenderCacheKey( object ) ); + + } + + } + + return super.delete( object ); + + } + + getForCompute( computeNode ) { + + const computeData = this.get( computeNode ); + + let nodeBuilderState = computeData.nodeBuilderState; + + if ( nodeBuilderState === undefined ) { + + const nodeBuilder = this.backend.createNodeBuilder( computeNode, this.renderer ); + nodeBuilder.build(); + + nodeBuilderState = this._createNodeBuilderState( nodeBuilder ); + + computeData.nodeBuilderState = nodeBuilderState; + + } + + return nodeBuilderState; + + } + + _createNodeBuilderState( nodeBuilder ) { + + return new NodeBuilderState( + nodeBuilder.vertexShader, + nodeBuilder.fragmentShader, + nodeBuilder.computeShader, + nodeBuilder.getAttributesArray(), + nodeBuilder.getBindings(), + nodeBuilder.updateNodes, + nodeBuilder.updateBeforeNodes, + nodeBuilder.updateAfterNodes, + nodeBuilder.monitor, + nodeBuilder.transforms + ); + + } + + getEnvironmentNode( scene ) { + + return scene.environmentNode || this.get( scene ).environmentNode || null; + + } + + getBackgroundNode( scene ) { + + return scene.backgroundNode || this.get( scene ).backgroundNode || null; + + } + + getFogNode( scene ) { + + return scene.fogNode || this.get( scene ).fogNode || null; + + } + + getCacheKey( scene, lightsNode ) { + + const chain = [ scene, lightsNode ]; + const callId = this.renderer.info.calls; + + let cacheKeyData = this.callHashCache.get( chain ); + + if ( cacheKeyData === undefined || cacheKeyData.callId !== callId ) { + + const environmentNode = this.getEnvironmentNode( scene ); + const fogNode = this.getFogNode( scene ); + + const values = []; + + if ( lightsNode ) values.push( lightsNode.getCacheKey( true ) ); + if ( environmentNode ) values.push( environmentNode.getCacheKey() ); + if ( fogNode ) values.push( fogNode.getCacheKey() ); + + values.push( this.renderer.shadowMap.enabled ? 1 : 0 ); + + cacheKeyData = { + callId, + cacheKey: hashArray( values ) + }; + + this.callHashCache.set( chain, cacheKeyData ); + + } + + return cacheKeyData.cacheKey; + + } + + updateScene( scene ) { + + this.updateEnvironment( scene ); + this.updateFog( scene ); + this.updateBackground( scene ); + + } + + get isToneMappingState() { + + return this.renderer.getRenderTarget() ? false : true; + + } + + updateBackground( scene ) { + + const sceneData = this.get( scene ); + const background = scene.background; + + if ( background ) { + + const forceUpdate = ( scene.backgroundBlurriness === 0 && sceneData.backgroundBlurriness > 0 ) || ( scene.backgroundBlurriness > 0 && sceneData.backgroundBlurriness === 0 ); + + if ( sceneData.background !== background || forceUpdate ) { + + let backgroundNode = null; + + if ( background.isCubeTexture === true || ( background.mapping === EquirectangularReflectionMapping || background.mapping === EquirectangularRefractionMapping || background.mapping === CubeUVReflectionMapping ) ) { + + if ( scene.backgroundBlurriness > 0 || background.mapping === CubeUVReflectionMapping ) { + + backgroundNode = pmremTexture( background, normalWorld ); + + } else { + + let envMap; + + if ( background.isCubeTexture === true ) { + + envMap = cubeTexture( background ); + + } else { + + envMap = texture( background ); + + } + + backgroundNode = cubeMapNode( envMap ); + + } + + } else if ( background.isTexture === true ) { + + backgroundNode = texture( background, screenUV.flipY() ).setUpdateMatrix( true ); + + } else if ( background.isColor !== true ) { + + console.error( 'WebGPUNodes: Unsupported background configuration.', background ); + + } + + sceneData.backgroundNode = backgroundNode; + sceneData.background = background; + sceneData.backgroundBlurriness = scene.backgroundBlurriness; + + } + + } else if ( sceneData.backgroundNode ) { + + delete sceneData.backgroundNode; + delete sceneData.background; + + } + + } + + updateFog( scene ) { + + const sceneData = this.get( scene ); + const fog = scene.fog; + + if ( fog ) { + + if ( sceneData.fog !== fog ) { + + let fogNode = null; + + if ( fog.isFogExp2 ) { + + const color = reference( 'color', 'color', fog ).setGroup( renderGroup ); + const density = reference( 'density', 'float', fog ).setGroup( renderGroup ); + + fogNode = densityFog( color, density ); + + } else if ( fog.isFog ) { + + const color = reference( 'color', 'color', fog ).setGroup( renderGroup ); + const near = reference( 'near', 'float', fog ).setGroup( renderGroup ); + const far = reference( 'far', 'float', fog ).setGroup( renderGroup ); + + fogNode = rangeFog( color, near, far ); + + } else { + + console.error( 'WebGPUNodes: Unsupported fog configuration.', fog ); + + } + + sceneData.fogNode = fogNode; + sceneData.fog = fog; + + } + + } else { + + delete sceneData.fogNode; + delete sceneData.fog; + + } + + } + + updateEnvironment( scene ) { + + const sceneData = this.get( scene ); + const environment = scene.environment; + + if ( environment ) { + + if ( sceneData.environment !== environment ) { + + let environmentNode = null; + + if ( environment.isCubeTexture === true ) { + + environmentNode = cubeTexture( environment ); + + } else if ( environment.isTexture === true ) { + + environmentNode = texture( environment ); + + } else { + + console.error( 'Nodes: Unsupported environment configuration.', environment ); + + } + + sceneData.environmentNode = environmentNode; + sceneData.environment = environment; + + } + + } else if ( sceneData.environmentNode ) { + + delete sceneData.environmentNode; + delete sceneData.environment; + + } + + } + + getNodeFrame( renderer = this.renderer, scene = null, object = null, camera = null, material = null ) { + + const nodeFrame = this.nodeFrame; + nodeFrame.renderer = renderer; + nodeFrame.scene = scene; + nodeFrame.object = object; + nodeFrame.camera = camera; + nodeFrame.material = material; + + return nodeFrame; + + } + + getNodeFrameForRender( renderObject ) { + + return this.getNodeFrame( renderObject.renderer, renderObject.scene, renderObject.object, renderObject.camera, renderObject.material ); + + } + + getOutputCacheKey() { + + const renderer = this.renderer; + + return renderer.toneMapping + ',' + renderer.currentColorSpace; + + } + + hasOutputChange( outputTarget ) { + + const cacheKey = outputNodeMap.get( outputTarget ); + + return cacheKey !== this.getOutputCacheKey(); + + } + + getOutputNode( outputTexture ) { + + const renderer = this.renderer; + const cacheKey = this.getOutputCacheKey(); + + const output = texture( outputTexture, screenUV ).renderOutput( renderer.toneMapping, renderer.currentColorSpace ); + + outputNodeMap.set( outputTexture, cacheKey ); + + return output; + + } + + updateBefore( renderObject ) { + + const nodeBuilder = renderObject.getNodeBuilderState(); + + for ( const node of nodeBuilder.updateBeforeNodes ) { + + // update frame state for each node + + this.getNodeFrameForRender( renderObject ).updateBeforeNode( node ); + + } + + } + + updateAfter( renderObject ) { + + const nodeBuilder = renderObject.getNodeBuilderState(); + + for ( const node of nodeBuilder.updateAfterNodes ) { + + // update frame state for each node + + this.getNodeFrameForRender( renderObject ).updateAfterNode( node ); + + } + + } + + updateForCompute( computeNode ) { + + const nodeFrame = this.getNodeFrame(); + const nodeBuilder = this.getForCompute( computeNode ); + + for ( const node of nodeBuilder.updateNodes ) { + + nodeFrame.updateNode( node ); + + } + + } + + updateForRender( renderObject ) { + + const nodeFrame = this.getNodeFrameForRender( renderObject ); + const nodeBuilder = renderObject.getNodeBuilderState(); + + for ( const node of nodeBuilder.updateNodes ) { + + nodeFrame.updateNode( node ); + + } + + } + + needsRefresh( renderObject ) { + + const nodeFrame = this.getNodeFrameForRender( renderObject ); + const monitor = renderObject.getMonitor(); + + return monitor.needsRefresh( renderObject, nodeFrame ); + + } + + dispose() { + + super.dispose(); + + this.nodeFrame = new NodeFrame(); + this.nodeBuilderCache = new Map(); + + } + +} + +class RenderBundle { + + constructor( scene, camera ) { + + this.scene = scene; + this.camera = camera; + + } + + clone() { + + return Object.assign( new this.constructor(), this ); + + } + +} + +class RenderBundles { + + constructor() { + + this.lists = new ChainMap(); + + } + + get( scene, camera ) { + + const lists = this.lists; + const keys = [ scene, camera ]; + + let list = lists.get( keys ); + + if ( list === undefined ) { + + list = new RenderBundle( scene, camera ); + lists.set( keys, list ); + + } + + return list; + + } + + dispose() { + + this.lists = new ChainMap(); + + } + +} + +class NodeLibrary { + + constructor() { + + this.lightNodes = new WeakMap(); + this.materialNodes = new Map(); + this.toneMappingNodes = new Map(); + this.colorSpaceNodes = new Map(); + + } + + fromMaterial( material ) { + + if ( material.isNodeMaterial ) return material; + + let nodeMaterial = null; + + const nodeMaterialClass = this.getMaterialNodeClass( material.type ); + + if ( nodeMaterialClass !== null ) { + + nodeMaterial = new nodeMaterialClass(); + + for ( const key in material ) { + + nodeMaterial[ key ] = material[ key ]; + + } + + } + + return nodeMaterial; + + } + + addColorSpace( colorSpaceNode, colorSpace ) { + + this.addType( colorSpaceNode, colorSpace, this.colorSpaceNodes ); + + } + + getColorSpaceFunction( colorSpace ) { + + return this.colorSpaceNodes.get( colorSpace ) || null; + + } + + addToneMapping( toneMappingNode, toneMapping ) { + + this.addType( toneMappingNode, toneMapping, this.toneMappingNodes ); + + } + + getToneMappingFunction( toneMapping ) { + + return this.toneMappingNodes.get( toneMapping ) || null; + + } + + getMaterialNodeClass( materialType ) { + + return this.materialNodes.get( materialType ) || null; + + } + + addMaterial( materialNodeClass, materialClass ) { + + this.addType( materialNodeClass, materialClass.name, this.materialNodes ); + + } + + getLightNodeClass( light ) { + + return this.lightNodes.get( light ) || null; + + } + + addLight( lightNodeClass, lightClass ) { + + this.addClass( lightNodeClass, lightClass, this.lightNodes ); + + } + + addType( nodeClass, type, library ) { + + if ( library.has( type ) ) { + + console.warn( `Redefinition of node ${ type }` ); + return; + + } + + if ( typeof nodeClass !== 'function' ) throw new Error( `Node class ${ nodeClass.name } is not a class.` ); + if ( typeof type === 'function' || typeof type === 'object' ) throw new Error( `Base class ${ type } is not a class.` ); + + library.set( type, nodeClass ); + + } + + addClass( nodeClass, baseClass, library ) { + + if ( library.has( baseClass ) ) { + + console.warn( `Redefinition of node ${ baseClass.name }` ); + return; + + } + + if ( typeof nodeClass !== 'function' ) throw new Error( `Node class ${ nodeClass.name } is not a class.` ); + if ( typeof baseClass !== 'function' ) throw new Error( `Base class ${ baseClass.name } is not a class.` ); + + library.set( baseClass, nodeClass ); + + } + +} + +const _scene = /*@__PURE__*/ new Scene(); +const _drawingBufferSize = /*@__PURE__*/ new Vector2(); +const _screen = /*@__PURE__*/ new Vector4(); +const _frustum = /*@__PURE__*/ new Frustum(); +const _projScreenMatrix = /*@__PURE__*/ new Matrix4(); +const _vector4 = /*@__PURE__*/ new Vector4(); + +class Renderer { + + constructor( backend, parameters = {} ) { + + this.isRenderer = true; + + // + + const { + logarithmicDepthBuffer = false, + alpha = true, + depth = true, + stencil = false, + antialias = false, + samples = 0, + getFallback = null + } = parameters; + + // public + this.domElement = backend.getDomElement(); + + this.backend = backend; + + this.samples = samples || ( antialias === true ) ? 4 : 0; + + this.autoClear = true; + this.autoClearColor = true; + this.autoClearDepth = true; + this.autoClearStencil = true; + + this.alpha = alpha; + + this.logarithmicDepthBuffer = logarithmicDepthBuffer; + + this.outputColorSpace = SRGBColorSpace; + + this.toneMapping = NoToneMapping; + this.toneMappingExposure = 1.0; + + this.sortObjects = true; + + this.depth = depth; + this.stencil = stencil; + + this.clippingPlanes = []; + + this.info = new Info(); + + this.nodes = { + library: new NodeLibrary(), + modelViewMatrix: null, + modelNormalViewMatrix: null + }; + + // internals + + this._getFallback = getFallback; + + this._pixelRatio = 1; + this._width = this.domElement.width; + this._height = this.domElement.height; + + this._viewport = new Vector4( 0, 0, this._width, this._height ); + this._scissor = new Vector4( 0, 0, this._width, this._height ); + this._scissorTest = false; + + this._attributes = null; + this._geometries = null; + this._nodes = null; + this._animation = null; + this._bindings = null; + this._objects = null; + this._pipelines = null; + this._bundles = null; + this._renderLists = null; + this._renderContexts = null; + this._textures = null; + this._background = null; + + this._quad = new QuadMesh( new NodeMaterial() ); + this._quad.material.type = 'Renderer_output'; + + this._currentRenderContext = null; + + this._opaqueSort = null; + this._transparentSort = null; + + this._frameBufferTarget = null; + + const alphaClear = this.alpha === true ? 0 : 1; + + this._clearColor = new Color4( 0, 0, 0, alphaClear ); + this._clearDepth = 1; + this._clearStencil = 0; + + this._renderTarget = null; + this._activeCubeFace = 0; + this._activeMipmapLevel = 0; + + this._mrt = null; + + this._renderObjectFunction = null; + this._currentRenderObjectFunction = null; + this._currentRenderBundle = null; + + this._handleObjectFunction = this._renderObjectDirect; + + this._initialized = false; + this._initPromise = null; + + this._compilationPromises = null; + + this.transparent = true; + this.opaque = true; + + this.shadowMap = { + enabled: false, + type: PCFShadowMap$1 + }; + + this.xr = { + enabled: false + }; + + this.debug = { + checkShaderErrors: true, + onShaderError: null, + getShaderAsync: async ( scene, camera, object ) => { + + await this.compileAsync( scene, camera ); + + const renderList = this._renderLists.get( scene, camera ); + const renderContext = this._renderContexts.get( scene, camera, this._renderTarget ); + + const material = scene.overrideMaterial || object.material; + + const renderObject = this._objects.get( object, material, scene, camera, renderList.lightsNode, renderContext ); + + const { fragmentShader, vertexShader } = renderObject.getNodeBuilderState(); + + return { fragmentShader, vertexShader }; + + } + }; + + } + + async init() { + + if ( this._initialized ) { + + throw new Error( 'Renderer: Backend has already been initialized.' ); + + } + + if ( this._initPromise !== null ) { + + return this._initPromise; + + } + + this._initPromise = new Promise( async ( resolve, reject ) => { + + let backend = this.backend; + + try { + + await backend.init( this ); + + } catch ( error ) { + + if ( this._getFallback !== null ) { + + // try the fallback + + try { + + this.backend = backend = this._getFallback( error ); + await backend.init( this ); + + } catch ( error ) { + + reject( error ); + return; + + } + + } else { + + reject( error ); + return; + + } + + } + + this._nodes = new Nodes( this, backend ); + this._animation = new Animation( this._nodes, this.info ); + this._attributes = new Attributes( backend ); + this._background = new Background( this, this._nodes ); + this._geometries = new Geometries( this._attributes, this.info ); + this._textures = new Textures( this, backend, this.info ); + this._pipelines = new Pipelines( backend, this._nodes ); + this._bindings = new Bindings( backend, this._nodes, this._textures, this._attributes, this._pipelines, this.info ); + this._objects = new RenderObjects( this, this._nodes, this._geometries, this._pipelines, this._bindings, this.info ); + this._renderLists = new RenderLists(); + this._bundles = new RenderBundles(); + this._renderContexts = new RenderContexts(); + + // + + this._initialized = true; + + resolve(); + + } ); + + return this._initPromise; + + } + + get coordinateSystem() { + + return this.backend.coordinateSystem; + + } + + async compileAsync( scene, camera, targetScene = null ) { + + if ( this._initialized === false ) await this.init(); + + // preserve render tree + + const nodeFrame = this._nodes.nodeFrame; + + const previousRenderId = nodeFrame.renderId; + const previousRenderContext = this._currentRenderContext; + const previousRenderObjectFunction = this._currentRenderObjectFunction; + const previousCompilationPromises = this._compilationPromises; + + // + + const sceneRef = ( scene.isScene === true ) ? scene : _scene; + + if ( targetScene === null ) targetScene = scene; + + const renderTarget = this._renderTarget; + const renderContext = this._renderContexts.get( targetScene, camera, renderTarget ); + const activeMipmapLevel = this._activeMipmapLevel; + + const compilationPromises = []; + + this._currentRenderContext = renderContext; + this._currentRenderObjectFunction = this.renderObject; + + this._handleObjectFunction = this._createObjectPipeline; + + this._compilationPromises = compilationPromises; + + nodeFrame.renderId ++; + + // + + nodeFrame.update(); + + // + + renderContext.depth = this.depth; + renderContext.stencil = this.stencil; + + if ( ! renderContext.clippingContext ) renderContext.clippingContext = new ClippingContext(); + renderContext.clippingContext.updateGlobal( this, camera ); + + // + + sceneRef.onBeforeRender( this, scene, camera, renderTarget ); + + // + + const renderList = this._renderLists.get( scene, camera ); + renderList.begin(); + + this._projectObject( scene, camera, 0, renderList ); + + // include lights from target scene + if ( targetScene !== scene ) { + + targetScene.traverseVisible( function ( object ) { + + if ( object.isLight && object.layers.test( camera.layers ) ) { + + renderList.pushLight( object ); + + } + + } ); + + } + + renderList.finish(); + + // + + if ( renderTarget !== null ) { + + this._textures.updateRenderTarget( renderTarget, activeMipmapLevel ); + + const renderTargetData = this._textures.get( renderTarget ); + + renderContext.textures = renderTargetData.textures; + renderContext.depthTexture = renderTargetData.depthTexture; + + } else { + + renderContext.textures = null; + renderContext.depthTexture = null; + + } + + // + + this._nodes.updateScene( sceneRef ); + + // + + this._background.update( sceneRef, renderList, renderContext ); + + // process render lists + + const opaqueObjects = renderList.opaque; + const transparentObjects = renderList.transparent; + const lightsNode = renderList.lightsNode; + + if ( this.opaque === true && opaqueObjects.length > 0 ) this._renderObjects( opaqueObjects, camera, sceneRef, lightsNode ); + if ( this.transparent === true && transparentObjects.length > 0 ) this._renderObjects( transparentObjects, camera, sceneRef, lightsNode ); + + // restore render tree + + nodeFrame.renderId = previousRenderId; + + this._currentRenderContext = previousRenderContext; + this._currentRenderObjectFunction = previousRenderObjectFunction; + this._compilationPromises = previousCompilationPromises; + + this._handleObjectFunction = this._renderObjectDirect; + + // wait for all promises setup by backends awaiting compilation/linking/pipeline creation to complete + + await Promise.all( compilationPromises ); + + } + + async renderAsync( scene, camera ) { + + if ( this._initialized === false ) await this.init(); + + const renderContext = this._renderScene( scene, camera ); + + await this.backend.resolveTimestampAsync( renderContext, 'render' ); + + } + + setMRT( mrt ) { + + this._mrt = mrt; + + return this; + + } + + getMRT() { + + return this._mrt; + + } + + _renderBundle( bundle, sceneRef, lightsNode ) { + + const { bundleGroup, camera, renderList } = bundle; + + const renderContext = this._currentRenderContext; + + // + + const renderBundle = this._bundles.get( bundleGroup, camera ); + const renderBundleData = this.backend.get( renderBundle ); + + if ( renderBundleData.renderContexts === undefined ) renderBundleData.renderContexts = new Set(); + + // + + const needsUpdate = bundleGroup.version !== renderBundleData.version; + const renderBundleNeedsUpdate = renderBundleData.renderContexts.has( renderContext ) === false || needsUpdate; + + renderBundleData.renderContexts.add( renderContext ); + + if ( renderBundleNeedsUpdate ) { + + this.backend.beginBundle( renderContext ); + + if ( renderBundleData.renderObjects === undefined || needsUpdate ) { + + renderBundleData.renderObjects = []; + + } + + this._currentRenderBundle = renderBundle; + + const opaqueObjects = renderList.opaque; + + if ( opaqueObjects.length > 0 ) this._renderObjects( opaqueObjects, camera, sceneRef, lightsNode ); + + this._currentRenderBundle = null; + + // + + this.backend.finishBundle( renderContext, renderBundle ); + + renderBundleData.version = bundleGroup.version; + + } else { + + const { renderObjects } = renderBundleData; + + for ( let i = 0, l = renderObjects.length; i < l; i ++ ) { + + const renderObject = renderObjects[ i ]; + + if ( this._nodes.needsRefresh( renderObject ) ) { + + this._nodes.updateBefore( renderObject ); + + this._nodes.updateForRender( renderObject ); + this._bindings.updateForRender( renderObject ); + + this._nodes.updateAfter( renderObject ); + + } + + } + + } + + this.backend.addBundle( renderContext, renderBundle ); + + } + + render( scene, camera ) { + + if ( this._initialized === false ) { + + console.warn( 'THREE.Renderer: .render() called before the backend is initialized. Try using .renderAsync() instead.' ); + + return this.renderAsync( scene, camera ); + + } + + this._renderScene( scene, camera ); + + } + + _getFrameBufferTarget() { + + const { currentToneMapping, currentColorSpace } = this; + + const useToneMapping = currentToneMapping !== NoToneMapping; + const useColorSpace = currentColorSpace !== LinearSRGBColorSpace; + + if ( useToneMapping === false && useColorSpace === false ) return null; + + const { width, height } = this.getDrawingBufferSize( _drawingBufferSize ); + const { depth, stencil } = this; + + let frameBufferTarget = this._frameBufferTarget; + + if ( frameBufferTarget === null ) { + + frameBufferTarget = new RenderTarget( width, height, { + depthBuffer: depth, + stencilBuffer: stencil, + type: HalfFloatType, // FloatType + format: RGBAFormat, + colorSpace: LinearSRGBColorSpace, + generateMipmaps: false, + minFilter: LinearFilter, + magFilter: LinearFilter, + samples: this.samples + } ); + + frameBufferTarget.isPostProcessingRenderTarget = true; + + this._frameBufferTarget = frameBufferTarget; + + } + + frameBufferTarget.depthBuffer = depth; + frameBufferTarget.stencilBuffer = stencil; + frameBufferTarget.setSize( width, height ); + frameBufferTarget.viewport.copy( this._viewport ); + frameBufferTarget.scissor.copy( this._scissor ); + frameBufferTarget.viewport.multiplyScalar( this._pixelRatio ); + frameBufferTarget.scissor.multiplyScalar( this._pixelRatio ); + frameBufferTarget.scissorTest = this._scissorTest; + + return frameBufferTarget; + + } + + _renderScene( scene, camera, useFrameBufferTarget = true ) { + + const frameBufferTarget = useFrameBufferTarget ? this._getFrameBufferTarget() : null; + + // preserve render tree + + const nodeFrame = this._nodes.nodeFrame; + + const previousRenderId = nodeFrame.renderId; + const previousRenderContext = this._currentRenderContext; + const previousRenderObjectFunction = this._currentRenderObjectFunction; + + // + + const sceneRef = ( scene.isScene === true ) ? scene : _scene; + + const outputRenderTarget = this._renderTarget; + + const activeCubeFace = this._activeCubeFace; + const activeMipmapLevel = this._activeMipmapLevel; + + // + + let renderTarget; + + if ( frameBufferTarget !== null ) { + + renderTarget = frameBufferTarget; + + this.setRenderTarget( renderTarget ); + + } else { + + renderTarget = outputRenderTarget; + + } + + // + + const renderContext = this._renderContexts.get( scene, camera, renderTarget ); + + this._currentRenderContext = renderContext; + this._currentRenderObjectFunction = this._renderObjectFunction || this.renderObject; + + // + + this.info.calls ++; + this.info.render.calls ++; + this.info.render.frameCalls ++; + + nodeFrame.renderId = this.info.calls; + + // + + const coordinateSystem = this.coordinateSystem; + + if ( camera.coordinateSystem !== coordinateSystem ) { + + camera.coordinateSystem = coordinateSystem; + + camera.updateProjectionMatrix(); + + } + + // + + if ( scene.matrixWorldAutoUpdate === true ) scene.updateMatrixWorld(); + + if ( camera.parent === null && camera.matrixWorldAutoUpdate === true ) camera.updateMatrixWorld(); + + // + + let viewport = this._viewport; + let scissor = this._scissor; + let pixelRatio = this._pixelRatio; + + if ( renderTarget !== null ) { + + viewport = renderTarget.viewport; + scissor = renderTarget.scissor; + pixelRatio = 1; + + } + + this.getDrawingBufferSize( _drawingBufferSize ); + + _screen.set( 0, 0, _drawingBufferSize.width, _drawingBufferSize.height ); + + const minDepth = ( viewport.minDepth === undefined ) ? 0 : viewport.minDepth; + const maxDepth = ( viewport.maxDepth === undefined ) ? 1 : viewport.maxDepth; + + renderContext.viewportValue.copy( viewport ).multiplyScalar( pixelRatio ).floor(); + renderContext.viewportValue.width >>= activeMipmapLevel; + renderContext.viewportValue.height >>= activeMipmapLevel; + renderContext.viewportValue.minDepth = minDepth; + renderContext.viewportValue.maxDepth = maxDepth; + renderContext.viewport = renderContext.viewportValue.equals( _screen ) === false; + + renderContext.scissorValue.copy( scissor ).multiplyScalar( pixelRatio ).floor(); + renderContext.scissor = this._scissorTest && renderContext.scissorValue.equals( _screen ) === false; + renderContext.scissorValue.width >>= activeMipmapLevel; + renderContext.scissorValue.height >>= activeMipmapLevel; + + if ( ! renderContext.clippingContext ) renderContext.clippingContext = new ClippingContext(); + renderContext.clippingContext.updateGlobal( this, camera ); + + // + + sceneRef.onBeforeRender( this, scene, camera, renderTarget ); + + // + + _projScreenMatrix.multiplyMatrices( camera.projectionMatrix, camera.matrixWorldInverse ); + _frustum.setFromProjectionMatrix( _projScreenMatrix, coordinateSystem ); + + const renderList = this._renderLists.get( scene, camera ); + renderList.begin(); + + this._projectObject( scene, camera, 0, renderList ); + + renderList.finish(); + + if ( this.sortObjects === true ) { + + renderList.sort( this._opaqueSort, this._transparentSort ); + + } + + // + + if ( renderTarget !== null ) { + + this._textures.updateRenderTarget( renderTarget, activeMipmapLevel ); + + const renderTargetData = this._textures.get( renderTarget ); + + renderContext.textures = renderTargetData.textures; + renderContext.depthTexture = renderTargetData.depthTexture; + renderContext.width = renderTargetData.width; + renderContext.height = renderTargetData.height; + renderContext.renderTarget = renderTarget; + renderContext.depth = renderTarget.depthBuffer; + renderContext.stencil = renderTarget.stencilBuffer; + + } else { + + renderContext.textures = null; + renderContext.depthTexture = null; + renderContext.width = this.domElement.width; + renderContext.height = this.domElement.height; + renderContext.depth = this.depth; + renderContext.stencil = this.stencil; + + } + + renderContext.width >>= activeMipmapLevel; + renderContext.height >>= activeMipmapLevel; + renderContext.activeCubeFace = activeCubeFace; + renderContext.activeMipmapLevel = activeMipmapLevel; + renderContext.occlusionQueryCount = renderList.occlusionQueryCount; + + // + + this._nodes.updateScene( sceneRef ); + + // + + this._background.update( sceneRef, renderList, renderContext ); + + // + + this.backend.beginRender( renderContext ); + + // process render lists + + const { + bundles, + lightsNode, + transparent: transparentObjects, + opaque: opaqueObjects + } = renderList; + + if ( bundles.length > 0 ) this._renderBundles( bundles, sceneRef, lightsNode ); + if ( this.opaque === true && opaqueObjects.length > 0 ) this._renderObjects( opaqueObjects, camera, sceneRef, lightsNode ); + if ( this.transparent === true && transparentObjects.length > 0 ) this._renderObjects( transparentObjects, camera, sceneRef, lightsNode ); + + // finish render pass + + this.backend.finishRender( renderContext ); + + // restore render tree + + nodeFrame.renderId = previousRenderId; + + this._currentRenderContext = previousRenderContext; + this._currentRenderObjectFunction = previousRenderObjectFunction; + + // + + if ( frameBufferTarget !== null ) { + + this.setRenderTarget( outputRenderTarget, activeCubeFace, activeMipmapLevel ); + + const quad = this._quad; + + if ( this._nodes.hasOutputChange( renderTarget.texture ) ) { + + quad.material.fragmentNode = this._nodes.getOutputNode( renderTarget.texture ); + quad.material.needsUpdate = true; + + } + + this._renderScene( quad, quad.camera, false ); + + } + + // + + sceneRef.onAfterRender( this, scene, camera, renderTarget ); + + // + + return renderContext; + + } + + getMaxAnisotropy() { + + return this.backend.getMaxAnisotropy(); + + } + + getActiveCubeFace() { + + return this._activeCubeFace; + + } + + getActiveMipmapLevel() { + + return this._activeMipmapLevel; + + } + + async setAnimationLoop( callback ) { + + if ( this._initialized === false ) await this.init(); + + this._animation.setAnimationLoop( callback ); + + } + + async getArrayBufferAsync( attribute ) { + + return await this.backend.getArrayBufferAsync( attribute ); + + } + + getContext() { + + return this.backend.getContext(); + + } + + getPixelRatio() { + + return this._pixelRatio; + + } + + getDrawingBufferSize( target ) { + + return target.set( this._width * this._pixelRatio, this._height * this._pixelRatio ).floor(); + + } + + getSize( target ) { + + return target.set( this._width, this._height ); + + } + + setPixelRatio( value = 1 ) { + + this._pixelRatio = value; + + this.setSize( this._width, this._height, false ); + + } + + setDrawingBufferSize( width, height, pixelRatio ) { + + this._width = width; + this._height = height; + + this._pixelRatio = pixelRatio; + + this.domElement.width = Math.floor( width * pixelRatio ); + this.domElement.height = Math.floor( height * pixelRatio ); + + this.setViewport( 0, 0, width, height ); + + if ( this._initialized ) this.backend.updateSize(); + + } + + setSize( width, height, updateStyle = true ) { + + this._width = width; + this._height = height; + + this.domElement.width = Math.floor( width * this._pixelRatio ); + this.domElement.height = Math.floor( height * this._pixelRatio ); + + if ( updateStyle === true ) { + + this.domElement.style.width = width + 'px'; + this.domElement.style.height = height + 'px'; + + } + + this.setViewport( 0, 0, width, height ); + + if ( this._initialized ) this.backend.updateSize(); + + } + + setOpaqueSort( method ) { + + this._opaqueSort = method; + + } + + setTransparentSort( method ) { + + this._transparentSort = method; + + } + + getScissor( target ) { + + const scissor = this._scissor; + + target.x = scissor.x; + target.y = scissor.y; + target.width = scissor.width; + target.height = scissor.height; + + return target; + + } + + setScissor( x, y, width, height ) { + + const scissor = this._scissor; + + if ( x.isVector4 ) { + + scissor.copy( x ); + + } else { + + scissor.set( x, y, width, height ); + + } + + } + + getScissorTest() { + + return this._scissorTest; + + } + + setScissorTest( boolean ) { + + this._scissorTest = boolean; + + this.backend.setScissorTest( boolean ); + + } + + getViewport( target ) { + + return target.copy( this._viewport ); + + } + + setViewport( x, y, width, height, minDepth = 0, maxDepth = 1 ) { + + const viewport = this._viewport; + + if ( x.isVector4 ) { + + viewport.copy( x ); + + } else { + + viewport.set( x, y, width, height ); + + } + + viewport.minDepth = minDepth; + viewport.maxDepth = maxDepth; + + } + + getClearColor( target ) { + + return target.copy( this._clearColor ); + + } + + setClearColor( color, alpha = 1 ) { + + this._clearColor.set( color ); + this._clearColor.a = alpha; + + } + + getClearAlpha() { + + return this._clearColor.a; + + } + + setClearAlpha( alpha ) { + + this._clearColor.a = alpha; + + } + + getClearDepth() { + + return this._clearDepth; + + } + + setClearDepth( depth ) { + + this._clearDepth = depth; + + } + + getClearStencil() { + + return this._clearStencil; + + } + + setClearStencil( stencil ) { + + this._clearStencil = stencil; + + } + + isOccluded( object ) { + + const renderContext = this._currentRenderContext; + + return renderContext && this.backend.isOccluded( renderContext, object ); + + } + + clear( color = true, depth = true, stencil = true ) { + + if ( this._initialized === false ) { + + console.warn( 'THREE.Renderer: .clear() called before the backend is initialized. Try using .clearAsync() instead.' ); + + return this.clearAsync( color, depth, stencil ); + + } + + const renderTarget = this._renderTarget || this._getFrameBufferTarget(); + + let renderTargetData = null; + + if ( renderTarget !== null ) { + + this._textures.updateRenderTarget( renderTarget ); + + renderTargetData = this._textures.get( renderTarget ); + + } + + this.backend.clear( color, depth, stencil, renderTargetData ); + + if ( renderTarget !== null && this._renderTarget === null ) { + + // If a color space transform or tone mapping is required, + // the clear operation clears the intermediate renderTarget texture, but does not update the screen canvas. + + const quad = this._quad; + + if ( this._nodes.hasOutputChange( renderTarget.texture ) ) { + + quad.material.fragmentNode = this._nodes.getOutputNode( renderTarget.texture ); + quad.material.needsUpdate = true; + + } + + this._renderScene( quad, quad.camera, false ); + + } + + } + + clearColor() { + + return this.clear( true, false, false ); + + } + + clearDepth() { + + return this.clear( false, true, false ); + + } + + clearStencil() { + + return this.clear( false, false, true ); + + } + + async clearAsync( color = true, depth = true, stencil = true ) { + + if ( this._initialized === false ) await this.init(); + + this.clear( color, depth, stencil ); + + } + + clearColorAsync() { + + return this.clearAsync( true, false, false ); + + } + + clearDepthAsync() { + + return this.clearAsync( false, true, false ); + + } + + clearStencilAsync() { + + return this.clearAsync( false, false, true ); + + } + + get currentToneMapping() { + + return this._renderTarget !== null ? NoToneMapping : this.toneMapping; + + } + + get currentColorSpace() { + + return this._renderTarget !== null ? LinearSRGBColorSpace : this.outputColorSpace; + + } + + dispose() { + + this.info.dispose(); + + this._animation.dispose(); + this._objects.dispose(); + this._pipelines.dispose(); + this._nodes.dispose(); + this._bindings.dispose(); + this._renderLists.dispose(); + this._renderContexts.dispose(); + this._textures.dispose(); + + this.setRenderTarget( null ); + this.setAnimationLoop( null ); + + } + + setRenderTarget( renderTarget, activeCubeFace = 0, activeMipmapLevel = 0 ) { + + this._renderTarget = renderTarget; + this._activeCubeFace = activeCubeFace; + this._activeMipmapLevel = activeMipmapLevel; + + } + + getRenderTarget() { + + return this._renderTarget; + + } + + setRenderObjectFunction( renderObjectFunction ) { + + this._renderObjectFunction = renderObjectFunction; + + } + + getRenderObjectFunction() { + + return this._renderObjectFunction; + + } + + async computeAsync( computeNodes ) { + + if ( this._initialized === false ) await this.init(); + + const nodeFrame = this._nodes.nodeFrame; + + const previousRenderId = nodeFrame.renderId; + + // + + this.info.calls ++; + this.info.compute.calls ++; + this.info.compute.frameCalls ++; + + nodeFrame.renderId = this.info.calls; + + // + + const backend = this.backend; + const pipelines = this._pipelines; + const bindings = this._bindings; + const nodes = this._nodes; + + const computeList = Array.isArray( computeNodes ) ? computeNodes : [ computeNodes ]; + + if ( computeList[ 0 ] === undefined || computeList[ 0 ].isComputeNode !== true ) { + + throw new Error( 'THREE.Renderer: .compute() expects a ComputeNode.' ); + + } + + backend.beginCompute( computeNodes ); + + for ( const computeNode of computeList ) { + + // onInit + + if ( pipelines.has( computeNode ) === false ) { + + const dispose = () => { + + computeNode.removeEventListener( 'dispose', dispose ); + + pipelines.delete( computeNode ); + bindings.delete( computeNode ); + nodes.delete( computeNode ); + + }; + + computeNode.addEventListener( 'dispose', dispose ); + + // + + computeNode.onInit( { renderer: this } ); + + } + + nodes.updateForCompute( computeNode ); + bindings.updateForCompute( computeNode ); + + const computeBindings = bindings.getForCompute( computeNode ); + const computePipeline = pipelines.getForCompute( computeNode, computeBindings ); + + backend.compute( computeNodes, computeNode, computeBindings, computePipeline ); + + } + + backend.finishCompute( computeNodes ); + + await this.backend.resolveTimestampAsync( computeNodes, 'compute' ); + + // + + nodeFrame.renderId = previousRenderId; + + } + + async hasFeatureAsync( name ) { + + if ( this._initialized === false ) await this.init(); + + return this.backend.hasFeature( name ); + + } + + hasFeature( name ) { + + if ( this._initialized === false ) { + + console.warn( 'THREE.Renderer: .hasFeature() called before the backend is initialized. Try using .hasFeatureAsync() instead.' ); + + return false; + + } + + return this.backend.hasFeature( name ); + + } + + copyFramebufferToTexture( framebufferTexture, rectangle = null ) { + + const renderContext = this._currentRenderContext; + + this._textures.updateTexture( framebufferTexture ); + + rectangle = rectangle === null ? _vector4.set( 0, 0, framebufferTexture.image.width, framebufferTexture.image.height ) : rectangle; + + this.backend.copyFramebufferToTexture( framebufferTexture, renderContext, rectangle ); + + } + + copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { + + this._textures.updateTexture( srcTexture ); + this._textures.updateTexture( dstTexture ); + + this.backend.copyTextureToTexture( srcTexture, dstTexture, srcRegion, dstPosition, level ); + + } + + + readRenderTargetPixelsAsync( renderTarget, x, y, width, height, index = 0, faceIndex = 0 ) { + + return this.backend.copyTextureToBuffer( renderTarget.textures[ index ], x, y, width, height, faceIndex ); + + } + + _projectObject( object, camera, groupOrder, renderList ) { + + if ( object.visible === false ) return; + + const visible = object.layers.test( camera.layers ); + + if ( visible ) { + + if ( object.isGroup ) { + + groupOrder = object.renderOrder; + + } else if ( object.isLOD ) { + + if ( object.autoUpdate === true ) object.update( camera ); + + } else if ( object.isLight ) { + + renderList.pushLight( object ); + + } else if ( object.isSprite ) { + + if ( ! object.frustumCulled || _frustum.intersectsSprite( object ) ) { + + if ( this.sortObjects === true ) { + + _vector4.setFromMatrixPosition( object.matrixWorld ).applyMatrix4( _projScreenMatrix ); + + } + + const { geometry, material } = object; + + if ( material.visible ) { + + renderList.push( object, geometry, material, groupOrder, _vector4.z, null ); + + } + + } + + } else if ( object.isLineLoop ) { + + console.error( 'THREE.Renderer: Objects of type THREE.LineLoop are not supported. Please use THREE.Line or THREE.LineSegments.' ); + + } else if ( object.isMesh || object.isLine || object.isPoints ) { + + if ( ! object.frustumCulled || _frustum.intersectsObject( object ) ) { + + const { geometry, material } = object; + + if ( this.sortObjects === true ) { + + if ( geometry.boundingSphere === null ) geometry.computeBoundingSphere(); + + _vector4 + .copy( geometry.boundingSphere.center ) + .applyMatrix4( object.matrixWorld ) + .applyMatrix4( _projScreenMatrix ); + + } + + if ( Array.isArray( material ) ) { + + const groups = geometry.groups; + + for ( let i = 0, l = groups.length; i < l; i ++ ) { + + const group = groups[ i ]; + const groupMaterial = material[ group.materialIndex ]; + + if ( groupMaterial && groupMaterial.visible ) { + + renderList.push( object, geometry, groupMaterial, groupOrder, _vector4.z, group ); + + } + + } + + } else if ( material.visible ) { + + renderList.push( object, geometry, material, groupOrder, _vector4.z, null ); + + } + + } + + } + + } + + if ( object.isBundleGroup === true && this.backend.beginBundle !== undefined ) { + + const baseRenderList = renderList; + + // replace render list + renderList = this._renderLists.get( object, camera ); + + renderList.begin(); + + baseRenderList.pushBundle( { + bundleGroup: object, + camera, + renderList, + } ); + + renderList.finish(); + + } + + const children = object.children; + + for ( let i = 0, l = children.length; i < l; i ++ ) { + + this._projectObject( children[ i ], camera, groupOrder, renderList ); + + } + + } + + _renderBundles( bundles, sceneRef, lightsNode ) { + + for ( const bundle of bundles ) { + + this._renderBundle( bundle, sceneRef, lightsNode ); + + } + + } + + _renderObjects( renderList, camera, scene, lightsNode ) { + + // process renderable objects + + for ( let i = 0, il = renderList.length; i < il; i ++ ) { + + const renderItem = renderList[ i ]; + + // @TODO: Add support for multiple materials per object. This will require to extract + // the material from the renderItem object and pass it with its group data to renderObject(). + + const { object, geometry, material, group } = renderItem; + + if ( camera.isArrayCamera ) { + + const cameras = camera.cameras; + + for ( let j = 0, jl = cameras.length; j < jl; j ++ ) { + + const camera2 = cameras[ j ]; + + if ( object.layers.test( camera2.layers ) ) { + + const vp = camera2.viewport; + const minDepth = ( vp.minDepth === undefined ) ? 0 : vp.minDepth; + const maxDepth = ( vp.maxDepth === undefined ) ? 1 : vp.maxDepth; + + const viewportValue = this._currentRenderContext.viewportValue; + viewportValue.copy( vp ).multiplyScalar( this._pixelRatio ).floor(); + viewportValue.minDepth = minDepth; + viewportValue.maxDepth = maxDepth; + + this.backend.updateViewport( this._currentRenderContext ); + + this._currentRenderObjectFunction( object, scene, camera2, geometry, material, group, lightsNode ); + + } + + } + + } else { + + this._currentRenderObjectFunction( object, scene, camera, geometry, material, group, lightsNode ); + + } + + } + + } + + renderObject( object, scene, camera, geometry, material, group, lightsNode ) { + + let overridePositionNode; + let overrideFragmentNode; + let overrideDepthNode; + + // + + object.onBeforeRender( this, scene, camera, geometry, material, group ); + + // + + if ( scene.overrideMaterial !== null ) { + + const overrideMaterial = scene.overrideMaterial; + + if ( material.positionNode && material.positionNode.isNode ) { + + overridePositionNode = overrideMaterial.positionNode; + overrideMaterial.positionNode = material.positionNode; + + } + + if ( overrideMaterial.isShadowNodeMaterial ) { + + overrideMaterial.side = material.shadowSide === null ? material.side : material.shadowSide; + + if ( material.depthNode && material.depthNode.isNode ) { + + overrideDepthNode = overrideMaterial.depthNode; + overrideMaterial.depthNode = material.depthNode; + + } + + + if ( material.shadowNode && material.shadowNode.isNode ) { + + overrideFragmentNode = overrideMaterial.fragmentNode; + overrideMaterial.fragmentNode = material.shadowNode; + + } + + if ( this.localClippingEnabled ) { + + if ( material.clipShadows ) { + + if ( overrideMaterial.clippingPlanes !== material.clippingPlanes ) { + + overrideMaterial.clippingPlanes = material.clippingPlanes; + overrideMaterial.needsUpdate = true; + + } + + if ( overrideMaterial.clipIntersection !== material.clipIntersection ) { + + overrideMaterial.clipIntersection = material.clipIntersection; + + } + + } else if ( Array.isArray( overrideMaterial.clippingPlanes ) ) { + + overrideMaterial.clippingPlanes = null; + overrideMaterial.needsUpdate = true; + + } + + } + + } + + material = overrideMaterial; + + } + + // + + if ( material.transparent === true && material.side === DoubleSide && material.forceSinglePass === false ) { + + material.side = BackSide; + this._handleObjectFunction( object, material, scene, camera, lightsNode, group, 'backSide' ); // create backSide pass id + + material.side = FrontSide; + this._handleObjectFunction( object, material, scene, camera, lightsNode, group ); // use default pass id + + material.side = DoubleSide; + + } else { + + this._handleObjectFunction( object, material, scene, camera, lightsNode, group ); + + } + + // + + if ( overridePositionNode !== undefined ) { + + scene.overrideMaterial.positionNode = overridePositionNode; + + } + + if ( overrideDepthNode !== undefined ) { + + scene.overrideMaterial.depthNode = overrideDepthNode; + + } + + if ( overrideFragmentNode !== undefined ) { + + scene.overrideMaterial.fragmentNode = overrideFragmentNode; + + } + + // + + object.onAfterRender( this, scene, camera, geometry, material, group ); + + } + + _renderObjectDirect( object, material, scene, camera, lightsNode, group, passId ) { + + const renderObject = this._objects.get( object, material, scene, camera, lightsNode, this._currentRenderContext, passId ); + renderObject.drawRange = object.geometry.drawRange; + renderObject.group = group; + + // + + const needsRefresh = this._nodes.needsRefresh( renderObject ); + + if ( needsRefresh ) { + + this._nodes.updateBefore( renderObject ); + + this._geometries.updateForRender( renderObject ); + + this._nodes.updateForRender( renderObject ); + this._bindings.updateForRender( renderObject ); + + } + + this._pipelines.updateForRender( renderObject ); + + // + + if ( this._currentRenderBundle !== null ) { + + const renderBundleData = this.backend.get( this._currentRenderBundle ); + + renderBundleData.renderObjects.push( renderObject ); + + renderObject.bundle = this._currentRenderBundle.scene; + + } + + this.backend.draw( renderObject, this.info ); + + if ( needsRefresh ) this._nodes.updateAfter( renderObject ); + + } + + _createObjectPipeline( object, material, scene, camera, lightsNode, passId ) { + + const renderObject = this._objects.get( object, material, scene, camera, lightsNode, this._currentRenderContext, passId ); + + // + + this._nodes.updateBefore( renderObject ); + + this._geometries.updateForRender( renderObject ); + + this._nodes.updateForRender( renderObject ); + this._bindings.updateForRender( renderObject ); + + this._pipelines.getForRender( renderObject, this._compilationPromises ); + + this._nodes.updateAfter( renderObject ); + + } + + get compute() { + + return this.computeAsync; + + } + + get compile() { + + return this.compileAsync; + + } + +} + +class Binding { + + constructor( name = '' ) { + + this.name = name; + + this.visibility = 0; + + } + + setVisibility( visibility ) { + + this.visibility |= visibility; + + } + + clone() { + + return Object.assign( new this.constructor(), this ); + + } + +} + +function getFloatLength( floatLength ) { + + // ensure chunk size alignment (STD140 layout) + + return floatLength + ( ( GPU_CHUNK_BYTES - ( floatLength % GPU_CHUNK_BYTES ) ) % GPU_CHUNK_BYTES ); + +} + +class Buffer extends Binding { + + constructor( name, buffer = null ) { + + super( name ); + + this.isBuffer = true; + + this.bytesPerElement = Float32Array.BYTES_PER_ELEMENT; + + this._buffer = buffer; + + } + + get byteLength() { + + return getFloatLength( this._buffer.byteLength ); + + } + + get buffer() { + + return this._buffer; + + } + + update() { + + return true; + + } + +} + +class UniformBuffer extends Buffer { + + constructor( name, buffer = null ) { + + super( name, buffer ); + + this.isUniformBuffer = true; + + } + +} + +let _id$4 = 0; + +class NodeUniformBuffer extends UniformBuffer { + + constructor( nodeUniform, groupNode ) { + + super( 'UniformBuffer_' + _id$4 ++, nodeUniform ? nodeUniform.value : null ); + + this.nodeUniform = nodeUniform; + this.groupNode = groupNode; + + } + + get buffer() { + + return this.nodeUniform.value; + + } + +} + +class UniformsGroup extends UniformBuffer { + + constructor( name ) { + + super( name ); + + this.isUniformsGroup = true; + + this._values = null; + + // the order of uniforms in this array must match the order of uniforms in the shader + + this.uniforms = []; + + } + + addUniform( uniform ) { + + this.uniforms.push( uniform ); + + return this; + + } + + removeUniform( uniform ) { + + const index = this.uniforms.indexOf( uniform ); + + if ( index !== - 1 ) { + + this.uniforms.splice( index, 1 ); + + } + + return this; + + } + + get values() { + + if ( this._values === null ) { + + this._values = Array.from( this.buffer ); + + } + + return this._values; + + } + + get buffer() { + + let buffer = this._buffer; + + if ( buffer === null ) { + + const byteLength = this.byteLength; + + buffer = new Float32Array( new ArrayBuffer( byteLength ) ); + + this._buffer = buffer; + + } + + return buffer; + + } + + get byteLength() { + + let offset = 0; // global buffer offset in bytes + + for ( let i = 0, l = this.uniforms.length; i < l; i ++ ) { + + const uniform = this.uniforms[ i ]; + + const { boundary, itemSize } = uniform; + + // offset within a single chunk in bytes + + const chunkOffset = offset % GPU_CHUNK_BYTES; + const remainingSizeInChunk = GPU_CHUNK_BYTES - chunkOffset; + + // conformance tests + + if ( chunkOffset !== 0 && ( remainingSizeInChunk - boundary ) < 0 ) { + + // check for chunk overflow + + offset += ( GPU_CHUNK_BYTES - chunkOffset ); + + } else if ( chunkOffset % boundary !== 0 ) { + + // check for correct alignment + + offset += ( chunkOffset % boundary ); + + } + + uniform.offset = ( offset / this.bytesPerElement ); + + offset += ( itemSize * this.bytesPerElement ); + + } + + return Math.ceil( offset / GPU_CHUNK_BYTES ) * GPU_CHUNK_BYTES; + + } + + update() { + + let updated = false; + + for ( const uniform of this.uniforms ) { + + if ( this.updateByType( uniform ) === true ) { + + updated = true; + + } + + } + + return updated; + + } + + updateByType( uniform ) { + + if ( uniform.isNumberUniform ) return this.updateNumber( uniform ); + if ( uniform.isVector2Uniform ) return this.updateVector2( uniform ); + if ( uniform.isVector3Uniform ) return this.updateVector3( uniform ); + if ( uniform.isVector4Uniform ) return this.updateVector4( uniform ); + if ( uniform.isColorUniform ) return this.updateColor( uniform ); + if ( uniform.isMatrix3Uniform ) return this.updateMatrix3( uniform ); + if ( uniform.isMatrix4Uniform ) return this.updateMatrix4( uniform ); + + console.error( 'THREE.WebGPUUniformsGroup: Unsupported uniform type.', uniform ); + + } + + updateNumber( uniform ) { + + let updated = false; + + const a = this.values; + const v = uniform.getValue(); + const offset = uniform.offset; + + if ( a[ offset ] !== v ) { + + const b = this.buffer; + + b[ offset ] = a[ offset ] = v; + updated = true; + + } + + return updated; + + } + + updateVector2( uniform ) { + + let updated = false; + + const a = this.values; + const v = uniform.getValue(); + const offset = uniform.offset; + + if ( a[ offset + 0 ] !== v.x || a[ offset + 1 ] !== v.y ) { + + const b = this.buffer; + + b[ offset + 0 ] = a[ offset + 0 ] = v.x; + b[ offset + 1 ] = a[ offset + 1 ] = v.y; + + updated = true; + + } + + return updated; + + } + + updateVector3( uniform ) { + + let updated = false; + + const a = this.values; + const v = uniform.getValue(); + const offset = uniform.offset; + + if ( a[ offset + 0 ] !== v.x || a[ offset + 1 ] !== v.y || a[ offset + 2 ] !== v.z ) { + + const b = this.buffer; + + b[ offset + 0 ] = a[ offset + 0 ] = v.x; + b[ offset + 1 ] = a[ offset + 1 ] = v.y; + b[ offset + 2 ] = a[ offset + 2 ] = v.z; + + updated = true; + + } + + return updated; + + } + + updateVector4( uniform ) { + + let updated = false; + + const a = this.values; + const v = uniform.getValue(); + const offset = uniform.offset; + + if ( a[ offset + 0 ] !== v.x || a[ offset + 1 ] !== v.y || a[ offset + 2 ] !== v.z || a[ offset + 4 ] !== v.w ) { + + const b = this.buffer; + + b[ offset + 0 ] = a[ offset + 0 ] = v.x; + b[ offset + 1 ] = a[ offset + 1 ] = v.y; + b[ offset + 2 ] = a[ offset + 2 ] = v.z; + b[ offset + 3 ] = a[ offset + 3 ] = v.w; + + updated = true; + + } + + return updated; + + } + + updateColor( uniform ) { + + let updated = false; + + const a = this.values; + const c = uniform.getValue(); + const offset = uniform.offset; + + if ( a[ offset + 0 ] !== c.r || a[ offset + 1 ] !== c.g || a[ offset + 2 ] !== c.b ) { + + const b = this.buffer; + + b[ offset + 0 ] = a[ offset + 0 ] = c.r; + b[ offset + 1 ] = a[ offset + 1 ] = c.g; + b[ offset + 2 ] = a[ offset + 2 ] = c.b; + + updated = true; + + } + + return updated; + + } + + updateMatrix3( uniform ) { + + let updated = false; + + const a = this.values; + const e = uniform.getValue().elements; + const offset = uniform.offset; + + if ( a[ offset + 0 ] !== e[ 0 ] || a[ offset + 1 ] !== e[ 1 ] || a[ offset + 2 ] !== e[ 2 ] || + a[ offset + 4 ] !== e[ 3 ] || a[ offset + 5 ] !== e[ 4 ] || a[ offset + 6 ] !== e[ 5 ] || + a[ offset + 8 ] !== e[ 6 ] || a[ offset + 9 ] !== e[ 7 ] || a[ offset + 10 ] !== e[ 8 ] ) { + + const b = this.buffer; + + b[ offset + 0 ] = a[ offset + 0 ] = e[ 0 ]; + b[ offset + 1 ] = a[ offset + 1 ] = e[ 1 ]; + b[ offset + 2 ] = a[ offset + 2 ] = e[ 2 ]; + b[ offset + 4 ] = a[ offset + 4 ] = e[ 3 ]; + b[ offset + 5 ] = a[ offset + 5 ] = e[ 4 ]; + b[ offset + 6 ] = a[ offset + 6 ] = e[ 5 ]; + b[ offset + 8 ] = a[ offset + 8 ] = e[ 6 ]; + b[ offset + 9 ] = a[ offset + 9 ] = e[ 7 ]; + b[ offset + 10 ] = a[ offset + 10 ] = e[ 8 ]; + + updated = true; + + } + + return updated; + + } + + updateMatrix4( uniform ) { + + let updated = false; + + const a = this.values; + const e = uniform.getValue().elements; + const offset = uniform.offset; + + if ( arraysEqual( a, e, offset ) === false ) { + + const b = this.buffer; + b.set( e, offset ); + setArray( a, e, offset ); + updated = true; + + } + + return updated; + + } + +} + +function setArray( a, b, offset ) { + + for ( let i = 0, l = b.length; i < l; i ++ ) { + + a[ offset + i ] = b[ i ]; + + } + +} + +function arraysEqual( a, b, offset ) { + + for ( let i = 0, l = b.length; i < l; i ++ ) { + + if ( a[ offset + i ] !== b[ i ] ) return false; + + } + + return true; + +} + +let _id$3 = 0; + +class NodeUniformsGroup extends UniformsGroup { + + constructor( name, groupNode ) { + + super( name ); + + this.id = _id$3 ++; + this.groupNode = groupNode; + + this.isNodeUniformsGroup = true; + + } + + getNodes() { + + const nodes = []; + + for ( const uniform of this.uniforms ) { + + const node = uniform.nodeUniform.node; + + if ( ! node ) throw new Error( 'NodeUniformsGroup: Uniform has no node.' ); + + nodes.push( node ); + + } + + return nodes; + + } + +} + +let _id$2 = 0; + +class SampledTexture extends Binding { + + constructor( name, texture ) { + + super( name ); + + this.id = _id$2 ++; + + this.texture = texture; + this.version = texture ? texture.version : 0; + this.store = false; + this.generation = null; + + this.isSampledTexture = true; + + } + + needsBindingsUpdate( generation ) { + + const { texture } = this; + + if ( generation !== this.generation ) { + + this.generation = generation; + + return true; + + } + + return texture.isVideoTexture; + + } + + update() { + + const { texture, version } = this; + + if ( version !== texture.version ) { + + this.version = texture.version; + + return true; + + } + + return false; + + } + +} + +class NodeSampledTexture extends SampledTexture { + + constructor( name, textureNode, groupNode, access = null ) { + + super( name, textureNode ? textureNode.value : null ); + + this.textureNode = textureNode; + this.groupNode = groupNode; + + this.access = access; + + } + + needsBindingsUpdate( generation ) { + + return this.textureNode.value !== this.texture || super.needsBindingsUpdate( generation ); + + } + + update() { + + const { textureNode } = this; + + if ( this.texture !== textureNode.value ) { + + this.texture = textureNode.value; + + return true; + + } + + return super.update(); + + } + +} + +class NodeSampledCubeTexture extends NodeSampledTexture { + + constructor( name, textureNode, groupNode, access ) { + + super( name, textureNode, groupNode, access ); + + this.isSampledCubeTexture = true; + + } + +} + +class NodeSampledTexture3D extends NodeSampledTexture { + + constructor( name, textureNode, groupNode, access ) { + + super( name, textureNode, groupNode, access ); + + this.isSampledTexture3D = true; + + } + +} + +const glslMethods = { + atan2: 'atan', + textureDimensions: 'textureSize', + equals: 'equal' +}; + +const precisionLib = { + low: 'lowp', + medium: 'mediump', + high: 'highp' +}; + +const supports$1 = { + swizzleAssign: true, + storageBuffer: false +}; + +const defaultPrecisions = ` +precision highp float; +precision highp int; +precision highp sampler2D; +precision highp sampler3D; +precision highp samplerCube; +precision highp sampler2DArray; + +precision highp usampler2D; +precision highp usampler3D; +precision highp usamplerCube; +precision highp usampler2DArray; + +precision highp isampler2D; +precision highp isampler3D; +precision highp isamplerCube; +precision highp isampler2DArray; + +precision lowp sampler2DShadow; +`; + +class GLSLNodeBuilder extends NodeBuilder { + + constructor( object, renderer ) { + + super( object, renderer, new GLSLNodeParser() ); + + this.uniformGroups = {}; + this.transforms = []; + this.extensions = {}; + + this.useComparisonMethod = true; + + } + + needsColorSpaceToLinearSRGB( texture ) { + + return texture.isVideoTexture === true && texture.colorSpace !== NoColorSpace; + + } + + getMethod( method ) { + + return glslMethods[ method ] || method; + + } + + getOutputStructName() { + + return ''; + + } + + buildFunctionCode( shaderNode ) { + + const layout = shaderNode.layout; + const flowData = this.flowShaderNode( shaderNode ); + + const parameters = []; + + for ( const input of layout.inputs ) { + + parameters.push( this.getType( input.type ) + ' ' + input.name ); + + } + + // + + const code = `${ this.getType( layout.type ) } ${ layout.name }( ${ parameters.join( ', ' ) } ) { + + ${ flowData.vars } + +${ flowData.code } + return ${ flowData.result }; + +}`; + + // + + return code; + + } + + setupPBO( storageBufferNode ) { + + const attribute = storageBufferNode.value; + + if ( attribute.pbo === undefined ) { + + const originalArray = attribute.array; + const numElements = attribute.count * attribute.itemSize; + + const { itemSize } = attribute; + + const isInteger = attribute.array.constructor.name.toLowerCase().includes( 'int' ); + + let format = isInteger ? RedIntegerFormat : RedFormat; + + + if ( itemSize === 2 ) { + + format = isInteger ? RGIntegerFormat : RGFormat; + + } else if ( itemSize === 3 ) { + + format = isInteger ? RGBIntegerFormat : RGBFormat; + + } else if ( itemSize === 4 ) { + + format = isInteger ? RGBAIntegerFormat : RGBAFormat; + + } + + const typeMap = { + Float32Array: FloatType, + Uint8Array: UnsignedByteType, + Uint16Array: UnsignedShortType, + Uint32Array: UnsignedIntType, + Int8Array: ByteType, + Int16Array: ShortType, + Int32Array: IntType, + Uint8ClampedArray: UnsignedByteType, + }; + + const width = Math.pow( 2, Math.ceil( Math.log2( Math.sqrt( numElements / itemSize ) ) ) ); + let height = Math.ceil( ( numElements / itemSize ) / width ); + if ( width * height * itemSize < numElements ) height ++; // Ensure enough space + + const newSize = width * height * itemSize; + + const newArray = new originalArray.constructor( newSize ); + + newArray.set( originalArray, 0 ); + + attribute.array = newArray; + + const pboTexture = new DataTexture( attribute.array, width, height, format, typeMap[ attribute.array.constructor.name ] || FloatType ); + pboTexture.needsUpdate = true; + pboTexture.isPBOTexture = true; + + const pbo = new TextureNode( pboTexture, null, null ); + pbo.setPrecision( 'high' ); + + attribute.pboNode = pbo; + attribute.pbo = pbo.value; + + this.getUniformFromNode( attribute.pboNode, 'texture', this.shaderStage, this.context.label ); + + } + + } + + getPropertyName( node, shaderStage = this.shaderStage ) { + + if ( node.isNodeUniform && node.node.isTextureNode !== true && node.node.isBufferNode !== true ) { + + return shaderStage.charAt( 0 ) + '_' + node.name; + + } + + return super.getPropertyName( node, shaderStage ); + + } + + generatePBO( storageArrayElementNode ) { + + const { node, indexNode } = storageArrayElementNode; + const attribute = node.value; + + if ( this.renderer.backend.has( attribute ) ) { + + const attributeData = this.renderer.backend.get( attribute ); + attributeData.pbo = attribute.pbo; + + } + + + const nodeUniform = this.getUniformFromNode( attribute.pboNode, 'texture', this.shaderStage, this.context.label ); + const textureName = this.getPropertyName( nodeUniform ); + + this.increaseUsage( indexNode ); // force cache generate to be used as index in x,y + const indexSnippet = indexNode.build( this, 'uint' ); + + const elementNodeData = this.getDataFromNode( storageArrayElementNode ); + + let propertyName = elementNodeData.propertyName; + + if ( propertyName === undefined ) { + + // property element + + const nodeVar = this.getVarFromNode( storageArrayElementNode ); + + propertyName = this.getPropertyName( nodeVar ); + + // property size + + const bufferNodeData = this.getDataFromNode( node ); + + let propertySizeName = bufferNodeData.propertySizeName; + + if ( propertySizeName === undefined ) { + + propertySizeName = propertyName + 'Size'; + + this.getVarFromNode( node, propertySizeName, 'uint' ); + + this.addLineFlowCode( `${ propertySizeName } = uint( textureSize( ${ textureName }, 0 ).x )`, storageArrayElementNode ); + + bufferNodeData.propertySizeName = propertySizeName; + + } + + // + + const { itemSize } = attribute; + + const channel = '.' + vectorComponents.join( '' ).slice( 0, itemSize ); + const uvSnippet = `ivec2(${indexSnippet} % ${ propertySizeName }, ${indexSnippet} / ${ propertySizeName })`; + + const snippet = this.generateTextureLoad( null, textureName, uvSnippet, null, '0' ); + + // + + + let prefix = 'vec4'; + + if ( attribute.pbo.type === UnsignedIntType ) { + + prefix = 'uvec4'; + + } else if ( attribute.pbo.type === IntType ) { + + prefix = 'ivec4'; + + } + + this.addLineFlowCode( `${ propertyName } = ${prefix}(${ snippet })${channel}`, storageArrayElementNode ); + + elementNodeData.propertyName = propertyName; + + } + + return propertyName; + + } + + generateTextureLoad( texture, textureProperty, uvIndexSnippet, depthSnippet, levelSnippet = '0' ) { + + if ( depthSnippet ) { + + return `texelFetch( ${ textureProperty }, ivec3( ${ uvIndexSnippet }, ${ depthSnippet } ), ${ levelSnippet } )`; + + } else { + + return `texelFetch( ${ textureProperty }, ${ uvIndexSnippet }, ${ levelSnippet } )`; + + } + + } + + generateTexture( texture, textureProperty, uvSnippet, depthSnippet ) { + + if ( texture.isDepthTexture ) { + + return `texture( ${ textureProperty }, ${ uvSnippet } ).x`; + + } else { + + if ( depthSnippet ) uvSnippet = `vec3( ${ uvSnippet }, ${ depthSnippet } )`; + + return `texture( ${ textureProperty }, ${ uvSnippet } )`; + + } + + } + + generateTextureLevel( texture, textureProperty, uvSnippet, levelSnippet ) { + + return `textureLod( ${ textureProperty }, ${ uvSnippet }, ${ levelSnippet } )`; + + } + + generateTextureBias( texture, textureProperty, uvSnippet, biasSnippet ) { + + return `texture( ${ textureProperty }, ${ uvSnippet }, ${ biasSnippet } )`; + + } + + generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet ) { + + return `textureGrad( ${ textureProperty }, ${ uvSnippet }, ${ gradSnippet[ 0 ] }, ${ gradSnippet[ 1 ] } )`; + + } + + generateTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, depthSnippet, shaderStage = this.shaderStage ) { + + if ( shaderStage === 'fragment' ) { + + return `texture( ${ textureProperty }, vec3( ${ uvSnippet }, ${ compareSnippet } ) )`; + + } else { + + console.error( `WebGPURenderer: THREE.DepthTexture.compareFunction() does not support ${ shaderStage } shader.` ); + + } + + } + + getVars( shaderStage ) { + + const snippets = []; + + const vars = this.vars[ shaderStage ]; + + if ( vars !== undefined ) { + + for ( const variable of vars ) { + + snippets.push( `${ this.getVar( variable.type, variable.name ) };` ); + + } + + } + + return snippets.join( '\n\t' ); + + } + + getUniforms( shaderStage ) { + + const uniforms = this.uniforms[ shaderStage ]; + + const bindingSnippets = []; + const uniformGroups = {}; + + for ( const uniform of uniforms ) { + + let snippet = null; + let group = false; + + if ( uniform.type === 'texture' ) { + + const texture = uniform.node.value; + + let typePrefix = ''; + + if ( texture.isDataTexture === true ) { + + + if ( texture.type === UnsignedIntType ) { + + typePrefix = 'u'; + + } else if ( texture.type === IntType ) { + + typePrefix = 'i'; + + } + + } + + if ( texture.compareFunction ) { + + snippet = `sampler2DShadow ${ uniform.name };`; + + } else if ( texture.isDataArrayTexture === true || texture.isCompressedArrayTexture === true ) { + + snippet = `${typePrefix}sampler2DArray ${ uniform.name };`; + + } else { + + snippet = `${typePrefix}sampler2D ${ uniform.name };`; + + } + + } else if ( uniform.type === 'cubeTexture' ) { + + snippet = `samplerCube ${ uniform.name };`; + + } else if ( uniform.type === 'texture3D' ) { + + snippet = `sampler3D ${ uniform.name };`; + + } else if ( uniform.type === 'buffer' ) { + + const bufferNode = uniform.node; + const bufferType = this.getType( bufferNode.bufferType ); + const bufferCount = bufferNode.bufferCount; + + const bufferCountSnippet = bufferCount > 0 ? bufferCount : ''; + snippet = `${bufferNode.name} {\n\t${ bufferType } ${ uniform.name }[${ bufferCountSnippet }];\n};\n`; + + } else { + + const vectorType = this.getVectorType( uniform.type ); + + snippet = `${ vectorType } ${ this.getPropertyName( uniform, shaderStage ) };`; + + group = true; + + } + + const precision = uniform.node.precision; + + if ( precision !== null ) { + + snippet = precisionLib[ precision ] + ' ' + snippet; + + } + + if ( group ) { + + snippet = '\t' + snippet; + + const groupName = uniform.groupNode.name; + const groupSnippets = uniformGroups[ groupName ] || ( uniformGroups[ groupName ] = [] ); + + groupSnippets.push( snippet ); + + } else { + + snippet = 'uniform ' + snippet; + + bindingSnippets.push( snippet ); + + } + + } + + let output = ''; + + for ( const name in uniformGroups ) { + + const groupSnippets = uniformGroups[ name ]; + + output += this._getGLSLUniformStruct( shaderStage + '_' + name, groupSnippets.join( '\n' ) ) + '\n'; + + } + + output += bindingSnippets.join( '\n' ); + + return output; + + } + + getTypeFromAttribute( attribute ) { + + let nodeType = super.getTypeFromAttribute( attribute ); + + if ( /^[iu]/.test( nodeType ) && attribute.gpuType !== IntType ) { + + let dataAttribute = attribute; + + if ( attribute.isInterleavedBufferAttribute ) dataAttribute = attribute.data; + + const array = dataAttribute.array; + + if ( ( array instanceof Uint32Array || array instanceof Int32Array ) === false ) { + + nodeType = nodeType.slice( 1 ); + + } + + } + + return nodeType; + + } + + getAttributes( shaderStage ) { + + let snippet = ''; + + if ( shaderStage === 'vertex' || shaderStage === 'compute' ) { + + const attributes = this.getAttributesArray(); + + let location = 0; + + for ( const attribute of attributes ) { + + snippet += `layout( location = ${ location ++ } ) in ${ attribute.type } ${ attribute.name };\n`; + + } + + } + + return snippet; + + } + + getStructMembers( struct ) { + + const snippets = []; + const members = struct.getMemberTypes(); + + for ( let i = 0; i < members.length; i ++ ) { + + const member = members[ i ]; + snippets.push( `layout( location = ${i} ) out ${ member} m${i};` ); + + } + + return snippets.join( '\n' ); + + } + + getStructs( shaderStage ) { + + const snippets = []; + const structs = this.structs[ shaderStage ]; + + if ( structs.length === 0 ) { + + return 'layout( location = 0 ) out vec4 fragColor;\n'; + + } + + for ( let index = 0, length = structs.length; index < length; index ++ ) { + + const struct = structs[ index ]; + + let snippet = '\n'; + snippet += this.getStructMembers( struct ); + snippet += '\n'; + + snippets.push( snippet ); + + } + + return snippets.join( '\n\n' ); + + } + + getVaryings( shaderStage ) { + + let snippet = ''; + + const varyings = this.varyings; + + if ( shaderStage === 'vertex' || shaderStage === 'compute' ) { + + for ( const varying of varyings ) { + + if ( shaderStage === 'compute' ) varying.needsInterpolation = true; + const type = varying.type; + const flat = type.includes( 'int' ) || type.includes( 'uv' ) || type.includes( 'iv' ) ? 'flat ' : ''; + + snippet += `${flat}${varying.needsInterpolation ? 'out' : '/*out*/'} ${type} ${varying.name};\n`; + + } + + } else if ( shaderStage === 'fragment' ) { + + for ( const varying of varyings ) { + + if ( varying.needsInterpolation ) { + + const type = varying.type; + const flat = type.includes( 'int' ) || type.includes( 'uv' ) || type.includes( 'iv' ) ? 'flat ' : ''; + + snippet += `${flat}in ${type} ${varying.name};\n`; + + } + + } + + } + + return snippet; + + } + + getVertexIndex() { + + return 'uint( gl_VertexID )'; + + } + + getInstanceIndex() { + + return 'uint( gl_InstanceID )'; + + } + + getInvocationLocalIndex() { + + const workgroupSize = this.object.workgroupSize; + + const size = workgroupSize.reduce( ( acc, curr ) => acc * curr, 1 ); + + return `uint( gl_InstanceID ) % ${size}u`; + + } + + getDrawIndex() { + + const extensions = this.renderer.backend.extensions; + + if ( extensions.has( 'WEBGL_multi_draw' ) ) { + + return 'uint( gl_DrawID )'; + + } + + return null; + + } + + getFrontFacing() { + + return 'gl_FrontFacing'; + + } + + getFragCoord() { + + return 'gl_FragCoord.xy'; + + } + + getFragDepth() { + + return 'gl_FragDepth'; + + } + + enableExtension( name, behavior, shaderStage = this.shaderStage ) { + + const map = this.extensions[ shaderStage ] || ( this.extensions[ shaderStage ] = new Map() ); + + if ( map.has( name ) === false ) { + + map.set( name, { + name, + behavior + } ); + + } + + } + + getExtensions( shaderStage ) { + + const snippets = []; + + if ( shaderStage === 'vertex' ) { + + const ext = this.renderer.backend.extensions; + const isBatchedMesh = this.object.isBatchedMesh; + + if ( isBatchedMesh && ext.has( 'WEBGL_multi_draw' ) ) { + + this.enableExtension( 'GL_ANGLE_multi_draw', 'require', shaderStage ); + + } + + } + + const extensions = this.extensions[ shaderStage ]; + + if ( extensions !== undefined ) { + + for ( const { name, behavior } of extensions.values() ) { + + snippets.push( `#extension ${name} : ${behavior}` ); + + } + + } + + return snippets.join( '\n' ); + + } + + isAvailable( name ) { + + let result = supports$1[ name ]; + + if ( result === undefined ) { + + if ( name === 'float32Filterable' ) { + + const extensions = this.renderer.backend.extensions; + + if ( extensions.has( 'OES_texture_float_linear' ) ) { + + extensions.get( 'OES_texture_float_linear' ); + result = true; + + } else { + + result = false; + + } + + } + + supports$1[ name ] = result; + + } + + return result; + + } + + isFlipY() { + + return true; + + } + + registerTransform( varyingName, attributeNode ) { + + this.transforms.push( { varyingName, attributeNode } ); + + } + + getTransforms( /* shaderStage */ ) { + + const transforms = this.transforms; + + let snippet = ''; + + for ( let i = 0; i < transforms.length; i ++ ) { + + const transform = transforms[ i ]; + + const attributeName = this.getPropertyName( transform.attributeNode ); + + snippet += `${ transform.varyingName } = ${ attributeName };\n\t`; + + } + + return snippet; + + } + + _getGLSLUniformStruct( name, vars ) { + + return ` +layout( std140 ) uniform ${name} { +${vars} +};`; + + } + + _getGLSLVertexCode( shaderData ) { + + return `#version 300 es + +${ this.getSignature() } + +// extensions +${shaderData.extensions} + +// precision +${ defaultPrecisions } + +// uniforms +${shaderData.uniforms} + +// varyings +${shaderData.varyings} + +// attributes +${shaderData.attributes} + +// codes +${shaderData.codes} + +void main() { + + // vars + ${shaderData.vars} + + // transforms + ${shaderData.transforms} + + // flow + ${shaderData.flow} + + gl_PointSize = 1.0; + +} +`; + + } + + _getGLSLFragmentCode( shaderData ) { + + return `#version 300 es + +${ this.getSignature() } + +// precision +${ defaultPrecisions } + +// uniforms +${shaderData.uniforms} + +// varyings +${shaderData.varyings} + +// codes +${shaderData.codes} + +${shaderData.structs} + +void main() { + + // vars + ${shaderData.vars} + + // flow + ${shaderData.flow} + +} +`; + + } + + buildCode() { + + const shadersData = this.material !== null ? { fragment: {}, vertex: {} } : { compute: {} }; + + this.sortBindingGroups(); + + for ( const shaderStage in shadersData ) { + + let flow = '// code\n\n'; + flow += this.flowCode[ shaderStage ]; + + const flowNodes = this.flowNodes[ shaderStage ]; + const mainNode = flowNodes[ flowNodes.length - 1 ]; + + for ( const node of flowNodes ) { + + const flowSlotData = this.getFlowData( node/*, shaderStage*/ ); + const slotName = node.name; + + if ( slotName ) { + + if ( flow.length > 0 ) flow += '\n'; + + flow += `\t// flow -> ${ slotName }\n\t`; + + } + + flow += `${ flowSlotData.code }\n\t`; + + if ( node === mainNode && shaderStage !== 'compute' ) { + + flow += '// result\n\t'; + + if ( shaderStage === 'vertex' ) { + + flow += 'gl_Position = '; + flow += `${ flowSlotData.result };`; + + } else if ( shaderStage === 'fragment' ) { + + if ( ! node.outputNode.isOutputStructNode ) { + + flow += 'fragColor = '; + flow += `${ flowSlotData.result };`; + + } + + } + + } + + } + + const stageData = shadersData[ shaderStage ]; + + stageData.extensions = this.getExtensions( shaderStage ); + stageData.uniforms = this.getUniforms( shaderStage ); + stageData.attributes = this.getAttributes( shaderStage ); + stageData.varyings = this.getVaryings( shaderStage ); + stageData.vars = this.getVars( shaderStage ); + stageData.structs = this.getStructs( shaderStage ); + stageData.codes = this.getCodes( shaderStage ); + stageData.transforms = this.getTransforms( shaderStage ); + stageData.flow = flow; + + } + + if ( this.material !== null ) { + + this.vertexShader = this._getGLSLVertexCode( shadersData.vertex ); + this.fragmentShader = this._getGLSLFragmentCode( shadersData.fragment ); + + } else { + + this.computeShader = this._getGLSLVertexCode( shadersData.compute ); + + } + + } + + getUniformFromNode( node, type, shaderStage, name = null ) { + + const uniformNode = super.getUniformFromNode( node, type, shaderStage, name ); + const nodeData = this.getDataFromNode( node, shaderStage, this.globalCache ); + + let uniformGPU = nodeData.uniformGPU; + + if ( uniformGPU === undefined ) { + + const group = node.groupNode; + const groupName = group.name; + + const bindings = this.getBindGroupArray( groupName, shaderStage ); + + if ( type === 'texture' ) { + + uniformGPU = new NodeSampledTexture( uniformNode.name, uniformNode.node, group ); + bindings.push( uniformGPU ); + + } else if ( type === 'cubeTexture' ) { + + uniformGPU = new NodeSampledCubeTexture( uniformNode.name, uniformNode.node, group ); + bindings.push( uniformGPU ); + + } else if ( type === 'texture3D' ) { + + uniformGPU = new NodeSampledTexture3D( uniformNode.name, uniformNode.node, group ); + bindings.push( uniformGPU ); + + } else if ( type === 'buffer' ) { + + node.name = `NodeBuffer_${ node.id }`; + uniformNode.name = `buffer${ node.id }`; + + const buffer = new NodeUniformBuffer( node, group ); + buffer.name = node.name; + + bindings.push( buffer ); + + uniformGPU = buffer; + + } else { + + const uniformsStage = this.uniformGroups[ shaderStage ] || ( this.uniformGroups[ shaderStage ] = {} ); + + let uniformsGroup = uniformsStage[ groupName ]; + + if ( uniformsGroup === undefined ) { + + uniformsGroup = new NodeUniformsGroup( shaderStage + '_' + groupName, group ); + //uniformsGroup.setVisibility( gpuShaderStageLib[ shaderStage ] ); + + uniformsStage[ groupName ] = uniformsGroup; + + bindings.push( uniformsGroup ); + + } + + uniformGPU = this.getNodeUniform( uniformNode, type ); + + uniformsGroup.addUniform( uniformGPU ); + + } + + nodeData.uniformGPU = uniformGPU; + + } + + return uniformNode; + + } + +} + +let vector2 = null; +let vector4 = null; +let color4 = null; + +class Backend { + + constructor( parameters = {} ) { + + this.parameters = Object.assign( {}, parameters ); + this.data = new WeakMap(); + this.renderer = null; + this.domElement = null; + + } + + async init( renderer ) { + + this.renderer = renderer; + + } + + // render context + + begin( /*renderContext*/ ) { } + + finish( /*renderContext*/ ) { } + + // render object + + draw( /*renderObject, info*/ ) { } + + // program + + createProgram( /*program*/ ) { } + + destroyProgram( /*program*/ ) { } + + // bindings + + createBindings( /*bingGroup, bindings*/ ) { } + + updateBindings( /*bingGroup, bindings*/ ) { } + + // pipeline + + createRenderPipeline( /*renderObject*/ ) { } + + createComputePipeline( /*computeNode, pipeline*/ ) { } + + destroyPipeline( /*pipeline*/ ) { } + + // cache key + + needsRenderUpdate( /*renderObject*/ ) { } // return Boolean ( fast test ) + + getRenderCacheKey( /*renderObject*/ ) { } // return String + + // node builder + + createNodeBuilder( /*renderObject*/ ) { } // return NodeBuilder (ADD IT) + + // textures + + createSampler( /*texture*/ ) { } + + createDefaultTexture( /*texture*/ ) { } + + createTexture( /*texture*/ ) { } + + copyTextureToBuffer( /*texture, x, y, width, height*/ ) {} + + // attributes + + createAttribute( /*attribute*/ ) { } + + createIndexAttribute( /*attribute*/ ) { } + + updateAttribute( /*attribute*/ ) { } + + destroyAttribute( /*attribute*/ ) { } + + // canvas + + getContext() { } + + updateSize() { } + + // utils + + resolveTimestampAsync( /*renderContext, type*/ ) { } + + hasFeatureAsync( /*name*/ ) { } // return Boolean + + hasFeature( /*name*/ ) { } // return Boolean + + getInstanceCount( renderObject ) { + + const { object, geometry } = renderObject; + + return geometry.isInstancedBufferGeometry ? geometry.instanceCount : ( object.count > 1 ? object.count : 1 ); + + } + + getDrawingBufferSize() { + + vector2 = vector2 || new Vector2(); + + return this.renderer.getDrawingBufferSize( vector2 ); + + } + + getScissor() { + + vector4 = vector4 || new Vector4(); + + return this.renderer.getScissor( vector4 ); + + } + + setScissorTest( /*boolean*/ ) { } + + getClearColor() { + + const renderer = this.renderer; + + color4 = color4 || new Color4(); + + renderer.getClearColor( color4 ); + + color4.getRGB( color4, this.renderer.currentColorSpace ); + + return color4; + + } + + getDomElement() { + + let domElement = this.domElement; + + if ( domElement === null ) { + + domElement = ( this.parameters.canvas !== undefined ) ? this.parameters.canvas : createCanvasElement(); + + // OffscreenCanvas does not have setAttribute, see #22811 + if ( 'setAttribute' in domElement ) domElement.setAttribute( 'data-engine', `three.js r${REVISION} webgpu` ); + + this.domElement = domElement; + + } + + return domElement; + + } + + // resource properties + + set( object, value ) { + + this.data.set( object, value ); + + } + + get( object ) { + + let map = this.data.get( object ); + + if ( map === undefined ) { + + map = {}; + this.data.set( object, map ); + + } + + return map; + + } + + has( object ) { + + return this.data.has( object ); + + } + + delete( object ) { + + this.data.delete( object ); + + } + +} + +let _id$1 = 0; + +class DualAttributeData { + + constructor( attributeData, dualBuffer ) { + + this.buffers = [ attributeData.bufferGPU, dualBuffer ]; + this.type = attributeData.type; + this.bufferType = attributeData.bufferType; + this.pbo = attributeData.pbo; + this.byteLength = attributeData.byteLength; + this.bytesPerElement = attributeData.BYTES_PER_ELEMENT; + this.version = attributeData.version; + this.isInteger = attributeData.isInteger; + this.activeBufferIndex = 0; + this.baseId = attributeData.id; + + } + + + get id() { + + return `${ this.baseId }|${ this.activeBufferIndex }`; + + } + + get bufferGPU() { + + return this.buffers[ this.activeBufferIndex ]; + + } + + get transformBuffer() { + + return this.buffers[ this.activeBufferIndex ^ 1 ]; + + } + + switchBuffers() { + + this.activeBufferIndex ^= 1; + + } + +} + +class WebGLAttributeUtils { + + constructor( backend ) { + + this.backend = backend; + + } + + createAttribute( attribute, bufferType ) { + + const backend = this.backend; + const { gl } = backend; + + const array = attribute.array; + const usage = attribute.usage || gl.STATIC_DRAW; + + const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute; + const bufferData = backend.get( bufferAttribute ); + + let bufferGPU = bufferData.bufferGPU; + + if ( bufferGPU === undefined ) { + + bufferGPU = this._createBuffer( gl, bufferType, array, usage ); + + bufferData.bufferGPU = bufferGPU; + bufferData.bufferType = bufferType; + bufferData.version = bufferAttribute.version; + + } + + //attribute.onUploadCallback(); + + let type; + + if ( array instanceof Float32Array ) { + + type = gl.FLOAT; + + } else if ( array instanceof Uint16Array ) { + + if ( attribute.isFloat16BufferAttribute ) { + + type = gl.HALF_FLOAT; + + } else { + + type = gl.UNSIGNED_SHORT; + + } + + } else if ( array instanceof Int16Array ) { + + type = gl.SHORT; + + } else if ( array instanceof Uint32Array ) { + + type = gl.UNSIGNED_INT; + + } else if ( array instanceof Int32Array ) { + + type = gl.INT; + + } else if ( array instanceof Int8Array ) { + + type = gl.BYTE; + + } else if ( array instanceof Uint8Array ) { + + type = gl.UNSIGNED_BYTE; + + } else if ( array instanceof Uint8ClampedArray ) { + + type = gl.UNSIGNED_BYTE; + + } else { + + throw new Error( 'THREE.WebGLBackend: Unsupported buffer data format: ' + array ); + + } + + let attributeData = { + bufferGPU, + bufferType, + type, + byteLength: array.byteLength, + bytesPerElement: array.BYTES_PER_ELEMENT, + version: attribute.version, + pbo: attribute.pbo, + isInteger: type === gl.INT || type === gl.UNSIGNED_INT || attribute.gpuType === IntType, + id: _id$1 ++ + }; + + if ( attribute.isStorageBufferAttribute || attribute.isStorageInstancedBufferAttribute ) { + + // create buffer for tranform feedback use + const bufferGPUDual = this._createBuffer( gl, bufferType, array, usage ); + attributeData = new DualAttributeData( attributeData, bufferGPUDual ); + + } + + backend.set( attribute, attributeData ); + + } + + updateAttribute( attribute ) { + + const backend = this.backend; + const { gl } = backend; + + const array = attribute.array; + const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute; + const bufferData = backend.get( bufferAttribute ); + const bufferType = bufferData.bufferType; + const updateRanges = attribute.isInterleavedBufferAttribute ? attribute.data.updateRanges : attribute.updateRanges; + + gl.bindBuffer( bufferType, bufferData.bufferGPU ); + + if ( updateRanges.length === 0 ) { + + // Not using update ranges + + gl.bufferSubData( bufferType, 0, array ); + + } else { + + for ( let i = 0, l = updateRanges.length; i < l; i ++ ) { + + const range = updateRanges[ i ]; + gl.bufferSubData( bufferType, range.start * array.BYTES_PER_ELEMENT, + array, range.start, range.count ); + + } + + bufferAttribute.clearUpdateRanges(); + + } + + gl.bindBuffer( bufferType, null ); + + bufferData.version = bufferAttribute.version; + + } + + destroyAttribute( attribute ) { + + const backend = this.backend; + const { gl } = backend; + + if ( attribute.isInterleavedBufferAttribute ) { + + backend.delete( attribute.data ); + + } + + const attributeData = backend.get( attribute ); + + gl.deleteBuffer( attributeData.bufferGPU ); + + backend.delete( attribute ); + + } + + async getArrayBufferAsync( attribute ) { + + const backend = this.backend; + const { gl } = backend; + + const bufferAttribute = attribute.isInterleavedBufferAttribute ? attribute.data : attribute; + const { bufferGPU } = backend.get( bufferAttribute ); + + const array = attribute.array; + const byteLength = array.byteLength; + + gl.bindBuffer( gl.COPY_READ_BUFFER, bufferGPU ); + + const writeBuffer = gl.createBuffer(); + + gl.bindBuffer( gl.COPY_WRITE_BUFFER, writeBuffer ); + gl.bufferData( gl.COPY_WRITE_BUFFER, byteLength, gl.STREAM_READ ); + + gl.copyBufferSubData( gl.COPY_READ_BUFFER, gl.COPY_WRITE_BUFFER, 0, 0, byteLength ); + + await backend.utils._clientWaitAsync(); + + const dstBuffer = new attribute.array.constructor( array.length ); + + // Ensure the buffer is bound before reading + gl.bindBuffer( gl.COPY_WRITE_BUFFER, writeBuffer ); + + gl.getBufferSubData( gl.COPY_WRITE_BUFFER, 0, dstBuffer ); + + gl.deleteBuffer( writeBuffer ); + + gl.bindBuffer( gl.COPY_READ_BUFFER, null ); + gl.bindBuffer( gl.COPY_WRITE_BUFFER, null ); + + return dstBuffer.buffer; + + } + + _createBuffer( gl, bufferType, array, usage ) { + + const bufferGPU = gl.createBuffer(); + + gl.bindBuffer( bufferType, bufferGPU ); + gl.bufferData( bufferType, array, usage ); + gl.bindBuffer( bufferType, null ); + + return bufferGPU; + + } + +} + +let initialized$1 = false, equationToGL, factorToGL; + +class WebGLState { + + constructor( backend ) { + + this.backend = backend; + + this.gl = this.backend.gl; + + this.enabled = {}; + this.currentFlipSided = null; + this.currentCullFace = null; + this.currentProgram = null; + this.currentBlendingEnabled = false; + this.currentBlending = null; + this.currentBlendSrc = null; + this.currentBlendDst = null; + this.currentBlendSrcAlpha = null; + this.currentBlendDstAlpha = null; + this.currentPremultipledAlpha = null; + this.currentPolygonOffsetFactor = null; + this.currentPolygonOffsetUnits = null; + this.currentColorMask = null; + this.currentDepthFunc = null; + this.currentDepthMask = null; + this.currentStencilFunc = null; + this.currentStencilRef = null; + this.currentStencilFuncMask = null; + this.currentStencilFail = null; + this.currentStencilZFail = null; + this.currentStencilZPass = null; + this.currentStencilMask = null; + this.currentLineWidth = null; + + this.currentBoundFramebuffers = {}; + this.currentDrawbuffers = new WeakMap(); + + this.maxTextures = this.gl.getParameter( this.gl.MAX_TEXTURE_IMAGE_UNITS ); + this.currentTextureSlot = null; + this.currentBoundTextures = {}; + this.currentBoundBufferBases = {}; + + if ( initialized$1 === false ) { + + this._init( this.gl ); + + initialized$1 = true; + + } + + } + + _init( gl ) { + + // Store only WebGL constants here. + + equationToGL = { + [ AddEquation ]: gl.FUNC_ADD, + [ SubtractEquation ]: gl.FUNC_SUBTRACT, + [ ReverseSubtractEquation ]: gl.FUNC_REVERSE_SUBTRACT + }; + + factorToGL = { + [ ZeroFactor ]: gl.ZERO, + [ OneFactor ]: gl.ONE, + [ SrcColorFactor ]: gl.SRC_COLOR, + [ SrcAlphaFactor ]: gl.SRC_ALPHA, + [ SrcAlphaSaturateFactor ]: gl.SRC_ALPHA_SATURATE, + [ DstColorFactor ]: gl.DST_COLOR, + [ DstAlphaFactor ]: gl.DST_ALPHA, + [ OneMinusSrcColorFactor ]: gl.ONE_MINUS_SRC_COLOR, + [ OneMinusSrcAlphaFactor ]: gl.ONE_MINUS_SRC_ALPHA, + [ OneMinusDstColorFactor ]: gl.ONE_MINUS_DST_COLOR, + [ OneMinusDstAlphaFactor ]: gl.ONE_MINUS_DST_ALPHA + }; + + } + + enable( id ) { + + const { enabled } = this; + + if ( enabled[ id ] !== true ) { + + this.gl.enable( id ); + enabled[ id ] = true; + + } + + } + + disable( id ) { + + const { enabled } = this; + + if ( enabled[ id ] !== false ) { + + this.gl.disable( id ); + enabled[ id ] = false; + + } + + } + + setFlipSided( flipSided ) { + + if ( this.currentFlipSided !== flipSided ) { + + const { gl } = this; + + if ( flipSided ) { + + gl.frontFace( gl.CW ); + + } else { + + gl.frontFace( gl.CCW ); + + } + + this.currentFlipSided = flipSided; + + } + + } + + setCullFace( cullFace ) { + + const { gl } = this; + + if ( cullFace !== CullFaceNone ) { + + this.enable( gl.CULL_FACE ); + + if ( cullFace !== this.currentCullFace ) { + + if ( cullFace === CullFaceBack ) { + + gl.cullFace( gl.BACK ); + + } else if ( cullFace === CullFaceFront ) { + + gl.cullFace( gl.FRONT ); + + } else { + + gl.cullFace( gl.FRONT_AND_BACK ); + + } + + } + + } else { + + this.disable( gl.CULL_FACE ); + + } + + this.currentCullFace = cullFace; + + } + + setLineWidth( width ) { + + const { currentLineWidth, gl } = this; + + if ( width !== currentLineWidth ) { + + gl.lineWidth( width ); + + this.currentLineWidth = width; + + } + + } + + + setBlending( blending, blendEquation, blendSrc, blendDst, blendEquationAlpha, blendSrcAlpha, blendDstAlpha, premultipliedAlpha ) { + + const { gl } = this; + + if ( blending === NoBlending ) { + + if ( this.currentBlendingEnabled === true ) { + + this.disable( gl.BLEND ); + this.currentBlendingEnabled = false; + + } + + return; + + } + + if ( this.currentBlendingEnabled === false ) { + + this.enable( gl.BLEND ); + this.currentBlendingEnabled = true; + + } + + if ( blending !== CustomBlending ) { + + if ( blending !== this.currentBlending || premultipliedAlpha !== this.currentPremultipledAlpha ) { + + if ( this.currentBlendEquation !== AddEquation || this.currentBlendEquationAlpha !== AddEquation ) { + + gl.blendEquation( gl.FUNC_ADD ); + + this.currentBlendEquation = AddEquation; + this.currentBlendEquationAlpha = AddEquation; + + } + + if ( premultipliedAlpha ) { + + switch ( blending ) { + + case NormalBlending: + gl.blendFuncSeparate( gl.ONE, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + break; + + case AdditiveBlending: + gl.blendFunc( gl.ONE, gl.ONE ); + break; + + case SubtractiveBlending: + gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE ); + break; + + case MultiplyBlending: + gl.blendFuncSeparate( gl.ZERO, gl.SRC_COLOR, gl.ZERO, gl.SRC_ALPHA ); + break; + + default: + console.error( 'THREE.WebGLState: Invalid blending: ', blending ); + break; + + } + + } else { + + switch ( blending ) { + + case NormalBlending: + gl.blendFuncSeparate( gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA ); + break; + + case AdditiveBlending: + gl.blendFunc( gl.SRC_ALPHA, gl.ONE ); + break; + + case SubtractiveBlending: + gl.blendFuncSeparate( gl.ZERO, gl.ONE_MINUS_SRC_COLOR, gl.ZERO, gl.ONE ); + break; + + case MultiplyBlending: + gl.blendFunc( gl.ZERO, gl.SRC_COLOR ); + break; + + default: + console.error( 'THREE.WebGLState: Invalid blending: ', blending ); + break; + + } + + } + + this.currentBlendSrc = null; + this.currentBlendDst = null; + this.currentBlendSrcAlpha = null; + this.currentBlendDstAlpha = null; + + this.currentBlending = blending; + this.currentPremultipledAlpha = premultipliedAlpha; + + } + + return; + + } + + // custom blending + + blendEquationAlpha = blendEquationAlpha || blendEquation; + blendSrcAlpha = blendSrcAlpha || blendSrc; + blendDstAlpha = blendDstAlpha || blendDst; + + if ( blendEquation !== this.currentBlendEquation || blendEquationAlpha !== this.currentBlendEquationAlpha ) { + + gl.blendEquationSeparate( equationToGL[ blendEquation ], equationToGL[ blendEquationAlpha ] ); + + this.currentBlendEquation = blendEquation; + this.currentBlendEquationAlpha = blendEquationAlpha; + + } + + if ( blendSrc !== this.currentBlendSrc || blendDst !== this.currentBlendDst || blendSrcAlpha !== this.currentBlendSrcAlpha || blendDstAlpha !== this.currentBlendDstAlpha ) { + + gl.blendFuncSeparate( factorToGL[ blendSrc ], factorToGL[ blendDst ], factorToGL[ blendSrcAlpha ], factorToGL[ blendDstAlpha ] ); + + this.currentBlendSrc = blendSrc; + this.currentBlendDst = blendDst; + this.currentBlendSrcAlpha = blendSrcAlpha; + this.currentBlendDstAlpha = blendDstAlpha; + + } + + this.currentBlending = blending; + this.currentPremultipledAlpha = false; + + } + + setColorMask( colorMask ) { + + if ( this.currentColorMask !== colorMask ) { + + this.gl.colorMask( colorMask, colorMask, colorMask, colorMask ); + this.currentColorMask = colorMask; + + } + + } + + setDepthTest( depthTest ) { + + const { gl } = this; + + if ( depthTest ) { + + this.enable( gl.DEPTH_TEST ); + + } else { + + this.disable( gl.DEPTH_TEST ); + + } + + } + + setDepthMask( depthMask ) { + + if ( this.currentDepthMask !== depthMask ) { + + this.gl.depthMask( depthMask ); + this.currentDepthMask = depthMask; + + } + + } + + setDepthFunc( depthFunc ) { + + if ( this.currentDepthFunc !== depthFunc ) { + + const { gl } = this; + + switch ( depthFunc ) { + + case NeverDepth: + + gl.depthFunc( gl.NEVER ); + break; + + case AlwaysDepth: + + gl.depthFunc( gl.ALWAYS ); + break; + + case LessDepth: + + gl.depthFunc( gl.LESS ); + break; + + case LessEqualDepth: + + gl.depthFunc( gl.LEQUAL ); + break; + + case EqualDepth: + + gl.depthFunc( gl.EQUAL ); + break; + + case GreaterEqualDepth: + + gl.depthFunc( gl.GEQUAL ); + break; + + case GreaterDepth: + + gl.depthFunc( gl.GREATER ); + break; + + case NotEqualDepth: + + gl.depthFunc( gl.NOTEQUAL ); + break; + + default: + + gl.depthFunc( gl.LEQUAL ); + + } + + this.currentDepthFunc = depthFunc; + + } + + } + + setStencilTest( stencilTest ) { + + const { gl } = this; + + if ( stencilTest ) { + + this.enable( gl.STENCIL_TEST ); + + } else { + + this.disable( gl.STENCIL_TEST ); + + } + + } + + setStencilMask( stencilMask ) { + + if ( this.currentStencilMask !== stencilMask ) { + + this.gl.stencilMask( stencilMask ); + this.currentStencilMask = stencilMask; + + } + + } + + setStencilFunc( stencilFunc, stencilRef, stencilMask ) { + + if ( this.currentStencilFunc !== stencilFunc || + this.currentStencilRef !== stencilRef || + this.currentStencilFuncMask !== stencilMask ) { + + this.gl.stencilFunc( stencilFunc, stencilRef, stencilMask ); + + this.currentStencilFunc = stencilFunc; + this.currentStencilRef = stencilRef; + this.currentStencilFuncMask = stencilMask; + + } + + } + + setStencilOp( stencilFail, stencilZFail, stencilZPass ) { + + if ( this.currentStencilFail !== stencilFail || + this.currentStencilZFail !== stencilZFail || + this.currentStencilZPass !== stencilZPass ) { + + this.gl.stencilOp( stencilFail, stencilZFail, stencilZPass ); + + this.currentStencilFail = stencilFail; + this.currentStencilZFail = stencilZFail; + this.currentStencilZPass = stencilZPass; + + } + + } + + setMaterial( material, frontFaceCW ) { + + const { gl } = this; + + material.side === DoubleSide + ? this.disable( gl.CULL_FACE ) + : this.enable( gl.CULL_FACE ); + + let flipSided = ( material.side === BackSide ); + if ( frontFaceCW ) flipSided = ! flipSided; + + this.setFlipSided( flipSided ); + + ( material.blending === NormalBlending && material.transparent === false ) + ? this.setBlending( NoBlending ) + : this.setBlending( material.blending, material.blendEquation, material.blendSrc, material.blendDst, material.blendEquationAlpha, material.blendSrcAlpha, material.blendDstAlpha, material.premultipliedAlpha ); + + this.setDepthFunc( material.depthFunc ); + this.setDepthTest( material.depthTest ); + this.setDepthMask( material.depthWrite ); + this.setColorMask( material.colorWrite ); + + const stencilWrite = material.stencilWrite; + this.setStencilTest( stencilWrite ); + if ( stencilWrite ) { + + this.setStencilMask( material.stencilWriteMask ); + this.setStencilFunc( material.stencilFunc, material.stencilRef, material.stencilFuncMask ); + this.setStencilOp( material.stencilFail, material.stencilZFail, material.stencilZPass ); + + } + + this.setPolygonOffset( material.polygonOffset, material.polygonOffsetFactor, material.polygonOffsetUnits ); + + material.alphaToCoverage === true && this.backend.renderer.samples > 1 + ? this.enable( gl.SAMPLE_ALPHA_TO_COVERAGE ) + : this.disable( gl.SAMPLE_ALPHA_TO_COVERAGE ); + + } + + setPolygonOffset( polygonOffset, factor, units ) { + + const { gl } = this; + + if ( polygonOffset ) { + + this.enable( gl.POLYGON_OFFSET_FILL ); + + if ( this.currentPolygonOffsetFactor !== factor || this.currentPolygonOffsetUnits !== units ) { + + gl.polygonOffset( factor, units ); + + this.currentPolygonOffsetFactor = factor; + this.currentPolygonOffsetUnits = units; + + } + + } else { + + this.disable( gl.POLYGON_OFFSET_FILL ); + + } + + } + + useProgram( program ) { + + if ( this.currentProgram !== program ) { + + this.gl.useProgram( program ); + + this.currentProgram = program; + + return true; + + } + + return false; + + } + + // framebuffer + + + bindFramebuffer( target, framebuffer ) { + + const { gl, currentBoundFramebuffers } = this; + + if ( currentBoundFramebuffers[ target ] !== framebuffer ) { + + gl.bindFramebuffer( target, framebuffer ); + + currentBoundFramebuffers[ target ] = framebuffer; + + // gl.DRAW_FRAMEBUFFER is equivalent to gl.FRAMEBUFFER + + if ( target === gl.DRAW_FRAMEBUFFER ) { + + currentBoundFramebuffers[ gl.FRAMEBUFFER ] = framebuffer; + + } + + if ( target === gl.FRAMEBUFFER ) { + + currentBoundFramebuffers[ gl.DRAW_FRAMEBUFFER ] = framebuffer; + + } + + return true; + + } + + return false; + + } + + drawBuffers( renderContext, framebuffer ) { + + const { gl } = this; + + let drawBuffers = []; + + let needsUpdate = false; + + if ( renderContext.textures !== null ) { + + drawBuffers = this.currentDrawbuffers.get( framebuffer ); + + if ( drawBuffers === undefined ) { + + drawBuffers = []; + this.currentDrawbuffers.set( framebuffer, drawBuffers ); + + } + + + const textures = renderContext.textures; + + if ( drawBuffers.length !== textures.length || drawBuffers[ 0 ] !== gl.COLOR_ATTACHMENT0 ) { + + for ( let i = 0, il = textures.length; i < il; i ++ ) { + + drawBuffers[ i ] = gl.COLOR_ATTACHMENT0 + i; + + } + + drawBuffers.length = textures.length; + + needsUpdate = true; + + } + + + } else { + + if ( drawBuffers[ 0 ] !== gl.BACK ) { + + drawBuffers[ 0 ] = gl.BACK; + + needsUpdate = true; + + } + + } + + if ( needsUpdate ) { + + gl.drawBuffers( drawBuffers ); + + } + + } + + + // texture + + activeTexture( webglSlot ) { + + const { gl, currentTextureSlot, maxTextures } = this; + + if ( webglSlot === undefined ) webglSlot = gl.TEXTURE0 + maxTextures - 1; + + if ( currentTextureSlot !== webglSlot ) { + + gl.activeTexture( webglSlot ); + this.currentTextureSlot = webglSlot; + + } + + } + + bindTexture( webglType, webglTexture, webglSlot ) { + + const { gl, currentTextureSlot, currentBoundTextures, maxTextures } = this; + + if ( webglSlot === undefined ) { + + if ( currentTextureSlot === null ) { + + webglSlot = gl.TEXTURE0 + maxTextures - 1; + + } else { + + webglSlot = currentTextureSlot; + + } + + } + + let boundTexture = currentBoundTextures[ webglSlot ]; + + if ( boundTexture === undefined ) { + + boundTexture = { type: undefined, texture: undefined }; + currentBoundTextures[ webglSlot ] = boundTexture; + + } + + if ( boundTexture.type !== webglType || boundTexture.texture !== webglTexture ) { + + if ( currentTextureSlot !== webglSlot ) { + + gl.activeTexture( webglSlot ); + this.currentTextureSlot = webglSlot; + + } + + gl.bindTexture( webglType, webglTexture ); + + boundTexture.type = webglType; + boundTexture.texture = webglTexture; + + } + + } + + bindBufferBase( target, index, buffer ) { + + const { gl } = this; + + const key = `${target}-${index}`; + + if ( this.currentBoundBufferBases[ key ] !== buffer ) { + + gl.bindBufferBase( target, index, buffer ); + this.currentBoundBufferBases[ key ] = buffer; + + return true; + + } + + return false; + + } + + + unbindTexture() { + + const { gl, currentTextureSlot, currentBoundTextures } = this; + + const boundTexture = currentBoundTextures[ currentTextureSlot ]; + + if ( boundTexture !== undefined && boundTexture.type !== undefined ) { + + gl.bindTexture( boundTexture.type, null ); + + boundTexture.type = undefined; + boundTexture.texture = undefined; + + } + + } + +} + +class WebGLUtils { + + constructor( backend ) { + + this.backend = backend; + + this.gl = this.backend.gl; + this.extensions = backend.extensions; + + } + + convert( p, colorSpace = NoColorSpace ) { + + const { gl, extensions } = this; + + let extension; + + if ( p === UnsignedByteType ) return gl.UNSIGNED_BYTE; + if ( p === UnsignedShort4444Type ) return gl.UNSIGNED_SHORT_4_4_4_4; + if ( p === UnsignedShort5551Type ) return gl.UNSIGNED_SHORT_5_5_5_1; + if ( p === UnsignedInt5999Type ) return gl.UNSIGNED_INT_5_9_9_9_REV; + + if ( p === ByteType ) return gl.BYTE; + if ( p === ShortType ) return gl.SHORT; + if ( p === UnsignedShortType ) return gl.UNSIGNED_SHORT; + if ( p === IntType ) return gl.INT; + if ( p === UnsignedIntType ) return gl.UNSIGNED_INT; + if ( p === FloatType ) return gl.FLOAT; + + if ( p === HalfFloatType ) { + + return gl.HALF_FLOAT; + + } + + if ( p === AlphaFormat ) return gl.ALPHA; + if ( p === RGBFormat ) return gl.RGB; + if ( p === RGBAFormat ) return gl.RGBA; + if ( p === LuminanceFormat ) return gl.LUMINANCE; + if ( p === LuminanceAlphaFormat ) return gl.LUMINANCE_ALPHA; + if ( p === DepthFormat ) return gl.DEPTH_COMPONENT; + if ( p === DepthStencilFormat ) return gl.DEPTH_STENCIL; + + // WebGL2 formats. + + if ( p === RedFormat ) return gl.RED; + if ( p === RedIntegerFormat ) return gl.RED_INTEGER; + if ( p === RGFormat ) return gl.RG; + if ( p === RGIntegerFormat ) return gl.RG_INTEGER; + if ( p === RGBAIntegerFormat ) return gl.RGBA_INTEGER; + + // S3TC + + if ( p === RGB_S3TC_DXT1_Format || p === RGBA_S3TC_DXT1_Format || p === RGBA_S3TC_DXT3_Format || p === RGBA_S3TC_DXT5_Format ) { + + if ( colorSpace === SRGBColorSpace ) { + + extension = extensions.get( 'WEBGL_compressed_texture_s3tc_srgb' ); + + if ( extension !== null ) { + + if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_S3TC_DXT1_EXT; + if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT; + if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT; + if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT; + + } else { + + return null; + + } + + } else { + + extension = extensions.get( 'WEBGL_compressed_texture_s3tc' ); + + if ( extension !== null ) { + + if ( p === RGB_S3TC_DXT1_Format ) return extension.COMPRESSED_RGB_S3TC_DXT1_EXT; + if ( p === RGBA_S3TC_DXT1_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT1_EXT; + if ( p === RGBA_S3TC_DXT3_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT3_EXT; + if ( p === RGBA_S3TC_DXT5_Format ) return extension.COMPRESSED_RGBA_S3TC_DXT5_EXT; + + } else { + + return null; + + } + + } + + } + + // PVRTC + + if ( p === RGB_PVRTC_4BPPV1_Format || p === RGB_PVRTC_2BPPV1_Format || p === RGBA_PVRTC_4BPPV1_Format || p === RGBA_PVRTC_2BPPV1_Format ) { + + extension = extensions.get( 'WEBGL_compressed_texture_pvrtc' ); + + if ( extension !== null ) { + + if ( p === RGB_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_4BPPV1_IMG; + if ( p === RGB_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGB_PVRTC_2BPPV1_IMG; + if ( p === RGBA_PVRTC_4BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_4BPPV1_IMG; + if ( p === RGBA_PVRTC_2BPPV1_Format ) return extension.COMPRESSED_RGBA_PVRTC_2BPPV1_IMG; + + } else { + + return null; + + } + + } + + // ETC + + if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format || p === RGBA_ETC2_EAC_Format ) { + + extension = extensions.get( 'WEBGL_compressed_texture_etc' ); + + if ( extension !== null ) { + + if ( p === RGB_ETC1_Format || p === RGB_ETC2_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ETC2 : extension.COMPRESSED_RGB8_ETC2; + if ( p === RGBA_ETC2_EAC_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ETC2_EAC : extension.COMPRESSED_RGBA8_ETC2_EAC; + + } else { + + return null; + + } + + } + + // ASTC + + if ( p === RGBA_ASTC_4x4_Format || p === RGBA_ASTC_5x4_Format || p === RGBA_ASTC_5x5_Format || + p === RGBA_ASTC_6x5_Format || p === RGBA_ASTC_6x6_Format || p === RGBA_ASTC_8x5_Format || + p === RGBA_ASTC_8x6_Format || p === RGBA_ASTC_8x8_Format || p === RGBA_ASTC_10x5_Format || + p === RGBA_ASTC_10x6_Format || p === RGBA_ASTC_10x8_Format || p === RGBA_ASTC_10x10_Format || + p === RGBA_ASTC_12x10_Format || p === RGBA_ASTC_12x12_Format ) { + + extension = extensions.get( 'WEBGL_compressed_texture_astc' ); + + if ( extension !== null ) { + + if ( p === RGBA_ASTC_4x4_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR : extension.COMPRESSED_RGBA_ASTC_4x4_KHR; + if ( p === RGBA_ASTC_5x4_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR : extension.COMPRESSED_RGBA_ASTC_5x4_KHR; + if ( p === RGBA_ASTC_5x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR : extension.COMPRESSED_RGBA_ASTC_5x5_KHR; + if ( p === RGBA_ASTC_6x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR : extension.COMPRESSED_RGBA_ASTC_6x5_KHR; + if ( p === RGBA_ASTC_6x6_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR : extension.COMPRESSED_RGBA_ASTC_6x6_KHR; + if ( p === RGBA_ASTC_8x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR : extension.COMPRESSED_RGBA_ASTC_8x5_KHR; + if ( p === RGBA_ASTC_8x6_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR : extension.COMPRESSED_RGBA_ASTC_8x6_KHR; + if ( p === RGBA_ASTC_8x8_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR : extension.COMPRESSED_RGBA_ASTC_8x8_KHR; + if ( p === RGBA_ASTC_10x5_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR : extension.COMPRESSED_RGBA_ASTC_10x5_KHR; + if ( p === RGBA_ASTC_10x6_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR : extension.COMPRESSED_RGBA_ASTC_10x6_KHR; + if ( p === RGBA_ASTC_10x8_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR : extension.COMPRESSED_RGBA_ASTC_10x8_KHR; + if ( p === RGBA_ASTC_10x10_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR : extension.COMPRESSED_RGBA_ASTC_10x10_KHR; + if ( p === RGBA_ASTC_12x10_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR : extension.COMPRESSED_RGBA_ASTC_12x10_KHR; + if ( p === RGBA_ASTC_12x12_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR : extension.COMPRESSED_RGBA_ASTC_12x12_KHR; + + } else { + + return null; + + } + + } + + // BPTC + + if ( p === RGBA_BPTC_Format ) { + + extension = extensions.get( 'EXT_texture_compression_bptc' ); + + if ( extension !== null ) { + + if ( p === RGBA_BPTC_Format ) return ( colorSpace === SRGBColorSpace ) ? extension.COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT : extension.COMPRESSED_RGBA_BPTC_UNORM_EXT; + + } else { + + return null; + + } + + } + + // RGTC + + if ( p === RED_RGTC1_Format || p === SIGNED_RED_RGTC1_Format || p === RED_GREEN_RGTC2_Format || p === SIGNED_RED_GREEN_RGTC2_Format ) { + + extension = extensions.get( 'EXT_texture_compression_rgtc' ); + + if ( extension !== null ) { + + if ( p === RGBA_BPTC_Format ) return extension.COMPRESSED_RED_RGTC1_EXT; + if ( p === SIGNED_RED_RGTC1_Format ) return extension.COMPRESSED_SIGNED_RED_RGTC1_EXT; + if ( p === RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_RED_GREEN_RGTC2_EXT; + if ( p === SIGNED_RED_GREEN_RGTC2_Format ) return extension.COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT; + + } else { + + return null; + + } + + } + + // + + if ( p === UnsignedInt248Type ) { + + return gl.UNSIGNED_INT_24_8; + + } + + // if "p" can't be resolved, assume the user defines a WebGL constant as a string (fallback/workaround for packed RGB formats) + + return ( gl[ p ] !== undefined ) ? gl[ p ] : null; + + } + + _clientWaitAsync() { + + const { gl } = this; + + const sync = gl.fenceSync( gl.SYNC_GPU_COMMANDS_COMPLETE, 0 ); + + gl.flush(); + + return new Promise( ( resolve, reject ) => { + + function test() { + + const res = gl.clientWaitSync( sync, gl.SYNC_FLUSH_COMMANDS_BIT, 0 ); + + if ( res === gl.WAIT_FAILED ) { + + gl.deleteSync( sync ); + + reject(); + return; + + } + + if ( res === gl.TIMEOUT_EXPIRED ) { + + requestAnimationFrame( test ); + return; + + } + + gl.deleteSync( sync ); + + resolve(); + + } + + test(); + + } ); + + } + +} + +let initialized = false, wrappingToGL, filterToGL, compareToGL; + +class WebGLTextureUtils { + + constructor( backend ) { + + this.backend = backend; + + this.gl = backend.gl; + this.extensions = backend.extensions; + this.defaultTextures = {}; + + if ( initialized === false ) { + + this._init( this.gl ); + + initialized = true; + + } + + } + + _init( gl ) { + + // Store only WebGL constants here. + + wrappingToGL = { + [ RepeatWrapping ]: gl.REPEAT, + [ ClampToEdgeWrapping ]: gl.CLAMP_TO_EDGE, + [ MirroredRepeatWrapping ]: gl.MIRRORED_REPEAT + }; + + filterToGL = { + [ NearestFilter ]: gl.NEAREST, + [ NearestMipmapNearestFilter ]: gl.NEAREST_MIPMAP_NEAREST, + [ NearestMipmapLinearFilter ]: gl.NEAREST_MIPMAP_LINEAR, + + [ LinearFilter ]: gl.LINEAR, + [ LinearMipmapNearestFilter ]: gl.LINEAR_MIPMAP_NEAREST, + [ LinearMipmapLinearFilter ]: gl.LINEAR_MIPMAP_LINEAR + }; + + compareToGL = { + [ NeverCompare ]: gl.NEVER, + [ AlwaysCompare ]: gl.ALWAYS, + [ LessCompare ]: gl.LESS, + [ LessEqualCompare ]: gl.LEQUAL, + [ EqualCompare ]: gl.EQUAL, + [ GreaterEqualCompare ]: gl.GEQUAL, + [ GreaterCompare ]: gl.GREATER, + [ NotEqualCompare ]: gl.NOTEQUAL + }; + + } + + filterFallback( f ) { + + const { gl } = this; + + if ( f === NearestFilter || f === NearestMipmapNearestFilter || f === NearestMipmapLinearFilter ) { + + return gl.NEAREST; + + } + + return gl.LINEAR; + + } + + getGLTextureType( texture ) { + + const { gl } = this; + + let glTextureType; + + if ( texture.isCubeTexture === true ) { + + glTextureType = gl.TEXTURE_CUBE_MAP; + + } else if ( texture.isDataArrayTexture === true || texture.isCompressedArrayTexture === true ) { + + glTextureType = gl.TEXTURE_2D_ARRAY; + + } else if ( texture.isData3DTexture === true ) { // TODO: isCompressed3DTexture, wait for #26642 + + glTextureType = gl.TEXTURE_3D; + + } else { + + glTextureType = gl.TEXTURE_2D; + + + } + + return glTextureType; + + } + + getInternalFormat( internalFormatName, glFormat, glType, colorSpace, forceLinearTransfer = false ) { + + const { gl, extensions } = this; + + if ( internalFormatName !== null ) { + + if ( gl[ internalFormatName ] !== undefined ) return gl[ internalFormatName ]; + + console.warn( 'THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format \'' + internalFormatName + '\'' ); + + } + + let internalFormat = glFormat; + + if ( glFormat === gl.RED ) { + + if ( glType === gl.FLOAT ) internalFormat = gl.R32F; + if ( glType === gl.HALF_FLOAT ) internalFormat = gl.R16F; + if ( glType === gl.UNSIGNED_BYTE ) internalFormat = gl.R8; + if ( glType === gl.UNSIGNED_SHORT ) internalFormat = gl.R16; + if ( glType === gl.UNSIGNED_INT ) internalFormat = gl.R32UI; + if ( glType === gl.BYTE ) internalFormat = gl.R8I; + if ( glType === gl.SHORT ) internalFormat = gl.R16I; + if ( glType === gl.INT ) internalFormat = gl.R32I; + + } + + if ( glFormat === gl.RED_INTEGER ) { + + if ( glType === gl.UNSIGNED_BYTE ) internalFormat = gl.R8UI; + if ( glType === gl.UNSIGNED_SHORT ) internalFormat = gl.R16UI; + if ( glType === gl.UNSIGNED_INT ) internalFormat = gl.R32UI; + if ( glType === gl.BYTE ) internalFormat = gl.R8I; + if ( glType === gl.SHORT ) internalFormat = gl.R16I; + if ( glType === gl.INT ) internalFormat = gl.R32I; + + } + + if ( glFormat === gl.RG ) { + + if ( glType === gl.FLOAT ) internalFormat = gl.RG32F; + if ( glType === gl.HALF_FLOAT ) internalFormat = gl.RG16F; + if ( glType === gl.UNSIGNED_BYTE ) internalFormat = gl.RG8; + if ( glType === gl.UNSIGNED_SHORT ) internalFormat = gl.RG16; + if ( glType === gl.UNSIGNED_INT ) internalFormat = gl.RG32UI; + if ( glType === gl.BYTE ) internalFormat = gl.RG8I; + if ( glType === gl.SHORT ) internalFormat = gl.RG16I; + if ( glType === gl.INT ) internalFormat = gl.RG32I; + + } + + if ( glFormat === gl.RG_INTEGER ) { + + if ( glType === gl.UNSIGNED_BYTE ) internalFormat = gl.RG8UI; + if ( glType === gl.UNSIGNED_SHORT ) internalFormat = gl.RG16UI; + if ( glType === gl.UNSIGNED_INT ) internalFormat = gl.RG32UI; + if ( glType === gl.BYTE ) internalFormat = gl.RG8I; + if ( glType === gl.SHORT ) internalFormat = gl.RG16I; + if ( glType === gl.INT ) internalFormat = gl.RG32I; + + } + + if ( glFormat === gl.RGB ) { + + if ( glType === gl.FLOAT ) internalFormat = gl.RGB32F; + if ( glType === gl.HALF_FLOAT ) internalFormat = gl.RGB16F; + if ( glType === gl.UNSIGNED_BYTE ) internalFormat = gl.RGB8; + if ( glType === gl.UNSIGNED_SHORT ) internalFormat = gl.RGB16; + if ( glType === gl.UNSIGNED_INT ) internalFormat = gl.RGB32UI; + if ( glType === gl.BYTE ) internalFormat = gl.RGB8I; + if ( glType === gl.SHORT ) internalFormat = gl.RGB16I; + if ( glType === gl.INT ) internalFormat = gl.RGB32I; + if ( glType === gl.UNSIGNED_BYTE ) internalFormat = ( colorSpace === SRGBColorSpace && forceLinearTransfer === false ) ? gl.SRGB8 : gl.RGB8; + if ( glType === gl.UNSIGNED_SHORT_5_6_5 ) internalFormat = gl.RGB565; + if ( glType === gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = gl.RGB5_A1; + if ( glType === gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = gl.RGB4; + if ( glType === gl.UNSIGNED_INT_5_9_9_9_REV ) internalFormat = gl.RGB9_E5; + + } + + if ( glFormat === gl.RGB_INTEGER ) { + + if ( glType === gl.UNSIGNED_BYTE ) internalFormat = gl.RGB8UI; + if ( glType === gl.UNSIGNED_SHORT ) internalFormat = gl.RGB16UI; + if ( glType === gl.UNSIGNED_INT ) internalFormat = gl.RGB32UI; + if ( glType === gl.BYTE ) internalFormat = gl.RGB8I; + if ( glType === gl.SHORT ) internalFormat = gl.RGB16I; + if ( glType === gl.INT ) internalFormat = gl.RGB32I; + + } + + if ( glFormat === gl.RGBA ) { + + if ( glType === gl.FLOAT ) internalFormat = gl.RGBA32F; + if ( glType === gl.HALF_FLOAT ) internalFormat = gl.RGBA16F; + if ( glType === gl.UNSIGNED_BYTE ) internalFormat = gl.RGBA8; + if ( glType === gl.UNSIGNED_SHORT ) internalFormat = gl.RGBA16; + if ( glType === gl.UNSIGNED_INT ) internalFormat = gl.RGBA32UI; + if ( glType === gl.BYTE ) internalFormat = gl.RGBA8I; + if ( glType === gl.SHORT ) internalFormat = gl.RGBA16I; + if ( glType === gl.INT ) internalFormat = gl.RGBA32I; + if ( glType === gl.UNSIGNED_BYTE ) internalFormat = ( colorSpace === SRGBColorSpace && forceLinearTransfer === false ) ? gl.SRGB8_ALPHA8 : gl.RGBA8; + if ( glType === gl.UNSIGNED_SHORT_4_4_4_4 ) internalFormat = gl.RGBA4; + if ( glType === gl.UNSIGNED_SHORT_5_5_5_1 ) internalFormat = gl.RGB5_A1; + + } + + if ( glFormat === gl.RGBA_INTEGER ) { + + if ( glType === gl.UNSIGNED_BYTE ) internalFormat = gl.RGBA8UI; + if ( glType === gl.UNSIGNED_SHORT ) internalFormat = gl.RGBA16UI; + if ( glType === gl.UNSIGNED_INT ) internalFormat = gl.RGBA32UI; + if ( glType === gl.BYTE ) internalFormat = gl.RGBA8I; + if ( glType === gl.SHORT ) internalFormat = gl.RGBA16I; + if ( glType === gl.INT ) internalFormat = gl.RGBA32I; + + } + + if ( glFormat === gl.DEPTH_COMPONENT ) { + + if ( glType === gl.UNSIGNED_INT ) internalFormat = gl.DEPTH24_STENCIL8; + if ( glType === gl.FLOAT ) internalFormat = gl.DEPTH_COMPONENT32F; + + } + + if ( glFormat === gl.DEPTH_STENCIL ) { + + if ( glType === gl.UNSIGNED_INT_24_8 ) internalFormat = gl.DEPTH24_STENCIL8; + + } + + if ( internalFormat === gl.R16F || internalFormat === gl.R32F || + internalFormat === gl.RG16F || internalFormat === gl.RG32F || + internalFormat === gl.RGBA16F || internalFormat === gl.RGBA32F ) { + + extensions.get( 'EXT_color_buffer_float' ); + + } + + return internalFormat; + + } + + setTextureParameters( textureType, texture ) { + + const { gl, extensions, backend } = this; + + + gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, texture.flipY ); + gl.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, texture.premultiplyAlpha ); + gl.pixelStorei( gl.UNPACK_ALIGNMENT, texture.unpackAlignment ); + gl.pixelStorei( gl.UNPACK_COLORSPACE_CONVERSION_WEBGL, gl.NONE ); + + gl.texParameteri( textureType, gl.TEXTURE_WRAP_S, wrappingToGL[ texture.wrapS ] ); + gl.texParameteri( textureType, gl.TEXTURE_WRAP_T, wrappingToGL[ texture.wrapT ] ); + + if ( textureType === gl.TEXTURE_3D || textureType === gl.TEXTURE_2D_ARRAY ) { + + gl.texParameteri( textureType, gl.TEXTURE_WRAP_R, wrappingToGL[ texture.wrapR ] ); + + } + + gl.texParameteri( textureType, gl.TEXTURE_MAG_FILTER, filterToGL[ texture.magFilter ] ); + + + const hasMipmaps = texture.mipmaps !== undefined && texture.mipmaps.length > 0; + + // follow WebGPU backend mapping for texture filtering + const minFilter = texture.minFilter === LinearFilter && hasMipmaps ? LinearMipmapLinearFilter : texture.minFilter; + + gl.texParameteri( textureType, gl.TEXTURE_MIN_FILTER, filterToGL[ minFilter ] ); + + if ( texture.compareFunction ) { + + gl.texParameteri( textureType, gl.TEXTURE_COMPARE_MODE, gl.COMPARE_REF_TO_TEXTURE ); + gl.texParameteri( textureType, gl.TEXTURE_COMPARE_FUNC, compareToGL[ texture.compareFunction ] ); + + } + + if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { + + if ( texture.magFilter === NearestFilter ) return; + if ( texture.minFilter !== NearestMipmapLinearFilter && texture.minFilter !== LinearMipmapLinearFilter ) return; + if ( texture.type === FloatType && extensions.has( 'OES_texture_float_linear' ) === false ) return; // verify extension for WebGL 1 and WebGL 2 + + if ( texture.anisotropy > 1 ) { + + const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); + gl.texParameterf( textureType, extension.TEXTURE_MAX_ANISOTROPY_EXT, Math.min( texture.anisotropy, backend.getMaxAnisotropy() ) ); + + } + + } + + } + + createDefaultTexture( texture ) { + + const { gl, backend, defaultTextures } = this; + + + const glTextureType = this.getGLTextureType( texture ); + + let textureGPU = defaultTextures[ glTextureType ]; + + if ( textureGPU === undefined ) { + + textureGPU = gl.createTexture(); + + backend.state.bindTexture( glTextureType, textureGPU ); + gl.texParameteri( glTextureType, gl.TEXTURE_MIN_FILTER, gl.NEAREST ); + gl.texParameteri( glTextureType, gl.TEXTURE_MAG_FILTER, gl.NEAREST ); + + // gl.texImage2D( glTextureType, 0, gl.RGBA, 1, 1, 0, gl.RGBA, gl.UNSIGNED_BYTE, data ); + + defaultTextures[ glTextureType ] = textureGPU; + + } + + backend.set( texture, { + textureGPU, + glTextureType, + isDefault: true + } ); + + } + + createTexture( texture, options ) { + + const { gl, backend } = this; + const { levels, width, height, depth } = options; + + const glFormat = backend.utils.convert( texture.format, texture.colorSpace ); + const glType = backend.utils.convert( texture.type ); + const glInternalFormat = this.getInternalFormat( texture.internalFormat, glFormat, glType, texture.colorSpace, texture.isVideoTexture ); + + const textureGPU = gl.createTexture(); + const glTextureType = this.getGLTextureType( texture ); + + backend.state.bindTexture( glTextureType, textureGPU ); + + this.setTextureParameters( glTextureType, texture ); + + if ( texture.isDataArrayTexture || texture.isCompressedArrayTexture ) { + + gl.texStorage3D( gl.TEXTURE_2D_ARRAY, levels, glInternalFormat, width, height, depth ); + + } else if ( texture.isData3DTexture ) { + + gl.texStorage3D( gl.TEXTURE_3D, levels, glInternalFormat, width, height, depth ); + + } else if ( ! texture.isVideoTexture ) { + + gl.texStorage2D( glTextureType, levels, glInternalFormat, width, height ); + + } + + backend.set( texture, { + textureGPU, + glTextureType, + glFormat, + glType, + glInternalFormat + } ); + + } + + copyBufferToTexture( buffer, texture ) { + + const { gl, backend } = this; + + const { textureGPU, glTextureType, glFormat, glType } = backend.get( texture ); + + const { width, height } = texture.source.data; + + gl.bindBuffer( gl.PIXEL_UNPACK_BUFFER, buffer ); + + backend.state.bindTexture( glTextureType, textureGPU ); + + gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, false ); + gl.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false ); + gl.texSubImage2D( glTextureType, 0, 0, 0, width, height, glFormat, glType, 0 ); + + gl.bindBuffer( gl.PIXEL_UNPACK_BUFFER, null ); + + backend.state.unbindTexture(); + // debug + // const framebuffer = gl.createFramebuffer(); + // gl.bindFramebuffer( gl.FRAMEBUFFER, framebuffer ); + // gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, glTextureType, textureGPU, 0 ); + + // const readout = new Float32Array( width * height * 4 ); + + // const altFormat = gl.getParameter( gl.IMPLEMENTATION_COLOR_READ_FORMAT ); + // const altType = gl.getParameter( gl.IMPLEMENTATION_COLOR_READ_TYPE ); + + // gl.readPixels( 0, 0, width, height, altFormat, altType, readout ); + // gl.bindFramebuffer( gl.FRAMEBUFFER, null ); + // console.log( readout ); + + } + + updateTexture( texture, options ) { + + const { gl } = this; + const { width, height } = options; + const { textureGPU, glTextureType, glFormat, glType, glInternalFormat } = this.backend.get( texture ); + + if ( texture.isRenderTargetTexture || ( textureGPU === undefined /* unsupported texture format */ ) ) + return; + + const getImage = ( source ) => { + + if ( source.isDataTexture ) { + + return source.image.data; + + } else if ( source instanceof ImageBitmap || source instanceof OffscreenCanvas || source instanceof HTMLImageElement || source instanceof HTMLCanvasElement ) { + + return source; + + } + + return source.data; + + }; + + this.backend.state.bindTexture( glTextureType, textureGPU ); + + this.setTextureParameters( glTextureType, texture ); + + if ( texture.isCompressedTexture ) { + + const mipmaps = texture.mipmaps; + const image = options.image; + + for ( let i = 0; i < mipmaps.length; i ++ ) { + + const mipmap = mipmaps[ i ]; + + if ( texture.isCompressedArrayTexture ) { + + + if ( texture.format !== gl.RGBA ) { + + if ( glFormat !== null ) { + + gl.compressedTexSubImage3D( gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, mipmap.data, 0, 0 ); + + + } else { + + console.warn( 'THREE.WebGLRenderer: Attempt to load unsupported compressed texture format in .uploadTexture()' ); + + } + + } else { + + gl.texSubImage3D( gl.TEXTURE_2D_ARRAY, i, 0, 0, 0, mipmap.width, mipmap.height, image.depth, glFormat, glType, mipmap.data ); + + } + + } else { + + if ( glFormat !== null ) { + + gl.compressedTexSubImage2D( gl.TEXTURE_2D, i, 0, 0, mipmap.width, mipmap.height, glFormat, mipmap.data ); + + } else { + + console.warn( 'Unsupported compressed texture format' ); + + } + + } + + } + + + } else if ( texture.isCubeTexture ) { + + const images = options.images; + + for ( let i = 0; i < 6; i ++ ) { + + const image = getImage( images[ i ] ); + + gl.texSubImage2D( gl.TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, 0, 0, width, height, glFormat, glType, image ); + + } + + } else if ( texture.isDataArrayTexture ) { + + const image = options.image; + + gl.texSubImage3D( gl.TEXTURE_2D_ARRAY, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); + + } else if ( texture.isData3DTexture ) { + + const image = options.image; + + gl.texSubImage3D( gl.TEXTURE_3D, 0, 0, 0, 0, image.width, image.height, image.depth, glFormat, glType, image.data ); + + } else if ( texture.isVideoTexture ) { + + texture.update(); + + gl.texImage2D( glTextureType, 0, glInternalFormat, glFormat, glType, options.image ); + + + } else { + + const image = getImage( options.image ); + + gl.texSubImage2D( glTextureType, 0, 0, 0, width, height, glFormat, glType, image ); + + } + + } + + generateMipmaps( texture ) { + + const { gl, backend } = this; + const { textureGPU, glTextureType } = backend.get( texture ); + + backend.state.bindTexture( glTextureType, textureGPU ); + gl.generateMipmap( glTextureType ); + + } + + deallocateRenderBuffers( renderTarget ) { + + const { gl, backend } = this; + + // remove framebuffer reference + if ( renderTarget ) { + + const renderContextData = backend.get( renderTarget ); + + renderContextData.renderBufferStorageSetup = undefined; + + if ( renderContextData.framebuffers ) { + + for ( const cacheKey in renderContextData.framebuffers ) { + + gl.deleteFramebuffer( renderContextData.framebuffers[ cacheKey ] ); + + } + + delete renderContextData.framebuffers; + + } + + if ( renderContextData.depthRenderbuffer ) { + + gl.deleteRenderbuffer( renderContextData.depthRenderbuffer ); + delete renderContextData.depthRenderbuffer; + + } + + if ( renderContextData.stencilRenderbuffer ) { + + gl.deleteRenderbuffer( renderContextData.stencilRenderbuffer ); + delete renderContextData.stencilRenderbuffer; + + } + + if ( renderContextData.msaaFrameBuffer ) { + + gl.deleteFramebuffer( renderContextData.msaaFrameBuffer ); + delete renderContextData.msaaFrameBuffer; + + } + + if ( renderContextData.msaaRenderbuffers ) { + + for ( let i = 0; i < renderContextData.msaaRenderbuffers.length; i ++ ) { + + gl.deleteRenderbuffer( renderContextData.msaaRenderbuffers[ i ] ); + + } + + delete renderContextData.msaaRenderbuffers; + + } + + } + + } + + destroyTexture( texture ) { + + const { gl, backend } = this; + const { textureGPU, renderTarget } = backend.get( texture ); + + this.deallocateRenderBuffers( renderTarget ); + gl.deleteTexture( textureGPU ); + + backend.delete( texture ); + + } + + copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { + + const { gl, backend } = this; + const { state } = this.backend; + + const { textureGPU: dstTextureGPU, glTextureType, glType, glFormat } = backend.get( dstTexture ); + + + let width, height, minX, minY; + let dstX, dstY; + if ( srcRegion !== null ) { + + width = srcRegion.max.x - srcRegion.min.x; + height = srcRegion.max.y - srcRegion.min.y; + minX = srcRegion.min.x; + minY = srcRegion.min.y; + + } else { + + width = srcTexture.image.width; + height = srcTexture.image.height; + minX = 0; + minY = 0; + + } + + if ( dstPosition !== null ) { + + dstX = dstPosition.x; + dstY = dstPosition.y; + + } else { + + dstX = 0; + dstY = 0; + + } + + state.bindTexture( glTextureType, dstTextureGPU ); + + // As another texture upload may have changed pixelStorei + // parameters, make sure they are correct for the dstTexture + gl.pixelStorei( gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); + gl.pixelStorei( gl.UNPACK_FLIP_Y_WEBGL, dstTexture.flipY ); + gl.pixelStorei( gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, dstTexture.premultiplyAlpha ); + gl.pixelStorei( gl.UNPACK_ALIGNMENT, dstTexture.unpackAlignment ); + + const currentUnpackRowLen = gl.getParameter( gl.UNPACK_ROW_LENGTH ); + const currentUnpackImageHeight = gl.getParameter( gl.UNPACK_IMAGE_HEIGHT ); + const currentUnpackSkipPixels = gl.getParameter( gl.UNPACK_SKIP_PIXELS ); + const currentUnpackSkipRows = gl.getParameter( gl.UNPACK_SKIP_ROWS ); + const currentUnpackSkipImages = gl.getParameter( gl.UNPACK_SKIP_IMAGES ); + + const image = srcTexture.isCompressedTexture ? srcTexture.mipmaps[ level ] : srcTexture.image; + + gl.pixelStorei( gl.UNPACK_ROW_LENGTH, image.width ); + gl.pixelStorei( gl.UNPACK_IMAGE_HEIGHT, image.height ); + gl.pixelStorei( gl.UNPACK_SKIP_PIXELS, minX ); + gl.pixelStorei( gl.UNPACK_SKIP_ROWS, minY ); + + + if ( srcTexture.isDataTexture ) { + + gl.texSubImage2D( gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image.data ); + + } else { + + if ( srcTexture.isCompressedTexture ) { + + gl.compressedTexSubImage2D( gl.TEXTURE_2D, level, dstX, dstY, image.width, image.height, glFormat, image.data ); + + } else { + + gl.texSubImage2D( gl.TEXTURE_2D, level, dstX, dstY, width, height, glFormat, glType, image ); + + } + + } + + gl.pixelStorei( gl.UNPACK_ROW_LENGTH, currentUnpackRowLen ); + gl.pixelStorei( gl.UNPACK_IMAGE_HEIGHT, currentUnpackImageHeight ); + gl.pixelStorei( gl.UNPACK_SKIP_PIXELS, currentUnpackSkipPixels ); + gl.pixelStorei( gl.UNPACK_SKIP_ROWS, currentUnpackSkipRows ); + gl.pixelStorei( gl.UNPACK_SKIP_IMAGES, currentUnpackSkipImages ); + + // Generate mipmaps only when copying level 0 + if ( level === 0 && dstTexture.generateMipmaps ) gl.generateMipmap( gl.TEXTURE_2D ); + + state.unbindTexture(); + + } + + copyFramebufferToTexture( texture, renderContext, rectangle ) { + + const { gl } = this; + const { state } = this.backend; + + const { textureGPU } = this.backend.get( texture ); + + const { x, y, z: width, w: height } = rectangle; + + const requireDrawFrameBuffer = texture.isDepthTexture === true || ( renderContext.renderTarget && renderContext.renderTarget.samples > 0 ); + + const srcHeight = renderContext.renderTarget ? renderContext.renderTarget.height : this.backend.gerDrawingBufferSize().y; + + if ( requireDrawFrameBuffer ) { + + const partial = ( x !== 0 || y !== 0 ); + let mask; + let attachment; + + if ( texture.isDepthTexture === true ) { + + mask = gl.DEPTH_BUFFER_BIT; + attachment = gl.DEPTH_ATTACHMENT; + + if ( renderContext.stencil ) { + + mask |= gl.STENCIL_BUFFER_BIT; + + } + + } else { + + mask = gl.COLOR_BUFFER_BIT; + attachment = gl.COLOR_ATTACHMENT0; + + } + + if ( partial ) { + + const renderTargetContextData = this.backend.get( renderContext.renderTarget ); + + const fb = renderTargetContextData.framebuffers[ renderContext.getCacheKey() ]; + const msaaFrameBuffer = renderTargetContextData.msaaFrameBuffer; + + state.bindFramebuffer( gl.DRAW_FRAMEBUFFER, fb ); + state.bindFramebuffer( gl.READ_FRAMEBUFFER, msaaFrameBuffer ); + + const flippedY = srcHeight - y - height; + + gl.blitFramebuffer( x, flippedY, x + width, flippedY + height, x, flippedY, x + width, flippedY + height, mask, gl.NEAREST ); + + state.bindFramebuffer( gl.READ_FRAMEBUFFER, fb ); + + state.bindTexture( gl.TEXTURE_2D, textureGPU ); + + gl.copyTexSubImage2D( gl.TEXTURE_2D, 0, 0, 0, x, flippedY, width, height ); + + state.unbindTexture(); + + } else { + + const fb = gl.createFramebuffer(); + + state.bindFramebuffer( gl.DRAW_FRAMEBUFFER, fb ); + + gl.framebufferTexture2D( gl.DRAW_FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureGPU, 0 ); + gl.blitFramebuffer( 0, 0, width, height, 0, 0, width, height, mask, gl.NEAREST ); + + gl.deleteFramebuffer( fb ); + + } + + } else { + + state.bindTexture( gl.TEXTURE_2D, textureGPU ); + gl.copyTexSubImage2D( gl.TEXTURE_2D, 0, 0, 0, x, srcHeight - height - y, width, height ); + + state.unbindTexture(); + + } + + if ( texture.generateMipmaps ) this.generateMipmaps( texture ); + + this.backend._setFramebuffer( renderContext ); + + } + + // Setup storage for internal depth/stencil buffers and bind to correct framebuffer + setupRenderBufferStorage( renderbuffer, renderContext ) { + + const { gl } = this; + const renderTarget = renderContext.renderTarget; + + const { samples, depthTexture, depthBuffer, stencilBuffer, width, height } = renderTarget; + + gl.bindRenderbuffer( gl.RENDERBUFFER, renderbuffer ); + + if ( depthBuffer && ! stencilBuffer ) { + + let glInternalFormat = gl.DEPTH_COMPONENT24; + + if ( samples > 0 ) { + + if ( depthTexture && depthTexture.isDepthTexture ) { + + if ( depthTexture.type === gl.FLOAT ) { + + glInternalFormat = gl.DEPTH_COMPONENT32F; + + } + + } + + gl.renderbufferStorageMultisample( gl.RENDERBUFFER, samples, glInternalFormat, width, height ); + + } else { + + gl.renderbufferStorage( gl.RENDERBUFFER, glInternalFormat, width, height ); + + } + + gl.framebufferRenderbuffer( gl.FRAMEBUFFER, gl.DEPTH_ATTACHMENT, gl.RENDERBUFFER, renderbuffer ); + + } else if ( depthBuffer && stencilBuffer ) { + + if ( samples > 0 ) { + + gl.renderbufferStorageMultisample( gl.RENDERBUFFER, samples, gl.DEPTH24_STENCIL8, width, height ); + + } else { + + gl.renderbufferStorage( gl.RENDERBUFFER, gl.DEPTH_STENCIL, width, height ); + + } + + + gl.framebufferRenderbuffer( gl.FRAMEBUFFER, gl.DEPTH_STENCIL_ATTACHMENT, gl.RENDERBUFFER, renderbuffer ); + + } + + } + + async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { + + const { backend, gl } = this; + + const { textureGPU, glFormat, glType } = this.backend.get( texture ); + + const fb = gl.createFramebuffer(); + + gl.bindFramebuffer( gl.READ_FRAMEBUFFER, fb ); + + const target = texture.isCubeTexture ? gl.TEXTURE_CUBE_MAP_POSITIVE_X + faceIndex : gl.TEXTURE_2D; + + gl.framebufferTexture2D( gl.READ_FRAMEBUFFER, gl.COLOR_ATTACHMENT0, target, textureGPU, 0 ); + + const typedArrayType = this._getTypedArrayType( glType ); + const bytesPerTexel = this._getBytesPerTexel( glType, glFormat ); + + const elementCount = width * height; + const byteLength = elementCount * bytesPerTexel; + + const buffer = gl.createBuffer(); + + gl.bindBuffer( gl.PIXEL_PACK_BUFFER, buffer ); + gl.bufferData( gl.PIXEL_PACK_BUFFER, byteLength, gl.STREAM_READ ); + gl.readPixels( x, y, width, height, glFormat, glType, 0 ); + gl.bindBuffer( gl.PIXEL_PACK_BUFFER, null ); + + await backend.utils._clientWaitAsync(); + + const dstBuffer = new typedArrayType( byteLength / typedArrayType.BYTES_PER_ELEMENT ); + + gl.bindBuffer( gl.PIXEL_PACK_BUFFER, buffer ); + gl.getBufferSubData( gl.PIXEL_PACK_BUFFER, 0, dstBuffer ); + gl.bindBuffer( gl.PIXEL_PACK_BUFFER, null ); + + gl.deleteFramebuffer( fb ); + + return dstBuffer; + + } + + _getTypedArrayType( glType ) { + + const { gl } = this; + + if ( glType === gl.UNSIGNED_BYTE ) return Uint8Array; + + if ( glType === gl.UNSIGNED_SHORT_4_4_4_4 ) return Uint16Array; + if ( glType === gl.UNSIGNED_SHORT_5_5_5_1 ) return Uint16Array; + if ( glType === gl.UNSIGNED_SHORT_5_6_5 ) return Uint16Array; + if ( glType === gl.UNSIGNED_SHORT ) return Uint16Array; + if ( glType === gl.UNSIGNED_INT ) return Uint32Array; + + if ( glType === gl.HALF_FLOAT ) return Uint16Array; + if ( glType === gl.FLOAT ) return Float32Array; + + throw new Error( `Unsupported WebGL type: ${glType}` ); + + } + + _getBytesPerTexel( glType, glFormat ) { + + const { gl } = this; + + let bytesPerComponent = 0; + + if ( glType === gl.UNSIGNED_BYTE ) bytesPerComponent = 1; + + if ( glType === gl.UNSIGNED_SHORT_4_4_4_4 || + glType === gl.UNSIGNED_SHORT_5_5_5_1 || + glType === gl.UNSIGNED_SHORT_5_6_5 || + glType === gl.UNSIGNED_SHORT || + glType === gl.HALF_FLOAT ) bytesPerComponent = 2; + + if ( glType === gl.UNSIGNED_INT || + glType === gl.FLOAT ) bytesPerComponent = 4; + + if ( glFormat === gl.RGBA ) return bytesPerComponent * 4; + if ( glFormat === gl.RGB ) return bytesPerComponent * 3; + if ( glFormat === gl.ALPHA ) return bytesPerComponent; + + } + +} + +class WebGLExtensions { + + constructor( backend ) { + + this.backend = backend; + + this.gl = this.backend.gl; + this.availableExtensions = this.gl.getSupportedExtensions(); + + this.extensions = {}; + + } + + get( name ) { + + let extension = this.extensions[ name ]; + + if ( extension === undefined ) { + + extension = this.gl.getExtension( name ); + + this.extensions[ name ] = extension; + + } + + return extension; + + } + + has( name ) { + + return this.availableExtensions.includes( name ); + + } + +} + +class WebGLCapabilities { + + constructor( backend ) { + + this.backend = backend; + + this.maxAnisotropy = null; + + } + + getMaxAnisotropy() { + + if ( this.maxAnisotropy !== null ) return this.maxAnisotropy; + + const gl = this.backend.gl; + const extensions = this.backend.extensions; + + if ( extensions.has( 'EXT_texture_filter_anisotropic' ) === true ) { + + const extension = extensions.get( 'EXT_texture_filter_anisotropic' ); + + this.maxAnisotropy = gl.getParameter( extension.MAX_TEXTURE_MAX_ANISOTROPY_EXT ); + + } else { + + this.maxAnisotropy = 0; + + } + + return this.maxAnisotropy; + + } + +} + +const GLFeatureName = { + + 'WEBGL_multi_draw': 'WEBGL_multi_draw', + 'WEBGL_compressed_texture_astc': 'texture-compression-astc', + 'WEBGL_compressed_texture_etc': 'texture-compression-etc2', + 'WEBGL_compressed_texture_etc1': 'texture-compression-etc1', + 'WEBGL_compressed_texture_pvrtc': 'texture-compression-pvrtc', + 'WEBKIT_WEBGL_compressed_texture_pvrtc': 'texture-compression-pvrtc', + 'WEBGL_compressed_texture_s3tc': 'texture-compression-bc', + 'EXT_texture_compression_bptc': 'texture-compression-bptc', + 'EXT_disjoint_timer_query_webgl2': 'timestamp-query', + +}; + +class WebGLBufferRenderer { + + constructor( backend ) { + + this.gl = backend.gl; + this.extensions = backend.extensions; + this.info = backend.renderer.info; + this.mode = null; + this.index = 0; + this.type = null; + this.object = null; + + } + + render( start, count ) { + + const { gl, mode, object, type, info, index } = this; + + if ( index !== 0 ) { + + gl.drawElements( mode, count, type, start ); + + } else { + + gl.drawArrays( mode, start, count ); + + } + + info.update( object, count, mode, 1 ); + + } + + renderInstances( start, count, primcount ) { + + const { gl, mode, type, index, object, info } = this; + + if ( primcount === 0 ) return; + + if ( index !== 0 ) { + + gl.drawElementsInstanced( mode, count, type, start, primcount ); + + } else { + + gl.drawArraysInstanced( mode, start, count, primcount ); + + } + + info.update( object, count, mode, primcount ); + + } + + renderMultiDraw( starts, counts, drawCount ) { + + const { extensions, mode, object, info } = this; + + if ( drawCount === 0 ) return; + + const extension = extensions.get( 'WEBGL_multi_draw' ); + + if ( extension === null ) { + + for ( let i = 0; i < drawCount; i ++ ) { + + this.render( starts[ i ], counts[ i ] ); + + } + + } else { + + if ( this.index !== 0 ) { + + extension.multiDrawElementsWEBGL( mode, counts, 0, this.type, starts, 0, drawCount ); + + } else { + + extension.multiDrawArraysWEBGL( mode, starts, 0, counts, 0, drawCount ); + + } + + let elementCount = 0; + for ( let i = 0; i < drawCount; i ++ ) { + + elementCount += counts[ i ]; + + } + + info.update( object, elementCount, mode, 1 ); + + } + + } + + renderMultiDrawInstances( starts, counts, drawCount, primcount ) { + + const { extensions, mode, object, info } = this; + + if ( drawCount === 0 ) return; + + const extension = extensions.get( 'WEBGL_multi_draw' ); + + if ( extension === null ) { + + for ( let i = 0; i < drawCount; i ++ ) { + + this.renderInstances( starts[ i ], counts[ i ], primcount[ i ] ); + + } + + } else { + + if ( this.index !== 0 ) { + + extension.multiDrawElementsInstancedWEBGL( mode, counts, 0, this.type, starts, 0, primcount, 0, drawCount ); + + } else { + + extension.multiDrawArraysInstancedWEBGL( mode, starts, 0, counts, 0, primcount, 0, drawCount ); + + } + + let elementCount = 0; + + for ( let i = 0; i < drawCount; i ++ ) { + + elementCount += counts[ i ]; + + } + + for ( let i = 0; i < primcount.length; i ++ ) { + + info.update( object, elementCount, mode, primcount[ i ] ); + + } + + } + + } + + // + +} + +// + +class WebGLBackend extends Backend { + + constructor( parameters = {} ) { + + super( parameters ); + + this.isWebGLBackend = true; + + } + + init( renderer ) { + + super.init( renderer ); + + // + + const parameters = this.parameters; + + const glContext = ( parameters.context !== undefined ) ? parameters.context : renderer.domElement.getContext( 'webgl2' ); + + this.gl = glContext; + + this.extensions = new WebGLExtensions( this ); + this.capabilities = new WebGLCapabilities( this ); + this.attributeUtils = new WebGLAttributeUtils( this ); + this.textureUtils = new WebGLTextureUtils( this ); + this.bufferRenderer = new WebGLBufferRenderer( this ); + + this.state = new WebGLState( this ); + this.utils = new WebGLUtils( this ); + + this.vaoCache = {}; + this.transformFeedbackCache = {}; + this.discard = false; + this.trackTimestamp = ( parameters.trackTimestamp === true ); + + this.extensions.get( 'EXT_color_buffer_float' ); + this.extensions.get( 'WEBGL_clip_cull_distance' ); + this.extensions.get( 'OES_texture_float_linear' ); + this.extensions.get( 'EXT_color_buffer_half_float' ); + this.extensions.get( 'WEBGL_multisampled_render_to_texture' ); + this.extensions.get( 'WEBGL_render_shared_exponent' ); + this.extensions.get( 'WEBGL_multi_draw' ); + + this.disjoint = this.extensions.get( 'EXT_disjoint_timer_query_webgl2' ); + this.parallel = this.extensions.get( 'KHR_parallel_shader_compile' ); + + this._currentContext = null; + + } + + get coordinateSystem() { + + return WebGLCoordinateSystem; + + } + + async getArrayBufferAsync( attribute ) { + + return await this.attributeUtils.getArrayBufferAsync( attribute ); + + } + + + initTimestampQuery( renderContext ) { + + if ( ! this.disjoint || ! this.trackTimestamp ) return; + + const renderContextData = this.get( renderContext ); + + if ( this.queryRunning ) { + + if ( ! renderContextData.queryQueue ) renderContextData.queryQueue = []; + renderContextData.queryQueue.push( renderContext ); + return; + + } + + if ( renderContextData.activeQuery ) { + + this.gl.endQuery( this.disjoint.TIME_ELAPSED_EXT ); + renderContextData.activeQuery = null; + + } + + renderContextData.activeQuery = this.gl.createQuery(); + + if ( renderContextData.activeQuery !== null ) { + + this.gl.beginQuery( this.disjoint.TIME_ELAPSED_EXT, renderContextData.activeQuery ); + this.queryRunning = true; + + } + + } + + // timestamp utils + + prepareTimestampBuffer( renderContext ) { + + if ( ! this.disjoint || ! this.trackTimestamp ) return; + + const renderContextData = this.get( renderContext ); + + if ( renderContextData.activeQuery ) { + + this.gl.endQuery( this.disjoint.TIME_ELAPSED_EXT ); + + if ( ! renderContextData.gpuQueries ) renderContextData.gpuQueries = []; + renderContextData.gpuQueries.push( { query: renderContextData.activeQuery } ); + renderContextData.activeQuery = null; + this.queryRunning = false; + + if ( renderContextData.queryQueue && renderContextData.queryQueue.length > 0 ) { + + const nextRenderContext = renderContextData.queryQueue.shift(); + this.initTimestampQuery( nextRenderContext ); + + } + + } + + } + + async resolveTimestampAsync( renderContext, type = 'render' ) { + + if ( ! this.disjoint || ! this.trackTimestamp ) return; + + const renderContextData = this.get( renderContext ); + + if ( ! renderContextData.gpuQueries ) renderContextData.gpuQueries = []; + + for ( let i = 0; i < renderContextData.gpuQueries.length; i ++ ) { + + const queryInfo = renderContextData.gpuQueries[ i ]; + const available = this.gl.getQueryParameter( queryInfo.query, this.gl.QUERY_RESULT_AVAILABLE ); + const disjoint = this.gl.getParameter( this.disjoint.GPU_DISJOINT_EXT ); + + if ( available && ! disjoint ) { + + const elapsed = this.gl.getQueryParameter( queryInfo.query, this.gl.QUERY_RESULT ); + const duration = Number( elapsed ) / 1000000; // Convert nanoseconds to milliseconds + this.gl.deleteQuery( queryInfo.query ); + renderContextData.gpuQueries.splice( i, 1 ); // Remove the processed query + i --; + this.renderer.info.updateTimestamp( type, duration ); + + } + + } + + } + + getContext() { + + return this.gl; + + } + + beginRender( renderContext ) { + + const { gl } = this; + const renderContextData = this.get( renderContext ); + + // + + // + + this.initTimestampQuery( renderContext ); + + renderContextData.previousContext = this._currentContext; + this._currentContext = renderContext; + + this._setFramebuffer( renderContext ); + + this.clear( renderContext.clearColor, renderContext.clearDepth, renderContext.clearStencil, renderContext, false ); + + // + if ( renderContext.viewport ) { + + this.updateViewport( renderContext ); + + } else { + + gl.viewport( 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight ); + + } + + if ( renderContext.scissor ) { + + const { x, y, width, height } = renderContext.scissorValue; + + gl.scissor( x, renderContext.height - height - y, width, height ); + + } + + const occlusionQueryCount = renderContext.occlusionQueryCount; + + if ( occlusionQueryCount > 0 ) { + + // Get a reference to the array of objects with queries. The renderContextData property + // can be changed by another render pass before the async reading of all previous queries complete + renderContextData.currentOcclusionQueries = renderContextData.occlusionQueries; + renderContextData.currentOcclusionQueryObjects = renderContextData.occlusionQueryObjects; + + renderContextData.lastOcclusionObject = null; + renderContextData.occlusionQueries = new Array( occlusionQueryCount ); + renderContextData.occlusionQueryObjects = new Array( occlusionQueryCount ); + renderContextData.occlusionQueryIndex = 0; + + } + + } + + finishRender( renderContext ) { + + const { gl, state } = this; + const renderContextData = this.get( renderContext ); + const previousContext = renderContextData.previousContext; + + const occlusionQueryCount = renderContext.occlusionQueryCount; + + if ( occlusionQueryCount > 0 ) { + + if ( occlusionQueryCount > renderContextData.occlusionQueryIndex ) { + + gl.endQuery( gl.ANY_SAMPLES_PASSED ); + + } + + this.resolveOccludedAsync( renderContext ); + + } + + const textures = renderContext.textures; + + if ( textures !== null ) { + + for ( let i = 0; i < textures.length; i ++ ) { + + const texture = textures[ i ]; + + if ( texture.generateMipmaps ) { + + this.generateMipmaps( texture ); + + } + + } + + } + + this._currentContext = previousContext; + + if ( renderContext.textures !== null && renderContext.renderTarget ) { + + const renderTargetContextData = this.get( renderContext.renderTarget ); + + const { samples } = renderContext.renderTarget; + + if ( samples > 0 ) { + + const fb = renderTargetContextData.framebuffers[ renderContext.getCacheKey() ]; + + const mask = gl.COLOR_BUFFER_BIT; + + const msaaFrameBuffer = renderTargetContextData.msaaFrameBuffer; + + const textures = renderContext.textures; + + state.bindFramebuffer( gl.READ_FRAMEBUFFER, msaaFrameBuffer ); + state.bindFramebuffer( gl.DRAW_FRAMEBUFFER, fb ); + + for ( let i = 0; i < textures.length; i ++ ) { + + // TODO Add support for MRT + + if ( renderContext.scissor ) { + + const { x, y, width, height } = renderContext.scissorValue; + + const viewY = renderContext.height - height - y; + + gl.blitFramebuffer( x, viewY, x + width, viewY + height, x, viewY, x + width, viewY + height, mask, gl.NEAREST ); + gl.invalidateSubFramebuffer( gl.READ_FRAMEBUFFER, renderTargetContextData.invalidationArray, x, viewY, width, height ); + + } else { + + gl.blitFramebuffer( 0, 0, renderContext.width, renderContext.height, 0, 0, renderContext.width, renderContext.height, mask, gl.NEAREST ); + gl.invalidateFramebuffer( gl.READ_FRAMEBUFFER, renderTargetContextData.invalidationArray ); + + } + + } + + } + + + } + + if ( previousContext !== null ) { + + this._setFramebuffer( previousContext ); + + if ( previousContext.viewport ) { + + this.updateViewport( previousContext ); + + } else { + + gl.viewport( 0, 0, gl.drawingBufferWidth, gl.drawingBufferHeight ); + + } + + } + + this.prepareTimestampBuffer( renderContext ); + + } + + resolveOccludedAsync( renderContext ) { + + const renderContextData = this.get( renderContext ); + + // handle occlusion query results + + const { currentOcclusionQueries, currentOcclusionQueryObjects } = renderContextData; + + if ( currentOcclusionQueries && currentOcclusionQueryObjects ) { + + const occluded = new WeakSet(); + const { gl } = this; + + renderContextData.currentOcclusionQueryObjects = null; + renderContextData.currentOcclusionQueries = null; + + const check = () => { + + let completed = 0; + + // check all queries and requeue as appropriate + for ( let i = 0; i < currentOcclusionQueries.length; i ++ ) { + + const query = currentOcclusionQueries[ i ]; + + if ( query === null ) continue; + + if ( gl.getQueryParameter( query, gl.QUERY_RESULT_AVAILABLE ) ) { + + if ( gl.getQueryParameter( query, gl.QUERY_RESULT ) > 0 ) occluded.add( currentOcclusionQueryObjects[ i ] ); + + currentOcclusionQueries[ i ] = null; + gl.deleteQuery( query ); + + completed ++; + + } + + } + + if ( completed < currentOcclusionQueries.length ) { + + requestAnimationFrame( check ); + + } else { + + renderContextData.occluded = occluded; + + } + + }; + + check(); + + } + + } + + isOccluded( renderContext, object ) { + + const renderContextData = this.get( renderContext ); + + return renderContextData.occluded && renderContextData.occluded.has( object ); + + } + + updateViewport( renderContext ) { + + const gl = this.gl; + const { x, y, width, height } = renderContext.viewportValue; + + gl.viewport( x, renderContext.height - height - y, width, height ); + + } + + setScissorTest( boolean ) { + + const gl = this.gl; + + if ( boolean ) { + + gl.enable( gl.SCISSOR_TEST ); + + } else { + + gl.disable( gl.SCISSOR_TEST ); + + } + + } + + clear( color, depth, stencil, descriptor = null, setFrameBuffer = true ) { + + const { gl } = this; + + if ( descriptor === null ) { + + descriptor = { + textures: null, + clearColorValue: this.getClearColor() + }; + + } + + // + + let clear = 0; + + if ( color ) clear |= gl.COLOR_BUFFER_BIT; + if ( depth ) clear |= gl.DEPTH_BUFFER_BIT; + if ( stencil ) clear |= gl.STENCIL_BUFFER_BIT; + + if ( clear !== 0 ) { + + const clearColor = descriptor.clearColorValue || this.getClearColor(); + + // premultiply alpha + + clearColor.r *= clearColor.a; + clearColor.g *= clearColor.a; + clearColor.b *= clearColor.a; + + if ( depth ) this.state.setDepthMask( true ); + + if ( descriptor.textures === null ) { + + gl.clearColor( clearColor.r, clearColor.g, clearColor.b, clearColor.a ); + gl.clear( clear ); + + } else { + + if ( setFrameBuffer ) this._setFramebuffer( descriptor ); + + if ( color ) { + + for ( let i = 0; i < descriptor.textures.length; i ++ ) { + + gl.clearBufferfv( gl.COLOR, i, [ clearColor.r, clearColor.g, clearColor.b, clearColor.a ] ); + + } + + } + + if ( depth && stencil ) { + + gl.clearBufferfi( gl.DEPTH_STENCIL, 0, 1, 0 ); + + } else if ( depth ) { + + gl.clearBufferfv( gl.DEPTH, 0, [ 1.0 ] ); + + } else if ( stencil ) { + + gl.clearBufferiv( gl.STENCIL, 0, [ 0 ] ); + + } + + } + + } + + } + + beginCompute( computeGroup ) { + + const { state, gl } = this; + + state.bindFramebuffer( gl.FRAMEBUFFER, null ); + this.initTimestampQuery( computeGroup ); + + } + + compute( computeGroup, computeNode, bindings, pipeline ) { + + const { state, gl } = this; + + if ( ! this.discard ) { + + // required here to handle async behaviour of render.compute() + gl.enable( gl.RASTERIZER_DISCARD ); + this.discard = true; + + } + + const { programGPU, transformBuffers, attributes } = this.get( pipeline ); + + const vaoKey = this._getVaoKey( null, attributes ); + + const vaoGPU = this.vaoCache[ vaoKey ]; + + if ( vaoGPU === undefined ) { + + this._createVao( null, attributes ); + + } else { + + gl.bindVertexArray( vaoGPU ); + + } + + state.useProgram( programGPU ); + + this._bindUniforms( bindings ); + + const transformFeedbackGPU = this._getTransformFeedback( transformBuffers ); + + gl.bindTransformFeedback( gl.TRANSFORM_FEEDBACK, transformFeedbackGPU ); + gl.beginTransformFeedback( gl.POINTS ); + + if ( attributes[ 0 ].isStorageInstancedBufferAttribute ) { + + gl.drawArraysInstanced( gl.POINTS, 0, 1, computeNode.count ); + + } else { + + gl.drawArrays( gl.POINTS, 0, computeNode.count ); + + } + + gl.endTransformFeedback(); + gl.bindTransformFeedback( gl.TRANSFORM_FEEDBACK, null ); + + // switch active buffers + + for ( let i = 0; i < transformBuffers.length; i ++ ) { + + const dualAttributeData = transformBuffers[ i ]; + + if ( dualAttributeData.pbo ) { + + this.textureUtils.copyBufferToTexture( dualAttributeData.transformBuffer, dualAttributeData.pbo ); + + } + + dualAttributeData.switchBuffers(); + + + } + + } + + finishCompute( computeGroup ) { + + const gl = this.gl; + + this.discard = false; + + gl.disable( gl.RASTERIZER_DISCARD ); + + this.prepareTimestampBuffer( computeGroup ); + + } + + draw( renderObject/*, info*/ ) { + + const { object, pipeline, material, context } = renderObject; + const { programGPU } = this.get( pipeline ); + + const { gl, state } = this; + + const contextData = this.get( context ); + + const drawParms = renderObject.getDrawParameters(); + + if ( drawParms === null ) return; + + // + + this._bindUniforms( renderObject.getBindings() ); + + const frontFaceCW = ( object.isMesh && object.matrixWorld.determinant() < 0 ); + + state.setMaterial( material, frontFaceCW ); + + state.useProgram( programGPU ); + + // + + let vaoGPU = renderObject.staticVao; + + if ( vaoGPU === undefined ) { + + const vaoKey = this._getVaoKey( renderObject.getIndex(), renderObject.getAttributes() ); + + vaoGPU = this.vaoCache[ vaoKey ]; + + if ( vaoGPU === undefined ) { + + let staticVao; + + ( { vaoGPU, staticVao } = this._createVao( renderObject.getIndex(), renderObject.getAttributes() ) ); + + if ( staticVao ) renderObject.staticVao = vaoGPU; + + } + + } + + gl.bindVertexArray( vaoGPU ); + + // + + const index = renderObject.getIndex(); + + // + + const lastObject = contextData.lastOcclusionObject; + + if ( lastObject !== object && lastObject !== undefined ) { + + if ( lastObject !== null && lastObject.occlusionTest === true ) { + + gl.endQuery( gl.ANY_SAMPLES_PASSED ); + + contextData.occlusionQueryIndex ++; + + } + + if ( object.occlusionTest === true ) { + + const query = gl.createQuery(); + + gl.beginQuery( gl.ANY_SAMPLES_PASSED, query ); + + contextData.occlusionQueries[ contextData.occlusionQueryIndex ] = query; + contextData.occlusionQueryObjects[ contextData.occlusionQueryIndex ] = object; + + } + + contextData.lastOcclusionObject = object; + + } + + // + const renderer = this.bufferRenderer; + + if ( object.isPoints ) renderer.mode = gl.POINTS; + else if ( object.isLineSegments ) renderer.mode = gl.LINES; + else if ( object.isLine ) renderer.mode = gl.LINE_STRIP; + else if ( object.isLineLoop ) renderer.mode = gl.LINE_LOOP; + else { + + if ( material.wireframe === true ) { + + state.setLineWidth( material.wireframeLinewidth * this.renderer.getPixelRatio() ); + renderer.mode = gl.LINES; + + } else { + + renderer.mode = gl.TRIANGLES; + + } + + } + + // + + const { vertexCount, instanceCount } = drawParms; + let { firstVertex } = drawParms; + + renderer.object = object; + + if ( index !== null ) { + + firstVertex *= index.array.BYTES_PER_ELEMENT; + + const indexData = this.get( index ); + + renderer.index = index.count; + renderer.type = indexData.type; + + } else { + + renderer.index = 0; + + } + + if ( object.isBatchedMesh ) { + + if ( object._multiDrawInstances !== null ) { + + renderer.renderMultiDrawInstances( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount, object._multiDrawInstances ); + + } else if ( ! this.hasFeature( 'WEBGL_multi_draw' ) ) { + + warnOnce( 'THREE.WebGLRenderer: WEBGL_multi_draw not supported.' ); + + } else { + + renderer.renderMultiDraw( object._multiDrawStarts, object._multiDrawCounts, object._multiDrawCount ); + + } + + } else if ( instanceCount > 1 ) { + + renderer.renderInstances( firstVertex, vertexCount, instanceCount ); + + } else { + + renderer.render( firstVertex, vertexCount ); + + } + // + + gl.bindVertexArray( null ); + + } + + needsRenderUpdate( /*renderObject*/ ) { + + return false; + + } + + getRenderCacheKey( /*renderObject*/ ) { + + return ''; + + } + + // textures + + createDefaultTexture( texture ) { + + this.textureUtils.createDefaultTexture( texture ); + + } + + createTexture( texture, options ) { + + this.textureUtils.createTexture( texture, options ); + + } + + updateTexture( texture, options ) { + + this.textureUtils.updateTexture( texture, options ); + + } + + generateMipmaps( texture ) { + + this.textureUtils.generateMipmaps( texture ); + + } + + + destroyTexture( texture ) { + + this.textureUtils.destroyTexture( texture ); + + } + + copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { + + return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height, faceIndex ); + + } + + createSampler( /*texture*/ ) { + + //console.warn( 'Abstract class.' ); + + } + + destroySampler() {} + + // node builder + + createNodeBuilder( object, renderer ) { + + return new GLSLNodeBuilder( object, renderer ); + + } + + // program + + createProgram( program ) { + + const gl = this.gl; + const { stage, code } = program; + + const shader = stage === 'fragment' ? gl.createShader( gl.FRAGMENT_SHADER ) : gl.createShader( gl.VERTEX_SHADER ); + + gl.shaderSource( shader, code ); + gl.compileShader( shader ); + + this.set( program, { + shaderGPU: shader + } ); + + } + + destroyProgram( /*program*/ ) { + + console.warn( 'Abstract class.' ); + + } + + createRenderPipeline( renderObject, promises ) { + + const gl = this.gl; + const pipeline = renderObject.pipeline; + + // Program + + const { fragmentProgram, vertexProgram } = pipeline; + + const programGPU = gl.createProgram(); + + const fragmentShader = this.get( fragmentProgram ).shaderGPU; + const vertexShader = this.get( vertexProgram ).shaderGPU; + + gl.attachShader( programGPU, fragmentShader ); + gl.attachShader( programGPU, vertexShader ); + gl.linkProgram( programGPU ); + + this.set( pipeline, { + programGPU, + fragmentShader, + vertexShader + } ); + + if ( promises !== null && this.parallel ) { + + const p = new Promise( ( resolve /*, reject*/ ) => { + + const parallel = this.parallel; + const checkStatus = () => { + + if ( gl.getProgramParameter( programGPU, parallel.COMPLETION_STATUS_KHR ) ) { + + this._completeCompile( renderObject, pipeline ); + resolve(); + + } else { + + requestAnimationFrame( checkStatus ); + + } + + }; + + checkStatus(); + + } ); + + promises.push( p ); + + return; + + } + + this._completeCompile( renderObject, pipeline ); + + } + + _handleSource( string, errorLine ) { + + const lines = string.split( '\n' ); + const lines2 = []; + + const from = Math.max( errorLine - 6, 0 ); + const to = Math.min( errorLine + 6, lines.length ); + + for ( let i = from; i < to; i ++ ) { + + const line = i + 1; + lines2.push( `${line === errorLine ? '>' : ' '} ${line}: ${lines[ i ]}` ); + + } + + return lines2.join( '\n' ); + + } + + _getShaderErrors( gl, shader, type ) { + + const status = gl.getShaderParameter( shader, gl.COMPILE_STATUS ); + const errors = gl.getShaderInfoLog( shader ).trim(); + + if ( status && errors === '' ) return ''; + + const errorMatches = /ERROR: 0:(\d+)/.exec( errors ); + if ( errorMatches ) { + + const errorLine = parseInt( errorMatches[ 1 ] ); + return type.toUpperCase() + '\n\n' + errors + '\n\n' + this._handleSource( gl.getShaderSource( shader ), errorLine ); + + } else { + + return errors; + + } + + } + + _logProgramError( programGPU, glFragmentShader, glVertexShader ) { + + if ( this.renderer.debug.checkShaderErrors ) { + + const gl = this.gl; + + const programLog = gl.getProgramInfoLog( programGPU ).trim(); + + if ( gl.getProgramParameter( programGPU, gl.LINK_STATUS ) === false ) { + + + if ( typeof this.renderer.debug.onShaderError === 'function' ) { + + this.renderer.debug.onShaderError( gl, programGPU, glVertexShader, glFragmentShader ); + + } else { + + // default error reporting + + const vertexErrors = this._getShaderErrors( gl, glVertexShader, 'vertex' ); + const fragmentErrors = this._getShaderErrors( gl, glFragmentShader, 'fragment' ); + + console.error( + 'THREE.WebGLProgram: Shader Error ' + gl.getError() + ' - ' + + 'VALIDATE_STATUS ' + gl.getProgramParameter( programGPU, gl.VALIDATE_STATUS ) + '\n\n' + + 'Program Info Log: ' + programLog + '\n' + + vertexErrors + '\n' + + fragmentErrors + ); + + } + + } else if ( programLog !== '' ) { + + console.warn( 'THREE.WebGLProgram: Program Info Log:', programLog ); + + } + + } + + } + + _completeCompile( renderObject, pipeline ) { + + const { state, gl } = this; + const pipelineData = this.get( pipeline ); + const { programGPU, fragmentShader, vertexShader } = pipelineData; + + if ( gl.getProgramParameter( programGPU, gl.LINK_STATUS ) === false ) { + + this._logProgramError( programGPU, fragmentShader, vertexShader ); + + } + + state.useProgram( programGPU ); + + // Bindings + + const bindings = renderObject.getBindings(); + + this._setupBindings( bindings, programGPU ); + + // + + this.set( pipeline, { + programGPU + } ); + + } + + createComputePipeline( computePipeline, bindings ) { + + const { state, gl } = this; + + // Program + + const fragmentProgram = { + stage: 'fragment', + code: '#version 300 es\nprecision highp float;\nvoid main() {}' + }; + + this.createProgram( fragmentProgram ); + + const { computeProgram } = computePipeline; + + const programGPU = gl.createProgram(); + + const fragmentShader = this.get( fragmentProgram ).shaderGPU; + const vertexShader = this.get( computeProgram ).shaderGPU; + + const transforms = computeProgram.transforms; + + const transformVaryingNames = []; + const transformAttributeNodes = []; + + for ( let i = 0; i < transforms.length; i ++ ) { + + const transform = transforms[ i ]; + + transformVaryingNames.push( transform.varyingName ); + transformAttributeNodes.push( transform.attributeNode ); + + } + + gl.attachShader( programGPU, fragmentShader ); + gl.attachShader( programGPU, vertexShader ); + + gl.transformFeedbackVaryings( + programGPU, + transformVaryingNames, + gl.SEPARATE_ATTRIBS + ); + + gl.linkProgram( programGPU ); + + if ( gl.getProgramParameter( programGPU, gl.LINK_STATUS ) === false ) { + + this._logProgramError( programGPU, fragmentShader, vertexShader ); + + + } + + state.useProgram( programGPU ); + + // Bindings + + this.createBindings( null, bindings ); + + this._setupBindings( bindings, programGPU ); + + const attributeNodes = computeProgram.attributes; + const attributes = []; + const transformBuffers = []; + + for ( let i = 0; i < attributeNodes.length; i ++ ) { + + const attribute = attributeNodes[ i ].node.attribute; + + attributes.push( attribute ); + + if ( ! this.has( attribute ) ) this.attributeUtils.createAttribute( attribute, gl.ARRAY_BUFFER ); + + } + + for ( let i = 0; i < transformAttributeNodes.length; i ++ ) { + + const attribute = transformAttributeNodes[ i ].attribute; + + if ( ! this.has( attribute ) ) this.attributeUtils.createAttribute( attribute, gl.ARRAY_BUFFER ); + + const attributeData = this.get( attribute ); + + transformBuffers.push( attributeData ); + + } + + // + + this.set( computePipeline, { + programGPU, + transformBuffers, + attributes + } ); + + } + + createBindings( bindGroup, bindings ) { + + this.updateBindings( bindGroup, bindings ); + + } + + updateBindings( bindGroup, bindings ) { + + if ( ! bindGroup ) return; + + const { gl } = this; + + const bindingsData = this.get( bindings ); + const bindGroupData = this.get( bindGroup ); + + if ( bindingsData.textureIndex === undefined ) bindingsData.textureIndex = 0; + + if ( bindGroupData.textureIndex === undefined ) { + + bindGroupData.textureIndex = bindingsData.textureIndex; + + } else { + + // reset textureIndex to match previous mappimgs when rebuilt + bindingsData.textureIndex = bindGroupData.textureIndex; + + } + + let i = 0; + + for ( const binding of bindGroup.bindings ) { + + if ( binding.isUniformsGroup || binding.isUniformBuffer ) { + + const data = binding.buffer; + const bufferGPU = gl.createBuffer(); + + gl.bindBuffer( gl.UNIFORM_BUFFER, bufferGPU ); + gl.bufferData( gl.UNIFORM_BUFFER, data, gl.DYNAMIC_DRAW ); + + this.set( binding, { + index: bindGroup.index * 2 + i ++, + bufferGPU + } ); + + } else if ( binding.isSampledTexture ) { + + const { textureGPU, glTextureType } = this.get( binding.texture ); + + this.set( binding, { + index: bindingsData.textureIndex ++, + textureGPU, + glTextureType + } ); + + } + + } + + } + + updateBinding( binding ) { + + const gl = this.gl; + + if ( binding.isUniformsGroup || binding.isUniformBuffer ) { + + const bindingData = this.get( binding ); + const bufferGPU = bindingData.bufferGPU; + const data = binding.buffer; + + gl.bindBuffer( gl.UNIFORM_BUFFER, bufferGPU ); + gl.bufferData( gl.UNIFORM_BUFFER, data, gl.DYNAMIC_DRAW ); + + } + + } + + // attributes + + createIndexAttribute( attribute ) { + + const gl = this.gl; + + this.attributeUtils.createAttribute( attribute, gl.ELEMENT_ARRAY_BUFFER ); + + } + + createAttribute( attribute ) { + + if ( this.has( attribute ) ) return; + + const gl = this.gl; + + this.attributeUtils.createAttribute( attribute, gl.ARRAY_BUFFER ); + + } + + createStorageAttribute( attribute ) { + + if ( this.has( attribute ) ) return; + + const gl = this.gl; + + this.attributeUtils.createAttribute( attribute, gl.ARRAY_BUFFER ); + + } + + updateAttribute( attribute ) { + + this.attributeUtils.updateAttribute( attribute ); + + } + + destroyAttribute( attribute ) { + + this.attributeUtils.destroyAttribute( attribute ); + + } + + updateSize() { + + //console.warn( 'Abstract class.' ); + + } + + hasFeature( name ) { + + const keysMatching = Object.keys( GLFeatureName ).filter( key => GLFeatureName[ key ] === name ); + + const extensions = this.extensions; + + for ( let i = 0; i < keysMatching.length; i ++ ) { + + if ( extensions.has( keysMatching[ i ] ) ) return true; + + } + + return false; + + } + + getMaxAnisotropy() { + + return this.capabilities.getMaxAnisotropy(); + + } + + copyTextureToTexture( position, srcTexture, dstTexture, level ) { + + this.textureUtils.copyTextureToTexture( position, srcTexture, dstTexture, level ); + + } + + copyFramebufferToTexture( texture, renderContext, rectangle ) { + + this.textureUtils.copyFramebufferToTexture( texture, renderContext, rectangle ); + + } + + _setFramebuffer( descriptor ) { + + const { gl, state } = this; + + let currentFrameBuffer = null; + + if ( descriptor.textures !== null ) { + + const renderTarget = descriptor.renderTarget; + const renderTargetContextData = this.get( renderTarget ); + const { samples, depthBuffer, stencilBuffer } = renderTarget; + + const isCube = renderTarget.isWebGLCubeRenderTarget === true; + + let msaaFb = renderTargetContextData.msaaFrameBuffer; + let depthRenderbuffer = renderTargetContextData.depthRenderbuffer; + + const cacheKey = getCacheKey( descriptor ); + + let fb; + + if ( isCube ) { + + renderTargetContextData.cubeFramebuffers || ( renderTargetContextData.cubeFramebuffers = {} ); + + fb = renderTargetContextData.cubeFramebuffers[ cacheKey ]; + + } else { + + renderTargetContextData.framebuffers || ( renderTargetContextData.framebuffers = {} ); + + fb = renderTargetContextData.framebuffers[ cacheKey ]; + + } + + if ( fb === undefined ) { + + fb = gl.createFramebuffer(); + + state.bindFramebuffer( gl.FRAMEBUFFER, fb ); + + const textures = descriptor.textures; + + if ( isCube ) { + + renderTargetContextData.cubeFramebuffers[ cacheKey ] = fb; + + const { textureGPU } = this.get( textures[ 0 ] ); + + const cubeFace = this.renderer._activeCubeFace; + + gl.framebufferTexture2D( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_CUBE_MAP_POSITIVE_X + cubeFace, textureGPU, 0 ); + + } else { + + renderTargetContextData.framebuffers[ cacheKey ] = fb; + + for ( let i = 0; i < textures.length; i ++ ) { + + const texture = textures[ i ]; + const textureData = this.get( texture ); + textureData.renderTarget = descriptor.renderTarget; + + const attachment = gl.COLOR_ATTACHMENT0 + i; + + gl.framebufferTexture2D( gl.FRAMEBUFFER, attachment, gl.TEXTURE_2D, textureData.textureGPU, 0 ); + + } + + state.drawBuffers( descriptor, fb ); + + } + + if ( descriptor.depthTexture !== null ) { + + const textureData = this.get( descriptor.depthTexture ); + const depthStyle = stencilBuffer ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT; + + gl.framebufferTexture2D( gl.FRAMEBUFFER, depthStyle, gl.TEXTURE_2D, textureData.textureGPU, 0 ); + + } + + } + + if ( samples > 0 ) { + + if ( msaaFb === undefined ) { + + const invalidationArray = []; + + msaaFb = gl.createFramebuffer(); + + state.bindFramebuffer( gl.FRAMEBUFFER, msaaFb ); + + const msaaRenderbuffers = []; + + const textures = descriptor.textures; + + for ( let i = 0; i < textures.length; i ++ ) { + + msaaRenderbuffers[ i ] = gl.createRenderbuffer(); + + gl.bindRenderbuffer( gl.RENDERBUFFER, msaaRenderbuffers[ i ] ); + + invalidationArray.push( gl.COLOR_ATTACHMENT0 + i ); + + if ( depthBuffer ) { + + const depthStyle = stencilBuffer ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT; + invalidationArray.push( depthStyle ); + + } + + const texture = descriptor.textures[ i ]; + const textureData = this.get( texture ); + + gl.renderbufferStorageMultisample( gl.RENDERBUFFER, samples, textureData.glInternalFormat, descriptor.width, descriptor.height ); + gl.framebufferRenderbuffer( gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0 + i, gl.RENDERBUFFER, msaaRenderbuffers[ i ] ); + + + } + + renderTargetContextData.msaaFrameBuffer = msaaFb; + renderTargetContextData.msaaRenderbuffers = msaaRenderbuffers; + + if ( depthRenderbuffer === undefined ) { + + depthRenderbuffer = gl.createRenderbuffer(); + this.textureUtils.setupRenderBufferStorage( depthRenderbuffer, descriptor ); + + renderTargetContextData.depthRenderbuffer = depthRenderbuffer; + + const depthStyle = stencilBuffer ? gl.DEPTH_STENCIL_ATTACHMENT : gl.DEPTH_ATTACHMENT; + invalidationArray.push( depthStyle ); + + } + + renderTargetContextData.invalidationArray = invalidationArray; + + } + + currentFrameBuffer = renderTargetContextData.msaaFrameBuffer; + + } else { + + currentFrameBuffer = fb; + + } + + } + + state.bindFramebuffer( gl.FRAMEBUFFER, currentFrameBuffer ); + + } + + + _getVaoKey( index, attributes ) { + + let key = []; + + if ( index !== null ) { + + const indexData = this.get( index ); + + key += ':' + indexData.id; + + } + + for ( let i = 0; i < attributes.length; i ++ ) { + + const attributeData = this.get( attributes[ i ] ); + + key += ':' + attributeData.id; + + } + + return key; + + } + + _createVao( index, attributes ) { + + const { gl } = this; + + const vaoGPU = gl.createVertexArray(); + let key = ''; + + let staticVao = true; + + gl.bindVertexArray( vaoGPU ); + + if ( index !== null ) { + + const indexData = this.get( index ); + + gl.bindBuffer( gl.ELEMENT_ARRAY_BUFFER, indexData.bufferGPU ); + + key += ':' + indexData.id; + + } + + for ( let i = 0; i < attributes.length; i ++ ) { + + const attribute = attributes[ i ]; + const attributeData = this.get( attribute ); + + key += ':' + attributeData.id; + + gl.bindBuffer( gl.ARRAY_BUFFER, attributeData.bufferGPU ); + gl.enableVertexAttribArray( i ); + + if ( attribute.isStorageBufferAttribute || attribute.isStorageInstancedBufferAttribute ) staticVao = false; + + let stride, offset; + + if ( attribute.isInterleavedBufferAttribute === true ) { + + stride = attribute.data.stride * attributeData.bytesPerElement; + offset = attribute.offset * attributeData.bytesPerElement; + + } else { + + stride = 0; + offset = 0; + + } + + if ( attributeData.isInteger ) { + + gl.vertexAttribIPointer( i, attribute.itemSize, attributeData.type, stride, offset ); + + } else { + + gl.vertexAttribPointer( i, attribute.itemSize, attributeData.type, attribute.normalized, stride, offset ); + + } + + if ( attribute.isInstancedBufferAttribute && ! attribute.isInterleavedBufferAttribute ) { + + gl.vertexAttribDivisor( i, attribute.meshPerAttribute ); + + } else if ( attribute.isInterleavedBufferAttribute && attribute.data.isInstancedInterleavedBuffer ) { + + gl.vertexAttribDivisor( i, attribute.data.meshPerAttribute ); + + } + + } + + gl.bindBuffer( gl.ARRAY_BUFFER, null ); + + this.vaoCache[ key ] = vaoGPU; + + return { vaoGPU, staticVao }; + + } + + _getTransformFeedback( transformBuffers ) { + + let key = ''; + + for ( let i = 0; i < transformBuffers.length; i ++ ) { + + key += ':' + transformBuffers[ i ].id; + + } + + let transformFeedbackGPU = this.transformFeedbackCache[ key ]; + + if ( transformFeedbackGPU !== undefined ) { + + return transformFeedbackGPU; + + } + + const { gl } = this; + + transformFeedbackGPU = gl.createTransformFeedback(); + + gl.bindTransformFeedback( gl.TRANSFORM_FEEDBACK, transformFeedbackGPU ); + + for ( let i = 0; i < transformBuffers.length; i ++ ) { + + const attributeData = transformBuffers[ i ]; + + gl.bindBufferBase( gl.TRANSFORM_FEEDBACK_BUFFER, i, attributeData.transformBuffer ); + + } + + gl.bindTransformFeedback( gl.TRANSFORM_FEEDBACK, null ); + + this.transformFeedbackCache[ key ] = transformFeedbackGPU; + + return transformFeedbackGPU; + + } + + + _setupBindings( bindings, programGPU ) { + + const gl = this.gl; + + for ( const bindGroup of bindings ) { + + for ( const binding of bindGroup.bindings ) { + + const bindingData = this.get( binding ); + const index = bindingData.index; + + if ( binding.isUniformsGroup || binding.isUniformBuffer ) { + + const location = gl.getUniformBlockIndex( programGPU, binding.name ); + gl.uniformBlockBinding( programGPU, location, index ); + + } else if ( binding.isSampledTexture ) { + + const location = gl.getUniformLocation( programGPU, binding.name ); + gl.uniform1i( location, index ); + + } + + } + + } + + } + + _bindUniforms( bindings ) { + + const { gl, state } = this; + + for ( const bindGroup of bindings ) { + + for ( const binding of bindGroup.bindings ) { + + const bindingData = this.get( binding ); + const index = bindingData.index; + + if ( binding.isUniformsGroup || binding.isUniformBuffer ) { + + // TODO USE bindBufferRange to group multiple uniform buffers + state.bindBufferBase( gl.UNIFORM_BUFFER, index, bindingData.bufferGPU ); + + } else if ( binding.isSampledTexture ) { + + state.bindTexture( bindingData.glTextureType, bindingData.textureGPU, gl.TEXTURE0 + index ); + + } + + } + + } + + } + +} + +class Sampler extends Binding { + + constructor( name, texture ) { + + super( name ); + + this.texture = texture; + this.version = texture ? texture.version : 0; + + this.isSampler = true; + + } + +} + +class NodeSampler extends Sampler { + + constructor( name, textureNode, groupNode ) { + + super( name, textureNode ? textureNode.value : null ); + + this.textureNode = textureNode; + this.groupNode = groupNode; + + } + + update() { + + this.texture = this.textureNode.value; + + } + +} + +class StorageBuffer extends Buffer { + + constructor( name, attribute ) { + + super( name, attribute ? attribute.array : null ); + + this.attribute = attribute; + + this.isStorageBuffer = true; + + } + +} + +let _id = 0; + +class NodeStorageBuffer extends StorageBuffer { + + constructor( nodeUniform, groupNode ) { + + super( 'StorageBuffer_' + _id ++, nodeUniform ? nodeUniform.value : null ); + + this.nodeUniform = nodeUniform; + this.access = nodeUniform ? nodeUniform.access : GPUBufferBindingType.Storage; + this.groupNode = groupNode; + + + } + + get buffer() { + + return this.nodeUniform.value; + + } + +} + +class WebGPUTexturePassUtils extends DataMap { + + constructor( device ) { + + super(); + + this.device = device; + + const mipmapVertexSource = ` +struct VarysStruct { + @builtin( position ) Position: vec4, + @location( 0 ) vTex : vec2 +}; + +@vertex +fn main( @builtin( vertex_index ) vertexIndex : u32 ) -> VarysStruct { + + var Varys : VarysStruct; + + var pos = array< vec2, 4 >( + vec2( -1.0, 1.0 ), + vec2( 1.0, 1.0 ), + vec2( -1.0, -1.0 ), + vec2( 1.0, -1.0 ) + ); + + var tex = array< vec2, 4 >( + vec2( 0.0, 0.0 ), + vec2( 1.0, 0.0 ), + vec2( 0.0, 1.0 ), + vec2( 1.0, 1.0 ) + ); + + Varys.vTex = tex[ vertexIndex ]; + Varys.Position = vec4( pos[ vertexIndex ], 0.0, 1.0 ); + + return Varys; + +} +`; + + const mipmapFragmentSource = ` +@group( 0 ) @binding( 0 ) +var imgSampler : sampler; + +@group( 0 ) @binding( 1 ) +var img : texture_2d; + +@fragment +fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { + + return textureSample( img, imgSampler, vTex ); + +} +`; + + const flipYFragmentSource = ` +@group( 0 ) @binding( 0 ) +var imgSampler : sampler; + +@group( 0 ) @binding( 1 ) +var img : texture_2d; + +@fragment +fn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 { + + return textureSample( img, imgSampler, vec2( vTex.x, 1.0 - vTex.y ) ); + +} +`; + this.mipmapSampler = device.createSampler( { minFilter: GPUFilterMode.Linear } ); + this.flipYSampler = device.createSampler( { minFilter: GPUFilterMode.Nearest } ); //@TODO?: Consider using textureLoad() + + // We'll need a new pipeline for every texture format used. + this.transferPipelines = {}; + this.flipYPipelines = {}; + + this.mipmapVertexShaderModule = device.createShaderModule( { + label: 'mipmapVertex', + code: mipmapVertexSource + } ); + + this.mipmapFragmentShaderModule = device.createShaderModule( { + label: 'mipmapFragment', + code: mipmapFragmentSource + } ); + + this.flipYFragmentShaderModule = device.createShaderModule( { + label: 'flipYFragment', + code: flipYFragmentSource + } ); + + } + + getTransferPipeline( format ) { + + let pipeline = this.transferPipelines[ format ]; + + if ( pipeline === undefined ) { + + pipeline = this.device.createRenderPipeline( { + label: `mipmap-${ format }`, + vertex: { + module: this.mipmapVertexShaderModule, + entryPoint: 'main' + }, + fragment: { + module: this.mipmapFragmentShaderModule, + entryPoint: 'main', + targets: [ { format } ] + }, + primitive: { + topology: GPUPrimitiveTopology.TriangleStrip, + stripIndexFormat: GPUIndexFormat.Uint32 + }, + layout: 'auto' + } ); + + this.transferPipelines[ format ] = pipeline; + + } + + return pipeline; + + } + + getFlipYPipeline( format ) { + + let pipeline = this.flipYPipelines[ format ]; + + if ( pipeline === undefined ) { + + pipeline = this.device.createRenderPipeline( { + label: `flipY-${ format }`, + vertex: { + module: this.mipmapVertexShaderModule, + entryPoint: 'main' + }, + fragment: { + module: this.flipYFragmentShaderModule, + entryPoint: 'main', + targets: [ { format } ] + }, + primitive: { + topology: GPUPrimitiveTopology.TriangleStrip, + stripIndexFormat: GPUIndexFormat.Uint32 + }, + layout: 'auto' + } ); + + this.flipYPipelines[ format ] = pipeline; + + } + + return pipeline; + + } + + flipY( textureGPU, textureGPUDescriptor, baseArrayLayer = 0 ) { + + const format = textureGPUDescriptor.format; + const { width, height } = textureGPUDescriptor.size; + + const transferPipeline = this.getTransferPipeline( format ); + const flipYPipeline = this.getFlipYPipeline( format ); + + const tempTexture = this.device.createTexture( { + size: { width, height, depthOrArrayLayers: 1 }, + format, + usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.TEXTURE_BINDING + } ); + + const srcView = textureGPU.createView( { + baseMipLevel: 0, + mipLevelCount: 1, + dimension: GPUTextureViewDimension.TwoD, + baseArrayLayer + } ); + + const dstView = tempTexture.createView( { + baseMipLevel: 0, + mipLevelCount: 1, + dimension: GPUTextureViewDimension.TwoD, + baseArrayLayer: 0 + } ); + + const commandEncoder = this.device.createCommandEncoder( {} ); + + const pass = ( pipeline, sourceView, destinationView ) => { + + const bindGroupLayout = pipeline.getBindGroupLayout( 0 ); // @TODO: Consider making this static. + + const bindGroup = this.device.createBindGroup( { + layout: bindGroupLayout, + entries: [ { + binding: 0, + resource: this.flipYSampler + }, { + binding: 1, + resource: sourceView + } ] + } ); + + const passEncoder = commandEncoder.beginRenderPass( { + colorAttachments: [ { + view: destinationView, + loadOp: GPULoadOp.Clear, + storeOp: GPUStoreOp.Store, + clearValue: [ 0, 0, 0, 0 ] + } ] + } ); + + passEncoder.setPipeline( pipeline ); + passEncoder.setBindGroup( 0, bindGroup ); + passEncoder.draw( 4, 1, 0, 0 ); + passEncoder.end(); + + }; + + pass( transferPipeline, srcView, dstView ); + pass( flipYPipeline, dstView, srcView ); + + this.device.queue.submit( [ commandEncoder.finish() ] ); + + tempTexture.destroy(); + + } + + generateMipmaps( textureGPU, textureGPUDescriptor, baseArrayLayer = 0 ) { + + const textureData = this.get( textureGPU ); + + if ( textureData.useCount === undefined ) { + + textureData.useCount = 0; + textureData.layers = []; + + } + + const passes = textureData.layers[ baseArrayLayer ] || this._mipmapCreateBundles( textureGPU, textureGPUDescriptor, baseArrayLayer ); + + const commandEncoder = this.device.createCommandEncoder( {} ); + + this._mipmapRunBundles( commandEncoder, passes ); + + this.device.queue.submit( [ commandEncoder.finish() ] ); + + if ( textureData.useCount !== 0 ) textureData.layers[ baseArrayLayer ] = passes; + + textureData.useCount ++; + + } + + _mipmapCreateBundles( textureGPU, textureGPUDescriptor, baseArrayLayer ) { + + const pipeline = this.getTransferPipeline( textureGPUDescriptor.format ); + + const bindGroupLayout = pipeline.getBindGroupLayout( 0 ); // @TODO: Consider making this static. + + let srcView = textureGPU.createView( { + baseMipLevel: 0, + mipLevelCount: 1, + dimension: GPUTextureViewDimension.TwoD, + baseArrayLayer + } ); + + const passes = []; + + for ( let i = 1; i < textureGPUDescriptor.mipLevelCount; i ++ ) { + + const bindGroup = this.device.createBindGroup( { + layout: bindGroupLayout, + entries: [ { + binding: 0, + resource: this.mipmapSampler + }, { + binding: 1, + resource: srcView + } ] + } ); + + const dstView = textureGPU.createView( { + baseMipLevel: i, + mipLevelCount: 1, + dimension: GPUTextureViewDimension.TwoD, + baseArrayLayer + } ); + + const passDescriptor = { + colorAttachments: [ { + view: dstView, + loadOp: GPULoadOp.Clear, + storeOp: GPUStoreOp.Store, + clearValue: [ 0, 0, 0, 0 ] + } ] + }; + + const passEncoder = this.device.createRenderBundleEncoder( { + colorFormats: [ textureGPUDescriptor.format ] + } ); + + passEncoder.setPipeline( pipeline ); + passEncoder.setBindGroup( 0, bindGroup ); + passEncoder.draw( 4, 1, 0, 0 ); + + passes.push( { + renderBundles: [ passEncoder.finish() ], + passDescriptor + } ); + + srcView = dstView; + + } + + return passes; + + } + + _mipmapRunBundles( commandEncoder, passes ) { + + const levels = passes.length; + + for ( let i = 0; i < levels; i ++ ) { + + const pass = passes[ i ]; + + const passEncoder = commandEncoder.beginRenderPass( pass.passDescriptor ); + + passEncoder.executeBundles( pass.renderBundles ); + + passEncoder.end(); + + } + + } + +} + +const _compareToWebGPU = { + [ NeverCompare ]: 'never', + [ LessCompare ]: 'less', + [ EqualCompare ]: 'equal', + [ LessEqualCompare ]: 'less-equal', + [ GreaterCompare ]: 'greater', + [ GreaterEqualCompare ]: 'greater-equal', + [ AlwaysCompare ]: 'always', + [ NotEqualCompare ]: 'not-equal' +}; + +const _flipMap = [ 0, 1, 3, 2, 4, 5 ]; + +class WebGPUTextureUtils { + + constructor( backend ) { + + this.backend = backend; + + this._passUtils = null; + + this.defaultTexture = {}; + this.defaultCubeTexture = {}; + this.defaultVideoFrame = null; + + this.colorBuffer = null; + + this.depthTexture = new DepthTexture(); + this.depthTexture.name = 'depthBuffer'; + + } + + createSampler( texture ) { + + const backend = this.backend; + const device = backend.device; + + const textureGPU = backend.get( texture ); + + const samplerDescriptorGPU = { + addressModeU: this._convertAddressMode( texture.wrapS ), + addressModeV: this._convertAddressMode( texture.wrapT ), + addressModeW: this._convertAddressMode( texture.wrapR ), + magFilter: this._convertFilterMode( texture.magFilter ), + minFilter: this._convertFilterMode( texture.minFilter ), + mipmapFilter: this._convertFilterMode( texture.minFilter ), + maxAnisotropy: texture.anisotropy + }; + + if ( texture.isDepthTexture && texture.compareFunction !== null ) { + + samplerDescriptorGPU.compare = _compareToWebGPU[ texture.compareFunction ]; + + } + + textureGPU.sampler = device.createSampler( samplerDescriptorGPU ); + + } + + createDefaultTexture( texture ) { + + let textureGPU; + + const format = getFormat( texture ); + + if ( texture.isCubeTexture ) { + + textureGPU = this._getDefaultCubeTextureGPU( format ); + + } else if ( texture.isVideoTexture ) { + + this.backend.get( texture ).externalTexture = this._getDefaultVideoFrame(); + + } else { + + textureGPU = this._getDefaultTextureGPU( format ); + + } + + this.backend.get( texture ).texture = textureGPU; + + } + + createTexture( texture, options = {} ) { + + const backend = this.backend; + const textureData = backend.get( texture ); + + if ( textureData.initialized ) { + + throw new Error( 'WebGPUTextureUtils: Texture already initialized.' ); + + } + + if ( options.needsMipmaps === undefined ) options.needsMipmaps = false; + if ( options.levels === undefined ) options.levels = 1; + if ( options.depth === undefined ) options.depth = 1; + + const { width, height, depth, levels } = options; + + const dimension = this._getDimension( texture ); + const format = texture.internalFormat || options.format || getFormat( texture, backend.device ); + + textureData.format = format; + + let sampleCount = options.sampleCount !== undefined ? options.sampleCount : 1; + + sampleCount = backend.utils.getSampleCount( sampleCount ); + + const primarySampleCount = texture.isRenderTargetTexture && ! texture.isMultisampleRenderTargetTexture ? 1 : sampleCount; + + let usage = GPUTextureUsage.TEXTURE_BINDING | GPUTextureUsage.COPY_DST | GPUTextureUsage.COPY_SRC; + + if ( texture.isStorageTexture === true ) { + + usage |= GPUTextureUsage.STORAGE_BINDING; + + } + + if ( texture.isCompressedTexture !== true && texture.isCompressedArrayTexture !== true ) { + + usage |= GPUTextureUsage.RENDER_ATTACHMENT; + + } + + const textureDescriptorGPU = { + label: texture.name, + size: { + width: width, + height: height, + depthOrArrayLayers: depth, + }, + mipLevelCount: levels, + sampleCount: primarySampleCount, + dimension: dimension, + format: format, + usage: usage + }; + + // texture creation + + if ( texture.isVideoTexture ) { + + const video = texture.source.data; + const videoFrame = new VideoFrame( video ); + + textureDescriptorGPU.size.width = videoFrame.displayWidth; + textureDescriptorGPU.size.height = videoFrame.displayHeight; + + videoFrame.close(); + + textureData.externalTexture = video; + + } else { + + if ( format === undefined ) { + + console.warn( 'WebGPURenderer: Texture format not supported.' ); + + return this.createDefaultTexture( texture ); + + } + + textureData.texture = backend.device.createTexture( textureDescriptorGPU ); + + } + + if ( texture.isRenderTargetTexture && sampleCount > 1 && ! texture.isMultisampleRenderTargetTexture ) { + + const msaaTextureDescriptorGPU = Object.assign( {}, textureDescriptorGPU ); + + msaaTextureDescriptorGPU.label = msaaTextureDescriptorGPU.label + '-msaa'; + msaaTextureDescriptorGPU.sampleCount = sampleCount; + + textureData.msaaTexture = backend.device.createTexture( msaaTextureDescriptorGPU ); + + } + + textureData.initialized = true; + + textureData.textureDescriptorGPU = textureDescriptorGPU; + + } + + destroyTexture( texture ) { + + const backend = this.backend; + const textureData = backend.get( texture ); + + textureData.texture.destroy(); + + if ( textureData.msaaTexture !== undefined ) textureData.msaaTexture.destroy(); + + backend.delete( texture ); + + } + + destroySampler( texture ) { + + const backend = this.backend; + const textureData = backend.get( texture ); + + delete textureData.sampler; + + } + + generateMipmaps( texture ) { + + const textureData = this.backend.get( texture ); + + if ( texture.isCubeTexture ) { + + for ( let i = 0; i < 6; i ++ ) { + + this._generateMipmaps( textureData.texture, textureData.textureDescriptorGPU, i ); + + } + + } else { + + const depth = texture.image.depth || 1; + + for ( let i = 0; i < depth; i ++ ) { + + this._generateMipmaps( textureData.texture, textureData.textureDescriptorGPU, i ); + + } + + } + + } + + getColorBuffer() { + + if ( this.colorBuffer ) this.colorBuffer.destroy(); + + const backend = this.backend; + const { width, height } = backend.getDrawingBufferSize(); + + this.colorBuffer = backend.device.createTexture( { + label: 'colorBuffer', + size: { + width: width, + height: height, + depthOrArrayLayers: 1 + }, + sampleCount: backend.utils.getSampleCount( backend.renderer.samples ), + format: backend.utils.getPreferredCanvasFormat(), + usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC + } ); + + return this.colorBuffer; + + } + + getDepthBuffer( depth = true, stencil = false ) { + + const backend = this.backend; + const { width, height } = backend.getDrawingBufferSize(); + + const depthTexture = this.depthTexture; + const depthTextureGPU = backend.get( depthTexture ).texture; + + let format, type; + + if ( stencil ) { + + format = DepthStencilFormat; + type = UnsignedInt248Type; + + } else if ( depth ) { + + format = DepthFormat; + type = UnsignedIntType; + + } + + if ( depthTextureGPU !== undefined ) { + + if ( depthTexture.image.width === width && depthTexture.image.height === height && depthTexture.format === format && depthTexture.type === type ) { + + return depthTextureGPU; + + } + + this.destroyTexture( depthTexture ); + + } + + depthTexture.name = 'depthBuffer'; + depthTexture.format = format; + depthTexture.type = type; + depthTexture.image.width = width; + depthTexture.image.height = height; + + this.createTexture( depthTexture, { sampleCount: backend.utils.getSampleCount( backend.renderer.samples ), width, height } ); + + return backend.get( depthTexture ).texture; + + } + + updateTexture( texture, options ) { + + const textureData = this.backend.get( texture ); + + const { textureDescriptorGPU } = textureData; + + if ( texture.isRenderTargetTexture || ( textureDescriptorGPU === undefined /* unsupported texture format */ ) ) + return; + + // transfer texture data + + if ( texture.isDataTexture ) { + + this._copyBufferToTexture( options.image, textureData.texture, textureDescriptorGPU, 0, texture.flipY ); + + } else if ( texture.isDataArrayTexture || texture.isData3DTexture ) { + + for ( let i = 0; i < options.image.depth; i ++ ) { + + this._copyBufferToTexture( options.image, textureData.texture, textureDescriptorGPU, i, texture.flipY, i ); + + } + + } else if ( texture.isCompressedTexture || texture.isCompressedArrayTexture ) { + + this._copyCompressedBufferToTexture( texture.mipmaps, textureData.texture, textureDescriptorGPU ); + + } else if ( texture.isCubeTexture ) { + + this._copyCubeMapToTexture( options.images, textureData.texture, textureDescriptorGPU, texture.flipY ); + + } else if ( texture.isVideoTexture ) { + + const video = texture.source.data; + + textureData.externalTexture = video; + + } else { + + this._copyImageToTexture( options.image, textureData.texture, textureDescriptorGPU, 0, texture.flipY ); + + } + + // + + textureData.version = texture.version; + + if ( texture.onUpdate ) texture.onUpdate( texture ); + + } + + async copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { + + const device = this.backend.device; + + const textureData = this.backend.get( texture ); + const textureGPU = textureData.texture; + const format = textureData.textureDescriptorGPU.format; + const bytesPerTexel = this._getBytesPerTexel( format ); + + let bytesPerRow = width * bytesPerTexel; + bytesPerRow = Math.ceil( bytesPerRow / 256 ) * 256; // Align to 256 bytes + + const readBuffer = device.createBuffer( + { + size: width * height * bytesPerTexel, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ + } + ); + + const encoder = device.createCommandEncoder(); + + encoder.copyTextureToBuffer( + { + texture: textureGPU, + origin: { x, y, z: faceIndex }, + }, + { + buffer: readBuffer, + bytesPerRow: bytesPerRow + }, + { + width: width, + height: height + } + + ); + + const typedArrayType = this._getTypedArrayType( format ); + + device.queue.submit( [ encoder.finish() ] ); + + await readBuffer.mapAsync( GPUMapMode.READ ); + + const buffer = readBuffer.getMappedRange(); + + return new typedArrayType( buffer ); + + } + + _isEnvironmentTexture( texture ) { + + const mapping = texture.mapping; + + return ( mapping === EquirectangularReflectionMapping || mapping === EquirectangularRefractionMapping ) || ( mapping === CubeReflectionMapping || mapping === CubeRefractionMapping ); + + } + + _getDefaultTextureGPU( format ) { + + let defaultTexture = this.defaultTexture[ format ]; + + if ( defaultTexture === undefined ) { + + const texture = new Texture(); + texture.minFilter = NearestFilter; + texture.magFilter = NearestFilter; + + this.createTexture( texture, { width: 1, height: 1, format } ); + + this.defaultTexture[ format ] = defaultTexture = texture; + + } + + return this.backend.get( defaultTexture ).texture; + + } + + _getDefaultCubeTextureGPU( format ) { + + let defaultCubeTexture = this.defaultTexture[ format ]; + + if ( defaultCubeTexture === undefined ) { + + const texture = new CubeTexture(); + texture.minFilter = NearestFilter; + texture.magFilter = NearestFilter; + + this.createTexture( texture, { width: 1, height: 1, depth: 6 } ); + + this.defaultCubeTexture[ format ] = defaultCubeTexture = texture; + + } + + return this.backend.get( defaultCubeTexture ).texture; + + } + + _getDefaultVideoFrame() { + + let defaultVideoFrame = this.defaultVideoFrame; + + if ( defaultVideoFrame === null ) { + + const init = { + timestamp: 0, + codedWidth: 1, + codedHeight: 1, + format: 'RGBA', + }; + + this.defaultVideoFrame = defaultVideoFrame = new VideoFrame( new Uint8Array( [ 0, 0, 0, 0xff ] ), init ); + + } + + return defaultVideoFrame; + + } + + _copyCubeMapToTexture( images, textureGPU, textureDescriptorGPU, flipY ) { + + for ( let i = 0; i < 6; i ++ ) { + + const image = images[ i ]; + + const flipIndex = flipY === true ? _flipMap[ i ] : i; + + if ( image.isDataTexture ) { + + this._copyBufferToTexture( image.image, textureGPU, textureDescriptorGPU, flipIndex, flipY ); + + } else { + + this._copyImageToTexture( image, textureGPU, textureDescriptorGPU, flipIndex, flipY ); + + } + + } + + } + + _copyImageToTexture( image, textureGPU, textureDescriptorGPU, originDepth, flipY ) { + + const device = this.backend.device; + + device.queue.copyExternalImageToTexture( + { + source: image + }, { + texture: textureGPU, + mipLevel: 0, + origin: { x: 0, y: 0, z: originDepth } + }, { + width: image.width, + height: image.height, + depthOrArrayLayers: 1 + } + ); + + if ( flipY === true ) { + + this._flipY( textureGPU, textureDescriptorGPU, originDepth ); + + } + + } + + _getPassUtils() { + + let passUtils = this._passUtils; + + if ( passUtils === null ) { + + this._passUtils = passUtils = new WebGPUTexturePassUtils( this.backend.device ); + + } + + return passUtils; + + } + + _generateMipmaps( textureGPU, textureDescriptorGPU, baseArrayLayer = 0 ) { + + this._getPassUtils().generateMipmaps( textureGPU, textureDescriptorGPU, baseArrayLayer ); + + } + + _flipY( textureGPU, textureDescriptorGPU, originDepth = 0 ) { + + this._getPassUtils().flipY( textureGPU, textureDescriptorGPU, originDepth ); + + } + + _copyBufferToTexture( image, textureGPU, textureDescriptorGPU, originDepth, flipY, depth = 0 ) { + + // @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture() + // @TODO: Consider to support valid buffer layouts with other formats like RGB + + const device = this.backend.device; + + const data = image.data; + + const bytesPerTexel = this._getBytesPerTexel( textureDescriptorGPU.format ); + const bytesPerRow = image.width * bytesPerTexel; + + device.queue.writeTexture( + { + texture: textureGPU, + mipLevel: 0, + origin: { x: 0, y: 0, z: originDepth } + }, + data, + { + offset: image.width * image.height * bytesPerTexel * depth, + bytesPerRow + }, + { + width: image.width, + height: image.height, + depthOrArrayLayers: 1 + } ); + + if ( flipY === true ) { + + this._flipY( textureGPU, textureDescriptorGPU, originDepth ); + + } + + } + + _copyCompressedBufferToTexture( mipmaps, textureGPU, textureDescriptorGPU ) { + + // @TODO: Consider to use GPUCommandEncoder.copyBufferToTexture() + + const device = this.backend.device; + + const blockData = this._getBlockData( textureDescriptorGPU.format ); + const isTextureArray = textureDescriptorGPU.size.depthOrArrayLayers > 1; + + for ( let i = 0; i < mipmaps.length; i ++ ) { + + const mipmap = mipmaps[ i ]; + + const width = mipmap.width; + const height = mipmap.height; + const depth = isTextureArray ? textureDescriptorGPU.size.depthOrArrayLayers : 1; + + const bytesPerRow = Math.ceil( width / blockData.width ) * blockData.byteLength; + const bytesPerImage = bytesPerRow * Math.ceil( height / blockData.height ); + + for ( let j = 0; j < depth; j ++ ) { + + device.queue.writeTexture( + { + texture: textureGPU, + mipLevel: i, + origin: { x: 0, y: 0, z: j } + }, + mipmap.data, + { + offset: j * bytesPerImage, + bytesPerRow, + rowsPerImage: Math.ceil( height / blockData.height ) + }, + { + width: Math.ceil( width / blockData.width ) * blockData.width, + height: Math.ceil( height / blockData.height ) * blockData.height, + depthOrArrayLayers: 1 + } + ); + + } + + } + + } + + _getBlockData( format ) { + + // this method is only relevant for compressed texture formats + + if ( format === GPUTextureFormat.BC1RGBAUnorm || format === GPUTextureFormat.BC1RGBAUnormSRGB ) return { byteLength: 8, width: 4, height: 4 }; // DXT1 + if ( format === GPUTextureFormat.BC2RGBAUnorm || format === GPUTextureFormat.BC2RGBAUnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; // DXT3 + if ( format === GPUTextureFormat.BC3RGBAUnorm || format === GPUTextureFormat.BC3RGBAUnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; // DXT5 + if ( format === GPUTextureFormat.BC4RUnorm || format === GPUTextureFormat.BC4RSNorm ) return { byteLength: 8, width: 4, height: 4 }; // RGTC1 + if ( format === GPUTextureFormat.BC5RGUnorm || format === GPUTextureFormat.BC5RGSnorm ) return { byteLength: 16, width: 4, height: 4 }; // RGTC2 + if ( format === GPUTextureFormat.BC6HRGBUFloat || format === GPUTextureFormat.BC6HRGBFloat ) return { byteLength: 16, width: 4, height: 4 }; // BPTC (float) + if ( format === GPUTextureFormat.BC7RGBAUnorm || format === GPUTextureFormat.BC7RGBAUnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; // BPTC (unorm) + + if ( format === GPUTextureFormat.ETC2RGB8Unorm || format === GPUTextureFormat.ETC2RGB8UnormSRGB ) return { byteLength: 8, width: 4, height: 4 }; + if ( format === GPUTextureFormat.ETC2RGB8A1Unorm || format === GPUTextureFormat.ETC2RGB8A1UnormSRGB ) return { byteLength: 8, width: 4, height: 4 }; + if ( format === GPUTextureFormat.ETC2RGBA8Unorm || format === GPUTextureFormat.ETC2RGBA8UnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; + if ( format === GPUTextureFormat.EACR11Unorm ) return { byteLength: 8, width: 4, height: 4 }; + if ( format === GPUTextureFormat.EACR11Snorm ) return { byteLength: 8, width: 4, height: 4 }; + if ( format === GPUTextureFormat.EACRG11Unorm ) return { byteLength: 16, width: 4, height: 4 }; + if ( format === GPUTextureFormat.EACRG11Snorm ) return { byteLength: 16, width: 4, height: 4 }; + + if ( format === GPUTextureFormat.ASTC4x4Unorm || format === GPUTextureFormat.ASTC4x4UnormSRGB ) return { byteLength: 16, width: 4, height: 4 }; + if ( format === GPUTextureFormat.ASTC5x4Unorm || format === GPUTextureFormat.ASTC5x4UnormSRGB ) return { byteLength: 16, width: 5, height: 4 }; + if ( format === GPUTextureFormat.ASTC5x5Unorm || format === GPUTextureFormat.ASTC5x5UnormSRGB ) return { byteLength: 16, width: 5, height: 5 }; + if ( format === GPUTextureFormat.ASTC6x5Unorm || format === GPUTextureFormat.ASTC6x5UnormSRGB ) return { byteLength: 16, width: 6, height: 5 }; + if ( format === GPUTextureFormat.ASTC6x6Unorm || format === GPUTextureFormat.ASTC6x6UnormSRGB ) return { byteLength: 16, width: 6, height: 6 }; + if ( format === GPUTextureFormat.ASTC8x5Unorm || format === GPUTextureFormat.ASTC8x5UnormSRGB ) return { byteLength: 16, width: 8, height: 5 }; + if ( format === GPUTextureFormat.ASTC8x6Unorm || format === GPUTextureFormat.ASTC8x6UnormSRGB ) return { byteLength: 16, width: 8, height: 6 }; + if ( format === GPUTextureFormat.ASTC8x8Unorm || format === GPUTextureFormat.ASTC8x8UnormSRGB ) return { byteLength: 16, width: 8, height: 8 }; + if ( format === GPUTextureFormat.ASTC10x5Unorm || format === GPUTextureFormat.ASTC10x5UnormSRGB ) return { byteLength: 16, width: 10, height: 5 }; + if ( format === GPUTextureFormat.ASTC10x6Unorm || format === GPUTextureFormat.ASTC10x6UnormSRGB ) return { byteLength: 16, width: 10, height: 6 }; + if ( format === GPUTextureFormat.ASTC10x8Unorm || format === GPUTextureFormat.ASTC10x8UnormSRGB ) return { byteLength: 16, width: 10, height: 8 }; + if ( format === GPUTextureFormat.ASTC10x10Unorm || format === GPUTextureFormat.ASTC10x10UnormSRGB ) return { byteLength: 16, width: 10, height: 10 }; + if ( format === GPUTextureFormat.ASTC12x10Unorm || format === GPUTextureFormat.ASTC12x10UnormSRGB ) return { byteLength: 16, width: 12, height: 10 }; + if ( format === GPUTextureFormat.ASTC12x12Unorm || format === GPUTextureFormat.ASTC12x12UnormSRGB ) return { byteLength: 16, width: 12, height: 12 }; + + } + + _convertAddressMode( value ) { + + let addressMode = GPUAddressMode.ClampToEdge; + + if ( value === RepeatWrapping ) { + + addressMode = GPUAddressMode.Repeat; + + } else if ( value === MirroredRepeatWrapping ) { + + addressMode = GPUAddressMode.MirrorRepeat; + + } + + return addressMode; + + } + + _convertFilterMode( value ) { + + let filterMode = GPUFilterMode.Linear; + + if ( value === NearestFilter || value === NearestMipmapNearestFilter || value === NearestMipmapLinearFilter ) { + + filterMode = GPUFilterMode.Nearest; + + } + + return filterMode; + + } + + _getBytesPerTexel( format ) { + + // 8-bit formats + if ( format === GPUTextureFormat.R8Unorm || + format === GPUTextureFormat.R8Snorm || + format === GPUTextureFormat.R8Uint || + format === GPUTextureFormat.R8Sint ) return 1; + + // 16-bit formats + if ( format === GPUTextureFormat.R16Uint || + format === GPUTextureFormat.R16Sint || + format === GPUTextureFormat.R16Float || + format === GPUTextureFormat.RG8Unorm || + format === GPUTextureFormat.RG8Snorm || + format === GPUTextureFormat.RG8Uint || + format === GPUTextureFormat.RG8Sint ) return 2; + + // 32-bit formats + if ( format === GPUTextureFormat.R32Uint || + format === GPUTextureFormat.R32Sint || + format === GPUTextureFormat.R32Float || + format === GPUTextureFormat.RG16Uint || + format === GPUTextureFormat.RG16Sint || + format === GPUTextureFormat.RG16Float || + format === GPUTextureFormat.RGBA8Unorm || + format === GPUTextureFormat.RGBA8UnormSRGB || + format === GPUTextureFormat.RGBA8Snorm || + format === GPUTextureFormat.RGBA8Uint || + format === GPUTextureFormat.RGBA8Sint || + format === GPUTextureFormat.BGRA8Unorm || + format === GPUTextureFormat.BGRA8UnormSRGB || + // Packed 32-bit formats + format === GPUTextureFormat.RGB9E5UFloat || + format === GPUTextureFormat.RGB10A2Unorm || + format === GPUTextureFormat.RG11B10UFloat || + format === GPUTextureFormat.Depth32Float || + format === GPUTextureFormat.Depth24Plus || + format === GPUTextureFormat.Depth24PlusStencil8 || + format === GPUTextureFormat.Depth32FloatStencil8 ) return 4; + + // 64-bit formats + if ( format === GPUTextureFormat.RG32Uint || + format === GPUTextureFormat.RG32Sint || + format === GPUTextureFormat.RG32Float || + format === GPUTextureFormat.RGBA16Uint || + format === GPUTextureFormat.RGBA16Sint || + format === GPUTextureFormat.RGBA16Float ) return 8; + + // 128-bit formats + if ( format === GPUTextureFormat.RGBA32Uint || + format === GPUTextureFormat.RGBA32Sint || + format === GPUTextureFormat.RGBA32Float ) return 16; + + + } + + _getTypedArrayType( format ) { + + if ( format === GPUTextureFormat.R8Uint ) return Uint8Array; + if ( format === GPUTextureFormat.R8Sint ) return Int8Array; + if ( format === GPUTextureFormat.R8Unorm ) return Uint8Array; + if ( format === GPUTextureFormat.R8Snorm ) return Int8Array; + if ( format === GPUTextureFormat.RG8Uint ) return Uint8Array; + if ( format === GPUTextureFormat.RG8Sint ) return Int8Array; + if ( format === GPUTextureFormat.RG8Unorm ) return Uint8Array; + if ( format === GPUTextureFormat.RG8Snorm ) return Int8Array; + if ( format === GPUTextureFormat.RGBA8Uint ) return Uint8Array; + if ( format === GPUTextureFormat.RGBA8Sint ) return Int8Array; + if ( format === GPUTextureFormat.RGBA8Unorm ) return Uint8Array; + if ( format === GPUTextureFormat.RGBA8Snorm ) return Int8Array; + + + if ( format === GPUTextureFormat.R16Uint ) return Uint16Array; + if ( format === GPUTextureFormat.R16Sint ) return Int16Array; + if ( format === GPUTextureFormat.RG16Uint ) return Uint16Array; + if ( format === GPUTextureFormat.RG16Sint ) return Int16Array; + if ( format === GPUTextureFormat.RGBA16Uint ) return Uint16Array; + if ( format === GPUTextureFormat.RGBA16Sint ) return Int16Array; + if ( format === GPUTextureFormat.R16Float ) return Uint16Array; + if ( format === GPUTextureFormat.RG16Float ) return Uint16Array; + if ( format === GPUTextureFormat.RGBA16Float ) return Uint16Array; + + + if ( format === GPUTextureFormat.R32Uint ) return Uint32Array; + if ( format === GPUTextureFormat.R32Sint ) return Int32Array; + if ( format === GPUTextureFormat.R32Float ) return Float32Array; + if ( format === GPUTextureFormat.RG32Uint ) return Uint32Array; + if ( format === GPUTextureFormat.RG32Sint ) return Int32Array; + if ( format === GPUTextureFormat.RG32Float ) return Float32Array; + if ( format === GPUTextureFormat.RGBA32Uint ) return Uint32Array; + if ( format === GPUTextureFormat.RGBA32Sint ) return Int32Array; + if ( format === GPUTextureFormat.RGBA32Float ) return Float32Array; + + if ( format === GPUTextureFormat.BGRA8Unorm ) return Uint8Array; + if ( format === GPUTextureFormat.BGRA8UnormSRGB ) return Uint8Array; + if ( format === GPUTextureFormat.RGB10A2Unorm ) return Uint32Array; + if ( format === GPUTextureFormat.RGB9E5UFloat ) return Uint32Array; + if ( format === GPUTextureFormat.RG11B10UFloat ) return Uint32Array; + + if ( format === GPUTextureFormat.Depth32Float ) return Float32Array; + if ( format === GPUTextureFormat.Depth24Plus ) return Uint32Array; + if ( format === GPUTextureFormat.Depth24PlusStencil8 ) return Uint32Array; + if ( format === GPUTextureFormat.Depth32FloatStencil8 ) return Float32Array; + + } + + _getDimension( texture ) { + + let dimension; + + if ( texture.isData3DTexture ) { + + dimension = GPUTextureDimension.ThreeD; + + } else { + + dimension = GPUTextureDimension.TwoD; + + } + + return dimension; + + } + +} + +function getFormat( texture, device = null ) { + + const format = texture.format; + const type = texture.type; + const colorSpace = texture.colorSpace; + + let formatGPU; + + if ( texture.isFramebufferTexture === true && texture.type === UnsignedByteType ) { + + formatGPU = GPUTextureFormat.BGRA8Unorm; + + } else if ( texture.isCompressedTexture === true || texture.isCompressedArrayTexture === true ) { + + switch ( format ) { + + case RGBA_S3TC_DXT1_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.BC1RGBAUnormSRGB : GPUTextureFormat.BC1RGBAUnorm; + break; + + case RGBA_S3TC_DXT3_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.BC2RGBAUnormSRGB : GPUTextureFormat.BC2RGBAUnorm; + break; + + case RGBA_S3TC_DXT5_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.BC3RGBAUnormSRGB : GPUTextureFormat.BC3RGBAUnorm; + break; + + case RGB_ETC2_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ETC2RGB8UnormSRGB : GPUTextureFormat.ETC2RGB8Unorm; + break; + + case RGBA_ETC2_EAC_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ETC2RGBA8UnormSRGB : GPUTextureFormat.ETC2RGBA8Unorm; + break; + + case RGBA_ASTC_4x4_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC4x4UnormSRGB : GPUTextureFormat.ASTC4x4Unorm; + break; + + case RGBA_ASTC_5x4_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC5x4UnormSRGB : GPUTextureFormat.ASTC5x4Unorm; + break; + + case RGBA_ASTC_5x5_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC5x5UnormSRGB : GPUTextureFormat.ASTC5x5Unorm; + break; + + case RGBA_ASTC_6x5_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC6x5UnormSRGB : GPUTextureFormat.ASTC6x5Unorm; + break; + + case RGBA_ASTC_6x6_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC6x6UnormSRGB : GPUTextureFormat.ASTC6x6Unorm; + break; + + case RGBA_ASTC_8x5_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC8x5UnormSRGB : GPUTextureFormat.ASTC8x5Unorm; + break; + + case RGBA_ASTC_8x6_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC8x6UnormSRGB : GPUTextureFormat.ASTC8x6Unorm; + break; + + case RGBA_ASTC_8x8_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC8x8UnormSRGB : GPUTextureFormat.ASTC8x8Unorm; + break; + + case RGBA_ASTC_10x5_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC10x5UnormSRGB : GPUTextureFormat.ASTC10x5Unorm; + break; + + case RGBA_ASTC_10x6_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC10x6UnormSRGB : GPUTextureFormat.ASTC10x6Unorm; + break; + + case RGBA_ASTC_10x8_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC10x8UnormSRGB : GPUTextureFormat.ASTC10x8Unorm; + break; + + case RGBA_ASTC_10x10_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC10x10UnormSRGB : GPUTextureFormat.ASTC10x10Unorm; + break; + + case RGBA_ASTC_12x10_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC12x10UnormSRGB : GPUTextureFormat.ASTC12x10Unorm; + break; + + case RGBA_ASTC_12x12_Format: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.ASTC12x12UnormSRGB : GPUTextureFormat.ASTC12x12Unorm; + break; + + default: + console.error( 'WebGPURenderer: Unsupported texture format.', format ); + + } + + } else { + + switch ( format ) { + + case RGBAFormat: + + switch ( type ) { + + case ByteType: + formatGPU = GPUTextureFormat.RGBA8Snorm; + break; + + case ShortType: + formatGPU = GPUTextureFormat.RGBA16Sint; + break; + + case UnsignedShortType: + formatGPU = GPUTextureFormat.RGBA16Uint; + break; + case UnsignedIntType: + formatGPU = GPUTextureFormat.RGBA32Uint; + break; + + case IntType: + formatGPU = GPUTextureFormat.RGBA32Sint; + break; + + case UnsignedByteType: + formatGPU = ( colorSpace === SRGBColorSpace ) ? GPUTextureFormat.RGBA8UnormSRGB : GPUTextureFormat.RGBA8Unorm; + break; + + case HalfFloatType: + formatGPU = GPUTextureFormat.RGBA16Float; + break; + + case FloatType: + formatGPU = GPUTextureFormat.RGBA32Float; + break; + + default: + console.error( 'WebGPURenderer: Unsupported texture type with RGBAFormat.', type ); + + } + + break; + + case RGBFormat: + + switch ( type ) { + + case UnsignedInt5999Type: + formatGPU = GPUTextureFormat.RGB9E5UFloat; + break; + + default: + console.error( 'WebGPURenderer: Unsupported texture type with RGBFormat.', type ); + + } + + break; + + case RedFormat: + + switch ( type ) { + + case ByteType: + formatGPU = GPUTextureFormat.R8Snorm; + break; + + case ShortType: + formatGPU = GPUTextureFormat.R16Sint; + break; + + case UnsignedShortType: + formatGPU = GPUTextureFormat.R16Uint; + break; + + case UnsignedIntType: + formatGPU = GPUTextureFormat.R32Uint; + break; + + case IntType: + formatGPU = GPUTextureFormat.R32Sint; + break; + + case UnsignedByteType: + formatGPU = GPUTextureFormat.R8Unorm; + break; + + case HalfFloatType: + formatGPU = GPUTextureFormat.R16Float; + break; + + case FloatType: + formatGPU = GPUTextureFormat.R32Float; + break; + + default: + console.error( 'WebGPURenderer: Unsupported texture type with RedFormat.', type ); + + } + + break; + + case RGFormat: + + switch ( type ) { + + case ByteType: + formatGPU = GPUTextureFormat.RG8Snorm; + break; + + case ShortType: + formatGPU = GPUTextureFormat.RG16Sint; + break; + + case UnsignedShortType: + formatGPU = GPUTextureFormat.RG16Uint; + break; + + case UnsignedIntType: + formatGPU = GPUTextureFormat.RG32Uint; + break; + + case IntType: + formatGPU = GPUTextureFormat.RG32Sint; + break; + + case UnsignedByteType: + formatGPU = GPUTextureFormat.RG8Unorm; + break; + + case HalfFloatType: + formatGPU = GPUTextureFormat.RG16Float; + break; + + case FloatType: + formatGPU = GPUTextureFormat.RG32Float; + break; + + default: + console.error( 'WebGPURenderer: Unsupported texture type with RGFormat.', type ); + + } + + break; + + case DepthFormat: + + switch ( type ) { + + case UnsignedShortType: + formatGPU = GPUTextureFormat.Depth16Unorm; + break; + + case UnsignedIntType: + formatGPU = GPUTextureFormat.Depth24Plus; + break; + + case FloatType: + formatGPU = GPUTextureFormat.Depth32Float; + break; + + default: + console.error( 'WebGPURenderer: Unsupported texture type with DepthFormat.', type ); + + } + + break; + + case DepthStencilFormat: + + switch ( type ) { + + case UnsignedInt248Type: + formatGPU = GPUTextureFormat.Depth24PlusStencil8; + break; + + case FloatType: + + if ( device && device.features.has( GPUFeatureName.Depth32FloatStencil8 ) === false ) { + + console.error( 'WebGPURenderer: Depth textures with DepthStencilFormat + FloatType can only be used with the "depth32float-stencil8" GPU feature.' ); + + } + + formatGPU = GPUTextureFormat.Depth32FloatStencil8; + + break; + + default: + console.error( 'WebGPURenderer: Unsupported texture type with DepthStencilFormat.', type ); + + } + + break; + + case RedIntegerFormat: + + switch ( type ) { + + case IntType: + formatGPU = GPUTextureFormat.R32Sint; + break; + + case UnsignedIntType: + formatGPU = GPUTextureFormat.R32Uint; + break; + + default: + console.error( 'WebGPURenderer: Unsupported texture type with RedIntegerFormat.', type ); + + } + + break; + + case RGIntegerFormat: + + switch ( type ) { + + case IntType: + formatGPU = GPUTextureFormat.RG32Sint; + break; + + case UnsignedIntType: + formatGPU = GPUTextureFormat.RG32Uint; + break; + + default: + console.error( 'WebGPURenderer: Unsupported texture type with RGIntegerFormat.', type ); + + } + + break; + + case RGBAIntegerFormat: + + switch ( type ) { + + case IntType: + formatGPU = GPUTextureFormat.RGBA32Sint; + break; + + case UnsignedIntType: + formatGPU = GPUTextureFormat.RGBA32Uint; + break; + + default: + console.error( 'WebGPURenderer: Unsupported texture type with RGBAIntegerFormat.', type ); + + } + + break; + + default: + console.error( 'WebGPURenderer: Unsupported texture format.', format ); + + } + + } + + return formatGPU; + +} + +const declarationRegexp = /^[fn]*\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)\s*[\-\>]*\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/i; +const propertiesRegexp = /([a-z_0-9]+)\s*:\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/ig; + +const wgslTypeLib$1 = { + 'f32': 'float', + 'i32': 'int', + 'u32': 'uint', + 'bool': 'bool', + + 'vec2': 'vec2', + 'vec2': 'ivec2', + 'vec2': 'uvec2', + 'vec2': 'bvec2', + + 'vec2f': 'vec2', + 'vec2i': 'ivec2', + 'vec2u': 'uvec2', + 'vec2b': 'bvec2', + + 'vec3': 'vec3', + 'vec3': 'ivec3', + 'vec3': 'uvec3', + 'vec3': 'bvec3', + + 'vec3f': 'vec3', + 'vec3i': 'ivec3', + 'vec3u': 'uvec3', + 'vec3b': 'bvec3', + + 'vec4': 'vec4', + 'vec4': 'ivec4', + 'vec4': 'uvec4', + 'vec4': 'bvec4', + + 'vec4f': 'vec4', + 'vec4i': 'ivec4', + 'vec4u': 'uvec4', + 'vec4b': 'bvec4', + + 'mat2x2': 'mat2', + 'mat2x2f': 'mat2', + + 'mat3x3': 'mat3', + 'mat3x3f': 'mat3', + + 'mat4x4': 'mat4', + 'mat4x4f': 'mat4', + + 'sampler': 'sampler', + + 'texture_1d': 'texture', + + 'texture_2d': 'texture', + 'texture_2d_array': 'texture', + 'texture_multisampled_2d': 'cubeTexture', + + 'texture_depth_2d': 'depthTexture', + + 'texture_3d': 'texture3D', + + 'texture_cube': 'cubeTexture', + 'texture_cube_array': 'cubeTexture', + + 'texture_storage_1d': 'storageTexture', + 'texture_storage_2d': 'storageTexture', + 'texture_storage_2d_array': 'storageTexture', + 'texture_storage_3d': 'storageTexture' + +}; + +const parse = ( source ) => { + + source = source.trim(); + + const declaration = source.match( declarationRegexp ); + + if ( declaration !== null && declaration.length === 4 ) { + + const inputsCode = declaration[ 2 ]; + const propsMatches = []; + let match = null; + + while ( ( match = propertiesRegexp.exec( inputsCode ) ) !== null ) { + + propsMatches.push( { name: match[ 1 ], type: match[ 2 ] } ); + + } + + // Process matches to correctly pair names and types + const inputs = []; + for ( let i = 0; i < propsMatches.length; i ++ ) { + + const { name, type } = propsMatches[ i ]; + + let resolvedType = type; + + if ( resolvedType.startsWith( 'texture' ) ) { + + resolvedType = type.split( '<' )[ 0 ]; + + } + + resolvedType = wgslTypeLib$1[ resolvedType ] || resolvedType; + + inputs.push( new NodeFunctionInput( resolvedType, name ) ); + + } + + const blockCode = source.substring( declaration[ 0 ].length ); + const outputType = declaration[ 3 ] || 'void'; + + const name = declaration[ 1 ] !== undefined ? declaration[ 1 ] : ''; + const type = wgslTypeLib$1[ outputType ] || outputType; + + return { + type, + inputs, + name, + inputsCode, + blockCode, + outputType + }; + + } else { + + throw new Error( 'FunctionNode: Function is not a WGSL code.' ); + + } + +}; + +class WGSLNodeFunction extends NodeFunction { + + constructor( source ) { + + const { type, inputs, name, inputsCode, blockCode, outputType } = parse( source ); + + super( type, inputs, name ); + + this.inputsCode = inputsCode; + this.blockCode = blockCode; + this.outputType = outputType; + + } + + getCode( name = this.name ) { + + const outputType = this.outputType !== 'void' ? '-> ' + this.outputType : ''; + + return `fn ${ name } ( ${ this.inputsCode.trim() } ) ${ outputType }` + this.blockCode; + + } + +} + +class WGSLNodeParser extends NodeParser { + + parseFunction( source ) { + + return new WGSLNodeFunction( source ); + + } + +} + +// GPUShaderStage is not defined in browsers not supporting WebGPU +const GPUShaderStage = self.GPUShaderStage; + +const gpuShaderStageLib = { + 'vertex': GPUShaderStage ? GPUShaderStage.VERTEX : 1, + 'fragment': GPUShaderStage ? GPUShaderStage.FRAGMENT : 2, + 'compute': GPUShaderStage ? GPUShaderStage.COMPUTE : 4 +}; + +const supports = { + instance: true, + swizzleAssign: false, + storageBuffer: true +}; + +const wgslFnOpLib = { + '^^': 'tsl_xor' +}; + +const wgslTypeLib = { + float: 'f32', + int: 'i32', + uint: 'u32', + bool: 'bool', + color: 'vec3', + + vec2: 'vec2', + ivec2: 'vec2', + uvec2: 'vec2', + bvec2: 'vec2', + + vec3: 'vec3', + ivec3: 'vec3', + uvec3: 'vec3', + bvec3: 'vec3', + + vec4: 'vec4', + ivec4: 'vec4', + uvec4: 'vec4', + bvec4: 'vec4', + + mat2: 'mat2x2', + imat2: 'mat2x2', + umat2: 'mat2x2', + bmat2: 'mat2x2', + + mat3: 'mat3x3', + imat3: 'mat3x3', + umat3: 'mat3x3', + bmat3: 'mat3x3', + + mat4: 'mat4x4', + imat4: 'mat4x4', + umat4: 'mat4x4', + bmat4: 'mat4x4' +}; + +const wgslPolyfill = { + tsl_xor: new CodeNode( 'fn tsl_xor( a : bool, b : bool ) -> bool { return ( a || b ) && !( a && b ); }' ), + mod_float: new CodeNode( 'fn tsl_mod_float( x : f32, y : f32 ) -> f32 { return x - y * floor( x / y ); }' ), + mod_vec2: new CodeNode( 'fn tsl_mod_vec2( x : vec2f, y : vec2f ) -> vec2f { return x - y * floor( x / y ); }' ), + mod_vec3: new CodeNode( 'fn tsl_mod_vec3( x : vec3f, y : vec3f ) -> vec3f { return x - y * floor( x / y ); }' ), + mod_vec4: new CodeNode( 'fn tsl_mod_vec4( x : vec4f, y : vec4f ) -> vec4f { return x - y * floor( x / y ); }' ), + equals_bool: new CodeNode( 'fn tsl_equals_bool( a : bool, b : bool ) -> bool { return a == b; }' ), + equals_bvec2: new CodeNode( 'fn tsl_equals_bvec2( a : vec2f, b : vec2f ) -> vec2 { return vec2( a.x == b.x, a.y == b.y ); }' ), + equals_bvec3: new CodeNode( 'fn tsl_equals_bvec3( a : vec3f, b : vec3f ) -> vec3 { return vec3( a.x == b.x, a.y == b.y, a.z == b.z ); }' ), + equals_bvec4: new CodeNode( 'fn tsl_equals_bvec4( a : vec4f, b : vec4f ) -> vec4 { return vec4( a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w ); }' ), + repeatWrapping: new CodeNode( ` +fn tsl_repeatWrapping( uv : vec2, dimension : vec2 ) -> vec2 { + + let uvScaled = vec2( uv * vec2( dimension ) ); + + return ( ( uvScaled % dimension ) + dimension ) % dimension; + +} +` ), + biquadraticTexture: new CodeNode( ` +fn tsl_biquadraticTexture( map : texture_2d, coord : vec2f, level : i32 ) -> vec4f { + + let iRes = vec2i( textureDimensions( map, level ) ); + let res = vec2f( iRes ); + + let uvScaled = coord * res; + let uvWrapping = ( ( uvScaled % res ) + res ) % res; + + // https://www.shadertoy.com/view/WtyXRy + + let uv = uvWrapping - 0.5; + let iuv = floor( uv ); + let f = fract( uv ); + + let rg1 = textureLoad( map, vec2i( iuv + vec2( 0.5, 0.5 ) ) % iRes, level ); + let rg2 = textureLoad( map, vec2i( iuv + vec2( 1.5, 0.5 ) ) % iRes, level ); + let rg3 = textureLoad( map, vec2i( iuv + vec2( 0.5, 1.5 ) ) % iRes, level ); + let rg4 = textureLoad( map, vec2i( iuv + vec2( 1.5, 1.5 ) ) % iRes, level ); + + return mix( mix( rg1, rg2, f.x ), mix( rg3, rg4, f.x ), f.y ); + +} +` ) +}; + +const wgslMethods = { + dFdx: 'dpdx', + dFdy: '- dpdy', + mod_float: 'tsl_mod_float', + mod_vec2: 'tsl_mod_vec2', + mod_vec3: 'tsl_mod_vec3', + mod_vec4: 'tsl_mod_vec4', + equals_bool: 'tsl_equals_bool', + equals_bvec2: 'tsl_equals_bvec2', + equals_bvec3: 'tsl_equals_bvec3', + equals_bvec4: 'tsl_equals_bvec4', + inversesqrt: 'inverseSqrt', + bitcast: 'bitcast' +}; + +// WebGPU issue: does not support pow() with negative base on Windows + +if ( /Windows/g.test( navigator.userAgent ) ) { + + wgslPolyfill.pow_float = new CodeNode( 'fn tsl_pow_float( a : f32, b : f32 ) -> f32 { return select( -pow( -a, b ), pow( a, b ), a > 0.0 ); }' ); + wgslPolyfill.pow_vec2 = new CodeNode( 'fn tsl_pow_vec2( a : vec2f, b : vec2f ) -> vec2f { return vec2f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ) ); }', [ wgslPolyfill.pow_float ] ); + wgslPolyfill.pow_vec3 = new CodeNode( 'fn tsl_pow_vec3( a : vec3f, b : vec3f ) -> vec3f { return vec3f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ), tsl_pow_float( a.z, b.z ) ); }', [ wgslPolyfill.pow_float ] ); + wgslPolyfill.pow_vec4 = new CodeNode( 'fn tsl_pow_vec4( a : vec4f, b : vec4f ) -> vec4f { return vec4f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ), tsl_pow_float( a.z, b.z ), tsl_pow_float( a.w, b.w ) ); }', [ wgslPolyfill.pow_float ] ); + + wgslMethods.pow_float = 'tsl_pow_float'; + wgslMethods.pow_vec2 = 'tsl_pow_vec2'; + wgslMethods.pow_vec3 = 'tsl_pow_vec3'; + wgslMethods.pow_vec4 = 'tsl_pow_vec4'; + +} + +// + +let diagnostics = ''; + +if ( /Firefox/g.test( navigator.userAgent ) !== true ) { + + diagnostics += 'diagnostic( off, derivative_uniformity );\n'; + +} + +// + +class WGSLNodeBuilder extends NodeBuilder { + + constructor( object, renderer ) { + + super( object, renderer, new WGSLNodeParser() ); + + this.uniformGroups = {}; + + this.builtins = {}; + + this.directives = {}; + + this.scopedArrays = new Map(); + + } + + needsToWorkingColorSpace( texture ) { + + return texture.isVideoTexture === true && texture.colorSpace !== NoColorSpace; + + } + + _generateTextureSample( texture, textureProperty, uvSnippet, depthSnippet, shaderStage = this.shaderStage ) { + + if ( shaderStage === 'fragment' ) { + + if ( depthSnippet ) { + + return `textureSample( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ depthSnippet } )`; + + } else { + + return `textureSample( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet } )`; + + } + + } else if ( this.isFilteredTexture( texture ) ) { + + return this.generateFilteredTexture( texture, textureProperty, uvSnippet ); + + } else { + + return this.generateTextureLod( texture, textureProperty, uvSnippet, '0' ); + + } + + } + + _generateVideoSample( textureProperty, uvSnippet, shaderStage = this.shaderStage ) { + + if ( shaderStage === 'fragment' ) { + + return `textureSampleBaseClampToEdge( ${ textureProperty }, ${ textureProperty }_sampler, vec2( ${ uvSnippet }.x, 1.0 - ${ uvSnippet }.y ) )`; + + } else { + + console.error( `WebGPURenderer: THREE.VideoTexture does not support ${ shaderStage } shader.` ); + + } + + } + + _generateTextureSampleLevel( texture, textureProperty, uvSnippet, levelSnippet, depthSnippet, shaderStage = this.shaderStage ) { + + if ( shaderStage === 'fragment' && this.isUnfilterable( texture ) === false ) { + + return `textureSampleLevel( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ levelSnippet } )`; + + } else if ( this.isFilteredTexture( texture ) ) { + + return this.generateFilteredTexture( texture, textureProperty, uvSnippet, levelSnippet ); + + } else { + + return this.generateTextureLod( texture, textureProperty, uvSnippet, levelSnippet ); + + } + + } + + generateFilteredTexture( texture, textureProperty, uvSnippet, levelSnippet = '0' ) { + + this._include( 'biquadraticTexture' ); + + return `tsl_biquadraticTexture( ${ textureProperty }, ${ uvSnippet }, i32( ${ levelSnippet } ) )`; + + } + + generateTextureLod( texture, textureProperty, uvSnippet, levelSnippet = '0' ) { + + this._include( 'repeatWrapping' ); + + const dimension = texture.isMultisampleRenderTargetTexture === true ? `textureDimensions( ${ textureProperty } )` : `textureDimensions( ${ textureProperty }, 0 )`; + + return `textureLoad( ${ textureProperty }, tsl_repeatWrapping( ${ uvSnippet }, ${ dimension } ), i32( ${ levelSnippet } ) )`; + + } + + generateTextureLoad( texture, textureProperty, uvIndexSnippet, depthSnippet, levelSnippet = '0u' ) { + + if ( depthSnippet ) { + + return `textureLoad( ${ textureProperty }, ${ uvIndexSnippet }, ${ depthSnippet }, ${ levelSnippet } )`; + + } else { + + return `textureLoad( ${ textureProperty }, ${ uvIndexSnippet }, ${ levelSnippet } )`; + + } + + } + + generateTextureStore( texture, textureProperty, uvIndexSnippet, valueSnippet ) { + + return `textureStore( ${ textureProperty }, ${ uvIndexSnippet }, ${ valueSnippet } )`; + + } + + isUnfilterable( texture ) { + + return this.getComponentTypeFromTexture( texture ) !== 'float' || ( ! this.isAvailable( 'float32Filterable' ) && texture.isDataTexture === true && texture.type === FloatType ) || texture.isMultisampleRenderTargetTexture === true; + + } + + generateTexture( texture, textureProperty, uvSnippet, depthSnippet, shaderStage = this.shaderStage ) { + + let snippet = null; + + if ( texture.isVideoTexture === true ) { + + snippet = this._generateVideoSample( textureProperty, uvSnippet, shaderStage ); + + } else if ( this.isUnfilterable( texture ) ) { + + snippet = this.generateTextureLod( texture, textureProperty, uvSnippet, '0', depthSnippet, shaderStage ); + + } else { + + snippet = this._generateTextureSample( texture, textureProperty, uvSnippet, depthSnippet, shaderStage ); + + } + + return snippet; + + } + + generateTextureGrad( texture, textureProperty, uvSnippet, gradSnippet, depthSnippet, shaderStage = this.shaderStage ) { + + if ( shaderStage === 'fragment' ) { + + // TODO handle i32 or u32 --> uvSnippet, array_index: A, ddx, ddy + return `textureSampleGrad( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ gradSnippet[ 0 ] }, ${ gradSnippet[ 1 ] } )`; + + } else { + + console.error( `WebGPURenderer: THREE.TextureNode.gradient() does not support ${ shaderStage } shader.` ); + + } + + } + + generateTextureCompare( texture, textureProperty, uvSnippet, compareSnippet, depthSnippet, shaderStage = this.shaderStage ) { + + if ( shaderStage === 'fragment' ) { + + return `textureSampleCompare( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ compareSnippet } )`; + + } else { + + console.error( `WebGPURenderer: THREE.DepthTexture.compareFunction() does not support ${ shaderStage } shader.` ); + + } + + } + + generateTextureLevel( texture, textureProperty, uvSnippet, levelSnippet, depthSnippet, shaderStage = this.shaderStage ) { + + let snippet = null; + + if ( texture.isVideoTexture === true ) { + + snippet = this._generateVideoSample( textureProperty, uvSnippet, shaderStage ); + + } else { + + snippet = this._generateTextureSampleLevel( texture, textureProperty, uvSnippet, levelSnippet, depthSnippet, shaderStage ); + + } + + return snippet; + + } + + generateTextureBias( texture, textureProperty, uvSnippet, biasSnippet, depthSnippet, shaderStage = this.shaderStage ) { + + if ( shaderStage === 'fragment' ) { + + return `textureSampleBias( ${ textureProperty }, ${ textureProperty }_sampler, ${ uvSnippet }, ${ biasSnippet } )`; + + } else { + + console.error( `WebGPURenderer: THREE.TextureNode.biasNode does not support ${ shaderStage } shader.` ); + + } + + } + + getPropertyName( node, shaderStage = this.shaderStage ) { + + if ( node.isNodeVarying === true && node.needsInterpolation === true ) { + + if ( shaderStage === 'vertex' ) { + + return `varyings.${ node.name }`; + + } + + } else if ( node.isNodeUniform === true ) { + + const name = node.name; + const type = node.type; + + if ( type === 'texture' || type === 'cubeTexture' || type === 'storageTexture' || type === 'texture3D' ) { + + return name; + + } else if ( type === 'buffer' || type === 'storageBuffer' ) { + + return `NodeBuffer_${ node.id }.${name}`; + + } else { + + return node.groupNode.name + '.' + name; + + } + + } + + return super.getPropertyName( node ); + + } + + getOutputStructName() { + + return 'output'; + + } + + _getUniformGroupCount( shaderStage ) { + + return Object.keys( this.uniforms[ shaderStage ] ).length; + + } + + getFunctionOperator( op ) { + + const fnOp = wgslFnOpLib[ op ]; + + if ( fnOp !== undefined ) { + + this._include( fnOp ); + + return fnOp; + + } + + return null; + + } + + getStorageAccess( node ) { + + if ( node.isStorageTextureNode ) { + + switch ( node.access ) { + + case GPUStorageTextureAccess.ReadOnly: + + return 'read'; + + case GPUStorageTextureAccess.WriteOnly: + + return 'write'; + + default: + + return 'read_write'; + + } + + } else { + + switch ( node.access ) { + + case GPUBufferBindingType.Storage: + + return 'read_write'; + + + case GPUBufferBindingType.ReadOnlyStorage: + + return 'read'; + + default: + + return 'write'; + + } + + } + + } + + getUniformFromNode( node, type, shaderStage, name = null ) { + + const uniformNode = super.getUniformFromNode( node, type, shaderStage, name ); + const nodeData = this.getDataFromNode( node, shaderStage, this.globalCache ); + + if ( nodeData.uniformGPU === undefined ) { + + let uniformGPU; + + const group = node.groupNode; + const groupName = group.name; + + const bindings = this.getBindGroupArray( groupName, shaderStage ); + + if ( type === 'texture' || type === 'cubeTexture' || type === 'storageTexture' || type === 'texture3D' ) { + + let texture = null; + + if ( type === 'texture' || type === 'storageTexture' ) { + + texture = new NodeSampledTexture( uniformNode.name, uniformNode.node, group, node.access ? node.access : null ); + + } else if ( type === 'cubeTexture' ) { + + texture = new NodeSampledCubeTexture( uniformNode.name, uniformNode.node, group, node.access ? node.access : null ); + + } else if ( type === 'texture3D' ) { + + texture = new NodeSampledTexture3D( uniformNode.name, uniformNode.node, group, node.access ? node.access : null ); + + } + + texture.store = node.isStorageTextureNode === true; + texture.setVisibility( gpuShaderStageLib[ shaderStage ] ); + + if ( shaderStage === 'fragment' && this.isUnfilterable( node.value ) === false && texture.store === false ) { + + const sampler = new NodeSampler( `${uniformNode.name}_sampler`, uniformNode.node, group ); + sampler.setVisibility( gpuShaderStageLib[ shaderStage ] ); + + bindings.push( sampler, texture ); + + uniformGPU = [ sampler, texture ]; + + } else { + + bindings.push( texture ); + + uniformGPU = [ texture ]; + + } + + } else if ( type === 'buffer' || type === 'storageBuffer' ) { + + const bufferClass = type === 'storageBuffer' ? NodeStorageBuffer : NodeUniformBuffer; + const buffer = new bufferClass( node, group ); + buffer.setVisibility( gpuShaderStageLib[ shaderStage ] ); + + bindings.push( buffer ); + + uniformGPU = buffer; + + } else { + + const uniformsStage = this.uniformGroups[ shaderStage ] || ( this.uniformGroups[ shaderStage ] = {} ); + + let uniformsGroup = uniformsStage[ groupName ]; + + if ( uniformsGroup === undefined ) { + + uniformsGroup = new NodeUniformsGroup( groupName, group ); + uniformsGroup.setVisibility( gpuShaderStageLib[ shaderStage ] ); + + uniformsStage[ groupName ] = uniformsGroup; + + bindings.push( uniformsGroup ); + + } + + uniformGPU = this.getNodeUniform( uniformNode, type ); + + uniformsGroup.addUniform( uniformGPU ); + + } + + nodeData.uniformGPU = uniformGPU; + + } + + return uniformNode; + + } + + getBuiltin( name, property, type, shaderStage = this.shaderStage ) { + + const map = this.builtins[ shaderStage ] || ( this.builtins[ shaderStage ] = new Map() ); + + if ( map.has( name ) === false ) { + + map.set( name, { + name, + property, + type + } ); + + } + + return property; + + } + + hasBuiltin( name, shaderStage = this.shaderStage ) { + + return ( this.builtins[ shaderStage ] !== undefined && this.builtins[ shaderStage ].has( name ) ); + + } + + getVertexIndex() { + + if ( this.shaderStage === 'vertex' ) { + + return this.getBuiltin( 'vertex_index', 'vertexIndex', 'u32', 'attribute' ); + + } + + return 'vertexIndex'; + + } + + buildFunctionCode( shaderNode ) { + + const layout = shaderNode.layout; + const flowData = this.flowShaderNode( shaderNode ); + + const parameters = []; + + for ( const input of layout.inputs ) { + + parameters.push( input.name + ' : ' + this.getType( input.type ) ); + + } + + // + + let code = `fn ${ layout.name }( ${ parameters.join( ', ' ) } ) -> ${ this.getType( layout.type ) } { +${ flowData.vars } +${ flowData.code } +`; + + if ( flowData.result ) { + + code += `\treturn ${ flowData.result };\n`; + + } + + code += '\n}\n'; + + // + + return code; + + } + + getInstanceIndex() { + + if ( this.shaderStage === 'vertex' ) { + + return this.getBuiltin( 'instance_index', 'instanceIndex', 'u32', 'attribute' ); + + } + + return 'instanceIndex'; + + } + + getInvocationLocalIndex() { + + return this.getBuiltin( 'local_invocation_index', 'invocationLocalIndex', 'u32', 'attribute' ); + + } + + getSubgroupSize() { + + this.enableSubGroups(); + + return this.getBuiltin( 'subgroup_size', 'subgroupSize', 'u32', 'attribute' ); + + } + + getInvocationSubgroupIndex() { + + this.enableSubGroups(); + + return this.getBuiltin( 'subgroup_invocation_id', 'invocationSubgroupIndex', 'u32', 'attribute' ); + + } + + getSubgroupIndex() { + + this.enableSubGroups(); + + return this.getBuiltin( 'subgroup_id', 'subgroupIndex', 'u32', 'attribute' ); + + } + + getDrawIndex() { + + return null; + + } + + getFrontFacing() { + + return this.getBuiltin( 'front_facing', 'isFront', 'bool' ); + + } + + getFragCoord() { + + return this.getBuiltin( 'position', 'fragCoord', 'vec4' ) + '.xy'; + + } + + getFragDepth() { + + return 'output.' + this.getBuiltin( 'frag_depth', 'depth', 'f32', 'output' ); + + } + + isFlipY() { + + return false; + + } + + enableDirective( name, shaderStage = this.shaderStage ) { + + const stage = this.directives[ shaderStage ] || ( this.directives[ shaderStage ] = new Set() ); + stage.add( name ); + + } + + getDirectives( shaderStage ) { + + const snippets = []; + const directives = this.directives[ shaderStage ]; + + if ( directives !== undefined ) { + + for ( const directive of directives ) { + + snippets.push( `enable ${directive};` ); + + } + + } + + return snippets.join( '\n' ); + + } + + enableSubGroups() { + + this.enableDirective( 'subgroups' ); + + } + + enableSubgroupsF16() { + + this.enableDirective( 'subgroups-f16' ); + + } + + enableClipDistances() { + + this.enableDirective( 'clip_distances' ); + + } + + enableShaderF16() { + + this.enableDirective( 'f16' ); + + } + + enableDualSourceBlending() { + + this.enableDirective( 'dual_source_blending' ); + + } + + getBuiltins( shaderStage ) { + + const snippets = []; + const builtins = this.builtins[ shaderStage ]; + + if ( builtins !== undefined ) { + + for ( const { name, property, type } of builtins.values() ) { + + snippets.push( `@builtin( ${name} ) ${property} : ${type}` ); + + } + + } + + return snippets.join( ',\n\t' ); + + } + + getScopedArray( name, scope, bufferType, bufferCount ) { + + if ( this.scopedArrays.has( name ) === false ) { + + this.scopedArrays.set( name, { + name, + scope, + bufferType, + bufferCount + } ); + + } + + return name; + + } + + getScopedArrays( shaderStage ) { + + if ( shaderStage !== 'compute' ) { + + return; + + } + + const snippets = []; + + for ( const { name, scope, bufferType, bufferCount } of this.scopedArrays.values() ) { + + const type = this.getType( bufferType ); + + snippets.push( `var<${scope}> ${name}: array< ${type}, ${bufferCount} >;` ); + + } + + return snippets.join( '\n' ); + + } + + getAttributes( shaderStage ) { + + const snippets = []; + + if ( shaderStage === 'compute' ) { + + this.getBuiltin( 'global_invocation_id', 'id', 'vec3', 'attribute' ); + this.getBuiltin( 'workgroup_id', 'workgroupId', 'vec3', 'attribute' ); + this.getBuiltin( 'local_invocation_id', 'localId', 'vec3', 'attribute' ); + this.getBuiltin( 'num_workgroups', 'numWorkgroups', 'vec3', 'attribute' ); + + if ( this.renderer.hasFeature( 'subgroups' ) ) { + + this.enableDirective( 'subgroups', shaderStage ); + this.getBuiltin( 'subgroup_size', 'subgroupSize', 'u32', 'attribute' ); + + } + + } + + if ( shaderStage === 'vertex' || shaderStage === 'compute' ) { + + const builtins = this.getBuiltins( 'attribute' ); + + if ( builtins ) snippets.push( builtins ); + + const attributes = this.getAttributesArray(); + + for ( let index = 0, length = attributes.length; index < length; index ++ ) { + + const attribute = attributes[ index ]; + const name = attribute.name; + const type = this.getType( attribute.type ); + + snippets.push( `@location( ${index} ) ${ name } : ${ type }` ); + + } + + } + + return snippets.join( ',\n\t' ); + + } + + getStructMembers( struct ) { + + const snippets = []; + const members = struct.getMemberTypes(); + + for ( let i = 0; i < members.length; i ++ ) { + + const member = members[ i ]; + snippets.push( `\t@location( ${i} ) m${i} : ${ member }` ); + + } + + const builtins = this.getBuiltins( 'output' ); + + if ( builtins ) snippets.push( '\t' + builtins ); + + return snippets.join( ',\n' ); + + } + + getStructs( shaderStage ) { + + const snippets = []; + const structs = this.structs[ shaderStage ]; + + for ( let index = 0, length = structs.length; index < length; index ++ ) { + + const struct = structs[ index ]; + const name = struct.name; + + let snippet = `\struct ${ name } {\n`; + snippet += this.getStructMembers( struct ); + snippet += '\n}'; + + + snippets.push( snippet ); + + snippets.push( `\nvar output : ${ name };\n\n` ); + + } + + return snippets.join( '\n\n' ); + + } + + getVar( type, name ) { + + return `var ${ name } : ${ this.getType( type ) }`; + + } + + getVars( shaderStage ) { + + const snippets = []; + const vars = this.vars[ shaderStage ]; + + if ( vars !== undefined ) { + + for ( const variable of vars ) { + + snippets.push( `\t${ this.getVar( variable.type, variable.name ) };` ); + + } + + } + + return `\n${ snippets.join( '\n' ) }\n`; + + } + + getVaryings( shaderStage ) { + + const snippets = []; + + if ( shaderStage === 'vertex' ) { + + this.getBuiltin( 'position', 'Vertex', 'vec4', 'vertex' ); + + } + + if ( shaderStage === 'vertex' || shaderStage === 'fragment' ) { + + const varyings = this.varyings; + const vars = this.vars[ shaderStage ]; + + for ( let index = 0; index < varyings.length; index ++ ) { + + const varying = varyings[ index ]; + + if ( varying.needsInterpolation ) { + + let attributesSnippet = `@location( ${index} )`; + + if ( /^(int|uint|ivec|uvec)/.test( varying.type ) ) { + + attributesSnippet += ' @interpolate( flat )'; + + + } + + snippets.push( `${ attributesSnippet } ${ varying.name } : ${ this.getType( varying.type ) }` ); + + } else if ( shaderStage === 'vertex' && vars.includes( varying ) === false ) { + + vars.push( varying ); + + } + + } + + } + + const builtins = this.getBuiltins( shaderStage ); + + if ( builtins ) snippets.push( builtins ); + + const code = snippets.join( ',\n\t' ); + + return shaderStage === 'vertex' ? this._getWGSLStruct( 'VaryingsStruct', '\t' + code ) : code; + + } + + getUniforms( shaderStage ) { + + const uniforms = this.uniforms[ shaderStage ]; + + const bindingSnippets = []; + const bufferSnippets = []; + const structSnippets = []; + const uniformGroups = {}; + + for ( const uniform of uniforms ) { + + const groupName = uniform.groupNode.name; + const uniformIndexes = this.bindingsIndexes[ groupName ]; + + if ( uniform.type === 'texture' || uniform.type === 'cubeTexture' || uniform.type === 'storageTexture' || uniform.type === 'texture3D' ) { + + const texture = uniform.node.value; + + if ( shaderStage === 'fragment' && this.isUnfilterable( texture ) === false && uniform.node.isStorageTextureNode !== true ) { + + if ( texture.isDepthTexture === true && texture.compareFunction !== null ) { + + bindingSnippets.push( `@binding( ${ uniformIndexes.binding ++ } ) @group( ${ uniformIndexes.group } ) var ${ uniform.name }_sampler : sampler_comparison;` ); + + } else { + + bindingSnippets.push( `@binding( ${ uniformIndexes.binding ++ } ) @group( ${ uniformIndexes.group } ) var ${ uniform.name }_sampler : sampler;` ); + + } + + } + + let textureType; + + let multisampled = ''; + + if ( texture.isMultisampleRenderTargetTexture === true ) { + + multisampled = '_multisampled'; + + } + + if ( texture.isCubeTexture === true ) { + + textureType = 'texture_cube'; + + } else if ( texture.isDataArrayTexture === true || texture.isCompressedArrayTexture === true ) { + + textureType = 'texture_2d_array'; + + } else if ( texture.isDepthTexture === true ) { + + textureType = `texture_depth${multisampled}_2d`; + + } else if ( texture.isVideoTexture === true ) { + + textureType = 'texture_external'; + + } else if ( texture.isData3DTexture === true ) { + + textureType = 'texture_3d'; + + } else if ( uniform.node.isStorageTextureNode === true ) { + + const format = getFormat( texture ); + const access = this.getStorageAccess( uniform.node ); + + textureType = `texture_storage_2d<${ format }, ${ access }>`; + + } else { + + const componentPrefix = this.getComponentTypeFromTexture( texture ).charAt( 0 ); + + textureType = `texture${multisampled}_2d<${ componentPrefix }32>`; + + } + + bindingSnippets.push( `@binding( ${ uniformIndexes.binding ++ } ) @group( ${ uniformIndexes.group } ) var ${ uniform.name } : ${ textureType };` ); + + } else if ( uniform.type === 'buffer' || uniform.type === 'storageBuffer' ) { + + const bufferNode = uniform.node; + const bufferType = this.getType( bufferNode.bufferType ); + const bufferCount = bufferNode.bufferCount; + + const bufferCountSnippet = bufferCount > 0 ? ', ' + bufferCount : ''; + const bufferTypeSnippet = bufferNode.isAtomic ? `atomic<${bufferType}>` : `${bufferType}`; + const bufferSnippet = `\t${ uniform.name } : array< ${ bufferTypeSnippet }${ bufferCountSnippet } >\n`; + const bufferAccessMode = bufferNode.isStorageBufferNode ? `storage, ${ this.getStorageAccess( bufferNode ) }` : 'uniform'; + + bufferSnippets.push( this._getWGSLStructBinding( 'NodeBuffer_' + bufferNode.id, bufferSnippet, bufferAccessMode, uniformIndexes.binding ++, uniformIndexes.group ) ); + + } else { + + const vectorType = this.getType( this.getVectorType( uniform.type ) ); + const groupName = uniform.groupNode.name; + + const group = uniformGroups[ groupName ] || ( uniformGroups[ groupName ] = { + index: uniformIndexes.binding ++, + id: uniformIndexes.group, + snippets: [] + } ); + + group.snippets.push( `\t${ uniform.name } : ${ vectorType }` ); + + } + + } + + for ( const name in uniformGroups ) { + + const group = uniformGroups[ name ]; + + structSnippets.push( this._getWGSLStructBinding( name, group.snippets.join( ',\n' ), 'uniform', group.index, group.id ) ); + + } + + let code = bindingSnippets.join( '\n' ); + code += bufferSnippets.join( '\n' ); + code += structSnippets.join( '\n' ); + + return code; + + } + + buildCode() { + + const shadersData = this.material !== null ? { fragment: {}, vertex: {} } : { compute: {} }; + + this.sortBindingGroups(); + + for ( const shaderStage in shadersData ) { + + const stageData = shadersData[ shaderStage ]; + stageData.uniforms = this.getUniforms( shaderStage ); + stageData.attributes = this.getAttributes( shaderStage ); + stageData.varyings = this.getVaryings( shaderStage ); + stageData.structs = this.getStructs( shaderStage ); + stageData.vars = this.getVars( shaderStage ); + stageData.codes = this.getCodes( shaderStage ); + stageData.directives = this.getDirectives( shaderStage ); + stageData.scopedArrays = this.getScopedArrays( shaderStage ); + + // + + let flow = '// code\n\n'; + flow += this.flowCode[ shaderStage ]; + + const flowNodes = this.flowNodes[ shaderStage ]; + const mainNode = flowNodes[ flowNodes.length - 1 ]; + + const outputNode = mainNode.outputNode; + const isOutputStruct = ( outputNode !== undefined && outputNode.isOutputStructNode === true ); + + for ( const node of flowNodes ) { + + const flowSlotData = this.getFlowData( node/*, shaderStage*/ ); + const slotName = node.name; + + if ( slotName ) { + + if ( flow.length > 0 ) flow += '\n'; + + flow += `\t// flow -> ${ slotName }\n\t`; + + } + + flow += `${ flowSlotData.code }\n\t`; + + if ( node === mainNode && shaderStage !== 'compute' ) { + + flow += '// result\n\n\t'; + + if ( shaderStage === 'vertex' ) { + + flow += `varyings.Vertex = ${ flowSlotData.result };`; + + } else if ( shaderStage === 'fragment' ) { + + if ( isOutputStruct ) { + + stageData.returnType = outputNode.nodeType; + + flow += `return ${ flowSlotData.result };`; + + } else { + + let structSnippet = '\t@location(0) color: vec4'; + + const builtins = this.getBuiltins( 'output' ); + + if ( builtins ) structSnippet += ',\n\t' + builtins; + + stageData.returnType = 'OutputStruct'; + stageData.structs += this._getWGSLStruct( 'OutputStruct', structSnippet ); + stageData.structs += '\nvar output : OutputStruct;\n\n'; + + flow += `output.color = ${ flowSlotData.result };\n\n\treturn output;`; + + } + + } + + } + + } + + stageData.flow = flow; + + + } + + if ( this.material !== null ) { + + this.vertexShader = this._getWGSLVertexCode( shadersData.vertex ); + this.fragmentShader = this._getWGSLFragmentCode( shadersData.fragment ); + + } else { + + this.computeShader = this._getWGSLComputeCode( shadersData.compute, ( this.object.workgroupSize || [ 64 ] ).join( ', ' ) ); + + } + + } + + getMethod( method, output = null ) { + + let wgslMethod; + + if ( output !== null ) { + + wgslMethod = this._getWGSLMethod( method + '_' + output ); + + } + + if ( wgslMethod === undefined ) { + + wgslMethod = this._getWGSLMethod( method ); + + } + + return wgslMethod || method; + + } + + getType( type ) { + + return wgslTypeLib[ type ] || type; + + } + + isAvailable( name ) { + + let result = supports[ name ]; + + if ( result === undefined ) { + + if ( name === 'float32Filterable' ) { + + result = this.renderer.hasFeature( 'float32-filterable' ); + + } + + supports[ name ] = result; + + } + + return result; + + } + + _getWGSLMethod( method ) { + + if ( wgslPolyfill[ method ] !== undefined ) { + + this._include( method ); + + } + + return wgslMethods[ method ]; + + } + + _include( name ) { + + const codeNode = wgslPolyfill[ name ]; + codeNode.build( this ); + + if ( this.currentFunctionNode !== null ) { + + this.currentFunctionNode.includes.push( codeNode ); + + } + + return codeNode; + + } + + _getWGSLVertexCode( shaderData ) { + + return `${ this.getSignature() } +// directives +${shaderData.directives} + +// uniforms +${shaderData.uniforms} + +// varyings +${shaderData.varyings} +var varyings : VaryingsStruct; + +// codes +${shaderData.codes} + +@vertex +fn main( ${shaderData.attributes} ) -> VaryingsStruct { + + // vars + ${shaderData.vars} + + // flow + ${shaderData.flow} + + return varyings; + +} +`; + + } + + _getWGSLFragmentCode( shaderData ) { + + return `${ this.getSignature() } +// global +${ diagnostics } + +// uniforms +${shaderData.uniforms} + +// structs +${shaderData.structs} + +// codes +${shaderData.codes} + +@fragment +fn main( ${shaderData.varyings} ) -> ${shaderData.returnType} { + + // vars + ${shaderData.vars} + + // flow + ${shaderData.flow} + +} +`; + + } + + _getWGSLComputeCode( shaderData, workgroupSize ) { + + return `${ this.getSignature() } +// directives +${shaderData.directives} + +// system +var instanceIndex : u32; + +// locals +${shaderData.scopedArrays} + +// uniforms +${shaderData.uniforms} + +// codes +${shaderData.codes} + +@compute @workgroup_size( ${workgroupSize} ) +fn main( ${shaderData.attributes} ) { + + // system + instanceIndex = id.x + id.y * numWorkgroups.x * u32(${workgroupSize}) + id.z * numWorkgroups.x * numWorkgroups.y * u32(${workgroupSize}); + + // vars + ${shaderData.vars} + + // flow + ${shaderData.flow} + +} +`; + + } + + _getWGSLStruct( name, vars ) { + + return ` +struct ${name} { +${vars} +};`; + + } + + _getWGSLStructBinding( name, vars, access, binding = 0, group = 0 ) { + + const structName = name + 'Struct'; + const structSnippet = this._getWGSLStruct( structName, vars ); + + return `${structSnippet} +@binding( ${binding} ) @group( ${group} ) +var<${access}> ${name} : ${structName};`; + + } + +} + +class WebGPUUtils { + + constructor( backend ) { + + this.backend = backend; + + } + + getCurrentDepthStencilFormat( renderContext ) { + + let format; + + if ( renderContext.depthTexture !== null ) { + + format = this.getTextureFormatGPU( renderContext.depthTexture ); + + } else if ( renderContext.depth && renderContext.stencil ) { + + format = GPUTextureFormat.Depth24PlusStencil8; + + } else if ( renderContext.depth ) { + + format = GPUTextureFormat.Depth24Plus; + + } + + return format; + + } + + getTextureFormatGPU( texture ) { + + return this.backend.get( texture ).format; + + } + + getCurrentColorFormat( renderContext ) { + + let format; + + if ( renderContext.textures !== null ) { + + format = this.getTextureFormatGPU( renderContext.textures[ 0 ] ); + + + } else { + + format = this.getPreferredCanvasFormat(); // default context format + + } + + return format; + + } + + getCurrentColorSpace( renderContext ) { + + if ( renderContext.textures !== null ) { + + return renderContext.textures[ 0 ].colorSpace; + + } + + return this.backend.renderer.outputColorSpace; + + } + + getPrimitiveTopology( object, material ) { + + if ( object.isPoints ) return GPUPrimitiveTopology.PointList; + else if ( object.isLineSegments || ( object.isMesh && material.wireframe === true ) ) return GPUPrimitiveTopology.LineList; + else if ( object.isLine ) return GPUPrimitiveTopology.LineStrip; + else if ( object.isMesh ) return GPUPrimitiveTopology.TriangleList; + + } + + getSampleCount( sampleCount ) { + + let count = 1; + + if ( sampleCount > 1 ) { + + // WebGPU only supports power-of-two sample counts and 2 is not a valid value + count = Math.pow( 2, Math.floor( Math.log2( sampleCount ) ) ); + + if ( count === 2 ) { + + count = 4; + + } + + } + + return count; + + } + + getSampleCountRenderContext( renderContext ) { + + if ( renderContext.textures !== null ) { + + return this.getSampleCount( renderContext.sampleCount ); + + } + + return this.getSampleCount( this.backend.renderer.samples ); + + } + + getPreferredCanvasFormat() { + + // TODO: Remove this check when Quest 34.5 is out + // https://github.com/mrdoob/three.js/pull/29221/files#r1731833949 + + if ( navigator.userAgent.includes( 'Quest' ) ) { + + return GPUTextureFormat.BGRA8Unorm; + + } else { + + return navigator.gpu.getPreferredCanvasFormat(); + + } + + } + +} + +const typedArraysToVertexFormatPrefix = new Map( [ + [ Int8Array, [ 'sint8', 'snorm8' ]], + [ Uint8Array, [ 'uint8', 'unorm8' ]], + [ Int16Array, [ 'sint16', 'snorm16' ]], + [ Uint16Array, [ 'uint16', 'unorm16' ]], + [ Int32Array, [ 'sint32', 'snorm32' ]], + [ Uint32Array, [ 'uint32', 'unorm32' ]], + [ Float32Array, [ 'float32', ]], +] ); + +const typedAttributeToVertexFormatPrefix = new Map( [ + [ Float16BufferAttribute, [ 'float16', ]], +] ); + +const typeArraysToVertexFormatPrefixForItemSize1 = new Map( [ + [ Int32Array, 'sint32' ], + [ Int16Array, 'sint32' ], // patch for INT16 + [ Uint32Array, 'uint32' ], + [ Uint16Array, 'uint32' ], // patch for UINT16 + [ Float32Array, 'float32' ] +] ); + +class WebGPUAttributeUtils { + + constructor( backend ) { + + this.backend = backend; + + } + + createAttribute( attribute, usage ) { + + const bufferAttribute = this._getBufferAttribute( attribute ); + + const backend = this.backend; + const bufferData = backend.get( bufferAttribute ); + + let buffer = bufferData.buffer; + + if ( buffer === undefined ) { + + const device = backend.device; + + let array = bufferAttribute.array; + + // patch for INT16 and UINT16 + if ( attribute.normalized === false && ( array.constructor === Int16Array || array.constructor === Uint16Array ) ) { + + const tempArray = new Uint32Array( array.length ); + for ( let i = 0; i < array.length; i ++ ) { + + tempArray[ i ] = array[ i ]; + + } + + array = tempArray; + + } + + bufferAttribute.array = array; + + if ( ( bufferAttribute.isStorageBufferAttribute || bufferAttribute.isStorageInstancedBufferAttribute ) && bufferAttribute.itemSize === 3 ) { + + array = new array.constructor( bufferAttribute.count * 4 ); + + for ( let i = 0; i < bufferAttribute.count; i ++ ) { + + array.set( bufferAttribute.array.subarray( i * 3, i * 3 + 3 ), i * 4 ); + + } + + // Update BufferAttribute + bufferAttribute.itemSize = 4; + bufferAttribute.array = array; + + } + + const size = array.byteLength + ( ( 4 - ( array.byteLength % 4 ) ) % 4 ); // ensure 4 byte alignment, see #20441 + + buffer = device.createBuffer( { + label: bufferAttribute.name, + size: size, + usage: usage, + mappedAtCreation: true + } ); + + new array.constructor( buffer.getMappedRange() ).set( array ); + + buffer.unmap(); + + bufferData.buffer = buffer; + + } + + } + + updateAttribute( attribute ) { + + const bufferAttribute = this._getBufferAttribute( attribute ); + + const backend = this.backend; + const device = backend.device; + + const buffer = backend.get( bufferAttribute ).buffer; + + const array = bufferAttribute.array; + const updateRanges = bufferAttribute.updateRanges; + + if ( updateRanges.length === 0 ) { + + // Not using update ranges + + device.queue.writeBuffer( + buffer, + 0, + array, + 0 + ); + + } else { + + for ( let i = 0, l = updateRanges.length; i < l; i ++ ) { + + const range = updateRanges[ i ]; + device.queue.writeBuffer( + buffer, + 0, + array, + range.start * array.BYTES_PER_ELEMENT, + range.count * array.BYTES_PER_ELEMENT + ); + + } + + bufferAttribute.clearUpdateRanges(); + + } + + } + + createShaderVertexBuffers( renderObject ) { + + const attributes = renderObject.getAttributes(); + const vertexBuffers = new Map(); + + for ( let slot = 0; slot < attributes.length; slot ++ ) { + + const geometryAttribute = attributes[ slot ]; + const bytesPerElement = geometryAttribute.array.BYTES_PER_ELEMENT; + const bufferAttribute = this._getBufferAttribute( geometryAttribute ); + + let vertexBufferLayout = vertexBuffers.get( bufferAttribute ); + + if ( vertexBufferLayout === undefined ) { + + let arrayStride, stepMode; + + if ( geometryAttribute.isInterleavedBufferAttribute === true ) { + + arrayStride = geometryAttribute.data.stride * bytesPerElement; + stepMode = geometryAttribute.data.isInstancedInterleavedBuffer ? GPUInputStepMode.Instance : GPUInputStepMode.Vertex; + + } else { + + arrayStride = geometryAttribute.itemSize * bytesPerElement; + stepMode = geometryAttribute.isInstancedBufferAttribute ? GPUInputStepMode.Instance : GPUInputStepMode.Vertex; + + } + + // patch for INT16 and UINT16 + if ( geometryAttribute.normalized === false && ( geometryAttribute.array.constructor === Int16Array || geometryAttribute.array.constructor === Uint16Array ) ) { + + arrayStride = 4; + + } + + vertexBufferLayout = { + arrayStride, + attributes: [], + stepMode + }; + + vertexBuffers.set( bufferAttribute, vertexBufferLayout ); + + } + + const format = this._getVertexFormat( geometryAttribute ); + const offset = ( geometryAttribute.isInterleavedBufferAttribute === true ) ? geometryAttribute.offset * bytesPerElement : 0; + + vertexBufferLayout.attributes.push( { + shaderLocation: slot, + offset, + format + } ); + + } + + return Array.from( vertexBuffers.values() ); + + } + + destroyAttribute( attribute ) { + + const backend = this.backend; + const data = backend.get( this._getBufferAttribute( attribute ) ); + + data.buffer.destroy(); + + backend.delete( attribute ); + + } + + async getArrayBufferAsync( attribute ) { + + const backend = this.backend; + const device = backend.device; + + const data = backend.get( this._getBufferAttribute( attribute ) ); + + const bufferGPU = data.buffer; + const size = bufferGPU.size; + + const readBufferGPU = device.createBuffer( { + label: attribute.name, + size, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ + } ); + + + const cmdEncoder = device.createCommandEncoder( {} ); + + cmdEncoder.copyBufferToBuffer( + bufferGPU, + 0, + readBufferGPU, + 0, + size + ); + + readBufferGPU.unmap(); + + const gpuCommands = cmdEncoder.finish(); + device.queue.submit( [ gpuCommands ] ); + + await readBufferGPU.mapAsync( GPUMapMode.READ ); + + const arrayBuffer = readBufferGPU.getMappedRange(); + + return arrayBuffer; + + } + + _getVertexFormat( geometryAttribute ) { + + const { itemSize, normalized } = geometryAttribute; + const ArrayType = geometryAttribute.array.constructor; + const AttributeType = geometryAttribute.constructor; + + let format; + + if ( itemSize == 1 ) { + + format = typeArraysToVertexFormatPrefixForItemSize1.get( ArrayType ); + + } else { + + const prefixOptions = typedAttributeToVertexFormatPrefix.get( AttributeType ) || typedArraysToVertexFormatPrefix.get( ArrayType ); + const prefix = prefixOptions[ normalized ? 1 : 0 ]; + + if ( prefix ) { + + const bytesPerUnit = ArrayType.BYTES_PER_ELEMENT * itemSize; + const paddedBytesPerUnit = Math.floor( ( bytesPerUnit + 3 ) / 4 ) * 4; + const paddedItemSize = paddedBytesPerUnit / ArrayType.BYTES_PER_ELEMENT; + + if ( paddedItemSize % 1 ) { + + throw new Error( 'THREE.WebGPUAttributeUtils: Bad vertex format item size.' ); + + } + + format = `${prefix}x${paddedItemSize}`; + + } + + } + + if ( ! format ) { + + console.error( 'THREE.WebGPUAttributeUtils: Vertex format not supported yet.' ); + + } + + return format; + + } + + _getBufferAttribute( attribute ) { + + if ( attribute.isInterleavedBufferAttribute ) attribute = attribute.data; + + return attribute; + + } + +} + +class WebGPUBindingUtils { + + constructor( backend ) { + + this.backend = backend; + this.bindGroupLayoutCache = new WeakMap(); + + } + + createBindingsLayout( bindGroup ) { + + const backend = this.backend; + const device = backend.device; + + const entries = []; + + let index = 0; + + for ( const binding of bindGroup.bindings ) { + + const bindingGPU = { + binding: index ++, + visibility: binding.visibility + }; + + if ( binding.isUniformBuffer || binding.isStorageBuffer ) { + + const buffer = {}; // GPUBufferBindingLayout + + if ( binding.isStorageBuffer ) { + + buffer.type = binding.access; + + } + + bindingGPU.buffer = buffer; + + } else if ( binding.isSampler ) { + + const sampler = {}; // GPUSamplerBindingLayout + + if ( binding.texture.isDepthTexture ) { + + if ( binding.texture.compareFunction !== null ) { + + sampler.type = 'comparison'; + + } + + } + + bindingGPU.sampler = sampler; + + } else if ( binding.isSampledTexture && binding.texture.isVideoTexture ) { + + bindingGPU.externalTexture = {}; // GPUExternalTextureBindingLayout + + } else if ( binding.isSampledTexture && binding.store ) { + + const format = this.backend.get( binding.texture ).texture.format; + const access = binding.access; + + bindingGPU.storageTexture = { format, access }; // GPUStorageTextureBindingLayout + + } else if ( binding.isSampledTexture ) { + + const texture = {}; // GPUTextureBindingLayout + + if ( binding.texture.isMultisampleRenderTargetTexture === true ) { + + texture.multisampled = true; + + } + + if ( binding.texture.isDepthTexture ) { + + texture.sampleType = GPUTextureSampleType.Depth; + + } else if ( binding.texture.isDataTexture || binding.texture.isDataArrayTexture || binding.texture.isData3DTexture ) { + + const type = binding.texture.type; + + if ( type === IntType ) { + + texture.sampleType = GPUTextureSampleType.SInt; + + } else if ( type === UnsignedIntType ) { + + texture.sampleType = GPUTextureSampleType.UInt; + + } else if ( type === FloatType ) { + + if ( this.backend.hasFeature( 'float32-filterable' ) ) { + + texture.sampleType = GPUTextureSampleType.Float; + + } else { + + texture.sampleType = GPUTextureSampleType.UnfilterableFloat; + + } + + } + + } + + if ( binding.isSampledCubeTexture ) { + + texture.viewDimension = GPUTextureViewDimension.Cube; + + } else if ( binding.texture.isDataArrayTexture || binding.texture.isCompressedArrayTexture ) { + + texture.viewDimension = GPUTextureViewDimension.TwoDArray; + + } else if ( binding.isSampledTexture3D ) { + + texture.viewDimension = GPUTextureViewDimension.ThreeD; + + } + + bindingGPU.texture = texture; + + } else { + + console.error( `WebGPUBindingUtils: Unsupported binding "${ binding }".` ); + + } + + entries.push( bindingGPU ); + + } + + return device.createBindGroupLayout( { entries } ); + + } + + createBindings( bindGroup ) { + + const { backend, bindGroupLayoutCache } = this; + const bindingsData = backend.get( bindGroup ); + + // setup (static) binding layout and (dynamic) binding group + + let bindLayoutGPU = bindGroupLayoutCache.get( bindGroup.bindingsReference ); + + if ( bindLayoutGPU === undefined ) { + + bindLayoutGPU = this.createBindingsLayout( bindGroup ); + bindGroupLayoutCache.set( bindGroup.bindingsReference, bindLayoutGPU ); + + } + + const bindGroupGPU = this.createBindGroup( bindGroup, bindLayoutGPU ); + + bindingsData.layout = bindLayoutGPU; + bindingsData.group = bindGroupGPU; + + } + + updateBinding( binding ) { + + const backend = this.backend; + const device = backend.device; + + const buffer = binding.buffer; + const bufferGPU = backend.get( binding ).buffer; + + device.queue.writeBuffer( bufferGPU, 0, buffer, 0 ); + + } + + createBindGroup( bindGroup, layoutGPU ) { + + const backend = this.backend; + const device = backend.device; + + let bindingPoint = 0; + const entriesGPU = []; + + for ( const binding of bindGroup.bindings ) { + + if ( binding.isUniformBuffer ) { + + const bindingData = backend.get( binding ); + + if ( bindingData.buffer === undefined ) { + + const byteLength = binding.byteLength; + + const usage = GPUBufferUsage.UNIFORM | GPUBufferUsage.COPY_DST; + + const bufferGPU = device.createBuffer( { + label: 'bindingBuffer_' + binding.name, + size: byteLength, + usage: usage + } ); + + bindingData.buffer = bufferGPU; + + } + + entriesGPU.push( { binding: bindingPoint, resource: { buffer: bindingData.buffer } } ); + + } else if ( binding.isStorageBuffer ) { + + const bindingData = backend.get( binding ); + + if ( bindingData.buffer === undefined ) { + + const attribute = binding.attribute; + //const usage = GPUBufferUsage.STORAGE | GPUBufferUsage.VERTEX | /*GPUBufferUsage.COPY_SRC |*/ GPUBufferUsage.COPY_DST; + + //backend.attributeUtils.createAttribute( attribute, usage ); // @TODO: Move it to universal renderer + + bindingData.buffer = backend.get( attribute ).buffer; + + } + + entriesGPU.push( { binding: bindingPoint, resource: { buffer: bindingData.buffer } } ); + + } else if ( binding.isSampler ) { + + const textureGPU = backend.get( binding.texture ); + + entriesGPU.push( { binding: bindingPoint, resource: textureGPU.sampler } ); + + } else if ( binding.isSampledTexture ) { + + const textureData = backend.get( binding.texture ); + + let resourceGPU; + + if ( textureData.externalTexture !== undefined ) { + + resourceGPU = device.importExternalTexture( { source: textureData.externalTexture } ); + + } else { + + const mipLevelCount = binding.store ? 1 : textureData.texture.mipLevelCount; + const propertyName = `view-${ textureData.texture.width }-${ textureData.texture.height }-${ mipLevelCount }`; + + resourceGPU = textureData[ propertyName ]; + + if ( resourceGPU === undefined ) { + + const aspectGPU = GPUTextureAspect.All; + + let dimensionViewGPU; + + if ( binding.isSampledCubeTexture ) { + + dimensionViewGPU = GPUTextureViewDimension.Cube; + + } else if ( binding.isSampledTexture3D ) { + + dimensionViewGPU = GPUTextureViewDimension.ThreeD; + + } else if ( binding.texture.isDataArrayTexture || binding.texture.isCompressedArrayTexture ) { + + dimensionViewGPU = GPUTextureViewDimension.TwoDArray; + + } else { + + dimensionViewGPU = GPUTextureViewDimension.TwoD; + + } + + resourceGPU = textureData[ propertyName ] = textureData.texture.createView( { aspect: aspectGPU, dimension: dimensionViewGPU, mipLevelCount } ); + + } + + } + + entriesGPU.push( { binding: bindingPoint, resource: resourceGPU } ); + + } + + bindingPoint ++; + + } + + return device.createBindGroup( { + label: 'bindGroup_' + bindGroup.name, + layout: layoutGPU, + entries: entriesGPU + } ); + + } + +} + +class WebGPUPipelineUtils { + + constructor( backend ) { + + this.backend = backend; + + } + + _getSampleCount( renderObjectContext ) { + + return this.backend.utils.getSampleCountRenderContext( renderObjectContext ); + + } + + createRenderPipeline( renderObject, promises ) { + + const { object, material, geometry, pipeline } = renderObject; + const { vertexProgram, fragmentProgram } = pipeline; + + const backend = this.backend; + const device = backend.device; + const utils = backend.utils; + + const pipelineData = backend.get( pipeline ); + + // bind group layouts + + const bindGroupLayouts = []; + + for ( const bindGroup of renderObject.getBindings() ) { + + const bindingsData = backend.get( bindGroup ); + + bindGroupLayouts.push( bindingsData.layout ); + + } + + // vertex buffers + + const vertexBuffers = backend.attributeUtils.createShaderVertexBuffers( renderObject ); + + // blending + + let blending; + + if ( material.transparent === true && material.blending !== NoBlending ) { + + blending = this._getBlending( material ); + + } + + // stencil + + let stencilFront = {}; + + if ( material.stencilWrite === true ) { + + stencilFront = { + compare: this._getStencilCompare( material ), + failOp: this._getStencilOperation( material.stencilFail ), + depthFailOp: this._getStencilOperation( material.stencilZFail ), + passOp: this._getStencilOperation( material.stencilZPass ) + }; + + } + + const colorWriteMask = this._getColorWriteMask( material ); + + const targets = []; + + if ( renderObject.context.textures !== null ) { + + const textures = renderObject.context.textures; + + for ( let i = 0; i < textures.length; i ++ ) { + + const colorFormat = utils.getTextureFormatGPU( textures[ i ] ); + + targets.push( { + format: colorFormat, + blend: blending, + writeMask: colorWriteMask + } ); + + } + + } else { + + const colorFormat = utils.getCurrentColorFormat( renderObject.context ); + + targets.push( { + format: colorFormat, + blend: blending, + writeMask: colorWriteMask + } ); + + } + + const vertexModule = backend.get( vertexProgram ).module; + const fragmentModule = backend.get( fragmentProgram ).module; + + const primitiveState = this._getPrimitiveState( object, geometry, material ); + const depthCompare = this._getDepthCompare( material ); + const depthStencilFormat = utils.getCurrentDepthStencilFormat( renderObject.context ); + + const sampleCount = this._getSampleCount( renderObject.context ); + + const pipelineDescriptor = { + label: `renderPipeline_${ material.name || material.type }_${ material.id }`, + vertex: Object.assign( {}, vertexModule, { buffers: vertexBuffers } ), + fragment: Object.assign( {}, fragmentModule, { targets } ), + primitive: primitiveState, + depthStencil: { + format: depthStencilFormat, + depthWriteEnabled: material.depthWrite, + depthCompare: depthCompare, + stencilFront: stencilFront, + stencilBack: {}, // three.js does not provide an API to configure the back function (gl.stencilFuncSeparate() was never used) + stencilReadMask: material.stencilFuncMask, + stencilWriteMask: material.stencilWriteMask + }, + multisample: { + count: sampleCount, + alphaToCoverageEnabled: material.alphaToCoverage && sampleCount > 1 + }, + layout: device.createPipelineLayout( { + bindGroupLayouts + } ) + }; + + if ( promises === null ) { + + pipelineData.pipeline = device.createRenderPipeline( pipelineDescriptor ); + + } else { + + const p = new Promise( ( resolve /*, reject*/ ) => { + + device.createRenderPipelineAsync( pipelineDescriptor ).then( pipeline => { + + pipelineData.pipeline = pipeline; + resolve(); + + } ); + + } ); + + promises.push( p ); + + } + + } + + createBundleEncoder( renderContext ) { + + const backend = this.backend; + const { utils, device } = backend; + + const depthStencilFormat = utils.getCurrentDepthStencilFormat( renderContext ); + const colorFormat = utils.getCurrentColorFormat( renderContext ); + const sampleCount = this._getSampleCount( renderContext ); + + const descriptor = { + label: 'renderBundleEncoder', + colorFormats: [ colorFormat ], + depthStencilFormat, + sampleCount + }; + + return device.createRenderBundleEncoder( descriptor ); + + } + + createComputePipeline( pipeline, bindings ) { + + const backend = this.backend; + const device = backend.device; + + const computeProgram = backend.get( pipeline.computeProgram ).module; + + const pipelineGPU = backend.get( pipeline ); + + // bind group layouts + + const bindGroupLayouts = []; + + for ( const bindingsGroup of bindings ) { + + const bindingsData = backend.get( bindingsGroup ); + + bindGroupLayouts.push( bindingsData.layout ); + + } + + pipelineGPU.pipeline = device.createComputePipeline( { + compute: computeProgram, + layout: device.createPipelineLayout( { + bindGroupLayouts + } ) + } ); + + } + + _getBlending( material ) { + + let color, alpha; + + const blending = material.blending; + const blendSrc = material.blendSrc; + const blendDst = material.blendDst; + const blendEquation = material.blendEquation; + + + if ( blending === CustomBlending ) { + + const blendSrcAlpha = material.blendSrcAlpha !== null ? material.blendSrcAlpha : blendSrc; + const blendDstAlpha = material.blendDstAlpha !== null ? material.blendDstAlpha : blendDst; + const blendEquationAlpha = material.blendEquationAlpha !== null ? material.blendEquationAlpha : blendEquation; + + color = { + srcFactor: this._getBlendFactor( blendSrc ), + dstFactor: this._getBlendFactor( blendDst ), + operation: this._getBlendOperation( blendEquation ) + }; + + alpha = { + srcFactor: this._getBlendFactor( blendSrcAlpha ), + dstFactor: this._getBlendFactor( blendDstAlpha ), + operation: this._getBlendOperation( blendEquationAlpha ) + }; + + } else { + + const premultipliedAlpha = material.premultipliedAlpha; + + const setBlend = ( srcRGB, dstRGB, srcAlpha, dstAlpha ) => { + + color = { + srcFactor: srcRGB, + dstFactor: dstRGB, + operation: GPUBlendOperation.Add + }; + + alpha = { + srcFactor: srcAlpha, + dstFactor: dstAlpha, + operation: GPUBlendOperation.Add + }; + + }; + + if ( premultipliedAlpha ) { + + switch ( blending ) { + + case NormalBlending: + setBlend( GPUBlendFactor.One, GPUBlendFactor.OneMinusSrcAlpha, GPUBlendFactor.One, GPUBlendFactor.OneMinusSrcAlpha ); + break; + + case AdditiveBlending: + setBlend( GPUBlendFactor.One, GPUBlendFactor.One, GPUBlendFactor.One, GPUBlendFactor.One ); + break; + + case SubtractiveBlending: + setBlend( GPUBlendFactor.Zero, GPUBlendFactor.OneMinusSrc, GPUBlendFactor.Zero, GPUBlendFactor.One ); + break; + + case MultiplyBlending: + setBlend( GPUBlendFactor.Zero, GPUBlendFactor.Src, GPUBlendFactor.Zero, GPUBlendFactor.SrcAlpha ); + break; + + } + + } else { + + switch ( blending ) { + + case NormalBlending: + setBlend( GPUBlendFactor.SrcAlpha, GPUBlendFactor.OneMinusSrcAlpha, GPUBlendFactor.One, GPUBlendFactor.OneMinusSrcAlpha ); + break; + + case AdditiveBlending: + setBlend( GPUBlendFactor.SrcAlpha, GPUBlendFactor.One, GPUBlendFactor.SrcAlpha, GPUBlendFactor.One ); + break; + + case SubtractiveBlending: + setBlend( GPUBlendFactor.Zero, GPUBlendFactor.OneMinusSrc, GPUBlendFactor.Zero, GPUBlendFactor.One ); + break; + + case MultiplyBlending: + setBlend( GPUBlendFactor.Zero, GPUBlendFactor.Src, GPUBlendFactor.Zero, GPUBlendFactor.Src ); + break; + + } + + } + + } + + if ( color !== undefined && alpha !== undefined ) { + + return { color, alpha }; + + } else { + + console.error( 'THREE.WebGPURenderer: Invalid blending: ', blending ); + + } + + } + + _getBlendFactor( blend ) { + + let blendFactor; + + switch ( blend ) { + + case ZeroFactor: + blendFactor = GPUBlendFactor.Zero; + break; + + case OneFactor: + blendFactor = GPUBlendFactor.One; + break; + + case SrcColorFactor: + blendFactor = GPUBlendFactor.Src; + break; + + case OneMinusSrcColorFactor: + blendFactor = GPUBlendFactor.OneMinusSrc; + break; + + case SrcAlphaFactor: + blendFactor = GPUBlendFactor.SrcAlpha; + break; + + case OneMinusSrcAlphaFactor: + blendFactor = GPUBlendFactor.OneMinusSrcAlpha; + break; + + case DstColorFactor: + blendFactor = GPUBlendFactor.Dst; + break; + + case OneMinusDstColorFactor: + blendFactor = GPUBlendFactor.OneMinusDstColor; + break; + + case DstAlphaFactor: + blendFactor = GPUBlendFactor.DstAlpha; + break; + + case OneMinusDstAlphaFactor: + blendFactor = GPUBlendFactor.OneMinusDstAlpha; + break; + + case SrcAlphaSaturateFactor: + blendFactor = GPUBlendFactor.SrcAlphaSaturated; + break; + + case BlendColorFactor: + blendFactor = GPUBlendFactor.Constant; + break; + + case OneMinusBlendColorFactor: + blendFactor = GPUBlendFactor.OneMinusConstant; + break; + + default: + console.error( 'THREE.WebGPURenderer: Blend factor not supported.', blend ); + + } + + return blendFactor; + + } + + _getStencilCompare( material ) { + + let stencilCompare; + + const stencilFunc = material.stencilFunc; + + switch ( stencilFunc ) { + + case NeverStencilFunc: + stencilCompare = GPUCompareFunction.Never; + break; + + case AlwaysStencilFunc: + stencilCompare = GPUCompareFunction.Always; + break; + + case LessStencilFunc: + stencilCompare = GPUCompareFunction.Less; + break; + + case LessEqualStencilFunc: + stencilCompare = GPUCompareFunction.LessEqual; + break; + + case EqualStencilFunc: + stencilCompare = GPUCompareFunction.Equal; + break; + + case GreaterEqualStencilFunc: + stencilCompare = GPUCompareFunction.GreaterEqual; + break; + + case GreaterStencilFunc: + stencilCompare = GPUCompareFunction.Greater; + break; + + case NotEqualStencilFunc: + stencilCompare = GPUCompareFunction.NotEqual; + break; + + default: + console.error( 'THREE.WebGPURenderer: Invalid stencil function.', stencilFunc ); + + } + + return stencilCompare; + + } + + _getStencilOperation( op ) { + + let stencilOperation; + + switch ( op ) { + + case KeepStencilOp: + stencilOperation = GPUStencilOperation.Keep; + break; + + case ZeroStencilOp: + stencilOperation = GPUStencilOperation.Zero; + break; + + case ReplaceStencilOp: + stencilOperation = GPUStencilOperation.Replace; + break; + + case InvertStencilOp: + stencilOperation = GPUStencilOperation.Invert; + break; + + case IncrementStencilOp: + stencilOperation = GPUStencilOperation.IncrementClamp; + break; + + case DecrementStencilOp: + stencilOperation = GPUStencilOperation.DecrementClamp; + break; + + case IncrementWrapStencilOp: + stencilOperation = GPUStencilOperation.IncrementWrap; + break; + + case DecrementWrapStencilOp: + stencilOperation = GPUStencilOperation.DecrementWrap; + break; + + default: + console.error( 'THREE.WebGPURenderer: Invalid stencil operation.', stencilOperation ); + + } + + return stencilOperation; + + } + + _getBlendOperation( blendEquation ) { + + let blendOperation; + + switch ( blendEquation ) { + + case AddEquation: + blendOperation = GPUBlendOperation.Add; + break; + + case SubtractEquation: + blendOperation = GPUBlendOperation.Subtract; + break; + + case ReverseSubtractEquation: + blendOperation = GPUBlendOperation.ReverseSubtract; + break; + + case MinEquation: + blendOperation = GPUBlendOperation.Min; + break; + + case MaxEquation: + blendOperation = GPUBlendOperation.Max; + break; + + default: + console.error( 'THREE.WebGPUPipelineUtils: Blend equation not supported.', blendEquation ); + + } + + return blendOperation; + + } + + _getPrimitiveState( object, geometry, material ) { + + const descriptor = {}; + const utils = this.backend.utils; + + descriptor.topology = utils.getPrimitiveTopology( object, material ); + + if ( geometry.index !== null && object.isLine === true && object.isLineSegments !== true ) { + + descriptor.stripIndexFormat = ( geometry.index.array instanceof Uint16Array ) ? GPUIndexFormat.Uint16 : GPUIndexFormat.Uint32; + + } + + switch ( material.side ) { + + case FrontSide: + descriptor.frontFace = GPUFrontFace.CCW; + descriptor.cullMode = GPUCullMode.Back; + break; + + case BackSide: + descriptor.frontFace = GPUFrontFace.CCW; + descriptor.cullMode = GPUCullMode.Front; + break; + + case DoubleSide: + descriptor.frontFace = GPUFrontFace.CCW; + descriptor.cullMode = GPUCullMode.None; + break; + + default: + console.error( 'THREE.WebGPUPipelineUtils: Unknown material.side value.', material.side ); + break; + + } + + return descriptor; + + } + + _getColorWriteMask( material ) { + + return ( material.colorWrite === true ) ? GPUColorWriteFlags.All : GPUColorWriteFlags.None; + + } + + _getDepthCompare( material ) { + + let depthCompare; + + if ( material.depthTest === false ) { + + depthCompare = GPUCompareFunction.Always; + + } else { + + const depthFunc = material.depthFunc; + + switch ( depthFunc ) { + + case NeverDepth: + depthCompare = GPUCompareFunction.Never; + break; + + case AlwaysDepth: + depthCompare = GPUCompareFunction.Always; + break; + + case LessDepth: + depthCompare = GPUCompareFunction.Less; + break; + + case LessEqualDepth: + depthCompare = GPUCompareFunction.LessEqual; + break; + + case EqualDepth: + depthCompare = GPUCompareFunction.Equal; + break; + + case GreaterEqualDepth: + depthCompare = GPUCompareFunction.GreaterEqual; + break; + + case GreaterDepth: + depthCompare = GPUCompareFunction.Greater; + break; + + case NotEqualDepth: + depthCompare = GPUCompareFunction.NotEqual; + break; + + default: + console.error( 'THREE.WebGPUPipelineUtils: Invalid depth function.', depthFunc ); + + } + + } + + return depthCompare; + + } + +} + +/*// debugger tools +import 'https://greggman.github.io/webgpu-avoid-redundant-state-setting/webgpu-check-redundant-state-setting.js'; +//*/ + + +// + +class WebGPUBackend extends Backend { + + constructor( parameters = {} ) { + + super( parameters ); + + this.isWebGPUBackend = true; + + // some parameters require default values other than "undefined" + this.parameters.alpha = ( parameters.alpha === undefined ) ? true : parameters.alpha; + + this.parameters.requiredLimits = ( parameters.requiredLimits === undefined ) ? {} : parameters.requiredLimits; + + this.trackTimestamp = ( parameters.trackTimestamp === true ); + + this.device = null; + this.context = null; + this.colorBuffer = null; + this.defaultRenderPassdescriptor = null; + + this.utils = new WebGPUUtils( this ); + this.attributeUtils = new WebGPUAttributeUtils( this ); + this.bindingUtils = new WebGPUBindingUtils( this ); + this.pipelineUtils = new WebGPUPipelineUtils( this ); + this.textureUtils = new WebGPUTextureUtils( this ); + this.occludedResolveCache = new Map(); + + } + + async init( renderer ) { + + await super.init( renderer ); + + // + + const parameters = this.parameters; + + // create the device if it is not passed with parameters + + let device; + + if ( parameters.device === undefined ) { + + const adapterOptions = { + powerPreference: parameters.powerPreference + }; + + const adapter = await navigator.gpu.requestAdapter( adapterOptions ); + + if ( adapter === null ) { + + throw new Error( 'WebGPUBackend: Unable to create WebGPU adapter.' ); + + } + + // feature support + + const features = Object.values( GPUFeatureName ); + + const supportedFeatures = []; + + for ( const name of features ) { + + if ( adapter.features.has( name ) ) { + + supportedFeatures.push( name ); + + } + + } + + const deviceDescriptor = { + requiredFeatures: supportedFeatures, + requiredLimits: parameters.requiredLimits + }; + + device = await adapter.requestDevice( deviceDescriptor ); + + } else { + + device = parameters.device; + + } + + const context = ( parameters.context !== undefined ) ? parameters.context : renderer.domElement.getContext( 'webgpu' ); + + this.device = device; + this.context = context; + + const alphaMode = parameters.alpha ? 'premultiplied' : 'opaque'; + + this.trackTimestamp = this.trackTimestamp && this.hasFeature( GPUFeatureName.TimestampQuery ); + + this.context.configure( { + device: this.device, + format: this.utils.getPreferredCanvasFormat(), + usage: GPUTextureUsage.RENDER_ATTACHMENT | GPUTextureUsage.COPY_SRC, + alphaMode: alphaMode + } ); + + this.updateSize(); + + } + + get coordinateSystem() { + + return WebGPUCoordinateSystem; + + } + + async getArrayBufferAsync( attribute ) { + + return await this.attributeUtils.getArrayBufferAsync( attribute ); + + } + + getContext() { + + return this.context; + + } + + _getDefaultRenderPassDescriptor() { + + let descriptor = this.defaultRenderPassdescriptor; + + if ( descriptor === null ) { + + const renderer = this.renderer; + + descriptor = { + colorAttachments: [ { + view: null + } ], + depthStencilAttachment: { + view: this.textureUtils.getDepthBuffer( renderer.depth, renderer.stencil ).createView() + } + }; + + const colorAttachment = descriptor.colorAttachments[ 0 ]; + + if ( this.renderer.samples > 0 ) { + + colorAttachment.view = this.colorBuffer.createView(); + + } else { + + colorAttachment.resolveTarget = undefined; + + } + + this.defaultRenderPassdescriptor = descriptor; + + } + + const colorAttachment = descriptor.colorAttachments[ 0 ]; + + if ( this.renderer.samples > 0 ) { + + colorAttachment.resolveTarget = this.context.getCurrentTexture().createView(); + + } else { + + colorAttachment.view = this.context.getCurrentTexture().createView(); + + } + + return descriptor; + + } + + _getRenderPassDescriptor( renderContext ) { + + const renderTarget = renderContext.renderTarget; + const renderTargetData = this.get( renderTarget ); + + let descriptors = renderTargetData.descriptors; + + if ( descriptors === undefined || + renderTargetData.width !== renderTarget.width || + renderTargetData.height !== renderTarget.height || + renderTargetData.activeMipmapLevel !== renderTarget.activeMipmapLevel || + renderTargetData.samples !== renderTarget.samples + ) { + + descriptors = {}; + + renderTargetData.descriptors = descriptors; + + // dispose + + const onDispose = () => { + + renderTarget.removeEventListener( 'dispose', onDispose ); + + this.delete( renderTarget ); + + }; + + renderTarget.addEventListener( 'dispose', onDispose ); + + } + + const cacheKey = renderContext.getCacheKey(); + + let descriptor = descriptors[ cacheKey ]; + + if ( descriptor === undefined ) { + + const textures = renderContext.textures; + const colorAttachments = []; + + for ( let i = 0; i < textures.length; i ++ ) { + + const textureData = this.get( textures[ i ] ); + + const textureView = textureData.texture.createView( { + baseMipLevel: renderContext.activeMipmapLevel, + mipLevelCount: 1, + baseArrayLayer: renderContext.activeCubeFace, + dimension: GPUTextureViewDimension.TwoD + } ); + + let view, resolveTarget; + + if ( textureData.msaaTexture !== undefined ) { + + view = textureData.msaaTexture.createView(); + resolveTarget = textureView; + + } else { + + view = textureView; + resolveTarget = undefined; + + } + + colorAttachments.push( { + view, + resolveTarget, + loadOp: GPULoadOp.Load, + storeOp: GPUStoreOp.Store + } ); + + } + + const depthTextureData = this.get( renderContext.depthTexture ); + + const depthStencilAttachment = { + view: depthTextureData.texture.createView() + }; + + descriptor = { + colorAttachments, + depthStencilAttachment + }; + + descriptors[ cacheKey ] = descriptor; + + renderTargetData.width = renderTarget.width; + renderTargetData.height = renderTarget.height; + renderTargetData.samples = renderTarget.samples; + renderTargetData.activeMipmapLevel = renderTarget.activeMipmapLevel; + + } + + return descriptor; + + } + + beginRender( renderContext ) { + + const renderContextData = this.get( renderContext ); + + const device = this.device; + const occlusionQueryCount = renderContext.occlusionQueryCount; + + let occlusionQuerySet; + + if ( occlusionQueryCount > 0 ) { + + if ( renderContextData.currentOcclusionQuerySet ) renderContextData.currentOcclusionQuerySet.destroy(); + if ( renderContextData.currentOcclusionQueryBuffer ) renderContextData.currentOcclusionQueryBuffer.destroy(); + + // Get a reference to the array of objects with queries. The renderContextData property + // can be changed by another render pass before the buffer.mapAsyc() completes. + renderContextData.currentOcclusionQuerySet = renderContextData.occlusionQuerySet; + renderContextData.currentOcclusionQueryBuffer = renderContextData.occlusionQueryBuffer; + renderContextData.currentOcclusionQueryObjects = renderContextData.occlusionQueryObjects; + + // + + occlusionQuerySet = device.createQuerySet( { type: 'occlusion', count: occlusionQueryCount } ); + + renderContextData.occlusionQuerySet = occlusionQuerySet; + renderContextData.occlusionQueryIndex = 0; + renderContextData.occlusionQueryObjects = new Array( occlusionQueryCount ); + + renderContextData.lastOcclusionObject = null; + + } + + let descriptor; + + if ( renderContext.textures === null ) { + + descriptor = this._getDefaultRenderPassDescriptor(); + + } else { + + descriptor = this._getRenderPassDescriptor( renderContext ); + + } + + this.initTimestampQuery( renderContext, descriptor ); + + descriptor.occlusionQuerySet = occlusionQuerySet; + + const depthStencilAttachment = descriptor.depthStencilAttachment; + + if ( renderContext.textures !== null ) { + + const colorAttachments = descriptor.colorAttachments; + + for ( let i = 0; i < colorAttachments.length; i ++ ) { + + const colorAttachment = colorAttachments[ i ]; + + if ( renderContext.clearColor ) { + + colorAttachment.clearValue = i === 0 ? renderContext.clearColorValue : { r: 0, g: 0, b: 0, a: 1 }; + colorAttachment.loadOp = GPULoadOp.Clear; + colorAttachment.storeOp = GPUStoreOp.Store; + + } else { + + colorAttachment.loadOp = GPULoadOp.Load; + colorAttachment.storeOp = GPUStoreOp.Store; + + } + + } + + } else { + + const colorAttachment = descriptor.colorAttachments[ 0 ]; + + if ( renderContext.clearColor ) { + + colorAttachment.clearValue = renderContext.clearColorValue; + colorAttachment.loadOp = GPULoadOp.Clear; + colorAttachment.storeOp = GPUStoreOp.Store; + + } else { + + colorAttachment.loadOp = GPULoadOp.Load; + colorAttachment.storeOp = GPUStoreOp.Store; + + } + + } + + // + + if ( renderContext.depth ) { + + if ( renderContext.clearDepth ) { + + depthStencilAttachment.depthClearValue = renderContext.clearDepthValue; + depthStencilAttachment.depthLoadOp = GPULoadOp.Clear; + depthStencilAttachment.depthStoreOp = GPUStoreOp.Store; + + } else { + + depthStencilAttachment.depthLoadOp = GPULoadOp.Load; + depthStencilAttachment.depthStoreOp = GPUStoreOp.Store; + + } + + } + + if ( renderContext.stencil ) { + + if ( renderContext.clearStencil ) { + + depthStencilAttachment.stencilClearValue = renderContext.clearStencilValue; + depthStencilAttachment.stencilLoadOp = GPULoadOp.Clear; + depthStencilAttachment.stencilStoreOp = GPUStoreOp.Store; + + } else { + + depthStencilAttachment.stencilLoadOp = GPULoadOp.Load; + depthStencilAttachment.stencilStoreOp = GPUStoreOp.Store; + + } + + } + + // + + const encoder = device.createCommandEncoder( { label: 'renderContext_' + renderContext.id } ); + const currentPass = encoder.beginRenderPass( descriptor ); + + // + + renderContextData.descriptor = descriptor; + renderContextData.encoder = encoder; + renderContextData.currentPass = currentPass; + renderContextData.currentSets = { attributes: {}, bindingGroups: [], pipeline: null, index: null }; + renderContextData.renderBundles = []; + + // + + if ( renderContext.viewport ) { + + this.updateViewport( renderContext ); + + } + + if ( renderContext.scissor ) { + + const { x, y, width, height } = renderContext.scissorValue; + + currentPass.setScissorRect( x, y, width, height ); + + } + + } + + finishRender( renderContext ) { + + const renderContextData = this.get( renderContext ); + const occlusionQueryCount = renderContext.occlusionQueryCount; + + if ( renderContextData.renderBundles.length > 0 ) { + + renderContextData.currentPass.executeBundles( renderContextData.renderBundles ); + + } + + if ( occlusionQueryCount > renderContextData.occlusionQueryIndex ) { + + renderContextData.currentPass.endOcclusionQuery(); + + } + + renderContextData.currentPass.end(); + + if ( occlusionQueryCount > 0 ) { + + const bufferSize = occlusionQueryCount * 8; // 8 byte entries for query results + + // + + let queryResolveBuffer = this.occludedResolveCache.get( bufferSize ); + + if ( queryResolveBuffer === undefined ) { + + queryResolveBuffer = this.device.createBuffer( + { + size: bufferSize, + usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC + } + ); + + this.occludedResolveCache.set( bufferSize, queryResolveBuffer ); + + } + + // + + const readBuffer = this.device.createBuffer( + { + size: bufferSize, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ + } + ); + + // two buffers required here - WebGPU doesn't allow usage of QUERY_RESOLVE & MAP_READ to be combined + renderContextData.encoder.resolveQuerySet( renderContextData.occlusionQuerySet, 0, occlusionQueryCount, queryResolveBuffer, 0 ); + renderContextData.encoder.copyBufferToBuffer( queryResolveBuffer, 0, readBuffer, 0, bufferSize ); + + renderContextData.occlusionQueryBuffer = readBuffer; + + // + + this.resolveOccludedAsync( renderContext ); + + } + + this.prepareTimestampBuffer( renderContext, renderContextData.encoder ); + + this.device.queue.submit( [ renderContextData.encoder.finish() ] ); + + + // + + if ( renderContext.textures !== null ) { + + const textures = renderContext.textures; + + for ( let i = 0; i < textures.length; i ++ ) { + + const texture = textures[ i ]; + + if ( texture.generateMipmaps === true ) { + + this.textureUtils.generateMipmaps( texture ); + + } + + } + + } + + } + + isOccluded( renderContext, object ) { + + const renderContextData = this.get( renderContext ); + + return renderContextData.occluded && renderContextData.occluded.has( object ); + + } + + async resolveOccludedAsync( renderContext ) { + + const renderContextData = this.get( renderContext ); + + // handle occlusion query results + + const { currentOcclusionQueryBuffer, currentOcclusionQueryObjects } = renderContextData; + + if ( currentOcclusionQueryBuffer && currentOcclusionQueryObjects ) { + + const occluded = new WeakSet(); + + renderContextData.currentOcclusionQueryObjects = null; + renderContextData.currentOcclusionQueryBuffer = null; + + await currentOcclusionQueryBuffer.mapAsync( GPUMapMode.READ ); + + const buffer = currentOcclusionQueryBuffer.getMappedRange(); + const results = new BigUint64Array( buffer ); + + for ( let i = 0; i < currentOcclusionQueryObjects.length; i ++ ) { + + if ( results[ i ] !== BigInt( 0 ) ) { + + occluded.add( currentOcclusionQueryObjects[ i ] ); + + } + + } + + currentOcclusionQueryBuffer.destroy(); + + renderContextData.occluded = occluded; + + } + + } + + updateViewport( renderContext ) { + + const { currentPass } = this.get( renderContext ); + const { x, y, width, height, minDepth, maxDepth } = renderContext.viewportValue; + + currentPass.setViewport( x, y, width, height, minDepth, maxDepth ); + + } + + clear( color, depth, stencil, renderTargetData = null ) { + + const device = this.device; + const renderer = this.renderer; + + let colorAttachments = []; + + let depthStencilAttachment; + let clearValue; + + let supportsDepth; + let supportsStencil; + + if ( color ) { + + const clearColor = this.getClearColor(); + + if ( this.renderer.alpha === true ) { + + // premultiply alpha + + const a = clearColor.a; + + clearValue = { r: clearColor.r * a, g: clearColor.g * a, b: clearColor.b * a, a: a }; + + } else { + + clearValue = { r: clearColor.r, g: clearColor.g, b: clearColor.b, a: clearColor.a }; + + } + + } + + if ( renderTargetData === null ) { + + supportsDepth = renderer.depth; + supportsStencil = renderer.stencil; + + const descriptor = this._getDefaultRenderPassDescriptor(); + + if ( color ) { + + colorAttachments = descriptor.colorAttachments; + + const colorAttachment = colorAttachments[ 0 ]; + + colorAttachment.clearValue = clearValue; + colorAttachment.loadOp = GPULoadOp.Clear; + colorAttachment.storeOp = GPUStoreOp.Store; + + } + + if ( supportsDepth || supportsStencil ) { + + depthStencilAttachment = descriptor.depthStencilAttachment; + + } + + } else { + + supportsDepth = renderTargetData.depth; + supportsStencil = renderTargetData.stencil; + + if ( color ) { + + for ( const texture of renderTargetData.textures ) { + + const textureData = this.get( texture ); + const textureView = textureData.texture.createView(); + + let view, resolveTarget; + + if ( textureData.msaaTexture !== undefined ) { + + view = textureData.msaaTexture.createView(); + resolveTarget = textureView; + + } else { + + view = textureView; + resolveTarget = undefined; + + } + + colorAttachments.push( { + view, + resolveTarget, + clearValue, + loadOp: GPULoadOp.Clear, + storeOp: GPUStoreOp.Store + } ); + + } + + } + + if ( supportsDepth || supportsStencil ) { + + const depthTextureData = this.get( renderTargetData.depthTexture ); + + depthStencilAttachment = { + view: depthTextureData.texture.createView() + }; + + } + + } + + // + + if ( supportsDepth ) { + + if ( depth ) { + + depthStencilAttachment.depthLoadOp = GPULoadOp.Clear; + depthStencilAttachment.depthClearValue = renderer.getClearDepth(); + depthStencilAttachment.depthStoreOp = GPUStoreOp.Store; + + } else { + + depthStencilAttachment.depthLoadOp = GPULoadOp.Load; + depthStencilAttachment.depthStoreOp = GPUStoreOp.Store; + + } + + } + + // + + if ( supportsStencil ) { + + if ( stencil ) { + + depthStencilAttachment.stencilLoadOp = GPULoadOp.Clear; + depthStencilAttachment.stencilClearValue = renderer.getClearStencil(); + depthStencilAttachment.stencilStoreOp = GPUStoreOp.Store; + + } else { + + depthStencilAttachment.stencilLoadOp = GPULoadOp.Load; + depthStencilAttachment.stencilStoreOp = GPUStoreOp.Store; + + } + + } + + // + + const encoder = device.createCommandEncoder( {} ); + const currentPass = encoder.beginRenderPass( { + colorAttachments, + depthStencilAttachment + } ); + + currentPass.end(); + + device.queue.submit( [ encoder.finish() ] ); + + } + + // compute + + beginCompute( computeGroup ) { + + const groupGPU = this.get( computeGroup ); + + + const descriptor = {}; + + this.initTimestampQuery( computeGroup, descriptor ); + + groupGPU.cmdEncoderGPU = this.device.createCommandEncoder(); + + groupGPU.passEncoderGPU = groupGPU.cmdEncoderGPU.beginComputePass( descriptor ); + + } + + compute( computeGroup, computeNode, bindings, pipeline ) { + + const { passEncoderGPU } = this.get( computeGroup ); + + // pipeline + + const pipelineGPU = this.get( pipeline ).pipeline; + passEncoderGPU.setPipeline( pipelineGPU ); + + // bind groups + + for ( let i = 0, l = bindings.length; i < l; i ++ ) { + + const bindGroup = bindings[ i ]; + const bindingsData = this.get( bindGroup ); + + passEncoderGPU.setBindGroup( i, bindingsData.group ); + + } + + const maxComputeWorkgroupsPerDimension = this.device.limits.maxComputeWorkgroupsPerDimension; + + const computeNodeData = this.get( computeNode ); + + if ( computeNodeData.dispatchSize === undefined ) computeNodeData.dispatchSize = { x: 0, y: 1, z: 1 }; + + const { dispatchSize } = computeNodeData; + + if ( computeNode.dispatchCount > maxComputeWorkgroupsPerDimension ) { + + dispatchSize.x = Math.min( computeNode.dispatchCount, maxComputeWorkgroupsPerDimension ); + dispatchSize.y = Math.ceil( computeNode.dispatchCount / maxComputeWorkgroupsPerDimension ); + + } else { + + dispatchSize.x = computeNode.dispatchCount; + + } + + passEncoderGPU.dispatchWorkgroups( + dispatchSize.x, + dispatchSize.y, + dispatchSize.z + ); + + } + + finishCompute( computeGroup ) { + + const groupData = this.get( computeGroup ); + + groupData.passEncoderGPU.end(); + + this.prepareTimestampBuffer( computeGroup, groupData.cmdEncoderGPU ); + + this.device.queue.submit( [ groupData.cmdEncoderGPU.finish() ] ); + + } + + // render object + + draw( renderObject, info ) { + + const { object, context, pipeline } = renderObject; + const bindings = renderObject.getBindings(); + const renderContextData = this.get( context ); + const pipelineGPU = this.get( pipeline ).pipeline; + const currentSets = renderContextData.currentSets; + const passEncoderGPU = renderContextData.currentPass; + + const drawParms = renderObject.getDrawParameters(); + + if ( drawParms === null ) return; + + // pipeline + + if ( currentSets.pipeline !== pipelineGPU ) { + + passEncoderGPU.setPipeline( pipelineGPU ); + + currentSets.pipeline = pipelineGPU; + + } + + // bind groups + + const currentBindingGroups = currentSets.bindingGroups; + + for ( let i = 0, l = bindings.length; i < l; i ++ ) { + + const bindGroup = bindings[ i ]; + const bindingsData = this.get( bindGroup ); + + if ( currentBindingGroups[ bindGroup.index ] !== bindGroup.id ) { + + passEncoderGPU.setBindGroup( bindGroup.index, bindingsData.group ); + currentBindingGroups[ bindGroup.index ] = bindGroup.id; + + } + + } + + // attributes + + const index = renderObject.getIndex(); + + const hasIndex = ( index !== null ); + + // index + + if ( hasIndex === true ) { + + if ( currentSets.index !== index ) { + + const buffer = this.get( index ).buffer; + const indexFormat = ( index.array instanceof Uint16Array ) ? GPUIndexFormat.Uint16 : GPUIndexFormat.Uint32; + + passEncoderGPU.setIndexBuffer( buffer, indexFormat ); + + currentSets.index = index; + + } + + } + + // vertex buffers + + const vertexBuffers = renderObject.getVertexBuffers(); + + for ( let i = 0, l = vertexBuffers.length; i < l; i ++ ) { + + const vertexBuffer = vertexBuffers[ i ]; + + if ( currentSets.attributes[ i ] !== vertexBuffer ) { + + const buffer = this.get( vertexBuffer ).buffer; + passEncoderGPU.setVertexBuffer( i, buffer ); + + currentSets.attributes[ i ] = vertexBuffer; + + } + + } + + // occlusion queries - handle multiple consecutive draw calls for an object + + if ( renderContextData.occlusionQuerySet !== undefined ) { + + const lastObject = renderContextData.lastOcclusionObject; + + if ( lastObject !== object ) { + + if ( lastObject !== null && lastObject.occlusionTest === true ) { + + passEncoderGPU.endOcclusionQuery(); + renderContextData.occlusionQueryIndex ++; + + } + + if ( object.occlusionTest === true ) { + + passEncoderGPU.beginOcclusionQuery( renderContextData.occlusionQueryIndex ); + renderContextData.occlusionQueryObjects[ renderContextData.occlusionQueryIndex ] = object; + + } + + renderContextData.lastOcclusionObject = object; + + } + + } + + // draw + + if ( object.isBatchedMesh === true ) { + + const starts = object._multiDrawStarts; + const counts = object._multiDrawCounts; + const drawCount = object._multiDrawCount; + const drawInstances = object._multiDrawInstances; + + const bytesPerElement = hasIndex ? index.array.BYTES_PER_ELEMENT : 1; + + for ( let i = 0; i < drawCount; i ++ ) { + + const count = drawInstances ? drawInstances[ i ] : 1; + const firstInstance = count > 1 ? 0 : i; + + passEncoderGPU.drawIndexed( counts[ i ], count, starts[ i ] / bytesPerElement, 0, firstInstance ); + + } + + } else if ( hasIndex === true ) { + + const { vertexCount: indexCount, instanceCount, firstVertex: firstIndex } = drawParms; + + passEncoderGPU.drawIndexed( indexCount, instanceCount, firstIndex, 0, 0 ); + + info.update( object, indexCount, instanceCount ); + + } else { + + const { vertexCount, instanceCount, firstVertex } = drawParms; + + passEncoderGPU.draw( vertexCount, instanceCount, firstVertex, 0 ); + + info.update( object, vertexCount, instanceCount ); + + } + + } + + // cache key + + needsRenderUpdate( renderObject ) { + + const data = this.get( renderObject ); + + const { object, material } = renderObject; + + const utils = this.utils; + + const sampleCount = utils.getSampleCountRenderContext( renderObject.context ); + const colorSpace = utils.getCurrentColorSpace( renderObject.context ); + const colorFormat = utils.getCurrentColorFormat( renderObject.context ); + const depthStencilFormat = utils.getCurrentDepthStencilFormat( renderObject.context ); + const primitiveTopology = utils.getPrimitiveTopology( object, material ); + + let needsUpdate = false; + + if ( data.material !== material || data.materialVersion !== material.version || + data.transparent !== material.transparent || data.blending !== material.blending || data.premultipliedAlpha !== material.premultipliedAlpha || + data.blendSrc !== material.blendSrc || data.blendDst !== material.blendDst || data.blendEquation !== material.blendEquation || + data.blendSrcAlpha !== material.blendSrcAlpha || data.blendDstAlpha !== material.blendDstAlpha || data.blendEquationAlpha !== material.blendEquationAlpha || + data.colorWrite !== material.colorWrite || data.depthWrite !== material.depthWrite || data.depthTest !== material.depthTest || data.depthFunc !== material.depthFunc || + data.stencilWrite !== material.stencilWrite || data.stencilFunc !== material.stencilFunc || + data.stencilFail !== material.stencilFail || data.stencilZFail !== material.stencilZFail || data.stencilZPass !== material.stencilZPass || + data.stencilFuncMask !== material.stencilFuncMask || data.stencilWriteMask !== material.stencilWriteMask || + data.side !== material.side || data.alphaToCoverage !== material.alphaToCoverage || + data.sampleCount !== sampleCount || data.colorSpace !== colorSpace || + data.colorFormat !== colorFormat || data.depthStencilFormat !== depthStencilFormat || + data.primitiveTopology !== primitiveTopology || + data.clippingContextCacheKey !== renderObject.clippingContext.cacheKey + ) { + + data.material = material; data.materialVersion = material.version; + data.transparent = material.transparent; data.blending = material.blending; data.premultipliedAlpha = material.premultipliedAlpha; + data.blendSrc = material.blendSrc; data.blendDst = material.blendDst; data.blendEquation = material.blendEquation; + data.blendSrcAlpha = material.blendSrcAlpha; data.blendDstAlpha = material.blendDstAlpha; data.blendEquationAlpha = material.blendEquationAlpha; + data.colorWrite = material.colorWrite; + data.depthWrite = material.depthWrite; data.depthTest = material.depthTest; data.depthFunc = material.depthFunc; + data.stencilWrite = material.stencilWrite; data.stencilFunc = material.stencilFunc; + data.stencilFail = material.stencilFail; data.stencilZFail = material.stencilZFail; data.stencilZPass = material.stencilZPass; + data.stencilFuncMask = material.stencilFuncMask; data.stencilWriteMask = material.stencilWriteMask; + data.side = material.side; data.alphaToCoverage = material.alphaToCoverage; + data.sampleCount = sampleCount; + data.colorSpace = colorSpace; + data.colorFormat = colorFormat; + data.depthStencilFormat = depthStencilFormat; + data.primitiveTopology = primitiveTopology; + data.clippingContextCacheKey = renderObject.clippingContext.cacheKey; + + needsUpdate = true; + + } + + return needsUpdate; + + } + + getRenderCacheKey( renderObject ) { + + const { object, material } = renderObject; + + const utils = this.utils; + const renderContext = renderObject.context; + + return [ + material.transparent, material.blending, material.premultipliedAlpha, + material.blendSrc, material.blendDst, material.blendEquation, + material.blendSrcAlpha, material.blendDstAlpha, material.blendEquationAlpha, + material.colorWrite, + material.depthWrite, material.depthTest, material.depthFunc, + material.stencilWrite, material.stencilFunc, + material.stencilFail, material.stencilZFail, material.stencilZPass, + material.stencilFuncMask, material.stencilWriteMask, + material.side, + utils.getSampleCountRenderContext( renderContext ), + utils.getCurrentColorSpace( renderContext ), utils.getCurrentColorFormat( renderContext ), utils.getCurrentDepthStencilFormat( renderContext ), + utils.getPrimitiveTopology( object, material ), + renderObject.clippingContext.cacheKey + ].join(); + + } + + // textures + + createSampler( texture ) { + + this.textureUtils.createSampler( texture ); + + } + + destroySampler( texture ) { + + this.textureUtils.destroySampler( texture ); + + } + + createDefaultTexture( texture ) { + + this.textureUtils.createDefaultTexture( texture ); + + } + + createTexture( texture, options ) { + + this.textureUtils.createTexture( texture, options ); + + } + + updateTexture( texture, options ) { + + this.textureUtils.updateTexture( texture, options ); + + } + + generateMipmaps( texture ) { + + this.textureUtils.generateMipmaps( texture ); + + } + + destroyTexture( texture ) { + + this.textureUtils.destroyTexture( texture ); + + } + + copyTextureToBuffer( texture, x, y, width, height, faceIndex ) { + + return this.textureUtils.copyTextureToBuffer( texture, x, y, width, height, faceIndex ); + + } + + + initTimestampQuery( renderContext, descriptor ) { + + if ( ! this.trackTimestamp ) return; + + const renderContextData = this.get( renderContext ); + + if ( ! renderContextData.timeStampQuerySet ) { + + // Create a GPUQuerySet which holds 2 timestamp query results: one for the + // beginning and one for the end of compute pass execution. + const timeStampQuerySet = this.device.createQuerySet( { type: 'timestamp', count: 2 } ); + + const timestampWrites = { + querySet: timeStampQuerySet, + beginningOfPassWriteIndex: 0, // Write timestamp in index 0 when pass begins. + endOfPassWriteIndex: 1, // Write timestamp in index 1 when pass ends. + }; + + Object.assign( descriptor, { + timestampWrites, + } ); + + renderContextData.timeStampQuerySet = timeStampQuerySet; + + } + + } + + // timestamp utils + + prepareTimestampBuffer( renderContext, encoder ) { + + if ( ! this.trackTimestamp ) return; + + const renderContextData = this.get( renderContext ); + + + const size = 2 * BigInt64Array.BYTES_PER_ELEMENT; + + if ( renderContextData.currentTimestampQueryBuffers === undefined ) { + + renderContextData.currentTimestampQueryBuffers = { + resolveBuffer: this.device.createBuffer( { + label: 'timestamp resolve buffer', + size: size, + usage: GPUBufferUsage.QUERY_RESOLVE | GPUBufferUsage.COPY_SRC, + } ), + resultBuffer: this.device.createBuffer( { + label: 'timestamp result buffer', + size: size, + usage: GPUBufferUsage.COPY_DST | GPUBufferUsage.MAP_READ, + } ), + isMappingPending: false, + }; + + } + + const { resolveBuffer, resultBuffer, isMappingPending } = renderContextData.currentTimestampQueryBuffers; + + if ( isMappingPending === true ) return; + + encoder.resolveQuerySet( renderContextData.timeStampQuerySet, 0, 2, resolveBuffer, 0 ); + encoder.copyBufferToBuffer( resolveBuffer, 0, resultBuffer, 0, size ); + + } + + async resolveTimestampAsync( renderContext, type = 'render' ) { + + if ( ! this.trackTimestamp ) return; + + const renderContextData = this.get( renderContext ); + + if ( renderContextData.currentTimestampQueryBuffers === undefined ) return; + + const { resultBuffer, isMappingPending } = renderContextData.currentTimestampQueryBuffers; + + if ( isMappingPending === true ) return; + + renderContextData.currentTimestampQueryBuffers.isMappingPending = true; + + resultBuffer.mapAsync( GPUMapMode.READ ).then( () => { + + const times = new BigUint64Array( resultBuffer.getMappedRange() ); + const duration = Number( times[ 1 ] - times[ 0 ] ) / 1000000; + + + this.renderer.info.updateTimestamp( type, duration ); + + resultBuffer.unmap(); + + renderContextData.currentTimestampQueryBuffers.isMappingPending = false; + + } ); + + } + + // node builder + + createNodeBuilder( object, renderer ) { + + return new WGSLNodeBuilder( object, renderer ); + + } + + // program + + createProgram( program ) { + + const programGPU = this.get( program ); + + programGPU.module = { + module: this.device.createShaderModule( { code: program.code, label: program.stage } ), + entryPoint: 'main' + }; + + } + + destroyProgram( program ) { + + this.delete( program ); + + } + + // pipelines + + createRenderPipeline( renderObject, promises ) { + + this.pipelineUtils.createRenderPipeline( renderObject, promises ); + + } + + createComputePipeline( computePipeline, bindings ) { + + this.pipelineUtils.createComputePipeline( computePipeline, bindings ); + + } + + beginBundle( renderContext ) { + + const renderContextData = this.get( renderContext ); + + renderContextData._currentPass = renderContextData.currentPass; + renderContextData._currentSets = renderContextData.currentSets; + + renderContextData.currentSets = { attributes: {}, bindingGroups: [], pipeline: null, index: null }; + renderContextData.currentPass = this.pipelineUtils.createBundleEncoder( renderContext ); + + } + + finishBundle( renderContext, bundle ) { + + const renderContextData = this.get( renderContext ); + + const bundleEncoder = renderContextData.currentPass; + const bundleGPU = bundleEncoder.finish(); + + this.get( bundle ).bundleGPU = bundleGPU; + + // restore render pass state + + renderContextData.currentSets = renderContextData._currentSets; + renderContextData.currentPass = renderContextData._currentPass; + + } + + addBundle( renderContext, bundle ) { + + const renderContextData = this.get( renderContext ); + + renderContextData.renderBundles.push( this.get( bundle ).bundleGPU ); + + } + + // bindings + + createBindings( bindGroup ) { + + this.bindingUtils.createBindings( bindGroup ); + + } + + updateBindings( bindGroup ) { + + this.bindingUtils.createBindings( bindGroup ); + + } + + updateBinding( binding ) { + + this.bindingUtils.updateBinding( binding ); + + } + + // attributes + + createIndexAttribute( attribute ) { + + this.attributeUtils.createAttribute( attribute, GPUBufferUsage.INDEX | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST ); + + } + + createAttribute( attribute ) { + + this.attributeUtils.createAttribute( attribute, GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST ); + + } + + createStorageAttribute( attribute ) { + + this.attributeUtils.createAttribute( attribute, GPUBufferUsage.STORAGE | GPUBufferUsage.VERTEX | GPUBufferUsage.COPY_SRC | GPUBufferUsage.COPY_DST ); + + } + + updateAttribute( attribute ) { + + this.attributeUtils.updateAttribute( attribute ); + + } + + destroyAttribute( attribute ) { + + this.attributeUtils.destroyAttribute( attribute ); + + } + + // canvas + + updateSize() { + + this.colorBuffer = this.textureUtils.getColorBuffer(); + this.defaultRenderPassdescriptor = null; + + } + + // utils public + + getMaxAnisotropy() { + + return 16; + + } + + hasFeature( name ) { + + return this.device.features.has( name ); + + } + + copyTextureToTexture( srcTexture, dstTexture, srcRegion = null, dstPosition = null, level = 0 ) { + + let dstX = 0; + let dstY = 0; + let dstLayer = 0; + + let srcX = 0; + let srcY = 0; + let srcLayer = 0; + + let srcWidth = srcTexture.image.width; + let srcHeight = srcTexture.image.height; + + if ( srcRegion !== null ) { + + srcX = srcRegion.x; + srcY = srcRegion.y; + srcLayer = srcRegion.z || 0; + srcWidth = srcRegion.width; + srcHeight = srcRegion.height; + + } + + if ( dstPosition !== null ) { + + dstX = dstPosition.x; + dstY = dstPosition.y; + dstLayer = dstPosition.z || 0; + + } + + const encoder = this.device.createCommandEncoder( { label: 'copyTextureToTexture_' + srcTexture.id + '_' + dstTexture.id } ); + + const sourceGPU = this.get( srcTexture ).texture; + const destinationGPU = this.get( dstTexture ).texture; + + encoder.copyTextureToTexture( + { + texture: sourceGPU, + mipLevel: level, + origin: { x: srcX, y: srcY, z: srcLayer } + }, + { + texture: destinationGPU, + mipLevel: level, + origin: { x: dstX, y: dstY, z: dstLayer } + }, + [ + srcWidth, + srcHeight, + 1 + ] + ); + + this.device.queue.submit( [ encoder.finish() ] ); + + } + + copyFramebufferToTexture( texture, renderContext, rectangle ) { + + const renderContextData = this.get( renderContext ); + + const { encoder, descriptor } = renderContextData; + + let sourceGPU = null; + + if ( renderContext.renderTarget ) { + + if ( texture.isDepthTexture ) { + + sourceGPU = this.get( renderContext.depthTexture ).texture; + + } else { + + sourceGPU = this.get( renderContext.textures[ 0 ] ).texture; + + } + + } else { + + if ( texture.isDepthTexture ) { + + sourceGPU = this.textureUtils.getDepthBuffer( renderContext.depth, renderContext.stencil ); + + } else { + + sourceGPU = this.context.getCurrentTexture(); + + } + + } + + const destinationGPU = this.get( texture ).texture; + + if ( sourceGPU.format !== destinationGPU.format ) { + + console.error( 'WebGPUBackend: copyFramebufferToTexture: Source and destination formats do not match.', sourceGPU.format, destinationGPU.format ); + + return; + + } + + renderContextData.currentPass.end(); + + encoder.copyTextureToTexture( + { + texture: sourceGPU, + origin: { x: rectangle.x, y: rectangle.y, z: 0 } + }, + { + texture: destinationGPU + }, + [ + rectangle.z, + rectangle.w + ] + ); + + if ( texture.generateMipmaps ) this.textureUtils.generateMipmaps( texture ); + + for ( let i = 0; i < descriptor.colorAttachments.length; i ++ ) { + + descriptor.colorAttachments[ i ].loadOp = GPULoadOp.Load; + + } + + if ( renderContext.depth ) descriptor.depthStencilAttachment.depthLoadOp = GPULoadOp.Load; + if ( renderContext.stencil ) descriptor.depthStencilAttachment.stencilLoadOp = GPULoadOp.Load; + + renderContextData.currentPass = encoder.beginRenderPass( descriptor ); + renderContextData.currentSets = { attributes: {}, bindingGroups: [], pipeline: null, index: null }; + + } + +} + +class IESSpotLight extends SpotLight { + + constructor( color, intensity, distance, angle, penumbra, decay ) { + + super( color, intensity, distance, angle, penumbra, decay ); + + this.iesMap = null; + + } + + copy( source, recursive ) { + + super.copy( source, recursive ); + + this.iesMap = source.iesMap; + + return this; + + } + +} + +class BasicNodeLibrary extends NodeLibrary { + + constructor() { + + super(); + + this.addLight( PointLightNode, PointLight ); + this.addLight( DirectionalLightNode, DirectionalLight ); + this.addLight( RectAreaLightNode, RectAreaLight ); + this.addLight( SpotLightNode, SpotLight ); + this.addLight( AmbientLightNode, AmbientLight ); + this.addLight( HemisphereLightNode, HemisphereLight ); + this.addLight( LightProbeNode, LightProbe ); + this.addLight( IESSpotLightNode, IESSpotLight ); + + this.addToneMapping( linearToneMapping, LinearToneMapping ); + this.addToneMapping( reinhardToneMapping, ReinhardToneMapping ); + this.addToneMapping( cineonToneMapping, CineonToneMapping ); + this.addToneMapping( acesFilmicToneMapping, ACESFilmicToneMapping ); + this.addToneMapping( agxToneMapping, AgXToneMapping ); + this.addToneMapping( neutralToneMapping, NeutralToneMapping ); + + this.addColorSpace( linearSRGBTosRGB, getColorSpaceMethod( LinearSRGBColorSpace, SRGBColorSpace ) ); + this.addColorSpace( sRGBToLinearSRGB, getColorSpaceMethod( SRGBColorSpace, LinearSRGBColorSpace ) ); + + } + +} + +class WebGPURenderer extends Renderer { + + constructor( parameters = {} ) { + + let BackendClass; + + if ( parameters.forceWebGL ) { + + BackendClass = WebGLBackend; + + } else { + + BackendClass = WebGPUBackend; + + parameters.getFallback = () => { + + console.warn( 'THREE.WebGPURenderer: WebGPU is not available, running under WebGL2 backend.' ); + + return new WebGLBackend( parameters ); + + }; + + } + + const backend = new BackendClass( parameters ); + + super( backend, parameters ); + + this.nodes.library = new BasicNodeLibrary(); + + this.isWebGPURenderer = true; + + } + +} + +const _material = /*@__PURE__*/ new NodeMaterial(); +const _quadMesh = /*@__PURE__*/ new QuadMesh( _material ); + +class PostProcessing { + + constructor( renderer, outputNode = vec4( 0, 0, 1, 1 ) ) { + + this.renderer = renderer; + this.outputNode = outputNode; + + this.outputColorTransform = true; + + this.needsUpdate = true; + + _material.name = 'PostProcessing'; + + } + + render() { + + this.update(); + + const renderer = this.renderer; + + const toneMapping = renderer.toneMapping; + const outputColorSpace = renderer.outputColorSpace; + + renderer.toneMapping = NoToneMapping; + renderer.outputColorSpace = LinearSRGBColorSpace; + + // + + _quadMesh.render( renderer ); + + // + + renderer.toneMapping = toneMapping; + renderer.outputColorSpace = outputColorSpace; + + } + + update() { + + if ( this.needsUpdate === true ) { + + const renderer = this.renderer; + + const toneMapping = renderer.toneMapping; + const outputColorSpace = renderer.outputColorSpace; + + _quadMesh.material.fragmentNode = this.outputColorTransform === true ? renderOutput( this.outputNode, toneMapping, outputColorSpace ) : this.outputNode.context( { toneMapping, outputColorSpace } ); + _quadMesh.material.needsUpdate = true; + + this.needsUpdate = false; + + } + + } + + async renderAsync() { + + this.update(); + + const renderer = this.renderer; + + const toneMapping = renderer.toneMapping; + const outputColorSpace = renderer.outputColorSpace; + + renderer.toneMapping = NoToneMapping; + renderer.outputColorSpace = LinearSRGBColorSpace; + + // + + await _quadMesh.renderAsync( renderer ); + + // + + renderer.toneMapping = toneMapping; + renderer.outputColorSpace = outputColorSpace; + + } + +} + +class StorageTexture extends Texture { + + constructor( width = 1, height = 1 ) { + + super(); + + this.image = { width, height }; + + this.magFilter = LinearFilter; + this.minFilter = LinearFilter; + + this.isStorageTexture = true; + + } + +} + +class StorageBufferAttribute extends BufferAttribute { + + constructor( array, itemSize, typeClass = Float32Array ) { + + if ( ArrayBuffer.isView( array ) === false ) array = new typeClass( array * itemSize ); + + super( array, itemSize ); + + this.isStorageBufferAttribute = true; + + } + +} + +class StorageInstancedBufferAttribute extends InstancedBufferAttribute { + + constructor( array, itemSize, typeClass = Float32Array ) { + + if ( ArrayBuffer.isView( array ) === false ) array = new typeClass( array * itemSize ); + + super( array, itemSize ); + + this.isStorageInstancedBufferAttribute = true; + + } + +} + +class NodeLoader extends Loader { + + constructor( manager ) { + + super( manager ); + + this.textures = {}; + this.nodes = {}; + + } + + load( url, onLoad, onProgress, onError ) { + + const loader = new FileLoader( this.manager ); + loader.setPath( this.path ); + loader.setRequestHeader( this.requestHeader ); + loader.setWithCredentials( this.withCredentials ); + loader.load( url, ( text ) => { + + try { + + onLoad( this.parse( JSON.parse( text ) ) ); + + } catch ( e ) { + + if ( onError ) { + + onError( e ); + + } else { + + console.error( e ); + + } + + this.manager.itemError( url ); + + } + + }, onProgress, onError ); + + } + + parseNodes( json ) { + + const nodes = {}; + + if ( json !== undefined ) { + + for ( const nodeJSON of json ) { + + const { uuid, type } = nodeJSON; + + nodes[ uuid ] = this.createNodeFromType( type ); + nodes[ uuid ].uuid = uuid; + + } + + const meta = { nodes, textures: this.textures }; + + for ( const nodeJSON of json ) { + + nodeJSON.meta = meta; + + const node = nodes[ nodeJSON.uuid ]; + node.deserialize( nodeJSON ); + + delete nodeJSON.meta; + + } + + } + + return nodes; + + } + + parse( json ) { + + const node = this.createNodeFromType( json.type ); + node.uuid = json.uuid; + + const nodes = this.parseNodes( json.nodes ); + const meta = { nodes, textures: this.textures }; + + json.meta = meta; + + node.deserialize( json ); + + delete json.meta; + + return node; + + } + + setTextures( value ) { + + this.textures = value; + return this; + + } + + setNodes( value ) { + + this.nodes = value; + return this; + + } + + createNodeFromType( type ) { + + if ( this.nodes[ type ] === undefined ) { + + console.error( 'THREE.NodeLoader: Node type not found:', type ); + return float(); + + } + + return nodeObject( new this.nodes[ type ]() ); + + } + +} + +class NodeMaterialLoader extends MaterialLoader { + + constructor( manager ) { + + super( manager ); + + this.nodes = {}; + this.nodeMaterials = {}; + + } + + parse( json ) { + + const material = super.parse( json ); + + const nodes = this.nodes; + const inputNodes = json.inputNodes; + + for ( const property in inputNodes ) { + + const uuid = inputNodes[ property ]; + + material[ property ] = nodes[ uuid ]; + + } + + return material; + + } + + setNodes( value ) { + + this.nodes = value; + return this; + + } + + setNodeMaterials( value ) { + + this.nodeMaterials = value; + return this; + + } + + createMaterialFromType( type ) { + + const materialClass = this.nodeMaterials[ type ]; + + if ( materialClass !== undefined ) { + + return new materialClass(); + + } + + return super.createMaterialFromType( type ); + + } + +} + +class NodeObjectLoader extends ObjectLoader { + + constructor( manager ) { + + super( manager ); + + this.nodes = {}; + this.nodeMaterials = {}; + + this._nodesJSON = null; + + } + + setNodes( value ) { + + this.nodes = value; + return this; + + } + + setNodeMaterials( value ) { + + this.nodeMaterials = value; + return this; + + } + + parse( json, onLoad ) { + + this._nodesJSON = json.nodes; + + const data = super.parse( json, onLoad ); + + this._nodesJSON = null; // dispose + + return data; + + } + + parseNodes( json, textures ) { + + if ( json !== undefined ) { + + const loader = new NodeLoader(); + loader.setNodes( this.nodes ); + loader.setTextures( textures ); + + return loader.parseNodes( json ); + + } + + return {}; + + } + + parseMaterials( json, textures ) { + + const materials = {}; + + if ( json !== undefined ) { + + const nodes = this.parseNodes( this._nodesJSON, textures ); + + const loader = new NodeMaterialLoader(); + loader.setTextures( textures ); + loader.setNodes( nodes ); + loader.setNodeMaterials( this.nodeMaterials ); + + for ( let i = 0, l = json.length; i < l; i ++ ) { + + const data = json[ i ]; + + materials[ data.uuid ] = loader.parse( data ); + + } + + } + + return materials; + + } + +} + +if ( typeof __THREE_DEVTOOLS__ !== 'undefined' ) { + + __THREE_DEVTOOLS__.dispatchEvent( new CustomEvent( 'register', { detail: { + revision: REVISION, + } } ) ); + +} + +if ( typeof window !== 'undefined' ) { + + if ( window.__THREE__ ) { + + console.warn( 'WARNING: Multiple instances of Three.js being imported.' ); + + } else { + + window.__THREE__ = REVISION; + + } + +} + +export { ACESFilmicToneMapping, AONode, AddEquation, AddOperation, AdditiveAnimationBlendMode, AdditiveBlending, AfterImageNode, AgXToneMapping, AlphaFormat, AlwaysCompare, AlwaysDepth, AlwaysStencilFunc, AmbientLight, AmbientLightNode, AnaglyphPassNode, AnalyticLightNode, AnamorphicNode, AnimationAction, AnimationClip, AnimationLoader, AnimationMixer, AnimationObjectGroup, AnimationUtils, ArcCurve, ArrayCamera, ArrayElementNode, ArrowHelper, AssignNode, AttachedBindMode, AttributeNode, Audio, AudioAnalyser, AudioContext, AudioListener, AudioLoader, AxesHelper, BRDF_GGX, BRDF_Lambert, BackSide, BasicDepthPacking, BasicEnvironmentNode, BasicShadowMap$1 as BasicShadowMap, BatchNode, BatchedMesh, BloomNode, Bone, BooleanKeyframeTrack, Box2, Box3, Box3Helper, BoxGeometry, BoxHelper, Break, BufferAttribute, BufferAttributeNode, BufferGeometry, BufferGeometryLoader, BufferNode, BumpMapNode, BypassNode, ByteType, Cache, CacheNode, Camera, CameraHelper, CanvasTexture, CapsuleGeometry, CatmullRomCurve3, CineonToneMapping, CircleGeometry, ClampToEdgeWrapping, Clock, CodeNode, Color, ColorKeyframeTrack, ColorManagement, ColorSpaceNode, CompressedArrayTexture, CompressedCubeTexture, CompressedTexture, CompressedTextureLoader, ComputeNode, ConeGeometry, ConstNode, ConstantAlphaFactor, ConstantColorFactor, ContextNode, Continue, Controls, ConvertNode, CubeCamera, CubeReflectionMapping, CubeRefractionMapping, CubeTexture, CubeTextureLoader, CubeTextureNode, CubeUVReflectionMapping, CubicBezierCurve, CubicBezierCurve3, CubicInterpolant, CullFaceBack, CullFaceFront, CullFaceFrontBack, CullFaceNone, Curve, CurvePath, CustomBlending, CustomToneMapping, CylinderGeometry, Cylindrical, DFGApprox, D_GGX, Data3DTexture, DataArrayTexture, DataTexture, DataTextureLoader, DataUtils, DecrementStencilOp, DecrementWrapStencilOp, DefaultLoadingManager, DenoiseNode, DepthFormat, DepthOfFieldNode, DepthStencilFormat, DepthTexture, DetachedBindMode, DirectionalLight, DirectionalLightHelper, DirectionalLightNode, Discard, DiscreteInterpolant, DisplayP3ColorSpace, DodecahedronGeometry, DotScreenNode, DoubleSide, DstAlphaFactor, DstColorFactor, DynamicCopyUsage, DynamicDrawUsage, DynamicReadUsage, EPSILON, EdgesGeometry, EllipseCurve, EnvironmentNode, EqualCompare, EqualDepth, EqualStencilFunc, EquirectUVNode, EquirectangularReflectionMapping, EquirectangularRefractionMapping, Euler, EventDispatcher, ExpressionNode, ExtrudeGeometry, FXAANode, F_Schlick, FileLoader, FilmNode, Float16BufferAttribute, Float32BufferAttribute, FloatType, Fn, Fog, FogExp2, FogExp2Node, FogNode, FogRangeNode, FramebufferTexture, FrontFacingNode, FrontSide, Frustum, FunctionCallNode, FunctionNode, FunctionOverloadingNode, GLBufferAttribute, GLSL1, GLSL3, GLSLNodeParser, GTAONode, GaussianBlurNode, GreaterCompare, GreaterDepth, GreaterEqualCompare, GreaterEqualDepth, GreaterEqualStencilFunc, GreaterStencilFunc, GridHelper, Group, HalfFloatType, HemisphereLight, HemisphereLightHelper, HemisphereLightNode, IESSpotLight, IESSpotLightNode, INFINITY, IcosahedronGeometry, If, ImageBitmapLoader, ImageLoader, ImageUtils, IncrementStencilOp, IncrementWrapStencilOp, IndexNode, InstanceNode, InstancedBufferAttribute, InstancedBufferGeometry, InstancedInterleavedBuffer, InstancedMesh, InstancedPointsNodeMaterial, Int16BufferAttribute, Int32BufferAttribute, Int8BufferAttribute, IntType, InterleavedBuffer, InterleavedBufferAttribute, Interpolant, InterpolateDiscrete, InterpolateLinear, InterpolateSmooth, InvertStencilOp, IrradianceNode, JoinNode, KeepStencilOp, KeyframeTrack, LOD, LatheGeometry, Layers, LessCompare, LessDepth, LessEqualCompare, LessEqualDepth, LessEqualStencilFunc, LessStencilFunc, Light, LightProbe, LightProbeNode, LightingContextNode, LightingModel, LightingNode, LightsNode, Line, Line2NodeMaterial, Line3, LineBasicMaterial, LineBasicNodeMaterial, LineCurve, LineCurve3, LineDashedMaterial, LineDashedNodeMaterial, LineLoop, LineSegments, LinearDisplayP3ColorSpace, LinearFilter, LinearInterpolant, LinearMipMapLinearFilter, LinearMipMapNearestFilter, LinearMipmapLinearFilter, LinearMipmapNearestFilter, LinearSRGBColorSpace, LinearToneMapping, LinearTransfer, Loader, LoaderUtils, LoadingManager, Loop, LoopNode, LoopOnce, LoopPingPong, LoopRepeat, LuminanceAlphaFormat, LuminanceFormat, Lut3DNode, MOUSE, MRTNode, MatcapUVNode, Material, MaterialLoader, MaterialNode, MaterialReferenceNode, MathUtils, Matrix2, Matrix3, Matrix4, MaxEquation, MaxMipLevelNode, Mesh, MeshBasicMaterial, MeshBasicNodeMaterial, MeshDepthMaterial, MeshDistanceMaterial, MeshLambertMaterial, MeshLambertNodeMaterial, MeshMatcapMaterial, MeshMatcapNodeMaterial, MeshNormalMaterial, MeshNormalNodeMaterial, MeshPhongMaterial, MeshPhongNodeMaterial, MeshPhysicalMaterial, MeshPhysicalNodeMaterial, MeshSSSNodeMaterial, MeshStandardMaterial, MeshStandardNodeMaterial, MeshToonMaterial, MeshToonNodeMaterial, MinEquation, MirroredRepeatWrapping, MixOperation, ModelNode, ModelViewProjectionNode, MorphNode, MultiplyBlending, MultiplyOperation, NearestFilter, NearestMipMapLinearFilter, NearestMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipmapNearestFilter, NeutralToneMapping, NeverCompare, NeverDepth, NeverStencilFunc, NoBlending, NoColorSpace, NoToneMapping, Node, NodeAttribute, NodeBuilder, NodeCache, NodeCode, NodeFrame, NodeFunctionInput, NodeLoader, NodeMaterial, NodeMaterialLoader, NodeMaterialObserver, NodeObjectLoader, NodeShaderStage, NodeType, NodeUniform, NodeUpdateType, NodeUtils, NodeVar, NodeVarying, NormalAnimationBlendMode, NormalBlending, NormalMapNode, NotEqualCompare, NotEqualDepth, NotEqualStencilFunc, NumberKeyframeTrack, Object3D, Object3DNode, ObjectLoader, ObjectSpaceNormalMap, OctahedronGeometry, OneFactor, OneMinusConstantAlphaFactor, OneMinusConstantColorFactor, OneMinusDstAlphaFactor, OneMinusDstColorFactor, OneMinusSrcAlphaFactor, OneMinusSrcColorFactor, OrthographicCamera, OscNode, OutputStructNode, P3Primaries, PCFShadowMap$1 as PCFShadowMap, PCFSoftShadowMap$1 as PCFSoftShadowMap, PI, PI2, PMREMGenerator, PMREMNode, ParallaxBarrierPassNode, ParameterNode, PassNode, Path, PerspectiveCamera, PhongLightingModel, PhysicalLightingModel, PixelationPassNode, Plane, PlaneGeometry, PlaneHelper, PointLight, PointLightHelper, PointLightNode, PointUVNode, Points, PointsMaterial, PointsNodeMaterial, PolarGridHelper, PolyhedronGeometry, PositionalAudio, PostProcessing, PosterizeNode, PropertyBinding, PropertyMixer, PropertyNode, QuadMesh, QuadraticBezierCurve, QuadraticBezierCurve3, Quaternion, QuaternionKeyframeTrack, QuaternionLinearInterpolant, RED_GREEN_RGTC2_Format, RED_RGTC1_Format, REVISION, RGBADepthPacking, RGBAFormat, RGBAIntegerFormat, RGBA_ASTC_10x10_Format, RGBA_ASTC_10x5_Format, RGBA_ASTC_10x6_Format, RGBA_ASTC_10x8_Format, RGBA_ASTC_12x10_Format, RGBA_ASTC_12x12_Format, RGBA_ASTC_4x4_Format, RGBA_ASTC_5x4_Format, RGBA_ASTC_5x5_Format, RGBA_ASTC_6x5_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_8x5_Format, RGBA_ASTC_8x6_Format, RGBA_ASTC_8x8_Format, RGBA_BPTC_Format, RGBA_ETC2_EAC_Format, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_S3TC_DXT1_Format, RGBA_S3TC_DXT3_Format, RGBA_S3TC_DXT5_Format, RGBDepthPacking, RGBFormat, RGBIntegerFormat, RGBShiftNode, RGB_BPTC_SIGNED_Format, RGB_BPTC_UNSIGNED_Format, RGB_ETC1_Format, RGB_ETC2_Format, RGB_PVRTC_2BPPV1_Format, RGB_PVRTC_4BPPV1_Format, RGB_S3TC_DXT1_Format, RGDepthPacking, RGFormat, RGIntegerFormat, RTTNode, RangeNode, RawShaderMaterial, Ray, Raycaster, Rec709Primaries, RectAreaLight, RectAreaLightNode, RedFormat, RedIntegerFormat, ReferenceNode, ReflectorNode, ReinhardToneMapping, RemapNode, RenderOutputNode, RenderTarget, RendererReferenceNode, RepeatWrapping, ReplaceStencilOp, Return, ReverseSubtractEquation, RingGeometry, RotateNode, SIGNED_RED_GREEN_RGTC2_Format, SIGNED_RED_RGTC1_Format, SRGBColorSpace, SRGBTransfer, SSAAPassNode, Scene, SceneNode, Schlick_to_F0, ScreenNode, ScriptableNode, ScriptableValueNode, SetNode, ShaderMaterial, ShaderNode, ShadowMaterial, ShadowNodeMaterial, Shape, ShapeGeometry, ShapePath, ShapeUtils, ShortType, Skeleton, SkeletonHelper, SkinnedMesh, SkinningNode, SobelOperatorNode, Source, Sphere, SphereGeometry, Spherical, SphericalHarmonics3, SplineCurve, SplitNode, SpotLight, SpotLightHelper, SpotLightNode, Sprite, SpriteMaterial, SpriteNodeMaterial, SpriteSheetUVNode, SrcAlphaFactor, SrcAlphaSaturateFactor, SrcColorFactor, StackNode, StaticCopyUsage, StaticDrawUsage, StaticReadUsage, StereoCamera, StereoPassNode, StorageArrayElementNode, StorageBufferAttribute, StorageBufferNode, StorageInstancedBufferAttribute, StorageTexture, StorageTextureNode, StreamCopyUsage, StreamDrawUsage, StreamReadUsage, StringKeyframeTrack, SubtractEquation, SubtractiveBlending, TBNViewMatrix, TOUCH, TangentSpaceNormalMap, TempNode, TetrahedronGeometry, Texture, Texture3DNode, TextureLoader, TextureNode, TextureSizeNode, TimerNode, ToneMappingNode, ToonOutlinePassNode, TorusGeometry, TorusKnotGeometry, TransitionNode, Triangle, TriangleFanDrawMode, TriangleStripDrawMode, TrianglesDrawMode, TriplanarTexturesNode, TubeGeometry, UVMapping, Uint16BufferAttribute, Uint32BufferAttribute, Uint8BufferAttribute, Uint8ClampedBufferAttribute, Uniform$1 as Uniform, UniformArrayNode, UniformGroupNode, UniformNode, UniformsGroup$1 as UniformsGroup, UnsignedByteType, UnsignedInt248Type, UnsignedInt5999Type, UnsignedIntType, UnsignedShort4444Type, UnsignedShort5551Type, UnsignedShortType, UserDataNode, VSMShadowMap, V_GGX_SmithCorrelated, VarNode, VaryingNode, Vector2, Vector3, Vector4, VectorKeyframeTrack, VertexColorNode, VideoTexture, ViewportDepthNode, ViewportDepthTextureNode, ViewportSharedTextureNode, ViewportTextureNode, VolumeNodeMaterial, WebGL3DRenderTarget, WebGLArrayRenderTarget, WebGLCoordinateSystem, WebGLCubeRenderTarget, WebGLMultipleRenderTargets, WebGLRenderTarget, WebGPUCoordinateSystem, WebGPURenderer, WireframeGeometry, WrapAroundEnding, ZeroCurvatureEnding, ZeroFactor, ZeroSlopeEnding, ZeroStencilOp, abs, acesFilmicToneMapping, acos, add, addMethodChaining, addNodeElement, afterImage, agxToneMapping, all, alphaT, anaglyphPass, anamorphic, and, anisotropy, anisotropyB, anisotropyT, any, ao, append, arrayBuffer, asin, assign, atan, atan2, atomicAdd, atomicAnd, atomicFunc, atomicMax, atomicMin, atomicOr, atomicStore, atomicSub, atomicXor, attenuationColor, attenuationDistance, attribute, backgroundBlurriness, backgroundIntensity, batch, billboarding, bitAnd, bitNot, bitOr, bitXor, bitangentGeometry, bitangentLocal, bitangentView, bitangentWorld, bitcast, bleach, bloom, blur, bool, buffer, bufferAttribute, bumpMap, burn, bvec2, bvec3, bvec4, bypass, cache, call, cameraFar, cameraLogDepth, cameraNear, cameraNormalMatrix, cameraPosition, cameraProjectionMatrix, cameraProjectionMatrixInverse, cameraViewMatrix, cameraWorldMatrix, cbrt, ceil, checker, cineonToneMapping, clamp, clearcoat, clearcoatRoughness, code, color, colorSpaceToWorking, colorToDirection, compute, cond, context, convert, convertToTexture, cos, createCanvasElement, cross, cubeTexture, dFdx, dFdy, dashSize, defaultBuildStages, defaultShaderStages, defined, degrees, denoise, densityFog, depth, depthPass, difference, diffuseColor, directionToColor, dispersion, distance, div, dodge, dof, dot, dotScreen, drawIndex, dynamicBufferAttribute, element, emissive, equal, equals, equirectUV, exp, exp2, expression, faceDirection, faceForward, film, float, floor, fog, fract, frameGroup, frameId, frontFacing, fwidth, fxaa, gain, gapSize, gaussianBlur, getColorSpaceMethod, getConstNodeType, getCurrentStack, getDirection, getDistanceAttenuation, getGeometryRoughness, getRoughness, getShIrradianceAt, getTextureIndex, global, glsl, glslFn, grayscale, greaterThan, greaterThanEqual, hash, highPrecisionModelNormalViewMatrix, highPrecisionModelViewMatrix, hue, instance, instanceIndex, instancedBufferAttribute, instancedDynamicBufferAttribute, int, inverseSqrt, invocationLocalIndex, invocationSubgroupIndex, ior, iridescence, iridescenceIOR, iridescenceThickness, ivec2, ivec3, ivec4, js, label, length, lengthSq, lessThan, lessThanEqual, lightPosition, lightTargetDirection, lightTargetPosition, lightViewPosition, lightingContext, lights, linearDepth, linearSRGBTosRGB, linearToneMapping, localId, log, log2, loop, luminance, lut3D, mat2, mat3, mat4, matcapUV, materialAOMap, materialAlphaTest, materialAnisotropy, materialAnisotropyVector, materialAttenuationColor, materialAttenuationDistance, materialClearcoat, materialClearcoatNormal, materialClearcoatRoughness, materialColor, materialDispersion, materialEmissive, materialIOR, materialIridescence, materialIridescenceIOR, materialIridescenceThickness, materialLightMap, materialLineDashOffset, materialLineDashSize, materialLineGapSize, materialLineScale, materialLineWidth, materialMetalness, materialNormal, materialOpacity, materialPointWidth, materialReference, materialReflectivity, materialRefractionRatio, materialRotation, materialRoughness, materialSheen, materialSheenRoughness, materialShininess, materialSpecular, materialSpecularColor, materialSpecularIntensity, materialSpecularStrength, materialThickness, materialTransmission, max$1 as max, maxMipLevel, metalness, min$1 as min, mix, mixElement, mod, modInt, modelDirection, modelNormalMatrix, modelPosition, modelScale, modelViewMatrix, modelViewPosition, modelViewProjection, modelWorldMatrix, modelWorldMatrixInverse, morphReference, motionBlur, mrt, mul, mx_aastep, mx_cell_noise_float, mx_contrast, mx_fractal_noise_float, mx_fractal_noise_vec2, mx_fractal_noise_vec3, mx_fractal_noise_vec4, mx_hsvtorgb, mx_noise_float, mx_noise_vec3, mx_noise_vec4, mx_ramplr, mx_ramptb, mx_rgbtohsv, mx_safepower, mx_splitlr, mx_splittb, mx_srgb_texture_to_lin_rec709, mx_transform_uv, mx_worley_noise_float, mx_worley_noise_vec2, mx_worley_noise_vec3, negate, neutralToneMapping, nodeArray, nodeImmutable, nodeObject, nodeObjects, nodeProxy, normalFlat, normalGeometry, normalLocal, normalMap, normalView, normalWorld, normalize, not, notEqual, numWorkgroups, objectDirection, objectGroup, objectPosition, objectScale, objectViewPosition, objectWorldMatrix, oneMinus, or, orthographicDepthToViewZ, oscSawtooth, oscSine, oscSquare, oscTriangle, output, outputStruct, overlay, overloadingFn, parabola, parallaxBarrierPass, parallaxDirection, parallaxUV, parameter, pass, passTexture, pcurve, perspectiveDepthToViewZ, pixelationPass, pmremTexture, pointUV, pointWidth, positionGeometry, positionLocal, positionPrevious, positionView, positionViewDirection, positionWorld, positionWorldDirection, posterize, pow, pow2, pow3, pow4, property, radians, rand, range, rangeFog, reciprocal, reference, referenceBuffer, reflect, reflectVector, reflectView, reflector, refract, refractVector, refractView, reinhardToneMapping, remainder, remap, remapClamp, renderGroup, renderOutput, rendererReference, rgbShift, rotate, rotateUV, roughness, round, rtt, sRGBToLinearSRGB, sampler, saturate, saturation, screen, screenCoordinate, screenSize, screenUV, scriptable, scriptableValue, select, sepia, setCurrentStack, shaderStages, sharedUniformGroup, sheen, sheenRoughness, shiftLeft, shiftRight, shininess, sign, sin, sinc, skinning, skinningReference, smoothstep, smoothstepElement, sobel, specularColor, specularF90, spherizeUV, split, spritesheetUV, sqrt, ssaaPass, stack, step, stereoPass, storage, storageBarrier, storageObject, storageTexture, string, sub, subgroupIndex, subgroupSize, tan, tangentGeometry, tangentLocal, tangentView, tangentWorld, temp, texture, texture3D, textureBarrier, textureBicubic, textureCubeUV, textureLoad, textureSize, textureStore, thickness, threshold, timerDelta, timerGlobal, timerLocal, toOutputColorSpace, toWorkingColorSpace, toneMapping, toneMappingExposure, toonOutlinePass, transformDirection, transformNormal, transformNormalToView, transformedBentNormalView, transformedBitangentView, transformedBitangentWorld, transformedClearcoatNormalView, transformedNormalView, transformedNormalWorld, transformedTangentView, transformedTangentWorld, transition, transmission, transpose, tri, tri3, triNoise3D, triplanarTexture, triplanarTextures, trunc, tslFn, uint, uniform, uniformArray, uniformGroup, uniforms, userData, uv, uvec2, uvec3, uvec4, varying, varyingProperty, vec2, vec3, vec4, vectorComponents, velocity, vertexColor, vertexIndex, vibrance, viewZToOrthographicDepth, viewZToPerspectiveDepth, viewport, viewportBottomLeft, viewportCoordinate, viewportDepthTexture, viewportLinearDepth, viewportMipTexture, viewportResolution, viewportSafeUV, viewportSharedTexture, viewportSize, viewportTexture, viewportTopLeft, viewportUV, wgsl, wgslFn, workgroupArray, workgroupBarrier, workgroupId, workingToColorSpace, xor }; diff --git a/build/three.webgpu.nodes.min.js b/build/three.webgpu.nodes.min.js new file mode 100644 index 00000000000000..17808bc51fbd44 --- /dev/null +++ b/build/three.webgpu.nodes.min.js @@ -0,0 +1,6 @@ +/** + * @license + * Copyright 2010-2024 Three.js Authors + * SPDX-License-Identifier: MIT + */ +const e="169",t={LEFT:0,MIDDLE:1,RIGHT:2,ROTATE:0,DOLLY:1,PAN:2},s={ROTATE:0,PAN:1,DOLLY_PAN:2,DOLLY_ROTATE:3},i=0,r=1,n=2,o=3,a=0,h=1,u=2,l=3,c=0,d=1,p=2,m=0,g=1,f=2,y=3,x=4,b=5,v=100,T=101,_=102,w=103,S=104,M=200,N=201,A=202,C=203,R=204,E=205,B=206,I=207,P=208,F=209,z=210,U=211,O=212,L=213,V=214,D=0,k=1,G=2,W=3,j=4,H=5,q=6,$=7,X=0,Y=1,Z=2,J=0,K=1,Q=2,ee=3,te=4,se=5,ie=6,re=7,ne="attached",oe="detached",ae=300,he=301,ue=302,le=303,ce=304,de=306,pe=1e3,me=1001,ge=1002,fe=1003,ye=1004,xe=1004,be=1005,ve=1005,Te=1006,_e=1007,we=1007,Se=1008,Me=1008,Ne=1009,Ae=1010,Ce=1011,Re=1012,Ee=1013,Be=1014,Ie=1015,Pe=1016,Fe=1017,ze=1018,Ue=1020,Oe=35902,Le=1021,Ve=1022,De=1023,ke=1024,Ge=1025,We=1026,je=1027,He=1028,qe=1029,$e=1030,Xe=1031,Ye=1032,Ze=1033,Je=33776,Ke=33777,Qe=33778,et=33779,tt=35840,st=35841,it=35842,rt=35843,nt=36196,ot=37492,at=37496,ht=37808,ut=37809,lt=37810,ct=37811,dt=37812,pt=37813,mt=37814,gt=37815,ft=37816,yt=37817,xt=37818,bt=37819,vt=37820,Tt=37821,_t=36492,wt=36494,St=36495,Mt=36283,Nt=36284,At=36285,Ct=36286,Rt=2200,Et=2201,Bt=2202,It=2300,Pt=2301,Ft=2302,zt=2400,Ut=2401,Ot=2402,Lt=2500,Vt=2501,Dt=0,kt=1,Gt=2,Wt=3200,jt=3201,Ht=3202,qt=3203,$t=0,Xt=1,Yt="",Zt="srgb",Jt="srgb-linear",Kt="display-p3",Qt="display-p3-linear",es="linear",ts="srgb",ss="rec709",is="p3",rs=0,ns=7680,os=7681,as=7682,hs=7683,us=34055,ls=34056,cs=5386,ds=512,ps=513,ms=514,gs=515,fs=516,ys=517,xs=518,bs=519,vs=512,Ts=513,_s=514,ws=515,Ss=516,Ms=517,Ns=518,As=519,Cs=35044,Rs=35048,Es=35040,Bs=35045,Is=35049,Ps=35041,Fs=35046,zs=35050,Us=35042,Os="100",Ls="300 es",Vs=2e3,Ds=2001;class ks{addEventListener(e,t){void 0===this._listeners&&(this._listeners={});const s=this._listeners;void 0===s[e]&&(s[e]=[]),-1===s[e].indexOf(t)&&s[e].push(t)}hasEventListener(e,t){if(void 0===this._listeners)return!1;const s=this._listeners;return void 0!==s[e]&&-1!==s[e].indexOf(t)}removeEventListener(e,t){if(void 0===this._listeners)return;const s=this._listeners[e];if(void 0!==s){const e=s.indexOf(t);-1!==e&&s.splice(e,1)}}dispatchEvent(e){if(void 0===this._listeners)return;const t=this._listeners[e.type];if(void 0!==t){e.target=this;const s=t.slice(0);for(let t=0,i=s.length;t>8&255]+Gs[e>>16&255]+Gs[e>>24&255]+"-"+Gs[255&t]+Gs[t>>8&255]+"-"+Gs[t>>16&15|64]+Gs[t>>24&255]+"-"+Gs[63&s|128]+Gs[s>>8&255]+"-"+Gs[s>>16&255]+Gs[s>>24&255]+Gs[255&i]+Gs[i>>8&255]+Gs[i>>16&255]+Gs[i>>24&255]).toLowerCase()}function $s(e,t,s){return Math.max(t,Math.min(s,e))}function Xs(e,t){return(e%t+t)%t}function Ys(e,t,s){return(1-s)*e+s*t}function Zs(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return e/4294967295;case Uint16Array:return e/65535;case Uint8Array:return e/255;case Int32Array:return Math.max(e/2147483647,-1);case Int16Array:return Math.max(e/32767,-1);case Int8Array:return Math.max(e/127,-1);default:throw new Error("Invalid component type.")}}function Js(e,t){switch(t.constructor){case Float32Array:return e;case Uint32Array:return Math.round(4294967295*e);case Uint16Array:return Math.round(65535*e);case Uint8Array:return Math.round(255*e);case Int32Array:return Math.round(2147483647*e);case Int16Array:return Math.round(32767*e);case Int8Array:return Math.round(127*e);default:throw new Error("Invalid component type.")}}const Ks={DEG2RAD:js,RAD2DEG:Hs,generateUUID:qs,clamp:$s,euclideanModulo:Xs,mapLinear:function(e,t,s,i,r){return i+(e-t)*(r-i)/(s-t)},inverseLerp:function(e,t,s){return e!==t?(s-e)/(t-e):0},lerp:Ys,damp:function(e,t,s,i){return Ys(e,t,1-Math.exp(-s*i))},pingpong:function(e,t=1){return t-Math.abs(Xs(e,2*t)-t)},smoothstep:function(e,t,s){return e<=t?0:e>=s?1:(e=(e-t)/(s-t))*e*(3-2*e)},smootherstep:function(e,t,s){return e<=t?0:e>=s?1:(e=(e-t)/(s-t))*e*e*(e*(6*e-15)+10)},randInt:function(e,t){return e+Math.floor(Math.random()*(t-e+1))},randFloat:function(e,t){return e+Math.random()*(t-e)},randFloatSpread:function(e){return e*(.5-Math.random())},seededRandom:function(e){void 0!==e&&(Ws=e);let t=Ws+=1831565813;return t=Math.imul(t^t>>>15,1|t),t^=t+Math.imul(t^t>>>7,61|t),((t^t>>>14)>>>0)/4294967296},degToRad:function(e){return e*js},radToDeg:function(e){return e*Hs},isPowerOfTwo:function(e){return 0==(e&e-1)&&0!==e},ceilPowerOfTwo:function(e){return Math.pow(2,Math.ceil(Math.log(e)/Math.LN2))},floorPowerOfTwo:function(e){return Math.pow(2,Math.floor(Math.log(e)/Math.LN2))},setQuaternionFromProperEuler:function(e,t,s,i,r){const n=Math.cos,o=Math.sin,a=n(s/2),h=o(s/2),u=n((t+i)/2),l=o((t+i)/2),c=n((t-i)/2),d=o((t-i)/2),p=n((i-t)/2),m=o((i-t)/2);switch(r){case"XYX":e.set(a*l,h*c,h*d,a*u);break;case"YZY":e.set(h*d,a*l,h*c,a*u);break;case"ZXZ":e.set(h*c,h*d,a*l,a*u);break;case"XZX":e.set(a*l,h*m,h*p,a*u);break;case"YXY":e.set(h*p,a*l,h*m,a*u);break;case"ZYZ":e.set(h*m,h*p,a*l,a*u);break;default:console.warn("THREE.MathUtils: .setQuaternionFromProperEuler() encountered an unknown order: "+r)}},normalize:Js,denormalize:Zs};class Qs{constructor(e=0,t=0){Qs.prototype.isVector2=!0,this.x=e,this.y=t}get width(){return this.x}set width(e){this.x=e}get height(){return this.y}set height(e){this.y=e}set(e,t){return this.x=e,this.y=t,this}setScalar(e){return this.x=e,this.y=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;default:throw new Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y)}copy(e){return this.x=e.x,this.y=e.y,this}add(e){return this.x+=e.x,this.y+=e.y,this}addScalar(e){return this.x+=e,this.y+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this}subScalar(e){return this.x-=e,this.y-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this}multiply(e){return this.x*=e.x,this.y*=e.y,this}multiplyScalar(e){return this.x*=e,this.y*=e,this}divide(e){return this.x/=e.x,this.y/=e.y,this}divideScalar(e){return this.multiplyScalar(1/e)}applyMatrix3(e){const t=this.x,s=this.y,i=e.elements;return this.x=i[0]*t+i[3]*s+i[6],this.y=i[1]*t+i[4]*s+i[7],this}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this}clampLength(e,t){const s=this.length();return this.divideScalar(s||1).multiplyScalar(Math.max(e,Math.min(t,s)))}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=Math.trunc(this.x),this.y=Math.trunc(this.y),this}negate(){return this.x=-this.x,this.y=-this.y,this}dot(e){return this.x*e.x+this.y*e.y}cross(e){return this.x*e.y-this.y*e.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}angleTo(e){const t=Math.sqrt(this.lengthSq()*e.lengthSq());if(0===t)return Math.PI/2;const s=this.dot(e)/t;return Math.acos($s(s,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){const t=this.x-e.x,s=this.y-e.y;return t*t+s*s}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)}setLength(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this}lerpVectors(e,t,s){return this.x=e.x+(t.x-e.x)*s,this.y=e.y+(t.y-e.y)*s,this}equals(e){return e.x===this.x&&e.y===this.y}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this}rotateAround(e,t){const s=Math.cos(t),i=Math.sin(t),r=this.x-e.x,n=this.y-e.y;return this.x=r*s-n*i+e.x,this.y=r*i+n*s+e.y,this}random(){return this.x=Math.random(),this.y=Math.random(),this}*[Symbol.iterator](){yield this.x,yield this.y}}class ei{constructor(e,t,s,i,r,n,o,a,h){ei.prototype.isMatrix3=!0,this.elements=[1,0,0,0,1,0,0,0,1],void 0!==e&&this.set(e,t,s,i,r,n,o,a,h)}set(e,t,s,i,r,n,o,a,h){const u=this.elements;return u[0]=e,u[1]=i,u[2]=o,u[3]=t,u[4]=r,u[5]=a,u[6]=s,u[7]=n,u[8]=h,this}identity(){return this.set(1,0,0,0,1,0,0,0,1),this}copy(e){const t=this.elements,s=e.elements;return t[0]=s[0],t[1]=s[1],t[2]=s[2],t[3]=s[3],t[4]=s[4],t[5]=s[5],t[6]=s[6],t[7]=s[7],t[8]=s[8],this}extractBasis(e,t,s){return e.setFromMatrix3Column(this,0),t.setFromMatrix3Column(this,1),s.setFromMatrix3Column(this,2),this}setFromMatrix4(e){const t=e.elements;return this.set(t[0],t[4],t[8],t[1],t[5],t[9],t[2],t[6],t[10]),this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){const s=e.elements,i=t.elements,r=this.elements,n=s[0],o=s[3],a=s[6],h=s[1],u=s[4],l=s[7],c=s[2],d=s[5],p=s[8],m=i[0],g=i[3],f=i[6],y=i[1],x=i[4],b=i[7],v=i[2],T=i[5],_=i[8];return r[0]=n*m+o*y+a*v,r[3]=n*g+o*x+a*T,r[6]=n*f+o*b+a*_,r[1]=h*m+u*y+l*v,r[4]=h*g+u*x+l*T,r[7]=h*f+u*b+l*_,r[2]=c*m+d*y+p*v,r[5]=c*g+d*x+p*T,r[8]=c*f+d*b+p*_,this}multiplyScalar(e){const t=this.elements;return t[0]*=e,t[3]*=e,t[6]*=e,t[1]*=e,t[4]*=e,t[7]*=e,t[2]*=e,t[5]*=e,t[8]*=e,this}determinant(){const e=this.elements,t=e[0],s=e[1],i=e[2],r=e[3],n=e[4],o=e[5],a=e[6],h=e[7],u=e[8];return t*n*u-t*o*h-s*r*u+s*o*a+i*r*h-i*n*a}invert(){const e=this.elements,t=e[0],s=e[1],i=e[2],r=e[3],n=e[4],o=e[5],a=e[6],h=e[7],u=e[8],l=u*n-o*h,c=o*a-u*r,d=h*r-n*a,p=t*l+s*c+i*d;if(0===p)return this.set(0,0,0,0,0,0,0,0,0);const m=1/p;return e[0]=l*m,e[1]=(i*h-u*s)*m,e[2]=(o*s-i*n)*m,e[3]=c*m,e[4]=(u*t-i*a)*m,e[5]=(i*r-o*t)*m,e[6]=d*m,e[7]=(s*a-h*t)*m,e[8]=(n*t-s*r)*m,this}transpose(){let e;const t=this.elements;return e=t[1],t[1]=t[3],t[3]=e,e=t[2],t[2]=t[6],t[6]=e,e=t[5],t[5]=t[7],t[7]=e,this}getNormalMatrix(e){return this.setFromMatrix4(e).invert().transpose()}transposeIntoArray(e){const t=this.elements;return e[0]=t[0],e[1]=t[3],e[2]=t[6],e[3]=t[1],e[4]=t[4],e[5]=t[7],e[6]=t[2],e[7]=t[5],e[8]=t[8],this}setUvTransform(e,t,s,i,r,n,o){const a=Math.cos(r),h=Math.sin(r);return this.set(s*a,s*h,-s*(a*n+h*o)+n+e,-i*h,i*a,-i*(-h*n+a*o)+o+t,0,0,1),this}scale(e,t){return this.premultiply(ti.makeScale(e,t)),this}rotate(e){return this.premultiply(ti.makeRotation(-e)),this}translate(e,t){return this.premultiply(ti.makeTranslation(e,t)),this}makeTranslation(e,t){return e.isVector2?this.set(1,0,e.x,0,1,e.y,0,0,1):this.set(1,0,e,0,1,t,0,0,1),this}makeRotation(e){const t=Math.cos(e),s=Math.sin(e);return this.set(t,-s,0,s,t,0,0,0,1),this}makeScale(e,t){return this.set(e,0,0,0,t,0,0,0,1),this}equals(e){const t=this.elements,s=e.elements;for(let e=0;e<9;e++)if(t[e]!==s[e])return!1;return!0}fromArray(e,t=0){for(let s=0;s<9;s++)this.elements[s]=e[s+t];return this}toArray(e=[],t=0){const s=this.elements;return e[t]=s[0],e[t+1]=s[1],e[t+2]=s[2],e[t+3]=s[3],e[t+4]=s[4],e[t+5]=s[5],e[t+6]=s[6],e[t+7]=s[7],e[t+8]=s[8],e}clone(){return(new this.constructor).fromArray(this.elements)}}const ti=new ei;const si={Int8Array:Int8Array,Uint8Array:Uint8Array,Uint8ClampedArray:Uint8ClampedArray,Int16Array:Int16Array,Uint16Array:Uint16Array,Int32Array:Int32Array,Uint32Array:Uint32Array,Float32Array:Float32Array,Float64Array:Float64Array};function ii(e,t){return new si[e](t)}function ri(e){return document.createElementNS("http://www.w3.org/1999/xhtml",e)}function ni(){const e=ri("canvas");return e.style.display="block",e}const oi={};const ai=(new ei).set(.8224621,.177538,0,.0331941,.9668058,0,.0170827,.0723974,.9105199),hi=(new ei).set(1.2249401,-.2249404,0,-.0420569,1.0420571,0,-.0196376,-.0786361,1.0982735),ui={[Jt]:{transfer:es,primaries:ss,luminanceCoefficients:[.2126,.7152,.0722],toReference:e=>e,fromReference:e=>e},[Zt]:{transfer:ts,primaries:ss,luminanceCoefficients:[.2126,.7152,.0722],toReference:e=>e.convertSRGBToLinear(),fromReference:e=>e.convertLinearToSRGB()},[Qt]:{transfer:es,primaries:is,luminanceCoefficients:[.2289,.6917,.0793],toReference:e=>e.applyMatrix3(hi),fromReference:e=>e.applyMatrix3(ai)},[Kt]:{transfer:ts,primaries:is,luminanceCoefficients:[.2289,.6917,.0793],toReference:e=>e.convertSRGBToLinear().applyMatrix3(hi),fromReference:e=>e.applyMatrix3(ai).convertLinearToSRGB()}},li=new Set([Jt,Qt]),ci={enabled:!0,_workingColorSpace:Jt,get workingColorSpace(){return this._workingColorSpace},set workingColorSpace(e){if(!li.has(e))throw new Error(`Unsupported working color space, "${e}".`);this._workingColorSpace=e},convert:function(e,t,s){if(!1===this.enabled||t===s||!t||!s)return e;const i=ui[t].toReference;return(0,ui[s].fromReference)(i(e))},fromWorkingColorSpace:function(e,t){return this.convert(e,this._workingColorSpace,t)},toWorkingColorSpace:function(e,t){return this.convert(e,t,this._workingColorSpace)},getPrimaries:function(e){return ui[e].primaries},getTransfer:function(e){return e===Yt?es:ui[e].transfer},getLuminanceCoefficients:function(e,t=this._workingColorSpace){return e.fromArray(ui[t].luminanceCoefficients)}};function di(e){return e<.04045?.0773993808*e:Math.pow(.9478672986*e+.0521327014,2.4)}function pi(e){return e<.0031308?12.92*e:1.055*Math.pow(e,.41666)-.055}let mi;class gi{static getDataURL(e){if(/^data:/i.test(e.src))return e.src;if("undefined"==typeof HTMLCanvasElement)return e.src;let t;if(e instanceof HTMLCanvasElement)t=e;else{void 0===mi&&(mi=ri("canvas")),mi.width=e.width,mi.height=e.height;const s=mi.getContext("2d");e instanceof ImageData?s.putImageData(e,0,0):s.drawImage(e,0,0,e.width,e.height),t=mi}return t.width>2048||t.height>2048?(console.warn("THREE.ImageUtils.getDataURL: Image converted to jpg for performance reasons",e),t.toDataURL("image/jpeg",.6)):t.toDataURL("image/png")}static sRGBToLinear(e){if("undefined"!=typeof HTMLImageElement&&e instanceof HTMLImageElement||"undefined"!=typeof HTMLCanvasElement&&e instanceof HTMLCanvasElement||"undefined"!=typeof ImageBitmap&&e instanceof ImageBitmap){const t=ri("canvas");t.width=e.width,t.height=e.height;const s=t.getContext("2d");s.drawImage(e,0,0,e.width,e.height);const i=s.getImageData(0,0,e.width,e.height),r=i.data;for(let e=0;e0&&(s.userData=this.userData),t||(e.textures[this.uuid]=s),s}dispose(){this.dispatchEvent({type:"dispose"})}transformUv(e){if(this.mapping!==ae)return e;if(e.applyMatrix3(this.matrix),e.x<0||e.x>1)switch(this.wrapS){case pe:e.x=e.x-Math.floor(e.x);break;case me:e.x=e.x<0?0:1;break;case ge:1===Math.abs(Math.floor(e.x)%2)?e.x=Math.ceil(e.x)-e.x:e.x=e.x-Math.floor(e.x)}if(e.y<0||e.y>1)switch(this.wrapT){case pe:e.y=e.y-Math.floor(e.y);break;case me:e.y=e.y<0?0:1;break;case ge:1===Math.abs(Math.floor(e.y)%2)?e.y=Math.ceil(e.y)-e.y:e.y=e.y-Math.floor(e.y)}return this.flipY&&(e.y=1-e.y),e}set needsUpdate(e){!0===e&&(this.version++,this.source.needsUpdate=!0)}set needsPMREMUpdate(e){!0===e&&this.pmremVersion++}}vi.DEFAULT_IMAGE=null,vi.DEFAULT_MAPPING=ae,vi.DEFAULT_ANISOTROPY=1;class Ti{constructor(e=0,t=0,s=0,i=1){Ti.prototype.isVector4=!0,this.x=e,this.y=t,this.z=s,this.w=i}get width(){return this.z}set width(e){this.z=e}get height(){return this.w}set height(e){this.w=e}set(e,t,s,i){return this.x=e,this.y=t,this.z=s,this.w=i,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this.w=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setW(e){return this.w=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;case 3:this.w=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){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: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z,this.w)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this.w=void 0!==e.w?e.w:1,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this.w+=e.w,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this.w+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this.w=e.w+t.w,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this.w+=e.w*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this.w-=e.w,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this.w-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this.w=e.w-t.w,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this.w*=e.w,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this.w*=e,this}applyMatrix4(e){const t=this.x,s=this.y,i=this.z,r=this.w,n=e.elements;return this.x=n[0]*t+n[4]*s+n[8]*i+n[12]*r,this.y=n[1]*t+n[5]*s+n[9]*i+n[13]*r,this.z=n[2]*t+n[6]*s+n[10]*i+n[14]*r,this.w=n[3]*t+n[7]*s+n[11]*i+n[15]*r,this}divideScalar(e){return this.multiplyScalar(1/e)}setAxisAngleFromQuaternion(e){this.w=2*Math.acos(e.w);const t=Math.sqrt(1-e.w*e.w);return t<1e-4?(this.x=1,this.y=0,this.z=0):(this.x=e.x/t,this.y=e.y/t,this.z=e.z/t),this}setAxisAngleFromRotationMatrix(e){let t,s,i,r;const n=.01,o=.1,a=e.elements,h=a[0],u=a[4],l=a[8],c=a[1],d=a[5],p=a[9],m=a[2],g=a[6],f=a[10];if(Math.abs(u-c)a&&e>y?ey?a=0?1:-1,i=1-t*t;if(i>Number.EPSILON){const r=Math.sqrt(i),n=Math.atan2(r,t*s);e=Math.sin(e*n)/r,o=Math.sin(o*n)/r}const r=o*s;if(a=a*e+c*r,h=h*e+d*r,u=u*e+p*r,l=l*e+m*r,e===1-o){const e=1/Math.sqrt(a*a+h*h+u*u+l*l);a*=e,h*=e,u*=e,l*=e}}e[t]=a,e[t+1]=h,e[t+2]=u,e[t+3]=l}static multiplyQuaternionsFlat(e,t,s,i,r,n){const o=s[i],a=s[i+1],h=s[i+2],u=s[i+3],l=r[n],c=r[n+1],d=r[n+2],p=r[n+3];return e[t]=o*p+u*l+a*d-h*c,e[t+1]=a*p+u*c+h*l-o*d,e[t+2]=h*p+u*d+o*c-a*l,e[t+3]=u*p-o*l-a*c-h*d,e}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get w(){return this._w}set w(e){this._w=e,this._onChangeCallback()}set(e,t,s,i){return this._x=e,this._y=t,this._z=s,this._w=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._w)}copy(e){return this._x=e.x,this._y=e.y,this._z=e.z,this._w=e.w,this._onChangeCallback(),this}setFromEuler(e,t=!0){const s=e._x,i=e._y,r=e._z,n=e._order,o=Math.cos,a=Math.sin,h=o(s/2),u=o(i/2),l=o(r/2),c=a(s/2),d=a(i/2),p=a(r/2);switch(n){case"XYZ":this._x=c*u*l+h*d*p,this._y=h*d*l-c*u*p,this._z=h*u*p+c*d*l,this._w=h*u*l-c*d*p;break;case"YXZ":this._x=c*u*l+h*d*p,this._y=h*d*l-c*u*p,this._z=h*u*p-c*d*l,this._w=h*u*l+c*d*p;break;case"ZXY":this._x=c*u*l-h*d*p,this._y=h*d*l+c*u*p,this._z=h*u*p+c*d*l,this._w=h*u*l-c*d*p;break;case"ZYX":this._x=c*u*l-h*d*p,this._y=h*d*l+c*u*p,this._z=h*u*p-c*d*l,this._w=h*u*l+c*d*p;break;case"YZX":this._x=c*u*l+h*d*p,this._y=h*d*l+c*u*p,this._z=h*u*p-c*d*l,this._w=h*u*l-c*d*p;break;case"XZY":this._x=c*u*l-h*d*p,this._y=h*d*l-c*u*p,this._z=h*u*p+c*d*l,this._w=h*u*l+c*d*p;break;default:console.warn("THREE.Quaternion: .setFromEuler() encountered an unknown order: "+n)}return!0===t&&this._onChangeCallback(),this}setFromAxisAngle(e,t){const s=t/2,i=Math.sin(s);return this._x=e.x*i,this._y=e.y*i,this._z=e.z*i,this._w=Math.cos(s),this._onChangeCallback(),this}setFromRotationMatrix(e){const t=e.elements,s=t[0],i=t[4],r=t[8],n=t[1],o=t[5],a=t[9],h=t[2],u=t[6],l=t[10],c=s+o+l;if(c>0){const e=.5/Math.sqrt(c+1);this._w=.25/e,this._x=(u-a)*e,this._y=(r-h)*e,this._z=(n-i)*e}else if(s>o&&s>l){const e=2*Math.sqrt(1+s-o-l);this._w=(u-a)/e,this._x=.25*e,this._y=(i+n)/e,this._z=(r+h)/e}else if(o>l){const e=2*Math.sqrt(1+o-s-l);this._w=(r-h)/e,this._x=(i+n)/e,this._y=.25*e,this._z=(a+u)/e}else{const e=2*Math.sqrt(1+l-s-o);this._w=(n-i)/e,this._x=(r+h)/e,this._y=(a+u)/e,this._z=.25*e}return this._onChangeCallback(),this}setFromUnitVectors(e,t){let s=e.dot(t)+1;return sMath.abs(e.z)?(this._x=-e.y,this._y=e.x,this._z=0,this._w=s):(this._x=0,this._y=-e.z,this._z=e.y,this._w=s)):(this._x=e.y*t.z-e.z*t.y,this._y=e.z*t.x-e.x*t.z,this._z=e.x*t.y-e.y*t.x,this._w=s),this.normalize()}angleTo(e){return 2*Math.acos(Math.abs($s(this.dot(e),-1,1)))}rotateTowards(e,t){const s=this.angleTo(e);if(0===s)return this;const i=Math.min(1,t/s);return this.slerp(e,i),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(e){return this._x*e._x+this._y*e._y+this._z*e._z+this._w*e._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 e=this.length();return 0===e?(this._x=0,this._y=0,this._z=0,this._w=1):(e=1/e,this._x=this._x*e,this._y=this._y*e,this._z=this._z*e,this._w=this._w*e),this._onChangeCallback(),this}multiply(e){return this.multiplyQuaternions(this,e)}premultiply(e){return this.multiplyQuaternions(e,this)}multiplyQuaternions(e,t){const s=e._x,i=e._y,r=e._z,n=e._w,o=t._x,a=t._y,h=t._z,u=t._w;return this._x=s*u+n*o+i*h-r*a,this._y=i*u+n*a+r*o-s*h,this._z=r*u+n*h+s*a-i*o,this._w=n*u-s*o-i*a-r*h,this._onChangeCallback(),this}slerp(e,t){if(0===t)return this;if(1===t)return this.copy(e);const s=this._x,i=this._y,r=this._z,n=this._w;let o=n*e._w+s*e._x+i*e._y+r*e._z;if(o<0?(this._w=-e._w,this._x=-e._x,this._y=-e._y,this._z=-e._z,o=-o):this.copy(e),o>=1)return this._w=n,this._x=s,this._y=i,this._z=r,this;const a=1-o*o;if(a<=Number.EPSILON){const e=1-t;return this._w=e*n+t*this._w,this._x=e*s+t*this._x,this._y=e*i+t*this._y,this._z=e*r+t*this._z,this.normalize(),this}const h=Math.sqrt(a),u=Math.atan2(h,o),l=Math.sin((1-t)*u)/h,c=Math.sin(t*u)/h;return this._w=n*l+this._w*c,this._x=s*l+this._x*c,this._y=i*l+this._y*c,this._z=r*l+this._z*c,this._onChangeCallback(),this}slerpQuaternions(e,t,s){return this.copy(e).slerp(t,s)}random(){const e=2*Math.PI*Math.random(),t=2*Math.PI*Math.random(),s=Math.random(),i=Math.sqrt(1-s),r=Math.sqrt(s);return this.set(i*Math.sin(e),i*Math.cos(e),r*Math.sin(t),r*Math.cos(t))}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._w===this._w}fromArray(e,t=0){return this._x=e[t],this._y=e[t+1],this._z=e[t+2],this._w=e[t+3],this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._w,e}fromBufferAttribute(e,t){return this._x=e.getX(t),this._y=e.getY(t),this._z=e.getZ(t),this._w=e.getW(t),this._onChangeCallback(),this}toJSON(){return this.toArray()}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._w}}class Ri{constructor(e=0,t=0,s=0){Ri.prototype.isVector3=!0,this.x=e,this.y=t,this.z=s}set(e,t,s){return void 0===s&&(s=this.z),this.x=e,this.y=t,this.z=s,this}setScalar(e){return this.x=e,this.y=e,this.z=e,this}setX(e){return this.x=e,this}setY(e){return this.y=e,this}setZ(e){return this.z=e,this}setComponent(e,t){switch(e){case 0:this.x=t;break;case 1:this.y=t;break;case 2:this.z=t;break;default:throw new Error("index is out of range: "+e)}return this}getComponent(e){switch(e){case 0:return this.x;case 1:return this.y;case 2:return this.z;default:throw new Error("index is out of range: "+e)}}clone(){return new this.constructor(this.x,this.y,this.z)}copy(e){return this.x=e.x,this.y=e.y,this.z=e.z,this}add(e){return this.x+=e.x,this.y+=e.y,this.z+=e.z,this}addScalar(e){return this.x+=e,this.y+=e,this.z+=e,this}addVectors(e,t){return this.x=e.x+t.x,this.y=e.y+t.y,this.z=e.z+t.z,this}addScaledVector(e,t){return this.x+=e.x*t,this.y+=e.y*t,this.z+=e.z*t,this}sub(e){return this.x-=e.x,this.y-=e.y,this.z-=e.z,this}subScalar(e){return this.x-=e,this.y-=e,this.z-=e,this}subVectors(e,t){return this.x=e.x-t.x,this.y=e.y-t.y,this.z=e.z-t.z,this}multiply(e){return this.x*=e.x,this.y*=e.y,this.z*=e.z,this}multiplyScalar(e){return this.x*=e,this.y*=e,this.z*=e,this}multiplyVectors(e,t){return this.x=e.x*t.x,this.y=e.y*t.y,this.z=e.z*t.z,this}applyEuler(e){return this.applyQuaternion(Bi.setFromEuler(e))}applyAxisAngle(e,t){return this.applyQuaternion(Bi.setFromAxisAngle(e,t))}applyMatrix3(e){const t=this.x,s=this.y,i=this.z,r=e.elements;return this.x=r[0]*t+r[3]*s+r[6]*i,this.y=r[1]*t+r[4]*s+r[7]*i,this.z=r[2]*t+r[5]*s+r[8]*i,this}applyNormalMatrix(e){return this.applyMatrix3(e).normalize()}applyMatrix4(e){const t=this.x,s=this.y,i=this.z,r=e.elements,n=1/(r[3]*t+r[7]*s+r[11]*i+r[15]);return this.x=(r[0]*t+r[4]*s+r[8]*i+r[12])*n,this.y=(r[1]*t+r[5]*s+r[9]*i+r[13])*n,this.z=(r[2]*t+r[6]*s+r[10]*i+r[14])*n,this}applyQuaternion(e){const t=this.x,s=this.y,i=this.z,r=e.x,n=e.y,o=e.z,a=e.w,h=2*(n*i-o*s),u=2*(o*t-r*i),l=2*(r*s-n*t);return this.x=t+a*h+n*l-o*u,this.y=s+a*u+o*h-r*l,this.z=i+a*l+r*u-n*h,this}project(e){return this.applyMatrix4(e.matrixWorldInverse).applyMatrix4(e.projectionMatrix)}unproject(e){return this.applyMatrix4(e.projectionMatrixInverse).applyMatrix4(e.matrixWorld)}transformDirection(e){const t=this.x,s=this.y,i=this.z,r=e.elements;return this.x=r[0]*t+r[4]*s+r[8]*i,this.y=r[1]*t+r[5]*s+r[9]*i,this.z=r[2]*t+r[6]*s+r[10]*i,this.normalize()}divide(e){return this.x/=e.x,this.y/=e.y,this.z/=e.z,this}divideScalar(e){return this.multiplyScalar(1/e)}min(e){return this.x=Math.min(this.x,e.x),this.y=Math.min(this.y,e.y),this.z=Math.min(this.z,e.z),this}max(e){return this.x=Math.max(this.x,e.x),this.y=Math.max(this.y,e.y),this.z=Math.max(this.z,e.z),this}clamp(e,t){return this.x=Math.max(e.x,Math.min(t.x,this.x)),this.y=Math.max(e.y,Math.min(t.y,this.y)),this.z=Math.max(e.z,Math.min(t.z,this.z)),this}clampScalar(e,t){return this.x=Math.max(e,Math.min(t,this.x)),this.y=Math.max(e,Math.min(t,this.y)),this.z=Math.max(e,Math.min(t,this.z)),this}clampLength(e,t){const s=this.length();return this.divideScalar(s||1).multiplyScalar(Math.max(e,Math.min(t,s)))}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=Math.trunc(this.x),this.y=Math.trunc(this.y),this.z=Math.trunc(this.z),this}negate(){return this.x=-this.x,this.y=-this.y,this.z=-this.z,this}dot(e){return this.x*e.x+this.y*e.y+this.z*e.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(e){return this.normalize().multiplyScalar(e)}lerp(e,t){return this.x+=(e.x-this.x)*t,this.y+=(e.y-this.y)*t,this.z+=(e.z-this.z)*t,this}lerpVectors(e,t,s){return this.x=e.x+(t.x-e.x)*s,this.y=e.y+(t.y-e.y)*s,this.z=e.z+(t.z-e.z)*s,this}cross(e){return this.crossVectors(this,e)}crossVectors(e,t){const s=e.x,i=e.y,r=e.z,n=t.x,o=t.y,a=t.z;return this.x=i*a-r*o,this.y=r*n-s*a,this.z=s*o-i*n,this}projectOnVector(e){const t=e.lengthSq();if(0===t)return this.set(0,0,0);const s=e.dot(this)/t;return this.copy(e).multiplyScalar(s)}projectOnPlane(e){return Ei.copy(this).projectOnVector(e),this.sub(Ei)}reflect(e){return this.sub(Ei.copy(e).multiplyScalar(2*this.dot(e)))}angleTo(e){const t=Math.sqrt(this.lengthSq()*e.lengthSq());if(0===t)return Math.PI/2;const s=this.dot(e)/t;return Math.acos($s(s,-1,1))}distanceTo(e){return Math.sqrt(this.distanceToSquared(e))}distanceToSquared(e){const t=this.x-e.x,s=this.y-e.y,i=this.z-e.z;return t*t+s*s+i*i}manhattanDistanceTo(e){return Math.abs(this.x-e.x)+Math.abs(this.y-e.y)+Math.abs(this.z-e.z)}setFromSpherical(e){return this.setFromSphericalCoords(e.radius,e.phi,e.theta)}setFromSphericalCoords(e,t,s){const i=Math.sin(t)*e;return this.x=i*Math.sin(s),this.y=Math.cos(t)*e,this.z=i*Math.cos(s),this}setFromCylindrical(e){return this.setFromCylindricalCoords(e.radius,e.theta,e.y)}setFromCylindricalCoords(e,t,s){return this.x=e*Math.sin(t),this.y=s,this.z=e*Math.cos(t),this}setFromMatrixPosition(e){const t=e.elements;return this.x=t[12],this.y=t[13],this.z=t[14],this}setFromMatrixScale(e){const t=this.setFromMatrixColumn(e,0).length(),s=this.setFromMatrixColumn(e,1).length(),i=this.setFromMatrixColumn(e,2).length();return this.x=t,this.y=s,this.z=i,this}setFromMatrixColumn(e,t){return this.fromArray(e.elements,4*t)}setFromMatrix3Column(e,t){return this.fromArray(e.elements,3*t)}setFromEuler(e){return this.x=e._x,this.y=e._y,this.z=e._z,this}setFromColor(e){return this.x=e.r,this.y=e.g,this.z=e.b,this}equals(e){return e.x===this.x&&e.y===this.y&&e.z===this.z}fromArray(e,t=0){return this.x=e[t],this.y=e[t+1],this.z=e[t+2],this}toArray(e=[],t=0){return e[t]=this.x,e[t+1]=this.y,e[t+2]=this.z,e}fromBufferAttribute(e,t){return this.x=e.getX(t),this.y=e.getY(t),this.z=e.getZ(t),this}random(){return this.x=Math.random(),this.y=Math.random(),this.z=Math.random(),this}randomDirection(){const e=Math.random()*Math.PI*2,t=2*Math.random()-1,s=Math.sqrt(1-t*t);return this.x=s*Math.cos(e),this.y=t,this.z=s*Math.sin(e),this}*[Symbol.iterator](){yield this.x,yield this.y,yield this.z}}const Ei=new Ri,Bi=new Ci;class Ii{constructor(e=new Ri(1/0,1/0,1/0),t=new Ri(-1/0,-1/0,-1/0)){this.isBox3=!0,this.min=e,this.max=t}set(e,t){return this.min.copy(e),this.max.copy(t),this}setFromArray(e){this.makeEmpty();for(let t=0,s=e.length;t=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y&&e.z>=this.min.z&&e.z<=this.max.z}containsBox(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y&&this.min.z<=e.min.z&&e.max.z<=this.max.z}getParameter(e,t){return t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y),(e.z-this.min.z)/(this.max.z-this.min.z))}intersectsBox(e){return e.max.x>=this.min.x&&e.min.x<=this.max.x&&e.max.y>=this.min.y&&e.min.y<=this.max.y&&e.max.z>=this.min.z&&e.min.z<=this.max.z}intersectsSphere(e){return this.clampPoint(e.center,Fi),Fi.distanceToSquared(e.center)<=e.radius*e.radius}intersectsPlane(e){let t,s;return e.normal.x>0?(t=e.normal.x*this.min.x,s=e.normal.x*this.max.x):(t=e.normal.x*this.max.x,s=e.normal.x*this.min.x),e.normal.y>0?(t+=e.normal.y*this.min.y,s+=e.normal.y*this.max.y):(t+=e.normal.y*this.max.y,s+=e.normal.y*this.min.y),e.normal.z>0?(t+=e.normal.z*this.min.z,s+=e.normal.z*this.max.z):(t+=e.normal.z*this.max.z,s+=e.normal.z*this.min.z),t<=-e.constant&&s>=-e.constant}intersectsTriangle(e){if(this.isEmpty())return!1;this.getCenter(Gi),Wi.subVectors(this.max,Gi),Ui.subVectors(e.a,Gi),Oi.subVectors(e.b,Gi),Li.subVectors(e.c,Gi),Vi.subVectors(Oi,Ui),Di.subVectors(Li,Oi),ki.subVectors(Ui,Li);let t=[0,-Vi.z,Vi.y,0,-Di.z,Di.y,0,-ki.z,ki.y,Vi.z,0,-Vi.x,Di.z,0,-Di.x,ki.z,0,-ki.x,-Vi.y,Vi.x,0,-Di.y,Di.x,0,-ki.y,ki.x,0];return!!qi(t,Ui,Oi,Li,Wi)&&(t=[1,0,0,0,1,0,0,0,1],!!qi(t,Ui,Oi,Li,Wi)&&(ji.crossVectors(Vi,Di),t=[ji.x,ji.y,ji.z],qi(t,Ui,Oi,Li,Wi)))}clampPoint(e,t){return t.copy(e).clamp(this.min,this.max)}distanceToPoint(e){return this.clampPoint(e,Fi).distanceTo(e)}getBoundingSphere(e){return this.isEmpty()?e.makeEmpty():(this.getCenter(e.center),e.radius=.5*this.getSize(Fi).length()),e}intersect(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this}union(e){return this.min.min(e.min),this.max.max(e.max),this}applyMatrix4(e){return this.isEmpty()||(Pi[0].set(this.min.x,this.min.y,this.min.z).applyMatrix4(e),Pi[1].set(this.min.x,this.min.y,this.max.z).applyMatrix4(e),Pi[2].set(this.min.x,this.max.y,this.min.z).applyMatrix4(e),Pi[3].set(this.min.x,this.max.y,this.max.z).applyMatrix4(e),Pi[4].set(this.max.x,this.min.y,this.min.z).applyMatrix4(e),Pi[5].set(this.max.x,this.min.y,this.max.z).applyMatrix4(e),Pi[6].set(this.max.x,this.max.y,this.min.z).applyMatrix4(e),Pi[7].set(this.max.x,this.max.y,this.max.z).applyMatrix4(e),this.setFromPoints(Pi)),this}translate(e){return this.min.add(e),this.max.add(e),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}const Pi=[new Ri,new Ri,new Ri,new Ri,new Ri,new Ri,new Ri,new Ri],Fi=new Ri,zi=new Ii,Ui=new Ri,Oi=new Ri,Li=new Ri,Vi=new Ri,Di=new Ri,ki=new Ri,Gi=new Ri,Wi=new Ri,ji=new Ri,Hi=new Ri;function qi(e,t,s,i,r){for(let n=0,o=e.length-3;n<=o;n+=3){Hi.fromArray(e,n);const o=r.x*Math.abs(Hi.x)+r.y*Math.abs(Hi.y)+r.z*Math.abs(Hi.z),a=t.dot(Hi),h=s.dot(Hi),u=i.dot(Hi);if(Math.max(-Math.max(a,h,u),Math.min(a,h,u))>o)return!1}return!0}const $i=new Ii,Xi=new Ri,Yi=new Ri;class Zi{constructor(e=new Ri,t=-1){this.isSphere=!0,this.center=e,this.radius=t}set(e,t){return this.center.copy(e),this.radius=t,this}setFromPoints(e,t){const s=this.center;void 0!==t?s.copy(t):$i.setFromPoints(e).getCenter(s);let i=0;for(let t=0,r=e.length;tthis.radius*this.radius&&(t.sub(this.center).normalize(),t.multiplyScalar(this.radius).add(this.center)),t}getBoundingBox(e){return this.isEmpty()?(e.makeEmpty(),e):(e.set(this.center,this.center),e.expandByScalar(this.radius),e)}applyMatrix4(e){return this.center.applyMatrix4(e),this.radius=this.radius*e.getMaxScaleOnAxis(),this}translate(e){return this.center.add(e),this}expandByPoint(e){if(this.isEmpty())return this.center.copy(e),this.radius=0,this;Xi.subVectors(e,this.center);const t=Xi.lengthSq();if(t>this.radius*this.radius){const e=Math.sqrt(t),s=.5*(e-this.radius);this.center.addScaledVector(Xi,s/e),this.radius+=s}return this}union(e){return e.isEmpty()?this:this.isEmpty()?(this.copy(e),this):(!0===this.center.equals(e.center)?this.radius=Math.max(this.radius,e.radius):(Yi.subVectors(e.center,this.center).setLength(e.radius),this.expandByPoint(Xi.copy(e.center).add(Yi)),this.expandByPoint(Xi.copy(e.center).sub(Yi))),this)}equals(e){return e.center.equals(this.center)&&e.radius===this.radius}clone(){return(new this.constructor).copy(this)}}const Ji=new Ri,Ki=new Ri,Qi=new Ri,er=new Ri,tr=new Ri,sr=new Ri,ir=new Ri;class rr{constructor(e=new Ri,t=new Ri(0,0,-1)){this.origin=e,this.direction=t}set(e,t){return this.origin.copy(e),this.direction.copy(t),this}copy(e){return this.origin.copy(e.origin),this.direction.copy(e.direction),this}at(e,t){return t.copy(this.origin).addScaledVector(this.direction,e)}lookAt(e){return this.direction.copy(e).sub(this.origin).normalize(),this}recast(e){return this.origin.copy(this.at(e,Ji)),this}closestPointToPoint(e,t){t.subVectors(e,this.origin);const s=t.dot(this.direction);return s<0?t.copy(this.origin):t.copy(this.origin).addScaledVector(this.direction,s)}distanceToPoint(e){return Math.sqrt(this.distanceSqToPoint(e))}distanceSqToPoint(e){const t=Ji.subVectors(e,this.origin).dot(this.direction);return t<0?this.origin.distanceToSquared(e):(Ji.copy(this.origin).addScaledVector(this.direction,t),Ji.distanceToSquared(e))}distanceSqToSegment(e,t,s,i){Ki.copy(e).add(t).multiplyScalar(.5),Qi.copy(t).sub(e).normalize(),er.copy(this.origin).sub(Ki);const r=.5*e.distanceTo(t),n=-this.direction.dot(Qi),o=er.dot(this.direction),a=-er.dot(Qi),h=er.lengthSq(),u=Math.abs(1-n*n);let l,c,d,p;if(u>0)if(l=n*a-o,c=n*o-a,p=r*u,l>=0)if(c>=-p)if(c<=p){const e=1/u;l*=e,c*=e,d=l*(l+n*c+2*o)+c*(n*l+c+2*a)+h}else c=r,l=Math.max(0,-(n*c+o)),d=-l*l+c*(c+2*a)+h;else c=-r,l=Math.max(0,-(n*c+o)),d=-l*l+c*(c+2*a)+h;else c<=-p?(l=Math.max(0,-(-n*r+o)),c=l>0?-r:Math.min(Math.max(-r,-a),r),d=-l*l+c*(c+2*a)+h):c<=p?(l=0,c=Math.min(Math.max(-r,-a),r),d=c*(c+2*a)+h):(l=Math.max(0,-(n*r+o)),c=l>0?r:Math.min(Math.max(-r,-a),r),d=-l*l+c*(c+2*a)+h);else c=n>0?-r:r,l=Math.max(0,-(n*c+o)),d=-l*l+c*(c+2*a)+h;return s&&s.copy(this.origin).addScaledVector(this.direction,l),i&&i.copy(Ki).addScaledVector(Qi,c),d}intersectSphere(e,t){Ji.subVectors(e.center,this.origin);const s=Ji.dot(this.direction),i=Ji.dot(Ji)-s*s,r=e.radius*e.radius;if(i>r)return null;const n=Math.sqrt(r-i),o=s-n,a=s+n;return a<0?null:o<0?this.at(a,t):this.at(o,t)}intersectsSphere(e){return this.distanceSqToPoint(e.center)<=e.radius*e.radius}distanceToPlane(e){const t=e.normal.dot(this.direction);if(0===t)return 0===e.distanceToPoint(this.origin)?0:null;const s=-(this.origin.dot(e.normal)+e.constant)/t;return s>=0?s:null}intersectPlane(e,t){const s=this.distanceToPlane(e);return null===s?null:this.at(s,t)}intersectsPlane(e){const t=e.distanceToPoint(this.origin);if(0===t)return!0;return e.normal.dot(this.direction)*t<0}intersectBox(e,t){let s,i,r,n,o,a;const h=1/this.direction.x,u=1/this.direction.y,l=1/this.direction.z,c=this.origin;return h>=0?(s=(e.min.x-c.x)*h,i=(e.max.x-c.x)*h):(s=(e.max.x-c.x)*h,i=(e.min.x-c.x)*h),u>=0?(r=(e.min.y-c.y)*u,n=(e.max.y-c.y)*u):(r=(e.max.y-c.y)*u,n=(e.min.y-c.y)*u),s>n||r>i?null:((r>s||isNaN(s))&&(s=r),(n=0?(o=(e.min.z-c.z)*l,a=(e.max.z-c.z)*l):(o=(e.max.z-c.z)*l,a=(e.min.z-c.z)*l),s>a||o>i?null:((o>s||s!=s)&&(s=o),(a=0?s:i,t)))}intersectsBox(e){return null!==this.intersectBox(e,Ji)}intersectTriangle(e,t,s,i,r){tr.subVectors(t,e),sr.subVectors(s,e),ir.crossVectors(tr,sr);let n,o=this.direction.dot(ir);if(o>0){if(i)return null;n=1}else{if(!(o<0))return null;n=-1,o=-o}er.subVectors(this.origin,e);const a=n*this.direction.dot(sr.crossVectors(er,sr));if(a<0)return null;const h=n*this.direction.dot(tr.cross(er));if(h<0)return null;if(a+h>o)return null;const u=-n*er.dot(ir);return u<0?null:this.at(u/o,r)}applyMatrix4(e){return this.origin.applyMatrix4(e),this.direction.transformDirection(e),this}equals(e){return e.origin.equals(this.origin)&&e.direction.equals(this.direction)}clone(){return(new this.constructor).copy(this)}}class nr{constructor(e,t,s,i,r,n,o,a,h,u,l,c,d,p,m,g){nr.prototype.isMatrix4=!0,this.elements=[1,0,0,0,0,1,0,0,0,0,1,0,0,0,0,1],void 0!==e&&this.set(e,t,s,i,r,n,o,a,h,u,l,c,d,p,m,g)}set(e,t,s,i,r,n,o,a,h,u,l,c,d,p,m,g){const f=this.elements;return f[0]=e,f[4]=t,f[8]=s,f[12]=i,f[1]=r,f[5]=n,f[9]=o,f[13]=a,f[2]=h,f[6]=u,f[10]=l,f[14]=c,f[3]=d,f[7]=p,f[11]=m,f[15]=g,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 nr).fromArray(this.elements)}copy(e){const t=this.elements,s=e.elements;return t[0]=s[0],t[1]=s[1],t[2]=s[2],t[3]=s[3],t[4]=s[4],t[5]=s[5],t[6]=s[6],t[7]=s[7],t[8]=s[8],t[9]=s[9],t[10]=s[10],t[11]=s[11],t[12]=s[12],t[13]=s[13],t[14]=s[14],t[15]=s[15],this}copyPosition(e){const t=this.elements,s=e.elements;return t[12]=s[12],t[13]=s[13],t[14]=s[14],this}setFromMatrix3(e){const t=e.elements;return this.set(t[0],t[3],t[6],0,t[1],t[4],t[7],0,t[2],t[5],t[8],0,0,0,0,1),this}extractBasis(e,t,s){return e.setFromMatrixColumn(this,0),t.setFromMatrixColumn(this,1),s.setFromMatrixColumn(this,2),this}makeBasis(e,t,s){return this.set(e.x,t.x,s.x,0,e.y,t.y,s.y,0,e.z,t.z,s.z,0,0,0,0,1),this}extractRotation(e){const t=this.elements,s=e.elements,i=1/or.setFromMatrixColumn(e,0).length(),r=1/or.setFromMatrixColumn(e,1).length(),n=1/or.setFromMatrixColumn(e,2).length();return t[0]=s[0]*i,t[1]=s[1]*i,t[2]=s[2]*i,t[3]=0,t[4]=s[4]*r,t[5]=s[5]*r,t[6]=s[6]*r,t[7]=0,t[8]=s[8]*n,t[9]=s[9]*n,t[10]=s[10]*n,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromEuler(e){const t=this.elements,s=e.x,i=e.y,r=e.z,n=Math.cos(s),o=Math.sin(s),a=Math.cos(i),h=Math.sin(i),u=Math.cos(r),l=Math.sin(r);if("XYZ"===e.order){const e=n*u,s=n*l,i=o*u,r=o*l;t[0]=a*u,t[4]=-a*l,t[8]=h,t[1]=s+i*h,t[5]=e-r*h,t[9]=-o*a,t[2]=r-e*h,t[6]=i+s*h,t[10]=n*a}else if("YXZ"===e.order){const e=a*u,s=a*l,i=h*u,r=h*l;t[0]=e+r*o,t[4]=i*o-s,t[8]=n*h,t[1]=n*l,t[5]=n*u,t[9]=-o,t[2]=s*o-i,t[6]=r+e*o,t[10]=n*a}else if("ZXY"===e.order){const e=a*u,s=a*l,i=h*u,r=h*l;t[0]=e-r*o,t[4]=-n*l,t[8]=i+s*o,t[1]=s+i*o,t[5]=n*u,t[9]=r-e*o,t[2]=-n*h,t[6]=o,t[10]=n*a}else if("ZYX"===e.order){const e=n*u,s=n*l,i=o*u,r=o*l;t[0]=a*u,t[4]=i*h-s,t[8]=e*h+r,t[1]=a*l,t[5]=r*h+e,t[9]=s*h-i,t[2]=-h,t[6]=o*a,t[10]=n*a}else if("YZX"===e.order){const e=n*a,s=n*h,i=o*a,r=o*h;t[0]=a*u,t[4]=r-e*l,t[8]=i*l+s,t[1]=l,t[5]=n*u,t[9]=-o*u,t[2]=-h*u,t[6]=s*l+i,t[10]=e-r*l}else if("XZY"===e.order){const e=n*a,s=n*h,i=o*a,r=o*h;t[0]=a*u,t[4]=-l,t[8]=h*u,t[1]=e*l+r,t[5]=n*u,t[9]=s*l-i,t[2]=i*l-s,t[6]=o*u,t[10]=r*l+e}return t[3]=0,t[7]=0,t[11]=0,t[12]=0,t[13]=0,t[14]=0,t[15]=1,this}makeRotationFromQuaternion(e){return this.compose(hr,e,ur)}lookAt(e,t,s){const i=this.elements;return dr.subVectors(e,t),0===dr.lengthSq()&&(dr.z=1),dr.normalize(),lr.crossVectors(s,dr),0===lr.lengthSq()&&(1===Math.abs(s.z)?dr.x+=1e-4:dr.z+=1e-4,dr.normalize(),lr.crossVectors(s,dr)),lr.normalize(),cr.crossVectors(dr,lr),i[0]=lr.x,i[4]=cr.x,i[8]=dr.x,i[1]=lr.y,i[5]=cr.y,i[9]=dr.y,i[2]=lr.z,i[6]=cr.z,i[10]=dr.z,this}multiply(e){return this.multiplyMatrices(this,e)}premultiply(e){return this.multiplyMatrices(e,this)}multiplyMatrices(e,t){const s=e.elements,i=t.elements,r=this.elements,n=s[0],o=s[4],a=s[8],h=s[12],u=s[1],l=s[5],c=s[9],d=s[13],p=s[2],m=s[6],g=s[10],f=s[14],y=s[3],x=s[7],b=s[11],v=s[15],T=i[0],_=i[4],w=i[8],S=i[12],M=i[1],N=i[5],A=i[9],C=i[13],R=i[2],E=i[6],B=i[10],I=i[14],P=i[3],F=i[7],z=i[11],U=i[15];return r[0]=n*T+o*M+a*R+h*P,r[4]=n*_+o*N+a*E+h*F,r[8]=n*w+o*A+a*B+h*z,r[12]=n*S+o*C+a*I+h*U,r[1]=u*T+l*M+c*R+d*P,r[5]=u*_+l*N+c*E+d*F,r[9]=u*w+l*A+c*B+d*z,r[13]=u*S+l*C+c*I+d*U,r[2]=p*T+m*M+g*R+f*P,r[6]=p*_+m*N+g*E+f*F,r[10]=p*w+m*A+g*B+f*z,r[14]=p*S+m*C+g*I+f*U,r[3]=y*T+x*M+b*R+v*P,r[7]=y*_+x*N+b*E+v*F,r[11]=y*w+x*A+b*B+v*z,r[15]=y*S+x*C+b*I+v*U,this}multiplyScalar(e){const t=this.elements;return t[0]*=e,t[4]*=e,t[8]*=e,t[12]*=e,t[1]*=e,t[5]*=e,t[9]*=e,t[13]*=e,t[2]*=e,t[6]*=e,t[10]*=e,t[14]*=e,t[3]*=e,t[7]*=e,t[11]*=e,t[15]*=e,this}determinant(){const e=this.elements,t=e[0],s=e[4],i=e[8],r=e[12],n=e[1],o=e[5],a=e[9],h=e[13],u=e[2],l=e[6],c=e[10],d=e[14];return e[3]*(+r*a*l-i*h*l-r*o*c+s*h*c+i*o*d-s*a*d)+e[7]*(+t*a*d-t*h*c+r*n*c-i*n*d+i*h*u-r*a*u)+e[11]*(+t*h*l-t*o*d-r*n*l+s*n*d+r*o*u-s*h*u)+e[15]*(-i*o*u-t*a*l+t*o*c+i*n*l-s*n*c+s*a*u)}transpose(){const e=this.elements;let t;return t=e[1],e[1]=e[4],e[4]=t,t=e[2],e[2]=e[8],e[8]=t,t=e[6],e[6]=e[9],e[9]=t,t=e[3],e[3]=e[12],e[12]=t,t=e[7],e[7]=e[13],e[13]=t,t=e[11],e[11]=e[14],e[14]=t,this}setPosition(e,t,s){const i=this.elements;return e.isVector3?(i[12]=e.x,i[13]=e.y,i[14]=e.z):(i[12]=e,i[13]=t,i[14]=s),this}invert(){const e=this.elements,t=e[0],s=e[1],i=e[2],r=e[3],n=e[4],o=e[5],a=e[6],h=e[7],u=e[8],l=e[9],c=e[10],d=e[11],p=e[12],m=e[13],g=e[14],f=e[15],y=l*g*h-m*c*h+m*a*d-o*g*d-l*a*f+o*c*f,x=p*c*h-u*g*h-p*a*d+n*g*d+u*a*f-n*c*f,b=u*m*h-p*l*h+p*o*d-n*m*d-u*o*f+n*l*f,v=p*l*a-u*m*a-p*o*c+n*m*c+u*o*g-n*l*g,T=t*y+s*x+i*b+r*v;if(0===T)return this.set(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0);const _=1/T;return e[0]=y*_,e[1]=(m*c*r-l*g*r-m*i*d+s*g*d+l*i*f-s*c*f)*_,e[2]=(o*g*r-m*a*r+m*i*h-s*g*h-o*i*f+s*a*f)*_,e[3]=(l*a*r-o*c*r-l*i*h+s*c*h+o*i*d-s*a*d)*_,e[4]=x*_,e[5]=(u*g*r-p*c*r+p*i*d-t*g*d-u*i*f+t*c*f)*_,e[6]=(p*a*r-n*g*r-p*i*h+t*g*h+n*i*f-t*a*f)*_,e[7]=(n*c*r-u*a*r+u*i*h-t*c*h-n*i*d+t*a*d)*_,e[8]=b*_,e[9]=(p*l*r-u*m*r-p*s*d+t*m*d+u*s*f-t*l*f)*_,e[10]=(n*m*r-p*o*r+p*s*h-t*m*h-n*s*f+t*o*f)*_,e[11]=(u*o*r-n*l*r-u*s*h+t*l*h+n*s*d-t*o*d)*_,e[12]=v*_,e[13]=(u*m*i-p*l*i+p*s*c-t*m*c-u*s*g+t*l*g)*_,e[14]=(p*o*i-n*m*i-p*s*a+t*m*a+n*s*g-t*o*g)*_,e[15]=(n*l*i-u*o*i+u*s*a-t*l*a-n*s*c+t*o*c)*_,this}scale(e){const t=this.elements,s=e.x,i=e.y,r=e.z;return t[0]*=s,t[4]*=i,t[8]*=r,t[1]*=s,t[5]*=i,t[9]*=r,t[2]*=s,t[6]*=i,t[10]*=r,t[3]*=s,t[7]*=i,t[11]*=r,this}getMaxScaleOnAxis(){const e=this.elements,t=e[0]*e[0]+e[1]*e[1]+e[2]*e[2],s=e[4]*e[4]+e[5]*e[5]+e[6]*e[6],i=e[8]*e[8]+e[9]*e[9]+e[10]*e[10];return Math.sqrt(Math.max(t,s,i))}makeTranslation(e,t,s){return e.isVector3?this.set(1,0,0,e.x,0,1,0,e.y,0,0,1,e.z,0,0,0,1):this.set(1,0,0,e,0,1,0,t,0,0,1,s,0,0,0,1),this}makeRotationX(e){const t=Math.cos(e),s=Math.sin(e);return this.set(1,0,0,0,0,t,-s,0,0,s,t,0,0,0,0,1),this}makeRotationY(e){const t=Math.cos(e),s=Math.sin(e);return this.set(t,0,s,0,0,1,0,0,-s,0,t,0,0,0,0,1),this}makeRotationZ(e){const t=Math.cos(e),s=Math.sin(e);return this.set(t,-s,0,0,s,t,0,0,0,0,1,0,0,0,0,1),this}makeRotationAxis(e,t){const s=Math.cos(t),i=Math.sin(t),r=1-s,n=e.x,o=e.y,a=e.z,h=r*n,u=r*o;return this.set(h*n+s,h*o-i*a,h*a+i*o,0,h*o+i*a,u*o+s,u*a-i*n,0,h*a-i*o,u*a+i*n,r*a*a+s,0,0,0,0,1),this}makeScale(e,t,s){return this.set(e,0,0,0,0,t,0,0,0,0,s,0,0,0,0,1),this}makeShear(e,t,s,i,r,n){return this.set(1,s,r,0,e,1,n,0,t,i,1,0,0,0,0,1),this}compose(e,t,s){const i=this.elements,r=t._x,n=t._y,o=t._z,a=t._w,h=r+r,u=n+n,l=o+o,c=r*h,d=r*u,p=r*l,m=n*u,g=n*l,f=o*l,y=a*h,x=a*u,b=a*l,v=s.x,T=s.y,_=s.z;return i[0]=(1-(m+f))*v,i[1]=(d+b)*v,i[2]=(p-x)*v,i[3]=0,i[4]=(d-b)*T,i[5]=(1-(c+f))*T,i[6]=(g+y)*T,i[7]=0,i[8]=(p+x)*_,i[9]=(g-y)*_,i[10]=(1-(c+m))*_,i[11]=0,i[12]=e.x,i[13]=e.y,i[14]=e.z,i[15]=1,this}decompose(e,t,s){const i=this.elements;let r=or.set(i[0],i[1],i[2]).length();const n=or.set(i[4],i[5],i[6]).length(),o=or.set(i[8],i[9],i[10]).length();this.determinant()<0&&(r=-r),e.x=i[12],e.y=i[13],e.z=i[14],ar.copy(this);const a=1/r,h=1/n,u=1/o;return ar.elements[0]*=a,ar.elements[1]*=a,ar.elements[2]*=a,ar.elements[4]*=h,ar.elements[5]*=h,ar.elements[6]*=h,ar.elements[8]*=u,ar.elements[9]*=u,ar.elements[10]*=u,t.setFromRotationMatrix(ar),s.x=r,s.y=n,s.z=o,this}makePerspective(e,t,s,i,r,n,o=2e3){const a=this.elements,h=2*r/(t-e),u=2*r/(s-i),l=(t+e)/(t-e),c=(s+i)/(s-i);let d,p;if(o===Vs)d=-(n+r)/(n-r),p=-2*n*r/(n-r);else{if(o!==Ds)throw new Error("THREE.Matrix4.makePerspective(): Invalid coordinate system: "+o);d=-n/(n-r),p=-n*r/(n-r)}return a[0]=h,a[4]=0,a[8]=l,a[12]=0,a[1]=0,a[5]=u,a[9]=c,a[13]=0,a[2]=0,a[6]=0,a[10]=d,a[14]=p,a[3]=0,a[7]=0,a[11]=-1,a[15]=0,this}makeOrthographic(e,t,s,i,r,n,o=2e3){const a=this.elements,h=1/(t-e),u=1/(s-i),l=1/(n-r),c=(t+e)*h,d=(s+i)*u;let p,m;if(o===Vs)p=(n+r)*l,m=-2*l;else{if(o!==Ds)throw new Error("THREE.Matrix4.makeOrthographic(): Invalid coordinate system: "+o);p=r*l,m=-1*l}return a[0]=2*h,a[4]=0,a[8]=0,a[12]=-c,a[1]=0,a[5]=2*u,a[9]=0,a[13]=-d,a[2]=0,a[6]=0,a[10]=m,a[14]=-p,a[3]=0,a[7]=0,a[11]=0,a[15]=1,this}equals(e){const t=this.elements,s=e.elements;for(let e=0;e<16;e++)if(t[e]!==s[e])return!1;return!0}fromArray(e,t=0){for(let s=0;s<16;s++)this.elements[s]=e[s+t];return this}toArray(e=[],t=0){const s=this.elements;return e[t]=s[0],e[t+1]=s[1],e[t+2]=s[2],e[t+3]=s[3],e[t+4]=s[4],e[t+5]=s[5],e[t+6]=s[6],e[t+7]=s[7],e[t+8]=s[8],e[t+9]=s[9],e[t+10]=s[10],e[t+11]=s[11],e[t+12]=s[12],e[t+13]=s[13],e[t+14]=s[14],e[t+15]=s[15],e}}const or=new Ri,ar=new nr,hr=new Ri(0,0,0),ur=new Ri(1,1,1),lr=new Ri,cr=new Ri,dr=new Ri,pr=new nr,mr=new Ci;class gr{constructor(e=0,t=0,s=0,i=gr.DEFAULT_ORDER){this.isEuler=!0,this._x=e,this._y=t,this._z=s,this._order=i}get x(){return this._x}set x(e){this._x=e,this._onChangeCallback()}get y(){return this._y}set y(e){this._y=e,this._onChangeCallback()}get z(){return this._z}set z(e){this._z=e,this._onChangeCallback()}get order(){return this._order}set order(e){this._order=e,this._onChangeCallback()}set(e,t,s,i=this._order){return this._x=e,this._y=t,this._z=s,this._order=i,this._onChangeCallback(),this}clone(){return new this.constructor(this._x,this._y,this._z,this._order)}copy(e){return this._x=e._x,this._y=e._y,this._z=e._z,this._order=e._order,this._onChangeCallback(),this}setFromRotationMatrix(e,t=this._order,s=!0){const i=e.elements,r=i[0],n=i[4],o=i[8],a=i[1],h=i[5],u=i[9],l=i[2],c=i[6],d=i[10];switch(t){case"XYZ":this._y=Math.asin($s(o,-1,1)),Math.abs(o)<.9999999?(this._x=Math.atan2(-u,d),this._z=Math.atan2(-n,r)):(this._x=Math.atan2(c,h),this._z=0);break;case"YXZ":this._x=Math.asin(-$s(u,-1,1)),Math.abs(u)<.9999999?(this._y=Math.atan2(o,d),this._z=Math.atan2(a,h)):(this._y=Math.atan2(-l,r),this._z=0);break;case"ZXY":this._x=Math.asin($s(c,-1,1)),Math.abs(c)<.9999999?(this._y=Math.atan2(-l,d),this._z=Math.atan2(-n,h)):(this._y=0,this._z=Math.atan2(a,r));break;case"ZYX":this._y=Math.asin(-$s(l,-1,1)),Math.abs(l)<.9999999?(this._x=Math.atan2(c,d),this._z=Math.atan2(a,r)):(this._x=0,this._z=Math.atan2(-n,h));break;case"YZX":this._z=Math.asin($s(a,-1,1)),Math.abs(a)<.9999999?(this._x=Math.atan2(-u,h),this._y=Math.atan2(-l,r)):(this._x=0,this._y=Math.atan2(o,d));break;case"XZY":this._z=Math.asin(-$s(n,-1,1)),Math.abs(n)<.9999999?(this._x=Math.atan2(c,h),this._y=Math.atan2(o,r)):(this._x=Math.atan2(-u,d),this._y=0);break;default:console.warn("THREE.Euler: .setFromRotationMatrix() encountered an unknown order: "+t)}return this._order=t,!0===s&&this._onChangeCallback(),this}setFromQuaternion(e,t,s){return pr.makeRotationFromQuaternion(e),this.setFromRotationMatrix(pr,t,s)}setFromVector3(e,t=this._order){return this.set(e.x,e.y,e.z,t)}reorder(e){return mr.setFromEuler(this),this.setFromQuaternion(mr,e)}equals(e){return e._x===this._x&&e._y===this._y&&e._z===this._z&&e._order===this._order}fromArray(e){return this._x=e[0],this._y=e[1],this._z=e[2],void 0!==e[3]&&(this._order=e[3]),this._onChangeCallback(),this}toArray(e=[],t=0){return e[t]=this._x,e[t+1]=this._y,e[t+2]=this._z,e[t+3]=this._order,e}_onChange(e){return this._onChangeCallback=e,this}_onChangeCallback(){}*[Symbol.iterator](){yield this._x,yield this._y,yield this._z,yield this._order}}gr.DEFAULT_ORDER="XYZ";class fr{constructor(){this.mask=1}set(e){this.mask=(1<>>0}enable(e){this.mask|=1<1){for(let e=0;e1){for(let e=0;e0&&(i.userData=this.userData),i.layers=this.layers.mask,i.matrix=this.matrix.toArray(),i.up=this.up.toArray(),!1===this.matrixAutoUpdate&&(i.matrixAutoUpdate=!1),this.isInstancedMesh&&(i.type="InstancedMesh",i.count=this.count,i.instanceMatrix=this.instanceMatrix.toJSON(),null!==this.instanceColor&&(i.instanceColor=this.instanceColor.toJSON())),this.isBatchedMesh&&(i.type="BatchedMesh",i.perObjectFrustumCulled=this.perObjectFrustumCulled,i.sortObjects=this.sortObjects,i.drawRanges=this._drawRanges,i.reservedRanges=this._reservedRanges,i.visibility=this._visibility,i.active=this._active,i.bounds=this._bounds.map((e=>({boxInitialized:e.boxInitialized,boxMin:e.box.min.toArray(),boxMax:e.box.max.toArray(),sphereInitialized:e.sphereInitialized,sphereRadius:e.sphere.radius,sphereCenter:e.sphere.center.toArray()}))),i.maxInstanceCount=this._maxInstanceCount,i.maxVertexCount=this._maxVertexCount,i.maxIndexCount=this._maxIndexCount,i.geometryInitialized=this._geometryInitialized,i.geometryCount=this._geometryCount,i.matricesTexture=this._matricesTexture.toJSON(e),null!==this._colorsTexture&&(i.colorsTexture=this._colorsTexture.toJSON(e)),null!==this.boundingSphere&&(i.boundingSphere={center:i.boundingSphere.center.toArray(),radius:i.boundingSphere.radius}),null!==this.boundingBox&&(i.boundingBox={min:i.boundingBox.min.toArray(),max:i.boundingBox.max.toArray()})),this.isScene)this.background&&(this.background.isColor?i.background=this.background.toJSON():this.background.isTexture&&(i.background=this.background.toJSON(e).uuid)),this.environment&&this.environment.isTexture&&!0!==this.environment.isRenderTargetTexture&&(i.environment=this.environment.toJSON(e).uuid);else if(this.isMesh||this.isLine||this.isPoints){i.geometry=r(e.geometries,this.geometry);const t=this.geometry.parameters;if(void 0!==t&&void 0!==t.shapes){const s=t.shapes;if(Array.isArray(s))for(let t=0,i=s.length;t0){i.children=[];for(let t=0;t0){i.animations=[];for(let t=0;t0&&(s.geometries=t),i.length>0&&(s.materials=i),r.length>0&&(s.textures=r),o.length>0&&(s.images=o),a.length>0&&(s.shapes=a),h.length>0&&(s.skeletons=h),u.length>0&&(s.animations=u),l.length>0&&(s.nodes=l)}return s.object=i,s;function n(e){const t=[];for(const s in e){const i=e[s];delete i.metadata,t.push(i)}return t}}clone(e){return(new this.constructor).copy(this,e)}copy(e,t=!0){if(this.name=e.name,this.up.copy(e.up),this.position.copy(e.position),this.rotation.order=e.rotation.order,this.quaternion.copy(e.quaternion),this.scale.copy(e.scale),this.matrix.copy(e.matrix),this.matrixWorld.copy(e.matrixWorld),this.matrixAutoUpdate=e.matrixAutoUpdate,this.matrixWorldAutoUpdate=e.matrixWorldAutoUpdate,this.matrixWorldNeedsUpdate=e.matrixWorldNeedsUpdate,this.layers.mask=e.layers.mask,this.visible=e.visible,this.castShadow=e.castShadow,this.receiveShadow=e.receiveShadow,this.frustumCulled=e.frustumCulled,this.renderOrder=e.renderOrder,this.animations=e.animations.slice(),this.userData=JSON.parse(JSON.stringify(e.userData)),!0===t)for(let t=0;t0?i.multiplyScalar(1/Math.sqrt(r)):i.set(0,0,0)}static getBarycoord(e,t,s,i,r){Pr.subVectors(i,t),Fr.subVectors(s,t),zr.subVectors(e,t);const n=Pr.dot(Pr),o=Pr.dot(Fr),a=Pr.dot(zr),h=Fr.dot(Fr),u=Fr.dot(zr),l=n*h-o*o;if(0===l)return r.set(0,0,0),null;const c=1/l,d=(h*a-o*u)*c,p=(n*u-o*a)*c;return r.set(1-d-p,p,d)}static containsPoint(e,t,s,i){return null!==this.getBarycoord(e,t,s,i,Ur)&&(Ur.x>=0&&Ur.y>=0&&Ur.x+Ur.y<=1)}static getInterpolation(e,t,s,i,r,n,o,a){return null===this.getBarycoord(e,t,s,i,Ur)?(a.x=0,a.y=0,"z"in a&&(a.z=0),"w"in a&&(a.w=0),null):(a.setScalar(0),a.addScaledVector(r,Ur.x),a.addScaledVector(n,Ur.y),a.addScaledVector(o,Ur.z),a)}static getInterpolatedAttribute(e,t,s,i,r,n){return Wr.setScalar(0),jr.setScalar(0),Hr.setScalar(0),Wr.fromBufferAttribute(e,t),jr.fromBufferAttribute(e,s),Hr.fromBufferAttribute(e,i),n.setScalar(0),n.addScaledVector(Wr,r.x),n.addScaledVector(jr,r.y),n.addScaledVector(Hr,r.z),n}static isFrontFacing(e,t,s,i){return Pr.subVectors(s,t),Fr.subVectors(e,t),Pr.cross(Fr).dot(i)<0}set(e,t,s){return this.a.copy(e),this.b.copy(t),this.c.copy(s),this}setFromPointsAndIndices(e,t,s,i){return this.a.copy(e[t]),this.b.copy(e[s]),this.c.copy(e[i]),this}setFromAttributeAndIndices(e,t,s,i){return this.a.fromBufferAttribute(e,t),this.b.fromBufferAttribute(e,s),this.c.fromBufferAttribute(e,i),this}clone(){return(new this.constructor).copy(this)}copy(e){return this.a.copy(e.a),this.b.copy(e.b),this.c.copy(e.c),this}getArea(){return Pr.subVectors(this.c,this.b),Fr.subVectors(this.a,this.b),.5*Pr.cross(Fr).length()}getMidpoint(e){return e.addVectors(this.a,this.b).add(this.c).multiplyScalar(1/3)}getNormal(e){return qr.getNormal(this.a,this.b,this.c,e)}getPlane(e){return e.setFromCoplanarPoints(this.a,this.b,this.c)}getBarycoord(e,t){return qr.getBarycoord(e,this.a,this.b,this.c,t)}getInterpolation(e,t,s,i,r){return qr.getInterpolation(e,this.a,this.b,this.c,t,s,i,r)}containsPoint(e){return qr.containsPoint(e,this.a,this.b,this.c)}isFrontFacing(e){return qr.isFrontFacing(this.a,this.b,this.c,e)}intersectsBox(e){return e.intersectsTriangle(this)}closestPointToPoint(e,t){const s=this.a,i=this.b,r=this.c;let n,o;Or.subVectors(i,s),Lr.subVectors(r,s),Dr.subVectors(e,s);const a=Or.dot(Dr),h=Lr.dot(Dr);if(a<=0&&h<=0)return t.copy(s);kr.subVectors(e,i);const u=Or.dot(kr),l=Lr.dot(kr);if(u>=0&&l<=u)return t.copy(i);const c=a*l-u*h;if(c<=0&&a>=0&&u<=0)return n=a/(a-u),t.copy(s).addScaledVector(Or,n);Gr.subVectors(e,r);const d=Or.dot(Gr),p=Lr.dot(Gr);if(p>=0&&d<=p)return t.copy(r);const m=d*h-a*p;if(m<=0&&h>=0&&p<=0)return o=h/(h-p),t.copy(s).addScaledVector(Lr,o);const g=u*p-d*l;if(g<=0&&l-u>=0&&d-p>=0)return Vr.subVectors(r,i),o=(l-u)/(l-u+(d-p)),t.copy(i).addScaledVector(Vr,o);const f=1/(g+m+c);return n=m*f,o=c*f,t.copy(s).addScaledVector(Or,n).addScaledVector(Lr,o)}equals(e){return e.a.equals(this.a)&&e.b.equals(this.b)&&e.c.equals(this.c)}}const $r={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},Xr={h:0,s:0,l:0},Yr={h:0,s:0,l:0};function Zr(e,t,s){return s<0&&(s+=1),s>1&&(s-=1),s<1/6?e+6*(t-e)*s:s<.5?t:s<2/3?e+6*(t-e)*(2/3-s):e}class Jr{constructor(e,t,s){return this.isColor=!0,this.r=1,this.g=1,this.b=1,this.set(e,t,s)}set(e,t,s){if(void 0===t&&void 0===s){const t=e;t&&t.isColor?this.copy(t):"number"==typeof t?this.setHex(t):"string"==typeof t&&this.setStyle(t)}else this.setRGB(e,t,s);return this}setScalar(e){return this.r=e,this.g=e,this.b=e,this}setHex(e,t=Zt){return e=Math.floor(e),this.r=(e>>16&255)/255,this.g=(e>>8&255)/255,this.b=(255&e)/255,ci.toWorkingColorSpace(this,t),this}setRGB(e,t,s,i=ci.workingColorSpace){return this.r=e,this.g=t,this.b=s,ci.toWorkingColorSpace(this,i),this}setHSL(e,t,s,i=ci.workingColorSpace){if(e=Xs(e,1),t=$s(t,0,1),s=$s(s,0,1),0===t)this.r=this.g=this.b=s;else{const i=s<=.5?s*(1+t):s+t-s*t,r=2*s-i;this.r=Zr(r,i,e+1/3),this.g=Zr(r,i,e),this.b=Zr(r,i,e-1/3)}return ci.toWorkingColorSpace(this,i),this}setStyle(e,t=Zt){function s(t){void 0!==t&&parseFloat(t)<1&&console.warn("THREE.Color: Alpha component of "+e+" will be ignored.")}let i;if(i=/^(\w+)\(([^\)]*)\)/.exec(e)){let r;const n=i[1],o=i[2];switch(n){case"rgb":case"rgba":if(r=/^\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return s(r[4]),this.setRGB(Math.min(255,parseInt(r[1],10))/255,Math.min(255,parseInt(r[2],10))/255,Math.min(255,parseInt(r[3],10))/255,t);if(r=/^\s*(\d+)\%\s*,\s*(\d+)\%\s*,\s*(\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return s(r[4]),this.setRGB(Math.min(100,parseInt(r[1],10))/100,Math.min(100,parseInt(r[2],10))/100,Math.min(100,parseInt(r[3],10))/100,t);break;case"hsl":case"hsla":if(r=/^\s*(\d*\.?\d+)\s*,\s*(\d*\.?\d+)\%\s*,\s*(\d*\.?\d+)\%\s*(?:,\s*(\d*\.?\d+)\s*)?$/.exec(o))return s(r[4]),this.setHSL(parseFloat(r[1])/360,parseFloat(r[2])/100,parseFloat(r[3])/100,t);break;default:console.warn("THREE.Color: Unknown color model "+e)}}else if(i=/^\#([A-Fa-f\d]+)$/.exec(e)){const s=i[1],r=s.length;if(3===r)return this.setRGB(parseInt(s.charAt(0),16)/15,parseInt(s.charAt(1),16)/15,parseInt(s.charAt(2),16)/15,t);if(6===r)return this.setHex(parseInt(s,16),t);console.warn("THREE.Color: Invalid hex color "+e)}else if(e&&e.length>0)return this.setColorName(e,t);return this}setColorName(e,t=Zt){const s=$r[e.toLowerCase()];return void 0!==s?this.setHex(s,t):console.warn("THREE.Color: Unknown color "+e),this}clone(){return new this.constructor(this.r,this.g,this.b)}copy(e){return this.r=e.r,this.g=e.g,this.b=e.b,this}copySRGBToLinear(e){return this.r=di(e.r),this.g=di(e.g),this.b=di(e.b),this}copyLinearToSRGB(e){return this.r=pi(e.r),this.g=pi(e.g),this.b=pi(e.b),this}convertSRGBToLinear(){return this.copySRGBToLinear(this),this}convertLinearToSRGB(){return this.copyLinearToSRGB(this),this}getHex(e=Zt){return ci.fromWorkingColorSpace(Kr.copy(this),e),65536*Math.round($s(255*Kr.r,0,255))+256*Math.round($s(255*Kr.g,0,255))+Math.round($s(255*Kr.b,0,255))}getHexString(e=Zt){return("000000"+this.getHex(e).toString(16)).slice(-6)}getHSL(e,t=ci.workingColorSpace){ci.fromWorkingColorSpace(Kr.copy(this),t);const s=Kr.r,i=Kr.g,r=Kr.b,n=Math.max(s,i,r),o=Math.min(s,i,r);let a,h;const u=(o+n)/2;if(o===n)a=0,h=0;else{const e=n-o;switch(h=u<=.5?e/(n+o):e/(2-n-o),n){case s:a=(i-r)/e+(i0!=e>0&&this.version++,this._alphaTest=e}onBeforeRender(){}onBeforeCompile(){}customProgramCacheKey(){return this.onBeforeCompile.toString()}setValues(e){if(void 0!==e)for(const t in e){const s=e[t];if(void 0===s){console.warn(`THREE.Material: parameter '${t}' has value of undefined.`);continue}const i=this[t];void 0!==i?i&&i.isColor?i.set(s):i&&i.isVector3&&s&&s.isVector3?i.copy(s):this[t]=s:console.warn(`THREE.Material: '${t}' is not a property of THREE.${this.type}.`)}}toJSON(e){const t=void 0===e||"string"==typeof e;t&&(e={textures:{},images:{}});const s={metadata:{version:4.6,type:"Material",generator:"Material.toJSON"}};function i(e){const t=[];for(const s in e){const i=e[s];delete i.metadata,t.push(i)}return t}if(s.uuid=this.uuid,s.type=this.type,""!==this.name&&(s.name=this.name),this.color&&this.color.isColor&&(s.color=this.color.getHex()),void 0!==this.roughness&&(s.roughness=this.roughness),void 0!==this.metalness&&(s.metalness=this.metalness),void 0!==this.sheen&&(s.sheen=this.sheen),this.sheenColor&&this.sheenColor.isColor&&(s.sheenColor=this.sheenColor.getHex()),void 0!==this.sheenRoughness&&(s.sheenRoughness=this.sheenRoughness),this.emissive&&this.emissive.isColor&&(s.emissive=this.emissive.getHex()),void 0!==this.emissiveIntensity&&1!==this.emissiveIntensity&&(s.emissiveIntensity=this.emissiveIntensity),this.specular&&this.specular.isColor&&(s.specular=this.specular.getHex()),void 0!==this.specularIntensity&&(s.specularIntensity=this.specularIntensity),this.specularColor&&this.specularColor.isColor&&(s.specularColor=this.specularColor.getHex()),void 0!==this.shininess&&(s.shininess=this.shininess),void 0!==this.clearcoat&&(s.clearcoat=this.clearcoat),void 0!==this.clearcoatRoughness&&(s.clearcoatRoughness=this.clearcoatRoughness),this.clearcoatMap&&this.clearcoatMap.isTexture&&(s.clearcoatMap=this.clearcoatMap.toJSON(e).uuid),this.clearcoatRoughnessMap&&this.clearcoatRoughnessMap.isTexture&&(s.clearcoatRoughnessMap=this.clearcoatRoughnessMap.toJSON(e).uuid),this.clearcoatNormalMap&&this.clearcoatNormalMap.isTexture&&(s.clearcoatNormalMap=this.clearcoatNormalMap.toJSON(e).uuid,s.clearcoatNormalScale=this.clearcoatNormalScale.toArray()),void 0!==this.dispersion&&(s.dispersion=this.dispersion),void 0!==this.iridescence&&(s.iridescence=this.iridescence),void 0!==this.iridescenceIOR&&(s.iridescenceIOR=this.iridescenceIOR),void 0!==this.iridescenceThicknessRange&&(s.iridescenceThicknessRange=this.iridescenceThicknessRange),this.iridescenceMap&&this.iridescenceMap.isTexture&&(s.iridescenceMap=this.iridescenceMap.toJSON(e).uuid),this.iridescenceThicknessMap&&this.iridescenceThicknessMap.isTexture&&(s.iridescenceThicknessMap=this.iridescenceThicknessMap.toJSON(e).uuid),void 0!==this.anisotropy&&(s.anisotropy=this.anisotropy),void 0!==this.anisotropyRotation&&(s.anisotropyRotation=this.anisotropyRotation),this.anisotropyMap&&this.anisotropyMap.isTexture&&(s.anisotropyMap=this.anisotropyMap.toJSON(e).uuid),this.map&&this.map.isTexture&&(s.map=this.map.toJSON(e).uuid),this.matcap&&this.matcap.isTexture&&(s.matcap=this.matcap.toJSON(e).uuid),this.alphaMap&&this.alphaMap.isTexture&&(s.alphaMap=this.alphaMap.toJSON(e).uuid),this.lightMap&&this.lightMap.isTexture&&(s.lightMap=this.lightMap.toJSON(e).uuid,s.lightMapIntensity=this.lightMapIntensity),this.aoMap&&this.aoMap.isTexture&&(s.aoMap=this.aoMap.toJSON(e).uuid,s.aoMapIntensity=this.aoMapIntensity),this.bumpMap&&this.bumpMap.isTexture&&(s.bumpMap=this.bumpMap.toJSON(e).uuid,s.bumpScale=this.bumpScale),this.normalMap&&this.normalMap.isTexture&&(s.normalMap=this.normalMap.toJSON(e).uuid,s.normalMapType=this.normalMapType,s.normalScale=this.normalScale.toArray()),this.displacementMap&&this.displacementMap.isTexture&&(s.displacementMap=this.displacementMap.toJSON(e).uuid,s.displacementScale=this.displacementScale,s.displacementBias=this.displacementBias),this.roughnessMap&&this.roughnessMap.isTexture&&(s.roughnessMap=this.roughnessMap.toJSON(e).uuid),this.metalnessMap&&this.metalnessMap.isTexture&&(s.metalnessMap=this.metalnessMap.toJSON(e).uuid),this.emissiveMap&&this.emissiveMap.isTexture&&(s.emissiveMap=this.emissiveMap.toJSON(e).uuid),this.specularMap&&this.specularMap.isTexture&&(s.specularMap=this.specularMap.toJSON(e).uuid),this.specularIntensityMap&&this.specularIntensityMap.isTexture&&(s.specularIntensityMap=this.specularIntensityMap.toJSON(e).uuid),this.specularColorMap&&this.specularColorMap.isTexture&&(s.specularColorMap=this.specularColorMap.toJSON(e).uuid),this.envMap&&this.envMap.isTexture&&(s.envMap=this.envMap.toJSON(e).uuid,void 0!==this.combine&&(s.combine=this.combine)),void 0!==this.envMapRotation&&(s.envMapRotation=this.envMapRotation.toArray()),void 0!==this.envMapIntensity&&(s.envMapIntensity=this.envMapIntensity),void 0!==this.reflectivity&&(s.reflectivity=this.reflectivity),void 0!==this.refractionRatio&&(s.refractionRatio=this.refractionRatio),this.gradientMap&&this.gradientMap.isTexture&&(s.gradientMap=this.gradientMap.toJSON(e).uuid),void 0!==this.transmission&&(s.transmission=this.transmission),this.transmissionMap&&this.transmissionMap.isTexture&&(s.transmissionMap=this.transmissionMap.toJSON(e).uuid),void 0!==this.thickness&&(s.thickness=this.thickness),this.thicknessMap&&this.thicknessMap.isTexture&&(s.thicknessMap=this.thicknessMap.toJSON(e).uuid),void 0!==this.attenuationDistance&&this.attenuationDistance!==1/0&&(s.attenuationDistance=this.attenuationDistance),void 0!==this.attenuationColor&&(s.attenuationColor=this.attenuationColor.getHex()),void 0!==this.size&&(s.size=this.size),null!==this.shadowSide&&(s.shadowSide=this.shadowSide),void 0!==this.sizeAttenuation&&(s.sizeAttenuation=this.sizeAttenuation),1!==this.blending&&(s.blending=this.blending),this.side!==c&&(s.side=this.side),!0===this.vertexColors&&(s.vertexColors=!0),this.opacity<1&&(s.opacity=this.opacity),!0===this.transparent&&(s.transparent=!0),this.blendSrc!==R&&(s.blendSrc=this.blendSrc),this.blendDst!==E&&(s.blendDst=this.blendDst),this.blendEquation!==v&&(s.blendEquation=this.blendEquation),null!==this.blendSrcAlpha&&(s.blendSrcAlpha=this.blendSrcAlpha),null!==this.blendDstAlpha&&(s.blendDstAlpha=this.blendDstAlpha),null!==this.blendEquationAlpha&&(s.blendEquationAlpha=this.blendEquationAlpha),this.blendColor&&this.blendColor.isColor&&(s.blendColor=this.blendColor.getHex()),0!==this.blendAlpha&&(s.blendAlpha=this.blendAlpha),3!==this.depthFunc&&(s.depthFunc=this.depthFunc),!1===this.depthTest&&(s.depthTest=this.depthTest),!1===this.depthWrite&&(s.depthWrite=this.depthWrite),!1===this.colorWrite&&(s.colorWrite=this.colorWrite),255!==this.stencilWriteMask&&(s.stencilWriteMask=this.stencilWriteMask),this.stencilFunc!==bs&&(s.stencilFunc=this.stencilFunc),0!==this.stencilRef&&(s.stencilRef=this.stencilRef),255!==this.stencilFuncMask&&(s.stencilFuncMask=this.stencilFuncMask),this.stencilFail!==ns&&(s.stencilFail=this.stencilFail),this.stencilZFail!==ns&&(s.stencilZFail=this.stencilZFail),this.stencilZPass!==ns&&(s.stencilZPass=this.stencilZPass),!0===this.stencilWrite&&(s.stencilWrite=this.stencilWrite),void 0!==this.rotation&&0!==this.rotation&&(s.rotation=this.rotation),!0===this.polygonOffset&&(s.polygonOffset=!0),0!==this.polygonOffsetFactor&&(s.polygonOffsetFactor=this.polygonOffsetFactor),0!==this.polygonOffsetUnits&&(s.polygonOffsetUnits=this.polygonOffsetUnits),void 0!==this.linewidth&&1!==this.linewidth&&(s.linewidth=this.linewidth),void 0!==this.dashSize&&(s.dashSize=this.dashSize),void 0!==this.gapSize&&(s.gapSize=this.gapSize),void 0!==this.scale&&(s.scale=this.scale),!0===this.dithering&&(s.dithering=!0),this.alphaTest>0&&(s.alphaTest=this.alphaTest),!0===this.alphaHash&&(s.alphaHash=!0),!0===this.alphaToCoverage&&(s.alphaToCoverage=!0),!0===this.premultipliedAlpha&&(s.premultipliedAlpha=!0),!0===this.forceSinglePass&&(s.forceSinglePass=!0),!0===this.wireframe&&(s.wireframe=!0),this.wireframeLinewidth>1&&(s.wireframeLinewidth=this.wireframeLinewidth),"round"!==this.wireframeLinecap&&(s.wireframeLinecap=this.wireframeLinecap),"round"!==this.wireframeLinejoin&&(s.wireframeLinejoin=this.wireframeLinejoin),!0===this.flatShading&&(s.flatShading=!0),!1===this.visible&&(s.visible=!1),!1===this.toneMapped&&(s.toneMapped=!1),!1===this.fog&&(s.fog=!1),Object.keys(this.userData).length>0&&(s.userData=this.userData),t){const t=i(e.textures),r=i(e.images);t.length>0&&(s.textures=t),r.length>0&&(s.images=r)}return s}clone(){return(new this.constructor).copy(this)}copy(e){this.name=e.name,this.blending=e.blending,this.side=e.side,this.vertexColors=e.vertexColors,this.opacity=e.opacity,this.transparent=e.transparent,this.blendSrc=e.blendSrc,this.blendDst=e.blendDst,this.blendEquation=e.blendEquation,this.blendSrcAlpha=e.blendSrcAlpha,this.blendDstAlpha=e.blendDstAlpha,this.blendEquationAlpha=e.blendEquationAlpha,this.blendColor.copy(e.blendColor),this.blendAlpha=e.blendAlpha,this.depthFunc=e.depthFunc,this.depthTest=e.depthTest,this.depthWrite=e.depthWrite,this.stencilWriteMask=e.stencilWriteMask,this.stencilFunc=e.stencilFunc,this.stencilRef=e.stencilRef,this.stencilFuncMask=e.stencilFuncMask,this.stencilFail=e.stencilFail,this.stencilZFail=e.stencilZFail,this.stencilZPass=e.stencilZPass,this.stencilWrite=e.stencilWrite;const t=e.clippingPlanes;let s=null;if(null!==t){const e=t.length;s=new Array(e);for(let i=0;i!==e;++i)s[i]=t[i].clone()}return this.clippingPlanes=s,this.clipIntersection=e.clipIntersection,this.clipShadows=e.clipShadows,this.shadowSide=e.shadowSide,this.colorWrite=e.colorWrite,this.precision=e.precision,this.polygonOffset=e.polygonOffset,this.polygonOffsetFactor=e.polygonOffsetFactor,this.polygonOffsetUnits=e.polygonOffsetUnits,this.dithering=e.dithering,this.alphaTest=e.alphaTest,this.alphaHash=e.alphaHash,this.alphaToCoverage=e.alphaToCoverage,this.premultipliedAlpha=e.premultipliedAlpha,this.forceSinglePass=e.forceSinglePass,this.visible=e.visible,this.toneMapped=e.toneMapped,this.userData=JSON.parse(JSON.stringify(e.userData)),this}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(e){!0===e&&this.version++}onBuild(){console.warn("Material: onBuild() has been removed.")}}class tn extends en{constructor(e){super(),this.isMeshBasicMaterial=!0,this.type="MeshBasicMaterial",this.color=new Jr(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.envMapRotation=new gr,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(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.fog=e.fog,this}}const sn=rn();function rn(){const e=new ArrayBuffer(4),t=new Float32Array(e),s=new Uint32Array(e),i=new Uint32Array(512),r=new Uint32Array(512);for(let e=0;e<256;++e){const t=e-127;t<-27?(i[e]=0,i[256|e]=32768,r[e]=24,r[256|e]=24):t<-14?(i[e]=1024>>-t-14,i[256|e]=1024>>-t-14|32768,r[e]=-t-1,r[256|e]=-t-1):t<=15?(i[e]=t+15<<10,i[256|e]=t+15<<10|32768,r[e]=13,r[256|e]=13):t<128?(i[e]=31744,i[256|e]=64512,r[e]=24,r[256|e]=24):(i[e]=31744,i[256|e]=64512,r[e]=13,r[256|e]=13)}const n=new Uint32Array(2048),o=new Uint32Array(64),a=new Uint32Array(64);for(let e=1;e<1024;++e){let t=e<<13,s=0;for(;0==(8388608&t);)t<<=1,s-=8388608;t&=-8388609,s+=947912704,n[e]=t|s}for(let e=1024;e<2048;++e)n[e]=939524096+(e-1024<<13);for(let e=1;e<31;++e)o[e]=e<<23;o[31]=1199570944,o[32]=2147483648;for(let e=33;e<63;++e)o[e]=2147483648+(e-32<<23);o[63]=3347054592;for(let e=1;e<64;++e)32!==e&&(a[e]=1024);return{floatView:t,uint32View:s,baseTable:i,shiftTable:r,mantissaTable:n,exponentTable:o,offsetTable:a}}function nn(e){Math.abs(e)>65504&&console.warn("THREE.DataUtils.toHalfFloat(): Value out of range."),e=$s(e,-65504,65504),sn.floatView[0]=e;const t=sn.uint32View[0],s=t>>23&511;return sn.baseTable[s]+((8388607&t)>>sn.shiftTable[s])}function on(e){const t=e>>10;return sn.uint32View[0]=sn.mantissaTable[sn.offsetTable[t]+(1023&e)]+sn.exponentTable[t],sn.floatView[0]}const an={toHalfFloat:nn,fromHalfFloat:on},hn=new Ri,un=new Qs;class ln{constructor(e,t,s=!1){if(Array.isArray(e))throw new TypeError("THREE.BufferAttribute: array should be a Typed Array.");this.isBufferAttribute=!0,this.name="",this.array=e,this.itemSize=t,this.count=void 0!==e?e.length/t:0,this.normalized=s,this.usage=Cs,this.updateRanges=[],this.gpuType=Ie,this.version=0}onUploadCallback(){}set needsUpdate(e){!0===e&&this.version++}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.name=e.name,this.array=new e.array.constructor(e.array),this.itemSize=e.itemSize,this.count=e.count,this.normalized=e.normalized,this.usage=e.usage,this.gpuType=e.gpuType,this}copyAt(e,t,s){e*=this.itemSize,s*=t.itemSize;for(let i=0,r=this.itemSize;i=0;--t)if(e[t]>=65535)return!0;return!1}(e)?yn:gn)(e,1):this.index=e,this}getAttribute(e){return this.attributes[e]}setAttribute(e,t){return this.attributes[e]=t,this}deleteAttribute(e){return delete this.attributes[e],this}hasAttribute(e){return void 0!==this.attributes[e]}addGroup(e,t,s=0){this.groups.push({start:e,count:t,materialIndex:s})}clearGroups(){this.groups=[]}setDrawRange(e,t){this.drawRange.start=e,this.drawRange.count=t}applyMatrix4(e){const t=this.attributes.position;void 0!==t&&(t.applyMatrix4(e),t.needsUpdate=!0);const s=this.attributes.normal;if(void 0!==s){const t=(new ei).getNormalMatrix(e);s.applyNormalMatrix(t),s.needsUpdate=!0}const i=this.attributes.tangent;return void 0!==i&&(i.transformDirection(e),i.needsUpdate=!0),null!==this.boundingBox&&this.computeBoundingBox(),null!==this.boundingSphere&&this.computeBoundingSphere(),this}applyQuaternion(e){return Tn.makeRotationFromQuaternion(e),this.applyMatrix4(Tn),this}rotateX(e){return Tn.makeRotationX(e),this.applyMatrix4(Tn),this}rotateY(e){return Tn.makeRotationY(e),this.applyMatrix4(Tn),this}rotateZ(e){return Tn.makeRotationZ(e),this.applyMatrix4(Tn),this}translate(e,t,s){return Tn.makeTranslation(e,t,s),this.applyMatrix4(Tn),this}scale(e,t,s){return Tn.makeScale(e,t,s),this.applyMatrix4(Tn),this}lookAt(e){return _n.lookAt(e),_n.updateMatrix(),this.applyMatrix4(_n.matrix),this}center(){return this.computeBoundingBox(),this.boundingBox.getCenter(wn).negate(),this.translate(wn.x,wn.y,wn.z),this}setFromPoints(e){const t=[];for(let s=0,i=e.length;s0&&(e.userData=this.userData),void 0!==this.parameters){const t=this.parameters;for(const s in t)void 0!==t[s]&&(e[s]=t[s]);return e}e.data={attributes:{}};const t=this.index;null!==t&&(e.data.index={type:t.array.constructor.name,array:Array.prototype.slice.call(t.array)});const s=this.attributes;for(const t in s){const i=s[t];e.data.attributes[t]=i.toJSON(e.data)}const i={};let r=!1;for(const t in this.morphAttributes){const s=this.morphAttributes[t],n=[];for(let t=0,i=s.length;t0&&(i[t]=n,r=!0)}r&&(e.data.morphAttributes=i,e.data.morphTargetsRelative=this.morphTargetsRelative);const n=this.groups;n.length>0&&(e.data.groups=JSON.parse(JSON.stringify(n)));const o=this.boundingSphere;return null!==o&&(e.data.boundingSphere={center:o.center.toArray(),radius:o.radius}),e}clone(){return(new this.constructor).copy(this)}copy(e){this.index=null,this.attributes={},this.morphAttributes={},this.groups=[],this.boundingBox=null,this.boundingSphere=null;const t={};this.name=e.name;const s=e.index;null!==s&&this.setIndex(s.clone(t));const i=e.attributes;for(const e in i){const s=i[e];this.setAttribute(e,s.clone(t))}const r=e.morphAttributes;for(const e in r){const s=[],i=r[e];for(let e=0,r=i.length;e0){const s=e[t[0]];if(void 0!==s){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=s.length;e(e.far-e.near)**2)return}Cn.copy(r).invert(),Rn.copy(e.ray).applyMatrix4(Cn),null!==s.boundingBox&&!1===Rn.intersectsBox(s.boundingBox)||this._computeIntersections(e,t,Rn)}}_computeIntersections(e,t,s){let i;const r=this.geometry,n=this.material,o=r.index,a=r.attributes.position,h=r.attributes.uv,u=r.attributes.uv1,l=r.attributes.normal,c=r.groups,d=r.drawRange;if(null!==o)if(Array.isArray(n))for(let r=0,a=c.length;rs.far?null:{distance:u,point:Ln.clone(),object:e}}(e,t,s,i,In,Pn,Fn,On);if(l){const e=new Ri;qr.getBarycoord(On,In,Pn,Fn,e),r&&(l.uv=qr.getInterpolatedAttribute(r,a,h,u,e,new Qs)),n&&(l.uv1=qr.getInterpolatedAttribute(n,a,h,u,e,new Qs)),o&&(l.normal=qr.getInterpolatedAttribute(o,a,h,u,e,new Ri),l.normal.dot(i.direction)>0&&l.normal.multiplyScalar(-1));const t={a:a,b:h,c:u,normal:new Ri,materialIndex:0};qr.getNormal(In,Pn,Fn,t.normal),l.face=t,l.barycoord=e}return l}class kn extends An{constructor(e=1,t=1,s=1,i=1,r=1,n=1){super(),this.type="BoxGeometry",this.parameters={width:e,height:t,depth:s,widthSegments:i,heightSegments:r,depthSegments:n};const o=this;i=Math.floor(i),r=Math.floor(r),n=Math.floor(n);const a=[],h=[],u=[],l=[];let c=0,d=0;function p(e,t,s,i,r,n,p,m,g,f,y){const x=n/g,b=p/f,v=n/2,T=p/2,_=m/2,w=g+1,S=f+1;let M=0,N=0;const A=new Ri;for(let n=0;n0?1:-1,u.push(A.x,A.y,A.z),l.push(a/g),l.push(1-n/f),M+=1}}for(let e=0;e0&&(t.defines=this.defines),t.vertexShader=this.vertexShader,t.fragmentShader=this.fragmentShader,t.lights=this.lights,t.clipping=this.clipping;const s={};for(const e in this.extensions)!0===this.extensions[e]&&(s[e]=!0);return Object.keys(s).length>0&&(t.extensions=s),t}}class jn extends Ir{constructor(){super(),this.isCamera=!0,this.type="Camera",this.matrixWorldInverse=new nr,this.projectionMatrix=new nr,this.projectionMatrixInverse=new nr,this.coordinateSystem=Vs}copy(e,t){return super.copy(e,t),this.matrixWorldInverse.copy(e.matrixWorldInverse),this.projectionMatrix.copy(e.projectionMatrix),this.projectionMatrixInverse.copy(e.projectionMatrixInverse),this.coordinateSystem=e.coordinateSystem,this}getWorldDirection(e){return super.getWorldDirection(e).negate()}updateMatrixWorld(e){super.updateMatrixWorld(e),this.matrixWorldInverse.copy(this.matrixWorld).invert()}updateWorldMatrix(e,t){super.updateWorldMatrix(e,t),this.matrixWorldInverse.copy(this.matrixWorld).invert()}clone(){return(new this.constructor).copy(this)}}const Hn=new Ri,qn=new Qs,$n=new Qs;class Xn extends jn{constructor(e=50,t=1,s=.1,i=2e3){super(),this.isPerspectiveCamera=!0,this.type="PerspectiveCamera",this.fov=e,this.zoom=1,this.near=s,this.far=i,this.focus=10,this.aspect=t,this.view=null,this.filmGauge=35,this.filmOffset=0,this.updateProjectionMatrix()}copy(e,t){return super.copy(e,t),this.fov=e.fov,this.zoom=e.zoom,this.near=e.near,this.far=e.far,this.focus=e.focus,this.aspect=e.aspect,this.view=null===e.view?null:Object.assign({},e.view),this.filmGauge=e.filmGauge,this.filmOffset=e.filmOffset,this}setFocalLength(e){const t=.5*this.getFilmHeight()/e;this.fov=2*Hs*Math.atan(t),this.updateProjectionMatrix()}getFocalLength(){const e=Math.tan(.5*js*this.fov);return.5*this.getFilmHeight()/e}getEffectiveFOV(){return 2*Hs*Math.atan(Math.tan(.5*js*this.fov)/this.zoom)}getFilmWidth(){return this.filmGauge*Math.min(this.aspect,1)}getFilmHeight(){return this.filmGauge/Math.max(this.aspect,1)}getViewBounds(e,t,s){Hn.set(-1,-1,.5).applyMatrix4(this.projectionMatrixInverse),t.set(Hn.x,Hn.y).multiplyScalar(-e/Hn.z),Hn.set(1,1,.5).applyMatrix4(this.projectionMatrixInverse),s.set(Hn.x,Hn.y).multiplyScalar(-e/Hn.z)}getViewSize(e,t){return this.getViewBounds(e,qn,$n),t.subVectors($n,qn)}setViewOffset(e,t,s,i,r,n){this.aspect=e/t,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=e,this.view.fullHeight=t,this.view.offsetX=s,this.view.offsetY=i,this.view.width=r,this.view.height=n,this.updateProjectionMatrix()}clearViewOffset(){null!==this.view&&(this.view.enabled=!1),this.updateProjectionMatrix()}updateProjectionMatrix(){const e=this.near;let t=e*Math.tan(.5*js*this.fov)/this.zoom,s=2*t,i=this.aspect*s,r=-.5*i;const n=this.view;if(null!==this.view&&this.view.enabled){const e=n.fullWidth,o=n.fullHeight;r+=n.offsetX*i/e,t-=n.offsetY*s/o,i*=n.width/e,s*=n.height/o}const o=this.filmOffset;0!==o&&(r+=e*o/this.getFilmWidth()),this.projectionMatrix.makePerspective(r,r+i,t,t-s,e,this.far,this.coordinateSystem),this.projectionMatrixInverse.copy(this.projectionMatrix).invert()}toJSON(e){const t=super.toJSON(e);return t.object.fov=this.fov,t.object.zoom=this.zoom,t.object.near=this.near,t.object.far=this.far,t.object.focus=this.focus,t.object.aspect=this.aspect,null!==this.view&&(t.object.view=Object.assign({},this.view)),t.object.filmGauge=this.filmGauge,t.object.filmOffset=this.filmOffset,t}}const Yn=-90;class Zn extends Ir{constructor(e,t,s){super(),this.type="CubeCamera",this.renderTarget=s,this.coordinateSystem=null,this.activeMipmapLevel=0;const i=new Xn(Yn,1,e,t);i.layers=this.layers,this.add(i);const r=new Xn(Yn,1,e,t);r.layers=this.layers,this.add(r);const n=new Xn(Yn,1,e,t);n.layers=this.layers,this.add(n);const o=new Xn(Yn,1,e,t);o.layers=this.layers,this.add(o);const a=new Xn(Yn,1,e,t);a.layers=this.layers,this.add(a);const h=new Xn(Yn,1,e,t);h.layers=this.layers,this.add(h)}updateCoordinateSystem(){const e=this.coordinateSystem,t=this.children.concat(),[s,i,r,n,o,a]=t;for(const e of t)this.remove(e);if(e===Vs)s.up.set(0,1,0),s.lookAt(1,0,0),i.up.set(0,1,0),i.lookAt(-1,0,0),r.up.set(0,0,-1),r.lookAt(0,1,0),n.up.set(0,0,1),n.lookAt(0,-1,0),o.up.set(0,1,0),o.lookAt(0,0,1),a.up.set(0,1,0),a.lookAt(0,0,-1);else{if(e!==Ds)throw new Error("THREE.CubeCamera.updateCoordinateSystem(): Invalid coordinate system: "+e);s.up.set(0,-1,0),s.lookAt(-1,0,0),i.up.set(0,-1,0),i.lookAt(1,0,0),r.up.set(0,0,1),r.lookAt(0,1,0),n.up.set(0,0,-1),n.lookAt(0,-1,0),o.up.set(0,-1,0),o.lookAt(0,0,1),a.up.set(0,-1,0),a.lookAt(0,0,-1)}for(const e of t)this.add(e),e.updateMatrixWorld()}update(e,t){null===this.parent&&this.updateMatrixWorld();const{renderTarget:s,activeMipmapLevel:i}=this;this.coordinateSystem!==e.coordinateSystem&&(this.coordinateSystem=e.coordinateSystem,this.updateCoordinateSystem());const[r,n,o,a,h,u]=this.children,l=e.getRenderTarget(),c=e.getActiveCubeFace(),d=e.getActiveMipmapLevel(),p=e.xr.enabled;e.xr.enabled=!1;const m=s.texture.generateMipmaps;s.texture.generateMipmaps=!1,e.setRenderTarget(s,0,i),e.render(t,r),e.setRenderTarget(s,1,i),e.render(t,n),e.setRenderTarget(s,2,i),e.render(t,o),e.setRenderTarget(s,3,i),e.render(t,a),e.setRenderTarget(s,4,i),e.render(t,h),s.texture.generateMipmaps=m,e.setRenderTarget(s,5,i),e.render(t,u),e.setRenderTarget(l,c,d),e.xr.enabled=p,s.texture.needsPMREMUpdate=!0}}class Jn extends vi{constructor(e,t,s,i,r,n,o,a,h,u){super(e=void 0!==e?e:[],t=void 0!==t?t:he,s,i,r,n,o,a,h,u),this.isCubeTexture=!0,this.flipY=!1}get images(){return this.image}set images(e){this.image=e}}class Kn extends wi{constructor(e=1,t={}){super(e,e,t),this.isWebGLCubeRenderTarget=!0;const s={width:e,height:e,depth:1},i=[s,s,s,s,s,s];this.texture=new Jn(i,t.mapping,t.wrapS,t.wrapT,t.magFilter,t.minFilter,t.format,t.type,t.anisotropy,t.colorSpace),this.texture.isRenderTargetTexture=!0,this.texture.generateMipmaps=void 0!==t.generateMipmaps&&t.generateMipmaps,this.texture.minFilter=void 0!==t.minFilter?t.minFilter:Te}fromEquirectangularTexture(e,t){this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;const s={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"},i=new kn(5,5,5),r=new Wn({name:"CubemapFromEquirect",uniforms:Gn(s.uniforms),vertexShader:s.vertexShader,fragmentShader:s.fragmentShader,side:d,blending:m});r.uniforms.tEquirect.value=t;const n=new Vn(i,r),o=t.minFilter;t.minFilter===Se&&(t.minFilter=Te);return new Zn(1,10,this).update(e,n),t.minFilter=o,n.geometry.dispose(),n.material.dispose(),this}clear(e,t,s,i){const r=e.getRenderTarget();for(let r=0;r<6;r++)e.setRenderTarget(this,r),e.clear(t,s,i);e.setRenderTarget(r)}}class Qn{constructor(e,t=25e-5){this.isFogExp2=!0,this.name="",this.color=new Jr(e),this.density=t}clone(){return new Qn(this.color,this.density)}toJSON(){return{type:"FogExp2",name:this.name,color:this.color.getHex(),density:this.density}}}class eo{constructor(e,t=1,s=1e3){this.isFog=!0,this.name="",this.color=new Jr(e),this.near=t,this.far=s}clone(){return new eo(this.color,this.near,this.far)}toJSON(){return{type:"Fog",name:this.name,color:this.color.getHex(),near:this.near,far:this.far}}}class to extends Ir{constructor(){super(),this.isScene=!0,this.type="Scene",this.background=null,this.environment=null,this.fog=null,this.backgroundBlurriness=0,this.backgroundIntensity=1,this.backgroundRotation=new gr,this.environmentIntensity=1,this.environmentRotation=new gr,this.overrideMaterial=null,"undefined"!=typeof __THREE_DEVTOOLS__&&__THREE_DEVTOOLS__.dispatchEvent(new CustomEvent("observe",{detail:this}))}copy(e,t){return super.copy(e,t),null!==e.background&&(this.background=e.background.clone()),null!==e.environment&&(this.environment=e.environment.clone()),null!==e.fog&&(this.fog=e.fog.clone()),this.backgroundBlurriness=e.backgroundBlurriness,this.backgroundIntensity=e.backgroundIntensity,this.backgroundRotation.copy(e.backgroundRotation),this.environmentIntensity=e.environmentIntensity,this.environmentRotation.copy(e.environmentRotation),null!==e.overrideMaterial&&(this.overrideMaterial=e.overrideMaterial.clone()),this.matrixAutoUpdate=e.matrixAutoUpdate,this}toJSON(e){const t=super.toJSON(e);return null!==this.fog&&(t.object.fog=this.fog.toJSON()),this.backgroundBlurriness>0&&(t.object.backgroundBlurriness=this.backgroundBlurriness),1!==this.backgroundIntensity&&(t.object.backgroundIntensity=this.backgroundIntensity),t.object.backgroundRotation=this.backgroundRotation.toArray(),1!==this.environmentIntensity&&(t.object.environmentIntensity=this.environmentIntensity),t.object.environmentRotation=this.environmentRotation.toArray(),t}}class so{constructor(e,t){this.isInterleavedBuffer=!0,this.array=e,this.stride=t,this.count=void 0!==e?e.length/t:0,this.usage=Cs,this.updateRanges=[],this.version=0,this.uuid=qs()}onUploadCallback(){}set needsUpdate(e){!0===e&&this.version++}setUsage(e){return this.usage=e,this}addUpdateRange(e,t){this.updateRanges.push({start:e,count:t})}clearUpdateRanges(){this.updateRanges.length=0}copy(e){return this.array=new e.array.constructor(e.array),this.count=e.count,this.stride=e.stride,this.usage=e.usage,this}copyAt(e,t,s){e*=this.stride,s*=t.stride;for(let i=0,r=this.stride;ie.far||t.push({distance:a,point:ao.clone(),uv:qr.getInterpolation(ao,mo,go,fo,yo,xo,bo,new Qs),face:null,object:this})}copy(e,t){return super.copy(e,t),void 0!==e.center&&this.center.copy(e.center),this.material=e.material,this}}function To(e,t,s,i,r,n){lo.subVectors(e,s).addScalar(.5).multiply(i),void 0!==r?(co.x=n*lo.x-r*lo.y,co.y=r*lo.x+n*lo.y):co.copy(lo),e.copy(t),e.x+=co.x,e.y+=co.y,e.applyMatrix4(po)}const _o=new Ri,wo=new Ri;class So extends Ir{constructor(){super(),this._currentLevel=0,this.type="LOD",Object.defineProperties(this,{levels:{enumerable:!0,value:[]},isLOD:{value:!0}}),this.autoUpdate=!0}copy(e){super.copy(e,!1);const t=e.levels;for(let e=0,s=t.length;e0){let s,i;for(s=1,i=t.length;s0){_o.setFromMatrixPosition(this.matrixWorld);const s=e.ray.origin.distanceTo(_o);this.getObjectForDistance(s).raycast(e,t)}}update(e){const t=this.levels;if(t.length>1){_o.setFromMatrixPosition(e.matrixWorld),wo.setFromMatrixPosition(this.matrixWorld);const s=_o.distanceTo(wo)/e.zoom;let i,r;for(t[0].object.visible=!0,i=1,r=t.length;i=e))break;t[i-1].object.visible=!1,t[i].object.visible=!0}for(this._currentLevel=i-1;i1?null:t.copy(e.start).addScaledVector(s,r)}intersectsLine(e){const t=this.distanceToPoint(e.start),s=this.distanceToPoint(e.end);return t<0&&s>0||s<0&&t>0}intersectsBox(e){return e.intersectsPlane(this)}intersectsSphere(e){return e.intersectsPlane(this)}coplanarPoint(e){return e.copy(this.normal).multiplyScalar(-this.constant)}applyMatrix4(e,t){const s=t||Jo.getNormalMatrix(e),i=this.coplanarPoint(Yo).applyMatrix4(e),r=this.normal.applyMatrix3(s).normalize();return this.constant=-i.dot(r),this}translate(e){return this.constant-=e.dot(this.normal),this}equals(e){return e.normal.equals(this.normal)&&e.constant===this.constant}clone(){return(new this.constructor).copy(this)}}const Qo=new Zi,ea=new Ri;class ta{constructor(e=new Ko,t=new Ko,s=new Ko,i=new Ko,r=new Ko,n=new Ko){this.planes=[e,t,s,i,r,n]}set(e,t,s,i,r,n){const o=this.planes;return o[0].copy(e),o[1].copy(t),o[2].copy(s),o[3].copy(i),o[4].copy(r),o[5].copy(n),this}copy(e){const t=this.planes;for(let s=0;s<6;s++)t[s].copy(e.planes[s]);return this}setFromProjectionMatrix(e,t=2e3){const s=this.planes,i=e.elements,r=i[0],n=i[1],o=i[2],a=i[3],h=i[4],u=i[5],l=i[6],c=i[7],d=i[8],p=i[9],m=i[10],g=i[11],f=i[12],y=i[13],x=i[14],b=i[15];if(s[0].setComponents(a-r,c-h,g-d,b-f).normalize(),s[1].setComponents(a+r,c+h,g+d,b+f).normalize(),s[2].setComponents(a+n,c+u,g+p,b+y).normalize(),s[3].setComponents(a-n,c-u,g-p,b-y).normalize(),s[4].setComponents(a-o,c-l,g-m,b-x).normalize(),t===Vs)s[5].setComponents(a+o,c+l,g+m,b+x).normalize();else{if(t!==Ds)throw new Error("THREE.Frustum.setFromProjectionMatrix(): Invalid coordinate system: "+t);s[5].setComponents(o,l,m,x).normalize()}return this}intersectsObject(e){if(void 0!==e.boundingSphere)null===e.boundingSphere&&e.computeBoundingSphere(),Qo.copy(e.boundingSphere).applyMatrix4(e.matrixWorld);else{const t=e.geometry;null===t.boundingSphere&&t.computeBoundingSphere(),Qo.copy(t.boundingSphere).applyMatrix4(e.matrixWorld)}return this.intersectsSphere(Qo)}intersectsSprite(e){return Qo.center.set(0,0,0),Qo.radius=.7071067811865476,Qo.applyMatrix4(e.matrixWorld),this.intersectsSphere(Qo)}intersectsSphere(e){const t=this.planes,s=e.center,i=-e.radius;for(let e=0;e<6;e++){if(t[e].distanceToPoint(s)0?e.max.x:e.min.x,ea.y=i.normal.y>0?e.max.y:e.min.y,ea.z=i.normal.z>0?e.max.z:e.min.z,i.distanceToPoint(ea)<0)return!1}return!0}containsPoint(e){const t=this.planes;for(let s=0;s<6;s++)if(t[s].distanceToPoint(e)<0)return!1;return!0}clone(){return(new this.constructor).copy(this)}}function sa(e,t){return e.z-t.z}function ia(e,t){return t.z-e.z}class ra{constructor(){this.index=0,this.pool=[],this.list=[]}push(e,t,s){const i=this.pool,r=this.list;this.index>=i.length&&i.push({start:-1,count:-1,z:-1,index:-1});const n=i[this.index];r.push(n),this.index++,n.start=e.start,n.count=e.count,n.z=t,n.index=s}reset(){this.list.length=0,this.index=0}}const na=new nr,oa=new nr,aa=new nr,ha=new Jr(1,1,1),ua=new nr,la=new ta,ca=new Ii,da=new Zi,pa=new Ri,ma=new Ri,ga=new Ri,fa=new ra,ya=new Vn,xa=[];function ba(e,t,s=0){const i=t.itemSize;if(e.isInterleavedBufferAttribute||e.array.constructor!==t.array.constructor){const r=e.count;for(let n=0;n65535?new Uint32Array(i):new Uint16Array(i);t.setIndex(new ln(e,1))}this._geometryInitialized=!0}}_validateGeometry(e){const t=this.geometry;if(Boolean(e.getIndex())!==Boolean(t.getIndex()))throw new Error('BatchedMesh: All geometries must consistently have "index".');for(const s in t.attributes){if(!e.hasAttribute(s))throw new Error(`BatchedMesh: Added geometry missing "${s}". All geometries must have consistent attributes.`);const i=e.getAttribute(s),r=t.getAttribute(s);if(i.itemSize!==r.itemSize||i.normalized!==r.normalized)throw new Error("BatchedMesh: All attributes must have a consistent itemSize and normalized value.")}}setCustomSort(e){return this.customSort=e,this}computeBoundingBox(){null===this.boundingBox&&(this.boundingBox=new Ii);const e=this.boundingBox,t=this._drawInfo;e.makeEmpty();for(let s=0,i=t.length;s=this.maxInstanceCount&&0===this._availableInstanceIds.length)throw new Error("BatchedMesh: Maximum item count reached.");const t={visible:!0,active:!0,geometryIndex:e};let s=null;this._availableInstanceIds.length>0?(s=this._availableInstanceIds.pop(),this._drawInfo[s]=t):(s=this._drawInfo.length,this._drawInfo.push(t));const i=this._matricesTexture,r=i.image.data;aa.toArray(r,16*s),i.needsUpdate=!0;const n=this._colorsTexture;return n&&(ha.toArray(n.image.data,4*s),n.needsUpdate=!0),s}addGeometry(e,t=-1,s=-1){if(this._initializeGeometry(e),this._validateGeometry(e),this._drawInfo.length>=this._maxInstanceCount)throw new Error("BatchedMesh: Maximum item count reached.");const i={vertexStart:-1,vertexCount:-1,indexStart:-1,indexCount:-1};let r=null;const n=this._reservedRanges,o=this._drawRanges,a=this._bounds;0!==this._geometryCount&&(r=n[n.length-1]),i.vertexCount=-1===t?e.getAttribute("position").count:t,i.vertexStart=null===r?0:r.vertexStart+r.vertexCount;const h=e.getIndex(),u=null!==h;if(u&&(i.indexCount=-1===s?h.count:s,i.indexStart=null===r?0:r.indexStart+r.indexCount),-1!==i.indexStart&&i.indexStart+i.indexCount>this._maxIndexCount||i.vertexStart+i.vertexCount>this._maxVertexCount)throw new Error("BatchedMesh: Reserved space request exceeds the maximum buffer size.");const l=this._geometryCount;return this._geometryCount++,n.push(i),o.push({start:u?i.indexStart:i.vertexStart,count:-1}),a.push({boxInitialized:!1,box:new Ii,sphereInitialized:!1,sphere:new Zi}),this.setGeometryAt(l,e),l}setGeometryAt(e,t){if(e>=this._geometryCount)throw new Error("BatchedMesh: Maximum geometry count reached.");this._validateGeometry(t);const s=this.geometry,i=null!==s.getIndex(),r=s.getIndex(),n=t.getIndex(),o=this._reservedRanges[e];if(i&&n.count>o.indexCount||t.attributes.position.count>o.vertexCount)throw new Error("BatchedMesh: Reserved space not large enough for provided geometry.");const a=o.vertexStart,h=o.vertexCount;for(const e in s.attributes){const i=t.getAttribute(e),r=s.getAttribute(e);ba(i,r,a);const n=i.itemSize;for(let e=i.count,t=h;e=t.length||!1===t[e].active||(t[e].active=!1,this._availableInstanceIds.push(e),this._visibilityChanged=!0),this}getBoundingBoxAt(e,t){if(e>=this._geometryCount)return null;const s=this._bounds[e],i=s.box,r=this.geometry;if(!1===s.boxInitialized){i.makeEmpty();const t=r.index,n=r.attributes.position,o=this._drawRanges[e];for(let e=o.start,s=o.start+o.count;e=this._geometryCount)return null;const s=this._bounds[e],i=s.sphere,r=this.geometry;if(!1===s.sphereInitialized){i.makeEmpty(),this.getBoundingBoxAt(e,ca),ca.getCenter(i.center);const t=r.index,n=r.attributes.position,o=this._drawRanges[e];let a=0;for(let e=o.start,s=o.start+o.count;e=s.length||!1===s[e].active||(t.toArray(r,16*e),i.needsUpdate=!0),this}getMatrixAt(e,t){const s=this._drawInfo,i=this._matricesTexture.image.data;return e>=s.length||!1===s[e].active?null:t.fromArray(i,16*e)}setColorAt(e,t){null===this._colorsTexture&&this._initColorsTexture();const s=this._colorsTexture,i=this._colorsTexture.image.data,r=this._drawInfo;return e>=r.length||!1===r[e].active||(t.toArray(i,4*e),s.needsUpdate=!0),this}getColorAt(e,t){const s=this._colorsTexture.image.data,i=this._drawInfo;return e>=i.length||!1===i[e].active?null:t.fromArray(s,4*e)}setVisibleAt(e,t){const s=this._drawInfo;return e>=s.length||!1===s[e].active||s[e].visible===t||(s[e].visible=t,this._visibilityChanged=!0),this}getVisibleAt(e){const t=this._drawInfo;return!(e>=t.length||!1===t[e].active)&&t[e].visible}setGeometryIdAt(e,t){const s=this._drawInfo;return e>=s.length||!1===s[e].active||t<0||t>=this._geometryCount?null:(s[e].geometryIndex=t,this)}getGeometryIdAt(e){const t=this._drawInfo;return e>=t.length||!1===t[e].active?-1:t[e].geometryIndex}getGeometryRangeAt(e,t={}){if(e<0||e>=this._geometryCount)return null;const s=this._drawRanges[e];return t.start=s.start,t.count=s.count,t}raycast(e,t){const s=this._drawInfo,i=this._drawRanges,r=this.matrixWorld,n=this.geometry;ya.material=this.material,ya.geometry.index=n.index,ya.geometry.attributes=n.attributes,null===ya.geometry.boundingBox&&(ya.geometry.boundingBox=new Ii),null===ya.geometry.boundingSphere&&(ya.geometry.boundingSphere=new Zi);for(let n=0,o=s.length;n({...e}))),this._reservedRanges=e._reservedRanges.map((e=>({...e}))),this._drawInfo=e._drawInfo.map((e=>({...e}))),this._bounds=e._bounds.map((e=>({boxInitialized:e.boxInitialized,box:e.box.clone(),sphereInitialized:e.sphereInitialized,sphere:e.sphere.clone()}))),this._maxInstanceCount=e._maxInstanceCount,this._maxVertexCount=e._maxVertexCount,this._maxIndexCount=e._maxIndexCount,this._geometryInitialized=e._geometryInitialized,this._geometryCount=e._geometryCount,this._multiDrawCounts=e._multiDrawCounts.slice(),this._multiDrawStarts=e._multiDrawStarts.slice(),this._matricesTexture=e._matricesTexture.clone(),this._matricesTexture.image.data=this._matricesTexture.image.data.slice(),null!==this._colorsTexture&&(this._colorsTexture=e._colorsTexture.clone(),this._colorsTexture.image.data=this._colorsTexture.image.data.slice()),this}dispose(){return this.geometry.dispose(),this._matricesTexture.dispose(),this._matricesTexture=null,this._indirectTexture.dispose(),this._indirectTexture=null,null!==this._colorsTexture&&(this._colorsTexture.dispose(),this._colorsTexture=null),this}onBeforeRender(e,t,s,i,r){if(!this._visibilityChanged&&!this.perObjectFrustumCulled&&!this.sortObjects)return;const n=i.getIndex(),o=null===n?1:n.array.BYTES_PER_ELEMENT,a=this._drawInfo,h=this._multiDrawStarts,u=this._multiDrawCounts,l=this._drawRanges,c=this.perObjectFrustumCulled,d=this._indirectTexture,p=d.image.data;c&&(ua.multiplyMatrices(s.projectionMatrix,s.matrixWorldInverse).multiply(this.matrixWorld),la.setFromProjectionMatrix(ua,e.coordinateSystem));let m=0;if(this.sortObjects){oa.copy(this.matrixWorld).invert(),pa.setFromMatrixPosition(s.matrixWorld).applyMatrix4(oa),ma.set(0,0,-1).transformDirection(s.matrixWorld).transformDirection(oa);for(let e=0,t=a.length;e0){const s=e[t[0]];if(void 0!==s){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=s.length;ei)return;Aa.applyMatrix4(e.matrixWorld);const a=t.ray.origin.distanceTo(Aa);return at.far?void 0:{distance:a,point:Ca.clone().applyMatrix4(e.matrixWorld),index:r,face:null,faceIndex:null,barycoord:null,object:e}}const Ba=new Ri,Ia=new Ri;class Pa extends Ra{constructor(e,t){super(e,t),this.isLineSegments=!0,this.type="LineSegments"}computeLineDistances(){const e=this.geometry;if(null===e.index){const t=e.attributes.position,s=[];for(let e=0,i=t.count;e0){const s=e[t[0]];if(void 0!==s){this.morphTargetInfluences=[],this.morphTargetDictionary={};for(let e=0,t=s.length;er.far)return;n.push({distance:h,distanceToRay:Math.sqrt(a),point:s,index:t,face:null,faceIndex:null,barycoord:null,object:o})}}class Ga extends Ir{constructor(){super(),this.isGroup=!0,this.type="Group"}}class Wa extends vi{constructor(e,t,s,i,r,n,o,a,h){super(e,t,s,i,r,n,o,a,h),this.isVideoTexture=!0,this.minFilter=void 0!==n?n:Te,this.magFilter=void 0!==r?r:Te,this.generateMipmaps=!1;const u=this;"requestVideoFrameCallback"in e&&e.requestVideoFrameCallback((function t(){u.needsUpdate=!0,e.requestVideoFrameCallback(t)}))}clone(){return new this.constructor(this.image).copy(this)}update(){const e=this.image;!1==="requestVideoFrameCallback"in e&&e.readyState>=e.HAVE_CURRENT_DATA&&(this.needsUpdate=!0)}}class ja extends vi{constructor(e,t){super({width:e,height:t}),this.isFramebufferTexture=!0,this.magFilter=fe,this.minFilter=fe,this.generateMipmaps=!1,this.needsUpdate=!0}}class Ha extends vi{constructor(e,t,s,i,r,n,o,a,h,u,l,c){super(null,n,o,a,h,u,i,r,l,c),this.isCompressedTexture=!0,this.image={width:t,height:s},this.mipmaps=e,this.flipY=!1,this.generateMipmaps=!1}}class qa extends Ha{constructor(e,t,s,i,r,n){super(e,t,s,r,n),this.isCompressedArrayTexture=!0,this.image.depth=i,this.wrapR=me,this.layerUpdates=new Set}addLayerUpdate(e){this.layerUpdates.add(e)}clearLayerUpdates(){this.layerUpdates.clear()}}class $a extends Ha{constructor(e,t,s){super(void 0,e[0].width,e[0].height,t,s,he),this.isCompressedCubeTexture=!0,this.isCubeTexture=!0,this.image=e}}class Xa extends vi{constructor(e,t,s,i,r,n,o,a,h){super(e,t,s,i,r,n,o,a,h),this.isCanvasTexture=!0,this.needsUpdate=!0}}class Ya extends vi{constructor(e,t,s,i,r,n,o,a,h,u=1026){if(u!==We&&u!==je)throw new Error("DepthTexture format must be either THREE.DepthFormat or THREE.DepthStencilFormat");void 0===s&&u===We&&(s=Be),void 0===s&&u===je&&(s=Ue),super(null,i,r,n,o,a,u,s,h),this.isDepthTexture=!0,this.image={width:e,height:t},this.magFilter=void 0!==o?o:fe,this.minFilter=void 0!==a?a:fe,this.flipY=!1,this.generateMipmaps=!1,this.compareFunction=null}copy(e){return super.copy(e),this.compareFunction=e.compareFunction,this}toJSON(e){const t=super.toJSON(e);return null!==this.compareFunction&&(t.compareFunction=this.compareFunction),t}}class Za{constructor(){this.type="Curve",this.arcLengthDivisions=200}getPoint(){return console.warn("THREE.Curve: .getPoint() not implemented."),null}getPointAt(e,t){const s=this.getUtoTmapping(e);return this.getPoint(s,t)}getPoints(e=5){const t=[];for(let s=0;s<=e;s++)t.push(this.getPoint(s/e));return t}getSpacedPoints(e=5){const t=[];for(let s=0;s<=e;s++)t.push(this.getPointAt(s/e));return t}getLength(){const e=this.getLengths();return e[e.length-1]}getLengths(e=this.arcLengthDivisions){if(this.cacheArcLengths&&this.cacheArcLengths.length===e+1&&!this.needsUpdate)return this.cacheArcLengths;this.needsUpdate=!1;const t=[];let s,i=this.getPoint(0),r=0;t.push(0);for(let n=1;n<=e;n++)s=this.getPoint(n/e),r+=s.distanceTo(i),t.push(r),i=s;return this.cacheArcLengths=t,t}updateArcLengths(){this.needsUpdate=!0,this.getLengths()}getUtoTmapping(e,t){const s=this.getLengths();let i=0;const r=s.length;let n;n=t||e*s[r-1];let o,a=0,h=r-1;for(;a<=h;)if(i=Math.floor(a+(h-a)/2),o=s[i]-n,o<0)a=i+1;else{if(!(o>0)){h=i;break}h=i-1}if(i=h,s[i]===n)return i/(r-1);const u=s[i];return(i+(n-u)/(s[i+1]-u))/(r-1)}getTangent(e,t){const s=1e-4;let i=e-s,r=e+s;i<0&&(i=0),r>1&&(r=1);const n=this.getPoint(i),o=this.getPoint(r),a=t||(n.isVector2?new Qs:new Ri);return a.copy(o).sub(n).normalize(),a}getTangentAt(e,t){const s=this.getUtoTmapping(e);return this.getTangent(s,t)}computeFrenetFrames(e,t){const s=new Ri,i=[],r=[],n=[],o=new Ri,a=new nr;for(let t=0;t<=e;t++){const s=t/e;i[t]=this.getTangentAt(s,new Ri)}r[0]=new Ri,n[0]=new Ri;let h=Number.MAX_VALUE;const u=Math.abs(i[0].x),l=Math.abs(i[0].y),c=Math.abs(i[0].z);u<=h&&(h=u,s.set(1,0,0)),l<=h&&(h=l,s.set(0,1,0)),c<=h&&s.set(0,0,1),o.crossVectors(i[0],s).normalize(),r[0].crossVectors(i[0],o),n[0].crossVectors(i[0],r[0]);for(let t=1;t<=e;t++){if(r[t]=r[t-1].clone(),n[t]=n[t-1].clone(),o.crossVectors(i[t-1],i[t]),o.length()>Number.EPSILON){o.normalize();const e=Math.acos($s(i[t-1].dot(i[t]),-1,1));r[t].applyMatrix4(a.makeRotationAxis(o,e))}n[t].crossVectors(i[t],r[t])}if(!0===t){let t=Math.acos($s(r[0].dot(r[e]),-1,1));t/=e,i[0].dot(o.crossVectors(r[0],r[e]))>0&&(t=-t);for(let s=1;s<=e;s++)r[s].applyMatrix4(a.makeRotationAxis(i[s],t*s)),n[s].crossVectors(i[s],r[s])}return{tangents:i,normals:r,binormals:n}}clone(){return(new this.constructor).copy(this)}copy(e){return this.arcLengthDivisions=e.arcLengthDivisions,this}toJSON(){const e={metadata:{version:4.6,type:"Curve",generator:"Curve.toJSON"}};return e.arcLengthDivisions=this.arcLengthDivisions,e.type=this.type,e}fromJSON(e){return this.arcLengthDivisions=e.arcLengthDivisions,this}}class Ja extends Za{constructor(e=0,t=0,s=1,i=1,r=0,n=2*Math.PI,o=!1,a=0){super(),this.isEllipseCurve=!0,this.type="EllipseCurve",this.aX=e,this.aY=t,this.xRadius=s,this.yRadius=i,this.aStartAngle=r,this.aEndAngle=n,this.aClockwise=o,this.aRotation=a}getPoint(e,t=new Qs){const s=t,i=2*Math.PI;let r=this.aEndAngle-this.aStartAngle;const n=Math.abs(r)i;)r-=i;r0?0:(Math.floor(Math.abs(h)/r)+1)*r:0===u&&h===r-1&&(h=r-2,u=1),this.closed||h>0?o=i[(h-1)%r]:(eh.subVectors(i[0],i[1]).add(i[0]),o=eh);const l=i[h%r],c=i[(h+1)%r];if(this.closed||h+2i.length-2?i.length-1:n+1],l=i[n>i.length-3?i.length-1:n+2];return s.set(nh(o,a.x,h.x,u.x,l.x),nh(o,a.y,h.y,u.y,l.y)),s}copy(e){super.copy(e),this.points=[];for(let t=0,s=e.points.length;t=s){const e=i[r]-s,n=this.curves[r],o=n.getLength(),a=0===o?0:1-e/o;return n.getPointAt(a,t)}r++}return null}getLength(){const e=this.getCurveLengths();return e[e.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 e=[];let t=0;for(let s=0,i=this.curves.length;s1&&!t[t.length-1].equals(t[0])&&t.push(t[0]),t}copy(e){super.copy(e),this.curves=[];for(let t=0,s=e.curves.length;t0){const e=h.getPoint(0);e.equals(this.currentPoint)||this.lineTo(e.x,e.y)}this.curves.push(h);const u=h.getPoint(1);return this.currentPoint.copy(u),this}copy(e){return super.copy(e),this.currentPoint.copy(e.currentPoint),this}toJSON(){const e=super.toJSON();return e.currentPoint=this.currentPoint.toArray(),e}fromJSON(e){return super.fromJSON(e),this.currentPoint.fromArray(e.currentPoint),this}}class xh extends An{constructor(e=[new Qs(0,-.5),new Qs(.5,0),new Qs(0,.5)],t=12,s=0,i=2*Math.PI){super(),this.type="LatheGeometry",this.parameters={points:e,segments:t,phiStart:s,phiLength:i},t=Math.floor(t),i=$s(i,0,2*Math.PI);const r=[],n=[],o=[],a=[],h=[],u=1/t,l=new Ri,c=new Qs,d=new Ri,p=new Ri,m=new Ri;let g=0,f=0;for(let t=0;t<=e.length-1;t++)switch(t){case 0:g=e[t+1].x-e[t].x,f=e[t+1].y-e[t].y,d.x=1*f,d.y=-g,d.z=0*f,m.copy(d),d.normalize(),a.push(d.x,d.y,d.z);break;case e.length-1:a.push(m.x,m.y,m.z);break;default:g=e[t+1].x-e[t].x,f=e[t+1].y-e[t].y,d.x=1*f,d.y=-g,d.z=0*f,p.copy(d),d.x+=m.x,d.y+=m.y,d.z+=m.z,d.normalize(),a.push(d.x,d.y,d.z),m.copy(p)}for(let r=0;r<=t;r++){const d=s+r*u*i,p=Math.sin(d),m=Math.cos(d);for(let s=0;s<=e.length-1;s++){l.x=e[s].x*p,l.y=e[s].y,l.z=e[s].x*m,n.push(l.x,l.y,l.z),c.x=r/t,c.y=s/(e.length-1),o.push(c.x,c.y);const i=a[3*s+0]*p,u=a[3*s+1],d=a[3*s+0]*m;h.push(i,u,d)}}for(let s=0;s0&&(u.push(r,n,a),x+=3),t>0&&(u.push(n,o,a),x+=3)}h.addGroup(f,x,0),f+=x}(),!1===n&&(e>0&&y(!0),t>0&&y(!1)),this.setIndex(u),this.setAttribute("position",new bn(l,3)),this.setAttribute("normal",new bn(c,3)),this.setAttribute("uv",new bn(d,2))}copy(e){return super.copy(e),this.parameters=Object.assign({},e.parameters),this}static fromJSON(e){return new Th(e.radiusTop,e.radiusBottom,e.height,e.radialSegments,e.heightSegments,e.openEnded,e.thetaStart,e.thetaLength)}}class _h extends Th{constructor(e=1,t=1,s=32,i=1,r=!1,n=0,o=2*Math.PI){super(0,e,t,s,i,r,n,o),this.type="ConeGeometry",this.parameters={radius:e,height:t,radialSegments:s,heightSegments:i,openEnded:r,thetaStart:n,thetaLength:o}}static fromJSON(e){return new _h(e.radius,e.height,e.radialSegments,e.heightSegments,e.openEnded,e.thetaStart,e.thetaLength)}}class wh extends An{constructor(e=[],t=[],s=1,i=0){super(),this.type="PolyhedronGeometry",this.parameters={vertices:e,indices:t,radius:s,detail:i};const r=[],n=[];function o(e,t,s,i){const r=i+1,n=[];for(let i=0;i<=r;i++){n[i]=[];const o=e.clone().lerp(s,i/r),a=t.clone().lerp(s,i/r),h=r-i;for(let e=0;e<=h;e++)n[i][e]=0===e&&i===r?o:o.clone().lerp(a,e/h)}for(let e=0;e.9&&o<.1&&(t<.2&&(n[e+0]+=1),s<.2&&(n[e+2]+=1),i<.2&&(n[e+4]+=1))}}()}(),this.setAttribute("position",new bn(r,3)),this.setAttribute("normal",new bn(r.slice(),3)),this.setAttribute("uv",new bn(n,2)),0===i?this.computeVertexNormals():this.normalizeNormals()}copy(e){return super.copy(e),this.parameters=Object.assign({},e.parameters),this}static fromJSON(e){return new wh(e.vertices,e.indices,e.radius,e.details)}}class Sh extends wh{constructor(e=1,t=0){const s=(1+Math.sqrt(5))/2,i=1/s;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,-i,-s,0,-i,s,0,i,-s,0,i,s,-i,-s,0,-i,s,0,i,-s,0,i,s,0,-s,0,-i,s,0,-i,-s,0,i,s,0,i],[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],e,t),this.type="DodecahedronGeometry",this.parameters={radius:e,detail:t}}static fromJSON(e){return new Sh(e.radius,e.detail)}}const Mh=new Ri,Nh=new Ri,Ah=new Ri,Ch=new qr;class Rh extends An{constructor(e=null,t=1){if(super(),this.type="EdgesGeometry",this.parameters={geometry:e,thresholdAngle:t},null!==e){const s=4,i=Math.pow(10,s),r=Math.cos(js*t),n=e.getIndex(),o=e.getAttribute("position"),a=n?n.count:o.count,h=[0,0,0],u=["a","b","c"],l=new Array(3),c={},d=[];for(let e=0;e80*s){a=u=e[0],h=l=e[1];for(let t=s;tu&&(u=c),d>l&&(l=d);p=Math.max(u-a,l-h),p=0!==p?32767/p:0}return Fh(n,o,s,a,h,p,0),o};function Ih(e,t,s,i,r){let n,o;if(r===function(e,t,s,i){let r=0;for(let n=t,o=s-i;n0)for(n=t;n=t;n-=i)o=Qh(n,e[n],e[n+1],o);return o&&$h(o,o.next)&&(eu(o),o=o.next),o}function Ph(e,t){if(!e)return e;t||(t=e);let s,i=e;do{if(s=!1,i.steiner||!$h(i,i.next)&&0!==qh(i.prev,i,i.next))i=i.next;else{if(eu(i),i=t=i.prev,i===i.next)break;s=!0}}while(s||i!==t);return t}function Fh(e,t,s,i,r,n,o){if(!e)return;!o&&n&&function(e,t,s,i){let r=e;do{0===r.z&&(r.z=Gh(r.x,r.y,t,s,i)),r.prevZ=r.prev,r.nextZ=r.next,r=r.next}while(r!==e);r.prevZ.nextZ=null,r.prevZ=null,function(e){let t,s,i,r,n,o,a,h,u=1;do{for(s=e,e=null,n=null,o=0;s;){for(o++,i=s,a=0,t=0;t0||h>0&&i;)0!==a&&(0===h||!i||s.z<=i.z)?(r=s,s=s.nextZ,a--):(r=i,i=i.nextZ,h--),n?n.nextZ=r:e=r,r.prevZ=n,n=r;s=i}n.nextZ=null,u*=2}while(o>1)}(r)}(e,i,r,n);let a,h,u=e;for(;e.prev!==e.next;)if(a=e.prev,h=e.next,n?Uh(e,i,r,n):zh(e))t.push(a.i/s|0),t.push(e.i/s|0),t.push(h.i/s|0),eu(e),e=h.next,u=h.next;else if((e=h)===u){o?1===o?Fh(e=Oh(Ph(e),t,s),t,s,i,r,n,2):2===o&&Lh(e,t,s,i,r,n):Fh(Ph(e),t,s,i,r,n,1);break}}function zh(e){const t=e.prev,s=e,i=e.next;if(qh(t,s,i)>=0)return!1;const r=t.x,n=s.x,o=i.x,a=t.y,h=s.y,u=i.y,l=rn?r>o?r:o:n>o?n:o,p=a>h?a>u?a:u:h>u?h:u;let m=i.next;for(;m!==t;){if(m.x>=l&&m.x<=d&&m.y>=c&&m.y<=p&&jh(r,a,n,h,o,u,m.x,m.y)&&qh(m.prev,m,m.next)>=0)return!1;m=m.next}return!0}function Uh(e,t,s,i){const r=e.prev,n=e,o=e.next;if(qh(r,n,o)>=0)return!1;const a=r.x,h=n.x,u=o.x,l=r.y,c=n.y,d=o.y,p=ah?a>u?a:u:h>u?h:u,f=l>c?l>d?l:d:c>d?c:d,y=Gh(p,m,t,s,i),x=Gh(g,f,t,s,i);let b=e.prevZ,v=e.nextZ;for(;b&&b.z>=y&&v&&v.z<=x;){if(b.x>=p&&b.x<=g&&b.y>=m&&b.y<=f&&b!==r&&b!==o&&jh(a,l,h,c,u,d,b.x,b.y)&&qh(b.prev,b,b.next)>=0)return!1;if(b=b.prevZ,v.x>=p&&v.x<=g&&v.y>=m&&v.y<=f&&v!==r&&v!==o&&jh(a,l,h,c,u,d,v.x,v.y)&&qh(v.prev,v,v.next)>=0)return!1;v=v.nextZ}for(;b&&b.z>=y;){if(b.x>=p&&b.x<=g&&b.y>=m&&b.y<=f&&b!==r&&b!==o&&jh(a,l,h,c,u,d,b.x,b.y)&&qh(b.prev,b,b.next)>=0)return!1;b=b.prevZ}for(;v&&v.z<=x;){if(v.x>=p&&v.x<=g&&v.y>=m&&v.y<=f&&v!==r&&v!==o&&jh(a,l,h,c,u,d,v.x,v.y)&&qh(v.prev,v,v.next)>=0)return!1;v=v.nextZ}return!0}function Oh(e,t,s){let i=e;do{const r=i.prev,n=i.next.next;!$h(r,n)&&Xh(r,i,i.next,n)&&Jh(r,n)&&Jh(n,r)&&(t.push(r.i/s|0),t.push(i.i/s|0),t.push(n.i/s|0),eu(i),eu(i.next),i=e=n),i=i.next}while(i!==e);return Ph(i)}function Lh(e,t,s,i,r,n){let o=e;do{let e=o.next.next;for(;e!==o.prev;){if(o.i!==e.i&&Hh(o,e)){let a=Kh(o,e);return o=Ph(o,o.next),a=Ph(a,a.next),Fh(o,t,s,i,r,n,0),void Fh(a,t,s,i,r,n,0)}e=e.next}o=o.next}while(o!==e)}function Vh(e,t){return e.x-t.x}function Dh(e,t){const s=function(e,t){let s,i=t,r=-1/0;const n=e.x,o=e.y;do{if(o<=i.y&&o>=i.next.y&&i.next.y!==i.y){const e=i.x+(o-i.y)*(i.next.x-i.x)/(i.next.y-i.y);if(e<=n&&e>r&&(r=e,s=i.x=i.x&&i.x>=h&&n!==i.x&&jh(os.x||i.x===s.x&&kh(s,i)))&&(s=i,c=l)),i=i.next}while(i!==a);return s}(e,t);if(!s)return t;const i=Kh(s,e);return Ph(i,i.next),Ph(s,s.next)}function kh(e,t){return qh(e.prev,e,t.prev)<0&&qh(t.next,e,e.next)<0}function Gh(e,t,s,i,r){return(e=1431655765&((e=858993459&((e=252645135&((e=16711935&((e=(e-s)*r|0)|e<<8))|e<<4))|e<<2))|e<<1))|(t=1431655765&((t=858993459&((t=252645135&((t=16711935&((t=(t-i)*r|0)|t<<8))|t<<4))|t<<2))|t<<1))<<1}function Wh(e){let t=e,s=e;do{(t.x=(e-o)*(n-a)&&(e-o)*(i-a)>=(s-o)*(t-a)&&(s-o)*(n-a)>=(r-o)*(i-a)}function Hh(e,t){return e.next.i!==t.i&&e.prev.i!==t.i&&!function(e,t){let s=e;do{if(s.i!==e.i&&s.next.i!==e.i&&s.i!==t.i&&s.next.i!==t.i&&Xh(s,s.next,e,t))return!0;s=s.next}while(s!==e);return!1}(e,t)&&(Jh(e,t)&&Jh(t,e)&&function(e,t){let s=e,i=!1;const r=(e.x+t.x)/2,n=(e.y+t.y)/2;do{s.y>n!=s.next.y>n&&s.next.y!==s.y&&r<(s.next.x-s.x)*(n-s.y)/(s.next.y-s.y)+s.x&&(i=!i),s=s.next}while(s!==e);return i}(e,t)&&(qh(e.prev,e,t.prev)||qh(e,t.prev,t))||$h(e,t)&&qh(e.prev,e,e.next)>0&&qh(t.prev,t,t.next)>0)}function qh(e,t,s){return(t.y-e.y)*(s.x-t.x)-(t.x-e.x)*(s.y-t.y)}function $h(e,t){return e.x===t.x&&e.y===t.y}function Xh(e,t,s,i){const r=Zh(qh(e,t,s)),n=Zh(qh(e,t,i)),o=Zh(qh(s,i,e)),a=Zh(qh(s,i,t));return r!==n&&o!==a||(!(0!==r||!Yh(e,s,t))||(!(0!==n||!Yh(e,i,t))||(!(0!==o||!Yh(s,e,i))||!(0!==a||!Yh(s,t,i)))))}function Yh(e,t,s){return t.x<=Math.max(e.x,s.x)&&t.x>=Math.min(e.x,s.x)&&t.y<=Math.max(e.y,s.y)&&t.y>=Math.min(e.y,s.y)}function Zh(e){return e>0?1:e<0?-1:0}function Jh(e,t){return qh(e.prev,e,e.next)<0?qh(e,t,e.next)>=0&&qh(e,e.prev,t)>=0:qh(e,t,e.prev)<0||qh(e,e.next,t)<0}function Kh(e,t){const s=new tu(e.i,e.x,e.y),i=new tu(t.i,t.x,t.y),r=e.next,n=t.prev;return e.next=t,t.prev=e,s.next=r,r.prev=s,i.next=s,s.prev=i,n.next=i,i.prev=n,i}function Qh(e,t,s,i){const r=new tu(e,t,s);return i?(r.next=i.next,r.prev=i,i.next.prev=r,i.next=r):(r.prev=r,r.next=r),r}function eu(e){e.next.prev=e.prev,e.prev.next=e.next,e.prevZ&&(e.prevZ.nextZ=e.nextZ),e.nextZ&&(e.nextZ.prevZ=e.prevZ)}function tu(e,t,s){this.i=e,this.x=t,this.y=s,this.prev=null,this.next=null,this.z=0,this.prevZ=null,this.nextZ=null,this.steiner=!1}class su{static area(e){const t=e.length;let s=0;for(let i=t-1,r=0;r2&&e[t-1].equals(e[0])&&e.pop()}function ru(e,t){for(let s=0;sNumber.EPSILON){const c=Math.sqrt(l),d=Math.sqrt(h*h+u*u),p=t.x-a/c,m=t.y+o/c,g=((s.x-u/d-p)*u-(s.y+h/d-m)*h)/(o*u-a*h);i=p+o*g-e.x,r=m+a*g-e.y;const f=i*i+r*r;if(f<=2)return new Qs(i,r);n=Math.sqrt(f/2)}else{let e=!1;o>Number.EPSILON?h>Number.EPSILON&&(e=!0):o<-Number.EPSILON?h<-Number.EPSILON&&(e=!0):Math.sign(a)===Math.sign(u)&&(e=!0),e?(i=-a,r=o,n=Math.sqrt(l)):(i=o,r=a,n=Math.sqrt(l/2))}return new Qs(i/n,r/n)}const B=[];for(let e=0,t=N.length,s=t-1,i=e+1;e=0;e--){const t=e/p,s=l*Math.cos(t*Math.PI/2),i=c*Math.sin(t*Math.PI/2)+d;for(let e=0,t=N.length;e=0;){const i=s;let r=s-1;r<0&&(r=e.length-1);for(let e=0,s=a+2*p;e0)&&d.push(t,r,h),(e!==s-1||a0!=e>0&&this.version++,this._anisotropy=e}get clearcoat(){return this._clearcoat}set clearcoat(e){this._clearcoat>0!=e>0&&this.version++,this._clearcoat=e}get iridescence(){return this._iridescence}set iridescence(e){this._iridescence>0!=e>0&&this.version++,this._iridescence=e}get dispersion(){return this._dispersion}set dispersion(e){this._dispersion>0!=e>0&&this.version++,this._dispersion=e}get sheen(){return this._sheen}set sheen(e){this._sheen>0!=e>0&&this.version++,this._sheen=e}get transmission(){return this._transmission}set transmission(e){this._transmission>0!=e>0&&this.version++,this._transmission=e}copy(e){return super.copy(e),this.defines={STANDARD:"",PHYSICAL:""},this.anisotropy=e.anisotropy,this.anisotropyRotation=e.anisotropyRotation,this.anisotropyMap=e.anisotropyMap,this.clearcoat=e.clearcoat,this.clearcoatMap=e.clearcoatMap,this.clearcoatRoughness=e.clearcoatRoughness,this.clearcoatRoughnessMap=e.clearcoatRoughnessMap,this.clearcoatNormalMap=e.clearcoatNormalMap,this.clearcoatNormalScale.copy(e.clearcoatNormalScale),this.dispersion=e.dispersion,this.ior=e.ior,this.iridescence=e.iridescence,this.iridescenceMap=e.iridescenceMap,this.iridescenceIOR=e.iridescenceIOR,this.iridescenceThicknessRange=[...e.iridescenceThicknessRange],this.iridescenceThicknessMap=e.iridescenceThicknessMap,this.sheen=e.sheen,this.sheenColor.copy(e.sheenColor),this.sheenColorMap=e.sheenColorMap,this.sheenRoughness=e.sheenRoughness,this.sheenRoughnessMap=e.sheenRoughnessMap,this.transmission=e.transmission,this.transmissionMap=e.transmissionMap,this.thickness=e.thickness,this.thicknessMap=e.thicknessMap,this.attenuationDistance=e.attenuationDistance,this.attenuationColor.copy(e.attenuationColor),this.specularIntensity=e.specularIntensity,this.specularIntensityMap=e.specularIntensityMap,this.specularColor.copy(e.specularColor),this.specularColorMap=e.specularColorMap,this}}class Su extends en{constructor(e){super(),this.isMeshPhongMaterial=!0,this.type="MeshPhongMaterial",this.color=new Jr(16777215),this.specular=new Jr(1118481),this.shininess=30,this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Jr(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Qs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new gr,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(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.specular.copy(e.specular),this.shininess=e.shininess,this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.emissive.copy(e.emissive),this.emissiveMap=e.emissiveMap,this.emissiveIntensity=e.emissiveIntensity,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.flatShading=e.flatShading,this.fog=e.fog,this}}class Mu extends en{constructor(e){super(),this.isMeshToonMaterial=!0,this.defines={TOON:""},this.type="MeshToonMaterial",this.color=new Jr(16777215),this.map=null,this.gradientMap=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Jr(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Qs(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(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.gradientMap=e.gradientMap,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.emissive.copy(e.emissive),this.emissiveMap=e.emissiveMap,this.emissiveIntensity=e.emissiveIntensity,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.alphaMap=e.alphaMap,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.fog=e.fog,this}}class Nu extends en{constructor(e){super(),this.isMeshNormalMaterial=!0,this.type="MeshNormalMaterial",this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Qs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.wireframe=!1,this.wireframeLinewidth=1,this.flatShading=!1,this.setValues(e)}copy(e){return super.copy(e),this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.flatShading=e.flatShading,this}}class Au extends en{constructor(e){super(),this.isMeshLambertMaterial=!0,this.type="MeshLambertMaterial",this.color=new Jr(16777215),this.map=null,this.lightMap=null,this.lightMapIntensity=1,this.aoMap=null,this.aoMapIntensity=1,this.emissive=new Jr(0),this.emissiveIntensity=1,this.emissiveMap=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Qs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.specularMap=null,this.alphaMap=null,this.envMap=null,this.envMapRotation=new gr,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(e)}copy(e){return super.copy(e),this.color.copy(e.color),this.map=e.map,this.lightMap=e.lightMap,this.lightMapIntensity=e.lightMapIntensity,this.aoMap=e.aoMap,this.aoMapIntensity=e.aoMapIntensity,this.emissive.copy(e.emissive),this.emissiveMap=e.emissiveMap,this.emissiveIntensity=e.emissiveIntensity,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.specularMap=e.specularMap,this.alphaMap=e.alphaMap,this.envMap=e.envMap,this.envMapRotation.copy(e.envMapRotation),this.combine=e.combine,this.reflectivity=e.reflectivity,this.refractionRatio=e.refractionRatio,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this.wireframeLinecap=e.wireframeLinecap,this.wireframeLinejoin=e.wireframeLinejoin,this.flatShading=e.flatShading,this.fog=e.fog,this}}class Cu extends en{constructor(e){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(e)}copy(e){return super.copy(e),this.depthPacking=e.depthPacking,this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.wireframe=e.wireframe,this.wireframeLinewidth=e.wireframeLinewidth,this}}class Ru extends en{constructor(e){super(),this.isMeshDistanceMaterial=!0,this.type="MeshDistanceMaterial",this.map=null,this.alphaMap=null,this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.setValues(e)}copy(e){return super.copy(e),this.map=e.map,this.alphaMap=e.alphaMap,this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this}}class Eu extends en{constructor(e){super(),this.isMeshMatcapMaterial=!0,this.defines={MATCAP:""},this.type="MeshMatcapMaterial",this.color=new Jr(16777215),this.matcap=null,this.map=null,this.bumpMap=null,this.bumpScale=1,this.normalMap=null,this.normalMapType=0,this.normalScale=new Qs(1,1),this.displacementMap=null,this.displacementScale=1,this.displacementBias=0,this.alphaMap=null,this.flatShading=!1,this.fog=!0,this.setValues(e)}copy(e){return super.copy(e),this.defines={MATCAP:""},this.color.copy(e.color),this.matcap=e.matcap,this.map=e.map,this.bumpMap=e.bumpMap,this.bumpScale=e.bumpScale,this.normalMap=e.normalMap,this.normalMapType=e.normalMapType,this.normalScale.copy(e.normalScale),this.displacementMap=e.displacementMap,this.displacementScale=e.displacementScale,this.displacementBias=e.displacementBias,this.alphaMap=e.alphaMap,this.flatShading=e.flatShading,this.fog=e.fog,this}}class Bu extends Ta{constructor(e){super(),this.isLineDashedMaterial=!0,this.type="LineDashedMaterial",this.scale=1,this.dashSize=3,this.gapSize=1,this.setValues(e)}copy(e){return super.copy(e),this.scale=e.scale,this.dashSize=e.dashSize,this.gapSize=e.gapSize,this}}function Iu(e,t,s){return!e||!s&&e.constructor===t?e:"number"==typeof t.BYTES_PER_ELEMENT?new t(e):Array.prototype.slice.call(e)}function Pu(e){return ArrayBuffer.isView(e)&&!(e instanceof DataView)}function Fu(e){const t=e.length,s=new Array(t);for(let e=0;e!==t;++e)s[e]=e;return s.sort((function(t,s){return e[t]-e[s]})),s}function zu(e,t,s){const i=e.length,r=new e.constructor(i);for(let n=0,o=0;o!==i;++n){const i=s[n]*t;for(let s=0;s!==t;++s)r[o++]=e[i+s]}return r}function Uu(e,t,s,i){let r=1,n=e[0];for(;void 0!==n&&void 0===n[i];)n=e[r++];if(void 0===n)return;let o=n[i];if(void 0!==o)if(Array.isArray(o))do{o=n[i],void 0!==o&&(t.push(n.time),s.push.apply(s,o)),n=e[r++]}while(void 0!==n);else if(void 0!==o.toArray)do{o=n[i],void 0!==o&&(t.push(n.time),o.toArray(s,s.length)),n=e[r++]}while(void 0!==n);else do{o=n[i],void 0!==o&&(t.push(n.time),s.push(o)),n=e[r++]}while(void 0!==n)}const Ou={convertArray:Iu,isTypedArray:Pu,getKeyframeOrder:Fu,sortedArray:zu,flattenJSON:Uu,subclip:function(e,t,s,i,r=30){const n=e.clone();n.name=t;const o=[];for(let e=0;e=i)){h.push(t.times[e]);for(let s=0;sn.tracks[e].times[0]&&(a=n.tracks[e].times[0]);for(let e=0;e=i.times[c]){const e=c*h+a,t=e+h-a;d=i.values.slice(e,t)}else{const e=i.createInterpolant(),t=a,s=h-a;e.evaluate(n),d=e.resultBuffer.slice(t,s)}if("quaternion"===r){(new Ci).fromArray(d).normalize().conjugate().toArray(d)}const p=o.times.length;for(let e=0;e=r)break e;{const o=t[1];e=r)break t}n=s,s=0}}for(;s>>1;et;)--n;if(++n,0!==r||n!==i){r>=n&&(n=Math.max(n,1),r=n-1);const e=this.getValueSize();this.times=s.slice(r,n),this.values=this.values.slice(r*e,n*e)}return this}validate(){let e=!0;const t=this.getValueSize();t-Math.floor(t)!=0&&(console.error("THREE.KeyframeTrack: Invalid value size in track.",this),e=!1);const s=this.times,i=this.values,r=s.length;0===r&&(console.error("THREE.KeyframeTrack: Track is empty.",this),e=!1);let n=null;for(let t=0;t!==r;t++){const i=s[t];if("number"==typeof i&&isNaN(i)){console.error("THREE.KeyframeTrack: Time is not a valid number.",this,t,i),e=!1;break}if(null!==n&&n>i){console.error("THREE.KeyframeTrack: Out of order keys.",this,t,i,n),e=!1;break}n=i}if(void 0!==i&&Pu(i))for(let t=0,s=i.length;t!==s;++t){const s=i[t];if(isNaN(s)){console.error("THREE.KeyframeTrack: Value is not a valid number.",this,t,s),e=!1;break}}return e}optimize(){const e=this.times.slice(),t=this.values.slice(),s=this.getValueSize(),i=this.getInterpolation()===Ft,r=e.length-1;let n=1;for(let o=1;o0){e[n]=e[r];for(let e=r*s,i=n*s,o=0;o!==s;++o)t[i+o]=t[e+o];++n}return n!==e.length?(this.times=e.slice(0,n),this.values=t.slice(0,n*s)):(this.times=e,this.values=t),this}clone(){const e=this.times.slice(),t=this.values.slice(),s=new(0,this.constructor)(this.name,e,t);return s.createInterpolant=this.createInterpolant,s}}Gu.prototype.TimeBufferType=Float32Array,Gu.prototype.ValueBufferType=Float32Array,Gu.prototype.DefaultInterpolation=Pt;class Wu extends Gu{constructor(e,t,s){super(e,t,s)}}Wu.prototype.ValueTypeName="bool",Wu.prototype.ValueBufferType=Array,Wu.prototype.DefaultInterpolation=It,Wu.prototype.InterpolantFactoryMethodLinear=void 0,Wu.prototype.InterpolantFactoryMethodSmooth=void 0;class ju extends Gu{}ju.prototype.ValueTypeName="color";class Hu extends Gu{}Hu.prototype.ValueTypeName="number";class qu extends Lu{constructor(e,t,s,i){super(e,t,s,i)}interpolate_(e,t,s,i){const r=this.resultBuffer,n=this.sampleValues,o=this.valueSize,a=(s-t)/(i-t);let h=e*o;for(let e=h+o;h!==e;h+=4)Ci.slerpFlat(r,0,n,h-o,n,h,a);return r}}class $u extends Gu{InterpolantFactoryMethodLinear(e){return new qu(this.times,this.values,this.getValueSize(),e)}}$u.prototype.ValueTypeName="quaternion",$u.prototype.InterpolantFactoryMethodSmooth=void 0;class Xu extends Gu{constructor(e,t,s){super(e,t,s)}}Xu.prototype.ValueTypeName="string",Xu.prototype.ValueBufferType=Array,Xu.prototype.DefaultInterpolation=It,Xu.prototype.InterpolantFactoryMethodLinear=void 0,Xu.prototype.InterpolantFactoryMethodSmooth=void 0;class Yu extends Gu{}Yu.prototype.ValueTypeName="vector";class Zu{constructor(e="",t=-1,s=[],i=2500){this.name=e,this.tracks=s,this.duration=t,this.blendMode=i,this.uuid=qs(),this.duration<0&&this.resetDuration()}static parse(e){const t=[],s=e.tracks,i=1/(e.fps||1);for(let e=0,r=s.length;e!==r;++e)t.push(Ju(s[e]).scale(i));const r=new this(e.name,e.duration,t,e.blendMode);return r.uuid=e.uuid,r}static toJSON(e){const t=[],s=e.tracks,i={name:e.name,duration:e.duration,tracks:t,uuid:e.uuid,blendMode:e.blendMode};for(let e=0,i=s.length;e!==i;++e)t.push(Gu.toJSON(s[e]));return i}static CreateFromMorphTargetSequence(e,t,s,i){const r=t.length,n=[];for(let e=0;e1){const e=n[1];let t=i[e];t||(i[e]=t=[]),t.push(s)}}const n=[];for(const e in i)n.push(this.CreateFromMorphTargetSequence(e,i[e],t,s));return n}static parseAnimation(e,t){if(!e)return console.error("THREE.AnimationClip: No animation in JSONLoader data."),null;const s=function(e,t,s,i,r){if(0!==s.length){const n=[],o=[];Uu(s,n,o,i),0!==n.length&&r.push(new e(t,n,o))}},i=[],r=e.name||"default",n=e.fps||30,o=e.blendMode;let a=e.length||-1;const h=e.hierarchy||[];for(let e=0;e{t&&t(r),this.manager.itemEnd(e)}),0),r;if(void 0!==sl[e])return void sl[e].push({onLoad:t,onProgress:s,onError:i});sl[e]=[],sl[e].push({onLoad:t,onProgress:s,onError:i});const n=new Request(e,{headers:new Headers(this.requestHeader),credentials:this.withCredentials?"include":"same-origin"}),o=this.mimeType,a=this.responseType;fetch(n).then((t=>{if(200===t.status||0===t.status){if(0===t.status&&console.warn("THREE.FileLoader: HTTP Status 0 received."),"undefined"==typeof ReadableStream||void 0===t.body||void 0===t.body.getReader)return t;const s=sl[e],i=t.body.getReader(),r=t.headers.get("X-File-Size")||t.headers.get("Content-Length"),n=r?parseInt(r):0,o=0!==n;let a=0;const h=new ReadableStream({start(e){!function t(){i.read().then((({done:i,value:r})=>{if(i)e.close();else{a+=r.byteLength;const i=new ProgressEvent("progress",{lengthComputable:o,loaded:a,total:n});for(let e=0,t=s.length;e{e.error(t)}))}()}});return new Response(h)}throw new il(`fetch for "${t.url}" responded with ${t.status}: ${t.statusText}`,t)})).then((e=>{switch(a){case"arraybuffer":return e.arrayBuffer();case"blob":return e.blob();case"document":return e.text().then((e=>(new DOMParser).parseFromString(e,o)));case"json":return e.json();default:if(void 0===o)return e.text();{const t=/charset="?([^;"\s]*)"?/i.exec(o),s=t&&t[1]?t[1].toLowerCase():void 0,i=new TextDecoder(s);return e.arrayBuffer().then((e=>i.decode(e)))}}})).then((t=>{Ku.add(e,t);const s=sl[e];delete sl[e];for(let e=0,i=s.length;e{const s=sl[e];if(void 0===s)throw this.manager.itemError(e),t;delete sl[e];for(let e=0,i=s.length;e{this.manager.itemEnd(e)})),this.manager.itemStart(e)}setResponseType(e){return this.responseType=e,this}setMimeType(e){return this.mimeType=e,this}}class nl extends tl{constructor(e){super(e)}load(e,t,s,i){const r=this,n=new rl(this.manager);n.setPath(this.path),n.setRequestHeader(this.requestHeader),n.setWithCredentials(this.withCredentials),n.load(e,(function(s){try{t(r.parse(JSON.parse(s)))}catch(t){i?i(t):console.error(t),r.manager.itemError(e)}}),s,i)}parse(e){const t=[];for(let s=0;s0:i.vertexColors=e.vertexColors),void 0!==e.uniforms)for(const t in e.uniforms){const r=e.uniforms[t];switch(i.uniforms[t]={},r.type){case"t":i.uniforms[t].value=s(r.value);break;case"c":i.uniforms[t].value=(new Jr).setHex(r.value);break;case"v2":i.uniforms[t].value=(new Qs).fromArray(r.value);break;case"v3":i.uniforms[t].value=(new Ri).fromArray(r.value);break;case"v4":i.uniforms[t].value=(new Ti).fromArray(r.value);break;case"m3":i.uniforms[t].value=(new ei).fromArray(r.value);break;case"m4":i.uniforms[t].value=(new nr).fromArray(r.value);break;default:i.uniforms[t].value=r.value}}if(void 0!==e.defines&&(i.defines=e.defines),void 0!==e.vertexShader&&(i.vertexShader=e.vertexShader),void 0!==e.fragmentShader&&(i.fragmentShader=e.fragmentShader),void 0!==e.glslVersion&&(i.glslVersion=e.glslVersion),void 0!==e.extensions)for(const t in e.extensions)i.extensions[t]=e.extensions[t];if(void 0!==e.lights&&(i.lights=e.lights),void 0!==e.clipping&&(i.clipping=e.clipping),void 0!==e.size&&(i.size=e.size),void 0!==e.sizeAttenuation&&(i.sizeAttenuation=e.sizeAttenuation),void 0!==e.map&&(i.map=s(e.map)),void 0!==e.matcap&&(i.matcap=s(e.matcap)),void 0!==e.alphaMap&&(i.alphaMap=s(e.alphaMap)),void 0!==e.bumpMap&&(i.bumpMap=s(e.bumpMap)),void 0!==e.bumpScale&&(i.bumpScale=e.bumpScale),void 0!==e.normalMap&&(i.normalMap=s(e.normalMap)),void 0!==e.normalMapType&&(i.normalMapType=e.normalMapType),void 0!==e.normalScale){let t=e.normalScale;!1===Array.isArray(t)&&(t=[t,t]),i.normalScale=(new Qs).fromArray(t)}return void 0!==e.displacementMap&&(i.displacementMap=s(e.displacementMap)),void 0!==e.displacementScale&&(i.displacementScale=e.displacementScale),void 0!==e.displacementBias&&(i.displacementBias=e.displacementBias),void 0!==e.roughnessMap&&(i.roughnessMap=s(e.roughnessMap)),void 0!==e.metalnessMap&&(i.metalnessMap=s(e.metalnessMap)),void 0!==e.emissiveMap&&(i.emissiveMap=s(e.emissiveMap)),void 0!==e.emissiveIntensity&&(i.emissiveIntensity=e.emissiveIntensity),void 0!==e.specularMap&&(i.specularMap=s(e.specularMap)),void 0!==e.specularIntensityMap&&(i.specularIntensityMap=s(e.specularIntensityMap)),void 0!==e.specularColorMap&&(i.specularColorMap=s(e.specularColorMap)),void 0!==e.envMap&&(i.envMap=s(e.envMap)),void 0!==e.envMapRotation&&i.envMapRotation.fromArray(e.envMapRotation),void 0!==e.envMapIntensity&&(i.envMapIntensity=e.envMapIntensity),void 0!==e.reflectivity&&(i.reflectivity=e.reflectivity),void 0!==e.refractionRatio&&(i.refractionRatio=e.refractionRatio),void 0!==e.lightMap&&(i.lightMap=s(e.lightMap)),void 0!==e.lightMapIntensity&&(i.lightMapIntensity=e.lightMapIntensity),void 0!==e.aoMap&&(i.aoMap=s(e.aoMap)),void 0!==e.aoMapIntensity&&(i.aoMapIntensity=e.aoMapIntensity),void 0!==e.gradientMap&&(i.gradientMap=s(e.gradientMap)),void 0!==e.clearcoatMap&&(i.clearcoatMap=s(e.clearcoatMap)),void 0!==e.clearcoatRoughnessMap&&(i.clearcoatRoughnessMap=s(e.clearcoatRoughnessMap)),void 0!==e.clearcoatNormalMap&&(i.clearcoatNormalMap=s(e.clearcoatNormalMap)),void 0!==e.clearcoatNormalScale&&(i.clearcoatNormalScale=(new Qs).fromArray(e.clearcoatNormalScale)),void 0!==e.iridescenceMap&&(i.iridescenceMap=s(e.iridescenceMap)),void 0!==e.iridescenceThicknessMap&&(i.iridescenceThicknessMap=s(e.iridescenceThicknessMap)),void 0!==e.transmissionMap&&(i.transmissionMap=s(e.transmissionMap)),void 0!==e.thicknessMap&&(i.thicknessMap=s(e.thicknessMap)),void 0!==e.anisotropyMap&&(i.anisotropyMap=s(e.anisotropyMap)),void 0!==e.sheenColorMap&&(i.sheenColorMap=s(e.sheenColorMap)),void 0!==e.sheenRoughnessMap&&(i.sheenRoughnessMap=s(e.sheenRoughnessMap)),i}setTextures(e){return this.textures=e,this}createMaterialFromType(e){return Bl.createMaterialFromType(e)}static createMaterialFromType(e){return new{ShadowMaterial:vu,SpriteMaterial:no,RawShaderMaterial:Tu,ShaderMaterial:Wn,PointsMaterial:za,MeshPhysicalMaterial:wu,MeshStandardMaterial:_u,MeshPhongMaterial:Su,MeshToonMaterial:Mu,MeshNormalMaterial:Nu,MeshLambertMaterial:Au,MeshDepthMaterial:Cu,MeshDistanceMaterial:Ru,MeshBasicMaterial:tn,MeshMatcapMaterial:Eu,LineDashedMaterial:Bu,LineBasicMaterial:Ta,Material:en}[e]}}class Il{static decodeText(e){if(console.warn("THREE.LoaderUtils: decodeText() has been deprecated with r165 and will be removed with r175. Use TextDecoder instead."),"undefined"!=typeof TextDecoder)return(new TextDecoder).decode(e);let t="";for(let s=0,i=e.length;s0){const s=new Qu(t);r=new al(s),r.setCrossOrigin(this.crossOrigin);for(let t=0,s=e.length;t0){i=new al(this.manager),i.setCrossOrigin(this.crossOrigin);for(let t=0,i=e.length;t{const t=new Ii;t.min.fromArray(e.boxMin),t.max.fromArray(e.boxMax);const s=new Zi;return s.radius=e.sphereRadius,s.center.fromArray(e.sphereCenter),{boxInitialized:e.boxInitialized,box:t,sphereInitialized:e.sphereInitialized,sphere:s}})),n._maxInstanceCount=e.maxInstanceCount,n._maxVertexCount=e.maxVertexCount,n._maxIndexCount=e.maxIndexCount,n._geometryInitialized=e.geometryInitialized,n._geometryCount=e.geometryCount,n._matricesTexture=l(e.matricesTexture.uuid),void 0!==e.colorsTexture&&(n._colorsTexture=l(e.colorsTexture.uuid));break;case"LOD":n=new So;break;case"Line":n=new Ra(h(e.geometry),u(e.material));break;case"LineLoop":n=new Fa(h(e.geometry),u(e.material));break;case"LineSegments":n=new Pa(h(e.geometry),u(e.material));break;case"PointCloud":case"Points":n=new Da(h(e.geometry),u(e.material));break;case"Sprite":n=new vo(u(e.material));break;case"Group":n=new Ga;break;case"Bone":n=new zo;break;default:n=new Ir}if(n.uuid=e.uuid,void 0!==e.name&&(n.name=e.name),void 0!==e.matrix?(n.matrix.fromArray(e.matrix),void 0!==e.matrixAutoUpdate&&(n.matrixAutoUpdate=e.matrixAutoUpdate),n.matrixAutoUpdate&&n.matrix.decompose(n.position,n.quaternion,n.scale)):(void 0!==e.position&&n.position.fromArray(e.position),void 0!==e.rotation&&n.rotation.fromArray(e.rotation),void 0!==e.quaternion&&n.quaternion.fromArray(e.quaternion),void 0!==e.scale&&n.scale.fromArray(e.scale)),void 0!==e.up&&n.up.fromArray(e.up),void 0!==e.castShadow&&(n.castShadow=e.castShadow),void 0!==e.receiveShadow&&(n.receiveShadow=e.receiveShadow),e.shadow&&(void 0!==e.shadow.intensity&&(n.shadow.intensity=e.shadow.intensity),void 0!==e.shadow.bias&&(n.shadow.bias=e.shadow.bias),void 0!==e.shadow.normalBias&&(n.shadow.normalBias=e.shadow.normalBias),void 0!==e.shadow.radius&&(n.shadow.radius=e.shadow.radius),void 0!==e.shadow.mapSize&&n.shadow.mapSize.fromArray(e.shadow.mapSize),void 0!==e.shadow.camera&&(n.shadow.camera=this.parseObject(e.shadow.camera))),void 0!==e.visible&&(n.visible=e.visible),void 0!==e.frustumCulled&&(n.frustumCulled=e.frustumCulled),void 0!==e.renderOrder&&(n.renderOrder=e.renderOrder),void 0!==e.userData&&(n.userData=e.userData),void 0!==e.layers&&(n.layers.mask=e.layers),void 0!==e.children){const o=e.children;for(let e=0;e{t&&t(s),r.manager.itemEnd(e)})).catch((e=>{i&&i(e)})):(setTimeout((function(){t&&t(n),r.manager.itemEnd(e)}),0),n);const o={};o.credentials="anonymous"===this.crossOrigin?"same-origin":"include",o.headers=this.requestHeader;const a=fetch(e,o).then((function(e){return e.blob()})).then((function(e){return createImageBitmap(e,Object.assign(r.options,{colorSpaceConversion:"none"}))})).then((function(s){return Ku.add(e,s),t&&t(s),r.manager.itemEnd(e),s})).catch((function(t){i&&i(t),Ku.remove(e),r.manager.itemError(e),r.manager.itemEnd(e)}));Ku.add(e,a),r.manager.itemStart(e)}}let Dl;class kl{static getContext(){return void 0===Dl&&(Dl=new(window.AudioContext||window.webkitAudioContext)),Dl}static setContext(e){Dl=e}}class Gl extends tl{constructor(e){super(e)}load(e,t,s,i){const r=this,n=new rl(this.manager);function o(t){i?i(t):console.error(t),r.manager.itemError(e)}n.setResponseType("arraybuffer"),n.setPath(this.path),n.setRequestHeader(this.requestHeader),n.setWithCredentials(this.withCredentials),n.load(e,(function(e){try{const s=e.slice(0);kl.getContext().decodeAudioData(s,(function(e){t(e)})).catch(o)}catch(e){o(e)}}),s,i)}}const Wl=new nr,jl=new nr,Hl=new nr;class ql{constructor(){this.type="StereoCamera",this.aspect=1,this.eyeSep=.064,this.cameraL=new Xn,this.cameraL.layers.enable(1),this.cameraL.matrixAutoUpdate=!1,this.cameraR=new Xn,this.cameraR.layers.enable(2),this.cameraR.matrixAutoUpdate=!1,this._cache={focus:null,fov:null,aspect:null,near:null,far:null,zoom:null,eyeSep:null}}update(e){const t=this._cache;if(t.focus!==e.focus||t.fov!==e.fov||t.aspect!==e.aspect*this.aspect||t.near!==e.near||t.far!==e.far||t.zoom!==e.zoom||t.eyeSep!==this.eyeSep){t.focus=e.focus,t.fov=e.fov,t.aspect=e.aspect*this.aspect,t.near=e.near,t.far=e.far,t.zoom=e.zoom,t.eyeSep=this.eyeSep,Hl.copy(e.projectionMatrix);const s=t.eyeSep/2,i=s*t.near/t.focus,r=t.near*Math.tan(js*t.fov*.5)/t.zoom;let n,o;jl.elements[12]=-s,Wl.elements[12]=s,n=-r*t.aspect+i,o=r*t.aspect+i,Hl.elements[0]=2*t.near/(o-n),Hl.elements[8]=(o+n)/(o-n),this.cameraL.projectionMatrix.copy(Hl),n=-r*t.aspect-i,o=r*t.aspect-i,Hl.elements[0]=2*t.near/(o-n),Hl.elements[8]=(o+n)/(o-n),this.cameraR.projectionMatrix.copy(Hl)}this.cameraL.matrixWorld.copy(e.matrixWorld).multiply(jl),this.cameraR.matrixWorld.copy(e.matrixWorld).multiply(Wl)}}class $l extends Xn{constructor(e=[]){super(),this.isArrayCamera=!0,this.cameras=e}}class Xl{constructor(e=!0){this.autoStart=e,this.startTime=0,this.oldTime=0,this.elapsedTime=0,this.running=!1}start(){this.startTime=Yl(),this.oldTime=this.startTime,this.elapsedTime=0,this.running=!0}stop(){this.getElapsedTime(),this.running=!1,this.autoStart=!1}getElapsedTime(){return this.getDelta(),this.elapsedTime}getDelta(){let e=0;if(this.autoStart&&!this.running)return this.start(),0;if(this.running){const t=Yl();e=(t-this.oldTime)/1e3,this.oldTime=t,this.elapsedTime+=e}return e}}function Yl(){return performance.now()}const Zl=new Ri,Jl=new Ci,Kl=new Ri,Ql=new Ri;class ec extends Ir{constructor(){super(),this.type="AudioListener",this.context=kl.getContext(),this.gain=this.context.createGain(),this.gain.connect(this.context.destination),this.filter=null,this.timeDelta=0,this._clock=new Xl}getInput(){return this.gain}removeFilter(){return null!==this.filter&&(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination),this.gain.connect(this.context.destination),this.filter=null),this}getFilter(){return this.filter}setFilter(e){return null!==this.filter?(this.gain.disconnect(this.filter),this.filter.disconnect(this.context.destination)):this.gain.disconnect(this.context.destination),this.filter=e,this.gain.connect(this.filter),this.filter.connect(this.context.destination),this}getMasterVolume(){return this.gain.gain.value}setMasterVolume(e){return this.gain.gain.setTargetAtTime(e,this.context.currentTime,.01),this}updateMatrixWorld(e){super.updateMatrixWorld(e);const t=this.context.listener,s=this.up;if(this.timeDelta=this._clock.getDelta(),this.matrixWorld.decompose(Zl,Jl,Kl),Ql.set(0,0,-1).applyQuaternion(Jl),t.positionX){const e=this.context.currentTime+this.timeDelta;t.positionX.linearRampToValueAtTime(Zl.x,e),t.positionY.linearRampToValueAtTime(Zl.y,e),t.positionZ.linearRampToValueAtTime(Zl.z,e),t.forwardX.linearRampToValueAtTime(Ql.x,e),t.forwardY.linearRampToValueAtTime(Ql.y,e),t.forwardZ.linearRampToValueAtTime(Ql.z,e),t.upX.linearRampToValueAtTime(s.x,e),t.upY.linearRampToValueAtTime(s.y,e),t.upZ.linearRampToValueAtTime(s.z,e)}else t.setPosition(Zl.x,Zl.y,Zl.z),t.setOrientation(Ql.x,Ql.y,Ql.z,s.x,s.y,s.z)}}class tc extends Ir{constructor(e){super(),this.type="Audio",this.listener=e,this.context=e.context,this.gain=this.context.createGain(),this.gain.connect(e.getInput()),this.autoplay=!1,this.buffer=null,this.detune=0,this.loop=!1,this.loopStart=0,this.loopEnd=0,this.offset=0,this.duration=void 0,this.playbackRate=1,this.isPlaying=!1,this.hasPlaybackControl=!0,this.source=null,this.sourceType="empty",this._startedAt=0,this._progress=0,this._connected=!1,this.filters=[]}getOutput(){return this.gain}setNodeSource(e){return this.hasPlaybackControl=!1,this.sourceType="audioNode",this.source=e,this.connect(),this}setMediaElementSource(e){return this.hasPlaybackControl=!1,this.sourceType="mediaNode",this.source=this.context.createMediaElementSource(e),this.connect(),this}setMediaStreamSource(e){return this.hasPlaybackControl=!1,this.sourceType="mediaStreamNode",this.source=this.context.createMediaStreamSource(e),this.connect(),this}setBuffer(e){return this.buffer=e,this.sourceType="buffer",this.autoplay&&this.play(),this}play(e=0){if(!0===this.isPlaying)return void console.warn("THREE.Audio: Audio is already playing.");if(!1===this.hasPlaybackControl)return void console.warn("THREE.Audio: this Audio has no playback control.");this._startedAt=this.context.currentTime+e;const t=this.context.createBufferSource();return t.buffer=this.buffer,t.loop=this.loop,t.loopStart=this.loopStart,t.loopEnd=this.loopEnd,t.onended=this.onEnded.bind(this),t.start(this._startedAt,this._progress+this.offset,this.duration),this.isPlaying=!0,this.source=t,this.setDetune(this.detune),this.setPlaybackRate(this.playbackRate),this.connect()}pause(){if(!1!==this.hasPlaybackControl)return!0===this.isPlaying&&(this._progress+=Math.max(this.context.currentTime-this._startedAt,0)*this.playbackRate,!0===this.loop&&(this._progress=this._progress%(this.duration||this.buffer.duration)),this.source.stop(),this.source.onended=null,this.isPlaying=!1),this;console.warn("THREE.Audio: this Audio has no playback control.")}stop(e=0){if(!1!==this.hasPlaybackControl)return this._progress=0,null!==this.source&&(this.source.stop(this.context.currentTime+e),this.source.onended=null),this.isPlaying=!1,this;console.warn("THREE.Audio: this Audio has no playback control.")}connect(){if(this.filters.length>0){this.source.connect(this.filters[0]);for(let e=1,t=this.filters.length;e0){this.source.disconnect(this.filters[0]);for(let e=1,t=this.filters.length;e0&&this._mixBufferRegionAdditive(s,i,this._addIndex*t,1,t);for(let e=t,r=t+t;e!==r;++e)if(s[e]!==s[e+t]){o.setValue(s,i);break}}saveOriginalState(){const e=this.binding,t=this.buffer,s=this.valueSize,i=s*this._origIndex;e.getValue(t,i);for(let e=s,r=i;e!==r;++e)t[e]=t[i+e%s];this._setIdentity(),this.cumulativeWeight=0,this.cumulativeWeightAdditive=0}restoreOriginalState(){const e=3*this.valueSize;this.binding.setValue(this.buffer,e)}_setAdditiveIdentityNumeric(){const e=this._addIndex*this.valueSize,t=e+this.valueSize;for(let s=e;s=.5)for(let i=0;i!==r;++i)e[t+i]=e[s+i]}_slerp(e,t,s,i){Ci.slerpFlat(e,t,e,t,e,s,i)}_slerpAdditive(e,t,s,i,r){const n=this._workIndex*r;Ci.multiplyQuaternionsFlat(e,n,e,t,e,s),Ci.slerpFlat(e,t,e,t,e,n,i)}_lerp(e,t,s,i,r){const n=1-i;for(let o=0;o!==r;++o){const r=t+o;e[r]=e[r]*n+e[s+o]*i}}_lerpAdditive(e,t,s,i,r){for(let n=0;n!==r;++n){const r=t+n;e[r]=e[r]+e[s+n]*i}}}const uc="\\[\\]\\.:\\/",lc=new RegExp("["+uc+"]","g"),cc="[^"+uc+"]",dc="[^"+uc.replace("\\.","")+"]",pc=new RegExp("^"+/((?:WC+[\/:])*)/.source.replace("WC",cc)+/(WCOD+)?/.source.replace("WCOD",dc)+/(?:\.(WC+)(?:\[(.+)\])?)?/.source.replace("WC",cc)+/\.(WC+)(?:\[(.+)\])?/.source.replace("WC",cc)+"$"),mc=["material","materials","bones","map"];class gc{constructor(e,t,s){this.path=t,this.parsedPath=s||gc.parseTrackName(t),this.node=gc.findNode(e,this.parsedPath.nodeName),this.rootNode=e,this.getValue=this._getValue_unbound,this.setValue=this._setValue_unbound}static create(e,t,s){return e&&e.isAnimationObjectGroup?new gc.Composite(e,t,s):new gc(e,t,s)}static sanitizeNodeName(e){return e.replace(/\s/g,"_").replace(lc,"")}static parseTrackName(e){const t=pc.exec(e);if(null===t)throw new Error("PropertyBinding: Cannot parse trackName: "+e);const s={nodeName:t[2],objectName:t[3],objectIndex:t[4],propertyName:t[5],propertyIndex:t[6]},i=s.nodeName&&s.nodeName.lastIndexOf(".");if(void 0!==i&&-1!==i){const e=s.nodeName.substring(i+1);-1!==mc.indexOf(e)&&(s.nodeName=s.nodeName.substring(0,i),s.objectName=e)}if(null===s.propertyName||0===s.propertyName.length)throw new Error("PropertyBinding: can not parse propertyName from trackName: "+e);return s}static findNode(e,t){if(void 0===t||""===t||"."===t||-1===t||t===e.name||t===e.uuid)return e;if(e.skeleton){const s=e.skeleton.getBoneByName(t);if(void 0!==s)return s}if(e.children){const s=function(e){for(let i=0;i=r){const n=r++,u=e[n];t[u.uuid]=h,e[h]=u,t[a]=n,e[n]=o;for(let e=0,t=i;e!==t;++e){const t=s[e],i=t[n],r=t[h];t[h]=i,t[n]=r}}}this.nCachedObjects_=r}uncache(){const e=this._objects,t=this._indicesByUUID,s=this._bindings,i=s.length;let r=this.nCachedObjects_,n=e.length;for(let o=0,a=arguments.length;o!==a;++o){const a=arguments[o].uuid,h=t[a];if(void 0!==h)if(delete t[a],h0&&(t[o.uuid]=h),e[h]=o,e.pop();for(let e=0,t=i;e!==t;++e){const t=s[e];t[h]=t[r],t.pop()}}}this.nCachedObjects_=r}subscribe_(e,t){const s=this._bindingsIndicesByPath;let i=s[e];const r=this._bindings;if(void 0!==i)return r[i];const n=this._paths,o=this._parsedPaths,a=this._objects,h=a.length,u=this.nCachedObjects_,l=new Array(h);i=r.length,s[e]=i,n.push(e),o.push(t),r.push(l);for(let s=u,i=a.length;s!==i;++s){const i=a[s];l[s]=new gc(i,e,t)}return l}unsubscribe_(e){const t=this._bindingsIndicesByPath,s=t[e];if(void 0!==s){const i=this._paths,r=this._parsedPaths,n=this._bindings,o=n.length-1,a=n[o];t[e[o]]=s,n[s]=a,n.pop(),r[s]=r[o],r.pop(),i[s]=i[o],i.pop()}}}class yc{constructor(e,t,s=null,i=t.blendMode){this._mixer=e,this._clip=t,this._localRoot=s,this.blendMode=i;const r=t.tracks,n=r.length,o=new Array(n),a={endingStart:zt,endingEnd:zt};for(let e=0;e!==n;++e){const t=r[e].createInterpolant(null);o[e]=t,t.settings=a}this._interpolantSettings=a,this._interpolants=o,this._propertyBindings=new Array(n),this._cacheIndex=null,this._byClipCacheIndex=null,this._timeScaleInterpolant=null,this._weightInterpolant=null,this.loop=2201,this._loopCount=-1,this._startTime=null,this.time=0,this.timeScale=1,this._effectiveTimeScale=1,this.weight=1,this._effectiveWeight=1,this.repetitions=1/0,this.paused=!1,this.enabled=!0,this.clampWhenFinished=!1,this.zeroSlopeAtStart=!0,this.zeroSlopeAtEnd=!0}play(){return this._mixer._activateAction(this),this}stop(){return this._mixer._deactivateAction(this),this.reset()}reset(){return this.paused=!1,this.enabled=!0,this.time=0,this._loopCount=-1,this._startTime=null,this.stopFading().stopWarping()}isRunning(){return this.enabled&&!this.paused&&0!==this.timeScale&&null===this._startTime&&this._mixer._isActiveAction(this)}isScheduled(){return this._mixer._isActiveAction(this)}startAt(e){return this._startTime=e,this}setLoop(e,t){return this.loop=e,this.repetitions=t,this}setEffectiveWeight(e){return this.weight=e,this._effectiveWeight=this.enabled?e:0,this.stopFading()}getEffectiveWeight(){return this._effectiveWeight}fadeIn(e){return this._scheduleFading(e,0,1)}fadeOut(e){return this._scheduleFading(e,1,0)}crossFadeFrom(e,t,s){if(e.fadeOut(t),this.fadeIn(t),s){const s=this._clip.duration,i=e._clip.duration,r=i/s,n=s/i;e.warp(1,r,t),this.warp(n,1,t)}return this}crossFadeTo(e,t,s){return e.crossFadeFrom(this,t,s)}stopFading(){const e=this._weightInterpolant;return null!==e&&(this._weightInterpolant=null,this._mixer._takeBackControlInterpolant(e)),this}setEffectiveTimeScale(e){return this.timeScale=e,this._effectiveTimeScale=this.paused?0:e,this.stopWarping()}getEffectiveTimeScale(){return this._effectiveTimeScale}setDuration(e){return this.timeScale=this._clip.duration/e,this.stopWarping()}syncWith(e){return this.time=e.time,this.timeScale=e.timeScale,this.stopWarping()}halt(e){return this.warp(this._effectiveTimeScale,0,e)}warp(e,t,s){const i=this._mixer,r=i.time,n=this.timeScale;let o=this._timeScaleInterpolant;null===o&&(o=i._lendControlInterpolant(),this._timeScaleInterpolant=o);const a=o.parameterPositions,h=o.sampleValues;return a[0]=r,a[1]=r+s,h[0]=e/n,h[1]=t/n,this}stopWarping(){const e=this._timeScaleInterpolant;return null!==e&&(this._timeScaleInterpolant=null,this._mixer._takeBackControlInterpolant(e)),this}getMixer(){return this._mixer}getClip(){return this._clip}getRoot(){return this._localRoot||this._mixer._root}_update(e,t,s,i){if(!this.enabled)return void this._updateWeight(e);const r=this._startTime;if(null!==r){const i=(e-r)*s;i<0||0===s?t=0:(this._startTime=null,t=s*i)}t*=this._updateTimeScale(e);const n=this._updateTime(t),o=this._updateWeight(e);if(o>0){const e=this._interpolants,t=this._propertyBindings;if(this.blendMode===Vt)for(let s=0,i=e.length;s!==i;++s)e[s].evaluate(n),t[s].accumulateAdditive(o);else for(let s=0,r=e.length;s!==r;++s)e[s].evaluate(n),t[s].accumulate(i,o)}}_updateWeight(e){let t=0;if(this.enabled){t=this.weight;const s=this._weightInterpolant;if(null!==s){const i=s.evaluate(e)[0];t*=i,e>s.parameterPositions[1]&&(this.stopFading(),0===i&&(this.enabled=!1))}}return this._effectiveWeight=t,t}_updateTimeScale(e){let t=0;if(!this.paused){t=this.timeScale;const s=this._timeScaleInterpolant;if(null!==s){t*=s.evaluate(e)[0],e>s.parameterPositions[1]&&(this.stopWarping(),0===t?this.paused=!0:this.timeScale=t)}}return this._effectiveTimeScale=t,t}_updateTime(e){const t=this._clip.duration,s=this.loop;let i=this.time+e,r=this._loopCount;const n=2202===s;if(0===e)return-1===r?i:n&&1==(1&r)?t-i:i;if(2200===s){-1===r&&(this._loopCount=0,this._setEndings(!0,!0,!1));e:{if(i>=t)i=t;else{if(!(i<0)){this.time=i;break e}i=0}this.clampWhenFinished?this.paused=!0:this.enabled=!1,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:e<0?-1:1})}}else{if(-1===r&&(e>=0?(r=0,this._setEndings(!0,0===this.repetitions,n)):this._setEndings(0===this.repetitions,!0,n)),i>=t||i<0){const s=Math.floor(i/t);i-=t*s,r+=Math.abs(s);const o=this.repetitions-r;if(o<=0)this.clampWhenFinished?this.paused=!0:this.enabled=!1,i=e>0?t:0,this.time=i,this._mixer.dispatchEvent({type:"finished",action:this,direction:e>0?1:-1});else{if(1===o){const t=e<0;this._setEndings(t,!t,n)}else this._setEndings(!1,!1,n);this._loopCount=r,this.time=i,this._mixer.dispatchEvent({type:"loop",action:this,loopDelta:s})}}else this.time=i;if(n&&1==(1&r))return t-i}return i}_setEndings(e,t,s){const i=this._interpolantSettings;s?(i.endingStart=Ut,i.endingEnd=Ut):(i.endingStart=e?this.zeroSlopeAtStart?Ut:zt:Ot,i.endingEnd=t?this.zeroSlopeAtEnd?Ut:zt:Ot)}_scheduleFading(e,t,s){const i=this._mixer,r=i.time;let n=this._weightInterpolant;null===n&&(n=i._lendControlInterpolant(),this._weightInterpolant=n);const o=n.parameterPositions,a=n.sampleValues;return o[0]=r,a[0]=t,o[1]=r+e,a[1]=s,this}}const xc=new Float32Array(1);class bc extends ks{constructor(e){super(),this._root=e,this._initMemoryManager(),this._accuIndex=0,this.time=0,this.timeScale=1}_bindAction(e,t){const s=e._localRoot||this._root,i=e._clip.tracks,r=i.length,n=e._propertyBindings,o=e._interpolants,a=s.uuid,h=this._bindingsByRootAndName;let u=h[a];void 0===u&&(u={},h[a]=u);for(let e=0;e!==r;++e){const r=i[e],h=r.name;let l=u[h];if(void 0!==l)++l.referenceCount,n[e]=l;else{if(l=n[e],void 0!==l){null===l._cacheIndex&&(++l.referenceCount,this._addInactiveBinding(l,a,h));continue}const i=t&&t._propertyBindings[e].binding.parsedPath;l=new hc(gc.create(s,h,i),r.ValueTypeName,r.getValueSize()),++l.referenceCount,this._addInactiveBinding(l,a,h),n[e]=l}o[e].resultBuffer=l.buffer}}_activateAction(e){if(!this._isActiveAction(e)){if(null===e._cacheIndex){const t=(e._localRoot||this._root).uuid,s=e._clip.uuid,i=this._actionsByClip[s];this._bindAction(e,i&&i.knownActions[0]),this._addInactiveAction(e,s,t)}const t=e._propertyBindings;for(let e=0,s=t.length;e!==s;++e){const s=t[e];0==s.useCount++&&(this._lendBinding(s),s.saveOriginalState())}this._lendAction(e)}}_deactivateAction(e){if(this._isActiveAction(e)){const t=e._propertyBindings;for(let e=0,s=t.length;e!==s;++e){const s=t[e];0==--s.useCount&&(s.restoreOriginalState(),this._takeBackBinding(s))}this._takeBackAction(e)}}_initMemoryManager(){this._actions=[],this._nActiveActions=0,this._actionsByClip={},this._bindings=[],this._nActiveBindings=0,this._bindingsByRootAndName={},this._controlInterpolants=[],this._nActiveControlInterpolants=0;const e=this;this.stats={actions:{get total(){return e._actions.length},get inUse(){return e._nActiveActions}},bindings:{get total(){return e._bindings.length},get inUse(){return e._nActiveBindings}},controlInterpolants:{get total(){return e._controlInterpolants.length},get inUse(){return e._nActiveControlInterpolants}}}}_isActiveAction(e){const t=e._cacheIndex;return null!==t&&t=0;--t)e[t].stop();return this}update(e){e*=this.timeScale;const t=this._actions,s=this._nActiveActions,i=this.time+=e,r=Math.sign(e),n=this._accuIndex^=1;for(let o=0;o!==s;++o){t[o]._update(i,e,r,n)}const o=this._bindings,a=this._nActiveBindings;for(let e=0;e!==a;++e)o[e].apply(n);return this}setTime(e){this.time=0;for(let e=0;e=this.min.x&&e.x<=this.max.x&&e.y>=this.min.y&&e.y<=this.max.y}containsBox(e){return this.min.x<=e.min.x&&e.max.x<=this.max.x&&this.min.y<=e.min.y&&e.max.y<=this.max.y}getParameter(e,t){return t.set((e.x-this.min.x)/(this.max.x-this.min.x),(e.y-this.min.y)/(this.max.y-this.min.y))}intersectsBox(e){return e.max.x>=this.min.x&&e.min.x<=this.max.x&&e.max.y>=this.min.y&&e.min.y<=this.max.y}clampPoint(e,t){return t.copy(e).clamp(this.min,this.max)}distanceToPoint(e){return this.clampPoint(e,Ic).distanceTo(e)}intersect(e){return this.min.max(e.min),this.max.min(e.max),this.isEmpty()&&this.makeEmpty(),this}union(e){return this.min.min(e.min),this.max.max(e.max),this}translate(e){return this.min.add(e),this.max.add(e),this}equals(e){return e.min.equals(this.min)&&e.max.equals(this.max)}}const Fc=new Ri,zc=new Ri;class Uc{constructor(e=new Ri,t=new Ri){this.start=e,this.end=t}set(e,t){return this.start.copy(e),this.end.copy(t),this}copy(e){return this.start.copy(e.start),this.end.copy(e.end),this}getCenter(e){return e.addVectors(this.start,this.end).multiplyScalar(.5)}delta(e){return e.subVectors(this.end,this.start)}distanceSq(){return this.start.distanceToSquared(this.end)}distance(){return this.start.distanceTo(this.end)}at(e,t){return this.delta(t).multiplyScalar(e).add(this.start)}closestPointToPointParameter(e,t){Fc.subVectors(e,this.start),zc.subVectors(this.end,this.start);const s=zc.dot(zc);let i=zc.dot(Fc)/s;return t&&(i=$s(i,0,1)),i}closestPointToPoint(e,t,s){const i=this.closestPointToPointParameter(e,t);return this.delta(s).multiplyScalar(i).add(this.start)}applyMatrix4(e){return this.start.applyMatrix4(e),this.end.applyMatrix4(e),this}equals(e){return e.start.equals(this.start)&&e.end.equals(this.end)}clone(){return(new this.constructor).copy(this)}}const Oc=new Ri;class Lc extends Ir{constructor(e,t){super(),this.light=e,this.matrixAutoUpdate=!1,this.color=t,this.type="SpotLightHelper";const s=new An,i=[0,0,0,0,0,1,0,0,0,1,0,1,0,0,0,-1,0,1,0,0,0,0,1,1,0,0,0,0,-1,1];for(let e=0,t=1,s=32;e1)for(let s=0;s.99999)this.quaternion.set(0,0,0,1);else if(e.y<-.99999)this.quaternion.set(1,0,0,0);else{ud.set(e.z,0,-e.x).normalize();const t=Math.acos(e.y);this.quaternion.setFromAxisAngle(ud,t)}}setLength(e,t=.2*e,s=.2*t){this.line.scale.set(1,Math.max(1e-4,e-t),1),this.line.updateMatrix(),this.cone.scale.set(s,t,s),this.cone.position.y=e,this.cone.updateMatrix()}setColor(e){this.line.material.color.set(e),this.cone.material.color.set(e)}copy(e){return super.copy(e,!1),this.line.copy(e.line),this.cone.copy(e.cone),this}dispose(){this.line.geometry.dispose(),this.line.material.dispose(),this.cone.geometry.dispose(),this.cone.material.dispose()}}class pd extends Pa{constructor(e=1){const t=[0,0,0,e,0,0,0,0,0,0,e,0,0,0,0,0,0,e],s=new An;s.setAttribute("position",new bn(t,3)),s.setAttribute("color",new bn([1,0,0,1,.6,0,0,1,0,.6,1,0,0,0,1,0,.6,1],3));super(s,new Ta({vertexColors:!0,toneMapped:!1})),this.type="AxesHelper"}setColors(e,t,s){const i=new Jr,r=this.geometry.attributes.color.array;return i.set(e),i.toArray(r,0),i.toArray(r,3),i.set(t),i.toArray(r,6),i.toArray(r,9),i.set(s),i.toArray(r,12),i.toArray(r,15),this.geometry.attributes.color.needsUpdate=!0,this}dispose(){this.geometry.dispose(),this.material.dispose()}}class md{constructor(){this.type="ShapePath",this.color=new Jr,this.subPaths=[],this.currentPath=null}moveTo(e,t){return this.currentPath=new yh,this.subPaths.push(this.currentPath),this.currentPath.moveTo(e,t),this}lineTo(e,t){return this.currentPath.lineTo(e,t),this}quadraticCurveTo(e,t,s,i){return this.currentPath.quadraticCurveTo(e,t,s,i),this}bezierCurveTo(e,t,s,i,r,n){return this.currentPath.bezierCurveTo(e,t,s,i,r,n),this}splineThru(e){return this.currentPath.splineThru(e),this}toShapes(e){function t(e,t){const s=t.length;let i=!1;for(let r=s-1,n=0;nNumber.EPSILON){if(h<0&&(s=t[n],a=-a,o=t[r],h=-h),e.yo.y)continue;if(e.y===s.y){if(e.x===s.x)return!0}else{const t=h*(e.x-s.x)-a*(e.y-s.y);if(0===t)return!0;if(t<0)continue;i=!i}}else{if(e.y!==s.y)continue;if(o.x<=e.x&&e.x<=s.x||s.x<=e.x&&e.x<=o.x)return!0}}return i}const s=su.isClockWise,i=this.subPaths;if(0===i.length)return[];let r,n,o;const a=[];if(1===i.length)return n=i[0],o=new Eh,o.curves=n.curves,a.push(o),a;let h=!s(i[0].getPoints());h=e?!h:h;const u=[],l=[];let c,d,p=[],m=0;l[m]=void 0,p[m]=[];for(let t=0,o=i.length;t1){let e=!1,s=0;for(let e=0,t=l.length;e0&&!1===e&&(p=u)}for(let e=0,t=l.length;e>>16,2246822507),s^=Math.imul(i^i>>>13,3266489909),i=Math.imul(i^i>>>16,2246822507),i^=Math.imul(s^s>>>13,3266489909),4294967296*(2097151&i)+(s>>>0)}const vd=e=>bd(e),Td=e=>bd(e),_d=(...e)=>bd(e);function wd(e,t=!1){const s=[];!0===e.isNode&&(s.push(e.id),e=e.getSelf());for(const{property:i,childNode:r}of Sd(e))s.push(s,bd(i.slice(0,-4)),r.getCacheKey(t));return bd(s)}function*Sd(e,t=!1){for(const s in e){if(!0===s.startsWith("_"))continue;const i=e[s];if(!0===Array.isArray(i))for(let e=0;ee.charCodeAt(0))).buffer}var Rd=Object.freeze({__proto__:null,arrayBufferToBase64:Ad,base64ToArrayBuffer:Cd,getCacheKey:wd,getNodeChildren:Sd,getValueFromType:Nd,getValueType:Md,hash:_d,hashArray:Td,hashString:vd});const Ed={VERTEX:"vertex",FRAGMENT:"fragment"},Bd={NONE:"none",FRAME:"frame",RENDER:"render",OBJECT:"object"},Id={BOOLEAN:"bool",INTEGER:"int",FLOAT:"float",VECTOR2:"vec2",VECTOR3:"vec3",VECTOR4:"vec4",MATRIX2:"mat2",MATRIX3:"mat3",MATRIX4:"mat4"},Pd=["fragment","vertex"],Fd=["setup","analyze","generate"],zd=[...Pd,"compute"],Ud=["x","y","z","w"];let Od=0;class Ld extends ks{static get type(){return"Node"}constructor(e=null){super(),this.nodeType=e,this.updateType=Bd.NONE,this.updateBeforeType=Bd.NONE,this.updateAfterType=Bd.NONE,this.uuid=Ks.generateUUID(),this.version=0,this._cacheKey=null,this._cacheKeyVersion=0,this.global=!1,this.isNode=!0,Object.defineProperty(this,"id",{value:Od++})}set needsUpdate(e){!0===e&&this.version++}get type(){return this.constructor.type}onUpdate(e,t){return this.updateType=t,this.update=e.bind(this.getSelf()),this}onFrameUpdate(e){return this.onUpdate(e,Bd.FRAME)}onRenderUpdate(e){return this.onUpdate(e,Bd.RENDER)}onObjectUpdate(e){return this.onUpdate(e,Bd.OBJECT)}onReference(e){return this.updateReference=e.bind(this.getSelf()),this}getSelf(){return this.self||this}updateReference(){return this}isGlobal(){return this.global}*getChildren(){for(const{childNode:e}of Sd(this))yield e}dispose(){this.dispatchEvent({type:"dispose"})}traverse(e){e(this);for(const t of this.getChildren())t.traverse(e)}getCacheKey(e=!1){return!0!==(e=e||this.version!==this._cacheKeyVersion)&&null!==this._cacheKey||(this._cacheKey=wd(this,e),this._cacheKeyVersion=this.version),this._cacheKey}getScope(){return this}getHash(){return this.uuid}getUpdateType(){return this.updateType}getUpdateBeforeType(){return this.updateBeforeType}getUpdateAfterType(){return this.updateAfterType}getElementType(e){const t=this.getNodeType(e);return e.getElementType(t)}getNodeType(e){const t=e.getNodeProperties(this);return t.outputNode?t.outputNode.getNodeType(e):this.nodeType}getShared(e){const t=this.getHash(e);return e.getNodeFromHash(t)||this}setup(e){const t=e.getNodeProperties(this);let s=0;for(const e of this.getChildren())t["node"+s++]=e;return null}analyze(e){if(1===e.increaseUsage(this)){const t=e.getNodeProperties(this);for(const s of Object.values(t))s&&!0===s.isNode&&s.build(e)}}generate(e,t){const{outputNode:s}=e.getNodeProperties(this);if(s&&!0===s.isNode)return s.build(e,t)}updateBefore(){console.warn("Abstract function.")}updateAfter(){console.warn("Abstract function.")}update(){console.warn("Abstract function.")}build(e,t=null){const s=this.getShared(e);if(this!==s)return s.build(e,t);e.addNode(this),e.addChain(this);let i=null;const r=e.getBuildStage();if("setup"===r){this.updateReference(e);const t=e.getNodeProperties(this);if(!0!==t.initialized){e.stack.nodes.length;t.initialized=!0,t.outputNode=this.setup(e),null!==t.outputNode&&e.stack.nodes.length;for(const s of Object.values(t))s&&!0===s.isNode&&s.build(e)}}else if("analyze"===r)this.analyze(e);else if("generate"===r){if(1===this.generate.length){const s=this.getNodeType(e),r=e.getDataFromNode(this);i=r.snippet,void 0===i?(i=this.generate(e)||"",r.snippet=i):void 0!==r.flowCodes&&void 0!==e.context.nodeBlock&&e.addFlowCodeHierarchy(this,e.context.nodeBlock),i=e.format(i,s,t)}else i=this.generate(e,t)||""}return e.removeChain(this),i}getSerializeChildren(){return Sd(this)}serialize(e){const t=this.getSerializeChildren(),s={};for(const{property:i,index:r,childNode:n}of t)void 0!==r?(void 0===s[i]&&(s[i]=Number.isInteger(r)?[]:{}),s[i][r]=n.toJSON(e.meta).uuid):s[i]=n.toJSON(e.meta).uuid;Object.keys(s).length>0&&(e.inputNodes=s)}deserialize(e){if(void 0!==e.inputNodes){const t=e.meta.nodes;for(const s in e.inputNodes)if(Array.isArray(e.inputNodes[s])){const i=[];for(const r of e.inputNodes[s])i.push(t[r]);this[s]=i}else if("object"==typeof e.inputNodes[s]){const i={};for(const r in e.inputNodes[s]){const n=e.inputNodes[s][r];i[r]=t[n]}this[s]=i}else{const i=e.inputNodes[s];this[s]=t[i]}}}toJSON(e){const{uuid:t,type:s}=this,i=void 0===e||"string"==typeof e;i&&(e={textures:{},images:{},nodes:{}});let r=e.nodes[t];function n(e){const t=[];for(const s in e){const i=e[s];delete i.metadata,t.push(i)}return t}if(void 0===r&&(r={uuid:t,type:s,meta:e,metadata:{version:4.6,type:"Node",generator:"Node.toJSON"}},!0!==i&&(e.nodes[r.uuid]=r),this.serialize(r),delete r.meta),i){const t=n(e.textures),s=n(e.images),i=n(e.nodes);t.length>0&&(r.textures=t),s.length>0&&(r.images=s),i.length>0&&(r.nodes=i)}return r}}class Vd extends Ld{static get type(){return"ArrayElementNode"}constructor(e,t){super(),this.node=e,this.indexNode=t,this.isArrayElementNode=!0}getNodeType(e){return this.node.getElementType(e)}generate(e){return`${this.node.build(e)}[ ${this.indexNode.build(e,"uint")} ]`}}class Dd extends Ld{static get type(){return"ConvertNode"}constructor(e,t){super(),this.node=e,this.convertTo=t}getNodeType(e){const t=this.node.getNodeType(e);let s=null;for(const i of this.convertTo.split("|"))null!==s&&e.getTypeLength(t)!==e.getTypeLength(i)||(s=i);return s}serialize(e){super.serialize(e),e.convertTo=this.convertTo}deserialize(e){super.deserialize(e),this.convertTo=e.convertTo}generate(e,t){const s=this.node,i=this.getNodeType(e),r=s.build(e,i);return e.format(r,i,t)}}class kd extends Ld{static get type(){return"TempNode"}constructor(e){super(e),this.isTempNode=!0}hasDependencies(e){return e.getDataFromNode(this).usageCount>1}build(e,t){if("generate"===e.getBuildStage()){const s=e.getVectorType(this.getNodeType(e,t)),i=e.getDataFromNode(this);if(void 0!==i.propertyName)return e.format(i.propertyName,s,t);if("void"!==s&&"void"!==t&&this.hasDependencies(e)){const r=super.build(e,s),n=e.getVarFromNode(this,null,s),o=e.getPropertyName(n);return e.addLineFlowCode(`${o} = ${r}`,this),i.snippet=r,i.propertyName=o,e.format(i.propertyName,s,t)}}return super.build(e,t)}}class Gd extends kd{static get type(){return"JoinNode"}constructor(e=[],t=null){super(t),this.nodes=e}getNodeType(e){return null!==this.nodeType?e.getVectorType(this.nodeType):e.getTypeFromLength(this.nodes.reduce(((t,s)=>t+e.getTypeLength(s.getNodeType(e))),0))}generate(e,t){const s=this.getNodeType(e),i=this.nodes,r=e.getComponentType(s),n=[];for(const t of i){let s=t.build(e);const i=e.getComponentType(t.getNodeType(e));i!==r&&(s=e.format(s,i,r)),n.push(s)}const o=`${e.getType(s)}( ${n.join(", ")} )`;return e.format(o,s,t)}}const Wd=Ud.join("");class jd extends Ld{static get type(){return"SplitNode"}constructor(e,t="x"){super(),this.node=e,this.components=t,this.isSplitNode=!0}getVectorLength(){let e=this.components.length;for(const t of this.components)e=Math.max(Ud.indexOf(t)+1,e);return e}getComponentType(e){return e.getComponentType(this.node.getNodeType(e))}getNodeType(e){return e.getTypeFromLength(this.components.length,this.getComponentType(e))}generate(e,t){const s=this.node,i=e.getTypeLength(s.getNodeType(e));let r=null;if(i>1){let n=null;this.getVectorLength()>=i&&(n=e.getTypeFromLength(this.getVectorLength(),this.getComponentType(e)));const o=s.build(e,n);r=this.components.length===i&&this.components===Wd.slice(0,this.components.length)?e.format(o,n,t):e.format(`${o}.${this.components}`,this.getNodeType(e),t)}else r=s.build(e,t);return r}serialize(e){super.serialize(e),e.components=this.components}deserialize(e){super.deserialize(e),this.components=e.components}}class Hd extends kd{static get type(){return"SetNode"}constructor(e,t,s){super(),this.sourceNode=e,this.components=t,this.targetNode=s}getNodeType(e){return this.sourceNode.getNodeType(e)}generate(e){const{sourceNode:t,components:s,targetNode:i}=this,r=this.getNodeType(e),n=e.getTypeFromLength(s.length,i.getNodeType(e)),o=i.build(e,n),a=t.build(e,r),h=e.getTypeLength(r),u=[];for(let e=0;ee.replace(/r|s/g,"x").replace(/g|t/g,"y").replace(/b|p/g,"z").replace(/a|q/g,"w"),Qd=e=>Kd(e).split("").sort().join(""),ep={setup(e,t){const s=t.shift();return e(Mp(s),...t)},get(e,t,s){if("string"==typeof t&&void 0===e[t]){if(!0!==e.isStackNode&&"assign"===t)return(...e)=>(Yd.assign(s,...e),s);if(Zd.has(t)){const i=Zd.get(t);return e.isStackNode?(...e)=>s.add(i(...e)):(...e)=>i(s,...e)}if("self"===t)return e;if(t.endsWith("Assign")&&Zd.has(t.slice(0,t.length-6))){const i=Zd.get(t.slice(0,t.length-6));return e.isStackNode?(...e)=>s.assign(e[0],i(...e)):(...e)=>s.assign(i(s,...e))}if(!0===/^[xyzwrgbastpq]{1,4}$/.test(t))return t=Kd(t),Sp(new jd(s,t));if(!0===/^set[XYZWRGBASTPQ]{1,4}$/.test(t))return t=Qd(t.slice(3).toLowerCase()),s=>Sp(new Hd(e,t,s));if(!0===/^flip[XYZWRGBASTPQ]{1,4}$/.test(t))return t=Qd(t.slice(4).toLowerCase()),()=>Sp(new qd(Sp(e),t));if("width"===t||"height"===t||"depth"===t)return"width"===t?t="x":"height"===t?t="y":"depth"===t&&(t="z"),Sp(new jd(e,t));if(!0===/^\d+$/.test(t))return Sp(new Vd(s,new Xd(Number(t),"uint")))}return Reflect.get(e,t,s)},set:(e,t,s,i)=>"string"!=typeof t||void 0!==e[t]||!0!==/^[xyzwrgbastpq]{1,4}$/.test(t)&&"width"!==t&&"height"!==t&&"depth"!==t&&!0!==/^\d+$/.test(t)?Reflect.set(e,t,s,i):(i[t].assign(s),!0)},tp=new WeakMap,sp=new WeakMap,ip=function(e,t=null){for(const s in e)e[s]=Sp(e[s],t);return e},rp=function(e,t=null){const s=e.length;for(let i=0;iSp(null!==i?Object.assign(e,i):e);return null===t?(...t)=>r(new e(...Np(t))):null!==s?(s=Sp(s),(...i)=>r(new e(t,...Np(i),s))):(...s)=>r(new e(t,...Np(s)))},op=function(e,...t){return Sp(new e(...Np(t)))};class ap extends Ld{constructor(e,t){super(),this.shaderNode=e,this.inputNodes=t}getNodeType(e){return this.shaderNode.nodeType||this.getOutputNode(e).getNodeType(e)}call(e){const{shaderNode:t,inputNodes:s}=this,i=e.getNodeProperties(t);if(i.onceOutput)return i.onceOutput;let r=null;if(t.layout){let i=sp.get(e.constructor);void 0===i&&(i=new WeakMap,sp.set(e.constructor,i));let n=i.get(t);void 0===n&&(n=Sp(e.buildFunctionNode(t)),i.set(t,n)),null!==e.currentFunctionNode&&e.currentFunctionNode.includes.push(n),r=Sp(n.call(s))}else{const i=t.jsFunc,n=null!==s?i(s,e):i(e);r=Sp(n)}return t.once&&(i.onceOutput=r),r}getOutputNode(e){const t=e.getNodeProperties(this);return null===t.outputNode&&(t.outputNode=this.setupOutput(e)),t.outputNode}setup(e){return this.getOutputNode(e)}setupOutput(e){return e.addStack(),e.stack.outputNode=this.call(e),e.removeStack()}generate(e,t){return this.getOutputNode(e).build(e,t)}}class hp extends Ld{constructor(e,t){super(t),this.jsFunc=e,this.layout=null,this.global=!0,this.once=!1}setLayout(e){return this.layout=e,this}call(e=null){return Mp(e),Sp(new ap(this,e))}setup(){return this.call()}}const up=[!1,!0],lp=[0,1,2,3],cp=[-1,-2],dp=[.5,1.5,1/3,1e-6,1e6,Math.PI,2*Math.PI,1/Math.PI,2/Math.PI,1/(2*Math.PI),Math.PI/2],pp=new Map;for(const e of up)pp.set(e,new Xd(e));const mp=new Map;for(const e of lp)mp.set(e,new Xd(e,"uint"));const gp=new Map([...mp].map((e=>new Xd(e.value,"int"))));for(const e of cp)gp.set(e,new Xd(e,"int"));const fp=new Map([...gp].map((e=>new Xd(e.value))));for(const e of dp)fp.set(e,new Xd(e));for(const e of dp)fp.set(-e,new Xd(-e));const yp={bool:pp,uint:mp,ints:gp,float:fp},xp=new Map([...pp,...fp]),bp=(e,t)=>xp.has(e)?xp.get(e):!0===e.isNode?e:new Xd(e,t),vp=function(e,t=null){return(...s)=>{if((0===s.length||!["bool","float","int","uint"].includes(e)&&s.every((e=>"object"!=typeof e)))&&(s=[Nd(e,...s)]),1===s.length&&null!==t&&t.has(s[0]))return Sp(t.get(s[0]));if(1===s.length){const t=bp(s[0],e);return(e=>{try{return e.getNodeType()}catch(e){return}})(t)===e?Sp(t):Sp(new Dd(t,e))}const i=s.map((e=>bp(e)));return Sp(new Gd(i,e))}},Tp=e=>"object"==typeof e&&null!==e?e.value:e,_p=e=>null!=e?e.nodeType||e.convertTo||("string"==typeof e?e:null):null;function wp(e,t){return new Proxy(new hp(e,t),ep)}const Sp=(e,t=null)=>function(e,t=null){const s=Md(e);if("node"===s){let t=tp.get(e);return void 0===t&&(t=new Proxy(e,ep),tp.set(e,t),tp.set(t,t)),t}return null===t&&("float"===s||"boolean"===s)||s&&"shader"!==s&&"string"!==s?Sp(bp(e,t)):"shader"===s?Rp(e):e}(e,t),Mp=(e,t=null)=>new ip(e,t),Np=(e,t=null)=>new rp(e,t),Ap=(...e)=>new np(...e),Cp=(...e)=>new op(...e),Rp=(e,t)=>{const s=new wp(e,t),i=(...e)=>{let t;return Mp(e),t=e[0]&&e[0].isNode?[...e]:e[0],s.call(t)};return i.shaderNode=s,i.setLayout=e=>(s.setLayout(e),i),i.once=()=>(s.once=!0,i),i},Ep=(...e)=>(console.warn("TSL.ShaderNode: tslFn() has been renamed to Fn()."),Rp(...e));Jd("toGlobal",(e=>(e.global=!0,e)));const Bp=e=>{Yd=e},Ip=()=>Yd,Pp=(...e)=>Yd.If(...e);function Fp(e){return Yd&&Yd.add(e),e}Jd("append",Fp);const zp=new vp("color"),Up=new vp("float",yp.float),Op=new vp("int",yp.ints),Lp=new vp("uint",yp.uint),Vp=new vp("bool",yp.bool),Dp=new vp("vec2"),kp=new vp("ivec2"),Gp=new vp("uvec2"),Wp=new vp("bvec2"),jp=new vp("vec3"),Hp=new vp("ivec3"),qp=new vp("uvec3"),$p=new vp("bvec3"),Xp=new vp("vec4"),Yp=new vp("ivec4"),Zp=new vp("uvec4"),Jp=new vp("bvec4"),Kp=new vp("mat2"),Qp=new vp("mat3"),em=new vp("mat4"),tm=(e="")=>Sp(new Xd(e,"string")),sm=e=>Sp(new Xd(e,"ArrayBuffer"));Jd("toColor",zp),Jd("toFloat",Up),Jd("toInt",Op),Jd("toUint",Lp),Jd("toBool",Vp),Jd("toVec2",Dp),Jd("toIVec2",kp),Jd("toUVec2",Gp),Jd("toBVec2",Wp),Jd("toVec3",jp),Jd("toIVec3",Hp),Jd("toUVec3",qp),Jd("toBVec3",$p),Jd("toVec4",Xp),Jd("toIVec4",Yp),Jd("toUVec4",Zp),Jd("toBVec4",Jp),Jd("toMat2",Kp),Jd("toMat3",Qp),Jd("toMat4",em);const im=Ap(Vd),rm=(e,t)=>Sp(new Dd(Sp(e),t)),nm=(e,t)=>Sp(new jd(Sp(e),t));Jd("element",im),Jd("convert",rm);class om extends Ld{static get type(){return"UniformGroupNode"}constructor(e,t=!1,s=1){super("string"),this.name=e,this.version=0,this.shared=t,this.order=s,this.isUniformGroup=!0}set needsUpdate(e){!0===e&&this.version++}serialize(e){super.serialize(e),e.name=this.name,e.version=this.version,e.shared=this.shared}deserialize(e){super.deserialize(e),this.name=e.name,this.version=e.version,this.shared=e.shared}}const am=e=>new om(e),hm=(e,t=0)=>new om(e,!0,t),um=hm("frame"),lm=hm("render"),cm=am("object");class dm extends $d{static get type(){return"UniformNode"}constructor(e,t=null){super(e,t),this.isUniformNode=!0,this.name="",this.groupNode=cm}label(e){return this.name=e,this}setGroup(e){return this.groupNode=e,this}getGroup(){return this.groupNode}getUniformHash(e){return this.getHash(e)}onUpdate(e,t){const s=this.getSelf();return e=e.bind(s),super.onUpdate((t=>{const i=e(t,s);void 0!==i&&(this.value=i)}),t)}generate(e,t){const s=this.getNodeType(e),i=this.getUniformHash(e);let r=e.getNodeFromHash(i);void 0===r&&(e.setHashNode(this,i),r=this);const n=r.getInputType(e),o=e.getUniformFromNode(r,n,e.shaderStage,this.name||e.context.label),a=e.getPropertyName(o);return void 0!==e.context.label&&delete e.context.label,e.format(a,s,t)}}const pm=(e,t)=>{const s=_p(t||e),i=e&&!0===e.isNode?e.node&&e.node.value||e.value:e;return Sp(new dm(i,s))};class mm extends Ld{static get type(){return"PropertyNode"}constructor(e,t=null,s=!1){super(e),this.name=t,this.varying=s,this.isPropertyNode=!0}getHash(e){return this.name||super.getHash(e)}isGlobal(){return!0}generate(e){let t;return!0===this.varying?(t=e.getVaryingFromNode(this,this.name),t.needsInterpolation=!0):t=e.getVarFromNode(this,this.name),e.getPropertyName(t)}}const gm=(e,t)=>Sp(new mm(e,t)),fm=(e,t)=>Sp(new mm(e,t,!0)),ym=Cp(mm,"vec4","DiffuseColor"),xm=Cp(mm,"vec3","EmissiveColor"),bm=Cp(mm,"float","Roughness"),vm=Cp(mm,"float","Metalness"),Tm=Cp(mm,"float","Clearcoat"),_m=Cp(mm,"float","ClearcoatRoughness"),wm=Cp(mm,"vec3","Sheen"),Sm=Cp(mm,"float","SheenRoughness"),Mm=Cp(mm,"float","Iridescence"),Nm=Cp(mm,"float","IridescenceIOR"),Am=Cp(mm,"float","IridescenceThickness"),Cm=Cp(mm,"float","AlphaT"),Rm=Cp(mm,"float","Anisotropy"),Em=Cp(mm,"vec3","AnisotropyT"),Bm=Cp(mm,"vec3","AnisotropyB"),Im=Cp(mm,"color","SpecularColor"),Pm=Cp(mm,"float","SpecularF90"),Fm=Cp(mm,"float","Shininess"),zm=Cp(mm,"vec4","Output"),Um=Cp(mm,"float","dashSize"),Om=Cp(mm,"float","gapSize"),Lm=Cp(mm,"float","pointWidth"),Vm=Cp(mm,"float","IOR"),Dm=Cp(mm,"float","Transmission"),km=Cp(mm,"float","Thickness"),Gm=Cp(mm,"float","AttenuationDistance"),Wm=Cp(mm,"color","AttenuationColor"),jm=Cp(mm,"float","Dispersion");class Hm extends kd{static get type(){return"AssignNode"}constructor(e,t){super(),this.targetNode=e,this.sourceNode=t}hasDependencies(){return!1}getNodeType(e,t){return"void"!==t?this.targetNode.getNodeType(e):"void"}needsSplitAssign(e){const{targetNode:t}=this;if(!1===e.isAvailable("swizzleAssign")&&t.isSplitNode&&t.components.length>1){const s=e.getTypeLength(t.node.getNodeType(e));return Ud.join("").slice(0,s)!==t.components}return!1}generate(e,t){const{targetNode:s,sourceNode:i}=this,r=this.needsSplitAssign(e),n=s.getNodeType(e),o=s.context({assign:!0}).build(e),a=i.build(e,n),h=i.getNodeType(e),u=e.getDataFromNode(this);let l;if(!0===u.initialized)"void"!==t&&(l=o);else if(r){const i=e.getVarFromNode(this,null,n),r=e.getPropertyName(i);e.addLineFlowCode(`${r} = ${a}`,this);const h=s.node.context({assign:!0}).build(e);for(let t=0;t(t=t.length>1||t[0]&&!0===t[0].isNode?Np(t):Mp(t[0]),Sp(new $m(Sp(e),t)));Jd("call",Xm);class Ym extends kd{static get type(){return"OperatorNode"}constructor(e,t,s,...i){if(super(),i.length>0){let r=new Ym(e,t,s);for(let t=0;t>"===s||"<<"===s)return e.getIntegerType(n);if("!"===s||"=="===s||"&&"===s||"||"===s||"^^"===s)return"bool";if("<"===s||">"===s||"<="===s||">="===s){const s=t?e.getTypeLength(t):Math.max(e.getTypeLength(n),e.getTypeLength(o));return s>1?`bvec${s}`:"bool"}return"float"===n&&e.isMatrix(o)?o:e.isMatrix(n)&&e.isVector(o)?e.getVectorFromMatrix(n):e.isVector(n)&&e.isMatrix(o)?e.getVectorFromMatrix(o):e.getTypeLength(o)>e.getTypeLength(n)?o:n}generate(e,t){const s=this.op,i=this.aNode,r=this.bNode,n=this.getNodeType(e,t);let o=null,a=null;"void"!==n?(o=i.getNodeType(e),a=void 0!==r?r.getNodeType(e):null,"<"===s||">"===s||"<="===s||">="===s||"=="===s?e.isVector(o)?a=o:o!==a&&(o=a="float"):">>"===s||"<<"===s?(o=n,a=e.changeComponentType(a,"uint")):e.isMatrix(o)&&e.isVector(a)?a=e.getVectorFromMatrix(o):o=e.isVector(o)&&e.isMatrix(a)?e.getVectorFromMatrix(a):a=n):o=a=n;const h=i.build(e,o),u=void 0!==r?r.build(e,a):null,l=e.getTypeLength(t),c=e.getFunctionOperator(s);return"void"!==t?"<"===s&&l>1?e.useComparisonMethod?e.format(`${e.getMethod("lessThan",t)}( ${h}, ${u} )`,n,t):e.format(`( ${h} < ${u} )`,n,t):"<="===s&&l>1?e.useComparisonMethod?e.format(`${e.getMethod("lessThanEqual",t)}( ${h}, ${u} )`,n,t):e.format(`( ${h} <= ${u} )`,n,t):">"===s&&l>1?e.useComparisonMethod?e.format(`${e.getMethod("greaterThan",t)}( ${h}, ${u} )`,n,t):e.format(`( ${h} > ${u} )`,n,t):">="===s&&l>1?e.useComparisonMethod?e.format(`${e.getMethod("greaterThanEqual",t)}( ${h}, ${u} )`,n,t):e.format(`( ${h} >= ${u} )`,n,t):"!"===s||"~"===s?e.format(`(${s}${h})`,o,t):c?e.format(`${c}( ${h}, ${u} )`,n,t):e.format(`( ${h} ${s} ${u} )`,n,t):"void"!==o?c?e.format(`${c}( ${h}, ${u} )`,n,t):e.format(`${h} ${s} ${u}`,n,t):void 0}serialize(e){super.serialize(e),e.op=this.op}deserialize(e){super.deserialize(e),this.op=e.op}}const Zm=Ap(Ym,"+"),Jm=Ap(Ym,"-"),Km=Ap(Ym,"*"),Qm=Ap(Ym,"/"),eg=Ap(Ym,"%"),tg=Ap(Ym,"=="),sg=Ap(Ym,"!="),ig=Ap(Ym,"<"),rg=Ap(Ym,">"),ng=Ap(Ym,"<="),og=Ap(Ym,">="),ag=Ap(Ym,"&&"),hg=Ap(Ym,"||"),ug=Ap(Ym,"!"),lg=Ap(Ym,"^^"),cg=Ap(Ym,"&"),dg=Ap(Ym,"~"),pg=Ap(Ym,"|"),mg=Ap(Ym,"^"),gg=Ap(Ym,"<<"),fg=Ap(Ym,">>");Jd("add",Zm),Jd("sub",Jm),Jd("mul",Km),Jd("div",Qm),Jd("modInt",eg),Jd("equal",tg),Jd("notEqual",sg),Jd("lessThan",ig),Jd("greaterThan",rg),Jd("lessThanEqual",ng),Jd("greaterThanEqual",og),Jd("and",ag),Jd("or",hg),Jd("not",ug),Jd("xor",lg),Jd("bitAnd",cg),Jd("bitNot",dg),Jd("bitOr",pg),Jd("bitXor",mg),Jd("shiftLeft",gg),Jd("shiftRight",fg);const yg=(...e)=>(console.warn("TSL.OperatorNode: .remainder() has been renamed to .modInt()."),eg(...e));Jd("remainder",yg);class xg extends kd{static get type(){return"MathNode"}constructor(e,t,s=null,i=null){super(),this.method=e,this.aNode=t,this.bNode=s,this.cNode=i}getInputType(e){const t=this.aNode.getNodeType(e),s=this.bNode?this.bNode.getNodeType(e):null,i=this.cNode?this.cNode.getNodeType(e):null,r=e.isMatrix(t)?0:e.getTypeLength(t),n=e.isMatrix(s)?0:e.getTypeLength(s),o=e.isMatrix(i)?0:e.getTypeLength(i);return r>n&&r>o?t:n>o?s:o>r?i:t}getNodeType(e){const t=this.method;return t===xg.LENGTH||t===xg.DISTANCE||t===xg.DOT?"float":t===xg.CROSS?"vec3":t===xg.ALL?"bool":t===xg.EQUALS?e.changeComponentType(this.aNode.getNodeType(e),"bool"):t===xg.MOD?this.aNode.getNodeType(e):this.getInputType(e)}generate(e,t){const s=this.method,i=this.getNodeType(e),r=this.getInputType(e),n=this.aNode,o=this.bNode,a=this.cNode,h=!0===e.renderer.isWebGLRenderer;if(s===xg.TRANSFORM_DIRECTION){let s=n,i=o;e.isMatrix(s.getNodeType(e))?i=Xp(jp(i),0):s=Xp(jp(s),0);const r=Km(s,i).xyz;return Ug(r).build(e,t)}if(s===xg.NEGATE)return e.format("( - "+n.build(e,r)+" )",i,t);if(s===xg.ONE_MINUS)return Jm(1,n).build(e,t);if(s===xg.RECIPROCAL)return Qm(1,n).build(e,t);if(s===xg.DIFFERENCE)return jg(Jm(n,o)).build(e,t);{const u=[];return s===xg.CROSS||s===xg.MOD?u.push(n.build(e,i),o.build(e,i)):h&&s===xg.STEP?u.push(n.build(e,1===e.getTypeLength(n.getNodeType(e))?"float":r),o.build(e,r)):h&&(s===xg.MIN||s===xg.MAX)||s===xg.MOD?u.push(n.build(e,r),o.build(e,1===e.getTypeLength(o.getNodeType(e))?"float":r)):s===xg.REFRACT?u.push(n.build(e,r),o.build(e,r),a.build(e,"float")):s===xg.MIX?u.push(n.build(e,r),o.build(e,r),a.build(e,1===e.getTypeLength(a.getNodeType(e))?"float":r)):(u.push(n.build(e,r)),null!==o&&u.push(o.build(e,r)),null!==a&&u.push(a.build(e,r))),e.format(`${e.getMethod(s,i)}( ${u.join(", ")} )`,i,t)}}serialize(e){super.serialize(e),e.method=this.method}deserialize(e){super.deserialize(e),this.method=e.method}}xg.ALL="all",xg.ANY="any",xg.EQUALS="equals",xg.RADIANS="radians",xg.DEGREES="degrees",xg.EXP="exp",xg.EXP2="exp2",xg.LOG="log",xg.LOG2="log2",xg.SQRT="sqrt",xg.INVERSE_SQRT="inversesqrt",xg.FLOOR="floor",xg.CEIL="ceil",xg.NORMALIZE="normalize",xg.FRACT="fract",xg.SIN="sin",xg.COS="cos",xg.TAN="tan",xg.ASIN="asin",xg.ACOS="acos",xg.ATAN="atan",xg.ABS="abs",xg.SIGN="sign",xg.LENGTH="length",xg.NEGATE="negate",xg.ONE_MINUS="oneMinus",xg.DFDX="dFdx",xg.DFDY="dFdy",xg.ROUND="round",xg.RECIPROCAL="reciprocal",xg.TRUNC="trunc",xg.FWIDTH="fwidth",xg.BITCAST="bitcast",xg.TRANSPOSE="transpose",xg.ATAN2="atan2",xg.MIN="min",xg.MAX="max",xg.MOD="mod",xg.STEP="step",xg.REFLECT="reflect",xg.DISTANCE="distance",xg.DIFFERENCE="difference",xg.DOT="dot",xg.CROSS="cross",xg.POW="pow",xg.TRANSFORM_DIRECTION="transformDirection",xg.MIX="mix",xg.CLAMP="clamp",xg.REFRACT="refract",xg.SMOOTHSTEP="smoothstep",xg.FACEFORWARD="faceforward";const bg=Up(1e-6),vg=Up(1e6),Tg=Up(Math.PI),_g=Up(2*Math.PI),wg=Ap(xg,xg.ALL),Sg=Ap(xg,xg.ANY),Mg=Ap(xg,xg.EQUALS),Ng=Ap(xg,xg.RADIANS),Ag=Ap(xg,xg.DEGREES),Cg=Ap(xg,xg.EXP),Rg=Ap(xg,xg.EXP2),Eg=Ap(xg,xg.LOG),Bg=Ap(xg,xg.LOG2),Ig=Ap(xg,xg.SQRT),Pg=Ap(xg,xg.INVERSE_SQRT),Fg=Ap(xg,xg.FLOOR),zg=Ap(xg,xg.CEIL),Ug=Ap(xg,xg.NORMALIZE),Og=Ap(xg,xg.FRACT),Lg=Ap(xg,xg.SIN),Vg=Ap(xg,xg.COS),Dg=Ap(xg,xg.TAN),kg=Ap(xg,xg.ASIN),Gg=Ap(xg,xg.ACOS),Wg=Ap(xg,xg.ATAN),jg=Ap(xg,xg.ABS),Hg=Ap(xg,xg.SIGN),qg=Ap(xg,xg.LENGTH),$g=Ap(xg,xg.NEGATE),Xg=Ap(xg,xg.ONE_MINUS),Yg=Ap(xg,xg.DFDX),Zg=Ap(xg,xg.DFDY),Jg=Ap(xg,xg.ROUND),Kg=Ap(xg,xg.RECIPROCAL),Qg=Ap(xg,xg.TRUNC),ef=Ap(xg,xg.FWIDTH),tf=Ap(xg,xg.BITCAST),sf=Ap(xg,xg.TRANSPOSE),rf=Ap(xg,xg.ATAN2),nf=Ap(xg,xg.MIN),of=Ap(xg,xg.MAX),af=Ap(xg,xg.MOD),hf=Ap(xg,xg.STEP),uf=Ap(xg,xg.REFLECT),lf=Ap(xg,xg.DISTANCE),cf=Ap(xg,xg.DIFFERENCE),df=Ap(xg,xg.DOT),pf=Ap(xg,xg.CROSS),mf=Ap(xg,xg.POW),gf=Ap(xg,xg.POW,2),ff=Ap(xg,xg.POW,3),yf=Ap(xg,xg.POW,4),xf=Ap(xg,xg.TRANSFORM_DIRECTION),bf=e=>Km(Hg(e),mf(jg(e),1/3)),vf=e=>df(e,e),Tf=Ap(xg,xg.MIX),_f=(e,t=0,s=1)=>Sp(new xg(xg.CLAMP,Sp(e),Sp(t),Sp(s))),wf=e=>_f(e),Sf=Ap(xg,xg.REFRACT),Mf=Ap(xg,xg.SMOOTHSTEP),Nf=Ap(xg,xg.FACEFORWARD),Af=Rp((([e])=>{const t=df(e.xy,Dp(12.9898,78.233)),s=af(t,Tg);return Og(Lg(s).mul(43758.5453))})),Cf=(e,t,s)=>Tf(t,s,e),Rf=(e,t,s)=>Mf(t,s,e);Jd("all",wg),Jd("any",Sg),Jd("equals",Mg),Jd("radians",Ng),Jd("degrees",Ag),Jd("exp",Cg),Jd("exp2",Rg),Jd("log",Eg),Jd("log2",Bg),Jd("sqrt",Ig),Jd("inverseSqrt",Pg),Jd("floor",Fg),Jd("ceil",zg),Jd("normalize",Ug),Jd("fract",Og),Jd("sin",Lg),Jd("cos",Vg),Jd("tan",Dg),Jd("asin",kg),Jd("acos",Gg),Jd("atan",Wg),Jd("abs",jg),Jd("sign",Hg),Jd("length",qg),Jd("lengthSq",vf),Jd("negate",$g),Jd("oneMinus",Xg),Jd("dFdx",Yg),Jd("dFdy",Zg),Jd("round",Jg),Jd("reciprocal",Kg),Jd("trunc",Qg),Jd("fwidth",ef),Jd("atan2",rf),Jd("min",nf),Jd("max",of),Jd("mod",af),Jd("step",hf),Jd("reflect",uf),Jd("distance",lf),Jd("dot",df),Jd("cross",pf),Jd("pow",mf),Jd("pow2",gf),Jd("pow3",ff),Jd("pow4",yf),Jd("transformDirection",xf),Jd("mix",Cf),Jd("clamp",_f),Jd("refract",Sf),Jd("smoothstep",Rf),Jd("faceForward",Nf),Jd("difference",cf),Jd("saturate",wf),Jd("cbrt",bf),Jd("transpose",sf),Jd("rand",Af);class Ef extends Ld{static get type(){return"ConditionalNode"}constructor(e,t,s=null){super(),this.condNode=e,this.ifNode=t,this.elseNode=s}getNodeType(e){const t=this.ifNode.getNodeType(e);if(null!==this.elseNode){const s=this.elseNode.getNodeType(e);if(e.getTypeLength(s)>e.getTypeLength(t))return s}return t}setup(e){const t=this.condNode.cache(),s=this.ifNode.cache(),i=this.elseNode?this.elseNode.cache():null,r=e.context.nodeBlock;e.getDataFromNode(s).parentNodeBlock=r,null!==i&&(e.getDataFromNode(i).parentNodeBlock=r);const n=e.getNodeProperties(this);n.condNode=t,n.ifNode=s.context({nodeBlock:s}),n.elseNode=i?i.context({nodeBlock:i}):null}generate(e,t){const s=this.getNodeType(e),i=e.getDataFromNode(this);if(void 0!==i.nodeProperty)return i.nodeProperty;const{condNode:r,ifNode:n,elseNode:o}=e.getNodeProperties(this),a="void"!==t,h=a?gm(s).build(e):"";i.nodeProperty=h;const u=r.build(e,"bool");e.addFlowCode(`\n${e.tab}if ( ${u} ) {\n\n`).addFlowTab();let l=n.build(e,s);if(l&&(l=a?h+" = "+l+";":"return "+l+";"),e.removeFlowTab().addFlowCode(e.tab+"\t"+l+"\n\n"+e.tab+"}"),null!==o){e.addFlowCode(" else {\n\n").addFlowTab();let t=o.build(e,s);t&&(t=a?h+" = "+t+";":"return "+t+";"),e.removeFlowTab().addFlowCode(e.tab+"\t"+t+"\n\n"+e.tab+"}\n\n")}else e.addFlowCode("\n\n");return e.format(h,s,t)}}const Bf=Ap(Ef);Jd("select",Bf);const If=(...e)=>(console.warn("TSL.ConditionalNode: cond() has been renamed to select()."),Bf(...e));Jd("cond",If);class Pf extends Ld{static get type(){return"ContextNode"}constructor(e,t={}){super(),this.isContextNode=!0,this.node=e,this.value=t}getScope(){return this.node.getScope()}getNodeType(e){return this.node.getNodeType(e)}analyze(e){this.node.build(e)}setup(e){const t=e.getContext();e.setContext({...e.context,...this.value});const s=this.node.build(e);return e.setContext(t),s}generate(e,t){const s=e.getContext();e.setContext({...e.context,...this.value});const i=this.node.build(e,t);return e.setContext(s),i}}const Ff=Ap(Pf),zf=(e,t)=>Ff(e,{label:t});Jd("context",Ff),Jd("label",zf);class Uf extends Ld{static get type(){return"VarNode"}constructor(e,t=null){super(),this.node=e,this.name=t,this.global=!0,this.isVarNode=!0}getHash(e){return this.name||super.getHash(e)}getNodeType(e){return this.node.getNodeType(e)}generate(e){const{node:t,name:s}=this,i=e.getVarFromNode(this,s,e.getVectorType(this.getNodeType(e))),r=e.getPropertyName(i),n=t.build(e,i.type);return e.addLineFlowCode(`${r} = ${n}`,this),r}}const Of=Ap(Uf);Jd("temp",Of),Jd("toVar",((...e)=>Of(...e).append()));class Lf extends Ld{static get type(){return"VaryingNode"}constructor(e,t=null){super(),this.node=e,this.name=t,this.isVaryingNode=!0}isGlobal(){return!0}getHash(e){return this.name||super.getHash(e)}getNodeType(e){return this.node.getNodeType(e)}setupVarying(e){const t=e.getNodeProperties(this);let s=t.varying;if(void 0===s){const i=this.name,r=this.getNodeType(e);t.varying=s=e.getVaryingFromNode(this,i,r),t.node=this.node}return s.needsInterpolation||(s.needsInterpolation="fragment"===e.shaderStage),s}setup(e){this.setupVarying(e)}analyze(e){return this.setupVarying(e),this.node.analyze(e)}generate(e){const t=e.getNodeProperties(this),s=this.setupVarying(e);if(void 0===t.propertyName){const i=this.getNodeType(e),r=e.getPropertyName(s,Ed.VERTEX);e.flowNodeFromShaderStage(Ed.VERTEX,this.node,i,r),t.propertyName=r}return e.getPropertyName(s)}}const Vf=Ap(Lf);Jd("varying",Vf);const Df="WorkingColorSpace",kf="OutputColorSpace";function Gf(e){let t=null;return e===Jt?t="Linear":e===Zt&&(t="sRGB"),t}function Wf(e,t){return Gf(e)+"To"+Gf(t)}class jf extends kd{static get type(){return"ColorSpaceNode"}constructor(e,t,s){super("vec4"),this.colorNode=e,this.source=t,this.target=s}getColorSpace(e,t){return t===Df?ci.workingColorSpace:t===kf?e.context.outputColorSpace||e.renderer.outputColorSpace:t}setup(e){const{renderer:t}=e,{colorNode:s}=this,i=this.getColorSpace(e,this.source),r=this.getColorSpace(e,this.target);if(i===r)return s;const n=Wf(i,r);let o=null;const a=t.nodes.library.getColorSpaceFunction(n);return null!==a?o=Xp(a(s.rgb),s.a):(console.error("ColorSpaceNode: Unsupported Color Space configuration.",n),o=s),o}}const Hf=e=>Sp(new jf(Sp(e),Df,kf)),qf=e=>Sp(new jf(Sp(e),kf,Df)),$f=(e,t)=>Sp(new jf(Sp(e),Df,t)),Xf=(e,t)=>Sp(new jf(Sp(e),t,Df));Jd("toOutputColorSpace",Hf),Jd("toWorkingColorSpace",qf),Jd("workingToColorSpace",$f),Jd("colorSpaceToWorking",Xf);let Yf=class extends Vd{static get type(){return"ReferenceElementNode"}constructor(e,t){super(e,t),this.referenceNode=e,this.isReferenceElementNode=!0}getNodeType(){return this.referenceNode.uniformType}generate(e){const t=super.generate(e),s=this.referenceNode.getNodeType(),i=this.getNodeType();return e.format(t,s,i)}};class Zf extends Ld{static get type(){return"ReferenceBaseNode"}constructor(e,t,s=null,i=null){super(),this.property=e,this.uniformType=t,this.object=s,this.count=i,this.properties=e.split("."),this.reference=s,this.node=null,this.group=null,this.updateType=Bd.OBJECT}setGroup(e){return this.group=e,this}element(e){return Sp(new Yf(this,Sp(e)))}setNodeType(e){const t=pm(null,e).getSelf();null!==this.group&&t.setGroup(this.group),this.node=t}getNodeType(e){return null===this.node&&(this.updateReference(e),this.updateValue()),this.node.getNodeType(e)}getValueFromReference(e=this.reference){const{properties:t}=this;let s=e[t[0]];for(let e=1;eSp(new Jf(e,t,s));class Qf extends kd{static get type(){return"ToneMappingNode"}constructor(e,t=ty,s=null){super("vec3"),this.toneMapping=e,this.exposureNode=t,this.colorNode=s}getCacheKey(){return _d(super.getCacheKey(),this.toneMapping)}setup(e){const t=this.colorNode||e.context.color,s=this.toneMapping;if(0===s)return t;let i=null;const r=e.renderer.nodes.library.getToneMappingFunction(s);return null!==r?i=Xp(r(t.rgb,this.exposureNode),t.a):(console.error("ToneMappingNode: Unsupported Tone Mapping configuration.",s),i=t),i}}const ey=(e,t,s)=>Sp(new Qf(e,Sp(t),Sp(s))),ty=Kf("toneMappingExposure","float");Jd("toneMapping",((e,t,s)=>ey(t,s,e)));class sy extends $d{static get type(){return"BufferAttributeNode"}constructor(e,t=null,s=0,i=0){super(e,t),this.isBufferNode=!0,this.bufferType=t,this.bufferStride=s,this.bufferOffset=i,this.usage=Cs,this.instanced=!1,this.attribute=null,this.global=!0,e&&!0===e.isBufferAttribute&&(this.attribute=e,this.usage=e.usage,this.instanced=e.isInstancedBufferAttribute)}getHash(e){if(0===this.bufferStride&&0===this.bufferOffset){let t=e.globalCache.getData(this.value);return void 0===t&&(t={node:this},e.globalCache.setData(this.value,t)),t.node.uuid}return this.uuid}getNodeType(e){return null===this.bufferType&&(this.bufferType=e.getTypeFromAttribute(this.attribute)),this.bufferType}setup(e){if(null!==this.attribute)return;const t=this.getNodeType(e),s=this.value,i=e.getTypeLength(t),r=this.bufferStride||i,n=this.bufferOffset,o=!0===s.isInterleavedBuffer?s:new so(s,r),a=new ro(o,i,n);o.setUsage(this.usage),this.attribute=a,this.attribute.isInstancedBufferAttribute=this.instanced}generate(e){const t=this.getNodeType(e),s=e.getBufferAttributeFromNode(this,t),i=e.getPropertyName(s);let r=null;if("vertex"===e.shaderStage||"compute"===e.shaderStage)this.name=i,r=i;else{r=Vf(this).build(e,t)}return r}getInputType(){return"bufferAttribute"}setUsage(e){return this.usage=e,this.attribute&&!0===this.attribute.isBufferAttribute&&(this.attribute.usage=e),this}setInstanced(e){return this.instanced=e,this}}const iy=(e,t,s,i)=>Sp(new sy(e,t,s,i)),ry=(e,t,s,i)=>iy(e,t,s,i).setUsage(Rs),ny=(e,t,s,i)=>iy(e,t,s,i).setInstanced(!0),oy=(e,t,s,i)=>ry(e,t,s,i).setInstanced(!0);Jd("toAttribute",(e=>iy(e.value)));class ay extends Ld{static get type(){return"ComputeNode"}constructor(e,t,s=[64]){super("void"),this.isComputeNode=!0,this.computeNode=e,this.count=t,this.workgroupSize=s,this.dispatchCount=0,this.version=1,this.updateBeforeType=Bd.OBJECT,this.updateDispatchCount()}dispose(){this.dispatchEvent({type:"dispose"})}set needsUpdate(e){!0===e&&this.version++}updateDispatchCount(){const{count:e,workgroupSize:t}=this;let s=t[0];for(let e=1;eSp(new ay(Sp(e),t,s));Jd("compute",hy);class uy extends Ld{static get type(){return"CacheNode"}constructor(e,t=!0){super(),this.node=e,this.parent=t,this.isCacheNode=!0}getNodeType(e){return this.node.getNodeType(e)}build(e,...t){const s=e.getCache(),i=e.getCacheFromNode(this,this.parent);e.setCache(i);const r=this.node.build(e,...t);return e.setCache(s),r}}const ly=(e,...t)=>Sp(new uy(Sp(e),...t));Jd("cache",ly);class cy extends Ld{static get type(){return"BypassNode"}constructor(e,t){super(),this.isBypassNode=!0,this.outputNode=e,this.callNode=t}getNodeType(e){return this.outputNode.getNodeType(e)}generate(e){const t=this.callNode.build(e,"void");return""!==t&&e.addLineFlowCode(t,this),this.outputNode.build(e)}}const dy=Ap(cy);Jd("bypass",dy);class py extends Ld{static get type(){return"RemapNode"}constructor(e,t,s,i=Up(0),r=Up(1)){super(),this.node=e,this.inLowNode=t,this.inHighNode=s,this.outLowNode=i,this.outHighNode=r,this.doClamp=!0}setup(){const{node:e,inLowNode:t,inHighNode:s,outLowNode:i,outHighNode:r,doClamp:n}=this;let o=e.sub(t).div(s.sub(t));return!0===n&&(o=o.clamp()),o.mul(r.sub(i)).add(i)}}const my=Ap(py,null,null,{doClamp:!1}),gy=Ap(py);Jd("remap",my),Jd("remapClamp",gy);class fy extends Ld{static get type(){return"ExpressionNode"}constructor(e="",t="void"){super(t),this.snippet=e}generate(e,t){const s=this.getNodeType(e),i=this.snippet;if("void"!==s)return e.format(`( ${i} )`,s,t);e.addLineFlowCode(i,this)}}const yy=Ap(fy),xy=e=>(e?Bf(e,yy("discard")):yy("discard")).append(),by=()=>yy("return").append();Jd("discard",xy);class vy extends kd{static get type(){return"RenderOutputNode"}constructor(e,t,s){super("vec4"),this.colorNode=e,this.toneMapping=t,this.outputColorSpace=s,this.isRenderOutput=!0}setup({context:e}){let t=this.colorNode||e.color;const s=(null!==this.toneMapping?this.toneMapping:e.toneMapping)||0,i=(null!==this.outputColorSpace?this.outputColorSpace:e.outputColorSpace)||Yt;return 0!==s&&(t=t.toneMapping(s)),i!==Yt&&i!==ci.workingColorSpace&&(t=t.workingToColorSpace(i)),t}}const Ty=(e,t=null,s=null)=>Sp(new vy(Sp(e),t,s));function _y(e){console.warn("THREE.TSLBase: AddNodeElement has been removed in favor of tree-shaking. Trying add",e)}Jd("renderOutput",Ty);class wy extends Ld{static get type(){return"AttributeNode"}constructor(e,t=null){super(t),this.global=!0,this._attributeName=e}getHash(e){return this.getAttributeName(e)}getNodeType(e){let t=this.nodeType;if(null===t){const s=this.getAttributeName(e);if(e.hasGeometryAttribute(s)){const i=e.geometry.getAttribute(s);t=e.getTypeFromAttribute(i)}else t="float"}return t}setAttributeName(e){return this._attributeName=e,this}getAttributeName(){return this._attributeName}generate(e){const t=this.getAttributeName(e),s=this.getNodeType(e);if(!0===e.hasGeometryAttribute(t)){const i=e.geometry.getAttribute(t),r=e.getTypeFromAttribute(i),n=e.getAttribute(t,r);if("vertex"===e.shaderStage)return e.format(n.name,r,s);return Vf(this).build(e,s)}return console.warn(`AttributeNode: Vertex attribute "${t}" not found on geometry.`),e.generateConst(s)}serialize(e){super.serialize(e),e.global=this.global,e._attributeName=this._attributeName}deserialize(e){super.deserialize(e),this.global=e.global,this._attributeName=e._attributeName}}const Sy=(e,t)=>Sp(new wy(e,t)),My=e=>Sy("uv"+(e>0?e:""),"vec2");class Ny extends Ld{static get type(){return"TextureSizeNode"}constructor(e,t=null){super("uvec2"),this.isTextureSizeNode=!0,this.textureNode=e,this.levelNode=t}generate(e,t){const s=this.textureNode.build(e,"property"),i=null===this.levelNode?"0":this.levelNode.build(e,"int");return e.format(`${e.getMethod("textureDimensions")}( ${s}, ${i} )`,this.getNodeType(e),t)}}const Ay=Ap(Ny);class Cy extends dm{static get type(){return"MaxMipLevelNode"}constructor(e){super(0),this._textureNode=e,this.updateType=Bd.FRAME}get textureNode(){return this._textureNode}get texture(){return this._textureNode.value}update(){const e=this.texture,t=e.images,s=t&&t.length>0?t[0]&&t[0].image||t[0]:e.image;if(s&&void 0!==s.width){const{width:e,height:t}=s;this.value=Math.log2(Math.max(e,t))}}}const Ry=Ap(Cy);class Ey extends dm{static get type(){return"TextureNode"}constructor(e,t=null,s=null,i=null){super(e),this.isTextureNode=!0,this.uvNode=t,this.levelNode=s,this.biasNode=i,this.compareNode=null,this.depthNode=null,this.gradNode=null,this.sampler=!0,this.updateMatrix=!1,this.updateType=Bd.NONE,this.referenceNode=null,this._value=e,this._matrixUniform=null,this.setUpdateMatrix(null===t)}set value(e){this.referenceNode?this.referenceNode.value=e:this._value=e}get value(){return this.referenceNode?this.referenceNode.value:this._value}getUniformHash(){return this.value.uuid}getNodeType(){return!0===this.value.isDepthTexture?"float":this.value.type===Be?"uvec4":this.value.type===Ee?"ivec4":"vec4"}getInputType(){return"texture"}getDefaultUV(){return My(this.value.channel)}updateReference(){return this.value}getTransformedUV(e){return null===this._matrixUniform&&(this._matrixUniform=pm(this.value.matrix)),this._matrixUniform.mul(jp(e,1)).xy}setUpdateMatrix(e){return this.updateMatrix=e,this.updateType=e?Bd.FRAME:Bd.NONE,this}setupUV(e,t){const s=this.value;return!e.isFlipY()||!0!==s.isRenderTargetTexture&&!0!==s.isFramebufferTexture&&!0!==s.isDepthTexture||(t=this.sampler?t.flipY():t.setY(Op(Ay(this,this.levelNode).y).sub(t.y).sub(1))),t}setup(e){const t=e.getNodeProperties(this);t.referenceNode=this.referenceNode;let s=this.uvNode;null!==s&&!0!==e.context.forceUVContext||!e.context.getUV||(s=e.context.getUV(this)),s||(s=this.getDefaultUV()),!0===this.updateMatrix&&(s=this.getTransformedUV(s)),s=this.setupUV(e,s);let i=this.levelNode;null===i&&e.context.getTextureLevel&&(i=e.context.getTextureLevel(this)),t.uvNode=s,t.levelNode=i,t.biasNode=this.biasNode,t.compareNode=this.compareNode,t.gradNode=this.gradNode,t.depthNode=this.depthNode}generateUV(e,t){return t.build(e,!0===this.sampler?"vec2":"ivec2")}generateSnippet(e,t,s,i,r,n,o,a){const h=this.value;let u;return u=i?e.generateTextureLevel(h,t,s,i,n):r?e.generateTextureBias(h,t,s,r,n):a?e.generateTextureGrad(h,t,s,a,n):o?e.generateTextureCompare(h,t,s,o,n):!1===this.sampler?e.generateTextureLoad(h,t,s,n):e.generateTexture(h,t,s,n),u}generate(e,t){const s=e.getNodeProperties(this),i=this.value;if(!i||!0!==i.isTexture)throw new Error("TextureNode: Need a three.js texture.");const r=super.generate(e,"property");if("sampler"===t)return r+"_sampler";if(e.isReference(t))return r;{const n=e.getDataFromNode(this);let o=n.propertyName;if(void 0===o){const{uvNode:t,levelNode:i,biasNode:a,compareNode:h,depthNode:u,gradNode:l}=s,c=this.generateUV(e,t),d=i?i.build(e,"float"):null,p=a?a.build(e,"float"):null,m=u?u.build(e,"int"):null,g=h?h.build(e,"float"):null,f=l?[l[0].build(e,"vec2"),l[1].build(e,"vec2")]:null,y=e.getVarFromNode(this);o=e.getPropertyName(y);const x=this.generateSnippet(e,r,c,d,p,m,g,f);e.addLineFlowCode(`${o} = ${x}`,this),n.snippet=x,n.propertyName=o}let a=o;const h=this.getNodeType(e);return e.needsToWorkingColorSpace(i)&&(a=Xf(yy(a,h),i.colorSpace).setup(e).build(e,h)),e.format(a,h,t)}}setSampler(e){return this.sampler=e,this}getSampler(){return this.sampler}uv(e){const t=this.clone();return t.uvNode=Sp(e),t.referenceNode=this.getSelf(),Sp(t)}blur(e){const t=this.clone();return t.biasNode=Sp(e).mul(Ry(t)),t.referenceNode=this.getSelf(),Sp(t)}level(e){const t=this.clone();return t.levelNode=Sp(e),t.referenceNode=this.getSelf(),Sp(t)}size(e){return Ay(this,e)}bias(e){const t=this.clone();return t.biasNode=Sp(e),t.referenceNode=this.getSelf(),Sp(t)}compare(e){const t=this.clone();return t.compareNode=Sp(e),t.referenceNode=this.getSelf(),Sp(t)}grad(e,t){const s=this.clone();return s.gradNode=[Sp(e),Sp(t)],s.referenceNode=this.getSelf(),Sp(s)}depth(e){const t=this.clone();return t.depthNode=Sp(e),t.referenceNode=this.getSelf(),Sp(t)}serialize(e){super.serialize(e),e.value=this.value.toJSON(e.meta).uuid,e.sampler=this.sampler,e.updateMatrix=this.updateMatrix,e.updateType=this.updateType}deserialize(e){super.deserialize(e),this.value=e.meta.textures[e.value],this.sampler=e.sampler,this.updateMatrix=e.updateMatrix,this.updateType=e.updateType}update(){const e=this.value,t=this._matrixUniform;null!==t&&(t.value=e.matrix),!0===e.matrixAutoUpdate&&e.updateMatrix()}clone(){const e=new this.constructor(this.value,this.uvNode,this.levelNode,this.biasNode);return e.sampler=this.sampler,e}}const By=Ap(Ey),Iy=(...e)=>By(...e).setSampler(!1),Py=e=>(!0===e.isNode?e:By(e)).convert("sampler"),Fy=pm("float").label("cameraNear").setGroup(lm).onRenderUpdate((({camera:e})=>e.near)),zy=pm("float").label("cameraFar").setGroup(lm).onRenderUpdate((({camera:e})=>e.far)),Uy=pm("float").label("cameraLogDepth").setGroup(lm).onRenderUpdate((({camera:e})=>2/(Math.log(e.far+1)/Math.LN2))),Oy=pm("mat4").label("cameraProjectionMatrix").setGroup(lm).onRenderUpdate((({camera:e})=>e.projectionMatrix)),Ly=pm("mat4").label("cameraProjectionMatrixInverse").setGroup(lm).onRenderUpdate((({camera:e})=>e.projectionMatrixInverse)),Vy=pm("mat4").label("cameraViewMatrix").setGroup(lm).onRenderUpdate((({camera:e})=>e.matrixWorldInverse)),Dy=pm("mat4").label("cameraWorldMatrix").setGroup(lm).onRenderUpdate((({camera:e})=>e.matrixWorld)),ky=pm("mat3").label("cameraNormalMatrix").setGroup(lm).onRenderUpdate((({camera:e})=>e.normalMatrix)),Gy=pm(new Ri).label("cameraPosition").setGroup(lm).onRenderUpdate((({camera:e},t)=>t.value.setFromMatrixPosition(e.matrixWorld)));class Wy extends Ld{static get type(){return"Object3DNode"}constructor(e,t=null){super(),this.scope=e,this.object3d=t,this.updateType=Bd.OBJECT,this._uniformNode=new dm(null)}getNodeType(){const e=this.scope;return e===Wy.WORLD_MATRIX?"mat4":e===Wy.POSITION||e===Wy.VIEW_POSITION||e===Wy.DIRECTION||e===Wy.SCALE?"vec3":void 0}update(e){const t=this.object3d,s=this._uniformNode,i=this.scope;if(i===Wy.WORLD_MATRIX)s.value=t.matrixWorld;else if(i===Wy.POSITION)s.value=s.value||new Ri,s.value.setFromMatrixPosition(t.matrixWorld);else if(i===Wy.SCALE)s.value=s.value||new Ri,s.value.setFromMatrixScale(t.matrixWorld);else if(i===Wy.DIRECTION)s.value=s.value||new Ri,t.getWorldDirection(s.value);else if(i===Wy.VIEW_POSITION){const i=e.camera;s.value=s.value||new Ri,s.value.setFromMatrixPosition(t.matrixWorld),s.value.applyMatrix4(i.matrixWorldInverse)}}generate(e){const t=this.scope;return t===Wy.WORLD_MATRIX?this._uniformNode.nodeType="mat4":t!==Wy.POSITION&&t!==Wy.VIEW_POSITION&&t!==Wy.DIRECTION&&t!==Wy.SCALE||(this._uniformNode.nodeType="vec3"),this._uniformNode.build(e)}serialize(e){super.serialize(e),e.scope=this.scope}deserialize(e){super.deserialize(e),this.scope=e.scope}}Wy.WORLD_MATRIX="worldMatrix",Wy.POSITION="position",Wy.SCALE="scale",Wy.VIEW_POSITION="viewPosition",Wy.DIRECTION="direction";const jy=Ap(Wy,Wy.DIRECTION),Hy=Ap(Wy,Wy.WORLD_MATRIX),qy=Ap(Wy,Wy.POSITION),$y=Ap(Wy,Wy.SCALE),Xy=Ap(Wy,Wy.VIEW_POSITION);class Yy extends Wy{static get type(){return"ModelNode"}constructor(e){super(e)}update(e){this.object3d=e.object,super.update(e)}}const Zy=Cp(Yy,Yy.DIRECTION),Jy=Cp(Yy,Yy.WORLD_MATRIX),Ky=Cp(Yy,Yy.POSITION),Qy=Cp(Yy,Yy.SCALE),ex=Cp(Yy,Yy.VIEW_POSITION),tx=pm(new ei).onObjectUpdate((({object:e},t)=>t.value.getNormalMatrix(e.matrixWorld))),sx=pm(new nr).onObjectUpdate((({object:e},t)=>t.value.copy(e.matrixWorld).invert())),ix=Vy.mul(Jy).toVar("modelViewMatrix"),rx=Rp((e=>(e.context.isHighPrecisionModelViewMatrix=!0,pm("mat4").onObjectUpdate((({object:e,camera:t})=>e.modelViewMatrix.multiplyMatrices(t.matrixWorldInverse,e.matrixWorld)))))).once()().toVar("highPrecisionModelViewMatrix"),nx=Rp((e=>{const t=e.context.isHighPrecisionModelViewMatrix;return pm("mat3").onObjectUpdate((({object:e,camera:s})=>(!0!==t&&e.modelViewMatrix.multiplyMatrices(s.matrixWorldInverse,e.matrixWorld),e.normalMatrix.getNormalMatrix(e.modelViewMatrix))))})).once()().toVar("highPrecisionModelNormalMatrix"),ox=Sy("position","vec3"),ax=ox.varying("positionLocal"),hx=ox.varying("positionPrevious"),ux=Jy.mul(ax).xyz.varying("v_positionWorld"),lx=ax.transformDirection(Jy).varying("v_positionWorldDirection").normalize().toVar("positionWorldDirection"),cx=ix.mul(ax).xyz.varying("v_positionView"),dx=cx.negate().varying("v_positionViewDirection").normalize().toVar("positionViewDirection");class px extends Ld{static get type(){return"FrontFacingNode"}constructor(){super("bool"),this.isFrontFacingNode=!0}generate(e){const{renderer:t,material:s}=e;return t.coordinateSystem===Vs&&s.side===d?"false":e.getFrontFacing()}}const mx=Cp(px),gx=Up(mx).mul(2).sub(1),fx=Sy("normal","vec3"),yx=Rp((e=>!1===e.geometry.hasAttribute("normal")?(console.warn('TSL.NormalNode: Vertex attribute "normal" not found on geometry.'),jp(0,1,0)):fx),"vec3").once()().toVar("normalLocal"),xx=cx.dFdx().cross(cx.dFdy()).normalize().toVar("normalFlat"),bx=Rp((e=>{let t;return t=!0===e.material.flatShading?xx:Vf(Mx(yx),"v_normalView").normalize(),t}),"vec3").once()().toVar("normalView"),vx=Vf(bx.transformDirection(Vy),"v_normalWorld").normalize().toVar("normalWorld"),Tx=Rp((e=>e.context.setupNormal()),"vec3").once()().mul(gx).toVar("transformedNormalView"),_x=Tx.transformDirection(Vy).toVar("transformedNormalWorld"),wx=Rp((e=>e.context.setupClearcoatNormal()),"vec3").once()().mul(gx).toVar("transformedClearcoatNormalView"),Sx=Rp((([e,t=Jy])=>{const s=Qp(t),i=e.div(jp(s[0].dot(s[0]),s[1].dot(s[1]),s[2].dot(s[2])));return s.mul(i).xyz})),Mx=Rp((([e],t)=>{const s=t.renderer.nodes.modelNormalViewMatrix;if(null!==s)return s.transformDirection(e);const i=tx.mul(e);return Vy.transformDirection(i)})),Nx=pm(0).onReference((({material:e})=>e)).onRenderUpdate((({material:e})=>e.refractionRatio)),Ax=dx.negate().reflect(Tx),Cx=dx.negate().refract(Tx,Nx),Rx=Ax.transformDirection(Vy).toVar("reflectVector"),Ex=Cx.transformDirection(Vy).toVar("reflectVector");class Bx extends Ey{static get type(){return"CubeTextureNode"}constructor(e,t=null,s=null,i=null){super(e,t,s,i),this.isCubeTextureNode=!0}getInputType(){return"cubeTexture"}getDefaultUV(){const e=this.value;return e.mapping===he?Rx:e.mapping===ue?Ex:(console.error('THREE.CubeTextureNode: Mapping "%s" not supported.',e.mapping),jp(0,0,0))}setUpdateMatrix(){}setupUV(e,t){const s=this.value;return e.renderer.coordinateSystem!==Ds&&s.isRenderTargetTexture?t:jp(t.x.negate(),t.yz)}generateUV(e,t){return t.build(e,"vec3")}}const Ix=Ap(Bx);class Px extends dm{static get type(){return"BufferNode"}constructor(e,t,s=0){super(e,t),this.isBufferNode=!0,this.bufferType=t,this.bufferCount=s}getElementType(e){return this.getNodeType(e)}getInputType(){return"buffer"}}const Fx=(e,t,s)=>Sp(new Px(e,t,s));class zx extends Vd{static get type(){return"UniformArrayElementNode"}constructor(e,t){super(e,t),this.isArrayBufferElementNode=!0}generate(e){const t=super.generate(e),s=this.getNodeType();return e.format(t,"vec4",s)}}class Ux extends Px{static get type(){return"UniformArrayNode"}constructor(e,t=null){super(null,"vec4"),this.array=e,this.elementType=t,this._elementType=null,this._elementLength=0,this.updateType=Bd.RENDER,this.isArrayBufferNode=!0}getElementType(){return this.elementType||this._elementType}getElementLength(){return this._elementLength}update(){const{array:e,value:t}=this,s=this.getElementLength(),i=this.getElementType();if(1===s)for(let s=0;sSp(new Ux(e,t)),Lx=(e,t)=>(console.warn("TSL.UniformArrayNode: uniforms() has been renamed to uniformArray()."),Sp(new Ux(e,t)));class Vx extends Vd{static get type(){return"ReferenceElementNode"}constructor(e,t){super(e,t),this.referenceNode=e,this.isReferenceElementNode=!0}getNodeType(){return this.referenceNode.uniformType}generate(e){const t=super.generate(e),s=this.referenceNode.getNodeType(),i=this.getNodeType();return e.format(t,s,i)}}class Dx extends Ld{static get type(){return"ReferenceNode"}constructor(e,t,s=null,i=null){super(),this.property=e,this.uniformType=t,this.object=s,this.count=i,this.properties=e.split("."),this.reference=s,this.node=null,this.group=null,this.name=null,this.updateType=Bd.OBJECT}element(e){return Sp(new Vx(this,Sp(e)))}setGroup(e){return this.group=e,this}label(e){return this.name=e,this}setNodeType(e){let t=null;t=null!==this.count?Fx(null,e,this.count):Array.isArray(this.getValueFromReference())?Ox(null,e):"texture"===e?By(null):"cubeTexture"===e?Ix(null):pm(null,e),null!==this.group&&t.setGroup(this.group),null!==this.name&&t.label(this.name),this.node=t.getSelf()}getNodeType(e){return null===this.node&&(this.updateReference(e),this.updateValue()),this.node.getNodeType(e)}getValueFromReference(e=this.reference){const{properties:t}=this;let s=e[t[0]];for(let e=1;eSp(new Dx(e,t,s)),Gx=(e,t,s,i)=>Sp(new Dx(e,t,i,s));class Wx extends Dx{static get type(){return"MaterialReferenceNode"}constructor(e,t,s=null){super(e,t,s),this.material=s,this.isMaterialReferenceNode=!0}updateReference(e){return this.reference=null!==this.material?this.material:e.material,this.reference}}const jx=(e,t,s)=>Sp(new Wx(e,t,s)),Hx=Rp((e=>(!1===e.geometry.hasAttribute("tangent")&&e.geometry.computeTangents(),Sy("tangent","vec4"))))(),qx=Hx.xyz.toVar("tangentLocal"),$x=ix.mul(Xp(qx,0)).xyz.varying("v_tangentView").normalize().toVar("tangentView"),Xx=$x.transformDirection(Vy).varying("v_tangentWorld").normalize().toVar("tangentWorld"),Yx=$x.toVar("transformedTangentView"),Zx=Yx.transformDirection(Vy).normalize().toVar("transformedTangentWorld"),Jx=e=>e.mul(Hx.w).xyz,Kx=Vf(Jx(fx.cross(Hx)),"v_bitangentGeometry").normalize().toVar("bitangentGeometry"),Qx=Vf(Jx(yx.cross(qx)),"v_bitangentLocal").normalize().toVar("bitangentLocal"),eb=Vf(Jx(bx.cross($x)),"v_bitangentView").normalize().toVar("bitangentView"),tb=Vf(Jx(vx.cross(Xx)),"v_bitangentWorld").normalize().toVar("bitangentWorld"),sb=Jx(Tx.cross(Yx)).normalize().toVar("transformedBitangentView"),ib=sb.transformDirection(Vy).normalize().toVar("transformedBitangentWorld"),rb=Qp($x,eb,bx),nb=dx.mul(rb),ob=(e,t)=>e.sub(nb.mul(t)),ab=(()=>{let e=Bm.cross(dx);return e=e.cross(Bm).normalize(),e=Tf(e,Tx,Rm.mul(bm.oneMinus()).oneMinus().pow2().pow2()).normalize(),e})(),hb=Rp((e=>{const{eye_pos:t,surf_norm:s,mapN:i,uv:r}=e,n=t.dFdx(),o=t.dFdy(),a=r.dFdx(),h=r.dFdy(),u=s,l=o.cross(u),c=u.cross(n),d=l.mul(a.x).add(c.mul(h.x)),p=l.mul(a.y).add(c.mul(h.y)),m=d.dot(d).max(p.dot(p)),g=gx.mul(m.inverseSqrt());return Zm(d.mul(i.x,g),p.mul(i.y,g),u.mul(i.z)).normalize()}));class ub extends kd{static get type(){return"NormalMapNode"}constructor(e,t=null){super("vec3"),this.node=e,this.scaleNode=t,this.normalMapType=0}setup(e){const{normalMapType:t,scaleNode:s}=this;let i=this.node.mul(2).sub(1);null!==s&&(i=jp(i.xy.mul(s),i.z));let r=null;if(1===t)r=Mx(i);else if(0===t){r=!0===e.hasGeometryAttribute("tangent")?rb.mul(i).normalize():hb({eye_pos:cx,surf_norm:bx,mapN:i,uv:My()})}return r}}const lb=Ap(ub),cb=Rp((({textureNode:e,bumpScale:t})=>{const s=t=>e.cache().context({getUV:e=>t(e.uvNode||My()),forceUVContext:!0}),i=Up(s((e=>e)));return Dp(Up(s((e=>e.add(e.dFdx())))).sub(i),Up(s((e=>e.add(e.dFdy())))).sub(i)).mul(t)})),db=Rp((e=>{const{surf_pos:t,surf_norm:s,dHdxy:i}=e,r=t.dFdx().normalize(),n=s,o=t.dFdy().normalize().cross(n),a=n.cross(r),h=r.dot(o).mul(gx),u=h.sign().mul(i.x.mul(o).add(i.y.mul(a)));return h.abs().mul(s).sub(u).normalize()}));class pb extends kd{static get type(){return"BumpMapNode"}constructor(e,t=null){super("vec3"),this.textureNode=e,this.scaleNode=t}setup(){const e=null!==this.scaleNode?this.scaleNode:1,t=cb({textureNode:this.textureNode,bumpScale:e});return db({surf_pos:cx,surf_norm:bx,dHdxy:t})}}const mb=Ap(pb),gb=new Map;class fb extends Ld{static get type(){return"MaterialNode"}constructor(e){super(),this.scope=e}getCache(e,t){let s=gb.get(e);return void 0===s&&(s=jx(e,t),gb.set(e,s)),s}getFloat(e){return this.getCache(e,"float")}getColor(e){return this.getCache(e,"color")}getTexture(e){return this.getCache("map"===e?"map":e+"Map","texture")}setup(e){const t=e.context.material,s=this.scope;let i=null;if(s===fb.COLOR){const e=void 0!==t.color?this.getColor(s):jp();i=t.map&&!0===t.map.isTexture?e.mul(this.getTexture("map")):e}else if(s===fb.OPACITY){const e=this.getFloat(s);i=t.alphaMap&&!0===t.alphaMap.isTexture?e.mul(this.getTexture("alpha")):e}else if(s===fb.SPECULAR_STRENGTH)i=t.specularMap&&!0===t.specularMap.isTexture?this.getTexture("specular").r:Up(1);else if(s===fb.SPECULAR_INTENSITY){const e=this.getFloat(s);i=t.specularMap?e.mul(this.getTexture(s).a):e}else if(s===fb.SPECULAR_COLOR){const e=this.getColor(s);i=t.specularColorMap&&!0===t.specularColorMap.isTexture?e.mul(this.getTexture(s).rgb):e}else if(s===fb.ROUGHNESS){const e=this.getFloat(s);i=t.roughnessMap&&!0===t.roughnessMap.isTexture?e.mul(this.getTexture(s).g):e}else if(s===fb.METALNESS){const e=this.getFloat(s);i=t.metalnessMap&&!0===t.metalnessMap.isTexture?e.mul(this.getTexture(s).b):e}else if(s===fb.EMISSIVE){const e=this.getFloat("emissiveIntensity"),r=this.getColor(s).mul(e);i=t.emissiveMap&&!0===t.emissiveMap.isTexture?r.mul(this.getTexture(s)):r}else if(s===fb.NORMAL)t.normalMap?(i=lb(this.getTexture("normal"),this.getCache("normalScale","vec2")),i.normalMapType=t.normalMapType):i=t.bumpMap?mb(this.getTexture("bump").r,this.getFloat("bumpScale")):bx;else if(s===fb.CLEARCOAT){const e=this.getFloat(s);i=t.clearcoatMap&&!0===t.clearcoatMap.isTexture?e.mul(this.getTexture(s).r):e}else if(s===fb.CLEARCOAT_ROUGHNESS){const e=this.getFloat(s);i=t.clearcoatRoughnessMap&&!0===t.clearcoatRoughnessMap.isTexture?e.mul(this.getTexture(s).r):e}else if(s===fb.CLEARCOAT_NORMAL)i=t.clearcoatNormalMap?lb(this.getTexture(s),this.getCache(s+"Scale","vec2")):bx;else if(s===fb.SHEEN){const e=this.getColor("sheenColor").mul(this.getFloat("sheen"));i=t.sheenColorMap&&!0===t.sheenColorMap.isTexture?e.mul(this.getTexture("sheenColor").rgb):e}else if(s===fb.SHEEN_ROUGHNESS){const e=this.getFloat(s);i=t.sheenRoughnessMap&&!0===t.sheenRoughnessMap.isTexture?e.mul(this.getTexture(s).a):e,i=i.clamp(.07,1)}else if(s===fb.ANISOTROPY)if(t.anisotropyMap&&!0===t.anisotropyMap.isTexture){const e=this.getTexture(s);i=Kp(ev.x,ev.y,ev.y.negate(),ev.x).mul(e.rg.mul(2).sub(Dp(1)).normalize().mul(e.b))}else i=ev;else if(s===fb.IRIDESCENCE_THICKNESS){const e=kx("1","float",t.iridescenceThicknessRange);if(t.iridescenceThicknessMap){const r=kx("0","float",t.iridescenceThicknessRange);i=e.sub(r).mul(this.getTexture(s).g).add(r)}else i=e}else if(s===fb.TRANSMISSION){const e=this.getFloat(s);i=t.transmissionMap?e.mul(this.getTexture(s).r):e}else if(s===fb.THICKNESS){const e=this.getFloat(s);i=t.thicknessMap?e.mul(this.getTexture(s).g):e}else if(s===fb.IOR)i=this.getFloat(s);else if(s===fb.LIGHT_MAP)i=this.getTexture(s).rgb.mul(this.getFloat("lightMapIntensity"));else if(s===fb.AO_MAP)i=this.getTexture(s).r.sub(1).mul(this.getFloat("aoMapIntensity")).add(1);else{const t=this.getNodeType(e);i=this.getCache(s,t)}return i}}fb.ALPHA_TEST="alphaTest",fb.COLOR="color",fb.OPACITY="opacity",fb.SHININESS="shininess",fb.SPECULAR="specular",fb.SPECULAR_STRENGTH="specularStrength",fb.SPECULAR_INTENSITY="specularIntensity",fb.SPECULAR_COLOR="specularColor",fb.REFLECTIVITY="reflectivity",fb.ROUGHNESS="roughness",fb.METALNESS="metalness",fb.NORMAL="normal",fb.CLEARCOAT="clearcoat",fb.CLEARCOAT_ROUGHNESS="clearcoatRoughness",fb.CLEARCOAT_NORMAL="clearcoatNormal",fb.EMISSIVE="emissive",fb.ROTATION="rotation",fb.SHEEN="sheen",fb.SHEEN_ROUGHNESS="sheenRoughness",fb.ANISOTROPY="anisotropy",fb.IRIDESCENCE="iridescence",fb.IRIDESCENCE_IOR="iridescenceIOR",fb.IRIDESCENCE_THICKNESS="iridescenceThickness",fb.IOR="ior",fb.TRANSMISSION="transmission",fb.THICKNESS="thickness",fb.ATTENUATION_DISTANCE="attenuationDistance",fb.ATTENUATION_COLOR="attenuationColor",fb.LINE_SCALE="scale",fb.LINE_DASH_SIZE="dashSize",fb.LINE_GAP_SIZE="gapSize",fb.LINE_WIDTH="linewidth",fb.LINE_DASH_OFFSET="dashOffset",fb.POINT_WIDTH="pointWidth",fb.DISPERSION="dispersion",fb.LIGHT_MAP="light",fb.AO_MAP="ao";const yb=Cp(fb,fb.ALPHA_TEST),xb=Cp(fb,fb.COLOR),bb=Cp(fb,fb.SHININESS),vb=Cp(fb,fb.EMISSIVE),Tb=Cp(fb,fb.OPACITY),_b=Cp(fb,fb.SPECULAR),wb=Cp(fb,fb.SPECULAR_INTENSITY),Sb=Cp(fb,fb.SPECULAR_COLOR),Mb=Cp(fb,fb.SPECULAR_STRENGTH),Nb=Cp(fb,fb.REFLECTIVITY),Ab=Cp(fb,fb.ROUGHNESS),Cb=Cp(fb,fb.METALNESS),Rb=Cp(fb,fb.NORMAL).context({getUV:null}),Eb=Cp(fb,fb.CLEARCOAT),Bb=Cp(fb,fb.CLEARCOAT_ROUGHNESS),Ib=Cp(fb,fb.CLEARCOAT_NORMAL).context({getUV:null}),Pb=Cp(fb,fb.ROTATION),Fb=Cp(fb,fb.SHEEN),zb=Cp(fb,fb.SHEEN_ROUGHNESS),Ub=Cp(fb,fb.ANISOTROPY),Ob=Cp(fb,fb.IRIDESCENCE),Lb=Cp(fb,fb.IRIDESCENCE_IOR),Vb=Cp(fb,fb.IRIDESCENCE_THICKNESS),Db=Cp(fb,fb.TRANSMISSION),kb=Cp(fb,fb.THICKNESS),Gb=Cp(fb,fb.IOR),Wb=Cp(fb,fb.ATTENUATION_DISTANCE),jb=Cp(fb,fb.ATTENUATION_COLOR),Hb=Cp(fb,fb.LINE_SCALE),qb=Cp(fb,fb.LINE_DASH_SIZE),$b=Cp(fb,fb.LINE_GAP_SIZE),Xb=Cp(fb,fb.LINE_WIDTH),Yb=Cp(fb,fb.LINE_DASH_OFFSET),Zb=Cp(fb,fb.POINT_WIDTH),Jb=Cp(fb,fb.DISPERSION),Kb=Cp(fb,fb.LIGHT_MAP),Qb=Cp(fb,fb.AO_MAP),ev=pm(new Qs).onReference((function(e){return e.material})).onRenderUpdate((function({material:e}){this.value.set(e.anisotropy*Math.cos(e.anisotropyRotation),e.anisotropy*Math.sin(e.anisotropyRotation))}));class tv extends kd{static get type(){return"ModelViewProjectionNode"}constructor(e=null){super("vec4"),this.positionNode=e}setup(e){if("fragment"===e.shaderStage)return Vf(e.context.mvp);const t=this.positionNode||ax,s=e.renderer.nodes.modelViewMatrix||ix;return Oy.mul(s).mul(t)}}const sv=Ap(tv);class iv extends Ld{static get type(){return"IndexNode"}constructor(e){super("uint"),this.scope=e,this.isInstanceIndexNode=!0}generate(e){const t=this.getNodeType(e),s=this.scope;let i,r;if(s===iv.VERTEX)i=e.getVertexIndex();else if(s===iv.INSTANCE)i=e.getInstanceIndex();else if(s===iv.DRAW)i=e.getDrawIndex();else if(s===iv.INVOCATION_LOCAL)i=e.getInvocationLocalIndex();else if(s===iv.INVOCATION_SUBGROUP)i=e.getInvocationSubgroupIndex();else{if(s!==iv.SUBGROUP)throw new Error("THREE.IndexNode: Unknown scope: "+s);i=e.getSubgroupIndex()}if("vertex"===e.shaderStage||"compute"===e.shaderStage)r=i;else{r=Vf(this).build(e,t)}return r}}iv.VERTEX="vertex",iv.INSTANCE="instance",iv.SUBGROUP="subgroup",iv.INVOCATION_LOCAL="invocationLocal",iv.INVOCATION_SUBGROUP="invocationSubgroup",iv.DRAW="draw";const rv=Cp(iv,iv.VERTEX),nv=Cp(iv,iv.INSTANCE),ov=Cp(iv,iv.SUBGROUP),av=Cp(iv,iv.INVOCATION_SUBGROUP),hv=Cp(iv,iv.INVOCATION_LOCAL),uv=Cp(iv,iv.DRAW);class lv extends Ld{static get type(){return"InstanceNode"}constructor(e){super("void"),this.instanceMesh=e,this.instanceMatrixNode=null,this.instanceColorNode=null,this.updateType=Bd.FRAME,this.buffer=null,this.bufferColor=null}setup(e){let t=this.instanceMatrixNode,s=this.instanceColorNode;const i=this.instanceMesh;if(null===t){const e=i.instanceMatrix;if(i.count<=1e3)t=Fx(e.array,"mat4",Math.max(i.count,1)).element(nv);else{const s=new wc(e.array,16,1);this.buffer=s;const i=e.usage===Rs?oy:ny,r=[i(s,"vec4",16,0),i(s,"vec4",16,4),i(s,"vec4",16,8),i(s,"vec4",16,12)];t=em(...r)}this.instanceMatrixNode=t}const r=i.instanceColor;if(r&&null===s){const e=new Do(r.array,3),t=r.usage===Rs?oy:ny;this.bufferColor=e,s=jp(t(e,"vec3",3,0)),this.instanceColorNode=s}const n=t.mul(ax).xyz;if(ax.assign(n),e.hasGeometryAttribute("normal")){const e=Sx(yx,t);yx.assign(e)}null!==this.instanceColorNode&&fm("vec3","vInstanceColor").assign(this.instanceColorNode)}update(){this.instanceMesh.instanceMatrix.usage!==Rs&&null!=this.buffer&&this.instanceMesh.instanceMatrix.version!==this.buffer.version&&(this.buffer.version=this.instanceMesh.instanceMatrix.version),this.instanceMesh.instanceColor&&this.instanceMesh.instanceColor.usage!==Rs&&null!=this.bufferColor&&this.instanceMesh.instanceColor.version!==this.bufferColor.version&&(this.bufferColor.version=this.instanceMesh.instanceColor.version)}}const cv=Ap(lv);class dv extends Ld{static get type(){return"BatchNode"}constructor(e){super("void"),this.batchMesh=e,this.batchingIdNode=null}setup(e){null===this.batchingIdNode&&(null===e.getDrawIndex()?this.batchingIdNode=nv:this.batchingIdNode=uv);const t=Rp((([e])=>{const t=Ay(Iy(this.batchMesh._indirectTexture),0),s=Op(e).modInt(Op(t)),i=Op(e).div(Op(t));return Iy(this.batchMesh._indirectTexture,kp(s,i)).x})).setLayout({name:"getIndirectIndex",type:"uint",inputs:[{name:"id",type:"int"}]}),s=t(Op(this.batchingIdNode)),i=this.batchMesh._matricesTexture,r=Ay(Iy(i),0),n=Up(s).mul(4).toInt().toVar(),o=n.modInt(r),a=n.div(Op(r)),h=em(Iy(i,kp(o,a)),Iy(i,kp(o.add(1),a)),Iy(i,kp(o.add(2),a)),Iy(i,kp(o.add(3),a))),u=this.batchMesh._colorsTexture;if(null!==u){const e=Rp((([e])=>{const t=Ay(Iy(u),0).x,s=e,i=s.modInt(t),r=s.div(t);return Iy(u,kp(i,r)).rgb})).setLayout({name:"getBatchingColor",type:"vec3",inputs:[{name:"id",type:"int"}]}),t=e(s);fm("vec3","vBatchColor").assign(t)}const l=Qp(h);ax.assign(h.mul(ax));const c=yx.div(jp(l[0].dot(l[0]),l[1].dot(l[1]),l[2].dot(l[2]))),d=l.mul(c).xyz;yx.assign(d),e.hasGeometryAttribute("tangent")&&qx.mulAssign(l)}}const pv=Ap(dv),mv=new WeakMap;class gv extends Ld{static get type(){return"SkinningNode"}constructor(e,t=!1){let s,i,r;super("void"),this.skinnedMesh=e,this.useReference=t,this.updateType=Bd.OBJECT,this.skinIndexNode=Sy("skinIndex","uvec4"),this.skinWeightNode=Sy("skinWeight","vec4"),t?(s=kx("bindMatrix","mat4"),i=kx("bindMatrixInverse","mat4"),r=Gx("skeleton.boneMatrices","mat4",e.skeleton.bones.length)):(s=pm(e.bindMatrix,"mat4"),i=pm(e.bindMatrixInverse,"mat4"),r=Fx(e.skeleton.boneMatrices,"mat4",e.skeleton.bones.length)),this.bindMatrixNode=s,this.bindMatrixInverseNode=i,this.boneMatricesNode=r,this.previousBoneMatricesNode=null}getSkinnedPosition(e=this.boneMatricesNode,t=ax){const{skinIndexNode:s,skinWeightNode:i,bindMatrixNode:r,bindMatrixInverseNode:n}=this,o=e.element(s.x),a=e.element(s.y),h=e.element(s.z),u=e.element(s.w),l=r.mul(t),c=Zm(o.mul(i.x).mul(l),a.mul(i.y).mul(l),h.mul(i.z).mul(l),u.mul(i.w).mul(l));return n.mul(c).xyz}getSkinnedNormal(e=this.boneMatricesNode,t=yx){const{skinIndexNode:s,skinWeightNode:i,bindMatrixNode:r,bindMatrixInverseNode:n}=this,o=e.element(s.x),a=e.element(s.y),h=e.element(s.z),u=e.element(s.w);let l=Zm(i.x.mul(o),i.y.mul(a),i.z.mul(h),i.w.mul(u));return l=n.mul(l).mul(r),l.transformDirection(t).xyz}getPreviousSkinnedPosition(e){const t=e.object;return null===this.previousBoneMatricesNode&&(t.skeleton.previousBoneMatrices=new Float32Array(t.skeleton.boneMatrices),this.previousBoneMatricesNode=Gx("skeleton.previousBoneMatrices","mat4",t.skeleton.bones.length)),this.getSkinnedPosition(this.previousBoneMatricesNode,hx)}needsPreviousBoneMatrices(e){const t=e.renderer.getMRT();return t&&t.has("velocity")}setup(e){this.needsPreviousBoneMatrices(e)&&hx.assign(this.getPreviousSkinnedPosition(e));const t=this.getSkinnedPosition();if(ax.assign(t),e.hasGeometryAttribute("normal")){const t=this.getSkinnedNormal();yx.assign(t),e.hasGeometryAttribute("tangent")&&qx.assign(t)}}generate(e,t){if("void"!==t)return ax.build(e,t)}update(e){const t=(this.useReference?e.object:this.skinnedMesh).skeleton;mv.get(t)!==e.frameId&&(mv.set(t,e.frameId),null!==this.previousBoneMatricesNode&&t.previousBoneMatrices.set(t.boneMatrices),t.update())}}const fv=e=>Sp(new gv(e)),yv=e=>Sp(new gv(e,!0));class xv extends Ld{static get type(){return"LoopNode"}constructor(e=[]){super(),this.params=e}getVarName(e){return String.fromCharCode("i".charCodeAt()+e)}getProperties(e){const t=e.getNodeProperties(this);if(void 0!==t.stackNode)return t;const s={};for(let e=0,t=this.params.length-1;eNumber(n)?">=":"<"));const l={start:r,end:n,condition:h},c=l.start,d=l.end;let p="",m="",g="";u||(u="int"===a||"uint"===a?h.includes("<")?"++":"--":h.includes("<")?"+= 1.":"-= 1."),p+=e.getVar(a,o)+" = "+c,m+=o+" "+h+" "+d,g+=o+" "+u;const f=`for ( ${p}; ${m}; ${g} )`;e.addFlowCode((0===t?"\n":"")+e.tab+f+" {\n\n").addFlowTab()}const r=i.build(e,"void"),n=t.returnsNode?t.returnsNode.build(e):"";e.removeFlowTab().addFlowCode("\n"+e.tab+r);for(let t=0,s=this.params.length-1;tSp(new xv(Np(e,"int"))).append(),vv=()=>yy("continue").append(),Tv=()=>yy("break").append(),_v=(...e)=>(console.warn("TSL.LoopNode: loop() has been renamed to Loop()."),bv(...e)),wv=new WeakMap,Sv=new Ti,Mv=Rp((({bufferMap:e,influence:t,stride:s,width:i,depth:r,offset:n})=>{const o=Op(rv).mul(s).add(n),a=o.div(i),h=o.sub(a.mul(i));return Iy(e,kp(h,a)).depth(r).mul(t)}));class Nv extends Ld{static get type(){return"MorphNode"}constructor(e){super("void"),this.mesh=e,this.morphBaseInfluence=pm(1),this.updateType=Bd.OBJECT}setup(e){const{geometry:t}=e,s=void 0!==t.morphAttributes.position,i=t.hasAttribute("normal")&&void 0!==t.morphAttributes.normal,r=t.morphAttributes.position||t.morphAttributes.normal||t.morphAttributes.color,n=void 0!==r?r.length:0,{texture:o,stride:a,size:h}=function(e){const t=void 0!==e.morphAttributes.position,s=void 0!==e.morphAttributes.normal,i=void 0!==e.morphAttributes.color,r=e.morphAttributes.position||e.morphAttributes.normal||e.morphAttributes.color,n=void 0!==r?r.length:0;let o=wv.get(e);if(void 0===o||o.count!==n){void 0!==o&&o.texture.dispose();const a=e.morphAttributes.position||[],h=e.morphAttributes.normal||[],u=e.morphAttributes.color||[];let l=0;!0===t&&(l=1),!0===s&&(l=2),!0===i&&(l=3);let c=e.attributes.position.count*l,d=1;const p=4096;c>p&&(d=Math.ceil(c/p),c=p);const m=new Float32Array(c*d*4*n),g=new Si(m,c,d,n);g.type=Ie,g.needsUpdate=!0;const f=4*l;for(let x=0;x{const t=Up(0).toVar();this.mesh.count>1&&null!==this.mesh.morphTexture&&void 0!==this.mesh.morphTexture?t.assign(Iy(this.mesh.morphTexture,kp(Op(e).add(1),Op(nv))).r):t.assign(kx("morphTargetInfluences","float").element(e).toVar()),!0===s&&ax.addAssign(Mv({bufferMap:o,influence:t,stride:a,width:u,depth:e,offset:Op(0)})),!0===i&&yx.addAssign(Mv({bufferMap:o,influence:t,stride:a,width:u,depth:e,offset:Op(1)}))}))}update(){const e=this.morphBaseInfluence;this.mesh.geometry.morphTargetsRelative?e.value=1:e.value=1-this.mesh.morphTargetInfluences.reduce(((e,t)=>e+t),0)}}const Av=Ap(Nv),Cv=(e,t)=>{for(const s of t)if(s.isAnalyticLightNode&&s.light.id===e)return s;return null},Rv=new WeakMap;class Ev extends Ld{static get type(){return"LightsNode"}constructor(e=[]){super("vec3"),this.totalDiffuseNode=jp().toVar("totalDiffuse"),this.totalSpecularNode=jp().toVar("totalSpecular"),this.outgoingLightNode=jp().toVar("outgoingLight"),this._lights=e,this._lightNodes=null,this._lightNodesHash=null,this.global=!0}getHash(e){if(null===this._lightNodesHash){null===this._lightNodes&&this.setupLightsNode(e);const t=[];for(const e of this._lightNodes)t.push(e.getHash());this._lightNodesHash="lights-"+t.join(",")}return this._lightNodesHash}analyze(e){const t=e.getDataFromNode(this);for(const s of t.nodes)s.build(e)}setupLightsNode(e){const t=[],s=this._lightNodes,i=(e=>e.sort(((e,t)=>e.id-t.id)))(this._lights),r=e.renderer.nodes.library;for(const e of i)if(e.isNode)t.push(Sp(e));else{let i=null;if(null!==s&&(i=Cv(e.id,s)),null===i){const s=r.getLightNodeClass(e.constructor);if(null===s){console.warn(`LightsNode.setupNodeLights: Light node not found for ${e.constructor.name}`);continue}let i=null;Rv.has(e)?i=Rv.get(e):(i=new s(e),Rv.set(e,i)),t.push(i)}}this._lightNodes=t}setup(e){null===this._lightNodes&&this.setupLightsNode(e);const t=e.context,s=t.lightingModel;let i=this.outgoingLightNode;if(s){const{_lightNodes:r,totalDiffuseNode:n,totalSpecularNode:o}=this;t.outgoingLight=i;const a=e.addStack();e.getDataFromNode(this).nodes=a.nodes,s.start(t,a,e);for(const t of r)t.build(e);s.indirect(t,a,e);const{backdrop:h,backdropAlpha:u}=t,{directDiffuse:l,directSpecular:c,indirectDiffuse:d,indirectSpecular:p}=t.reflectedLight;let m=l.add(d);null!==h&&(m=jp(null!==u?u.mix(m,h):h),t.material.transparent=!0),n.assign(m),o.assign(c.add(p)),i.assign(n.add(o)),s.finish(t,a,e),i=i.bypass(e.removeStack())}return i}setLights(e){return this._lights=e,this._lightNodes=null,this._lightNodesHash=null,this}getLights(){return this._lights}}const Bv=Ap(Ev);class Iv extends Ld{static get type(){return"LightingNode"}constructor(){super("vec3"),this.isLightingNode=!0}generate(){console.warn("Abstract function.")}}class Pv extends Iv{static get type(){return"AONode"}constructor(e=null){super(),this.aoNode=e}setup(e){e.context.ambientOcclusion.mulAssign(this.aoNode)}}class Fv extends Pf{static get type(){return"LightingContextNode"}constructor(e,t=null,s=null,i=null){super(e),this.lightingModel=t,this.backdropNode=s,this.backdropAlphaNode=i,this._value=null}getContext(){const{backdropNode:e,backdropAlphaNode:t}=this,s={directDiffuse:jp().toVar("directDiffuse"),directSpecular:jp().toVar("directSpecular"),indirectDiffuse:jp().toVar("indirectDiffuse"),indirectSpecular:jp().toVar("indirectSpecular")};return{radiance:jp().toVar("radiance"),irradiance:jp().toVar("irradiance"),iblIrradiance:jp().toVar("iblIrradiance"),ambientOcclusion:Up(1).toVar("ambientOcclusion"),reflectedLight:s,backdrop:e,backdropAlpha:t}}setup(e){return this.value=this._value||(this._value=this.getContext()),this.value.lightingModel=this.lightingModel||e.context.lightingModel,super.setup(e)}}const zv=Ap(Fv);class Uv extends Iv{static get type(){return"IrradianceNode"}constructor(e){super(),this.node=e}setup(e){e.context.irradiance.addAssign(this.node)}}let Ov,Lv;class Vv extends Ld{static get type(){return"ScreenNode"}constructor(e){super(),this.scope=e,this.isViewportNode=!0}getNodeType(){return this.scope===Vv.VIEWPORT?"vec4":"vec2"}getUpdateType(){let e=Bd.NONE;return this.scope!==Vv.SIZE&&this.scope!==Vv.VIEWPORT||(e=Bd.RENDER),this.updateType=e,e}update({renderer:e}){const t=e.getRenderTarget();this.scope===Vv.VIEWPORT?null!==t?Lv.copy(t.viewport):(e.getViewport(Lv),Lv.multiplyScalar(e.getPixelRatio())):null!==t?(Ov.width=t.width,Ov.height=t.height):e.getDrawingBufferSize(Ov)}setup(){const e=this.scope;let t=null;return t=e===Vv.SIZE?pm(Ov||(Ov=new Qs)):e===Vv.VIEWPORT?pm(Lv||(Lv=new Ti)):Dp(Gv.div(kv)),t}generate(e){if(this.scope===Vv.COORDINATE){let t=e.getFragCoord();if(e.isFlipY()){const s=e.getNodeProperties(kv).outputNode.build(e);t=`${e.getType("vec2")}( ${t}.x, ${s}.y - ${t}.y )`}return t}return super.generate(e)}}Vv.COORDINATE="coordinate",Vv.VIEWPORT="viewport",Vv.SIZE="size",Vv.UV="uv";const Dv=Cp(Vv,Vv.UV),kv=Cp(Vv,Vv.SIZE),Gv=Cp(Vv,Vv.COORDINATE),Wv=Cp(Vv,Vv.VIEWPORT),jv=Wv.zw,Hv=Gv.sub(Wv.xy),qv=Hv.div(jv),$v=Rp((()=>(console.warn('TSL.ViewportNode: "viewportResolution" is deprecated. Use "screenSize" instead.'),kv)),"vec2").once()(),Xv=Rp((()=>(console.warn('TSL.ViewportNode: "viewportTopLeft" is deprecated. Use "screenUV" instead.'),Dv)),"vec2").once()(),Yv=Rp((()=>(console.warn('TSL.ViewportNode: "viewportBottomLeft" is deprecated. Use "screenUV.flipY()" instead.'),Dv.flipY())),"vec2").once()(),Zv=new Qs;class Jv extends Ey{static get type(){return"ViewportTextureNode"}constructor(e=Dv,t=null,s=null){null===s&&((s=new ja).minFilter=Se),super(s,e,t),this.generateMipmaps=!1,this.isOutputTextureNode=!0,this.updateBeforeType=Bd.FRAME}updateBefore(e){const t=e.renderer;t.getDrawingBufferSize(Zv);const s=this.value;s.image.width===Zv.width&&s.image.height===Zv.height||(s.image.width=Zv.width,s.image.height=Zv.height,s.needsUpdate=!0);const i=s.generateMipmaps;s.generateMipmaps=this.generateMipmaps,t.copyFramebufferToTexture(s),s.generateMipmaps=i}clone(){const e=new this.constructor(this.uvNode,this.levelNode,this.value);return e.generateMipmaps=this.generateMipmaps,e}}const Kv=Ap(Jv),Qv=Ap(Jv,null,null,{generateMipmaps:!0});let eT=null;class tT extends Jv{static get type(){return"ViewportDepthTextureNode"}constructor(e=Dv,t=null){null===eT&&(eT=new Ya),super(e,t,eT)}}const sT=Ap(tT);class iT extends Ld{static get type(){return"ViewportDepthNode"}constructor(e,t=null){super("float"),this.scope=e,this.valueNode=t,this.isViewportDepthNode=!0}generate(e){const{scope:t}=this;return t===iT.DEPTH_BASE?e.getFragDepth():super.generate(e)}setup({camera:e}){const{scope:t}=this,s=this.valueNode;let i=null;if(t===iT.DEPTH_BASE)null!==s&&(i=hT().assign(s));else if(t===iT.DEPTH)i=e.isPerspectiveCamera?oT(cx.z,Fy,zy):rT(cx.z,Fy,zy);else if(t===iT.LINEAR_DEPTH)if(null!==s)if(e.isPerspectiveCamera){const e=aT(s,Fy,zy);i=rT(e,Fy,zy)}else i=s;else i=rT(cx.z,Fy,zy);return i}}iT.DEPTH_BASE="depthBase",iT.DEPTH="depth",iT.LINEAR_DEPTH="linearDepth";const rT=(e,t,s)=>e.add(t).div(t.sub(s)),nT=(e,t,s)=>t.sub(s).mul(e).sub(t),oT=(e,t,s)=>t.add(e).mul(s).div(s.sub(t).mul(e)),aT=(e,t,s)=>t.mul(s).div(s.sub(t).mul(e).sub(s)),hT=Ap(iT,iT.DEPTH_BASE),uT=Cp(iT,iT.DEPTH),lT=Ap(iT,iT.LINEAR_DEPTH),cT=lT(sT());uT.assign=e=>hT(e);class dT extends Ld{static get type(){return"ClippingNode"}constructor(e=dT.DEFAULT){super(),this.scope=e}setup(e){super.setup(e);const t=e.clippingContext,{localClipIntersection:s,localClippingCount:i,globalClippingCount:r}=t,n=r+i,o=s?n-i:n;return this.scope===dT.ALPHA_TO_COVERAGE?this.setupAlphaToCoverage(t.planes,n,o):this.setupDefault(t.planes,n,o)}setupAlphaToCoverage(e,t,s){return Rp((()=>{const i=Ox(e),r=gm("float","distanceToPlane"),n=gm("float","distanceToGradient"),o=gm("float","clipOpacity");let a;if(o.assign(1),bv(s,(({i:e})=>{a=i.element(e),r.assign(cx.dot(a.xyz).negate().add(a.w)),n.assign(r.fwidth().div(2)),o.mulAssign(Mf(n.negate(),n,r)),o.equal(0).discard()})),s{a=i.element(t),r.assign(cx.dot(a.xyz).negate().add(a.w)),n.assign(r.fwidth().div(2)),e.mulAssign(Mf(n.negate(),n,r).oneMinus())})),o.mulAssign(e.oneMinus())}ym.a.mulAssign(o),ym.a.equal(0).discard()}))()}setupDefault(e,t,s){return Rp((()=>{const i=Ox(e);let r;if(bv(s,(({i:e})=>{r=i.element(e),cx.dot(r.xyz).greaterThan(r.w).discard()})),s{r=i.element(t),e.assign(cx.dot(r.xyz).greaterThan(r.w).and(e))})),e.discard()}}))()}}dT.ALPHA_TO_COVERAGE="alphaToCoverage",dT.DEFAULT="default";class pT extends en{static get type(){return"NodeMaterial"}constructor(){super(),this.isNodeMaterial=!0,this.type=this.constructor.type,this.forceSinglePass=!1,this.fog=!0,this.lights=!1,this.lightsNode=null,this.envNode=null,this.aoNode=null,this.colorNode=null,this.normalNode=null,this.opacityNode=null,this.backdropNode=null,this.backdropAlphaNode=null,this.alphaTestNode=null,this.positionNode=null,this.depthNode=null,this.shadowNode=null,this.shadowPositionNode=null,this.outputNode=null,this.mrtNode=null,this.fragmentNode=null,this.vertexNode=null}customProgramCacheKey(){return this.type+wd(this)}build(e){this.setup(e)}setupObserver(e){return new xd(e)}setup(e){let t;e.context.setupNormal=()=>this.setupNormal(e),e.addStack(),e.stack.outputNode=this.vertexNode||this.setupPosition(e),e.addFlow("vertex",e.removeStack()),e.addStack();const s=this.setupClipping(e);if(!0===this.depthWrite&&this.setupDepth(e),null===this.fragmentNode){this.setupDiffuseColor(e),this.setupVariants(e);const i=this.setupLighting(e);null!==s&&e.stack.add(s);const r=Xp(i,ym.a).max(0);t=this.setupOutput(e,r),zm.assign(t),null!==this.outputNode&&(t=this.outputNode);if(null!==e.renderer.getRenderTarget()){const s=e.renderer.getMRT(),i=this.mrtNode;null!==s?(t=s,null!==i&&(t=s.merge(i))):null!==i&&(t=i)}}else{let s=this.fragmentNode;!0!==s.isOutputStructNode&&(s=Xp(s)),t=this.setupOutput(e,s)}e.stack.outputNode=t,e.addFlow("fragment",e.removeStack()),e.monitor=this.setupObserver(e)}setupClipping(e){if(null===e.clippingContext)return null;const{globalClippingCount:t,localClippingCount:s}=e.clippingContext;let i=null;if(t||s){const t=e.renderer.samples;this.alphaToCoverage&&t>1?i=Sp(new dT(dT.ALPHA_TO_COVERAGE)):e.stack.add(Sp(new dT))}return i}setupDepth(e){const{renderer:t}=e;let s=this.depthNode;if(null===s){const e=t.getMRT();if(e&&e.has("depth"))s=e.get("depth");else if(!0===t.logarithmicDepthBuffer){s=sv().w.add(1).log2().mul(Uy).mul(.5)}}null!==s&&uT.assign(s).append()}setupPosition(e){const{object:t}=e,s=t.geometry;if(e.addStack(),(s.morphAttributes.position||s.morphAttributes.normal||s.morphAttributes.color)&&Av(t).append(),!0===t.isSkinnedMesh&&yv(t).append(),this.displacementMap){const e=jx("displacementMap","texture"),t=jx("displacementScale","float"),s=jx("displacementBias","float");ax.addAssign(yx.normalize().mul(e.x.mul(t).add(s)))}t.isBatchedMesh&&pv(t).append(),t.instanceMatrix&&!0===t.instanceMatrix.isInstancedBufferAttribute&&cv(t).append(),null!==this.positionNode&&ax.assign(this.positionNode);const i=sv();return e.context.vertex=e.removeStack(),e.context.mvp=i,i}setupDiffuseColor({object:e,geometry:t}){let s=this.colorNode?Xp(this.colorNode):xb;if(!0===this.vertexColors&&t.hasAttribute("color")&&(s=Xp(s.xyz.mul(Sy("color","vec3")),s.a)),e.instanceColor){s=fm("vec3","vInstanceColor").mul(s)}if(e.isBatchedMesh&&e._colorsTexture){s=fm("vec3","vBatchColor").mul(s)}ym.assign(s);const i=this.opacityNode?Up(this.opacityNode):Tb;if(ym.a.assign(ym.a.mul(i)),null!==this.alphaTestNode||this.alphaTest>0){const e=null!==this.alphaTestNode?Up(this.alphaTestNode):yb;ym.a.lessThanEqual(e).discard()}!1===this.transparent&&1===this.blending&&!1===this.alphaToCoverage&&ym.a.assign(1)}setupVariants(){}setupOutgoingLight(){return!0===this.lights?jp(0):ym.rgb}setupNormal(){return this.normalNode?jp(this.normalNode):Rb}setupEnvironment(){let e=null;return this.envNode?e=this.envNode:this.envMap&&(e=this.envMap.isCubeTexture?jx("envMap","cubeTexture"):jx("envMap","texture")),e}setupLightMap(e){let t=null;return e.material.lightMap&&(t=new Uv(Kb)),t}setupLights(e){const t=[],s=this.setupEnvironment(e);s&&s.isLightingNode&&t.push(s);const i=this.setupLightMap(e);if(i&&i.isLightingNode&&t.push(i),null!==this.aoNode||e.material.aoMap){const e=null!==this.aoNode?this.aoNode:Qb;t.push(new Pv(e))}let r=this.lightsNode||e.lightsNode;return t.length>0&&(r=Bv([...r.getLights(),...t])),r}setupLightingModel(){}setupLighting(e){const{material:t}=e,{backdropNode:s,backdropAlphaNode:i,emissiveNode:r}=this,n=!0===this.lights||null!==this.lightsNode?this.setupLights(e):null;let o=this.setupOutgoingLight(e);if(n&&n.getScope().getLights().length>0){const t=this.setupLightingModel(e);o=zv(n,t,s,i)}else null!==s&&(o=jp(null!==i?Tf(o,s,i):s));return(r&&!0===r.isNode||t.emissive&&!0===t.emissive.isColor)&&(xm.assign(jp(r||vb)),o=o.add(xm)),o}setupOutput(e,t){if(!0===this.fog){const s=e.fogNode;s&&(t=Xp(s.mix(t.rgb,s.colorNode),t.a))}return t}setDefaultValues(e){for(const t in e){const s=e[t];void 0===this[t]&&(this[t]=s,s&&s.clone&&(this[t]=s.clone()))}const t=Object.getOwnPropertyDescriptors(e.constructor.prototype);for(const e in t)void 0===Object.getOwnPropertyDescriptor(this.constructor.prototype,e)&&void 0!==t[e].get&&Object.defineProperty(this.constructor.prototype,e,t[e])}toJSON(e){const t=void 0===e||"string"==typeof e;t&&(e={textures:{},images:{},nodes:{}});const s=en.prototype.toJSON.call(this,e),i=Sd(this);s.inputNodes={};for(const{property:t,childNode:r}of i)s.inputNodes[t]=r.toJSON(e).uuid;function r(e){const t=[];for(const s in e){const i=e[s];delete i.metadata,t.push(i)}return t}if(t){const t=r(e.textures),i=r(e.images),n=r(e.nodes);t.length>0&&(s.textures=t),i.length>0&&(s.images=i),n.length>0&&(s.nodes=n)}return s}copy(e){return this.lightsNode=e.lightsNode,this.envNode=e.envNode,this.colorNode=e.colorNode,this.normalNode=e.normalNode,this.opacityNode=e.opacityNode,this.backdropNode=e.backdropNode,this.backdropAlphaNode=e.backdropAlphaNode,this.alphaTestNode=e.alphaTestNode,this.positionNode=e.positionNode,this.depthNode=e.depthNode,this.shadowNode=e.shadowNode,this.shadowPositionNode=e.shadowPositionNode,this.outputNode=e.outputNode,this.mrtNode=e.mrtNode,this.fragmentNode=e.fragmentNode,this.vertexNode=e.vertexNode,super.copy(e)}}const mT=new za;class gT extends pT{static get type(){return"InstancedPointsNodeMaterial"}constructor(e={}){super(),this.lights=!1,this.useAlphaToCoverage=!0,this.useColor=e.vertexColors,this.pointWidth=1,this.pointColorNode=null,this.pointWidthNode=null,this.setDefaultValues(mT),this.setValues(e)}setup(e){this.setupShaders(e),super.setup(e)}setupShaders({renderer:e}){const t=this.alphaToCoverage,s=this.useColor;this.vertexNode=Rp((()=>{const e=Sy("instancePosition").xyz,t=Xp(ix.mul(Xp(e,1))),s=Wv.z.div(Wv.w),i=Oy.mul(t),r=ox.xy.toVar();return r.mulAssign(this.pointWidthNode?this.pointWidthNode:Zb),r.assign(r.div(Wv.z)),r.y.assign(r.y.mul(s)),r.assign(r.mul(i.w)),i.addAssign(Xp(r,0,0)),i}))(),this.fragmentNode=Rp((()=>{const i=Up(1).toVar(),r=vf(My().mul(2).sub(1));if(t&&e.samples>1){const e=Up(r.fwidth()).toVar();i.assign(Mf(e.oneMinus(),e.add(1),r).oneMinus())}else r.greaterThan(1).discard();let n;if(this.pointColorNode)n=this.pointColorNode;else if(s){n=Sy("instanceColor").mul(xb)}else n=xb;return i.mulAssign(Tb),Xp(n,i)}))()}get alphaToCoverage(){return this.useAlphaToCoverage}set alphaToCoverage(e){this.useAlphaToCoverage!==e&&(this.useAlphaToCoverage=e,this.needsUpdate=!0)}}const fT=new Ta;class yT extends pT{static get type(){return"LineBasicNodeMaterial"}constructor(e){super(),this.isLineBasicNodeMaterial=!0,this.lights=!1,this.setDefaultValues(fT),this.setValues(e)}}const xT=new Bu;class bT extends pT{static get type(){return"LineDashedNodeMaterial"}constructor(e){super(),this.isLineDashedNodeMaterial=!0,this.lights=!1,this.setDefaultValues(xT),this.offsetNode=null,this.dashScaleNode=null,this.dashSizeNode=null,this.gapSizeNode=null,this.setValues(e)}setupVariants(){const e=this.offsetNode,t=this.dashScaleNode?Up(this.dashScaleNode):Hb,s=this.dashSizeNode?Up(this.dashSizeNode):qb,i=this.dashSizeNode?Up(this.dashGapNode):$b;Um.assign(s),Om.assign(i);const r=Vf(Sy("lineDistance").mul(t));(e?r.add(e):r).mod(Um.add(Om)).greaterThan(Um).discard()}}const vT=new Bu;class TT extends pT{static get type(){return"Line2NodeMaterial"}constructor(e={}){super(),this.lights=!1,this.setDefaultValues(vT),this.useAlphaToCoverage=!0,this.useColor=e.vertexColors,this.useDash=e.dashed,this.useWorldUnits=!1,this.dashOffset=0,this.lineWidth=1,this.lineColorNode=null,this.offsetNode=null,this.dashScaleNode=null,this.dashSizeNode=null,this.gapSizeNode=null,this.setValues(e)}setup(e){this.setupShaders(e),super.setup(e)}setupShaders({renderer:e}){const t=this.alphaToCoverage,s=this.useColor,i=this.dashed,r=this.worldUnits,n=Rp((({start:e,end:t})=>{const s=Oy.element(2).element(2),i=Oy.element(3).element(2).mul(-.5).div(s).sub(e.z).div(t.z.sub(e.z));return Xp(Tf(e.xyz,t.xyz,i),t.w)})).setLayout({name:"trimSegment",type:"vec4",inputs:[{name:"start",type:"vec4"},{name:"end",type:"vec4"}]});this.vertexNode=Rp((()=>{const e=Sy("instanceStart"),t=Sy("instanceEnd"),s=Xp(ix.mul(Xp(e,1))).toVar("start"),o=Xp(ix.mul(Xp(t,1))).toVar("end");r&&(fm("vec3","worldStart").assign(s.xyz),fm("vec3","worldEnd").assign(o.xyz));const a=Wv.z.div(Wv.w),h=Oy.element(2).element(3).equal(-1);Pp(h,(()=>{Pp(s.z.lessThan(0).and(o.z.greaterThan(0)),(()=>{o.assign(n({start:s,end:o}))})).ElseIf(o.z.lessThan(0).and(s.z.greaterThanEqual(0)),(()=>{s.assign(n({start:o,end:s}))}))}));const u=Oy.mul(s),l=Oy.mul(o),c=u.xyz.div(u.w),d=l.xyz.div(l.w),p=d.xy.sub(c.xy).toVar();p.x.assign(p.x.mul(a)),p.assign(p.normalize());const m=Xp().toVar();if(r){const e=o.xyz.sub(s.xyz).normalize(),t=Tf(s.xyz,o.xyz,.5).normalize(),r=e.cross(t).normalize(),n=e.cross(r),a=fm("vec4","worldPos");a.assign(ox.y.lessThan(.5).select(s,o));const h=Xb.mul(.5);a.addAssign(Xp(ox.x.lessThan(0).select(r.mul(h),r.mul(h).negate()),0)),i||(a.addAssign(Xp(ox.y.lessThan(.5).select(e.mul(h).negate(),e.mul(h)),0)),a.addAssign(Xp(n.mul(h),0)),Pp(ox.y.greaterThan(1).or(ox.y.lessThan(0)),(()=>{a.subAssign(Xp(n.mul(2).mul(h),0))}))),m.assign(Oy.mul(a));const u=jp().toVar();u.assign(ox.y.lessThan(.5).select(c,d)),m.z.assign(u.z.mul(m.w))}else{const e=Dp(p.y,p.x.negate()).toVar("offset");p.x.assign(p.x.div(a)),e.x.assign(e.x.div(a)),e.assign(ox.x.lessThan(0).select(e.negate(),e)),Pp(ox.y.lessThan(0),(()=>{e.assign(e.sub(p))})).ElseIf(ox.y.greaterThan(1),(()=>{e.assign(e.add(p))})),e.assign(e.mul(Xb)),e.assign(e.div(Wv.w)),m.assign(ox.y.lessThan(.5).select(u,l)),e.assign(e.mul(m.w)),m.assign(m.add(Xp(e,0,0)))}return m}))();const o=Rp((({p1:e,p2:t,p3:s,p4:i})=>{const r=e.sub(s),n=i.sub(s),o=t.sub(e),a=r.dot(n),h=n.dot(o),u=r.dot(o),l=n.dot(n),c=o.dot(o).mul(l).sub(h.mul(h)),d=a.mul(h).sub(u.mul(l)).div(c).clamp(),p=a.add(h.mul(d)).div(l).clamp();return Dp(d,p)}));this.fragmentNode=Rp((()=>{const n=My();if(i){const e=this.offsetNode?Up(this.offsetNodeNode):Yb,t=this.dashScaleNode?Up(this.dashScaleNode):Hb,s=this.dashSizeNode?Up(this.dashSizeNode):qb,i=this.dashSizeNode?Up(this.dashGapNode):$b;Um.assign(s),Om.assign(i);const r=Sy("instanceDistanceStart"),o=Sy("instanceDistanceEnd"),a=ox.y.lessThan(.5).select(t.mul(r),Hb.mul(o)),h=Vf(a.add(Yb)),u=e?h.add(e):h;n.y.lessThan(-1).or(n.y.greaterThan(1)).discard(),u.mod(Um.add(Om)).greaterThan(Um).discard()}const a=Up(1).toVar("alpha");if(r){const s=fm("vec3","worldStart"),r=fm("vec3","worldEnd"),n=fm("vec4","worldPos").xyz.normalize().mul(1e5),h=r.sub(s),u=o({p1:s,p2:r,p3:jp(0,0,0),p4:n}),l=s.add(h.mul(u.x)),c=n.mul(u.y),d=l.sub(c).length().div(Xb);if(!i)if(t&&e.samples>1){const e=d.fwidth();a.assign(Mf(e.negate().add(.5),e.add(.5),d).oneMinus())}else d.greaterThan(.5).discard()}else if(t&&e.samples>1){const e=n.x,t=n.y.greaterThan(0).select(n.y.sub(1),n.y.add(1)),s=e.mul(e).add(t.mul(t)),i=Up(s.fwidth()).toVar("dlen");Pp(n.y.abs().greaterThan(1),(()=>{a.assign(Mf(i.oneMinus(),i.add(1),s).oneMinus())}))}else Pp(n.y.abs().greaterThan(1),(()=>{const e=n.x,t=n.y.greaterThan(0).select(n.y.sub(1),n.y.add(1));e.mul(e).add(t.mul(t)).greaterThan(1).discard()}));let h;if(this.lineColorNode)h=this.lineColorNode;else if(s){const e=Sy("instanceColorStart"),t=Sy("instanceColorEnd");h=ox.y.lessThan(.5).select(e,t).mul(xb)}else h=xb;return Xp(h,a)}))()}get worldUnits(){return this.useWorldUnits}set worldUnits(e){this.useWorldUnits!==e&&(this.useWorldUnits=e,this.needsUpdate=!0)}get dashed(){return this.useDash}set dashed(e){this.useDash!==e&&(this.useDash=e,this.needsUpdate=!0)}get alphaToCoverage(){return this.useAlphaToCoverage}set alphaToCoverage(e){this.useAlphaToCoverage!==e&&(this.useAlphaToCoverage=e,this.needsUpdate=!0)}}const _T=e=>Sp(e).mul(.5).add(.5),wT=e=>Sp(e).mul(2).sub(1),ST=new Nu;class MT extends pT{static get type(){return"MeshNormalNodeMaterial"}constructor(e){super(),this.lights=!1,this.isMeshNormalNodeMaterial=!0,this.setDefaultValues(ST),this.setValues(e)}setupDiffuseColor(){const e=this.opacityNode?Up(this.opacityNode):Tb;ym.assign(Xp(_T(Tx),e))}}class NT extends kd{static get type(){return"EquirectUVNode"}constructor(e=lx){super("vec2"),this.dirNode=e}setup(){const e=this.dirNode,t=e.z.atan2(e.x).mul(1/(2*Math.PI)).add(.5),s=e.y.clamp(-1,1).asin().mul(1/Math.PI).add(.5);return Dp(t,s)}}const AT=Ap(NT);class CT extends Kn{constructor(e=1,t={}){super(e,t),this.isCubeRenderTarget=!0}fromEquirectangularTexture(e,t){const s=t.minFilter,i=t.generateMipmaps;t.generateMipmaps=!0,this.texture.type=t.type,this.texture.colorSpace=t.colorSpace,this.texture.generateMipmaps=t.generateMipmaps,this.texture.minFilter=t.minFilter,this.texture.magFilter=t.magFilter;const r=new kn(5,5,5),n=AT(lx),o=new pT;o.colorNode=By(t,n,0),o.side=d,o.blending=m;const a=new Vn(r,o),h=new to;h.add(a),t.minFilter===Se&&(t.minFilter=Te);const u=new Zn(1,10,this),l=e.getMRT();return e.setMRT(null),u.update(e,h),e.setMRT(l),t.minFilter=s,t.currentGenerateMipmaps=i,a.geometry.dispose(),a.material.dispose(),this}}const RT=new WeakMap;class ET extends kd{static get type(){return"CubeMapNode"}constructor(e){super("vec3"),this.envNode=e,this._cubeTexture=null,this._cubeTextureNode=Ix();const t=new Jn;t.isRenderTargetTexture=!0,this._defaultTexture=t,this.updateBeforeType=Bd.RENDER}updateBefore(e){const{renderer:t,material:s}=e,i=this.envNode;if(i.isTextureNode||i.isMaterialReferenceNode){const e=i.isTextureNode?i.value:s[i.property];if(e&&e.isTexture){const s=e.mapping;if(s===le||s===ce){if(RT.has(e)){const t=RT.get(e);IT(t,e.mapping),this._cubeTexture=t}else{const s=e.image;if(function(e){return null!=e&&e.height>0}(s)){const i=new CT(s.height);i.fromEquirectangularTexture(t,e),IT(i.texture,e.mapping),this._cubeTexture=i.texture,RT.set(e,i.texture),e.addEventListener("dispose",BT)}else this._cubeTexture=this._defaultTexture}this._cubeTextureNode.value=this._cubeTexture}else this._cubeTextureNode=this.envNode}}}setup(e){return this.updateBefore(e),this._cubeTextureNode}}function BT(e){const t=e.target;t.removeEventListener("dispose",BT);const s=RT.get(t);void 0!==s&&(RT.delete(t),s.dispose())}function IT(e,t){t===le?e.mapping=he:t===ce&&(e.mapping=ue)}const PT=Ap(ET);class FT extends Iv{static get type(){return"BasicEnvironmentNode"}constructor(e=null){super(),this.envNode=e}setup(e){e.context.environment=PT(this.envNode)}}class zT extends Iv{static get type(){return"BasicLightMapNode"}constructor(e=null){super(),this.lightMapNode=e}setup(e){const t=Up(1/Math.PI);e.context.irradianceLightMap=this.lightMapNode.mul(t)}}class UT{start(){}finish(){}direct(){}directRectArea(){}indirect(){}ambientOcclusion(){}}class OT extends UT{constructor(){super()}indirect(e,t,s){const i=e.ambientOcclusion,r=e.reflectedLight,n=s.context.irradianceLightMap;r.indirectDiffuse.assign(Xp(0)),n?r.indirectDiffuse.addAssign(n):r.indirectDiffuse.addAssign(Xp(1,1,1,0)),r.indirectDiffuse.mulAssign(i),r.indirectDiffuse.mulAssign(ym.rgb)}finish(e,t,s){const i=s.material,r=e.outgoingLight,n=s.context.environment;if(n)switch(i.combine){case 0:r.rgb.assign(Tf(r.rgb,r.rgb.mul(n.rgb),Mb.mul(Nb)));break;case 1:r.rgb.assign(Tf(r.rgb,n.rgb,Mb.mul(Nb)));break;case 2:r.rgb.addAssign(n.rgb.mul(Mb.mul(Nb)));break;default:console.warn("THREE.BasicLightingModel: Unsupported .combine value:",i.combine)}}}const LT=new tn;class VT extends pT{static get type(){return"MeshBasicNodeMaterial"}constructor(e){super(),this.isMeshBasicNodeMaterial=!0,this.lights=!0,this.setDefaultValues(LT),this.setValues(e)}setupNormal(){return bx}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new FT(t):null}setupLightMap(e){let t=null;return e.material.lightMap&&(t=new zT(Kb)),t}setupOutgoingLight(){return ym.rgb}setupLightingModel(){return new OT}}const DT=Rp((({f0:e,f90:t,dotVH:s})=>{const i=s.mul(-5.55473).sub(6.98316).mul(s).exp2();return e.mul(i.oneMinus()).add(t.mul(i))})),kT=Rp((e=>e.diffuseColor.mul(1/Math.PI))),GT=Rp((({dotNH:e})=>Fm.mul(Up(.5)).add(1).mul(Up(1/Math.PI)).mul(e.pow(Fm)))),WT=Rp((({lightDirection:e})=>{const t=e.add(dx).normalize(),s=Tx.dot(t).clamp(),i=dx.dot(t).clamp(),r=DT({f0:Im,f90:1,dotVH:i}),n=Up(.25),o=GT({dotNH:s});return r.mul(n).mul(o)}));class jT extends OT{constructor(e=!0){super(),this.specular=e}direct({lightDirection:e,lightColor:t,reflectedLight:s}){const i=Tx.dot(e).clamp().mul(t);s.directDiffuse.addAssign(i.mul(kT({diffuseColor:ym.rgb}))),!0===this.specular&&s.directSpecular.addAssign(i.mul(WT({lightDirection:e})).mul(Mb))}indirect({ambientOcclusion:e,irradiance:t,reflectedLight:s}){s.indirectDiffuse.addAssign(t.mul(kT({diffuseColor:ym}))),s.indirectDiffuse.mulAssign(e)}}const HT=new Au;class qT extends pT{static get type(){return"MeshLambertNodeMaterial"}constructor(e){super(),this.isMeshLambertNodeMaterial=!0,this.lights=!0,this.setDefaultValues(HT),this.setValues(e)}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new FT(t):null}setupLightingModel(){return new jT(!1)}}const $T=new Su;class XT extends pT{static get type(){return"MeshPhongNodeMaterial"}constructor(e){super(),this.isMeshPhongNodeMaterial=!0,this.lights=!0,this.shininessNode=null,this.specularNode=null,this.setDefaultValues($T),this.setValues(e)}setupEnvironment(e){const t=super.setupEnvironment(e);return t?new FT(t):null}setupLightingModel(){return new jT}setupVariants(){const e=(this.shininessNode?Up(this.shininessNode):bb).max(1e-4);Fm.assign(e);const t=this.specularNode||_b;Im.assign(t)}copy(e){return this.shininessNode=e.shininessNode,this.specularNode=e.specularNode,super.copy(e)}}const YT=Rp((()=>{const e=bx.dFdx().abs().max(bx.dFdy().abs());return e.x.max(e.y).max(e.z)})),ZT=Rp((e=>{const{roughness:t}=e,s=YT();let i=t.max(.0525);return i=i.add(s),i=i.min(1),i})),JT=Rp((({alpha:e,dotNL:t,dotNV:s})=>{const i=e.pow2(),r=t.mul(i.add(i.oneMinus().mul(s.pow2())).sqrt()),n=s.mul(i.add(i.oneMinus().mul(t.pow2())).sqrt());return Qm(.5,r.add(n).max(bg))})).setLayout({name:"V_GGX_SmithCorrelated",type:"float",inputs:[{name:"alpha",type:"float"},{name:"dotNL",type:"float"},{name:"dotNV",type:"float"}]}),KT=Rp((({alphaT:e,alphaB:t,dotTV:s,dotBV:i,dotTL:r,dotBL:n,dotNV:o,dotNL:a})=>{const h=a.mul(jp(e.mul(s),t.mul(i),o).length()),u=o.mul(jp(e.mul(r),t.mul(n),a).length());return Qm(.5,h.add(u)).saturate()})).setLayout({name:"V_GGX_SmithCorrelated_Anisotropic",type:"float",inputs:[{name:"alphaT",type:"float",qualifier:"in"},{name:"alphaB",type:"float",qualifier:"in"},{name:"dotTV",type:"float",qualifier:"in"},{name:"dotBV",type:"float",qualifier:"in"},{name:"dotTL",type:"float",qualifier:"in"},{name:"dotBL",type:"float",qualifier:"in"},{name:"dotNV",type:"float",qualifier:"in"},{name:"dotNL",type:"float",qualifier:"in"}]}),QT=Rp((({alpha:e,dotNH:t})=>{const s=e.pow2(),i=t.pow2().mul(s.oneMinus()).oneMinus();return s.div(i.pow2()).mul(1/Math.PI)})).setLayout({name:"D_GGX",type:"float",inputs:[{name:"alpha",type:"float"},{name:"dotNH",type:"float"}]}),e_=Up(1/Math.PI),t_=Rp((({alphaT:e,alphaB:t,dotNH:s,dotTH:i,dotBH:r})=>{const n=e.mul(t),o=jp(t.mul(i),e.mul(r),n.mul(s)),a=o.dot(o),h=n.div(a);return e_.mul(n.mul(h.pow2()))})).setLayout({name:"D_GGX_Anisotropic",type:"float",inputs:[{name:"alphaT",type:"float",qualifier:"in"},{name:"alphaB",type:"float",qualifier:"in"},{name:"dotNH",type:"float",qualifier:"in"},{name:"dotTH",type:"float",qualifier:"in"},{name:"dotBH",type:"float",qualifier:"in"}]}),s_=Rp((e=>{const{lightDirection:t,f0:s,f90:i,roughness:r,f:n,USE_IRIDESCENCE:o,USE_ANISOTROPY:a}=e,h=e.normalView||Tx,u=r.pow2(),l=t.add(dx).normalize(),c=h.dot(t).clamp(),d=h.dot(dx).clamp(),p=h.dot(l).clamp(),m=dx.dot(l).clamp();let g,f,y=DT({f0:s,f90:i,dotVH:m});if(Tp(o)&&(y=Mm.mix(y,n)),Tp(a)){const e=Em.dot(t),s=Em.dot(dx),i=Em.dot(l),r=Bm.dot(t),n=Bm.dot(dx),o=Bm.dot(l);g=KT({alphaT:Cm,alphaB:u,dotTV:s,dotBV:n,dotTL:e,dotBL:r,dotNV:d,dotNL:c}),f=t_({alphaT:Cm,alphaB:u,dotNH:p,dotTH:i,dotBH:o})}else g=JT({alpha:u,dotNL:c,dotNV:d}),f=QT({alpha:u,dotNH:p});return y.mul(g).mul(f)})),i_=Rp((({roughness:e,dotNV:t})=>{const s=Xp(-1,-.0275,-.572,.022),i=Xp(1,.0425,1.04,-.04),r=e.mul(s).add(i),n=r.x.mul(r.x).min(t.mul(-9.28).exp2()).mul(r.x).add(r.y);return Dp(-1.04,1.04).mul(n).add(r.zw)})).setLayout({name:"DFGApprox",type:"vec2",inputs:[{name:"roughness",type:"float"},{name:"dotNV",type:"vec3"}]}),r_=Rp((e=>{const{dotNV:t,specularColor:s,specularF90:i,roughness:r}=e,n=i_({dotNV:t,roughness:r});return s.mul(n.x).add(i.mul(n.y))})),n_=Rp((({f:e,f90:t,dotVH:s})=>{const i=s.oneMinus().saturate(),r=i.mul(i),n=i.mul(r,r).clamp(0,.9999);return e.sub(jp(t).mul(n)).div(n.oneMinus())})).setLayout({name:"Schlick_to_F0",type:"vec3",inputs:[{name:"f",type:"vec3"},{name:"f90",type:"float"},{name:"dotVH",type:"float"}]}),o_=Rp((({roughness:e,dotNH:t})=>{const s=e.pow2(),i=Up(1).div(s),r=t.pow2().oneMinus().max(.0078125);return Up(2).add(i).mul(r.pow(i.mul(.5))).div(2*Math.PI)})).setLayout({name:"D_Charlie",type:"float",inputs:[{name:"roughness",type:"float"},{name:"dotNH",type:"float"}]}),a_=Rp((({dotNV:e,dotNL:t})=>Up(1).div(Up(4).mul(t.add(e).sub(t.mul(e)))))).setLayout({name:"V_Neubelt",type:"float",inputs:[{name:"dotNV",type:"float"},{name:"dotNL",type:"float"}]}),h_=Rp((({lightDirection:e})=>{const t=e.add(dx).normalize(),s=Tx.dot(e).clamp(),i=Tx.dot(dx).clamp(),r=Tx.dot(t).clamp(),n=o_({roughness:Sm,dotNH:r}),o=a_({dotNV:i,dotNL:s});return wm.mul(n).mul(o)})),u_=Rp((({N:e,V:t,roughness:s})=>{const i=e.dot(t).saturate(),r=Dp(s,i.oneMinus().sqrt());return r.assign(r.mul(.984375).add(.0078125)),r})).setLayout({name:"LTC_Uv",type:"vec2",inputs:[{name:"N",type:"vec3"},{name:"V",type:"vec3"},{name:"roughness",type:"float"}]}),l_=Rp((({f:e})=>{const t=e.length();return of(t.mul(t).add(e.z).div(t.add(1)),0)})).setLayout({name:"LTC_ClippedSphereFormFactor",type:"float",inputs:[{name:"f",type:"vec3"}]}),c_=Rp((({v1:e,v2:t})=>{const s=e.dot(t),i=s.abs().toVar(),r=i.mul(.0145206).add(.4965155).mul(i).add(.8543985).toVar(),n=i.add(4.1616724).mul(i).add(3.417594).toVar(),o=r.div(n),a=s.greaterThan(0).select(o,of(s.mul(s).oneMinus(),1e-7).inverseSqrt().mul(.5).sub(o));return e.cross(t).mul(a)})).setLayout({name:"LTC_EdgeVectorFormFactor",type:"vec3",inputs:[{name:"v1",type:"vec3"},{name:"v2",type:"vec3"}]}),d_=Rp((({N:e,V:t,P:s,mInv:i,p0:r,p1:n,p2:o,p3:a})=>{const h=n.sub(r).toVar(),u=a.sub(r).toVar(),l=h.cross(u),c=jp().toVar();return Pp(l.dot(s.sub(r)).greaterThanEqual(0),(()=>{const h=t.sub(e.mul(t.dot(e))).normalize(),u=e.cross(h).negate(),l=i.mul(Qp(h,u,e).transpose()).toVar(),d=l.mul(r.sub(s)).normalize().toVar(),p=l.mul(n.sub(s)).normalize().toVar(),m=l.mul(o.sub(s)).normalize().toVar(),g=l.mul(a.sub(s)).normalize().toVar(),f=jp(0).toVar();f.addAssign(c_({v1:d,v2:p})),f.addAssign(c_({v1:p,v2:m})),f.addAssign(c_({v1:m,v2:g})),f.addAssign(c_({v1:g,v2:d})),c.assign(jp(l_({f:f})))})),c})).setLayout({name:"LTC_Evaluate",type:"vec3",inputs:[{name:"N",type:"vec3"},{name:"V",type:"vec3"},{name:"P",type:"vec3"},{name:"mInv",type:"mat3"},{name:"p0",type:"vec3"},{name:"p1",type:"vec3"},{name:"p2",type:"vec3"},{name:"p3",type:"vec3"}]}),p_=1/6,m_=e=>Km(p_,Km(e,Km(e,e.negate().add(3)).sub(3)).add(1)),g_=e=>Km(p_,Km(e,Km(e,Km(3,e).sub(6))).add(4)),f_=e=>Km(p_,Km(e,Km(e,Km(-3,e).add(3)).add(3)).add(1)),y_=e=>Km(p_,mf(e,3)),x_=e=>m_(e).add(g_(e)),b_=e=>f_(e).add(y_(e)),v_=e=>Zm(-1,g_(e).div(m_(e).add(g_(e)))),T_=e=>Zm(1,y_(e).div(f_(e).add(y_(e)))),__=(e,t,s)=>{const i=e.uvNode,r=Km(i,t.zw).add(.5),n=Fg(r),o=Og(r),a=x_(o.x),h=b_(o.x),u=v_(o.x),l=T_(o.x),c=v_(o.y),d=T_(o.y),p=Dp(n.x.add(u),n.y.add(c)).sub(.5).mul(t.xy),m=Dp(n.x.add(l),n.y.add(c)).sub(.5).mul(t.xy),g=Dp(n.x.add(u),n.y.add(d)).sub(.5).mul(t.xy),f=Dp(n.x.add(l),n.y.add(d)).sub(.5).mul(t.xy),y=x_(o.y).mul(Zm(a.mul(e.uv(p).level(s)),h.mul(e.uv(m).level(s)))),x=b_(o.y).mul(Zm(a.mul(e.uv(g).level(s)),h.mul(e.uv(f).level(s))));return y.add(x)},w_=Rp((([e,t=Up(3)])=>{const s=Dp(e.size(Op(t))),i=Dp(e.size(Op(t.add(1)))),r=Qm(1,s),n=Qm(1,i),o=__(e,Xp(r,s),Fg(t)),a=__(e,Xp(n,i),zg(t));return Og(t).mix(o,a)})),S_=Rp((([e,t,s,i,r])=>{const n=jp(Sf(t.negate(),Ug(e),Qm(1,i))),o=jp(qg(r[0].xyz),qg(r[1].xyz),qg(r[2].xyz));return Ug(n).mul(s.mul(o))})).setLayout({name:"getVolumeTransmissionRay",type:"vec3",inputs:[{name:"n",type:"vec3"},{name:"v",type:"vec3"},{name:"thickness",type:"float"},{name:"ior",type:"float"},{name:"modelMatrix",type:"mat4"}]}),M_=Rp((([e,t])=>e.mul(_f(t.mul(2).sub(2),0,1)))).setLayout({name:"applyIorToRoughness",type:"float",inputs:[{name:"roughness",type:"float"},{name:"ior",type:"float"}]}),N_=Qv(),A_=Rp((([e,t,s])=>{const i=N_.uv(e),r=Bg(Up(kv.x)).mul(M_(t,s));return w_(i,r)})),C_=Rp((([e,t,s])=>(Pp(s.notEqual(0),(()=>{const i=Eg(t).negate().div(s);return Cg(i.negate().mul(e))})),jp(1)))).setLayout({name:"volumeAttenuation",type:"vec3",inputs:[{name:"transmissionDistance",type:"float"},{name:"attenuationColor",type:"vec3"},{name:"attenuationDistance",type:"float"}]}),R_=Rp((([e,t,s,i,r,n,o,a,h,u,l,c,d,p,m])=>{let g,f;if(m){g=Xp().toVar(),f=jp().toVar();const r=l.sub(1).mul(m.mul(.025)),n=jp(l.sub(r),l,l.add(r));bv({start:0,end:3},(({i:r})=>{const l=n.element(r),m=S_(e,t,c,l,a),y=o.add(m),x=u.mul(h.mul(Xp(y,1))),b=Dp(x.xy.div(x.w)).toVar();b.addAssign(1),b.divAssign(2),b.assign(Dp(b.x,b.y.oneMinus()));const v=A_(b,s,l);g.element(r).assign(v.element(r)),g.a.addAssign(v.a),f.element(r).assign(i.element(r).mul(C_(qg(m),d,p).element(r)))})),g.a.divAssign(3)}else{const r=S_(e,t,c,l,a),n=o.add(r),m=u.mul(h.mul(Xp(n,1))),y=Dp(m.xy.div(m.w)).toVar();y.addAssign(1),y.divAssign(2),y.assign(Dp(y.x,y.y.oneMinus())),g=A_(y,s,l),f=i.mul(C_(qg(r),d,p))}const y=f.rgb.mul(g.rgb),x=e.dot(t).clamp(),b=jp(r_({dotNV:x,specularColor:r,specularF90:n,roughness:s})),v=f.r.add(f.g,f.b).div(3);return Xp(b.oneMinus().mul(y),g.a.oneMinus().mul(v).oneMinus())})),E_=Qp(3.2404542,-.969266,.0556434,-1.5371385,1.8760108,-.2040259,-.4985314,.041556,1.0572252),B_=(e,t)=>e.sub(t).div(e.add(t)).pow2(),I_=(e,t)=>{const s=e.mul(2*Math.PI*1e-9),i=jp(54856e-17,44201e-17,52481e-17),r=jp(1681e3,1795300,2208400),n=jp(43278e5,93046e5,66121e5),o=Up(9747e-17*Math.sqrt(2*Math.PI*45282e5)).mul(s.mul(2239900).add(t.x).cos()).mul(s.pow2().mul(-45282e5).exp());let a=i.mul(n.mul(2*Math.PI).sqrt()).mul(r.mul(s).add(t).cos()).mul(s.pow2().negate().mul(n).exp());a=jp(a.x.add(o),a.y,a.z).div(1.0685e-7);return E_.mul(a)},P_=Rp((({outsideIOR:e,eta2:t,cosTheta1:s,thinFilmThickness:i,baseF0:r})=>{const n=Tf(e,t,Mf(0,.03,i)),o=e.div(n).pow2().mul(Up(1).sub(s.pow2())),a=Up(1).sub(o).sqrt(),h=B_(n,e),u=DT({f0:h,f90:1,dotVH:s}),l=u.oneMinus(),c=n.lessThan(e).select(Math.PI,0),d=Up(Math.PI).sub(c),p=(e=>{const t=e.sqrt();return jp(1).add(t).div(jp(1).sub(t))})(r.clamp(0,.9999)),m=B_(p,n.toVec3()),g=DT({f0:m,f90:1,dotVH:a}),f=jp(p.x.lessThan(n).select(Math.PI,0),p.y.lessThan(n).select(Math.PI,0),p.z.lessThan(n).select(Math.PI,0)),y=n.mul(i,a,2),x=jp(d).add(f),b=u.mul(g).clamp(1e-5,.9999),v=b.sqrt(),T=l.pow2().mul(g).div(jp(1).sub(b));let _=u.add(T),w=T.sub(l);for(let e=1;e<=2;++e){w=w.mul(v);const t=I_(Up(e).mul(y),Up(e).mul(x)).mul(2);_=_.add(w.mul(t))}return _.max(jp(0))})).setLayout({name:"evalIridescence",type:"vec3",inputs:[{name:"outsideIOR",type:"float"},{name:"eta2",type:"float"},{name:"cosTheta1",type:"float"},{name:"thinFilmThickness",type:"float"},{name:"baseF0",type:"vec3"}]}),F_=Rp((({normal:e,viewDir:t,roughness:s})=>{const i=e.dot(t).saturate(),r=s.pow2(),n=Bf(s.lessThan(.25),Up(-339.2).mul(r).add(Up(161.4).mul(s)).sub(25.9),Up(-8.48).mul(r).add(Up(14.3).mul(s)).sub(9.95)),o=Bf(s.lessThan(.25),Up(44).mul(r).sub(Up(23.7).mul(s)).add(3.26),Up(1.97).mul(r).sub(Up(3.27).mul(s)).add(.72));return Bf(s.lessThan(.25),0,Up(.1).mul(s).sub(.025)).add(n.mul(i).add(o).exp()).mul(1/Math.PI).saturate()})),z_=jp(.04),U_=Up(1);class O_ extends UT{constructor(e=!1,t=!1,s=!1,i=!1,r=!1,n=!1){super(),this.clearcoat=e,this.sheen=t,this.iridescence=s,this.anisotropy=i,this.transmission=r,this.dispersion=n,this.clearcoatRadiance=null,this.clearcoatSpecularDirect=null,this.clearcoatSpecularIndirect=null,this.sheenSpecularDirect=null,this.sheenSpecularIndirect=null,this.iridescenceFresnel=null,this.iridescenceF0=null}start(e){if(!0===this.clearcoat&&(this.clearcoatRadiance=jp().toVar("clearcoatRadiance"),this.clearcoatSpecularDirect=jp().toVar("clearcoatSpecularDirect"),this.clearcoatSpecularIndirect=jp().toVar("clearcoatSpecularIndirect")),!0===this.sheen&&(this.sheenSpecularDirect=jp().toVar("sheenSpecularDirect"),this.sheenSpecularIndirect=jp().toVar("sheenSpecularIndirect")),!0===this.iridescence){const e=Tx.dot(dx).clamp();this.iridescenceFresnel=P_({outsideIOR:Up(1),eta2:Nm,cosTheta1:e,thinFilmThickness:Am,baseF0:Im}),this.iridescenceF0=n_({f:this.iridescenceFresnel,f90:1,dotVH:e})}if(!0===this.transmission){const t=ux,s=Gy.sub(ux).normalize(),i=_x;e.backdrop=R_(i,s,bm,ym,Im,Pm,t,Jy,Vy,Oy,Vm,km,Wm,Gm,this.dispersion?jm:null),e.backdropAlpha=Dm,ym.a.mulAssign(Tf(1,e.backdrop.a,Dm))}}computeMultiscattering(e,t,s){const i=Tx.dot(dx).clamp(),r=i_({roughness:bm,dotNV:i}),n=(this.iridescenceF0?Mm.mix(Im,this.iridescenceF0):Im).mul(r.x).add(s.mul(r.y)),o=r.x.add(r.y).oneMinus(),a=Im.add(Im.oneMinus().mul(.047619)),h=n.mul(a).div(o.mul(a).oneMinus());e.addAssign(n),t.addAssign(h.mul(o))}direct({lightDirection:e,lightColor:t,reflectedLight:s}){const i=Tx.dot(e).clamp().mul(t);if(!0===this.sheen&&this.sheenSpecularDirect.addAssign(i.mul(h_({lightDirection:e}))),!0===this.clearcoat){const s=wx.dot(e).clamp().mul(t);this.clearcoatSpecularDirect.addAssign(s.mul(s_({lightDirection:e,f0:z_,f90:U_,roughness:_m,normalView:wx})))}s.directDiffuse.addAssign(i.mul(kT({diffuseColor:ym.rgb}))),s.directSpecular.addAssign(i.mul(s_({lightDirection:e,f0:Im,f90:1,roughness:bm,iridescence:this.iridescence,f:this.iridescenceFresnel,USE_IRIDESCENCE:this.iridescence,USE_ANISOTROPY:this.anisotropy})))}directRectArea({lightColor:e,lightPosition:t,halfWidth:s,halfHeight:i,reflectedLight:r,ltc_1:n,ltc_2:o}){const a=t.add(s).sub(i),h=t.sub(s).sub(i),u=t.sub(s).add(i),l=t.add(s).add(i),c=Tx,d=dx,p=cx.toVar(),m=u_({N:c,V:d,roughness:bm}),g=n.uv(m).toVar(),f=o.uv(m).toVar(),y=Qp(jp(g.x,0,g.y),jp(0,1,0),jp(g.z,0,g.w)).toVar(),x=Im.mul(f.x).add(Im.oneMinus().mul(f.y)).toVar();r.directSpecular.addAssign(e.mul(x).mul(d_({N:c,V:d,P:p,mInv:y,p0:a,p1:h,p2:u,p3:l}))),r.directDiffuse.addAssign(e.mul(ym).mul(d_({N:c,V:d,P:p,mInv:Qp(1,0,0,0,1,0,0,0,1),p0:a,p1:h,p2:u,p3:l})))}indirect(e,t,s){this.indirectDiffuse(e,t,s),this.indirectSpecular(e,t,s),this.ambientOcclusion(e,t,s)}indirectDiffuse({irradiance:e,reflectedLight:t}){t.indirectDiffuse.addAssign(e.mul(kT({diffuseColor:ym})))}indirectSpecular({radiance:e,iblIrradiance:t,reflectedLight:s}){if(!0===this.sheen&&this.sheenSpecularIndirect.addAssign(t.mul(wm,F_({normal:Tx,viewDir:dx,roughness:Sm}))),!0===this.clearcoat){const e=wx.dot(dx).clamp(),t=r_({dotNV:e,specularColor:z_,specularF90:U_,roughness:_m});this.clearcoatSpecularIndirect.addAssign(this.clearcoatRadiance.mul(t))}const i=jp().toVar("singleScattering"),r=jp().toVar("multiScattering"),n=t.mul(1/Math.PI);this.computeMultiscattering(i,r,Pm);const o=i.add(r),a=ym.mul(o.r.max(o.g).max(o.b).oneMinus());s.indirectSpecular.addAssign(e.mul(i)),s.indirectSpecular.addAssign(r.mul(n)),s.indirectDiffuse.addAssign(a.mul(n))}ambientOcclusion({ambientOcclusion:e,reflectedLight:t}){const s=Tx.dot(dx).clamp().add(e),i=bm.mul(-16).oneMinus().negate().exp2(),r=e.sub(s.pow(i).oneMinus()).clamp();!0===this.clearcoat&&this.clearcoatSpecularIndirect.mulAssign(e),!0===this.sheen&&this.sheenSpecularIndirect.mulAssign(e),t.indirectDiffuse.mulAssign(e),t.indirectSpecular.mulAssign(r)}finish(e){const{outgoingLight:t}=e;if(!0===this.clearcoat){const e=wx.dot(dx).clamp(),s=DT({dotVH:e,f0:z_,f90:U_}),i=t.mul(Tm.mul(s).oneMinus()).add(this.clearcoatSpecularDirect.add(this.clearcoatSpecularIndirect).mul(Tm));t.assign(i)}if(!0===this.sheen){const e=wm.r.max(wm.g).max(wm.b).mul(.157).oneMinus(),s=t.mul(e).add(this.sheenSpecularDirect,this.sheenSpecularIndirect);t.assign(s)}}}const L_=Up(1),V_=Up(-2),D_=Up(.8),k_=Up(-1),G_=Up(.4),W_=Up(2),j_=Up(.305),H_=Up(3),q_=Up(.21),$_=Up(4),X_=Up(4),Y_=Up(16),Z_=Rp((([e])=>{const t=jp(jg(e)).toVar(),s=Up(-1).toVar();return Pp(t.x.greaterThan(t.z),(()=>{Pp(t.x.greaterThan(t.y),(()=>{s.assign(Bf(e.x.greaterThan(0),0,3))})).Else((()=>{s.assign(Bf(e.y.greaterThan(0),1,4))}))})).Else((()=>{Pp(t.z.greaterThan(t.y),(()=>{s.assign(Bf(e.z.greaterThan(0),2,5))})).Else((()=>{s.assign(Bf(e.y.greaterThan(0),1,4))}))})),s})).setLayout({name:"getFace",type:"float",inputs:[{name:"direction",type:"vec3"}]}),J_=Rp((([e,t])=>{const s=Dp().toVar();return Pp(t.equal(0),(()=>{s.assign(Dp(e.z,e.y).div(jg(e.x)))})).ElseIf(t.equal(1),(()=>{s.assign(Dp(e.x.negate(),e.z.negate()).div(jg(e.y)))})).ElseIf(t.equal(2),(()=>{s.assign(Dp(e.x.negate(),e.y).div(jg(e.z)))})).ElseIf(t.equal(3),(()=>{s.assign(Dp(e.z.negate(),e.y).div(jg(e.x)))})).ElseIf(t.equal(4),(()=>{s.assign(Dp(e.x.negate(),e.z).div(jg(e.y)))})).Else((()=>{s.assign(Dp(e.x,e.y).div(jg(e.z)))})),Km(.5,s.add(1))})).setLayout({name:"getUV",type:"vec2",inputs:[{name:"direction",type:"vec3"},{name:"face",type:"float"}]}),K_=Rp((([e])=>{const t=Up(0).toVar();return Pp(e.greaterThanEqual(D_),(()=>{t.assign(L_.sub(e).mul(k_.sub(V_)).div(L_.sub(D_)).add(V_))})).ElseIf(e.greaterThanEqual(G_),(()=>{t.assign(D_.sub(e).mul(W_.sub(k_)).div(D_.sub(G_)).add(k_))})).ElseIf(e.greaterThanEqual(j_),(()=>{t.assign(G_.sub(e).mul(H_.sub(W_)).div(G_.sub(j_)).add(W_))})).ElseIf(e.greaterThanEqual(q_),(()=>{t.assign(j_.sub(e).mul($_.sub(H_)).div(j_.sub(q_)).add(H_))})).Else((()=>{t.assign(Up(-2).mul(Bg(Km(1.16,e))))})),t})).setLayout({name:"roughnessToMip",type:"float",inputs:[{name:"roughness",type:"float"}]}),Q_=Rp((([e,t])=>{const s=e.toVar();s.assign(Km(2,s).sub(1));const i=jp(s,1).toVar();return Pp(t.equal(0),(()=>{i.assign(i.zyx)})).ElseIf(t.equal(1),(()=>{i.assign(i.xzy),i.xz.mulAssign(-1)})).ElseIf(t.equal(2),(()=>{i.x.mulAssign(-1)})).ElseIf(t.equal(3),(()=>{i.assign(i.zyx),i.xz.mulAssign(-1)})).ElseIf(t.equal(4),(()=>{i.assign(i.xzy),i.xy.mulAssign(-1)})).ElseIf(t.equal(5),(()=>{i.z.mulAssign(-1)})),i})).setLayout({name:"getDirection",type:"vec3",inputs:[{name:"uv",type:"vec2"},{name:"face",type:"float"}]}),ew=Rp((([e,t,s,i,r,n])=>{const o=Up(s),a=jp(t),h=_f(K_(o),V_,n),u=Og(h),l=Fg(h),c=jp(tw(e,a,l,i,r,n)).toVar();return Pp(u.notEqual(0),(()=>{const t=jp(tw(e,a,l.add(1),i,r,n)).toVar();c.assign(Tf(c,t,u))})),c})),tw=Rp((([e,t,s,i,r,n])=>{const o=Up(s).toVar(),a=jp(t),h=Up(Z_(a)).toVar(),u=Up(of(X_.sub(o),0)).toVar();o.assign(of(o,X_));const l=Up(Rg(o)).toVar(),c=Dp(J_(a,h).mul(l.sub(2)).add(1)).toVar();return Pp(h.greaterThan(2),(()=>{c.y.addAssign(l),h.subAssign(3)})),c.x.addAssign(h.mul(l)),c.x.addAssign(u.mul(Km(3,Y_))),c.y.addAssign(Km(4,Rg(n).sub(l))),c.x.mulAssign(i),c.y.mulAssign(r),e.uv(c).grad(Dp(),Dp())})),sw=Rp((({envMap:e,mipInt:t,outputDirection:s,theta:i,axis:r,CUBEUV_TEXEL_WIDTH:n,CUBEUV_TEXEL_HEIGHT:o,CUBEUV_MAX_MIP:a})=>{const h=Vg(i),u=s.mul(h).add(r.cross(s).mul(Lg(i))).add(r.mul(r.dot(s).mul(h.oneMinus())));return tw(e,u,t,n,o,a)})),iw=Rp((({n:e,latitudinal:t,poleAxis:s,outputDirection:i,weights:r,samples:n,dTheta:o,mipInt:a,envMap:h,CUBEUV_TEXEL_WIDTH:u,CUBEUV_TEXEL_HEIGHT:l,CUBEUV_MAX_MIP:c})=>{const d=jp(Bf(t,s,pf(s,i))).toVar();Pp(wg(d.equals(jp(0))),(()=>{d.assign(jp(i.z,0,i.x.negate()))})),d.assign(Ug(d));const p=jp().toVar();return p.addAssign(r.element(Op(0)).mul(sw({theta:0,axis:d,outputDirection:i,mipInt:a,envMap:h,CUBEUV_TEXEL_WIDTH:u,CUBEUV_TEXEL_HEIGHT:l,CUBEUV_MAX_MIP:c}))),bv({start:Op(1),end:e},(({i:e})=>{Pp(e.greaterThanEqual(n),(()=>{Tv()}));const t=Up(o.mul(Up(e))).toVar();p.addAssign(r.element(e).mul(sw({theta:t.mul(-1),axis:d,outputDirection:i,mipInt:a,envMap:h,CUBEUV_TEXEL_WIDTH:u,CUBEUV_TEXEL_HEIGHT:l,CUBEUV_MAX_MIP:c}))),p.addAssign(r.element(e).mul(sw({theta:t,axis:d,outputDirection:i,mipInt:a,envMap:h,CUBEUV_TEXEL_WIDTH:u,CUBEUV_TEXEL_HEIGHT:l,CUBEUV_MAX_MIP:c})))})),Xp(p,1)}));let rw=null;const nw=new WeakMap;function ow(e){let t=nw.get(e);if((void 0!==t?t.pmremVersion:-1)!==e.pmremVersion){const s=e.image;if(e.isCubeTexture){if(!function(e){if(null==e)return!1;let t=0;const s=6;for(let i=0;i0}(s))return null;t=rw.fromEquirectangular(e,t)}t.pmremVersion=e.pmremVersion,nw.set(e,t)}return t.texture}class aw extends kd{static get type(){return"PMREMNode"}constructor(e,t=null,s=null){super("vec3"),this._value=e,this._pmrem=null,this.uvNode=t,this.levelNode=s,this._generator=null;const i=new vi;i.isRenderTargetTexture=!0,this._texture=By(i),this._width=pm(0),this._height=pm(0),this._maxMip=pm(0),this.updateBeforeType=Bd.RENDER}set value(e){this._value=e,this._pmrem=null}get value(){return this._value}updateFromTexture(e){const t=function(e){const t=Math.log2(e)-2,s=1/e;return{texelWidth:1/(3*Math.max(Math.pow(2,t),112)),texelHeight:s,maxMip:t}}(e.image.height);this._texture.value=e,this._width.value=t.texelWidth,this._height.value=t.texelHeight,this._maxMip.value=t.maxMip}updateBefore(){let e=this._pmrem;const t=e?e.pmremVersion:-1,s=this._value;t!==s.pmremVersion&&(e=!0===s.isPMREMTexture?s:ow(s),null!==e&&(this._pmrem=e,this.updateFromTexture(e)))}setup(e){null===rw&&(rw=e.createPMREMGenerator()),this.updateBefore(e);let t=this.uvNode;null===t&&e.context.getUV&&(t=e.context.getUV(this));const s=this.value;e.renderer.coordinateSystem===Vs&&!0!==s.isPMREMTexture&&!0===s.isRenderTargetTexture&&(t=jp(t.x.negate(),t.yz));let i=this.levelNode;return null===i&&e.context.getTextureLevel&&(i=e.context.getTextureLevel(this)),ew(this._texture,t,i,this._width,this._height,this._maxMip)}}const hw=Ap(aw),uw=new WeakMap;class lw extends Iv{static get type(){return"EnvironmentNode"}constructor(e=null){super(),this.envNode=e}setup(e){const{material:t}=e;let s=this.envNode;if(s.isTextureNode||s.isMaterialReferenceNode){const e=s.isTextureNode?s.value:t[s.property];let i=uw.get(e);void 0===i&&(i=hw(e),uw.set(e,i)),s=i}const i=t.envMap?kx("envMapIntensity","float",e.material):kx("environmentIntensity","float",e.scene),r=!0===t.useAnisotropy||t.anisotropy>0?ab:Tx,n=s.context(cw(bm,r)).mul(i),o=s.context(dw(_x)).mul(Math.PI).mul(i),a=ly(n),h=ly(o);e.context.radiance.addAssign(a),e.context.iblIrradiance.addAssign(h);const u=e.context.lightingModel.clearcoatRadiance;if(u){const e=s.context(cw(_m,wx)).mul(i),t=ly(e);u.addAssign(t)}}}const cw=(e,t)=>{let s=null;return{getUV:()=>(null===s&&(s=dx.negate().reflect(t),s=e.mul(e).mix(s,t).normalize(),s=s.transformDirection(Vy)),s),getTextureLevel:()=>e}},dw=e=>({getUV:()=>e,getTextureLevel:()=>Up(1)}),pw=new _u;class mw extends pT{static get type(){return"MeshStandardNodeMaterial"}constructor(e){super(),this.isMeshStandardNodeMaterial=!0,this.lights=!0,this.emissiveNode=null,this.metalnessNode=null,this.roughnessNode=null,this.setDefaultValues(pw),this.setValues(e)}setupEnvironment(e){let t=super.setupEnvironment(e);return null===t&&e.environmentNode&&(t=e.environmentNode),t?new lw(t):null}setupLightingModel(){return new O_}setupSpecular(){const e=Tf(jp(.04),ym.rgb,vm);Im.assign(e),Pm.assign(1)}setupVariants(){const e=this.metalnessNode?Up(this.metalnessNode):Cb;vm.assign(e);let t=this.roughnessNode?Up(this.roughnessNode):Ab;t=ZT({roughness:t}),bm.assign(t),this.setupSpecular(),ym.assign(Xp(ym.rgb.mul(e.oneMinus()),ym.a))}copy(e){return this.emissiveNode=e.emissiveNode,this.metalnessNode=e.metalnessNode,this.roughnessNode=e.roughnessNode,super.copy(e)}}const gw=new wu;class fw extends mw{static get type(){return"MeshPhysicalNodeMaterial"}constructor(e){super(),this.isMeshPhysicalNodeMaterial=!0,this.clearcoatNode=null,this.clearcoatRoughnessNode=null,this.clearcoatNormalNode=null,this.sheenNode=null,this.sheenRoughnessNode=null,this.iridescenceNode=null,this.iridescenceIORNode=null,this.iridescenceThicknessNode=null,this.specularIntensityNode=null,this.specularColorNode=null,this.iorNode=null,this.transmissionNode=null,this.thicknessNode=null,this.attenuationDistanceNode=null,this.attenuationColorNode=null,this.dispersionNode=null,this.anisotropyNode=null,this.setDefaultValues(gw),this.setValues(e)}get useClearcoat(){return this.clearcoat>0||null!==this.clearcoatNode}get useIridescence(){return this.iridescence>0||null!==this.iridescenceNode}get useSheen(){return this.sheen>0||null!==this.sheenNode}get useAnisotropy(){return this.anisotropy>0||null!==this.anisotropyNode}get useTransmission(){return this.transmission>0||null!==this.transmissionNode}get useDispersion(){return this.dispersion>0||null!==this.dispersionNode}setupSpecular(){const e=this.iorNode?Up(this.iorNode):Gb;Vm.assign(e),Im.assign(Tf(nf(gf(Vm.sub(1).div(Vm.add(1))).mul(Sb),jp(1)).mul(wb),ym.rgb,vm)),Pm.assign(Tf(wb,1,vm))}setupLightingModel(){return new O_(this.useClearcoat,this.useSheen,this.useIridescence,this.useAnisotropy,this.useTransmission,this.useDispersion)}setupVariants(e){if(super.setupVariants(e),this.useClearcoat){const e=this.clearcoatNode?Up(this.clearcoatNode):Eb,t=this.clearcoatRoughnessNode?Up(this.clearcoatRoughnessNode):Bb;Tm.assign(e),_m.assign(ZT({roughness:t}))}if(this.useSheen){const e=this.sheenNode?jp(this.sheenNode):Fb,t=this.sheenRoughnessNode?Up(this.sheenRoughnessNode):zb;wm.assign(e),Sm.assign(t)}if(this.useIridescence){const e=this.iridescenceNode?Up(this.iridescenceNode):Ob,t=this.iridescenceIORNode?Up(this.iridescenceIORNode):Lb,s=this.iridescenceThicknessNode?Up(this.iridescenceThicknessNode):Vb;Mm.assign(e),Nm.assign(t),Am.assign(s)}if(this.useAnisotropy){const e=(this.anisotropyNode?Dp(this.anisotropyNode):Ub).toVar();Rm.assign(e.length()),Pp(Rm.equal(0),(()=>{e.assign(Dp(1,0))})).Else((()=>{e.divAssign(Dp(Rm)),Rm.assign(Rm.saturate())})),Cm.assign(Rm.pow2().mix(bm.pow2(),1)),Em.assign(rb[0].mul(e.x).add(rb[1].mul(e.y))),Bm.assign(rb[1].mul(e.x).sub(rb[0].mul(e.y)))}if(this.useTransmission){const e=this.transmissionNode?Up(this.transmissionNode):Db,t=this.thicknessNode?Up(this.thicknessNode):kb,s=this.attenuationDistanceNode?Up(this.attenuationDistanceNode):Wb,i=this.attenuationColorNode?jp(this.attenuationColorNode):jb;if(Dm.assign(e),km.assign(t),Gm.assign(s),Wm.assign(i),this.useDispersion){const e=this.dispersionNode?Up(this.dispersionNode):Jb;jm.assign(e)}}}setupClearcoatNormal(){return this.clearcoatNormalNode?jp(this.clearcoatNormalNode):Ib}setup(e){e.context.setupClearcoatNormal=()=>this.setupClearcoatNormal(e),super.setup(e)}copy(e){return this.clearcoatNode=e.clearcoatNode,this.clearcoatRoughnessNode=e.clearcoatRoughnessNode,this.clearcoatNormalNode=e.clearcoatNormalNode,this.sheenNode=e.sheenNode,this.sheenRoughnessNode=e.sheenRoughnessNode,this.iridescenceNode=e.iridescenceNode,this.iridescenceIORNode=e.iridescenceIORNode,this.iridescenceThicknessNode=e.iridescenceThicknessNode,this.specularIntensityNode=e.specularIntensityNode,this.specularColorNode=e.specularColorNode,this.transmissionNode=e.transmissionNode,this.thicknessNode=e.thicknessNode,this.attenuationDistanceNode=e.attenuationDistanceNode,this.attenuationColorNode=e.attenuationColorNode,this.dispersionNode=e.dispersionNode,this.anisotropyNode=e.anisotropyNode,super.copy(e)}}class yw extends O_{constructor(e,t,s,i){super(e,t,s),this.useSSS=i}direct({lightDirection:e,lightColor:t,reflectedLight:s},i,r){if(!0===this.useSSS){const i=r.material,{thicknessColorNode:n,thicknessDistortionNode:o,thicknessAmbientNode:a,thicknessAttenuationNode:h,thicknessPowerNode:u,thicknessScaleNode:l}=i,c=e.add(Tx.mul(o)).normalize(),d=Up(dx.dot(c.negate()).saturate().pow(u).mul(l)),p=jp(d.add(a).mul(n));s.directDiffuse.addAssign(p.mul(h.mul(t)))}super.direct({lightDirection:e,lightColor:t,reflectedLight:s},i,r)}}class xw extends fw{static get type(){return"MeshSSSNodeMaterial"}constructor(e){super(e),this.thicknessColorNode=null,this.thicknessDistortionNode=Up(.1),this.thicknessAmbientNode=Up(0),this.thicknessAttenuationNode=Up(.1),this.thicknessPowerNode=Up(2),this.thicknessScaleNode=Up(10)}get useSSS(){return null!==this.thicknessColorNode}setupLightingModel(){return new yw(this.useClearcoat,this.useSheen,this.useIridescence,this.useSSS)}copy(e){return this.thicknessColorNode=e.thicknessColorNode,this.thicknessDistortionNode=e.thicknessDistortionNode,this.thicknessAmbientNode=e.thicknessAmbientNode,this.thicknessAttenuationNode=e.thicknessAttenuationNode,this.thicknessPowerNode=e.thicknessPowerNode,this.thicknessScaleNode=e.thicknessScaleNode,super.copy(e)}}const bw=Rp((({normal:e,lightDirection:t,builder:s})=>{const i=e.dot(t),r=Dp(i.mul(.5).add(.5),0);if(s.material.gradientMap){const e=jx("gradientMap","texture").context({getUV:()=>r});return jp(e.r)}{const e=r.fwidth().mul(.5);return Tf(jp(.7),jp(1),Mf(Up(.7).sub(e.x),Up(.7).add(e.x),r.x))}}));class vw extends UT{direct({lightDirection:e,lightColor:t,reflectedLight:s},i,r){const n=bw({normal:fx,lightDirection:e,builder:r}).mul(t);s.directDiffuse.addAssign(n.mul(kT({diffuseColor:ym.rgb})))}indirect({ambientOcclusion:e,irradiance:t,reflectedLight:s}){s.indirectDiffuse.addAssign(t.mul(kT({diffuseColor:ym}))),s.indirectDiffuse.mulAssign(e)}}const Tw=new Mu;class _w extends pT{static get type(){return"MeshToonNodeMaterial"}constructor(e){super(),this.isMeshToonNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Tw),this.setValues(e)}setupLightingModel(){return new vw}}class ww extends kd{static get type(){return"MatcapUVNode"}constructor(){super("vec2")}setup(){const e=jp(dx.z,0,dx.x.negate()).normalize(),t=dx.cross(e);return Dp(e.dot(Tx),t.dot(Tx)).mul(.495).add(.5)}}const Sw=Cp(ww),Mw=new Eu;class Nw extends pT{static get type(){return"MeshMatcapNodeMaterial"}constructor(e){super(),this.lights=!1,this.isMeshMatcapNodeMaterial=!0,this.setDefaultValues(Mw),this.setValues(e)}setupVariants(e){const t=Sw;let s;s=e.material.matcap?jx("matcap","texture").context({getUV:()=>t}):jp(Tf(.2,.8,t.y)),ym.rgb.mulAssign(s.rgb)}}const Aw=new za;class Cw extends pT{static get type(){return"PointsNodeMaterial"}constructor(e){super(),this.isPointsNodeMaterial=!0,this.lights=!1,this.transparent=!0,this.sizeNode=null,this.setDefaultValues(Aw),this.setValues(e)}copy(e){return this.sizeNode=e.sizeNode,super.copy(e)}}class Rw extends kd{static get type(){return"RotateNode"}constructor(e,t){super(),this.positionNode=e,this.rotationNode=t}getNodeType(e){return this.positionNode.getNodeType(e)}setup(e){const{rotationNode:t,positionNode:s}=this;if("vec2"===this.getNodeType(e)){const e=t.cos(),i=t.sin();return Kp(e,i,i.negate(),e).mul(s)}{const e=t,i=em(Xp(1,0,0,0),Xp(0,Vg(e.x),Lg(e.x).negate(),0),Xp(0,Lg(e.x),Vg(e.x),0),Xp(0,0,0,1)),r=em(Xp(Vg(e.y),0,Lg(e.y),0),Xp(0,1,0,0),Xp(Lg(e.y).negate(),0,Vg(e.y),0),Xp(0,0,0,1)),n=em(Xp(Vg(e.z),Lg(e.z).negate(),0,0),Xp(Lg(e.z),Vg(e.z),0,0),Xp(0,0,1,0),Xp(0,0,0,1));return i.mul(r).mul(n).mul(Xp(s,1)).xyz}}}const Ew=Ap(Rw),Bw=new no;class Iw extends pT{static get type(){return"SpriteNodeMaterial"}constructor(e){super(),this.isSpriteNodeMaterial=!0,this.lights=!1,this._useSizeAttenuation=!0,this.positionNode=null,this.rotationNode=null,this.scaleNode=null,this.setDefaultValues(Bw),this.setValues(e)}setupPosition({object:e,camera:t,context:s}){const i=this.sizeAttenuation,{positionNode:r,rotationNode:n,scaleNode:o}=this,a=ax;let h=ix.mul(jp(r||0)),u=Dp(Jy[0].xyz.length(),Jy[1].xyz.length());null!==o&&(u=u.mul(o)),!i&&t.isPerspectiveCamera&&(u=u.mul(h.z.negate()));let l=a.xy;if(e.center&&!0===e.center.isVector2){const e=((e,t,s)=>Sp(new Zf(e,t,s)))("center","vec2");l=l.sub(e.sub(.5))}l=l.mul(u);const c=Up(n||Pb),d=Ew(l,c);h=Xp(h.xy.add(d),h.zw);const p=Oy.mul(h);return s.vertex=a,p}copy(e){return this.positionNode=e.positionNode,this.rotationNode=e.rotationNode,this.scaleNode=e.scaleNode,super.copy(e)}get sizeAttenuation(){return this._useSizeAttenuation}set sizeAttenuation(e){this._useSizeAttenuation!==e&&(this._useSizeAttenuation=e,this.needsUpdate=!0)}}class Pw extends UT{constructor(){super(),this.shadowNode=Up(1).toVar("shadowMask")}direct({shadowMask:e}){this.shadowNode.mulAssign(e)}finish(e){ym.a.mulAssign(this.shadowNode.oneMinus()),e.outgoingLight.rgb.assign(ym.rgb)}}const Fw=new vu;class zw extends pT{static get type(){return"ShadowNodeMaterial"}constructor(e){super(),this.isShadowNodeMaterial=!0,this.lights=!0,this.setDefaultValues(Fw),this.setValues(e)}setupLightingModel(){return new Pw}}const Uw=Rp((({texture:e,uv:t})=>{const s=1e-4,i=jp().toVar();return Pp(t.x.lessThan(s),(()=>{i.assign(jp(1,0,0))})).ElseIf(t.y.lessThan(s),(()=>{i.assign(jp(0,1,0))})).ElseIf(t.z.lessThan(s),(()=>{i.assign(jp(0,0,1))})).ElseIf(t.x.greaterThan(.9999),(()=>{i.assign(jp(-1,0,0))})).ElseIf(t.y.greaterThan(.9999),(()=>{i.assign(jp(0,-1,0))})).ElseIf(t.z.greaterThan(.9999),(()=>{i.assign(jp(0,0,-1))})).Else((()=>{const s=.01,r=e.uv(t.add(jp(-.01,0,0))).r.sub(e.uv(t.add(jp(s,0,0))).r),n=e.uv(t.add(jp(0,-.01,0))).r.sub(e.uv(t.add(jp(0,s,0))).r),o=e.uv(t.add(jp(0,0,-.01))).r.sub(e.uv(t.add(jp(0,0,s))).r);i.assign(jp(r,n,o))})),i.normalize()}));class Ow extends Ey{static get type(){return"Texture3DNode"}constructor(e,t=null,s=null){super(e,t,s),this.isTexture3DNode=!0}getInputType(){return"texture3D"}getDefaultUV(){return jp(.5,.5,.5)}setUpdateMatrix(){}setupUV(e,t){return t}generateUV(e,t){return t.build(e,"vec3")}normal(e){return Uw({texture:this,uv:e})}}const Lw=Ap(Ow);class Vw extends pT{static get type(){return"VolumeNodeMaterial"}constructor(e={}){super(),this.lights=!1,this.isVolumeNodeMaterial=!0,this.testNode=null,this.setValues(e)}setup(e){const t=Lw(this.map,null,0),s=Rp((({orig:e,dir:t})=>{const s=jp(-.5),i=jp(.5),r=t.reciprocal(),n=s.sub(e).mul(r),o=i.sub(e).mul(r),a=nf(n,o),h=of(n,o),u=of(a.x,of(a.y,a.z)),l=nf(h.x,nf(h.y,h.z));return Dp(u,l)}));this.fragmentNode=Rp((()=>{const e=Vf(jp(sx.mul(Xp(Gy,1)))),i=Vf(ox.sub(e)).normalize(),r=Dp(s({orig:e,dir:i})).toVar();r.x.greaterThan(r.y).discard(),r.assign(Dp(of(r.x,0),r.y));const n=jp(e.add(r.x.mul(i))).toVar(),o=jp(i.abs().reciprocal()).toVar(),a=Up(nf(o.x,nf(o.y,o.z))).toVar("delta");a.divAssign(jx("steps","float"));const h=Xp(jx("base","color"),0).toVar();return bv({type:"float",start:r.x,end:r.y,update:"+= delta"},(()=>{const e=gm("float","d").assign(t.uv(n.add(.5)).r);null!==this.testNode?this.testNode({map:t,mapValue:e,probe:n,finalColor:h}).append():(h.a.assign(1),Tv()),n.addAssign(i.mul(a))})),h.a.equal(0).discard(),Xp(h)}))(),super.setup(e)}}class Dw{constructor(e,t){this.nodes=e,this.info=t,this.animationLoop=null,this.requestId=null,this._init()}_init(){const e=(t,s)=>{this.requestId=self.requestAnimationFrame(e),!0===this.info.autoReset&&this.info.reset(),this.nodes.nodeFrame.update(),this.info.frame=this.nodes.nodeFrame.frameId,null!==this.animationLoop&&this.animationLoop(t,s)};e()}dispose(){self.cancelAnimationFrame(this.requestId),this.requestId=null}setAnimationLoop(e){this.animationLoop=e}}class kw{constructor(){this.weakMap=new WeakMap}get(e){let t=this.weakMap;for(let s=0;s{this.dispose()},this.material.addEventListener("dispose",this.onMaterialDispose)}updateClipping(e){const t=this.material;let s=this.clippingContext;Array.isArray(t.clippingPlanes)?(s!==e&&s||(s=new Ww,this.clippingContext=s),s.update(e,t)):this.clippingContext!==e&&(this.clippingContext=e)}get clippingNeedsUpdate(){return this.clippingContext.version!==this.clippingContextVersion&&(this.clippingContextVersion=this.clippingContext.version,!0)}getNodeBuilderState(){return this._nodeBuilderState||(this._nodeBuilderState=this._nodes.getForRender(this))}getMonitor(){return this._monitor||(this._monitor=this.getNodeBuilderState().monitor)}getBindings(){return this._bindings||(this._bindings=this.getNodeBuilderState().createBindings())}getIndex(){return this._geometries.getIndex(this)}getChainArray(){return[this.object,this.material,this.context,this.lightsNode]}getAttributes(){if(null!==this.attributes)return this.attributes;const e=this.getNodeBuilderState().nodeAttributes,t=this.geometry,s=[],i=new Set;for(const r of e){const e=r.node&&r.node.attribute?r.node.attribute:t.getAttribute(r.name);if(void 0===e)continue;s.push(e);const n=e.isInterleavedBufferAttribute?e.data:e;i.add(n)}return this.attributes=s,this.vertexBuffers=Array.from(i.values()),s}getVertexBuffers(){return null===this.vertexBuffers&&this.getAttributes(),this.vertexBuffers}getDrawParameters(){const{object:e,material:t,geometry:s,group:i,drawRange:r}=this,n=this.drawParams||(this.drawParams={vertexCount:0,firstVertex:0,instanceCount:0,firstInstance:0}),o=this.getIndex(),a=null!==o,h=s.isInstancedBufferGeometry?s.instanceCount:e.count>1?e.count:1;if(0===h)return null;if(n.instanceCount=h,!0===e.isBatchedMesh)return n;let u=1;!0!==t.wireframe||e.isPoints||e.isLineSegments||e.isLine||e.isLineLoop||(u=2);let l=r.start*u,c=(r.start+r.count)*u;null!==i&&(l=Math.max(l,i.start*u),c=Math.min(c,(i.start+i.count)*u));const d=!0===a?o.count:s.attributes.position.count;l=Math.max(l,0),c=Math.min(c,d);const p=c-l;return p<0||p===1/0?null:(n.vertexCount=p,n.firstVertex=l,n)}getGeometryCacheKey(){const{geometry:e}=this;let t="";for(const s of Object.keys(e.attributes).sort()){const i=e.attributes[s];t+=s+",",i.data&&(t+=i.data.stride+","),i.offset&&(t+=i.offset+","),i.itemSize&&(t+=i.itemSize+","),i.normalized&&(t+="n,")}return e.index&&(t+="index,"),t}getMaterialCacheKey(){const{object:e,material:t}=this;let s=t.customProgramCacheKey();for(const e of function(e){const t=Object.keys(e);let s=Object.getPrototypeOf(e);for(;s;){const e=Object.getOwnPropertyDescriptors(s);for(const s in e)if(void 0!==e[s]){const i=e[s];i&&"function"==typeof i.get&&t.push(s)}s=Object.getPrototypeOf(s)}return t}(t)){if(/^(is[A-Z]|_)|^(visible|version|uuid|name|opacity|userData)$/.test(e))continue;const i=t[e];let r;if(null!==i){const e=typeof i;"number"===e?r=0!==i?"1":"0":"object"===e?(r="{",i.isTexture&&(r+=i.mapping),r+="}"):r=String(i)}else r=String(i);s+=r+","}return s+=this.clippingContext.cacheKey+",",e.geometry&&(s+=this.getGeometryCacheKey()),e.skeleton&&(s+=e.skeleton.bones.length+","),e.morphTargetInfluences&&(s+=e.morphTargetInfluences.length+","),e.isBatchedMesh&&(s+=e._matricesTexture.uuid+",",null!==e._colorsTexture&&(s+=e._colorsTexture.uuid+",")),e.count>1&&(s+=e.uuid+","),vd(s)}get needsUpdate(){return this.initialNodesCacheKey!==this.getDynamicCacheKey()||this.clippingNeedsUpdate}getDynamicCacheKey(){let e=this._nodes.getCacheKey(this.scene,this.lightsNode);return this.object.receiveShadow&&(e+=1),e}getCacheKey(){return this.getMaterialCacheKey()+this.getDynamicCacheKey()}dispose(){this.material.removeEventListener("dispose",this.onMaterialDispose),this.onDispose()}}const qw=[];class $w{constructor(e,t,s,i,r,n){this.renderer=e,this.nodes=t,this.geometries=s,this.pipelines=i,this.bindings=r,this.info=n,this.chainMaps={}}get(e,t,s,i,r,n,o){const a=this.getChainMap(o);qw[0]=e,qw[1]=t,qw[2]=n,qw[3]=r;let h=a.get(qw);return void 0===h?(h=this.createRenderObject(this.nodes,this.geometries,this.renderer,e,t,s,i,r,n,o),a.set(qw,h)):(h.updateClipping(n.clippingContext),(h.version!==t.version||h.needsUpdate)&&(h.initialCacheKey!==h.getCacheKey()?(h.dispose(),h=this.get(e,t,s,i,r,n,o)):h.version=t.version)),h}getChainMap(e="default"){return this.chainMaps[e]||(this.chainMaps[e]=new kw)}dispose(){this.chainMaps={}}createRenderObject(e,t,s,i,r,n,o,a,h,u){const l=this.getChainMap(u),c=new Hw(e,t,s,i,r,n,o,a,h);return c.onDispose=()=>{this.pipelines.delete(c),this.bindings.delete(c),this.nodes.delete(c),l.delete(c.getChainArray())},c}}class Xw{constructor(){this.data=new WeakMap}get(e){let t=this.data.get(e);return void 0===t&&(t={},this.data.set(e,t)),t}delete(e){let t;return this.data.has(e)&&(t=this.data.get(e),this.data.delete(e)),t}has(e){return this.data.has(e)}dispose(){this.data=new WeakMap}}const Yw=1,Zw=2,Jw=4,Kw=16;class Qw extends Xw{constructor(e){super(),this.backend=e}delete(e){const t=super.delete(e);return void 0!==t&&this.backend.destroyAttribute(e),t}update(e,t){const s=this.get(e);if(void 0===s.version)t===Yw?this.backend.createAttribute(e):t===Zw?this.backend.createIndexAttribute(e):t===Jw&&this.backend.createStorageAttribute(e),s.version=this._getBufferAttribute(e).version;else{const t=this._getBufferAttribute(e);(s.version=0;--t)if(e[t]>=65535)return!0;return!1}(t)?yn:gn)(t,1);return r.version=eS(e),r}class sS extends Xw{constructor(e,t){super(),this.attributes=e,this.info=t,this.wireframes=new WeakMap,this.attributeCall=new WeakMap}has(e){const t=e.geometry;return super.has(t)&&!0===this.get(t).initialized}updateForRender(e){!1===this.has(e)&&this.initGeometry(e),this.updateAttributes(e)}initGeometry(e){const t=e.geometry;this.get(t).initialized=!0,this.info.memory.geometries++;const s=()=>{this.info.memory.geometries--;const i=t.index,r=e.getAttributes();null!==i&&this.attributes.delete(i);for(const e of r)this.attributes.delete(e);const n=this.wireframes.get(t);void 0!==n&&this.attributes.delete(n),t.removeEventListener("dispose",s)};t.addEventListener("dispose",s)}updateAttributes(e){const t=e.getAttributes();for(const e of t)e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute?this.updateAttribute(e,Jw):this.updateAttribute(e,Yw);const s=this.getIndex(e);null!==s&&this.updateAttribute(s,Zw)}updateAttribute(e,t){const s=this.info.render.calls;e.isInterleavedBufferAttribute?void 0===this.attributeCall.get(e)?(this.attributes.update(e,t),this.attributeCall.set(e,s)):this.attributeCall.get(e.data)!==s&&(this.attributes.update(e,t),this.attributeCall.set(e.data,s),this.attributeCall.set(e,s)):this.attributeCall.get(e)!==s&&(this.attributes.update(e,t),this.attributeCall.set(e,s))}getIndex(e){const{geometry:t,material:s}=e;let i=t.index;if(!0===s.wireframe){const e=this.wireframes;let s=e.get(t);void 0===s?(s=tS(t),e.set(t,s)):s.version!==eS(t)&&(this.attributes.delete(s),s=tS(t),e.set(t,s)),i=s}return i}}class iS{constructor(){this.autoReset=!0,this.frame=0,this.calls=0,this.render={calls:0,frameCalls:0,drawCalls:0,triangles:0,points:0,lines:0,timestamp:0,previousFrameCalls:0,timestampCalls:0},this.compute={calls:0,frameCalls:0,timestamp:0,previousFrameCalls:0,timestampCalls:0},this.memory={geometries:0,textures:0}}update(e,t,s){this.render.drawCalls++,e.isMesh||e.isSprite?this.render.triangles+=s*(t/3):e.isPoints?this.render.points+=s*t:e.isLineSegments?this.render.lines+=s*(t/2):e.isLine?this.render.lines+=s*(t-1):console.error("THREE.WebGPUInfo: Unknown object type.")}updateTimestamp(e,t){0===this[e].timestampCalls&&(this[e].timestamp=0),this[e].timestamp+=t,this[e].timestampCalls++,this[e].timestampCalls>=this[e].previousFrameCalls&&(this[e].timestampCalls=0)}reset(){const e=this.render.frameCalls;this.render.previousFrameCalls=e;const t=this.compute.frameCalls;this.compute.previousFrameCalls=t,this.render.drawCalls=0,this.render.frameCalls=0,this.compute.frameCalls=0,this.render.triangles=0,this.render.points=0,this.render.lines=0}dispose(){this.reset(),this.calls=0,this.render.calls=0,this.compute.calls=0,this.render.timestamp=0,this.compute.timestamp=0,this.memory.geometries=0,this.memory.textures=0}}class rS{constructor(e){this.cacheKey=e,this.usedTimes=0}}class nS extends rS{constructor(e,t,s){super(e),this.vertexProgram=t,this.fragmentProgram=s}}class oS extends rS{constructor(e,t){super(e),this.computeProgram=t,this.isComputePipeline=!0}}let aS=0;class hS{constructor(e,t,s=null,i=null){this.id=aS++,this.code=e,this.stage=t,this.transforms=s,this.attributes=i,this.usedTimes=0}}class uS extends Xw{constructor(e,t){super(),this.backend=e,this.nodes=t,this.bindings=null,this.caches=new Map,this.programs={vertex:new Map,fragment:new Map,compute:new Map}}getForCompute(e,t){const{backend:s}=this,i=this.get(e);if(this._needsComputeUpdate(e)){const r=i.pipeline;r&&(r.usedTimes--,r.computeProgram.usedTimes--);const n=this.nodes.getForCompute(e);let o=this.programs.compute.get(n.computeShader);void 0===o&&(r&&0===r.computeProgram.usedTimes&&this._releaseProgram(r.computeProgram),o=new hS(n.computeShader,"compute",n.transforms,n.nodeAttributes),this.programs.compute.set(n.computeShader,o),s.createProgram(o));const a=this._getComputeCacheKey(e,o);let h=this.caches.get(a);void 0===h&&(r&&0===r.usedTimes&&this._releasePipeline(r),h=this._getComputePipeline(e,o,a,t)),h.usedTimes++,o.usedTimes++,i.version=e.version,i.pipeline=h}return i.pipeline}getForRender(e,t=null){const{backend:s}=this,i=this.get(e);if(this._needsRenderUpdate(e)){const r=i.pipeline;r&&(r.usedTimes--,r.vertexProgram.usedTimes--,r.fragmentProgram.usedTimes--);const n=e.getNodeBuilderState();let o=this.programs.vertex.get(n.vertexShader);void 0===o&&(r&&0===r.vertexProgram.usedTimes&&this._releaseProgram(r.vertexProgram),o=new hS(n.vertexShader,"vertex"),this.programs.vertex.set(n.vertexShader,o),s.createProgram(o));let a=this.programs.fragment.get(n.fragmentShader);void 0===a&&(r&&0===r.fragmentProgram.usedTimes&&this._releaseProgram(r.fragmentProgram),a=new hS(n.fragmentShader,"fragment"),this.programs.fragment.set(n.fragmentShader,a),s.createProgram(a));const h=this._getRenderCacheKey(e,o,a);let u=this.caches.get(h);void 0===u?(r&&0===r.usedTimes&&this._releasePipeline(r),u=this._getRenderPipeline(e,o,a,h,t)):e.pipeline=u,u.usedTimes++,o.usedTimes++,a.usedTimes++,i.pipeline=u}return i.pipeline}delete(e){const t=this.get(e).pipeline;return t&&(t.usedTimes--,0===t.usedTimes&&this._releasePipeline(t),t.isComputePipeline?(t.computeProgram.usedTimes--,0===t.computeProgram.usedTimes&&this._releaseProgram(t.computeProgram)):(t.fragmentProgram.usedTimes--,t.vertexProgram.usedTimes--,0===t.vertexProgram.usedTimes&&this._releaseProgram(t.vertexProgram),0===t.fragmentProgram.usedTimes&&this._releaseProgram(t.fragmentProgram))),super.delete(e)}dispose(){super.dispose(),this.caches=new Map,this.programs={vertex:new Map,fragment:new Map,compute:new Map}}updateForRender(e){this.getForRender(e)}_getComputePipeline(e,t,s,i){s=s||this._getComputeCacheKey(e,t);let r=this.caches.get(s);return void 0===r&&(r=new oS(s,t),this.caches.set(s,r),this.backend.createComputePipeline(r,i)),r}_getRenderPipeline(e,t,s,i,r){i=i||this._getRenderCacheKey(e,t,s);let n=this.caches.get(i);return void 0===n&&(n=new nS(i,t,s),this.caches.set(i,n),e.pipeline=n,this.backend.createRenderPipeline(e,r)),n}_getComputeCacheKey(e,t){return e.id+","+t.id}_getRenderCacheKey(e,t,s){return t.id+","+s.id+","+this.backend.getRenderCacheKey(e)}_releasePipeline(e){this.caches.delete(e.cacheKey)}_releaseProgram(e){const t=e.code,s=e.stage;this.programs[s].delete(t)}_needsComputeUpdate(e){const t=this.get(e);return void 0===t.pipeline||t.version!==e.version}_needsRenderUpdate(e){return void 0===this.get(e).pipeline||this.backend.needsRenderUpdate(e)}}class lS extends Xw{constructor(e,t,s,i,r,n){super(),this.backend=e,this.textures=s,this.pipelines=r,this.attributes=i,this.nodes=t,this.info=n,this.pipelines.bindings=this}getForRender(e){const t=e.getBindings();for(const e of t){const s=this.get(e);void 0===s.bindGroup&&(this._init(e),this.backend.createBindings(e,t),s.bindGroup=e)}return t}getForCompute(e){const t=this.nodes.getForCompute(e).bindings;for(const e of t){const s=this.get(e);void 0===s.bindGroup&&(this._init(e),this.backend.createBindings(e,t),s.bindGroup=e)}return t}updateForCompute(e){this._updateBindings(this.getForCompute(e))}updateForRender(e){this._updateBindings(this.getForRender(e))}_updateBindings(e){for(const t of e)this._update(t,e)}_init(e){for(const t of e.bindings)if(t.isSampledTexture)this.textures.updateTexture(t.texture);else if(t.isStorageBuffer){const e=t.attribute;this.attributes.update(e,Jw)}}_update(e,t){const{backend:s}=this;let i=!1;for(const t of e.bindings){if(t.isNodeUniformsGroup){if(!this.nodes.updateGroup(t))continue}if(t.isUniformBuffer){t.update()&&s.updateBinding(t)}else if(t.isSampler)t.update();else if(t.isSampledTexture){t.needsBindingsUpdate(this.textures.get(t.texture).generation)&&(i=!0);const e=t.update(),r=t.texture;e&&this.textures.updateTexture(r);const n=s.get(r);if(!0===s.isWebGPUBackend&&void 0===n.texture&&void 0===n.externalTexture&&(console.error("Bindings._update: binding should be available:",t,e,r,t.textureNode.value,i),this.textures.updateTexture(r),i=!0),!0===r.isStorageTexture){const e=this.get(r);!0===t.store?e.needsMipmap=!0:!0===r.generateMipmaps&&this.textures.needsMipmaps(r)&&!0===e.needsMipmap&&(this.backend.generateMipmaps(r),e.needsMipmap=!1)}}}!0===i&&this.backend.updateBindings(e,t)}}class cS{constructor(e,t,s=null){this.isNodeAttribute=!0,this.name=e,this.type=t,this.node=s}}class dS{constructor(e,t,s){this.isNodeUniform=!0,this.name=e,this.type=t,this.node=s.getSelf()}get value(){return this.node.value}set value(e){this.node.value=e}get id(){return this.node.id}get groupNode(){return this.node.groupNode}}class pS{constructor(e,t){this.isNodeVar=!0,this.name=e,this.type=t}}class mS extends pS{constructor(e,t){super(e,t),this.needsInterpolation=!1,this.isNodeVarying=!0}}class gS{constructor(e,t,s=""){this.name=e,this.type=t,this.code=s,Object.defineProperty(this,"isNodeCode",{value:!0})}}let fS=0;class yS{constructor(e=null){this.id=fS++,this.nodesData=new WeakMap,this.parent=e}getData(e){let t=this.nodesData.get(e);return void 0===t&&null!==this.parent&&(t=this.parent.getData(e)),t}setData(e,t){this.nodesData.set(e,t)}}class xS extends mm{static get type(){return"ParameterNode"}constructor(e,t=null){super(e,t),this.isParameterNode=!0}getHash(){return this.uuid}generate(){return this.name}}const bS=(e,t)=>Sp(new xS(e,t));class vS extends Ld{static get type(){return"CodeNode"}constructor(e="",t=[],s=""){super("code"),this.isCodeNode=!0,this.code=e,this.language=s,this.includes=t}isGlobal(){return!0}setIncludes(e){return this.includes=e,this}getIncludes(){return this.includes}generate(e){const t=this.getIncludes(e);for(const s of t)s.build(e);const s=e.getCodeFromNode(this,this.getNodeType(e));return s.code=this.code,s.code}serialize(e){super.serialize(e),e.code=this.code,e.language=this.language}deserialize(e){super.deserialize(e),this.code=e.code,this.language=e.language}}const TS=Ap(vS),_S=(e,t)=>TS(e,t,"js"),wS=(e,t)=>TS(e,t,"wgsl"),SS=(e,t)=>TS(e,t,"glsl");class MS extends vS{static get type(){return"FunctionNode"}constructor(e="",t=[],s=""){super(e,t,s)}getNodeType(e){return this.getNodeFunction(e).type}getInputs(e){return this.getNodeFunction(e).inputs}getNodeFunction(e){const t=e.getDataFromNode(this);let s=t.nodeFunction;return void 0===s&&(s=e.parser.parseFunction(this.code),t.nodeFunction=s),s}generate(e,t){super.generate(e);const s=this.getNodeFunction(e),i=s.name,r=s.type,n=e.getCodeFromNode(this,r);""!==i&&(n.name=i);const o=e.getPropertyName(n),a=this.getNodeFunction(e).getCode(o);return n.code=a+"\n","property"===t?o:e.format(`${o}()`,r,t)}}const NS=(e,t=[],s="")=>{for(let e=0;ei.call(...e);return r.functionNode=i,r},AS=(e,t)=>NS(e,t,"glsl"),CS=(e,t)=>NS(e,t,"wgsl");class RS{constructor(e,t){this.name=e,this.value=t,this.boundary=0,this.itemSize=0,this.offset=0}setValue(e){this.value=e}getValue(){return this.value}}class ES extends RS{constructor(e,t=0){super(e,t),this.isNumberUniform=!0,this.boundary=4,this.itemSize=1}}class BS extends RS{constructor(e,t=new Qs){super(e,t),this.isVector2Uniform=!0,this.boundary=8,this.itemSize=2}}class IS extends RS{constructor(e,t=new Ri){super(e,t),this.isVector3Uniform=!0,this.boundary=16,this.itemSize=3}}class PS extends RS{constructor(e,t=new Ti){super(e,t),this.isVector4Uniform=!0,this.boundary=16,this.itemSize=4}}class FS extends RS{constructor(e,t=new Jr){super(e,t),this.isColorUniform=!0,this.boundary=16,this.itemSize=3}}class zS extends RS{constructor(e,t=new ei){super(e,t),this.isMatrix3Uniform=!0,this.boundary=48,this.itemSize=12}}class US extends RS{constructor(e,t=new nr){super(e,t),this.isMatrix4Uniform=!0,this.boundary=64,this.itemSize=16}}class OS extends ES{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class LS extends BS{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class VS extends IS{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class DS extends PS{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class kS extends FS{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class GS extends zS{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class WS extends US{constructor(e){super(e.name,e.value),this.nodeUniform=e}getValue(){return this.nodeUniform.value}}class jS extends Ld{static get type(){return"StackNode"}constructor(e=null){super(),this.nodes=[],this.outputNode=null,this.parent=e,this._currentCond=null,this.isStackNode=!0}getNodeType(e){return this.outputNode?this.outputNode.getNodeType(e):"void"}add(e){return this.nodes.push(e),this}If(e,t){const s=new wp(t);return this._currentCond=Bf(e,s),this.add(this._currentCond)}ElseIf(e,t){const s=new wp(t),i=Bf(e,s);return this._currentCond.elseNode=i,this._currentCond=i,this}Else(e){return this._currentCond.elseNode=new wp(e),this}build(e,...t){const s=Ip();Bp(this);for(const t of this.nodes)t.build(e,"void");return Bp(s),this.outputNode?this.outputNode.build(e,...t):super.build(e,...t)}else(...e){return console.warn("TSL.StackNode: .else() has been renamed to .Else()."),this.Else(...e)}elseif(...e){return console.warn("TSL.StackNode: .elseif() has been renamed to .ElseIf()."),this.ElseIf(...e)}}const HS=Ap(jS),qS=[.125,.215,.35,.446,.526,.582],$S=20,XS=new Sl(-1,1,1,-1,0,1),YS=new Xn(90,1),ZS=new Jr;let JS=null,KS=0,QS=0;const eM=(1+Math.sqrt(5))/2,tM=1/eM,sM=[new Ri(-eM,tM,0),new Ri(eM,tM,0),new Ri(-tM,0,eM),new Ri(tM,0,eM),new Ri(0,eM,-tM),new Ri(0,eM,tM),new Ri(-1,1,-1),new Ri(1,1,-1),new Ri(-1,1,1),new Ri(1,1,1)],iM=[3,1,5,0,4,2],rM=Q_(My(),Sy("faceIndex")).normalize(),nM=jp(rM.x,rM.y.negate(),rM.z);class oM{constructor(e){this._renderer=e,this._pingPongRenderTarget=null,this._lodMax=0,this._cubeSize=0,this._lodPlanes=[],this._sizeLods=[],this._sigmas=[],this._lodMeshes=[],this._blurMaterial=null,this._cubemapMaterial=null,this._equirectMaterial=null,this._backgroundBox=null}fromScene(e,t=0,s=.1,i=100){JS=this._renderer.getRenderTarget(),KS=this._renderer.getActiveCubeFace(),QS=this._renderer.getActiveMipmapLevel(),this._setSize(256);const r=this._allocateTargets();return r.depthBuffer=!0,this._sceneToCubeUV(e,s,i,r),t>0&&this._blur(r,0,0,t),this._applyPMREM(r),this._cleanup(r),r}fromEquirectangular(e,t=null){return this._fromTexture(e,t)}fromCubemap(e,t=null){return this._fromTexture(e,t)}async compileCubemapShader(){null===this._cubemapMaterial&&(this._cubemapMaterial=lM(),await this._compileMaterial(this._cubemapMaterial))}async compileEquirectangularShader(){null===this._equirectMaterial&&(this._equirectMaterial=cM(),await this._compileMaterial(this._equirectMaterial))}dispose(){this._dispose(),null!==this._cubemapMaterial&&this._cubemapMaterial.dispose(),null!==this._equirectMaterial&&this._equirectMaterial.dispose(),null!==this._backgroundBox&&(this._backgroundBox.geometry.dispose(),this._backgroundBox.material.dispose())}_setSize(e){this._lodMax=Math.floor(Math.log2(e)),this._cubeSize=Math.pow(2,this._lodMax)}_dispose(){null!==this._blurMaterial&&this._blurMaterial.dispose(),null!==this._pingPongRenderTarget&&this._pingPongRenderTarget.dispose();for(let e=0;ee-4?h=qS[a-e+4-1]:0===a&&(h=0),i.push(h);const u=1/(o-2),l=-u,c=1+u,d=[l,l,c,l,c,c,l,l,c,c,l,c],p=6,m=6,g=3,f=2,y=1,x=new Float32Array(g*m*p),b=new Float32Array(f*m*p),v=new Float32Array(y*m*p);for(let e=0;e2?0:-1,i=[t,s,0,t+2/3,s,0,t+2/3,s+1,0,t,s,0,t+2/3,s+1,0,t,s+1,0],r=iM[e];x.set(i,g*m*r),b.set(d,f*m*r);const n=[r,r,r,r,r,r];v.set(n,y*m*r)}const T=new An;T.setAttribute("position",new ln(x,g)),T.setAttribute("uv",new ln(b,f)),T.setAttribute("faceIndex",new ln(v,y)),t.push(T),r.push(new Vn(T,null)),n>4&&n--}return{lodPlanes:t,sizeLods:s,sigmas:i,lodMeshes:r}}(i)),this._blurMaterial=function(e,t,s){const i=Ox(new Array($S).fill(0)),r=pm(new Ri(0,1,0)),n=pm(0),o=Up($S),a=pm(0),h=pm(1),u=By(null),l=pm(0),c=Up(1/t),d=Up(1/s),p=Up(e),m={n:o,latitudinal:a,weights:i,poleAxis:r,outputDirection:nM,dTheta:n,samples:h,envMap:u,mipInt:l,CUBEUV_TEXEL_WIDTH:c,CUBEUV_TEXEL_HEIGHT:d,CUBEUV_MAX_MIP:p},g=uM("blur");return g.uniforms=m,g.fragmentNode=iw({...m,latitudinal:a.equal(1)}),g}(i,e,t)}return i}async _compileMaterial(e){const t=new Vn(this._lodPlanes[0],e);await this._renderer.compile(t,XS)}_sceneToCubeUV(e,t,s,i){const r=YS;r.near=t,r.far=s;const n=[-1,1,-1,-1,-1,-1],o=[1,1,1,-1,-1,-1],a=this._renderer,h=a.autoClear;a.getClearColor(ZS),a.autoClear=!1;let u=this._backgroundBox;if(null===u){const e=new tn({name:"PMREM.Background",side:d,depthWrite:!1,depthTest:!1});u=new Vn(new kn,e)}let l=!1;const c=e.background;c?c.isColor&&(u.material.color.copy(c),e.background=null,l=!0):(u.material.color.copy(ZS),l=!0),a.setRenderTarget(i),a.clear(),l&&a.render(u,r);for(let t=0;t<6;t++){const s=t%3;0===s?(r.up.set(0,n[t],0),r.lookAt(o[t],0,0)):1===s?(r.up.set(0,0,n[t]),r.lookAt(0,o[t],0)):(r.up.set(0,n[t],0),r.lookAt(0,0,o[t]));const h=this._cubeSize;hM(i,s*h,t>2?h:0,h,h),a.render(e,r)}a.autoClear=h,e.background=c}_textureToCubeUV(e,t){const s=this._renderer,i=e.mapping===he||e.mapping===ue;i?null===this._cubemapMaterial&&(this._cubemapMaterial=lM(e)):null===this._equirectMaterial&&(this._equirectMaterial=cM(e));const r=i?this._cubemapMaterial:this._equirectMaterial;r.fragmentNode.value=e;const n=this._lodMeshes[0];n.material=r;const o=this._cubeSize;hM(t,0,0,3*o,2*o),s.setRenderTarget(t),s.render(n,XS)}_applyPMREM(e){const t=this._renderer,s=t.autoClear;t.autoClear=!1;const i=this._lodPlanes.length;for(let t=1;t$S&&console.warn(`sigmaRadians, ${r}, is too large and will clip, as it requested ${m} samples when the maximum is set to 20`);const g=[];let f=0;for(let e=0;e<$S;++e){const t=e/p,s=Math.exp(-t*t/2);g.push(s),0===e?f+=s:ey-4?i-y+4:0),4*(this._cubeSize-x),3*x,2*x),a.setRenderTarget(t),a.render(u,XS)}}function aM(e,t,s){const i=new _i(e,t,s);return i.texture.mapping=de,i.texture.name="PMREM.cubeUv",i.texture.isPMREMTexture=!0,i.scissorTest=!0,i}function hM(e,t,s,i,r){e.viewport.set(t,s,i,r),e.scissor.set(t,s,i,r)}function uM(e){const t=new pT;return t.depthTest=!1,t.depthWrite=!1,t.blending=m,t.name=`PMREM_${e}`,t}function lM(e){const t=uM("cubemap");return t.fragmentNode=Ix(e,nM),t}function cM(e){const t=uM("equirect");return t.fragmentNode=By(e,AT(nM),0),t}let dM=0;class pM{constructor(e="",t=[],s=0,i=[]){this.name=e,this.bindings=t,this.index=s,this.bindingsReference=i,this.id=dM++}}const mM=new WeakMap,gM=new Map([[2,"vec2"],[3,"vec3"],[4,"vec4"],[9,"mat3"],[16,"mat4"]]),fM=new Map([[Int8Array,"int"],[Int16Array,"int"],[Int32Array,"int"],[Uint8Array,"uint"],[Uint16Array,"uint"],[Uint32Array,"uint"],[Float32Array,"float"]]),yM=e=>(e=Number(e))+(e%1?"":".0");class xM{constructor(e,t,s){this.object=e,this.material=e&&e.material||null,this.geometry=e&&e.geometry||null,this.renderer=t,this.parser=s,this.scene=null,this.camera=null,this.nodes=[],this.updateNodes=[],this.updateBeforeNodes=[],this.updateAfterNodes=[],this.hashNodes={},this.monitor=null,this.lightsNode=null,this.environmentNode=null,this.fogNode=null,this.clippingContext=null,this.vertexShader=null,this.fragmentShader=null,this.computeShader=null,this.flowNodes={vertex:[],fragment:[],compute:[]},this.flowCode={vertex:"",fragment:"",compute:""},this.uniforms={vertex:[],fragment:[],compute:[],index:0},this.structs={vertex:[],fragment:[],compute:[],index:0},this.bindings={vertex:{},fragment:{},compute:{}},this.bindingsIndexes={},this.bindGroups=null,this.attributes=[],this.bufferAttributes=[],this.varyings=[],this.codes={},this.vars={},this.flow={code:""},this.chaining=[],this.stack=HS(),this.stacks=[],this.tab="\t",this.currentFunctionNode=null,this.context={material:this.material},this.cache=new yS,this.globalCache=this.cache,this.flowsData=new WeakMap,this.shaderStage=null,this.buildStage=null,this.useComparisonMethod=!1}getBindGroupsCache(){let e=mM.get(this.renderer);return void 0===e&&(e=new kw,mM.set(this.renderer,e)),e}createRenderTarget(e,t,s){return new _i(e,t,s)}createCubeRenderTarget(e,t){return new CT(e,t)}createPMREMGenerator(){return new oM(this.renderer)}includes(e){return this.nodes.includes(e)}_getBindGroup(e,t){const s=this.getBindGroupsCache(),i=[];let r,n=!0;for(const e of t)i.push(e),n=n&&!0!==e.groupNode.shared;return n?(r=s.get(i),void 0===r&&(r=new pM(e,i,this.bindingsIndexes[e].group,i),s.set(i,r))):r=new pM(e,i,this.bindingsIndexes[e].group,i),r}getBindGroupArray(e,t){const s=this.bindings[t];let i=s[e];return void 0===i&&(void 0===this.bindingsIndexes[e]&&(this.bindingsIndexes[e]={binding:0,group:Object.keys(this.bindingsIndexes).length}),s[e]=i=[]),i}getBindings(){let e=this.bindGroups;if(null===e){const t={},s=this.bindings;for(const e of zd)for(const i in s[e]){const r=s[e][i];(t[i]||(t[i]=[])).push(...r)}e=[];for(const s in t){const i=t[s],r=this._getBindGroup(s,i);e.push(r)}this.bindGroups=e}return e}sortBindingGroups(){const e=this.getBindings();e.sort(((e,t)=>e.bindings[0].groupNode.order-t.bindings[0].groupNode.order));for(let t=0;t=0?`${Math.round(t)}u`:"0u";if("bool"===e)return t?"true":"false";if("color"===e)return`${this.getType("vec3")}( ${yM(t.r)}, ${yM(t.g)}, ${yM(t.b)} )`;const s=this.getTypeLength(e),i=this.getComponentType(e),r=e=>this.generateConst(i,e);if(2===s)return`${this.getType(e)}( ${r(t.x)}, ${r(t.y)} )`;if(3===s)return`${this.getType(e)}( ${r(t.x)}, ${r(t.y)}, ${r(t.z)} )`;if(4===s)return`${this.getType(e)}( ${r(t.x)}, ${r(t.y)}, ${r(t.z)}, ${r(t.w)} )`;if(s>4&&t&&(t.isMatrix3||t.isMatrix4))return`${this.getType(e)}( ${t.elements.map(r).join(", ")} )`;if(s>4)return`${this.getType(e)}()`;throw new Error(`NodeBuilder: Type '${e}' not found in generate constant attempt.`)}getType(e){return"color"===e?"vec3":e}hasGeometryAttribute(e){return this.geometry&&void 0!==this.geometry.getAttribute(e)}getAttribute(e,t){const s=this.attributes;for(const t of s)if(t.name===e)return t;const i=new cS(e,t);return s.push(i),i}getPropertyName(e){return e.name}isVector(e){return/vec\d/.test(e)}isMatrix(e){return/mat\d/.test(e)}isReference(e){return"void"===e||"property"===e||"sampler"===e||"texture"===e||"cubeTexture"===e||"storageTexture"===e||"depthTexture"===e||"texture3D"===e}needsToWorkingColorSpace(){return!1}getComponentTypeFromTexture(e){const t=e.type;if(e.isDataTexture){if(t===Ee)return"int";if(t===Be)return"uint"}return"float"}getElementType(e){return"mat2"===e?"vec2":"mat3"===e?"vec3":"mat4"===e?"vec4":this.getComponentType(e)}getComponentType(e){if("float"===(e=this.getVectorType(e))||"bool"===e||"int"===e||"uint"===e)return e;const t=/(b|i|u|)(vec|mat)([2-4])/.exec(e);return null===t?null:"b"===t[1]?"bool":"i"===t[1]?"int":"u"===t[1]?"uint":"float"}getVectorType(e){return"color"===e?"vec3":"texture"===e||"cubeTexture"===e||"storageTexture"===e||"texture3D"===e?"vec4":e}getTypeFromLength(e,t="float"){if(1===e)return t;const s=gM.get(e);return("float"===t?"":t[0])+s}getTypeFromArray(e){return fM.get(e.constructor)}getTypeFromAttribute(e){let t=e;e.isInterleavedBufferAttribute&&(t=e.data);const s=t.array,i=e.itemSize,r=e.normalized;let n;return e instanceof xn||!0===r||(n=this.getTypeFromArray(s)),this.getTypeFromLength(i,n)}getTypeLength(e){const t=this.getVectorType(e),s=/vec([2-4])/.exec(t);return null!==s?Number(s[1]):"float"===t||"bool"===t||"int"===t||"uint"===t?1:!0===/mat2/.test(e)?4:!0===/mat3/.test(e)?9:!0===/mat4/.test(e)?16:0}getVectorFromMatrix(e){return e.replace("mat","vec")}changeComponentType(e,t){return this.getTypeFromLength(this.getTypeLength(e),t)}getIntegerType(e){const t=this.getComponentType(e);return"int"===t||"uint"===t?e:this.changeComponentType(e,"int")}addStack(){return this.stack=HS(this.stack),this.stacks.push(Ip()||this.stack),Bp(this.stack),this.stack}removeStack(){const e=this.stack;return this.stack=e.parent,Bp(this.stacks.pop()),e}getDataFromNode(e,t=this.shaderStage,s=null){let i=(s=null===s?e.isGlobal(this)?this.globalCache:this.cache:s).getData(e);return void 0===i&&(i={},s.setData(e,i)),void 0===i[t]&&(i[t]={}),i[t]}getNodeProperties(e,t="any"){const s=this.getDataFromNode(e,t);return s.properties||(s.properties={outputNode:null})}getBufferAttributeFromNode(e,t){const s=this.getDataFromNode(e);let i=s.bufferAttribute;if(void 0===i){const r=this.uniforms.index++;i=new cS("nodeAttribute"+r,t,e),this.bufferAttributes.push(i),s.bufferAttribute=i}return i}getStructTypeFromNode(e,t=this.shaderStage){const s=this.getDataFromNode(e,t);if(void 0===s.structType){const i=this.structs.index++;e.name=`StructType${i}`,this.structs[t].push(e),s.structType=e}return e}getUniformFromNode(e,t,s=this.shaderStage,i=null){const r=this.getDataFromNode(e,s,this.globalCache);let n=r.uniform;if(void 0===n){const o=this.uniforms.index++;n=new dS(i||"nodeUniform"+o,t,e),this.uniforms[s].push(n),r.uniform=n}return n}getVarFromNode(e,t=null,s=e.getNodeType(this),i=this.shaderStage){const r=this.getDataFromNode(e,i);let n=r.variable;if(void 0===n){const e=this.vars[i]||(this.vars[i]=[]);null===t&&(t="nodeVar"+e.length),n=new pS(t,s),e.push(n),r.variable=n}return n}getVaryingFromNode(e,t=null,s=e.getNodeType(this)){const i=this.getDataFromNode(e,"any");let r=i.varying;if(void 0===r){const e=this.varyings,n=e.length;null===t&&(t="nodeVarying"+n),r=new mS(t,s),e.push(r),i.varying=r}return r}getCodeFromNode(e,t,s=this.shaderStage){const i=this.getDataFromNode(e);let r=i.code;if(void 0===r){const e=this.codes[s]||(this.codes[s]=[]),n=e.length;r=new gS("nodeCode"+n,t),e.push(r),i.code=r}return r}addFlowCodeHierarchy(e,t){const{flowCodes:s,flowCodeBlock:i}=this.getDataFromNode(e);let r=!0,n=t;for(;n;){if(!0===i.get(n)){r=!1;break}n=this.getDataFromNode(n).parentNodeBlock}if(r)for(const e of s)this.addLineFlowCode(e)}addLineFlowCodeBlock(e,t,s){const i=this.getDataFromNode(e),r=i.flowCodes||(i.flowCodes=[]),n=i.flowCodeBlock||(i.flowCodeBlock=new WeakMap);r.push(t),n.set(s,!0)}addLineFlowCode(e,t=null){return""===e||(null!==t&&this.context.nodeBlock&&this.addLineFlowCodeBlock(t,e,this.context.nodeBlock),e=this.tab+e,/;\s*$/.test(e)||(e+=";\n"),this.flow.code+=e),this}addFlowCode(e){return this.flow.code+=e,this}addFlowTab(){return this.tab+="\t",this}removeFlowTab(){return this.tab=this.tab.slice(0,-1),this}getFlowData(e){return this.flowsData.get(e)}flowNode(e){const t=e.getNodeType(this),s=this.flowChildNode(e,t);return this.flowsData.set(e,s),s}buildFunctionNode(e){const t=new MS,s=this.currentFunctionNode;return this.currentFunctionNode=t,t.code=this.buildFunctionCode(e),this.currentFunctionNode=s,t}flowShaderNode(e){const t=e.layout,s={[Symbol.iterator](){let e=0;const t=Object.values(this);return{next:()=>({value:t[e],done:e++>=t.length})}}};for(const e of t.inputs)s[e.name]=new xS(e.type,e.name);e.layout=null;const i=e.call(s),r=this.flowStagesNode(i,t.type);return e.layout=t,r}flowStagesNode(e,t=null){const s=this.flow,i=this.vars,r=this.cache,n=this.buildStage,o=this.stack,a={code:""};this.flow=a,this.vars={},this.cache=new yS,this.stack=HS();for(const s of Fd)this.setBuildStage(s),a.result=e.build(this,t);return a.vars=this.getVars(this.shaderStage),this.flow=s,this.vars=i,this.cache=r,this.stack=o,this.setBuildStage(n),a}getFunctionOperator(){return null}flowChildNode(e,t=null){const s=this.flow,i={code:""};return this.flow=i,i.result=e.build(this,t),this.flow=s,i}flowNodeFromShaderStage(e,t,s=null,i=null){const r=this.shaderStage;this.setShaderStage(e);const n=this.flowChildNode(t,s);return null!==i&&(n.code+=`${this.tab+i} = ${n.result};\n`),this.flowCode[e]=this.flowCode[e]+n.code,this.setShaderStage(r),n}getAttributesArray(){return this.attributes.concat(this.bufferAttributes)}getAttributes(){console.warn("Abstract function.")}getVaryings(){console.warn("Abstract function.")}getVar(e,t){return`${this.getType(e)} ${t}`}getVars(e){let t="";const s=this.vars[e];if(void 0!==s)for(const e of s)t+=`${this.getVar(e.type,e.name)}; `;return t}getUniforms(){console.warn("Abstract function.")}getCodes(e){const t=this.codes[e];let s="";if(void 0!==t)for(const e of t)s+=e.code+"\n";return s}getHash(){return this.vertexShader+this.fragmentShader+this.computeShader}setShaderStage(e){this.shaderStage=e}getShaderStage(){return this.shaderStage}setBuildStage(e){this.buildStage=e}getBuildStage(){return this.buildStage}buildCode(){console.warn("Abstract function.")}build(){const{object:e,material:t,renderer:s}=this;if(null!==t){let e=s.nodes.library.fromMaterial(t);null===e&&(console.error(`NodeMaterial: Material "${t.type}" is not compatible.`),e=new pT),e.build(this)}else this.addFlow("compute",e);for(const e of Fd){this.setBuildStage(e),this.context.vertex&&this.context.vertex.isNode&&this.flowNodeFromShaderStage("vertex",this.context.vertex);for(const t of zd){this.setShaderStage(t);const s=this.flowNodes[t];for(const t of s)"generate"===e?this.flowNode(t):t.build(this)}}return this.setBuildStage(null),this.setShaderStage(null),this.buildCode(),this.buildUpdateNodes(),this}getNodeUniform(e,t){if("float"===t||"int"===t||"uint"===t)return new OS(e);if("vec2"===t||"ivec2"===t||"uvec2"===t)return new LS(e);if("vec3"===t||"ivec3"===t||"uvec3"===t)return new VS(e);if("vec4"===t||"ivec4"===t||"uvec4"===t)return new DS(e);if("color"===t)return new kS(e);if("mat3"===t)return new GS(e);if("mat4"===t)return new WS(e);throw new Error(`Uniform "${t}" not declared.`)}createNodeMaterial(e="NodeMaterial"){throw new Error(`THREE.NodeBuilder: createNodeMaterial() was deprecated. Use new ${e}() instead.`)}format(e,t,s){if((t=this.getVectorType(t))===(s=this.getVectorType(s))||null===s||this.isReference(s))return e;const i=this.getTypeLength(t),r=this.getTypeLength(s);return 16===i&&9===r?`${this.getType(s)}(${e}[0].xyz, ${e}[1].xyz, ${e}[2].xyz)`:9===i&&4===r?`${this.getType(s)}(${e}[0].xy, ${e}[1].xy)`:i>4||r>4||0===r?e:i===r?`${this.getType(s)}( ${e} )`:i>r?this.format(`${e}.${"xyz".slice(0,r)}`,this.getTypeFromLength(r,this.getComponentType(t)),s):4===r&&i>1?`${this.getType(s)}( ${this.format(e,t,"vec3")}, 1.0 )`:2===i?`${this.getType(s)}( ${this.format(e,t,"vec2")}, 0.0 )`:(1===i&&r>1&&t!==this.getComponentType(s)&&(e=`${this.getType(this.getComponentType(s))}( ${e} )`),`${this.getType(s)}( ${e} )`)}getSignature(){return`// Three.js r${e} - Node System\n`}}class bM{constructor(){this.time=0,this.deltaTime=0,this.frameId=0,this.renderId=0,this.startTime=null,this.updateMap=new WeakMap,this.updateBeforeMap=new WeakMap,this.updateAfterMap=new WeakMap,this.renderer=null,this.material=null,this.camera=null,this.object=null,this.scene=null}_getMaps(e,t){let s=e.get(t);return void 0===s&&(s={renderMap:new WeakMap,frameMap:new WeakMap},e.set(t,s)),s}updateBeforeNode(e){const t=e.getUpdateBeforeType(),s=e.updateReference(this);if(t===Bd.FRAME){const{frameMap:t}=this._getMaps(this.updateBeforeMap,s);t.get(s)!==this.frameId&&!1!==e.updateBefore(this)&&t.set(s,this.frameId)}else if(t===Bd.RENDER){const{renderMap:t}=this._getMaps(this.updateBeforeMap,s);t.get(s)!==this.renderId&&!1!==e.updateBefore(this)&&t.set(s,this.renderId)}else t===Bd.OBJECT&&e.updateBefore(this)}updateAfterNode(e){const t=e.getUpdateAfterType(),s=e.updateReference(this);if(t===Bd.FRAME){const{frameMap:t}=this._getMaps(this.updateAfterMap,s);t.get(s)!==this.frameId&&!1!==e.updateAfter(this)&&t.set(s,this.frameId)}else if(t===Bd.RENDER){const{renderMap:t}=this._getMaps(this.updateAfterMap,s);t.get(s)!==this.renderId&&!1!==e.updateAfter(this)&&t.set(s,this.renderId)}else t===Bd.OBJECT&&e.updateAfter(this)}updateNode(e){const t=e.getUpdateType(),s=e.updateReference(this);if(t===Bd.FRAME){const{frameMap:t}=this._getMaps(this.updateMap,s);t.get(s)!==this.frameId&&!1!==e.update(this)&&t.set(s,this.frameId)}else if(t===Bd.RENDER){const{renderMap:t}=this._getMaps(this.updateMap,s);t.get(s)!==this.renderId&&!1!==e.update(this)&&t.set(s,this.renderId)}else t===Bd.OBJECT&&e.update(this)}update(){this.frameId++,void 0===this.lastTime&&(this.lastTime=performance.now()),this.deltaTime=(performance.now()-this.lastTime)/1e3,this.lastTime=performance.now(),this.time+=this.deltaTime}}class vM{constructor(e,t,s=null,i="",r=!1){this.type=e,this.name=t,this.count=s,this.qualifier=i,this.isConst=r}}vM.isNodeFunctionInput=!0;class TM extends Ld{static get type(){return"StructTypeNode"}constructor(e){super(),this.types=e,this.isStructTypeNode=!0}getMemberTypes(){return this.types}}class _M extends Ld{static get type(){return"OutputStructNode"}constructor(...e){super(),this.members=e,this.isOutputStructNode=!0}setup(e){super.setup(e);const t=this.members,s=[];for(let i=0;ir&&(i=s,r=n)}}this._candidateFnCall=s=i(...t)}return s}}const CM=Ap(AM),RM=e=>(...t)=>CM(e,...t);class EM extends dm{static get type(){return"TimerNode"}constructor(e=EM.LOCAL,t=1,s=0){super(s),this.scope=e,this.scale=t,this.updateType=Bd.FRAME}update(e){const t=this.scope,s=this.scale;t===EM.LOCAL?this.value+=e.deltaTime*s:t===EM.DELTA?this.value=e.deltaTime*s:t===EM.FRAME?this.value=e.frameId:this.value=e.time*s}serialize(e){super.serialize(e),e.scope=this.scope,e.scale=this.scale}deserialize(e){super.deserialize(e),this.scope=e.scope,this.scale=e.scale}}EM.LOCAL="local",EM.GLOBAL="global",EM.DELTA="delta",EM.FRAME="frame";const BM=(e,t=0)=>Sp(new EM(EM.LOCAL,e,t)),IM=(e,t=0)=>Sp(new EM(EM.GLOBAL,e,t)),PM=(e,t=0)=>Sp(new EM(EM.DELTA,e,t)),FM=Cp(EM,EM.FRAME).toUint();class zM extends Ld{static get type(){return"OscNode"}constructor(e=zM.SINE,t=BM()){super(),this.method=e,this.timeNode=t}getNodeType(e){return this.timeNode.getNodeType(e)}setup(){const e=this.method,t=Sp(this.timeNode);let s=null;return e===zM.SINE?s=t.add(.75).mul(2*Math.PI).sin().mul(.5).add(.5):e===zM.SQUARE?s=t.fract().round():e===zM.TRIANGLE?s=t.add(.5).fract().mul(2).sub(1).abs():e===zM.SAWTOOTH&&(s=t.fract()),s}serialize(e){super.serialize(e),e.method=this.method}deserialize(e){super.deserialize(e),this.method=e.method}}zM.SINE="sine",zM.SQUARE="square",zM.TRIANGLE="triangle",zM.SAWTOOTH="sawtooth";const UM=Ap(zM,zM.SINE),OM=Ap(zM,zM.SQUARE),LM=Ap(zM,zM.TRIANGLE),VM=Ap(zM,zM.SAWTOOTH);class DM extends Ld{static get type(){return"SpriteSheetUVNode"}constructor(e,t=My(),s=Up(0)){super("vec2"),this.countNode=e,this.uvNode=t,this.frameNode=s}setup(){const{frameNode:e,uvNode:t,countNode:s}=this,{width:i,height:r}=s,n=e.mod(i.mul(r)).floor(),o=n.mod(i),a=r.sub(n.add(1).div(i).ceil()),h=s.reciprocal(),u=Dp(o,a);return t.add(u).mul(h)}}const kM=Ap(DM);class GM extends Vd{static get type(){return"StorageArrayElementNode"}constructor(e,t){super(e,t),this.isStorageArrayElementNode=!0}set storageBufferNode(e){this.node=e}get storageBufferNode(){return this.node}setup(e){return!1===e.isAvailable("storageBuffer")&&!0===this.node.bufferObject&&e.setupPBO(this.node),super.setup(e)}generate(e,t){let s;const i=e.context.assign;if(s=!1===e.isAvailable("storageBuffer")?!0===this.node.bufferObject&&!0!==i?e.generatePBO(this):this.node.build(e):super.generate(e),!0!==i){const i=this.getNodeType(e);s=e.format(s,i,t)}return s}}const WM=Ap(GM);class jM extends Ld{static get type(){return"TriplanarTexturesNode"}constructor(e,t=null,s=null,i=Up(1),r=ax,n=yx){super("vec4"),this.textureXNode=e,this.textureYNode=t,this.textureZNode=s,this.scaleNode=i,this.positionNode=r,this.normalNode=n}setup(){const{textureXNode:e,textureYNode:t,textureZNode:s,scaleNode:i,positionNode:r,normalNode:n}=this;let o=n.abs().normalize();o=o.div(o.dot(jp(1)));const a=r.yz.mul(i),h=r.zx.mul(i),u=r.xy.mul(i),l=e.value,c=null!==t?t.value:l,d=null!==s?s.value:l,p=By(l,a).mul(o.x),m=By(c,h).mul(o.y),g=By(d,u).mul(o.z);return Zm(p,m,g)}}const HM=Ap(jM),qM=(...e)=>HM(...e),$M=new Ko,XM=new Ri,YM=new Ri,ZM=new Ri,JM=new nr,KM=new Ri(0,0,-1),QM=new Ti,eN=new Ri,tN=new Ri,sN=new Ti,iN=new Qs,rN=new _i,nN=Dv.flipX();let oN=!1;class aN extends Ey{static get type(){return"ReflectorNode"}constructor(e={}){super(rN.texture,nN);const{target:t=new Ir,resolution:s=1,generateMipmaps:i=!1,bounces:r=!0}=e;this.target=t,this.resolution=s,this.generateMipmaps=i,this.bounces=r,this.updateBeforeType=r?Bd.RENDER:Bd.FRAME,this.virtualCameras=new WeakMap,this.renderTargets=new WeakMap}_updateResolution(e,t){const s=this.resolution;t.getDrawingBufferSize(iN),e.setSize(Math.round(iN.width*s),Math.round(iN.height*s))}setup(e){return this._updateResolution(rN,e.renderer),super.setup(e)}getTextureNode(){return this.textureNode}getVirtualCamera(e){let t=this.virtualCameras.get(e);return void 0===t&&(t=e.clone(),this.virtualCameras.set(e,t)),t}getRenderTarget(e){let t=this.renderTargets.get(e);return void 0===t&&(t=new _i(0,0,{type:Pe}),!0===this.generateMipmaps&&(t.texture.minFilter=1008,t.texture.generateMipmaps=!0),this.renderTargets.set(e,t)),t}updateBefore(e){if(!1===this.bounces&&oN)return!1;oN=!0;const{scene:t,camera:s,renderer:i,material:r}=e,{target:n}=this,o=this.getVirtualCamera(s),a=this.getRenderTarget(o);if(i.getDrawingBufferSize(iN),this._updateResolution(a,i),YM.setFromMatrixPosition(n.matrixWorld),ZM.setFromMatrixPosition(s.matrixWorld),JM.extractRotation(n.matrixWorld),XM.set(0,0,1),XM.applyMatrix4(JM),eN.subVectors(YM,ZM),eN.dot(XM)>0)return;eN.reflect(XM).negate(),eN.add(YM),JM.extractRotation(s.matrixWorld),KM.set(0,0,-1),KM.applyMatrix4(JM),KM.add(ZM),tN.subVectors(YM,KM),tN.reflect(XM).negate(),tN.add(YM),o.coordinateSystem=s.coordinateSystem,o.position.copy(eN),o.up.set(0,1,0),o.up.applyMatrix4(JM),o.up.reflect(XM),o.lookAt(tN),o.near=s.near,o.far=s.far,o.updateMatrixWorld(),o.projectionMatrix.copy(s.projectionMatrix),$M.setFromNormalAndCoplanarPoint(XM,YM),$M.applyMatrix4(o.matrixWorldInverse),QM.set($M.normal.x,$M.normal.y,$M.normal.z,$M.constant);const h=o.projectionMatrix;sN.x=(Math.sign(QM.x)+h.elements[8])/h.elements[0],sN.y=(Math.sign(QM.y)+h.elements[9])/h.elements[5],sN.z=-1,sN.w=(1+h.elements[10])/h.elements[14],QM.multiplyScalar(1/QM.dot(sN));h.elements[2]=QM.x,h.elements[6]=QM.y,h.elements[10]=QM.z-0,h.elements[14]=QM.w,this.value=a.texture,r.visible=!1;const u=i.getRenderTarget(),l=i.getMRT();i.setMRT(null),i.setRenderTarget(a),i.render(t,o),i.setMRT(l),i.setRenderTarget(u),r.visible=!0,oN=!1}}const hN=e=>Sp(new aN(e)),uN=new Sl(-1,1,1,-1,0,1);class lN extends An{constructor(e=!1){super();const t=!1===e?[0,-1,0,1,2,1]:[0,2,0,0,2,0];this.setAttribute("position",new bn([-1,3,0,-1,-1,0,3,-1,0],3)),this.setAttribute("uv",new bn(t,2))}}const cN=new lN;class dN extends Vn{constructor(e=null){super(cN,e),this.camera=uN,this.isQuadMesh=!0}renderAsync(e){return e.renderAsync(this,uN)}render(e){e.render(this,uN)}}const pN=new Qs;class mN extends Ey{static get type(){return"RTTNode"}constructor(e,t=null,s=null,i={type:Pe}){const r=new _i(t,s,i);super(r.texture,My()),this.node=e,this.width=t,this.height=s,this.renderTarget=r,this.textureNeedsUpdate=!0,this.autoUpdate=!0,this.updateMap=new WeakMap,this._rttNode=null,this._quadMesh=new dN(new pT),this.updateBeforeType=Bd.RENDER}get autoSize(){return null===this.width}setup(e){return this._rttNode=this.node.context(e.getSharedContext()),this._quadMesh.material.name="RTT",this._quadMesh.material.needsUpdate=!0,super.setup(e)}setSize(e,t){this.width=e,this.height=t;const s=e*this.pixelRatio,i=t*this.pixelRatio;this.renderTarget.setSize(s,i),this.textureNeedsUpdate=!0}setPixelRatio(e){this.pixelRatio=e,this.setSize(this.width,this.height)}updateBefore({renderer:e}){if(!1===this.textureNeedsUpdate&&!1===this.autoUpdate)return;if(this.textureNeedsUpdate=!1,!0===this.autoSize){this.pixelRatio=e.getPixelRatio();const t=e.getSize(pN);this.setSize(t.width,t.height)}this._quadMesh.material.fragmentNode=this._rttNode;const t=e.getRenderTarget();e.setRenderTarget(this.renderTarget),this._quadMesh.render(e),e.setRenderTarget(t)}clone(){const e=new Ey(this.value,this.uvNode,this.levelNode);return e.sampler=this.sampler,e.referenceNode=this,e}}const gN=(e,...t)=>Sp(new mN(Sp(e),...t)),fN=(e,...t)=>e.isTextureNode?e:gN(e,...t);class yN extends wy{static get type(){return"VertexColorNode"}constructor(e=0){super(null,"vec4"),this.isVertexColorNode=!0,this.index=e}getAttributeName(){const e=this.index;return"color"+(e>0?e:"")}generate(e){const t=this.getAttributeName(e);let s;return s=!0===e.hasGeometryAttribute(t)?super.generate(e):e.generateConst(this.nodeType,new Ti(1,1,1,1)),s}serialize(e){super.serialize(e),e.index=this.index}deserialize(e){super.deserialize(e),this.index=e.index}}const xN=(...e)=>Sp(new yN(...e));class bN extends Ld{static get type(){return"PointUVNode"}constructor(){super("vec2"),this.isPointUVNode=!0}generate(){return"vec2( gl_PointCoord.x, 1.0 - gl_PointCoord.y )"}}const vN=Cp(bN);class TN extends Ld{static get type(){return"SceneNode"}constructor(e=TN.BACKGROUND_BLURRINESS,t=null){super(),this.scope=e,this.scene=t}setup(e){const t=this.scope,s=null!==this.scene?this.scene:e.scene;let i;return t===TN.BACKGROUND_BLURRINESS?i=kx("backgroundBlurriness","float",s):t===TN.BACKGROUND_INTENSITY?i=kx("backgroundIntensity","float",s):console.error("THREE.SceneNode: Unknown scope:",t),i}}TN.BACKGROUND_BLURRINESS="backgroundBlurriness",TN.BACKGROUND_INTENSITY="backgroundIntensity";const _N=Cp(TN,TN.BACKGROUND_BLURRINESS),wN=Cp(TN,TN.BACKGROUND_INTENSITY),SN="point-list",MN="line-list",NN="line-strip",AN="triangle-list",CN="triangle-strip",RN="never",EN="less",BN="equal",IN="less-equal",PN="greater",FN="not-equal",zN="greater-equal",UN="always",ON="store",LN="load",VN="clear",DN="ccw",kN="none",GN="front",WN="back",jN="uint16",HN="uint32",qN={R8Unorm:"r8unorm",R8Snorm:"r8snorm",R8Uint:"r8uint",R8Sint:"r8sint",R16Uint:"r16uint",R16Sint:"r16sint",R16Float:"r16float",RG8Unorm:"rg8unorm",RG8Snorm:"rg8snorm",RG8Uint:"rg8uint",RG8Sint:"rg8sint",R32Uint:"r32uint",R32Sint:"r32sint",R32Float:"r32float",RG16Uint:"rg16uint",RG16Sint:"rg16sint",RG16Float:"rg16float",RGBA8Unorm:"rgba8unorm",RGBA8UnormSRGB:"rgba8unorm-srgb",RGBA8Snorm:"rgba8snorm",RGBA8Uint:"rgba8uint",RGBA8Sint:"rgba8sint",BGRA8Unorm:"bgra8unorm",BGRA8UnormSRGB:"bgra8unorm-srgb",RGB9E5UFloat:"rgb9e5ufloat",RGB10A2Unorm:"rgb10a2unorm",RG11B10uFloat:"rgb10a2unorm",RG32Uint:"rg32uint",RG32Sint:"rg32sint",RG32Float:"rg32float",RGBA16Uint:"rgba16uint",RGBA16Sint:"rgba16sint",RGBA16Float:"rgba16float",RGBA32Uint:"rgba32uint",RGBA32Sint:"rgba32sint",RGBA32Float:"rgba32float",Stencil8:"stencil8",Depth16Unorm:"depth16unorm",Depth24Plus:"depth24plus",Depth24PlusStencil8:"depth24plus-stencil8",Depth32Float:"depth32float",Depth32FloatStencil8:"depth32float-stencil8",BC1RGBAUnorm:"bc1-rgba-unorm",BC1RGBAUnormSRGB:"bc1-rgba-unorm-srgb",BC2RGBAUnorm:"bc2-rgba-unorm",BC2RGBAUnormSRGB:"bc2-rgba-unorm-srgb",BC3RGBAUnorm:"bc3-rgba-unorm",BC3RGBAUnormSRGB:"bc3-rgba-unorm-srgb",BC4RUnorm:"bc4-r-unorm",BC4RSnorm:"bc4-r-snorm",BC5RGUnorm:"bc5-rg-unorm",BC5RGSnorm:"bc5-rg-snorm",BC6HRGBUFloat:"bc6h-rgb-ufloat",BC6HRGBFloat:"bc6h-rgb-float",BC7RGBAUnorm:"bc7-rgba-unorm",BC7RGBAUnormSRGB:"bc7-rgba-srgb",ETC2RGB8Unorm:"etc2-rgb8unorm",ETC2RGB8UnormSRGB:"etc2-rgb8unorm-srgb",ETC2RGB8A1Unorm:"etc2-rgb8a1unorm",ETC2RGB8A1UnormSRGB:"etc2-rgb8a1unorm-srgb",ETC2RGBA8Unorm:"etc2-rgba8unorm",ETC2RGBA8UnormSRGB:"etc2-rgba8unorm-srgb",EACR11Unorm:"eac-r11unorm",EACR11Snorm:"eac-r11snorm",EACRG11Unorm:"eac-rg11unorm",EACRG11Snorm:"eac-rg11snorm",ASTC4x4Unorm:"astc-4x4-unorm",ASTC4x4UnormSRGB:"astc-4x4-unorm-srgb",ASTC5x4Unorm:"astc-5x4-unorm",ASTC5x4UnormSRGB:"astc-5x4-unorm-srgb",ASTC5x5Unorm:"astc-5x5-unorm",ASTC5x5UnormSRGB:"astc-5x5-unorm-srgb",ASTC6x5Unorm:"astc-6x5-unorm",ASTC6x5UnormSRGB:"astc-6x5-unorm-srgb",ASTC6x6Unorm:"astc-6x6-unorm",ASTC6x6UnormSRGB:"astc-6x6-unorm-srgb",ASTC8x5Unorm:"astc-8x5-unorm",ASTC8x5UnormSRGB:"astc-8x5-unorm-srgb",ASTC8x6Unorm:"astc-8x6-unorm",ASTC8x6UnormSRGB:"astc-8x6-unorm-srgb",ASTC8x8Unorm:"astc-8x8-unorm",ASTC8x8UnormSRGB:"astc-8x8-unorm-srgb",ASTC10x5Unorm:"astc-10x5-unorm",ASTC10x5UnormSRGB:"astc-10x5-unorm-srgb",ASTC10x6Unorm:"astc-10x6-unorm",ASTC10x6UnormSRGB:"astc-10x6-unorm-srgb",ASTC10x8Unorm:"astc-10x8-unorm",ASTC10x8UnormSRGB:"astc-10x8-unorm-srgb",ASTC10x10Unorm:"astc-10x10-unorm",ASTC10x10UnormSRGB:"astc-10x10-unorm-srgb",ASTC12x10Unorm:"astc-12x10-unorm",ASTC12x10UnormSRGB:"astc-12x10-unorm-srgb",ASTC12x12Unorm:"astc-12x12-unorm",ASTC12x12UnormSRGB:"astc-12x12-unorm-srgb"},$N="clamp-to-edge",XN="repeat",YN="mirror-repeat",ZN="linear",JN="nearest",KN="zero",QN="one",eA="src",tA="one-minus-src",sA="src-alpha",iA="one-minus-src-alpha",rA="dst",nA="one-minus-dst",oA="dst-alpha",aA="one-minus-dst-alpha",hA="src-alpha-saturated",uA="constant",lA="one-minus-constant",cA="add",dA="subtract",pA="reverse-subtract",mA="min",gA="max",fA=0,yA=15,xA="keep",bA="zero",vA="replace",TA="invert",_A="increment-clamp",wA="decrement-clamp",SA="increment-wrap",MA="decrement-wrap",NA="storage",AA="read-only-storage",CA="write-only",RA="read-only",EA="float",BA="unfilterable-float",IA="depth",PA="sint",FA="uint",zA="2d",UA="3d",OA="2d",LA="2d-array",VA="cube",DA="3d",kA="all",GA="vertex",WA="instance",jA={DepthClipControl:"depth-clip-control",Depth32FloatStencil8:"depth32float-stencil8",TextureCompressionBC:"texture-compression-bc",TextureCompressionETC2:"texture-compression-etc2",TextureCompressionASTC:"texture-compression-astc",TimestampQuery:"timestamp-query",IndirectFirstInstance:"indirect-first-instance",ShaderF16:"shader-f16",RG11B10UFloat:"rg11b10ufloat-renderable",BGRA8UNormStorage:"bgra8unorm-storage",Float32Filterable:"float32-filterable",ClipDistances:"clip-distances",DualSourceBlending:"dual-source-blending",Subgroups:"subgroups"};class HA extends Px{static get type(){return"StorageBufferNode"}constructor(e,t,s=0){super(e,t,s),this.isStorageBufferNode=!0,this.access=NA,this.isAtomic=!1,this.bufferObject=!1,this.bufferCount=s,this._attribute=null,this._varying=null,this.global=!0,!0!==e.isStorageBufferAttribute&&!0!==e.isStorageInstancedBufferAttribute&&(e.isInstancedBufferAttribute?e.isStorageInstancedBufferAttribute=!0:e.isStorageBufferAttribute=!0)}getHash(e){if(0===this.bufferCount){let t=e.globalCache.getData(this.value);return void 0===t&&(t={node:this},e.globalCache.setData(this.value,t)),t.node.uuid}return this.uuid}getInputType(){return"storageBuffer"}element(e){return WM(this,e)}setBufferObject(e){return this.bufferObject=e,this}setAccess(e){return this.access=e,this}toReadOnly(){return this.setAccess(AA)}setAtomic(e){return this.isAtomic=e,this}toAtomic(){return this.setAtomic(!0)}generate(e){if(e.isAvailable("storageBuffer"))return super.generate(e);const t=this.getNodeType(e);null===this._attribute&&(this._attribute=iy(this.value),this._varying=Vf(this._attribute));const s=this._varying.build(e,t);return e.registerTransform(s,this._attribute),s}}const qA=(e,t,s)=>Sp(new HA(e,t,s)),$A=(e,t,s)=>Sp(new HA(e,t,s).setBufferObject(!0));class XA extends Ey{static get type(){return"StorageTextureNode"}constructor(e,t,s=null){super(e,t),this.storeNode=s,this.isStorageTextureNode=!0,this.access=CA}getInputType(){return"storageTexture"}setup(e){super.setup(e);e.getNodeProperties(this).storeNode=this.storeNode}setAccess(e){return this.access=e,this}generate(e,t){let s;return s=null!==this.storeNode?this.generateStore(e):super.generate(e,t),s}toReadOnly(){return this.setAccess(RA)}toWriteOnly(){return this.setAccess(CA)}generateStore(e){const t=e.getNodeProperties(this),{uvNode:s,storeNode:i}=t,r=super.generate(e,"property"),n=s.build(e,"uvec2"),o=i.build(e,"vec4"),a=e.generateTextureStore(e,r,n,o);e.addLineFlowCode(a,this)}}const YA=Ap(XA),ZA=(e,t,s)=>{const i=YA(e,t,s);return null!==s&&i.append(),i};class JA extends Dx{static get type(){return"UserDataNode"}constructor(e,t,s=null){super(e,t,s),this.userData=s}updateReference(e){return this.reference=null!==this.userData?this.userData:e.object.userData,this.reference}}const KA=(e,t,s)=>Sp(new JA(e,t,s));class QA extends kd{static get type(){return"PosterizeNode"}constructor(e,t){super(),this.sourceNode=e,this.stepsNode=t}setup(){const{sourceNode:e,stepsNode:t}=this;return e.mul(t).floor().div(t)}}const eC=Ap(QA);let tC=null;class sC extends Jv{static get type(){return"ViewportSharedTextureNode"}constructor(e=Dv,t=null){null===tC&&(tC=new ja),super(e,t,tC)}updateReference(){return this}}const iC=Ap(sC),rC=new Qs;class nC extends Ey{static get type(){return"PassTextureNode"}constructor(e,t){super(t),this.passNode=e,this.setUpdateMatrix(!1)}setup(e){return e.object.isQuadMesh&&this.passNode.build(e),super.setup(e)}clone(){return new this.constructor(this.passNode,this.value)}}class oC extends nC{static get type(){return"PassMultipleTextureNode"}constructor(e,t,s=!1){super(e,null),this.textureName=t,this.previousTexture=s}updateTexture(){this.value=this.previousTexture?this.passNode.getPreviousTexture(this.textureName):this.passNode.getTexture(this.textureName)}setup(e){return this.updateTexture(),super.setup(e)}clone(){return new this.constructor(this.passNode,this.textureName,this.previousTexture)}}class aC extends kd{static get type(){return"PassNode"}constructor(e,t,s,i={}){super("vec4"),this.scope=e,this.scene=t,this.camera=s,this.options=i,this._pixelRatio=1,this._width=1,this._height=1;const r=new Ya;r.isRenderTargetTexture=!0,r.name="depth";const n=new _i(this._width*this._pixelRatio,this._height*this._pixelRatio,{type:Pe,...i});n.texture.name="output",n.depthTexture=r,this.renderTarget=n,this.updateBeforeType=Bd.FRAME,this._textures={output:n.texture,depth:r},this._textureNodes={},this._linearDepthNodes={},this._viewZNodes={},this._previousTextures={},this._previousTextureNodes={},this._cameraNear=pm(0),this._cameraFar=pm(0),this._mrt=null,this.isPassNode=!0}setMRT(e){return this._mrt=e,this}getMRT(){return this._mrt}isGlobal(){return!0}getTexture(e){let t=this._textures[e];if(void 0===t){t=this.renderTarget.texture.clone(),t.isRenderTargetTexture=!0,t.name=e,this._textures[e]=t,this.renderTarget.textures.push(t)}return t}getPreviousTexture(e){let t=this._previousTextures[e];return void 0===t&&(t=this.getTexture(e).clone(),t.isRenderTargetTexture=!0,this._previousTextures[e]=t),t}toggleTexture(e){const t=this._previousTextures[e];if(void 0!==t){const s=this._textures[e],i=this.renderTarget.textures.indexOf(s);this.renderTarget.textures[i]=t,this._textures[e]=t,this._previousTextures[e]=s,this._textureNodes[e].updateTexture(),this._previousTextureNodes[e].updateTexture()}}getTextureNode(e="output"){let t=this._textureNodes[e];return void 0===t&&(this._textureNodes[e]=t=Sp(new oC(this,e)),this._textureNodes[e].updateTexture()),t}getPreviousTextureNode(e="output"){let t=this._previousTextureNodes[e];return void 0===t&&(void 0===this._textureNodes[e]&&this.getTextureNode(e),this._previousTextureNodes[e]=t=Sp(new oC(this,e,!0)),this._previousTextureNodes[e].updateTexture()),t}getViewZNode(e="depth"){let t=this._viewZNodes[e];if(void 0===t){const s=this._cameraNear,i=this._cameraFar;this._viewZNodes[e]=t=aT(this.getTextureNode(e),s,i)}return t}getLinearDepthNode(e="depth"){let t=this._linearDepthNodes[e];if(void 0===t){const s=this._cameraNear,i=this._cameraFar,r=this.getViewZNode(e);this._linearDepthNodes[e]=t=rT(r,s,i)}return t}setup({renderer:e}){return this.renderTarget.samples=void 0===this.options.samples?e.samples:this.options.samples,!0===e.backend.isWebGLBackend&&(this.renderTarget.samples=0),this.renderTarget.depthTexture.isMultisampleRenderTargetTexture=this.renderTarget.samples>1,this.scope===aC.COLOR?this.getTextureNode():this.getLinearDepthNode()}updateBefore(e){const{renderer:t}=e,{scene:s,camera:i}=this;this._pixelRatio=t.getPixelRatio();const r=t.getSize(rC);this.setSize(r.width,r.height);const n=t.getRenderTarget(),o=t.getMRT();this._cameraNear.value=i.near,this._cameraFar.value=i.far;for(const e in this._previousTextures)this.toggleTexture(e);t.setRenderTarget(this.renderTarget),t.setMRT(this._mrt),t.render(s,i),t.setRenderTarget(n),t.setMRT(o)}setSize(e,t){this._width=e,this._height=t;const s=this._width*this._pixelRatio,i=this._height*this._pixelRatio;this.renderTarget.setSize(s,i)}setPixelRatio(e){this._pixelRatio=e,this.setSize(this._width,this._height)}dispose(){this.renderTarget.dispose()}}aC.COLOR="color",aC.DEPTH="depth";const hC=(e,t,s)=>Sp(new aC(aC.COLOR,e,t,s)),uC=(e,t)=>Sp(new nC(e,t)),lC=(e,t)=>Sp(new aC(aC.DEPTH,e,t)),cC=new dN,dC=new dN;class pC extends kd{static get type(){return"GaussianBlurNode"}constructor(e,t=null,s=2){super("vec4"),this.textureNode=e,this.directionNode=t,this.sigma=s,this._invSize=pm(new Qs),this._passDirection=pm(new Qs),this._horizontalRT=new _i,this._horizontalRT.texture.name="GaussianBlurNode.horizontal",this._verticalRT=new _i,this._verticalRT.texture.name="GaussianBlurNode.vertical",this._textureNode=uC(this,this._verticalRT.texture),this.updateBeforeType=Bd.RENDER,this.resolution=new Qs(1,1)}setSize(e,t){e=Math.max(Math.round(e*this.resolution.x),1),t=Math.max(Math.round(t*this.resolution.y),1),this._invSize.value.set(1/e,1/t),this._horizontalRT.setSize(e,t),this._verticalRT.setSize(e,t)}updateBefore(e){const{renderer:t}=e,s=this.textureNode,i=s.value,r=t.getRenderTarget(),n=t.getMRT(),o=s.value;cC.material=this._material,dC.material=this._material,this.setSize(i.image.width,i.image.height);const a=i.type;this._horizontalRT.texture.type=a,this._verticalRT.texture.type=a,t.setMRT(null),t.setRenderTarget(this._horizontalRT),this._passDirection.value.set(1,0),cC.render(t),s.value=this._horizontalRT.texture,t.setRenderTarget(this._verticalRT),this._passDirection.value.set(0,1),dC.render(t),t.setRenderTarget(r),t.setMRT(n),s.value=o}getTextureNode(){return this._textureNode}setup(e){const t=this.textureNode;if(!0!==t.isTextureNode)return console.error("GaussianBlurNode requires a TextureNode."),Xp();const s=t.uvNode||My(),i=Dp(this.directionNode||1),r=e=>t.uv(e),n=Rp((()=>{const e=3+2*this.sigma,t=this._getCoefficients(e),n=this._invSize,o=i.mul(this._passDirection),a=Up(t[0]).toVar(),h=Xp(r(s).mul(a)).toVar();for(let i=1;iSp(new pC(fN(e),t,s)),gC=new Qs,fC=new dN;class yC extends kd{static get type(){return"AfterImageNode"}constructor(e,t=.96){super(e),this.textureNode=e,this.textureNodeOld=By(),this.damp=pm(t),this._compRT=new _i,this._compRT.texture.name="AfterImageNode.comp",this._oldRT=new _i,this._oldRT.texture.name="AfterImageNode.old",this._textureNode=uC(this,this._compRT.texture),this.updateBeforeType=Bd.RENDER}getTextureNode(){return this._textureNode}setSize(e,t){this._compRT.setSize(e,t),this._oldRT.setSize(e,t)}updateBefore(e){const{renderer:t}=e,s=this.textureNode,i=s.value.type;this._compRT.texture.type=i,this._oldRT.texture.type=i,t.getDrawingBufferSize(gC),this.setSize(gC.x,gC.y);const r=t.getRenderTarget(),n=s.value;this.textureNodeOld.value=this._oldRT.texture,t.setRenderTarget(this._compRT),fC.render(t);const o=this._oldRT;this._oldRT=this._compRT,this._compRT=o,t.setRenderTarget(r),s.value=n}setup(e){const t=this.textureNode,s=this.textureNodeOld,i=t.uvNode||My();s.uvNode=i;const r=Rp((([e,t])=>{const s=Up(t).toVar(),i=Xp(e).toVar();return of(Hg(i.sub(s)),0)})),n=Rp((()=>{const e=Xp(s),n=Xp((e=>t.uv(e))(i));return e.mulAssign(this.damp.mul(r(e,.1))),of(n,e)})),o=this._materialComposed||(this._materialComposed=new pT);o.name="AfterImage",o.fragmentNode=n(),fC.material=o;return e.getNodeProperties(this).textureNode=t,this._textureNode}dispose(){this._compRT.dispose(),this._oldRT.dispose()}}const xC=(e,t)=>Sp(new yC(fN(e),t)),bC=Rp((([e])=>SC(e.rgb))),vC=Rp((([e,t=Up(1)])=>t.mix(SC(e.rgb),e.rgb))),TC=Rp((([e,t=Up(1)])=>{const s=Zm(e.r,e.g,e.b).div(3),i=e.r.max(e.g.max(e.b)),r=i.sub(s).mul(t).mul(-3);return Tf(e.rgb,i,r)})),_C=Rp((([e,t=Up(1)])=>{const s=jp(.57735,.57735,.57735),i=t.cos();return jp(e.rgb.mul(i).add(s.cross(e.rgb).mul(t.sin()).add(s.mul(df(s,e.rgb).mul(i.oneMinus())))))})),wC=new Ri,SC=(e,t=jp(...ci.getLuminanceCoefficients(wC)))=>df(e,t),MC=(e,t)=>Tf(jp(0),e,SC(e).sub(t).max(0)),NC=new dN;class AC extends kd{static get type(){return"AnamorphicNode"}constructor(e,t,s,i){super("vec4"),this.textureNode=e,this.tresholdNode=t,this.scaleNode=s,this.colorNode=jp(.1,0,1),this.samples=i,this.resolution=new Qs(1,1),this._renderTarget=new _i,this._renderTarget.texture.name="anamorphic",this._invSize=pm(new Qs),this._textureNode=uC(this,this._renderTarget.texture),this.updateBeforeType=Bd.RENDER}getTextureNode(){return this._textureNode}setSize(e,t){this._invSize.value.set(1/e,1/t),e=Math.max(Math.round(e*this.resolution.x),1),t=Math.max(Math.round(t*this.resolution.y),1),this._renderTarget.setSize(e,t)}updateBefore(e){const{renderer:t}=e,s=this.textureNode,i=s.value;this._renderTarget.texture.type=i.type;const r=t.getRenderTarget(),n=s.value;NC.material=this._material,this.setSize(i.image.width,i.image.height),t.setRenderTarget(this._renderTarget),NC.render(t),t.setRenderTarget(r),s.value=n}setup(e){const t=this.textureNode,s=t.uvNode||My(),i=Rp((()=>{const e=this.samples,i=Math.floor(e/2),r=jp(0).toVar();return bv({start:-i,end:i},(({i:e})=>{const n=Up(e).abs().div(i).oneMinus(),o=(e=>t.uv(e))(Dp(s.x.add(this._invSize.x.mul(e).mul(this.scaleNode)),s.y)),a=MC(o,this.tresholdNode).mul(n);r.addAssign(a)})),r.mul(this.colorNode)})),r=this._material||(this._material=new pT);r.name="Anamorphic",r.fragmentNode=i();return e.getNodeProperties(this).textureNode=t,this._textureNode}dispose(){this._renderTarget.dispose()}}const CC=(e,t=.9,s=3,i=32)=>Sp(new AC(fN(e),Sp(t),Sp(s),i));class RC extends kd{static get type(){return"SobelOperatorNode"}constructor(e){super(),this.textureNode=e,this.updateBeforeType=Bd.RENDER,this._invSize=pm(new Qs)}updateBefore(){const e=this.textureNode.value;this._invSize.value.set(1/e.image.width,1/e.image.height)}setup(){const{textureNode:e}=this,t=e.uvNode||My(),s=t=>e.uv(t);return Rp((()=>{const e=this._invSize,i=Qp(-1,-2,-1,0,0,0,1,2,1),r=Qp(-1,0,1,-2,0,2,-1,0,1),n=SC(s(t.add(e.mul(Dp(-1,-1)))).xyz),o=SC(s(t.add(e.mul(Dp(-1,0)))).xyz),a=SC(s(t.add(e.mul(Dp(-1,1)))).xyz),h=SC(s(t.add(e.mul(Dp(0,-1)))).xyz),u=SC(s(t.add(e.mul(Dp(0,0)))).xyz),l=SC(s(t.add(e.mul(Dp(0,1)))).xyz),c=SC(s(t.add(e.mul(Dp(1,-1)))).xyz),d=SC(s(t.add(e.mul(Dp(1,0)))).xyz),p=SC(s(t.add(e.mul(Dp(1,1)))).xyz),m=Zm(i[0][0].mul(n),i[1][0].mul(h),i[2][0].mul(c),i[0][1].mul(o),i[1][1].mul(u),i[2][1].mul(d),i[0][2].mul(a),i[1][2].mul(l),i[2][2].mul(p)),g=Zm(r[0][0].mul(n),r[1][0].mul(h),r[2][0].mul(c),r[0][1].mul(o),r[1][1].mul(u),r[2][1].mul(d),r[0][2].mul(a),r[1][2].mul(l),r[2][2].mul(p)),f=m.mul(m).add(g.mul(g)).sqrt();return Xp(jp(f),1)}))()}}const EC=e=>Sp(new RC(fN(e)));class BC extends kd{static get type(){return"DepthOfFieldNode"}constructor(e,t,s,i,r){super(),this.textureNode=e,this.viewZNode=t,this.focusNode=s,this.apertureNode=i,this.maxblurNode=r,this._aspect=pm(0),this.updateBeforeType=Bd.RENDER}updateBefore(){const e=this.textureNode.value;this._aspect.value=e.image.width/e.image.height}setup(){const e=this.textureNode,t=e.uvNode||My(),s=t=>e.uv(t);return Rp((()=>{const e=Dp(1,this._aspect),i=this.focusNode.add(this.viewZNode),r=Dp(_f(i.mul(this.apertureNode),this.maxblurNode.negate(),this.maxblurNode)),n=r.mul(.9),o=r.mul(.7),a=r.mul(.4);let h=Xp(0);return h=h.add(s(t)),h=h.add(s(t.add(Dp(0,.4).mul(e).mul(r)))),h=h.add(s(t.add(Dp(.15,.37).mul(e).mul(r)))),h=h.add(s(t.add(Dp(.29,.29).mul(e).mul(r)))),h=h.add(s(t.add(Dp(-.37,.15).mul(e).mul(r)))),h=h.add(s(t.add(Dp(.4,0).mul(e).mul(r)))),h=h.add(s(t.add(Dp(.37,-.15).mul(e).mul(r)))),h=h.add(s(t.add(Dp(.29,-.29).mul(e).mul(r)))),h=h.add(s(t.add(Dp(-.15,-.37).mul(e).mul(r)))),h=h.add(s(t.add(Dp(0,-.4).mul(e).mul(r)))),h=h.add(s(t.add(Dp(-.15,.37).mul(e).mul(r)))),h=h.add(s(t.add(Dp(-.29,.29).mul(e).mul(r)))),h=h.add(s(t.add(Dp(.37,.15).mul(e).mul(r)))),h=h.add(s(t.add(Dp(-.4,0).mul(e).mul(r)))),h=h.add(s(t.add(Dp(-.37,-.15).mul(e).mul(r)))),h=h.add(s(t.add(Dp(-.29,-.29).mul(e).mul(r)))),h=h.add(s(t.add(Dp(.15,-.37).mul(e).mul(r)))),h=h.add(s(t.add(Dp(.15,.37).mul(e).mul(n)))),h=h.add(s(t.add(Dp(-.37,.15).mul(e).mul(n)))),h=h.add(s(t.add(Dp(.37,-.15).mul(e).mul(n)))),h=h.add(s(t.add(Dp(-.15,-.37).mul(e).mul(n)))),h=h.add(s(t.add(Dp(-.15,.37).mul(e).mul(n)))),h=h.add(s(t.add(Dp(.37,.15).mul(e).mul(n)))),h=h.add(s(t.add(Dp(-.37,-.15).mul(e).mul(n)))),h=h.add(s(t.add(Dp(.15,-.37).mul(e).mul(n)))),h=h.add(s(t.add(Dp(.29,.29).mul(e).mul(o)))),h=h.add(s(t.add(Dp(.4,0).mul(e).mul(o)))),h=h.add(s(t.add(Dp(.29,-.29).mul(e).mul(o)))),h=h.add(s(t.add(Dp(0,-.4).mul(e).mul(o)))),h=h.add(s(t.add(Dp(-.29,.29).mul(e).mul(o)))),h=h.add(s(t.add(Dp(-.4,0).mul(e).mul(o)))),h=h.add(s(t.add(Dp(-.29,-.29).mul(e).mul(o)))),h=h.add(s(t.add(Dp(0,.4).mul(e).mul(o)))),h=h.add(s(t.add(Dp(.29,.29).mul(e).mul(a)))),h=h.add(s(t.add(Dp(.4,0).mul(e).mul(a)))),h=h.add(s(t.add(Dp(.29,-.29).mul(e).mul(a)))),h=h.add(s(t.add(Dp(0,-.4).mul(e).mul(a)))),h=h.add(s(t.add(Dp(-.29,.29).mul(e).mul(a)))),h=h.add(s(t.add(Dp(-.4,0).mul(e).mul(a)))),h=h.add(s(t.add(Dp(-.29,-.29).mul(e).mul(a)))),h=h.add(s(t.add(Dp(0,.4).mul(e).mul(a)))),h=h.div(41),h.a=1,Xp(h)}))()}}const IC=(e,t,s=1,i=.025,r=1)=>Sp(new BC(fN(e),Sp(t),Sp(s),Sp(i),Sp(r)));class PC extends kd{static get type(){return"DotScreenNode"}constructor(e,t=new Qs(.5,.5),s=1.57,i=1){super("vec4"),this.inputNode=e,this.center=pm(t),this.angle=pm(s),this.scale=pm(i)}setup(){const e=this.inputNode,t=Rp((()=>{const e=Lg(this.angle),t=Vg(this.angle),s=My().mul(kv).sub(this.center),i=Dp(t.mul(s.x).sub(e.mul(s.y)),e.mul(s.x).add(t.mul(s.y))).mul(this.scale);return Lg(i.x).mul(Lg(i.y)).mul(4)})),s=Rp((()=>{const s=e,i=Zm(s.r,s.g,s.b).div(3);return Xp(jp(i.mul(10).sub(5).add(t())),s.a)}));return s()}}const FC=(e,t,s,i)=>Sp(new PC(Sp(e),t,s,i));class zC extends kd{static get type(){return"RGBShiftNode"}constructor(e,t=.005,s=0){super("vec4"),this.textureNode=e,this.amount=pm(t),this.angle=pm(s)}setup(){const{textureNode:e}=this,t=e.uvNode||My(),s=t=>e.uv(t);return Rp((()=>{const e=Dp(Vg(this.angle),Lg(this.angle)).mul(this.amount),i=s(t.add(e)),r=s(t),n=s(t.sub(e));return Xp(i.r,r.g,n.b,r.a)}))()}}const UC=(e,t,s)=>Sp(new zC(fN(e),t,s));class OC extends kd{static get type(){return"FilmNode"}constructor(e,t=null,s=null){super(),this.inputNode=e,this.intensityNode=t,this.uvNode=s}setup(){const e=this.uvNode||My(),t=Rp((()=>{const t=this.inputNode.rgb,s=Af(Og(e.add(BM())));let i=t.add(t.mul(_f(s.add(.1),0,1)));return null!==this.intensityNode&&(i=Tf(t,i,this.intensityNode)),Xp(i,this.inputNode.a)}));return t()}}const LC=Ap(OC);class VC extends kd{static get type(){return"Lut3DNode"}constructor(e,t,s,i){super(),this.inputNode=e,this.lutNode=t,this.size=pm(s),this.intensityNode=i}setup(){const{inputNode:e,lutNode:t}=this,s=Rp((()=>{const s=e,i=Up(1).div(this.size),r=Up(.5).div(this.size),n=jp(r).add(s.rgb.mul(Up(1).sub(i))),o=Xp((e=>t.uv(e))(n).rgb,s.a);return Xp(Tf(s,o,this.intensityNode))}));return s()}}const DC=(e,t,s,i)=>Sp(new VC(Sp(e),Sp(t),s,Sp(i))),kC=new dN,GC=new Jr,WC=new Qs;class jC extends kd{static get type(){return"GTAONode"}constructor(e,t,s){super(),this.depthNode=e,this.normalNode=t,this.radius=pm(.25),this.resolution=pm(new Qs),this.thickness=pm(1),this.distanceExponent=pm(1),this.distanceFallOff=pm(1),this.scale=pm(1),this.noiseNode=By(function(e=5){const t=Math.floor(e)%2==0?Math.floor(e)+1:Math.floor(e),s=function(e){const t=Math.floor(e)%2==0?Math.floor(e)+1:Math.floor(e),s=t*t,i=Array(s).fill(0);let r=Math.floor(t/2),n=t-1;for(let e=1;e<=s;)-1===r&&n===t?(n=t-2,r=0):(n===t&&(n=0),r<0&&(r=t-1)),0===i[r*t+n]?(i[r*t+n]=e++,n++,r--):(n-=2,r++);return i}(t),i=s.length,r=new Uint8Array(4*i);for(let e=0;ethis.depthNode.uv(e).x,i=e=>this.noiseNode.uv(e),r=Rp((([e])=>{const t=this.cameraProjectionMatrix.mul(Xp(e,1));let i=t.xy.div(t.w).mul(.5).add(.5).toVar();i=Dp(i.x,i.y.oneMinus());const r=s(i);return jp(i,r)})),n=Rp((([e,t])=>{e=Dp(e.x,e.y.oneMinus()).mul(2).sub(1);const s=Xp(jp(e,t),1),i=Xp(this.cameraProjectionMatrixInverse.mul(s));return i.xyz.div(i.w)})),o=Rp((()=>{const e=s(t);e.greaterThanEqual(1).discard();const o=n(t,e),a=this.normalNode.rgb.normalize(),h=this.radius,u=Ay(this.noiseNode,0);let l=Dp(t.x,t.y.oneMinus());l=l.mul(this.resolution.div(u));const c=i(l),d=c.xyz.mul(2).sub(1),p=jp(d.xy,0).normalize(),m=jp(p.y.mul(-1),p.x,0),g=Qp(p,m,jp(0,0,1)),f=this.SAMPLES.lessThan(30).select(3,5),y=Zm(this.SAMPLES,f.sub(1)).div(f),x=Up(0).toVar();return bv({start:Op(0),end:f,type:"int",condition:"<"},(({i:e})=>{const t=Up(e).div(Up(f)).mul(Tg),s=Xp(Vg(t),Lg(t),0,Zm(.5,Km(.5,c.w)));s.xyz=Ug(g.mul(s.xyz));const i=Ug(o.xyz.negate()),u=Ug(pf(s.xyz,i)),l=pf(u,i),d=Ug(a.sub(u.mul(df(a,u)))),p=pf(d,u),m=Dp(df(i,p),df(i,p.negate())).toVar();bv({end:y,type:"int",name:"j",condition:"<"},(({j:e})=>{const t=s.xyz.mul(h).mul(s.w).mul(mf(Qm(Up(e).add(1),Up(y)),this.distanceExponent)),a=r(o.add(t)),u=n(a.xy,a.z).sub(o);Pp(jg(u.z).lessThan(this.thickness),(()=>{const t=df(i,Ug(u));m.x.addAssign(of(0,Km(t.sub(m.x),Tf(1,Up(2).div(Up(e).add(2)),this.distanceFallOff))))}));const l=r(o.sub(t)),c=n(l.xy,l.z).sub(o);Pp(jg(c.z).lessThan(this.thickness),(()=>{const t=df(i,Ug(c));m.y.addAssign(of(0,Km(t.sub(m.y),Tf(1,Up(2).div(Up(e).add(2)),this.distanceFallOff))))}))}));const b=Ig(Jm(1,m.mul(m))),v=df(d,l),T=df(d,i),_=Km(.5,Gg(m.y).sub(Gg(m.x)).add(b.x.mul(m.x).sub(b.y.mul(m.y)))),w=Km(.5,Jm(2,m.x.mul(m.x)).sub(m.y.mul(m.y))),S=v.mul(_).add(T.mul(w));x.addAssign(S)})),x.assign(_f(x.div(f),0,1)),x.assign(mf(x,this.scale)),Xp(jp(x),1)})),a=this._material||(this._material=new pT);return a.fragmentNode=o().context(e.getSharedContext()),a.name="GTAO",a.needsUpdate=!0,this._textureNode}dispose(){this._aoRenderTarget.dispose()}}const HC=(e,t,s)=>Sp(new jC(Sp(e),Sp(t),s));class qC extends kd{static get type(){return"DenoiseNode"}constructor(e,t,s,i,r){super(),this.textureNode=e,this.depthNode=t,this.normalNode=s,this.noiseNode=i,this.cameraProjectionMatrixInverse=pm(r.projectionMatrixInverse),this.lumaPhi=pm(5),this.depthPhi=pm(5),this.normalPhi=pm(5),this.radius=pm(5),this.index=pm(0),this._resolution=pm(new Qs),this._sampleVectors=Ox(function(e,t,s){const i=function(e,t,s){const i=[];for(let r=0;rthis.textureNode.uv(e),s=e=>this.depthNode.uv(e).x,i=e=>this.normalNode.uv(e),r=e=>this.noiseNode.uv(e),n=Rp((([e,t])=>{e=Dp(e.x,e.y.oneMinus()).mul(2).sub(1);const s=Xp(jp(e,t),1),i=Xp(this.cameraProjectionMatrixInverse.mul(s));return i.xyz.div(i.w)})),o=Rp((([e,r,o,a])=>{const h=t(a),u=s(a),l=i(a).rgb.normalize(),c=h.rgb,d=n(a,u),p=df(r,l).toVar(),m=mf(of(p,0),this.normalPhi).toVar(),g=jg(SC(c).sub(SC(e))).toVar(),f=of(Up(1).sub(g.div(this.lumaPhi)),0).toVar(),y=jg(df(o.sub(d),r)).toVar(),x=of(Up(1).sub(y.div(this.depthPhi)),0),b=f.mul(x).mul(m);return Xp(c.mul(b),b)})),a=Rp((([e])=>{const a=s(e),h=i(e).rgb.normalize(),u=t(e);Pp(a.greaterThanEqual(1).or(df(h,h).equal(0)),(()=>u));const l=jp(u.rgb),c=n(e,a),d=Ay(this.noiseNode,0);let p=Dp(e.x,e.y.oneMinus());p=p.mul(this._resolution.div(d));const m=r(p),g=Lg(m.element(this.index.mod(4).mul(2).mul(Tg))),f=Vg(m.element(this.index.mod(4).mul(2).mul(Tg))),y=Dp(g,f),x=Kp(y.x,y.y.negate(),y.x,y.y),b=Up(1).toVar(),v=jp(u.rgb).toVar();return bv({start:Op(0),end:Op(16),type:"int",condition:"<"},(({i:t})=>{const s=this._sampleVectors.element(t).toVar(),i=x.mul(s.xy.mul(Up(1).add(s.z.mul(this.radius.sub(1))))).div(this._resolution).toVar(),r=e.add(i).toVar(),n=o(l,h,c,r);v.addAssign(n.xyz),b.addAssign(n.w)})),Pp(b.greaterThan(Up(0)),(()=>{v.divAssign(b)})),Xp(v,u.a)})).setLayout({name:"denoise",type:"vec4",inputs:[{name:"uv",type:"vec2"}]});return Rp((()=>a(e)))()}}const $C=(e,t,s,i,r)=>Sp(new qC(fN(e),Sp(t),Sp(s),Sp(i),r));class XC extends kd{static get type(){return"FXAANode"}constructor(e){super(),this.textureNode=e,this.updateBeforeType=Bd.RENDER,this._invSize=pm(new Qs)}updateBefore(){const e=this.textureNode.value;this._invSize.value.set(1/e.image.width,1/e.image.height)}setup(){const e=this.textureNode.bias(-100),t=e.uvNode||My(),s=t=>e.uv(t),i=(t,s,i)=>e.uv(t.add(s.mul(i))),r=Op(5),n=Rp((([e,t])=>{const s=Xp(t).toVar(),i=Xp(e).toVar(),r=Xp(jg(i.sub(s))).toVar();return of(of(of(r.r,r.g),r.b),r.a)})),o=Rp((([e,t,o,a])=>{const h=s(e).toVar(),u=i(e,Dp(0,-1),t.xy).toVar(),l=i(e,Dp(1,0),t.xy).toVar(),c=i(e,Dp(0,1),t.xy).toVar(),d=i(e,Dp(-1,0),t.xy).toVar(),p=n(h,c).toVar(),m=n(h,u).toVar(),g=n(h,l).toVar(),f=n(h,d).toVar(),y=of(p,of(m,of(g,f))).toVar();Pp(y.lessThan(o),(()=>h));const x=Jm(p.add(m),g.add(f)).toVar();x.mulAssign(a),Pp(jg(x).lessThan(.3),(()=>{const s=g.greaterThan(f).select(1,-1).toVar(),r=m.greaterThan(p).select(1,-1).toVar(),o=Dp(s,r).toVar(),y=i(e,Dp(o.x,o.y),t.xy),b=n(h,y).toVar(),v=i(e,Dp(o.x.negate(),o.y.negate()),t.xy),T=n(h,v).toVar();x.assign(T.sub(b)),x.mulAssign(a),Pp(jg(x).lessThan(.3),(()=>{const e=c.add(u).add(l).add(d);return Tf(h,e.mul(.25),.4)}))}));const b=Dp().toVar();Pp(x.lessThanEqual(0),(()=>{c.assign(d),u.assign(l),b.x.assign(0),b.y.assign(t.y)})).Else((()=>{b.x.assign(t.x),b.y.assign(0)}));const v=n(h,c).toVar(),T=n(h,u).toVar();Pp(v.lessThanEqual(T),(()=>{c.assign(u)}));const _=Op(0).toVar(),w=Op(0).toVar(),S=Up(0).toVar(),M=Up(0).toVar(),N=Dp(e).toVar(),A=Dp(e).toVar(),C=Op(0).toVar(),R=Op(0).toVar();bv(r,(({i:t})=>{const i=t.add(1).toVar();Pp(_.equal(0),(()=>{S.addAssign(i),N.assign(e.add(b.mul(S)));const r=s(N.xy),o=n(r,h).toVar(),a=n(r,c).toVar();Pp(o.greaterThan(a),(()=>{_.assign(1)})),C.assign(t)})),Pp(w.equal(0),(()=>{M.addAssign(i),A.assign(e.sub(b.mul(M)));const r=s(A.xy),o=n(r,h).toVar(),a=n(r,c).toVar();Pp(o.greaterThan(a),(()=>{w.assign(1)})),R.assign(t)})),Pp(_.equal(1).or(w.equal(1)),(()=>{Tv()}))})),Pp(_.equal(0).and(w.equal(0)),(()=>h));const E=Up(1).toVar(),B=Up(1).toVar();Pp(_.equal(1),(()=>{E.assign(Up(C).div(Up(r.sub(1))))})),Pp(w.equal(1),(()=>{B.assign(Up(R).div(Up(r.sub(1))))}));const I=nf(E,B);return I.assign(mf(I,.5)),I.assign(Up(1).sub(I)),Tf(h,c,I.mul(.5))})).setLayout({name:"FxaaPixelShader",type:"vec4",inputs:[{name:"uv",type:"vec2"},{name:"fxaaQualityRcpFrame",type:"vec2"},{name:"fxaaQualityEdgeThreshold",type:"float"},{name:"fxaaQualityinvEdgeThreshold",type:"float"}]});return Rp((()=>{const e=Up(.2),s=Up(1).div(e);return o(t,this._invSize,e,s)}))()}}const YC=e=>Sp(new XC(fN(e))),ZC=new dN,JC=new Jr(0,0,0),KC=new Jr,QC=new Qs,eR=new Qs(1,0),tR=new Qs(0,1);class sR extends kd{static get type(){return"BloomNode"}constructor(e,t=1,s=0,i=0){super(),this.inputNode=e,this.strength=pm(t),this.radius=pm(s),this.threshold=pm(i),this.smoothWidth=pm(.01),this._renderTargetsHorizontal=[],this._renderTargetsVertical=[],this._nMips=5,this._renderTargetBright=new _i(1,1,{type:Pe}),this._renderTargetBright.texture.name="UnrealBloomPass.bright",this._renderTargetBright.texture.generateMipmaps=!1;for(let e=0;e{const e=this.inputNode,t=SC(e.rgb),s=Mf(this.threshold,this.threshold.add(this.smoothWidth),t);return Tf(Xp(0),e,s)}));this._highPassFilterMaterial=this._highPassFilterMaterial||new pT,this._highPassFilterMaterial.fragmentNode=t().context(e.getSharedContext()),this._highPassFilterMaterial.name="Bloom_highPass",this._highPassFilterMaterial.needsUpdate=!0;const s=[3,5,7,9,11];for(let t=0;t{const s=Up(1.2).sub(e);return Tf(e,s,t)})).setLayout({name:"lerpBloomFactor",type:"float",inputs:[{name:"factor",type:"float"},{name:"radius",type:"float"}]}),o=Rp((()=>{const e=n(i.element(0),this.radius).mul(Xp(r.element(0),1)).mul(this._textureNodeBlur0),t=n(i.element(1),this.radius).mul(Xp(r.element(1),1)).mul(this._textureNodeBlur1),s=n(i.element(2),this.radius).mul(Xp(r.element(2),1)).mul(this._textureNodeBlur2),o=n(i.element(3),this.radius).mul(Xp(r.element(3),1)).mul(this._textureNodeBlur3),a=n(i.element(4),this.radius).mul(Xp(r.element(4),1)).mul(this._textureNodeBlur4);return e.add(t).add(s).add(o).add(a).mul(this.strength)}));return this._compositeMaterial=this._compositeMaterial||new pT,this._compositeMaterial.fragmentNode=o().context(e.getSharedContext()),this._compositeMaterial.name="Bloom_comp",this._compositeMaterial.needsUpdate=!0,this._textureOutput}dispose(){for(let e=0;ei.uv(e),u=Rp((()=>{const e=r.element(0).toVar(),s=h(a).rgb.mul(e).toVar();return bv({start:Op(1),end:Op(t),type:"int",condition:"<"},(({i:t})=>{const i=Up(t),u=r.element(t),l=o.mul(n).mul(i),c=h(a.add(l)).rgb,d=h(a.sub(l)).rgb;s.addAssign(Zm(c,d).mul(u)),e.addAssign(Up(2).mul(u))})),Xp(s.div(e),1)})),l=new pT;return l.fragmentNode=u().context(e.getSharedContext()),l.name="Bloom_seperable",l.needsUpdate=!0,l.colorTexture=i,l.direction=o,l.invSize=n,l}}const iR=(e,t,s,i)=>Sp(new sR(Sp(e),t,s,i));class rR extends kd{static get type(){return"TransitionNode"}constructor(e,t,s,i,r,n){super(),this.textureNodeA=e,this.textureNodeB=t,this.mixTextureNode=s,this.mixRatioNode=i,this.thresholdNode=r,this.useTextureNode=n}setup(){const{textureNodeA:e,textureNodeB:t,mixTextureNode:s,mixRatioNode:i,thresholdNode:r,useTextureNode:n}=this,o=e=>{const t=e.uvNode||My();return e.uv(t)},a=Rp((()=>{const a=o(e),h=o(t),u=Xp().toVar();return Pp(n.equal(Op(1)),(()=>{const e=o(s),t=i.mul(r.mul(2).add(1)).sub(r),n=_f(Jm(e.r,t).mul(Up(1).div(r)),0,1);u.assign(Tf(a,h,n))})).Else((()=>{u.assign(Tf(h,a,i))})),u}));return a()}}const nR=(e,t,s,i=0,r=.1,n=0)=>Sp(new rR(fN(e),fN(t),fN(s),Sp(i),Sp(r),Sp(n)));class oR extends kd{static get type(){return"PixelationNode"}constructor(e,t,s,i,r,n){super(),this.textureNode=e,this.depthNode=t,this.normalNode=s,this.pixelSize=i,this.normalEdgeStrength=r,this.depthEdgeStrength=n,this._resolution=pm(new Ti),this.updateBeforeType=Bd.RENDER}updateBefore(){const e=this.textureNode.value,t=e.image.width,s=e.image.height;this._resolution.value.set(t,s,1/t,1/s)}setup(){const{textureNode:e,depthNode:t,normalNode:s}=this,i=e.uvNode||My(),r=t.uvNode||My(),n=s.uvNode||My(),o=(e,s)=>t.uv(r.add(Dp(e,s).mul(this._resolution.zw))).r,a=(e,t)=>s.uv(n.add(Dp(e,t).mul(this._resolution.zw))).rgb.normalize(),h=(e,t,s,i)=>{const r=o(e,t).sub(s),n=a(e,t),h=jp(1,1,1),u=df(i.sub(n),h),l=_f(Mf(-.01,.01,u),0,1),c=_f(Hg(r.mul(.25).add(.0025)),0,1);return Up(1).sub(df(i,n)).mul(c).mul(l)},u=Rp((()=>{const t=e.uv(i),s=gm("float","depth"),r=gm("vec3","normal");Pp(this.depthEdgeStrength.greaterThan(0).or(this.normalEdgeStrength.greaterThan(0)),(()=>{s.assign(o(0,0)),r.assign(a(0,0))}));const n=gm("float","dei");Pp(this.depthEdgeStrength.greaterThan(0),(()=>{n.assign((e=>{const t=gm("float","diff");return t.addAssign(_f(o(1,0).sub(e))),t.addAssign(_f(o(-1,0).sub(e))),t.addAssign(_f(o(0,1).sub(e))),t.addAssign(_f(o(0,-1).sub(e))),Fg(Mf(.01,.02,t).mul(2)).div(2)})(s))}));const u=gm("float","nei");Pp(this.normalEdgeStrength.greaterThan(0),(()=>{u.assign(((e,t)=>{const s=gm("float","indicator");return s.addAssign(h(0,-1,e,t)),s.addAssign(h(0,1,e,t)),s.addAssign(h(-1,0,e,t)),s.addAssign(h(1,0,e,t)),hf(.1,s)})(s,r))}));const l=n.greaterThan(0).select(Up(1).sub(n.mul(this.depthEdgeStrength)),u.mul(this.normalEdgeStrength).add(1));return t.mul(l)}));return u()}}class aR extends aC{static get type(){return"PixelationPassNode"}constructor(e,t,s=6,i=.3,r=.4){super("color",e,t,{minFilter:fe,magFilter:fe}),this.pixelSize=s,this.normalEdgeStrength=i,this.depthEdgeStrength=r,this.isPixelationPassNode=!0,this._mrt=NM({output:zm,normal:bx})}setSize(e,t){const s=this.pixelSize.value?this.pixelSize.value:this.pixelSize,i=Math.floor(e/s),r=Math.floor(t/s);super.setSize(i,r)}setup(){return((e,t,s,i=6,r=.3,n=.4)=>Sp(new oR(fN(e),fN(t),fN(s),Sp(i),Sp(r),Sp(n))))(super.getTextureNode("output"),super.getTextureNode("depth"),super.getTextureNode("normal"),this.pixelSize,this.normalEdgeStrength,this.depthEdgeStrength)}}const hR=(e,t,s,i,r)=>Sp(new aR(e,t,s,i,r)),uR=new Qs;class lR extends aC{static get type(){return"SSAAPassNode"}constructor(e,t){super(aC.COLOR,e,t),this.isSSAAPassNode=!0,this.sampleLevel=4,this.unbiased=!0,this.clearColor=new Jr(0),this.clearAlpha=0,this._currentClearColor=new Jr,this.sampleWeight=pm(1),this.sampleRenderTarget=null,this._quadMesh=new dN}updateBefore(e){const{renderer:t}=e,{scene:s,camera:i}=this;this._pixelRatio=t.getPixelRatio();const r=t.getSize(uR);this.setSize(r.width,r.height),this.sampleRenderTarget.setSize(this.renderTarget.width,this.renderTarget.height),t.getClearColor(this._currentClearColor);const n=t.getClearAlpha(),o=t.getRenderTarget(),a=t.getMRT(),h=t.autoClear;this._cameraNear.value=i.near,this._cameraFar.value=i.far,t.setMRT(this.getMRT()),t.autoClear=!1;const u=cR[Math.max(0,Math.min(this.sampleLevel,5))],l=1/u.length,c={fullWidth:this.renderTarget.width,fullHeight:this.renderTarget.height,offsetX:0,offsetY:0,width:this.renderTarget.width,height:this.renderTarget.height},d=Object.assign({},i.view);d.enabled&&Object.assign(c,d);for(let e=0;e=0&&(e[t]=By(this.sampleRenderTarget.textures[s]).mul(this.sampleWeight))}t=NM(e)}else t=By(this.sampleRenderTarget.texture).mul(this.sampleWeight);return this._quadMesh.material=new pT,this._quadMesh.material.fragmentNode=t,this._quadMesh.material.transparent=!0,this._quadMesh.material.depthTest=!1,this._quadMesh.material.depthWrite=!1,this._quadMesh.material.premultipliedAlpha=!0,this._quadMesh.material.blending=2,this._quadMesh.material.normals=!1,this._quadMesh.material.name="SSAA",super.setup(e)}dispose(){super.dispose(),null!==this.sampleRenderTarget&&this.sampleRenderTarget.dispose()}}const cR=[[[0,0]],[[4,4],[-4,-4]],[[-2,-6],[6,-2],[-6,2],[2,6]],[[1,-3],[-1,3],[5,1],[-3,-5],[-5,5],[-7,-1],[3,7],[7,-7]],[[1,1],[-1,-3],[-3,2],[4,-1],[-5,-2],[2,5],[5,3],[3,-5],[-2,6],[0,-7],[-4,-6],[-6,4],[-8,0],[7,-4],[6,7],[-7,-8]],[[-4,-7],[-7,-5],[-3,-5],[-5,-4],[-1,-4],[-2,-2],[-6,-1],[-4,0],[-7,1],[-1,2],[-6,3],[-3,3],[-7,6],[-3,6],[-5,7],[-1,7],[5,-7],[1,-6],[6,-5],[4,-4],[2,-3],[7,-2],[1,-1],[4,-1],[2,1],[6,2],[0,4],[4,4],[2,5],[7,5],[5,6],[3,7]]],dR=(e,t)=>Sp(new lR(e,t)),pR=new Qs;class mR extends aC{static get type(){return"StereoPassNode"}constructor(e,t){super(aC.COLOR,e,t),this.isStereoPassNode=!0,this.stereo=new ql,this.stereo.aspect=.5}updateBefore(e){const{renderer:t}=e,{scene:s,camera:i,stereo:r,renderTarget:n}=this;this._pixelRatio=t.getPixelRatio(),r.cameraL.coordinateSystem=t.coordinateSystem,r.cameraR.coordinateSystem=t.coordinateSystem,r.update(i);const o=t.getSize(pR);this.setSize(o.width,o.height);const a=t.autoClear;t.autoClear=!1;const h=t.getRenderTarget(),u=t.getMRT();this._cameraNear.value=i.near,this._cameraFar.value=i.far;for(const e in this._previousTextures)this.toggleTexture(e);t.setRenderTarget(n),t.setMRT(this._mrt),t.clear(),n.scissorTest=!0,n.scissor.set(0,0,n.width/2,n.height),n.viewport.set(0,0,n.width/2,n.height),t.render(s,r.cameraL),n.scissor.set(n.width/2,0,n.width/2,n.height),n.viewport.set(n.width/2,0,n.width/2,n.height),t.render(s,r.cameraR),n.scissorTest=!1,t.setRenderTarget(h),t.setMRT(u),t.autoClear=a}}const gR=(e,t)=>Sp(new mR(e,t)),fR=new Qs,yR=new dN;class xR extends aC{static get type(){return"StereoCompositePassNode"}constructor(e,t){super(aC.COLOR,e,t),this.isStereoCompositePassNode=!0,this.stereo=new ql;const s={minFilter:Te,magFilter:fe,type:Pe};this._renderTargetL=new _i(1,1,s),this._renderTargetR=new _i(1,1,s),this._mapLeft=By(this._renderTargetL.texture),this._mapRight=By(this._renderTargetR.texture),this._material=null}updateStereoCamera(e){this.stereo.cameraL.coordinateSystem=e,this.stereo.cameraR.coordinateSystem=e,this.stereo.update(this.camera)}setSize(e,t){super.setSize(e,t),this._renderTargetL.setSize(this.renderTarget.width,this.renderTarget.height),this._renderTargetR.setSize(this.renderTarget.width,this.renderTarget.height)}updateBefore(e){const{renderer:t}=e,{scene:s,stereo:i,renderTarget:r}=this;this._pixelRatio=t.getPixelRatio(),this.updateStereoCamera(t.coordinateSystem);const n=t.getSize(fR);this.setSize(n.width,n.height);const o=t.getRenderTarget();t.setRenderTarget(this._renderTargetL),t.render(s,i.cameraL),t.setRenderTarget(this._renderTargetR),t.render(s,i.cameraR),t.setRenderTarget(r),yR.material=this._material,yR.render(t),t.setRenderTarget(o)}dispose(){super.dispose(),this._renderTargetL.dispose(),this._renderTargetR.dispose(),null!==this._material&&this._material.dispose()}}class bR extends xR{static get type(){return"AnaglyphPassNode"}constructor(e,t){super(e,t),this.isAnaglyphPassNode=!0,this._colorMatrixLeft=pm((new ei).fromArray([.4561,-.0400822,-.0152161,.500484,-.0378246,-.0205971,.176381,-.0157589,-.00546856])),this._colorMatrixRight=pm((new ei).fromArray([-.0434706,.378476,-.0721527,-.0879388,.73364,-.112961,-.00155529,-.0184503,1.2264]))}setup(e){const t=My(),s=Rp((()=>{const e=this._mapLeft.uv(t),s=this._mapRight.uv(t),i=_f(this._colorMatrixLeft.mul(e.rgb).add(this._colorMatrixRight.mul(s.rgb)));return Xp(i.rgb,of(e.a,s.a))})),i=this._material||(this._material=new pT);return i.fragmentNode=s().context(e.getSharedContext()),i.name="Anaglyph",i.needsUpdate=!0,super.setup(e)}}const vR=(e,t)=>Sp(new bR(e,t));class TR extends xR{static get type(){return"ParallaxBarrierPassNode"}constructor(e,t){super(e,t),this.isParallaxBarrierPassNode=!0}setup(e){const t=My(),s=Rp((()=>{const e=Xp().toVar();return Pp(af(Gv.y,2).greaterThan(1),(()=>{e.assign(this._mapLeft.uv(t))})).Else((()=>{e.assign(this._mapRight.uv(t))})),e})),i=this._material||(this._material=new pT);return i.fragmentNode=s().context(e.getSharedContext()),i.needsUpdate=!0,super.setup(e)}}const _R=(e,t)=>Sp(new TR(e,t));class wR extends aC{static get type(){return"ToonOutlinePassNode"}constructor(e,t,s,i,r){super(aC.COLOR,e,t),this.colorNode=s,this.thicknessNode=i,this.alphaNode=r,this._materialCache=new WeakMap}updateBefore(e){const{renderer:t}=e,s=t.getRenderObjectFunction();t.setRenderObjectFunction(((e,s,i,r,n,o,a)=>{if((n.isMeshToonMaterial||n.isMeshToonNodeMaterial)&&!1===n.wireframe){const h=this._getOutlineMaterial(n);t.renderObject(e,s,i,r,h,o,a)}t.renderObject(e,s,i,r,n,o,a)})),super.updateBefore(e),t.setRenderObjectFunction(s)}_createMaterial(){const e=new pT;e.isMeshToonOutlineMaterial=!0,e.name="Toon_Outline",e.side=d;const t=yx.negate(),s=Oy.mul(ix),i=Up(1),r=s.mul(Xp(ax,1)),n=s.mul(Xp(ax.add(t),1)),o=Ug(r.sub(n));return e.vertexNode=r.add(o.mul(this.thicknessNode).mul(r.w).mul(i)),e.colorNode=Xp(this.colorNode,this.alphaNode),e}_getOutlineMaterial(e){let t=this._materialCache.get(e);return void 0===t&&(t=this._createMaterial(),this._materialCache.set(e,t)),t}}const SR=(e,t,s=new Jr(0,0,0),i=.003,r=1)=>Sp(new wR(e,t,Sp(s),Sp(i),Sp(r)));class MR extends Ld{static get type(){return"ScriptableValueNode"}constructor(e=null){super(),this._value=e,this._cache=null,this.inputType=null,this.outpuType=null,this.events=new ks,this.isScriptableValueNode=!0}get isScriptableOutputNode(){return null!==this.outputType}set value(e){this._value!==e&&(this._cache&&"URL"===this.inputType&&this.value.value instanceof ArrayBuffer&&(URL.revokeObjectURL(this._cache),this._cache=null),this._value=e,this.events.dispatchEvent({type:"change"}),this.refresh())}get value(){return this._value}refresh(){this.events.dispatchEvent({type:"refresh"})}getValue(){const e=this.value;if(e&&null===this._cache&&"URL"===this.inputType&&e.value instanceof ArrayBuffer)this._cache=URL.createObjectURL(new Blob([e.value]));else if(e&&null!==e.value&&void 0!==e.value&&(("URL"===this.inputType||"String"===this.inputType)&&"string"==typeof e.value||"Number"===this.inputType&&"number"==typeof e.value||"Vector2"===this.inputType&&e.value.isVector2||"Vector3"===this.inputType&&e.value.isVector3||"Vector4"===this.inputType&&e.value.isVector4||"Color"===this.inputType&&e.value.isColor||"Matrix3"===this.inputType&&e.value.isMatrix3||"Matrix4"===this.inputType&&e.value.isMatrix4))return e.value;return this._cache||e}getNodeType(e){return this.value&&this.value.isNode?this.value.getNodeType(e):"float"}setup(){return this.value&&this.value.isNode?this.value:Up()}serialize(e){super.serialize(e),null!==this.value?"ArrayBuffer"===this.inputType?e.value=Ad(this.value):e.value=this.value?this.value.toJSON(e.meta).uuid:null:e.value=null,e.inputType=this.inputType,e.outputType=this.outputType}deserialize(e){super.deserialize(e);let t=null;null!==e.value&&(t="ArrayBuffer"===e.inputType?Cd(e.value):"Texture"===e.inputType?e.meta.textures[e.value]:e.meta.nodes[e.value]||null),this.value=t,this.inputType=e.inputType,this.outputType=e.outputType}}const NR=Ap(MR);class AR extends Map{get(e,t=null,...s){if(this.has(e))return super.get(e);if(null!==t){const i=t(...s);return this.set(e,i),i}}}class CR{constructor(e){this.scriptableNode=e}get parameters(){return this.scriptableNode.parameters}get layout(){return this.scriptableNode.getLayout()}getInputLayout(e){return this.scriptableNode.getInputLayout(e)}get(e){const t=this.parameters[e];return t?t.getValue():null}}const RR=new AR;class ER extends Ld{static get type(){return"ScriptableNode"}constructor(e=null,t={}){super(),this.codeNode=e,this.parameters=t,this._local=new AR,this._output=NR(),this._outputs={},this._source=this.source,this._method=null,this._object=null,this._value=null,this._needsOutputUpdate=!0,this.onRefresh=this.onRefresh.bind(this),this.isScriptableNode=!0}get source(){return this.codeNode?this.codeNode.code:""}setLocal(e,t){return this._local.set(e,t)}getLocal(e){return this._local.get(e)}onRefresh(){this._refresh()}getInputLayout(e){for(const t of this.getLayout())if(t.inputType&&(t.id===e||t.name===e))return t}getOutputLayout(e){for(const t of this.getLayout())if(t.outputType&&(t.id===e||t.name===e))return t}setOutput(e,t){const s=this._outputs;return void 0===s[e]?s[e]=NR(t):s[e].value=t,this}getOutput(e){return this._outputs[e]}getParameter(e){return this.parameters[e]}setParameter(e,t){const s=this.parameters;return t&&t.isScriptableNode?(this.deleteParameter(e),s[e]=t,s[e].getDefaultOutput().events.addEventListener("refresh",this.onRefresh)):t&&t.isScriptableValueNode?(this.deleteParameter(e),s[e]=t,s[e].events.addEventListener("refresh",this.onRefresh)):void 0===s[e]?(s[e]=NR(t),s[e].events.addEventListener("refresh",this.onRefresh)):s[e].value=t,this}getValue(){return this.getDefaultOutput().getValue()}deleteParameter(e){let t=this.parameters[e];return t&&(t.isScriptableNode&&(t=t.getDefaultOutput()),t.events.removeEventListener("refresh",this.onRefresh)),this}clearParameters(){for(const e of Object.keys(this.parameters))this.deleteParameter(e);return this.needsUpdate=!0,this}call(e,...t){const s=this.getObject()[e];if("function"==typeof s)return s(...t)}async callAsync(e,...t){const s=this.getObject()[e];if("function"==typeof s)return"AsyncFunction"===s.constructor.name?await s(...t):s(...t)}getNodeType(e){return this.getDefaultOutputNode().getNodeType(e)}refresh(e=null){null!==e?this.getOutput(e).refresh():this._refresh()}getObject(){if(this.needsUpdate&&this.dispose(),null!==this._object)return this._object;const e=new CR(this),t=RR.get("THREE"),s=RR.get("TSL"),i=this.getMethod(this.codeNode),r=[e,this._local,RR,()=>this.refresh(),(e,t)=>this.setOutput(e,t),t,s];this._object=i(...r);const n=this._object.layout;if(n&&(!1===n.cache&&this._local.clear(),this._output.outputType=n.outputType||null,Array.isArray(n.elements)))for(const e of n.elements){const t=e.id||e.name;e.inputType&&(void 0===this.getParameter(t)&&this.setParameter(t,null),this.getParameter(t).inputType=e.inputType),e.outputType&&(void 0===this.getOutput(t)&&this.setOutput(t,null),this.getOutput(t).outputType=e.outputType)}return this._object}deserialize(e){super.deserialize(e);for(const e in this.parameters){let t=this.parameters[e];t.isScriptableNode&&(t=t.getDefaultOutput()),t.events.addEventListener("refresh",this.onRefresh)}}getLayout(){return this.getObject().layout}getDefaultOutputNode(){const e=this.getDefaultOutput().value;return e&&e.isNode?e:Up()}getDefaultOutput(){return this._exec()._output}getMethod(){if(this.needsUpdate&&this.dispose(),null!==this._method)return this._method;const e=["layout","init","main","dispose"].join(", "),t="\nreturn { ...output, "+e+" };",s="var "+e+"; var output = {};\n"+this.codeNode.code+t;return this._method=new Function(...["parameters","local","global","refresh","setOutput","THREE","TSL"],s),this._method}dispose(){null!==this._method&&(this._object&&"function"==typeof this._object.dispose&&this._object.dispose(),this._method=null,this._object=null,this._source=null,this._value=null,this._needsOutputUpdate=!0,this._output.value=null,this._outputs={})}setup(){return this.getDefaultOutputNode()}getCacheKey(e){const t=[vd(this.source),this.getDefaultOutputNode().getCacheKey(e)];for(const s in this.parameters)t.push(this.parameters[s].getCacheKey(e));return Td(t)}set needsUpdate(e){!0===e&&this.dispose()}get needsUpdate(){return this.source!==this._source}_exec(){return null===this.codeNode||(!0===this._needsOutputUpdate&&(this._value=this.call("main"),this._needsOutputUpdate=!1),this._output.value=this._value),this}_refresh(){this.needsUpdate=!0,this._exec(),this._output.refresh()}}const BR=Ap(ER);class IR extends Ld{static get type(){return"FogNode"}constructor(e,t){super("float"),this.isFogNode=!0,this.colorNode=e,this.factorNode=t}getViewZNode(e){let t;const s=e.context.getViewZ;return void 0!==s&&(t=s(this)),(t||cx.z).negate()}setup(){return this.factorNode}}const PR=Ap(IR);class FR extends IR{static get type(){return"FogRangeNode"}constructor(e,t,s){super(e),this.isFogRangeNode=!0,this.nearNode=t,this.farNode=s}setup(e){const t=this.getViewZNode(e);return Mf(this.nearNode,this.farNode,t)}}const zR=Ap(FR);class UR extends IR{static get type(){return"FogExp2Node"}constructor(e,t){super(e),this.isFogExp2Node=!0,this.densityNode=t}setup(e){const t=this.getViewZNode(e),s=this.densityNode;return s.mul(s,t,t).negate().exp().oneMinus()}}const OR=Ap(UR);let LR=null,VR=null;class DR extends Ld{static get type(){return"RangeNode"}constructor(e=Up(),t=Up()){super(),this.minNode=e,this.maxNode=t}getVectorLength(e){const t=e.getTypeLength(Md(this.minNode.value)),s=e.getTypeLength(Md(this.maxNode.value));return t>s?t:s}getNodeType(e){return e.object.count>1?e.getTypeFromLength(this.getVectorLength(e)):"float"}setup(e){const t=e.object;let s=null;if(t.count>1){const i=this.minNode.value,r=this.maxNode.value,n=e.getTypeLength(Md(i)),o=e.getTypeLength(Md(r));LR=LR||new Ti,VR=VR||new Ti,LR.setScalar(0),VR.setScalar(0),1===n?LR.setScalar(i):i.isColor?LR.set(i.r,i.g,i.b):LR.set(i.x,i.y,i.z||0,i.w||0),1===o?VR.setScalar(r):r.isColor?VR.set(r.r,r.g,r.b):VR.set(r.x,r.y,r.z||0,r.w||0);const a=4,h=a*t.count,u=new Float32Array(h);for(let e=0;eBy(e,t.xy).compare(t.z))),WR=Rp((({depthTexture:e,shadowCoord:t,shadow:s})=>{const i=(t,s)=>By(e,t).compare(s),r=kx("mapSize","vec2",s).setGroup(lm),n=kx("radius","float",s).setGroup(lm),o=Dp(1).div(r),a=o.x.negate().mul(n),h=o.y.negate().mul(n),u=o.x.mul(n),l=o.y.mul(n),c=a.div(2),d=h.div(2),p=u.div(2),m=l.div(2);return Zm(i(t.xy.add(Dp(a,h)),t.z),i(t.xy.add(Dp(0,h)),t.z),i(t.xy.add(Dp(u,h)),t.z),i(t.xy.add(Dp(c,d)),t.z),i(t.xy.add(Dp(0,d)),t.z),i(t.xy.add(Dp(p,d)),t.z),i(t.xy.add(Dp(a,0)),t.z),i(t.xy.add(Dp(c,0)),t.z),i(t.xy,t.z),i(t.xy.add(Dp(p,0)),t.z),i(t.xy.add(Dp(u,0)),t.z),i(t.xy.add(Dp(c,m)),t.z),i(t.xy.add(Dp(0,m)),t.z),i(t.xy.add(Dp(p,m)),t.z),i(t.xy.add(Dp(a,l)),t.z),i(t.xy.add(Dp(0,l)),t.z),i(t.xy.add(Dp(u,l)),t.z)).mul(1/17)})),jR=Rp((({depthTexture:e,shadowCoord:t,shadow:s})=>{const i=(t,s)=>By(e,t).compare(s),r=kx("mapSize","vec2",s).setGroup(lm),n=Dp(1).div(r),o=n.x,a=n.y,h=t.xy,u=Og(h.mul(r).add(.5));return h.subAssign(u.mul(n)),Zm(i(h,t.z),i(h.add(Dp(o,0)),t.z),i(h.add(Dp(0,a)),t.z),i(h.add(n),t.z),Tf(i(h.add(Dp(o.negate(),0)),t.z),i(h.add(Dp(o.mul(2),0)),t.z),u.x),Tf(i(h.add(Dp(o.negate(),a)),t.z),i(h.add(Dp(o.mul(2),a)),t.z),u.x),Tf(i(h.add(Dp(0,a.negate())),t.z),i(h.add(Dp(0,a.mul(2))),t.z),u.y),Tf(i(h.add(Dp(o,a.negate())),t.z),i(h.add(Dp(o,a.mul(2))),t.z),u.y),Tf(Tf(i(h.add(Dp(o.negate(),a.negate())),t.z),i(h.add(Dp(o.mul(2),a.negate())),t.z),u.x),Tf(i(h.add(Dp(o.negate(),a.mul(2))),t.z),i(h.add(Dp(o.mul(2),a.mul(2))),t.z),u.x),u.y)).mul(1/9)})),HR=Rp((({depthTexture:e,shadowCoord:t})=>{const s=Up(1).toVar(),i=By(e).uv(t.xy).rg,r=hf(t.z,i.x);return Pp(r.notEqual(Up(1)),(()=>{const e=t.z.sub(i.x),n=of(0,i.y.mul(i.y));let o=n.div(n.add(e.mul(e)));o=_f(Jm(o,.3).div(.95-.3)),s.assign(_f(of(r,o)))})),s})),qR=Rp((({samples:e,radius:t,size:s,shadowPass:i})=>{const r=Up(0).toVar(),n=Up(0).toVar(),o=e.lessThanEqual(Up(1)).select(Up(0),Up(2).div(e.sub(1))),a=e.lessThanEqual(Up(1)).select(Up(0),Up(-1));bv({start:Op(0),end:Op(e),type:"int",condition:"<"},(({i:e})=>{const h=a.add(Up(e).mul(o)),u=i.uv(Zm(Gv.xy,Dp(0,h).mul(t)).div(s)).x;r.addAssign(u),n.addAssign(u.mul(u))})),r.divAssign(e),n.divAssign(e);const h=Ig(n.sub(r.mul(r)));return Dp(r,h)})),$R=Rp((({samples:e,radius:t,size:s,shadowPass:i})=>{const r=Up(0).toVar(),n=Up(0).toVar(),o=e.lessThanEqual(Up(1)).select(Up(0),Up(2).div(e.sub(1))),a=e.lessThanEqual(Up(1)).select(Up(0),Up(-1));bv({start:Op(0),end:Op(e),type:"int",condition:"<"},(({i:e})=>{const h=a.add(Up(e).mul(o)),u=i.uv(Zm(Gv.xy,Dp(h,0).mul(t)).div(s));r.addAssign(u.x),n.addAssign(Zm(u.y.mul(u.y),u.x.mul(u.x)))})),r.divAssign(e),n.divAssign(e);const h=Ig(n.sub(r.mul(r)));return Dp(r,h)})),XR=[GR,WR,jR,HR];let YR=null;const ZR=new dN;class JR extends Iv{static get type(){return"AnalyticLightNode"}constructor(e=null){super(),this.updateType=Bd.FRAME,this.light=e,this.color=new Jr,this.colorNode=pm(this.color).setGroup(lm),this.baseColorNode=null,this.shadowMap=null,this.shadowNode=null,this.shadowColorNode=null,this.vsmShadowMapVertical=null,this.vsmShadowMapHorizontal=null,this.vsmMaterialVertical=null,this.vsmMaterialHorizontal=null,this.isAnalyticLightNode=!0}getCacheKey(){return _d(super.getCacheKey(),this.light.id,this.light.castShadow?1:0)}getHash(){return this.light.uuid}setupShadow(e){const{object:t,renderer:s}=e;if(!1===s.shadowMap.enabled)return;let i=this.shadowColorNode;if(null===i){null===YR&&(YR=new pT,YR.fragmentNode=Xp(0,0,0,1),YR.isShadowNodeMaterial=!0,YR.name="ShadowMaterial");const r=s.shadowMap.type,n=this.light.shadow,o=new Ya;o.compareFunction=Ts;const a=e.createRenderTarget(n.mapSize.width,n.mapSize.height);if(a.depthTexture=o,n.camera.updateProjectionMatrix(),3===r){o.compareFunction=null,this.vsmShadowMapVertical=e.createRenderTarget(n.mapSize.width,n.mapSize.height,{format:$e,type:Pe}),this.vsmShadowMapHorizontal=e.createRenderTarget(n.mapSize.width,n.mapSize.height,{format:$e,type:Pe});const t=By(o),s=By(this.vsmShadowMapVertical.texture),i=kx("blurSamples","float",n).setGroup(lm),r=kx("radius","float",n).setGroup(lm),a=kx("mapSize","vec2",n).setGroup(lm);let h=this.vsmMaterialVertical||(this.vsmMaterialVertical=new pT);h.fragmentNode=qR({samples:i,radius:r,size:a,shadowPass:t}).context(e.getSharedContext()),h.name="VSMVertical",h=this.vsmMaterialHorizontal||(this.vsmMaterialHorizontal=new pT),h.fragmentNode=$R({samples:i,radius:r,size:a,shadowPass:s}).context(e.getSharedContext()),h.name="VSMHorizontal"}const h=kx("intensity","float",n).setGroup(lm),u=kx("bias","float",n).setGroup(lm),l=kx("normalBias","float",n).setGroup(lm),c=t.material.shadowPositionNode||ux;let d=pm(n.matrix).setGroup(lm).mul(c.add(vx.mul(l)));d=d.xyz.div(d.w);let p=d.z.add(u);s.coordinateSystem===Ds&&(p=p.mul(2).sub(1)),d=jp(d.x,d.y.oneMinus(),p);const m=d.x.greaterThanEqual(0).and(d.x.lessThanEqual(1)).and(d.y.greaterThanEqual(0)).and(d.y.lessThanEqual(1)).and(d.z.lessThanEqual(1)),g=n.filterNode||XR[s.shadowMap.type]||null;if(null===g)throw new Error("THREE.WebGPURenderer: Shadow map type not supported yet.");const f=By(a.texture,d),y=m.select(g({depthTexture:3===r?this.vsmShadowMapHorizontal.texture:o,shadowCoord:d,shadow:n}),Up(1));this.shadowMap=a,this.light.shadow.map=a,this.shadowNode=y,this.shadowColorNode=i=this.colorNode.mul(Tf(1,y.rgb.mix(f,1),h.mul(f.a))),this.baseColorNode=this.colorNode}this.colorNode=i,this.updateBeforeType=Bd.RENDER}setup(e){this.colorNode=this.baseColorNode||this.colorNode,this.light.castShadow?e.object.receiveShadow&&this.setupShadow(e):null!==this.shadowNode&&this.disposeShadow()}updateShadow(e){const{shadowMap:t,light:s}=this,{renderer:i,scene:r,camera:n}=e,o=i.shadowMap.type,a=t.depthTexture.version;this._depthVersionCached=a;const h=r.overrideMaterial;r.overrideMaterial=YR,t.setSize(s.shadow.mapSize.width,s.shadow.mapSize.height),s.shadow.updateMatrices(s),s.shadow.camera.layers.mask=n.layers.mask;const u=i.getRenderTarget(),l=i.getRenderObjectFunction();i.setRenderObjectFunction(((e,...t)=>{(!0===e.castShadow||e.receiveShadow&&3===o)&&i.renderObject(e,...t)})),i.setRenderTarget(t),i.render(r,s.shadow.camera),i.setRenderObjectFunction(l),!0!==s.isPointLight&&3===o&&this.vsmPass(e,s),i.setRenderTarget(u),r.overrideMaterial=h}vsmPass(e,t){const{renderer:s}=e;this.vsmShadowMapVertical.setSize(t.shadow.mapSize.width,t.shadow.mapSize.height),this.vsmShadowMapHorizontal.setSize(t.shadow.mapSize.width,t.shadow.mapSize.height),s.setRenderTarget(this.vsmShadowMapVertical),ZR.material=this.vsmMaterialVertical,ZR.render(s),s.setRenderTarget(this.vsmShadowMapHorizontal),ZR.material=this.vsmMaterialHorizontal,ZR.render(s)}disposeShadow(){this.shadowMap.dispose(),this.shadowMap=null,null!==this.vsmShadowMapVertical&&(this.vsmShadowMapVertical.dispose(),this.vsmShadowMapVertical=null,this.vsmMaterialVertical.dispose(),this.vsmMaterialVertical=null),null!==this.vsmShadowMapHorizontal&&(this.vsmShadowMapHorizontal.dispose(),this.vsmShadowMapHorizontal=null,this.vsmMaterialHorizontal.dispose(),this.vsmMaterialHorizontal=null),this.shadowNode=null,this.shadowColorNode=null,this.baseColorNode=null,this.updateBeforeType=Bd.NONE}updateBefore(e){const t=this.light.shadow;(t.needsUpdate||t.autoUpdate)&&(this.updateShadow(e),this.shadowMap.depthTexture.version===this._depthVersionCached&&(t.needsUpdate=!1))}update(){const{light:e}=this;this.color.copy(e.color).multiplyScalar(e.intensity)}}const KR=Rp((e=>{const{lightDistance:t,cutoffDistance:s,decayExponent:i}=e,r=t.pow(i).max(.01).reciprocal();return s.greaterThan(0).select(r.mul(t.div(s).pow4().oneMinus().clamp().pow2()),r)}));let QR;function eE(e){QR=QR||new WeakMap;let t=QR.get(e);return void 0===t&&QR.set(e,t={}),t}function tE(e){const t=eE(e);return t.position||(t.position=pm(new Ri).setGroup(lm).onRenderUpdate(((t,s)=>s.value.setFromMatrixPosition(e.matrixWorld))))}function sE(e){const t=eE(e);return t.targetPosition||(t.targetPosition=pm(new Ri).setGroup(lm).onRenderUpdate(((t,s)=>s.value.setFromMatrixPosition(e.target.matrixWorld))))}function iE(e){const t=eE(e);return t.viewPosition||(t.viewPosition=pm(new Ri).setGroup(lm).onRenderUpdate((({camera:t},s)=>{s.value=s.value||new Ri,s.value.setFromMatrixPosition(e.matrixWorld),s.value.applyMatrix4(t.matrixWorldInverse)})))}const rE=e=>Vy.transformDirection(tE(e).sub(sE(e))),nE=Rp((([e])=>{const t=e.toUint().mul(747796405).add(2891336453),s=t.shiftRight(t.shiftRight(28).add(4)).bitXor(t).mul(277803737);return s.shiftRight(22).bitXor(s).toFloat().mul(1/2**32)})),oE=(e,t)=>mf(Km(4,e.mul(Jm(1,e))),t),aE=(e,t)=>e.lessThan(.5)?oE(e.mul(2),t).div(2):Jm(1,oE(Km(Jm(1,e),2),t).div(2)),hE=(e,t,s)=>mf(Qm(mf(e,t),Zm(mf(e,t),mf(Jm(1,e),s))),1/t),uE=(e,t)=>Lg(Tg.mul(t.mul(e).sub(1))).div(Tg.mul(t.mul(e).sub(1))),lE=Rp((([e])=>e.fract().sub(.5).abs())).setLayout({name:"tri",type:"float",inputs:[{name:"x",type:"float"}]}),cE=Rp((([e])=>jp(lE(e.z.add(lE(e.y.mul(1)))),lE(e.z.add(lE(e.x.mul(1)))),lE(e.y.add(lE(e.x.mul(1))))))).setLayout({name:"tri3",type:"vec3",inputs:[{name:"p",type:"vec3"}]}),dE=Rp((([e,t,s])=>{const i=jp(e).toVar(),r=Up(1.4).toVar(),n=Up(0).toVar(),o=jp(i).toVar();return bv({start:Up(0),end:Up(3),type:"float",condition:"<="},(()=>{const e=jp(cE(o.mul(2))).toVar();i.addAssign(e.add(s.mul(Up(.1).mul(t)))),o.mulAssign(1.8),r.mulAssign(1.5),i.mulAssign(1.2);const a=Up(lE(i.z.add(lE(i.x.add(lE(i.y)))))).toVar();n.addAssign(a.div(r)),o.addAssign(.14)})),n})).setLayout({name:"triNoise3D",type:"float",inputs:[{name:"p",type:"vec3"},{name:"spd",type:"float"},{name:"time",type:"float"}]}),pE=Rp((([e,t,s=Dp(.5)])=>Ew(e.sub(s),t).add(s))),mE=Rp((([e,t,s=Dp(.5)])=>{const i=e.sub(s),r=i.dot(i),n=r.mul(r).mul(t);return e.add(i.mul(n))})),gE=Rp((({position:e=null,horizontal:t=!0,vertical:s=!1})=>{let i;null!==e?(i=Jy.toVar(),i[3][0]=e.x,i[3][1]=e.y,i[3][2]=e.z):i=Jy;const r=Vy.mul(i);return Tp(t)&&(r[0][0]=Jy[0].length(),r[0][1]=0,r[0][2]=0),Tp(s)&&(r[1][0]=0,r[1][1]=Jy[1].length(),r[1][2]=0),r[2][0]=0,r[2][1]=0,r[2][2]=1,Oy.mul(r).mul(ax)})),fE=Rp((([e=null])=>{const t=lT();return lT(sT(e)).sub(t).lessThan(0).select(Dv,e)})),yE=new WeakMap;class xE extends kd{static get type(){return"VelocityNode"}constructor(){super("vec2"),this.updateType=Bd.OBJECT,this.updateAfterType=Bd.OBJECT,this.previousModelWorldMatrix=pm(new nr),this.previousProjectionMatrix=pm(new nr).setGroup(lm),this.previousCameraViewMatrix=pm(new nr)}update({frameId:e,camera:t,object:s}){const i=vE(s);this.previousModelWorldMatrix.value.copy(i);const r=bE(t);r.frameId!==e&&(r.frameId=e,void 0===r.previousProjectionMatrix?(r.previousProjectionMatrix=new nr,r.previousCameraViewMatrix=new nr,r.currentProjectionMatrix=new nr,r.currentCameraViewMatrix=new nr,r.previousProjectionMatrix.copy(t.projectionMatrix),r.previousCameraViewMatrix.copy(t.matrixWorldInverse)):(r.previousProjectionMatrix.copy(r.currentProjectionMatrix),r.previousCameraViewMatrix.copy(r.currentCameraViewMatrix)),r.currentProjectionMatrix.copy(t.projectionMatrix),r.currentCameraViewMatrix.copy(t.matrixWorldInverse),this.previousProjectionMatrix.value.copy(r.previousProjectionMatrix),this.previousCameraViewMatrix.value.copy(r.previousCameraViewMatrix))}updateAfter({object:e}){vE(e).copy(e.matrixWorld)}setup(){const e=this.previousCameraViewMatrix.mul(this.previousModelWorldMatrix),t=Oy.mul(ix).mul(ax),s=this.previousProjectionMatrix.mul(e).mul(hx),i=t.xy.div(t.w),r=s.xy.div(s.w);return Jm(i,r)}}function bE(e){let t=yE.get(e);return void 0===t&&(t={},yE.set(e,t)),t}function vE(e,t=0){const s=bE(e);let i=s[t];return void 0===i&&(s[t]=i=new nr),i}const TE=Cp(xE),_E=Rp((([e,t])=>nf(1,e.oneMinus().div(t)).oneMinus())).setLayout({name:"burnBlend",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),wE=Rp((([e,t])=>nf(e.div(t.oneMinus()),1))).setLayout({name:"dodgeBlend",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),SE=Rp((([e,t])=>e.oneMinus().mul(t.oneMinus()).oneMinus())).setLayout({name:"screenBlend",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),ME=Rp((([e,t])=>Tf(e.mul(2).mul(t),e.oneMinus().mul(2).mul(t.oneMinus()).oneMinus(),hf(.5,e)))).setLayout({name:"overlayBlend",type:"vec3",inputs:[{name:"base",type:"vec3"},{name:"blend",type:"vec3"}]}),NE=Rp((([e,t,s=Op(16)])=>{const i=t=>e.uv(t),r=My(),n=i(r).toVar(),o=Up(s);return bv({start:Op(1),end:s,type:"int",condition:"<="},(({i:e})=>{const s=t.mul(Up(e).div(o.sub(1)).sub(.5));n.addAssign(i(r.add(s)))})),n.divAssign(o),n})),AE=Rp((([e,t=1])=>{const s=e,i=SC(s.rgb),r=jp(i),n=nf(1,of(0,Up(10).mul(i.sub(.45)))),o=r.mul(s.rgb).mul(2),a=Up(2).mul(r.oneMinus()).mul(s.rgb.oneMinus()).oneMinus(),h=Tf(o,a,n),u=s.a.mul(t),l=u.mul(h.rgb);return l.addAssign(s.rgb.mul(u.oneMinus())),Xp(l,s.a)})),CE=Rp((([e])=>{const t=jp(e);return Xp(df(t,jp(.393,.769,.189)),df(t,jp(.349,.686,.168)),df(t,jp(.272,.534,.131)),e.a)})),RE=Rp((([e])=>{const t=e.mul(.9478672986).add(.0521327014).pow(2.4),s=e.mul(.0773993808),i=e.lessThanEqual(.04045);return Tf(t,s,i)})).setLayout({name:"sRGBToLinearSRGB",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),EE=Rp((([e])=>{const t=e.pow(.41666).mul(1.055).sub(.055),s=e.mul(12.92),i=e.lessThanEqual(.0031308);return Tf(t,s,i)})).setLayout({name:"linearSRGBTosRGB",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),BE=Rp((([e,t])=>e.mul(t).clamp())).setLayout({name:"linearToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),IE=Rp((([e,t])=>(e=e.mul(t)).div(e.add(1)).clamp())).setLayout({name:"reinhardToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),PE=Rp((([e,t])=>{const s=(e=(e=e.mul(t)).sub(.004).max(0)).mul(e.mul(6.2).add(.5)),i=e.mul(e.mul(6.2).add(1.7)).add(.06);return s.div(i).pow(2.2)})).setLayout({name:"cineonToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),FE=Rp((([e])=>{const t=e.mul(e.add(.0245786)).sub(90537e-9),s=e.mul(e.add(.432951).mul(.983729)).add(.238081);return t.div(s)})),zE=Rp((([e,t])=>{const s=Qp(.59719,.35458,.04823,.076,.90834,.01566,.0284,.13383,.83777),i=Qp(1.60475,-.53108,-.07367,-.10208,1.10813,-.00605,-.00327,-.07276,1.07602);return e=e.mul(t).div(.6),e=s.mul(e),e=FE(e),(e=i.mul(e)).clamp()})).setLayout({name:"acesFilmicToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),UE=Qp(jp(1.6605,-.1246,-.0182),jp(-.5876,1.1329,-.1006),jp(-.0728,-.0083,1.1187)),OE=Qp(jp(.6274,.0691,.0164),jp(.3293,.9195,.088),jp(.0433,.0113,.8956)),LE=Rp((([e])=>{const t=jp(e).toVar(),s=jp(t.mul(t)).toVar(),i=jp(s.mul(s)).toVar();return Up(15.5).mul(i.mul(s)).sub(Km(40.14,i.mul(t))).add(Km(31.96,i).sub(Km(6.868,s.mul(t))).add(Km(.4298,s).add(Km(.1191,t).sub(.00232))))})),VE=Rp((([e,t])=>{const s=jp(e).toVar(),i=Qp(jp(.856627153315983,.137318972929847,.11189821299995),jp(.0951212405381588,.761241990602591,.0767994186031903),jp(.0482516061458583,.101439036467562,.811302368396859)),r=Qp(jp(1.1271005818144368,-.1413297634984383,-.14132976349843826),jp(-.11060664309660323,1.157823702216272,-.11060664309660294),jp(-.016493938717834573,-.016493938717834257,1.2519364065950405)),n=Up(-12.47393),o=Up(4.026069);return s.mulAssign(t),s.assign(OE.mul(s)),s.assign(i.mul(s)),s.assign(of(s,1e-10)),s.assign(Bg(s)),s.assign(s.sub(n).div(o.sub(n))),s.assign(_f(s,0,1)),s.assign(LE(s)),s.assign(r.mul(s)),s.assign(mf(of(jp(0),s),jp(2.2))),s.assign(UE.mul(s)),s.assign(_f(s,0,1)),s})).setLayout({name:"agxToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]}),DE=Rp((([e,t])=>{const s=Up(.76),i=Up(.15);e=e.mul(t);const r=nf(e.r,nf(e.g,e.b)),n=Bf(r.lessThan(.08),r.sub(Km(6.25,r.mul(r))),.04);e.subAssign(n);const o=of(e.r,of(e.g,e.b));Pp(o.lessThan(s),(()=>e));const a=Jm(1,s),h=Jm(1,a.mul(a).div(o.add(a.sub(s))));e.mulAssign(h.div(o));const u=Jm(1,Qm(1,i.mul(o.sub(h)).add(1)));return Tf(e,jp(h),u)})).setLayout({name:"neutralToneMapping",type:"vec3",inputs:[{name:"color",type:"vec3"},{name:"exposure",type:"float"}]});class kE extends Ld{static get type(){return"ComputeBuiltinNode"}constructor(e,t){super(t),this._builtinName=e}getHash(e){return this.getBuiltinName(e)}getNodeType(){return this.nodeType}setBuiltinName(e){return this._builtinName=e,this}getBuiltinName(){return this._builtinName}hasBuiltin(e){e.hasBuiltin(this._builtinName)}generate(e,t){const s=this.getBuiltinName(e),i=this.getNodeType(e);return"compute"===e.shaderStage?e.format(s,i,t):(console.warn(`ComputeBuiltinNode: Compute built-in value ${s} can not be accessed in the ${e.shaderStage} stage`),e.generateConst(i))}serialize(e){super.serialize(e),e.global=this.global,e._builtinName=this._builtinName}deserialize(e){super.deserialize(e),this.global=e.global,this._builtinName=e._builtinName}}const GE=(e,t)=>Sp(new kE(e,t)),WE=GE("numWorkgroups","uvec3"),jE=GE("workgroupId","uvec3"),HE=GE("localId","uvec3"),qE=GE("subgroupSize","uint");const $E=Ap(class extends Ld{constructor(e){super(),this.scope=e}generate(e){const{scope:t}=this,{renderer:s}=e;!0===s.backend.isWebGLBackend?e.addFlowCode(`\t// ${t}Barrier \n`):e.addLineFlowCode(`${t}Barrier()`,this)}}),XE=()=>$E("workgroup").append(),YE=()=>$E("storage").append(),ZE=()=>$E("texture").append();class JE extends Vd{constructor(e,t){super(e,t),this.isWorkgroupInfoElementNode=!0}generate(e,t){let s;const i=e.context.assign;if(s=super.generate(e),!0!==i){const i=this.getNodeType(e);s=e.format(s,i,t)}return s}}class KE extends Ld{constructor(e,t,s=0){super(t),this.bufferType=t,this.bufferCount=s,this.isWorkgroupInfoNode=!0,this.scope=e}label(e){return this.name=e,this}getHash(){return this.uuid}setScope(e){return this.scope=e,this}getInputType(){return`${this.scope}Array`}element(e){return Sp(new JE(this,e))}generate(e){return e.getScopedArray(this.name||`${this.scope}Array_${this.id}`,this.scope.toLowerCase(),this.bufferType,this.bufferCount)}}const QE=(e,t)=>Sp(new KE("Workgroup",e,t));class eB extends kd{static get type(){return"AtomicFunctionNode"}constructor(e,t,s,i=null){super("uint"),this.method=e,this.pointerNode=t,this.valueNode=s,this.storeNode=i}getInputType(e){return this.pointerNode.getNodeType(e)}getNodeType(e){return this.getInputType(e)}generate(e){const t=this.method,s=this.getNodeType(e),i=this.getInputType(e),r=this.pointerNode,n=this.valueNode,o=[];o.push(`&${r.build(e,i)}`),o.push(n.build(e,i));const a=`${e.getMethod(t,s)}( ${o.join(", ")} )`;if(null!==this.storeNode){const t=this.storeNode.build(e,i);e.addLineFlowCode(`${t} = ${a}`,this)}else e.addLineFlowCode(a,this)}}eB.ATOMIC_LOAD="atomicLoad",eB.ATOMIC_STORE="atomicStore",eB.ATOMIC_ADD="atomicAdd",eB.ATOMIC_SUB="atomicSub",eB.ATOMIC_MAX="atomicMax",eB.ATOMIC_MIN="atomicMin",eB.ATOMIC_AND="atomicAnd",eB.ATOMIC_OR="atomicOr",eB.ATOMIC_XOR="atomicXor";const tB=Ap(eB),sB=(e,t,s,i)=>{const r=tB(e,t,s,i);return r.append(),r},iB=(e,t,s=null)=>sB(eB.ATOMIC_STORE,e,t,s),rB=(e,t,s=null)=>sB(eB.ATOMIC_ADD,e,t,s),nB=(e,t,s=null)=>sB(eB.ATOMIC_SUB,e,t,s),oB=(e,t,s=null)=>sB(eB.ATOMIC_MAX,e,t,s),aB=(e,t,s=null)=>sB(eB.ATOMIC_MIN,e,t,s),hB=(e,t,s=null)=>sB(eB.ATOMIC_AND,e,t,s),uB=(e,t,s=null)=>sB(eB.ATOMIC_OR,e,t,s),lB=(e,t,s=null)=>sB(eB.ATOMIC_XOR,e,t,s),cB=Rp((([e=t()])=>{const t=e.mul(2),s=t.x.floor(),i=t.y.floor();return s.add(i).mod(2).sign()})),dB=Rp((([e,t,s])=>{const i=Up(s).toVar(),r=Up(t).toVar(),n=Vp(e).toVar();return Bf(n,r,i)})).setLayout({name:"mx_select",type:"float",inputs:[{name:"b",type:"bool"},{name:"t",type:"float"},{name:"f",type:"float"}]}),pB=Rp((([e,t])=>{const s=Vp(t).toVar(),i=Up(e).toVar();return Bf(s,i.negate(),i)})).setLayout({name:"mx_negate_if",type:"float",inputs:[{name:"val",type:"float"},{name:"b",type:"bool"}]}),mB=Rp((([e])=>{const t=Up(e).toVar();return Op(Fg(t))})).setLayout({name:"mx_floor",type:"int",inputs:[{name:"x",type:"float"}]}),gB=Rp((([e,t])=>{const s=Up(e).toVar();return t.assign(mB(s)),s.sub(Up(t))})),fB=RM([Rp((([e,t,s,i,r,n])=>{const o=Up(n).toVar(),a=Up(r).toVar(),h=Up(i).toVar(),u=Up(s).toVar(),l=Up(t).toVar(),c=Up(e).toVar(),d=Up(Jm(1,a)).toVar();return Jm(1,o).mul(c.mul(d).add(l.mul(a))).add(o.mul(u.mul(d).add(h.mul(a))))})).setLayout({name:"mx_bilerp_0",type:"float",inputs:[{name:"v0",type:"float"},{name:"v1",type:"float"},{name:"v2",type:"float"},{name:"v3",type:"float"},{name:"s",type:"float"},{name:"t",type:"float"}]}),Rp((([e,t,s,i,r,n])=>{const o=Up(n).toVar(),a=Up(r).toVar(),h=jp(i).toVar(),u=jp(s).toVar(),l=jp(t).toVar(),c=jp(e).toVar(),d=Up(Jm(1,a)).toVar();return Jm(1,o).mul(c.mul(d).add(l.mul(a))).add(o.mul(u.mul(d).add(h.mul(a))))})).setLayout({name:"mx_bilerp_1",type:"vec3",inputs:[{name:"v0",type:"vec3"},{name:"v1",type:"vec3"},{name:"v2",type:"vec3"},{name:"v3",type:"vec3"},{name:"s",type:"float"},{name:"t",type:"float"}]})]),yB=RM([Rp((([e,t,s,i,r,n,o,a,h,u,l])=>{const c=Up(l).toVar(),d=Up(u).toVar(),p=Up(h).toVar(),m=Up(a).toVar(),g=Up(o).toVar(),f=Up(n).toVar(),y=Up(r).toVar(),x=Up(i).toVar(),b=Up(s).toVar(),v=Up(t).toVar(),T=Up(e).toVar(),_=Up(Jm(1,p)).toVar(),w=Up(Jm(1,d)).toVar();return Up(Jm(1,c)).toVar().mul(w.mul(T.mul(_).add(v.mul(p))).add(d.mul(b.mul(_).add(x.mul(p))))).add(c.mul(w.mul(y.mul(_).add(f.mul(p))).add(d.mul(g.mul(_).add(m.mul(p))))))})).setLayout({name:"mx_trilerp_0",type:"float",inputs:[{name:"v0",type:"float"},{name:"v1",type:"float"},{name:"v2",type:"float"},{name:"v3",type:"float"},{name:"v4",type:"float"},{name:"v5",type:"float"},{name:"v6",type:"float"},{name:"v7",type:"float"},{name:"s",type:"float"},{name:"t",type:"float"},{name:"r",type:"float"}]}),Rp((([e,t,s,i,r,n,o,a,h,u,l])=>{const c=Up(l).toVar(),d=Up(u).toVar(),p=Up(h).toVar(),m=jp(a).toVar(),g=jp(o).toVar(),f=jp(n).toVar(),y=jp(r).toVar(),x=jp(i).toVar(),b=jp(s).toVar(),v=jp(t).toVar(),T=jp(e).toVar(),_=Up(Jm(1,p)).toVar(),w=Up(Jm(1,d)).toVar();return Up(Jm(1,c)).toVar().mul(w.mul(T.mul(_).add(v.mul(p))).add(d.mul(b.mul(_).add(x.mul(p))))).add(c.mul(w.mul(y.mul(_).add(f.mul(p))).add(d.mul(g.mul(_).add(m.mul(p))))))})).setLayout({name:"mx_trilerp_1",type:"vec3",inputs:[{name:"v0",type:"vec3"},{name:"v1",type:"vec3"},{name:"v2",type:"vec3"},{name:"v3",type:"vec3"},{name:"v4",type:"vec3"},{name:"v5",type:"vec3"},{name:"v6",type:"vec3"},{name:"v7",type:"vec3"},{name:"s",type:"float"},{name:"t",type:"float"},{name:"r",type:"float"}]})]),xB=Rp((([e,t,s])=>{const i=Up(s).toVar(),r=Up(t).toVar(),n=Lp(e).toVar(),o=Lp(n.bitAnd(Lp(7))).toVar(),a=Up(dB(o.lessThan(Lp(4)),r,i)).toVar(),h=Up(Km(2,dB(o.lessThan(Lp(4)),i,r))).toVar();return pB(a,Vp(o.bitAnd(Lp(1)))).add(pB(h,Vp(o.bitAnd(Lp(2)))))})).setLayout({name:"mx_gradient_float_0",type:"float",inputs:[{name:"hash",type:"uint"},{name:"x",type:"float"},{name:"y",type:"float"}]}),bB=Rp((([e,t,s,i])=>{const r=Up(i).toVar(),n=Up(s).toVar(),o=Up(t).toVar(),a=Lp(e).toVar(),h=Lp(a.bitAnd(Lp(15))).toVar(),u=Up(dB(h.lessThan(Lp(8)),o,n)).toVar(),l=Up(dB(h.lessThan(Lp(4)),n,dB(h.equal(Lp(12)).or(h.equal(Lp(14))),o,r))).toVar();return pB(u,Vp(h.bitAnd(Lp(1)))).add(pB(l,Vp(h.bitAnd(Lp(2)))))})).setLayout({name:"mx_gradient_float_1",type:"float",inputs:[{name:"hash",type:"uint"},{name:"x",type:"float"},{name:"y",type:"float"},{name:"z",type:"float"}]}),vB=RM([xB,bB]),TB=Rp((([e,t,s])=>{const i=Up(s).toVar(),r=Up(t).toVar(),n=qp(e).toVar();return jp(vB(n.x,r,i),vB(n.y,r,i),vB(n.z,r,i))})).setLayout({name:"mx_gradient_vec3_0",type:"vec3",inputs:[{name:"hash",type:"uvec3"},{name:"x",type:"float"},{name:"y",type:"float"}]}),_B=Rp((([e,t,s,i])=>{const r=Up(i).toVar(),n=Up(s).toVar(),o=Up(t).toVar(),a=qp(e).toVar();return jp(vB(a.x,o,n,r),vB(a.y,o,n,r),vB(a.z,o,n,r))})).setLayout({name:"mx_gradient_vec3_1",type:"vec3",inputs:[{name:"hash",type:"uvec3"},{name:"x",type:"float"},{name:"y",type:"float"},{name:"z",type:"float"}]}),wB=RM([TB,_B]),SB=Rp((([e])=>{const t=Up(e).toVar();return Km(.6616,t)})).setLayout({name:"mx_gradient_scale2d_0",type:"float",inputs:[{name:"v",type:"float"}]}),MB=Rp((([e])=>{const t=Up(e).toVar();return Km(.982,t)})).setLayout({name:"mx_gradient_scale3d_0",type:"float",inputs:[{name:"v",type:"float"}]}),NB=RM([SB,Rp((([e])=>{const t=jp(e).toVar();return Km(.6616,t)})).setLayout({name:"mx_gradient_scale2d_1",type:"vec3",inputs:[{name:"v",type:"vec3"}]})]),AB=RM([MB,Rp((([e])=>{const t=jp(e).toVar();return Km(.982,t)})).setLayout({name:"mx_gradient_scale3d_1",type:"vec3",inputs:[{name:"v",type:"vec3"}]})]),CB=Rp((([e,t])=>{const s=Op(t).toVar(),i=Lp(e).toVar();return i.shiftLeft(s).bitOr(i.shiftRight(Op(32).sub(s)))})).setLayout({name:"mx_rotl32",type:"uint",inputs:[{name:"x",type:"uint"},{name:"k",type:"int"}]}),RB=Rp((([e,t,s])=>{e.subAssign(s),e.bitXorAssign(CB(s,Op(4))),s.addAssign(t),t.subAssign(e),t.bitXorAssign(CB(e,Op(6))),e.addAssign(s),s.subAssign(t),s.bitXorAssign(CB(t,Op(8))),t.addAssign(e),e.subAssign(s),e.bitXorAssign(CB(s,Op(16))),s.addAssign(t),t.subAssign(e),t.bitXorAssign(CB(e,Op(19))),e.addAssign(s),s.subAssign(t),s.bitXorAssign(CB(t,Op(4))),t.addAssign(e)})),EB=Rp((([e,t,s])=>{const i=Lp(s).toVar(),r=Lp(t).toVar(),n=Lp(e).toVar();return i.bitXorAssign(r),i.subAssign(CB(r,Op(14))),n.bitXorAssign(i),n.subAssign(CB(i,Op(11))),r.bitXorAssign(n),r.subAssign(CB(n,Op(25))),i.bitXorAssign(r),i.subAssign(CB(r,Op(16))),n.bitXorAssign(i),n.subAssign(CB(i,Op(4))),r.bitXorAssign(n),r.subAssign(CB(n,Op(14))),i.bitXorAssign(r),i.subAssign(CB(r,Op(24))),i})).setLayout({name:"mx_bjfinal",type:"uint",inputs:[{name:"a",type:"uint"},{name:"b",type:"uint"},{name:"c",type:"uint"}]}),BB=Rp((([e])=>{const t=Lp(e).toVar();return Up(t).div(Up(Lp(Op(4294967295))))})).setLayout({name:"mx_bits_to_01",type:"float",inputs:[{name:"bits",type:"uint"}]}),IB=Rp((([e])=>{const t=Up(e).toVar();return t.mul(t).mul(t).mul(t.mul(t.mul(6).sub(15)).add(10))})).setLayout({name:"mx_fade",type:"float",inputs:[{name:"t",type:"float"}]}),PB=RM([Rp((([e])=>{const t=Op(e).toVar(),s=Lp(Lp(1)).toVar(),i=Lp(Lp(Op(3735928559)).add(s.shiftLeft(Lp(2))).add(Lp(13))).toVar();return EB(i.add(Lp(t)),i,i)})).setLayout({name:"mx_hash_int_0",type:"uint",inputs:[{name:"x",type:"int"}]}),Rp((([e,t])=>{const s=Op(t).toVar(),i=Op(e).toVar(),r=Lp(Lp(2)).toVar(),n=Lp().toVar(),o=Lp().toVar(),a=Lp().toVar();return n.assign(o.assign(a.assign(Lp(Op(3735928559)).add(r.shiftLeft(Lp(2))).add(Lp(13))))),n.addAssign(Lp(i)),o.addAssign(Lp(s)),EB(n,o,a)})).setLayout({name:"mx_hash_int_1",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"}]}),Rp((([e,t,s])=>{const i=Op(s).toVar(),r=Op(t).toVar(),n=Op(e).toVar(),o=Lp(Lp(3)).toVar(),a=Lp().toVar(),h=Lp().toVar(),u=Lp().toVar();return a.assign(h.assign(u.assign(Lp(Op(3735928559)).add(o.shiftLeft(Lp(2))).add(Lp(13))))),a.addAssign(Lp(n)),h.addAssign(Lp(r)),u.addAssign(Lp(i)),EB(a,h,u)})).setLayout({name:"mx_hash_int_2",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"}]}),Rp((([e,t,s,i])=>{const r=Op(i).toVar(),n=Op(s).toVar(),o=Op(t).toVar(),a=Op(e).toVar(),h=Lp(Lp(4)).toVar(),u=Lp().toVar(),l=Lp().toVar(),c=Lp().toVar();return u.assign(l.assign(c.assign(Lp(Op(3735928559)).add(h.shiftLeft(Lp(2))).add(Lp(13))))),u.addAssign(Lp(a)),l.addAssign(Lp(o)),c.addAssign(Lp(n)),RB(u,l,c),u.addAssign(Lp(r)),EB(u,l,c)})).setLayout({name:"mx_hash_int_3",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xx",type:"int"}]}),Rp((([e,t,s,i,r])=>{const n=Op(r).toVar(),o=Op(i).toVar(),a=Op(s).toVar(),h=Op(t).toVar(),u=Op(e).toVar(),l=Lp(Lp(5)).toVar(),c=Lp().toVar(),d=Lp().toVar(),p=Lp().toVar();return c.assign(d.assign(p.assign(Lp(Op(3735928559)).add(l.shiftLeft(Lp(2))).add(Lp(13))))),c.addAssign(Lp(u)),d.addAssign(Lp(h)),p.addAssign(Lp(a)),RB(c,d,p),c.addAssign(Lp(o)),d.addAssign(Lp(n)),EB(c,d,p)})).setLayout({name:"mx_hash_int_4",type:"uint",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xx",type:"int"},{name:"yy",type:"int"}]})]),FB=RM([Rp((([e,t])=>{const s=Op(t).toVar(),i=Op(e).toVar(),r=Lp(PB(i,s)).toVar(),n=qp().toVar();return n.x.assign(r.bitAnd(Op(255))),n.y.assign(r.shiftRight(Op(8)).bitAnd(Op(255))),n.z.assign(r.shiftRight(Op(16)).bitAnd(Op(255))),n})).setLayout({name:"mx_hash_vec3_0",type:"uvec3",inputs:[{name:"x",type:"int"},{name:"y",type:"int"}]}),Rp((([e,t,s])=>{const i=Op(s).toVar(),r=Op(t).toVar(),n=Op(e).toVar(),o=Lp(PB(n,r,i)).toVar(),a=qp().toVar();return a.x.assign(o.bitAnd(Op(255))),a.y.assign(o.shiftRight(Op(8)).bitAnd(Op(255))),a.z.assign(o.shiftRight(Op(16)).bitAnd(Op(255))),a})).setLayout({name:"mx_hash_vec3_1",type:"uvec3",inputs:[{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"}]})]),zB=RM([Rp((([e])=>{const t=Dp(e).toVar(),s=Op().toVar(),i=Op().toVar(),r=Up(gB(t.x,s)).toVar(),n=Up(gB(t.y,i)).toVar(),o=Up(IB(r)).toVar(),a=Up(IB(n)).toVar(),h=Up(fB(vB(PB(s,i),r,n),vB(PB(s.add(Op(1)),i),r.sub(1),n),vB(PB(s,i.add(Op(1))),r,n.sub(1)),vB(PB(s.add(Op(1)),i.add(Op(1))),r.sub(1),n.sub(1)),o,a)).toVar();return NB(h)})).setLayout({name:"mx_perlin_noise_float_0",type:"float",inputs:[{name:"p",type:"vec2"}]}),Rp((([e])=>{const t=jp(e).toVar(),s=Op().toVar(),i=Op().toVar(),r=Op().toVar(),n=Up(gB(t.x,s)).toVar(),o=Up(gB(t.y,i)).toVar(),a=Up(gB(t.z,r)).toVar(),h=Up(IB(n)).toVar(),u=Up(IB(o)).toVar(),l=Up(IB(a)).toVar(),c=Up(yB(vB(PB(s,i,r),n,o,a),vB(PB(s.add(Op(1)),i,r),n.sub(1),o,a),vB(PB(s,i.add(Op(1)),r),n,o.sub(1),a),vB(PB(s.add(Op(1)),i.add(Op(1)),r),n.sub(1),o.sub(1),a),vB(PB(s,i,r.add(Op(1))),n,o,a.sub(1)),vB(PB(s.add(Op(1)),i,r.add(Op(1))),n.sub(1),o,a.sub(1)),vB(PB(s,i.add(Op(1)),r.add(Op(1))),n,o.sub(1),a.sub(1)),vB(PB(s.add(Op(1)),i.add(Op(1)),r.add(Op(1))),n.sub(1),o.sub(1),a.sub(1)),h,u,l)).toVar();return AB(c)})).setLayout({name:"mx_perlin_noise_float_1",type:"float",inputs:[{name:"p",type:"vec3"}]})]),UB=RM([Rp((([e])=>{const t=Dp(e).toVar(),s=Op().toVar(),i=Op().toVar(),r=Up(gB(t.x,s)).toVar(),n=Up(gB(t.y,i)).toVar(),o=Up(IB(r)).toVar(),a=Up(IB(n)).toVar(),h=jp(fB(wB(FB(s,i),r,n),wB(FB(s.add(Op(1)),i),r.sub(1),n),wB(FB(s,i.add(Op(1))),r,n.sub(1)),wB(FB(s.add(Op(1)),i.add(Op(1))),r.sub(1),n.sub(1)),o,a)).toVar();return NB(h)})).setLayout({name:"mx_perlin_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"vec2"}]}),Rp((([e])=>{const t=jp(e).toVar(),s=Op().toVar(),i=Op().toVar(),r=Op().toVar(),n=Up(gB(t.x,s)).toVar(),o=Up(gB(t.y,i)).toVar(),a=Up(gB(t.z,r)).toVar(),h=Up(IB(n)).toVar(),u=Up(IB(o)).toVar(),l=Up(IB(a)).toVar(),c=jp(yB(wB(FB(s,i,r),n,o,a),wB(FB(s.add(Op(1)),i,r),n.sub(1),o,a),wB(FB(s,i.add(Op(1)),r),n,o.sub(1),a),wB(FB(s.add(Op(1)),i.add(Op(1)),r),n.sub(1),o.sub(1),a),wB(FB(s,i,r.add(Op(1))),n,o,a.sub(1)),wB(FB(s.add(Op(1)),i,r.add(Op(1))),n.sub(1),o,a.sub(1)),wB(FB(s,i.add(Op(1)),r.add(Op(1))),n,o.sub(1),a.sub(1)),wB(FB(s.add(Op(1)),i.add(Op(1)),r.add(Op(1))),n.sub(1),o.sub(1),a.sub(1)),h,u,l)).toVar();return AB(c)})).setLayout({name:"mx_perlin_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec3"}]})]),OB=RM([Rp((([e])=>{const t=Up(e).toVar(),s=Op(mB(t)).toVar();return BB(PB(s))})).setLayout({name:"mx_cell_noise_float_0",type:"float",inputs:[{name:"p",type:"float"}]}),Rp((([e])=>{const t=Dp(e).toVar(),s=Op(mB(t.x)).toVar(),i=Op(mB(t.y)).toVar();return BB(PB(s,i))})).setLayout({name:"mx_cell_noise_float_1",type:"float",inputs:[{name:"p",type:"vec2"}]}),Rp((([e])=>{const t=jp(e).toVar(),s=Op(mB(t.x)).toVar(),i=Op(mB(t.y)).toVar(),r=Op(mB(t.z)).toVar();return BB(PB(s,i,r))})).setLayout({name:"mx_cell_noise_float_2",type:"float",inputs:[{name:"p",type:"vec3"}]}),Rp((([e])=>{const t=Xp(e).toVar(),s=Op(mB(t.x)).toVar(),i=Op(mB(t.y)).toVar(),r=Op(mB(t.z)).toVar(),n=Op(mB(t.w)).toVar();return BB(PB(s,i,r,n))})).setLayout({name:"mx_cell_noise_float_3",type:"float",inputs:[{name:"p",type:"vec4"}]})]),LB=RM([Rp((([e])=>{const t=Up(e).toVar(),s=Op(mB(t)).toVar();return jp(BB(PB(s,Op(0))),BB(PB(s,Op(1))),BB(PB(s,Op(2))))})).setLayout({name:"mx_cell_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"float"}]}),Rp((([e])=>{const t=Dp(e).toVar(),s=Op(mB(t.x)).toVar(),i=Op(mB(t.y)).toVar();return jp(BB(PB(s,i,Op(0))),BB(PB(s,i,Op(1))),BB(PB(s,i,Op(2))))})).setLayout({name:"mx_cell_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec2"}]}),Rp((([e])=>{const t=jp(e).toVar(),s=Op(mB(t.x)).toVar(),i=Op(mB(t.y)).toVar(),r=Op(mB(t.z)).toVar();return jp(BB(PB(s,i,r,Op(0))),BB(PB(s,i,r,Op(1))),BB(PB(s,i,r,Op(2))))})).setLayout({name:"mx_cell_noise_vec3_2",type:"vec3",inputs:[{name:"p",type:"vec3"}]}),Rp((([e])=>{const t=Xp(e).toVar(),s=Op(mB(t.x)).toVar(),i=Op(mB(t.y)).toVar(),r=Op(mB(t.z)).toVar(),n=Op(mB(t.w)).toVar();return jp(BB(PB(s,i,r,n,Op(0))),BB(PB(s,i,r,n,Op(1))),BB(PB(s,i,r,n,Op(2))))})).setLayout({name:"mx_cell_noise_vec3_3",type:"vec3",inputs:[{name:"p",type:"vec4"}]})]),VB=Rp((([e,t,s,i])=>{const r=Up(i).toVar(),n=Up(s).toVar(),o=Op(t).toVar(),a=jp(e).toVar(),h=Up(0).toVar(),u=Up(1).toVar();return bv(o,(()=>{h.addAssign(u.mul(zB(a))),u.mulAssign(r),a.mulAssign(n)})),h})).setLayout({name:"mx_fractal_noise_float",type:"float",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),DB=Rp((([e,t,s,i])=>{const r=Up(i).toVar(),n=Up(s).toVar(),o=Op(t).toVar(),a=jp(e).toVar(),h=jp(0).toVar(),u=Up(1).toVar();return bv(o,(()=>{h.addAssign(u.mul(UB(a))),u.mulAssign(r),a.mulAssign(n)})),h})).setLayout({name:"mx_fractal_noise_vec3",type:"vec3",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),kB=Rp((([e,t,s,i])=>{const r=Up(i).toVar(),n=Up(s).toVar(),o=Op(t).toVar(),a=jp(e).toVar();return Dp(VB(a,o,n,r),VB(a.add(jp(Op(19),Op(193),Op(17))),o,n,r))})).setLayout({name:"mx_fractal_noise_vec2",type:"vec2",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),GB=Rp((([e,t,s,i])=>{const r=Up(i).toVar(),n=Up(s).toVar(),o=Op(t).toVar(),a=jp(e).toVar(),h=jp(DB(a,o,n,r)).toVar(),u=Up(VB(a.add(jp(Op(19),Op(193),Op(17))),o,n,r)).toVar();return Xp(h,u)})).setLayout({name:"mx_fractal_noise_vec4",type:"vec4",inputs:[{name:"p",type:"vec3"},{name:"octaves",type:"int"},{name:"lacunarity",type:"float"},{name:"diminish",type:"float"}]}),WB=Rp((([e,t,s,i,r,n,o])=>{const a=Op(o).toVar(),h=Up(n).toVar(),u=Op(r).toVar(),l=Op(i).toVar(),c=Op(s).toVar(),d=Op(t).toVar(),p=Dp(e).toVar(),m=jp(LB(Dp(d.add(l),c.add(u)))).toVar(),g=Dp(m.x,m.y).toVar();g.subAssign(.5),g.mulAssign(h),g.addAssign(.5);const f=Dp(Dp(Up(d),Up(c)).add(g)).toVar(),y=Dp(f.sub(p)).toVar();return Pp(a.equal(Op(2)),(()=>jg(y.x).add(jg(y.y)))),Pp(a.equal(Op(3)),(()=>of(jg(y.x),jg(y.y)))),df(y,y)})).setLayout({name:"mx_worley_distance_0",type:"float",inputs:[{name:"p",type:"vec2"},{name:"x",type:"int"},{name:"y",type:"int"},{name:"xoff",type:"int"},{name:"yoff",type:"int"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),jB=RM([WB,Rp((([e,t,s,i,r,n,o,a,h])=>{const u=Op(h).toVar(),l=Up(a).toVar(),c=Op(o).toVar(),d=Op(n).toVar(),p=Op(r).toVar(),m=Op(i).toVar(),g=Op(s).toVar(),f=Op(t).toVar(),y=jp(e).toVar(),x=jp(LB(jp(f.add(p),g.add(d),m.add(c)))).toVar();x.subAssign(.5),x.mulAssign(l),x.addAssign(.5);const b=jp(jp(Up(f),Up(g),Up(m)).add(x)).toVar(),v=jp(b.sub(y)).toVar();return Pp(u.equal(Op(2)),(()=>jg(v.x).add(jg(v.y)).add(jg(v.z)))),Pp(u.equal(Op(3)),(()=>of(of(jg(v.x),jg(v.y)),jg(v.z)))),df(v,v)})).setLayout({name:"mx_worley_distance_1",type:"float",inputs:[{name:"p",type:"vec3"},{name:"x",type:"int"},{name:"y",type:"int"},{name:"z",type:"int"},{name:"xoff",type:"int"},{name:"yoff",type:"int"},{name:"zoff",type:"int"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),HB=Rp((([e,t,s])=>{const i=Op(s).toVar(),r=Up(t).toVar(),n=Dp(e).toVar(),o=Op().toVar(),a=Op().toVar(),h=Dp(gB(n.x,o),gB(n.y,a)).toVar(),u=Up(1e6).toVar();return bv({start:-1,end:Op(1),name:"x",condition:"<="},(({x:e})=>{bv({start:-1,end:Op(1),name:"y",condition:"<="},(({y:t})=>{const s=Up(jB(h,e,t,o,a,r,i)).toVar();u.assign(nf(u,s))}))})),Pp(i.equal(Op(0)),(()=>{u.assign(Ig(u))})),u})).setLayout({name:"mx_worley_noise_float_0",type:"float",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),qB=Rp((([e,t,s])=>{const i=Op(s).toVar(),r=Up(t).toVar(),n=Dp(e).toVar(),o=Op().toVar(),a=Op().toVar(),h=Dp(gB(n.x,o),gB(n.y,a)).toVar(),u=Dp(1e6,1e6).toVar();return bv({start:-1,end:Op(1),name:"x",condition:"<="},(({x:e})=>{bv({start:-1,end:Op(1),name:"y",condition:"<="},(({y:t})=>{const s=Up(jB(h,e,t,o,a,r,i)).toVar();Pp(s.lessThan(u.x),(()=>{u.y.assign(u.x),u.x.assign(s)})).ElseIf(s.lessThan(u.y),(()=>{u.y.assign(s)}))}))})),Pp(i.equal(Op(0)),(()=>{u.assign(Ig(u))})),u})).setLayout({name:"mx_worley_noise_vec2_0",type:"vec2",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),$B=Rp((([e,t,s])=>{const i=Op(s).toVar(),r=Up(t).toVar(),n=Dp(e).toVar(),o=Op().toVar(),a=Op().toVar(),h=Dp(gB(n.x,o),gB(n.y,a)).toVar(),u=jp(1e6,1e6,1e6).toVar();return bv({start:-1,end:Op(1),name:"x",condition:"<="},(({x:e})=>{bv({start:-1,end:Op(1),name:"y",condition:"<="},(({y:t})=>{const s=Up(jB(h,e,t,o,a,r,i)).toVar();Pp(s.lessThan(u.x),(()=>{u.z.assign(u.y),u.y.assign(u.x),u.x.assign(s)})).ElseIf(s.lessThan(u.y),(()=>{u.z.assign(u.y),u.y.assign(s)})).ElseIf(s.lessThan(u.z),(()=>{u.z.assign(s)}))}))})),Pp(i.equal(Op(0)),(()=>{u.assign(Ig(u))})),u})).setLayout({name:"mx_worley_noise_vec3_0",type:"vec3",inputs:[{name:"p",type:"vec2"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]}),XB=RM([HB,Rp((([e,t,s])=>{const i=Op(s).toVar(),r=Up(t).toVar(),n=jp(e).toVar(),o=Op().toVar(),a=Op().toVar(),h=Op().toVar(),u=jp(gB(n.x,o),gB(n.y,a),gB(n.z,h)).toVar(),l=Up(1e6).toVar();return bv({start:-1,end:Op(1),name:"x",condition:"<="},(({x:e})=>{bv({start:-1,end:Op(1),name:"y",condition:"<="},(({y:t})=>{bv({start:-1,end:Op(1),name:"z",condition:"<="},(({z:s})=>{const n=Up(jB(u,e,t,s,o,a,h,r,i)).toVar();l.assign(nf(l,n))}))}))})),Pp(i.equal(Op(0)),(()=>{l.assign(Ig(l))})),l})).setLayout({name:"mx_worley_noise_float_1",type:"float",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),YB=RM([qB,Rp((([e,t,s])=>{const i=Op(s).toVar(),r=Up(t).toVar(),n=jp(e).toVar(),o=Op().toVar(),a=Op().toVar(),h=Op().toVar(),u=jp(gB(n.x,o),gB(n.y,a),gB(n.z,h)).toVar(),l=Dp(1e6,1e6).toVar();return bv({start:-1,end:Op(1),name:"x",condition:"<="},(({x:e})=>{bv({start:-1,end:Op(1),name:"y",condition:"<="},(({y:t})=>{bv({start:-1,end:Op(1),name:"z",condition:"<="},(({z:s})=>{const n=Up(jB(u,e,t,s,o,a,h,r,i)).toVar();Pp(n.lessThan(l.x),(()=>{l.y.assign(l.x),l.x.assign(n)})).ElseIf(n.lessThan(l.y),(()=>{l.y.assign(n)}))}))}))})),Pp(i.equal(Op(0)),(()=>{l.assign(Ig(l))})),l})).setLayout({name:"mx_worley_noise_vec2_1",type:"vec2",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),ZB=RM([$B,Rp((([e,t,s])=>{const i=Op(s).toVar(),r=Up(t).toVar(),n=jp(e).toVar(),o=Op().toVar(),a=Op().toVar(),h=Op().toVar(),u=jp(gB(n.x,o),gB(n.y,a),gB(n.z,h)).toVar(),l=jp(1e6,1e6,1e6).toVar();return bv({start:-1,end:Op(1),name:"x",condition:"<="},(({x:e})=>{bv({start:-1,end:Op(1),name:"y",condition:"<="},(({y:t})=>{bv({start:-1,end:Op(1),name:"z",condition:"<="},(({z:s})=>{const n=Up(jB(u,e,t,s,o,a,h,r,i)).toVar();Pp(n.lessThan(l.x),(()=>{l.z.assign(l.y),l.y.assign(l.x),l.x.assign(n)})).ElseIf(n.lessThan(l.y),(()=>{l.z.assign(l.y),l.y.assign(n)})).ElseIf(n.lessThan(l.z),(()=>{l.z.assign(n)}))}))}))})),Pp(i.equal(Op(0)),(()=>{l.assign(Ig(l))})),l})).setLayout({name:"mx_worley_noise_vec3_1",type:"vec3",inputs:[{name:"p",type:"vec3"},{name:"jitter",type:"float"},{name:"metric",type:"int"}]})]),JB=Rp((([e])=>{const t=e.y,s=e.z,i=jp().toVar();return Pp(t.lessThan(1e-4),(()=>{i.assign(jp(s,s,s))})).Else((()=>{let r=e.x;r=r.sub(Fg(r)).mul(6).toVar();const n=Op(Qg(r)),o=r.sub(Up(n)),a=s.mul(t.oneMinus()),h=s.mul(t.mul(o).oneMinus()),u=s.mul(t.mul(o.oneMinus()).oneMinus());Pp(n.equal(Op(0)),(()=>{i.assign(jp(s,u,a))})).ElseIf(n.equal(Op(1)),(()=>{i.assign(jp(h,s,a))})).ElseIf(n.equal(Op(2)),(()=>{i.assign(jp(a,s,u))})).ElseIf(n.equal(Op(3)),(()=>{i.assign(jp(a,h,s))})).ElseIf(n.equal(Op(4)),(()=>{i.assign(jp(u,a,s))})).Else((()=>{i.assign(jp(s,a,h))}))})),i})).setLayout({name:"mx_hsvtorgb",type:"vec3",inputs:[{name:"hsv",type:"vec3"}]}),KB=Rp((([e])=>{const t=jp(e).toVar(),s=Up(t.x).toVar(),i=Up(t.y).toVar(),r=Up(t.z).toVar(),n=Up(nf(s,nf(i,r))).toVar(),o=Up(of(s,of(i,r))).toVar(),a=Up(o.sub(n)).toVar(),h=Up().toVar(),u=Up().toVar(),l=Up().toVar();return l.assign(o),Pp(o.greaterThan(0),(()=>{u.assign(a.div(o))})).Else((()=>{u.assign(0)})),Pp(u.lessThanEqual(0),(()=>{h.assign(0)})).Else((()=>{Pp(s.greaterThanEqual(o),(()=>{h.assign(i.sub(r).div(a))})).ElseIf(i.greaterThanEqual(o),(()=>{h.assign(Zm(2,r.sub(s).div(a)))})).Else((()=>{h.assign(Zm(4,s.sub(i).div(a)))})),h.mulAssign(1/6),Pp(h.lessThan(0),(()=>{h.addAssign(1)}))})),jp(h,u,l)})).setLayout({name:"mx_rgbtohsv",type:"vec3",inputs:[{name:"c",type:"vec3"}]}),QB=Rp((([e])=>{const t=jp(e).toVar(),s=$p(rg(t,jp(.04045))).toVar(),i=jp(t.div(12.92)).toVar(),r=jp(mf(of(t.add(jp(.055)),jp(0)).div(1.055),jp(2.4))).toVar();return Tf(i,r,s)})).setLayout({name:"mx_srgb_texture_to_lin_rec709",type:"vec3",inputs:[{name:"color",type:"vec3"}]}),eI=(e,t)=>{e=Up(e),t=Up(t);const s=Dp(t.dFdx(),t.dFdy()).length().mul(.7071067811865476);return Mf(e.sub(s),e.add(s),t)},tI=(e,t,s,i)=>Tf(e,t,s[i].clamp()),sI=(e,t,s=My())=>tI(e,t,s,"x"),iI=(e,t,s=My())=>tI(e,t,s,"y"),rI=(e,t,s,i,r)=>Tf(e,t,eI(s,i[r])),nI=(e,t,s,i=My())=>rI(e,t,s,i,"x"),oI=(e,t,s,i=My())=>rI(e,t,s,i,"y"),aI=(e=1,t=0,s=My())=>s.mul(e).add(t),hI=(e,t=1)=>(e=Up(e)).abs().pow(t).mul(e.sign()),uI=(e,t=1,s=.5)=>Up(e).sub(s).mul(t).add(s),lI=(e=My(),t=1,s=0)=>zB(e.convert("vec2|vec3")).mul(t).add(s),cI=(e=My(),t=1,s=0)=>UB(e.convert("vec2|vec3")).mul(t).add(s),dI=(e=My(),t=1,s=0)=>{e=e.convert("vec2|vec3");return Xp(UB(e),zB(e.add(Dp(19,73)))).mul(t).add(s)},pI=(e=My(),t=1)=>XB(e.convert("vec2|vec3"),t,Op(1)),mI=(e=My(),t=1)=>YB(e.convert("vec2|vec3"),t,Op(1)),gI=(e=My(),t=1)=>ZB(e.convert("vec2|vec3"),t,Op(1)),fI=(e=My())=>OB(e.convert("vec2|vec3")),yI=(e=My(),t=3,s=2,i=.5,r=1)=>VB(e,Op(t),s,i).mul(r),xI=(e=My(),t=3,s=2,i=.5,r=1)=>kB(e,Op(t),s,i).mul(r),bI=(e=My(),t=3,s=2,i=.5,r=1)=>DB(e,Op(t),s,i).mul(r),vI=(e=My(),t=3,s=2,i=.5,r=1)=>GB(e,Op(t),s,i).mul(r),TI=Rp((([e,t])=>{const s=e.x,i=e.y,r=e.z;let n=t.element(0).mul(.886227);return n=n.add(t.element(1).mul(1.023328).mul(i)),n=n.add(t.element(2).mul(1.023328).mul(r)),n=n.add(t.element(3).mul(1.023328).mul(s)),n=n.add(t.element(4).mul(.858086).mul(s).mul(i)),n=n.add(t.element(5).mul(.858086).mul(i).mul(r)),n=n.add(t.element(6).mul(r.mul(r).mul(.743125).sub(.247708))),n=n.add(t.element(7).mul(.858086).mul(s).mul(r)),n=n.add(t.element(8).mul(.429043).mul(Km(s,s).sub(Km(i,i)))),n}));class _I extends JR{static get type(){return"PointLightNode"}constructor(e=null){super(e),this.cutoffDistanceNode=pm(0).setGroup(lm),this.decayExponentNode=pm(0).setGroup(lm)}update(e){const{light:t}=this;super.update(e),this.cutoffDistanceNode.value=t.distance,this.decayExponentNode.value=t.decay}setup(e){const{colorNode:t,cutoffDistanceNode:s,decayExponentNode:i,light:r}=this,n=e.context.lightingModel,o=iE(r).sub(cx),a=o.normalize(),h=o.length(),u=KR({lightDistance:h,cutoffDistance:s,decayExponent:i}),l=t.mul(u),c=e.context.reflectedLight;n.direct({lightDirection:a,lightColor:l,reflectedLight:c},e.stack,e)}}class wI extends JR{static get type(){return"DirectionalLightNode"}constructor(e=null){super(e)}setup(e){super.setup(e);const t=e.context.lightingModel,s=this.colorNode,i=rE(this.light),r=e.context.reflectedLight;t.direct({lightDirection:i,lightColor:s,reflectedLight:r},e.stack,e)}}const SI=new nr,MI=new nr;let NI=null;class AI extends JR{static get type(){return"RectAreaLightNode"}constructor(e=null){super(e),this.halfHeight=pm(new Ri).setGroup(lm),this.halfWidth=pm(new Ri).setGroup(lm)}update(e){super.update(e);const{light:t}=this,s=e.camera.matrixWorldInverse;MI.identity(),SI.copy(t.matrixWorld),SI.premultiply(s),MI.extractRotation(SI),this.halfWidth.value.set(.5*t.width,0,0),this.halfHeight.value.set(0,.5*t.height,0),this.halfWidth.value.applyMatrix4(MI),this.halfHeight.value.applyMatrix4(MI)}setup(e){let t,s;super.setup(e),e.isAvailable("float32Filterable")?(t=By(NI.LTC_FLOAT_1),s=By(NI.LTC_FLOAT_2)):(t=By(NI.LTC_HALF_1),s=By(NI.LTC_HALF_2));const{colorNode:i,light:r}=this,n=e.context.lightingModel,o=iE(r),a=e.context.reflectedLight;n.directRectArea({lightColor:i,lightPosition:o,halfWidth:this.halfWidth,halfHeight:this.halfHeight,reflectedLight:a,ltc_1:t,ltc_2:s},e.stack,e)}static setLTC(e){NI=e}}class CI extends JR{static get type(){return"SpotLightNode"}constructor(e=null){super(e),this.coneCosNode=pm(0).setGroup(lm),this.penumbraCosNode=pm(0).setGroup(lm),this.cutoffDistanceNode=pm(0).setGroup(lm),this.decayExponentNode=pm(0).setGroup(lm)}update(e){super.update(e);const{light:t}=this;this.coneCosNode.value=Math.cos(t.angle),this.penumbraCosNode.value=Math.cos(t.angle*(1-t.penumbra)),this.cutoffDistanceNode.value=t.distance,this.decayExponentNode.value=t.decay}getSpotAttenuation(e){const{coneCosNode:t,penumbraCosNode:s}=this;return Mf(t,s,e)}setup(e){super.setup(e);const t=e.context.lightingModel,{colorNode:s,cutoffDistanceNode:i,decayExponentNode:r,light:n}=this,o=iE(n).sub(cx),a=o.normalize(),h=a.dot(rE(n)),u=this.getSpotAttenuation(h),l=o.length(),c=KR({lightDistance:l,cutoffDistance:i,decayExponent:r}),d=s.mul(u).mul(c),p=e.context.reflectedLight;t.direct({lightDirection:a,lightColor:d,reflectedLight:p},e.stack,e)}}class RI extends CI{static get type(){return"IESSpotLightNode"}getSpotAttenuation(e){const t=this.light.iesMap;let s=null;if(t&&!0===t.isTexture){const i=e.acos().mul(1/Math.PI);s=By(t,Dp(i,0),0).r}else s=super.getSpotAttenuation(e);return s}}class EI extends JR{static get type(){return"AmbientLightNode"}constructor(e=null){super(e)}setup({context:e}){e.irradiance.addAssign(this.colorNode)}}class BI extends JR{static get type(){return"HemisphereLightNode"}constructor(e=null){super(e),this.lightPositionNode=tE(e),this.lightDirectionNode=this.lightPositionNode.normalize(),this.groundColorNode=pm(new Jr).setGroup(lm)}update(e){const{light:t}=this;super.update(e),this.lightPositionNode.object3d=t,this.groundColorNode.value.copy(t.groundColor).multiplyScalar(t.intensity)}setup(e){const{colorNode:t,groundColorNode:s,lightDirectionNode:i}=this,r=bx.dot(i).mul(.5).add(.5),n=Tf(s,t,r);e.context.irradiance.addAssign(n)}}class II extends JR{static get type(){return"LightProbeNode"}constructor(e=null){super(e);const t=[];for(let e=0;e<9;e++)t.push(new Ri);this.lightProbe=Ox(t)}update(e){const{light:t}=this;super.update(e);for(let e=0;e<9;e++)this.lightProbe.array[e].copy(t.sh.coefficients[e]).multiplyScalar(t.intensity)}setup(e){const t=TI(vx,this.lightProbe);e.context.irradiance.addAssign(t)}}class PI{parseFunction(){console.warn("Abstract function.")}}class FI{constructor(e,t,s="",i=""){this.type=e,this.inputs=t,this.name=s,this.precision=i}getCode(){console.warn("Abstract function.")}}FI.isNodeFunction=!0;const zI=/^\s*(highp|mediump|lowp)?\s*([a-z_0-9]+)\s*([a-z_0-9]+)?\s*\(([\s\S]*?)\)/i,UI=/[a-z_0-9]+/gi,OI="#pragma main";class LI extends FI{constructor(e){const{type:t,inputs:s,name:i,precision:r,inputsCode:n,blockCode:o,headerCode:a}=(e=>{const t=(e=e.trim()).indexOf(OI),s=-1!==t?e.slice(t+12):e,i=s.match(zI);if(null!==i&&5===i.length){const r=i[4],n=[];let o=null;for(;null!==(o=UI.exec(r));)n.push(o);const a=[];let h=0;for(;h0?this.transparent:this.opaque).push(o)}unshift(e,t,s,i,r,n){const o=this.getNextRenderItem(e,t,s,i,r,n);(!0===s.transparent?this.transparent:this.opaque).unshift(o)}pushBundle(e){this.bundles.push(e)}pushLight(e){this.lightsArray.push(e)}getLightsNode(){return this.lightsNode.fromLights(this.lightsArray)}sort(e,t){this.opaque.length>1&&this.opaque.sort(e||DI),this.transparent.length>1&&this.transparent.sort(t||kI)}finish(){this.lightsNode.setLights(this.lightsArray);for(let e=this.renderItemsIndex,t=this.renderItems.length;e>t,h=o.height>>t;let u=e.depthTexture||r[t],l=!1;void 0===u&&(u=new Ya,u.format=e.stencilBuffer?je:We,u.type=e.stencilBuffer?Ue:Be,u.image.width=a,u.image.height=h,r[t]=u),s.width===o.width&&o.height===s.height||(l=!0,u.needsUpdate=!0,u.image.width=a,u.image.height=h),s.width=o.width,s.height=o.height,s.textures=n,s.depthTexture=u,s.depth=e.depthBuffer,s.stencil=e.stencilBuffer,s.renderTarget=e,s.sampleCount!==i&&(l=!0,u.needsUpdate=!0,s.sampleCount=i);const c={sampleCount:i};for(let e=0;e{e.removeEventListener("dispose",t);for(let e=0;e0){const i=e.image;if(void 0===i)console.warn("THREE.Renderer: Texture marked for update but image is undefined.");else if(!1===i.complete)console.warn("THREE.Renderer: Texture marked for update but image is incomplete.");else{if(e.images){const s=[];for(const t of e.images)s.push(t);t.images=s}else t.image=i;void 0!==s.isDefaultTexture&&!0!==s.isDefaultTexture||(r.createTexture(e,t),s.isDefaultTexture=!1,s.generation=e.version),!0===e.source.dataReady&&r.updateTexture(e,t),t.needsMipmaps&&0===e.mipmaps.length&&r.generateMipmaps(e)}}else r.createDefaultTexture(e),s.isDefaultTexture=!0,s.generation=e.version}if(!0!==s.initialized){s.initialized=!0,s.generation=e.version,this.info.memory.textures++;const t=()=>{e.removeEventListener("dispose",t),this._destroyTexture(e),this.info.memory.textures--};e.addEventListener("dispose",t)}s.version=e.version}getSize(e,t=XI){let s=e.images?e.images[0]:e.image;return s?(void 0!==s.image&&(s=s.image),t.width=s.width,t.height=s.height,t.depth=e.isCubeTexture?6:s.depth||1):t.width=t.height=t.depth=1,t}getMipLevels(e,t,s){let i;return i=e.isCompressedTexture?e.mipmaps.length:Math.floor(Math.log2(Math.max(t,s)))+1,i}needsMipmaps(e){return!!this.isEnvironmentTexture(e)||(!0===e.isCompressedTexture||e.minFilter!==fe&&e.minFilter!==Te)}isEnvironmentTexture(e){const t=e.mapping;return t===le||t===ce||t===he||t===ue}_destroyTexture(e){this.backend.destroySampler(e),this.backend.destroyTexture(e),this.delete(e)}}class ZI extends Jr{constructor(e,t,s,i=1){super(e,t,s),this.a=i}set(e,t,s,i=1){return this.a=i,super.set(e,t,s)}copy(e){return void 0!==e.a&&(this.a=e.a),super.copy(e)}clone(){return new this.constructor(this.r,this.g,this.b,this.a)}}const JI=new ZI;class KI extends Xw{constructor(e,t){super(),this.renderer=e,this.nodes=t}update(e,t,s){const i=this.renderer,r=this.nodes.getBackgroundNode(e)||e.background;let n=!1;if(null===r)i._clearColor.getRGB(JI,Jt),JI.a=i._clearColor.a;else if(!0===r.isColor)r.getRGB(JI,Jt),JI.a=1,n=!0;else if(!0===r.isNode){const s=this.get(e),n=r;JI.copy(i._clearColor);let o=s.backgroundMesh;if(void 0===o){const e=Ff(Xp(n).mul(wN),{getUV:()=>vx,getTextureLevel:()=>_N});let t=sv();t=t.setZ(t.w);const i=new pT;i.name="Background.material",i.side=d,i.depthTest=!1,i.depthWrite=!1,i.fog=!1,i.lights=!1,i.vertexNode=t,i.colorNode=e,s.backgroundMeshNode=e,s.backgroundMesh=o=new Vn(new du(1,32,32),i),o.frustumCulled=!1,o.name="Background.mesh",o.onBeforeRender=function(e,t,s){this.matrixWorld.copyPosition(s.matrixWorld)}}const a=n.getCacheKey();s.backgroundCacheKey!==a&&(s.backgroundMeshNode.node=Xp(n).mul(wN),s.backgroundMeshNode.needsUpdate=!0,o.material.needsUpdate=!0,s.backgroundCacheKey=a),t.unshift(o,o.geometry,o.material,0,0,null)}else console.error("THREE.Renderer: Unsupported background configuration.",r);if(!0===i.autoClear||!0===n){JI.multiplyScalar(JI.a);const e=s.clearColorValue;e.r=JI.r,e.g=JI.g,e.b=JI.b,e.a=JI.a,s.depthClearValue=i._clearDepth,s.stencilClearValue=i._clearStencil,s.clearColor=!0===i.autoClearColor,s.clearDepth=!0===i.autoClearDepth,s.clearStencil=!0===i.autoClearStencil}else s.clearColor=!1,s.clearDepth=!1,s.clearStencil=!1}}class QI{constructor(e,t,s,i,r,n,o,a,h,u=[]){this.vertexShader=e,this.fragmentShader=t,this.computeShader=s,this.transforms=u,this.nodeAttributes=i,this.bindings=r,this.updateNodes=n,this.updateBeforeNodes=o,this.updateAfterNodes=a,this.monitor=h,this.usedTimes=0}createBindings(){const e=[];for(const t of this.bindings){if(!0!==t.bindings[0].groupNode.shared){const s=new pM(t.name,[],t.index,t);e.push(s);for(const e of t.bindings)s.bindings.push(e.clone())}else e.push(t)}return e}}const eP=new WeakMap;class tP extends Xw{constructor(e,t){super(),this.renderer=e,this.backend=t,this.nodeFrame=new bM,this.nodeBuilderCache=new Map,this.callHashCache=new kw,this.groupsData=new kw}updateGroup(e){const t=e.groupNode,s=t.name;if(s===cm.name)return!0;if(s===lm.name){const t=this.get(e),s=this.nodeFrame.renderId;return t.renderId!==s&&(t.renderId=s,!0)}if(s===um.name){const t=this.get(e),s=this.nodeFrame.frameId;return t.frameId!==s&&(t.frameId=s,!0)}const i=[t,e];let r=this.groupsData.get(i);return void 0===r&&this.groupsData.set(i,r={}),r.version!==t.version&&(r.version=t.version,!0)}getForRenderCacheKey(e){return e.initialCacheKey}getForRender(e){const t=this.get(e);let s=t.nodeBuilderState;if(void 0===s){const{nodeBuilderCache:i}=this,r=this.getForRenderCacheKey(e);if(s=i.get(r),void 0===s){const t=this.backend.createNodeBuilder(e.object,this.renderer);t.scene=e.scene,t.material=e.material,t.camera=e.camera,t.context.material=e.material,t.lightsNode=e.lightsNode,t.environmentNode=this.getEnvironmentNode(e.scene),t.fogNode=this.getFogNode(e.scene),t.clippingContext=e.clippingContext,t.build(),s=this._createNodeBuilderState(t),i.set(r,s)}s.usedTimes++,t.nodeBuilderState=s}return s}delete(e){if(e.isRenderObject){const t=this.get(e).nodeBuilderState;t.usedTimes--,0===t.usedTimes&&this.nodeBuilderCache.delete(this.getForRenderCacheKey(e))}return super.delete(e)}getForCompute(e){const t=this.get(e);let s=t.nodeBuilderState;if(void 0===s){const i=this.backend.createNodeBuilder(e,this.renderer);i.build(),s=this._createNodeBuilderState(i),t.nodeBuilderState=s}return s}_createNodeBuilderState(e){return new QI(e.vertexShader,e.fragmentShader,e.computeShader,e.getAttributesArray(),e.getBindings(),e.updateNodes,e.updateBeforeNodes,e.updateAfterNodes,e.monitor,e.transforms)}getEnvironmentNode(e){return e.environmentNode||this.get(e).environmentNode||null}getBackgroundNode(e){return e.backgroundNode||this.get(e).backgroundNode||null}getFogNode(e){return e.fogNode||this.get(e).fogNode||null}getCacheKey(e,t){const s=[e,t],i=this.renderer.info.calls;let r=this.callHashCache.get(s);if(void 0===r||r.callId!==i){const n=this.getEnvironmentNode(e),o=this.getFogNode(e),a=[];t&&a.push(t.getCacheKey(!0)),n&&a.push(n.getCacheKey()),o&&a.push(o.getCacheKey()),a.push(this.renderer.shadowMap.enabled?1:0),r={callId:i,cacheKey:Td(a)},this.callHashCache.set(s,r)}return r.cacheKey}updateScene(e){this.updateEnvironment(e),this.updateFog(e),this.updateBackground(e)}get isToneMappingState(){return!this.renderer.getRenderTarget()}updateBackground(e){const t=this.get(e),s=e.background;if(s){const i=0===e.backgroundBlurriness&&t.backgroundBlurriness>0||e.backgroundBlurriness>0&&0===t.backgroundBlurriness;if(t.background!==s||i){let i=null;if(!0===s.isCubeTexture||s.mapping===le||s.mapping===ce||s.mapping===de)if(e.backgroundBlurriness>0||s.mapping===de)i=hw(s,vx);else{let e;e=!0===s.isCubeTexture?Ix(s):By(s),i=PT(e)}else!0===s.isTexture?i=By(s,Dv.flipY()).setUpdateMatrix(!0):!0!==s.isColor&&console.error("WebGPUNodes: Unsupported background configuration.",s);t.backgroundNode=i,t.background=s,t.backgroundBlurriness=e.backgroundBlurriness}}else t.backgroundNode&&(delete t.backgroundNode,delete t.background)}updateFog(e){const t=this.get(e),s=e.fog;if(s){if(t.fog!==s){let e=null;if(s.isFogExp2){const t=kx("color","color",s).setGroup(lm),i=kx("density","float",s).setGroup(lm);e=OR(t,i)}else if(s.isFog){const t=kx("color","color",s).setGroup(lm),i=kx("near","float",s).setGroup(lm),r=kx("far","float",s).setGroup(lm);e=zR(t,i,r)}else console.error("WebGPUNodes: Unsupported fog configuration.",s);t.fogNode=e,t.fog=s}}else delete t.fogNode,delete t.fog}updateEnvironment(e){const t=this.get(e),s=e.environment;if(s){if(t.environment!==s){let e=null;!0===s.isCubeTexture?e=Ix(s):!0===s.isTexture?e=By(s):console.error("Nodes: Unsupported environment configuration.",s),t.environmentNode=e,t.environment=s}}else t.environmentNode&&(delete t.environmentNode,delete t.environment)}getNodeFrame(e=this.renderer,t=null,s=null,i=null,r=null){const n=this.nodeFrame;return n.renderer=e,n.scene=t,n.object=s,n.camera=i,n.material=r,n}getNodeFrameForRender(e){return this.getNodeFrame(e.renderer,e.scene,e.object,e.camera,e.material)}getOutputCacheKey(){const e=this.renderer;return e.toneMapping+","+e.currentColorSpace}hasOutputChange(e){return eP.get(e)!==this.getOutputCacheKey()}getOutputNode(e){const t=this.renderer,s=this.getOutputCacheKey(),i=By(e,Dv).renderOutput(t.toneMapping,t.currentColorSpace);return eP.set(e,s),i}updateBefore(e){const t=e.getNodeBuilderState();for(const s of t.updateBeforeNodes)this.getNodeFrameForRender(e).updateBeforeNode(s)}updateAfter(e){const t=e.getNodeBuilderState();for(const s of t.updateAfterNodes)this.getNodeFrameForRender(e).updateAfterNode(s)}updateForCompute(e){const t=this.getNodeFrame(),s=this.getForCompute(e);for(const e of s.updateNodes)t.updateNode(e)}updateForRender(e){const t=this.getNodeFrameForRender(e),s=e.getNodeBuilderState();for(const e of s.updateNodes)t.updateNode(e)}needsRefresh(e){const t=this.getNodeFrameForRender(e);return e.getMonitor().needsRefresh(e,t)}dispose(){super.dispose(),this.nodeFrame=new bM,this.nodeBuilderCache=new Map}}class sP{constructor(e,t){this.scene=e,this.camera=t}clone(){return Object.assign(new this.constructor,this)}}class iP{constructor(){this.lists=new kw}get(e,t){const s=this.lists,i=[e,t];let r=s.get(i);return void 0===r&&(r=new sP(e,t),s.set(i,r)),r}dispose(){this.lists=new kw}}class rP{constructor(){this.lightNodes=new WeakMap,this.materialNodes=new Map,this.toneMappingNodes=new Map,this.colorSpaceNodes=new Map}fromMaterial(e){if(e.isNodeMaterial)return e;let t=null;const s=this.getMaterialNodeClass(e.type);if(null!==s){t=new s;for(const s in e)t[s]=e[s]}return t}addColorSpace(e,t){this.addType(e,t,this.colorSpaceNodes)}getColorSpaceFunction(e){return this.colorSpaceNodes.get(e)||null}addToneMapping(e,t){this.addType(e,t,this.toneMappingNodes)}getToneMappingFunction(e){return this.toneMappingNodes.get(e)||null}getMaterialNodeClass(e){return this.materialNodes.get(e)||null}addMaterial(e,t){this.addType(e,t.name,this.materialNodes)}getLightNodeClass(e){return this.lightNodes.get(e)||null}addLight(e,t){this.addClass(e,t,this.lightNodes)}addType(e,t,s){if(s.has(t))console.warn(`Redefinition of node ${t}`);else{if("function"!=typeof e)throw new Error(`Node class ${e.name} is not a class.`);if("function"==typeof t||"object"==typeof t)throw new Error(`Base class ${t} is not a class.`);s.set(t,e)}}addClass(e,t,s){if(s.has(t))console.warn(`Redefinition of node ${t.name}`);else{if("function"!=typeof e)throw new Error(`Node class ${e.name} is not a class.`);if("function"!=typeof t)throw new Error(`Base class ${t.name} is not a class.`);s.set(t,e)}}}const nP=new to,oP=new Qs,aP=new Ti,hP=new ta,uP=new nr,lP=new Ti;class cP{constructor(e,t={}){this.isRenderer=!0;const{logarithmicDepthBuffer:s=!1,alpha:i=!0,depth:r=!0,stencil:n=!1,antialias:o=!1,samples:a=0,getFallback:h=null}=t;this.domElement=e.getDomElement(),this.backend=e,this.samples=a||!0===o?4:0,this.autoClear=!0,this.autoClearColor=!0,this.autoClearDepth=!0,this.autoClearStencil=!0,this.alpha=i,this.logarithmicDepthBuffer=s,this.outputColorSpace=Zt,this.toneMapping=0,this.toneMappingExposure=1,this.sortObjects=!0,this.depth=r,this.stencil=n,this.clippingPlanes=[],this.info=new iS,this.nodes={library:new rP,modelViewMatrix:null,modelNormalViewMatrix:null},this._getFallback=h,this._pixelRatio=1,this._width=this.domElement.width,this._height=this.domElement.height,this._viewport=new Ti(0,0,this._width,this._height),this._scissor=new Ti(0,0,this._width,this._height),this._scissorTest=!1,this._attributes=null,this._geometries=null,this._nodes=null,this._animation=null,this._bindings=null,this._objects=null,this._pipelines=null,this._bundles=null,this._renderLists=null,this._renderContexts=null,this._textures=null,this._background=null,this._quad=new dN(new pT),this._quad.material.type="Renderer_output",this._currentRenderContext=null,this._opaqueSort=null,this._transparentSort=null,this._frameBufferTarget=null;const u=!0===this.alpha?0:1;this._clearColor=new ZI(0,0,0,u),this._clearDepth=1,this._clearStencil=0,this._renderTarget=null,this._activeCubeFace=0,this._activeMipmapLevel=0,this._mrt=null,this._renderObjectFunction=null,this._currentRenderObjectFunction=null,this._currentRenderBundle=null,this._handleObjectFunction=this._renderObjectDirect,this._initialized=!1,this._initPromise=null,this._compilationPromises=null,this.transparent=!0,this.opaque=!0,this.shadowMap={enabled:!1,type:1},this.xr={enabled:!1},this.debug={checkShaderErrors:!0,onShaderError:null,getShaderAsync:async(e,t,s)=>{await this.compileAsync(e,t);const i=this._renderLists.get(e,t),r=this._renderContexts.get(e,t,this._renderTarget),n=e.overrideMaterial||s.material,o=this._objects.get(s,n,e,t,i.lightsNode,r),{fragmentShader:a,vertexShader:h}=o.getNodeBuilderState();return{fragmentShader:a,vertexShader:h}}}}async init(){if(this._initialized)throw new Error("Renderer: Backend has already been initialized.");return null!==this._initPromise||(this._initPromise=new Promise((async(e,t)=>{let s=this.backend;try{await s.init(this)}catch(e){if(null===this._getFallback)return void t(e);try{this.backend=s=this._getFallback(e),await s.init(this)}catch(e){return void t(e)}}this._nodes=new tP(this,s),this._animation=new Dw(this._nodes,this.info),this._attributes=new Qw(s),this._background=new KI(this,this._nodes),this._geometries=new sS(this._attributes,this.info),this._textures=new YI(this,s,this.info),this._pipelines=new uS(s,this._nodes),this._bindings=new lS(s,this._nodes,this._textures,this._attributes,this._pipelines,this.info),this._objects=new $w(this,this._nodes,this._geometries,this._pipelines,this._bindings,this.info),this._renderLists=new WI,this._bundles=new iP,this._renderContexts=new $I,this._initialized=!0,e()}))),this._initPromise}get coordinateSystem(){return this.backend.coordinateSystem}async compileAsync(e,t,s=null){!1===this._initialized&&await this.init();const i=this._nodes.nodeFrame,r=i.renderId,n=this._currentRenderContext,o=this._currentRenderObjectFunction,a=this._compilationPromises,h=!0===e.isScene?e:nP;null===s&&(s=e);const u=this._renderTarget,l=this._renderContexts.get(s,t,u),c=this._activeMipmapLevel,d=[];this._currentRenderContext=l,this._currentRenderObjectFunction=this.renderObject,this._handleObjectFunction=this._createObjectPipeline,this._compilationPromises=d,i.renderId++,i.update(),l.depth=this.depth,l.stencil=this.stencil,l.clippingContext||(l.clippingContext=new Ww),l.clippingContext.updateGlobal(this,t),h.onBeforeRender(this,e,t,u);const p=this._renderLists.get(e,t);if(p.begin(),this._projectObject(e,t,0,p),s!==e&&s.traverseVisible((function(e){e.isLight&&e.layers.test(t.layers)&&p.pushLight(e)})),p.finish(),null!==u){this._textures.updateRenderTarget(u,c);const e=this._textures.get(u);l.textures=e.textures,l.depthTexture=e.depthTexture}else l.textures=null,l.depthTexture=null;this._nodes.updateScene(h),this._background.update(h,p,l);const m=p.opaque,g=p.transparent,f=p.lightsNode;!0===this.opaque&&m.length>0&&this._renderObjects(m,t,h,f),!0===this.transparent&&g.length>0&&this._renderObjects(g,t,h,f),i.renderId=r,this._currentRenderContext=n,this._currentRenderObjectFunction=o,this._compilationPromises=a,this._handleObjectFunction=this._renderObjectDirect,await Promise.all(d)}async renderAsync(e,t){!1===this._initialized&&await this.init();const s=this._renderScene(e,t);await this.backend.resolveTimestampAsync(s,"render")}setMRT(e){return this._mrt=e,this}getMRT(){return this._mrt}_renderBundle(e,t,s){const{bundleGroup:i,camera:r,renderList:n}=e,o=this._currentRenderContext,a=this._bundles.get(i,r),h=this.backend.get(a);void 0===h.renderContexts&&(h.renderContexts=new Set);const u=i.version!==h.version,l=!1===h.renderContexts.has(o)||u;if(h.renderContexts.add(o),l){this.backend.beginBundle(o),(void 0===h.renderObjects||u)&&(h.renderObjects=[]),this._currentRenderBundle=a;const e=n.opaque;e.length>0&&this._renderObjects(e,r,t,s),this._currentRenderBundle=null,this.backend.finishBundle(o,a),h.version=i.version}else{const{renderObjects:e}=h;for(let t=0,s=e.length;t>=c,p.viewportValue.height>>=c,p.viewportValue.minDepth=x,p.viewportValue.maxDepth=b,p.viewport=!1===p.viewportValue.equals(aP),p.scissorValue.copy(f).multiplyScalar(y).floor(),p.scissor=this._scissorTest&&!1===p.scissorValue.equals(aP),p.scissorValue.width>>=c,p.scissorValue.height>>=c,p.clippingContext||(p.clippingContext=new Ww),p.clippingContext.updateGlobal(this,t),h.onBeforeRender(this,e,t,d),uP.multiplyMatrices(t.projectionMatrix,t.matrixWorldInverse),hP.setFromProjectionMatrix(uP,m);const v=this._renderLists.get(e,t);if(v.begin(),this._projectObject(e,t,0,v),v.finish(),!0===this.sortObjects&&v.sort(this._opaqueSort,this._transparentSort),null!==d){this._textures.updateRenderTarget(d,c);const e=this._textures.get(d);p.textures=e.textures,p.depthTexture=e.depthTexture,p.width=e.width,p.height=e.height,p.renderTarget=d,p.depth=d.depthBuffer,p.stencil=d.stencilBuffer}else p.textures=null,p.depthTexture=null,p.width=this.domElement.width,p.height=this.domElement.height,p.depth=this.depth,p.stencil=this.stencil;p.width>>=c,p.height>>=c,p.activeCubeFace=l,p.activeMipmapLevel=c,p.occlusionQueryCount=v.occlusionQueryCount,this._nodes.updateScene(h),this._background.update(h,v,p),this.backend.beginRender(p);const{bundles:T,lightsNode:_,transparent:w,opaque:S}=v;if(T.length>0&&this._renderBundles(T,h,_),!0===this.opaque&&S.length>0&&this._renderObjects(S,t,h,_),!0===this.transparent&&w.length>0&&this._renderObjects(w,t,h,_),this.backend.finishRender(p),r.renderId=n,this._currentRenderContext=o,this._currentRenderObjectFunction=a,null!==i){this.setRenderTarget(u,l,c);const e=this._quad;this._nodes.hasOutputChange(d.texture)&&(e.material.fragmentNode=this._nodes.getOutputNode(d.texture),e.material.needsUpdate=!0),this._renderScene(e,e.camera,!1)}return h.onAfterRender(this,e,t,d),p}getMaxAnisotropy(){return this.backend.getMaxAnisotropy()}getActiveCubeFace(){return this._activeCubeFace}getActiveMipmapLevel(){return this._activeMipmapLevel}async setAnimationLoop(e){!1===this._initialized&&await this.init(),this._animation.setAnimationLoop(e)}async getArrayBufferAsync(e){return await this.backend.getArrayBufferAsync(e)}getContext(){return this.backend.getContext()}getPixelRatio(){return this._pixelRatio}getDrawingBufferSize(e){return e.set(this._width*this._pixelRatio,this._height*this._pixelRatio).floor()}getSize(e){return e.set(this._width,this._height)}setPixelRatio(e=1){this._pixelRatio=e,this.setSize(this._width,this._height,!1)}setDrawingBufferSize(e,t,s){this._width=e,this._height=t,this._pixelRatio=s,this.domElement.width=Math.floor(e*s),this.domElement.height=Math.floor(t*s),this.setViewport(0,0,e,t),this._initialized&&this.backend.updateSize()}setSize(e,t,s=!0){this._width=e,this._height=t,this.domElement.width=Math.floor(e*this._pixelRatio),this.domElement.height=Math.floor(t*this._pixelRatio),!0===s&&(this.domElement.style.width=e+"px",this.domElement.style.height=t+"px"),this.setViewport(0,0,e,t),this._initialized&&this.backend.updateSize()}setOpaqueSort(e){this._opaqueSort=e}setTransparentSort(e){this._transparentSort=e}getScissor(e){const t=this._scissor;return e.x=t.x,e.y=t.y,e.width=t.width,e.height=t.height,e}setScissor(e,t,s,i){const r=this._scissor;e.isVector4?r.copy(e):r.set(e,t,s,i)}getScissorTest(){return this._scissorTest}setScissorTest(e){this._scissorTest=e,this.backend.setScissorTest(e)}getViewport(e){return e.copy(this._viewport)}setViewport(e,t,s,i,r=0,n=1){const o=this._viewport;e.isVector4?o.copy(e):o.set(e,t,s,i),o.minDepth=r,o.maxDepth=n}getClearColor(e){return e.copy(this._clearColor)}setClearColor(e,t=1){this._clearColor.set(e),this._clearColor.a=t}getClearAlpha(){return this._clearColor.a}setClearAlpha(e){this._clearColor.a=e}getClearDepth(){return this._clearDepth}setClearDepth(e){this._clearDepth=e}getClearStencil(){return this._clearStencil}setClearStencil(e){this._clearStencil=e}isOccluded(e){const t=this._currentRenderContext;return t&&this.backend.isOccluded(t,e)}clear(e=!0,t=!0,s=!0){if(!1===this._initialized)return console.warn("THREE.Renderer: .clear() called before the backend is initialized. Try using .clearAsync() instead."),this.clearAsync(e,t,s);const i=this._renderTarget||this._getFrameBufferTarget();let r=null;if(null!==i&&(this._textures.updateRenderTarget(i),r=this._textures.get(i)),this.backend.clear(e,t,s,r),null!==i&&null===this._renderTarget){const e=this._quad;this._nodes.hasOutputChange(i.texture)&&(e.material.fragmentNode=this._nodes.getOutputNode(i.texture),e.material.needsUpdate=!0),this._renderScene(e,e.camera,!1)}}clearColor(){return this.clear(!0,!1,!1)}clearDepth(){return this.clear(!1,!0,!1)}clearStencil(){return this.clear(!1,!1,!0)}async clearAsync(e=!0,t=!0,s=!0){!1===this._initialized&&await this.init(),this.clear(e,t,s)}clearColorAsync(){return this.clearAsync(!0,!1,!1)}clearDepthAsync(){return this.clearAsync(!1,!0,!1)}clearStencilAsync(){return this.clearAsync(!1,!1,!0)}get currentToneMapping(){return null!==this._renderTarget?0:this.toneMapping}get currentColorSpace(){return null!==this._renderTarget?Jt:this.outputColorSpace}dispose(){this.info.dispose(),this._animation.dispose(),this._objects.dispose(),this._pipelines.dispose(),this._nodes.dispose(),this._bindings.dispose(),this._renderLists.dispose(),this._renderContexts.dispose(),this._textures.dispose(),this.setRenderTarget(null),this.setAnimationLoop(null)}setRenderTarget(e,t=0,s=0){this._renderTarget=e,this._activeCubeFace=t,this._activeMipmapLevel=s}getRenderTarget(){return this._renderTarget}setRenderObjectFunction(e){this._renderObjectFunction=e}getRenderObjectFunction(){return this._renderObjectFunction}async computeAsync(e){!1===this._initialized&&await this.init();const t=this._nodes.nodeFrame,s=t.renderId;this.info.calls++,this.info.compute.calls++,this.info.compute.frameCalls++,t.renderId=this.info.calls;const i=this.backend,r=this._pipelines,n=this._bindings,o=this._nodes,a=Array.isArray(e)?e:[e];if(void 0===a[0]||!0!==a[0].isComputeNode)throw new Error("THREE.Renderer: .compute() expects a ComputeNode.");i.beginCompute(e);for(const t of a){if(!1===r.has(t)){const e=()=>{t.removeEventListener("dispose",e),r.delete(t),n.delete(t),o.delete(t)};t.addEventListener("dispose",e),t.onInit({renderer:this})}o.updateForCompute(t),n.updateForCompute(t);const s=n.getForCompute(t),a=r.getForCompute(t,s);i.compute(e,t,s,a)}i.finishCompute(e),await this.backend.resolveTimestampAsync(e,"compute"),t.renderId=s}async hasFeatureAsync(e){return!1===this._initialized&&await this.init(),this.backend.hasFeature(e)}hasFeature(e){return!1===this._initialized?(console.warn("THREE.Renderer: .hasFeature() called before the backend is initialized. Try using .hasFeatureAsync() instead."),!1):this.backend.hasFeature(e)}copyFramebufferToTexture(e,t=null){const s=this._currentRenderContext;this._textures.updateTexture(e),t=null===t?lP.set(0,0,e.image.width,e.image.height):t,this.backend.copyFramebufferToTexture(e,s,t)}copyTextureToTexture(e,t,s=null,i=null,r=0){this._textures.updateTexture(e),this._textures.updateTexture(t),this.backend.copyTextureToTexture(e,t,s,i,r)}readRenderTargetPixelsAsync(e,t,s,i,r,n=0,o=0){return this.backend.copyTextureToBuffer(e.textures[n],t,s,i,r,o)}_projectObject(e,t,s,i){if(!1===e.visible)return;if(e.layers.test(t.layers))if(e.isGroup)s=e.renderOrder;else if(e.isLOD)!0===e.autoUpdate&&e.update(t);else if(e.isLight)i.pushLight(e);else if(e.isSprite){if(!e.frustumCulled||hP.intersectsSprite(e)){!0===this.sortObjects&&lP.setFromMatrixPosition(e.matrixWorld).applyMatrix4(uP);const{geometry:t,material:r}=e;r.visible&&i.push(e,t,r,s,lP.z,null)}}else if(e.isLineLoop)console.error("THREE.Renderer: Objects of type THREE.LineLoop are not supported. Please use THREE.Line or THREE.LineSegments.");else if((e.isMesh||e.isLine||e.isPoints)&&(!e.frustumCulled||hP.intersectsObject(e))){const{geometry:t,material:r}=e;if(!0===this.sortObjects&&(null===t.boundingSphere&&t.computeBoundingSphere(),lP.copy(t.boundingSphere.center).applyMatrix4(e.matrixWorld).applyMatrix4(uP)),Array.isArray(r)){const n=t.groups;for(let o=0,a=n.length;o0?i:"";t=`${e.name} {\n\t${s} ${r.name}[${n}];\n};\n`}else{t=`${this.getVectorType(r.type)} ${this.getPropertyName(r,e)};`,n=!0}const o=r.node.precision;if(null!==o&&(t=NP[o]+" "+t),n){t="\t"+t;const e=r.groupNode.name;(i[e]||(i[e]=[])).push(t)}else t="uniform "+t,s.push(t)}let r="";for(const t in i){const s=i[t];r+=this._getGLSLUniformStruct(e+"_"+t,s.join("\n"))+"\n"}return r+=s.join("\n"),r}getTypeFromAttribute(e){let t=super.getTypeFromAttribute(e);if(/^[iu]/.test(t)&&e.gpuType!==Ee){let s=e;e.isInterleavedBufferAttribute&&(s=e.data);const i=s.array;!1==(i instanceof Uint32Array||i instanceof Int32Array)&&(t=t.slice(1))}return t}getAttributes(e){let t="";if("vertex"===e||"compute"===e){const e=this.getAttributesArray();let s=0;for(const i of e)t+=`layout( location = ${s++} ) in ${i.type} ${i.name};\n`}return t}getStructMembers(e){const t=[],s=e.getMemberTypes();for(let e=0;ee*t),1)}u`}getDrawIndex(){return this.renderer.backend.extensions.has("WEBGL_multi_draw")?"uint( gl_DrawID )":null}getFrontFacing(){return"gl_FrontFacing"}getFragCoord(){return"gl_FragCoord.xy"}getFragDepth(){return"gl_FragDepth"}enableExtension(e,t,s=this.shaderStage){const i=this.extensions[s]||(this.extensions[s]=new Map);!1===i.has(e)&&i.set(e,{name:e,behavior:t})}getExtensions(e){const t=[];if("vertex"===e){const t=this.renderer.backend.extensions;this.object.isBatchedMesh&&t.has("WEBGL_multi_draw")&&this.enableExtension("GL_ANGLE_multi_draw","require",e)}const s=this.extensions[e];if(void 0!==s)for(const{name:e,behavior:i}of s.values())t.push(`#extension ${e} : ${i}`);return t.join("\n")}isAvailable(e){let t=AP[e];if(void 0===t){if("float32Filterable"===e){const e=this.renderer.backend.extensions;e.has("OES_texture_float_linear")?(e.get("OES_texture_float_linear"),t=!0):t=!1}AP[e]=t}return t}isFlipY(){return!0}registerTransform(e,t){this.transforms.push({varyingName:e,attributeNode:t})}getTransforms(){const e=this.transforms;let t="";for(let s=0;s0&&(s+="\n"),s+=`\t// flow -> ${n}\n\t`),s+=`${i.code}\n\t`,e===r&&"compute"!==t&&(s+="// result\n\t","vertex"===t?(s+="gl_Position = ",s+=`${i.result};`):"fragment"===t&&(e.outputNode.isOutputStructNode||(s+="fragColor = ",s+=`${i.result};`)))}const n=e[t];n.extensions=this.getExtensions(t),n.uniforms=this.getUniforms(t),n.attributes=this.getAttributes(t),n.varyings=this.getVaryings(t),n.vars=this.getVars(t),n.structs=this.getStructs(t),n.codes=this.getCodes(t),n.transforms=this.getTransforms(t),n.flow=s}null!==this.material?(this.vertexShader=this._getGLSLVertexCode(e.vertex),this.fragmentShader=this._getGLSLFragmentCode(e.fragment)):this.computeShader=this._getGLSLVertexCode(e.compute)}getUniformFromNode(e,t,s,i=null){const r=super.getUniformFromNode(e,t,s,i),n=this.getDataFromNode(e,s,this.globalCache);let o=n.uniformGPU;if(void 0===o){const i=e.groupNode,a=i.name,h=this.getBindGroupArray(a,s);if("texture"===t)o=new _P(r.name,r.node,i),h.push(o);else if("cubeTexture"===t)o=new wP(r.name,r.node,i),h.push(o);else if("texture3D"===t)o=new SP(r.name,r.node,i),h.push(o);else if("buffer"===t){e.name=`NodeBuffer_${e.id}`,r.name=`buffer${e.id}`;const t=new fP(e,i);t.name=e.name,h.push(t),o=t}else{const e=this.uniformGroups[s]||(this.uniformGroups[s]={});let n=e[a];void 0===n&&(n=new bP(s+"_"+a,i),e[a]=n,h.push(n)),o=this.getNodeUniform(r,t),n.addUniform(o)}n.uniformGPU=o}return r}}let EP=null,BP=null,IP=null;class PP{constructor(e={}){this.parameters=Object.assign({},e),this.data=new WeakMap,this.renderer=null,this.domElement=null}async init(e){this.renderer=e}begin(){}finish(){}draw(){}createProgram(){}destroyProgram(){}createBindings(){}updateBindings(){}createRenderPipeline(){}createComputePipeline(){}destroyPipeline(){}needsRenderUpdate(){}getRenderCacheKey(){}createNodeBuilder(){}createSampler(){}createDefaultTexture(){}createTexture(){}copyTextureToBuffer(){}createAttribute(){}createIndexAttribute(){}updateAttribute(){}destroyAttribute(){}getContext(){}updateSize(){}resolveTimestampAsync(){}hasFeatureAsync(){}hasFeature(){}getInstanceCount(e){const{object:t,geometry:s}=e;return s.isInstancedBufferGeometry?s.instanceCount:t.count>1?t.count:1}getDrawingBufferSize(){return EP=EP||new Qs,this.renderer.getDrawingBufferSize(EP)}getScissor(){return BP=BP||new Ti,this.renderer.getScissor(BP)}setScissorTest(){}getClearColor(){const e=this.renderer;return IP=IP||new ZI,e.getClearColor(IP),IP.getRGB(IP,this.renderer.currentColorSpace),IP}getDomElement(){let t=this.domElement;return null===t&&(t=void 0!==this.parameters.canvas?this.parameters.canvas:ni(),"setAttribute"in t&&t.setAttribute("data-engine",`three.js r${e} webgpu`),this.domElement=t),t}set(e,t){this.data.set(e,t)}get(e){let t=this.data.get(e);return void 0===t&&(t={},this.data.set(e,t)),t}has(e){return this.data.has(e)}delete(e){this.data.delete(e)}}let FP=0;class zP{constructor(e,t){this.buffers=[e.bufferGPU,t],this.type=e.type,this.bufferType=e.bufferType,this.pbo=e.pbo,this.byteLength=e.byteLength,this.bytesPerElement=e.BYTES_PER_ELEMENT,this.version=e.version,this.isInteger=e.isInteger,this.activeBufferIndex=0,this.baseId=e.id}get id(){return`${this.baseId}|${this.activeBufferIndex}`}get bufferGPU(){return this.buffers[this.activeBufferIndex]}get transformBuffer(){return this.buffers[1^this.activeBufferIndex]}switchBuffers(){this.activeBufferIndex^=1}}class UP{constructor(e){this.backend=e}createAttribute(e,t){const s=this.backend,{gl:i}=s,r=e.array,n=e.usage||i.STATIC_DRAW,o=e.isInterleavedBufferAttribute?e.data:e,a=s.get(o);let h,u=a.bufferGPU;if(void 0===u&&(u=this._createBuffer(i,t,r,n),a.bufferGPU=u,a.bufferType=t,a.version=o.version),r instanceof Float32Array)h=i.FLOAT;else if(r instanceof Uint16Array)h=e.isFloat16BufferAttribute?i.HALF_FLOAT:i.UNSIGNED_SHORT;else if(r instanceof Int16Array)h=i.SHORT;else if(r instanceof Uint32Array)h=i.UNSIGNED_INT;else if(r instanceof Int32Array)h=i.INT;else if(r instanceof Int8Array)h=i.BYTE;else if(r instanceof Uint8Array)h=i.UNSIGNED_BYTE;else{if(!(r instanceof Uint8ClampedArray))throw new Error("THREE.WebGLBackend: Unsupported buffer data format: "+r);h=i.UNSIGNED_BYTE}let l={bufferGPU:u,bufferType:t,type:h,byteLength:r.byteLength,bytesPerElement:r.BYTES_PER_ELEMENT,version:e.version,pbo:e.pbo,isInteger:h===i.INT||h===i.UNSIGNED_INT||e.gpuType===Ee,id:FP++};if(e.isStorageBufferAttribute||e.isStorageInstancedBufferAttribute){const e=this._createBuffer(i,t,r,n);l=new zP(l,e)}s.set(e,l)}updateAttribute(e){const t=this.backend,{gl:s}=t,i=e.array,r=e.isInterleavedBufferAttribute?e.data:e,n=t.get(r),o=n.bufferType,a=e.isInterleavedBufferAttribute?e.data.updateRanges:e.updateRanges;if(s.bindBuffer(o,n.bufferGPU),0===a.length)s.bufferSubData(o,0,i);else{for(let e=0,t=a.length;e1?this.enable(s.SAMPLE_ALPHA_TO_COVERAGE):this.disable(s.SAMPLE_ALPHA_TO_COVERAGE)}setPolygonOffset(e,t,s){const{gl:i}=this;e?(this.enable(i.POLYGON_OFFSET_FILL),this.currentPolygonOffsetFactor===t&&this.currentPolygonOffsetUnits===s||(i.polygonOffset(t,s),this.currentPolygonOffsetFactor=t,this.currentPolygonOffsetUnits=s)):this.disable(i.POLYGON_OFFSET_FILL)}useProgram(e){return this.currentProgram!==e&&(this.gl.useProgram(e),this.currentProgram=e,!0)}bindFramebuffer(e,t){const{gl:s,currentBoundFramebuffers:i}=this;return i[e]!==t&&(s.bindFramebuffer(e,t),i[e]=t,e===s.DRAW_FRAMEBUFFER&&(i[s.FRAMEBUFFER]=t),e===s.FRAMEBUFFER&&(i[s.DRAW_FRAMEBUFFER]=t),!0)}drawBuffers(e,t){const{gl:s}=this;let i=[],r=!1;if(null!==e.textures){i=this.currentDrawbuffers.get(t),void 0===i&&(i=[],this.currentDrawbuffers.set(t,i));const n=e.textures;if(i.length!==n.length||i[0]!==s.COLOR_ATTACHMENT0){for(let e=0,t=n.length;e{!function r(){const n=e.clientWaitSync(t,e.SYNC_FLUSH_COMMANDS_BIT,0);if(n===e.WAIT_FAILED)return e.deleteSync(t),void i();n!==e.TIMEOUT_EXPIRED?(e.deleteSync(t),s()):requestAnimationFrame(r)}()}))}}let GP,WP,jP,HP=!1;class qP{constructor(e){this.backend=e,this.gl=e.gl,this.extensions=e.extensions,this.defaultTextures={},!1===HP&&(this._init(this.gl),HP=!0)}_init(e){GP={[pe]:e.REPEAT,[me]:e.CLAMP_TO_EDGE,[ge]:e.MIRRORED_REPEAT},WP={[fe]:e.NEAREST,[ye]:e.NEAREST_MIPMAP_NEAREST,[be]:e.NEAREST_MIPMAP_LINEAR,[Te]:e.LINEAR,[_e]:e.LINEAR_MIPMAP_NEAREST,[Se]:e.LINEAR_MIPMAP_LINEAR},jP={512:e.NEVER,519:e.ALWAYS,[Ts]:e.LESS,515:e.LEQUAL,514:e.EQUAL,518:e.GEQUAL,516:e.GREATER,517:e.NOTEQUAL}}filterFallback(e){const{gl:t}=this;return e===fe||e===ye||e===be?t.NEAREST:t.LINEAR}getGLTextureType(e){const{gl:t}=this;let s;return s=!0===e.isCubeTexture?t.TEXTURE_CUBE_MAP:!0===e.isDataArrayTexture||!0===e.isCompressedArrayTexture?t.TEXTURE_2D_ARRAY:!0===e.isData3DTexture?t.TEXTURE_3D:t.TEXTURE_2D,s}getInternalFormat(e,t,s,i,r=!1){const{gl:n,extensions:o}=this;if(null!==e){if(void 0!==n[e])return n[e];console.warn("THREE.WebGLRenderer: Attempt to use non-existing WebGL internal format '"+e+"'")}let a=t;return t===n.RED&&(s===n.FLOAT&&(a=n.R32F),s===n.HALF_FLOAT&&(a=n.R16F),s===n.UNSIGNED_BYTE&&(a=n.R8),s===n.UNSIGNED_SHORT&&(a=n.R16),s===n.UNSIGNED_INT&&(a=n.R32UI),s===n.BYTE&&(a=n.R8I),s===n.SHORT&&(a=n.R16I),s===n.INT&&(a=n.R32I)),t===n.RED_INTEGER&&(s===n.UNSIGNED_BYTE&&(a=n.R8UI),s===n.UNSIGNED_SHORT&&(a=n.R16UI),s===n.UNSIGNED_INT&&(a=n.R32UI),s===n.BYTE&&(a=n.R8I),s===n.SHORT&&(a=n.R16I),s===n.INT&&(a=n.R32I)),t===n.RG&&(s===n.FLOAT&&(a=n.RG32F),s===n.HALF_FLOAT&&(a=n.RG16F),s===n.UNSIGNED_BYTE&&(a=n.RG8),s===n.UNSIGNED_SHORT&&(a=n.RG16),s===n.UNSIGNED_INT&&(a=n.RG32UI),s===n.BYTE&&(a=n.RG8I),s===n.SHORT&&(a=n.RG16I),s===n.INT&&(a=n.RG32I)),t===n.RG_INTEGER&&(s===n.UNSIGNED_BYTE&&(a=n.RG8UI),s===n.UNSIGNED_SHORT&&(a=n.RG16UI),s===n.UNSIGNED_INT&&(a=n.RG32UI),s===n.BYTE&&(a=n.RG8I),s===n.SHORT&&(a=n.RG16I),s===n.INT&&(a=n.RG32I)),t===n.RGB&&(s===n.FLOAT&&(a=n.RGB32F),s===n.HALF_FLOAT&&(a=n.RGB16F),s===n.UNSIGNED_BYTE&&(a=n.RGB8),s===n.UNSIGNED_SHORT&&(a=n.RGB16),s===n.UNSIGNED_INT&&(a=n.RGB32UI),s===n.BYTE&&(a=n.RGB8I),s===n.SHORT&&(a=n.RGB16I),s===n.INT&&(a=n.RGB32I),s===n.UNSIGNED_BYTE&&(a=i===Zt&&!1===r?n.SRGB8:n.RGB8),s===n.UNSIGNED_SHORT_5_6_5&&(a=n.RGB565),s===n.UNSIGNED_SHORT_5_5_5_1&&(a=n.RGB5_A1),s===n.UNSIGNED_SHORT_4_4_4_4&&(a=n.RGB4),s===n.UNSIGNED_INT_5_9_9_9_REV&&(a=n.RGB9_E5)),t===n.RGB_INTEGER&&(s===n.UNSIGNED_BYTE&&(a=n.RGB8UI),s===n.UNSIGNED_SHORT&&(a=n.RGB16UI),s===n.UNSIGNED_INT&&(a=n.RGB32UI),s===n.BYTE&&(a=n.RGB8I),s===n.SHORT&&(a=n.RGB16I),s===n.INT&&(a=n.RGB32I)),t===n.RGBA&&(s===n.FLOAT&&(a=n.RGBA32F),s===n.HALF_FLOAT&&(a=n.RGBA16F),s===n.UNSIGNED_BYTE&&(a=n.RGBA8),s===n.UNSIGNED_SHORT&&(a=n.RGBA16),s===n.UNSIGNED_INT&&(a=n.RGBA32UI),s===n.BYTE&&(a=n.RGBA8I),s===n.SHORT&&(a=n.RGBA16I),s===n.INT&&(a=n.RGBA32I),s===n.UNSIGNED_BYTE&&(a=i===Zt&&!1===r?n.SRGB8_ALPHA8:n.RGBA8),s===n.UNSIGNED_SHORT_4_4_4_4&&(a=n.RGBA4),s===n.UNSIGNED_SHORT_5_5_5_1&&(a=n.RGB5_A1)),t===n.RGBA_INTEGER&&(s===n.UNSIGNED_BYTE&&(a=n.RGBA8UI),s===n.UNSIGNED_SHORT&&(a=n.RGBA16UI),s===n.UNSIGNED_INT&&(a=n.RGBA32UI),s===n.BYTE&&(a=n.RGBA8I),s===n.SHORT&&(a=n.RGBA16I),s===n.INT&&(a=n.RGBA32I)),t===n.DEPTH_COMPONENT&&(s===n.UNSIGNED_INT&&(a=n.DEPTH24_STENCIL8),s===n.FLOAT&&(a=n.DEPTH_COMPONENT32F)),t===n.DEPTH_STENCIL&&s===n.UNSIGNED_INT_24_8&&(a=n.DEPTH24_STENCIL8),a!==n.R16F&&a!==n.R32F&&a!==n.RG16F&&a!==n.RG32F&&a!==n.RGBA16F&&a!==n.RGBA32F||o.get("EXT_color_buffer_float"),a}setTextureParameters(e,t){const{gl:s,extensions:i,backend:r}=this;s.pixelStorei(s.UNPACK_FLIP_Y_WEBGL,t.flipY),s.pixelStorei(s.UNPACK_PREMULTIPLY_ALPHA_WEBGL,t.premultiplyAlpha),s.pixelStorei(s.UNPACK_ALIGNMENT,t.unpackAlignment),s.pixelStorei(s.UNPACK_COLORSPACE_CONVERSION_WEBGL,s.NONE),s.texParameteri(e,s.TEXTURE_WRAP_S,GP[t.wrapS]),s.texParameteri(e,s.TEXTURE_WRAP_T,GP[t.wrapT]),e!==s.TEXTURE_3D&&e!==s.TEXTURE_2D_ARRAY||s.texParameteri(e,s.TEXTURE_WRAP_R,GP[t.wrapR]),s.texParameteri(e,s.TEXTURE_MAG_FILTER,WP[t.magFilter]);const n=void 0!==t.mipmaps&&t.mipmaps.length>0,o=t.minFilter===Te&&n?Se:t.minFilter;if(s.texParameteri(e,s.TEXTURE_MIN_FILTER,WP[o]),t.compareFunction&&(s.texParameteri(e,s.TEXTURE_COMPARE_MODE,s.COMPARE_REF_TO_TEXTURE),s.texParameteri(e,s.TEXTURE_COMPARE_FUNC,jP[t.compareFunction])),!0===i.has("EXT_texture_filter_anisotropic")){if(t.magFilter===fe)return;if(t.minFilter!==be&&t.minFilter!==Se)return;if(t.type===Ie&&!1===i.has("OES_texture_float_linear"))return;if(t.anisotropy>1){const n=i.get("EXT_texture_filter_anisotropic");s.texParameterf(e,n.TEXTURE_MAX_ANISOTROPY_EXT,Math.min(t.anisotropy,r.getMaxAnisotropy()))}}}createDefaultTexture(e){const{gl:t,backend:s,defaultTextures:i}=this,r=this.getGLTextureType(e);let n=i[r];void 0===n&&(n=t.createTexture(),s.state.bindTexture(r,n),t.texParameteri(r,t.TEXTURE_MIN_FILTER,t.NEAREST),t.texParameteri(r,t.TEXTURE_MAG_FILTER,t.NEAREST),i[r]=n),s.set(e,{textureGPU:n,glTextureType:r,isDefault:!0})}createTexture(e,t){const{gl:s,backend:i}=this,{levels:r,width:n,height:o,depth:a}=t,h=i.utils.convert(e.format,e.colorSpace),u=i.utils.convert(e.type),l=this.getInternalFormat(e.internalFormat,h,u,e.colorSpace,e.isVideoTexture),c=s.createTexture(),d=this.getGLTextureType(e);i.state.bindTexture(d,c),this.setTextureParameters(d,e),e.isDataArrayTexture||e.isCompressedArrayTexture?s.texStorage3D(s.TEXTURE_2D_ARRAY,r,l,n,o,a):e.isData3DTexture?s.texStorage3D(s.TEXTURE_3D,r,l,n,o,a):e.isVideoTexture||s.texStorage2D(d,r,l,n,o),i.set(e,{textureGPU:c,glTextureType:d,glFormat:h,glType:u,glInternalFormat:l})}copyBufferToTexture(e,t){const{gl:s,backend:i}=this,{textureGPU:r,glTextureType:n,glFormat:o,glType:a}=i.get(t),{width:h,height:u}=t.source.data;s.bindBuffer(s.PIXEL_UNPACK_BUFFER,e),i.state.bindTexture(n,r),s.pixelStorei(s.UNPACK_FLIP_Y_WEBGL,!1),s.pixelStorei(s.UNPACK_PREMULTIPLY_ALPHA_WEBGL,!1),s.texSubImage2D(n,0,0,0,h,u,o,a,0),s.bindBuffer(s.PIXEL_UNPACK_BUFFER,null),i.state.unbindTexture()}updateTexture(e,t){const{gl:s}=this,{width:i,height:r}=t,{textureGPU:n,glTextureType:o,glFormat:a,glType:h,glInternalFormat:u}=this.backend.get(e);if(e.isRenderTargetTexture||void 0===n)return;const l=e=>e.isDataTexture?e.image.data:e instanceof ImageBitmap||e instanceof OffscreenCanvas||e instanceof HTMLImageElement||e instanceof HTMLCanvasElement?e:e.data;if(this.backend.state.bindTexture(o,n),this.setTextureParameters(o,e),e.isCompressedTexture){const i=e.mipmaps,r=t.image;for(let t=0;t0,c=t.renderTarget?t.renderTarget.height:this.backend.gerDrawingBufferSize().y;if(l){const s=0!==o||0!==a;let l,d;if(!0===e.isDepthTexture?(l=i.DEPTH_BUFFER_BIT,d=i.DEPTH_ATTACHMENT,t.stencil&&(l|=i.STENCIL_BUFFER_BIT)):(l=i.COLOR_BUFFER_BIT,d=i.COLOR_ATTACHMENT0),s){const e=this.backend.get(t.renderTarget),s=e.framebuffers[t.getCacheKey()],d=e.msaaFrameBuffer;r.bindFramebuffer(i.DRAW_FRAMEBUFFER,s),r.bindFramebuffer(i.READ_FRAMEBUFFER,d);const p=c-a-u;i.blitFramebuffer(o,p,o+h,p+u,o,p,o+h,p+u,l,i.NEAREST),r.bindFramebuffer(i.READ_FRAMEBUFFER,s),r.bindTexture(i.TEXTURE_2D,n),i.copyTexSubImage2D(i.TEXTURE_2D,0,0,0,o,p,h,u),r.unbindTexture()}else{const e=i.createFramebuffer();r.bindFramebuffer(i.DRAW_FRAMEBUFFER,e),i.framebufferTexture2D(i.DRAW_FRAMEBUFFER,d,i.TEXTURE_2D,n,0),i.blitFramebuffer(0,0,h,u,0,0,h,u,l,i.NEAREST),i.deleteFramebuffer(e)}}else r.bindTexture(i.TEXTURE_2D,n),i.copyTexSubImage2D(i.TEXTURE_2D,0,0,0,o,c-u-a,h,u),r.unbindTexture();e.generateMipmaps&&this.generateMipmaps(e),this.backend._setFramebuffer(t)}setupRenderBufferStorage(e,t){const{gl:s}=this,i=t.renderTarget,{samples:r,depthTexture:n,depthBuffer:o,stencilBuffer:a,width:h,height:u}=i;if(s.bindRenderbuffer(s.RENDERBUFFER,e),o&&!a){let t=s.DEPTH_COMPONENT24;r>0?(n&&n.isDepthTexture&&n.type===s.FLOAT&&(t=s.DEPTH_COMPONENT32F),s.renderbufferStorageMultisample(s.RENDERBUFFER,r,t,h,u)):s.renderbufferStorage(s.RENDERBUFFER,t,h,u),s.framebufferRenderbuffer(s.FRAMEBUFFER,s.DEPTH_ATTACHMENT,s.RENDERBUFFER,e)}else o&&a&&(r>0?s.renderbufferStorageMultisample(s.RENDERBUFFER,r,s.DEPTH24_STENCIL8,h,u):s.renderbufferStorage(s.RENDERBUFFER,s.DEPTH_STENCIL,h,u),s.framebufferRenderbuffer(s.FRAMEBUFFER,s.DEPTH_STENCIL_ATTACHMENT,s.RENDERBUFFER,e))}async copyTextureToBuffer(e,t,s,i,r,n){const{backend:o,gl:a}=this,{textureGPU:h,glFormat:u,glType:l}=this.backend.get(e),c=a.createFramebuffer();a.bindFramebuffer(a.READ_FRAMEBUFFER,c);const d=e.isCubeTexture?a.TEXTURE_CUBE_MAP_POSITIVE_X+n:a.TEXTURE_2D;a.framebufferTexture2D(a.READ_FRAMEBUFFER,a.COLOR_ATTACHMENT0,d,h,0);const p=this._getTypedArrayType(l),m=i*r*this._getBytesPerTexel(l,u),g=a.createBuffer();a.bindBuffer(a.PIXEL_PACK_BUFFER,g),a.bufferData(a.PIXEL_PACK_BUFFER,m,a.STREAM_READ),a.readPixels(t,s,i,r,u,l,0),a.bindBuffer(a.PIXEL_PACK_BUFFER,null),await o.utils._clientWaitAsync();const f=new p(m/p.BYTES_PER_ELEMENT);return a.bindBuffer(a.PIXEL_PACK_BUFFER,g),a.getBufferSubData(a.PIXEL_PACK_BUFFER,0,f),a.bindBuffer(a.PIXEL_PACK_BUFFER,null),a.deleteFramebuffer(c),f}_getTypedArrayType(e){const{gl:t}=this;if(e===t.UNSIGNED_BYTE)return Uint8Array;if(e===t.UNSIGNED_SHORT_4_4_4_4)return Uint16Array;if(e===t.UNSIGNED_SHORT_5_5_5_1)return Uint16Array;if(e===t.UNSIGNED_SHORT_5_6_5)return Uint16Array;if(e===t.UNSIGNED_SHORT)return Uint16Array;if(e===t.UNSIGNED_INT)return Uint32Array;if(e===t.HALF_FLOAT)return Uint16Array;if(e===t.FLOAT)return Float32Array;throw new Error(`Unsupported WebGL type: ${e}`)}_getBytesPerTexel(e,t){const{gl:s}=this;let i=0;return e===s.UNSIGNED_BYTE&&(i=1),e!==s.UNSIGNED_SHORT_4_4_4_4&&e!==s.UNSIGNED_SHORT_5_5_5_1&&e!==s.UNSIGNED_SHORT_5_6_5&&e!==s.UNSIGNED_SHORT&&e!==s.HALF_FLOAT||(i=2),e!==s.UNSIGNED_INT&&e!==s.FLOAT||(i=4),t===s.RGBA?4*i:t===s.RGB?3*i:t===s.ALPHA?i:void 0}}class $P{constructor(e){this.backend=e,this.gl=this.backend.gl,this.availableExtensions=this.gl.getSupportedExtensions(),this.extensions={}}get(e){let t=this.extensions[e];return void 0===t&&(t=this.gl.getExtension(e),this.extensions[e]=t),t}has(e){return this.availableExtensions.includes(e)}}class XP{constructor(e){this.backend=e,this.maxAnisotropy=null}getMaxAnisotropy(){if(null!==this.maxAnisotropy)return this.maxAnisotropy;const e=this.backend.gl,t=this.backend.extensions;if(!0===t.has("EXT_texture_filter_anisotropic")){const s=t.get("EXT_texture_filter_anisotropic");this.maxAnisotropy=e.getParameter(s.MAX_TEXTURE_MAX_ANISOTROPY_EXT)}else this.maxAnisotropy=0;return this.maxAnisotropy}}const YP={WEBGL_multi_draw:"WEBGL_multi_draw",WEBGL_compressed_texture_astc:"texture-compression-astc",WEBGL_compressed_texture_etc:"texture-compression-etc2",WEBGL_compressed_texture_etc1:"texture-compression-etc1",WEBGL_compressed_texture_pvrtc:"texture-compression-pvrtc",WEBKIT_WEBGL_compressed_texture_pvrtc:"texture-compression-pvrtc",WEBGL_compressed_texture_s3tc:"texture-compression-bc",EXT_texture_compression_bptc:"texture-compression-bptc",EXT_disjoint_timer_query_webgl2:"timestamp-query"};class ZP{constructor(e){this.gl=e.gl,this.extensions=e.extensions,this.info=e.renderer.info,this.mode=null,this.index=0,this.type=null,this.object=null}render(e,t){const{gl:s,mode:i,object:r,type:n,info:o,index:a}=this;0!==a?s.drawElements(i,t,n,e):s.drawArrays(i,e,t),o.update(r,t,i,1)}renderInstances(e,t,s){const{gl:i,mode:r,type:n,index:o,object:a,info:h}=this;0!==s&&(0!==o?i.drawElementsInstanced(r,t,n,e,s):i.drawArraysInstanced(r,e,t,s),h.update(a,t,r,s))}renderMultiDraw(e,t,s){const{extensions:i,mode:r,object:n,info:o}=this;if(0===s)return;const a=i.get("WEBGL_multi_draw");if(null===a)for(let i=0;i0)){const e=t.queryQueue.shift();this.initTimestampQuery(e)}}async resolveTimestampAsync(e,t="render"){if(!this.disjoint||!this.trackTimestamp)return;const s=this.get(e);s.gpuQueries||(s.gpuQueries=[]);for(let e=0;e0&&(s.currentOcclusionQueries=s.occlusionQueries,s.currentOcclusionQueryObjects=s.occlusionQueryObjects,s.lastOcclusionObject=null,s.occlusionQueries=new Array(i),s.occlusionQueryObjects=new Array(i),s.occlusionQueryIndex=0)}finishRender(e){const{gl:t,state:s}=this,i=this.get(e),r=i.previousContext,n=e.occlusionQueryCount;n>0&&(n>i.occlusionQueryIndex&&t.endQuery(t.ANY_SAMPLES_PASSED),this.resolveOccludedAsync(e));const o=e.textures;if(null!==o)for(let e=0;e0){const r=i.framebuffers[e.getCacheKey()],n=t.COLOR_BUFFER_BIT,o=i.msaaFrameBuffer,a=e.textures;s.bindFramebuffer(t.READ_FRAMEBUFFER,o),s.bindFramebuffer(t.DRAW_FRAMEBUFFER,r);for(let s=0;s{let o=0;for(let t=0;t0&&e.add(i[t]),s[t]=null,r.deleteQuery(n),o++))}o1?m.renderInstances(y,g,f):m.render(y,g),o.bindVertexArray(null)}needsRenderUpdate(){return!1}getRenderCacheKey(){return""}createDefaultTexture(e){this.textureUtils.createDefaultTexture(e)}createTexture(e,t){this.textureUtils.createTexture(e,t)}updateTexture(e,t){this.textureUtils.updateTexture(e,t)}generateMipmaps(e){this.textureUtils.generateMipmaps(e)}destroyTexture(e){this.textureUtils.destroyTexture(e)}copyTextureToBuffer(e,t,s,i,r,n){return this.textureUtils.copyTextureToBuffer(e,t,s,i,r,n)}createSampler(){}destroySampler(){}createNodeBuilder(e,t){return new RP(e,t)}createProgram(e){const t=this.gl,{stage:s,code:i}=e,r="fragment"===s?t.createShader(t.FRAGMENT_SHADER):t.createShader(t.VERTEX_SHADER);t.shaderSource(r,i),t.compileShader(r),this.set(e,{shaderGPU:r})}destroyProgram(){console.warn("Abstract class.")}createRenderPipeline(e,t){const s=this.gl,i=e.pipeline,{fragmentProgram:r,vertexProgram:n}=i,o=s.createProgram(),a=this.get(r).shaderGPU,h=this.get(n).shaderGPU;if(s.attachShader(o,a),s.attachShader(o,h),s.linkProgram(o),this.set(i,{programGPU:o,fragmentShader:a,vertexShader:h}),null!==t&&this.parallel){const r=new Promise((t=>{const r=this.parallel,n=()=>{s.getProgramParameter(o,r.COMPLETION_STATUS_KHR)?(this._completeCompile(e,i),t()):requestAnimationFrame(n)};n()}));t.push(r)}else this._completeCompile(e,i)}_handleSource(e,t){const s=e.split("\n"),i=[],r=Math.max(t-6,0),n=Math.min(t+6,s.length);for(let e=r;e":" "} ${r}: ${s[e]}`)}return i.join("\n")}_getShaderErrors(e,t,s){const i=e.getShaderParameter(t,e.COMPILE_STATUS),r=e.getShaderInfoLog(t).trim();if(i&&""===r)return"";const n=/ERROR: 0:(\d+)/.exec(r);if(n){const i=parseInt(n[1]);return s.toUpperCase()+"\n\n"+r+"\n\n"+this._handleSource(e.getShaderSource(t),i)}return r}_logProgramError(e,t,s){if(this.renderer.debug.checkShaderErrors){const i=this.gl,r=i.getProgramInfoLog(e).trim();if(!1===i.getProgramParameter(e,i.LINK_STATUS))if("function"==typeof this.renderer.debug.onShaderError)this.renderer.debug.onShaderError(i,e,s,t);else{const n=this._getShaderErrors(i,s,"vertex"),o=this._getShaderErrors(i,t,"fragment");console.error("THREE.WebGLProgram: Shader Error "+i.getError()+" - VALIDATE_STATUS "+i.getProgramParameter(e,i.VALIDATE_STATUS)+"\n\nProgram Info Log: "+r+"\n"+n+"\n"+o)}else""!==r&&console.warn("THREE.WebGLProgram: Program Info Log:",r)}}_completeCompile(e,t){const{state:s,gl:i}=this,r=this.get(t),{programGPU:n,fragmentShader:o,vertexShader:a}=r;!1===i.getProgramParameter(n,i.LINK_STATUS)&&this._logProgramError(n,o,a),s.useProgram(n);const h=e.getBindings();this._setupBindings(h,n),this.set(t,{programGPU:n})}createComputePipeline(e,t){const{state:s,gl:i}=this,r={stage:"fragment",code:"#version 300 es\nprecision highp float;\nvoid main() {}"};this.createProgram(r);const{computeProgram:n}=e,o=i.createProgram(),a=this.get(r).shaderGPU,h=this.get(n).shaderGPU,u=n.transforms,l=[],c=[];for(let e=0;eYP[t]===e)),s=this.extensions;for(let e=0;e0){if(void 0===l){const i=[];l=t.createFramebuffer(),s.bindFramebuffer(t.FRAMEBUFFER,l);const r=[],u=e.textures;for(let s=0;s,\n\t@location( 0 ) vTex : vec2\n};\n\n@vertex\nfn main( @builtin( vertex_index ) vertexIndex : u32 ) -> VarysStruct {\n\n\tvar Varys : VarysStruct;\n\n\tvar pos = array< vec2, 4 >(\n\t\tvec2( -1.0, 1.0 ),\n\t\tvec2( 1.0, 1.0 ),\n\t\tvec2( -1.0, -1.0 ),\n\t\tvec2( 1.0, -1.0 )\n\t);\n\n\tvar tex = array< vec2, 4 >(\n\t\tvec2( 0.0, 0.0 ),\n\t\tvec2( 1.0, 0.0 ),\n\t\tvec2( 0.0, 1.0 ),\n\t\tvec2( 1.0, 1.0 )\n\t);\n\n\tVarys.vTex = tex[ vertexIndex ];\n\tVarys.Position = vec4( pos[ vertexIndex ], 0.0, 1.0 );\n\n\treturn Varys;\n\n}\n"}),this.mipmapFragmentShaderModule=e.createShaderModule({label:"mipmapFragment",code:"\n@group( 0 ) @binding( 0 )\nvar imgSampler : sampler;\n\n@group( 0 ) @binding( 1 )\nvar img : texture_2d;\n\n@fragment\nfn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 {\n\n\treturn textureSample( img, imgSampler, vTex );\n\n}\n"}),this.flipYFragmentShaderModule=e.createShaderModule({label:"flipYFragment",code:"\n@group( 0 ) @binding( 0 )\nvar imgSampler : sampler;\n\n@group( 0 ) @binding( 1 )\nvar img : texture_2d;\n\n@fragment\nfn main( @location( 0 ) vTex : vec2 ) -> @location( 0 ) vec4 {\n\n\treturn textureSample( img, imgSampler, vec2( vTex.x, 1.0 - vTex.y ) );\n\n}\n"})}getTransferPipeline(e){let t=this.transferPipelines[e];return void 0===t&&(t=this.device.createRenderPipeline({label:`mipmap-${e}`,vertex:{module:this.mipmapVertexShaderModule,entryPoint:"main"},fragment:{module:this.mipmapFragmentShaderModule,entryPoint:"main",targets:[{format:e}]},primitive:{topology:CN,stripIndexFormat:HN},layout:"auto"}),this.transferPipelines[e]=t),t}getFlipYPipeline(e){let t=this.flipYPipelines[e];return void 0===t&&(t=this.device.createRenderPipeline({label:`flipY-${e}`,vertex:{module:this.mipmapVertexShaderModule,entryPoint:"main"},fragment:{module:this.flipYFragmentShaderModule,entryPoint:"main",targets:[{format:e}]},primitive:{topology:CN,stripIndexFormat:HN},layout:"auto"}),this.flipYPipelines[e]=t),t}flipY(e,t,s=0){const i=t.format,{width:r,height:n}=t.size,o=this.getTransferPipeline(i),a=this.getFlipYPipeline(i),h=this.device.createTexture({size:{width:r,height:n,depthOrArrayLayers:1},format:i,usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.TEXTURE_BINDING}),u=e.createView({baseMipLevel:0,mipLevelCount:1,dimension:OA,baseArrayLayer:s}),l=h.createView({baseMipLevel:0,mipLevelCount:1,dimension:OA,baseArrayLayer:0}),c=this.device.createCommandEncoder({}),d=(e,t,s)=>{const i=e.getBindGroupLayout(0),r=this.device.createBindGroup({layout:i,entries:[{binding:0,resource:this.flipYSampler},{binding:1,resource:t}]}),n=c.beginRenderPass({colorAttachments:[{view:s,loadOp:VN,storeOp:ON,clearValue:[0,0,0,0]}]});n.setPipeline(e),n.setBindGroup(0,r),n.draw(4,1,0,0),n.end()};d(o,u,l),d(a,l,u),this.device.queue.submit([c.finish()]),h.destroy()}generateMipmaps(e,t,s=0){const i=this.get(e);void 0===i.useCount&&(i.useCount=0,i.layers=[]);const r=i.layers[s]||this._mipmapCreateBundles(e,t,s),n=this.device.createCommandEncoder({});this._mipmapRunBundles(n,r),this.device.queue.submit([n.finish()]),0!==i.useCount&&(i.layers[s]=r),i.useCount++}_mipmapCreateBundles(e,t,s){const i=this.getTransferPipeline(t.format),r=i.getBindGroupLayout(0);let n=e.createView({baseMipLevel:0,mipLevelCount:1,dimension:OA,baseArrayLayer:s});const o=[];for(let a=1;a1&&!e.isMultisampleRenderTargetTexture){const e=Object.assign({},p);e.label=e.label+"-msaa",e.sampleCount=l,i.msaaTexture=s.device.createTexture(e)}i.initialized=!0,i.textureDescriptorGPU=p}destroyTexture(e){const t=this.backend,s=t.get(e);s.texture.destroy(),void 0!==s.msaaTexture&&s.msaaTexture.destroy(),t.delete(e)}destroySampler(e){delete this.backend.get(e).sampler}generateMipmaps(e){const t=this.backend.get(e);if(e.isCubeTexture)for(let e=0;e<6;e++)this._generateMipmaps(t.texture,t.textureDescriptorGPU,e);else{const s=e.image.depth||1;for(let e=0;e1;for(let o=0;o]*\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/i,uF=/([a-z_0-9]+)\s*:\s*([a-z_0-9]+(?:<[\s\S]+?>)?)/gi,lF={f32:"float",i32:"int",u32:"uint",bool:"bool","vec2":"vec2","vec2":"ivec2","vec2":"uvec2","vec2":"bvec2",vec2f:"vec2",vec2i:"ivec2",vec2u:"uvec2",vec2b:"bvec2","vec3":"vec3","vec3":"ivec3","vec3":"uvec3","vec3":"bvec3",vec3f:"vec3",vec3i:"ivec3",vec3u:"uvec3",vec3b:"bvec3","vec4":"vec4","vec4":"ivec4","vec4":"uvec4","vec4":"bvec4",vec4f:"vec4",vec4i:"ivec4",vec4u:"uvec4",vec4b:"bvec4","mat2x2":"mat2",mat2x2f:"mat2","mat3x3":"mat3",mat3x3f:"mat3","mat4x4":"mat4",mat4x4f:"mat4",sampler:"sampler",texture_1d:"texture",texture_2d:"texture",texture_2d_array:"texture",texture_multisampled_2d:"cubeTexture",texture_depth_2d:"depthTexture",texture_3d:"texture3D",texture_cube:"cubeTexture",texture_cube_array:"cubeTexture",texture_storage_1d:"storageTexture",texture_storage_2d:"storageTexture",texture_storage_2d_array:"storageTexture",texture_storage_3d:"storageTexture"};class cF extends FI{constructor(e){const{type:t,inputs:s,name:i,inputsCode:r,blockCode:n,outputType:o}=(e=>{const t=(e=e.trim()).match(hF);if(null!==t&&4===t.length){const s=t[2],i=[];let r=null;for(;null!==(r=uF.exec(s));)i.push({name:r[1],type:r[2]});const n=[];for(let e=0;e "+this.outputType:"";return`fn ${e} ( ${this.inputsCode.trim()} ) ${t}`+this.blockCode}}class dF extends PI{parseFunction(e){return new cF(e)}}const pF=self.GPUShaderStage,mF={vertex:pF?pF.VERTEX:1,fragment:pF?pF.FRAGMENT:2,compute:pF?pF.COMPUTE:4},gF={instance:!0,swizzleAssign:!1,storageBuffer:!0},fF={"^^":"tsl_xor"},yF={float:"f32",int:"i32",uint:"u32",bool:"bool",color:"vec3",vec2:"vec2",ivec2:"vec2",uvec2:"vec2",bvec2:"vec2",vec3:"vec3",ivec3:"vec3",uvec3:"vec3",bvec3:"vec3",vec4:"vec4",ivec4:"vec4",uvec4:"vec4",bvec4:"vec4",mat2:"mat2x2",imat2:"mat2x2",umat2:"mat2x2",bmat2:"mat2x2",mat3:"mat3x3",imat3:"mat3x3",umat3:"mat3x3",bmat3:"mat3x3",mat4:"mat4x4",imat4:"mat4x4",umat4:"mat4x4",bmat4:"mat4x4"},xF={tsl_xor:new vS("fn tsl_xor( a : bool, b : bool ) -> bool { return ( a || b ) && !( a && b ); }"),mod_float:new vS("fn tsl_mod_float( x : f32, y : f32 ) -> f32 { return x - y * floor( x / y ); }"),mod_vec2:new vS("fn tsl_mod_vec2( x : vec2f, y : vec2f ) -> vec2f { return x - y * floor( x / y ); }"),mod_vec3:new vS("fn tsl_mod_vec3( x : vec3f, y : vec3f ) -> vec3f { return x - y * floor( x / y ); }"),mod_vec4:new vS("fn tsl_mod_vec4( x : vec4f, y : vec4f ) -> vec4f { return x - y * floor( x / y ); }"),equals_bool:new vS("fn tsl_equals_bool( a : bool, b : bool ) -> bool { return a == b; }"),equals_bvec2:new vS("fn tsl_equals_bvec2( a : vec2f, b : vec2f ) -> vec2 { return vec2( a.x == b.x, a.y == b.y ); }"),equals_bvec3:new vS("fn tsl_equals_bvec3( a : vec3f, b : vec3f ) -> vec3 { return vec3( a.x == b.x, a.y == b.y, a.z == b.z ); }"),equals_bvec4:new vS("fn tsl_equals_bvec4( a : vec4f, b : vec4f ) -> vec4 { return vec4( a.x == b.x, a.y == b.y, a.z == b.z, a.w == b.w ); }"),repeatWrapping:new vS("\nfn tsl_repeatWrapping( uv : vec2, dimension : vec2 ) -> vec2 {\n\n\tlet uvScaled = vec2( uv * vec2( dimension ) );\n\n\treturn ( ( uvScaled % dimension ) + dimension ) % dimension;\n\n}\n"),biquadraticTexture:new vS("\nfn tsl_biquadraticTexture( map : texture_2d, coord : vec2f, level : i32 ) -> vec4f {\n\n\tlet iRes = vec2i( textureDimensions( map, level ) );\n\tlet res = vec2f( iRes );\n\n\tlet uvScaled = coord * res;\n\tlet uvWrapping = ( ( uvScaled % res ) + res ) % res;\n\n\t// https://www.shadertoy.com/view/WtyXRy\n\n\tlet uv = uvWrapping - 0.5;\n\tlet iuv = floor( uv );\n\tlet f = fract( uv );\n\n\tlet rg1 = textureLoad( map, vec2i( iuv + vec2( 0.5, 0.5 ) ) % iRes, level );\n\tlet rg2 = textureLoad( map, vec2i( iuv + vec2( 1.5, 0.5 ) ) % iRes, level );\n\tlet rg3 = textureLoad( map, vec2i( iuv + vec2( 0.5, 1.5 ) ) % iRes, level );\n\tlet rg4 = textureLoad( map, vec2i( iuv + vec2( 1.5, 1.5 ) ) % iRes, level );\n\n\treturn mix( mix( rg1, rg2, f.x ), mix( rg3, rg4, f.x ), f.y );\n\n}\n")},bF={dFdx:"dpdx",dFdy:"- dpdy",mod_float:"tsl_mod_float",mod_vec2:"tsl_mod_vec2",mod_vec3:"tsl_mod_vec3",mod_vec4:"tsl_mod_vec4",equals_bool:"tsl_equals_bool",equals_bvec2:"tsl_equals_bvec2",equals_bvec3:"tsl_equals_bvec3",equals_bvec4:"tsl_equals_bvec4",inversesqrt:"inverseSqrt",bitcast:"bitcast"};/Windows/g.test(navigator.userAgent)&&(xF.pow_float=new vS("fn tsl_pow_float( a : f32, b : f32 ) -> f32 { return select( -pow( -a, b ), pow( a, b ), a > 0.0 ); }"),xF.pow_vec2=new vS("fn tsl_pow_vec2( a : vec2f, b : vec2f ) -> vec2f { return vec2f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ) ); }",[xF.pow_float]),xF.pow_vec3=new vS("fn tsl_pow_vec3( a : vec3f, b : vec3f ) -> vec3f { return vec3f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ), tsl_pow_float( a.z, b.z ) ); }",[xF.pow_float]),xF.pow_vec4=new vS("fn tsl_pow_vec4( a : vec4f, b : vec4f ) -> vec4f { return vec4f( tsl_pow_float( a.x, b.x ), tsl_pow_float( a.y, b.y ), tsl_pow_float( a.z, b.z ), tsl_pow_float( a.w, b.w ) ); }",[xF.pow_float]),bF.pow_float="tsl_pow_float",bF.pow_vec2="tsl_pow_vec2",bF.pow_vec3="tsl_pow_vec3",bF.pow_vec4="tsl_pow_vec4");let vF="";!0!==/Firefox/g.test(navigator.userAgent)&&(vF+="diagnostic( off, derivative_uniformity );\n");class TF extends xM{constructor(e,t){super(e,t,new dF),this.uniformGroups={},this.builtins={},this.directives={},this.scopedArrays=new Map}needsToWorkingColorSpace(e){return!0===e.isVideoTexture&&e.colorSpace!==Yt}_generateTextureSample(e,t,s,i,r=this.shaderStage){return"fragment"===r?i?`textureSample( ${t}, ${t}_sampler, ${s}, ${i} )`:`textureSample( ${t}, ${t}_sampler, ${s} )`:this.isFilteredTexture(e)?this.generateFilteredTexture(e,t,s):this.generateTextureLod(e,t,s,"0")}_generateVideoSample(e,t,s=this.shaderStage){if("fragment"===s)return`textureSampleBaseClampToEdge( ${e}, ${e}_sampler, vec2( ${t}.x, 1.0 - ${t}.y ) )`;console.error(`WebGPURenderer: THREE.VideoTexture does not support ${s} shader.`)}_generateTextureSampleLevel(e,t,s,i,r,n=this.shaderStage){return"fragment"===n&&!1===this.isUnfilterable(e)?`textureSampleLevel( ${t}, ${t}_sampler, ${s}, ${i} )`:this.isFilteredTexture(e)?this.generateFilteredTexture(e,t,s,i):this.generateTextureLod(e,t,s,i)}generateFilteredTexture(e,t,s,i="0"){return this._include("biquadraticTexture"),`tsl_biquadraticTexture( ${t}, ${s}, i32( ${i} ) )`}generateTextureLod(e,t,s,i="0"){this._include("repeatWrapping");return`textureLoad( ${t}, tsl_repeatWrapping( ${s}, ${!0===e.isMultisampleRenderTargetTexture?`textureDimensions( ${t} )`:`textureDimensions( ${t}, 0 )`} ), i32( ${i} ) )`}generateTextureLoad(e,t,s,i,r="0u"){return i?`textureLoad( ${t}, ${s}, ${i}, ${r} )`:`textureLoad( ${t}, ${s}, ${r} )`}generateTextureStore(e,t,s,i){return`textureStore( ${t}, ${s}, ${i} )`}isUnfilterable(e){return"float"!==this.getComponentTypeFromTexture(e)||!this.isAvailable("float32Filterable")&&!0===e.isDataTexture&&e.type===Ie||!0===e.isMultisampleRenderTargetTexture}generateTexture(e,t,s,i,r=this.shaderStage){let n=null;return n=!0===e.isVideoTexture?this._generateVideoSample(t,s,r):this.isUnfilterable(e)?this.generateTextureLod(e,t,s,"0",i,r):this._generateTextureSample(e,t,s,i,r),n}generateTextureGrad(e,t,s,i,r,n=this.shaderStage){if("fragment"===n)return`textureSampleGrad( ${t}, ${t}_sampler, ${s}, ${i[0]}, ${i[1]} )`;console.error(`WebGPURenderer: THREE.TextureNode.gradient() does not support ${n} shader.`)}generateTextureCompare(e,t,s,i,r,n=this.shaderStage){if("fragment"===n)return`textureSampleCompare( ${t}, ${t}_sampler, ${s}, ${i} )`;console.error(`WebGPURenderer: THREE.DepthTexture.compareFunction() does not support ${n} shader.`)}generateTextureLevel(e,t,s,i,r,n=this.shaderStage){let o=null;return o=!0===e.isVideoTexture?this._generateVideoSample(t,s,n):this._generateTextureSampleLevel(e,t,s,i,r,n),o}generateTextureBias(e,t,s,i,r,n=this.shaderStage){if("fragment"===n)return`textureSampleBias( ${t}, ${t}_sampler, ${s}, ${i} )`;console.error(`WebGPURenderer: THREE.TextureNode.biasNode does not support ${n} shader.`)}getPropertyName(e,t=this.shaderStage){if(!0===e.isNodeVarying&&!0===e.needsInterpolation){if("vertex"===t)return`varyings.${e.name}`}else if(!0===e.isNodeUniform){const t=e.name,s=e.type;return"texture"===s||"cubeTexture"===s||"storageTexture"===s||"texture3D"===s?t:"buffer"===s||"storageBuffer"===s?`NodeBuffer_${e.id}.${t}`:e.groupNode.name+"."+t}return super.getPropertyName(e)}getOutputStructName(){return"output"}_getUniformGroupCount(e){return Object.keys(this.uniforms[e]).length}getFunctionOperator(e){const t=fF[e];return void 0!==t?(this._include(t),t):null}getStorageAccess(e){if(e.isStorageTextureNode)switch(e.access){case RA:return"read";case CA:return"write";default:return"read_write"}else switch(e.access){case NA:return"read_write";case AA:return"read";default:return"write"}}getUniformFromNode(e,t,s,i=null){const r=super.getUniformFromNode(e,t,s,i),n=this.getDataFromNode(e,s,this.globalCache);if(void 0===n.uniformGPU){let i;const o=e.groupNode,a=o.name,h=this.getBindGroupArray(a,s);if("texture"===t||"cubeTexture"===t||"storageTexture"===t||"texture3D"===t){let n=null;if("texture"===t||"storageTexture"===t?n=new _P(r.name,r.node,o,e.access?e.access:null):"cubeTexture"===t?n=new wP(r.name,r.node,o,e.access?e.access:null):"texture3D"===t&&(n=new SP(r.name,r.node,o,e.access?e.access:null)),n.store=!0===e.isStorageTextureNode,n.setVisibility(mF[s]),"fragment"===s&&!1===this.isUnfilterable(e.value)&&!1===n.store){const e=new QP(`${r.name}_sampler`,r.node,o);e.setVisibility(mF[s]),h.push(e,n),i=[e,n]}else h.push(n),i=[n]}else if("buffer"===t||"storageBuffer"===t){const r=new("storageBuffer"===t?sF:fP)(e,o);r.setVisibility(mF[s]),h.push(r),i=r}else{const e=this.uniformGroups[s]||(this.uniformGroups[s]={});let n=e[a];void 0===n&&(n=new bP(a,o),n.setVisibility(mF[s]),e[a]=n,h.push(n)),i=this.getNodeUniform(r,t),n.addUniform(i)}n.uniformGPU=i}return r}getBuiltin(e,t,s,i=this.shaderStage){const r=this.builtins[i]||(this.builtins[i]=new Map);return!1===r.has(e)&&r.set(e,{name:e,property:t,type:s}),t}hasBuiltin(e,t=this.shaderStage){return void 0!==this.builtins[t]&&this.builtins[t].has(e)}getVertexIndex(){return"vertex"===this.shaderStage?this.getBuiltin("vertex_index","vertexIndex","u32","attribute"):"vertexIndex"}buildFunctionCode(e){const t=e.layout,s=this.flowShaderNode(e),i=[];for(const e of t.inputs)i.push(e.name+" : "+this.getType(e.type));let r=`fn ${t.name}( ${i.join(", ")} ) -> ${this.getType(t.type)} {\n${s.vars}\n${s.code}\n`;return s.result&&(r+=`\treturn ${s.result};\n`),r+="\n}\n",r}getInstanceIndex(){return"vertex"===this.shaderStage?this.getBuiltin("instance_index","instanceIndex","u32","attribute"):"instanceIndex"}getInvocationLocalIndex(){return this.getBuiltin("local_invocation_index","invocationLocalIndex","u32","attribute")}getSubgroupSize(){return this.enableSubGroups(),this.getBuiltin("subgroup_size","subgroupSize","u32","attribute")}getInvocationSubgroupIndex(){return this.enableSubGroups(),this.getBuiltin("subgroup_invocation_id","invocationSubgroupIndex","u32","attribute")}getSubgroupIndex(){return this.enableSubGroups(),this.getBuiltin("subgroup_id","subgroupIndex","u32","attribute")}getDrawIndex(){return null}getFrontFacing(){return this.getBuiltin("front_facing","isFront","bool")}getFragCoord(){return this.getBuiltin("position","fragCoord","vec4")+".xy"}getFragDepth(){return"output."+this.getBuiltin("frag_depth","depth","f32","output")}isFlipY(){return!1}enableDirective(e,t=this.shaderStage){(this.directives[t]||(this.directives[t]=new Set)).add(e)}getDirectives(e){const t=[],s=this.directives[e];if(void 0!==s)for(const e of s)t.push(`enable ${e};`);return t.join("\n")}enableSubGroups(){this.enableDirective("subgroups")}enableSubgroupsF16(){this.enableDirective("subgroups-f16")}enableClipDistances(){this.enableDirective("clip_distances")}enableShaderF16(){this.enableDirective("f16")}enableDualSourceBlending(){this.enableDirective("dual_source_blending")}getBuiltins(e){const t=[],s=this.builtins[e];if(void 0!==s)for(const{name:e,property:i,type:r}of s.values())t.push(`@builtin( ${e} ) ${i} : ${r}`);return t.join(",\n\t")}getScopedArray(e,t,s,i){return!1===this.scopedArrays.has(e)&&this.scopedArrays.set(e,{name:e,scope:t,bufferType:s,bufferCount:i}),e}getScopedArrays(e){if("compute"!==e)return;const t=[];for(const{name:e,scope:s,bufferType:i,bufferCount:r}of this.scopedArrays.values()){const n=this.getType(i);t.push(`var<${s}> ${e}: array< ${n}, ${r} >;`)}return t.join("\n")}getAttributes(e){const t=[];if("compute"===e&&(this.getBuiltin("global_invocation_id","id","vec3","attribute"),this.getBuiltin("workgroup_id","workgroupId","vec3","attribute"),this.getBuiltin("local_invocation_id","localId","vec3","attribute"),this.getBuiltin("num_workgroups","numWorkgroups","vec3","attribute"),this.renderer.hasFeature("subgroups")&&(this.enableDirective("subgroups",e),this.getBuiltin("subgroup_size","subgroupSize","u32","attribute"))),"vertex"===e||"compute"===e){const e=this.getBuiltins("attribute");e&&t.push(e);const s=this.getAttributesArray();for(let e=0,i=s.length;e`)}const i=this.getBuiltins("output");return i&&t.push("\t"+i),t.join(",\n")}getStructs(e){const t=[],s=this.structs[e];for(let e=0,i=s.length;e output : ${r};\n\n`)}return t.join("\n\n")}getVar(e,t){return`var ${t} : ${this.getType(e)}`}getVars(e){const t=[],s=this.vars[e];if(void 0!==s)for(const e of s)t.push(`\t${this.getVar(e.type,e.name)};`);return`\n${t.join("\n")}\n`}getVaryings(e){const t=[];if("vertex"===e&&this.getBuiltin("position","Vertex","vec4","vertex"),"vertex"===e||"fragment"===e){const s=this.varyings,i=this.vars[e];for(let r=0;r";else if(!0===t.isDataArrayTexture||!0===t.isCompressedArrayTexture)i="texture_2d_array";else if(!0===t.isDepthTexture)i=`texture_depth${n}_2d`;else if(!0===t.isVideoTexture)i="texture_external";else if(!0===t.isData3DTexture)i="texture_3d";else if(!0===r.node.isStorageTextureNode){i=`texture_storage_2d<${aF(t)}, ${this.getStorageAccess(r.node)}>`}else{i=`texture${n}_2d<${this.getComponentTypeFromTexture(t).charAt(0)}32>`}s.push(`@binding( ${o.binding++} ) @group( ${o.group} ) var ${r.name} : ${i};`)}else if("buffer"===r.type||"storageBuffer"===r.type){const e=r.node,t=this.getType(e.bufferType),s=e.bufferCount,n=s>0?", "+s:"",a=e.isAtomic?`atomic<${t}>`:`${t}`,h=`\t${r.name} : array< ${a}${n} >\n`,u=e.isStorageBufferNode?`storage, ${this.getStorageAccess(e)}`:"uniform";i.push(this._getWGSLStructBinding("NodeBuffer_"+e.id,h,u,o.binding++,o.group))}else{const e=this.getType(this.getVectorType(r.type)),t=r.groupNode.name;(n[t]||(n[t]={index:o.binding++,id:o.group,snippets:[]})).snippets.push(`\t${r.name} : ${e}`)}}for(const e in n){const t=n[e];r.push(this._getWGSLStructBinding(e,t.snippets.join(",\n"),"uniform",t.index,t.id))}let o=s.join("\n");return o+=i.join("\n"),o+=r.join("\n"),o}buildCode(){const e=null!==this.material?{fragment:{},vertex:{}}:{compute:{}};this.sortBindingGroups();for(const t in e){const s=e[t];s.uniforms=this.getUniforms(t),s.attributes=this.getAttributes(t),s.varyings=this.getVaryings(t),s.structs=this.getStructs(t),s.vars=this.getVars(t),s.codes=this.getCodes(t),s.directives=this.getDirectives(t),s.scopedArrays=this.getScopedArrays(t);let i="// code\n\n";i+=this.flowCode[t];const r=this.flowNodes[t],n=r[r.length-1],o=n.outputNode,a=void 0!==o&&!0===o.isOutputStructNode;for(const e of r){const r=this.getFlowData(e),h=e.name;if(h&&(i.length>0&&(i+="\n"),i+=`\t// flow -> ${h}\n\t`),i+=`${r.code}\n\t`,e===n&&"compute"!==t)if(i+="// result\n\n\t","vertex"===t)i+=`varyings.Vertex = ${r.result};`;else if("fragment"===t)if(a)s.returnType=o.nodeType,i+=`return ${r.result};`;else{let e="\t@location(0) color: vec4";const t=this.getBuiltins("output");t&&(e+=",\n\t"+t),s.returnType="OutputStruct",s.structs+=this._getWGSLStruct("OutputStruct",e),s.structs+="\nvar output : OutputStruct;\n\n",i+=`output.color = ${r.result};\n\n\treturn output;`}}s.flow=i}null!==this.material?(this.vertexShader=this._getWGSLVertexCode(e.vertex),this.fragmentShader=this._getWGSLFragmentCode(e.fragment)):this.computeShader=this._getWGSLComputeCode(e.compute,(this.object.workgroupSize||[64]).join(", "))}getMethod(e,t=null){let s;return null!==t&&(s=this._getWGSLMethod(e+"_"+t)),void 0===s&&(s=this._getWGSLMethod(e)),s||e}getType(e){return yF[e]||e}isAvailable(e){let t=gF[e];return void 0===t&&("float32Filterable"===e&&(t=this.renderer.hasFeature("float32-filterable")),gF[e]=t),t}_getWGSLMethod(e){return void 0!==xF[e]&&this._include(e),bF[e]}_include(e){const t=xF[e];return t.build(this),null!==this.currentFunctionNode&&this.currentFunctionNode.includes.push(t),t}_getWGSLVertexCode(e){return`${this.getSignature()}\n// directives\n${e.directives}\n\n// uniforms\n${e.uniforms}\n\n// varyings\n${e.varyings}\nvar varyings : VaryingsStruct;\n\n// codes\n${e.codes}\n\n@vertex\nfn main( ${e.attributes} ) -> VaryingsStruct {\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n\treturn varyings;\n\n}\n`}_getWGSLFragmentCode(e){return`${this.getSignature()}\n// global\n${vF}\n\n// uniforms\n${e.uniforms}\n\n// structs\n${e.structs}\n\n// codes\n${e.codes}\n\n@fragment\nfn main( ${e.varyings} ) -> ${e.returnType} {\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n}\n`}_getWGSLComputeCode(e,t){return`${this.getSignature()}\n// directives\n${e.directives}\n\n// system\nvar instanceIndex : u32;\n\n// locals\n${e.scopedArrays}\n\n// uniforms\n${e.uniforms}\n\n// codes\n${e.codes}\n\n@compute @workgroup_size( ${t} )\nfn main( ${e.attributes} ) {\n\n\t// system\n\tinstanceIndex = id.x + id.y * numWorkgroups.x * u32(${t}) + id.z * numWorkgroups.x * numWorkgroups.y * u32(${t});\n\n\t// vars\n\t${e.vars}\n\n\t// flow\n\t${e.flow}\n\n}\n`}_getWGSLStruct(e,t){return`\nstruct ${e} {\n${t}\n};`}_getWGSLStructBinding(e,t,s,i=0,r=0){const n=e+"Struct";return`${this._getWGSLStruct(n,t)}\n@binding( ${i} ) @group( ${r} )\nvar<${s}> ${e} : ${n};`}}class _F{constructor(e){this.backend=e}getCurrentDepthStencilFormat(e){let t;return null!==e.depthTexture?t=this.getTextureFormatGPU(e.depthTexture):e.depth&&e.stencil?t=qN.Depth24PlusStencil8:e.depth&&(t=qN.Depth24Plus),t}getTextureFormatGPU(e){return this.backend.get(e).format}getCurrentColorFormat(e){let t;return t=null!==e.textures?this.getTextureFormatGPU(e.textures[0]):this.getPreferredCanvasFormat(),t}getCurrentColorSpace(e){return null!==e.textures?e.textures[0].colorSpace:this.backend.renderer.outputColorSpace}getPrimitiveTopology(e,t){return e.isPoints?SN:e.isLineSegments||e.isMesh&&!0===t.wireframe?MN:e.isLine?NN:e.isMesh?AN:void 0}getSampleCount(e){let t=1;return e>1&&(t=Math.pow(2,Math.floor(Math.log2(e))),2===t&&(t=4)),t}getSampleCountRenderContext(e){return null!==e.textures?this.getSampleCount(e.sampleCount):this.getSampleCount(this.backend.renderer.samples)}getPreferredCanvasFormat(){return navigator.userAgent.includes("Quest")?qN.BGRA8Unorm:navigator.gpu.getPreferredCanvasFormat()}}const wF=new Map([[Int8Array,["sint8","snorm8"]],[Uint8Array,["uint8","unorm8"]],[Int16Array,["sint16","snorm16"]],[Uint16Array,["uint16","unorm16"]],[Int32Array,["sint32","snorm32"]],[Uint32Array,["uint32","unorm32"]],[Float32Array,["float32"]]]),SF=new Map([[xn,["float16"]]]),MF=new Map([[Int32Array,"sint32"],[Int16Array,"sint32"],[Uint32Array,"uint32"],[Uint16Array,"uint32"],[Float32Array,"float32"]]);class NF{constructor(e){this.backend=e}createAttribute(e,t){const s=this._getBufferAttribute(e),i=this.backend,r=i.get(s);let n=r.buffer;if(void 0===n){const o=i.device;let a=s.array;if(!1===e.normalized&&(a.constructor===Int16Array||a.constructor===Uint16Array)){const e=new Uint32Array(a.length);for(let t=0;t1},layout:u.createPipelineLayout({bindGroupLayouts:d})};if(null===t)c.pipeline=u.createRenderPipeline(M);else{const e=new Promise((e=>{u.createRenderPipelineAsync(M).then((t=>{c.pipeline=t,e()}))}));t.push(e)}}createBundleEncoder(e){const t=this.backend,{utils:s,device:i}=t,r=s.getCurrentDepthStencilFormat(e),n={label:"renderBundleEncoder",colorFormats:[s.getCurrentColorFormat(e)],depthStencilFormat:r,sampleCount:this._getSampleCount(e)};return i.createRenderBundleEncoder(n)}createComputePipeline(e,t){const s=this.backend,i=s.device,r=s.get(e.computeProgram).module,n=s.get(e),o=[];for(const e of t){const t=s.get(e);o.push(t.layout)}n.pipeline=i.createComputePipeline({compute:r,layout:i.createPipelineLayout({bindGroupLayouts:o})})}_getBlending(e){let t,s;const i=e.blending,r=e.blendSrc,n=e.blendDst,o=e.blendEquation;if(5===i){const i=null!==e.blendSrcAlpha?e.blendSrcAlpha:r,a=null!==e.blendDstAlpha?e.blendDstAlpha:n,h=null!==e.blendEquationAlpha?e.blendEquationAlpha:o;t={srcFactor:this._getBlendFactor(r),dstFactor:this._getBlendFactor(n),operation:this._getBlendOperation(o)},s={srcFactor:this._getBlendFactor(i),dstFactor:this._getBlendFactor(a),operation:this._getBlendOperation(h)}}else{const r=(e,i,r,n)=>{t={srcFactor:e,dstFactor:i,operation:cA},s={srcFactor:r,dstFactor:n,operation:cA}};if(e.premultipliedAlpha)switch(i){case 1:r(QN,iA,QN,iA);break;case 2:r(QN,QN,QN,QN);break;case 3:r(KN,tA,KN,QN);break;case 4:r(KN,eA,KN,sA)}else switch(i){case 1:r(sA,iA,QN,iA);break;case 2:r(sA,QN,sA,QN);break;case 3:r(KN,tA,KN,QN);break;case 4:r(KN,eA,KN,eA)}}if(void 0!==t&&void 0!==s)return{color:t,alpha:s};console.error("THREE.WebGPURenderer: Invalid blending: ",i)}_getBlendFactor(e){let t;switch(e){case 200:t=KN;break;case 201:t=QN;break;case 202:t=eA;break;case 203:t=tA;break;case R:t=sA;break;case E:t=iA;break;case 208:t=rA;break;case 209:t=nA;break;case 206:t=oA;break;case 207:t=aA;break;case 210:t=hA;break;case 211:t=uA;break;case 212:t=lA;break;default:console.error("THREE.WebGPURenderer: Blend factor not supported.",e)}return t}_getStencilCompare(e){let t;const s=e.stencilFunc;switch(s){case 512:t=RN;break;case bs:t=UN;break;case 513:t=EN;break;case 515:t=IN;break;case 514:t=BN;break;case 518:t=zN;break;case 516:t=PN;break;case 517:t=FN;break;default:console.error("THREE.WebGPURenderer: Invalid stencil function.",s)}return t}_getStencilOperation(e){let t;switch(e){case ns:t=xA;break;case 0:t=bA;break;case 7681:t=vA;break;case 5386:t=TA;break;case 7682:t=_A;break;case 7683:t=wA;break;case 34055:t=SA;break;case 34056:t=MA;break;default:console.error("THREE.WebGPURenderer: Invalid stencil operation.",t)}return t}_getBlendOperation(e){let t;switch(e){case v:t=cA;break;case 101:t=dA;break;case 102:t=pA;break;case 103:t=mA;break;case 104:t=gA;break;default:console.error("THREE.WebGPUPipelineUtils: Blend equation not supported.",e)}return t}_getPrimitiveState(e,t,s){const i={},r=this.backend.utils;switch(i.topology=r.getPrimitiveTopology(e,s),null!==t.index&&!0===e.isLine&&!0!==e.isLineSegments&&(i.stripIndexFormat=t.index.array instanceof Uint16Array?jN:HN),s.side){case c:i.frontFace=DN,i.cullMode=WN;break;case d:i.frontFace=DN,i.cullMode=GN;break;case 2:i.frontFace=DN,i.cullMode=kN;break;default:console.error("THREE.WebGPUPipelineUtils: Unknown material.side value.",s.side)}return i}_getColorWriteMask(e){return!0===e.colorWrite?yA:fA}_getDepthCompare(e){let t;if(!1===e.depthTest)t=UN;else{const s=e.depthFunc;switch(s){case 0:t=RN;break;case 1:t=UN;break;case 2:t=EN;break;case 3:t=IN;break;case 4:t=BN;break;case 5:t=zN;break;case 6:t=PN;break;case 7:t=FN;break;default:console.error("THREE.WebGPUPipelineUtils: Invalid depth function.",s)}}return t}}class RF extends PP{constructor(e={}){super(e),this.isWebGPUBackend=!0,this.parameters.alpha=void 0===e.alpha||e.alpha,this.parameters.requiredLimits=void 0===e.requiredLimits?{}:e.requiredLimits,this.trackTimestamp=!0===e.trackTimestamp,this.device=null,this.context=null,this.colorBuffer=null,this.defaultRenderPassdescriptor=null,this.utils=new _F(this),this.attributeUtils=new NF(this),this.bindingUtils=new AF(this),this.pipelineUtils=new CF(this),this.textureUtils=new oF(this),this.occludedResolveCache=new Map}async init(e){await super.init(e);const t=this.parameters;let s;if(void 0===t.device){const e={powerPreference:t.powerPreference},i=await navigator.gpu.requestAdapter(e);if(null===i)throw new Error("WebGPUBackend: Unable to create WebGPU adapter.");const r=Object.values(jA),n=[];for(const e of r)i.features.has(e)&&n.push(e);const o={requiredFeatures:n,requiredLimits:t.requiredLimits};s=await i.requestDevice(o)}else s=t.device;const i=void 0!==t.context?t.context:e.domElement.getContext("webgpu");this.device=s,this.context=i;const r=t.alpha?"premultiplied":"opaque";this.trackTimestamp=this.trackTimestamp&&this.hasFeature(jA.TimestampQuery),this.context.configure({device:this.device,format:this.utils.getPreferredCanvasFormat(),usage:GPUTextureUsage.RENDER_ATTACHMENT|GPUTextureUsage.COPY_SRC,alphaMode:r}),this.updateSize()}get coordinateSystem(){return Ds}async getArrayBufferAsync(e){return await this.attributeUtils.getArrayBufferAsync(e)}getContext(){return this.context}_getDefaultRenderPassDescriptor(){let e=this.defaultRenderPassdescriptor;if(null===e){const t=this.renderer;e={colorAttachments:[{view:null}],depthStencilAttachment:{view:this.textureUtils.getDepthBuffer(t.depth,t.stencil).createView()}};const s=e.colorAttachments[0];this.renderer.samples>0?s.view=this.colorBuffer.createView():s.resolveTarget=void 0,this.defaultRenderPassdescriptor=e}const t=e.colorAttachments[0];return this.renderer.samples>0?t.resolveTarget=this.context.getCurrentTexture().createView():t.view=this.context.getCurrentTexture().createView(),e}_getRenderPassDescriptor(e){const t=e.renderTarget,s=this.get(t);let i=s.descriptors;if(void 0===i||s.width!==t.width||s.height!==t.height||s.activeMipmapLevel!==t.activeMipmapLevel||s.samples!==t.samples){i={},s.descriptors=i;const e=()=>{t.removeEventListener("dispose",e),this.delete(t)};t.addEventListener("dispose",e)}const r=e.getCacheKey();let n=i[r];if(void 0===n){const o=e.textures,a=[];for(let t=0;t0&&(t.currentOcclusionQuerySet&&t.currentOcclusionQuerySet.destroy(),t.currentOcclusionQueryBuffer&&t.currentOcclusionQueryBuffer.destroy(),t.currentOcclusionQuerySet=t.occlusionQuerySet,t.currentOcclusionQueryBuffer=t.occlusionQueryBuffer,t.currentOcclusionQueryObjects=t.occlusionQueryObjects,r=s.createQuerySet({type:"occlusion",count:i}),t.occlusionQuerySet=r,t.occlusionQueryIndex=0,t.occlusionQueryObjects=new Array(i),t.lastOcclusionObject=null),n=null===e.textures?this._getDefaultRenderPassDescriptor():this._getRenderPassDescriptor(e),this.initTimestampQuery(e,n),n.occlusionQuerySet=r;const o=n.depthStencilAttachment;if(null!==e.textures){const t=n.colorAttachments;for(let s=0;s0&&t.currentPass.executeBundles(t.renderBundles),s>t.occlusionQueryIndex&&t.currentPass.endOcclusionQuery(),t.currentPass.end(),s>0){const i=8*s;let r=this.occludedResolveCache.get(i);void 0===r&&(r=this.device.createBuffer({size:i,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),this.occludedResolveCache.set(i,r));const n=this.device.createBuffer({size:i,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ});t.encoder.resolveQuerySet(t.occlusionQuerySet,0,s,r,0),t.encoder.copyBufferToBuffer(r,0,n,0,i),t.occlusionQueryBuffer=n,this.resolveOccludedAsync(e)}if(this.prepareTimestampBuffer(e,t.encoder),this.device.queue.submit([t.encoder.finish()]),null!==e.textures){const t=e.textures;for(let e=0;eo?(h.x=Math.min(t.dispatchCount,o),h.y=Math.ceil(t.dispatchCount/o)):h.x=t.dispatchCount,r.dispatchWorkgroups(h.x,h.y,h.z)}finishCompute(e){const t=this.get(e);t.passEncoderGPU.end(),this.prepareTimestampBuffer(e,t.cmdEncoderGPU),this.device.queue.submit([t.cmdEncoderGPU.finish()])}draw(e,t){const{object:s,context:i,pipeline:r}=e,n=e.getBindings(),o=this.get(i),a=this.get(r).pipeline,h=o.currentSets,u=o.currentPass,l=e.getDrawParameters();if(null===l)return;h.pipeline!==a&&(u.setPipeline(a),h.pipeline=a);const c=h.bindingGroups;for(let e=0,t=n.length;e1?0:s;u.drawIndexed(t[s],i,e[s]/n,0,o)}}else if(!0===p){const{vertexCount:e,instanceCount:i,firstVertex:r}=l;u.drawIndexed(e,i,r,0,0),t.update(s,e,i)}else{const{vertexCount:e,instanceCount:i,firstVertex:r}=l;u.draw(e,i,r,0),t.update(s,e,i)}}needsRenderUpdate(e){const t=this.get(e),{object:s,material:i}=e,r=this.utils,n=r.getSampleCountRenderContext(e.context),o=r.getCurrentColorSpace(e.context),a=r.getCurrentColorFormat(e.context),h=r.getCurrentDepthStencilFormat(e.context),u=r.getPrimitiveTopology(s,i);let l=!1;return t.material===i&&t.materialVersion===i.version&&t.transparent===i.transparent&&t.blending===i.blending&&t.premultipliedAlpha===i.premultipliedAlpha&&t.blendSrc===i.blendSrc&&t.blendDst===i.blendDst&&t.blendEquation===i.blendEquation&&t.blendSrcAlpha===i.blendSrcAlpha&&t.blendDstAlpha===i.blendDstAlpha&&t.blendEquationAlpha===i.blendEquationAlpha&&t.colorWrite===i.colorWrite&&t.depthWrite===i.depthWrite&&t.depthTest===i.depthTest&&t.depthFunc===i.depthFunc&&t.stencilWrite===i.stencilWrite&&t.stencilFunc===i.stencilFunc&&t.stencilFail===i.stencilFail&&t.stencilZFail===i.stencilZFail&&t.stencilZPass===i.stencilZPass&&t.stencilFuncMask===i.stencilFuncMask&&t.stencilWriteMask===i.stencilWriteMask&&t.side===i.side&&t.alphaToCoverage===i.alphaToCoverage&&t.sampleCount===n&&t.colorSpace===o&&t.colorFormat===a&&t.depthStencilFormat===h&&t.primitiveTopology===u&&t.clippingContextCacheKey===e.clippingContext.cacheKey||(t.material=i,t.materialVersion=i.version,t.transparent=i.transparent,t.blending=i.blending,t.premultipliedAlpha=i.premultipliedAlpha,t.blendSrc=i.blendSrc,t.blendDst=i.blendDst,t.blendEquation=i.blendEquation,t.blendSrcAlpha=i.blendSrcAlpha,t.blendDstAlpha=i.blendDstAlpha,t.blendEquationAlpha=i.blendEquationAlpha,t.colorWrite=i.colorWrite,t.depthWrite=i.depthWrite,t.depthTest=i.depthTest,t.depthFunc=i.depthFunc,t.stencilWrite=i.stencilWrite,t.stencilFunc=i.stencilFunc,t.stencilFail=i.stencilFail,t.stencilZFail=i.stencilZFail,t.stencilZPass=i.stencilZPass,t.stencilFuncMask=i.stencilFuncMask,t.stencilWriteMask=i.stencilWriteMask,t.side=i.side,t.alphaToCoverage=i.alphaToCoverage,t.sampleCount=n,t.colorSpace=o,t.colorFormat=a,t.depthStencilFormat=h,t.primitiveTopology=u,t.clippingContextCacheKey=e.clippingContext.cacheKey,l=!0),l}getRenderCacheKey(e){const{object:t,material:s}=e,i=this.utils,r=e.context;return[s.transparent,s.blending,s.premultipliedAlpha,s.blendSrc,s.blendDst,s.blendEquation,s.blendSrcAlpha,s.blendDstAlpha,s.blendEquationAlpha,s.colorWrite,s.depthWrite,s.depthTest,s.depthFunc,s.stencilWrite,s.stencilFunc,s.stencilFail,s.stencilZFail,s.stencilZPass,s.stencilFuncMask,s.stencilWriteMask,s.side,i.getSampleCountRenderContext(r),i.getCurrentColorSpace(r),i.getCurrentColorFormat(r),i.getCurrentDepthStencilFormat(r),i.getPrimitiveTopology(t,s),e.clippingContext.cacheKey].join()}createSampler(e){this.textureUtils.createSampler(e)}destroySampler(e){this.textureUtils.destroySampler(e)}createDefaultTexture(e){this.textureUtils.createDefaultTexture(e)}createTexture(e,t){this.textureUtils.createTexture(e,t)}updateTexture(e,t){this.textureUtils.updateTexture(e,t)}generateMipmaps(e){this.textureUtils.generateMipmaps(e)}destroyTexture(e){this.textureUtils.destroyTexture(e)}copyTextureToBuffer(e,t,s,i,r,n){return this.textureUtils.copyTextureToBuffer(e,t,s,i,r,n)}initTimestampQuery(e,t){if(!this.trackTimestamp)return;const s=this.get(e);if(!s.timeStampQuerySet){const e=this.device.createQuerySet({type:"timestamp",count:2}),i={querySet:e,beginningOfPassWriteIndex:0,endOfPassWriteIndex:1};Object.assign(t,{timestampWrites:i}),s.timeStampQuerySet=e}}prepareTimestampBuffer(e,t){if(!this.trackTimestamp)return;const s=this.get(e),i=2*BigInt64Array.BYTES_PER_ELEMENT;void 0===s.currentTimestampQueryBuffers&&(s.currentTimestampQueryBuffers={resolveBuffer:this.device.createBuffer({label:"timestamp resolve buffer",size:i,usage:GPUBufferUsage.QUERY_RESOLVE|GPUBufferUsage.COPY_SRC}),resultBuffer:this.device.createBuffer({label:"timestamp result buffer",size:i,usage:GPUBufferUsage.COPY_DST|GPUBufferUsage.MAP_READ}),isMappingPending:!1});const{resolveBuffer:r,resultBuffer:n,isMappingPending:o}=s.currentTimestampQueryBuffers;!0!==o&&(t.resolveQuerySet(s.timeStampQuerySet,0,2,r,0),t.copyBufferToBuffer(r,0,n,0,i))}async resolveTimestampAsync(e,t="render"){if(!this.trackTimestamp)return;const s=this.get(e);if(void 0===s.currentTimestampQueryBuffers)return;const{resultBuffer:i,isMappingPending:r}=s.currentTimestampQueryBuffers;!0!==r&&(s.currentTimestampQueryBuffers.isMappingPending=!0,i.mapAsync(GPUMapMode.READ).then((()=>{const e=new BigUint64Array(i.getMappedRange()),r=Number(e[1]-e[0])/1e6;this.renderer.info.updateTimestamp(t,r),i.unmap(),s.currentTimestampQueryBuffers.isMappingPending=!1})))}createNodeBuilder(e,t){return new TF(e,t)}createProgram(e){this.get(e).module={module:this.device.createShaderModule({code:e.code,label:e.stage}),entryPoint:"main"}}destroyProgram(e){this.delete(e)}createRenderPipeline(e,t){this.pipelineUtils.createRenderPipeline(e,t)}createComputePipeline(e,t){this.pipelineUtils.createComputePipeline(e,t)}beginBundle(e){const t=this.get(e);t._currentPass=t.currentPass,t._currentSets=t.currentSets,t.currentSets={attributes:{},bindingGroups:[],pipeline:null,index:null},t.currentPass=this.pipelineUtils.createBundleEncoder(e)}finishBundle(e,t){const s=this.get(e),i=s.currentPass.finish();this.get(t).bundleGPU=i,s.currentSets=s._currentSets,s.currentPass=s._currentPass}addBundle(e,t){this.get(e).renderBundles.push(this.get(t).bundleGPU)}createBindings(e){this.bindingUtils.createBindings(e)}updateBindings(e){this.bindingUtils.createBindings(e)}updateBinding(e){this.bindingUtils.updateBinding(e)}createIndexAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.INDEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}createStorageAttribute(e){this.attributeUtils.createAttribute(e,GPUBufferUsage.STORAGE|GPUBufferUsage.VERTEX|GPUBufferUsage.COPY_SRC|GPUBufferUsage.COPY_DST)}updateAttribute(e){this.attributeUtils.updateAttribute(e)}destroyAttribute(e){this.attributeUtils.destroyAttribute(e)}updateSize(){this.colorBuffer=this.textureUtils.getColorBuffer(),this.defaultRenderPassdescriptor=null}getMaxAnisotropy(){return 16}hasFeature(e){return this.device.features.has(e)}copyTextureToTexture(e,t,s=null,i=null,r=0){let n=0,o=0,a=0,h=0,u=0,l=0,c=e.image.width,d=e.image.height;null!==s&&(h=s.x,u=s.y,l=s.z||0,c=s.width,d=s.height),null!==i&&(n=i.x,o=i.y,a=i.z||0);const p=this.device.createCommandEncoder({label:"copyTextureToTexture_"+e.id+"_"+t.id}),m=this.get(e).texture,g=this.get(t).texture;p.copyTextureToTexture({texture:m,mipLevel:r,origin:{x:h,y:u,z:l}},{texture:g,mipLevel:r,origin:{x:n,y:o,z:a}},[c,d,1]),this.device.queue.submit([p.finish()])}copyFramebufferToTexture(e,t,s){const i=this.get(t),{encoder:r,descriptor:n}=i;let o=null;o=t.renderTarget?e.isDepthTexture?this.get(t.depthTexture).texture:this.get(t.textures[0]).texture:e.isDepthTexture?this.textureUtils.getDepthBuffer(t.depth,t.stencil):this.context.getCurrentTexture();const a=this.get(e).texture;if(o.format===a.format){i.currentPass.end(),r.copyTextureToTexture({texture:o,origin:{x:s.x,y:s.y,z:0}},{texture:a},[s.z,s.w]),e.generateMipmaps&&this.textureUtils.generateMipmaps(e);for(let e=0;e(console.warn("THREE.WebGPURenderer: WebGPU is not available, running under WebGL2 backend."),new JP(e)));super(new t(e),e),this.nodes.library=new BF,this.isWebGPURenderer=!0}}const PF=new pT,FF=new dN(PF);class zF{constructor(e,t=Xp(0,0,1,1)){this.renderer=e,this.outputNode=t,this.outputColorTransform=!0,this.needsUpdate=!0,PF.name="PostProcessing"}render(){this.update();const e=this.renderer,t=e.toneMapping,s=e.outputColorSpace;e.toneMapping=0,e.outputColorSpace=Jt,FF.render(e),e.toneMapping=t,e.outputColorSpace=s}update(){if(!0===this.needsUpdate){const e=this.renderer,t=e.toneMapping,s=e.outputColorSpace;FF.material.fragmentNode=!0===this.outputColorTransform?Ty(this.outputNode,t,s):this.outputNode.context({toneMapping:t,outputColorSpace:s}),FF.material.needsUpdate=!0,this.needsUpdate=!1}}async renderAsync(){this.update();const e=this.renderer,t=e.toneMapping,s=e.outputColorSpace;e.toneMapping=0,e.outputColorSpace=Jt,await FF.renderAsync(e),e.toneMapping=t,e.outputColorSpace=s}}class UF extends vi{constructor(e=1,t=1){super(),this.image={width:e,height:t},this.magFilter=Te,this.minFilter=Te,this.isStorageTexture=!0}}class OF extends ln{constructor(e,t,s=Float32Array){!1===ArrayBuffer.isView(e)&&(e=new s(e*t)),super(e,t),this.isStorageBufferAttribute=!0}}class LF extends Do{constructor(e,t,s=Float32Array){!1===ArrayBuffer.isView(e)&&(e=new s(e*t)),super(e,t),this.isStorageInstancedBufferAttribute=!0}}class VF extends tl{constructor(e){super(e),this.textures={},this.nodes={}}load(e,t,s,i){const r=new rl(this.manager);r.setPath(this.path),r.setRequestHeader(this.requestHeader),r.setWithCredentials(this.withCredentials),r.load(e,(s=>{try{t(this.parse(JSON.parse(s)))}catch(t){i?i(t):console.error(t),this.manager.itemError(e)}}),s,i)}parseNodes(e){const t={};if(void 0!==e){for(const s of e){const{uuid:e,type:i}=s;t[e]=this.createNodeFromType(i),t[e].uuid=e}const s={nodes:t,textures:this.textures};for(const i of e){i.meta=s;t[i.uuid].deserialize(i),delete i.meta}}return t}parse(e){const t=this.createNodeFromType(e.type);t.uuid=e.uuid;const s={nodes:this.parseNodes(e.nodes),textures:this.textures};return e.meta=s,t.deserialize(e),delete e.meta,t}setTextures(e){return this.textures=e,this}setNodes(e){return this.nodes=e,this}createNodeFromType(e){return void 0===this.nodes[e]?(console.error("THREE.NodeLoader: Node type not found:",e),Up()):Sp(new this.nodes[e])}}class DF extends Bl{constructor(e){super(e),this.nodes={},this.nodeMaterials={}}parse(e){const t=super.parse(e),s=this.nodes,i=e.inputNodes;for(const e in i){const r=i[e];t[e]=s[r]}return t}setNodes(e){return this.nodes=e,this}setNodeMaterials(e){return this.nodeMaterials=e,this}createMaterialFromType(e){const t=this.nodeMaterials[e];return void 0!==t?new t:super.createMaterialFromType(e)}}class kF extends zl{constructor(e){super(e),this.nodes={},this.nodeMaterials={},this._nodesJSON=null}setNodes(e){return this.nodes=e,this}setNodeMaterials(e){return this.nodeMaterials=e,this}parse(e,t){this._nodesJSON=e.nodes;const s=super.parse(e,t);return this._nodesJSON=null,s}parseNodes(e,t){if(void 0!==e){const s=new VF;return s.setNodes(this.nodes),s.setTextures(t),s.parseNodes(e)}return{}}parseMaterials(e,t){const s={};if(void 0!==e){const i=this.parseNodes(this._nodesJSON,t),r=new DF;r.setTextures(t),r.setNodes(i),r.setNodeMaterials(this.nodeMaterials);for(let t=0,i=e.length;t[method:Float getVolume]()

[method:this play]( delay )

+ delay (optional) - The delay, in seconds, at which the audio should start playing.
If [page:Audio.hasPlaybackControl hasPlaybackControl] is true, starts playback.

@@ -244,8 +245,9 @@

[method:this setPlaybackRate]( [param:Float value] )

[method:this setVolume]( [param:Float value] )

Set the volume.

-

[method:this stop]()

+

[method:this stop]( delay )

+ delay (optional) - The delay, in seconds, at which the audio should stop playing.
If [page:Audio.hasPlaybackControl hasPlaybackControl] is enabled, stops playback.

diff --git a/docs/api/en/materials/LineBasicMaterial.html b/docs/api/en/materials/LineBasicMaterial.html index 8efaf0b1be3fd4..3f24c3b601a688 100644 --- a/docs/api/en/materials/LineBasicMaterial.html +++ b/docs/api/en/materials/LineBasicMaterial.html @@ -69,7 +69,9 @@

[property:Float linewidth]

Due to limitations of the [link:https://www.khronos.org/registry/OpenGL/specs/gl/glspec46.core.pdf OpenGL Core Profile] with the [page:WebGLRenderer WebGL] renderer on most - platforms linewidth will always be `1` regardless of the set value. + platforms linewidth will always be `1` regardless of the set value.

+ + If you need wider lines, consider using [page:Line2] or [page:LineSegments2] with [page:LineMaterial].

[property:String linecap]

diff --git a/docs/api/en/math/Triangle.html b/docs/api/en/math/Triangle.html index 4e7a055f4ca1ac..4ddadd8bfb026f 100644 --- a/docs/api/en/math/Triangle.html +++ b/docs/api/en/math/Triangle.html @@ -140,6 +140,20 @@

triangle. Returns `null` if the triangle is degenerate.

+

+ [method:Vector getInterpolatedAttribute]( [param:BufferAttribute attribute], [param:Number i1], [param:Vector3 i2], [param:Number i3], [param:Vector3 barycoord], [param:Vector3 target] ) +

+

+ [page:BufferAttribute attribute] - The attribute to interpolate.
+ p1 - Index of first vertex.
+ p2 - Index of second vertex.
+ p3 - Index of third vertex.
+ barycoord - The barycoordinate value to use to interpolate.
+ [page:Vector target] — Result will be copied into this Vector.

+ + Returns the value barycentrically interpolated for the given attribute and indices. +

+

[method:Boolean intersectsBox]( [param:Box3 box] )

[page:Box3 box] - Box to check for intersection against.

diff --git a/docs/api/en/objects/BatchedMesh.html b/docs/api/en/objects/BatchedMesh.html index 417ef92361ade1..1b59384361dc47 100644 --- a/docs/api/en/objects/BatchedMesh.html +++ b/docs/api/en/objects/BatchedMesh.html @@ -167,7 +167,28 @@

[page:Integer instanceId]: The id of an instance to get the visibility state of.

-

Get whether the given instance is marked as "visible" or not.

+

Get whether the given instance is marked as "visible" or not.

+ +

+ [method:Object getGeometryRangeAt]( [param:Integer geometryId], [param:Object target] ) +

+

+ [page:Integer geometryId]: The id of the geometry to get the range of. +

+

+ [page:Object target]: Optional target object to copy the range in to. +

+

Get the range representing the subset of triangles related to the attached geometry, indicating the starting offset and count, or `null` if invalid.

+

Return an object of the form:

+ { start: Integer, count: Integer } + +

+ [method:Integer getGeometryIdAt]( [param:Integer instanceId] ) +

+

+ [page:Integer instanceId]: The id of an instance to get the geometryIndex of. +

+

Get the geometryIndex of the defined instance.

[method:undefined setColorAt]( [param:Integer instanceId], [param:Color color] ) @@ -207,6 +228,19 @@

Sets the visibility of the instance at the given index.

+

+ [method:this setGeometryIdAt]( [param:Integer instanceId], [param:Integer geometryId] ) +

+

+ [page:Integer instanceId]: The id of the instance to set the geometryIndex of. +

+

+ [page:Integer geometryId]: The geometryIndex to be use by the instance. +

+

+ Sets the geometryIndex of the instance at the given index. +

+

[method:Integer addGeometry]( [param:BufferGeometry geometry], [param:Integer reservedVertexRange], [param:Integer reservedIndexRange] )

@@ -237,6 +271,15 @@

Adds a new instance to the [name] using the geometry of the given geometryId and returns a new id referring to the new instance to be used by other functions.

+

+ [method:Integer deleteInstance]( [param:Integer instanceId] ) +

+

+ [page:Integer instanceId]: The id of an instance to remove from the [name] that was previously added via "addInstance". +

+

+ Removes an existing instance from the [name] using the given instanceId. +

[method:Integer setGeometryAt]( [param:Integer geometryId], [param:BufferGeometry geometry] ) diff --git a/docs/api/en/objects/LOD.html b/docs/api/en/objects/LOD.html index 314420e229fe16..49aec0cf64560a 100644 --- a/docs/api/en/objects/LOD.html +++ b/docs/api/en/objects/LOD.html @@ -85,6 +85,15 @@

Adds a mesh that will display at a certain distance and greater. Typically the further away the distance, the lower the detail on the mesh.

+

+ [method:Boolean removeLevel]( [param:Float distance]) +

+

+ distance - Distance of the level to delete.

+ + Removes an existing level, based on the distance from the camera. + Returns `true` when the level has been removed. Otherwise `false`. +

[method:Integer getCurrentLevel]()

Get the currently active LOD level. As index of the levels array.

diff --git a/docs/api/en/renderers/WebGLRenderer.html b/docs/api/en/renderers/WebGLRenderer.html index 8a453696ec1a10..0b085051595cde 100644 --- a/docs/api/en/renderers/WebGLRenderer.html +++ b/docs/api/en/renderers/WebGLRenderer.html @@ -75,6 +75,9 @@

[name]( [param:Object parameters] )

[link:https://www.khronos.org/opengl/wiki/Early_Fragment_Test Early Fragment Test] optimization and can cause a decrease in performance. Default is `false`. See the [example:webgl_camera_logarithmicdepthbuffer camera / logarithmicdepthbuffer] example. + + [page:Boolean reverseDepthBuffer] - whether to use a reverse depth buffer. Requires the `EXT_clip_control` extension. + This is a more faster and accurate version than logarithmic depth buffer. Default is `false`.

Properties

@@ -119,9 +122,7 @@

[property:Object capabilities]

- [page:Boolean isWebGL2]: `true` if the context in use is a WebGL2RenderingContext object.
- [page:Boolean logarithmicDepthBuffer]: `true` if the [page:parameter logarithmicDepthBuffer] - was set to true in the constructor and the context - supports the - [link:https://developer.mozilla.org/en-US/docs/Web/API/EXT_frag_depth EXT_frag_depth] extension.
+ was set to true in the constructor.
- [page:Integer maxAttributes]: The value of `gl.MAX_VERTEX_ATTRIBS`.
- [page:Integer maxCubemapSize]: The value of `gl.MAX_CUBE_MAP_TEXTURE_SIZE`. Maximum height * width of cube map @@ -145,6 +146,9 @@

[property:Object capabilities]

be used in a vertex shader.
- [page:String precision]: The shader precision currently being used by the renderer.
+ - [page:Boolean reverseDepthBuffer]: `true` if the [page:parameter reverseDepthBuffer] + was set to `true` in the constructor and the context + supports the [link:https://registry.khronos.org/webgl/extensions/EXT_clip_control/ EXT_clip_control] extension.
- [page:Boolean vertexTextures]: `true` if [property:Integer maxVertexTextures] is greater than 0 (i.e. vertex textures can be used).

diff --git a/docs/api/zh/extras/TextureUtils.html b/docs/api/zh/extras/TextureUtils.html new file mode 100644 index 00000000000000..1aec64d138bc02 --- /dev/null +++ b/docs/api/zh/extras/TextureUtils.html @@ -0,0 +1,42 @@ + + + + + + + + + +

[name]

+ +

包含纹理实用函数的类。

+ +

方法

+ +

[method:Texture contain]( [param:Texture texture], [param:Number aspect] )

+

+ 在不裁剪或拉伸纹理的情况下,将纹理在其表面内缩放到尽可能大。该方法保留了纹理的原始纵横比。类似于 CSS 中的 `object-fit: contain`。 +

+ +

[method:Texture cover]( [param:Texture texture], [param:Number aspect] )

+

+ 将纹理缩放到尽可能小的尺寸以填充表面,不留空白。该方法保留了纹理的原始纵横比。类似于 CSS 中的 `object-fit: cover`。 +

+ +

[method:Texture fill]( [param:Texture texture] )

+

+ 将纹理配置为默认转换。类似于 CSS 中的 `object-fit: fill`。 +

+ +

[method:Number getByteLength]( [param:Number width], [param:Number height], [param:Number format], [param:Number type] )

+

+ 给定纹理的宽度、高度、格式和类型。确定必须使用多少个字节来表示纹理。 +

+ +

源代码

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/src/[path].js src/[path].js] +

+ + diff --git a/docs/api/zh/objects/InstancedMesh.html b/docs/api/zh/objects/InstancedMesh.html index 83ea9ce4fae6aa..46d1fd31700c7d 100644 --- a/docs/api/zh/objects/InstancedMesh.html +++ b/docs/api/zh/objects/InstancedMesh.html @@ -34,7 +34,7 @@

[name]( [param:BufferGeometry geometry], [param:Material material], [param:I

属性

-

See the base [page:Mesh] class for common properties.

+

公共属性请查看基类 [page:Mesh]。

[property:Box3 boundingBox]

@@ -67,14 +67,19 @@

[property:InstancedBufferAttribute instanceMatrix]

如果你要通过 [page:.setMatrixAt]() 来修改实例数据,你必须将它的 [page:BufferAttribute.needsUpdate needsUpdate] 标识为 true 。

+

[property:DataTexture morphTexture]

+

+ 用于表示所有实例的变形权重。如果你通过 [page:.setMorphAt]() 修改了实例数据,你必须将 [page:Texture.needsUpdate needsUpdate] 标识设置为 true。 +

+

[property:Boolean isInstancedMesh]

- Read-only flag to check if a given object is of type [name]. + 用来检查对象是否属于 [name] 类型的只读标识。

方法

-

See the base [page:Mesh] class for common methods.

+

公共方法请查看基类 [page:Mesh]。

[method:undefined computeBoundingBox]()

@@ -90,18 +95,18 @@

[method:undefined computeBoundingSphere]()

[method:undefined dispose]()

- Frees the internal resources of this instance. + 释放实例的内部资源。

[method:undefined getColorAt]( [param:Integer index], [param:Color color] )

- [page:Integer index]: The index of an instance. Values have to be in the range [0, count]. + [page:Integer index]: 实例的索引。 值必须在 [0, count] 区间。

- [page:Color color]: This color object will be set to the color of the defined instance. + [page:Color color]: 传入的颜色对象将会被设置为指定的实例的颜色。

- Get the color of the defined instance. + 获取已定义实例的颜色。

[method:undefined getMatrixAt]( [param:Integer index], [param:Matrix4 matrix] )

@@ -115,16 +120,26 @@

[method:undefined getMatrixAt]( [param:Integer index], [param:Matrix4 matrix 获得已定义实例的本地变换矩阵。

+

+ [method:undefined getMorphAt]( [param:Integer index], [param:Mesh mesh] ) +

+

+ [page:Integer index]: 实例的索引。值必须在 [0, count] 区间。 +

+

+ [page:Mesh mesh]: 网格属性 [page:Mesh.morphTargetInfluences .morphTargetInfluences] 将会被填充为已定义实例的变形权重。 +

+

获取已定义实例的变形权重

+

[method:undefined setColorAt]( [param:Integer index], [param:Color color] )

- [page:Integer index]: The index of an instance. Values have to be in the range [0, count]. + [page:Integer index]: 实例的索引。值必须在 [0, count] 区间。

- [page:Color color]: The color of a single instance. + [page:Color color]: 单个实例的颜色。

- Sets the given color to the defined instance. - Make sure you set [page:.instanceColor][page:BufferAttribute.needsUpdate .needsUpdate] to true after updating all the colors. + 设置已定义实例的颜色。请确保在更新颜色后将 [page:.instanceColor][page:BufferAttribute.needsUpdate .needsUpdate] 标识设置为 true。

[method:undefined setMatrixAt]( [param:Integer index], [param:Matrix4 matrix] )

@@ -139,6 +154,19 @@

[method:undefined setMatrixAt]( [param:Integer index], [param:Matrix4 matrix 请确保在更新所有矩阵后将 [page:.instanceMatrix][page:BufferAttribute.needsUpdate .needsUpdate] 设置为true。

+

+ [method:undefined setMorphAt]( [param:Integer index], [param:Mesh mesh] ) +

+

+ [page:Integer index]: 实例的索引。值必须在 [0, count] 区间。 +

+

+ [page:Mesh mesh]: 网格属性 [page:Mesh.morphTargetInfluences .morphTargetInfluences] 包含了单个实例的变形权重。 +

+

+ 设置已定义实例的变形权重。请确保在更新所有变形数据后将 [page:.morphTexture][page:Texture.needsUpdate .needsUpdate] 设置为 true。 +

+

源代码

diff --git a/docs/examples/en/controls/DragControls.html b/docs/examples/en/controls/DragControls.html index 8671d98c049004..cb6ddd78119173 100644 --- a/docs/examples/en/controls/DragControls.html +++ b/docs/examples/en/controls/DragControls.html @@ -127,21 +127,6 @@

Methods

See the base [page:Controls] class for common methods.

-

[method:undefined connect] ()

-

- Adds the event listeners of the controls. -

- -

[method:undefined disconnect] ()

-

- Removes the event listeners of the controls. -

- -

[method:undefined dispose] ()

-

- Should be called if the controls is no longer required. -

-

Source

diff --git a/docs/examples/en/controls/TransformControls.html b/docs/examples/en/controls/TransformControls.html index 334ca36614f04c..8b826c89935d7a 100644 --- a/docs/examples/en/controls/TransformControls.html +++ b/docs/examples/en/controls/TransformControls.html @@ -7,7 +7,7 @@ - [page:Object3D] → + [page:Controls] →

[name]

@@ -41,7 +41,7 @@

[name]( [param:Camera camera], [param:HTMLDOMElement domElement] )

[page:Camera camera]: The camera of the rendered scene.

- [page:HTMLDOMElement domElement]: The HTML element used for event listeners. + [page:HTMLDOMElement domElement]: The HTML element used for event listeners. (optional)

Creates a new instance of [name]. @@ -73,7 +73,7 @@

objectChange

Properties

-

See the base [page:Object3D] class for common properties.

+

See the base [page:Controls] class for common properties.

[property:String axis]

@@ -85,32 +85,16 @@

[property:Camera camera]

The camera of the rendered scene.

-

[property:HTMLDOMElement domElement]

-

- The HTMLDOMElement used to listen for mouse / touch events. This must be passed in the constructor; changing it here will - not set up new event listeners. -

-

[property:Boolean dragging]

Whether or not dragging is currently performed. Read-only property.

-

[property:Boolean enabled]

-

- Whether or not the controls are enabled. -

-

[property:String mode]

The current transformation mode. Possible values are "translate", "rotate" and "scale". Default is `translate`.

-

[property:Object3D object]

-

- The 3D object being controlled. -

-

[property:Number rotationSnap]

By default, 3D objects are continuously rotated. If you set this property to a numeric value (radians), you can define in which @@ -150,7 +134,7 @@

[property:Number translationSnap]

Methods

-

See the base [page:Object3D] class for common methods.

+

See the base [page:Controls] class for common methods.

[method:TransformControls attach] ( [param:Object3D object] )

@@ -167,9 +151,10 @@

[method:TransformControls detach] ()

Removes the current 3D object from the controls and makes the helper UI invisible.

-

[method:undefined dispose] ()

+

[method:Object3D getHelper] ()

- Should be called if the controls is no longer required. + Returns the visual representation of the controls. Add the helper to your scene to visually transform the attached + 3D object.

[method:Raycaster getRaycaster] ()

diff --git a/docs/examples/en/geometries/SDFGeometryGenerator.html b/docs/examples/en/geometries/SDFGeometryGenerator.html deleted file mode 100644 index a7c256c10e3b3a..00000000000000 --- a/docs/examples/en/geometries/SDFGeometryGenerator.html +++ /dev/null @@ -1,70 +0,0 @@ - - - - - - - - - - -

[name]

- -

- [name] generates instances of [page:BufferGeometry] from a Signed Distance Function
- Uses Mikola Lysenko's Isosurface -

- -

Import

- -

- [name] is an add-on, and must be imported explicitly. - See [link:#manual/introduction/Installation Installation / Addons]. -

- - - import { SDFGeometryGenerator } from 'three/addons/geometries/SDFGeometryGenerator.js'; - - -

Code Example

- - - const generator = new SDFGeometryGenerator( renderer ); - const sdf = 'float dist( vec3 p ){ return length(p) - 0.5; }' // glsl - const geometry = generator.generate( 64, sdf, 1 ); // ~> THREE.BufferGeometry - - -

Examples

- -

[example:webgl_geometry_sdf geometry / sdf ]

- -

Constructor

- -

[name]( [param:WebGLRenderer renderer] )

- -

- [page:WebGLRenderer renderer] -- The renderer used to render the scene.
-

- -

Methods

- -

[method:BufferGeometry generate]( [param:Int resolution], [param:String distanceField], [param:Int bounds] )

- -

- resolution - Int [ mandatory ] Amount of 'voxels' used for triangulation. Must be power of 2.
Gets heavy after 256, most machines won't be able to process over 512. Defaults to 64. -

-

- distanceField - String [ mandatory ] String with glsl distance function. Name of function must be 'dist', with a vec3 argument. ( see code above ). Defaults to a sphere distance. -

-

- bounds - Int [ optional ] Bounds in which signed distance field will be evaluated. Defaults to 1. -

- - -

Source

- -

- [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/geometries/SDFGeometry.js examples/jsm/geometries/SDFGeometryGenerator.js] -

- - diff --git a/docs/examples/en/geometries/TeapotGeometry.html b/docs/examples/en/geometries/TeapotGeometry.html index 4d2e8050b4bdfa..03668f86f3ba56 100644 --- a/docs/examples/en/geometries/TeapotGeometry.html +++ b/docs/examples/en/geometries/TeapotGeometry.html @@ -60,8 +60,7 @@

Methods

Source

- [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/geometries/TeapotGeometry.js - examples/jsm/geometries/TeapotGeometry.js] + [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/geometries/TeapotGeometry.js examples/jsm/geometries/TeapotGeometry.js]

diff --git a/docs/examples/en/lines/Line2.html b/docs/examples/en/lines/Line2.html new file mode 100644 index 00000000000000..41c484d2a7690a --- /dev/null +++ b/docs/examples/en/lines/Line2.html @@ -0,0 +1,65 @@ + + + + + + + + + + [page:Object3D] → [page:Mesh] → [page:LineSegments2] → + +

[name]

+ +

+ A polyline drawn between vertices. +

+ +

+ This adds functionality beyond [page:Line], like arbitrary line width and changing width to be in world units. + It extends [page:LineSegments2], simplifying constructing segments from a chain of points. +

+ +

Import

+ +

+ [name] is an add-on, and therefore must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { Line2 } from 'three/addons/lines/Line2.js'; + + +

Examples

+ +

+ [example:webgl_lines_fat WebGL / lines / fat ]
+ [example:webgl_lines_fat_raycasting WebGL / lines / fat / raycasting ]
+ [example:webgpu_lines_fat WebGPU / lines / fat / raycasting ] +

+ +

Constructor

+ +

[name]( [param:LineGeometry geometry], [param:LineMaterial material] )

+

+ [page:LineGeometry geometry] — (optional) Pair(s) of vertices representing each line segment.
+ [page:Material material] — (optional) Material for the line. Default is a [page:LineMaterial] with random color. +

+ +

Properties

+

See the base [page:LineSegments2] class for common properties.

+ +

[property:Boolean isLine2]

+

Read-only flag to check if a given object is of type [name].

+ +

Methods

+

See the base [page:LineSegments2] class for common methods.

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/lines/Line2.js examples/jsm/lines/Line2.js] +

+ + diff --git a/docs/examples/en/lines/LineGeometry.html b/docs/examples/en/lines/LineGeometry.html new file mode 100644 index 00000000000000..d1a3ff370e036d --- /dev/null +++ b/docs/examples/en/lines/LineGeometry.html @@ -0,0 +1,84 @@ + + + + + + + + + + [page:BufferGeometry] → [page:InstancedBufferGeometry] → [page:LineSegmentsGeometry] → + +

[name]

+ +

+ A chain of vertices, forming a polyline. +

+ +

+ This is used in [page:Line2] to describe the shape. +

+ +

Import

+ +

+ [name] is an add-on, and therefore must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { LineGeometry } from 'three/addons/lines/LineGeometry.js'; + + +

Examples

+ +

+ [example:webgl_lines_fat WebGL / lines / fat ]
+ [example:webgl_lines_fat_raycasting WebGL / lines / fat / raycasting ]
+ [example:webgpu_lines_fat WebGPU / lines / fat / raycasting ] +

+ +

Constructor

+ +

[name]()

+

+ Creates a new geometry. + Call [page:LineGeometry.setPositions setPositions] to add segments. +

+ +

Properties

+

See the base [page:LineSegmentsGeometry] class for common properties.

+ +

[property:Boolean isLineGeometry]

+

Read-only flag to check if a given object is of type [name].

+ +

Methods

+

See the base [page:LineSegmentsGeometry] class for common methods.

+ +

[method:this fromLine]( [param:Line line] )

+

+ Copy the vertex positions of a [page:Line] object into this geometry. + Assumes the source geometry is not using indices. +

+ +

[method:this setColors]( [param:Array array] )

+

+ Replace the per-vertex colors. + Every triple describes a line vertex: `[r1, g1, b1]`. + The array can be an `Array` or `Float32Array`. +

+ +

[method:this setPositions]( [param:Array array] )

+

+ Replace the vertex positions with a new set. + The array can be an `Array` or `Float32Array`. + The length must be a multiple of three. +

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/lines/LineGeometry.js examples/jsm/lines/LineGeometry.js] +

+ + diff --git a/docs/examples/en/lines/LineMaterial.html b/docs/examples/en/lines/LineMaterial.html new file mode 100644 index 00000000000000..d988ad641df6d6 --- /dev/null +++ b/docs/examples/en/lines/LineMaterial.html @@ -0,0 +1,92 @@ + + + + + + + + + + [page:Material] → [page:ShaderMaterial] → + +

[name]

+ +

+ A material for drawing wireframe-style geometries. + Unlike [page:LineBasicMaterial], it supports arbitrary line widths and allows using world units instead of screen space units. + This material is used with [page:LineSegments2] and [page:Line2]. +

+ +

+ Lines are always rendered with round caps and round joints. +

+ +

Examples

+

+ [example:webgl_lines_fat WebGL / lines / fat ]
+ [example:webgl_lines_fat_raycasting WebGL / lines / fat / raycasting ]
+ [example:webgl_lines_fat_wireframe WebGL / lines / fat / wireframe ]
+ [example:webgpu_lines_fat WebGPU / lines / fat / raycasting ] +

+ +

Constructor

+

[name]( [param:Object parameters] )

+ +

+ [page:Object parameters] - (optional) an object with one or more properties defining the material's appearance. + Any property of the material (including any property inherited from [page:ShaderMaterial]) can be passed in here. +

+ +

+ The exception is the property [page:Hexadecimal color], which can be passed in as a number or hexadecimal string and is `0xffffff` (white) by default. + [page:Color.set]( color ) is called internally. +

+ +

Properties

+

See the base [page:ShaderMaterial] class for common properties.

+ +

[property:Color color]

+

[page:Color] of the material, by default set to white (0xffffff).

+ +

[property:Boolean dashed]

+

Whether the line is dashed, or solid. Default is `false`.

+ +

[property:number dashOffset]

+

Where in the dash cycle the dash starts. Default is `0`.

+ +

[property:number dashScale]

+

The scale of the dashes and gaps. Default is `1`.

+ +

[property:number dashSize]

+

The size of the dash. Default is `1`.

+ +

[property:number gapSize]

+

The size of the gap. Default is `1`.

+ +

[property:Float linewidth]

+

Controls line thickness. Default is `1`.

+ +

[property:Vector2 resolution]

+

+ The size of the viewport, in screen pixels. + This must be kept updated to make screen-space rendering accurate. + The [page:LineSegments2.onBeforeRender] callback performs the update for visible objects. + Default is `[1, 1]`. +

+ +

[property:Boolean worldUnits]

+

+ Whether the material's sizes (width, dash gaps) are in world units. + Default is `false` (screen space units.) +

+ +

Methods

+

See the base [page:ShaderMaterial] class for common methods.

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/lines/LineMaterial.js examples/jsm/lines/LineMaterial.js] +

+ + diff --git a/docs/examples/en/lines/LineSegments2.html b/docs/examples/en/lines/LineSegments2.html new file mode 100644 index 00000000000000..ae32f9d8d2f17c --- /dev/null +++ b/docs/examples/en/lines/LineSegments2.html @@ -0,0 +1,69 @@ + + + + + + + + + + [page:Object3D] → [page:Mesh] → + +

[name]

+ +

+ A series of lines drawn between pairs of vertices. +

+ +

+ This adds functionality beyond [page:LineSegments], like arbitrary line width and changing width to be in world units. + The [page:Line2] extends this object, forming a polyline instead of individual segments. +

+ +

Import

+ +

+ [name] is an add-on, and therefore must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { LineSegments2 } from 'three/addons/lines/LineSegments2.js'; + + +

Example

+ +

[example:webgl_lines_fat_raycasting WebGL / lines / fat / raycasting ]

+ +

Constructor

+ +

[name]( [param:LineSegmentsGeometry geometry], [param:LineMaterial material] )

+

+ [page:LineSegmentsGeometry geometry] — (optional) Pair(s) of vertices representing each line segment.
+ [page:Material material] — (optional) Material for the line. Default is a [page:LineMaterial] with random color. +

+ +

Properties

+

See the base [page:Mesh] class for common properties.

+ +

[property:Boolean isLineSegments2]

+

Read-only flag to check if a given object is of type [name].

+ +

Methods

+

See the base [page:Mesh] class for common methods.

+ +

[method:undefined onBeforeRender]( [param:WebGLRenderer renderer] )

+

+ Called by the framework to update the material's resolution property, needed for screen-scaled widths. +

+

+ If your object is not visible to a camera (e.g. by [page:Object3D.layers layers] or [page:Object3D.visible visible],) you must call this manually whenever the viewport changes. +

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/lines/LineSegments2.js examples/jsm/lines/LineSegments2.js] +

+ + diff --git a/docs/examples/en/lines/LineSegmentsGeometry.html b/docs/examples/en/lines/LineSegmentsGeometry.html new file mode 100644 index 00000000000000..56e81af1859ec7 --- /dev/null +++ b/docs/examples/en/lines/LineSegmentsGeometry.html @@ -0,0 +1,103 @@ + + + + + + + + + + [page:BufferGeometry] → [page:InstancedBufferGeometry] → + +

[name]

+ +

+ A series of vertex pairs, forming line segments. +

+ +

+ This is used in [page:LineSegments2] to describe the shape. +

+ +

Import

+ +

+ [name] is an add-on, and therefore must be imported explicitly. + See [link:#manual/introduction/Installation Installation / Addons]. +

+ + + import { LineSegmentsGeometry } from 'three/addons/lines/LineSegmentsGeometry.js'; + + +

Example

+ +

[example:webgl_lines_fat_raycasting WebGL / lines / fat / raycasting ]

+ +

Constructor

+ +

[name]()

+

+ Creates a new geometry. + Call [page:LineSegmentsGeometry.setPositions setPositions] to add segments. +

+ +

Properties

+

See the base [page:InstancedBufferGeometry] class for common properties.

+ +

[property:Boolean isLineSegmentsGeometry]

+

Read-only flag to check if a given object is of type [name].

+ +

Methods

+

See the base [page:Mesh] class for common methods.

+ +

[method:this fromEdgesGeometry]( [param:EdgesGeometry geometry] )

+

+ Copy the vertex positions of an edge geometry into this geometry. +

+ +

[method:this fromLineSegments]( [param:LineSegments lineSegments] )

+

+ Copy the vertex positions of a [page:LineSegments] object into this geometry. + Assumes the source geometry is not using indices. +

+ +

[method:this fromMesh]( [param:Mesh mesh] )

+

+ Copy the vertex positions of a mesh object into this geometry. +

+ +

[method:this fromWireframeGeometry]( [param:WireframeGeometry geometry] )

+

+ Copy the vertex positions of a wireframe geometry into this geometry. +

+ +

[method:this setColors]( [param:Array array] )

+

+ Replace the per-vertex colors. + Every sixtuple describes a segment: `[r1, g1, b1, r2, g2, b2]`. + The array can be an `Array` or `Float32Array`. +

+ +

[method:this setPositions]( [param:Array array] )

+

+ Replace the vertex positions with a new set. + The array can be an `Array` or `Float32Array`. + The length must be a multiple of six. +

+

+ See also [page:LineSegmentsGeometry.positions positions]. +

+ +

[method:undefined toJSON]()

+

+ Unimplemented. +

+ +

Source

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/lines/LineSegmentsGeometry.js examples/jsm/lines/LineSegmentsGeometry.js] +

+ + diff --git a/docs/examples/ko/controls/MapControls.html b/docs/examples/ko/controls/MapControls.html new file mode 100644 index 00000000000000..51963bd66cdcaf --- /dev/null +++ b/docs/examples/ko/controls/MapControls.html @@ -0,0 +1,122 @@ + + + + + + + + + + + + [page:OrbitControls] → + +

[name]

+ +

+ [name]은 지도 위에서 조망자의 시각으로 카메라를 이동하기 위해 설계되었습니다. + 이 클래스는 [page:OrbitControls]와 같은 구현을 공유하지만 특정한 마우스/터치 상호작용 프리셋을 사용하고 기본적으로 화면 공간 패닝을 비활성화합니다. +

+ +

가져오기

+ +

+ [name]은 애드온으로서 명시적으로 가져와야 합니다. + [link:#manual/introduction/Installation 설치 / 애드온]을 참조하십시오. +

+ + + import { MapControls } from 'three/addons/controls/MapControls.js'; + + +

코드 예제

+ + + const renderer = new THREE.WebGLRenderer(); + renderer.setSize( window.innerWidth, window.innerHeight ); + document.body.appendChild( renderer.domElement ); + + const scene = new THREE.Scene(); + + const camera = new THREE.PerspectiveCamera( 45, window.innerWidth / window.innerHeight, 1, 10000 ); + camera.position.set( 0, 20, 100 ); + + const controls = new MapControls( camera, renderer.domElement ); + controls.enableDamping = true; + + function animate() { + + requestAnimationFrame( animate ); + + // controls.enableDamping 또는 controls.autoRotate가 true로 설정된 경우 필수 + controls.update(); + + renderer.render( scene, camera ); + + } + + +

예제

+ +

[example:misc_controls_map misc / controls / map ]

+ +

생성자

+ +

[name]( [param:Camera object], [param:HTMLDOMElement domElement] )

+

+ [page:Camera object]: (필수) 제어할 카메라입니다. 카메라는 다른 객체의 자식이어서는 안 되며, 그 객체가 스케인 자체가 아니라면 됩니다.

+ + [page:HTMLDOMElement domElement]: 이벤트 리스너에 사용되는 HTML 요소입니다. +

+ +

이벤트

+ +

공통 이벤트를 보기 위해 기본 [page:OrbitControls] 클래스를 참조하십시오.

+ +

속성

+ +

공통 속성을 보기 위해 기본 [page:OrbitControls] 클래스를 참조하십시오.

+ +

+ [property:Object mouseButtons]

+

+ 이 객체에는 컨트롤에 의해 사용되는 마우스 동작에 대한 참조가 포함되어 있습니다. + +controls.mouseButtons = { + LEFT: THREE.MOUSE.PAN, + MIDDLE: THREE.MOUSE.DOLLY, + RIGHT: THREE.MOUSE.ROTATE +} + +

+ +

[property:Boolean screenSpacePanning]

+

+ 패닝 시 카메라 위치가 어떻게 이동되는지 정의합니다. 만약 true이면, 카메라는 화면 공간에서 패닝합니다. + 그렇지 않으면, 카메라는 카메라의 위 방향에 수직인 평면에서 패닝합니다. + 기본값은 `false`입니다. +

+ +

[property:Object touches]

+

+ 이 객체에는 컨트롤에 의해 사용되는 터치 동작에 대한 참조가 포함되어 있습니다. + +controls.touches = { + ONE: THREE.TOUCH.PAN, + TWO: THREE.TOUCH.DOLLY_ROTATE +} + +

+ +

메서드

+ +

공통 메서드를 보기 위해 기본 [page:OrbitControls] 클래스를 참조하십시오.

+ +

소스

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/controls/MapControls.js examples/jsm/controls/MapControls.js] +

+ + + \ No newline at end of file diff --git a/docs/examples/ko/webxr/XREstimatedLight.html b/docs/examples/ko/webxr/XREstimatedLight.html new file mode 100644 index 00000000000000..0f55ff1c1282f1 --- /dev/null +++ b/docs/examples/ko/webxr/XREstimatedLight.html @@ -0,0 +1,117 @@ + + + + + + + + + + + + [page:Group] → + +

[name]

+ +

+ XREstimatedLight은 WebXR의 빛 추정 기능을 사용하여 광도계(light probe), 방향광(directional light) 그리고 (선택적으로) 환경 맵(environment + map)을 생성하여 사용자의 현실 세계의 환경과 조명을 모델링합니다.
+ WebXR가 빛과 환경 추정을 업데이트할 때, XREstimatedLight는 자동으로 광도계, 방향광, 그리고 환경 맵을 업데이트합니다.

+ + WebXR 세션을 생성할 때 `light-estimation`을 선택적 또는 필수 기능으로 지정하는 것이 중요합니다. 그렇지 않으면 빛 추정 기능은 작동하지 않습니다.

+ + 브라우저 호환성 정보는 여기를 참조하십시오. 이는 아직 WebXR의 실험적 기능입니다. 여기

+ + 이를 사용하려면, /examples 디렉토리 내의 모든 파일과 마찬가지로, HTML에 별도로 파일을 포함해야 합니다. +

+ +

가져오기

+ +

+ [name]은 애드온이므로 명시적으로 가져와야 합니다. + [link:#manual/introduction/Installation 설치 / 애드온]을 참조하십시오. +

+ + + import { XREstimatedLight } from 'three/addons/webxr/XREstimatedLight.js'; + + +

코드 예제

+ + + renderer.xr.enabled = true; + + // XREstimatedLight를 초기 시점에 장면에 추가하지 마세요. + // AR 세션이 시작할 때까지 추정된 조명값이 없기 때문입니다. + const xrLight = new XREstimatedLight( renderer ); + + xrLight.addEventListener( 'estimationstart' , () => { + + scene.add( xrLight ); + + if ( xrLight.environment ) { + + scene.environment = xrLight.environment; + + } + + } ); + + xrLight.addEventListener( 'estimationend', () => { + + scene.remove( xrLight ); + + scene.environment = null; + + } ); + + // 조명 추정 기능을 작동하도록 하려면 'light-estimation'을 선택적 또는 필수 기능으로 포함해야 합니다. + document.body.appendChild( XRButton.createButton( renderer, { + optionalFeatures: [ 'light-estimation' ] + } ) ); + + +

예제

+ +

[example:webxr_ar_lighting webxr / light estimation]

+ +

생성자

+ +

[name]( [param:WebGLRenderer renderer], [param:Boolean environmentEstimation] )

+

+ [page:WebGLRenderer renderer]: (필수) 장면을 렌더링하는 렌더러. 주로 WebXRManager와 상호작용하는 데 사용됩니다.

+ + environmentEstimation: `true`로 설정하면 WebXR을 사용하여 환경 맵을 추정합니다. +

+ +

이벤트

+ +

estimationstart

+

+ 추정된 조명값이 업데이트 시작할 때 발생합니다. +

+ +

estimationend

+

+ 추정된 조명값이 업데이트 중지할 때 발생합니다. +

+ +

속성

+ +

[property:Texture environment]

+

+ WebXR에 의해 추정된 환경 맵입니다. 이는 environmentEstimation이 `true`로 설정된 경우에만 사용할 수 있습니다.

+ + 이는 [page:Scene.environment], [page:MeshStandardMaterial.envMap], 또는 [page:Scene.background]로 사용할 수 있습니다. +

+ +

소스

+ +

+ [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/webxr/XREstimatedLight.js + examples/jsm/webxr/XREstimatedLight.js] +

+ + + \ No newline at end of file diff --git a/docs/examples/zh/controls/DragControls.html b/docs/examples/zh/controls/DragControls.html index e0795737498230..b3051c45a53f56 100644 --- a/docs/examples/zh/controls/DragControls.html +++ b/docs/examples/zh/controls/DragControls.html @@ -129,21 +129,6 @@

方法

共有方法请参见其基类[page:Controls]。

-

[method:undefined connect] ()

-

- 添加控制器的事件监听。 -

- -

[method:undefined disconnect] ()

-

- 移除控制器的事件监听。 -

- -

[method:undefined dispose] ()

-

- 若不再需要该控制器,则应当调用此函数。 -

-

源代码

diff --git a/docs/examples/zh/controls/OrbitControls.html b/docs/examples/zh/controls/OrbitControls.html index 9e611a278ce096..2d1fd24fdfd2c4 100644 --- a/docs/examples/zh/controls/OrbitControls.html +++ b/docs/examples/zh/controls/OrbitControls.html @@ -7,6 +7,8 @@ + [page:Controls] → +

轨道控制器([name])

@@ -67,7 +69,7 @@

[name]( [param:Camera object], [param:HTMLDOMElement domElement] )

[page:Camera object]: (必须)将要被控制的相机。该相机不允许是其他任何对象的子级,除非该对象是场景自身。

- [page:HTMLDOMElement domElement]: 用于事件监听的HTML元素。 + [page:HTMLDOMElement domElement]: 用于事件监听的HTML元素。(可选)

Events

@@ -89,12 +91,13 @@

end

属性

+

共有属性请参见其基类[page:Controls]。

+

[property:Boolean autoRotate]

将其设为true,以自动围绕目标旋转。
请注意,如果它被启用,你必须在你的动画循环里调用[page:.update]()。 - Set to true to automatically rotate around the target.
Note that if this is enabled, you must call [page:.update] - () in your animation loop. If you want the auto-rotate speed to be independent of the frame rate (the refresh rate of the display), you must pass the time `deltaTime`, in seconds, to [page:.update](). + 如果希望自动旋转速度与帧速率(显示器的刷新率)无关,则必须将时间 `deltaTime`(以秒为单位)传递给 [page:.update]()。

[property:Float autoRotateSpeed]

@@ -110,16 +113,6 @@

请注意,要使得这一值生效,你必须在你的动画循环里调用[page:.update]()。

-

[property:HTMLDOMElement domElement]

-

- 该 HTMLDOMElement 用于监听鼠标/触摸事件,该属性必须在构造函数中传入。在此处改变它将不会设置新的事件监听。 -

- -

[property:Boolean enabled]

-

- 当设置为false时,控制器将不会响应用户的操作。默认值为true。 -

-

[property:Boolean enableDamping]

将其设置为true以启用阻尼(惯性),这将给控制器带来重量感。默认值为false。
@@ -177,6 +170,11 @@

[property:Float maxPolarAngle]

你能够垂直旋转的角度的上限,范围是0到Math.PI,其默认值为Math.PI。

+

[property:Float maxTargetRadius]

+

+ 你能够让目标移动离 [page:.cursor] 有多远,其默认值为Infinity。 +

+

[property:Float maxZoom]

你能够将相机缩小多少(仅适用于[page:OrthographicCamera]),其默认值为Infinity。 @@ -197,6 +195,11 @@

[property:Float minPolarAngle]

你能够垂直旋转的角度的下限,范围是0到Math.PI,其默认值为0。

+

[property:Float minTargetRadius]

+

+ 你能够让目标移动离 [page:.cursor] 有多近,其默认值为0。 +

+

[property:Float minZoom]

你能够将相机放大多少(仅适用于[page:OrthographicCamera]),其默认值为0。 @@ -215,11 +218,6 @@

-

[property:Camera object]

-

- 正被控制的摄像机。 -

-

[property:Float panSpeed]

位移的速度,其默认值为1。 @@ -253,6 +251,11 @@

[property:Vector3 target]

它可以在任何时候被手动更新,以更改控制器的焦点。

+

[property:Vector3 cursor]

+

+ 被 [page:.minTargetRadius] 和 [page:.maxTargetRadius] 限制的焦点。可随时手动更新以更改 [page:.target] 的兴趣中心。 +

+

[property:Object touches]

该对象包含由控件所使用的触摸操作的引用。 @@ -276,15 +279,12 @@

[property:Float zoomSpeed]

[property:Boolean zoomToCursor]

- Setting this property to `true` allows to zoom to the cursor's position. Default is `false`. + 将此属性设置为 `true` 可以缩放至光标位置。默认值为 `false`。

-

Methods

+

方法

-

[method:undefined dispose] ()

-

- 移除所有的事件监听。 -

+

共有方法请参见其基类[page:Controls]。

[method:radians getAzimuthalAngle] ()

@@ -298,7 +298,7 @@

[method:radians getPolarAngle] ()

[method:Float getDistance] ()

- Returns the distance from the camera to the target. + 返回从相机到目标的距离。

[method:undefined listenToKeyEvents] ( [param:HTMLDOMElement domElement] )

@@ -323,11 +323,7 @@

[method:undefined stopListenToKeyEvents] ()

[method:Boolean update] ( [param:Number deltaTime] )

- 更新控制器。必须在摄像机的变换发生任何手动改变后调用, - 或如果[page:.autoRotate]或[page:.enableDamping]被设置时,在update循环里调用。 - Update the controls. Must be called after any manual changes to the camera's transform, - or in the update loop if [page:.autoRotate] or [page:.enableDamping] are set. `deltaTime`, in seconds, is optional, - and is only required if you want the auto-rotate speed to be independent of the frame rate (the refresh rate of the display). + 更新控制器。必须在摄像机的变换发生任何手动改变后调用,或如果[page:.autoRotate]或[page:.enableDamping]被设置时,在update循环里调用。`deltaTime` 以秒为单位,是可选的,并且仅当您希望自动旋转速度独立于帧速率(显示器的刷新率)时才是必需的。

源代码

diff --git a/docs/examples/zh/controls/PointerLockControls.html b/docs/examples/zh/controls/PointerLockControls.html index cd9814fe7d6981..08429e2c131d27 100644 --- a/docs/examples/zh/controls/PointerLockControls.html +++ b/docs/examples/zh/controls/PointerLockControls.html @@ -102,6 +102,11 @@

[property:Float minPolarAngle]

摄像机的俯仰角下限限制。范围为0到Math.PI弧度之间。默认值为0。

+

[property:Float pointerSpeed]

+

+ 指针移动对相机旋转的影响程度的乘数。默认值为1。 +

+

方法

共有方法请参见其基类[page:Controls]。

diff --git a/docs/examples/zh/controls/TrackballControls.html b/docs/examples/zh/controls/TrackballControls.html index 64a013505ed5aa..ac4ff0bb0de291 100644 --- a/docs/examples/zh/controls/TrackballControls.html +++ b/docs/examples/zh/controls/TrackballControls.html @@ -7,7 +7,7 @@ - [page:EventDispatcher] → + [page:Controls] →

轨迹球控制器([name])

@@ -41,7 +41,7 @@

[name]( [param:Camera camera], [param:HTMLDOMElement domElement] )

[page:Camera camera]: 渲染场景的摄像机。

- [page:HTMLDOMElement domElement]: 用于事件监听的HTML元素。 + [page:HTMLDOMElement domElement]: 用于事件监听的HTML元素。(可选)

创建一个新的 [name] 实例。 @@ -67,21 +67,13 @@

end

属性

-

[property:HTMLDOMElement domElement]

-

- 该 HTMLDOMElement 用于监听鼠标/触摸事件,该属性必须在构造函数中传入。在此处改变它将不会设置新的事件监听。 -

+

共有属性请参见其基类[page:Controls]。

[property:Number dynamicDampingFactor]

设置阻尼的强度。仅在[page:.staticMoving staticMoving]设为*false*时考虑。默认为*0.2*。

-

[property:Boolean enabled]

-

- 是否启用控制器。 -

-

[property:Array keys]

该数组包含用于控制交互的按键代码。 @@ -139,11 +131,6 @@

[property:Boolean noZoom]

是否禁用缩放,默认为*false*。

-

[property:Camera object]

-

- 正被控制的摄像机。 -

-

[property:Number panSpeed]

平移的速度,其默认值为*0.3*。 @@ -170,6 +157,11 @@

[property:Boolean staticMoving]

阻尼是否被禁用。默认为*false*。

+

[property:Vector3 target]

+

+ 控件的焦点。 +

+

[property:Number zoomSpeed]

缩放的速度,其默认值为*1.2*。 @@ -177,46 +169,18 @@

[property:Number zoomSpeed]

方法

-

[method:undefined checkDistances] ()

-

- 确保控制器位于 [minDistance, maxDistance] 范围内。由[page:.update update]()调用。 -

- -

[method:undefined dispose] ()

-

- 若不再需要该控制器,则应当调用此函数。 -

+

共有方法请参见其基类[page:Controls]。

[method:undefined handleResize] ()

若应用程序窗口大小发生改变,则应当调用此函数。

-

[method:undefined panCamera] ()

-

- 如有必要,执行平移。由[page:.update update]()调用。 -

-

[method:undefined reset] ()

重置控制器到初始状态。

-

[method:undefined rotateCamera] ()

-

- 如有必要,旋转相机。由[page:.update update]()调用。 -

- -

[method:undefined update] ()

-

- 更新控制器,常被用在动画循环中。 -

- -

[method:undefined zoomCamera] ()

-

- 如有必要,执行缩放。由[page:.update update]()调用。 -

-

源代码

diff --git a/docs/examples/zh/controls/TransformControls.html b/docs/examples/zh/controls/TransformControls.html index be66b519f224e4..7083adc6fdf19b 100644 --- a/docs/examples/zh/controls/TransformControls.html +++ b/docs/examples/zh/controls/TransformControls.html @@ -7,7 +7,7 @@ - [page:Object3D] → + [page:Controls] →

变换控制器([name])

@@ -41,7 +41,7 @@

[name]( [param:Camera camera], [param:HTMLDOMElement domElement] )

[page:Camera camera]: 被控制的摄像机。

- [page:HTMLDOMElement domElement]: 用于事件监听的HTML元素。 + [page:HTMLDOMElement domElement]: 用于事件监听的HTML元素。(可选)

创建一个新的 [name] 实例。 @@ -73,7 +73,7 @@

objectChange

属性

-

共有属性请参见其基类[page:Object3D]。

+

共有属性请参见其基类[page:Controls]。

[property:String axis]

@@ -85,31 +85,16 @@

[property:Camera camera]

渲染场景的摄像机。

-

[property:HTMLDOMElement domElement]

-

- 该 HTMLDOMElement 用于监听鼠标/触摸事件,该属性必须在构造函数中传入。在此处改变它将不会设置新的事件监听。 -

-

[property:Boolean dragging]

当前是否正在拖动。只读属性。

-

[property:Boolean enabled]

-

- 是否启用控制器。默认为*true*。 -

-

[property:String mode]

当前的变换模式。可能的值包括"translate"、"rotate" 和 "scale"。默认为*translate*。

-

[property:Object3D object]

-

- 正在被控制的3D对象。 -

-

[property:Number rotationSnap]

默认情况下,3D对象是可以被连续旋转的。如果你将该值设为一个数值(弧度),则你将可以定义每次旋转3D对象时的步幅。 @@ -149,7 +134,7 @@

[property:Number translationSnap]

方法

-

共有方法请参见其基类[page:Object3D]。

+

共有方法请参见其基类[page:Controls]。

[method:TransformControls attach] ( [param:Object3D object] )

@@ -166,9 +151,9 @@

[method:TransformControls detach] ()

从控制器中移除当前3D对象,并确保控制器UI是不可见的。

-

[method:undefined dispose] ()

+

[method:Object3D getHelper] ()

- 若不再需要该控制器,则应当调用此函数。 + 返回控件的视觉表示。将辅助对象添加到场景中,以直观地变换附着的3D对象。

[method:Raycaster getRaycaster] ()

@@ -182,6 +167,11 @@

[method:String getMode] ()

返回变换模式。

+ +

[method:undefined reset] ()

+

+ 将对象的位置、旋转和缩放重置为当前变换开始时的状态。 +

[method:undefined setMode] ( [param:String mode] )

diff --git a/docs/examples/zh/geometries/SDFGeometryGenerator.html b/docs/examples/zh/geometries/SDFGeometryGenerator.html deleted file mode 100644 index 94672f8524b595..00000000000000 --- a/docs/examples/zh/geometries/SDFGeometryGenerator.html +++ /dev/null @@ -1,72 +0,0 @@ - - - - - - - - - - - - -

SDF几何体生成器([name])

- -

- [name] 从有符号距离函数 生成 [page:BufferGeometry] 实例。
- 使用 Mikola Lysenko 的等值面。 -

- -

导入

- -

- [name] 是一个附加组件,必须显式导入。请参阅 [link:#manual/introduction/Installation Installation / Addons]. -

- - - import { SDFGeometryGenerator } from 'three/addons/geometries/SDFGeometryGenerator.js'; - - -

代码示例

- - - const generator = new SDFGeometryGenerator( renderer ); - const sdf = 'float dist( vec3 p ){ return length(p) - 0.5; }' // glsl - const geometry = generator.generate( 64, sdf, 1 ); // ~> THREE.BufferGeometry - - -

例子

- -

[example:webgl_geometry_sdf geometry / sdf ]

- -

构造函数

- -

[name]( [param:WebGLRenderer renderer] )

- -

- [page:WebGLRenderer renderer] -- 用于渲染场景的渲染器。
-

- -

方法

- -

[method:BufferGeometry generate]( [param:Int resolution], [param:String distanceField], [param:Int bounds] )

- -

- resolution - Int [必填项] 用于三角测量的“体素”数量。必须是 2 的幂。256 之后会变得很重,大多数机器将无法处理超过 512 的数据。默认为 64。 -

-

- distanceField - String [必填项] 具有 glsl 距离函数的字符串。函数名称必须是“dist”,带有 vec3 参数。(参见上面的代码)。默认为球体距离。 -

-

- bounds - Int [可选] 将评估有符号距离字段的边界。默认为 1。 -

- - -

源代码

- -

- [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/geometries/SDFGeometry.js examples/jsm/geometries/SDFGeometryGenerator.js] -

- - - diff --git a/docs/examples/zh/geometries/TeapotGeometry.html b/docs/examples/zh/geometries/TeapotGeometry.html index 15f8bca1b7a32f..b5ff451e009cb9 100644 --- a/docs/examples/zh/geometries/TeapotGeometry.html +++ b/docs/examples/zh/geometries/TeapotGeometry.html @@ -63,8 +63,7 @@

方法

源代码

- [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/geometries/TeapotGeometry.js - examples/jsm/geometries/TeapotGeometry.js] + [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/geometries/TeapotGeometry.js examples/jsm/geometries/TeapotGeometry.js]

diff --git a/docs/index.html b/docs/index.html index 892c35685b248e..43e7148c934ac5 100644 --- a/docs/index.html +++ b/docs/index.html @@ -538,17 +538,23 @@

three.js

const oldIframe = iframe; iframe = oldIframe.cloneNode(); + iframe.style.display = 'none'; + if ( hash && titles[ splitHash[ 0 ] ] ) { + iframe.onload = function () { + + iframe.style.display = 'unset'; + + }; + iframe.src = splitHash[ 0 ] + '.html' + splitHash[ 1 ]; subtitle = titles[ splitHash[ 0 ] ] + splitHash[ 1 ] + ' – '; - iframe.style.display = 'unset'; } else { iframe.src = ''; subtitle = ''; - iframe.style.display = 'none'; } diff --git a/docs/list.json b/docs/list.json index 86141e3326621f..81426149a26793 100644 --- a/docs/list.json +++ b/docs/list.json @@ -346,7 +346,6 @@ "ConvexGeometry": "examples/en/geometries/ConvexGeometry", "DecalGeometry": "examples/en/geometries/DecalGeometry", "ParametricGeometry": "examples/en/geometries/ParametricGeometry", - "SDFGeometryGenerator": "examples/en/geometries/SDFGeometryGenerator", "TeapotGeometry": "examples/en/geometries/TeapotGeometry", "TextGeometry": "examples/en/geometries/TextGeometry" }, @@ -363,6 +362,14 @@ "LightProbeGenerator": "examples/en/lights/LightProbeGenerator" }, + "Lines": { + "Line2": "examples/en/lines/Line2", + "LineGeometry": "examples/en/lines/LineGeometry", + "LineMaterial": "examples/en/lines/LineMaterial", + "LineSegments2": "examples/en/lines/LineSegments2", + "LineSegmentsGeometry": "examples/en/lines/LineSegmentsGeometry" + }, + "Loaders": { "3DMLoader": "examples/en/loaders/3DMLoader", "DRACOLoader": "examples/en/loaders/DRACOLoader", @@ -434,7 +441,7 @@ "SceneUtils": "examples/en/utils/SceneUtils", "SkeletonUtils": "examples/en/utils/SkeletonUtils" }, - + "WebXR": { "XREstimatedLight": "examples/en/webxr/XREstimatedLight" } @@ -859,7 +866,8 @@ "Earcut": "api/zh/extras/Earcut", "ImageUtils": "api/zh/extras/ImageUtils", "PMREMGenerator": "api/zh/extras/PMREMGenerator", - "ShapeUtils": "api/zh/extras/ShapeUtils" + "ShapeUtils": "api/zh/extras/ShapeUtils", + "TextureUtils": "api/zh/extras/TextureUtils" }, "附件 / 核心": { @@ -1100,8 +1108,7 @@ "DecalGeometry": "examples/zh/geometries/DecalGeometry", "ParametricGeometry": "examples/zh/geometries/ParametricGeometry", "TeapotGeometry": "examples/zh/geometries/TeapotGeometry", - "TextGeometry": "examples/zh/geometries/TextGeometry", - "SDFGeometryGenerator": "examples/zh/geometries/SDFGeometryGenerator" + "TextGeometry": "examples/zh/geometries/TextGeometry" }, "辅助对象": { @@ -1362,12 +1369,16 @@ "DragControls": "examples/ko/controls/DragControls", "FirstPersonControls": "examples/ko/controls/FirstPersonControls", "FlyControls": "examples/ko/controls/FlyControls", + "MapControls": "examples/ko/controls/MapControls", "OrbitControls": "examples/ko/controls/OrbitControls", "PointerLockControls": "examples/ko/controls/PointerLockControls", "TrackballControls": "examples/ko/controls/TrackballControls", "TransformControls": "examples/ko/controls/TransformControls" - } + }, + "WebXR": { + "XREstimatedLight": "examples/ko/webxr/XREstimatedLight" + } } }, diff --git a/docs/manual/ar/introduction/How-to-create-VR-content.html b/docs/manual/ar/introduction/How-to-create-VR-content.html index 85f45c3b386e5a..f4264174f92a2c 100644 --- a/docs/manual/ar/introduction/How-to-create-VR-content.html +++ b/docs/manual/ar/introduction/How-to-create-VR-content.html @@ -59,15 +59,15 @@

الخطوات التالية

ألق نظرة على أحد أمثلة WebVR الرسمية لرؤية سير العمل.

- [example:webxr_vr_ballshooter WebXR / VR / ballshooter]
- [example:webxr_vr_cubes WebXR / VR / cubes]
- [example:webxr_vr_dragging WebXR / VR / dragging]
- [example:webxr_vr_paint WebXR / VR / paint]
+ [example:webxr_xr_ballshooter WebXR / XR / ballshooter]
+ [example:webxr_xr_cubes WebXR / XR / cubes]
+ [example:webxr_xr_dragging WebXR / XR / dragging]
+ [example:webxr_xr_paint WebXR / XR / paint]
+ [example:webxr_xr_sculpt WebXR / XR / sculpt]
[example:webxr_vr_panorama_depth WebXR / VR / panorama_depth]
[example:webxr_vr_panorama WebXR / VR / panorama]
[example:webxr_vr_rollercoaster WebXR / VR / rollercoaster]
[example:webxr_vr_sandbox WebXR / VR / sandbox]
- [example:webxr_vr_sculpt WebXR / VR / sculpt]
[example:webxr_vr_video WebXR / VR / video]

diff --git a/docs/manual/ar/introduction/Libraries-and-Plugins.html b/docs/manual/ar/introduction/Libraries-and-Plugins.html index 44c7eca01c9004..743b874692f4cc 100644 --- a/docs/manual/ar/introduction/Libraries-and-Plugins.html +++ b/docs/manual/ar/introduction/Libraries-and-Plugins.html @@ -107,6 +107,7 @@

الأغلفة والأطُر (Wrappers and Frameworks)

  • [link:https://threlte.xyz/ Threlte] - Svelte components for 3D graphics built on Three.
  • [link:https://needle.tools/ Needle Engine]
  • [link:https://tresjs.org/ tresjs] - Vue components for 3D graphics built on Three.
  • +
  • [link:https://giro3d.org Giro3D] - Versatile framework built on Three for visualizing and interacting with Geospatial 2D, 2.5D and 3D data.
  • diff --git a/docs/manual/en/introduction/How-to-create-VR-content.html b/docs/manual/en/introduction/How-to-create-VR-content.html index c27063612bc0ce..9b76b9e8e3468e 100644 --- a/docs/manual/en/introduction/How-to-create-VR-content.html +++ b/docs/manual/en/introduction/How-to-create-VR-content.html @@ -64,15 +64,15 @@

    Next Steps

    Have a look at one of the official WebVR examples to see this workflow in action.

    - [example:webxr_vr_ballshooter WebXR / VR / ballshooter]
    - [example:webxr_vr_cubes WebXR / VR / cubes]
    - [example:webxr_vr_dragging WebXR / VR / dragging]
    - [example:webxr_vr_paint WebXR / VR / paint]
    + [example:webxr_xr_ballshooter WebXR / XR / ballshooter]
    + [example:webxr_xr_cubes WebXR / XR / cubes]
    + [example:webxr_xr_dragging WebXR / XR / dragging]
    + [example:webxr_xr_paint WebXR / XR / paint]
    + [example:webxr_xr_sculpt WebXR / XR / sculpt]
    [example:webxr_vr_panorama_depth WebXR / VR / panorama_depth]
    [example:webxr_vr_panorama WebXR / VR / panorama]
    [example:webxr_vr_rollercoaster WebXR / VR / rollercoaster]
    [example:webxr_vr_sandbox WebXR / VR / sandbox]
    - [example:webxr_vr_sculpt WebXR / VR / sculpt]
    [example:webxr_vr_video WebXR / VR / video]

    diff --git a/docs/manual/en/introduction/How-to-update-things.html b/docs/manual/en/introduction/How-to-update-things.html index 7a28ac5bcfd17f..61e7372f642eaa 100644 --- a/docs/manual/en/introduction/How-to-update-things.html +++ b/docs/manual/en/introduction/How-to-update-things.html @@ -62,7 +62,7 @@

    BufferGeometry

    const geometry = new THREE.BufferGeometry(); // attributes -const positions = new Float32Array( MAX_POINTS * 3 ); // 3 vertices per point +const positions = new Float32Array( MAX_POINTS * 3 ); // 3 floats (x, y and z) per point geometry.setAttribute( 'position', new THREE.BufferAttribute( positions, 3 ) ); // draw range diff --git a/docs/manual/en/introduction/Libraries-and-Plugins.html b/docs/manual/en/introduction/Libraries-and-Plugins.html index 84beff181027e6..7342dd23f0c512 100644 --- a/docs/manual/en/introduction/Libraries-and-Plugins.html +++ b/docs/manual/en/introduction/Libraries-and-Plugins.html @@ -111,6 +111,7 @@

    Wrappers and Frameworks

  • [link:https://threlte.xyz/ Threlte] - Svelte components for 3D graphics built on Three.
  • [link:https://needle.tools/ Needle Engine]
  • [link:https://tresjs.org/ tresjs] - Vue components for 3D graphics built on Three.
  • +
  • [link:https://giro3d.org Giro3D] - Versatile framework built on Three for visualizing and interacting with Geospatial 2D, 2.5D and 3D data.
  • diff --git a/docs/manual/fr/introduction/How-to-create-VR-content.html b/docs/manual/fr/introduction/How-to-create-VR-content.html index bad2a211ede43a..d846cd1d2b730f 100644 --- a/docs/manual/fr/introduction/How-to-create-VR-content.html +++ b/docs/manual/fr/introduction/How-to-create-VR-content.html @@ -64,15 +64,15 @@

    Étapes Suivantes

    Jetez un coup d'oeil à un des exemples officiels WebVR pour voir le workflow en action.

    - [example:webxr_vr_ballshooter WebXR / VR / ballshooter]
    - [example:webxr_vr_cubes WebXR / VR / cubes]
    - [example:webxr_vr_dragging WebXR / VR / dragging]
    - [example:webxr_vr_paint WebXR / VR / paint]
    + [example:webxr_xr_ballshooter WebXR / XR / ballshooter]
    + [example:webxr_xr_cubes WebXR / XR / cubes]
    + [example:webxr_xr_dragging WebXR / XR / dragging]
    + [example:webxr_xr_paint WebXR / XR / paint]
    + [example:webxr_xr_sculpt WebXR / XR / sculpt]
    [example:webxr_vr_panorama_depth WebXR / VR / panorama_depth]
    [example:webxr_vr_panorama WebXR / VR / panorama]
    [example:webxr_vr_rollercoaster WebXR / VR / rollercoaster]
    [example:webxr_vr_sandbox WebXR / VR / sandbox]
    - [example:webxr_vr_sculpt WebXR / VR / sculpt]
    [example:webxr_vr_video WebXR / VR / video]

    diff --git a/docs/manual/fr/introduction/How-to-update-things.html b/docs/manual/fr/introduction/How-to-update-things.html index 544e0074f2190b..5937b7eaff78ed 100644 --- a/docs/manual/fr/introduction/How-to-update-things.html +++ b/docs/manual/fr/introduction/How-to-update-things.html @@ -95,22 +95,23 @@

    BufferGeometry

    }

    - If you want to change the number of points rendered after the first render, do this: + Si vous voulez changer le nombre de points rendus après le premier rendu, faites ainsi :

    line.geometry.setDrawRange( 0, newValue );

    - If you want to change the position data values after the first render, you need to - set the needsUpdate flag like so: + Si vous voulez changer la valeur des données de position après le premier rendu, vous devez + régler le flag needsUpdate ainsi :

    positionAttribute.needsUpdate = true; // required after the first render

    - If you change the position data values after the initial render, you may need to recompute - bounding volumes so other features of the engine like view frustum culling or helpers properly work. + Si vous changez les valeurs de la donnée de position après le premier rendu, vous devez + recalculer les volumes englobants de telle sorte que les autres fonctionnalités du moteur comme + le frustrum culling ou les helpers le prenne en compte correctement.

    line.geometry.computeBoundingBox(); @@ -118,10 +119,10 @@

    BufferGeometry

    - [link:https://jsfiddle.net/t4m85pLr/1/ Here is a fiddle] showing an animated line which you can adapt to your use case. + [link:https://jsfiddle.net/t4m85pLr/1/ Voici un fiddle] montrant une ligne animée, que vous pouvez adapter comme vous le souhaitez.

    -

    Examples

    +

    Exemples

    [example:webgl_custom_attributes WebGL / custom / attributes]
    @@ -130,11 +131,11 @@

    Examples

    -

    Materiaux

    +

    Matériaux

    Toutes les valeurs uniformes peuvent être changées librement(e.g. couleurs, textures, opacité, etc), les valeurs sont envoyées aux shaders à chaque frame.

    -

    De plus, les paramètresen relation avec GLstate peuvent changer à tout moment (depthTest, blending, polygonOffset, etc).

    +

    De plus, les paramètres en relation avec GLstate peuvent changer à tout moment (depthTest, blending, polygonOffset, etc).

    Les propriétés suivantes ne peuvent pas être changées facilement durant l'exécution (une fois que le matériau a été rendu au moins une fois):

      diff --git a/docs/manual/fr/introduction/How-to-use-post-processing.html b/docs/manual/fr/introduction/How-to-use-post-processing.html index 1e5c9254668eea..f31877d72edcc0 100644 --- a/docs/manual/fr/introduction/How-to-use-post-processing.html +++ b/docs/manual/fr/introduction/How-to-use-post-processing.html @@ -88,11 +88,11 @@

      Effets Intégrés

      [link:https://github.com/mrdoob/three.js/tree/dev/examples/jsm/postprocessing postprocessing].

      -

      Effets Customisés

      +

      Effets Personnalisés

      - Parfois vous voulez écrire un shader de post-processing customisé et l'inclure dans les effets (passes) de post-processing. Dans ce scénario, - vous pouvez utiliser `ShaderPass`. Après avoir importé le fichier et votre shader customisé, vous pouvez utiliser le code suivant pour mettre en place l'effet (pass). + Parfois vous voulez écrire un shader de post-processing personnalisé et l'inclure dans les effets (passes) de post-processing. Dans ce scénario, + vous pouvez utiliser `ShaderPass`. Après avoir importé le fichier et votre shader personnalisé, vous pouvez utiliser le code suivant pour mettre en place l'effet (pass).

      @@ -106,8 +106,8 @@

      Effets Customisés

      - Ce repository fournit un fichier appelé [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/shaders/CopyShader.js CopyShader] qui est - une bonne base de code pour créer votre propose shader customisé. `CopyShader` copie simplement le contenu de l'image du buffer de l'[page:EffectComposer] + Ce dépôt fournit un fichier appelé [link:https://github.com/mrdoob/three.js/blob/master/examples/jsm/shaders/CopyShader.js CopyShader] qui est + une bonne base de code pour créer votre propose shader personnalisé. `CopyShader` copie simplement le contenu de l'image du buffer de l'[page:EffectComposer] à son buffer d'écriture sans y appliquer aucun effet.

      diff --git a/docs/manual/fr/introduction/Libraries-and-Plugins.html b/docs/manual/fr/introduction/Libraries-and-Plugins.html index c3d9d5b3c21aa0..07bb7a5641a4ef 100644 --- a/docs/manual/fr/introduction/Libraries-and-Plugins.html +++ b/docs/manual/fr/introduction/Libraries-and-Plugins.html @@ -37,7 +37,7 @@

      Postprocessing

    • [link:https://github.com/vanruesc/postprocessing postprocessing]
    -

    Intersections et Performance de Raycast

    +

    Intersections et lancers de rayon

    • [link:https://github.com/gkjohnson/three-mesh-bvh three-mesh-bvh]
    • @@ -91,7 +91,7 @@

      Cinématique inverse

    • [link:https://github.com/gkjohnson/closed-chain-ik-js closed-chain-ik]
    -

    Jeu IA

    +

    Jeu et IA

    • [link:https://mugen87.github.io/yuka/ yuka]
    • @@ -103,13 +103,14 @@

      Wrappers et Frameworks

      • [link:https://aframe.io/ A-Frame]
      • -
      • [link:https://lume.io/ Lume] - HTML elements for 3D graphics built on Three.
      • -
      • [link:https://github.com/pmndrs/react-three-fiber react-three-fiber] - React components for 3D graphics built on Three.
      • -
      • [link:https://threepipe.org/ threepipe] - A versatile 3D viewer framework using three.js for rendering.
      • +
      • [link:https://lume.io/ Lume] - Éléments HTML pour interface 3D, basé sur Three.
      • +
      • [link:https://github.com/pmndrs/react-three-fiber react-three-fiber] - Composants React pour interface 3D, basé sur Three.
      • +
      • [link:https://threepipe.org/ threepipe] - Un framework de visualisation 3D polyvalent utilisant Three pour le rendu.
      • [link:https://github.com/ecsyjs/ecsy-three ECSY]
      • -
      • [link:https://threlte.xyz/ Threlte] - Svelte components for 3D graphics built on Three.
      • +
      • [link:https://threlte.xyz/ Threlte] - Des composants Svelte pour interface 3D, basé sur Three.
      • [link:https://needle.tools/ Needle Engine]
      • -
      • [link:https://tresjs.org/ tresjs] - Vue components for 3D graphics built on Three.
      • +
      • [link:https://tresjs.org/ tresjs] - Des composants Vue pour interface 3D, basé sur Three.
      • +
      • [link:https://giro3d.org Giro3D] - Un framework polyvalent basé sur Three pour la visualisation et l'interaction avec des données géospatiales 2D, 2.5D et 3D.
      diff --git a/docs/manual/it/introduction/How-to-create-VR-content.html b/docs/manual/it/introduction/How-to-create-VR-content.html index e54f2478fdd5e7..9737690beb7836 100644 --- a/docs/manual/it/introduction/How-to-create-VR-content.html +++ b/docs/manual/it/introduction/How-to-create-VR-content.html @@ -62,15 +62,15 @@

      Prossimi passi

      Dai un'occhiata ad uno degli esempi ufficiali di WebVR per vedere questo flusso di lavoro in azione.

      - [example:webxr_vr_ballshooter WebXR / VR / ballshooter]
      - [example:webxr_vr_cubes WebXR / VR / cubes]
      - [example:webxr_vr_dragging WebXR / VR / dragging]
      - [example:webxr_vr_paint WebXR / VR / paint]
      + [example:webxr_xr_ballshooter WebXR / XR / ballshooter]
      + [example:webxr_xr_cubes WebXR / XR / cubes]
      + [example:webxr_xr_dragging WebXR / XR / dragging]
      + [example:webxr_xr_paint WebXR / XR / paint]
      + [example:webxr_xr_sculpt WebXR / XR / sculpt]
      [example:webxr_vr_panorama_depth WebXR / VR / panorama_depth]
      [example:webxr_vr_panorama WebXR / VR / panorama]
      [example:webxr_vr_rollercoaster WebXR / VR / rollercoaster]
      [example:webxr_vr_sandbox WebXR / VR / sandbox]
      - [example:webxr_vr_sculpt WebXR / VR / sculpt]
      [example:webxr_vr_video WebXR / VR / video]

      diff --git a/docs/manual/it/introduction/Libraries-and-Plugins.html b/docs/manual/it/introduction/Libraries-and-Plugins.html index 35a747b50128f6..0ed081f3ba72e2 100644 --- a/docs/manual/it/introduction/Libraries-and-Plugins.html +++ b/docs/manual/it/introduction/Libraries-and-Plugins.html @@ -110,6 +110,7 @@

      Wrappers e Frameworks

    • [link:https://threlte.xyz/ Threlte] - Svelte components for 3D graphics built on Three.
    • [link:https://needle.tools/ Needle Engine]
    • [link:https://tresjs.org/ tresjs] - Vue components for 3D graphics built on Three.
    • +
    • [link:https://giro3d.org Giro3D] - Versatile framework built on Three for visualizing and interacting with Geospatial 2D, 2.5D and 3D data.
    diff --git a/docs/manual/ja/introduction/How-to-create-VR-content.html b/docs/manual/ja/introduction/How-to-create-VR-content.html index 9fd2dd351530df..859511bbdb6f6d 100644 --- a/docs/manual/ja/introduction/How-to-create-VR-content.html +++ b/docs/manual/ja/introduction/How-to-create-VR-content.html @@ -58,15 +58,15 @@

    Next Steps

    このワークフローを実際に見るために、公式のWebVRの例を見てみましょう。

    - [example:webxr_vr_ballshooter WebXR / VR / ballshooter]
    - [example:webxr_vr_cubes WebXR / VR / cubes]
    - [example:webxr_vr_dragging WebXR / VR / dragging]
    - [example:webxr_vr_paint WebXR / VR / paint]
    + [example:webxr_xr_ballshooter WebXR / XR / ballshooter]
    + [example:webxr_xr_cubes WebXR / XR / cubes]
    + [example:webxr_xr_dragging WebXR / XR / dragging]
    + [example:webxr_xr_paint WebXR / XR / paint]
    + [example:webxr_xr_sculpt WebXR / XR / sculpt]
    [example:webxr_vr_panorama_depth WebXR / VR / panorama_depth]
    [example:webxr_vr_panorama WebXR / VR / panorama]
    [example:webxr_vr_rollercoaster WebXR / VR / rollercoaster]
    [example:webxr_vr_sandbox WebXR / VR / sandbox]
    - [example:webxr_vr_sculpt WebXR / VR / sculpt]
    [example:webxr_vr_video WebXR / VR / video]

    diff --git a/docs/manual/ja/introduction/Libraries-and-Plugins.html b/docs/manual/ja/introduction/Libraries-and-Plugins.html index dac20124c856d9..593678c94db9dc 100644 --- a/docs/manual/ja/introduction/Libraries-and-Plugins.html +++ b/docs/manual/ja/introduction/Libraries-and-Plugins.html @@ -103,6 +103,7 @@

    Wrappers and Frameworks

  • [link:https://threlte.xyz/ Threlte] - Svelte components for 3D graphics built on Three.
  • [link:https://needle.tools/ Needle Engine]
  • [link:https://tresjs.org/ tresjs] - Vue components for 3D graphics built on Three.
  • +
  • [link:https://giro3d.org Giro3D] - Versatile framework built on Three for visualizing and interacting with Geospatial 2D, 2.5D and 3D data.
  • diff --git a/docs/manual/ko/introduction/Drawing-lines.html b/docs/manual/ko/introduction/Drawing-lines.html index 454c23b0045289..36142f4cf7b101 100644 --- a/docs/manual/ko/introduction/Drawing-lines.html +++ b/docs/manual/ko/introduction/Drawing-lines.html @@ -47,7 +47,7 @@

    선 그리기([name])

    const geometry = new THREE.BufferGeometry().setFromPoints( points ); -

    선은 연속된 꼭짓점 쌍 사이에 그려지고 첫 번재와 마지막 꼭짓점에는 그려지지 않습니다. (선은 닫혀있지 않습니다.)

    +

    선은 연속된 꼭짓점 쌍 사이에 그려지고 첫 번째와 마지막 꼭짓점에는 그려지지 않습니다. (선은 닫혀있지 않습니다.)

    이제 두 선을 그리기 위한 점과 재질이 있으니, 합쳐서 선을 만들 수 있습니다.

    @@ -64,4 +64,4 @@

    선 그리기([name])

    - \ No newline at end of file + diff --git a/docs/manual/ko/introduction/How-to-create-VR-content.html b/docs/manual/ko/introduction/How-to-create-VR-content.html index 2534d9d5e19a3e..32ecf7374ee9b4 100644 --- a/docs/manual/ko/introduction/How-to-create-VR-content.html +++ b/docs/manual/ko/introduction/How-to-create-VR-content.html @@ -62,15 +62,15 @@

    다음 절차

    실행을 위한 작업 절차와 관련된 공식 WebVR 예제를 확인하세요.

    - [example:webxr_vr_ballshooter WebXR / VR / ballshooter]
    - [example:webxr_vr_cubes WebXR / VR / cubes]
    - [example:webxr_vr_dragging WebXR / VR / dragging]
    - [example:webxr_vr_paint WebXR / VR / paint]
    + [example:webxr_xr_ballshooter WebXR / XR / ballshooter]
    + [example:webxr_xr_cubes WebXR / XR / cubes]
    + [example:webxr_xr_dragging WebXR / XR / dragging]
    + [example:webxr_xr_paint WebXR / XR / paint]
    + [example:webxr_xr_sculpt WebXR / XR / sculpt]
    [example:webxr_vr_panorama_depth WebXR / VR / panorama_depth]
    [example:webxr_vr_panorama WebXR / VR / panorama]
    [example:webxr_vr_rollercoaster WebXR / VR / rollercoaster]
    [example:webxr_vr_sandbox WebXR / VR / sandbox]
    - [example:webxr_vr_sculpt WebXR / VR / sculpt]
    [example:webxr_vr_video WebXR / VR / video]

    diff --git a/docs/manual/pt-br/introduction/How-to-create-VR-content.html b/docs/manual/pt-br/introduction/How-to-create-VR-content.html index 1fe33be277a179..adf249e6c7df95 100644 --- a/docs/manual/pt-br/introduction/How-to-create-VR-content.html +++ b/docs/manual/pt-br/introduction/How-to-create-VR-content.html @@ -64,15 +64,15 @@

    Próximos Passos

    Dê uma olhada em um dos exemplos oficiais de WebVR para ver esse workflow em ação

    - [example:webxr_vr_ballshooter WebXR / VR / ballshooter]
    - [example:webxr_vr_cubes WebXR / VR / cubes]
    - [example:webxr_vr_dragging WebXR / VR / dragging]
    - [example:webxr_vr_paint WebXR / VR / paint]
    + [example:webxr_xr_ballshooter WebXR / XR / ballshooter]
    + [example:webxr_xr_cubes WebXR / XR / cubes]
    + [example:webxr_xr_dragging WebXR / XR / dragging]
    + [example:webxr_xr_paint WebXR / XR / paint]
    + [example:webxr_xr_sculpt WebXR / XR / sculpt]
    [example:webxr_vr_panorama_depth WebXR / VR / panorama_depth]
    [example:webxr_vr_panorama WebXR / VR / panorama]
    [example:webxr_vr_rollercoaster WebXR / VR / rollercoaster]
    [example:webxr_vr_sandbox WebXR / VR / sandbox]
    - [example:webxr_vr_sculpt WebXR / VR / sculpt]
    [example:webxr_vr_video WebXR / VR / video]

    diff --git a/docs/manual/pt-br/introduction/Libraries-and-Plugins.html b/docs/manual/pt-br/introduction/Libraries-and-Plugins.html index 90ef230cdf846f..6e0fab2a1421cf 100644 --- a/docs/manual/pt-br/introduction/Libraries-and-Plugins.html +++ b/docs/manual/pt-br/introduction/Libraries-and-Plugins.html @@ -110,6 +110,7 @@

    Wrappers e Frameworks

  • [link:https://threlte.xyz/ Threlte] - Svelte components for 3D graphics built on Three.
  • [link:https://needle.tools/ Needle Engine]
  • [link:https://tresjs.org/ tresjs] - Vue components for 3D graphics built on Three.
  • +
  • [link:https://giro3d.org Giro3D] - Versatile framework built on Three for visualizing and interacting with Geospatial 2D, 2.5D and 3D data.
  • diff --git a/docs/manual/ru/introduction/Libraries-and-Plugins.html b/docs/manual/ru/introduction/Libraries-and-Plugins.html index 9ed45fa94e8a56..3b706b953b6aaa 100644 --- a/docs/manual/ru/introduction/Libraries-and-Plugins.html +++ b/docs/manual/ru/introduction/Libraries-and-Plugins.html @@ -109,6 +109,7 @@

    Обертки и фреймворки

  • [link:https://threlte.xyz/ Threlte] - Svelte components for 3D graphics built on Three.
  • [link:https://needle.tools/ Needle Engine]
  • [link:https://tresjs.org/ tresjs] - Vue components for 3D graphics built on Three.
  • +
  • [link:https://giro3d.org Giro3D] - Versatile framework built on Three for visualizing and interacting with Geospatial 2D, 2.5D and 3D data.
  • diff --git a/docs/manual/zh/introduction/How-to-create-VR-content.html b/docs/manual/zh/introduction/How-to-create-VR-content.html index 37d6c3c7b5c5a5..730bbe0d57fff7 100644 --- a/docs/manual/zh/introduction/How-to-create-VR-content.html +++ b/docs/manual/zh/introduction/How-to-create-VR-content.html @@ -64,15 +64,15 @@

    接下来的步骤

    请查看官方示例中与WebVR相关的示例,了解这一工作流程的实际使用、运行情况。

    - [example:webxr_vr_ballshooter WebXR / VR / ballshooter]
    - [example:webxr_vr_cubes WebXR / VR / cubes]
    - [example:webxr_vr_dragging WebXR / VR / dragging]
    - [example:webxr_vr_paint WebXR / VR / paint]
    + [example:webxr_xr_ballshooter WebXR / XR / ballshooter]
    + [example:webxr_xr_cubes WebXR / XR / cubes]
    + [example:webxr_xr_dragging WebXR / XR / dragging]
    + [example:webxr_xr_paint WebXR / XR / paint]
    + [example:webxr_xr_sculpt WebXR / XR / sculpt]
    [example:webxr_vr_panorama_depth WebXR / VR / panorama_depth]
    [example:webxr_vr_panorama WebXR / VR / panorama]
    [example:webxr_vr_rollercoaster WebXR / VR / rollercoaster]
    [example:webxr_vr_sandbox WebXR / VR / sandbox]
    - [example:webxr_vr_sculpt WebXR / VR / sculpt]
    [example:webxr_vr_video WebXR / VR / video]

    diff --git a/docs/manual/zh/introduction/Libraries-and-Plugins.html b/docs/manual/zh/introduction/Libraries-and-Plugins.html index 4a20d8cdf25723..e022958eb95e32 100644 --- a/docs/manual/zh/introduction/Libraries-and-Plugins.html +++ b/docs/manual/zh/introduction/Libraries-and-Plugins.html @@ -106,6 +106,7 @@

    封装器和框架(Wrappers and Frameworks)

  • [link:https://threlte.xyz/ Threlte] - Svelte components for 3D graphics built on Three.
  • [link:https://needle.tools/ Needle Engine]
  • [link:https://tresjs.org/ tresjs] - Vue components for 3D graphics built on Three.
  • +
  • [link:https://giro3d.org Giro3D] - Versatile framework built on Three for visualizing and interacting with Geospatial 2D, 2.5D and 3D data.
  • diff --git a/docs/page.css b/docs/page.css index 641915d7ce6c21..192705002f35a0 100644 --- a/docs/page.css +++ b/docs/page.css @@ -122,6 +122,10 @@ summary { margin-bottom: 16px; } +summary:hover { + cursor: pointer; +} + p { padding-right: 16px; } diff --git a/editor/js/Viewport.js b/editor/js/Viewport.js index 3b04fc8b4f91c1..334288367b1511 100644 --- a/editor/js/Viewport.js +++ b/editor/js/Viewport.js @@ -142,7 +142,7 @@ function Viewport( editor ) { } ); - sceneHelpers.add( transformControls ); + sceneHelpers.add( transformControls.getHelper() ); // diff --git a/examples/files.json b/examples/files.json index 31f706f8f73475..99aa8b5d01225f 100644 --- a/examples/files.json +++ b/examples/files.json @@ -34,7 +34,6 @@ "webgl_geometry_extrude_splines", "webgl_geometry_minecraft", "webgl_geometry_nurbs", - "webgl_geometry_sdf", "webgl_geometry_shapes", "webgl_geometry_spline_editor", "webgl_geometry_teapot", @@ -114,7 +113,6 @@ "webgl_loader_ply", "webgl_loader_stl", "webgl_loader_svg", - "webgl_loader_tilt", "webgl_loader_texture_dds", "webgl_loader_texture_exr", "webgl_loader_texture_ultrahdr", @@ -254,7 +252,6 @@ "webgl_buffergeometry", "webgl_buffergeometry_attributes_integer", "webgl_buffergeometry_attributes_none", - "webgl_buffergeometry_compression", "webgl_buffergeometry_custom_attributes_particles", "webgl_buffergeometry_drawrange", "webgl_buffergeometry_glbufferattribute", @@ -302,6 +299,8 @@ "webgl_performance" ], "webgpu (wip)": [ + "webgpu_animation_retargeting", + "webgpu_animation_retargeting_readyplayer", "webgpu_backdrop", "webgpu_backdrop_area", "webgpu_backdrop_water", @@ -315,8 +314,10 @@ "webgpu_compute_particles_rain", "webgpu_compute_particles_snow", "webgpu_compute_points", + "webgpu_compute_sort_bitonic", "webgpu_compute_texture", "webgpu_compute_texture_pingpong", + "webgpu_compute_water", "webgpu_cubemap_adjustments", "webgpu_cubemap_dynamic", "webgpu_cubemap_mix", @@ -329,7 +330,9 @@ "webgpu_instance_points", "webgpu_instance_uniform", "webgpu_instancing_morph", + "webgpu_lensflares", "webgpu_lightprobe", + "webgpu_lightprobe_cubecamera", "webgpu_lights_custom", "webgpu_lights_ies_spotlight", "webgpu_lights_phong", @@ -345,6 +348,7 @@ "webgpu_loader_gltf_transmission", "webgpu_loader_materialx", "webgpu_materials", + "webgpu_materials_arrays", "webgpu_materials_basic", "webgpu_materials_displacementmap", "webgpu_materials_envmaps", @@ -357,6 +361,7 @@ "webgpu_materialx_noise", "webgpu_mesh_batch", "webgpu_mirror", + "webgpu_modifier_curve", "webgpu_morphtargets", "webgpu_morphtargets_face", "webgpu_mrt", @@ -399,6 +404,7 @@ "webgpu_shadertoy", "webgpu_shadowmap", "webgpu_shadowmap_opacity", + "webgpu_shadowmap_vsm", "webgpu_skinning", "webgpu_skinning_instancing", "webgpu_skinning_points", @@ -410,6 +416,7 @@ "webgpu_textures_2d-array_compressed", "webgpu_textures_anisotropy", "webgpu_textures_partialupdate", + "webgpu_tonemapping", "webgpu_tsl_angular_slicing", "webgpu_tsl_coffee_smoke", "webgpu_tsl_compute_attractors_particles", @@ -422,6 +429,7 @@ "webgpu_tsl_raging_sea", "webgpu_tsl_transpiler", "webgpu_tsl_vfx_flames", + "webgpu_tsl_vfx_linkedparticles", "webgpu_tsl_vfx_tornado", "webgpu_video_panorama", "webgpu_volume_cloud", diff --git a/examples/jsm/Addons.js b/examples/jsm/Addons.js index 6941a5553a9ee5..81a0a1d6a8a01a 100644 --- a/examples/jsm/Addons.js +++ b/examples/jsm/Addons.js @@ -124,7 +124,6 @@ export * from './loaders/TDSLoader.js'; export * from './loaders/TGALoader.js'; export * from './loaders/TIFFLoader.js'; export * from './loaders/TTFLoader.js'; -export * from './loaders/TiltLoader.js'; export * from './loaders/USDZLoader.js'; export * from './loaders/VOXLoader.js'; export * from './loaders/VRMLLoader.js'; @@ -172,9 +171,6 @@ export * from './objects/ShadowMesh.js'; export * from './objects/Sky.js'; export * from './objects/Water.js'; export { Water as Water2 } from './objects/Water2.js'; -export * from './objects/SkyMesh.js'; -export * from './objects/WaterMesh.js'; -export { WaterMesh as Water2Mesh } from './objects/Water2Mesh.js'; export * from './physics/AmmoPhysics.js'; export * from './physics/RapierPhysics.js'; @@ -271,11 +267,9 @@ export * from './textures/FlakesTexture.js'; export * as BufferGeometryUtils from './utils/BufferGeometryUtils.js'; export * as CameraUtils from './utils/CameraUtils.js'; -export * from './utils/GPUStatsPanel.js'; export * as GeometryCompressionUtils from './utils/GeometryCompressionUtils.js'; export * as GeometryUtils from './utils/GeometryUtils.js'; export * from './utils/LDrawUtils.js'; -export * from './utils/PackedPhongMaterial.js'; export * as SceneUtils from './utils/SceneUtils.js'; export * from './utils/ShadowMapViewer.js'; export * as SkeletonUtils from './utils/SkeletonUtils.js'; diff --git a/examples/jsm/controls/TrackballControls.js b/examples/jsm/controls/TrackballControls.js index dec8248f6bf514..eebf91004d66ff 100644 --- a/examples/jsm/controls/TrackballControls.js +++ b/examples/jsm/controls/TrackballControls.js @@ -618,23 +618,43 @@ function onKeyDown( event ) { function onMouseDown( event ) { - if ( this.state === _STATE.NONE ) { + let mouseAction; - switch ( event.button ) { + switch ( event.button ) { - case this.mouseButtons.LEFT: - this.state = _STATE.ROTATE; - break; + case 0: + mouseAction = this.mouseButtons.LEFT; + break; + + case 1: + mouseAction = this.mouseButtons.MIDDLE; + break; - case this.mouseButtons.MIDDLE: - this.state = _STATE.ZOOM; - break; + case 2: + mouseAction = this.mouseButtons.RIGHT; + break; - case this.mouseButtons.RIGHT: - this.state = _STATE.PAN; - break; + default: + mouseAction = - 1; - } + } + + switch ( mouseAction ) { + + case MOUSE.DOLLY: + this.state = _STATE.ZOOM; + break; + + case MOUSE.ROTATE: + this.state = _STATE.ROTATE; + break; + + case MOUSE.PAN: + this.state = _STATE.PAN; + break; + + default: + this.state = _STATE.NONE; } diff --git a/examples/jsm/controls/TransformControls.js b/examples/jsm/controls/TransformControls.js index 38ee44ae6f322a..78dafca81304b0 100644 --- a/examples/jsm/controls/TransformControls.js +++ b/examples/jsm/controls/TransformControls.js @@ -1,6 +1,7 @@ import { BoxGeometry, BufferGeometry, + Controls, CylinderGeometry, DoubleSide, Euler, @@ -36,32 +37,22 @@ const _mouseDownEvent = { type: 'mouseDown', mode: null }; const _mouseUpEvent = { type: 'mouseUp', mode: null }; const _objectChangeEvent = { type: 'objectChange' }; -class TransformControls extends Object3D { +class TransformControls extends Controls { - constructor( camera, domElement ) { + constructor( camera, domElement = null ) { - super(); - - if ( domElement === undefined ) { - - console.warn( 'THREE.TransformControls: The second parameter "domElement" is now mandatory.' ); - domElement = document; + super( undefined, domElement ); - } + const root = new TransformControlsRoot( this ); + this._root = root; - this.isTransformControls = true; + const gizmo = new TransformControlsGizmo(); + this._gizmo = gizmo; + root.add( gizmo ); - this.visible = false; - this.domElement = domElement; - this.domElement.style.touchAction = 'none'; // disable touch scroll - - const _gizmo = new TransformControlsGizmo(); - this._gizmo = _gizmo; - this.add( _gizmo ); - - const _plane = new TransformControlsPlane(); - this._plane = _plane; - this.add( _plane ); + const plane = new TransformControlsPlane(); + this._plane = plane; + root.add( plane ); const scope = this; @@ -83,8 +74,8 @@ class TransformControls extends Object3D { if ( propValue !== value ) { propValue = value; - _plane[ propName ] = value; - _gizmo[ propName ] = value; + plane[ propName ] = value; + gizmo[ propName ] = value; scope.dispatchEvent( { type: propName + '-changed', value: value } ); scope.dispatchEvent( _changeEvent ); @@ -96,8 +87,8 @@ class TransformControls extends Object3D { } ); scope[ propName ] = defaultValue; - _plane[ propName ] = defaultValue; - _gizmo[ propName ] = defaultValue; + plane[ propName ] = defaultValue; + gizmo[ propName ] = defaultValue; } @@ -172,50 +163,38 @@ class TransformControls extends Object3D { this._onPointerMove = onPointerMove.bind( this ); this._onPointerUp = onPointerUp.bind( this ); - this.domElement.addEventListener( 'pointerdown', this._onPointerDown ); - this.domElement.addEventListener( 'pointermove', this._onPointerHover ); - this.domElement.addEventListener( 'pointerup', this._onPointerUp ); - - } - - // updateMatrixWorld updates key transformation variables - updateMatrixWorld( force ) { - - if ( this.object !== undefined ) { + if ( domElement !== null ) { - this.object.updateMatrixWorld(); - - if ( this.object.parent === null ) { - - console.error( 'TransformControls: The attached 3D object must be a part of the scene graph.' ); - - } else { + this.connect(); - this.object.parent.matrixWorld.decompose( this._parentPosition, this._parentQuaternion, this._parentScale ); + } - } + } - this.object.matrixWorld.decompose( this.worldPosition, this.worldQuaternion, this._worldScale ); + connect() { - this._parentQuaternionInv.copy( this._parentQuaternion ).invert(); - this._worldQuaternionInv.copy( this.worldQuaternion ).invert(); + this.domElement.addEventListener( 'pointerdown', this._onPointerDown ); + this.domElement.addEventListener( 'pointermove', this._onPointerHover ); + this.domElement.addEventListener( 'pointerup', this._onPointerUp ); - } + this.domElement.style.touchAction = 'none'; // disable touch scroll - this.camera.updateMatrixWorld(); - this.camera.matrixWorld.decompose( this.cameraPosition, this.cameraQuaternion, this._cameraScale ); + } - if ( this.camera.isOrthographicCamera ) { + disconnect() { - this.camera.getWorldDirection( this.eye ).negate(); + this.domElement.removeEventListener( 'pointerdown', this._onPointerDown ); + this.domElement.removeEventListener( 'pointermove', this._onPointerHover ); + this.domElement.removeEventListener( 'pointermove', this._onPointerMove ); + this.domElement.removeEventListener( 'pointerup', this._onPointerUp ); - } else { + this.domElement.style.touchAction = 'auto'; - this.eye.copy( this.cameraPosition ).sub( this.worldPosition ).normalize(); + } - } + getHelper() { - super.updateMatrixWorld( force ); + return this._root; } @@ -555,10 +534,7 @@ class TransformControls extends Object3D { dispose() { - this.domElement.removeEventListener( 'pointerdown', this._onPointerDown ); - this.domElement.removeEventListener( 'pointermove', this._onPointerHover ); - this.domElement.removeEventListener( 'pointermove', this._onPointerMove ); - this.domElement.removeEventListener( 'pointerup', this._onPointerUp ); + this.disconnect(); this.traverse( function ( child ) { @@ -573,7 +549,7 @@ class TransformControls extends Object3D { attach( object ) { this.object = object; - this.visible = true; + this._root.visible = true; return this; @@ -583,9 +559,10 @@ class TransformControls extends Object3D { detach() { this.object = undefined; - this.visible = false; this.axis = null; + this._root.visible = false; + return this; } @@ -778,6 +755,64 @@ const _v1 = new Vector3(); const _v2 = new Vector3(); const _v3 = new Vector3(); +class TransformControlsRoot extends Object3D { + + constructor( controls ) { + + super(); + + this.isTransformControlsRoot = true; + + this.controls = controls; + this.visible = false; + + } + + // updateMatrixWorld updates key transformation variables + updateMatrixWorld( force ) { + + const controls = this.controls; + + if ( controls.object !== undefined ) { + + controls.object.updateMatrixWorld(); + + if ( controls.object.parent === null ) { + + console.error( 'TransformControls: The attached 3D object must be a part of the scene graph.' ); + + } else { + + controls.object.parent.matrixWorld.decompose( controls._parentPosition, controls._parentQuaternion, controls._parentScale ); + + } + + controls.object.matrixWorld.decompose( controls.worldPosition, controls.worldQuaternion, controls._worldScale ); + + controls._parentQuaternionInv.copy( controls._parentQuaternion ).invert(); + controls._worldQuaternionInv.copy( controls.worldQuaternion ).invert(); + + } + + controls.camera.updateMatrixWorld(); + controls.camera.matrixWorld.decompose( controls.cameraPosition, controls.cameraQuaternion, controls._cameraScale ); + + if ( controls.camera.isOrthographicCamera ) { + + controls.camera.getWorldDirection( controls.eye ).negate(); + + } else { + + controls.eye.copy( controls.cameraPosition ).sub( controls.worldPosition ).normalize(); + + } + + super.updateMatrixWorld( force ); + + } + +} + class TransformControlsGizmo extends Object3D { constructor() { diff --git a/examples/jsm/exporters/DRACOExporter.js b/examples/jsm/exporters/DRACOExporter.js index 85a2e15adc4d6d..4b0a1a396e184a 100644 --- a/examples/jsm/exporters/DRACOExporter.js +++ b/examples/jsm/exporters/DRACOExporter.js @@ -1,4 +1,4 @@ -import { Color } from 'three'; +import { Color, ColorManagement, SRGBColorSpace } from 'three'; /** * Export draco compressed files from threejs geometry objects. @@ -227,7 +227,9 @@ function createVertexColorSRGBArray( attribute ) { for ( let i = 0, il = count; i < il; i ++ ) { - _color.fromBufferAttribute( attribute, i ).convertLinearToSRGB(); + _color.fromBufferAttribute( attribute, i ); + + ColorManagement.fromWorkingColorSpace( _color, SRGBColorSpace ); array[ i * itemSize ] = _color.r; array[ i * itemSize + 1 ] = _color.g; diff --git a/examples/jsm/exporters/EXRExporter.js b/examples/jsm/exporters/EXRExporter.js index bd1d8202d2d83d..950e2d1641490d 100644 --- a/examples/jsm/exporters/EXRExporter.js +++ b/examples/jsm/exporters/EXRExporter.js @@ -21,20 +21,20 @@ const ZIP_COMPRESSION = 3; class EXRExporter { - parse( arg1, arg2, arg3 ) { + async parse( arg1, arg2, arg3 ) { - if ( ! arg1 || ! ( arg1.isWebGLRenderer || arg1.isDataTexture ) ) { + if ( ! arg1 || ! ( arg1.isWebGLRenderer || arg1.isWebGPURenderer || arg1.isDataTexture ) ) { throw Error( 'EXRExporter.parse: Unsupported first parameter, expected instance of WebGLRenderer or DataTexture.' ); - } else if ( arg1.isWebGLRenderer ) { + } else if ( arg1.isWebGLRenderer || arg1.isWebGPURenderer ) { const renderer = arg1, renderTarget = arg2, options = arg3; supportedRTT( renderTarget ); const info = buildInfoRTT( renderTarget, options ), - dataBuffer = getPixelData( renderer, renderTarget, info ), + dataBuffer = await getPixelData( renderer, renderTarget, info ), rawContentBuffer = reorganizeDataBuffer( dataBuffer, info ), chunks = compressData( rawContentBuffer, info ); @@ -61,7 +61,7 @@ class EXRExporter { function supportedRTT( renderTarget ) { - if ( ! renderTarget || ! renderTarget.isWebGLRenderTarget ) { + if ( ! renderTarget || ! renderTarget.isRenderTarget ) { throw Error( 'EXRExporter.parse: Unsupported second parameter, expected instance of WebGLRenderTarget.' ); @@ -189,22 +189,30 @@ function buildInfoDT( texture, options = {} ) { } -function getPixelData( renderer, rtt, info ) { +async function getPixelData( renderer, rtt, info ) { let dataBuffer; - if ( info.type === FloatType ) { + if ( renderer.isWebGLRenderer ) { - dataBuffer = new Float32Array( info.width * info.height * info.numInputChannels ); + if ( info.type === FloatType ) { + + dataBuffer = new Float32Array( info.width * info.height * info.numInputChannels ); + + } else { + + dataBuffer = new Uint16Array( info.width * info.height * info.numInputChannels ); + + } + + await renderer.readRenderTargetPixelsAsync( rtt, 0, 0, info.width, info.height, dataBuffer ); } else { - dataBuffer = new Uint16Array( info.width * info.height * info.numInputChannels ); + dataBuffer = await renderer.readRenderTargetPixelsAsync( rtt, 0, 0, info.width, info.height ); } - renderer.readRenderTargetPixels( rtt, 0, 0, info.width, info.height, dataBuffer ); - return dataBuffer; } diff --git a/examples/jsm/exporters/KTX2Exporter.js b/examples/jsm/exporters/KTX2Exporter.js index bfc24d8dda08b2..e5b086a24529c4 100644 --- a/examples/jsm/exporters/KTX2Exporter.js +++ b/examples/jsm/exporters/KTX2Exporter.js @@ -111,7 +111,7 @@ const ERROR_COLOR_SPACE = 'THREE.KTX2Exporter: Supported color spaces are SRGBCo export class KTX2Exporter { - parse( arg1, arg2 ) { + async parse( arg1, arg2 ) { let texture; @@ -119,9 +119,9 @@ export class KTX2Exporter { texture = arg1; - } else if ( arg1.isWebGLRenderer && arg2.isWebGLRenderTarget ) { + } else if ( ( arg1.isWebGLRenderer || arg1.isWebGPURenderer ) && arg2.isRenderTarget ) { - texture = toDataTexture( arg1, arg2 ); + texture = await toDataTexture( arg1, arg2 ); } else { @@ -235,32 +235,40 @@ export class KTX2Exporter { } -function toDataTexture( renderer, rtt ) { +async function toDataTexture( renderer, rtt ) { const channelCount = getChannelCount( rtt.texture ); let view; - if ( rtt.texture.type === FloatType ) { + if ( renderer.isWebGLRenderer ) { - view = new Float32Array( rtt.width * rtt.height * channelCount ); + if ( rtt.texture.type === FloatType ) { - } else if ( rtt.texture.type === HalfFloatType ) { + view = new Float32Array( rtt.width * rtt.height * channelCount ); - view = new Uint16Array( rtt.width * rtt.height * channelCount ); + } else if ( rtt.texture.type === HalfFloatType ) { - } else if ( rtt.texture.type === UnsignedByteType ) { + view = new Uint16Array( rtt.width * rtt.height * channelCount ); - view = new Uint8Array( rtt.width * rtt.height * channelCount ); + } else if ( rtt.texture.type === UnsignedByteType ) { + + view = new Uint8Array( rtt.width * rtt.height * channelCount ); + + } else { + + throw new Error( ERROR_TYPE ); + + } + + await renderer.readRenderTargetPixelsAsync( rtt, 0, 0, rtt.width, rtt.height, view ); } else { - throw new Error( ERROR_TYPE ); + view = await renderer.readRenderTargetPixelsAsync( rtt, 0, 0, rtt.width, rtt.height ); } - renderer.readRenderTargetPixels( rtt, 0, 0, rtt.width, rtt.height, view ); - return new DataTexture( view, rtt.width, rtt.height, rtt.texture.format, rtt.texture.type ); } diff --git a/examples/jsm/exporters/OBJExporter.js b/examples/jsm/exporters/OBJExporter.js index 63a483e2b7c2e7..c49662700b9a1b 100644 --- a/examples/jsm/exporters/OBJExporter.js +++ b/examples/jsm/exporters/OBJExporter.js @@ -1,6 +1,8 @@ import { Color, + ColorManagement, Matrix3, + SRGBColorSpace, Vector2, Vector3 } from 'three'; @@ -226,7 +228,9 @@ class OBJExporter { if ( colors !== undefined ) { - color.fromBufferAttribute( colors, i ).convertLinearToSRGB(); + color.fromBufferAttribute( colors, i ); + + ColorManagement.fromWorkingColorSpace( color, SRGBColorSpace ); output += ' ' + color.r + ' ' + color.g + ' ' + color.b; diff --git a/examples/jsm/exporters/PLYExporter.js b/examples/jsm/exporters/PLYExporter.js index 2e46a8c45b5358..b96bb999e6c743 100644 --- a/examples/jsm/exporters/PLYExporter.js +++ b/examples/jsm/exporters/PLYExporter.js @@ -1,7 +1,9 @@ import { Matrix3, Vector3, - Color + Color, + ColorManagement, + SRGBColorSpace } from 'three'; /** @@ -302,9 +304,9 @@ class PLYExporter { if ( colors != null ) { - tempColor - .fromBufferAttribute( colors, i ) - .convertLinearToSRGB(); + tempColor.fromBufferAttribute( colors, i ); + + ColorManagement.fromWorkingColorSpace( tempColor, SRGBColorSpace ); output.setUint8( vOffset, Math.floor( tempColor.r * 255 ) ); vOffset += 1; @@ -461,9 +463,9 @@ class PLYExporter { if ( colors != null ) { - tempColor - .fromBufferAttribute( colors, i ) - .convertLinearToSRGB(); + tempColor.fromBufferAttribute( colors, i ); + + ColorManagement.fromWorkingColorSpace( tempColor, SRGBColorSpace ); line += ' ' + Math.floor( tempColor.r * 255 ) + ' ' + diff --git a/examples/jsm/geometries/DecalGeometry.js b/examples/jsm/geometries/DecalGeometry.js index 5e712f23c65bf0..d5782ac2a0b531 100644 --- a/examples/jsm/geometries/DecalGeometry.js +++ b/examples/jsm/geometries/DecalGeometry.js @@ -1,6 +1,7 @@ import { BufferGeometry, Float32BufferAttribute, + Matrix3, Matrix4, Vector3 } from 'three'; @@ -36,6 +37,8 @@ class DecalGeometry extends BufferGeometry { const plane = new Vector3(); + const normalMatrix = new Matrix3().getNormalMatrix( mesh.matrixWorld ); + // this matrix represents the transformation of the decal projector const projectorMatrix = new Matrix4(); @@ -146,7 +149,7 @@ class DecalGeometry extends BufferGeometry { vertex.applyMatrix4( mesh.matrixWorld ); vertex.applyMatrix4( projectorMatrixInverse ); - normal.transformDirection( mesh.matrixWorld ); + normal.applyNormalMatrix( normalMatrix ); decalVertices.push( new DecalVertex( vertex.clone(), normal.clone() ) ); diff --git a/examples/jsm/geometries/InstancedPointsGeometry.js b/examples/jsm/geometries/InstancedPointsGeometry.js index 081ab6b81af176..1238ad88391542 100644 --- a/examples/jsm/geometries/InstancedPointsGeometry.js +++ b/examples/jsm/geometries/InstancedPointsGeometry.js @@ -20,7 +20,7 @@ class InstancedPointsGeometry extends InstancedBufferGeometry { this.type = 'InstancedPointsGeometry'; const positions = [ - 1, 1, 0, 1, 1, 0, - 1, - 1, 0, 1, - 1, 0 ]; - const uvs = [ - 1, 1, 1, 1, - 1, - 1, 1, - 1 ]; + const uvs = [ 0, 1, 1, 1, 0, 0, 1, 0 ]; const index = [ 0, 2, 1, 2, 3, 1 ]; this.setIndex( index ); diff --git a/examples/jsm/geometries/SDFGeometryGenerator.js b/examples/jsm/geometries/SDFGeometryGenerator.js deleted file mode 100644 index e80c9a39ab1422..00000000000000 --- a/examples/jsm/geometries/SDFGeometryGenerator.js +++ /dev/null @@ -1,144 +0,0 @@ -/** - * @author santiago / @glitch_life - * wrapper of https://www.npmjs.com/package/isosurface by https://github.com/mikolalysenko - * - * Returns BufferGeometry from SDF - */ - -import { - BufferAttribute, - BufferGeometry, - FloatType, - Mesh, - OrthographicCamera, - PlaneGeometry, - Scene, - ShaderMaterial, - Vector2, - WebGLRenderTarget -} from 'three'; - -import { surfaceNet } from './../libs/surfaceNet.js'; - -class SDFGeometryGenerator { - - constructor( renderer ) { - - this.renderer = renderer; - - } - - generate( res = 64, distFunc = 'float dist( vec3 p ){ return length(p) - 0.5; }', bounds = 1 ) { - - let w, h; - if ( res == 8 ) [ w, h ] = [ 32, 16 ]; - else if ( res == 16 ) [ w, h ] = [ 64, 64 ]; - else if ( res == 32 ) [ w, h ] = [ 256, 128 ]; - else if ( res == 64 ) [ w, h ] = [ 512, 512 ]; - else if ( res == 128 ) [ w, h ] = [ 2048, 1024 ]; - else if ( res == 256 ) [ w, h ] = [ 4096, 4096 ]; - else if ( res == 512 ) [ w, h ] = [ 16384, 8096 ]; - else if ( res == 1024 ) [ w, h ] = [ 32768, 32768 ]; - else throw new Error( 'THREE.SDFGeometryGenerator: Resolution must be in range 8 < res < 1024 and must be ^2' ); - - const maxTexSize = this.renderer.capabilities.maxTextureSize; - - if ( w > maxTexSize || h > maxTexSize ) throw new Error( 'THREE.SDFGeometryGenerator: Your device does not support this resolution ( ' + res + ' ), decrease [res] param.' ); - - const [ tilesX, tilesY ] = [ ( w / res ), ( h / res ) ]; - - const sdfCompute = ` - varying vec2 vUv; - uniform float tileNum; - uniform float bounds; - [#dist#] - void main() { gl_FragColor=vec4( ( dist( vec3( vUv, tileNum ) * 2.0 * bounds - vec3( bounds ) ) < 0.00001 ) ? 1.0 : 0.0 ); } - `; - - const sdfRT = this.computeSDF( w, h, tilesX, tilesY, bounds, sdfCompute.replace( '[#dist#]', distFunc ) ); - - const read = new Float32Array( w * h * 4 ); - this.renderer.readRenderTargetPixels( sdfRT, 0, 0, w, h, read ); - sdfRT.dispose(); - - // - - const mesh = surfaceNet( [ res, res, res ], ( x, y, z ) => { - - x = ( x + bounds ) * ( res / ( bounds * 2 ) ); - y = ( y + bounds ) * ( res / ( bounds * 2 ) ); - z = ( z + bounds ) * ( res / ( bounds * 2 ) ); - let p = ( x + ( z % tilesX ) * res ) + y * w + ( Math.floor( z / tilesX ) * res * w ); - p *= 4; - return ( read[ p + 3 ] > 0 ) ? - 0.000000001 : 1; - - }, [[ - bounds, - bounds, - bounds ], [ bounds, bounds, bounds ]] ); - - const ps = [], ids = []; - const geometry = new BufferGeometry(); - mesh.positions.forEach( p => { - - ps.push( p[ 0 ], p[ 1 ], p[ 2 ] ); - - } ); - mesh.cells.forEach( p => ids.push( p[ 0 ], p[ 1 ], p[ 2 ] ) ); - geometry.setAttribute( 'position', new BufferAttribute( new Float32Array( ps ), 3 ) ); - geometry.setIndex( ids ); - - return geometry; - - } - - computeSDF( width, height, tilesX, tilesY, bounds, shader ) { - - const rt = new WebGLRenderTarget( width, height, { type: FloatType } ); - const scn = new Scene(); - const cam = new OrthographicCamera(); - const tiles = tilesX * tilesY; - let currentTile = 0; - - Object.assign( cam, { left: width / - 2, right: width / 2, top: height / 2, bottom: height / - 2 } ).updateProjectionMatrix(); - cam.position.z = 2; - - const tileSize = width / tilesX; - const geometry = new PlaneGeometry( tileSize, tileSize ); - - while ( currentTile ++ < tiles ) { - - const c = currentTile - 1; - const [ px, py ] = [ ( tileSize ) / 2 + ( c % tilesX ) * ( tileSize ) - width / 2, ( tileSize ) / 2 + Math.floor( c / tilesX ) * ( tileSize ) - height / 2 ]; - const compPlane = new Mesh( geometry, new ShaderMaterial( { - uniforms: { - res: { value: new Vector2( width, height ) }, - tileNum: { value: c / ( tilesX * tilesY - 1 ) }, - bounds: { value: bounds } - }, - vertexShader: 'varying vec2 vUv;void main(){vUv=uv;gl_Position=projectionMatrix*modelViewMatrix*vec4(position,1.0);}', - fragmentShader: shader - } ) ); - compPlane.position.set( px, py, 0 ); - scn.add( compPlane ); - - } - - this.renderer.setRenderTarget( rt ); - this.renderer.render( scn, cam ); - this.renderer.setRenderTarget( null ); - - // - - geometry.dispose(); - - scn.traverse( function ( object ) { - - if ( object.material !== undefined ) object.material.dispose(); - - } ); - - return rt; - - } - -} - -export { SDFGeometryGenerator }; diff --git a/examples/jsm/helpers/LightProbeHelper.js b/examples/jsm/helpers/LightProbeHelper.js index e8d1356fc20e24..d6fff3ef1732a1 100644 --- a/examples/jsm/helpers/LightProbeHelper.js +++ b/examples/jsm/helpers/LightProbeHelper.js @@ -6,7 +6,7 @@ import { class LightProbeHelper extends Mesh { - constructor( lightProbe, size ) { + constructor( lightProbe, size = 1 ) { const material = new ShaderMaterial( { diff --git a/examples/jsm/helpers/LightProbeHelperGPU.js b/examples/jsm/helpers/LightProbeHelperGPU.js new file mode 100644 index 00000000000000..c44df32acb1d2f --- /dev/null +++ b/examples/jsm/helpers/LightProbeHelperGPU.js @@ -0,0 +1,65 @@ +import { + Mesh, + NodeMaterial, + SphereGeometry +} from 'three'; +import { float, Fn, getShIrradianceAt, normalWorld, uniformArray, uniform, vec4 } from 'three/tsl'; + +class LightProbeHelper extends Mesh { + + constructor( lightProbe, size = 1 ) { + + const sh = uniformArray( lightProbe.sh.coefficients ); + const intensity = uniform( lightProbe.intensity ); + + const RECIPROCAL_PI = float( 1 / Math.PI ); + + const fragmentNode = Fn( () => { + + const irradiance = getShIrradianceAt( normalWorld, sh ); + + const outgoingLight = RECIPROCAL_PI.mul( irradiance ).mul( intensity ); + + return vec4( outgoingLight, 1.0 ); + + } )(); + + const material = new NodeMaterial(); + material.fragmentNode = fragmentNode; + + const geometry = new SphereGeometry( 1, 32, 16 ); + + super( geometry, material ); + + this.lightProbe = lightProbe; + this.size = size; + this.type = 'LightProbeHelper'; + + this._intensity = intensity; + this._sh = sh; + + this.onBeforeRender(); + + } + + dispose() { + + this.geometry.dispose(); + this.material.dispose(); + + } + + onBeforeRender() { + + this.position.copy( this.lightProbe.position ); + + this.scale.set( 1, 1, 1 ).multiplyScalar( this.size ); + + this._intensity.value = this.lightProbe.intensity; + this._sh.array = this.lightProbe.sh.coefficients; + + } + +} + +export { LightProbeHelper }; diff --git a/examples/jsm/libs/basis/basis_transcoder.js b/examples/jsm/libs/basis/basis_transcoder.js index 9e285ddc9515bd..6f02a4ac8504ea 100644 --- a/examples/jsm/libs/basis/basis_transcoder.js +++ b/examples/jsm/libs/basis/basis_transcoder.js @@ -1,21 +1,19 @@ -var BASIS = (function() { - var _scriptDir = typeof document !== 'undefined' && document.currentScript ? document.currentScript.src : undefined; - if (typeof __filename !== 'undefined') _scriptDir = _scriptDir || __filename; +var BASIS = (() => { + var _scriptName = typeof document != 'undefined' ? document.currentScript?.src : undefined; + if (typeof __filename != 'undefined') _scriptName ||= __filename; return ( -function(BASIS) { - BASIS = BASIS || {}; +function(moduleArg = {}) { + var moduleRtn; -var Module=typeof BASIS!=="undefined"?BASIS:{};var readyPromiseResolve,readyPromiseReject;Module["ready"]=new Promise(function(resolve,reject){readyPromiseResolve=resolve;readyPromiseReject=reject});var moduleOverrides={};var key;for(key in Module){if(Module.hasOwnProperty(key)){moduleOverrides[key]=Module[key]}}var arguments_=[];var thisProgram="./this.program";var quit_=function(status,toThrow){throw toThrow};var ENVIRONMENT_IS_WEB=false;var ENVIRONMENT_IS_WORKER=false;var ENVIRONMENT_IS_NODE=false;var ENVIRONMENT_IS_SHELL=false;ENVIRONMENT_IS_WEB=typeof window==="object";ENVIRONMENT_IS_WORKER=typeof importScripts==="function";ENVIRONMENT_IS_NODE=typeof process==="object"&&typeof process.versions==="object"&&typeof process.versions.node==="string";ENVIRONMENT_IS_SHELL=!ENVIRONMENT_IS_WEB&&!ENVIRONMENT_IS_NODE&&!ENVIRONMENT_IS_WORKER;var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var read_,readAsync,readBinary,setWindowTitle;var nodeFS;var nodePath;if(ENVIRONMENT_IS_NODE){if(ENVIRONMENT_IS_WORKER){scriptDirectory=require("path").dirname(scriptDirectory)+"/"}else{scriptDirectory=__dirname+"/"}read_=function shell_read(filename,binary){if(!nodeFS)nodeFS=require("fs");if(!nodePath)nodePath=require("path");filename=nodePath["normalize"](filename);return nodeFS["readFileSync"](filename,binary?null:"utf8")};readBinary=function readBinary(filename){var ret=read_(filename,true);if(!ret.buffer){ret=new Uint8Array(ret)}assert(ret.buffer);return ret};if(process["argv"].length>1){thisProgram=process["argv"][1].replace(/\\/g,"/")}arguments_=process["argv"].slice(2);process["on"]("uncaughtException",function(ex){if(!(ex instanceof ExitStatus)){throw ex}});process["on"]("unhandledRejection",abort);quit_=function(status){process["exit"](status)};Module["inspect"]=function(){return"[Emscripten Module object]"}}else if(ENVIRONMENT_IS_SHELL){if(typeof read!="undefined"){read_=function shell_read(f){return read(f)}}readBinary=function readBinary(f){var data;if(typeof readbuffer==="function"){return new Uint8Array(readbuffer(f))}data=read(f,"binary");assert(typeof data==="object");return data};if(typeof scriptArgs!="undefined"){arguments_=scriptArgs}else if(typeof arguments!="undefined"){arguments_=arguments}if(typeof quit==="function"){quit_=function(status){quit(status)}}if(typeof print!=="undefined"){if(typeof console==="undefined")console={};console.log=print;console.warn=console.error=typeof printErr!=="undefined"?printErr:print}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!=="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptDir){scriptDirectory=_scriptDir}if(scriptDirectory.indexOf("blob:")!==0){scriptDirectory=scriptDirectory.substr(0,scriptDirectory.lastIndexOf("/")+1)}else{scriptDirectory=""}{read_=function shell_read(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.send(null);return xhr.responseText};if(ENVIRONMENT_IS_WORKER){readBinary=function readBinary(url){var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=function readAsync(url,onload,onerror){var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=function xhr_onload(){if(xhr.status==200||xhr.status==0&&xhr.response){onload(xhr.response);return}onerror()};xhr.onerror=onerror;xhr.send(null)}}setWindowTitle=function(title){document.title=title}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.warn.bind(console);for(key in moduleOverrides){if(moduleOverrides.hasOwnProperty(key)){Module[key]=moduleOverrides[key]}}moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var tempRet0=0;var setTempRet0=function(value){tempRet0=value};var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var noExitRuntime;if(Module["noExitRuntime"])noExitRuntime=Module["noExitRuntime"];if(typeof WebAssembly!=="object"){abort("no native wasm support detected")}var wasmMemory;var ABORT=false;var EXITSTATUS;function assert(condition,text){if(!condition){abort("Assertion failed: "+text)}}var UTF8Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf8"):undefined;function UTF8ArrayToString(heap,idx,maxBytesToRead){var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heap[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heap.subarray&&UTF8Decoder){return UTF8Decoder.decode(heap.subarray(idx,endPtr))}else{var str="";while(idx>10,56320|ch&1023)}}}return str}function UTF8ToString(ptr,maxBytesToRead){return ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):""}function stringToUTF8Array(str,heap,outIdx,maxBytesToWrite){if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx}function stringToUTF8(str,outPtr,maxBytesToWrite){return stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite)}function lengthBytesUTF8(str){var len=0;for(var i=0;i=55296&&u<=57343)u=65536+((u&1023)<<10)|str.charCodeAt(++i)&1023;if(u<=127)++len;else if(u<=2047)len+=2;else if(u<=65535)len+=3;else len+=4}return len}var UTF16Decoder=typeof TextDecoder!=="undefined"?new TextDecoder("utf-16le"):undefined;function UTF16ToString(ptr,maxBytesToRead){var endPtr=ptr;var idx=endPtr>>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&HEAPU16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder){return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr))}else{var str="";for(var i=0;!(i>=maxBytesToRead/2);++i){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)break;str+=String.fromCharCode(codeUnit)}return str}}function stringToUTF16(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr}function lengthBytesUTF16(str){return str.length*2}function UTF32ToString(ptr,maxBytesToRead){var i=0;var str="";while(!(i>=maxBytesToRead/4)){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str}function stringToUTF32(str,outPtr,maxBytesToWrite){if(maxBytesToWrite===undefined){maxBytesToWrite=2147483647}if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr}function lengthBytesUTF32(str){var len=0;for(var i=0;i=55296&&codeUnit<=57343)++i;len+=4}return len}function alignUp(x,multiple){if(x%multiple>0){x+=multiple-x%multiple}return x}var buffer,HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateGlobalBufferAndViews(buf){buffer=buf;Module["HEAP8"]=HEAP8=new Int8Array(buf);Module["HEAP16"]=HEAP16=new Int16Array(buf);Module["HEAP32"]=HEAP32=new Int32Array(buf);Module["HEAPU8"]=HEAPU8=new Uint8Array(buf);Module["HEAPU16"]=HEAPU16=new Uint16Array(buf);Module["HEAPU32"]=HEAPU32=new Uint32Array(buf);Module["HEAPF32"]=HEAPF32=new Float32Array(buf);Module["HEAPF64"]=HEAPF64=new Float64Array(buf)}var INITIAL_MEMORY=Module["INITIAL_MEMORY"]||16777216;var wasmTable;var __ATPRERUN__=[];var __ATINIT__=[];var __ATMAIN__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function preMain(){callRuntimeCallbacks(__ATMAIN__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}}function removeRunDependency(id){runDependencies--;if(Module["monitorRunDependencies"]){Module["monitorRunDependencies"](runDependencies)}if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}Module["preloadedImages"]={};Module["preloadedAudios"]={};function abort(what){if(Module["onAbort"]){Module["onAbort"](what)}what+="";err(what);ABORT=true;EXITSTATUS=1;what="abort("+what+"). Build with -s ASSERTIONS=1 for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}function hasPrefix(str,prefix){return String.prototype.startsWith?str.startsWith(prefix):str.indexOf(prefix)===0}var dataURIPrefix="data:application/octet-stream;base64,";function isDataURI(filename){return hasPrefix(filename,dataURIPrefix)}var fileURIPrefix="file://";function isFileURI(filename){return hasPrefix(filename,fileURIPrefix)}var wasmBinaryFile="basis_transcoder.wasm";if(!isDataURI(wasmBinaryFile)){wasmBinaryFile=locateFile(wasmBinaryFile)}function getBinary(){try{if(wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(wasmBinaryFile)}else{throw"both async and sync fetching of the wasm failed"}}catch(err){abort(err)}}function getBinaryPromise(){if(!wasmBinary&&(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER)&&typeof fetch==="function"&&!isFileURI(wasmBinaryFile)){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){if(!response["ok"]){throw"failed to load wasm binary file at '"+wasmBinaryFile+"'"}return response["arrayBuffer"]()}).catch(function(){return getBinary()})}return Promise.resolve().then(getBinary)}function createWasm(){var info={"a":asmLibraryArg};function receiveInstance(instance,module){var exports=instance.exports;Module["asm"]=exports;wasmMemory=Module["asm"]["K"];updateGlobalBufferAndViews(wasmMemory.buffer);wasmTable=Module["asm"]["L"];removeRunDependency("wasm-instantiate")}addRunDependency("wasm-instantiate");function receiveInstantiatedSource(output){receiveInstance(output["instance"])}function instantiateArrayBuffer(receiver){return getBinaryPromise().then(function(binary){return WebAssembly.instantiate(binary,info)}).then(receiver,function(reason){err("failed to asynchronously prepare wasm: "+reason);abort(reason)})}function instantiateAsync(){if(!wasmBinary&&typeof WebAssembly.instantiateStreaming==="function"&&!isDataURI(wasmBinaryFile)&&!isFileURI(wasmBinaryFile)&&typeof fetch==="function"){return fetch(wasmBinaryFile,{credentials:"same-origin"}).then(function(response){var result=WebAssembly.instantiateStreaming(response,info);return result.then(receiveInstantiatedSource,function(reason){err("wasm streaming compile failed: "+reason);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(receiveInstantiatedSource)})})}else{return instantiateArrayBuffer(receiveInstantiatedSource)}}if(Module["instantiateWasm"]){try{var exports=Module["instantiateWasm"](info,receiveInstance);return exports}catch(e){err("Module.instantiateWasm callback failed with error: "+e);return false}}instantiateAsync().catch(readyPromiseReject);return{}}function callRuntimeCallbacks(callbacks){while(callbacks.length>0){var callback=callbacks.shift();if(typeof callback=="function"){callback(Module);continue}var func=callback.func;if(typeof func==="number"){if(callback.arg===undefined){wasmTable.get(func)()}else{wasmTable.get(func)(callback.arg)}}else{func(callback.arg===undefined?null:callback.arg)}}}var structRegistrations={};function runDestructors(destructors){while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}}function simpleReadValueFromPointer(pointer){return this["fromWireType"](HEAPU32[pointer>>2])}var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var char_0=48;var char_9=57;function makeLegalFunctionName(name){if(undefined===name){return"_unknown"}name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return"_"+name}else{return name}}function createNamedFunction(name,body){name=makeLegalFunctionName(name);return new Function("body","return function "+name+"() {\n"+' "use strict";'+" return body.apply(this, arguments);\n"+"};\n")(body)}function extendError(baseErrorType,errorName){var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return this.name+": "+this.message}};return errorClass}var InternalError=undefined;function throwInternalError(message){throw new InternalError(message)}function whenDependentTypesAreResolved(myTypes,dependentTypes,getTypeConverters){myTypes.forEach(function(type){typeDependencies[type]=dependentTypes});function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i>shift])},destructorFunction:null})}function ClassHandle_isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right}function shallowCopyInternalPointer(o){return{count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType}}function throwInstanceAlreadyDeleted(obj){function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")}var finalizationGroup=false;function detachFinalizer(handle){}function runDestructor($$){if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}}function releaseClassHandle($$){$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}}function attachFinalizer(handle){if("undefined"===typeof FinalizationGroup){attachFinalizer=function(handle){return handle};return handle}finalizationGroup=new FinalizationGroup(function(iter){for(var result=iter.next();!result.done;result=iter.next()){var $$=result.value;if(!$$.ptr){console.warn("object already deleted: "+$$.ptr)}else{releaseClassHandle($$)}}});attachFinalizer=function(handle){finalizationGroup.register(handle,handle.$$,handle.$$);return handle};detachFinalizer=function(handle){finalizationGroup.unregister(handle.$$)};return attachFinalizer(handle)}function ClassHandle_clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}}function ClassHandle_delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}}function ClassHandle_isDeleted(){return!this.$$.ptr}var delayFunction=undefined;var deletionQueue=[];function flushPendingDeletes(){while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}}function ClassHandle_deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}function init_ClassHandle(){ClassHandle.prototype["isAliasOf"]=ClassHandle_isAliasOf;ClassHandle.prototype["clone"]=ClassHandle_clone;ClassHandle.prototype["delete"]=ClassHandle_delete;ClassHandle.prototype["isDeleted"]=ClassHandle_isDeleted;ClassHandle.prototype["deleteLater"]=ClassHandle_deleteLater}function ClassHandle(){}var registeredPointers={};function ensureOverloadTable(proto,methodName,humanName){if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(){if(!proto[methodName].overloadTable.hasOwnProperty(arguments.length)){throwBindingError("Function '"+humanName+"' called with an invalid number of arguments ("+arguments.length+") - expects one of ("+proto[methodName].overloadTable+")!")}return proto[methodName].overloadTable[arguments.length].apply(this,arguments)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}}function exposePublicSymbol(name,value,numArguments){if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError("Cannot register public name '"+name+"' twice")}ensureOverloadTable(Module,name,name);if(Module.hasOwnProperty(numArguments)){throwBindingError("Cannot register multiple overloads of a function with the same number of arguments ("+numArguments+")!")}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;if(undefined!==numArguments){Module[name].numArguments=numArguments}}}function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}function upcastPointer(ptr,ptrClass,desiredClass){while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError("Expected null or instance of "+desiredClass.name+", got an instance of "+ptrClass.name)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr}function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}return 0}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError("Cannot convert argument of type "+(handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name)+" to parameter type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError("Cannot convert argument of type "+(handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name)+" to parameter type "+this.name)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,__emval_register(function(){clonedHandle["delete"]()}));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupporting sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError("null is not a valid "+this.name)}return 0}if(!handle.$$){throwBindingError('Cannot pass "'+_embind_repr(handle)+'" as a '+this.name)}if(!handle.$$.ptr){throwBindingError("Cannot pass deleted object as a pointer of type "+this.name)}if(handle.$$.ptrType.isConst){throwBindingError("Cannot convert argument of type "+handle.$$.ptrType.name+" to parameter type "+this.name)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function RegisteredPointer_getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr}function RegisteredPointer_destructor(ptr){if(this.rawDestructor){this.rawDestructor(ptr)}}function RegisteredPointer_deleteObject(handle){if(handle!==null){handle["delete"]()}}function downcastPointer(ptr,ptrClass,desiredClass){if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)}function getInheritedInstanceCount(){return Object.keys(registeredInstances).length}function getLiveInheritedInstances(){var rv=[];for(var k in registeredInstances){if(registeredInstances.hasOwnProperty(k)){rv.push(registeredInstances[k])}}return rv}function setDelayFunction(fn){delayFunction=fn;if(deletionQueue.length&&delayFunction){delayFunction(flushPendingDeletes)}}function init_embind(){Module["getInheritedInstanceCount"]=getInheritedInstanceCount;Module["getLiveInheritedInstances"]=getLiveInheritedInstances;Module["flushPendingDeletes"]=flushPendingDeletes;Module["setDelayFunction"]=setDelayFunction}var registeredInstances={};function getBasestPointer(class_,ptr){if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr}function getInheritedInstance(class_,ptr){ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]}function makeClassHandle(prototype,record){if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record}}))}function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr:ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}function init_RegisteredPointer(){RegisteredPointer.prototype.getPointee=RegisteredPointer_getPointee;RegisteredPointer.prototype.destructor=RegisteredPointer_destructor;RegisteredPointer.prototype["argPackAdvance"]=8;RegisteredPointer.prototype["readValueFromPointer"]=simpleReadValueFromPointer;RegisteredPointer.prototype["deleteObject"]=RegisteredPointer_deleteObject;RegisteredPointer.prototype["fromWireType"]=RegisteredPointer_fromWireType}function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this["toWireType"]=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this["toWireType"]=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this["toWireType"]=genericPointerToWireType}}function replacePublicSymbol(name,value,numArguments){if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistant public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}}function dynCallLegacy(sig,ptr,args){if(args&&args.length){return Module["dynCall_"+sig].apply(null,[ptr].concat(args))}return Module["dynCall_"+sig].call(null,ptr)}function dynCall(sig,ptr,args){if(sig.indexOf("j")!=-1){return dynCallLegacy(sig,ptr,args)}return wasmTable.get(ptr).apply(null,args)}function getDynCaller(sig,ptr){assert(sig.indexOf("j")>=0,"getDynCaller should only be called with i64 sigs");var argCache=[];return function(){argCache.length=arguments.length;for(var i=0;i>2)+i])}return array}function __embind_register_class_constructor(rawClassType,argCount,rawArgTypesAddr,invokerSignature,invoker,rawConstructor){assert(argCount>0);var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);var args=[rawConstructor];var destructors=[];whenDependentTypesAreResolved([],[rawClassType],function(classType){classType=classType[0];var humanName="constructor "+classType.name;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError("Cannot register multiple constructors with identical number of parameters ("+(argCount-1)+") for class '"+classType.name+"'! Overload resolution is currently only performed using the parameter count, not actual type info!")}classType.registeredClass.constructor_body[argCount-1]=function unboundTypeHandler(){throwUnboundTypeError("Cannot construct "+classType.name+" due to unbound types",rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,function(argTypes){classType.registeredClass.constructor_body[argCount-1]=function constructor_body(){if(arguments.length!==argCount-1){throwBindingError(humanName+" called with "+arguments.length+" arguments, expected "+(argCount-1))}destructors.length=0;args.length=argCount;for(var i=1;i0?", ":"")+argsListWired}invokerFnBody+=(returns?"var rv = ":"")+"invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n";if(needsDestructorStack){invokerFnBody+="runDestructors(destructors);\n"}else{for(var i=isClassMethodFunc?1:2;i4&&0===--emval_handle_array[handle].refcount){emval_handle_array[handle]=undefined;emval_free_list.push(handle)}}function count_emval_handles(){var count=0;for(var i=5;i>1])};case 2:return function(pointer){var heap=signed?HEAP32:HEAPU32;return this["fromWireType"](heap[pointer>>2])};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_enum(rawType,name,size,isSigned){var shift=getShiftFromSize(size);name=readLatin1String(name);function ctor(){}ctor.values={};registerType(rawType,{name:name,constructor:ctor,"fromWireType":function(c){return this.constructor.values[c]},"toWireType":function(destructors,c){return c.value},"argPackAdvance":8,"readValueFromPointer":enumReadValueFromPointer(name,shift,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor)}function requireRegisteredType(rawType,humanName){var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(humanName+" has unknown type "+getTypeName(rawType))}return impl}function __embind_register_enum_value(rawEnumType,name,enumValue){var enumType=requireRegisteredType(rawEnumType,"enum");name=readLatin1String(name);var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(enumType.name+"_"+name,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value}function _embind_repr(v){if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}}function floatReadValueFromPointer(name,shift){switch(shift){case 2:return function(pointer){return this["fromWireType"](HEAPF32[pointer>>2])};case 3:return function(pointer){return this["fromWireType"](HEAPF64[pointer>>3])};default:throw new TypeError("Unknown float type: "+name)}}function __embind_register_float(rawType,name,size){var shift=getShiftFromSize(size);name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":function(value){return value},"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}return value},"argPackAdvance":8,"readValueFromPointer":floatReadValueFromPointer(name,shift),destructorFunction:null})}function __embind_register_function(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn){var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=readLatin1String(name);rawInvoker=embind__requireFunction(signature,rawInvoker);exposePublicSymbol(name,function(){throwUnboundTypeError("Cannot call "+name+" due to unbound types",argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,function(argTypes){var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn),argCount-1);return[]})}function integerReadValueFromPointer(name,shift,signed){switch(shift){case 0:return signed?function readS8FromPointer(pointer){return HEAP8[pointer]}:function readU8FromPointer(pointer){return HEAPU8[pointer]};case 1:return signed?function readS16FromPointer(pointer){return HEAP16[pointer>>1]}:function readU16FromPointer(pointer){return HEAPU16[pointer>>1]};case 2:return signed?function readS32FromPointer(pointer){return HEAP32[pointer>>2]}:function readU32FromPointer(pointer){return HEAPU32[pointer>>2]};default:throw new TypeError("Unknown integer type: "+name)}}function __embind_register_integer(primitiveType,name,size,minRange,maxRange){name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var shift=getShiftFromSize(size);var fromWireType=function(value){return value};if(minRange===0){var bitshift=32-8*size;fromWireType=function(value){return value<>>bitshift}}var isUnsignedType=name.indexOf("unsigned")!=-1;registerType(primitiveType,{name:name,"fromWireType":fromWireType,"toWireType":function(destructors,value){if(typeof value!=="number"&&typeof value!=="boolean"){throw new TypeError('Cannot convert "'+_embind_repr(value)+'" to '+this.name)}if(valuemaxRange){throw new TypeError('Passing a number "'+_embind_repr(value)+'" from JS side to C/C++ side to an argument of type "'+name+'", which is outside the valid range ['+minRange+", "+maxRange+"]!")}return isUnsignedType?value>>>0:value|0},"argPackAdvance":8,"readValueFromPointer":integerReadValueFromPointer(name,shift,minRange!==0),destructorFunction:null})}function __embind_register_memory_view(rawType,dataTypeIndex,name){var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){handle=handle>>2;var heap=HEAPU32;var size=heap[handle];var data=heap[handle+1];return new TA(buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name:name,"fromWireType":decodeMemoryView,"argPackAdvance":8,"readValueFromPointer":decodeMemoryView},{ignoreDuplicateRegistrations:true})}function __embind_register_std_string(rawType,name){name=readLatin1String(name);var stdStringIsUTF8=name==="std::string";registerType(rawType,{name:name,"fromWireType":function(value){var length=HEAPU32[value>>2];var str;if(stdStringIsUTF8){var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i;if(i==length||HEAPU8[currentBytePtr]==0){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr+4,length+1)}else{if(valueIsOfTypeString){for(var i=0;i255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+4+i]=charCode}}else{for(var i=0;i>2];var HEAP=getHeap();var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(i==length||HEAP[currentBytePtr>>shift]==0){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},"toWireType":function(destructors,value){if(!(typeof value==="string")){throwBindingError("Cannot pass non-string to C++ string type "+name)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length>>shift;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},"argPackAdvance":8,"readValueFromPointer":simpleReadValueFromPointer,destructorFunction:function(ptr){_free(ptr)}})}function __embind_register_value_object(rawType,name,constructorSignature,rawConstructor,destructorSignature,rawDestructor){structRegistrations[rawType]={name:readLatin1String(name),rawConstructor:embind__requireFunction(constructorSignature,rawConstructor),rawDestructor:embind__requireFunction(destructorSignature,rawDestructor),fields:[]}}function __embind_register_value_object_field(structType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext){structRegistrations[structType].fields.push({fieldName:readLatin1String(fieldName),getterReturnType:getterReturnType,getter:embind__requireFunction(getterSignature,getter),getterContext:getterContext,setterArgumentType:setterArgumentType,setter:embind__requireFunction(setterSignature,setter),setterContext:setterContext})}function __embind_register_void(rawType,name){name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,"argPackAdvance":0,"fromWireType":function(){return undefined},"toWireType":function(destructors,o){return undefined}})}function requireHandle(handle){if(!handle){throwBindingError("Cannot use deleted val. handle = "+handle)}return emval_handle_array[handle].value}function __emval_as(handle,returnType,destructorsRef){handle=requireHandle(handle);returnType=requireRegisteredType(returnType,"emval::as");var destructors=[];var rd=__emval_register(destructors);HEAP32[destructorsRef>>2]=rd;return returnType["toWireType"](destructors,handle)}var emval_symbols={};function getStringOrSymbol(address){var symbol=emval_symbols[address];if(symbol===undefined){return readLatin1String(address)}else{return symbol}}var emval_methodCallers=[];function __emval_call_void_method(caller,handle,methodName,args){caller=emval_methodCallers[caller];handle=requireHandle(handle);methodName=getStringOrSymbol(methodName);caller(handle,methodName,null,args)}function emval_get_global(){if(typeof globalThis==="object"){return globalThis}return function(){return Function}()("return this")()}function __emval_get_global(name){if(name===0){return __emval_register(emval_get_global())}else{name=getStringOrSymbol(name);return __emval_register(emval_get_global()[name])}}function __emval_addMethodCaller(caller){var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id}function __emval_lookupTypes(argCount,argTypes){var a=new Array(argCount);for(var i=0;i>2)+i],"parameter "+i)}return a}function __emval_get_method_caller(argCount,argTypes){var types=__emval_lookupTypes(argCount,argTypes);var retType=types[0];var signatureName=retType.name+"_$"+types.slice(1).map(function(t){return t.name}).join("_")+"$";var params=["retType"];var args=[retType];var argsList="";for(var i=0;i4){emval_handle_array[handle].refcount+=1}}function craftEmvalAllocator(argCount){var argsList="";for(var i=0;i>> 2) + "+i+'], "parameter '+i+'");\n'+"var arg"+i+" = argType"+i+".readValueFromPointer(args);\n"+"args += argType"+i+"['argPackAdvance'];\n"}functionBody+="var obj = new constructor("+argsList+");\n"+"return __emval_register(obj);\n"+"}\n";return new Function("requireRegisteredType","Module","__emval_register",functionBody)(requireRegisteredType,Module,__emval_register)}var emval_newers={};function __emval_new(handle,argCount,argTypes,args){handle=requireHandle(handle);var newer=emval_newers[argCount];if(!newer){newer=craftEmvalAllocator(argCount);emval_newers[argCount]=newer}return newer(handle,argTypes,args)}function __emval_new_cstring(v){return __emval_register(getStringOrSymbol(v))}function __emval_run_destructors(handle){var destructors=emval_handle_array[handle].value;runDestructors(destructors);__emval_decref(handle)}function _abort(){abort()}function _emscripten_memcpy_big(dest,src,num){HEAPU8.copyWithin(dest,src,src+num)}function _emscripten_get_heap_size(){return HEAPU8.length}function emscripten_realloc_buffer(size){try{wasmMemory.grow(size-buffer.byteLength+65535>>>16);updateGlobalBufferAndViews(wasmMemory.buffer);return 1}catch(e){}}function _emscripten_resize_heap(requestedSize){requestedSize=requestedSize>>>0;var oldSize=_emscripten_get_heap_size();var maxHeapSize=2147483648;if(requestedSize>maxHeapSize){return false}var minHeapSize=16777216;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(minHeapSize,requestedSize,overGrownHeapSize),65536));var replacement=emscripten_realloc_buffer(newSize);if(replacement){return true}}return false}var SYSCALLS={mappings:{},buffers:[null,[],[]],printChar:function(stream,curr){var buffer=SYSCALLS.buffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}},varargs:undefined,get:function(){SYSCALLS.varargs+=4;var ret=HEAP32[SYSCALLS.varargs-4>>2];return ret},getStr:function(ptr){var ret=UTF8ToString(ptr);return ret},get64:function(low,high){return low}};function _fd_close(fd){return 0}function _fd_seek(fd,offset_low,offset_high,whence,newOffset){}function _fd_write(fd,iov,iovcnt,pnum){var num=0;for(var i=0;i>2];var len=HEAP32[iov+(i*8+4)>>2];for(var j=0;j>2]=num;return 0}function _setTempRet0($i){setTempRet0($i|0)}InternalError=Module["InternalError"]=extendError(Error,"InternalError");embind_init_charCodes();BindingError=Module["BindingError"]=extendError(Error,"BindingError");init_ClassHandle();init_RegisteredPointer();init_embind();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");init_emval();__ATINIT__.push({func:function(){___wasm_call_ctors()}});var asmLibraryArg={"t":__embind_finalize_value_object,"I":__embind_register_bool,"x":__embind_register_class,"w":__embind_register_class_constructor,"d":__embind_register_class_function,"k":__embind_register_constant,"H":__embind_register_emval,"n":__embind_register_enum,"a":__embind_register_enum_value,"A":__embind_register_float,"i":__embind_register_function,"j":__embind_register_integer,"h":__embind_register_memory_view,"B":__embind_register_std_string,"v":__embind_register_std_wstring,"u":__embind_register_value_object,"c":__embind_register_value_object_field,"J":__embind_register_void,"m":__emval_as,"s":__emval_call_void_method,"b":__emval_decref,"y":__emval_get_global,"p":__emval_get_method_caller,"r":__emval_get_module_property,"e":__emval_get_property,"g":__emval_incref,"q":__emval_new,"f":__emval_new_cstring,"l":__emval_run_destructors,"o":_abort,"E":_emscripten_memcpy_big,"F":_emscripten_resize_heap,"G":_fd_close,"C":_fd_seek,"z":_fd_write,"D":_setTempRet0};var asm=createWasm();var ___wasm_call_ctors=Module["___wasm_call_ctors"]=function(){return(___wasm_call_ctors=Module["___wasm_call_ctors"]=Module["asm"]["M"]).apply(null,arguments)};var _malloc=Module["_malloc"]=function(){return(_malloc=Module["_malloc"]=Module["asm"]["N"]).apply(null,arguments)};var _free=Module["_free"]=function(){return(_free=Module["_free"]=Module["asm"]["O"]).apply(null,arguments)};var ___getTypeName=Module["___getTypeName"]=function(){return(___getTypeName=Module["___getTypeName"]=Module["asm"]["P"]).apply(null,arguments)};var ___embind_register_native_and_builtin_types=Module["___embind_register_native_and_builtin_types"]=function(){return(___embind_register_native_and_builtin_types=Module["___embind_register_native_and_builtin_types"]=Module["asm"]["Q"]).apply(null,arguments)};var dynCall_jiji=Module["dynCall_jiji"]=function(){return(dynCall_jiji=Module["dynCall_jiji"]=Module["asm"]["R"]).apply(null,arguments)};var calledRun;function ExitStatus(status){this.name="ExitStatus";this.message="Program terminated with exit("+status+")";this.status=status}dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(args){args=args||arguments_;if(runDependencies>0){return}preRun();if(runDependencies>0)return;function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();preMain();readyPromiseResolve(Module);if(Module["onRuntimeInitialized"])Module["onRuntimeInitialized"]();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}Module["run"]=run;if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}noExitRuntime=true;run(); +var Module=moduleArg;var readyPromiseResolve,readyPromiseReject;var readyPromise=new Promise((resolve,reject)=>{readyPromiseResolve=resolve;readyPromiseReject=reject});var ENVIRONMENT_IS_WEB=typeof window=="object";var ENVIRONMENT_IS_WORKER=typeof importScripts=="function";var ENVIRONMENT_IS_NODE=typeof process=="object"&&typeof process.versions=="object"&&typeof process.versions.node=="string";if(ENVIRONMENT_IS_NODE){}var moduleOverrides=Object.assign({},Module);var arguments_=[];var thisProgram="./this.program";var quit_=(status,toThrow)=>{throw toThrow};var scriptDirectory="";function locateFile(path){if(Module["locateFile"]){return Module["locateFile"](path,scriptDirectory)}return scriptDirectory+path}var readAsync,readBinary;if(ENVIRONMENT_IS_NODE){var fs=require("fs");var nodePath=require("path");scriptDirectory=__dirname+"/";readBinary=filename=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);var ret=fs.readFileSync(filename);return ret};readAsync=(filename,binary=true)=>{filename=isFileURI(filename)?new URL(filename):nodePath.normalize(filename);return new Promise((resolve,reject)=>{fs.readFile(filename,binary?undefined:"utf8",(err,data)=>{if(err)reject(err);else resolve(binary?data.buffer:data)})})};if(!Module["thisProgram"]&&process.argv.length>1){thisProgram=process.argv[1].replace(/\\/g,"/")}arguments_=process.argv.slice(2);quit_=(status,toThrow)=>{process.exitCode=status;throw toThrow}}else if(ENVIRONMENT_IS_WEB||ENVIRONMENT_IS_WORKER){if(ENVIRONMENT_IS_WORKER){scriptDirectory=self.location.href}else if(typeof document!="undefined"&&document.currentScript){scriptDirectory=document.currentScript.src}if(_scriptName){scriptDirectory=_scriptName}if(scriptDirectory.startsWith("blob:")){scriptDirectory=""}else{scriptDirectory=scriptDirectory.substr(0,scriptDirectory.replace(/[?#].*/,"").lastIndexOf("/")+1)}{if(ENVIRONMENT_IS_WORKER){readBinary=url=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,false);xhr.responseType="arraybuffer";xhr.send(null);return new Uint8Array(xhr.response)}}readAsync=url=>{if(isFileURI(url)){return new Promise((reject,resolve)=>{var xhr=new XMLHttpRequest;xhr.open("GET",url,true);xhr.responseType="arraybuffer";xhr.onload=()=>{if(xhr.status==200||xhr.status==0&&xhr.response){resolve(xhr.response)}reject(xhr.status)};xhr.onerror=reject;xhr.send(null)})}return fetch(url,{credentials:"same-origin"}).then(response=>{if(response.ok){return response.arrayBuffer()}return Promise.reject(new Error(response.status+" : "+response.url))})}}}else{}var out=Module["print"]||console.log.bind(console);var err=Module["printErr"]||console.error.bind(console);Object.assign(Module,moduleOverrides);moduleOverrides=null;if(Module["arguments"])arguments_=Module["arguments"];if(Module["thisProgram"])thisProgram=Module["thisProgram"];if(Module["quit"])quit_=Module["quit"];var wasmBinary;if(Module["wasmBinary"])wasmBinary=Module["wasmBinary"];var wasmMemory;var ABORT=false;var EXITSTATUS;var HEAP8,HEAPU8,HEAP16,HEAPU16,HEAP32,HEAPU32,HEAPF32,HEAPF64;function updateMemoryViews(){var b=wasmMemory.buffer;Module["HEAP8"]=HEAP8=new Int8Array(b);Module["HEAP16"]=HEAP16=new Int16Array(b);Module["HEAPU8"]=HEAPU8=new Uint8Array(b);Module["HEAPU16"]=HEAPU16=new Uint16Array(b);Module["HEAP32"]=HEAP32=new Int32Array(b);Module["HEAPU32"]=HEAPU32=new Uint32Array(b);Module["HEAPF32"]=HEAPF32=new Float32Array(b);Module["HEAPF64"]=HEAPF64=new Float64Array(b)}var __ATPRERUN__=[];var __ATINIT__=[];var __ATPOSTRUN__=[];var runtimeInitialized=false;function preRun(){if(Module["preRun"]){if(typeof Module["preRun"]=="function")Module["preRun"]=[Module["preRun"]];while(Module["preRun"].length){addOnPreRun(Module["preRun"].shift())}}callRuntimeCallbacks(__ATPRERUN__)}function initRuntime(){runtimeInitialized=true;callRuntimeCallbacks(__ATINIT__)}function postRun(){if(Module["postRun"]){if(typeof Module["postRun"]=="function")Module["postRun"]=[Module["postRun"]];while(Module["postRun"].length){addOnPostRun(Module["postRun"].shift())}}callRuntimeCallbacks(__ATPOSTRUN__)}function addOnPreRun(cb){__ATPRERUN__.unshift(cb)}function addOnInit(cb){__ATINIT__.unshift(cb)}function addOnPostRun(cb){__ATPOSTRUN__.unshift(cb)}var runDependencies=0;var runDependencyWatcher=null;var dependenciesFulfilled=null;function addRunDependency(id){runDependencies++;Module["monitorRunDependencies"]?.(runDependencies)}function removeRunDependency(id){runDependencies--;Module["monitorRunDependencies"]?.(runDependencies);if(runDependencies==0){if(runDependencyWatcher!==null){clearInterval(runDependencyWatcher);runDependencyWatcher=null}if(dependenciesFulfilled){var callback=dependenciesFulfilled;dependenciesFulfilled=null;callback()}}}function abort(what){Module["onAbort"]?.(what);what="Aborted("+what+")";err(what);ABORT=true;EXITSTATUS=1;what+=". Build with -sASSERTIONS for more info.";var e=new WebAssembly.RuntimeError(what);readyPromiseReject(e);throw e}var dataURIPrefix="data:application/octet-stream;base64,";var isDataURI=filename=>filename.startsWith(dataURIPrefix);var isFileURI=filename=>filename.startsWith("file://");function findWasmBinary(){var f="basis_transcoder.wasm";if(!isDataURI(f)){return locateFile(f)}return f}var wasmBinaryFile;function getBinarySync(file){if(file==wasmBinaryFile&&wasmBinary){return new Uint8Array(wasmBinary)}if(readBinary){return readBinary(file)}throw"both async and sync fetching of the wasm failed"}function getBinaryPromise(binaryFile){if(!wasmBinary){return readAsync(binaryFile).then(response=>new Uint8Array(response),()=>getBinarySync(binaryFile))}return Promise.resolve().then(()=>getBinarySync(binaryFile))}function instantiateArrayBuffer(binaryFile,imports,receiver){return getBinaryPromise(binaryFile).then(binary=>WebAssembly.instantiate(binary,imports)).then(receiver,reason=>{err(`failed to asynchronously prepare wasm: ${reason}`);abort(reason)})}function instantiateAsync(binary,binaryFile,imports,callback){if(!binary&&typeof WebAssembly.instantiateStreaming=="function"&&!isDataURI(binaryFile)&&!isFileURI(binaryFile)&&!ENVIRONMENT_IS_NODE&&typeof fetch=="function"){return fetch(binaryFile,{credentials:"same-origin"}).then(response=>{var result=WebAssembly.instantiateStreaming(response,imports);return result.then(callback,function(reason){err(`wasm streaming compile failed: ${reason}`);err("falling back to ArrayBuffer instantiation");return instantiateArrayBuffer(binaryFile,imports,callback)})})}return instantiateArrayBuffer(binaryFile,imports,callback)}function getWasmImports(){return{a:wasmImports}}function createWasm(){var info=getWasmImports();function receiveInstance(instance,module){wasmExports=instance.exports;wasmMemory=wasmExports["L"];updateMemoryViews();wasmTable=wasmExports["P"];addOnInit(wasmExports["M"]);removeRunDependency("wasm-instantiate");return wasmExports}addRunDependency("wasm-instantiate");function receiveInstantiationResult(result){receiveInstance(result["instance"])}if(Module["instantiateWasm"]){try{return Module["instantiateWasm"](info,receiveInstance)}catch(e){err(`Module.instantiateWasm callback failed with error: ${e}`);readyPromiseReject(e)}}if(!wasmBinaryFile)wasmBinaryFile=findWasmBinary();instantiateAsync(wasmBinary,wasmBinaryFile,info,receiveInstantiationResult).catch(readyPromiseReject);return{}}var callRuntimeCallbacks=callbacks=>{while(callbacks.length>0){callbacks.shift()(Module)}};var noExitRuntime=Module["noExitRuntime"]||true;class ExceptionInfo{constructor(excPtr){this.excPtr=excPtr;this.ptr=excPtr-24}set_type(type){HEAPU32[this.ptr+4>>2]=type}get_type(){return HEAPU32[this.ptr+4>>2]}set_destructor(destructor){HEAPU32[this.ptr+8>>2]=destructor}get_destructor(){return HEAPU32[this.ptr+8>>2]}set_caught(caught){caught=caught?1:0;HEAP8[this.ptr+12]=caught}get_caught(){return HEAP8[this.ptr+12]!=0}set_rethrown(rethrown){rethrown=rethrown?1:0;HEAP8[this.ptr+13]=rethrown}get_rethrown(){return HEAP8[this.ptr+13]!=0}init(type,destructor){this.set_adjusted_ptr(0);this.set_type(type);this.set_destructor(destructor)}set_adjusted_ptr(adjustedPtr){HEAPU32[this.ptr+16>>2]=adjustedPtr}get_adjusted_ptr(){return HEAPU32[this.ptr+16>>2]}get_exception_ptr(){var isPointer=___cxa_is_pointer_type(this.get_type());if(isPointer){return HEAPU32[this.excPtr>>2]}var adjusted=this.get_adjusted_ptr();if(adjusted!==0)return adjusted;return this.excPtr}}var exceptionLast=0;var uncaughtExceptionCount=0;var ___cxa_throw=(ptr,type,destructor)=>{var info=new ExceptionInfo(ptr);info.init(type,destructor);exceptionLast=ptr;uncaughtExceptionCount++;throw exceptionLast};var __abort_js=()=>{abort("")};var structRegistrations={};var runDestructors=destructors=>{while(destructors.length){var ptr=destructors.pop();var del=destructors.pop();del(ptr)}};function readPointer(pointer){return this["fromWireType"](HEAPU32[pointer>>2])}var awaitingDependencies={};var registeredTypes={};var typeDependencies={};var InternalError;var throwInternalError=message=>{throw new InternalError(message)};var whenDependentTypesAreResolved=(myTypes,dependentTypes,getTypeConverters)=>{myTypes.forEach(function(type){typeDependencies[type]=dependentTypes});function onComplete(typeConverters){var myTypeConverters=getTypeConverters(typeConverters);if(myTypeConverters.length!==myTypes.length){throwInternalError("Mismatched type converter count")}for(var i=0;i{if(registeredTypes.hasOwnProperty(dt)){typeConverters[i]=registeredTypes[dt]}else{unregisteredTypes.push(dt);if(!awaitingDependencies.hasOwnProperty(dt)){awaitingDependencies[dt]=[]}awaitingDependencies[dt].push(()=>{typeConverters[i]=registeredTypes[dt];++registered;if(registered===unregisteredTypes.length){onComplete(typeConverters)}})}});if(0===unregisteredTypes.length){onComplete(typeConverters)}};var __embind_finalize_value_object=structType=>{var reg=structRegistrations[structType];delete structRegistrations[structType];var rawConstructor=reg.rawConstructor;var rawDestructor=reg.rawDestructor;var fieldRecords=reg.fields;var fieldTypes=fieldRecords.map(field=>field.getterReturnType).concat(fieldRecords.map(field=>field.setterArgumentType));whenDependentTypesAreResolved([structType],fieldTypes,fieldTypes=>{var fields={};fieldRecords.forEach((field,i)=>{var fieldName=field.fieldName;var getterReturnType=fieldTypes[i];var getter=field.getter;var getterContext=field.getterContext;var setterArgumentType=fieldTypes[i+fieldRecords.length];var setter=field.setter;var setterContext=field.setterContext;fields[fieldName]={read:ptr=>getterReturnType["fromWireType"](getter(getterContext,ptr)),write:(ptr,o)=>{var destructors=[];setter(setterContext,ptr,setterArgumentType["toWireType"](destructors,o));runDestructors(destructors)}}});return[{name:reg.name,fromWireType:ptr=>{var rv={};for(var i in fields){rv[i]=fields[i].read(ptr)}rawDestructor(ptr);return rv},toWireType:(destructors,o)=>{for(var fieldName in fields){if(!(fieldName in o)){throw new TypeError(`Missing field: "${fieldName}"`)}}var ptr=rawConstructor();for(fieldName in fields){fields[fieldName].write(ptr,o[fieldName])}if(destructors!==null){destructors.push(rawDestructor,ptr)}return ptr},argPackAdvance:GenericWireTypeSize,readValueFromPointer:readPointer,destructorFunction:rawDestructor}]})};var __embind_register_bigint=(primitiveType,name,size,minRange,maxRange)=>{};var embind_init_charCodes=()=>{var codes=new Array(256);for(var i=0;i<256;++i){codes[i]=String.fromCharCode(i)}embind_charCodes=codes};var embind_charCodes;var readLatin1String=ptr=>{var ret="";var c=ptr;while(HEAPU8[c]){ret+=embind_charCodes[HEAPU8[c++]]}return ret};var BindingError;var throwBindingError=message=>{throw new BindingError(message)};function sharedRegisterType(rawType,registeredInstance,options={}){var name=registeredInstance.name;if(!rawType){throwBindingError(`type "${name}" must have a positive integer typeid pointer`)}if(registeredTypes.hasOwnProperty(rawType)){if(options.ignoreDuplicateRegistrations){return}else{throwBindingError(`Cannot register type '${name}' twice`)}}registeredTypes[rawType]=registeredInstance;delete typeDependencies[rawType];if(awaitingDependencies.hasOwnProperty(rawType)){var callbacks=awaitingDependencies[rawType];delete awaitingDependencies[rawType];callbacks.forEach(cb=>cb())}}function registerType(rawType,registeredInstance,options={}){if(!("argPackAdvance"in registeredInstance)){throw new TypeError("registerType registeredInstance requires argPackAdvance")}return sharedRegisterType(rawType,registeredInstance,options)}var GenericWireTypeSize=8;var __embind_register_bool=(rawType,name,trueValue,falseValue)=>{name=readLatin1String(name);registerType(rawType,{name:name,fromWireType:function(wt){return!!wt},toWireType:function(destructors,o){return o?trueValue:falseValue},argPackAdvance:GenericWireTypeSize,readValueFromPointer:function(pointer){return this["fromWireType"](HEAPU8[pointer])},destructorFunction:null})};var shallowCopyInternalPointer=o=>({count:o.count,deleteScheduled:o.deleteScheduled,preservePointerOnDelete:o.preservePointerOnDelete,ptr:o.ptr,ptrType:o.ptrType,smartPtr:o.smartPtr,smartPtrType:o.smartPtrType});var throwInstanceAlreadyDeleted=obj=>{function getInstanceTypeName(handle){return handle.$$.ptrType.registeredClass.name}throwBindingError(getInstanceTypeName(obj)+" instance already deleted")};var finalizationRegistry=false;var detachFinalizer=handle=>{};var runDestructor=$$=>{if($$.smartPtr){$$.smartPtrType.rawDestructor($$.smartPtr)}else{$$.ptrType.registeredClass.rawDestructor($$.ptr)}};var releaseClassHandle=$$=>{$$.count.value-=1;var toDelete=0===$$.count.value;if(toDelete){runDestructor($$)}};var downcastPointer=(ptr,ptrClass,desiredClass)=>{if(ptrClass===desiredClass){return ptr}if(undefined===desiredClass.baseClass){return null}var rv=downcastPointer(ptr,ptrClass,desiredClass.baseClass);if(rv===null){return null}return desiredClass.downcast(rv)};var registeredPointers={};var getInheritedInstanceCount=()=>Object.keys(registeredInstances).length;var getLiveInheritedInstances=()=>{var rv=[];for(var k in registeredInstances){if(registeredInstances.hasOwnProperty(k)){rv.push(registeredInstances[k])}}return rv};var deletionQueue=[];var flushPendingDeletes=()=>{while(deletionQueue.length){var obj=deletionQueue.pop();obj.$$.deleteScheduled=false;obj["delete"]()}};var delayFunction;var setDelayFunction=fn=>{delayFunction=fn;if(deletionQueue.length&&delayFunction){delayFunction(flushPendingDeletes)}};var init_embind=()=>{Module["getInheritedInstanceCount"]=getInheritedInstanceCount;Module["getLiveInheritedInstances"]=getLiveInheritedInstances;Module["flushPendingDeletes"]=flushPendingDeletes;Module["setDelayFunction"]=setDelayFunction};var registeredInstances={};var getBasestPointer=(class_,ptr)=>{if(ptr===undefined){throwBindingError("ptr should not be undefined")}while(class_.baseClass){ptr=class_.upcast(ptr);class_=class_.baseClass}return ptr};var getInheritedInstance=(class_,ptr)=>{ptr=getBasestPointer(class_,ptr);return registeredInstances[ptr]};var makeClassHandle=(prototype,record)=>{if(!record.ptrType||!record.ptr){throwInternalError("makeClassHandle requires ptr and ptrType")}var hasSmartPtrType=!!record.smartPtrType;var hasSmartPtr=!!record.smartPtr;if(hasSmartPtrType!==hasSmartPtr){throwInternalError("Both smartPtrType and smartPtr must be specified")}record.count={value:1};return attachFinalizer(Object.create(prototype,{$$:{value:record,writable:true}}))};function RegisteredPointer_fromWireType(ptr){var rawPointer=this.getPointee(ptr);if(!rawPointer){this.destructor(ptr);return null}var registeredInstance=getInheritedInstance(this.registeredClass,rawPointer);if(undefined!==registeredInstance){if(0===registeredInstance.$$.count.value){registeredInstance.$$.ptr=rawPointer;registeredInstance.$$.smartPtr=ptr;return registeredInstance["clone"]()}else{var rv=registeredInstance["clone"]();this.destructor(ptr);return rv}}function makeDefaultHandle(){if(this.isSmartPointer){return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this.pointeeType,ptr:rawPointer,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(this.registeredClass.instancePrototype,{ptrType:this,ptr:ptr})}}var actualType=this.registeredClass.getActualType(rawPointer);var registeredPointerRecord=registeredPointers[actualType];if(!registeredPointerRecord){return makeDefaultHandle.call(this)}var toType;if(this.isConst){toType=registeredPointerRecord.constPointerType}else{toType=registeredPointerRecord.pointerType}var dp=downcastPointer(rawPointer,this.registeredClass,toType.registeredClass);if(dp===null){return makeDefaultHandle.call(this)}if(this.isSmartPointer){return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp,smartPtrType:this,smartPtr:ptr})}else{return makeClassHandle(toType.registeredClass.instancePrototype,{ptrType:toType,ptr:dp})}}var attachFinalizer=handle=>{if("undefined"===typeof FinalizationRegistry){attachFinalizer=handle=>handle;return handle}finalizationRegistry=new FinalizationRegistry(info=>{releaseClassHandle(info.$$)});attachFinalizer=handle=>{var $$=handle.$$;var hasSmartPtr=!!$$.smartPtr;if(hasSmartPtr){var info={$$:$$};finalizationRegistry.register(handle,info,handle)}return handle};detachFinalizer=handle=>finalizationRegistry.unregister(handle);return attachFinalizer(handle)};var init_ClassHandle=()=>{Object.assign(ClassHandle.prototype,{isAliasOf(other){if(!(this instanceof ClassHandle)){return false}if(!(other instanceof ClassHandle)){return false}var leftClass=this.$$.ptrType.registeredClass;var left=this.$$.ptr;other.$$=other.$$;var rightClass=other.$$.ptrType.registeredClass;var right=other.$$.ptr;while(leftClass.baseClass){left=leftClass.upcast(left);leftClass=leftClass.baseClass}while(rightClass.baseClass){right=rightClass.upcast(right);rightClass=rightClass.baseClass}return leftClass===rightClass&&left===right},clone(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.preservePointerOnDelete){this.$$.count.value+=1;return this}else{var clone=attachFinalizer(Object.create(Object.getPrototypeOf(this),{$$:{value:shallowCopyInternalPointer(this.$$)}}));clone.$$.count.value+=1;clone.$$.deleteScheduled=false;return clone}},delete(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}detachFinalizer(this);releaseClassHandle(this.$$);if(!this.$$.preservePointerOnDelete){this.$$.smartPtr=undefined;this.$$.ptr=undefined}},isDeleted(){return!this.$$.ptr},deleteLater(){if(!this.$$.ptr){throwInstanceAlreadyDeleted(this)}if(this.$$.deleteScheduled&&!this.$$.preservePointerOnDelete){throwBindingError("Object already scheduled for deletion")}deletionQueue.push(this);if(deletionQueue.length===1&&delayFunction){delayFunction(flushPendingDeletes)}this.$$.deleteScheduled=true;return this}})};function ClassHandle(){}var createNamedFunction=(name,body)=>Object.defineProperty(body,"name",{value:name});var ensureOverloadTable=(proto,methodName,humanName)=>{if(undefined===proto[methodName].overloadTable){var prevFunc=proto[methodName];proto[methodName]=function(...args){if(!proto[methodName].overloadTable.hasOwnProperty(args.length)){throwBindingError(`Function '${humanName}' called with an invalid number of arguments (${args.length}) - expects one of (${proto[methodName].overloadTable})!`)}return proto[methodName].overloadTable[args.length].apply(this,args)};proto[methodName].overloadTable=[];proto[methodName].overloadTable[prevFunc.argCount]=prevFunc}};var exposePublicSymbol=(name,value,numArguments)=>{if(Module.hasOwnProperty(name)){if(undefined===numArguments||undefined!==Module[name].overloadTable&&undefined!==Module[name].overloadTable[numArguments]){throwBindingError(`Cannot register public name '${name}' twice`)}ensureOverloadTable(Module,name,name);if(Module.hasOwnProperty(numArguments)){throwBindingError(`Cannot register multiple overloads of a function with the same number of arguments (${numArguments})!`)}Module[name].overloadTable[numArguments]=value}else{Module[name]=value;if(undefined!==numArguments){Module[name].numArguments=numArguments}}};var char_0=48;var char_9=57;var makeLegalFunctionName=name=>{if(undefined===name){return"_unknown"}name=name.replace(/[^a-zA-Z0-9_]/g,"$");var f=name.charCodeAt(0);if(f>=char_0&&f<=char_9){return`_${name}`}return name};function RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast){this.name=name;this.constructor=constructor;this.instancePrototype=instancePrototype;this.rawDestructor=rawDestructor;this.baseClass=baseClass;this.getActualType=getActualType;this.upcast=upcast;this.downcast=downcast;this.pureVirtualFunctions=[]}var upcastPointer=(ptr,ptrClass,desiredClass)=>{while(ptrClass!==desiredClass){if(!ptrClass.upcast){throwBindingError(`Expected null or instance of ${desiredClass.name}, got an instance of ${ptrClass.name}`)}ptr=ptrClass.upcast(ptr);ptrClass=ptrClass.baseClass}return ptr};function constNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}function genericPointerToWireType(destructors,handle){var ptr;if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}if(this.isSmartPointer){ptr=this.rawConstructor();if(destructors!==null){destructors.push(this.rawDestructor,ptr)}return ptr}else{return 0}}if(!handle||!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(!this.isConst&&handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);if(this.isSmartPointer){if(undefined===handle.$$.smartPtr){throwBindingError("Passing raw pointer to smart pointer is illegal")}switch(this.sharingPolicy){case 0:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{throwBindingError(`Cannot convert argument of type ${handle.$$.smartPtrType?handle.$$.smartPtrType.name:handle.$$.ptrType.name} to parameter type ${this.name}`)}break;case 1:ptr=handle.$$.smartPtr;break;case 2:if(handle.$$.smartPtrType===this){ptr=handle.$$.smartPtr}else{var clonedHandle=handle["clone"]();ptr=this.rawShare(ptr,Emval.toHandle(()=>clonedHandle["delete"]()));if(destructors!==null){destructors.push(this.rawDestructor,ptr)}}break;default:throwBindingError("Unsupporting sharing policy")}}return ptr}function nonConstNoSmartPtrRawPointerToWireType(destructors,handle){if(handle===null){if(this.isReference){throwBindingError(`null is not a valid ${this.name}`)}return 0}if(!handle.$$){throwBindingError(`Cannot pass "${embindRepr(handle)}" as a ${this.name}`)}if(!handle.$$.ptr){throwBindingError(`Cannot pass deleted object as a pointer of type ${this.name}`)}if(handle.$$.ptrType.isConst){throwBindingError(`Cannot convert argument of type ${handle.$$.ptrType.name} to parameter type ${this.name}`)}var handleClass=handle.$$.ptrType.registeredClass;var ptr=upcastPointer(handle.$$.ptr,handleClass,this.registeredClass);return ptr}var init_RegisteredPointer=()=>{Object.assign(RegisteredPointer.prototype,{getPointee(ptr){if(this.rawGetPointee){ptr=this.rawGetPointee(ptr)}return ptr},destructor(ptr){this.rawDestructor?.(ptr)},argPackAdvance:GenericWireTypeSize,readValueFromPointer:readPointer,fromWireType:RegisteredPointer_fromWireType})};function RegisteredPointer(name,registeredClass,isReference,isConst,isSmartPointer,pointeeType,sharingPolicy,rawGetPointee,rawConstructor,rawShare,rawDestructor){this.name=name;this.registeredClass=registeredClass;this.isReference=isReference;this.isConst=isConst;this.isSmartPointer=isSmartPointer;this.pointeeType=pointeeType;this.sharingPolicy=sharingPolicy;this.rawGetPointee=rawGetPointee;this.rawConstructor=rawConstructor;this.rawShare=rawShare;this.rawDestructor=rawDestructor;if(!isSmartPointer&®isteredClass.baseClass===undefined){if(isConst){this["toWireType"]=constNoSmartPtrRawPointerToWireType;this.destructorFunction=null}else{this["toWireType"]=nonConstNoSmartPtrRawPointerToWireType;this.destructorFunction=null}}else{this["toWireType"]=genericPointerToWireType}}var replacePublicSymbol=(name,value,numArguments)=>{if(!Module.hasOwnProperty(name)){throwInternalError("Replacing nonexistent public symbol")}if(undefined!==Module[name].overloadTable&&undefined!==numArguments){Module[name].overloadTable[numArguments]=value}else{Module[name]=value;Module[name].argCount=numArguments}};var dynCallLegacy=(sig,ptr,args)=>{sig=sig.replace(/p/g,"i");var f=Module["dynCall_"+sig];return f(ptr,...args)};var wasmTableMirror=[];var wasmTable;var getWasmTableEntry=funcPtr=>{var func=wasmTableMirror[funcPtr];if(!func){if(funcPtr>=wasmTableMirror.length)wasmTableMirror.length=funcPtr+1;wasmTableMirror[funcPtr]=func=wasmTable.get(funcPtr)}return func};var dynCall=(sig,ptr,args=[])=>{if(sig.includes("j")){return dynCallLegacy(sig,ptr,args)}var rtn=getWasmTableEntry(ptr)(...args);return rtn};var getDynCaller=(sig,ptr)=>(...args)=>dynCall(sig,ptr,args);var embind__requireFunction=(signature,rawFunction)=>{signature=readLatin1String(signature);function makeDynCaller(){if(signature.includes("j")){return getDynCaller(signature,rawFunction)}return getWasmTableEntry(rawFunction)}var fp=makeDynCaller();if(typeof fp!="function"){throwBindingError(`unknown function pointer with signature ${signature}: ${rawFunction}`)}return fp};var extendError=(baseErrorType,errorName)=>{var errorClass=createNamedFunction(errorName,function(message){this.name=errorName;this.message=message;var stack=new Error(message).stack;if(stack!==undefined){this.stack=this.toString()+"\n"+stack.replace(/^Error(:[^\n]*)?\n/,"")}});errorClass.prototype=Object.create(baseErrorType.prototype);errorClass.prototype.constructor=errorClass;errorClass.prototype.toString=function(){if(this.message===undefined){return this.name}else{return`${this.name}: ${this.message}`}};return errorClass};var UnboundTypeError;var getTypeName=type=>{var ptr=___getTypeName(type);var rv=readLatin1String(ptr);_free(ptr);return rv};var throwUnboundTypeError=(message,types)=>{var unboundTypes=[];var seen={};function visit(type){if(seen[type]){return}if(registeredTypes[type]){return}if(typeDependencies[type]){typeDependencies[type].forEach(visit);return}unboundTypes.push(type);seen[type]=true}types.forEach(visit);throw new UnboundTypeError(`${message}: `+unboundTypes.map(getTypeName).join([", "]))};var __embind_register_class=(rawType,rawPointerType,rawConstPointerType,baseClassRawType,getActualTypeSignature,getActualType,upcastSignature,upcast,downcastSignature,downcast,name,destructorSignature,rawDestructor)=>{name=readLatin1String(name);getActualType=embind__requireFunction(getActualTypeSignature,getActualType);upcast&&=embind__requireFunction(upcastSignature,upcast);downcast&&=embind__requireFunction(downcastSignature,downcast);rawDestructor=embind__requireFunction(destructorSignature,rawDestructor);var legalFunctionName=makeLegalFunctionName(name);exposePublicSymbol(legalFunctionName,function(){throwUnboundTypeError(`Cannot construct ${name} due to unbound types`,[baseClassRawType])});whenDependentTypesAreResolved([rawType,rawPointerType,rawConstPointerType],baseClassRawType?[baseClassRawType]:[],base=>{base=base[0];var baseClass;var basePrototype;if(baseClassRawType){baseClass=base.registeredClass;basePrototype=baseClass.instancePrototype}else{basePrototype=ClassHandle.prototype}var constructor=createNamedFunction(name,function(...args){if(Object.getPrototypeOf(this)!==instancePrototype){throw new BindingError("Use 'new' to construct "+name)}if(undefined===registeredClass.constructor_body){throw new BindingError(name+" has no accessible constructor")}var body=registeredClass.constructor_body[args.length];if(undefined===body){throw new BindingError(`Tried to invoke ctor of ${name} with invalid number of parameters (${args.length}) - expected (${Object.keys(registeredClass.constructor_body).toString()}) parameters instead!`)}return body.apply(this,args)});var instancePrototype=Object.create(basePrototype,{constructor:{value:constructor}});constructor.prototype=instancePrototype;var registeredClass=new RegisteredClass(name,constructor,instancePrototype,rawDestructor,baseClass,getActualType,upcast,downcast);if(registeredClass.baseClass){registeredClass.baseClass.__derivedClasses??=[];registeredClass.baseClass.__derivedClasses.push(registeredClass)}var referenceConverter=new RegisteredPointer(name,registeredClass,true,false,false);var pointerConverter=new RegisteredPointer(name+"*",registeredClass,false,false,false);var constPointerConverter=new RegisteredPointer(name+" const*",registeredClass,false,true,false);registeredPointers[rawType]={pointerType:pointerConverter,constPointerType:constPointerConverter};replacePublicSymbol(legalFunctionName,constructor);return[referenceConverter,pointerConverter,constPointerConverter]})};var heap32VectorToArray=(count,firstElement)=>{var array=[];for(var i=0;i>2])}return array};function usesDestructorStack(argTypes){for(var i=1;i0?", ":"")+argsListWired}invokerFnBody+=(returns||isAsync?"var rv = ":"")+"invoker(fn"+(argsListWired.length>0?", ":"")+argsListWired+");\n";if(needsDestructorStack){invokerFnBody+="runDestructors(destructors);\n"}else{for(var i=isClassMethodFunc?1:2;i{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);invoker=embind__requireFunction(invokerSignature,invoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`constructor ${classType.name}`;if(undefined===classType.registeredClass.constructor_body){classType.registeredClass.constructor_body=[]}if(undefined!==classType.registeredClass.constructor_body[argCount-1]){throw new BindingError(`Cannot register multiple constructors with identical number of parameters (${argCount-1}) for class '${classType.name}'! Overload resolution is currently only performed using the parameter count, not actual type info!`)}classType.registeredClass.constructor_body[argCount-1]=()=>{throwUnboundTypeError(`Cannot construct ${classType.name} due to unbound types`,rawArgTypes)};whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{argTypes.splice(1,0,null);classType.registeredClass.constructor_body[argCount-1]=craftInvokerFunction(humanName,argTypes,null,invoker,rawConstructor);return[]});return[]})};var getFunctionName=signature=>{signature=signature.trim();const argsIndex=signature.indexOf("(");if(argsIndex!==-1){return signature.substr(0,argsIndex)}else{return signature}};var __embind_register_class_function=(rawClassType,methodName,argCount,rawArgTypesAddr,invokerSignature,rawInvoker,context,isPureVirtual,isAsync)=>{var rawArgTypes=heap32VectorToArray(argCount,rawArgTypesAddr);methodName=readLatin1String(methodName);methodName=getFunctionName(methodName);rawInvoker=embind__requireFunction(invokerSignature,rawInvoker);whenDependentTypesAreResolved([],[rawClassType],classType=>{classType=classType[0];var humanName=`${classType.name}.${methodName}`;if(methodName.startsWith("@@")){methodName=Symbol[methodName.substring(2)]}if(isPureVirtual){classType.registeredClass.pureVirtualFunctions.push(methodName)}function unboundTypesHandler(){throwUnboundTypeError(`Cannot call ${humanName} due to unbound types`,rawArgTypes)}var proto=classType.registeredClass.instancePrototype;var method=proto[methodName];if(undefined===method||undefined===method.overloadTable&&method.className!==classType.name&&method.argCount===argCount-2){unboundTypesHandler.argCount=argCount-2;unboundTypesHandler.className=classType.name;proto[methodName]=unboundTypesHandler}else{ensureOverloadTable(proto,methodName,humanName);proto[methodName].overloadTable[argCount-2]=unboundTypesHandler}whenDependentTypesAreResolved([],rawArgTypes,argTypes=>{var memberFunction=craftInvokerFunction(humanName,argTypes,classType,rawInvoker,context,isAsync);if(undefined===proto[methodName].overloadTable){memberFunction.argCount=argCount-2;proto[methodName]=memberFunction}else{proto[methodName].overloadTable[argCount-2]=memberFunction}return[]});return[]})};var __embind_register_constant=(name,type,value)=>{name=readLatin1String(name);whenDependentTypesAreResolved([],[type],type=>{type=type[0];Module[name]=type["fromWireType"](value);return[]})};var emval_freelist=[];var emval_handles=[];var __emval_decref=handle=>{if(handle>9&&0===--emval_handles[handle+1]){emval_handles[handle]=undefined;emval_freelist.push(handle)}};var count_emval_handles=()=>emval_handles.length/2-5-emval_freelist.length;var init_emval=()=>{emval_handles.push(0,1,undefined,1,null,1,true,1,false,1);Module["count_emval_handles"]=count_emval_handles};var Emval={toValue:handle=>{if(!handle){throwBindingError("Cannot use deleted val. handle = "+handle)}return emval_handles[handle]},toHandle:value=>{switch(value){case undefined:return 2;case null:return 4;case true:return 6;case false:return 8;default:{const handle=emval_freelist.pop()||emval_handles.length;emval_handles[handle]=value;emval_handles[handle+1]=1;return handle}}}};var EmValType={name:"emscripten::val",fromWireType:handle=>{var rv=Emval.toValue(handle);__emval_decref(handle);return rv},toWireType:(destructors,value)=>Emval.toHandle(value),argPackAdvance:GenericWireTypeSize,readValueFromPointer:readPointer,destructorFunction:null};var __embind_register_emval=rawType=>registerType(rawType,EmValType);var enumReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?function(pointer){return this["fromWireType"](HEAP8[pointer])}:function(pointer){return this["fromWireType"](HEAPU8[pointer])};case 2:return signed?function(pointer){return this["fromWireType"](HEAP16[pointer>>1])}:function(pointer){return this["fromWireType"](HEAPU16[pointer>>1])};case 4:return signed?function(pointer){return this["fromWireType"](HEAP32[pointer>>2])}:function(pointer){return this["fromWireType"](HEAPU32[pointer>>2])};default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};var __embind_register_enum=(rawType,name,size,isSigned)=>{name=readLatin1String(name);function ctor(){}ctor.values={};registerType(rawType,{name:name,constructor:ctor,fromWireType:function(c){return this.constructor.values[c]},toWireType:(destructors,c)=>c.value,argPackAdvance:GenericWireTypeSize,readValueFromPointer:enumReadValueFromPointer(name,size,isSigned),destructorFunction:null});exposePublicSymbol(name,ctor)};var requireRegisteredType=(rawType,humanName)=>{var impl=registeredTypes[rawType];if(undefined===impl){throwBindingError(`${humanName} has unknown type ${getTypeName(rawType)}`)}return impl};var __embind_register_enum_value=(rawEnumType,name,enumValue)=>{var enumType=requireRegisteredType(rawEnumType,"enum");name=readLatin1String(name);var Enum=enumType.constructor;var Value=Object.create(enumType.constructor.prototype,{value:{value:enumValue},constructor:{value:createNamedFunction(`${enumType.name}_${name}`,function(){})}});Enum.values[enumValue]=Value;Enum[name]=Value};var embindRepr=v=>{if(v===null){return"null"}var t=typeof v;if(t==="object"||t==="array"||t==="function"){return v.toString()}else{return""+v}};var floatReadValueFromPointer=(name,width)=>{switch(width){case 4:return function(pointer){return this["fromWireType"](HEAPF32[pointer>>2])};case 8:return function(pointer){return this["fromWireType"](HEAPF64[pointer>>3])};default:throw new TypeError(`invalid float width (${width}): ${name}`)}};var __embind_register_float=(rawType,name,size)=>{name=readLatin1String(name);registerType(rawType,{name:name,fromWireType:value=>value,toWireType:(destructors,value)=>value,argPackAdvance:GenericWireTypeSize,readValueFromPointer:floatReadValueFromPointer(name,size),destructorFunction:null})};var __embind_register_function=(name,argCount,rawArgTypesAddr,signature,rawInvoker,fn,isAsync)=>{var argTypes=heap32VectorToArray(argCount,rawArgTypesAddr);name=readLatin1String(name);name=getFunctionName(name);rawInvoker=embind__requireFunction(signature,rawInvoker);exposePublicSymbol(name,function(){throwUnboundTypeError(`Cannot call ${name} due to unbound types`,argTypes)},argCount-1);whenDependentTypesAreResolved([],argTypes,argTypes=>{var invokerArgsArray=[argTypes[0],null].concat(argTypes.slice(1));replacePublicSymbol(name,craftInvokerFunction(name,invokerArgsArray,null,rawInvoker,fn,isAsync),argCount-1);return[]})};var integerReadValueFromPointer=(name,width,signed)=>{switch(width){case 1:return signed?pointer=>HEAP8[pointer]:pointer=>HEAPU8[pointer];case 2:return signed?pointer=>HEAP16[pointer>>1]:pointer=>HEAPU16[pointer>>1];case 4:return signed?pointer=>HEAP32[pointer>>2]:pointer=>HEAPU32[pointer>>2];default:throw new TypeError(`invalid integer width (${width}): ${name}`)}};var __embind_register_integer=(primitiveType,name,size,minRange,maxRange)=>{name=readLatin1String(name);if(maxRange===-1){maxRange=4294967295}var fromWireType=value=>value;if(minRange===0){var bitshift=32-8*size;fromWireType=value=>value<>>bitshift}var isUnsignedType=name.includes("unsigned");var checkAssertions=(value,toTypeName)=>{};var toWireType;if(isUnsignedType){toWireType=function(destructors,value){checkAssertions(value,this.name);return value>>>0}}else{toWireType=function(destructors,value){checkAssertions(value,this.name);return value}}registerType(primitiveType,{name:name,fromWireType:fromWireType,toWireType:toWireType,argPackAdvance:GenericWireTypeSize,readValueFromPointer:integerReadValueFromPointer(name,size,minRange!==0),destructorFunction:null})};var __embind_register_memory_view=(rawType,dataTypeIndex,name)=>{var typeMapping=[Int8Array,Uint8Array,Int16Array,Uint16Array,Int32Array,Uint32Array,Float32Array,Float64Array];var TA=typeMapping[dataTypeIndex];function decodeMemoryView(handle){var size=HEAPU32[handle>>2];var data=HEAPU32[handle+4>>2];return new TA(HEAP8.buffer,data,size)}name=readLatin1String(name);registerType(rawType,{name:name,fromWireType:decodeMemoryView,argPackAdvance:GenericWireTypeSize,readValueFromPointer:decodeMemoryView},{ignoreDuplicateRegistrations:true})};var stringToUTF8Array=(str,heap,outIdx,maxBytesToWrite)=>{if(!(maxBytesToWrite>0))return 0;var startIdx=outIdx;var endIdx=outIdx+maxBytesToWrite-1;for(var i=0;i=55296&&u<=57343){var u1=str.charCodeAt(++i);u=65536+((u&1023)<<10)|u1&1023}if(u<=127){if(outIdx>=endIdx)break;heap[outIdx++]=u}else if(u<=2047){if(outIdx+1>=endIdx)break;heap[outIdx++]=192|u>>6;heap[outIdx++]=128|u&63}else if(u<=65535){if(outIdx+2>=endIdx)break;heap[outIdx++]=224|u>>12;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}else{if(outIdx+3>=endIdx)break;heap[outIdx++]=240|u>>18;heap[outIdx++]=128|u>>12&63;heap[outIdx++]=128|u>>6&63;heap[outIdx++]=128|u&63}}heap[outIdx]=0;return outIdx-startIdx};var stringToUTF8=(str,outPtr,maxBytesToWrite)=>stringToUTF8Array(str,HEAPU8,outPtr,maxBytesToWrite);var lengthBytesUTF8=str=>{var len=0;for(var i=0;i=55296&&c<=57343){len+=4;++i}else{len+=3}}return len};var UTF8Decoder=typeof TextDecoder!="undefined"?new TextDecoder:undefined;var UTF8ArrayToString=(heapOrArray,idx,maxBytesToRead)=>{var endIdx=idx+maxBytesToRead;var endPtr=idx;while(heapOrArray[endPtr]&&!(endPtr>=endIdx))++endPtr;if(endPtr-idx>16&&heapOrArray.buffer&&UTF8Decoder){return UTF8Decoder.decode(heapOrArray.subarray(idx,endPtr))}var str="";while(idx>10,56320|ch&1023)}}return str};var UTF8ToString=(ptr,maxBytesToRead)=>ptr?UTF8ArrayToString(HEAPU8,ptr,maxBytesToRead):"";var __embind_register_std_string=(rawType,name)=>{name=readLatin1String(name);var stdStringIsUTF8=name==="std::string";registerType(rawType,{name:name,fromWireType(value){var length=HEAPU32[value>>2];var payload=value+4;var str;if(stdStringIsUTF8){var decodeStartPtr=payload;for(var i=0;i<=length;++i){var currentBytePtr=payload+i;if(i==length||HEAPU8[currentBytePtr]==0){var maxRead=currentBytePtr-decodeStartPtr;var stringSegment=UTF8ToString(decodeStartPtr,maxRead);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+1}}}else{var a=new Array(length);for(var i=0;i>2]=length;if(stdStringIsUTF8&&valueIsOfTypeString){stringToUTF8(value,ptr,length+1)}else{if(valueIsOfTypeString){for(var i=0;i255){_free(ptr);throwBindingError("String has UTF-16 code units that do not fit in 8 bits")}HEAPU8[ptr+i]=charCode}}else{for(var i=0;i{var endPtr=ptr;var idx=endPtr>>1;var maxIdx=idx+maxBytesToRead/2;while(!(idx>=maxIdx)&&HEAPU16[idx])++idx;endPtr=idx<<1;if(endPtr-ptr>32&&UTF16Decoder)return UTF16Decoder.decode(HEAPU8.subarray(ptr,endPtr));var str="";for(var i=0;!(i>=maxBytesToRead/2);++i){var codeUnit=HEAP16[ptr+i*2>>1];if(codeUnit==0)break;str+=String.fromCharCode(codeUnit)}return str};var stringToUTF16=(str,outPtr,maxBytesToWrite)=>{maxBytesToWrite??=2147483647;if(maxBytesToWrite<2)return 0;maxBytesToWrite-=2;var startPtr=outPtr;var numCharsToWrite=maxBytesToWrite>1]=codeUnit;outPtr+=2}HEAP16[outPtr>>1]=0;return outPtr-startPtr};var lengthBytesUTF16=str=>str.length*2;var UTF32ToString=(ptr,maxBytesToRead)=>{var i=0;var str="";while(!(i>=maxBytesToRead/4)){var utf32=HEAP32[ptr+i*4>>2];if(utf32==0)break;++i;if(utf32>=65536){var ch=utf32-65536;str+=String.fromCharCode(55296|ch>>10,56320|ch&1023)}else{str+=String.fromCharCode(utf32)}}return str};var stringToUTF32=(str,outPtr,maxBytesToWrite)=>{maxBytesToWrite??=2147483647;if(maxBytesToWrite<4)return 0;var startPtr=outPtr;var endPtr=startPtr+maxBytesToWrite-4;for(var i=0;i=55296&&codeUnit<=57343){var trailSurrogate=str.charCodeAt(++i);codeUnit=65536+((codeUnit&1023)<<10)|trailSurrogate&1023}HEAP32[outPtr>>2]=codeUnit;outPtr+=4;if(outPtr+4>endPtr)break}HEAP32[outPtr>>2]=0;return outPtr-startPtr};var lengthBytesUTF32=str=>{var len=0;for(var i=0;i=55296&&codeUnit<=57343)++i;len+=4}return len};var __embind_register_std_wstring=(rawType,charSize,name)=>{name=readLatin1String(name);var decodeString,encodeString,readCharAt,lengthBytesUTF;if(charSize===2){decodeString=UTF16ToString;encodeString=stringToUTF16;lengthBytesUTF=lengthBytesUTF16;readCharAt=pointer=>HEAPU16[pointer>>1]}else if(charSize===4){decodeString=UTF32ToString;encodeString=stringToUTF32;lengthBytesUTF=lengthBytesUTF32;readCharAt=pointer=>HEAPU32[pointer>>2]}registerType(rawType,{name:name,fromWireType:value=>{var length=HEAPU32[value>>2];var str;var decodeStartPtr=value+4;for(var i=0;i<=length;++i){var currentBytePtr=value+4+i*charSize;if(i==length||readCharAt(currentBytePtr)==0){var maxReadBytes=currentBytePtr-decodeStartPtr;var stringSegment=decodeString(decodeStartPtr,maxReadBytes);if(str===undefined){str=stringSegment}else{str+=String.fromCharCode(0);str+=stringSegment}decodeStartPtr=currentBytePtr+charSize}}_free(value);return str},toWireType:(destructors,value)=>{if(!(typeof value=="string")){throwBindingError(`Cannot pass non-string to C++ string type ${name}`)}var length=lengthBytesUTF(value);var ptr=_malloc(4+length+charSize);HEAPU32[ptr>>2]=length/charSize;encodeString(value,ptr+4,length+charSize);if(destructors!==null){destructors.push(_free,ptr)}return ptr},argPackAdvance:GenericWireTypeSize,readValueFromPointer:readPointer,destructorFunction(ptr){_free(ptr)}})};var __embind_register_value_object=(rawType,name,constructorSignature,rawConstructor,destructorSignature,rawDestructor)=>{structRegistrations[rawType]={name:readLatin1String(name),rawConstructor:embind__requireFunction(constructorSignature,rawConstructor),rawDestructor:embind__requireFunction(destructorSignature,rawDestructor),fields:[]}};var __embind_register_value_object_field=(structType,fieldName,getterReturnType,getterSignature,getter,getterContext,setterArgumentType,setterSignature,setter,setterContext)=>{structRegistrations[structType].fields.push({fieldName:readLatin1String(fieldName),getterReturnType:getterReturnType,getter:embind__requireFunction(getterSignature,getter),getterContext:getterContext,setterArgumentType:setterArgumentType,setter:embind__requireFunction(setterSignature,setter),setterContext:setterContext})};var __embind_register_void=(rawType,name)=>{name=readLatin1String(name);registerType(rawType,{isVoid:true,name:name,argPackAdvance:0,fromWireType:()=>undefined,toWireType:(destructors,o)=>undefined})};var __emscripten_memcpy_js=(dest,src,num)=>HEAPU8.copyWithin(dest,src,src+num);var emval_returnValue=(returnType,destructorsRef,handle)=>{var destructors=[];var result=returnType["toWireType"](destructors,handle);if(destructors.length){HEAPU32[destructorsRef>>2]=Emval.toHandle(destructors)}return result};var __emval_as=(handle,returnType,destructorsRef)=>{handle=Emval.toValue(handle);returnType=requireRegisteredType(returnType,"emval::as");return emval_returnValue(returnType,destructorsRef,handle)};var emval_methodCallers=[];var __emval_call=(caller,handle,destructorsRef,args)=>{caller=emval_methodCallers[caller];handle=Emval.toValue(handle);return caller(null,handle,destructorsRef,args)};var emval_symbols={};var getStringOrSymbol=address=>{var symbol=emval_symbols[address];if(symbol===undefined){return readLatin1String(address)}return symbol};var __emval_call_method=(caller,objHandle,methodName,destructorsRef,args)=>{caller=emval_methodCallers[caller];objHandle=Emval.toValue(objHandle);methodName=getStringOrSymbol(methodName);return caller(objHandle,objHandle[methodName],destructorsRef,args)};var emval_get_global=()=>{if(typeof globalThis=="object"){return globalThis}return function(){return Function}()("return this")()};var __emval_get_global=name=>{if(name===0){return Emval.toHandle(emval_get_global())}else{name=getStringOrSymbol(name);return Emval.toHandle(emval_get_global()[name])}};var emval_addMethodCaller=caller=>{var id=emval_methodCallers.length;emval_methodCallers.push(caller);return id};var emval_lookupTypes=(argCount,argTypes)=>{var a=new Array(argCount);for(var i=0;i>2],"parameter "+i)}return a};var reflectConstruct=Reflect.construct;var __emval_get_method_caller=(argCount,argTypes,kind)=>{var types=emval_lookupTypes(argCount,argTypes);var retType=types.shift();argCount--;var functionBody=`return function (obj, func, destructorsRef, args) {\n`;var offset=0;var argsList=[];if(kind===0){argsList.push("obj")}var params=["retType"];var args=[retType];for(var i=0;it.name).join(", ")}) => ${retType.name}>`;return emval_addMethodCaller(createNamedFunction(functionName,invokerFunction))};var __emval_get_module_property=name=>{name=getStringOrSymbol(name);return Emval.toHandle(Module[name])};var __emval_get_property=(handle,key)=>{handle=Emval.toValue(handle);key=Emval.toValue(key);return Emval.toHandle(handle[key])};var __emval_incref=handle=>{if(handle>9){emval_handles[handle+1]+=1}};var __emval_new_cstring=v=>Emval.toHandle(getStringOrSymbol(v));var __emval_run_destructors=handle=>{var destructors=Emval.toValue(handle);runDestructors(destructors);__emval_decref(handle)};var getHeapMax=()=>2147483648;var growMemory=size=>{var b=wasmMemory.buffer;var pages=(size-b.byteLength+65535)/65536;try{wasmMemory.grow(pages);updateMemoryViews();return 1}catch(e){}};var _emscripten_resize_heap=requestedSize=>{var oldSize=HEAPU8.length;requestedSize>>>=0;var maxHeapSize=getHeapMax();if(requestedSize>maxHeapSize){return false}var alignUp=(x,multiple)=>x+(multiple-x%multiple)%multiple;for(var cutDown=1;cutDown<=4;cutDown*=2){var overGrownHeapSize=oldSize*(1+.2/cutDown);overGrownHeapSize=Math.min(overGrownHeapSize,requestedSize+100663296);var newSize=Math.min(maxHeapSize,alignUp(Math.max(requestedSize,overGrownHeapSize),65536));var replacement=growMemory(newSize);if(replacement){return true}}return false};var _fd_close=fd=>52;var convertI32PairToI53Checked=(lo,hi)=>hi+2097152>>>0<4194305-!!lo?(lo>>>0)+hi*4294967296:NaN;function _fd_seek(fd,offset_low,offset_high,whence,newOffset){var offset=convertI32PairToI53Checked(offset_low,offset_high);return 70}var printCharBuffers=[null,[],[]];var printChar=(stream,curr)=>{var buffer=printCharBuffers[stream];if(curr===0||curr===10){(stream===1?out:err)(UTF8ArrayToString(buffer,0));buffer.length=0}else{buffer.push(curr)}};var _fd_write=(fd,iov,iovcnt,pnum)=>{var num=0;for(var i=0;i>2];var len=HEAPU32[iov+4>>2];iov+=8;for(var j=0;j>2]=num;return 0};InternalError=Module["InternalError"]=class InternalError extends Error{constructor(message){super(message);this.name="InternalError"}};embind_init_charCodes();BindingError=Module["BindingError"]=class BindingError extends Error{constructor(message){super(message);this.name="BindingError"}};init_ClassHandle();init_embind();init_RegisteredPointer();UnboundTypeError=Module["UnboundTypeError"]=extendError(Error,"UnboundTypeError");init_emval();var wasmImports={K:___cxa_throw,G:__abort_js,s:__embind_finalize_value_object,C:__embind_register_bigint,I:__embind_register_bool,w:__embind_register_class,v:__embind_register_class_constructor,d:__embind_register_class_function,m:__embind_register_constant,H:__embind_register_emval,o:__embind_register_enum,a:__embind_register_enum_value,A:__embind_register_float,i:__embind_register_function,l:__embind_register_integer,f:__embind_register_memory_view,z:__embind_register_std_string,u:__embind_register_std_wstring,t:__embind_register_value_object,c:__embind_register_value_object_field,J:__embind_register_void,F:__emscripten_memcpy_js,n:__emval_as,q:__emval_call,p:__emval_call_method,b:__emval_decref,x:__emval_get_global,j:__emval_get_method_caller,r:__emval_get_module_property,g:__emval_get_property,k:__emval_incref,h:__emval_new_cstring,e:__emval_run_destructors,D:_emscripten_resize_heap,E:_fd_close,B:_fd_seek,y:_fd_write};var wasmExports=createWasm();var ___wasm_call_ctors=()=>(___wasm_call_ctors=wasmExports["M"])();var ___getTypeName=a0=>(___getTypeName=wasmExports["N"])(a0);var _malloc=a0=>(_malloc=wasmExports["O"])(a0);var _free=a0=>(_free=wasmExports["Q"])(a0);var ___cxa_is_pointer_type=a0=>(___cxa_is_pointer_type=wasmExports["R"])(a0);var dynCall_jiji=Module["dynCall_jiji"]=(a0,a1,a2,a3,a4)=>(dynCall_jiji=Module["dynCall_jiji"]=wasmExports["S"])(a0,a1,a2,a3,a4);var calledRun;dependenciesFulfilled=function runCaller(){if(!calledRun)run();if(!calledRun)dependenciesFulfilled=runCaller};function run(){if(runDependencies>0){return}preRun();if(runDependencies>0){return}function doRun(){if(calledRun)return;calledRun=true;Module["calledRun"]=true;if(ABORT)return;initRuntime();readyPromiseResolve(Module);Module["onRuntimeInitialized"]?.();postRun()}if(Module["setStatus"]){Module["setStatus"]("Running...");setTimeout(function(){setTimeout(function(){Module["setStatus"]("")},1);doRun()},1)}else{doRun()}}if(Module["preInit"]){if(typeof Module["preInit"]=="function")Module["preInit"]=[Module["preInit"]];while(Module["preInit"].length>0){Module["preInit"].pop()()}}run();moduleRtn=readyPromise; - return BASIS.ready + return moduleRtn; } ); })(); if (typeof exports === 'object' && typeof module === 'object') module.exports = BASIS; else if (typeof define === 'function' && define['amd']) - define([], function() { return BASIS; }); -else if (typeof exports === 'object') - exports["BASIS"] = BASIS; + define([], () => BASIS); diff --git a/examples/jsm/libs/basis/basis_transcoder.wasm b/examples/jsm/libs/basis/basis_transcoder.wasm index 4b9c3437170cf226600057096490d0a2fa8d74ea..bc64682561438128604ac550da774f8cc6617460 100644 GIT binary patch delta 238096 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 delta 210516 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 M($Wu@lsuFE9~D>_n*aa+ diff --git a/examples/jsm/libs/ktx-parse.module.js b/examples/jsm/libs/ktx-parse.module.js index c1d66bc7462119..3593d4378b02e0 100644 --- a/examples/jsm/libs/ktx-parse.module.js +++ b/examples/jsm/libs/ktx-parse.module.js @@ -1 +1 @@ -const t=0,e=1,n=2,i=3,s=0,a=0,r=2,o=0,l=1,f=160,U=161,c=162,h=163,_=0,p=1,g=0,y=1,x=2,u=3,b=4,d=5,m=6,w=7,D=8,B=9,L=10,A=11,k=12,v=13,S=14,I=15,O=16,T=17,V=18,E=0,F=1,P=2,C=3,z=4,M=5,W=6,N=7,H=8,K=9,X=10,j=11,R=0,Y=1,q=2,G=13,J=14,Q=15,Z=128,$=64,tt=32,et=16,nt=0,it=1,st=2,at=3,rt=4,ot=5,lt=6,ft=7,Ut=8,ct=9,ht=10,_t=13,pt=14,gt=15,yt=16,xt=17,ut=20,bt=21,dt=22,mt=23,wt=24,Dt=27,Bt=28,Lt=29,At=30,kt=31,vt=34,St=35,It=36,Ot=37,Tt=38,Vt=41,Et=42,Ft=43,Pt=44,Ct=45,zt=48,Mt=49,Wt=50,Nt=58,Ht=59,Kt=62,Xt=63,jt=64,Rt=65,Yt=68,qt=69,Gt=70,Jt=71,Qt=74,Zt=75,$t=76,te=77,ee=78,ne=81,ie=82,se=83,ae=84,re=85,oe=88,le=89,fe=90,Ue=91,ce=92,he=95,_e=96,pe=97,ge=98,ye=99,xe=100,ue=101,be=102,de=103,me=104,we=105,De=106,Be=107,Le=108,Ae=109,ke=110,ve=111,Se=112,Ie=113,Oe=114,Te=115,Ve=116,Ee=117,Fe=118,Pe=119,Ce=120,ze=121,Me=122,We=123,Ne=124,He=125,Ke=126,Xe=127,je=128,Re=129,Ye=130,qe=131,Ge=132,Je=133,Qe=134,Ze=135,$e=136,tn=137,en=138,nn=139,sn=140,an=141,rn=142,on=143,ln=144,fn=145,Un=146,cn=147,hn=148,_n=149,pn=150,gn=151,yn=152,xn=153,un=154,bn=155,dn=156,mn=157,wn=158,Dn=159,Bn=160,Ln=161,An=162,kn=163,vn=164,Sn=165,In=166,On=167,Tn=168,Vn=169,En=170,Fn=171,Pn=172,Cn=173,zn=174,Mn=175,Wn=176,Nn=177,Hn=178,Kn=179,Xn=180,jn=181,Rn=182,Yn=183,qn=184,Gn=1000156007,Jn=1000156008,Qn=1000156009,Zn=1000156010,$n=1000156011,ti=1000156017,ei=1000156018,ni=1000156019,ii=1000156020,si=1000156021,ai=1000054e3,ri=1000054001,oi=1000054002,li=1000054003,fi=1000054004,Ui=1000054005,ci=1000054006,hi=1000054007,_i=1000066e3,pi=1000066001,gi=1000066002,yi=1000066003,xi=1000066004,ui=1000066005,bi=1000066006,di=1000066007,mi=1000066008,wi=1000066009,Di=1000066010,Bi=1000066011,Li=1000066012,Ai=1000066013,ki=100034e4,vi=1000340001;class Si{constructor(){this.vkFormat=0,this.typeSize=1,this.pixelWidth=0,this.pixelHeight=0,this.pixelDepth=0,this.layerCount=0,this.faceCount=1,this.supercompressionScheme=0,this.levels=[],this.dataFormatDescriptor=[{vendorId:0,descriptorType:0,descriptorBlockSize:0,versionNumber:2,colorModel:0,colorPrimaries:1,transferFunction:2,flags:0,texelBlockDimension:[0,0,0,0],bytesPlane:[0,0,0,0,0,0,0,0],samples:[]}],this.keyValue={},this.globalData=null}}class Ii{constructor(t,e,n,i){this._dataView=new DataView(t.buffer,t.byteOffset+e,n),this._littleEndian=i,this._offset=0}_nextUint8(){const t=this._dataView.getUint8(this._offset);return this._offset+=1,t}_nextUint16(){const t=this._dataView.getUint16(this._offset,this._littleEndian);return this._offset+=2,t}_nextUint32(){const t=this._dataView.getUint32(this._offset,this._littleEndian);return this._offset+=4,t}_nextUint64(){const t=this._dataView.getUint32(this._offset,this._littleEndian)+2**32*this._dataView.getUint32(this._offset+4,this._littleEndian);return this._offset+=8,t}_nextInt32(){const t=this._dataView.getInt32(this._offset,this._littleEndian);return this._offset+=4,t}_skip(t){return this._offset+=t,this}_scan(t,e=0){const n=this._offset;let i=0;for(;this._dataView.getUint8(this._offset)!==e&&i0?c+a.byteLength:0;h%8&&(h+=8-h%8);const _=[],p=new DataView(new ArrayBuffer(3*t.levels.length*8));let g=(h||c+a.byteLength)+n.byteLength;for(let e=0;e0?h:0),!0),x.setBigUint64(60,BigInt(n.byteLength),!0),new Uint8Array(Fi([new Uint8Array(Ti).buffer,y,p.buffer,o,a,h>0?new ArrayBuffer(h-(c+a.byteLength)):new ArrayBuffer(0),n,..._]))}export{Q as KHR_DF_CHANNEL_RGBSDA_ALPHA,q as KHR_DF_CHANNEL_RGBSDA_BLUE,J as KHR_DF_CHANNEL_RGBSDA_DEPTH,Y as KHR_DF_CHANNEL_RGBSDA_GREEN,R as KHR_DF_CHANNEL_RGBSDA_RED,G as KHR_DF_CHANNEL_RGBSDA_STENCIL,p as KHR_DF_FLAG_ALPHA_PREMULTIPLIED,_ as KHR_DF_FLAG_ALPHA_STRAIGHT,s as KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT,c as KHR_DF_MODEL_ASTC,f as KHR_DF_MODEL_ETC1,h as KHR_DF_MODEL_ETC1S,U as KHR_DF_MODEL_ETC2,l as KHR_DF_MODEL_RGBSDA,o as KHR_DF_MODEL_UNSPECIFIED,W as KHR_DF_PRIMARIES_ACES,N as KHR_DF_PRIMARIES_ACESCC,j as KHR_DF_PRIMARIES_ADOBERGB,z as KHR_DF_PRIMARIES_BT2020,P as KHR_DF_PRIMARIES_BT601_EBU,C as KHR_DF_PRIMARIES_BT601_SMPTE,F as KHR_DF_PRIMARIES_BT709,M as KHR_DF_PRIMARIES_CIEXYZ,X as KHR_DF_PRIMARIES_DISPLAYP3,H as KHR_DF_PRIMARIES_NTSC1953,K as KHR_DF_PRIMARIES_PAL525,E as KHR_DF_PRIMARIES_UNSPECIFIED,tt as KHR_DF_SAMPLE_DATATYPE_EXPONENT,Z as KHR_DF_SAMPLE_DATATYPE_FLOAT,et as KHR_DF_SAMPLE_DATATYPE_LINEAR,$ as KHR_DF_SAMPLE_DATATYPE_SIGNED,O as KHR_DF_TRANSFER_ACESCC,T as KHR_DF_TRANSFER_ACESCCT,V as KHR_DF_TRANSFER_ADOBERGB,w as KHR_DF_TRANSFER_BT1886,k as KHR_DF_TRANSFER_DCIP3,B as KHR_DF_TRANSFER_HLG_EOTF,D as KHR_DF_TRANSFER_HLG_OETF,u as KHR_DF_TRANSFER_ITU,y as KHR_DF_TRANSFER_LINEAR,b as KHR_DF_TRANSFER_NTSC,S as KHR_DF_TRANSFER_PAL625_EOTF,v as KHR_DF_TRANSFER_PAL_OETF,L as KHR_DF_TRANSFER_PQ_EOTF,A as KHR_DF_TRANSFER_PQ_OETF,d as KHR_DF_TRANSFER_SLOG,m as KHR_DF_TRANSFER_SLOG2,x as KHR_DF_TRANSFER_SRGB,I as KHR_DF_TRANSFER_ST240,g as KHR_DF_TRANSFER_UNSPECIFIED,a as KHR_DF_VENDORID_KHRONOS,r as KHR_DF_VERSION,e as KHR_SUPERCOMPRESSION_BASISLZ,t as KHR_SUPERCOMPRESSION_NONE,i as KHR_SUPERCOMPRESSION_ZLIB,n as KHR_SUPERCOMPRESSION_ZSTD,Si as KTX2Container,Ut as VK_FORMAT_A1R5G5B5_UNORM_PACK16,qt as VK_FORMAT_A2B10G10R10_SINT_PACK32,Rt as VK_FORMAT_A2B10G10R10_SNORM_PACK32,Yt as VK_FORMAT_A2B10G10R10_UINT_PACK32,jt as VK_FORMAT_A2B10G10R10_UNORM_PACK32,Xt as VK_FORMAT_A2R10G10B10_SINT_PACK32,Ht as VK_FORMAT_A2R10G10B10_SNORM_PACK32,Kt as VK_FORMAT_A2R10G10B10_UINT_PACK32,Nt as VK_FORMAT_A2R10G10B10_UNORM_PACK32,vi as VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,ki as VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,Bi as VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT,Xn as VK_FORMAT_ASTC_10x10_SRGB_BLOCK,Kn as VK_FORMAT_ASTC_10x10_UNORM_BLOCK,mi as VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT,zn as VK_FORMAT_ASTC_10x5_SRGB_BLOCK,Cn as VK_FORMAT_ASTC_10x5_UNORM_BLOCK,wi as VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT,Wn as VK_FORMAT_ASTC_10x6_SRGB_BLOCK,Mn as VK_FORMAT_ASTC_10x6_UNORM_BLOCK,Di as VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT,Hn as VK_FORMAT_ASTC_10x8_SRGB_BLOCK,Nn as VK_FORMAT_ASTC_10x8_UNORM_BLOCK,Li as VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT,Rn as VK_FORMAT_ASTC_12x10_SRGB_BLOCK,jn as VK_FORMAT_ASTC_12x10_UNORM_BLOCK,Ai as VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT,qn as VK_FORMAT_ASTC_12x12_SRGB_BLOCK,Yn as VK_FORMAT_ASTC_12x12_UNORM_BLOCK,_i as VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT,wn as VK_FORMAT_ASTC_4x4_SRGB_BLOCK,mn as VK_FORMAT_ASTC_4x4_UNORM_BLOCK,pi as VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT,Bn as VK_FORMAT_ASTC_5x4_SRGB_BLOCK,Dn as VK_FORMAT_ASTC_5x4_UNORM_BLOCK,gi as VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT,An as VK_FORMAT_ASTC_5x5_SRGB_BLOCK,Ln as VK_FORMAT_ASTC_5x5_UNORM_BLOCK,yi as VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT,vn as VK_FORMAT_ASTC_6x5_SRGB_BLOCK,kn as VK_FORMAT_ASTC_6x5_UNORM_BLOCK,xi as VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT,In as VK_FORMAT_ASTC_6x6_SRGB_BLOCK,Sn as VK_FORMAT_ASTC_6x6_UNORM_BLOCK,ui as VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT,Tn as VK_FORMAT_ASTC_8x5_SRGB_BLOCK,On as VK_FORMAT_ASTC_8x5_UNORM_BLOCK,bi as VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT,En as VK_FORMAT_ASTC_8x6_SRGB_BLOCK,Vn as VK_FORMAT_ASTC_8x6_UNORM_BLOCK,di as VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT,Pn as VK_FORMAT_ASTC_8x8_SRGB_BLOCK,Fn as VK_FORMAT_ASTC_8x8_UNORM_BLOCK,Me as VK_FORMAT_B10G11R11_UFLOAT_PACK32,$n as VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,si as VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,at as VK_FORMAT_B4G4R4A4_UNORM_PACK16,ft as VK_FORMAT_B5G5R5A1_UNORM_PACK16,ot as VK_FORMAT_B5G6R5_UNORM_PACK16,Mt as VK_FORMAT_B8G8R8A8_SINT,Ct as VK_FORMAT_B8G8R8A8_SNORM,Wt as VK_FORMAT_B8G8R8A8_SRGB,zt as VK_FORMAT_B8G8R8A8_UINT,Pt as VK_FORMAT_B8G8R8A8_UNORM,St as VK_FORMAT_B8G8R8_SINT,kt as VK_FORMAT_B8G8R8_SNORM,It as VK_FORMAT_B8G8R8_SRGB,vt as VK_FORMAT_B8G8R8_UINT,At as VK_FORMAT_B8G8R8_UNORM,Qe as VK_FORMAT_BC1_RGBA_SRGB_BLOCK,Je as VK_FORMAT_BC1_RGBA_UNORM_BLOCK,Ge as VK_FORMAT_BC1_RGB_SRGB_BLOCK,qe as VK_FORMAT_BC1_RGB_UNORM_BLOCK,$e as VK_FORMAT_BC2_SRGB_BLOCK,Ze as VK_FORMAT_BC2_UNORM_BLOCK,en as VK_FORMAT_BC3_SRGB_BLOCK,tn as VK_FORMAT_BC3_UNORM_BLOCK,sn as VK_FORMAT_BC4_SNORM_BLOCK,nn as VK_FORMAT_BC4_UNORM_BLOCK,rn as VK_FORMAT_BC5_SNORM_BLOCK,an as VK_FORMAT_BC5_UNORM_BLOCK,ln as VK_FORMAT_BC6H_SFLOAT_BLOCK,on as VK_FORMAT_BC6H_UFLOAT_BLOCK,Un as VK_FORMAT_BC7_SRGB_BLOCK,fn as VK_FORMAT_BC7_UNORM_BLOCK,Ne as VK_FORMAT_D16_UNORM,je as VK_FORMAT_D16_UNORM_S8_UINT,Re as VK_FORMAT_D24_UNORM_S8_UINT,Ke as VK_FORMAT_D32_SFLOAT,Ye as VK_FORMAT_D32_SFLOAT_S8_UINT,We as VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,dn as VK_FORMAT_EAC_R11G11_SNORM_BLOCK,bn as VK_FORMAT_EAC_R11G11_UNORM_BLOCK,un as VK_FORMAT_EAC_R11_SNORM_BLOCK,xn as VK_FORMAT_EAC_R11_UNORM_BLOCK,pn as VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,_n as VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,yn as VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,gn as VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,hn as VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,cn as VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,Zn as VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,ii as VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,fi as VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG,ai as VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG,Ui as VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG,ri as VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG,ci as VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG,oi as VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG,hi as VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG,li as VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG,Qn as VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,Jn as VK_FORMAT_R10X6G10X6_UNORM_2PACK16,Gn as VK_FORMAT_R10X6_UNORM_PACK16,ni as VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,ei as VK_FORMAT_R12X4G12X4_UNORM_2PACK16,ti as VK_FORMAT_R12X4_UNORM_PACK16,pe as VK_FORMAT_R16G16B16A16_SFLOAT,_e as VK_FORMAT_R16G16B16A16_SINT,ce as VK_FORMAT_R16G16B16A16_SNORM,he as VK_FORMAT_R16G16B16A16_UINT,Ue as VK_FORMAT_R16G16B16A16_UNORM,fe as VK_FORMAT_R16G16B16_SFLOAT,le as VK_FORMAT_R16G16B16_SINT,re as VK_FORMAT_R16G16B16_SNORM,oe as VK_FORMAT_R16G16B16_UINT,ae as VK_FORMAT_R16G16B16_UNORM,se as VK_FORMAT_R16G16_SFLOAT,ie as VK_FORMAT_R16G16_SINT,ee as VK_FORMAT_R16G16_SNORM,ne as VK_FORMAT_R16G16_UINT,te as VK_FORMAT_R16G16_UNORM,$t as VK_FORMAT_R16_SFLOAT,Zt as VK_FORMAT_R16_SINT,Jt as VK_FORMAT_R16_SNORM,Qt as VK_FORMAT_R16_UINT,Gt as VK_FORMAT_R16_UNORM,Ae as VK_FORMAT_R32G32B32A32_SFLOAT,Le as VK_FORMAT_R32G32B32A32_SINT,Be as VK_FORMAT_R32G32B32A32_UINT,De as VK_FORMAT_R32G32B32_SFLOAT,we as VK_FORMAT_R32G32B32_SINT,me as VK_FORMAT_R32G32B32_UINT,de as VK_FORMAT_R32G32_SFLOAT,be as VK_FORMAT_R32G32_SINT,ue as VK_FORMAT_R32G32_UINT,xe as VK_FORMAT_R32_SFLOAT,ye as VK_FORMAT_R32_SINT,ge as VK_FORMAT_R32_UINT,st as VK_FORMAT_R4G4B4A4_UNORM_PACK16,it as VK_FORMAT_R4G4_UNORM_PACK8,lt as VK_FORMAT_R5G5B5A1_UNORM_PACK16,rt as VK_FORMAT_R5G6B5_UNORM_PACK16,ze as VK_FORMAT_R64G64B64A64_SFLOAT,Ce as VK_FORMAT_R64G64B64A64_SINT,Pe as VK_FORMAT_R64G64B64A64_UINT,Fe as VK_FORMAT_R64G64B64_SFLOAT,Ee as VK_FORMAT_R64G64B64_SINT,Ve as VK_FORMAT_R64G64B64_UINT,Te as VK_FORMAT_R64G64_SFLOAT,Oe as VK_FORMAT_R64G64_SINT,Ie as VK_FORMAT_R64G64_UINT,Se as VK_FORMAT_R64_SFLOAT,ve as VK_FORMAT_R64_SINT,ke as VK_FORMAT_R64_UINT,Et as VK_FORMAT_R8G8B8A8_SINT,Tt as VK_FORMAT_R8G8B8A8_SNORM,Ft as VK_FORMAT_R8G8B8A8_SRGB,Vt as VK_FORMAT_R8G8B8A8_UINT,Ot as VK_FORMAT_R8G8B8A8_UNORM,Bt as VK_FORMAT_R8G8B8_SINT,wt as VK_FORMAT_R8G8B8_SNORM,Lt as VK_FORMAT_R8G8B8_SRGB,Dt as VK_FORMAT_R8G8B8_UINT,mt as VK_FORMAT_R8G8B8_UNORM,bt as VK_FORMAT_R8G8_SINT,xt as VK_FORMAT_R8G8_SNORM,dt as VK_FORMAT_R8G8_SRGB,ut as VK_FORMAT_R8G8_UINT,yt as VK_FORMAT_R8G8_UNORM,pt as VK_FORMAT_R8_SINT,ht as VK_FORMAT_R8_SNORM,gt as VK_FORMAT_R8_SRGB,_t as VK_FORMAT_R8_UINT,ct as VK_FORMAT_R8_UNORM,Xe as VK_FORMAT_S8_UINT,nt as VK_FORMAT_UNDEFINED,He as VK_FORMAT_X8_D24_UNORM_PACK32,Pi as read,Mi as write}; +const t=0,e=1,n=2,i=3,s=0,a=0,r=2,o=0,l=1,f=160,h=161,U=162,c=163,_=166,p=0,g=1,y=0,x=1,u=2,b=3,d=4,w=5,m=6,D=7,B=8,L=9,v=10,A=11,k=12,V=13,I=14,S=15,F=16,O=17,E=18,T=0,C=1,M=2,P=3,z=4,W=5,H=6,N=7,K=8,X=9,R=10,Y=11,j=0,q=1,G=2,J=13,Q=14,Z=15,$=128,tt=64,et=32,nt=16,it=0,st=1,at=2,rt=3,ot=4,lt=5,ft=6,ht=7,Ut=8,ct=9,_t=10,pt=13,gt=14,yt=15,xt=16,ut=17,bt=20,dt=21,wt=22,mt=23,Dt=24,Bt=27,Lt=28,vt=29,At=30,kt=31,Vt=34,It=35,St=36,Ft=37,Ot=38,Et=41,Tt=42,Ct=43,Mt=44,Pt=45,zt=48,Wt=49,Ht=50,Nt=58,Kt=59,Xt=62,Rt=63,Yt=64,jt=65,qt=68,Gt=69,Jt=70,Qt=71,Zt=74,$t=75,te=76,ee=77,ne=78,ie=81,se=82,ae=83,re=84,oe=85,le=88,fe=89,he=90,Ue=91,ce=92,_e=95,pe=96,ge=97,ye=98,xe=99,ue=100,be=101,de=102,we=103,me=104,De=105,Be=106,Le=107,ve=108,Ae=109,ke=110,Ve=111,Ie=112,Se=113,Fe=114,Oe=115,Ee=116,Te=117,Ce=118,Me=119,Pe=120,ze=121,We=122,He=123,Ne=124,Ke=125,Xe=126,Re=127,Ye=128,je=129,qe=130,Ge=131,Je=132,Qe=133,Ze=134,$e=135,tn=136,en=137,nn=138,sn=139,an=140,rn=141,on=142,ln=143,fn=144,hn=145,Un=146,cn=147,_n=148,pn=149,gn=150,yn=151,xn=152,un=153,bn=154,dn=155,wn=156,mn=157,Dn=158,Bn=159,Ln=160,vn=161,An=162,kn=163,Vn=164,In=165,Sn=166,Fn=167,On=168,En=169,Tn=170,Cn=171,Mn=172,Pn=173,zn=174,Wn=175,Hn=176,Nn=177,Kn=178,Xn=179,Rn=180,Yn=181,jn=182,qn=183,Gn=184,Jn=1000156007,Qn=1000156008,Zn=1000156009,$n=1000156010,ti=1000156011,ei=1000156017,ni=1000156018,ii=1000156019,si=1000156020,ai=1000156021,ri=1000054e3,oi=1000054001,li=1000054002,fi=1000054003,hi=1000054004,Ui=1000054005,ci=1000054006,_i=1000054007,pi=1000066e3,gi=1000066001,yi=1000066002,xi=1000066003,ui=1000066004,bi=1000066005,di=1000066006,wi=1000066007,mi=1000066008,Di=1000066009,Bi=1000066010,Li=1000066011,vi=1000066012,Ai=1000066013,ki=100034e4,Vi=1000340001;class Ii{constructor(){this.vkFormat=0,this.typeSize=1,this.pixelWidth=0,this.pixelHeight=0,this.pixelDepth=0,this.layerCount=0,this.faceCount=1,this.supercompressionScheme=0,this.levels=[],this.dataFormatDescriptor=[{vendorId:0,descriptorType:0,descriptorBlockSize:0,versionNumber:2,colorModel:0,colorPrimaries:1,transferFunction:2,flags:0,texelBlockDimension:[0,0,0,0],bytesPlane:[0,0,0,0,0,0,0,0],samples:[]}],this.keyValue={},this.globalData=null}}class Si{constructor(t,e,n,i){this._dataView=void 0,this._littleEndian=void 0,this._offset=void 0,this._dataView=new DataView(t.buffer,t.byteOffset+e,n),this._littleEndian=i,this._offset=0}_nextUint8(){const t=this._dataView.getUint8(this._offset);return this._offset+=1,t}_nextUint16(){const t=this._dataView.getUint16(this._offset,this._littleEndian);return this._offset+=2,t}_nextUint32(){const t=this._dataView.getUint32(this._offset,this._littleEndian);return this._offset+=4,t}_nextUint64(){const t=this._dataView.getUint32(this._offset,this._littleEndian)+2**32*this._dataView.getUint32(this._offset+4,this._littleEndian);return this._offset+=8,t}_nextInt32(){const t=this._dataView.getInt32(this._offset,this._littleEndian);return this._offset+=4,t}_nextUint8Array(t){const e=new Uint8Array(this._dataView.buffer,this._dataView.byteOffset+this._offset,t);return this._offset+=t,e}_skip(t){return this._offset+=t,this}_scan(t,e){void 0===e&&(e=0);const n=this._offset;let i=0;for(;this._dataView.getUint8(this._offset)!==e&&i0?U+a.byteLength:0;c%8&&(c+=8-c%8);const _=[],p=new DataView(new ArrayBuffer(3*t.levels.length*8)),g=new Uint32Array(t.levels.length);let y=0;0===t.supercompressionScheme&&(y=function(t,e){const n=Math.max(t,4),i=Math.min(t,4);let s=n;for(;s%i!=0;)s+=n;return s}(function(t){return t.levels[0].levelData.byteLength/function(t,e){let n=1;const i=[t.pixelWidth,t.pixelHeight,t.pixelDepth],s=function(t){const[e,n,i]=t.dataFormatDescriptor[0].texelBlockDimension;return[e+1,n+1,i+1]}(t);for(let t=0;t<3;t++)if(i[t]>0){const e=Math.ceil(Math.floor(i[t]*Math.pow(2,-0))/s[t]);n*=Math.max(1,e)}return t.layerCount>0&&(n*=t.layerCount),t.faceCount>0&&(n*=t.faceCount),n}(t)}(t)));let x=(c||U+a.byteLength)+n.byteLength;for(let e=t.levels.length-1;e>=0;e--){if(x%y){const t=Mi(x,y);_.push(new Uint8Array(t)),x+=t}const n=t.levels[e];_.push(n.levelData),g[e]=x,x+=n.levelData.byteLength}for(let e=0;e0?c:0),!0),b.setBigUint64(60,BigInt(n.byteLength),!0),new Uint8Array(Ci([new Uint8Array(Oi).buffer,u,p.buffer,o,a,c>0?new ArrayBuffer(c-(U+a.byteLength)):new ArrayBuffer(0),n,..._]))}export{Z as KHR_DF_CHANNEL_RGBSDA_ALPHA,G as KHR_DF_CHANNEL_RGBSDA_BLUE,Q as KHR_DF_CHANNEL_RGBSDA_DEPTH,q as KHR_DF_CHANNEL_RGBSDA_GREEN,j as KHR_DF_CHANNEL_RGBSDA_RED,J as KHR_DF_CHANNEL_RGBSDA_STENCIL,g as KHR_DF_FLAG_ALPHA_PREMULTIPLIED,p as KHR_DF_FLAG_ALPHA_STRAIGHT,s as KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT,U as KHR_DF_MODEL_ASTC,f as KHR_DF_MODEL_ETC1,c as KHR_DF_MODEL_ETC1S,h as KHR_DF_MODEL_ETC2,l as KHR_DF_MODEL_RGBSDA,_ as KHR_DF_MODEL_UASTC,o as KHR_DF_MODEL_UNSPECIFIED,H as KHR_DF_PRIMARIES_ACES,N as KHR_DF_PRIMARIES_ACESCC,Y as KHR_DF_PRIMARIES_ADOBERGB,z as KHR_DF_PRIMARIES_BT2020,M as KHR_DF_PRIMARIES_BT601_EBU,P as KHR_DF_PRIMARIES_BT601_SMPTE,C as KHR_DF_PRIMARIES_BT709,W as KHR_DF_PRIMARIES_CIEXYZ,R as KHR_DF_PRIMARIES_DISPLAYP3,K as KHR_DF_PRIMARIES_NTSC1953,X as KHR_DF_PRIMARIES_PAL525,T as KHR_DF_PRIMARIES_UNSPECIFIED,et as KHR_DF_SAMPLE_DATATYPE_EXPONENT,$ as KHR_DF_SAMPLE_DATATYPE_FLOAT,nt as KHR_DF_SAMPLE_DATATYPE_LINEAR,tt as KHR_DF_SAMPLE_DATATYPE_SIGNED,F as KHR_DF_TRANSFER_ACESCC,O as KHR_DF_TRANSFER_ACESCCT,E as KHR_DF_TRANSFER_ADOBERGB,D as KHR_DF_TRANSFER_BT1886,k as KHR_DF_TRANSFER_DCIP3,L as KHR_DF_TRANSFER_HLG_EOTF,B as KHR_DF_TRANSFER_HLG_OETF,b as KHR_DF_TRANSFER_ITU,x as KHR_DF_TRANSFER_LINEAR,d as KHR_DF_TRANSFER_NTSC,I as KHR_DF_TRANSFER_PAL625_EOTF,V as KHR_DF_TRANSFER_PAL_OETF,v as KHR_DF_TRANSFER_PQ_EOTF,A as KHR_DF_TRANSFER_PQ_OETF,w as KHR_DF_TRANSFER_SLOG,m as KHR_DF_TRANSFER_SLOG2,u as KHR_DF_TRANSFER_SRGB,S as KHR_DF_TRANSFER_ST240,y as KHR_DF_TRANSFER_UNSPECIFIED,a as KHR_DF_VENDORID_KHRONOS,r as KHR_DF_VERSION,e as KHR_SUPERCOMPRESSION_BASISLZ,t as KHR_SUPERCOMPRESSION_NONE,i as KHR_SUPERCOMPRESSION_ZLIB,n as KHR_SUPERCOMPRESSION_ZSTD,Ii as KTX2Container,Ut as VK_FORMAT_A1R5G5B5_UNORM_PACK16,Gt as VK_FORMAT_A2B10G10R10_SINT_PACK32,jt as VK_FORMAT_A2B10G10R10_SNORM_PACK32,qt as VK_FORMAT_A2B10G10R10_UINT_PACK32,Yt as VK_FORMAT_A2B10G10R10_UNORM_PACK32,Rt as VK_FORMAT_A2R10G10B10_SINT_PACK32,Kt as VK_FORMAT_A2R10G10B10_SNORM_PACK32,Xt as VK_FORMAT_A2R10G10B10_UINT_PACK32,Nt as VK_FORMAT_A2R10G10B10_UNORM_PACK32,Vi as VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT,ki as VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT,Li as VK_FORMAT_ASTC_10x10_SFLOAT_BLOCK_EXT,Rn as VK_FORMAT_ASTC_10x10_SRGB_BLOCK,Xn as VK_FORMAT_ASTC_10x10_UNORM_BLOCK,mi as VK_FORMAT_ASTC_10x5_SFLOAT_BLOCK_EXT,zn as VK_FORMAT_ASTC_10x5_SRGB_BLOCK,Pn as VK_FORMAT_ASTC_10x5_UNORM_BLOCK,Di as VK_FORMAT_ASTC_10x6_SFLOAT_BLOCK_EXT,Hn as VK_FORMAT_ASTC_10x6_SRGB_BLOCK,Wn as VK_FORMAT_ASTC_10x6_UNORM_BLOCK,Bi as VK_FORMAT_ASTC_10x8_SFLOAT_BLOCK_EXT,Kn as VK_FORMAT_ASTC_10x8_SRGB_BLOCK,Nn as VK_FORMAT_ASTC_10x8_UNORM_BLOCK,vi as VK_FORMAT_ASTC_12x10_SFLOAT_BLOCK_EXT,jn as VK_FORMAT_ASTC_12x10_SRGB_BLOCK,Yn as VK_FORMAT_ASTC_12x10_UNORM_BLOCK,Ai as VK_FORMAT_ASTC_12x12_SFLOAT_BLOCK_EXT,Gn as VK_FORMAT_ASTC_12x12_SRGB_BLOCK,qn as VK_FORMAT_ASTC_12x12_UNORM_BLOCK,pi as VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT,Dn as VK_FORMAT_ASTC_4x4_SRGB_BLOCK,mn as VK_FORMAT_ASTC_4x4_UNORM_BLOCK,gi as VK_FORMAT_ASTC_5x4_SFLOAT_BLOCK_EXT,Ln as VK_FORMAT_ASTC_5x4_SRGB_BLOCK,Bn as VK_FORMAT_ASTC_5x4_UNORM_BLOCK,yi as VK_FORMAT_ASTC_5x5_SFLOAT_BLOCK_EXT,An as VK_FORMAT_ASTC_5x5_SRGB_BLOCK,vn as VK_FORMAT_ASTC_5x5_UNORM_BLOCK,xi as VK_FORMAT_ASTC_6x5_SFLOAT_BLOCK_EXT,Vn as VK_FORMAT_ASTC_6x5_SRGB_BLOCK,kn as VK_FORMAT_ASTC_6x5_UNORM_BLOCK,ui as VK_FORMAT_ASTC_6x6_SFLOAT_BLOCK_EXT,Sn as VK_FORMAT_ASTC_6x6_SRGB_BLOCK,In as VK_FORMAT_ASTC_6x6_UNORM_BLOCK,bi as VK_FORMAT_ASTC_8x5_SFLOAT_BLOCK_EXT,On as VK_FORMAT_ASTC_8x5_SRGB_BLOCK,Fn as VK_FORMAT_ASTC_8x5_UNORM_BLOCK,di as VK_FORMAT_ASTC_8x6_SFLOAT_BLOCK_EXT,Tn as VK_FORMAT_ASTC_8x6_SRGB_BLOCK,En as VK_FORMAT_ASTC_8x6_UNORM_BLOCK,wi as VK_FORMAT_ASTC_8x8_SFLOAT_BLOCK_EXT,Mn as VK_FORMAT_ASTC_8x8_SRGB_BLOCK,Cn as VK_FORMAT_ASTC_8x8_UNORM_BLOCK,We as VK_FORMAT_B10G11R11_UFLOAT_PACK32,ti as VK_FORMAT_B10X6G10X6R10X6G10X6_422_UNORM_4PACK16,ai as VK_FORMAT_B12X4G12X4R12X4G12X4_422_UNORM_4PACK16,rt as VK_FORMAT_B4G4R4A4_UNORM_PACK16,ht as VK_FORMAT_B5G5R5A1_UNORM_PACK16,lt as VK_FORMAT_B5G6R5_UNORM_PACK16,Wt as VK_FORMAT_B8G8R8A8_SINT,Pt as VK_FORMAT_B8G8R8A8_SNORM,Ht as VK_FORMAT_B8G8R8A8_SRGB,zt as VK_FORMAT_B8G8R8A8_UINT,Mt as VK_FORMAT_B8G8R8A8_UNORM,It as VK_FORMAT_B8G8R8_SINT,kt as VK_FORMAT_B8G8R8_SNORM,St as VK_FORMAT_B8G8R8_SRGB,Vt as VK_FORMAT_B8G8R8_UINT,At as VK_FORMAT_B8G8R8_UNORM,Ze as VK_FORMAT_BC1_RGBA_SRGB_BLOCK,Qe as VK_FORMAT_BC1_RGBA_UNORM_BLOCK,Je as VK_FORMAT_BC1_RGB_SRGB_BLOCK,Ge as VK_FORMAT_BC1_RGB_UNORM_BLOCK,tn as VK_FORMAT_BC2_SRGB_BLOCK,$e as VK_FORMAT_BC2_UNORM_BLOCK,nn as VK_FORMAT_BC3_SRGB_BLOCK,en as VK_FORMAT_BC3_UNORM_BLOCK,an as VK_FORMAT_BC4_SNORM_BLOCK,sn as VK_FORMAT_BC4_UNORM_BLOCK,on as VK_FORMAT_BC5_SNORM_BLOCK,rn as VK_FORMAT_BC5_UNORM_BLOCK,fn as VK_FORMAT_BC6H_SFLOAT_BLOCK,ln as VK_FORMAT_BC6H_UFLOAT_BLOCK,Un as VK_FORMAT_BC7_SRGB_BLOCK,hn as VK_FORMAT_BC7_UNORM_BLOCK,Ne as VK_FORMAT_D16_UNORM,Ye as VK_FORMAT_D16_UNORM_S8_UINT,je as VK_FORMAT_D24_UNORM_S8_UINT,Xe as VK_FORMAT_D32_SFLOAT,qe as VK_FORMAT_D32_SFLOAT_S8_UINT,He as VK_FORMAT_E5B9G9R9_UFLOAT_PACK32,wn as VK_FORMAT_EAC_R11G11_SNORM_BLOCK,dn as VK_FORMAT_EAC_R11G11_UNORM_BLOCK,bn as VK_FORMAT_EAC_R11_SNORM_BLOCK,un as VK_FORMAT_EAC_R11_UNORM_BLOCK,gn as VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK,pn as VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK,xn as VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK,yn as VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK,_n as VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK,cn as VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK,$n as VK_FORMAT_G10X6B10X6G10X6R10X6_422_UNORM_4PACK16,si as VK_FORMAT_G12X4B12X4G12X4R12X4_422_UNORM_4PACK16,hi as VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG,ri as VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG,Ui as VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG,oi as VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG,ci as VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG,li as VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG,_i as VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG,fi as VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG,Zn as VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16,Qn as VK_FORMAT_R10X6G10X6_UNORM_2PACK16,Jn as VK_FORMAT_R10X6_UNORM_PACK16,ii as VK_FORMAT_R12X4G12X4B12X4A12X4_UNORM_4PACK16,ni as VK_FORMAT_R12X4G12X4_UNORM_2PACK16,ei as VK_FORMAT_R12X4_UNORM_PACK16,ge as VK_FORMAT_R16G16B16A16_SFLOAT,pe as VK_FORMAT_R16G16B16A16_SINT,ce as VK_FORMAT_R16G16B16A16_SNORM,_e as VK_FORMAT_R16G16B16A16_UINT,Ue as VK_FORMAT_R16G16B16A16_UNORM,he as VK_FORMAT_R16G16B16_SFLOAT,fe as VK_FORMAT_R16G16B16_SINT,oe as VK_FORMAT_R16G16B16_SNORM,le as VK_FORMAT_R16G16B16_UINT,re as VK_FORMAT_R16G16B16_UNORM,ae as VK_FORMAT_R16G16_SFLOAT,se as VK_FORMAT_R16G16_SINT,ne as VK_FORMAT_R16G16_SNORM,ie as VK_FORMAT_R16G16_UINT,ee as VK_FORMAT_R16G16_UNORM,te as VK_FORMAT_R16_SFLOAT,$t as VK_FORMAT_R16_SINT,Qt as VK_FORMAT_R16_SNORM,Zt as VK_FORMAT_R16_UINT,Jt as VK_FORMAT_R16_UNORM,Ae as VK_FORMAT_R32G32B32A32_SFLOAT,ve as VK_FORMAT_R32G32B32A32_SINT,Le as VK_FORMAT_R32G32B32A32_UINT,Be as VK_FORMAT_R32G32B32_SFLOAT,De as VK_FORMAT_R32G32B32_SINT,me as VK_FORMAT_R32G32B32_UINT,we as VK_FORMAT_R32G32_SFLOAT,de as VK_FORMAT_R32G32_SINT,be as VK_FORMAT_R32G32_UINT,ue as VK_FORMAT_R32_SFLOAT,xe as VK_FORMAT_R32_SINT,ye as VK_FORMAT_R32_UINT,at as VK_FORMAT_R4G4B4A4_UNORM_PACK16,st as VK_FORMAT_R4G4_UNORM_PACK8,ft as VK_FORMAT_R5G5B5A1_UNORM_PACK16,ot as VK_FORMAT_R5G6B5_UNORM_PACK16,ze as VK_FORMAT_R64G64B64A64_SFLOAT,Pe as VK_FORMAT_R64G64B64A64_SINT,Me as VK_FORMAT_R64G64B64A64_UINT,Ce as VK_FORMAT_R64G64B64_SFLOAT,Te as VK_FORMAT_R64G64B64_SINT,Ee as VK_FORMAT_R64G64B64_UINT,Oe as VK_FORMAT_R64G64_SFLOAT,Fe as VK_FORMAT_R64G64_SINT,Se as VK_FORMAT_R64G64_UINT,Ie as VK_FORMAT_R64_SFLOAT,Ve as VK_FORMAT_R64_SINT,ke as VK_FORMAT_R64_UINT,Tt as VK_FORMAT_R8G8B8A8_SINT,Ot as VK_FORMAT_R8G8B8A8_SNORM,Ct as VK_FORMAT_R8G8B8A8_SRGB,Et as VK_FORMAT_R8G8B8A8_UINT,Ft as VK_FORMAT_R8G8B8A8_UNORM,Lt as VK_FORMAT_R8G8B8_SINT,Dt as VK_FORMAT_R8G8B8_SNORM,vt as VK_FORMAT_R8G8B8_SRGB,Bt as VK_FORMAT_R8G8B8_UINT,mt as VK_FORMAT_R8G8B8_UNORM,dt as VK_FORMAT_R8G8_SINT,ut as VK_FORMAT_R8G8_SNORM,wt as VK_FORMAT_R8G8_SRGB,bt as VK_FORMAT_R8G8_UINT,xt as VK_FORMAT_R8G8_UNORM,gt as VK_FORMAT_R8_SINT,_t as VK_FORMAT_R8_SNORM,yt as VK_FORMAT_R8_SRGB,pt as VK_FORMAT_R8_UINT,ct as VK_FORMAT_R8_UNORM,Re as VK_FORMAT_S8_UINT,it as VK_FORMAT_UNDEFINED,Ke as VK_FORMAT_X8_D24_UNORM_PACK32,Pi as read,Wi as write}; diff --git a/examples/jsm/lights/LightProbeGenerator.js b/examples/jsm/lights/LightProbeGenerator.js index 4bd9896c8cd3fd..692c7c219518c7 100644 --- a/examples/jsm/lights/LightProbeGenerator.js +++ b/examples/jsm/lights/LightProbeGenerator.js @@ -7,7 +7,8 @@ import { SRGBColorSpace, NoColorSpace, HalfFloatType, - DataUtils + DataUtils, + WebGLCoordinateSystem } from 'three'; class LightProbeGenerator { @@ -126,7 +127,9 @@ class LightProbeGenerator { } - static fromCubeRenderTarget( renderer, cubeRenderTarget ) { + static async fromCubeRenderTarget( renderer, cubeRenderTarget ) { + + const flip = renderer.coordinateSystem === WebGLCoordinateSystem ? -1 : 1; // The renderTarget must be set to RGBA in order to make readRenderTargetPixels works let totalWeight = 0; @@ -143,12 +146,11 @@ class LightProbeGenerator { const shCoefficients = sh.coefficients; const dataType = cubeRenderTarget.texture.type; + const imageWidth = cubeRenderTarget.width; // assumed to be square - for ( let faceIndex = 0; faceIndex < 6; faceIndex ++ ) { - - const imageWidth = cubeRenderTarget.width; // assumed to be square + let data; - let data; + if ( renderer.isWebGLRenderer ) { if ( dataType === HalfFloatType ) { @@ -162,7 +164,19 @@ class LightProbeGenerator { } - renderer.readRenderTargetPixels( cubeRenderTarget, 0, 0, imageWidth, imageWidth, data, faceIndex ); + } + + for ( let faceIndex = 0; faceIndex < 6; faceIndex ++ ) { + + if ( renderer.isWebGLRenderer ) { + + await renderer.readRenderTargetPixelsAsync( cubeRenderTarget, 0, 0, imageWidth, imageWidth, data, faceIndex ); + + } else { + + data = await renderer.readRenderTargetPixelsAsync( cubeRenderTarget, 0, 0, imageWidth, imageWidth, 0, faceIndex ); + + } const pixelSize = 2 / imageWidth; @@ -194,15 +208,15 @@ class LightProbeGenerator { const pixelIndex = i / 4; - const col = - 1 + ( pixelIndex % imageWidth + 0.5 ) * pixelSize; + const col = ( 1 - ( pixelIndex % imageWidth + 0.5 ) * pixelSize ) * flip; const row = 1 - ( Math.floor( pixelIndex / imageWidth ) + 0.5 ) * pixelSize; switch ( faceIndex ) { - case 0: coord.set( 1, row, - col ); break; + case 0: coord.set( - 1 * flip, row, col * flip ); break; - case 1: coord.set( - 1, row, col ); break; + case 1: coord.set( 1 * flip, row, - col * flip ); break; case 2: coord.set( col, 1, - row ); break; diff --git a/examples/jsm/loaders/ColladaLoader.js b/examples/jsm/loaders/ColladaLoader.js index f3497f33e7d7e8..dbff500338a2e7 100644 --- a/examples/jsm/loaders/ColladaLoader.js +++ b/examples/jsm/loaders/ColladaLoader.js @@ -5,6 +5,7 @@ import { BufferGeometry, ClampToEdgeWrapping, Color, + ColorManagement, DirectionalLight, DoubleSide, FileLoader, @@ -1681,9 +1682,9 @@ class ColladaLoader extends Loader { } - material.color.convertSRGBToLinear(); - if ( material.specular ) material.specular.convertSRGBToLinear(); - if ( material.emissive ) material.emissive.convertSRGBToLinear(); + ColorManagement.toWorkingColorSpace( material.color, SRGBColorSpace ); + if ( material.specular ) ColorManagement.toWorkingColorSpace( material.specular, SRGBColorSpace ); + if ( material.emissive ) ColorManagement.toWorkingColorSpace( material.emissive, SRGBColorSpace ); // @@ -2019,7 +2020,8 @@ class ColladaLoader extends Loader { case 'color': const array = parseFloats( child.textContent ); - data.color = new Color().fromArray( array ).convertSRGBToLinear(); + data.color = new Color().fromArray( array ); + ColorManagement.toWorkingColorSpace( data.color, SRGBColorSpace ); break; case 'falloff_angle': @@ -2548,8 +2550,9 @@ class ColladaLoader extends Loader { tempColor.setRGB( array[ startIndex + 0 ], array[ startIndex + 1 ], - array[ startIndex + 2 ] - ).convertSRGBToLinear(); + array[ startIndex + 2 ], + SRGBColorSpace + ); array[ startIndex + 0 ] = tempColor.r; array[ startIndex + 1 ] = tempColor.g; diff --git a/examples/jsm/loaders/DRACOLoader.js b/examples/jsm/loaders/DRACOLoader.js index 07a4e83898dbbc..ca111d71274d95 100644 --- a/examples/jsm/loaders/DRACOLoader.js +++ b/examples/jsm/loaders/DRACOLoader.js @@ -2,6 +2,7 @@ import { BufferAttribute, BufferGeometry, Color, + ColorManagement, FileLoader, Loader, LinearSRGBColorSpace, @@ -235,7 +236,8 @@ class DRACOLoader extends Loader { for ( let i = 0, il = attribute.count; i < il; i ++ ) { - _color.fromBufferAttribute( attribute, i ).convertSRGBToLinear(); + _color.fromBufferAttribute( attribute, i ); + ColorManagement.toWorkingColorSpace( _color, SRGBColorSpace ); attribute.setXYZ( i, _color.r, _color.g, _color.b ); } diff --git a/examples/jsm/loaders/FBXLoader.js b/examples/jsm/loaders/FBXLoader.js index ee2890e85ca395..bc8d49a7290720 100644 --- a/examples/jsm/loaders/FBXLoader.js +++ b/examples/jsm/loaders/FBXLoader.js @@ -5,6 +5,7 @@ import { BufferGeometry, ClampToEdgeWrapping, Color, + ColorManagement, DirectionalLight, EquirectangularReflectionMapping, Euler, @@ -23,13 +24,14 @@ import { MeshPhongMaterial, NumberKeyframeTrack, Object3D, - OrthographicCamera, PerspectiveCamera, PointLight, PropertyBinding, Quaternion, QuaternionKeyframeTrack, RepeatWrapping, + SRGBColorSpace, + ShapeUtils, Skeleton, SkinnedMesh, SpotLight, @@ -39,10 +41,9 @@ import { Vector2, Vector3, Vector4, - VectorKeyframeTrack, - SRGBColorSpace, - ShapeUtils + VectorKeyframeTrack } from 'three'; + import * as fflate from '../libs/fflate.module.js'; import { NURBSCurve } from '../curves/NURBSCurve.js'; @@ -538,12 +539,12 @@ class FBXTreeParser { if ( materialNode.Diffuse ) { - parameters.color = new Color().fromArray( materialNode.Diffuse.value ).convertSRGBToLinear(); + parameters.color = ColorManagement.toWorkingColorSpace( new Color().fromArray( materialNode.Diffuse.value ), SRGBColorSpace ); } else if ( materialNode.DiffuseColor && ( materialNode.DiffuseColor.type === 'Color' || materialNode.DiffuseColor.type === 'ColorRGB' ) ) { // The blender exporter exports diffuse here instead of in materialNode.Diffuse - parameters.color = new Color().fromArray( materialNode.DiffuseColor.value ).convertSRGBToLinear(); + parameters.color = ColorManagement.toWorkingColorSpace( new Color().fromArray( materialNode.DiffuseColor.value ), SRGBColorSpace ); } @@ -555,12 +556,12 @@ class FBXTreeParser { if ( materialNode.Emissive ) { - parameters.emissive = new Color().fromArray( materialNode.Emissive.value ).convertSRGBToLinear(); + parameters.emissive = ColorManagement.toWorkingColorSpace( new Color().fromArray( materialNode.Emissive.value ), SRGBColorSpace ); } else if ( materialNode.EmissiveColor && ( materialNode.EmissiveColor.type === 'Color' || materialNode.EmissiveColor.type === 'ColorRGB' ) ) { // The blender exporter exports emissive color here instead of in materialNode.Emissive - parameters.emissive = new Color().fromArray( materialNode.EmissiveColor.value ).convertSRGBToLinear(); + parameters.emissive = ColorManagement.toWorkingColorSpace( new Color().fromArray( materialNode.EmissiveColor.value ), SRGBColorSpace ); } @@ -596,12 +597,12 @@ class FBXTreeParser { if ( materialNode.Specular ) { - parameters.specular = new Color().fromArray( materialNode.Specular.value ).convertSRGBToLinear(); + parameters.specular = ColorManagement.toWorkingColorSpace( new Color().fromArray( materialNode.Specular.value ), SRGBColorSpace ); } else if ( materialNode.SpecularColor && materialNode.SpecularColor.type === 'Color' ) { // The blender exporter exports specular color here instead of in materialNode.Specular - parameters.specular = new Color().fromArray( materialNode.SpecularColor.value ).convertSRGBToLinear(); + parameters.specular = ColorManagement.toWorkingColorSpace( new Color().fromArray( materialNode.SpecularColor.value ), SRGBColorSpace ); } @@ -1094,7 +1095,8 @@ class FBXTreeParser { break; case 1: // Orthographic - model = new OrthographicCamera( - width / 2, width / 2, height / 2, - height / 2, nearClippingPlane, farClippingPlane ); + console.warn( 'THREE.FBXLoader: Orthographic cameras not supported yet.' ); + model = new Object3D(); break; default: @@ -1151,7 +1153,7 @@ class FBXTreeParser { if ( lightAttribute.Color !== undefined ) { - color = new Color().fromArray( lightAttribute.Color.value ).convertSRGBToLinear(); + color = ColorManagement.toWorkingColorSpace( new Color().fromArray( lightAttribute.Color.value ), SRGBColorSpace ); } @@ -1329,7 +1331,7 @@ class FBXTreeParser { if ( 'InheritType' in modelNode ) transformData.inheritType = parseInt( modelNode.InheritType.value ); if ( 'RotationOrder' in modelNode ) transformData.eulerOrder = getEulerOrder( modelNode.RotationOrder.value ); - else transformData.eulerOrder = 'ZYX'; + else transformData.eulerOrder = getEulerOrder( 0 ); if ( 'Lcl_Translation' in modelNode ) transformData.translation = modelNode.Lcl_Translation.value; @@ -1477,7 +1479,7 @@ class FBXTreeParser { if ( r !== 0 || g !== 0 || b !== 0 ) { - const color = new Color( r, g, b ).convertSRGBToLinear(); + const color = new Color().setRGB( r, g, b, SRGBColorSpace ); sceneGraph.add( new AmbientLight( color, 1 ) ); } @@ -2319,7 +2321,9 @@ class GeometryParser { for ( let i = 0, c = new Color(); i < buffer.length; i += 4 ) { - c.fromArray( buffer, i ).convertSRGBToLinear().toArray( buffer, i ); + c.fromArray( buffer, i ); + ColorManagement.toWorkingColorSpace( c, SRGBColorSpace ); + c.toArray( buffer, i ); } @@ -2809,10 +2813,13 @@ class AnimationParser { } + // For Maya models using "Joint Orient", Euler order only applies to rotation, not pre/post-rotations + const defaultEulerOrder = getEulerOrder( 0 ); + if ( preRotation !== undefined ) { preRotation = preRotation.map( MathUtils.degToRad ); - preRotation.push( eulerOrder ); + preRotation.push( defaultEulerOrder ); preRotation = new Euler().fromArray( preRotation ); preRotation = new Quaternion().setFromEuler( preRotation ); @@ -2822,7 +2829,7 @@ class AnimationParser { if ( postRotation !== undefined ) { postRotation = postRotation.map( MathUtils.degToRad ); - postRotation.push( eulerOrder ); + postRotation.push( defaultEulerOrder ); postRotation = new Euler().fromArray( postRotation ); postRotation = new Quaternion().setFromEuler( postRotation ).invert(); @@ -4134,10 +4141,13 @@ function generateTransform( transformData ) { if ( transformData.translation ) lTranslationM.setPosition( tempVec.fromArray( transformData.translation ) ); + // For Maya models using "Joint Orient", Euler order only applies to rotation, not pre/post-rotations + const defaultEulerOrder = getEulerOrder( 0 ); + if ( transformData.preRotation ) { const array = transformData.preRotation.map( MathUtils.degToRad ); - array.push( transformData.eulerOrder || Euler.DEFAULT_ORDER ); + array.push( defaultEulerOrder ); lPreRotationM.makeRotationFromEuler( tempEuler.fromArray( array ) ); } @@ -4145,7 +4155,7 @@ function generateTransform( transformData ) { if ( transformData.rotation ) { const array = transformData.rotation.map( MathUtils.degToRad ); - array.push( transformData.eulerOrder || Euler.DEFAULT_ORDER ); + array.push( transformData.eulerOrder || defaultEulerOrder ); lRotationM.makeRotationFromEuler( tempEuler.fromArray( array ) ); } @@ -4153,7 +4163,7 @@ function generateTransform( transformData ) { if ( transformData.postRotation ) { const array = transformData.postRotation.map( MathUtils.degToRad ); - array.push( transformData.eulerOrder || Euler.DEFAULT_ORDER ); + array.push( defaultEulerOrder ); lPostRotationM.makeRotationFromEuler( tempEuler.fromArray( array ) ); lPostRotationM.invert(); diff --git a/examples/jsm/loaders/GLTFLoader.js b/examples/jsm/loaders/GLTFLoader.js index 27170277e22c03..e39cbcb9233e31 100644 --- a/examples/jsm/loaders/GLTFLoader.js +++ b/examples/jsm/loaders/GLTFLoader.js @@ -267,16 +267,6 @@ class GLTFLoader extends Loader { } - setDDSLoader() { - - throw new Error( - - 'THREE.GLTFLoader: "MSFT_texture_dds" no longer supported. Please update to "KHR_texture_basisu".' - - ); - - } - setKTX2Loader( ktx2Loader ) { this.ktx2Loader = ktx2Loader; @@ -3153,6 +3143,9 @@ class GLTFParser { } + // Ignore normalized since we copy from sparse + bufferAttribute.normalized = false; + for ( let i = 0, il = sparseIndices.length; i < il; i ++ ) { const index = sparseIndices[ i ]; @@ -3165,6 +3158,8 @@ class GLTFParser { } + bufferAttribute.normalized = normalized; + } return bufferAttribute; diff --git a/examples/jsm/loaders/KTX2Loader.js b/examples/jsm/loaders/KTX2Loader.js index 95649b9bd691c0..d402f44af27afc 100644 --- a/examples/jsm/loaders/KTX2Loader.js +++ b/examples/jsm/loaders/KTX2Loader.js @@ -9,6 +9,7 @@ * References: * - KTX: http://github.khronos.org/KTX-Specification/ * - DFD: https://www.khronos.org/registry/DataFormat/specs/1.3/dataformat.1.3.html#basicdescriptor + * - BasisU HDR: https://github.com/BinomialLLC/basis_universal/wiki/UASTC-HDR-Texture-Specification-v1.0 */ import { @@ -63,6 +64,7 @@ import { VK_FORMAT_R8G8_UNORM, VK_FORMAT_R8G8B8A8_SRGB, VK_FORMAT_R8G8B8A8_UNORM, + VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT, VK_FORMAT_ASTC_6x6_SRGB_BLOCK, VK_FORMAT_ASTC_6x6_UNORM_BLOCK, KHR_DF_PRIMARIES_UNSPECIFIED, @@ -251,7 +253,7 @@ class KTX2Loader extends Loader { loader.load( url, ( buffer ) => { - this.parse( buffer, onLoad, onError); + this.parse( buffer, onLoad, onError ); }, onProgress, onError ); @@ -269,15 +271,15 @@ class KTX2Loader extends Loader { // again from this thread. if ( _taskCache.has( buffer ) ) { - const cachedTask = _taskCache.get( buffer ); + const cachedTask = _taskCache.get( buffer ); - return cachedTask.promise.then( onLoad ).catch( onError ); + return cachedTask.promise.then( onLoad ).catch( onError ); } this._createTexture( buffer ) - .then( ( texture ) => onLoad ? onLoad( texture ) : null ) - .catch( onError ); + .then( ( texture ) => onLoad ? onLoad( texture ) : null ) + .catch( onError ); } @@ -730,8 +732,7 @@ KTX2Loader.BasisWorker = function () { }; -// -// Parsing for non-Basis textures. These textures are may have supercompression +// Parsing for non-Basis textures. These textures may have supercompression // like Zstd, but they do not require transcoding. const UNCOMPRESSED_FORMATS = new Set( [ RGBAFormat, RGFormat, RedFormat ] ); @@ -753,6 +754,7 @@ const FORMAT_MAP = { [ VK_FORMAT_R8_SRGB ]: RedFormat, [ VK_FORMAT_R8_UNORM ]: RedFormat, + [ VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT ]: RGBA_ASTC_4x4_Format, [ VK_FORMAT_ASTC_6x6_SRGB_BLOCK ]: RGBA_ASTC_6x6_Format, [ VK_FORMAT_ASTC_6x6_UNORM_BLOCK ]: RGBA_ASTC_6x6_Format, @@ -775,6 +777,7 @@ const TYPE_MAP = { [ VK_FORMAT_R8_SRGB ]: UnsignedByteType, [ VK_FORMAT_R8_UNORM ]: UnsignedByteType, + [ VK_FORMAT_ASTC_4x4_SFLOAT_BLOCK_EXT ]: HalfFloatType, [ VK_FORMAT_ASTC_6x6_SRGB_BLOCK ]: UnsignedByteType, [ VK_FORMAT_ASTC_6x6_UNORM_BLOCK ]: UnsignedByteType, diff --git a/examples/jsm/loaders/MTLLoader.js b/examples/jsm/loaders/MTLLoader.js index f277c973536ea4..41d7663d967650 100644 --- a/examples/jsm/loaders/MTLLoader.js +++ b/examples/jsm/loaders/MTLLoader.js @@ -1,5 +1,6 @@ import { Color, + ColorManagement, DefaultLoadingManager, FileLoader, FrontSide, @@ -384,21 +385,21 @@ class MaterialCreator { // Diffuse color (color under white light) using RGB values - params.color = new Color().fromArray( value ).convertSRGBToLinear(); + params.color = ColorManagement.toWorkingColorSpace( new Color().fromArray( value ), SRGBColorSpace ); break; case 'ks': // Specular color (color when light is reflected from shiny surface) using RGB values - params.specular = new Color().fromArray( value ).convertSRGBToLinear(); + params.specular = ColorManagement.toWorkingColorSpace( new Color().fromArray( value ), SRGBColorSpace ); break; case 'ke': // Emissive using RGB values - params.emissive = new Color().fromArray( value ).convertSRGBToLinear(); + params.emissive = ColorManagement.toWorkingColorSpace( new Color().fromArray( value ), SRGBColorSpace ); break; diff --git a/examples/jsm/loaders/MaterialXLoader.js b/examples/jsm/loaders/MaterialXLoader.js index 051438732d6047..371e357e804438 100644 --- a/examples/jsm/loaders/MaterialXLoader.js +++ b/examples/jsm/loaders/MaterialXLoader.js @@ -7,7 +7,7 @@ import { add, sub, mul, div, mod, abs, sign, floor, ceil, round, pow, sin, cos, tan, asin, acos, atan2, sqrt, exp, clamp, min, max, normalize, length, dot, cross, normalMap, remap, smoothstep, luminance, mx_rgbtohsv, mx_hsvtorgb, - mix, + mix, split, mx_ramplr, mx_ramptb, mx_splitlr, mx_splittb, mx_fractal_noise_float, mx_noise_float, mx_cell_noise_float, mx_worley_noise_float, mx_transform_uv, @@ -44,6 +44,10 @@ const mx_power = ( in1, in2 = float( 1 ) ) => pow( in1, in2 ); const mx_atan2 = ( in1 = float( 0 ), in2 = float( 1 ) ) => atan2( in1, in2 ); const mx_timer = () => timerLocal(); const mx_frame = () => frameId; +const mx_invert = ( in1, amount = float( 1 ) ) => sub( amount, in1 ); + +const separate = ( in1, channel ) => split( in1, channel.at( - 1 ) ); +const extract = ( in1, index ) => in1.element( index ); const MXElements = [ @@ -75,6 +79,7 @@ const MXElements = [ new MXElement( 'magnitude', length, [ 'in1', 'in2' ] ), new MXElement( 'dotproduct', dot, [ 'in1', 'in2' ] ), new MXElement( 'crossproduct', cross, [ 'in' ] ), + new MXElement( 'invert', mx_invert, [ 'in', 'amount' ] ), //new MtlXElement( 'transformpoint', ... ), //new MtlXElement( 'transformvector', ... ), //new MtlXElement( 'transformnormal', ... ), @@ -127,10 +132,10 @@ const MXElements = [ new MXElement( 'contrast', mx_contrast, [ 'in', 'amount', 'pivot' ] ), //new MtlXElement( 'hsvadjust', ... ), new MXElement( 'saturate', saturation, [ 'in', 'amount' ] ), - //new MtlXElement( 'extract', ... ), - //new MtlXElement( 'separate2', ... ), - //new MtlXElement( 'separate3', ... ), - //new MtlXElement( 'separate4', ... ) + new MXElement( 'extract', extract, [ 'in', 'index' ] ), + new MXElement( 'separate2', separate, [ 'in' ] ), + new MXElement( 'separate3', separate, [ 'in' ] ), + new MXElement( 'separate4', separate, [ 'in' ] ), new MXElement( 'time', mx_timer ), new MXElement( 'frame', mx_frame ) @@ -369,11 +374,11 @@ class MaterialXNode { } - getNode() { + getNode( out = null ) { let node = this.node; - if ( node !== null ) { + if ( node !== null && out === null ) { return node; @@ -391,7 +396,13 @@ class MaterialXNode { } else if ( this.hasReference ) { - node = this.materialX.getMaterialXNode( this.referencePath ).getNode(); + if ( this.element === 'output' && this.output && out === null ) { + + out = this.output; + + } + + node = this.materialX.getMaterialXNode( this.referencePath ).getNode( out ); } else { @@ -474,7 +485,15 @@ class MaterialXNode { const nodeElement = MtlXLibrary[ element ]; - node = nodeElement.nodeFunc( ...this.getNodesByNames( ...nodeElement.params ) ); + if ( out !== null ) { + + node = nodeElement.nodeFunc( ...this.getNodesByNames( ...nodeElement.params ), out ); + + } else { + + node = nodeElement.nodeFunc( ...this.getNodesByNames( ...nodeElement.params ) ); + + } } @@ -542,7 +561,7 @@ class MaterialXNode { const child = this.getChildByName( name ); - return child ? child.getNode() : undefined; + return child ? child.getNode( child.output ) : undefined; } diff --git a/examples/jsm/loaders/OBJLoader.js b/examples/jsm/loaders/OBJLoader.js index 7792458abce807..c6bc16c12c8414 100644 --- a/examples/jsm/loaders/OBJLoader.js +++ b/examples/jsm/loaders/OBJLoader.js @@ -12,7 +12,8 @@ import { Points, PointsMaterial, Vector3, - Color + Color, + SRGBColorSpace } from 'three'; // o object_name | g group_name @@ -534,8 +535,9 @@ class OBJLoader extends Loader { _color.setRGB( parseFloat( data[ 4 ] ), parseFloat( data[ 5 ] ), - parseFloat( data[ 6 ] ) - ).convertSRGBToLinear(); + parseFloat( data[ 6 ] ), + SRGBColorSpace + ); state.colors.push( _color.r, _color.g, _color.b ); diff --git a/examples/jsm/loaders/PCDLoader.js b/examples/jsm/loaders/PCDLoader.js index 49f7c8334f9e1a..8cd6edbabc9df3 100644 --- a/examples/jsm/loaders/PCDLoader.js +++ b/examples/jsm/loaders/PCDLoader.js @@ -6,7 +6,8 @@ import { Int32BufferAttribute, Loader, Points, - PointsMaterial + PointsMaterial, + SRGBColorSpace } from 'three'; class PCDLoader extends Loader { @@ -279,7 +280,7 @@ class PCDLoader extends Loader { const g = ( ( rgb >> 8 ) & 0x0000ff ) / 255; const b = ( ( rgb >> 0 ) & 0x0000ff ) / 255; - c.set( r, g, b ).convertSRGBToLinear(); + c.setRGB( r, g, b, SRGBColorSpace ); color.push( c.r, c.g, c.b ); @@ -346,7 +347,7 @@ class PCDLoader extends Loader { const g = dataview.getUint8( ( PCDheader.points * offset.rgb ) + PCDheader.size[ rgbIndex ] * i + 1 ) / 255.0; const b = dataview.getUint8( ( PCDheader.points * offset.rgb ) + PCDheader.size[ rgbIndex ] * i + 0 ) / 255.0; - c.set( r, g, b ).convertSRGBToLinear(); + c.setRGB( r, g, b, SRGBColorSpace ); color.push( c.r, c.g, c.b ); @@ -404,7 +405,7 @@ class PCDLoader extends Loader { const g = dataview.getUint8( row + offset.rgb + 1 ) / 255.0; const b = dataview.getUint8( row + offset.rgb + 0 ) / 255.0; - c.set( r, g, b ).convertSRGBToLinear(); + c.setRGB( r, g, b, SRGBColorSpace ); color.push( c.r, c.g, c.b ); diff --git a/examples/jsm/loaders/PDBLoader.js b/examples/jsm/loaders/PDBLoader.js index bb24a5510d86e3..2be3aa2b688d6a 100644 --- a/examples/jsm/loaders/PDBLoader.js +++ b/examples/jsm/loaders/PDBLoader.js @@ -3,7 +3,8 @@ import { FileLoader, Float32BufferAttribute, Loader, - Color + Color, + SRGBColorSpace } from 'three'; class PDBLoader extends Loader { @@ -131,7 +132,7 @@ class PDBLoader extends Loader { const g = atom[ 3 ][ 1 ] / 255; const b = atom[ 3 ][ 2 ] / 255; - c.set( r, g, b ).convertSRGBToLinear(); + c.setRGB( r, g, b, SRGBColorSpace ); colorsAtoms.push( c.r, c.g, c.b ); diff --git a/examples/jsm/loaders/PLYLoader.js b/examples/jsm/loaders/PLYLoader.js index 3834bfbfd36984..2e83745d7cf1c3 100644 --- a/examples/jsm/loaders/PLYLoader.js +++ b/examples/jsm/loaders/PLYLoader.js @@ -3,7 +3,8 @@ import { FileLoader, Float32BufferAttribute, Loader, - Color + Color, + SRGBColorSpace } from 'three'; /** @@ -468,8 +469,9 @@ class PLYLoader extends Loader { _color.setRGB( element[ cacheEntry.attrR ] / 255.0, element[ cacheEntry.attrG ] / 255.0, - element[ cacheEntry.attrB ] / 255.0 - ).convertSRGBToLinear(); + element[ cacheEntry.attrB ] / 255.0, + SRGBColorSpace + ); buffer.colors.push( _color.r, _color.g, _color.b ); @@ -516,8 +518,9 @@ class PLYLoader extends Loader { _color.setRGB( element[ cacheEntry.attrR ] / 255.0, element[ cacheEntry.attrG ] / 255.0, - element[ cacheEntry.attrB ] / 255.0 - ).convertSRGBToLinear(); + element[ cacheEntry.attrB ] / 255.0, + SRGBColorSpace + ); buffer.faceVertexColors.push( _color.r, _color.g, _color.b ); buffer.faceVertexColors.push( _color.r, _color.g, _color.b ); buffer.faceVertexColors.push( _color.r, _color.g, _color.b ); diff --git a/examples/jsm/loaders/STLLoader.js b/examples/jsm/loaders/STLLoader.js index 75d4f84586b83c..b94b8069555cdf 100644 --- a/examples/jsm/loaders/STLLoader.js +++ b/examples/jsm/loaders/STLLoader.js @@ -5,7 +5,8 @@ import { FileLoader, Float32BufferAttribute, Loader, - Vector3 + Vector3, + SRGBColorSpace } from 'three'; /** @@ -242,7 +243,7 @@ class STLLoader extends Loader { if ( hasColors ) { - color.set( r, g, b ).convertSRGBToLinear(); + color.setRGB( r, g, b, SRGBColorSpace ); colors[ componentIdx ] = color.r; colors[ componentIdx + 1 ] = color.g; diff --git a/examples/jsm/loaders/TiltLoader.js b/examples/jsm/loaders/TiltLoader.js deleted file mode 100644 index b8e6a8d935eceb..00000000000000 --- a/examples/jsm/loaders/TiltLoader.js +++ /dev/null @@ -1,520 +0,0 @@ -import { - BufferAttribute, - BufferGeometry, - Color, - DoubleSide, - FileLoader, - Group, - Loader, - Mesh, - MeshBasicMaterial, - RawShaderMaterial, - TextureLoader, - Quaternion, - Vector3 -} from 'three'; -import * as fflate from '../libs/fflate.module.js'; - -class TiltLoader extends Loader { - - load( url, onLoad, onProgress, onError ) { - - const scope = this; - - const loader = new FileLoader( this.manager ); - loader.setPath( this.path ); - loader.setResponseType( 'arraybuffer' ); - loader.setWithCredentials( this.withCredentials ); - - loader.load( url, function ( buffer ) { - - try { - - onLoad( scope.parse( buffer ) ); - - } catch ( e ) { - - if ( onError ) { - - onError( e ); - - } else { - - console.error( e ); - - } - - scope.manager.itemError( url ); - - } - - }, onProgress, onError ); - - } - - parse( buffer ) { - - const group = new Group(); - // https://docs.google.com/document/d/11ZsHozYn9FnWG7y3s3WAyKIACfbfwb4PbaS8cZ_xjvo/edit# - - const zip = fflate.unzipSync( new Uint8Array( buffer.slice( 16 ) ) ); - - /* - const thumbnail = zip[ 'thumbnail.png' ].buffer; - const img = document.createElement( 'img' ); - img.src = URL.createObjectURL( new Blob( [ thumbnail ] ) ); - document.body.appendChild( img ); - */ - - const metadata = JSON.parse( fflate.strFromU8( zip[ 'metadata.json' ] ) ); - - /* - const blob = new Blob( [ zip[ 'data.sketch' ].buffer ], { type: 'application/octet-stream' } ); - window.open( URL.createObjectURL( blob ) ); - */ - - const data = new DataView( zip[ 'data.sketch' ].buffer ); - - const num_strokes = data.getInt32( 16, true ); - - const brushes = {}; - - let offset = 20; - - for ( let i = 0; i < num_strokes; i ++ ) { - - const brush_index = data.getInt32( offset, true ); - - const brush_color = [ - data.getFloat32( offset + 4, true ), - data.getFloat32( offset + 8, true ), - data.getFloat32( offset + 12, true ), - data.getFloat32( offset + 16, true ) - ]; - const brush_size = data.getFloat32( offset + 20, true ); - const stroke_mask = data.getUint32( offset + 24, true ); - const controlpoint_mask = data.getUint32( offset + 28, true ); - - let offset_stroke_mask = 0; - let offset_controlpoint_mask = 0; - - for ( let j = 0; j < 4; j ++ ) { - - // TOFIX: I don't understand these masks yet - - const byte = 1 << j; - if ( ( stroke_mask & byte ) > 0 ) offset_stroke_mask += 4; - if ( ( controlpoint_mask & byte ) > 0 ) offset_controlpoint_mask += 4; - - } - - // console.log( { brush_index, brush_color, brush_size, stroke_mask, controlpoint_mask } ); - // console.log( offset_stroke_mask, offset_controlpoint_mask ); - - offset = offset + 28 + offset_stroke_mask + 4; // TOFIX: This is wrong - - const num_control_points = data.getInt32( offset, true ); - - // console.log( { num_control_points } ); - - const positions = new Float32Array( num_control_points * 3 ); - const quaternions = new Float32Array( num_control_points * 4 ); - - offset = offset + 4; - - for ( let j = 0, k = 0; j < positions.length; j += 3, k += 4 ) { - - positions[ j + 0 ] = data.getFloat32( offset + 0, true ); - positions[ j + 1 ] = data.getFloat32( offset + 4, true ); - positions[ j + 2 ] = data.getFloat32( offset + 8, true ); - - quaternions[ k + 0 ] = data.getFloat32( offset + 12, true ); - quaternions[ k + 1 ] = data.getFloat32( offset + 16, true ); - quaternions[ k + 2 ] = data.getFloat32( offset + 20, true ); - quaternions[ k + 3 ] = data.getFloat32( offset + 24, true ); - - offset = offset + 28 + offset_controlpoint_mask; // TOFIX: This is wrong - - } - - if ( brush_index in brushes === false ) { - - brushes[ brush_index ] = []; - - } - - brushes[ brush_index ].push( [ positions, quaternions, brush_size, brush_color ] ); - - } - - for ( const brush_index in brushes ) { - - const geometry = new StrokeGeometry( brushes[ brush_index ] ); - const material = getMaterial( metadata.BrushIndex[ brush_index ] ); - - group.add( new Mesh( geometry, material ) ); - - } - - return group; - - } - -} - -class StrokeGeometry extends BufferGeometry { - - constructor( strokes ) { - - super(); - - const vertices = []; - const colors = []; - const uvs = []; - - const position = new Vector3(); - const prevPosition = new Vector3(); - - const quaternion = new Quaternion(); - const prevQuaternion = new Quaternion(); - - const vector1 = new Vector3(); - const vector2 = new Vector3(); - const vector3 = new Vector3(); - const vector4 = new Vector3(); - - const color = new Color(); - - // size = size / 2; - - for ( const k in strokes ) { - - const stroke = strokes[ k ]; - const positions = stroke[ 0 ]; - const quaternions = stroke[ 1 ]; - const size = stroke[ 2 ]; - const rgba = stroke[ 3 ]; - const alpha = stroke[ 3 ][ 3 ]; - - color.fromArray( rgba ).convertSRGBToLinear(); - - prevPosition.fromArray( positions, 0 ); - prevQuaternion.fromArray( quaternions, 0 ); - - for ( let i = 3, j = 4, l = positions.length; i < l; i += 3, j += 4 ) { - - position.fromArray( positions, i ); - quaternion.fromArray( quaternions, j ); - - vector1.set( - size, 0, 0 ); - vector1.applyQuaternion( quaternion ); - vector1.add( position ); - - vector2.set( size, 0, 0 ); - vector2.applyQuaternion( quaternion ); - vector2.add( position ); - - vector3.set( size, 0, 0 ); - vector3.applyQuaternion( prevQuaternion ); - vector3.add( prevPosition ); - - vector4.set( - size, 0, 0 ); - vector4.applyQuaternion( prevQuaternion ); - vector4.add( prevPosition ); - - vertices.push( vector1.x, vector1.y, - vector1.z ); - vertices.push( vector2.x, vector2.y, - vector2.z ); - vertices.push( vector4.x, vector4.y, - vector4.z ); - - vertices.push( vector2.x, vector2.y, - vector2.z ); - vertices.push( vector3.x, vector3.y, - vector3.z ); - vertices.push( vector4.x, vector4.y, - vector4.z ); - - prevPosition.copy( position ); - prevQuaternion.copy( quaternion ); - - colors.push( ...color, alpha ); - colors.push( ...color, alpha ); - colors.push( ...color, alpha ); - - colors.push( ...color, alpha ); - colors.push( ...color, alpha ); - colors.push( ...color, alpha ); - - const p1 = i / l; - const p2 = ( i - 3 ) / l; - - uvs.push( p1, 0 ); - uvs.push( p1, 1 ); - uvs.push( p2, 0 ); - - uvs.push( p1, 1 ); - uvs.push( p2, 1 ); - uvs.push( p2, 0 ); - - } - - } - - this.setAttribute( 'position', new BufferAttribute( new Float32Array( vertices ), 3 ) ); - this.setAttribute( 'color', new BufferAttribute( new Float32Array( colors ), 4 ) ); - this.setAttribute( 'uv', new BufferAttribute( new Float32Array( uvs ), 2 ) ); - - } - -} - -const BRUSH_LIST_ARRAY = { - '89d104cd-d012-426b-b5b3-bbaee63ac43c': 'Bubbles', - '700f3aa8-9a7c-2384-8b8a-ea028905dd8c': 'CelVinyl', - '0f0ff7b2-a677-45eb-a7d6-0cd7206f4816': 'ChromaticWave', - '1161af82-50cf-47db-9706-0c3576d43c43': 'CoarseBristles', - '79168f10-6961-464a-8be1-57ed364c5600': 'CoarseBristlesSingleSided', - '1caa6d7d-f015-3f54-3a4b-8b5354d39f81': 'Comet', - 'c8313697-2563-47fc-832e-290f4c04b901': 'DiamondHull', - '4391aaaa-df73-4396-9e33-31e4e4930b27': 'Disco', - 'd1d991f2-e7a0-4cf1-b328-f57e915e6260': 'DotMarker', - '6a1cf9f9-032c-45ec-9b1d-a6680bee30f7': 'Dots', - '0d3889f3-3ede-470c-8af4-f44813306126': 'DoubleTaperedFlat', - '0d3889f3-3ede-470c-8af4-de4813306126': 'DoubleTaperedMarker', - 'd0262945-853c-4481-9cbd-88586bed93cb': 'DuctTape', - '3ca16e2f-bdcd-4da2-8631-dcef342f40f1': 'DuctTapeSingleSided', - 'f6e85de3-6dcc-4e7f-87fd-cee8c3d25d51': 'Electricity', - '02ffb866-7fb2-4d15-b761-1012cefb1360': 'Embers', - 'cb92b597-94ca-4255-b017-0e3f42f12f9e': 'Fire', - '2d35bcf0-e4d8-452c-97b1-3311be063130': 'Flat', - '55303bc4-c749-4a72-98d9-d23e68e76e18': 'FlatDeprecated', - '280c0a7a-aad8-416c-a7d2-df63d129ca70': 'FlatSingleSided', - 'cf019139-d41c-4eb0-a1d0-5cf54b0a42f3': 'Highlighter', - '6a1cf9f9-032c-45ec-9b6e-a6680bee32e9': 'HyperGrid', - 'dce872c2-7b49-4684-b59b-c45387949c5c': 'Hypercolor', - 'e8ef32b1-baa8-460a-9c2c-9cf8506794f5': 'HypercolorSingleSided', - '2f212815-f4d3-c1a4-681a-feeaf9c6dc37': 'Icing', - 'f5c336cf-5108-4b40-ade9-c687504385ab': 'Ink', - 'c0012095-3ffd-4040-8ee1-fc180d346eaa': 'InkSingleSided', - '4a76a27a-44d8-4bfe-9a8c-713749a499b0': 'Leaves', - 'ea19de07-d0c0-4484-9198-18489a3c1487': 'LeavesSingleSided', - '2241cd32-8ba2-48a5-9ee7-2caef7e9ed62': 'Light', - '4391aaaa-df81-4396-9e33-31e4e4930b27': 'LightWire', - 'd381e0f5-3def-4a0d-8853-31e9200bcbda': 'Lofted', - '429ed64a-4e97-4466-84d3-145a861ef684': 'Marker', - '79348357-432d-4746-8e29-0e25c112e3aa': 'MatteHull', - 'b2ffef01-eaaa-4ab5-aa64-95a2c4f5dbc6': 'NeonPulse', - 'f72ec0e7-a844-4e38-82e3-140c44772699': 'OilPaint', - 'c515dad7-4393-4681-81ad-162ef052241b': 'OilPaintSingleSided', - 'f1114e2e-eb8d-4fde-915a-6e653b54e9f5': 'Paper', - '759f1ebd-20cd-4720-8d41-234e0da63716': 'PaperSingleSided', - 'e0abbc80-0f80-e854-4970-8924a0863dcc': 'Petal', - 'c33714d1-b2f9-412e-bd50-1884c9d46336': 'Plasma', - 'ad1ad437-76e2-450d-a23a-e17f8310b960': 'Rainbow', - 'faaa4d44-fcfb-4177-96be-753ac0421ba3': 'ShinyHull', - '70d79cca-b159-4f35-990c-f02193947fe8': 'Smoke', - 'd902ed8b-d0d1-476c-a8de-878a79e3a34c': 'Snow', - 'accb32f5-4509-454f-93f8-1df3fd31df1b': 'SoftHighlighter', - 'cf7f0059-7aeb-53a4-2b67-c83d863a9ffa': 'Spikes', - '8dc4a70c-d558-4efd-a5ed-d4e860f40dc3': 'Splatter', - '7a1c8107-50c5-4b70-9a39-421576d6617e': 'SplatterSingleSided', - '0eb4db27-3f82-408d-b5a1-19ebd7d5b711': 'Stars', - '44bb800a-fbc3-4592-8426-94ecb05ddec3': 'Streamers', - '0077f88c-d93a-42f3-b59b-b31c50cdb414': 'Taffy', - 'b468c1fb-f254-41ed-8ec9-57030bc5660c': 'TaperedFlat', - 'c8ccb53d-ae13-45ef-8afb-b730d81394eb': 'TaperedFlatSingleSided', - 'd90c6ad8-af0f-4b54-b422-e0f92abe1b3c': 'TaperedMarker', - '1a26b8c0-8a07-4f8a-9fac-d2ef36e0cad0': 'TaperedMarker_Flat', - '75b32cf0-fdd6-4d89-a64b-e2a00b247b0f': 'ThickPaint', - 'fdf0326a-c0d1-4fed-b101-9db0ff6d071f': 'ThickPaintSingleSided', - '4391385a-df73-4396-9e33-31e4e4930b27': 'Toon', - 'a8fea537-da7c-4d4b-817f-24f074725d6d': 'UnlitHull', - 'd229d335-c334-495a-a801-660ac8a87360': 'VelvetInk', - '10201aa3-ebc2-42d8-84b7-2e63f6eeb8ab': 'Waveform', - 'b67c0e81-ce6d-40a8-aeb0-ef036b081aa3': 'WetPaint', - 'dea67637-cd1a-27e4-c9b1-52f4bbcb84e5': 'WetPaintSingleSided', - '5347acf0-a8e2-47b6-8346-30c70719d763': 'WigglyGraphite', - 'e814fef1-97fd-7194-4a2f-50c2bb918be2': 'WigglyGraphiteSingleSided', - '4391385a-cf83-4396-9e33-31e4e4930b27': 'Wire' -}; - -const common = { - - 'colors': { - - 'BloomColor': ` - vec3 BloomColor(vec3 color, float gain) { - // Guarantee that there's at least a little bit of all 3 channels. - // This makes fully-saturated strokes (which only have 2 non-zero - // color channels) eventually clip to white rather than to a secondary. - float cmin = length(color.rgb) * .05; - color.rgb = max(color.rgb, vec3(cmin, cmin, cmin)); - // If we try to remove this pow() from .a, it brightens up - // pressure-sensitive strokes; looks better as-is. - color = pow(color, vec3(2.2)); - color.rgb *= 2. * exp(gain * 10.); - return color; - } - `, - - 'LinearToSrgb': ` - vec3 LinearToSrgb(vec3 color) { - // Approximation http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html - vec3 linearColor = color.rgb; - vec3 S1 = sqrt(linearColor); - vec3 S2 = sqrt(S1); - vec3 S3 = sqrt(S2); - color.rgb = 0.662002687 * S1 + 0.684122060 * S2 - 0.323583601 * S3 - 0.0225411470 * linearColor; - return color; - } - `, - - 'hsv': ` - // uniform sampler2D lookupTex; - vec4 lookup(vec4 textureColor) { - return textureColor; - } - - vec3 lookup(vec3 textureColor) { - return textureColor; - } - - vec3 hsv2rgb( vec3 hsv ) { - vec3 rgb = clamp( abs(mod(hsv.x*6.0+vec3(0.0,4.0,2.0),6.0)-3.0)-1.0, 0.0, 1.0 ); - return hsv.z * mix( vec3(1.0), rgb, hsv.y); - } - - vec3 rgb2hsv( vec3 rgb ) { - vec4 K = vec4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0); - vec4 p = mix(vec4(rgb.bg, K.wz), vec4(rgb.gb, K.xy), step(rgb.b, rgb.g)); - vec4 q = mix(vec4(p.xyw, rgb.r), vec4(rgb.r, p.yzx), step(p.x, rgb.r)); - - float d = q.x - min(q.w, q.y); - float e = 1.0e-10; - - return vec3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x); - } - `, - - 'SrgbToLinear': ` - vec3 SrgbToLinear(vec3 color) { - // Approximation http://chilliant.blogspot.com/2012/08/srgb-approximations-for-hlsl.html - vec3 sRGB = color.rgb; - color.rgb = sRGB * (sRGB * (sRGB * 0.305306011 + 0.682171111) + 0.012522878); - return color; - } - ` - - } - -}; - -let shaders = null; - -function getShaders() { - - if ( shaders === null ) { - - const loader = new TextureLoader().setPath( './textures/tiltbrush/' ); - - shaders = { - 'Light': { - uniforms: { - mainTex: { value: loader.load( 'Light.webp' ) }, - alphaTest: { value: 0.067 }, - emission_gain: { value: 0.45 }, - alpha: { value: 1 }, - }, - vertexShader: ` - precision highp float; - precision highp int; - - attribute vec2 uv; - attribute vec4 color; - attribute vec3 position; - - uniform mat4 modelMatrix; - uniform mat4 modelViewMatrix; - uniform mat4 projectionMatrix; - uniform mat4 viewMatrix; - uniform mat3 normalMatrix; - uniform vec3 cameraPosition; - - varying vec2 vUv; - varying vec3 vColor; - - ${ common.colors.LinearToSrgb } - ${ common.colors.hsv } - - void main() { - - vUv = uv; - - vColor = lookup(color.rgb); - - vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 ); - - gl_Position = projectionMatrix * mvPosition; - - } - `, - fragmentShader: ` - precision highp float; - precision highp int; - - uniform float emission_gain; - - uniform sampler2D mainTex; - uniform float alphaTest; - - varying vec2 vUv; - varying vec3 vColor; - - ${ common.colors.BloomColor } - ${ common.colors.SrgbToLinear } - - void main(){ - vec4 col = texture2D(mainTex, vUv); - vec3 color = vColor; - color = BloomColor(color, emission_gain); - color = color * col.rgb; - color = color * col.a; - color = SrgbToLinear(color); - gl_FragColor = vec4(color, 1.0); - } - `, - side: 2, - transparent: true, - depthFunc: 2, - depthWrite: true, - depthTest: false, - blending: 5, - blendDst: 201, - blendDstAlpha: 201, - blendEquation: 100, - blendEquationAlpha: 100, - blendSrc: 201, - blendSrcAlpha: 201, - } - - }; - - } - - return shaders; - -} - -function getMaterial( GUID ) { - - const name = BRUSH_LIST_ARRAY[ GUID ]; - - switch ( name ) { - - case 'Light': - return new RawShaderMaterial( getShaders().Light ); - - default: - return new MeshBasicMaterial( { vertexColors: true, side: DoubleSide } ); - - } - -} - -export { TiltLoader }; diff --git a/examples/jsm/loaders/VRMLLoader.js b/examples/jsm/loaders/VRMLLoader.js index fc5098a72171c5..e8e6022d2eca72 100644 --- a/examples/jsm/loaders/VRMLLoader.js +++ b/examples/jsm/loaders/VRMLLoader.js @@ -5,6 +5,7 @@ import { BufferGeometry, ClampToEdgeWrapping, Color, + ColorManagement, ConeGeometry, CylinderGeometry, DataTexture, @@ -918,8 +919,7 @@ class VRMLLoader extends Loader { } else { - skyMaterial.color.setRGB( skyColor[ 0 ], skyColor[ 1 ], skyColor[ 2 ] ); - skyMaterial.color.convertSRGBToLinear(); + skyMaterial.color.setRGB( skyColor[ 0 ], skyColor[ 1 ], skyColor[ 2 ], SRGBColorSpace ); } @@ -1240,13 +1240,11 @@ class VRMLLoader extends Loader { break; case 'diffuseColor': - materialData.diffuseColor = new Color( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] ); - materialData.diffuseColor.convertSRGBToLinear(); + materialData.diffuseColor = new Color().setRGB( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ], SRGBColorSpace ); break; case 'emissiveColor': - materialData.emissiveColor = new Color( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] ); - materialData.emissiveColor.convertSRGBToLinear(); + materialData.emissiveColor = new Color().setRGB( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ], SRGBColorSpace ); break; case 'shininess': @@ -1254,8 +1252,7 @@ class VRMLLoader extends Loader { break; case 'specularColor': - materialData.specularColor = new Color( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ] ); - materialData.specularColor.convertSRGBToLinear(); + materialData.specularColor = new Color().setRGB( fieldValues[ 0 ], fieldValues[ 1 ], fieldValues[ 2 ], SRGBColorSpace ); break; case 'transparency': @@ -3111,7 +3108,8 @@ class VRMLLoader extends Loader { for ( let i = 0; i < attribute.count; i ++ ) { color.fromBufferAttribute( attribute, i ); - color.convertSRGBToLinear(); + + ColorManagement.toWorkingColorSpace( color, SRGBColorSpace ); attribute.setXYZ( i, color.r, color.g, color.b ); @@ -3216,7 +3214,9 @@ class VRMLLoader extends Loader { const colorA = colors[ thresholdIndexA ]; const colorB = colors[ thresholdIndexB ]; - color.copy( colorA ).lerp( colorB, t ).convertSRGBToLinear(); + color.copy( colorA ).lerp( colorB, t ); + + ColorManagement.toWorkingColorSpace( color, SRGBColorSpace ); colorAttribute.setXYZ( index, color.r, color.g, color.b ); diff --git a/examples/jsm/loaders/VTKLoader.js b/examples/jsm/loaders/VTKLoader.js index 05fac6a29ebc01..d6fe8ba7b23dcf 100644 --- a/examples/jsm/loaders/VTKLoader.js +++ b/examples/jsm/loaders/VTKLoader.js @@ -4,7 +4,8 @@ import { Color, FileLoader, Float32BufferAttribute, - Loader + Loader, + SRGBColorSpace } from 'three'; import * as fflate from '../libs/fflate.module.js'; @@ -211,7 +212,7 @@ class VTKLoader extends Loader { const g = parseFloat( result[ 2 ] ); const b = parseFloat( result[ 3 ] ); - color.set( r, g, b ).convertSRGBToLinear(); + color.setRGB( r, g, b, SRGBColorSpace ); colors.push( color.r, color.g, color.b ); @@ -325,7 +326,7 @@ class VTKLoader extends Loader { const g = colors[ 3 * i + 1 ]; const b = colors[ 3 * i + 2 ]; - color.set( r, g, b ).convertSRGBToLinear(); + color.setRGB( r, g, b, SRGBColorSpace ); newColors.push( color.r, color.g, color.b ); newColors.push( color.r, color.g, color.b ); diff --git a/examples/jsm/loaders/XYZLoader.js b/examples/jsm/loaders/XYZLoader.js index 40d5519da560ca..9d94c5e863e936 100644 --- a/examples/jsm/loaders/XYZLoader.js +++ b/examples/jsm/loaders/XYZLoader.js @@ -3,7 +3,8 @@ import { Color, FileLoader, Float32BufferAttribute, - Loader + Loader, + SRGBColorSpace } from 'three'; class XYZLoader extends Loader { @@ -80,7 +81,7 @@ class XYZLoader extends Loader { const g = parseFloat( lineValues[ 4 ] ) / 255; const b = parseFloat( lineValues[ 5 ] ) / 255; - color.set( r, g, b ).convertSRGBToLinear(); + color.setRGB( r, g, b, SRGBColorSpace ); colors.push( color.r, color.g, color.b ); diff --git a/examples/jsm/misc/Timer.js b/examples/jsm/misc/Timer.js index 36ff8a7b7202d5..1a541ec8ecb044 100644 --- a/examples/jsm/misc/Timer.js +++ b/examples/jsm/misc/Timer.js @@ -115,7 +115,7 @@ class FixedTimer extends Timer { function now() { - return ( typeof performance === 'undefined' ? Date : performance ).now(); + return performance.now(); } diff --git a/examples/jsm/modifiers/CurveModifierGPU.js b/examples/jsm/modifiers/CurveModifierGPU.js new file mode 100644 index 00000000000000..b561bff9e27db9 --- /dev/null +++ b/examples/jsm/modifiers/CurveModifierGPU.js @@ -0,0 +1,233 @@ +// Original src: https://github.com/zz85/threejs-path-flow +const CHANNELS = 4; +const TEXTURE_WIDTH = 1024; +const TEXTURE_HEIGHT = 4; + +import { + DataTexture, + DataUtils, + RGBAFormat, + HalfFloatType, + RepeatWrapping, + Mesh, + InstancedMesh, + LinearFilter +} from 'three'; + +import { modelWorldMatrix, normalLocal, vec2, vec3, vec4, mat3, varyingProperty, texture, reference, Fn, select, positionLocal } from 'three/tsl'; + +/** + * Make a new DataTexture to store the descriptions of the curves. + * + * @param { number } numberOfCurves the number of curves needed to be described by this texture. + */ +export function initSplineTexture( numberOfCurves = 1 ) { + + const dataArray = new Uint16Array( TEXTURE_WIDTH * TEXTURE_HEIGHT * numberOfCurves * CHANNELS ); + const dataTexture = new DataTexture( + dataArray, + TEXTURE_WIDTH, + TEXTURE_HEIGHT * numberOfCurves, + RGBAFormat, + HalfFloatType + ); + + dataTexture.wrapS = RepeatWrapping; + dataTexture.wrapY = RepeatWrapping; + dataTexture.magFilter = LinearFilter; + dataTexture.minFilter = LinearFilter; + dataTexture.needsUpdate = true; + + return dataTexture; + +} + +/** + * Write the curve description to the data texture + * + * @param { DataTexture } texture The DataTexture to write to + * @param { Curve } splineCurve The curve to describe + * @param { number } offset Which curve slot to write to + */ +export function updateSplineTexture( texture, splineCurve, offset = 0 ) { + + const numberOfPoints = Math.floor( TEXTURE_WIDTH * ( TEXTURE_HEIGHT / 4 ) ); + splineCurve.arcLengthDivisions = numberOfPoints / 2; + splineCurve.updateArcLengths(); + const points = splineCurve.getSpacedPoints( numberOfPoints ); + const frenetFrames = splineCurve.computeFrenetFrames( numberOfPoints, true ); + + for ( let i = 0; i < numberOfPoints; i ++ ) { + + const rowOffset = Math.floor( i / TEXTURE_WIDTH ); + const rowIndex = i % TEXTURE_WIDTH; + + let pt = points[ i ]; + setTextureValue( texture, rowIndex, pt.x, pt.y, pt.z, 0 + rowOffset + ( TEXTURE_HEIGHT * offset ) ); + pt = frenetFrames.tangents[ i ]; + setTextureValue( texture, rowIndex, pt.x, pt.y, pt.z, 1 + rowOffset + ( TEXTURE_HEIGHT * offset ) ); + pt = frenetFrames.normals[ i ]; + setTextureValue( texture, rowIndex, pt.x, pt.y, pt.z, 2 + rowOffset + ( TEXTURE_HEIGHT * offset ) ); + pt = frenetFrames.binormals[ i ]; + setTextureValue( texture, rowIndex, pt.x, pt.y, pt.z, 3 + rowOffset + ( TEXTURE_HEIGHT * offset ) ); + + } + + texture.needsUpdate = true; + +} + + +function setTextureValue( texture, index, x, y, z, o ) { + + const image = texture.image; + const { data } = image; + const i = CHANNELS * TEXTURE_WIDTH * o; // Row Offset + + data[ index * CHANNELS + i + 0 ] = DataUtils.toHalfFloat( x ); + data[ index * CHANNELS + i + 1 ] = DataUtils.toHalfFloat( y ); + data[ index * CHANNELS + i + 2 ] = DataUtils.toHalfFloat( z ); + data[ index * CHANNELS + i + 3 ] = DataUtils.toHalfFloat( 1 ); + +} + +/** + * Create a new set of uniforms for describing the curve modifier + * + * @param { DataTexture } Texture which holds the curve description + */ +export function getUniforms( splineTexture ) { + + return { + spineTexture: splineTexture, + pathOffset: 0, // time of path curve + pathSegment: 1, // fractional length of path + spineOffset: 161, + spineLength: 400, + flow: 1, // int + }; + +} + +export function modifyShader( material, uniforms, numberOfCurves ) { + + const spineTexture = uniforms.spineTexture; + + const pathOffset = reference( 'pathOffset', 'float', uniforms ); + const pathSegment = reference( 'pathSegment', 'float', uniforms ); + const spineOffset = reference( 'spineOffset', 'float', uniforms ); + const spineLength = reference( 'spineLength', 'float', uniforms ); + const flow = reference( 'flow', 'float', uniforms ); + + material.positionNode = Fn( () => { + + const textureStacks = TEXTURE_HEIGHT / 4; + const textureScale = TEXTURE_HEIGHT * numberOfCurves; + + const worldPos = modelWorldMatrix.mul( vec4( positionLocal, 1 ) ).toVar(); + + const bend = flow.greaterThan( 0 ).toVar(); + const xWeight = select( bend, 0, 1 ).toVar(); + + const spinePortion = select( bend, worldPos.x.add( spineOffset ).div( spineLength ), 0 ); + const mt = spinePortion.mul( pathSegment ).add( pathOffset ).mul( textureStacks ).toVar(); + + mt.assign( mt.mod( textureStacks ) ); + + const rowOffset = mt.floor().toVar(); + + const spinePos = texture( spineTexture, vec2( mt, rowOffset.add( 0.5 ).div( textureScale ) ) ).xyz; + + const a = texture( spineTexture, vec2( mt, rowOffset.add( 1.5 ).div( textureScale ) ) ).xyz; + const b = texture( spineTexture, vec2( mt, rowOffset.add( 2.5 ).div( textureScale ) ) ).xyz; + const c = texture( spineTexture, vec2( mt, rowOffset.add( 3.5 ).div( textureScale ) ) ).xyz; + + const basis = mat3( a, b, c ).toVar(); + + varyingProperty( 'vec3', 'curveNormal' ).assign( basis.mul( normalLocal ) ); + + return basis.mul( vec3( worldPos.x.mul( xWeight ), worldPos.y, worldPos.z ) ).add( spinePos ); + + } )(); + + material.normalNode = varyingProperty( 'vec3', 'curveNormal' ); + +} + +/** + * A helper class for making meshes bend aroudn curves + */ +export class Flow { + + /** + * @param {Mesh} mesh The mesh to clone and modify to bend around the curve + * @param {number} numberOfCurves The amount of space that should preallocated for additional curves + */ + constructor( mesh, numberOfCurves = 1 ) { + + const obj3D = mesh.clone(); + const splineTexure = initSplineTexture( numberOfCurves ); + const uniforms = getUniforms( splineTexure ); + + obj3D.traverse( function ( child ) { + + if ( + child instanceof Mesh || + child instanceof InstancedMesh + ) { + + if ( Array.isArray( child.material ) ) { + + const materials = []; + + for ( const material of child.material ) { + + const newMaterial = material.clone(); + modifyShader( newMaterial, uniforms, numberOfCurves ); + materials.push( newMaterial ); + + } + + child.material = materials; + + } else { + + child.material = child.material.clone(); + modifyShader( child.material, uniforms, numberOfCurves ); + + } + + } + + } ); + + this.curveArray = new Array( numberOfCurves ); + this.curveLengthArray = new Array( numberOfCurves ); + + this.object3D = obj3D; + this.splineTexure = splineTexure; + this.uniforms = uniforms; + + } + + updateCurve( index, curve ) { + + if ( index >= this.curveArray.length ) throw Error( 'Index out of range for Flow' ); + + const curveLength = curve.getLength(); + + this.uniforms.spineLength = curveLength; + this.curveLengthArray[ index ] = curveLength; + this.curveArray[ index ] = curve; + + updateSplineTexture( this.splineTexure, curve, index ); + + } + + moveAlongCurve( amount ) { + + this.uniforms.pathOffset += amount; + + } + +} diff --git a/examples/jsm/objects/LensflareMesh.js b/examples/jsm/objects/LensflareMesh.js new file mode 100644 index 00000000000000..0fc9bd7ab9b47c --- /dev/null +++ b/examples/jsm/objects/LensflareMesh.js @@ -0,0 +1,322 @@ +import { + AdditiveBlending, + Box2, + BufferGeometry, + Color, + FramebufferTexture, + InterleavedBuffer, + InterleavedBufferAttribute, + Mesh, + MeshBasicNodeMaterial, + NodeMaterial, + UnsignedByteType, + Vector2, + Vector3, + Vector4 } from 'three'; + +import { texture, textureLoad, uv, ivec2, vec2, vec4, positionGeometry, reference, varyingProperty, materialReference, Fn, Node } from 'three/tsl'; + +class LensflareMesh extends Mesh { + + constructor() { + + super( LensflareMesh.Geometry, new MeshBasicNodeMaterial( { opacity: 0, transparent: true } ) ); + + this.isLensflare = true; + + this.type = 'LensflareMesh'; + this.frustumCulled = false; + this.renderOrder = Infinity; + + // + + const positionView = new Vector3(); + + // textures + + const tempMap = new FramebufferTexture( 16, 16 ); + const occlusionMap = new FramebufferTexture( 16, 16 ); + + let currentType = UnsignedByteType; + + const geometry = LensflareMesh.Geometry; + + // values for shared material uniforms + + const sharedValues = { + scale: new Vector2(), + positionScreen: new Vector3() + }; + + // materials + + const scale = reference( 'scale', 'vec2', sharedValues ); + const screenPosition = reference( 'positionScreen', 'vec3', sharedValues ); + + const vertexNode = vec4( positionGeometry.xy.mul( scale ).add( screenPosition.xy ), screenPosition.z, 1.0 ); + + const material1a = new NodeMaterial(); + + material1a.depthTest = true; + material1a.depthWrite = false; + material1a.transparent = false; + material1a.fog = false; + material1a.type = 'Lensflare-1a'; + + material1a.vertexNode = vertexNode; + material1a.fragmentNode = vec4( 1.0, 0.0, 1.0, 1.0 ); + + const material1b = new NodeMaterial(); + + material1b.depthTest = false; + material1b.depthWrite = false; + material1b.transparent = false; + material1b.fog = false; + material1b.type = 'Lensflare-1b'; + + material1b.vertexNode = vertexNode; + material1b.fragmentNode = texture( tempMap, vec2( uv().flipY() ) ); + + // the following object is used for occlusionMap generation + + const mesh1 = new Mesh( geometry, material1a ); + + // + + const elements = []; + const elementMeshes = []; + + const material2 = new NodeMaterial(); + + material2.transparent = true; + material2.blending = AdditiveBlending; + material2.depthWrite = false; + material2.depthTest = false; + material2.fog = false; + material2.type = 'Lensflare-2'; + + material2.screenPosition = new Vector3(); + material2.scale = new Vector2(); + material2.occlusionMap = occlusionMap; + + material2.vertexNode = Fn( ( { material } ) => { + + const scale = materialReference( 'scale', 'vec2' ); + const screenPosition = materialReference( 'screenPosition', 'vec3' ); + + const occlusionMap = material.occlusionMap; + + const pos = positionGeometry.xy.toVar(); + + const visibility = textureLoad( occlusionMap, ivec2( 2, 2 ) ).toVar(); + visibility.addAssign( textureLoad( occlusionMap, ivec2( 8, 2 ) ) ); + visibility.addAssign( textureLoad( occlusionMap, ivec2( 14, 2 ) ) ); + visibility.addAssign( textureLoad( occlusionMap, ivec2( 14, 8 ) ) ); + visibility.addAssign( textureLoad( occlusionMap, ivec2( 14, 14 ) ) ); + visibility.addAssign( textureLoad( occlusionMap, ivec2( 8, 14 ) ) ); + visibility.addAssign( textureLoad( occlusionMap, ivec2( 2, 14 ) ) ); + visibility.addAssign( textureLoad( occlusionMap, ivec2( 2, 8 ) ) ); + visibility.addAssign( textureLoad( occlusionMap, ivec2( 8, 8 ) ) ); + + const vVisibility = varyingProperty( 'float', 'vVisibility' ); + + vVisibility.assign( visibility.r.div( 9.0 ) ); + vVisibility.mulAssign( visibility.g.div( 9.0 ).oneMinus() ); + vVisibility.mulAssign( visibility.b.div( 9.0 ) ); + + return vec4( ( pos.mul( scale ).add( screenPosition.xy ).xy ), screenPosition.z, 1.0 ); + + } )(); + + material2.fragmentNode = Fn( () => { + + const color = reference( 'color', 'color' ); + const map = reference( 'map', 'texture' ); + + const vVisibility = varyingProperty( 'float', 'vVisibility' ); + + const output = map.toVar(); + + output.a.mulAssign( vVisibility ); + output.rgb.mulAssign( color ); + + return output; + + } )(); + + + this.addElement = function ( element ) { + + elements.push( element ); + + }; + + // + + const positionScreen = sharedValues.positionScreen; + const screenPositionPixels = new Vector4( 0, 0, 16, 16 ); + const validArea = new Box2(); + const viewport = new Vector4(); + + // dummy node for renderer.renderObject() + const lightsNode = new Node(); + + this.onBeforeRender = ( renderer, scene, camera ) => { + + renderer.getViewport( viewport ); + + viewport.multiplyScalar( window.devicePixelRatio ); + + const renderTarget = renderer.getRenderTarget(); + const type = ( renderTarget !== null ) ? renderTarget.texture.type : UnsignedByteType; + + if ( currentType !== type ) { + + tempMap.dispose(); + occlusionMap.dispose(); + + tempMap.type = occlusionMap.type = type; + + currentType = type; + + } + + const invAspect = viewport.w / viewport.z; + const halfViewportWidth = viewport.z / 2.0; + const halfViewportHeight = viewport.w / 2.0; + + const size = 16 / viewport.w; + + sharedValues.scale.set( size * invAspect, size ); + + validArea.min.set( viewport.x, viewport.y ); + validArea.max.set( viewport.x + ( viewport.z - 16 ), viewport.y + ( viewport.w - 16 ) ); + + // calculate position in screen space + + positionView.setFromMatrixPosition( this.matrixWorld ); + positionView.applyMatrix4( camera.matrixWorldInverse ); + + if ( positionView.z > 0 ) return; // lensflare is behind the camera + + positionScreen.copy( positionView ).applyMatrix4( camera.projectionMatrix ); + + // horizontal and vertical coordinate of the lower left corner of the pixels to copy + + screenPositionPixels.x = viewport.x + ( positionScreen.x * halfViewportWidth ) + halfViewportWidth - 8; + screenPositionPixels.y = viewport.y - ( positionScreen.y * halfViewportHeight ) + halfViewportHeight - 8; + + // screen cull + + if ( validArea.containsPoint( screenPositionPixels ) ) { + + // save current RGB to temp texture + + renderer.copyFramebufferToTexture( tempMap, screenPositionPixels ); + + // render pink quad + + renderer.renderObject( mesh1, scene, camera, geometry, material1a, null, lightsNode ); + + // copy result to occlusionMap + + renderer.copyFramebufferToTexture( occlusionMap, screenPositionPixels ); + + // restore graphics + + renderer.renderObject( mesh1, scene, camera, geometry, material1b, null, lightsNode ); + + // render elements + + const vecX = - positionScreen.x * 2; + const vecY = - positionScreen.y * 2; + + for ( let i = 0, l = elements.length; i < l; i ++ ) { + + const element = elements[ i ]; + + let mesh2 = elementMeshes[ i ]; + + if ( mesh2 === undefined ) { + + mesh2 = elementMeshes[ i ] = new Mesh( geometry, material2 ); + + mesh2.color = element.color.convertSRGBToLinear(); + mesh2.map = element.texture; + + } + + material2.screenPosition.x = positionScreen.x + vecX * element.distance; + material2.screenPosition.y = positionScreen.y - vecY * element.distance; + material2.screenPosition.z = positionScreen.z; + + const size = element.size / viewport.w; + + material2.scale.set( size * invAspect, size ); + + renderer.renderObject( mesh2, scene, camera, geometry, material2, null, lightsNode ); + + } + + } + + }; + + this.dispose = function () { + + material1a.dispose(); + material1b.dispose(); + material2.dispose(); + + tempMap.dispose(); + occlusionMap.dispose(); + + for ( let i = 0, l = elements.length; i < l; i ++ ) { + + elements[ i ].texture.dispose(); + + } + + }; + + } + +} + +// + +class LensflareElement { + + constructor( texture, size = 1, distance = 0, color = new Color( 0xffffff ) ) { + + this.texture = texture; + this.size = size; + this.distance = distance; + this.color = color; + + } + +} + +LensflareMesh.Geometry = ( function () { + + const geometry = new BufferGeometry(); + + const float32Array = new Float32Array( [ + - 1, - 1, 0, 0, 0, + 1, - 1, 0, 1, 0, + 1, 1, 0, 1, 1, + - 1, 1, 0, 0, 1 + ] ); + + const interleavedBuffer = new InterleavedBuffer( float32Array, 5 ); + + geometry.setIndex( [ 0, 1, 2, 0, 2, 3 ] ); + geometry.setAttribute( 'position', new InterleavedBufferAttribute( interleavedBuffer, 3, 0, false ) ); + geometry.setAttribute( 'uv', new InterleavedBufferAttribute( interleavedBuffer, 2, 3, false ) ); + + return geometry; + +} )(); + +export { LensflareMesh, LensflareElement }; diff --git a/examples/jsm/objects/SkyMesh.js b/examples/jsm/objects/SkyMesh.js index 6d0287d3839a0a..ad54769f8d67f4 100644 --- a/examples/jsm/objects/SkyMesh.js +++ b/examples/jsm/objects/SkyMesh.js @@ -2,10 +2,9 @@ import { BackSide, BoxGeometry, Mesh, - NodeMaterial, Vector3 } from 'three'; -import { float, Fn, vec3, acos, add, mul, clamp, cos, dot, exp, max, mix, modelViewProjection, normalize, positionWorld, pow, smoothstep, sub, varying, varyingProperty, vec4, uniform, cameraPosition } from 'three/tsl'; +import { Fn, NodeMaterial, float, vec3, acos, add, mul, clamp, cos, dot, exp, max, mix, modelViewProjection, normalize, positionWorld, pow, smoothstep, sub, varying, varyingProperty, vec4, uniform, cameraPosition } from 'three/tsl'; /** * Based on "A Practical Analytic Model for Daylight" diff --git a/examples/jsm/objects/Water2Mesh.js b/examples/jsm/objects/Water2Mesh.js index 29092ff2a16190..752008b3b8ebd6 100644 --- a/examples/jsm/objects/Water2Mesh.js +++ b/examples/jsm/objects/Water2Mesh.js @@ -1,11 +1,10 @@ import { Color, Mesh, - NodeMaterial, Vector2, Vector3 } from 'three'; -import { vec2, viewportSafeUV, viewportSharedTexture, reflector, pow, float, abs, texture, uniform, TempNode, NodeUpdateType, vec4, Fn, cameraPosition, positionWorld, uv, mix, vec3, normalize, max, dot, viewportUV } from 'three/tsl'; +import { Fn, NodeMaterial, NodeUpdateType, TempNode, vec2, viewportSafeUV, viewportSharedTexture, reflector, pow, float, abs, texture, uniform, vec4, cameraPosition, positionWorld, uv, mix, vec3, normalize, max, dot, screenUV } from 'three/tsl'; /** * References: @@ -141,7 +140,7 @@ class WaterNode extends TempNode { this.waterBody.add( reflectionSampler.target ); reflectionSampler.uvNode = reflectionSampler.uvNode.add( offset ); - const refractorUV = viewportUV.add( offset ); + const refractorUV = screenUV.add( offset ); const refractionSampler = viewportSharedTexture( viewportSafeUV( refractorUV ) ); // calculate final uv coords diff --git a/examples/jsm/objects/WaterMesh.js b/examples/jsm/objects/WaterMesh.js index 47f59dd18768b5..3e8dd31dfff85c 100644 --- a/examples/jsm/objects/WaterMesh.js +++ b/examples/jsm/objects/WaterMesh.js @@ -1,10 +1,9 @@ import { Color, Mesh, - NodeMaterial, Vector3 } from 'three'; -import { add, cameraPosition, div, normalize, positionWorld, sub, timerLocal, Fn, texture, vec2, vec3, vec4, max, dot, reflect, pow, length, float, uniform, reflector, mul, mix } from 'three/tsl'; +import { Fn, NodeMaterial, add, cameraPosition, div, normalize, positionWorld, sub, timerLocal, texture, vec2, vec3, vec4, max, dot, reflect, pow, length, float, uniform, reflector, mul, mix } from 'three/tsl'; /** * Work based on : diff --git a/examples/jsm/physics/JoltPhysics.js b/examples/jsm/physics/JoltPhysics.js index 4e2010e7a8a82a..133f7b56fb03d3 100644 --- a/examples/jsm/physics/JoltPhysics.js +++ b/examples/jsm/physics/JoltPhysics.js @@ -61,7 +61,7 @@ async function JoltPhysics() { if ( Jolt === null ) { - const { default: initJolt } = await import( JOLT_PATH ); + const { default: initJolt } = await import( `${JOLT_PATH}` ); Jolt = await initJolt(); } diff --git a/examples/jsm/physics/RapierPhysics.js b/examples/jsm/physics/RapierPhysics.js index 20ed2af8a817c4..e31ca9fcc1b784 100644 --- a/examples/jsm/physics/RapierPhysics.js +++ b/examples/jsm/physics/RapierPhysics.js @@ -58,7 +58,7 @@ async function RapierPhysics() { if ( RAPIER === null ) { - RAPIER = await import( RAPIER_PATH ); + RAPIER = await import( `${RAPIER_PATH}` ); await RAPIER.init(); } diff --git a/examples/jsm/transpiler/GLSLDecoder.js b/examples/jsm/transpiler/GLSLDecoder.js index 57bacb997022f9..5359e41f10607b 100644 --- a/examples/jsm/transpiler/GLSLDecoder.js +++ b/examples/jsm/transpiler/GLSLDecoder.js @@ -226,7 +226,7 @@ class GLSLDecoder { this._currentFunction = null; - this.addPolyfill( 'gl_FragCoord', 'vec3 gl_FragCoord = vec3( viewportCoordinate.x, viewportCoordinate.y.oneMinus(), viewportCoordinate.z );' ); + this.addPolyfill( 'gl_FragCoord', 'vec3 gl_FragCoord = vec3( screenCoordinate.x, screenCoordinate.y.oneMinus(), screenCoordinate.z );' ); } diff --git a/examples/jsm/transpiler/ShaderToyDecoder.js b/examples/jsm/transpiler/ShaderToyDecoder.js index 76e4ede44a011a..c640559a10525a 100644 --- a/examples/jsm/transpiler/ShaderToyDecoder.js +++ b/examples/jsm/transpiler/ShaderToyDecoder.js @@ -8,8 +8,8 @@ class ShaderToyDecoder extends GLSLDecoder { super(); this.addPolyfill( 'iTime', 'float iTime = timerGlobal();' ); - this.addPolyfill( 'iResolution', 'vec2 iResolution = viewportResolution;' ); - this.addPolyfill( 'fragCoord', 'vec3 fragCoord = vec3( viewportCoordinate.x, viewportResolution.y - viewportCoordinate.y, viewportCoordinate.z );' ); + this.addPolyfill( 'iResolution', 'vec2 iResolution = screenSize;' ); + this.addPolyfill( 'fragCoord', 'vec3 fragCoord = vec3( screenCoordinate.x, screenSize.y - screenCoordinate.y, screenCoordinate.z );' ); } diff --git a/examples/jsm/utils/GPUStatsPanel.js b/examples/jsm/utils/GPUStatsPanel.js deleted file mode 100644 index 8f74800ad58f8f..00000000000000 --- a/examples/jsm/utils/GPUStatsPanel.js +++ /dev/null @@ -1,95 +0,0 @@ -import Stats from '../libs/stats.module.js'; - -// https://www.khronos.org/registry/webgl/extensions/EXT_disjoint_timer_query_webgl2/ -export class GPUStatsPanel extends Stats.Panel { - - constructor( context, name = 'GPU MS' ) { - - super( name, '#f90', '#210' ); - - const extension = context.getExtension( 'EXT_disjoint_timer_query_webgl2' ); - - if ( extension === null ) { - - console.warn( 'GPUStatsPanel: disjoint_time_query extension not available.' ); - - } - - this.context = context; - this.extension = extension; - this.maxTime = 30; - this.activeQueries = 0; - - this.startQuery = function () { - - const gl = this.context; - const ext = this.extension; - - if ( ext === null ) { - - return; - - } - - // create the query object - const query = gl.createQuery(); - gl.beginQuery( ext.TIME_ELAPSED_EXT, query ); - - this.activeQueries ++; - - const checkQuery = () => { - - // check if the query is available and valid - - const available = gl.getQueryParameter( query, gl.QUERY_RESULT_AVAILABLE ); - const disjoint = gl.getParameter( ext.GPU_DISJOINT_EXT ); - const ns = gl.getQueryParameter( query, gl.QUERY_RESULT ); - - const ms = ns * 1e-6; - - if ( available ) { - - // update the display if it is valid - if ( ! disjoint ) { - - this.update( ms, this.maxTime ); - - } - - gl.deleteQuery( query ); - - this.activeQueries --; - - - } else if ( gl.isContextLost() === false ) { - - // otherwise try again the next frame - requestAnimationFrame( checkQuery ); - - } - - }; - - requestAnimationFrame( checkQuery ); - - }; - - this.endQuery = function () { - - // finish the query measurement - const ext = this.extension; - const gl = this.context; - - if ( ext === null ) { - - return; - - } - - gl.endQuery( ext.TIME_ELAPSED_EXT ); - - }; - - } - -} diff --git a/examples/jsm/utils/GeometryCompressionUtils.js b/examples/jsm/utils/GeometryCompressionUtils.js index 0be91d568c15bf..31bbaf9718faae 100644 --- a/examples/jsm/utils/GeometryCompressionUtils.js +++ b/examples/jsm/utils/GeometryCompressionUtils.js @@ -11,27 +11,19 @@ import { Matrix4, Vector3 } from 'three'; -import { PackedPhongMaterial } from './PackedPhongMaterial.js'; /** - * Make the input mesh.geometry's normal attribute encoded and compressed by 3 different methods. - * Also will change the mesh.material to `PackedPhongMaterial` which let the vertex shader program decode the normal data. + * Make the input geometry's normal attribute encoded and compressed by 3 different methods. * - * @param {THREE.Mesh} mesh + * @param {THREE.BufferGeometry} geometry * @param {String} encodeMethod "DEFAULT" || "OCT1Byte" || "OCT2Byte" || "ANGLES" * */ -function compressNormals( mesh, encodeMethod ) { +function compressNormals( geometry, encodeMethod ) { - if ( ! mesh.geometry ) { - - console.error( 'Mesh must contain geometry. ' ); - - } - - const normal = mesh.geometry.attributes.normal; + const normal = geometry.attributes.normal; if ( ! normal ) { @@ -66,8 +58,8 @@ function compressNormals( mesh, encodeMethod ) { } - mesh.geometry.setAttribute( 'normal', new BufferAttribute( result, 3, true ) ); - mesh.geometry.attributes.normal.bytes = result.length * 1; + geometry.setAttribute( 'normal', new BufferAttribute( result, 3, true ) ); + geometry.attributes.normal.bytes = result.length * 1; } else if ( encodeMethod == 'OCT1Byte' ) { @@ -88,8 +80,8 @@ function compressNormals( mesh, encodeMethod ) { } - mesh.geometry.setAttribute( 'normal', new BufferAttribute( result, 2, true ) ); - mesh.geometry.attributes.normal.bytes = result.length * 1; + geometry.setAttribute( 'normal', new BufferAttribute( result, 2, true ) ); + geometry.attributes.normal.bytes = result.length * 1; } else if ( encodeMethod == 'OCT2Byte' ) { @@ -104,8 +96,8 @@ function compressNormals( mesh, encodeMethod ) { } - mesh.geometry.setAttribute( 'normal', new BufferAttribute( result, 2, true ) ); - mesh.geometry.attributes.normal.bytes = result.length * 2; + geometry.setAttribute( 'normal', new BufferAttribute( result, 2, true ) ); + geometry.attributes.normal.bytes = result.length * 2; } else if ( encodeMethod == 'ANGLES' ) { @@ -120,8 +112,8 @@ function compressNormals( mesh, encodeMethod ) { } - mesh.geometry.setAttribute( 'normal', new BufferAttribute( result, 2, true ) ); - mesh.geometry.attributes.normal.bytes = result.length * 2; + geometry.setAttribute( 'normal', new BufferAttribute( result, 2, true ) ); + geometry.attributes.normal.bytes = result.length * 2; } else { @@ -129,60 +121,22 @@ function compressNormals( mesh, encodeMethod ) { } - mesh.geometry.attributes.normal.needsUpdate = true; - mesh.geometry.attributes.normal.isPacked = true; - mesh.geometry.attributes.normal.packingMethod = encodeMethod; - - // modify material - if ( ! ( mesh.material instanceof PackedPhongMaterial ) ) { - - mesh.material = new PackedPhongMaterial().copy( mesh.material ); - - } - - if ( encodeMethod == 'ANGLES' ) { - - mesh.material.defines.USE_PACKED_NORMAL = 0; - - } - - if ( encodeMethod == 'OCT1Byte' ) { - - mesh.material.defines.USE_PACKED_NORMAL = 1; - - } - - if ( encodeMethod == 'OCT2Byte' ) { - - mesh.material.defines.USE_PACKED_NORMAL = 1; - - } - - if ( encodeMethod == 'DEFAULT' ) { - - mesh.material.defines.USE_PACKED_NORMAL = 2; - - } + geometry.attributes.normal.needsUpdate = true; + geometry.attributes.normal.isPacked = true; + geometry.attributes.normal.packingMethod = encodeMethod; } /** - * Make the input mesh.geometry's position attribute encoded and compressed. - * Also will change the mesh.material to `PackedPhongMaterial` which let the vertex shader program decode the position data. + * Make the input geometry's position attribute encoded and compressed. * - * @param {THREE.Mesh} mesh + * @param {THREE.BufferGeometry} geometry * */ -function compressPositions( mesh ) { +function compressPositions( geometry ) { - if ( ! mesh.geometry ) { - - console.error( 'Mesh must contain geometry. ' ); - - } - - const position = mesh.geometry.attributes.position; + const position = geometry.attributes.position; if ( ! position ) { @@ -204,47 +158,27 @@ function compressPositions( mesh ) { const result = quantizedEncode( array, encodingBytes ); const quantized = result.quantized; - const decodeMat = result.decodeMat; // IMPORTANT: calculate original geometry bounding info first, before updating packed positions - if ( mesh.geometry.boundingBox == null ) mesh.geometry.computeBoundingBox(); - if ( mesh.geometry.boundingSphere == null ) mesh.geometry.computeBoundingSphere(); + if ( geometry.boundingBox == null ) geometry.computeBoundingBox(); + if ( geometry.boundingSphere == null ) geometry.computeBoundingSphere(); - mesh.geometry.setAttribute( 'position', new BufferAttribute( quantized, 3 ) ); - mesh.geometry.attributes.position.isPacked = true; - mesh.geometry.attributes.position.needsUpdate = true; - mesh.geometry.attributes.position.bytes = quantized.length * encodingBytes; - - // modify material - if ( ! ( mesh.material instanceof PackedPhongMaterial ) ) { - - mesh.material = new PackedPhongMaterial().copy( mesh.material ); - - } - - mesh.material.defines.USE_PACKED_POSITION = 0; - - mesh.material.uniforms.quantizeMatPos.value = decodeMat; - mesh.material.uniforms.quantizeMatPos.needsUpdate = true; + geometry.setAttribute( 'position', new BufferAttribute( quantized, 3 ) ); + geometry.attributes.position.isPacked = true; + geometry.attributes.position.needsUpdate = true; + geometry.attributes.position.bytes = quantized.length * encodingBytes; } /** - * Make the input mesh.geometry's uv attribute encoded and compressed. - * Also will change the mesh.material to `PackedPhongMaterial` which let the vertex shader program decode the uv data. + * Make the input geometry's uv attribute encoded and compressed. * - * @param {THREE.Mesh} mesh + * @param {THREE.BufferGeometry} geometry * */ -function compressUvs( mesh ) { +function compressUvs( geometry ) { - if ( ! mesh.geometry ) { - - console.error( 'Mesh must contain geometry property. ' ); - - } - - const uvs = mesh.geometry.attributes.uv; + const uvs = geometry.attributes.uv; if ( ! uvs ) { @@ -281,39 +215,20 @@ function compressUvs( mesh ) { } - mesh.geometry.setAttribute( 'uv', new BufferAttribute( result, 2, true ) ); - mesh.geometry.attributes.uv.isPacked = true; - mesh.geometry.attributes.uv.needsUpdate = true; - mesh.geometry.attributes.uv.bytes = result.length * 2; - - if ( ! ( mesh.material instanceof PackedPhongMaterial ) ) { - - mesh.material = new PackedPhongMaterial().copy( mesh.material ); - - } - - mesh.material.defines.USE_PACKED_UV = 0; + geometry.setAttribute( 'uv', new BufferAttribute( result, 2, true ) ); + geometry.attributes.uv.isPacked = true; + geometry.attributes.uv.needsUpdate = true; + geometry.attributes.uv.bytes = result.length * 2; } else { // use quantized encoding method result = quantizedEncodeUV( array, 2 ); - mesh.geometry.setAttribute( 'uv', new BufferAttribute( result.quantized, 2 ) ); - mesh.geometry.attributes.uv.isPacked = true; - mesh.geometry.attributes.uv.needsUpdate = true; - mesh.geometry.attributes.uv.bytes = result.quantized.length * 2; - - if ( ! ( mesh.material instanceof PackedPhongMaterial ) ) { - - mesh.material = new PackedPhongMaterial().copy( mesh.material ); - - } - - mesh.material.defines.USE_PACKED_UV = 1; - - mesh.material.uniforms.quantizeMatUV.value = result.decodeMat; - mesh.material.uniforms.quantizeMatUV.needsUpdate = true; + geometry.setAttribute( 'uv', new BufferAttribute( result.quantized, 2 ) ); + geometry.attributes.uv.isPacked = true; + geometry.attributes.uv.needsUpdate = true; + geometry.attributes.uv.bytes = result.quantized.length * 2; } diff --git a/examples/jsm/utils/PackedPhongMaterial.js b/examples/jsm/utils/PackedPhongMaterial.js deleted file mode 100644 index f71aab8e2d8c6b..00000000000000 --- a/examples/jsm/utils/PackedPhongMaterial.js +++ /dev/null @@ -1,178 +0,0 @@ - -/** - * `PackedPhongMaterial` inherited from THREE.MeshPhongMaterial - * - * @param {Object} parameters - */ -import { - MeshPhongMaterial, - ShaderChunk, - ShaderLib, - UniformsUtils, -} from 'three'; - -class PackedPhongMaterial extends MeshPhongMaterial { - - constructor( parameters ) { - - super(); - - this.defines = {}; - this.type = 'PackedPhongMaterial'; - this.uniforms = UniformsUtils.merge( [ - - ShaderLib.phong.uniforms, - - { - quantizeMatPos: { value: null }, - quantizeMatUV: { value: null } - } - - ] ); - - this.vertexShader = [ - '#define PHONG', - - 'varying vec3 vViewPosition;', - - ShaderChunk.common, - ShaderChunk.uv_pars_vertex, - ShaderChunk.displacementmap_pars_vertex, - ShaderChunk.envmap_pars_vertex, - ShaderChunk.color_pars_vertex, - ShaderChunk.fog_pars_vertex, - ShaderChunk.normal_pars_vertex, - ShaderChunk.morphtarget_pars_vertex, - ShaderChunk.skinning_pars_vertex, - ShaderChunk.shadowmap_pars_vertex, - ShaderChunk.logdepthbuf_pars_vertex, - ShaderChunk.clipping_planes_pars_vertex, - - `#ifdef USE_PACKED_NORMAL - #if USE_PACKED_NORMAL == 0 - vec3 decodeNormal(vec3 packedNormal) - { - float x = packedNormal.x * 2.0 - 1.0; - float y = packedNormal.y * 2.0 - 1.0; - vec2 scth = vec2(sin(x * PI), cos(x * PI)); - vec2 scphi = vec2(sqrt(1.0 - y * y), y); - return normalize( vec3(scth.y * scphi.x, scth.x * scphi.x, scphi.y) ); - } - #endif - - #if USE_PACKED_NORMAL == 1 - vec3 decodeNormal(vec3 packedNormal) - { - vec3 v = vec3(packedNormal.xy, 1.0 - abs(packedNormal.x) - abs(packedNormal.y)); - if (v.z < 0.0) - { - v.xy = (1.0 - abs(v.yx)) * vec2((v.x >= 0.0) ? +1.0 : -1.0, (v.y >= 0.0) ? +1.0 : -1.0); - } - return normalize(v); - } - #endif - - #if USE_PACKED_NORMAL == 2 - vec3 decodeNormal(vec3 packedNormal) - { - vec3 v = (packedNormal * 2.0) - 1.0; - return normalize(v); - } - #endif - #endif`, - - `#ifdef USE_PACKED_POSITION - #if USE_PACKED_POSITION == 0 - uniform mat4 quantizeMatPos; - #endif - #endif`, - - `#ifdef USE_PACKED_UV - #if USE_PACKED_UV == 1 - uniform mat3 quantizeMatUV; - #endif - #endif`, - - `#ifdef USE_PACKED_UV - #if USE_PACKED_UV == 0 - vec2 decodeUV(vec2 packedUV) - { - vec2 uv = (packedUV * 2.0) - 1.0; - return uv; - } - #endif - - #if USE_PACKED_UV == 1 - vec2 decodeUV(vec2 packedUV) - { - vec2 uv = ( vec3(packedUV, 1.0) * quantizeMatUV ).xy; - return uv; - } - #endif - #endif`, - - 'void main() {', - - ShaderChunk.uv_vertex, - - `#ifdef USE_MAP - #ifdef USE_PACKED_UV - vMapUv = decodeUV(vMapUv); - #endif - #endif`, - - ShaderChunk.color_vertex, - ShaderChunk.morphcolor_vertex, - - ShaderChunk.beginnormal_vertex, - - `#ifdef USE_PACKED_NORMAL - objectNormal = decodeNormal(objectNormal); - #endif - - #ifdef USE_TANGENT - vec3 objectTangent = vec3( tangent.xyz ); - #endif - `, - - ShaderChunk.morphnormal_vertex, - ShaderChunk.skinbase_vertex, - ShaderChunk.skinnormal_vertex, - ShaderChunk.defaultnormal_vertex, - ShaderChunk.normal_vertex, - - ShaderChunk.begin_vertex, - - `#ifdef USE_PACKED_POSITION - #if USE_PACKED_POSITION == 0 - transformed = ( vec4(transformed, 1.0) * quantizeMatPos ).xyz; - #endif - #endif`, - - ShaderChunk.morphtarget_vertex, - ShaderChunk.skinning_vertex, - ShaderChunk.displacementmap_vertex, - ShaderChunk.project_vertex, - ShaderChunk.logdepthbuf_vertex, - ShaderChunk.clipping_planes_vertex, - - 'vViewPosition = - mvPosition.xyz;', - - ShaderChunk.worldpos_vertex, - ShaderChunk.envmap_vertex, - ShaderChunk.shadowmap_vertex, - ShaderChunk.fog_vertex, - - '}', - ].join( '\n' ); - - // Use the original MeshPhongMaterial's fragmentShader. - this.fragmentShader = ShaderLib.phong.fragmentShader; - - this.setValues( parameters ); - - } - -} - -export { PackedPhongMaterial }; diff --git a/examples/jsm/utils/ShadowMapViewer.js b/examples/jsm/utils/ShadowMapViewer.js index 53b928249dc079..ff36f70848c62a 100644 --- a/examples/jsm/utils/ShadowMapViewer.js +++ b/examples/jsm/utils/ShadowMapViewer.js @@ -1,13 +1,12 @@ import { DoubleSide, - LinearFilter, + CanvasTexture, Mesh, MeshBasicMaterial, OrthographicCamera, PlaneGeometry, Scene, ShaderMaterial, - Texture, UniformsUtils } from 'three'; import { UnpackDepthRGBAShader } from '../shaders/UnpackDepthRGBAShader.js'; @@ -93,13 +92,9 @@ class ShadowMapViewer { context.fillStyle = 'rgba( 255, 0, 0, 1 )'; context.fillText( light.name, 0, 20 ); - const labelTexture = new Texture( labelCanvas ); - labelTexture.magFilter = LinearFilter; - labelTexture.minFilter = LinearFilter; - labelTexture.needsUpdate = true; + const labelTexture = new CanvasTexture( labelCanvas ); - const labelMaterial = new MeshBasicMaterial( { map: labelTexture, side: DoubleSide } ); - labelMaterial.transparent = true; + const labelMaterial = new MeshBasicMaterial( { map: labelTexture, side: DoubleSide, transparent: true } ); const labelPlane = new PlaneGeometry( labelCanvas.width, labelCanvas.height ); labelMesh = new Mesh( labelPlane, labelMaterial ); diff --git a/examples/jsm/utils/ShadowMapViewerGPU.js b/examples/jsm/utils/ShadowMapViewerGPU.js new file mode 100644 index 00000000000000..ff8caa3054c833 --- /dev/null +++ b/examples/jsm/utils/ShadowMapViewerGPU.js @@ -0,0 +1,201 @@ +import { + DoubleSide, + CanvasTexture, + Mesh, + MeshBasicMaterial, + NodeMaterial, + OrthographicCamera, + PlaneGeometry, + Scene, + Texture +} from 'three'; +import { texture } from 'three/tsl'; + +/** + * This is a helper for visualising a given light's shadow map. + * It works for shadow casting lights: DirectionalLight and SpotLight. + * It renders out the shadow map and displays it on a HUD. + * + * Example usage: + * 1) Import ShadowMapViewer into your app. + * + * 2) Create a shadow casting light and name it optionally: + * let light = new DirectionalLight( 0xffffff, 1 ); + * light.castShadow = true; + * light.name = 'Sun'; + * + * 3) Create a shadow map viewer for that light and set its size and position optionally: + * let shadowMapViewer = new ShadowMapViewer( light ); + * shadowMapViewer.size.set( 128, 128 ); //width, height default: 256, 256 + * shadowMapViewer.position.set( 10, 10 ); //x, y in pixel default: 0, 0 (top left corner) + * + * 4) Render the shadow map viewer in your render loop: + * shadowMapViewer.render( renderer ); + * + * 5) Optionally: Update the shadow map viewer on window resize: + * shadowMapViewer.updateForWindowResize(); + * + * 6) If you set the position or size members directly, you need to call shadowMapViewer.update(); + */ + +class ShadowMapViewer { + + constructor( light ) { + + //- Internals + const scope = this; + const doRenderLabel = ( light.name !== undefined && light.name !== '' ); + let currentAutoClear; + + //Holds the initial position and dimension of the HUD + const frame = { + x: 10, + y: 10, + width: 256, + height: 256 + }; + + const camera = new OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, 1, 10 ); + camera.position.set( 0, 0, 2 ); + const scene = new Scene(); + + //HUD for shadow map + + const material = new NodeMaterial(); + + const shadowMapUniform = texture( new Texture() ); + material.fragmentNode = shadowMapUniform; + + const plane = new PlaneGeometry( frame.width, frame.height ); + const mesh = new Mesh( plane, material ); + + scene.add( mesh ); + + //Label for light's name + let labelCanvas, labelMesh; + + if ( doRenderLabel ) { + + labelCanvas = document.createElement( 'canvas' ); + + const context = labelCanvas.getContext( '2d' ); + context.font = 'Bold 20px Arial'; + + const labelWidth = context.measureText( light.name ).width; + labelCanvas.width = labelWidth; + labelCanvas.height = 25; //25 to account for g, p, etc. + + context.font = 'Bold 20px Arial'; + context.fillStyle = 'rgba( 255, 0, 0, 1 )'; + context.fillText( light.name, 0, 20 ); + + const labelTexture = new CanvasTexture( labelCanvas ); + + const labelMaterial = new MeshBasicMaterial( { map: labelTexture, side: DoubleSide, transparent: true } ); + + const labelPlane = new PlaneGeometry( labelCanvas.width, labelCanvas.height ); + labelMesh = new Mesh( labelPlane, labelMaterial ); + + scene.add( labelMesh ); + + } + + function resetPosition() { + + scope.position.set( scope.position.x, scope.position.y ); + + } + + //- API + // Set to false to disable displaying this shadow map + this.enabled = true; + + // Set the size of the displayed shadow map on the HUD + this.size = { + width: frame.width, + height: frame.height, + set: function ( width, height ) { + + this.width = width; + this.height = height; + + mesh.scale.set( this.width / frame.width, this.height / frame.height, 1 ); + + //Reset the position as it is off when we scale stuff + resetPosition(); + + } + }; + + // Set the position of the displayed shadow map on the HUD + this.position = { + x: frame.x, + y: frame.y, + set: function ( x, y ) { + + this.x = x; + this.y = y; + + const width = scope.size.width; + const height = scope.size.height; + + mesh.position.set( - window.innerWidth / 2 + width / 2 + this.x, window.innerHeight / 2 - height / 2 - this.y, 0 ); + + if ( doRenderLabel ) labelMesh.position.set( mesh.position.x, mesh.position.y - scope.size.height / 2 + labelCanvas.height / 2, 0 ); + + } + }; + + this.render = function ( renderer ) { + + if ( this.enabled ) { + + //Because a light's .shadowMap is only initialised after the first render pass + //we have to make sure the correct map is sent into the shader, otherwise we + //always end up with the scene's first added shadow casting light's shadowMap + //in the shader + //See: https://github.com/mrdoob/three.js/issues/5932 + shadowMapUniform.value = light.shadow.map.texture; + + currentAutoClear = renderer.autoClear; + renderer.autoClear = false; // To allow render overlay + renderer.clearDepth(); + renderer.render( scene, camera ); + renderer.autoClear = currentAutoClear; + + } + + }; + + this.updateForWindowResize = function () { + + if ( this.enabled ) { + + camera.left = window.innerWidth / - 2; + camera.right = window.innerWidth / 2; + camera.top = window.innerHeight / 2; + camera.bottom = window.innerHeight / - 2; + camera.updateProjectionMatrix(); + + this.update(); + + } + + }; + + this.update = function () { + + this.position.set( this.position.x, this.position.y ); + this.size.set( this.size.width, this.size.height ); + + }; + + //Force an update to set position/size + this.update(); + + } + +} + + +export { ShadowMapViewer }; diff --git a/examples/jsm/utils/SkeletonUtils.js b/examples/jsm/utils/SkeletonUtils.js index 1f25e4cbbc9a00..a4fd9922d4de26 100644 --- a/examples/jsm/utils/SkeletonUtils.js +++ b/examples/jsm/utils/SkeletonUtils.js @@ -9,28 +9,37 @@ import { VectorKeyframeTrack } from 'three'; +function getBoneName( bone, options ) { + + if ( options.getBoneName !== undefined ) { + + return options.getBoneName( bone ); + + } + + return options.names[ bone.name ]; + +} function retarget( target, source, options = {} ) { - const pos = new Vector3(), - quat = new Quaternion(), + const quat = new Quaternion(), scale = new Vector3(), - bindBoneMatrix = new Matrix4(), relativeMatrix = new Matrix4(), globalMatrix = new Matrix4(); - options.preserveMatrix = options.preserveMatrix !== undefined ? options.preserveMatrix : true; - options.preservePosition = options.preservePosition !== undefined ? options.preservePosition : true; - options.preserveHipPosition = options.preserveHipPosition !== undefined ? options.preserveHipPosition : false; + options.preserveBoneMatrix = options.preserveBoneMatrix !== undefined ? options.preserveBoneMatrix : true; + options.preserveBonePositions = options.preserveBonePositions !== undefined ? options.preserveBonePositions : true; options.useTargetMatrix = options.useTargetMatrix !== undefined ? options.useTargetMatrix : false; options.hip = options.hip !== undefined ? options.hip : 'hip'; + options.hipInfluence = options.hipInfluence !== undefined ? options.hipInfluence : new Vector3( 1, 1, 1 ); + options.scale = options.scale !== undefined ? options.scale : 1; options.names = options.names || {}; const sourceBones = source.isObject3D ? source.skeleton.bones : getBones( source ), bones = target.isObject3D ? target.skeleton.bones : getBones( target ); - let bindBones, - bone, name, boneTo, + let bone, name, boneTo, bonesPosition; // reset bones @@ -42,11 +51,11 @@ function retarget( target, source, options = {} ) { } else { options.useTargetMatrix = true; - options.preserveMatrix = false; + options.preserveBoneMatrix = false; } - if ( options.preservePosition ) { + if ( options.preserveBonePositions ) { bonesPosition = []; @@ -58,7 +67,7 @@ function retarget( target, source, options = {} ) { } - if ( options.preserveMatrix ) { + if ( options.preserveBoneMatrix ) { // reset matrix @@ -76,35 +85,10 @@ function retarget( target, source, options = {} ) { } - if ( options.offsets ) { - - bindBones = []; - - for ( let i = 0; i < bones.length; ++ i ) { - - bone = bones[ i ]; - name = options.names[ bone.name ] || bone.name; - - if ( options.offsets[ name ] ) { - - bone.matrix.multiply( options.offsets[ name ] ); - - bone.matrix.decompose( bone.position, bone.quaternion, bone.scale ); - - bone.updateMatrixWorld(); - - } - - bindBones.push( bone.matrixWorld.clone() ); - - } - - } - for ( let i = 0; i < bones.length; ++ i ) { bone = bones[ i ]; - name = options.names[ bone.name ] || bone.name; + name = getBoneName( bone, options ); boneTo = getBoneByName( name, sourceBones ); @@ -136,10 +120,15 @@ function retarget( target, source, options = {} ) { if ( target.isObject3D ) { - const boneIndex = bones.indexOf( bone ), - wBindMatrix = bindBones ? bindBones[ boneIndex ] : bindBoneMatrix.copy( target.skeleton.boneInverses[ boneIndex ] ).invert(); + if ( options.localOffsets ) { + + if ( options.localOffsets[ bone.name ] ) { - globalMatrix.multiply( wBindMatrix ); + globalMatrix.multiply( options.localOffsets[ bone.name ] ); + + } + + } } @@ -147,20 +136,30 @@ function retarget( target, source, options = {} ) { } - if ( bone.parent && bone.parent.isBone ) { + if ( name === options.hip ) { - bone.matrix.copy( bone.parent.matrixWorld ).invert(); - bone.matrix.multiply( globalMatrix ); + globalMatrix.elements[ 12 ] *= options.scale * options.hipInfluence.x; + globalMatrix.elements[ 13 ] *= options.scale * options.hipInfluence.y; + globalMatrix.elements[ 14 ] *= options.scale * options.hipInfluence.z; - } else { + if ( options.hipPosition !== undefined ) { - bone.matrix.copy( globalMatrix ); + globalMatrix.elements[ 12 ] += options.hipPosition.x * options.scale; + globalMatrix.elements[ 13 ] += options.hipPosition.y * options.scale; + globalMatrix.elements[ 14 ] += options.hipPosition.z * options.scale; + + } } - if ( options.preserveHipPosition && name === options.hip ) { + if ( bone.parent ) { - bone.matrix.setPosition( pos.set( 0, bone.position.y, 0 ) ); + bone.matrix.copy( bone.parent.matrixWorld ).invert(); + bone.matrix.multiply( globalMatrix ); + + } else { + + bone.matrix.copy( globalMatrix ); } @@ -170,12 +169,12 @@ function retarget( target, source, options = {} ) { } - if ( options.preservePosition ) { + if ( options.preserveBonePositions ) { for ( let i = 0; i < bones.length; ++ i ) { bone = bones[ i ]; - name = options.names[ bone.name ] || bone.name; + name = getBoneName( bone, options ) || bone.name; if ( name !== options.hip ) { @@ -187,7 +186,7 @@ function retarget( target, source, options = {} ) { } - if ( options.preserveMatrix ) { + if ( options.preserveBoneMatrix ) { // restore matrix @@ -200,6 +199,7 @@ function retarget( target, source, options = {} ) { function retargetClip( target, source, clip, options = {} ) { options.useFirstFramePosition = options.useFirstFramePosition !== undefined ? options.useFirstFramePosition : false; + // Calculate the fps from the source clip based on the track with the most frames, unless fps is already provided. options.fps = options.fps !== undefined ? options.fps : ( Math.max( ...clip.tracks.map( track => track.times.length ) ) / clip.duration ); options.names = options.names || []; @@ -216,30 +216,48 @@ function retargetClip( target, source, clip, options = {} ) { mixer = new AnimationMixer( source ), bones = getBones( target.skeleton ), boneDatas = []; + let positionOffset, bone, boneTo, boneData, name; mixer.clipAction( clip ).play(); - mixer.update( 0 ); + + // trim + + let start = 0, end = numFrames; + + if ( options.trim !== undefined ) { + + start = Math.round( options.trim[ 0 ] * options.fps ); + end = Math.min( Math.round( options.trim[ 1 ] * options.fps ), numFrames ) - start; + + mixer.update( options.trim[ 0 ] ); + + } else { + + mixer.update( 0 ); + + } source.updateMatrixWorld(); - for ( let i = 0; i < numFrames; ++ i ) { + // + + for ( let frame = 0; frame < end; ++ frame ) { - const time = i * delta; + const time = frame * delta; retarget( target, source, options ); for ( let j = 0; j < bones.length; ++ j ) { - name = options.names[ bones[ j ].name ] || bones[ j ].name; - + bone = bones[ j ]; + name = getBoneName( bone, options ) || bone.name; boneTo = getBoneByName( name, source.skeleton ); if ( boneTo ) { - bone = bones[ j ]; boneData = boneDatas[ j ] = boneDatas[ j ] || { bone: bone }; if ( options.hip === name ) { @@ -247,15 +265,15 @@ function retargetClip( target, source, clip, options = {} ) { if ( ! boneData.pos ) { boneData.pos = { - times: new Float32Array( numFrames ), - values: new Float32Array( numFrames * 3 ) + times: new Float32Array( end ), + values: new Float32Array( end * 3 ) }; } if ( options.useFirstFramePosition ) { - if ( i === 0 ) { + if ( frame === 0 ) { positionOffset = bone.position.clone(); @@ -265,30 +283,30 @@ function retargetClip( target, source, clip, options = {} ) { } - boneData.pos.times[ i ] = time; + boneData.pos.times[ frame ] = time; - bone.position.toArray( boneData.pos.values, i * 3 ); + bone.position.toArray( boneData.pos.values, frame * 3 ); } if ( ! boneData.quat ) { boneData.quat = { - times: new Float32Array( numFrames ), - values: new Float32Array( numFrames * 4 ) + times: new Float32Array( end ), + values: new Float32Array( end * 4 ) }; } - boneData.quat.times[ i ] = time; + boneData.quat.times[ frame ] = time; - bone.quaternion.toArray( boneData.quat.values, i * 4 ); + bone.quaternion.toArray( boneData.quat.values, frame * 4 ); } } - if ( i === numFrames - 2 ) { + if ( frame === end - 2 ) { // last mixer update before final loop iteration // make sure we do not go over or equal to clip duration diff --git a/examples/jsm/utils/TextureUtils.js b/examples/jsm/utils/TextureUtils.js index 0f944e5ffde10f..625c7354dc870b 100644 --- a/examples/jsm/utils/TextureUtils.js +++ b/examples/jsm/utils/TextureUtils.js @@ -83,6 +83,7 @@ export function decompress( texture, maxTextureSize = Infinity, renderer = null readableTexture.magFilter = texture.magFilter; readableTexture.wrapS = texture.wrapS; readableTexture.wrapT = texture.wrapT; + readableTexture.colorSpace = texture.colorSpace; readableTexture.name = texture.name; if ( _renderer ) { diff --git a/examples/jsm/utils/TextureUtilsGPU.js b/examples/jsm/utils/TextureUtilsGPU.js new file mode 100644 index 00000000000000..9c44273c9530e3 --- /dev/null +++ b/examples/jsm/utils/TextureUtilsGPU.js @@ -0,0 +1,63 @@ +import { + QuadMesh, + NodeMaterial, + WebGPURenderer, + CanvasTexture +} from 'three'; +import { texture, uv } from 'three/tsl'; + +let _renderer; +const _quadMesh = /*@__PURE__*/ new QuadMesh(); + +export async function decompress( blitTexture, maxTextureSize = Infinity, renderer = null ) { + + if ( renderer === null ) { + + renderer = _renderer = new WebGPURenderer(); + await renderer.init(); + + } + + const material = new NodeMaterial(); + material.fragmentNode = texture( blitTexture ).uv( uv().flipY() ); + + const width = Math.min( blitTexture.image.width, maxTextureSize ); + const height = Math.min( blitTexture.image.height, maxTextureSize ); + + const currentOutputColorSpace = renderer.outputColorSpace; + + renderer.setSize( width, height ); + renderer.outputColorSpace = blitTexture.colorSpace; + + _quadMesh.material = material; + _quadMesh.render( renderer ); + + renderer.outputColorSpace = currentOutputColorSpace; + + const canvas = document.createElement( 'canvas' ); + const context = canvas.getContext( '2d' ); + + canvas.width = width; + canvas.height = height; + + context.drawImage( renderer.domElement, 0, 0, width, height ); + + const readableTexture = new CanvasTexture( canvas ); + + readableTexture.minFilter = blitTexture.minFilter; + readableTexture.magFilter = blitTexture.magFilter; + readableTexture.wrapS = blitTexture.wrapS; + readableTexture.wrapT = blitTexture.wrapT; + readableTexture.colorSpace = blitTexture.colorSpace; + readableTexture.name = blitTexture.name; + + if ( _renderer !== null ) { + + _renderer.dispose(); + _renderer = null; + + } + + return readableTexture; + +} diff --git a/examples/jsm/webxr/XRControllerModelFactory.js b/examples/jsm/webxr/XRControllerModelFactory.js index b888406cf70c4d..8f13ff1bf97d27 100644 --- a/examples/jsm/webxr/XRControllerModelFactory.js +++ b/examples/jsm/webxr/XRControllerModelFactory.js @@ -239,7 +239,7 @@ class XRControllerModelFactory { const xrInputSource = event.data; - if ( xrInputSource.targetRayMode !== 'tracked-pointer' || ! xrInputSource.gamepad ) return; + if ( xrInputSource.targetRayMode !== 'tracked-pointer' || ! xrInputSource.gamepad || xrInputSource.hand ) return; fetchProfile( xrInputSource, this.path, DEFAULT_PROFILE ).then( ( { profile, assetPath } ) => { diff --git a/examples/misc_controls_transform.html b/examples/misc_controls_transform.html index b19805c8ff63ec..be16f880e08295 100644 --- a/examples/misc_controls_transform.html +++ b/examples/misc_controls_transform.html @@ -78,7 +78,6 @@ control = new TransformControls( currentCamera, renderer.domElement ); control.addEventListener( 'change', render ); - control.addEventListener( 'dragging-changed', function ( event ) { orbit.enabled = ! event.value; @@ -89,7 +88,9 @@ scene.add( mesh ); control.attach( mesh ); - scene.add( control ); + + const gizmo = control.getHelper(); + scene.add( gizmo ); window.addEventListener( 'resize', onWindowResize ); diff --git a/examples/misc_exporter_exr.html b/examples/misc_exporter_exr.html index ff19ba878d2ff1..af3ae4bc085b0c 100644 --- a/examples/misc_exporter_exr.html +++ b/examples/misc_exporter_exr.html @@ -178,7 +178,7 @@ } - function exportFile() { + async function exportFile() { let result, exportType, exportCompression; @@ -195,9 +195,9 @@ exportCompression = NO_COMPRESSION; if ( params.target == 'pmrem' ) - result = exporter.parse( renderer, renderTarget, { type: exportType, compression: exportCompression } ); + result = await exporter.parse( renderer, renderTarget, { type: exportType, compression: exportCompression } ); else - result = exporter.parse( dataTexture, { type: exportType, compression: exportCompression } ); + result = await exporter.parse( dataTexture, { type: exportType, compression: exportCompression } ); saveArrayBuffer( result, params.target + '.exr' ); diff --git a/examples/misc_exporter_gltf.html b/examples/misc_exporter_gltf.html index 13ed63341229c4..3e3ef06d519056 100644 --- a/examples/misc_exporter_gltf.html +++ b/examples/misc_exporter_gltf.html @@ -368,7 +368,13 @@ // --------------------------------------------------------------------- // Ortho camera // --------------------------------------------------------------------- - const cameraOrtho = new THREE.OrthographicCamera( window.innerWidth / - 2, window.innerWidth / 2, window.innerHeight / 2, window.innerHeight / - 2, 0.1, 10 ); + + const height = 1000; // frustum height + const aspect = window.innerWidth / window.innerHeight; + + const cameraOrtho = new THREE.OrthographicCamera( - height * aspect, height * aspect, height, - height, 0, 2000 ); + cameraOrtho.position.set( 600, 400, 0 ); + cameraOrtho.lookAt( 0, 0, 0 ); scene1.add( cameraOrtho ); cameraOrtho.name = 'OrthographicCamera'; diff --git a/examples/models/fbx/mixamo.fbx b/examples/models/fbx/mixamo.fbx new file mode 100644 index 0000000000000000000000000000000000000000..41653ea6128b420973cdff805bb960a7515158ac GIT binary patch literal 3080384 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πk{uY3>Ce&gGOzIJ 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 lgEqU{Yx_hj$p2 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 %zQbRGQm*xE z<7<5WHK6#?DA1r(3up1lE6}Uc7NjNhNVrBu1t*Dfn6N!7{~=F4sRgWiCR?7q)#Tgz zQbCWvQzC7#Ss%n4kc6)Xy>_{s2bfzXPpM`D2kd^b>QVl#{Oi@mEiQ59wJ!RnQ>$~| z?Nfc9b?oLtwvvh_by|X6Okt2$P$EIa)f+Imkanpg$Qm)5tFzJFST`EK9 z2~5%uJ@yKWl1EBah^e!?&A|nQmHlB>lXl97Xbsujo9!1BL$#+uYSN!`{)tT7w_9^q zFDl9cw0%{qr3Ob1)Vl{4n;+R<@7Z}WbsOhhBz!KN%z4IvH!pz=%~CGSU8=)B->T+8 zhNx0JnCc-wS)&4vP|DLEPatXXP%esEww#b8Ek;*tSN6Wjn zSk3Ju<~}E6MgGhe$|fiJnRV(S@8&zY73F?9pd7j29kv0cGUs6)cSaPJMwRDs!c5E+ z9(W<#F<{ylCi!By6qU2zXi(tV|Jst3&2Ew<*bc*RicWKXq5t&cCXN9&1=vS zvrahLU9&SN%)*o>KNqS z`754=-kqV}o#J%ChMyb5e4=q}HC7I7I>m;V{m7%|pumuC2N<_owKjT7@X=&1PH`k} z%G_hi@hnkjYiXLrtp!-6aO00$*$;E0oQ0-Jp}s>l!?(9{^}`CGu3&q{Xe4v<{M+=+ zk@!ATU-Q579w0^SHbrMu(sj%ZSZGNRG~p*Vsf1Qh8cL4+WI z1PCNR2zk%N`M2BHZe}k%?TbUthPN>G@43tzAsQVko~jyW?6$egq};gsr+wFWBYUSI_{Vzv>5RvX zT=kRTugBsNr2n+*vP$pTxvxQ+5qFJ(9e8D1A3>7&{Qm9yHf5feW&KS z-nZNnuoG?>Bst>x%#Q`nv_TP@ZJU-0PbEi?AGDN|4XHvKW6meKYEuzAtuHg1zS&6S zJgyegJK^;@MPpT}t$6AsNXaw}@shR~?qO>w3*wm$*dV>>78J806#l(xO=C5kWAVe} zYiQ5*+1xVJeukNyAdT~+vR1=SZQjPYI=C42Es2`s22awU+05u%Zq~RFfXsc2G+x%_ zN*D$x5Ti*>T`r=miR#{^i!Jmvm)AtG1&u`!L%eK?gsn4n_hSd1+}O>>#zMB9_|hrc zTtAj-{Pj}ud)DIHVpPv+q;{Td`+7>x%rj@fO^!t=Os+|FKF*<9sR2I1drdj9yze#l zx2A_P&0(zeWc%LHUP{i&?P9Ak6yh^)8%lV-@qvGMy!vaFQ}UI*(Y|J_AKRP|&b*>x zm?lbL9+~ccIbQK~#8<5>N}8)MS+Ux|w`cvlGAe*|hfY5TTrA{5e64AW4IGQs{nEA~ zQ_3g)mBCoC=Owu+4zlA|bQ@9MYV8r;NvFCZt~^Wq2`!o8NyJ~xW(3Yq z-w_5jEFVhstJW1_brQTwVe2=?S7zThA>p0E)#A}Y3N@R)VWfb+>A;Ej)ZgYcmA+B+ z*Px7z{5;}l)ApHDVI(V3U80Wt5I;( ze@{d&xqQG%5uLyD3m%CjU;Mxu=B+=mhwlM>yr#a@Mr&(ftdq&RdTpP7Y+DI0LnW?# z`s|WMN#kf#av=%O_R8kxYFvX z?P2_Y-tL>KJA4XP)h97IgQ+kPbinU}V)Ctrm#;3#i!>>Xt88ld8-6o={f~K=Zdg6v zrYC->@>W92UgC?isEjH|5&@U>uhlr|waZNg; z%r7U-lgG2aQs=L^d^O(oSJl_eBmCcFmN})3_YurwG!@|&&ae6I)3Wlp#JN~jX@5^y>y(o}hVeJWY< zhd^|UO;3uv%lu_odlnSxKoRcsE|zWAcmQ{ly>pPaZQO#Er;*FFdx$JJI#VUgwOmg_ z`+JVJcPHsV;S-xXY`kMtO_m2Huw~Glw!7rtyKqVuL;k1ETjd> zHG~#Bmr15=hVeQ^&&Q2Sa${^A>Wj#U_{A!30cM0NG&uYyxt=9mRWCb&xOqM14NJwomswK8 z(qz85Ohu@2{m2Mas-J|4Un8Km@tVzL|oA)C9Ef!e@ezNIH9P!H6M-#YPUw^G} zB`oYBZ~G=roP8$_xak)$j7aXZA!_s5mWp6mqHW?JXjXjV!)P1Rq2Z6=rV5G)eE=4y*0# zWRDw^0EOht!R?Se?%2Xc^gDr$t|s(;IXW7hoGVnA6^{V4h)7vcQDy3-|5tKXsW7op{YuA z5{N>N_3MV_M*Tuo@%E%OSz^+=r{E4Fh$A!NF->bbRVFL_!~$ey?_mYGwSRblmNU#P zPkB%**tc^xsAmTV9|G00#yehHUdFq};g3bPs174=>)!NC1zR~hGTOfaCw9wRtE>LAcJpu-mrp?n}0oLkf zf){{I;ZB?a)jfSB7f{`+BFQ8}o}F8tR$;*OCwstktAGpEEc3U72W^u)H6fCrFbX( z!KJuLBw+L5PEOgg9%MA_l-ruCjA9MQv(^PVS1~PJ865TtgwTym*o0oXp6KugP`=aI z9|F8o_Nm%4We!bylJC@Vj)T6O2gDR(iuA8gkNSMo*Q5^9-v`b_!&Hb>+XDA6}c*cQ(lki=EWfD2FP7GzZeuN78> zE_8LXb8!IaMr~VSguP)f30eXg6`=o$fHy{JCQzmIm zIJtROHu$wYsS98~HHlaE-WS=twL=pm)JP>z&x1RVkIdx9G%3>FB&E=o#IHI+J68%M zBfF(;ff?dzfEhAr-ftbRy>7cIV8PJOrP4NmwZu6=&Qi_Sc<+sq@Ce*J*_=%~|7LMx zxpf_oHfacKK#CL88V7mre){{ZA%8z}z5Se?Fc?1KN#|Xb*iPEE6|l;=D$pw53IqgBl$b-`d;{U{yn4X3eCozt3T@~x(EupayKFu3Wys!ZLX;3fx=wh z3nVaS`X64%oE-MlRUCtiehQ1w9$lxFPD1uz>>Vzj$MEfimq1oHqm{*5zzZjud}OP? z6At-kmwbe_i*n2ADGWYwz$t%Cd869ld2JK%2XwgHs>6JZz9E|neg5>qTGM|gn zKXhF=kGp*Xcwh4K5yFKMRanij$<=|sGD5}FKXm2yn%FD?2ZnA=!xu1R!9oZCfk~HQ z(g6gXc{e$;d3}u{p7({lw?WU>*kp}&C*Qd;?t^gN@7Pfj*+r>!{cs&sb=HmsV_##f zwSo$aAu6toBre(6rRt8$tplyrZg&t$g_2cRt+8*b1JhX;Nrn4*XIN#+pK_Q8JS#se z$!>PNY(DrJItH?KtBW-5fZt1wkS&&U7nodTu4A0k<-*7Dl6Tx3D&r2yB_4rxz}qcz zsKzoEm_tt~43M5SJJR;Gge)yZmm8iQ%LMsr`)In6!k~df)%BDJm$t6d%I{MhGv2rB zz$m!cjVFUma6029WN@?gg3S2d-@-xvmn`o{_6jzGk>DsucRgJh_d@ED2NanNfUPX5 zKmV_05#MU7WVPgdag~`>5|7V;hRD^A@AiSMeVQ0N^LI?sAsRRy>a8Vlzn823rf8E@ zdKUOhpCAQ5Sd*p#Cb3$6JJb-Y@d>i-2`}8 zNbb+~_-xKv@u0{Jfp;zo@yDeZ>W41aBDNwtt0q%6eRf{x{yaYK+Xuf z39=hE!6rHqlMa?wzJyJumUHU)PcQY8FWl2QwUNL6sUJD_Pq6_A6%`Bs#i4DCY+cbo zp7_;}CR;c@Y)-^C7k^OJ% zfsmwf95UrTPY2O#z;)N#t!7l?*JOiyzT{BO*>f*Lbr>t$ z^xwX3+QIf1b7AGb&HM!xjnT&R416N_OKZ?{#60|aNQuuqEDt#$7rzH!r6l?aSim9a z_E6t|UN7iT9RV(X&Yq8c(OSz?sCjVctfA0#&^fSsRmB}g+}LZ=RP;9p)Be#v?PCg1QzSO+ zZ}3>jHl9FO^uyRMp99vn*v!REe}?bl3?t}06E8u}`k2kNbX}Kz;Qd9G(5Z0^GHSs@ zph%spfchczKxTWXlyX`rZ*idEdBn+mOR?45ukT&~DpTA42pU28p{~U_1FF<%fOm~~ zUI4G*_TVv9^u_DqQ7HMS+d9p$(DUfOCtTuJ=0(~ zWG7I$uF`{}in_5W5sGd3sl@M7&wnJ{`~&#njeqfT1s7AuD1>J0c&8J%n8&Y|AWyBj zgI)&k)FOAVxZCKlA_e;(!10E>=&z4h>VT%4Z@gC|toA;HX5oF%5leF|H38v2Ytf{{ zt#xHn)arQio6rx1j-mUFx!iNr)$!q_pj82ihoLQy7agtpC-}wzh81`p19QEmjNA%B zl;0ge(Pet9@}Iz4`aI#qmhoMET?Ab0_g%oo*dS8+*)59f^6ooW8o3kCPQW3*Ky=3B zDBJQE0J<9ij{4w%bB`Du1lJjC*$!PtYwvE*ryv1j`T%rZ(XGB(S~9Hl(t95AQCz+3 zZm7N7$QHDhm)?->t-h6vNF`x!@Smr_h1NQ|COzWvcL2g~oTjc05enN??4&nNXLHB9 zJuGft`*O-n-H$v^z1PI!3GKa{R~+Rb=tU0rw3$1C`^gdb;+*pW)6ROy(Q+<(`X7A8 zSbx`iklzI;8#t5AVS`tBETmLljWVWHw}Q@x-}{^QIsx_DWzx~kGo8^S;t57Dn#MYL zb!n+)ImJZ|zzMe0NE@nc7r^^$Qv+3S1AXR1pYR`l%Lqz|vJ!t3lkZ5*%FD0<5()>=UONT$09H*@g~u>^If zLqYs8@VG9;)3kx5_P3j%TOA6jh1j$Z)zygRQO*hv-7QA80VChB7 z6pGqBUR>hcu;_Cx$L5F^?m+AqfBHvm0mj+5YZ0^}goYpLC71WGF{V!wh>tJUItt&v z$5i>#;ZL82lMPnStez=9yccy(;)lw;D5d+`e^dG)A--2!`M#9|0)zQP^}WJeso>A? zi`cpwOvi(?lpA}BZr%DDoJbfFk%Zn!?#j6FUZ4|xln49M815aHvfnrLvUz}%RTo_r zNT&I3Ok_$>gapxKnMq_2NiO(JZ zcR$$xCup%I4{LBRo=e1kCsaDEj<+==oVrRS6B3-)QPW4pwi!DP$m;c=V__GbMoKaU z(B{Fti9;jgzYdQ``0$3WUKLalHV;1G$6AbeFKw^0X0AyT@0uG_F2Ruq$( zC5W0FU2tdz{YQ0n*EGdhA~~X!!j2khFkb@Zp9;oKR+4(8pL!DAY9hIRGdgYQ)dJB3 zrO2)BN!Aair%3uBPRP^t#YE3$_b;jSu#!>XT<_L~mC&oqdTq{}?WBcyJEaCODrK0; zw{8w>l5SQqM~quh#Gcc~H~hk6FtV8JQ3g<{^vK_yJS|xR!;9o8)QHv=N4c6~=?V2u z7%{R#>n^6UQR2L{HH&q2?;j(d1ZR8kl7rtL&lpVej4JP=nn`aWI5%wRUDIEJsHC&B zH3B_c>litd&(XQgj#DGGQ?Kl;Mp$a;xczha*L|!9ObvEy; zd#|sp));XA^mmx22RHvdLMCW0ai5D)bk|rcoiR7(a1+7VqEs%!;aVa-LBKj&_@a9Q zCb&M(=#C2x9Ty-kd4|_GSYvLlMD>Swdy(I>$H5PfBOBPl z<-y2dIAfEAXetLk;jwb13HD}qumV4^CV3;EPVshkgJ8Zdf8?-jfhg1M+IHg@*H^~0 zlChkGOQu4)B0iz^q7$uzgplQZ)>1}x{B3Vio+gQdbLvBowDg6*@EZPt{(@3?4Js}4 zclj(*V9`qave}p(C*?_9uJTozncBo_5_1CGSyEZFJCagIz?b3a2G*k7XI-1M**2VH z;~t%}^8$(a!=Z0Wbkp=4;AOMmz@g;k}fM7gO1S>8|O8=;o3Y8uOoohRZ;I_J{}k+f6L1 zT8P=OY{)v-(vYIHFFTqRLMq$4(A_dEAH>^VYSoDbubbY@n{UizmaG!qL|}?D3H5JS zcyj`M@e{|mt#DBY977H6$Y|l04Y%bT|E5){m*pHVkBs8WIcDfhgc!TW4^i}I4&Ija z$+t&09}S9QsLt4cJHnLgATXb@@KT9-CglFDKMT~*dAKC!!U^R%_!mrB1K|xkuFKwr<~lAR0$D~g4vdQ+bB*{OFS@PcP($P|e_bEi<3#nE9X1xG5D)7VrLq-1Rwg=VUGv(W zOxKnl*J~nY_C{8l!0pt7BH#kKRg0l9%RQFzR$YfpEJYbr-QSZ>IAqS|Onlh{elXlT>@PiWp! zv0Jb3(8!yV)sx`axdOAT#l_=I+}W5pI>*X+!=MPf24vmUosizO6o*Sn0%`MFqqMi} zSur)A!z3f4m1lnq(~Gpps5sE91wP43Z0k8@a4WI3A);BZYY6qp`n))W4E|y(54d=M z6?V-_&)z?~L3^aF!3gWDMSE4}?f6=G({y39fIg3VF9&zy%_Dst3`YluUy!cMs^ohw z(688lq2dXYhS)bkc(4anWipo~Jr&+CD%*KHSF_&mflAb0hni)~YbmZA8{fi_3e7|9 zY>s7(`DN83u)GgkRyq+8L3Kk;VD2cH<;@?B52| z9?_GKIFDKfws&pO*#T|5IQVQY4op&o_@P#I&zq=>5JJ?oXoD0>@DyuU@TSUc;sZDE zjTq`P!;$ueHzxBq39w3@8w6qCpEk~HY~(!PMK>hI932|L#PM(b^|`u>+Xo}q3iFkQ zRyfw9(q}`)N8Tu`?uBLyFOB%qoPB2Ba5StQi8!h1U7Pq9N);?|)>VbECnKM%uC=m5 zKjf6ygjq9UJqOTjS~XD=`AzNmD4X0*WQ-iNa67z)Lc1Hv+N@dHjG{18#sFuX4Fki; zNjXmgIA2tMoQ&5GNG+ITzp|m+7ob<@WY%j+m@uPZj{9ja#(1nkPg8=&K8VA9OX6*8 zGBZY_@hkqvc=L>0iQ?+Oh{5&A3;;g$SM5bG!io+Y9((?d@q8M8?QP;XkIQm9GkbF8 zIAdTF_uU|6Cx9=rSy6gh&7Qbn;I_8!#S-2KY_;!TgmFHKj;Nr}C-V0Ez;QDw=D?h7 zNYM)=7EBw){?zV`z?iT)SW;QHiGPJy|0O0-I?Ja?R=o%MmdUJsEPvnq0T zQ5hqzqUJ}g62TJY8+zxooTt6$M04Zbo0=+cxL-#SNY#q3m>82as^K*+cslNEXp?y4 zrbKt9UoD4PW39>fjP}}p=Pac zlfmw8-O>X9g_|7u0=Y+#X{Bw0*K0@~@k4B?L#=y=7dE==PXcQK^+zLBXY7sh0rNRZ zNWRC|0x>d5aCt*9UTy0dH08~TB?JP zC@w5ynei$#xhL6S{Zr|rF&LugxS{%i550av^&zKvb&jh4=dVJFJ^5)$!iX zB`>P2=cr3sL1=X(6V3QT4{xd5AjydR_4}GCEu@IbJGEnos7)ViGGLMU<|gD%{HWF* z?vo2M$u}rP+=&Q6JqVl1uD5W{?6HAJn=Z*2iHfeG#lv$oA;0x*JAS3S+ZP7wx~+SfZ;}nBzF6g*otjMUH)-N`;ru9eaofrSR=Yq5lla7 zI;lxfu-Q4iZDz1Zi*6achY^A=7O6nOH|3_C)x8FTG0j|XwuGP3d{&bdi);%9i(fb- zum1168MdoMgSMXXnzY)(RU%6OC)m zg@xYmH?O6#*e2!23)0z)rKH!n3H4%2s6x6giParEIA@dnwxy`uKW-Q=37`CY0LD%j zj!U-1Tcv-RAMDym??h8JwMw*8eZ9|OSkrB#`L7~4`<=Q1$wAfib6hO-)SF&WFRTqX ziL-vSa}3>N9-B8N6n$%?Sc70x>qu>>jH%&-9U8MFtkn|go0`A@b2?E2T6Y!5xP%iA z0{xh2PU6f{HbN^IRui0*yX)=v31+aZ26M-3$*Ovc4bfya`+fUBx4XKjf_ZHsoLX%V zHO;%5IX|Cg>#Q2+r+c$G9R;f~?h739epOF@na@4R?>*v$<(2J9BNcN}dKkH*lf;vR z2#$h1Dv*4wx_(SaAS3T28sw*&PQ;(A8; zSgXLa@*7$?$@DUhXfNzI$p);?D}D5Zhwixgs3>z;v()j9$fMz6jrqfN{YttyI77R; zL1eh_S%-kO25aerOq3$4eT=_F77s4U;t~Qm#&o`tmu-xN9S+f0s~^pbX?mO7?^eV`P`mu2Rmw8xhvRF z!Q~(oXi~YDft?JYmdz5Hnt6zFBe0`hh!AC9qc;z=_59u)(bn^Zk|WdJW5$!-mhL$j z0uBuy;`wI`lqM34s_h?%R6nPrj#0S_Y=Rp=C7trUM4j3}Uyk2Zc6!YD6jg8*d20i4 z+oLqtWQdi=!5do45%fd7#JpkQ@7BoRIBrBb%MM=pE5V3$vPd8~_KA&zH;UrO3Jl64 zE*)(cGdNZ)G?#+6xU-Z+pSQTV1kn9|+1dQcVR)HapdaVXlR&%~PkahWz&<6!)ldN% zqdrxYDFVc8ynU|K`Fc&n0kb*2p0hqU=?v>udiXyKcpfv@Q?^V%;`~l%w6R~+^H&y| zXFQjWR&Ij5051la|M?X?|AdLT56>NF`LjgZ|_$*Yd>8fO72%PbMGF(zaNYL)A3 zj@KH10HE62t1&GO8ZBOcE}e%$e5kYCYVmG+;zAJgH7%ly{H4CW~PD@*R0=D^-bmhj4DE4td< zH(C_SQ2}%dgvcvs>^BeW-w*?1UzN|(fZMeP`Ed%0$n^D{alDm|PK#G~gy*u{vy6m# z^<-mkcnaCWbO@i3+X(^EXldsH9769m!OwBK+KG4eg0VZkD_ViK1wv!o4 z$JN9W@sB&l){L(YZZDPs`@ZREsg!CH~^c!n@o>uY-`|GIXm>+FQc9EkcpRlo0t202@W9qA#m(& z9`2cwXVBnW{;eo6G~RMwg9NW2;ZnR5U^yu>J2!-*IMSAK&hNhzFVF0*=+Y~Vi@7{D zw`W?DKc)&wYl0T)Lwt$MqQ0{`}tKr>pdUu^t22t_I1pd z0&>e{Vx?hmq)D*bJM5l|gqCn@Q}E?CTpvp6q$OAwgM&sVLMZuMtQBF6Phk34lGmic zqMQV8g=d6b64FUc7)DYh=^fp-i}AGdx(Fso)F>18$j%Ck%bISTCbMQKye=k?4e};~ z+qX-~2uAA8jUw1$qg!KSlnn_5fbr4^E!q+^`n-?ROg$aryB|xh5sWam&D(=xYHowG zE)@`!5|^c|z!}xCMNO~jd5-M{C5OUvD!MNAano#&3Ezny>uh>_wiUr%W?X7%nA>!j zxLoIL^IEP-XJ|t=GOC(otzMOjGqa~=)4ONO{smv2J>4pOJ=6@GKf`*tEBwye_JLdO zdtM6xN}t4y3t)ZmP3+!09)_mv?>~E=r79Yoce%tHK(o^q+V(ncA5)zujUjL{@))Hj zOk_*~#z^0vMeiOX^KGi%JYn3r9=hh5Pvb5mmhX8g;-i0ZzVGVLSc7UTNullu?`)=D z4cvSQ9nAWS8fV#zg*KEdf?cwCWumIi+s#yynb$b2k<*5s4B__;P9zPdsBM@rYhnZH zoCDdL1n#)(ic=hj02$fhOqX%RdOUAEX$V?qo?$yT_CdNq{^t0C}crEwrB`AJI%VYHzSsTald`&e=t`fXTmdjY zf!Xg=><`HGj(#1^90glH_mqF#-E9aQA5t!9tqRk+JJNnd6jz(sRVvkRhZ6wT83^^5clXcqq{*NDUq`z~t`HDSE% zU(@K4=G78B9{o(5g-ns2p#vh&&*+Y3i)>8Izva6MObKiDU|Rn!-%gZ*@f5y-h`VOn z%#uk-3Zy6H)paISIk!iYJqxpmEL1W)2~vOvdL5p3$!;2~;|`~UAl|3PyI7MpW31N~ z!wyw+QF6KesK9u-7js6%%}D?tUC6W)?x}QN?BIk|uVT4aMOUMT@(ul{x02hk5aQ+n zHS=2Tfsew1n>Zc&`gV2*yd<4qq<6AjL|})Kc$UST;P~48pc&R7pQxvEv)6YQ>H24| zoO62h2`iW4g{CsPE62%PtDCqrv_%leBJdt)FD$wA4uKWIG59EEEJ_)h2O%-bfPNQJ-i(NLAyYVs0YA2I7#nKdMG?FCELkclZQ2?f6h!`y|=Jsfjyt7 z^DMox>C4Ll`y!)Is{694CqfYJ#~|)6u`Vud)gt%`1 z5(I6uZkROVH^inmlFIS}{WeAS$))74+s0z3?Yynv89HOLdJtN|jh)l?X?IugGs@t6 ztEDU8Ajg|He%7xoZZU(K_R4|uKblVV)OeaBNb;+3%PNjp32S=a*8;XE^qLhR=?PdH zNf>6WJffSwyA8zqUq0M;J}M9pZIo$)0AjB$!?cxQxwrk>ILVI@G#J4M`Cfmak>GuJ zSuOE#bX-$@R4WBxIy-YfmsQ=xDhaLVI_iGr`(|?vJ_qcJ zCh0!C7?CkRIuZA~tJ`r&=H>~$%TfbVH)e#jC1Ea^%+|&0gXcADp7?p=XFs`} zDU=%r2y3ylaSFsx7JsjNr2kX)&$vJOBy<`*7)a-xxg2j{9qksr3dFEN-NKA7v=F@# zDj@$Zmhs{P!Q>k%n@WK4yS4(VV%*a6#^|O(OOIJsKBrwHrbc9D=Nu~Z&&?e+*$Eb^ zmO95x61M-mYY29y?VM=^|D`OfjKNn_>4!SD!lZ=N!Mr{T!@qXa(=9jQ3y zcLOusII+7fVpCx*HTPS{v)&#ky~89Cy=Zp{+}SfVX9=WybjP-w007@ydR5E5&eOXA z5Mu)7ANbV_vc?Q!yobO5bMJMJV{A~QlFu3;96bY_~o}O|~oMybDbBM1H=Y%cD^&R)?=jih!mvyQ+p6 zRBUieVQ+*HPuDhrxw*-|`HP>dV<_A&FZ~jMSwQa`qetYJk*M2SdyYo@cW=~y-^v*! zR6tP1iaa^4nmYmV9zBM|(F{EzOjQS_%)>OtWMGWc=CsjoRSC{lXo+>h^e|tL``|?| zS-c8sr6|3j4TCymigJPzln$i7mt>wEm#+`dAJgS($u@>W!%fwgxuX$AjUdz9yt}Ad zuC6K0h>bSYX5PZBI0v+&Vg@D3jKNNl|8FP#wW=PrQ&WzyggrzE)w`;o*fM{eA~Zy9 zw-RWsyWH44L$(1+z$zExOCA7}M5O9wP3Wbb9E;8*6OfAz9=47)*E7pX80Kq9`k!c0GE1dTa1J}k1GcnM z7}07FgX|8DsCiR<7${Lbea{zmk44HJl0*i$^q%V%AD9X*SD3S<;Op7g$*M~GM}gd9 zKKXxVLNo3|Gw2JyAUZI`^7z^k0rASpw)yM+!9!-q+LF%%I$_W^Dlhs3&RyIK3)@3( zRECY_eauWCGYbSZ(PY;Pw-fvlNh%8pW8hqKIZ9UJwAEA&rlnha*Z|iUuxI0dW%mB|h7|2!5X0Se(=BTEY{hVm<9Ba^y+roe zKU9+ppVpW#0c-rsUpeG&A?m$3;FiWVBUY=^&bLu;Cf(;+H*L>2(A`m9*yp8kX_zwG ze8A55sDB_@ee{4?iUyR@*j$a{M&DLEq3+@4g_SIOO^9>a6^AEfHV$YtDT0ZUh%G`v zT=+Wt%gZoRkVlQOKThB>ZF><{QY< zn{&YG#!s+&QT-AFQ;y(l!-5}R!|Bngt~nhIqW@vz*i++XUQ4oQ7PYb4_J8}W2<$h6 z=rJsQQu%i_b$MpRaFeHp-BX5*aTq%+vo4vZwtB6HJ4)^RtZ4jixv5bq{ekt6+7iPq&#OueLgMzUG2*!=#U<+T4 zSLTd?hcx~}U<sA zZHS7ztAlghAc){;&?x6dHp`+vpzF)o#d`=wbjKXpSe>_UyiiY0<0X~()WR#5WGu-3 z!(;r-5cJ8}-81@L*xcRZ04W%IgW?7b5LaH~f8NrxHm?*t;mv0PIWD;G?E=x}*+eC{ zZHw2!Mj5z^4q8D#(|R6e1y;^=GhbcU%e>~C!hN{t?81m~x$ca@hygW}tY=HNtvx%4 z)u@sXybQ9yi@i@Ou}C3J86;Kbg;mK#f)T<=RRmGOy!}7nz&}iEO!YtE;3R=cx>XK$z7pi; zn&;F$e!Yegws%YvVQ9WC1Nb|(Gl>H-B{~&r+t2R}AQ*9-i%7;%(`!w7kPvtOzuSfj zD1X#buMF}2{-OC)j`0dk6%Asw@k|6Fx|xla#8=WJCqvpjs9QR#SIRH6sI5TE1cA8z zMNa7om}qCd2vU8fr;v!GaD$l4@bp7UGJY?a0ub!O$ z&d(*i0cf0B`TvW;S9)!L)KyD=)b!wbXHw5ua0Vru^+&&IZ;TgqvaE-IN9tXrC>Pyq z+^+E^OMfEdi+khNJ!z-J(n4a8;h|5>a`;I8t`)Uqu*uJqqiE6P&jC50N^RxteBNi3 zqFW%;@pM7r!{e68t;D}p9GH?RH=8R+2WSvVt1>%@2jQ2u-2#N7F*J#E*@Ntq8{`+2 zZ(TiC_{p&+E=u&Ok#UP>Da#|l3p-f+apBNdq|VgKfw^+O8P|8}EKJZocz zFg!p2KotL;hB(KvuczIuvmq6aEgS=Cyg{3m9ZC$m=DQtMQaN*eDA{7<&c~l>{Iyn~ z#;XvTMz_u+o8ljU0~F9XA-;tI(YDQ6^CumH{5GYx$q=z4Yzvn2m@a)=s$UJ13m~I_ z{Yjz2a9{*$`S?c}oDbefV?woVxO(Oa z#K_e?DgZV9c@~)#f_1k9t1>ABtV%_9JFqIb?joy)qZ0M@rQ5J9mbKQ!2Bz2tP&C<8$ zYs*%rMHowZoos4rw>60y2O}iS|3}D003rVdN!t1c5`h5cd|>;3wfM=cTD(7bN$uY> zu#cS51#R8_WeBKPaWs&Ax#M)JE^Liw531N`8TfPaTxo$gl8PzA9*_sJ4E#VW&9h&y z`~M&SIod_U{J~X-VvTA;I-LH(xmkg`*l`guBi3QVj1k>7(zsx7T!nc#a#;#+TkY@G zK)W5sNRypQ^78y!8a8y7HaxCFoZLY+(m$8mw*_9!5O~>S1Mphx!-HDFw>Cvk0m_^) z(pH4Iq@#0y7$@Cp50?65!g1xO$13Bg0KBLGwhE>BGFF3!_kiOd-*?+O(F0jl2NRB| z-Dm%Zjg5bhU?HBYS5JZ@d841G@0tOvW}{bY8aHgon>TG!tAT>3=a+WAHRMO{zT;-h z5%YLWaNi+6i4x8^AbD1<+?w7um4A;e*n+Qo4CX4^a`|U6(d7;FonsZqfK9oOG!~(% z>;B>c0%*i}qL)+it!m9GMy$u_+G8!g3KW8kQ$rPriX8vK-`?tRxP7cT?U)M`XDoly z`eQ?Z>XaQIbeqjj0r5rZ>SVIBAWpvE9mfs$g}UpZ1|ITQ>&Ys!UXNJp;JGSpue-ujQ*<^?}EDh0#a+V}w1i?>?`d^|9BuF{Bz3@U|t` z9zvR(JuNF$L-cNdIB0 z7pVpGu>+mHRq2EF@_oO0VYN!uVo+lh(wBu`QjwcFkx|h|Q}L)fK#%_dK;dkkuNQW- z^hMgJ2g1Ic7E)(}>Wit{&h($Aw&AlH6m3PSGGWe@y@!F>Dm*RZCn&sm2S6b@5b0B9 z9%f$AHQu*l2w}q0zMBEo4YK*;4d;H1v*`)-vYL8z25;zb{(#)m?`DArrw1Yl1PXuO zQ0$kz3w{K)giihj=|%qo1$l>zAOH%orc&m$o2PRmX(9H#LJ%gnfU49uN!?lsru7?O z1!!D*&zqvOk+vQ)T=qyy#`T&XaiI517i#MPRbpdRs;l!UC>SbEBy_Sa~p!vJVBwdINkh5E+yFd|P zieDe#H)h5)5VfL)f^scDfy81JAd*F0*g?64<7eIm%AjC{4-06`u4CWFd`5a>Coe)}B&KNnPIw=^*5GNRG}g)m||E4|Xwf zp6{(n@E-nN*v7K4g`lyy9UrCjTKyvK9s`5S+xC-q9h&IqJ7p?4Fm=9@jcyDddtm}5kQvzHg5>mpp-!&j}N62+fML+U!U%~;G; z0$JT->Y~8o9oO`8kOyjf>Su{&2b9MDh(LQUZy^CvJfMV}bcmwr=g1H8W9FP|?a{dX z3AL%oysZ9E4GgKycWd6&IG({IdK%Vu_5XOlDBuC}TRhl5&pnw$gvP_<8Byx~uqSkm?CHZaXRrlP8d`p=q6>Ks zVkUHOM}9e9(xWX|&20NmDY}1s@Ygcug~mE>?d84J#yEjIDW6x7 zqLZgGw6TAqmUWV^n+zUAZrL>E%&b=@zjTsQ2gsKhQnjoxW;ZlcC{XRed_Z4+F zVgn#oMPq6Gb;CI`A_dzK-D}S$;_JLa;`f8w!soCjZ4FpCUnI@pQoK!#a=0B3ID2mP zNNoOLsTvFCuB1TQ7$>Wf76)ZeOprthA~;=kh4O`&2^LmB`uVpzwk&|AT^AwV=Raf- zl68+g_o#cE6);UN>B&)OZ`hEwR2r&LKhe_#RS8iONi|!He_YVf;`k!B#4jdjtVm@> z5C^#?E2U?iH zm$p@I6?#ZPXp32yFx85#ZGG!4kD!eFQ3ntuE`x7o6bEl*fF9g1o# zqb{i%Dl&@3Ed)qP5n%eje}m4QNUrm~@>(e>6{O_d*;?O140{Uz!E6>{W&$ZiIZACP z<=7nGv?K}?92zz>o@&);B*X!Ihrx#mIMF_)+oGU=yrra|1O6?G$^uDg!H(`!pKl@a zy{2_$%*%47!XO^2|AY@Vuhu3(a#>_xDlhC@Aeo{8f?OY1qudGd2~ShKfnW^feQVKI z-cdbKM7tk5G*)a(2gbPTv{mDjq~RrX#gNfGrdo15-n~Z+k|WZLSR>OzF>bT|AOjwx zs&D0HH?!OLkkmo7H%DMddJjCfCrRM0WaKjn9|%9;r38$<5t}gp(-*LtKCF)$WzpwD z*Ts{i{*%LwL6P@56nQnqHBq9B*ho_)PTUIHY%4k7D9nl~zVFU1Yu?fc{#m`(GEQ>> zwJ?SPk85DI;tmn<ZSX7=a|^8Zi)$_^^CKTVxlja)Vi2LiQq|Bj*zoZ*SHwEDE} z(UxgWmD5++THP?WJmdx?a#y$zW9jsTJqw3s?}Do9j@nTDL*i~7<6XpE!~^|S3!fLn zQlu~E&9)7g^q#vQxm5^{)&Pa@i#hXtY0dU4fqsT3!Gu z(MtKRH2MA_a#F-~WPztH5JCLPk8dgC`jbAr<`+N>dcKo4d>hA4J^epr9MbSXEc|KsXv4!%9>mGj*2cOUY3%xrQ!gsR<^b0O>^dFP*!dPPFUXcn%o)tA-1kV zPVaM|_d6wt2+p9yAXbRlD(--&VVm_|474MV34RF0 zuxbfU%F1knDJbK%}7L^V8R#hLMIkaXQr}GRLq2jhZ17^PH z(mxl>#^w}GON=tSqly)wvhw1DPu;NSLm@CcMIs=EMW{hB%wSm|MGMALZ<0k)5q+!! zAnXF~Z5qpi>I{g&>d$(V$+GT-+J6b{FAJu?fGhPc5bBTK7Kgv<-n2VP)31vVlt_W) zK-syaWl=9|SR~&nZEM(2T-q?+lEgQ3hKRvGV;Bx7YG~ykpostZkoaXqfT0vgEkppj z=dpFIyqh>jM`K7muv*Z92)OF1-_YUh$udCnz=&H7T3R%S0s?-pLEgEw`}dMY0$1m* zrRD7o9%BhPqX9r$P4#~SJSAQ)FXul3Zg^uixytc6t%G0`ZKpUfMDP|_7Rt+Qd@C}Z zS$O5K$j{)rzZZMY^61~>q<9PIrHxx#cMfUd(Pw{Z;;;;$iNEY_;7*Zgyam~Tgke03 zu|>cGvd(W2aAj9<$kVe`fY+PU6SEbCBCwS#k2izx4L>f;D(iaQ7d$X!dcY8ZaPC)7 z*rK%0Xcz2ShD0#((?-G7^|z(V3;KZNHufg{CyHZkHony@%m#M~FbK+gF}fR{OiKU$ zG#E^tPYP!3RgEo*8{8Q;Oh#&a6rpA$B$-)C^XhqPxUI~f+uoTLN$`$Zc7ftBNvOzX z!S=Y!8ZKu0> zh4UqtRI6CSET{<@2aKEflp2i$iQ_iA9ySmoK~lcq`Z2%MB;Y@(ART}KD(}-&=?#ku z%GWXz>QyewVmrG3E>4KaYMCAd9yzUI$C%);id~mALEZQErS=A2MMG&{e1pbQ8PAUS z-*WzHeRiFDOrTq}efI5YeBBX$(XUR_)`4L6v#&*dx?;8iFfhypHrLtGM+767b4?Jn zyF&b_>{gk~alxq^uzg1C`Q>Xga=8tjtvSg#9<2amkoi8fp*XNa)Z2YZ2g3GObX~j0 z{jw$4OEV~U<5DQ(L2`x3Q!!v!)#-BprC$S0QAAs}Ef92&O>Cnuz&e<4Ic7F)#jzby z049Uzm-8J^f%K>H&P@}{x?!n)bq>+S-OW^XV9Gztfkx>^-TVJZIXX+CEnrLi%mw1R zQ5x4iptyu!qJ!d4xTra<3X8r3#(wb_9JE};f%xunfqTVRkaVNTWj z2?ie_FmMB4V4{$qNFFtjNB~tt{o=d@ud&Euvtj@Y-j|Vqc6z6B0!a08{Sp8SDB=JN zVlOEEKepaHED7v=A1?RZ+$$Hx9LpB9G&RGeGIgpcby{7~$;8saGFJp#QYXu-X)#w^ zrqRlhk<>H+m#Lf-(8&~1L8lTE5)1(af%iZ&-_P%l_pdJVl5;rA^W4vU-{%|<41PLh zQGKPt5ttvjNFA{TN}v7p*oZrC=iKLS?l?udswyn+X8zmdC{3q)>VAC4p;M)-nmFFJ ziA0}sI@Fhu;W_6N9F4)ZJ$3LO-JzdH){K6#@8>)JsQ|Qi2i!6+T`7b;(dPMb$vZ_Q z{y3x<(1_qMdEjN&f27vjOCGI%gCkUbLLM^#>ewmssB0DH{jmxo&trv=r$ncR;x>Lw zrTHepb&d3L$(5>UwbLX<0xY9|H7BkF)N0WRdQ;{Sp8g!vG#o6ndrz1HxBlU zC*dK%+Uc6}Vb=ezk!S05ZUAy<%c)Y#zG``((#Ru|-XgaHu2#Vzy2OyB_xc!P+b*v; z4vI`HH%l1-SUHB%PY?ThPW3&f@3`X%5ZpLML+;6Ytt8`q1Z13a*ho=5H3vWKCIv(M zmG$>~1u${Gqwe#6ycbxCwI39u`Y&gA~$ zn8>I?1rIk7KuMlgiFK0a`0fh|P6UR|y0yI16CCv-1K++#iJ^ZsAcYt;z{W}UT5sk0 zPVT$ax8s$Z7VEcj5i^AUlfy_y z18Z(vkpVKzdQsp76)89l%Q$|Ao6Y{Q3}5VRc`pm8!Qshkn|Y<*xvrrxl7= ziKZ`@LL_q4>wL0tEix$!C}PYjz{0tC=m|iUGR;aOQRwov%I&yiPnrk_y=sK)6wl3_ z*1OiFTv8y*Wd%{~;n=Cw(DR?zqsbBd$MOR!r~QR{29dc(KRi9NuK^6$nSgKXnq)92 zs0uLtDa&??3DH#9j!TR}AQwPQs+AfraK3C(f!9-R+~^HWLSCvn4Lm(!isp2dqAqF; zHF~BG3`8#R&`MR0t;MO`jFV1t6AJ1-V<_eu24}sD+**{{2Qawa7iBr<8;eHI<;MFq z4df36<>(%j5Gh-;0qTbUxy|v~H>>4x(2PZclj1}}giZ#-_&L2HKH-#zLs@3>g?9og zLdVXC#{?2wjiICHHz$lEzk!RB8fBfAcp= ze_1-7-Dz9&M)c6hW1lX-1V|I0Ly4t{PT<~sy{v*!;3uJuM<}&1{B)c`8#_{1@geT~ z&~*j*jM>!XKXnx+n)wlb07o+1{4l%@79DxyTAaoO|H<{rI{0Tr#|{jeKKK3~A%6Pu zT-$6KaQ)Ul#3dWsC1VkVFN6l=t3bbWzlmdL2KsmFVFgH065sL~>S@N>xjI)*f#^O;p?8t@$2PV@YHtAi>6Go4S&tvW5V|F>hX zyY(^^>8k&?KzMnp!)q-h?^XQ;pw#ZEn)>58{d?f=v7mK%BwpYGOO2Niu++2yliA?_ zaM-xIxLgz5%&_)dHmT=JX#TlgyCjhdcU6$K;9!^eikXiYdC&Q1_O1B!=kzPWUtqZ& z)*gImd5@5?A0Hfksf|W~pl~z01xT|Tvw{8Q^@HyS*m=+`NMXKp1Ad98yeM@Eq z|44>y7qy!P3U9G|vnw*tTvl{6zZ#HrUu6>rQ;^I)DKxQ7Aqq|Gb;t?Ygm~v0Ex_ZT z{ULpTP&(?M(8P8)W@&i5xbnBc>fs7VJ9M@&Anjfh8h67l;w27792C}%RBMcL!Uld; zh1C#$`JcE{;ozC2`Y#q=0%z)6I*Wb+nz8+2VD8^EY-KmA@T^E|LoDrk;}bgL~ZWzf@Rj&@Y@< z%&gYk$bG*9R$9M-DtEeIZk^$)$i&Fu=0HCNR#F^0IVcVLV;&W`cgJ+2f)0~jK`VqY zjN0qoNNCA?-ybn}wb|8)z(#^`@j5aUuFS>bAQ$`AJm&?1^O4A5Y}3F(aF!yL1B*Hc z1mi=IyDrWuYG15dn%s8LF;IIth#pjWvflSp8U^4M{?$`y=WRQIi*XxJ9TilYgg*tZ zHofpB>t7qluXaF|j+!l%b~V%k;aQ#iHR7_hFj>U+An7#x8Cj9-)cY_Re|h#NB`bD% zC9fMEjloo&O*OaClX&cMTk!7>cD-*0u#0o?FbxO~=egBc+h7YJD?a$LHpiF=d zgE9f{+ay^j1U7cj_*szr%5L$qlm`3e*A8}-*Oxn2tTF%@{?`>ihL6|6C;`m!r^a+X1^QsWSrXa%TN>Qu0KT z;d*T(<6fhgBIAt4XHL0~od2Ifmg@gu%IV)=V3?Qu&zF$Eoq#|%62D<$wFeux@T)G4 ziEC>?l`96Mhr+R8&;^~l8qn7{p_?J2Dn+J6twgj#6Y?Zjo1gk3lS$2>${pOZbC(x_ zY7xH%C}ekm8;4v_vswXc74*ILY3KAc7u<~n1y%MWGAJIXd(OwO$`AXUpXzx|zdT|f zBr5oO;A=DVL#Y@x*yQ{#6lgcPdfEIN3PzJIWSOqd%k1v-GEd11{19gnVv%k&|Nh4j zW56VA`^F>;{@vt>q}X2IXKqK z54KA;xX`x7tpI3Z%sO*LDA>)*nn?6~q^PYBKn=?@d87p$OH_Td%DJ2DUUv{DB4{}V zcmph$JEtCXkf8UiAXntr$02U%W{Ok>T!Ejao6^rLT0hcfU(!Ej5|vYdDtXkm_2SqY zg&Z*G{_hZ*XX%F(ruKGr*<{FCmBH(vhP$uTx8U^^lsn85G|BqnwweOP?vFHAlHq^z zPE54MH16us_mHftA;R|%a*5IcVev)<`{#c>N}f_3y0{ZiRy_`uoXUC7qo65Ja;yWmQd;z_ zM^0G=yNi`{xnjF}UIW|xK!1c!3Cw>i1XMJL8qVUvmDB1()k%u2k31a8ADd zJEmSgr|X(pqYGXLAw>WvarD0dxX5mKfV{>5=S14aRTFZWZ}9<~-{ri4!f!^|mfpaWX#mb^^^%QiG?OAGS{0rhE4=Bq z%$Rm-S^J?$y)Qt6x$~f7f8FF8gHtHn6X}d?_MJeglE8E;i^Qsz*P$WpoAf(XfFQ}u zGN5Dwz978fjDO+u&gY>~i>{UHgYv!tJB{e>z1`NCI_yiCmu*rZTjAyKo| z`Hu)!nO&tI!X;BH&qIwCO(NE$k<;FG@&Zeb$FWIk*#>joPs*^;N>BM2pu@ZbNFBE{IUW=cTl4(u)<*Ua5qt4Vu z7^QEBxc|N^?sl{s?O$`@s;uMy{)V{aeW%0Z4?1<1f3VY6`TINjBCVh5zWdI8QvYv9 z`^icB$iF8Y?GNT%zPdopAoZtz$UkJ z@X;`{KRp5iqaSlnNKy;+H+2PXC>e~n;9qs6;K4N0%xQtd{AW}B4c>RBe2r3aHG3(- z{e9E!Nqf(&-dWY;BRO0gR|_g~Im zKF>41vx;bl+3%P;ShR!NI+)#1Pgx|4o?Utvuhyk1Q*X^F>>FRO9@_KVq={Lq(PKRg z;~|5?)7LgJ^WXRQ#lSVUK3CVo*oMdDgU0-{iQCGEta8y>0B5&&Vf%!N_#2CXwspY8yT1xQ>4Qc+bg) zo2E}YK)sB8@_hZsdTi$!eA31x7lCmn$BX6s+S!lP0~>}FlXB&%$FrM5EN-3O|JVJr z)XklHtBsG81QpJAADDJo`g_)V!g#cFU;WhgIQ-e+^SgGes1vt{O^&EBAIw$UD*luu z^&YXZQH4r8T@H135p^=PHeDeLn751LqA-xw?7$uhx?qs;Gb7YFaSU_lW4{Vo$Xm7-scxMDq*FlA8nliBjV62HgOUwNmx=+q>0 z8ohtycG8JQ40tARVw7CTirYF}ln%_l>SJ{Qdqaj3pQrMoSlehT;UC=sXELkKuW2F8 zj&%q64G%{=kK<9uIb_QXV_msb=S^EIk}_8gQ;Ph(4dFF&r)!dvLeKrUXyVGAa#^~S zju-GG$KW5p%)FXH{SKeHG(zi#w`s`Ma--rBrsqbU&pPge$XwE!lWl;D! zF5#eJu^s6n`AKe%7#-?3qV^@S9gY6GEuffQOC}llUEfp3xMV^)olD)%`>v~uiM=|l zn(j)1NTWDK9(>6TZ7(y#3=?u-dOqD%E=$*}&hg-Luf-;9>MFy)x^$giRV+)SHWQYJ z8SuANmVn_Lgc z8iqRe&kD2Lv|i~#oa_cSyZs;X3N#w(wZ>Q7cb!zFIfq=-J08t_*R+*q*sI9#jlMVHP>CwvP}tHExF*9wu~ z^n+AWLa1%dmgU=Nz;3O-#g>%f7w--+7o|_%VRC=|TZB9bTlX?s>d5!t90jKu(++dJ z1M{R+i|v0gM;>rkTrkG?L(y`B?fkUN9h@|5=<)QBXj0w^BSYi09)sKZs+!sa{@Jv6 zT9YeEJt{^!&n47p;YeG>VU5}xL_UL=k2%HV7BHBEnMG;jFed-!p3@Ic-y}UIM}rsP zWKRPMrIYWFB*$osC1!tLf5RUnlB@MX!|*X0v-)T{elw0_=eH1dd%A!Z(nbINxzWUW zgu9XOg+z^!s4}tECdb3l&?CornvBk^=smv>_hBlI=MNT9kXvCPST4vpY`j^y?>J9JjoEfI%G%`8(77L4-a6<;1O?5&|3NN6y2`M( zXK+|o{P0K|?fICG_$1gM*Sz*t)=YVUw_D^b5 z44|7arY#yg(=P6DJR*iU@Wk%~L`au3k>`3;RVpz0)S3$o2&d*6r$E;b9fqODtm8}P zy(zO)9rTV?_pD-BV%Lg#S9zxndGEthh`T52$`@H0T+ew@f!I}?hdMV@%Bo#%wCZwS zVt&TxA+jxM*hy#8tr?7c=R(uHk8^)qmu~bfA)Nf92ZitRe)`j+MM8T@I-WYc`WSu1 zmBu>Vc3r%ggLmPtJ6=F&Hi(^R5p`N3gxVYoWMIZjRdT(H6%i4%HM8(mL^YA)$|G71 zVb$0KYE)9tDK2XC3ad90JFxw^eiQSTM?DO=VXW>gYJv$TVU9h^ZZA7Gld$B(CszB6 zJ0=|vXJQ{vpQ&;1jG}g!{wTt4{xnRkdnss)jX7Nmzn6=G{WSyWfi^;Kv5N`?UsI2n z3Q<$nS>Ln7sUc~0@S>qH?p}&Tf#4*anG9-OEY}mC8^iE^+TA(@f~M=&KB6I6Xv-`i zS_p)sD^;!Bh%HZF^Sd-eyAMp3tQ=W*u^*AD@+sd?4O3a3*Q)t&QyJml;REtD?>HWJ zbcp*1*KfGqwj^fDkN0$_KnhA~p7CBzIlm23#pY4#ba|RNCB3hMHE5^_t{3p@RyFjm zI8qIeUu5$YXYvGb4Z(3w|%BtxM2( zMEh9Utt}M|x?nVY3SGENHSr+_eGYStZ1TH?IGGw_5I)Oa>=38@(!ogis(px>u-{R^p1w@(oK}|{LEW!>3fmuqe zKeDIUzmcx}?aF08AQfgwQC|d@x=I{ZRf@V(p25@m0eRXZ{0Ts@s7@jS=@DdQQ;2?fNKEYgz_@PI53#ygTU{IxEkU8~W#<+~+sH z&PRQT{E)EX#A!;bwo0W8vdlDvq2-@XH++JcllP`Le|=%R^5fiQT9)~n9Kd9gZCb*T z%)9Wq!H3f?@c4}-(fnnHt&dhi*->%tVx&JmQ$uN2ur2CtiIq1|I@QS8R{#4RC^EmjzqBbY->CNNWzTMCl zHg^lh)JXTlYusUlmjLyE2a1U~fRq(OuW=n{)!iy=l=(u)I$9|9LFi^$0{wbh%|YDQ zqqO-oO`_JM!)Iyq=eAo{2lgTYp}`l^6L{l|nlXG>F#4EYsynQ|s5^s4nctf~UDd;_ z^T{Ts)ps?n;WQ!3%&rI|L+C}@#HY+_2Hlz1d=YF_>L~o|JwsubK}{YY99rk9#x>a} z$B5gIRN<4GpK|P`O6pEKcw{*&^^Fj4%SMZ~Z`7gT+haYaRMO!=bsXNp6pHFyKn|)& zY}8S-aVB5TFm(2gzWbQ-zD>~t>INUNin5J$!Z1n=-eHrn4Si)B>Z$Hg{Vu&k`NGxKwY6% z;Tw1+_(vN3Z`*4crGG*thDADZvz4uLk+c=WF&+OLMH@fhWWJ`h)}&%whYU8i@e~)& zliBrB#M{WS7u|A$ILeRTo8}S0#9vTVPP`h8ekC1`IR&}8{_eK*;$MhNgt#B5YbCip z8|4)l@PU8GQN7DN%BwvYWg>|`7d&2$L0$eR;YQLzMJ`B6ChEtmZHp@IW0GoSPZt9| zEp5oI5`>m}pJ60iJ#4N?$R#)tlG*p=Fv|6W>ftnZBgPnO2S>sbWo3O0Op16Ub9{DB zAWm=G;A;388g5!PSvW9Vb@;mMiisNbW@d$8=4x=p%=~Z~n4|e_@o!6M;0l}wxqDb& zCd$}#=EB>wHWda(gVVZHhO|HfM3~7sfsexKbR=ZcZkFKXYMlbRx95iMubaJ7S%+e$H{UqQM`#J?$zH?48urqwsE0iBs>4cro6d zE%4Fh%1??F!$|3gIuww#@v@n)bCKc*Cn#o%^%*L0XK?ha^s)L_>#71*P2jM;E|>`o zIX-h_I8B(`MZdV@+J)~J+OaE;2MI>BFuXQB>YWG?Q#woOF{iMaSPSbMvY-RpaR&A& zLvE{V%Ah;ykWUu+vazzMIAv3spP?0Mh&Dr^gzJ}OYg&~-VlJu=1)PGdIc~=s=)%LM z$f-SO`L1v^sjfs?Cz5^=k%-&BO4F(oU#m@Z6m!M7D7AMclgaeOM=4eZ0*o#EtWX!! zhkX`-$mr%n+=+dl8;%ip@HYn*;=*H?aw6+cy<^hVsY5?m;22$|kN%p716{247}q-a z8VYEb>;W~{z04}X45Z$2P*EDEfLZ zeuP(<{LDtDI>!3Xq-xeJa%YiSW&3DV}3+1MKo=jF@8*XQ+ za?8C2xrMhskiYhZET9&o!G@zE1EOJy7n_XPbGVFsgh}6+j(6gvrNcFADZGn9-vW(p z(jQS6Q@6OMCMfu1!gsBzP2k;+qTRg|o4t9{*i+5E*SqB4(N00AIO~0H)WG(Yq!E3^ z`Y%4CT>oEYp%p5K(e*d3L-HZTVLf)akOS6znS4ly?o8O4zszA$$zn;7>P$)&`n(G-0!`zm$Urya4XZ6OfYR<3nkSRg*V7610$xxBEBNo8!hF zq|FD8veUM+%LBl#t^z&zM!)!TtZOhT{UGn?L%UFfkA7?1QyUaKe40Gh>$pIn1i*S+ z^O%FO2kDqH>b~%)UzPc{B13Am5&?XkV~8_EHNG-CS}8KuiQ5^?XKc_uVhzPN(`ShV zMDwQ){h9P*>3HYq_s2+m7C(`)b^o!LDy{pm$yb$aQLl+ZYoGIry1RUL>63&0$~sOI ztPjW#v`(E?`)0jyzT|b&2CKWB8q({dcuZ)foX;~6|3MxO`-lme8>>wnyj#yr1Y;AL zzMFd11g-jLfM0It+=oQHnwOt5C%(^R=Ct*^%$4WQ zG23UxLo{cK{!VMNV>D@X-Q-(*M|IYt{z=^v#Vo|ZrTN0{mobk;b5gV1FZTQ5)TalJ z$-#BLWKD^bWPw>zd_{^LlVnMy?;v}8Lxu~YZQf-pK?3V@3hEatcw0gJ~9F{fpkKiEVChOu0afmKMM`ilP@Rq*H+McOTx z!}veVz!LFi7vj!>OB^#lVEoQb9qNJoE{q{8n~mJ=7y*mWqi>u2gf*Arc1MM{euX=t z+vFiv6+}CEDpnIG@)SlDV?xlZU^mw@n#Qnu85kFF^(2It|5Hy?A;UX!2PT)5Y0NC^ zX!3$#s6YKfZt2;vkhUNi8Xsg92-=5FoWf`dY%vwmsxQSJhqNqSLnW(T#>jRw$&dDk z!RzT6Dl>|lo{p0l$#xVOR9OTK@@sY7AU{y0AX4BM$pbK3Sy)mJ@3nKric;yzXJ^OciX9pu$>82cfb68| z?9)@H>rUc2eAdtPW}+@H`XoDlhK@rJLOo%aaZ+635=`0NRe|_azZ>;ing#d#Oj4J^ zlTJP*A$S+3E;f0TT+`Sgx}O1;Ua#=JB1MwvYK{8r!r`&kelkK+Nr{GwC_6(jVL_*` zTG+Ldg=B$t2-xC^OzW)-r}N!W*O)sHeI<&F6rriie#xaoJW)=*&^NsB-uc%RAQqrkn87FF>7QDwrVXdY86WU-% zz`VVVrlz@D>{fq4lBs@VH&d?$Y)`wR#71jJSua_Bfgssl7%38ny&O!E3umEFV+1&# z7xpIUu=>;oMHGFi&K4}+N-!8o8^t*97zdh{$Q!1mKP^ZIgu&JvjwQ(ac9wT|4?@{U zMxw>U8ZIZW(Sj{HDyr?BO&ev4>Ouy;#DeU;W#6O$``YxidTSgW862|c&Hl2?$+8Lm zjBLaHVI1$lNtvxmpaAU2Ek6(TtiXL-CGgLnX`6xWis@gEp*D|P7l{9kw@R*-EY+8to(mnVDD^vC79OZXEUHSx(h3lZ%DFe0NXwzjXGKIf_2YV<9FJbG zqdPVZ%AH@oh;u{1J*GYC?j|LUVhWmb?|l^?t8H$+9*2*TZ(dKG(3z={Y9rcApBAUJ zZ7ClRmxJk-EinBASUV<6a$k|z&HKd8ymv#!is@%F0%gqCwrKl zvY#~PZQSlrp_nXplTl1wb75T1jJUJWh%JEC4-S%RxSai6^kcMyvTMYAR&P`(qeG)< zY%K6;8Gs4T`x9L_l1Wjz-J)AFR!(R}WC!4)m}?HlTrlQS#5NuktJ-^^<7)4srCy_K zlAjFu3voyJ;6%DIR$asq*AYF%+U{c>{>&C7z(IcLm21xFs& zt*#tW!_L|_Gv`mq^%;q4BeG>l=a4PfzuxpQxLUDJNGyYUbdViL@pM70tgKI7(+ObNb8C#%lugHQ% zF6LD9eOS<>y~S+$Diel4|Av^4A#(%jODE$e7=ehw({tbN_ICsSL8WX z06!}5VTJK3r#xD~8)Syn*FMHnvNEZn-5PzFuA*8v{0%5+*?-JY}YX#}!pWY%| zXr_1Q@Tfg6g6wHh#pwlhT5$w806JK?S+iN6k#ZOCmn7Xv_F6HTC>=bRLx6A*)|Uv! zg=Nolz0^{RQDe)}=`dzJ(TDgu@!r>cA4%ilO!9tW9A!y%esECZ5$3VQgM0ZNKj{`W z>2+yiD~X|J(_LFNB|si%@7CwV*-t-70+2{M-Li5$;)In<-R8Q-Rt-d<`p`pmX-+^8sd^NfrCl<$gT3hX z+0Q|BY0+G+SD9SnJ(h|WJrXhf@huEeJ?cvr(+|gJQh7J_Hf(b`Jjg+? z187{mj268W4~x!>YI$|t@B6vx=)&?1v17APNw(WeOEP6s;MrY)+!a(Dx`7*!iJaY% z7=+b%36BCv_SK4+xP^aq_zVsIcRoj>iS$F9{N$3UkDZUnZbP`13^f*Cvz#2TJu7)c4S?AW-W7AsvDtk5K-oL_mKcJ`?0^R7x2`H z2cD@r8Fe)y!a#BgAO<=qYeDzE69A`+q(4)Upz21pQC}sRaOfv_acoeYQ-@#kQfQ)f znR=)frTtzWiuu=x<;@*qaMFed?I&jliv4_zNL1;3HL+ey@#(90lI#7#MRxR=fiRJf zJRI6ASL;w@wdQ}w_xgOe)S*Ky*9QlD-kywKhf0>fY91uro$_ti2xoL{5nt=DU#v=b zLf>!-W-Yf5)2m=Vu5D}@LpC#*`v7uC9GvMRR>#eMkn9!m*@G%#*2C7n=4vvMil-8O zvU5d5=}KQuM2IP}YaSKq^5Qh1g(s0zyt7ZC1gEEU8Xa8f>3UF!xB|GnE$Fs)EV;)W~(rW(`qaJHqo+*;sE z>)KIt{NgS$M`uqp9=jTVyym3_jXq$dQbR z5}ijZ+l22l=MPA2W4!_1Mvg|LQkH#Yt)HIcW|@vu5tCJeF(dkI4cx-0o=h&8%{8WF zaG8>YZN4UP1i*S9f<)Zs>$UcWq(NryCu;b}q$? z{5DatToSK#&QAe&67<6f7R@BHM6jk3Rx8$2lRby-ao;V$KwbnXlxw@?Juw+x>OTF@ zWZx)Aox{KrRtW@>zn(`C_(V^IQ%%R>_fx%lcW(*!;TsW+lVY8YA`E z33&(ju;d}#Q@$3HpLQqoP+n=#O93~&#&I80$&)tV(5o*U)~C_OIcJ3G90}q(^twkn z&IV|0fp#L%^rb(x4-izY61^LTQ&P>urcpL4I_G|#XJ*+K-bGubO7oI z@+lNB9*a(zfPS7nv6k|qTQWqB+#}?k1cH-D+P;=#*;@ESGSt}pq7msQv<2{rS_UE% zNpo5HB+bWY%MZ+szS-}#tQvpI4NQxXuD)Et?zf;V`#CssLWvDzot{iANg9D8`FisL zl@^4+MxzcJ{#$T8;{j4ybTX!SMe>sVA>Mf6yQR~|eDK(cjzpP|^#`r;M@QY8rj`z!DZ5V55&QE{0 zH;{@h^Z~*jTX|~(jz1QBiN;^KUj86gfQF3+X>5AH*dt3jw2^`|#B7T7P_&wVqWf+h z>41P6!hbRAe()eObgaTY=SkG#F_AmiJ+6n;kkxW&;=Q#(?(2Xh-{D}Icuk6KR*Cq# zSnXM;P&?LQcl{dW~a1&!=ouCq@g9X*y zl#TjyJ6gxmtmER^Hez072Dyy)a9AHy7yIK3W2i-igV;W?=$5N!`eX!VL)OoWn<~Fs zx-tT4_c2z6C>l;UfrloUKEfXuI!`M%f1u52%{(8cpedqezA`JZR#+A3>hPnrcM!OQ z$qzap^p10Yuw{N{om2zKY*{|D1QQ08P_v!DmzacqH=g_?fl^3hpeVgWBArJccBPF4 zVa=ra?Bsgz#43#*VGA{otW=S6Y`RBt`}t>(Psvwr^r$xqtDq{Nr1J+C1<+e;@mxBj zkmJCipV^nHC6vAG$r#>CD~Ej2<)oxncToGHE*{hSQb@3&x{q6oLJ>}ZHRk*BhcD2? zMq9pWycqRvQv?b!cpv4&o=?LDG~`_}CP)53d}tc5;kb7afz791k6{bx0W^AJe?(g+ zR`Rs)OU6BV98J1)+IMdSpfvm!Et=$3C~z2*azdMakS48sa(%RWbbY_1)VChJuEk8j z6gsgjYhT5$k$R(HCY>Bla-aH>>!9i$cpqw=k_S z{X`##u(QiN+0(ey{88~t?`U&yRkv_rz#IOyeazHtFFsmy(HCD9L%`2m+CSIcxVl^? zoPgnmJ`EBq-#?sNRa`K5<}niaN{v4T4}$%PrIO&$S_RtQw6R$tuhpK-m>Ku4ldHBZ{KB1+<30A zpm)@u5f$Cs#~(zYID$Qs;97U~LLz=|41qt>!X#BKL=JIrty{lBg>GP!K^_64EbgHQ z0}=IyaH1_0@>LSaudA4rg4`#JW|4!aPV6<9*-Z)9JJa$`Dii6&Agj-enh2Ml`Ktoc z{O&c&)mh}cg}mTEv5yDc6Wf6A3vt_NZDUUBQss31F&hX@h<>?$lP(JFpYh>pjXa9i zdaoW{xPiovr7n0S`;vqKwOR3&oMrH-?oDZo2%*Hw5UnOQYrC<(j2S)F8F)xMzZIIc zCN~XGCW;B$=W=2Jm9`@R9V*Bh ztTKtHf>73|w_6WMgqNW#6{}Ms2~qLYf0Fy;ZOB~@TI>9R8%lJyYFq^hwQ$>iD2993 zy;(Q#w^2X*P&{o;nu%>;S9)OAi(4ck1s1`WfP`RsTBpquec;bt_@ATH!3%)Q|mAIj|U$} zPv(U;VtZ$zu&ld4?h7Lq^$a|uTnO}!VaHr{z>UqdmZA155JoBMsHhIr_+6rRwvg2G zG^L~q#A^h81&41K-h9VUNIb*$;_aIYxeOlmdct@?-P6Vj8~dn*B1mHMP$+6$a-#}| z-Qb(&lP4%0YIZQ;a9-Xd7=n%OU2?E*)b}O}EK20+GufDi_i0Yni88gx03gpo@&}1< zUxUz08Xi)xO`ju$>^%wI^~yApn$y@kuVic?;l-@ML2aaW_4#`n6cZlxBjLt{nzR_U z<7K{n>J#MmwSZKsAOOpup11#j818X*jAhh*LWvD{&`Y`ReINQ50%8`w^=3z6im#|x zcbvZsuZEM5_Be;E;G*PK#|s4Vx|0qX9F8xLYhPgTnA%e~w}aqxC}tV4%O%m=Od&g; zLG8=D8WKyx8&8w#x~uQ5LYNx~Ghlv3Q(8E;UkM&GycZvfU%~9Se^;^j-3^M0We*@* zam!5H*r(R}1Ba&Lmu6?3Y3og1Y9&$$6MS_P^1#setS8539xmM0lr|a>)hk=zEr64x zbA(Ll*YIQ5d^(CozuUB<^vV2}b)slw^?Bi%RCyZjuc17^0GgtD`9lr+xwRFGRfmmQ z*fG9vrhj`(LZ&hRR9Hpky$$&S6+siLbR2`_hWyLQ4HOwH3p`)}8F8#= zcyc}LK9!sa2He+=$t)#1K(mb7GD(d3%HlcxcBldLg;m+W32?(lJ&qu+QpaYad>-;L zh7QrnEfhgud0}~I^?yMiKY0J5nhYFyMblF3hXMgp`2HV|67V<4Ct&d* z_hVW$$Fmwf&l-yg`6#;hGmY;(kZ36JWOaduF_zC9TPw@XNHF?{pe2BX!HH&|&ahTw zX>H%X52{udGGh5(1|?`(UQrJVC?G7Ashr!w=cX4z zrd{HJ2gWd#mF2rDeD#wv#5L>zO?T!VX3FuQP4W7i_tbrHOlnCYT2ClKnu*s^`q878 zW;c{6y9YqQ7CQ{=?*c{l92MOgvzJIN8Xmt=?}~VGWrcxO4CL{_7tNeX5{!brVO;YA zPPDP2IhMg~e!dhmtPg@hhB7FKB!6#tL3Me)zE%5N(W^eDI`jT+Yj?y|VxVsirA>=| z3YQ>!}^7lTmet?+Q zcPXvXtM4S~|GCPyn3nu%9;7Z*E+jD2O7k#yDZ3r2;^(o<9Nju3~H+G5-nwrt8;ja}zh; zSJ)dpyrVgY?U8ZFiB^ z7-lu{Y2rLT<%0I3Yn7!{f`(aX# z_P^<&WDr?*3kfg@<#^8IKtl42$@7gVs_%dCDHu~HRqtL6K3e3U3uV*e9>lP+Qhods z1KqxxBMTpPKc>+p%boCRYghfU|7A2%a*JC3eOFbdbF6=#Via$W9L>?~n@>?G8}Q+p z#d~Z~3m4USBXF#YfYsvatxy*G11IFNnwjE7Myeswx*Fkx+3THcP$$C)*322vs*xRV z8?o?6eQKkJA{^a=D#FpzgXi;a)LVgKK~N3DCrsLHRU|RKsE_rBZk7MtXeLbT8o!~5 zl#TWWFNoX*Ly|mi_0{`hS2D|QX2o#@VtdH&h0xull#oWBV1?#&u8G`7j%J(fwB`BF zeY*Jo2r1y^OeoU2cu#ROyg7dxIO;#fcKf~Hi>Dn)6A2Mk@%dp@yY(XdC#QXSBsj%85N6A&;%D6Vgx&5mkQNv9DfW*)+8@v* z{smR%uPBgS2mE_la%?gQW*7HQM@{?CZPyi%mm7G*YL|fItlsv!-&qB+daVw4w|2Tc zjc(-t?bK3~0?kR^pWAq6T~+@70fI^c00=6tpis$m5wk#LY>=-aWDAx)T-j($MxuYY4|sVi4cx7ZolFVu`n&vk_G@) z^L5;me#){}rDO5I+R3E9x@Vv<%>xNLO6!BK)%_d~O?1pD(rjZz&36lHcK8ZVEH z)F?L$PpB;i8xJ{SC5|fOR5q93^@rNyog#d3%ZW7h*Ra7)@gtqH;HLJrQ9q`dqQjn5 zM1uJ&a;Ltc!xih59e#i=Twj0nTZaP_9S*|b|4=Mw1a&RIFNt_QJ}k3pKa@!l=AFB))X5u@OSm!UN@yhcHy11A(D2(23h za-9^HyeE;tED&zJ@eowAUn*tnHQlGtW6n^dlgP06R<)?KLg#Xv`bMk!xu@vWNGT$S z#)!V7S5>Hpx0(5hcq=1z6>|$adrokf$a|8XP(E>y(eTrNU7urA4{Nuv=y8!T*pq=f z)yUaT{BCg%&{^(QWfHG1#rxcbW7F3PUf*ohXIFWYzCOB1?Sj5!+hFCwazHKmYCsJv zn*GDEIenoQHU0oI8Km=--B1J6FYY~x=R>jqYVjzw3(>6^p4CgV&TG+B3?cInld=Df zxwW!?<)D8R14PJAwb)1e$srlf zAk`+cE+Qkzmwal1OK?!I3`_OpwA zEMlWbabSCuF3Q`T868)7#&hQuT_34|Wa5_dAru)0{-Ru2o#NViT2?|-8l@xaDF z)zX|v_I8(2ix7`ma^ud#$)dKdo@&;*mw=U|$JxigMfIpgwJvaj?hXK@vywA*q-=Vh zU(`M79iJABoc~mvKRXV+aii8SMp1s|D$38VKh5pEtn~?O=f|Rz@<_IgC-^KzTt^J7 z#ANpSM_S=Qw%Ce9uHNozExke~TamLa_V*~g(0e#WX!5dw;KI~(9C9*XrezGXsw$A% zH>x{3rby*>*56WjCE>=?+C?5Dhx`_3w5*DOfrlrD5WvYPwT{$RU}9H$6cSU1bWm3& zAulB+4j^2;Pz%nhiRQc&!xZ?lA_|56ij(=sRv**}hirgH@l96j7J(fMVyD3Q7+dZp z+Z7jFMg%QohYO!{w>BQfuKPgdyg0eD3&d+y$~teqKcd;Xi(WXEf?IeS_5EnT{vFX& z(Kh_7qVD~AaE>_(F;#Dq70OU~U>J-5Il_p$1=jTR>AGKVBHIdiTDjaeN75ZK%mn$7 zZv$A36f&%~ISp$OgG$V@TGVNK<^S~7mzO~112>Txe-!xUF?&hYErH51|J=FqZc&Wr zVE*74EOqOhH8PX7jR98~(Nz9*=%V+@R0`{J;-y8K&O`Fa?wR%&CGL6I6jX%KG>ap+ zt@{c+sE8aHc^SyF!{*}U&o4?OWswbB1s3ohJimYQ^yB}_+8MIY2gBvf>cRJwNdIe4goQ|39X_Js#@(`#*#bDj~$IZ1+%vkeMRvW=obXuEU10QQCwUGvlt3XuDYCzLhST zSyNguGcH}UVJMl=#n1(rsZq>KX3Wg*yx;b--`_v`c|1Pe&HMF!z2C2Mp67Yac^<;$ zh#~X{ZYfink&A6EyU}KT9YxPzv0buWRL<1K`0m`Z=bn59!A>&e<zyk>f8 z1h;TdMcU&WZ)1Gz(gIKyo{AXlGUW28d+X+1E|A|+KgY7C4o+=7s6T}u9Ui8~$dimC zWa6~rm}M!*&PB0!@m1|d(?;t(i+E)Xa2lI<67kLztoXOt@;B@_O$4FKo|5sNkBmKh z|L;KVLsusWG&y8A?Hr^Re6#vS1~5U38z8Gv4+5l6c98*0C9TJ+g|iCA38nu#X9i+=|t~wjDMi4hvq?=1p^dxPYiiov+ zKXYvLA$E~&CM0nZ0&&X=cBqB3O&2$0&VTj6$*M4W^tmtfMd%@>n~{jMy@hq_kwZMN5;?>mA39&x(;T)|==L=0 zIu=83q|qz?^$(_qfA|z30j-#tqzDFibC4E)bxq}-1n!`gWh~-=-|f-ix|pXZzn+-5 zQ{;dYPbUPjmRfuB+A8jDh=lQfK}#BPY3ydFQkcawa6RT9gdYklWO6J~4=Ump%Y81a!W~K9wXK0W{!giDm#868q~d z*Xtw1YJ*~)OExywjUNt?K*e2LWYn2+gxj)3 zkeFgUdhFK;+Zb06giHR8bubDs+?Y18UM;nE3+haMI3T>$6mmMq;FE_soGjR2BC^52 z+kh?r0vI|`z@SQF$6C2$GBfMFQ3sraI^c3I|2?|jmWcv7u?r9fY`e!+qepMf0bi=! z?Y??XGBSeL;H_w6y(+u{P-|+ zlRQfL_^LVEw0Z>H&quVO6j1u@xHrB(U@1ZmNRZh4&srh)-}4c8q1(7!sctZ}Dm8=j zhPnb|5r`bWy_*dc1*z7N*V|Lax<54c6Epl<`Cp=Y-e*1CgM;}`mNb!m{|w@PPZa*o z|K97{*pFcva%V$PXE$?j;=AK&kQ8(3%SIPvKK@E(V73fN=0nzMSeiDD7e9bty93*4qtjwUhCAo;@u!luGjPw1v~g%N@SO^pAIy z5lI!2-(ttG@wj;NG_0T|3DAMha5Qtx3xSiErv3E6+FY=wxk-+(Yo|XMdSa@rkhecL zf+B-WGUHa`9kRKva|Zc3-Dq^%z=JlyZ(i9awZYJB!21g5tLz=3h2a-^z7xGD_Phe= zr=Ck%gO_NP^p$-{+#szK<*{E6JuEt$JGW+?7u(Gu*f-1@cF_ng77nIz$I8uZ@&?)l zwCiRO12AL%KSXQ0XYU;i#a7zPp*aLjxV+y)xi&~E_+}Lwr4T}P^TI->4TCfgKWYt7 z)St=K8g5@GtG_d7(B08>GUl%hJ1jkH1+%- zdg0{GtNA!xet22Kb>QOowI#H>&R_*J`lBt&R8cFyw3;}x3iNx|MxKvgPb_NCqOoNL ze{V9?4=$@&g@z3W{$~Xc8?Sf7kejv;wF1D!^WFtl$!K?1es$f4c>fuzII7O+Q%7Ld zB{|v(;Q^v3_?ow`YOCksh9o3zfFZ3E|GD(RHY9zZn?VZWjWpL7((amlbz3WYo%&ru zEq@VpveOC z(3yXPL-$&Z%W1YIFGy7h&a3$wEJ0qa^20QQ2MWgY0*hSbrpUt`h$;Beuayzpp$n#9 zVWylx&hct3j^O`rVdVdd4`khgzm0nwuTXIRM;Jv>a9>BfYwKx=3)dMSCNm93A{zMZ zx}$dn>(_1^+dp>*1_Gocsm%8)Y{I9!$r-S#+uHS!=Smbt6uX+Mpzhd4EHGW~O z6{L&>e-(W|T)%}^W!nI~bLvBFzrE#C^*Pt%a{m-I-Hq?nd91x6(K>Q4LYS=Sa;l+i z;Q4qza*|3)P**y2RIGjfOhaq2Y8e4~g{TihDt5aSl05Xb$5GS& z5;^=SrlRC&&7E3kMvJ)*B{diy+LO@hG0eGQ2Gx{vNF04wuTjRez9TysmKX~m;kK&TpZ*#{whDG z@YIS9wU!!(kpSVw2iAD~NdIDs$+U4BzRpi41? z;w#d;mR{ul746Pk9aR}@1p3-{iq&RPPHn^4V~L$Ty~#Z(3C^|-_+ftY#l3Mu~ zdN(g;$ZrkyMm2B*DHXqErXcj}6hH3B@zYx!E<>W@x4Bs0nq9IgX`XTPP^rO;*($`M z%H;93xR>q~IDwEH?agI7kG;W*<+Q~gGN=HtI5LzDS3|>JX9|nN@E_5EmdCr_eT~-` zwmQNGNd%f z(M(g8dS^#{uO0WL>CEd$;$c76&8m$Y^(LkJ-@11bI&;w_snw~e>1VvTi32)TA>5<6 zd0AtUyEz<{sWU2Q#3@T?)SoEOXlJOFN%GL3ZoOY~_2)X`hLZZx^fM>Z+H5Gavpd zqdU0cb{ULsy-MRpLkf`Cy)e*+JNCk`z}-5WzihM1zmfS+z-D!aJU1S_YmUgdc>P`9 z{QhN)yWI@{7b!5$qfL(NebMOmXLIn*`^~{c8Xt=;1r+W1dc|YY0?&X&MZX_e^!=Y6 z_pdCzaOude%uTbSO*Z7$oP(O!_qJ`wig__qx~X-q8q2M5jeLnn?f#1 zb%HXkwhzFd0@RK=jK6x7URrYswWA_5B+D`OHBAqFr#74BBOYraK>PhF;s zO-e_P=}sIyzFd@Dzq*$*x2TqT$wuAV-k=;-9182LCjyR}I%FWQ-W-XVf0}*+o6e@Q zt~>QvUs&2Ww!j#1R zv^#Hb%L$;BIQI*?&bLar)0a;{k%wz%=?>A(ytU>WoDNb6uzxCrb(>Ja9M0R z1!>V;_Mb5tdra|NrA`uC<=>{G{T`83Wyh7D%$-^C3Sfb<%dmxSijU-!Gg;qr;yKGSYMP_sJ* zyVe-oUr1OOM_w!rsdyN|>=Zp4d0sn36Inw(0D<(Z@mEjtzg8unkbV$_^r|vK2f_Q= zTtpv;K>Bwyx{~$?;nX=>v|mlVj9wifVHet_?}iXLZH+Uvkhx}EwjMO&{Lm@RlV7$z zsn;>^4BVrRzfTUpf7G#0)UA4{Myxlre5FIIKVa%AJHnsVj*VSdev2nN$}=Og~j`0R<=D=4IY zh(P-45B~@0gXjMX>7|RT(-{MrzycBL^(@OYWi3xzclCyFUoK@xOo=3_b3StnEeLAV zO~rKQ25UN2YN3mk&Ad|OEn#HV*B4d()qw2uM;c@IxE8+xJ!8+23~3Y#KfC)^ec#;r zA(mvry;^Bn*D7cdFaHGzo??GW|CDkVREF6%H!PZ7TfPXHz-;kh~b$MlW#hox5meKvV zwW5O$LL#^%MOd5}duuj*U1TQ86(?Kul3n?BXI zwO=nOX?N$#)}CD+{(FMCF2-ODZhrCcgYf>gd$bT#tJc{G7w{>bJ$Ev_f2MfZ`}v$m zowTnjk4RvTiGo^tQuooLCzAsR1n_T(&Ot_?6zxct%vIQ}nQ*_ez#+Zfr}r%fG7)~z zdIG6w{iG!8psb1Zp?h&*W)>cy8T)EVfx?xTbc#dxr4tCTe1k?6y4{9{K34@SMOf>>Qe7A(actzrC#&S&jdVd(gZ zood0hwLa*AucHeFTraG81+!(>(^7VF6H<&4W`ZXij>B|VAbbkY;=1$C?n#!qZT}G^ zd>)|LjRO;;>3I+H(38YNPSV@f9t8+!LvdZf0h$~2u#tX}a%^1vG_)X9LSBUQerwul z|JwE*rb?M-?i==C@fw%7f*;wkVylsZ-_f1sGHa{bR(nwOrbxSYo$gxECkZ;`AhJ+9C|50{tf-bf@nABkOnSbHay8Rq8FzBe_5M z?7d<`>s8d{2*sc9FU3zjkZ#vjh?3~uNd4&Mx$MI$j;jjR45~KhRun=J=}iJk^`-QE zFD)1!YaP=X{B4fnziOnFwp2X!xT~aWGDd7tc&yEEkX>qacvXHlbe zEn1$Ff@C0&57D=Wp~%z$lcd5U|J_dkliC~X;125IzED6R-GHO^7VJL8QVF)^4lTv z0AuT%dXXOk{Va{4=5xti&_6(uZaHW&=*L3_(-x(0j`jhXh{RX$sAXEjl?*|b??)vr#{3~sKzo$;xum`L{Fh2f@gn~jidldVGH zUmH&V{ndVG63Gh5mqLRolmXwQF>&O1rdq+8D+nu2EFdp3g)YRl&bTcC!GiblGwC>; zIPB7-H_0(eCp4Rngmem;Irl7K7FCN&Z3KuB%a`iv&+-x{N3p)dgS|1E=ZU3ZPj7)D z*-Y1mhJM@LVhA?OPcc&qU=xtuilJx*BKF9u4MVDV!rxWd|hOcDbMT^X3jMd_UvbW^nzv$ABgBJYheCF8$kD5T*ld5mPhE zcWnnP`OTX}2-d7MM6u@7@g$qlte_4$O3qruDYMy^s<2Q+WNOYGYXGXfMIb+&#v-fQ z*4|zi_zB^}Q_K@d!$CC3q0uvJ>gL2XQuTtY`t`k!QJ?4VKTsZ;?^3gA5@Zlw%z^UX z`^7ParE0sVllzkS2u#BTpeB&R*D?5} z&Z%^vP&+PciFkP!5BXR!lB#?o_`5f6LEJ-Ar9>>Qjfe5YNV59?0uVxSr4BE%u>S`T z-2VmT9{spJm~GgoDCkkgddSyDg2st>3zWAoa*ot2q|rGZm-Lc8uW%`R)-hn#S+an9 zmXiK^Z?f3L&Icf(PUlvGTa?q6Qw*@%7@4i0C!;?!lR8;(R;AQEQ26Y1U0U(!Ax8y|{=H+Rwp30(8_U1duc+rESggB=UiFjui& zzM$eW!H_MCg#7NV>0VB=ZvdC$^m7=Q=VcOs$H~_pN;-fs_uLM-;o2O*hiWB7(c`ts z$Af2ToI-M5huz&7wh_(cN&DC6rfLxDojk_f3_w%mW% zzb1AL+rCGzts!^t{J+@N23kED2XQnRDCOkb&J{_g*Q{rIR2oLPQ$Xj(r?V$le!2T( zPshM(0Oa=m2}n&5QW7j$>G$h#=mx&xo}?iTTIrs&M4a+Ci(YF$b6EY)7X;g;T=*Zh z-MB6rs`}N+lq#rS!@NsPfeOzEZqU3B`pEH_`i?}5@-sO;4>>-s0G!3zV4{@2e0v+? zG{>>80gk;2Ae@O~vxr`W%Y!%Hfm)u~xXbT-(z>phjQrfpa7w2K&l%C^!OvB%ild zcO++Svo(;-PU8l$=6LpkCUo8N#3_5*oILWvV-wyJe-=00-GNxW!$mk-;)qed#6z5b zoQqi%QAg|Ze~EUA1$`tK28`Wx_-bzpYO|a_cJlbZIRVF}xm4#(`YQ+=R8e0no3T*i z89f}H34UeC>WD-@`Qxrv{Onn5!A}Tih+9G$yX;gg3J;D4@Z3HZ&>>&8ILf$HXY1Ge5id(_ZkQcb9S z4?T0gW8eh@=RVhOy6-bai^t@`nAJCQiS_1|HzC^nWO-Aa$imec)~$+@8`h^GU+66_ z^b6g38L|L16O%AOc5ejxLtxhj%l^CLP5~y3x4rpj<|++1xi>M!Hx?kA++N7xIuvXA z->W%Xw*fs=DLQbd_Gu@H?IY26@d6qz+Rw>lipVK91O~Xg$<+aUKt{ zdYvyAV9mH&UC}sV>zP#Ta<9M$e&zU2XdF=j8G>BJ_7e1CID^9SJrnB37hlOjp>5?g zfaOEk<>nc4Mj!w=OqYz3lxE|rb{Y(Te2cP8N`$^HZC9dGoywu}c5y@wJC^f-5cmwE=zM#J)hK+ufB&kZA;Ytbq{tzVe5vFj|eN)FJxvQxo)! z#FR;B7{Epi0R}L1QT}Iz51@w&xkH+}ycZ-*5-ku-)uBISzF@h~g19J==Xszx0y*ST6-I4XU1!2R! zem6?qt~DIp6>LzG5{VSHr0n8`9owAK;>YF5yN=K+6MC9i0$Ie8ovPl1q5mDWzk6DM z%D#JWh$A!HsY00_>|cX<5{Z}e10>*uxorNOthvPyd${v9jfD{Ha{+^VW>dnb`qo8? zejsU<%I?uYz$xX$hlpQ@jOzG zun&|`7~SL?lG~wL7hoLf^V5zrFr;-VL8`A}Prs%(g%nD|{w4p-uVdzi&1>GT3Hl9+ zb#;rOCbX>T5en-PP*^8q4?2#MHX9!?=cYNL{O{$mm&@;Ng94!S{dTB>H<<>ckE!{H zGH!Q}XxrKNuKA(DRsZq7kLRN$0S{A%tFjB}DH zwbziBIlxV89BccL!%DmAJzVwS>LzBJg0 zU_q$PwUuI|s*PfAdDuayPrQa!A1$WQt$GRCNH@jEQHzO1oBN?z4KMUVx`7sIljIck z8t9@^sOsj{<5zGx#a=ajb^39_;P*4KHoV{C+*`@Wd)rzf^#=)e;x5RgvajizW??hx zc~w;WK?w5h_aQ_S)|arl>PwyLtVj6N?SJ3f#FlAuh=*9-7g5_M_=z{PG+;@64ib#I zpzm$4?qTnaewF{;+skL@w?rjb)b<5TJI9shYG{a?y0(pCZHe@ALQcfw@rheScOjSI zRBZgSvHB4eA{7GT*<=1VFWh>rivdGvN_3<4onay$`Pk#ZnYvA-s%)LOp{1y=>-q8U z$K(#P>jY^B@2`^n|1pB{ zXp;3rx>0+qYT5ogG;m4qdsVY{+?9LZG*Jh!Sf9rj4BePzQVnELH=!ar-e#;?&x-}c zUH?M{eskHal*V)SH9vWN7~a(;tOXSdf04}3F< z1Lldb)7SjSTsog!l}3|PD-Ay6xHT&_{G&$1NE6mL2?j-!>Ja1)W*@TQ4~QTxCY2qs ztTAkxG0Y~U^KGkd(Fh#8S712%HY?Mvqau`I7zGLm3e1JYVu3Vv+!`*T)-HsLc-uZk zz(uE?wZTO?SKvlN_Jq9pdwu59tKde-euv;vVRZm2)YelGX(aJpdy~R5< zV9BgCYvIyDza?;KWz_??6z6#gZY}BhHJoohy?kXlT&jLrA1?KQgtS1q9|mC!iq3tV za@qv{8xKOZ1dg}YU+_-~GkGvdVdGutuyU1Qbc671K-M;s@he zaB+q6I?laS+kfn1O~c2Wi-=+3wiT=WqNqUn6Mse{~7i>PfJWM_0jv*7ovq?&NiPf*V>C@SeQgp24^PvHRx zp2hHc>|7i8y-M>?y$`PFa77r><}A-16NeQG@5 z(qeZ_B8bSEGV_}f8ArIE!DEo`O~{8t#J$4g+q~{6pF6>EKDMy*#>w?ZeU%(x1gYkX@cOo5Whl zQ(M^HECYOAs&1(F+L85b_$y=xnX*!=mO?>f_J*~ub%lb%7v?h;&+eL7!JRdlIJ=|+ zk;!vEK+%V~2pFGXKJ9Rem2X-zpGL>zZLkppTGV*2fmUQuPeG-A%s*XYFNE8WR1n3{sozrw{E_a8w!L+mp8QgM z?dYB1T7MjYk+QJAvI(jnKIJ(P=Sv>Cn(4b`AJoL;-A@;d{?@1bgSZW8Hf`4A8w?xN z$UsgGYubitK>^)~Xh9w3(!XzC?Nu1T260FKIe9mr$VFeGokn){zmHtotGngL$sezG z1jbh^)cxhN3yGllw)=Lw+GNjFul>Up+GG{MU8z$6of7U?(X2@XO z>)jaL1M;hqmch!&@D_StpUD>g$&%|+2jVN#K}l{iQne%a{uVofeQGx-c*VtR@>ss&QnIUxyWK($U0?LD0QW#)@|Z^Rbg$&~AA@O%0N z;hz_g2)K^2PavCLZk;J^Q_r&9QT{Y_s(svlRE$apBy~uU*jYdBw(V)@oIGqYDi7PJ zCf=}eawT-nCwwfIVfcs|%HWT@L9Y|^Pe&cn0@IxD=-L>j{dx!wnl;<;o9o8h}T%RSnIC-%z6~uh?COXiUr7S=tTODYG>zUNk zFv=6O_-xUaMZd(P7kr7n8JVV=wrkpUx&608{pILbQ@#(eO=cM@Fp%O3F8E!tIX>NCxh(l7xK(`Q4 z`atq>nNGp;5w$wr0_$wPCNEv8#qTz&iT@)QJ~Q4_^weXz}#stW_D@n?fJI-Q5Dc-MWkqvBy@(?ASX&@|nXc#y#~Jl4Gs z^m3$SyK-XRy&8E{yLM96cCR`qijfjLZJvPZOHNu2nl@XFgo39<&-&q?eks z(0gIRNrYK%sNA?M%)Sqc2Q6O~szw&KTo8DFxVh#DZ46`~OHhHqG;iMERS=s!syn;- zo5i@<-@%h_u9t)4&Zg4V*PQ8c^Fk*xbxL7!Bg~eQECf+{!a$kC3%5~Xh<<}Q2b8!p z-1JJgS3Y)5`HZp~Jz4}B;bS2t{So@M5K%?z5c^CfBHPvxfm3R{%d6_9RmMv*>YVtZ ztlk}?xj@Bvw?GLY8$-yeenG3WP37Uq3Vz-S9%W8pS1m$*boLrBySF9sH;AZZjznpX zN*T%{*k4V^^G&sp@BP!9!tOliiF{lp*B8r$M8*1kW5w2QwsoK2!B&>GhhSiXE1dZ1 zzU{8A8lr4(4cuuL5Gk(hiyTcwz;_omS9I_Tuf`WlAg9inFXB}VbR~i=ukQ)EjonaX zlWA3tDnI}1}-ng07GA|R4d&*bSi~#ZKT_!y>hs` zJo^`W<)Q)Q$yvECZt<>_!qygG0|xX4l-ZS;FFQu1PwE^{iAEOSYETXqc2q>IBb!PW zA>UyTsOG_U=m_88DW_O%

    B#3Rkc5*&BmS4k4zFg(JgAuS#xqXb>uAIWKG$em#4woe-= zVGl^q5e$Q=&;G|`R_!C&D9`LMu?d0Zu!*b-Nhurn<6+uO%J2Vc!S`L`nSZ}&KVC^7 z@)8jGKhSy3jlXoOq&(kDh8=_$7Qo_^E~hN#_%gA_Egt#I(k!rd+Af@ixiX6O zQ~PomPxw!RYWoI9shsh4Ct+d*vbmR-vuASpv>*x5_+{oNiY(7qnk7#)AYNFI~4^KTt5)mYZ^Va zgDKH(bTl85U*`l4So@w(_C9P`D~5!N&~_+yix~M*E);E*Jgh^NiEmz!Z&Mhs4&Qp# ztPPwwm$5_Y%m;SmfwhAp)zCY8rZ7dOx4(CA`;i(;2_i$Mln0@ej??;gpCn0*o>x_7 zMi!v9!!B})v%+lapCTRt!@2u1I;!9Jn*3^a#iU`&Ri(O?^W2}rPJyg-h< z*1fex@c0Jfe=(yGJbry)pNYeYri&IabFIU*Cx(1 z7>HQ4Y{Xi@m+gWMe%b@;D|8+%Ck|`d(QovOs0FWj&DDYM&^tOX^YMZXRRs0h^CUO} z`IPlJ%jx!lP$gzr<==Qv738G$ z4G8o7a$a;E=<9rXDH`oSHr8^$4sQUfq159&b&5i`Bco!0SB(m5=(Wef#FsVnZklS0 zv3`F%+iw9vP+dIP1^Hs}T#waX`J~BzH63uyB&g|~ulNATP}{UZ2O|Ql>=x$fHx*q) zeZ(!2O}uB>%o{MH1et0U?fXlvK`+YyEC!R>m=8E0uqv&o8{Hc1Ly;Ov9q&pqRMbBb zq6*FMEOZ{oD*KOqx|k)?r2ytE{kH^JOg#%d)oneJCSN8_Z8aX+L2W~lVZ!0-xUK-l_d+xUURQ4Y7rUO!fGW@sHdzY{F`aPTfo+cuUn%pd= z@>cml(w)9O?{NdrEFK>$N&aGK`sNM8b2ES}P5vWOlZAxr)}gP@SDsKlL2nDc;=hUmZk1qP{JK({WKL)Q3o#Q;+o)?lpG~ z`uR3BDR1%z@X7ikMO4i)o%{)oTD{V_FvXfN*E9jiD01*4kW2O6>K5WN+(@!1%?_Zc}dt<&NV=i#=2 z$TiA=pM6n$pQp`uHWqYzbR;oP5Y`OcjBqlUWm~@Vhmwc-6+7+10B-%)tPg9B9?!f)5($_9c*ll}q z$|woc3Nw!c_ft^j+1Fr`^pM1`Mc*q%Eh;#-*_Cu=xvd$;t;e`b(0(G&Y$-Imv&0wM z9}7a+Kesx}l3EyxpFp7y=~XxH^5K_@%nJ$mJCIF37Y#ZF_B{xhkH{f^Fg@QF$O*O2 z*jj|Bm6)~Xd>&`K@N0i`Df+Xzu{k;nV+Q!CGUi}#V~M7YJE03n{R!h>{jrDD4IJL6 zBi;mm+fEeNt#N9!;A;usyoDPR?Iz%cwa>FnM=Xo0nEnS)tP>mSgd0s?Bmrl=l;e9a zyp~AX7Cu*}yh`Imjx)p%RR&$H%{}v}U8c>t*fW#{ez)RjMKQ2EY+a<1RFO1RI3UJE zRG?;s68>uP-kt^Z9>{4)iyXCU3*spfC!srw)|Ft1K9x(d)hdggoE>#nW**`}KnLlI z%X&>6W{N!l`8woVH=#$^Ety0<#1p_vBdO`UB!JaP8{=BER@nNJ#NW)Fh$W2cx*`+u zUqr~78w-|;fp`UgxwjxkBVLCMuLl^i)Z4ff&rW5Ri1At@&&-t>b7PS%9}ka|?;*A= z=DE**0LA}rluyb1_$DK8R3s~X z!Y#u&-p~Ei^dsce2`h|oYcJ{cs=wtUu1<&CV&{^A(oj-F2Ot8t$ z_trLLpv1qHU1jN~Sb&>&~u;xU*o1b|5kK`#qK( zP5M}u8Wbz9rxeP9Wo;x57H+Oxv$o6Q>MGhVI^bt!@}F{g51n`vdKcvzy}}gRVs5ux zw}S;%g@i9lJ~)k>qCg)a&g(p&`~|s{!3}M1yET;wjonppQD44~XMPr4zZ%4Wq`XdA zHyV{)jOjewC@L~5l6$@ewL8sKf)}8b?RLRva>{jR^_+U8oZADAjN-kJlh~^Yp^r_w zvQ=~(uw6%dhN6AO!;2b1k~XLQ_2MX3V%{DkV3U3d>{)}0!id}r#U;;dIIUr zTn_7TXQTo>Tz*?)Zn5Q@cu9NT>*)n&dV1L};!*Qy&`GlF_x!nT>f9ph2WvcR#z6?e zzhhvB4?H~WTI;}%df|GP?8Pw43p2iue74dKll5128SOT_p>C1Ymo$d0m7fufCVk0x z+pKM(;@ua|Yp_=Knug{0hQ2XD>+L$l@fLthHk)%@WkjOvDOFBVUw)~cS&r$~)Y(@5 z_d9$4(qq$5_j40WZdN1W7s>d$Cm*-9#Q=T_@nj;_i1<`i@zW5*B=a|PA~k|7+JhAl zO07bG`35t`KY&n*+v`*^ghokln0F*(W?a!>V#ioA`ABPa`PuN3&jLMvnlUChJbi0bV3iL4I}uewb^Q%Z+Fy9!^X##L{zhr0Lf3({gtliz9INt&Xl9ud7U;>Y#BS{e6>^W5)>Hoh4$PIgJz$M8h+|R=;px_!Ga*_4R$KP77G?T~{;9H2Ij#Kh%*F1hg^XM`RMJ z5XILaEzNI-UgdZQ0PgRCuLeJ{Ubp=A?(ZD+&JNg5{5RZcOvL_mb64NV^*|xZ3hU`Qlcpc zlHwE=!|yyg3E`SXRi-`>v|Wx>KgtWM;W~YaVJl~5@Q*K3Ty}594&|}cR0Qej8LuF! z;f$d9F=E5|zXh)&mok6iXB5u;n)I1%QrIo^`e{<%LyFy=cP^2O28VX!UjKI;1w6!5 z-Gi=SBc5r7)ncy6sRi#k0COZPH~BBiEZJ^>n#V1c#fpFosm}8ENyM!)Ev~Wf`7_GG zw%??l;R?s#I*BIXt#G@pdal`2-3_7wj(z9OAGx}^@;s{ZM^+!Q5EB#L0TR+zrU@(! zeq3pT)OkdyBK>Zh{CM6_0AeTg+*K{U@97$)nz`G{ zBq?q?HDI2Z;}IWX)BS?8p=ao zK4WjSL3+v~aOfaRp~73Kqnv!DXtbG*OpMkfXo~|w1)#wAZgLGlAzB82ErgW85|p!# zDb+o2KItr3!!U4X&_F0cbg|)UZz}IKfVF^xobW%$W;gDsh{Zo_v6H@73_sxQhFoLt zGSKf4_q#PSp%-gUyd@U55={5=_ViHFo~(Ni&sATU|H|>7Q*H^@W){aOgssg9nb-%b z%{ioQlbJE1D{bD#5KVD4+=-aJ`sDtq`C)p1OcdQzINlRti`ma#_21QGl0IY>{Bf*s z3;zV`$F^lBY|!h;w7(5dPeBcIOWnXm3!F0aKs37H{?`+vW-G*BD# zEP=vJg1PAYq7JXr-YwK2G49%_*|OPYk9QaqT2<)mcb=}V^!pt3sA`uP^-!DRSHke> zT{p(6hu!t{_<4v5SO>p!@2j!h#ho3AE6hsdNw!4Oy)TTn9jtRJ*+>r2J{V+wG%#;! z_#BSGelOLfGP_#2qWdpyQ97)@0WZeF=Gp2R(XUl!dK&BYKl3;TaX=)ZA zUp48UKs|@w(`Pzp?*83CZ&97&X0ZSE$1wu-rL%DqU)1@*8!Vw}nDTDesz9TVaKs6V^mVGb4;#6bWIRERuovzr zdn0fB{v(gJaABgc7OWj{{8%?No6u<{UxAFDEap6#Q4nwE7iT94=^ZSRsg22W?+9?@ zHLq>)Noe9fi2t0o8Dhd*W|x1!6w_N*I@hH9qJ7Zz#J!D-g9bzm2U>PCq1Y?$bakap z0R9nCkRz?iglZ?xtqH9au{-UFlXSUgjhnP_6 za#UxIm5nwLGfj^Xo-=#E{DHH`MsT{r>$XSuq`zsG(cFp#yIx<$50&@_=nK25yKaa? zg}c#)AyLH-wu6e#l`9^y8G3ePOB9=1xomtw>cT>QKk>q@+Gw84!#qOv-?_5R_rlKt z2s3kK-PmOfP*LB+MG-_om7fMLk}%4D5?%u|{hGFSYG<)L>@yY*Cu{rRWvID*LS?Yv z=sf72IL^_!vOU!6_g=>t_RgliHf_YU%8B9#T|SRw%rH9^+eXWxiaL^Sh`^3~$n3UD z1o*R^AbkZWZF*_IPR{iC!#>C|s_uT=Ptg4#NT( zOClIO>Z2PB?uao4E@qP+i5}2?Uj7mz8PLeVl6=Uv6KGlv_fpKfimy-wXa6??*A!>Ww;)hYSL&xYj% z?~v3QE04OJ3&~J5+`L;>k1VHn_DIKr3zndj7+~298)?8aUKX4^LwG8;uV0jdFF^tE z;Y8icW$l3LtszxQX7FoW05z~eu3b@KVNI_{(0nVeL4~uY&*aSP@xO2`jX2N{e;^na z*z?ECKYKM*!64jH&NKJuS7lv09_60X;(9qW-oxzS|6w%ZRyMvSXBLj#k;ut`AnucL zkTvdvBZ@D_TRY`ymo`g%r~{i(NpOcfteT@j57BR?2?s&jX>;INlg|Qt7GcX^?>tex zDXK@j(J63s@2u&mpW2xws)mA2r#HkMx&$#O4@c7wjlASmF?XY*H*K*WqNjIeUYzzSo>4%xdd`OAFSnTM7WV`qa0?{Ts1IG!m)|mnYAB zx37KQex^h#YSN4;m41F9Ba*Ik4p@H05^{bsPMg`vB7eMB-0VZ_*Pt^4zPTMXy!*4g z&#r66lD(qr?4%l;?o~`O3cWA8CJmCFx2%vYh7Q%Kd;fSu>-Sr>~m z6>_*imf3D46ww_32V&HC*5ePkZi~{RbZqW#uWxS;tc$?)Y=HtQc66ukzE1d;!k&ym z?V0*45)G=ae`@Km>+Ju5HF}@82_6~WmWy3Jw?dkhZgw9^i%j_0VD~Hxe<}@BZbhQD zyX!G$mzx(P-3B^z6&PT!O7oOS5>9}k(&Vn_fPpC*PKBI*c{qn_zPPqke$=`+Nj`u@Ab*yqJk8jR`})j4ho{+Dy)~(&ieC-;9`;SWkWMB1o+u3;?4h3i~oQ! z6(2#JMG2FH;on_n-|;EY9Ygp3Ua})>C_Bl%44`E4j-jClj8nB-9`+Gp;Dq=?iD_-A|sm`m|bvJ{(M6Ri?? zUgZ>Ps>bDsETV(`0lf14#@j6_Xm9@JMyUWZDeOmz=Z?rV!!jlMOn0eUQD}DrK3`q^ z{S4uI&mJuYC~w0EK)1qg(mK{kSB@(38Ol!X#EJ3FU6^_QPC__zK^ z2@dN#R``#02KfGeQUcH@V&y^J^O`FBYAb&qs;wr;^q11&i3L5O)fcmCvOT|suQhKE z0E$>9f&mvfHXi^-Kdai$zI@1!rkR*YL;zYveSf(hv_&iiUC zbqY?cNGkNAFUVHAO>buc{T6ipUI3`kc1?vV&iV~KZc6J52#cD^+at8_x|4{rjYPiL)#6wE~d^Vj`MwwE)NV^_^;%e z9N@{*YZF-;>84)b>V;{wZ1oQ;QCycJ@e`Q1`n;~d-)M&+v6NniouLI^B=U{!E$BG{s*5tK^2mo&^xF2BMVG zc@#Vw>6!pf)n^CwkXXq&0p@V!FR7tjZP@!`=jSv*o992Cj#V&tq{L}aC2cd7b+~Ir zG>zrmjadwf)GR7#zo-p796Y*t)^2xzY{HtxF|eZfA$ z+f2vB8jZ2iTnlsT-Jw7ht4j10)aqZIU*Yo<%2C_XTqRxV3cIuH+n08-L75BqrF( zzU$sDR~jZMCBbnfjlmwDPmzsm4iIZZJXnu}KxVw?M-+3uP3@YHIsjTjh_XEy2bvU` zbv@^APh5x)p^Hc(Nv3ibU&%RxME=HL`?7n_O$0ixXgl6%J0 z8;8TV9HZ798kTlBD0gJ|7h$IRzuWuo7-e4RBrx-6M>4RXn5V28|8V@9#C8G8wh-la zA|Sn*aBLEq$daE~sYf*SS`@E-e>}EbF@#d+6^$PJ_#W|K-1AF7Xo_|-RmU$H6`5me zWQ_iJlm8jIi0+;GeAn9YyAEYsG7}}hd+rkiqUN6fuK(TE(*eEOv<FL&(&l*%OiFEt3nLLil+HO=)WbwxAf>#BadEQC3{NTQwzx+`Js+&`}%1j)Q2%I+KJ zGqQF4oYS0o+fZg^FLx#bqQ-)6aon7dqNjG5ca=CaLhzqjx29}oXv&ilO1 zc|M=#dET#AByHNgHHg8+12f^|<+TeFx=$eU(0i#l)RU_TPn|BDt^H>`pC<^%oNyJL zY#k}ni{Aidp&_<<7iE*YiZMxBM;x`aLg(&_k<$q>Q~99<=PSALCHa<@>gA$021{Cx zRWIc0NP@x^FU9Et!=HKySM9g;MrdGUoWUl%UGH9@_pgYGd75P& z43Q?1=&Bs`L%g!<_?MRlt-^QhxPJc2_nH2)$NxQZV5j7>#8bP^e))E`>}2~Dt8Z7{ z`*kzbwP>j_5?aazRv%2dLK!%n`nC(*fTW!ivtt=W!utP1(>e#_BEF@wPxJbs|+U z$|QS`XC`_dq%8m5abVl#`=vX`cJRw3mCUgD`R=xBUT75&)4DK0f~mJG*zYu!q7M4% z*tgA_;=9wvE)6dxWXmrMWBml%Y9xu@8?H;!N|%5uL$AoCwOs%$`Oq&aD#2A_d^eth zxLSJ93v)vOB~|Uqs5xDzMEVdtp-!A<-W}WI~@)y&+Nc=js@DHN=&p* z?L>IG`Mk9K8f{}kmXsJdoj#ySky`&)-Z8qr=yHO7Z{p{^hzY}6)NsQ^s9lj{EW*Fp zzf&z2ZHzfM=ukYiaC_0HBwE`X_R^8^-?rG~)1rNy!(Ml+e9k%PUFCs#Q{!64SSyPr z3+ykw{T))@@m6Mtj~TTW(#wT0n<@$2#zmeTu=o>P z>3aga*`)z!HX@L^O?~-$s`q#N3?$r;yKDYNps^U3b-Kg^Xh32Jy-ZD6Gw63-Ec08v zSQawcuJjJQio-k60`B)fJ?vC8yHhQuY5d6)W?MHiD5YAjf@D6|H>^9I8f;#eo0OBg zlDkZ3wkK#k^?6w$<&QX1rLwq(hYsewP@f8O95_L4J-xwhA2O~X$j<6PfvD;BiXw?D zeutP~o9HI)OUQ#Xh63y>>mTnrwsI}gpQ%3;;Wd%RP2MQEQe)^1DC zs19g?dflq5A`z4zwKJfBxJS|mU7Q`dRKDQqAZB<&X_>nsi&284esL}IDllUXJ?EeLw_|MWoxV!ZH zfx_jpguOaRBsU%jHflQ^n{H@E4VOAiBW*6T1|^S>m9^(m2V>G*%rqOCRXqvIaUrVu zZz{dW3xZk(X(_vn7#ionh1o^Q6V?ry~vM{EDmHCx@y%=Ed& zi(*E-UDjWTEa)%^yY)B`+*g(1+xT@Oo^V29#zH+V!LjcJ>q1Ay8;Bk@enR}nlR|y+ zW){0`yQ(KfgGe1*sk;@5QJDJZfQYN$FbjMj^s0+~yWB|z#0CXfQ3XZ$oS8qNmoaTr zqE&ZGY`hNjxQx|Z<#3`4`UnUT`{jE_iZT79{=^s9>(M~2l(_ zu{jG#b$uLpx&oU}dqjKuoK9LAYdUF^Rn_sJG7jYhTqx3b0TlR2In{_@j(^05jJCbG z+_Eft&6LfLm?K_60hw@xh(A%=toAZc5s(!dL4T=dS<>6$zO-b$C&|eDky56G=B< z*{KV`oOZln!k&L-Gsi129Z)S3*FGRYAA9E+9=5uBN%Rg#iCG1pnz+gK`r-J-dPrNs zMWnpdIQz^cbKNgKMnKJ_pN5@~?Qk*ISkc(ZpOR=@f=U4|$*Bo+NUZ6tINKIIk5)ay zV|36Or98=(J@4G$**|$V2D#jJkm@%(d^>V8vSSCdI_ayFQhk&ZEZ$Mh@4CHrjd z@pfNpp5~dc=jzOGAW_+cJxKS5!Nf!O|F=Z|-eov)x8jCd$P^ddo13KD-!<00kXC%2y2yK^}*YE{gC zFjoavH8D9lABZhd8C^$U!Y@VL0p_qfT9krw6jsaf=^zu@UV>}tdzd-UMAn?HhQ>V@ z*Jv6!G*)D~D;MAJ>#=gC$H;!2ry&l+p_fN` z11XQDpjPsc^0Q!JF=R6`cu z#o$IQFXvU!NcFdQ{S!a_95V`suj4m{)!}El5ayTzWktnJ3s<;DleWjYsWlbmz*2M9 zy){c;)x!31kIo{WOAXbZ<8$Z>yaFs|n040ELjN`Oxl{v^dA2BHvpHcc((jKoDw=`F z5v~)T4(s0>&kW-abr#>|-aLRW@7s_bgrJt#dN~dbq@dxa`7UKp3;i1mXa+mYf}hFu z>*ZD4CXYuU&#dP@PJ)|noN#o*eD!U%y=%sKz||E$2fVs_@$km2Rf$B%^XbQED^5Gt zVbtXkE(oEZa~>P=1vYQIDh*&Ft=S-kTx`eqIl{%Fin*sDeMs^gK4HyCEf3CFlh;Op zPrtQ1CM{XP7RBZp;1DDfbFNL93O0-?FfGUYJN>>@8efz&VPe84zs*3N$km_fM_x7- z`;0jFk+2)bI{U}(IP{iXEiI2{m@ebRYv1>=q}M4om35>;gHroi2fJHFRcblkcDNJ# zCDr>ZXwL$tQRCHKMc5vMV#O%M5&(qq6jGhFkA4WW>2kEpGS+$#(m$2i(NyI3)TWm8 z0r#ND3b(?=qkl8no;n z&ienX>P&G)Zk#28GRkENNX6asjtoVxf^3KKS@?0`TK#D8z!m20S?hlO(Ry?XbsCCR zMDrI!3-!0}{fOZ7*Go-p6*&K3wuWoiKT?)i#j)~?d&Sjiy?u2zhABP5;qHSPnp6{lO)Ji6-jv_LnRV=l;C3YniI zbLr>DFh$J@tRPg}`Lbm1Z$F8y6HIxV1>QTn*4(j8E^p2sVS7FZkCXZRyT7) z8*r7VxILP%5&)2WF)MBk=Hp*BUKi=jP#!D^ZH{d$X9%_{L1ed@smR#6Zh`el zwlo0z3*i&D;RaL?Oa2McZXAbm0MxEJbuEL?8~m1LCi}20pl`#No_|Mc>RtLFF;{Xr zMXOxnwE#td^JrCGAZ_Q`204S_{%D(>8IzcWPZlFIaas377SV;py0` zqUaovN59|G->S?^QDpzBH}K8vzGK-V!L%;HOgLqN&_(VK82E>jY?_V20N|2;U9gn6 zbdWeV-;%S$pzL`Z08`$~7d@S-Ghcg)51l5VYdGuCVRYIK0C{1Xs!JP1#}hXEGLFR+ zmf@OAm${)0?G4&qhuL!4y-7Tv6o-OzQQg9BonB)$wTnpp(M#*?znfn0>^s^~be*kh zT_&!JM=ncZOE)feY50^L85O-rcb^%(>+-hS_>A!~SM)eJxYc6UJOganj~-v4NvNrq zIV@aGgy>Y}jf=iD$=b&TzQ_^HoZuSwR4y?;ED}JMg`_LTU;#L$IB-r-D*yL%dbT^1>&!_;5|L%D;X`*h@?%;%TOjqJ4k-SRN6y&B zLAclIKrcn6OUtFGfep$URmMjo1OGW{;*c&x=_O5n%J17`2;z~n5Abzu{Cud>5j{q9 zy4nqn6|8<(&tvM|JJ;u!WF~Y>N!!tx<&B2zYftniF7Czmmb@U={%$F!2A@{bla)X2pxMMHRS}#oykjs!4mpVMXWdskr8|_n?6u;Ns-%W7Y(O| zPs_=l*|L5aUDn`~k)e@`e^6()_=&T;pJKSa2Nu$# zM}WPFRW$otA2DW+!ajJ?Wp5CX=(gckr$`(a5EYwfHY8nu&>406aq?xF4SfkwHp8I% zbF!(TO*-URH8yW!mwnvQL9?|EFKx2qVHG6MBHda-LW!Cqr)5Lo8dH{N;48i;wPR1j zgqj&cFNZTPcT`m*zMPj+bqrDUB_Ldk@v1FYoM8x&4F&6!N2d=Pgq&${3H6i*%0g(p z7`4(0jPu(`1h#j3{X_t-0~w?=N-b5fvRx8j;X$T|9O5KoAZ{jNfG{O3lL$NgfpsrH6o8bu%;tTD@b7|!CrQWr z&2=w#BK&-~6d8qQA!Tbig9@of*Df&AI_V6&vQ~DM6XBF%SEl{HfyN^5iCU718UK+6 zH~GJV9YqJRou};O9mc9|2QK@Ipl9>}l58;Vd&~$!pAtWZ?MJ0^oNM0@Ra9*5VS2yT zegIu_VQHn3G~NXHGsm)yka<~OI@(p4r_e7YEB|~TebBk2A0Os&N%i4m7=|+{rxhJ(NdXvB&9T>uNQPZvdqsWjJty61siq@Y_a>xs3M;8T z<$vkQFGwH#g9$N1S=nwbQ!RR{iw>dt0G77J{H(YR+@OIkKl`iiotCCa$Bej+O&`|E z3wR#lL%clJy#qKz3x2m&&Hcwb+Fr5S%*#6$?_A{wV>HsrsZ*~$FRJKI?YQpYU%5`X zm0vco?klV3yqF^6UWI;FHiD$Hosug)LjmToh2r}=6DW}{IEM6->4$(CUmnemnH2|M zcLUL_UZJ+RpP}_Mkw2Myn3eBJmuL|@;%v91LdDayTnKTvw0b)nHn^@x@bre9=2upQ zOd>mYf3|yC;&@+l|fwbkXenb(4z$u_;*TedPO{O;2%dxMrf?wBlfx@MQXl$#7x;$(8xi zcvflJKlrUnOWy)adsHI$TKq4sSn>%TO$KB2k9w|Bw@pkn zdJ5Bc3A3fa0}P!dwpFZVO37LY>YKh>BikszYJ9h7sdzkzr|cEL(KsgwZQSE2v|sh~ zejGhU`>SznTKy@^cGXM02!0L|^V%I1a$h>&JFkLOoH^KTa0F7H5y4U^6R)wTeG?~Q z7R*!dkDvFG7nRX3ac!z4o56}<1929s4q{LBl#FD5;}pqfWEqU0Av>NBN_0(I76i9b zKNZJ*2@nHxgx&v37$6W1;1`4ky5St-(0D>G>P6rSm)#i8`&%iKuz_tGvlszkO344~SkyB#Rcg=XGtmL=FiiT*oOgrQ%d9do@E0z-BTY%~iL+5Ey z%LN;$+$~Me`wOmPyI>ACC}(W(oFs?)rpwu0?oJ6(xV>r?(XNvlS5329P5*^ z3Ax;-(O~=$SKSmH)dkGe-6%jk`-31v6KqOrSDNCWZu;K>CCz%iKktqd>x6kT(cTf% z3O%1V;aFrlaS!C&a{BfIx_$|r%Jsgq4>vUcz44O*)lTf$xRa>Q z?65~^Lm;1_Y|n9(&q^XV6r9H(@z@ef*gG3e11#*4>Pz{~@zA1s+lGHohX+&v(P>8b zUPlGfbH<1zU$rtAc$}&o5eb7dd%h3v~jp)o#@~iaQTbOl(}vuXA5V(r5zAOLa3FGk~hWM6lMn1ad&Fp5y!>Ye}ydh zI)mwx-rLKQeF9CG6iXWv6h&{(;&CH>l#V-6nR-~yUAGpjG>tD>BmoVHKo`gw=^wiEafEz z-j>>|!97igCik;l9U}q_B94!_wLDmL@yj6=MKo_!7I$eT)5FQWAaFp0K>c999R1`^ z*C8cEP#16EI9;ITxQ;z-Ys=aW9Ay6hVPa_4Lfhox@}Zzeo~irUZSl` z@eY$;Djsfu)oABrbbQ4(M|ksZs6C99ew?DhU&%=)WIBj$*GNjV8vcfDDL2ei;1kOl zc~~ofcjurNTWyxLEDKbf29rLMry+!(>Cib7g}Y|cX&u`lMolnRQD?!&Nj<7_SGfBC zk$b9f?=hP3CzXyxL1qpg`n&8GTD5QC%{t*xgGCJcY|hy5o}3yq?mJOAif55k5~X7> zda+Q9a@7rBMp{z^g?Z?LM@D*6A!)CPRwAd7>6O(0fA;nc^wP>U2nLzTDzED8-*oiP zjZPuD!)gKhqupeB&_O-v!cvap-_vq0Z&VhPYWi$|;`Vw?yOKbsYBN)e=>O_ty50LA zvV9ixD3hJro2RFt>hgcu9qk}UkG@%vjn-7p=Bpu{H_z1~tqVhPM^MFWchnR?rGtPf_=ou?&#!80DeNrzVj%8~WQE25VGp3<|KHdGjH z$V_Fq0P_7W-Pk|_jbla@$#0_zezXrbwq-J^oFfXCjpw&H(`omok7)c5LuLAyPR9a> zZ!4UdABcdi2PAh#+tv~0fcNK}5t+p%r9N2S*sEcKk$E!qF`F2d)F(2=$8V1v!8B;@ zS=~K#N@2*WoHJFqQ$3FJObvHXzuCT#d8U@8zRR!Vc1iG=qnL3DC#$|+Kgmt&!6y~q zm8?FkNq~0RFgDO%2(B2M%O|r(vIBMkk8noxJBOB9o)omka;XtL^dw^%MJ4@WM!NjN1C@Cl zFmn9h_1T1xhc@Vyih^a2x^%#&(~Knk3io)We&xPg;K9lQLKcxYrHN*c%R6E3$F^}@ zsjPN*LM&DYsjuFce3R*KABKU3!gV2Uov(9(UiRAYWKxdQu7NjYL)Np4z8=MC-qXwA;SAX!C zW4Q$hjCU|2mJaIA8#2M%U-hzdo%fClMvY&&Z#W60M~xoNRLFko4p1W@${p4&?Q$Z_^R&;?^S<=?q*OvN7BsUXMQx#L}~f1z<|0|TimElCHBs~UdFoTGi`>=?LkC3-QzNGm^ zN+(Li5(aJR7h!s)bmq%lHJjAWD7P`055#3w@4inCycckm%iUo_%)+TnM|$IOP@$*O z!;nqebc<@yYz8pn8GvrpyHS&M#dLH2o-dBSr6{^U_Ri7H!!2abq|eaQ$-TPQb@2uw zWD#TFa)(Z%=k*zz_LxBpI~Z^>*tAWslR0KuVTRnPdNF3)_gu#0o zl5Xv{Pb`;JVhAb6*z=xuALX4RfU_rKWF}jAoI*QMFswUK9!Q|=u27&oC$Szh?zsZ) zAOd)J*b1hK{zJGv18x|m1;p@@Z9RFzuv$xj`<>|OsvW2|5K2$Y9-v5VXYQB={XLE9 zi=dou(O7Fr!uppB(?7Pdc)^}W{s#{C{qz6e@PhC*GtLfXd}jR+kmO}vKCuQGiH0L4bHqyAJ7vol9ApVpJt_K0o;gvfIC za6wbo5+b_FIZj`7RpanMd9zY1jYeio&^=e5mr~0idz>n=8Y7RbI~KA)$$QBkLhaeM zTOA0X3-2KuL;qo&W#RRhTP`Z(;I13YwGB~b-Dq9B4ON)u;h7%3aS+_BNH!0C(spou z8o2AKdlW)CkmIj2pL$47HGLvV+~k}Yi%J@!4~}Wy=J?zaPecME9arwi%%RT3LXsW1 zbtm|fl0)&ftdlp z_%U;h?SBYPTtl3j_#(rVnVq_25G(Z=-3Z$>$02llwM0}cEj=V=nhF*uR;ec;r)KudK=%emP>=~`MB-mk(fmh zL&R)$q3@;Q9yDy1$hq~y;s_+y!W9!mk04v;={_Cy{H_9O*m^8S;~giBH7$Baep0Dv zCtT6prJ_9-k7-~sT3a{w3vlmO0BsqG%uz%{(r{Lo!w&KTy`xzolY=5}&fn`5 zB#cgup*aW3@ayu&;9JCx2sQ|u9wYXNNKhgm#nbqI==N-nGeV2J+PD|=e`Vh~zr)4@ zYAodhP}}2iDKG7l?9;k53aPMczF+G`giBx2yj@1ZDja+FF8Z~P0S34)!fC~?`78Is zEaHEor){6xA|ZN}&G{RQ%lRHv=&u{61%GTmz{PfsdLSAXFPSjg%SMB*txswxg~N%0 zo4fRNF0a>+CgZe@A((UN%c&;X+yf%l7RG4u8?S15c)65buWu2Dq3d_srijp)vP$sb z0Ag4K3u^~GV7BHKNMf8%Z0jHj?x=|T1Xs7z+D|}NZM@)NZ~9)Bv2qxr$c0c!S_!9=MB~!(<4`O?eRys40Q>9BRnd*bg$E z4*HXSk1>|XAI}B3Pu!BHe-m`g74ibG5dMaIiwVGujK%CKf#V**``xVeyW&@Qe%qgQ zYbc{hzb|IFO;Tchx@&xaa(!qte~>6mtOEx3dD1yjY#br&9C` z6A?&wj{nVSr`W)+_)K^)A-nZ%53;o1t0A6QB98hEawCT=-GQBySc*7+Es3U)Cw1-r zJ}ZcpaY2lE1+abZ#*6wz>i|=%D~kv~G(dfCbEdfUqm12?BF}IsvW@v-L}q);DC2@g zxerf7AeNx|NgCnBp-f;HGW`QTrw z^9KxI@uW3YX7E*J#OQThMfrH3S#eKvSpp9g_`oP5ppomre?8(f$B?o4OYg8BmU8*H zbfarT@Nroz<0LJjUpwXlSjZIq>mi0?UnPdUq%|GD0E-be`!&k@>SiCKePTz&hzSP5 zb(%K1?@r|yxeYq-$)l)&*EXn%y@o9BeDt4Mdy*6wV3ftr;ZcxB(qlV`tC_T*Ek^+F#q7LV zTOlFB#FENprpvo+sOiB!rZ?Tze9%@0Ip?$z$~#=r&-il!d1%_3rLgwI<87}DsM~tnFekt{8@W-6{#N7%#oV; z=kml}h?!6oqq_iM;Z!3I#D=U!@84keWHLyA%UoGt@_*TxEX*BjC|S%#tMNA+CdCW7A0 z{HCnffQD)=gscQ;U>X4VQ@@#<|I<<^1+OntU9XY(Bwln@ltp`Pp+%Xo_car`m4J#l zLePHcQR12?wDH1zY$EuK_}CoAxhgw>KTfP$D_Hr%w~7Yq_ghUX>;kMw^YATsr`37i zbn;f>rEj4mE~LdCIO$B$@S1Ln3(0T1>7=8}U(5#hY{9yi0Iv0NbE@MOt7&q4H%(c>B`t-3e?Fs@2!1>RLd_D@^u5_%u$3_H%y1~ML$`*>*t)~&jIiOz- z%tA(>H#Jt7NW+1NC^rRqVz)>^V$NBDHo#fOd1QuYeKPkbUE5JRF!9LbKWUdIgfDfM zyY=9!ch_$3j6f9UY>+9d4c1fJ!2tAT&VmA%YHWE87)H}xU`9VFdyH`i{9AP@LH`gW z62yJ5kLY~je*s_J$%NGU3voimbQWfIHaXJ6Cew+{`%*(_aGFomO_Vazod3)pV)PWg zUpK)9+GQ%IRzgxIhxT};URKdH)Ab@}_=TP+jOqwmfS;3Gc6L58raY1*5|h+tp3s}; zt1q1ay_)`FaAUp7&vRvvd(& ziZiXGc#5hivQ(+;jigHzx}!cce@Db`M(ZjcQ7&PUK6Dc`qUStr74;>Ep0_R*NwP-AFwRF!+Z^Sm!r(op+K2fKpIWF!-d=pRjJhU+0WLsaJQ*pE)x9(n=PPCg3U^RBXe!`!(eq) z6$PMbexirN&|huOC1!t;qB>_g1sR3%1|@@lv#sw1zh^P%7O%cH&nDFjgo2CdDB^L>QZN?CiyD>Sn6~;s-d%5n;OJz=b^lOgGuJYN9Cs0w_)y>cVW;PaEFrtKU zDqZZK2$Z#Pyzs$>0%FES=-9AQ_q9q>T_wGQtRMWJ6@6r0j>y_x9@If&)g=`MbT{!P z;7_YH%HOZ8eZiDrB4^2yU-6w!1#^p!Rbvyo3aTW}$wE-r0E3vtQ)vJpSr=z*lS8qj zfa{_cCX3XgM9ejV{!Ch=wpoM>=(ch7k7U@FkF#mN)NP!mUU2;CYs974uU@}c z9~MnB$IU`NOYg=7pZTIT|KttigOtR&ba^t%#V;^j2GMEahKX7}S4svZ?!n8JW8j8N zb*fLh-`&{1zJJtCfFP+=L-F%RU|Kbt;+Fj$x)~uKSUUhQ=7)@z4@Iw18+MOymwDEK zjE-3ubF@Z9mVyWCHMVH9W)gT)OR3f;5no3+4p7;@sy!#tbwYnoy@rMYm}Qs{D)=Mq zilF$qHNd;Fl|bi(DUAlA2-I7Dg*4Oms!^Q=ckD5TbvJ8SC){l~zBGIVeoApDORL)~AsM1w;~Q#sFuw1LStJW6!P zYg$~V;vRM-ssiRpPw|XgjkY7omQWjDX+eK|y@Fj@AbH?f#ca$z5y#Bu%p7p1NTNdx zBILGu@W*AtYqc`JVS0@b0XsG!%m{9D@Mp2{)!hQsoM!SE-Y0idZ<*U~9kJ45-cmk8 z1r5LlRF5HMwm|4N;Q{O$5CxR)drMHS6S1kMDkxqCHg{6vC7wLepP$5~X!Q=M<@d#o zd6fBmqqx+4w=5tN-LhGeWU&GAY{O@sFuxv4y-Y1PAZe6gCA-g7bPTbFyREDL+pM?u z!UubbL||0kr_EQKcM|fPJtL<{zdgOPGFy|eKB=uaxX}ERAoh{InzQK$i`7^S>Vp>B zf&G;80B-A3spkHqR$$|m6~?veyYizHn6>!>A`BtrkP$zMe1;VvfE>p1PmGmM>|TCW zdzGqH6l?rblc8a$e_(L_d+4qO%hb#&_kYNXe{XGGACB@!->Y%>o*UOZ74U^h1!(%- z(B=xTR(z(~VQFA?%CW+2CeIqV7i~-5!#T0__+Ska&(@#9IR9;S5)%~vgO3s?W(%U= z%&9#{DwGFxtv`_lAp38jHWGF^2I-bj5$!f%!0aq@`&4kb)7W=1z398HhO5@+l^;sKE)cIje_LXnf29{9wuOXk8!qPudsu&dC;9({Y7eF=8@ zk@V5w|gIk0<9EiCyr#63cT~H0}EDGyeY_(5a;cnlQO%~V-A0LT1`gF{>=54$v zOByUVz)#}z)WJCePJIbWp*hG}=3Up!Ar*s9!|L^X!=0q{7ez_-=*E3ncjNq{H&F_L zmv_;C7A~NERfrTM7=|9V6#dZ;niK(9o<#o-|DV~$*wLs zWvt`+XGGmkl7=y^h*izapR)fv%)c!6O3Jj}9H4lON7IJZuof_>dy;+#x#KpWfd%#rmtTU+nPSBl0 zY!7tqNmzr(y#Y-{D1zJxmpm)11y4M?3pBwhDwoeuYsOAN^?&GUqe>EooEtz5SM%X~ ze*w48?G{wJvdtgi0+<)ETmwQ%BAjZ40|csP;Fak!mt+}1r5@;mKOD~rHRFEO8R{BG zd?(9@Kjnq-b}7ap@r*>#0dQl^<_u)UX26LupMXoizU-cX8T0J>3&7V1GE~W4p^ZBB zx)kj1S5}?Tc-=k12g<>PeVCh?LSARG9l!Ycu9mdPO6cPV|KqY=_hP~TYc|QQP7sQ} zB=OB`og`?3W-Cs#w7k^I9bSCz*mpv{*L?AgAL`wP5gvokgq^I-l;NCUMy3~XUsF9Q zk^+1RXEZCj#jsyC+uxV4MBeLKQ#&SjQS3vacJe#Oob15wn(>Wj8;@9ug)i+f4bh{z z$}6s~sK@%hrCcpuqezTlDDbV4>$yPf-)v@tm-MysA=;OQYtT_OK)oeU?m=hRL+(&tM2a1KTw0JSSCajZ5i5eVtV69J=01; zqR}aFPtsFvf+J<#P-w`#Q9_q1Zz3&x>&8i<5>mgcj{h%UP!)7ALpJ;z zO22Y$q%E6=_)>ek?E#=mI1T%shO-f`|66Rc^A}gl&jvF;wGO;5U|swzaLgPdCJVhI z@u38LB{W6V>s-H!CgjR`(_8qQ5VJOJ+alI~Vft3IA#LxR?yjkf?ybT-{~YtL02qOK zu1!%%ea<0LEnHWdvBR7DXsDYSQBC1+R1a>7fA3#f{huUNqZz0Hv}MrMMby6G$NBZa z(jAc~;~;NNRLdRi%++r(j>->b1fcJR#IoIWsA>(Ji%0C`577Xf?3&!O)w!D!@4R*J@fu(tC6tq(ke5D%3EQoZUM0fa&d>r&W4g_05_TxY}93fCcqlHC<*5 zFnV8JcL%N`DbNJK7R`HnTI?C}Pw942Jv?$>l+2dyqWh9FX)^;U!&Y{fE;6R{38cW&zx&++M1yFJ zQkTni!*=R0BfaMw9)>cFT^6KgwhONS#ZVh(7$|7qmU$hNMh#+ZVepN)Xyz}791d7U3fAvG)&u3QR!{LJK^qAwY z9MoTOIVE*ar*4ey#Zyc8x}hcjy<8BZlB#RY+Lrzn>T7;#DU_MVO0B@e8{rckp+l52 z+#`Q(m2<$d!zj-q5lV4K90x-$D)l@Ls~6KRb2<)S^3Zq*W1Mx43RVPW%P$?bFKfU^ zOky9cVG|yW!~qVzZ&1~mRV)qc=sp(B`Lccf2DO2Tk7}EWWDMK#oYFNufUZ}Pg8pF4 zl&V&poydcu8aL8=;+)cAAu495{``z*$d_Xk;y56|#$9%y7J^t(+E_DD@;)8X(wbI< zVpj!pDFMOD3^tQlXtU`6|0IC2WsjsQ>IJ?TjO?yGsLz$*f|xm5KDuxn(J?~RWYsgH zx=j2AXr6x*FwjKt-vPhc9Xf9a7*)Cvy&=_ezthvKp`zP|*O4m>z0acg)PsX@YWPpP zX&b;gL>GJ7ViD$_ehU9TSj{|vy@KkASUXjF#z%xx^K!IsFmoU77pT|3qH7FNPXPg{ z=@l5&AY=#hLjG}q7)=agp$j1uKC06G07p$kkpMwi98`AdBPr|J3ZLNMuwRH;( z*E?`8_h;#}cW;KOLIK{c+IQmE*ckP(46$Zozp2V=g-fWFxOtKH0`Yim$!fL92lu7d!1A`-Gd{>oKniVCAQ3gc@X zoMZy+>zwMOsWOj>e5ikbL7nlszyYQ$a=mQE)A8A;2a5eI4NSZ(O_mRano5!}CUU~& zzy)ar2^k@2Iy3*PDV z2DGj)6)cy;FA&<>URw+-ozSy686NnRR98)61j*^Ta&P=M(WieG)zp6sE_`mwBA#!G zizvXK8atIXwn1>qL;Fq33`W;;Z3GWrlNMRek)Lz*0hNJ8H0CD4HqX%E;m|c3d9S^~ z1y<6JcFE5Ex;m4ZgAy?cYj9wz#9a0`fGfv#qI8Q2H&ViC!u%(CZhIU@*LASZ3X#P9 zrlp%Z4kN4`zHKsdPj-;M5ixx=8tr}=-i^`=`Q+P4;Dg+zZ+Q}8D{kX0=gqdusFNZw8gs6uI>5nUP>(>LiaxAp}S9~aj+V61h zNNWrC?Ev{cos~FiD@q(2=il30Dmj!toGAU;4t<;LrH*~?sSof(h}_M}l^3t3RpRE- zQlpH7;$btOCl7RQ=wd~WUg1CEV_MV-%;8LxI`wf9T$|*CIVfKM8yhnDA%9mlcH?l* z;YGvLwvcTrkvSmk1kc}6qb8aI2=yWhp)9Po@19;*rOR)xKUIp$<1^(WI(MF72mZ_F z{=Ln$^?Ap-trYi9+e}AE8>J07mMexm(YV$Ww9sj>1Nqw z-XU`~#NRl;NH>YUd))`JoIJ~Cahn7MPP>5f-+_G-m(0|ugb@}@m>_wPE%VT->~}_@ zO35wlWVt*+=l#)hRFxS~I9wOqSA8RD^K|{R*1E|%0w8AcUUD>1^dNC&tfI){|=lC!wxVlf8yf3+Qr_RbXp_ ze?%Y)L~0581_sPt1af3N&OvB=;?9( zVf|2B;i3I`SSvDHd6{zGnk`D%z0ejkILz7W=}BWHqLJZJ&|tg8{9xgY5!2X50gH|P z6id+^!U6EWHh%b0wv8C!nqrHFrDjgF*Yvn(Ji*{o7QBR%#uLA&ng~wtJOtW<^FL0i z^8t*1!N?jnc~c2#eO1`ekEWP|1<(wPdS%*xi)b)qP*vpp!&z}y(Anv4yhxbjV@R+) zV7Yu>5lezAHkhMn?31{Hm($D2(HNI4M}50IICM|=Kfv?$O2kZ>a^HzhBZiwhsJwO} zV5xFOuYg%%K;%xrP7zK5{E)d?m_347Vb|pb-14^1DBbYW{ZY3e_i}@&G=^}hbw0{<+@rydIo8bg0MK6jgYN((d~LJ4m%3se+|AmTf9e>Nx#E}rSX-#C z)i!PgT113FV@j)xySGO#U8>(Cthxi>_D<~^c%N%nYgYT(;$9Dp&v(bWk`E+*$9T8p zvqT)bc{d8y=Q(9p%Z0T{xAJlrC9SsP)ZoJTSwxpTrlMt`Z7#vIqm(b<(vko?)xK>! zNdT!#1^clID(QPB5L1+CngSK#!|+fw>qg$<+N~Mc4m%Z_V2&c%FIjTv;?UCJnd&$y z4!}^YlM&3meJqnA;~x`^*wEL&5+g8|4`=O%w$Y+!Q?Hz&z!PfQV{LgpqV@$5Ct7|K zZWbu#%S>7r_BaEB_kDJ)drbx%j%8m_plVGm9J6zQKIia>1yX1pb0lkOjb@n1aK*9Co-7c7q%|5Yd+VRaVqXt`jQ1fD8XKl#CR?-ha2BMF%5B?;9aBA8?|HD%EcjgjFP({I2Y7$oSPkQ;o ztCw@8#0JxFPnMFheYUS>lvz;~8-l#5H0>T`d&eh3)_-aWDRJS>moFWO731s*ZXJm0 zVE~)S|4~C9X0=i?@XbWnW+{cxF6fm>BG~YhnIPyup!Sv8-`MZit>6T{#~uVXg8HqC zERhklJVg7KA@?AEBL#X}X!JPpjNntsj8XQTiS$1D&SbF=@_uh_(`SLQidj7MIVA=5 z>@Dkb9^B_6r2@pk)DoRL+mve%KEFT`?y^0)SGOeJ0|8x}=x1IWlo8ideL*Z{`~M^j zemFl0u;R7@P67I-Tmm0pH{4`KfZ z5D9VYQ%`BcE_jjzkRf+O2f+zH+xL15f6!G#Q^3}>yzd9t#X^}ejW^gxI|)deUJclc ziQ~rv$9D_k$ZiC!biW%u5O?0p!F(9=tzB7<@L|bs0hx^KNHaPA3kPhGBu2>0>eTkL zO>mC_QbPI`1@;o79-8R5XiM0+&qcnI#@Zh*I94nMoo3&RDDHce+qe@Dr}9 z-a6?~SUh%TtXa8s7%+*#$g6)sjj(kreX-SPu%)CFjKrYTiE=Srrnr@y#pqFRY?c+Qv*1tQd*Pmqh0kUu| zUL6C}n0{`=3QqyhYJ1uoo$m3)=MUqj(`)6R&;r!i^mjJvbE*Ff#(|xDZr13(-wolc z@2A1Ng#a#fwn-2QuHef8_=(L)h? zwwTklRB(nLV)k!v%V1`wZVOh_CS0V7p(}93HrV9O)h+b6t{Te? zd@kIxnA#jMo3;aRjb%bc)^TS~PWUY2J+T@H33_Rd{=xYp8a~rXinGRXE1y9Auoo+l z@EtW4A>Q?oLrv|OLOblvyHU04H_DxU5LQ17>w8)W3Kgue6kzN9$yZiJ)hIEF*zjKG z!|*r9NjTsHlmfG)MhRJhz7@KJC$8%MsCw_XB-gkP_;ebcvZS&yb5O_1%#zBz;B?H) zOvy|w7nPMOMROtwr_9VuEk~BAlnb|&dveTGn&93-YKo|ch{%Tbrt>_{`@aA8DT3?1 z?%#L*+N$zGOrC6AORR9L2U)Rm29O$w>zA9fyTs7uv&qA!gRr>OZ6$-bVRD;RERqrCKcwHtHMAx8=Vp;P)p^0hQaE;)t|kbrdgB|cjm4Sf zX=cRa^2M7f%rLCW*wVP9(i)sCthcT$XeNi)3u%iHKKk#!zYD#A@L_pI;vi{y3vk?*LcW&W6;csXpdH{6bzj< z`E)C`so&7I2#mR|ZcTu!MF%}sZz2pYUZA>ehi$={NjCig?>gSu!8N=J!uo0&G*6tz zat8!F?7G=!+3+MW@GTutSrG2eOw*PT-?%R@J!nU6kGJ|T+!ACHyD0D)s>J<7##XAv zh3pGiGBtw#PHp)E;EbirHf%R^?E@?Ry;*Na(gx-G>(D#JH3+}Ffw#n=fBg29{~?`L z7Q|{(kPSJT5hGn_`2E-M3b#AUD?t_k4HGO1r36=tf^;zc}lxw3-`>li}BS%YQRrZ{PyKbZ_>I zV!C(h>1N)Kj_8fWdoDj$0q4?gv8kf~;+7RMlj?##Z}e(vy;}dP{SbZ0FMztY^-y9g z!I8DOR6QwxqfySriLQnxLvw*Q(Y!|em&Lu4+?H#_IK-Ts6lSYu)jOlkCw+Rl+KBzU zL;dC%bChq2;Hl*o%1^Q}Jj9Z;+Rk=eX0!q&un6nnI4v-6bIS_?zA4XrV8T{VHuuw) zJb+85>49%5WlNq3UGquP<>e|quxIQfV^@)BT}QQAxVG7y?k2_AAj+8Wr~8SgL3)y0 zvEI#)E^szp7W`>$`W>a4QGlrx9}flJy5&pP@1%zQq0VRf(cRyMD@4l^&`}+GraM_m zhRsS#G^o$R?B+1_drGwCY}oy@t{zRWkH`iX))#hXjvY1rQ21%ITAy5F#@`KYlTm3* zpV(iXO-J}(4ZLbEiSA}SDBR$0B_u=72Z>+O75d|Y&gf1GPL+qg7oKoV3)Fd3iu^GAO7g}cM0+J=i87WGg!?n2dHH>* zLQup&`%nnO+vH-gQY};WeSd^Nkh|8Skqe1sqR%2J5kH`BBZTqG+z zjuDUiIN&y`w|NSquzCb`L?pEfVr)VNCdf-H&b8vG(DlM^-W(RC0hQ}()AJ5f{<+&1 zHRwl}*X@^?*g6{r(DhI5ftDui)c?B35BgK2I8L z>^}l^x{Ogy{c7AkuFt@hOMx$(T}b$dy-iln+QdCFzBN+=YqNnIHZ&^_@u*1*TPO1z z)PZ7cMi?Hlq&%I$>5!I( zos0EO*j$8ntW_*bF3pOI0SC3#J4@lLyJ)J1s8U#+0%Ez zoC{FBXT5NU@C!p}20}-8X|n4NGwwc^hTGPLb0^5*R$2B~^SFscG;5{}vv-n;8r!%=y)*pC7y#4PDq1)c6 zQfb5mH)}@D^lf!7HhZH+xlPlqk6&l<oK6RM!M_khsUOpC&aQ~)ZegcgxoZb z>s2^oP*ypv+irsVd3^0ky4%$4a&a$uP|NP~=b3UDdbT)QY~Ju*y-GItH*CImjT2E8 znO!hb?v1=L@2jsmpYg0zu1`kYRZ@Mkkh{P6;lSU{s`np~n$95*skklnNCfT<+qo7I z{&bhDl|>Pp^?N&geI}VW2x(K_qVg3k4b|~G9Rn|se)OC>lqiN59wITRsmGl}vsl%j z*~n>R=OFmsjgM25zx~y>=yz_Zak{ke>W8v41_Zj?=#j~TIYckUCyQX}2 z>Qcb`({aTP8aT>{ z%-K1g7(hqGk^?;|+yd$#xz=!1X2F8-E~6_k`$WHyPGK+W$sC;iw~8m`2~SIFS1_8nl%|VA1wSl~yseN%YDbyTi-D4=Edz1eDM;_vH-+!5RCvCV%*ye!<SBDEGuF3EquDKh(;OUVg^tv_=}{knol%Um2~X>-U1b!M@kqis@`P%$ z>lM^h6MQYJ{FQHT9^W>WlPa+wG%_%b3vxUhE~hZA*r&!YL-keJGs%^+c$U~Ut~6`9 zij#|+oU>x?Wa*zdNw}RFM*`q+w%oKVvE0tl_anD&o|Fj%NKDI^_mddfOybE;4#L0` zL-%sG+TK!@-{d0S<26JTaLev~fC_C01B2hBKUC4HLsmuXVD|0>(Mp0SVY zIx%PXZ;Wt@U@L&90C8TwiJpggJ%6tspqf>_;s9?{B5H0fr&^NT;5TfdQiCW9^EkBZ z>ernNK2R)qd_;SS^AmX$CR|GG8-~n;<*+IO+=F4s{Am8Gu;ZA3Qc|lR%itD0%zTYe zIg)$TYR>mO3+6)B6P7f9l5MhVM-FM9c3W*Xq;_U{csGAAu%xfaa(X5ICcR!FIW>N? zpNrq{){~fM%<+fN6Xocv+N@h7e_Muc z`3f6dq1|9I-+f<;DYB_s5H{8#Kup>7rIe*N$e_YbHst)n}`-K-=b_g&qG@k4RR zlL!Zc^OTZS-^gF`3SXNG17xmxEZy{s&nsVx-n-2~t8mq!2&D(h<&lCPSri@BrWKKn z91RK?0yU$osRiGaIg;j|#PTOroapU97s7w{+$68bx|))6&PpdixTxR2K9h-j6sR(Y z*hc|wAfU=Y`sNtm{b@v+#X5!6baabP`MHsAc;|>7oU1a;TT4csAa{VP58Z*eM?Pyk zSThg{H?kx2HvUBo`2##5OD*@ueBjM|Jx^ETw3=WILA@TnmkX-WZ)B&eM%~{Z4Gxh6#tuCK-qn)12Dp=JlxND??5)Yk z%mbapdYyA%7-bhB_Uke6 z#{K=Fysl3${KVS(oAE<@Rp8T1BBDjtekR+fB&D)kRU=qeXvvk{`8)-NTC3=C{}HV| z3s$n@o$f2eaS|t6x_+|jBE%aKZ+8d*82Q+Hz#Ycznlp*?t=RW0r65(cw*eJ1(P<1* zw#DFS&iM&gkj)Dq%U!sXwb|S6Md!`QyF+bi8<(lIyJLjO!sp9hPhD7MRWqvmoN^#y=y%t5y(wMvoT< zgnzU4Oj}qz^ifSF_LhbKHe5v_K=d0v{%Ff$zShs2 zzz2#4$?yAC><&O8>R$}!)<3s&M->?3EoVaL}tj zn*7hjT*2_Ki9E+c-+I&EJis-GJb+8~I`Kd7y zUFILx{`hr#z~x!ZCX+(wOlufE%v@LqbUp+@cadfzD=c|7H$48~ckVk`D)=KPA+F2p zUuHUFkh|+5rPOC~#eL2h(7*kG*k^gKR))6JrWl^&T7DT(<9BdmY%UEZjOgun#M&f^aGS9e|mdXLFsFmp9i)$kXOE<=a_@ z$IP?*{T{90(ZGZA3Azsa{&PouA{TJ~;>MMl$TxU)qYqzg-2TFh)5Se8=U7*Zv%Y(m z2-OS4^IkkFyi3%wZuk$mG}8WuB&+8VXld9q@ZC-(gC$;?__~`C zQ8hc_>?!_7XZ$eN-JwW?X}cYHTv#A-o1(5=Q2$mvRqC} z3kNM@ety`{Jk`uw$!!3y*=YaLQn^oHubuoR*RjjKQQPy^VXTFus=CWru%&dO3cj_C|ui)~BNsi(QhT=7fkK`Ks77!J7r{N#C|BtpC#byy-fejg0Hl~Ntvhny3<6ElKKi}`@b zHTa7wCTFKxG@e2YlDT)x>2U(Y>m;aH#Wh1tmsn&%X7Vr5?3T@F2i9+DPBlJ6*0IN0 z(-KD+v)=K#m;%h;%#vkMnn&8q8;%V|0oEYOWsQnU&2%AKJhDsxKO01W^U^hJ-2CpZx@rakvKF zLRKTG-f{T@BmWc3Z5|` z%KiiX4Gs!AK6S@aAyrN8yFdqFCsuBBbz#}>7BeIWi-F0;;dZ2_pk1f5Ea09|SpZA< z=foTA?+KyswA2HXa@$J*hDC_AXLQFd`Mv*c&p~V(r=VCx4Ut_u*U&Li-}m2v`6N_e zqfZHyjArWp){twq{w1xybDx%4)@}B%^JysH5|m2k+=5A+ZrJ!xKaC|kLo-9k4JCdV zr~tYT1_=AHQ5vDN%VIe9+jFS=X`DZxgHU(O<$Aar>Ap6tPdJsC`~YGol7@uj@G6wQ72gcBNb%u8%bH7 zoaO_8CD1;V?w_#y8)X{(niN7kNZ!LIm$_id`pAO!o?dahUng>nSW}}?yY=B!IJ1A% zp#@4WWDi-i$uK2fvm;;M9doNmSTyEdEgCx3Io-37E_Agu+Cq5Y&l%Ag#Cc4lEoWs% zoEWXS%Cj)x)ehgA)}Nhh-1zZ9M<6)3_%5!zHh3~g?u(_vz5|%vAmYwAaH{gs8u4~} zm7H3{jN)IvCNO->%Dhu`WXr~WEl9?sjZpMZ;7T?K$`}YtM>9@V%L-%oY0}wMYj6|y zFlO96J?)EzVi2weTlI)|K5Pk&RgZ)g7Dec2oV8xsiJi>=`%1!nL#=8GX3TkTu3Ns@ zA}66PT3+aSteSx5Z*RN(eBudMzek@m&P=b|3nnl+*U;$}(qMqf4Ar|KfOEka$na~+ zIZ0Ejg}=sCfHzLU0X{UvD9IaJb6p94*SV!br@pF3KDNbb*u)@Q{V51jl#574e37q4 zobO=Gg}xPoi9{1O{9>f!-R`8M{u9P0@18KXd|3VAyUzQ+AEaJA`s$|dzH_7_t$L)u zdm+`Rtj-q`5z2P=c1(v3SMgaKaibemFoK~64+l<-L{4#>mdHNkR1=8^%WOhs*t;Bd zdm>*M=5PP_Tk+NnPSvDrqRVdLhCWt**%z=hpd46 z*x}b>#*9|T#S88YS$>h!JsEFOh^$I>U5g8Pb~pj}mbR;F1qEdT+dg9abTG9Ql=@tO zb}F>RFoS0Bo-va2EW*`hVQyJD#-KBSzANM|A@u?^r#+c zE03q!+!$$`3S*|LUk4lE(B2@uQ~_+-PW2jjFZdAT37r2j>+XoxnLksq1j~%=okPx} z!Yko7maq}r(T6z*7c>nukQl^TB*UCU^JSE~Wkj=bS%3@xEpB6(?VNqa-HoZ71`S09 zY<%y0fg?Yah!Zc*?(J`B;u9|qtYD3<7;Q;R%gh&a-JE~tGb(;2+*K5sp0g3vkXR(5 zk9BD-GDyoMktWm!G|PN!2D{$BkqqCd!?6|Lj2Xn-tF4mdLRViLN!XV*xb{McUBhzj z2;HWXwKDJ;yMC?W$UJ#W&x}+Uz=+XZ`3iZi&@O!%ek#!Ziui+4D*QaJAt~Ik!D~i? zj3IN75|m-MXWZJ?Zl`MjK`d@aGc^5vZcx|IwE$2e=Ha=Ph2iinWPb&aqyHe*0Sz=- zb1~n9rtwV+O%9^(x|De;?)E?~7(?hAJrTYnNLcKT*X&8y-R^*4?m-Q?k2 zfxuj$fz9@C!0GV~Zu^>&jAbSEm}r_KLx;|MW^ug+)zsik{xh>M(|=N(FvMyQTsY#a zk34jXvq^exQwfzLt2>*Ea~nC6X;m1D9I(@a@hKBU`|{d>z!gg!&RvC|XNXMPU4LQc zVk{!!D5|ODNW)io;h#`994fvYHlY_!T4;Bqi?{WldnvqyFFSdW8&H~Z!l)X|Gb=Yj z7MUq*S>3LB`lPAIjC6@q5RNRh@S{5pslLd{V;%QY2uqUN2ZTH7&qJRCE)sPys40C< z=tIe58I`_Df#||{R-{5xr#@s^AJFX$4NK*pgtb;q&;!l$G&btwmXio6G1KEZ9_`pg zd!><7Q@&D`R6dIQoBg!Guk9p_`R)2#s=y501MXX)SC{!Xn+G>e%sD;a+e&WTObec8 z1jLzF`)TQ2;K`2^1ddh;syr4^5boFExx#k5Np9mYsE*qoU{N&x`La>*f${p)%tu|V zKdw%oE-H9T>Xmx*O^oO;qWyA1`cH=~{Ih6@C*7QGb3ZVO25#_NrFiKL9q0+vJtxt?$+QY#~cgp zgO&lgwfNWg5m9Kn;aB!su0@PiX)@GbE=HIgW-D#KwZy!V5@vu+FH`V*{4T{W==nCz zK>d8miT6ULY@>firJ!di>#`0O?BrX@KaWk1@gg4=h6S*YFEW1=GWK_#p(%{zvE!DL z08S!P@Fzebi!|UT%D*CJVyP{+Tz12qz+R?1?qf@X&)yKnmd2CSypScSU@}?bt&3HEm9-^!k`JS?4;T^THGI}E2(L$4GDZ0ocRa}WfDY3(7Nz1DaMI};`To%F+L6Ektqy01BQ#I)BC z_mar@g0lJ!eg+w1|D(>c0<@7Yc&e-sN%_IM$no!H)1B>=kXbEMP)#gsh&PCv_eduJ zpWSGnRt=g0dIA?`XRV6liehr2Ga;Unde~5WY?R%-`o&J~OAVVlDKn%v|frN^}& zHcV+~c|ahDxUulTY8ypFYd!tcgKIlc_gO~x4KYJ=DLyJDhan4F;yw696$@y$pK02@ z@4_x(@1MHs-`G=3=ap_Ud>}xariZ^2Ebd^1N)ZiK>fCJ(%y|~ZcX#r=q9a_9{Ll|% zPfXgPN9mu$PeV=4dW4EpgvX$jl8YfgGW-cKW`LuZV}F{Ygq>8E3^vNYroY$B%*hw8 z3^#oVXif+w9z8f<9gxo|lRkj4N6Mdp=Cr4i34oj(yrEicq!2520^1Q(J^MRRl;r1! zt9gJ?B@@mEpiy6x1CRakk%oN`0{lFjTE5!oQU)*ab1yE`+C@;()jZqoYJ}fsD^XO^ zAs7-1O8W_@eTvFP@V~i1)%6PA~-;;51v% z^VP0CVUks>2=_~!93Kgiaj`|GTqnHn0ujWPvqXtr!`i6ITHJig0*7!N$$Q7i)HWET z7!qh6tWZwQQ>VlzJe|`Jbxxa|FUtb?KbG<7!*Kcc zsUvX>cU z{nQbN^W8Gchw2d1gXAlM8|3FPr^KQd`w^gX0N`ybWdJf_I<`|6i88x*2@WBs;HEXp z>1V`YG>cOM?2R+U+5jW+%zYuE(BNt64$bD<>F1wA0Af)8!`H4S`?8pPP!&Xp63D5o z18I`_FqVULf`C>EvQP6{rSZK9T4ec%z>PlfRMFyOvrQ+k<&Lo0@z2q~c>NSp9)aJG z2^%fIxCZV}KPa&H%oiLh&Dx5SPY_U-<-Os@pmVVx;90&TBYhp#zj9T#t}?xdyCoF$ zcbfJIO8Sn3Q9p0U&g!TvL+=#oJx|+Qk5YQ>Bl+{BFA03XO2HHQ>&fop=1I>DqZuuH z(|6?iM)`*Pj1tlt{7p&6jmpX>?S{W2pqZT^xRad2Xg_~iky^g#3bU$bf`ov6z!*vd zn2?`djbXj8g$*F$B8z)Fgk)ZNh4HiN$>?Yaj9KjE2< zJDil=PKlba|E|ae8J!ldye#=J4(=*x{F89P?I7Z#Rd^C21qYyjD2!kqXN$m;ynuu0 zK(;n5db!E=_Y5}De@+392?DTUCQvL#U%yO(Vft$FoP&;bd()~S2fPMWO#S=I@V&VC z+vzpH&B4s8-3{(c#F9drZ3l8xcUmz)+d-pJCp8x zmeic^3lDz0`Unse&q#X1K>ez3k;_ja87Ef6i}$)F{0D4?1~3!qm2&NIU4_Jau{aV$ z+Cu^5Ujj?!qHG`cQ77HM#Ip7)V1l%o*0hJXFL7@i|BYEwWbIx*Vrm&v+b7a~0qvUy zP7;d6LFA2O&pAORi9LCVf<%$(G1~k*JvZRzppYTpE|L39XQJc)*oNrB0LML>@(OTJn7r*j6&H7!DD(DuT3DohksEMcX=chAT7`48Iio5kqsqin zlJqE`O7bFY_>Ipf)t;G1qBvxp$JjQWXug}aew1)Y2KY$Rk2k}Pzo}Ib+6RPUDhXyw z2tr-U!fsd)ZsDs8u8qgG`0LocARM{{B%9V50nrhh2o2R);IK++C{xntkN1dwfx zL1|Y4J_J7x@<05aG$_LuA>UbFcNFHz)tmas0r(LrjN*dwQU9zRDFc?7BbwSZOXPaO zyAgof`tROd6LI8Tp)y@@)I2w*)4yLCStdTEr0{cl!1~2ul@l2yZ)0{~ zTL}kn%fDlvyEpQ;H!*g3VD2qZkXW>iFspgW$teJo435nk zd2)juz}6h6WQ$w!RL2qi1MvfBU20SG47kp`QuQK4-|EVxJ_^m5UD9$aqD#LEm}SI! z;p()_LtB~8><-DeRUDrISKok$Z4%bQiL8^xGjNQpTl7n*|0#(eb=E}STfey$RH#IQ+XDTdtHsyJ__V3QxT5ud!k)8ZMY*B-d-;qbX;+la<#M&%*o$ZScJ!y(DF z?g4^|W#apb#dle}TLDQM176Cn5aLX$r5@_kh`5g%6sXtFUu3LRCGH_s6Jit_>sqRT zWPP&mm*#{nRaL#S9@Gs^&JvH773pX00U>oT(L;!9=*GbD-~YRi&Mv;b$qdFEyfc!B zmm!`7DEn0}(HC}sSe}o$V{o@&IJhRntzF|%eGX4^w9=WCIuM*PTz8OSbM zNk;OJ6yH(4df_u!_UUG%m)k=M+N*f|5hrMn0%N`1*gm^{PZuUA_nYwYUuaToDnFV9 zZF@D7oc~WEW!wfwk&GZ~EnzxyyGzJXOkp4%&zmy3GLp#YssHu2A zW>aRRsyRKqsBBGJ+0JzLFrhGF_4ydX^4c#PVsjd}OlA|ffR+j6S%vrWAG1&cN$HFX z!_F!gok6=x32Y6#uv0X36L->P#kpcxz;rIQNAv~Cn3ng2@53|=4EwTh&|7QA##5}9 zfV3Sp7SEbELED}7;B)^AXJnU3kI%ZYHKyI;T8Nf4ln|lUAM6Qs1|pzehc&J8FKmN_ zeZp}8KFLy?EtS4AL5WsWE**3o(NSu1C0UgR-7V?$g^>N+Ed(AvAadm!4$u)YQ$jlE`Wd%#^D zzed7JV|32?cDQ32bmdXHQm%X>ERSRDXX;E5D0G~*Yb0)6>e2oEKcsRBhz*#cM^$ zg|Jdt9UT4uE+`+E6~4YkTyN=y8cG zJ^yrR@C)LmYgo?Qqb{%q_2OJS7SDJnk2KPM;}p>a@6wzx<6YqbYZzeB%lxtDm%$8n zzLP?$ySqJhhPTTAPlXQun~+mL`C|?-q_)(P3eZxti@Ym5xHJ)m>_r`9R5c$;T#2$y zO~Wja>?H$+GK-9+!HX!>ss)NQinmG#hg&iR_TY$?*CHOl__8J<_r9C06UBN6hISMQ z?FmaE!+-rmK-S&V68jzg)uSzj6SWT2I>_XBwHvc`v>RVSI|}62v!3y1>wjaY0cXp| z&ILe7o23ZJBjq;fevXGwe1mof#*AOYb02MTQg5x-(s@<52WjgfRh3%r?(+{u;Z+_X*PG$r&w6LAZKZQ4?+?1X( zb!bb~CPWu5gnCzfG3@JNge22F-;^IQdEA}C=kO*b?`LWFwsZ(CF1T#>1ywM40SNfcd4AQqQG%`Hs(imwz&= zTSahR+5}B7K8TlYP{`d()II~+-TY4QbnWB{;2_%nz{itya-w(TBCMuMk@f>4DOi6Y z&KwzDm{rGmvl+pc>gzIb6Q1K!k@$pnK4<1%FFshrtqHo+tO@=%WHQ}X^#DbRmieFr zrS|oW6-gi#e@;)69?4nZ_J}`$RYzN9fU#mm(GdF*noQ=OJz|bOA#rW6IgP9BsWdk9 zpt%&_mL?^G@$-RzAM{eq557Qt7s0>N%%hFr9kxB5y9PKx@tIO+<^(bks5O zOy8}*He}CHQ9VE>xSdI-sL>xuCZR&m|oe88@ z94k2T>diPpP3bx)yzI4DIswYbwg1W*85oPn-s`bWA`S7hxN;mUSCROM4>l6Sln1z*)1)YEpO|tJ?|=w_ zM5U<|RA5R>GiL?*=RPU**aX}1e>2NqXo|YqK&WrlDMYhdeWTmo^xNMMRS|eCz)pk{dt7SpM1TdJ#jyv^+%knbdA z-B;W=WX}GpcU%n1U$se#&j+*dJls6}x7F6ZCST=|=5hlgtm_Sr<$j~bAuW*p7Sr|2 z<$C<_OJL5bbC)~-Z?0mc?;U_2?RZJ`R0zr!Zody1;4j?;-x(p?ZXms>t<~MO^U9^V z@HnJ5!SGb$Mx&Ryl*-SzFPoCM(gROP6jvKk?<&lg8`!ogj}zo-O#Mju2Wkk6>EL?A zQgoUj>*TD3$%t6I38+uGgC7iFp*U%-K0Ue-x5jU_N+WI0A!}Y&t!Mj7U)eCXf8L)A zu!@`3IePOWV(&A{+vyx0Y3r93z_N4t1kOF0X}r?l-_+Mq$N6S8PbRH)U!i?s3VQNQ z%Qi~Jr6wko6aT4DD{TCR!eqpLdwkfeO&nGz3ZqwSh3AimpE%NLfj>EC_VIYb+Br`? z)svPQnBFb}XbNk+Q>(Am1}OgMH!UDp1#3M=fMF~I^ru$Bphxzyt8f&W*j}d#+cLKD z;2fPi<2a~#y8J^#t9YpU`(Db6QvKt(5k%i*OYn&GU^908VvBD6loDq4F+XoFZtdlo z-fsYvzZSz>Ql^JG2y>|_E~YU&$_kDCERf*+A8&|^y2AlO+K&yH;0_r&n<%+WJt#X5HbyoOu!d%wWViSp-R3FR`d5feZL&c7 zu_YXk{s7JdTxDDoc|($%9}`b-(-uf}&rD=096u=WA%tHydf{?fC7X2llrDX`8$Vnm z`u6-#sI8zbMCEkzb>6{Y(O8EHf57AlOK&=+Q=4?weema89(=y=FzQ#*NyAu%KCVc&c54JAzGeei%T1RN&_Ulz1 z^pfCqbZ{?bK-x|2;T<#Z#S&*nMdpm%3_Yj}9Exv{pW4}!qhq{j?P5~oKrU!5N>()M zuE-V>d9?|y>Z&^)WZV|33&Z-0b9UltNk?gl`yb}w8$M?Zt9h8~m1;5<=bT3V=e&NE z3HmFeNpeMp$;LpD)SRU$ycI|E_ByXY4QXRo~}Fo0!2wv{$$+- z93d=k?M&FrL##aG$Gm%y((LJ>2d1Gv+LY%uEzC1Yw1*cI(rWJogeN}mTLEmNKf+>o zEinNXq_ZiE%Sa=83s=ugNX+)y+vKpGlB;X(zYVFW80th-KI=G=DgRzf^cmwHRHjyn zRCue!G8|xTx#(Z^&niI5{Q`cNglM~5k_G7`TzGu01nO_|6rja#M*xAB|DXQUok+Pe zvkVEduCH^2EJD2_Hd4kp4-9;Rf>kN^IMnyBo>m>CJf^pL@Ya};_SX*PoM{M5Wq8l$ zI7~~O0f<;}1l+%gYlpe!*8T%%t!CZ2nC?<^BU-+%1jShY8CFMZpu7rWg`i=I5CSPx+2HfPU=1dfCC+d>8U#vYAPZqke%tmKbY08mF z9x-b>h{%_ID}z-)`EJ6eiXLjtHqb9I{QpHAq+V3&2^1kx4vOWyXO18qU?EXN#cNpV zrGiKo2C3Oj-p>Cq2y;F1FY4ayIAZ)u@h=!goH`lqx1Q-HvrAHNPk}De$8%eYn=xks z!;8Eq`j>b@QV7Z#6Fq#k@$Io&j4sJs+@I5>7N!bl)v$pG8`7R9{|7vPn^C@*a-RJW z7rL@FCp0B5Z)1DLg3vnrUIHD}70PL;RAVSZ_scX^4`PppA)IpIume#@|ek8`ptVf!JuhFaVf@ zVm1I-ar$ajFVCM3b?=fCUe*ivgVb2S84TzyY4~m`m7$0@58_)=U2Dyb&M|g3V?K-6 zkbeNTcJ!ZLG|V#);9&6NC~+G5TI*I{t#4nNpltoXa?gFo`3?$+xMxrtuutV9)yd?S z{5z*TC$&bKV7F4|vgJ2I<#KACj|r6#)}(SE9>*6T9t@g*2NC(yyjAL02t}Tld>EQB za9jjfRzXLzrb9PE>#~D_>FA{8_Vo-42AtM-pgnHJN{Wr7LLmSSN7kE1EyJ8J|&Tke&}XMAEi^x%W!j(CpUq^h3c7N( zx#kIH_0qJIY%vOBtu016tp2ny9jUWkTDT0{Qe5s$sF!<~;FyfBE@q1?_%pvTX{C02 zN!UDI*-(y10%m&J?$nZlZ%G1>OP_FwRL%ZV+Bk>Yy|a(|LRB^F-_>|6AS|?8Qr5Ub zj;(xqyfvOO!3NFD{f&iClk%QoD?J+)jY2&lof(e-rF&W?8SPCtlL3n;<05W)v+zyE z?W4OG74?R#_q()!RO6qL_cIEOYj0H`QQ~V^(vOW=IE87Mr*4AJ>YYS&B=|g&Z3irn zBbr{YQ3~Q3>nUsArwh9-yWG)9?h6YgmJMQ}0@?4INCOTiRf)@A0?>33=V#2oEgv6w z5S7Uq*I!3idyGWkm4rnGnXc(~XXGO@EX4d?8w0mw!MgHp`;3E{MA3?)i_m3g{w*3p zbBqJx9MkeZd&;5EyCXnTWxC8Q@?Tj$6qwr~ev+Yu-Dy4#zq>>Y$g&&v2qObO*M)XX z1ZqsrX!OVMW5}zaY~C@@&5UW#I5j@^nET$Hn8fA&vBC^{lsQ*tA_1^cX;XI=y%0hzo)4@qykUZt<8RDqv zJx$uJ#8yVgNLWC9$>*ize!RWH*3BmiZCDo2)npnN`(|VXi48Pk#wRDoya~a651-y5 zP}&g#j5+Y7-+>XU|80<3)~FmaFYFcJI?MuBIhp)28{fdnp08T{nb9;4Z8Y?)>l+i@ zFAV~1xLu9B5PZB!K0#mTTPpC=>@0KMnyzv#q|oNDa_Ha1H=lYeNPJl6h}XW`)ayf2 z=HphG30>+CDwZG*EI*S8b>GgTL(=b1(^#ZZU9R*?M&z1tZRKgRmE+~X-F4wM{9Bou zMXm2+=A9X<_QfnaV_-izoQt7wd>gYwlL;it{WVG|j}_!(Vaj7y`NkFuN8|CW0HSYy z1;o;yvDz!vx^d*bHN?hT(5$0DWBm9mby?E14?CopW!w+a#0k+lT3>#i$9+=rk2 zrLFiT>kdG}VpMWP3QqhEF{l6lNfW7peTFZNDU7|Cc*rmX)K{4hf~l>uXVrxsPv#m} z=RX6p6ER(95C&B$wApn?&Cn`nF|m*3HX1{mJg=Qr}g9oEDG;o8PKl{$fWfx5x~09oPbAw z*Xu{b8vooZ!l0zwmBYYz;#zGs?6S7d!S-2UzMs9Zx(kLa^F!sJOEtaN^8yI*9im6a zfGqa0?7-F#^W^8V_!hLqV2mW!NPR~UfDHc*m@}KCr*vdG(lN#mw#%uhFXhl0_P<+6!{(Cjj>a1?sDo7B ze-km5*OXi9+#e`Yg|*+>`eK5QN|#y$`BzU>q1Jk?(+*62D>3;sWB-o}hxQk6`~2L_ zlRuSyhXQJH{C6dB*QMlK)N~KT`FL)d`h!7x-i%6ja7!hS*;D<^Cd}{2444DFq%Fwu zq)dG-aMxWR4Z3-U@g18kFh#|bV^Q+t$!y**?UVo8@rI2WIC~&af%Km_ zZbm#L^{WGPehaMk#%w=2qNx-H&59(B=0&_0i_>XV>vc$I6(bE?`yk*}*3k%Rp6{!c zSXQNL=B={8VoOrk*AeY#$(RFewxeqBSG)3G0Y`zX0q@7@1_TLV+fMNKnz)e5m8tV1 z>T+!RnDXC;&@(AgU>N1Nv{LjWg(M*C&${D3*|<5{EaV%a%dDLB_nb$V2PQNMtk75@ z1e(^hcfN-{3O{V4npbNfj+n#O;h z4+7u8avH|@s{*7>S$oOvp54kk4+dOEekKcwbZj)k`ZN0$HPQh`jJ&RX z5wd^uuKj!B0jS&jR5$sz=R^LEhdXgA%t8t+AeZZ55-(V4hq06nt>z&1Z zKsm9*Ou5^UY+)0N^RIJR1Pd=ZXDJ@;Ii4weU6l%J$;_hfy~eMTkgJ0Gm)|)t z3b2jy>wgVUAmMJo^)>v^={7L*46#ziTB$h8A8&$tu)GIo*fhB20w`MaP@j_N{p^$F zqU#bVQka#zXrtx1)z23NCYQFUl(3i^APNip=x=3vMC|n z;poB0Ec7*_+Q_0Y_F1%QmGM0*&xq(T@NjM1p~&#>>zpqe;i~boj{8Gp{uduAxha;1 zH91WZ%a^ivIAH8G&w3vf8n~R;Q8tiQJw(kANnn6vQ3#vcKDWR0U0d>6#`2%=uee+E z&EtebtDX^)-KrajCu~Z?Y03oxW=vNFx7n3%Jf~E>*=F*{(v`W}>H_1i+wpjKmsVT% zW@Y`45{91B?Gf67NIt}sx0HBn8|=HW_0sde6~0>(5Q2~KoXFSyLJPHKm2yb+rQ3kT zMF6G2+^(QU_g=1#DjVgA=;%CvAZK%q-&6AP&sdYOcWmczP9zveS{o0QzBzX>qTc0o zRv-I7|A5NK!;fBx=#ioN8JOE8{;yHx!fp#dIe#L5o>9&dL~Q8ncU7bchFw?diF0sUvHjbC_mceTlAiq6$=3V#yz7?>m2 z+lMx>eCn_M=Euw~^S7e=iBkjDBL_%3} zdUK~bXSDGU<-*bp06YB8E!!p|t^84nOo~kCgG|276$X{f520Vyw*5x?S$Pu@Ig`T> zXT9u){66*AH~8s0LIYh={0{fl^tx!1w9-UJ%Tsv|;5cJ}Rw}*~xeMF2g=8_DJj$7x z58j=mIu|A#KaNioM%)~+uHP!3=BLjgCYTh-JVua> zQ{OyPnsN@v^umjEBvLo*ZGM?kqEMz-6W2<8M}O^lgYe53zF?vxjd%Tj&)42x2F11K zl0u_y-U_s|oA^z?651cA!%i&P^_heUWzo;_=7p2gH+B5g|1641p|ObChhG$G zp>kQJTDrL8&Mv2rR<1x*n#lB#*ZGG+&v`T>NO}r!6Xcf`IEVrn6y zpI`Rdx_$;1V>Sb;2>UAX%;ejeZMOeezZr;s@c2}{b-eOKB?ZtAtn*V-CeU?1pixt< z4H7>}EX_;tj^4bR{J{IO*Oo61g|r_zF^`C2wWu+5dYKdLFJOC@e;w+jzzq5ioPzvY zKkwSfo6HpZR#Egldat6|3?w-$G6Tz&NrX(1h6aU8J7%nacN%|*vRB<1P^O!R^Z^vU zq+{XxWOPb*vK2A;s_56hlOn+Onx=e#O{)PHOW=Bt%EafDp|Gf7^hYiqRF%UEUqCJ3 zm^y~!um6#VhBO(TiRfL*b%KqN5}ChZ8k62x>KT|f;kTH1+iaOQINPi2YG3X_fqST!KPkw{?An- ztrZQ&$G}L5nxx`F?F;XyP55Nr<-t}M7mGL|zrxaYKnZ0WL<1gDex!>WU6-+tvhW3tCOUTE4AOa8hlMwPFLaz`ZNzVI1(`k55ggq8`ZUgsLObI-$ zk+Qv`6W7AvN7NLR+^u9Q<+uH~*9YB+_p>|!NYNw!DcVuO)_+x{bmM%liv*AP%kxUW zb8edk;lU=Odv@8YtmP;hLQW0YRH<=VgM+WT$;ywWRiKab!hi=tR#A!CGh z>r}56@RoLI0d`&!?y4veP%YB5^z%G9CVa~W$t4Pnw0{5RocI4~O6QICPyC-@u`X=Y zdyOorol_X~GGSGE4Pro}gqv=;oxMC}KoNgwk(OmzK)}1L1!>f@&F-^8+cE7|9j*Dv z-aKs}sRt|%JK?w>UOes)zjO;pW?m8hZV!eLdMJ}s0fk!AX#4ibzpA>c#!l6Cqum+< zT}ZsoZ#*h=WzKi2M5$C<>Sr080Ky>wS+huokSDjS70w>1d#~s_x(UEJHxO=L(V185 z{Z6j+r4EQKX72qCYT(ZI;`18@{94eTD3`(Bs>;_eaOA6MPmQA93I%XRu6{UB6?%wE zYB4e}8tQ2qshXH)A?9W-!9K9{MhQeJZQ`w1L2H2)Z==+%0ETdi7_WljpetD(f9kWg?iLS=yERrrHIfGzvq-3F)J zwrt^~+BQ?a4lsp~`+h@W(UNFOl;q zKDAa7{|=|1{Q0%hZa?unX!ugzl5Kkyx`}iP@*O)UJ0)#(Jw0?%#c*z0>c*{^1=#uO3h_~SnV4{5z%V$g#lU0a^P{>zDYF}6YQujuVFF9SL+vYM+vFS`+ zZa|jS3rXjmGP$T>y;1Ij_^PR1r{Lgg16F!KO5dhB$&?J8x={aX2J>*nL2M=_T5-td zM7x10>z3n~jniUpfd7{!MJ!UP+^sF2RDA<^UfD{ovqcx8fI?PFoWX$J+n`_j{7v85 z+&*_CS!pm9y!@fb!4k7Eis`1aH1WWm73X!IwC7)xd&IuE;Ft14>TJu+LJZ*Oi3eCj zOpZk$d=3q5Zhy=)7+h0cP+Fjo#chW3))a$@I@;4cvNNz=7lv2FDr%C|{G{7}{F}P+eDV^2uy_b?4({3klY3xCMQ)6?x23q^K5?&OsuXkD9W~4U z`bbjwD0sxg8avT?xlk{>WfilYCfr=>VeD%F%Ketf-3-!9xWBl*l8C9(7UtY}HVa#^ zl=nLqTM*~(uLv!m{FOEe#ou0~dXLSXSoI4Q#9SeAyDrYtjDTp_b2nDBDoIj51;s>z z$yuvzts-u0SZr}!Sc4R>#%4XNOg5TuoQN2_*El+Uj*6lSrn(vd-+LeHC>b0WeGp(z zx{q9@oM($A0zMtOpKuLWWP+LlW&>g0)$kKLUX{6jq8X3`&t2N=o@GH0VWaGP@;a_w8v8svaLV+{%1(@?iR^bY9z=_6Zv{|DaW7zoLSn8d9am ztXqY6Z~6b?5*u5FZG3)oueC8Qg8gc(8Ggl>jJ1PnS)J0|Di4Og_!de9%=P=<2mVBd zfzl@`+yodH->OZ2l3TRKlsN^4O(HTKuibrZ^ur<`g0;0rg7G`($iAS7r5F4*T~R>E zN;4P@Z0k5NEBwUP79UcC4iGKhPR!CKT00f5h#!tgcBx@pB64bzMsB$e;U{IDh|>Si ziG6C&t6Dptya<-!fDcZlfF>!<9P6GN7opo{DSURtN8;B;?^Hri27dLx=;sgzye08= zU1;X!Mh*Yo$-mZ>l%2rPcmcH?u=Ogx#CqqJI}r)3U)BbjM6VZKm6+;RBACydu2zMn zMrUYl1L9&HK;_BI;#sU%NPYl-fm8jy`0Rd%sn9jETBP?Wp|ZH<;snaUxGW$5p|U^O zx!*P{RN0=O%K@@@onEQd8xMsIPlmFLG zG*xT*6wP$e!Uy}|aK${YnR=hC>SZBn%ppCt(ALx2V7k9TnYB=8rT>)lxug-cWN>FK zNIW1`qhRRoSJsiXbwbgA)gJ{htjVf9PI%cSYN-{A*8rh6U~1#?s6!m@Hj&YTMLy(~ zIvm)iB7toNIK^8KV9PeJ>6LgCJHj9=1hi@-Q$sq{R0LcVFPVKTGXD0m!R~8L)Kzj8 zE7Cj7w}#P;F6an>J+2MBA59F9*{g$G#bQ z4W%J8P(bu_ofAJrSFbwGWgo&gaiv8@b{$NXU+B0ya?}NKyu@Oyv2pF;hz*q6K_;%X zJ*@3Vi>v{_PVordHRX`tdrf+`3^=cr)79<1mWmdg?S1;H8h3H1tOM_04GfNey7-eG zkX@>#L~DLGvy$EYgtxn2azzjxIIoiK(yHDC6n`zqo2*}W45&Z zj}8Byw+&T>Us%|0sUM|Dcl5Z_gRJin5ZvmK(DfHhGM#SFSiWpA>%twa3A9E zSXp*I+MAkms9Qy*>>*`1`e|`e&;p!!vJEg3-_wMd`KFB^nY^a(pjM+C#2-Z4dpUx; zA4*R*{8Vue``_vEK!>n?3)fBwx4S4W z-A7~W)_K-*uj~Z2myoKJZInUw53cr$h(z22^k#rU=rH;XsQxi8-WU6IdQ+R?^5?S} z(&V{MUi(PK%Lf(ff`kT-dt^mB!MDtSow0hcYK6qh{IAaQf1eS{v-F<`wo-$#D04=~ zSvY<1T>{qa@GwV@$PXl0tsC2L0e=G%$V2iwI>3v?Eb40&<*z9%9>WVG9UvC&dVsGj zKympfNGJ>_bl)YbNE{pA4$M11B@JC6tgCkkpP0uOb3pRVwx5dw?gH=r^j^_EeApM! zSdIKwA`CNu3YKe4R9l}Ex!!Iet7cGdQJ8;2{b{kJPGV+swBoEBRzLmnAMXKl002(c z**SpN%1dK*8Iw-=f{70;%iZI&h+|&Y@bLf3HWkXf4Lzr{{-YPXvcg8aL$w}Nu$C*K zovk*#`xZO&Ueb)OV)GWT6j_5^?suTzl*%X60Ip~kn)G6UNB1bV*xVnG_JQ3p5>hdQ z_?J+Wzy4NsnT9{pEVgqhPS8M;A^<{hbVw~lohGKdrom?Fb*f4%xnt=uUoB1-=K=ua zzc#O6t`_RBsM<^Qs}~m~+q>0@YGWscT&D8Ww~$j3KYRv42f#yEuj>D?iB(_h$Mcy- ztUS}cNX#yL4e*Oto;N(Z>h~;uw^a|ZbRmpebo+VrCuXjMxYJnIBI$|#P?5TtS z7c4O37Xl%k#0=21&ipwVcpjaPorTWNzW2XGi%2cg@J%e~4$@x)F?HH0bm%UIde!&k zjzDAHpUxjiA9~hCbz>{1TdL^q9_!H+lt!|HYWhfn>}t71AKQLf-)8mVRkr?JcMySQe;@`J*>7*WF1Ba1yc$Oi0+E)E2%z^ zG6s&VJCcUQ>k3iy7PR}wPG*4n<2F{=@(;2X=%?W)-}Fhp8b**~AysDmaB6jJ;GL@& z*)auC922$V4WOTA)-G}@JfFt6;?f9Rx<|Q1L+deIO2O(d^{VA8{uAfEyt`9Us4cKu z?uP}{yude4xG%++2LvxL&zL`F9Ie4V+pcg-Fvl-JzF=_X7N!;mXKylO(pk1a$q!=d z6@Dyym^Tv!zoWz@lK7OzTVPj?9#(QUv8*@pN5Aw)?gVdB1A1dZtbJYM2IZrqCbvgE zTjVXtcUKuNO6|lX!j*R^5a*($w(?u}@;=*&OAt!-ax;nB=p`xRe3BKr09s!*0BJ^o z)<5Se;+N076ITAkp-=e{X9ba8He*;}9XQGx#E38s zpsUzh@(;(NZNhQ-wSW)yi^L4DBTYG@Y9$H(u4*|Z;agSPnJmni?>4MKL#%jBa^L>BbV7udKdq~TMC7pml=74@0 z*RjZenrt~s%bY#y`K}?|YtA#9)T3etzQM_~dX=aYE89L~90zYYqxc1xsjeX>L(@5{ znGi&5%k-IDc>e$UN9Ntbi7>GOLmCI^q`mEuO?`L#Q03E?1luj~%>AHpehSmpIeo0O0@K-%T3$sgmv4=QoEAs5Too&+o2 zwt8x9P1(zw^04(un<6H6kB+6m{4AxV_%arDrf&h|HTh;^umrbG(kGZ<0Vv$J!wAJB zI*6HaU3p4+DAlLa+#W%4GA0L}fuDl9Qge#kn-SQNBW-G)YqCG93=tOtsJWH70_iZP z?a@G`*<<-MCBFQK5-hW1wvEfOd*pY-uaMOj91tS6zBBA!Mk9wc=9`)nbpKWFr}~3! z>0?3i#R@h*TtT=WkT#bd>w%o55b*vZmXma*m zHoAR029a40N)qTJ{H-;5ZSR!YYb69h_|`KKkhI?q2A?KdF9DP47P#OZ3@lSboovXL zmw^si7Re$NbGJLMv~;O$d1(Pol)O=Fuga@bPxszZAvu#L$<2_MyBJtzK@_zOu&Apa z65l+Fa-$XdBJq8O^0~PkZH0WIRpFANSZruc8vm8%xtZMJjQm{f39UH3u8~uZwyJ4R z-rVnicln$zcSxKDK=G3b)oZV)oh6@=B8?#Avfu{HcgoL674&-t=4bJ!!P;1G5_>?Q zoAg}NZo~Eq#UC#^9X-`mR0qoiA~Jc&#g)Me-M4#$$Tp)1mnvh?cJQjazka#Y!r38L zcGLA*E&r?-WrQkuhd5*8&DS)eR%bgwlNM;DIT+ab3iNXpQxQOb2mMK->TCFQYKg!J zL53$utZV(*B7X`u5}{x@1tN`tE6Fqe~ve;Kg7^P(Xj&3%YA z#u{Ubr{xnHg>k|d-S#15C)B0nn_#D$JSY7?R`$qPJgdS||Eidq-j#(F5W(B6Jo-eK z)AJX(bvnmbZx>*+s)`z1kdYfvQh#oITP`_2qKuW)0W{FuO3MiJq zlNvoY^2XnPgZ9r+W8vEgAA|CvW}yq;uW{YH5Y)@N5WC?&)*ZyamIt6-%^4g!71-b; zKggTmofKwT<)i7EHn6Fx|)+r+rqI;rgpBPZHc!1{H^k9> z@HG=pdsNuxb!lDecJyB-e=6YQpWBYez0G+#^yDqnI&G)$E9pn^SGeH5LYswixO%WS z-VHN~acCt^p-D$Um66P#BOib`jXyQ*kF%DG>A+rR{WMsSoF6yr^NwP)xYL(art%0H zv2IpPE{|ulD$-L$Zu28aGFB*ravRKZ%Fsbtwz5B!^N%(?a{r%vm(@Nae)a@7((s6A zETY}FmN2Fo^Dkz;-W2p~SV;gP9whLPEy?NfiulPT&H!U&_;@eUIHzm~htt4yp%l^L zsFiK}+OmI`zQ-8W$QynSoj#)WqgLcuAr#d_($t{tVg=DHgFPQy`~ZA1;0kHS0CC(m z2X578Uzl5GW&voMDY7-V+eWXe_^s_keD-j_+;puk{%_HG5W%RF>ywnWh5TRBsl#hJ zMo56r;?3AAePz&OgDm+!7;}jlQ7N5fUhm1)KUL(UF&@m%qhae#sa3UgmZRJ}^ov(V zQFNbCp0i&|@fvkSBO~xC$zZH+f-O#YL)@;F7}li83k6a$EJ_FkPcOa;$9ZuSdi~sf z$~HR$f_B=7Kgq|6MJ!zOQLKt$aqD;&A298%OEZDQRp9CT87?+UVSg}9s9H;2*NQBL zBdxe9+s7dFZBmbv>K*dl>k>fll%Ld14Hkd>Yn38(@F(Xi%0UyyLF~QQ;P}~w z6~*@9t60jon?bJ5l@DP81gS!$s$5UUNzYycu!;`!la%n5AI=nr?+$HzbUp z&AG!WJX@{-`9rqvdUXCDgRinciOumyReZYS{|$4UAL2=Ak(VZaZ1JundL#}om)EmR z#M_q6kEp}xf&(Z-Ep_C8Ip#3#y3_P&9w6Ip*SIF0yPkM2cxt*C?da*mdCszhC^i7Pahl{j+Hstv=Q6p}-|l@{ zduHK&#uKLG7}6S>NN|OwbFTg;ES;681GG&kn5w^l{EYb4xLoVE*VLk_Cf-mJNh8bs zw(!y@`G+H$cXQfx%E}$O79qkHCK83wfkn_xue9!O$tiLpP2G$78--J3tf+ci?=g|! z;xP%8*9C1h3R*a;-rDI`JA+a@pr@UxMvRGKHv_z#)hfY(7;VxBejd`CjoJ!JZ^_EdhGT7Ty@++<}s3L-pJ0 z4j=3IwPwnAAzH>?)QHp+6+vu?p&;KKe|RY9o#^;N!Y*Br4L_zD5>wYr>UtKPuV~aa zxWMLte?pHyKbn*@-F)it!o|!seUs{D3m`EcAfkfr4#yHOWmC;?r0x9~wffM>OL}f) zW{cb*e%NeO$+)zE`#*rSjsGB)ZU2I{4}U7q-}Tf01Ge~F4ltM9iR&8zsU>&C3~Wqv?VqHB`be#A+V z*W=2MA~$id+0kg%;Vo*%$gQ*3pZd0zLEJI_rPL6I%>#iu=&mZiJh!czS=R^B5E`bm zcGlMMX26V5zj?rJvLET!##EXd@@p{D5^%S{gl4x_!^Qqr%IZ7s&F^`CxyQ@o^kbGb zkgdYrngT2~Ed+4X-HF9Fd7g!NImIuR_lW17PdZovl0xOr zehnGRTLC`}$)Ci}mX-wwWI$c&`5GP%ofzZX?>~F`>e^Mji4gw?Z>x5pGHH;cJQ}{h8&^V`GJ}angWJOToSszK=00TZSqnQ$>|I+fR6l?o zxr~M=plj~REPA#0^TowAcgz*PI;=|-C4M_hngH6b>UE?nusrU{+jd2*VZm8{(w0<{ zjv6Q=RCn_+*eJ@&ED4h_oPJ^n+VrinCVbeZlfUOr`gOF~zI9JfuwZacGm*(-DN)`V zWl_H0Uc515K5{&D<>aM!1Pz<4j*Wx}gLjKB5&XyFp3aWlyfH8D#X^9;tR48)CHgY- z32P`Gdp}FFUO8$2ip<_0WL&d$iSYP?Gwbo`Q+l6(_9tbR*=s4DsiE+o)M?z=C^K^~ zE#1jM1}-iZS3!p81`aq~H|$7Z3<6r$@`<}HGx|3dtoA8#iF4|;ldY(PaQrQ?vllNF zNuKzeWEYl9-DOsMe#SM;XvoXN)33_ylOR0F{hHA@2T(Yk%@w~}{qkQjortI5iw|`F zHo2EmUTNwX;uEsYr+=c`|4{66(?m}Wk<3`R!G9*=dD%~`qoSJwgQ9l*s=!GGX(%AXN@|6V^1s_(vRE?EV6w$LBebr#-uyP_t{|=OfS^K&$`*G;)q2LJL zYQ#zecjIu?;FHA=oU)B@hs@ca_K~RyGhzR?-m~nbkzyGXG#c)`9ejbE`3ZR z5HzP%OjMhY7CkN-a*w^0berq^IhUv;n`ps0VZli)tFO-D~8lMMp?f7$6f-fl5%q;2tP;o_A> zQnM_e6}nEiTDb%I#)+M5#vi8Sd-0dJP6ozQb3ucrK`toW)&LOL(sXO-KGZ$VfS7VB z$U)fBK6nClYQ{N>T|cOmg;+nf>k8Xw`QKhEfN!yU87&tJS+-z{ks+MCIH;R2Y6udE z@OMk~*1z?;o%GRxKB~Q>qi0``q3OXEbBqH2coW({r=x+MNs>GuwxP|!Qp?Vk_3;WB z1{rUfQsM(KA!7)C_vubUh1pEQM!~3sKO76HLeeL}8d?8q0;+Y-(#oG3EJ%kumZ5Q;aB1{X9G82 z^Tq@21$6E!P>$+DdBHa0u#zh+o(<057hm+IH|p#|?4Tb|{#RDU1Ii|;Q&GB) z1&w1JQ1gzQ=c|lIKZ}^BTY~_TD_Y~ymCnY1($BMI#jY=4ks6?!7|Y>_U`%l zVw7FrMb`zvlc6c1WR_9IPcu^XAJPK|Ra}=XqN}b_UVjdhw~eop>Hn!M3LzQ}k2+Qw z6hEzem)rd@BsOTBff5=S^Azqod|qo1u5>=%EWdPq46qP4?l}eoJkT;!UacT$2glZZ ze(1^bM%&%caFYCTbaf(JsG@M1s85u)8&!<_?sJ81|3aj-k%hxzv`?X??2890ZW-Rr zF7;#g{bb!)jq1(m9WVM5*L7g#1i(0)=T5IL9tb93ZafgMBL>CU<3=B>cne1~W7@~& z%)U5OaQY@g#Gf3zD~E0e%W+E6P_kvHQ%$RXD(k=W>AJn`f(Ab;#pA(%SiBv*Fw8i^ z<;^!B{94Y;;QX|6hUSycZ4}nt93}2)Z)fj8lFcjC(!Dml0s#ogpPWyaz`^I)8}v7B z*a@B2FnsNS|6odBY|fCF)&Ue*+WMe9M;?&xG=%Z%Id;W?em*p%48Mj#v$3ZJbO)-x}zaN_n_IgH>K+5r}247H-jMaYgN2UXY2Yz(jO3`#^G5f;S5) z@O|H;^CwG?K9OzhSip4jvZmSXV4|_MAQgs6?!(&U!;mclm+4m_JRqSxpCF)r$XN`rAeJdR-l&g|J z{fSmI2{_Ns)?7l`xgCR5Hngo)wFgv9TTekM!(=`YIbBlCgzvxJ49rae)Xoh(y2uEC zuhjtf`u|Lc`Z-$jrJ8OAiy572j{Yt&xgMC{F+Vetlpeijc~Qv^pcYfVOe; zC_!5cqglgL#mv`pzYs?3ar_uyyT~6 z0!pW`Co7K5BG{E%Uy^|6`ezFNxK9$Ry&lnhs^5J#;te=g2izzH zy`TF#~>}aHF zZ>Nz3`-sTYefw7@@gx6CA5T?3dC)S`Ce#*d@q5XE;^NhfBX;8XlE$r zY+2VsL*frkdXH8d>`RsUgLwMAH68Q~(RcrR4sH>hk3KtP8D7k=Z!k@B6xs((@IF+g zy9jThAFzN3$16zv<==*;%;$A)c^0fIsArc~r9}ef!G_LCqGn4kJ0l`+&!YZwU-7ai zyK8x75l1=aMW zjYKaW9fnDycz+wVBaC-HTvi%EZqu>xAI5Ly$^9ImuA~<(9bLN9Q#kcG3Gu8v+bjgs zU5&jObb#I{q&8TWZW-4B{#1*J(UYz1{hPk}s=`>~&ws-k!s_2nY=rGX91v6zizUc7 zw;Nb36~9iZV1Bd8aV75yeT{1J-1)8KCnjc z=1is`b>Mt;V*?1y&ad@s9=55e>8pVpQ@F0hb^@1Aul z-P_BrNZLt$aB7I*)pPx+#jRnoqmL1>*GSK2XY=Bzlq-_^%&tl9ts;IuGP}d(iKd{} zy)TS7A$+H53TB;i3eFv-d~%XGuB*5f_lyY2gqMnk6|F{>7W_{R&fmmZUkgE{ta5a& zI7pAY92^lj=Y!oYV}tlR+wX_Kb4xtahYwU`)+6-`N=`zrNXDtP0vsUy85(N6+F3kV z++xcb3}5>;q-3DVF&=|_Bxpi+k)B_H+#+p-c0Zp_+idT{-*;G}T)@@NQ#3n4fNc^P zxlQp9QQ>|*Pgqk5JJbcjkS9T&mAB+En;4>FrJ%9brbg^EY2y)e7oj)cjMhn%rT;1X zO~<3~8p6bPe{JlEn=tB<<*48dc6;CBGP}Rq6Fx*M8W?k4(o|KBFwmd0lOW^}oQ zJ7v{=&9@>{OL$sYV(Ewb!do?`n)+aoIC(@+5xqY(=p5m8hxuG>-`Q_OSD)Qv;;=nWjgwP<=!V={>MoNvN_;>Iv939v}rKu zwsSFS*U(L@kWTh_A!oO?n>S^z8#Xh>_u4kQ$%dGo4b#0`PGMc2EHJzm(8B%BsG%ni zufQMl@5zZ`P;Cc71lP5uok3_XWL@ATu-26H63 z0ys@kQQli=2Xq&4!E6A#b;#Y5*;9JUz78QCB;E*y$5>TPdfe zo8pP~>-Fi3nr|Iah}LvCc#Yng7t_8KLqEBJdtI`Dg0D81W{MiL8NXcf*>U49>y!2` zFVwPbP%?L#KScWO?yQbnYwm5-m0+OK)2o&ir1M(@UoktBd$L2%yaGQ;^|KRn^=6H} z2}%Tg!E%`v5!1{gpQPJwW?qB*Q@e1e7E(VP4EI23_cbnXW#?RvA!Rngep5tw4&T|& zy9tAb4R1Q$P+EV#wOe7XWmmjy-6=OTF#|j8-C8P7Y!5{{Ib|Q1HP0j8DYPj+1n!9k zn@Z&(gonJZEtUTjHhACgrb-~T@H{5Vwt9PhYO$G%3hDKHqEki*PBf2+(9h}O6knds7@7tx3E09+&+Ok#i?7%w`3ZNpEMT+% zw?kQY*3Z7F*STr~UIFMTyj`YVM5#7}O$7OskB>YTPo`OXHhbfGeBt{NMpA#^nuDx) zc|6-7-aTwz?s=kFKHn34_4iCKbsq)Vn&h|h>!|oQn%Ji%>@|xrFni_fuv~Wu`+h`8 zZ|z>YLJ18z{n@d0Gs!6?`!F|BEkZTI;!(iR%>-+*VA#)33PyC)lII*|(Nhi|)!9wG zWW(~KBQg2@`P@_GSKzbq-Oqvc!}q*WpZ0@!vpt@dxe7eFLc+?EgQAR2#9M1`mGCRYC%&!EO#4JXP?+%h8M}x z?=ZI%v;d#RK!&$!9m479sg(;mH_f?F-&cF>2Y%6gj5gHy z*>ZGEKN;FIPt4fWVALYnhmb!O9&qSNfudeRQpUVAzFDLu!wsfp$`&`RqZW~t`hKoDAZk*bAl+9 zakhE5>~V0QbuHYY)ualG&DwQCMODgpP9qn;$EP?#6b#&zIkH4~S7 zer)ron~NimV>t8aNPq?J4Qpp@x@aeGVt1F`OP~9=S@_aWTDHxbbV7^fQ`U!>>uWpV z^)39;d|HAV&ClVWUfMi#{KM{`tKk1mZ09@A=^apM0v=1hmF&s1#lP<`?q8$7n)`V9 zL@m?(>gTg7%>*6krN!jGsCi?}P&4oDVJV5m>&nT0;hT7JFG>C{4@DmbLVI0%s!Yd; z)eI2UO-8hsEN!4wJy}25vUtiU6LCna0DcK4;qsZcT_35$>LtbDuNGUzJkiV>LcKuW zu+2KwClN@N>Bq6uSY#KUr15O$2sC|uEwhDUJdA5LN+RA6LPFFG#0~9eZQ#eUkv#K- z&A^R#FTjc!GuJw6rVp+>CCNni3*X0_67>iUwMHzS9eM+>pf|1iYx;3_mD6=(>H{va zN80Fv6}M~p+?;NFd*vW6${b-HoHCj9Yp^+N_c!K7z5zSmlIHcHe-H{{YRqu5M+Ek{ zf3fR*x_&u*&UTw+d)6|S#nJrt)H1IdbwEj9O<&s%l_tm0LWEmwAFHRB2;;E>uNmb+ zo#LuiTWQh8sj(sTrB*~kSet6AX6>DT8n*o)CexXbJZw*IabTF`LBm+vf#i zLi;+pmo(9L@Rfu?{BQcriVvbl5G$Tu_*G;o`jBU!^eWar&%jI8Q;iaofH>}aysA~R zJ7&#dC1!n?;l02kfm9Nq{rj9+)6TYG1C@ZfJ|0luNZ(S@_YvyjBMlnD@D2|=?*Uip z;F{xGmPdzIpJkJcyKkm{CjzH1&emw+7(W!>EpXc!O{RUVe>Iil^SrhSQeB0t?qjB1 ztR8*=HXQm1r?)}o&y1(gk)nMK1@0Pj`}>^bosKcZvSZ8wT7Wk3Nv};bg{*o}D!Pom ze9@7JQdpW@O8p>TaVPvCXuU_~wyfSkeUMcrt9lw@4L1V-5UeI}&^Iu|x0m^T2OYVH z&wQ)CY>nEf^;6ui2o(L4@63rse&mC;ImJo%8?}9u`rtyu_}SQ$)FVP+PW*E@JJ+d& z{?B&9o8tdC zdr8Rnz9$vL-6giK>$kwQ+!cytFCB)zcdIc(VMHE_h!2mJm5QMTqC-R3@->(^H>TWJ ztv2yG4L?v!fBimux3h8E4=a*ip4;0XB2|5Sc(O4$r4Bfz^KhU2sJ&HAokkb^U*4B8 zA$=6@D0UNhlbj3FOH1Lo>_S>!>PBEJ_dH!xu39xVmHa9ji&oB!1l59cIDfhCeorf- zul{T-p$NOa=HpbBVZP==tR>1nG@tff$7Nx3sNBpx6^BUf!V^`sX7owDiA2Y!{>}Vr z->@ZKhAYECMXDZGYAOG?Ah1E{C}-BqZA!Fy)GzZB&=%60>D^PQK*b;>tVe(M2_=|! zxS4#h%$=0TrXA`(Lcj#r7Igdd=g^5SobP!x-UZt3b>>(H%5T@w#7FYE5@8cDB_~G* zxGZy#4fMFCR*{d-J&($JT&GX(vvCBhue9houHu+I@nX+ehQ@Ea)Dq^3Z#<#A`H*>e zQXepK%BKNgV@L7hTpr3H%S6TP27A{P9mvNV|j>7!cY-A-xxNy7P zUkE3h?Vo?`$jViE<#P4OrNWUQg;CCG+mc$?1&DI@qvArzJo|H_Kh@y0cfMlW_>aP* z$w8-)o7huY9cB2-e*mT=`3%`Z@DEODiVlcS;*}vS{j~>MW_@UGhl}0(0~XG74)Pn& z*pnq)!jM%LsuFIs_ynrX0%@a33yYP6Cc%MH=NexTM$yFQLsm?PC>hQexl%iCa2U89 z;FL%?QReJTtvY_i$7X|ZcL-}UHV)R4hXI>~r-+KTMk9yjqmlh;)GtPYUpd9C^)~r6 zI{SSSQd+grf{y?P%oQpl2wuT|*IdnQyiMrPyt$a-r%`ymytxb=MMrWYK@q7=hF+jm ze5tpkCDJd*W3RF+_!4f##(ZESSHSQ+Y?d8`9r-Y)+kQ?r9vH`L~! z1|w_N&@TeCE6#{ZxHBB?Ujd&Vm5E#2Ztc2&Sr|XeRV<_y$cyYP&yPwqmXSlZfH@mw zmtcWX3#gJNVeZYVJf}#?xG?({!%Gxl*dGx$EDk04|IqtU@+A&A0F@B*1wShhB=jj% zSQe8wTgl^{XnJwfo^inzW<-5Nef*&91>pGfKA+a9hnU#CCXT(_%gu&93@_oUjflU3 zmfd}q8k0;USvBf&vw8k4Go;6^{Vf!q2I5b%FOI!tv~qS+x~J$p3+eNr7mz{f0Mq_n zaGFGm+=KXqbE_ceQ}E%ymo3;D<~uTF*=KI#v1FfVR{O3(YMNh1yZ@suGU}%i^T#0X za0*Pwn}1#_xO}4O*skXl-yP!b;4=u*B_{-yQ+G2IF-4h@<79Zc`zJj8j{e4{%)835 zFXUvB+o;cL*HwBBh5Hts_x~~?P^r3~KsgfM+yn!U!?^N>1>5vL*z7S>fJOmVf1zYT zk_+avl)+uXHM7NkMAaW}4&?RVQ~&O4gPp7^l1sS)&+dK3Xd!iYmyTy>X&ETpjjzYo zcf#!2@vzF#2hRcZ)~H9>4xpn<0`E?sy>RVold8=s^X$iLm{ehxzYJ(y)C==TB7Ajz zN53nyr0H^eZO)E#QVQUW@<2(`Ej( zw5DLs8aOHIZxJT_Tm1A`gHge)+(*^sz+kcIP~HudQ|sVc{DKJpLugUD#YkSWEirGVt$Z1bX4JHRPi+sFj(;qj z!uIG4eZ`qPmTM(u7ef1+J&zvzN_1Y?wD5X#UL;ndk`{Ebvo}=3&&G4HEBEwmMqeRf zVc}X)@(J=EM8<-Yjh)?A%`>yC)?WAl6%EA`vA$RuU9kkq`K3^LN*UD!t6;AW_C>q6 zqVXWg#<2MYx&qvRv6tOjb8+kVJbpw`m78XjN>;s=%VrGk1${zq_BjOjhCI!jQkHH6 zS$YI#hLM`z_kw5b2l99HS(jB4-9)(tHN8a}HsStq@5l6*p#zeFa{s%BB!C-*6;tU3 z@TkXDPxt>gvlDGADx|km6p!WvrSLtH3w2NcRH==k7*0NJWP39kwGi+}<`w7i3Oo;vEej-UjSIcnK806}+f1_*h_Hws%&- ztFU|ToQZdLX|_vpU{qWQ>pqbZXnHB-BxA$mli6|D9e}$#&vi zc<;}I?CfApsn5huUC9tw5Uy45zv={V1nZ;lszBl_>GnlY$wvJpZzA%`Bc)*tPW8yG zMo**Rni<=f5~pXRKLfAtBSu2|am`3ji{wkV@Ni%kFSN%C+s*l4f8|+D%-eT)B3H+G zuZ{D0r+j`@?DYNp+9$3U0_$^KEDfG00DM(_3e+?B^b>5ON;9h%-3RXTJ!mEzrDIMQ!3yEa$p#L0n@xd;^er_x%v-ZDHBYprAowK^R&!}3y zmlOdzBO-K9f`dRcYZ}z{piO5Q&c|=#d?z=LC4B+rNwpS@hOil({{WEQ@34i)sNBEt zmbCC?UP1++!4G)6d;k=@nh^K8{n1lz!`$`WsVtvy*IcCYzaBF<=jwu-SecuJ z9|o6Pd`BqkMvpLSdnsY&nCwi>Keg>z`Ci8t(U1tO8Iv)hPRbavvKls0+OahCl1PXt z>1Mi2SI9)jM``7^_@BZiK!JV?N%ito(GuwI<4raGEZ^_RInw^??Dd~1NTDnG$U3=k zyz2kFqP7(*!Tlc9;b+RKz7TVBrN`ZN?e!dZ#L(y5^5EGUeXvV9v_zCu)N-VcEuES) zpyfh&pa69MC8_$o+eqefOo|E6rICjd>$COQsd=9uaoYdK)w{=A@0#w<=llKs z{>&q;?RvkC&*$^?dQVys`$i&MAaK^Pl_b(mheCP|$a5=^H*jsMTVa74xk2&Zvk9yn zY(Htac-H}pYK20yHPrlja2UZGm`(#xW*yV9^7eIvVrB?dI$g|VsLd3<)|Jj29;qQ2KM2l(NZ;80YnWIQ)0U5$JI zz@P#Z))HaODfD$#A5r}%8o+{m4{r81R$n93#gUy97sahEPBpHl2~5S!SnGnq9MzX1 zGjp>NQOtF{4Slw?TM9#)`bBE#WMAhIDZ^#sjiApwliF9+ex98_pmbt4MNEZc>Kb>^;)H{ z!9&LE__OkmvAVk3qn(Yg^=>UIL3Es8-zm8f$(^Tlc*I6_`&tATXvV|m?AGhrjZMqy zfSJdeaW1=r)C)*Tw2;)jZG98fl_9}!W9I3d$qBEC#2?>dX4G3HAra&+T@Nps_zpE) zn$osQC7o(cNl|LQT9Th4pdn-K@uNA=+*$Pdd)9pZ*Fct8dL1`tu*48;7ajyl z1nd>hnvi3)smzd7c)Od9sxArc0*u2@ z)nmS^t3hW->xD*vtEst+0XQ+p%=~MlUsC0!V?kepmzPdGdc>k&i1A2dW8m{4ex9xp zdOfcXe2?Vdf1Fg}#y=X$IKUvfJb{)T^PvD3Vs}-;e7eowM7@932Ne4{R9s1rz+Oe& z>cMTTP7dn3X5Iqe{bv>(tImGLg6J>(=YFMq7Zyu!w{R2M%rcZO2nA{V?7bHXk#M z19fuk0;NyER^w4xN<~!@C1oSc7msA#nTS|dO~rG=(zx0;B+(Dzu z>m)0zIVZbq_W0Aqh<75JRTUFl2M&X7YH@&@0cSJ8J3rE7{24lHY=>_<;6>@Xk6b zo>@|LvoW9NYWnjqQ1ac`H{)fjZ&W&Zj`%yBKhuqku2I`aJkd3O@0Pn_{j6VJ~(5i=|5~W4SJvF4X~rk zTq98J`ZO5^B@ma_b{b<@hk`!;7SWNcmCHP$Pon9@X<9>a@(s>j(W$hx@hRYOjhxD> zgppn`Te$#s)XuC@ysooH(Ccz0`b+{WC8@Z5UdSnBN6*iK%(wZA{v)z)HT3)}FQ;*Z zzn76KO2q)MKu{OJ8Oy=9DsaO*_oO!Mk$q=RI6&&n43up)JMkA@1u120V(+vGe^GXE zR=f6C_7}88fv3($-j6HjrmwBqJPE2Z^%U$o${OlvgF z`b(sS;w2L>F(sr%zfi;bR_Wv=^jn#Y*o}=%v&KMjrP(#Bn$wy^vDWVe3ovym;`E!( z8nxp>Ol6Du()!_1AlI1TQ`^jiaI`MMwwKV;hu+w@_tZSh_=W+xa!T_DhtTiC7OPzX z>#9cO{Pwju#aLZ!PW2cNS>Bv2zv1!;XXsXTvykBFnUAXORs* z126;c5peeMW*N4;cimy}%xvyi0Q{%`+bthfE~43&h)RBa$=K4AyKWOS@gq9L->-Qx z$f7n#AgG;2m)*BuFWWR-)$cOSqd`9#rb<-!7VY)@00DjWCvZJh(9O;F8+OZw{xjDl z;qE!d`D@FQz(r7OgocAasKN!gA7GKyp*r0#r|SJCO^7TMDdJ(ejG>kfd3s}C2+ecK0kY8i7KV(FURZh(%xod0Fg=dY| z2TC-0rs#j%aiN4g&3wxq??p0>oC>b(m0b2^v$Q5tjh*-Zaqr^>bU8(NE)nhP=Z*hb zD}RDn2A@rCh2-0O)KtL?iaZrqCD>9Euov#JEl4%R+^l&L3LL0RG(benDaWQjF{G+j z$Kd4EEh;OL{X6zmh+S0rl)VhBZFV=RII~fh-T4DRbo@@Mu~z}J*z6kEj~SW;zC^TqQ_F{!}ZnI+CWPH zz@Z)hPNkFj)acSyw5$NE+N6+~6kz~3N{2$T{(zeqkN?p_cA+$tqqe9yu4N*8YtCXF z`ayuKq@^V6^%&?~m-&x}3;X__UTVd&kG?=b)QkhLLoOOwICQZ9NgRmSm!zIZ@&a^< zSB0M25!Sior{;+#w54TWBdRU&H$obOfAG|v^9@J+l5gix&KkWnsWmpP4R?auMNPWc za~Kn`t?%9s)*F4xUW05#8!!jKWd=cS$h?+l2BVRbE5+wfRNr2kbMa259x= z(9q-L7uyrGu5;K8%1}|htG0w{g%*Mu}^M15Ce6f5T_6S&1J$`0#*nhwCZ*4#+ zmFMni_1fzfV7LCPYanP`a6#@|z|1nGu;rJ6U(uhA*0-@=Y5ZFzklF};f1~GQ^J;Ba zQNusoJTQx<+M>^dL#;vl&B;wkO=rus9+WT~^bqUgcI!heF;WQdYz99EWE!~jEMi-dF*5p=>bb6u{CKDSruj1ouS#aM0V~ zjo|yK8*)M=EwRIo5?c5y z>}8O;)@x?y^nzcv?jv#K`7e2?{Jmi?_bFJ0V|yBD$oqrkzSqhKQHhw zpoICL0`(P+TVljX#)i>7&9BWuIHc6_W^!@DeUUC|!u5Z#9m>+` zMfQ-+gka}O)>zWRp2-~Dg&SSsr7S1!h%pSc6w;-_6XIiaG~;=O!DE8hUuFtmJNOmm z{K;(BvA(49H4oU1qAxM0{|`0wzkG)_w3yUU?WEq}fJNTw>2B8$B}acJJ%pQ~9%>t3 z{6CEcN1{>zc3!rttsq})>nnCvr`XuSu2c%hOz_w-8)H1in*(eA1XRqz*W1tcYXg$S zZEd~^q`7tb-U&RW)_8sOPX{DM`!}M1EpDt`#_xMq`H~&($mJ7$M_8|kEdVj~fn9HE zZRCCmRr!FP_$D7p=J|ohz5S~->?d{FwThF^fRM-uP&RnF5#n}iMwhkx%cKU=OdrN7 z3HPEhg_wN!PZ!W3?ebER?`2j()#%_H_;jqxbfS1AzhBF|b~M4%KjFi+0+_Dhdp>QC zBynxnul_8d&@{Gt^Tph|v!TNjk@MhQ#A4e@6bc^!rZM<>S{|qV*t4V4#Vqw{m@>Fy zEnOJr@Aqvwz(V0}Xg1eCd>r&Wo6~p`iiU&K!?vz$ntEi!P~Mw4Ue9zQytQDTw0;z~ zY-`1|XfuG{(_2v}^SJ|X$P@>fDR`D~YDQd|*4$}|`Q(Q18f05*wMcBT-U2m?-ppe(H9(E?Zu{dOs-E|QIfDK8VzZwKhH+{wAbD%c zxft>cjz1_lIKeU%rc2`A9Jc&rX^r$X~ zY3MNnIBCBN=ogUmNBlpznOgv6XEKFsLGzJ=V?g^;GkBMb|+bK4ogGs>NCFQ>!pz{lKO^ zyH;4Mag%I$8_iOY-JaWuds*BLwA}X#FczK-9ce<&?DP{xJiEdEi9>Lqa2Vr_!)qWf zFS_H;df9nBR)bCbe9!=OV;`q(_g_C&Uzcz0pA4wt z#nf>15q{T7S+TxZHKq{kp|5sDi^(I78pRs*f0JQLk)oXv!{ZM<+lrh#-XoJCwb)G0 zax_AHfun;Ww=+6eKlCOrNk@s%Krb=FYCtyqc* z@CqtZ70gw0afS&ut183fXF}uM(}=If(}@=%oGrY>=2Zr^Yb~BqPD?Z@U|LmOW^KAr z2P7eVa;k;5;AVu8ntGtd`l8$$ztc3D#&X3wvr5Tj57S@m=zrhYw``8?Vd5XWW>MUG znB;x(9`3o3c;C#n!71(*5oDZSmS}+VjM?|psr9ztcN-<-icURnjjzaZ!%4d{+k%ZA z2`h<)ZOOKaE`?$J+kuNME0?5d^!8^NcvfgF-M5(9v#VOXH3ZS+IWAsqMnxnqox!Yz zh?|&?XduXxHCXW-hMCu`o{{B00zii-Ue~L#p5a)n?H#;!2fSzeS7~pLN)E!`w3u&K zvM3@dqW>GQaKj7CJWTrFK8I|nc?L(5VKgo^!jt(7Z@=87mf-+L|A*igmVI(Z!Wils z0=cu#?&VjhG4AHoTeS@ zZi(>o#`VKfZ5+koBjlHUS~UgCU{*x7Q*cc8azQfQ7GipRCk`H2nv5ry=_l z-f*J0AO`RCX!`RdeOqbDZGvZar>sxHOKGT)F0=n-aJ5g;S*V0OvoUe$x+;5B?-jc8 zn{oD!F+PtR_+7^K-klobT_F5QBc*QQrH>seQc7M>bmFSyqSp0!spdWzjTg(`fKo=G z&m6vf!$<{_H%?AgeXt(dfo4%oeT)$UvB%D){}MEnSt?i;tb>uG#>+x&nY9B0 zDOk4m%w5RVc4NIAr`G-2yA^&kz$-Y9!`sdGOp=}M12#K@Z_%xMtAo0Hb< zsQfY=rgnfXw#d)oER5Us7R)z{W(jRl=*;c*0ju+iTT1Ur!2J2$vC00pwWNH=*I&6i#++7h z=H-+rJQ~?isLB)?RL5uPh&jXRH01?V{Tf+z3w~1n(v}Vs*;)aNyI=Jm?uFq1uBB?I zjJO)71f0o?=ev?128sc}m;PncmwWd+iZ&x)1^mc~JO+y#NW;Zzbr@#sN3+_-IZJzc^Dii=TJ#6@zs_Nvbl210$zdqks}UTjO=8 z6Sev&NUMd%8b`TWlhaZna6dkvS@)FyA^=VHMe()rU~ob|@ppV#E8D^c&Wq0`)j{|AX)Y-3 zp}-J(+m6EhAQDK7?{~sXlHjLZRkv~|=27!rdzp^Sc49j;0i6h!CZ!2z zY6nqsyzR08gVMH{G4fffjnO)<2|0hXTl|XyLrENdZG;>Mtw-iOgp;t+m4((?VP7Xx zMJe`DT}ZSzI9;@+8HC=M@#dcQQ1B4eLMeeepud&%1tyn8+~I~0+A#)4wAdaJaCH8A z4_(MlTaLJTM7v=%(b^g|-v$#0RreGP69)cc5;^1)&J*J^O9$CnJNyob53lbV;jW<(_0I%$A<-in$zU#YaD46IB-ou^;NHuhQ9;eor=^xnak2 z)_+`*9SbeqGu@3J18x@Me9dM+n9`=R3k8s43!}hah7$w3?X&e;PQzPw4u2a97*VYA zov-WN4Du@`Qe^^u|q8FlY74`w+un{V9CG0S*#3!l%Q)SjLQ28QO ztQ$)ZelGmRCmQHFBUPbH+nx`f1bYLfQA~k&IJ>`~M?boVzvM1ZV*N z1*=0lyA0A-;OC-k@Xw8li^Sp{%_B)|q=UPpKVd~ZV(PEpz#pFuU}^s~h}LUWmaTo~ zlqqLC%4j@u$S}bOa^={Y=Q9M&+MAvXsdA2N@!CckIF1rLFxFr&(OVJ$>iC%$_Rp@K z;sc~I68@S}E@j_xV>T{DmW~u9%bpg}a_c;#6D}+qPHCpqi#`!-_HU@MrIh=Rr&GQu*_ZAT`>Plw^fAONFED^t*DZ$s z9%#x?GWcc(xn2~L(5S5rjI%A1AYA&Zs1PeKh@T!3Yc&#N?r)SnRitO3P|k>tARLW*X5s)agG6RF~ro1*5VhIn$5q9i0MC@n)d?mMUL{!0$j#$1_rh? z;Z4A0>pZ1DYd&ZV)uMJ*Ct7dz#%B!KGar1F$@8!)$x`aU!NP$C75QSSFHq<&f%vsf zF7{`>LN_^rO`OAqHsMi#;&M0cHv{5Q;FQF`VeFfDeID86(`){1NQ>T1Ik1F+`8G0v zLmv(RcfkEUqW6NpD4xLtMj^D+wAq;IRra`QRE}u%CLgKdn7r`J!}?A`*w|Le+)^$1 z_r9ucpx=_OT@+8rY^rIIUxsvPl}phVS;?P=01@1PW53f5`g@W8jYD0XdkY1kFjGO` ze<6&3rA-4}z~a=c%`Z zd)T{=9|?I6RJmzTLmr@h;(1u=AUXPAC`oV|M4>fm3sZ6(1?=ng;;g#xMtPks367MwxGnJd{aXDbgVBXctkW*}OhPclxaf)RO zj2VO~ZG9VGR!20q4jj96AYq48##hK>uX%hhY^46_9Nep4WXL6HntQxUXaOlBX_TyG z>~#;(z4_}60Qt!EhR>_F8Gn%|%a5%Ulc7a6;mwO}QE15%sPaL=-u|UE1LW%%=xq5d65V& z7^%29HI~CQ>c*6Hmoi*=_CP%!nw|k>9H^27CwzOPX&qQ*U)Qh z=t)4R4s>ZPlWSKOrs6GT*C9{AW-EZ;9-2gJY(}fAiTaJa51HJo7=0RmoZ1+(;NkHb zvXw4<`QA3HnU+3?crN@aaMB}K?m6U{xzc3bc5*RN;M~e}X*vK8bLuL9?eAFsiunY) zgvRr6-F0S|$$m^^`y`DVg%%B~F9;V>MQN$$1m7EI_I1kNB225u|5?;>e#$p_Hzm6St; zILd%~70qCr4RQ20&5tak@GhlNykQGDqO*}*1psC^tt6;Z~SMR^uqmXu{fhk*d)x zH2Y)M@eLGNka(<-gsxWi&D}DW6~(<}&8OT+*{E9asW3o4wbtTYFN(VOf}2g!(ugGob+JFwvg_m&a1Sbs7=6}*Qx)KDPm{uVKl(vX_V0bhx-c}4PcFAr{|Nli7l~R^S$={4?Nlx zE9-Fdb6YA8VLGr&xF@xzsh8z-RYSsDeP68STMQ1wMuO0RnfV$w0>_rzwe~BAMCMvc zpbrI++!NHOoKR!We3<#z@7sz~eJ|*F(S+7vsbMvH z*dhWwPSQ(|pUe@JJb5b;y&h9*N8Hh?^Whw>aYer zsy9O;F@hhpt^A)>{go>AUctPgez@L!TCmozTyq}^sDoTt_9VSw1rbu+g&Mw@({Ulk z$v285-u=t^W=_d6`pOGE1uMW{(9BzlATUaT!ORpMCtXeAtuI+6S--=CKmx|(hVIWK zGd=+~gBFK61+{Xt08)(0EsDq=6MVE(2cBI0SJG)L@8u4bW>#XRqW_m4mf7j3{40aJ zHuPK!k+d-s`xydM#i_dzs$J0=$WUE1)-Q#<%C&F=`Q)f9?5pK_pD6L z{C(v69Rb}h_50KLvRJ9xMJ+nco3Qs&|C6Y`BCVrnIfA<3@O9=*Erk+F>q^+!c+syO zoJpIVCf|>tH*5BJv%-n)x#brc#Lxb*8lj4$y1KELR&_ zzp*bzQA>vZ;pY8NZ}5vwg&#=$&bo6mU0bx~+7!6OP^ZFd(1m}PwL3vLs&S#j#lY$j z<-A-#u&A9|T>b3*Y;d)FTr;cO{r!Puv0a}!AR7|_0B?aLHVWSJQcGVM(?I-F?bilE zOat?zvlGS8Y(A9lDw<`vm%-v1{5`?xWq~CFrvT9oQdwl@V~U|p?T`-4liu3*>}Pcb zBrybUO*Q*L#WEa2Eu@_M#RWQrH(5=unUd%NnR#VWL!DnG(v$0*rRe@tvpd z1$+s$_P@`p0aq;tbvLZAySt|Syw$wqaPxp5kgU!*WZ?Yy(kj8F1V?< zqT&61l6ukDA+vs0vGczBRNL;r4P^+}m{9pd-}_U4v{jSQE6fGB$_l*9=Uf4%8ZJ4b z5tkPkCcthQ6y;7t8k{0n{O`aGe;0d!3L+*jwc&RyXN5GK^#Fa9&i^tS?SQCukPws6 zLi#XtgEcG=oky5&f5dwhb!wms|*R12=VwpjJhyX*aTL}WB6Ib5{&5PjHALPhb?egMV+rYz4* zkKUOS{7ufcVlHDqz?>*yI1TFbTMyy0Er-;sO@i`^A_rMsmg|NLltDPXxcBBb2jcoG z*b623pZ2ZT8K?7^uB#WMG`1$Kw|`5@^O#4qSwJ}L!75Z~SEZ=QQ7KN9-}!mLYaK+< zuf3A=z-qiLNN*5|ONHO@tXW-Sw*)n|7bS)GG zr`o4IJa;q;5cfxEYoS8wL@X^tC0K(g+ckcuW-e`oCOLp)}<#0 zg%6VcO3#Nwv76yj%J4MgmuD}1vY~;hyvt@D<`mPPaBRTL;uh%Vhfg=ea;xj}spvx5 znNj8?1TJKL(y~Bs%SHD2OyV8lAm&r%)C=p})d*&XPqF-;c6I|@q_*lo+>d-hFtlj` zbh#;HABRK{?Ywg16{dS|U*U<_t{iUR*lwY5+k1PpRC&_b*I*_7QNmX;gKnR>XN=VrG4Pj`FM>de4u(#wR>%S z=NaIGP}9Ml-4qaG+4DE}(Ycz=N$}6525yD@$6Io$i7zoZ=O$gkkkt0XR3ZH9%XNYjY5~{;$nCFec1<3wP5m^ZZVs z1Z4>nC#>=%HXWp#=t-Yv8dOvA;qJQHw&WLp`m`m)@3+&&nC=ilO1T?zic)|q_K(V0 zn~#sZiRC*aqXyTAG(K(7;x54o3Ok!h#)8(3BpSOM3bqzBnx!I!_we6lggaDA$1 zJaQhq#XD+)Wu3~G`H?v_oa}BxEBz_~sx?xty{T0 z69zRhC-hb3N7oTak4N~Xq&IA#0ma0{2O#@8d-974Vae6pM%eR_E#*O%`OWhkGC$;# zG#Wi4-m*zi8`b0k)A^+tSAof-7r+rDS9rgf)m3i+m8e!?$bdWnfyS=oHs zf7Z-dEa6ag5g%;*8ec)ngX)bn^;iAEW<_E~Jv8d^NrLOkopXUME4Qk0cR#CxOjsnX zXw7+V9TBG&#xXkOjE^BO1}hrskr=YZTtBvz?HAoI9-~Z8ip>Qkh$S|)_5l`Wfo}1n z$?Jo^@y*zug?AL+=s^t%-z&P@cs}63%&kO)x?@zb=qb2`cGfCCqW`d2%9G3;azTiE zRrN6vD&UIfJZX}t8Ms#35@QRxPA-ZG?p)#pJaaz3y#4G%?T?KO@59-|k2Yn&*T;Ah zG-m9y3-KMrx7G(DyX#Q{!oZRlY5ss6a|;qG<@W zpW(60JB9MMvV9btXhP!(RdGR0b;o~hH#_$v0;lPIFkvLbC1sejeGJ2oK90^2_u$YQ+)LfZy*@lr&SlXX)JkwR;@gEf&9V%xXB6B8M+vnKVqKKkIR) ziwyx^9Y{7S)uIl1f|y6#&EcaDk9LpkT2c;NEG94*Bi{l>Ot56ub2%;;l_S_ZwbOJZ zMtQ^l;O`c26?N4?btk5^ z76eh7Oo)}IS>){ZCYw3=kZz9=j|c)WM6+oG9g117Yfi+RH-8r(Gic5E@`+Rb)I{x= zH$60;$R3P@dxtft za|y^Y>7O?5TP$Rv44kuVda8Ao_!~<`-k7K|QHTCHrqWWq_j>5sze|S0(+wKYF2(TfXH`*i$vtZrKl_TUU2n}e zndiO7A0HT3O)w6o)n316Y>}Cz#^+p3;obiXO{=hPkeu?k1w;jD>_*PKeeFl(w++?f z7z0%O$47T$`0WOl-{b{vK!_Ss+2&)oQT`q zryy?l#4N~eL|Jf9uDo4`=%hG=2FZw?0fIb`i*^s4UmfN8r~|K{RgT&aDGW2NA|Fv# z=1i(at~2do5*3 z5xpYG`Nv3*b(GHP8!czGe)+T(H$2)a&p~#rTEj*QdV>llcqciVyML}8eN_VM$ zRO7rU5DtcG+D63%(m_C-Wk)*cCgbHyl5%klU8uP+e+T&Q*RB*PNnSAqD#gZm72@N| z$i9fFwGb1VeC|q*AA>&$KUJjGGqQc=nyIB_X4N|sG}E1F^~v8fZNiY&7wM=Kh5qsp zN6%42=2&PpZipKFVtMxD9ccC&b_qDP-Z$G4v_GVci7B-G-PZQU$m_;CY+Yu+7cJ^= zLhX8;^_?{TL#X^Q5dC(=g5;Kizjk&cSm`)jllFQ4&uHQ6!J26BtV$95GGin(BbRgpC<6dMq?qz zGTxVXYpi;L&km5OGjWUU4W@7;pCA6$?1XfZH&Ny%o6G)L=5^$PC~Qn_)u!v-t1|Pd z7k!Y%PhOilo@J1Nj$(QZRY7Eg2 z4Nzd*0N5iGTH|(0jK`)jtEXjbn}2fxnZKVI*_oo`!9xW90-ppboZ$PP@>QQUqpM9S z)RsQdC{ub1)?Xp(wM@`y)cLM&6{+R}^Kv~c6&8EISm;B4zJxW_@Z3NF#&{Ar;<$5l zIxpH95Ur@eEck-#{VTcP#Hkw{P&*OTLh@orD;#2dnA)@gc!C3X1S1-}Rm~sPZ@d<; zlj_co=sNR>r3|dyy8==I+GYv;XB&4_jpux34D?#!5^lDoe{_GKT1XVUZWYn^FyNJq z>v)NOjLvk|Ca|&3?^qwOmCIMrRr|)ENnEbGwxmY>WgUf>I*mq${)e@+nDlOfN_`-O z=vMWQ1_FM=o>i{g>;S*#CL336%XfI}EPN=yG7F60%in`2H_f=VDr8(n5?b#x@Yn-! z9bXO@R`3&|E*YJl1nTy)^&#p-_y3uPKCpkEZ|);oMI%k^H=mG?YY0*U~YQ*1SxidS6+sAOtYex4lh}1(S-vdrSP4G~!rolF@3@nq2(Mqu*}qAv&no_4NE+`YrJvAy2b$YNuG2z%i5D z3KQ5+=>@^8bd)?~M6(uKSBwJ(=@PX^KRH7+RlRriTO57y|u;{ zl26S2#@P~z%iwy_p2m$RR)7ImltH6DpQLKqJUU0Q*_50dZhlzVTH7^KC0k~&T|QiQ zcvt3?DuCZUWP||E6&qFN6Q{nN6Y;EmaC=CPQ5qQ|{aP0Iu-InZ1*i8+(X%K@tahYd z&1gV#6X4H*th=arUpjCtM{yq$dfSvtg<+Lo*CUh67sPJX z`ZhF+k|iuj#a83pMwW&M$Bzmjo^^{&5YPC})S0Y5qCNN{*!vQ1{=9GH&{EgGeaV{a zP9v`q%onV9SkNd@xF*o=jOV%dExLC56`P|FC#=GTeXd&5IeW>GO8(89YRsbZ4wAN9 z0fH)#;d_i`U^hHZPp2#%@yi2la9Bf|2;P`7ZWRGtXdJXg1OTXm|)^61?D00J&%-9C+SxM; zS%NFT(j1dYNt>cz^&V)o@dWpu#3`7ws7z%pm`cDB$)yRR(? zFpyPCpG9F@)HU^CW5$m){7Dl(3tdHOovT{}2J&7sz)`bvJbW zqNBT{G!M{}6nG?Z@AT-8bf0_Eiqy^CkWA7JJ)VZEOl-jSo`M$BKXnxHCb(Y)1)6w| z=|q6;Jc(sFQ=-L;)~{cfy{J4}6c&-=meK8^UwYajEt^#FO1lGpWG5XsRNcnq>AGar z7tl7gqhA*?aRd`5;|453K9R-?bA7K9@{#QTwPo2;qJgt3_LH^rxFlIS?+|AiQcLum zdYViA#lQ|?Iuw>g8)->YM=kM$^e zmtz^xINCl96fVJ0Kr}d@%VUELKVg* z1Va1Yw$89C1|j;lu)Ze2f*kGKxx2}rjNlKd<46@f6{@gZq~YPrce=SlHrDp2D5<8fYYU;1@n2PH6x{-s_mE5{H& zQkr-hqc`8`A^UTX`;GgC-9^Jv-S0bB6d3?x2Ee8_ANtwT((`o6O8(m-f%Yo&o2fUF zIfE)D`iNR&gT~1f$V|j=qp9Ov!4bb1FL#gfpBMab6&D5_roK2Db)^AlwwIp5K49h0QVYgAp{f$la!Z+9+(HWieZV}{ZP_kDKCvaV(T(_5JP z2&v_b+J*iKSzsUN&$QghM5^Oz`6uhRMET(3%%gIQqqO`0iR{d4lo$VO6veJ;9snN? z$xQMAa?H~8vqdCa0Hb;#|2B-p{N@xh`4v(z1-9R^gUtFwIt zU~e}whcxee{%1yAhoKQ310^_IaC>=8%SxA>4~k3rogDjlKaaxPs93A zz@q=4!ULO$Mn;idPA>PaTaB2H(YB|aW#V@9LDVE^b5h(eP(o`fKc2vg zd}MN%6sukE8gBSU*s@9bDB!|nv!V+QZ=|_U#l*C#NdrddcB#J-c&dR{jHl53(!5kU zTeTy(*F`ui6D%*WiLrJIg`EZ3nGav^7d6mVc9=iugn#G5*OSFo=*zOEy&(6m*I5o~ z)y?{?4i%+P_=qD;;1xKSQMM5Q8ke73t{id>S0EeEUXsrMarIKhq%2fH_q+R5{Y+Q0 zgC2cEgCFg#QU_Si$OK4^bwTZ~E>FY0G|enybv9-{7N@Gj%5#4q_&?!CBQbd=wjw3& zOr|EJ**tY8zA@Wlt1tCVwt<=|XftkfZCRKUNWRz;8>ji6=U;)v01+7g7cntZ{i585 zP1;S0Bg}~>TeE7t+H#M6x0$%nG#@5Z8~z5Xe>jAp?^HHu&GPu8-U6i!EKZXwB5BxIRNahD<_`%FctTaikXW$a4!eVdt3QI=7PWSOEYS;kU!#=b-*+1J5j z9n3JyzC54l{{Eil_x#!GRnyGp^M0Rmo$EU1I#i%r2yOnmw>!2^%}edE6ds>seucf> zzsQHs3Y6deUwqzCtjD$cZg&DJnW!E}m~e#3(q&zD0(238#EjQK@|H16RvP>!{gUYo zNBxYXUsyfC?wvjDBxats$y6}E-xBHoFU*=PV@u@8;{PVEKDFVfe!L6k#JVfKy9zme zOpm~L|)Vi(zH;kI+4Tp<1hgK=_jNqRJJ>b1c^ak&xuzmG@LQ^6fxDEe8!89*CV z+%}5Wy%fjMUutPkDtYUEVo-(Gy_5WuCxgJXCIt?u_W^WoMiE*l=>yeZwPV&hmhJCt z;vH>xRy?vaRmZyg})p!FBKZtzgDw%t#h)v&$HT(99!~qX&}o zE&B-&SwiD5#tmTskA=R9@g zgZ2$4&ejBQ*i~~SkIrsS!=I#+M4p6DS(RO-SL+p^Fa4TZOOeC9L@=`dY3*tx;M9D)hm7StUJc*c)o)6q!Bbc&BMOqw z@YAipaW&+!N)Cihz++m>6T3eg)3Hdr0cT}z)SL8AZ&jBefbc4Rn1^~dU33NtTW8TB z!H^RMmYffGC*xREXp6#ytQbc7*^*eA6C6k+e0dO3+nyr?pC|f6wl+{o@-FyYj4?os zSYV8`FD7{s%o{mAuzgwUZ{cH00})%{Y-nw4&C4YF^51H_Wg1a}u$EeIX6=wyJi=~g2G|r8>n`6!1!s9mj?T&ALm4J5EoplI~c6PsTdD>g{ z$b&OFRsZ_T5;P>sh*C#rPB}D-EGq}xOJLZI&BWgu@7#=bJ}_dUph>Qv(VyH2`=c#2 zdH^eN9{3+AGy8Zy7pNufy=(i`HT}NHI&eS6BVp-J;9?6fA8R&oHrUXs2t&NQcG&#` zLhbY9-Cbm~UdVo?vtyoXGjjDUPLbxl^Ol^W(&iWP!D#8@NODh&_vg`ZEx@ej=zsv> z6$#5%ymaCJ&0mL?8tt>WahBa}d6Ve(0&8`IvRFLDCpkD>v5^OV0mwd0VX(MfLg(}{ zz7bDw)&K7&i_`=Fn5@YfOlgs!Hs*fbiWT7#vzd0jbiBqH;3Td`Jjetj6YTlv_t3n( zC0*CqouL&>%*N%tf6__UOQ*$STUy?5;KY=3tOnaBl8bhOIp;<;x51}tk)HdL;%(*$ zKWA58Q|I&SZ z?eNOpkhuz5pBdf2t80#_MG*^+jyCxjt$kv{M}YvBbS6+5|1Z~Hk|1EWl~xojVaU;4 z9VozuG>awOd;xiZzo_iB3#DooX+Hy=#=7(W`}0t}8C^aIQ?!)>T54AtY?(>OoaIwN zb?CL1CN%!D)Tf5OF?p4?T!m0>Hs?swv`zMC!B!S9q+8Wszi(UT~1JxDA@O8aCdsrEjfwy_BJ&auXRGIxomewMn zS*AL;aK;(z27h4i>@%nk+L|)|4Wq-iezq`OEd_Qw76p33IwHxPNvMmRI zFb{fl3gT0^7dDV94%_x55Nxswa9Cit>Kzti2cUC>=yg@w(tmcF0NCg2eP%OuD0~!2 z@KQWqYR7pnhOjVAYuQ*0(c3p|{`oS3a5nxth_JixwbgnZvpavFl>fa{v`$Q9_u8x3 zWy)OeK=0YFF);i`ZZ3NSS*<8~uWq+>Y>lRSDMuEyd~?KgE9^qZnb3WhuBZ7&>m9Sl zy#5vLM9b^UAk}yU*4u0kzOJmPeXyK(&}GnS+BfZE>rQ&_k#}N3&IfFyj>U3f{DN9= zo|AE5s%P&X+;mWZWu0UdWX&482Yf;d*F`NOG+moU^KIl7_sVYI&cdh3!*8O@eb*}N z0v5>2iy~{>Wn0YduF}^4u4PC+y4?U1oT=x;S%)dDP1P%kHlKf`!b?hSt*UDznv z1-{G~im8B~LJ_z-q;;qDQ^B`r{WMkohGO zt<^uLm+Px9X5%eD!JQ37*G3w50sD2k^;Ns3CHxgOg5W6EHo>7AbM-drV*G}AOhS6r z>@&2&Wtc*f-jSf>u>2Y%H~%YIBAYQX+dDsc684JaBban_R2u7UyyO1KTkBTS9<$`8 zD3sJgu$GZ;4n55wAO2D_uLJcyHs`Wv(5uyfc7ibwM^eAVZ(2y{l}ODz+}R?0mXm0K zzU%WaM$K;Cn3Z4+|H6g<8S)LhtKmqhouLJ*W*8AMeeKJYMybPc8%*|AE*GJs!?+y{ zRdeC^)sZT^*ak&#&xZTHUQz9qP9aaM!Z^UKjoMM%F$Lgo*|pcFS_g|gH13CfmD6q> z{6?sdXQh~8B_p9%ORQoJF}0XZ7WL&MTQ{EC-&@qgmium9j)T8M67P@%H?VZ-5PGTop7 zvOe}l?TUsdmTfF_2CsLwaMvP~iZO#+hZt+w$8uUK??%ob9?u0vqTOOm{at{(0a$-B zBNiIGqR~EcWAZ-?pFP=>!+)OsG4y_sDgw=fPKQx49>?|}} zptrYZz;igxfDO8}h`hS6NheufD>mX4xZmSf98}?zS6Cl3!o)wr24c?GbGtO{pTSJG z6v`)UBw&bx`fZ;GCKWR-IxTOR<*jXUL;_RA`+Vrb3XbdlD)JvG?J?tY?L}p>mHQuA zGTw=#t(|A~F1S$4`xvDDK|jHK!jyhct`2b}&^gi?>`q7V%CxXd0D7<- z9$AH3af?CFHYj=XUPa%Mx)?;vo`S_!_?fKp@hZHG6FRSkH1BDP`@C8{$Yb438H|%5 zYqeQrleT|?rssEWVE3i#pZph6&b{Fn{E9sFxKID`>pFOrUBjSOi#u1M#doTS2{J@*B zT5e<U-ln$F;~#;a~`!%1kMK~+psJLbQ@sXa)IgOeOq_7pD4EjGl6S|^Izdi z0;|(5W0q5I9N`gW5+zJwzm2-8O~0*94n6-GrCs3eWl)Gu^Q#IErXPj3$nDZH_bRN#I^#D*=pug^NK7U0AB5h5ctUL%#!YM zV_sM`!bx180d@Os6V}B9;k2={e-h7|Ao|qSU@^j7uFLvHzEg~CxP0xxso9!QAqUi% zqrozC6R8Y@-T%b}%`Kma@a!|Pw_x|jNerXQM(IO@%`(KHc)G;e81Yd{F2ty; z_ChyYx!>2bRq{^{seM%8pasmz)4;z^dA= zRtE#U-*B9Q-KJsAs{zP4Hf~#yY&vP`+qY~e@r$!9@*265+zK``3mR8hFaK$?W>i1o zZepvB=_{4#|E5sG&AWg9>a?_o3~@;+N4Cw8p1Ht%N&_w{Jr4M8<6NlD7Dlp)nO|VO z_Vgi#&Hyy($>zEfy)+SS*WcD4`$ewFyKLNR zIEjB|sEl0`HVIil2Ho{_7uhi3Tko_x97zHCBh)9c&ak6-H=Zx;&vB!oqnCX2S)Aeb zpV`3m+dMW>GNcxUmXGiOKw)S_umxD{Vl;SQQlxAn=|$f&@S3ipo0y=e4Wwd6sZCuQ zPz@Hq`^0RFExkODMGjhGp$?()x=&-! zS0(^|7P%@!E5JrwK&7xjJepw9k5_--;~KHI3w5oL{EF2GMfSYMNE_>VmwXSvKvku+ z1CNXM^E+fC5Q<@3;3kJwEFo+^oivbgp}5_O>JK62DhL);`In0YX`fzs)1jbXD^!09 z+jAbcSg9ggVJBK3OA^A@k&Jjlo5~Zc*?uUuEy&mrOS|TM=Q7<=-EWC{KtuXmTiPf~_&WWq^Au^FFMmg06eY>GDG`^<0+e2BWYSeM4 zvZ}49XaH<=5I#oUmo&>KkJ=3K>-@wCo0r+Wk$cTg|F(%hHAm)DUD1jan{5DG+)K>= zxa<1h-OK|U`P5{hWoO=?F|uq{4UYLb1pkA8ZTDn3x$`*w0RP<4b32+fSYn-9yI$%_ z=ltzPYiYcdRqsohun%{hP*{P19&D=ecztpJ!cz2$m3uIy5z*}X-rHrWdWf0DV(_cGbLo{^hTp**c&LrHUlWrF^AAL* zUF8}xm%LK}Zt@~0&frM)PyYv{LTPH9I(ITsKZ=Todo(M2Gi?+_Nnq{?Y)$C^ujNI% zPau6&W=>N6-*%n-gVZZ>s}X*`bpKi7qB>mOmzk8_H3mA_1J7$~TtWR~q*SaDShQwM zR0n$y_dyi$iy>zW0-qPbaVMTgjKx4VVtj`Fk^gJZPZ|#u?xu=1PzBXfduZYwn<7A(#)?F7uZpi~4EOr#6_#=DyCZ-yPO0xy|fdja7_8XwuCS zYyytwL#h4iM8Yl#Vw^|R)xNfNFHj$kFFC6wTaKrxQ$ILkF3Jtdl0VI)U3!DhvTRB+s;y;#)7w?jTldOi8mkE(<_2 zV~P)0dK+11tx>TmDkTTy7PU|CLOF=pMR<>}iwxPeBK2t7eC$H`y;qLGz|B+1%k+&{ zp7=Rd_o5_UI%#rTR&UZt$~>lv!!&ieil_ht$^SqDfUb<*=gMrA0WMqk&=tGBYDNY( zjEP0%;&PEc){X0}BVO`UDD}a_xw6Rq)c_!1U0PDqK&WSX%JJj393l&?1_NW7aEE79 zOzhUZmO&jIUU9ECDIvG|ggmFzfp(;I*Uf8w*X26`|7t7>&OwLqJ*x-`=1bjdNW^DQ zs{|w$w8zF>fbqOo%9`EhyY}m}4Zr!RVg9DoY{JLPO1-GLXZ)HRX)-C|^2AA0e(wTQ zN#|lA!=O9^ThZcO1vQS~F&#|Yo&V7|tq~n%Ac+|&F-lMt5^io#m}bpx_RaC9lI$Ud zy*Q#3&`*si4+o4-k2>eQ>JPrH!5HYMy2=s$@Rq2`{>adJ!LjJQ)%<_qs`t8vR6%aR zB?(Zhom-T9M2hDHkKIssRO=#a(4N@k|nG zp()Ac*Ie0bfm=Mjy_A``yT!9g$Tgo9mZU-b3H$l3 zv)9*8mTqSajfGr*BB*F!2FBJlHtd`=M*W6wTRXz6$HKLLj;gQ01*}I(2lp`3g_Uh- zSNG8FH7zb}GEHH2^*SmWR%4N0)YX0ZoL;Lh z#7;sFN8Ae?yE^A((zvh=glu%2=xXfCE|tI)J=xu!NxIECsiL1225$qeP8yjWr|MeXq0oR=r-} zOP9JLT~cRASh1m|So%LFcOZ6Z$)W#~;<_@QJY|8Z>Y``^KRq(v($qT;t*in!&=z&~ ze5!&34Dqjsw**Z>=p&Ogj6z@TlJRM^K;RaF1v|VDoC8;sR`-eo+4Khs*8%4z9WCYrCc` zZ9)l`|JHj^w$Xmg;{(@F5;(VIgBdf2vs>Oa>GLZW7&v?bB#X`zHn;E;*ZnJQIGZaa za>%@;((u{=F@UoH;y0xNpxCQ^fJsA}LI*)Doq1zc|IzIfE|hl!D4=Ed729(|jdkx3 zC^MbH=9?=ajO@rQ$etIo1*Za%aXE^ns{2dBZ|^4`TS}x3TdZ;_Y&9uZ&oVx~F0ce+-l+;Fjf z$ziV+ctZSX(H<<|0;E<+f7`KyNOT9>Q%~nv_G>MpDd)QPGxTJTotzRH`X$lc?dg()facBMdS1x_cx4^=XBF zTv_0zDMq?&2hP5gIVhzP%3G>I^ECL)c(r+)s3p=Jp&z3Op}`;MhJX2HvSW&52Tl-A zipl^r_i!u;sHOfkYmG&=^K@V?CU{V39v<8C!S}{|SCvo{BX94?-o#x_@N8>laGkUzAjl3-By6`lwya`=%Utrpyt`MOoV z&tGXb>m^Vd{0iN_szP=2!kAxFY{Uw*^J0kPA#lr(G1?rtBAA0b_sy+{1jHzSZ-^aQ zFP?GJ8HgSH81Pn8fhqKLa{c-2jgec$-uZfE@RL9!I3jj=MsXJOHdKIc1m<-*>1&7T znB{l7_^XJ!UssRnR!}tbI~)o3|CWrX1@}7dQvkp7>@UBw`aq2Ek+iegt@hR5tU*fY z%#PBkhvu9simH!EQj{eEC+$CZ$+O7~ke5CzH?JP#g;+Y|W`xJCPQnO?t-~qVwR*^M z_2{3wL)VjV{QoS`L42 zKm0f?JPfobaMw|4{uKb#o)!8tVdbW=$;h8bWu-XC-@2)TR-k~~AjmU?$N}Fz8m{^s zQ3k%)6}$aR**Q)9C}MW~3*3#eP-h+Q6~E;Y=Q>9@0el24e4YU^xyqegKTv}?N?AoR zWq5@=P;vvcU+Dg9`)}q9%`q)0znq8W5Tyn?#)rxFjeTd^^e#an053w!keTnz*X2U| zII|zmH(isU0!_#3)WI!iE9Cy9ms|lx(bn+!r0q{X$71)tn%a%XpbBrP0Ffmw^_!k5 zt!0FN_Ho*DyWUG)Wv+7vqb$$Q_1f&FI&zu4e{9tX_SJi3@2`gwCKuFyn`z7daqNFF zCImhO6&%s#H{Y?I{?eMVdTl;&<)DK8+|EmgK;-E9*1Z8>>$<@>XYaJRG^@|`ajdDK zJR!P((13p=MaKwJxQ9N>@`bS?AUmIg!CYL{JXwy85qw1s)Ck>oix`t%dv_F#uU2c; zIlpo04~QC}-~N|qA+Vp)Pp!KWx$cpDR@133XWW>U%lM0uSM|puwt#Q9T!is{r*j~m z$;}#ehe0Z->zZ;qM)A6F@%mR`S;<7XE$ifk9m8nQIkZ@W?m%VCwAaDb@jA(^q{I+vmRgv25CqR2Y8erKCh}=8|8vA; zdsj99BLF|(ZATs*0W`-{aCe;lBdu_lN?b|(q`rAiP1R${@tIc7bCga4gHen2`W^5zrX&+R44ig@RRp4r}h4;AHip0p&{>I?=*tu8dn7CGQV3t_= zZj*UZ-xe|?*Pnoi1#n?*UPE838u#I zvQa9%=HX;7_K8bFjZ_>#R?T1ttYmiA& zz&u5xeu^Nf7R$1t-I);NW*+WF%84amlUtDsnUM-RxEEnR-f^6R`r63H>`wjZ@r6C? zQw(-~ea?y3>(R@O_&3I4x(q6P5BvS{Uuo@o{Fa|k3*^UkHp*RydNs=uaSnUK;Z&9k!K+AXd=NYhBFtj6F>n6J%2`qb5ko#`4EvEP4*SHtc z1-&c*^V_F0&_B>D_M~J+E%<+ZEnn78ZGKdM?#d3oVFZp; zvAQRKzX@O`Gn4>U=&Q2;jGLFSL_p+ZobY=TY~M^9u0DDk?3HT5oviaZm%SA9nCKii z?i4$qcEP(x$6q*hxs%a*q-a0fyZ`7~r2uig<``pNml+-Q`fE&b+7Oyu`f9q0N>!Os zOJUa)uW#=-X;04>MNCQcz#*_}6G2?Jd>!i6M~G!f)G}1dReaT){QK%!+IV@9TBpJG z5<}i-y2E$M9j%&1Xr24+$L)Z>cg`mX#?I_fvpX%jwzz{1=?QuPaFfPi9>i24f0jfU zr+jdxCDi3_weV#;^BApeReae&0T;HPQ!#TDQ3z~{Cb|tG1Ql-b_?`XGzUK{dGu%CJ zul~nl)h>~NooBnP9AB!}*kc&E$fX%cmR>k+FfOIc(*j~92sk2;9w<2Dtqy^ULBj%w z(l}TFMi#f5T}0HTkXIHnH=U~Q?wd*mwnn4I;tAIq%0qwg2#ZxCUu$rFT{-;Ze=O>H zqKEvYrrUd!a{32|hz%+k>wYbg@VfCJ@$#pOV*&v&59xYN3wV33UC<$`s_XRf-=LOt zpMyROUyna(fJEg;Zs_J-erFc9RB%%7N_GbfLj*eIAO-tNfWdd0YYBAI_?M24m z3Koc9Fgc6rm+k*^3DFu07z7Iz#aq|&>>gLIb(*BfzY4nhK5!ZtukQNG{yvE3YcW?D z>b8lcy?=;aOM%}bTJa&AH==;#0%ThU+VLLcZ+6D+Rh;k6*N#E2@|U)ETxZTRXOe^W zW%wu`_byt*DF@qe!JT3@$~?~NrWnz^#WIdyeXUI4cC$bplRlp5VSXze6QA(@*GJ zF5hex(PUB)s};j#pih-=yXu~<-eAPfl?7X5<-6W6)<-Xz$UBCddpdKxC-yA%z1n>x zp`=$?NVbH2^*a;@!t5J`k@w9R>^FA?X&i&gnBArhMCjY(cYv>s>1IH&;+SI0Bd&Pl zgnb3r75<<;Cw2I|!p?x~nDT)obTcQm2dCiYxMW^h70&7Ba1815}rNr!C#N_pKr2Uv+C_ocoS?9*{WIGI8e<^X<2%XVgDJH ziN?|Zq!H@8*~ZeyGPvk=2ob}jOLAVF0bAI?t=4*nj6TE$QJ^0%L)k`?XLY8_h=jtp1F*3S$MNi=k zc{y?)%3Tm1NVIIP_P8kNCoXSYC9d2q6}JEjvIfn~#z8!-i4dJ(V> zBOrOjNEuKx`g(+nd201aWJ{nDql}kTDHWTo^R|cnJN!=TPVDY2;U|D$SR#7Xe*Bbp zzV~o_w|4kLg@l*_5@FLx`-UV;elzr4qJRHq-$<(Bin3;9t}DKbT#Q?R49nPx~TWKoU8+QofGiW=JQsK zjNKy-ycvPZ4&m3D%oNE&!?AM`@>8=RuYGdmwHm-6?Q4ct=&a!2@5?f`bmItZproIN z42MytV77mlhk_^n(E^rL&q*9)6^z#j&W~C)iLhn|OZLIjEHjmZ@8S=x4Qy*$ab-ax zNDo(C2=rS#nJtS`*hF7@`(Q8Y4wp=GC!Z*Ngh>f?;LV$O%b4k4e;&+cbcd6MrtRBU z-GRA)kZVwnMSfQdgYlG{CuI}lfwQp za52nVUJSFXq=@VHioHsN{#LyxRuS33$QoW+3x8owmVH_D(T8#9x0?4uFOW|PoBeiH zx$+w0r?BiZcwl|y9N@3QNkXPMo{O}TvY-BEw6^+y1GJ0%Kqfe7ipH$s!yN`C>6AZM zVutEu9NJv_a8d4=j?CELQeySYO9>!CjZc?VZyKh2QuJN>FfPPrl5u#-3CSwi+Gm53Diz zsHO{<^Af<$#-zLA+yo?(u(wz?M;p+{Z|9{T#eS=fU@j=^2me%d$<&bFUYGLaj_rJn z3LCk&i50t=k&%6*@m4)JPJ-htjJ*fE{OsVg9pTBO5_pvE^6;U=(TdSnyth7g>tj!JXq_2l~^2hNY@_Qu(Pjn1hhKKV~Gc5aBCX zOB+6uhgHInV=GGwFY0{}fS@i~1hQ^y@r{;OGk>b^g|lg3(g42R|A5`b(#wfa{I8)r zc0ndp;61NN!;|A$SFYm{mc8gGUL7d+n*MyHGtiB$e7$n(!2BtSNwLZF3`FflWGt@s ziIZ6Hw|34e8_40HGqU+WV!MYcYOXc~%<-SOBfOO1>HUZEM^Xu`gJ$bddef9M5yrlO zUsAO@y#H;ezT1Cm=IhR%>uhoPp%C3q$l80Z>5;g8Dp#l|4*DbI+o<8Aee$jMy~<0^ z-$(%(tdCgT1dXVEZTtM@m-0=VL{Q!O9Z>?$M*s0O=)R;eZ$t8pH#DKjybjuL`Krv<0rznla&}=wqxo}(*Q~~6)zObiNIp5knK{*%8JC{}as-IpXqg?@SSvv4by`Ajt+X2VPCTUGu%4lmLm> zJ_1;519LaxsA4-$gFBqhxCfbKONhYuV6d4|6VS*pWMiUe)=I^GxkMdTEXyu`Qni*E zK#|*DKhw`dVNvHqL02K~JTaC@YqhVr3Fh<9767l*)l2hbd*ZJlZRw0Wr$puvNbuqM2*m)^+>SY>LnPJEJr!MRPBqf%X=dCZe8h_*v= zvZ$c=*{`x{*sW}FXxEj45Dfh^bBLjm$W7Tm&of}xYT0W zPc>l_&?M6{(E+eQNgEO~ZokuoW^vw;Ip0#&HF?_Yoh8GwH3I?WwtVpX=T`ivb>;J! z1!E=x3(R2W523oNBI%8sootiogP%PUBqDxMpCUoLt_YxRWupyl;R0sSuTqT_gb+G= zv*+B6%nlF>{=M1vK=x^v>3~s{|tQINk?2}hGsYu4?PbabJZ^qMDM*O&Bi+YC5afPAP{$I+gpyQCrU|<~2+?w+V zIQ)5Hz1+80M1xukCwi4g(n*le`Z^K9+im9 zdUOc2NIH)}+~v9|bH>SyYm7^F#;nQU+CvB>vU#&3cCTh+uwfhW1(Vv6@dnMPLFvn3 zgMKe1-iR0vb@c0}0WZ@LA72%3VA8cE8DGRb3hZD7gzRVRrp~E^mnk(ugXc`R>HLpx zFO}__ofL4Otx+{vSXQ^W0)=9ZQ~WXg$9yya_^^8LVRbSaSO^zd0T6=&8AYG^g|}QN z>#Vw?6F*lky}$y_t_oN#0@h0_!)f!*Y`nk=?3N(VZ`4LH8d}{`gDK3Gt2OPsT&BAD zuvl)K=)uJkePx>T3=VK|s7xoehgx;barg>Ru4l*F)!slr^4{uRgGOE4trka2{Ab!9 zYK$<>MY_S9^$eEX0x$hJe1J7h6nPLaTzh=X-Pa_eB=I!`v&~O4q2K@H9ngqYd&-^( z9Fqa@8sM&^8MfkvYRHMRv0<-v0Y`t`WPGpXZA@JxsN;ZHGClm&Yz3T)_Pf6M5*Wp! zz+aNu?pjwD95??2%I%W9B0!0dpy(faVUC+5QHls3@AmR<{#uVon+24l;KuTn(3Szy zty@Rrv{sXdCR_E=BdRZa1kJw(t>4*{^?Wi3f`cNqBM;0;D4c1M7{OO7) z9rJS1j$fptDY?Iaeg6aLP>T z>9AstTj*SFH+gKE?h@^c+K8pS?DyQJy6AnCc33z+*3x+AA(ju0 z(gb69lZ-$Bmg)jd;Rv8?71ckIzdiw2>;@| zj&KF*g(ZF<`~tbU2oSbKe=2_l0}ZL*L6g@8H|b?dW$UIc+{5EB7M2 z>)_6ZM51QB#~l%BzO5=3LtGsd*5-r4LRbe`tPw5M`z#Y>bT6>&`PI*DD##6a2^?q{ zuQbQ#0(ZdF8pCB4Z6dVeyOaSEz|CFnJz4DvYB}C*R$}p1fXw=F17J(AbnH@Y?w?W7 zm!jTP2(dbPXaYK7k%>c%3k#0&p;oT}lLc`d>}^J1i~$$g6@&5686zvNJJB5TlqR2>|0=jR z-_F`TMKd->9AFQZn~kA_;;Ul&KLEXU=~=4*K?eix#zH0~naQd2UzdU2vK4bY$wjn1 zKe*Nqj%tVlta8WYThvV-(pkP$`kiP!=1J1I$7x=H+^^pTVHbt`N|~M%Je}}wk5jdz zNsD*98$_Ay(l%2TtEKeOtorAN)>73av$uqp>;MO`4^o%F8WC(FcN!E+vNa<03p9sF zJ=tS|u@ntXE1G=JBF4jPTgp6FhE4#x{n-uBlI9T$mQJ5i$Hu6}65M4>&(DXWo_ zKbmz2n0ZXVM6eWRGuU11x-+)BBeUv`Q0}$~+C;*=!vvTm$AJu@p)Z^7X{(uCZ1=YZ z@@~+BxFC4waj6ZddUdEGl3zaK5@PVg5p3*O7~PL+rhW5TBl^W!xB~vu4U=Mlsr8#y zCpouXETtVw8eHhmaS5Kx5nJ6U;F5G|XD)bTg zziHA4;v~mKN}oh*;JqGph5{5ztvXG;k~5YR3R9z=C~lF6J#;@Z?Mb3Yop{xJkzI-r~t72C~8XeV3c6onOU=YxI4=_ZZb zdpVi)r%@-&+FaLfFBN%rok!IxnI7a?q(5k~Pp{qAbzWzkY+YN|4XI-C&lY97N?p%f z_CG*Bd4{A!%2mJG88;nlFu%zg-kunzox&$=-urBKR;&zoQL6#iOWN|I;q}W7KOQfG zzK`u@Z!5cMw}FYO+m3bWoZ=0qprZiWq5;%ao(;SgdKSyO97WWdsRW=U@H5qd`+h1n zsmovubu4^Wec@p|0ej-eX8-D)`)Y+`>~XPW^Vr?EpOF&e17s#NYy#wOn^q(EN{P8+ zI(}E61yfjeJXpU-o|bU|x526oR?lv6PI>C{wRl(43ey1%T*P9#o1psw*JPG1X=~#p zXhA_E3cSvWdi#*XDABrZ(_fcEGG6J$eUG1;EW{ZJOovbv1}x=S`l5(L?C?asV z7|C@-wR$Ul`qcpoQ9_@XS5% zK^W$YXi$>wZDB0GiI3cFbMjD}4!tR3Qw8W=RF{`-3fu6(R+{c%OdnB5Tsqgswq2(B z4t(~SAFXLEK-$6(TwDTM@%~zPXio}vL^W?OkQnS66JWwc*)4UwZXSt2SGHL(x$`(B zm)3w6bJ*u5gfyL!%U6>%wHlV@b6(_otT%8++Ayck*r|a9L>G2q%T?*c27J zgAwP0cXt-v;L?RUyepej=KxVpb5n4ew5fKHqU zwmc)h?FLMOlr?k#ml809h$sY~6f0|JnSa&siM^$pAl5i1n;;cYVmRLkC+Tz+t`7ug zY}>tg#%oMh4t;!Ps~}5v(|sjvx%O0#|B#K;F6cQh=HLEXu|jZz6!w85vBik-@K@_8 z&s^lxF`kg9l1gh?8Ujil3(V{fh}V$ zRGy#diy%7B{NBM#oC~HN6Qz{dLQq@*WhMcKkfE!F`_-Yi%I{*Q?;VZS*)N6=V9nN+ zHkacmdt-U^g;xo(Ys7AM^R3xDs*zLB_5hmU~dYA6w8ruNaN~ z_br8a5=!9*nrw<;An55cHj2T3M5BO9dZVbjQfPRoc z2+$qFP~pvwkoCBRr6d}c9zUX#gRt|5B_Io$L&lckw*oI?_#oOle$!Rg#V6<;ALW0M zzw0k!mdR&cI)!LXws=30YSR%EWl$mS(V}~B*#=Sc4|L0C%9WKmE`GhCM*-d^31|+~ z{7|`iCQ!)TM|}F;y+0LlK^Zoq9i{QYSDO4L?=l&Q%bm3PG>^TIe<<}(x+kE<9uHm%XZ9@>Y(~aHMvj$zoNV&`^Q7K< z^Kh7_+{oUqZKgJSCS2C3MR@?PV;7%41y(zG+71$4g3pQp%VHt%M&!?kq-$vr80|pQ z6d6L~2o#`NtnC3nOL%mYd(wM6Ja*k#M}zlDQcCizS-(O7QE)`{=+a4V8T0!-#-{8D zwP+URlj;Ghj?%ZGf)HZZ-K3V^!UYK1LT#&VT|gMf${m&5lhhdLZMD`$thYiu6qTE& zVzz|)Y20^K=N5CC4m{jwhuH`CK@YG#bEFB#W&i9H|Ne=N(64GCc6<9F1Vip?oD&D= zQOUjsy2CA4FZq~JmwaITPFm~<%$@8%3}0yY@<*xQE8IFYp(qG&z>wl0p!$$r*eLAHlH>!325gLcZ%y~c5nviUB0Jg8 zy(7?#-MT?72ZDV8bjv`x9_hJnriJ#qq*p#U^tTr_JK6bHrS|H99Zt89f9V}PM^**1 ze+^zRGt0$IkDI6N;toCpdK|eb<{4|Z1-=f3Q1>_8Vs@HWn~^aAN#oHsHTH*f}(XhCN<0;>?W_KFZq6t_C&7z-T4?`W)w18nuT zL35}m0$4cqetcYpnSH#aT>rkq)Q6$F?7DATznn>^WDwJD<9bZ|tok=I@wGl5&Z}-U z3;)Z-h(70%yxtvQ)Yi(tQG)B_N9mEMD%UoUvx`B$S`^H{Fz0;e1eHbJRmEhEN%?Be zwAI~16^b_6*4tT|PrPpPZTwmrh?PiehiLO$gJn@IwiL^DdToG)%i-$*e%qtLnsLOJqHz=FGX!mYCu{j=C5 z2Pb4pHX6+PgA#W)f$gV3Y;jeBp6sYpPw-_h@<`I|BpZfzbY_tU;gGgtC9$O|FJiS1 zGanfN46#ya3bT`h8w96zpH&~TxapZ90kC8Bbd8w=rWk4s*|+ZTVAGj%b~ono!do3( zG3|R9%3Y7h)?>Mz&Sgl6jj`vPYAh^~qmi%AWTuv@$Ej$2sv)8)Qyi+q>}Whb(CdC~$h@m;S@l z^#iO!n6v#sW3r(e)$+4G>#+95bc8r&Hu{Vl?8ksdgR-Mn_`L zdbcekqOTxD9<$l0ci0v_MQ?GLV|IBPH~fbh%@~_>=UcSzrl3ZQ58Dmh>pohJJDl(} zL=cxzKAR(VtFdQkldUnMAjjUdlsY?>xsM=79WYsjOs@INuF9c~LDRq7Xs#9UDAhVl)81bkBy7t!Wm9iyAHtyeB7>h;e00396;8{^;hA#6O#^aBB2Wr zEjUQsI7n}D^o4vfF_x%Cp;J8V(cCf<3~`*yzlbFbYW-54IIIscux2I0hhozdK?Oek zc>*Y0ZxNsp>mcf_{UZ}p?z67HqQ#r~0&RM}Op>c2ZY{qxy}q}F%z(jN5> zhmU0gYOlnO9oV!99m3>-#1LwDCKA{m;)qQGo1d)p!aUleZY^VnYzdOIz^FgK_(rawZ+2TNz<$W1x+%l-CunQ-*{uC}K`sX>6 zz17we=Kp68TsVVG7)pbscpmirce0 z8IZsT_qKz%^v+BAfIbZD-ZosydUUDYy40ql*zEO_dXkv@|?U50^dvxHePrCS=^<0>phDK}F$&}Ej`TJ`6(}&Xu z^Ot-3Z^1^?Sf8)@;ekU6=Yiw2swLBY4d2_|wqg`;u_v%i^82uP2ak)N&Jwk&{>uhT zeTemHORx|EE_akFZgSMr!TxBMfD^LFHx9KXg?iobLN?jyP2~lxb zF49(W)qcd^KT34HgO8$KecR&O6?~3*Uy-_fn!WqeZ;6RMU@f@h&`$JcvSFT9(=fzT zSbi?Jan;9WR26XAPqi;!2UQlH53o+gT&W*=(RyF;p3z~D@yfZkF{dZrY@0_cnhmg* z*(a~-7MP$!E;;V*w?s}pIM=7*Km>w5n1OmmcQBgaxkoSqnZbVYw zz zWr;*@K+;+FQ<=X%`oZBO>u6JT=NIXTzflgs?+v=eJmq>P;}5yvJ=mGe&%N;)nK3?G zwMApwig^4m^OSm!%oX)%cXK(o+thob$}TaVf-dtrQt{+(DNjr2H0k$B3$lLP>BvfN zy5p$?;gB|6C*{%$e9N71sxwhTiUl{s2l#a<`N-Efp=mtRhA0ud@u>YIe{<{e{#MB@2vGf%KjJJ zI+A80V7W})>2N>+l~!B{z7ViWTci9*fJ)_k(D!-<@0|W{fyxk5jkfM4ve0d%IE68Q z?PTFLDH^5;xSflNgnOhweOn3tzkkKpvX%fTZtVfzKCKMsmrH}}`~F>}g4tbhGRo&4 zEDkfek9Px%C=>#lOR1R%syOSxL=vy>GN^Jo_{2uoS!my8+;7wT+NWq2+o1Pr*5~Bz zQKGub9+R_;%n%^XQkqd`>-tZ9_kH4$>6m7`4anDJLo6lRCw!EqnT6B1PQ0x zCR?8PSmuWCzSuQ8et5KtA>pkRswh6J^f4gVKlceXB31Bm-}GF-Lm?mThp@GNy~xK( zCbFu|_`5}?F8~WV1MeWsh}xJ{bSOkL?o_+4uGabD1YT`|NiWO$&i+kU7=n060NPRh z5JW2N%XPH@kxySv({sRkgDC=8d{s(uEmC~J+u2JE8HbC>PnP^y;25S~>+412pXsi^ zzAS(iWKuv~Ux!5P?5twN_L_IFF5<=T-&ZJ@{$JT(~AK<(E97KF(5 zM-4(B&7Upr3`lvy3vMO5YSf&;EQh6^PiQj>hi8<#l57w&KLBnN*dk}@!+))A6XWlx z1%qH#V93x0(zv1-YU+;q6d7@CFlR+|KFc&iaj(~K;1eIxsT8fYdA!zLG%`Kq)Lg-( zT+ls`;>4==+>B9Om;}eOx6RJAiXq&*Jn={tf-XVJgNH{7rq&|Ff_jjco;gf<_f}Rc z%tbiOK60-_vhbFfFE()}hPG;+6kSe(Ej-^eho!DA8D+{%;eEJlzXHq4hnk~%-rzE7 zc~f7_pW{adT7*GG?Nmlrk$0ljC&`G1QpB*(x`45Bc0nC6CrEE@qcC@w zJNqm5ezB#cbPl(R!@gvcKxV9K8OQGwtyFk|{mx$T(?9hgBhB=cbcG`UEbOabeKm+Mkb#T4I7K4#r8$ zTnv8=KC@xXFgI$qg2rMWS zy}_OrMzlM0?}@7KA8M-$vR~f`_sGvbr1f!@jD2ltR7Bq<_|uZ(L0X}*{RP^rBc~46 zU8_>LUGkM^5gUjL=nmTiBXVem77UxKC{$yXsE&U>mcSiE6v}U;d;E#q1&*Y-5EAh6 z*S-pKE36I8$VKBY;bg5dUy@C0?oMb$`u-B4zN`f=T%-iXQ~vOsH?-bL`Pvu!a)VI( zjOIe;S#UKuP~@CB@{QY{oV!iLps}!xn`q28Zd>;i(l=terQU|%Y($#{#iNg%v0;2N zV%UshLmW`#2W91;^+mZ{51jzvp+c$2e!)R@UY!lmM$2l+*=OR(#y+8!^|A+Pu++XyM1ywp~OBe;2%?XTST$lKId^SIdapn{4oh#LhC-bvzkDyVwBPF@fU>7$>u=gkw z$2{bKRl-D?gzC*~ZiGv)O`gtOi!?zlgz6Yq9)o-U-Gsa$)lTZ41(qCKr%7kJ{y=y@ z<-_q(~k0YSL-o$7R$K&_W&9kG25NB@x2+fXo$z@d?;d=YQgo$9A6gw0LVv4nEv zJqPNCHmbZ)W}V6B;Bix@n}l(9McW!PBFx>1`!{y;T0?}z)Fs$88BrC3rUpA*nn_N! z%yq%f9TpC+3KT}$Uin`9MT%rWm57fPcn(@-ntOu;+}ptzg%!7pJnV5Vf3=dj+$-lj`2k9B!uIWuD@$ zDE`gboF^HQU*J;T+Ea$G#f03f-WkPJUQON(M0oM@h>|sVT|KQ+PyIXQ$8`fmrP8SW_-t{ybC;mw23C&(NTX3>6kUh|opY5MK zpLP<|Q_<{ye3GxqFrTyRtB%!i{k*xIe%x^K=jJuV56L}(W`Ui%=#V>D{A7v?yx>vU zmpxx&pMp1YSXaW`F_+iRj?R7TVP}LM+fy?M+oiLQp7MH>>V<4tVlvUmlJtx)Dp7&Cz~deOHG>#g z4ABEW-3XfEsp#?G!(X7Mx!W=2=rb!&`K=(-xY5k|Gj>8h?z%;#;?E~hLlRwu{VmW_ zD?>5v>Cv2hkaX#1OU_?E|E)01>m;{@&@+?oTt`Jo ztPB+*5TkxM0^4>idbYsEPju^-C@JKap(39`_6QMAG z@c<#iNZaU>^4ow=-l+eJATpyl9tojneWG*!HgrM2if^ZxX(slvgEo+=BfG%Q^{&v8 z`*_iR<9C8OE*qJFfYO=7-Of~YVCOO)IG}O^Ictp;tNQkWz|LjP`{f8L+AV}B%Esl; zKuz$=il~W>s_+LN45eD+w9Qz*({G3Q>}Sj62DVo<#+IfgsE@Cke2IFRPD;=_usv(OVQAs2L^MCk4^;HSt>H~J#dM+i~zdR&;QH%Qxi;;NM|5wQ& zEExY91U#P0rdL?>;LIn993q=4<+cLvUyR0Jo1v_}b+rVSYe9`>qm_d^j+xWLuQSpg z3UEx$=TKJQA+5T?@?{~_X;rXu&D`LQ@pJLJa-ql3$8O$Bi%x4fx71AS8hf7 zdALu3hH3Yf#o+wi)=Te^ zaKX)`&&vkvR=4=c-a}_3e8RU8=F~B~?wBKm@Gpbu>-)3QZ`AF*W=tj9UOSvmb4rkh z)r4vByY>&75)sUag5>oS-(z2-E$#9?tWCXYVnS>N@~YL{76-BpQHX_<9drlhffoPY z(!|6J5lmC2H~8J%ndoR+`pE1NXk!br|5V)Y=9OV#12Bo-;tu)Ld1NB6h2DFaS`70U z=4YpDlW_=ou>~7EyU5NEq(MgThCZG5Em49jg6c5;n7|mg^i3Vo7J&%Xq?&6NaobH6 z>AN5|iGV?j$)ioVwruqskh@n(&K&~h(KD#HldQCW^WFV@#m4eFs)u?gDi6WLysd-E zoE*kY#OaCLxUYPw0s43nUSG%7h;Tskwt|({KWtrWycp6~0RpCbpXGQ)gI)|M;6&e; zOLw5G=$39{Mu;UHBzP{VqbN?Bf*-E&kj5kmDx)Q=u#Bi$=>>Ka&W&0GR7BkJK5ED` zECoL`VOp+4`kp`^oA{x%@XzMoz^n?#1h>s8_gW6N5wzqKzSJPHAW-)empRQ2b&Hc( zAxjYqp@A1#E4?q`(MLmEryL0Wb)WQ%uf3D@JP0h?g_6Y?!U^4$@G^geYh0;EBJ`Ks$)~ z0lY_TMdSk7uT09S!()0==-xEfzP+3qMmP=(X(jP@Tf0_bGS|weER7NSW%{3m$Ft?P zAyc+?9yh&fJ=0+{!%wi>d{=9tiQ(@Xq50|iKpk!;L`uN*XYNnSh9ajh#Fxd6RqRsMFOw>7FXmO?izb^pW%DO^ zy1}mSP4MP5^`1-8Wb4`(Br!On!qi#Os`fbX0a)Gvsx+}PimKm&+SqOITTgOImY$8A zuKa-u@-97Ri;7h%w-NoNUPHT?Nl$;V@^$@UeoPnR)^$^J~N3_N^qmf~Q$Q#5s0oBBVoz;*SN7(wg}+ z|Cx`IY}856&YoLi4@Ilp9P7=KliO%rMjo^nNJ(DcC*Pr%=qQ)04!0uXkj=F)1e5o8 zFvJvTCgD)21eC;%m*GA~P6@5v_&EgsmHOBM)_y8Vmu|Rl==Nw)7~Qs*%!0Fa`aZ90 zO;3c_lE)t7tzOm|{_+|JPb{$bnJZl0j6#|9GG$Af`KF29-QK9P0U}PIrVAN0tUsA} z>Vps7g>L(3iS|1=;B(j|VzcxpaMXJJ6m)6oWfB%zP>4ZoBc75K{VtRYL%y%x-!*^G zQSyX1W>F0PNnQm*rO%B{wL!#Q)%`8atf7WTV#Y7=OUCuSyL4;#U_XEU{td5D5*jpj z6QM%Pei7_=cQVSNj9prFq5Iom)-_~)-2mEs;w&Fn=a>ZN4=09F1@{oi5*JZ8;Z;35 z7XVyI3k|G|UZgojIXc&kBv!;-tjTb-Bj)h2`~##1H=i}#HpTPZW#I_j{+cWCS!q-= z2AgHkS54kmj0?d_1+cuhMdhr|R0-blIiJZM=I-G7JfWh@=x6%V<;eS%!NGK5$HE&% z?ZTNXuVUkI77Hw;N2#oF@Fxe#TPUqmuZVvv+}Lmzrp zV&$ApXd)#<`eH@re9y^Ga~#qwhzFg2I5fa@8@sLjjsQDchi5nvC*2SlB}80g>!9zi zwf;lks;`+`g-JP@9G#&SIB|z2C0a&)r$#DsPY6@wu^#Cfn;V&}-awmf7WKQ;ZKe$r zd}Uo3)nY(D3WnAx@KDV^KXp3w3r)`E#Vtp^;D+0o z2n?dfArZL^i86<<{F|W`ct@GGx@b~(F{dsU|Fa7eCXa^yTE$Hp^CAj zvSB+^Zy9ENE6H#l&dFyX{W>1?liFM@andpbU-y}X9ayToJ<}1IKs_X$RMk{f+#_n3 z_iQ0CYWu9#*N`n76->GCdU&0sv5aj3dxypsVI7}shH}8E7*5_0UfEQfyu{NoOqVN9 zbqjqJ#eMWzYkFl~b`+=q-0c%P+ek^I?iWF>hiIIra;qd16`n95$0?$w+MW$esYq}w zRhH~ZJpl*HM@JomdXO&}+%N(IZ$9_EM}$>PtMPc~y+^^Z3;Ev^1kO%$@JDVkBgwZZ z30*Aw7Z%yLcmgfR)VT#9<4Sbt9)&7lav!BC-yS}0$~0yz(mWPt^`+;kL+#^Dmz=Gd z61WO`@x*?z?8L~8rN@4~lHe5@=bnZD#h8TzJCFQBPhO6cPV`Aqty@BO!1)bVT59v! zX3tTR+2^BNaRp^tL3n$KZg4_9w#KNY^GU3FL(O)74a?KW(oWMt{F8NwwWSx5I&c-D zor{|68a;_Hezt`H?X_qAhW4BCn{W`2cjrSFQbE`*q^1ZDq|4RuG&{a8<&TAgIs;3+ z3k=pCFIaAQAd{FuSbm-G6_rGwIB{;$7CzQV)zW__d^{37)l%t2mOIEb0UA1BjPL&` zE(aWwB&0iY1L9rU;PS#{M27uBW9D{&Q)*jr1?$VLSL(7H6-cBs1o^0}g&il#sH5QD z&$$LFr-hhUcGq5Sn8Vp&9+8erhHOU9hdu~E20vc8u=>6aVBRF#kLXf#20Od^QqB_i1wr##WoO(BqUU)7Ij<;&vZj1gb z#;7Mm?C)CiwvZVf5W7%+JD&N1{M@G;KivXbQ_`)3NBRR= z@dkn8;dkbtjcX^p z+XzmZ7J7#PN0|MzSc;mQ(s1U(CoYq`pNCmAYish~E>9;1>^#rUMNZ?5a#`~$Mw;@# zn-4IK;0`;bh|IHl3SuScLsj z9=T7Z4;u0yepz)z3I|=I(;mYgM{FW^OPkN~tuApdd015VJnZuftl(I+O3p}$ulrfC zS8MHf+8u|{^PN!0uZt^2$VJtbkMln<&ZV}5;Eyx#A*_w!MI=CN(Zedq$>D@j^v1$Z z8&0;|_Dbp!LL&M^z;ZIl+73kk9GwM00^~58x03QE+ z!B|Wo=pl!QHe~nCANonSVg6-0TTPw}M}diaoiUfGr7P8bdppd-cede2FNDSn2Q*!e z0U0M}aL_edK+$stMPlGJwIARN2GCu~3C^N|jpl#_XX6;hWWCKVG1}VXp!LqAu|YgA z_7f8FYFgi<8=w6PpTtP?gQ*pewD0?xbQgP4DzWd#^gNU#?$NilwU=Y6_O%PA?L*65 zsaKM*Ki97T4bTmEuh9}%vS&U*w*UUOS&NOdm%j1Js{$namI{53>qM5&%O&J~MMuTD z!DJMV9Ke~D4S0Qf{F|e}+qJk+ubTy#qhO%W+GzGEwI{6(ZO8n|sd`X)ey}F;+1w=n z75;}VGyPW1)vJ0-M!WgK-RRkYTN&mCH;gj@^gU|w1lX5s&@1Zf(()iBnD)_TOj8Pp zL%t8_z;UF5GzwWJ;vg+YUaZ+K+2S890y@sm^w<0Yutig=h090W2*E)$At<_V>uu4O zFl%OQ9x4|5m=I}>#}w`mDDadg{|U_}><6IwRb5Z`|HGFhV*@oSZ@DIAOSi|kSL?^i znq0a^VsH;>0=gQ{5Hr+LEZrm!PG-5S2-N_nvcMHRqo?_WEv;6Cw+a}@F+IfT1OG)RuOk6UXl zJ0g+k@gi#E$z`p#2@}UB&+-hHt?zXa6O%V~u~EwMv=lAD)VFi@C!e~i;X@1S7FC4x z`Hmo=E6SKeUnORS(Mz0!z0^+;6=n64%Zv1_<(IxtCTR z%)l28fdqfT)MV+q+%!Hw+UL~^lILr;mbkbR4+61iV^rB8Grdq0xcu1*iGwcdKG##| z(Mvm{El-N*|Iqf5fVCAdb-&p-{UxX1_%P6f_){@YQJG<0a{=+%a!{Id$Hlfny1&A+ zVCJyX->S7I9UYez8%DgCihpeaV4_(fZYNZ&>bhUQQ-?tdS4G^sD7C0|#X%e8 zg9xMT6$vpa1IRirq{D;2)5$JXo}$K#n#LdqP7~I99TZ+%yts$^A{2j7n?Zl&P%scQz zWGRum;A99Ay_V$@Q308=T`_XtL{522ll0h~)+-Ty-TDsjtDd40;nro#@*`0gr=!r{ z$@Q+ev>@X(^BOCFuyL;`zpNC307mhpK?7H#q~A{ ze7!{Zw`T#^Tj^1gU&y+UFzIjQ<#pZtP>r&g)7rv#WBFeXQ;;|i?Gb)j3~C6|WVgMN zFQInhz84b!s=&4{*7r2VM0g#*O-Il_0M-$CiBgt&9$U+*&g=T8(45oU=~!g>e;^AU zX|lNo09jTNKib59JcoWXSekHqc)Ha-x^k9)-;n%ep74n`()5nwCF<=;_qM=#2>GumNi~YVP*QG|RO>HqVp+tVy|Pl+FLxad{<{s=t}@#0t^mC*KN`gB7Fa;ZOO; zNcU1V_^oe`{3ff1XKmgcLuU%sh5KQlo{HEJb!2;kyP`p^mYp3yrv5ssFbmf#FqzntzpD|LW8)i*c zBFxAz$$8Z&DgZ5*Hnbo#{a>2V^BRl_D<8?x~sC`SO>j5U{kLMxL2q54L5 zf&U)8KIIZmD950Vqiw7eA7Xqasa7Suz-iTO!?P*x;zL!4W}5?pEE+jw$wpB$QN~*l zZI6*#*nIC=mKl-~3cVUtWg!`XPtqAZj<``c>ViO}+;)3GQ1yC?uw17fleNvLH==1T z?1LbZ3x}m0og&2aConxaj7SaJw9(d<^eIwx*f!!oN#+>xTG{OH55hWggAOEy-sXaJ_x$+6%IlS%X%J4BkVYt~u%#9*Q9{eW<;ARg zB~hAYFjxq6H?0vU*w#6ReOmS2Fgi7^SYVWEAw7ujz0=fjkcR?4iZ7^ejty$YTiT`VZ{6atMl2Jmf*8&9SHupkN|1eX_JMm9GI-_g&lc}{% z&=otg6^-f$=Go4sw}dOS+HJRbuIXx5e(8{LS}jH%d8?+XkU17ybhEl+Hc4nTfuX|H zK)u11v*Uw-Y-h}>6j=|)9Gmap%dkX^Lwf^>(A7vU+3ymYCZZgq>B{j>Hy&U+tiZJa zyU>ZZ2pO)Pwogsyk<>o`LJo5if$kI*=p8~`7bG5~ev(4jaRB7II1wsEL# zVYGdy?E`4Pg$j=YI5T+a#3_pW_P^Lp39KC0tuS(K%w zkGCcM2XeV<(*{f6u<|Ib?G0S)Vv~()%?+0Hf~Igf4brs;3u=5rlVhg0oLP!0#9mo= zf$XCx;Rdyu#vFE1QVC&CTfp-0u4K7o(RNqY2{^Tj7maUMXP10sRb5f2s9lqW1^o*l z{smi;++~Ub=I%gK%Ze@0S1@&baIh2~W-mCVnMPttozSB1`lGD~pHJ8QC1dDZ8bQa` zC`mTAe?};^WPN^8!}YlNrJAut{B?CXoa;c|-;{~-8oyq$=_D9d4-w5D93!v(m}&i} znQ%~o`lDb%ErTIg5xMhgw^M`s%iX9S!(JNo)z!_G2$i%4p@Uml!q0YQOf4cgC{cNJ zEt&D*sK}uu>h}{%S!}!3{O@#P4Se;d?jT&?O~Bcs08oCj`bN}1TvQRrIxu?UOlrp) zB9xzNJ+uldtcILhKXM3DMRI9Z{8Msf@Pm|eoa+O+LnpXn#EOeZfcA4N*8lwf4S9(n z*IwArLy~FZpVxYg3NcrY)k0<+P_uQSfkxT^)+%b&RNPC5hg6*O-2kbn85vM5Ko$}! zC%P*Iavg8Wh~2!^P((;hTqmeh-a4%rDdG3@|C))t;$|Xy>$JI;4_r440}in9&gFn) z)lqhWsX!L*PBz!G`dCLje7)X&%8Wk?cXdpg zjtQkI1c!IV-k)*tPWa>j1~^;eU}doirlkTg>%T>%$r3}llG;+M&waHWol5{p7;AZX zW3!^PpVr=FehRsh_wswyHdi%6Yk^hpN6`picBTh6vC5gK3M@PF6iP!mn#<6dl^{zjo%e(~X7~pzJehug) zLB0NSdGPxcy!lie=8~_A)J*pP?Wd%kn5Sq4htGJm;ODb~1DHM`x47?orey=4GW~(q z(?fK^0IjUI5m%oo=~csiJ+&Eg`&ZB_-l+zNO{BDo|6_DZOc_p{A_bnH+~SnGO0Vrg z`px0DQ|6!^A_~p*rr%k;aX`DKIGC@T_asML_nf7OdzLw$&#u4Ccys%(A%VPzZ$=H$ zvWYa)TMk`id=Kp5Qt3F|AL&~kjk?JoPuKQ(#-MqFe_*qhMF;1yBEC}XZVGk-ifMV6 z8S4RiZz-bb>}`ke{{@_y*5o#Q+ZbFm%f79D$*`BP;oqG!p?<5mWv-5SOA{E-#xuKJ zWsz0fph=1KM_v$%n*EmB=xJ0ace{eSyeaXs98=jKSk;3b=>_d3`f^DIfCjl7yia1E z1OVY8eNUsG^P@)P{wJqw2#&7E9+?iaUOy{}1?Lc5Yf=%yos^N@;Mai2Q1v-bj@T}B zWbOr97C`s)+Q-te=alHz3-(&4>Fzz^>8$0zFOCttm?b5rW0i?!~RRIL}Fu?B- z^~LebOkn$8vdQs2#T!N+f&T`wuR^k!=!D2+5MHHMI25zM^J{!_dpN1*E}^l}YzM1% zz4Z4xM9CZ||8v-``iP55w*VOZIqW!KL|z4E_?(rs1`*u|Mfv{L*TsuCunJT-DS8#|#|+0tlWO_=xcG(Wt!plaCQbW?^PpFT zm;Kh`84sJ=K+us9s0ce+&7P32^szub0|N&-SndP$#ga*9zDv)^o(3t&_W|$teDVg! z|GM9)aK9uf>?f`SvC16wE|8_IvPxWT?pO!~)0Gf^=6roU4>4h2)IDx#Fd*_UCu(oT(JIF@b2jKM&=vu)n z1u!K?7~3@p;ooMm=87Yw9~Poo#d3pGH1Dp^gDa_N@33A}ky^4kZiD|m=zkZGli&R# zCIAixPb^~K4-XRulKSO+dFn0c>m7;%S1rm|RicQFx%e%%?A;%o1F9=bBfRniDTibS zN~pK6-4(0{lf$(yC4l_E+q)p$wRwC{NUXg7bOZetC~2ZIczur-nOwG-@6nKo{l+@MJ~$Y&1&{#P3+Dj{yLp|oD`75n$@O<~N9u== z_181+r^7spHPA%r7smd6QT%A7?YW!0I7#Bdtcga4LIu0+GSc-f4K4g@LeMnaskm42 z_O7|!{0{Vy#i)x=yFvF}oAUN=`umn$ zJf~j?pF;Q63$BLHqc&UZYO$r)h`Yd>>dZ6&RKzZezHgPI9lHXz7Q`=KcrlU1L8RSK=gyA3EWTWXBr5D%4F&8`^h0bn0 z9VZPNB~CnU&tS=PF;Jx|%76cy{Y+4uC{V|nueyHLlZhZ&_?;+$TnU1YPb^B2H@pIK zcv(iN&QPvT;%ZD+y-o~zPGw7d{@KpW?y$x!Thx)I#a#TzdiwG#CO=FlR`(Y6 zRX8kj?G)iFgz%E?;%~! zumG=U!bQMJL_OXDVwiKXrCRO+zL3)+s0%CFd%V;{Y#1yxgjbS#_?t3Hz3s|0IJo2?$LiZ2$C3x# zwY;Kqe!TG?@@bWg;nIFbCGYbiL%ntak_1jq3`2WEo6T579lDLImO(rrKcc+n9|52N znatz_UDVTYN$?Suf$$dq71jZzk7Ikf#}PBUHV>B%k2yE#9~e5Nrjh>Zce0Qbt0~m7 z_IgK-PS3F(hQ}gy@>SvybbOH3NqltA!G8a%@LAg}F7MtI*|zw;5C9D(SloBzyKKgxwhvjPPkd9-_6*mP4H zk1TP0006od?5nY_8a-;l6IyoBT#iNj2>>MJdD8&Jq+!(B@lC_`gWYJCz&Vf=Q5g`D z#PYqRUPkl2LRdgZA~gj&^*UAd*}o&YuKZJL{>l=z+-Jce%z@O@)q41oZ7a0O<|`1eJanXxebLF4C)+{`)W!*i44H^gX*VpY0bO9_AJ6$mO(YnPVnL+FA`08 z0i65&-J{sCxoKGFzWEBO=}Rx`Nljgb`wJLmHF1t=hJe&zRA9>3ZFFBWobfHqOyuo# z3WREi@svWQTE3}hyYE)=jr9eih4^sZX{p%i-qZlBUZ zQfAn$o}PJ49*OotF&hUQ*aAYXx7s20jw%K%T>?f6A7UJV+Fx-(--*)?%Ll!jTZMS~ zb@!NjC2+N7q#=`$t`#m1Y33b@hwu6wTYpcz6;hOgF}YHK`FMAQ9N`U^hW5|zJBI{2 z8#&0&gVPirDgaIyz`Zi)omGYHD$u!x^zmK}@o^}qQ(COdNw1K=<_Zd3`x=zfP8#Fv z$3ud2x|2HP&q`tgw#tju0&NOdgc8I{Lf)E+RSv-q08K;k2o_8~ctYrHY@TmWGV~un zp;;gI_mmoIyL9dlK;e?5GVI@&3 zwth`f%y4x~%^mCpKK)@*1wus=Q)(-24t9$9UBGIERhj@&!hcq)gQA5x45u&)S1cq; zQ%>SpHIS;YMcCAKz^6g+>5E4H2yo|)`0h}5EnEjK|puU7rDE$o$WzS8~tgg4-grwwco@UCHD)%%$#GUft zx6nseM<)6n5C?%aW%81Mgq7*}daFM$;`88+$;ZO0toe3|lcFFC&tz@`p3??B4eW04 zcGbQ(=s=Nq>itdA%b&UriC~L{h>=B)p;g%w;xq+tWm=H68{dSTntv>UE?V7vRRTc7 z%PT(%31*x}?oHK)h7S_h63z`;jL7xkdHznIb@UT#8IpePaoIBaK@wOot?J3c71WQU z&KD6+7m%U`sezuRg#~M-C}&X)u%X`BMZqSnXU`;*7o7j)GG!4VyB!D`W6RsN(2JzKToNXUuYq*7zd|N=HptrtPL3ryZ?c4Zlf!prD z*tcZjQKC>iD~DKF{CUWnkl!R_=i-t?Euef}f8l^)jrQCYs2YFUO)1yRGa5D0d6?Q^ z_1kJB>zMATFUY2N*h0169zf?yUA-N?J518i!!L8#)m|C0sa9QOD^zWX)pLuGWj}@O z^g9~~q>VS=#jQZE@{=o5Z2I1{z*O9;wC-n^^FTYkz%z6aSyWGcbL#qI!48Qgp7k9S4IP$o%jyh(3 zEo!aUO*e)Z`j6n`>sd1i5xGDO_2p6Y#v0V$uU%elX%&kYlN5k{?Z>gPlA4Hr;w8pQpkam=cGvzz@+(RZjVtADPL~x=lPV(*0yU6=R1ECx}7~G;^bR(IEuY? z;4|=D6uElGCH!3`n`aOGS6a^Iyg^=&kOKH|u^H8!(sP`5x&r1eST8QpY=|EXlX@-| zR@y+r|1f=4=NDV^>tfH31YP!f;p<+PO9$|hqf zk4=KKM@-CKO;#J8*OyLTzsgGS{YJ*KK=Rl2*DriE_xscnb6g((=oF@*5MJ@kNMJxX zDBC1O_TxnC_*Nd25E0L{-v(IezKpGFS_o~l$3s=|!R z@j&-jd=*Zn8J0>*cDwr4Zw-IW$qxCXWS)acTaRc#ePU<0iXkjO6sySNZ7t|*M_n6; z^y)|!eR#kHT&vq`?Gj&9q}#Fx6Kk6~G}ZqZ=K!4aJ7n9x#<>sI;l)B3)Op{pgTutC z&Kd2)f&o0ijnSc~dmjc;Cg1c;TmvlDF8{KMuhEAGFRXLF z1hicK7EW#_vc}ZENza=`PR$4|bKO>DlkWOWc|U84VqMW|7~j&T%oiLf26GO}NI4pb za>$lA(CTd$1*be!1u;_kpMvhv#Pl4#Tj{m~_lOZk*8dy?vOJRcBqTY>b3E3iB#ZIR z6~JP4+~~C|KmQNxZA*%`YXJ!lj9KV;e-1B|b~ljyXgnumk!e54sPdgx^Fq5I24+G5 z9qVc-X~1X@A26&_20n3a|;Teb0un#9A02O|3Dm$eLPz@=70G-n=Y$#%c!} zPNvLl9dx_NqgpuT&sS?N;Y3WHa7n7Tqz;-A@&G&7gb%@vT7AI(4C5JYZswyZq$LxRM|Vx$fSA+( z>cTSyz?TAyrLKW(kItB%-XKeYCLpjDZ{-*AV_9a(hEyHi#=91aMOexsywEFf5b8lZ z*SJe{qOM6u^jIhFN9H^-WVo?`Z5(h{qaroWVD9IT z*Dn^g;+h1`lAiSk{iT}IxPv6`;1taHDD1+vwo=+ z7aZDIRBANU`qD{QHk)g#HVoFP2~7OzgGB%?*c1wF%+v2WDY;pD#MXKfEd|t*$xFKD zd`TCgA~wG=rH3esLod$qJ-!){8^B3pg@^UN12i(7z6HElZGVdY6{T4={G~Ct5x_9t zGyEdOV`1oUJD$O*jk70?QGgu>MOev~2Iax>8%xx@b`odN(($Cg47yW=2_LEbV~EkbP3v zMjHy`i1lJIyO)&Qu|1qRL}OcgT@hwYEqs%A8RR+f?E#njs6f`C%Fo+kRXpY0Adh-8 zz4qz)_cO8z;rBlhT5+nidOMbOi0vK#)d>_F{)Q~G{^pIjjFBW1g9sn6%v`@L_lu&+ z?u$G5&B^0IL7isZ-z4UXv zcc$-s=95|Ho(rHS(Z?_w>1QJ<%_+vc!N$OkNZ4PL-O?~FIjtT*Yt0Gu{y18Yc->5d zsRzZJ5o2_hXg!)7FAgNqM^@z};`aoWf36_u-#^LrAi4tU%$)m?zst4G03}aHD>qc- zzt7E+z$avSP*3Z{=23cf-I2L-I{0mv52Sve>>q$RkeZoS?7+t{<#E@RoW&wYm|pR) zIKeNiRh8^qiu@r>HqBul5MPJgF;BR}FsI@B5DzzyV&Y)~B1Zs;*&PBHM#}*}uNlo* z8bZ&YNzNN?4}+(P;g;+L-VUIYzM(`k3Aausvy#8l>hFrSjN+e$+;q7XdMbhjGs?Q+ zU+ywZG2TdO`LZi;vx?0jNRtzo*gL2*D+IG{JpDH#sE1v-ZH`=#o(*vGP<%V6Z^zz+YgNGKB zAWAtTkirvhasc|y7vJ397c3}?%67Jhmi)jt(KNApO(E%qXG6*NLRnsfjHHgcv&-OHiGU;dWWme#aa zjI{NjfZcJhje2$FDpk77SJw(QFucPKMzRC^!nC(~x2n%+3MWlH-uH*>j^m%sZ(+*P zwiF?!N^`FK?C0H3baZ!)-Vc8}ws8=icn)?^t=j7Vv9WG^eGk=D-?3;|8Tsr#Vd3OlSS?AAR0$e%2scdLpuA9=n6+M}+;yqRhWYzRy|D zpE_3UL`ojLY}&XjQJu8f*0EgjBwO1xtj!Rsms7V*{Z69G@8r~3q^a1Ye;HI*6CL?c zGtL&Q7klS_gHX1zB;vcZsCeMXk60!vPO{SZdMg_j<7FGRD^%bLbCvzryT7QGGicAk z$pTMUrqN6H{`cbUWTs2O3;qM-pNcnT-fKP>G?bawqH%;!wbD@RzBT(c^jOl1;<{Ub z%Jo-a2|uyO5Mwc1d;Wtwz_=G@Y|LJK_kom|E9(!T_H@V7M(zWUDKMs;aESTv;GMs1 zPJX>@I|SeP5^lbf1-x7$8Ni}<-#D%6dGH-o@791k7B@%?w> z=>32ozsJ78_D@o0|GRhSpeLM*IH3Mtq<=o|TKWk9UR{6O9K*%UdqVsQ_&<&R48nhA z!hfXTKT_}?Dfo{R{C{2w*nGU3_5VM$|3BLQ|L?1;{lxz{`@e<(&;RrZ-g_M35oF@) z;pgH1!q)E2e_gKqUq;0LrRB5p2nzNN@W116Ks5Wmh>raa!z1?}`*~O&IXLrs{9OI) zk^i?na{7O$L@gdaf9~z?b;sZHzYLQX2V89;o_kmW4*G9KJP7cO@Cxuh__-Gz;qL#7 z#i{>cA^yBErW4d0BlK|3cn2gsIH5T+{_y0N>Sw8 z@IQr?+q=Xy7UdpK*ygG&9RJQcG~Jfja(VgSK&qLqb!xHA@oNCqbq7t#?Kzr~jO*L^ zTY_A^b8{(a%9N*j0>zO+j1N#_*NI`FiWpWo-10~e>#CqbXy+kOtKke_wr<+ap4d#A zX4qI|i*1c8&sa};tVx4QIca>@>oDrs3xUlQmSCuumpZGaYsY?Z5S$yv`E?y9wh^5k zT9P^LgR~N*ZQKLSB{7{j!7a9?UDvmExHbWrG3W}rWM^U+QZiJ6pmFEf4V+yHf7GHT zaZUaG15ns?qobQYjwOG`_%1=0~*T`4lFXSvMV#>(*CTii$JI!@SU{{7vrsC^AGleZ|OC>G}?Zy zY_XJ!yL95LW^%z1d#Avy8_!P(XiX9eW7@u}4TODvEz1?=Hy>Y?!U3?N%18QQAox$< zur%d>Fn5Oi(7;}oSX^7-&_GUoY<&JJk7m`yH9zFA9N!KRq}IIHaIP2Oqp=Q3?c65? zC)0a;GGx^bPxnf9YWyG`-~7mXsZ-_Lxh4w@F={kwm%)uH@7*rdk8gfva{%|va!0h* z59H+DkN3NjZLcDWQqS1Pe@AtL@kkn@CT%?}&hGL3b@m^=`48w=7=S(RavIsxyW_d} zWHm)z-Eq!ZJ^M(I71JK+{f}qU)V`Q$-CB*@+mYW)zNnosmtAoJMWUY|kOSu`qsxG? zv)trsW?nMAQPp9s5wa2j9y-P8v zw!Gy|@Hy#;QIbNeAL=*Q3aUeozgsQ31mAEJP`<~r1E@TA6~!UC--s0XYDkCsg%ZP? z-F$VCbVU`s!mci|(>0&U{*bnVHusnVy5fr1AMqtt1tb**OUxTG$gb3kRb;Nq{=#@o z{tK<=hS)Bhn&=xrt|&#fhd2qdJ#Kd(2IYMHiN9#Tui_9b+MJ(6QbC+nw@az}+MzqJJ+yM?@>GT>61 z7ZEPKJmuEdLn#a?HT<78{CBb_Ur?sMg2U{iT3$M3FNRn@nkg4BaDuEXYh%LxvGN?* z^Wr4g+tkDucEyu>X?px7N1YP(SN7SmXb|G4DH!wO+?U!iSiG~%tSPP3^{K4J1+j^+ zJIz${2zFq`{i+|wQBI@B2^5mpF#G2}*5^PUB+X2V74Qe68tS#$P(#bWtHI>@Tye!1cEO?_)uMFRsuto$XEq<=3k^+B_Db94wmzxOdum_Jh83|D|c#>0`=lVrzKc z73sCU+9>cxoy$ZP^;o%nLPuGR*8|s|bH7-kqh7S>UxqFfjI8nRJdEE_7rulQQ;-H; z!JiEjK>AflmXU91wxkp)vTKsVWV!ev;&ac|-ceI$ebO4i>GH9&tt#Y!gPcP{DGQn{ z{y4)gVL~;(Ad%6xBHvy%0FlM6xPBz@6~Yo0k1gfC=4jBmA<{EdcA z8_NmMnO%d#(7VWjC6ClwjqoR%$@^mYIhC06%5nRmx!?Z4skLh0%vwQaaYw;&IB@US z#EeT)xE<(GapP7)LMkZaO=I|}MN81LMEWroiCqnn^&kwl73Z=Rl}a)sO&VD*pF_6} ztAee=^qGpG%8zLe?QXJ|3+T;&!68|J^_3{2TM&F^&A%k?tlV95CO?x9B)A+-Hn_n2 zo>-6syT`o7h~KI4SE85obvGfy&T=_?yIidZ{;t-7V<#D^f-^njSe)VUpIjT~C0n*4 zI`X-uF*z}|=?fp=2cbnDjr{XGVx3)FxNCj}l_x-F_`$(1D0wj~6zHIsCgUMKpyVps zHrc%s)O3#rr8J&HP_xb^XDbe)&oS<*gbAo@=N3IvJpp^ zD(R@1p`h19No#*?VarZZg-<@EcSCzNmR8AIuVp-41TfV`Zp z#>+?p#`f*r2J7$8mOjt0-Hxow$_m&iCd$KVziCd4sqxl~iV)O6!&ug-xZQOtyf;VA zb@Sh;a?obQQxIjVRc8PDAHyod9opfg%(PDe%GB}c6STNQFs@36!ATqTt81_$DpG76mUog8=hEsm=C+X6E?jv+f_#|dN! zEvtgSk@<{&JD=D@~5lt!u^R;S*8l~<0vAPuU*!je0;)U;y7$dD{K(K8q^TC zj84^B?I_$mm4?WzQ^k{NjXA$ZYo5E^*3_b%TZaD@0E`T{#2AcieL1*zdC(Yp30-F20zqbCU6B^DldD9^p=m7 z{7|HVCz9^Jw$w7J?Jr=*J#37F^~VSHe(U{HCWtLw<|Hx_l;w2331A(D-a;x|aqNaQ9noKA z3L#}2g@X1BfIEaN&V>J)q8N)G?@H6xP@=n9)AHwl_JM-ifyV7ORgZ^yp}C81`rAKq z_89IeEt%L!-Of*L_Iz-o^^HS#HoNIhNKmkW<}iUC6KXAOdP6m(`iB16UJ|$?CEX06 z_%qIs^W^Me_nc~~4%uH~sDV!<9QG`Ti}(y<6gyLXIZX%IW}XQ&QV5$oCQ5t<&Qs?I z7&|A9nX6aOEXu%^WztbX+8yYm8H>IXC?OH3s@yxU*B-) zt4jruzw6-Xy*TBL5smReAoMir5;bo06;COKrYp2%%vO8D{&5w5q^AK}$9CvDD`S!! z433~EBJZhwCaojt&PxLT1p1#p7mipH} zz#GYm8cDn^^V+Mm&~Zned2X2`FWXyxdabtIgt2i?U^yP^?_p5qAIzO?eDzNOCY)>O zty!crK@2le!r9JpgA7BsbDb6#ggj9&ChRJ6sXgRILyGglZo0R7*bypg-ccOk(&O_l z6CQb-{0-Zm=;FjM?IgsMA>9w+kY}sr zX7lEr5PNXH8Yr@v+-357bW9GG6L1tYalzT;c0%BzI?z6&ItS^_VE_oVe(hi>fi{(G z_4k%BEIbBm+3~YA&^!MnI-ob?%>d;%>mcDT&xnSd_5Sdto`7gW&P~-sZ9-kpf_`^q z$)V{wF$ZkAaNt2|P5pL&E-`Q)I>sG@^Ex!;6b4G%x9WqRbHy`wU)eh<3oSa`^W(z& z;F)f@d{eV3MOH?FHOsWl3d~SabU>%XhKl^qBY6GUph^CChd{UrkC>mnd^A+oO<8cF zAl=MJJ?ttzAh_R{)nIWOS^*pK;41Sq7x&^<{CU*Dv@3o)+4RC7W`sfbmz3LZhULf^ zJjEU#=9dTQ6TLcZ%f(mWi%j`_W9BS47>o^Fp~N%a`8YKf>RgYsg2?yS$8IFKZAc+M zyvw1y7l~Mf|8*HKs<3;3)Rlx2bZb7bA&oBymj-fKl}^^Hxm0X8$PB_4#5pTDtrl>( z9aO_phj=-sc6P3}Mgcrn4K|*;~a7-)B|qyWqNy+L>rQ;0zm5r;FO;?9G>v&ZEWWWCQc| zVDG)9CZKG7=v%8$V^ED6R>x)JWDty@-5xmUT$2m@29jK^-zKu(uEfffXwJ*Oevo;Qcl#TM zA%@@irp%?#d<<%@KQfoB*sa*p_mX4GkkRqCiSF5c@v}LiEy1ZO?8PB^X1;A);FY~= zB-8iT7O#gYr?QK3aEr`R{KKl01}RqPMWrI3Gf+1*8`ym1S;QZ~}&M zjz0*F(OgUC%2`{n2CQ*V(Fl1!O^oZ)`~+6C;JC3%WAZDt;9B)=67+jQVAl)uo9KJf zO?9{~ovs!mW2ya)ocz9UC!27udEhS}jUL^&4Kq*khiPI$L4PW`9Z%7Im?%9qwFzj4 z1{z9lb`nD7)r5b^t_NtHZwXh`aQ+6XIB$$O3DSOSppMA-?7WQi{8ys(AdmQaUMhlp zznz8aT7cPBYId*Hh;dD8lN{62Xq}UM8iFZL&H{U@M0bCPi7CH(<-ygUV*eOq3ew^; zC{kIHAHKX?yCCi0yw69lGOax~H}d^MBf>taL1OLdHB(6Rg4jjVRay-33RsI?+ts?O z5|U0L_R*^T<@lcw2sL5U{VUOJ3o*$F(PimJpW0l_A}qi-VBVpGcK$SLuj%K`pw<;7 z9L8|z$H=u#;-1PvfbOzoYdR2ik}W!&E?3c;682P${EEakg9Hx3d@U1#7|+zSngb4k zn{8Dqm_fmWN6Eu(E}hsVe%av(?A zutq1G{W@r^o6_=o-XUw6S<` z`pPA2Y_zQB@ckqR>+4l~5%y%idFX{=_NIw4u3`c_`b)4oz@5LF#Nne-XN#NJoG}eT z*(~6&-7iv0z}29(B(B`6Jhe-Dm(}p}>uxi9z4c3bZ_%M=S_^3rM;$^9>JIW}*N$d& zOte7@w(OA(Q&MEVnou4_G!Wc)QobX$@4}nFagWdu+}ugBewxh%GU!GcT|Ij&Y%cmRr`bY_ipA-&$6*?rdak;mbHc-?g>wZ6F=gN)_cUi zdUKpUaO%Ug%@j9)agfY((yzX{S4b~Lb{x8nERPS0G^pvxa07>^@=uMv@8yFuDN0YI zFV%A>(bTDe`ztb?+%D{xP#=Q_BlU$lZV?UIYd5l-~|!YH_G; z22W;;Ib(}a9RmiZ=-n5JVD^F0fxA$*s3#;rh_#N)#3m}0_O&cqfSnPh9b-)KOtp8j zitGo#b)wZLSD=*U; zV_+5lJJvBhTKdX9c;7x%kzG3k{`FL|Bd3E;$6uMw8|rsE-r}V#xFLkU;@MsK^}h1t zKnvG^6QR3Gu|%CTOHb;<)t+MV+jM#uz#(6vME2dUn| z2O0HHw*2ypT*-pYM$S<-6t7p&pA$cWi9TL~8K~$VJfZB5Zyn8Bgz7oIA|#lYy*5&NE)oE~9ghr|@HhV05g73Ji?4O4YYjpo@s!&5E(tI$J&KYfCw?&)x0rb{nf#I{qdP2T;Ivfj9k%Omna zA~qD4wSUP^W{|XQC@*|1OloJW)ehs0}kWa2)NuUfqazJHWE%lgP z59Xa(WwhRy>1vtKLg>XzsZi%)_+$m&nHyXBwugJ7+FHKNOV>D=3Pcs{IU+Brr#mYf zPUNgWT}Me5H(a7dRd#R!3+!N)@I+SGo9!+^*K{me3c~A4RQ)CfcZA2y z0KEX1>(Fn3cUBwDh@A9V-ZEWn=&6(&=jXjqkyI@owiIzf+E0AxT2y2^_7e{{Fi465 zz;4)#hgWHTzPO=LrK&RmZ~ndR-9AjPl?nqe4^xveHRdE6;|wc9Pj^g048<+QuEx4p zqdC=gQp9y9Y$g`Z-z8kslK6$5UtBm_45bsuBl6UpHr=J4wk{2Fs18|YGa!;9l|qZM)blJuTQq>Je0UTZw$ebW&K zNLVfvNP(7&wI|H5t;MLLGrJiZ*skUZlKVlXgQLpkOs?z;IWfdHH^GA*fC)uHaEmh||5L00HouNS9VSbz@2 zDI-}F3A`HNX5 zZ-lQ}P-AbEHduLwkn>{S#b|}?=d!Ag1ctq#{agyJ>#P>sRJ)Zl7lMRhkF$5y)pOf zwx^})>boq-4NmV5DKBQ3uwIx}2!{(7z{9|ixOv4+lOKjv^u_4z@E--`!K$ed4 zC_`88Mxjo{5ESObqW{32a!MZ7(K#~nmwQzH+QLgXt$eP1J%|ydW{M(|mxxk*vitYp zH;}U+?d5XME6ewVA{3RY?=he+ppbD1Fif9+C^_Il%QL+mkK39GcGa6a*5w^P zyb~BjQ=z;Wk}S6uc+83_kh6peYSn^bAv=!-?7f74169lcsOjiKzWU<|9cx|NoazMX zR%$U54r`|W!`$O+3Uy>oERf6f_GEJrzyyZniEQmZkg0|)ik@2*UxRU8Qe9cwQ^d16 z&ezo&v^o_tlDr=`LuoU8@y{XT87#dM#otn-&nkQU2uaHpUUSJ;05{AF?$QBZR3!DL zuHS|r_?MTsgJs`w*vB8TpAn1fL)j5}*DI!6Vr6@8rcu82s?b&F0V6=YPfO6>kHLE+ zW8{5GEb*c4rH$Ok1%6IQ0{k=P zN%{xy$7|ep_KnLyQUKV;aLeXpwHl012eWUGk}(~tD_0xnHH6{uiFZ*fVAx6Dea=E& z#;&~zd=f@HF^rHeQ(J1@mYkF!=mu(+$x*QS`Ma!tqSO~#T;-O7$R_*QmijKGG1$i4 z8f@t^-*h-?u8iczJ)I~&fukFhF!fgaDuQf#?RSS9R)Oapc?V4kY+9DEJ)?S4UqQtl zk#5jl_$Akkx3%Bg$_<=-gtzRW&h{`;EHq9l0|N7hPU!bDmmoJIH9m`P3x5p#16_?c zEJKz?W##LrX+jW9sx^q%>*zK|Kc>0HMngiNA z4|sR{6+ta9mR9omHPeRux(Wo=?9r~2bV%#OGWSj#Nx27$v1Jy6rz=Euj90XERa z%tooh*}||AV9_l;hE8(JeNI2QnjA@I%!SXHD(r%3#{*pvY-NC*p3!=-hV%^tCDF>0(O_d3RpV`N0xpmGY(W|z0kUTs724Te+Rzj|ZiIBm+ zM_xj7l^fxWMDJy>e2Rl+n2tkl0B_XLc2m*BLHz*n2xV%BuqNiToT8;u=V`A#u?wX$-1=9H`V%S5<0j_@?=VUHm#$Z3Jq z340#1ZYR1IfUaNX%8u>)k9&%y`wLdy7 zp_4aQ9wuD^0t9k!A=8Z*)M-bnvy2qA?`e=Yv z)R|a|;bp6syAc~f~U5pOP^|6zufb2T2Ll5Ey_3D?OCxYEE=4PmCi`1iht`W zy`qPRe3V9OcZw++C3HpTg47%KXP$TlLRD*wuA^GvsX&ma`t0l4i|Lnp*q29P;OSQ@ z*FyeIr&gX$ADAope2bZ4W7$GAe}=4Zlqi4n67HkG?hYpn$CIhU{>aNZN6E!9eT9ur zq*Gz_!b@0F|86pp21`YZ@O|K9FARvOKYIu}f&+A$Md;3j%*4?5V@)K|SM1|Q-<+Et zpkLh3L~}0%Gu6N!gU&kC+)WBfK0jigR2jcp{6008R(1)|n6otNYZS0*vanmk_w#Iy z)A1`Z!RhB=?86Yo^zEsJ{TOPtWl@ukN1+<&C0sjE`!T)!&Dk)kx(emjFyjb|zw9i) zJpJupU&{~Xu}59(2G$W@^Gm0iks;taIxNR44)obig}cg#6$ zqUN#zuELLZ3?iOXxHt038fe%kV^et8!G=J|l8%-Q^tt?xX4YtSm!9QIiU&4;NCPWIlUoMB{%(@2Rk&LsNP z;KJSw-H86Xn;-78N{=y*q0esgi)FjCO&?k3%DWKoTcyZ z&m{NLNzR|RE+V393)rj;QC-SyWK$PQed~OO(BQ7=moT0>*UJyf<+bOTR>}>$HIm`5 z_dW-z(_E&x;I}pySG^oureo^x30&lu1s)QD3$?Y+8U!5_hi{3zwCV6)76$}@e3u#B?aW65>S z(hln9XeScI@<~g0oLEcbsyY3!5-zGfJ6er2MA7Z$jGx>UhFIUUw73J%iuyykV|_uc zBUumyQ|H~aO}ZMly95C@Tx7bcZ9wQtXRu|{Te&S;?YF-HTlVzz6qZJ-n(narE#v@w zwJnh+aU?pN?=3cnS?h>GUmU-EozDj zK${dtmxG|)voOD|2LG#Qf1B& zdGuew=)s#SWXJbx7R`Yv_dtosBmlR7Rb zmH}rr@lIfwxq);PH$h0DIn8?@eI}L!uu+>!8bLnIXyB@JNQW$h%s2>tR=XW)iVi*5 zp-Wr3mMxF|~;jb;8!;k2-+fVQTUjHDUrDs#< z7M}ki!dk${@^^=P3xZkB_=|^OpZwFGA})=4M~6_&9fJj@SA5+ja)xurv{HA+_4LMg zYOOx|rtVC+5*T&OfF#pOOPI{yqEpY}oTmSnG*?9LM=XT()OD6TfI;3c3~Ww7Ew5uq z+>p^??)892RYx|yI;&OZ=c-o_{JUX(Ts40Cb0#kNe4=U++PC$P&vrF-SPuQh_g({= zi>^y#b;uUZ5F%3|QOlbh=LRuZiYE|=24G82bJYHw(~NlMxTQ1(?dU}7a+HEPM0cz9 zN3huH#_f(4s2TTW2N|G6IyN@w`!06^@#Mz~t`xjb9eiahaWUk%lU!7AkuQbdPb~sboNqKZGXKiy?CeZ zI|PhYlZ^d=Uzh0{Z>}YM2C6F%j!|!d=DMR#?TY6K2jyQ7omiRXLivzMWRAVRQ=7gJ zl9RCZ1{ZxI&roJ)IzjQk&^z%(TiQoj0RPNd_5df5<{LAI#yES`h3jPGdUrJcfNd|U_0z@&c55c^j(r^8a9i=H6L@vMys~budOF@04 zR;R^-A8YThZnm2v76)>?p>77F>8;VSUrifJ*|iz2_Y6o6NJC+7)8AhRn=`R>q3$)_Brv3sW}tAtqR6%2AEWz8 zUf9|q`*DV=%90VU^xhQ*42%b2m_SNyi|!XDzCSFEbzae^f^YNho?)hyiD(Df>R+^1 z!VbE=e=W7w5XQw&LABI84_&ukfN1U*W-(rwV^^#o9~hmzuYv0Rj9!jhQ}T0($aNdg z_G&u#Am6`(fErK3GQkY#z>%LIEkYe}KBpb*%(zjrpU(IOi``<4pbPeA;Y*Cmlgb*K z8-Sz-f`im)!>me`@iyBxEntd|;fQ&3lYkviHVLgVB)(=c)eW}(guPL?cc#;_9gSt? zuy1kZmZE|iYNRIE25AIPN5l`b81%k3=U5O1Z?G+V$vB8eWPGCiTxL6d{Bnim&-9dKbq?2i$5*?QChXphdnTU-(Y zv>4H;LrhbpTM9|@F}81rV8|y%>Q3s3o$+|tOPEet{AG~zCKVX(9P;#5l!VXc=&MHX zVPCg)#G4-4OAEwP(&~v3Qx%n?V?QT>9^J;BpcniI)7ymlta{*k`fRB2mXU}8p!9h5 z$H*9qyfffnzhi^~tU!=|IPm7OPb$eDc0*M!2v}awvX>vJ2Cp0)tjO57mt1lc5{zs>WR)%98;t2xd9`xDz)7NbHk#PPb{H-5g## zsZ%uvxw7w)Q~GE7tJL#D(NDy6LuOfAxjMAwb5QwCV*F7sto}-O8E-J?3pD@uF4?F3 z4|;m!Xi()BE(hGv>8QGszF{xsqpR@a)txJl zL9D>?frNXU-{!eS4CgujN_uoo%ToZ$X}|GLvPoXY=wif?Y4`E|&(3ZXk1F{3z5uZh zB*2rj%=5vtH2Wa8sP0=acBUl_I;{nO5QQZZSg#p@0n6Qz86+o8HEBaco0UVqy!kvW93A%O>lRCrWd-scB z8r`|z7VAs$MUeMANLEQ2AGwa$;T#xt?IHE8)Vmn~dSS$2htrL)i^vsgEf3Dm%007Y zt-n{12GM(0CZZ3gw8)-Bxa|f#Kd2qMr04?Ku?)MUagfthSN5s~_A%OfqpdZZSWv;2 z^1?Z1&uPvby&8#V2^U%q$jIe#*M;_W-HGx*`TNzH9+D*U&>AW=z6Tgg^s>duUA6c& zDn#Z1nm$H^HO@J0B>}tP$lnGB+rNQLn1NrP(LdzIy^WVnIb=g`MZtk&n$m@isP{%d zW=R^PRfh(V|rVoiZ&b>=% z-hLiF%UT*viFGc(*JGl?MOQ2nSiL*%R;>J{7v=}{j(NYt^cAK zZmXnUSZ}ppx$O_YLC~mQMbyUS-R62}5}@CXCkgF!pH(f=^6k>Jb-{AjwlQuYac0jj zcHbVQ6l1&fywU#C4Vq*Mn|Ma`a7r5{K4dJgG~Hh(2D@j~S@TbH%IRRS_IC$v1k+4^ z{qem+0W(Ahu7|r4^soX(lVqxvyMP3PCgp+a2;dj4+z(F8>;`La;IdK&{GH4uY-R72 z4MP4Re07NYY`|z)crUi6IR3fdnCur=FYfzUu_n7;P0vhYW(t;~j*)}+87}U+pd8yR zIirJ#;{|&*b!$^ zLe1!@Uu$7Q-BPu+qRuyBcNG~2ZcW=qJ`~you$1FddY}cGjX|td3cs6kWLgeOe`s!X zrV0k9ykN|0_Dsi6f@Xhd=~VeAZYTAxJv53^aJVKJ%e;x*Kq`uo8xAk3?-_q!=1KrO z_FbE^);p+D+ecZ}=_yB0{_T{fKOP5H06lulqS82j3zbA3N2HG%$?V_h2;ixK@4HAk z?6aLi$e5Tw2tXwX0N@W}jgR^g=o?X> z7-;TUWKgqu6_2n!sD61HV_~#&l%N69{~ZnYiDMPYUJPKRvM&m`h9Q2P_Kix~`~GPc ztnr$(RE4|AdK}#^$_fY&WXdOc-DWxG`FyDTARsKugJC2sgdi-3Th=4)_LjKRz8I*5 z-EWJwuqnlEi=@8VIj|E@gr^a!WkyQgm=5PWhM3m`TNNkL%ekjplY;=sQcMO99-|k? zrWdjMxIh+JvLSsdB7GYsHL{Au-=0xauCIwhJI>0o?fv+Jqr z94q3DDMFoufur|0-&GfTUd#vomf=VQH5KaNL;D0fP2`OBUN4k9wuBe-ZCByy)H*H4 zCR&(Nwl^Yd-hRkPqE=hGsteNuFty*3f?Rso6u>xf%GV@vI1zV40AeX1MHf6vhzR;+ zfWj6vF_&oIkBWNTO0Jq*Wgih4@cxsoD<6Ucf~>o-m*&zdkMCbKWNKg?jY+Voc9A2!=Bne$tmrf1B9wwPw@UrUc?MXh={YQm@5wo{i%c3D%<s}NGR0}|M8=_H11h)ibrY%jhUAhGsX^JnxhSn^Npy}us`)mLPuw8*kY zf(-w)@UE6DN146#st32!Ps;ZrfiQ zLZDKZ)@?E9VdnitXT5y#YJ{Nu*T@s7$bOPxI4C=MWhnn_lfi%tbvNlJ*u{u@S+*jq zU^F9LpI7vKO?=4fXL*38`xfXaQHsR$k8>42-iA`^!8tdr zJ^NSJG=*@5B;YTj_wF|n^}`#T~n*5frTWBTxg$Cf0{@$C4_=7I@bu5x?U4I1k3 z2>i+`n)Hl0r~1_^TAgFA$o4?kLW`Cl&MCKhu!4{M4;9XCZY(_>@f3IFAfE0RDq2Qt zv->@Yixtm=*ADEBv=l-_GkPRoRv1;R{7dx4@u=;48d)6x^ikC79?Fp#@5rg?uDz{7 z65wHhezc4n^#*bhC_uF>DI5@kGc+)AnGX(h2561L(p~^!VzIeykX!W1wdXtO4>+-$ zd;b3qzN7`iE_7C1X&{UJUl`L6ZbaPEt<$;kkLYc@B zk|kIJVB9HB2GxPuL`EE>R;5S(0B(BHslG-&tSUP;`A8jjwW6$ znN;rGvc5k{-cA?;Xz8{iNY4D4oP%GUCcX z*=x$MJRxQ5%0DQzmN{2FHTQ`;cosOU=FO9>0^??M%y8ykmp^8pbrQoVK(;9?>|lk3 z^Zm?@i&FvLz_@HIaTzuVQ>frhNg0(u>;eDLDC3nE;ZcThSW68+T;Dlp$3xD;eF?hD z8@&&h6d{l1P>J!qd)rO}ITS;v&-5E>a;=z-&g#8?PHnY+SNadmBqL$+0-cI zPE#p-#4(I6&yKBD0ZtHNx%=R3SVGQK%nWxR(9V4;zU{9?YPy&0(||{oNObt=@}(C# zM;Uzu>YRgdtpiIiL4=z22|q3vTa2Q-Q4(fiCD2Qa<12-V}=WtO}UlT#sY)KI$0#QEn&PR5loio_6)W(;Ch_{ky)u zUWVx>*j8Y#QqHXkM=c4ap%CxSlCYb#`{;sa%8VhtL7w34W2bfm3$cWYW*)ot8>tH;V&lSECrxt zZ}B@B6RZ}3$i>%$+`0FWIjW)VX-W4&7hzv6lS6pdnkS#`*;YNQ%DakKPi0811Mc%> z!sDFnRwh>~{&>PwM?0r-pAZkbJN^rM@}9?yk2#g0{k@0;s#9W2ze{RB6rO4ZzZf7a z@B=`XAHcuWIjNnOcAJ8wGvwPBf0bPQFO$g$dBLENKk+eC{yumeCvmP=Q?KgnhFqU zwr^5Ei*s%ipZ&uJz9oD^_3vPIl<0;Cn2y`)>F1G~rLG1R)$8QQyGXJqks}8!=BciK zGpRdsDnoZjnO#QB|U(*7pEBq95 zX-v&T+zCI|Mex>^l5U9*;ea`D?JtE+1udCLM%_^8A}LoflV=3?`C7MX;B_ZQ+lGJX zS3)|I@+m9#%`yTsrxW2z&8Jo;tM?GY#hLXJOwrb3ZE{3SLh(E|^0E924FEKxKyM(PG1VPkIY2;}Y(Vr7RWH^!u50-eN&3hXLXx7Ruy z+^nHFh~He*%A4m46+O1-t)hLKzb zWd)7CZ&9Q#qavn6mDylRHre`I7YzIJ&*o&m zX7)^Okew5H^3EZD`iKuZkF-0}sAM;RtXR&8wCe;jaic9yAsu>=nfy?v^D8NNx`Nfl z&+K8h4WMkWD-OBn;rJFJzsSyq2j`Hk)=7liE8PArYM8+5qo^wsv$&v62P=5pUVO%w zsBjh%8Iil39cas&e)9@i+_;A(0rOQ}Gr3u%&-er{Hm@Y$5UulsLtT!jClb;uG3k`+*|r%aDX4dFl}43wUHDIDfplM-?IY%>SL@d$H*`wA2-Cpy zy~V$#x4x~%44GkHzN+fYy!xjYj6DED#!9SN6Zv9I%oy~veg>^pIT)M= zV;3TbC<=2g=XEUP>j$;t_|JWj%WyG&FN}3_*X4}v$>?}{p$)IY-li8JF4;QR0MSOf zUp&qeo50`6ygHST!V~-5JQpzchff1YIdE^b%j69>t4x+QnACv8mCv%@O?NTzWqudB zJa{ozK#NrOFB?zS9{s^oKalCN?-j{xDtQgM^GuF-ay9&S>KI}B$~#nrToOjL=%9Zf zy-5j!2*7Cx9bj3!-5nL}!9&rzlouN#Pr4$O~0*pNiBK(eyl8*p=EFD(r z$?WE!;63aM>xN^lJYxFMmRCPtyQ9El4be98fhR*Y%}u(o7^edG<>plx;7v7Nrl3N{ z_PAFR(mT$*FYsba6EhT3`~B3|_!PA~(n4vQN#DT?=aE@^r|macTRVG}Qm4aMX8-&R z2MMGI{&sQ`G`mH7av_I6yrwl3dEvC|Z*^JW zGhQc~e!;yLj2lY|K6cv%W`%^dTEtsL=QN+~5XF{|XZmWLO@$k;{N2aa@-Q4=u0&`A zO{cRyxeezp*v>tl6owhzPTYl^Z5#e*lpB)+i(LTJ-BjZ{e3~*+Uely<7}2!Q*P!>? z(L~fMIa}766F;a%87AfbPia?zpRk+Bm!f-RC6U*z*HST)Kg?`TD~!ItWcVOIcskPF zaZN@7(SdY&<7`Ar)9l2o7V{|)=OUXa`-qs{aN5VuH9{PHvi0wpX@euA`p(ri2BQ~QR^*t! zKr4!14*5rbQoY=`*zv9<57v6@X4K9-n|m<_XfQvhqx0ncTq}wW01jBU>xlexS2j@) z_E9V|nUD1gJIeGcwA|3NaTDQ5(WP5GbA4WlDpwren%=@g_4pUIyg7MC^42oD{uut$ z9V5-`X)KPC=iQoKguBvC$Ieq75tBHNgkmeRRu2~?@ zRp1{6uiM7F)C*WbRZ#xIEd$*S6E#DcEn`yI;{K~^m$=XQzK7ZTgMtX-XB+$0HMD0g z#3A84A#MzmxTj-xpCDzGGTzgiMGDq0FDUnk?U2+L( z5Mw|J;;c&$PrANMZgA)l3umS8#w9y_Vx~x(gFm2Wjke4VG`jUMlfDL~XkLomjH3v9 zvnkyv254}*68i|r?UvZ~cd&y{GQ;&3Av_w4rfnV!vZOZ;3HYLR9!4?XE0ib24`Xx1 zDYjMl`?e3E8WF}@h!Lo9z>!`831xN31bj}>&9x_;%^EDe38_D$L;))Q`wN#Tsi5Xr z%vizXJ1!R$UK4Kp>1|tE3f!$9m_W5|$3KwD^gJ<+=h&t1g+hD)9ib3?4Vr|xXyWjL z4aDKjl6d>JtW(JGKhjKz>_Sebb@A-_-!4nKHQ$DsG z1@M5P|B?sVE>>0bziY{e1)e~r3#DofXCa-

    %*b&Bv~JU#bgQ`*p;34L%@hN%s0f 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

    ?_c!KigxS~RI+|O~+RdHu)w41Hk~!tI-DvXi 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

    #BW_1~bG&QGXt(bdI$*?vMZTr9?UM8)%xT z(4tK@s?6?YCSA`aaiKUVOtq`ZA2tcqSY#VCbf%llCnf92W7Z-KFE|d&@b99UU#pl~ zsv5-wnDgYf*Hk`THjFSNv20D}zYfuBzi^(`Mn-VY#hl$sH`p3-vKh7d%x4rk7Vwry z@IeP+pHbhoS)5GBJZBd@s-$vB;+fEuxb}t^j%{Ip--lCgm8xzvns?c`I!MrN-#RxHHef6VWF)`6ICx1u2rvX~*@o8M+ynh{~@~ z*GG*lpH&yGY4eU*uEVo(4--9aip&3)sGN$*Tj)11Ub2>xB#ge>TV0tl&*9|H zv&wUkr{BHcGpJi4>7hn5O~oV)nl-Y>edg~!@y{(UrO5%={Kjn_qmdT4-Wz70tIUX0 z;&{gOQLXaI^mq(9)4ajrMCS7{VW2^&LqrgYE+^OtpHK2liq5h<)1B1H+tTN~G%axWO&Mrm)h>rJ@#)Q+~W?<7!Jt$&{s zW6B}EEWwFTcO=&ORpMbnl093&SG2x`s&;%9Hy-- zETP5E|3PaZhGv3)XuUh62yW2DY4?8ah;Uhy*uY-Cx`EX30CtVvFp58??)@r3=yZIw zdg0ysS*UV7Z(|nWc$vs$I;Cah>>O7&pFqExF`;ax%S$Uo=`#Tv9cP6qGaXOr01p`lI($ zQ$YAxUA`N`aLZ_r3_SmcaOnYNUw@E-R@9&tK>%)6mG*0QnkI@K5BeN5gq8&_W*P+{fs?k;6o zP&i>1!F_+Fe>b@ocW~pQe0Z?DQf@fd!AU06p(g!^V(SFuxgg8A&aL*gE#-Ek+dQtL zOls{$(TSB&PKd<@iT6fKQ1Y^DDLmsexkSD^8hX}g`0SJ8Q;U3XV^ZY%GyjZcS_8kq zEn`c_DEgmQ!}#CmR%FVe*e0b|yK1MdcDdz`c7jyka*`D`64iJw*5>x#D5GCe;Y zP0=#8caCt;!)bm{>?gVEBVi<|#oA4D0-BtNNZTp?uh-pcYuRYVWN5#-Kt z$~GT1@td}*lf~$BL3u)3R*U?e#RxC2E@&r7O9seE<9tx{gLrp@bhlScxqTI*ZZ6^|8|Juv0Ba_i^KR4o88pPqK~d89rC=1TUI>J zG#K3^IhdunQGFWCsvnBm&pq73t@M{`Bz`v6yU0Ieb@U$3rM@@pvsHCbaYp=uKQ}k* zz8BRAWa{Zd_%^h7pnE#9+T!UWd+(oL8tCtgHgs1aYlT;T`;$*j-#3tchQ6!2w;Wo# zmEPLry$jKf-Ag`^L2C}p@n5-syD@G^Vg)Uz(f0m{B1`gqtG$zhr8D?cAQ4VSmZ&}3r0^G*!zEW^z6*@ z^i9&WVT;7p5Mi+P`bF7z*BY>l2HBD9e}EI?$CplZRhjAd@Tz4e(>+6>OVIf7L|-1I ztVz$!p@kJ(ROLd+BZma|DN(E|hIT2@xY%gHSM}OI0dpjMTT*B7r0^=b`#%3E8XRZa z(d5g&ebWDab;c4&EQCO&mw8B>ij0Jby)OEDjoH+1wf1Lx_qy zh?MfeT#gCxwn&kBD9L(sdZ8C0okgTQ3XJs8$lJqP@^g&9rjeNzwRNT&E$D$GRNTKt z8l$Oxt<@?hocX<1`R%x(@#b~$jxZ+G+Dqjz!nFLhn}*}~J-ro4m&QAdcdX zhdh;{m$_+dl4i{r>46PdH|yEADcJ^fsF2Un#@^U0l@)JYb43OP$5EfMasLqTT|?-U zX|eb!b9oua+gmh7ID#j6a7qlKA;DC(TUmCVui(pbjjtjaZ`r39WcvKn85a6;*ewHx zPQpj5I2~PIR;!Ni79mqBozH?B+T2IYt@mA|lzw{cteL zCL`sQUaGZF?zsJU7;X)VsTHe;PNejMbw2#rrFZms{3v%yaJIoo&G-_s3dTwwnOF

    &weuJg)j|GSB1iXt5{Rnu9% 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

  • dH|&o++T?fhX(L#5w~E8y=asT>z19W`xVPNwP8kiEAXvB9%BhJAp2OZXwcv6`$@M z=~pf&0b{{;>91P}Am}aZ@#s1kz2Xtcztek8@}c~ZC|(E{(ED&2_fxCH(PjrqPqa;7 zeOqps)%^)9KqrazptNoF@cA=8nn_4av5p5ybD3oWm~?;|ssLRlyF*PR#3~DyO(;|i zXJ8(_`yyU;NE|VT0CSbYs`34Q><0Am4$TCr_6#5YZufA>%?ZZkiA@P2bpfRKDy?mk zXxbmpFJdz;Rp9jJ;)6}N&JXO6I5}d4JRs;Ts6CR9V?4NpBF^~(tC`G+-ZotrdXfrC zBy8n}t!-o@Q6M%lPni!_5I}D4VZR0>P7l7T1a$+`$m+P{nJQaAb*{Pbz_Ze(i<@xH zP?TuH-}-_&7z?%$=X`A=rsL&iKEwL6_}S{c#^%~o0pu$D3o!LJX^fQ4XSlS~nFhf2 z;vhgP!LjHsAiydPt_CJhaB!RwlyrQg);b*Ha{=hxnu4CCDa7rL5)}Jp6BMh=XZ+A* zBfTWP+4uj~sUoo|N>5@ZIMNO>s4oLBue$@EeEv1YC=2X++K)(3qzf}5%E!fIt-WR55<~qfIw&0 zdv*bMe2+#xNJ7K`fG*Q%krqR+8etDf{^$+*9hh`RaGZqz5^687HlF5g*ZaN+r56bd zC}BH^d`}sGCOZJ95`(O&h%7U^i%U#0jaz5ILAmY+8Y@3Zm1Z!47qkQrV|l>rK?V3X z=K-)f++5hkwXuV;kryRc(kaOyH7NGbNTk8gm4ePvwPr>pwuNyHi4LOXBcF#4D_}Y% z74_^I6<5&51jkmCX|=c#SAztM0twR>7X14PtY)78!b1Y~IKUQvu@pe0Zu6oS`wE5t zm0t8k*c=xpsI!q*m1vfLXgL#n;9Q0yr< ztg0{?S4RQY=_J;u0y36E-J;ncUt750vIkER9#Bk9gTDSj{8mRpD{7KR{ucqmxC=DU z00`*9BLYiDa1w6Ljmj}q6`_?2u!|P`?1bG>Fm~ET+zAwbH~;ZqP`7Ps2pyE3M&s@6 zL#d>;*`TcTI5$TnX!_(<5l}$(*<;Vogm#ALC1dUGPfYMxa~Xhq*A>w?qFn{}wgS|x zn2xcg7KY+peIo7xn$e!VLeyMr6ugz)qrtv*S7xtz9|QbkP9pKEkv{!PBB{^-*gWy3 zr}`mLm)+BhVQaQ9IQ}(NMB!G!k-4_tSs(L10;u^vMJ9)d!C03l0J=9)&kUP^NW!7! z+DtbEbPv0)=fpv4o8iK<-$+u6ee-#Ox8`z$IV%A3qA&Me{ z>GAf{(Wi$7)17aRb|BA)bzY34a!lNbxBtih4bE}cv+IL<4n78Ht*a(n5dF?NTj4H% z+_^>F3Fw69w1EI(zml`sUNSp9>N8_8o+f}$&?|F+Uc8RjRI-)qq$DLda$Wi;O{6=f`HZ z^Ajk|Zr7KjEtd~AE=zO8->OJ1FUAkx&Q&NWNPYUQe_~C)wWv};kI}ZFsK3sLkJe}i z?o6MC((L3RRzO>a#Xfo1l{c%dw32mqz*MezDt&=WbKAFP7Pc#(d>b%l z6bN~vTcOyWa)f7p6~xdG1uvz0Epg>pLh*U&PeXt%Xc!?;QM&EUMdqEtQ2o`wcC3Nd z^d14EA)r#9gVYN9Y>lG2$hJV{?xg3$JFt<(8;JmTe83|BNYlO9CoN`QPB;tzAz(Ms;ubNfrU>VLb{tZu*k%`5ndn=y6} zK!mH^ZC61FR+R*S<2+HlKjtt1GQqyo(;~Uwd;miX8|1MW0=xY=U`}HtVflZ8kMRTm ze?sVo4thke0MJ@zGc;XzbOZ)?=r^0B>1JCYaYh2j@-e{ifY`Zi&5YDZSYx;3hj;($ z?Q6jZ?})sGG8+M;Z1=Q37SL-$f~78>zugVF6Zq!9QDkxN(bRf!0bcQ}`IJbdD$E$T z2P;SXpZc(z*vOdyJtjWSBcGKkhz3BwLfXmLmoQ+SF#MDYTe&A z;5vzl5M%cGk}(@eIZ2BlgCfNSCq=t!z!8s&(B8PaBQO@w(j+RE`{xWw?{`{7t|0Dg zHsDjT74Dg@JU3>8Tc=W0c8yNtnaRz~U;Bq(jCKal zRcEqj%jI~4p0Gh@weQh(k^~Shw9;bojCk!b;DH`|cax-k*0P8PTvNP;;D^POB%cYq zO><%dp*u->u?M9$sE^W;pkrada)3*IKqH+->9rmleng_XC5F+9rzB=FZ2{!i7O_qO z>l^4Cbr$gQ62KjZ}6q&rN@p6kjS0c+F&2HPYvssPO4d=kvxoxQ5p#q&~NhXlkD zF9iPJtDum851p)G;wLsku?-UsMUj!)^&K{#^gOo+p}RP%pIaD~0}}hzAm|zKEci(s z;!Uf?&2;|XRYgFcyJ#_i9BDopa0ArsVk3=7{81RRb^Y@;!I8K_llZTtfDVh`Vjb!k zezM)gYk={w9){8Xr>m}+fN?3noMS8wo~s}~A{8nF6Ea4VxHy1>cQ>#8FkQ^Z#JmTH zUX?ww{D1Be4+KZ>hspm#?>j)N7iioMO^DqS*dls#-$LEvkAGwd-NI>L0&0MNZQH^k zWdp+Nd)D>7801HLDwQB%j^rLZOf$QWXQXwe`XSgWiSuFx2 z<_~~^V%H{E1s9+__)QWvp}rPSRsTx-(<#Y6)<8HGxhwV_fsJ03HZw-Ih#Pb!u^9yG zCkYn{!d_!;0lszpZ#D4f@XWNN5v9wUooHs*jYV1fEozd5I&6ZHUa2~t4Q&;%8cYRt zbEHj^&M97Mqlio(;(Y~>^LQnWI_VUm2%zjwV#}fuN!+6V`kjlFN!-}T2iE}{*_NI| z+$n&(YH|ME!IooGo?nP@8wg=<&j1wUspiNz`V_U3ud?buBc;F*wD4CFPJ+Cp z9!d{v4)CmGmbTa@pI<$hi1X(KBs^iJ{x2qb0zhDFr&#~m|6&W^w&kgK_2u{Q}q)?=+C3J2yJl?1vJkFciMfdr8F@y|x}6*~xccV)2-Zt?oY z?!J7dE`|#rRX~F8t)>gPr>J-4(=h684qJIn`MgSu1}BE42+@4#%men^L;_K;${Q`> z$V8Od`o8E#Bts!l9ur)1s0;mAr0)Xjf` z5ArY@R3$ddp1u4`+y}PAm3p-ti3K1Ggj+V+xACy-_m8KnDH;zk29^VQ&Nx8h>Y&P1n zh_55^p)s;Jstpj`f4D@Qa1$J$S^ zyMM);s3?(3#)^#+cF*v(-cMPSb7R9v$pvZ74jT8%Oe@QsKizbuFS<`#o6$y8y$(ho z4QX|XuzSC9(jG}h+2e{Ld)o8MFdgE~yuycVYp1-fbe#8^v`@MJI<&U`IpJm+OO!h& zs)-PV73b3;yq}xU*Z-Y-;{I86<=wBrX9E}UkG)hLdB0h1Hsi%8%naAeEry7G5IzGR zvi&q?{5Gsgu2X6wS~7NP-$#L;@g3q+R@XFX_Y*>WF+jaTwT;q)pTiM`T}y2~ZFf+C zi20sd&chp2N9A}SDM|KQbmlG{IHmKTFU#bAGuB%eY^{iJ5B!cknTxyNv&pX zO^7-I0dM66GH5}Mlc#ZyoPpX*;OUu@#EL`rN4BJtD@z+r4xV{VMEfW+Ng>qW0Jl!> zsYQeEkG!yZvXZ^{FPVHvg_(%bv5E^b@krb$XjG1?2R@_?-MVIgt?JlJ@vCf zYXKAeoCI*cnoK+bwULK6l`0<4E?WBYCcHyC?hTYeazo80p-XSEO%^aiq z-M6S1_4_*i>c?p@1s7UKo82}}sR>surJR3^n>j=SL$45#xLK6HNG2yv>_OVvqUm$bU+HpIUaU)NYhGFLV|^p(G@V zLYK+!fqK1i5kvaI3J)47Akj-nWNs>en0I+A14`bg)d9#tTm!7d7%Py1MAxk|^xxu> zyi7JG_sNNj{hLRRHi1VD(9VIFjDHIzpF|&0nL%%7jxn7;p~jdbLW%Pc}Q)vC8!yUod_j3_K0FN)=u%f zd)`vjZRe#hzBapOuK8W=yVVn+@~qC7GY-JFzp>T|)aCoIDi!AV;pQnr%qR=L7bKUQ zBHULm+ZF+0UV-h;QF-L01X)ry0Ws@T<(&Vh{cYT?lpD%D^RyAMqrgq2qK{PW3WM<7 zi#U)0wI`IE#>j%P^7jXRq`#F#3o2YeU#(A6O#6~Sq+^Lfb&Ypn`j2A##*)+uZ=b42 zA{;<5P!~Q_FiustGl>dNEN)Z%0TmsqyUs#CtC6uohEEw}ld%iE)ak0e#i?;L>Tgk~1~VcXX{t3=`DcL?qKDSA^#zpVvtS%#vW zaD8U(Evl1I_t5Ky#GUs?wwqWhM2tGpWT5c1EBn9>xNUTfYZ9Y}5Ge}@aMN#(41N=8 zz^X;XboD7fYI%%H4Fk{9w*89SGKJ)0Pr!7UKdV0nJtx*+DiIo_&r6DI-`?1+gkNAr z8{fQRljLFB8Obl(kD<>SsSn$VRm6D}&vO%+eGAcN5xgWX={JAPbyEY(=*88x&KbPj zHXQ>;X3ymFw3&x(gRKq2cu1Q{scmpKw+_a>TP6RduHqPUeM>>S9;O0ioE%NwX!RAwwVNTsWM4 zPTYl~8aGW3$v1QMxQyQpG~^X3uQKa@RZRRG4(N20Zwz&B__ZMYlMh%@LCI8(*Ts#2c$N=}BTvOw?)pE0cQV*Cgu#Cc@E z7y2La3;jSvndVH*bwTLGqof^OK3}Dm;& zvZ$}W=ydXAv_Ex%IsTmxdGO=`k199y%co0U{`~s($1Zo?m%#dLvnO>4$qx+2H9e}1 zrnD9@y*-J@0)G5SqSP**Ak@EAHTaYdt^_%dnf1d>@0wndhS6rJ{_r>Ch3T1 zvLGS8RXdE=n~W!DN@`B)q>`vz0$2TZmTd(mP{$ye0$A4x9M0#iQ#&jyNoiv8r=RQOh3AddN8HZm z$%Iy<-%^jPxN1w{`9PoIXvIirBTuU@?6H;pRXYZ8N~Kr-)En7Th&wf6@^23WK9k6$ zQg(7r*6x|9S7tn$wH?R;HtTZJQs`JNLL#cX^Iy#UyqKH9s65!7evHP_>3*;-gP5@t zv1pLdOOFU4|445O`zZPEADB+^dRPG`9({cJOO&3E_-M9dEG(0Y=vl{yJ&In}I3nvi z^~U6Fg2OZJ{eFx!-7R+lPge%a%wk=ilPf%;_RXH_F1K<7yZ)YE`Rpab<{iU)I@}0v z5RK|4ouwdU!ItI+ky@FZ{LG-#!Z*Z2>$@^N=Nel*y9RG`(BBYUdKU#Rh&v=-uS)Np z0~WrW{iKJkiCBcsbPz(^#d!g8CpsZ&-pzHMIZ=S{m6pvt`>6k#@w8;Bu8VhbZlLuE z$?*V@dX{LT8e={kVMH~O`t>zhVgj9yFJE_({ok0DbpF( z{m6ZCb%kV53*1+d3I1k;DPMVkz1HYpCG%PtHvr>W(YJhRI<9a@@7gWm5;?hzyOp?v z7fRX0PECh@d=5@*P3VmMot0t;OKz$nDho@ErYqz9v|Z3Qm?Ic#x4x#Z5d6%OSr&5q zw%feqjbuCVlwMOu;5;}R)i^JjF1cLuvXOCzc+V;HASvC%+D(7An;GLg^YOIvs=Q>b zHnh$YZ#`^yveY@n=U$KfFS}3UFXNted7sHQbn~4k{^NW))PvgnNx#V5WCyZtXO!w7 zeHtC1dkuM8azK|PJYTAjiYB~XD`Z^4r(T2Z3Ew}A{orFLyaSz1`J{ht;*TS#gpzi>PVDY_>3BGtyJO;A0*51vd?5PB1>Uu68qf|F~-c?>R+M!oinLXW^Hk}qWlN8(_Ka1{itNL zV4CLn_51F%_8SXj(_o&TWcAFj_j&JYGoi+dgecF2R|alsr$|!e&e?;{8Ms?y+=OhC z9g*+{GbFYBb8t!iqo<4ajU@{|Z?5JaPw&$Brx3_#5xLNOVRy;;>oux7@%r~YvIFhv z|Gr&5wC1%QzbA@vc8Txy7Iz0mZLz&UUb~kg$zG%CSFZg5XNFUHgccI};dlO`QBn%7 zEX*QM0{((1M+~QNWBy5gN12op@z7r#juf!BOh0c3_x}=BiVHodGq+YAn&j-soES5UKqFbrABwujHNQ2JEh%2Xw1l(_uu4| zuadOdv+;w7?eLE)E$O+EumfuMf*{*Ce|Z14TAU-EUOAsCp^;5U)^o|$ML6$oS8TNb zcFM^7T#iy*$JJQ~2i>X9O@AiPI@vlgt0f4$MH&FB|iAd^7-E+ zj`?KF!vC@N=21;$UHf49S{CJqii*mlB1T0)MFk`wmZ+445)~DdsgOcMfiTDrAc-?Z zfq)cFK;j4@lavTVAW=cWAVdw5OaT&z5JE^o5;FI>fvWF)zy5yfx4KvN>VMj-$i2zE z=bpQVXFq$NlXJ1RyMI;uEXz6;V@hxvgFO+<#jokQXe+SfU^Zb$7wdW-lJ(QMD;kxq z6mnx2r6JdBE|{Enj&<;oI^Lx8Mt3rdVbFj*#@~XoF^)pWm-(=xgY~}4)yoy>amDT9 zI9J?(G3^N6QNZ=tVk+7>?A?o=%MjD;49Esy6*JTEFVyTCVqEXf$aL;(4(3|g`4r7l zwFOw%V?6BwGQ~QaJP>bR`(Q3@Exqfj_qY8GJr6(v6B@sUy_H~_c_qwgpnP|&{zhx| z;vPq$kN}tYBfYPLT}7^7Uuh7Z1XIEM5j%>O)r&j2>cqzMFat`~_Id2BJ~5`n7wW6+ zl4WOXCkcs6+#Cd5`0OeCI4Pi8z&1!y=6-SiF5k?yedE&=w}ozl082Y_39s!f{9)MPtm}JUO~T=!PNfEv(C00B(bj&c!UnE#||L=LQpU9(Qd0(?|q= zfSbqu#KDA{$XdnWijRuQhlC})M?j$lZ3dTg9{IbFgz zxF-wMvtwj6#pn4p>l9pgCh9t@kABBb7)g4CP=7{iW-`p_+=fLa&6qmG{e%@FczTAA z<8i)1HJit>2&?(fb2F>P&W4g%xddqt#f={+N=yiw6JV}BV=vf#+|?0wit{lK+bBO) zD7GHa8*vcrDU{CSCiU-A=(Np5Su~qD4c_bwiODOm4fPJGd%j$>Wt-W( zD9#;OiYC-&i`mf_)6|O9DS9G!*jmv{>L>a>AJKxpl4Op#G#?j=dGx?-stUnGuVWan zu9-PG=7`|M9H+gkW6cS|pPkLa>&f3)_2&NJPM2}P;+?0SSJcBu13FdnZ-eD}koJ@~z zTv->8ZO=Kg5#~gq+mau5hn&2{-Flt72zkf7Wi!UKK48R=uQ%l4Rv&Q7Q@ z;k(nT8>j?)rIc$?r59+WFsbN4tJ$-mpb~WgsiXd7B0K+u=@g`N81! zC*K%+cd3c}l8ANoX?Fqu>*U=h!`#!}uF;~;S3RPP< zxOnJsxUB`+S_7Ae3FCglws*L*!TnV2CDBv4x$vWdQD0}}=NzM6hoj!+v0~(2D-__g zGy1h&l*jCE`e3twmck9=1aDG;pp&cqu2gZi3EB4sFlPeMPN`hxIWioz%6hG2R-jL1 zl4OBspVY3-hMhY3v3YSX0e*Cq?H_NM8e!UDef<5%g4KPyyZ7bKy@NjRym>utCNH|U z#o!}u5Wq~v$q~XDVtSfyk0ttIS8KS*#|yr&*JFdtXM3#ogw!pa%`n#t#MB}9dZK*< z&y;WTW3$`Z>*Uvdd1V<1FJ`-_T}yr6|0Mg3)*kC=6^TmaiWf$&kA#1VPGqKV52Tmn zX3pagN<}Ul%o-kn+C(c{jFj&z%?sT*-=Ef|26)g?RC#zXbQ`}t_^ol&VvMP~;=rhX zxN|!9z;mB{q>aQDzM|q83tQmg?wTDA%a6;s%sDuR^@MM2oYX;R-)-umKFt|k(em6W z*DcQ!b7^#$V?H-}0||yafV&js+3(A-YgEKkE{@v7uXyX9S==&woK|Dq)nTAWcV0|# z=E(Qd${)3dT?#-TJohTE`K<1 z?-^ri-&`~~WD<^0Y_88ri4aT0cD9(jei2LXQ9ZZFdFod!Q4e19I#WMNF@6%6HY ze6Q*mip#^vAZ(w8?}w?6J*#FF0hMm>Ebs2Bg?NIQxd zyR8L2y_Dpfd^?do>g;`!;p0rAr&upe-Y==|Y7t%y&0kZ-3I22;0J$n`6Q(&WE|>9f zFK*p@XZQm~#WA~;Z+u7>=AS|5a*Iyg;vTT3*?X#wg(SdHziT<$3Ku%0b5pq$qcG8t zR_X@f3)P(O4z=dO+n(iM9f(dzyk?I3Cei2Erw)U$3jhyMpR7&VSj1)+ZAlh8JB8GV z_lAGVMsO&hTapI2Ym%MxADf8mHLq5yKN2nOEv^?I3t68A8JK^(m2?{vMn5hiIS&H* zA&+kqhORAR*EiLC_yPpu&L;UB5F6cv9~{KMG571DY8v<{UaNja=4x^@V->-J4b`PuhSxDBb?*|J3U z1>1n|RL4oqLvCM9U2yB}7TilcVy4_K|Sp3dRZ9}EUXokY^ z*TH~uurzKl>=m+1v@cnB zvNQUV&)^+fH-~tn)jgGmU$M2^GF|4ZDjll--o9Pd;O0BLSkFg_f$dBKyS&##|$5C0L&5xT*M-crS@@#moik!}9U--uP8>r*f&- z{SA_7bQ7jpjkk!JDRxhmTY7Z0PT;c2%J0xxr6~zv>D&hg3a@o1`)aKHY5(1yw#IMf(D5oTKh5^Z6% zJT21usCw7XbpvrtYmo&5Ejq`mXy{-@&gwm4v9H1$s#ikB@X(N_GSrQl1>tz?isE0#4uN zRL&EuPv-{ubDLLhIG8>CxRzcy=hAOp2c%AVZM4E!w#St8g6N?|Uwhvv(5vp<+5g%q zZsrK_sNo6xby(mgMK-{_oED5f&&=6tCvZ{eOpK}4l9IOBeR%=*o+!p*y1|)R?~%vz7rPUQN31jEBGco-(oWqo z(N~giO^hJ!nn^+sx{|0C{mh0T{Z48nCbi!y-*(Qv_t?rP`>Q_x*{m1rTC}E{T$)c@ zEj)qDm5Pb^2Kd@og!(Pv74OD-V$1Ep$?o7MB9|c^QoLDXJg#48K6&|A%nx6pJ&6`e zsC%UM#y9$7@6`Tf)C|-6g;b*a&3M(1^w`cQT6kWD>dp34K~-%b%Yi>3hBVe56Tqi^CRPLE>b_-V$r@|p_;x_Wr3(BzGMe3)bugJgNbbUZQGI4IMZTcuV%vUzd z&8p!gD>OEuvz#0A27L`lId1&{gi57_?E$5iP3`gK+qKd229g7+af1u;m58$&P{;YtaCWF-OVvp*qVrhLcEgO~y4KXK+@jd8ZoYh^EZ=#p z=&k9IKjQe_C2`wSn}*9wGDc!H;gXbByYV%+A$2$6hVquR%pkRkQeHGG+=8Ge9^WjI zh0Ywae4r2-h1>8<6)!Vc7MY(8i{OSD9P$`V{Man#1F;+3Y9&8d&E5Y-;FI93Au(ns z=G#^mTFQ>tJ6aK5%luY4Q_OC4f5lnJ27e;Z3T^hP-$_E}*=O&ju+=-qDZcA%LFENj z=2iB3GFOq^%b=^Ynnl>xKgfp9I}a?RgchAAR=RC8&S}UqE459!>g8|?uFpPTc(DbO z#k<9gi+vd1{CIi5@^H)CM7@=_X`bZ)-){UxN}QbSuUe%{HZC13U-dN^X~H(O9XZNx zKS-(inZ4G-Zl!&%>tz$x1NO5Ou-tEb)Y>X?S|{p>Sv9I|7+do{|6ZJ|~w zcyLSg*qnBivpW9gTASj;*Ly=Wv(yud=~>p*sNj1RK3SdbQBQE2gtmWH`zfV$dB^3e z64Sz0a2r^g2eao+@GZw**Jy^9C)g)9&QliD`Y}F)T~_zaF?^02&Z$L*;EgNWoH!Ho zu%7$%ncPnwV|u;xF`b6uIovIUM8Js;WnRV{c)LuYITCJ@?d-1Z@pO{=yt2yC+NwS0 zQ?Qxh+|qG_JeB3Ai0*qG>pF{rAKi0Ng?le%&o;1QoLYeEj(kNXo_{H~sxJSqyw+xE zm{BKVg7=&8S9H2xLrGeLa@88fY}__}jq_)s9NDxa)xO(9qGz+<4c)@DI-8 z26}r~1^bc{Dw77^?iNOj2(e~vm}l=_8990%5t9ksM=~+|KLU#ciRE8cbr3BUB*g`n zUJaMc=seXv3F z`Z<{2a42=zD%-yRKT=S8V^eY*%vJ{_qvI zE&F0^^?|5f8jidsFhobGYmlYw2L~1K%aVsjtv^qW?E2-o$$Sf|MhWJ_=KPsGiNTL> za@8P^-E!)8!JZ}ANzhX;ZL`$p6G#{V- z_VGyB-YV-qWvq`>iv)IqQXrC*f4RqeUPTFa@N}*f*m>~o7W;X;Nh?ag*w)Mz>To zr#LritEm{UzRPKtah;~yP;Gh&wOzfcNNsA$mXFM*uy@V%-P&&cBx`%$@}>&^LQ8gI z?8%j~c4+LNBul=HLjd zuopEL=3K~#=)W2HCd*lR97C#+AVOB;;=0=mUv#r-Blna1@U=5uMQpTBJYF36Q&={d zLe;bX7f6bhSUvuwbD!y|rMTUyiq-BTcJJ~(N`m(b&`=_||MK*^SI_h3oxYCsy*7s!PSlI7RmX8ZC=jYNmU!3qkBHW0%U5L0 zm4d2Q+U7MV)N2;)DtU`=v!y6Te({ZmrsA+v%vyH7=VLdOJ4Ye&$>6E0qvyN%BR#M2 zkOc%DOyB5*sAN{5pLiFhG9*Q5KB-i%Xg|^&oiaiX7CO{dt$d>nWNJ3r+73hyW(Z|n zRm6s#{TJBL7*-nLwk7OEvU+%f9potX^Q zHqH&lv4d2-)ph+F%bd52fz__Owk}pweQP$WH#FJ)+hEud94*&UQD1tko46l2vVnqn5 z2Hl|kjlm+_dx6vZrCy`XO6At)8NY15tOmon@tUEsuHCqqB&WcwRAhRT!_V#PzYK;h z#7Xfevfr3+=5bQgsb9!696r;hY&Hk?FY4T-xHu28Pl$8p3Vp0{At`SxbaKAs2WoH< z*UvQiRi})^z8n?wE=Z5E-@@aIk81+%cW%1w2Q57D%*cJXFA<5`CW``<=itXxU$m;IrPcBk;(h~ZUM zjyl1N&AiYlh|ThN)F+38SNcPeyOmtOv$eB2{aGl zKe!2#aii-_yqA6G{^=&GN_#DttQJpFPwpzr>l6kU7sKV+izWb2>U+I{KB`mdx zm>xfmb5}vJ;AWurn8v=x#Vq!SHXR@!*%j@%^Qp9;(p`E&)LvEp&EOW4VzH=PxGfgf z^Zpe0Mb2Z>m*jxpr($PTDy!Xb(zA|+U)lXN_*_}VT+u{bTc>r1BUfOvI+_)~#i!G- z>6DR+av&k4YnBHVlm&jqjc%%IdSw5SoN?#~ayY7!;%D^64E2rx2}>Q`^x8C_ zaE~f*AZjJvG1^GN&UsXo{q3TOtiwCPS5Ss^Y_;1tBD_<>ZNGhvd$^A6erN~Y-|>`_ z*gedtuIcyqcJR0q^&MjY2(kS8!H!?VV^O^d=PGO0E8VWO(M?{B)De269z}cBsxa-t zT!J=e1@XE%^o;6PPPQ#)_+kw^VZcsi#r9NtzPZrugCl*XTPe@Ot#-(X-9<;si2VT% zXu0sa(%-uKg&r+b6FmyK>{cnWOM0!x z!M*mE$ViTG4>czwCE*S7s9J?JnEbXhJdW9P9@&#vkZ~*K4th?Ny`9zAUis6imO^!u zy(G=rIga0t22YQUeU;W30h^~eC{?!#Q1>RgKg{ITQM=Mb9}V8Wf!7IqcU*@*I}x!L zx$}X8*F;nI4-VGRUp3oo76h)w%WPIf8yQQAN4Xowx#W(YF~&30b&~Uh#_w zK^J^UxU#3>CU=GLJ^kx&;~h@?PT#D)0FOGhb<~BxA}#B_?H?BuAPaU zB3+hqG@vu^8g4T1lA^w8JxgDz{@y~&$Mtm_R^o_0Y&oc&cBQkKjtL7sLBN%q{nkAr&> zxCFE7p+XjUKU;L+G-@HmevT;S-RW}E0r1-m79W=q7u_)L8^b#C1hUwkwR^E zU!|99LEQBlpYHSCy~bfxnS&-@SiT56&0cmLZguW?6h9BqLbSgQ|I}DCtlr3?&YD17 z>rS*g!FGj_vvJ|Jb>fojbKE9gAiRHZU3C&HkamBoxB7m?Dpd8(uej}TB7q{X&oFF%)#c+Q7#_-$q9aDeX(66_$zPjstX2unCu8MGB zU-MAt1b&t6Ks{LRi~CZvHaFk8<>Y9_PvP5J82&wGsX6IUG6j_hxnM_~zpwcY||ypiub8tge3Y!_{FS_tMk) zNOfj|IDbxZcKD9s@qJIsT+gaX{OZN!{y+6(^9y(*^L85(RK({vFfQ6Q!+OaEA{dy2 zOW{Pv?pTzTsX{OaSqqPKB*fWh5ESe%&&+}cch}`|z%T*)m}3GjV^IJ77dz1w zjcIsN`t4^X{nsWYQ6!jbO~M`u7;z+<7oFsb<2=S@i#8|HRS99B^9qNf zAw@9QG5d#|g=xKQstc;j?)iiABQ?GainC{O!tE&WdM?t4Q+mJh-PH}KWym$C9VE1G zd(>&kX?vQ>=#~X;F{J&)Wq(rTi}^3$sFz`(CJsIl!)>Gwk+-tyVmybV3Fe8bWWP}a z+f+Vod%Y(YektlsUY&EMA)35*tS+e|ugu%4@QkU@3>gSUrxSyH`IZH86X6# zN1D|YUz^bvbhQ7*$_60`P8{A#${Dv=V>@A_eJ8$I8NSK?F*d2XB~mX}Ap6CbIu3v0 zgE6fTjxm0X<74`KjoJGC*k9kckiNMW=GMNKM1=G83O&~Hei#l5a(7%BRpk?ZGn3WO z8WXUyhN-zqt{2(b)m=QO0p?4SR z2Yq(!6&QhYY+n0TsKCyuX8>`s^A##I&-oPdF~ z-<5xjC6{!$7v9KBQvNI6?g-4YcXndrq6AAgu_G6bf^(j~;NF8L=D|_@xArnN zUBbH1C?dGtou{k8V>-7cZ?G#A+1!n)F5kRvSa5^C1DZKRy;Xj2FrrRuN9FqNPvgp0 zO4a(DdoRqujEN{ne2s0zW}s?tGR8E$J<7y}_Y=Wfq+W#q%S41wdcjcEU)F-*y0!?f zo*EgEgIJZG#@*_#_HKnSAXBBm9}6fA%DtlKYFWk^xug5l4j6uoKv~D~>&NU3u|zYC z!}e0$m(+>Zir^%{(pj}+z10hl(H}AAX(FUs8F>vY4_rA_+0d1^+qigg5oI-*&5QFS z-{IvdI6i&X z-;E4uainB5i0@ZhwM5R?W^aZf(M53{q^OtFyzV*bp>=)N=h4d2>%}#Ss?CMAAq{W4 zSIQa_uL@>$HuQ52D5&0Ve}*UaE07LFd*zn47Q9LqIH<6|MU~eY3?sdV1bt;wvhF4jqO0ALVm_}9P80FTSY*UK>)B048v(&4XS;<*-9!-fWaY*DpBOm zwYJ8WK|AMXl3OHHw0 z_}#dp&1Lb|+%u@Nu)w)n-eC)$o30g}puQ+%xY1nB*7Hx|q8}H=t!0^~u+L;f-{8p$ z1cPZ@p?}p%b=*u=qctld1^e297Yz*#?k3UifJafp9reVo10&k3wTWa(@}Yq^Wub-r zLw4trLRS*K)T!rF3b!8pxS9J?F?Bx)wqSS9)+MBz$2IJ@%iMbUW7G4%SHqdca8yX| zAD2sP6BDQxW|3f;Yj#0DI2$C-LbEqho}cPiDS}HXJp04jQ1@1sfk_=!c4r?k(N1@2#WljT2B1ke1~x(UXEu#J+9M>=CQEc z%5@Vjye@2Pb_+8?-D_ZPrnMRw7_$iqK1JL!!8D68MUdcx0$#`_>X{p*W%&-P@wT4P z=B}oNk%!_oV=~zF-%564yF=!a=#H~{-;G{X#B|Ju69GP3`(ahyeG92Idnb zxP2)m2s~Rgl}oTqu8FLiHGN1<@%IGYdvOP|&KE!x2eW8kD+jY!**flUMpE%hBqGg| zsx+s6^Pt7;SM==AV+}ArUdSc8gEO4omvv|&+!tdeH~~?8(wn7ky^pVD7*K1%gkRZa z_m55>>@zw7ub+*LXBF-IGgw}BxHPaSw-bqZ)^$o+eU*b5i#w&XX^Q{d9RP~KTn6*- z#Ar?04)ULRcV74JvK@P*zjG1Rz3u%Mc3s(IFS2U2@EN~4sH*wl<)>TK`azGSXRkst za8j}Oew&QkOgIq$;@%&e}ly5|V5Et^Di&VMhSbjD~mz=_{;5Ov~F z?8xnKoY-Nq3MPW*&Wu?O=BB;D%gG>|{VaU8voC5B#Ap20-?3eh`AdblNE zhD4|qHW(c=hw&5#Vu_znwc|SX2#|X>>83d_M1JM$-dYeM^ZMi$v~w}57=F|TpFJnk zMk!p@J25A^_Y1eEDl1$Bm&PQUcYaxbF=ZOE7uaYRK#4OMEcnlGqCI$n^;w>l2n@#I zV;xn0at|DO-&5{VC(fK_x-MOU*^9g<%&DzF)aDJxhv=_E+Ze_U*(U0%4T18CUS;Ty zJ&t!dd9T}b5QF=Xbq9Y1euo>jjD1{bF&YQ1yE4&3oXWwR7@7o1TKCp>q}t4V=<1Vu#zR@cbKwrh@$Tb$!j^GzVfLi@zT0~SG0QG*6JydQ%0cz(?NEtlb+JouwDgfJ)Bs_%;E%_&SDri z?o(-Y)bY#uFr#!jIv;1lIlDT>)CVGm+MhU=;lxuHZZ+c(U@EDDJ;|u-i@c~O0hq%z zz+p}B76WA*%t4gM1@+WS)SdD0fH8&Z`G#F5uGtJMAo4xq+3LPORMC9_1Km4%mnt#X zx}L+Lo%}f3Ga>CqM*wv7OorwN9q=$X#*}t}b*}~=W2gYLc~tl1mLfRluKkMmRKY$H zcb;fp_0S0B!0XkFL+`~L$z3u`YJeeC7RMbLSO`Ed6^`ot5fG4zx4l`uo9rHp1MmdQ zH!MevXZ z2kIPp+`^9$jO%fqL>p#l@Z1O_liU{MU| zVpE*LxE{>E!;r?uwj-Q{>n2_lRtqe_>S;6-Nd! zql0}=+SAgU`x#6|j0bQ{lHGut{7A~FGz7o6!;nhOWbD|>nExr3f^VkW#Q_vxBfyaF zpif|_;MtI(O!i|%a9jhuv#5BpQvCBcJnU!t4I=ni$c>mpY*ljp@ z4(9$rb&+1>DpAS0L3{!>S{}*|X#cseRsiS$KbCFuL~vvG*v=UYKNdCmZr!2iI%aE8 z(4(lbxBVzZ@$49q>Z`?h7V25nFbAWMGGjjJmoQg?G)elhR-nCQhqWAsYZ9N9RArlU z#==5(j!_An$j3$;si6p|Bo(N^lkz$M2RN}JUws-wdSwgRt9cVk1=Oi`pSnC_-{e`q0s=0p$t3rrpv*w=>{pdEZ#X9Cpwa||iQ{Q|-&@Hq4be;Ah5<$h2>-j&Q~h;~Q~5#+b_HmJ{}pU}!+vu5W&$ z<nHhKcH> zeHhXDA|Y@dP5d}qUSJTt&|&ov?fG$d;1>I*wyPP+E8OBd)z0U|-#tX|z~kU^(bi5a zW(M1HFDZb#Y!bUUJBxOiOStO5Sm=-puwo!SsX89{x~kdezWbaD6SLZdzc?VQ)45QJ z$JPGua9K!E<$}dOK>udw{{P{J)ai|%UD4sezCjW0e=OcG_3btAP0S4b=gZKMmmaBe z4L4kyGxMi;%eVag?$V6^f8+msAsn9hEBPNqP3!C5{za2Dty1^e^eS`hoegu2LzM)%* z|Lv$H(?=~kd+MnM6-@<6p;5{1NUuWx)%< zXE8HIdwyv?Yai7sKYdGfcAX;9ued(%uue|1Jf9{88K>muXw4_| zMrHR{Fm*%54$T*hGfg8Q^TTZ01mZCid=!J^Yv5+>+i4+Nhl@S2cm>dTDBuT|Klg^#cK;0`JGr;-m0ji8quZz6_j=6wA>Sc(%fZ zOw=92UE4cfGaS} z6#5j(eR)Loh=M&Kh-G&aT9@KFV*6`&&|A^hQK*+~n{Dk{Ida>eD7N;*y-DT!;*0q2 zrSh(1n+{wH3%7~srtKIZ3=<3(IFYf^IbQkvAc_rkQR>^Wts{rvlFg)8D`v#)9B&>< znPchg*xIk*4NT_2Xp!$cJlSSD)pgQAW6-z44s(i9!qJ<=EHDDURNa_$rX`H=!RJIL~ zlml~xE4?a5>dh|DZo4Dopkqa`XJQ*{Ac3?R1b9knz_q&-HKeO37ZiV@hTx6}Q@Eot zC!x0JQcX4V!N74;W=yLA=toU)RZ*yJw*ZCt$kIZIFX(2;L3%j+T1x?4u2I8#;$WRr_hdVbLmQ0HsxCpg& zpVR>#4+PyjkJ9SyS&6%$>-IoR-t@)(*&Q|~XK_Ur~Y%c=FAaq9=^Kb&hLcD~-=o=yUnaQ>wn2_~;!TyQ@%K`(*BCXjq5ep_M zZ(>D_GohxYB&o9pFzI-RrM!t0zJz7xaBErm*)ZtU4Eg~~MJZkfwkux(3*g?3dmAfa z8Z^!&?*!MBf{sA_6H_@=jmo3;;3Ey8T``e)(u{kMXOkp7z=M>30=jW7^#7D80<(ZN zH=*J?LFd6eP2Cl+exR(7F!l(xh5M{3R>Z}$8qjg3NbN&+2`2}1D4CC=Pt-j44OkCk zRnQAY+Lg+x{_2L;bp+hIl=(ctPJRIi2?1DnvR1s63bgc=Xo`#;4~U1<^5Ec6B&8D}+q14LdPONkWRl&Fpi!ok0`o zVSJ4+m?aEf0V$y89o3=iH->5 zq^(qC9jBV8mN*MY*0pF){18(z2*9=^j`c_%05V@5qN*ja6nzYFn7TfPyHr~%32^K| zs{o=)iRO540^55`1z~q!6#)WvVnjJxw`;Nz>~@N~+m1l;?$Rgk)G*v}o#OU3{bY$_ z%j5$e-gP9KHp(tQ;s+wtVTx#MSWvs62QsKCbRZIXBSM4PXEKeLhCp5)3GI>Q2G_y9a|?4`FSr7jOhwU8Yu3Q=h-J^D0VjRc$5nAG~jDJtZAGE`U1~OKml|s zQcivXZh^^ZR4RAIex9=Xh`fvu0vnATNQ}$8DlBW3+jQ*O1@j=Qa+)UFa-t-_lOzNt z4Ztb64R(TT*QSgG7G8kT)Lg(0fH&~kj$U^=;b}7T7Tuzmffz9rH&%E8;C4Vlz&C{w z--LmGL$GMV@r#DQRV^us9YN`w7;+Zi;5zitDtYn13BbK(7DE2%;T&W-SpxjwO%8A) zfQwjU^%Up<*alG0C59Xr!~$?glS7-c*D=QSyTB2spmS65u<`DJUt}YL6&1u!bnG9M zWMaca_dq#u1Vl05xPJr6z;Q+}DXfZyehQYFLWDhg3GgoVtXF=7q()fg7#1V|50mE^ z1cdTHAX3$g7zD)g47zOXgr<@AH9#iJv++E)3PlZoF5SDhmz$?I9pWH(9a@Cf!HG>_ zEEI1cSY+ye4+7RUSq2f?NY*qn5<*lt&vT@o81ipIa7S_*7C@jZGNi<5jOL#Bq`J&5 zf)D_L=n@FCI;drRP&;Cg`mA8E2B;GRZV5`&w&<>*V=xdD9|9Cz=rrbG>s2pdc<>>E zAQ_GTEd`dKfC{Ie4uEuoncy-Y03bR;0Uj?)l^+8k;tXa$ha^w{nkECs8Jj~q1%j^c zzd)blzJ!7J+x7Ms3X&7O)Gu64cWXjitr1Nbd(RI?b@Z7=L)l^w75;2uK0Wum+wbfasD zBeLMKi&eA=;!|f?+-QA(1JVOOLgD5Ljf}MNmp+=4o_J5dJ(GB-N)io1E~yJcAKF#k zLuhIx4nBzxXUyTw*VYcmRQ<${k^m}#CAXEvBi)a+LzFc>)_VnnSSW_I?mT)b62MrP zwM-7t)d|vKh>DtVL+KDK`mtJRTk#Lu1dXE1(g0KK?_PlcOszQGtl7r{1>E^C+aJ(Q zO``TMVwpxoXqV83S(1;%UOqwUSCS6|F7{WPnNrMT#GO!2>?BbELlD#kj^OgFCZ4$k zwa+k0KxG`3!m{}EZHO|UDjnVX0|)SID)HliLr(#?7iVYI55B5cB#Jdb3bz_ z(k#EQaiUu_&{C9jNJp$}igY{ySRB|jfII`TYp^NsW7vWqh=lBSv>h8?Zia#3B;A0T zbd1f+)Bqy5yoWDNc%Gw~Vyy$;1S8!z!?G!G0b#iU1Z89!u80gVCg2CQu5L8zaD9L` zFyLIkAHjvLy(D!+K=C#U;z9q_hk=s%EgVA;XkYh|O#7c~n zm`tPz`EY9*88ju-h3-u95LX2_IX-p(&QM;H+ao{bkrY#mL+Jz12Oo&Rmcm~Gw&WA* z3k*1yWakA1`E1xu{V85Eg%Kx_WF@5}Ry1wYKoUW$qAid=Gm@As#9c2)fjZNk=1Gu; zRyO4^+MBW#9;@g-@OQt z1R_lkZ_jMgDM1G#&}C&p5-+d_Jd+R*BtG^U=qV&dJ876cGY!dxZUYb(LX**dQBDZK z+SJ~N?>fE&dazv*AFuK}=M8mlnjt}b7#37L6%N;vg~0t4IB_vr&ZI?NAG{1D1rNw# zH!4sl&`EM6?jc@a4gsT4&ahDV2Gy?iGo50^D^BYo5z7NeX-HD;ytqiB!}?9uQ*zZM z9y;3Fro0nD0ivZ6Bc8`*FDi4~syh>s1ZIqlNYRn;F$-}Z7I0Rk0U8rk8Fd$+FZ2Qt zA|#V0bsX7cfs;&R>H>}*k|<*&qh3tK7UM2;GGL|*>>oH{+_k@zAGt{23#B9f$Wr-& zyT23Zr3eZG!i+Q<)?x(Y$E^`Of#Z4n6o-YJOIardmKY?M4=Gq@jWhlcZb)W!uQLMn zeS<6TjKl~t5CG%`F9Cm#HnUH7%Yx9n$C*!td;y@Z1h^1~$gjFQoxFfx{n8G2*q0FCmx3^`hLdVr~&g!+G*XfPLSr|D6NoIL1bcUXtcews`Cj@|BlUYgQcUGGG14?{hc&e&Kd_MfVzZJ z5CWpHozPLL0;aCBTyPoCiHJsr!ZDx7;|RH51?qp9u7ey*ms^1sk%8=Ds$V)Hwch?0Jyf19yi|phnjjz!n*NC`tpcgmQL>t10K`5UgGCr#s-+ zQ|{tHwz~>-xEFAT764cv&bU|=1FiLle$b# zm$Al7CELJ*-TwfY7LBjqwuWU7#O4n_W+yFMX@&BH%gF73hEVaS^TZ*YGr9kJ$-9w6FyUhWw zzYrD$d1ka;uxq)46G~mQA0`YEP#H0; zZVmtgp>U?-?`7p-2%Po=Laq}yl1Rok<^5y3Kx?^xTSBo)cgjF+TC=-@3$UvxeFF0i z8xZJ0d=a!Z&G!ByWd~euWD?kgsu=0RgD4(>+3ILe^j7o_hz@`xX{F)+nW(d{9ODrj zmjM|Gpsq4U&9t8->mbyIrmH&q1EG+gxzTjxBpqV_UDBDx6cer`V<;f`fXh;+eHY(d z9Vn=J4?tBHpqaC$EVxD)74NguUDgDcC-Z;9JT=tKYxdt8<9T#`?DUJX3hLHKks#~M zsp8Ji){F zF=-S>C0p)tWY8rrGRa++XtS{&RiWw?vM>%2;AD5Bi4J)MTNx0H((Sv25DWblEkS$I z$}u5=L5RnfnK=fl$VI9WZc%}maaZhnkVMZ4P~F2;O1LP1m03O@iw0;!?NIpgt{W8b zt^&@7$8}biswQeDJ`&s^{N#3wECzbHJEq^W6W{piN8(CV2m^P;n|l943@;PdNWSUc*$!k8!__fIduBQ2`r7 zAazs(GF)b*AGT$mb^0eB#dvU`1ow~%Pz1JG^;tNu-LoAJb2t@~g z=@6}iBF$B>DRI=6+fGi`GUHl&74CW(Kv*1fu?2M7fF4U0#Qz#y@^6|69Y_M#{vVOCR2OsY{zgXdKzhe)7_D-;RQz|K z0Qz=m9@I&i8F2=iY12AY&(xLvAaCbVh_ZJecuy64rz#v1HKH0Fi^}?Up?ZLf$4p`m z2)AmQ%>P??7=)=_wyA5}RD~0w>yc|{P)hW7fp|2Br#_mgdZWvQK_W1nRsWNkLwy1K z@&y~jZxLNn$(Tx(0?5Gh<^NTSA96<|O()cU7c@hs3z`&S1IWK5#KUF~a1O=>o%8G@qBe-cGOmVfL@s17~iR{2lK5NJtW zFtc}HrS{dt{}SnXkXZqLR}6KmUdnTH6u#u%jec7>T@HgH?tcLt-F`Wqmx;VuF$N{g zHdINjm#!crLslPcnc`# zgK~_D-P;FI3~-d-NW!p>$uxnSCeWaAM-@K@IXJ|oA)tm&)1BJmpyUP;XsG6@#4%-m zR2f2pJ_9FNXh-R0XmDYZKE%)&s!Z}o`BW95xEUoDsGFe>02SOKEYE7*0nP-%5!BLD z@(eZrbNM@aChG+I_n-{`YJm4p5-y=~JPUOU8v$#h+q)sa3SK3SI*8S&n8d3Bct6FE zr>I*o94e3egKlT0hif8T0DeIf^FLz-bQx2SWtz!;{<{{zTmOF(+*sI&a@&dNg2uuB zgSvMCYwFC}hG$;CN@uJxt!Yr?pD02b4oHGrld;vBI>rqD4S!TWV1vg>cGg zI!tRV0^?Xk<&d_vQsoe>3J4@ADxgJ3EkY1Tq6CN#$reJ`Bs(oc4j*L{`bHB z>-#TJ$=Yi_d+)W^y4QNvTF(=bfVneq0nl&TTG!knYPe0;rHHb5z03>5XApfrfDJR~R+xv3hR!P|hChD|l8lF`)`tTWgF9JKB8*_7IKri@ z$b8P5z=ngLIgw68rNn$FjVJct9dT)`9CvjtO#5tK;o`|WHn2onmH;Irb&qoMPjfV) zoTXKkoKPRd3R9G#6B%oQX)OM_CaWTt=f+EsoI?f;e+l|{{s<;{&l!H-%S&uNTnxp* z#F^aVGeaGf=5}S_XQUKb>}iP@E>r-y73Ors=l4!^C$ZvjE{>7Q3w>b;NYb~S;XF47N)uBmV*JhEhcq=`nO0JS||NW#07A1VXrzhvIBs#d_=0Oq`gV zFf9UT>34I5Ve^j4Mb`y85S&ev{(*Bp5cE!^f5YV*;boBZ9w}yz%;>8l#{Ey2Co|)P z@BX)89W|Q-y)Cr`j4F?d(>=M;=Obk4lVw!S1CwN`ArEs!l92Tls_oAok$&Uk0F(1+ z>E-kaOMmYz+_^3;B0+%3H^d@(Gc8}mWzAuaU&!a7Gqv0@19Q_H<4uN z5tsjgi3}pS14VOh65})a#WrUgP-^9{+|Nh6_e@^mw_ZN zo@5W*uEktsnP@Eu>_*DaRzP*dYsP;~YA(#TX1;9brKrn;wF6H&NPl~>Zo$B(}qSkNZc0ci&}B5qTJc9jXgOYDtF981;zc1Et7Qde9;&o*d!l3 zV$R|wt!bJ!JqY;{4S_c^F|`$|vot5o%-K&&HpwRW$Uyq*z`!`ZA@Z^>n0R3xGT&8s z=ewgtBQBCQEa>8O~slrtp55<&8YC?$)Iu7PjbP%TLAa_wlGyfRyRWb|38fkfeok+){~H~lnUfA2gnrdfDfsa#>rYDMBW5m&jxcG zgImL!C$R7@i_L&fM3iMhWf1pzmYIauTxnaunXJ0_s8RTZ!*4>1%(ghF#-3+nQn z3y}1fjJFHSe8UtBgxoaAOmopCnu2C>$*;RGNrd{HZXR$0XkFq7ylY z;j6p9gOla-n#2(u*J6efCPU>?=H_sc52+`U{Gs(o4pIS^khJHc;6f(DQuNLA3LqVP z0NkQ0XW8PreQFc=#bTsGR`v3qz=Zy)pk4YBdD?I121&qAg5||rQ=B*Bay7s^5FP+; z13@OjZmvi^ks3r`sxXs`dBHGwG*#gE#C9g?3EW5X(heU{m zAffY0p=|IlS7O2Z_`xOB$+5<77PtF%C2cW{RkA-2A2qgmt|F3QKvXI3R0+TK!L)cx z5-8iMrIVg%G&`z1y{)#dIHp=~enbMWm!P6|J8UdxGfl!m(*p_8SG9HD?XQ`MShJ1Hqzp;H=%hg< z-rGZhDT7+@5Eo`x*2R$gJnn;wYFoZ0zxCexPDrb-$nv^@yFmi`R$2VlA4paj) zZS(&Z!485xNk#xEq}}PpxuiPZ!3U)V#EnlZp|@C;tR1{5Z(@sjec91``L(2ex2b)7`G>#>#(WNlD>OGq-vk{*9R8~fB^<1dYYL^H@+(s#_pocYcLfmp!vpjv= zCqiROu2*_mS$%4oygx9_$&Tl@Q=`5`GPC6aqo_||dN1dawzzsQuVI8l+_IGw&b9u| z=lwIdA4j;qW39hqi(|X(gN6GZ75##@eJ;ODays_oa(h9@$f0ll)Qv334XNfm$(w6d zB^)WQzk#l{K;Ft%@vB;2-YtBmkf)Y&|TV7c=GTi-G5}T;qS~x{py-Fl7ho)tT zb7So(w&Q`rg{jV9YBW`F(pxYL6t}d)`StP^F|SZ`M4(?EVjEnw)O5Sar%TY` zsT=dHkWbZ0E~rj9+DfNbPPtO~nQdLS0u*hE^3Yjvd{^=Q+!V)V{CS|r@&0_C=t)JN z#x^^|b|scyqN%R3yg86zJDe9Je#PI|nawj5>-n91OVj#~DD1OCXzfTzrM2l$uBScD9x0^x2YfY>6Ot3@rq-|GPP0b& zNVA~Ex@*XGzC~`+Y8YK`7z?M^;BITVLPV{55i^+JGzp!y3!^+r zb4@NQ-AbY!cH$>!NG?cdLfVAI2Wi#)b&zYw>1)zfKCt#nnIGptbSm|o;L$vY~4 zifxaXw@(qVQL}7B@FW`Sc5S8H3AOH=q15e~t<1bGszV0p?1(w^hsTE1!ZGs`mh-PD zE)Av@c1Z&c%Iuev{wJO12X~yX4|m7!Xebta(bjb;;n{f`8~2=Ll;)f4=@Nr=>}8?z zEGvw$A7vSJ`l7GX6Bf;*Y@2Uy;P+ z^oXTXwM63fLAKjx%vU42&=N0s#e62kY`=aeSC+aWQuXq#L*#upWx#*rf#H5>Uo zmwcLh@&lo@&oX1`$M*5Y==vdPndc^}78?Gf7kSjeiWswcr?yNn-$(^g83U`H(kkuz zH0thSH;x5Y7=5CO(`RHy=N87Uw6^#WC1}++p7;Om&t}KL#y^@PH}LTXod=FLX=!Wk zUhO?Uz6Wy6U*V=24Rq778tF~h?Aq)aOF~;$bBW>VXX0p<5ziZ5uNsgmvd#-^8?~2y zJ_2Rk=m}QTwa1O+X$OTd6rEpLPCGY*SuzWKGR@A?q|ci6397A0(gU%oHi0foZaL*F z$*Rd|uh!T0i)?d>H5si&@jpC+Wf;laQHqEh@eLh(@wL#GaCy$La0uZDqMB z7EZa_W{2qF9Fzp6HHwSM&6$1NpJwvxN8D0lfl*tLaEh;1s4U}dnawSAsv0Tjc1^BW zW~D`xB{G<<@r*HpREWCq8s#D~Jn7XY-xPfB#aqvA;IC{6^Y7e9J-5=Gf3JkRze7&x z8~mRHo;*2&fDYTEitAnKp0Btx@q;7U{k{i$b6yrk=o^FHuYmzpMspD2?zT8VtXAZK?5=)XH3WKS`MzbdulU+-%7l z*b`ARSY{bh3)NIULvZgni0!JhwSX=Z1*;Cbbxu^Re*uOWIhvMDY<(!X%E8KP&H z(UPC7SA`m9cCRTh6wyCtk5@WjNcENn-38_^H`1AHpA9Fmr5+j!M*5EEJ#`}h&I4Ll zP8HNko7tz)X4Wm`xmAiXPqI|5kZp^Xmgd``auCdNYs|-WP%bt`f&WG;ftwj(jj>zT zSY6QW+%pEVl^P|+Kpv~MTRz*Bw5=%C;vV8_rdskEnC_rkA)3)tS(%J>ysHbPtBNbe zW##gMeXT-GR-6Vmu|nAo)vB*A7P0XWZ2!{q-ldM()W*;yZu42e$RW>Oq6*6nx!xff zSYHP`AB(M}3#jSy6=ibjGfp3fGGyD2m5)4UI+YNv_sOcU2U;si3<-RrxLsAQq4Gyz zi7>IRmMZK8u%)GnzDS*0{f*Q02fEEzYoG!HURTZ97-s%)1)rFdNUaN-$MAPL3X?*2 z^*e8BS^~`rkXYDwW*k4h0KVa431@k>*`BlV^>TX(HN^q{l)r!| zZd2Ut%VC0&rD@hl$76JsdQu5O;7>>G@V36CokqHOQi_FZS^^48W#(D@GTR2RlXe{r zX;EG>-Sgiud^*>%)wXl)R^r$a$t!iwqC)2@26%S?X|p4(9KL90DZ?IP0Jj=>b%6ee zb6=2b!#0Xaa<_4D8n(V08Oi9x02|B?~KIJvaGGD%KOUwDt^jGN5Qt02L#J)=Z#;g4g z%>g9JXyT8yok><11MPBE9~E12dA4A!V~NIANPMp`V0?H~VII9cz%w_`l^1oH zWCuNUNv^X2u>Foa{1VY9ecGLwZS16^1^=tDxHPtNoOb|qobxAXZC-=YHlA~;Wou$# zQ(#R%b}DYXZ!_YtuYUgYZrUhRvohNge|uRt_@YW*J2=!2|0*AnrWZ{sDOVO>rgQK{ zVxu*h2xIbL%d652l$L`iIE_M|^bbYqq73O*#I6%(tO|TXZiMX*_T*^V9sSD#wDNo6 zq4G;<@_fgWuzDcF~PyS@~na-Z%(;@9tpdMc$RBScZ z`Ybq@SSixHnX1`LPfPLs15__HcRL=a;3sFdy5ZJi{&c08;L@9w+`C_zR-U_(9z;94 zO6W!QA;mRTY8*AD>sj@_g!aDE?O`>DEOcQ4xIVBL$$wl#r_ufxQuU}`(i3a;MiG-L zN-;;1E;-&!sAg!`ysbJuY@i1kiI$sBT}5bLd%$YONG$V<~D$UbvQ8 z?kMxEfJ7cBvYcwrFI+~Rw4{<|nx)@uzlo+yh2; z-X`;Qy2f~VM*d;7ifLt4kXg|TUc>*#S?ccLuYGjgqe|KqPc zL_ytIcmK=xlYosXOo;Ku9GaY@vQk68xYfSLl2kM$PVc)u?-a|p``t|E8N7g>l=*7x zbuF22q3vhiR%+8*7He!}+Cs|_jeVoLtv*zHrbU~s^rQwKKvYA}3Bj)!`!?vBsBS6T z?O30S`cYf+vEZZg`DJ$CC7plg$2#4-q~*b@wnr81%&Dy)F&-rJ~t537T1S(O&InuH>;AbN6}9g?!6%Z172}^jO)ha)y0_ zZgQ@==vHdvc}F$u;xT-FlnYT`;zCq{qVE2qt*%vHI!_pCZdbFaJU%O8L`0R%J`1H@Y(CH;e6>F5oyl+dKcVwp`?oQi{A-m5R#Gd$E02OS@0& zyw(R5_eL8=dM*7PbD#Nt4W{pjut=YUtCSu3m#)$}%T|?h*@Ec7^cD%rJ4c25&ceoh zVSMtVPqNn8#?LJYw?PQwrpgE?{qGjBP2*G}5Utb}ALoQPH9IF)9O2&1y7XYoL z9+~cAu`r#i?5Q>M@3QEMP*nP6veU?z@l8=3X{mHhwp7M@I-I7eYQsu*jbUYl zC98~A5wmi*n*8PC^E(6C16f=unOW9;1kLCXolPf`1B9k=-ipkU;^6_Ipn`|SaFQ9s zijT&mTZ*@Px&kK4NU^n~A99_s=a?A_e*US?2>D1XP5kHTJGYw3+drKfisU-UrjrFI zB(2^(l2gJ&M3V*BMblQAY8G$U#C5753x@i)R)#u-e$}g*iRDAr$m%T525t#C>2yMd z^@nz&SI|6Cl$gk)lSCkz3(;(fBw@VttA)tNbEUMCWXT$-EeN$cqTh-m_ux3Dv7LIJ zG+Wt1sF_$nfr|ZPd%W2*3)xvDf740BmWlNQ#bUh)8a|5Sy^T%%?{HntV)WpUPEUHN zw^w;W1f+9`JOw`fyVUBpTG0bo&)MOdm(cU-ZKy}tVm`?iPsp-=cBDM~3ni)9k*YJ- z#pCU*?g|oM1>{8XFitjBgB5_@)hE{|^z`A47pF(R665U-w9Mbx_j7#;?T&3^B_-EdROBZYkd{)UDlrD~$3xnD{BFYnqv3)m>j23hKRL0M z$L8{C3-b@U+?$X`KE~T`S>`P|LH6EWB=WCUBm-3U(+caFZ!c^lbs)Zg6y%Ysek8Em z5GD=pL=CG5OBimMhi%GqZ@mvo&relZ4U5w41SI4 z1qEg!o3nG-uRZcm7%;Y9pjIuvHmmP~jk)@Ek6RgPI2tR`k1mY+nfqoq)`erS_`R#f z<3hf*q`dEP9$7yAcFz^>it<*$YR`4*TD5UzF;iVgd0rnnnTr+MwME4)KR@Hd3L;&` zy(@^W6q|j}7SFzp%T#%8>L-d^)oRl8nL_!E)^Y1Dvw`VRJXbouTmby-;Z_PwG)qk^ zAL?u2cK&G3A14^Sa#t{i;O!ryqd*y|-7$~sN#X66lJpga%6FiIPp!^YIL^e3FZDF> z4NlBnbi87@ZdPN8^rZcK`!swef2TC2gidsXqR17!>tA%g=l=WdclrN=?spNpECDFx z;TG>ef!f{k4UI*lo{9H`?vK&lTr^8*T|b~LwCqUI7xqi??{>gr1)aAsG?h;llibr9 z${{hg-28E}jRj{6q@o5SF4ov=q$ksh6!R1*6DxxjM0^K}y*2#p_76D((r8+IyuFMA zq?hre=)(6S@ek;KZ)?7{|DADs{=9Zk&Ygxp(#3iQhS9I*U1T42oK$n-+UtX`YMHEx z9^;=Qi^->w1?5_@92)ClPD-)h0sWpvXD^zcD*0zh;1s;814#E%#@GL`ay7AhNvd&l zRAN!IOLDVeviE5oN>yky0Ak$jX$MYcB-CH#k!~_?EpW9LV#U))`Dtl@Q8*S8Ufa0p zAQq^w7liY+e1H3sf*3*Q1)WQV#gr%ZJAhf50M$sRfR2K$W9sBd9K;`I5^R&?(OD`B{ z?uT`%-`#qHYwJ~bNVmC$DHK%DQ}1*Le`hU^cPW8aqtIsy7gEYxq$`MMx#f`7`2b|B zG`XjviEBqdwH}QFWc!UAD*yOavLJGq=i3V+qxRQ&7eroNPS!-a*x$;G{hBFmX^JQH zqsj`+xzfagYiTqw^)|XZ;tkl>-IHoKC>XZdYzmnzpppOE2zH!WT2C9}!&!&XJ_D7f zfe(zf&CW)-_G~>x*hOWi}U}3=&_NW~7@b z$q74>t|N8**%1pBS3Dl-@eo$Eq1`OVv5oKp*>OK(;Hogj_QD6_{ghfPQ631osm*JZ zyTr;{fr7BzI`>EAGDV?CL=_>C$(COx2_)6Cg{}5kOmeAd)OUp}p51n}e#1MA`$ba2 zxz$ab7tqMR7kxYbUK)->L4Kr-+{`(WOT}bpVkYFB4{`r);P+p7ZN!JnL?7`X)ee2$ z1XJ4)aXj+ygFD8#{7l=+{B4r<=3~tDp;b;YVX2X}<;$#Wexz!E^1sSj81#h-PVUKHxif#&o^!;49M3JnKT)WyQy3k+Kl?5m~YPHga_aX zNs%QFGMMYWZsQ-Zh4_Z+PuhMoAq%dUQ|NQ(q)2`Iy7R+ITei`$zKBb?)~}mIr#Wsb z(|5C{@z9ua#*13SmxF?7AFcfgNhfQi+oj_q%UK86rnE)rhPaG8IPL1f!fxi9RW*f; zE!W~JV-;VZ=PyZP5o&^G8R%xSYI%$DSQkkVkZix9OZQc8W|?n}C8iRosN0GaZn1wn za(r_&^7WNu8a#Wu^kz!gT7fC%6hEIe#GMyP$F-tAmNM$(h$3Wb_0rw?yos!EPfl__ zV{)o5u{jqCwKoN%?79(~T9F)31#&{&G5tT414WVG&6+s+GB- zRa~ayp3Lw@Bs%tf!#w2842%6E{OQqNn_(V(0k6)pviK;zsHnsJsz2Q~q87fgYi%A= zG%9N-r;nS(GuUdKf=0Rkh4E@=e}vAk+Lh*PlofdDTIEIJ z%wqX1-6|QBk$D@1BI(LT1(SS>8sKerwaX~euUGP4cYo8so-kx#k>plN+?{5gm4bBm ztQhlEd{4=@l2ufz(O4YIVWZRCj|vF#RYzG}qWVBv7ruWZ^mR|_{3NzOB-ju=M?iDs zMR`E7B|}cVF|W)Q=81e^%l^d?o}1NL`$n0$%SJ!sL}A1pIV*KunW!ec+0wr}Ty9)F z$a?thS3b7+pK7tbTbIO=@);`zaMqE$$gPksi=*vhU@>f@m^YGlT0f64?;$zzxSO_^ z*~I#?6?DU}xR^6O6vrS6!JyPhN@VN+FT}l7@I1TOQ>I@fj%@DGIX~MwnXKaqjM!PD zW6}_jSnjHQ`d#28mj_nZYg&dph9qa(0!_w+LEn*d|N-YgV!u0yaz!E_;Cr`~FENrgN@3WI$(;pf8 zIAfvEzTPmn7PX&Kwl70JS$vYgLrY$vwQm~LybqgwO|`!j8hsBejWzlXQqm!-M$M~r zTQpQVi{k0}b7wcbt#$Eh^h<|wH=3TxZz&VVE-U>}MIfGaw=Scvu@$LpPkl#3w2yP6 zPsZ8`qbi{Do=5Ho+Gq}`eIz?%a)Ogao_&&X=)6yZf~dRdQUlcmS4;O zxRP2f(wT42w$8lNOVig2QT}jIxmJ3%xjo2OD{!Wk%gWO`Md|@6^f`^vBv};fTR~qH zOP?(`%U_tFo#HO^N$aB3aVp!A82*On>-*`@m|#n7LyLu=@!Xy8fK77bF;VkT2qOPg z(T5q0*Bp(q!(3s{|7#qb0W!w7Y8_*f)+ZdEfC1O*R zd#lZpfGk&dpnY7miWPOUuiN`W-5LKaFt6I#?%pig=IR!dXwp@h2+iNl z@Y}DzOVwRJ%eQPgt22kh63nD%|03Ss*$@d#3TI~CY^ zvG!t|^G*=Z)>Y-xOG+@`>*ATm+%@vcLei!~-tj3{u5`0h_A!Gt1*^Mwzjl!F=(KM6 zDfcO-k?X*T7hSD$x{p#rR>^zv{v&KPYcIB-e!ZsaWg%U?Q6ZXv(lrXOi72AOC#b9~ zm#)ZRdMK=h*vCr!WTJPxO*n-*QdBIoGDc?0r`krw z#HgMqUE1NOu*;2s0ne08 zDfCv&?v`0b`R0&@maXVzIXN~8ruqLB-MwyK-PF4Yi_|&PoBY25l9QLY2=OoN=Q&O!Z5i zj1=r`4KR#v7fu(i((KHsEQ%dJZCx`oV6??^MVov6D}F53HZ3@}`F!G@yKNA7I5*YG zguWx*PzU6;Nwv(ijkHtA7^(ewHc*L@jrMh&Tgkd@KZ2pvv(;Lo=eaos+iNe8UKlq& z$=X$yr0^E&$pl8FeKXH@j6d;=T*FMEcC+~%dhF1h9-w<$;P8;%)+FFuq{A%?JF$*n%#3bCk8Lgj05e(=+*=hp zhHI2Z*W79|?_h`WEj z2eL4-lMpYycqi5w7UzGFVJnh_exk6=U1^b>s9q+sD$w=eq6L_YwXrP(D$z~|K$|tZ#W$AG4n80aQvfFcOPRbOi@}4c)c=zE*{~T=FCNQFA!zx_; zf%3Bq*@&`6pslmBw@tZn6}KDkfb1FyH4%)_%IzrWPN%WchMVT~aINyTRED(5yE0~w zjV8CT9b5&-MtgSYKV&dUiE$W?qmpCy~dJk!r>6I5sWEJzwp9abm|IPd({zm)+fr@&kI{gS-e) z6!=yeIZ|IAv^Zlm!$k+%eu;ncRjb6?Ge23rWf6vF+NO zy=sxJ%p^%iThHC~8c1a)_OIiT{ghy$$U+t|k(0k~BcgD*=!Md&3>@ao+F5rNf4m-+s((|_?fdL?f`!iDCG>-Nsx_-jM0Bcy-hTgH9ek+#RR z3l_I5NVq9^mA^z$wNf!YUJxK0(OxW0A)g&*jnPKQSGL`b3vEf7eEd4g+*%v6IM!#e zKvDIk+{pj4jNj)Mq^PPgFX*2cC?h9jMEO*CYG%0hNZvBfj1=+{?fo-n4N*0GejkR( zkJzMgEXy4U-sx~$$i^obKQYrhQ)d)6T32H%j9W!DRb|+ATLg*@(e=3Abz*ynK`BiY~`N76H5+wB*kI2f_1Tm16`m!zkEIc}sVYHYyqp?PM_ zV%HvAc&Jd$-Jc<^Hno`>0(VzfeDihzx&rjr2NkCmL|k5AttAgE>G{O0cBCa7(puNx zD;~>d3g#<133>2ZZi=VVysk)lB;nXl7}NchBEr!Ui2JthhA0kVgvD6(;eBpMfLs(K zhbpoxHNR3gIbq_tC1O?V@zz{U4)u-;edd{gY5c@1vScasccBaKgUC%M=O-pkoNvjn z9WzM2^4`XT9LrrZhyYFfGxHP?-Pau#?3KLq8AGx>jL`Fm`(_5UPs!qz@s<;eUqURn zO^7zV4sUo2;w(2v1_KYdGn=${ePoEQxd(S&6n9I$3JhTOnm=^^k#$_fk@0w5xw|v$ zuu+21`e))xXHMdVR2fFT-1yR4w41j;H|p+faEsnHGwE;JJwv@Ctn6)jIV-Q~XL)gI zC!7AZ$!uF*se8d=qEx(bXR2qjnNICl{xYlaxA(7O2OTw^Jx148Wq68?8{`W647sh- zG42=mzQEw{<9Ql(3DP|cZ6={)9G~`>BZ@SMcJgb(E={7XkB}pCHN!WAn?gOK!iy}E zTA`=fu1QrbJa=PfR-|C4P^ew!Kv$UUck1^GDN1KvWXw%-3=TOK%5RT2uGv=OhFDR% zk{5#xNA;s1HpgKfqq-)YRhr4GmDuz){di`f+_GA2GxgOJg(`b}W7LlAs*5-{MCDo< zn^3E}+gtaWGR3He3m{k$K)9?#6v8PY3rzM{VD)A6)8DcM}xF*#9}stoG_bE4*RN;ccJEd(FiH5rt`5*=!Z3bmwPHou_Fh*pnP zMyhhs$H#{Q@#51JQ}}~(N%u}9L=K;H1IAwfwL>-bRV@q)vf>}fm2 zD-$S2>e*F|u)>h?n#DEpvJ%IK0oJpBaa@?LPaj@7a;y-BP+r97CEb+CdDhq{nWH72 zqgCLmHbQ~ZITg1J1T{e-Q2zvS=XLxr?WN{5p4pD8Ekr$goZ1Bmd}1`uP?r1%=!qH% zT;kQ^tS;qFSV^SN(kj|-d?$;r)$10k)teP(`k*6_gjtqapQG-=(f#_QdD7osSaso z3Ht2SWf6|J)BH0aX5g<4d$N4umYPlLiU`&c$hG}eGlf`p)g7F1t5R?Ad)KLlZM(B% znsj~Th@EzAGKek`c*$3o%?(5-M9eo)q^~h@zh>A5YWH0eRB`A8_?}K)@nWm$J^+8B zZG>qaYHG7}e-S}+=vCdjUZL5DE=6ilt6xm50sc5KFhI8>y-6FFZQY0G!O5J`+G418 zvZ0FPW1@Q~tp61AVo}7cpy8$Kh5R!__RzZ_*BLFrZrkTkgBEIs@FA4B(x5ZSl85}9kew5wmA7>{Ka@X91}Bf|Xf96d zOTA8fNt~cF=`$BF5SWZxDOwE?5a0Bs;1w1YAOWo@Qcl-M5}Bz)0lljHSH<3lAulvv zRdUb_4FM8Q_1aUIc*b)0%ltg|#iXxfpK9E1UN$fBbnc4RjO`_oN%a7IUoE=LJ#Qq{ zWv24`PiDvqHks&sezfjVA!WYQ#yG`Y&&$&IuHhDisM$DvdjV^wD}LSoI&I(8X)IM$ zna|Z(j2Q;oOP=d}@xVHO8pE7X_c0HaXv|89eRxD4AeLR^-EwJKoc8lglSrrab7bZz zrCJ{T6RO4PCUB@DFAL3$O{t;cnAseRX#>1WO9>Nytgn#0-j}Z(d)!2TFl~kqU>V4x z^&>t3$^^4M=n3dutiZLWPhQK99dZNcvZ4a296MCk8`z*m#?@C+spaX6%-8)<3_mtq z!5d4zF__Nl93NCE%t{4a+UHnN6bmh`Z_79L)P4vXuZ=b2xH=Ov^|{U(wm~u&OI$W^ zRotVgXhY2caO1qPz(MfyHf&)H{;radxRtnx}Doe3Oo768~iS^|(@l)+_9|Oh7hbX7w&{a zjs)KzHX@mjHABq%%v&VHLomYu13ZX%CQo7OTkDx!B2aYtQOx-U+v7%8H&qU7;ck$N z4G~fjpJ;~V@@{woIS9*xui?V2;5Jq9^V;S9y~MWgR=A+0=M&n|oHyY?V13O;{wWXw z+(|05#FZ^Zj$UN^3bE8l%a>XNKK*9Lws{?)os0p%viEapvNjNDQnoqDo z$%=Tk$EoTG6XiSr+)qX>_EsfyUdp*?Kkr1Agb!o-M+y1bzOCxWdwDz>Yo9`*67Rz?tBKEPbcW-Prew5@kg z>Q?P|Oc28Jq?xtV{RsE=u}*Q+L$)s%=jtJ0drWuIjq6yR)I?%2u|M!lBGiUuL;mA^!gz!*nU;^>9cjqY3P8DrKWmrL8G+rDRr}*ol z?{&48%_kE8GU&_5?n?5>GX^zIH#je}WGYS~BvZo0fDnRiIc6W;xNQP9ehBVyI=8r`82f@v$zyGHNgX!>w0LJL&ot5i)q7Q+8Tg zHs<({l5pamoIVp!jHI~0=)nn$GbbfWBYWYk@vaEs3YGL4ku#BltCf>M76&x*Mu58{ zByhiJvIqs$W79Ex|9-d|I}#fC6&wPWh>-QJdQI@OjBgL<%srsQj2ouLYRz=ET`6VW zBeN;agsPCjP2D9=seX1xt%Iwkf$`p3u@ z=9dz+`+ADveF7-QuYh3tM`S05eM%_lYH4k)d9TwaSVKMRN2R~a_K9| zBzkkZ?XJB7AYdRq(Y5=4UZz!*4&Y{SML4i5T@*}>^^weq{k(RAr_s!OI4oCel2faj z0yRT{gUdX+YesW`@wHmt9TK<7H`_vMx4QTdCT^NqyVE}Axc&)U+GdVI=oU(=9L-Au zNO*FQ=^MJJoEMmkNf|#b!VoE zIbvU~wvPlQTy}|52fTjF%n)L5sh3XqW%;C+1iIPswWjJd@EzH{P@R=8!^T6}n*kSy z$P&fj*GHnvRdr1F_l0e4XK0qhj_)_I<9lG>RE@l21R%Sd$^%`xE|gvC|-zYWGiQT>7keV{MMo#LHZK(&L??54SgyXbW2ZG>_RkY}+>X&Wwdi zj;Sp4)QRcS!MJ03%8EHV!Y<6clfCy=5FwGYaOmfeyd|uqKg&iea!(d;5_r=w+eVDB zI6-i3GI7PY&Im6~WB_$RrECZ{mE`W7Ji;@SEkA$@JGcPua2OXP^fVyOLBLUm;2RAr zQGv~I%qJ4WmkMuG2Z*;5DmA(XU~mNge<(OAz(im@mfg%5n8Xv`&K9 z^mMB*w%mYhpWh>ZH=m5lMy%MNG|&1e9{~I_+$kf7Ks>%W~RnaJ20Vu z!F!|O{+Tu5-lQfuA5pHvU$kb2pwqmbk$jb^{!ZWvg-jhfeeV7V2^Cs?kH6D7$bC;W} z7T+_Pjp9V@yO}zTz1Dn;iJ~E-b?a=C?<(#rPf`%uqY>0uiL) zyO$EU`D;-Zi56{1#zjET@)BFZJfhc1o~&U+5Th$r@$g-ZiI)2UH3;9vW6fy_jl^E- zyV1-@`mz|wNv$vAMY|SOR-{RxHU{&I&WZe-?eZFE_$1_Y;9I~L;pJivQ5!_wih@S> zCmwGmHBy@qNx73$C2`VR$1=d1q? z-rNY1ZQ=w>QZZZf9>X=eW$$tkew3oT1k)`t?*LxPB2%=f@<3VIMm}lur?RVTrqFH5_0{FxX5lIlt^+>oDy+GCg z;2}jJuks=K<)Sy+RX$=H+z>9!VXyaf^bAHbJBRMbEv~TY+t{aLJ_~YJk(?yaWIS~y zAb%)KN6&Boeo4Mic6u1`yQ4>7b`c*Hsg)i@D0Zj#(e3JQt@`I85*NG8ff(-uZ=`~P zJnz3jzWfNcH}x<%;e`-M2}Zc@Zs5jE@`rW&P0ZMIk|+T3p;#6HM;(YMFFj)DF<9QdTy8qAaA~Z@F3&9Y{ogzv^qnsa{@FS2 z_vZTGi-O7b>u&qw=iV>Roq_{tKYmib^=I!zezNFBN5zgV{H$2u{l8+Ux7=K`{N?Bx z+IfvCzh3g((_j8*$^%bre)P8wY~uae{E>cq^OoBQlJ}o_Es+1xqt$-A#~$d)_MP<} z)ev_7{1nstclXu|zi{qz{rH<(MiV4^o_ZsYzy8r0Ki+~pUD>&_8mNW^_s^W_r}*vj zbGJ+W@zk~x!`>wo#_60U4EbuM~j`=*-u%LW~l z0MmNH^e4i!s^gLSgUTLSUuHS|3NAQ^JBUv<1(jXPwwzuMLMI3oLg)e^1_UPvei(Jz z`4hj7F3$cd$cZNs3s?MPMS1Jdx&~3_lO0vz`98R8)@I!JqVwxTLlxGBGhIhP>PpyD zGgO^8R6&98F$j$y6oQaq#hIV^8GmtW&h|~kdNQgQqmJE=QH#i^3o)t~qi$2+VTSy+ zAKpf5PQ*snU^|2O)ZcYz%JuKyae{w~XZ8V`_3vPthp}qT{}l{r7%PX2wHIRrJ%O>p zz%+1hvngnvA1-LZ1(PLU3I~&ZciquL;S1i~XJO1CzX5OYRPde#Z=pYUmlEDLz}xau z40w$UxByIM!co9r- zG$&k3ZWo#p6bj8LHbczxAIRugH$JNl4@fo9yCNZo(YJ77%ru;6At%nqi9#ZXGMuQI zhZ9o?Qv#R_goy!@^B1+Tx`Fdxkp3JDx#aTCK_~gsS2Ukyo|MGs2C@=16$jKL7ODrq zUX9`MK@bvx1q3w+yFlQ9AR`=Su}ISO5XOonV@2U&GGAPbM=rJ$&nv$VhUuQ?ITlX~ zVRmvDmFK9o;f&u?sZha>s$hLPyYcbY38v2Jb1D;ure<|jrDQhl*i`e&9t`yNMCje; zRj|qA?gr7E#}Z6I)BP$F3*Q4<_<6$iU=QxyZwdd!>z&ziapc+EIC2Dn*hbVQo2bna z2x1vgn+Bpb9k{nSL~TrjiKtCBQJbF-rY&H4j4)jQ)8Sv^0rmk|g4RCrn9{QB8R*1^ z(1~@>iM0eKh}HmV!dnReTCJ%m!z|sXZ*MRKC1C0Tsfk$mK!vu8)szPNZk{tnN(~EWw`e^uC_+_;nS3 zQ#ie@XFh&i&VMnSZtXdOUqkt?gwsoVw&K^N{Pp4VsU8!44d%y$(@8xu@oOOeg>c%| zvk$)t_#4CNX+7(DlQmCSv(pyNvX6!@o)IqW{YR0Z@w2*t9h=%)YpOz4s&+5T$ncGv zT3osF-@Q?@(5%;w16vYY>YegH&+pPs_{o18(w!}M$bYDTH!U~S6!EtOHN(Z{TJ_^g zZ(K`ooxP2;@gLGo`pF-!?atOb6f@KiJ58Bt68hCacix-AQY;r~Li zL1#SzIp*RO@dp~tFsC8MQy^$TP~QaM3lK^`P!a;+r~sh`1PTNh;W!CGF$fAm7&v+; zMf09pe@mV(es#z?{=KdHxUw?7pXU2_dW>W9?wPvHj3 zA+@uF0J-K@f}jS$0m38Th&lnn#~{2*2;hjqyGb|+LOlov2*($I*hLQ?D37mv9vArn za&3ZK7a{hk`~wIdfUppRGQ>WWe*)n+2qlDocT@Q+2!}z4Cj`8k%5V^>L9h^nvY($S z8d?Fk=^}t+!d2J8)K&m)x(FcIKv)Dq1>qooWC39ZArKA%NDK(`Ku94R$3QR>gj&;a zrd*$Zi_`#Jh6o_V;i@qphzWrJ67d!+P8=hMp@DAw1tU$tBhLV)1XqFZcMw(+0yu(e zA%l4j=9I>#zJwF6V5CN1$~<67>Lw6|L0AAnVFw5=f^Z3hVnXNy0nwL!0E9R~xCR2E zFa0$T%*l{J()o1JPz&Iuh5*tzTr~^#wHRqa1cQH3WO36$_WPnq)rel zgg`hDd087EgVc3ZXUp}AaFNOsgbVGssu)+D2SO?#w1JQcLMR9{A?QGmgD?dIUl2mC z!jN`?Fdu|mLTCp{`};;*JtHR8dJI=BhIopgGh$+`XF)K75CfeN6KnkpgginZ9A`i{ z1A-0&1L1&XTFXGFBq$BEs7|4vA}VMV{d-(>7p}?!K?<#+p97&71O*`wi-)V!=YbGQ z2*lz^R9*>!kr2ojs|oNdalNFonsJd>h(`vUVajk-8Uz6d9_S2H0s;ksoDc{Hag~30 zhZVx&57q!0{!9R1B>{kk2!dpj@S%Rk;cbCwlJ~znbAlj*?FiV4UqD2&>=l9=B%*ng;07X^@U8dZ#9N53ixbaPi3%GK z7R`ZvZu=|3qMslvdJJLFVd&?!e}M2DA%NpB{N}a~KzJO4ql5!~bK7AMwh;p1Ab#^b zC`RDcgU8DCmm#ZDP{(HIXJ8bBcMF6hLV$h-MuN}{f{hTMjv_LS6XSq(<`NxvJ7WSluxm+c5Q?)wd+K52mjX3 zQl69)pGdk<^S9_}#znVc#{IWw&(S{>&r(NpRNiLab^p{TnEU7PcW!)i&UePHpUd7{ zS$g~Y`3K+S&CYqkb#v$QHyYnF{Zzm&`1APg8=szwm{I(5*;^|Yy_uS^a{kS!vNyh- z?kfGrZ~WTt18*n&HQ~B>s{TvuwCZ;hyyPjGUw~l?7(M|*Js8%2ArA}zV2Jex!>_>b zIv9?Fq3!pphsuAV!(k;kOwRu$4sXTbqd44*^P_NnB^ZQYFp~4h9mIj591MCeh`~UE zfg%hTLH>(3Ki6m8_!x)J<8T-b=i)FAhXpuaj_Z3~!}-U+&DRR^w2AN`lR?g!WGo}v zgJ3uTh8tiw4~8%>+QeiF_< z0ESX9Tm!=?FqjDgIiK7?Dj15uPzweJ7;HY%&qV#=Nt_>x>#K6TpSV7MJA40*h ztJV*8-UWid+wr)-{}c+|>(u*Maf3$OznmB%k-+~H3jSP^ckV6_=)a7`1vHSr{{#x= zyhW#v-vt7{aUI^k{}c+&&$H192d~1CLe?&BN?r zY&vES%)7tushD!^qr|S?Z#hvl^!KOIx>Ghh`m2QCUp+9pa^Az3J>>jkb>oi4cenIZ z%sh7@vFo`lRaHYDJ|*c+dF9bxCfL?LyGK0#(Z{XQ&AnBX@4V1sxbN9)@ytgTSwlCE zR#pCGNsr;j4SU2>9$jc;;pVKVfIgY)Jq@R!!#WHt(AGT zr%IUhT#tJA(^U(m?c4SE;JW^T<9>>u=UcNQ{NVVDeU~PimcDnWdic=!C-vi{TPhMH zV^4(z^5YJc_$h)fw`Obo`YjD+U%2*Z@4Z_+{OBm3Wa`JyO_x9mUR@vVFnS)Sh zDOGtX5Fn$dRe326+JJ>-7)BXIs0_-BrG$!tSemv14cIo3rY|yBIu0Y?6o`si5utSu zQV1kA(K3oqutK0|NJEv1&^85Z0!f?avv|&2=jS;yXXecH{PDZ4uIpa??zQ*6?|tvJ z_S$RjdquAZq9~yRx3m|Upm$(4CZ~=DXMwrFT z{Q)3d0Ne<(xVa4gmju9#FcV~S-vCemWJnpa0BU8{vaxDes^u6ySOQM03pZDL6sK%A zz&{mW+~<0aEKahx$&w>w?7(Ah9n$$>x>?-ZBx()f#CC~$cQXorAKDK;G?DpF+goHb z3V^4YD09;)00+PZkq~e91ArX@$jp-g{)dL)c$qqx|E#0vINZ){c&a*?|Lg>)5CBhA zC-a{-0hS7Yr>c|r&jElI0i+D^c8h3(ws*3!Q!UfE|FQU?7Un-~SEzLqz#cqR3-h10 z9{|z?5DDf#Z8rcE09uh?{?m2=AVmO?*i9R_N3?yAu9NvsDz)mE|G1g|=w$wr58wxw zOhCrJ2w*Bei~t06{4W4324MEzFqt`&|2cr!0LeOLElcftSG8_uYLts(*;YiYu{6&@ zCQrEpWZK>Um@9xt5Rhpr1yBK;6A25zHUOOfA|VqnBhINmE%3n}_Yo>F(M9st5U$bQou_RT)dm$VyVQyPf9T0WeEmI+78(F<)6kq@sxAfd2#s<;_|oR(9=Pd(LpNi19<;303Bo*9i(EJ z03tyLSw;t`7y__FBAz7;|W=pfpg9Ryu% zWrA#$3G&a#7=bAn&IDN}6XZJpN(7Ke_G*CJM4SJT^;GJAm<())OpvQ7x|s)>DMsaE zfOi2l3Ls`jCdi)v)B_wB37H^&1h7{CkucK++hUJb{?%ku=frYfsbY3yg8Ux0u~`5y zJ2F9L1tMpz0AhAzg3Jm;j#B_JJF;xW3Pg@-RrzQ`*F(#yC;IPOanN(S>EVjt?v7=! zgG@;k!Pbr;u(z2eRs^?o%!eIlnp_cdcT9xsZ%V8P9`0BJ8*5Tm1iLzVt~jW^RWqR? zXzX|dc7SG5MbOc4H|*^i%H7fNJnSHuy&cJYIWGB@3e}b8lG~eiGJD(Jb}@BQe`arc znZ30X)TgYrR_J`cV)ho_d96zmIn&eq9kaJl%-(Db^?v;rW^c~i8^<$msmKg1N%r`6 z`*K#t9a5azWiwqhYC{g+ELC@Q;9W)d!MxL@h7p7rZGDLsFljj0k?GL61AcFbHgv={ zTh+ZH@SY<4Q0R1NctrR2wc);oRn3MH!@&-N!{845o3W*RR6%LXfL?925q*p~beWo$ zl#|f*|7r*5En7s}|EZW^y6Q!-Dr3Ybh*c3=;Kmm0Q;a(EVEwYo<7TE-WHWiM{eKex z*jH|)`y9J<$w%ob>Hh!k0syqfBaUZT!erDCpnqmUr|x?I z$^}6G%!E$eg8)(lAjoAVbm~q3a0%dKFxVfH_{}~S`lpp}@;0<92kmm9e_Atu8=w>Y zb4lp565y}^B0=c1O%|Afs8Fk@&@U-^EkJ~XGL4QqR<-tH)J>F;+egNcJkSQlfJn&59RTPLFjFLCd-u5KQ^``S>^2#>WhrG1Knp-B zhFK>|DUSfe3V>nOEdzKSV6y-iX5I4uPXo*qpq@6^6YV^;&mtptF|{gqLM>+3A|v-E zfD{2RyA~O_Hvl98w26d_+}i&+sGr2Nyy8-+H z&}V`YI&}b)0VE+2l+bBCK%D?0A)!<8DJuc2ZH#@M!putz`SdD3!E|>FwW{eNT@v<` zV0t`&O#ph8UqYu!0D}PZD!=%YYJji+l+mJjIYYb$O~G)+zqbOPvUKnp(eDSvYZ!!n z_bL;wLE?jVNPO@~@eRHgYw?7LC5Tw8I2R%|Qp9c(vEPW;x3a?UxVR7xv0}J`B~MI7 z?FXzmvI;PdRe;4hj7U8~^o{z}0L=h1P5{t1>VFN;Ux2Rx=o|IV0c;fDBmjM*{wbbh zws>{R?4PV^W!8YTpkC=4LwM0kc=P2lXiMLiFMvqMpe=o4BESWakU?Ae#u@=cg1(_$ zD~h~m9$wvlh6~Y3=^N*%bviG4j11b+H@*fqDu4{y(l@REi~{%@^9?%joTy#Szgmk0 zmVLa}(_&9#(3ZaOqX4{l7kxu3eWMg00SOml4qaCmepg$ICA(BUsAIelofJd{fi4d-`3xIC^4%lMfpm#(KqscPiQq&t=`{ zoc7~2cNt50p)K33{*P-erYN2Dx}>BD`OW=bzG00k-e}+H{bSZk-ing?NcH%wvjS(m zAKB}oTL$R$6DoaCj-ExDVPo$PeVz4~cXP?nNZT(K%nF?HerT_Zb`H?zSMTvD9MMId zVcPpcr?aMe%_Xi#+xW&=0k?P0TkgYNi5lfI>kb;VO)<9+A?!;4Z~)W#3B(P4L)_pb z0*etifRI42=6;Y)W$H8KP4R>H&j=%u~t`H%e({~gN zHJ9W{$xr>(7fIen@(<*Hi2Ui~cZz`IrvG+$(52!ew)-!_%tK|=(gJUge;4_kpOJ&R!@(6zFhO$+{a%{zTLcS z;60_T<9#-Mp3zeDMf3hB`+#iMBWYh&xBg+=(~UXvw>+%1-1$U*bLznNOI>^V)PJ7g zEV|gdUt#Z??V6ERTiv>8-0a4jlr0mrmXTlGZgvk`QtCSN#@PZ@!C9k!?Zg7}+KEQp z+5-iuwFiv;SJo7mUs+>Rt-W5LdgZ#Yy{ucRGD{yZw!ijy zLFQ|p8{604U68r{Ze!-5r{+C8y8ou#@tap%*X9*fJ*%?*cHRMn=I)OgN-GC3LvZ#^ z&uLCC+GpulWk2W+yqwmh%`;Y|sjRckR4Y7pEpI5z9F)*rYwpb)Af;%xr6a?>-yO(F z3u^O9suruPv(Fr0D%5&=&hB)xEPb}&W#r;zw2B`hOP}Wef&z$-dNWvv=g^5Ok@yd` z4B=HyD;#;LVYsZWucV|0DCr0;;&5CLmfH;6{5-Y$FzZafOb#1PWG$rrdBia8n*-wWIxR|0G$95Jdph~hXMQoF!S-t%*O~2129=u z=zjyS1E5T%LPs3^i48KZ$(5OpY$97q18!$tlPfcy>j1F;3q?X^KHmY%6+k3p=JO+f z3gDbb$O?U{#0F=sHt%ugQb{}0n0$#@%FJgPfKmX7S<1|3DS$};iCN0bXD)z70A^4A z3;-Q~2cYW&UZlRS`qaLl%zQRetA^&$4}o zMQo&qy)I(+BDU-s2?w&3v*M)e7I;)*hO(7&p2P_fB~Gw)oHn(hg8(0!mserToy*uk zQn3!;9`@b-30HU7*8pD#AQDW2mVF7Z6X1Q3V1mA^0pOwl^zrhyB~CDS$%pAGnFfuf zt@hF#kI_F>G7TCAutEU(r%I+llK`#?Kp$60fb8D^q5#Io1YH7TcLJ=JxXI`C^Q-=2 zPZ3QZJ4oK6H8;^eQ|O;s*+KFhz#RH#%Etij0lXoANXP_zAHXSq(;^`g^xZPO$eCC1 z*F8nd73iOs^F8ijYE{rbGw7dY36Q-HP%Z#{+$;gIO#mqZ(8tXZAlnb%62L>p$myMU z`mcM6*j-3>%%Oj}=$~3Yw=o%@lm6+Ve`?zS@&!O5sG%f1B?akX!)1alk<%#v5i-S^ zYJZzJ0UaojJsWMWl5r#tw1F;`$exY1EdYxJ5DA%}7XtJLm?;v{P5%fmTL6)eZu*+U z36@OQ_18T`*bWSrP8M6PQ)?`iES1T%P8M4}2iPnClWUzsPQL?~D*(n%Cy~=r08Rm1 zw85Szr}M9SiWXSPc|t7{C<`H*w$t2(O91+eMMCSx0W1J*A|Vs>a{xgBkjNFwSp!gV zkT`+E`#Ny~y2xaiTuaEbKeZ+cAd_pcoZ|uN1fW;>#d1ag!~-0b3A$L$Q2>2YK$V2)1-&z~1Je+|3=sVF!9B*O{I9S<3bI zD|A;fvR)qP`SDtkHD+dJbIJB|pO@8KoDuq_J~uFN!r>y#%P&XRdR4F&BiR%7H(hHD ze}B;u9k4qOx0yi;B6$w;^ZgcJWR!TsKt4B0_WjP zoQJ(Q4@(iK8-&1Q1g0Ty9DxN096;bI0xcpSC8%*T3)0q-{40`+NM28JEXncY*G$4m z{x$i(K;X9syobP11U8ER`8C{u^;Zadj=6NAioNMOawfVU+y3UfldU5Ban!I4uN(N=#P_a&5}7#H_1InjvzUPWF^UJ@*AkX zTUww4f&K`@A&`uKNd&k919#9ZEpQ!yCRpd&B@K{71LR2;xCMbe2=qrF4uND!Fwp=>(g63_za{xTl4p}#A<5)7(Ev#_ zK%R7gz6cCKU_1g#5vY^=atAa(o^*j>2uws^1p+NJfGTr~1R|sXqzn8z$vsJqA~}}) z@#NP~zm+bKCtcun1nx#)Is%(TfIHA|2Ufa3o^*jo2?RurVj4b|kK^ z{}B1p$?p^a$xjPdr3Iu5^gX#Of zF3=Bw;RqxmphKWt^2;4a3rH6jfxu)0a%Hnn++_(QNEZ|npeLz|qzGPX4AV0u0UW3-BiTSu5nhaP{`^=Qn}+Kk1;d(ZFx*l{-7Rqfqc zoe|2?HYTJ^h}V`+*s3(o7&`V<*F7<@wHdRE*Pl8kjUuaS^ zZ)ysjKi%XyzrRW08POK0D^85G#Wkh|^1bKm%HICi?k87Q`KH+&Me0E##)Q`SR(q3+ z;-U=qOiB%`@Se46de_Bv|917qzPa|JMYcf;$An6KFMBhKR8fYwL#csWuiLKf-5$}J z6se>;{1<(W4qc_aVrkHSL8Ivo?OuuM{8XP&c)CMaUgu4X_ICd-HJYu1d~t|ANN*OC z-kbZojTb(W-ZYKgR7P+5-)i*K)_Wpv2KLCGO#c7S=jgmER4{-F{soPu0WPOWVDG2; zjKb3ZCb200f<`lD-!obQb3fH*m2V&|Fp3tK%M(=c1pgb2emh4|d^4~|{{Pfx^pQa= zPrAUrpwVm{G*?Mr@2C3AkS+=@7U5seXvXaOhY=R~FZ!(VHS_dwD10&sZxV|@d|59M z?r*sJWxT(71ePLDCjw#-i0J4g!rjP7&{86Sy;zdtN!F0xCKg5F+h3FadGa46|6Bwr zMS%P^u_zMZZa`oa0+$d_A&`lHX8>dNrYs3-ohCVhWEaUglG`O&@=N{62%JOUpN#Pr zH%uO~ow%8r{051z|Mv(#p*DjQ>fC-+nW&#|{3S2)`n*lqaY|;Gc}~GiI*{ zNMP^pNBA)Tv_QACz<+q4ZGKck)=bi@eyNsOqn46QP>`FK-PYfET={~^YY z37`SWXaFT$Ac-!JCtctL9^mf;^`5lg&6E6}Aw5h0`AxFQKo`i9E+EnUFSxPUyuu19 zNahuoWR-y~kSASWB?1=_7>~fxzKq!`w$K1cG(etof#oEhC3ywOE#$A0{1Q~80rI2^ zie?ak`ekE@n9cK&+a zSZ(h8qm|~#{pY;u+8#BkHY2|9jr03A+rP|qjY@l?`j~Baqv@gjk^19j9u5pyT;9~OKEr4lvp-5- z>nho1-;h>f*Y!z^wWgfe=bLPAD{3FuIXcf&rSk@h@}ty0zpM#N@qTKL=@SvFpEuzX z-$=W6N^q7J-!Jq%M9g1?`%pE+FcB(*K7)w)hQ5XV2z}F}_{20~X4JtNLjE;%eW6IG zAJhkmh9oWKU=0!fnt0OVBdt?{HzWRH8bW`Du0X$ozJ&N>AoK(DCx~tlItbmM63<{Q z1!Ph{h}B2;YJoOGP6)R^T>VfP#FS6I69~0KMEOIWCPhx~a8aw{xYtm#KYj3`!muZ&EM~B| zb%^W@?k9VLi`g68<#;RGwN~~9H_6`M7i4enB=!a$`0mMU)n_NN{f=?jW=B=F&XJX^ za`>|S_TJfM`>WYH`){&U_P=ENYwpc9*L;wz8ak%#0mseheZR#6leB{?d>xL}MahHj zxi|0pxLMwf#g9drCOt7H@W-^@*(>_Z9+;G|<$d2p$I2R^m%)rHfTGoR~LJM)@h+-Vre-Py(X5Hi>2jaX}MU^VrjWp(l?X7xi78v zb=poczX_d%4nVl@c|{Pj`8+-W$@>ms0VnSiw2w+EZ<|8_P6~HYxRb)26z-&OCxtsn zQ&G5zbQS5UepK>)8Y?(?IPWst=dFj1Lc5?#P&wp+ED-*CUI~@756Gba9fj*CoQZsm zj>2^m&es1LKWTmnXRxpFlkShElACk*&?~%SCUCOrKhy-Vcqe{)s0#8yuR@~3A5e+1 z{{{*uqj0wT*OXCsGKD8ocrt}2la@^3$)vOAza}|`O5XIoM&^&8%g|P+5jq5gpaRGa z@$FBDRlCq1niP-5Y%V@&pXdGaB1PPS5zCv4MipcfWIbOsW5Axs{g2sC)g;WXzUR#Q zy`8;WPk9e6D!*rea(R7`qTtw=%)Z)J%L{_u3r#uIcULR4(b{5HL9Vy6X-@UX>i%tg zwS|^~U{hODLUmmA$-~~YS%&ILUy0pV#23F~Lm&HI@Fo`?i89IU(- zuhqBNzP^aBeaD9O`CdHH{pf0fBZl!1Yheb)3^)Wtij4i zEo<>I4Y#g_2t-)WoAA*v^JL|mb*_bdchzQeZ`w1+e0b=bGFRhErA@{2##bv(M`}y<87*ns znwHE{RmYx=(iZ(_OiVL2J$hzbbxcB})>vv(WZa$*Q(iP9%JYlmvjV5ncG=C*t^wBk zGkbi)9sP>hhvnR#=d7CUwUoFcJ>xIW3Y<%;wELrjx3mUJSY`M15Tb7wxf;1n0#g!17Z#~!bT&EXM$^2^EKpXKL`8v<`3y76val&m(1#MJr zqjDRS+o;_30F|gp$|)d4h(cIc7a!c0$d&M#&%)KhHJ58H*I)r!@XKn{$$%=!y1D`H z%fS8$0~H%aLsTxG<{7A5memapQ%PMhALsd6geWAIYb@8zTsL!_%XKbSCs!v|RRNXE zSuMK!5A_%|qw?^BRAQ3-HUESjqsvrcD#$$ZU}#uEpOivPLB=j$dR0b$eboL|dwb3P zsezGaav}}ATw}eJi(F$u!=l^>Cujl`I{vXf(<9nfW7sky-V{xiw(~QK+l5!ye$4N_}xe$8=#HW^B zGf5gWJGS>#3SiHSgv*+u;E9|!t>^#s{J)<6r}O`G{-4hO(<7+lY!&k=iIrKgPZBn_ zVxO$oC;8CMihYtDGZHN0CzYeEk5Y*JyNpE2niTwB z&j01TsN`xDb888iTd_}8?2{GyWW_$oZW#%bS+P$NGq)~=W>X2SFa=mB%tB!n_*@Fh z<^Np%&*gst=1oEV5AuI7!t++wr&+%|5v|8Q>9J1|Ak$-?^w=jo_DPR@lCSIZ*eBT} zqkn=*%A)wbuIUJcF`I6RgO8)IIR3BTe?G2js^EY2$jD^6X=yLdxF;rz>N~tRW@&`$ zRqxhCgv%7mcNAYO$helJuPPlfwl~qTqM8J4^}T0mV`3v*h2B3bDxa`m=yL6v`B_sJ zjA)FRdyCoeMvXh`>8$Y!hBrnzZ!z2V)oja3%^JBt*%+a^#avTbQ>u+L7pK^d6?sNz zM}>}OP4ntXERi-<NU&>(08bQ?s);eim96D2c- zsXR>O;drb-j}2SH$MJR|@O+pX*F*@9=M#bF6M<*M#JHve&!~j-64Fch;0uCn2^6mW#Xk5Kp#3O_>OaTFd$;c=wJ zQFt8baiqsZQ3>l_WM=x4$Mh$U=}+FDpa$q5bORDMxfZ(VDpN__&?OYGl){%%IA6=w zFe$ESq3{+8Zy~LP!dpoHzpk>?dm)s$sAf{;msj^!J!wunA9W-{SMKUt#>FSi=*fb_Nc}#F*H=6{$^2(q( zs1j<2Opph%L1A%l2lwOQV|efw9z2EzkKw^%c<>k+ri`>Q8m5f&GSbWX(AwEvUg_VT z(UQh1mBp-(IKuKuO~a2M$4?0!rOVWcAiYxn@Xm7WmfxlXSAd-^9fyqnEiy#Qi)o*odW*;jFvPC z_t0z}n#~hQC5c{{)w-d>P#5%*87==a^I;pSBE;+`bhSxwI#N^kkmI2D=%N&L-oWLG z;!0yivu{RK#!zeY{$mbZ&Hm>DNoV%=Q{Up+?>(}}l@uDVJh9khJT}JANBgSA81$N( zasrd972UnH#cE@&x3XzYAhEiCcOPw`!5D0^H6;WzSv!9A=of~Kg=_7v6vYhfbzh!u z+&u5p;yWUh5BGgKP?fgDUJ~ONnDp%6w|%cWep6I7^wInBu8n)fySVs)g3gZ}^DrY5 zAmUcC9ZmM8%Cc0T5c)Or8FUx)F7zDc#&qWsn3!bD3xO*mTT_k6n3rVCOETsq8QWHe zZL7n!)nVJ}hGEm@J4Tb4xRvZnl@NAdE3^P=geF0Upgbr9{X3Ot?&X_yBimAq@fgN< zY#WQy#&{}@$F}h~yD^^1*_CRHr}B6Om3-%TiOiAE?;uvD17AY-LmxsfLO(#PM+N=_ zJtLLGeMAA3+&K%=#!BuylRM{Ac4H=Y&W==LCY5JWIqTBK%n?*F#zFWxFb6sfB|!V3 z9H& zOd<0f(AyAePysK*a&+KzXclx5dI0(u%4YUGctcE&!YTGXH3{=3JaDGCcU(``liqI^ zDel>N`*KIoY-2`Y)-zS517^nTpJg9Xlkm)h@n>p#FYQ^LvVC~ttu43s9S3S!vleEl zwkjL@#@^z$7uD>}nw1r|U|3`C&A0e#-mA&TnxD1fsN-qxmsyW^orSxiY-1Os1fsn+ z?3t0OLHg;{2YfF3?jp}^+W63(tfgLmp(V-|-un!%n{NDuZv2LB{DyA) zhHm_ZZu|y0o}wGSLAI7k6uNskzJn>I4&NXizaSnzAzpa=gi8Le!268k-H=9bkIhR28n0GUqV{tjUdkvNFbr}U{C`?0P z9(WIhdHA1QrLx7mNzMOi{#WzA?G`FA`*0S!aTL386y;coZX89~R4UQuZX88fh?2F% zyjNz0Z7GS$aWdK-xjD{a(*EZ$mT?xdRw6dDcbbf||8R^&hUi4zWz1QbqLvE&@fgcE zi&?7>oB33ljI;l6j78>VII2mp=P&Kf{hb6CRtdG%F~dCN({Sv-3dcnBdku6QVz)@32zmti9J(8N4|*Q@4jPEDvE9Fb z0yG#G4aP--anWF0G*s-txOk}CL**VS_fWY<{7sjGB_-J@64(Z%LT+d>bQsEqx*)cS z1dPyBDlyzOi2~HzxtcpybLVRATusF+CK=UKuBLJ|m8+>-t)!AzM--W-Lr0-e&@Lz) zx&*OJBv1~eKrSe;Mm1V_F8XNE8}{6q{g1C!pP3V-yu~%t>sXXBDsRB@ONC{|jKjXi zsxod(ir!ypUs|*OvB0D=2~nC`%2V`18gJF~^gEn2t-cvqsyszwUr$fJ-CwiYH#I9R zG`O+1x~IRUt|r4bJ!^-?q4fHFDPBX7Iw~9&N(~si9(%;#G2z{>#|3_w_NhIhPmkE7 zd4oUk-C=JkiWyiuI&aIkm0m|tnz8e?E5is8D2YudiA~4~k&@ViEEX$?O(=6)cPSGw1kJ_SOujieMiz+V0}$E!;akUb9oNUWKF0M6u3vDyuORb8($iZA5yS*AvU3*Vhyng4V7!CTvmxSRIW*)5_FRS-VmaY zr@21O^%U1rTp!~45Z8TN_ixkRT(OX(xuSv+- zKCP$gE${b>6qAPaUp}>Xu`%QOtOZrkiVZOd=1F%{-!ZdqTgk=(m-pKy?S#9lhs=y_ zE2=L@@m_11Ibme=ZO8kz8TS^rnl3jz+ERGcvBukIkMA2hK%ZUxfp5Cw?jp^Iv7L}r!%LM#EuHyrXoS7;yf zBUB0)TkMW)TI4%Wrs?fUX}sm`wjV+D`bI! zPzfZfIu#I;p8s6gp^~tCzEKmV@GymkDLhQ!VG0lPWHO@DcbU^i+*%Yq`nu&6@2STY9GbNgMll zMX777e6g`vzStNgUu--rUu^tIzSu~WFE;LwFE$47#fG-e-p@0%6LYhsesx=8%!*!S z$ATL7I9=BGulhGeUF~JI=hbW*XJGiewJ{>9m$~LwHKl|4tuK1Sac5EdZG+&U$t%fZz-ec|;Z!GMI|B|MXBpdR)^_oP z2hnt_z>;}8v=BN6B|%n54|PL7gVsV*pc*PsKRAp6l)Muq??lNvQSwfdRIKEkD5+dY zmB3vjeFl-F}M9e2*m?Hv&IG?8*$3LNlOa&=_bplmWF;2_I!rfQLKx zaOWQG+{2xFsMy1utEpT~!4p+_o zC9C7kobK1&t31UT+jwhxgx?Xt@R`Q&IiRtxGQw|A<3UD?47gvK!!NMat4#5^F0c|a2L0NIGahnCUovHUM9J5*93+pYgbz?h&h zm5nEDFO~15vc3GjH-buzk7F+I-vh>AvZ_PW^rtI3R1zC?GiXdQ-s5`d8Vik9kga0nUwi)fJjCc^u%ix2iKmrv9($Ab=@m;kaDAL?|JU;YJR+@Kn;rb}s=mpON2t3&;U0hv8)`*r?PJ|67!Y0c)I1xWx z+QC~XE1E_DN1!+gVcWE?f@=j=S=L#~^`}caEZ@Ae8t2V`<7U8XG~hKFWO&g0U+xRKl<1VauaZ8o!V#m7k`^P&z%XXbj`$KhWk=Kj&{()j+HT5C5)9o03DDjaC(c*FjsJ8*y6DQ(`qs+U#PN9XNTXhwbHF0Jf; zy0w;Au&!BA7;QQ5rYmDW!XAqph~naCB#V2AFy~-65yi#XNEY`TVcakY!nj~^gz>=i zgW+@}i+iRpjWA<{k#e-|#;;m)VsgK6b3RgIYv&KOZa#T}xd`JC<`PU8rr-CqZVpw4 zL8h%q7-TqA9R?ZBMQM~n)!ZDb4kI$(Yqb}0jubAwq}44@wdEYqHETImtxdj?)N+(E zj3AH0@R_8Rvy@>3c@&24B()r-3?s-)m=-}63M0rAm1>10%JIl5v!z<0le5*#d@8Av z^OVh&LolO+`7_KeVGhEi3$q{Qk}y^ng)kq(lnZkJCPkQi<>d$58Q#u=F84{Ai0>s` z?o%*sVd`P{VAADw!gRq*J^{lQldj3%z&M2Y8ir3MU3>#&k#ka99I|F{ZxrU#v15&G z7ky8-<)cYACo4C$Zf}Pvg5j%4H%BYOw86X~jL7U0Mr2B1_-@k8;mR-~vrQP0IV?>3 zg(X`5lt5LR9IvePXVX@ul`zYM5o8UFMv&))5o8sNN01C*1j&a{3$j=kK~})nR<0Ot z4n7o`qqBG{*=7!0)5-UfW)4}_S!}{o!0-X3nNyZ^mN5BLpUw;0vdxNd?Fnr;JwDH9 zy!jcWOU_z0%h@Sf)x1W!mam$oxiyh&DNGxv{mF6PaCdbc$KNq}0lB z%WmywBG1_=I{B2cP0m|x-1ca6Lfgz8Jrz3nmeL{zF1wd~wWzu6!8z>28k%^fI z^2Tkoh~+f*-tMtR-mZ4jxOBIiqvFV#j-K{+?jHp(dFrr%L zgb|r;m_Z^_BaFy+g%O#P!iY=<%%<;oyJpU8Y|ELB0&rk^Th38bg40xB1QFF5C5Wij zC_zNEb_pV?wM!6Dt#m;|wbBI<)w-0!+f9l8NTahvqX4cdT9+eL%q~%_8N!Haai)ry zUvbdMx$S0`sMc;_M71)65!GrHMpSFKFrr%94r07ohvn?FxcAURt)dcb!iY+27e-Wz z@3LJS-fnSQg%Q>2hT#)SiyXt`8ZN3;BaEol+rmgWUNK%9dQUs;<`hSaj;O>IVMHaW zg%PzWgyASAH;1yph|C{_5t&bf5t-Luj*HAk!idaPF z)!HnGsMcmdM78D$BC0i45K%3sAfj4MK}5Awf-Dx}Rc=3q@p_LY;!Gy9WjBmV7*Q<_ zWinetwJgGjYUK(esuhIEeG4W+m=9n|gn1WcnlK-^wq6fctSCHkH7R-fIn%3kn=AZr z%~9W8?AjUl)tZ+L4_ki&ye@uIg@0-Dbl?Ml-vTFDpV)p*^J+ZOvCX4^-wQkrJkk0% z@VZK*=QgJU?+ZKwJlQ&P`#I06l}M|a6~MczJ-69LW%@7rzune!QTMGosY`z-c2bx2 zkf*}4KBl0;vo0ohE$Ex&yJqoaoAfbBeYWc(l3MHQ!h4%8E)B0S>Dx57B&)B+2d`c2 zzJK+N`384|>8h%xzAoTO>dLc4c}kS_GH=C=x;5QjmxhP(CAT5Qu(H`uY&+OtbEw?` zo7bid8PZ<)IBaO{Q5zANkd!s}t}}tR(yA6U8%yrsn71LtfGY>zbB499>P5|tlG_SO z%LYFR_|o9J&jdb5<7Z!Xlsr%%O8iw|-dc0_iH{*CNd2Ki6Vj z_{|sHpYFxH%ov7wxu*|SXk#y|&=&<51b$u0z3g{lg`O8Ne!eJi#&E>mM=Ynlmsp{d zX*Uig9;1`XProD{qm$QvB@CThe)}bnFS9N6mxV!DnI)$OCw*e&d$ke{u7R510`;xpp1QCOSEvXT#9RwQmX|GBOTr5*ZnX z=7@}pLvut%#-TYPBjeB<8Dq?NDOeA>v^j?^%^9#9uO^HjqAUtQL|GJqh_aLmBFa)O zh$u^nAfhZOf{3!XWQ=hoET4-Rp(pc8QW z7e-{h7Di;Q!0Zv3FNG1AAH)hd3)69-QfVS57MtT8F(cS;-E3h5nGRzXBt;lOrore0 znJbJS$uNFFG{S&z(gRi~!ZCG~IalobG%R+m*!d&Eh@FoUM(lirFk)JSnPZ`ZFN}eyh|9d^A=&m&Ie)g#m<)qBX<6X zFkz1!te7P3$gjm6`Aapo#ffh^ zIRN5+=eKAt%-m6Y@`ttuUskovT)YxPu|$|vFsRkcWQi zbE6=r)y$28pjIE_rP2fM$~GEFrrp(3L|PYUl>uV zv%-j4O%z7d>VPn!R%?W*6z4dUw)UWFjHtt}cq3y(9XJWXHAd9oSz$!2ZWl(>>bJs( zTKz&8QLC4P5w(hh*)8QfF3e5$>5Zxv-EwxUTl*t#gySIG92p5Cu2HKn;u^Vy5t%NS z1d(wFBQnjxh)lgOB6AgH|4sMl`7^jrDRh3$guvjS4xAthBZ#O~q9CGHiGqk)Sp*Ta zvIrt-l`Dv-RjweSR>7RBnRVUKFWU|U%}d&YN4gUC`g@%3ED;-{um`f1gB6}C~0?ov=Wr{cF{pE)En8&PJdDfx4As zIqO@H8oUaEVQG~^Av7G0VdI<+11D2-zepAi3JG39K!reN4p}%IHZ_E>vRE`EI|7>7VI0;W}Dx$1i)HHb0klp`ZG9Ohx;7!m_VYlJz)rkg_} zyZ9ZlU>O1?1k~~@n|6vs6kfNJ9yy%yu&C*^|%D)TJvQ7D%Mhj5GEg z_u74{wvFUB9H()-^9FtgY8WSkOym&q72jwVw7lT1K7NuTWHB2LAK^yIPR-cM7M%&J zTAOLJBb*;n#$hQYj^;?>B%ORt6bgREtv$xmY(yXqf#h>!xzGN`RjsqR;R=rSNahqB z6Q{K#ajJ4Yr%MO>l4S^wJ05|h2-JPudL@*UI%vtU;L~efHjUBG*nVzlnFcR#;(67# z7xRw?W&n@UPv3s7WrGKwam{%h@VP)LaJ(LWw5800bkFnJ?>9wtUfdAXGg-BuI@zCc z*Xo1rck&Oqo~@}rHmJS+@TT6|wfmkkwSDrGZ{?2nf-6nW+y9()pek?P+tz2dk6P6{ zs^sZ|9Zx%6bO(M&E7j&5tD2*-a#oB&qx#5MTB*b$sQTi3C`x7=?3m$L;(jpQGimuO zr2y#_2|cWgb8VEI#G>Zl zBt6HVba5O^@MFm`c9_Pg=eYT<&p>c5IyX{_{K8Z++G0Xm)Eot)=d}5*uMn6oSrWI- zcIr71wCfNEC&6?^QA;e(5|6fM&=wn~1L-+3sf(kdg5QzFcISfmPCcigSOZ>mPgO|!Cf399vmZC9%`K9)N?RU7iWP6iGp-ms0C-Dp&f1Upe;6z z+}Cq1P#4F<290Flr{xwnyE!qc>m`eAwpBTDb zA8jl0TrzxneW|K@Zor~o2Y{jBKfw+IT4j!fl9Za(#KKhZK(9a|FTMB1?D@JuWH@Pi*2Ek z*3n5#oP3nT2~hbQ`Wj@G(RrPBLS(Zc7J>LPWFfq{s&zdtHkM8rPbbx2(yf^Ed@<>a z_?>e8lN|ZFSp=M9`OXo!s+9mm!(2LPC7o1*Nw;Fs^Tnj|^Aep8Q47(D2B!$P$-*gc zt6G^>G&t#`nRHSQCf$lj&li(UFtl?9wJ@h>P>H}vvfTXX+7xcpOef8xlX@`eR!n-n znDh-~*+wml?+rQx+8fB?wzsWn&E;18bkcS@sRxs8#iZwpN!OEwc|>aj0x<|Ezd7bv zXfVbcx7hZbi&+;;ywr7~+V=6enDxQn4_&^%zvZj%tXq3S|J-)twXP2)MO+G=T+{EQ zfAN)JAGRO4F!2db+0puF_mx1ByQ8q_VsTvOMSWb)WOL$yWL@Ijs}G*tnSao^tfqeV z%=Y?i$1#H|mzdgC%$bn5wg2(xmQ!_ge6bR;XU$TvGvHl??ZE}7OEn{yG*tE_>M*w? z{a{DBW0jlD0ma%-ZPsiRy93@UU(#wWcKy(hDXPxdX*SN+(sLYMR~yeandc+A(CViZ z+YwOH%!Vqm#1xfWYEaThYEG0gaP)OI$2oPaBMXttPUZxy$+V(L1ZZZ%9Sn;|Iz^UrvN)+FlUDSIfY<^HS=tMAml`~x>X_g#y}O&<-L-=(N8H_I zJ#!;(Up3iyZ{G6%`<=03;$J^EzN_o08_%9Hcdy!Le);`hd~rb=#uM+_n9$al%p_f% z-mDEDI(AGOzB6yWE;twWU4!FpsIPT*XDD<*9e@WQd;(xGKr(<@fUhqsF%w?cW$E%$ zmb#(Z6<$tRyC|GMW~V`b41i2B{adp{IAgYCmRj=PswQL1Fy&oY=9r<*YFEVi^u|`> zk%!tk?>IkH7yNxTG9Ogex|3EeXx1w4*^{m7r+BdKxVHc(??mI}a;@#T}LvTwWhZy-_8xL;|Ak! zf=%xNd=2o003z`Yz?b{?UcLJ8s3+cNzk21y_J{RT7JBMGi~sUcZbRViHTlW0w$YXC z7n|pP`{U%Pp$`vPm%gUi==49)aS7px`l$;&dq2xW_;hu2#>5m&;_(rO61MKB?7Gl* zq3hTwr*=g|<*^GF(<|2)opY}KxUW7`lfI+pjfSN)RZq^FF#7gEyW=+`JnCTQAD?kar zZ~)zl00#gz1EjhdFW)o;=Ju16wUn|JQdX{XiV9>*$mEmBFQwS%4zB?8kW5B<%__6< z>sq(|1u~_Psf0{QO3^O?|1-{l0ArE6=J*4^5&FWYSLP}UU6Dx&aM01cB-{bK;{0c;lF9Ka*xSppaQ@|uQa?5a2B9NfXtK$ z?Z5ICRn7BtJv;9mPyBbOA9~_jQs4Jfew(_-Q+XlvZBONQsXINDEvfH$GQUmT?a925 zy2F$CUFt4RX3M^}$9OKLAJG||#qB@t^8{PYFYlyO$JJfblMyS%KyE(?! zh84ZGG=)oJ_}RD@cxRt>O!;?R@GVj0DpBRtqRMyf!2}FJ<4b;r#!nTEPZN!=LTp9# zTO=wUR9RLOj(gUryQxhKr*di(}fSa;s^6L05yt1vcgBKIW zn=*}ip|Q1pQJ+g%(*(GUw{RO@Q-1QG2hnmPc^)}Y?W*YeCo(?0HDlzl4!A(<8*Zbw| zolYx1m}t&uRus3&ZAg3Qq&+s!9*xo-iP9dMd9pT&IqsHXa!-U>e^jk5tG4a4`d?$L z&#h#vxB53Q)(6$uhLrsF{(jvlzct%1JHI{F@BhZ%oo$$&ue{Z-`^LYv<7dJACl@Lj zt~6N_67O2wy6Oc@%J4ylavnZZS-PS3!r-v8&V*?_D^oYLrEgqZ;2d$Jb6;JyH<0zK z2@h<2NJn>a}fY~#Y zKH9}h-rcGri{~s^=90xN3jayA?i^*T(a=Y`C?kfRceTd%OLuEbPiiwvnDkp+a0ilQ z*c~;!x%<~--3X8@0KNJ86AHu6C&_r%LaTPmc-I+gU%$$1W4!BTybF#(x)MWTW4!BT zybCI*D3kHditV{B<6WXyO^f&NL6-;168ApTg5&n6e+(tVR*QEy-qz9DI9wBKDwX}!yfNm+qBN`DN(fxttY8~Cs zMlTMd5upl%`1OF}VQ#PAIB%F{dFA@)>cj{Pz_uP@0H&N5C43>T>eK((NVHT@^RThh z?4afqg*-snV6hhOj(f?yZ3hj%fpKl(Gt}_C7zY7(H52CmoB?PSfLD{W(ADQ`b6}j_ zntc3HZb4utWBFk9Y&;T=@b3ce zAw0x3sj_|N`Gilt`zF72!VF(SR)e*(eC+BBRlde@?AAjG zOP92!o6g!Vr)?O=ugxXt&aG((97?k$BpK$tRT@8d(2LDcC66@7kIf}mSI>K=G=9jY z7n`S-Jl_yt8lPZg9xtl=z(-H%f?x9HchTo6Wd!F*gFgVI3&4|FdD0-~ytZBvz{UHh zj6Gdx$v0vrqOlVy8NqS<^2PC+A%Kj|hXB?Ci~%se$lEvfbA98sisP3981{sJ-}iCWQ^Yf5CG`kfGYHNJhsYgk`bJ7A-I#WDo`Ag zjNpt5!8ZYx3VwoA#Y_<+om)xmtB7_FRne8}(PgS&Hz4ysvB3(WZSJb&lAK&{5yhitxjE z^|iKW&%Ta!M@)wNDwHBTG4ypU+Yk5g!fYjKYzRY5S0&G2qs78BVb}~{qa}JgaV?B~ zEwZB3Yh_sfR7U^b-*oneDo5k&kC37NRT=tgk$GEWPKeAFJcNnMF)<}km>8cZ`W;xR zk-d%`Ya4doYYYAfAHQXS=s549%t_BLQ{Kba{7?A!JjYJnMTNM|6@BVYyOYHFU*l=U z(~0YFos(t*diEk3UQrR6d(9OYqIbV+bL@eZPJ2TnQ(gZ*8=neh(+-< zqIj;*Dq$zgaMeH=s%U6iwpkO=uENTi`v$ zGrfNBzHV7B?XHBaj9I%ZD=@)(WsF8i*{#n-#xI)PYk?M$ure;X2yeOdsT1x z^=;XpZXKUB5h-T>82{$0*Lb62GVX+m&Bp9*=rySCXgxD#*!{FYynsU*hT$h6MaCPVgpJNNnDh~=1frKQ&=m&dSp?uBBhM7T zDgZhF6o_};Fi=9?yu~MQmXAE}1HE_?y&Qw`BLtv&yy+t2JbNw3y3IU1510bQHmxdQZ(j|UPl-ARPPrHW_o&He4NP~x*X_2GOdUcAhSCH=csfM;9ge` zXC3u%*3oYkD8Z~ISmKX?Mh5vyd{&QpWQObQ`R|X0s?0X%;d=X7X7a!9TDSKaG$Ubl z6z zXdBT0U1RS6U`+ss!ji7B*8pe?U=q#0ljB=@(-2$pK1#6=ZTqhOV(G{Z|0c2B1eX z^e_PX=pd`4j0>@wklYGN|D$l=0J^&g>93&lKL;Qgz!;J^4d5UZ+dt0V#HAiVa{JNj zO6R%Fq1=W5y2hsT?+4&10W?E<(fm8`TmU9_bhii1zm)#8u5*n5q`#Wd|0;mv0Q^bf zFkJ!|PMcJ4#-G{;*`9#(_oDQ_0p-C2ApN~4{Zj!5XZ(f^@wS(yTdhsZN$Y8@PXE(r zggX6(k%c<_nvt10J<4d3TJH~|F>1Z*MwV*5t0AUpy_+Fp)p~!13{&gfup4Y)ayMq< zCT;&Ze$VXGomR!Tjd>jy8x3}}dG{dYKG@O4Gxa|Yu;UulnR>`(&pz!Liv!NpXgGGZw3Tz3Z9SC+n@*6r0^CDcUe^N_MEPcYT$8vgI0oVn?S- z!Ha^u5uiLeh0#GD6o^!j509@oxqgd91 zBgL-b@fqHIBRbR13yxGFS65r@zfjsL9()&Oc+ARJQSp30)8d7mo^hWw!(++3qW>seaB3|1h;Hl{T%Z`nQ;P{PSjboY^Cj``EtoC@Q@xA-D$VJ5`iz| zPbTMWd>7v_E&W)!LozOC+&ojydE$b`NA)JQ*J6iYbIXv_mZ65Rhy26b>ddf6y&E$+ zMBCr@%`-bc;|MT8hF`!K&xFvNz|7o;N)GSCoyY1b`nJ3ssZ+-%Ff$^ezQcPw|5aDf zzh!jfraD&wGm|4~IK2Pec|29>!oG*Fjz?9GSSiAgX5V9|^Z`VHC>1oh`~tv*0FqEs zrM8(i`SWJ@hpCfj%8y1gEp<;}h5B=5__Q}hh-SJySUA0=d(3Ce@JK`9avm(a$*0qc z&zj-Uw?pXLHmc7_myYAwo~n;s%9k|5LxPfCo08rq>A;20n&DBww2T-_gc_28r2m{5 z9&CW5&!eQzbI(T7f0*G9eqx3P6(rIb{debr+&%nz&hbbHRr#z>_lwE;E3@*ecda{m zInPLlh}5}}vg}-T(h^S{JwA3zELpg9$dc)^2_^@2@b+JoeB$CIeC!LhKwFfjbi~^1mHseO^uTQ zB+)_jlm5UgPsNL~oZRhjU^e={iHa9zIk~F=Gz2h)B(Rf^`x7N4*6c9LqgMUs^qkIe zra-w30XWIs|4{f+MCE_4{=hEt5uY~RHSG^K`a)05K@QeEcuY@1n-+3kMbdU5(*y{eoD`AiO zU9W`A?r*#jcDUd4O86O9*`Xo+t|kB7O~1#9CfTjxz+%wSw)``{{j zGp@1^;3|9a;sFEd@2NfJj^E83tmPRFh>7&m>2Wr*X~YPJ_m4Ba(e?g1^lqf3j?>x9 zJ`olU?^82I>w5PIjfqUq(W8@Vy|tTga*gXn$qpTW4d_%4giwtT=2MVqyT*xFB>hs> zqT+VwP{y=SD1+H&!urCug~?Hfd#v4T+BDb zg579joXI$vd{NYCZ-%4qosds{v}&~;eeVq52!i29=hZs_*b+bzDk|r;*D+m;MBnw% z_b6Ntnouz80h}QK!7!me4}2S&;*{~??VI4cSuGZL+j#mn z&+2nGYw7}TOHcn+S;2R*`Y-UF6jw6~ zlT~gHJ1llMXKR_`&?Gb{Hq<{ZsQQdu4)yrhM0g7M2+ky*8u1!jgtct6NCu}UyhS>99o>eZ`jpRB!RRcv7Jq2w7x1|zj~wXlRK^15}VyQ>2E`?seQw4%ndSX|I3u% zIMlEkYB+Xxbfkm3qi%2f` zTL75EW2Z;Y)sLNyNjx^~ouOk0F4I#T?URE-j`_x>Jpq8r^i)R&04D*w0f0$7HH{>W z14sj~i~y4G2apFq8$fIOGdogS*VKt|$QlM~n8e+%CLe1YAL)>#1b{VpH>}CW8pi<` z3E&KXC;}1y3<9tLKo0<64*`4w;5Y#P!28$T{C)bo2wHXq)=t72z8jJnZ<`#nEEqr- zfGhwe^OA#d0stHUfTta&nm{7wEPyirq5!B!;x_=t0rZ%cg7R7eMzy?!tV7_<5 ze2;r|0Z?-M2w(&ONRD7i4wStc${u&>0-)qT*}I|aV^5L}N{(M049~=2xBf!vT@0)R zlEaab0~>a!cQN!9G$fQ9uK^fBA{NQvNXg+#03>3O9FCM6Hvj~Y1d_w?xZ$q*jwu17 z;@n~}untI$U`mdpay_W0Ctm(g}ZLp zyMNO+&@m($*6^gTAfp4w@ayQ+830(*3o^n_IHWxU@QMIPgzN=y3BU#b-60Wj5WsB! z*9ahq{UDwYY~%&UVI$8i<}64f7S^W2JT~&&a9JN4cMpI$09@9);j%t9?g0P`0JyAo z!)1MJ+JN6|km_u(zI%GCl|Mn*o>+UHl`fnh$Gsu;ve%3j^BdH}qT{5iy( zPXSmGKoZ2ASpXCO@<@WXGaZ2U1Ghi&)%X#;UFo}Dy~}g*hzV6`Z-11ZAOCV$c=nzp z?mCq(XJKzFG1~-Z^9>Su_@@s{*2cQqNGn5=r45m=<_?WLTNF!=H&EYdy8 z?gin7ithgDR>_?pJnj8KTqkVugK+iCXbAU8bN@a4>aYd=30pQN&rr8N@Ozk-VyN%3 zT*vR5WW5V(W}NogsMpYkDOpz6&&8x)nhe2Jry*E58G?DqkzrnMk}rpOr6pep^Lo+{ zSbRfZcN+q`*$`Od7GSC^k)3Lpuf-#w*5C@Ei^qeWqmrV1p4as2b$x91b*sadZ0ek8 zWU_4g$&7vxE!RY~deX%szUP>vS3YlRTK4>EZ1yFqeV3Zn+0Y2vb|*5vjA*c?N2{$} zJn-|hN!NTHuPk_!bI1z+MlY+W76#~Mce#jXx>WCTO>ycG9p2fFXcb0!V`=fVu#T0Hl)!7XaM> zgb+YpECbLQz_Mz(4;<42CgG#^N<0CkhFj%?KKJT)sAtl%obVi{>TZ=4J@3_dzZbwN z0wAF<01yBm0>CDc=ndc~fCB`OgyFrv+^+Z}L**E1?}he*Xy1bNG1UGwfU^Li0Ys66 zK7bPd&JaKn@Zx ziOT@Ckpy``DRBr{7HmJcBR-zT$H!=&MD64QrNqw!kOuOBQsNGP7?L0_C?x_3APMq< zQsOm$KGl(BL#-n4(U(4=J%N0nl(+#P7#b4D2TF;P1ds$pf>I(CfICT$7nBma2_T8D z5nTKVJ%XD>?c@WcL>Suh8-hZ{fHPD`iJYq76up<#yi5VC0H6&(uO)zC0QLd!A)qw? zC4kK!GNb-2!CPJ<@$od;uTVQ_7zAJ)fKCAXNW(V(jsZAA0BINsU^a(17#tNp`< zF;8k{MFuXpafLZx;8k(hmD`>G%c5`*Zc%Ae$ z?zQrJdW_A!l62q_HvJprEy+HS(IcYi8t+!BF7IPAMt#l?4pkocbAI~frXG8H&P-ah zdPOZfo3({~A7%VSWP_yC>6wlw*6zrcY~)LQB#;@AL1zH}02oIANpu77AAnu}u8>4m z054H{zWDJ?eC&ab@6lcZ?VZr>M}+eTz;FVf!H)>%UjUr}93crJoEHFW2_Omb;vInI z#6afTDaoJU;}o>pP&@hX20%XmPe}v$kOp800VF|QG(peZCQ$%`ZaLkOsY+IwV0 z<^Cl;ZliYc;W+?n0-(W?e0U3>F@Q-VL6LY2;9CMng1mSQ;A;ReB+(VMN53D2kJL^+ z0`)%mC;S zKpH3#HURtxATKBqlK@x}&=A2*zZ8s*3HX>#8YmKD04N9`4HO9{0BQnA14Y6TfHwi; z1x3OeX{x>bU4F>@jXKR$R_fj~|%m`VrYGp#LmM!0pPW&M;tCCMOb*;W%WgCYlT};>7SluhHZ}05; z$ww2PZalEcuiwTRUh#bmv!^7VOMLo$@+!YxqpN$V`u57c|L9<%jmN^iU;ff!^l`sE zS>GFa;lc2}_?dm%Wc*CYgY36SD-Cf&@KImOmfdaXcHjrukCWCL((V7gmaR_NCdaHz zc|hL_GW42#?wD^vOGn#ed@JZdc52c_L;Q@{ao>biX|}kGPpgx4$HCnjm*ACg39f@> z4r5x4qotDe05%aot8uhc(h$HH0%$dkmP+&iL=iwMdbCth3qX$`T*miUvn?fP*&$ql z-@zq#46ey%V3}hXEtT8=5DXw53n9yBsU!|S76FjRp{0@t0Js4t6~6-%ltW7;(Ey@o zQ49C^Vf_%x99iGOS`4fuV41@cOC?#fRDv6T+^{_un~SBAELtjw0)QKUVso)nl0{1; z=>WV5ARV++l0b`Eill@Ksd>=SC)@zrgKl&KP>?Qe0E(@H8-PFpw4fMC3yP1h7>Mn` zSjX>Zr4aW31?l1*px8RN2PkzdiA9iD5{YGy*lH4+H4T9tx_(p3bE!iiGx`92T)_71 zUaTLsHgG)BYb90$=l*qWcVx{L!O`~yCcCxhG!M&(Bos=8GYG&10M7x;od@7FfWrWG5I_=v z0D=JA2k?X>u&!r&3IRV)3${xxg)WM{f#K~#De?uPR}16ajn?ESMcM(_Kme`DQHnGG zFoFPDlcN;r4d5C9w5~@fQj-F{-s;eWRD1y_$O0+iNGWm$<2?}xV1X2Iq!bARaF-;I zB94?IuL*!eEK6nD&zF_z4F>!7=1d$d?$Y4Lw4f~0)t)Rty zECB2$x?w*Nzcm72GJqriW&}Ws`vd^D09+veI&g}ORYZ@z`y4~CpO`utD{e;Tk>@|5 zSLOs@#my)T!1n<30o)`BtfQv=0>Fg;l28L!37{5$?vMyMN2`b(rcEt%F9PNr;LjrX z6N4qVINHyc4PX?2J_OKyh8+M00Ko*@qE*D^X}^}b7lC3v3V)K|j~NE0HP+;oodA#t zpc8;SSd&{u>w3=t*bv}=s@PL23fmW@>_uP|k@ho&!k=C6#|aD4VYHty8bAnubOLBU zV;}$@0D822q31K^MX7rcSXQLn3Y14$2>eM$1ifgt;xvFG0Q?9b36w`#Fn|QA27F&= zQAv9dwrno~r81Uip)b)w*|sB47|xkVl}q1?h@M9bVT|IRT?LhTofx7q7~=FQFvMu0 z5o}mQFD4-cgc_32B|OJ+RHL)z|E5>&FnSEo4 zXH+Bg*Z%1{l7k^U;{8p0m(Vu>!uAW)?Y(-;O;2&3wK4H^PEQ+4buE{wSm->T^RCtQ zPK$HjKTS=sQCMcYJ0F!06XmfY@%5`20selk2VG2g8tQDRNFK5>Cd&Pm$}4C?Re!&f zN1nMOw^g5^i25?;-P`Vsx7NjX3L_T2e*EgxUy+k)cMZ(^IiiaL9t$v4*V6dJt;m?# zc7d6J5&a!J;sR#qS}N@Sq8|zf%=C@u=zu2!Owq;91l)=Yu5A&Rc{0M#!6PBMhWX$C(R| zQyJ&rbe;Noy|I7Un9d_eCW2(FNXD6Dvd@861`)6HqK!#XHI&2-KN2 z{bp49`os@aQTi`Y`o0YfcHOsq*mFjlj7`eX=E2ytq>WC@8qu!U#*7AV17p)?Hc|tN z5$9!YQl3j~g2-E7Y#eFUz`Y5nO%OAS6G#n<0bh-ixk>rZ?Kp4;m~&ZXAH++#$0>3gAe z6#;Z^j_(xU++5BkCHmbN{XPO7+D#jsO9314bZ(v!QD>37O-eXOCsny{PzS_h4C>0Fld1^f-}XtjF38)Y#Q6rDRQ(JGCn2OW zKupVsx_pDI|5Yb!tLyY++1pT6!g~MhFhN=|nogjQA(-#|w9aOe668s|jK=@4d)+L_atrPnDr}uai3t?-I zoKTf|eL93=GHKVbW5I46H?LjtoHE`u*Xfy? zZ>dPAlw5huz=$?hiI=o>Ry8)6(`uzEvfz5`Ze|XeLn%ed-&5O zGo1sCP3AT`kb%d1t-%w5I(xkDIU}jz+8QvKE#RO|Y7_7OQE^u~=eL6F@%zTLDZVpq5)i{?uQuwHbM>ckPJPu0G3$xgT?N zcTeqpdW5_C)7x=zFE8DW`=-|V+uimWG&$sYWl8P#eV>Fp$y;KQe%+==qqu;k8y)X$ zQ1*E_+@0ptN8uXH^vZ)hnS_o-)Soz>cs`NMtEUR6wvDj@i7oT0x^9w-$(N_=vy-Y`YcHw`qBde+aS;t0_pgthkth55g9GXMX?ByD%I4yatDa8opIfPY)B zH$dYtG`gY@KJ>t`+t7Fo$2P{X>(P7&%?r^CAN+CbBs3pK^VewJiRP1Nc0+Tg7W4bG zNkO@-05}#v56B~+eZE5l1HK4&7|QE^sN9x-QP{fx-+-DYXxacZ)@bg6=2j@|b!#6u zY;(W}y+NZ78fT-iGb$Iyy5rao92wh5DegacnMFNUBt+W#-Ez}4vI&ZdyfMWgIMc-~*5T4G(Qdo?J`IZNcw>n}@Sh94 zVjb2``^#-t@1{X74rBY1Q#ZA&D=tJD%&P(mv(uv?Aq^QR2JoYUkR<`{^d9p6?vLdsp&} z^IyjAvPeF8zFYi`*ks@H?c=u@B|Dt&8lP7_Lnq z{+f)ka(1?Lv>EO=*J+`Hl`Aw(SmJDLu8p>V_V(sD{u{}m4GIp_(rPx|dam_CYscBv z(u3%|kCl(q}4XS;ezRMclGYVfYQ*z$-}VNE5zM2svxAXN)OSP-*#i8&tS z!kEp0_QfLvJyJupKOTxcOo)5elu1`92ogo&W9iWpLVHWeG2D7hI%ZBmTnfCD8ZP|Y zi1n}#U~fd8MN6zSXF`H!jqvGX&v=}3BuACmw_iWUH(SXN@jwf{)s^`6?ZnLz`7(RO z`d)^Ytg(VqmDw>p*=yBNPIIj7M`pZnFGxi5#=sqH7h5?vEwr`iKg`zIMXOSQhUXV%u?Y??Xe4;oUIqS+FHBx>3NrFqWYu1VZw`6rLpF< z@OJD%>+w#m1!Y>`z(f?6(?Wfvc{MZ&AI#|p53Xz7j?eC0vz zDhQAT8X2yB;A~f0H*0f>!Yn5z`vR>6{~J!VFkPbLe;<^Po5LOFfx%o0ii9*+J1%mN zXizZ?yrX6xG}Odf^VwGRpruh(i%ah(J4&mtdxdZ6jS=^=?*{`ks7mX(R*URi2fDg0 zw4Jrc6&wb>GN*K~b#yJDzu}Iq);87)g-+AKOPEIP@)!c~hsf#RW#nx8HWL@nO`L_B~P3ev4()et}eTku=XrMoq1Z0TCrywal{!C)# zG(rQF`2~OJiVtt7QA;aB(UD~$?})z8K>CTg=i1sk%yL>xqc>b>PI+QJ&uO8nFo0F? zabVYPhfS%fCH&{gl<|Br_@Inf$lhtT9p(r7MKn=NvbMFE=ju|BRf7t%ih>T6rIVsR zGsBsff=GYb=JTxPAX5fUiI+%F{OM17@FIK4C3DIv_I}LVxdm;-{jb5dLgH|0=*5H> zH3TRYQw+4so8W&RsKFewsC9ANU^h-s#~tT!5^=-P34#zaRrn&}hJTqRK5TNip~q4K z+t}Id!j;?qdF|JsRfI~ps;k|gwn4e7KH~*9xR0{9VTnXZ*|>qm^#RksJ8H(_f&45V zZurVv+)vH9;U}h%yFB`X%f<0PaTp!JN>{7*^00K1+%V;jIt?byo8F;-8nm<$GeiHA z*pWvKLM~<~l!b3NSqx-}$orxHp&wUCuKq-ES(LqU ze_|SV`jmU+K9RVndF76tBy^g)tYPJ9B}QGW78#;!Zs4$WMkS$gvu{+nJm8eXj=ahh zMjw@%$7gpT+cOk768#!g?r@fKJe?}2a#u4mJpYSU?iq=M+{%46t<=g5SX*-C_Aah+ z2Tl?6anE_6M3w8sj24zGdn2mcKbR(-e{yH_E-n^(P4{MfbjEM9I`UM~wOgt>Qw3kS zkFvO7j6_MYkED?D>^jRXxI^nlw%6K|e5I5{)W_X1a<%TGUgj{ae zJ5$ITKC4UC0+t_R+#p^H7;QblER`89GfiBBth&{nAufut z*X=x}fhSM7*X;#~i<;MMJ4>O{+-1$`_Nr&?(-W7!H&(hI8Wy-FuBWMT%i}NKhYjdy zyi#IE!@4b;(|G|$N%ZS$Qn#&G&hd1rpt_yR%<%j#TDLwD3AuGUd5$p3CDiTM8^zY` zFl(zh#no*?D?uCgn}vN9?e+XI-x|IDb*IaPYNq|!F!Io7ShubOimV5d3nk(+7=HMn_(Ct;EO9P5R}&A>lP+~e^QmGEsl!8RW<{wlhrZfPqB z@!|U@L2BWE&)!Az@j5o3TK@EKWy+?VqffjaAFdqL+5W*>k6GbX%mVjO7D*hCC@DKh zRGBaCXt|TbL}q~ZQ*)9~NnF;9B*Nx(8F1LFLAbK%<+106%;{*VtQB^DPioY2b!(O= zJO|{>@r9@41sRRKGo>&uW+?0=`t?~R%A$z#Oc@Vz1yRI*%nT=hqH}zER@z)bE=5dr z77~+F1n&@|h_U?{MbK>v5{ekO(4jbXI3w|lhf2f_8BT&(&I+$g1BJ5+!A?-$zUXPttO)UxS6>e)4fZ zV#&Nm<`<@syR2FL4)*>_dBb{$N?GT`q4N$gMyAT|ewe&2QM-fjdx;%+v%8Rg#qEO+ zXKBLwq0jO}*6hBGDdXu>LG^o^nJKw`E3vxc5_0P|#$Cu8UcXb+fZfl*69ptGiDaV5)4m=xFPymu{P!m)Mb4ynL~(aLz5fo242{ z6W$MvigyB2#?z^Sigyz;!%MU1)TwdZ z(Y30na`n`)XH$YJn<|&oczm-)kGG0=i5+<)QFw+f)YC`T?_F6U@_y)l2z}Y_bX&rd z@pP&nk~quE@CqwR63G$?xg^ncxsW$}hL@1U^2eV+62;y)v(!US%)7uNCL)PoZ$XHY z1Ai5fL?ur_h!3D#lDPRsTUDvvEwys@7snd@b3a_Ie4V^tq<7s+#ZYE}`zVVfzLO{^ zJ4rm3bhO+_!pKXAB=4u@ByoUgY?| zu*xh^xE*;UA*2_$q41RAJ=@V6E77m72}$f>%6OP7h$QYaGrYozl0r z31DILIR=B8i8q1nX=_3SUGd(Q$g_L>Q`OqI2dMl?=vZ({sEmMA<2EFcLX(LP!< zSR~P}&r(s=T0sO;#=~4eB$3C=a0)0&65UvFa|yX5VfUSom?eN)pcN#0esoB#VAt?{f2Go7 zy6LK+ThxKf0{2lCNn}Zsl$|6duNQZ;+)3hBW`OrobCPJVLF}?-BvGYt>bwq(zA#m` z?)6`~b06F{xVQDt&E`KQDi%uY$Ri0M&2R!ycyj?q)Dr#rnvg^tmeoAW6+{xln3uaCCTk(Kd;6BPCiIy9M4s#`CCkaocfp@grNg_((qUI#gXOqxr?y_bi(I!1) z!M$OX!;}#_=&z2c@+X6?oqd~B4cjKMBabA6xfUc*_=cZJ{3Fq?uL()?W?9WMp@K-l zftleIR`g8b7m0*il6dfwFv=y6#LPXPK@!ETN$77D6!R|dh>1wTnOW!c%U?y88yA=+ zo`~f|5?adoQRli3-oIL%&n$2sWs$_dAB7HcC1odx{Y(SzXt|Tbe-alpCy8lWgidpp zH6w|82lidw-DYx_GVwb7RWnsKxA;BCW@BAdsKkyuk|?rXS-1sSgC!#GhrT8xF^MVT znNUF_@gp=nEbP#n0J9kOhghtGwYlj_^XH{ z5|}1FfO1K~F7=f`&OiT|C_{#wZrpT!m_nKL=$z|p$JL4sTLoXakFrQ&u0%=MN#Y9A zz&mR8Aydm|3$*z*aX&RDi4{yEcUd!%SUAGa>GCZ*V`cN$149;e14&%yJ$g;(kCjZ4 zBzEMHgpi9LtydP3M0b{mydU}>LSObRP!Fbzr&9%yL@+bME37Cy16R3gdj|lj?7n1@5CPmiS(xr0gt_D(PssvxH)o5J}!o%~|3I z)5yn0GnTmR9_6+AZnjE!5nJ&G>$Rt!1Ty(*(&H)$ZI&q9jy#qS@(V0c_=aD2Opxf; zXQ?P_dt*OS#=~4eED^`d@Cqx+617=%a|yXDF=C&PHzlyd@|w%4P`u1bWr<=}B@RkF zA%>cres%h(p>rg)_6jeU!x#ze$vooh2Ij zi91^EEMd(I@P2B}5;r6+YsM0(TAK%*-BK+~d6BP5{P4>Ri;H{o!n(0U;Wr<@i12qOH^jH%Q>JZOZ1jV$YqHIhlIo|fh7`qd=5(#yDV{4;vo;2 zh$Xa{d0xQ$Rm2kG_KSvSutXwYQ5_o4|2l$}0sdp>3*c-&kkKfbYku%nyn~BabD7dMfT*Vy{HM zz9uY@#+30eR}f2dX2nx7OH7tX$YqIb$AsvYz!GgHehy0%yDpI-@sNj1#1h?@dCm^} zRm2kRhs7BpmnDKiE|{L${)Iwm@axT+Llq$kW%v3|edn*;q6lRcxR0_}B2S{E>?~n< zMBLGGXNl9y0Pm;fEYbX^*k#RFVvg&VmK%~4#>&Zao;3dLN3g{5dl}go|C*RAk=T*P z5<+@`B??zD`OVsq68-v`utX!4)jZ4<#1dnenUYz;OClkcB|=ULqs&>NKZ_1qmoQz* zSV9kYG3yfJ@l(jfu1YleRnW_Ozyl`Yh;hs~vsw5e;)q>L6F=9K%MpLPi2e6^NTLb* zg7x(aO2u^7N!5q{s7PcMxR0_pqTO+!!(2((Ibs#lz&l#*9C1hDqUIc7d_w3ncUd!z zxI8UA?dOw3OyigNN(q?NC?o7kuSD%HoKj5+!Blh$Bn`?`XMm#9N7rnsbCz zfDk$EvSu8y`TDv4QhR2FDo>eqWxre4@Zi5(3&qVRSqejZVmB_i*K zz9t+ojVa^lR6!iEjhW#UR+J+mB@%KuqH>Th$|Z3`#HTr;*cFLszX^JI4|u>t9I+!% z5aQ*_Uqu{|%rx=wD?g4{{#8h~K1}bB)aGomHF zGyY>-u9N=S$|i3lb~LJCCCfTK+!a*A-pmZIfTA^gN+Kb*hF^w>YgqDC?y>4S2F8`)yv+9iugLy#1lns5qDXa-~8ITfqWAi zw@sh6STXRN&nZRy5OH$LDq?eqlCl@^S*C$^wA_ohTBx|6nosnOOe1$$vm(A;bJb4+ zUFwD_n@!T!9n`6fsnYrE(1D#gCMa%7?8uwwg)%B`qSs}K$orws5>eKIfh|+UQ@(;o z;vh4_E37CvfbxCyzFU|wi8$iAmZ`Eu$dlha&QDY|V~N7;$Ri29 zh{&dikM=38CHnO>A&E0g84q&>kwh9Z!z-*PNwi|c%_ZcLgvC`MZ%QHw_s<}SV%H4L zN*v@76OlybpMrHx4*XR_5=K`9A)X*|N#ch~!|ms5rK^<37NjSRs(MACZ0MTT>d%=j z>gCJ=_fZx}T#_g$J4v+vL)_7FCy7PO0Pm;fBoQZZSu>J&IV)Q$Z@?g9<>lL1dt0Z1 zBsvaX?Xxyxw23iG6rKa}NTTr81)*v{5}Y>HOZ4k&LK63wG9Km%B8i5qbU6hSC5b^2 z3ArTUc~eMCP7*wC_z%b$v+q`je*k)<_1sb)AaPgX9S@g?AsRB%oEiA5h#{t56BmwL zhA`SSZP)8OJV3%dO!v{j_v1~K!F6wssO34!bU(AeeU!xz|45XSogs!?7k9MW8DbkV z!28KZ8kgNNe_}dc;<9E8VSVpT<@UoGm@1F$bp5U?JwRez*Tk2}cz}fE4RL7XF$CuW zrI6}i2qEDz6elG5^)+FLcT5=%a|JQP*Q|I-W{5cw3Aqfh^R^Iu&Ja90j3Jz_u+xZU zh}wr$OJax;ejWam#4#Qz5jpf^Ryir~R}ncZjS?q@Tyl8aw6WFlQ`N$iiH}wU=>HsH zqFleP(H!^7olMot0{2lCIaK;faFZ)3J2}i^8u%Pp?&NS*;-co{(DIgeY&0W>+>`UB zT(*B2s{C$wLg3RAcz(o-79Fi?AN(uSLt;lmawud8enRo5L_be|S*w*zSyuB*s339} z&&-re4l5)Qa>-%JU15|tIY^!$H})kX2k{f+h#X3Jd_<#YK`D2iM@vKy>30MnP7M52 zL=av~6W1WCe8VM5%3i*0{}z0$u<~_b26#U;FW*>+%bJz%mrK6>veDEkc;NEkO>YVw zA91snTi5Y+uR@L3F!IpID__29SonqN!XIn-PNH9*<%z8Fy~~vGFjr9d)@Mb<^S|iX zzo|q*ZuvHTAS5O)U)~`$xBsByDeOp!9}Y$3Thh}b{*rjcLnW%+pk}?*R{(sDh*71mkQ(3SUICZ}V6|h>xG# z)ARb7mK`Fe;NcOccWjO6y&J#gx^#QvAur$eF`dCIa35uH#9oP#vU5bGhvJTwJ4cu^ z1H7M_b3};5Wz9HZfIN;UJS*p4 zaxT1fpC{3;uL(y4F=af=6~qyl%nYxvqVszjR@+=cE=Np%BqU}D9IVXA&i4=ZN9|h&x*D9I=ZT;QiE`BPu@@yQ~>U^crlXI^R4d zRCzzBLw4+Bd_&1$MYsN2a=IJOme`SZ9+6Y9s+a!J{YIQ40wntNHQ|Unri_QVf;gfd zE1r@$VxB}oE=L@CA&hbf9P!sLpXP{S?E^Wt>0|F+tBnXv%r0n#Syii32t&FW#}lkjoK&rU|250!L(om&y?(KRBXYilCSGfCo&(5tht& zsT^^PY2u|Lmm|)$8WCNyS|bHZ41Bra()UZ=bO>-&r!foMM_C-v^QF*XuB7Z7v6*S$ z9W8f`NS3&$IY*306*|pb){G;n+5KHvztI=r%IdvcCuY%uBL?K}3<}+ns5maMBab5r z*DU!iVc}1wWJ~nxYr+vjSyuB*s34A5!OZXqD|)RFAd!&E5vl(Qqg(<<)O-ACjwp6L zVraUcm-m1NOvDkZnDJ6M;s(>i^H45FBz^U@$Be~Q6zt(LFE1#aUNw8y^Vjbb4Kf5@ zxsS3qVuD0T**PMRY2Y0#caG4`6!%kej&Nccxyzby#L&};IxGKsAF5ozf1&Yh_hx!G zM`?vcN$kku2qDd|9#O~nU5}XmO3=%Dzyl`Yh$C+VAvPj~FQPTeOs0vCpInYu zZ_vVUnEM(&Jnqij+Q$|jCm_WlJ`?{jtFKN`PgX25u*oIQe^aXG*+(pu}%2P-r$HX zJs&R`IH#j=Q%FOTzE6NcqS#5I(xg0Sy zU&tHI5t1)bFL!KI&{gv`h?@AmWxBVil!r!~kvPaBCL)Q9Ji&S)JFqt*lIZ_l5aJ0U zmn81(uvXiyul~`A#CCnhgY5zx)ZWYj_fZx}T$Cs&J4v+56?e4UNy3#G;QiE`Bpym! z){G=ZbXzyzzn+!V%1ho_S}p1qJT&4_&ukVi~J5{;SlQc1#6OK_1V zh+L9bd9O#a=SNgbDtGf0iLm(DjkT8l8)_x7BabA6G{cHS;qoPab4sFLBa(Q} zl<_bdd|(`kR(aiN*@qQR$s{pXA|aO~4r&XdTmngi2Ym)f6uTsmD{+uVOhgj>ne|dh zVs#a9BFZI+j`8gc9Rg~o`42t!S0?SPHnfWUY{j3<0{2lCNz|$;xXG22oh0m;2F`}% zP7*4Ki<*-}$7meo8H3@U~srZF=mlf(vzgj|yNvz9Q*C6UB~&mf6n*Cg6i7Zmd@ z@Q8^>!jf4pl_ZWaO}uvGlEl`Le?|Vc|A9)mLT5r;ms%>dvT3WW9rTCHSEMlu+(%g? z(X)ooVXma?B(a%k;2kY@l1P@gs5wcDs3~-syQ~>WtgW->p8fw0gefCm>`8R<14(#9 ztr$Lj^`Nlh5-GV|KPgzeXf6lw~!~1cQnpi51KYudt$*8vzmtxg_yY zM;K*J68%_**!Qi%^B76A23~YcqQnPA45=-sdoTX1i31xXv{3G?YsbR$G0q zZMfXvqZNte2hYwpf7VP0DwJOxeemb%ujzpi|J-?dP5ZForo@gsiV)K5;=4tY2aB@?ge~B;-cmS+@pceY3{OS1^oJc%U?Sz z&BW6jx)|x}>(?+xBDv6L^m%(m{evJw^g(>4u(fIBhUr55mlX5#dady;;|XN$W@LcU7rHooJQQLj!Y zly7b|d4H(Q3`G#Lzp{ap#B) zo;7dUtMSZDo$#cE-(%*dK3#E6t95I3!FO?&HW}5i9rd*Dw ztNdFx^3));^2;Z6o{#Qg( z;t12WLWjAMvU9{frh#{~+&SWv#6`_H!lIqfY3{OS9I?n^e8k3eSSy&#pX0Dt9nL*X0F8r4}M@_uN<5fhm*o(TpO!x5XA8D3#UIU-ylA(ta^I|-v) z0!KLC{xnAvyI3%>gP@o9fCo&(5nGt?QaK`yY2xE2mm^v)Nv)YN^ErQlbZCF2?ZZmV zT|B(i?Y?Oat$z*@xUJpYJ*}?I`Z2<{aV8G;)_UqD`V7TaED?D>G~$S*Oc_rngAe0K z@h`8tj{=z)USUN!;vb2GT#jh_m5?_ja74hnPjf`E>k&);C+Oup-~khHL~vI@s8o)q z)L9VX<0qFR>UQ&5S-V3mg>wJNbf11XL29K@UL{w*3H#JTnFa2nEROh2qNMB`@m$i; za_0!6E*OaF0;UWl*JE6 zB}&T94>h`rJ6i7iV8IOVernDS5fYa*pR1HM(~1 zY;}8_GA75v1#95+WBYsdZWjxFVEU(M?rh>Q346pv8{O~_k*IYs_KUf+F ziOKnacZfg3VG!d7@$Wnr@Iwjga8BYG50!`=Uh4~H3u%G95wU}!mmtJ5LoPd<&`oo= z>Q+De!}lAen$?Xzx#M?})yx9-Q5HKyN|cnH9Xj8oQBuQM>j2-O$ z=TrCH?*1mqT{=J2`@Y9eQ{_3YlbtTjH47Wa5{2i0Ja#C&!YFck;zo&njo9HKQ^v#0 zi>aL1p((3bUi(GaVW>nxE<1Sj6%v!P!`G}#89R)f$Jn6-aLL)jP$wtX;!Yl7B(CvT ziRhsbvs)@X%=lVdHFD|Uul6@a-JCJPRQV`5bJdH*u_nrgPp(W`|J@7K0cL^wD2pB* zOO%wI9)=ov;{nVTuwEBo$){Guj`rrC@{-1qR%9K{;Z8r@DJ?zw4wrxSx z#>O)xcI456kY*pBJP4(gp*ShguMs`uFl9W<1}weHnH~&T@svyt))EQ1^ssk;Fv^@B zc-}C2==nXP2k|4~3Qis-I9U&}aK;7A$%kfav9>1sW8eVFhqubsSIH`#Bok>454c*XyyL% zaETaVGBaH&L+odoc;U!p2yR5_(KWN)=3%c3zuutrlv&_D%3_GlCPIg~lCm?zdZvMQ zwA>lup~OYa8A7QLI?Y|yj3EXec+uQs)VWaQ>CEWAtT*CY4ZF>w6;H>$8gNizM;=26 z8Sv3P5QUGK&6McZh#?d#t9d3ER18BbWoCGV6}`kbCXtZK5J^g5lsQ94E-`+HF7^_G z9#&K0`egrsf=cc@kCliX+?icox%^eM0&$UP;wdPX9`@@7^>qINza7o2ELWN*9Z}Kx zWVJzpuiQsj^e{}Kr0n!?jA`HDuy0*Ff+WuiqgX$ z5(&BVkT*;iWlj$~I_wf-Z#JWcX6WdL6$qk-5|$??4G|P_*LkEwYX}x36>{?&5N%>ly;Z@TN?Mv?nOzYSY`X`CprBaa*k zmnYv9TwdUtReYVY8%spq51#(G?kf9_JuYL)csdz;7)OeKdEEdJ#LVytD@qQJB@%MU zq2(wcZ#X&d4l!~FXxX%&tLEa(3nGV-Rwow?7c_F;d8kC}@Y_g1h_eEJ6|uv6riqW7 zTy`+eS?u&LtxkH*nHYWYkNYOdrGNDAn)>9KYT!458{9`(?669rr0neQ57WRqYW5+k z%7+~cM~M5WIXmoO8oA4wu|v0xKQ+A{jn&Cs-nU(Upw-D&Q>S<&-)I(=C$S@s9fVx` z=!~K89AX4ZMBWdL*kK1##?#5*!#Gm>%ZnZUW@dPW6=jFYtg5+$Ty`)XC*%!h2gwtt zf7n&x6R1mBoZKpLjz>#G5Yb}=%bXbatB4?4jTVIX;K?Nj_3Pzh3Kl1){x;U-j>~Nm z<)hkd9D`Gzt7b6^+(%giaZsY9>;zGDjJTuaP7srr0p3r|2|_J#Su=t-Sa+Guc&En$ zls|_5+M-}_vO~bH)iym#3)N$Z!gD|#K@_e@3VHU?MTWgZzeWUcfhpr*HehL8&f6ES znHgUGMG2wW*QXh}UYq3Zb=%S>Qg(B8bZpC1odwj^^TymODW#W(IgaH7AHf ziOZT1M7YPC;q6+i3stJ$L}%D+#M)$A-GRB^ABqVzWr?C0K?oV}@fie1d?ordB8XU~ zjEC8PWnMWGL=#rFy!?w2#1M&uT!P4+BqSy$h%T%{?D|5>Mz5f&<_&=lvUatyG+(rE zuGQ?qUCk=MM_IefyC(662S~&T8<{a?qwqz<313eXJmMN;Rjj*2N!cov!hVlw;AvUz z72AacgZESOid`hp*oy@i$ypn3XD?c~(Av@U+ll7ZuIALO5$3K7Z5?gQNz9!3{H-|+ zr-PL z&HqC=yXl{Z#bHS=#j(hE<4#PYHJ+*YoLKx+u=JU(*f@9MzKc30MuS8ZJ}=)^ zf2t{7O_#=Jv*SyNt^15m#NszeFU7G4P%JKp#SEtAb7GOpmV?7audwWVtDi|sjixKd zrC70;XlX5Z9_;%3PJLDD#oryxI-IVsy0E8L#;r?g-q#;@hy0Y*dzQ*Vz!i;|9B;R; zqBV2r(-$hx!Cu4N(@e?1o^RiMIu@%eKM@O+q?h7Y{MB8E#eAmbb7H|)#6wst?n+|e z&SKGm_0duii=SC67_QKj#KO+x=*~K+FI2AEYL0hkVrjY@->@}WckR=$*fjGKvA8Pf zr8pJ=YlT?2F*TnPi)5A;$w8|$itIOg)%6IQ!n{~xoVhB^!o}o?b=J|b5$OuW z#`azNw@?@6#qJ}QvU2oit7>j4z!m>7Ii44}&Qs4T{(Yeu_eK0bv)^W#hTQvSqn78t z?D$e@WS7+^VsTf}OK~ig9}{A+lBxOsAr?QGIlk7mex_PCrP}iBKWCW+-22z%<^CGs zLaa)O#gSQ`h{YpGFU7GKdqarDMy94bVzHX##bY+!CS}ZvdNZ_s*l+h#^;6%)75LME^GJq)uZZ||IUSYO}koHBl~OzsN=pprWkwi>_2Z_ zr!zbvl-I}(WAjDmo?30@#RjuX?K}N?JJ+Y?r}IKR=M%AbC+Vd)7GwJhu{g}s zd`>L1v}XPtw0RZgyu@b?)fB2dj6Zl^)(D@`$GtCaHD6>>`SoA71$iz}{TXo83ntgC z@qhXYpoh2abs5xXhI#k!LssMT-c*`p+TriZ&yV$L^66Myv;IUZsxblHOK~iE&Jtqr zn?$O#bFFGD7ByKcj!I&&j`guJi$zsQEOPU;3u5t@$^B0fi}MSUtu`(n5^go=S$m4b z57i&O`}K2T5i|D_v1q^qijPH`bwVsu5~CxlpBl}MEqi)*bz zY+P*aE3QR8wH~njhGNq4yRBE-zbxd7GwF5X4s3d+Ha}?U5dF(T_2_O0Pl z?-Q};!UT$s#q!5OEbdCAN{hwFrIE)+Y`UkI*Zk0lZ-!h~)HvPfrQ-C5ShVf?GOum? zGqrBb)5~k_eW*5Z3|KdO;={sNT&(l=g_|!E6sg@7RR2Hr-UF(sJ!tzyzyg9@6a}$h zJtBw&QAq+SHbkV^rGqFa|F69bf*8WyU>zVFT+#gbk~r zz{i_2u#%@4enf0jzdMW3Vl**mT#Nm3EBM=yLYkE*Eef4x+b=JF#@x`VRY8!^edd;e zGb7oB4O;Z9os@J?sf;skTlVV8138?yJGED)hPihft0Yqj+t!`sVCIiqyjrmXeN;k;PN z4DRpqx_3oO{3Rq2y9M8dRz%nkizpykY-B zeKh|u$7g!>p3U)>7>lJnr9Vfm5ut4*Cu-P+tkdffl~S^ z&_Yi6pzQ?!A^2o zFk?LXjb_WbKegE1iT{}MKKaP1ZO~$L%{IP0rNw%p#WkYEYMK^lGrS)t%2{yrma9DD zX`w%_#^I!q1X}##CPoWKT9(557uInCEjkf5l4xN)FF8CkGM7DN@s|0yhI;H-I|ZY$ zsa#w5@*i`?-pL<<_n#3Q(uZ$PEf=T7jCDt~y*Ut-EY^V zN}|OC4>4K<(XymzQ6kV{2yr8c7F(2(r$6&BVeTLOEq=&CCi|E9g_>V~XrZpaf6S56 zyX7F;=_W(*x4@pt)lBVmPU}uL*&0^_{o-)!rijmxqwD*{vcwu|CmnNcS*+&6&)DzG zJ6?JClqCCFGna|cB7~Nuuol7c0sL+1XyQf^Emj(?cf9||kkfIpb5zGQTI{qlIe~xn ziz)~HW6s=pRWWkV!tm2tzCESIOrk}9qD34{iwDM){YR=>aK9IP&EaV=X3Lhj`5F=& zkIeTJqs4Aomcm-R))Z)AK-@^8MM6b;ld|x(98X5+(iX(6sIwoFZ|k}9y^YPOFq<7pB2VETivni6Q?+5nh=%)p^yDwsT56#y7@rM=$SNlBY^^2$xK66Liyu!E=)wksV z*i%{rluWOvE4axHXnD>C>v1^p1spf{p_XU%a17oZYsr1?G^m!Rh2pVkE`7Bm(89}G zj235TSqf{xS|QM49&say7Qf9_pB&{rlJk<;PdTWZ!G8Ry1c#grb&(=?%o%>lJ*oE; z54QIbfjyOLAGN6(Q>J(@KJ(fIw8+WRNjm?OQQt3Oy9V_6)YF`M@PXQlT~f9z>zSP7fKZl9T%`==ICg2$ZIK~=+iphfI- zfjy-~Z=%H~qQxtk7PdOyuMatG!EK>q#@Ax+#OIgBOQJ=juNW<|Xjuwt!7UYN5k%Zb zqQx!aO(tow)=ZtHhMi~kAHn>5{#?nQ`xk2xV}A1X8y;TTU$5u4e43Rl+HZDo$2-w)GtNp_V^UUD{RA(voZT^~ZExT};;r&YL93XXKEd7%lQ> zSqf`m(pGS5Y6x*7i5BhKA96`loW)UAX`ADJiowpCJ2dyt{R=Pe0ldc?-H!$eH7;-1 zYN3bu_EfIcAroxyJY!D}-X9@UaSm=A+Lq(jpFu5mG|}ig?xh*G^!R55yAL+35zeW* z4qfWY6)YFgFV6al(c&E~OJOZMGzD7hCT=9rVtm{S_tEx_oKrm)9kvRd!#2IJa>$oI z`bF8p<-Ern^$DXx-$M&_MGoJd%GH)=v5#nRgr-GMltb_Vt~s}=Q|mjn(Bj6poa@`K zNT5aH3Nc#L(y|oRBGgQv#X;gm5-lcYT{RrMdI6``!^v@z^=7d590|<+bDOHe_2oV0 z%zG-YSPd-#+;8yhDJ`ss7BNlK#dUVk?beemxKUFl$MLjKSU0lks_PPHaVJ2G7ShCk z%95squRx14G%HcZsV^r-Jue?HpEF|QnuE_TJ2U5f%}x98M_m+*O6m0zS~z!~-p8e| zki9Kr@PwzZr?iOE8Zj`sB!jW1ch{4jVfXP-H;X*@p_VTj6?EDo-GY0mw7(Be3(Zlt zx7*y1K#S~^Vzg*S3>w#>x1Qj52~)RXZy}>`mg@DKJp-O^Hevp;~dq;kF&niUmuC8KgTySV6|OD3 zJd)b;H;xTj$mZ}ime}72&KzjE_X7J_IAiYNwlb2B}NNvV$ir2q3r`@ zdGALa%}SIOtB4jYh!!1bTC^cr$Pg{+Xj(`UExr;hmeI7>Hm=<&TpwZ0EOSZa9gpm+ zDD#h%L<^bKVzgic3k(|9f;(KG#XFjnC@s>b-*A*NeZkC98oo$-`9sdez2TLsy(;Q^ zqs+SDhaw~2GLL2GIT^*~aFSL(>h;g`hU+8y*GnxA?)I9ak}&7zt7GMygnd2-7xc*+ zPkly=u1@9*^fF~VD-GPa9@j@~Q#($QuWH2=EElnV(SD5>Ev6B%8rNdKxj>6rnw2Om z6f}I-_l1}z>~tbISB zeHk;Ryr}+%>GEU*<`0ePqOXF$ znk&$v2XP~b7OyAtHw-UQ;nn~SGr!S`M+m6cxgOhe`{IEUr&`&`wV`VlvWd?!@l%f zX365Due;3CVnz4Qk7XpO3%ku?w1}f+DXc}Xo8a5Zrx7=jXfdzV?uxP29XMV~XLi!< z@>tLB@khMD4RxWkga4Shtn-FVA;-AvI3gz&! zdOMDfjybFEJfn}ieJwwyWm#d8>}$D)h|%H%ElXi7_J<3!uq19I(W1i9Ym&L*XEt}5 zbI^{!V@cnQiugHExrV9mA2atXHF9{HoygubS71*qj~zaQ|9nh_Knp*&(!{oIck8v7 zW0AeZK;43MFaFINo)(X@&N-(`qD8TjE9%Ew~Hg^(R=?GS-j( zc+=|rlcXPyUJGfl|2F?IQ{T>6KzJ*CBp-_sm<&&QK}_oy$M9@UJ=tk=SL z@cudN3oKa0m-fHlX;GkNR-G$}78|#U(IT0aB~6Q$0xjH#8%eZKcU;$hwSE`oojyxP zZNFp9>D5syig$jK%GEU9f%lnVrr$J4yRCPWowcXE@m|-h#N_?sQaEV zr2VK0h7yY{?XQ0>X-U{ep}Ghh!hg(kuHEU{b=obq`f-6hrG?a~NdEIm(Spy&w1Uw? zeAb>%qL$C@x4xGQ_Af3!oj-zi?$=Xqor#wu=YIEX7o){XT9(3EP+#M|fw+-Givvp@ z@U@uN@djUuN$abGwD>wjphc40E`H83w}iE*7$A85>^|OI_EntIJ4Xs>k#(}y)xE{$ zERR(-{dig=`|6HbEQuB;cZkuVgqEeS7SuOlhZ8rFXz_#8MR!sc?zFmCMe1S+sfz)$ zx{x7t(Ua803|d{JFD_r_e9(e*YLHoHo)%_LpRZaZi56Ev#c1(?mZh*3)Rzm#5jT=( zu`#3zqhCR5W^%%i1+0Hem`3z!?c;HSRd*!!3NJ~G{swfOwkHasn^Su1s(DTx*-VPdrSMaxoH z3+h``PY^efXd(USE?f1c2XowE^-rUw+A(aN9QLmKLyN7O_VFGwQw=_S%wJN-m~j0* z-=69Ri`kzP-r@P77X;Twq>6G={1;uUKi}yx`*E((OEcDsE9*ws;N0)UuyTjJl3X9j z2p6M;JTaiM6xM?Jw#dsgD^bVnewxp3oM`99oUL}-|CEsp!`Vl-u;vdfMuv^zJ!T%3 z4vqh^BcHLheJ1@|&Vr#<4@XN;)7w%qmc+uP^4=ByPHvwV13 zELFKNz0(;9&V#>-5Tk_>F=$*1>Ra)WX;z}N$bZ|?()hCrGu=NewzmqEF)tWLcaayg8e?vpK8 zkH**T=4ml;eEFi@CnV6Kbf*|C`Vxc2wV=NJE1hN~N{cZ&j=Z+(wV1hWwC3_PC+BiD z4bZmy^oJHd`}Z%ag%&$C7L4lh<|RYnV7ZGm>?tjtkL!MR@E|s$?yS5k?>fp3X&?6; zC+F5L{~W9A)+fV)wbL^63QvoI_CZ@F$4j8a$6aEy7)A^l*Mj<%qn9)*QCbLcs^(ZP z2yK({#F8N^o3X0XxAFDYL&raB(ZBZ{OZLO8ZWFl3_13AR8~v+R)#q9ocHrcI1U-fd zdH%k@u6{XhuY>o6IBle)datyZ!?OPUn=@v}Q4V?CdOJ$n`u~6L7Nf;jV$ir29^@Nc zN@!N1wBQ|S^Y;tpv{-JhIh&pE{`rNK&Ww63t{J>t?7!ENk+^Nnl4liF9BHe%+5W4} zkzAyt5_N03wVG|f__9dwJV#(xpW}+F_tfkKT3AO#Ok?4bl)sCSO_qx|_uDo~j24EG z0)xi2puWH21IFis=frWp`p>)6G5J!tPFvU?@2QQ~(JA6= zkhy)rF#Tl zi*C_kv@j)NHLe9Utp69yN|Y8YaYm0<7fC->EwaxGXVm6@_M4`+vtEnvv$64qd5=To zKB)KV%vrQLoPT^m)p8pZse>|DFPeJ3w=>VKUJHM#_=P+zq=IF8GYqCM1Mvq;HF;_* zv0C(t5u?Q-B39#CP-DsEi5tpFloma&+ESR%JxiwL4c z3!;TJl`|2;@Xh_>y!Dgfrq}l$GV@g$w5T!Ln#j{)6D~Igoa?|;#~*c7F@}rR zLUWH8Etb%-r0rjj0nAFojU-y|_KzrbBI#wpQ{(ZkPqTkQ;F-*pyWWn?I1a|eyrSXSqwiwnci~j@AJ9!cw94tZa z9Jg1D7RzZ_3Tr`4o9#>7NTLPRJEb%nhi9xUOsbuKJ@fq@W_|C>I&N)xVD{If_7`lA zKSu9dQW*W>dT>MUTwM6FvR4F?K|S9=U{|ljh)p`yJS})1#c1?SUc_@}O3*te$BNNn z4J}JyEvVs|!-yM6wCGIgLZxl>?6@mi88T)Md(Zl`y#6!NQ+BTYJGm|F%lqF9<@L@% zftpwT?43C+51Gzu8N`q$&&MC&+tq84-{++jsSDOB^v;A9Qm=niOVB&b;>2jNotCAr z7St%gvBZreT9om27g75Y_i@_ku8m*>KYsLX*qDaiIpo;_jjg=LEFIP&^v+B_;okYK zbFlOCH4%(z>iI{}JiB@=EM|L4^R&RgjNW@5Ok*1U{=H8%UxMCgwNH!|F|;g&wV=Xc093M2~amow|0ioK?nA%)#?6Snd3IrT#PW57D9p(IT75nfJlR&sC>u{Pou4 zk5`5trmC-FH$T+|EslOaa@Yo1gl6;(R$bkf`Ska1tM8KZPJ#PI{#{xu5J`qC(;)u~ z#+-O~jpENBF{6z+(QahSNd-+OMat8^#+-EAFL+H#(MHFdjBUb5Xv~QLUc>N!n74T~ z&6DukOwGR1Aa1CjL~SAknTgniA*uf#w=+E`MvHBL9HY!;Z!Zp_K@ zBVx2TN6S)J3u?^CLgGdeEt>6^lQr>Tv`C_5DXaxG=ERw}X%1Ta=P@VSkBZSEjh3ab z7Sxy%AL8bJLyP}wV@_g@iP7Q-ElXi7JZc0ZUse-0{~KCtAR}MO$jBE1+Q^qUG73n6 zi~_2qjRFcDnm2uTO(A=Kr#n{FY)4jE;+zdV-*;n)-A2bB7o$Z1ElXi7sF5$*h#N_? zXtpC?&YuvY#d}(o!dg%xU!sW{NwjFTBVX7j#c1)BmZh*3)X0}3#Em3cG~1Cc_fCn? zq9rk)vJ}>W8u@aLW+iGLyxER?d3sum79EK}<62N7Uy^86qO@qXBVP*7h|xlo7&NX0 zHS#5mW+h6CW;^nw@~jvw1`~tEwV+16JfT^M(xTapeEF6jMvGCzpm8mzkuL=_D^XfB z+mSD=&Wq7P|D3>}aV@BkFYjqqqO@qXBVRgQ5TnHmB39#CP$OTy(yT;j(QHS)^tvcU zi@8Ls#1sVC`K-@^8MYA3G5|SiFi`%p;g|(nY zzAPhdB+;VTj(pk87NbQbElXi7sF5#$#Em3cG~1Cc2RUN2$fac|tOYglWixRji5AUv zJG|fuXacZ+2`I40)Mhit^(6|=V$d_w0D^XfB+mSDMx5Q|nObi;=f*Sd9 zn`R|Si)K6W<=t&DTJ$FdjcY-Te95F)iPECkj(n+26{E#)V$ir2)X0}ynw2Omn(fFJ z>APaI(7PirXj}_wJGtEkr7R`3#OOJbEw6Gvz zHLe9U@}&iFLs^N^qS=mo8E{{W7B;jjh4(M0kuQqGjU-w$+mSEY55#EUO3PAM3u@$x zGI1k`7R`3#3*(^}E&OR&3Tr`)eCbczNTNlv9r-dXU5pm%X;}(uL5+MFPTWYMMYA3G zVwoXEi!fT2!dg%xU-XC@NwjFTBVTMEiP0jKmZh*3)X0~q#Em3cG~1CcZkb}VI8Mt_ zSPN?8iv@8bi5AUvnZY0s7*^YeKkS#`wo3t!xT9A=1uEdQb zS~S~{FX4~HXz`GirLY#%$QOU&MiMQW?Z}t7Ct|dCLCaED3u@%cdg4YBEt>7fmlIFL zXi-edQdkRWCn6xMs;f*Sd9lV&AK zi)K6WrR0?uE&33H#290Y$jeM!0S&7o3*^YcsdM!qa zSwyVHwV+16{G?fl(xTapeCb;tMvH|+tj4tnB_m(th#SgElori)O_N>ym7EzyJB8 zVB+cS;o#}*?BJ!Nb&WV{O)T`u|1C_+6!5FQtF5zxoA(5F7k5v71cKjqMrOQl^(XRv z<^BBomoBA(w3=`|(b>__$IC&qYu3fP@0dK-T$#Dq{9jnt@*gp+h-)f!>WxCwio93^ zt_^MMyb*RQJY($RYU|+1e@hzT-X9%Z#ym@NH5%5uAGqR;_A&Rgar5%9@pN#r^B3n2 z=GDx$Z-ukw4dUVbkkHIL9PE5tY&=D$-8)|+pP#MpFY}0RD(z7M*F4`H@vGTlXE$dz z2QRNleje^_c-xvz-TJAcBI_8<-N*)a9q_BEgQJUsowu{Qn*@nVNlBLpC(df{h5?vT zlU$v>yquRi@ME%sU%WFs3p3t_P5&Q@f7eg_GxKSlsR39>n^#+;M*oB3i=rKqGHTK> zYxew>3tfwu6N6iXJkI)*j$abCW^ey}kJ;{>NG+%$XwoyX5`O1-TJWE7rg{G3^UCYk z^(DY}{b$wxAv6EYuUEJJmt>l2n#?mjZ0wx9{Y5!O0M-1m#V>z!gx;hPQH_9lMZAB! z9z)gHa`E2(a7sDhztrFTGpa`L?oe%BgRI`r=B-DN>0Ujsh~MU?xjVagds)rUHy=)G z@wZ8KRQIMnoUJV#JiYMYnaXSNpJ+y6TD(eyAVRuNdW%;fnb7kWYVmuCGfMtHO6Gss z;_F1amZ-&BTUb2d7tL$60*;`1dgNSV8oU=sK*{+(Xz}4RSO3!%UrGE?g8sJ_-?_hF zgVtN<7rjd1wEugH=hXyj3(eg~QYrZ8{dJ3f%`7I~sKi+f-u{Ozo>3)8oAONSJ^#JM zM~ZeVuEoF3%~kE#F_Ssbx|N1mN$@q)XV#a@E(sTzH8jUGEhK93Lhn4Uq48_Ms9IQy zKR&M#w|L$g!>VtQ^}igUxu(hd-&?#4X++ffN4?_ztrq{4*5aw|(PpB9qr0c8gQrpT zTU~x@G2^v(v!%{%z5nR*QY|PuGg-3u6!A!J$@OjC0fw(>M$|!6CnIOKrB(u;`gT5^ zHg^6*p{Xpa*7y(mgP;zm&6GAVYsjIuDcMZ*#G-~A%zQi@ZR{KxNn#msDKd#8G^77f z5-D}UN$CA6iO@wPiGEl#!Ntc5hg!W|o&9WF-94S1#!hke@RDj_=3`s`j__)X*y(>1 zcyBTvd)T@VBWd!|)V8;cg_ncpL>q4#!G0)jX~kz@f7WE3)>HA-Lw*ik&Ovx3-iw)G zfnSTR*-s2Q;P8UgK_P*4?wpp^Ihor^=3VAjq;hW=3?J=vA#vQ(>=`;ddRb_+e>xoTwF@W?*@~qrspTY5K;VVSBWa(yh*4*m-see zU5<3WJy?J0!9kOp@0sjgd~a5qy!qiyyEY$?w>WO-v&1A~-sAXoKAVs9`n>s23q|LN zb}^53I*uF|Cp+&^xTShl%xLw@-ODc?l~FC5=yW~QX!iBY*j}FwcS|apVD&9?Uke5G z_4*2qZ6-{0=$@i{bBf{cn31VkyO(Wsk}fl{@1$(xC~p>>YBv6%x1(0X+y{>BGOCAq zMc-Meln^>;sH5EUxv8F(3E>u}92J+&y|ZF;Lf8x!$F}odq%L1xt&;IkTJu9E&5!bD z&qpl0ky>8i*xtQ*K){PTLG3(3C)~LG>PAZ9jXU30ayPELb!TPr(UqyCDkW_u>!vO< z_6RrITcTi9-QTKal#}iqot5`}S7!JRtCnGUhE4x*E8|D<*##x?v#+K4xOqg(|B+ht zibd}#NyI;j}zf0Szch;AUh#qR+zh|Fy;jt=3>fNr%_1inX zsQ;RkMMtGt4xVTe(qZbXkXd^>?Nkpj-5IaousL3(_&96QkXg~)PnhglVt%yMsN<7d z-!Qp4M)by&2TpKDxA8%rH1pQzNeihbaHi`95D7#n6Y`8nm-CO- zhpgk0r_>79ANAF#t!F#nG=sO7Jyn02s6oFLcGgm>+t*qz+1X2RW9BEV7&XKDt1~^V zFRFCcXkGuSWwDf$+uB>&bu{19sa`q$Aug{g+Vge^ct62l4}VN$74v|S!&Qfj{p{Vp z4V+x>kE}~MR;PK~1MicZ_iVmL)~{xsAdQ3iXj9=T)`!dMsX`%# zk&w5O(E15paxC?d`$#I6NyzOpZlA<$7g&s2Yak$$@zGfq&;K+{iSooi{BJT^? zh>93``|yWw6Qo3J=;U1Mv4X9UI)eFk6EyR{aeb3raPk-7s^NQrpZZM`uM2t-Bht~N zM0CO0Z^HiU$vXe)g0r!}uZ3bt>!^0JQc{mNp2r7uInrmG!Ndvc&-*G*3R$P!!*JG^ z^7LN5wRr(m7p|q~2AsW6nSOnoQ(WSkttA2Zb!#rjN+(sgs(pW%(P6^-Dyi0E@7`>; z>{yCQWt$WQ-@}Jg-gmzam*_D8tazCQl z@yq$MQO{-vK71CKvXbo_)OOAz1EtHGCI#NNRjPBHJ}1kRZRdRd%NYla(g1c<>!8K{ z%nx?Vb8EVuE;<_I=x}n*lO>i{HjFy$;95TC*@~xiUYvy0imvu{oKOGkdH(pUYl%+K zQm^@6Vl{r|Szf-pjrrw}tE*GMxGxdR?^`%8GmV#D-op8sxbS_6+An9{falrP0WV%L zYA@~Uv*Bfai+0|jYgG$PHtObd+@M@JWwP$e;oE)ozKMN3aiH#t!Nxu@*|7yiPP(sj z(|zJTE_`j!?b`GH!+fIeFD#fg``XJXhCPax`(Djn?5q67 zt?ufxz{U&hF51MQ~TCZPvyF;nN@DXSRiHS=N<;fm;l^l{72NeI+SjwY$7 zkx*<&Xw>pBk|GJ2Ne|gYR?2!s={sI0+&?;Y0jn)m)cPvHw-kT*C3st@eOgMShE5nf znsmbc@YzHs#3`62b_h*>3YSfztuT-nNze+1l6WO772fyS@L{4mCAKeD&2_g z^Jt~=jJ!|O`_Z0ODgmTaR(jj-eVeq1JBd~*`Avi?qEy69qaHz0=|MuVrj<%KNzsa= zLfKKJw3KlyM)CbSwpXOQsjHF|D=e#P%W<3Ui{EJWYtfbOqv=x7S}DF%Fps~9QVIMm zL8%-gMiP|DY$-v!5|&CKDV0z%y*GwT>7{ggb9r6hZUs+vA(__OhD`6JmfzO3Tl*lz ziNPY%em~Hr`lc=_n|iUPmXSR+b4SleYp%A^xp^Ujhj9h#S2N{_y!3EIlnOPhyNHCA zN2sE{c? z|N4JuE8$Z4_d#ZG7%7#;4>FA%?3OlJDDgC<8to~W#7Kfdv5*xm6mh#(*}iMr^LDSS zRCHW)Dw1?n?!5S3F|K?}j;@ODUZ2TREtMTcZasfx`OaA*j}Hoo*X!YEcI3QH)sDK3 zdAmYcuZKLlny%>Px#d+(!LYikGkcHh;J0Z((SS`j28!xnAlFar>tL3?{H&k5C6fL(Gr#cye5S#*&URcn3n=aUe7Y2SQ_dWJV1bc|`f4v;OpX znK7d;9#O5K4mBU`lI>Jx=)2-k#3FSZ2&rdB27Ma1-n><4Dy!A-C~q7MDQGLFdYtdh zKj<88ACWRAwMJ`)R@~%ht{o0NBchYddzH$?506!TP&75pR_Q`?%7VBO<+x(qlHvPW z4lVLuWZiMg++@?;=k|6zW#9GW+?07w&&74~-yG?`ezyO%XZ~vyU5aMp*>>LZBH1#p zMD_BySYQ7gbzg(qf8C^7QDny`Fk60ZPsW$MdKJZO+4gGRzlNOsy21VH_9|Vje!FE+ z{Zxv(-_gA}HR$!^ph73(Wicc67ORwgU2pYuTmILz%xhd6YBCoTS^avmYS^;qe-;$? zcy{gP47X)_#^n_Es*_vyb>=Y7&J%lm=w#I9z`C#LleM+v z;{N`p7tiSVGHbiv%k0(Ly$_C9_;#A~X75Ae^xjU@41YUAExc?x^IL?$5Sb}X*NUO_(`=1Ii_LV zn0PuoEfS4z&CC^s56;_iO=*p=Gie^ps1fd(?Dn~}!&~;|xvhe~q}j4AJ^$cUaZrvc zwh>yi5!(pYi)@5b9Bk~HY=mcNN;TRDUlJn;8sX;Fe^n^FFGT07r{@9$hOyk7P3MBKk96soqV zjrkohTTCWxbU&4%d=pzt#YIw~2bY$zca4!@v47gJ#@wo7v@`i4ev6r=C|oFpWSiQs zAFg$c6v|L6`uBdgDerug*;G9;yyRJTryENbmafo=dTpq4?Zrgi zLA0ArnrfwYWMb}{MRnKmWqN%I-KbYMYlnYM=K*^Pr_S_$IU;V$R0na~Mv&KE`B}2HyO^emh;M+QI7F{`D)LBrBaec6;T+!rcjnj|_EHwyIOi|D=&$ zt9t+2nX0+zA1o6NR()TsHZSd7P|=+r+pZ_)J$&~xA^y^-_c&FdT0Sr1+vtP?+gw~a z?|J#4iLX*{_QzQ>ML{PyulC&8pA~{LL55>*9Wc~=uz2IRNq4(`_jc;_TSta@UHfN2*^t?Zsbk(OEa#mL zlGVAM_He-U+o#>U5~o&r98Ju5->dF=#?M~W`!|lS=(uCWgEw(nFS^WJaW5OEgO11h zr+-{jeK7JyMc1<{9+t-kq$s$rxNqeCy?d9@Z`j5P!X>zmd~*JEiZ&bz{93#>({C5t zTOlB(s*6?8*)F!4(_>y=@1wrLS!Mn!SCiUrvGe6p4ShfMYOkp^Z)44*vem5@f1Z<5 za&Faw&9N7*p1AM#+b?%YUO~>nyCvHjL*{ZW2EXy(~pNu;@ zD9++@65Hwc{g+lsXUAR{YE_ZTd15zyN&cx`zxKDa|2lV>MV<7Smc@sD(!v+Baef&W zXExUS9!I~m!ptzkDvpfvcuuaxadPw~B^5J%zt!)&b(|Nn0ev6eJI0xK^I}o$=Z3FV z)@CoBZD&%&y!Yv9V$gznoV^(-7H@)5>c3Ju;de^eo3ZU!!3hsdy!QWO4piFp#d>7+7-<^x?zIn8F|Ex>NN)ikD31vKi+n# z?<$|lQRhRXl6%hzIx$>{wc%?!A1kwA+*bjaDzzF%sgSAH`Pctby9=bJ z&L2)977gvzWAY$=hcx>Ki<)S+hVGsYqFQbWO|eE>ZY432pyhfh2^WmGlS9 z9~eyQ8y<3S;_nx4Q0j zrqsx5U{j%rh)o%CwnZo>e zpY!uhKwh1d+LuSaf8T%=O%jo!yITx(43Aa=K`o<>ip7Z*dlZ z`R#u^T4Gt(Z|R)uc~38ISDTMZa936<{=7Bw=Yx!&$(pW3vxDB_3Y;D1W5B9}%`;p} zc8snYIRAMT|5_aH3f$A>m#?hlyugLHTHnOyPu!MY*@(jk_wUc21=acn%cvGv;|Rj0 zo$tDSs>O@%bg!6mM>kK-*gHHTw$S{jZmx2=_wEa^Zx)p5=6C3J_0gma*Kq}I)C0j0 zgu~U73*XFpb}g@s&ehB*hjIj$;oNjy3XUM`ww_D9_AD?pvHmck^Z1fwGySs6;%c`# z>6Q9-o}vAsZG6;{m~Jz4Ql>Ae4Vj(f82>B@#}Z$=pC3{(KAl#B|C=X=0=o&!?6>`R4RL#$oNwsqT!9oK z?n0Q*Teu+_5b+usV!{)$|2YVYnrMhqY}}eYLzGFAtI=-wgBVHB4NZFqSIcPPu>N>| zH@Z9Ty%~%JINpD37tldLWJ$@K?DU3{8+{@RlJmt9|7{`&m#iwOMhx~J-E!H<@8 z%W{1uNK02P+t+%0QO6zr$!2jid%N8z>U!3H0&6jg`@4<0a++M8GTCzs2&rYqZ z4#xBPZc-0foYir{3fnZ6igMaS$MYR#TAmLR+*5?RwmyXIlkRf3!}`GnvqHjH%chxx zPYf5_wdJ||~c=SQ%qSkgC~eCw`iEW8 zlU+QHUD`URXkbuDx1eI3pwjlgiZp-W-T;SIzlZa0?2_!Ru7rq%xQ&athfDZ&E!?Q( zKg=U+`X6^@3GT__-HWbJGl$dxl2fibZ?>wEFwvCJi=}=G_<9Y3ji) zM+Q%rOWhZD+`!_*tk@op4=Y_dK4BrQQ?wd+xZ^fw1GAXSy-F7kcg4M0^IvAhwevpQ zIkwDzb~jwGM`Fh*+Tooi%A1CVJeKWjFv#X`pS>3+c9_~F^KicnpKgV(9-|$;`GI|( zxKsB1#_8UjI?OX-J8jbWd+%s2!5I6({k#XUGoF-kfG+GbB4Ied`ovnvvu1 zJ-QDZdVQSBHBdSi)qkji^8L9tr&*qh8Fk7*wfqIwaP+xo4Ht)=uU_0V#&r+93J10C z!WTNIOB~m@lN!08;m@7Wt0rpT_+sS@|C`en)x_w?PAuET3J=@c+cY%X{O|z&wIs!Y z!~NGxIk;(n>hQw@cPrcq3p27G(6$D5-;w(panY&adef2aa$Szf_MfW0nSbNm;K}|& zOv0v_#|z!sczkl;ANSnx?rOXkulUF9b_>Z>rcd$h1Is3_YNZv*zo8M=mJGGRXKi&9 z+-av3HdSyhqjz4RYhJ;^yf=Z2*Ap0pyvsn0H(u=5)7gbf*#-02Zvq4te1ZyQ2fgwA z^?K&7Lib+5k-y}0dGn-CdTQ7YA1_m<6ekDYcZrLqHcZ#$=Z?DpDQD&6hcEr&B6yOu5} zZKZSVwrizFWI#@7i}wDv?Bc3-I*l)Fsp)@vX%XEEXyl;iZ&C%{K*-$$ydg!f)T`u+mTkEDxa{CY(S$}Jz$xd5!6W*8akK!%d60pY}`7KlADH zQ(vuOwT#MZsn%n-E!uemH~Q=A%+)RC)-mq*stNaUFs^A`E_Yqaw-HOuavkg zzqmu8?iXubn)(1cD&23Iv1IU=3Ic)`9h41K0>Qfz2QUYyn%rHn1J+0HGiZgo6mM6YK)JK_rL* z(I5uw0ee9#hy(k;esBOB1c$(3a0JAIqu>}g4o-lR;1oCw&VaKZ0h|Np!3A&;TmqND z6>t??1J^+!xB-#?8*l&@+yu!W1>6F+K`OWd?t(OM58MY2z(bG@GQcB{39>*ocnqF^ zr{EcQ4qkwl;1$RLxgZbZgV&${6oNOP2o!@7Pzv6HGVl(Rg9`8-RDvo{4Qjv#@DXgL z6%lXemiJTN?s!GS`5>)O;;&mOL7mwRZ( zTaL_tf=FGz^*X+GHoOgYG-@X)IUVrE^JNRj@buJZ5eT|Gg z6CHDz*W!o0_iyv2{?vKhF2{a1PStQSX0+Ey8mrB5v?` z&@0i&%jpG^3XKXu;1ZQZQn4Z-n~>0`<#Hs&k0g~;j!Z9o`G%0+y}QBc6BF0Z?u6W5hDp2nDijwni1K+ zKA~7YgIZ7rzJRab8~6@>fS=$O_zk4mp>BaRkO8uwC1?d&gEl}8$b+^(0VslYpgrgS zI)YB1Gw1@k0wvH5bO*|y2j~e@fGX$()Ie|02lNH~fI8?827rNJ5Eu-GfPcVHpaF&f zO`rva18pz@j0B^=XrKee09`N^j059=9$)|_U;%w#049KmU=lC{lfe`)6-)!uff1Mi zjKNG`0%ieIUnS;z*67> zT!9;K2OeM<@C07K8~A|bz!&%de=vz=7O8MWG_V;Y z0SsFVsxWe^FONkXHRr;`-ll2p32dzu@0ry=Ad*YV}gSZ3Vg7dEg?MA)#} z75aE{23C@uEuw*K7$&ZPNnQPm28J;sP2AOLHbl7LG}^#|h>-*hEM=&$KamY=1&TEQ ztOS7|2&@9ZU^Q3+)`E3lJ=g#?f=ysE2mxEbR1Tm+ZEWpD*t z1=qlJkO*#oB)|q7zy&u!GDrcpz-^EU?tr@>4cr6w!2|FRq=O9b2xNjRkPRM#C*Ub~ z2A+c#;3aqkazHM~1Nq=JC;)}v4JZP|pahhHx1bEX1LdFsya$z_3RHs{@Bw@TpTK8O z3+liZ@D+Rm-@y;?6Z`_dL0b*sBKofl>^jX4)e)N51AFc?+kScZGiHa{Nl6El$~b3n z>0rdwh6d)_s#QUd(S4@Pw(QlF2XZ)a(*1sQz2DHlf(p)zWEWO2WA4;mnHutndE`a= zpu{u1>#wGTx%Ivo#(lv__3FC({k=TSQki49T7NV!SMs6%iw0IiLf$|^+e$*98k7=A zWibhP9|?_Geu<>mmZY+C)eX*ugocn`#arLwzBA+Q$}X+FWoyG)oBsXXc4i^z=^`4~ zbuDoXOzSi`c{~ikh&zNF*<=IjqA6S}jW#eQF_NHxRnq*4sTrk@KDBGF7BEY#2N~X8 zUdmZpq_uG?>qY%WZ7F8%fdcnAuC2 z!To(+GuNb^xN-D1^=FOPwrgn}+z@HN;wo8h|6E(hdR#J`cRX;DgF}UBL6B?!%b4|X8iS-zcwx5`x!V` zeaLGQz54b2zc_C)STD~yG%jM2wu(8|Z{OUHwly~OHS?s2a7FAW?Ia;np)DgJP&GlN z(t(8hgM>ycUrSQFMpDtBg`9acP)Z-6-jh>)XopaHm=w4Unkm6eQfGC<)r`mMzo?m} zkMvfKkf3Ic5+ey}rec(^Kao318`@*X2W$eHK?v9awt{V7JJ;m-_JRH205}K^fy3YkhzCc(F>oB504KpIa2lKeXF&ou2hM{F;3BvL zE`uxJD!2x&gG6uxBmp+y04}%*l0gc%1#W{>a0lE4Y2Y5X4<3MrART0YM<5eqfo$*? zJONL^Gw>X|058ESkOOi-9>@o;K>;WPZ$J?!1|^^ryai?89ViDC;611WRiGNwfDhm! z_yj(KT2KeRfUn>i_zr%6pWqkx4W#fF^(}xjkO8uwC1?d&gEl}8$b+_E!q;~BI*=36sbw9nft72sc5nNmft~S7a#}EBJbP$OSk-nkurss<_C%Av z9&=gi?R-C@P761%x>p%C12yDXg9;WO?;&Twow7-|f$b(AdV0SV(ZD{EkdsJgMI;2O zK}C{O)Je$xBs6Nd>@VeH8Adn zzi41hAL;3h5w4X+ca#9NB8L^d!56ssa=2ik)Upd;u6I)g5tD^LR6KzE=F zdVrol1*n2vKn?T;eL!E(52%CwU;r2h27$p~2>1sK1sY%&&;(jwIM4`0v6B*24Di12qpnTFd0k%Q^7Pa9T6ggn`er zBKofl?C?0@VieQBSa~Vop^>@lR=z)Q*{_OIaN*U`bAL3j;_|KYa}D*_{k)z0@jT-^ zt$`WuSX`yJYEC4-||?(jTsU& zu)_>-4NNQNFB(|WM|!_#qBYvU2I~o;k)VM+C#Li_p^3eAuk`%wa-4yjf;n3JjoysF z{=+7gHSD#QSJX0gx>_?AwX{+>ec&v^r`-SUchna32BdkM;NUTHV>h+;D)2L>u&yu9 zo?6~7F2|)JuQf|^!sV;w9+un$Cz;6If9$nyAv)8;6|vD z4L{^{Bs6My3n_JeioPV3`LvL??Rb1EAE8!fnU(Nrrnvj)Wkm`&JN6Qwzqe2X!=lZ1XH*%G+H!^h>-+EqevpBzY9$iP0Mb{)1P^m zFjW*T)cis*==PbH*t*lr`a`ufI^W`lEM&5OyE7-scDl(>y~4WmQ8cYd$XiHg zKS>Azm)O*jR9bonLN+3yQOlVmMGcb5bXv$Bi8a2!%>0`ac`VtgP1Tm7JXr50H_9t>zsXIn9D}x@OCr|;ZpchaBy+I$) z7xV+_pg$M@27*CgFc<><0YiZX7zQ+f78nk+!3Z!Ci~^&94j2P;!B{X3j0bvv0hoXV z^nn4G049P-zz|FZQ@~U(4NM0{Ug5d0;+R02YEp zzzSFc8(<6UfIV;kj=%{l2F_p!SPEQ#D{uquzymA;p1=!u10S#)_yRxR4_1Hxuo47< zAg~GqgVkUSSPRyH^#kA;&5xK}B|XFSj`trKa!MR>0(qS&qx}fQHh*-mK_*U79oJ~F?*&e{ zFNY4+kJiE1XZY(e1HY{0`{{aFxPyH@GC4h>rYmbn?;Ux*>K5F~cETNO4f)j58?J~B zHi3jZgoJjNgg|wuDk>Ec@_G^)wLG1qs7_MpLJRr6ab^FJ2=#lx*Bo94)7`RVZoY;D z9c(+7J)426rO(aoL(F_NHz#Y_?QC$fWuW5+%M>;${OZV(BgKs1N} zd%#{03*x{&upb-%2f-n57#sod;3zl-j)N26Bsc|5gEQbPNC4-+d2j(-1ed^Na0Ofi z*T8j<2yTERzy=(^1vf!5NCCINZIBA?fV&_K+ynQ)1Mm=}gADKpWP&V^4IYCh;3;?p zo`VcAK96?_BV!4L2g`~ts$6uL|cAPr=IENBT@f!3f6kOT6dEl>c8pdDxrI)IL#6X*=O zfUZCZbOVL7BKof#ENrT9F^cJ6*MGJ*DGP7QNj<2~-?xggJH9~vj}GR4tmNsGzN6XF zuScxK^9(gw2a7D{ug8q;^JON_Px0$bLi=DXPZcbg@Q)H}MW)j_`2q`WKVL7%_0nre-9ux`@@;YiTIQi&=3U1(y*eS1yMyl{P8 zj=|MF&v~0YE9IP$x`Kus_r9#O0C)FA%*hWUjYr+Q!dTt%oXw9vcHCWuX6xcH(|S+e zmIvUcPO*UF27Brq8dh!B$NpOv*1NIaZr+Hs>N#*x%LC6b8Xw>pwzhCiFTuxGXPYXG-hhy+=g!8m9{ z(cCr`E}F^Y6&sHBOs0^c(ZC`RM|-CDcAKV;_0(nv_k~7FW*RY)pk%(%{E6u^A7`yT zIm&$`hx@6dm{&60e`=l|JH>-R>AQ8Ax^hrCgZ+MtmO6*A@L zU;nQ+6IU{08$t2Gb_9t>bNgZDp)E^801Hm9L7z_dbfT2JG z3;wD30dNo;0*Ap75D$)m zW8gTDHx(|T|GJ-ajpj#8|B};?svJ3@5A*RsYYh3U;%x4_Y0Tn3`q%qm9Y%b3$YA^Q z*`4Nx{#8TkUj>5om@_MXzvuZ;3l{EQSH~PCI zYEMG`PC~0BAyEC~B}t`4UqQ&TNNCjZ-+crrz9*^lqJ{i>T92 zq<~xCHb@0`z+I3A?t%N@0eA?~K?ZmPGC>x|29LoL@Dw})&%q1u61)OAAQ$9;eDE3+ zfI{#F6oFz;0!qPKPzK(Ca!>)@gGx{ZszD9-06v0G;4`QNb>Iv53ci8w;0O2#eu3XW z3O%C*kOne97PJJdKx@zj$N_oK7AOEk&feKIs zy?`3%4f=q-pdYwLE296}zx-zl7o(W|m0>%-^s=oE^Yf$3Twedu2tQkE_DBEHKj|^7 zgw0@QT-E#%+{pe{%S`@yO#cZ2KZoay5!(Ms)*iFI{EjMXPX3|+zfW0k`-~RuUqi`f z{xAC1D-yC139SfYE zbvV+E|NfeZx#QOaU)15>^kH7B`NHpUqct;}7)ekwuWA0ow3*cQhg=dBXK|do2jucD z>GhP=m|NrWroLv*Uu>P@e~Q6Y={-~y&$GjO@V*GU;ga6{xkGvDF}p+@=KJwZ7~GcQ z*S~)KE^Tj)pS7hgYvHf%LvOt_)(1cD&23Iv1IU=3Ic)`9h41K0>Q zfz2QUYyn%rHn1J+0HGiZgo6mM6YK)JK_rL*(I5uw0ee9#hy(k;esBOB1pg0vcLER9 z`}dDus4Rsfw4rRN6e3HQX_GBw36&ySX_ciYg;J4HsL(=-_LUZuWu`1;i_$_umS~Z+ zg-U*};TkpbA^P0k`@a9b|Kr!=`~3E4&Y3gs>&$!J*Ewg-T-Paxh0|~b&cZo34;SDf zT!PDR1+Kz1h=X{z4maQ?+=2wS4R_!!BtjA-LkiG<4)>smEs6f^ancDp)@1CZfE|b~ zS~u0vnO2>e$X5 ze|eSyCOyGe*>>hw>hz|Yi3;~E=z|Wk7BCC)q5q2lc8G+mNLk~J05ARRK`0X&3E$bxLhfn0b5d5{l};RzJLQ+Ni? z;RO^z5xj(Acm*X;3T5yb%Ao=(p$gtWHPpaccn9y{1JuGtsDpZFfJSJ7X7~i3;R}3) z7HEZU@Ev|Y8~lWJ;J`lW2b{nK+|VBwLzXkfBIf~K-~+};(~Pll2ZI0z0%JH-#(0#% zFcd^!7>EL6Tr+VP4kKVBjDpd?7;i-qq+kq;1;(HRGQjvPxg5yDIAHwfbv#S}#&0hb zf$=-C$-ww+5aU-YjNf}q0aal9?0|8%H{%v+4bTL}O_rZ~o(W{g{+7&i}1 zhZ(@Qg@tkF0ORX;#`nf^;5u6p{o4X&?}Uxv4|_%E;k%iV{M&j8{x&ov`o;prcP^z9 z*4X@Bz-$)iMbFWhoAP+PDo;Zz=SoJ&W%WKC{U-TQ4 z^KH%o`s6RsEJt9&$cLUi+&_FbQ%XW!PC`3OLg;8V{!fiGwsS<6-8M}UR@=?`!T}R#Ws@qN$-g2Rw@trefbwx$W zQK?}UKmT^rzNob%vk5tKXOF_n=h%)wf!Kmltj~OdY+|L>MFx+d?r3nSw8~pRzcE99 z_Wb5wN9_h=KmSF}WRQ@hNoWg52+Ws!O`5{#*BLUMgvMO{vt72MiHAs2_}M~sRoi;m z^$|j?k@aNcjFMV<$g-q9( z8A=}#=GZFMgmEIz=^7h|Iaj7N7GP|^f;aY}+&Ea9XE#z)ujcK}xPA_M3iU$v){Rg; zJXlhunlG)9eMD($$>`v#j zCmjRRtxpT5GROZ5@{kE~)Os8>>7O%+4hX%^m`QY5tV-uhqQfz5PN<$%WfXmuN+cNx zP(FNM)IDPfdr`qDN9K4Pc;IzZ-Ye{^*I~_^H;n0XqHFpub(CoCnkc7p#5i@YaM_7( z6ic0djT`r7bZO_%aTqMEWAwN;%#j5d1R|Nd|iESepD^EIn1M zX3zV)Ee)fknthjStolKV&*iF_-5USiB4%OB)i--f#iDJWfA`;VLDTE=1zXj1pCdde zNzGnH0_)bEj&Yh~8S~uza&?pH)g~oMR{xSf+L1~Q%8oZt0_4NbUdVdrtK-HDHjl)F z06!O%E(p=9r<5lK8LTxwPh%FT(>iADdL;oAp7ZsS*FHQ)8~*g^la}8m1dx=U=)H7) zJuUEn*z{sd2w-A+@phJUMAx7o$CVAX1ZxV=hgO#5TnKNYxHf%zVfx#I0QY(b_YZyb z1rqXc5}FtZff@3E#hpzNBq8r3p)r>;n>dOzMU2i>IQQ)x3>%)XjRUh!Amb^So6SgG$i;|mf`|y9eJwnY6oB=MH<_~g5xp`DMn)O4)ZRgy(JhRUp`y}R4F zooTAp=TsV8lbO$-@m9*?B7U$DWO3bg7Dn3dw@1R`_mMDFNtt5rA^uQuV@Sx%m*6KM zF#pX#ni51pen~=OE}ur4_=PluJ>>kCX8eoICsA)MXf|Pl8rIyTh`~JRozMTn{fbi{Nm+BR}>SjCD}x*X^vl0yyRAiQ{tiGLu-l`Z>|5nG_%E@s<0h1 zK4mZJnC0o%-UsAi0F?Un+m-vJ&wW}!K zr_ucd+^)?W^iDegW<9&I{_=-Gp2;I$y_Hi>?3k=++N*by zHYPquu5+gi)P6fg@O#8>Q+NA*-`Bn=<9c*+l33DP*~y#JFD`AqtDf{uaoy$ziKWdc zf|Z}LOW72s#-O|H?ml}S}mqk(QbPCjr}_m?M;Ihz7jrk`A5;@VvZy%gDlfy{We_i-5EHV)4~Ri;G@Py>;{0$B%Y%rWF-U+R)n+ z4Zls@y_0QIGORDUDpLz_lGwi%uI(V%|_>qzd%Y-{6Y_pD)^}BJoJU^c;G0Gi0V-w*O-{yBnj#6$f_xr{x=bmUsS&fY}HSkt@`nk zrtBltuad3$QArcqNK+_mAqQ<5m9p1wHWkCr@iD4jrR3Z3C;L+Ubo^MW-}HY}Ke{5R ze%;SN#W>*n;{*Ut*!EVprLT>w)Q8e%yp=UsCX)?zl|JTB)nl=Magv{UOPr6B`$ftu5UYd$zE-hb+*>?>;8LJ+fP|sm^Jm*_3g)M?bSCIX6t@& z_uD?ILTQdhmU4*uw(z4Bs>?O9H6OYA2isJrSl!N2yW+n6$g7H}8*gXp)HVC<(ymaR z=an@jx_MhfQia+&uk2~1&Hnp*DyG=BWT~e#Z;$y=q3+v~P2sd}iJ@}K@l5B{bDbd+ zHa|da&@$dRUSowq^=HZPnFi^3*b9YQr^yMd51Qj6ynp{J89819jGNv$GW}o|gE^a2 z_IC_L-`#8i)hmrlexD*ak4vH{@PT%@LY~(n{-sU3UnG?))_dg*)NKmN^C_QD*78Vj zYg2I9kMhawJb|Z2`tukIZ4=(}IzUS11kYUY`@$g&v!up`1{#Z;6yEzbO-e28OXsqVZvSYpbN>?>w9<(G>P;wqUbA zO%!}??&$Ys`@X3jAM?*Sg1>kimp=B^SnTeTy>*|C%O_)c;BQTmeVI;Rkh4l~QO>eS z&5?PWqVa+06PGDuTR-BnjNkq2(lW&l)_DV_#s}rDUN)h)@R7iV_~4S-Ws|=b=JgYB z3rrnVKJJ0WBVH4?-33R>C)Q}>^`GPxlxbUEV(>SGrkK0gn`>AUF}c>aFABSU)0zv%H#v-SAGY&||N zX-WtQxq_|7*C9=8B~8&`3wiG}0bh*#Po4K}bq3?7ItOasc^~UbkKY!++T;K8r#e(q z(&H=kc)r8v@p~EgKZ|Xjb=&WMCM)%!-`CpCnlgX?i|Q!oQ_uz&?%307bY3tVqh12}>cIKy&S0WPo-R>5jm18ZR& zxWamH19$KMPuKt(!3(@$6Kn<_*aBO@7yQ5oq?JxZ+WTV@2 zX!7o6)E6~d4(!0d{|hsQ%;u{fK<|A1AFkIV2lZON9Q$6sdcL1<_YT&2({25_NmlAZ z{ra|xb$frTUs=f2Y{-FJcm#Qn50Bvq6u?t>2G8LI6haZagkpFFB~S`w@EXdY0xF>j z-as|fz*~3+@8JW~!bhlsdT4+~Xo6<=1fSsxe1#Thg>Ud3en1=igm&N30>eNQ#6TQ|!w47&qhK^hfFwx47#IuEAOo@> z2l6lu6kt3|fQg_8lVCC^fikGT6i@{8*bG zo$7o2>iKp;!`-Z@(rx|nBrElye%;-}y1hTvuldMTQ!oQ_uz&?%307bY3tVqh12}>cIKy&S0WPo-R>5jm18ZR&xWamH19$KMPuKt(!3(@$6Kn<_*aBO@ z7yQ52idak&Z z<}~}~^7^yIlwmp|Hcl6myN3OjOH~{G@cc_kGXJm(TRs-kChb{xQ0=$+&?@~~ zY3V)_{;Ulb9cI!4hE5*(O6?Kle383a=6VNe=lj<{i6FcA zFH)w4ge*itJ4ixcrbIDm3XO!!42`)wi!`xyP-j!lvV}Y@ZpHDHt1YOOr{^3=#i;+A z6m2k;19xn@J{Z>BneaG`?`qMkN6EkDN*uy`| zx~fcgRB+{SDj!|2-dSn>C=2@H$KFwlF*%tjlhs4Ge>h57Lqawup=FQ|m??3Z*%T7; z91e0vg)H-UyRGRc3u;2qvgTz7RpjU!4(`4T`hO~-x0LbA>wC)de3s`L z-iMSqLRRWS%Dg_vy1hRhCHalUQ3h;-?GOMvU?=Q?KnQ}}5Da@@FNDB8*bku)2H|i3 z4#FXbfJlgf!*B$S!ZC=37&s0m;3S-aSU3%5;4GYj^Kbz!!X>y2SKumKgE)wX>u>{Z z!YxRE+i(Z&LLwwVGNb?v=x`72Ln@>}I%L2DcnF!01=)}Tx$p?`ARivX6DWYE@C=^A z3n+vlcnQVu3QC|9%HTDWLj_bq6}*9JsDZce4&K8DsD+PE2ldbZjnD+m@CiP{7x)S- z&?u6igLWFkuf?5 z#V>8yG_M<3Da;T1@x7AsawXf6pF6KpXFPs&E^Ga&In>lKs)*<7&h6yyy&Vz%`JN8* z`E6PuCyE^T=mY8f1%xn=zDxS;A&$S*uifM`&t7i-P`~ITsQZbc}kJ2 zsnYFH(qghwAL`ff!>rr;WBrPhM16t7a0HIRF^Gm3I1VS^B%Fd+I1OjuES!V$Z~-pD zCAbV%;3`~$IEaVqa070_El7ada0l)}A|ydFqyP=*a1ZW7Dx^U=WWWP>2$_%t*^mRd z@CfoCA0ERKD1fK%44%UaD1;(-3B~XVN}v?V;5C#(1yn*6yn$+{fw%Au-opo|g^y4N z_0Rx~&;-r!2|mLY_zEr13g6&6{D3z23GKikh57=Vzy;jU9|pic-~nFX1AZ6;gFyfU zK?sI`Fbo9|7zUys2I4RrM!-lI1*73DTN3@-`W116H5q%UU$$!N2gj>arF=i!g2Gf! zX|fQTFj67EtA2g6+G!DT-alEpdPK+L&%XU+tViP@e`Jp{ZXBwoUES*1v7H*vCb`M} z>0R}!Wh&QRU5tI6y!*^RAB>~FA^TPE@Ab=&eCGe6emRhk$60rVrbt3yhQxKGvnkU_ z$Tvx7%;ld*6AMXGYS}`*oxDFRfVO~oJGCK)QNJuWzdZhI(uX1c4@GzGdghJj-F!=! z-S_&{^I2X4+dk{IevLfV8B8DQR~A{7{XOX6ko`>XDSO9zoHQ-ovmGh(_>h>ryW+2u z8CqHx?3toZn{fW&8V|$#l#l)EoPSRlJ&A~pe~(D{__>|VNxMn^@&fBqnD5Vc5hGW( zmArJdn|i4t>n-WD{-;B{e(UnKkloB4?jO3m^CV<35}F|if%%fUq$&N5cZNKggvMOX zb-c5Qt)wZ*Y$4B%3T+v=-jYgt6mW}?GMmLeKjrF6mzQ;%HD&b4EB?BXRw>D)N-r{QX55V6wS4`P(7xP^5PZ6~oN37Ui=65CJkR<>A97|pS*Z^> z^Y9ew_WpRB^lcRSXZQha@DtjBV>J3_-~=waEfSE80W`iEg0evt4LofnkmUd;HiHjrfvw;RLb0q#^ly)oXl&c*rGW7$xzDy3{5d6ZR8>c(cfn!glD7qkT?MS4 z{DQ6fwwz18cW7qE<0tZ13)mOqj_1)Tzqxg6$C&ask$>$&9cHz7yq{`01fvGmRit@P zF^K+7&B1)X7ce*Sq5q2lHjsqOOG5ibLSVk+e$te?B;*Pb8gqFpX<{U4iUC{5RtpM( zXUHs|W}T_5WE8MxPvTr2^`(FrU+ArXQOo|Kfc1Q$H~b81u5{b!%_1xHp@0RQW8K~# z3z#rYCWe9t3<9vr|CoWL2D!wPVLm9Pp{!x~r%>%bM(gB!Sm z2YA8;*a%+W4Vz#y_`nv}3clb6{;&dp6TKR!zi zE4TGvJbsGp-pkMV9nYgx9PZqXRNAimMvcc^1?zqv~Uyv2```m7_LzE&J|E3=n zG&zdx#FS_#Vtoqp4Z4-6z?a20jILOF(TOwKlAg6aSJaf#p4z#*fwG+JXZCRaaHc0h zLVig?lO!Q9U($p$rLDa)0#*~-K zJ-0786Muy@XY|M`{yNih{Z4XbA{KT3lS#%c#D5;_f6!&ts?cr5sFRiYkTKP4+v}yu z)aB=o7gVd&^&Za{d$pdDIAN>%FvDM8=PkOQ!s$IdE;-Jv^YNiktcOX9?OfhKi6VRXFEZu}33(X_ z&4q-(e90}ODK|*SsU$S!ayn_EC~3+bwva8QcSvyI>%3df7f)e~9J*d7V7_}_Mh;zn zy|;{^4qDmq{+jomF+HE<>0a$a#<-A``j9bK;#jx$$AcsfoY8s02G|H*;0>E#Gx)$3 z*b2Vj2mY`PwnG5yfSs@l0wD-?Lon=ty$}NXU_XRH7=*(CI0%Oz0wN&_4#N>R3dbNC zV&FKOfRk_vV&OELfwOQ9&cg+`2$$e8T!E`_4dNgkuEPzu3AZ2tZo?h83yF{f$&dmx zpu;`552=s_>5u^r;2~r}7Gy&XL;3X8pD=2|dD1+Bf z4i!)dRqzI?p$6W(~k1RF{rbAJ-Oz`Qoe>Y(mTr6GTYAbrJKnpGz~OnE!cJJE2Heu%HuoB*SL5! zmh!b~EJq!qe2w1v-0t8T3;NYZwk+k#ntbH{qI{j8745A?hj>8E!38x?yPQw{E3+LcGT!4#k2`K z3liWq+=0802uY9(DL?}{+=Kg&3TcoI8SnreLMCKEHsnAqJc2yPhsW>)3g9U`gXi!9 z3ZV#ILNUC85-5c-cn#%H0hLe%Z=f1#;4Qp^_wWH~;Um;RJv2ZgG(j_bg3s^;zCsJM z!Z-L1KcEeMLOXEa{Hz~v0vB*Ye;5D*fd_bj5BOma32?sUicUCZAMw5j3Hk)W$rCF<~U+@gy`p5&|=% zOQb0SI0`#LZX=;FmveJ;Ht_>#N+w&#j@}>IPa9cMSH!pSFf!)0o#@bceaV=ENvs+3 z&#!;!S|no>5lqi#c)bktU(dGBx=oo8iJigpA!Rbjs_gGU4;KXtKRrwteb1E=92nzK zhm?6Ry?N04l@+?o{Tm!B^GVIXL6>7-Q*#*}A9tN~p#LS$Vj0h)UB8>%u^q~sXST`C zHbd$@nND8LMPFA2?#gur}B zW>c6UUn8M0muHeDP9#k^wSv1N|?!*IUZ? z8TCD7dOpV+o6K4jx=oq6WTif&Oc;%Idw)DgsvC*U85*DwnxGjz!DsjaU!etB;TwF1 zAJ7Irp&dAIUeFIXfeW~yKMa6@zyrL%2mCMy27>?yf)ES=VHgS`FbqUN48&nLjDV3a z3PytjNP-lMfw3SBG9U|bAP?g}0mj1wmCS+4QpU6tOHkA4{qQNFWHjl-yS3d(OHwRmxH9($%RQ5 z1lCd}hpJUHqJHhqd7{a`zpSf%c}k{xUou{%J2fZdOv}D9-JFp>SWc*xdTKJBN8=DG z>DZ2Zbr#(*Z%S8}xpC6gpWh9n>1#c16$PbO(3=Nex3c-Ierc1>{9n|sDD%;px&_sH))P-g{aQIH$w>H0ABH?0meE`N z%3sp=`qlGEUIp7e>$ZLkzTX*4AL^G`8f(h@v3?DZKz#uo-~~S5he0qH1V9jkU?i|Q!oQ_uz&?% z307bY3tVqh12}>cIKy&S0WPo-R>5jm18ZR&xWamH19$KMPuKt( z!3(@$6Kn<_*aBO@7yQ5u+iD zc{L^X)wwr}q1WqNJe_7-F4bjz*!4DL?tXvIPS;oP;c+EAUT4NyzY2mbF`h@87tPnP zoqSV+4<_8|Da_}K(VkaG&yuF^yDHPjJ$nKD+(P>;zt^uHJ%sy*kK-OpF~)-YxRVDA5Iaw?Xe@NbI~A6DC8JDL4F*X_HwkiuLZ za%%X~1GmP~zYMh6z9M%4-CslR((~WCyvbxYGn>!M@IR!C9tk;^gce9bV7}xx(iBdP z_>PdxNodUF+#Hxd3{7kyP03;l`O~rCYscg*pdPf`pTJ0&a>1>^bI$Z3WsGxKQ)VW4 z#b4j!aqJ{1qku*KJj*k4S-!$!fvd68a*lrHp7yhxoY%RnadI;s_-pOQZ2PO*booJ6 z>O;DCX0xWtLh_uh;s2P!s~cm%Z)5!LTcdi)L3OpqM)f^IMwXP643;~8+(X@P+_;i) zr|}@4;kY&Xzg9|=mvZ;#T<85@Gv_^j>cnk4ash>DVK|9G>YEQ=H4p9RKh znLa%(ck|p_RpqBACVf6Pk88w}zzo$B3b`vx_!m9d{rtuW#g8lI4b*xP^vL7Hgp#)= zf}5TMmwq}inQh26-3kZYa&rv5ucxy6@t$Q9D_gcr9-haYQn5--B`DK)+4zFUNB7Xr z&&WwVuuP#`xpGnNnod^@OiNScOMPakd;f{pOgh#RyOf+HTkqRd<2bqVe1*Sh>n4)N zvpd)8TFz5@V7B8*Df-O~wU(yKtf_}5+n8`yRFfLoK$$}7#$VLH&Yjgjdq6_#PeLF& zkz*KXN-haGjV)wd(nN9ccotj8j2+^Dka=4T8H+uLaxb3&@BrEly0`ACXO_t?7Rlr500(v_La^w4qm^)Fq zM^6O~4h$R8QC)-`-_m0QOoEB=90DZ%MgvXZR|)aiVtkz++U;LkqcW`WNOOT&ZpBxw3&r&HKQEbLo{&t9jqgkC6A?z3FLtxz;rc)Hg|t zewX&$hrY|>4F8hWz_mU(@*XwjoASf+-p*e4Ek9zb&m%FPOe>#Ub)W2wpO$lQ4NtR6 zsTsJnN`7m#80KiP9iHK;rxa$o$9WJcq_5H;N^3B!b(e4JzV_h{yyTQZ4UC=n%%d_q zoRz{C<~R$u2iZ$BFQlsSFHEzyx4v(7DDJ3rh4no{%ecd8moO1a&~h%`j)5U(j9px$ zCtO@~&m^oUeXUvH%<(R@PLkgZYB&aJrY#F`J>W2^hFe}U-Q|(%A@`&5+xZ>cLXB*y z`K<2fiN45`+r=0s@=oU@D^gE>n{Z8G=UCUR0~_BcbObe=H>DgsQmg&jDl>NL(s z+PYOw)UGrH;_ijJG( zWUG|az1AyV)Yj9!Ed6Tb?Hfmm1HNwjSa{vXMOT;Gw)63Oo$GbgLutuHt&HNLuj?8x zf2SdJoS9YI#0z}X&Qj4pnMrEMU(`d!FV7euXOPgYkPt}q;czBRxkEzkM?zyR4<=3g zN}7_w7V@UsS(1zrjw3O<$Z$g{u3MKK)GZ)QYUpYjb9-HXdls?Q!x?1BuX@OFn$$za zNn#K6P;cEjj~)*RtJro|w*^tKpfip>6vW^ctl46NYRCA~bx8OF8)3XR^RU3H->|2t z+r)V|X5A|)T$-MlMh1iK92`3C<}R%y!M7n2;zB~(Bh$uCT_0$qT`^RjarBoaGe#j( z--ORBZ1>aHF^cc>=M7K^3(9dEGvTie{LYySUTGHm^1pV>$2`;%&*T2XLEit?FumL| zJUlJirFtBp*SAT`w^^`V_?UQ_jA&fYOq+@!G1R{vr1=cbYz6k|wG1uJ@GUs6=ecrz z_@bw01U%2r*)k%3KVxRCxh{I{i}J%PZ=C6<=vw)qCX6cnPH!XX_tH;i1h>4K<2yiU z|MWr5JTrgQX$NLu{z)6UioF+fLUpFk5RHqJo#^yylB~`dvO1>6>YNp8L);M^Mmg4` zPZwApDLv}Ve{QsKKbfC?|Nq+0tQ}y~10T_A`)5yd?l{JFm9sS&c zEfNj;=V({+&hyT2U)m66l~g^LaoVTb5IWDNn%}lHW8>C_aN8epQs>*cAI7~|vU+%f z{WrGSGq0oap!QffG0u(M9htRQyv1uJj9fkKT6m4)R+5uP&VTO7S6&7i4#=*R@=It60a0 z!u_3siAMV+sQDjxB0h{2p?B_t28s>oO#Y%{lprC`B%vvh5XgSzxJsJxg@hc)7IFb; z;%4&rOSX`60%SNC9it>J5_@`%p>Dy6f@Nd>u8^6p^N+vJ6ti}Wv&kC2I!3?yq+{%U zO2m$fB^K+PW-N1e>alO+c**((ciT5kAS?BuZ+ywNydAxX_3uC>mgt3ku zFqpCT6X%KgH=gYgc2bB$XL5^L765_luI=5~d-qPYGi?d#z)S z38Va~4+&#KR_a5-@RO+7-+>-3MF=I_dy&;vPctv=Oqk7;+2?)IBgh+yFB~o{KF9d? zfSAsNDR8!Uj`h0|LYP<9e^MenWhvSFuFXHV7LWRsFl*GKN9npq(KGj44XoEyra$wL zng1f>VOPSW^bqbJF2{}_A@3!jiI5POZ{Rf2l>Q`S8@7b;Ax(TnnzEKH}t4~O2>6|4!v=rS08eycEpS9KHw^X?D589$)^^VL|}(mrI% zZn9DzvPH0*b$d?aIbDa|%&W0v#?@3_F9F822uTIQps>KO2`5Jd11y{Y^{=|RTS8t0MDk8-!Z`JPd2;>cX&e2TI&irC zx$UFvBWI4TcAcZ~#C4A5OJzNc=j%f@ZVT1Zd~BdM(&1A0u?mZ`nkBDR(?PhiR$$~2z_O4n|vq?R&PEY+#k>Xm(qJ1eAjtBUC_HwTHdd0x-mqrYwwORjRd>h)~ZQuTt7rJoKZBv&q} z_bwawvwo)J@P{LK9F;E?`P{G7eP>>+bavkNJ$HPb*W`R`u2#M}x#eW5Pv(!5)&2Ot z?cOo5_F{_j5Zi=v=@ZxT8hzV&dg8|;hvF`+YrXYm;=2A5zJ(n0d68w=sB>{q?$^s} z2UD({kzADha%_R(_B(}no7v~{iYje5laTarbp58h z@45rT8%po5VoSpR%$popD;9Z>c<`>VtF2Y08wg9fv7h{im({h`8ux zXWfKhc@;FQXLH~7@-Z&Iu5u`CGGnLO1YO-hshy9fcdpm9-1q!w5&M-=RR7v<;q!5s z(}AN@c=@MaS7vj22=@==ka0&FBV>CLnj8tCv-aSAXVMfB3Qd@V#$0}pG|`qcC6g^= zF5C*v2$}KsW`xYRHUES{AFj++)v%UBDtX0Ub(*zKr8ksqpCoj&#f}SCqTV#65~RwOnBT!D=}(L~jMoR&-u(Wc|df&vVNa zKC!%YYwwyh%WpI0mXpROdd1&PFlXX#%}1Wm%}ZX-5W7<-JIOODdr7$= zt-;9Z&P%l`p2t3vyk;+}Ti-1G+Iq9B<#O4bGOn%lf)bzhQ@(}o(y1`r=lyDE^rr)7 zbt)I;d6)7p{S+3_Ry1MhXEEQ;hhHR@&t2zTJgxL|^w%w~XG*pf%Ikhs_x&1`*Op4z zQf}1Vw649;*0%Mf`p=s7l+VZN+w7z?gaUt?!q0BT(5S+B#`b36QLjYKs2+?tjQRUM zPbr8h&11~pH{9`BRIa_{^{9>s{O;sBENzY|7w>jagEce;=<<}b{3Zk zY*4+ge`?RI@M9nCtrCk$B);5;VDxF5c1U1|M5vy|7w zBaGRJJ@Pno{aB?T@NgkoWODg6}pHSlH!j^Ua$?7LgK7xI$ex0i|&^GdUE-OiL;yUcQim0Nye!s56{#<<05P!s|2cdgv@xIC|rjff(@)h4oeAam})>@*8H|mg# zl%3X;$jph(Q+D0SanR+remGY2dcf(44w@6JGsjzA-+A+rgU-mphjLS|@3_3$VcN99 z%t;%r?@F$9pbXS_I7Yxd;MAx}4S9`B1rzt3*N;|ei`{-GJIQ^=MVm@3_1l?>Yu$Gx zzN*v}^m-^Q(HwAAyHazqSLTGJ%{vp4Ds?1V9?I)B@3`tyIgQeiIeBaIE*iJYV4jv; z)c>|g=l*A}XI9((bYS_e>3{uFTeYAsuYNV<|DMV7p6vTM$WCgzc#hCcl|AKq>|{=f z=Za^jgftr4jSY{?q5XIuazyf#ms#W&2PP7{nY@H)~D1OhIOLnpst#d~_ zj}Q60+D`gNVUFmn_`M%%?c@^+b0xmS?`s?NT56X@&X5qdJ(Wja%beB79sbBIq}k^6 z*ofOX!>+jP{qX9wT*B?#(RFV7zH7f8v(GDMXmrz_nxxmVSG{samNtca^?5BF(~={W z(zLh!$7^|7ORnTk;r*}vFPc2>v}D_GI(2|@FX&UR^H<@sxqqM8|n6b zJXy8QK5S*@zxfL61X7p#*d+=v4z6)@9UHfA`g`8s6nixV^F{r)cAXGtN9tKeC+yL^ ze!Oxb;|eU-mdOdfUxEE;mMdlYX+z3b^7!!+9qV;bL@HJanWeF|*ZOh1{@KunE3op7tX<-)e{_k*4M>;R^Gw~nU4ZqkXYIwh?G-PPmHN;tE^c7m zUN0A58$0gpsi$3hZlkzI<3P$~nuAN>w(zce;WauXpt(Ix)c{+>%3Sm!0vvU z|9%pl_k=udlpe)cuPa|py=ymP?EF~Dkx!$_Bt=*^<_|D;p>RWFNDq_aE}* z4GEcxgyv5|VCKtd(v%4#;0~`=kECTedW%4@h{UJj`h2ik6U!z_CQ;LZaUfdT$`Q6yhi`Zm$+{iiYB>8QDmz16~#svZ;JpH;I4;f1-BT7+xJEm z-zqA+_3=jMbl7_t2j6E4cC`lRj1oj1e&-Sox19D()y@T(=_e`fmP_7<)o|90wP zn*Pj1PeP*yIm!%;%A8>tA9`$5m5kV(%$ZA@LSr~ZVuf}n%rM<;dQ|v8tjKAFnG3T_ zqxmdig%6&evEYK~G2CZ1;%Tht&GR#tyf=**pc*@5ugeVc!;g=O-iRG`*=6S9mye?b zJYt6)dpE=C?&D(;pJK(5-_5lBkIi1(9v`KMdjT2usQowI4?+1s`T3_av<%;b%6`(P z**-e6J3ctSeQD49=xAWUKfbh|f6w%fU)oD(C^;?hQm|-Y{e1S)@gHGa7sc-xPKY|) zcFH@Ra;SaA@-^Ahx;p+)XUh}!@{a4?K1LsGiuG1V@1ND^zMB+coJNc1j#q6te^*Gp z<8jK^lb!34rg7YyF}$+Lav)7=-kZ0k!i(r9J|?>y3Cij!Kq$uDBaA}ao-ZYpgdeb*npNHhG- zTF99@@mC>t4J3tJ2EqKZkej=@tnK+b`dGGI)omruBP;cxl5hR?SDEsq^Z1;iQIp{D z?%9x({l^jy)T!8~Fn4Q$iNCGFV@=&*UV-Pno~frSyc@0D@c2I2ZMdM%E4Iz_!!li) z&c|t@WIg8d-H(o<)>ysM{hWI!GfBsWKI3cE9zI_cdgt;6iZa=|e~~HV22Dyb39XQX zz*Lw04{p@=IcwWHb!l1jQ@CdH9Gtkhd$m^OjLAu)^upi+9K=v=G10MA4-|b z5Kc}`149-3CPPy}-(b91_)d>ld9LA^vv^K8%JDDE)Z5@Dq-Ww5dPJMthrQcuPsM@b zGN;GQ9iC+t(qwUb?7?%!8Vk-Ds$DSOe)#Fhsh;PIblw;E?NmLfJa>iRl*0wv4&6AZ zwq}LVw3h|`As#2EEO~3Fez#zI^rw^RTizN`zD@D-A7rmIQ#?y)=ag-sd+b#m#IrRr zruYXL+Y9{T5+Lh+b&QLBdHpB31!dcmkAHFd(crai!Nsr2Cw=vz&y;A4?6|LsHxPGr z`UlP$t6~~xsCshfubVu>{Q_jhDjV>~C}i@CjjW25l0C0Kx9gY&_dql6^t}JjV3J$- zuB56{9X+n0>0y-vr$@axPn|v9G|CnCoU`_`^2u-KN`7M=spP3TE8+fmr|xcI`;k%q z`+aQXf{bfFKQehu+;$fnEuUD^5=^`E=PQ_!Ki_nJ5tEWKR5NTt(0{eX(v<$=^vCd- z2b>f+r6D`cK*4aR$;`jFm9q241LU^J->&604_(y~W!rMFn=86s;$p~e1tb|aPPT>* zJz6DlRx@?sqed}b_h^2bD&dGb_ZM7Qe~fVxd%~U6C3Wj#25MIg+2?)VJQ`naHyssA zsv36HJ9TksW3-@8)zFyM`&KE9l4ZPsql6kLV}(NXXUXxgAKZoqP{YFZNNqD*p zr`Vk|rz@@pSJ~7IP`{JDrp`5D^Q)SEg5GHk(G3TdYuEIj?47=O3dS}kr$~S-i z43X}yS<4+AZ*h7Ae%dzrJ$pw_~EcvXOO`%AxDq7}>zMs}sLp2tQh(x?Ce$GrA${104k-2Y#^d8f40&KW4KG~adi=_%d8 zEA*vD6a<`6J*BC*!eGLpf}OuL>59jxX*zEWCT}X(mGbEng-iUQ)PN}gCk8oaNQ-B( z{JNuoi=xu`1CMSlx>w6TZFCdX-G9pL5KOTE zhq6W9s+MIx2fD^iKM}TRqISjVpA1u0FqfGb<&>qJSKtu6 zYhaZ3e8bb_b!|(Gwpe}ry5#GX`uZ#16KOZE_sZ64Lr_kyoD^?plZkF~xFr_SeeX94hNfDuPYWt|mR!Mwb zwfxDx4+}@X@_O;WN21WvctGK-8sFOb=o9n#`J=eTtKAdxc5bE)6|Z-VcjBxr8&(!_ z^YHf3n=pXb1^A7lAk5S_bO8ioL{HH3Xz^w9qS*tf|)W`_mh;w`Y zz|%K5&-ccbs)IN4_I%9y{%uZ7`@CtTU!v128k_`v#2aTnzc_bW`}7gHOScGDjV_&U zUpS5XhUnOhA~)rKUh$1@@m3W`4%y~n=)PmPz(9@DDtBLreir|h)UtAH)#~yE*8ZQC z)Gu2h)hd_Ml+mt1TQvVn*_C%S&8O#?Ry@yXy>of|)p{yRtdTJ5}%zF$(`Z%v&ex#NOuD7EnGyZp7)3b!lft+p|f^ej9x=LDGyAGe{HDtS>Yd8ln|SsQIivO$*c<{Bw; z*EOy8`GwDwG-OVFb~IqG{KF=}HAlHV7MN72u08d7>e}(C4I}#Vc+)!T z{VVzj1&bevPx(HxzwdFcnz)s32Y-#=*=p8*k?gi94-S;l8!t4zp6yYx>u#BZkMrt* z7v3fN51grWZ-bi~)%aBZD^|Y7XUDJeODl4!_@v7@=+ZOCuiDlF7KH|>Yo5%ee=(!R z&t9tN`uK9d5=#Z{;ddTvy(({H=lH&ke*XE5) zJR>6xug?kcQyqD5C08TQL#y?w7o@rUJ)GxmC^^PC->!M(g(H_a-HawXm@06J-!NL| z@^!+FRTqYBUu5X1v_UbvY@M^n?RB0e`}Yps{-x+xrQ(}#sUwa`3GgI}`U z$7FMc`58`|YJWq$my-;>T;0c2T0PY5O2dmh+bypve7xRxr?<^M4nsK5`eoXbukOdW06KCyn z8yvWQNpQKkgM$fH&HpIV=telb|)NoF$Bx802?@a*_ zUhZ4m`Oela#w@Vq{Nf+&=6GF=K0Ed5ZJt~q4e2%Iwa*2v-U(QD{^8W^>!KH4R(r-F z9=iC^Wz)@EOB1(?T>dimetdY$ik}g@cC{{x*6tg$!)mPPgB4mJIb5B)n`OdHm}=SLNoIJ=y^OxTd8=(vZ5cM=qj4lsSDakV~bvfmMR1%nSR9J8vYj9=oZ;CJF=>2}U~ zx;~Rm^4t!b+i%lIzSjkH>lc3bd^ulO>u|)Exc(CLL3@(ag5E!~d{DAnHJ)yL(;}+c ze&VQMSK78-^yV{}ocN44Z|}A(MsCMftW~dlEIegcg7}VoFBNOEOJ#-buT&pSJ0YPh zygDF5>+tb0>i%ADsr-XdR&6@}u$ZrCSL?juJQ{cT9A3jCDwX%lFPN{txLSL^B+rFn zn-PL49{hQEs&e;N8?E3sa#fL$4gdJLG=^`?Nb7wQR-N`gRCp)#ZbHHIxBh1`r~e%E zP`lXFdCNGiw~FJeR-2Br6*4nZ{x)DO?UmY?ZI8Awyo}wpyCJr=C8%K;;!!LXSGUZm))&_ z4~IT!zS{V%{muF}l*=)CYYzV(=H3FViY@y4SCMX%ZX`sdQMyYMq(vHORHVD4ySoJh z1f-=KBm|_pyStnJMi2L1z4?3p&l~4?K63AwIp?fBvu5qtv-bWjcaCHml7*wHe#Gsp znx{<9w@tEdylG#u@pXI(`qCA6add*jDU-u=s#F;2tk?bMbV)GzSoYp4R|R}gm(#@0WHCE3WO z&uJbZk+sLr^gT#*AuEXPk+!1lot;x&M9lWM7U8K_8To%rkeU}ToOcLXr&FB6kiJuK{+HIZ~f6O9vo<8VcGnpp$3^AXkPKa~M$keA& zs7NC{TSY2vYGEC;OOm_DWUJ;cBsbq9-VXLi2>1S0n|5bUWKj349 zNp8RDj-;ZFn^woshR-mGpe^n+?J;b*7?BFO)eBW45_#Pp-53v8u7j`5Z?&0G#}%*2 zan~ncjGIW!yB|>B;40L#VJh?fE!HdLG7G$FViY9{vHC5Jm}jmF9XCeG@;J<`3)EW; zvwKJB5krwiHdJ{8>h^-~YtX^>`I$a#y+Qs0-rnS_(uQfX(Y<#&D+ZSPI`$A!v~}e4 z#J4%W?Y-rV27T{~xMOS#v!2ScG!bZeH4+uJfCu1Z*UadfwL6q8{LtLExXOs3(q`~l|8;e%f%L^Rs87W zJk(sKQ=5w~_di+YQoWfCYW=dKl0UDzHHiON5CwV4I(9L<4S$f3)%Q_Q)WwF}*@HsMp+5hLSO^D+xvN>NzDtv3X}lHE2e7A=z?*7>VF@ z!}eA{&YAWqe&)hiUw_7uDrS6fcD&(7QSMJJ1io9|!yM%gY$Y`}xifr~T~#lN8?%~4 zpYt5ZD-EoreaSCIdn<>w4S3klID6gS+Fis%TqSIyv6f64VA9V zmaMw#)=XbLiYEF~(E`{bfzeYd_I;1wD($zc=6)yj^0@=M6Ebg`h-MmX$x%)w>*u*d z@r&?IixOce!}8F1HS|9>bjkT#2p%dkz_> zMt3rF^3a`egZM66U(PgkL-}>KS+*^P(dou!U1mS)sECT-sT$+f+H10wOtMhRa34|1 zw^|QYtZ4z~QJrZG%Hwc8ud)LQY>{m2*g z9cC$uj-d^;12ab#w_^)=9T*v<6e?kkyx=VBb!4g8o9xYRZlC;`sBg^+XNkZ=qc@{@nhltI!v)x81(%Z%;q_D#yF_Un@aDp?pY=IMHS1z=z9LrP+d+w;Ez4(~ zWh6Uh-hH?I)aFCoKIR-5+9%?!5j)#R3r{o&he z?c=^DChX0|H_Zi#;7K;9pXH5voA!sVU@$S?<$->ta!Zug`l+KXy*5)uv5Y@)RQr1y zjv_am7}o9R-Z#ngtL5QuLkX!ro{z7MoFbQ_;B8o6yf}F72rC^I<}+yey!b+8t+FXW z`yBIpXXUIVo{{?8(n=DiDe{^{!oxJS1WnlJL2^TnN{`f(48(GprqPg-K?T&FviMqV zj$!j#YP5!3xVfyycW5|`-cM`Es;`>1llu2iqASX*n0C+SfP&s3}e#HY-afy zP}a4`nw=Ossw_F2E7FWyA~5#jbIJN1t#Yl1kOydPq$e2{HH|YlGHh^Pw?-Y?LtYxR z?$7M+*I1BB#v)N)7$VnZ^o(23Y{R_1%E^tYTA~4F^bTK?@92e9?VcyEoE|Hm4;ko? zB@UAaH7;zjKfcHZUZz;(W|4{K~pWI6j7 zda5{|CXmj+k0$gEi3G;^<}3;9HhCHo-CBJhixdxr>4p&Zy9xu`oXk<8bd+`xhrlE) ztD#XL)KGNtLsG+gpKb3J6CQP+_46fJhr_zQroeBfvZ=>S9iXw+16M$*sj)rCNRqchZ7cB}=HV*!t>A@zYV7r(FOx za4)-o8Ea0z$A2$+j$WftY*ugGqtPAaWo$V%^~1Sdea{*)_S`Q{b_r6RI6hn%3{Ewj z{>o}eBz|9S%+ZA-hlZLo=eh2AiVYUV+JBZab|CfrBsg^%Om=5o!+$$ywT`<%{w|$; z^IBi6d0MWsbIC2X-Ud|JGzl`1?JPEnUDDhDEBv$frE4 z&=H&E(9gzi@pXa@8rwtn-dd8hv&DD{2jq=Nw49i}^uV|mNHIxpyKn6T-Zn}~R+mNf z;;{!6!%yI!nb>0Pud-=*zQaij6ylut6og5KsWR>d+`hKr`iSH zB1Oe(d?qXUDOFBrY8e9{1@H0*Ov|FVj-;O6_ zw`>OW%#E1$1N8Ex2xC{q4kI;O*SbE z3^%SJZXZ6Va%kJNK@-|-ucZO`5MzfhR>lXeXBq}6YCa^}-pUCr2CNfBYZ#m!_IFmH z9Iv$(mbWBOPbvGD)Jfx-pg8xZV?GSE{YLfN#5&0E(^y&Xpy&41jpTeB3-3tpb=p-F z*OT_)LBi#nhCX#mv~q>jfH5b-xDoqR6s@Tbf~zRlMgBONmT+Y&#`xv+_4T$A>XwVu zg7dy(PTS2aM5`zPJqA4LmWNh@l1A{Q0ylfC2rS&33(eGW@5jEruioH4Nh!y2(ZO0b zaqan(I29}Q&rcu!CC7bP%lb0M%?wHR1^kk^EQ6#6u_0+d#a}X)1CX@gReBKhm&~Ot zBy(wJrWLzbsahlSOXhOrZ_NFN$!*_L+`!~=h-p{J(;rV+fjB9oDR>Z5)PKob21A;t z25HLGepjD=&HXVNd2PAMGy*}|085QGs2dZS!>je*Gndw^|CYJz9QpUm<=@L}dqFaz zSDD7Y%v^qk?DQWpmlK3Py9(m3nM-|;gT4H*^B=1NdiNaBZr*5|`U=PQq=uF4gdd(y z5f27Gi+~2c;O8veWqN{GGVXh#4n7skd8yO2YnL}m!5>@Vld$Om&+liHj&}&54&$AW z$U)@i|Jx{kq3z(6hzf4gUQ{p-7o5Y zC{$3!Au$fsJuk|OBU~l-v0wdNkV(rl_P0!y@sBjt*C`;#)M);D{z~oio6LCe&$EudXI=xAnj_58 zV7ZQ>FQrc=fOOS&xhlcCF1U4)?hLW?K&Hxw%#++(Ps8(SzO`Gr*d3?a^9%{lm$F|9 z-{q(oUnEh5~ZTOxCMUNiOGL z#Z&M=QwzTImJD6^u1XU?0)%JO`Sk>!Dt1Lb`kca~a_9^)L@f4)?*G}lI&L~#t|Slx zPWBQkg%KqaB`aYi02$Vh!DboP55?Dv!M!Q(cb=NZ}lV#xzWU`I!w5AXMc{EPySEnB$CP^aCb+a#mgV!W8de6lT}I`{BW z&ux}wd|vG|=3-NAd`jheP?+Na6XgzmWbgkN7k*5XyE==Sm+ElLY0!xfd7wI++Q)TX zB;T)(+sU}~FB%!*;ZMIWOJJRjs*_C(stGv#(jle`!xSY1&Ra;`n|b<(OVPYbF}LvC zQ0)i0mwI`0r!9u3?ZlAF=mP4fY;yVh(a)js0_T^U-c_jF1{ zRtX0yRS5wLSyIrL5yMy|leK|L2C6WLc7;Aw-j!%&6*E-A|}bv8jTC&WhFL!@>dte*`gCL~IuRn3DPMx;`=^miDR($}E_- z>~tHWS>`x-?76L&m)JFF# zX1pSX@8@ES!}b&5mEmpL`Ygz!N4%kiSviiV(j(Z^&&uzRN+nQ#_@^8tfidI!g(qxH)u#9Ki3aMgqHL51%DM7|Kqq?#kyMrh< zJXVP}T;D&6JRj7188wXTyq92Fi8V4+X^KBH^LkG*Y4L6o={Ule53E4=TkUst&1djg zme9GQ{N|ck5)^N$OG@@Unrsh=q8TWcBv-Bk4;9uNs^~xz3HHd*z#x=y`=Gh zAyLsoC24son?H;qVPK|pr)`Z|t(se~eYg!5lH-uI_GL$zwXDezs$*yI zQ*c_~SLRqPxK|Z9N#yCZrq)b|6GKx|Wh=wcH{I z^-i`|^EK^llqpKFxlg`R@5>DZd)~9%rtKNS4*!&K?a96RzMw?}G_w(#&tfNtxo$+< zya%kfCL3Mn>k^-wd7i$+d#Qx4KI`3EaBx&gqHXj-y449OL^+mvwpohaU|XxYpBR>hIWT;xeP0`^7(IJ5(c|elu4Ss@=I>fm zOvDgpJYhx=2#mRTfM-cJ7=;<5Yg1f*#4M2hs7LCBdQRmFet877FYe2`9UrC^rbbh! zao`=E1uJ(!+t=KmFy7bK<&YJTLflctg$Y+!>7Pf`nv`UtXSQ)hGGtLZCLU%$3R0uZ z-ReLVh;iQJUn9nd9h#h1>RNMmlA-R&*Z5W=$U-nvm<+wFL3eIdq>ELtg?Q4keQS3t zrdoFFt&{0&C2B#t9h9!MJkhfzgvpkYcze>y8@JU)E0$6sq0@w2P`V{`>IE4L-?bf! zuzuTtpO+z|Y0-*y949V$SZoXmV&x(zPTb*zYo<|VC28DaU)N@DBx2eyfw3v%HAim zZ)QxRIO6K6qQ@5ldkjd@JVA^%Xs0B4HJpWOW&&)6!gkTo9J9oa?!CE*wD=~6mYC2f z#OH+LwWcl!pKG7{de|-5EbQ_SD03S79qP_bEu+8k8QK`dksV-jR4i`p)O>>=3Y zl0S}yRv&3%+=J!(HXz_6mg@Q%>z-Kq%5{J2lpoaKKVC0W zFW+4odF6Dnn(7sP1Xcy=Fd@BdcdwRMtWqPgMRjZ97&5eb?8J@ElRJoXJxfN73!80( zR5{2kc~|4ss43oZb!|6PfZG|0`)6|}Bk6H;Z<(xIE3)tf8)1q!7K6fiGJAY+(+4T3 zTW`_EQkM=>s$m8{`3=w5D=*N%GEVv_k|1v~P(8ES#oiRTxa<)V~Ydb9juyj{ki z#BZ_+2S^=gp2ntKTsRv}18NU#D?bdsZ~pqS+rg1yHtQ)TaT|^6Ehf6iySj{1J*_Yz zuhVJKI$M%uBJMyPU=?LR#XaO@bnGiED1cTBX-mb`E8`ViN!_>8Bc`XKvuDDHhkkuJ zeG6eheQr_EGh&NbS$g<2)BT6YOWR&5%Fnen)dDwW#~vbeNqH~GXNSC-$BfurOh)N6 z&h0LSU-M`uj#|O^;NUrN?3bfwdb6k_7;8<~-I&&qfkBF-7Ox2logvo8+4Aspcf8v* z%#gZgJlSHK$V~bnxvg$~+FS8o4um!h%A4yCvoPOd+#M*$&&0Cm%VD&a&2&CL6YZwR z6h|8{uXv&O312Y`wn=<{mrt@XWQ`LWcQ}V@)b_NEzWJN}zHGNyO~X?xYg1*uz_vCV zvjJ7uH{RoW`m28L=234kYNX}A|M0fty&NY3F{+)>5D8kZiT2W<1YWJf@%`y@x}=wF zNs^Ayu?R7wPIT?x9Irv=IXY2}nADQc-xulO!RfBhJczT(f=BcpaJ44#ibV4%FRe50+KifvH_=M^Ip?fZcYhBz_@;Qu{O~>ob(_S+0spVpqx=v`~kWu$Am! zlCb9uZyr!!;#tN=#(6fo=|d0I4SWkjOTT+);8ljqy7<+y_|?9%^>Q9=Pm+{+>@)f2 z?_=HxxrC+C)z3&Sz1H0sH6Unfchs3Mwj&rsb#Ll}^LOGYbneGfwM@7_!LhhdJ}HN9 z=vJdl@iF4Ih>ENzG%@VN^Dtrow9JIkwqsAEA-Z_tk4xkN$YH+r#TIm(GH^R;IrSaY zJc?QR!AO2zza!8(7*oqSn&GSWMu_WP}MWJ3xpOp(Huvi>_>L zu$cU+gvw-~?@`=)l6+rmgimRvmk+@W@2;$^!MSAy-fj1UEv%^L0*C6kuv8MO)o(Y(_2?!F+roAS-s`O*l+lmu?(}pm5@>g}qC~E{BmK zhducyJ)R=!Ue0iGPCVYtN5K+J*JSvoN+W5y=xv-Uwcs}7i8PnfvAS>~FX;7$3LKGO zsP!y_cYNzy4w3!4GwapY&(xz$9Bzi!!(_%}`_&l0r!*mIYgv^=7fkx0n89;xWVv=o zgnfBRX4kJ@Kq)+%PNPJ*9MWZ|zl#6)OH}}c+ZqW0RicBIlaZph!#crK$#_Gc0NI5O z$;7st&v*=Oq$E7cZ9ys>l>EZLPR;T~{5NopG%8(;T{){z!o#0ZOYc{bkdg*{b;*vM z6l3n>&&eW+L))pTBoDHF=6_?XH1Cah5p<=cbSQJU&xzsOq%$n^u|Zm`{reZg*s!aqucOJ)@ElGq_LKqOQ^(CHC#fa4qrHrUw*OgLQsk5sP<{WRAG@t#}czz zm&nzPq_wdwuc(?rH;Xm$n391t8+{&CgDSXgtGjxtgJe2UL81ACr_6A}p#1$&eF}-0 zu>I0?_H4FZ_ia-4_A{|CU-b4u{Q1NUF{Adk4^u<4o@T#D7qf-dUaT(50W*z{ zRY?aK6!y~&GqFXFCOQrJ#EK1TZ5i8o ziglBLno%fKCI$fz^hmq@{X@@apxTJyp19hNB?qkYwwG7t4s=C0rEmi5$XL}q0#De z=Qat`PVL~-B!Ycb%Qm$mx6{Uzs8yw92coliE!ou<&d-#%mLnAXP49~O_v`NHVoO?z zboC_;kZ<5FSk0UdhvOs_<1e5q>A@n?wBI>v+o+vhEQuT2y5~C5yk)rLb)<8rg^SHu zl>@z5hQy1zb@9NsD zTwrjOZj(4l5)fw88nMT?`r9q`D#0x_Pjbu**mMQ4cXxf-TYTKkz1~x|__&@XH6!N9 zHzR6S?>fRAH|mfWZ@76sbH1V00xN&bhqACZoj$@YHuu>hMP&J>Q@jW)d6c*A26c=- zf2D+B-M%+fUaAp0qTySv7;5}B0VjGDS%|J>M*$kWvNO?7dyh4CrW#YY2tAv89-o0{ zA%*sNMADt1h8~T<&VW~?&)Zyyb2iSjo&{Lz30t2?)cGM_=h?vEe)9mw2fj(Q>Fkvl zT~|GrR5U|*j4!=96U;X%LCB&uMp<##oGu@>IemCyO=Z5T_1u352g(NBHn{xNV$;V2 zKCGz4hJ`#!Ii=138E=s^yiPyTH;QhzLRpLbYZqTWp#msqVdW0r51ubX`6;Ulw|z$5<_idZ@tlZhDV&VUhm z-dn0)sx(!ID+gz`cU>`Uq!rT(cb3t2$M!zPA8^&9mF(7--8H+p8g=KZDbV2Xg7qgl zJCy#iucJK)7dy9*=it#15mO~T@30N`W><8SYP%f97y0%XXgFo@UJ#90?agNNkl08rktXZtyJDZ-%Nk21#khgg!X1~uHS;c9 zz9w&kj)-v$o7*v>#aVHMtXm@QF8y5lY(xVQvTbWK_bMG?)M8S*M)lFYz^I7k?tH?W z?){WO*y-~y78XzF@WNvW;lZ@E)%Zz!pR?h7UV%Wx1eQ-+RSh{_st=jX-%JX7L=(ge z&sT|_IcONaHNu{V)0!C&9?@nolF}(wxs2I@0vtM zMMf`(y3tkllvk@2+-=8>KBQNY&tE9?4P6syyP(7#L*nSnvR)ygDOhY5Kp`f~?}{sK z6q9G`QpoQqegUUjY5Rcc&?gD2<#6Z%Az9PD>0Uyt(1gR?n8AT}<8z8{UP|%~c;_O2 zVV+s(e915v5qP6p=|Y9fz_q3jyY2cxzrj@h`dd7?-PNeNtWV5~MP1l1qz;RUujim_ zBT^KnwpdzCNX-n&bJwe27l+YM4`$iTvie27GCP_b=GPEjFq)MvjH|*}nyu&Y)pHuI zzE1!2B>wQdWdeaEijUC7^ni^f7T4fc=@<#CjB!!E*v;F?pZu_c4$>Tl?Y3&;yHzy~ zM448Z3~A>2(75JJjWJtHc2}&2sOgd-cGZU**Q!seil%r=ic47McwiHF`nsOZ4jaLE zn~@DrauLv_b1|dT6O~zd5%?X2^PJgIenuFpqM_AvJXc~cd5*ImmI)4g^b3U_hv(P1e72-AVYp6Qs_w>ae)9W-t3Yf!+QDgPdfX-TAUt3P-f)WTDamPH z)k-1Z)VLGA6x&JBu5#dQMh~j3&Y;Q3v@4^ZQnYad-%@3FZNyu%RDyHQ1wK{ zSp$&^dsu|KQF1!s9Kn>R-S|^iVq!!(7Ap1XL>`@030CQ9)9xsvms0u~%w47(;jwsU zKHLwKUOmU;?`Wf9w_6tM7}b**d&Vl2RM4AXv}C^I?bG|3JZa)9hu>SRR_Q1T8>5b# z@_XG6;Abxpe0<&I9PJ2+v|{B61POp&X7IFd=#wD!SA$@&c*xPUwN+3~8c zRsvsZVAFJItJme`_5c2U^)_U`s|
    XPW^t$pqu_O1Z@2=y99tUN_;YTB9~+c$aC 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

    R2G+tlu!i-p0c^k) z?7$uzz!99l8C<{>++ZWPg9mtm7kGmYYyw~K1AhpB&9DUmAqcj@HrNh3U?=Q?-LMDt zLNJ8DKG+YTZ~(#}93tQ#M8Y9B40cm0LpaDS5t2Z)dxh|tD}5GD_1{755;l1zmBh6s(k zK8q+~Hc^zRA+HimwPJc^uG)P*wVjj+pYWLWKl+nQIGc1u8DU`vZ@u?rO(W36G=1NOg;vF2+di1l=Of3F($(#>?h@syacxY z*6VZOswjOeJ!`qd+fz={Pgs=K1~;%7Pq$b7djEcvpxcng#3UAjfV)~>n@Ro zh@y;7d=0sn2#vgcY@%ech^<6X;--YG;F`fS^Mr*e-}|gKQk^lTqx5U|lRC4Jbj2eU za-Gp49`UbFtQs97>I`WX!(U(L^ZTialZdMM+Zt0%Z1e{;CWCarCKmGke*3;83i&M> zVjvdcARdlD0vv@zI0nZd36kLiq(Ca9K{}j-49J8m$c7xqg*-R~`EVM}z*#7Ob5ICH zPz>kc0$hYka2c+^RVaaLPzq&G4%eXqZa^he!A+=!TTlbFPzUwU0FBTD&Cmj^a2wj- z4%~%%a39*?0X&2bcm$8(2|R^o&-yo6Wq8s0z;yoFwP2Yt{F?_mH2;RAex zPcQ_-Fan=p6vkj2zQ6=faN&i9=|BloKn*j1255l}=wT)>03*x-CYTL#fEnfj3$Owk z%!B#B4jixmIDreefd_bj5BNa<1VIRdVIhcsD2Tx#5C;j61SwbyOF$ZAU@6GLGLQp# zPyj_(4t-N9_y6F1$qCX$&EFj-|BzYVH8+bf$-Y$%5+lv3)~9lH(M~^By}vH=SzA#$ zJxJ}`wR65-Z=aj^qeSU_;$waFOpgWZ0t_fQU3`RPka)uWjI z*Dz*%-4P0V)vxRORg8&jL_Vy^;r=GGej-A)BSLc{LioB%oFoxNDJDX`L4-zLUrrQ} zjVQ{&DIr@3?Bk}yWj+_~u9G3n3ASlPh>>45S2;Ok@_zpIyOMO>IF{dJ)-!*cS%2N* z^J&Uc_S3eQk918tmOsd>Ur3j|VT zg8{4pLs$()U<@W;3T9vq7GMchum;w`IP1gARHp#AVk6; zI1Et`4KWZ4aS#tjAOVg-A{>L`kOawa0#YCq(jXm9LIz|)7Gy&XGK@lRqp>mW*wfgD{`v( zMUT%)`?krY8icFr1_JVeUKWzPz~W>%3x z*&i~iJ3qxcQfB4adDk}ng<1L8Mw=fp>nS1|kq>KfxWCD)X(|nqA!o;yOopbluWvGh z$!8EhMs&Uwg?9hfkkem%4UN41bk?@XA{M0J`Xq$jH-E_wA>Tg5eJSaMnX1n&I{{K= zy|G0>*7Z*^Ydz`HH&}k1Sqm!uIJ5q`zsHF5p&u;dr|hShbsMqKA7oZq(g%mW+uv{d zdtRZozJ@o@18<=h-a#Mq!+RKjLHGb4;S&tOFpR)w7=?i|cHn>ozzJNy4LraLe83L^AP7Pr3=2U7 zL_rJ|fjCHjBuK$xSOU@@14}^`mVq3|g90eRa!`U5pbRRY3TmJZD?tM^K?}4&2XsLX z^uYjDfg!90BQORNFahFZh8!1i)t40)Y?&TVWe)haIpJc7gGf%J^UR_e_2i?z>t|PAtF3gRhCx zwJpSH+2wyY!(^IrhPjS7y(=Y7;|@$YU2841NjZ!>s2hD!!am)+Jnpe(?e}MxMMUl( zAJpVt^(z%MAD(!7)>10g!AzUbCt-8oag}Lxv`03MSrO)l7a5dFmy*<2H_9^2O$y;!C{DkXo!JWh=X`I0ts*w65$ve zha^ab6OaO_kOt{+5;7nYvLG9BAQ$rB6y(EcI0I*)0M0=n6hSeZhYN5KF2QBE0#~5~ zu0bi3K{;H93b+B4Pz5)k8g4-i)IuH9LjyEI6Es5$w8Cv@gFA2+?!kR%hX?QwI^YpJ zh9~e8ollxK8zGHLE zxwwRUe=DseqMhpm$^!+LUFf=JT0ZgV{q}X3Ve9MqeicFYsp|cUAu@IdwJ5sBDd|t9DK1|0 zPpS3kf+c^PT7TW&(>>)m`)O*Ov+!#$e~?<=k-nY)3;8wpZE6)qb(H`~kb=dq1f)R* zmVzuS138cf1yF?Lpad&G8B{Tg8{4pLs$()U<@W;3T9vq z7GMchum;w`IP1gARHp#AVk6;I1Et`4KWZ4aS#tjAOVg- zA{>L`kOawa0#YCq(jXm9LIz|)7Gy&Xcqarz$Alz)pEt{h_Sk z!%vj!7mWSTxw0WZfpotzirJ4Q_p`9Ow%oBvrgXA6__0ND=a*4kfpRbZ3+-X0X61v7 zMV8jzrPkv_IwBv|CWk;grVLROMIz)GL}=uY$VDU{%vnBsLwf?%pM@{_4 z+Va!X>OpMu2dQ<0^erz~$gja~JACe=y0*gucnBTv2p+=|cnZ&;6T09zynt?a39sNa zyn!Bg3%&3T`k)`)!vGAz2lxn|Ugb5CUOX2qGW~Vz3Cr zK>{Q}3Kqi>kOmo83bL>amaD$ED4j$kMUf>Pt zQa@HkQHrn2w^=og;{R#D34zlbY$^6IeX`vc$ITep@?r5Yp8ZA&$f@2%uisDEQ6#n} zEx$;FS+A)r3_p6PG<4*=AWa-Y8j5<&tBL`6!!Rhj*=Qk(alT2uDu#5q}(t_R8=&(eF6<}xM%px7%cZSevB zo2B)5*kV65(*nE?pIW0rUVrE$dt2NE{_;;WmcgzK=H+|jwes(N*LL3fMYzAIGFn8) z5kzPQh!DsR`I#unbc({skWGou$m^*n{3nYzOcbSdO2{9Q*}eFh%vIwpqArrE%rmB) z5!zXQP-Q$x-yVjATxC`gkN8)W@!3FB8B#|0`}I90ZZ59=<~{~aE)>&D1MD@NoV|TL zoqSDc{@OZ-^vz{h$S?0tt4jv4(H~ToP|`P_eYd|GMDX8cT#3X^NDp=aD@Zf0I0Vn0 zfs?^?UhNkeuGW2>bmcF1}KL8T$c937@^mOdx>Kb(>Sb4=7| zdJRM+Y=53jK`p9b7j6`1&yr0gB&z9FYjngnE_*s_u7*>dQT#@;>>0ATnx1cr61KKw zPh)h`a5&Z+=e#tVTEb1!{Xz4Q&BfW2T(31;t~AGc`DfFtc&+LEx%r>x=yfx2nIV%{ z<YH#Zsj#F!>^Gq@;J2TA%w>sxozTV5v3EgZY9qkGntKb%%(*T`X;sWZzo z^=a_(M;|a?NoS6HRmm%S?!YR}PUgeIg1mfTItI)!F$bS#@CxPXtm0^mIrPDiS0M40 z0b5~AO?K?6BfxPxBx~tO1qoN(MQd;GzfgQ~1=lN`g^IWLo$)`pe8nqW zsjas|OFx`cp`3q=en0ccj3r^39-Xrj0xK6zqtn%}kBN$N6kJFxs;jxNHR_0e#zIQ= z8V%>dsCW;@g)|Cuf(LAUF}vV%A)XOYRW*9!qx>wH^Q%PFboGpnNylY!zQ|S86f;f~ zGt1<-ldHCBqw#UYwoLAiZmKIeT8;`Y&17$IQ`2ADa%@>~CRgukRc*zVL`nb51&>~< zttQPhjajnC*~?XDEIG=@;57dR`*j_yCC8Q=bmHtvEY}cTk|=86gn6^C8+@UmraeDv zV9Ft`KY768Ow!VclyCeT$%i;8>Hlp;l&JFcC&nG!3-1N+jjQpz-9yRwl!8XSeA+CZ z-GBZ0^jSH@+*ay2X{7H^#6r$a|Iql5&OS(^)w7hcgn6qiN>$FBIVD`M;#=cWS-F({ z#vKdgiq?56%dy?O{A(pbeY?IjF4L)+b}@feQoc&uUiWpoZ|iB_#%VfkQ^x%686+^f7AF(77y17R1=|56Cr%P9jDnuQ5uMlE2o64OcZfG zaeM8QkV#L7145>wpy1t(kb@>B%H+kezlBVGoWK2!B7IFI7INdGMr`p{;}c~;G(HQl z>KBdA@0y+uQ=YA#Ha$F~Z_mW?2Tjif(id!EAwT&+<#G-p*DKr77-Ar@!W=uSG$O zdA@L*Y`zm$PkXu6vU76jAB!A%;nWPt- z#z_m0&9r{boN&3q{LH501s%`XE?&N|-u}P~?xCRamE7--E>wEK-V}6Qf5ZD@awRXg z_VDj1r>W$Ve1Bl|^u0Pd{LHZ-8QXQfP8QZFU=q8(I746s`>k8m+tr1oWB27d3M^N+ zr7P(>C>k_;u;h7{Un%coZZFMPtSO?mBz%xnX!w{nDZ>v+JTd-hk{?_VFuaFnBrGKt z^N0=3WE_s)zqC`1l<>zId6ssq{%%6CFP+{G2AL*WF|Amq%9re)&Md}%^g4r`$PHS% z|GWX1Tg!2`@X$vOTY=;E>)9?8M)tn7U3m3=1NW!G!{eO12ZKZW4&2~;CNhV!OManz zji}+=8umutLn4iH8>l6H!|JS`iQT)@$mr!8@v!5WmEnSkU<$pINV&#dC1pM%ChuEq}9fIZ~MwVZ5Xl)+I5b| z7w9?cyq>yhCp`9T@__|BHizbS4nFx6r5gK`Y1X08xq9~b2KN|C!wi4-Y9_Bcb(f;tr5Xt@ztF24UCK;>w*{)LCUz&ska43)#Dlgp$&Wd!DLGmX++3O_+Tdz9b8Tz*-QqNfUf0z$imhRd{%MOI zy)tCl+8XirLz>k1t0syW(g!BntND$zTGHVy2kpeW<~LCZONZ4M*ooaf+Q{H69noHI zCpmbuX*yfsfhuu3(Fw}ZXQ`JBSN?d2>P#N6-<@8Q57FgV@%Phfwc4T-k5!+pNM@+K z3SRO3Ni}hP-QTfi+N;`DuJI|4L(as%=-6Q+vT(Y4MK>LDL}>%VfZi9!ZQmLW<)d1O z!j~eH-`4Ud$;mx0^QElH(`tP6tzlTGxThm8H?VX&ar^DM$?d+am)kjS^4z*&KhstH zC~no}UfP5newOmDrSDfMAd)RP6OzOIO~b)WguIdnZ7~r7@q|*GC5rNi2>HO2kZ%)3 z+(z8~U`ojKA%Ya7hJyz^%mD#>sylFQZSkJ^Tgc?c`P=U*(pS1;AvYYF#1?-w9Q|2D z!?6gfe$jB4c{{1w`8oZv?Jy&KnLHNqGxpQAV;8Z}AG94~q%WlZZhz~iwjFJgtI=JK z71=nO$$?zRgHw!pR6rHfKpj?s255p7XoC*uf*$CD z0jvT;SPe#C3?^U-W?&8$U

    9Ja3^n_Erqlet9d)yzy3of!!}jG?AVyoi%-EEK9xp%GS4*`tk$i2V^iyB zZ4&$BN5t|cEu!LMstQ$kvT#{V#hBGR$MX67&*>ugjXb*|QwI};@$RS%N1eFJ-FYI0 zJ`A~m3%AE?bs3oUO*7#rsSVSV;Z22PiYFll4YMn;LpX|sJ0K@Ub>_L;{k73gCrI3t zdxnFBN=|N-L4Hg)f1ER{mAG|GZBPCtF)XnHJbq2Sg#=g$Nx({zpeL0E3>PLWJ|fkx zdzhZ{#tW&q1&Uug0Kc@qQejZUN+GF~JDCqoBLiC`ko1Ll#1WU}j=p$9o3w#@E91Fv zc@Dl;%fj?he2F-1R+EVrQ3an+ES=WzvRj)%_Wqfc&7mS0?yLNs3i1?LuRhr5rEeAq zM_Hq=djvw}qYfeEvnc61x)>fLjM-xiN~WRUaS*WXDKfm|>wUN){1E*s`+l4(p7j{KvZD%-zQdWHu0JSn`x8`E#<1Q1=}m>oIPyh!+KO zb5fqNkl*DYN{h!Wciyn}aLpMmVAp!j)e|Lh%dq|#rnc6KkAGl`jzOiOr@G%J+7RJz zug`aiy5LrL-pBxRTTqpKWI2`T>) z9wftYhih&Qv}S9C9YzXZSV|LkQg4Hs)(NY+eRwJscm_CQ9L-`SvDF2;njQmWX6AhD z#qZ9Bobqp%BtKR);eK8?gutE;BNKh$9iR?W$b|Z3r-=@0hac78Z;#wdR*o-yP&wF@ zbgq_{76@F={m91+&|ZePzNQIXTMCbp>no^f0I+$X{bPhAIQ_mQN+}I%TG1j)sd(i( zX!{{jVi{%e27Xw5w)F`(HtQ!Bs+=(+I`eSvFbD{>K}_bt_a z4f${S_8_1|5(tD2bMYpFh?cgc3 zxiB<_Tvy&l${7>My`DP|z^+IAPojvEZ}s3?N{v^%!b7MN zX44MCIn6+Tv&FlUA~(u7+3nOB>~*21#eHkIlEmEp>*XlF^p27U>#ZYw5QRp8@{L9$Gb?fmn~KY z=W^gRLK)-~bpcEzM-E%LLP&)=7Nzv70nW6CSRupZ*Y_YcJ?jYED+obqfjg`^5$}dA54t7H z5Vso`f)x)dV}p%p^C)zHX2=}b{sU8yv|bO*_2R;ePOyDoUr&_iT45f^dc1LXck_r7&{X7W_=+sprVnkBn7Oo^=PR+@(UVgW2-lO4hpm*aJ?rjXrH1i(S@4I5N+B z%0#})4#c}IT9(a?Om3-0oYL{8aB_Qk!5>cirnG(iN0W3DhcXtzFq*%#RPUfTf>W7H zPRT8x38W_dRvn1u*Hijx=?H;31nUcvMsEm0xc+q+3RE0J zFu-)JiH6ML4Xr5GO5p^NJO@TaqW};%A6U+*HloG`NYCAoI0N+qg{|F>ENk+30GSs` zCCx`UO)3GE*b}9ysIg-;Oz8FJ*Qp;zQ{M}w z3?dfo)6blGTfN2;7Oj)&L$NK@NH@b4`8)&F>sChvH*vC4FM>?TL0KSR%E4On{qm=^ zqQf$L%p{RaUK6U^gm9NS(m%qXRlw1{#+w{L$p`osQ~eHKe~)gWzm585=;r%dm;e9h z_Ac<>p_?7d-=G^P-CqOBe?&LR-wOX7y47<0wb>`SeWKeZx_zSCC%S#2+b6nxqT46B zeWKg{0Nv>S6^#Fk`Radd`iP7UYYB6?=Kq z&M?ZRTA~^72N_Ml>U7F+$v_3DHv@_>L+U17Lq3>{+Z>xJ$6S8);Y|6XLYcmy$VT5z zy%FtCklLCzL2hCmBSETEY2Oi*A3taE$yFGC`Ab2fs9Ex}95^5ooon^2N!Y){WJOP`Mq_GK`7;Sh&(Y<{l-MNweVuqWV; zDicetS(6VNkl`)*==*+D%wN%71Xra<9V#B8=+zWI#=~<-(KT)qzeV?eP>IDEVl&6j zFGYhg%gKS(%J;HB&ZIt zjEpLUQq^}@(#>KLQ;S)h;iZdn&h{HH&M`ruSU~~FWFRt^Dpi{- z+^E=G2eOQaj!~bZ-;V<;(cUJ2 zDAR^tle<3RabJ51k4}K+Xwu}7*B+QKID3Zb3K!g3Vd-JIgEGm&bGfpD+iTUyc{0N3 ze8;AF+P~Zk!r^B!g%uEL7rlNbs2?^Zjb}F|&Bw4EL0@YbU9@Yjg&B1@DY&Kv`wqF& zYd`1irX?%HONS%5W@X1KPG56NX;5L?XD~@qBip>QZNX7QT>;p6gXku)P{OShJ?jH# zOq4@b1tg^&kW#DUrHT!>wXtZokq6}36?c3{61UzOHDIF(9BS7pBp!ppO^3_hZ49}b z2c6JrEU4=ND|BErLYb$pT8kGr*o!{33Rphci|(=sQs1fX7Ka$Le<~NT9GvHj4;{Nk zcvW=@w{I=pmx-hmvH+R0Lp5~E$k5;|j1GZp5Uk3Ygf(Q~Sq-5TxB>a}4mO`|2KH?9 z2dA7CMIPl9nkbu~)}Qdm7!OVEkH2D7@&xCqQv{4?aW6_RW++2Em@u^~Gy$G!_3 z#sGoQNCB7yb?*!fB4IDp&5;wf9#~TzrvcHJx85$GJW%oDczf|11ug9Jj?70hYa;UM zR|jJDW$<(6#n(>{r47d(QOMS>#;Fg{}) zVWLaQChP8~VN;uJbt|wiRA+&DsqcmNj2ZC8d+&f>EC9>!J*Fcf;V$)(bosK#I(wyt z~Cc zA**Lj*A!TP1Kc~kZZwBP61?uBXkV?Q!||%sEDwplvlUr(m`9!n*AHz$-xVuKx?8*= z_7xMQOIWsDLtF4v7j)cb(>~i(5wpyWh>K0gfL9g2kRieh=NN%Ps)1E+)9p@spu?}^ zBYbnkbpr$w^V^pu4R?`b-Zc(f+6qUqo@^_#UuW{?M>_Dwn!1E+@|v>(6a*beUqNPG zrv%Zj0b_n90e`pZOfs=oPOK2v3K8{ssj3(bTTD6P7*<>KuFbB5O(^>U=1zW zFvt3>v{hL zs3rjg&z=?SvE=oNrwn9@Yx3Lj`=@mMy|PvOHtL@#+re*L{+#=tZ*5~x{_m6xzT5df z->YgR_*WSFkIEMFTj9S`HngvQZT6{bpUU>BY@f>ZscfIh_Ni>2%J!*jpUU<>P&PxQ zzs69~zgISl|5LUEb9R(Rz~D6&nka=J^R%#ngbQiO{)Cec%0$!&3{3`hM0LneVW%iZ znY#FcxQc~L$*=kaW&{KAe_T<3pKxTcrBr4<1cCvR>%tKA9LnP)Vl zM3RGv1Qy6Z4mmGAp&S9NY+#gEFsLTcC>^>%Ml#wdN$W=GriU%KU}zZ85NiS$N&OTiH-cQ7+kGIN>)V*QSNIh;3S4K@l zakuCMxbCR~pAb@Onuox^BlX$_26ZjV8^q4&^?{RJ9)s0lgV@43+N24bz|=*93$-(Y zgF@(vACNU^3L*Z!xQoq>CuTG~tDPZ~{@AcMVLKivIOj|a<}C^Y3gsPv%8P(ITQzD{ z4A)5h7q6NP(7aTuf1G5y>!RA7$;8|_auHbOGedSEvI&_?jt+1(&R*u;%QtgM`^Kp) z*JY3ORfh5~`En@VhzUn`MNz}H-wg;W4R6h{k2q#2*{~%!TQJmzvF_H>jtQptsUDAH znC+%AmnuCBJ665=U|m*aKtm&D*-Ugx2MRT_E|1Ke=Hr<2dRShyBiJ3@U5|*=zjONH z;h@F<>*18htunX3eMDzAd@odv#No;u5fe?(eLX=B;NX=tyAruejik3fU5s{E|Q zl16RD%&)PLK!FYkmRH@+BZ22Ok9&Il7vX3xN_%g4=|_LUd20OiD>Z@BAv$ew^ueIx zS7JJr)R+8#8zMw*8j`d7IYL4quqkx!xFYHtir%D)=gRdHg*|Srz^YaZt+mAO!7`Wv zffN<85{EliMkcW#r$W@2=?`*mf)dXZB=3zD5zq#u^%8pKvV<^Gi0rHkNf3V=6jKdG zq*Nw`xd{56P)ZB8rJcTZe%0SoF7a+3wrkjwV~ zTBw~lL5^8>`v#sVqpLSU0~gfWok5CqhcS%ODuXg_8kIN`Ue|_L-w#kxRJNH1oBRh0 z9#fQI4pxdx2;Z_9)`Z*YNqWd5kZsS!cvU7XH`Q}~g_Wr@8%?nT+j0i>+6)2%KSOJ?75OZphe422Idic4;$QKF@FY?ClXymHAz3M2Hm!+ zA~xE?go~}jzAUHy6ys?{7E?qkYbNM;sPUEPWZ7g>LF8S&?(3PN(o2WwhdXE;q2tyV)d}Gag%gvt~=btD|YaoI$3sNI4h*cc?nI~j2Kkk2oiLnDv4UuC50hOVBk z9dqg%Jvn1PfO~;h_H%eJug+@6HkJI8EHGqzla`QoO7pQR8m;xC6afSyUtV&8BWZUa z^){Ux{J!@tlutmLpo3Cr*D$7UEwh!n)g?eXmqe>WsrR*x5-=%yPs0JkUM$?4BSyq4 z!LQp1yM&Qd=;sgYG8}3gqs#bMk(3rz3F(Z1RS!N8}dZ&;8;-;J9r-;tT5-e0rICz*Yc*(aHOlG!JjeUjNHnSGMkCz*Yc+5dpd?oIz1LxcXF z%-sLAF%5z!F%%PE8@7&(cuaw#$x6)r?BxNMv~Ze|$w=-L^&!fWoT9Fv4teaDnLI9z zrlHKP>w%>pPh7H4kSLO#LW<#F^N5YRjgcF%2}7Ya9T$U`n&cNS4CHRPg4-yZ(gls! zLwljw0}8BhMaJMwD8?Dfi(jXH_O;a>`YFnfZ5a{~g{+-fMhxC3$O^Mt4j{>AS|J3H z=9#N{4h!l!B(P#+MvI$B=|y2gq)XPN#B;8(&CA`~ARXSeC)j*((fGx|+Y#oKZwB+o zCG~|^FVbVzG26tLbleeK)`$#5oLF06+CtsdEM~1Y_(NRfyT8IE&P>rPmllN)>fe&h z4?6={yc9Ws^A{K388<Gcl^gv>hE-G_aE4i9e@)=ayh{o`L|E^OG& zME81TKf3Mv`qA?9rEAQT@zx4)CoQ70P~jx1?Y->;(#_Xev&@+nO`_~rw1r$U;OWdV zk?~62s8Ng9Lfk1>4UQnWmOP?(43E@Ckv+ZjqdqFWWR{xHm!5!E+SBHkTYxwEO#JBG z=r!Oh4^GETB6#Nr&e(5lC?4>GW@Vr27l4c7`zf?@%DevrZ06`kpzbQAkkx|9qVs5| zPFE)>lnT>qF^l1oMc6Q41)#o(P*U>@!%Jz}7hJ`T{tE)=<6iiYR|gn@?Lwex7GPbA z12751n?6HS4#x>`o^V2sd^IHX$t^L`>bmdXU42&Jsks1G{ur$g+5tZH3on58SWh>b$AXc&`^>E`pYj0;ug5? z1JleEOo@nEQE#BPfbHAK+JiNHj(E$Z9{djlNXT8cU=Ls?^tj5fWsTHo9*sTrm#8hQ z(s~QpFv_Y?U#h=>fzXj)yv&+fElQ|r?H_$(i*J-OIuD$BuFlU+B}^UGkPE5!Mj4tL zT?{Nc6-hiZ4Qimp-cnd;@d3yNfj<_$F=w!NZy%I=SN1n_WOPkXx9MUO61OBD2y8H@oc0~PGiH8eBg=ccv zv<`&VeNQ;40OiLt-2g-p5q27P4A=Eip_5wD^_p4;q}|gRjY3FY1zO?CSu3wwN~GWd znf%T%5-rD9(3{y)2KD7{(Rdp}88;SQJv_md;XXo|7zkO%mBP(%ILj6Ef$Eu%%;*IY z`Y@tKI+kKl_2uL=7DSPKq;+r)MfjO`Cy)AIoO4z(kximb$^~C(*8>x7lwzfi#N(ZE zh@G^N|~I;|mT8u~+dwP^OGw^M}8yqR08*aoK2#Bu;w0 zUUo7wPe+PPfy5qna6_Z*2X2?7;+?K~S|1YK7p*xLX`f?$WA|TjJk~gtB85Iru0>+x^*`R-)g5+#Hs)t@n%2 zt3d@K-}F#lv<$Xtd^tieQ?cYe7e(m7UYtrN@=UA2Jfy|xxP%pj(_z#$oOcERsjQj4 zcnpCzk(;@A%{VAwP%*!Egdw9-EsXJEv1L~y>Ty6@WP7}z|ADJfuDuGVfpDu&#5$?sd7kO zA0q1USFUpzwsxw9WZ^GV;s)dxr*Ci@N?U>?oSMf@x0uhKRU9x@M{+yy{$`Z5nerKw zfwjaCy%YS-Uj{M2Z30uEkRvL9d2>nqBn?pn0O#N`vs&#O7|<~9XtaT3pld}KE>iFj zLO$FZP{f#;3_rSvrB^*+F>b+@r=G&1@6cjIx(PPiO@%Ta&L|vzL=;q+PhTLYE0`zb zglaOWp)*GwenC>ZpQ6V+_l^$RoMYc|BhX%HjYtZv%;|KrHe0FzA{lI*-c|_`euw7C za?X8gnsm}x4L!xg8NJIV>cp@kHWd%Sv8`jNjOIY#rp#+Uy{aw@+S{yUP}aQthtPm=p2 zxlfY&B)LzL`y{zflKUjNPm=p2x&HylS$qC9hWa9$<{V%%d*H~X31h^W{a6+ zi`imEi)Ar0Gcz+YGcz+Y^X>b8?SZ{cd!5yTGb#;AgNoRZlgixhQ<0U%e%icq5^#m>2$zTD`b=1#`sQGsx zs3Cf*yTv7?T;rPksR8jNCELI0ghZa;3?u~wWKy`G^mjBkD*5y$>) zjJ*@pvA1&Pi9wB9eh(>;pGO?!!wfitkwj=bdA}#^Mt(v!mJ*s@1V0H!0GdA?3nWlUW4~` zl5+ByAk})SHX~Z@r{K6+gy$edpQ3|F(f_i`^R7I_}b((hw}}h?@Su zjBWBZ>TRk46HC+R|6FuXK5vV~qVpd9X!FM)@Rut zcytAtOh5ZdzTfVnub?l6TZqGL->~E&_dGh+YQ&n&d=HhY)~TCjyZlCiEY>%g{)HG> zBgQ~BHzm}fcQ2eiCHSw6i^({ry!*{3mYk@8t*f7xmp8qx@QUEx79n=Ruq;hVfKPjh z-_fjLEE-63xG{Y0ugB9DLus$EfpA(n37=p8&_F?%SUk60Q^N90#Yv0O^O6 zVb4mmoMg(?FWVN3^M}EYWPAas{eo@y(1e|FEMKPE+QM4&Ofhr+ntr zeoQYaRVb^wuzL6%4}R2VnZyUg59&aM&shF=phr0>LCm^XXNaq0D1(hEr5PwfOZ0N3`HtA7Z2A%^oo*Q(0|3igD8-!Ke@ zLe<^A2s!7|#mOx_T3?4vJg#qBCO^zmuTh0!RCXWcCimoII(z67lN%)G>>&3|hnhvuZ}P|Ic(BQd=t8aA?|IJ zoRP>j_395#Jw2X?DOS|8QUl30wLCkdOp(3e%#np4`;Cb2%7!f^B+dA3@4re=fM|Cc zbDcIhr*n6r8#AGVyO#P?&s15mw0VimkPqA_v7NLk3Nw9wB-2sA84|mJQ#1)X4+1iT zJL5O7!iRAY?R^j|kO`9Df4N}vx1F^7M2t*CM;0Ey34PEje?L~5g*Fr76JbD02+ghK z28X{f{_(h8KOjS&{~0$flvyY1x9jmw`ua1w9sD-y-?1D1-$?d5`ThHya0_Ao9lQOI zvH$0ta0R~|)<3e_$ZrGx6T2z+{o3yU*bTsL0Coeg8-U#a>;_;r0J{O$4Zv>y19pS_ zyD|RRYDfH;-MoLY+ox%xzaC#on5#y_h@F{?z19D`rl?XUF*xnEGc1=azFio--G3n) zY8Q=A)gOq3eD(H1p4LBOmYF|0`;8-3XhGzNBFPoUuVrQY{1%a{v{@?4%&VXatb4$o zI$m?FC)!-Yn_wXa4e766VVm>)v78XrAtpt5s7jxY=0y7dU3H-y0ri~L^rKu8B<`Hx z2aSQac&Vum$c2s8{)mq46p4V3vTp`RS9@ zPp^kms^KXon~S&azL^Q1(W%qsJdn;fGv{wSsccjHay&kpVaOYn?R=VmToh&F1|Hsz z6uUpU!dWbc1DbsbCreu9rRi@(qkxaetSzfh#$!43+9S%xWkED!3_>r4Wg^RT2M^JE(eEZVWM}Z zNQz)T;7eqn6*v?i+m6oS3>2aiaYgnNF5)g`X6Y$l0;&J>1mu?45RM2Rw3PE6D(0Xg z#<8k=?uEW0u&lSJ88IHq$g}$ss6-S~KD8od6OrG=BDv?oDs}r{O@!j@h0D$(qX>D( z=Nd(-^jDimhx!P=Rw8o4rEJlpqP=z{UpQn*w{OxATo(_nGrfudrL<0_)UmUGbm+oPBPQ7p<}dCW8&lb%S=B z|MB&@a*LT=i7;Js_t948Qb9M-fCJrz!ZVZ=%yvdZYcegBk4TmT32P!}3^HuJ2btmC zjLC`g3$^Z*A#=O3xf@GutK~Y~k&Rmv5eyErBEeYPJ z9-d*L$tT?xKD9~WAM+!(3Me?dM;4?LT{}A0!Q$DNUCs#$=-hC-{UooK(Tw(O1XaXP zv=`pN$y8$ArKlmn{C6mqgftP@XJ$Hg)-WBbEHLv7l-)f+L;cczE3~2;pxh!QKFTM8 zaIbEWq70g0ff&5)5z*~ik|wluMP8O*)D;Bij)Y?FC_854J`;YPj}IoH6PjTGA0V<;W@VVue}jh<+S>YvI$TMlqdJ|VXO*Jk>d zK~wN;_~}$yF@wnq4!||##Mpiz)4I3C?k+MJPfA@W?rT?7l6ix(m2x-O1BuRx2*h(; zWG|vmN>&y4*GqUxt9WY^WnuJ!PbsixvJxxqV#vqPYiG=OU`(cE1?n>#uozj zB+M&)Uy`Sz0uT|C&i$8wu)vc$H(zx(!;L|7*oi@eJ&2zi6fi;hZrV+@4LBzf#OzE) zBTg?v&>Wg$Z5>AS0_#HIIEIP@ESwpdPGN=jIr|YwEFe4U-imVyZ~M}R59n0m7{riZ zydyn0V7?8`ho>?!^vt7c&c}`L+P+0KU7sFltI_d;eP{Lk{7sd>`J!#;0^UW7o{HXcJCYsq_GX0P&9TOQ&(5X83FEwtDovAgcqK}yQCcTDVomgVH| zXIIFE@sx03PiXD0hCKO7vB8}WoS;`LKScd|-w7frNCpw$sVdR#CrP%6cjo&~d2%E< zI9wGXjLKSkn(SQD+B}u>O}+B58N$t!%tp8kF_AfIQVCX$Wne2h;4j05?2N*rL%Y}L zXmmG*swNroA5D>WC}<4PaQWIBAJ)6YvS*5+rZ3=LnCOu=hU-(`R<#~@2#!TI(Gdq) z8-E)A;o($sV`qdO>c}0`V3BQ~O{pK|j3FJ;9m{viq=r{=21}4$_qID84jIE>laI#n zIi3#n?2EUTWEoWKcC)T`nA&~iYD@RQIHsXw=5$d_5;_;3XmmBWIm#Ja*kwb!;{e(h z?~ZCJg0aH-tXQZR(f(m^C_X9&vLBmVj3f}LJAp~M^LV-Qul;<197ulcjx`>vi;xboZoM={+-UX|5oMa+W%hXe6#*LowF4FgU$(u z{|ajVsBfX)GQ?th?j^_jo6q3M6t zxv2lAbI{X%{9_N8@6K(Nb21ns@R288Ii>qWq}m$u`Pm3CkfiXp@{o+~g=E)AjmV`0 z$sSwN`UXV&i%pfG(e;q9M@ik<=5Q|_qjNecAqB^?b)e$hI3xnlo9?|Madw>2GQU`~ z%9nGdioZ1GED}PWvPk$a*dEhW^+1YW(;L2VlYG2l^l?3GSjg!p)DD-_pS$L8;Gxs%Ub#ea{b z4E8`zWomUag4}4)(fL`r(WXRfy4esp!`PsQZ)#=oDUQ8f%RV0|vKW?V&Sax44rRle z(l-@~h!j0hh)A9HI42PwxyKcMt$OR0U!O&sW4AZZN;P%@KZe%uc?;aTP>=6mQ#HK8 zFssw}2I_F943^l9S*gy13e5gkuwe^paj_O*uE{u$Nm~giB1$ewy)!lIPA)SA zNn*PKED_clV*svg-@5e{ZuzoO!b{@}>x)h;?cBr;yR)9cZ5eQsyg6F9I`kIc2&x3dyR5OY&}A--WwQQwMQ(D2fZYXGj8lq9tkk zaT$$P*AJY_aLFDGatdwj5qK=CO;SOOPo(9g|>KEkRWKx+=PI)g**iwV%LG&sFTQta;? z!bn0@D}}5k6(QrWjr`WpIr7WHfQDr&HjH3S)yAEpNS(e2lxg~ivN1ngKYOt6GPig& zj|r$K8Q== z=3q-}k}d_mtZ-9W0wkpas9CQ^Oe5|n*vlGjW^9i{7hT$u|} z{93Q@)yVNY5)aHUmb2DchZiAvi6b8N7`A)+kjD0ST;Y+yjxbSiXVM$rfHKs9DEVqN zyscMBEiKnmdPbM+Rh7*F9b+@=``kX?Gk<0I0(3+R{k`_=n$~kW)LL?)lsZgmvfGOy zN>Zf~2T{NfvGdDY(g)*ILPVD6Wyia$R#TP(9I`YAX#P~jSatUEh(!*%{X;^+bHX8? zc-BK^3aDuxPh?>#j8PyebNDFwMcD22NS2>%xczpDk)gRkkB=)t>tMq6qSs%W=gVkD zA&R{W&Jalt-LRF^(Y+sZ>pI%~Tkl(~F$$W4cZysidD&dKsj|)ak411sIy8bslx96+MrCfV9OMqWt76&Hu?Tz8%CC-8RP8q7%`U3`{%-) zQ2PjsV>Y_5W5w?F{j$(N*&WpN^Z4nl^^_fRIU;)UASWpg*I29cDB{Sf`Noi+TI}kFGGGbDgJlMmo;h1j4W_Fbs50M-Gp4uEw4 ztOH=({{ZU_YJP1)3IB|BsDEQ!fMO^F@aK!#Iv<661*uz@%;@TIUqT;&d=UXg5fUHM zjF*{jWChhM^a`^GUSeae^u!_ea_HiT_yd#XGT7Yiom_XxYtuy+BGf(b8dN!|6tU_9 z6ZMXQvh@U!kRkAd&p5p5b|0XH@vUaVb|+huicj1HTWCG}2cgv1KZ;0G=F)HC2ULnq z_gHkM4@WNV9uV#)YSY`p9C4ZrR8?#ZP;!_GEy1H{g~e79>@ZUpTCH||%xj5{$NDBL z`Duxq({ZQy2c7sx!G5YxAuR~(g3*3GhE2zSf2B02fWbb38i)7c4_v;xANWAJk|H;& zA(OsP!APYWbXUv>>K+|uu;3KMc{$G@ek`0MCToaT-xaUU>cmX#P7x+u5zj&?o^{bbw z5jnU{qch(X(lL%P?24vXxzP*-4>b?Zguz2sFY5q<9ezp(OkWuLlLVeutt$~0ozstF zzqtIXfRVtL;-VMcpr+t`#&fUCTHI`jaQKte*Y@5=j>B574;--T22AaP^=`GpuY>VV zuGwiPxdkOrvzt;_FyF1%ijvehoZRg1%Cqy6FuBx8+x9mb1X+mKSGpN(>5DfJV>P*H z9j<`cF4DpoZLKT}aThPr7FcS-m@L?7V{5I&F3|lv3+d`;@+S8%Ogt~oxf25?>kzTh zFr>$h9qey$vTiycCYcZlLPU3s_)rY&x2uLP*&AZMk6%;om1~n(GnhxRmd2Bw9Vwkr zb{S3ce{FLV94v+5gnojMj7H8A5EZb%Mz-31%Fxl7roAw{roFHpmzlT;$y73NY5a4PA?z#i zwje!OHq=;KY;I`SR(vG0vF)PN)o03m8J3#nShj-s2_CoPW~YXQaEB%B7xI_MrV-^T z+TfaL`Iq%yQ?S>Bt6r*S#_BK+R>%bT6GPm^Ax67!!=oO8Wv$8*9`aL?AEjP7?|h_4 z(5)(bJ?pdi@!3TPb!2OT4UZQ1C3Oju>Fz`wH3giEsAWIq`9t{g8EkwNYPBMkpNqZ+ zMs#d*hjP5KEfD?ELt3lYzj7zyz+uVX&#gx4LOFk~M(^+kze>hX{w$0SE*D_BXV2zBKdEeo_J3) z4O^wbd1+8gxtiW_+Ap1jRbuh3vpXAtx`lkl_2!2nS5{#CwHcK2PzBR)3qw)yt-bG5 zzv~h=s$S(f;y8I#LGW-Uh|kqnITrO+d21`3%H**bA|Z5c`3O%#&?@um#tyIO#l5q~cQ$iPBnH z#CKUe=k-50K;~{aMMbgi&-{|t8P}(R6`0nYXQ01LHfC^Tt$10?`H(Z^*Dj~2ar6{f z?ZQQ{Ij6gK*0)OFq4XWM-Pi&Nr!M=0F!oNd3#G-VfMwmryOCME{yOs`e3}bBbaTt+O|7w!lByN+IAU&YtnN+1S1;cfBf`2C`h1%Y$C9&$9jQwlu zK7qs`>;;qNvicGF9D0=PH;*3a@07bJ<6o>oCx_R{_s2HBNnupE$SEnt4nOM^uqKNT z5U>JAB}yc|4Qy&@Gh>o$m)knPl;KxKd{iz@PWBO$B`$eEZ>A9M`@#jym8H;|K!V84 z7O)d3P|BFv-f)ff1}4g&g@OAwG5w^kpJ?@GFw^^O*1rR@)ZeQ7T>IaH*|)*}4$Ne5 z{;<1^sP5P1;vd0G^tXZk3CzYjek}$7GXR(YzzhIp05Ai9834=xU=Kzp-gwlv_A&bpd5ju*w9~l*;06` zMQX=$_y!YbM;*DPiE`*6Y?#DaL>3}T@`E{eTHd_BN2CXAC*~p!eGryAFSEaBrb_CL zyTT9f$QolCizpxBXKNNt1Rqy6E zyG_&{8ipvd$>yh8E}5DXp#U-%s8hd7$FD%wh|W^m+O10dD50~_pUll#e)$>iYIV-* zgv?|AaWUlHP|c^Ub;~L(E6!Sqx>ijv4kqrg8g4SwCBq=Abv+=JNA<&7{URdI>(LnRUP^ zfcbW|XtR-5-S)OVe?eP+BA79>!;ehh7$8pKkUR5go7!>tu7<1-a8altacS_5VK&f! zGe+y{Hj6I~^KEtI0UBCc(YrjG0ys4zs9v9dY#;ER)H77MF3A%G)?JTUi~7vZb}H_F&hQ1%YUmBFD{9W4mKzc*OFoCgSo5NZAZ>Ad75_b=ZZ2YNhHQx3$=r zwdxl8O-2O8{>pxJb}!|{c8IrP$rtY@dN7mLCc%fOs>cjDlw;0-H9_h!xYJQlR^&F9 zP4Ct8k0nlLBc$NIMRzeRG2Y*WC|O`i2u2C*Kqh(JVp?{!Hj&a7 zw`->eOlueft5b8TL`wub4>4Ijy^MWoi32rz($$_bb++V+>X9JS; zve}?*n^}TJszt~yu1#9e6MQL1nha?v#@!Gj9n&8r)0(`9wfn@ME%&k8W2N?|Ww*a^ zd}){;D*L3QiMi<|rQ`AZKG$8On~=*_qN5PRAQJ@T>;iAY+6pe>0*ieVikH_M_gQ7- zW0w;`KjyGE7mr})D3Wx!JEgZUMQT)4MlGSPea-Nv2R3z=G=4Yd4~x=fy*DayiL7!$ zZVzM-#Ut~CTKcTh?d)kE1E5l$Iw zY20hU6t#~uU?AV%L}|Pn$pvkvpNlkKOD^2IszkerrLJ!=Y~b`-rSzB&`lNY`|J8CL zUeNcTYFwKF)}IA9W3j zca+kudUrqEqYFRfqTf3zi^s9d9xwxeZkRxlB@I~{CDBUVEDipy3&cQc|43Qn)f$4E zMBQU(RS{1;7IJY?pj_<6%Ylu{5$7oC50W0~YIR73 zG%ol9xRs(8tD+SaNhQH7(mvGZ3fXpFCg@uT5oO;j4s`m2B=M~Sh)cQY5yt7n^n0(g zI91=xb^Cq_p!MUk5HAl@1#LNsLn$aLoKx8^*F_>#!D z%R_);<4*Dtk|1!`3cs+QN5b`8!*8`jQ?#UQEbaun01o$Zm2Z*ZHmW6qxLcB1u9(~K z6J%jb7PDUIb)AK*ZH_$*)0Df!Tmxx_P%}`kEl0*ytor?CH<5zPard~GUG3!+er`HLYD&Xm1}K*cu}t4FDp`zoGXE zY|Cm?r?N6s`{lbs0;ed(&=RhJZlI6Qx>iAP-LVUReT*eF@^S}o0+EFeYRwIl6mB6a&zE1I@_7YRc1E5j0zV$*)7MJX}cI#fJ7ix*w4lyk)2w{;c*0UKdOu1oHHGU!>DMn##EZ_lPoUlPmpB6sK{hD zi%n#Udnk(^3H2MSQjfuQs6J(molotnbuUey1~wIk+y4f%jJC)({M%LhCz$;i>k$4%v7f~E@32n%w<9WDMJcDGIbc3A(2b+^9_{7+ctI`eCn1i(4~)&Z~%fOP<@17IBh>i}2> zz&Zfd{SUB?YvtEAH1W^7+d}?tciUtDPt3u4Fw0QB=#Ghf=78dXYVaA!E$ z9vQ4$4I;*k3wXcfqHlRmI#kK4hR{*@f<0(-c^)8stqtnjuU?SQ*4tE@GfsWN$nTNHh=Id3N7}U!gW3 zK$H+N^)-ts?kdd2sC7L{oRyD$WJ|);2TR+@2-m0(QuQWd_*gH(m#^X3z7tT(qD!4V=Ku(q?m#)dIC#e;rLU-P2yiq6a2gfb2NUW$~<-O^&@pxG)jxMLT#uP%|T2ats0v^ zc41BCXBtTqc;X*^lrVP4)}|V)KTu6#?r)W_xz(A|#@6Z+-_9uM&YC$AHK*+p%U)wg za8Y*7?F)>aQ+&vp<;?NZo)`l(oA3j8e< zh(ND~UB)5_RHI~S`C;vN8V^H~b`}%_oHJ~Vb4x=bE*6+3nf=I@ukwL9QxQ9h!_BoX zlAg+qRZ!t}hFn3G7$`eEi?`wObErb@f1G(=*>#&=jG)_QP8iA+*j)sqIbRUC@$Hkx z@E$pebM#+7JRka<+{{w+th1}OslJ>VxEmi_BNl9 zQImT>&ohx8klRb~>I|AeQJmIk8~TuFsa&^o!8b%qmQ78}T0E(O6t3m#AIoX7LL;hn ztYIBK%RzSb%S8&9qmrfr1K(7Z5fDLkY7b;|i}0CAggm#KzdqlJ`AD-&?=c;RJjCxi zHp^#*!%if3x1RTr8aINroWc!{gKNQ;r;B#&71Vr6SzLOWQsv0LUT@HMvY1nDyv+1= zK>bc$osx!l)sN+5vBbpQHk3kKgTevR!q`#B|5^^S=+&iqJT8|H*^y>eycfh?H9bYh z)(EpbwD-b2S+vj#{KbIb8Rd(v+*c5fdvX+8=Z)*|#Lf{n4z4`Hyb$KMj4ZpT z>Mo;Ta$=2%QN0m`2N!f`l_*K^x%)|E289EeRh0+g5D-h2$jsgh)KibG{vb4Am1~au z{g(FCN_&yFe7=b%oBM@jRF?xe(ma}OrFd`~Gl<-7m$02g`rZ8-wTs+c>?ZTy6EF)XE{cvIVUnB*WOF z^=*B;$)sv6E^g?C5%T$J$9SWqx=QJ*90}vYK~If6GGq0|LJUxq?KS;=WQ!s(oN>q%y%z1Q{EAeM&$ z_)qJUTx7!fM$kp;H^_NkW~1iETVY{@Ab-UA6$|E%B)c>Tss>p^&}6A7kaT#u#d9aQ zQM*fV-+PBQWb9@hP1!2-NkKHFr438C_zdgV8BEVfyR{|`&xzb77`eC0T5?0PeIA{=b{Sb)=~Of0qy%Q8}DLflQ|Xf;mSg@%M}zOBQau9V_iXON&KC7XO=VZfHY;;b-x6Z$}M zzFwp38Qa3O|A;5;BNpWkZrrW-s&YN>b(*{^a?f9m!vuj0zv`$^JC7wrrA;B%Z+hD> zLj#lVaQa;E4H^C*kd~9Vd(ax!x&#u&N<5}&!HajNdxxh-L&t&@teozHO|3o|*_` z;9~n@CjFhX%OP3&Rlg8x8WUcXh*^BQTvzV>+ z6zwb;nT+7;dt)j!k%X*6#^Dm=5o`E+{wrd1+_iyb+^BF$GwxQ_p^3Gzq$&Ci@rBaJ>EFPo3OkG6XbV616h;Z4`FpU69y%-nc$)7X@Q#wPb?ha>MGqt=3tVGNUkLGCdlJ44S)wA!;A?&1x3|Q5 zCO7}u&oWx4CTwh>L(NoG6L~5-88=#%gl{+H*0ln$#|kDlDA+>2k!VPyh^#nxvh3;^ zL{_M`*8CzSp{EGs)~#?7+0<;I(wcH{x_xdiEaSNMtx|+ptPg@N z8-nxm)E*wBq)LdA7+|QrF-_T7j?!Zz*De^|%>z^Lv$-H1ljP}#(zPD((6>^l`delv zHP4%aoj7NlPi^zBX?QAoy`a@RLZmQBt_xn4%aMHC40O$3K=iS@F@n=5{ zmYnHjy-v3I zfGrlywcB_C(E*3_b7v(JsWdfy?1GMge9D^g%%H=qhA}$_BUayOGILl;KDz>ih=pD# zXnuH}xN$sNf{{eMAI!xV0vw433&b%N!HMq;p~!VqgG_DYi;X(6Nx4^Fp+f+nw3}J6 zMWCpOG6);S$tQFq4y!9BW453j3^_dzj)P%C;RBv9yBz8_ip|?pne9~A)!63q0Uc0> zIkY=p*4<0NQ0;H}-=y7;L@63SySN96=DJXk?XHm2QQ<^g?>ZCG7x-6CL-q#-Ajr8k zrF}4;?bt(iim$QsW@U&2f1r;+3&1ok2`i{lp*U6+O#wBDu8`8XUyrfT<$G7<>hTe= zuuK+n_%0&&a)`)aWsztU#}PqD*h!Hwbwth1soy2$njKe7gJysdN(&gYY5{bWY8J0G zP@O}eeOEn53soIE?t@V-TMHwmZgQ4|Rgh)r3yn@Gr1lK{kGry1;Z$U8@3bK0kD}vWZ@T+4eP|J>-YK8? z3#;;{@4J6Q_F0Grf7KH!Lb!>7rOSB1nFWcO=T=P-0y~<(t$^HjRVPSv(ZWG?k;ynS zx65!d2hCkF)~;rlB`dD*Sz*56Si)^cteKCJav7r$s`BJ9w(XSZB;KfRe&@T(_UR5} z9808Q5VFEj&HcS3NfoWDz-ThnuT+^5H}+p8E|bcD9V! zHx<3r-)ey*2VO!#5r_)e7Q(PYu*>C3yWnf+yI(0#TM+Z`Xu(08jxYMl{JdujBa?OI zM3oJT2o0wQb`Od19FOEAvLEyQ+CDdRm{|n*w`Bc9sGm0WXP1-xZPveYxxnA5{9OCr zyWGS(jCcS4AMpQsefJLM@Bc8o=0;}Pwni4_{C3v%dJ^w){&24={N=Ab%s;vu({BU+ zlgl+f|5^;-asZbDxE#Rc04@h`Ie^OnTn^xJ0GIn8xE%1`jq%SmAMfuD8CqP=@vF9} zot}`Xg|@B!<6rOp|3i@edfNerX_~`ih8GUxT%#LSi$K6T-tbj4f;>{CTS?g{qr~SP zUI2~*@QPx)B{w(@=;=;j7g67 zK8cW0HJmhHr_^9KZk#2cXTTcQq>4Ogz|GeO(FUu{Ua!<2jIV>lgK4<7Wbg3WyEs;Z zJih0n59B}}-q>@?Q1m5ew1lBwefA@Eb-j82Y&-IvM!jZN=B!YtMX4p^^fxFJU3Lc{f)Xk4D)^uYkjNd`N3{?;yWHJ3C*r%>iNuY&%xFE(dr({jqszA<)tg7H9TyL%N?beAddwF z3m23&xAW=a*vdJtHNS*>Dl-+^Y5#(PvmYo@7%lDC*msAcH;NX+95^p=zA?nEO!|a< zhpsad<4rfZ?j_2D8!;?wtMBq&64IS^kK}*wLt7XpkA%2C4gqnq>yuGyhOQnIMjX9i z@w6H5C;D)4QQ%fvUgRnoG+Xyf4|S2jhOL#)uzcG6F1dt51KX;rwtJ9dvlk3j$ADvC z#kBd#FuauD-j3%7yLxgX9@jUcMZ^mCjDEa$FEi(BZ+qfA+6Ao6QOm@JsGc+*_2OG9 zNgZ50GO)nJvG@udR=bktw=~z2!F+B~IfBhOxvMBuYvC7GSCjU%G+j_}d)KGMQBhk} zVu58Mf27XQ$T*p+D6|-Nale4s8c}+(6v;qHS(eP33~2s zH>JpZEo$Lt1nVZ(;9-~W>)9@hAKM#P7^#O7+ixGEpNaL)Y1#d^S^q9A*Z)@K=i2{1 zE!)BUcWIgS{13ZWc!2(|$j>v&Kc;2f-v<7tw0sEpYcW7t2Bc*`S_Y(LKw1W*Wk6a6 zq-8)_2BhWxL0Zm({k08^`*T_j{J*q3BQ7(djn-#HX=*y3Xr$N68UPYf(N#^?)j6m| z>qkHg#o!4XVnm797zP9(mB`q%{ zOUT*D)%+Q>c9X3%;~mR{pN&W;m&FCA*LQ~iDXfl9rRk6@B0a*%z9y65e&(k9bg`XG zVX|O%B|X^3pFcX4gT0jFj9ov8*T1_H?*n!CO5`i!?PYl;wB3bq+u{7QqMzIil_Qv1>N!fpwF8WXaW-%jCxI@SVZLhA99s496}wWi!f=O8`S97AuI7$;B2)o+Wo_>5C zgDlL|m4v%_J9K^CUcBEJv#BR~{Fc~<`daMMln>5F+(Q)~+~#~pIlGceGLTI+9J3M< z>(-oE?ryn`EV)lR*+=GshkMwU`!MRVK#sJ^T*g}SI+u&Pif?sUj`@+*zT1 z46I`HNRaG?fCCR;9W@bygM6B@}uov+Xz1_j4>}sI7pxEIgjQ{%0fNqm(I2#%x*M+Skf>U zdNs80qo8zAj@;8U$DKK|nA~u;t*?1ACHgo&oZ>n7qK8tvY6dwcS>Yzvf%Ok)`aTVB5SMpJWpDA?efH6}andVSCImNq!A`$sk$7bUh%528vHR^#k$6ce z3rpyO`9RV{EBMttg<~W4W)qU(PIN|^v)v~BHVi7-?*`|ejx!uzfF%TI)>nS}@czun zf6nLxe`n#JG4|hObhY2A{9OCrXLOZM|92|-`waAt-)Mi1`a?$F`t7j(F{6XQ|9ay4 zPZ>QF^Vczej1I`?fQ$~v=zxq4$moEK4#?<$j1I`?|AUMkjQeXFI{)X4KJ<4+ca)gZ z!)m|SS+q7&c|^tFpJIlzN>sEN#bGRgy6SKC)$!X2P;tzruc3vxivOGrRDvKFJrvIN z05p}6(=fU5h01^eUA~wwtYGBuMdQ5BB<(D0?e2*)ZR_E3h$hUt>K>a$L7>xG2fvaI z9MKX7cY~Om4mC_0#&<(QnK1Yhb>~Nv&4 zU|0D+#wb13&iowL{O-6yinb?2mc0h%1EA+a58|QIZXO+j`Eix*oV&v&AZ8~J(H+3* zl<(NNx16XFBj!-D{C8`sse0j0q`6T#pU$pK(Jy*x$Hw4F^tchufr>ZKhDVwM$5X@Z z!UUO|GT<2KAm=7p*JMkNCf;3HYqYh$I+xW*dvMjE_GzEO%D78&cGNIf>w}d0BG!Mn zdxJ;R#+BMqjeml12?IZNgn;S9sMHE++9*yga(4H>yP!y1Zy4&JH|^PTz`kWdxh;>r zhrOV_`0`B$(Txwoc&yEYi zc?x~c>Rr|Tiq__rdiU?#JYv<-rz{vjTDYK{Os=<@_bx=%f-* zw}n334niYy+%RTAqg`XSX4K1V9?o3ybN)*KsbD5ghXSW-0pbj zJr0Oo1ryC9W8c4_KaalHcQ`tu4#7&a(DJ zyY)$nr#1s!FdlY}yaU4p=qRj%xW0`|&=QlI13M(Yhol~A?gVIzkNVh(QLXEBxSPD# z+x5CZmle#p5@+>$)B;=AL^+Gl9JBk`g{v!YlQs_*Y--Mi5=U;sJGv(^{I_xUH}!#{o1uK;q!O|LzEh#7=BXH3U#u8-KT5^<50f5eZK~EboEmV_a1OSO-&#-^?Bj^ z|Jb|BpgNL@ZbA+mU`b%yQ!@_ zRre?OK!sFyPoMssGt+bRoEab!OS{Jhn9o`8MYIq@6v%GtK&sm&hbQ~@pwbEgBW*7} z{m&=bzdp$a`|D)-|8|nk^P-jKZU6pBJ`vu(JIQYew|)DcE81ls|MUCJe=chOpX=FW z{_|(gi*EhnN&fzef`50CkBj^B-WBOTTln(_^v~;sWR1-9OrM7k?0^6Ne|{^zsPsHA zFD^2AuKJ&s!g|K{G2|br{W{Bu7qxy5Y@q)d`R6`8clnoDJ{SJ~z4ZU@pQrf$F3ZyK zUwj22>P5HyG0U141^+I~gBNA~Rh9&Qy^QDA`aCed$g(zY?W6KPRQq+7X)kL1UY4^j zT6ymB?`PRW`0uj(1MwI5rb+PgN9iB4^mMYsO(bBRgv zbLfAUrPPZu|0+wr7nPm|<`-E4T{AZ{{X?~1XZiN8G5fz|$@!v{=Pv(#mU!g-RpF;D3$$ z^E=|X%fFwcE7!lvQZn%u``EA--TKEYD_<1+yDZt6e$MiBvFdfP>UFW|b+PJovFdfP z>UFW|b+PJovFdfP>c6m9Rm%DEG*sf(w?*Uq>*)n|8Uy~=-6y+TnYQCXbP;&=ldZy8 zM|Uz*@G6K?gyq&o`1Kgd-_1ovi%HfeL_*@qBjC*R5_Z4kYmw6jkL5{9)mcERRX(~; z!wz?gI@Cd87RcK^9zpxe?}gdOznO-mL!@WCmXi#wc0dd9nQYA{e{+)nO(Ig@U26kk zd{$w3G0SRr607OJiP3E_g0TEp8o>p|XR|yd31t`YL_D^p9{Vvp??^Pl(_R4MW7HSg!=~3X^Zc6YEL5eA`(uO#(ZXl7=@P$?-#U(yr29+)1Wuyg!(-Jm2&PSE z$eE?o7Cw`+tq{#bt1Ag0X19nVHkyU#W3y)ALp<5KrBNg`TZNvFyQ(-D?*4;YPti6P zOYsi8OCw>mRvzYQU!)_4t6eYqEilZa1Je_u>?&m#s=ba%C`9ri#ahR%38Jp1b&9A$=2$jM#lmWmnE`#J9ufMA;1)PO68f~ zW09hiwCeA30k!vsH$6~#U6Nteb!QY-Xq(i4ED5S!e|nB-UHMKGEoLv|4&>n;Qs zS#sE7aP7{5ElYYK)%VdTD0-xu=&@8}zAFwX0;}irN>fp;q%z__quL%b%m*Lrk;cz9 z!^U$vbC)<^Avo=JpRIhi1zOB&BT5-Fv=JuyE_6o4V2poL3_V^){IV_v(VQWAs#A<8 z`46gi$Gylb-oW!AH}`^DP>1QMwf@!jH7Xn*uTEqa{Nd8H8^JU#mNP|Ef?Z8UaxU8w zqN~UA4h)>Xmye`xzgzr+D}|c^VE*U5uY7)FDR$sql+?+h=ZdDX zm?|p|XJ|K4v4CTwwZ>+W3BSRK2TH<^R@}LPGbeIh*oATbv(O`SrpFlhzo$phN*DHPO{y2!n& zTJE^wvMo6O5ey8_i6>V8I>6JOz;J2@lk06kC z+z7po9(YYpZXjE8aaK*0nYM^FGOwIT^#{MWd)t`MkmdVuTv@1^xQ6I!kWxs7Jo$3Pre4EPl=^i_~Vfwmzi*SoF&nw-8)~DUel6t^*8VT2q3xO{}Hb^K3 zs@{>X6xG??MMkei{|ths{i3u~rmbWT+L#SptELouv^^NC(%h>@z+bAsap1G0=C~ZI z{B56KOW$ouIfQY4;ZdFn*G10MrbV{gknZY4q#gHS@^Sh zeA>fzoL1dASPDIvzn;;F4-U$HU#UkPrt}Dt8NXP=&E}PK_G1DujgMVpC%lzS2ZCZ< z`j!hpnJGgs@JTxJ_It7)qp8p&Ja5&kj?;FJB8&NWRGYAcPnR7KGmxqH#z^qD+rTWp;RX0E#Y+%|V zp6^t=qlH=|L^HH4;j4^i6V^bB5U6+)uK9-yM|s-8HuSs^PMlAR=m5m1T$g9mz@?(i zzNzB7!+p6L*FL1xu}RH&i`LE~U`x|uMC)l^ohqfbwlD%KLK{k6`heE0Zb-2HRX#J} zcl_}0_XnIpH|uX{b>wg!L1LwX6SrO*bf10e*S1FSmtj4t*zehz-iubAxBW|7`_J7M z{_$s1>fhO#CH*hVd;dkZ{?XRpxPP9o{GF}E3jbW@)z)5Z?bX&^ZSB?8UTy8w)?RJx z)z)5Z?Z04aD1S|ipC`}CzqU2;zijP>8|nH_TN8}QkoD=4x3e}C4mM+{wv>j?rpQJD zR}hh%BKa&?&cQ29`ezZiZOf+A?*jQbfP_)1e4YqjbNlinvBf`Sje2-`KST(MYt9Rp zx*-ku2MnJY3jZ0F=3VbQw{xX-hXL&2f`t!}-ytT6Qb^d=y*itSgsvidl$^kY%@W0t zlCvq!4-f-W<@t1Us#*H`0eoL5-(RYCRwe<7#aRHVrkn{_6h>;T&>Y8IBo=PcbBx3% z%ccl=EhyI*3{HykKgstXNv>vrKh{$sbZaoT7hJ=0O)s?ddC`|D8-Nm|WSfqrnqD5t z+dZfg2`^C!_)h$J<96i?N)4fy%wojt`d~yeU&9+A8VJFm%vc%FVT^4!avP}V%M-u( zq_6pE!g-9ayj2wtbX<%h#|Z>%&ZMzRdoF3j1*RX8Qat*9bneWnxf^^h=IzY@S7w45 zTM%##;{w?_{OY73Xw(~WH(_fMG}JJ~ADsdcbqalAF|KO3gqnuf`^EUW-7ChNv+J5R zv=bw+DUc6QP>~O5C%=$fR&}iGN`Q^b+(Ph}LGYXgAM>Fwz#WXVvI`Ci2MX77-S<5LWY6GbbQ#9Zm;(MDbgGYeF88U%~&jEo+q(1S- z#a@q2Kbv@^+k{|aB$e_sdKzClGFpUqX@Dr7sRWmL2iUQAJ(~WhxC2fq$nL&|rN9oK z-ZWL2^MNRZWic%$bc67TO;T8jvPTu+RoO8w4kE$P2;%{xGt#5S$u21Bp-J~$gT7+E zMi);Y(0%y{O^U@#z#aZ4%O^EZV2kXN`30`IyHwnWL0Qj@Om1gnUF{E>49IocYhHGA z@0(|IGz3wiOQy2x8U2F5(|Oyg3QzTnV_Q z!4CO4-6~gVxVn~+3wb$Jm$p0)6%VA8Cj>8y)kkn~`Qh7D1+In*Birf;Y+}_9dwC4W zcJpDxa?(LuCK-88OzL{+=zgNPunKoBz4;LyBWOAc*^CbsSY(n<(E(&d!c47kQFBnc zLaedI&EDZ??|aSMz|?51(pE%dq?dcMM<6kJwI7Y=tkvR~vNUvZ-0zg0rg@33)WV&q z^+%Js>~)c{LtyLo;n-ZTmb|>v=}-O`$Q-Bb_JuVVG~K~Cv9h-(V~e!c8J6NkOtR(q zxcI)NNaZbLf~W7iK^l(=cHc$cNZ&Z$a(DLib~UtvGLvDS3QYS>_Ax3$cQTg#&Ly*_ z91E!H7}-cZPR?pE8+t#xguD^fx$W?MXjD}1La*BY1()(F#vAk z9881S&HK}a$^?@G$;lcWRvd~2J{K~pDqMdB#@R7Hb6=#lh?*_-=>oP-BC+e5k?04s zstRFSr*94e#ELl0QD@R+`XD4S2Fr9){=DE{j^{&1YO_qr;=j$&!%DRi#C{kYie*fTcL8_Mhy?e+8w76;QS!8NNc>X_e@s2A+6?i z-o1s`q**s;&0_(|hhAdAKKg@^!e_k)YG2|YOO@ z(hcX^(ypuOdAzg!Y_50)D6W((4+`YtnspDxym+NE&YYyt!>0Wiu6WbmvR`RlOpo z-2<%|J)SeMx2P{oi?)Sc}NBiptQPOZO#Z(E2Hv=T>EuP_pH6cH;@$A1#XFk+BsU(~|C=p|=moDQ5D z-QqCb8GfwgyCIs04{KkaiO+3mSn}bEA#(8Dku;McXRW3!S2LsNT^I15N^ohD2i{L| zo__TgN^&m`go_%q1}?a2fD-vrCpvmEqL`cEaEp4e>RtI4TxziXYNSezK-`Nn^n0hywQHh~uQjOO0{M1H zg{)@r*odV(qGRTC*hsO)Y=B$?anM2}J;mtvBPjh+LA zj}z1Q7<1y1)NGPpueRSLvb72`z3iA$n((URjpKqyrjmmhEhxMGNxz|m$Glpc^FRPT zLeOrGg@|koJ~PDq&93X)MTO!V3spqERNobgBkv4fcyGDr@)hAM(>OR{aZ1Lq47!zw zGK?uv;F%PRUX2dxwJElDW{QG>E$GH}0>{oh9Oi~O#}(-bb%{&Pi{rk&Ootm&K_9md z6cFVaBTW+KGnOlOta&9wZ&CpfI}wz9Ew=t=%Xox*mm)&iwLv@MBsaU?JGWz>dR_M3 zDW%F%U0{f2&*VtQ+^HfSWXAFv7zH~gs1nAkDs;AAxEnSbN8{KY^#`<(Ybz>}drm53 zPh=`Z#6D2niAxAyt__ycIL6Bki@fiyBF=6&Y&11tAo?~Lo@+*yvvk&J;qbv?%#$^> z+$#_PzcetIU>VN?o)bkTi6Iu6Ge_sX7sJ!fDk>{RxrQ-2h+p4#Bw*f$5Q@?E2O;! z>-bF_=i{MW9`?+->Z;cg3yR0-LfjWYL+Q}%4LOPT56-CaC9O@m5NZdx;RQ#c#ktgc zpmz~ohV0UMY@ja1mm?JE0v<2$Ns_hQ9lxS=!@v+N zOo8o5+@dx)5yM1Rm2=qS-d~&4iHUN4Ai7f~80r1`IUT=D7R-pc0bF$@^vvgmq>ieU zWygtVI9N+W8t7)Qcf(Y4_2f3Vfi>*w4xn7c1bb8_*UCH^Wp5!WOF5)tC-Cf%^r@#P zOys6SzAlK-CQKc9JNnKJmBeL#(>Bn&bJpvR`GB-KF9?(G4@j;NY324mPeb{BO=(R3OKBti8c+_vEm|8rvoSCP0E#{l z$In4JuFFZ$1-z`v>Vg|kQsUh?MhQ9WySFrE!d0_}8H(u(f~+zj!G+T4$4w!f<&U1* zXAV_eWyNgBnO%nHf`HW$c`do@4jM%sgCNWc23EZSL_`LDNk%S+igO`43$OKi+OKFg z=9tT-{QeK5tE#K`Yjcnta}V5fMw+Nsn}SA38UUFw(!-=713zKBrlrIkQ#wK&nc6t? zD6%S%>T=3mrVewloY11ev@59DGu=_PiKv)C_Xel9LBCu^%oJM$y%9Mwy1;xJ2%R=a z{IUHpuajPq(Rn`K?cw{dIP8{OE-#BtgfEBlxD8l!TH|z~7oe92G&M;m@p5l#qRZ|z zkt+~jt*cTKOi(6vW(bdM2ldan<0I)xaEQ!qCyG-9&y-oysdo3tNwwRfLo`_Z`%}`(38m*bjGc=!s`Kdwu*rpE!vib3Q5kAj~?(dIjBa`&i$J72D41a#?&_pCfo@h(hE< zA~Ye!Ya>Fpov3YOAzAv(g2p%ZPHG43qm2Q{4JZDIQgX{z|NJBv5d%|arW6fGQZ%aw zyfd2}?mEBGslb8CMnB(uIxO~*6OmlxvZj!m2Me35{O}UbgwdLdB)Jmy8kCtK;{yZL zFV}wFPev=l78kMr2JJuZG5Z*_rz?kY(!}ZUco}j%jLp-fN{O6hLQ5>@JNJ>ZjsrS= zjWdSJ?0vaTtkuALDlYyS>iMVO#SK#!W!>=k@V@9ovN?kry5lMoH3Pd$2UMQSNgmg@ zxNhxkytQ0pn}I?vBv_IBFG@nGW42U8J~DOVi53={J1K)Xn-i?APBt*Jqxe}!H|w+m z;f(M$Rtfv9zG4pyTTw_5n@Qq48X#q0>5?sZ2kRxtkH=ky zVo92{4F;I1DgO)mq>eNU>XNYY1gUX z)}fEQ%cAV1Q6l)c}Wmvc4KN;oeOd%Dyf9G{p2ypLQ zvBZANUWu>rVCMFAcOz*9^(?bEZ*>~iKgF9unBVokqp{$!i=}O(iUVH;vcfnD)XQSd z{*oxAw$$=f;b}8w&45Cks=Kz+yJbCOp`H~%?u@}0g7~yg#dnbrIwM`Md}J~rP~Ov7 zN_jRI7nrDGzzM1Pk*+T@st^lnIGZm&?~IP7E>*O7j#q!5Gh}ID9Cet*_qz-ul3aIq z)FzDq0K$Aa(<)TGt;(eCBo&lFN#!Qw<7KRta2`;7JQ1x&0{zx872I z-m*u*`KC7-WG;tbY=byh4W!!dmbv&L8NuqVwp>hj=thk}+-BozI+bYkw*SyE%Pu~j z*?hu5m0bvvc|^{>S%mwfdIV7LNB`cp)WSA_)w-MX`m|&XpVepgzCFchLt^_wR z6qW^KNeqUzPM;b)))+22%DL{>RoE=@i;=>KZi}2Zo4LNn&bhdQF_|@3nw<&0ROcj@ z_>JTd6R}qJkemn39y>1%w9lsXYfq#4%dMUz?Dss);6*FX+x~q|yAJ$!p7xRP7kA1# ze9^6c^tAV1ex9WKou|cn{#@qO(_TI8)ze-*?bXv>J?+)gUOnyA(_TI8zu;+Pe@%>^ zC+sG__B8eX^|T3pZloP-P|YYI+sN#k{194(7}R7bQe#~VvSEK+EC_gZi(&CuXc4{-w97a+z;Im4;m;ra-bsp6EHw4*NI&|s$iD4L zZr{>|ay5EMPZQpIJ|)hXQjr!F4wSP@ZN9@aW`Btz(bk|byNDR3a^-^pvFdt{CJb0W z3J+s(O_$d7R|!C8PG!HZ)fX7t<;swBj8veq*68e|vBgipPFJ@r~O@Q@01JsPA^>U`&`&pNZir2WvdQf#PsMo2+;4 zF~x{l{-cW)(ZGIc3(qxTV2(UKpXHlDH7%CfGX)k<#r9q&2y9)#kpuhktZl5$I!v?K z(jQP$*%;JH2NQTqcO*!mv6G@(bIIDd#OkHKR51+XK@_y4gXYE}s7$I8Qm#+Wb@#PaIRU>PcEq zGZ&uvr4Q8PFhysO8U@4Vk~ap{wB8HJT)?k(g6DK-+Hj#XO5H#qLV|G=?S|;~ye>8C zY;u$mlXhD1m-?P%oP0eAgL&j}$O3gb%b!z`*bl=~Av!=Wy@O(0NoCf^lhd&#+j zJe|TqG-jO(IMQL(ozz(+91524=;PFcErTw0D|;iNAM<4kv0xzeqhMgH*$)qGCsaBE zv{j;UzTgu_{!pCOAmCO>8A$$BoYoz3i7u#7Xoe*hsC9CDFbU~ZeA2U87ISRwiAhKU z4G9JdZob1Yq3R2hw;0vR0F^+*^rsUbHbkN`pFePq6e_o==CQ7qNXV%WskfW%T-Q?C z->IgNtoRT;tv-Ir95HeLlj0++RL@zz4UjpGD)Y?#2nt;6lV>##={Y4$F?q;iIQll~ z2x`@kA7em1w^h^?8QE1`tRO)gwZd9kBw=bIiUlOq!~@Q5T?3drdk68;mdO^`3C(yu zN0wB~aIkA&)3GuMV59Xg9BiAB&T7k$C`CNbX8;Ja$2D3|f(L|>6&XNQoVYW&0xQdC z5O;7&p_d@%KR`<7TQ#_+k9+ej>LC`V^E>~aw++*h6-+b~&wgWdcT*|RAH`H_nq@`K z{3AgJpqGMdE4}1<2p%C+&+e-ZjzCi09jV%AmY+M4h`i%FE*_~PyFi*&RfH#BoYSpO zy*M0X-IOiROm@mv9O$G0^yhbj(_A&+?Pd|)ax=A_{XhUCuh(J_4j=`s$4xl>R~($4QpWUl&_URFY@_rVJF-8g&*2!D}D2aLi!-ja1FY5^AVQZ510!M6htuH zD|-Wm{3HNADiX~7KY|loo=?S9#@R)stwbf<9!?1=;In9=eg14hQq8Vau9;rG zDV!hW;9c;W}m0qZ>~#*k&Op1rAezPGLOMexmIB_)5)GKd3mc<6Lne<}U2 zNBapB7#qL=k%ISu9UcZWAdTJ*n>j#cWg_uwYP8Nsf)zSF-a{Ch69(@$=VO;6tpNro z-vB)*rdom3TmWuqgVWnFBd5}%N)&;n*&t?+Pk!T8Em+);3?^uqbn+P6ruyl|sT9?& zGQzZ>rbgA|2AMj-`;vR82#W!k)ekahHuLZYAgjlvJ^a^~(ze&rnb-WpOFNhNjFLWg z_Mg_rvnw3je81i;$MrLsM&E3&s^`T|u2ooYQ7sC!$El)jps=;Ii-0uu$An$k$ka(E zwnP*)63{7Ud>hkKj`)(o7_l(LQ(7HYG2vn+z5X`G)_~ZxjO}DaI+tIsuxU* z1~;^=o&_c~R^4+->~h zeRtDJ{dexxvWomaNcOi+=h6@Qnacjr-2z?|{5yApkNvr^S9g1Lw^w(2b+=b{dv&*0 zcYAfWS9g1LxBr5>MW*~b4ORWMyZz^(2M%wbBmGqd!GQ%-jNrG%a?B${0NFX4kXKht zwBmtcfqKfQ0%QcDeATTzeEhg3*`K3yX~3Z~o%9A#ddK{7yrt)&`0LEko?5>Q*?jsM z{Ekq^hwe)?+gWkGwRRdrHxc=0li-`Tmzmpr!~^8gAE*HFKFo5nd~#Ikw;QYkwBI|hJEbmo-8xw|mW8`N^+`o&^)cRIk(i_ogsIX$a`7Z)t2}lx-7z#EsPIsx z$wU~th@p>Nej>a15UuY6s*zZsjuAqeU$Zq25}6u2Ti@*+5kJ0rNU9YZOh``MJ6ib& zM)jEOnIuc7=uMRNB@HX_!k2co2xU9M`oy^3xspS}v(Yy@E<6|Dpll-^3_P8yGD>3! z)$RmHqBmjCxf7%}^e4&%nOaq~fN>QL;aiR-P#uYGQ?A9?X5OVEXz_TbK}4&u?EVI1 zC<*zntBZoz+>t(pz3J9SE{gYJ=gWpzO)$t8@fw?A(5LC!KAQ(LRc%qYvK!PW7zZ7p zIq`HVL8@@9a`=!>sGf?wMz)xe8NwA@ld4d8nVdoRYM}5o&A><~d+9RjAz#;=uUU)Q z^KJBN9}+o~nGvb99Z$%gYCUznScj(I5|ZG|e~oPJ*IGg8#0q9@SdP z9qXXIM*a)SG%IX2;Kv{5*!K7)QtY-KOKokp2>VodrPS(?@Dc(etb(!BK|!o%4XlmS z^H%z`kep5NZJyf;JGY4#Rc?uWzC=I<1n#$;S#EbwInz$`C!XAaBHOf7WN{aEJcV=Y ziNxDO+Jg|(O&UAG)A&mpWEND;c%_c%AQcc%U&?uWP6O~uVFSAx`cGyOlmCbW@sBIC z0n0W*QzRzs=mXx2D{lmrD)24uR*g0L9;~>m*OPI8|HZT(Vq9lFY)(3`D29?oRAEbk zn7=Rxvp?l(E2yY+C7VOEI8nFrbNtrAlVYs#gXi(6vBxGDYq2Bxc>8oTQ=(e_kxob1 zG~0-qoR9hNd#_0j-dq!em?Sgr(<$U@=<2q*G@JwthIrKCVU6U0xJLc=nWn0F32Ou1 zIog*+t|6PlcyR9*DWW=?k)0hmXQ|dVHtz>W=`T3)gd$*8eK|Tu(M7FlvA*{#5m)ox`b;WagnmpUA-F+(L+ObUR|;}7k5>+i4QzmsvQ}@s7Sn>P z*`V1YvTC;efKsGDsl>NF{L?oLDMkFd`h@akKf2Bnk&fr0LT`7$kM9tJQT7b*%le^- zu>-8wWTB;=_TDpqgIx)CFC5|}gGtP41O z;Ei=`HA(^f;R@yfhZ9&n!h-2ghdh?g-8R|Mx z%dYz~{#^lNNo_JJrkpSBAe~pP!K%icj^EB5@VYpTj)pEMox1H>jU4oVdGy-Aut7Rz zimxXvfTe7YbjSg=rBT(FN)JzfKU8y<9{N!|t&KI?I*DOdptpGXn5qQO*N0BPG_?jh zuds9I6r9YiY(=z1iLL1TwWtnA*jr>mTs}QL2OW#3U_4JbS#ZMVc!m7)P-^Co%{OBP z8JX2FDG^%*sE_Mwe|%$nS9Ui1#t=X**$jZ8T;^i%ZQ#pX#BczaUOjv;j&qg){$hpy z$*A&&GOLZ@`ojtg@DXLY^nQ>8B{ExVW}^`gKSgJ`N13{eA; z!BEeRf2I0nj}9XhVmzD8@T~v+5U<#15B$PG_Rwwuu;RA`_oD(bTGcxWJRSSh+DP`w z`(+3=@&%A9!zhAzUy;rDS!t~G#Ie4#clmDjUuCJ#iRkY|C5Udv6{|nzxEEHrNY;@X zHQNd+du(_g0~{=>fU2rkd&C=o(@Q~|5RDOc_sR)oqS^zyY?Pb9Q(bfW*=Lm(_VYTr zWfE4E@%bXVxZ*kj!ZqaZ!C@a&94i;)L-$?ATAK~xGmm+ugk>8SopZw#y zaMThMVO1|uW|{m>4Em{NAjsJwN8YqJeh?naM2yaw)R3ekEwvmg0}Frnaa*#;I$F}g zx8ROaK9VM9>A0yyA~9wsLI#FJ+NPFdDiv^bYT2H3@?ORzi7FXJ)+O|Yh4C7;m4J(Y zUZGp@8g7)7&H$;9!A*bxM7XQEt-{QE!?HhoYc3S)wk28Wyp)=wGFciTn@r|!4yC!2 zW<_ita|vASnba~2mzvKuCMvTXh-y9{6?Ied_xZ$w@Gr_#OlJk#$x7yHbVjE^ zIByE z;zY75U=tJRONAG^c7f-2Fq8XRm3A?kskcg&3@6glIoyuKt1fwo7?skb(bFGwILND@ zc4)?1>tzyCM&KD9ibPM}@l6>HC^1QNY=Az-@9rc+aCP05@MVp<5eEC*szm$hP58x-(Vb5@h?9gQPPz${=fQSLm;cDk{! zVa)GC-@%p2M1Xx>q@&#e5zTVJ6Fb0ee|w_iDSWuPqqZc`bCs2 znIu>m-7LD)*@Z578Am*XZ!E~AilnvdRR&<|+*Qq>)6#Vj!pYYhOu6?Zsoh~){qt0^ z?&nemq3g{s8K}3GCZ!Wl6vmcS+=Df6o%->1Z0tYc(yy78!aJ(tB@NwJ5;G^qK|lkG zUcw`N4y&4mIjyOOX|Dr*Yq99-pvx%3OIEv~(v_&!$zqReDHiED*>CH7*hN3f0#y&^ z*3_dCnkWYqTU1WkoXIOFD(-Cp-yBMj<`x_@|LCg9&gl!8zm7Ui=g#bnH+JEoI33rb z{h4an7~+ewkY_{jTlS~-uC)b3^#DLeJjeS$!~x9Y5E4Sq%LFJga}mi#n02jK=K4Xc zj>?+`y9%P?4vK{LIVa+Q>e=h|9>K@A0RHgz{EBB?`srW6Xc(^Fj zHQEzaLRYY8$9L4zj!uX}>q^ZtXD!&^x3tCvQYMxbqS$<319t%s6y@;D@ZXi^Ee4L) z-=kjF#MkiAsV;3>?>KPfVsDg9lPBimY(zO_hb!T0dCPO?No4l?xzo`50MXl~C{N{2 zY+#MI?JAZr?*!@Ah%;oTcYG+pT9AOmp%m#4SU*Ilux$34DIb4f>FGsZ$K+}VbYrsn|E$uz2p=fPyPahw{0f0r4TRI00ydq$0YjrqUu9%8Fjd&JdT4Y121d+*CZ1+QE7%S#?LfLYhUTX*MkO(7S6XiGy+l8Y^_v~={Ss^>?FR+;O;`p{A%RYIH|4P{iT)L zG}p3%NqiqDTMSND3=jY1`tPvRh|Gg~Adz$UyQzJ0_N zUgn$WEUgYapCb^$e3H`cQCmM5O2}KP?$Zf{9n@NzhalLD9%w&>KvoJV8he_+C*XI@ za%Af-4w=t7^=la;{Y#+!Z!)I+qLt@u|GtcU@BDW%_MzGSpKqnM`=VR_C}YqSKTkLQ zPR61de=hSXW3MvyDr2uQ_9|nqGWIHCuQK*3W3MvyUy!lgj-RKY)W4Q7yuW13pBecY z=%YAlRNm-Dup_?=EvXQ?|=-^-3Q;7z9gmNBpSlX>U34#GPrnHDA5e>!60O!uo`((`1t0D6`!8 z3k44d8vEe-<){Ht*F3Z*TZmRuqH-H%qez^dSN>e*2z}-JOTK+HSUil;2Y!?tjHNxhm^#j*goIr_(K~+5>jx*b zR~kJ9t66|-j~_`JO|*z4vp0;AYxa49H9XZP9Z=bzGWUmcMyoH#z-}%Qx-ESEUPdvT zu&4D-OeRbxrBX5Oy2F25O%Sl&g)H^n*k^u##BprcQiTy=`j*=&AU48{EiBc;j&`jU zpPM9cG?O`Ly?!3hl`EaDEk%Jiya6Vf8@ZNkm2|yhEwn?P16glDn6W;~S2pxrgP>My)?Z$D8Y|;0qBg0mXeY$!WejT=%m;$~(AJl*ff+Lt-&zFcx zsG}Ii8d5EQ?|8SBVYd{%L+Bny5s<6I4DFdjaX7#&7;qq5ey`IreQfY40wWXHMd&nW zYo{Ku$#Gj|PHmt|N9NJ4qTV6r_WkCpgwp0? z7y@CH1LFN)Kp5}2ph21|dpJrWzS8!p=gC5q=}m*5*LSA#i=(z{Ss+s6*@+UW42uDf zI)kiqOIi;cnJwC-EQP|MW)kdqb$I%9P%n=rv>#n}mU6;)lB}_wcg16kxn9&aG?VLe zXLl7lJz`ytE)-jb(hH9GN~}x}MLC-1>MWxQ%*j2Yb8!QbI=n?3{R%FK0valS@c?%1 zvkSU(+cc4#hkK!*iyMM2G_n)NDs*cFS=MPPi7)5GQXIRDrRVo#?|!^Xw~@wf?gehE z%9a=ykm>kwZz=M?$U4Uzq-BEyULB?*5`p)P8z!4o!n;`E$lH0Aa`iqH5>E*Sm-y<_ zeZ*PgnMY@(oKq<~8K(cC)(?>g8Y6MQ!y#HqwjS& zZIsLnjHdYm4EhPtZ$LEk>BffQjUzvv8had5*=FDD(n%-l|9P)2QjG};@S<6M?*PQ2 z6oMb!*%{-BK{gUV0<5$S*pS;i0yMk(dX`}rkWZhpS(bw3u_R(XT@cCkhRP2=I4^zv zI)(&Kv5X3sYDMiUf;qjH#mrHG)k<*oW37j!eYmSA*uvHw*)ufX0%WWZJuLZ0(K=;| zl}D6wk$D6yt`g{ZNtNPxk$1Zop&btO%~CCJt@aiC;8b-)7K(HNI|A}hnqL>psYOw` zJj{A)N=#u7xjt>Kdn!YG3WXK7X(pQAg?G4|)UC@YGq+_NX-3`cb?qpXqeeAHDB)c+ zM5A0a&{IDD_44*Zl5ECIE&iJ`3F6~&Em*%lY*CuUBH;0PMlF0gy5Os zlHms3@;48DVOIa-TvB?q_QwNmItpBc>mPtX3;43N=@^@}6!FHIoLipj*(DGdb!XubDexL)NZD2e_OVpmXFi!@MC|dBX*r?NdrBB zKCs%-;ryjd&kFYJSHHG1y%)89@2awt7p**R`}ghaY3ASAS!vHNp6E%~_47RAAMH%| zMZv$bvyqXX8+*00S37&PvsXKNwX;_{d$qGyJA1XWS3CPJ*ct6#6XWM;KKrljjOy9W zxDml{eB-qkHd4$m0eu47iOhBKP0dV`uF|z^J0mfROab=X;pe1`)uN3Mo5pNC5d>@u zBDnbJs0HGgS%~jEX;F0;^p&34&c38<2Y0fVD(bKteRF5y3+|>`hQrQjbLJ+rOOpCv z9}grLOQvOK`nH$V*kM4LkJt$Ha__d(?2&k)3yjufF*VNWny%PI=+AH7i0a;Feq8Qxd+=xnP3~-)fr%{htzh1;7*y+^KJOs}=yaATuo7Rd^^i%5a$eKegJ8wK#mP;0NQbC1Cv?cW}GWQpC{ zRTL<#!Stp3?2tk9%JNma{gzl0BAcmWw|14^9|ePaMpg>TS%{FIRYq{B&Z!8OG4gJN zE>blT?8>~X9BT<@@zsxP>F8O%r>)Q{No-?cRyiP6*(grQ(hz|j-0t`FMT^M)r` z4uD^x_Nv<=jUh>0o3QAdA*JBi$)-!1mGnnLdE|AKr_Z3!vz%e|u`@xI!_<&H$~d<;HRfHG#gzh?e1XO`$pnI z01||`O7w;%6HpPcV#H*X>1loWmHU23i)HI$iJAJc3moy6LW;85#o`wpS~Z6UUH&5y z$I44zb?s@d8?h8I8ACilOxe&4gd}{Sd+d<|IZ(*Um}{_sw3t-2soUylu-Ia?E!hN)6tC1#TBNjrY$t2qZ-$y{qudEA}5Tr&zTP*tB}rsQ-Ma~ zetIO~mVgJf=Qlq#XFS_>paa09M0a|Oez_*p>D_D&T96c*^?)iF>}7N8t;v3p%f~0U zW2l?22N#%M=XbY?Uq6p~GzK1OB!N0h_UkVJ)%Iz1ODGd}QzH^wm;;V-a@g8U!Tuo; zU2k`g8RG37Xb3nD;7B{<28)Vc1p_&!Sj8_CEH zZ|f17E7-Ig&w8nao$sDVgXoyNQhGep5WAQ4KMZERKT>AKa;mgQw+Sp z!Xe++X1Y{ELdDZp@-J`6P6bt<;XjVKhBueGQKsD^K^MfaA`Rkt7eUX_7*F>V+aC6L zrkHwwMo)8#mW$iwD*E_6I!U@yeQ&HlCkpjA52gOXcv(27`v49#-7+_Lg2}fuNjvT-zde9YwBA70S~9!CPUuq5YQ2w7TMfsFHQ;%!MRa0o9^BaWL~ zTQd+2f#72O9$9ULkwLl%ywhB|->n$zHMC9lTVh?M9WcJzk4`RoJVAB)D2EMfjW153 zC#hgBP!M$8>X9bp(T!IY;M$blK~bCLp!+P}Z!$4riE>c4Di2@S0jJrGM30n#YhAEI zzf{zjb~J&%#LK&M!0m(zfwhv`WcF}@>*QAm5(oOuXy;f1e)qM8h68VKetNS$m;XtLf66vx#Jqs%%@#}iUe^k*D#D1jWdB9t{%FRM1KKl`nZzuadhE!mKUBq4 zH$74)>p)J>UnGnDhEq_IJ2kxeE7KNpd4y5V1hL6>@RMi@Y3G3d#ARdk7oW1c#X%aO zr~ZS@f**RB=Rl`-=F!w<{K{rDh9GmQRtyo|pM8Mh0!)6nVE?kL-#c2_FRT8UqwW8a z<*&W}xuXf3{&$W>d*Sq-d(f~aM-4amZh^+GKv z^v_ZyP2Do$Lz^ZN#5u}teNDnNgb_34i_Re}A22EUg-royTAN2%})CQutLKwzAQfK-`{WuEkUmL{`TPI>WVixV*Il)yr-;uF@w zuhhc_u!(Nv^H3F+1kpL`jS%a!lhW{SSoCTzZk4Q$w?m|fBH!xP-4Qt1UVQzzL-%>k zAF(`G*EWggY`m-WjVpPCA#XHPYP(pQQmv~1)VmJDK*qw@=8+iF1)au{k)49lbB2J> zs62c44S!~0V{a zj?}Pw3T%tNYcbX*mM=uN;j;a*lpiV-Wrvl+ny#i6kaS8^|Gt=?S&N3qsLkgv4%1E~ zH)}u1&srZonc57pEoqFWr-EMpl4-hOBfBdfTA&7mmC~zgWR7ce*tZ6*hVLB`SG<=N$Y(A`If15qkEjxK^#g z4D5reX%KOiXPjd?YR`6*Vj39Rkt@RL z2l&@*d$VSH-}UJg%a{eZ*FvBAJr&bJu`E16{@FyQ~=|j|7xc_O{!fAe~=849qcwl(}-IkmG|qlo(m+I(o?|_CN6RHx4rB(7U7;!_w^BHIG&yHzl`-0GdKcic3P0`IBTs3+yM9JJ zjQ^ThE>C|Jwb=IVCop9kepI=Wz?);hRqgH2DVwa>1L7RxqRfHp)a)ddLp#d;<69&1 zkm^Kwn)tVdovH|SnUh^qadCq~rFhsHrik%E7vL5`IxUv?I(vr6H;Mk6vZlqBy{fw- zqk8V~g3k7DQA}O z^U9NKT%v?k&K~3~0L0YGd6%;+bo)mGCF(Ww+fOV(B1ZeumaEnb@S}`0sfQKA)cK5@ zjdR|xm4zuav+p*c?9kdk-37+ZU3ItZWeZ=eR_f&fgydt@`h4MO5D)HLH8I=mGp9>z z!>X&DbEnx}_^t>G%DZbaOhD;JfVbWp5fJTJY`LCUiQe?-qK93UJ<`rwft7DLb&nT` zmAOi?R1VO!_FWfI#i}qc`#a6n4a1oBvuxWd4Vn|Ik_N>0q8j{%dHZyRF>XTQIxOSJ zZnWg%!JbLtM>KEagw?z3At;PNrDf>-kc^WpDW1_T+`JJFVv_C}W6qDxdLNyptE#^X z#9tx$v(=p6kaW@D%3rFXkg{4Bg9}w`faXOyx~e}TK&6CFHk-V*1+z)BR~}Xq6p%Dk zKfRfgL#z$5*o*Y&a;;l5L{)p!G;sKQb$NRu^H1HwkyzSM?C;3hPA)3><#PSYv3_r8 zSHG&HWPi?+i`z;qS%EhoOBK+J~Wi7}|%SeHhw@p?w(IhoOBK+W)}NPJjNr z3^o6~p=tfg&|=Map&kK5O58Qb;^R;e)PbWZh0Kx^<<-)MEl%@K2?;8akP-3I`9mxs zWv6i^R@&Y-Y=+C@qVkjFvxV|&LFE{@(<%;n*sA3=X51?Au<#vJV+x1jfy{5Y$g;X5 ziMZLPLP;Hs`eo#ICI{5xC{G6F0nKYq4*5@FTUg-{!e@x&DW%tF5K&_K#$@z&PPsvB zWFSr7jPwJv5C<}05OtL6c}%C#{;H~O7ED_@Vf|<}q*A|2N`kmI!a#bNHXy^Ii-%lH z^}YmzIk{=e$`W%lu+8rd8NrxwRM-Adeji#}Mq)%(Is>*(Y@%E3J_lz43#V63`l<3I zH7NVWL{C{UC>4ncbl5t;cNgsXL8m``74$ZeUhweVb2|a30;zw-FMC@%m$Z=?A?4N_ z_m0lQcH7W8&15*|q1IGmJ>va9nb%H+S5vxk8rKAqtQ5{1<{`ML`Np5GUr_EMm)J>b zOu>+*DL1J4M3Iw|N5PO&6#lz7()JVtMXHQ+H}Vc~Tq|>Cd^=c94kVgAUt0W4^VN7O zS_w7_f$SbZ@!M?SLh(ce9kGYwd`y410vi0jP)hS&D-TIry!6y7rz;4|tcd+dQyOH^ zsuV~=Tj|l_KwPCu1Z!;XrI1OYD{;6%X~m@DBhpVh`f#}8q0HH~9l-n+z>UQW3U7p@QwPRAlHXC@=<>k>l zlR;7J(Rk+VG;2C%WNSiD{qxvwZ+I&AP5q~FM|ie9^bCvXWq=N|beoKD#(>oAh9>yU zsk-H1nSbpj68GtGzZQg+Q(*Ykolv<$Vq4IW27lo^Mt}C%yI$N9O5y(4K+kAs_rWr; zt@#b$l$Y^m2lryyfsJ&yjBM6cuHYU|=}Nu)FbGAMo1+|7X}X|1PTG)Vs}r>H6Nwi! zC&?sEpL&Jose*DKiW!KntJ|Ez#DqJYD=S|at%wgyvh2Mjec7iY@9z?$4mpnr~wh>X*zG@F|*plh1s_sn^ayBEv0y zCNE@k<&~nj^%MlOy|8@8{e=+oy(no7_|*lHsAHu_v-fYUVE{u4)s#1ZpE1= zk$9|d9MBIGR8gtrzW#4+LI=oT(h;aZyl>y5fIE=XUFqSXSv62Wb!Z_M(MPspkyMZcGgK z=CUnp@rqSGQ@A0rdR}v{vnXxn@L>=ZbZqK+(%`ST)8?H5GD>k=YMEm+yQ^pIulh)a z@>K0yF`c%yVz?8QeC44)*E;XWA!~p?&PMA;Hj;%I6%V0cx2ZJ47-WjY(TxJtNo}JeM|<(8fEwVJPMPiTXL8=qsjTz;h+J3((xwejxFn z0DF~F7f+!#Q68g??~=+(m1uU)Bp0B|sA58bgQM9V`?ng*+M);P*zk9yojTz^2DXSl zt_pQ;+xUfoZx~ZlalcaJkFakg+yU=F868$=24z6t;5k^K^}n?B-#V75x;G#NYoK2d zHluSJWbEt>``xt@rK<#K~6T(8#ib6ML49GGLwo{9t z2N_kKHNh;Czy5l!=JPq+YPOK>jq7+Bhc}%5apJP4jNsTbh?5#X^48z7i?eUbMW)H= z=%NYUOrictX{~jMM`@2u=PtnlL_136h9VwBgfs44olE7sC5PGK#fCj3pokiu={iT0 ztr@n_1-w8zZu5kR%m#{aXU0VOwB>B9^gDJOW$hMDGI41ZF$=cE_akYb>H@2Pl_5^K zo%m8!locJlWx0J9T%P%(bnl><#GsuBFnXitX2*carKr3^3mwvTi$JIINoVnpnjsy; zoe4sS2MFX1bQvGXHYjp=3gmXpVV1iSmzkbmM=M8BIom$BQ+TmFXQXzJNU~GnqM-iQ zuTw`qXvV3{V4JvX{3UCoQZ9M+@P$0Dki8@9Om621tB0DiwZfKuPf}ePq_r`(iyGzD{E04_y zv_>JcMmGBbWW|W2+#=1F-7l3tJLsqfF>*MP1Eo4Zuc&3eKQK_(GDHF2DNP2kNgS&!iaAF)jI&QoLoD9R7Y#D zfJ?!$@m>j#KzgzBmI7%*5S8h|JnwN1((oQOb;F;3g9xrnE?9O5>ifG2#n(C{T@B|D zUf<==xW>ELKS75q^A?9H?SS6qN&G zXjw3ra+Hofp?OsDon4}p05SQ0%)UE8Kxd8@U{pZ)iR|>~=7Iz+{iSPx4s(kk`>LM? z8W6my5c^iZDUWD1vS>T-6AutaADX3ah5Y&w;0g{!DxJ9*3rRD~bD;c>*dY=ee0^4BamxAM0zH@S$t)Rh2j?*FlA)j_^5`6}@+mOfpx8;D5dF4&GBGsL`0RQGZ}?eDI0 z_*9$}v{B*@&ZAI^1c$xY=$o_seFi&1HOlbwg66s5g8Cr!tnfC8!PkoAZL|RdhESE9 z)T6-TqMw(qwouB=Pgxe7SjRj2s+_Um_MV!%$ZVM=3aByg^9EkoFv>8=nO_a5<5J_V z>aCzrt043o_))6ev?%ZN@rsu|)l`q#`d$Q;jw8Va0m!Xm1sB@WsS;lLSEs=ZV>TC> z8E_NTC=4>y`Hic!=Sve|4FeG1s;b_Y|{z9+=so)kcnZ z)ANEIUbPK0iA3nbmwfzM={Le_y6zz8Dc`LN2dLFdyx2GoR9d4Q7d#N)3U3hSdnAdyB&+Vv zD4^*b|HOCIZ{4VP*>_M?T$)&J&U?CQ& z?Dta&!eniUjiN(R;c+KZg6v~;j6~;@YoVOdGzA&i-VDWJGH38a73KM*dq}sjPejk{ z*X%~c^)c}_5NuLq1%P7*N4*6SyH0QDd2?DhHcPQTuQk!RFvLVw3U4J;P6=7LqIBS8`l<>;QEB2mWmpxQv!?;ZB24}pJv z^DAER^V7B%45#ur65w8kvBgUn=oWL9+AT5F-GGDIRWZlkZen)RKJF%n3y+ki_PGw< zB1PJSu%H)-1T~X3jzUe|xumwAwWJ%^zc7|H*YNuRt-z`XzNLr%%>oK1NuJwy_F8Xr zr^k~H24w;jZxaqhYUFnFO%A~tleqMNUJifG?-mT=v+#4{{vTh@2JDF4BV0ULgn|eL zJaJipO+KaC$FYH*MfR5up=h*8vVzG40O;0{Gwe^);u|_L!~@WBr53<<%s&P7j_Vxg zegbkSCIj_JTd@{Od5ILW6^EbcR!yN{*>J*Lc4L4@k~kBBiFlYoy4f2_6G9Y+ENH(?Rm=x@r_ellNDzX!MT$u?h0xQ3-=0x*!KqH*=^r=Cg0n8 zieOYT*f6h)8i`$VzleIBi$x1k$^6k1I~7BE2eblVy@9|{Enq64gS5u=p4<*Yn*CS= zJg)?rxri%la6~@{<&x8&kA#@sh-b2j?AVdA9iQkM(e)IBiIs_witlEYBa{G@MmnG& z9Ee@C1C)~>9+wgNu3EH&SiRhKq|xOJCj1ERx{l#qcSohqmPG{g7Ar#ZgGv#p;L`=J z=b(&pe~LSw>~>&|{TThFarNb9w*k7>59uywOmWgA5eo;)!}*r8UQ-@^nMRYs+heuk z`NB;3DWqltZ{IM#GefQ+S(qh;=M9>)UL05HniTD+lj{b?MJ`Fqbo%+z`R>L@&|nXa z%lYLU9(G2$Z0BEY+rMDz_o&wP%c_5dYWKfn`D^cg-peLK{NJG(?zi7O59;}+%>5rx zE$f%Se}`(M*nh8PK2Yrg)jm+|1JyoI?E}?5Q0)WNK2Yrg)&2*l_MPbOWhle%QH}Ut zs5WV)33d3#^Ptn&&HePE^?Ha|`OTVXmTfX|N$_+tGN#l7A&fy0&2}pb3ep8LW=d0b z6dEPRq#8r?YV-_4qQX=9B*bdMS{vyV?t<7Sg!20zv}|WVtNFu`k-ePc(F>D(8e0I^C;*ID*oXWZ$h@2Jfq~Wds7IZsqOr z5)zM`{J&$(9qNqqXA{JIn*$JmluLvBiWVyjdCQNgr05Y$5ug$(8l%2wqG3_GYa5UYQk_!OBLsGQwS6D zj+uCxphuTm`fK#?iN;(jb^GYKjRn~t)d9|#$kYXUcUg8(XVs*G1N_n1Lf`Hd^Px+x-h1P>)^|*k;Z#h0 z>JrmOwSWdQQi4(E%iO`wIA>y*+UsQC(ul#BP2#n;fkC-6Dxrib23Py}RbM&k`Boo~ zGcU(lC@C8rAXe-dmTpZEE})=k=Qu-04r-3*M>FZjqTA4H1xrJ=vQr=nY_C?2#PG+N zVi7d1CsQ24{0`~sYv*JO8hbsI2q5~IvdS&H4~-Gp)W%pjR`s$PA=n=(xt4{y53R*@ zT6uGF6M`z%cPy_W@=n&HV&5Q1daRdI*@MLo@mH&2F;>oDwLO0%mNTY1x$JOQ!M&kK zer2`dDm?CMG$+2nWenqB%n26I+RwccTzYFjDgsdmB;pM0*cwOa(f_7piq|EL`4oMT(K z!1W?JEcL#q*Bl283fGg4hz7N0)HWK}Cn7fe;Tafx&5BHC4bq>n)uurdeI|!!#XR%y zEAk^r6J>W+Yzf4>2%L0jyjn;SAqYig%GHgM{SU$IacOqhdwFERKMkUtEEEhc)g9c| z;jIqL{W83wS#?#YJ?hFs<}lJjW184qAhE^LcR)kr>&V94C<1W2s9%*kko<+wzeG;w zwi&{L!~*-hXRt$#;s`j53P!YHj<{)Xjaml663=X{kI}dk6-*%a*=Mb(lda|x1{X|g zZkeraD6&6-&Y( z0dk?$l${#*hS8ZJ8R%Y;wfb97o-||b#qPr*DEF}tLKfQS2@TiLi#<|x!-ky4hQBkI z{HSrCf%_xu-PO}A>CNS%3i3>w{G@sUudxFqnJ3(#HbmAuWg_+%tfYwl)TPuH=6X3r zo{%n^wa@q7vbyx5LiI}YTUcbH$!YyB3ucUB(@ADgap_`RO=CxYprKWjmD_M z*|9Hiel_;O;O;&UVvNO`w|NSfW@Vjj_qMMw&^s|j+o46#jVg@>SSG@w?aFk=P4Pje zbkQ!ejuNYFGi3xOhZ7Yuj7i=bPbW|Bs}`&qS&ylAs14{trfFTr=S_9Y6Fg@q=mBN= zb5;h#y^XO8ah+LPM4}@nQ(Vdu(`+KPrB@`J)1PbtCG~Q+6nbqEDf#U^dZl(^xA$8E z@d=t_79YJ}7wSN!sR3m@a7Nw*(YDjD6~UF zm640Ss{a^&|2(r2?bqsep&U;{EYce?fMI<{@VMW``IAdf9GePmVeWf z*7nP>{$o?x)-Qqo&d*Hg{$99z_}Pb_efZgjpMCh*ho61;*@vHf_}Pb_{SW-?nf32w zsO9hdOy^&IHv6P828JZbI5JCXI0l3t;tn%7&iAq#XYX~agiN7dDmodjFo4* z+)Xf7iPa3;j&Zr%^1q$BIj6FvK`o6^dvH|rY3xa|(zviUwAE}Sgr2D#Oj24y7r!56OrBhBU|WPfd6N{T|zMugRZWdNJs4#B=-(rvjU@VsC{(DX-#$V;`Li#v<( zAnOsXpP!>BqT#y4t9aX&f?0R|9%cx6sPJ5WJ)EQ2j&;`Jj6i`hD3_)-pd9Dbf!Gf5 z%ttnmc%D3c137lLbd*fy4BGNa?9@eIkPVr|2eD|3v4NT$00!!Z%01c~AWOrVs1_DV z!!%P7Yt7Sso;m8h34#&TPEa&r-qF6D4M zdc&R*cHy>z7o@mf6^lhYSSIXYv2ehaYka=RcR+>d0{|8qv?A|upKvBkDjGGb+F>>D zp)T2&+mXRSV68EsG-34a0+S&-&d<+M)A(`+jW+&l&yGQ?X4_W@58{NRFCqJBaRh?~ z9tL;Q4ASeQ?VCyp{1q21(6in`C1n=2jU@LDe+O{EBkIklYYm(6og{V>TXlFqnxLsIDaqg|9Klg3NS%@qrEDW?~8 zNqK6wEBVgjXzGQjvnTLQo_=a;lpm4^G=ZQ66!dMG$oCl-jq$mlq3Eq6pybj&=6nv! z0^1T4f_f73^wbcA`>;QMu?b(`_dK#iw`BC=lY*2FMTbQ%?@ahPw{PXTRRo47+Gj0 zSVM01D@{_!0Q{c${7m{-!_f~N;JL@%=wNmFv3ly<31zifQB2W_QAX1u3^0?j-<_~!SL4z zShM6oq2v&14LIOf+OZTs&@Xj&tZFNo!5-Gsf+i%s-H$UYF8=|Ic<39a`gq4dB1RtY zPP=)0C4?{ouQr=UIr6(@fKCGmIYmYA$dM&<1kJ!VRu-Gl@<4NBNU~Tj1`Os#w8w~i zDq?=T3~=d4D0)?MRIOnx5pV+lhTMbQa65#U$?(2++n~Fnk=^WOm`>8td`q{IxzwYb zXLm!QDxo5w4`?ooLY`JbtB7lBfV=uJyaGx! zg#$X_jEq`CEOm+31jJjGYPit(#CUI6pao?YIV%-d(+UEt@BB$=djmHjfnu#}8!;N^ zi`Vi77SK8t-CYxkY$PQJ5Y!uedVp{qCR#o#H?W8x6TZn^Jd94bA&?v7G2InT-QT;6 zue{TNe|WWlRH-yn^x`QIUU8S;VveR!9S*;M*1bG{4z$03zephYJ1gk-_2aY=9-ugb zosbyK2y$Sp*5CB`f*e%VsDhtlX;YfX>AgkJt!`8dL#MQ7E;XSgS@ca}I(}x?IJT7P!(9)aBSq!ET*w-G75?Z_%M1tVD)+t9kfy=?e!Y-P@kw))cNE4SJNHjd>hq ziWjfyS}}je%TrW`6zkmtkF>#l8h%Ug5#qiYpR;n^)JQd7$lRMS2!)8LQ7WaOJJOUz zxxa<8$!3rPME5Q{oVOz6`w7z{&j_!bDea$B^(%h;9^RaOS@qB0t>Tv~|M&1lD)ryN z8}HU{;EkF6??uXggg5nH0{bXMG+JUucH=bsAD~Kv%4hkXFv4cWk zap1uYv5NS>@ut&|4U#0r`e8ww=Tws97E&d-v{VZn4;L?-7dPXrH2cYrbe{EQ*MpL9 zHQ0srk-Xt-faIgM3dRfH;1%qZP;11(7Yq0XlF%VZ;pIh`A#-XbDoIZPrke#O6?B85 zt!YwIJh7?zdRUK4`knD=R5Q6#OeWOrZ}hby{O|SUpNt4OXu9ITo9DHk5IR#?Dy|$z;wmy^JyaqbE)o*qOd`u z-A_Z7u)f9HQf5jhoWaeWq~6M%0jd z)Nvf&xW>G}H;BR1z@>=WK#r@%Q1VJk2-&c>w%8fM#Mp?|F!fpiCYLJa5Ed#Wdm7@`mn18RWTM8!)2%LKm{GSDm zdpr$dp=o%s8@g(OWV||nzVNp!gfiTiw?VT;>!&J)yX^&6X7`(B!wVw!{&I~7u=q2Q z_ooOt?^Y0vl+%)eduk%I4*JzdAG~FvEx{LZI!s3It0-LHeB`F>R~$&n0A1G7;YVsu_Bz!{=9Pe}Cnrv~ z(R61b=+r&)o*t}zO3kdU#jBpeSkNZxHAQHa=4#i1fdyd7!d8J`n*j8w3%SUf`!N^K zN)Tga-$G8>Ac(OHJx0EyCF$i_NS6I>7Ufk~N)>|xc4At=G1hH z?(%ssO{1dz3mB*_mLnk3%TMGXk(pL&;j=2qmIsPIsFJz@N{Bp7ry`@CHYOG^NAB15=SzazZ5()cAkk6N~rrN2?o%E3fR(6XH>pNXdX z`wE6$2j%A?i2H0B6Tk>gQ2w$leN72){`_uoLFF=GU;8iERxkq@+hd8?Z8$j?)0q{~ z0CAT7gXHK^CoEYWBi5MJp*<|yeL<7SVcrM#L*QI~hh7(KIA1N5N=1*mawnQ1-;;(s~Pp*i!bjhe&z-4awlI9EX75DeL<4H^`Kn z^C35LXO+|Mpb{dVX-482-z(wQ>dCM3V*#9(!AKcVds6=xIZ68pV5>-Si-q0QS`2_y ztshsc*tOZo(5lJ)EjL;w%Ik>t=zL%@O?`>Vq<1Lu8Mw+OdSjgIGX%gdGKeE4mnQ=)OJ zun#|mHsNdVQvbVvf*#jB%4@`R0TXSDT!a-C$=4|pEO1~;IMm`u%q)tymisL&do%|@ z897@AP^A_>Ojy&a7B8-2tF-Q+pEIOZ)mavK3_7LuJI4$<9mhLEc~>pC zph0igSIM@-`z);|fv#uxb}2MH8aZQIJMQkR49}=~odKw4m+uVwkQ_SU^eW3RnU^Eq zyr-gac}M+n@&098zxTEIUsnAyUxWEm!+y2Bf8N+8sQcgfnrzq9fBv_%AHN*yKl)np zFMpDsk2 z(?vc?G&2q=%d%sGU*@wst$qW%V7stif4Hiay}?%=QxP_2?koDrS!(EPiJm`$SnDaR z7s~9+vDXauEgN$dp7@3YDk9}YKi6=Z8K9O zo%DBAWwOQ^-VrY$G_?VVLU77n5eHB;E$Xrf`=mXus2u_#MMUe|dLyuSxb(+J==~cI zIs=B9L#Wy6vJyY*3p;4Ju9g{-Cih$)R=F$L_JD&SI>J;iy?_N}%@zbTGon0kBEE+L zK>(CtRl$>8r*VNF;= zwUNtX9Sy*Go^!tWEk9T-h@%=zAm5j0!R<@7Jj&j17u6s^kzk8r&!X^80x@k~37A{XetM!^wVO14Rgka_^qIqP z$_8KbDZipNT@+b`q|+|fhprECU8OwO_kcofut#e+Cyg~pxFp_UOb9@AytPo{&=g*v zkfDC3hkIfJv{u)M*=+*v`Any@O_1xXsPEbVEm9((Nm^vmd5K?hucIrgAhq(n#leuSBeBHN7@Iu}!1WJm|n7E@mj+wQI!u%XU>bC+{GTWeYl zpJ8gig%!{W2h!?A44s<*rXvN5{&`cXzr2dPmI=d9UvfK#aU&PYmTwcB_ZmaC!@1!8 zl8ni*9mq2d8-slr#09YNRgZy1xrhe6s;>XfhI>u3R59K(ERAf-U}Ux^WyS;@$5pkY zJ#o`Of_13-$5}Sq3TJ+%(cnAb`PV$=tR^Lxp3rB+QpOzo>2RzNUV7`^s!a%pOMY_&2>Lm>v>MWjcYuth@T78mlP!b+wp>>N zm_m>kWI1z0{?ns~*BQgMX}AYoxsWX~^2+sMY%?T$ulT`wWYL7LhZDI!lsIi4NCe^i ziB+V)U{z_|8WxW3XzTxCwlD6cig zhNpE;;XMj5B*f{HY$DF9KBb*!`iGRj~Bt2s|_3K-oL}6 z$7x1LqJtgMfddRF(qIe=u7={X4m_Zm;ARzwrA=O2vHNwAxo z`F_tt%(>3#laj^No!-U+vD9Gh_pP0N3+G6EOJA>ivr3e}5U2pOrj)RINWTcy)LE9+ z!&CXuct!wkNe^-!jiJiwYTN$IxIHDNSA|dDr6X2KV+F1o1xYW#DNfb52U9a)$UYjr zLlx{gh*TNUt%}e>N6j|KHiz zr?KDISoJT*`j0j?|4ZP%voS4;zZWGRHuhm-A2#-3V;?s5VPhXQ_F-cmHuhm-{{tKA zwEKG*%Jq92qy5vyTvf-O0Qx1ysgmO2?#$@w;~c`NB)4N?Y$blk1q508!c9jL36+Q! zWNWQd86x6o9K1X+5lQI5g3Cpi1`uTHH&2~KK3qJws*DV3nq$UuY9x(RIWMW2(I4@! z_{w1yp(2w+t2rm0q6~d;$gd&7h1gi7l%|#-*-Zj4YDjCHv^9L7!{S`fL16#RgumeS zMG0tYHaTH(;ST93meDZ1Snntd|8_yxz-h_p zPOYkHKv$a!hIsmhUO>^tC3il0INc%kl%%Lh&oeBk&R$LNMeJ5lB_tReVLN>!iJKke zMr>&G{#Ji5|Fc8uMUO9$y(>mif9jm`ll#I(+?O`pqjYg%Y*|~}J8+I?q@45^nVWD^ z_Tv4iYLhP+1f_}gtG+`^Q;^;cKm1Y7v#XS5NfQN+k5v`PdGb3Q^9Ey$z^ZpCb}$FXf9e}NIgYR z)8uP)k~aFKqnRYNQ6c2T`XHx#oxXUQNjwbD&Li@=8`B@>$-@^Thg}9^)6Z3EolHW< zM=a;tehy;2>Lk!1jkSSjn6v60p9bhdkTE<0F`FIh8F__VV3*m{&FI=;0&6S_$$PY* zL|O`t^D~4^a!L(pl7EzK$k}+@C+)0S+t%{2f_7xz2y~w&T0}H`-|EG3Gb`D=0#o4egk-eeG%f zaLM6oh1kN^v}*UysiyXuQjcHJ<=ah6?_^U?gkc$beiXhh*O;AQ-p7?2=?i~3AgDeh zZS7pFQX!LR6K|a$3X`U=1ykO1;0kl5Ah3-P?K%*|6H7k1mFM2n5QPHjmx&rOFH)0} zDpW=j%4@oiERB)QxSK$h`?EKG;5}w^r>zwe^C!jZ-2~Evm0IlPOW{Uihg1HUL99 z6zvXOPnSJn;K`lLlslwJ1#O4{XUbe!-=S~4V zZy5~L_(E^5)-|!B-e|3;{nl~Tpzc8Y3WdVIRujJa878Z=nMD6=9gM;mO`AKw z0Tm6=j5cxBKgtM*1^1yV_a6T!Rq&#E4Yp<-WQRlKD)v-qIt60Xhe znnlwS{GRpL3hLK;pXVLxHR5$EGz4e1IK?$0GLd3M`%g(*V||NC;t7xkr`+2T(9cBI zq2(N|aI!^?^wdqTwypIQ2F{!&=y!Bq-MT^g_+=`t#=-T zfZ7>VnI8F1zu#0OzOVQm+SjN)=Wr;u)x#DCnXDzp3aaYhIQ}rxv_p zL={9*@w1D}&cXoHWJ-laq`zQT{fCn&fx& zR;Jr-9=Mr`DBOWCWf>V_kj4qkvw^yuMo{!Z6}NDYhuQ>0Cy6yUPwVZ*xgyFxPmVe8 z#_uuXQ9GO_sID&9BND#HI$FeBVLw(+7NeaM6W%u=e~{Xp*75HWig z*@b08m(Lw(qJ7quici4AhyvKDEHT{1@c4yCEVx;4w0sBBN+!oi5!0y}mz@(iCdbNm zp9C#Dhg|R>KyZuLHAFHX7$^NOBnO7Ec>kwT@x()jlGplxQr5Uw@lP59MP@*xVuuER z_@z{v;s#~x?FuiTZe0)OXG@%s=e+e%Rn%e98A#+d%5ED&peo;zNiBy!s&XPrCmw-| z6ScVHfv;WD3DG+JvOBs#=VuJrW@RnDuMJcRq3{usca9F}#dW1S0}Ou*2zam3RC-o8 z*an4RnG>-0gyZq9nsl`leGK42{G*Z6@Wow*n;apC6C}Ug{5tk0KGiGvmO=Lt-C9h{ z5_y$jx0l|7I<+v3C?cO1=-PUPkYq0pew#?3EUI%zc2ct`_kCCSkWcSJkL|lFp&f^X z_T$o~x{XBL5-R}9nBa&p63-h+YGN|ts>Zs=vC-c#r}B1}3&x4_rE++2UZ;j<&e&f;TG6 zYOLqi$n);_-OB3o_>Yt|i00Pr67#MHk@3i~osYz|DbV9dhpf|ydZSsP%XzjQ-aI-w zK;!+=AaXU=iMBE*2t7O%M?qSc5(VJKjEiO-gVC94W|vMYx>khrlX>76419n|)?p_} zvO$d6m_XO!Ar`<2;C{r1_^1$Fa&ZKaSqaxxq>Q3cV7QT}UcLx(p|7dvwFzU5*K78Y z&*@o$-STBGBJ*)&;5IJ99L)FOecj`tTrc810S5F+ww4M-nPJ=HPW#F912f9hPGjHx zG%8J`!3Z9k!iL|%n}v8mVi6~I{LoqIt4)({mI6za@s2$v8T`~)KAOsSo$;;Bk5UY# zyfrX^048+VETh5Wz~$3~@JyPP&&$nus;SB$_SFfZiiJ^&B_p@$4EM@v(+_P-2?fj3 zHx)&YUN$3PAp4N$=qB}T7zSkFk9kdK!5lAm_UJuYSEQD2&$ev;4}13zWm&eh4LCD0 zgBiAM+sLqO+qRKm+qP}nwrxAZ`0M}f%|_+8RpX9o+*X{%Ii0oU+`ajZXYaL7IYJi8 zoDo%<_v1b6=Jgv<;NEl9%PonXd*OG%IxwG`+a~FmL}`fT(0e308nw>RB_AQ$^X~LQ zq{V#~s4CT(NLgFh0{kkFv|CH~G4@dA6_CRO-<*dMUZoB;Ac}W!@5*QPZ1#{!)(TK0 z$cQfOWW*9yJEuvBkaZkXF;yZxw+CXzLILR;mBE`S)K*)S7%E=r7Sn-2hV@NgH)6S=FbVX~&gPi6}=boF~6ZK8ttqch? zXdI3CU2z*~4%-K87$go>Iu$W+;(K&PGbTePbah2}^AKs7sCqAI-p!AFLd*_WBb-$H zF_wU{3Y^{Z6h9;F>bjWhK%U8ZL)S_tCb3aG!=hFbMjG0bIGxj%K93O&j$v(Zj6$SBo+j=%2ac)1 zm{zAO+jNIyifLQF*^o|4+A*oWYd{0X7@@=e9jd>a32z}A1&8al3tMV57#(k3X!o|o zvY$E*#&ID;xjh%cs6D(Tj7Y128ZqHQuama|mh!VZ^+_DjE~8pGWbVh>wSP$LdOiqSX4LH>#)9BLlM`Xpj?;0{CSoaAzu^ zBW^N!&XuS*OQB^D$g^yeQmPJajqUpbyKzuP5EG}*vOzJ{QLp%tFeQPFrY0puUk-Rg z*y0AQr8|u^nZlhMda&D}0ONR-TKPLu)lKNh6?ed08OoQ5^`wiuG)oaDXT&=f*>a$% z-U9C{mT_V^c&%&@PABHJ)%Af#V*)mr%;7^2A+;2YfXPu&t@JAqk07WrRhENzadF(Q z>k@a1C3kjQUb-|=5L56=V}g+9aJ1Y`spAQuuz$9A)Fyd;Pu&niA4K8VEYSwf4cBo> zjuhT`Co@BsvTz%)g#$G$CMdm*x)v&o^;69gOUB)c(1u-yf~B)f2O8<&H%lbjegVYA zw1&G9Nn!QWEF1TOF&Q<3xs-1M8#~9^YSs8ra0MpD_6|b^G{8}ZWHl+$nY9bUJ}0wX zV*BNiQd&z!h$`Ofj9d7fZS?UDViXMpCauv<}l za85Rv)5BY zWhHR}K8qV?P#jdy(kUFG%v}9|e6JB6&5wt1D?9AWNe>9*O!A|G!sN-GMB}7kWp=s` zO4z=WuP~is(eSe!ca=vxa4AD`JGGY*2L{DCcVZ#>lywzl6<5%GZ-A3MldJ`YtLGF6 zBdDQDn>i5d&o#t+%o-?b8NB&30*+Yz+;6B&ow^~IuTdYMeLXsyP@nM>Q{%fMKV)qP zm9FBoII=nw&uAJf@t*!ybWKK8AzAT-d6lFR$% zLzy`Yk!;N>#$ARK%=e5hRbh7W8wN|Oteh+hv~OZKTuy2F##O+;;VjpWaY%0&*@dW@ zzVwwSX?|(MxGqavm+^02pYMJ`ZX?cwNY1OD3gk*(Q-=ODHW1p9d>*PKQx#FEUj zpG53mfVp)jVfb=OG%YVhMbF-d{lGH!tvm|xur>qVDI;|WC(Mkdct@)(^^dpt#}3Pa zMg$hrTz|D4Kka7Kg;_ptc53j1UfnzEo)2B=rXC~5X&@44Tu&st^;p4Q9FbF^L=!ZR zK)8Q#i^2%g%})VOaz^0aLYU=4q;W3HQ5TkRAe&ZtWbxT=RAXGF@40`iHIjRU(B zXM2@+5ol^|$(|kB2Cf1q<3rtiH7?D;nTC_JBYWhk_|Yd4M%GnfL(`)p0u(na0RR zA{6n2Xn)==ov)KY7*aX_Ydh!*ApjsBCOV1yIcnWt@s&L-nGf$tM(i>ub)t)FUmAy| zuUMZlF9&d%!NXt-O*P(x3P*p?Z=-lDX{iYrPaUoFz2;NSp02Z}>31mzd64CVjxLi4 zx9$^;rP?cci?AXyT4L-YK9qI}rbTEC!KX?>o@G_!K@0uu0K((bbLyc|Sl4Hr)r$RV zS#j1e+h{4WP;S*w0}~tYx?|zO`P`}0RKNK&^y!~ARyV`As&p~uZ{U!whFZ5$!GZ>) z<4H7MR|0JMyHYx3*KY|i`+lmkdxT71SxNLAjytEibt|dD2l~llyD#)C(LCZ_a1Kot zHFG=jQ;4V*Q!gru)CuEQ04~`n<>&0ij=CEIM1aFxK1B}taSV}12^XeB_rq*}^WfD; zUrpedNaDEe=q;9#^RTOl?aaa^BPLM))ThyW4t6SX46_r)(U^J^6C2gNC}O9~+ubrv z6U-Dnk3?c2eyOIejGuO(^`mY03JKIVlbte1D+vl@n|G+74_%7Whl?ARLPZHH9orc# zd^HOm(pSZhJi1)t#Fx%vKWvRE7H-pi0WCnFA;+P_tGGrV{|Ggp-(~gWC^@ zy}WnTt7=ef-4Ys=zt;%AnoZgqBwo$l7!9ixt!5F1{qX{ywA@D7uAPMw@^rkFb^;pF@PY^-S{Yj!- z3YC=WKn{m1X^~7(&n+6MWp2gb)zW(bBiqrKoF4Ve4q$cYRo zA{FP~hUzcB`g=R;_-)rev$Kcas{HEx&+Y6-*?(teQrUlFXP*BCxL>#H{?g8Jep~pT z?2I(;&!OeR&OYqy!_GeJ?8DAJ?CitNKJ4tn&OYqye_&@drGJj0x_@tH3jeaRnIJBt zyDtOQOeBxVCE!h%i@_vweBqI0yvk*w;l~AY>F-PO@tbNJl6$vS6&E_b^tmi6k-&!Smt#sv6YQ_>2Nb{v3 zi?5QymwFZhYq{^MJSu~eJZ%ji;GVhcER{l6o1^R&ht!I$!7b~yXDRf+I_o>pp4Iaj z6KvCVFG0YxETHD$iqx;ma#L%Mb>U)`+AybeA78olszYGHFQMtcB2GgN-;czaQfh(I zef1ca&#EvwJL@Jn^Qd)cjWP+67JDO!e=hHr?(oD@Kg++-mBFe-1G}mb#7q`1*9t#D zBX{NS&2tL6MfeGl67ScAbR)HDr>N9ki^L+jlKXsi=4UgZw0MxfTdvPOB94KaW<27z z?jjbds3oOH70adq)A0;I+uX1%6#?ljPv)!ORx0)L9!Au+jJPrm?%Yp&S`&RkcrT+V z@X(818fK2Xmgtz50tYCWkz%n*t-G4epw`25G~Y(t#GU5pu?yS8<(WpD)qB2Y_@%Iz z-w2tGawJ$(Vfn_tOD#F#=D@I^j6DTzz&;B!G)8oDB>QVKrnt_)k)F;0w}(@Lh&7>4 z)Zh+@bT3!g@PoS?i=cg6CEpqO&-wkTCtbt<*BWNwSL6(44E?1cC04`c%cn+eJ9<6d zF$acL&QU)ZU!vtVrBFi=&dXr%uIrqjMTb*(Rx}Hp<4p9|oY1672cY-#!(qNL6!Z); z9!Xh*W;RD%;x|ytVn}XDYjn}sGbaKU9L=F}t@IZWlZ&gpVu*ITj7{Morg*hT%7Nxe z&f3|d>msFo6fo;h2=Kiazm4n1H$fvdD@^|zN?i69l=NuILP{r}eVR7rRx9YfJl#fz z7?wRTgQ`_az!eL>sR0^)epkln7cAR)yHtVJ$RBBH(Sfaw8pLhY-8b%giis&eO;)QOyv$d~o!&;#o6VF)qth^NhZzkg$|=Rt;C~FpqII)c$4POfkr}Ah@m${4 zNEOEw+*UI%uyQ0pZ%))Yex|2T?L#vTSv=e8WZCMczkRsgO_7!>LLWmaAD#_7>~4CG z<(^>%+Rr~945ROEogz&vxZ-izc*wBYh^5GXcM%%oWFcY9ForKW*t>kya90zn_eu)I zxzjJqWXY8LYVjs3=0P5i(rzNu#*E7KNUY_SMO*Civx?LZ70BdN`_v$ONK?aVRN7DV zfO)eFG~I*fhof?ikYorFURephR42`pVGa;~2FPNQBChHIMDNSg>FP7XE0=QhPC(Ji zUNoL#ZnNykjoDL~{r+l^tP-y7aJ8XIZJ9#8%p%*Ws0a9CrvS5?JpvFNDoxKejl{vN zZX-{;^#nrVD!JsCcr|_N6KKkaU?i(Ka%ZsCw{@00s)ODbYl3!4>wCbR1m!KQ)tM3oEFy~!#bOjCw)>WEB7w*|`b1w5F^hpy-B+22f zfp?bBnEi2=J95a17+}DLwkp>`bqqfby3h!8v`CInG*VB)a1Z6LTc52J#YElI#y| zpE0C>LL~r9u4C-QhQwZ_Gv%T#VI`mW!-lQZ-X`-w41>`QP8D{P-}9A6uw!#hB0}vY z&08{$XhQs6p4TE%+nT$z%bjc~5h$e3Ly>4;OW7-$lvvdcc** zYkVa=pbR}Ssl;jRooJ3g&iS~IfZfG>k9|yz(0e``XXu4Vk(I#+4*>b@mXe#`=|`0m zgBi-=u@BmP_v-xytU(o!HZ79+G6D>QS+Z4x?2CT0M%)$;QLiR=9dT`EHJ$Uuiud+S z*@t`l=(j=q%e?;H+o=BSTE9r@pLv_nZ&iNv{^#B{+4Nm5vSt`6k;tvqA2ZV#6c0JIFE8^ z@d~obWNUaamQt_rdHV9poD^8zUfy2X@0~kxM*WP|PQiD+0<+UJ@a}4$m6A6IaC?Ik zXsB)*BqH$i_d*AoWjU-vTGpCRsT%<%@IlfhGf?{q;;TAG!V)^d>d((KHUaI%jYF4E z2}(r6=be{aZ5e!WXj9?OZPM|IynBYfVu^^SkAstZ@>4M{%{+AEn-Kl-anrIW&mCFBXvxv9{S1Kw$Y{$Fr-Jv* z$6gvf6n|i^9kXr0?82X0drWvgLF#!=P=}_sisz-VzYVwfC4%h&d2YgKf7yq z3=>!Dedla3gPCfw%u<48d%oPVlt(eQ@!Lr~(fw>y7gqfiKe+(;?fPDO>Z!%8xa?bQ ztgkt~o0V^<<9en;%zbW+F6D6g;`T0&V`}S8u&(2&HdEVFs?uj%tZQwXZt!4T+|dWU z2mwn)W{(8yj$YszULR|J3{Xv>D-v9o8nS4qg9Kj=$!KbWDo|2_p~=)Iz|n>xDe}S2 zwKua{{qxVd0+^>OH`LPcA@}Yr+KO>u6Eat9dI6&%AI;{yOc~mfd{n0blUJP z6oOQLQs?A*@r!s4TM^X4olYolbQY) zYOPcsny=!Ag&O-QSMR2NJn(q2Y3I>*1_I!`X(36@Be@3H8fi4f6?N+lMnv9?B!3X(8_Grm#SlpK!r8*_YPl)BtE+H2{XEAPv2KYXXJA>0xYmsEr2< zz@gxuz4b94eqey_|oL?;y*UWpa?7u_Eki-k)Bt)8EZ6#JT#37F$k4biym%%O)c__66Y< z6#g_j@r#2EV>>}Ok(Q2GXytlS)g%cAifidCT;DrGQ8{4c z?K# z3hFanc2i%)$EM|iCI_T@P+mhkE*k6jH(TJW3->8yoBBLh))OykNBHYP2EwxPY#jv-(*WC@ zuxVL(W9V5hUdE~D?pV;|8tcsN2Nk3t<zQv73Db^ z!WkN_kL+1&vUR*ntF2Li2_#3dbGXG&EWPOuRH< z`gSGA$71A%QMCYVWp-5D9V_b}NZ|GI1~=-oElx9z_4Ynu zYnCCsjf#9M7J2k0cZnv5Vlp;GnDv)qG)^v`^_tqP_TK^p)3u#skU^H{YkszcZzd@7 zT;#wI*2zidw~F+%YwK0ghT(>{<5{s(uF~^y&Dn{}k8jtdqJWuSv5cBb9di=C?{hAx z)lv%TM0eqf9vQGISo^8fx8_iQnk^C|WztiiM_|nB+}{cgF*0}4U!WPQq~Z=aGc`Lz zaCYxu3ouipQh z(;#R6J5GbPnEC6YpPXHP7O=nMG@aiT{wGd58u@dv4^I2wv=2`E;It1;`{1+>PW#}r z4^I2wwEqF8eV_Sr45j&dPQ(8}7j!n`$)|86lNx3Wln zkuYLYK9cEKe#qz`mwNYHqq`Pg>@;!onnu(LliYBk1U8?m&Aa?a-epH#j7wp3LjLi= z6mc^lR{Zh$>l^xcNI^nptrKKdP`FYlRCfiA5BLThxSPUAeY}fGv4zx%eaaY7iV}N! z_-$*469s4=_WNT@q8%+^t3i+&bd;*dyzTz@mc z<{{G9PKora@<3LDBKIf;0fvjR+9^A~jUZ?rro0{E+?LZBYf9RA^?0%0PZbL4T}%wn zGN+fB{@qohtGN=ON&73eO(@6skdLkD$Awgi)6} z-@W}Xql#feSzY2`1;yh0@jUSn^q!m=X(m;vq6ZYsFh8Sa)~U>gw98>^@^gGyq=Ye_ z)fqQ+CI7uZp8O`vfg08y?+<=(X(;`xjZXb4`q@NeTh9szNF|injZ$H@Qv_f@a&%j6 zfDo)igMkse^_=l$8RWPM3o_hr`ge7w4P4=E&)n1K4YcRel*K%d)&^o-|r|qP%4yL>tgcXI9B~R`R?`TM#dSp+w=Wbg26b6ZD`CT3}r>hHRsW{ zEoLO1G%T|QiJ-A^_$cjmtqnSr2?2{A4%|s(eP}1E*uKvXvpfj0!`mi<^%CD3ZXc#7 zt1&H)-BkBHJRwd$Ncoisn|GAhE6r=_tS;1)HYp0#95aKOleh^>WzOYyx>y5bNqP@S z+~Bwz^UM=S;2C;RzU>6i@;4|F-!}wLe^&H;%VyQKbX8=hddKgtg~F>a1ZYcwvz|ka z=oR>uljNhsVM?uTpyJey{v!!_T>BeEcP`%K&B6f3OlIS>VyUhQ*Z}oh&{Y*b6Ok+gomM%gfdp;44?)glX_uPt6HHn8mEhy2 zqhz=pzXL9`i6S>_!fO(yW14U#%fE$3K?F1ZjR<*F@y zg|)sG`u^-`?IhQCy)O-Jfu?&&7tz0Ci(H=kY`wnEEjF!_Y;#K8cEx6U52*XDEFq_Z zY}tILz22TaHAY!`W^-_KmS*QFs8gvvw6=+Ep}#l1V-syZ5=ZV@vDvK6zSA(=1dADb zDgb>!1ssJ7wbkeMMrr@`JyF2g)R^4w;yFz{KeL3!PkX6IZC2QD--zIImPmO387Q4x zwT&AqqC*jUVu2QwqSS2aXc^j2B0av3AZ>voLDjbD`^9-E?-4>@^PKiB8}OCZ0*(t( zz~&@U*GQ`o`du$I83~x|28hI>uTC9T;FlXn*h-#$7GZ3GfIF?}YM)PKV`dv|kX+`9 zW(lJOb?&ruoIiutVo>?Fo?LYdCaB$*RA$($=z#nEpbetDP8R6R$RuUhbG&MNMwItT zx6$k&zU3S@*`5*J6ERg~*Z+9JKx)iT=w<5A-`<$mn{KkULj}I+S*Ku^r_k!i=hT3h z=#8Go%WfSKLsv&5wSS|leNn9$tWLe_ucnZJ2txKy*v?2LJE~nLx?+kGy<0{W-Y#Vo zv1Hv9J|W-f-BAb$Vt%*#%IGi4R@2w9Y?8~^>=%E%OD$ZpCS9U?L0TpN6syvfvSzS%h_3x}o=iPD zBU88O+NwxS_ZBkBbOpP8X1btd#cvI%r-*4(`$slv2hxJj8Jnm-eH6}GhYoWM@5=+O zRO;Oe|L!p`$k7;VmEkB^)K+28MC=7kI(_Up86JuhOO)V^fmSI~fN>wJ$%Jau^+r>v zyIGi7zgz2jwQg7ulMz0idp&FYZP!23v!B0J`PKWM z>zUWVf2U`i&VQq4ZvQ5@UpMalQqMAfTlk;!jA-M}vE@V0KJ@HE&p!0*L(e|+>_g8! z^z1{=KJ@H=pl8+le~zL0f3Igs|I)MRAkEQ7EZ|EWHSuOMKeZy?U=97gA-v@H6PSdO!16zN}}h{b%R4C0e^fN({4XBgH!Njzg>48zOeB2*aH)Qu0cR zPDTwl_GUD#`a;AXnq*p=#6C+;1H{BYPXd@YPp`7Ahzh*uO5ez8z!n+Vd%cKZAU*0A z+Z)4BH0*VV=1vy_x6lmCpo155zg(UyR)hFcRh zB~K^x8RFlkw?-nWdjeUY8ZL9PJ5-^wy z?iG&RAe7Xe-!Y1r{uFL(4b70=>wT_lgi;W=pb>8+F5Ek0iD7gipEtPkG@IWP3O=DK z^^{@{?_mGOEA=_g((hr&=6WwLxB`QfV7$w8sHIYZT%;Ls&7z~?Z85z;$cTenmE<$& zR;Y$H=@rfoSnnjXjjcUvICqelBOG=vGh&2HkC=NPvW=N>PKBV%NX$CLjrASBqN%Nk6Q78HY!w;Y;@rL|cFBlj+WlgkS(s zP#{hFttoB5qF`i8*Ux+SU!}nByIt%5X!rOe>9T13V=r31FFCRv7s0J(h|xWQ;A5=|(TbnVFaY zJxd0VrC=0}=E4zHvK>Q;5fIs@QEIsKM;kt@CG^2m zxUeJA7Ye2WZ^wXCz|Ep3&=Kq20^TcOfVxi#=p1N{!{R4!RZ@3Xi{bz zI>|uVM`t4v3*8PbNbQ-Fv8BpC{u@)(CP5$27#md(8>A7kTsT-Z29>6)9r)131;Lq;Nk0Ms}U#CG_pi)&FBKz=os8EB#12% z({8gEp2hOuZfgX(Q4eBmj~Sq*Ls<8tS{mD;wREd;wt|F|ydJ~U7T6Mp^j^+KMVqu9 zE}J$&BK+>IqG@4=x7BJg00VWUK4=`@dn?r1Hm)v{Z8tDxL!NX)df~2bjTNS!npiBv zcA>{e0*-7O`U7k@ae~culaOv6NrH+@b7|jwjLqUaKcg9$>P=@)l-d(wsa_Oj4k|z- zz0Oox<`DM&w7ue#^s=1cGvazClZ!{fQ&9?k|6=oQ-hKGnDE_5he=ly7|CX&^DD}_8 z&G5G>zk2_3aoc?Q@5C+B_ix1Q{I|>cOL2oe{Bw-?PvVwz{pU3w;`SkKAL8~QZXe?I zA#NYy_91Q`;`SkK{{wM@{dX|_71(9}Ufcx!Puvh%r;@$A82N~rzlsPpn55&C9E^X3I|zwKug2A6p@_;r+I2anMhfK>p{DTxcT z1dpHC0kJ!K4fdiOg}3eEvwJ-U|C!%ZZjmN0TLj|FP0Ixdxh1K^EHTW&c^CvJX|BHH z0Ox0{0||$zS6{56d0Bx7XYS%ys0GyKcQy&K_G>W|=Z)Z6PQcjlw~%q-yh=%httc(P z`sJ^@ubpTDJ&+GpW?pwxl-LWdQMGyO0qh}cMbB9X(Q`br8c*MEWT<4%9Sej!nu3Bg z!U7DQ#d7J8vJ~q;&UG9?7RJ8o4AB4a&=v}vdjW2Ne?UUqtKQ<$_k0Z`<8eQQ>sC{6 zzbc5^XZQ#G3b2{rR;k&OZzpP=_~x3y(>0{vPD{EAT#18-jx+g-7EjAsnfx+zMjBR; zMgzSMDja9#O``JS1wmcw--}|L?N(pIMB-@^NF5WR#lwCiD@b(F{RCG_JofDu0M$^h z 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

    efb)n8SYq;!8()^%KoZTfl^rj0|Q7kx2M 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 z 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�Y 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

    ;w|M=x&j!VNc!0YrN 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ð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%0DV%{1iMz4D})6o%a>dexNw% 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 i#OY93&+6 zfqsXtE*(zC`iK(SZdiCDKWU!JPqev{@J_5;+TN*?ZN5^YZ1aYegzxG-{GRf^@Kt?+ zKT-YzJ|Y{N58y98CE4aRER@)USL-eOmKuJM?+^TkpBH~&11x-18I=CZ3glm%Wb=`J z7+{0VAG{dfsNoC9rKK+#=hE6|+J6VXqgEUIY=2;}m#BmnOK7<1S&%qEeG)9ZU}@YF zJ*+4F8OtGhSa0)~yYfW4FWKA?;gNjA^C$duFTr!3197(=5r2pKBw{afS03UIv8DVG z?y=rRcu});cC2SR;uRA+9iQemtv|nI#lI*L`yM;6E_})ceGE{?)=}HR(-B{r6NlKf z(+T9^u-E)odGS2u0j{jdJK)_hfd)2Z@iDo>!V~3gQ_98z_8?r!rZgTS;gj-U)v`FT zML|hI1&I~jEq6i%$W;)OBDEymr=mdY1ni7|sW7NWi>`Q+@&E^pO0=0D@0sv!=A&26 zL%pd!93UrXLS^wKR0Zt_mBW8f7PKeifzO~E z=s>7Ez5@>s3JWio2k1!6A*}7!0?mN%oP~jK4&hk~2VFsXd{^y2S3(`|-?RtaxCT+C z2MCA5Nfmyyo*crP))VyNs+yD50*EW?jo&O1^u=zjmF-Ht-dKWrk|Mlpz2IJ4|9|hi z+yswMFc6+Du@C7$Sgh&`U*G_E09H%t?hp6Jiqw2-k@(Pr7Fra(wZ0&l@*b>p3Ex=- zSg79&B)2y#{vT=pxhun!`9G@u#lUf#Iwy zKh)N!AK-l$MVZOu9nV?#-o}$2uW=X7q4>E3cjEk>_0e(gIG$wmiEL_tN$@26Rkds< z;618kn}GkTmhD)Z0<7s({44d`%YF5L-QzX1M8{iH2 zi`KxK;7$08gl}mzEcRbs35$K1h5n*YVO$5V!~3-y-_~Y$GkKHo?QDU!;6s~D8{6P* zv^;|rx8Wz7Lm%dYC8P@#zIi~DPNg54!75^RV{HMOsY~p#ycLK#x8o7PXNH~5DrFj+ zMp!7=?SaKU$U=?Ix(jm#Be%~c6VAj_w*WT7X4+nY=WPYNg7AD|vf*s{H3vQnA7-rP zle!RINSQ=pj>1P7&uQ>+_&DS2Z+nK-a)0~)Chme*Yds0Xck3*^i8J6L);X-x;0$;3 zHJ+1=-~jjW3L|oj)z=;1CTkmF@8avM;ojj2{sBAjMhNf04e$?sj9pl_fw1p!jd#Ev z?E6?kqwNkkgpXzy5IKc+M(kC*i>LoLUXF+00e%R3+h6c6yc~O31r}a0q2p)Wt2m8y z-`yO~@F(pCsT@LiNqFVfbG*PqupXpv2#-Mu*uWvyoHu|?@GJZ=8^Bv?zK6$RFL(+* zQR_$Wlu$0UegdK$;fE3X`wD;7XM8g+fbeg9r1V#EeT0SIM|f_8V%m4jeXsiz9u`MayZ$3pyUV2IkR>r za*MURyg=j;Z2QJ0zwJAo-~4!T3gYRg#R^$TxHv~Gd_G0tA{@2Q z;wc0d;Cialo2o!Zs0O{O4jh>iC!_v08q}mUH?1$Ow2_aVIO7RcSZ`DqNtv+FS-l3X z^1jSqMr*;>sTJIcFTT*;%7^bJA9V|#OFbKyUm|tH?-5(h#0KDVX#h9Cw{n0r;{Z5- zHN7URNe9A#*h0Z95Dp}+owh33jupZ7tRxO*bvqtRpq2pA>jSa#YztP?gF$OnhWE1$ z+ZZfo#e6C?v;|E_ZAT5kKVf?{DJ2>*^ioNlW6I zf+^JAh}HD{UZf-vEtnTG^A$@i46b;iK)+Oas$uD9Sh2IEr|yPbHF+eykMt$72!=27>;K&;T%q zwPvwTZ7k@jrNqLqto2889t8`}htSm;1&<<5tkX`wS1^h7XQ6_%nqxBS`l~?*+5^*B z!w&(|;pyaR!hI5|e~lTroy0GLm$7oZpO^#mBbqh*{$K)Q(1=*EkLm&P?WC^RtfkL| zg)Z1`#=AY-o;y5;v*1)x#J)5O;05$<6r2Pn(dWgi>kD-@;WJ3)JQg0yD!%a8EQS}8 zcOf|iFTe`r`Dw>BETe7VuL!~CFpQP&nP3ZdC=9aaUW=|K+gouEnt~z5-rB zyjUk+4ll=Q1t-7>topCyIcW_GeaKz-U*^Jdxq_Xn?yqHye;sjaKqyBCo~Tf;h8&w% z)1M3G5t>W-Ca{h*_#O0AXml-wm*VHz2Da1NEu_o@+X!vNceMp160=Q9-HsPx2XTpT zB5fz~*ADC9^@KMPPQ;s#NQrbjM;+mgjI{6+?qamlu;+l?@N8D;=K!%+?q1@AwpSXV zeU#e^M9EIP1ygxr+H+64Ffs>0Bd$$o3QpjTPlhM++)Mzg;8i?ZW)zejzzJDa1!OWn^>oT*m3s;me^U~G+v6wSXtlL*yLlooC^**q4bp3!l|?*1gF20ys|_=Vm0BNyN94N7wW7;~{eaYq@J0Idh}6sQWlCPBl}qp?>V2&B<1sbg zpw{!G+y(!jIHj@&-7{2RpP>Drpmz0~7_tAZ16o`!h!MN6+Up(kFNqO*@jB}5Q696$ ze$7AGb=1Em<`pVk2Gq0O5F>VT)uHM2mY6rFbp6G82gJUwf3V&Iv0tyO{{#QQ7Fu1h z{v$CT(Cfm`3)QZVXn*nX*5?xQ2|X<*{%H3pF}XY)54fI8kc9%+XLeo_d-aMPdW8QMWCur@ud_!Jz-m73hiiO59g^r09P# z9x5#M?)^=z_WECpghbeptN)E{N9uRdztcwtQh$>ElabTuzt9sMH5>F!q<$m)8&@Dx z^B3y=!qq#YHd9US4D#snp)fykz2fF~;QNFM*whIbQ)#2*c1<{hJ0oTAT zq_2ck2o%&8Mi-_MTnXD1eHt&=3%iKEJXR4P^v9}Txq%|+y?A341#YOyRm3U=#Qwh( zu!@6XXv@^Z$_t9~q}XviLUHD)Z5fnm%IU2;{+86cW0eGD^ks=H0gD}iOMwz_3DV1x z?#WS-9#tT&B1b7&t3(+O*n=zZCdM6hr$;{2QI(@CBUGK#a&S3DqB7wc93I%!NG%PQ zrjNd)mW9hw(u-Egz-6dc?Cx6%E=8+VsJSFulHTN@Turzp*Ctf7`osP8jersLDzP(K zBlMxBqcRo(nxdoB1jV#q&;q5Np8B$ewkT4Gopn2)ndHw|a1T_cLde|?Zl`xP45a2J z=xQ~g}yjcBx( zLePSW<_JSqDjJ9wXZBPKL4PWYLugoqfpFUHNiW+0XM@=J*B@mmf4x0@Zcjhjf(F#R z&kzAe(9&L1r24>pP~3{79%n-&*h^jAu)71Xn{OZVyCOkf)RESqF_i|^plNg--J&z# zBAQ*j7(YMIpDV9RXaMMsB2`^NZNNZ%VM7~@2Qmu1=t+CZwAV)6$TtOX^hYsaU;9 zO@I@)S7NW<@$h)8cv7dq)37>XPk<*dy5mtrn*dMa+?votcp@V@0lSc40ua_j^vwEz zC_;q{iEtv;NHo=E!Lw+4ihhHskJTX>GX82d=h)4Lhwp*uJm)wv)z2qm*1O~))qQ#KQO2(KWt z0{yZ1sFuxx=aFw7;bb_Onvzj16S`(|2rng^3@4)mCX~*W!$QYwIpO(Q9ShJ@%t0^e zDfobT*(!3c)Re<+urKTv_OASb8p>P!6LP!-A5f}WjrLVz5X7;QCoTvi>9f>K^%49C z<)209o29@h^mh?Y<_35JaSMsr2yf&HHlk^^5*GStD+zCgH`D%R{UO;RZ`NDnRkYF& z)w9N6H6ar^XAQv?LUx83@C+A^?F`$owxiJ)2nV8jwwipq;9c}_3;9yvRIIJ! z>kN0s5+yp5Hw&$@9bh}@Yq*+SU?-tn?L@{8<)1~tyk(gxcT|4C zeSN{0>J1j^(38W~Aa)R6!1K3&r|%Wd(P>yH;JxL|d;~w@ZC=WoW|5bIEV(Of?4hka z^i=FI{S6j75ntdr{07dUz;_;qxbK>Z+!u13qt?S%VxQwL;4`%gmAcp9FP7NH_%p}_ z?@__hp(mD0nV0D7y#j~zC)E?`U-&P(9G_6L)YtH9%38P%8?MI&y(9yH)^w&0~%}_^?41Oz-DdU%4^7AzRHjf z$<3LI-3$*5?uHos129N`2L-ml@L+ubzJ){dBjJ&TcKi|;$uEm`{KDv|KPAs$o<1cn z(I1p&GH;)PPs#hSm+G_NEcu|kk6EGvcen#j!xQe{V_59Q^q8kE2hJfpif_nVzRhj; zq7S8A(W=mY8_aioIBKCn32r#QZd##MSp-e5R{YATqkTQxQ2Uz4_o5}rv}k~V5{6+| zf=lrAjzh;&a7nH#KWD-2TxSD*EkyGb+#_$0XYn1J!nd_7zn41dOBq7>p6eP(A0@XYiTx^gECq*bkHh- z@`Nf=Lp4xE({ZZ|SH>1fZsp)|SVGCo2ll}dN^X^4v8Qn@RNK5^Z>-VOKLORY>Xh{Z z713_9py*Z))JDP0j0&MYutdAC5O<3soH9)tm z7A&*`8&Y3wSSTO1KwYgF+zeedp|jQ;ZjSXBb+txtBf}$2XDtv8#A<`iT4T5|Rxp}& zO<VMO*^i z%2OX$=%<}SFRdTkkCYy8G#rfvTQoXXUE!{T`*SwILW8j%V`+j-#Py?WeYiex4H?TY z+7TLe-9UF*720<_K{piK`qFlH;+w)v(YI`lp3!AePt(u()Ds4WQAao`Z?SMJYD_}G zEeH-`{CiU-7LL`@2T(^W2qNcsVj6NSac~@W5^Y|_Yp7mm8{S2MFayp&Jt_@7rx)-G zO^55b;icg*smpLcK`@Z!C!fK?SN;7zNl@dC7(s$dCDLJO`uXTb~6 zVJi<7!;9&~csLnOra!abrSMYprk0>TH4UDIJ(ZrXK(li*pDZ`!rUX~ zqBuh~oQ-XP55b2>@rRGVN0_Cu42OAtvVf7$acVpa`jg|B;RJkwT-mgD3_gaPO`YLz zIB}1dWd_0nd8gxe&d>AaT%tq_IL5oxoi|Io-=}!9&(hN~;1u~9@^+sh{tRz)FH(Ad zGlaTwjwCgV_p>Lp27*SspXbPNL7NdS5bn#n7C~FR!3FpNG2M9wd&9k{HHth!aWRs5 zn(;PYX4IO&m+99r_!vF!g#Or7_$s4(jd`mR+(`>xXXd&FI%_I%UEnU-j3!j-6IWaeLvtv~`XC9e@vLbHg6mywCIVirhl^?KyZs%R&(`1KcCm z0ebZkyg`}uI=@iAfJ^$NJi|guaT)K;Z**4eO1IH}vPb>N33igcqYwAX;3|Cr_T)c--k2TuYbZyF-|%lkS?VZF>;>r} zaTh>2LYJuZB2cOEmQ+Q)4T_)=Hc!qE=SN%02`#PCaA{hxgA0JXsArW11*oq8idJ^u zgr>Gu7%q(EfISc%NIxB=Y^!+B8fEk3Vp5De5LK_@0xsVF*40F$MUjNE6G^FA|fVk|#$-5(7f z3<_6U7S*}3(g(wNuD+af9w?0LXL{yFZvq(cY|dY>KO2gn$>vG#Jn5T4nK(F3t|Z6F zAE-S}{%A-9Zc;_KqMRsKl-(HZit=BBw{)GdRp2VpHI6E%f?Wgua0q>{f4~)T6hm{( z161Ltj=onF;DZL3FIry382cJ<4N|JZHQ}11_`*h5=zSIC-qeC?kzNC?4c8{UCTxOD znlhM-j#wTb((6d2;8LW>j9^{3E^&3>bMQG*iZizL;CjT>h3muhN%5i0hFb5c(y~$7 zEc=6vvXQ#B!dvCdvWfC3aEiQDE=8H`@OC*xK1U5Z;hpk!xe*F-O;9>(g4Wzs^w!=R zE`z2h;sqfW5eW1k2&FX}AQa--q6XItv>-N6(`jppUR_gaXblT3z}AEt!;LjXu@FMR zpbZeJYpp>m(2VkJK`Uv6v_aYoZ>>5!+*A6Bs$);70p|wNA&v&9lN|!N zhTdqK{epj?3fYl9MbgJeYUly?h5J%NPuLlDrd$J9lCK|9J%m1e>-r9^3unxUq`snSV~RB0AGOPawkiVfDP_=~biw3JrH5nTvE-cvyTk63$jb;XgcmYfyTCKx8PqeK_U6I!c-m*f z^WpjQaSpr;UPe#%s3)Zb@B(SCx)&bDd7QLQ-OM%2<^7q<8?=v@BsfXhulD0!NAWB~ z@eG}$m4)y^YFGf9VKX%hMRzX-j^R#^BW5wYm>LT5j0}bcbI%u(x*y(8{C;&8Z`gjY zOgbWuVI+^ptEA)d0a9b617H|WoR}$Ef)+fX3EaiCU=r`|a^BGOU>$FGrfimjdCP<* zXB0gx2x7T=JEWcPPVVItcrwRMwEiZ8Nu*6Li2ycP6NE<0JlBZ)WSR)-!(uVV%oCLNUaaUJ`(o`al+ z!b7D@Fj&fhvj}Gqj)h}+kM@y%6h0~?6Uvkp!HcjKY55kB>ns=~Szrs{LA-t641<6L z2pz?5hG^*+=Wyu=e1z~3!d*DR2p!R8t0T-#IDDM&ac#EhE@jK<%vb61ac1kw z%*u;pPrhV}We>i23*^(NlP-|G_`d!%I7n6bB36~X`6W<gEOb0>(mm-Z{8W0u@s!dpz!T{uXTeXTR~%2M0ReC2pW?O(w+j@Q)w4SeT#L+#(e501Cg`U8BD^hhJx$a=s+9c&BR%96ZHULyaL zmI0aneoDVM|B@70fq!%UEvd2!|Ka>cvXkxLznuR{_Od;!gLTxqf|_JlmK`}{$~yul z4u$egAPIe98PRURwH%Z213 za1l8{9w(2NU13+bq&!(JAs2^>%ai1Z#FT|MffZHmC-CEf0NwhA5sDNyHrRn%ykz6zojCyF8DWNRg{)Xl2(?HC=C8cw(>OD zgPxV6Z{N5N1>geo!9^}Fd%~V_F+w(sS$W_o7sVFrNgbZV{FOXGS#lQRDt>V1ykIY` zsiKsJ@v120l`F{e;8j+ReJQSusjl^g{I$ZO?w@@jasyi#5yFC=ymC@Ms4c(esmtMM&XEGCC5Lw?P`)oUmi?*WzT^*@fCo}jxT)Mk zZYn?E&1)(@l!D~vQZrd_5Y}C(x!g>?OU!fLx)ySC`6)4Xc^g~GE$C4T?0fXB72#HL zOWJNEw}x92(@1V32gAWwZ8!(O0dhn75F$5_+tF$yR$F2twH`#$iwF=T_lA2D?g!>~i)mT*g2Z$+z};7-`B=|cy&16D`5z1$b>EBE8* zEBAr>$i3iRat}G2v)~?bH@OSpaJe&i`@#LN*K)5H!V9_c1LT3+*#RJm&;WT3JV%}@ z&yWYnv2d(Bolt+-8}`O>kw@`tx`6UL{S$aT3xaaQOp?9iA+oRhQ5ph1OGD)kQZ7&4 zPh22FoMh5m-ZbgUY~VT+Z=ha{()*POT*XDNzYt2nO&Yk8)UNQ(wy z23bd*)nJgko!?s1`DHboU!uXhEp2(4+wv@j@Fq2ZoA53zXRUFrrcFP^P>UJDPp-}! z5C{h{mzVI4hr*-(#Hz=j03WJFE-fynIpqfOQdEkT1zEu`Yp& z@@4r2)@5)>z9K)tx&kiCSLMf8SHTteA2|o>A8=K^CcnbE2L6$+%g?c{gKP2)`5D#? za9zGBKgGHUZpdfkk635GP5HijOMVDHlpo2r{8|1a7gj!lLdq8`!G)B9 z%2)Y|EV!UjMENFvl?4}3T$S(gH(9W&;->tNzsrK%lmg06`G+jHfRbPNCI6HK=U4J5 zzvW-D;5>?x@<;wH3wBZ*mA~>IS+JwxqUbmac2V*vHk<|LQ=AoB&Vrqlyh^TYt8reX zsG=$kial(v;Iic`Sg%NmouY8I1NQt(kvPjhp*1IRIMEvebvP62O#L!FEkI5Afr{-y ziF`oj>I+dzA*C?v%JtjB_T(zSH9G)TxG?=tV1+zIC?VL6TzRNZg;m-rN^3GKlgou( z7+@B)luvT5Tof)!`4UPoB>)akOiD@4f=!B1apx@9s5DSYaTeS_sjrmgEV#bXP$|P% za6_e@QkJvedWxS?j;F?Me#gnt(8j8Q-#aXbwQdgBO_1^1igsTHa@FHXeL;OVfPVPEKICaY3BlFK zRg3zn!c}Rj5v^5$tB}i|UQ~iB(LynPQ@?(`2N=vw+#B;P#+Q4m; z@k)ZyS_y`Ol?fcdN(daHOymfm^h6+PX{)q@+fheLxINsSI$FUU;f~bQTIry4f;&-1 zFx(mLOdTO`Tez)OOQ;e?D2zJV!Cm35)X^U93HPL?4oVNDH{6>#I>C`}Bz1I#L*Y=$ zcTxH(QE-$J&Jm^bgZnAnIQl8kaJ150>812n2EYT92#x{DKzN|ihhre6`v6f(j4}uw zL>*CZEF4Q6{opt_j+*)_gOwrh5b78J4~2(P$3Qp+j-mW8B~WP$H&%voG*+6xO_UKF zO_U%wNExM!RGKQy;AYBbj%G@8xVbWhqdBF=fML`)M&n`BI)wBw@EBqTQ*Jao8atNy zM!}=#-5}Z-0gu3rq2zFQICgXH+gNxkwKn5^PJ}07H|0K0fG1!#;r@?@$J4vUJQwkB zJa!i_Wr;Eeo}(;RHYtmgS@0}n1J)dJEe9*G zW>ImCX;JD*rY5|5-Gh5tW?%<7Q9kftE{Hn3V4OG25TkOTCf^x1ud=ttCS?p zf>$Y1m4#ZFh2)sYA@a=xNy;SZTMMrxMwj^a6yiM6kXsWUW-h#D|xUKM3a&04KC%jWhrNnk+H@sWfL1?S83*Lpb zmGo3N6>Ar~2i~J(5ZbAv!|7N%$hQ~XtE3UyMe1&_mm@gj(P^NMiK8%$~&TKdvOXNDP>{pH`X2qf$QBqPI(ExRGxF!6P2g%Q{^?a>>zbBcuVXuQWL>ba!;b>b>JmW=X!EZ z29K!SLM!{gCndk?tp0?5D)SUomDE4*AH_zsQx#PQ>r{hUK+UJlRtkW{3dyPsX*Q(f zQ}e6ylzd>el9ybI;l;`~mIdr6C4=8e9@Pme50F&{)sfN;Kq1yaV}%q))t;6efyzG; z`=Qvw_Sky$ui^kZko&J^zS#l%S(@J=#dWOqixYY11Lc3 zAH^AVCgrQ*qPoJaTJ43@!qi!q_G}3igbUKXo*acpFQlavQ{6~&BgI86q85jXlkN%^ zg^QA_5L^r{M!uq|yIKk^g;fkL374dF5w(O`8ZJ$_;;=jHPQKErr|JQFV7bHP;qsI# z1($=%QM!a$mRu!($bFor-BUfJc#!)LPqT-5SSe5L!%9WCA|=YGUg}Y$EIB>Z3hH;B z{R(O_@4;c7`(N-ca+XsYsP*Cc)Gw(u)ar0`#_5kzU9H2p4x?3)R1<8X|88(SxE|wB z5cY<>8LMAPRW(rkr3BLQ55-%p3D@NARV20n+<-QmsnG}a;VH8xM-9?z(B4<2iP{0~ zz?fE0yQ$6L=JdCO8mfkIy2T)@{qF$+=Mp1DNQNyO=(M+veeuS?nZm<)Viua?5}oId#V%FN$@1KyV^^g zfYl51RC}vauzG`DYJ@r&D+2UZ`>0c~`hW;EQcb{$1bx)LYCKk75UEC~qp_kuU$vh) z3acN8Qlr(8Ska)L+Fu=y)gMHw1JrR?13-UupgI<7AQ+&=sAI5Vz(BQ!It{A_h*5{C zgVf>haCL+ltHxo)f}!d#Vg|v3)FJ9%FbEz*`bg48am3P#F~p7K7)%TClorHauHRQfGlV>U=ek^!Z?+I-RrNh3Z^& z2Dy@8k#8Uwf*hef{4#B77NVQ(U4quNF7tQujX8lbjU8>^MzN~#~BHfk-n7FHXzmFf%oVzp9R zsMX+VSS{2LwKiNED?|-aE5ntsnyFpYMsOpw3ZZbdA>0rvoOS}>0IXc)vvOC-1$PML zD5v4mSPzv~$`$yEa*EIsxuGAxd30ldZxTkF2k3xUMTmKlkiEb`^p>TANU`v zH_ChEI(!}Lz4B4H3E#x}NSk-yJ6QNu)Sc=+yfO#yt{lKmgO3FpPZWOMB(PtdkH1Us zesvk1v%Ts*bsjPEH4oliHIbNkc<17!baf`kAV&D=62Ts|7k;{Q!T26WXg)oYKG5*r|3V;19_^5hV{fED*J_H})Z@sVZ7tlwDKZ3oDzy3a?ZX=$*xfXwA zt{x(0n|`-!RxRpo*@CU-A8}`@dXR-DHdP%iod!q9af-iSHiK+EB7eFBlkV%0)SJb_ z_6g(k&76#pcjHZUJ{Yn@YM3spcEAUNzlam*)0VBN@pQlhOX)kA^|Z2-&vERKR;6-N zUy&}q)K$N>Xq;)no@@TXKC-Jt`nWyUvP7J)`(3w9TU%(h<>X+AO)_X3WLsvXC%@XF zm2Y(++*jXWjLCkDw^8J;-7Py^UE^&Qal&?8HzoZ`uN9Ud4?6s({MrHfj8nag=^}mH zD!In*Ch?}nVN103oyQdNy%)A5>kn}vefu%*jGpElmRC17aDCSH4;}E&@R-W+6d8qX0Y%D?(NCBq?mkHxf8(fTgx$Qfqqdv=p!hDd)s zMNV)2C*Cw6_4PqfJ}la?#^Kc0el3U->6Pc-@GZChlI8358GfRyK=mts(;e@QuP)L* zUjFNAL!3Tfqt>70_r|B$BrHxBaU%V3w138uO>ZrUbB+J$f5oGzRr^Jp)vn*~Mrx|4 z(YX+IcllE(-!jMN+_6lYz5hSuy(u5{Z~1zZ7kO=W{ZDz@|0?f# zHn-l(hj%P9|1E#$M1jnsr{YbK!%I`2F5y|uj;va0xh$XC<1C{6w@&dE`+&U%!^ZCP z7wJxe4*EB)5mwLRWVUwgJIzzF=E*juAH%{#{)DiIM*fLS!YsFLvFQx|4e^M#On8}` zmHX5n%Ihj*p2?~-Y^lj1Utg_!uRo#2s@{1_9S*kC$}gXnWNv!PWEs`jRV(j)dZ4B7 zoP9=J>ppcUo^bx`2&3U>Gt=7E;(jEUZo5q~PWt=ZxHY=HR=!tIS99O&)|P`0?6vZF zZDTFFLe?9PWM9#)@2?qg-Bqo8rB4TqiDepO4Y@=a`j=U9m$^op z7)xw=x>o+DG2HU3TDtMQ!#=IN?TrP-T7`R>w);D1<$bbx8Rwi@XlztypjN(T!K3E0 zcRE`t=I#~wb!k%~EP;*h8y|VC)W+{;i+#ou;T24)=d{(zcR$?ISaiZ!e_i_#T6z7F zJLb!edRQhOsIQg3oZHQ^YtSoWEv1;&ezSY$jn1EqrU-|sT6ym_bNzen9+~yxk@mbL z4D-8SF8@2q5_jr8^OH`O5fNqS*6Ez_Q_LQ%{e2Z)8=dQRFtu9t%P8)DPV0Kcg>qrD z!zpX~5k6&#_i{JOu`ad(I zobjtv*0`zJNUi+r(kIRDf+8#p>vY!2um2Hg`P~1iG5qC5t^eMcnZ`Pg{Y=43+BwR+sP}NKeCE-W=C#iUTBaSTL;rNTfVfyoX7FrdhsAY8eF-~Htut0?JlHg( z}bFfahHQqo!F|(jja4XOCB!uN4_=Ik369zi8hlHO^8iak+8Y z0quQAc(QDTF?~a*X=K7@t^DxL4GxYil4fjwB}TjcH(ggA^d;P_aGG}gpZ>&Kx@GqE z3y+!4e6LG5aQ|t&mu@Cg#MD+=|NS>+o3Ge98yyDq)5^c7*4ga4d8FlDy#($0m7G2n zpA(ghkISE-JzYZSa#xJqx^^+O4A*PrcT75C-tN3SE6i0ZuXD|fF>j9_Vu?I&z5gC1 zdRbD}%{LD9+pm@PEtF%d?cd*2r`mk2{~2M;%yBojn*a@a?X9{GVI~C78Dy@x|?#T}SSwG8W z)%$!GYtf^Z%aMgIV^^yVNW9@BBa1G9@dP4aPPS{{@);C+L2dCq%c`%I^*8YV>0McYSD` z|I69Nni84+S7ln~|CQM;=6L4+oPX#4Ru#`0?XvP4H$IHi%IBoFH5Kac)jYqkb^d?( z=Csj``Ts{t>-^vKNG;1p=KocVtn+`5`74a!C8Pb=2++d^^IDZ z)-eCaSF+Ck*{465Rp$Shw)x4QVCu;HuRC|IUj0SGwDN6B9W?e~{=esJo&T2w^fnD* z{!h(oo&V2%+hcZ!=wrIw!#e*PJ{&aKmTutx?9u?Oyz0KoSeg0XeYbV~?`aA*<*%M@ zd}wE#|I6K6U|!Dr|NYHqGL_4nl=zY9iB=Km^Ftn>f$h$z!@=Kp(xt@Hn7 zuh-@kbvl@0R$J%)Nap`9hQh|ur>yOps+=*NVg64!ZJqyL*6d@-8)q>V53|ny8E&V| zGb)Fg=8Ut>|KZI4L&C3`kI#tE`d_Z%N@F1Nf9w|P{J+3&km(Qe|3q8s{9p3hV)J^F zo9W;O>-;~WZ8>9WyRzo7%|>eFYn47}yu$pyp`LaA-}WQYbdUKz>4kOv-+3_8?8yAT z{D5`-fB7rde|nxMU z|HgeE`oHXd#$3`bN-JNmePv^B=KmXGt@D4?ouf>FUM-DR+F9rSe&0%)yBDrxavp4* z|HBhb`7d$3n)!LF_5N+0KGm4Y{J-e2b^foCG}JVd`G1_wI{!9#KHfZ;`G52s>-@j( zNUDF~@9q6>@358+9X;Jxg!%tvW9$6iF?pzIKJ)*OC)W9Yhh>U+7xRCguGaa#REfF% z-%PXoiyyLXLq&E|E|pc50&Nq3tX+` zb3exzPcZ-2KCRvV1kVz^OnaFB!~UKB8yC(oH)sBDUBf#6-{{oL9D8lMu}O5a*1jPp z(U|X5nryY>HnoMJqTMI9%Y!jhkB|Nqlqdc5V{+oAq` zmtD2*V_3$}tOK3KS++GerhWhXyY@Pm;d3mj;05dbdF@`t7#@+wwDd)&_WemN8gFrW znpp3CS?&GMz&~bNyhXIPKPTRjfA8VUkioOG-yavR9?Wc<5^wtWu)bEl>^&d< zW8IAAC6cT5{q^N;3FYWBh{u9lwd^%b5Q%eo9O0_|0SdD!IGyC z+h%<}PUgg$Ze$$JOnN+18^0#E4%Vy1_<6pzj^CZjK3NsJ8_fk|>-hb>@%J{u^0I-y z-ZaSkL5za)z~0&3-p=+HuB2PhGQ|oNa`$#G<5AwLf>)7} zm3%6B`jqqZ@)VWW;H0-#?F-o37w~i|UahO%IhH*@k~aA@bPRq8*e^%3rFg9IO;5UB5@{c$aD+ z1FVQzhc^Ilz@Uek|0etiAvw4tSYc#hd}^_xe(Vgsvfx66IruZ~~jDNCW4n3D5m zANB7O*uCBJb8Y7y*>UUq)fUf|Z;v_?(Z=BYJk?TejPv-Z`46k^3F#2n!oGGa~kN z_x+=Muv^xAOj^lKmJL}oR$Pd%f8JnWo;SVnWVdWRGuNyr4Yo&rs#fE3r!nX3_8suq z9C0kAV#P1P+ozv@Chc0(`tj(N9-{`wEPD5=?cK}DRb7dXb5=gt^f1=#UP}L|Z`zN( zS^oa#5}%t?ZBk@%zce}P>ZF~Y-u4Nc7k#@&v}@YvC53W#7)@1%bS~uo)qhXb$YI_m z?j+xsnw4Glz+=zApicG1-fTE@XW!1X&&|GD*|(8HMtPrG-<$uemKJg$x!aDkZ>2kq zcZ<1b>+S8^>3OHw4a0r<`CrN3LAlcCTenl~kN>zZJI&+Rjwxv=H)ki@_<8Qc(r+^k z#eR*v^t;*30Tqgj8a<`%d&f_1e|017j5{~x(D(cswndtY9K73q`MYCx+Ae4qdt*=M zpptJte=)83zC7=yu@TEwoi=tTaC3Tan>7Uw&U+hK@kyuAjfRe`TQxj%%Q^S0KP0_$r3^R7pu@YMTNx~@%|nA2f>@n+@yUzJU%mauKsEAz&n3m+?<=ozJc zpLN4-<}j`mtbe!gR@Jyyu@#OUd1^Z*;Nm*Zq7zhi$s@K?>s2e-7o0F^PW;tKw;9z2Hrw3b z?TG-Jr~U3N$UXhR_0g;Jn*)vO{*<{Z(D~k} zJDtbwSpDv0(A82?j;FM}7IL^or82dyUu`(Lz8rgH-y84ft)t$Q$tgcFI&gIU=&(k; zTF2zi6EW(JxrSZ%$?GW|`9fFDo9W5_sN~#8u2U!G(wye|f7!L@={s-Y)N#Wa1kdWy zxz`Ha+F|3Ce~UODx2MeGHnCNMuAfai_1kXSAmi-p+&AGa9ZFm_ZtXO-v2knVR%4z$ zJMbi{=!?9$VZrl~5^wJO>VJ4nkGc*A0{frXlX+&$*~CpJdJNVT-dFbbhTvBvJC1oe zCd{_M#I+B;PtJXEVR5C`b2<&ayR2wI^SYbUj2@$7%S|`-o|3u9`&sXkUup&4X?5pm zpQ5(KoCCxR;}=l$`b6*N*9V*)Sz+eNS<1~4A39xed-d{m!;r%630He%+}Y;mQ+3-0 z$EEYH-R$}E;r$|WP7WRswP^gyS``)=^E^x0_1ph=?Di(P$wS)NU3w8v>(qMI1@-=8&h!?#x(=Y22GF{DZ3 zj7=$<{SUO7nsY1e&$_4IGIi1C&!0GPN`Jub`Jd0#X2(3bUMr?@wS6zQ96R>H?qji` zQ+_RY_hWfU)0roq!nQA;>i+Ou`qzsWOJwKm8$I~jh+pBuf7XrZIx2O4t=jvXG9&zI z#xMCbu6!QvYhRxRd8d>u8o%#lpV#L-%C}kUSJmes15u{%op#PE$3Dn&aEsGHo1gP4 zU(jbXPkY-tI;ec_*T)?TM4dR3Wyvk``Ic|Y-uRD}zq-a{k0zfgoq6WUvF*Q3*`2zR z_u4R1@tHd(+uR-UFumQWFOrKK-v9KC9eZB9xZiiNzsKFVJ7+4t*LT=eZTKg*$+}Lv z#&4QG++Nl3$lDEG^L<{W`CS|DHY9#nH0P#k-^=x9jAlD*hdSq>4YEvs3LIU7Q>p92|?}FOb)zxLe5*#odY(b1z%D zynAWyGR2B{*7EZ9sp{+NTe5r||Jv2+Rj%$^P5WZo+1WWdIJ!DHxmGJxtW>rC=l`@X zwn1m$gZW=y?2`0T65rVW`O0cvY?(hbuy^1)o54rhMvvl)UXlz3a*rilXZ>i`mkR{< zP)f(TR2x5UjasHb>Y;)mm)@7H-ZO53oqeIgu0`C+d6f6`s^D9rX06(F>Nac?*tkj4 zpk{5`weQfeQ|HiLy(9WW_KoT{c*xLU!$*u9HF479DO0CSPn^FXY2l*9$xD{5UAI1E z!^TaUx9moNH*Vf~_$cS`lc&#~zj*oK>}Nx-^)# zCiReAnd%|$3-*k=WM8PP@56E*#HDFh_W$j|Cj9@pvj1Gz|6JGq@vG*_+Qf=8KTk;X zTy2{e8ns$VIakYf^``*)QI|u$tWB_K9(18!^?*DsNyFB!me#Mn^e(_*sh6jVERg7eP1J>57NP%*weu5oLrWyB3iY&!8oPPzqU1bl6GpC`E4d`u>xO4l zDZV+&D{5M3X#M8r+#N3k1?noviJmrBm#j~D6QE?dgtWD}8e;FIhFw~IIXJ*!WmNnM zkG>lcJlCbra7ggIWT}#EqOO_e+V!^M16{I1oyuwPfeB$(qM|$+rMsamd-aaqj*bsafYtA=lWxnbj5PE zmrA*?y=Fr3K$kW)8a&spHmps$+{QMsYoJF|U){PyFHf7hFUD?8?|sqcTB7IEg#1ZE z*ZcQ9r>mQ&G^-jQxu&e0p-W!7h|%!sOIZRfLLMc0>W;aD3>9}NP-nYneo`CT*-34j zJU7_(oEah#tF*Wjv{W}d#j`~2rE81E%U+{`ZzTq}1UDD;1Qz$2=2bVincUYkxcTMT zQxfbw*N&H5f&;*<1pCldNo{PFhBoumrL12o(*6g{LhCNodBp}6-(=%?tdh$%+u%T# z<4R&PMqesd$wik$cgne>x3TRx_sV8Zo20gz({*kQy!!e&My=oIHo)D!S!gp|=zrCi zKQXigL*vRlOe%48-`A8cs}04yg5Cv|5A9wgd$n8jR{_2W#`G0^Q|eu@@l1Ky_f1p7 zx=oK}=h`Idyqqc(e{Q36?Yl8#_-ezC%OTHPrX+BCUj*b?yC9>|zt3t=fJ0-RmH@lv zK}$n*VIh4IMm}BatLwAa_jIiP5BA?pbaH=|Wt&iFK2JeZ6PFdw%e&}a^6&3_{*NpF zuRe?T;*I;Bb5Xlqb!%2VAUinVe{uCDP)(iB8}Lm+!XiCjYP$M8qWC@57vH*(KHdNHoQZ?YxC?t_8EnVDx^w0}zoQYrl5tsyx@%JypuK;{+DHE@hBSkzKQ3QriH z7S)6bJdLi6Rd9*02=u1su&xX#EZn~f58q+kggh|mM%Y0u3VYh8U`S;(S|i+-1N|A? z2{(@I`S07ozDQFPtHfUgR$B&N}08d@{Mut9?qmQ)|?I>Pgh5=(H&uP z2{BA~+6RDuC`zxYk~yOjmG{9^eZYbc@45s{mzw0>r%3rsi!4Ob4_&*@Wl`v3aol(k z4tTx{Ns|f*6RMa|;DL%1WP=1i=NM6>U~&~mG&jNMIkG-WL zL47>-0{LFHPdGY5X}2Es`P~0^2g>rausU`WdL;eBCIj-nbISMhQSL4d`NJlqVP}nf zf3?8p{1K^mu>4btMSU!4qas{@&_5)JNb$BpuB8)|3E2Ra zBC|m9@s)yX>9)5Pc6f`L6wzlcwQjQztd4m`U&dAq;ZJiP`~Pp{2fO~;k2U`X^{)8t zp4Xx>(V%<+duCw(X;OEwkVhtVbTYPy1ayJ~-$1R=RpSXi=z=^L5>()ezuQJYZ>*Ux zP-gDympMPzqWL(IXf=e`cH+NVjzbzr0rxV|DvZsd_!WGX6>jeJf|Va-2RWl1jS80Q zP?-W^jNwp=Rf&K-gH;&v@LvdDym&Ey4D75g-Bl@q4JVmZF$}AK#IV!93IV*UN@3#% zD9a`R_>@h!tDx)fcmfL^4k&>;97AICbO2f5F!-dJ(Fc`t|}G@2oM|* zA%qwLe6EH7NWvt8>uBI}#IE2J#R39Hnu9NI`XP7`EH!s2fexTWh=J&^mkmy!0p~d+ zXQ9Y#k&9_@ow{N=J3KGBDf7z)J%X7DMcLUCSU+5>jSp{&{W{? z2~pazCz=~KAS3l;3ASjS#V!I`qj?4_1IN;U{|mM#;AtG7CL7%hmjlN7UzBICkx;=R zjn>2@2l#}yO@rO)&}dPFpjr(rehGnTgm`2?YF;PH#USejD!mUp*Nm|ow&)rp zm_fEaP|9QnO_b&ueI?gWNYIL7`UD8WDq&vh){t$4*UQgt4;?h0zUMnvDEs}0YzZ6 z45U%HNz;Qi))ZKU}MAuqieIH|^xh%Uy5czQ1=h$eC zr~&M{0@yx8Yz5uq23rsuBLObn_|ZLy#eHlbusk0AOPe~uEky!iuLQU+rqor)9HQ@5 zV>D#Fjal_o3dP3@qeYu#jux&O{v-QVV!O?mfSkd6lbew=Qzgg>lIF6eWENY3<2YnY zsn;&3DU4)9N*ZO;Ilv^=lhB>p8S^FBT7a+tU|h)J@gk+!`9DGx2dhBWV8CdXIL8*i zjTM_W8xgOeT{tw7-9O;8Wq=VJ$2wQ46p5Sw^tEcTdXuIRau8tX1bo#zE^3G2YSgwu z&cw)J;F9c_5R-P$f{o}VwQZ&%VO&6b0m}`k1jL8cR#Bz`5s$?bh%zf=9)I@n!H54g zXVx{qeN3cOV*@Ejc4L{i5TWZGBzgy%9*2~8^DdSHu%`BBJalh8h{36UWi!8fA0>dtTOJB{)8QTguEzZ{XrmTS_SzL3I@hiW??^K$6<0ipPzpzvQ;rfyr5F zHj4|H`{TH5qB}#{s1%Tl0iJq+mz2HW5UWtD8-j#j1ZU|V_Yd-uGBU6pgaMfj+!I7E zL}ZcT;1vMrV+tKn3r+65Oer%?#Y32E54zgMrFC(|?nz~D!^KfU)%|jUuEAi~GXNe3Ipj9;d&Yd=`Ir)1d#J3B15seDS+L_E zBvLj*im*Nw652G&tN=h^&`pS&)?FmzkS}RWK5jsd_*xwiP&$}3A?|P%{LZK*_g4@f z5hC2w2u^>HU|tw-J*WGlarLSwHsS%%)Lpa=$Pkc&LfpO0LN3c85quXQK?T_*ASjQ) zV0)$m1rWxQ(GiIr_==njR1w{Y??6}$HB3GcZB&Jc6gB~&Vpw3{^%g{Hf}I^<&^0)* zLGWCcz>Lj;4AVXi=kNh&I?zSDAVCLDjT!(pkj8e043PX0eM%+9kGN}xUo?~LieKFx zttYsyibqFGC=C`M8a@};7P6qsQiAo8_!$08V1aT1l{h_0-N#86iOe*d%dp7UAY|(Z zL@NGUbHnqW|1l}ixLp95W8;%7u2YizSi|7LY#yEvsj7j>Q_vH z2Y3vQku)hNC~#E5&xP)0GhiQ{j^QX75Gd^cfQeJZ55ZzWc_SD2if2>8N#fD6UjYkXJ1coF8HWCe zLm$Hd9-r`)b=48g8LAZgq0hg33wIUX$H-d>99_uvmAK+T&kF}AjaH)ruE~XkG^=BRZ?Uiq394Fk~uM~KH)CpqZFTo+AtL`*j#Rmgc2&2>m0H{!u%GhKNtKm z_T1sUb@ncyAcp*aqcm;ucqIH{)dl%>I=5zoAVT=@fm+CQ0B~FA~ z9^13V1O_ott1C6Uh$m~+4tZV({GTBc^@4YiQHK;8Aioe@4-KdoRy$z=+Lxe?Ps!E+ zv;&-@UD?3>Il$*}T*pZZU0sGR5hMd*S3@SASS)dfisJyAi7f!X!pm_@SSAh~eg!z9 z!N!=}bmm@gwKx`aj2!@+qzR}G$pID!-yKOR|J80t`rT>e!c$Kk$Jb!Ci#UPuU})F6PD zaDi8@ieU5{!=D3ekq~m9aT|b_BQvC7qDuadY~uK7xL8Mk77sc?DehAxz-wZ$TCIje z{|K)Jhj>^#pgA(!HUa_`RN)LUm_yb+<3o}N#Th_$+~Ls7T^yoH63L(jIn@hQ(XjOLQFp*gd8JdFS_HS~Q1E8N-1=&+(MfJykTHL2V z$gXP9#|Vm-yt?QbU;}s|PvrWqSD!(^mvv9(utUva*YoUf z^tON~nw+4~kT{K174i~H`5+#OBM~A6FaEVU`uhZz8T?QIX?PM(ApJQdeTssLItD9( zRS=4WEU;*U09Y$de-^%gU;SU;|Hz6pzNHKXav4&6y4rS~0?-_VjIp8^ECtvM+&vNS zJB|w#nI9p|h8(c6}0-0V>tmu-M^jUe&4aS%&gmFbY%`Yvihe=Z566FQpErw~m3t^PCuWQ?dc z7RdKOx=Tpw(C7thuaaRdPl6!>X`_iDZV!8j`MRMZtaeadir$Y$AHhvCG^n#N$O#IH z<^4dfaD2evGROgbS#-qj51m<+fWsUhut5p%4orpsd4pt7=Eh^tuK|-_7)Y#1wq}Jy zPk_R@XgmG^_)FnwSRfn<7}79dy@2#Ro+OAM?{~8B89Ew8)=Tx3xc8F!bwXpz{_d>L z-84by{X_@)t@tXRuu4=+kisH68NmN#;ueM#futVloCYClXR$DjLs2DI4N3&)^G<24 zP6iofvs^phpE0+KFd`ueq&HjlZ~O9&-+>QrUHosKyFl=FerhFz>K#f}&M0c2B4Lmg zSe%4$Y$Ab$8++UUB(_j&E*75z#v4dCBEEEEApI9LWw6p++zfRo1usWOL+I*0cs?9G z)Qs0+7L=VU>y>I{BN751Q6AW+C^^YMb+@8_FJTGO0u#k9EFEwoq>@E#~UDRO6ZVOjW``k;dr|U}Fz0LIU ztmH`l$^F_CL`mB+%mPxMCSS?04hZ9;3&ZMo&>a!WzX4_M%hp7&b6&}S|!b*BI3{>dEhZ>Nr2U zWXg^$6?3vjroR1>I&_=MOx@5kdqu?C3ooypExnk#bAOM=2x3~7`_k#2d(hJ>{~*7i z6NkUt^uq`G$&R|qtap27ug&Yp`uVH2mAA`U!ipmI8Mof~^(+1AqQal^vtI=L9=_vn zR<&^HVEE`)Rf~#vrHc1Guhgke$M1EOGH#w={P0`egr$z+pKQ}NF7f~0$ro3VPj1-% zgKSvxT%FYzp2M5teeHtk(|d%#@=xA<_qG02TT*t{{IaMgZ1SD?5M?3E(E(}*i6rlu zBHYB|6qJSNZt;s4Ix#{dzNk|n>k6V1FtdaZF0!mT*D{wyY6+>_I>-;a=Jk7D%?`&M z%=ZlYv$Vf7b8W?`>^G&~AN=mrtoNsvoclH~@6OVvm2;o%y5T+h?CcqD{Zc`;zyk=l+4UyuZh7U9@n8!@k|_{%`#i->Iz6 z6K+lXGgww~&Esbt@y+eyfj{=nI(?~!$XfjQKgeW($=O&md;Y>Zc~8DrdF#eVYs&4v zoL|ukXpQ~VRU1*J+vGFNZp+onr(XSI?Y<_(((nAPHazI~@Uy(_(8AU~d=UtzPBwk0IR>m=g0_*IxH zMx(YEV|0fA3`f=j1Zps0d^(LvQLu2oWRqx8U4s;=yFxBUtuUOQA8+e z%n-FN9q%eBS!zni6@<&h*=T!EhizN3YIOa&OWUud5WBB6M7Ac1{BQcfPcd7WX3NOJh_ioRj|%Iqez zEAf5;l{FD~s#$`BHs7$+SOaeh$X|>t^;kSUrkR7K8O+jLa#L`}i-BH^1n_j=X;myZ6U72cNyRDgH!d z-!_M#FIHR#-j}z$%Wrz%2~K$%O6?!_5QzSIz+A<+{K>w=#%X$31eEs)ev!^(P@I+e7$%nZqgL0Jo2GQB)H zk(VZrKD5qHHO^e_Hm=spiLo0z8g?+m`|i2h>t?2G8>@)C9Q6hz*M1V&Qj(Cyk7Tl* z2IU>47bIt?f}`es3%O3?q4=sGi_{da^Ym4UpxDq@QQhw8K=s0IzhF(olnvv+slMly z^C4l`{RVO_SAhholDFZv)+FguX zg%T&UT`C8vU+5m+t$qP)9Z#0YpkqLEv^-1|J*D_1_i#$M`E##r=3RVXzKZDm>(Q7{ z>1XQu>}3~DB6--m>T}1^Yq_ZhS{}6M$=4>EmvGBW&UrV zW9z2TVfR7XH@=45;@g*x-QL7Gl{@%JkKdIvr*Yx6$E&^@IaT4_Y3=zy$$C0tn)UZd z%-x@fzF0bwu=>)Kt4+__zOvcaalPF1{)cZYmnXd&(i~V}^;%T=`u>iwBgfmm@woK& zirD8ae|7x9?M#1)##S| zaWx@$JaY8fSL2_&4>_5;;qsCn7r8`n#bw!&oW!*5V}q|E&&@gZD&l&3Swe$ipqJrWd19)J(S}yf2j}J)T&Fw zjMkGsu#VCtbR{j-!qUr)Ofsg*LC3s>}ga=~o!)_ifj#=7EE`9Rmp_;(qr^}pTN_FLU(!R<4} z4^Q5j^8SLYY)N-3^R$bvy5!D^?mxcnyW#tb#gtR|=fvxmR*zI~KAti-$hD7j+lQ_i z{_RYC-TJ}wB|mO)xxVsGYJSm~^4iX6+V#I*7mN>jNa}2yls2p9jq2;oQ4=ceI<-Q-`k;eDEnBe1A%#rAi`-=wG}wq#)0Lpa zD;nL{$MObkI@H=2^LOr)G(XzjqGEfu-T7sv_u-afzioJE{o|DA8^etww>NiOEttfk zPVujP`yn|*dw#asQMtjc$L(kx;z5qd-c9HlmC^mrpV}~EcXsR%-Qko~*~h;ly!kUr zsxFtlXedb9-f}UAQ}xMei|7fz)6??(>5A9*lD!D#81J`8wL>tYQ`0Qwya;2HB?XuF8tWAy=5=t-r@zPJFc7 z>1m=O_>WNs)6ib zR?Ync^p`~RVurjC`a)h(DI-h9qoOnxrr7se$O48&M6B#lHAVikZTabVizDlGw@bcV{qQKU++4pts-?-z&E5Ko#HY!BG+r?j?0)hn<0(5wb?W>(>8X%Yzuy>N z{A$?7VPEfz#ujedzHHI$=aJFpe>?N#ug72}`023l z(*t`qJ^4Moq?-63Jn2FBo+HOM{1&US2v%+h;t*r+mR#9Y`$Naq8wCir2BpNan8RxH}qtEFnTXdXr zjAEvkw(kjXn#=M8|MTt12fybS6cz1B8~LkpRC{$&mvmC{!-s<>w)(1GZ|hS&9&**# z9{Qp!_vmfqe((NSyO-RJ95{UcAA}s6Prh?M^S~1C9ozml{AsI1aPs}V%lSf!i=Jj@ z^^7OGx_Zn>*fwX@lC^b1<-FfGMFSz62X;;09vzm*Hu|si-)3zhb#e>5Cle3c*GRg< zk{&jD?C{@rvu^jyeQJk=wvsNljNav`{kL-O#ynKrT%#`gIk@4KYx_07ifz5qm{YHn zAxEF5xb(PaU7FnokInVWS8w)b+k3R$&KcB9zBk@N?B!obZb6{Z$wai6GP4XU8ItBo z%us}vuXGhqJG1mFp`0DfjcP2HP?OJmRXIa<>||H#3O}v)U@~JU$m8twGGtf~b7OYW z#jR><&T42f_fYXS3&INYMDOX3I{pgKyz_OvlZp>HdMvIp>R{>8r~e?z@mxlPC+ zR(JZflgv>(1FJ%-4cs5~|JfK#Y3)Dg>g6=ug6sgAP(k`(~=N;@C;#hUR^zb!V6k3KDx&)!IEONjiht_|U!m6Bp5q$EuD+=+&)w7wH*~F~x}9=j$CB*%YXWk<+5I zCeKFMx0z6Bwotz-QOoboSUtD9RG zbT>D&+lA>eU6kROqiUIdy*ngjwUp}iJEKusmMbW2_uYHa?I<@n{V3O5wm(}{pSIs1rl8^^XA7W z%%D<$WO!*Xku%4}S3&jC2x_%suw(MZ&YtK|#jly~hvqE3_o!r@%i_)LvsO+Li|1wS zbxe{C?pnJqI8iJlCGu=~oZq!9K6q%_oi_W>Q)T^Mf93f#?uAdGVULo>_wP)w+L**dJKfel7{1Z1IJKr*1u2E|*cr0F@xmGB1b zfP#R6A|l+pscASG@q?n`lJ;feMMagOdA!}K@~x=C`ORwcEKe$50x*6GV?t1&Xc4Em<#lgfY zQP+G!MG6U~?v3-{F&dT0Qx+@5(sOdWGNVq1=A&v&0Cb3yVy71(M)NOv630GDuh>f~ zqpdvvnnSb23D`*=k2;?XZF1iliR*6bm(n2+=`Bmhn%1If%&HPGE}m{??pprPE^PKvlL%Vr#z_Cf5xilF?jwXnsX5pH&y{AH42OEb4c@Pc#1 zbXm2QUu0a;9^Lmdjgq=LYIV2j^ztJKF;dPotdCncXRY|8fMJZ+V=mdVFwgViX3~&4 zzB0r!)Wu1^i(@H!2Vj$pbxCik z?FsspX1RVB%bA34-92dq^wcESh|Rw{LZn$O30S{cv+P_`ny7u*P&w!LVB;)R?OQ89 zD&Hw-zfe)0#i|XvE;l!pWMvyJT!{3aHoDxwn!wn5TxzHFt|5 z;*otBg%G;Kpw@^depDkU2F5gN1V3mWnTEe+FHs9t;dpljkm1B(OgWoYx_&1#U_ zXh7pcEK@P4&>@5jLBph?MHTYmgPR?8$K;AtQT^rIa@6Rr4+*3XN9lt==T^Y5?^4$( z+bI{9y)iAj?RP)^^jGsoXVi(gKTpQ9iUn69OxCBG>eZN_4= z=w0fi8SSVBSAK`XC1@YFyJ~w-BwYqVMi4lo1Y7{N%_7sh74PBMc$|hNC<5J{G-v+b=4{0>6bg6bRrFL3pn;GLbW-mHp$(j`ItBg}snCG5w@qd|o@a1wRMfz;p{sw=qL~%Ex zqR&%L5)Rc3H$Ta>9>2fB#etCzMJdNqU)Jz@Iun_k?MX}2%qpc54g1TJFa9#TV%3(`-|L6UdT-ovPcB^Kvcgs0 z{bwkqnCX4*cQockh!>&Sh2l^zAYX{MUf9a~iJDUK9hvEDp3GABdI7h-3oAb}0ll1! zU5LQlcMofVK}$@+Wahmc1pQ%}zo z`JbG<;>fDi_Ps&auG}v}z3bad;?mXi)+aa9;`vhx=}-;TMY~f2r3MJv&_)3p zl{6$^4Q_u29a%|)!p}fDjV$~_lSr__`8>33 zk<$`k^26eZN}BJ+g6lt4#N?=6cJlg{<^G|1J!ikr)3e{@?k@MM8-Lc?A3XgiC*|_* zLAo=a&f$OVRkI@gr|F!lkAy2`S!j#*N2m9>v^Dvwla016p6#D6$#3{}@__FA&@xA= z`0S~dO`iQHD()(a?i|Ry~_7qxqyn!wpMC8pE=DZN0oR)T=zk2hZUAp+QIyxiJY z2UrfWG_?)Ztyh&ayLRhnxwJG0rVD__L&}aRYeB@@7lk+BrMTGJL@84t!F=Cp%)+wc z2U$vDJ`y=A^yoDhC`I?WR?TkEl{s4Lq*vVh3ajT#6n3S&nYGX__5@W{-4>_Cw5sKqA-w=-;zJxC9 z_%?CGkzuiT=aBrR)81+3h95?@C5^OurV8S|Y5)+A-wLnkHpizow#j33#&LYIOjt7Di1nJS z4xdPr7U%HzG2Jy(?40z1MPdVN2?nH~0W}KSu7qjL-XOI@xcOc$L6Hsew?cFz!TNIw z!i|lj6ZNMpc<0=ov>UQQP)$<3PFw>R~E#A9pMPs&N%Cqe9Bzup=xI*W2Qp z#95s_z9c4p7EyyK?LPO3c+iIRGCLZTFdj9fTEz$gHVSGj#}t@}yw!=IW=78_cR=R7 zR_9_|*)1(L5P*X7XW62_buIGdUxun9Ua6PWek3rHFoGv!MxN5Hq21mfC&Ed0{4yY2 zzgpxVYzmaZ8bXI$-u#kBML>hYUq+2sz}Q=v-JR20 zi0Q^)<<27(Y)LC4^puIz|HTq6RF`_j;{~#6<;zCtaY$EIGt zG5#TMLe>=KJ8NoWWtg+)E8R1jex&p3KeCdnlX6*MUk=QsMX$Q_&7^{Ft9f^x#P68` zz5boak;9t>oH6T>7P!AIWk~q;=rbi&!h(@hE1@M?SWUuOj989?yh)>pg??*3z9*on#7Bo8pdn%LRL4}llLwYv)n8`35qBSM?Y9m=BP17 zJZBgXrKmg#rXE4gw*bZxXDA(0c)ZkJ!YlR5n5`N$r96I?OCULDP&S=M^+Ich!k^!ikWL>z zW!qnW%CGG zOSBc>k6B&7%AEPWWe#9__F$7;stj68R*6c6w#QuKXX-YSeHrj^aJ;0s)a<2x_5NvKo|&ASmoXWr^oh>?Nq!X#{2)y$U_> z`eqFZicn+&BV61vQ9|f^@+_gLo#@6@XRB^-zwEZCz}&~`9;{2$c*`9% zV+l}A66I-)zGTvrVtl~P#<&oBo4H6$ge*o4lDq}DesGT}O)sL^ERad53q#dwyDYns zJT1EfyW?rqAx>G4AjF+f()L5K%I0j#=A>2HJFF=~_%okcFL0=#3;f;9Me1eutn${5 ztSwnKiD#-BDfKk@L~OT6kq>`4cI&h`E5i;QE1j=@9%5c^ik|E6z(ydQnjNs-_o=&R z!t&qmZ71hhq)ZN%L}@wXy6b$h@0Yc*x&I)ymO#(x_}0vjQ}3&i{*aF9oB^;5z4*dstT%&zAd&kRPS1g@tKNk1C{(pBG&z)KH zzwegqcy!3?yZ!I>ybS3*1h31l!=FWulsx2(rml|5J!F225zrCwWJ z(tX_fUQ&*ls3-1R`3il}rIRPXbZjC|8mf)-pAQ3V1s2evykK?D;KTe16Q2P^M{H&m z;K766|3nmp5@wDU228csuam% z7)Xuwt>_I5t;6ghNM0nPu~{ESBVgKB4ekO7G+~mtY+Nr&mpkgp6FtqiMQ1IIWOU$@ zfMCz%@!kzm4IF0x<)V*yR_z$;LK7--W>KH9ZQJ~`NPw5-5*$6igHgt)Xewq=sU%Ld zMna1{B(Vf~R(95I+NV~B3-?=YwK`evS-Yx11$;{MyL$O-YMg3+Uf@VN{BWkpG`*R) z#(M8MWkg`LGqi~)t*zJnJBf2iiIgMD^+g)*_+k-l!^qOR2CCg?xzNQJr;@6*-t*2? zI`BC$S@W6f%Occ&NRv!dFVfsSf28qI?z9yyp2l^5J*6+)V4Ibe8$HWht+@IwL$UaV z^>@kvINiae?sdO*+5vXgkN3nu{wD@jwG4_R9lysJMC(y`NuV?}b?}~OP>~WC8>EI& zjEy1FkvG$j(* z{EYRWzq&LB^wS=6IE;er{u+cy=wXn;8}ZW#C@`8T0;91TY>Ld{ec^zlX}k}?2r{OK z7w^@0mpNjGwfK0!uVQ|L1tw~u;~*qceHfr#r9w^PP&0znHi0afkk(xRGd(h=SHoan z-x$stiPPh;KNv7?hQX8rez;4KF{sak@MzU}?0NxB=6h#X+?gYH;?C6UJ0%)Aa)&n^ zv#a)1hAf+|N`)wV-Mgdpo<(Vy{ACDlrlR?Tcuo$>c|%jgD=6VRL~Vq=l|u?*ryDaZ zfyoW>MF(f0a`D03ObIiyCRKe=T1b_++BZEttv*_Ni|TvX{LW)$y3W0O!?mpB=;4$l z8QQ5G>aUGH(W=^{>*bVi(OOW7j0cDTHkoCL%G{r4*jtUJ|OKRI=R1LHDaMWpCUx+>jN-8A*u!j{631qCIC@0N3?1Y7xjtFKRw zTz1XmRe>Fx{H0~{Iu)bzTp!EkIXMws^zfC2lu=UuKz+3Q0=f=8sq+^sQm=4fa~O>c zVFIu7Fy)Sqsq*6c;Ao6s4&PHv#_k%N2P)+ISsHyd9T`((4|AdP(4-AO;rs|hPqUWz%HR4*h0`c+a?Tf5KrMu1Xpeg|e+iY{C?4V90H+ z1`BfCsuSmm7)2S91K~p6FcSw=V zpkk%tq&U`OC$`s+W>&~_A{|mrr6rLE10||7I4Z&R4Ft#;BMSwjcftl~T}y6!^!Gek z6W}#z*?owi(_1#bRxf+k^2^EO^Wt4#FOj?hNy`rU$3^+P$|_K`R^*81^xE9B6fSj5 zk~dHGmnRaNZ0jxO9c*}rKEvGP$awdJ$RcxE{aw;Tw#J~@P`7kA@GJV0L`V8zo|bG2 zrwZshr}wmZ(vmV&?9lcgRdmO0u^qJa0@$*WLJU-%YoR*5RN|+QVs`er@5OORU;d>| zuX@J!tx2g#kym6^=Eba5t(N)Bi=QW)Hs1WJvZ$P~qaf{@EN8!zw2GY-KI@u)J?I>X z{UCKodkUlPe0R$^=TbVH!lqU2v#W#?4WTq#X>tAk2$72=)^302UXt~ zkn>!;$C3e}C8cbsL~Ry$>Wf@vu#uOnDGp162V~N1;>i;NV$H`Ut4gZmWvb}Jyv532 z1;lkgT48X4d`WvpSQ#TB{Dr3ghYOHzAko^|gk9jCRgm1_r^VwJ;%W6W)KuQ|#p8wP z1H9PImE7D__ghB(?54Yvgj9yi@66Qv^kdSfAA0HJ7H;AcQqnTR{Q#uz>&4s5&)&2y z{i;CBe5IQjxV59{T2F!cH}qOWL2o#1@s3Wv`Y)E4-e_NT4yVrj%sFX)WaeLn`*ii( zthuM3#r=Hu`{iG6ZmIh6je2?DSGsA<5q+GsZ`8}QExRp_4ddqbFIf{an{Pg69J}ru zNpim?tRAYlCj9=DI)C=M<}23t53k%RU#Rna=ZhT=lH!E5!JMPcwTvR(?vs(j!K|m8 zm2Wfwd@XWV>$UF^_FQ9bO*#^*MZC3~)<}BtkS6I`iVc#~YB*9Lw&t=N$PuD+CD>Ji zG$se;r4hsKUMbxb=4J(?voLLr13C0}VLpFXJCvFby_^#!E+isAURdZoI)SB6m)YwJ z)zK`iaS58C*bGrAw$np`^uQ3@2RQOV+w&-{RLTgN2q)0g1F?9lqW44y0gl4W59IjV zQ-^C4*0I>I>%^bE#C6b4>Xr~?6Zvi?ABH;pokGliEAAY2_yy+gJ{~MHy|h5|(&YNE zcY7g1scfJ3jiH{zvM=2Nr(*fN)b?nR1(j}kTKr}mGnnsPzs;PdAyF5$M~uT{Gjfhm zqzQ3@aK`*OtV~hdYnP@|<&5DYKj%3)2@$mQBpQ1GkR=fu2m@rPYXjL28;RzSAzuK!Q}pHAXEAr{?<_E<6c4?z*#tbW=CqY_FB@LA38Uqkw^)3^sLgFq;pD0;u=$r()7!Z0r zz%n8wEZ4yUDNqbuO2WxeSl{>elS{9G9KX`^oYs!Ax^iNpjl?n!OWN{^DTjC z1fX%emmE$R3Ts0J!I)}(7V!zR%F1aAywEZ}R0)i$xunl@#bzzlU_3X%i6F5)j}7e@ zDOs7sUdZ{EFE4n`zL3c{mQael?MOSztn@BulEdkrb!%{MohqgNAj>V!Q5N`%G@Afu zv4f^HA1^m31Ft4R(1qUatJbRF``b6Y^C&mEX&B+m4jNe-yd-@nhxAsonCugaNB2N% z@m+5Kj}m&JfU5}lJHtrtKB|XUZWk?Byt+QR%=>8Em9rfgEmlkGdnaoBpEwWPo*Kxy z6DD9{8_L2WvugCO+zDZT;>%~1Mqh$JT(4XkyxH3xwdLxQSx8-l7WI&w`zGi=wf`Y1 zQo68+yXi|XhMBA7>AqmtV*y!iK_fNpObD$S#ybhri6S6t^>iTcu*nEWU{yEc76CPY zoCaMx*(qtfk9dwJS&E|EU@i(M*iI(Cqe=1%QAoQ?oG?^yOd#Kmp^9q-wr@)E+O&yj z&aqE+X@Cy@0+1406UIvCL30j+QT>s<1!Tpx)1wD~(;`{3Cd8NEuQlufBV5#eAK)x# zuT@du;3|}hGsd07UXp}u8AI9U>@P$WXQ}#%8M@m9zl^h*2dT- z79#Wn;R4VtNm7DFbs9F7Yr|+y$Aj=zHXve8@W=B~MM=v|mTfv-5XY8qh}#q@;;w+4 zNUH0+$8xlL8nQVk2tnU}Kw%%MnxP1-y>#V&=m8g<(UDeby9q2q1bSz^8u9gp0C)_8 zIF2?ztP=$ssiyWlAy0@rH^h6D=PlW&E0mD6LfO*RL7veW&n+@R1%Vuy0`78w@jw9` zCRP?R2VY*npfF#{A1{o4i zJoM`#1s{0^%Ed{GOF=YAh=|rXyB8;)bo7mZEsPl+${7H3gQ`k{GT)d{N5?c<(-AD! zvq1|#PEIeaD?>^foNP)luS@X$t>l#R%xJR;xcMHAvZYEUF2PO-bhY5-zKVh7aDT{* zK|IFpBhwW+&U+ZhQ(no1mZS}hqzkYc8VM$Z8t4$95*F#g4qY=y#yo-KrNKOkvmsve z)0#d`p4V#H0BxYq);{07Ys9be^-8t-C{b8XnkcC-(9u3=2f26PrXcSAO+iV@aqwUT zdlx5o*Qo1P4^rDG08Wr&vh5Q}p@n6H3fGl?k!erBKyeX&+%&roG$k$&r3P5heCe34A7@skn8F{ z$yct?f8)#W#eUeJ$Y-sn*xqGBG-XP7y(SMk9U9#dvyf`di4RJ;vr#lqzHHa9F!N!{e!8^H}8lUrtgN_0_?lza*P@6~B-$4WprnTNfzO(J9S&E0*y zr2YWo7jC#aPE2a6l1rxJM-QdTk_c_px%1A}M1j|^E{ zq<36D?AP9}+>AMR>yi0D(TcK3nH|-5nfF!_#E1GjgrNgT%e&pXJ+Ot9Nh`YD7r;L( zgudB+I=M;VQ~+q<1hgC)N`_wVrD{Pr-#~4t zOF{>f&!R}s(ryK8xsLqx6RcH^AtlDm<)W%d%fOl-YVB_ro`Gj zrW|e&n*wxXj)bbYKoOps0g{1GtcH4?BNYi3$g^5KKv@Alg4VJNv04C7 zzEp#mN*PpujL(Mh&(d?btJq>2z1ejBDktyctTEs}Zl^EdY>cNEb|n%TNwQ&GwEJFl zz=g(Kq7Xbn!l5T$Y~QfU2WI#a;$xnX@(Nr9!Or6=tjx*chEQOpD>SqAs|ZA@fhv_b z*o#azA@YwWGZDg@;$T-syw|u(Ws(XL7#+~QpF|%hWP-RC1PDMdupr?Fe4}bk0LFn> zml%bP92!AfH$*rP-+7*CN>Xu*+YaH03g0Bl&cGO-3E56F=ER8xf5J1^>LX!<1}nT5 zf@33phC$(OF=%8GFs}s*eaXZ}NovG*@e!^|v^cInSMqB|H3Iyhsmo20tt=JHT}c=H z2WXiOn$E6bHo;X$n~ z3HG36L_u%X(@)D$0S-CsCEED6bWEC8OnVwVpy27GXjAn-7O-5F6Vo=;dpU7-M-?<% z!^A+E{Mtd11^2EZ;osnG9^%n-#55Am_7E`XT@ zBOG*5Rpx=(AbMju*s6+|;e`;{W#J}dM4(swGYpL@+V&67WinX~4g92P?y8f_9rxo! z1F*EdjdUQsZU#Y;F=v+vcp_7P>p`)n*%0L00%QO-1tG(HQ0`gg0@)$DE`Z1&VIyP%G^4 zBrBX{QnSwZh7pvz{3ZhO3XTDzO<0_yVZ(UbRRCm^5vuQYns&80uVIb*zroK6&qBIf zBSb}xA3(@;1*8S=_Y8bp5R6QF(K${)APzV!t~9J?=7hg!AXyr{?F@}U%LiV1APM6> z=7!A!brncHDM=vTI)~^3d@To~0=4ISP)s=q!!hRK1S>llfve?s4+ViF+NvacKt2yt zXKZsdhVr4lh)P33P(p(!)!3ySIBGhOmIW@ZF{i;DjQ~*r)smL~GcSgMDr7-U?uBv0 zKL7#f_7-i5HOR}NnWGEaiXO|c2doyPs>-#^@d6&{Aj1fFEizC#M72f!eTQ7F;LoS8 z__!2KGrz4RPtlWfBwZ!oOkjX)5oUk&HK_Q7UjmZloKo$h#BemfJ zohCOgPqYBl*hmXvA9^aF^$KM(*-$BuXa@YtU7ra4IQVp)?qLB9&H90@sY|qEM{A9O zvV}2-x`NQ9jBA8PgRUH6rUpC-8-_9Dd2EVv23?V?aBEytutg+*ueGyOsVoj3k~GkB zQ-S_KBc;M=FUp!YB%BA5BU*U6OgJ#O0pFKv5DP-<^-}z^Y*t&u7+LXRoU7MU$W=*0 z8A18@z>eh84~L%tV%!V4i`FeaBkQq2rN>kH5*0NGaq#Hm>l9ah6JSQ1G!r5MNy z0n*l5=nJbS=woJhieRm!sL2rcMpGQ7C4B~FY#a6?0PGSHE z0388%2m?&}#T7be91FDs-iRj!qDBfROM~VJdDPjRtNkb$T3(NFi&>uG^6m5q7!&$l z4WWRiXETFpkfQRsAUZrBa>v|ObQO*{pYcWP$WRbTBq74Lk)VEpk<$Y{y`4QIa7=(r zeW;$~;^cHd5kSdN+t|e=^;2+HFv8Q|CoQbemh4TIu@FS@Go}O}Ug`|6^D0zEN&Fb7 zQvumm!ki1KfBGoe*fHo7!8F7{kIoVuQk#mR0N1dBF0%nDpaebw+R`-!TBvNB0!tWG z!o$g+X*32TVgn#7OL13pU8ErP-fW7iBhQG5oWTcNa0CVj0aatp1QaAMS%ygF@=Xt_kvI?mq;5KW(znZ1TM;1dy^ht znnP4e?Yx8;ie0%)xAe?9l?MYZ()8CI4)>U8n@0348OnSmwKlh+pvXA{Yoem}yYUC_ z-M6DMLEr8#62}B=AaRbC=giKKiW&K5NvX49As6ynHip04ys~5Y&T2ES8$NHA#>$wV zJJTsqbT?P@bI*axourxPW<9QnCYV=Ywl$Q3t?DTww^DylR5a?DXQQKM&7G#?*aPl@ zgGVz94t%lw$g?u~;CNI+5b}3x&fosoC6?PCu6cWIVP*Kf7y0x%erG&X%b(ZH_~U38P$JdFrLo@y<1rXxKn#>0rXb6eO-J06pL1j!eeRko-_HywnM%DRyU!Dj|6o>#*K^&zNI5iQUy4ldr)ofMFy05es5O}Q3A1bJ6ge?4=M=Sxl=$cQPy zM-ODB0g4EGcvMBV3sqzzQXuq*;Y)r3R*-b@G(n9n?`D}S8RzNz%c~4weWu6q_(ssU zH3Aquf#1rOu!H~tLba$W2Z($@ts;k%^5`QIcs3<9#;>Jcx{CI8q&olP8b^Y}B`F|T z($fyl;?l5DB_vfla+79g($VL3w3mnXX$_H;qihGa^M`(t?$|VMAqI7iR6ftrTp81_ zIp5cFD)8mt*06hx)t^G-?H-PLu;TK0uLP0b3yUv5i&!mK{hoc|XK`VgSWY`|%Q>J? zUwi>yWk=R#ZF;oEH#{@zsZnrOg8q|-E<&2pD*x70Zy?Ly@v^BVE4^H#|2eq!H?Dzr zLY0xh6c41z#eLCGd7$WZNGF z?x9usgXvdk1-3l_3k7kj4ZUjQ%Ue>XMYARil!S8lt0XD`=y5DOYnJqWL1G#vCPa!`Q8J z2Ml45?GAy(iP6qN{_%1uLsNk>p}Mf0Xh0mibHp}P!~9!^7k);O1_Ez+25sr03!rtS zJYoz45qlW%&yb8LQ%t!HW}&!cOnaCoSuNV|SLLg&;Wx;)VYB8W8!F61U9q zDpkO^Fhea15ZJn(2Z1}pK%KbmtTRkEwg;Yem=}Hniq25+i+CM#h@Z!8))1yVWTVoa zp0HhoodI;#)Z46cdvaJn-+L44cX?R@Nw^MZw{S8iNl9^{OVnCh*n!qF&_Z*Y)?nOX zK4EiueTvkG9OC^@QnFmfXOFzq-kYUT54E5at%EFXAgGjWwz=slu{vRU4gQj5ylWx&T_&hsh}b8M^LrrUr91Fd|$iTFaQG zZKZr1q_jQ3#qXd&ugn-$yLebm9f;H1#`0ANq`2Tb5M0cn-#|07chDcf!1oq1ra3KZ zp*oRBv}~JKj!S_3ZBiIPpg5mCapGDaAToVD$*4w1>%0CI`-h$Z3LfevS4|0bPTI#Bxc% zLcm&2fySgWv;8%d){t1lDk#ocBv;;TBK}A`x^Cql&(?e>r)=dPi7oDOJ4YeTrY zK&}x1dq$*$QWQ}tO*0ml6{OuQtFm$K56Ljas&+oupQzLIgVo=pb1Q zv|8CHP5@~StYp4^AY%;6N(^*I=HStYMD+!wL2$KkT%Kb-f@(74bdwMpq6a=G>q)CS zNfikqG}x+_K~Efac|K2h0D6Wq4?~tGWhEMCF4R2}A|VMuz>YTob7>uD+!9b3?No3G zFjC5f*9SCu4HdCN8}14K68A!de|xjU(XD70U@UKRv$Lx3P$&1i-~~CG{0l;lGn;B? z9O>KvdedMULJVFYBW@1+hB9$P2R2w@^P(>ZD3LOWNioF`yrf251#E`$JRJxsy_|25 z*Mq_h>|H=T0@#$$#wQylr>8P>A-*k6MndCt30oYS1_4#0ou5;Kgp&Y`!3s?l<>3F& z6`9B$9U|I1pC$rIAd)svqMLi#GQd89iEA6K?w~yR%zW9bdsJrisui5{`W5Ec*6~BaU9ZZ6-mRC5sQ)br zYovNZn7P_o<)~R`{dZql=1B0Frh3&Hi93;+y`h7m+>;TOZ(H2=$uCr>pZ?*sCwN0? zck|S4yiXDRYuvhKBg>*R%_l5X`x_(coLzbgz(2*Y9GjJrbKQ66M@J}kAB{6kb+Idc z2cnLU?)$EDo`F{Cr4^EyEKuKbx zvEB>qe3atAb`LIJVCg(RnrR>Wb^e&8(VadsJjm;@B5>`MEg9FrFQaQBiMj|U4g7;Z}I{U zbz&;dJn9lM0}Yo56?BffXooqHqBe@T*Gei73vn``^MYAuZ3?zr!9WQ_X@e(G*CSKi)ZtwO1@C?Qk}C``UN(rxF9J<>MfQmz#``uo zEWiVBe+NOP0szW?W8&=yI_itoP!E-Mz#Q#&aRM$9tetj%IZzDrWuMwwA{S&48^Ar2 zPtSAE5C%UB1%J;_kyD|{Wf5aejunWbBcyr(Py#jvqYN>1OW-ux+5P!cVgdS?9T|~O z0hMMFg8|~tCwY>^5t;5eIPiMyvL+xNd>)MgXi*dvVsFhVe5iw)&fw;4jx&v{rLJUC!B=Ucd8zA7K zYS3hH&13i=RE=Gg&k-tfmK_j8CY8Oo-TG!jno0ai((Py zMT9gnxR`0bs1PKr3*`rXu$UF@{yZB|qPgHulD>3O+0p-73G(PAiXf)4~#+;spy zfpD#*AOcex<>Tj=S#9#548*mt0liTIE~S{M-<-xJ@d2~|pktVB1|M9d+#Km9!8L0}S$3#t6Ql zYZkhU0VW+|C1J#Np==m|BMO=ik60N(vo;Bte*2_9zw}y_Tg_4$@#PE4PPJuA;@$6= zcFNfO^6*vFDY;=SYEyj7Sy5x|y?X&Lp{U`&gzU%wfm`IQCo@_NFkXjN_fcR>Ab~Z8 zXzTJk$i(BS6D;^z+!x@y0o}359n5v8yFjoF+;12;wN^XME|;%P<{+gGo<(Y^+hh2+ z2=_7Y^FV|#TqsH)K`a?xPgkwq%`W-=cdB~^h6D&yM15K6^B_katu*`Gs+Ao`VZ zus-5=t!s|F{*z~&nOo7_TYYL(PUyi~xF`E=Gbwo{(H3If`;VWDr>8#U^3)lNY(-2v z=m$Oy_Ab0JS2$h(X;H9 z*Q|q+IoQUaU;~FiCs_U6%eBkx3gB>99 z!z~`?l7L7db4Z!*^>Cn|g=X0b)Sm?aHV0)urU*4N5Tp1q;e{Hg6hnPT7BYxTA@tPQ zX|O=pfhCNF@)B_imGP1hzL>G7w=uq4Mqc`Qi{rQzfBZ5Mr<{IR)dAfw8}teN4vyFAF`B5fsGXF*8tJ zKY*A9uH1K)XgnVE0)h@!Tc5!fbUO=aVx&!INP9>=@o9{{AAcU4HdtPj^d*pQ18QNx zk(3XihJZjM+N&UtL2DrXgb(Q*{L-AS%yIl6g$_!!roxM3Ifgh zFr*+*K$Jto+9FY<2nmK|s|c>$1_}ttLnR9)3y|etA@R!UPoCnp5akLBS+&uZ%}TH6 z*Q;q<_g_lTHfX1k}WJ<|rd8sfmr!jqgnS)3IGmxKz| zpdjS0rU-i?O=_GBBs8HCspv8SEo1;&j)3~oB;eXz*$9s5>)!5#K%R<6jzek_!^L_+ zaS%_BZ*`J~e${fhEc9#iFQuJePbHPX4C`Vsci|CK63H3r7DOYUwP+gw<)s)ldfL7K zLg7|4ETcHX3MRJzIA{QCLHlGTvCb1v^g^a9%{Xu*F;{2p`iU7x-bv7a3(1=Tz)6sq z!Cm(+?#<0*cz~<#Ll7wJdSAn%}rAS_aQUNUec$pXr{`G%L)mk#BNuT!UQz&11x$~72 zL~MHkpQP7MQS)>XgMy+L1rXo=ge(Iy*hd&cQwc1+DL^@A$(?d`I8H0jdoAmv$hv&;v=3_rZAR*aC+EE$_qsV`)&tfJG3UdW=nUFP2F8 zGti4sJ1-E$+N=h?8UKbZa2f&6CAjAi)LswZG%&q@d+COdjs|@g5s<;a7s7IdE?`hb zf^~~{0tR8e9{Hco>UJ!HdR(R4kW zyUuQll`OY}u&GK+qDPn1D04u<)7N;IVx&-XhtG_#_KKgO`>U6hlxvBf+);G=Rp5SZM zT0|u9aml=wzI!0D)sz-zwMNJ+Bz}m>U^o$t8wi*dyN^_fO z62Z-4BAkO=uU6u&U1yM?XF7Y)K+;9=jsZivEunDwT@--c8L4;GVa#ysL zAPV-n9H0@)Hyf-4^7<#hw;-Q^zz!mNkW_pNMs>fcM~Kj_2^mHZsCJ;{Pmh>#I#@CT zZV>RKgMpIMgt!NH4E1{_*6263-+Cv!3dX!Zlx^Y`|U`KK+{zeHB2$)i~^QH!D7I_2}%!+ zU{FMsNhtm5M2u_0KwzLN-{Ccr=$XR$Mu6OcvXiBId8NaHJOrQ_PjZqdri4T@!bAC& zI0AMgO6+*AGgJm2mc@_@a+^*_hyF9hlE5(A*wD zF5m))Esh*328$4gfsjd|PXmQ^5(_$Ngs5H7{7MFyGN_nl=r?5eMZewmb@P>-8`2XV z9{tjOQ(ZL!3Zy~If6g*`%2+d~C9omb&z255J5t4vtb_WSwKCc_UG4_j%Cj;{5mxHy zush!=g$ec}NT?p_H3qg!G$ROO8Z2QtUe@CSc@%mf7G(-io@OfSrxT!LsSDc9LgAB? zWD0?!fJz}_j%iGIx=Pa3XmMcGrojpTu`~|0P{aoAiBUi_K8B-e6+xEv@Jl)8?#@ci zhU}?cB0F<}Rj|O_Pi|d}g*(_xRDcIjEb6LYNmoWo;Yg@9j{`&l9mx05Ius1Rzu{0^ zZlV}gv2f_@E-~4|1fdAfH3=AEQpLqiu@7oQxRwY=vKL@8{}e1~0owuVWOt$m6>>Z( z>g(%+)?_8v8ATx*>Pkx?4a!cIhh+qud{DPDHX6s8@fUJN-KD@_kocR>Wn=5RVVT{) z#i|SM_V(r;kN0m8i=sKm=@_X~NT6eoh6n#pFcSm18feb9!VDjE^aVL+M?12LU~G`H z{?4$I)G%=lA$%g5HzQDIdKU-86j(~3bd9IYJE&N7x?FmEtNWkXpOL|9>*6~D_bkmp z@4J<{TgNDX&~H6KtQ&U&v#1k(6E$T7ZXL)3fW;)F54{D)y!8_AGXRk!A;cbrxMh;+bI*6} z?V@#LMNjutFmL?P8b4}Mi2B~pTLGJf3ao{9GWL2THDNe-)OGht|5o>i<1=k;0N25R zIm2(FrYaBxz@!M7^iK-1gHjw>RvehvfF z9pcIcUsMbQAK|piu_KS^FOfr1q!=%BSdmKKq*A7M`{C%Qoq;@mrmd{z7u1@AL97x? zZrJX`B)GaWG$XL(1A6ZY8}xc1LViv!ldJ}%5^5mE9sH~sj2Ae@i9^*3_2W^82%=3f z&?+uN1m!yTI1$2w9Vjl9yl9e3y2FKfZE+S`B9#P7(mBp*CqA@iXfP(kQ}Wp0|0b?u z$S|M3qF~;O?iB$UDlCP-smt{Eh#I!&=2VD_qt3zBGdVSQoVO38q6;CS1E&I}72Lh> zqFOw>G?*p80%bfgzyIjULtjhWWEmhAC_DE8P{qt)r#_!zK$?M;qGc?-%1U^sd7J?P zK%~_`X8St=q9y~mtgDk8;4wHE`#XTL`Gmo;`3sa2H^}KYCl5O}@(>c1QHOS)iz7ea z0z{)Kg&39CH8m8kO<_g{Ex{&c4<6c}(9FbLC`5A{dg*fvc}Csvlv20b9MW69T)+0B zX6|0qxXtWmw{R0B9Y8`$!+-cBZdzpN1#?mkz6#1N1oIj2(LNEaqXOGVRrd)Y9ZT7N zy@vFYzdO^>_mKZ%o8N7V?f(XY+chL)3@h-y5^K;=2Le$Bl)3DN9Ye&l2QuitMFB}m zD}%WskZ(17R41SwV!#|}X(c~ie>|VW@>(E~P-e%SDghI?-n^`6K~S;})z?nM43vei z=0vtcccGxcC&~08r?5dntxIMpEQ?HpcDQUE`-E3JFu7qDSki15ykLQ&2sMxM+4;c< z(w7#D)1hKu)i25rsiMpg(AOjxKzpl!F4_!jMN9h8ftdW&}q+Mw;16HtWdNirg zyPrYMnk6|1JY*s8zGXf8$^pN{suGLJzue18xy3 zlkk&-GUj4AyU5K54HEfljCfE1a;1^*Gr{mmC#b$*P9S~&2?0|Y1XVO3yxKqw%jc{I zez6;D5On4-X;}TW78UW&Q)?JWUnYt(pqJFi7kFl}kY-X3^R@2)K~!s5QTtxDSI7Ac z5&$%S`)GzI;6p%ao8&BK@bf5L+1KrLnwzBK?vgJhUmjD zNg=ZEZ5%wph@l@a|Kl-s{xSNqB8o2wNCoyAQ-h5|On=YmF?8NR~$Hw2V#A2PP))d}3J$B8h%B zTD#Vm^PlrWkCKD^uh+yP9NhnU48M!MNnmjQIc|ynd2X1n|8;JdnE!chSj>Mt2PP5w z-_I@c{@eatSCGG_McDxe(`_*h>=^cKu%sxL0(<~FE1~TM?c8p z|NRri|C1+}t3wo}5Dr`&%yI;)h`}jh=6c{HW#;NJws4fse@BOOd>-5{xx?e(pHJTTHksrXi^?#7%=yD5)KqD+^HHV^Fiemm`PTlC-$ z2R#<|m@v1#{rv>5qT$ttpWZ<+$Mg7=PdbJs%^bJvjZM!NR5f;foKi%vSU6g-`D2ol z5I31W1a0F*VsHcz%NL8UO+Jf9kKiG__1n6Y0sRM4vNw1w35+C->qwvnAgOEeNCXE_ zvUE3PvuV_xf&V^)|Mw%%`(KAJ*M-R9=3i40u|+u9&V*%5=as`m=bR^HNOqn(Hhl3T zYNb&TK8d<$^Uc$X?JvZ9VZ$T0%V#gLgNel5IV0zEh%1M)>DkUJ!M9_s1)if_u3_a$ zo^+ivv}&jIJBfMjLl!@xahDBbD?g%n;=IP3y-%d%wM{J_Yx}-(o8&-txpYW?qRS>1 z`sQM)%mv*QS=pf}&QIN>bav5b% zC)%G=Z{NORW45wFz6>p|RA)}alYR{H>m8-bj-7IpFrfsuJ=A*I`E_Gp^emx#^{D>` zm5QcZlU2E`M$B$O*Hi#*jV(zWzuBx&5o^BJ_}Ax zOMA3tWXB%9WuiajHd?cVckicly6K%M`q${aGq2YBl&L$fCtlK#GfmJNnL|1<)(ag> zPAm7=+nzhOr^q%avZi|ud8hex4sjeQk9}1lr=!dxO%lobGt{+z*c5ADn+MyKD}T)m6Ub5PNC=`f7rEKx<|8lE5v^GJXqaw>_S6 zw)XhOub{{kN%OQSPA#_cUZD5>(oONY2Xk%LI*KdGUcXR0xAX0#P^IO!4mn)Drl_+0 z3Q45M<6d{OTqvH%jw*0-vouiCx2wFd@pSXW8gucq+W4RB$L)zXw~^O5y5Uq(E5~PC z!Dw)wc5nVq<57>($u-S^+jQy?>n4Hd`}p@Sl|XB$vR&S7aJ1UB=F9EWzkAvOXg*s5 z#m2N!O#YnwC-~s{>u*leZZ=%kEUXeyt@h>wKNkwOk79Ojc*kb%i>GsMbsiPP;YPpP=cjyJe^W>H#*(F55a={$BS`j&0PBmpUfxte*&zQy@v}NeY;`%rKCp-RP8G^ zruLW{=Y3c`u;jD%*v<4`8@^v=-SOQe{dv!?uVzyH(biY>ew<2R-5cE2v-9syzv8!- z3)a6(sL-4?t3KMATQj@vu0`FS2VZTScUe@Axk$0 zXDgk^&oemgsvq0_@lLtFVf@p5zE(MPzJtoArF?gK-nAGxx^?7f>ZzD=CWpFj8`KA~DDqZpEIr6I8+Fg)+%-pOGz#1zw8sR&z9H?{_*tjPt%H~OI-~UjV-y`dpqQ?BqdBR{QiQH!sAiN4GlAoMFzun3{Ac) zZ!%P6UkhGe*nQNZ_N)6)V!|3fXgqjs(+awU2Q= zho*L0^t~G?|7tsQlNY7F>W|;w;E@BN=gQUfR9f8bSa#V>-fMfb>u1#*(m12p>5?|- zd?C&}!=lH-@V@-TZMP2IQme8V{jO~iq$2Yx5e^*Rf zojljkX{pCZV}{9`yj7qv5}@GwL2I~W#Xcu@*%fP_{)&;Q9FY7#eB3I|kehrXb^4z0 zvh0n?FU-}0;|?8JeW8OX%(wR>m8`yQO?ku{$zpazWo}MCuRg`O+p@%V({$;1HG5}% zLw=+tN%FO8sl^l9<*Au>k0?0Fo~osa@pG}C*3xveh<}bmZCEMxB`T+j^h)mI3)-r> zfPn%X=|>?S=Q>}zdT}r9zlu*^TTJiQ(Upg$rVa9~2E9^UU9PfVQDb^58{0`N_S_}8JOU31;w7mS_BS6cfedlwx`2Zz(lSa*l~q)AboB^CeUgc( znYo4KhK&>lM<-{h*QU+hTYR?q2JYSyv^SU$5*Za86MN`zTx!~}hIs`}2|M~~|po-{sv)+B0cf7Q|X`b}5=z~K82Lmxj4kBoo+ zG4XS9YWmj<>}&q}BLAC?|Bv&56aP2al|;`6gN;Q`R#8k`+gM_eou}lkh{em-CQIS% zA?JQ5y<#2x+me8Ttujh0N&PzG=qb&g(f`>ArTl+7qyIjk|307pJwg7p{(+utsq_-* zLCpDZ<(`(kImfJv7B0)rT`^>VVBf~9btx)8{%jDpGCA+rrztN{!w2P*Y#}8 zsh2zMU3n8_RCwrNckJJ|SxS4GkA9Yvd^lXOM!$7$7w&wX(!aFh@0yMt>)N9>uC=$? zy5^8I)3zP=KGo;D2S|HPk)Jl@DL<9VP&+%VrkJt#aiQs~WXXeH(Zk(eKP%SHA*OdH zEAw}rKL5Z?wyH93U16qjp8o>*g9oK#1$yd{Z{s>btKZm!-rL!kzvIP;S7~`?z{T-p z+r-;bjLDf8+bDIxn@pqEdaE*Wm{$aUkNO_|9Bf*!c=dj%7ZUwRu?Sh~!$VmM$pxuJ z+xQeD`d49x_)l)Zd6@AmK)b#Sg9`Qf!1r)BoUFN_K9u*rD_4TF;*kv+=sSNgGXj zM>B3Oc^_`3uzvq>ooydpA{Ppu+?=hn%DY>B?j~awsr-9Vld}KWY=taowId~`U#sX{ z`k38*Ab!=JW^jXHI7f$v-A1B`(_W?W)L`M$gF37?f_`X2SFy&}cCVTmb2 ztKyq?`dz4hw(>c{%H;m~F||y2;y}pypo-J07^4>mhFDgV{zaJ>HEP(&$p&eH$P<@tg^q_p4WOM=;GfR zagA+LAM!c7svlKZdz&rr$o}%*yK2z#2ci=R$T#l+^dU5)jPDHHfTw#mH0_iH$CRIs!A<=$9X zullFfss$k|{_qRyTc<*t`(i6^ikd?%MBQ>9BPE2YJvkQaP_FVMy!5)#{jaTWuI<>A zQ&Bi+{ln*5+SBdF)WUiB7Gf+hvm@gvHtWu?t4Bl;TUr@2!JWU3dURYm>9O%k_p8ur z`M(4Y{678YzAnFG+f$tO3Vmlk>GvPyQadHB5^iRU*AEPI<<#D_{b6%=Nqc{BXT{9c zeO2r^WMy1m>is1K&o>_79JG6}P#ITLB*;7}|Ei6;lo`6uugc|8aGC$gkD2NG);h`L*BZGa{olS(k5ZCqs$}+v%Ts`nJsMo7Mo&S@G51Ha|FdWb5zsiT{XpbiEn&t<1fAWY@UENu73@ z%Ye%%^^J!Dp+FVpXQ9_7ym#-w(w%PmM@=eTaM(NQGObRpm9(WKm#FG*-n0AjC5f&n zuMY2+p5G6?9S9tV%!nG7Q9i_2@SB=fQ+V+%w`16<>7`3)ZO63B6J=+g_T4;s zD$!(E^;qH5sl^Ws_!|Vxg7OkZqV4#OhN|@YCVO|wl+`HZcb#iD^j<46IGz)IXsdSg z_Zq41&#oW7_vK4X?3Omc#dn7cguN%X#`Nqk%p3W7>Cdj|o$elre$M{SXR}(*Eny|h zA?G$#+19H(aY#J)R_^sR*XXUgh?kq(8rjY3XKFg8Zr`fR^X>W=gUyJDEY#bhBe|-I zm*f2Bi)ggw^UP7Vi{HZbp0Rd`9bYMzUWaM+q7#%q%Lr-%EmEaS(dZhRG`sW2T| zSGy`6Z|>7qAJc2_?Lz+98w=(Td^_Fo!|k_+|5T@YsMr@RH?8@lrxRAzWY*j9A@}0N z&>CxTYPHO(VCM&W6A$g&-Tfh^^YE&}Kleq>tQfC)RB^JWq)IZd7HQIOerCJIHL9mY zV_o*bQzuHI_eOvB9=m+Eqci5VXx4k?^F8(0D?R%XybJI0db%qn?|mx|?5{u3-F#C< zpchv<5_6pV;1Si#darCm7Ui%Bp}O+zj=aLqkuQ}oq5CHv1dfE~w#AuTndp203!`Dp z+0i28o9Ujkf@Q}&FC5!GD3g|r>B$I}Zgl-7!CGNv7`iF&YJP9W-@a@2KE2rgq#~y? zn*V#J-}zO72QS@@I?al|W^|Y-HpDJU*=l-0%Nkd$U@^P6JH={Ci$D7wJ)vAQ`SWL6 z+m^m}KQ`;^m5dqqQk8gl4oN7iS@`h!wB_PSzs?FP%{Nw)ufCPDrV{bf`=ehbUtF># zG&`VnX~p>Zn~Z@2$Ku8YeXl&*TiiP;n(lsF)m7M;yKmpMkzNIn$nk#XSfI`8*VIG$ z%-rtuT2WvA#y+>2p4eA?L5Gwr>^FZ@?F^%i`>tv-_X`>RaKZBVO*6 z>ZWhKaxZmwbm{&I%C0gIRTgDeHiA(Q&Yku%~>f2YZY&E-qQ&pW4N0%M( zti92D^JEl=*X*2*tn*bp&zz+ht)w!^EDscsu0DYeX~WYwr!YE9}hbjviHKR zgw9`` z^=vtAV)&VTxK-G#?mjnq9vj!u9-g4ku4Hf!+38mo4*SN}+&ldD_kkK=rJ(D>kFby_ zXU8p-J^S;nZ!=3sjM-vsqUOE$u%>?PdT(XK)Sl#B0c`)%BvSwnR`vcRd?gM4-^XqK!iJH^-{bw39 zD=p>Lw3FF8qq|imru^PjC!QnYDAshSMM8p{K&xPNy{~m49jir*;m!2##ra; z!?A0;YoLA*JeSJ7# z=huYHQ{O)J?@YOG{OwA=-tj0~+!4!frl$||_sL9qJ+4f7Ol>8dx4jd(Pg>_adn=bc zGCMi4@AL+*_OJsc>eQi+w0n2&b#4xM@+_Vg6(8(m zkM*(Xp*Khcs+*U8>L~o6a<6<~!b3Fj ztWwzN*InekW`XjXN0wWE?C&(`5xVea4D(|vUT$o??-{XAEBMQ^RgZNC?mQE_lJWk+ z*s5%^P_;0tD|hpVWpAjHe}1p;Ivn@;kWYr1u8?_3^rGi_C3D8gX3gF2ekFl}DyEd# z!sQ2OTVLh=U+ldFSXE8;IC>Bj13^IPk`NRQU58Y87lH$ zMLmeJ!L#qa*}b)6+0$m}Vp*tKlk(V1aWl)5JI>x^71pUSKiG{o>ey;z7=U7WH|G8& zgd$-Jl+8d#nGiLOJOQzX8yZHIS`8vbEp0dSMt5XAF^US_M6Ybg3@q$C&=?s=PAnm( zOqmeHu%Gs#xVTvKg3fsMo|2I46Ki2*-P{_~gQnbtpk8A)=Ft|{07cL9qXZhIoi1sn zmR!yjy|c;TixF#XRdg&D=+9J)Q8Zu!;sl$=t&$hVG|xGwd`blCy$U^A**@rr)GF`& zY`}()Vq8x=Y#-Lr9;jG#e?jc6b=b3js$aP%REkl{^m1DzN5nuj$o3YLL z&V2b)SsPgm?css_{gLH;A%P@2)hbDr^;bQiGMhTd?kl~W>UJ~6%ocUFk6`#pn9NG< zxR}WlYc3kbNEs$DJ_A}94#-*uL1Lh*m$7lMFI~mCf`gBDm4KL$l$el^n4OlMf{~w7 zND#uw$9qRwSMiRxrUWnFJxgUxeM4gtV_^jwCu^9aF5DQ3CW3*7k57D^n3a^26)MUn z3jMF$>1q^O691D#wFX3b3P20#e>n7F6vp|J8W20Me1Ezcbq@0^unL8Cr;9h}wJ7Ct zGz1(5HjimVRnYR%>zsz|<3JJ;v=sjrYUm_q&jC>kXu&7iVVwO+3r!6V6A-5%L&e&(v{Z zX2w9Nl*I0F@_sU7=ILAZy5U@~(45qR>7z@D3yymRv88Og#w>yAo`?k7KsuYzl)(cP zas77-B0ZI@_DTDKR@u2>bCOdm1Is^Lwe9xDskDrY$;kR$qg+x(l5#1 zHY$B}_By^ZNCv0`>v*`sq-)4xwl7 z*P4WJR@91a6xvJ_sFw*VOSyZ=B;21jZRuK z48`O%t0-;CuGwCCF%x^c_0~9w^+GBYz8gHJQrNvVB2nEmb@IiCQW~f8Tv#pta`-TQ z7-x;)fdlnq?#s0b&wivjAEA$X{ossB{C?h}Pu%W$BG}f}-1>G)G9U6Q)t#-f?onXCh{d5W6JX(DYVEBK1lp zJnR^kluJIeH_l6(kuH}$_N}=La^xZ-PtLA*F-fsS21aKa+^?UC`d{x%#(!LfZ z`7+!=Ud(tZh$T6R5)D1Rn?^agqOrj}A%W+WjNCY*Rh!9XvrDwSmKRhnJdAvn`0^7x zH%zd7ez#p09KM7qX~}M~STM=^+)?dsw4dXh=Ev#}+t1nJ3e^`2Y-p0+D60fddl0fz z&f5j~_m;kGc5^va@WwBZRlV;$7e12|Ju=6lsXjG&HiU}czGE!8$W1nk5n%fh-hd)g zaP`nwnqPPsJF?(@C@wvDrZjvH%Gz*IxhpAfRxyfvZ_(}&g0P|j?=ytZb^RdX6GMM= zf2q_0r-o&PPVkCt;e;4?@ABf>hfshZ}62Bpmbm**%xHog1g0_AA&6`dPWp zevXV!Ogz^p;lg_qKv(o}oRrRcNbV+T9ckZ4iWkElDofA9n3>oh+mgrF&upBMX(#z^ zqOu8cZICfP#IU75l%uP-4+`*N+F z^i188d#_@}=%1YBDk(BsR0+Ue@ga2!RV1>pqaE^5gLSDMys4OLwPTLr%3p~X=KUC8 zk6KE#_KpgY*?8W!Totj|D*wJRXD%IN7d3{SPjK9`6c~-HXDIYP&&8ab3w|R9x>Aj;biT{k?@HM5s-Cs=biC<|_F_(gFB5ZwWp+(WY+BTPNc^X3wOw8QWRB!DZ}HC(qRcz15y$9jqeXD!b3b zY?eW#MVd{XlSbHp&IkQ%-c#HKI}R+!r7kc zKiBrTBw}MF=#aoqxfR|jaIt|VQ@4b3{V-LZP-LkXNy?Pe%|a5#HdJ2a=E7DJLYpfP z(3L5dozxRwC8yU^tASumx7-$`?3l}Im%A^N>F642Wb!JoAw~|LM_5@RaOzo;^5@NE zshX_umV-D8lf7N7+v%!4)l$evsGY2h;3^Z*MO1+NLbbqtj^b^Zc#A;Eh)8z z%oljEsmI2(g~?$;5+GQws;Jeadymwg(KZj;?o*p1tBDPfqJ z$YJ$-uc54z%h)g+Ys`2v$J_u_%h^J< z^f<U&3=pD#EiC4);yt%+&rFtW}M!$Bvj|R zMUosYlc&8KL-&w&{JjlIZz+lxgKhcriHIb+;H3ktPqGl*B*SuhNfF5{!Y|3i8wWc4 z8r3e2V>3toK4RoBe{+SV3p{Uvyi)DnrPG1~tJ;Z-g3V;ZBqJ-vAwRTP0yYd;~c#DkD?k;iy!pIHo6qtuW>ql?`5%%jg(~|> zd@|)HKl!VK-Lh{X2qh#^@hk?L_;_7)$SoAOCr5hAL}R<5=_71_mNhVo8F)%^*yY$B zJ~Jv}IQKHX;c6-KEAiaU5pd8x**a>|Rd1IUwo#UUEY|*o*LU_2uJp#EUzh;A{_r~! z9f`>e>g(?E(`!dmaI;WK!#S8FFWZ5ojAD?fuaD=}X6ile&2;1-Ed^&xZT4;l*OK=N z#Yuc>3YRGm_11x?NbhUIBjQG%q=mO`E~~xWR}F;@3ig?+dYFlyQl8#d_nNf;F-U?#M1)h5|s`L%1H?qVh z*JI?jg>Y{QMTiV2$pBWP-94LMZ&q>|MMY66&Nx%jq#NDAn4>iLtyaLC+tSnV)_$u) zf2pzcQ#X^DwVS@w*pwEQ?hw2i-YO@I>W7J1gLiESh8`mCAm+*!xn^Z;THk9DnseA` z70#8<^qk(vjMabp2GpI(M_}1xMJl~T8=u~R@W9VsSt)z1!cqY1CgsvjF`X$MTlrW& zdZpdCmCkJQ!1#(hb!>qWcEVUpQ_Y-~jzyA4vXMfEmZZS=lR$?gDtj}fTO27{*W}o% zg<`RvC&@?0cNJ0h()&yc8g6Sd1uN4yPd{^cQfzlSKDYFy6!9aB><|CKQUHK?Gg+p1 zHG{e0UC$X?##s+Jhc!U&DpxK!hcsfEahzeAOy>5eyYN)8$qVWBpwb%^eB_@DD6NcS zuA$`LN^}c5bMzm)Z=VjnKb4{|mG5%%R-W!iR{#Oi(5PxxeSGR=FK8$pXyh);8y0pG zbT<57xr8nh#*(|^Q44k(Rg4I7(b7+Om=J3C_dfrve4alD~8v=jQYF zod$M(b`E|vK5BMeel9+KPA-57P{%jG8V_*CI63)Qli}=7nhcmnr0(8Yr?w{Z=_vp#YMN9fT1L z-T4TZsIfA!+3wll_K*2gOPZ$Hc{@E)=>BFyXkW)o5$?=)mG-O6MqT1>C0DjT>mL!y z7ma@qDh`+SNt%&R*HhEI1EzXgk12iBD>dUmyKyy}%ugDZ6QON><8xDd(H>dL3WB0^c*$0b>2)NvbQCvIUNzFN z2h6)~?s^o}yCl{e+}#nW+2saP7tIMcCb{mb7X=yLbLUT>{@`GRf4(P3{sV(24JPwp z;`-$A`m?{3Ky)u_duFe!V8nY8q-@;EaM6SLVSKh9XX*)4USP^_pL-Z2L-YLSrinf2 z{K_n82oXoTj{c`-UTZIpH{q(nVY`rGOsZFwZ71=fTw$a^1GPICBG(vlKCX708THOq zxb}X(`@zor&v(y|avv*Zoq&>F4^Z|Bbl#jfx_NOYVDnW#OL=U=vCR#By53|3dv=kX zw8X!pW!ZCS;4HNB69EX7K{+iJHYLmkHja49=9}cb1)qhwmz?Zl8?M|#WuU6HDehYk zTZ3(4Ezb zLG$&)73tmqd>L6_+^U{*eH%oO;AKXK!MXg*B|WSadeSt~?G@5z`J`{;wC}1?Hq8?x zr}k2XrnV?T2iCt7L8hNq-1xv2urF;$Wk0#+7aP9)j?Xd;>ckQx1#DBE>iBD7=RH_Fk#ZftjJZZisU?fxnZ(A%7sxXnL&|{?(Q`Vm|j5#W;<*y5uJO@Haolr zjF|+XbpdPggTgxYQb%-ApLdp~&U@nSC*OQ3Ib}7$7c5?LFL#C9@dT8`I=#VBo>2Ux zkZ|=}EyR!K-BL!vN|Dlf^l{f?+;fvp-w5B8TI$QBoY-3hiLwu>xYq<-sh5ps4SQzJ zDAoDt(?RZDT(jZo!<<5~7dTi4A;de{tKzwvhm4MYe;AeTuE?7Vx^2HuR<>3Np)S|$IK3RPCex>q7|>tN;vd@{Wwjdxi#KfxGjV^ z^NCE-TNFbTa=e;0 zv*&J?T}utWDD|vM@&p8)oP0qHY!GB%j`9$hHl7zF`+z5S9 zbVNgJe_^?(I1?G3D?khx2}Zpi;IbuMc}OKwe7(4|Ja+zm)9rh_70YA=5ij?#Ih3{l zEsj9NT-MM>89Vt>O7wE_)@DLAW<;rE2)7vH)g8mc657s zaG-51QUtJYCm$HIEvu9-66~^JteaQYg-w7!7h5%u|L( z5%IJ%8@Rg9NLZYJ3N7ws?F*4rywa3vCc0^(__E_HDUERDUgutAjdUOvt@2}XF~wWN z`@*J52OCG{Qd3LB?KdwDa7$jQbaYap0CGd;XHqveIflfvM4ohS!O#9l)hz3)wK z^T#5u6y6U~D07f^Xw7tH9Z|)3;rDiLzVjH#@Xf(H1H)=b#>T}W*@MoXfGFiL_zp}O zQ97m;d0t=_j}F!3(mkMf=VM)bNt+%`-N9N7kt_~K>#Qh%acAd;UL24rbhAPf2OP)w zq`kXfzI;U_yy(t)bYutq3Sfu5<@V+yoTMeGgQ8&uX;qE z;GA%-P0Mv8yfL6vq|7TFQTVz1I2LSxdK7p9!V6)u&;;h$~>WZF$TZ;^Cu=YmXLqDRw3a3{6VG0~tQhV6+6nYHX*|C= z`OjP}0haPrV{zC^qT##1L=Px`^yEA?Vsw{EAESyFGk0ho5)ob<&4`_gJY3+H zOXijI)4%tL#5(XcK6{sqKjRnMqHN2a;t@Yqn};@bZDZwinr>7hNb6orOZ&VkXw}nk z{$q9HOGzXHAh4jTOVYyg*ZEjGMN1~DA~LO1{mPQczU6PY!w#o|>T&K*)Lv|W*x1PJ zHHX6&V{~JC!di}`xha&bc*K}Kzt`58GJmf;Vo?B=Z^dSgQ;n>c(kLfdb4V zT4+0*Z#$G&bVE4xld+P$s5uw}p5BIkVY%U~)GhB(HWI2nkfHapBYMj5@XYFE-BHAm zhq=gj$m>1MciH|p+0X8pzvwWJh_df=?mGc_Kd$UOp7-6i#qyJTB;rv_I`F!O`VTOo>e{A)5R05~A@TTv= z0vVO+^c(w7_V!&N(WN*GUhW!obK>pdbeuC%^TewQ{lypjY4OizSMD8hoPeThf~lhJ z6-%q{zcUP(1YS+gEq&zW_AlP*x3t90Tz0Uu@=K#B43N8>1n36lkR0RE%M=v*8Y?cO zZx1F34Hoh$#kFb9yLf!)KV0@`dGO+a4l_T0n!AqPu8YT9+O} zYQ(Jj^s7Y1zqrpoF6Uww0fvL!gSQ*Fecjo~c*nu5^OU{T&^?*O>>bERq)|!D!0|`- zryl9Ew<w%zD$73_bF?@IkuyGq>)8%U_5; zs>B2eav?1lKME!8gJ*b3`k0CbweMPOeCW|CI!1J;29ut0^fd1%o$FK=VA+w-+VqmPzdL zS121DxTGn{CA${L<94*5#JU&CgY`0A?lbfsv>YeZIeW}?>Nc5B59%3~3bmNf?-t^Y zB)0BM4g=g;IsrYEb0g%#)>*7&n1{moJOiec|KbJauT9U7qG@Hc$%mhU325$IkW_uQ zPs2W0M>PUuuKv2;T*uEgw5UEHq0S>QWwc`SkYF$W(wBA0wZQ`3P8%FY+tyL5?f33G z>%oC=R?4Ig=ie?lX200aG_G`5x4(5}?8c)!3c2XbX5ejP!y_;1V($w>-g)!pX%Y;d zySVbktP8b*99fI*vss6;8%`wM0l|uTGjT%^>q1o>J&+{#=Pjs$BZB4Z%FU~cZMo!x zM4XhhL7hrT`bNO}4VM0qHk&oncn-J1V_jB#dPt8x!_FNSbOHi))z1>I?&b|}NnA8J zUlAL2XadH1>HK10436p$M8zJHTvYPeG&q;ioXnV0$4SLX+3PIX!y;k;NTMb6f{Y2U z5jM7%MxOf_><(2+@JD*|4qc1uBv&4Vg*D(E6CFQl&)i>mXlIWlSnKyi6(6^RH!!WN zGAL%q;x@vjDywtLvinW6Z(#BA!+q}Tm1E1;nVTqm`ox%A0q=l$vLo&2{2q^Lvf)m{L4h__de zJFjs9TD&!40l(hUnO_iwC5QqkKW~ znUV+flZHRzR1DOPqM|puJxQNFWx^S7fBYV!D4^L~dv?j;(2xX5us~aL3Fys!2My_{ zFg!0BLSu@vd^Zj&LwRhqtk}4_S2KW@ZK%#BxrbZSlJoOdwo-2V%Qa5Z@1;*b@eACt zi=G`ySlLP%1n1l{m2IQ7Ni*Srdd0D z@jMN(9~Tug^}jo7=9+g&eV{kM0&*;+zf3D2wCiV(em?&%IkGE(>yp{8`!$@MFly7{ z2Edeq=VR|^cMKA5Vo!00$YAMI+%ny8_f>W^nkK;01k5?gik1uNvYQqAvyjyf&-R16 z{VwNGN&BBgCK}O$t$O^YnH>;vL9 zPJa$8#*jsM$G4Q&eB-n8u{%W%d*a`zh&}IMitZlj2_nYD&fTfZOrMmq1sj#jn3U4zw=XCvzhci860?8*~tG@n9Ertceqc*~GkX zs|-uYZgNqHQhdNdf!M@}QwByX@abaHvCymMPxd$${>Deo!J4k1Qf9O~dCx1QsnL!a z#vV=863(o({TMiwGSdn;d4?Tk((!(H^t>rlyJHD}*of$%W{ zQ2OOZDk-mV<)y9@?0>widNjI{IG~H8$er{-C^UcUY4WZ>nnQ7AgIs53qlXkVCi`&a zu1DskU!)aL=aN&$2Rrk@gDlLAN}Ktpu?Ms7Er#EMwl_q*j$UlbSkR02;rl+9rT0@T z$mPW8k_M>lWvbfs2xUUYTdct-xw~g6wMCyuzkZr>rpH?9UCDwSE3hqbnR4pyqii@? z*g$-uG74wuPZwFQep_n&aXXFUKMhU;S9JW>1@6n%NK-3YB|BSdJ6iyVK7j{x4`r)r zh(K7JV#rw8!r@kSmgoqyAAJ|IK%&FAr)hz+2+$a!rncxb=;*IB;YdXTOSqcEeKi2| zHM6e??jaEf;6Z6?XRTyt1_dIqLH9sN5CZr!0#SohL2!^Q$PQ$UCIz}={R0~aosto? zu(kSDB5XrDQwv*Dt5cFd{KZpjF$FETuiOwolQ;tgE`Qe;|EC%&S=*W-tWZEa5gJp> z+SclOC4fpAB7X!_j8O_d0%AxjvA+XWwtolY4J}YVVib*S?SBL$EG@);1OPt%ODnHOK*~6i>2&A}ytpU0Qr-i&{d=K@#SD^i9WZ;f2 zHb@?B^p(tS*{T6YF8x!ss!)rs@Owz;9W6A4Q+E}LL|AK@z=6gEdZ?+D@pty&pd(a( zGKnH=Z4s6h2rJ`nNwB}ipo{Pm{K|K@im9>5&k>iuM*wB}fsY<5n9E4=xcwwatZ@ZufPT4G!<|_71~|;Hb?;Q zDel%OR2sx;WCX-m09W83DZpWTgS-uo_yOTKg=+)X?>OkAt1v+5p8pMUN^=(ogU}=E z2?FVS*TU5JJEw5JR$lr$7^pcGa6E*8-RWe1(H@Sp z{Rec7@8Dn2FB=+*AuJHcpO}mHmASOc13wQqroBs%#{|KA^2%G;1oBs%# z{|KA^2%G;1oBs%#{|KA^2%G;1oBs%#{|KA^2%G;1oBs%#|CbA!zpl9602Wd~AWh(R zsxyTPx(kRj5FkT9v_TDsa7_TeE$~B~`m6!8YySrfY7hsA?evFUv^`zL{VGSn0$l*I z0RB(LaRp6mZLRrPS*=hk2518=EKr0ctD}K6D`35a6(lI)Xl(#Bhucyc!T~9Q5Y1|7 zB@MMHOo&F4TY*i%S`2PtD(#Gft2!&HL7mN^5EzY!Ftwl~zoVtKCEV74+R@U&3dQdz zL~}}~fNDMm<3k(M3HH308Qv=3h z*jd^5SlM~O?411UfT9&I^*2WYivuSM0%^?34uL>e z**I7^IKTh~80BPTYv2gBLeYMwAPz@Ck*23IYicw_KptynD?|g7^=l<8t$&dHM{fOu zsG#ugQ7tXeEI1{LvX!t0a`|`7fI`a+SXJOCgdGwJm#~Lh+0uSbZvEZf&Oej*5q;X8 z-xI;0Kd`L6##jRJ7lPs?Y`FNTC00McnSKr;Qkss7#;0a*C?NgEDL z{96JzAkBsg(V$xm%+3L3<5T;t9>>H6Xv?vEMO6TL0t^s)|7XYun5mJ|e}W3wypXX% z*&0|u;WFYvG(e$POif|@Jbb)Ha6>o@%*Dyc2Zph8!NCSRKtJFz;)Ze=85uxfhDN95 z0@8~kpmu0ZpwoZtxG)41pz(v7{JcEeyqrKfFq;7s0_I}lG6eI%03R723Kpv=uv?&T`JEw00L=|rH z&1YdsecJ2z4WQ@^8bUNsbSuMw0)GXY{sa5|vx0t2?*MEo__wY96%B;jN!oC$x4H+3@dt$`PwL~zqi-l4gS5; z+y%Nbx;0VX*dS_P{DUFF99(>oyrLXDoMP;pe4?D35s;E?;fK#%17nwN#? z-zomNS93tvIbnS4TwpGAU*_Qh`nLf)J3E*Y&IdIxFyv%6s##aYKzDMqmhp zn-2_y0JI?7++1KDE?zc1HZB+&Cl~ZTrUixa^0KoVfw{Th00kp19}&8zdvpM-2ZUk4+s8m;137>aNrLI z{ugoJ?=NAv74Qn@0DR{HhiTk6{dxt#?x4TgF+o=`&tQK2#0J7>_upDsIz9dM>jm?N z`)Qjc+Aijq9})kl=j0<`DHQYQEO72DaKh|&D@**qqQF->pkK=hT+ajN&;k}h&tP1_ z_#fiVU|hU}wh#&&dW&)X?0KN5fE`v$z6S`>tbe}Ul64R+3JTx>MgFJ7g-_mGy5 zgXk_DHxE58@l8<@Jb*{1WrAs+r5Whkg9Zq7XUk-P%ip7ZaW?#>WWgArjAT z##h@ut5Jt18WH28v%x%j9;nK>3s~nduAs94eKQ|=Zq4Q~4Z(S|F(r=naZx1gHLR<5 zzNi>-(p_hJ_#~*~UR=({2{A50YE>wzlm5cf;P~8XZX$8D^+}j**UcIUb$I^Q19;IV z^P;!R4eM7rf6RLSgNOf-=dziIJ7Aj!y?6h=aA#Uamk}OJ=uLS4jms@O&>3y)zVqLt z0fCs8k9&63^Y8t4sV)n6cdJ3d@L*re3Qt-SMVd4CH1Q_sd6-)Yft zb?soyIJPFLu(i#4;5ynx6>~W9x%ibqVzDf4n_8u5?~;}Kl+18uWoM+OiE@VO#%fkK z+fRgl^J)zqWvot{z4;rAvF3W@cIetXVZA?~JYo5)o1jmg30`fjZ6#Ok+PUD~nP`Jj z8qPSvP9Md)-Sqj(24XRLZ#BSqM+w=+v56(Qm?C*p_BJp@=fUT+>xWw#i!CCf6-rsL zV#}QE^BYa4Douaq_TBdn6WgxqUO*OHY^H2jdk2fGNii>`wx~}TY%1g<#-mFplnguA zX<nKfO&fjt-wX2V{r4V()j7xbN(37*N=m8x^uzSHz-0oT ze)crC$*l6)bS^d-x{b=wp614ETep71wYr;f*{-EI>|`!Pp8fZu z6zi%cd33d7)*g5H!DqFV47&QVEo}sRM7QZ~cMt^i?N16s4qYXq$nt!?(KF!H}CmrR4(2Qnk$oB7Mw;*ogXi8~KJOj9Kg>pn}} z&n&O!4%M#HnYAHpWB2kM<8;a44IU(#d*}8KrT=}h!JO6~4H>88N8NW?yq_@x)llNz z4h&mJmpH!poGP?MKd5l_mfK};c|eWD&`m1%ICBY>uGWepjyXnfQyoiANu$F1t>!S+ z%Pso%r#K)YydKw6WY~+!rlSk%(hkd{t~bv&zAmTz>%E_`&3&>3 zlr(noX6_XyzVfV$oGZ{*c|ChWibc)ial6>HLr?4Z?V(R|N)OW3`bqC@{zF9w?E&lV zE_>SVzQ-LU&a8;EN6Zu|iETizsl2eY59m{8B4%Y;@{MpNas5)B6>nrB3HR~MMSI=G zph5;2)Oye3QnUbJ1r(~VMx^C4N}@YLfF~4CJ)^vPEL%;4*k~#LRDcC3Fd%6u#Q)%K z)&v`U_g;6U<9UN^Vn!XS{+Qj0F$qE2#Ft&{*#$Z=k)q7oi!Oj+`8rm324_)*W%$Qh zHj<29tTtQMIy^a(kNN2<>^QSma%1x0>08|>Ze0(}-0{^hUw=hCC2l-|G5-pS2VQ*vKeYQAL5;VBCvZhqd~ zoi8v*F7I=NFh+don&mQ+Rvn#-xpY(Ms)X(aUFnTx0y#wY;RBUgBIb$PJcqrnKGx*+ zF?#CHDvl$m-Z3W?JTP0R;I`MHNZa6Z)VR!9@Fs{QKHR`!`x&R!(#v$F?cO@ba)Tu9 zZMFZTl|-(aJLWd^4bIq*Ny^|34s0-#a=YdV;nwRJxYs`n5jHeKX^2v!L4s|nlQ-Pm z2l)8>KUa_O5Mo+3#czar5>W*1tWwxWU3PlyH>z8`P9mpc%IvC z?H!xSExc$NRjQ$otF};EDdhUSLOctE>iEU2uqj`2UY+$wLxu%Z=6sK(76ZfEUbL~+_!6d!-eTRnYZA7x;S+E>8Q@3PIo3%17J=2K?8x9)yQU`+4IEk*MUH*fVoFt@u2dkz`8-q0pelx7zx6^fw(wT3W!=+;->0A^~3HygRZ#Ho}2;F6lv!e^d2wipJJ<+pR=P zVNjM!Qj1wVfwxAlT!Ssyq-C<-_P9pO}Dt)HqHV{iiE z)zPF`I&lKJZ>-ztUs7{#D=%wl8N4F&X|+IH=~nQ^sr;>cODC6g zPO;&Ydf%?VKDWcI&Gp|a3;OK^IJY4G@%-qJMN5q8Wd~!?tn}4@yabP?%&y?gBq~-n zbN$JsES1K5C6kRhGxP8n@72||;n~9_2gIz$?44Qr=amn%yZU0Ub3{Bz8Y|k^&MG0| zh88ah3{R&zob_k$nPqu$sQkKbd?iEJS-o*Ix%V0iP0p}elYqyDeQPT_?S@d_YyA#y zP3Qe+Hvv)qpuOxK;zg_8Pu#^!I9^z>RW!W72}rfC>VR^w;KQYMvL+8yIW}3K}p1PMbte3UP(I&BJI!7qHc(S+`roqCJJc4aWGLE}IuQRkMK{YSe7Q~?vf!BbaX zw)s<~@+0@79JmdhZZh0)I6u`}PJby}0wQO(cFia$bqKHZWB9`o&5Jj>zAX7C`|2+s zhAa-O7f0LWoN$7Djk%W);EWCS$n&F;>&aZQqovrA|l@$Cpr4ByKg9-w;o zkiSlUip5m58EP{~D&rl#B+V;e%aT3m*LimGQclB&7}MaOxy&Z+>u9+TL)E2DCm>F^ z&x#(TE7~nV;0zhKWYDWU+!KNo99sfq=UW_R+fD^PatCAaRl(vm@TzugMIy2OZxi#+Xo2QNMCTSLrmTy2{)5RjzxV5ynOzRtF` zG(<}Ox^eKql7LQBK+}rs=*ok}!qss88=hIE) z3fm!9EbQXW(om*hd<*$S-0*Ijq09>Z(T^-&j>KGWSNQTuwQ8rGSp)(*k@7rZ?N(Qh zuDq_XAx=?4DXxM^vWyQ`E!Ux`Gl5i%r14hOtMH<-3YMhXWRWjwa(eCiDg4Z}Pe2pN zzR}UTi7{u62d|sz!^`1RZlGV@Tz+Q=krpz5wQs|?H@_w0)=>rP2Euk#9CiRru$w6f z884uG6*03X_fVd9N`#?r|F%J19>d)|sV=GrH+|wstNcf<^#^?gEgqMfBqyD`xb#`~ zorv2k^$k2J-ia`$~cW!84-ylAc2+=!`^7GAuQN7yy)7%ECp zVlZ4BmeXpu{@&ueC)Rq1&B~@+Tl+LsGK*V&hF`o0M&}9fpR_ zd*Vu=g~t&C#9FRTdae^RJhUn^*uG{M#mkEKRJwd%is!mttMNt?Jz|l`_*rG%2dMds z?Pimm-1}~$-FKtCb*lp&v1X5c>M9txIb-2eRrz_)E4# z8jVHAA`U+DdM4l*MfR>49UJh5^Y2Kp~lKgmRoIAh@eG2-O5Z~wWzWG zAqU}WUCUYr*%pTfl`Tuy!{l_G=du`frCVL7+%#8oHdaSRV}u`wxCaEh7=5n1yLB)V z+}rtmvFFz}U(DGdxK1<^cJsjP%utk-QBPeQ_w2(lBmr2Jp>grB zR+}><#plb-L2Yfz&ulE@a~H5~tT<|<9yIGOmOp3fMcu-AA2$3Dkvl9GS0WZytdv+* zyeiVR7h_c`Wg1wRHyi%kzr7A-#6FbYEW6LTv)W@!1^26HGSv!Q?cH-4LDW*Jn_dc< z;O=oDx!7VbNtI_IV%~^2-a6_bK)ETWALy*C>i3kls~xEXOtI%L=h&I4IH!Iei@$fb zgS06vi}NZo)ibo(?L96$&w7*c%PaLZGD}({xgJ?(W;t=&`CDAfFHkYA^0B;( z88E!5+=N{qvOJATrOt6R92T#w#5s_uAJ)}LRvDpHF*se(7qPzGzy4xNb3@E{P;UBl zv}&&5>!vmW^V`QMN4}pp?0LC1N~{cuwho^@oCRBRq`O{{^L=8R%@4fX`_y&hK6BmA z*K5qN75KPw4zTj+uHT)O#gY>>x?bP|o4iMIHp_PLNXoZK{>u)R@bSz8^JABc{q?;s zUta@$V`ZI7@#FejV!6r?^LJ{wMagoU{yF`4(v^1?mOXaX1v01ZKPa0?IU7{RnqgdI zsgRRgZroUoJGN>r`u?DYsgza|Pj1*Q`$qAo9A8@zl%vc-5&oouOh6YU{CTFSRM%dI z3QAp&QVv)!mdfeQc9Mp76Az6*cCtv?CJ3BC9 zp8ckyc$q3@TTthUfR9v?awOx53n#{F>3sPn`iz8__x;%NIYLDxi{2vA#ZOdQhMo=y zIz$vz3@N7xZd2;ul{MEO=u6UQh5U@5kp#^uZZAH{3yV%UM%%?!*KqDGX&8lx-S6mp zeF7rYc(wVI$#ft0uc}qjS8GI?LoItc7q8dX0$-haWp*QxdG#{ZB#bAZX<~)Z=)kn8 zgBS;j5Bh5Px80A{PUpj4`AH>AnX+GBhrAvS;olV)wH0ble9%AB%N|g-@=oZG@~&4m zzKLe$As*Wcg>_PMm>6{jl}oSM=E!Ys$}ca_pI9>N#uQyg>cH`Kc zhB$@j=Y4j_n}k4<9}?mkpI0>Qy6!yO->(+m>N+3E&=KCCzxr-m0U!Ozmk~eAco@bS zS~rS2wsbf;JRCb))Ze0#jVj~Fz|kshNhHD=c0JvXM$&C=Pm}V0i(ac_XuQ^H6j8&z zs9`@D9NWL#*#)emB5yMxC0?_-&-sn6FNw3Qod|>1^mKbkSKJ8w~VkC^0@a85&m21Ji=v;j?T|nrs4Br==a+FRYDV5m_X;r zqu`|W520u;y$!2ve@nkce2uHx6bIoqv$|hd1yWI@gx(82kZ}(;8e+cH2f4b%B>L3s zj=Jfop&~cdXco*K0Ht^rJb=hqr#b2@-m+idhgs zFTX@cMB0#_XB$^?)`AT{9#EwN;3x9RvbMxiFut&W&Ec9&S{F^R&pEvycO`Uzg zH8Br{F*<I6qs8aBy)c3v?A+UL+h%=Yh4S3 zZhMKcpZ#-?rtdQ@6UJpPW?H0Sw14nME~&pk_u@aaUesc{O8?}O0fU}&mPCW}%8wr| zb};=hXQ7ueP`7{aTK6F_g8rH8`f%S0Tvd~vHUVh2-|F$-j)p)%bQ?u|;*b0yZJE%J z!^8eyVfUGB^OUxSmRokN+YV~gbeP`x#rMHnp_yh*Z-gJV=Pq{f_Q7gU8|ExTN`KYb zJeLNzuS-p9Wjf!Yt8<$YV~<&V+1FHC2t~M5oPL=|`t7Z2dy%K9!aElgn9Ih+4erL_ zFsZ+pQ=mLQ&>+7*aO5%_9NJ1ORH^8Z|`?|&DRUIRr;h)Ol&2j)e-VzMh3G-YCFX8n$q?sr<+lS zZ2WZiY=ujkXvWj8np#?SyzXX}4dkcFEbHZez8U5eWIjJ=((l(<8H$(O8EJg6K-2*U zgVy|yZEyF6b-R?xCcN~0aN3Yp=pw!-ws7tzpWNB`%sO%DEvvp!_ru`+n>cqg@ID=g zT3v9PpRW9YvZ0A*tlzG`{t?gG-AGunl}ex1u!_t`bB?_+1X1}IErJ-=Op(KJOua2b zf(Y0jQ1S?y2z4I#CTYw#gGR$3F=emk2vc0!nBiL>w z&FFR6^)D{Y4oI1Pcj|E<&_um1*<-m$S)20cYZNaq+cF?X8a1Jts=aJo_D$s#ypVp< zS|Fr%yBMn_JsVRs($me5jGTIR{@ql5qG@D->Feb=!r@5Z)XJ4svP|}1A5x1!>09s` z+&1rB3e;p{>67u`nOGa9foArm;H;61#2d2!M-z(roS5>dQz_5c8Ql>AXBc3QBikFj z;dhMbt9~b>vYy^zhV@6pg_4PFvT_#=Rlw73nc=D=>KaT4YIm4Z{(d{EA`kq7)pvu2 zXyW+mSKZ>XMHsJN;#{N>I(s3z{nUby@(%1>I`GsKM>KE^D4;R9`1Yf|pqGihrX6M5 zs-ZGPU&$djCBH0IZSWuw*}WM40dk(4(y^$|?`cvpZu!qb%@Y6Skvj`NAmgVHL11kQ z2TEj`Uw~11rxw5xml|w+XW?*Sbv9GQTOHefS+~mP*?IG=Loq9dTXBE=&(0+O74@p2 z*KW`13rvw2b?2_S_tuM93D=efn9)z*;HQd?(%f7;r?@Z#IB_OKj|ZX5n%;tG!b?^HJ*x%DB2G4s)i38p5O_mRvANhX`( z(JlR2Y9Qgpp3RRsn|IUVs7DdFwgQH0)Xh+xl!r!T)e)s0g8uGItqT8+>{`zqaCOj| zmEk?zrPIpLn;ELd5u<~T=G*inb5=gKear~*71cQ-ZGp)T6-T}QKi8%JLd?a$wIoI6 zb!M$-ZhlY_X0%fkNzjA2*>7IV@Ds{sW))B9SJxSLU$)ZvnSG5aicprnfk(ZKowYGC;DBlHb^8w{%Q6D z(uH{VLET`0`!gJuzY5G~`4$6T>~mA+u|r%S82P4t-_W0Y>d|LbvqFGR`}#t4+}Gkt zz}8(_-o7=&7`IBnFO(nb%qu>R_AJ{qOfx9R%#?|6u$(SzReE~7mA|<$@w?se?3=;A zjF1QmY3e^bs(r*UAAi#qc(^Ts%3%cM_ml5s=vz>&84n}6aB71d<2Jf+l)bElt(3Oc z{UJ-y*&!)*rti_X+Er;L4l`O3zap=8W$EokCvkWdJa=ta039ikFyQ%H9?=sN;<$(@ z(^cN@oJeLmxI8rStk)93ZjCnjWQ(=I=H|U@&n~t&mQs1IgYgxOcpw73L+YB)hX*p=$rl)=-B>%WjBR=07qZQ=u?PJ!GBvYn z{BA5x;O-63j*JzxvwY@}6T--5?--cv`JGA?nk5M_mm#QLp53Il((;rs-T((*vHfs}J5qB2OL(p(y;6jPV)ExWH${=rDLA{Z3!^J7nv)t>DOHVLM`Zp91E z{k1vZnF^RrDD$BV-f@V)rw zcVHtwjM9e)O^5%2zY$2oTG6{FOOPY?<`p3((~BJ)Hqx3g9D?xmbq>0cteBM;SbqDt zIKyq*RjJe%8rl##wwME9XlMYv@Oo&;FLe~{BD^cd$Q}XEb3;PUH zlknV=$1KjLv|^VTyyYMlB4n}#Wph5-LTVkGeq6hui@s_vTN508w`dh{#M|- ze{k4yEMX!8mhYSO_B~DWR8JWj`V6pXIG461&v+PI_!!5vp2tbVtPOVLqAt0bVXpt= z3k(;%8&3Hnr1Qv(tHBsv{ZM&ElA?E_QeDnxpv!H=vbrABZ6T5G zo@9PBHX?^>=d}jO5QoVBIQog=@u_9dLg>TfZp`_1+mY%@k`+;kW@E0qHR%}?JS|w+ z25W4P-+atW{ek<**Z4o;&|j+y{}={Vh0g^B_$$067SCE3%pV>ERt7W6y&8GoiK1=d zEse-JrdG0ARgDz0pz3cgDau;KZMS`ci^Kai@Bu+qZ@UaAOs;{uo%R=CXARk!My^ia zeVk4gbFUm+$J~ejtaeIhnuvv_=igxYD}ii=Q=UoJz4g2lV{=~qa82x7rM~2o3v-eV z=_N*k-dr^SaL#AHM>w5F+$3cw{LFqw;N7Z(ZBw0$1fQ*4gV%V>qk7j{CVqD|?=HM> zDB1yz^gjt1wvr`Zu^2rKnNfw_knKB7sce{5SJaD!57FHbzgUeT3*N>z5Eo?5;CX+9*aAY!O9!1EWdEG)&GeB&~&%8CQ zA4};GP4WlI$F#jFWlXh|7WyZkKFv;YPjaw90sn+5I%hKU4xg-XavW;BuPUG*mV3a zxjNVT={o)@?0a!vG1bKzcEg`MLM?Jk~=k?6q_AI*lsO48JpK?Z!x~+r6jeIx35jJBwG`1G`2U1Pt_Q@Jk;=)VkZV z5e+zu0&rQSze={?RNftK4f=gpE2H=5kjsJCjz{1B1wO>ZJ^Wm+{Q_jKF<4EzR94Bj z+nTi7frzw_*<(t8oC`(h)k2593B+)?gZD$igiRH$^|fzH_7<9yObXX)zxB++BS1e) zjD$q0%nEmVI1XKp=uHi9xfL~}xwFhZ-x9JBL^59QP|@VwDNlXc-x)nREQ1qUF_jr@ z6a0~_R@gm!g&h(kfq|;ZHZPeEXsIC2@sEECERxX7(rFg2?B&H@fHi;&|Vp zp7WQ0c=S(MVH0u%JLiTLCrf;vch)Y7GgbKC_P5|7!{=SQBxxa56XNoq7fhLE?HBMx z?%5AsBK1`=gRyw93rNG&=PG@KUwnujY&9J`4aYEs?%bTC(roFt4v)sD>+%*Ykv{AK z`5KJAKK|zR{W~60`l2>X3(wr-rq_B+U*7yf^b$k3=TwpH`^z~8 zOMSDHPY%<&1=VS_$hW*brT+PEsE1C_ip6)MsX&3yG$pej~cSqC=D#;sh@~pP3o5?wj32o~~k{R))&Xq75kUa26g{ zyU-JJ8KorfCgz#H>P4^%u=bzWZTHe{dWYSwLtYmrektutCRoO|ZWNLxT_)Xw+s`)& zCe2DE6cn8nYAN}xsZt+BR)Pf4Cpr}_0xx2UULnnqYE6KkjO&M8gKpoNeN?f|y zWolQuwx_kg6;7uZ%Jo`%tI=vib*7O;oCAy3L%po~bWLm==ro?Q?DoE~+T-TN!_hTk z2f?PR^Hp`N>k_%V(%rhJzEo%_d162PR7(7pnmGx`qvEgG-X1f-%CuCGrVf>q$`fUw zIt{4E?7CN!P~9sB_I7ez=#w^rKo?v~4ykC*vT!DWR2nLYHyrWQ`hh{5iOpvop$0Is zrq@#A;X8NE4t)f@+N)FFU9&%f_=5@?dYub0l)|9T;Z%TYFr_Y1bK0A7`4Bnz&FYdp zmAgtUQ}-5@nudaNE!_)yUk7p1a(AcDps84pX1|NlZCA4gJF3Qh!OB}xAwD^aNsyax zkJIf~15(P8=68lcT4#F+kV|en(UjS4KT{JRO_@%wc3R-H@hf4W3x^>8jlB!#P(BnS z=;9LF6O_|TzC;I`M_094D;dwI&nNG^kdXD4=)ijY#AF=U4*gCk@c3utXk6kE z7te2TOu=-#i>lU9yso)^{-gE6^rs=OqGUxc_XZ6P=pTC3BF!5nMwWHJ{y`^)L)?J! zL*MB?4324?UOVM*zJILfpILoHO<*7b)l~W_V{7E?+}mGHX4lo2VWr!%5~|>)iioC` z#S2zeczr~w+^+|K(S?Yp=8Ry3L9Co4@(n{MHig}!)3w>s`pB%>!C{E8b04pDWOO4Z z%40!Eg@qc-)dtYlpN-AN=Gk<)$qj(bw-5IHi=*lm%g(nC&JwFCAAo3;kV#Zfc=GNh z+sHo-3^ZX+2O3vbs9jd)wM*Z9ykEY<{(Ok?-wl`K*^?$|6mjeUjyNS0$>={O;Inse zhEUkydHx+er{JlTr|7_}3F;AN(v`Dsp6UDHx?01Xy1^aQ_k%PbI5IDDStZhyi(pym ze5@k!{Ey7#<3Ir-So;b1S-w^M-Pum-i^4PFWw!%nyA2XJX+W!B*2yl>8t++RvH;;n&|D#p_JzV@ZmmH1U)N)jdBw4+C-D;~rqVGlcldLZ@eRXs?t`u~*BY+v0*6{vJJc zac{Qjp4`-28WZpHZL?0_$~I^cbok?ZUXrG}|Mrr@YXiae zToYTYT*jd$0MpQjKPgY?4m>Wq#L~$Zr7Q`Jlpfi_a+c=4Qn6PVIKAi@$)9}rID|oz zkulG4_Cod3{odQKtA7s9I8io3TcM#byi)V8L`Ai3pcKEs7<*PIaqW~&_N@5GAY3Ps zo!Jq9nAXTm5EeULD2;ir?iMhemn2+(u6b;+`RLX87_xJh0`Rw**2aFvQPzEFN=7jN zoc%$zP4sNajH9Jr_ZJ_z3rTH)$q=NAMTLWwqFrMfw%lQGeg$ws%joeT%72Y#uE`Z|U>w2X_iL1a#L0;pGqqW^yv+1hwF<-Q9*@uW*PXPkkYH0>82(~?$ z=*AwMgh%c*sn-v7Md<*Y+#{QQ51gs?7W`^|sJ6V(%er$)0h8$&=UfI?YTu@pr1iA= z_ru2jfLVV*GFgB}qP9{N3WP0vU9(e#9p$W10Z8c6PGn9!mJ|$BGQPDH=GbxS?brgd zisHl=sX{VtnW;+$*zNh+v(LX7@Cw;?BE+^fy&-*&^6!g7FryoGLa>YCM5P9;#3qb0 z!js(IN-g)ezESX#ZyF7gTPJvVRYVwypF)3+;S_!ZJVaZM*q$C9tZh^+-F1!nHktdA zPq(R5!k*q2(JK?A+wB&-iu1Bb#?&H{8d{p#8#_2V_KiA|V?6G^>g@j!TLgw+W|NJS z1Rj%37#(ed1ue#NnniRpAqML7s>WiE4!yK=PIjS|vDaxCT>c>uE*zQVMP8kqBOK=> zZUV+z-yM3bK~%NA!);t(4T=*G{m))zq_+N zlJ?Ecsj$lzEr6d`XHrO@QM)RQI149ooWWTzIJ4*kfiwT7FKr8P{SsGI0Ht@yTZ$FF zm1rK}m$mRFKz`xC=OQL%GC#s(G zHnQ|Z_K=s}fp4anp%+ckZDmvi_h!bgFYPv~!Nz&u(JlaSR`NWL;4z7wh@_)M9bL0Apq4jFVtb=OGZ*!a@ zV~AW%5uizF7P13)y8{Xh+fa~AZ2fAc<{jn&v8t<+^uYKobTvk411>tl5}AtFn{?Xh z3Nl|rU9WsyjBP%sbQ(p7-1lReD5Qey?*$=!zw3CChF7+Np^bg4YWShU%k&FZ3 zI$Vjp)F~G=6<*){{9wjH#=bp;N%!m0tgQh{&A$Ta4!a(x$))nxME_e6l4WB3`Th>W zyogof#IjrpX03AbaQ`3r&Kb~GiB@3>VpT?-bEKFnnh_n6h!ack7;nXV(08$p49T2n zl}XbnyAq*|pysEXu8zz$If$TKc8QCi5~fzG+FXgKov7*ORxz09HQ=NW+%)`Gt3gz( zwZjYSXP+N5Q`NMH(jvlX7h1~1oGp`DqQ|yoUhWF`fpL#K_LN{2rP1j;QZ{e&s#5Ni zkDsnmx%?5t+n}F(gF*15=4Cw<3V%n>?^}TA6^GL}j)Qy1g{8JeTm0Gm`s1zZ6`^oy z!*7HvTd~p#k_rmbk{2zX=(@krp>k}e_tkaQ?&PkrYS4y8EIvIb#kQ_E&lnmw;Y1=KpbJ-SQJwe3+aHOt7!ys1bc_3JQHz*cnp}ZX(EpG6U-SGC=KZzN z*<|ChVZPK&`rrUeZO6~WV#}f-SR>Bk=)1*nMqHB^(SNA6`Ii?SjL}c5zV1z_vVxp211%qkj+c$Xj-i zP4QLRV%5*j>86!n76Ap`HJjpI9uJs1RFVh6uK^j`=FlH?O#5GUi@!X5_{r7J4l2B^ zach0!-qn%z--3B#vmw&$U8LARBZn}o5pdzQqAP3OxnBiHs|IIvDV}O+DicATqo<8B z#$X~a3xEnLG~L5-8(_N;bKmr>5tWvyJFs!mn((dj+4qjJUkqR(h%>oTpu$^{>j(! zUdqEie*uq*D)q%$WX|2NkETdNlLR}turPj;Ur zsuIWg<0XD~rn`@(c(4lvt| z(N)As=N%J~?QHV{_yo7iPhUH<$IW-hJu$q=A55BTmx>N}M(=#I@6_w_!_^Z5yQW?2 zAL;e2Q++;K=ETS?j_7^X${m*zsiY4(<=;3i*48aaz%E&E4n1lT%fZcy%M>8JO#)0- zA4yV>V*b^4pgK?-B1uyUL7;TG6;W6QxgjxtNrx{WJ5AbikYK zg8hYP9&f-*wZ+9hGNgT`t;m~Llm8Fw`ONxW&vlyqxs~g+>D-6zk0}u39%ZUoYIKPs zLw3fc4_lS-^@o+tw=r$Y$fwOGQI#$KERr#e>RM%7crF_GIr1`IIO(~0$)9G&EZB=g zQYHR1!Wc5Xxx0B91BGlK`YZ-+o1+M*$NvKRznZO(*1K@S6C5q;rli=$Ehu^Z$@t8G zTbJjrOLrxt;Bk7q5~`c86bg<sRc_lZi|)Q z&q#u9tS=?M?*IN~X!}lwxQpL$gLlgz&FS&$CrePBIebGE+>;bYe}qMqkN#e%8v zlzUrC1C&-+ai=vDVZN111Jz&qv%tk~JL=W4>Kf4!ngHLnVUjqo(rBHI6s?j%`T^wm z_GS6r@OAEDHd3WUw5a~z-VXiiGg5tvOW*|cxa-JQ%{?Z+VfXIhuQN-|cyZ(Qz4~fH zXgd`0=b}f6_++Ot&vi{zhez&V3$GP^ zB+Lih3hq0axiMh$F4a4vb`$YN<|f#C+vX2XJ;sP}3vXpR$nK!{&@uVJ;LsP8h=um@ z=C(1nBIS)45?Be!Nb~7*lFU~N!EAZw)tEk(CRmz!p=W2A$>pynARmnWzZE; z%DFPzjKTiXvozm=f#8!-E`HwXqO46`BfN7s+4E4WM5P@zeeZv;U8Auw0S$`xIsff+ z`!7fT$4CRNZKxNhR<>s#G`RDV?=hz=3u!=!afALdL=BO0Pf9?Fc)&V%=X(!gbYXa1 z5;&E1K3w?AV(+rfuhJB9A*KlB3-yo06B&Lt05>ifi0Dkuo&BiW8T7vRpvr)Fa~qUr zWVZ)fTA*@m3wvE2;r4mkPprSeF$1vo@v?YBL9N~a$~Y}^tQ7@Z>&X3dt>q*PKM)to zum8$-vtYO(Vq@J%o+_m{y@1hN=IRMGyq$$&DC$uff$AC|a7y8`-CQgJ3Wm(e6sRW^s4^du_OBlvj)~x>XOu@Z2%^pM%JKd~VALbz1c zYwU6 zOsQtsYi>{LW`GJ-eQ_$FuEqSL7yqquy#f z_f*0dpSv_XCR0|xKMqUgPAE?A_}$lZRP zW8aU`p%HBH?dSZk5TuDbt}X3;cNjtEvY?k`jYBNU`&_C|ZLX5bFtI9H;0ir8_~lAX z2YlFQt-sBK*%mg>qTj@O-z`u2>UUjPp7^HzT%DUvG0c9=ukoC-3F^VUnfr(SXAo=)1XO=9bFdN0M#w{ENbW82SU{l%Ae%Pe^Xx#W(` zq?oei#%Y^7yJz#`OV^z6ry>)|yqx=YGAU^xyT{JfFL!=t3hSr)&20&7VJ0U}7|0$W z8l+}TmA$K^%6O2{D5C&C;Mz&n+KA)#=oSCl(Eb0Bw*LS3--}Z))|e!2+jw0Fz5fSp z!U{Ie#`K@_=O1{prVtdiG;vV6mF}k1q_JStSfdZ3&~LC5GV1UdM&G|j*W_gJGrZP4 zrd8!<5$SPU{`uzqgVv#5l%Kd@NqYfZxUZT!<<@1+<}ydIQkxE_lhQhiBYL|S{| z@)RQ0r4WNLCp*aIU%8(m<#A8UKa6d#1SrF9`0A$W)R|T#SIPs3(fc-LW>gx9V1)%( zo(}=4UTYoj>JxW_FVqcQf^55D@F02quV@@P7dNbKsTf= zJ5Sr;DC&IUwq^m$>Y9eIcJ$kaQ*HMiRzc=GG!3aI`=PL=TYZfD!Jm~SXs8pq`1cp=#`&Lx<%59Q2-r6!*-w^c!KQWjR8Ge36<@;HNmEc&bj%R2`k1JiA z-c{OYJl_|Oeq!b|(>9v#EZiR1UGGR$R4rH=KF$&D=bA8WK6w#7vK%f{#`Te3UX-(^nvgFm1)&{p}uMvpQjV0D}-GvR+xl?O^ zD+lkfK83PpW(-YayPe{I`~`dChqNj>Lqo61Pgo&fYi@aK07-T^ZR*{nttxZhI{rJo zzeygH!xKRRaH=l#Yx`D(-HT>gLjx9F9j8#9v*ih~4q$NydjiPY&ZjvkA5N*b?q3vN zxkv3=bi)%G%OC$6^8dIgj+jzuAHun;RN;H8osOA5`Tl6p!xqegtuN0x8i{Fqen7r( zg)Dp#X1)vnuAjOvYz__8e|DbK6bYlrKktS5ev7u|kC_AhVb!gGjzR4_!$LQBzs%$w zw~2ZPnu6)a_CDiUm@@*P;x>Ea-bD0}^PE{tX|s{2C*)~O+lQJWJ!me@mIhIM(G!N2 zxOx_IX>Z0J`Hrb(w+b8URGz~iq&!6#d7_Rd-N?dstigAhl7nFvYqY1%27ppRkG!H7 zhvOy)a|b49ja{?rS+eL$I9QsI3Gmsgex2tYvc7}wAg4DJgb&Kr%L{P)+D|@*{p5SC z2UfU825NUL*i(8~AW?~TUXOC}he{F{NrB*&?%2EN#>URE$(&JTeS0$sJHW#dNP{?# zlshLAESL3w9TbEORo6bu#MeUaUh=zdomc<*&2PMU<164oM}0T-RVLkd`J!YWiNyKI2mdY> zK(^uMrW`rExaWwKdO?s@yxU@c>KqY)#~5(VZVsq7G~iuSuE=_ z0ti!;EEeQCMig?;S!LY|x6oDIzW2)udT`CnJ8y7eRw(}A;8P{1BBir?wirwTJ`+cv{73KFsa|5dhraEH3$sQNcGz(C zi(dcQto(l{mPTz`n1l?+nL~sYmb@9N8uT0;M?ZCLSt>`s?S~(3tg~nf;0clfjk!lf z0EkPg9jlVS6{_%?<^d-n>zuh(!^fPwXl*K{pgRCbg`?$XFGZ+J=5#EvHULTozy6@q4zFT=)v~0JdFMai94a6(9n6T@7ABL zDunz5?GAIk?G)aP-jJbo-g2bZQ@n`x)wx*fVfdv#@;)kL=&NcUZ-27pIlx${gmERMzZ>u`S%{szS zsbJ`idXHt&uOvScgT3T3U%v4qPG7mL4Dk-LkJ%uf5paYA1V?7>MHfpg9j9z{o`VhmA(FcWh`%6i6HfkrV8i79Q zEC?5_xPL#KgyJltn-d7hZ3uM=ZgCfc7fhfc{tfPbNyp)q^ouEtt42_ zAAAJoEZEA5rFdy%>Dxq)G&3O3%!dJ(u+j2$Cu{h4-WF;Z<~9r63$!X9%9nMe2cQf< z47IlOO@XNp=>GF*7n?lN-68gQ#s$_T78T%0EsM1D_I?m*j~81kL#^<3GCGKz?be_{P=$O=$K z+uH60(k81TRReWIhI&8dUf4KHO{w->y*oJEo0x3Q>3xM;Vfm^-k(KDIB8uXv?By4O z=>3H9Yh_X`laTUmOgU5|iox7l(=OXr93ky&7@LB!x`-`BKrdORlUNOwQyeILc0AsP zC@8gNC3TUUdk*w2R_CzY3ccpyyt}^LFf9{4P#BIESs(%*&$;%rFc-tCY9#ywPrNnt ze5ZU)zcEXrTBB2S{U@J`gl@<)d*AABegS`plcrT9U}y{=_cj&fG)QbpMSz&(VxDYW;h zD^9?R2q;v7?03MRynhGnU+y+OsO{dHnxZ+$roM?BR{^=lDIQp&XlUO)PT)8el1Mm^ zWtncf>6Aasi^I>$3w9d}$n7@flymIfyxEaP!9z#Awz5|}PMI~|Gw6s+D_}HX&0L!dviJfqxt!63?caRgquuLW4pIpP2~NG8^;HhmP3GB z5h^R%0KeV!d~0)=uF9q#fDNxJDkdc%f=b!*NDuSV7DN5;A2be>sL){>O>A3 zhalteWjo7DbB*zk#RF+E!d-aW)V%o-UghG3tF%DmK@QZe_}}RMho&9=f7)64FOPYye`@p@_#U?Gcbm@`mS z{%vc&b+{&)6j6Uo0eetO)^45_Adr$2dr?u+(6FKHHh_S&)kl4sY^AFL~a{_@9V z=ZUx`7P>i;Dts@^FqTlDpL)u$g#G>zyC5LFHfgX{x;4Ep4&*$Mz1zz~dNo~A;O2ba5@URMFs1LLG z8YV%gyUtLiKU8+`G}+v1Kjm2Mo>~I$Z?GOJT(f$jTi-mBwZvGn`?4RGjMWgGY5mEk zJ>*4+`Kqd>QrWNWx})*s)^By?J^Cn&3@m=Ee|7?Sr}G%qx9bOdR{Ytv^!Ong8?-j} zEvcP1DXUGF?&q-&d#3*N{YOMP{81PYvkqZ?1r&xuoIa_^vRvDy-6EF>u~6>(K0M^L zzV(eH^vegW7F0*7_1CAc%QPbaePM<_EMSydbgi zI=!jK_ab^`{-x1K|CE^2+bULalb$m`rRTOzhKaCmexCnweTXkSoL)QMA#tT=&1TR# zV%X7kXvRl-0kC}#F7nLLqzJ0PCZC0RRYT z9S(0fIAZ0SUo@%eL+hyLn+YA-F?L^^>-7sd5X*6%57vDF^9gE~_CHO%=$%|*qY#kZ z=N-n*>Lk^)_?g<-_!^G3M9FAwfK{(Hwo@dcTR-f@??0C{N}F_G)m0s{Q86VD5YW)< zi13*C$M2ED;K-M4OaoY);eiaZkL>bVu#WY{wN~UUb}OVJ*?y z4>Hu>S;4BJL{-f$x%}iS+Y^;rMyx3ak5&x&cxd0zPi0Rxa76Fjot@(_am4;rdd1hx zZPAP5i*MN-J1Yj`so}FT&8%_eXl+YW^qJ*3)@A_`8DNAlBL}yYZZZC#rNADiuSq>w zE?cdBwZ7UTruDpVg7V--2s`-o@lIA${j7d!n&zg0(}AUV$EcAWc_f?ATL1o06Buf{ z*v=pAkguU9l-OmLH|Oj}Gu|6?^e&m11H1Z|1O(-%Ij&V%dz{z(+!y|q_mi*MgCL|p zxEE*9Z#?~yJ3Ot_nM;ZcROXE67YoaM~ZI^2MI{wc{} zth+Mw@y1U+Bkqat#nwbfr18gfL#<%8B2BG7Sb6D2ZB>*5?S#Z7gDo=Q2*^R{O~c^l zmD$D9ig`VtDu^@b7nI$@E4K+Rv4Wc3AJF?h`J_O|6q(MaL=>HfuOFr!eP#9In&6z6 zYa}jADPyQ>%K)b*wkToad~lgkKjyq=mF8JUU|T%_o6k!``akb%=yll4uNzt#?|}T^ z?_c?Jgh^$5{y#o=zH6|{yi7QK&3EU;eC?sVqp%hg0C7*AyqJ_fh7C4w2l57oL#)r> z;(}0zLMHcX7eET92{H5bP{g_RT%XtsK;$g8l|??!FJiudr+4g(sSsy~G}y$}~G^GV;tcB{Qo;&tEL04t5=OX$e4=C8e3h}E?sQhlIVymDKLJ4oz_T6o7V4?$mk!5kRHVl;lxzzUO$J>1M`2> zW&yHyP73U684dj-1`$e~A>Xv!xo0<-cbJRlj;bB)n>E*>Tlzw5q94dg9l8GEKxJuk zD<`-ii#oKrhC34lh=U8o_%mdT`3*d$RrwRgGl(4+dd z9KvTD^MNTV*uTMJzw~PyFpm;C`qs8(eLib^YF6?`#rljcz#hHBy?Z@nU=Q2t#aC zh_()yEjCa%RSOWLmG@$TH}&Fs9h~v|mZ^SKHMxfNL5wRQzZ|mImZrLvXiup2AD3Zj zb&E$~sZU8Yt?c#EaJ`gt|IK>piMB4H6j<~57Hi?z_v;6+n3zzGf70q7$MWCaZp}`V zgQ1%D>_r4rC?Sv9aZ9D)=uDPv-j4s3Z4u0})UfSjr_+Me#gCW&6l*}`G$pf-zw6m6 z8W$fChN%qvnQ2oaCWcc`0i*`gip1*fG@YxH*zHk3bg6c1AVF#cJYJvKW|kwhQdw#r zZA{J_HcYi1m2=N*1nFd7XBb2GcJF^6Zge>Vhj9Ne-J{b7FaC-%@IZuRZr$%(^a=@@ zg_Lob_)!8z=Hd7~Ud%qEB#7l}I{fbux99e^Rw#a3BVTeC?zPOH9^7yFHJ1kTZ!Ev9 z-9EwHOXbc=MVI(V3}(v5SyV;dm#Ayhe%npXJ?WDKS$92vXEL!RGx|0@x2c2I_Hw52 zH#buckOp6O^Jcaac9QX1iP!x$+v}O2DkP1lOHHyAfw9VdU5&HgsfY<5O7QJR8;JRu zAHe=QGRd*Bd$i{Kh^pMNGcmaQVJ|HR++xGt!LO?xKA2aR9HJ{AZdMy+P$40x@UpVZ z=QP8JHG2EO4ERry(XLk;U1YgyYJnh!+OKh&!lx;>9IJhdZf*q zUdVWN`Zu@nBCy3#e}|qPi4C~m`u3HD$!63RcXJ&vT_R&3>KLK@oifsjbOI6uCp|W>E2=5RUKzPgV-4SVr^Nbd93vy`X*t z56Z@M$pe)>eBnc1L#yx{L~eUzX|ym^?fhh$tvjt>wXl=4^kN|JR0mFy*s>#^SQvl| z&0kf0`(hiRVDn*e^#In^pgK1Ay@egWUTwJ!jU-8tih}((9NRukD;h5yy2M6*oeLYu zeiGqF7>g&4?ZPNt><2qaMiaZ7t$--$PHj5Fr5`A(GqZL(t>u`GZ0Pb*+3UR^7p_5? zhnn_idP-zlw1*xG#At1R-ihB?M`8O8n<}kQr!#RHSz<8TJ3j zd+Vn*yLWGtD#c3i;>C-*TZ=ozJvbDCyVK$t+^skSLU8v2!6_2lT|@Dree*nffA@LM z{u9nw_YavhnaSi{>vH*AQGe`oDgiH6aWm)65UX=@`9ewmb0gwk{Wc&CP4&mA>i+&$ zZ>y1>t^Rr7zA@bsz8yJSL&lzcnt~z6O zwFS6Vq0e31Zwi<46IMKh=HpUM#Jt=K*-N(aC4IpSGum^1Ial+$1#7a_JUcwCZmN+# zV+0sQz)~83|!nxFy-zROfsFinK&9IBp;i>*~azLaG?0l&;T>y`%+t}{PBq3gE`}}$VT0XODiSSF4jSVB}6}U2WU89uF}0EdAty;g@l_ z3s%O%l_HDicA~wbz^O7N=P^qwTGN&vXGSgb%vIE9z+WxYZ>jgGOp5T&!&_kKRi|g` zQ`PSbVFR07Jks`t+>H4zAo;|8CyuN&Z(o1%`0mYmtD(o|a9`JC$2tRMQTw{4DoB#O zs44T}VjL=6gvOvuu?X+1pe|wvQY`W$_m!d?fwc0>A14oV8v~fFo$*sQ%tTQu&%Ezd z^-D~R6;-$i;ouXmys=>7!CniBkMO4ULg)I1-Lve2-1v*5{H_m$bz|i9Oo;MbN|PPd zD(2fONrZXE_KM=fRA>HR4KnK%C78SW-Uxv{0#{T`<6#xKb1eQ%@E?q?$NY;hkJvIALd;3c0rPS+ zx^h)kKRtmIBfH*ninnTuBui-3(EB<0W5qUQoa=iPXlw0 zM_pm3`Xog*A=Wkm@*d7k%82$E#O?h{M}28{2}eHJXu#Xlxd{&*%iJF?HrBrEj(b{*a0F2ZuG2oO4$3lzh|5sLLX>s`!Ex( z3m@>mU3ee;0O*NSg;u)&069X1y5~I4g{yf{CC}zGk8*Y*yB3_vNqCbl0KHXn-)EM5 zF7Sp(U(C@twvGRqb-Te-ob5{d15d&jrJLv&LxUlZ9%YU#Aob$Z?a5+*|7}?w|JY_= zT5WSz!_}?CmbA`(oK+X@AN`}E+nb!$G=4{!oDQGr$`a!qwvNXazXWq)Pdn3gN&Yj- zDPZcBOwI$F|H*Hy`Y9J#aDK-2u>54}QT6RW1ls^nCKbqQU9mHXg%#Dc)+U2TKCi!I zEW1hA>37LCu$ObgvN-?8DtqbNt12MR(lvW&X8culuZMly$J6~A)XN+;;5>26tC_eP zgjvBkwBk-1*}(wC_0Nxl9mOE9Up0I9-1tTgc)h(?JHkh zh-{Z74;z7ol{|R#$E_(w%-NZBjSiQXvffU$Z{fuEt}PB0Pe!__QjHs_<)4#j)F68= zCjD-fgn+`$>jn&1i4bgL*Ww`EA2N_6s_(9SXy37%TVR4Gom~g!o~aGHnjqG7QP!F* zT8W~m)U~SISFF7Wz47-`StC)6qU4bDo2DmRma&|j$70a&?jM+`t0&V%liFZ_*rIxc zet0xxT$z=z_&Q9>6B$BrBG>yLP<=7`fT4mvCn*z8?c*n2W64bo9&8wB?Hj+cb2?*Z zrhxYt<<`oFkIn+1_3PAnI4P;7ZQC0e5NOYZ!qI*0^rf+{^QAC@hJ~a>K;v)POf5@C zlzA@)+hxs`IN*+(5<(tIi)*N*1R3+odCb)?-8^k#5n5FYnyRVDB^|Qh8~0iB-?ejT z5!Nk+e{_Tkn2l5312OB{=f7l!@6QU)?sQz(C|nCV`VZA2>u?D)Zb5^q2%#%JX&-^L z8QZBah1|MF%orrV21n~6Rc5$6z0kEzI&7v-)x41@ah~26fH3kF8rBOt@sPA& zR?t+v5=l7aPh8dV+5lKBR>gO6l59=j{^73I6@+(c^fkT9&w;h&_B+w2_AD;u?CT@m zeH~^ipL+?l{@rR1?~l7|olG<|rO;hsWpk#^;9=KWMc}Om({2ej>X2`=+Vmj8=2e&i zFsyIHDP3t*j7EErTw+!5ef*`H!ciMrB|VWGT(R9AeL3OAW@xR+yFG8LI4M7;;-det z(gC(zN`-Oy*5Y=;a1Cy_v=0-WJ3Nt1nDM2!*Bv=2yhT%yStI=z?64v3~wKy}y==|wEn>i^~d5$QU?*iK9M5abs zvzafjyr!WFol}qAr#HLDL7X=8XzQ1bCeC@SpInE%Et+Qh*0?>^@CV|a9dfLnMZ>!1 zIDPwZRDY(mP=B>FZbB8d2F+6i6F?61{S6=gqoPqzzAg}s@80gt6d$dPoKObR3CzRt zg%s1c1^%q;GMtPHG30a~MML@9PwMXSJ|l6;WSgLT{-gHB-3JbmF5N}A_C|~ehX?eI z)}L$1uSVyqg5b`I6>>YptK7s1NTy5S5X}6Oo!o|&wjgkK5lhEWze_#`z91wNJTiP4 zj1!b##^If1=YWo6Lh3Xlpsxf{Y0FZ&ZlRew-gfD)eOjx-1dR>e9Led3IM}=$`DTl-n0FOt65?*GOSZhwXCC(SMz20eiJECG{Ro=5UvAYV-M@&&qBC;eW*;$pZ`fXG`;+hfA;iwW zs3Pm8h0SjdA@aY#U64W5uX=0~yX8+)54XlQ6H8t1pZ=oktr{J5U`&Xor*_2~9eLv? z>DrTTjV*bW?99$XCZLwY_H^IAJN`u(?y3wMSWNI;%5xbrVotQR;RE0#j_f+m2}1!} zP54BwY75Smx-#xD7Ld)DwO@TlRt*-doM(kVdf@u1iOE}1I~kRcXTHjMGn9?~L|0n~ zv(@BGQLH;qfYxS(?P=R6{Lw~v3^7?6$kz>DN?@WaaIe0{?Hb0(@xC3)zYD)O#migd z$Q~aL-eu?@g`C_^D6LxxOdz#sKxD!p0B`;DXsN=jJ#Eon^;SOhKzvM0_vkA-CBhp! z(Fl89uy4Q`sB#_Kuc}+FI;J)4q%7M&{cA;ozJ9l5JRlHf_)dJN<|*d82`>mXaF}tD z3(i;p3OaaRC&!h$y)8OrAcMI!Zazfk8LQUXs2<$j%>Tb}M3Co< zg+;xvJXw96wc~pvZ2Za1kP)XgR2|F zk8RB)_$*YgHoM@Gkd*G3}@k_FlTIGWkt?b zmHqLOuW{t6Qf8~{oR8l#`RfpeCmDanL*ZQ3dB3r(lD(_2F9vCtW#_)gfChPZ;^la4 zm^%-izSmaHQ?y0)*c3&sv;R$lP~Leo_f%J=A@-t20Qq&7%NUE!C40cr#*VSO_2-}U z<6|J{hM1DSC{*TKP7)5heHC+@s$bp3((Vt!+15WywQFZDG`6PNdqRo@Gn2U=l}k#v zF!5)FlXGRB#?5dc-Z2R-=M6`2U2Vq@T1MZTJP|U6(x-;;mFQ!Jv26n zab-{YYF4nyhF&=>Hp7Q7WBHm@t~C7f>HTb)LN}xnev)o2egg5&_n@FwrtOh$F?O=} zbMG#1uHJIYZlYL{+Su``ih0DmT@a^v?!8i@IROBPvcnwv=TS0j>t2#HI~G3plU_T( zwfO;C0f^4%!%O7>WQEBeJtZ$vRx_Ql@>N3!F zDyYNfmRH(t5O^Y1`cTs2KCuhEIJhgE{$e+C4PCYagG%>5RuwIrHCI)nto=N{s?(+r z!ZZA{nt3;o#g|Hx*l4BN)-pk}p4K=BkO%(4mGp-+zj3y``7d}peml<*0|qaU+g}fq1E3&J)1A0>i__mS;~5`7@RQRbNMtMBEpq!} zqI3;M-#M1D+9KnS3mwj=dA57n=egGxC>Yy4RvqBt_0#}6TwTc23*=VE%niH|uQPRh z`>myvv3!e_a7cyPn>_Me`}{Aad)#MR+#L;pbZ)y1TjUKvTZ10zE?si#azU`CeR%`1x@Y$9qce!sSUXv! z2UtP8di`ymTez!37;QzE1EP3tFHZvvHSltFSRylE4 zpPub1tf$KKkX8L;S5CRt`P#g>+B@>3kpK4Flz8xXzr!e&-2P20+Nrzi%@($bZIx`q zsOvj4*?C&fz#c=RxC`lpp@OsimN-Rw&CQ_>>Xjy!Zb*Y}T|%Rxp*3sT`pLKNn=N8_Hy zb0(Vm$I1u~#`MnKHTAli3)#Vg3(SJRi9pW~Y_wnM$4d9jzkOV5HkOC#DuAeqp91`V z4^w!V_RUSptKvI>;&ksD2O_42<|prNFYw~)cXRTr$G9seye@Y7Qe%--bIa2$*Ej#w zHu%5D5rqUwN4g`L06Dc;K26swbh8cgCm+KZw5T#4B!$-1C&yI@@#{LF%BnqB&&=l4 z3L1u~ayAG~g`P00x(J+H??%rpsYTmo;GNa@@~1 zx^(PUzC}xvcApJkhq!)OO__FqN(oxIj`?1Tj~SS+sqLqkT!@wb$uH%tym&#FWPLT; zGye0O1WXEGB_Gr^xW9@&JG{V)95Hj^#w4g(n!9P8(xTc?2~B@^EX*kvPhPv6F=tQd zUH$XNzu|sMPQlg{WNYn@w;;-mUp$>2YngN({&;_Mar*1U)^*n2^v%&_`G&jg{jKU1 zvPpGnYYaW8;zWE65J*Ys|Lq@Y`j@=!@3o=v|Lp!*SUT~s=Z&yg@jTHdHdA8qwTS!9 zJ6m2^A1Q}gugFuX+ati)udeTj4^3pY27wFhRW53QwSueMsS7ns_nUkRoTNrsGmF+2 z=1p#aJDtys*g}UK)@xg<^#EpT%&k=qmv52qM5ytyR}Vpg72M7uSU^gn<~HCS3%5vH z`>}g{6X{C(O2vh)*Xz1G%in@zVO-~uH$ZSDi@S(=y@aSY(B65A$_7bdkt3!~cw|`Q z(V;mPt9u6#+0$b8yMIw;Zmx?8QdINuUhJKYhIS})iayQ!uL(HF6nrb>;s}|q{IB&w z$AZSMMHEii`4G_g=-r;>HF2!uF_K~GQJ*Nt+U>W}?x+YB)!$Ryp%!KCJ+KSBMEfxB zwC^xF0<*FEQ)sF3;ZA3IRrTRz|7h{Ag;#wP8vf5y*EZ_1#F;OO?7-veE&C5d!ep~8 z&7%x7!Og|0@Z3)ez8C5vEpwh*xBRXPr;j$!J5tROd&cC0}Q}~e+ zxZgZ`j+|bOg3FE6{Qv)b;)A|~?*s-a+&;TCUYqLt6rgi+35};rd3ymfMd48WRuqULAT&Y1A-6@)6k4(X_VAvnq zR*JCl@a5t3Y&s>4^b}`w<-A(kgX1%$)Pr|c68t$DxjRpT|NKrz7dY^3dA|z-sXfMQ zEWY|HYT@Nn-VP{)UCgh~NO!s(1`rU~Lk0CUlikqF^J zH8;$zsl?0kMz+kfEztK{{bVkw2;5W+ZX4ENm#|lE7C`BDE)-?7d53;oND?`ho7FrZ zc!=V*ec*ItD$|syhf`cGkb8N!>aK!(RM#U5L=v7t?z#R{xxzKFe4v>pED8q;sW;$ugJaSd5sofQoWnT; z;^CT4P5=G}V;$EE*Ixi1j8XQEq&MtF3Y5+gWwnJ++CCkZ)s|m6iXAiW}SsBzGDGRMx#=HF?4yMnIoz(h^vL%_|6KmKGB)dWpRyRZnkDYnB zhWIy!SCM!H_^}~VM29I8U#C994c{Pq`lA;I8oXivaZ)ORgR3k*>SB|L*o}|4{^5*z zcNL}rXT#M5=3trx&epA_N0kKcr*fI>vVu@R=XHCGqr@{UC45gT@(!yW{Kr zhG4bK#-5@dz{%!Crp6d*&;2URq}co%!XFMgk|;|bl@EX4eC*B!5rS2-(I+R;*tTm5 zib|v-BA~t!A)<9!DUlkgHiGS$9A))U$2p%SZW?XuWF3cQE}2ElBQ=Z#Ot zpcXpK`682AlK;V-kcj7~GO5V??k1eLZkdr?5yhQ$@ymPW;MrxCG0s<20XYfevQRto z55GxK&stZ_&N3&#m2me{S({}&FLM5fnpYv_oVddTQnE%vc9vzS;RY}6Xr8H2s;(m3 zeMuyl3g^HPtXw>pDjb+w5|O>UUb0M#An@US02HsLoJ|L4tzye36^=88szObp9vf#V zsZl5n9!BaLz;G9CV88$VwY#3vuUHNWhQ4ayHT;o-;YNwsE^P2{t&*{}3C|UCxzl_1 zCD%SB>cifs=n*Ux7RTY(pK)57ZI#4u(O2G|@ee!8OUjy$h=dbXvvu55)!MJ{A_kxo zR&hzkNv-FB+AAIBE1-U_)F*YH!QEudki%k6?XI@M)=LOFNLas$Ms_;K$EoU|mx-Nf z?opwx5nVpFr_sHDxp-LPGreP0BIo6KYDu9a>}U^M;TeU|I@^C)hsH@2Hw=55!+tJ|h?pl#+fo9rcVl zHrAxD!C%^%tY4ZFCjzl2AWGAyH~ElmjYE#E=T*H-_kPkqRe5E+>~+gBwo9orQd|XU z{;Qu-_H*p*aNkptX~oJ^p#v+bbQ-+!~+ zw6iW6#WDztqx0dYHEyhaquVxbT7*R74_YHS~94D8Ocy zn~@3|8VyzCu6SwqZ!Cfp3Os+43iLSP-2ZCu_c9S-$~`?)|A!-M@3S*(bU$kukdPi8 zQ|n^aL{2<9yv-z=*CN>Rk7-e&q$6{bexH5U*dUm;z^9^^q8C)lc>XIWD%Bf$HDk*a z>F~zuP-jGw5d&r*xa@b$E>^D)>u2o@Ba&@40uXf){-F6@rS&*`&0xPsRW*Pw|Gukb z7pN9zo(WQ88gmxvrAc@#EyXBA8wAyjljRv#sh$Mqwk1V!su?k!+9u!#U2W;_s9|Zz zph9V4NnxUbT;f%*EAy_h|049YL1BYekDniDE17x0wia)m=tc}vu1Dh+qL_AG&XFdP zPkwjY3+p>DWrPjaaR@nZT2|9elNt{K8)_xE8WHjRUezOvZ&r*1maT&E5=8uB+Knl` zWqSmX3Nk2+U|855JoC#|t0~yPXDjQCf2$&A+b9C7pdjMhf*H;veX#c`67SF>u9CQ) zjM36=@v>%ryW>eiSrak7gZpuDis{EZxE6;b)(84}920OBsU`zgUEkKBA^8RBkGX0~ zyNmf(yVS;X%VuEqXHypfc4Htu@qTx;4Q?kD4#cjeRM!L(+do@K-^T)^W$M*FA8m6n ziWx*CS*Sprr?e{Si{x*p2F zofoCw_%;uClu7Jp5_L7G;Z@vD>epE|2+Vjd%N5A9jG7e`{6$gymkUx)R-`Po`79`l zKMTqgFewBmvI2w43WZvlY;P2Tq#Y?{XiORacnQ>#>IoC6dpyn}-xKAjXPg0|b`msd zJ~+w)frB9`SOkOzGU0Jz@x>LPp|sj{`K>9=&(9sy zl(e6RD0oQ^UNJFI#yoGpp@=QFHs>PxaqzJ>Ps5s(rf=*6>#mL}U^q&Tfs#tVV#5%w z4W>@cCKgcVQN~SF<%U3lw+>QI$)0|-)_Ed2za?C6Z#NXdo570M1b0aA98xj;{;XXg6BQTJFB>{$eDJTSRXcVV zB?HE+$~m(*zkQ7ZQaJ92sJ{z{DokROc{yIQt^#ZK>SB|G zko9liWdYEKAW?Msi=EqP04)ooRvr1UF1}6aD|=@BU@uPl)gBR#5@6D=GDB(McROyc z#wAcGw5*ftd@dL4$5N^4Y;QbfolP^ z1a3T?Pxqs?wT|F{h5rhM5!NDa^2LpKn_p+k;Kte)da;{@B9gLR@1WYh9W}RfTIy3u z7`X{KtJkPrE)ValbaH9p@(G%V{~jDZ6Vjf)Mg9I$Z&i9cbs@{qOhK>CC9(pKA{n4z z>VA%)rzAj~1GvE5|7f+Ub>)GTqS8~_JY}{ZE4RapOlF-Z zcvJS{=0hjTUzFJCR#>H$O@7P%pZzFa>@QXXBSLAcria_0Cr|xIJS$=15J47N>xSwg zo}!>HO-bY0l`W2&H+ZqQ9cD7tU&A5?csoc|k#?$Vhk!(>${uw?#WXlj_FoQ6?nKat zb1%)sp|>Rf4PDLMDY6(eo)k%XBY!cM46*1_$EKVakY}h@XLp(xpdY&yr@bDnxZ15B zVXHH2G;l^!)tPxs^EnRF!Jfl#KE2(X{eaV?_~V^u?k)~dKXyJqFHGU{HpHY$#w5d_G_{u;{yz68Bn|3pTql(Ngc_o)z)Hmx-yE70!;} z_jC$&y{&7=w={^;e-xw|g6$V`~Mo1weBing7L~`g*mr4l{VgL zs&wN~6VjnLI8{|qI&$QGmQZH`26A%@`jG>(EZSvVZnKSd)E1ltn?I`jj@=WcG~b1P zhg>x)Xm096C~R?v0OOY{q!7TQdTrI2dck~79NC+3; zmrnu^uLUvx5R75Ji=gk6%v}h^Nj@V%LMugGscyl=pG^RD7Iyw|Xw5YbzhT7e!fb-= zU;NUJDR#Hi(caM`aw0lf&DE-ND z4$?meqBSOR*t8IGi=S@2g1j5$_2~yew!?f-M1NYy*(~+>>Lib>UaG|UYJG`>8}flw zKv7#dFWV^uP^mZ%XJOHv?qP&gvlUb?zO6}oS%y@{T(QVutP%37NTm{8TnHy_jHa`s z(eyj-$uEOsjE>18ZKXYA+96=gZGJu-s!*E7H?8^QSqvGoq_~iqhL+dQ?4ewX_AL=| zg)T6K1{Dg3*FHsNaE1OflaqSNusZl`9I$_utrh(2bySDIChxmFl~8d2+2fbu{WACU zq2;X(nXv3@=V7dj?rp_^_Mw5FHaE0xVAEzIKd*$5(27fE*8AmURZSuE2=9?f5?#gj2}Hz)Qwb-~#Z zWM+x+L?uJr%&CRPAQdWWAbMmacrc^UTEZdaJIL=LNPu&)yE&voWPIV_v!KKGB6X`ZC)Oglj3r(lxo07-?uS!^j;&?;jXbu64F4E zu9%n(J}R>GQN0jzle-c(U6so-j;0x50?3CHwPWcGgZ*z)(}&bOVfc%AJii#1P4%ABllDuNZ6ZDBQ_}O5vMZYH{_sa`KRj!*csr zG+=(8m^wcQxpb7nLv39|l3m%Do^iGXqNwrrb<})7HSlv%=9RP#bC(>YH{-M1;%t1S zXY|tW>t@Zf=-jQ;no1_QX#yE@>ik$ZriF{>BLM;-K`mIQl8upIWZHkz5{V$y!rSWZ zXE0aiwLn5kvTgT81v{GYQXpo&##j=H*>KMC%oj;{3N;YTTmH+g<|!buRBDchc1Nu( zq$R&J5bOPsT{Fe-`CzaSc`t$6C+(H~yV1okN@iPwStV(FUlzy1B8)Z>33QAi*nSTK=bgsq|~XHCO(8T zKB9lU{~$BFp0^5EAZt!SRH~^3cs1roLZ22^72~06HjH4Q z@Be}W`bz7zso+vUcd3u!p{P?C4P z1JRe;&=v*=+plxx4}5#g=jeuyygT&M)8|fpBc$_QJ(gIb@eZ?0ErW=5U|S2~WWCcq zIH?7%A}sfsS0{ny${Pc>nh=j}WiS%cS*lN_aImZpZ&abROPRJ&OjIZ31dTuKod=H$ z*Q*ZcEVVHJ|}=N1VTGt^nwGCSB+)z!hg6yWK%Gb#xhia0N0V!q2yXc+?3(cSnO4OPaO zMQ6YKMbRip`gnF+pyKEzFIRrp6l{w_C~iW}xmro)R7-|Q4)|sA+3{7Vj2XSyEH#{2 zpnADqrb3e`RxN3nzbO`|ld7r4@OC`c5VclbuSel9CO+FD8Q`-4u-3$}zP_0D`+Dl$OB9Laq9mMzRl4 zecInKZo|)1<4DRtshtHe3hkKg>r^c`QuEFh6Lg~y2??<>G+yU!>k=1s6KFK~*Oql>?9Q6=};VNu(3H#tpG!Jc@79y6*`kfiRyS(-pr6Lujn=;U|K zre-82K1p!4*sFlXT{QY%X9hW1rZx9BfQMOar_L>YpYC`*`#MJtZ+rLMFK+WFdS zqbh)$^l}3tQrBOOsl`1o?z4QCvN`Be7!?KLa`x4UxKv>Yt9ivL6sBnS-Iuf%6IId9 zM!y)?t&O7->~pTMTH&UH)4cR(@vYlkL*^vu4ZWKey)}g*!44m@7*87-X8a6o>R@Lr z*?d+hUGxtRLO~aiDAegI&@MB6;JFmQO;e|Eu?OlCqY(Z6Blxw<o&fB}pftu3PMWL18YFbNK+JS&PGNsQzEPb*d&08Bf>xG*3nxy3hoxQ~EZQeu|a-WrOJDN7!u?1!5>P2RiUt%Q?Lv52iL za16&^6fP;C-t&%F3xSC&w&Tl`w@S#Sgo25FmS#h0d16#DCqM;mIw_^u0$@>rmLdu+ zeC1G`;J{XWv@w*uE1SdnCK*ndvi((E6SOy$ILoJ1Dpi!a)iE-;7W{7r35`I1O^qVf zQ-%633Sn2l0GFF7QQ2?~$xS&Gai!9ftb=%5bbShqqbrUuH=+wt-$71JPJ0vo_#ykz6+!i$l)(5#Y0Ft_`$e6v<$i5n+65;&_w=G^WQW zkk1}p#jGN&)+-TEWdNrtT(X30j>s})jPxhw7}E(%w~XLF?FjoQ2o*FV0I&5+UzqH& z`ggbBstb}u?XJK%K_80T?1&0gbtOu=#yDD;?`Cxrf(lT27zbx+LLjm=v2G<`CcK6* zSHnV%0ZJ+=p`R~)56s}}(P?yit(kFP>XWF42PSjq_Qm%*Q-ABzs)I&SvYn$+RQfF` ztqF(%aKl+JzjC(RsW&iC3=2ft(=@s##F4?IKp$5i@XU@D{ESr0_=OTmi`!xxCL1+! zHe(-!)NRQjDZAS-P3D=2emKarWBY;F_=7m}yb2;l1)@y^rfHe`gIA$065>c=>@=|$ z!{qt0D~;Kfq%oIB5xop?7^G?C#n9=71hr%l;@)XR&=`*Vh{UtRbW6{RBE*iYdSwwN zc3(_uqb9tg3@!6%`OvJ~!$wZ9ugPrf$t8t)iH4q=3LpU4B;t&*1cPUbOAZhvG3S5_~;(AB5lu(PZeXH^3 zD4m&d0q}{5SN6_8;H@sj;MjwG<5bqsi{)x1y*j~57H(BVR<#*9WG|OCDcm`XlQa&T zWTA%s^KDX(MH`Mn?qa6){L2#+}f)V$UYM8TkwxYL5n*2)KonKC)eM9n8- zVpHM-DGK(+Ebzs0?x>o}KW|Tc9T!aV-8+`WYO~FsW8S?{OOOTgd+KuqCaA6|d&vT> zMx$Z9BfTy|iMr473zCpNv5l^a|2}Gh!EElfKM~umMyJF$YDA^N)8PQf6&ai?tSv@} z8nwj`IlOJUK)U>ySXCv(4UHO?7m&$A@>NXi_a1yN?H%<|ccv8A)>F7kASE@3qhj(< zIYCn~#*s9Fz8@OWzr7F00>;EwGLQcJRBPK@z4j!oCubk^`wmbmIvy!xF`PbH4hq!~ ziId*yb7_8mocMwBm8)J@bcNIWvK0ZAfRb=s$iN<06;{#|9$`we+P5i4lrTJ7>^2t( z_vknYv%=3HC4*V$sTKUJgelW*^r7tEs^DW!pO(4UvLq>br`ROT&fO|Uw-YRJ>lrn& zG}lRW4?4k+g7jndO6Xe_76Xoc-GzB9%@M4x46h|oJ~f`;jBaWTu=?lOml>|a{8HER~W=T$v-nv{rVzxR5JA%nyQcG0zzvT1x!AKZC$QnSSMgWEw z>wv{17|0yjU0Z*voUD_D$VF6b%}p!L6=vx2xc+cck)vinkMK3j-*4nu*M%2=Wiz$R zUcXi9Xbcc;*@nH|G1ITH(3lH8SkjL?)Q>B}1gG-6)}9*$WJhUAVJ6F3mDqgY70ZqZ z$f`Vtx&r#wH!Ehz%?W~Vos^|i1AkLKAlo4)@6OC<61Ca&%t#+FgZvKV<8$ywWr8Fc z;M4cy8iI+>s?SkzAZ6S+#wxqC0=;-F8w2snKd~{r^#F|Am~Dvyx1m_Og!=<8fl&hR zdv=#iTuyPpd{>H;D!UG$ie8LT^T;SwjyKF zL-v>+8hwz=QUbYNqHyQ5diNvc`zmJ2kL+f{X=DktBm-TYKAy7a1C8V93PJ~nldme{ zUFvYdoMnSxE7dVBO^Yyhib0 zWz-w<#)t!!5#VzER0hu?FkT5{YB9WD?JDQ8J>(YD&uv8+T1_KcTI7?6(}Dfx-+16w zWX{f)kH3Nrr!Y#%R->+cSI4tyyy%&=@W3L0sTc&_Xu`O|I<`ac;r zIhk_W9}AX(1T!1{MIl-!3M#A2@CVeEZfa`WFEAJ&#t#YU9J0#I9n}8T*l_2qq^@Sz z{`hvJErGhbU4d|JU7}QaY&uyu@tu_F7xtp>cackr100o7EMeysB@J~uOr4oDMMI^xVB=x%hBdwuRvemIpYNCFXwhR>m~-r z+jK!+D@HADO(eNe3$IU*>+iuz zDIsifzRhQ%Wu^rc1Ld$%M~VsG^meb6?gp=oD?6&o_2th!^(mmn%C;f5G)99jaX zp3N_Td$B_L(?IQ(!;I~;4!9b=R5^OH^JJyB#gAog+aqYX(=Bzs&t^gZ!~!`7Y^MeX zK}GmEhpL~uSn)^H$M2LnLVCW*>^B&3>?Mgiq>Y*dOx1Gj7S_VKky#V!uDHBcu|V*3 zcSy3QR$7@?0TC;eIQ(wlJD6kawX6yx2|)NM?uy=Z*3pcjKcbGIB14Dx+KR=g2dgNQ z$$Y{j6lHieN?jD20Bt}y1%FEV?I>!*gU1r(;QSndJdi$hF%GD)9QC?atT`{*`clwR zv!qkX`<)Gofpa-W%LqG6sHw9_ZU){7&aI81XHXxm)x%<5-jSeok(>eHzras02@)9H z-j{IO^KsGjw;1_Rc3bZ8=ISbGt5LCZHe#o%AewbS6zBO(&5044TIvouKhb}mHf#<# zR%J}u`%?!xTa+n-B=+j=+1LS$S12-D=Dwh5xtm5ZZCLMR6}HMVwX!0a!uOjl@Xi=A zA&eZ$voEob-7nE>tJQDr-<+7JE9L4bef_2eg|M!~ajl%AIg!?CK5|%ERPT z27t-eYPt{|QIaWl?HIooUfS-m-zQ|@f)C^*XZ0&(3g!%GnjV#lrO3HTpT%D5If9l< zTXw80^;p<3ERq#s{;zJV{Ny6*RHD@9FiZU%z^d!=uuhexuXFbUnG-zD~u{d>S zA?#+PV|l@I4I#3;$Eqp>$w2faOn{ZB&D(Lp(KCnE{l=KVhWrD*PSx)!GXNc6dq4Pq zh7unCW{*pUm9_!&C~p`V50XtV+`=*FB_8)PDJSH9r_8CQQ;{2@5_u+bX}bzBhLNtVQvc0u7K3eu2;I8su918P<&T$$n*ctznJf;y}C zH)!C9vgm=(c1==&j>vvjuP`lXZNZ`t;ukH&o{IXHc1pHxquL&#$ub?}?NlAt*WFR) zN(VzzLVOmN(xPRV(Hvn)ufGrAkgeAs9PRcG8`VEzej!Idg_MqUQ!%xrYi!R#P16gg zGe#Y!mspNXlD#L@BH7wL23Py(c2`>Mbn;k9vAw_>T;XCh-&THW|KZ1-)gn!V%!`># zDHo?6-!J8Jk)$mfB-l~XQZy-ARjz7>Ra#n7hpL)EHb#M92qLpDEg(VkW=Jz#HlNJpC>@l)nFuJweE|9 zPe1y_^vz4Ab`lx`lej!4Tmh%Sy(W;R&xlkY6G~apmzKAm;^LgN$j;hgY>7=}-ptQ2 z!#~`djcF;O3IL6#jJjVOL`KdhW>&dowqxkTsJgiA&-sF$_#}j*j9rFK)OD#{$aX~m zv*c|1IHMW*a;H5A%6C=SM3P-~cIC27>U@J!VGHU72o`i}Cri&CT3PZiXSFl22#fZSk5eOUrD5`Zr!?8BJmOdnZV+FPNVA=Aur7*0nKq zCM^p%6f@+jzk&EM=dHa=UomXQnWh?I8OG5tYLZs;-6V zUeDe67!Ro}BK9`dAz4^#vQ+M)AM)2bq_jAC5kU4&PVdj3bLJ8rRavROD63o3$Qw7c zex`d7>623d7yc6_Q#J~cZ~PfOe#I1n)`L+XC`gD@H>j6|rR5ShranO1!Z%T#(ij$K zBN~g9cCXaNBDNBMnMgeL1|VbRl{=?lY(+Zn{`W2O0E04Vo%I^p;W3NIBeTzfWinUl z4P)!85wVHU135ya06DFFb~UXUOTomgQK03>ou@?Rj-OunB6#R|W2H<-0tju&UZJ{h zvQ@Y17wb-OKwK@b9BB$+n!NlfXT{Qq%VH%^;A_O28x3U%xlmgz_AalKHm79znQs}H zx_Q%V7jf~+9MTfUS!1Ua{dP?4gZ{gdaE2cPUp!QMelx3&A%S5=;@vvC3R$AOBwriL z)XG+!Z&+w4lfLLPS1WP!6w521Y^ai@F4vD*-B!WU$R`2GavJnYtI%YvtY-VZ*X)An zak}^<4q2hS9_UOk{G9ar->d^{pw-_sMa{|sC5cw1Bu3;Mb7|=fGE~N-ByBr{TbOM4 zAuScx7~lSi#qh)R2T6npf!BOgIW9V9D!7iYwQEw|?}HKF_+nhgW+8QJL5}WFtepvm z!p|bFIXF>@qdW=>#(N# z|NS2a6{Mx5d(`L-LCKLLHyVkN8%j3@9V13J(y+l`Gzcm^LVC1ZG!mj9C?a}&d0n6P z@Aw_h<9PnR$MdmAocHs*-SwMVS)l^^?M|!86So6Q?49yq3gj!R@-35Y{Ac?#o?m(w z_oxB-S8iFM{cm9tv*Iq$tfBBUdCt#aeeOXm+og`qPQg+vw>L&bHT7R2l=hswaN%J; zgEryn@BhuzuEbw+wx8E?L;)O+T187xJtep!LX?YN7d0s71S9Q-nBhWIo{CNn)G! z^6si^J;zwia6A06s69VqT7-b&B)SBli}xa*++LVwQ2Bq{d~CctNg@wmPbkz{to83f zyGcidnDuh7kHJz{l@V9#)Xe=eF%^D9(TGhqWS(6r;B%pNmiRZl-+c0!Zc&!SQd;S> z0t~1f2sG$uClM@=e}YI^&2Ma-a;5ue!xTFu6`RqHTi0D41c5p)ogO+MwxQ=O_J&SK zs*KL%R4y%U;h9CcFd*Bz(TV#)uG~*i$n^vlg7qSmWvVnCIiRo1Y9UwB4PxydA(ON_Q8RD6?&w8d;9>a(pH@7gr{f=5pc7@H+NB-!RL}n-C%{9^L}} z@H6FB#cD7U{d;`Ll8i-f^jfZ9Ptad8c4zoF9wk-$)paM}n+ea4;&*ppC;HUmEhpoy z2+s$>V^`XvJeOi#V=v?KIy%(aRZPD`)okcbDmc9L**Q@F<)ql#jF*py`6jiMLLJHU zJ&a$P1esdyILc}2u?b8N);&>ae<}5Dd^Awikw|BWrd{$A=2flucmlU*sXr)~J}5xFgM$wF6ZHb*QtlQcE@- zV|44rjs#x+ROP|IGLFQSFS7)>7qk*ECJar0LGA4d+)4Q5;q4p;^AnUtzoF9(YD(x* zb#B7`ryzYJbB?QX#zgrAEIm|%1`s^dp#GH|kHwD4*Ha!3q|^Nh<`dlpmF2pKogKV5 zF%Bqp-q7Yc9behh+mGL6AaLYB&S^AtlN<9`5G1(^AH2yv?g}ZK9!QRtv9nlj3i8vS z5h@7^KAhS~kPw!_ajb%xgrHX9LfVwsN47MMMWg&*OvL;maP^X0f}fkrKWz6hCq|gI zQe)fGUZ+K=-Zx{6mQW;)b!X>fkR8>IU-%83fZ7{eZ8raidR>>g*}cyav=>8v&E z49Oa;$n0IS@#6tQ4^Z8B602ic>}if>py0;Rld(}(dNsdecQF+Bm5A_qnEm_XsvW=R zZjBT>= zDxlsZ5Da{F)>X4}mM4ANO=pZ-?JiC)-gQe&g%#aYNYI{=zIskt^NDw|xIvS5cs2gM zWdW0I38dKhVUy(+OI@RXpg+2)`G2;Er_%xM%RVt`t=8$!&rA}&y|QYKR*Vn>ZjZ$k zIl)Q9FK6Z!)ue@6CVEdxL!>1I1dfw`{wjEb+1`1feSEXJ#CJabWJ_%LQPaX(o&qH6 zFF8^t9!&eNUyxU&%OnqR>Znb(F)Xxmwo;lr7U(9`>{{PC8Ol@uptB>H1HAK=ZV-(Y zxGnUGo*PDVeIVY;v3*E+vEQ03F-7-zNUNfOHhgEYo@u}P4XnN}1o4reFzYdIH;l5i zBgvw(-PqXBgTTR#DVHfD(_eI213t0YEoIzl(ocrBTzfNRkv+_ctV={KyYN^2mJ_kD z*gozG`npFDs?TF168_RpvBTh6itFR6fJz>fpe!ou4*6=3PK` z%4W`$A5<1AZ$m1_nG~YFfA_V&L{{pUjReece^w52kvWT&>P}Vd4p4fL>@ecBok!!E zfDI=3QICp7JTh^rjumPW)Xctb{X#o)shcBZT6@}b;N}}5u>_+Hb)l%s8_X<(g#5!k5Epp7*>>qjWz#lgMTW@}y-yZqC z-+QT_vELn=Bp>S{NsBIawTGm0vc#~-Q(d}(cpttN6=h``SvBV8$oPHSacPnM+Ka03 zSMc4e?Y8a>wUWbM%j$-b_V`<0tfPj<>k}keWwJh9`%8n9Im#taepm9PK&qwdOZx@4)Vh1Hjn5n{Cnrn!Py)AW^RBG>2 zc%Z|_#Nj*E-Ta1ddPg-O*>RT)838KzNNWWJUT*c)C$9*SUP4r}3 zXlWPp5Gc$4jrEZ}^)*UOP50Zbj%ID&3pF!ks~M=L?pXQ_M~T_?@#v@}VD(4Q%6}Ti z!Pv;QjatN>2wPgx$K*!`4_zgTJ(iQ`}&s#X2a#uLOexe!8mnL37C*%D!YV<>nx=O0J{YO^Ev z@6d`w1TN~n!!bPYPBR^7R{!XM&?^}s4n^h8vt(8!pBBB;01^h2-jd*xd#siQ`xc@j zd8$>bm-%#s+k=$?^Gg@aLmRib*~RuW8x}Lo@vAV1$hME#TPmNmw^i$@?VWU{-OTtx z!&Q6qHs%Nz)10|p~h_!u-W88iO_=yo{iRm*+p>>mjyv}!~By} z-2|&+CWTfNWBSc54n>teH5zJOctl;s6~iqs|Dl_7d}gMhAS!8XhMvMecc4Y4M;=p{ zfwexk6TtNCl!B1pwvi$L(^O^(58AHa;^phv0!`J|q#<95GGE)X=!aE|$Ho7lH5wVtS`hE0P6{4MLg%NiZ5Pxm0*Yt8D| zcv(@8N~~1IetW^RuyIBHu>zKmq{f~R3;c4kaV6Qi_n0sx0O2LLC%kmNp=kx{oR|ip}sKT6&19ri}Q9ycQ!yxfJA+IVGp@x=0(d z{ZVV!DR!*EbJrz;UOs>5@`=u47uy{s8<+i36~ZmbpzypzN6UvYW0y5O#hqYk5Kw0A zfqDHE6sc5CP_?KinEjQyQT2|o9CW>X&;Zziy?RorjZ*!;8J)P;`yev7{-iJ!#TSsP zW;9e{D~HhMMCBv>NL|qCrF5{7BFA0l!hR*Sx_!~^7K530D-nmmeX$%7j7z_qS|jyZ zP3feRB|{V}Wje|rVCH|YPZ0YiirgXcA#)cTQ%LpA1iOWr1&w0EDq6WQ&V*BDoA-%#va#nlfWXR_mp>^&aUe zW>f($e{2i}Ow`9eBxGyS|B>bzsno+huV?Emvt8>K_2mYKF)>E7v2lq*xC;I9@1QY33a;e zmZ83KJR5FziH<9A;fqR;QQDoHuErwF9x*bXL03B!0f-Z6q2uchC=>heGfnh7f-!~B zJBh>ID}wgKLd=sIEcI-Mv{$22X`Y|nwQm@8_*S&Wke$t5?L(4BIzId3QjBqqT~*}T z3X7AJcvd`u!bV6;8lU;t+;~VY8vldNKgs5zv8nFd$8UH4B?ACk!h-tEEXtPFGo|hj zZ@q{r5FTT@dE=_O2ik93rGK>wygrWCN9r<`(KmUAr-jfp`Y#WpuL&EmwXa9?_%;2M zOWyrUcIyH6{-5FCeQC`6wO}9ZCdJrhWe}HDj>e$ZVdSeEFXt@xD}-%deOK#Aq1>ZR zkr4&vjP8=VfP{PKaQs)Nw-7Xmj#r#*J49n+G5|P|=T3&HT@ou@%dnkRzdI%Q)=lzXN^>`)WoHc< z>!R&D9<41e?`aX)S2_%=EL#>MYUDbaSD8 zg?#9jM11}+$1Nwnjblfp>toHrAZTO?m(w=|3*F5FetovrTo{`RxlpPCOX{qC>s zzeHKf82qH={xd%9abeiY#%I<3(TM7crZ*Tvc7l9~Aaz=b^{$zS@lx8+sd9<^x8J3JQ*)q_vgoPQyKg9~TnQ@$t@Wi`+qS%0 zqQ>{9RNqXFsqdt{@G~D+92>ba@(y_yA)J7=y(`wB-OhbYx2b;bDD*3eA>>HU2J*}% z&7_Ju{hbE%i>;Y-6<}y95rv(}a_i*iXjt#r4sI)gs0cfch&-7DN#~H|Pl4Ih^;sOp zTr4%2CM_PWd;Ao7xUrEkb^8p10^ucJ{QnnD`M%>4#xnq&c;TD{-3ltmed<=cVxg?lT?z@D*}v0HfkG9o2n zQ9e#1ha__}AiYxmLithGWSIk%0D1z=!ODSm?PW+CqCXrv30P`23rW>Ry{CJhl(9`_ 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®4h)AkBLo7-UoB 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

  • `l&CLcellKWMZ0R2 z$`JPk?Sx}{gi*gpqR@A55=ojv>e%WeBmd0I3Lec5_$Y}SkK7X;1Z_cg^W9x zpSGG1FE{ri^7_v2D(#xQW<`pmSP>D{;c&?mtRAgjaJoLTe~5$HGJ3bID0R51B;|~W z&lu-PFDjq)O0_@Jh_v@Vd;dZn9L3hvnfa<}jB`FMZ23X`U09=wr&RY6O__tz+tOJ) zU2J9di05Mh*4PuXJe5!B6%wc$vqGZm1-IoJ;tKRlwj^<0bkHwnz}_-J?^zr$pW(#Rj=XqS<MRDIK2D1x2=>Cb0P@ z02Eod?KI+_e5S;ZdC8+V>SEARK|m4(OIV?SEtYA{rKxf>j93R;CdZ!X56XQ~^Y>-C zlw#pp>`k1Mx1=2EDsd_oU2s}{kaqFFW0T+YxtMusZiuHqpe9ncZofBh#C@ zn}nyX;(0Q9^6%gIy^VOioOw*;uo?m&dcO#mCi6yI?B;`eIlbhC9mJUDA?xI<`|r&sa}eO77zSGynSv(^LqZm7f7F zaP)6gg2?MUvPs*ijHMRKo-yS3_%z3YPU6P|_tNHS7H?~L@N>$H()cxMPNF2d=(DFn zX7f~)T)WlAV$D4Ym#M>UzXS1wQu3Y;BFp33LM@})&Xh*vfx;tb^2hp>U%LONBt6L7 z{e!VpJkG#1$TiTIC-od=!#x^a5l@-1Se9dDHX;c!&foQBNap z5Iz$@iu%{rbo}!s0Wa)&j^4_BqRbPm#a)a=o`FAF_}WiEuN{|OmEu%{*t?Nz_`jYQ zzf~PYRy}R|N)05Nw67Yq zw5h(`^)UZxLl~XD^v-i}nK?UkD{Hg2V%;S09}G6>S^T~kWV+m|Lul6#-&KYThLbV}FY~jTeOwYZ*ACj0Pp5Rjr7y*A(%nauz z8vEu3$9XP{rg!o94>AHeg6I~3YGq@E7`%9E4lvB(+tja%iL*T+*J4}R?bZSf{|S0~ z;Na!EuwN}Y2UGo?*C22+17x5sm?}M^^~GQ65_6#~t-&CXLliy~{j2s}Z43|85wVG(ItAMB_Iq#WWpMXZR}) zo#p2j`&(-`I_u(ipN$)g`|7^Yq^?cTNM`_~=qdb~lK_Cd7_=Fgb zE-bcg`-3Sb_bEXc?WEoPK#nl6J%Y!^EY})Af45(o!CasqXVe>NGi|Fp?9E z6)w{D5q^0`n*cRH!Jyc_)T$f;Oa?c~3loZU(ThTiV}fQTe5gw#e^e3# znuVJDAccR@3QGMFw;=Y4CGnnncbE34IXL?wk6Mf(|8Lad?2=5&i>;}D3wM7#C{WK7 zJ1^e+RS{dGi?Q(jIx=t?w1%zI>8`v0ss@SidXn)g<{H7d9BN}lMid_B4^BpR=G)S| z!rz#!*v)>oJ^yr9VG-0pYWD;*XTYLIfz4cZ!ra16=?!ac7+$Wz3~ zWp6;9{5_(|R&UeTfSI(rOlZgNG=*82GCZ|E4nJ5bOFNHuCPoLjKN`=~Xo;? z`)P6J;KogG1pO?EQ=em-E;ts~cHW~ASLkm_9dmiEidA*1##u|l*IP3BMkhNx(H0ke z&&iU5OtE|MOp0wLbMTa2W|9gam&oViL28_F3&!JiC-l(v*v_2!I8Qt=8w=KQ;B095 z7~|NxLB|CZDhoF(@iElPZ9HvM7+1r9-YIub8#}Ck@}*rf3Wh#Ygp@=)vizub4;B5+ zm#6F3%(G`CLTUcJQT&6EglH1sg-47eUex}D%=T0#I8PKcdu1D5y&Q;8NP6d^Qb8Z zo}h%Vf7LZp`VN;tPqB+_ z*p*aEh46Fz-m_`pu$HB3i1aXZ4LQGA%8qAR>ds`VEmYYUGr>o<4ijhm`sP)!{Vk`T z&Pm4wTQq$EvV{Na(;roxHnQan&53@e*S60`Y)j3?Fwd%mqL1X@@nJt7&9XV%cS9bTGqNAT(s z0_6IKr)_UohRz8-mDM{fk3i0zLYRn72>Q&TGYzz3H&;9*DT5$YV{s*dbNqBaMOj@m zp1G`-4(Mr^Pq*)}f6#7tDH7!vgUJ)WL@e+~Gj;)R)z!l1*X#vCWw)ZB#`>U@AK=kW zt`1+5KXjYn{v2t!aH(QRnJ28;Csu)*>hvt7Z3DF%OGapiSh5%+X5SwvflVF@=Qc|4 zWDRU1niRA9*7UI?!F4k;*LPrbC!mp$P4W2dS2RWaNhvGN`wR|=U+rIC`=qH>rm(tr zkXq;|QXZ5Oe;VK&Z(1$nZf4^yie^0N~)^;`yrqenl7Twtc&+}Ezv9!uQ%%;wj6Bnz5 z*@E1HG4D2o=oxS?-bzS2jt=-pwFpWy?TFp;1KF7~>t4=7l0&zkz5X_g+VHqR1y6zm zr>?&r$o`8>mkF7S*|>LnWP0tO7n->kwVksoe`;;t^$a>+RlLAj_s>vIQitr)VN7Yp zXWh{0hJrJS{>DcMYiIhF5WCfG3$`xJP~~_HnGJ)r{=xY5Vz}KX;l;;LDKP&4%-zL8 z6l*FZ;5YdYKZWm05&Ore&-u=mj>w5?Sljr(kFwa`z zi{s+j!#5f7k%rPA`-43A!FWPDrdm<5ID;1x2^Jq+I!(p?Hp0t9>3q)UQ>$mt-BBL;b_!K#hnIz4QjrxJ;_u)gf?@4t=dD4>K0J@nsS9xxyFdK?chX7Ue z?zwh{D$91oI*+)I|6t5y)xmP2@WBY50%p+u^n0a!X91S>lEdfy#n}RGcxj6{+tHXd zdAeWbz=RX)9dwoAkp)h1>wrE5AF8PKIK|Y>X_cjJ^Ie}ucyIxC`ezfv6~JgZsogBQ z2WNUDtqE*`_Q~iWS5>0vNNw&eT^dva0CzK3oCF!H)u|$E151!^Ro^HcRDC5SPqG#q zq;jW2SR8lhtN`4jN3eE!(BEq%N`4|-J37xujZ);Ik`^C$K|))IXM+kKzL3{GFR zJ3AY4xx}$*TN?`oFZ}&--Tg2m@*+aKyLw5?K$m7K{4p3G=J=>)km14!%<7FBqlGgj zHfjdY7B2PwFtu&>;1#ZFE~~WV0_fSqFnwP9iSX(y=eo)ROF5KR=#4bB-@bnjd>ntW zwz4oL7b{#+3knGxGx&gsr_)-m%AXKfPkgj2K~0Q4ikU1dxN34UcKkX5-NN z328EKXLrQY#^vvy_YUnTk$oMM&&<^*qRH!CU9=6Z!g46>I#5M>Y9KrX(}ozCW6fCb z8VG6q1wHRBcy%epJT<&z$vWAFhzzKx^eo6I4f(*(J8y+8udD+x?O(Uo66B|0EJNz#bXFNRF> zYkqZTNo<+8b4?(-A04ZrlXlG6|B|VXmNG2idPKg0xVZQ)8b3=?aBi~Ct*yLYKISc@ z=1I`V0VZ>2lZyM$@-c?I`trNaXbmze`uV}H);Q}||DGL=Fa2w&?Fno92j+mtYQ_V_ zVV{IZd>5i~nki3_a`Otq^+rJRaTt2IzQ1fFS^wL`7!D_5#7>c|X&lF|?rJ51MOC!r z-FDZ>j;%5^zLHb}_E5K8xPV~w9!r?9U!r=NA2;|7>^-|WT(?A2-=^x`g-*V9KRuLd zE`U-_WS@JG-?5P$zGHaO{7i1yM6P)~3eRlOpm~B-6s}O@Kxq#W^jy_dKspyJ$&4Je zE$GFMexn%NGU!d0pKV?){J`r$%+3y;efn#D^1~Aaw48QNJ77@&&ou~!#XRlLhRl$ zCtD`OzVb7{&aiV2N$eyl!3!H^@mjr9&wns@y@H<^{rVkk1Neqb3KzH3gdl5IPJQ%S z10UYi7avq7b_IHCS^t~-h7WB&@Pa?EHhoV?t0*lV*dQ;TcfM=AhYN&as-? zFMg1?wK=vq+tnhqB_%ObeVqU2ixrCJ`bC{t{eI1Yys5d=uX;uKUL)N*E8m^sJ!#MY zC#+M>N+W zid=q-w*#3H=gFoIlov1I?@8k`Nx-K5A64$&=B(v@)8=(1h+{MCeCap`@#LV|uKnr0 zFQhKLhIC9o{F&4*G!`NqKdz~tY5%a8OEXcTK#jm4S(ao%ChJtLtdG&WP>J+V_|fr8 zmE2151MiZr3HRu_mL!&Wykqej5mFXIUkPt{X3uIi_^nLu1sbAOO>`DfzkHE`RD)vJ z9{faPKW0!hl~woIyN&=w8Ek`*2-6nd#UQk6$Ww}KTp*91{wh;Tw-;%%Z=DnDB(!|e zvppo`Uq`f$>bc8_^U}|HG|km!-eX(nqg{^jGFi1L8p?A<+isArHm2zianZAhS}g0y zwsVv?bB{RgPIYS3$urlzRiOA>fueO#kMV2Kq@&QSoR(DZQ4b9gGb&Rhd?6Q`y2t`0 z)Lwi-b1nCi?`Mq~E;h&eof$<|S2r~Dt#d4wY|nmwDQawtPF%yrTDPa3~p<9-~Eh#TX&0h#DAr(6-n2xi{<)}Q6p@E~X;R-s0+r^->&9bJcYGvealDx_!U0@TK;? zu&c1ubtqLXb!xOiPrdh?8>xKjf4T=<6JP~4R;@R|>($YIZ*1zcm;##FH@llJ{<`X_tN6J&XAJ$Z80tON)}Z& zHWfV;osjLEkGc3@?5{L{C@yBD7*-55N;H)EdBOc(=q_6)-}=n+L~hknIVMf&cEBMf z;f+i9z_<0+_%^s>!&1cnbDw5XkI;SDn={|(_qh-O z6OI;#MKYve)jOL+5Bw!|0ZAXs>Y*@WEFMeL@VRnH_OqAi*K_-nfk>^u6RM%;rrWT_ z@=pUdOt(cY=M`1fE5tP+IgL<0P#l+6dPKVc&q=hk?Pnvs{ok}Hmt?(7;ZE=tVwR+z z#Iu_9h!_dsbe}oHn(%b$n0GfgF-4^eyGzi7+$S(IK`$j0Idjsr~i^Hk)w zgaX$1ckHucJ~@IbY}AQ%>A(Gksd0UH9mZ%9KUMp7udGbA=hg;)OUoPhS&NeunbCYj zX-Uw|E(dPsW2Rc07A?zYDA)3%g2fC3Hfuf^#h+fN7(^vPt`GqWohn+fS!LvgV7jq? za~@adjPa!8#A}ry(4Zdesr6;bUW-DIqvi{;xptOGAWJ(WuMtH_WKKFu%P{F^=6#mL zD=W5I{tWki9q|Or15m401+`8J#x9a`PGKkw&t)^me&C0fqc=r=b)|MBi8n-~Fxw}8 zP#j5JGME(+fk1w8}R)5 z&|>#u;&BY3#(rZ2{0ua;K=y4OQVRNr?XEdp3Z4#^z< z>XKi1pkz{Qqb*5DnSV&O>v?%N=LsDHJ`gY)xKQ)sv1?SVhYGtS$XX~_4bq0JL2oic zOdjXBu{J0x{)q`TbjF0Aj&`qZmhqq2Vu(DGwUmK50zH&%Fph(={mTr;V!RAk* zpkQK$y$mXG1ybL<=_OU-1Ww-U6lqr~OLgr&VS?uc3Rd$$ z>-!S7I1586{a;a{{d+sssq1mIn9tkNMuK?V|1-u3B1LI(BPFwag>!A#=CWO}py0{2 zy><lB|gJ*T$u625aT3 zR1%Zd>>NBPDc{&QToCR7^ksH)5JQgM3xtZ;Mm5vtO#~{CU9NjLy5UU0mSKEJ%Fpdy z{hT~=L)0fjJtWf7Dm~R?K9t}(Ghs8PpL_G{*U?#<2D0HdF+J@D&bTsQXN9_lrtrR2 z%KvC3Tk7NDPBU_S@3WdwgMA<@ZlhncAWG@UX554{Ed??Hb`=z>$i%~rKv>uLJ4x_$ zw;KhAS~{8L;Kn@dsAQ@7Qos4FCA4XTX;0z{_^A4G3DU!ynmUt-%W9FxZYPkaC8bVx zyF<$xETiX79ls|5rpek>^%6xU@wW}xLu!7;*;PZMh&bzialPSp1a`i`qcfzJSZXyg zkES6mdK;Z~qNpSX8h+C6D{94~W+;C7z69v5t^mZN?R!$=$^Ip_i~96mN&O!TnN_bj zn-9At`Rd-9mdi4R&6gXQ+pLSE`jKGMT=B8y*HJk;uSsx)2r&O1f3&VtOq#ht8bCa0V#(jJ-(Z7AG zyk4grK>Bv%m#xvvZViNp8Z-ZkG{U0E1EHA2jcS`!Q)r1h%m`AO&=P!Yk-AuV#~@vo zIBBR7EZ#iqd>|=GZ&Dqmd61Jah(~9}f9ding4zkUQ|c4qc(azmtZER#kAJ=2MQ_E} zPep*}A7`dkV_y)b#k*i^%M4%XifXTa^|3Y?txCYU?HbrTx+&U04XawmV^ zhTyf{oNdE1Sl!qgKoiB)aOCLU%tzc8_e-)@8~SVCELN3Lx;m?3mXCbf6TKFwR%mYg zYdycj4gZmb|L3RILQhlsDXGWFpO1+Q8Aogx0TU@?##Zd>Q@2MJ>j-3wlxJ=CFJLe? z(E?zBYGm^L7825-ykOMgv|RK7xI0UzQDx8ix#cpHCby2-&APQ!Q~IizOp$i0;j2sL zBY{AOb60*nlwz-^WX}}4A;W0H{-HcwNcNhF?fR07{_qQ3hY1tf($}MSi^v%ru5fMl zM0z0`tJ6+7$pbV)z!5Xd)$Bg@hQ*~vZ{@u--KJBJ#oVPhVUE(N3K6*o0s=>p2NlQ7 zp zIVoR$j08q~NgkDT=(19stx+&go?@8RFd@qLiGdEx0T$sD%28P zg4wKmvKmgZvz1z%b5`^NK+Pka;7ggt5U}S?vyL99b6Mi(Igr@Fu_`SEzF*L-!7`NR zVI<^9!qzbJVilgRO}(tS?}cbz@bA)=?D%c=|J`y6bPO5)f1f{}X$x|k`&D1CNAIoc z1k{QdtGBj=6m6+zb)CYJp)E2Ayk4%su}Luyde-vh*WvKTpce(LallsnvBptYc#L2tO2yJ+o#%$xK(gzZbW>PQa~= zktnLNQbC@ujI4@Xv-nd|5m6>{!- zZD3nAc&WvBsK_>TB%#>I?kB9jtsLn?32(tr`jG(A&Yj8IReA3zCaYoh-q*{RbhZKa z7wvC@0vtt9m}VUj)5?fkG*U7qiS)|#g=V!)&K@3H-|?79oi^M1_OgWMdbYyp5q2v! zt*R$xt-f=$Tg7sg5B-pWq~$uI<_5cN$?qo2rszn?bGV8%G$ofyStKEkJgvI6_rTyC>M6o}T2g0l z$rb<5_Uh2c&6;&`(@=G~1*GA7?9LyTHhqPLv;8BLxf?R~7Hf(|p7Eu~xr4=Z{x7Tl zLN6Wy1m*bHs_>t{+)p!+=;gu}z2_o$8zDYqgg~Zu=r6ouVCxHKXWO+g1Y9?jzFZrM zIBZ=%W9az72x0l!Tot4=LU@zr9p2ypZ2r7*1MY9(OOIW2qUntuobO7BLi@bIF@Gw= zB|ETQ7GsD$g>YVLgxeUdR>P78tBKrwu@v(C8h)%er!8slJ|JusQ>0q%<6>4i3bu6s z>P}*Z(RIoYg}Ilm5wg|2prmH8pa-6p>z{9rfmNnDkafsGz7fPi1i z{JZ(QC|(NXdmkH^xf-%@bVoe3V-jGQ)M!*p8;(q9M?0CA#nT|h@^?D?473B!%{!&I zloK@$vo^X96;AE>>^3o!wP`XTwlqy$oxOC68Og=YMg&P8SR29Fi1R3hQ28-Ynp9e* z6`Ub~lZ1taX8G#!8kWjRd4r-2#2wSN%=avOk%^|F55!R}LDISRPYmq!mfh{D;Ruz9 zPiNUv!Ujt5vDX@pL7;PR`1l=N^?jE{UD%gn|nM!s>Ma z$$I~-OkQ^kzysi6OjVbhTGoPSdR%QZ80;cwXD38Uggh$TD3QyLTrfGNGGqR zL>jRpl>}`0a+uezR&T~g1J_lV(A<{;Wpcpt?*gzMQ1BNyH3E|3_E$6e$W79uUji_y zgm;x@AIbto39rAxbFL+pG9*3H|3YY+7dH9&+1iqCFR|I9b*}&1k+ly0jyug7KbB-6 zU46*ch61!ippU8h=%|B{wMGl6e7a$)C%n^Ah_h3Y zlxWvpJ)7USB27BBq(i-IHr<$!^UPqo-lrv2S2SO-(lH&Z%8BIl(lKn`JLp3JcV7?M zueLeMl_jGVtnc~J>nEyVgdC+oF)S{w@Bjm{ssn?u^^-~Va%Mv)%92Qd-H{mw%3XZE*U%Kz8H4w5|RPQ+b7;B^#ECh~{IZvVg zRUNWaHs{Qc*VY||bN%u`Cu5%!ufJI&eED-Svet1Yuh9T`J*fJ!n+u%}_ci+)zU2yg z*O*!63F&fuFjwce-vZHiEhUh0f;k&CWOxR1(hol)>!P%$JZsPJNXEQ&0k3UzQNSun zDX)HpOun$_A<>EI4bgN#q2gg~wvAeHW$_G=b4TXgS0xDU!hB7%yrt{{t47?7G zW9EY@zmIH?2K8`kOO_2(v!5@|tQZiu$1g43zBTx7tmS{;Fo1d)K)5C^WaL;x)V8*^ z-V+=aAZXapkDR)cz1mQ6MaqkMj4*%&)Ve^5y0kFvuI#F0dJM_7NImiqe2CC_hv#59 z3%hAC-1l=e)LnDb<9#sST;}SDANbtN!{4rBq7KZAc0qdvD1+EPvm#vQie07mxWJ&Q%Z!-j0K-0qe~OxkKq*HD{7 z1Q7Y>I)`XX-V0xx+l@bxMJ9Mea{ppZm@MRM(f7^x*=uNmX3b{bdWPTtYWrBbLRiu; z5+)QjR_BEBXq>a7K(JI}h-7t(kj^ofTWNeGtU=}bvZfn2jCow~$n=yB)%_#9BOrWi zlrR0={mKJVFUo2lH9`K5A;AlG^*YUTtvsKJ^vp<=9*5O3=7_Dbzs5vXti|j1e9HnG zUuRpWbzjAX^Y>vc){w@!LL0uiS~`z*&oYIdfu36dT=XnYzI&5RHTA{)RUED)KlPV$ z?EP=Fnf?3z<$mtYaz-evZfRP|$a{!bIgG^5z*E%5V;v)fU8Oot1QJxI3!tZ&p98-P!p7tUMmj8Kl)LUSa%& zmCmle_U)*}`9LhswS+pGZNz?|jX)S~SrUR7wSHy(JVe<7hJ zmdtQ`k;aI)c5N>~A#GF7V)i{(RlS;v6OjF)c2y7k6>l}`bp}) zU_s91pNq|eXu`)I3ag+7A~IY@6XC3)Yti4i=6t~=i2Bsrv_sT6s$>zi(F4l@H{mL$ zpRHE+753Tk_c~?jJjX1i@d77MMh*QBf3l(4S9RQL(S1cmcfVytsxnw zwc{AR(Pf-d#XTePsUv8G*2%NM_PH|hSt_XmNPW1uk>orq;cQMCM7sq-9BeUGS`{V$ ztTqcDStctWztlG*$WM(dN2$2uqs7*^FMsc9Xdju9?s29R!!$DpCjU9*&a!{oj5MEZ zE~R6K%6Qh=7C_mzV;<#aggRg)>g)Js4%Kr8%L||KTC-L1Szr(=T|ZJ7E(nzC@c^X* z{R7@$eE%u&v42kL*!z9Ae@0i8l6bkTYQk<#iM(GOL~70TRz=tAoBY{D z&0DNg>&|T`%;n}xK6#Kv>a($HON^fg+;u)RvEGg3eI-U@$OSQeEpAKJqv84C&=RHV zzj~e(F}#@vCe49RW?@x1z3B>e-qLutF4J3xlwL%&L6>rosdBPK1CxYSSqdthzJ%1D zr!us4KEDk~)V3E0NU0Oy*06{#g2EA}lFEjYM^A0NK=N{Yx1qfgkhW*5v zOE+P&3*hW&K8B?3T6IDr zjvei9My&4J&3k@quW}urWy5{1xWy$XR!ka6Okq;jvP)PZUP~=7_Dy9jUQX}_E%lG0 z@yt_c$uZd7d){?&cv3_g-SKQOncqp}9C)|58odQE|$ewl){XEW`cV3p*=F z`p?5;`AK9K<35FMzT|V#y?86k+wV0FfpH7C&k0NP>xKmFu$eO7;_pRHsKR;Rh`k2p zFgCCtNn4w(Exjc+J3?>`d2IY{%F!==64D$)Sve!!Wu3|X_G;)i-}{*e7li)2217v* zfY`&hhxpsPx~n0R-Fr*Df;cl85zoQr{NesCm+o;$Pjm#CXsT%n5@0=3j@#W{i>R4O zd}-uE&j5_dNN0Nv(eQJ2SfR9$)o3f&SyykN z$-zl2Wh}!V1lMf+4_pk9Y7ESjW@TWnFKYZaZyj;ANj;ng3six!m!+0!+aza8rNV72nDk{VJzDcu?K(3LrnB2aG7>bhBw$gvm6x3g+*4inZ2LiF|uZ@ufH$J zEDkX3mkbWH1L<{I*=4Bq`_n-CRd{^=)GVwo5z^Lmth`yDU6ShSY8#HU zhb#PU=gs_0dm66KG7*}+GVk_CUO*D-8zw66D-JlDRq9+Ni*A4RTOjFkfOyhJwH0sd zq)kZ}{@dFg6CFYtF8_EA(Nb{VLKVb6aUC>^=Qu?@Yfp)CI5`FL4S47?G)KVF>RIZT zcGVLh*FfG}E){|i@=SHoxghDBVTHWWv-F_3^q2=q{jqt@%(5@HWsq+v>HV<4X0YLK zmr=j2o@^aFVChnF{go)uR6Zfz)dysysG|w6@%f+CKkm`-;AXirzmKS&Y$0_TU(CrL z2|~cdO$Xc2heyqmP*YL2OI!s46-3?Lp6dA7Li1Pq*Y(nHkJDT`tIvsxbI{{GQ`ICt0Dyr;6iL}F1*<_LV!O>a-tOE#tQ#Nvicr@Gt6v$6kt^whDwA-wQF7em>o zsZ+L&jN2u#g0u4=!1urV7UG#a?_x>d2O=~$e;i|?)!XqnSWK>152znF<7f+C%vxn1ucgLD z9pTNVA0~bCK*`d>K81j*(k847y!rEuS#(4ub>e;V$$9`bZOuPo$Lc`@=J);&o>Q_w zLeemD&zOVki2>|sm|fN4x3>6XD%=#*J<~lJsN%Wnx4+%5|E0YRq(IyJfO2n)u$@IO z9drJdR(KPg!?&0!=y&G;r6^Hd! zuBN!3Wwt2=sE*Oe5V6DIifwV~Blk1moC!gnH^Vnf2 zKLDM->lYwS9Kn2|pcCc6y;3cqw%vf?VHGZ~+=sLs&oNo)Yx7)$DTywcnXa zE~SG20r9xxJmI1g3#8BEfY;;1^|R0wBOIX|M|3`ypJm~WWXo&ENDDvRQwhy5qZV@V zHeuxy`CfJ9w!D;*3u;qW&hNa)&Z-?LbR0`I&}{L?sWeBf56j_QZ=6~sc);H!z$&PS zyu{g(cVhfz^UbQ?>z$~$iVoC1d4i-jIhS&Dcs!|xDSxr@3MWOF{8_MeEqi06^;b39 zNBCU-N*HnU+{u%Mo*i$ZL(F_Hy2L+leRuVB=+ag)1AkwvBZjOmus4;D$6aaL($ht6 zY22$%Etg`&F410$0|*(H{RZP4-#y+xG_-@c_XZf9M5JE&uZ+n|Y-5~6Y^^{8GNVP^ zHBcpW>kKgp1?ur;3wd(Ib6d8AH;fV(vp zgO0v>*L(C>_O7_E5XjL#aQgbxhUSj)WQ|2s3n$&ej72@Ur?4gOddZREPg}4NHU8=q{V8t zxShCHcnf$!{C>2I$RP@>p#g|ff|s=P9kJNYYIBWT6Kp=R*2Kk1`ug`nyBPLXR$Kq> z?mqEU2?U6qD+J({w)9#nwn2^ev)Nll?eFlkAi08nw%Y|!239pUN$8xlt|k z@OT{^_fQ#My8&ML-m9pWNwy#c&*#Lmsr=F^KpQ1#3GS&1>B>A>({hl$ZOtueo^ zvG24LMdpB00QZw7F22Hr{x$ zMe#w^l*v$e>S+PH{>a6l8B4VjaKlZhV7eOc4#BP47Lq{=l*EHsa~)CyO$n^YDX$>w{j+|@)>@I zpvKQC)>c1<{-^Dn())-Kj~iJaP*L#@$4I`fB39h!n?%d0;{stY_)U%5-*f9HzT6IJ z7X(&oVw5S6LKJ|Pj z7+q6jR?cs4C93~oJnba-yXA<+o1?Risbb04v5@lb;e^jB{|IiGMD7T(9&)?N0>XOU{@9unm9#J$vE7!965xmP{3;MpEzE?p@Jt zdO`ZW#*e=ZsXXafKdps68Nq?tG%k6+`_LGGw;4F7R;WFAV>MUjEHnDX)k-cBIWqHn zD_cKVg2YrM>|2hq+Ho^&_5Q;6;WNoyq|;9Oo9PYGR3UsRYb}R$NDxwYvMiM@m!(dL zS`ZWhS+1`fV~7w5I660D3q+bBcL2J+z_&bWt}lN`Q~?j_R`gb|ZL}HRFwlyBFNifB zPQHjGJlc=xkJfalS!ZarfFH#fqDu~q9uZFZZIg6;xb@t%A#fMaRA-%0Ay3U)J;6eR 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

    %$ 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 lHPp!4$ivEcz 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

  • M>XPPw8j^gqfsC$&{3swAQYi{?5rJsS!oXK#b@-xKU_NdeJROJs3W(w^ zQ>U@fgeF08+rr6D;xIk63`W#%wrXrj6rEZZy_|cZXs4IV43nsU!XF8VJ2l^1)McSK zt7q)qrMBR9cJ`&_waL-nv||Ut@3d5BXvqELHm_Zte5p?P>`0gsG%K@b{@oF%bHf$4 z-kKB7%(z}bZ=Y4}b&yL)*>gI%WkEsS+hylNO|m4}bRKtfD)vlv;-TEvPmGL$ZJ#$IwTPHOAud-rNuL^jag2(xD78`zS zsU2#nFN?~fGTErShOaTbYsP)OON>Q`jPZjPry57YmZ7`!-)2MgGdp@CK4Os?hfX^m z&b#PsvvkO^Fg^XdLDj3BF3y&PTjLMx2se;Hm|}FDDrp&*l34vgH*d;IL6@Ab_5(Ans@WJ=%?Pe zXfI|sg_h}${|ub02-col!Gz#R!T+x67YIo zuVt2vnWw)S$)Rxvm2EFC>j0kX&adLVMLD>T+j12c8`<%`46ak z+G*UJ&sF2-U1qE+ILe0dksRI{GJ~Y?YVcZU#!d%(R6?_N&!xM8CE+`wRbV@7Hcq4t zN7DEw#2Yan!2-9NXTAYeulp$qy_}wac?*eF$%e?tU>-(i7Lso%MUTf~T}9Y$PcB#d zh7Kz^Zm7^aff{wvZ7QCYF4A$(EEi%KYTBFky`b4(^a>SErKe@6V^TyvrFp{MSgke+ zo>38Z9vyJJ2m1clw=}jgV!C0Swb+ZBB&3VS8j|P&&1hSX_n7yyk?EpUBfgg<%bbiU zj!RamHY=l57)epx0dYF2q{=r#I?KF)PLmP|y<%diICw;2m~cTOUoVM1E7eM9Qm8Rn zRBYIQwS0N-et_<@l1KZlaVz>p)ZE0EladO425%Bw&fnd)_0f&M zOO-}5d)$!DS?r!&CwBVfZYwPQa_(V)F0}HS@u0=V6B%<=?t=$QWM$I#2ec&d?v5$N z``^=*{=>ox?T4JMUWOK1o@C-~3vT2U>q%Eoi-O$q7AqYXgrBufeo?r>S z5ua8=>%)NrorY2h%_7-wnP*{HL@D3A2hnEHVAwi>gVdBPw_DxTZ4)KXx;7sB6uzL~ zbd}5Q;_(LgvNTZ|K%eMHLwi&n(O`%eS;7zV8Y^1s7uXbFxLErZlS0oxxa!cLKo$I8 zTQ{((0+CJgM$}^tE3k$KJ( zbTSeqO|j?F^ws(>z-YRWjVIp-Vx|*6JUa7`lQ#8F6idWCqjmf@Wysux)H?9+_cirS z%elrpq%eb>;rXn2=OLT^B11Z$65>*d;KuMfN4m~b-`45roVYW-WTep~TVawkZ*goc z)Hr26n6z{JOskRFvA9F4Y8nd4c$vhrJ1vD z%?)Dfho{*edIP>CTyNcXd){uHxS~qCS+;9OfJg1a8WrYb)wwOw2X!t*WXZHWbx8?Y z0tmG!qSV$oWjS~s?ZQ>7HD=y9wr2aifBsh8yZx|rmY3twZRFB_=9d}W9{p5=mF|2d zeHg=;%KQ?EAjJ2UymCY+q~FhzaXi$Tk=$}>T^ZL=S)p?H%o)p_F1F`n9e)XCd?(Np zr!vo;=?rv)8jmI^6DGfgbRaq6nijjcNy)I%HH9WE*AF?=piXil%h++1v?N5N$f2!N zmr_NrlF*G%^D;KiSj#RLP!>uIHql|mI;|?@d_LAHfwjgG)uEVa9B)K?VYS>MZjp5R!Y8LRoDRL0ZJD zfIHFa#$kHWrYVqe6x&24-w#|3cTHW9mo6NzQG;#-f!dy$?GNkoIV){%>Jww|Zo*yDSJsCO5Q$g@b?vEHJ9_rl0MH0 z-I8+WVN?z9?~Qlp-`gY4dmI?sd+F;SP+ga(-w+0n3kfZIixvcIi_e4SejU*IAftX z0Gb78Aojo4-pBKQ_VHWKaqM^djUsP6;J)try3X_bem~z`Kb~Is^lfRN=4iyg^yK#w zbrCUpzTT=hqonby`b%W)nWz@n#O{sHjJ=GeCJ%IKd?cD_HhEsO=XsIeYQGtXg^Wy_ zK}%NkjlV~E-E%jgbt-FOdRt6FPtkrZu-;vJqW`z`XvUV{VT}mU(M;_Y?A!y?|8QJ+ z9iIz~y{O;d5dJ(PKVn3}u2k+;`rm7#cJ+v9)kUJl)~%|ie4Z2r7T441je4*m;EOOl zDTyURS@Qtq49{Qkj~GSep{v?Ih-0Lo8Q+Mp#5w`T?^w9z#vfg2)C+=aPxz8AFcleyqmSR=n9((` zt&NRy`UQ*lg;^mbrhAUXMPZLGus3M=p^tf)btGBvv6ba{gxr)jhoI)6@hX?!q~jch6zvB`bR4p-^uD$1#ydZ zm7K~Rj#hK)P?k?4GPZmPuc;adFZWt=eG0kKi`1q3mk70kmzxjRcJ(CZ>Q^!w5|)l$&4L~({fOSaq2c47dF?NuwMB-OTjxWDOIlB% zHzu&){SlyZEA5*ASijwk9W2Gz_c^Zsku^WEfoq4&={KWjoFSj_c(oNbRR8ZGRL$RW zMk!k|@Q31h@IzFKj+3{Z^3Ok|V6xVJVwM%Y@<`P=PI!`dJEL<+I$;zpS_QJ-hQ{QW z_(1ZB2-L7VoSXx1-2mx8?O(MH$J}Nfws8SFe+sSsE&k@dLRmCiZ|DoUXH}>&s_8Qb zZ0>PdbdUld8dI^pNOiHO8>BY|kt*;8(bO}+N)i=}-+Zea86f}Gmb>~LOy?%qYV1mP z0i2y`WD}wsbv37pdLeP1t1|8&vYiOco3c^om<6F?Qc--^>I71evjT^m1-K(Ug3o=^ z!_gfQQdxbyHo8htiYREpMT;`nECXVwG=L}JW86lanKU}k+0j0d+Lei8o&bj0btRdB zdf5XacW|(>-2%upuL~00-%5&rt2A;yMu5KE2Xgaka!AbmX)16~xPt0Y-Q?=u!4z$m(%OLoM>#o86mUd2niPg7rnU=MVl zP3_;+7Kn7CP-<8I6xiRowegh3UCjhC0H6e4`NqhP>s=V;lod$>mIXW!tDK}UjVQ+) zCZ>t!-y}CM(a+rSm*J&O0{9F%Km2uT|7`VdB&4EA>Qok{L|fofJ^UOD3eGed-~sxQ zYV;=}p7K`WN-mtp;J^XGVnK-f8M9u+a+bRU%U?E_Y83%%q@IzH)4kYf#K6)1UWXq2 zrgq}Yu_!LR6#hJD%w$%trVkaM(&#cPnUK|4X6CM#NID7cA2xw(L6*R|MXG>C$y^L3 zf@*jiH4NZd0wlj%P~nl(C*jWB&TucC)LPy8%^h63$8jsl>ayZK9G2eLT54MF+dfKe zqqCq$xZ)8BS?dCfNh#AiSb$9zjB)D;0Ys!waNNQDa-wW82DyoS;9;oxXD>)TZ zolUg%o=2Vj$;h)-PN1YN{#M)MTi5QI2iDmK=^i_iU^l!uTrD)90#XHQ`d?3uxB_2f zi!*Rc$dXW>km44K>C`g>Recwk^s&vtlOyW5wh=1D83=;HLZ0bkvEcv$P&zngq@IB zo$Q;-0X2;Pb6QQ!f-`_lNOpJ_^9vLm%GFsSdm1olyhf;|g=9J>FV?9>U=7i1ace`& zO8Kr#j7BVx?3n|2A+T;MAxlzRM*)_woxZ~PCMbt$9;n^LcXxn}4|Uk!%Vl+CZljM7 zDy28D{M3KqKK)%*B5LX(!Ese#R~A%(_z@^P2S(*a-GXR z&yKDUy?NFTI9O~?JoIfGIb9WNkvgotTv(>l?0xfMv*GZN=$y9itEFm>XZ2qXW^3Xt zKX-?`{uxtwRoBndl%eCWimTTfhi}?#nQDAFZNu|5=J*T9#EgY7wNEB#TV1EK-PJCt zwdI&>`6Iu1hdnmJe@k1_PnKcF2z%1A5Tdj%iU=YmWK#$Kla9II^n0dA20ORwfIzvQ z*;G67_U5;Q{a3f1>J8K&$m(H>S&DWMDoz+1%^*kE5Mptk3)856m!`%MUE3p@r?M>Js>y1q00ru%dBAd334uOs-TFGCUNK|%6_OdcQbOcnb9$_ukfgOGr2Y6vkLn3n)hWZQozmbr5UwE-@`+%0jA8JGu5 z*8&>*d8stog0C5P#S!H*#!0~GDI;4Ert-G@0;m3(Zyie{M?V6Jp0VMkhd=p&l2Biq z7bHI-0j@BKq()n%yY`~)6g-J2wKekHu5QC5lWI4;O;^D~Gs7)=>=))4c*^3SCWiW% zl6Yx)4-)YF*xmH|oQ4+Kv*N>kS4_zrZRjgJpof3`7pVPaYv454+TdzT8YSpu!Pie9 zjm|tV+wORGJ@s9~t!BFu(i1|cyXC{(>mKRH(Q48X(@WJUUY)*w?xmFgBY>o$i-R8WtUS+4!bqi-MJmG7;@ZJ73*}r#qR&2SK zV{h(HzN%g62{R6IKN1WSFczxzY&(4LcdX*U9a^~EfF(!ks>kv7pBJxW8{ZDyz_5e_ zTE8BW8~q1qQt>^asuqS{vnK53moVE`C&Rxzd6lG{h)|AERMVOn%m-}W8IepAd2<*q z?3DfB+W9{6XPn{g)V&dFSlf1UU+c00O+PI8taaE%YFNCtWrEw zAD&Yd?@a3*4axQslZbqCOTh@04#{gVYJ`@Fgnjl5iq;V9L00xgxt8k-qYSXnP@j$M zVAYE{7lf%@3QsBP7&%8Q(Yn^b_JS1;2DBOw8Pop|Vw~r58B=qw6IZtttQ4693~?72 zGNXAT$C6-dje||>gltkqe;L4&;xymN=`m$xl{%S{DIko!se4~oeuNGOWh<-aLNa&` zrB@Tymk}NcNxC->>_J zenrA>*$MbE2kSk4kc1o);}gh)%T!@z@e3KN9 za8^}z+tm8<_O<;dW(3E5vKOyDw~})Gy;SZ*mX7=#wwN6SV(yH59e%u}J}@tH-~HO8 z*s4IKB&A-we|7vDRha22R?+!%nI;!iM4D96um+lK=U-!G+-fujS@YjtTGs5J4 zV|8vd`WSm?UHlmaVMHbJ0br?;#JB!?8=1%K!rp7`o;1clwLV9zxpx#4s0a988axC+ zgdIfTAqZ6e&u6t=Nm@dD8oHAr5zfmMSH*H7|D^)(`G66ney?Fdh2PjMXNc|KT8RVf zquXy(mZ$^udM1Yhs0cpe$UdfY@0~PuS%vEK2-F_|ZiE9qrK-5jh3@`2K#OPAX4wJ$ zoR7u&5mbXw7{en=8SDi`F)G+GAM7ieGrBk*}tse4Cm1an(68MU#jX?7O-U ztPyRns{f*8f!jaE1<6r^J#R%@RYN)6(P9xJV=S`AQA47N1IWv>rA@FRdHd=(n^2by z2tXojVhw|aX!*Gcz+>TPOi|u%YdC!j)x>U4qLAw|+S$bpB94JZkT_*K$oS5v=03W3 z{G#96w!Y*3J~$6T4F1TrEa$Ld@7m;htcGOVHoH%|n^aV*1mLAA9CReg>i*V)Zi7K1 z#?vEd%KfLcn(j1SyuoXFiuRoZ0TY}ZdMQtZk491}W=~(N@;Km`Tgm+yz3Dq$q<=y6 zYMJ5Dw^i;odC&J3KTSXR-Fjs&io1P@v~lT_S_xt+$V=booAi*bk?AEt;`3b^2_t8V za2iLiF<;+}rd*qBrTu>J@3^n{3rAxYo$s3@_+@UlW&O(?yCnKvS*5&+7Fgd3zEs#f z{P()wzn?v8a$BEP;CA&6;6bup5OqL*fq037C{)h;4ALCCL~Lu~XBDIjiE=!lO$O0o z>3MAZnAp%dZ2;Y4HVJ6n9VjYe;%VA7BfN+NS9A2aDTHr6OK<_@o7OjilB$8SuaBd0jP`tHnviiY{d%3 z&}U@rd5a6fZ7w1}Kl+gI{u}jk-i|j_edpMPN%r?lYPYy72Wmb@k0<((3j6LJiP9^v zHdZnCawg---Jyd+vBpJPibK|fx*v1_!(lu1i-t>{J(w@yG5&b+`)FocEzqQ+`0!3y)KV7eAlV;neGX6e_d)V_S_phv*+ zDg9kVp-(S9uLZ95agO?o&ifeZo-4T1s`ZdHAd}kxr9R7Q1`WF$pEa0o*RRDLG-SZu z>RK`xX?^Rsq(F_#t?QC$oXcOGJc@Kz=d4!WC6^-3;usmF)=r+XAMJek>te}V?gUt(Fq#CgWCAU$Bt2NkO z&;T$UN=A>KARXNyrFH~(7jH>IYK^U+v!V1jSbe5xxO5KLWt|kmSvrBCtHsgj&%=EKxQU=Um)4wj$l^I2)2av{FrC?AWi33=i!+1fDa+qQt}H#K<)1YibbdX zCBF9!nVY3pzt;-x{cNFQ7S;5L3~dt6-WTrJ?n(nhy@du!HDP#Y$t>+!8mxw&#%Vpy z(;2cB8#(nuQG>TlW=JU7ik7R~9KVALQ&bkArfUPDpgkOw#!t3NT*z|%v+lWdwi?&p zR;?R|%gPA@-Rc!5Ju^lV1@ht0jaKi2QqxW(ybq#uc-&eGs*Bv}4CU)ww!_|E7Tld4 z-JGM><1%^r`>N@jjo~e>#eqzhlZASTn|xOTd_!v=`|aZ2{ro7itAU1n|8s3uv_G?E zFWW3t+0kIifyJj`4m29Z{Xrue-v4suV(USRYX=saH&r$rioIu!W9rh5J%5w0%RdlVaHR=Y)QVcmo2!=<}24|ya)9TIWd9K2F> z1?7|%Q(rw`T3v<(x)NDqNw$;Z0-l&n*z_Tr^W|M6=J!hOU&dltO8~uQ zp57`DbwY@A`sTa&1wC!~CB#;9EnkJE$rQJ72E}uRtuE5mb8C*@h4DgI!-CKVs!J{$!K>6hEpHY-f#|wKi2=AkH(WAk3ixb6rC!l? z*8=*d2wlrGD6PiVR=<14JESAvd5n!!EK;~FjG~XC>%=(7?W5F`R4H(*_cfro>z+vyo9ZqO|%~uUg zQctpA7cD5h)Ph9Dojv-Nsxe?tgmwSo-1?uFlnec|_v*Ynlhlii*5jzv*!|d7-}9`+ z`ib=C*JC=m6X*=zb|2R|2_qlvA{j`S_zN>A`8qN3oC`A9= zoFj3&AK!g(Xu$Vmy|=;0%gj~e@++y0$EJhHHd7l#!E1vyTI~)A2s$5U zT!^%Y@=E0JcnJ;?eOZQ`uO8r1!Z-$Mc~OF24^c|wbi?bW;|MOmT!+uFOZcvewcXY0 z#GeSUUu2v(?}yWGxPtQxC4Up3l4Dnsd<VRUf+bw4WVAd|BeTo)X-v-BrGZW<75wk{Psk4I? zosi&QA|+%V82?uqgw*s!$|OcSaUh_Bz=agFBNsUz4O7{>ei6TdeFMB&fRzcqcdl&5AZHb?}jd{iWR zLGq>dnC4aQ?zQ+J_fe8xrI&jWW%zbWzT*bFcV0@t8_!xkk(}H-M^-mZHb`SHWsHvR zoH}4Lhh?FhuJEm=FN0$`5%Jy%b1oFDxbc*nN)fg`Qzc$doS?ukAM zUIEaC{{-)y|I;k|B|3CZtlIh)dzM3*>K6CD!Z8cKplGB2?2HPXG*f6oNJ<(Q)+=CH}#|%h3Q~JOrWa4w*Dx;IL+S=XF;34xb0sO+yG6wWR32Z;z+jB zLwZ!-LsrtbQ5o#5B!E-D*trs)g1S={+b_m12v>kbIRhfak7Ed)eR2vp$FyDtyeCQ@ z!uDP1`NvYgn_of9&vI+L>r51b@|!?KLI2A!(xs2kgKPcDDqD84NB>A?94&}s+hZ6J z%`awt1xTmDotD_BCx{5XV1!8y-MEsP7g&qCJkKhm9vzZt6gm#4; zYw$e$^nx!Fd35u^Z2#-7K7I_`6G#Bg*V zit)F7{3*je%scv>HvuElT%U5SO7VLb{a*|$2h}7?)j$UW9o}C@^XU6-{BhtulE$FE zdy)1&r#y+2qIG3x2u**4FxBG}%HX_NfQMeyDMXaSboAmn5ET#vY*gJApE%rX)H=Js z;d}~@1VEr0ZmoSvsRiYi9UD}IWLiRR+CT@nwZOibPJ+9(3(3n6c4-sW1+argapj93 zcJz`!!asq!YLv>U*P{l*eMKm%SJQo(!jzNZ&>RD?#2(NyWa`Z^rpJ*80drx}^v$SC zmke-)7j>6RXw}q1C%?w4@G>|O{_~~Kd1heM^!+y?DL*{F@?M)hwad( zQVyMNgysgN+0bbD5yR26c|Zm!vZnB>bEsIBH_Bt{kk75tA36eK&TCYaZB>6AwR)<0 zR_D;<8jh%&xtxx3mwV9D3(MZ=`B@jCsqw9~_o9sqeU{&O(e;IA&}9Md)L z_p~8E(C6*xqOyan@%w@1^%YqYyACEfa$2xPtzYIl8ne1eZ|y!FbU$)W^%JfGj%0>= zhSMt`z-X9VyoZtYJ5EmZUnxUmh53x1F)X(=c%NU#(WLL?FRpr>bUmn8xNUm!>)A@c z;!^DtW;Y&hd8hlD$z~BrnSI1#n|mw>{BPFd>F>+gztw42zl zcr?|SNYszKFOE0`qUI9W6Aj@GB1xL-JzRV%a=A9XuM>Y>5v0kcA(e!XlF&5JZ42}L z5>j2GmB1u)EQ6EynOlN&ZLhk3`Y@FE;#Pt8^wKO<|6V~V{(cA)Q8l460v2_$OU^ra zQp6po+ybmG(19vaWVGetCP|UP4BDv9eCNABsMFB6xoV(^>x%t_hzA9&TxugGw#Gn$ z&UIm)m9z1!P(`v`of?uAY+T*eba%0AS<7MdZ67YpILX8?b)H!m3k13c13ep^WGM}m+e-u7KH}*B zw{Jm)F?wx4#kLv++XAj;zF8a4pw3eOl0dG*0@&N0ZKh~5kGdUg@YYso7!SK#pws8* z3^xV<3cULO%n86D(pw>9NXXsQPE}_c?I=~K12o5O;qK#@?^-`syeq2*!9R9=IKk0& zba>G=m9aJ~)fq zcsc)3H{_nF&n>r4;3lo%|Li79ZJX^v4Jv1GGjq5kTi9RDUCCLH0Mzpzb6%5+)7w>i z{{VgMhZS4gY|%uvXdK+QfL`m-c8U)54m=t8wo9Uy0I{Mjkx_ZOF!#c^{rN`rYqJNC!$YYC!-*f0Vffg2OEJ?qglQ zovms;1(1)!-v;j98+gF!qq#Elo#xl`z++To4K8za^BKdIYmR<1^&6DTE>j$7Pb21N z%bgP1Sb!b&(yYLS<%*X&wIgig5t4wh`&DlH#jC<-=54jM!ESF?QZ&HtKQc|dVGqEV zdX6~_AW;EER5xL8qzJIOyED3arslh%JF~YCl>|!~hU~CwS-hbP-WNb$wHCa$#IVh2 z^FHJa(9@OIwML6Li%f?;>Yz`G%(t8^7|ST|*p{QouV5IDBEQS(s_*E) zp1N6DibOX2<9W%}7GzdQh>(?w_x^zWo-qn!qx0v)6g;{*8J17v(`yQ4$TH4|ez){| z^jzF$YO0ixPnHFoT(JK1w$G(|^R>}GubHW=A*h~xm~gV;&CRhPlTLk=snOE1Um&kD zTfJ|_^W`>8))qNEaT!?i*0eIS#u+aXZB`SHSo^~ ze4bRDYICy)>gK9Cvq8zK7aZ5`I(JEb+v!o2sz7!9ELOvI%R|kAl@C;)!`~8b7(XUl z`oH}QhrRRBaoX!ix$&(TMEXA>ac;L`4Va}ePZVKGlDh0xRu*_G0&7IsuxZTQQ11Sl z(vJ;TBZk*;hHgx+nrHVOq#|zg&v$wCCr+0Qz)LsT?DOBD(%k@6hid)M6n^jc{e#8z z%O`d2N9MAoyi@_lQS$kP0Y^`^4QHgNcYat@Apd*=sZB=@XQU}U`2`~_3 zwGsh0kHDM?rLqLfd>I}^+Rq%>-*?dOWUS+M(1N@@gE!AShAFVl(PDo3BKFe~slm>Xut6)>)2nOJMSxlz)#HddvzG8uS*jqMi`)y(#YlK>} zfS>?!nVtHO^hlu|Ev_e2AdO*4mzC}v=PHV!NOJ&wFYI`y)!I)(Mgl|PMgfbrEDb>S z795vSg5>6?vU&Y^F?VJG$P%Hm0K!#0|HH!-=$80l5sNoKBDclm+R80D%kKQ)ee2M70oT^!pAv*bgXp7r;>KjQXP24zQhv$qx+9O7^@|MmialCNU2Ze@L#BTMf)dOZCR zc{4En6&tXqUwa42oj_DJqbm?*d&>2x!4gMD$|b+vT~GU&U6k|6+Fy{Ucv$Ap6M}O+CbdA2$9uY57hrc=2=<$s9PZr$;jc*%|Jt? zcOW&5o}xJVjQy&uxa>4&YrR+LdUtC4ZMD`6(=Sijg{Bqmjl!fXbt738*YUa{SD z1ttva(u=wZM`X7z)Yyd%#M2GZeASt$H?#`uq1z;-OqmvzJDv$D4v6PdQa1qDi1VOtaYLJ!oQ0&LA4 zR%ZnU`xsfOpi^^z#N)eOH|mntj!2t=uRh35)6MsiRm>eAa*BpdO=T^C-@h~wtI^JD z)z;9$HbM~vFa3i-Hh0oFb(YA77C=9E7j5*AGI*KFaJqtHG<+espkK;OApoXbBm-73W>@&VO;`TSh0K%8qXY z&*ZTG$&TVt=ov_M|6fyu*-sCR@x0K#qaM3ZJ&<)Tfa`urO8G7RY*w-6hox1n9xzbG zl(rfH45*XS@h7iH{X*pQ02E@KC8M!bCoc%qMhr=Vu!2u6I*pjNh3ms;_eU5ji!Clb7eLCrVvi zap=LLOu71*7KqX&^i97SHH(a<#SlrnMj$!<4BaRW`NBFK%%fhDN{NfJT)L_NT_@rD z3h}&5L8=gR1q4Lng_@C4aPV1Lh`nSP~!GXG`lL&_>Bk<7nfp zNGHCSOryQT`qdlY1@Z{kO^6_I7J73i#Zl>A@@|zP5AC6h4>!xd(l=htvoK^;rE6Vf z#Rea!1?rQQijR)#%tcB2&)ZUmzQnJv#N2@YKjN=jgo)*hBL>xgkOEa{Z*GCF#Y{lS zbWN)=$%Q?a@w0RIU`QE14M<$D6n6CJ4VY+_DMRc<$YS62Dy<&(=4fN8drrsVzUL5A z;EX6*=$aPh9nlc$>D9D)A6|BWZ|@>$=5$f;U;*=@(u`xFl7gCQZ#`RfeLM_BT>wOXk(~cnw1FFyDXBS;HuHq!RX%arm(YFxr_NY!wH-c zXUivkxj>ZL{XBq!@%tE+vGRO&#M+<(VW|fVSTgApLv+Td^r`@B6j0|GI7@;NCDWWe zN;dLv%@0Eyp>=v8px@fxJu(E1={C~zt!bi!%yQ;f_g%G{QTe9F%83Q_I+WsLC|d;# za8raYDLm01=0x&{f_hHlW;|j1_F7O+P&pKp6Knv&MI#D@%;0G5NuYm0P$kt1rLO)a zce3MS`xEmf2nsKPmWL9Q6fMld9_C_35DJ!29NbwT)=3&BEJ>F5u_p`41NM-uWR_eN zFQNW03K=D{W-0E=ojw2=Ua;4xLS_?p<_odeh~x9$K^*&@D|k+o(BujrM8Y^4+BU6i zB{w(DQOzn(>#xu2Jnd1wR8=>S8nV4LioLjY-z6HgCB(Alfa+#Cb$)4f8AmQV z{Ant&w4Ejdo^BvYNT05;;WM_~qSb+qmdV>pYbk%ct+&?LcK0hBdm~S|N*#4WXMth3 z*l0ZyM=w>+yGkDHiPr+~(BKvO&QNXk|BRSj>tuWxM(f*baR90zVCMxD6KTK=}@GVT(SR zhZNp>>^8E;pt&GXvlbct8wdoeA;9NnQEd@hU2kJDz{jGbPF##rJ;%(baT&M79yC?e zItvOtOXFjB+WmCqNma*4a22W6(neprGyxH0*W2IIyqHiV9zcTpFvWb; z<2JgxnFPN6av~a4+&T*c69G4J<9}y$0yi=N2vcb(Xd>i=sCbGNtP_E65+$)e1fg>J8RBVh?>_xG3mzBB))PHM%~5zkgoV!Z({pGs3a3<^2Ad8iTJ| zCH{`Z$4AD^NpK9kKfR0D(AA}^d1rS~SI|&u^R~#vfwkUUJr%c~xo(Kq;V@?`y9h9Z zIYV;oBmCDAK43Nhrl8fH0+Ielt!R~%@IPxFAlGjUYl{LaVJAy+-Giuy4j$2{Ri-io zxxlcSzVFJAnCzJpDAhKs3+HnK8dQ8u>@S?x#@fvR>n!@QwDMAlNKzWwpRJpVbInV739W)D;F>ju|zl76Vh>fq&Egl*Y>9fPRK1j+OV(6oTfWmL3OG#R# zP086#c5(XMu-x;lxhdp3oO%`bC|bBUh!~H~qZ=neehg;A^9OY1Ci&O>TXrZkcV83dn7{^=CKKCu*HjKoNBTCQa)mnD%iytXf0&hhYb9o8mWeK3PvIYYr zS4IeTWMqyZooI6k)xX!jxxwi$G+grnf4BA|kO*U>dk4aAEh~u|NFGbfrsd-ejNB7q8i- zRinZgN`xizlE);1ba2^Nns=HILUPQau$~ijQZFOPNDSUi8$}FFo-5!d8wDG2(SR5D zA24|k3IHxX>ek=7%hM|(LAh!8SzZi!UGE>g4~5XO!dW?(GbHMWF}H_Rzb|X#ra{b? z@0VjztmCS&;>Q2phI=;l4)*1Jl6A3Rx*8G)X&z zBqTbKcGz11Opj5vOr<5PpVw@<=}v3iXXKOj8$oX&8lBRR)c4$?zD~3-#U$kf(t$l@ z4O&1wea>?2RoShk>I^?@AgklTrBgt%soggcwx6o4N|3NEX)O~DIkTDFi@>0oBkarr zl-3er3=13AUd0LHEMkSU#Lv@Q0h#;%Xp1=^@3JCp>&D{ z66#}I4GI2e-q1TD^*r+dAz;h>N-dN#{F&2|ze5MyJ60AV|NT_L!&yMM!B4D2;oe6W zAI!Otp!LHMWic&Z$Tu0)s9fu?zk!cXWA)~0RGX>Zym9VBI zYNgavrDcRJm48TvKDVL<9184aBp&{Dxf*JNR$Ox?*gX6KzKuKlx@MK zU!ZF;xH}n@m0oxhG8_Y@4+fARv%qJ$OONcEL=d3Xc z(_wSVZZEZPGLS-mJu^=tg@=Q^9T@43H=hRpAa;&7F;rhQ6ewzIhshoL>0e2l&LEmll0mlSQiQQ*#3lKTm$T z=;#D~eIM(N(rnVT>^_beOGnzesrhAWMWHL0I3qkaWvdbZj}P8R^`?f*0Uza~xl^Om zmINM2M%e-gI_%&FqPTNDqdp6gHm7Dw_3LvHL6NpgE*&VDV6J-ru`F1Qg@DBz4*iBPX=aYQ9Rfwr%4*rA5dB!XeOajK2SVq`C2g2$>^$BiR@&?zVh*x^T-#?##Qud$iGZx~ z{sRO0+z3AcBrZlYl^hF7Z)C5QmLDK4rGgv6pZvC~eBEz>%H@B#tKBNr2KRGog4Ntn zw(3mZ{4rp<%hHX=#?R?na@W0fe|H4G(izud#>PG~hx-C(yVKVRBtbXHk>6#($z zmXMn;9*2E_62>tT-4ZW_iOAHJtlpOZ>7C zO0Pw?_A^%jXPBsQXnM6z5p%EQ4+e2ho(oFLsYRc4Y0ZSUpzYR0`4TW^g?ynkJN zp~KXNjI33+1%e^;De??8A@#~(xtUsBHmv#WS~acXS+Z|Hj@}pIZSvr}JU#_vumKxS zK&rv*(TNpCo)UkDc?{FsqSs0!V%!lFv;yE@OvD%mS_lvr8y978NazRj{!XLsb6P*(VN(Y?qFO*TjIs$8xN6=e z0zM!YNG+m$4=fn@SD!i=z;*byV_*#p0_RhIKyp_DRyP6>iOIVDNtUQw>4+spX?zE8(C;lM3uVK zf0KP)@8kB-XB|sH3o=_m@&L*QLAyzxnZe@mH4qvd_|LRBAVVh221?F75}HtE-oDc| zjMIvxt6*N4TXvD!M?)1d{_#GNoD|)m5jl%OHSG)VGn!3Ubfa!agKU1VKPWmHAk?D*4)^5Ko6&$EMDc-N1rJTF(h=xBKE z9kKkH(PMu7X~*~Sey>ySAG==7skeu$3jV{lJ*-tPl7;dY1)*UtinKKVXQ*ZTU-mtB z3K=<#4=+;D%WoaqPoI1oFwU~Gmx0?62KbLoLsW04W8|L`iGr-`wbrOz0pyE#eo_g`-SNbBR8!Xy@SrFciD%QvNfFuY5BRP10Ny&n6mTy%eFp?R(6Klm zkp}>%u^VgpY1>kDILo*jUGaa{e5U%=50VfTwo)K!#d0Apg&Z+-KkWDrdek%cdLY5= zHAu5ZW3>+(r*+JhwmRO#Ma%&zmmar;Xz_w%qBF4wa6Dz9mwTp$(sbQ&3ywwnOy&Kw z{qpX^pl5&6sX*gwc!N5{VsJ~M>A>1gu)@{%CyQcE&Ygc=;BDxba4}*KzzD)?uHYA0 zt$lp6Soz`zN()#*1ZftutUqy1_MPd+(vDG7E#`DXpG3eBvo(Ejr#oN#k#Qp`>}lz{ z!_Ic66V-*y&1&|@$lmza|Aa7zz(Z2S#>HjHi^j9(b%;v^-^wAkBUN+>Bk${+=4^Cs zOTItJ*TJqvu(hqkJ$!HSATauFg^fjUq0<~YB82rM;(0Km1F8t$&yg#ZRqFldD*gK1 z))XrC%16=-zIUK&L2PBICu(s8NY1_y!;1C&$-D|bS>T0k;zG1)ohrSU?X&V;OVj$X zQACBr)v22`~Y#Ny+#`m2^T7oa&@Zq6#)8^SH~ zvcB|eoKfI)huf%ZDTKB~6x3kOoUD@iMIcIc>t7mPzHqKD(2>5NQSTvqeFm4bAEkLsn}iAI&4g^pG;B0~?|9>_^+u)1 z@7c9dci#F;bwW|2?p&dZn!d`wS_WB%+gQJ>fCPB+%Sr(^kHhj8@N;Rb#tx`CYJWG3 zUQ8EB;s&l7&!(=Pyg6~b?RC`PA6zq?SE|9q?$?}tfev$vg16cHCg@f zpSNHP`bWm)FsFR{#_PE!&Rr&iwT3FKUw7oIsdkH^fF+f%fMVPQv9QE{Z+oG*B?dJ~ z_5^d}wSk0CeIZI~X>Es*A6KeS+56Mj)h0cF&cHX`XIbsMIV8=O}~QML|d!|HMq~M z%`c5fieWgj>5F%0N}0BXIIyq zp={z8uR?+n#>*DC7a18GsgjCi>gwvs;#AS1_FDK)hZ*D|E%0kN$+1jj#%8TZAjQeP zlCz|%thkMz?!{QBi+dwp6zy}!dWU}=^z9(t)rz1FAC2lt{$y0vZL}tkl9obVo2+Bt ze=5@<(;*4<$nw?V>cw}h?y6tcMEYb$PCl96mUF~5-RbWW_Pb6egWkP6ywd}ea>4{4 zbm){@1BPomz*JJkrATHlhCnduyDLpNrNmUJLOTvvLdP(nb_dr_#cq4a(z&v|;oR;o z6*H8Q%1G>U)0#v7(1pFyOm6=#zHmJ0U$>~=lh4l{cS2NbZ~9c73EvgDC4sU!dd0cs zj_2{Wd_6Nte7@}qw`kOUOg&fLLagJcVdJdwj<{yQTj}-Mn*J6-0~{{kBRaA4>}?br z5+YqvKxQHUqETKeGGd)EfkvBOIf@7vGRI^XYdn{i(PudO8dba%;CcgKbhW?`1Mwa? zLfH>i|I*Z$_&|%4bOSd>+W(P=C8*=nZBsMJQPy|s1ePmhTam^&?#N=5kaHj6()Zr*CWkhL8bf44f|mJP z#?oLP(qQ?l{-oE#sIz&VZjUp_S%m@)a6n&R&KJaUL<-u42x?Q`q$0!E+GLkCIR~L#SN1WO z9$U&9)OoKax7BVFpx0Nv#rKrF-f?0g?7gY6n`sr%5MR+3XPx*9be9+2p)#XyEuLqU z(RIWQT#@X0uiy3z3+<6(1CL44^d4=58dK%b+t=Lh?a1#>HBR|-sa5Y+zj~ePfBa04fL?e;_hnd zIgL~xFid=_*($-t(Eqyg@D-Q$PXdZ&i)7?6(pnh`qY)T?1DDHgtqIgD>9u=prp17} zuHTLN83WA^SRZt4212Y1GN$|jWtad}yDFey6bog@_R%_k^#xc!c+`(K=Dz|YyQ0GWKUY zz`k@WMGPQ;ac=N-@_rrks4L;3RmVLJWG!coNfWmBU|q2v;I5OzXa;5T69X3_iykSF zP)jv0#LP=@+JR85D<5Wg@)K4@JpD6=PJhawzNS}WzL-@~FQ#e*JW~FE-sE3&FX3aj zpLyL2rL=Y1x7$w3cV9k$@_?%y-R+-IRib_RZjw5DtzXYc$>~%W@zD3*u5R)S@{ym? zqYVUGoLe8OJ6Q)gO;i7|YY)PwVq4|46UG8v6MO==j4wyiZo+zq@dUW#(EZPU!`Qjs zZr(%oU$gSU8Fwl_84?A93soo9JJe7Es}2M7?lB&B_yYse&s zCVfY;HAaHYduRq+tkfK}Y8(j~KyD)KA;bpT)&uNt%;3Km@Rfscw|?54GpMXY>uRKc zPe&AQF-T4^LKFw=+Gbi1ZN=bsUv@Pf4yxi0Z*-sKB`B{G-)`U8>zrb6AiubDO9q$5(RlDLtymxjj@5)!>pKNUAN7d2sIq*Q{08H}gG7q32(86sVhip(O5H`s|}` zQG4%vkrB0zJPv560K9b)QY-m`qNzjXUX8Vayb@&Op5fg#LgTcL!rBW z4rS}_R2Ct@jr=*iBB4IL8@-?}mRre;SHQ;s6_9$5A#kb_E-+emrEg1Bj-kl1sA>Yu zX64Fi+#Omz3#Pjpw&gPApeC>iE@Tucjl-gYl3k6R6Vz^Sg^SyvgZzwvyt zy7?(4Mpl6N1^OKTvBgW!@vD1*JooMY{a(-yY)<@_1psp%uk_b1zyH#j-Yb3g{_h`qBhHTfbF9ie*+ z3g5cW_Hw?*HL;QYi<#vgOp& z>c?^%s>!UUhjoH+n;iHS2%E+JSLI)G_tFo{*XxRQcjPb7!tZWlWwEa<$EcfqWce(% zW&%k5An5P=`%1bXy;kVY%lwn`03`YU!3$eLydjYwTLd(dHLc5^(U1bAfXrtYv)WYi z;kCK}=H}z)>xAPYlY369Y>!j9{MhMO-B#Ox?;HHqj>*Cg0&~}c58{tkXWb9}|G4|= zr@DSG+H-NIxE6Q!;_k)W-JRl4;3EA{+>1+#ySqzqcX!v~etCT7&HE=_W->{BIho{~ zGs)h2?X?K418}!GAo~)0Zh|v+&72qElu@-8{)UP^jyM`L(tVV?I5{tTx$x3|@_+Z=9xlA2AP}nE% z_N&VYBk=PJsQO@fecbJuzqkH4mBN}HpjRIP2GkGkz+|!abwe+ZSnCgM!`Z9BKu`W> zKi8zmq5zHoV`)9pX!!~&ea+=Eacj1TaC5qFh8!A`v2e zj8NrdCDi}`>Z1#SApEbfv?JI3Xb@dwb=?2}8S8%)1f*x;0{|HyCn=`koq5)A>}7uJ zy7vZoC$*|;bZYpuV5j@b(IJv!_ZzYa zbc`p#=5kocnxAgUpRp0ZWIoQ)Ru&d}?@dp2<6Z07Ebkj@Xr2O_4ij*L$5uBkbw1V0 zYsL`&X5v_$jKR?>3qGY3>ulD*W`35&!SVC-brznC)lpaLIzHW)w$bn_lZV@4&OMBn zuvIsjE?-}_;ja58nT&CwjQ2}8pz`3}ofKHxbhuz1eA^H13X^#6=t9Q9K|2`<#J6#U zt0%KsTQfogyaV}!0sJ{z6MU7xHyD5-=--z6Fu9Xc)!{iDU<3l1yZmI{D`ZY~v^nVT ziw}<=ee1NR)HuA@!l4AZMr*l$aW+_fxfoA(LEcR85MiKyeJENt9XZFjKtoq;|L+lL zNMxWbh%m6_KLh*x5YT=&+}KVxRxDAaIiw=gld$t2*w?2il6q}(B^m+?_aD5M>MMIc z5r)P?89x1M+{7!-+p@lAZ;wd3o(PGFH zn2vOHDYMq}0t@}@hXI_$(|S*tY#pHA@~=4oTMW*4RoFl^M#WKJE72P*z{Y=DN<@{K z!_buS7+}rkbg2bEffLVDK4=n<5fk3aFp#2q?GncJF}oo4@lHz~yh#p)C}rnts1BU_#tP zYhk_&bhCj+{#aK6w+bCoBp9ylZsu6cF~LFlKQCd?<=@LpyR&;fzq*FQINnb3T<>PE zTzRyw1Kl{AMkcVitn8iEpL3BuW^j3KgaLP8t1xmJLIZBHarnpF@F8tIk60-3X!$#$ z52wv-{^Gx(VEcI_rlbQgWe%&}NO$>NT>Fc9;+I zSfk}beQ)>x3wU0Ts0i$ECO6Qnvk4{IQ3vsNjL%K)_G(f$aeywqDqA!5f`Nv`g!#`` zoW8U8@*{Kp5UdV+w-v2(Yi zF@3127(Nj)`L4-}Av$I`OadDqIVatiWA z{0kc{&wwur8MKO0RP{Bdzp`6rsMpH$seQ#zjzI;C5~q{_Ua6z17ll1$eoh59lGMDe z=hAg@pxz$}7wP-t7=%O$cFNOT{U4{9---+-Is)MH-ueqR6NUz*c)W~kg2shI+-r(c zQCZ7rKYSH9X|_6y1;D!|GJgfsq zxkeQ8aYFAxyyLpiU|LZ^rMa#zY%UE=t+^2r3pufguNZH!C_uKuO}yXWm5TJDIzrC}{9T&Fua|nAmpDrh*y z>18t>a;O&nRy+8YQ3(`&)nvM5hbVhl)t=p&>swgKgbTAkjXSMT#eiQOw4D!AXV8p+ z+(9LLh_ciX3R~pz^)TGZp5p0He zg%U`?=;yQ)^D#md!>nigH);Ep;+}tUt9gc{fyH~C8-0NXo1|#+*WItyL_#VA=_fi* zhF23<^{|`j&3O@B&_F3RW0iC54BNkzxf*|j)PNRf)`3z%Yu?mT>eRl7F!b?jCHk2d zRzkNa?-hy~49|?nesj3@R;S!2M}G%|ij zjzn)E>G)+E9&m*4#`d~Zt0|Day|Rj#8g@6z6C_jYa#iXGlZOMd3XDC^LvKw1@mmv6 zaIpBk!Ij(v?{=THZ@|Lt0|?RI0!xW1{Y5UN)>#^*0hDFR(nB@usaykID8Rd2=nx6+ z;vzfUV`84~&Bblq38i*9yrIU3GV->dEf-AVl5mfH&dG-qHw#yS@Q0BY%QFU{oIQYz zGkokyk-I-7gHp=sjhXZg$yD^1vi~J zO3|)0C8PIMg@I4sk>pMp%5-<0tLpI`&`#6t{`-s2fJ`$kuEgDQ^N zQeYnMuZV6Eii=)J3`D#Y88KTgFaIsAyRtuQn$0;TqQS+ae;D`A(D-SmA6t*?u6j4rgCdO zh!eUI`i~=9c))5b&9&VTP5W~$h~3Ys6teoIMyxJVaLALiD46-SiOqydNxXN&>T*cH zCgFNAOP)2x?^Ah%xfWmr#Zb^iFFZe5@p^pm=Td`RY!)Fr*qfl%?32TgUgZUyhhhqX z8UZYh%!{A!-nm0cR+I5u`fZ@1ADPr@e4-&efc>IODPhSd*s>fubMrOR#nlk#{^q9S zQIK}iVR%5R--ESZ>;qYP6_bxGk9NSZ%rZrKD1|<8nB|k9l2t2CcF^0J2(MFhHko-` zx7YM{y)_cGc>Q~=P1ebc4_jR6TmpWiu|ssZF2g}9vDs=)yI4%wV^TcH`E49@?3?d2 zDgB7OYObD>vVY4t9yryozk<1@=dO(i2v(Gcb%t;9vlSryrm(VM*Ncg8yiq+AN2FxU4R?9>ura-Yiva+_-i6Q@U)GI(2&>LAM&CvwQ27mAThyG zMs04j1eY2D`r@YJ`S&q(f_4{5Xv#9hMi_X!z^zdD3hT{;T#%V`4-q)?xx)Vu5#p^C6K zdn$%bpEPy&r>Q8E=sZ$hJ+h$tsw7-WmmBkZcT8E9cX*)1LkKs66=Q?y3Gjky)A;Ugmk z653!EPu$)bhOjtO&;2T33j({_HjV{RV6|L496OD>b+5E}tderIYhlP2A6>jCn>(z4YZdR0)s zNvPGPoIG@6#)-o&LAkc;_xRzV;rk^1gs)!X%+wj~AbE6B%iFOxk10$g=WDtpl3;j6 zvPV!Tqea@SDU&8UpNc+wep<1Qys>BhB2C0Rel;Taumq7MW)ek7HkWG%Kadcja!cQ7 z)cH<~Q&>~1E2a{yI3R+0TMh28U`H25|jW&2`ALgQXD0_+Bm;&A zG=(Xq5xi0fwG#F7#Fkx@X)2NaGgnX$A|;pIO(iy%gb$9+lw-pfl!X@wVa%c{c-y;m zY#&`|7sn1Ez=2Q4Gp8rhObC^0*r3EyxSp7`-`o6`YwoAF9-}HW_E7g_f##8QhnE*f zD%Pc?R*&+m>^M>imrOQZ$^{%9zNQ*1o+lf3_&J}`c;#J>pQkZ{5-*lQwe2ZQ?f1{G z&OrDr77ai7`j>4|O~IcXt-YO(jF&%TQ9OXVZ=MC!LRNK#ng1vf``RPuD7@L`<5XXL z^{5}YbIFS1;!{+9ld$))F-yh1^E*1@=^Ha8{GmUKe=RwOnY##;8<|Y=@%yfZN=y$3 z8U;6>S8bKEepX_l-fmICA#}tzrOV_E^jITXx$Q!o#kt*ol@PE&ej}(o_n%YKLQGJ! z@{fWleW_vVF5g+902{>lz-cTb_Q5#b*r^dvQQnH{^$Y^gmMLaLJxn@o3ffocr@NQi zJEf8%d+&vvWu3vb0rsq?*G%Mb#d_*4)xLDJ(>%{z5zuDJrgLk)%=PPrs7t5vKI8-) z++i|!)5pos;BN$Ki3-*VIHe2;Tm=IQr(dzT>#8)JulJG(;TqS-S9=?&z$l$V#QKnI z&v)Eq#}L7;tn)wH12vf{yMMMTr~h|Rq|_t_~z)pyB}7|dj)eye?)Ro)v&ZPbJvx&C2qL~jQk;-)hQuj zqs_#7sbs-ZY?^;9n#pPEWRqDiPB#p+_W}}h0>;h_Ept%#%j(VS+aL-s);6A>IQlvI zP_>*^JI}N7N>&51r@x#HbactCJb3C4)??1Vv%K>n5ier}T%U|xtP!~hFI?}>s~$el zS|i*R4Z;B)B-%gO`>Z2yspP*>l2vjRP$rjx7V5ZK{Qs4Lz)CbfoFiPmfg{hx zi#JF4a}8+{$D!5Xb?eemO|3-v2wXN=BoW~9$vB`9+XQK5jl#kq9tIV7Q*umqmZFnZ zV9Y>YdNr9rS7NINK68iIS@!w}aOs3CncV`$T?ZGs<;Cy2t$6gGS$V-F_KDvhh#2|h zU8qOQqauWNcF_JYA)h~goT99_*G@(IRYOV~HFgU6&Wft(6vC(&=Z_{&wy`&!!f;@% zRdX7VJB2%2PU|mChbXtwSeh2XNNW`WuU>NTbG1OV7?bp?ay|?- zvLuTQ1^T$=WmrGB4;rWo7~vnjD-ujMQ#{4g7c(i;uaF~d(Gp55v)VA8KrJ*oU@Juv zI}V=Vx}C-_?_PFNGbR;oaB)1!nc_tR&W;*+(1$T9Xag%9Fq>xrvrx~_t^}=Eo0Qsi zA{lnKp6m{bZK=wwH7EImoWA^Yz+EN=BZexJD$7mEiY5IavwSF|)3kH`Y*of4os+3m z?|`5k)yQsA7gvKskN6?qT#@_kaXuS-9dicrBut1 zcWOxV!ln1e)2LDE-GB;V)pT6~lBVCc@u9t!Ic|%LO|Kztp*nqsV<4+n2rDTt^65@k ziSjF#&SXNZ#@b?uE=q!uf6y6*(G7?H0l2UydECv=vd%RgVAzZi8~xe5{h+SrP#X$}72`mHb|_C_jCQF0;Rx=B7CKyCKM5M3sqHVNB{jwP z$6K80(4@zaz1P{^#9N8A>r8ewLB7?Xd{c;Rr1VTBPYBOES&XJoU()RqS^4@Wk+RFq?ovZ{@18SI@IP9& ziuHgi+IFX^=yJK>8+37I;<0Im7%qyPisJ2~4uaecMg_N`9-0=QYN#^0nP9KmtO-o1 zBTbcK@@<7h%b0(H7VfgjG3$_?M?hO2)JRk5cSSOR!WF(b0^cudR0uMAW`Fel@x8ycyB0 zOF;uZJRO@Xhy88ExT`MC!w7?G<290XJ$sDGa4!}pm{fVf401=hDX~p$9S(L677v}^ zpuWCezYljFGdX4PX0*KKCJ>uCFsA ze$~~~jS0twgK(dODrdOzp41R1FxojygRRl%T7i>Qr?YvV;An|LwWg<)xtjH>Y6W_k z=~h%S3^?guB3gpaF&D-<$c#biDxAV8uj#q|2T*c?XimpaM^R`VQa|83KFWw zfzU7*f8!KT z6@)Vv0gu7PFR8EeL3^@PzwyMlW4_%???^9$3NrK==j7-QH{{rNU<5jrbDi{|zSA^d zSoox&J(gK2hv$OV?zFa&Z31Sfb z6e9G3o=u8+qe{MJ%}y|W&pF``1=vc=N6EPBxEcz4cFJ+bzTL&1Gg9E-C5Q~m1K?kH zz@~jmf-@+usCaM@@Pzw!Vr3~IeoQ6a1>~xQ6|wR^Z(jCxL?4NCqU0o+HaVh{tH#7U zk1-#k??1!P90dEGUr0gd|FWFWT2maE{W`sklFHTIXyQ zC=Ir-^UO%`Ad2#WS(@l9apieP9mLaTnk`ua$L9RhV=GQ>r^ z98z;9YDo#{3+Z-YR9`GiD*px%i6yc9heue)o($Rh#@A;oAI*=>e4B{p`@Hk#J%r5U zTo_j5#@+9YZ0Ys$N=@xo)7X*%cw>HEK!-EpWX!-S|12b2SwJF=0hS2!fD35STw5jn zJN_sm@GUxp;Py~{i1>D#zuWz7fpnpX#~jffs%a+o^`g-t_20q*C{22p#q1A4>owAr zrHN=-&-9u|!KCM~PIxy-Z8Taj6Pvke2C){)G4iSh(2Jfma;G z9>s9)f01~m7w^EH@@m*@ruK;^P345ox60oT?N+~-^8JPSU@z88XejWXF2x`Jlq=t_7AY# z5araIiuLu$a3C*aAMwr1--l{~@+||E zez8Y>dCtCEPT=FY%{T?sirU&zbn2^ixJPoLOr9>lq;Rb0+~0P zWQNkyP4rlQ;#>%9Xx^M2e#e`@{@qz{|cW-X{jv2ii z!!e_Wn)6)eel@lxID4K+Hd+Ej^!zzGq+nftz*k%DCZ@u<$j=*)Hk;LgQsI)nCx~|^tKk~ z^@*pgtIKbC`7_pw^4ja+;98dBxIk3j1BB0%L*%pTa{_2<+w*!9S6aO*?dvObuG`6cm04g`6N*|D%_dgCOdB{_bs zqaZ-k;cH!6`1I_(qdy7f0dCgdm(A$hk=4n?`w2>i$+mco$}WuHF^R(>ev>S~kmsQ< zkZE<`n@aqXxA*XrhRV$Q$6@h0>j;>oFNXMeKFzZ10V(AKWoBgRw&i! zCSVp9MpTp5^u(YMw;4pXAS?gK`~xgLnz*>|u8!?> zkl?>Jx5QGQd%}5@eu40Z(TD15`xGBIelGfhC*gQuCDFDM2lsf!Awe((V`)ansFBCp zcye3brETLJI>i*FulKV7o`>&}rJA<9VHe)%ujiG$MQADt`{H+N*?DcN=jE=Bvnv>Z z!c>o%p$#Ke_}}1SI8H$2+1YpoQ56-)lIG`h-4_yK#&Lq(-WOeD)1T_Y9n+x!|s5S!8cZvFGDu0sLx~0Fb zIt&%|l@quKod8!n3LW7fz5+|9@K!sf=hga@^B~iqgFS6bUcQJmGiARt{ghr@qPdWL zvTKWWVFzJivcC1{pO<}Pf%jHNj=oNIIi6;&ibpwtDfd5iq|SpIU@P0Cy2Sudq#QfA z)O2r)TdleFWwBYTdON6ep(RX|1Nt*}c2n|?=)b|0-Q%>&udFuaH*wAh9y|T1qIvW- zDBC-8MW}Dja6EY(?6hqII5eN+`RJv@T5dYVi^hZ>UI{_nQss){;RXlO1HH&7ve5@K zEV!R|;6=5IN?7olb1pM%(HsaAOd;=pPCqDko=IV!JwskC0`q5b2h~lR&U8+!1%>bdjpfIHpMf^gviF;RL?#;(&#zlDp|?;X zCwLfX#*kELGnFpN9AP!@0z$$)m!b*A}`vuvq}!X)8E=W};t5!99DcF*5P0Q_s`%e{z{yH5`CesrHIaT9@| z9zUncBF@N#_{Brxe1#Q>wJABff>&v{jlT(F`aD4ZVaxm5Rnlch$#UOwO}U&=EyoYi zph3xJ`bGDXbS7R4;fEs=>?!EEY^`TiCI#d$e%qv%Lg!IPVmkVHCm`FinvI zTdqeSZ=>4KIX>E%9P0cDoL`CGnz_SzOL6e8=-n3RY76*0GL0K(kLYeQq@$Ile^oDP zbIMJwP{@&BNv;Z{a;^_)a@|1|UNpJ8wLDq=_^^=$-#7lKVh8dm632B)#dQ^kp89rl z@CyF~sufa2x?h!+)3Ww6Iqu=x-Pk{od=(s|>>T~znyndGj;9aY~-(bJJaf$h!X~-plrKdu0 zBY_yFnC^mLG^5trJ-;IU6Lw}Z{P1~g^6)~~t?9dF!sQ2$c$nr+#J-&r|0)~?=lRri zSm!hi&d?pnPD;#kct4_GHz+6)PXWt$S44o>{_O6$KkdKvLXNKn9Vq8j$4hg!=wIdwNi1}3hVD3T9~njkabY8 zI!Ur$CPE(4kh`Sdy4p63MWPr68gz|(Bu_9+gpF1uhzu-ly7!EQe%Ig9goJgf%Teg;J>->ZATj2K>!YK5(MDJtZr15kb6hF z2uoL`%LLjFq^Bvf{P?0zPBh4FwAh$&T#>{v6DxZirMK@%v(yzWr6$lgIIifhd-wzfIPlNvWqKXIZog%)FN#I%fhnVb!YZjw{#9y@;p&RpNjAk9`E=7>_Y zJrkcz?dJ&xrCxh0FclG)pie7f2Pd4=H=X-e{$usSXZHF3ZAcox=E;;FOi(8^Vo7T^ zH6o1yI(BoxWeiXp`;+tRR^{SY%cpUQ5mx)Zv;}b(1y}w8or~^L$ zKM*TgjM>YWysor{t1%^7di~e0n+UZL-@h2awMSI05!^a-Yd6A{2j}(kX&l!_1(rR@ zH6b!Gmo+(9_S?Ah^yhl!Fph=7cnMIKO^eO2DhEFne{-IFzoBj<5rNA`D*pUtx#A>Q ze11a6E>clG@tvRgy^4nU1F#^pBuH{0tqnfwS~g&OTLc$9QvdilJz#SBypo!F_UVYh zbzvXkhB7pi{f}+uS>|gG&1Ng+`(RtzukaR5ZU<|qr5XKS_9QSs=`=0jp;FYNmDdoO zzGgg+rXcqzF$1*fhpdc`73C!po>N!7@!tZP-W6MqvO6YEH&Ot)2~mhPMk4C&j;mAu zKG9>-fn04$uA(TxU+TLjY&lx4!cZX>=j~*fM{B5&&u5oq_243*BAVI9p5nkrNakSv z!Qh|9u+qF!z;E+kb~ASr%vGeq7=^@l_q_frBIzRcI5JS>13$(+8n{d`*Z#M3yKikl@d))p;a`*cmLq!gkS zFY?F#*4qONgOW~ADNvt8cdd0t(r8D_5%JQ!t1}#AkKcuU>{(h;OwnElzyp%YYKaymi}?t+%OzOk0y3 zi?rT8=GCB8$3w!}vcSI88#k2j09YU%!uWj1XSy7H(T;axrT~9C=3d7^kja9AQ(cI_ z|KB=b-DZ9N-S_V&BUOP65d8tcd5?;EP>B$7F!tx0uCX;#xFwQYlv~KX;P0l-gZ&yi zvNelvuCNc`nxpYtp{&`^!1dI;nTC=5Uqj+*qYTYx}SuNuCliM-nq)KLY z@K$WD^$IT$o^&H~kmo2R-~6oW)aKVUYq4&MT>r!T@YLM;$tF_MU=Xv9{Wq5%KRJZ_ z+LzmX0D|J)4qtzFDE2QTG5KE$Ok(rZil3z#b(8ui4-5-5eh@Yt=RQ68V?Maw{iYkrEVv7q;s95~__c`~tgq|o zdf~s(vc;8!PQcYHnfdbsIlj8w)_1@g>$hs!-uo;!#6udLp|&MefdQ_;7|yI{~Yo{<#<<-PtJI=AZ^c z>i9UTLP0MmxA)V%bN8i9EbBiHDoEQa$+A4c-~djLcK_mli4)Q;Z}ZL%afwoFrWRSB zOm?Nl{3yq8M(yBl6k{BOk#qcC^~y*Ev}sNz9axS9^f+7Q@!5`)Q%Ro}=nM53n;}Tg zZQAHtPGK;4R^TA9uf4S@-ah~nj;Fuv!Yv-dwl?Dn93uAzd*5rXDpod@DIo;7y@EI%%9y+ zvcT5RUDHStIGt##&;|a87z2N8#bUVn}85XSq+)@KHj136Of~vdHnPhkcug{26>gY6X|(=?boG#*R#g$s8mnR{e2w-~v&x zeG&**%vh^^bf_po>BS*^@L@Dp%kVA?U6H;!77mD+ecVjMABv|Jv|9TRGQM!eKM zHm}#)AP{v%HIcl)yf}%gf}1>Wx7vP{XOi|vvp_s?wVo+K{)_Qy@pI%g3}7drN$tY# zK!s!%3Gl#GX2SYr`vY?l*2N8LIYaE%Hk>KgXz<0NhY;c8w}Pu8o5Q!Ci|){0H}P(u zINn)U9yzORwPCCq^UeJ)0vjnVsxm)kXv5ul2GpZND;)OKvz~%2SIW9RLjiW=3T4#z z#{}0f1$c2Qh>Z#LcOKP{gnFb>iWW}MOP|wH=Iv(c=Fc_`ZTe>m2LtP#SX8s$Zvt#& zV))Rk#t#iX6+W?IA-F~gz3}6#onG4G$C-4Ou-`-9_kxdKE87XG|ATEk8X~c%St6dk-K;V zu>D%x8*M0XOSnOdhk*;wV9U3N2~Eh#ADJuKgO$nK;sSp)49O2vgik5w9-F*aWBA+f z@=EQ6`-$ZdUhzMuCS{{v!M`B-KP}jpuXIk{l;Qoie9Ci(gst^;Hh&m~o;)|+Mc|wg z&NVHVAW1|LWaJpa7l6k)N8-BY#0ozpdmxf(aLn8{oP9T=?uo}*QLQ;^?%nS$fhBYl zZJ>~bUGKC_sj}4%s7eEj)kp8oa4T{z?R(XH{rbaM7b7| z%uc>vNA26qtbWE0^f$Z5WrHq^%%4z|YxAT!jp+GkgDPkpI`Z6+O3Y&!4a0txqyP9xRdn!ZtvIIm{S+@ZIYdfM*avdD zO$yt~acm|l4I)O68DSlcv;)u$#wEWZ^8DMQFo%nweE~!V6Rp*(vlVaNl7s(D`_26J zrP8;f6{SVpPG%mH0J`(myR=5Q^c^Kezotjz@MwDVxyav#hV$13%;x`D8M+l{|3+=I zp07VdT^!r`pX0sZM|gHVL@(WW^r&v~)n!vDHJ-0nylecsE-e^cjgZQ;SP^fQ&Mf*^ z9~nA~6^iByMzfj8Qk&V(LLl=4>3GlC-Rm}6kEC{11NWV`^g~8aUZq(p9Q(7I1o)}* zU@fQC%%d*iJu#f`{mamLe1)xv=rD~ZLf*Pf}hy1*Zy52DvCYc~`j;PkO+)|3Wc zky|`FCJ7f?z5lnEK=YqgZ#5!h6<6OMqd~KH#pf_OBXNL<{8T=KIp)SrZk3b+lI9hK zLgnx|l{ullA^reE@*oT_shpnFf~SHrnD_p-kpYMnIyWxI-}*8Lw*>T6iZOnFavJDf z`dW-vTgYXZYjt)5p}@ENGvLGCVd^8Z_zmqB;ce@bDyhc~bZKJZ#AF_C0B&4&pv>T` zM**NJ8KFG!tngjIBWSf9ZFviRwb;Ye0hm&9j(4Q;Dq&|=M>|S$PbNznGR3n0LLf#J zkY=6jkr69~Xs4Gu4X2SsFoI3PX0mH2_Ylhu@^!O+ZR`W_44X2*jz6dgCv9&OLJdRV z#O9y$803+P*nc*$4?~9r@KRJkmUE3J{v1~K(euCkiq9{(|7|r5DUqO((2a2t6yMSQ zq&uKdeE!)dG=g0qt;tR#0udjt>6o zLk(`=CrwOO{mFO${j9+TeYp1I2S>gK~dPn2B^K%w(;xsfa<#vyr*^*9$I8lfZfv5w( z0r7rld)YhC{(c3;W%NZ~Q#v^<*XlZRwwj)ZJddR2ZxAjxwT)yVPQX3Z0Pu zYi=&QAR9Dku21YK2;_b?<=gJ93zI&S|2N#O@7$<)nV*6%S=Z=jvTo8L*EUx`T!Mgt z^oI0sfSlg|Iv{6|WjnR?$ZnCku2svSgaLexmyA$bO$stMR~qU6DVu4Lpr2DqOO;@7 zG-eGyw_3H?FA9?@8uH6S9ve#;WWO)V1LnLkuanCWltI7O`D!}9Dx8Q!M;#PO6TZ$B zJdCB^L30N+Y$r;s+59%F#N3w~NC!VEiv>5JGA$N6=ku6nXFbafnjl&;#f4`bCaB!Z zv$_3r$0BYBUgmN#%v)9~#C5FQ%W~_YdQ1Krxm<*j#BAnQ=<#36ZRG*9Udd##a*z-- z;8K$iib4#gEf6+)t=JzG8%@&F>)a$9NGo&uN=F}gc*_wMs*yBQ96v6|m#_j`Cd+ZC zwjgkmSs4;qcNiB?nCZM{GF=MM`7VO4?yrIq=Uc&V%aFc0Y_U&^tSN!9N|%L*FzMh} z>m)Gj8>lAg#Utasn<=}BXv0kLjYgERM=i4OAZ%sIB8cNuxxMDT>hGJwtDT)fw*^mWD}7bPz(+g|K; z*^M+${ttHsCt$<*)`(VpDA=WNh13q#=%uB!nAlZd*ZG%@)6X zX(S=-DY1(UcysgwJwgl_NcwT4ETV_*)tWJS+U!t9_HKX483Dn{OF4r%yYuFy0K9>2 z?UoTWFlP|9Yc0AUgH`fS23=}VXY*%&I7Ae>S8Jy~&aPDQQ?05@4v?mnF9W3@BAC3d zu~Iilhy_)+)HXc!=FWf9Ma7l{|2Qfrn7%HKTMP^A8o?~m`$Wro=*%@C7xS+5n-<(8C-$J$!35%vJfeM}m zehN&efA*gV!#L7c;knYb_vKZs}7qD zWlN5pXS0`IV4$66OebQ5qB6NjWB#jBMPxt-D0UuGkm7XExfDcPK4=`JZ)wPnP&1_D(^T=q?HJ4aFV46m`YdjKdqwycx7De>amAyJZJY)W{#JDQ zU(n)MaD^?3?3=B_r0ljMlU75m@z%L0@UP1BYnj_m{O%h$NDUW^m2#?8Xo(XpyPf@^ zEKH5vfwVeQcf5D-!ns-8W30G{b;u#nsvEPy1rb|XU>haV3p`JlLYbYNgrk_wDZcz6 zFAv<~wU%$c)qf}8^nTln04x-ny2pFI)7a+)KU8w;OT9PhuNG}aO#M~Ir|C&C+Qc`s ze){`of1zA$tCzb8QjfbFD8GIh)7o4&lrSz0hw)y9#(xqK$w<37CL7F2!YBn2-nTW^ zD!I0IqSs?kV;*$oU_!+2lNQ!Q3bQqgYO*W1kNdd!}Xa(bTF;?Wd$KoIq8d#Ye7v~?k&0eg zoE&-_#d8&VtfX%9a%@hoi^z$6GXvCtlb&0tGtd$&jr5R-2`1hcFq1xwo}r!riOcs* zJ)1)Rl_WH&q$aHwW`Wka5HeFwPCI?Kxtj(Ke%6tg zdXl2Y-mO(o)kmAYy!z!ivM+AO;v-e+FV3s{iA=3{QE@W@D*|rG(VbN;vdl1$b`Lo{ zGnwWD%%qM52jFOO5mT%vL^6Qmd9^eIMcd)@t3FbG+WOaMNEkF&9!b7SYEbXFVOgUU zH!k5RK0>3ya0HsyNy$gqH-8Bid7;{OrD7l5rM}4yZclQ_rX@7|Z9FC#lhEo-1GKD? zN{~?B`R&89#Q_Hgl;L)KNruzxZxXJ4v(dUp6{oKn=mj@2RmWVx0N7$WYC5AquEv`e z-$?-r10{yQUMP0lQ`t*+#B%O@UF|YQyIuYGDm*MpJi{LzNKaVZQ8uN6$S5a+hrVC$ z14rB^rn|tb;Lda-pZME*eb#ysA6B!49#0 zGpo|>M*5TRW(RvnkSo&lPjD1={B2=ZFt&xHcAS?^s=9VsOIFRpHx!es&G4);`Tx*# z4%~G;ZyVkxcG4Ja%*Hkw+qP}_>0MABQ7e3C2{NggUPbTv4 znk?K3txlAcHI@gSetsn9>S+s;$^>_cZ_{V;wc}68duA<`_!AeHJ8v6aZlYthr%#Ko z->hwM@{DfR?LI14vwjj1f>J^|ne#x~{J(E7 zSE(!FAz(^y5D6z&sfhtaNRA&2a?X2cvW!+t?zeFzMQ5fntOZpq+W%<*97g;vQ`=HC zJgxGnKCn~0+vjbObCXgN4gzzgF(ls^0IfVybj;tH%Hi1e7%n_Fz~u|B?jK_P9ui&GMb?dRH^t9R8?3 z=RER=X1WIri+*1CIYBY@t}M7X89%7!m_`rl_<->G7i;+k;d8Pf-Nl+hDdP$dSNkg3MEZ6t^Ga(|w=l3ijhm|LGD~S#=U7kXvV-WTV@C_Z8o%q+V zhT1XFI(d+~m?xz4m!cB&TBcLRyQwQ32^cQ+n3g_Meib*F^x+`djgp+wzjS_qRDP>s zTa%zBhhH}$Exdz{G44rXcYv-ydL_LZbDIW<>ucOb)s{h=6wdF_92!Gn`|J@S6eOs=mom+4paKB6W(o8IiV zV5ic8xepsABQLTXiNAjGV`rPt0n;X}*pEJ)ek@k^o@DctM|X-y?2%$ma?!3$crXIt z&DOGtw!+uLG-7@hRlI6goqa1o++Ww#gBzXdZxcEk^QR&<8{SaKrSmy?doO;Cox zP+TXgx`@5*c_u3tm-lj@Cdq8H5ruTT2qR_35@5S$pF6;)T)igwnougg6{PlD2XU;l zI!qtL8JJ-=vdD=Zw+_b|&tzAKURzpP(`J#IgxFtr4evZ)LGZ;fI>pC?Mms1%LR-;-UWL4kKBUwAYwU5_8 zVuTiyBgx!w+Sf9sBHcP-PcAU1;c3bFay6NaN&@uuOPkLNA9U_t-FKO~vSE(G zg23%hc!1{JYoB}A?1w0g-F5GNzeGz2(W^$0b!k+u80?o4i_X`NvfwLk(rC!de#g-hTwFMPUsF|A%iip~(j15G6CD@h!CgosGJU{*K7Z>tDT;dKRPwS*YqgpY*OwjC> zHryVPa~6h8Oxp&rLkZj*@1D3{fIzo1pBCP6I_Z_D1W#bMa5Xi4$Q{q zi#acJaMHpxlJdceO66RDuh`R{d_Yw)t~qRucip=4v{Fk9HxG(V@W!4)|25bb%Uu0A zfu&zciKzpE?w7d|5EG1bPZ~!Ewj`|>rLtvY!E=eysOMT>fm4Pn z$xXA?@@kL&Z*2@o>=E)&>nsLGt)SoE7<LMyQItcQW0U!XPLxva@K&;fCC=Z?Ve0y+(7s*U2J>K?UkAIKVn`rP^FMx~=F^4U z&IibYa`pQvuspO-Ckn=I6N8v{$@F|1Bz|1>`Wr5KFV4l=V~$(75F|a9zGmD;ki|yw zGR&AwGM>d*^_`8o1}~&1TWa!ETVv-$`!q4%_weydC z%HiFp6BE_s`S0LsBXpEu=9LjNQ_|=nu zB*+fb)r!Pt3A>F#Pfk=b!xq6GmipZr+e0K#mi&7jvpKXt6Zg^nnw`B%O$PSQ99xId zpQ+Y}*s)I?16pPui$bI>$5tvS9)?{jTq}km0I3ks^huiXS%pT#Mjit5p ztP*<%Yl*#z5_sDmoW8a18)%x5)F-P2{Md3yxbYpn>3F)udia125Tmpnd5f(8hWEZ_=g@iH)jp>K$pei72q0j=Y4H0UMzXC`{SC zr42T61(O4Nmr)19?XEQ`vVjL9;)Z+}u0`k>QZL?Qk&n$ZkCXAX9Hiw)_OLr;Uh8*w zWeoDasCkhYjYZeb5N&zVyFk`+)hF{j=;=Sdu*%8SS#FUMeXx1f6g&OY10ST&BE49! zIFr+V-*i0TQjIz~>W^;vb!4Uuc>TkV?6}7q8Fmt-N~HSO{vWN^~cZQ95Jrwy%=_ z^QWapo8TEoq{>r+#S^FJR?4dK)w2veENblK9y?#9HRGFi>s`8tjrUqHrsW|APsx)#-v=HwWLzRIpoB zhWoLo=Vv6>+nsI^cd<)**tVDp>m}{QtbQ*q7gZ9=;Fw-#cI@13L>|w%a{2<^o}v71 zJhpMOHz#eBEI?~4_TFWk z5CrT0vrs(gSZ*fvXZ}GxOY(171lsBWVc(}{2Hr~~C_RLnILObJV`YRZ-zv2aN!vF-J&8;k1xsGEvL1*=6 zjw6ZtDhQ%QU;D-*Q+kgL8rSJcS-YdcCrUQz&}wrCg^x>m4>aG7)3;1|P-sEmk>K-W zwy>j-K6E6EChTunD-6Adc_vOlI3Kd`qdH*jT>QS)4GkzaWT;!wx*slhf|mn2qrx<` z^}Z+6VPHWletrqWbuYuUM_B{JXg@q0)HM|F9B^IJyVCv9Y~q{^ z2FxyMNSR|GHC0Okl=(MHB*3Ur{EWV#*)HfSUFi z9R8f(Qt0)=e7}hw87qU`{h^zya$%xzeE6are$1fEc8b)PRHyWX7TuiE5l`$qgF?-s zkho|dS+#+e+U0jBD~ITJa4XPzW3m@){jVc=QSMHGt^W8(#x{UD*`bb*jz@VedM>PO zU;Wyymb=kZZas@MT1=uKsYY8o#!fiyU16b#SNO`v%m)jMPJxorC+J6|gcVd+vwf^=x)e&mK9Zv2Xe3ET;k@>#};kT z?J}?No%SHXQhHi|mXRXTUeQo}c*|MV2{|vR?y#ZPG|}P%Oz=WVFqOXUw}L0X(~(u$ z+7K&7(+9Q3^&c?X%0qK_)nQ%SlIovsnWblX2EykY&;XTAxW2*eAD8t{_2XgV!+k%) zqgbd46C06)s9cN$Hx4t8>%PCRM>aU6D6)Qek1Ly*TkdnNFtSqb_>M$j^J5@Xci>|s zSFr6orX`JTxqIF?Xf~v>*^&YKhQakQp1tQZG=*O?hEdZPS6mgeFN5W%<4CGw_S2=LS*E0x+AtYO3 z(6vu+_J8+oHg51IlmA?mUMJEhKIXL$RFjQmeV#Y7)q+I*E`>yyqq%ja;>Y~{;oOdl zpinkdbL>(!g6U6d_}(Z*aplpkXw+4oWz8H~n%k?|76kwKaD#w>X@8Dnx?-glpYwbn9Mk_Kl+YF~N(&R-TOa1;+dP}U2J)nD zIS1YJd_(9J2W^Wh!eWoheEV$BS@Sv~>yDtC3c4RDR!l!UAK_jIQg*(*HfB0p{|&mf zm|#psh$j5w?#E+v7C)dtwa-w+#c5CFR5j<|GCabq@Nx~SdXquwTKxe_SllVx`i_5A zOK=RHq-)avq^ehY$IVI~4pJ!eXluyX-Z;f90C%>6^O?FGYcV?QiTD*1 z3Vf_3-TU@~!M3R*7Z~nq^!;qMA^+q9;4H zT_=(z2)JOxFdXT`w5cj_3)2bMFA`ZF8g0XQ?Lf5OZWxPfN}_u0qymhL;ka2h~QRgg#OVKr!JxC^Nw7BWi02X zxZ{<3-rm`9)4GS!ed)7x}TCnz;v}I8b9i12VrUEmFyQ9_^fMKk@jaOH; zz}S6@_#7MfH9Q)@Q{tFV_U{?oa!@(HXY*udH13{b1wb7CrXGIJ9FuSD9(k4j>k2Uq&);3k^m?TBdk6nOxHZwd`)jhASrNFZuEnh`W(fq4N|~iA zlOG`U&nB=7bBlUo)ZaU#%5=SO&jcA)U~HQT6p2#w{T-V_X6eF;J}qa~j@GLavU4|bCXj_a%IEGX1zheUJ%Z~AF!0< zjyEV5{?jK9x?WbJ%dmg)F7y3`TD+8)isU`f!fZtqql>=`2UdF2{al*SKn%Mmk)G7P zCgdl2`j(|+ai!orbaFi6c9#i&nOj;K-#))`6PtRFU+k<_>7|E%x|J(&N&jdEB3Ijuk4VS#i>Cz;hwo z1tWOmw;3u37kQI7#b+#ltp{Y}WBQ!(lm`PRUrnSPX9ZOT&;|q0v)iu8?8H(Q7<<() zgtP&y1OqdOVGJrc=ez|W!Ga%TLWCvIVSR>WpJq><48Bat8)=+bFm~ww3F&-^d4;{Y zz&)WpOzu#}BQxZ+?xaY5wHYxtI;YM*H^K&-G1tul zo0%2I9w>NQv8W%I;q;#p?=RsNgj?9;<;?!sd60(GBKPYxMack(fQ2@e$J^n~EeIM~ znZ!fxpyX4{`I61bGBG1ykbFOS!1W5Gw`~!(RBP zt3i``V-vS{4KWY(baRz-WT9x>*^NhivW`pPZH?zQ*=H381|4p{kdLq*kRd9i{?lC= zFnXZ$x6(6M7h^KOmsqoiLY($WXw4FZo=Pv5m!DJd%Z!1JW$TT+LO9{8hj#B^KN@U0 zALkz{S5`v$V~pKy@3v%Cj)BsyQd_dFN7?V0bI49fGvD;3k6JmjlPUHK{cu_u{-)~y z*}dxN+UU$eiK{YHrk0QeGFrbv>hZ*d_4Kury!Ds`M2;gR#A)ppDs%ZONau|7K|0;V zHIDYiov$G%miU*=vp{b$@vpbehSz{MeUMnRIOk3BrYV4h z3s2sUXm_ihP9gK1c6j;O+xCbjvXfhH0WHMXv{RN&^$0+2w=;0*nkcUuqPrfC(9M`S zy;4LM1uV4j%OHBytgAw%=I~pNTz+D;=OaFs6gCOVk8s!(;`(1<{B{`IFu1dC|LM0J z$Hm`rJzGY7-7y`6E|rCDIQdBzGlLWBEDww))*$v7R8qTCOUW)q%NPd2N2#EQSgb~0 zvSrgv?I`3?!0JnlzUddVo2wn(T(h_!KN06bFoY5w_@{h+X2&PYoTMjN-4Fw9z8gS3 zeguu0tXA3Gz}%|p{mMo&xBCs^{^Wfn&1y}bfZS8K^^ML}y7xP%ggm;IviAwDB}RVc zOO+Zbw&IjhoJ9`osIOzdxNP<(gX8w?!#7_mTB3?YQVSPM@akwkK+Mp9kuSkz0Q0p) z8|6qgVsd4prMz-1qcHfhdt;<+>2EYrdP>Sp2ZR1fm}#bEp>okPQ`33U^dB#0SqY!* zeBryi@x&MrnBlV;NEn$@mr7@P&cfJ8cDJySmMZBeSZy8SMY(u!I80(3mtb5*{ zDf212Z@+kLX`?t$DAI2D2!0DCFL0-z$;B6*3lGiA*0hZG$IPBrO0e}8T&vWjoZgJT zu*1bNF%F912E?FU%J>9Le4UZ66rx*oy4Pnsl~cAjEFua9C5EGXS_7${885o7rDWN9 zdPk+4sIol4=w~VLC>vz4Ux3x0Z=Ubx=;nTTaJD6VO&M}P1XL*9*xYn0qE{qmUBO(i z$kYOl#vVOWY1HV2OIpNPuC)Mr?^DxGq~afCOHi0^H}cp}%apY^U7Gx+X6);j?cq)@Y{u=JNOZ<7ws2gU8eu z{O^HdpF4!$t0ec5!#4> zd`^0up$sohnqHqe;_<3{>3|xORxOh+?ZQTMF54nRJYUu#FDeiSUyC92aH8$`xDQ#Y zLtil~Jf*{}?RH$KzX?w)7VFh6JBFc|-hiMtOY*^Z&Bf`eFqX!`J7$uIY6f+m8M}0Pp!J8KZq23qySm2pyZCxWQ_sYt zH=Z4Z#VD2+TwCJylp@`yl0EM#+A_s0w%;No7D0jt**k^aSLD&qdv!R-e7aPoaB$&_|5FhE#)aKOEH zYJN5A&GDVW@%3B_I;~Xr6MEp(Px>o=Kck=Eza%R27Ga*RUZ*ZoFTcLOViTUP@4X== zAy}=u1YtQ@r#qR^97}K0i*BdIa}Q!qWe?dFCB>#=lV#l9y8bj#|CI*%LWp zd^(h^19ZH1j1V!>l7{L`7c2FC27WS5x2EdzR4Opp!(^As=xh=ww67NK<%%cE;tpMA z{;0R&RC8fmje9(e0!WL9I=;)pK+22w%H2Q-ZT3{YhxgS+e(?M%F4K50?;DM@BcM7* zfCEdq;TeSK-Wf%iX5)Q}yo|RERgR$1DOe=&)`wz@yJK@>e*SLFULDU&up8^_A9l6h z()(?c67@+Az4^ZeZ}@I&pQ)>c9Nr28QI}48Pwtc|=Oma1A(pQ~G||bXAu*@ZaCNg* z3-iRLjA6n%%zwa9+d;29Q>DnMH((&&<`g66h1tD|J%X=Gfc+>H)H`4*L_K9)LZbM7 znEAvd#NyUt+aLyXMpd0r)}LfIoXiB-%ys2~J<@QxD`c)rzEbtqqZ4WZ5hs0QDHvL%ynf~rg|G9ZGU5=kU{-5OWKbg;YOLg3KU3C^eOe+ z+pqni1(}nW&c9b4LRu@7!tcKQ&h~MO7Kj}gY0JKwTuJA)>*=C!cvpcLN6W#){-6il zx4AqcOqLqrjISysn=K^0Y`vzR*%GN^i=F!kg+n!7wT+jrx{OZ)S)2Bt5Y;+5>5mP}Z|L`$a2k>7QI7I*wyvs>OLOnN+&~_z}ucMwSlds#8UQC<} zbdBGwe_29_a38rW<6Xn%JKp=912=keChYOMZl^(yTlWh&jo1Nv|5I;8gtm^osEhEM z@9lf=M3(^+sa{86Mtt;@Sp6pD;3J~{b~Y)tM)NyZhSx*hOA zXgLf4`#`^hM1Ers`dTB)Xu`ZWV+^1!#(Zr7H#4_{4os?jY-roH>r>1#RHcBRA9^@? zft|1#LG>-fWsEJo;6g<=j;}q6%LZ!brRZGV1{q%1k}WYw1ED2|gww@LKmJ6RA$$gJ7SUAnsKQsjQh z;d!m}X|x08!bepKN$W)&D&d@Bz}Gb~Yj>gdcgU;Jb$%q<6}tJAaNvn^*;Zwaa32NG ziNgJNlbwmP^kQ+RHXVui?=TqzPeT0UT61sZeqkK({LSZ;QX@H!qJ&?qu{a^xWsBd-?--^Y*wLutyr zSn!%5N5B3iG2BRAd#nyTJq{BdldD7cv4v(;dg1|BvW3DU2@Ecd`z7QXEc|HR*4x&Y zw2(3k`nf3Y3`H72Ck9nn({PxB8Vj|Bbzdgl+V#AGl@|XvVoW9~P2D=R><>iyvhLHoFOw*7=yeQ%xL@m|Z}D z+eR&VHhJezc4$Rc>SW;BS}AOd9`w>(bhBL^Qz6@tr$OhQv}m-qt1CnqY?6zmyT zt#7I)k|%3;TE#u_*pW{$RcJS*yMZBlQ-z-8S^?OfC12V%elANi` zty24<(zPPz1n&>s2Se5W%uWYnhB`YX$nOvyTz-9;kz9Pw6RI>T;&hceN;dIi?cqx) zU6Ei`lNY#FrQl9(Iv>2vUJI<6)pSXLU%cJkvG+`4vsYkY;+#HxI^d6Dh`Oe06M18=yoPHKYg*m-*TPk{B40>~f%*NcjZkVu^ zcG9$~O_N2wHP#T@lKpx0USuM}m7t#);X3;7;}c*3xC`zQU(U7WEART3n%qL0htr9J zECr@ukH*J&>+AN3gP7BJR;HoDv@~37w(cdWyfxCWxT!PJJm^Erl>-y5BD&t zRTAFg%OW~9b&a$UP)&bq|F`dZ^`*_SiA6n*qD`X1hD)k=VE&R7@?}|UeJ>JrF*lx^ zws9@ZGSfkEo>na)f!1c%fX?HfEJ;g;$9?R7OOi%7=DDMuK&e2b1XDVhfv- zO8(usGKqB8LUTu3u_8Oz({RvIlj3)KD*nGmr-=) z!PsYx&RoV&j=eutkL8iE)k5PzvbLwRaL2vBp12Okn78=>f{wTxTmGab3F8DhgA`nB zHqx9v|0=UOr5&dVuJgzrV8zC8E4;R>Yg+K1pT{L?q^7Ot1$zKL3Qp{J9-JNo=x(NV z`?TN9^B~Z=i6;0Ri3*{5;zDOdFUT=W-R);x$5WmT3b%ol{36|wk1Eh57{s@NLGVCc zyZ~6QM+yRk(Lb^Sf&P!@E-ZP6qEO2YeNxD#_4WN2w_Zkk8EL4v7P1|)jR)*8bwS;8 zT_wQr(BdT~&ojaDtK%IL5_YKmfz5ndu7(&&e}Epjz#UtN4wj0Ut(B?Wu|N}TXO)>DMZYmd5^2IY@QwjR`OYN;46_!Uw|G@rEDn7jEg9S@vKp9}APYMDk#prSo> zd;ISI?GPFd1LP{(kh?gSUj@1}KF-k;L6))qZRx+gKJY9lqtQFo32Zl}A%dqAJNr;x zZ!1)o$+qM6ljnQLjM(xMw>cGJ9xlF*rTrQtfS-$fIWlzzJHMNWCFEN8Bl%ODuJ9J>)b&4$)7?zkJSS$+f7_=XPB`Ats5Wjtgo~7E527~ z)nLERbdi!ofc>ykFUdCU z4`ZJJeNEMNi28rVJM*pAXL6V4*4G;}hTp3i_k_JPZD|pH@(+Mj{+f%8d@`U=MFnu) zN(&)trol{4I<*pzYJ0ISqhZkc=E5xNY7;=z#2q?Y%!KQR`tPU?o5CgmuP>T$@UaQ~ zP^~S`qBk3+LlF7`-pty7yOo)UmGw5~))5_+e(r~953sGBc5$e%iMpRKIQE!tJ>l$x z*cU+$1rstC@HfBQ>NBRdw_Lh3HgAJ!ij6}&#!D{fAcOn3mGA$oG8KmbTf9=bIh7Qen4RuiIe`4h zy{QZk+chmZyDUvZzDbtbephN)y{*OxC2A1<{}Sd0WwNKzT5>kOR(o51P(2I%1x~B5K~S`eA~$=W-BIw0=e1>)hB>+1%6~9x2@Z5pCIz5$T+V3u!jI4=_<&Ge;R(9uO}>9S!nm>ES4><|XM8^@rbwCr(SGmu(?ARhKvP)7=+92b zga!KpEr^2XVX=oq?Y>`&XLjw8)(F$0J`6Yq0e1n+!iPecq)Q0wK|_D7ds;g=8#ZiN zBc^LqcNh7tDRkNpHEJN9D8MzHN+!yC!WMMU3ZRbZgt|E-WOlxcZ_ZZ#dAM5Ki zX3NYqTLW{0_UeZG9li@rV*|kgC&F0zlEBt?LRBDeC;Q0&Dfm1_xK*#h`|I*SPZiR( zyY{)I)q%5-dF1W=We_}n3SqgksYah{wWHTGU&r~6m^>b?%kALp_O0K?E&mKL_5_H784m#R)+SyV zQw;j^uHT4W|v6mu0B*$ZG8)(z5Tu< zni)2<*?sdKsDQ|^1ka)zNO&hNpRytH>R--%6Q3}H`MemMDl!D#Gg^Ljb&36mwi}Xu zOfoBb;Ibd-kC%Y(ts3Pi_4)LzCHZ{XK|+hyjAl_!hU zg(swLXjzo*#qA+^UNukTWYDL|E^44Qcr@=@+NLJL2Dz{SSUz_|!+Rb)2-uY%@De z3HN$`d3(MwpKD^Hkom25bFJ2=<|5UK;1tc?^W|PpIZvT)PuM2Nk&)o!b)}vc81{OH zN%b>#Fhr)fms1kL&BliOdN({q9tpKXqjw&7gP2mZ^>nYiK>vOKD=};ZnW{=<`Wkf0 zsClq0j@{|KnvK0G?e>(M3huma{VnWCXB0$PK(X%r*@SqGZfdGNpn}bAplwlu7lGJV zIrjjwlucwh|DkI{9!N)nBV^!Wg>hsVHw5c~q7v;&{o2db{7J*U8V{7f5QThv@?gry zR>8w>_T9b{(>7=%ZWn0U6XWR)5I~=RLeL-JjqV7gAk^ho8LSbw9Z**>d*HNnbUH+PTEhqBT(=x+p2(DQYl$FJ2IbZ9@SIwXlPs*@~^A@sHynlVql<~ zA1wbhxu~^na%g`cdjkghbhN4*Lect3VrwxpNu*F(<10Cf7sb?XeQ^crSmKXV{YM67}MTFp$Zb;~V`6 zxa$?HO`yp%VbDpaTHonQ@lF!YGA{2=0pg=pwm+6^?^<}d z^1Nt8iFOQF^F0Zj*e%>ys{K^APFI|HflEr4tD_JEMQ!-YGiHRUa@brYf}4LE?QHK@ zW1q>QcYpKY{(D3!f*2o^DnSNbuweBMhM>k_y;);)ejbmhZ@cd0Q3MV7LX-xFc>Zfu zS&WKzqyZqY@wN=xlEviJkjQy&tshEv>iqUp)`q(^-z4xp$C0akt&n23EQ~TRBrCzJ z1?@_}S5qfvNu5^dKo%SuR{^2bP%!6<&t`j03QWNM55}=51t~}>zvO>ehQPbgq>H1( z#ED0A!|~1C|Hbj~UT|#tv^A}u)aA?^*uP6VL9~@^~ku@bh=vyAfI{7gbA>H zL>}^#(da9p1TXilFnR>=knmOFNe&O!uQQ7gblphuIp~LOnXUrH%cX65fJbfW!$GC;^fv# z(Gl_t*)IR=`#dC9gS^m__NOPPpQbeG9<3f>Kw`M)T|}`vyb3lm+?Ja(g^ISFCjK*n)V+b6HQbzZt_{C+?Z5ea-|ZYzOSpX4yb}*P794ZvX_g9mYGvCV z>w|A5%s*gz4dWWTEk{a{d!Ua`o+G2^gOUgVO*cr912zj7;G6l5y&|t$({2P!k)3XA7N zbo4>`Yf<1C{X4ykHydtf-DUkpoAq|j18LFtGsTld#@x5B((2X&^CUP%L0z{i=#~gy z5!_3b&|CohF;~Zth((hXw_eByMZw@Oksf;{RRxsjph6&edZ5i@$|iHlrUkDzi=BmB z{S2x$%c;leWZb*l92yPBT-;|AOUGsWk~f+5 zpT?7YFdC5+WMX+I?Dp(iNNl{a3_E6!F{@Y@mH;=V6=eRoUA(UEvfgMSVXxvzXykb*ndmh2 zjRXpB{wKZERQ7bR#eCoMv&p!-bLGYNxc_B=BjGg!y4VeOVs2qB`6<+op6GPc**)Yy zqE5oB$F)<-dCem~W7S-XhDXmgYvStulTd-Y_oR#YtZ9K-L%+C67O#{x^GGmGCT{iR z_(xuTV5jKy++C-WHhD+n$W(MUIA^`+B{MbLgiJ87%e~N*4_bc9j|?RNeD4gTBA`fn z6Q+5{R4d`-Rtw=}4m(0@{4cOS?K7wZmDuhRLmn@M5_j;5e5&a|^@a^`pM?HMM-|%i z_v6M^Lz!mKL(rH~*+=Xk69+X#+&rSEv&OFWtmhEhd#s|{Jf18_-FrxIz@aFU)-Rbf zpXVEn=evNhh&$fztLHt;z7VJq=_rrDxG?Z!%o{@HS}Ebv3$}hH!gF0C zSoOzOMo>*vDN+qeEpb`grg3b_r%_7cMn0+DjB^q?>xgs&);DOTBXA^+uA}Cuz6Je) zqaA5XtI-Rmgr?@uxE4$^;sNMlH;*8q-*KJ!@GjO)SP#RHb@YVZ8qt$=JmqYD~b84nf4jqy+4nqn^cO z>)PWc0Squ|tOu8fx})yJ5WN7X4mjm?;Lg8HzV(aQD3kf!nS1YG2 z^iR#&%6Moc?4`ZjFcK~kk3}V6Bj9ir5lxs85dl&DI=8@wTqw*Lo%W(6sRg;pH z)0>9&s^a4T>De>~p8#gPdFKc|3m}KDz-WXfVxYw_;!B?x!4Fxdl@6{q!v*tQqkh{LZ>C9B+s17k_&1e%L=&evRHVYJjr!BfLoA=Y7AARR9O-W6r&oHl?xfp z*D8owiu67aK3a4lmZ7Jf{?6Hmbf6+seV1P!E&u3YR96)`N!6Bcbws^?KltylO$`5i z^0X*1nS*#)kby-a%XgIRPtfCTc~(ca=+@vXq#g^VXO&dc1Y4{UR{kWJQ0!#uBiKAN z7U?6Jtxf;OSGtVfwz5+QJOOJwE|o`lWe?2zE}z=5UsPB^uVTg!Nh9B8rY{V_1@T`M zHlGT{V8OS@A{?%~v-j2Yu~W>xcg59dTV$+rHe0%HmL^6GaPa?Zx@mw!MVp($J3O4L z}rejw9hkQzo~C z?ryHcZBTip6+poO*jBJfdhUv>o?C;ci+T)|x$6yQAdQ_f5XPvtE!{$h;27EK=~%|) z3mzC9;Oy7YEp<^@4Jk3n%JpXL4M#VtzvQ7EysP3S9A4Eh|Is2TtU(1Ih*&ROMUk?a zmCUoTwWXMRofqqFq{CAPulJQ2#=8`3Mf;RcnI$ zjJOhA;|U09s1wF})kCxt-Ih@hHH`q#!fHL$Qs(DMqdhEQTfNyL3rB*q;L?k11Uj2H zMFzhp&i=X6a%wl_1kpUbytLT+1t`qv9JxHwoRVgVc>OSN8p%_O&zlj=AZsTnf2>-E zphDN^F#LL|ayJ<^7xEYekPqaT^=n-wl46+-gV9OXg+HV~@Qs}r(B_k5~?nu+x+hF?1+rTJgqhK~kh6mA@@1HBIw zb3Ha$6I-lH*O<_t>tW9Q?eyXDbbl)>)Fk#0c9Y2VQzLQ}-A|lXa4mDwCvHt{f)Wfi zoD;R_JO%2w_j$131r*I!opVS#jcTx6o5bk z?|lihAbI7UGzuvv&;k)QOT_0!U>1vehRm5uDcRXwjxGX6IdK@2n)C*>yj8vv^&C$L znKM|CrEt;TNXqTY>6Rwn&q31PC7O!)@WJy)z=-_W^k#9)Emh$-?TS_HUTiDr(vp?X zRG_TR_^(4AlY&4xxQrMd-bS$dL+XScY{CV$bvg~FS-soIZzC#+WzCL!5}%hsdRhbL zE?n5R4GbL1oGVD3PgUY;uq#KkY45vE9lV?b~3ltm)`r2DFD676i)=mzClwy074? z@JcZg%#UF|!w&;PP=Q;ekh*Hp6Rj;n${B)|AX6Tnw5Q-<-PMk1v_cGe0b&u#vp-QOPoHn()Yb92^>$27i27LcWG!1RD0x zQbwm85|VyDmSeUlUi{?3EV{-I zSVSmyd}pl=wZ-zpB(WehDJh3~{$BmN6>-+qP5hvrvwE)*|6jOmf2(A?`!dFDsH9WQ z2AyotF?x#cgay~dUEr;6t#q3eKc-$WKIt4m{>dBzhE1Eahfo}mIjWs#bgK4w8jmWMK;Y4Myv9eEiXo?>-Z3^EMSp6? zUwinrUq@avk96QK8wo%_JMb+)C$^i{-Gtv)%D&>QTAN(KqB+v9V+A!%l~PM8_r#JQ zF~W?x?b}2`<^Qw*6$*Xr%tWsSB)z$+gsPyR`CF^x{PXob9MWIZ&i_Z#S+GUHb!~eF zhE6Hzkd~WJX%L1k2|+@T5D*FJ&KX)lL6DH{PU##%TDp7alI~&R4{PGxuo>*tr`j}M4mjjE~zOzVfk)&f{d3~-%HVE=R52c2u| z-=sVOUr%+;&gyn5XGHJLY4{Iyt}ypDmm|lCkl*dSQbgL;TpdSXwxQWD1_=piH0l3)kY@&{r5AN2g`$azZos58yM+Xl*@mcTt@mYd6C2DIgo z+*NO->y=@nYonr^rB?Hr!=K>4Qow}x-2$g;RR`AlS0i|LrsCVkA%j{(OC@GJvh6mv zAv8~x4pR4O^K0*LRlk|E&><#KZ&$?+W53L!G2weriNlRPsuLjGS@dZms*bJUpB+;) zVYhNiD5+i=R^Cvg*U*`G|0Asqr#{;1L2j`F0Yb)?0cJXFR-EU9cu$J4K^-}i1b?vf zv%xKxj#chr9v%^iAvm{To!HNDCRSx5OVT38(H91&J%+Xae_#RdxMYnEn*h~Q8j6a& zkf89aGr{CLG%VQzEtu^6kk1(aag^G)&Q7_#PaoaQPJTOusbj>{w;wvwWZdytbO|;U z=!6^Jgq4%3vgwq6vwLNkcvI{UAG=M3;=8S0UzQrF)^eLo1KjCw12=zLvWM?W3^$uQ zUr4tbpr5}Bc=ui}A}9HQkImwwy1DvQ!S{7@G&tRqwwa3g1FL~?*;uK7@%e(JP|-&H zfgn&@YdgBTcs4Fea9vExnRf!VTuGasH#7G~@0W28a_%tFO?yhtfX{lRsTQCF89|)} z%RDDGN`zH=fQ;2pOU&eB6~MKU}RIg1)%r$7iwsq z@`mb3Az%5}=A6lWXDv*$=UeDJllS$VfflU#<4oP2>%SPlFx zoc?Qd_zJ>FTk?wy;Nvd^Q{FA6mmfmnV;>T%uXw>=En!L@yFNLxiR1Sl3q(K6xL(+) zSB>5*in{#r597Bja4aUFdB?Hik(%63p6CXl8zEgSRdsYXGayX8<35JEVNy_rEs);| z+{^3?JzV|H*O`g6YkR*$(#5q-`-*P}+G5C^9<>ob=hr{TVuNpK%m=sAQyg5RH55qQ zu>QX1>S^N>So4qJMLv6oWx6H?eeo@*y?tn1AQyw#yemFFCmXp%ta(Ys=COVQP473) zUb>JJoGibormJ@aqCP)CVSLJUQHMS1Nf>PrZbHCsf-lToHWyYz_HW=<8PtID>NRs& zQ_nhxvjjEb=5TmUVp_L%g?|2 z{Xy@o@q$Ur$WzR{~=pDR_uKbKRCWtVj498LiF-z4w!- z0N?TT|N8#G{(CxwF-`-@F8G1$q?@Aw?&`GN;G@%IfKKjvA}$G*haH@t!|5Q$w*KGt zOh5_}uLUh0#f`w5Fvt31cEMoGk9sweuQ97-IJoBT&th9JVy%C&|7y!Ac}Brt)E6>K zeNd5E=nDAA{6f^eqlloS$J;BaZ(&p^N zD~DRd77P};gbM;fJ80g!Ny?Ld(Q=>KjalGBt&09K{vv9p%cy&GRs_{Cji$L|Q*Nl!ZI)y@z2NRvJDiB!%*bExK() z1rbwNa96(b8q&syalcoVT_9x%^kr}-G9@&0<9YMwHM{)F%4eWh*Zf=2<^&V&n0`gp zlv^{Hty>hGfZ!k`5(PA$jm&`?TOfS)ep-N>sBoEH?lbN?W3l5xg}qQWOh|Ov;oYR0 z0n#P-I2zqRzPtIjP6@KRs4n}i-=0%~jXeGBP>;wuD?8zWd_>3al{3HGt7FbDnAo*n zq-a8vpJMKcP!}zmdZ;4ZqQT%_RLjeMV@@m8m@?Z`u`m@^Uri(J>#=|rUE318gvNo7 zg63+@0D$?lLRloB`nU@O3N-c8Fy6i)6-bRzJB@`;ih9gfdAYF8_Dk*LeT*29=Y5TnLTxuNRDoD6esUE_8I%qirBUuxJYNvW)MdxPMyFD~U+h z5&qNZ)%rN9w;)jFh9VD^n+fdtoWfEw2HHihcb$(~1V!_fWjwNGB1D7g{yfFGEiOOK z>BB6zS=23Vyh*NApc#-*G?4p19g*O1{pH|4M@G`fc3bgbNTERGscwsOWE~Y^XFn%i z6NYyJ8J7gNz{&^(079#KOac0n7?2>NCcX(Pv#a1`VM6Hw-DCYt<>rT|$BNaXDEE8~ zzzw93QzFzBf~RPBRE=CTX^f$Zmuro_Is7UnnO-Jyj>-`fJVid$ki8evxOxm!ni$`Y z$!HrOltu8~h6MEUZ1+{064WtbgX!Y=;Y83E@SNdRQy%0%23CKJ3Ua^C4Dc+)jYd`9 zIR7wZS$E{O*4wBwt;q!q%G``-V7~o({;Ewdf}AJLGH7_Gyf0L zAT^>?a(QgYf>Y4^SD;+YySZuA3rt96-K2&UiTx=r>EEbk=sVnOx7%$GBOE_Jm2$8| za73{@zn=d`=pmGFqLefb^NK`HU)y@*c1`>ihP|XRX%2l+jeR32dTHd0|Kml+C(pSQ z*45C*VA#Bk4|oUsLG)a5|HuMx7%zHN{OFQ`n0))=oU(vg-FXdbW=JzR+I{v}rbYUm zEIIX}ZifW(@ga-l%N{le@QL>Jdgnf2t$ctr;dPT}qly!pg5M0CZyZ)0{`G@dwI|Ld zM20zc?#5St;xnJPNRD6zX2|lZaSlD+bmw}R+e-w5KM!-ujxf|#bq^{0=jYt=QjL&K zq=3ui*!Olu3 z=sqh0mXPHB8uY3uF#fR`yGT#|8o#q7tD5uTXf-%%^k8GrtTRQ5{+8PbV3C2&7La@F zS79z9n!+9MP8RJl7o_tucU36U2@^Ex0;@J}H8d!!^ znCxeW6jQi! zV_h($EzF`D`VsJmq(t}Dj1*O6&3T2s7p8r5Tv6Cg+i>M|p zJ~(ba&>_ANO`V7CETN@pvN5f(P?S%1RN8#y$_kh1qrpB9{wxR928w~1Phnb9A#IsN z4@aDB6|+_%LD%~AX$_naS!s6FHYV`ts`rOJEizxRp1UJ2RPXXR)zNDP{}km8(_g&( za+)oZ^MUDahmD{P#tLDW#I=KC{cOG(fE|7M>@t7fxdmbe42s&v%tM1I2r;8hB47Zk zslrwmhdtFM^^vy%4{ zobqH-B=4-udGB&pF2_U>BQ!tjtdbtm-%o5&PkPmZc7KmeIY=vJkN&<=#+7WFZMYR2 zp?-+jSu&`aPk`YN9Fm|9+`2KNqWX{b;|#{RWh^FNuyA(|K9{ra>_jpPLT_Fqobt2m zo;Ge~x0dmtFgsJucW4S|bl5#%y%<-C^H8AsYVC@-0&MoKvfvS!?Fohb#_7?8*dq+> z4RyiCcyOel6!0t|Pu5c>7MJ?;Roj^Z9MYow8=~FgHvz8n!0s zOGSaa_DVJ>(uTdaBzXZ2wK#tK(l?-1Ms-iT-*2h*mrA;CM=e|^JTCc`{y}@xb|doF zJ*{gtMUWTH)X@7v=(*}#yNEVEZ@?gOW%V1nMIoXRpCEdMg0}M3ud|}vH@h*_hdKJ7 z2y1~10BJaT4l{FWnhA^T48J!yJQ6>1dmIZ$Tl^PL5nnev$E%C}!$ok!15w~H^#dXYZ=Uf!^53|u@ zM%FQyxKnQcc4PbLL#MM3HZg7}Nq+@4u@v?KZfrOFb|v;9fb02XsjddiN_T=5Q+D!- z{k3kAhNAU$Q@G>JT1a6h?-lnzlM@R(>@2ky!bGE?_Dml^aNqJ-qL&E6LDOn@mM4|? z_biV@u5HWMbYo)kJ2OQC7VujDY6`ao&-gF`*(e!b!2{NbOvb%_1 zU$W29R8r56#0pumz4|j}=qymH0{^z|SzixvzIVEuX(r>*BR#5^UtH<${)$#RFTIv| zy4QNZIcB}18FrMu4)MRYc?J6YbdZ@rIne*Yw~ zUeZFw^d)O;vkdLZF}4og!HYoroM*E7CkJ1;J6ua`GwIz;?N)is@1dNr@ED(r`wR{P zimt)=Oq=-tessqZ&z1MfgC%|6f=t#s=M)jyeSK%1prc#%XBm!+2WHa;d_eN~1WBdm zR6}5GMR|&bGc^nKY!$eVi2B$iN!il+-`gm(R*9~n)TZ2jHw@IgmiQK{F8CIaa^OgQ zU~^MuD_-S^`mX$tnJ`^1YLSOr?@5)rXRFDwg=hmQVBKIAUE$$1ce^vR56Mrur$Q@2 z&VkNKBz{vXwC0#1&l0mtm_36r;k}J|KxUV zHrX-Y%;B1=FFc2;`t*A!ngY3UY!}vw1hN2|?vE(&XBlf)k)PL!fOPxSF`U$oGl13E zY43_@;95zxP!J*-SqVp$;m*LE!(Q|byuE`^8jZG{#~812`pr>x9l9d-e$ga|{z1hl z=Ri6Zfsc!B^CvCFQC{DwivpV04q9*}(4@cXIi0SPrw8eg8aZ@7!NVT{$KgJIhEy33 z7O>8w1D=DB+8is{63}{JQ93V69X0?Nyi+v!WUArCMTUjIF}CZge4LF zU1AjDbDZ}wVt#2c@j#kT6sp@P|m2DkS`~#>Y?3H_o zCp}uYNa zY(U3)SGE{C-Uo;I%j?Dk)Q3|aHi|Blx496y_uJX$CMjEn6ORrcy#;(?mrDEhZ<+-* z|84jn4L7w{zN;kTOeC>27i^fY0JpS#j>jVa+PG+QD`Qqd>nQf~;S{_TU>$@Uoqu5- ziRr7Ns3*eHXPGFRg(64+ku5X(aF34H7F7yQP~k|Pow!-Fb1b{8*#m4f2NIOW(n&WP zN&$`@vEmSVlHtbuStr0}1@^178<&NCVv8F{=JTD;D~OPdBoNACB>^bT zIbehneSE%2#`IeGevR&#Z0Sw4lWVN7KVJ>UnU?qDLfFQ*d~iOs)V^I%s^DSklL%VAD&!H}vX%tN}ucdD0e_6!Q5RL}GiouU`~8jp$mrF3WT z&VLH1&{8xP%{|WV{PZkYH4CD-x6Vecx;l652lq6<~XFE2O~!{uopocIuxviE-K>3vvTRC^vlkF3;L+DC$-qI9SFDDIQO~H|ghac+Vrm0d8FkqsvFS4~Aj_1DOr| zN0);jXR!d~v#$=@VhcSqEXtg%z&L!IC8kg4zCoa~;^>{(BlX=8@sub>@*`X>`|LLE z<3x4$3x43-HuT+ zq9-+az55tT=ed+abidBIS^%U?5u->wsC4+_qf{xj>I3}|Q&-4JKV1r@{%IB$D^Qd9 zd>V1r#*WZRgA#(C+zt!^v^j=&{ni-aA=y%|hnsM3+d5e0E?{l8Yhoi-(#159AR!wD zF%7@e9LlNC`R}<8HJtpFVDKYmVV{4QaR|7H&Cy|aus5*$1OX$YQWa0Ys^{n;4g6jb@yvWN>E7o*hKq4xdTg3(^ZNe&ZU#fd+`O9@C<0+b-}Fq0gh zS6znyq2L_s{WO8QEq}cDzwiKEKQ#*ImaNP{1W~-8)9I30`Zn*MceiDB;iTV~Nh}KNsc>%fx!2_z}u8TTM6$7MwbtwTw*@FOQ(g~a= zMojc+wMg&CY(%qQ?IXQm79mJE^PZ3pAyP@>-v@SN(Gap0zeS(jm%O0Za zyw=nsy91q%kbv)ieZ-gz(Px_E0Hb<|BKV-sV7*f1N-lP@|aNp_j7$LRhG-AiG>sZ>Hzmb>=GKJOt_8& zwD4u{8A+F)3y+hUP2fIoye;!wJ+5(o{3KG~1X36I;C}@Zp+KRyLs%XG5w?-5=i8<3 zfajN|#wl=v%oXyPEi}mxM&kUhs_jbh;_F|l+lwU30cI&K)kfJD1GIGT_8vtn)nNZG z!`>A)Fq1r33P#a4fp8LI)`A&l*UGcP!r0B&=2F7y7Qa?;KtnLd8TOr432??4pJP)S zR&d6W3_a=ou=b{f20)4!OP4YpfS`)eXL8`Ug97E6Hh*P&zcb0jfU-DP!V!^-C)MGw z^zK@qa?KsOD0&h*t1M^&?{HJ5k>lQ*!w7eg|6384pVn+&ahcsq2J*Mv`U9Px^` zUg=-nCa}p`Rh(9SbUA${%R!K7)!JQucFWFgF_bbYl38{61PIRR`j;pSC#Nhomd=Ex zQ|^~@DvSc(A+&JsZUk~UWp5D#-h}FH9X57YL)ovQiik0DjpF0|^2QOQ!NH9JwTB@%IebIimDw?iBvh82)8ncwm>)M$i@Mwn`Fm z0ZEyJ6_4W0=z}}&{z>$jC2aCULD20NvgdrWv4cBc0<5Lwhz`NV{pwlg`Tr1nn{Cqy z!+58E4Ib8ORNO<++ZV~A;#>~4xPQ9b85iWJW=wg=%Kt3{CfKy5D2M@@HMFl!XV{UJ zn$Y!JV`V8eX%gV5#ywZx-YOf&<1+e<5aB5QsU zX$}X}nH{m-SjspKbSAwAeC+&9O!4Bu*QL&Rph-}vV8YMCPPh+Pg1sPqf_umlF9w_n zJt1I~p934FHSO=xSWmB1SJP^YP&sU@SE8tC0!g6F<_6Fq;=Ok(@nm5-tcD?eSghxF z-&5>KRs#t%UgA~&V_H3AUI0C}&O7gT3LgS$*<{PGJuJyl>xW91Xyi;VAWs(KS#FCt z579bWeXY&0Q<4Ut>n+4Nv3r}6hPz&P!q%C5MoG|>(#}1wyG?vP60cU}-?@@RDev?5 znoaXwYX*I*zF$27p`hYC8yJCzfL7!LSJDa0{D(o5Z~d2ig;y)J$o@7p+i(JjDZ6^( zorCD*7_E|<{57HOJ+0{X(>zCC9iFh)?7hQ^kE2~S-Ul2C2$B8VhKf9@Cl2O&;{xD) z=g9xEC2`){Qu3J38{i*v&P~p&6M^28w_b&$izMyTeXU02f6Q zK<8USAui%b`wrc1-jzh`JI`?-VhE-7mRywV1haAs!2j(z?2UEb@_3|K)CdsM(TURkPG(f$x*GI?xFrz%%%2CyWWD6bs0R{qwx$BWWi*r3E`~xTDJ&(dC$vuz2 zh1C{|2=OUEet{BtIc_&(n7Nh7iC8~kQ!PbC!ms_-gIU+W3l<&m!fNrh_F2%iCTrev zaTV_qZyc;N%+W)aOXt5G=rEoS3oHH|YM0qhq~}i`4PBflt`T_);kKp?UZ(hRLH8}G zg#r>0oD3ipTNhgwH0QQEI#ki|BS}wZPc@UcqSVPf83C@(f z@$MQ`Pf-LMj*Z)qeD*9fU@zn*K5Tep_OGz<@O|i}kq?e0 z>BPh68(eKLdl*^&<-#lqU3zo-uV-PtBLTpOY%v*zP=M3eH55hwmY#3VgjZzU|Ck3u zxul@Z{6HSO_W7zc#c5wspL~K#UQD&}JtS8G+zi4e?Q-y{esl)_2))j`)B#ImmzJOp z=R-%sJ%V`p?bNERtYn>P)LWLcPcbzBT?ZFo5O> z(Fdrek3%Qnl3&)ctyy>M2{vSry)nnEeb>%rJgef2AQ;t_Oj$du#R`Fz@tSM~2i_Vi z4V}p3v=*z+ME^7NkBGi6$OfDjf7u{_!c+4wAiDp}4$eKLmRtbw)v1>M>X9qV?Ajli z49VbwJip6-NMs769UTo1FxnXVI$P3&0~3fo$jr?)+5r4Jns02`8A-;LVYvZPN`PtN z5`sGEKZc+_3`G2Ii+dk=ESPRor@e>=)c>+}u47$u40)E3-S!MYk4jvQ8|V~yeYwX^ zgCbM1lwuIPoVE4VqQ}db=fUSW@A?;3O8If@R_3AjJ>VNBRQLpL2gX|I{V{1S&;Z-K z_V;R++K#utT1%6=+?wuztJ=LFk}?Vqp`EERxe~v_u1=?^C!g-)dQYX=)W5(8+4^o{sw?19T#8(F34r!+Q&2PG-H^_civ5t;EV3us)MQyq7|wH(+cc zI(F68q8=ZxTge*yI95qtqSeE2Syyu$sj=}T)U(Z7Tjcc!34t#keNJ8F$PT8&_E@S;-dWhJvWe%r>({h$TsR-m< zGVS^~(e%+z!89%0&~8L+Hyz*Jk%ghBQ^_0XL)&Nxo~AW;DoK+3=OA4cSpb8#`fBfzrx7-uSawn$}iywTy;}Z=Ief~<>eq!l*V@^is zw1D_OFF+plMAhmz`xQjQopfTqE1d-6`$Ff3yJJ$SBtX@|Iwy9J3%=IPk`f#Znp2!Q z@G<(JbS++i(bRw@cGk6?UTabu8Ns=tNP`_1BCD7ObDJ0qyylr`ycEfjiH(|=xwO?-`H+y znMX%{rCF?#e#t7)P1SQ*RQwWhPmQXC=3nWQcR-P)V(D_p^hauZb%XpYK!1F8ZJ?mH zMrM}J()QhMt<=HyvnJYfPA@Fh@P}y9+3(%w0@+0;yP?#i79Y*Y@{lQ-!-kav6W;`T zmh>c`b8B?cI3Y)GsWdR`xOdjeQ=UR;08c;&v|xoBSb|9QsG`fIteBqY?8LLT%skip!C55mCgeTC@i!wu9aR(88Y%q*y?h1A8mB+xJ+IlW z{PS1kCV+o1;qd)K0UZaDQ*Jni``1XU<|nC7j#g60+PLX@2|ULu z;9`w3BX5;9uZUZ`iWx0N3Vwoc<#KfC_?cJ_%|W zbJ=p@T!G*o=};$iRlkW7FnB7o=-V+VsIWLq_q#T3tY)O~Z^Wv)##R=YfNoUcBB1 zQU4nZqHj|=HKOc7nUU^O5Tm_)k4@*iC4nmk?`1r?vk`pEA)Fuckhe3spJNjN_5S(g z_MY~+8lHEnx-w_Cm8)iI0CocSQBlL)?{i=lc7P0c2Xp+0lEj+WtkHWylLXKSA$<1K zqpmXr`)fpJ2?%dD&=D1LQ)LSTkR{aQ96E3D$PzghF8!>%%=PI}c{5x0so5-*s^?41 zQaJnhp8#4PjeOvhdXn=8d_|*bCh$eD(Q{H({%0p+KntS7B5*N1Hd2{rv_v}iK`wX@ zZvwy*^8Dn~3RucLVVj!T|E{prtj|}zs4xTjjQ9CGy11=HhdbOYg-kOCTt^)48)$4o zqs>63>;|RmS+g#k{@Qyy(_If|v z_7&aA203s7W4!?cMDkQ1mYhwkrMO#TJOEw}h;@5g^$3s(GH{_1#e(KDG}ssdDCpWo z@B#XZH5KxSaB5xkGit*;ufWV0Mke@k;hLf+ua5cmL$?0nsj?On0n4mR?69s@Q~^~u zc|s7cZJ)mq&{iAnJ`^F)xBAsnmS_HJrbVT?P~jYGQb3_jQ`hZ*Jmd{3Wo~@+KSO6R zuTacp@wj$D`J~Ser+g0AL8EmU9+4nNtf>`nVM=i@E0$hfh@Pd3lY}O|03znJI0458`dDYA;Mo`c%kNW_Jl~vW1w_?aEKmQvy(MFb#6JoEKl4nI z_xck$*mr61f)}fk`^qql%4O(yqj8{@Ikp&&q^8f0YEEIS;XNJ;p8LHlCyWeRQ0+b& zA9^BgbofgsVtMr)_*pRBw7%Ub0rV}Pzk4FI2itIE{R!JKXwG$drjX^&(9OrAS2ACh zS?aT~Uq^W<=eoSk68&6+|J+e%mPFJzJLcK0_vN?yz+Ec@8kut1nihoYdmUUT8Du^f zI7OLtu8q9$fuLN?22X#;+*WfyeJR0HIJqRVv8h%4WXse74z{K?394D7`(VA_UqDtg z#DR~|cL(XDR^74vd;N(3Sz6c>?&+u3TrZgkJim^Wo&Pw(FMq-8-+El?j<+*hZ#KL#Q~=+gO3CI^HwJTDB5k*meM2n49% zZ#MvCUrDS*i)#PaBU-%6K1PkM_G8+j)b#kx`99|La)-F3(dq1;c z8_Mzl@zZws`$h)yx29(-g>CFq`i^ z)@1fXoRY+eoBogg*nTHd0hR1o-+G2V2dD=J9&;?NJ2^D081BaXzPMHlLS4vm->YM# zvH{}({QBLZ2{{9u@vv9Z+DB5t{7|96q8LzDrDy}=Hru3Vys}M zvybEum56bRd1VcWde#aj?R@M~X>A>XH_-Im)BncVzJ*pg5acYGvfjSYqK;v}=Gu3^ zBk~OjU^23Vo`qdNGbUyK~z)SfL1+h*R@4`SgkPmYs1ciWzd{fs*RoC_a& zyO^0}^{ctq2kAtv$UuE4A}&@3@BT07aRGV)Q^@Z6OW=aoIEWfffFl7eP6As= zf45MW_=F2X8sHS0=kH=`q5rTi#)thxYoGxouOW0{(e+W@woTm-`bEk2stBn#>-2J` zTCbTp*|qCW%4c6v9eLfx>2f_k6Ftj%Jik4FGy#7-!G4uY6*DdA-QAg??&$N-lUVPp zBtSLYGctw>;T(p+a5Y@h`N#s0J}FdmLU2y$MFqJ}pwR;#VoOoi0n-tI^m%;JzA5bQ z=CQrH9w6jA`x99Cc&v8;_V;8gXQ#V##iUSBjwsUD0n3B;C0Q&x`ElbdFlc|Tjoz$Y zFz8mXE`O5dBIOw!qw{P=7tQSa#Gt@3cYVt-NMDq^oe&b@?CHQNjGgBHi}=&%JD@%1 z51?Pff4Hi5WIvtN0js24N2qNf#NRs-Q9g3ibop7pubF!KK5;5v!v|Ioh6)RQobMcx z@;E;tUrK!aGD8W-fz6}Iafj5uDpC}>{0?r5N7|18SIWZJ7T7w+J6ts_cmSwg|2GEo>h2Zm18$k?{y7y69lgQ zTd?N6iyDpjN`52LW!OzVp+EnCby!BJUwUrC@EVBx2q0WXZKLStu#z?OJ}=?VsI5{U~s^*H!0b70Mp=v zll{$i{y{<~5b2=XKA-Jd_PO>I=3^JV6{7pM3(x*YnVmLA_8w_{GicLUr%!$oNNlfm)9-RA0If_b!FPtQ`p*c7fjpGr{1uX0e$&XAeX=9}8dllw52pfyamx2p zR}C(kZxUY~y$cZOPhe@(P$uqH|9titf}*?kD(Q&mqp5_==P{i~xqeMo@dN zL4dGyE7vTP|L`=_3=9jZp7pm%+Jm|E9$9yfls;HBn+xR9&f$ zeszvl@3S7h8|uwh^?h$p(P>HceupN&sjT1iymd5a-hFNviJeA}$^Edu@^6U`Je)zF zJ};BxKA(g1{`bf#u|0+EW53{&8^`(U@Ey8)wdNARasH23U;3QByET~~BD0yqWQT)xj z8ovP3rg_Kzpoed)0i+Hp%i(2FA55DD(r5PU>oQwb!<4JVbTrSFP>HUXVySvlx_+LM7Uh4jlW?&ia``VXA;UhL20uj+Uj~oPgFRSGlKqmxAyFwor ziYTdvwVUVJCf2WQ#69zGs~aFnLAqD6pC-*4Wa&jSo6;_(>GO`y%U~knsvpi-H2f+8 zP@=-R9Wcc(q&gOD#>d;O4;Y@R+3L^usPzV43#Mn-im2cz!n|3}7^M<{vT0Y-Oj{!C z?@i))JJ07gy+tN4TGHil?A7h`Z+G9+?OC&MEYna{m=kT(yUNUtos66&1#!NktUTo9 z*a@BOO>OHW;dZ8<`!|GF&n$p@JcUawrEUpXzrZi(h1W;=d%RDui~2QRz_8sIQYtCh zH=x%|@*#R0;TPaykJI_})#1Y~bv|RxkQ_CkbE-+`PbJC6N9U|2;c@W4Ss4B8tQ&K- zBnXkRZ&9rT8RS-itPcEO(InNdi&#p%fS6O(I64s}-YUyH>}cx|YA(qB7fF1cC~d_zg4U~@+6OI1}Sb<+D?hFB)zp<3tMnx+4ZghWsG2Ap6 zCDt$wYWO%DjTI7_1Xzp1`0%~+GWN3G%RlsTeGJDk}tn_`u-a-9og0)J@ zvh1(_Hui;S7A|B;%T3b^g}HhLzCLoPmdY(FN%(PfP7m z{42KZJh+o08{PJe`tG?Fv*{4aB4D0DQ~jqs(&1d;8w~}*vj^XA%FcZ#HW0L!ZJ!)q zx;^md@xXMuZtp3MI5MNWiC^X270;fFW<`7L&D(qz9XYqyo`9ezA|xoyCnmM+2hLn< zH+YF8yt-Cny!~AtBQRX{^WWF(qohit&6E=G_17!r^g6!4gB}`}f(cBuxQqkgWZY=0 z#)$>OVCgK~HIomoL{^6#@ubZ^t(lNcD`}EFi<83;B^v9F}bvhenZ|SH84->H~n3U#k zPP0AR0PyE6h4v-M7P2jCC`I!$ZT=Dexj#bRr~d~O~Ce!48h+6w_L~fYq;- z<|A>G%GPyrk6?q}u_D7h4i!aF09(~f3WL6nNat%u0*hrKV8Q-rNe9)fRel}8#O)Gn zZk2a4uJ*TDf_c8|Xg9rvg#)3b0=OC)l)0xKYWmk*V!C`^&^O@=89svWc518W7jcVg zfr6}|few9q>V=C!*cct-)yH?Z!$8@-QXInq5Gy$QrTGQW@UCRda3ZC5d@*EU--DvJ zAV)Uhp~UV#)+wg%9MhM(jHwC9(RiwvT2~a!ks0m3x%$vw zwa-oP6w#4-hYbu|hwh&)(M0;T6<#$Y0MKH`9SnO-pfr{L@B*k#e~W)CMV!n^ZH^Xn<60D^!AbGj&xKMZ+%6B5oAfr4$)W>a^<1#dw)xBEefZ+!ln z^M!~%_wMK;M1@#7DLMwt*uUm25;S@hB;fRc)-1dAWw=OGQNGwfBV}BWVd@7`j*W(7 zXRRd=;L^NV%xWnSo^o>ay*JcpnDTZK9;F%34-po#a=ZMU`iBG#u zg<%cge4t9}Usce)vS&?qeDB@MT&zt|UwJ!=2XghP?@Th?^ULk2wjVuDScI?4#mPj% zqEUP}`}1D~ZOQhM(3~#iX+MamIxtm3OXl~zKeDaZ2jfnCR3{;MeOJJX*;kCDi-o=X zM4uF%Id?al({#*RoXeueCMKMpq_y7^V^8Gn3mT{$xdt3n`~0*^_TdB~$LB|J(Ir<^ z67ZymDa*q0@_k!}`nU$Zc%qA+rt#bnPt50;Es5VOurbWm)up_ZfO{xLGJFHce6nxn z?ht&OjFrpZ)5!YqX;BJ@ZbLW+kuW*3aFnVPT=<# z1vk}j956{u?mUg;qBW{IQFAY~jAR3Cx1>=lFo`jWyVhJKGYD<=`g`xX zzEb$_HBP9Xq}i$e6LN1yb~)EX5ORLh8bE z+1h_W9;VLyQEo;jm7h<0AGf^IBi*R_C^AN8!wlP85t*sXKU`#P2d>4Ym9qo)c5Pw{ z5`U9zB9(yd^*=xfs)YqF+b-Wz51bkVlxmcCeNod=$I?-%wylak9DLa*T`KzT`EB@L z^7B=XIQU6=BC5Io916_1rHRG!kLf}%^{KGQUl{6;iqmiC8%{;}fj^>I z`k;4+lVJ7p)QpSvd-9%mwB#7M)6?8NY+;Z@1toY3YZy2mN~Xhdru1R_v?*9lGuB+_ zJ-0rl}lP%F3&*^GI@m|OSu6R^b}_y-xHexAIJ;O=~=$B zsl_G~l{iJHC6)FnemU`I>@qdQVTh*boDtuM3n7b-y|bZ23QZq%gM1Vn&(ruW?JF+V&R!#KE@=ZLLn9)$;hJh|U^wem9R-h)J<_%S_tUZezQk#?-QHBbqJS>=PQm2?oKX~$o zW`8;Q;ZY-}vHW=`y)nG1X7PA^S5YhlRZ@g3HAsr+dZYK{?^O2nvg3k`8(_{m`yZ{vFQ>UkILIV5UppTAYFhYsmv1HZyN*j-a z@rN+C*|?uVPNoo{J05-Jo$enTY6pZ#r!&)e?6M3uDQkGp1Z_$@*CPc5+vELCm8p9g z)}_s}KAa_ARpSFMoz0_6;K#`A8OYl}$})W4>(s!oOke5fsmN;jHS*Da4pT|LGzvi|D)=O@72v9+SJwptv7{UU{XF_6(g&2 z%^9H({(KM|wTddry@H;ccRaSO27<0a@5=dI@~Q1-D?ib-YUq@>uSQRq4$;c>WGdI6 z{V3TL_|sQ?U5QYrz%CCwf0YPa>UEXOV%Weg(tw2__p80b!OUiArhdEde@lEd%K-v7 zR}SRH_tb%;E-s#_CGKNG`FWkf0|E)!Z+mDCZG?YI5y>QBZ~t}Y*gQ>Y+?BKLl1*0% zlfSuceAxKnyrdy!_BHHWJzajj5x_N$p>t#ZPi^g60P9nU7Q&Yzy8_On=r7DsXv%=` zRKgNtk2gOt2zNynm7obHO?Fwd?|DlM0X)lLnYKF^zk>Gz@|s2gredwKbMM#!yt}k| z^+ERv(~yK&oe)G046r9#VNE!+Pc}aSBl2T#n6k)-B&|bOW@Kgxz{r1Q#qzhpaIGt~ zpel+4P?z}l&{rnoC2p$0o#PM8SHP;-Bf?-FpTv22F-tF%UiccC4gEy+LlU}%9 zgFubu;0cJp%_QLAcTo}V)*LQBu{3?fR5w;%#n{MmV*pR0%=^rJKZzTbT=W$Zw#r>` zKZ_%w)&j`+F|-j_RA9UG?fqBbEQTnqrF~5q)Ldk08#`?tCloELs$dP-nMZLQr@&S2 z$PyqCuoL0aNW3Q~mc}8$VNABam@d7E7XjFOZ&Q)m#oN6rH+=iCu{P@EkBnZU=ij-% zwO|iKX>bG_HN8XjfCj&Sr*bYEDUIGoo->XMw^kWw+Jk=q;Ay|i*tc>6zO*)LP;k8Z z46~)w9p|WN6gr7&TI$O*yOuis;WfzN&~E>E^_!(gV&UgC)1Y`&EH&dHU>PozQQ>=v zT1ev#AnDL~Nqy2VO;9+Uy;=k#?)xWbs;9%??Qr9EWCU%%=a&hm|IFq7vNRpMa(tpg zx*)T81xVja4x!|QCF2CFFkhWJlxc$HgM6%_(57u&SCo6T?KcC#_NM-Y@;cdZaR-*| zvUi7YDb&*|ploWFc@HE?CK!zaY(ZRZkfRK1tG}8btnWM)_OM{~U+ll3Nl!xW-|PWI z1?=V`&a3`hNlL!i31R+0)OBxiLQE8`MyJ(>xAkWBolpaV55Cfiw+#+kTXL0c6jOTg zmZ5>HIU4weWnB&!P%*x)_C0t~&%s);>I-wU6cf)rP2jXhP?N_s<3y4cC->o@g(NOs zu0w(oHCQ{#)h&8fF*UYe8{gkEm0<0=|KXT1)gu%tJ4v?19`b(na9z-tFDE;ImSkY{ z&VXl{a|AeHn67^1{h#ZXv;q^L_&>7$6rBIh3t;v!TM}y*tFm@K?qP%WV(W9oJepRu zqHYLR@>Ik%yQR6)%z>&l^2tRoC9aHi&A#+``rFRob?>F~Kz7`pfDClt!dbTYqcFCE za=|y;v;Z7u8c$SetW(E;ymS^cVN+U~Q0-;CDChrjU@=#T{nAOYb_@D@`;ECzYu&m^ z2Z7va_!L*kj8K8Wj@H(vF2;Yc7=KFdmYFKf+c*(p&Lz`;@B$OhccwT?Kt3%IrsOFT zzX*c5GC11kK(ab(75Hu2?oipYA*-*n=kweZ8*`1?sWpgQEkIXKScj^c4cia_Q)|Bw{|`g@SJ5Bsf5rXv@BQANTV4s^QM{Xbdb5%9VnK*L(_pYK_0{yL5&+;2 zB`TGE6_bo1;JW|Do&_YB&V)PbJXWSjJaA%Vou*4DP`9jhIAua$+9iIg zv_`Mpoj!HJYXiH=QbH0{KWQT^KN!Pvx}kjR$6c!YaF z^WuAv_sFitw?w?u*2O3d+-k<-@3plP?4Qu_ep^xZdOX^?_S|;GFMin^N#!zfxa=Cj zigh~rk68qAoA)Gjy)Noc(cf$TI_o|=?$1wXE0u=V7hQ(3HT2T@)|+mMi(Rho?>4&i zkCE*(i~IW7rhL@_0Neoq{m=qB=)Y_Kz3`{}hyGo@2|ypoJ8{MX-;X5#2EJSlbhzXI z{faMK#aP(A2a;H=j%cm!Da|Q}P?4ht#d%l*2Z!2@u!H3}U}>2=Te|2+cco(b)(K%> z5i`vLr%dBOQyRNP??IWiJ(3(0w>ormO%wgcbX`9k=$~GAH{fZYn**SH)|L4HCGta2 zfNMJtTix-MA{o#Y$SnGmmIky#SckSpKpU`Z;C%coeQJENa?pG`9_MPy0f*w$@;*T5 z|Gc=_#PQ4!83XWCaCZu)^6ClqpGJPF1B$c0EQIi>=C#8P04pk$aY_bj?W|kfvg3vJ z-u^qH?SmF@7SRVhY{kAaz`#C&gT9Msj`K6>&j$tZ_cT!H-({BoT>T01llp)|B?nY( zCSbUmwH-XAa1y)J6#pFLR5nBdE1rpnP#rwgwQ&c) zCEZ^+fQ>^sZ#@TeJwp8LO+t)G(E-#LG;{q@%??!UG~f9NG2 z)kL9(9ju&3HB|hM_Ftk6SWDoD(7gHJ=eB+d5?II&1HeLoDF4&wFKADKfPS>Jv`iC# z-uk!VN+a$wz2%2PKy^OAe-8eGoByt10`R%qq;FvniW8xJgK}nWxI$0(K4l|r!?GII zOaSH(q9VK(Su+fLHI64)PU1ElXRk9;6ZCIaNm;RS|3fPOC3e~#uR^GW^SX-*))QIb zF@L?1!xiK51fV_uiPye3sm@0_NuMoCy1j`z;*1!2SEV+)%K;6aNgQK;r=Q5 zC)|InHD}CeqT_HcLY`8}E574;V|)-lSp1nqM0C#>U@-wA0Fnbl8vgpNtycDkpVGkZ z%RB)*vZar;>OVNr3e=(Bblbgly#tVVjs)P7O<)(vc@4|9G=ViY^oK}}^D6&^5(pNM zD#@RTLz#1San_!l0ycFaexs|dNe*#UFyom*F{S ze;vF?ONSIL)56gz2k2%6_ZY9UFFyXl?6>RX^uKkgYfSTl;xpC$u)br+&)hKjr`o@6 zo^X|fDm4D!(>zM|Csr>~Ic>+NEljgtJA~{C?E~5mXcl^sH zB=3fMe9|X$LCFx5$8iEc5*-;>dICsBG!BNOI@)J(fq<%kD9#Xy0y2aUb0~*609rRe;vJofMxn`fqGc&qw!tKu1l3 zmunb?<6iE`OmFPIAmN!R=(YmC3}-b!{DFhy0xdZ|_z%(l$6g1ZH1ON9O#uEzqyAJ7 zS2uld1PdC|1$pi7(H{p0pT_b5rDQVfkV~@NC${RpRu4VJFb&0FSgyYkq3$&^_cYas z2ho~Ij?Oz0=d05?M#>+*=BFva)b2R??=%T-(S~>xs$P8?aNSJsC-ni-31GrnmH%>} z&)-rX4oDv;GXZBBx1>%EYpJc{da&KYDnu#(1odOKX0}8Sed&Cg5%>_SFIChJJ|k{|{~Y*N4A;vEi?JB=etTngG6O<-ejf^}FYQ z+8IE;G4abm^cVi)*8e_^izS&auXwh2VWw-wxy030Cqn8fUMS)#A+cqQ98kxSnM+6z zN?Hn*VzkSXe7Z6vs%jD1Er*GTX->*{avgd_dJhRY$(6e6ZuHkAfK)z@{oFeqnj7DB z4hpnw$mm=!I!6P5z<|DyINeUBBSin?12}f9isy4QIsl1+UW_JSw?)I`ui2G{rD+U! zW_L#Nx`9TD823J z(BIXaw*|?6cbEo#Z{yi8z&O6)0HJ&!>;DHs`q%NFlmN!)-{q13ezybwYOfs7RRJ9w z&jAp>UjB=q^Ccv@M14rLyQQd$lh!@#V3)pdN~p00h=kHoCu(9=5)QQm3LiWxorn`7 zS{1fVF8S3>vupkD;j&7Me2Wv)YHaCRA1?}XQwITv`(uM$e{l!UO$OW{aVm}i`Nyj8 z#PXjL!RQ>d6z-OSzUCev1#G(Ois7H{L?0tS<3N=E?}mQ#YLE(Q#nw*_VR;U4kWk+$ zwi4*w8l8Wk#DO}A!oHx*>yla-xVK#X+o>dl#I=XGlIPgJ(I4*GQTqVz$Z zh-eN#{cF?wd>6q=Mjh${mgTRfCaRK|4#po5f95K0qnIno^k*&y~_tU7R23H zu8jZ`69|R?60+eZZVi`7R7U~D(27gYHnjwx=ShrU@yJ2r0Hq2gf+(tvdEod(>v5l` zotS`b^iNSZP0SJpz5GwT^Okrg714P2s`_X_b6bB#0!UhyF<{MefCFE?_-u#GGYCu+hcIkvP%G8w*-(zz*NyQ8L+>X1N2{>EdUbTX_}^MNybl{Gb9IWZu?>M*TJ0-2+1Z$%rK*2?hnzO2um_e&jG%--D$Tm zgXmf&BLzYJPY|S-r5n(*Wrn%ByG;Ad{bl%1w*?t{OGOAL4geI0RRJ0amNU($0=ONp+mNLc(|}nt-?4P{JM?2!P?ND;TSnxcWJ^-KAL;Xbcu& zi_%~Y*?$YLYs2uZa36JIF(z8f`p)%ceb*0>A7_21k)L^^zhAJxwg+vg=Uod^415Xb z$NWc`KnXzjkL!OZ|9$rhY2c@k>EC6P07$Uk4HH1h0rUi^52&255`#j&tMn9(lMO>{ z#+d@^UV+t^;i-1QrG-GMvT&*h?c6s3x0=)Yl37$^%y!Xhp{B zm@$bhi7s?C?y`%M&^9~h^e2V;2?!`P0qFzf{jAuRj|B6Pod^Yv2v~A};%~S7PZp}x zETO7($3{Tr;?JG6jRMz#7CzXja{r`~xY?%#`Bw56kK>d|>X>!m2>ueSr7f*&)!uDF z23|5!QII7hn7SMop05=>{<1FfUvEh|#|2%S3_qS!*0leKv;KSp6zyu%Q7?Em!KRaEk2h!qJWgzK_Vzq!B z^Hh1NDGi)2RR^F1plebcE@v}Kbkz!oOH4SjTH5YBaN5&Scb+)7JYfl!!f5I(Fo9WH zpl!tnYAYWSPDZ4ECE7EV119uT>DvSWK|d-$XsY8tTl=iFz?ui%R|H*MyKid$lmo_g z;JD@(aAPi>$>|^fw6OlIV5E<H|{k5B{@f82!B%_v$qX*J|{izz`$^ z@KrPq2D?D zH1;tUf8td58GIP_(eK5Rk<%1dqKnFsg3F7BHE|!ok~@ZS)xCBpspQvUGU1kJpZt}& zn8I~FsR454gMQ0sr(n{<2BJw;2q*!l zcUDO#bw4LMgQkQSy#!$hT(?XGcgMkq6cq@n`fJyfjtO#H6N&F5Vi;FLYIs#|BV1q7 zdQa2Ne{nw0QHNk_#qAsb;&i2R76Y6NM+dD1mYL7#D2iocrR?Z%5WQwn%Q!v*g`Nhc z+<29OdRzR(s}cIYh(6$z$VsvYbu zh>Yz8b2YQ0j%i!x`a%w~h`1^~ed%7e@P~ZXCws_{pV|RDuuW~6_97Wz|H<}8$A4V> zQ#%0B#mhYbFb8ml>ZRFnzY(gIsld^aY=Z%oYUi(O;NGfYxQ5*w!fzS=jDnSXsN zFxIY3(7$P60PHuj9nAE}>+O65Uxoe`1A@QSocbLb@fmNQYppBi+(pNII1-RT2-_Ba z>uT`8pTw@Q*W31K4H)hmx(z1fjQczTSBfMPbLLWP8QUElJ~CJ(9&kQz;LkkK9;CW% z8bEvIGuRt@B!T*4PJR{>%~JcP=znk+_fM4saL-D9&jjuTo$Mc6|C3Zee$2}NKlurO z7j?090O)*@=^L`2qziJrzbY5S{XK>Lb^Q+-(5l8;HJhD)*OlH-dj~+WaTjG5P3rcx z<`=f7Tw3_URA-1P3GJ3(^vE+7jWGD zh`nHfzmG=r*DkQLEpVKRv-h=d_mt_kKoV8T5c{NoL=k&3(0lHL0Ra(uX+u1v6OjPk z3>4^JL7`oaGWJ*lqu?Y^=A_-6y0OWUIw-#`x?>Rv$VMSe&ICnEGqpMvKP&Og2d{(D>gp7cL;?Yk#{ z2?vPfk^pdFRR`cqulE66T@ZZ$l7Fgx#%|rG1@}!5`R>RJXvtVusYj|`m?%NwR!!3R zcTGHJEf7Cs`xI$leZT80l2BJfcu<}(5W|JK5(crh%y1Ofl%>Fbsu$4zi4R0q|MSdz zuGa}nL&}9__ds)iP@I*Er*;4wk8jVnRlt|x4zhhsvxl2YkOJ#Sb0q2KK;cTmJ0s1! z5((hFXaa6UT9Uo!k$AQ~d$_sh=m4z8=1X9oBgXU!M3pGW)e{N7s@RS%)Jp)7NB=rn z?@fa~g)Kw8(Y;&PM&LYw^Dfi4zdp+DAr;WW;r=gjfbgGhS~9q2^e^sjj`q~(UpLh( z-vsbY`#jQwSCeRYJb68@EOTF3(;2^H}SL1`7l&ZT~nYj zU^9*5ZETs?(NSMiiBf3Ye6>I7JFopu_xgb25!N4=<%6dI+~4s3arb}d-x~Cx1ZH7? zmrDY8BR&AN2FyBPj3(&Cp{62>`_ z*i}rT)erTZnG&?1G9q4?H8f_4M#c7AUbb z-e>Kh-7%aq@}472oGr)%VrjdCS)zYh`sRynlmK?d>8Eg@Y8p7vt^Zm5w#UNgg}`S% zj!d8(<(K1BSGW*CPjLMEPtyjibZA z!WH3G)#|)e`yXmU>FG+ThKa87tlqJl7Ub zYJO75Kb8Q#woSjXe;@&94dnO31psOO3%j>&8klzm_z6z{l>gfsUg@>fEIGh8y#V(+ z=Hn;2H{F!3$-z9C*vuGfsO~9PbS~<2bP-O9+N)aY0|#)tQLIV;ZWlZzNpg!&4`fti z-B&m7%faGQ(SK(=$y2TPavg2g1!w~H>6U(DkkLc~F-vwy2tyj4=&Du_=5CEM>SVlX zBt4j;;pagqP3tMbKx)w&5s_bra4clzWZaf;NJ|AoDzMfx4a1{!;3rZd-DqAw??tQe zNwfkt+SYjO89v({oThp2&>UB(MSZrSKkago()-jx)%K(spDN1s4O?6X<0`licUG!6 z9shNrNsJ`O(Tx-FUss~uza7y3htX&JD;8Sa3Lxn9=nv#np`JsJ!#*;tEIw)^wm5^G z!`eU1QaPrN_Qs)hcfRwHW5Ct1i%TEk*sR8?hRczdB}LQw39CojjlxRLUsvKbYvy#E zY}tJ*`d=`UA0Pf=1Wbp@d?kQiO#oU;{+||306eh?KriHGlYUZ|pxCylx#-&YO zX&S(D!1T+3$v`709Q;7h|LD0@3+RdZt{eBef{?NQo!x4J{~c3Ic>&8hc&T`$hI9!H zLEr5yS^46?x^NZcfQwDvr8XCd8p=y0gJaPRT#VrUQb0ymA_j?k)+S-yJ|Fs@ccS+H zFz}y$MXmaAGz7OIH@wl(z)KB!Vrqfd2i2+30fu{hWI_0krmkFd(>g+ zV4nO0pz{ArTn03!d&c{K?vaH5m_2~}U^fW&)wO~1B4rUUbWH#R1*!PQYTgYkQjh?2 zLVE(BiJq=-NdT^)PH<3_UW`59oQ**Va#iiAQ6Lfk^Ix+Vz~N#vUF?qu_G=;EMT*9H z8c?!TJ<69!BG^LBB#MxCkyh`Gct6k+ zC;_+w#BVnG3kOg$!Eehv0Xzy5D>chH?_s?#aCS~OmH%nkFKQnrxZJ6n2>@NmY9|u| zEc|Do(cg2xs$mDPu{~zRe-x}Yw~aA}TV-F;(x&(cr+z;~V<-+P zJPA2HX!s8lx`RIx_5N7lpF(`Pk-~lV+cY6D!7;eGrmI$*x)frt)nFf@2>~TlzWkz_ z9wV=03-rmRbHnr->o)IM4kbUaRp%Mtx0_q-7|UXOp@iNgPr;C?@i!vD?qxdwy( z8EN3X_!T7p4W==l%>D^iNMl6kQwSUFrTHRtN`4Rhz7C9cxNAbyO#l+rO+_L3MfhdSZH{V^~|A6puP~& z_)27gSEDC*GZMgu5#qHL_*(p{+;B4z!{~k?wLf>oXx(|PA7-=h7g!OHudxp zB>*+5>xb7sDp6$tq}+C_3AdF19Aj|+XWr-F5Kx+xcZKW3Yt(3h3So4RCnI+3Dw%1F zRG2_`5|WeVvpkO1NP%zbv_!SM*2%`~YxU7|-pJu2mRR{fuUe>M0o}-} znORm?R^N4{U(|W4=q58xGQrsZ^e+dvuaaN?-iUwSj0|xr+Urjv2WV;Vh4vw8EEy+f zFO`V?>XLo8SK4fxjEvUyK>v9MD!U(3H!-XlepsBGvM^E;aJapkWckjl8Kk1w{SnscR^s{j{A0Hhp%RzWyPB>+4DXarv{u?BF^fI?GGc$8KY#ciBP9ueWNM;N^1)3&8!EJm-l-%R<)e7+w37|5-xX-Ju)Jx_g@U79w zzCVeqs82CZMI*FsHYa8P03ZNKL_t(5K3{E+-!XIso$K9Z`#A)RwEyzwQII;*Y$v1z zy4|?nx1%|DJ34@G1I2zXvV!&&oEUlpd7T7922X}lg_GW%=jZ^E&F6GS*e&^=nv^&{ zJM3#&Pvk}&Dkb%Hu~)+rs)B=xt?A=va4^pOg8ozf^R3K2AK3htTL6tofPPzs2>{c# zNAWIbK85*S#Xipg48NrL0H^{V{bf7{y?;8hscX{8Y)=3aWYmletnb$r0}M!APjRjF z(B-W&PgJ(5Z0D#`a_Y9sJ_rU#jaCnqI~C*Ug@FI88>&A=hx*p1Y2>HE@s+~$_?}EM z+$Vzpi^Sh@+jB;RjJofVJIDjyt3*&YxoL>}xK_AYM|AD%Ndp2Ujx>$$j-dttD5)|E zPDoJw95k;Uam8;%i2opt_geJ76#&r>F~{^-Fa)nf({Qe-THP1jy(m(>@2h>?&N|ts zbo>C}6Z+Y0L)eGY+M8L5>r@&q0{lq@ zrmQ`&rCrl2Lix#B8)-Q*w2edn+BGQcGN@^6lE$1iB9&&{>uuFg{iy|Q$J;yXt3Sqs zN%g9BH)cYxZ=Ol<-Cc}QCh*&77lMyE`=6*U(-;5Zbc9q~d)0k?TQUo&4#ssWr&}2- z#~+FWa3a1DoP~Qe6pd28ZQk`sg z(s7M|`1_UO?1;N;CR+#@9eO)BP5F+|zxB?^=W2~f)HV$_wMpaT2>{&(>MU}=@yQP0 zqxRO-0~u&t0smW>0QmXwM!=rf1aPH|zq;9{@_`C`P=4e<^Z_c9nPybbOn@e^4+s6A zZ%M6o`HRMXa8Qt1S$|zFp7pBGX|2t=N&u2EAYfn>Oq#HrKv!5D1t;kVAbIt46O!~l zOipf#cUZn)@{sZJf0~rm?Xk6s4*n3t9hy(E)vdFW@npK~Fj3VzC92$)KC|GCrLh6IJI6{ftxU&)*eB^VyXoC8?g0B}9OePDe^~N2NfYP6m+u$f{NjA>tuhZt!+;8mws&F#_JBjQ~ zq1O8VpWLpSkl`WIj`f5mI8dW1L6t;G!0uyHpIGv(^h}`CA`4aN`ZZkYj`nUvl@f{n zkQ{)tRCJfbJPLMKTKWHJ6#JjW?SHm0F)2^Jj;wH_?TwKrNWLS?a}oNJ)F*-dY=7(e zK6QW6?OZ2@QPSeJRrdL!+)YDak^>zxZ3spHDy{S{SWveQI1=sD4{ZsIa{xXIrf8)^tN6QHv6%ZP3_LKJkaA^w!+ZT;|=b_leS5DY zfMfzXc05|n3Ex%+{1#z31gD(=s&Ix75S;gCO)k`i!^>g2|#7qhWHa> z?X4PRG6i3E4}oX ziD}@rPB0%EW+%b%fPKgTU&kRtNN#cWBL{reu%Ih#$JzeY>iM#~%Bf7O)vUvP6JoP@ zk)K3vJv&U>x>DQ%S_wc}Aa$-a2c$kgH%Ouf4FCDDf&RYy>ziTue`mM^*a?7%74Qok z0eb=yz-w*l)d#PI1&!qZIDq8-@5T>4{N)pjEL`pGweTSOnCL(HLTVHCICc}j+6JsA z&juI%r<%)=pQn3!v>B8~=>&A!eN3K=V@H~rL~#w>jjY?7ok-Whb4 z4mv==d+s(hHOG@Fp~~TDh5lE`e+s_cA>>pG`}PuX0J|Fpu-`_^NH(5Ujv2|y^2qK77pQV!VKn-72!J{9i_dVgkswG>R;ulfTm0cHuzuaj#a z-2`Hx4Dgeg0JH?dXRp-cyM@fmBEm zRy^jW&Bng!z(=lJ&FT7m*T1>|6jK37>}Ah@aJJ$1KqhQHR`tA~AnS`FoZm!j(bG7d4B-?RkqMclaGa=`nc$k3YmgXVz57=*uvi36|i zhJUORb|Bphkxq$j{(E-#*)b@m1i)rv`AZ(|<$xW96ZZLlEio&1uhst2{6PPr0%AcJ z5}=3H0gMpfIbeV30MPzBy@Tav*TW<&HJyD``n=JfZ7@mz6Hv+X zt+K9ow^Oy%V>zLs9?`&mXyLu%ako1k1rU48NR;$H``a|Em}KV2<~1X#7k0t~Du&RN zGbO4ZDZ!H~0K;6!LiBMXqOWKY_|Jx>BBOio^_FQEEp7CyAsZl$OsoX3yFozslzI7| zTw2Gh1JmrZ=YRwUZHs(!Gs68>R{nE*9kJ|g+~Ibh-cAOHOYGr{LX3r-JcWVJ4a9FX=fS58>!tT!SxO6VyRNM6to00@CR0RREb zG6J@U0RF@#038!Kpw0X32hFeTw({SHe(T(?zre22V_s=c_a|d6K#3mkCV=5J z9C+Mofp?g_BKk$e4ln=HiBaM2YH8;m4SG$tt(Oc`1&tsGXcg31b&qB`VY=9eP9DaX z-C0`6;AD70C=GlWHv|poh8WJz<393>KGK>1%|dh4xC$uEXQZ^0viLOAGiDHyN*qq| z=Z7S)5Ik`JsAJi2uNFwi?6E%JNWp^8 z4JseYeC4e!%v9CJf^2^FM@ zLCI&La@1of)9Va>TgU;vgiiI)Rs%YA#D#Xt6r!KCL*rxb$1VX`MypsBB;q+BwE}(x zb!(Tgl$Llb(uTJbY5e=SA@1i109QC=JJ*G)-Ukc9X$CiJ(&XlNw5w6qyW*2WIe>it z!har=Mey@_z%7CRSQZIjnh!{-&^`7syXjj}{&)~%kXay@HzV^) zR~JvJ;{5`sH74;o)kltKGZ*7~3M-}Q=zqGjWLzUaypDZ!QL+i0pJTzZyp3btL|q)* zJ>Yy4z)M0b%=9KWh^)73QxiTy#(JYr@r{Xa<`{+Biz+b5uwE6YD(kdP+5eCOJ`?Y- z|7o6~K0#Um7YM0BQaA8cGmT(O?8C5%yBP@hE6ui=$p9q9o&%CuMV0fqZmNs^)$+e< z^u)2+hSYp$8Tbn+l!oJU+d1Jw!#)5kNMU4Mgr>WVHt#NfXBhZSE9YGUI?EXFf=ob{ zO9Dt(kRL}!Iso5fw7F+yOCa_Rz+KCe(q^FvAcZI2qAvQe;s(;&tShn1FMwo>QwivIAcaJ>B+mLk4Ijg`ACZ&^kSLO z<&}1!|5TfIiC?DhoQZLD%C=^z0kq<8uQyngV@OsCNkdsB^NjNOo_Zb3$?u3u=}g-v zb2EFB(S+6X#1L#&^3;-(utnP7H&ood4@TcpCoN`7*iYlB9=74RB6W|u;TFXVBWO376)DI==E$jF?Xfz&i&T?VtDE) z`XEEpJM7FnkMCi9j6RttrB#UF<1ZeryQ_jwjAJnz?Oi>SonqM8?3LJfXW2IIRJbh+ygGn zf-PbMY}qA%(``P0#m$ZdX$R!40^#YL_I|sIZf+`=NU_xU4pbdFxdX6zVW`K404DiE|G2kD|F8F(kWq_Am0!V#;_BLqWn=F9R z=659kxBToT0H0@Zf3as45{xP_sPh;EM%{h)B;FEt^ReOD1v?YqS4*mcxZ!&Q6}2He z6b+MmS2baFR74R9Yl?Yo^2Q?3GfUS2j5S{A&oK&@a)5K-jE^ZU!)+$?--%7M|K0g# z7I6AUlhzBP0@4gHR<%fMyHd0sToC%%nm zUe^PRO)_@rffV=aFVak;U7Ks#i-P-A$DgnuXpbF3K0rBOZ%-GbsnSoQwD%%U_U znK?=5Zwrw{sZOVj&*CD-^x-d;pQcek{&ece9F8La2v}nTOlk%2I`?=;+NZHzYC5xO z;Uf3cXgVQs;}91D8p0x7M-Pwxe9pgZ&tAkQE(B19hjY9fKGKGD*n>>QT> z`MRZq{uBKj=dDmf7lNoXEN8Yye*wx>qp6ZJ^$pz>SAN;RT2tF5(F@l$yIap=mv2vTjYn z(@Hk!Kr2NYP~H&pDyj z#r03QS7H71$o$*g815oycm8pqo@c(Ktxm3%dLiput>mhhu?}EjjO)(``tznA+8U>M z6_1>#6q2Bdq0R}{K|Gg-b;nkd4WCOZpGnf)`Ld-=qAU${`8*m*+Gt4_ zu*#5lRGYRK5_Y-W+Huq|VQU2Rv_HAl`y8pan6qR<|KXeKH_WFCVm`ogz_AD^7n|do z3;#(5;s%r+qybd|NV~u$nt(+!z{@uQFduNN4Jcv(#K$T6H!;A86ir$MZ}yXlE@?0v zu1OU-C+@m-{ZP}PN(8vn`IoFzQp8W!iK4%Ubtjp<-XZaDN%#(cWbB^ibm+KciKEQ~ zo&YBBG52-pmgj$28b~8W$uPiKN~u3VU{K;Ghl3RQtK=p%aL&f-Qy>ia?h!UYCVeWb zslS$*=awYP3Lw&v%=O4aL~37_AQ8Pxvnja}5X4zWH{gXl|CK};b)}CNZ7Bz=vHw~( zf(5NFIbd7Cf_y$;|D#7QMi7?^^u2aNe8AWqm?Qy$1L!gVKgB&4{k41(fDYO;S8hqe zfKHiE=mK!&ztVM{WY=}9-+$u8ix(`+6KyH#h(yosi?cAP_!Xg?neb~MmH7mH&Ulbq zc<+he(rq}L!QR;3RZjqmSd*zcKc=bbg8o+h)F6cGPAh#_U6WMeZ+h?~vaIAhnZ^-0 z3S@mcI6#nix&?}l>D7q;_-VBQbm^1w@j%4En+ym#+y=xj(&4PD4R=CvQux+u_s@vC zVdb6n{H(SIaT_SGAlC(L8s`I&HgtbP{D+O;)gh^m4mAX<2D=*(*?mCW2~PjTzZ{EZ zfS=3+aJEJHSu%k(Y2X8zT%h3qY8>=a$5q}*;Rnm-W|`mst|1|6>jYIrNfPp*Gls&p z#$_Yl|0L!~@=Df0em-kiAVA>FShj0vO{<{>tMY zBf*gzpjYixb6CmvA(`^0@}IxbU9GMTz(GQnCpcA;lI~dJwS?@t-*#Nf zb@zJyJL3X8-t?^A2e|c~uOaH@V8=7l?IdKV^zZ6n8?n0A2XKwJ-U-cX$^m=he?N-2 zbbsjlAs z+@Q8r3CMB?XqI^NXT+w3R<$X7r_o&Uu{^(+{Bom< zCO;R)*8ZBeG!3}8XbL7krq)`w+a-ik0kpQ)i#w$0H@FXA8a;tuAgjl7K;i@HoG_d) z81m+rbx=wD%g_dnLz#eCu@6f*l1z`B~!t|@+{2|Dhm5@66S7%oF<=!R4XM_k1H8yU={I|`6O`OUPMsN zgwqOOgUU;A&P~Zi^&JUd&G-iSzc{`xI)tq%p;;jyxv+WppU#0gr&_&8btIC;g)yq2 zQJvO>Wj>_hE!yl;bxYU~cmc!B|f}lr8fMh!K{`kbc<4AmJ82PO+ z61Z{+-9Dh30}>XrCBnLD)B9!uffCeJK;H);e78w@DE}Xt476(ns>HC80REEzPPF*$ zK|keyGsXd&vIM{;0EQ~jfl>LUKC~JFyMb5ouId(#sZLSQWCsPaoq7&Fb-5#6?A9Se z1w@b@lk=4VUlE^qmYt0Pk*-`5E{=n-;i&FK;Oe6O^?ak1;&OraJy6Nd>#4s_0`N~z zFH;|r8${P>?K-uTrjwF{v8zq=i7>%yp#K!P6(3JPWmT#Dc?lr-6(*l>y?fF!X}kUL zp|gc5uq4NHD9mjN{e*Yp!b)Fx4p`meggpmz`2bG|Tp)@YJLBgcL`0H7+fOn2>s3F} zPcp$bZ4;yq0k{#+#1O#ZY~Y?i4&e2OiRXq1z~esAUk1@fq6rWWtQTKwP>>R8(C7S5|GQ=+ z2h0uMLs#6T9FY0|=L2@cea=KgLYsfTnfx&Pr34@!2;UO?Qy~B}1c3ghD+F3e0G$pX z^#R;C84>?zo7mO@Vc9{m3myp&b%%G6uK!6Cs79Zh7)WOE^<<)!p`%n0!Cqn_tSirU zv#Mc^R*|TUfnlcJQ(Yq~A=xx!znB}o6TuCSq2D}hiu4?!b zI^CBkPM9YBA2tVx`*nMzv?YzA5Bw*^*$Epm*L_t>dKX+dQUTuW=)aqi0?N5SK3VPi zT*5^Dd(3w)rP4I2Qk#H%abX^7RS0AG?#oLVME&6%Fs3OU{ZkG|)+VcmRe#E(b3Hzw zJ0m7IZchYys?tXR)BFA}C4;**|D_vudL6*LW5A2s1o@fqvF2} z2ukyM-rnKRCzg9hqv9(h=pavbTGfk9^p0u4oU@l6u+mU(~^>25zSWkobV-dwjr}h3JBOOl)(!u9H!Z z{}Hj21n`rM{;KfTp~)|VKxjaf0N4hT5`2<0iP<506b>{IEix*=C3$0=ZacyEv;+X5=b*%YAtCI8d#=$W zaIpAS3~=%V>CUE7iBnoSsatnrp>J`R0tOXcJ%x3jFChnz2F5JvJPj|OlqQ7tnDbLO|G3fplyj*_cpLe=My{wZb z^H{&>i=0@oO)cZ4z1)2jURD0cO_y?8caW*NdKZt#0&s-k?6J^)EZ%`r?F~5}+c~bp znBvQi9=#gdny$8gUyg+ySDIFeaSFYqr(4@3C#7TUIUF9otFqlb8-L<#W7_Fy(x%*` zm;dj{1Sxn`;6fr-xv_dB?){$vN*Y#5V&XJfJUz3jH%-sM*HTt3DQK0?h*U?NWUjd_ zl&a+b03ZNKL_t*KZ+n7(_;b8ckaUd&$Wl!!B(Z6s*Gy(Dx>QlbdUS>{9>aog^;m0s zfJ1H7KmrjqstP^Y#}S3R@aOCM=KuV)nLubF%)NlL3Pv1&qQBCBk9~C$z#q#T0@CaM zB0iE-^;hIahvJlOpO5<-H7(GNaRGjEDo4$-dPog%&hf9W&Pc0;faV3!9BofnIE=ah z8L1x`?l(Ri&s>X^&cz{ND?wTJKOO&-BL2$}>lNrPMLM|<9e~~qmH%oQPRGx$#GPM` zOzoNuh32uYrb$%r_-k1*yg-_fZO)19V$U<4$w!OG=9&=^HKB{_*0`3GJhWh_{M}l z{~qoF^L6ma2O=FS3E)2o;H&slHpfXr#R}_7`R~zRfl}y)v_ObK;Q+>zKi)gb3Wl7K z2w1iN#Xvg0NeIsY#sN~->8`^6WGm0lw`YF5`PQAVxn&CcLoFq!xR;D$m}pgyvf#<;5YhB|=6I{5fu zt+jcmG$cIXSGpwKSW;5?z_VKeA%aj2*dJ$|`T$OQS0x}ua8Ssl+cWk7b5`At@d0!3 zwB=s6GtT)>V$k=awv1)0dj7*q-`E9qcbFBF23Q4?R6qp!u{5yK0sLHmgsOKyx79ZsF%77oC(Q@wambqdA{%u8 zp!7_XL~%q>b0c#^C0aSyAg_W-!9`;cyI-blZMxoPV}3XZvhW1p;-6jd-tI6go|B}8 z4_EIbKFLFW(h*eQ5TR4St9nkPy=-ar&_Sw1TBJ1a%+jTS+5{x`L!cEk%Hq{k6)~=_ z^Vw~?obK{Xu09^Ieuf;dw$}%wIe@3)?Cp+RLHTwA@$bg^e%-Jj+#s|h^83;O_#A*+ z0CkVY`Fe67ps(W7(x<-3s)oa@AprhX$q#07As~?pt@u@j7hUNixT!j$;94^jDllf1 zmIuL$?z8=<6xS-%&$ghiaId=oOzF^xu6(1e!o{6REszH!iCyuqXKfD}Z4fMiY}uLr z@?kM;x=@1QX_I4gS^7#f-UlTTh7a^S^*GuPAkfz7^tw@J#<=e@M|Jsa*O;%C{AocW z(TedUg=7?$@EA>MrF~dEFJkW*CZ7^i9QFy}2xZ3WUs z$;asf(zB}Dr`1eL5hOAIt+tAreWewELesZQ&k*Rrg*MEr4Sn8N-)AiPE6^+G>rng| zO8|cit$Xg78>o)~*HtiM+hDx*Ur7M}NdR9rMS(7ijjgy=sD&H2*htP7?Z&O(KhHIB zy<7?9UQn06CoSE!7H~QLsGxNlUqBV<(4+$K$wS&rrY9`;#REDqo#|ZgC536=QSQbV zmxxOJ2?93>MmKg3J7_(=8{R5*tJ~OXX=%bn+kNH8C<1vs2e_2Q7a1nApzhwpx{1sK zeF|Rg&*9Dl$)V2;8z6ptN=x{UMlt011!P~%=>3O@fbISyRr)?c?91JrkH3rehVP&r z^BHw5kki6r3wTpTSu{VNeya||C6Tm~0h$aDPOCnEMw5z1X}}L%ygCCt2h4~Ct+75} zZ9M1WBl4bEz8(hId)HR@k_ng$kPqmOrU9LO9oYRxf5Q&ok0m|ywEx*U06x@BEzqbB zfR?<};{LTqk8V7A^mfc`zZ-qP(!nUw7MdFP((=Vrex@yH>8~d}C9Vt`8y0-5;XnBB@Dg10 zpXLFR_e0&_mNu-_4bQ7uiQ_9m(>svnZ__JsZ~Zjx)E#d3?6PPqC>fw8bCi?-Pz3EV z^in;#i;t<0n4RR3Nt|%v1G+%ay21zizhUjah_43?^8xmO1`q@!GT=_x2HYiqD-*B+ z0sZd>b0SVD=E74BNPWPiNB}QI;s4sBN7o-cx*dGZwfNs7abk(6WCOU{MM(^>zE#kg zAy6rebVn4ZbT}&ZQQV6)702rviCyRhkkVB>`}n)OXdH6!nJh(rsWA7I6s5nizU)NB zEV{100O0avPt4=E8y${7%+BZub9rm@pFY6hh{{IRsGUNm2mNlDpF)4K-*KX~Dsx=R zyEQ_O$VpWR$po}Q_Kw}xfS#~>50vRAJu=uq23BtK48Oae88IaWX{gV@y?O}F#ll%ypB8e zLmvb7U0`qkV~3vJe|rbu$@8Zux8I9@-;d+Ha@3!{JAT}b68>bIRhUEZp>DK3;D{+i zFE&}EgfVZ%0d;)1>AOJ^ozRm816ETJR#moub+qtjhXYo!AyOxsG|s+=hVZ>*h^XN9 z!&$4-)CUWkf!Nh97+-jhT(8mNr`m^j=Z;qn6S++^@41i9q-B$yV-UqE2heZvKKtZq zB`s4mogDYPMM$tXs;ye2I~cbI z*&ClS{P_e>lkE6Y3QVr%&O%SfLm!h6_N49-Dcpg4Vn#VY4fL6Y1?fU_3Q8pud>id4 zSdeQ&yE$O3l`J~_J{p(y&;Iqm93VK{4DOrZE-{}^Ygr4sjv7hs`+Ab|+?2urpI?lImi*{BwASJc_sQdYV+pI5s6^XiZ zXEzA6%FT+W5}qQyO532^2hFj#YP2^7q>S0}0Eqkej~j~lz^9!9&*Yy=6cX=S2jISMj0La> zKxRv<1u%cLXHnrSkQjM zg4hTKEOQ}FuYD%h5p%HL%4A&_+vA=Zn-Y}dx$0^>nd@yVS?CbRzAJgq4j~)$IkGxd z=380ZPDe9nZu_I-Kr|fkU`VSjeMxsRka4+sU5k-MntNDAH#hchk={G9znBsnNW~JnJnWIBQ1ZLMP7Rb@W;=y%xzX|K z&&CrI1F^06KzJL`MO}PjGe8hKqLIKSPia?(dY_@^wrDb-0znY4ZsjIb=%GfQX|7NR zDv~+KVO4Jl2y#B4x;n47>uWBa(y@rhOBD})YFf{9K>rE|5(EVP;|XA50zkeIe;X3` zPQW#{9zDAG=+PS`zIP+LA6J`QLH(f&46enQpt~z^sa0~<=XPYw-=x+pgb-nS%>SJyVd5DjiqV$D`zd|;4T6C^Eww%sorB^LT zVN;WvrY@d2BLLKA2*&v|5M*{dgbo!q^di1YHk3NkY z@J__jH(L&HcxNKS*NE@`3XM6`V0zzyPJO+xO=ID)lg10tT&nkEhD(wjF$Y)T&%GY` z;6}?0Qk1?QujqxQ5+MONh@Vy}CR_!#nY!nQ4#2N`Z74)Gr}9v$f6-!F3Uj;Gf<+=E zfd~?YlceZLEMN8bF0n_!;v=xpLOl?lWOq#Tg=fYb-5>fbXA{YzE&^L58$plL6> zYX1ozh-ng7a{zyj1n^r->V6d*069Q?fO0?u_h(54Gz5zN7}Tt5H717RiPQ7-CT=O^ zh_gJ()#mHi(#BGB+R6UxN;67(F`mZtNCuZn2cYxV&4udFxyumKZfjR(y7Mr=i;U@& ztCXk|r?&N4jpv84AmPp_zAFlhrHZazC8_V}_n#_49RO&(y^3y{Rfax+Dn}FLtBKu6 zXUsvtRfZ|_`$i|%x$5*_{OwTViVipPAKuB-11;@t1I0(tFl_Y^ufvK>yS1a$SFZde2{11Ef>=`{rYr09?1FMUA8f*6*>>D>XJKbn=> z(nkMBA@335?*stT0Bneq3aD}b6X4I^sRQ`!(W5V04)`*1z$Zg2=(Q1Qca}at1gt{8 za==b&0;n8g()kOtDW^zKqzLWytkW6LISKlyJg@_mnX1=g$MtFN6?l#!8{%VstVjr;i*^WDvCsWO0|KnY=Fcz~TBoV%*N=0(RQcfP+G; z31n+q-P>H3EvLCQRI?)Iu_|IiGRrbg#o2Wt?%-RIQ5hsFHwDMXto?=T;Xb6IM6MnO zdi*mHIgu`1OlbnOtL(kwfeAHA>`qttI!g}ly=lovLm=CUwxFUL{eAfd-tSl zD{bUTUdQW(@^e?1rIA014za`(h7@``<6-6c0(7{pnN`W}0bW7oZWo%vC{s=@7Nl*j z5=Jk|T$tg}-(8fY0(vHHC^|@@deB%(s#NYjZv|T2#E2%{xSu2|$@$A2o?ZTt#*ut; zy?oYW+N$nKUP+_@>6-9fO%~kF=;BJ`2oFJDSyP`QHb?lXYLNR%#1|1No_oA~Om=|` z=q|1Upd42HtJJu;wMQfXUj|U^LhI)Diom2wysHAJ51ZJaBn_I85KgCA^*#03w8L=? zo*AkAyPIFfIAL|9(pcZCB;3E;uVaeu_1^uIR&fC7;NybpM@ z^#NT%I7xu64r_mT=wE7v_`6#B?4suGJQ0|CjUB4*w#PF$W-D#i#M!@YXhrLE@$vS= z4z(#?5)x{MY8lVv`qWUB;fv@*PB;ln(I*mBNYvg&JYchG>mQ{LNFuJT1!=cYs8sMQ zY;bB5$Hw#kg?2T&-0A2~E8u)U$^oKq{`Hq6fQOUfA6CKqFun|6-kmUivku^^0D`zN zmILO6fY@dw(4X30rVB5`2k(vo$)q<)$mhx~7k7@`8s+?jHv1z$U%$JqEO%rF?+LS( zlVfn#f5x#?hf|%yU?Nv&13a)V)O{wN#{P)@r;T`Eg*|M+EEQLOmWU@zQ_kfhC+nXznKt=XJR$;D-f+|Ko5s14IfRs_ZT}Xw0 zWdg>^1%K6^15#Uz!0Avsv8QW)AI?_}z-~*4b60$JM<08DcE+#YM#_Ii!;k|d5*Q<( z=}iE?{JjzYq2CYqfHWVF62R47?SDCPfY<&)31uKIsKjj!tM|IjHtPMf&=J+p<#;kj znsFxcpPD*$i6`zQ2ikhYeR1h->=if;`lm6=Rb@IKnE*eYK=P(+R$T1S3567pu!&9Am6ZkJ~#ZA3FGd3}1J&7mkH$N&tGaYDhsVz^DV@?X{9FsU4buz zw&!G=K&%QNf1uAU6W>G>yWlhz6Evr(o>eGd^85AL{x-_<_!@IFW8upaR<42DC=t{<;mgpH$`~`dW8l>cB}xI zB)=A|rxaY;d#v&DGi}c3fa%H^=XOOxgy9N<_GoNyQSSM+z}N9V_>=Ckkq3c6HQ_YQXj@k^I# zZe2Xun@t8Tr)XAL;XL6Enkr!THV+9ko?;Gabyj^Vbzyj}0tM33+ho83nv?Z$W?yVN z2cmzP+nl|4_p*`Oi`WFh1c1xW-4|%BVQcA~OtzzFczoH8x&b-7>SXW(%RfzQ=;YD2 zFPgoe9Gu>Y<7OOh#rdX_N~#h~U;zaA?oXbf3y@sJi$*BzjY)6^*F|9E?x! z!@nv4Jm^`0>QMAoO1RSue^>@U0+`ng^lz2`YUrQn1Hgi6^yfOS(f>@tf)oV34@jY3 z<-boz`37L%qq(^7ZpL3f-YP+^K#4ul7C?*)V=R^4$`E+LnKq+`u+do#*O#x3M8BW;XO!r zk8m%3Rk1ock{5 zQ%IgoTG^!`fR-cr<_iVWXOOE0uKuL$4cY>z1Sm?q6`SfGM@l$5Yy$99aQm~WkDXp{ zy{M`sugmHs5mqjwoy~$qBPEqJRm7>Lf!cj)xo?ahl$JTBkM2gu!~npx~zu z4g{SlIRJX}!=V7pMR=9#??fwr8;qnt3H@UoK-vYnvs4nm_jaVvub#l?0aq;tNbXIX zA26SU{Gjg1_m5lopUB$2E|knw{4Vtw^8N@4Z?yHU-E9V_t=eR{$CGY~+x1lZcg6sT zMB!81x<@J|xIzO#0m70e0RGpr4f}#3;?63IO8^xF&?IyAUsY>E@qZY&?EqTC-=BV3Q%d_rRWCUh%4~D_$%W_mXjFOaSRfeZW^O2fQBw zJ6D?8^TmklME^APJ!R2fVu8fLbQAh$ju@Sw+nOZSL=bsB5|V3ysR?k9#E}h@TPQXO z7Gw+8;p*Ov+#cQmxK$|$Acgp4@vkHRcZ*$+!Fo3YINf_}kU0GtYPINUeH78W9fv{E z&|ZF3%IIzzqS=5B`4#W77J-co7lT4*URIqa;?la%w4UCJCIALHPCjr(JqJj<+BGT! zUP)v$Y12A7Y_tk6{-3&^ImdYGN?c3 z=72@?0aA|J8)4+(ME|)6>)-b%KtGr*jI^M;31AxkS*jhtbQ*9h=!4b=T#8Tbe8c@y z?N1|*tUt#oGxc>fO_zK~JnkC$buaCSXMex>#=!2^n$=3XnnmiMj@ukj=4AW^Jp6p# z6_=v^zGY2r`QpYFbN9;-D!RB#g^* zz{!Qo1I`2lbgsp^hmZrVk0gNqwAvpQ&`%?NkkeW~9Csg^1mKxKSkOn&iND>30qB7c z;&la3`@;nyF|ZdVx=t#=G+|37(GCHr4kc9WieLDCq@vRi2zCwk!h~rmViK)3#Knp* z9QUmzq6v`obxQ7{F^ybO7rGP<@vn{=_K?9T$;D|wg1rvlBq^8~=|E$cGQWff&Nw|u z8l<`9yd)X*0YqVU(^Njtf|zUmXm^jfE;u_R(bKIDxDv z8++3N^#@g~LMe@%I5y0mFFpkB+diSOEJD36q9;UXjL6^pG`oz?^kcIW2WcUoOGxeV zf_Ajl|MWtR??n!HBXYpY z4FYo9pW0u8ftTZsm02vS_c_L2( zX&YIO^-9Dd)ob?9uWdM(P7E+Hcu)eUE;K%6QNm6FByRSS6rOc)PNadcPr1qk&QcjT z;W+goY2z&I(9j1E(>ab!9&Gj20DiSJcbEC zCkxTgPlFixQB>dWG(Q%m!CDMCJ&gVr;|I$yy zFj0_Lsl3SL0f(QAbcg6aG`{B9weH|!ZF$i!v0y}j!Yf8{h>Lj9P&t}uEbPmV?)+ZY zeXCFXENNi&i>iB(B-hDw+0;GCr{m1L6=8wn%6!M`5p5r40{GrSKM$Azzygvv@NdNt ze#S+xxh0eUewg7@l83$^qPU8Vu+V z4=;_&wnt#S7-NYKo6;u>0q`+a^uQD39FUVc+BDqPS-0NBH#wvREU^TYz5Gtfd`}xI zTWm_`&@?A+mIRO{0W$(YmG|kJU&KDmep3&W1mpa+Pk>l=T_AOJE(7j|WXhH+001BW zNklK7ozNV(-wp216VvppU!0`G=C+KNr+G42o0juIS>{)C?dJxLb z>FaI`fv+`1Xexc6f60Op{RIIf9f(;Vpe2?7Gz6bMq!NLPtf;l4TK3HYPN{~jn7|x04>%;Ms5wrw^#W-QBVD(9c#s?P zPd+B~Ur~c!Z3@zFv~GZv&ez%&&!=&ta*xpm&^S}*$>%E>uP0w@p(uEPosQr9 zeH4QyhpH@Hku`!Bq#YQCJn!lu8AcR6aB#ozQva?%295z*Uq>4FGI9XJVKoGhwcm)I;7Tw@86Cgg_?j^1VCFeryKV_|hrmy_ zm97(!b-s;f#2*TWkg)_nP^Msq$Gxoq^bXN_P)oQ?B|(Y-xoHRiQETsPB1j~L+QQ$< zy;=d;3HQN@|Hzt+;8hn{bq*cQcKJ!Sjdc;}>aLt@cD%?{@~A@v?U!LpCS`9FwqJ@& zz)G-8q$NRmEb0#!VyF&480AlGqLB}j30%8WQv`f5p&McU@F85T;Z2d@Uu_}j^0HnRl zFaYmQEFq7^>BZ$O84V)Djn>eKCPYCd;7@eipbyav$d*7eWHqeYOqCk>3RaYlwyXdH ztx8a=u{_$XvXdXDt5xeeo(57eUWdbr0EPTNRz>Kp+GtG-E0#h6xM5Tuc>p9q2z3DR zgM2(8An$#~j&z#%d8Gj#5|9;03ExIg1}yrjO^-iq3j{AT+Mja))jK-`q;A?LW5DRo zHg(UJS_|@O1O>zeH^k466*zc}ZE59O;%|5YAn_!dJzwK=izsZ0lPAoUws4?Cl4`em zY}gYWNa#~{NSN$@wHddi)$GaBW-NbxRMzI@Acq(v;T@ zupKy=xQW!XmaAd$ud{d8FXI-&f`x}`|oda<5!!Nl2(Mo2=qxH9klNW zJ0P<>?vSl<>z<1ak?PPSoa?>}$5fnLlhHTM9yQDFDq^+!yG-xkdj?!;2H4QwXW2+N=vU0jZ+O z5P2&w7ISMKpu@AQt1qNVVtVy=ULDZxMKbnbb<@C#xw(JF`FX^@ZjF?@5&`93wFgi; z0L0*ydA*LflO!=Tat{m1x@M(Wq%&;zC@=i>%A7+BCZaq~!RMx<{sD8vHt zNq|O(&WKpu3>VMD)Zv?;A7H)0MwnK7>#?HoUht8ZnV*L?mppTVjr_P>W=QuN=X_Ef<7{5oW!lW6lBKf|piXUK#aHJ7ZUy0v& zaQI?iH@Mow24g3W>G`DnK9`8_A%V<|Q!z1dMd>?E_w4>m*L}L{Ka-{r&qM;)^9X}K zT|*f0TwEeF`2i#*=)?eEiFE+;CV*7?6aB9ZxwJg^H4-LG6K8>$$?Zn{#N6XlGtYB* z7O#?=IOsIcq)dQA@20qckH^6It4ITE2B8kUsezKU?4rh8-}KzKw)%JFh~9$|Phx`l z5-eDX`2I>5>zlR#>_C?qz4u9gYh83*%)0fakma?FWGVW;54~$>@BooKPlWjhyKwsK z*fB9$NZpkt0q8JOiDT+eWq%ZTcQnfpOvlimhQ7%XugZUN0G))$pqqyKC|rSfK#~Ja z#()7eDmj#GEjwkt4h`*X<)jyUcUYpajc*C0dZK=6-7>$6C8p0MrKK+DpYql}mO=u! zGok`5BQU9fdIz8!Fz*cD@k{^;^w;9N0POr4;hwn9#GEsA$IjHB5%&)VS_(%~wZGR# zY5eO6K=qgEQ!U4DjBfo%WS7q(0Wb!TMa-I!wwEBtIv8;TA`oOy?Y2niLGxSv-?Rg@ zuGaw&``$;_z+9Vs{jf8 zmlZJO|Bsdc7BmO`^D#&O!us{6s{Y^F+0i#C`EQwPnxCdW;)H$>MLPbyx?LswITrm> zCeXs9`p^v#~Op0_pu>*GF0Pgr9BXEzGbe%1nd>HzpLK|tdB z>*v|9-5pQiYM}Qe2c$`WxTiJ8$WO)-0NM{*S_7nBr(zVTDonDeE^wa&jk{T-P8alG zMN!L<2b{zqv=gAqNtHy}LEF+;p`HftCC7Mx9Kbw48(}h*;k2l^5&piV{kFr+?G9U{ zBdw+2H%LH24S^Dac8phzGyz>D(S(n!p1IQ+gBhnoe_HjbnxIK6>#0Yc0>l?YRN<6OAPZNrtmGg6?+yVuX-YMz7lt(h)s(>Fr-tvMZrf=w zm>d9KQ-<|jwFy$Pd1xi>0vFnkE%n1q>2gamcd* zw9#!wSkOsMT5?H*Rrw%^M%2OVM2lH*C#MLHMf{0lWk5hnA_4r`6F~s^akBgM-Xhr8 z>^F4)cb9Ymn5g~v&TlOTi20-rK+zv@)IS3J5w%XMlA_kB_Lna7v>Xs@eJ0XYCecGefFf1I#8 z_-0b^lm^^xbDr5h6blmmL${&*GE*+n@~#e=&!d8+b4lPP-SmKJuX2NQ8kkPh9Z8_0umzRyF~(*F%aGn5&V_dM*bnj z0Qe8T5YId2mH14n5O>Gzy3+=sD~3&gNT`BsUCC4~UGP}C(EIFVG z#iVGi1R!4o_>N>^!Bc6vkiefVR^Uwku|4GJ1dyK8Ii`tfMFQAr2|x~x8W;$;XE{T9 z&T=Xy3d^Qg7?A{`8H}?|=wzo9i&wQ}6wF~xMD%|v(549)Ip$gQqWHZ0o5EZW(II$ z$+3Wb?hODE@(Lhr<8?Q5|ow%txe~mnD+;;0j6Uy)b&2<$a~Hv?@-!NRE$!apF~FkgP++AQE@T z-DWfxU@9P)XwriioRW8~8vPQcg^tW}G7cx_oA&L8aeNSezTKosSY77u#bZFN=Z2@E z3(9*GPA95Tu*S^dxf1--tnV%b`iTP}=zVibZJ0_ui$UueVKLxxvgL2fc(B z!Nzd^S)zYs$nsC0w8F}1(XRXE{;LTBqTkm{SZqA6of!k{jXLXtXacUZF~Fg?yO>SY zxbsYtgxk?}$K2G{B_A}3)C?fm>ajg0g|^vOmOSR4tkKbytG#y$SG$%)(j{hEoJr z0-*dP0SH^04$yw`Yv>pqe+F>Jlx%Quz-ufNI@wOpP%_N(Jy^LK_&%*rpp9+Zr%A@Vle&eXK(5eR9qq-$Cjqc0g%%#u z?=dfdst==Npqc!Hrp5F$xT{g)Il$Kfv=bl&3l|+qhdML&^%Vt^G(Zl3`9m2F{zI!O zgO^lmduGyd7WD+$e^{cv7JUFhRmi7*65A@TMS&tY3UvdX1AG)*xuKP%3mpy+?S?f2H` zuU+4Hqrd+AGUD>?qLT&vpF2~b-&+Bd|H=x&c9TQP>iBKQg1#0v+to+_XW~11S~=X^ z1zX+j*n>^5lWs$Bziz5TKvDwm8;?1#TmgI)V3|GFCL`N)A=*Vpe@_4k8Qlmg4*wmsHCkt5NY7m5W*q{eBBh(zld)2<)%s`Em92zcC;K&DLVD!R7O@(-u9W3 ze{hM!nf|Zb8sK?pYmqcd6CIt|oQf=}cqS0P!V`*!Xa+vXu#~F5C0SWR54wA(qt6SpaXt|94C5NA`0=Aw) znaPDH4#%bVW|YSN4wYPtmA-CkD<@kYkXixO7}J(q6=O(gplj9ZZgHvbPxFH$b?)hH z;$YK-3wx;~fM16amU`eD!Xi3q8MtZzb&uOir33h};QkY}ze2pCzfMF#emwe%S)moM zGyw33PqF6101XLJ0`RhkSa2{(DohBVV`JC1sx2AS5Q7>TTb)Nu`^DF_{FVT>slsYn zh1LD9ve6e}1rdM(`H&z1wf7h?pP4TKFg)MbFb5Jq^3R!|3?}x-{oQEmt|mDo4b;Y5 zmqe?QKLOVMU$k22O@QP@cNi|@6JT3G}Z$O5M;-HeOZL)!&+kaB0}CH_qGSaDZ=?hQyQ4QiDB>*!wxrq_|r9D>o4RCDiT`iD_?Bk=-98 zEXaSrjWQJD!0`_R`{Kixw!IOLQH4XMyv7>tXQ27L@q$?_Vhq4g%TXY12_FLpa?zbb zi04QvnrZ?VF#4vLlFEH-0(75up%~uyCSy`orQ$J?eyv9D%Pa3bZz}(t*~#{@bo0Bj zN*BFwqJebfoEpUEA`@WI)wCUw?97DuxGkvvez_UbSRgz2QXoQ~My&ZM{`@AY=8J77 znO4AgqHE)vbfdqgVV44QIk}nu(w<#XpH7I@nvw<*(U#hO(^5+SHzMu}0&>3-mBqgd zr7cAR9qRx*D=du!a695Vm427+pK$+#{M2oTRQrop#~r24+86g-?4c$APZDl0;!+1| z8;o-@4E&pfI**wxY>kAejekX-uS{OC3oSXyyOhV-D~RPcfI%t0e0BJl!0SJhrq+pwEcU z!dHLE2VShu&$*ScSHZe&U4V$+tOP?2VA23v^jxHYuUfIm0^|8+Q=^f<&e8|e)SJ?P z5<}V)^D#yxu(_&LGHUJyec3xp-fqct0Dlw`ygNinBu+B`-vdadyoG9!X_{!BrVB&yclL4BJYn41JWpX ztoFZ`X|_L|E6uGPqAPA*Hbz@aUb|A3=JFF3M9_DMa-{)*mg)=jOVsK~o=BJyfTwm2 zNC4V9L!0_^0F@uNxbt0vPN-{=Cqh#Qn2vcs8Vh%K^eRoLt`Mhbxx@X+m)gA1p?ysL z%DWc1c4;Mm+e0@Pmj+@LfX_vi01I-3yhkF?Lrnm@&_COWaOCG#3+}}C6#Z|GAU~=0 zmk_SzV=nUJO@JQMe30yF75%~1Sp_%|wg1O$>E>kIMPqvaPa6cZqgl)HY8AV+FO!&{ zv=m7i)2meIK#8=<&AGY(O=%_g{^|l%_P0k^62O)?Xy1*#ssB zoQkQ{hqjCKVGOR6128O8AF!caezp8hJwbx_YkQPYI8Y!#-xHyqf4#jVAfWWDKMnc*j{Im8UTc4PpD%{Uk4Sa8RjT@1iuG00#lMpb zVO(+mB9NS6zKlKqXP7-@w&{UJzF;f^qgKrvSVW+N0*(2k(`!o=jsjEIaax`t`sknP zU44%MbY5s)34jj3mz=w-{FG6~1_1YKpII=sc${ATYf$eNiDNsfX`R@I0s3u902&PJ zZ1GoHTB3&v8qzdNTV|RlY`0860>FU)EBV7Mz8`AR5g)bC^IeRuFe*Swh#Vkl(B^m} zRY|)m(UF8YJPnB2FB*>&4}GfPa_IUFO|ufGARtt*mP!Jci()sifSd{X)3_SMv?JKP zi$ec32>@K|*CFzAV}@-nqW{qm+~1-9TK+r4UumGeCgxUCE~F!&1%mi%0jFMV31Ig~ zR8k=f8Exun&S0dz)C0mW0m)OYKxM7KR}7O`8ehD?mk}9Kcu@wvxAN-FZM) zL!yp+E9RpFIX0P-;-NrYPX_Db-7S@`pCjWs5s1gG33_eB7IB8a`!L+S?ja@w}HNKs;3aPBI_9TEx?5W?*D?hmiM+ zzvKyklc{*EXiJq%dah-D7woPM!&(i~b*Q`|<~{*e>@~stPF)k@Q<*?%K!OuB2gpF? z#fbYax8wB~TzwKj=acw>o~79{IRNCe&Ce76ax1lGjjPpb?*D)(w8(ObO(&|=-m zxh3;;y%B+208VSbqyZ-aC9{*t|G8g^K!0Tdpnbbz2Q5!G`roqJzeayy0>#{MTXfAAV-J8Cz_CdPNY?PI5s(1(**X|eMiJ9j0bE``iL{8QE|gi? za8A$QO;!J_d#|i3VZRO)fPm-#fPkKvVFSP?z%Da)AK9NiDRJnZ%LZJY35}QhV+&1g zTqVthwLKI_C^qs8T+CP{*9*0aQu?Bqe%sbz4nR2ia9n98Bg&tR3-y&q0B;5s^ifO# zUXLG84mfC7kSr(Hl+LW%3V06aay^~bq(vMZg1JPR@~YpvfxU4YS|V~la}mTe?3F8| z^x*g=%fJ#mPP%6|AIu#1uS@{l7wy^?t^+~zuT$TO`z!i8wJrfce$)|hN&pIN%m5$) zp$Yn4%m6O5P2jObFi!xRBlI)D-ri(Ec}CaINkkw|08UwvGAQ_xqdg97Yp+cytt;fY z(D0hXf4aE@2ncI+1WLP4RJs3B>8Yl{_ht20wW_2w1paI^jReVo)RI3XhU$VTLJvCwuU5E^EVmJ~& zw~khTK479b(@6mr>9M8p;!;(kk6pnpO?LxQdv z#Jnt^-|r!G|HU1EfAJ~a9j*a)r@mVFs<^*jMt-CmkU9V#42XK1+*B0D8BFbqd*^n`1R%h!NM;9{K}ym`b11nhnqPH+LvaIAS2DXx@5mpgCLsAu-pATMMSlS`aCNpe&XVw-F{NVXygNrLEpVj{U{`aIgTf#s zI5(LQW+H=9Rn0!c0u)M2=oXg0DaxI!2pa;DVrz8=UDCEodKlKUkiWtgCzb|m1E-ghDb%Hq67G-(LfKx zHChvZ|3@Txm?7f~1MDkVP#*)N9khx9DF;Z)nj1-m!zxrg0VFLKp9d_ozOIwo+DwoD zaI+$$R_0Il5JrC=*S@?~^`$M3{xEa)*vLAmv(?QePpke~76UPkj?@+Yn7 zq=V)av@U7wn)!YJ+H>DxqR>b!o`@T4+jxXR7n93 zOWjY^%*WgCm#Y3A$A2w1J4^x=tQH6UT7m?I@)7xCM;?Yq@Z=fqT%Ur^uH!5-D?im zYJlPUZhA~ZNl` zd;7pX2X?0yuVj;Bs*BN+17tep@&>MO=V`!g4;E2bCkYBSd!c9A9Oq|8yvPX%$XTSG z0H$AnKS&)(k}`JSUeS}2CZ#s`Goaq9dzv=B^6LIDd{R~Bp6E|RW?vVIJ+vQnoHd=e zLA?J?J)@SY1hCY-0kWD@BA5@;5bPh~LUaQlLYD#{I%;qb)i)Ch207k1Ry7FsOiqF; z$pFwmFTX6oU6fgZ(_eYzj{9rtQ#7rAN36K>$mf7x4ELw@cSuEu?kvP4Il%H z_(}lG8x;!uR!=-gje@I2v^W*oJkovu6=Dil0xniAHV1Uo8hp&lUK=u~(wP}c0LmHO zSd3{6`NX0-Om;48)udF!)ZmvWc_5-5pNlU5yF_;=F z?ta66UvrN&}S(OT@*b+!Ug1v#GaT%X%gwaxIko@u^dkA4EU+4%nI1JHuG8w5lGfC;*6oCylhjIZS3R%uEIUcpP- zNxlt`rlYCsa$8zy;c;ffv-WyZ1*V5K$wkbb1Cs1}g6v5EIH@5x+zs5zMj)W7a5s%d zC3Z@RP&%b9`Jm-2B$|naggJEp4sE9~uZTK;c$EXA4;@|&(Oam^s$|3rt2pSSJEbgZdjS*D9{tx^?;hMMt|in z`ll63M-bw-aAlA&zz@TzfGDAogmV-qC4e*&{{0?^K#y($P!2d9SC3%9RPQV3Yc)pK zSkJ^#96cFpQ;&~hM+8t{bW*aSzo+3enODQ%y~RXxko0z3 zi=ukeqzy6%*3u9K7kV+~!)GlA>}!EI$>q}Ex+{*;tZOf#`GknwdQ4iHuKoF)E7~f+ zqZ7NvzHS-pBk;!$8Rd2p!1OZkqKQC{XabnCto}=U@YGO==vk+}>qq!Mj*TXJ0D^DT zf$$E%Q3$4*8{OcfxBL~$<4f)Qb}r9 z8p4viPDoeXa(a4!5Kwo)Sc}cb0qu@=I$;NvG>7?9ol4ykP5@C7x~MY!$p$X*QV59f zWHbXvG0s8xq}Q)c$_rsln2}r-^e^xymG(;NzVP9Nw#GkQHr?K*j2xzg8Wli31$?` zcMya~31F6WusBpD z2jgBn-T?p~Q4em5y9*Zqip`V&GzX@vb2e%k2v^%x-TB}fTkWn>^l{UhF^j8NfFKvs z_mQCYOgdw`;?LxqoW>j7b+A=sD&ug|7|%xtj2nNZ{Fl5HH#Hv>A>DNYAn|K`Z!4{X zX-$uh8|LD3!;_yFHJ--C1lJP!R{^3Fk*R5%GUO9ur%|}T9QF7f6B9ib4Z)G7UAi@X zNg7MIqUyS`-|G#BjB6m>VokHp9{AK(BG?SfRL`jcc=RElJ3})79i#zV+kR@2aJPy# z=su<8gUyp5*(>Peak)+fVJv3Vy9B&>kI}2qffP0t}m@6nY~T!Ok~T zudS015Tjj11c*QoPKe8N4+?)SrOV5xJjg`ANCvHb}fkSBoT4u5|YftEl55D>Jj@#xbK zSljT4^W#gB-V^v5ebNO|Ch)K;JVdt^26g))0lXJ?#euk*=S=|AjG6WN^1e#T~qz4 zF%PM*6)qL^(rT{n1A7AA*D{J2#?#ApW8bWc7s>?b z8gO0y$`?ut1c{^R0Fh!hBb@zFik*p51Sv>v$)Y?t(_i?Ks($b#@lX%7rAYpy{CDIh zMSpMKmlgyx7eUN-!Sq=DYAqc9#Rv@zmrnAW?A=|I&rVT*}Ga2h);m zV$*X5I7NFS677le<6PUc0Z?@gc%1a$#21jWybH1}di6SWNJ$_h&8w5Ye0QC=D$V)i zRz1Pah|x!yY7mOHX%kH}e+_%R>Q8b1P%HeAp92n}_TSzt(tPUc^bKbLJ+iUOzpk}C z0AB=iTVR@iu{m&!_>xUqv@^^SNC3_VIyKAzmGe`19jW%O?qI3*SELXNNH<&R>$gTb z{C+_BtSfJe-|*CY2|z@kW03#=Mo0kZ-gar|Rm0et(DMl(NL&>6CZrf=OTa-4UrOQ( zOfTQ21W?JKDu)S$#EUMRRgt9xchvXjg3LZL=?48opZ7Sf)?s6Oj-CMgHFyJ&)}4F~ z?3QgXhWEvv(*5@Hv!DbpcK#FdwK7(_WFZ&m_gf%IPpjOfiDYbhFv^!h&FD>NTiQO; zAOTq+_Rh3m{DO4@GDP#O&o1(#2TO|vIu{gAR|C}qSi4{(fNM4fPO5N<^<8!7$2I}r z7BCmCI!uF|`sq>LY5o=WpZ11KGk}DHyYLP{d`m=%_ktrKb(iNR@9L);7y=RKX!DYk z_ee!QBs;8K(}WS%VQj(yT(!o#0RUNv5ml62q?cOt*971Z-=`)XHyM5at&D}gv>)JO z0Ec4Iu-BJz>r|sV;YbLZ&diR6Z)_L_)}+0WP;XTat`|gLMZ?ksnv%x&y&q{waBMI> zwos-P$`P$J&J~}BD+hU3cEonKThhnKZcRhIe;^JNM&&z3&}T=aMt}JJsrJ`{=ayOm zxY-*3&OK1o@7csiBfQb9Q8aGs90J#FxF~HbDz}?3$0d%LqF!8(FUSsos zZuEBmBthXm1+6ZOXnXB$8j1%R4HU)W2^5F~upxfjr=?JtY+>{gV=aro`3c@E>+#H`4{}JfV+KT21-88V|I)Fci=)bQ8$RYA)+Xq$$ATH3n_5gPt z;{>2r_;y^Hvd~L>|HK5H0R6l8kK^DfeiNx?on87DV;>kJJrcnB$=fn{L!N140JgLQ zIwyN91v^F&X*I0U>eEQDa>Kn3fT1szx)`F)RqsAa4c5sctQ$J3HGDS+*5BXV^{rvu zXT`oo>r;vfBI%Re8$+Fa@lopI@ZVW?fRzArxV6I0WB!+`rC#9RgY^o4|ANBEkCokO%}j z0Y49AL6brJm?yBlfBW%H0Oa}Ko2rZ}zNM+}#@UdcM2L0{i7dJjty_gN&LL-F9gIBy z)T*Bw@9v*!V*t4MdtcZO@L22 z5)IUW;z#rAZVY&d_-+P3+}A3AWI;UvjM+mbI?$hweF9Juu)?BzMSgq(NZ4iCe9=Xm z`dm$bxnaC&mV6l0<~>m@z7+}JdGmK&F?lPp4-A5IEKnd+VsId-*mqj0(yd$LNEcN| z4vXC_Sx9~m^?>Qs3M56+I)bhVz@IvWU?eW2v)0X&UHnHgkF+S@Pmw0Z^{M>_{KrU& z&$YpfQu5l~7$BWM7e4b1FF`>3T6F-*rq1SiIB8&(9&uuP!d>9o7%GX<_OCm9xmIJ6 zaCbu(Wdc$7<~?8&NDb7Z#3Q~6@S}x(QGmdOkPDSTd};#zxZln&OD_Sa3D|Aqv+lN6 zqO#T6Kd~L01}grKbO_Y>s{DuNa3bcwXaT{m-#D27_?;jFi~-IycQ8QDROhDkAFU=R zsLftT`fZ;WklcGR!$NjRdc~5et`WIQMoQKNX-do#WPLlyv(QXagP0zy8rdgE z4T0ZH)sw(uy?@79eEzR>xyPk^ld%VqT+hdn(7yu?`g-n>{<_{)0g^D>e}}EWe@zy2 z-XdPDTQtpK~Yl?ifHj0ZC(3sYPoa5L#S#wVUH> za(&RNC4201%eSk2r z?yGWIY8S#voO-6gs~7mmTZB=m~sXI zKc*`OFobK*t89vlgjRLkl_z?FS@Oi#Z*bc2#6-RN5G3YkZHC0ENSup$RA6Vre21d{ zuBg4vM9w}P!t57~+86B46LWJ{g2{s%5UT*|=DQ)$lqLZjkE<3RS|yJv z`JnifO17%Mw$K_-&^$R(-c|dGZ>>)P<}F=Q0`q9aGZGoK;oKzxjm-nPufb!ecTuSq z@tr<>xMaTlk&jvJ)`qr^0TNuUCV+XbqQ6XiwP370fV9XqCg_$VmHd28@TO8*Hr<@1 z|LB)f;=gt$=gubZS+O@m$r&bbE)p3pX|^Y%NDmbK+1WnbKC+j>zUIY%WFOhDTP^fs z3!^`^ACR^I#0Any@Psh{8^X6A;{@Pe@4&ojr(xKq*N@0>z z1OGV?;rsRI07wAXy<%230pmX1q!AbcTxbfEM4Y6Q(4}DV@|@X{@b`s+0E8{=xb1B6 zEbQWg*a*MwYFPRU?t&Y7@4}$CnMp0v^MLNmc`QlP2EI=1g`#9Y)adG7#v z-KnW!oHJy!MacD|F@Qrr^IE&O&6X#FiPJv)xp)6p!t@erD-BdC9ON2;t~kWmaPQ@` zX6*N1Z4r`{x1&JotoA4RV`F(SqW}5$_^!-7>Z<@h6fGdRLb3RYvJpTQK_@d}e$p z8X_zlP-H3LZf=a9@l2U~nEkRz+sKTI)dV0-Iu`wtLQ&dYPRNXdMKz%NbipU{6U|fl z$%LELQ9+edN{KCTNqwInvG06lpe~_C{|)m+|8r4DosZ+Xg@{M$>yB0WE&;?&fcF6? zgWl+^1S1NR6oJ$h{PFim08R-_++kl{C;Dq(I3Oq9UW>%@uvIM|A*R*1mL3-LQuHys|j{SW&Bsdj9YJDbMBNrN`cij$ce5%Xyy(_dhv|{v-gZsBLp|U$qeN z2!353>OU(VXf^CVrVP>D21trPbr^8>?~nlI>@_nDo|o_MmUv0US9j6!*w=LpOA!?| znH(<0fybi^xe^!O(P#n~1F%ChFDARj$R}sxvW9y@oUMTV*i@j~94xd0;7`AMfkzm7 zU=4_trw=oomYO0+mj#r14mmzP8;KKXNjYb&9frK_jC5?yoSFs?j@3AfUT1H7h$kZr z?6a*7O=Ua?c6CNoOe9E$Y^p6P2a&2KoiC=iZMBYRBhNHNa2X8OQ1T=(*34C1Lghbc zT2yVNWTBH*2hvnv^#~B;#xh;x=Y-+@)c)tpOy-*w93H_OaHE;OUvJDG2|_RlU>A(s z@asY}Ar?UdTJi}%dH#4@TkGeG{-OZ6>Y>;E3LGvH$qlRp;N8vC;&>E{Zw3F1F@T1L z^CkeuphBOq-agO@Pj+Qz8S5=B;!pGeu6+*{1U(cp5M<-D)av)YLPjkoC-#SlN0_Wp zgYS*V3;zDxd_BPgF61#Q?KcStl&;_Q2p`9rPbUJFjAWi0a&xQQN-g{oIL;F}{^P&I zCkJx7Ts_HEbIsZ+=`%4^uJBRP*Q?Nf>JpL|Ns{E#7Id{Is+J6%3EYYxnG>)xPxL<% zACOOd&&T5zo6t0H<(or&h)3${_lWG*Bko@_EXcRRWE;Rwx-_)rz+)@H3nBtNJ_+EP zxX7x~gFv37+>#n<_dur*_Bo+gK$|TAFaS6g3ERs@P)o23o-j+wVmu0j> zvP@jq+7P6rFyDXHY!-xp#%^B=E*O>20f@et76{T5R~J(CqR}MD6F^sx&f|Nnk(FlB zFHat4$=OY(t4lGeiJ`8`RpAZ2kz`V@9N>AvIYL!(F1=GZ^APa>6>0ug8cX$ zp6s*)h>HSrG!nptfPh|)%kfm>0_}_lK5xv`POMgtUTg~i#6Fp4)qp8>2KZPL2tI~vBvNAnrqvos2MGuWY=JD! z5Ex}7w`xfEhSPz(uuYl9+m{qB9RhMlq&ijj8?UmR{?y%$WV$m*VLi=$)AqQ3xc>9L zG?3n}&Q+bAq_G@ljLsO1LTdkt`xE`qFTqWINBpY8k8lSt7e##%0uuW(ImQ4MG4d4` zXkHZPkH2RExEX;djeI@&r_FUYeN2q_RFp|IlMa9ca5zemi;)1{jFRL`TM5P>-edRJ z0T&36{aF0AV-3e-xd8{=8Eg3oZp;K*X6%?uxj7qPfBBu{6x{DydW%QT@UyoJlNm#LVmE zWH+Dmg>>CI1e8Y2X%1XF174D@=S0{~X`s6d+!attxRA1iUkTNFr>+Zl!qa=imIv5p zSG&;?<5N>#)&7{$Ah~g{g@t4%^@x1^ZWi#4|FHi>=w}k3g@E5jCIMq<;BS`zc=2z= zEt+9Vq!0e!33?Aw`fdZXxlK`&8X-PO$lxQ&QjNf@aF75-3 z4n*bqY^$#q4fTxCW4e7qS~y5%IOKq>ac9z_Fxw;wBxuO`RQlJv{LWOR~`w0;O? zEg4bxfH!c7{gNbrk|%*P4mX$*>VY-^hR(}M2P`1>>Zvn;geau_#r?W=FqQ@?cc^Qp(~bMx7O?hAK1KI202jda7WyH`(Uw)@2izY^ zVeU9eG?cd`2!V3UBb5g3m@Fvj{{n^B2Kd1`fS-&D1PbJRz}O_#5$QR=W?Cih#v%K+i0-*N!r@)8tFkcdBZ z1t=P=Ii=a#d93FZ{s+n?-;5SU{v+8@J@OhzyTZ4!GTByb1butAL-(A@bK^6F*@O zdGqg<0Qhp_c%o{p{oU-vLvV`zPDqe$Em#3FfP-;eo{t3ZQP>i_8D!9N1|w{p4Y-F3 zMCbc_)Vwc6De9w0*=WdDcH%cHpE=AegAP~CQ+SeBZQV0S!vLWuNCsi>Tg3o;+*gG; z6X__8XGOYYJNJO)07)&86tyc*IjLPpI;9!cc6}i}IFdIVfS-9*pp(V1qu62!aM^IG z*=9&kRbolikec#AUA9UAT1nmKTWR6ePY&2XZvX%w07*naRFMyyeT>|V{{EmVuif=y zNYOu0kKAF&Z?p|VqTLJaqffa1iv{;jwZEgjtE1E1GB@{e3lXG&zdRY-jp$!B;ItJi z6zD&Zz^)q#ggSKMgD#E;^jIYTr-VATs2tFp`p#SXOP$KsfDbkS!Z*T`=-<%Lj<04)$i2`X10A9?t3r_JbwO`_V#Erw^Hw_hKY(lKZVHK0r&Bdb6f15K*s#9Yf z28bC&y_PD?N=Q$f!b$=1sG1fpNVkU~-7*svG%qu_WX9VSg7z2YaI?Y<1AvoF(qpHc zcJaz;0!aM?ISIpOr6@nQ6EdGE2aL(|r<%HoQX~#ing%Do8lNJh6rNIo0(uwxsjs>F z@{+G)@{r-W-PVY9`=gM$(CR9W{=0|KUzJU=v(`tma&GRQaeK;8 zXG;tqMW8@4HUYQ(o(Vwj;H+5)06|e~4PG_WSv%oEZ6j#e4$`kZ4<_1pP*8I5Lo|}IayGGrBT7kN~ zl`OO*a;Z^pH;Bl)#tDTE1f^0}pMoR8d)kgJi*i~M^LxIc79N;Vhp~1DIIw(hswG`m zSWF$FjddB0X|AZh_Y#=)c%}le)FP&^9;qQ){dGV0m0TKSzAH{Rkw0 z+YJT!#WsP}3J3*aE4a%Anpg<9HQO6}3=;rv`$k+z^6Qwl_E*Q?yO-;R(H|QCoFE}5 zTnHhckLKn+j}G8+R4Zo#g8~JbcN;)2Mo#h2fljsMvO~>kh8zGhoyaBkZ58|A<~!Q! z^v65x0nv@$Mz5g8LdNBZER^P-qEQk+#m@A?b7E!J@t>ry#(!KhoV#qd7|l$W3AwnT z-riO8Ss|&8f5CrP>pN%j8%7Swk$`WSC^+{qgNQo4r@9>jJ>c({7C;H`)33tCXkf-W{x?K$4uev~q3$zG9h{rPl@J6o09g@I}vD)8dqSuw^ zPsz;qcW*>wbRf$Q|H>JX|3W8Xv2X>+vs^n)m6&gTm~>fUD{01U*$jj8L8KYzz$M%mF!Zk zUC_~$Y#W=trUa1M-!vRf$X=3rOQ=+(03@JkO;6>G2rlN2M0Q`a?fS!wTD^CuO`B?e zM}C|do3h|j@xMMAdJFzlU%xlXKM)XfAlC$i2}&ja1*!`Hf84_y_;F4EH{+6WAfi^X ziSMuIPwkm%f1>~XxJK~;yAUz@-EgD+IJOW-0H+#%5t-6i6g`oRlo`wO5$s-x+u(TI z0Q(#3c~46Qs_S>!H}|%m5l4bMXK$m;=?D0E{<{zlZ5~kfCF;)8B|2|xgc-?}RcqX? z$P7GG4_oflr6xnAIsxMOI2$Baa)8F;dg>IaD*7*VBfur~Tdzmb1$JW&EEEVqO8r7X z89b>xzoaS(!ltH5F}LnUbhq{vkpsqNHkDlDrG07?^aCYbf)EVbN^_I0(buExOd&+zJk6GA%84; zfSLeO6Tqn8?+XDb2Otn6p@O9JkZ}LR_|(*QdyBC98Z&_+ECmATX^XK!!V}JWGjBEH`FW5IReIzUF?yWvm zo~TrkJTwz1ot~c%`P2cVrM5awRFHK>kg9d|b&ocRl+$Fz2ukF44?`+E$tciFPsQog7!-zMRjw)q7Qz922QT;J;oyS2|;R=d@wLC zJE;3R(}Y|Xj4P{if6=)T{gHflx!Lj@XvvtuWltN+b8H;P{U`F4n}(h?hUi~A3KkHg zhCoe#1cF=~H0c7#72wau+Y@*ZzQM;L+e^-OakxLxU$y_?2tdc%BG{ES2KXQn0Gbe7 zzQls*m0)M1t}$0$)Fu#{d!-?vXcf>DABblqvA7983qXPsA7|Kwwbt_O3#k2fY&n&INfBIb`7~Y3IPeLQGyrIP*51i z1M;pIJiHj^iaiW(0$lD*9gimPTrDJ5DS2o*;*HVDaR_J;X`s8*J%+7S32PtrdfA?& zr>CVx6Z=c2NPcE z`!HYx7FCWnGvL8p|`~1_9_G7G59=8;t zgRDTdAY;LSNqkcmgY*P|iq0;Z#re!LQNkzWfb>tgOI?6SIvjFiMu?jxhR~2$q0Z7# z7@}0C>hxMtD&Kt2^aMxD-GO1lvjx!DF#HWW+6;Mzoe&=bqz>SIh5j1-QyQ3%ov4S0 zZ(la9@J?zM68AdUsnS);ReQTd|ATS1&qncd!mdL=P6!KIMxwu7MN`ewd3o@7T_I09Cjbhr?S5!%c|!s47`)>=*dyN=eHF^hG!!scWvgarnRue-I%!X5NsT3g<7XQ&j$7Ly+B6x+srR-UM{# z;r9alcT++aTdUsgUCO5RX+>l0qAM=xlUUT^#e(&7qTqDFQ-Du#ur1XCbsiixqkOXb zcUlMLF@9EE7OA@8r~&Od6s?Hh;A7#3p96k3uBQ~@oD8Z7!L{fBW~6w|^7Z&90M68v zxIV}MiSOU#{0R3Kn6BDiQ5E&(bAiuXiRl03P!;ZQWAS4TFt1)4cd7PlHycOgWaO3i z;k}1{)0m{UJkvG#DVaskvbgy32-{^Z}GnL}Xr}x$w^GIJVtlBv5;bUFDAj#&cfI{DA>N-r zL<#+~3;oad_4p?MP5FO}ix2OSv0Y!s{dZgKf3QS<;_SI7TV4qi=!3bre+5?aYTE}s zVr!*a<1(F5b%*+kUc}dwE=Gd+AoNEsN9S=VUckk8Mx_MQvR-bf=%gV<1bwE&blJ`j zRmTGw?s`O^86;7ngUhJx7@^`+kCEvur)0b6lK>Iz>CDi~0BzIu7Ux-5fiMTXHYIx@ zGcLQYGyqMAD`8(l$@awi^-D!FOcD~)>66w0=y_ctRHKm^vY(1bQOn^r9`R3bJTnaP-f)tb|6kl0GHza zc_j{l{wq<-yw)g5M=kC{9D)PN-N-%xflM9u4x2*DtKcWTB!-(gn$B_YPJF7Fkju$NFap_`Hy?KDw>KzM$#oE$uW~8uR!?WWx!qG^5Ao4 zRZTnF?sF@Ct?Oe$hh=dcX9$tCb~d%8XBxvNox_QR;cgB{It_^o?Lt_70;{09Cjcc> zwC4owox4SrvP-^-=qKQ z5&hqYxco^p0jR>AF%*b#7K6c6lhp6TgIsHU0Hx@uR`M$woo@L483TpR*f&wQ6rGM& z0>m$sh$I%I+HH3{sho;8wi{2yIHyZnugR#yy#c!TPem}2goAJ1x_GBV;#jtD!+=z} z3MgcffcV!qa!HZ?s%e8u}UBhq0t;EKRroIC4gx$#{nQCE&Medq3jKmK+J!25t5@hNVy=uZK1JnlLT zsnCd@sQoX;1egTyeryAL6e$7t1t3V%VB#-uO4smR*P;~11h@+eVkUf|;W_G5xaIuD z^B<5;8O^nTa*4_j;MC5ivX0zCwADSoE55U3s3n)^B`z5@7PcIqNa_*NpI9}d9_@%X zsFh%lVwZ(*4*Qtiefp5Qf zCyuL8=075Wbie=I5EpTp% z^uzPg&Ct&8Dw@nG?mG=MB{_em)r~f_1v(WQhiVyni*;ApMX0+@$)ieyB~J!bCf4B* zf!zv=%Ah0$>IuCnr6uJs5~@}-2#dt}^ES!9(EfV1p?Qow_QtPD#eRzZt~Z{Tpso+< zs}in*;#%S)JW?zad-+RoU`(#8Ig(D&o$>5I3Is7&>h!-iy zzgd06>Obj7-~Tbzq*nah5`gD`-Epa5asEpCFaY)L#1Q7^xw)?*&~qPRNaV;5wg1)F z0{b*R*YDa^@LMsGz1VJAuppuEv;vIy#t>T#gdv6sc9$pRkw%zvt+!o0!8l+Fk_0V? z_VQKQIEhmMQCn2p{4gCMIAICt0XNwY)_XEdeXF3DM}MCLq%i=6=aE)9DxazLuc5)g zfeF7V*G2IB;pTp4Lrpu;!p zlIFIX#-tX9d=C#tEhFGQ{42qs;8YAPeC*^iGrmb%^HN0r*IQw9sFnX|kmE&3Rdlb? z6qWJWHC?F4&oZn1pPk`I-2kVKn^9TN_j2k1qilPGkzWcT^iexYeD3eWSn;EBeBA!z z!QzgOBXIp46M)2mu16f%7}5W36V^yO)--E3VtDYcVB)_SSMcSQ1E~E!jkr$-@NGQ! zFmeOC!Dm_@0J{Uo80ZPn7@GPt6m_Q;_egQR<{_Kw!sp@FCLb8FG8oG7q~dtg1unM@ zag&yH!@;KHcarCn-NQ{a>8_RL96tU81)>w$*|@nH00=Km{xDtXN`Ky@Wv^#+ zYP_o%yGwggyG-iPG%H{!Ob)~vV%Q7BPjDnYp0i9qwSgBd2cY6<+tpydM6upGCpYk_ zg4cuNN9{dL<4-p5Yg;Ezj+cIyrAi z6V~q!QuI&YPlbIFME1;Z_&;Ox7oCh*6jjmDk%Kv$5*}}vclvINMRy|3ycuU$=k{U) zmOp&}$7d0v{-z0lar|7w>vINO9mI?=Q&7`ILXUDX z`qx(*pZK*__vo*e;#H|um1&n=xh#Ay#!p^~YU$nh8TG{M{j$R$Jz6fyB=TIZDCddI zuCtxY7*-5Bx!I#X-vI}c1j|?g(2l)0f!bYP6W>=W@OEQz3jn+jMd#;1GQ7VBwDrGZ z0?-#}fZY4%F!bv|lHBuT07mp(z(k+7=>L6#+vo#6ii`eo+$!*b(1~*yPL01d#1&af z6&J>lSOusK;66)R^z7=R6G-iIJZ*qO*1TB-Q?FW{Ca? z_gC$&arZ>r2OSa>+pR1(c#8L80C^?O8_AVx<6d|{&$f8&~^H6{PoMWAuPj4R&#-aBznbgm?CIRE1A105w4I-Eleu_m(Cr&e3!?0 z3n1w%=`cb7LUH1}FH1XxvFb0ny?9zNbq}l*{gY9lzZhx8dL@Gzk3h zCru30YD*v=0zb)P23r+v=ynM@4~__FX^v%%Gf@zH9KGWk5g)1OPa1Si5v>@ikV>sh z0-$`}GOUyx*-ta=?lfDza$0-lHC%|OeI?4558_Xt&VRL6{?2eGkxW3i*G?jfikISN z-jAPurP;iIhsb|TqI+(nlc-!Nue-qKgwyi!`D*{wGemzU|ETtd<1|YG7#nqH4hOWj zzFiwMUa#03=t9GSo^$~B|H}*i8uZh@3KY84gt^_O`M0*t2TVjt_#!^G_v3C6HHa2o zilHKj(i=Y4qG9!8(M)(_uN9yq)U{Q|l{%6ghg6^i^d|zi!=tYFn4HIJ@m{x(s`#+? zA1Rlphgi`B-B?XvmXULuc=dB4ddg5?M?0knvt~pAhVyz{ zz#lZglb8Kgl=g2lbm)>jcr9WXWV!d_oxUEgpP?~JDp~>43_#^e+APuG`^=RBn{q&f z{>Aw8mB2MKPkn3jmkMte_ovh&`m6R=`R{YMHSvNs+lK$8ruro~=)C~$|J9lR9{5qe z^8^B#|Le|V0vO8ya%5(5Kr;9}asbi)dQcITdGUx7m))*OsrZiLhXUnWg_ot5LyuP^;+Nm^to|`fV^8z2|$x=-^ua> z(B14O`O&!SY7=1j5cq#d-sKhfNf1HmPV|f^11av*33jzXPs*ACTR_`L6{kbK~V>Su%qsRLjMjzNxCM!uJ;#f}u<=>N$26agqS(2pW%$1<0%ZUF~T*Q0y| z=J|d!2X8k}=yE%t$+04HH3HMyO}dKgrFj^@h%B#l$vL~s&#g~-6VoYiVaJf4wA7$#2 ziosN9uO2F4NDYaez#UNpD5a%=!~u13y=t_sHB~Z=QuOy3gWvP3<7L35fdI<+;XPI! zXM+26|JTP}=_f+!@}8ze(k$|kKo>!B>`o+l_5eV82i%Ab;Chfp z@pFJ0^i@l|?>6%QCc}^-*yCkVBv^)O$W=DI_F2_#Y_}z$6#(2czer>r{X*U^`UE@MVl(=BmHCtCfT>hWg@0N{s4Hw; zW?}cJiv?ssH%nm)3>qtSH(Ro#fr|l>ywivSln582=+;0O0aQG*wALr}P3i zYj^W;yR)>mMtIETpxdBo_Yg$r^`?FDRRp8=S`K*ILO*TI7x4pEBP(2LL+n!~PM&1o zw)Czs@553W?rLh)UEfOlUuf;WHolKK775@;4+2VzPoMf$nZl}_MHBEs8xD2*0Jx#T zf*k*O0s-Aq0;t1)i5!s7f3*wDhkt8L02)usgujoGfLej~tSn+O#>&VDv#;&j=yBACEtb2SlZJT0~OroKXcrlY_Axw<(`UFzk4^SwUc2?VtGuX&68?hh#XLnOV^ARysC zzqJnFTI7IV+CKO9;a0Dy00bel`%f2aRP!;{TdsJhJ4#Z^6Jh{Nh!hnocOV;ZuSM6VM|4J}h6>nsF zv{{@+r2*#!sSkM40o?1?SoEJ@2Wel74YJ>d(O+@jQJ`zq3cwEfy0rojgy2ZP@}|3V zgp{%H`cgPJQo+T&()M*_fDYMC|9uQ7r<0K1p`!{Em;?pncX&Ngg7bkeFD&^+B~uZP z`10(ni)qAM*z~(wZN<(+YKao!-z^NQ@0c^nyURpAHkh{|sLH0!EJ{0K&gCTy5M*It zGH!jRIl;ZvIF$Gmi#PyGk7BtDLE)&NNk=4I-S$7UH7(#sDPR7^!V=|+N1H+dIM-g= z)kg36v@JX)GU)43;(Tm5OnVPnX%-jAm!upBl7wn0{0_ZCPXgfXbD7MMgj3N0yfIY4`mpJv!2X2$|5n5!G*MV2 zW_eieLUwg%rRh4Cr>2_{(^gh#&nl~4WwC1la8mMWyEwJ><+Z=4QzA-Gi=;h(F6YOQ zAAWzAFPG|=r{c3v?cc?Mpy#F>@Pq|)-#P#Secch0?Zck|_e1@J^K;Fdo$>knrA2>m zA@T$O5kILk@OkS7-nDWG(zG@S#eCODfJ-Mq-ZhGm3^q32h=OMKc9Jcn>`m;bmVI0VfX*1-ZOCW`F{qhXZsJoW2guKBr#WOW1~_hO z0mOHBK57CGdV8&{{$6dOSnsq104{W)G2BrN;@vrNqG_-cKHT@QOZ1%R1G;U2D`c#) z4%KUa&y=`?0=SV0kaXn}Nt~apJ-&Zer#2-3U5d-%zaXJe56+(aXg``S0dxtYPdb44 z6F?gI%GL+f)|*Wvj=29*b9DPT3VdaPUz^IbQU&<{=g%KvB!HL%%`$M1ZVw5+Fc{G7 zp(1_FFbIy7NE~ZgjL@Q4cRXz4sf$cS*f^(vrIjS%d$b< zJUssd8Ybr;W?iEjk96*ir}+fWA_I3MKOrVD2Y%Nk0q~ny0(dKC7#a^K0jP$B(ZooD z5{G$!7K4eQY0i{jy6MnA4GpP3TQ%I3OX_&qi`+Owf#6D^&3@dFAGKd&xc}-&w%QLWmFtN(?2@PBEek(!7W(u;4JPgf#3=N1czV&f@^@_ z?h>3J!QENdz56`({onhZb3fhwFlXlUOilHfnyT*Vs$Ve$RcvwQvA%b?odpSBxcdp8 zh8-Z`8EZ8K($R0@KT_jhXo~`FJzhwd+to8#EGW7aH-?PL6f2<}p=<+f9!n6Z?n_=< zCE@1W&CFNaPUSU@e=EDnb8K3Bq(?F5u$r^JveUiw-}_vbPuwQ(u0x4989^r}BKQ;K zcD4EF@dX#N2R34#sMev|EIhW#>sVso>kFz~X%Q*bG;o(Xei3uk+6X=N*x%epsKlRM z`6OFYqi(J23Ve-A8fzfpYb};bz9%qyN2`G1LP5;;atA^FQ5fem!-_XH!u++JI3{Wh z)zM~NyC8W?W|L*strC%Ph413jjQfS?CwViKwP6EwbAGdhU0$14`?%4#{0 z{$Y#0P@T2}TsGikq5Xq~%y(Z+`-}3b6uWBV(c}6)YMv{~3-u<P^rL9%EoxB{o|{A)6Xoxs^MK^wC$2%GADppM5~1UG!($J8&@h zCT{-LsC6mWte5j8Xi{V9a{vv-yQk#N2G*SWrl{08<@uynFuVO% z$AxN&ejhFhuKwvoKNB-vE$rv`eyE^QG_-`Z*EyJD@V-0v=Q$CfGwL+n8LymM#z;vY zGez-|7vm>qr&(D;gdOR)rvmXU8{3B1Tx;AgIk_0ig&aGgq2=IwA^9^y+;sVfmujkJ zJShh0+m#jTx4qvP)g5y7%=M37Jh-eQ!4cUJuI(s@cZ#4CgnbG(BFYdU@9=RE1gE1x z5TuK$17Ub%l+O4&NK{=5h}Z_3GLe9}r;qpe;WUCg9sK5cQsi_r1!!D4>4U#qFynDP zs6Q6`eOv7=oC{L(0OSzyS?=4h{qjs7o`_1G*3WHj=_LF~b4QZ#EU-|Bj&xn2;dgzv zHaKUpBe;(-SuXH_NrdJWqZ}DZ&IdO$o9110h3$doFUPqz{2gYx zJ*Sv1eTrWGzM(>eNaH{#(gW>gNhx_%;H`luLs7q#>d12)e|L2G&GrXF?u;St-`7E# zfw63!)5n60sR}r67@FcUXQ8Mf_o-v z(F-~fC4jol_r-6#KXFWv?4~u5XUX3?un&L;IBmlo!nl{2`iLnJ{5`&!5miDND7?UD zdk{N8%NJV0$*KHvYeg-`@O;2^V1#V>F0EQ`T~@5wkYnn{QHS#lWJ zBe>NtdCDZ08j31oylDwJ+}MbPZS;g<4v7cU9gWvB3KOR^Ib3AuF!St2Y==gk#*-LTRDpezxl$m*`dHSlRt;bwmL6y z=C{B61}FTbAn1;XPWr>o`nQ(zBUFq559N=BSGzMN>xY0+njBPkr!yT@ii5`)&pQd= zL)9yU$^?Ep+<%Wx2SL<;e}y|2a=%%zk>qsM5(MQ*IX6jA_I7Idhmw4*T^=VCq#>1C znag~S+@p~LxeipGYerEg9l9>`zp5*~0j)_NzHx1}F=8d_3=?~c_WeWbx!=3;FQMAC z_W{VY#LLR$@aLF zN_roL@9Qdp+XR<}?V|jD9K$l7QvkhXKA3!QoP|fren7X_BNGFxvv6J;fpR#CmPB&xGRKg*Tn@9yG_QHLc&}bGU0dWx7=wbO15l0}8ucAoAe`{}K_*@Oc z{uyEM%P(?7rhDPdj^3X4zCXEt->Hb3a&jO+)3P}2^oP<8^d7EokSKrVas1z{bnqW& zo&t#Sd;nI6RWK`N-V8`h4yqpDoY}333?1?%e8N0oPRc#z{?$foCT}pl{arRW+bWepPK7xTK>|Bbog%08!RVG(NC%{>?S8 z6(QmJVeU2C&stOf9&$S8>R$Bu@lqq@7nY`DEyzN9NR zVmB7v04BJ&G{(QBJw#Uf$i?6Z@c)l`nYHpya_rl6T|rJ^*d7Y+CK|?r`we2L*!y3d z5xQ?V<6t8T#>&RM1Cn{CJ_}$b{3uM&>QsKQtZe)J{mBE%&vxd(ubC3K8f^!|q-^C0 zQ-%?G=gZ8DGB>&3AMUt+{NuuZb>-!Nh&na6%@Rob#NroqXS!YPN3ii){t7aA(=~vq z-u5_qm4vjI&s*d*1XB>s4MSX;6S=*fFwb5uUlSDEvEM?K!>$xY))ch(Hh_2Ex92ia z1?Z)eO20^=N$3om411}ind>J%#+QVTSsDGgQIWTQnUFeUXwo&b$2;asmI43+z4wGC z2$(-LGQ@Hh&4>7`2z-a=Jo!4joIUih`qc^df580WDB>m?o}C|st@4l$L1Ls)^{>Jk zsnpCLKV2>bGCSdr1hu7TeGI)9WNmM*3J~4O@}o(cilSeTlujFBEXF!nxZ3y(V{0RA zbNv>GmN8-PsnsB!+yq0Fxu%nW?oj(ks#p0ScZ;&|cXLdeBMU^P0R8 zBb2We{^MCdJASkNKhU~(2I$PwOL7IVyI25Oo`clWs8hT+4#Qzw<=0We{Em|OHDI2A z{>IAeV-^S_{1xwz7~8Qj7Q|KL{bw0UJg`$Y-{!+f)UjUKlTSD@8vP8jsDjy#I;x}Z zPm)1c-N27L8j}?-`k{J7_CXG2fET;M)5=TD^wJ7TM=rdM@OyqgYuL9}UKKgA(5LCt z;79k-P+9=`^(h!(`#2KFrWWp;bpW1O9|GCk2wfShdkW6>}-+g>!V<(;?ZuZ!eaX3&j+ zbC`mDFJw0wYdau#I}l#3VBpTXCl#-K%NdV2D21K^jsJDR4-WT6d}G-sX}xy^%17~* zr)O{Wm(=|5T;R&Jzlj$$U{*^XT<^1cd6dVb3-Ens)pB3m*k8-}#^B&%p(+ zN`BD`iE6Yad3rTbJveMsVRGOFpXDHcO8(w+QQaye2#^3xE^aY|W2OLDN|NXUOF6I33@!y>l)VJ`FGY;6_s3p-bf*K| zreEcE(cWUrqy8DmJc(#?__N^*@l04{9@zP%t5?bB(fQ0a7$?ds=S$ZTcyh11rKK!9 zhX$Q9nmDj6;pvnalmOmvK+dJJtHoj;L%x-)ydYjjEJtk6!JIwAL_wi{ErNq% zRRqpeu%AxquqZj=2n6U!=A`LOX~r!}AA(56nO<)+CsY}o5?yJs5i>Cq<~aNqJ@0%N zanFBLNvO^^%Kt5CTJzKCM6YL?!&|aTO$-a0p;Vl>^FV9%pK;}l=6hkaXZ;ijf*7TY za$29S;qE(t#=9y9y)yf2e1Y`GH9|lJQXeV{R_n(7a-QW>YJn$O=pg zY0s`+%~z)&6}BtClZ9uoc0407(+-~#%4@zQ)w@X*fIYKJ14I!K?kMj*^iM)m@qnmi zxE%J&fYn&pc#+e+$HBhz7iS+oJj3-wI6l)<2V;_N4lq$36i69Gy`%lQ3Xu_K0qtht zzi4-qffyYK+r4mT4@@6cvFE{@oE)njJds{c#HC(xt%g-#o?Jz@r9oaTmzfk`8QJBr zi;9QtP3SWHRVWj}K5$KHetqG8I~I}-#j1NrW{Wqv+wf|5^penuXa}0#QnZX3q1hrt z)OFu{V{)O}0C}VhhTEipm4FY}1rX)n-$3aUOuNH&fjSSnqG1(1V>6W*`0{Bw_1o1pUNP0WNLYBKj~W z@n7R9b8*@lr;rAw`zCCN;2q&1_Z+`rl*?o#O+=<>f3#WrTu#9ThL$4cjfWAg# zkPW;Z?_0l0_FR=QO{CqpxvB{kK2!A9pFPFRdbg=p+qe z+=MV{4msL%@SkB;Ogc|s|7-N+^{+WNWbwpM)aklApc^UxvX=XPK`U>2Bl#g+C1pV1 z`fQT;o0y{iWP|H@c5H=+BaaqZia4@M{$+9yMZbtXc-?8Pb`j0{3|pvWv7aA%@N$8qj=; z1q8FTa?`X={P4V&-q)}KwAX$p35|0shv2T@?d1bst~fML15oR_$<+7X2_w#GG<8B4 zd4v#%GEnEgYEK3a;L7QkZIJbcto7b%wlQbMBf%JE}~_?>$vN7*!y=DV_Tta$tN zr4%K=v~zi^?ryNsuKw$V*3f_AAHA9-5bMIu?kq;%@D})U&YP(|?EfM*IH_U=jdS??4!Jj>C@8o<{X)UYujDoST})x{@BQG50S4KPn$#nA;yF&tL$4CE z26`#_>3e>d%`EK(jRsPD!qTwG4QI&w^<&A)cYbdvm@-IB$atvs3OME0S~ zixJeY2ku_F@&@5|VtCLqbhx+LPZnU+*lgVD{&w{R?NR*=IL01j0@nJzJ;QoK0Io^Wh z=Z~6l=!zw$BMW1!m=^uqT7F-Cb`|K?$Zrpebq;XV5kI+^6ou( z-kG@in1o?$#)*Dx)pJm!*elDdf=LS!7g-r}ay*JD|NBvH`DU-q?K4qE!=crD@x(+9 ze!HIwmxGN2^K+$l9ge_$qu1`5oQZN*U%f&Ze1HG$G^^m1B+=hH`@GT_ zQGZ|kicPC6mQSzPi5h=Jz!@(6-#i3Oga-isN$X_-1e~}HuOO=|#)>MvvkLlr0vfrn z5G7#5H#H$0p-<;4i;w-jh~7903rDmn^^-&SN*|(kcaz66`z_0cFV4(Ou1^wR{jm8# zWY>lhqxmcZpbaGA+*8P_*kw2&ewb*QgnlS}jJe}4Ej|0D5>2Ah&NwWD-ZvZBLG!Iy z%5tt$6U`o3Exp5+QYoIArTk8_+>3~76=BIhC?Vl4G^tL+b~D$#9(%gFtJ9&!*Racb zm|^^&>fVJ+2E8KtMZP zc}qil|3j#sd-u83RfI)QsQ3^_1*k^}WZDidoQK;O-9yEzpg8&;P|-2;ex;~Bh(E)c ztW9*^BtnL`Zu;KmtICtdh?DL)_F`Z70M{m&M8y}jR_zoXpI;$$6ZAgm=cc!W_zB`I z4T7d8#2wdqrvUPYE^sq&+UHY6A=akf6}0jAlx`zXGEjscEHtO$_~6qA)?wyj`M5rY zW$Ip0^Fk}u-k_c*bEA-#xvz+N+jX6>nsE^8sr=#aiF2&_qdI52z0=|3w*mc#3a0g= ze5h;|LqXrCR^D@Np&k!me!s2Mgz)*5_{f(wmb&7n(S)_dS3w{C2yx+hi2`%j5xx#JZko*(q%#UY3{*WYcI#bqgdFk z_exI;$R1^HX-YlsrR0m7@7^)Y65qd=raSh??0t;7oC>0wfe#_ z_gJq&27l{rS8sCK-&AOh4e%51bbfh-^Q);}u@Peb4zq^-_op&DDG}P3Xd8#i%X9O# zW(!3WDPNj1MF#jb059j|773c;K?i8x?m-uj=t%FbSV080@@|C`GJl70KT|(*Q>gXU zLPGQzu2l)V%X$^30}B$s-y07NfaFD^xz-{0a+f+ z!E{NARgEqy43FDRgiu4A5{pFfX%Anx;neor#HyyZh2OY=Hz z)H$sGBI{Zs_FC#d4}PdowV}C?{%7&c#OqNT1M$B6h%c;+51k}Zk8RRD1GvFU&)s+0+W){;x&)kWGtOMg9HV9~WaX$1ko$Kb zFkcjq#2L~7by+^n8Vdl_>B@4_dOETP@z*;iYfY5TsYhN8p zZBzGOhGvZk=Vd)?rmsut77zY>8eQ!xlg>dGHXzO<#-vkOzOj%*0$%yG4;NZU#(ZLX zls*vdA(#u$D3mU?ah)P#oquD{AKpC!g1z7alPUkq$9P2|KTHd-z;KnW1b#YwDeIwF zab+KdN+X6r7ncv#{xoNHy0w&959|;8fSBm>r+n!dj6HD&9FAE1zcM;l<@e6{kuE+h z8`*hBB6)6Mo>~WUPrw6UDsyN|+qtX)ZwV)Qxc5y0$j%z}_7Dm^_IVLZh&6UR{cFeU zY^1wIU2k}9)wPKSwS&M@?pjafU5!JtFxg()eIERS)jyA|z^Bi0zN)^($a>y!^&{LD zbqDLNIr!4FT^OT^WYumD-#g|5D#Bt;x)fRwa}Dfca~X@1^~mAHO&rF|!JP%K>u)p7 zUj?$U;tH^uoH)!&y}$_gG`rNwj+jGcXA{F;!(;h z+WxCjO@D6Xx5@qbT3c>KJh`aB@_AcUNFgPytUk2SSCe$nsj;#kh#JIJWtTy_d2jN(b|7yIRwF^A z0OewdRj*|%>C!_aa9#wFX4#eKWLAE>`8;D3%ZVY{~7P}i(n*)cNb;?!MU-#3UcFW_FdXB~w7h#d%@E&SfbjbJ=ZE{Hy3`U$tVr^#Np$*=!K{ z0J<|fiXBkl?2Ldf_~U{s2*JQ!XVo^`sB&&}@S9mW1&ef1N^~vbK%|SYbaF^O%{}Lu zg$^~7EU6uFc3gFcmVutq*{UP@-9`miiwN)Dx0bTmRHOX4>BIB)zzRDZE)xt+xdvxy$x>Q-j^%60Y;neu7 zn!)A?$YGTpoJ$>lt}Hf?uGz#c7r&q6aFOk$a(i6n!W!({>ig^=&G{I7ZnMO34#(z$ ztoRJldJ69~IX@SQqPzZH^ajBxLZq=qYc};zM8kJG6eNm1$WX6H-ix|E6y#SWe{iDV zjU0EBgY+a+a{O_2FIVppFTx2$pL^QxE8EX4t5Tgb7xn2fvXFV|CF}W9 zS>uNBk`V=lC(N;$cM+6`>Eq|6ek(ra1#GuRdMYn>?RTu+TW8b}AA@5R9^wJQ;?Buj zcIilHD^-%?{ed+7;P5m&zo9GW$holpfF^1z#6t=SFZ=H~XS22bNx;CVX-2L_36&Ego6Pmt^(+KL|cDN(ve7V29N z4_Hs8Gf9vB5AhT8p@Ie->4!^I=+Yx%g# z%X}c8#mcN+c7)E&li>+?x6nH|Bf^P-UjxkeuBiO zJl~lxA)Km{((V^q7_Qx`X!J@?oq81Kkm2qf;NF7$ID2aR;r1vQjD^UqY$s==d4d19 zN(P-;<9kFxDPbN0&3VhNBZ>o4ozb`HkB}XB99+x&{jN8K7pVwt9SX|2k;bvA8u<}^ zb$tQX94N9;J%?HSV`(}HZ7<}Qon=%HkOjPZs_cBA0wZia>eFZo^_;>V4)?!U4|}WT zF}?d$-q`C{PDWI0p7;Z!4Lw8`C|#XK?wgM@Bj9Syn_ zjWF>DuV5cu4=HZ#P2{&>o56J0?;n|*7CzedB5Ws*z{&m*v*;IiBx>T?rO?4#Y%9d( zj?^>;=sN}Hhzo9u1gwRrgGt;3_lM1w=oS+lw}sP+^by6Ma0SAwK(bp9=42)LPVh-@ zZo*gEZ#4ExiqwuY#WepE_Ygzg>0b>{x=ZvVSu%o})_tRbQuQfke}I#;tFwkLY7$U2|;M^WEvQtCL2(_5lulh-b1Bgmo%B?&8JziDN1SC+s@ z1EF;ye0DSxgre=q9=X2G6|F{=uW|}}Lt!umgjLq^lnm_W_Pxiq#q;eajkn}jMJNNc z+p`2|kGGzaXU(>|PMkSgD^2dzkI6~5EzJ;e^H=CAxZ_dOpS+C*I|_zir)4C$OPD`4 zM>A;mv-MCDP9{xAvA2IcFELx?w={ZXTl_Ry8}=RuMjO^LV--rH`5y^iF(1Y6f5N85O1W+NWm$g-JaR0q=g5>Faa%7X8J)g#*LesGYZ%>5fx!M9IY#_ix!!af$Jqq508+rvlH6;}sHz*HsBg?xC~2 zIP~0Z9AHs~5)%&`fe>|sOS3886`PUEZ-XSQPWE~7Hs0`tZ`RA;M51C!8cru0!@bG zzz`i#6aSENm2_Mn^P2RO`}!UE)d(&_U&uo;Y93X8xQagSz~<{ zKhr_GEv=`yR@bC+ppmI>>dZ*xGJn6p7j5*~y4sdu;WA=}+@*B2wIb&2ag(5~z3I+}Rzr-MzrK`og_Q%cBPb_)4f!u76{tPDgdP-v@3gA$B zNlq$Ub<&90CfG-6oC_dr! zZNF7|9t0$n>w-E%1GFC+WBa`%v3<7QDB5Kyg#~8k_83{IVcp4==@u~Og!|N+o}QYn zA5-s5sD>dflod}jH%`j|kAsEdZO<;gkie<@k+$8?Vhgj(_D*wI;OpK&`Rd)jli<}3 z{#J}V)AEpd{Hw$~%oBUz6JPJ+r=jHKLIXhtv4_ys*(bi~GS3G|$JD(*TKz4& zo;QiZgr)ZOePTUh7?XW69YqH9NnZ;p<;hhGN$VC1s=vRO2?2p9 zw&sY_wxEQ&di1xT0Lu2^D?-;mzgv~!*So1WW zF;@aKnDYHaDOplrokyr~vGMTv*Md)vn(oI2>E$J=zuCHnr{1zb-ek5XH^rYeYldkQ zbn2AIDdZf4%~HL^OrS;mq-5j6{*xl-Nr#6=O^KJvvs`WxtU#=sf zoU<8XF#CjstVnEg1y28{b=dX{@B%;4L&X8{A2&6?`9cNwYyRJP_~< z^6d@`i2{+3#UE4uC8xVHUZH#op&DD+Wi4ypn_C#2pjqy(D;5Jh`heYFah!HBbu4k#@6$(ew{kcG{wXdH0A>f9B02G_W_#wcoo@aMga;$2w@yYI1>WS{s*mmr$UG(e z!cIQT+bf8O2J4^j~OQ8ztHL^7|Q$vA?ro!N%)D-fnFF@AJZP} zynU#>nIa(&yWHBAj8gO2v-JE~9UNFDLRvtQEAX&kiF!h?Yt=Tf6v3&2Lsc-!7?v_% zy=xK)`os0p@le68UJ~nBo7v;79jS$Nm)eZl(0U7D?o!yA2rY!JM`P5*_St22XSyg5 zP1E|@-IcK(C?tTvgr5XKelwVA8+J+=qdd@~?KM_OkDODQ?F(2$29!QEYe5H%8tK%g?>h9gwmQSIja06w9Tpb!o zx$E{}T`2m3sMe~3;-A0iY=+_CM%QJ-)I(ig>GMg0E@3lYe%5k|jd4gOkoWSwMg|Ir z0ttP@-U=oSLLV^cn(0F;PLry{{bfkQ(RmJ=6Dv3zWAL18n8sjmb{UH=>~w>ESw1ZM zC$4UBYkMGafFWSnbus_enhjyjuw!mI@2z~JlCU*Fi_&H6Awe6P)5j`=jdmJR$ab!| z-^nkYWz>9{T*Jxw+jK*#3oFR2nIgjuk^Vgztx)-Ia>tJ`F@q+xRL`b>o<#B^Hw_J4 zJsp^LNbBn^r5mCsDs->epZB=r6PKau!CFVRQ!Jc9;;IL@O}F1)fa zJr!ZrUHd(MV)C8f=jK#f;)mR%M`x~7R*Tg-k~$y!fcgFf(Dz7@junzo3M#U>95feF z^bUbrw2%DZ(^G0>wACqe^jvJs@d+vU=G1S`_`zyy8@wCQ=M;Hy=M7yc;n>;6tNT!D zfCxL~J#x``&A`(KRD%sQPnRZh&Gxvq-fcMUWAd}i3mz_~!o|>-t}p9(E!0WDE6)zO z3#W27VFR14EX%~z*Wa07V@QQv?Iv}U;VM0SBj5wI6HUDampyw-#z_0t_lGXxjP@fY z5>#U7w@l?T;`Kuwm#XxpqJTplo`#0}G_632+o&Cym3K9dS$?s^{!*Wj!3N6eZCKO0 z9dx4sMRPQHRGoz+AR8611+ps6(B^eD&I7$aozESMc>F`FhesF;BWfAHBo0K0sbP}v zzH8qt{iTZ2D?QLGuSJI#fOLAi?+Shj`u&5p622yj=@ZfrY}KJa@s(=9DJt|YFp!A-I5MbH97MhpYr(iG3P^ct*Duiclc4v!)d>_4J_9B9#%~ca7HO2#o(W} zc57IMsyOqhcD$Ej7@P;*{PYb!C_yRFYBMkO7W_J1tj&`YWO^D~bVqX8vnZJZt5cLm zWZLGY+=)HRfHc}LrpYMD*X|SF&oxyl?^K%C^PbR4mPJSlRxsZ+>6NBA86HBpAP6(&0eK zEUWY1cU^v+W&Ct8Nxgs9D@1>J)O`M}4S%0la(8RoTfqsLDAk&Spf`lWk-t~86_FxN zGcosMWmq-|rxRyuAQ!7N4#wY}VDsWA@?p2L`ykA(sF8T2;GcyeR0xBlhJRS=Rlwx- zQ!1=3D*AQyq&b2KZ2uH{;4-Bb*BI3+cOvK@7%1a`8drJx7SvhID6A*Wq1k3E6f#O8cq_h(_2=HB|z&obm(f; zBSP~;vF6em?Ly>9oq$=yFn8O-ER|aPx{XYNP!4Y``45HEW`}J*bc)dv!-p` zFtoVMu$4E9_xks1FXo&D!G@QXfP8K!Y?q*R78J4GMAq6K{b+aMadhzTDIYrg6!35H z>9lu<v8k z9)S0cQMkC|2TE09Ux-SXXmyGz@zS9M!6`O4`gL#;jwe>V(Ih$UJ2X9&kKx1GNmP2# zp4#{kh-L3tA1W7f6}N135TYlg&~A{cYxZFa=j%q3$l zRog|NF%&$OQs^yekd1GPv;Gt>7Yjk20RaaOt($cU&~x~8_m6rpp|^d?zWF!KMhfeY z@VB}8TRlBdpu>KMQ-mTIfwON*J+PzI**5vm7Lz#hHR}Lq05ww|w=Q*R;Uv7SS0&$; z_{$CMg;LUDR>i*uK23V!OC7IQ@#N9ctwRYq^~5J!o<9HQUvL5@hj|c0QV0W(Z->7T z3OIk$&NC-$uiFxUq5Un3k8zi#0sCXRWWx(l%464FzcF2Z^{)i`DZuVM|LtvRviemu zcJM!^llpKSDuFr2JBRZ^mh_S{B8BMPsbRv+&y8P{qjy5x4lqhtSB@}V92{fJ^1mNP zo5F8~EC&7YZ=lIT5HNl9+A{lH3kRdP0|k1^^o z3mV1n*W=sqVpV{m1np%XTW@Nf#8b@12H0Pf?B=IliN>%r!%M;u=cfW8y|pr^K7@J2 zFA75D(_D4k{ErF#m41wP^tWj!(SoP=cb;H)Q%}y}m$u}=bABq2y^_PZW48WIq1Eq+zl=T$GxSd<5t@Z zo-XI+g&Z2ULyX5WuF){E?_IB|4ZH+>ptNd-tWf(M&0oQ?q(Phvv-nE9K@fLiX_o=p zh1fw~wZtwPzIJ(T(LLR0P_D*0zU_EKc1+Bw&GeddSdx-aLmTY=QNaF_?o#3+t`dj;0LMfLY{0sM6qIGjE8ng-O6CqFg?P zxgXYNY<=1b0_@UgtHGb*2ZF#`ym@R`DrSU~gp)=!8FzQLL2v|@QEgxU4*d+&0r?f$ z=Yc$HKt8Bjsyl!lo*XB-VYiPVa0npxDbUm-KpbruwCaA5_vd!p$CQ^(zm%``!RG2~ z>y;%l+XiEo9@$9svcp&jEx_~cbc`aG!mgD7Chx8pHn!eS(`k$R-9~Fhs=%DzmS_*O zF(Zy&9Gc1gq*E(4NmD=@HeG=X5WmuzKN9vk|gHK*>&UfO*VPcnsPfK=NNomK|yKqlH$&g!H z>mt^W`qt#NWb?ydnBgcsFWqt7RqBqD*@QOTUu!lz67snnjn?>{R+l{kl zF=W)?2x6XE-z$W>`A3f>+@1*l*_7oq#Wg8y@lY=}RIWuyz602>Dn2a5m?7mtXL zfSBSXB?TE71ur8r^-EEH32_mAVIe6c6AdXj19>4~t&iFU=I?E6Z6wuQeOx|xn^@Uc z{)Y&Nkcfzal!BX*lG{>7SjO`IcSCdmgwId_6aWlj08j`)U_ub07oY@?*U0vN^ZVZ; z2nCFahK}sxBLGm44Fm?GqJU6Qz{p+@3L%)Dh*uhwSet?G9U6&iqReLh+=3)W&kH7!CT7q^eJA6}$d`y%0&u{{ z+X%sg00dY8@O{4i4=wQ5BLE=ye+W|*I}Yo9Jj~_wtOGdfS22Y1;u$S^b9*ri2HZFOKIhC)Gl3&S-zUj~<<}sq}&$?u3%&%oW z36lLTO5$Fz4Lrxg8FvZ5*Qpy;*?&vPvFiBui=Acqi(Ka~p7Q-Fn@3r3iM)D6i|iV| z^Lb`Xk|gkz1qzl~#WX&-$#Mi&Fub*5T}(L-T;_iDdO+2V5wq>Xg@qmO^w0B$?%I?e zX$;9mpLx^2Xa)Vhd|~_QMB5LmM8qsj74ga67QC8rH$uM>*nF_f=%3GcxzOaeyf_sP zpBfS#^5LEtH&*k}p!7b!Yx$)9MOlBZpa0|J`8UQP?)tc|5}7LYar$111r8%J&GqB< zuYQbcIZml?46_Y$*&5eSjF_y=kSjdh@nx2gb0~8v0VEdxhYe6^i^mV?pa16)efrHP zbH;_|)Y}=?sit&QcWRnM85p zt##zI+amE8m)>UfEz##`d_@le=>CWGEc8It?r^1O>R_G$8yQ#V1*H`WtJ>d~Lhdw* z*+PywYi`CxKesZKt*P;i<(b#-N&Z4Ujf8d>x6NdkcaHUw9sh$q5L|5ikM3b0ML;v7QqC+P&9aaFgUS{66C(pFusd9P7d?KmGCec zs7#DsuuLu~So`q6c=Pbh+8}u&kxNTFO*P3f>rLs0ny4s|XZEj21SV;&gz0WJ9~ovq zP6a#m0blt!zpjYxtuiX46xR6JeWw=hztOSIpljiMS@^MMAWFWU?5MdLCQy_}mYY6y z7*}&r7~v|97C8~DBJ-gPw@@L%);~xk@moUDVuc*O?eNzx^f8|RfDFklv3zm90N2m< zSuJfDDiiN#wz6nPN5Fd(sdrLnNt1gN!}PJZdC$watxNkT`x5nQ1Z@XbhE<9PDv`1U zfV`W_0%Y288A{IOIb-dii{A~dGVFcdf6Fdme%`-e&FjQpGDD@)f6xzaD8440QvNtK zQlj9%sA}zco08jtDR26b%Fk|TQ^pK#gabZ$;y)O)Tkx2%6+*PR7i-5Vrk_Yp+$!rHTwrg$uCjoEoU10$kqRdgNE3|uc-S7TM0$8 z;zUIa=o{d!HvJ1p#I|3M_IQ(N8C5h`oA$dG?PxYiZ6g1VEq4-g(#XIy`}_Tz@6&uM zwh2pjbSQi~Uno}A&pH&`j6KO%nQ6ui4vGb@s+dHSZ;ssXS%mO7Iz)&)bQN=-*LzrA z)6%!+k$ z;G@%c<6}XK^d-m!BWgvY|u&L1G z_nA>vV^Y1IHMg=p&FC+wo#vjm6b_lvx=U(M(FFXA^uq{u>rlQwfZDu^d_0l$=-1oEFEu9YtHC#V zPU6RfO_2C+&V|<4W0dx9BV*a60Bse6pP~^rPgFLQp3m>8F#S|-9eW^lqMJj!l|bvc z&l8a9?LNhA{j^3m!maD-$ual&0N((uUfCaj(QEpAp`vrWuGu~iF)BL}j&mz7`}oOb zn;QHn*)KgvwcACK5dZwSTEb`SS4R+LAX{Y?R>Kv^aEtYgmG6GW0iL%TcJ%(e_D!&1A?7D}ymGP~Lx6HVTer7R5=HvGCq~{dO-mj;g*pZiP zrqk2%^qx->wKJf|nV*R#kEU}1M0Z2C*~(4avtI{-K+SUGlx~GrffK==JZ=!{F6}83 z>c;FNS(`^0j&fl-k=MW?r($J4t#@17w)3&b16;-4q*K?c<-Of94~%geQq9l)iu*-@ z-}6}G(tt}7xOAw`o-ytYH|Ni<^3Obhy&tq!X>|uXTHi$jmRx~0)j*V?NtS)Jf9%rz zdBtC{m9jI6BjxG3QU0%AWkjmAwn(UIt5oOY@%)1cSX@+sHDo)9^)}dU{xB<&DpGDv zHSaJ=RaN*DTLf#f88BUbE_cISC83-5*$CmtT)9`~QTSRzjL0K@Y%s43@^ExAvi#$h zN;%~`WKh@8`L>5g?GNs}yJI3BJnqC2#I*XRI#qdHKe^E7Gxq{7T9#Y*cRVJz7;ZYY zWCg+65{lrVY!f{lRBL8AY#HMJVjuoY*1_+p;=lcrR714%MjiUzUZY*?G{-NC)SZ6& zF5WTO_R=#biuKG|^@-8_TekdpJW5L_f7|u-7wgR4@JJB=6<;>ZWJCphpZ;Sx_xB|K0lUR4W_&l=ZOhI2?nUa8_ca3t3{{TEt z0Z7NVRwSmT@{w!g$uSRaIYiXNEc4X5?m<-(GVwI%5x4c?E%8F3w$69+iQ9#4JrPsV zZ|jKJx)xcwUV5@bfAk6u&u!$^b4jrP8Q)sGeDReAeno-YB4^K)pEO(mz#&Mf;k)(+ z$stah=uG7;-T2X_YE*&D+&ZPUEsnaXYPi`^o(@9vNr#MM**zwdZ|c;@DvOB@1>kmz zE)3xy3WZXrOtRpD(60LYW9@Byg|M3W2M5z1w3{`WfzyhMm0hR?*u9v%rKW#dH@Qv( zP~Iv5lRdpkSLQOm^Ph{^y4`s{!>&~O!*my%Ox4u=6X=%5{>ApmU#F5^T~OXFz4w%u#0dS zbYMpMiK4JiZu)MYX(m_tZtm6|asBXc8)XDS7Rq-`;uaSb33*1Q?cij*VJbXa=ea%; zM-`D|T#`1Xc)(~TqJk{uI4LV@#}N2_rJ#V{8Aav{t3azq*Sb@~851ngo$iHJqPH}I z)W~;?!p2BLO~~ux;hM)oJ#Alh=Z0iF3i6Y%K7oeG51KG{s(Ihg?H%ilw3RW0oy(hU z30Cc19LQ$UD~r~1{f5~|PxKBnxEvWvj@Y}!o!co@)6_oHQ8oo#*`aE(lEF;-tKko#(Z}}H-{&u=^;7u%3`1!TP*zZnp#53_1So|7nd{a`Y6QTQy zbz!^X0Vx@5;Z#be$j(b4hp=*Ruj&1aK`VlXihH`U;1hGfBH^TSx-4237gSsFHNmDi z+!)Xw33?;JDiR_O*7O^F#Q$I0aiQ&)+&DKb+rn7ITu@{|Kc-@`NJC3ML?YR?S0`*w zEx}XVrWRDTIY=5By_eLxmK812*jB=Xb0hFxAZvyWW^3Lz9)lyVnVn6 zwVFl>bD$S&&C`Kv6C|7NCv$OIx1qhHW)>=^8fx-5@{`X3IzK}S9&9vD40kAKcfXgD z>Ss#IvJ1`zLvb~`k|}3P%=heg)I`E9@BRT$v>R!q74xy~Wa9!G79eYE>1E3t&KA{U z7{>Pg3X{N09}l&X^R5xtLNf+K<6DZ9#D=}M(}#=^J`E0qPM zjhnyLoubt*tHW=tBczw()$Rt!16trMoRVro(0TkMX9dZ6rz(YA%7T394B9*ym}b&V zckGm3O_21|oxjlQI zPL_%=Y{AX)IXtxOFr8u{Y3&`ga^G={@hr^-a;T3lD2Rv^2PR4S^@Nl&H4lZkrMkVX zLgvwOjYB7*xrE$wiT4Oy#o;^Fa^&WpY62%u56`yp<|QqH_2kM@c1Biy zD{n9DB62h`6`zJld7gCM1s?M-5l{S61v@Y)sh)eU#of|{udRH%NBlZcuUaiq-7SHN zP3!YeybkPnd2K{e-t0krMYRsYb>{AR+c~ok5JTQXHe9>+F^z1{-FYYz*v?>zG`r%$Jzv3_*NqYFA};n=*=WMpU+K_(Z_qn% z(2yOwR+a#63%MTCH;bD|&gC3=D^?1-DEsL94!A$J005%@E>r-rH_mR@jhZ>?mQY9b zvd-YT{)XFa8Y1!YyO3;&$|m-YMivtI0Ch1sV8OO9Z=nJ^NJ8#k@Mk0fJ{@8bzv;_N zU=eQ)jMCShwSyoq(s3o&OYw*7iU(iEas|+8`o(6kAq-@-PmvQnsrJ z#4x7%4KlFa)wP`aDmN06P3|A7j838{sJZ1E-=Ac2-Gws{q&jIuIpVxz%q7^%P;oI(M;!bB;H(ZC1amcPALi z8_NZQw!@MqZwFk_bfy(65ZPBU!n#!=taJFx+ejJ(6gxq?#jVq^PG!w>&-b3KBsyqs z*wnckj8R0uy(~P^(R~yTjz35y&2GWBp8$s~*V;X+Di^h&J`JGzia1=xRlO9G-t`qwNV`>gRo8#vFyzC#-~zBAvi+Nqw7 zzk(-kNFmcCZun1B%FmrI_}0E+T9k|6@5e|J!Qj)l56f`aWJwJO-&hp8Z$`(ZiJ1@L zyLxf^`>f0&FFg4`%E{!W-mI{TiV3^D{EV!rlPGl0Bj6PCP|w-UpviGp@Hawk~Zl^pwg3BpMc~EYlY2fwAx2pc5U+~zh7tIT-H7>Do|z=XOg^c7KT_ObA?iw3?_6O_erH5*`v4|I z416dW%=rf}+h;eQ*6D!y;#$;ZvhJoZ3&V%#tWCZHA&C`}KCXMRnAN3a76?4i6{Tfx zW*#QE=_b=s&mP@&m`{X5-*H`kJ)IaXL{7U0YQloE)>5Sw9O<0y5I}yTx z_Rl2vo^MO!=E1hr0_`1v)8=Jwu(qL~pi~Ptr64!X}L6^BmCfe1=-sRv z-By*g`PAJPxMPhE!AD$`8A^GC3z?W3za$XW6NHK>7TtbA6iV#T-XDQQ z)wq0Lt<52m$`tF{b*j0Wn&7G6Ew#A+1%(KQ}|KaNDEW znlcjZv9Ej@pMeOpxoY?Ojm&(byI-tkPSrW_2e9q@VQJ?0s{CmfX<}W1Mml~CN(8;y zO+C@;H-(=@A@^T?`~zsek9)<}Em#IOS1IsMlvL?P@1VaAs|tcD-qvD+hTD>mx{y*C zgLMF9+eDApx1Yj`JCXmgaUdLv`?ihg#4h#nN<8Dzz-m68$ zO!v7E4zb(F47(P|yTwboYCi;~PSSo|(oTDu!?E+cXYn5gzn#E`k7X0z zA9dhUsp1D3Jc2*9W#?wU$j(honkibmEqKJK2!F#xTh6m+Cs1ul(SFNoCJ8UN<}}1` zjf~nedbECRH8*a8f!%jo$QvjWgqMdHkL429R`4l1g%h|*TQ#A#To*(h?)-^%4Yyb; zl7(bw?)swxf3HW$;(n}tVXr+M54Lt?H^SmayYgJE1ZVFZQDjf?_U;?*`u+5dbc15e zu=0x^{KjD3eBqxnJy6C}T9h5UMj(DQ-Ga`CKctt>h@}c;{K_>hVS5 z&04|RB84s)x+Q(2)LfR>2h(2FA_ktZ0jBLyekFt0c?`j}MED`=qB2D3Yxiryn(u=( z-lETJ;LZ!hKtl%amgrZRysX=F+nbMBj+*Jjrhm8<(X#Zh!=+!Rkic_e-=5?jm}3v7 zE7sH5-XX-XI6wg4c*>I14;9V&-B##48qc z$_QW%$GyPq_RwsBaS}|}Jw=zJeUT^aJHa|Xw1m1f%<>NBMz1N;<23XQ$Ag62?Pa<3ayoPb zb)VW8>(HdZ4JW@_A+qVi6ztFihj9c{XO{k?{!&6pysJ^{nj8-x{c!e49tYZ7dv@Ka zu<93ZaLSR*W(YuT=J8* z2rC3>pV|v`tJxzTN)&GI^~-kT>kXsQF-o&flaLlAWJ#`8(!~NCg7>z?d-2o&b{qsS z1dhAMK;P+1&Rn_5EJq2)NI;Kn(3E{)L2$iJjv4+tUyCx}PLc6WBAK&^ihS)g*jm0|Q^=Ch$d8lhhfpU_< z!Zx;?Pc6A-j5BSAbxV`i8tfHAg9}?p(Iv@boxvoKSCv^&$P9-j4$de?Ltaa(#Wvu&J5ffQ>NMx71(eI_rQB!52Tg(TBQvlGHI~nd+^2>*Hma-`#D*#wO@3sxs~P1 zJBa{N3Yx#8$R%>wD$At_V+=z&LmnsxNi_!NMf9u`zgl0@)~Z^hP47ybhpj?x^Y6F` za0O~^C3by-4+SlfW3)T(ML&aj77ZIFmH6aUeu+EXe+CH*c;~$%fW@X)7Md^^2ug0X zzK2__L>CIvbZrkUf^vzR_h5Pqx5)W#VgXU;-P75!KX`3@cG z-iqs^Gf&4HDBF7;u5cy&qoJC^!2gxw&aSHqGEI4%gS2L(UY9UyIV#>SM8#E{#n>A0 zc)Pi`hO@AGXEyMdsFozTO=RmVKvk)|wQ3W&+b0TKN=4lpy!NYhV_@l{iofAg5dw!r z3}cIcMD@|TS#0}O5L5nE6jeb%^V1+XI1T(6i-YqM?uCupFF1{#XpO#D`uK|-)#+gK zMPyzdH+|@tgS1)F&LD!cuQqQuCe^9Kkz24jSh@R=S#Dn2=&IR*{McHNTt>|48?Kre z+tPVN{(=kSn>dnTU-_ZouSM!=am`HWzA*rJ5kbw-uj zc40Zr;5p{S+pe4mQyw2VX_A%Q2$UgHsj^U+#p4;#KwtEy++7Ym2b=dw#0||t&*tY- z#jG{p4zxm9OrTjvHgh?3ujQOSx~-37i`J`!$<4pIeD{UB{CjHVfs$lN{V$lG;ufBL zRuJReYFt|leVB(0O@NWKBx=uxaaWCY=kOM^Il&{`xT%$LP9|SJ$c5PI?Tj5yd(l3l zFY<=3K8FvpFkXP>~V82y#S z=LMO`1;wo*r8b4mu9;8CIULtnAxQ{da5LfaR|9~8o-wU1O-;*K*lD`H(KLz zA-D?-h;}v6oVx^aa+uhVC?WC(pp7Ez2VLyuK$HgWHD}7#(nM&#zU9?C#SrJr8DP%Uo^nHfS4{+-?8)U(7gpk=n^Li{ZO0#bj zzy*|{Co3UjNdwSz1Nm!35-`u?5Z4oPobTNXTb5|Pp&NpI zJbU_|Iv!@vUq|mw>=!$iW}G4p_B-sPF>7-d()lROlQ=*OyyoZe?=WT>4Kq=lS~Oj^ z#J%30Vx_f`!QQ zxouh;mTi2com=s$pjz=XF;KfJ`YtGhPSKJzXb) z<`iXI6k-9Co2k`iVuO)0BD-dOZ*~e%Sa|!DL9Si-2)Fl@MVT6Fx%Zniq{uqUc!s}G zX_IW5v3#|dr2NcQ5g}i^;?Ti%X~8v6=aGEA33oPXD+hj5CO1DNVlG!`#4_l}lvk~+ znj%r75e8+;UDd=$iY%tMKDUhUkRh0$(go8WRN`XSUVn|tNK;xWo3^h=@L<=qCsj(G zZYSm+M4jH9fdn}JkWIU)CCV=SQ2GN1j(^n`B|N)RW@?JD`P{eH!uI}lbNNX?&zI$c zhkVADKJronN2LasODcQOesUJ53_3T)R6XViP1Lc@A#OS)EfEis6Es;phtTUiG%`37 z%C%W#fIWEz2eG1s_KZC=qYYNa8N$pcZITYfi^)8L*zF!ccru=_+?f11d2FY^5X-`h z6Qg4xd!~nMSEt?pcPl_(IgguJ24J&~@OH&)iFnLj)~+)@fD#F)5k=LD;jP&;Yf=r< zNP_T;vrnB5GBlj4rF$_7Q9$j&A2&7$B0GZKr6;6S6Cshak z0Qf&9VjNtxgCMFh|9lQ=H_K3Q4;@>ONe4;BTW+nNr^AUU#2?!sU0_$2|Ew>b!ECjcK-Q?`{8aRv<#7J*iINa;?KcWm62KY+i2mlQ~mK6 zRCv)yZ|+2YN_J@s=T(ZVo9%T8zbw!wLh2-oMW5l<23e~r`0rBzeYjN#^NSG&(ZFh zQLqD{haLIAqqg|HnXi#yCjjbJhpPocY)VOJPlk#LiIPVm`mVL_$VEgbH*>evXw4IM z_9~TZeEt>k;Ku%2ZDQ4_-F9`IbAgZYNXoz)soy|*EjP|goOUHUoJme3%=|EG1m;IO zXcEqzSNhhRwUPr=RpVB6r`f?)MYdUTe)PC!;sfgst+q&oold!-yrpzX27azNcb^p_ z-6wG-D9S(%EfER?3whO4T3R}Pd`|U<{ETOqQJ4%2#cL|{oI-{&cMQgSnc`}6K=FPZ z!n|jtOv(ZdY)Zpq>n8xn<&mL+yV=XY=E=iiW!?pnw})di5pSVQp>#M`D3Bufi&bQJ zdG*NN;Lxy?<GO$l67=n%=w`l zd8#QI*C^VClcT4w?z*LXVyZ)EFYz&$D#RO1O^k0XFirvM0B{yicL*e<^^v+krW=hY zp8zMV3rCRd1zVr!7Lg}ex3tuJylg%-RmZ6PDJ&bx`t%Wf9frWsX0b83egRjT*pKp@ zzS?wEd7(c~Q%R^)fR%zPSt+>SOQ=6+z1QGt?JcYG|S_-DjV_9_zC`NSSqE`-e&ay$3g$16W>h9iOrKvKqW-^Z*@ zw!u?SW={#7t(w%K53bl0?W<;s$JlJG z56mwaMObaJzuBaH$G6iH40(H1&g z=cEM53CHmVun3CcZI+F?>I`))CIMA~<@34olwJxeL@lcF%1?oE@BfOBg^n$I_;kjM zzGH!c*=Gyc{IK0XMoqIoV;SP=^U1dI=6U9lKH-Y|^@6eede~u)SbB~;yu2!eL$j>P z5nYmcRZQv07?yI2Zyf9WOMdf2YSe_$)> zhbYUdJFmfz%bKb(w=3#Nv7!sy?tMsujGpexYGB%n6RX|TCGkRIorP46UN!1qk8ppw z0Gtj3DnHl3!JVu1qNI|hSS5-oC|x=ac4@K7{6k<(eP^OhIyLJ*c>w{6odY0Nil`jgZ0msI>puN?}hy!3^J zu!>-#-4L7Z<~=;rQ+Kxrq8?zHdclKPo3K#io)pz%9UbC4`>kM)UIQ_&Y{sd4?q@mZ z{alMY?yt3f;gvyTnfmncBV@RL5y-xtLV=8-;EZ9$E{M&T3=9Dh2K2FYM~CD-=I>SE@QcosCPG4BA*n zW+Y#vgjBm?^^`(2M81xiR0U5yJm#Q0&4|B|>hhyZrQJ>PX$8<5+cv%ASukr%OfzN) z^xU3xnT-#;Z;~>;fn6vwEtM0!ynocj?-(bnAv*9}Yf zoLNc=?jB+#Nd!QDV>O!W#Pty;HKy}bkuEgF49^1f`pN<9%e~`DhC50f9HP(}do0it zat)aGD;mJ^XN}~P_`iT>0Q@h{;O}7nxBZV7piZJ0kiJu0qoAfFr~2z;`AZpKViu60 zV1a3vAp`@nU7ljvC|PgGYMKYlYq?gw+KldNkoVL zp8UV00}4Si7Zw<+CL-|Zt;+vD?_dvb?Hvk00T{aF=`?%BmBhZoPcJS$^hljNXShW? z3sTfKcO%G|olY7+J}rJh<_DmY5q=_ja_w-4)JL84dDjsEkY)r(v&}h%UYn0@?yGcl zyvHCy*&Iv$|K5J-U9ZU4fx9`U?2~h18K-{$<#RITN97ehJ`R%N_m0X>>CFzyPXWI1 z#IYO1KLB;}M4#V`%*`=dV>i|=_zAqEMhRfEy`iSf`L}_+yAwZ_q1th(@wd_BYM`q` zW|Dd!6Ado-uLn|zJ`sILB@(uD6%826DEBqpxvB$Z8_IeJ$LptK~ z`x@KbwF`hH(MLuL_xlx-{ui_G`$&VpwXLu9c&b2Eb+LSzka?$ z%i8nw^Hp$3w)#|rz4=+`@xO#$iR(XVe;WeKMcbY!DLtpVgX)b#%2QP22LHPMarr|v zWn>y1pYZLpZ}*$jbou=M05X@a#=FUUYy0oK`2!#vkU}O=(;+p-YO70O8g25CoJ${+ zHO6i}_+a0udQeie$<_SePk z`w=?JppJX@5Bx9L61+RMqT23-lZcU8>kw;6+jU3RPz}m^AsEw}&N7Pt3 zF;B$eTjt1>-Yo+$+^v86UHXf!gd%UANG!Gd`-~K`fizJ+s`{LxI`we*{`GU-ZLx1r zzw%wHUcgT1Jhy{Bpi|nrzDoZ^@~e|3{JID@96>j${jKgQR4o}$e2-&KPVt-G;uWU ztyKrajguA&(^@Y+sIII3)J?ZD;MweZzhO6lea_8{;TFE>%=((!^_^`xA0|>Ew4xVM znm*|$!uS49d&^&I@)R6)_rVb0@M-w%Fj8% zW6TM7`VhX>5S}7~#izzoYF{nE3|+}IB~^YUiGotfR4bgXNk)^R%$(7};k?UxTs>he znsF<}Ct4QuuWn3SP<`deJ{4F_u^ugdVZZmosd}Ny+kx@O>1ltW&lCE8Q|rB~$)4S$ zxMN-6OxghuT0#sq8tgeIdY#fU9%*ndpWl?MklYpj+areO*_><74PEN6Q5%8v0b1}* z%N(g#Shqk7Pn#%>iDK%a1t(?uOMg#Np{<0kJZ+~^VSTaqzSgxz+N5)9QQSe2V8vf4 z+1|>o{k_(;zdN8k!)xybXwxKf1}lP_u+(9MIr|<`vm%#orMeU`VK326I@<-+-vjvi zS`W1Ytz7#~o)2oyXNshO5atvEjxsB)=l~y%?)>f7$qo>81_+WPSpa1|sAf0T92U-k zT&$VOq!wISom{n^HHl}mu7d8VypFtA$G?xWb35wtb%MQKMo5JdIrWq$oi=Xr7M}aR z`*LYBD$~pf7&@D@E0Ult!)MP^dZb@A*s#tkT&oCNreV!8Cv*EKGwCD7D2G2j^K?%1_<_u$HLsDYTEg^s8KXHwbDQL!P=;4Z{Ax|- zl>7rozuGS4^mG4ZZ8UJT+vWa7?ohNmSWO_W*XyKUtZv=7|8h{HKXyfGJO3*Q?$(vf zRpgkt9o4f8GW{N9eVHpK@GT1Z7IEm*sL1+K@@_o7XkhN-KqCL-!=xhX*AnE@=0Gdx zJpOQ(O?bI+D!q8Amh*>em${hD*ZN3@Csg%|_eT;d5mu4Iez0Aych}`Z3TbjbBu*HX z$~pt?k)9ON2Cs1`u*Qt}B?bBHZ0M`3dCO+x>4s`ri$U?sox?`D$yF%bb>GqsDe7Kq zqNl4BRZ6Rz$-4eb%5JCr>>7j2mJs=P^T5RnPMqcAFCym#7YuZ~@s}_1 zPpP8O-fKy&%)TC~#xBEYwe>iqd*9&SUxq3Ow9(iiBm~4jU>7@?S>HVUE{H}~gt*bf z=!4VVfdT+MX?PSe0QiI5Pqrn>FTKS>IYV5LEX)lN*bi|TZc}j~-%IhEfdH_UE$rUV zRzpjte~v-n(q;WQXlXVVyf{4VrPf})kJ_F;ziZJ6Ak`y3qY{WNsf3On%tt(L>GbB) zC$0ajEDoWNPJ`J$fcS^`5gRra%+>;uPBg@>t>-=JL+F8+;_sNd>On%ToI?K*7_G66 zV@ck-t&Qbk%Nd-Dh+#w%9U*}?O67RFWlGdR&sVlc?k&&S3sj?(L&t^BgLmFZHigiq zps=;!Z-rHJV=6PQV@MURaUmE7i;(+_ko#ovB;)9?lnhqs1aj=l@={D{4{PpKD=%okDwHW(2J)pJ@10`&YNI{&gG~|k8Mv#w~w=7zW zX)-qBKx9E;pM0-pC(5GHK-rP*I#gw0AI;zR+-PM6D3;p_$&wH-i~I18tU2hh`ES!t zUi5+e2&8syyqykB{OD>tJa0U&ibHh7I+YLW%RFB_k)UiH#l$=@Z0NfaDpG}Uyx#p@ zIfEri5{<}vVM4H);f8g6Ehv%%GWjj%7aavxg2UM!{J2GB{B|$igKeqTgv~nHV`*wb z++popO=iUTb~x?7gL-$iBHeQ&svKvsb_R)UiYV>RX!)fkiwMOpAw92fDIJhfi<1a0 z0ejoc?l2blKtVGaYcCFF1#E&*GH6P}>CN^*2P$_pMMwX}kZfGadfsMc?#JH|7)R?= zWL@u=V^mPkH?MD?+;%!P9xB?LgugeU-D&1#z?#fykd=3TPPlwczDR;gdQsPCnQ zcmCZ-V9;5G6=)jiq=asSq=3_FjN|4tkvi@(0+l7Hu@m7{Bi;3BagzeQ$!TzMo9(&+ zJ+rD6iy!$1?g;@a_v?!o%6NdjpUG| z$7w=ouxHQGjbM@#dtob<0eb7F(lmDptV&l{Pd=#xilKH(zPvZB6&UtH%oG@V?C7e9 ze^{#h12E`0b&%p}(qyZ-?vCs@GBl;T4W^XG;=?mGF1&))0FxagGW#3mP7uTX=!$!;3Bg2U(1Nnpwl} zzeM^oO7`Jc4i@Uy(lEWi_C%KxX0fc&yDDZ7ohgiP!M3TTt{xmXnJ!>{1GlTN!L>i5 z+K_r5-Fx81bJMUm-p)@-ZuWMrqq2Rzp!Dm<7U$xVz6F%g^OLk0UZc_E3s#)Cf7G8s zNY6E`CXy@%DlinJ!So9fXqCXv;#+@>aTGQBG=@tJ8?bzZM|<$xFO~yI%gNAVzsD)? z>pC`Y>n|6YZ^@(HZ#;OYoh+)|_9~m&l}kJZ$}DXdA0n0=uQTbeLw$1YpAjI;ZClvG zwI*LFDFSZhyDu3Yo;0Ra&n7Z%SB)PIl(Y`de1NQ_TdSdQ65p#vm`&=Yv$$+@FB0>o zytlOFom07l+Uo|2ZVP_Rhyac4#JkE2G$ly|I_Nk9!TeSbrGHMC%sz>35H>iU3B=4H zwfCX{XxueMh>qYy20reMbtcY$32BwwdiD%eua9hfS{C8k1yri89kF8f;O5D0ysstR zc5d8n?1jMpQt zuKHhP@0tOs$p}T}=`19TrqUk*s8iGJ=7vW4fBKKeBp5iM^!lik)`ApNdYMt}sMqv< zu$H*i{NexW(O|CImiokjdaV*GsJ~xxyk-ir`IyR z#yF&-hnUEy$#LWiq*fnd^5@S^LN~y16L7ReHC)@W*i)}k;uD0Kt+*cmkY{1$v_S#> z!i)8)z_~_HWe^vuA)CeiEfxS3wN?_xl#PvrPl?-?`LLScA{Vfg_1?tmE=I3s?GW$Nl=cxb9}`rHWulgO;3g41c0_= zv}t??)X6zvYt&V`7B|kRorChD9{Mb54tyvtefm0HC4tX4Z`cqwl?B92zRLVj-_XwXeZMWvB4)mDtH~pFS0> z0ojqXVwf#FhDQMa&=NuScxePISvIS7*fAudqk+FzI1^xiXhu+$G&tG1#({?C6&1-g z^4$Tv3Qkfd*$sa;3gQXW9YQLbKIBWnI4l5o=43lDl531by-jlst?%6DQggJQ?uHao zSh?8*W*|3|^Ccg6OD$cwClwF~;9t`VBWo@OtYY*g$q$Tf75e1Wt?kbEJdK7qD&pF% zF|MLqoH?mYHCX5Q8()&x%UL9c#PW?DRYN#=+&F|xJiihS4`j<(YOsYHyDPcLSq}?c z7Ps5NvDzU!>VjEoBcdQoY65PhCyaKmA;QD$s>sOBZ{=rZQi~b%aHcXG_(2H`T^3QW0BwWw#!P@#KX8(L71vj zY=!-ld+il!PCr3h1NocWYp~z15|nvp7j+q`UZ4Q z!&K9)LTkoi3xAX{J>t`NW}~d+dge50QMdKt_KS3fJiG9B8ns1ZtgFq+exCP@$`ovO z2v;Q`S2>|_)#W6c{CWsipo!V=1@K-CovXzruy)f6N@Mln+r;37xQf+OX%mhncE-WT zo`$Z6$eHj;yxnF~_F;;OzQ37-q1(ycj+R6~6_9B$n}KB-?Xxu>D65+V=^p70oMDJl zy0^M`TR%YnzaT2~kEDQk`VP#M~;H0m8=P~0qCB+ z(QKTR=|rj>GKW(0+RkCVNyemq@W!?I4aKYkp=}jt5%(Rt4N?N zAg6Atg?jvJQ-d>Y4#ny2Ad{Mgh^*~kBW5PscP7krcndTe2huCZTC>+IAx!1nV*2_N ztbV0bu?+nMpIhyZZny`3R`#=YYtqKhtgfB44)2y=u^SSiYg1LI8nW*8GuR{sjOds< z$X4ieT26m0(Vo)QfD8nucD>zyYlC57=SpXx@jFrdrZN6(5cQFli!PykbIDUU`EBt} z429JAi_yt5;gb6YI^hwRpHWLGQJK?pHx8hIdOvPNU8a;vEu~<+?l;~w{m23?L`?)L zt9Js$G-Hy`@S2K(jE?^b+UXtZPe%QFA2mpFhWTk5WM_;KnfiU|Yv6(BT%Qn4cgS() zf}1)ois)Pieg!8mJ(Hhakgs_>%-VK;dSJpHh};<-YJd=)>d#sf%^8}A-#;yB8jyPn z;j`8>cN>Q*S|)b7iCVeNt$h*~iJa>7?tW14)rx{s%jYX1Z^&VsQn_FHfB$sSJTL-i z9VWGdq1PltII~7ckw)%N8d7?-P1!Eex{DQgMrQCyUqaXXsm9K)wYkz+LzTN{Av!s^ zynF}2G42ln_Iv~N5#1;z?sx`W!i)5*DO85s0DeTv6=;X{*VLQPkCPftkn5ln*!u%O zNWGj+4mA2vb@^)u`3??ye!$yszs^YLC4%~M)Do+IJj|^!Xek-Z=r*sViD9*~!`ATD zg<{$FY~cM4$pX3`=-=aVf5_&Ya{wPYJj0i^ej>pvp|k6;p|{(ggnc25xU2R*zBREq zW)>`$Zfh^&AXZFF7<5E0lrs@PD@zM(EmAa!pmL7I-MqC0Pgm1ta(xE@^~C3&5aX6( z4}O!%w>mV==T@ctGD2*N?Tj^vZXc9@ani`uvv$Ts$d>O3!!2vc`~c}7*HJ>v9{^i= zMA~F-@xTmuEfBT*|COoM4Rujna0Nq2F~W^eZnT#o?r98}%+9ESK=Ux$KS0H4pKs*Y zguTy|L+LAVJ5D#huouYC=fjf_0B< z>8*`AAGOv$nd2GjMgHkiK$u%=2Iwa=evKbf9l@}Zub?@7n(dfkuCt~l)mC&{-$4Qe z?Iaq9#|+a@QV8Q>sPwAj;`Y+R*^ny;JI1l`!m>rXKLJ2JBA{Y zwzBRMm>%8E#Xi=U+YA*}vT>|gHaK?t=VKZTnpd_({5xZ95-!x6Zm|=zhur{x?*CQ- zvLrM)BRS_3r&doiJ10NI^*ba_0+}5=f7D#y_)#LzL+8e|5ErfJHQHyd?oM=?(c}g3 z&|qVdb}OpPrOp&Ie4>G2u4FP*apnSE_xWp*KuemRAO$mvekT%RUr9joalD=-RQX=` z0SR{bW@SAYf_stHaLglXZE#8N-a+pbJn3N0KnF&p@M!NbB(n+#Ls6afLIMlw<50Am z<*OY99R+jOf%1#WB%$G5>8S`ukbKQ(T6UA9V9@^aR2~ZnKp62n3G_uTP?{0aaP9wL z?ycjZh~Bs11(xnca_MfAj)f(bEX0@ZO*kh@e>w58Bzn>I2D3*A#Y0b3NrxPS4*FS>=;sBOj6C< zO%88t%#pBKnsJ95#2jbJ=u872GnuPe0&zz9Cvo=j6PxTs%GbhHNj#LKmTbCQYbP{z zp2)hF3TwTFxUVXVA7N)E=xYI(@ge^UvnR0*y7iK>+;cjVh{<>bD{2nvX@%qn*q$I7 zhzod_PqZ0Mma(>f@$~UJU1Sa_4eLkQ1rlD8$0hXR%!oKTm|mL=wXi@O@KD5AsP-fU zRnV?^l2L7Vi4q@+kDAm_O#Me*zL9X5>Q7$dA6Z%Nt0}YMGrJX;sq<94-)idZCs`dN z3Rf0bT*0Q`RiC3ORF|ih4O1fxfU0cPU@>~)z;Il`fRB3o1 zQ15?%i){~zZTCGpXD$&)!NFh+CJM)~hiA64X13$#H8aMetC0mP=6)$3>>hf#ymOd2 zQeCQEoIQ8lPZb;9f$@gu2O@f3J+8(j4xzZ2CKzA!lxHCa`!!#Rzy}J3FXR;JZ_wF_ zQ-l)AL^1VcG&X-Z<3!S-ikBTI41fHXLtg6BI%>lhjD{=(vPYV*|30@C@FFv zu;qVwp!Kn$^?Cj@#h#vwP3*8#kb5mRmMIU}n#NN>*0MJ!2&%C%RU3CvOTedmGobu) z=o3D}YZ}(}`wAUqaPD+$wD+65F+BxwC*mqI76sH?Wb2O8XItHk=RrJSt(7&jGhRrz z9p{|Zxjp|!Mdip)%f+vdi~;PxFMd@kY9@2R^w6i5$y`}m)TxoGiz?f7{KTX*9aLBR z88kc#QRCP~nI@(I2@7^r+CLtXTclL9;KviB@l+|$+7{|#a5xB5NT*5e~Os9yoZ!Ykvk} zEa5E{EK`*iU;dm{W<<=ZNNpQnH#lm=8>6ywl#ooTz!|zVrK7A{#j&e3px(sl-T_;P zD&!pEo4n9kcD&UmHGhQFauxW7WB7v{sRhIw$0E1cE|$`5m$Bcfmt8Zr@@ zX~XtgwqoLzENP>X+S{;s9+W5)-OskIk96YFJg2RU$yhbxL6(SYiD0#Hb)U-lEaPMCUKlsW~AI6|MN0W0_xgv_Z?%to$S*4w>C5FSucWS1r-NHwqr0 zk=Trn8j?7m!lMhD5!!OJfu+?NF^ltzWHlOjOq3amIA~CINZL(90}>rLn~2VJkG)x? zMvJP1Gjy@X%CwwjM%;aDf37W!Z+?B}Q~Oxe@#Ax=Mw$06Wep@w^%H9u)z~laxQ|Ga zwjS9^>(F8H5yM#f$CU0@5=|$tEBm#ZTm_09v6FztD{S{_Vpp&D^NfQotAijv{VN5K zz8bAq^srVEX5ZwpLbN*PA;hNrQU!!x$YpW0=q+fnhaHMkoE%*9VM&%Bp8gJScoH#$6aI%meKiti@)^-ZnC zJ?5j1@!9$DhdX{K^TPZ2=9ZZ$r?s8JeA_t%9rbn&K6IRtb}{aHh$D6TJK|R>XIu@9 zk?}#HQ#|Zj3v6D9#jwGIXU@D%u+W~4uwni&1O3P1`-UfsyZDCHv__Bj@I&XNC|`Va zN)g5$I(}DS-<_C_(J0m}R$s5~6@5El(wbFsiu;IKH|LAoXxq^v zYjNAm8$F_8EEsF4?R{-^zmCXabRFpn*OaqpH1gQjy5oSGDJ2a%eeXbiZbfWfoR-Ip z(nJJ(milURGLL_Pn6pZej7c_s?{6cRtEk zsQa?>JyvX>f6k@nw*S+g;|*dDm=b@?zy3?Y`%R1Fqk~FHpS>xae*RRqAJfuh)y1dB z_l=teOD6eg&-DCGqn<8qLpMaHFkG5xQQt;kbRhgq`Hh8XX}f$^giQO@^2 zuQCyZlbM3u@3L!#OU-A5cV#uvVTifR02B2;+9}Yr6#0;{CgkCXt>SM)){}N=b`2pj zmSLgz9zApQk|VNp_BxkSf8viZTsqr^?dm6;oVqo&8HxvNXRd|2oDPztdlnPsK}&g+ zoXDj*mTsMlwwID=B$1h!MF>OQrYqawr;4mT@Cp&8&f_ta^zq5>*fb+{c8f95h@-nJ z#|p1XGHU~KW|K>u7<0&Q$GvHYRmnl3&Fp%pZSwi(U(i!MbCP^==|?u^W3(TUUlc)X zo0BRN^%Hp+Mpr)Hj&>GD)dazx&B*fO3j_wG6P0@A(S~A=qA-q&)XJj}tp6j@uO)!;RY~=bZT_ zp{Yr3*%b4B!{XgwhxlaKt6EliC!vW#6XTv)e!%3yI^gd31op#a*y-p>==IT`x@ws@ zsOsxiPHT0Vi%I*9Da*-}Ev|ZqQtETVHYeA1|9x!PieI7g$D$QE3;Z!=G7&;;balg9 zWB$XJUDoZh(K{bj;9SW1YK;9CC(3w!Ayo|ypVV-I-f*|ITAXoxv{<6k54{Wf2o-80 z`%z@%K76zA#nps|YudZoaG!HatY?Ydd<^Hc(rn3*-YY4MowS{4*E`PkrmeJ*_BvPk z^?*hLqmEDu#28_9tN;5a+sh6TGkT@QM}boNdD+9Q`cGRl>#{nnD)xU4SgFytT4-n~ z*s9SuvNoO5y`^|H&wQ@2?1NFki>K^74QZ5P0vTca z$~zxl(>CO+Po7`vjM2D{Wc&q@RIaif@X0F8h6QY~&qy*(ZGXtuX?<08T@(5{SuQQuF+mI>jNwmy<$fA=Q;FNN;V#*-Q>kn*|>s ze-3tb`3y<~q#g|f2CRM*Kp@0>5>^CdQ=2-xO?-RsPxt4}Pn|#ca@L2ev->w+{pKg` zpq(K%j1Tz!^yj2aVzA8dLdBrh`GOLO)71r5sL?Z8e3pxwqs&_rmhQ`;ww>=h?cU8Z34$1t^n_aF`G8gMtD_1!E z@)txsGKX9psKsp8Go6$uR^jF$v&wtbu{&|MA`1eCc#Y`yo^>BUxkrQ}B^ zcXtSJdY!CK!7p%n$8dRJF~4$FYxWx{)1vh*sDOC+`O8mGlkvB2`tPZ6zYk3J4Brl0 zEO1`%>y{dmXed@q5;n3nPSMaH=9dJ-Z_r;e|hJQhoJsrXZ*Gg}5_Iz}1w(hTJXEKUb z%{8AS)i-5qeg6JP-;G|BVc>-YU+I0~(Ub-2Ur>jM&|lD&UomI!_>(v1Q=dP?IllUs z*+7o{Bi~hVXhJ5XG-sBaRkh3)^5c=D`9&LL%FAkg( zy2O!@ktIoBnc>6}zx1rv??N@}+)ICx16EK!ouw1KDt^&!)h4|W(%?EV(_EI+q(V$7 zmMdc-t&3X52;=bK7|?R#la`17C*X}Ix%_?8w~#`Z+F_*Rkmf|Izw@s-rO8)qGB6gqxj!Yj~~ zK74wJK(q|;h_`ks{YA?g)01zB8c{RgqplpKcx44*yEC7RHJ7A@aX8B>D+X{BUx<8E z@7zi+i{UL4akrE|uPZX`;WKPANnM!QlL(itgP%Q8W}n|XWtgAa^aZ`pw|Jr{+V%qd z%zkY^g9sC)edh?0Bq~-aGW5&G| z;sw<6+IyFRmv-l59q!B(Xv---M-rD7B{An0o4-8Y*Smcu{;RE?r!YBtf70O1v4jce zyi2M(hZ%%w^dD@rPq*wChfTw4on3Y-X!XCjH@quA-oMn}RMGzeXQYV1I+hCo!#aO<+9I^k{FTH9P2TfPj@wH&$gFl zD4XX>^jPL%`w;*82xpd3I01J2i>*riyfDd?;AWWSw{1-pVL3TYqDPZtgBNnUJ8px1 z?}~J+NLY`LyluL&O}|iOfb8eN7P}u8^0~QCl48J^K0V{IQfS)?>&=XjrWbSBVM_hl z+DULFY$K))i}HmDJz8$9<<{}-_JsDAD{UQf69vNyw*7$S9V=gc_}0C9l4=}MZ*2eG z-jz0iZFZZYScy8ub9nQyr`w_dMUIk`(6(^Kqj}!t-Qlhj18%KyT&;4#J6Y!|X=G53 zj@ysMe1>jCc`{bBz$Vd_rRV_DBx{;_SH>esj7{)O@?spjCW+7#vEPTEK&| zs*9#~mFsM^?b5%0Mnz6enGC>39TkUk&zR}Ve>#!}@CS&fBQ3tlJhH0$Hb8bYa-IK- z$6)O{;G%4d@GK{EB7B6^Uv+1;yOx`xadIlH)*8p)RHi3gjn`?K- z7`TBt)=?x$q{?PZ0*0*sqqqOmFSc1YsMZr2L+a5f+_^ehA5o#vi#uEPYG0h+rRQC( z4NDgukFz}qKctmerqmxvTKODiU{L+XLPWB8QJdf7O2VC7>Pqmv57PqPfZAAoeHUtT zIF=B1$m$0Q_M&$Y4jXgTl=o+JGZ5VFA{HJM)Lv717OK>G3Y5ML`Ju=@OX|3nUnt3A z(W`ulm&YbHdc-8xF5?}jJ*98aVW^_{pVv=4XAma zc9x;Z)MI#2J3MVu{T43gU*MzTdfZ}2)LSv#X$rzu9e+x`?3~7o_BLQU&IcqiQu6;k zE`d<~e`;3_28^=*Kl`tjCjy~>QP5DqU^EPL!2TNr{lT$3qaX=X2kkkNkY^g0R5wDt z6tFBO*R$$l7WPV?iCjNCQm|$b!O&;5Df0$Q%c&lmMVx(V$HKw?X--b~Tf~d<1MPhD3yup77R+xofl_tar!W#< zTw~NgZo!|%cwBTt2H=c$Ci#xiITH9mr1jrNU+p}}8F=Zr7Z<3C0WT;(H)FD02(Bdv z?Xyrj3abQ@1RHqhItqOK0=egh<;7luaS@uW4bi=4I`b#oc9^yJET7M~g*3COejw|o zvh+<0Wo`M`K9I_2wdS~PC#thy)|P*$v6Iwk&+a30Ds!D+!VJ!BxrNX-%$9W$_xM z_QlSyx0TD1RxfU?)P}<{8TBbg`7;?&SOaDMf*5x)4)6F7dDd%1!}q@zOnch9EF{nU z&7vfH33Z$%XHT!Jv{*T%vKVJsNeq?AM>cQDv{+%8aHv-+5qc1pYyn2scngXK76fuWloRk`s16<;ldeT5{D zn{?ju3+qW?FSNTzmF3t_cFG@xp<6OM3Md4K&AEv4Ad+ESRe{d4r>A*t-ZX}N*P11f zB|1PQ2>&52^IPu6=mwoXT6lf1UfepCz;s@L92p~~J%9=+-z`p~ z>2x2|1|(=cNbtO6#2746?I0a7t#16$tkFZV-VFW5o?ffP>KS^uekmXJQE~^m0N<=H zP~WU49Ac=1Ugpq6;@j+wJY`RR_tE}dZBX0LAVzCig)PY0V?Jo0Jj!6V^X(y zz(;o)onkg@SF!?dxDZ~X)%AnUKB~3pyIC(33Eu>G@wz|$Q^9^S_Axc8B4fm;Gruh> z?J|domY7d}}70#aC0{qOG^jv>{J*mYC-IZ*8Oh(C` z9oFPTBP^Mpuxf5*q)T-}wMX}qUAu;TT_>zazt0hoUR2SiqK9DTppL7};$H&e zHDHVyiyjoMYp-r{<1ZY1%sYLCSF&0fnb!AohMrJAnFv$Xvaa&7XSU?m9{Fhx<+Zk5 z7-cCu*S$pjf7&dj;dotj#BOy>v0{i6p+05j8MpA3v75B&_?5QsCj4sJgj&`2q)xs}|v6V(6HMsot?s{?6v5jouS7Oim)y9l?M zT>sjPpZY*MeM)mT{TC#=^zR_LM4Y2HPKFnQ_cCe2k$ZHdv3>BUYGBj!k!&->Psa)#nk&uB5oC;1yR{b z#ND;I%Zi}`+Gleum=UK$o+uoKi8>d_hy^`TE;|>WnA>7`!G64Y+W6nuN0UV$t7gSpG`R?v7Xw-^;Kl3lBr1JQC7`EAJ&->5};+v~`H6qX8 z#_DOE0&+HQR|2H+^@v|I& z(`?A*m6;YGdG(Zh=~i)d)JitK@EY#|It+xoUt-_|9Gid0u|ER5x)0lT$;ST$oeHmD z(#M4moGXuoj&nC%ru+pdNYC7=0KIU$c&MQsK!cf9MPtu~=Diy6t?~niZE=}@8UY0X z;j(vl7iyOoJ?VqAJ%D(q^60Khe^*a}kpS}Dy9g|RFdP{zy>0Hg%bW)h|A4Uq2>ydi>ss~q zJyTfvU{8GUW(y|&XxQunp-?l6!Ia}?DG!*59)wTpUC~*T0+V$}{Ewd%AF+pVBE&`n~pq8u{uTi6Ae@+Ti`fo@xq7zZSkG-{1F(2bVIrPJ$G z_f^_IH)6#23li@Z*M33!m7rL0if$ok{`i}{6uHvYilE^Rc7UjFeIJv+hVXVlz_!X4 zL<1W1c^sN)jWiP+62+xi_(Zu&_e<{3TFFYe$_?kV2093fuk(yEz;Yz-Aj%9w9SIiM zUX&C?UC{LS_MA7!UJXW!#m5#x;%xb32!rf)m>S;!kwt_O$tMuywG@cyiG|Nw=FyU7 zbUVkI|F&^AX{@yO&{jRbtCbMk3DR1DY!kEjwJZG`DjcO9FpK6ztT>v_hRt@t!5F=^=tDh>E5_r=N5lx{O)KDZ9#HW>AHs@JY~6fC^t4&KW6h@j z^I0ze10SBoUS*Z(n)N|c>HYzK7uXI)|2uE+ar*T4(wwMe19 zgY2dq_bxVR!iNAEcdg&J6Z3b>E7Zf&r0PMklGSI?!3V_)l!f&nDAYhBVaq)Vb0P|J z3f2J=1!XFinAU|Q2_LNlrBHwJEtI-wl_vsvb}V4y6i9!LhFw9bkHrCnvO*2?$x%7k zbmichy7D-gecHKDul(>Dv`keMIaLyQRNc&V7F42mIYt%;i3ad1`u}W>Y!Rhca*QJX zBGPMAQLyCyuTAhLeGQw`z&z#`+DtCq*6j4|KRT+cVw})*6pl=JMidTt_8INptsUtL z`!USZ+(;JC6K#kUj4Q1%1Q}^8vzkxn@<&A9i6^0xNK_Xz=NLzu)u$!iKz=gP_f8(LChJQHk*!gzH%&6;?ERU9%axm-jRx4$D9nEu}ew$ zjs3cK#2bA#IIK^$?x;}t%>-yj%XaEkw&tvD#jjB6+k4Mazc9kx5SI((!~5!mDPNtT zn5F+jGYni8n@CT4R(1Ua#huA?yr{mF{vmCidsDKh;TyUkdYN3@YQ2^R4A=9VLq|!? zEZ&K_$J@8cdi`h|q^%)eyouAZKb=}(zLBka4|K(^YPg&4CwK2$F7$3C>)MupkW$~` zrInC&hU>Ij$qmtI*zaLn14aSK&C_zvz~#~+sWcC**IU>ytxbL09MS`Tgj%5 zD8Q1?Vxa3=a~Luz0r%~tyUFg(P5GrgaQF*)he<-|e)zpkZ=05O0*9~&P^U<77>{XTifX)zE4tS11JkdPv9W(F|x?`(MQ;A83L6f$b( zMJAC)yBXI6Vk-@%i$7CoS4WdV z>9-UCu|#c`!%PUk1zd+ap64o;8gBKD@hyP~S;Vi^))YRBHfYjA*1+YxDxh5HR5U-~ z7bQU>ww(ko&?S;=`f-oo`x4)@Sf+0}`*EBrUqj#zf@3%@m9_FSMb=lfbIeMNCUhDqUh+W{Q!j zp1D7X3d(|Yp!_=1^?Iz;g#mXZVh7a_iN1_is)nJVsLa*rYko5>8;JSV)d5EWzASJu zPzHO2IH_zb(K@tUg^?sI*_3Kzf`>R^Fna7q~qPvlF!yat|^*F}9rt3NtY5hYYX^8kUsAgz7e1vK*6>037 zK20tGi(s{5!MbRtyo}|UsAM)xgzVLnpska#iz_9u&>6KvgV0M}i`rxnF8pA>AMJBY z|Mf_mwn7As>fH&eoa@^!+>)u`VTN!yI`kInCRf~c{6t?TE@}-p*ECyF9;eZ2wGjLY znKfGyFk7;%LwLxt{HXO~B(E$}o!UAh(E3?C;$xCYFS~E}p_q1U4%ALQa?(|-`}?kL z#ygaU$QQLQX1H_}ZgzQk;xt7;zC%_ z9s+pX#XbL>RGnOEb4q2xHybb&5Pr%BcbY`@h-1C0WQO>!d)NE&*ne_K>~%fWKiRjl(+l&#^xox-Kg&0E7AD09<1!>jU(du%i+?r-nR<3(g!J*8xVI&rSR^%4UHK*klp-r=qq3(LS9CU6a16iSe z=C5_72@tm&gvImMGbh(Qx(_$}|DKo79wc!B7!cLRLB**2io*O~GUuD>AP-9zc=P|CXA3%R&KU*!$u zKXeui4DZiEGaobv6M4|wmZ94>v^{ix{`w!n+i8A4rBRtM!{1yzfJBbFuXU#-7C@TT zoQKr1D_uQ6jU9Zjs082MH!bK&yVZ=1&Ru9WVcpHu_2b<;-2C`5v&9kHEG`q{Uf0C@J{bi4*=YI0aN*XhWUfz>Q1Y^_FsVV!HPL%7d8-p zsJtb((lrR(C*bM%yg%E}*B zDFr)1s9}=XjfBvE*iR(utzlvwdRO(|b@b|5AJ;9;Nv3ovU)uYXBsor%*?ti2yiil{ z3knC5lEM4&jnFtTEOPxchETvDMsRjI%M(}wNXP-DPfw0^h}+jyBK{R!qR8{X2>BOv5g!hZ3F)z%tqp5OIvt;bOHbsFvl4R{p6JWxz zo?ya~JdAf2U~5V18V~F?sq?`|Yu~H<8Wu7QkK75zz=D_HK58dscW-55ShiU%@f5TP zmq(%YnfjGU1Sjs-fyI}%Lf&DjP=~Q#A?^QyRH47HNj-Izv{zidX2!Gl=NnjVB=2fG z(I5#Q(|j#eS&{al+z?|#`xmLeEDfnsEEI#VR$%Vk3OfiJyyQ~CfDL*1Ihu}WR;jcl zy#*4-P(|M9S_|D@Q#6<148258scv1YfZ=iAEB>euYTI2r6C^L>( zQ6tLEd!~wXFMXPUK;>{Z3X*gJhUM$9fSv3#^x{%e?w<2pi6FPN)J{q_X)*6TMl54X zMl3mQrx*=ri9YeH^>vf8ge#wCFYeb%t?->-F@n&Xv$yPMGishSk2gij=RLAdi8CSzo#j(E&d?e!T(^D@)dw^E5Z=pQL{As%)5=D}h zbIWj%K}Lq5ffVS#_O&iT-##2IZLrBNkXV@|v!$xFWxPKNkEl$MBZin5d zmJEjw`~^9hpS+BP>mb>;B3Q-}1A*vx<3FX}KiQpku`7H?yeQiE8SnX|COju0^F-RB z={0HJQ_RSZ<4``EEUX7@CLr!i7fdcV-(7^&kJLujZbWVhPx zN(F`j!UpXAf}+{;c7sRcxOXJl<#Zi~XQW^5+y&o~#&%wVF(ej; zTWT4|X#obRYoUJ@A1ba=@bE5dvj?a^^*-kC$T_jrBKumIfK!Rp(Xbo+_v>B1=m@HT z!ZF(8mZwoIO#gyxPO58V9D+p$@lJti<%%0P+X(%41z7x4AudfX@&PI*;-<&qL8;@OA@kz z=jLTrpG-wx=2({^8)3XOhq7d0m$cHB{QhtXd0HpQexMBH_^G8;vJ1JLh;N--?t4=S ze325ae`;RfqgQ-Z(G!Pl2H0E!AmxHsz*J)%ss>m{`TBZum z;;72~3`b)mK4q=asW{B@%sgu()D=00`5D%GBtgMMnY=81nkefS+6Cm*V}GtHOT0q* zBZL%3?FCyZFt&F!L!MIPQITHgvkf{3NLJbW6vxgEP#04g!CIYH%49Z5V>u`qL>1Fk z;mbWW4$zb%*ek2zNQI3rH3ybN7!0M#{)P5Q8nv>oYXmAwTJc_q zrT`)56UgM(@^l<%#Tru{gC>*yM4w3H2IvU)pbP?+)Iis9W65K%%?0OZQDwOaEuk@o z8fY71iI0~(5`vMvOzu=)KXzMU?7*%)%Ln>%IdV!MV~U+!?5b0 zysp`6_qOb4LZDe8f=>>#D5+@b{c*b`qE8SC>O~vx*?MU$b5FS-m@rZ*oS1eZ2wrg) zzWMVTr2_0Nt3?rQM|LUR$n#MmeV5u@X)UK(X=igvU|P*8kcCSG?O z%2oes42OO!KV+8R94QUQBhU!A5cz3p$uQcS&pL~7a7}v@VGM?|foq+g55lPuaD2rl z-a)LG=IvqAe&0AAd)o|%ZgNDCXvEaLQHw=+Mxp^lMh@kYQwMTj!hhZCqnfe_kfu07 zgTCQvrfO9^#Y;sQM6mbUwK;`5fJ{rWzvN|b6>Lb&qNq?Ry=HI4B7Jrc4%R$W+U;Pv z!BRm}D)Fi}aVZnq38JK6UHxMKb{Jd5jAjy*vS(J^`js+Ui>1VL1D@sIZ<* z8Vw7WNbCTyYEp$8E}1L0C_sy6P65ji9aOI{-B@D@cbj&b-S*5yYh{@C;3b2)y0n7h z#M0gWaCYbT7~83t(U)RGY_5rTax55oeKn%!qf5Wl#uD<^cKco$AFIsuawHrBHak#( z9Z18gd==Gvp{N(7Qm8bE@!2^(fOn3Vf=qf)YN(8uL?Y9tBeCq)P8u%0ZmwUd-4MH1l>9H^w7s+!Bdx2p=!cLcU3h_9BFw@3 z*OPDjWHn8JLfEpKeb)VLY+5A2zmsiGvn~`vhY0%s|&Meaw0a;LAny< zaJO_7jQ$*Wo`~pUMzm1}C62OoepEEu=Flw?g__MFeMey%-PhoBOL|p;2&C`Wx>{E? z%8hAEUK?Xcq^K$b2ftnc@5y#)uf|6$uUrW@>ooQo0y4{hj)Qo&NYgb<5^sWdk`Q#Z zrFlW^T#10(elTYq%S=Uz&acsV9o{xlv8L7}8%v0B*Oq6nVXx#TdG=7CXLfKmNt$`}r_iY|-Jn9YBzxY1zo3;sJ7^^2RaEP5zV6%3?~mEJp3>GB z%K=@lU~1I%TTY(jniX+>*1+%C@kY-6oNRq6=uf*Z5x6u$ZqP)b(JYf4S8#!O%!5~!B-pZ zQHOev=~(=Dh+HHbi@iSz<~|Dk3V}uGreaP+Mc}-2g6w`)$X^(fLtm(U6!F3ZRT;77 zgiN3L3qmIVM^K@ou`%Q^C(WkX;hpSOG4}O!Hlq?03*KgdKCS6?ys1*C=o6G)aN*~Z za8Mt2sfn51k;&=8FT!|BtMfN6m3V&uMKvHq!%fO?q zY*te%WFrDtr(AHzbQz-%cXWK3lC-{Da7m?QeCvxk(YbfBD^OlyVPf*uG8Hf|Dwk(4 z5QptrbE`*$lG5thDa1nkhIo2SrBK+kz8rY7r+YjN!u+sTv6H@&+(*tsywl4WzGBwG zs;0ts_;N)jovn8rg_)PsGf~s}v^|`$#m{M;A{{=+!CK_lx#cMFb%WTa&DyV7e906S z-!UT+q3J=h$d$jRp-JM5Eo6*mQ;Y9Ws4e=G>Rpwl?rg)o7rL8nG!9V#dnLHkAX6UO z+eAK-?`v<5}y?M zQg3!4{mbj2Xc615d{c3k7;_&XBiATR@5}%<8FFYK^p|5hb18&x`PHhvXZW-o1RA3) zxx?kwy?u-EeCbK&#|-9sRmEl#i!ypXxxQ$ig@fZUGrROo&{6$j%JXOE_Ag*|YEE`c zqtjH?LG^1O8WDWmcX_Yh>!_PFGIOAgFl!h`K9-npLxj_@bRAlAlr9o1dt}1NNqc-q zd4%9=RdPf&REltX=L+l7r*ma4uy356MG&S|ktK1m5fN?9)ClzM+GnXBiWR{|wB$fwCqrFm}RZyy|Z55W`^f6GO zC5oD6ln7O|)A)!l#}RR+lD0NlT8KGaPFuGwR8EIsd_xv_@D#13Dk2W0Yoa1a9?DeR zIxPibpqMUkMb)ruh@k%Z48u^^R3#nze#{x!Z}~D>|J|oa9}ql?s`07VToOaas2`UX_*~YOB0X2E1Qz*@C!k%*a6b?izFnTQau8F6;3R6) zb85H?3ApacjDK*EK{wAH_Plz9xR3}OM;nqsfZ-GGqT7*8Bs)OB89tH(qN^cKYvyeg z^@7eS_!_X_HTWv!I8ffruwe5z5XFy701J~oVnk`6S@mf5^nMM25w(Vhspo*nX6@mR zKd>3ISw(_a53LR~NAghbu=SyBG`8H30GkMk+V)?ZPQ;QEqZn*`6uG?gh+IK&Bk79H z$YYt$NpF&syDS8Iv@d{LU5*e%1`aR8m$R-g-HprdacUbFjk$C4zd+Xw!|?aDSFY=< zgRO?)YsMS2kXJF>UoV@Y?FWTXnyCEGrE^l|cVx?v(lRA+gi~F=#hv5$#G;4f;jdz< zER?)-!_!9OPktahm{B-r!4|c8W2(<<8!=nCBlfD~b;YsxXnOU4R;y!Ljg}szltYk5 zEe}a`8T?@*^cr)oAndIV5jC78B6In-BM4T@42+ym%z(}1BjMCZ2{;p*6V}mk>7pBC zvEiVXib5NV6X)>BBPyS~%z}QU5Xo{+JuEIL%b$1pGs1cd`RQv=7ISqja7OO;9gs24 zC$FjsDnxi*na!^(K9*MayIw^>Omg$z($w(R1-v}O0+OoZxdM=H5HLzb{G%*3aPFVy z_^iX4y?5y>XcQor=(|H~Pazwqic}6ZuQ0Iki`h>yXdS#N+NL(5O9k!rFpf^gju4ll#ccK6bea2A1RzPNIH^Gp;?D|xabI` za+T00`A7V#?Saw19o3#z*Ae8bYD-e=T{%h@dy5xm>iR;{Qm z#zjU>tV0jo>_csFEMyudq(PBHKOK|-wF@c>X3~Cs#DF^acJOvss-=-0f}Y-CuTVZm zJcm-=v71kaWXYgqKfbAR3h2MGwr4$_;=Fx}M-;i39D>x97WE>TKCBxOSE|PEVId`e zrKQ$O9T3;NZ!ZZUdHf9vU9Wc`D@%sfocF7aEaA zPR5t0mH0?a2vZ%xE#UTs=gcV(6(pVY@$+Mh!Q(bZ-|YPeVh*CzRh_rBz_1c#7j7`q zxk9cD#o7ihv4$sxGZ{JMXKE-N^6_L^MeNX*EIARX1s*R1MwykA2|58p3xGZFeEsvSE0Qvpk~jWcZ&lqzSRv648aCk|i=zbk(wNz!z*Hy zV2ZeO`v4UYr(A7=w6br4t@CL-ZW~_B5enSsDegy>OT^%3}?22CF?QSxdp<(8%h9aN5s_0jX>K6V2X$=OabFwR9CG-12a2u{vex&tdUN$9bYsDrSTjKPo zC)g6|A|hY~QC$TpXb1Jp>1;O~kSJ1XAH_&1w8VM^ zLC-PZ{c|Rm_h~04eb53wZrS)tgIi@SwJ*+K8{R3C*vgX>6q1PmS<1r@i)jDL$Y&mh z9DhOmy*B(6VcH*J8lBZNh+vW3jXis_*!}~N%F}+QW@5)TURwh@EA=D#c!}JixI$Sm z6H9NZS?v~6n{*N=BBsi;=bGhw_BpbzAtLR^L{xr4iDDcbd1)$7EN6F8?E{T*h{+F{ zo!64srL&WSwl}vF6a7y=vqHhm-$tv61@P}{eTg=BH02Xfj-FsiErbw(#izBpP!N=k z8W}y?k!G9Y^65Vy^K{vbj*tyOBfS#G+zK?u{MgZ0*)9!~66AeNjsg?E41#sCU~rs8 zD^jK5J=+zV3Tg$1030Jk$AER9AAHT}7bqDW!HXe0+F<=c5;6(CFC_@y*LihaVXAdo zal|~x;jLc_>4M|Co^VPeB%G^hPdipQWu%a2X=5#@v|QCXmjslFjm8VXUryA4a=neQ z;#o>GJq8pNC$}B>$VB@~=lodwI8f=~0(3@DVuD2Wcl|TzrkY$>Dua)bOvtXE_YF90 zk%!oQmRwxo3&-Cfah?2BySwY$TVe`9S8N_i2uDne^ErCBC=!)4ziR=xHSA&dQmRIx zsR)(0MWUQ|Z&!qA#Fy2wmcfcpwVBX^AOz)9xhtG}9;g^|k6;1YfzdBYL?R?0t`3pd zX>|(};n*h$x;82Jc-0ynY=3AGG{L>Jc(uHwTgfC2$bHrpoQn0OelC@~b$ohV>i>tL zb8%#P|Nr=B7qem7=90Ua*<2##en}g{meDXOs-xVmxksnVE-rJQjoMslSd4B$LY;Gv zgw%1X5S@sMBd5FW-=E)K@qWLa&&TumjIz;5dS-lbGO3I2a&<+a7ZTnz^uyE^#yEY+ zCs;)&(;F5)t%4<`OpRHREqUr$fkdBN+9!tA-IBS6hVXGkQcz+7WZ$pK8pqlvN__R_ z7KIdV+BtaV+^S}rub)I49{W~Byw2$c7PV)I$`0O}y?VH%ZKPVS=O~`Lyv`O3eh7YY z4K-u%FNUUTUI0R=$EWrocuViz;LFatO95x6hRUstQ+rvJNi;hAJ*}h*2wSVP>)_s(wS;sk?^Yj}Ui6b^&ewm^{2eLbdTw4{LZpVSG9z~?-t0OAOQn^o21<+NZH8+xi=ZxBYiMOcolF_Yn$EoxLddc(%OF0xUp0G%#Ru_Jx@nqyj zxU|(kArm!D>5Gbg|CK{Xi!L30QGiXfPT|LXqz`V}9JR*z+Db0~5HVuWG zOnFZ;rZFg8G4D{Al@gv3hx4{DwM*cnac)}+Ms#DH;=_IdQk0_U4qj&t}c2YEsQCfvb0}(6LUkdQ@zU#TeItTsE ztBaPdj5Cdc3xk1jg{%WY-;$B%RUTnZaocsJk#R$>D^NSDG}na*)-62CLfqYf27US6 zkjab7ifF!VRKT}(^$HTE7j{Q4~UnulOVn@1fLuv~GCsOXns7NP%?+OaFQskGX&O+z-Xb1649cFRW)+F?PABD869)lB7Vqi$Ae{K30fP?>D-C=u4MG=e*_S=K6C4v4GkPO5m2<9=Y6*uWvvl73p z40-qROP}0*S5Xdyz>5&-KssK>FoVOk+fbZUeW&GIsbM)iMWnkzb@8Ioo0I}X*|-?` z7fTr>6)aKLxAk_Qa3wTS{nmjq-?V7$u+CCXTnLOBEZRK40aAO%3u8G0(DBLCT6Nf9 zDK37`6=+2u$J^;5tU#r%JJ4%biLXO3{1R|crh0~@Odt zob}OcbF@ll$Nm#_i~Ip8&lC0O)3dKsQF*w?>$MxF)OX8`Jz-~0%X8A_iEb(ir>xFy z3^cf$!o46W*I!Z5sI2|m84Vshm)VoBn^f3(h9wM}>gbsd+|sZ29(HNKmNB0QF%|<~lH^K4^XK*LXC@YCRw%F&J7GvvFRS zbOR?;^ev+^x8Ag+##rFS1GQ7*`ccwAgyBx6Sli9~B0A7DcSg0502&2K-IC>o=tuVD zRQSU7?5@C7=tK9B?vbqkO^oxbRc zpy^{@3Q%bsb_lDxugt&6MvSX?5rcH-km?#z$43ppQ@zz2Xr;K!O)R~&qS492#t1}Z zVp!nqAD#2u|_3sT^{8YMAXd+g5@O@(dkWJpW(*E*g zn+dRp5-L&2aj%w{pwu>$fCXrKzq}FFsNzH?X|7sqDIX%d@1kw)M&bbW48dse!uR z0^A$T3N&4V5>FG}*Hpu|#Z*3j%hEpURjd?I9+hNc;haMrOMnHbM{l`$f|*-ic!^dc!tuwwGSkZQWOYtA`)ENcC)v(@ zh7oIdeRCxs&ej37)jiFxWnZ=%nZ;%i$8$09P$8#Z^Yp6F@iP-ZraCGDO@0$s2Uw5@ z7P`0Hjp%>;K)KD^zcZ5*>L)0-D^=lJVUo6}&Qm@XyPburbH_uikv84-TIPsz805>U zaXhkgR1BKqquaYWj88Vm#jAxKmBsPoXW&UtlGwPH>%}V@HPi0W((m!y!uMV%<%>)4 z=TojyemL;GWMs^#Kq<_$|As%_4z;tr|9x5-&&Sob{M6&Ug4Z>3<1}u@BEj)4Z0N(N z+zmD+`FNePg|YHj`*ezNREi64y-^1-)9G~o}9d54J!F&RWbd#n*rV$v6;>sy;fi} zIeE;;+~xiW)!D}PzRMrWw!%p#(2c#^U!D$UURJ!$pE>Q?qOu{5MB5nf?bBtQf5?(N z5iXf$yNf!VzLYdu$3zU1W%*i~>gPZ`A=EzJNjcI6I>>HsO+<6SI}Se&t{2HV`&QJo z@SE)%r_x|t`h1HGRJo;del1^c2IEaLx}nMCm^A#XvZF(fWi>X1)0a+#JVuHIngO zI>lEB!|E=2 z9M0kja6-&Ju1~H;D8Vgqoc*48FO}>+;lIW z5{%B{zSbL!dT%Vz+ZAU~y;Ew1)~7;<0~us2u@k>P5>hwKBMuzD z7+!kmR{)JY1-8C81qc;VtHL8IZ0KY_Xza{10?8DOgIz!vkyN* zQ8%fkTNVY&r9p*iP(=)IcgK8c1b@X@>V0+}`QE2-_6`dJ)I(F)ZknEbpkxd5HjTXq!VZzC1YvkuP)^dHxo9=(Fig`RKOQnWs0S zY;CN!ZGGT;x3y3T2SwN6S`i#eG%%c(_J$l^E$ZBHXYedX@u=LJ9qpmmv`u=$`bZ!A z<3fRL(CwR_J#B{dGBSi)&Ve%aQ(Np7k+pk5sAzzZ=eO*)lN#D9348? z`fS6IhfY5#mBz$irv=;Tw}qN%&B3?SoNHy#i1TkztS+i#g(+?X#lWx?7kVE_&+6m` zD$=d4^-^aieTuV#Wo#>@f*8jha;cK?flx$>=q9yT7w11va$j z3SQ`g06UY5RU4dXU7(Djm7u~x!*4;rjlnzRnAWOff&-0~S;!FhVNQ`MgfATDR}{p& zCJ^Jx@A|jorTD^FEKMomfFxL_lRE?Z8Hg7W)dJ5kl#gku{Xu!2?X$*C7W}GjX~d46 zy8vVOD_yOjI^UL_?e5>TNjWcqt^x|wZhe=I0j$3T+jygu42`{KLb2A}T8IwHKaJKCF4>g9RJIbUbDn~6l zXgc)~p??(Uwi8f#nF%Qj??9^}pz!vnw-;6amZixq{~dU$QXt(@;Q_%67@CBWFdWfI zoLzc>-%WJe{!g{ESa+GxxUX;5EYarf`_xfsIGY!(VMo7wCQ=FdbDTszmr5}>EUvAg zA-yiUU$nX;YiLguUZ8(-xpEvfEt7uo=k@#c&qhqT^d=GWnAyxYm1Qh!xc^Vhlx*{F zemecOG_>RHj0KXxski`z2k#K1z>I(Y2e744Q$8gvMpt4#=cNF!hto|&V}b{l0_bm= z|K=*v=XSNLtO6;bIpxbkm2mGSc2;MxxA3Ub3h+H5x-!kF>zolTz%MtFs zh@ez8?ZsF)7 zwFKWb4=54f<>Z~Rk$YoVEgZs?FhKRcUZbDy+6xJ})GLMDg!WNiPJYn>SPMX0TCdq5 zHm+>={+W!*`iVMRx3E7~s~EkYlKO*L^Sm17L?LH;MG>9A=I^vZ#t+ULz!yym;?SF& zEJ5_^J^ls;N|VH(0;izqL^jFUgcY;2{5wv6_;X;UipPcRrgra6(Zu)9X5JEBHDM*l z(@K*zIzGl<+3D(`cT}=65t~?}Nr(ahWOdpVn+|)ZKfLD>4Dy8p^fL5-Y{n<2m#D#{1uV5AL z*ZscSutP$c!pPC@@2BC_EQn;ReShD{Ax5q=YKqffcy($u9voB55R zEf?P=sLHE-5o&gJZ27q7@&f%;q$ekaxlE@H&CL4R3083hx-v!|?{x#uGP7pR<8kO4 za==O?T@~k5I)&0R+44rm54;@|AO?=iU7Ek#khVAFMz~JrvL3GBS@@~R9MCk3I`MO)ClIAMP)4qIB4EdMANjLS z02u9~A)$AV=;-L;$(<;~4o!j_u1~;hu*ommKtH5>WNq)L~nJ zk@wfwWON?t*jIC;Y6cL4s$A8$zGy4gEZsNXP!W;wh5T@&FO&Y~7yra^6+Hu1r@mG> z3;Dp#-%*J@xkRp5@Ga--HO;xjYw60Z6tqKa0~ArD)j^Q6AH<7OSZ!7Vb+u9(UpJFp^+(7o=2KW zKeG-@PAm%j!_4gahuoJh%Et1)(9Z`0QCG2cybMm~>hy;{fa^KJt~I;u|KTPl7ucTz z_8T3OrJ!^W>Zq)f)~mZ0XQ$i^q}nUKGaEJacgEk#zSPG}{VV=@>d2Mb8|rHKIz1f}GKYp8yqk?VG z7R0er=Fl^(_dqz1&H0gTU`=F)VANR^fVp;kh=4>j>#a5iL)vw>CQ}KUd@sX02}ct_ zEe{abXl-V6;nLX>-c!C;KB~YpTK^T(JsZf!aY`{TZjXWU*HfPNwWOCxkn%{Q$NL8kWXSI)2+=#1N0Dq%_ z;mLLM3(iC}`};n9+;{n>Y4aF3xNwg22KLnnA^Z!BZ1>X{F<2OIYy&J#E z2EqZ1Fw{#`jTn241qiZ$msJ8!MlY2WMd7}WVMM02T$?;ys;#ieXHrJ(}bx!|Y1+|{+R%MSNdD2k=V zq@fO9hf*u8g^^E8jIG+AKT*nK!nyxe>bO8Moj`h*=c6kAR`ys#rQg21+#4Rqd2RCe zlN}`~nDdGXz567_W2LNUL)J>lZ&` z%hAu6lPU=7mH`q}Rf9Fs9@ECmQdDB0BZC{5=~;zAuB~PzIFes$z;w=k=4j@G@o!K_ za%j0y08di)l4Qiaya-X{n(EAlUYfxBWMbzfe_3yx(p}w(2;l@zz2UBd9$uhANOVBh zX9%XLg>OuPGPS2<{^6!AlQ^nKsj=Uw+P&re$G75p)zFPrTg$0M!tu)O@Ua*~e*dd> zKf%jtNG}_YM#B92JPKVRXrD~5l>66gl|E5wu(Rvj{xu9D_A^5bs|^bWLL%$PoIP{Y zQbO`Y4gW*|LeCVZ|4)^S_w-mVHJe^ol&dZB69U(B`xIpHoc1f$_L_^tIQ-cDT&37m zsCU0kSvi{L6!N%0kMa{N7@yVt-ikmGhK6mfw=i@Hl;*(a^syB;O~Dg#NBV^yolYP> zkS|Z_+2p9G#Ou$|xlK&51TFR%e)D@E_4n>;iFIM{zt<0v)n+x0o<9hP_uj#lo=r-v zDAu(!rfa0Gb218fOKc_lDpruKU?p)$ur(7ASy5;!o!V!rigFd_ z>7mlEH~<(6TZD_lrBfU$jzbMl@hydI5YgHg$>@ZmXG5B}jDUgC&^(nWh+>JCKt$C3 zM0Nn#jFS78_f*C;83&)qpaBOAiZcJMcCCL1j9(t$d8&fLc2(VYpsL;x*$uhrX1+Rf znJytEK{C!^V)s}$O(R!C0;(Yt1E z>@~Vl&*UEVJ%qcp9+YsWTy-l$!FAh-?hkyKl?UtiY>`}I?VBH>PokAIIav64^>nQV zgc)2|I&u;F&_nAdA#78rxH_5GwFuT>yQqA4ePw16bl~HIHIc~2f)Wu0c#ELCkSo`4 zob!v8*!CZHqhsxWgkIjoYhYc6-FVG{!rH4TM;>;+Q6|4@Ql9O;CJ1IMCw=i6SuWk9gHW5y~cUIl`6WC&-hJqitJ$DWThbX4V;UX(sM3Si5 z-Y}!2TNtCU0IDC**_pGT(3SlCQu^YR3KLJ024`)feSyl}SLK3m?P1DJtM+JT8XF{D zR=HyE`0Ue;fdVHsl){XpkB3hT=b}|RJd6|vmlnYyy#y|76t|aA?EcQYKPwYhxQBpP zVd!wnV;Dyh4a$}4A3!X-8&lUuD;k+lG@>9bMFL5YBi>eUgTN|3FPoQqE5!w4jvEDc@2<@_UJDq>9;^vk%Z9S1#%R$c-9if_-DakZHfiDm!Ub;B2a7< z9X8nYC{8egJFeH#uW%1;4!2X_GuHIXwjon04*XFCsZpGOq-4ze83o+wN8;C6of9Sp zaJfEkGwIqS4M=VsI{mLRCM6;Aeo2)2Cx8^cLcw-=&vxFao=P!^e1(C_KaR@%i2+*Y z)e)(j+>vt*)V?weMLS+Oxm9hy!jl#j?dgJl%LZRp&PGrzo*j{O{iqnzCUwa;1u;$}WvpUpJ|G=N)Pdahd zO?tlnKb-_>4oilKvB1aobcu=0ltH~u10a_9Kj)y6v%*{Z=#;5 zY!Z7jDEE7-fZ>(fbf?ic1CFNxUVu7)r=_;VLhsafRFqTMDyetJ)D`uyiQK;qjfWn^ z9W!$tcUtgePk1MP$2QaP5ZGV~KEjXlmGGq0b1(wxarT$dfw4IyON9p7vg%0N7g@Br z8~@=dI97;QvgYML8T-A?^=Aoe%uim1$@Vq)fC&$9wC^-;e}=4ggQO~$o3t%OAmMPvXe z$TrhKqba!%_dmb{S&Shh1q(J+Q;Pga_*WCa*&_FgL^PO!!YZZxOCw@Zvv%hj)HyAf{ zQ}3RVQN9Rk2drx(Mf~MHY6mtIzlu6?x!dM5`DrL8?$Yhwswe*y2@MTQ7OkMRwOu1HLW6l<%uS0Q-^>}69JaR;;}1Om>nnLJZlW~ zxB?EuSx)INUXC+9F`k6Cn$=%yPt7ygl<1|jOfT3}<@Pk*UD7Mb)!e8#l+@64cmQM< zhctQ?WV69O9dS^VR)5PK>4kfW|uiCdGnQ#AY^ z0~WZ#gUha|#=jrhHc8!n&KtKFo#Fkiyj|fszWDkqmf`oeVjlI2-QczZOiFt5sBxa> zBs6j>W`0C+PfCR#r;p`wP>%ZJq!+@U_9cOyDAm|K*0k)2e`4#Lebzs{J zoK*yqT_Y!tK`83fb#8C2lP`s+Rs|-r$+$P*a3K!u)$m^?ns~oCqf-)hrK3H$Lg$s) z_M)t6!V!pNdYH*GE^5`5@Hz^(Km2H`xte=4dr|!~mMk)_KAG|=gdy=PKQ~o^hYxbM z&BCObebqG#&7r!V^)a@hJ=Jd}2-}4Y`A4P9 zI&c{8^#)EP1c4@FjMF$;ed?_4!^c_p;Lth)+w69>1mI6w*U(jki7oET=p>|5jcIWl zs2kFI`iS6^qM2R)jX-^cw%xtZ(0FLYz%fO#wMDPLi@$`czCHeWMR*#gn_j4F+x>k{ z2yHstZ%_0N(Drt@zaB_$OL7eFa%=F%*!4fHWdAsf&M{FKL~^?PKh>%Q)%MX78!vSY9=7iv&(Jkmfw(U2p$Ue&22t6DY9fYzrAx+XNmmM>u zFwsk+#;zbN6~Mj{HV3!|m|`I>c87CwG0;LShKuxm`PF}k?$}O{2Ilftlb*mL==SV7 z3X0}y`gt33a#bAEw;2VmLc=hCJz_|+d~(CvDNe{vtjzuZkN zlh_8Rb8DwG>1cM5v&Jx7l}q^~JO6&&0rvBeF6UxXWzSmxyoUkh&ue34C&woh?WD;P zt6go<3fb6alK`FjA3jg zrrG6A16Pb5lzM!jKLo(Ge_)3tQU8e_e6poHG0)r1b0Zsz#Jbp;2MfxEaekod!$ZkOY~Jp6RQ z+Rf@LC)-;hR+|OCb2#Zi8=!(G@RFJLVpR^ATpXN2R!gN3eStQgmt25^_)cspd6-3h zBqg&^E;|Or?JP0S$G>sH7?uME)2xOmI&hQTH0NL_5Psld;P@hma%)zTDvBtrq@-m$ zYTO1}0j8^{g`9(jhhZalor{;Et(>bwWYOuNkoJrf4OOg9(Na#3oILea>ctgLv68?4t_cwT&DtdHSDV4FO9m@I{X$Du1n{mZ1Tmc`YG#0ip7%yb+MAc}HTAqPJX15cy$ zi9MWgsuwTMvM}z7d$)PD0~fKve2Vv^V6azocWepYn2tZ|6ptnc9f?+LPTd2G9GQ0A z4E3TpFB&!b>+7m@?|mBwE}W72nKboJrzUti#i0o9pQXOF2=TI!)R%&3vS{Mh{ZS#; zG8y;QRDp)aK|X{%oRAql@bVOoNRQcF;KnLl3VB6k2ENVQ|6Kuk4n+rM8Cr#V$I|C{ z?O}y@^g|CoQe>4HJY|4UrW@-|PA$4yzN~VHE(AN0`Mt(UW)ED#xWx8}2ZU4)%}{;3 zPN@JnA3in;H*Pb_=MIx-J+vp{{{gGeRV)}TNZ~%fO6&)kU4RV8zXOr?hoqD&n1*)0 zYhlrXs=86V#kq9;Vo>c`V?WDOC%4+UXRn{{-rP;*p`$50_MV0&M6#%csYgoz1E#8z zbRnSy_LinyVrm|BB}MF1MO}^S4Lo`K+2@*t9gbyS#3TIP+zMFbIoh?`M9fP`UjtJo zH0zJyN~#mWajo=3b>gu7p3ZWKc!7>}43W}iA+Y}GV`l9D&T*97#}~`&1iyY%25aMF z&(v3&N(QF0Uq_SFdv(afyR#7POXYzRWTcwz3T^8Lt6tl0Gh=FxZUqVAR7u2eS-0;W zUb#BS@Lik1p*IF#mWQi}QG9pI5;-rX5O1n~LZ0J#x}};lD_Pm5Ra67V0@`-}4x}$V zyDD@`p4yOP?RvPDuWui;uq$+{0090plVE(usn?&TK4GlcKqz#0z2LwOJ#LH<6J4PC zZ1Oo*>+E0@2omfm4~)nfQVp6S;*1e@#adoO&9lPwvim!9Bg><1?!z4f4y>EZ46l%R zGEYh1wGhz~YGL?*Fhe-IVWKbzO7FNHtVz!~2ammz^NB)8Fo%4ee~~*Py4W0NMe$JF zG~2F!q!jbvrv9jZD%75PFlBd7SjGv@rl&XcZdLjimM-_Pxmtfa-?$KTH3e=^j9v0W zgnB<*)5;$|AXMm0 zyh)I46o4P=eKAY7UXx}kv8Tfq0*e$1bUvDm+1=@qV;Fdp+xEEoKwS&PKT)~Nmdwh&p%_ls5_z-OK*@26UxY{rJLeczy*(o06FSXVQGrhegX3 zU(>?+f$6^uhHbfy8hKVOM-8j$F|kQ$jTCEBAMIc&c((N2{A>NzvOU+rD0Iefl9VXzPYMNhy;oK@|QZc0Kz%b>UDJ*s~qyC_=D~1#xRPirHyT^X`xZS zth=+0oAN%n%imKL|0jw4FaGZaC6s|3cP}w2$-pVSl@Ndfq!^t{J+tD}*Px5mROlItPbbP0eyst(!W9IGm_fqK-jk z`KNHN=QbSDUQm&6clIX5^*B|52`4=nZ^cmhd~R{9_U*tNUN1-n8@?7~CP@W%OGP9K z<|>HoJOBlue+%!*WQU|H?(JDEV)#1Y#i>?}lBZ>ea5RlDUZg0K;KtvWOf#VF`= zJryoW7e!SrG(o5KY|>>^k%F(Rj+6kYBti8aGO*3t_X7`qPEUD8k6f;QU?O#_HNafv zbErNqi|UwOgIIlU$QIm~FS6U#ONB9QbZ1$ZmtC<*=E|9_4{RT<^~Yjk9Y^iq?rN*1 zSb#dF#hZq7GjYI?^q)rIUT}ONumLwvjVPvv}iKiqpq8;~* z>f8nT<55pvFIN10$F~S<@?|>*zxhTHc2A3|0qdj41m5J$po zHyIq+m*k^U4&l|?b73RK0l4x=2TZFuD@z-#?31E#T+Fl|`mpsB^-YZlbvDnB+{ z{HRwjb-6%iuIl5R49$wV2OdgV)t^|<)27Z>F{OBkqN3S3r&8*Pz^c7usF3c!Ihv^p z7g<^ztN8=!I7V?lbW3i^k10qRgivWdlxt@Zeau70chv{U3b7Tl(G=J_@2}*XJZ0wZ z-xtH;CgG)1Mi(E)w&Lih%q%y&tMK${9WG)FqhT;CGp#6=Bb?O6*mXDN&G9bY^NZ+; zn3MYvE4i-8BcF_95Q7#l&iLdalb?w6{|Ddl3?$PWA<>DPUgZu=T#Ld1jI~ArGUgd< z?WiuFcxsCH!x0mqi*1-N>MQYhNF8IW*YJ&Gz8u|0vc*7XMP2|QtMNYt8vBX&?|H{i zji+{?zJ`hMEb{~ozBkoY>G<1RHMw2SY!P$6 zz{@ZBM%+o1&V*s6h-PVE#@o0W9q!SZOu+W(4)9Ibwdg?Za~A=UrqTxLTJf&sg`}+K(jTRFiaNE z6MdXnE|#qd09j$+7J&xU`k2eXyADDVm5Q3T2I>>F_6u|vr7x@KUwRX-$>?nVI-#2Ylx%~Rd4IB>7)eVW35$pV14^j?>(C?ewWP5%y2m( z?TxIxRn__;=D^tS#fhnZ6^~Bn?Y3yT_uI?X(`WBpG4?Dj0sdj#51n|CQAu5!5xrJZ z$$Eg?NIUm1A+DZ&Jm6&;&u@q3rrKBHRQk4{fn8@Kq<%f4)sOAiPj?C28%xB{wYeSm zE#_U|sJsvS+8OpD4}FsQvog>yudiFwD}~ZA-b}5f1(&uxJ1{zLZmwvMVG_WQI_TU; zdp6dBUFWf_s?0s zzxi2gxg;m9&gZREh|mmQB<9ordpF4<8#jyeGPod(9aA&7_A{7G-i`|iFYioMTCT_@ z_iOQNe@C5dJAiINsYIMjUR(nK*i`LEV`*bfBAF z1`6b}5-`+2Qb;H@J!qF|+#968v}9Q(BNMzm@C+pb4iM8>d81zqEYr$4Q| z*zB9@SCyRjB@9TEia@+GnoMkO^Lp8LNLi3zzMJwF3&4vZCYs~nT|Np>hoxI=u?r)A z4)$14moPe>6S;i4h%#acToSG>Sxfu-ZcK*rcuHi{ah`kY{m6y#U;>A&5(QecBvC9s z85u$EaEzxAw|%?xh#hnmW7q&O7X|(2EcC$M0C1BN?G_WWXtU1Fy1fB#rJbNm;;zR+ z{c5)?CIw%zVZ>w$Xo>rOj8D9#{0zz$9zE(D_&%Uz`pN{c~~)yX3mBU0L{SZkjRXM615x zR}Bpx_ocynw1QEq(DFwR=l^=QXhntKJD;8ht*DM8K&fGD8jRMO7a)q0X+d54EB+bPfw*0TKa|Nd_9JCzmqZcNA# zi<9~;u;v&7vmK8o6mMqOp>~~`2wj_eDwMG!$2_DKgLID8C^xbc`iY1lfV zdM|~Cgs0OJFYI9vhJ=wb4S^}566$DewpSNkBeYOUWbm5s$pAj<1l+Bj2|RIwT>Na0 zn;)QLz;BuK(|k5^qij09Oe6bO%jZBkkv`%K=Vu^t2wv3s3LAXscf!j;_6u6i2l7h| zWHX(la-2TZ5b?)cXj`)PokxzEKW-M{R+zrSi71O){eVcI!sMxnnN@O4hqG3I5-8SI z%?!q#eZU|*(V5rVV>+130cURgpy5Yiv1|4{+M%#8uYiV%cQk(4Fxb=g=J_1Pa5nx< z40sZnXpsg^PDl@Q7%a3(5^DOJvV%lIZ1X&c z!>@fD;4a7G=jSFtnq=L}?_Z{GH(_#I_aLzLGOZP7o26Mgz6*p#kOn_*1_$H4t37j3 zl&gVp&`mf@x=2Z~#l_>vxj;r?@rI!0cG}jDcUu0e{C=q6t2<3AY{LVttj zzi8TN#)Fj{&((=lSE@U0gq&61o?QRIn5o0Pq{%oiAXLoN79J;mbd?x3@F9lcjq?pS z8rqw=SxQiN-&q*peI2>EMM_?ITUp_X*)=Ih!?upTUN-ycX?gVpT=I9Xlt$u79q#VETWqpo}&Dp<;$>JT6{SRp6 zdegYC^|qEi+&;sR$4u_EBXxfra`JwyI%PSW6_Z;XuJ7Rr^_Sp$8emVfu$_<#)IyYU z3YBh#LA)JS%Y8Vw6_yMLnSv1qz$dN^`o?goY#o1Az#@P4P{=}?a1WLJhG|<6N!Z5u ziVr)UC;_)vX*RS$jDK2{eTVxYk?wm_EV;rKG65ZKh*t`^x4-Rj#Wea%gF-Wk!oB?4 zUR>p$IvK4I9I(yJRvM2u>xxO2YeJJqOxY1`v)9`f!PYiBu zY0J^ONWnVZjPF&Jj{69Lqd9tS1C1Gdq7idoi2^y}&te|2JC=FrY1>=Tk?44S8yo!F zeu<1DJQXZ__D+b4!hxC|T7i|owK|KqMIBGRq;r`KtJrk7QLvp3S=aDBh2DYZVJGz$ z-}&i)Vh4QFD9=sP3Cl+`EG@Z+`ZV!)`prmm(^0k5>sEzN*QE-2wCAk~6U!Q#h9-{nB6(00DpYX8S=lDab<9^LUjF zc>tH*U5R?4v^BT8a97$Sq(dj>E1g!a^E+Xl{RF{(Dt$G74ioqdu6x9n45EB!7-ET; z=;D(y6zB>-!=16Km-^-&zN^CrhVjQ|Nklo8W(2krgb$o^2t(szs*+J~eBf9wMe4}1 zRYg(t7^b#ZrRt9%Zsc=EC^)yUUo=EY4s<#+^oHGt+T4o5q;8>>5n}>fR0$1Aa}0ci zz$x}d4B~dAiE31@tCpDO>d`Gr-?lu{98wa$3;A8Ib!}AuTz@do0GiVE)<~$fJ{2hH zuFUpdR#)As+12&Gs`fSYl+SMIu6km6JWC@6)1?e((_1TxM}{4Hm|o$ zo|hG=e$CTrkr?>A^y{5e@J0od!F{e_GY9P#fRxB@F}t{0z;-)z9j;!~;GWQ-`ondT zKsWGs==@jK<8EHS?pAh&Fv9hlS)wuqK<|2V@5{*wrgZgKo>W^`ni38XQ=r`fi}r|s zaP+BF(km?(A-xKnWGToH!Z|mj)_jGI1%?wdOVq8zw%JXhFH5D9PnOEm1^9>Ft_{>$ zr%~llM)Ww+(Z+2vWF%?TB_^$dpQ7ut5Eh<4RVMK|04+l8_A(&FZSfP9;S^QHDha-~ z4~0_PXZQP<%rhcnCx}q(=;&TpIH{ZxjMkx+R6?Ni!qH23l=Tspp{Bt;Q)c7=qa^hgA}`h;ZO>p-7$a=j?v+apb7Ey z^k3CJ{!53@6qIj?N*WsrGkXc8Ry!gn=&Ii^0y?<=PGy%*4GCzEjvafE(>X^c`a zO*8Wdbi|rIn(U79l&LQib8Tqu0XDklQH(+ALaQo{?x^JZPzntWjUf1cH*K{e6KDfZ z=s3^%qi*c#U_2G=lQeEC0$L*D@hXwVEz@rW3LggY8DDbGWaz}R6K4Gzp1Vo?oddsN zp4+Rc;m_uukI^!P7VA;NN!Yk}I$YA7#sFp6krqqrVIKgUY6!o`B zEF@6q`d;c3&jG6%?Y9hX!H#LDW;Fl}jYk$uvR2v3$aBAnz7jFFbg#x3z@Kz(`PwfJ^nBzDI|AjPG%lV?ad%tLLZGPP21B%GwTIlD!lHydNC!A z^ZN;l6dkJgyqN|Puo;Xjs;FF|z1R?aAw&!2I#9WT+sgL3BoCOGhs4{A% zcQ{Eo+u)ZLnZNsnUH)zsn*g`cZ$Dp9(M*oh&7=PNj(SAZr9}TNIpnd6>ixRAeM60& z>-_GNe(%QaD$s^5Pe2+y*7yk{N=MF{Z`d3_tR{*REiJ&p={CGs zh(3QHK$UMS$e-Xwa7LxpFRWe7cId>1$5c@r>BGRjzhIayXCn;vUr zBeu#?vI5_`2gzuEHvmY#V|*Swr9g*!)-znZ9pu>Euaia!rrvzO^3q;VSZSvhK5ZAk z3!QdnxOw`~b)m{Z#VXyvHpIvy8REwFrZJwv=pFBNxa6)}_n^I+b&NvTA@yTbF3Q+t z{rZDE{B0m@8uR{@>%hbe^l2eceU*%yofKPYf=Kc)Z+T)lS$-h>vi{astl6E@%gr{o z6B{nkQqDfls$3otWSpnbMAlE7h8LjQkh;S&*mM1)!}f&GsRF;Tv`P@^pQBt#ESB}V zG&w{6^?p}*hrC21v!MZ}BBOS)-G{aK!q@zJ@c-lJ+~b+<|Np;}*)Vo+J~cCQC~`j2 z#;`HWu|nlAhY3**ov&?9b8I#=$A)1Jb(N6RRY*dVW2I6kLelx%b$x#O{{Gqi*zLBz zc6;yjdOjbI`~9d0+n+U$@P^MIHc&rXe5hEkA;TWMK~RdRFn1qF z=o^O)8EOT_A0@6pm5cDszoa;U(@B;bAL=|nnUpbAemEgnK_N#C^ymf8YLk_4s@>!$ zI<>>{xU^@80-fCiw@w(|TBi3@ZhN&~kp?}=xv~%`lA+k7B)#XwUK|V;3aG5ny&syv zEx62KEJ2v~{p>}b{>pT2V1~BvE9vM+F~72l$w6ui>^TV^hMBPkh(-Rd(ldjfe!99H z2z9l^)zk5R9%z%GF5TW6G^F^8N8waiae`4(g;BT%78 zc@w4@W3?vn69h1;eoD-oS*vmy^c~3n0k=h62QA;HcTlV_-%T_<`AXaeZY`Str12Bt zmpgHBZjrp`NRs%PX1vMLeGj5_tcp<5rJs>v=f;?9NgV(qWANH1Yb7U=3ejSqw6G z+ET0#*R9@^37~(AvBVl08{aZE=Xw`pN#w;;0G_jUc3lpe@?=ozgRADikOSX?DY6vo zz;}0cdWx)pg*k~WjluMKUVP6`CUje?kH=n`Jc%db;fDXAnwzSsRznn-OlVSS!`-Wd zp%ivDOE6%cP#U7~T;8EEKPAy{JIEy$-Ad&zT0vCk)XcV2tqMm{5%y$Aj}H~2 z&&rYRUbMkIjoEWhaE{3d1Rn9*@N)!N$85(Os@z>s0eg8X*ELp4v#h2I~)IjBq=-^-|5MJCEhlm>j&(T{iiLN1T+k9 zw2URi0A7EfQws`v+9^q z&>PWUfvWmK_u;(MjSN*Cx-Q<@|L~b{)|(3A+_5e!CoD2xK~)>_*9I=aD=#KGAC|$V zfeNQiWW8U2YVR6c#hx})6|k|xpJ7HI9k6owoo4JC>p_%$t~t^2>Y>;px z4WybAxBK}1|1_&?$?ahEvT^?DxX#o|W|1gr!nE4DG4UykP_SyKX3vR^a&arFgS^Hj z2xMN&NqC4Kof`FluFSr#VW6qli)C-+4NpYMjS*jkHv0bB%C`#FhMen)8Hx`;a;8YL z?L!J%);1$R4I@XtLuM~C!bk{5#{U2*^hg?s>{C5sLamoxgEXbEFh`c&O_s3N)A~)n z!f;>T1ZIH_nCKJ2`||`k%?J4uY3x}_exW(WfGU{UL}7NhD$jU?z9wKiWtFwdA1R>d z;3?12kqjiDZVHQrmkk6vNpE{2V|inQBoXMzb*+{e9H9PlzcCXp#S19l8KWo+x?`U{ z1iA*QZ^&oU|1xjH0wD2eLl;z8arWqoEp>Z&ApXbGA7Q)wbXfQ`Ei#f zFhjj$ik_;dtD$?N(Nn-Es~@#nk-a-%z$QN-W^)1COhtVpKve;+VC|k>$I_tAY#sE7 z0?*+e#smw_op{wxMrH(DYzrFXWx!VfIv@qoJ84l&xS2*qo+8Lu$2>*ip)kvAh8Fjk0jsD`gu6yd2@f4o9C%P`hRr;JLm#1J1 z7eF^JQu;7U%&hi?*-iW7rDX#l!2eo}=g&gVn`%uTK6Yk2Uh-(_HW}3<`E!FJbwjz< zK>B`5T)gZDE)AN>ek6V!mv=cJbbae^?3`hjyb!wWGCTLlhzYZfp^;dbFd-9%STafg z-U%vL0WlKr$HgBw#l6%jeHr@I6B_bXdD6>KMzi0WzJLG#Mcpnpk_Q|uq?>fYFV~nA zY$2g{j|KEItgW@#f}!09_Lsxede?XDP(CQ=ZcEr*ZC< zJsBq>LDZ~oUJ}$zT)Unq+o~%P)oig^JR?7vTAU5TZwmB$)~)@%nv_y`kt#J5a4z@#;cH68e|5F+nu6peG{qU_*d}DAVP$bw~WC% zG!f8ZG!kG9E|L0}piK_Xau6+MS2;b0xu3%(FPe54cAEkSu>;l@7;-)Z*sNS4dYX`F zSt@KrL=Hu3Vvh_gLXT#A)N)Hs8nemTM;)GeE(MA1#~(6k*>8aopP82;%6E_xP4TjP z2~>Eli_N^efj%W-gVs!uk2ujT=+kF)Em>(AeMJ=jG^}{L+f|R~WsHQ|=yDCC88F+n zoW38mUN0HU5_d}Q07)HRA(OzwpjBgNJYaJZd#r8ys_romT!W}Ecnd@hz#rL?fZ_u< zMmQR2I5s#gyn0^tLVxNT$4J15V2U~+CV6&lCzZVzpt{D=+8gDQpSNnYHe+7H{F`iBG7BTeM0ENMw4M0-x`K)?d^YHCb*Eio0R@X4I3onBI~ z#l!a{{_*y;80sXzB!9*w2M!pFP#}R1y&%dilWC6C%Ihg%D=6g*M4`>6^TkmEP5X5- z&w3XgUb;^`(s&U!X0_9N->S%_ioSI+zrvlU3+Br8eM$u*w zaN6vOc{afgZVkOrroQUp7_9)mVgxP7%%quLud=zU{8ho-1FyhzhyAKzGu( z$!3zf(NYsP0E+?HdF*!g)?SH#0q&U;>#Y9|5PKnzhRIQJ8KsyP2%gUO{D4mQ5l~`M z+G4N|I5*O(KRF>^1B!;GF&z^X>^_r1K-vm3fth38EWm;7mgeCtQSxyC;d_W_*7^VL z+fo~s$Rd{JX)pQ{84r6_H1T)S1VkRh{xipvz3?Mswl`5dD`mutj2wV--*jNq^uJ$ z2k+mwx3BzZB-cFK%i-eRV{s?NvmW1iWF{a*Y2>f4hGt2jX`1CL-Cl9Ma7Vx&zUhvF zyDthJ&H#vmCk7C@^D|q+MOTIhEV99>M>ko3bgb=?DVDu|QChnLCyKW3HxvL`@mWF~I z5yG>_y(C-Y`b}a+qOzR48Q|gS0xn`7V_>`HG7+v2>S-mgysJ(G+>$TaPPN=6=Cq0Hn%d zTckVp_(WnfKs*kLG})6VUd4aI*$21Bev()d;Tk*ry#R58UR!)QNn3 zTqgCBOvxV$uX)AKp5q{BmE9AZcGx1$UfPq9NXlCEt+a8Mb`Ql}Su_Sbu^IxRiGd1U zMo^})t%lNObp8@4B zDa6geRpGh?_N)Qej9o}|;|NChHSna@kuh_h%WJpaGsjZG!WRQHwNYlu-Ac8{GeJ#d zTiIy$o0Bs8p4fDExce#f*D2zQ*hA70LC~#1Q{sv6?U~pWl;M~0 zix94B{&kWiuoI4En?L`so#}HqK7}mfcLDX~si=8rR zYemU~e+;t(stCjgV5gp?LuR z2>BK;dd_!N7)yKjnl(`}nrmus>2?OuXKXgRzsytt|C;4#Mp(2g^>ivQ$}MFwH%$@>j#;KUOWtc4{y|m-b7=6!QT3ft&k=@E+86 z{|fZ|u)kJmJe?J(!=b2v#oIjxL)1!>DV~O9OuiNZmsvMYJR3Qm{f%xgT#&8GO3IHc zPGKdL8S*4)W_*$qGnTJ|A9&s(PbmwZnS4D__}W|UCs_$B&a`Zyn16fNNc!0GE!0tP z^P3(DU>kdB=D2l7_+9nX?W$~^>v;OTvf)hPSF01u?{WhI`u1|XnQmP6bNr&g9UqZ2 z$t7hR6XAJkjPYxG#EV}~8tp;;1p@{oZ+J#x>uaoHqu*Q~p_&klY_lTHqU7x|v|l%% z_k3Y-j@DoJW9-w5S~PksSm!i1UR|$&2kXv zkJ!4WWq2I$_pUPX$3?KFw&`%am)sw`$3$C$eO7zS@KhLXNq4;+KV2NT7FfXFbSfo~NfoVj+VZD|AqT z1qi<2^RQTvT>93tZ%}uN6S<*=Dr$}dBZD_52baxBBTm?3C^+7x}1PclcUp=^4hEZ-vu@Y#ChuC10W#r2(ZJgKNK=p^kUa38M4)DVHK>m>?d zniO!lO^ZVLv!CArw`COR0RR-#yH~SJaF~#HjYbMHAFUs4pTAPN{@Jqv_g3vEev^@1 zJOrr0VUH|8vZH7e+4nh5WBI#^AHtBDbt|~g*dYMOQZJ;?X`6>tSQ6!9I*xA_Go>}< zCUNP%IpYO0zW%S+fbPLl5jIi9c|+#L;hH`{u1{A^#q1FvCf^YZL8n zPPjaCY5{$|rS|H}9arq=z+bu@(`Cw}FP^LAgz|a}C!k@oM}f(F?z`)b(tq<`#t^B; zI`}Nply)tKb_>Apjx%`N&vIbBh^r9_ghb=?Jp4G?q#j?^BtDeUYzG0SVi5 zeN1m#U9!aiXx>IMe&~d(b6|Ph!R+3k`|v9k)ZVaN!ACi;k1!pnZ-xPuwXCcqUJ)$p z<#KEWzPXE~>e+eFab@jDl+_TC<^QFc2=z69sMvoGl`Qpe$+$f zyRkaRNGf3ECpj*Iu=WFJxkxmPrEu0;fsZef_MQL^Ei}ZyxEz7#tic^GV}$xq7A>iV z#r5Q^as)2=l#H7xA~kD)fL@s8q*w|{?)w)ib25swD*_roMp`IrXF>Mi_@4t1ogd|B zgtM0s}?cwOM;Uo}CR2QRA)ES!R6=gpV^feew~Fn z6<<-6K)Av}#_A7|QO|cOY75qDYRogOFXj+IR2LpmyJbxI*ItpeUou%xw8dsY+tPpG zDJ(GCp7Qgk^||!?+{;#0IjS?67~{)>6Mj@WM1YIwzf>p08->_v&yb76^#1Q-wI*o)M2~&%>u=biMp|p zR7~HO{cIJolyz@Ng|He0#TOLrHHL9r163Nrg0HeJj5$`NtCiBx1 zuN^$QSwz)%pd2s*7#VIiArVeLtFR!z>Lz0?mzI1w>s3z{q=NyUy^CgER?^g)4p+_i z%7x#`kPe_7%Fk}kI4jD23OVmw{?$}x>X@g}b0Zh4%R3l|rm%UDHIaI825Un4oImkC zFgs_5)j!^TL(-!8xtt%@{y1>t`@^r5E+5lVOZ#$0e|Gb7hT}nk6Xaq#-%@tr_#T;$ z=YDvV)z{p-Q~LIaq2yKds@FlgaAxFKMSY8IYo2}Je%E-Mrg@3clUMJ(hihi{wEJBq zSvwIPtM=wdv%ZOUr*i;6RLRgkzAsL>O}J9@(?hfUuG{Zu57e8Qp;F%CxqoIL(7Ik; zu*a+7xh6%s13aJ^nrMzTyd5V1jMR=8)w#0ofU<6&W?F%!%-ngPa??D|z`ZQ^af#zX5k+c?% z3HAn^ryP54o4sKXve`C8T%--_5L*G=d%GH`_oKtR;%LO%3?PEH`;+I#R1yq-rw$c) za@=pu*-E#D;EYu_H`QOR!(EeO(H^upjRii#qFuaGKHNl~eJri?7o) ziT$a5&d}ld<0Q}>ihvk`kAw|sUo@Xq(_ir6GWGFQ-5PzPR^WMBiF3*L^kqihguGm; zk-82K6lO-u{OM*IN&eB)d{&Y4@z( zn1Wk36x$3G=^?(EH>{xQZZw1TmHL662`ip{+${8c*oG%jZemI`~iBR5A~zccUa)I z;HZMp`EK&)Qj0EOkhyyM16$QOOQ)P$hEr{rUB!MI^dn*Iz1ndKAi9DO2nF8#?s4I_ zkyPLV`%qHwHP|uUAlN+12p5q?EtN8uirxrpDi{9G(sT0Gzgjdkcjc9i z9Zu1d=lPv?{!!~6MWV-q;dw~^fFZ<5<0-q0Z*)5sDWaS_g&lZ+*0J~^b!lrP?=U4g zVLJ#>)9}2!D($wIB?ZCIj8yt<_aGEbZDw-~xc{O5i@Sm7cHS3zIx{u2 zb38YjeBEe*Ng2a7JkR84mmy^iA@+069O69x0RRBQWbemi4anRO*uq6izX+*(R zqrrgeBxX~M$pmivd@^HpI9<$h=6+(JKQaV+G~XI(#I@S8K9|XFN5HnoUA}|>g|wZ0Jx8$ zjsgg_B>o?@k_MK^h+41qGhX($s?9~$@0flgH65CZ`fzLSo_9OAX&cwXQgxNzTjIyQ z+&3979RCSiIt-ppw0Q8x$rZEGbI)ILdLPs2+kv7x2lEI2gmyWeabH=umwu(*`PK{f zn-9Jk{r{Jc>T-y-=m0Q5=Iwvun>RW>ylGj9Zza|}z4<6T@4#07Ev=4E{R4&2y7dyD zinmOy^4fixL{-s7O`0p0=X|k#)hh()V@Z8cVMS?*!@>iH*19#0^t70Ez46lXh;VoU zyj;&;tHOfU8)aAKb{=gP>4ZymPCWUnjao1<`%r)yO3H`3>i;W9IQKiHFeU(n(JrT^ z0q%9;jk8c&VHVo`5WeD|C?rCME~KbW`WH^AW#0Hr?aVr`lwPPpEBj zz&Wrhmef!iC}$74t^n=zorr77^>|=%oraPeYMiLD@UDecaio*3xI1hfs3ed8Ew{dZ z1=BmGq&HUA0Qf*?3ART`<7XcdZ+#N=Vt+U4wp%+8!PItIK|+B&b)Zz(C<$q$LbEKJ zKenCME)CgtZ|&*{EX?q6juK|suzusnO;60>FmknlR^2~#WCBpli-GWp*=+00gqal* z9s~qMwdVLzjrd_Un0lo1kpBM-&&;V?GN#sLDB1q8OIKTppGf~|E?%)1Z|F~qKH*+V zga|=1daJ{uUx@&YR|CvS$L%0GIdb!A7e1d>rcMK*eY2w=!n{epPi%cEKeO3Gz;>4= z%SZ+y-4OUgJaLCKLXIZl4~`c^Ic9f$EAQ?lQ=ccp48C^vC*@oPop#DJdA_2MHv&-+ zLW-QW+tm}$Fb+#cs)~3YoGs>T7;=dzZS(jGe{w?P^KP{52m0J6@;0pGs%6l-OI1^@ zx~X^^mYo28B}LksU%mY=7QIVFCAL)OUvzztj(cCQ_G3gLj)4OP@3Y0@_bnHFA<5KY z9k#~ssY!;;Er|AAdDfpQZvo(yEEDBTYIj|gVoxvkcfsOd+&eCqLa}5Y&_nf<}{EH{p7ZLffA{lG%|J($c zx=WrMebO?HDpu97+YviOV<{eA)+@P^V6h7_!KcV&dzLXahGvL|Q{!_AW^D)zZ<>)6f_-t*xdv~Rg3HNY|RWUECTeq_|HtGqIK`UQ8 zaBnm38gtId>{WUq_PFn7d4!)(s7KGT-4krn!F@z2K2lyFBc|R`R)gNadA{|GBee;f z8e6C+2i?tH{;45ITFw)921^Bv!2BGVp&cBTzlopkK)d@!shGV;%VCv~mB?tbQUi)J zDi@690NnJU>vKD<_z%P$NCg?NHO3VeRfCI17@dQR?)i(&##yYoxG7vNmK;*o;Q)3@_a$PSa0 z0&m`3`1o3}>0~5d6aVXyjpWt%pBxM__xyz7W=Kz?_pFKOd5l{Mz=z^1uIxRU)MmyJ zi3Y6<7j20kz;3>FpzIx&xs1~WzfKS7$~q})Q61dsYo5(T9t**KxuxGt1qHy%^f7Fi_^8-*Ey}fFYNHCD)D#xY*u+CDhNTBt z#SL5e?ivT0hEQ~B$mA(3A(ibQ$F9ATQf?J(;?{H&ezj|KmR@#NBbfGJki?mYVRi}Y zh%BHHBJh;bq?NJ^hSOXYz23^Rc;Ch8ynvFd2KSp>`?7xn3rA^ece6!A{eA#>T!bBl zJ3R;EJ2EkTkhh@E0a`BFW{W;ioYH!{!+7qeiqk~y_FIOWL9viF8sh-B$CtbS6UQkA0r)@^PS&km4$#y6;39jc~ zKBl3ZZAWFJTA?Tw<4r~b)OWm2W?)dQ9~Yr_kM^s{hYC@6{h@<|N3S~#(PM0!+Oc(r zUXJ3Y=0}FUD0*kFR(Kc}@7J)WQU0@Sv4R^1QL50+qV6iAm!(AtyLQUukYol>$Ik_m zm;$>ekk#Lu_dHI(rM4uB2-N@J^$h<$kaB3}DtJ3%b1dHK^+nv=ZK z_Iz`Xc+=vkJk0QF+%PrvGU^|2F5Zz5(>7_6<=Yx7+u~I&x~@1WR$pjzo9MYC<>fs6 zj2omUq;n#h?hY$Pi2tlm4u=i?Z2o<#Y4-^ez1wZG8fjTkxjP*0{pod^OW(KH9MPQu zQat*gV^a9Liyrbb9~1`NHUK+%!4GRu{VD26zgkzG z064Mt5Z|eTYZG4R3*1II2yT~#>={1iT@d)DDWqG7rV341kgC2vbD?fv$d4wg{>v}` ziBpRp0E-Jlva>b|>wqJvO6wA^gsM~M(s~VE$yLPYltcMMTj=6U)BgY_tj{1gJ#8WP|vcQODi1BAak@FkIa zz{`0TBG}0wdxOJze?Mky|o zQxw(Jya#dE_3Zw_#!snA-`yG0zr*yz+~fSJgt{?ch|Ca~SP!}A!E-5m5cRZom@t*j z@=u4cZ=EX7|8W9boKjQj*HjA-5Axqis{)qHhbo-PGTD(mTS741Vn3?8>nC79Du!$Uw)UGT4i$IM0C$d)H6^E>mfUc`kkM>7>~L* zTHw6XG7K+wy;@G!+13D*fkCU-OX;~?0!g3$O30kdMJebmWM?h!1e~fR{2B&ZHWQz2 z9rhEz&gm@1-;lf!I2J#>9QJYfAzblX`f0)V)rj}^U9afzOtK;-H1l|Rt@!QUO`C_C z8)?GeN1PA(axF&ZkUEt|R70o#(=U$PwYX*!W%sA6^^$_kyU{RnA350k%$E?0htr#? zUtz8~+&%4YBbu|@W^Wd&{O!~7{Yy^YfLL|AMX)@&cyiG$|BDpdAo2cmk932-H~x;j zl~@Z}s(hqK+@}El8s_R6?n!hCTzm8?@At*0f8CL$hnfysC!$qfVYQygD9j?4_faZVY4+(hd{v9d?INtOaqI0Q#R6^|GXSS<_DNTX*7B4Ek^eC>Oa zJRVIJI2cGlwHGg?3Qymr$-hAEvsl&GzPbt87nX{xAM57DyK+-MsNZ-|w!fHK6ZkD@ z8eDN1&>cZ@dq}~e{czJ53>3Tcjm)xjZDWs_EB=IUXdTIHM|}hkCH|)Ug{8r$W&V+_ zJ}8bW4$OS@G>A>mAsd^Sa;<)f9F~`Wj3i`05)d-xR2?iccD2?RJhTqY8BemF{Z69C zN1_uz?w3;AhPhR_G7Ims%ISxpjk~r>h(*bY!DY%G?~EUmsfP0(xGLNIa-h4r z?^tl$cS;%dy-~_{o9u+NWN7W0zQ|v_kSqWELubh8&jTKJ6H*4wby?f}D*y96 z)n)qgL-3+PXx@j{2}iyf|J+{Ef8)gBUPLU9PQBa=l77Pu=MTuxy#E0Lt!?#(Tcsaf znEY!7sQ@0Lp4;xUg=^9}zj`QL3A5%{1_WxJ8qu@0^_?irq&X_$yrt=lE)H1X)gsO$ zwZ|;``J4VQYEqxD9u=shGK`-xkHgHafI7-q&x3eDHLA`BW{Rn@v2J0`t;WbVj?@B@ zpCJ+Bo>6(tWyK)z(U173F0P|^v}B6%{6W(x0v71HY};K%Af!C1#`*!&bBGh*_{7ka zNG`x=ccB@}&Oh8YpX#(W4`AYDJ*K*!Khdt5&<|2joe+J+PQ+AzW?77D^Y)q)tZze$ z$7iEW)yjyP4x;d}73g=)bFJiKZ*$TchIH!3mxLlEEzx~+!mZ83^jTcv>aFw!mJfL4LV)~W}PyUvg0U_cMG_0 zeOz;xh-Yan2oK!VOTEWH(gfIne}l~QI60Fo&f5g|D%2-o6$LW53VkKlMXX-dRLFAO z={8^`sc{EwzWb(5_H&iJofvI%- zk^g#AWBR5*?3Hnn`-hkvCnq2WxHQ=6xT0pi@EdEH7`~$I&V6}5JX5HPddk+{CR*_9 zn?@?ojpwlugHWREme{t($)tK$iB)i8eI*yWiqPlyGpe0~q-(TEb;B8?EswTwuD?ZK zX-qkl&8q#6nhgz)1syxE`Yinpd6`~R@LMc1DP6QOC`diAae5^j{J3lCNkEmP8fuWPuytN-EUIny_+>bwcJd{Kj&aPkAW7&+PBx1~`F+m!%;DG{o zhL*->G@Ik^2TnjpE#mxzSMr|siCFJ2l2w<&!&*SX)8rc6aW2=M#I(XbZL-Wz&>+eT z3%>6~>W6%Dk5q^9;0>W$uR#5!?KJgNjtjEJ11J4iw%%zFbebWXLzNPWswqR?Ivmv z%!m~@Js2d*xWgrp9v(?sw3ugprughzM9LxDTb^!w34UCKR&(WEq4qpXiY(nM<;>c9 z=1U(%=)k$_-RCM#>95wiU8KyN!XDb)?@C{F@j%me82>Z<>DeOA->6)rK{7KheFK*h zgY?TOt0??HU%@lu=P&_OaM(QuZ4zjPf;gLe0y8`c|u6WQ)ogrCO z-9WrG+aNpw2XCk{ft%}q^2V$^1ds}qoAUPCoT1s5Re>`wd~amR#U|h&M8|3+&5G9v zeQ~&)Yi~2^+d3Qu5cIPe@}{-hQV9^0nt3N}1%JvUyQ+>C4*bvird>QIXIguU24ku8Y+hasznpRrZD6-ysbnmgyg>AgnVLNQP6$jxEkYDra{N z=CAffyx`DjQ5eARE~QOQ=eN+=Hvhp}rBj>)hgb-5;vkv~r6sC}Lw$1KJ0U z4ah*7`-y^hxYmQL{oN0!Jl^JA05(v5=K7ul?uKarn>`pD2nk_EIp(wY7w$kkWEkxdmyUlaV6ACoSmv{-t zR2HPHhG>2Mn7&b?-<_PNyDj&S|5*C3u~Y}JC)+hp-?y5AyNSm60AiY274aE9Yr87W zwg|DcFF8a!#}tH|J^F)o9G49bb_HW ztctw60$GdE@Ea|UiD|z(zX)%RH|<2z&PAGe|x5NVL=9s`w@CzX_J@aZ$ zZ{zPj;KLpo%3ER4hzEBqJ-Yz5$3ueMt8KwE!K_~&|7|nOz``DwlF|zBxWpHfF<$e4 zXPsxl5QhxYDBj689s+zkTF~NIIq+p@a?&cZ`6o_*9x zbPZH$+=*PlJRS|*e{ECzWt4c_Pfm}@gh5K?6rBvT1EZcdl7cn4+cgn*Z*mq<6{X|x zD4;FjWVC;ot%wNZFl-5V^wX(6zEDC9vHO9D9y)F zv1kQ3kwjgB*UmL`_%rX8D&_UV9*mWQ(avzpNdq_}dHw|om>F38Y#ua+eqF zf+T7c79VJMu^+8)DE&(b!4DaE?M^=&A#>SkTT}%=Q?y}WT@laYUghFRc5M4`eH;XQ zWnAGw=SA2Y$*J=}Ok3<~M0ekqyhi<=tqZigJ}Tc{og_Z;o&FJ`-b_4ijj%mV zU1*mxdW1MzNI|4{{1&lh@E3Z=0Px#af`edySJ&Zv2g-DKQyH*$N$}czk>C)MBp72R z0J1tNgu`X~#;5xHI;=eB{xiasNdrlQJ6%MSRA7Xp{wAE>2X$cv*_?NGCx1Xj$XUs| z9BX02cVl4u-RO4*PF&SP-l=`WCzeLVEIVK1njOh6s;Js<>N1H+`xEl@AJCSme(asc zR*$mUJx`=h!rY{?tK02ob~{k3jKBO@^$0(@T66Pm!t?9yH^=|)X{X?zHCdGiMu!SRy33ex4y2JMdV{SIb?`?*bah09_` zgTb|UV2qq`_guhsP?Q-9Iv$D63Vl>U%vBD(-XObZzEOE6@@ZrV`L17}Stak$uL>1k zdu&$sf|WSpdqCvi{{RCu%$Z&Oi_o%A+=l&cZ_SO*p7b{WqWYid5HJOGtY5xbo~+m6 zmHgY7eQ9fLJUd`R_vWq$hWzzEl~oW9F7@iB^+o}Yov(V~cT0pc7w|E)L5w7#w^r@b z&I7@@beqTbj0g-~q(YR>*JG%oHATLB*!>2uS>Bz5dbz5!H0-O?Mk>K!{6>Zl)sORV zq_NuZebCpVmgSo^fO{I=wsV{PCWXKO&6nu|C8Xgq{26>56S_qlVviyqU_)anfVGp= zX|9@mJn$QzmRvXliSTUU*^kr17(4pf{ApE)s^V5aB&oWtjN-p?;&&^a#t**3EuiKP z;XydVihyYZ7h{++5v+m9t;w)$^bFy^1;hoIXerwXk4r*I_IDAGX>FsR)IAEF1)5yD zeS59Y$A$sZAW%Zbw1D$>0-ygGq-n^!kM!50Zfu z2p)-q=dGt?lI^I{`O(i(`*yj5&QMKC2s#z&I$ljft~&%U$o$NT#OgI#)$=)A&@>F@#^{~-Jv=eqT`>S&I1<6HGDhja-bv*DDr}Ndc zJEt3>;eOrc?pSz&4~bOk#OG$2g)xn;jKeg$$1u>|@|SPaIRqp?3I9Gb9}UB~6-J^Y z;Bt0dfot2~FRLP&H5mFY(mX>G&5r3xLIp~oFB=Q`SL2>q_Ar%7_HT0;S-wlig$wBgfVJzs!lR}0skfKD$f z;7iEbMTWUiKOm#@(*ts)7!lCQ1G(5NLP=RPZ!OMDc|2+4>J6|_<18S%U-i(`eMr2Gsyu=p?*Z)F48Trn&BlNtQ zXTuAgJ8SYNG8SU#%M6U_565=D>FSzsKPQ*Y+JK%jY3Lccs;@PE@u-mop?Cj_yH<*3 zW0no=x28^nyec64qdZzi9OI6AM$(}wA^iAZ7gIZ11@9`2D}&A*LcG1S1}j)^yB}HW z6x#rCjDZ8Ne3_(UCa|P^c-C=0;wWU~S&N748Bs14qXLd4W9mF(q_S;{%;W{e7uE_H z`R)}gY2$Abj_-poEf%;Kt)b1a{8d{Hn5;W_$ zYXSahfbo<0vp3e=Pr9TT<%3YTyKw90MN9g4!MIK{4>mb01hP4 zLN-?AzBop8g*o*O3aydrm4>uN27c6)kF7N$Nv?WtMyk+?QUp zhur0*mjmj9ElYc*Cm?HTTR-h?^*crYu2A~=?)5_xN#R#B_RQyt$pD&JFhjsD7E&q(^}@7RUON&5jLIWOJGZu@h59 z1|MLYNb`w|uZLJljx-j;&=O`qFn>I}H62aNhqp78oz!~0-A<5_tQ zOIz>L|4x`)8c2 zE=a`Tw*t?9QmxlTEibEZ4MV;|g9yZr5lgWeXhpyEV>DpBRNwpwRD3u6yWTR*pLpc-?+kYbn;s+3RIGdK#ie zuZRRiU9_rN#Yu~lN)-2uGalpw&A9acsDsn8`Z3;IlOnX2Sm;VecK!b{GE*e=|gakYUe=*ri5nDj^~v2%;@IR8f@HEZs@$9jmp) z9xZKERdu1-qRVWnrA13|sp`_9b=}|VcR$bTd0zKF_a7(uoO3=W|0J)I^ZlInSo7jr zs?AtXqX{@MTDlS@0N1L-w9oDCNBhW-3TAj~AYRh@jVJ7tvF?L&50#rD1$4vf9FWUE zU(&2{Kv|&}TQ%yT&vXk=R$|O)A$Jp+K4ml)@HPlWazoW$;P76K!A$0Ofo2`XJ;phI)+m2MT?ePrGOX0LDMC_q3HpDpnf=PEY-dcwRf!n5g8 z>N1g!qAVNSwFuAtPKe5z`z$oB67H|>4N6@kdaKG68k2S57$dI46vf(g+e<5*)K2iu z4zud}bTFbEVH1&L>fF!56|#CzZ}lBs5|4BgB_>l$i;x+$hti$+$BJtRHsOCJ((uhl zhz|^--(#=*^el|Ndbyz zU0^m&%KL?CurO9)?)28xbe^f(;DT|h8Af7Gn{;%tkn2B@AKQK>dRueCoO14)kSNdAa)od6U!& zJ%S~%G|$vS!B1H?u9{f7Z%X;l%La~pXIVy`Y>z^b9)@}}9?PPIzl(n06^D%TfP}!Z zpNh_~gQJotkl1uthsNUxoAo17?ZZ5LC>9rm@e>W24kY`X$LZ@Rg^JC1Djn$vyEQV1 z3XiQouV;>P4V`a9i-htm;xk- zEs`_4S@&PgbDO4S!hg#>T!TF6HNycJviv-byV#DyHWzbU*f|!@pE_u!MO{vIK+mNu z(^J%z@Y@3!fp!wGs~+Y-Pt-;~{<0{(K?XEi5> zh-tV2Coe}W#__PX7C##2x$f$a!5*DGH^m&u2+LJCSd4vPV5szK`| zqyoAFNi@fXP+~<~XTvua@H9r{N2)DPsU9FoJkueIVi8@wk5vq&bk6l6ZZ;nDHI;GU zLn42lAVe6y!9>t-Vs4isHaeZ~GArlj?)E5Q-;M$*@P0Awhy>0&h2$u8tFkcE;Ey0bXEOILk{I@_k$Bo~Jp&;9&PsM#`J{KYyqscDSd`K>`r)oIkQ zTWkeOOgEBEBLw}NlyytPAsh-2M2TH-P}fG(w<(cteOzxdt{o13Q)Y>eG73-;1bqOX zB=N%%<=Ps`365WgwD(+4a}7NKM^+5}nP6qwO(Iqz%!lEf?`(=BEbpUMIk+|b_;|UA z2iS)EBd^c|J@cCopb{~2(m}Tk+FMa{E!-6FY7Kzk1ND2_ls;b5#ag5CesLZ_<7Iz1 ziHu*S{U%Y%Xfm+<_7}eI`&^Sab87L5797>kZn%H^PgrxUOU}U_GmGMjv8;zXe^87k zO`4h)OOg&q5=vLIE`%r_-+lM-wZpwwk)X{OtxJtzRyi)PBoW~)C0t2(sd{qJZ&IJH z{lzCDH7^GAmTvc)>H}pPah$_PC$MdI**>Z-R@*O>uQ$|mNAC^(>#Y2+_A7XLh?jqp z$9eqdfqBF0ua%hRy}R3|Pp}VIoj*}zd#(WC{txlPO-&0m81?3b6dBeE?F&W~Ny09< z@INlpFhqS8KlIeqT!O=F2;5oP@V&;sy0_v~>&k>;5nHq=w99KsvJjWBOBGY!wF-MU zB@NO%AFf<1SbEp-r1K}?gh6O}WQ@6|7tM)vq?u14Kz>lqjT#+7%8D)ziwY-R@x_Bq zH~1dTO3vTiiBU3Uvx80oqDwn-(##o8?RJJxV5Y-eU5yqWkP2ZqW_}70QZd%#UORTu zAyP5m!)hzZ>?QQ+$u^jyqVj4IcyfV2w~K3ADoe=giQ7?BT#deb&GV-cW9;ULu(0|Q z8C1%R96Z#Tmw%@XW|_y8#EUeoSNqhZKtqotcsHjGUKt<+be6#6 zPU=U4*d`0#^4s%1Nf&eSlnsdFSw#=Ry(0;`6!RMDl}ryIn?sFg!R9YtC0epNp+w4e zmy{13=>bn`&=-m|pF7*67=G;|N8uuNXH-t2K75vnmpqz$?}pwqLEc0XTBun+fNp@) z<6JX}fy9U{uS+4_*)4>BZWlX@ITD;ZqSYJU6Yo*@>TqtTg0isA)M>k#u4={H=O3;M zHiwcW_s-xJL@KGb{!W~`+Y|cS#Y`qIt4DKYB(k~AbNA4KopX`W;nf_+l-$~?j-6;8FvWHX+lDk3V@U%wggyzdTTQ2PjKo6S(BG5JDMthsZLjEVCG zYgw?Af4SHIA*n+Yr!-Udr%e8uBY=9JK87}1j0o%a$YhDpyr*6X<)TyjN*-vs)+=3u z9vhJ$be1~iBFO^7*pz&$oDrn+8FSeY5wI)>N88rq=W?+HKNj|z*zA9&5|ZzDh+yzBA$ zU>US?5MYzahY|iUB-jR{JN@&r#t~1M1%ag0N;5B-vPS3l7@5#4--fyMhOcL+YYB+S zT7OsIuj+Qxm@p6<`oJ|YoRw4q@0uk3=8 zEB6PB%$p%TsRh^V-9C-yW@gyddgx_UnC_T!zdGc(`;ULt8L5l0vzGg9@1(s$o$ZS+ zC%KCKS{ToBR~x^|B+E3JJ3qbFci5X=ymd4oXA9fJ_xT?OYwaAFJR^O?bZc3 z|I8P43!Z-JNFUX_)m{GrSuX zf_b@RwFC_?Tb$6Ton<7Ib8YHRTiRt!X}eM{#UB`rrB8U@7$|+F$0d{y=zXekQmD;- z5g<;1tz)QqaOFb7!EO$^8u-f|b8XE7h?RNR^eJho=wT1$my%q}N?9id^8#gvvn!Cx zx2u)uh6W5om6YJ3e+hlDwKlDWP#u@bv&Hd8UNy|Xm2gww=YQz8mZOib@#aU-OA2wHOFnWd7oO#;D00DiS(L&bw{fmgSpk(Q+AHYht)h5`3EYB z&Zc~q@q0LS?rKMBk!eARM1C+X@sGd^r~k!qZ}J-#Qq1XbgR7zAOLf5-g=-ng)p23p z=+!iMu160zHQF?4w1T00cuPXiMe)|=9$znnC}hOKg=8pnDnJml-~T4EC$NA{u4$3@2V|X```03 z2$Z2=Pe^^C=?1GazkYu!$2A(7t}OIM)bibKrUITPhp!c{s6Xg(yG&EkQKnQS zcsDlpiDh$-P`isNnDE|@I;vS(rwcM7D~mm{ap-Ja=$=CwK|b8T+QO*MFx}1)lr8T` z49^m&*_fG;hEX!DrmaYfD0net$Ed4($6Nh&g@&p8@g!Ut<{i=bhZiMDZllPlbJ@sP zY|oJ)(NUAN&(jBVj7=O+aK%5Hq}6;Y)nQ@UVBd@gx10G%j8BaSF=}b7FJQ6*VDkkA z-ssiLxmkaj+>|aDR7Uu@Z9*PQ%u*Od>cL<5iWgbl2y16roz{2OmRSNk9guFea)3#hZq;oEImZv=LXJG zHH|IQugcuP(7JtZDfAzxnPC{*ghw+ZOCeLD<$i%VZ|Exw_$~{vWW3|345e}>11Y_X zH0Z15l+Q&IblT_zB*iJqmUyTjllO{mOH-<02+f3O2kG80($@~yEem)OrAR4}_@RRs zAPC6!kGX2FKA@o7md-tDyV{{eS8@z;^1juNY#`)AZY<(~o(-0ZxMC8wvVFt-6iFVN zyK)RK6W`H(cr7y^F_AORFg;z=;kIkW6C;tn%J(;hHja^f$Y@OsoHWGvf%Gg(pCm`Q zaliTdrPa&}qKN}q)bgV<%v-)&%m3IP`9-zyqJ*$=9h5=m5AB?S!;MbGzW$)Pf%B9G zoEJb}mdAia^(FuXY7P_WC|D_bj7}S?OG?=malB~;Q8X*wyjI^Mv2{ua^@m(`j=QIP z=w2e3tL1X8H*SE}tv9d?is$p6^^c7h#bAgk^=Df5NDArBVgt)iJ99>NHx+tZ2g7U3 zfW;ez^&PDp2eHq&eZ<$e&3PaBKOK4Jc2SnA#LnvXn0)xNLU-K@A74RNNcPYTq| zQH#Ihz$}Sc$Qa{9Y#o@@SX71jc{X7FpOE~!jrX8bo!&Ryd5!@$6-3eV;JpoAxk zVGZq*;U|TECvhZSAc>!u-hvoDu_r(o-Jp@=Jqg~Q1i%~RS*?K&bm0|f97 z1>E)Cb+x$f<^k6u$0RSIsD%ipY`x6FvX_j0r$%@y;y65teW?1bP79ZsIz*X=_&^4x z_|oS(vC^lnxPL$1Qry z0DGwF<7%LuloI05TKe55fP#Scgm+i>$^D1A%SVJvyNQB6P)-!O$kct7{uZ+N363h%hUZfWNRGYgKK=>u4J zQQ3SM;J~gX*?PXxKe?VT6=3KsrX7}D#vW~b+Gjcsa6Rmb@y)CcSD0T;wZVBws( zZSaXP2^!h5vwR@4m=aFx9(L}Jn*v-$8zWfn`}O*aDYbh_!s6%bl#8*|ULI~=>>+>U zhVyj3?f0Ju__dey3*4xfcRZJRqGPsF`2~`)6{9;ePi{N(pi9*UnAVkEU`Y#b-|451 zP1I^PZTNkMr)b_$^xTtdVC|6U1j5%8Gn;8zDZX)Mo~Zo`ME^YcFR*0qaHk~gtjn)F z-tpx>3DkS)bEmZ*C+I8RjGy~b`{FM}XWPw$#k`XD&^5oSZF3k1>8s$JVD9pQfAWnc z+utol;+J$x$0ZEj-Wa}32cl#snl_%;9>uYr$*2dmh4Qxxt;_rzS4@t%91VA8Vxl4u zg@zi+^p!GO+Y`k=d5co(az=yn(5J3tRJA9!?FrFLDu`0v>f~unDO)SdrYec}pzEtX zH*<#h5TM{B;e8B_H2s_%0gJsQY>tNadN*9z(+W?L7uCJdudkOpTJCoF`Db-Tv=%&h zTHh18p^5pxp>ShLUV(Nros!?ya8!yj}{Kt^m_?cv>S7*KLTj?H+^h`hl`md_HBjFitz z6KDz#lV=ENX@i?g!o}i10)=K>> zzg8+u5j90ZHSQJ3js~2UrvZbSfaM`EDt~rc727&V10~B10-^G7!9JZF0jq*`v`69z zwZ}%Y@mX?p&*%u^w2yOUJt(#v3#AY){w{fZLgeBs4Evk(m*o5GJsa{dJ!zxpuyXYi zM&OrfMS2s4lJl z@C!dW<~8xQ0iJlW?%vG4#=p8NN5_(^N9RDZrZlk|K&zr76=CkRXMQXQIR&XtbiL~9 z1t@3r2S3Q-l6JD^-qqOk)>BpS(ojN}f>UZf<%dhqi9N!xibP9#t?tdq)xuL=fdVPD zARk(a^H~rWy@jpjsSf5@Hb~Ed@3-~?5eub&?DSmD+p&~&Oo$%@YyaW+>yB)8xx6%G2vI^XnZ&z z=GV2u7ycr+I+=Z^&wI}q&)H*CuN`b{JqZ?B*`-#KTRy96+KfnY5JPDVw#O9iuRkJy zqm0UF$LpnNipcmfdJTE|cQ$;0oc_2tfYNyXOsM`r1+Q1|Jdd6_>!6REhQ2leAb#8l zJU>|_=k(lFce&U_JekY{%bY9x)Ka{u0%w*1wUb66NETf?bEOC>F?=8`fUd5M;M3=C zdz%IbSp80Ilk@}dYj5;aBVHXC1tn_YEhUGQLwz;t$A~E}Wga&^+;NbN@AaMol8hqY zqH+u)54{V_C;->k`P9&EXFz&IX*0|E8pIjNMVm|TEjj%VQH~_8ZpEZcn64B+Y-vx; z)V|f!990@i<>Q{eu_vKM7H{0*%MGR8kGgZy|4jAJsrG_v%6DtkMLI7rsbT7S4=M}K zrguS$ax3g26c4!VarJAc8|XUd*>vA!<)C)wvWtX4)i?_468y?Exrk{q{hOT%iy-shY4Tu)EV(cx#>?x;;6ePP#N)bI{Y zaPY`e#nWjz=-4ZAokRe0_?xRIMu*ywPF_U3FLiW0f*9N$;mx#d4vUVecAOCz1WM|z ziyhis0>DBOd4@1H$Cedf91>#0Hh*uC-5SE8e)m#>zqKn21%_awKH)FYuWpF#`KR$W zyf>EDix^R)Z+;OrK1z$6D4buv9~;xgC1Xvio$MUBBF!ey2t{pWy;vqt!h4IvF$)ZE zi-V=worC}e05LW43Dw9l$7yg-qzZyrU7%rf3j0xX;#yMu8|NRO>uWh@?adOV@Z?jU z(t=saO-~|;qm9*I{jR;Rvo-=n7x-JKwgCP(kqftY$Z(LW9(PhVa?k>rrW1?<%96{q z+%=GTKmkox<6ef3385&9`{n_gs5y}Op$JAm@>?V5$Qg#I10NNCeIT|!W-kV==%c~P z_eLqB9d1g?M8?0AcjUrX>;np!@}2mE=pxDslu6KoAvJWFt|i(}Xt|YMvYh|)U68cI z`_VswK=+E-dNf2Wu0kt%g94L_?N?^Xo+YJNFIYg`SOWxs=4FxW`j@qE`p~&jEu(rW z#zj=a`|2{%$e*;UT^b(+J~_FDI0q?omJGaVvDH$tO%7dS>)H}Mg1#l_j7|$nb?&&d zsSJ}7bhJjpJO5{>sCa43v+f2}M?tJJK{s`G2e(jb)NWEh8Y4u>VC}%Lca|s$fqTSx z#79{odHu+$rK*+ATx@+*W_3@(@CgUMlW@_$jDLX^>`Ps8pP{ca-9Uy7Jx&@iLY9A!s_YZbBPBF-r zJ#K;+ByT$bWqX=pBy{s{Knu%5F&eiuqluevbQR`s&?6qq=STw=W(X>ehY`tCxnTJD zd#&9*CiY}Rd3#KW=t3Wem0EyCz>HW&b$tQ(%~~EH<%z@r82(=Crf)t38o7$8LrUdR z%I-+tD+%peX09X~ z=NBaQopOGU*q@>;d6R$<_Y|u}Bq(GK>oh6F^cvVWjBV-Uyj)a%V)6 z3B48Lj-PN&o@IlY-&cB@QTRQTnWAtQC}FI_yf_y^q{clw;;rGDy>dqv76qC=?VeLV zl-sAVfEUD^o!j}1wZUPbtf_Z~R%*IalqPt(P%~=0ixfwOzTrAS7}!&BCPAV$i3JUsqHQq+8YZWz@~ zBV~8+&vQxQcF*g?bi(&%n6D)*`k-I3+g`GxlC%MrNa@0q#%XnTEYe*@X8oh&&)jnt z4@=wa8dJ-F{|ii=`qcm8{x|o&ci;Cj+bUAZUPzx=x71a=De3=9e{%f2u13?2St0ThiG*}U~ZDUe`?8G|#6AUHEQa%7ofiPSt?ygux3(78_?by)9ztSA`@ zrM#0a0;x<3ea}ejN$K=bY?clNLFxhCedkP_yjbB$2`ijKI0Uz=>cR^#7z08^rcJBj z5v@eVis59^??(6zib(>MWs#W4*_a}c`m`QLwJcuB(3IgttZ;oCGfH5n5&(OdWr-nn z>EMGVj&>9vG0UJI8bYgaQ%jj#K*=w{YKh82WdLfe$`ldK!45P^DB6EXw?(l9&-Z=*H6_t{b%I_kYk*DspS5l?UOLG=*gGto&7UOi;xRFR^b z{7^3L=y^AoLXlk~2v90GR_|!s%S*;@H<5Vol7UI6$7y$f@|#~8C1e6g9BD2A^;+qhCv?Z&#CJ(=wH$A)vcEQ>Yx&5?kqpLKE77; zZL7$`W0~@P7_Q=i~b(g0i0%K&4IT?bd&MJGIAD?0y$IeYUuy45^sQq98uLbGE# zhG$PZVRqE=!Eo@uwY=}rl;4?1FeLQkC`W;7y$Ey{B<{q)+k*=SHFk>Zi;Q@A)I}=+ z68JUlbvY8Gzrd-w-FRh)i9l%r%cwj#qgUIaGKPTLh`Yl5l&w2M56PV zB|_JpQ*gdFqE9;DLwv|!mgq-)qbLZ*o7tWCP z&4*7%ue7z>Zv(EHfAm!mn1e-hEF+#ujus1R?={g|B02wzj*BgleQk7Rq$I-#y@)Zj zY4~{sKO>TP^azHPE^Mej{BfzYGmpRs8_9s>ed z?~9_s89l|Z6Kx1tlTJjD&(%0J6PC`7U{Cii7oW=J^*^4IDZkER-G;Y zRs^C`JDLm7gvWF=tjHG=h#x@_ijtb-=dqH(v*q>SS`p&xH4s$l#<<-E=bl-<%mK9H zXeg~4lms127(bmL=@tEw{nvBuNa3y?v5FFqcC2XHpSnS!Ozk+ISvM&Y3FJx2x-0B_ zh#8s?84$_GCv2#-5-YV#7<20LCKR_W7^t3wHZWSP?4|I8KxVqzz6ua zEh+V5Q5{R~k()%Hri}FXoP8@KK-lll*x3jBI>pLRC>bX5unRkuhs>M^^YlP_GP!rm zOa3C&EFg_xZ>lAbzcNdrnS6f7snp6wF= z05v^ks-hjJyUizwTQ#dyb-f#Ouu(4kqdIu^;z{l1b-R493G{#WZ~sSiXvJ14C>(5J zTUS=Ien0Fukq4Vn1RE60C9r<|?*Wi*ZYS_X#C)SJYz@iXIaQ-r-9Lu3y=`fGcgo<% zoZ?JB)aL)!5fweZNtD{Y;p*Q_zaGVVnDBq}NTEu{EWw%l*mR;a?&Ub*9jq7uA*EM9 zTZHGbfK0JHEKGDoZ4-+hFnF=4{(PdJ?cNc_CyuuuP$FkUJri>rxnsZd-+Xg<87K@@ zN9In<`+K`QZ7k%Aih!bHx4jW0^L}XZ&_g7gsn{^eL>eNr%&B7%>Go5Is+}v-+ZI`s zlTu%%ksDqCnSVwUjuV*kYzbunb;kALOC%AUU4~R3{R@ECVONq?%6SunV~ozBjUxEL zdjL^$tu6rtBTey(!?}br&6)A$m@(RY0e4j$22y%wsTI$JA98fhu{;cL|>+gn}C zM(ysti7xqz*=GIEYW@!Sw^5~7#f&S-sf&5)BIZcz`h;DW)oo=Yc>(c2sCbz%&R$dG zljw8rXySLVhw(-71t%B6WOiFB6B}Kxg$p!-7)qnbv`F~03jjr`1v!wyE$=&w--l<| zG!rF~yq8+zA`;8%BFvWm(BHnLQfuVT$hQf-!X*U~9STj^C` zP$J8-Q=A|dDeb!WMtbYpI3Ze7SgODgO)V!8_Q4jTjr%3}grTaDQsVl-qFYY{qa_qK zi2MyP_>KE7+xT5&*&shrClB>dN4Gnpq&nVuQy&;K6&2r^FEd{CUbr}MOs(MaogH^9 zE)4Mxjh@yyp11Avi>F&t)$^wvJW9x0%!gga-=>j%P|b>Q{IH|S*A%nIrrM1UpL1`x zx`$G196vf9Fa14{|FHH~(RXK#W@^v=6j9{KTe==8PT5br!x}V=YFj;Z)kQsetN#V; zYqlCb4J{<9T}}RT*5w#!%k@n)t?jdwF4JklX~UEKP76|#=?h+}_kGu^fRJDss>7kv{}GgQ>!m$^s&GmEG7&n4~%F{oZ z6l7A^v;fkMkuW;;VCB8F_;L0qNz6V@QF{3nT(R?kM69mu+Ng2IIc`GHeB-t=>Dl*h z$vO9!e;Fuo7Y}45QH>$D`{ALP`F)fUxWLe)s&Tm>;+QM+mB)KfZ!d!^s4KJDiQ-8h zNlytut(s4?l6TG&CEYsG);lm|kJkhM(828u& z;>wXCh-SA2i$BvN2|m(ANek@75VT5B*s%*&`r{vWMT)8kX;64#LPsHQB8t$P;up$C zzbwK)(togVs6xy!<@)^qmPG5P0NZs8tV4UJJZY83ORfcvC)#ZIl2MT-*RI83+$C3# zP`8i4Y;+XqogUS?rgm7kw`FWjX;=r1CvYN)P&LL3?LOmJZZ>@|gQy%bj!~rIEi{Qs z@qKfIpk-d=h$oMPIT9)Ibkq_)R!BGEe(p{3*0}&LAc;Sjtu>hb?UFhGh<3E_DdqQt zjj79uIZaJX-*wSOMir`qX<(?~;j!W(6+~U-Egzc5+4eh=eUc~@ggEy%EKH5<{y!67 zK(Cs!w7Wej+M#!_2e`&QNdUk1CG5(#_jQZkp40BQNd>w7R2}Ykz4&eP>xsh(XJJ#g zEzu72ouh7Q7L8ZVgZt(7*^`9-`}A0XPcmhAcz^E(<2&0LwoM`fFy?7E;pxskoYkh5xM=KhoaA%}m)UtFy%a-@z;1~`TUYJfL`w_EG zkFZKC*y?-GCVJ+M!W?gl3`)sV)Ox8#{DnPx#!#EvcxsufKttIXlb0l;OiG!0k82}+ z=TT7(HRpNXlQE)xaW(tq_^!nyYr|K__Ce?=dDUj3MKuRQaEw^v!Q{1X$wZFk;k)b0 z#u197-NlrFKD9V$@c_@;nP8RcXfR~#H3s4VB>6wnsi(#^Ogq46+@Rq)-VBzK1eeCj zBC%7UVcopz@tR!phveS%*NwH(G#re}J&g&nj)8Q$^$w)x9xxzS${Y7`5N?mxnhXoq z%DH@}eVUL5fuy50LUMt|PE^ow?VR* zS`sU4G=Idwnr?620H8G5d7$$QF~>7+q&)YZmy{aH~iOREI8m>K1P4 zB$rY9D=G2NZAT~Kj0v9*obR@77|`9q;Ym1}A(c|m=i>6nZ7aa}u{cVnp!wU`;9F|1 zRMh|Zz5UFtr)LI5-gf#X9?pAzC&}x{(LC3Jj4N8u4DgSho-{LWmpL>xqPIP!Gde>_ z+_RZlDjGx~51e<}1RZ;Z@~9Rpl%F$8WSaFB304QP^_wk9AbD9;h zp_vi)Qtujim+=D*7FCFj5}^HRD;vKR!jhph6=HO-D-z+@<>O}iV*y)dh7xFxY7c2W zB{hsEq_2>RX7=mB{k1|IP}%75=6nd2?O$b1-EOoQh0h&2&o*tnZ12OC2hxqio`IU# zcWF|d=yOR+rSW+(_Zu4hP4~~})yP|N_6eOnoTYI|4`&R#Y#paqr2yMjI4Z=kym}CH z#OB5KD+M3h6F4Y4i{1HLjJad^{xbf^ix{!4!GNhCx01Y{l>5j`t)b5Jk5xnD0*}}Y z$L79ziSt&;Pn7-4tTXsdO8s6muD%E~1^tT>_E`}$B~ci~X~nQTvY)g4_YpLTfa7vl z1@+KF)R-qir<`}$(MXg*>b$fiKH=%&2ss6k1~^(}J`L@y zw0pA_ogNgqs5 zJloQG_TKxGb$@m^_lS-Eb)#3WgjfGJ`!67szsBzb-4i^)l}-Q6+k=V16K7jmQeS>H zbN+cMFYe)^{CT9YbyHB{O^w*l%~mNnFwz8TXCwCiMZ}Y}Cxy0q^XFGH)-u+(pN~0b zb!hi!_rUH?Vcz+KRxRUUIy&Oit58!r%cAC zx3+l&l9Rf3ETO=2w4~3qb`aE7IpjsY(USqs>j`)-yYg)cra8d7fJzr-Y7bbj6kvV1 zE+>*lazE?f%R&H|qGX1R>Pyb-QbE8P$4rRP*jge#OcvOQ@g12-AA34%F>p+vOFkdI zPdf-ecOSTYImZoMxnn`;!ROEkhRMO>Hp1o!!r2){nAZFLNYHSruIB=PIVp4?B?f`6 zl|%w2ER+HSDd#TBnlrO(i)m$AETmAjEl%vp(p5lgwev7D0-z6zUNP0yw@4JuzF%)g z2m&6iG|Vc=m?znm!|4a?AY)9cO(N3>v8jc+?3^~m4g&^yGjm4ZDqG7|1DBN}QM`tJ zV=NM_#fX2PYyN;cW&?_#Gs`+f<;O#$C3>|M?A&Vu52a{pCq7=Qc-*B6N}xYTm~9Cv zot`5A!j|?yn>m2V)0XDQ(NykorctkUEX7i@xH3DB415t7g&aNek7I<%X=xRMq_@aa z2B|tAg6)!2O7-2gn8)hsT2Gj!NS)wOZj91WLD(a2^WHOywhAo-RZmxvIsv zcF#wm!o|JtmWXGJNJjpY_X#)BKZzF~(dzd+O1eMdi@!)#^c!S&@oj6db_;p!SGqxVH}D)hOER}4QpyjX9>Q=sSE z?=-YohXe=xUa9RmZVf02Epw|d{{mn7Bijp#5AImdozu3Qg}>C+3(TOka???%H}3{Q zKfNLhbQ+J{{;QsN_VVDN`?tQ_` z-f3G&gSOWcfkq-D(UJK!nU+WREJuGB=PSMa$dGpkRmidq#p6}Hx1cZa;%`o)&$e0v6axnRcw zA4Rh^$x@ere141|u3HfFo3w0bGt94N%7NgDm>Rg3&sh|&z1j%S`)mJfqN z0vW~v?sM_n{N}}A*27ZtF$VB32n+0c(+u5)Eh*=qD!FTgJV`|K5G%4?6hdcPSk;pA zz}v=iBM)BJE6yHS@Vq43R#${s{kpfHnwuRz?<_-~V-b>$!W?m&X0*VPb z@^J2$b_V&P0*0YBAshLKg+FPaIOcbX2z<~J{qh+40p&cjRkPN1t`}ra3m?7z7hpRN zsj>ZD=(PJNoXYW5Pe%^~t) zi+#@sF(rqoGKZ>Z$>>X5e%52g`D3i997+`qtyy$1cPWQWe0X|gc=f)j~;gECCujrx+JsO6FLeH&038^&pU1U7#yxX$8sr^&~N1R)O5y zI5Ms@rPn%d#h&`|N%s>Tsk5@JG^5|lnl2R2WzFGndUGrYFT92O(fQ0jRCWHmy;J3i z5o)y)U5m_VpfQYwpoS*(eYn%b09oFpvlRcf2per>NlmLbmOKPNZoQ;_Wox83Xl1}g z*%f{2Zdjat(7if^@089Q=kV$tA(D`WscM|k5_{(JbOo)?);hCvj(boSZyFRkgKn&B zOj+X<&>re$CIlRF*~XFr1<6T;#)D42);v*_3A-oKQhy7rz4W56BgMR;*O8cILuOY zYXPz%AcHJ940B~y2hed#W5%0H2q(v)6f@##A)%y!^-TD|10a^)HFw9lbXU3WpMsTV zbNII@BL4#Ex1PQByW3m6vh}F>ddrQJ`Ez&drtlfZ2PS}e%=Vs5@csX%OyEG z{N`o8<><<`AsxW;+=0G-zSqNM)mk@fZKZ-2&h!V}ZC{?Mm1}DV-1u~_c70=KKVVdE zG3qIJEuH9Dk0lJ5US6QoxPLxzz(4O*kw=eu`3iDAl9QSgGNAxxmSFYi{Ik+)Lbqr> zWc|TPdEh@C`DJ3IwEPwRAy3kNO&p{1Q7?ji@{EgXmhd@yAEfAYAc!n|d}u^VYRnnp zc^Q5vf-Ze`AYhn!4}PKSNdjTtSa^@sI@OFFk&&QQ|r z#-V;_-g2_+lWgZ!y%5RXsPbt-7$QnADGlUKxf{ld4>#wB5Hf`gBS->D@68C(`eIc5 zjhdI2Mgh^Bx@>IED0i6{l%J7O7*D~OTKS8G#qnOk#T&`r)}AyQM5mTu@9KTn#W;_X z+{&^8@(Ekb`mX8MAzfY=1(*izTz>t-_o=0DENRsf{xh|*qdbT!;StvhBcNQ}V0g7J znPwP`o#^}y`4{NUejRw2AEE?N+6Qj7*Z7Vg=BZL&>`*a-h+vH}{v{)q@TqKxX5E zeA{3vl*OZ-=I?(-^k!?jbsx5Z#vl288%_xu?slH4cgsXHl2$WR{ubtOoLfcq{>|U} zKjEcC9%FWsK+E3LR&9npU{j$kgl*3}$4;qlFWG`>>_(=XyS@R|-hMef7)cjb@mNr- z9F~8Dg&Z)X-7GS`MTGY69oC$#$$8hoPW-qNcH@CkT<0m5tDC( z7PARvhh-xdbeh$rXO~NuSGqf25mfP#=m@7pE6NZ;JG{8Otx*`!_RzB=vjNVRs2;+Y zGix;XT*D2=;5xaL3+x?-zfm>J?mTi(WIZtHkSZKn^!XV3TMvbxz^m@-0xp!Fu3T&e zVpI|yn5NT8e6O}|x^4G76YJ?J3TqAcyBs;5sop`{9!!}Z=|i0J8$#4a4^J5PUEUex z_lpFC(Hv89{<<78n*(-hN{*pwcDuOA=MAw}ua^#@#3B?*78J9zlth?!uyG6-O(WNI zIO>D0L}%%(F-5|0R!pW!vwVRK90;k_IoWy~$B~~9&-fQ8rgkg5ulGaYb$Knn;|7|v zB@u2!(_`VRjEgNV|xcrNKf=t1I0_a`L8YX*NvTqCWT=r!l@` zY8GBpxATS&YvdpxsSxXu`-CB3BAsc9V$)MlWQw5R*rtKnf=H(k2mj@ve$vKGjk(`P zD(t_D_jqVVZ9O+#e}ez{@P}VzlVO#Mq!=b@=bHreuQFq{StY+RmyhPlsG$FPjePjt z3P+Ke!2N9(>*w1I+OFZSKk75n%@(c)1`yf6)!1~$JwdoSR!`CcpSbm=3tIP)|KDeUA^vqe4FO5|Ka=AZ`2E=-WMi!e{mls zKl0B?*11tY?I0bwz_IKj8jAt>_g~VKq2h;*yR{n;_{Olftax+(JV(8P@}zIidxnoe+(L<2+z- zy#fk74|RJPlqqczEwaQ65}Sgo{bE7&y>q5BKrHO5z6r`0_~c5@$9#&DeJXN{TGDhc zd1#=i=GD8RC2MnJ^bI*5B;L=dH^YxSTH!D#7QKT2A83Q!+R8Z?U0}*IaFc8 zN1c6m4ST7Z_Cu#?0dlFEerFCpU3;_XxKE2RGEG_hJUNj=hFb?{H-DvIFJh=ED&Cfs# z|KpF-!me8@HBfwPGFoG6#h>d3fw03$@=r;l>MM}b@W)UK?V?qT>qW0KO2*y{EPqKz z@f7uF_qoSYI#HC(R~C=qD*{-#m1g4sNIg0G!4l42b5!A*E8~wBRDH=PL_|;Y9$s7Q zKuzs<>vc$?psA%nx{DVr7pD+r?9F>U^SZZVyWmn%B z7CZN>tZ7Zg`hDaK6X+tmSmZ5Aj)?}aCABnN=M@77>;GXs<=o+(`&3FL1t}m*N{{E< zc6gjEUgb>)%TIB{u-+f@#<()H%ai9OZ5jga;vl25cqNt#@-tg|Qqqj}^l#>Yn*N}n z1!@I;cTV8}JRtJq+4KoWv;nDF$&S5)PGoq`WgG{Gs?Dp5ag zqY(MimXTC*%Vphm9Bk0aj(&C z?{U>EhG%H9{upjdhIL|pN1uwQ^TbX19nF|CPsX05^pU#PZo*3cQk{?3$#38Co5nmp zs2-sFq-y6+yTJy+sKh<$l#bL4oENZ9H7Sf*D0`uzf$11IUxL+IS~yO#dNNIFMN=ZAGP6 z;<1l^Yr`>+!sRe1tdj@+i7-qNn}lvFn`ZpQ-pt|4EYa9vLqf?rgb6paRMO~}4@rC= zs*(2h%lY_H^NC?F11#*Ou43@E?GJWF$aT7cCRCljtoG;w{)kT}ljSv=4 zvJmDTyAaaL=Tuk9Q1G+yp2QG_w1q#cfcVuFGljQbzt(Gcfugwd;5fAC{0YhXrh6@+ z@AS>{;XN8BDGJdQ!$!**r}SZ-*j(uXNRtE|)50}u_8`#L`% zjxg&)`eX(@%?>4(LSboQy#}~g>79`gSP}}a$1_y8vm`&QTu?KRFRwD(#nY^344)@I z{#@qcML}p740}%|xB*7h-pQCbXwcv* z%q)@q=SwFE0;!JI_DvnzYU=yq022sFXd(0t0YVqP^j;DOkU)UYr3zA{Nl}U* zN(;SL>4X+SQ=|x@C{3k_bU{U$ARwaB6h++pw#?4%OlETKoSQ$Ac{%Uhb3R4RutOC# zoZC zd`l|%yDe^uEeaj-kwN4sCtDPzir}K2kQz*fsiNv*a5Jyf@(xl1f1Up`<{z}uodZ<# zvh=}9#N&8auX2pAD17i%SlsoS>pIM1qKVI$ffK=gAFk##yQq9Ek#3(%%Ma1tf&(=Q zeV4UIDt}p8aWHW04m;~o$gUSV@c-AY+0);iN) z#92i%5{;v5CGl%iLNgZm(l{s|ghDux^zuL;&DZ=T)<>EWXJ|lbjX+Ss*!FvV1(wTwmzJ5V0%@kzmNFb>gNJ)&5O>pzT z_MlS*WRTm_2$pgh0!vtH_lr5&K9+J#Dc(tr4C4awKR}0tT9g2SW*HGFSx7&mp-^vg z6{{(&agP^ixs%M4rWOA_9Obg%yBUfTW?acfgQrc>vETQ-b(LV-Qbab_brthiy9~nNM$iC^@ zhhTx$!cF2oX z7>npg4&MhB8d<%RjT37s$&%(-YTO;$-q>__R)u6ELzx(v#^TVxeS#)~7cTCA$23VS zguUihMu$axIMijV!#B%O0xoc(pMr(WRUmCVdbtf%%% zYyt;EG;t95Q}ct#v<+JV#&$GGd`OCbZhm#OgnB?u9T=h|#BCxNNTo-EL$Xetk!HS-vEZT@ouY@P^)x zRmqFqe#Pm3w$y21m!BIEp2O~s8J7lRl^3D*IQ%1r&^;1gffx%WgS+hRw;Iz7C2c%; zu!)pkL?Sb}ss4LNw}<8>nnI01WJT5^yzT(BM5meTf=+<`kq(JfS1V2UtricSWPgkX z0Wi$@k%bthmh_P!S`1&)#VFDuA1IhZ4?!ca7NF5)3f3?uS@#r`m?>y1pP!2mh>#LR z@~@E*$`)m>x8SLOte5MT0dT~ga9Kjwq(Rdy8v4>LP_psP>}?q?Wbf^|1KkBi+lS##S2}@B$8mkti`C(>}|=0fWwt#UDiIPFgi3TQ16R5?H+cA zzu**&&z;$QXw8x~0Igg&etk7)q-Sw zF4Wu&;e`R~FOB$JLNd=$$!j3bI8w|1oTh8n$*x@Ph4lfUnjglId6+v%wdo{$lDULb z>jvMQg?6?%+6#i-Zy)NEEc}*xLNm)mH#qxMn4tuZNepOPO*mYF$V46jC`m<9Eid-6 z{SYFv#-`Jc@EP#>@_ouZm6Yi;Gh7-g&0MH5!YK}^kryf@-R@}*9{(NMJRqxUkJ#qQ zLRMgx*1>T!b0?QRK(%^or%@XGtt%TH)Dy7{A}(;h;l&gseg(j6;r9>FC%8S2iZ5gu z2<28(@5{%6)hV{3=AT(RKs=z2Lj(~dK|xNPTP3-m@ti$e;SiVjH;}V@vK+!>1jYH5Tiw6H`9$m{NuR~BziT8CfZv-Qlhty*^RH5(-qg5 z_|tXCTQ@x8G|+6zWL6Po(HMj&-qd(A9i20}cSn{bYgZ#il8|Tj`#$M&ruO0Gm{_aNYklz}0@qh0 z{i1JuPmpFK;F5a4;*Yv$he%HolSoRegh96YN6{I^?)6S)g)JPveG>~Ac3W_Sk z@cPS28{%wHE!{&xFM#5 zrT9rH6+x7{Pmnb^ZL%VWT*haXvm`1H)lCNr(zJuU|;^Mo;xDt%hk)?g++t*320QHQ+MDQvv0mMA=cP{ws zhK;Zy=^tQ3yfkduR+Q1Vw9p@}O~9*D0o4|@&{Xa|0N22$vibumlYkP2>$Z`&=Aa|h z%$EwLizw76MU?ab@dF@Q;uwf3r}hr)gv)Yn_GP|qyk|%p99{99vG}O3!uIVjE>}#U z;jtWy#=g(ER1`s%msZ_D4~g%Q0%v!!X3a4R6OA0gQd7#`grTHv%zw@#&oQU+Swa;g zaR>3aIt@Ml0O1w@GZdh8OuTDX@)P>F+LW^p>e?pho8Qc(f=7IuKqu3l&_93HBa4RId4_}*9iE3?f-w* zq@U-xT0X|HNa}}Cet8>Gna><6^XmG%O4Z1>DYB?7zRMi`0`+cizqNI~xsTktZ`6wZy@@;)!Y8DgUfrp2@_`Mr``Yj3#@U;JrqFq#S+WLX zEH%UY^*qKi2}BQrh^wpIV+53qGnOks56ZK6cpn&1-I3LaDyfgRIaHXv@|ispVnmTV z?Qq*lgJ%;2XGNz@GtnTmZ$;PPm|XgI1f>;GobouIPqt}7_%*%slK*feNwi^`^l)Ih zgc3t76HgAb*BV;-={CZd4Ov6VGp9Ntx+jG7)^FgbQi3bVSq;4}a}+PvC9KUE-H#%Q!J=JgJU%%~g(usJckAn^gpzK&O_ z`Mjxp$cGXYyIBZS?D6XQ_1*`~md5%}%$ZeLr;TaSc4V@ZRJ{1N zh;6&ikPKSFwZEO@NiSU08~P?=MoRrY`qGLE1^Gr)>7C}#7G_=f)nY?g<3tAkjWTMpwoOo{S!J!Eg?&MY6ILm5eg2RlHc>ZKmhxQw)0c*#9drLREqU+svLK z;6CPLK-d&j{9azts(%`*$3ydyEB-|rA^|oI%qV9_rTgTFf^V+@FItKWw|SIgQuGqs2GR?k4gdu=U53P3NW)s`eCQ92HXAY9`Ve2oG5oS%67h7JfBbS z0i`_8u8J#cyFhuA$Q2`@?l|oWr$a0ldmm64nCW5HNj>~P&Rm-1$tF+(x(U2?H3B#uQxdY+)P-BpaO{5ZPB1FffC^;x$?;dAsO`! z@OEi$>3G8QoEZVw@n2ZivZCS{MOm5TPLHS|?IJW=P=oBkVHud$7&}BJUmj2zc`N(Z zmM_0D^eh?&wuCCdrOK8;d_rq-qWo}CaU82wR5>(lR*Kcbe=!c~3!sR+Gg?+IdVsHV zH}eD$;k03_zw1v&bIm1Q=D)I~8WAK3g=S}~@f=Pqz&n~Yc^W$#KdqfO z$ab#$Y`EYj9MKq>MrV(oFN7wneLSP}CWMB`O%GwFdsC>)Ruj7nBKe$#=YDW@FjdVlFe>>=%ho>t+T|ZWU`UTAUzV_J`#_$Gqa(6nw?}}o_UqTk zi?2CqlNr%RL}hXHs3FL_5GRDur9nNxjfF12t`d4As55X-&Pgo^#~|JN2A_D%4-;j%Q;@~0 zI>f)h;eH*OCNbtGwxEC+c`IEu_xK5h=1bZZK`YbC_C+qU##r^p47o z`#0qL5T19(8IX_LBy^r!%1XHIx6S+sdg8cScD=0J2;tF)gZz%I9txzq>8focuz=eypneD&j`nR{89ucLlRi*OUwSb=%maH~|W_U-#=( z2Zy$A;<7UuW(4s2Wh%OAdE0_*B6S2M6+I6USI5=mg)o}j{FJCDS}DRQ5`y|GLeN#fa|OW#fcs@o#QGR*z*LsxnN>h zr}PuDN+kx^b)%tG5?r*i^;)n9+WnL`;FG9eY8jv)AOg(N6q`n#9Ls z*62=OX39PN!AA04QCd~qr)V&byndGwh6{w48j{`PK^0ETOHUg00(36Dvg$liZPj8zBqgDnH2(e z-BDuZup33!8*gg|W-(-`iWr3vw8`*k|Xe8Xuc&<%%K_UGomz z(DPOtPIM`>g7e{kc*qMjPp>*lJR21OXQxwoCYF1o?KKkF?xKVw$QfSsa6Ng#ATytN84V%ZqwfA#mnj+huu<4 z;+PArd{%d2pw5sJ*!Sia)i~uJ;0ygf!2D`hs{W*Zo7^*rd}AgQ;b^l7bm3nj{aU`- zAVuxFYq`<2=(UQ&whgB1E7E01H>f>M(O<^>4WtA0DOft?@k@%}d>L;kFN%GG`={-U zwV?JZ839aOK<|nI{`H1f5*@%D`jw%?xA;{(MgArQn)TAgrz!E7hLK|^4X46AR^*-e ze1GMqOfufN^m!d|A4VA-BTO7Hd@G!$FD&!c~v|5fG^T6&IP8or35po>WvO{`#C<$x_8Fn`r6nPmQ25{^Z?2`VXS6sr7P(QXPHe$G6WwE&ds+}w|MH>lLJ z;g(qu(~ej+OPwlUYi5N3mKyGgu@Bj9mQ(=Bqm~d=? ziiyv?>dikCW;8rL+0Rw@YJBM+K1F4;Jxa#SeIn=y&V)(&fV}lMDrm-ZCSo zEeYnymE@97*dqQQ+~Ym(6vy2QzCFd|st8N1_$?RqzJ5S0E}$IXpFK_#(BOO{uDMV7 z$fBRGQhm-S=uOxYBKQfPL37TNgcT0i1uaHpEiVkHIr^Bvq3CyUbN>Ljss8|@mNroq zCL*9+YKT{RbuK|PVI9X+)OeY);|NvK*JSM~oZ@?A3VURV_&Zw&-@>1`r-3+Ma^k@0 zvJF$rHP@2LGne(ffhQ4-j>{Akz!MFJwthvcJ$r?p-ZMLKFEgoDt=)o=7ZB_xV)=p+ z8bR+^AYT(-I0_mKPQM8a2(IvvfW0m9+z`+|emusk#3#Er8&I*fCMtT}=&j|Oo0;me z`V|{TAevb5cnQE5LSm;xs9tbkaG`BIAD^l*o)SJmoQ8CahEu20&G3Q`IFQ3vtr{tGB8qE>}7TX zpgZlN(v?8ZdyH4TqLIul`pfPpHN5hkUQ_6_4iXcIH%l(1A!7?i7E@Z+V%+jg+q|c8 zXF!AH=RSQVYdz@kau_?gJ_^P)j2;dLHkePCEL{)NK^QS#{ za{udo6_Re9c}eL@cu=?&qNeT5h(-<+5mfMd>j9`#zj@d(0r!yj!3dR@H=fZ}IvcR=y3=y{b(#v3raZxo9`x_O-T|ANt^7n{r!x@Gd5@U!DZdTTY zX%g3+jY&+4@Db61h0SGMo39>Pg8Y1Fh4!kn;lHYH z>#v|=^pIF-4NzcCBFuu+fV>z)baXsScc;js))#kbZRRwMWi1p|q#Uo)-TReBt6SjS zu7SVx;L!ZhF9|s#&|L&hDYqTXc5{!Cfa6OVlB);or=bx*Fhm+Fhg5s@slw>A8^Np0 zEZD?qu5k5Iedwrm{q*ddC`d*OM{B?KdcOtNVIG0)<)76(wWDw+dfLOKLTM~M zj=L~n*(&dq=0f&b9B0MYJ!p`7puX(uzSD-T^`nkh5>%|$iB?w$40jBnWiy?8B1gj_ z^L^S!+GiKJ8w$AamqNm4=MV?wctJ(od5vLD(MVg@(`{aVA1L#1K5CSk%;fPQEsMr>=JXJL@-M;@TbDHu1g!q zN?kV-;{kC|4A8j(I{4vm7t-1OreA7^topA`Ln6l-edgDLnwR{v-&WM&Z+TJymmT{I z>7VG#GQxs#nOJqm)Unj%q!LiVCXM<*c_twys|WRN9q}o!D@r6^;-@2!iyn!Q)2gYd zm9gCJN((6S)yT1P6Rco(v(;1h%sJwQtS`Oae&^Y>YhsoJ52~(*fOuVkt^Xcu_xvqW zH|=Z`M!UnXRo%~WyZsQ(JtUzfozhu^N=$%T-2Wu;wp0j-l1@(JNd2s703(nH#Oe4; zALQ-R-DIrTKD6)>KC~Dql%Z8+N{rjY8F1ZJ^^ZSVNoVJsTl}Fbcf0K8tF;jbZ&vZ- zQ*(Kj<`Jr{&?6XB@v>dlK|6LrtdAK5^IM1wQ@Mp}HD(XaZG!pk=9(ADG}bdtIFILl z`$5k&?QVL%;N4iL8lUHaiFwDGCVFNA27IU?0;%6#Ur4i^*wgqb>(-lH0(H<%G@M9N zQU)4U@Xf-0?RR~#QqSeqcL0JjLA{>*EzEaoUIJP2T@&?JQy8fy)gqXXpE4^$Mq_1go!U*5lQnu zF2w$*LXcbuSZGL82b9zmS@f)W#Y%WBS`*BI)Fjhu;Asx(dH8>Gx?VYgP*D1tccz6T z1{6PhhpSAQ7bwZ;k@xsN2RHjZq|05NH_vZ)h5KI7>?63xp>ZqM8P6{ya<|#bPaz;7 z(tc1kYQ2T~R~@yvQh#TU79&`AF4l-M3f2kye;%DR{17E~A;{{ck2 zsd`gA%nLKBAtK;F#PJKZP;Wt$Cjhpxc*h1t7o_9aNfd3D9JY--=-Pwx2+TNNdg)$s zkR30;VRRgGJ*b`?CRDv5%(CS#_?a4TgoCq-$=i0xw5r5sqJ6^Q<|_n7wleb}-vsVl z7kbHjhn9tqYq&T1M7F1dy{?fqRWa)~))EE0vx}-j(;5b!=fjtr5=0ah+oZ|~^Ryd= z_8VkB`5F;?iB-6~h?<7M*vkcl0dy-7Yb7GOCsX$GnavsfdE+5RSN^p7l5lP03jf0K zJ52WwRb3;1eaO7hQ8WrS^jY7VVtBu>2S0BrwUVqu)+-Knsvha-~u^u40iwqw*F#Dr!%VG5JzV1sxWh)L$@9AFjD~boEr$>j3om3UNVh^qqP-<~+boWWR8hm0++BXeWLN3757%qZafK9$u*QdY)%+-rl$EP> zc3rF3Ld=erX3R;0ZJLEgpml{EfXy6=ha=(?$_4ml6dQ2)^ocs;WyBZH4JLRue5tJ2we`Evpxk^yaq_7Ii{7-^W@jblDIG{B1D_UA2=n2{4mv&rp zDv&f@r)(ic04tDH87o|6l%!O&(-bHHka68YO#7`2R9;7c(iM&6%lT{ch=L9y;&;j$ zww2T^X+KH3fk_!rW*?3|Gbda;&mWT2P4@R*gJE#3>$Dz)Oqg`csFop7M()1qx&UEF ztK;%q-U`Bt#zIX%FaVLv~zRPF^?)Zx?omy32^=5h#MaLD8F%!LBLbNX|cjWp@wz+674z}gUah$ zx`w&wzS8~z#ENwe3`P90J!!9^3&92j5&1y#IaUW12`D(a;pgl%n^Vv?BcR)gj?-1n`vWeJfcoKf7+O`(be zZkZZYK_?*MI?wJ46Xp2ARd~jw4BLxIOdQ0DzJ556faIe>;#0(%^Ejk`XHD7NYwuOj zz&Qp`bxFszAT_hU?g$b-YeN8XRboxC>FLAkTK@p54fl_FbYIC_NN#Akva-Zx#23D6 z)>WhB^L9(#L8t(p9z6K!s0XWv3?=CMojeX+q2yo{lZGzOouUHF8nJHfzb<-}TW^C> zz6!NRuAdscZ8}_X@vcGrx?5hIAO?5%&+@c9_Dm~urKP8CVfWr!^pC>&gpA3tlfq|xkRSS=nuGT4%AP;yBOg$}>{t(2 zh^JYFM;n_dO#fY_tFFXxd{3!fd{oDS2aCFQJNr_iY2!Oy`)fLPnTkU(J}hbe(4@j! zMf(|TK&+M^9ae(P?*}is(dr{d_br2o=0j;+H>#MD@nu1yGWn>p8Ku>`R= zTkfR7cB5oZ3BfBsoOu8EJlBvi^UelQ3h=O!%L8LBCy9TZ)56lBO2RV#0mhubi4e}d zV%_>%X|H%~85uG7AgGZ!KJzZM8S1IsGCNu}6kdya5l#BcOcS_~#@{rJcYyb3@rim- zVLM#cI>bu4QiPaUi^y@%{Lpr%31-?D4+H=%_RZTW_Zs32!_sIjKjBdT4zO44Rl%HI zkSe7dqUBXBWuy1siFY6mR0yHB%hlx`ze?m8_8AnLf#X0l_6?J>;#5l&i6@PoF0>&D zsHoiO)sDLeI)gTIjq|*=hh8(wpk!=moF-NwW6M`)aHWx>;!%t^I(PIT9Ri|W>bx6N zqw_XQP)!o5um?nzD&I}FApOYwKvlOMPR~T1s$GgR+5#i!zaQG6w$+@nkP~KJEMB*K z6F7Om<%;PiW+>*87U$$Fw_CJqw%{(STaW~W)Unq`Y;+_AKUIM?m&Hn@^^bGODZFy% z)ZJuiLncE)G=w1A2g0(af5tcWa zO~@I63!+q=1kseev)pqK6uwe)yz-yR%FQ*QrgLef;IO*Zvwr(n_*c2sOqsAf$8+P4 zY2d)yl}gLU&c|M*sh5w{lV&H0wPC+%O{+S)p0GXm(J;?t%M0;;$Ju@>r}mzprrjJO z!JtM(oiGmlQCNC$HRuRYP*fwl_H)^1lhNi5`%VL|zfxZxW=AL^FFfpN!l}{ClfH)w zAx<5?y-bH6%q}d3g5;J&lHkiWw=cQ52%-ZgIguPZdwXnPE+Qw&sdkSmjr!h}%$~Co;xk`adJLIwFW{|-Ve3J` zaLES4(bA4=6B*N#Av;~^CQslPK?y^L>1kwCn!WOrA39rj59t zQq=UhdH$L3_`>yn0F7wG70wHX6`M$#A6NcYbK*Rrs)c_THgC>)d{9x)YTI>i;6=GPI&V=X;io}`~SwEJ?oFyk_!sv~Dt?>tUEhJ9eUE=dryl04 z;ObeqsB6)Z@f5>8fE^jB-cNqSqy$5clap1(C_3QM1RoT^>9(rGX7!5oO|8S9og%CJzR}MTDhadUzj=WwIBEwMf3Ukxq;_Cb1db z$lDdP{`#up^P;m7z5-CX*V~1AoT!24&(4$BycmNO8@X+vzU+ol0SQ7+x@~HjlKW^8 z&cr|(fnl&>9^DPqPu1)j_ZMJIu*uQ}@aOuk`c0N-$=BKH|Y2SMV^wq7gv$ViC%A0UuZqi!e+tm8SBy*QsfZu2feA4nyxLxW-8^(K*pV`*q zEd+aFxenQTfQ`Vk?5e2Fv(>JCc8o#C>lSApHGN5AT}HfG{~dQPTK;}1-NZfP95MIm zzSZ?^_B*q!S2oR>cfyIe z+KY#3nlA6}cZ4|kG(d^#wv2V8UDlx&ZSo4-&RWq1uP?8zf9eC|J6Mi=iItxCZ~5!O zk3cq2ukq7FlX_wJE?O=e?$?aCzz@;xmfuHTzwS*o=Pw)7#n$lCh=Kfa!JjTv$s(sE(9I zWbIttuRE+lCNIwa8|VA&d9J5d{YT#JAT!5q@JB4jiN(2Ay!58AN$vdonBLEmp&)T7 zC->=mxKGUZDd9$oH{gRQXudC&s1`n%DSme?CX{j2Er^JQSIpu!#2WTYj zGf*N*&a!p4uo8e#dd2A-jga$ceFfwiUpf~0`0*GX@YcF92P)+sPPKcxL1R?wLW?_S zBjc~LQAz-$gmpH0sx;N6T2d(!VA zz3@TJO|@VY?SxbwsDwhQyI}#o`W56G8W#-UV4l*dpGi$%gYUdEf{kgZpeH{qTmHbd zgAE`E_BuLjXy#j>sK+!t8(|4FL9(!f@~4S9fda2db7iTTL=Rag{Z*Dw$5eWa!3k;w za-Fn@gNBFlk4E<6ye=B>6Iq`n;Leo@sFFg$20&iI=att)401A?4cz)xKt?K&OqB_x zW&U94?eu)OO^2RvQ3C?9ces1M{7*041;@Rmjo3rx8*LPhDv53v@;$-|N$J-r9ExQ& zh3Kk{e40FLvG-*QU52YMz8vw1M2BhN?I(0^(kzsLuNoZzIT9<-Y%?E4*gbl@aUzq6 z{X*kiaU061bSScL39Xz=cb?XR8+4p7-+aHs&4?@7i&EBpyWL8^yF!uBN~U_t;ovN-Bn^{PmdogyWk`*s z471j$&SX$m}W3gM^t^-A(DcV1t07hS!I@&dSZqd^((*wQvSbR2devr7DHS z@-lcU1d80Jvh_Z;xP-wI$**gJkqC?{0KS0~)S?uE0 z?n&%5m9brY-1_R_W5Mr#-AYp)X^;DUrsiyzXN?L1JZ85>WAOk44s&f@?-EB}$`I${ z?dw(JuA8E%Kr3b#czmw$GlRRjl3hF8Fg1J3NUu`d(m}-Pw%3H|8%lT?1r_gf96Nc! zSUGUm{p$uFedubq)Kabh#|b3cE+BA{uG(>6(9gclIEbNEGLl zW6w%#=KXGug1KIYmR;M98$*_fLo|}-vf6%Mb1*wRUku*Oits7!R|j{c3y1@E3sY>& zwMBfd{PnmQZhXH6@kgqSv3}GkY*OL({fNYdFvY<(K&>>{N8@tEhW&FD=D5om6KUW) z=X1rJG;gn=V|voW%fK2+kC&L z+CSPom$akO8L$U^zx5eDrrnF%P>5jg6NzCl-0JEdei^YQ->2a?=6CT0g=R-^@@b0E zK`72_H##E;X|xFB7eS>cEAs>Sr~(BKmLpK*g=fE={v;>!g?+SiWZts|oAcIV>u+Lr ztT?{uFaP)Q4tr$v{=H4Tbg64+&B7PH{{YsHV#{h)w{uPqbt%#H-;QE;@#`O(w9i+6 z+nJ7@x$Zn@=&4QIq87>jz02#`{s zfTB|Esj!Vpw;u#Ie$tEAfAx;DsQjhFo5`BnmcQImY__?>oW(*-S@u_xW?}cXb@tAb z*WGx>`|mxN|9kIyTLS<5`yYkx|ERBbs~A$5B94|)w;VE8rf>9j{`qg+X`QwyA!f_) zxzD-Eqw3hjau$Xk)x>1(r?Fn=B7wyxiYFA|j%V-$l@tAs)ZE###*((ayGCE1pQ;a9 z&CNeNY2*DPwl-{%(v;JtQ?u^I_AJM&>FwR@9P<^E?=!MHrGI4CN_g&K@7z@~{j#gt zN>*)SO-{8LyT)+%{My}#y)d)BN(U94R3>hrhOpw|e3-$0@K479U970>Tih#wz0%J@ zEjBX&)qodl_r_<@^9=r;6|tYUNhLQe85^F%?$%rlX;_7BELNB37A=ejD>a^Ro);)n z#7R$43S_cK+H-`gpqxAvbL&JO(TuLPn+7=MXd4guUsMzN!p6sH-VG+QH9y*`=8%So z6!mG{TNt!~STHchvRL_S_)l?Fr%*aVMnV$ZN?^Oax5d8~|LpO0l?J3*egAq>>tG%V z;+J9{xl=(p6Fhb9ZZ7rH-9*hvDuA0ezEztf?Js$#XUBT?I;1 z!%g*#XTn<=F{iXja6SEXTuue>fJx+j{1$EB>(y;di5L^3HNU;~ztbBmR@3NXDfaW4 z@Z;DC#=IrhJHm%UVkw&!5Z$1R+mGu`7^gsqh*u%c(xO&{zv~6{p!+|}{7$kOeUrY| zdB?DCrJ8Gan=U1{H#fQ8o?6Shx;HC0tzr0BibLNa5HYH_L;deN*p=@I&V=u(P6aC- zaJB8x7JcsASc(~FKjiwl2T6kk`~!%R<)6SGzasS9(5LE7$l9L(kD%XjNnIk)cv=xC zFI3BdP~YDXgXVjGLdR##oGNM()~&t=onNIOKK;thaQem^K?PjN9US&J)PDWa^=#R* zqpI5cbtxT$emDHudCwndLHQcR!w)PW{gJGrKOL!8hJv^&KBQ+I7XlMC6`t8sczpKPx#Gu(1y2jIJwyI0|Io~Ib9~6f_6E2yo_e3Y%ia9S z*^7D5E#B|@;-I?XyN6Gkn%B;PH9S*~39HFpG-pWJThUp5Ouhmw|9H*+-skM(b)*dZ_GIeN$vIz#Jzg++w}gufpZhWnF`F+?0r;K zu{Vl1Cv^L{Pk*MLAZjC)$>7Cbp%%XtC5Dsg>w$p}_o~^*I;%zVs)sB4+0{egK0>sR z?S9d@<_LNnVTBex1>|35qAt(Bc- z`e0M}1={D6k4WGXbZk}lk340-R6St=Z-r*hYw~jn}e%w6k@!oA0e%C|W&yH6> zd*+H+un`?u(3$EwBkIXo1Qv*H)Bm-y(`XnE$Y40GF8+pLZ2V-av+7>J-`E(Ux0h(~ zpxsuk@42_hsIKi`c4Lf;*pRL_s&7d+c!BAtXF-o5?>iR)*(;~^g}-Xr!j4#ui(u!n zCeV;$8J9UZcy0GNWX4DR_+r9b5+7ucHy2WdF{BEi)jm2isl7*o%1XFOWK&3A{oXmF z7L`+LEmCU?pMyPvOI$l3#a7t$Xs)0jpV>RoYc70`r3LO3a4xX-N~uZH2CeSm&zuSr zbfM<+i=@dj%M}w#?;4JfhRkp~QAkwI>M^eBO1rI7xX@vNlRHZX>GOCr2*J|feDI=h`4jyK&&GGuJNRPmjM#phWy>ch;BAv7 zWp+DGiItto!BBmc(Qxy)ys?>nJq(N9zPtP@XXTZ7zf`c}VYpFp(uVei*0-=Ht%rB) zSG(>?{;bZ~)8X~BNd8SXx!?9uPOq+F-D@=*a4SUG{&MahLyfxBT^oV=FK7ixAY2k? z>vD=ZqNAlsKl=&L)r@B?aJ^{J>bEE@)_r{}t46N5pR*c0tsjAIDghDa0_-tjsKK>l!xdV{eKtA z#(OGvYoaC;7xq*pv~q&$((`}fw9>`AF5UHfj1PBRwrZxhI%qm@Rf_U>Rul89Q!ssQ%kVxv9(pFv z&3=mN)?gQx>@84aYcZ@ZozsL0Dk`>tvMrX63D}Ynp$w9O${6TxanSCBS(L4pSBh4I zaV}o%uYEN#Q90APU{+M*C6<6yLDfczvWJ!59MEfi=8){!C833&mpdWCouEf79Y!;} z-^66iIpv^dUXK9%0-b0une<#~3Pi#Y@@_(og&$7ggHKO0tQt9g*XL{+SVyDI1|CX&~UsbG@i z0kF~NGT2=s*OxF(-W$PI7UwboIC%|A%<2FKiL!vP>V5>bFUdX7zNUSSlOc>*8OwnN z3AT#aCG3w3k%pL~>o4P(R+mBDYdSd5sCNW&b|n*rjB77wZmsh%Z(z|PBY@AAwE|u* zV7tk~z*NCW@qCejp%rgp4%v^;yZ z8@H-tPtc%=LBzWBgW;jNxzJ(i(BFL|RU7dcIKsPf#S+dRRn$1H8B(>IEO<07hInhN z`0=_r4H!`5ojmXpwL9QGK=P)_B`8%#$EPE_m4f7dA`FJJ2$*s{g^>7{xSIxaU%gTt1oxFD}^l~UohH=#@;R`|wz8IblS zj5iU<4#&X8QV-W1#>6~-nv6FwKVAXl02M5sS@Y>req46yB=2M)DjO6=KmH+&JMp_W zOLWD%7MIb3lgHE>*_bVM6jL-3(9QJ#B&~w|3nD1T0#KGHr3m<>CI)nP2f`k7>q?X& z#!k$(@-IzN*}NeDTF8Ei)x*Rji(L)%8U11;|8^cba#?p)&8x&os0!QE<)?%aqA1Pc z5EX%WweA(S+Y-$mNx32qs)^dPP$l0COUiaqXLv@pp6 zEo{%+X@NHPb>%=MLuNr9NMu|t5sjB&l$Ic(rH#n>(tGKqxG{tKzo2m*3PsTptY|FR z8if#nCVKG=!Q;vd7}Ts#?C~dOa$8J8;24gz zW+KALhA09kj~PV1G+=4db+{wBBCNWK`*~TYf9vC*u>O<&gzdf6?I*i>J7@QQTlNiq z{u$YB^5)>1JL&yrUd}snx;L0gTIC}(`c6;nLMfNk07jR;Xb!$t)h{*VW@H3Rri4oW zayKF^ub{PQe>V%7NlbmIoJ>^yo7X(}Un*tGHcY4~0xlGY7iiT1$19E?SesE*w*3B7 zhv6wtFU?PJS6|RHWQ)}pPFjZRI_=U#NU6Z)5qJHv>!C{r2HU@}Nb=I0BJ%n;^BcR) zjXfMg_oGW&S3$IiKZ!gyjVq>ZH>;hI0m6T*j&R6HDR$P>uGI8#W{5SZPmBnwADN7F z90bAFS42fRTMmr^uRPqAQ#;{{`Q4j#xt9%#v>0pu#RS|&w^Y|c7XTkfPhYPD){MYP z=f6Sqnh~jN*sA}7y|;{ttLfH77tpx7Yd7xh-e_>w;7-scNN@=*4UIcAZb1ViA-KB) z2#^2)0)&u+5JCu$)9<&>-TS?JzdyeFczfLYNFEtt6QxxFBl*Yake>8I2a)4`qK;}P(d_=MY?6>gMinmW|Hwz@U`&8*U!@t=5fmf%bcv3(kp}*e*i6_rXU@hJ;(j) zVopTY(-^tCTt;RwVuF~Ts{Jt?Xq3aFdU1qtvOjfm{HYYh=!u$KF*rg^zeDxP=gnnp zN&So&RX!^fq)*3HACchzPq%QMQLz@Qyc;m$aoLry?@=@fzjjXxp;b$G$DxuYswVESF$=Kb-rW!?_hCv@CB ztk*)PuTroL$g{0~@deR-{nD!>0Er>JVUu`62ldMek^PKMZ4EIjaUraiWo?Oj36;9R z)D2ldX7+y+h$EFWds-rP<`-9I;hyb+UB8dtHS3r!TN`-Vbu1$u%@f^iT6vm}%OC4w z(tYLTsrd)U+m*7wCKb|QI+n>aIjI3Rf=GE8V&NABvK7aI4Llk~?fYYVb;HWSxDQmJ z#pV5knI_au(zs0R%djL~YFaS@v~eR5*NH@rZfuQte<0PyuKT7f3Z=r+jCT5AExxKO z%z^!Q6Lcpk3I;gEyS{&jqg7)C3FCoD~}0`tZ=2^2-_I3NdHwj^a;hzeee{da7A zcP;Ws1hMSz+GJ8Kws=-{R3we;cn~2D0HMwVm(=z>nThuxJ_JXitLob?}9 z!K9XOR@_NaN74_YFrRW!dHBW757EuQAQMieMg{AE+9%+{7pHC=_y9p17vv=Ay>rnr zU3jOccA=?IAP>Q8-?C@bb0v47Eh{>3Y%L3pF!m-WJ&i=l%nBnZiBxpjC2Pfpvjayq z+mxIIz+s9;R3t&5^tdl&xQKA|;$k>ZziIw5c7Rp_qamM1fk;F89{^BJ7A4D>TzoS| zZ579eC6;64*GN!KwS`=#;ZI6MPSIH@33;voj|yHSsSOp7_)(%;**m$221C!#v7z`m z{py&dDHwI=I^eR8&S>GPT?chmNuo^-(;8!i@HpH!5-o*ehy`clj5?Xc?vn_F*dWXJ zW8BNHw{u3^FXNVi;;fqk&~h8RFH7kO_+HLZXG})RY857L3Zudlu>t6M!E#7IAQ>J{ z;YcTn9gz+H5wS<~jA%H;VHkih!nLZ1Z!0?(DNh?_XL^1Ztn5>A(fB64lhPc;XmqXQ zv}o%?#EaKG*~7@}6KmU>du>WLy&&-Ztf@jjV^njx+Ktf`n`)_TEwG=?@sZ~>BX+b8 z6nOUZg^0ILQXdGA*9c-0@6kNN)h&=qBZEV5Hwy5g2RPW+*)+X0%lpNFWvORIMBcPj zLJovdG4)x35TwT-IoNr2iq2J?kW+xaCy5zGdqUus+)-|r4eQC!s9MbFO<+_nWtm-L z6D<(M9x(_u)5PLX?v?>2$?A2a3|L~T3JJ;Rot6xQoJHR(tpE&N35F<=06>WQa>R*QQ0DL+>mh1nuY_81+B)wc!6j(frcfx#jT1O1Uv9jS;#P1f;+RM?M+Qiywom_+dERKvt37Z=|h?cE>N_&O~VjmD2PrfIL2OBxpyiKtu zMQ-eX^~7*y{VE>Cu!$C$*gtgUrt9`V7l^L|h4>ko3h+Vbcpt)pXCOnOkK0Q*z4^oZ zWYmEv1ELEl*Kza`Ne{gK#6eLvJh7Z3%4x1OV`LI{0oVjj6OG1XNfa{7=2~0loQwsD z^h^_fs&<5snSDB@TSY6f0c2e3gfv^_lPH6dbX!?y9-Y-YRFLS$kCOvpvAA;y%5xmH zrrH?i2^G%)TZkrA`2)>hBQy>wS1kz*g_L_Hv``AM(P^Gq8DH>;1vJ!m38va56QD9I z2Ti_;r(%S}as~G1Q$1a)6^oT)9~K>^8&TD-VpEOB9YsP*w3l&$Vql#txc=Yq7#9s8 zMP$GPo+fLS(pipf$~=?@)H4$yewIG`N)tR!RHSYk)SduKE$rCpR| zOM(eS3LXhrvI>cORz5>*Ol^%A1!7!D$uwLWkgk!!vu7IP0%KwhLNU=soq33`gD7^{ z(8-l5*w9I$qmyt{(9u!LFdW=yaZnDEecZ{6j7Ze*?X(!|b^agVH)T7zE=Xz5VJRac z6SbxB2XIVhWIoLNN!d(9ijjcDo}Nv&fxhp$NGCQ_cxBZurGv%>w}8`jk*NluMQ!@f z3G`_0hE+_nFS_b2W>LAZvKm}c0x^u+)5uZu&IaSV(=~GfmnHUw%8bH{^teG7 zarB@#DZHtSO#K%vTp*E1B&`Q0g}f2Jn96Z9oxKBqJ|xF7K2^X2qbN48l;iTg@%fH z#egJPbR=j*x3bZ(IeZQo2WTl#^Eu~=TOm_M)KF_r#T?7TGs7GD8I9xqpQlk0IS z!RTgY)Da|$J1Uei&ksM%CRdRwUnld-To3+Tn4WieQ8UG4oxZ?_6}$F9%{*i535%Cl z(*xCFzyTVFMfRq!V8aK#h6S-YU3`z!7E2PNWXOo4t92ZP+K_TO_QxrEfN*l{(RE_t z#YZltWXn#AS5`fcrdPHVc$LFUK%l+zFx>$kr3!}*7`0z|yKe2s5)J)|jK)Dz3oL^Z zg9=g1ksm9bte=4+SZk53GZ$N-xFH*i>*4PJyNj_U283vKB%+1bvI4Sp(W(rrA{~-> zE2G0_S$7}IS}2!mMkTJ2iBSB2z;t4uly->?$4F}@4>WWt{7RNx-{&32gzn`yR#*}^ z%Y1$ft(FC(Ny?DPn55sWPrKA5Oz7~TT`q(HT~dn_($irAIvAq@S&Iw+z$1b3@%d;D z6vXO5Gblh*gALVfm_>)GTGDQH~J(kdVX4=d=jY z#T3=Cm`UM`Ntv1ipv4z>KKYQlQiD3lOru-jilx{O&Yi>H2qBAetw(c!J?(<;;kKtI zGP0?2W7B#p>$%xC#EMEKEWeSotVp7(!tMYA!%E9ro|P+)%ej6hbVjE^u;b3_XOx!( z^jH~LiTr@P6YDH7u`iy)@lq*BBXk+P)T)l>z{;20<{AAP6&&;gf{ICOKuLImXE``x zg11f+lm$Szyp$)0i9$qay9L}K_^dD`mdRWWF$dC^!sJO*Bn3QyWc;uadx}$)IGkuG ztyK9Mms~eYj4)(_H)c>R{Pky_{ORj;sfp`oDUGAvp4`jVJ@+Kx8iSwgzg>o__HIXg z#6Rl654e@KL=do4!{~WB2vuC`k)Qm|GHMN#XIZhGDTtlNBc~!M2(#Eo)||P-VsbjL zC>q5m$sqldQtBtLiIfnXLeVLuthm_X@OrALcr-N#kq(LA?^cox&<1NOy4Zeb1&>8L8n;lbs zu(~Jim?moGw?7`A6x~t0=M1YN*pvOG*RrVkdh#Tyfm!1wC;T=eHxgnO`tUOgK79n35(M#{7QiS5SFibxu zJSO6l9vtL*)_+Y5%@>)b#b}FO-!hjx2Vp5YWGEjvqUUYj%1t56h3RX`Z@hw_%+fl) zicufP5;-YTY|YY=eakK-oSq$rmG!_c!t^=klB#l?b(6bHsWltDAL;5$gux;TNuWaH z?GA}#l&Ro%OkJ!`L4w#8Evu-|E_TuNaj=@*L8Q@XR30VqSzSF*jCQn~cLhq_Ed)7x zC4uoB6QZ2IOz;}xj-vB-V_fBrjyw#S9pZ1Vd6hFek|ebUh0}9gz<9+6OpVZSN&uF! z%|pG<9HhbQTyaV{T`imrH&X0Sos>5QzI7-uqCYpZX3W!{y5uz?NU>CKelw<)bn>hC z(_QYpNOdhy?Hg2tQ4egx8oa3ZFb>5ImJ`Yj(6feyBOa7?7jFd*g;B;LV33WBjamhpyq0lQU;F< z&FviB+}#v({X_knLu_2!oc;nqBPAoFp`;O{qZ4#eky3H`|D65|0;D+T06Ktyh9VNA zXc(kue?|d101YKTL;F{E|KkM>1B8x=g(?#yK?BfGUUER#s0#m40}UO66hubBDy(ei zPcCW%XA@CzaEz%02RJSL1%|4Hj`4RaRC{#Le}Ivq%FqE2COQ@x=Kuaje}Q3=36rym zC>yf*Q-C32DlrbCM(smi|GWhVP(bLU7^HwAaAUy4z6_B3t&ji8BKjI^nj367o*G1x zP0dZt^*vRedQaorbd-y*hGJoP0RVwkGzOXde{Tl>OcjLcN&iEP&XW*`Zx}z?k!&7k z7RD!3TB_aclGhl?eg6I_eQ~Sljtjf1^!LE{YVH~FNr0pPlpM&d#6ps%ghE0`y`U~! z;9n^$THJ~S2lf7cBm!zTYR}9UPq5%LuZ*@M-t3=$;4t7{agb(sQI*^p4EhD;Fb^S> zTcH!vU*kG`${6G}xz;h!sGBWsl+jyuZQ@#MpJ=--&5#c~ z3tD61x5Rq&SJvDAwA`t+F4auA%_-C7H$9_5-<8a1NVhZH6;FimS!qVON%ddF!ksQv z(yMyO(DAd;A2Pe&JjZ2PldGB^wo{@UwNN?<(ar*gf}h%F#)fFCXSn z8>oJLydlz3OKZ0BaFD$1DFvGY=%1&%_V6?LKh9gvJ6b(icwOLia1I>u{sYWEiZFveQh7Rf zFV|6hdt=E|hgi3e{LY^i5zS~C4HQ3VHGanwH=kHdtT^xWQOh{L7b6z=k1+orq`iEd zU3S(YW4H9%HSC=wb8V9wa}A3O-yo1!sdt@NPI&e4_T)1Wvvg){&QIg~%|&9Fe;>PR zq55iespfX|%Iyh}E!|$@+ldoR!XqU>HK=f|@rlrgYr1szTbm4D+uh{rT+1i?Xh#(P z(8qriVF=`ZH{L9*dvK%Z{l#JC^&_)6c^1MWdqDiS%;XQS0yay&(23Zd_h7Ee4V4u{ zJEYtFN1T5U&ehy8_dG5YOyFy?n{f*lkNWxIuP;S%Ga6W_@@pupgYKCJ%NE|hwQ#=d z0xopz{{iD4MQ$i7|Jum2mN2_~@}DkY^X7_mPsbHCF_6yylC`Sa?qC`QdG@Om@c+J$^ zJB)oK{}q&Z(In_*FZcG}?K9vXjDp4w`cG)Pw0{9dyjnGWOT!ee&IUf)3oN|xU=Fg3 z$i`UU`iCxKcKS$zM}D^meX&j$6Me;dnoDUY*5_dw@J@09E0c5>7GZKW&DV@ApY`7x zOT9QW-%RMg+@G^8V9L*#INUmaP3;_g)&ig%zx-IW8`!pY*D!Mi>~jD2mZI*>~a1(@#)l#VS*H!MBUOg1auuVG6^Qd)7lc{~z-ltnwqM_h;?|aegat~_4+W6-Q zi%!k(ap*{IEBmqVH=2vbxncQQD(1p~-Vm-5fJ=s}#Ge9wOQqU+f9B`uc!P*Jg)ED4U;z(}lkH=H$+40f8!~_ak4&O9;EpTgjf}Jcn z&N`}En;URgb}?g+#>To#Djr{;4@Q~&a_LnFO(ETH`dTv>K2+Op4i#-YS~GdGV!1U% ze}25WE}i)_a#}+Bm#)ZXJ$U&(d13??8261DO6i+h~^RPhhdLoptHYusOS1U-|aurQ9qg9E}^oz`mSNZ zOD;C+A206OX~*sI42#7Nl*--en11q2VfyJ@NHhGc;R^msy}Bf%%k^y1Nx}f6jIH9< z6?!>5)hDF8d5AZT@#!CCRPThEUyvOP^o5Sd|NJvLn?q)`<6NBk+ zKuCwjJNsFwX=1ua(wf3}w^TTJp7YAfb5YtvwEd|%f1#sR98zglC#^;F3V?C6&`f7~B`e~u8$KrTPak%7_ zH1TQ_mx-#lHIHObD#AltEJIQtISG-xN)*Ihrsvs7KJ53*I0s9vtX@)pyVfK9JEEUf zU8>oWu&*Fc;-u^Wmc+<|@fO_e&bh)v0oRo3v9Dz z1^jn%{x9Iah`sJX4 zzo4PcZwM~(Xac?0xF-nVnpmoFg zp2Q5l%R}cltJ~~n{AR8|XUxVlRA5>WM@drm!~Qwag#}J@9orGU`a4&E+Oztb@wu^p z-CN;rvMa|G2T_}Lr@?hg%6E!aD(o=S;j76X;>2S+=Jy&m+zmG`Dj)0Th{F_vFg-NX z^s7T*JmzgCKN1#a1$>yr_0DZ|hLaiECZz^*XFocZnsx8onDH^pmtv7JrNmwsTN7G| zp<)aG!-Nu=7ccU|dAOd07K2&2^I{7WpDA9%^{OgbY%a&;G3^ol0kZ21@Gz#*qAY$| z#R*(mzPJynjs!1BFed1t6D6BmN29!(%ud_CJS$FCN7o{y)J(k9_UWqU1D0GH2pb*P zZSrx8>vd?joKjmv)k{rwx@CCy0N6Qxp<6|cUujHbFG zO<^QG*I^uwNg{VJR61{37ogAX@}FdP{n$nDL)V%O&s`}L+!57OtZCpSRcGo>p^bwtbMR=K*=o?);9U zu)y!9RZ5E_*0D#{2SHX4HO=sF!v$JX$_Wu>Es;@!jsosWP)@BWEkDg2-W*<02VG|+ zzJvnbm!PV|Y6+BG6ANnm05~cn=zdw9KDL{l9nTte#2%$zi$=;q{K!M8`!no4TJT%b ztr3lTnh`_sr!vcAEjeSG4X-5)@M6k?*eaiDtsokRWRY3h-gS|=8vAwI%_UmsMC6cs z5h6So>fwK1eR63KrGJM&9g8N1w?Wh15;01vC{-g-XOQ9dDLe-mjiI&Gr5t!g3G=Yz zX|hc@#`F!VrRN<7!E*e?22bH4j+A0HZ>xHJuamc1vmCO`DS0wnsL(;vZ)%>P)oLfJ z^#ls$RLW(ae^O#mNip~$(&6*eJ3pG6V+k@1RaVxifEj=77vrKeWmqOsQ5Tt_@r25a zC~wp$t}|M7vC#PdHru?A!0xxiRc0=CDzCt~A8uOYDLakVe2yV{DFsScP~^v|55*A- z8LyyQWLit8-Ip8|mPHS$=gxsjM>XIQ1iqaufz=z)($*>!%)GOP-8tTG4EjW?FBbB@-Kt+RuUUrpZ7LWfIm~Fd zYooKA#fC8_>b|FxDBIKA^Uz1+UGY41kSE(%MZSdp(nu9~{s(w=x5S{vf)R%!QRb-V zQqKu3w-6)w@LhYeWAZjDp4D<5ui^IlxYHoRYlX->`nrayLU#!rS9I?Rop;#$VC z$;7hhCa)roXOcKZ7ZT?j66aEK1*I?|;#wIy?!!17#=_f3m=8y$-teX<<-#5YMr{i5 z<4F%fxV|NtGv(iK_|i;WOVVs0saV$-*t@n-Thk8-gXyDX`!M$Ny_c1wjXWg+5s5_l zW9A#2zg)AV%l2U}BS_uNGtcDAa*{PtByv>~YnU5ldTY5>n31SmWeO{1F52tP%%XBC z;2B2a`;l5jCHbYvAq6FQvMvSxuNi?RrONW>6>r|{ob}J*_Ml=`KPK`zJ`fK}R&ERv z$N|~taPfOcx|dCDrqxmJ4z6PebvqSYH9nHCn|$xWndpV{b%8HA!;-0(ZETub!krO3 z?cj~erv0(nizWxz+G@?^YT-Y_JT)-7v1T~&6O&<=hHd)6%SD0)#~+ptrKH)AQWo#k zjN^_|9)Yyh9@H)2y9w5fUbF@XmV~kI`zA1CMFi;pvQ_Z6l^{_AM#o_N(Q%6LVm4ry zo2dHI+6%Lq7dx^^AYi2``+@#w2A7TDJBPW$N$JzR#$`U(0^+nSF<3z}cg^(WY6;ei zfDNtT9aFfEgRJ_F$t2A*G$;3&vFlKt`84`mE-?#vyw;Ac=z|AUUL?x|HRf|rSs=9v zN$Q);t=jOa=z!$JQP4)z_3Dx8%2kbCZkG-DFdrp2AK`h@FOttdAkSP5E@?8DAt z%z@QF2P>qjq*bXVQM!&LlRb+eusq;cNFLn5T0_&ZsyNFM7@AAtzOqu>vsC6-j5jZ0 zNIxWhrXw0mzA1#-pK+I8a;b;UhGE7XuQpgrh*}p)*ap&rUW%Fy;wpCNg`0LDT<)6O zg!UTpiTr0_xlI=18oWvvF5>LnI2*$ioLagH+VhW(-cRMuVn3WLoa?V5zhUuU^KDxL z@0ciUHE4t?YuW`QasTB0a2iv~6`!L#px=narI}!54NZTJo7|ykWF4eo(ycSBZ%-c^ zIUR&1;0{pgPV1sAVDSmTJ2S^L&h&s12L(4tvM$NF-wk|pmb?skC&GCW0lmG6BBjQl zg`l@IK{gCgT&*m#&(#dKs+kQl5k}spHAX5cg@JyVY#7b`+izZOymzjt^`)j6hXX&L zHxhi47f;fpU92 zQRq7cY1YekI;t&IZ;EFKlbMA&ON?dZCB$|&ipEQ%8o!Po@{$YK%Uk&rkb4H9{Q=fC zP2IpOBHsEBG%UPJ02KCwBTP;bl;+QNa#5?8m}(o@v%?|e}ktlXQ#>7#Id5^tWHxstFJz?e1Q{r z66x)=$YR&s@IJloJD+!FObr0f(`C6LKL(?#qHPXYsG@v?GN2 z2__;NXmNfcG&=BT#|IjmS=1RmWO=hC&k)GFMUY*gg6Utrug%)FbkBo{v ziOdQ3>_+;-Yfaxq6xQr+b|amCH+@6f5L9?z>(98>Q+YVeKq%j}R{HW=sSzc1&?L`R zBcZKt3HzWIW~t2{+ld9b4b~_R+PZMs4^pAPMJnB z!TKAY%Bq0Fb(*3Obtt6(_7B`Iw=EW5KQS~KKYDDBoDWR;PFjJ8me1>EQH!>m+~!e- zza=v4YG_`x+;XuQfu+XKunQkg#eS=r8_*uUKmHiE<(F%&I+UuJTjM<+<>qG;IqdyH zS@l`Fz$VsZt4N1zMS6S}>++Yyrg$fBT z+IM|6k+ieSYWry3>@K4aPVsYe1M=1*$3 zRVs!xOI5t<0@(E-&KDzR<+oZ4{4ZIope22cQ+bvW*p9&u6$nqDSBRH|P z!Mn-h4-RgN(953GW1T)-Y*u5~;{F44%ZxW9b-BZpmlXT7q~4IAHBV{S6=**eDM6x3 zGK;k}Mh#Sgvr%KHgr~av!%rh0l{b0BXNikn)i1~{P&TeomP5m<0Q4#i-vDLXxdf?5cj^{1pHhKamm9ava`bTmUGtVJr= zu6QX`ro@cQtBoIw#S-Q)2)#e(@Jbu8(QtW4pP|$6_QJiAqQ_(RnRCo(QkBT=6Iugq zM#DY!dyTIe%p|8!=@vG%p@bR3H)HvBr0UXV=A@r;mx$6trb1+|B?FhyXMCUaNnsrF zZ?um1b!Kn2(gsYpx@ZKLmMzvj`&Aoj8~^iCi|&vt76S~^N&Z#cDyclT0xZdq80o*t zVts6aHKkQjOD2}A3))jK5P9!Xs=mrv3x5$HX@*~^b{3d_Rj69z(@aZ7NhWS-O6p3( z^IN*Z+2X@g5j5FkIV!gpzts`f6yg9bR1bZdBVG&&+;Oyt6UM$}A3d=kllZ7V3jSsD z)%9zV-*E<4+aqvGHz1o^5yJ5)v2d{Qk%eSOK44f~`-3!MuB^9n9FAt?$t&nNOe_Hf@+n8Y zTR%`k>qds|W8Ae=OsR{-3BHg&Pr~?p>Y^K;HsUMdr#||7Xex6B*Bazf6FW5L;(_jj z^OGtAv~8q|XlAeR8*=tbFthk8)G0Wb`J6EWbK|V<-H7hu+4=K23-W-j`o*iE`2@)J!#M}4d8KSd zM`apgY@=>*Eok_ncfXporrTV=(~O3E+Gr!s$(&S~aE-G;xk|<}ncERd3}P3Xw1A{P_6;V`yKtu0*U0qVd{sg$v!iVlO6yhxxA zscmu^_Zl^h7%(^id_75m8*u2@F3~P;z>@BF)9jq@O6FM;F6Na_=3Mxf_}C-uC9JXD`RemZ{Ct z7@_GZ)BZh0l4HcF-qVt~Z~p-I8dyhTGm&0NTG9#Y!%|p%$RGGQZ)z)QQBhY*>->Mq z)$V@DMgGuFsoVV~=+0#19M*stMv`4(lAn{;+wYPFhP`@4uB?25TT`~h*@%UE7xX|& zLPd!wnPy2`Kt2;XnWN>MBV6Zh8!lYr=Mca!rO@O<`F<_d(Wq!is@SN<)a$iL9Ih>; z2VtHbdrJ(d442WHbcW|Tvrk3$VWqLN{W|uPddPFH4dx)_7Iz`h^Jd*vI7rHSx8}>m z5L||zrCI8Q5qW<^!BHJnjzF>Vr3sCzEBeIK2L8UXnFi$OLL*bs<+G3v?E!%7aS0)r zf3NWqZW)h`ir}*(-wmT=@Lios+or)vV~*}?~ zB!YAr)_WYYSoLecnG{k#bnunQ_-a~(?DnoJOV&kJzUSFZ zEG0X1+J4#gT&Lx)JKVOG_ctyd@--od1$sobWDG=71Dx+}Vn>U;%4VU5 zT^T=%{G1-T_Ev-JBctCd%u-J_B!iTLRKJ^Cb}2-FsR^W&upG*0Z(g8Ua4f;Qh~W^Nl@2`o>K)om+D%Yjh;o$%_wDbBZR<_+4~JPQ zdD$zh)}1`WjgD>&TEi_0)jPWCL-_d#Eqeps@%xd|omEF(X(@SYB@4cyPNvDSHZ4;* z_>$2p$;VwPo25VTnfN=E#&)N-3t-SvBmW~1sbiN;UasNDh%6%7ykbJE%QkcYc`8sU z#&hz9AEO}o%A9@1y?$(s@xaO1^ z2HTU^Qs>HjcWTX0;?m7cqi=HBMR`ea)+#7&av5c9VGQwaw&So>fhe=R-9sJg-h@PK zLNY>~jdI+>R}zG>M7gIOcx~g^G$nL(Dh_{;`KPlz3{6?c^|Vsz=T3$k%V-N~6tqu= zQiOM!Ny6bBuQeH0f8T(6jUp(V#^sq?@8~jYrz5ifG@}U|A)IeYp zbJ{Fc5@7&S&+bvX0=H`pt%fC-LlF$0Yau}@B88ONNfE4u9f6e=FA|@qRgMJ(ZHjS= znR9gclN`;)%Eptas+>uw-c#D7%g>dBpC2kDCu#Iw!&HPd`%G@f52deeFQN>C&gv@4md+5?8 z+(ki;b&-X>rPrz?H-2~1d|xLo1)looXX9?_)hp8w_=;i~{f$&?H@YNV%-DL>JiB1! zaKuC-6m@zz*vM3JL!+M*v0H)6K3469Q+2;~CNARebspC;K5O2-pQ0Gm{;hSM;Vq0VX!GjC?|IwbelV-k&(rsf*#^rRor1C2$o@7p&l<(646XBWc;}!Jj2f8 zs5DzqDAf_Gqoh2%^C&J;Dh6*94Fk`L|DGH>RC(*<*|%RaJr9ek7jL-rrWpBSt#qbC zh94#gJ4j61LFYw%VVNDc?euZn85jBQP3{jxvTSHUaf_S_(&Vs~E}xQ!)7a(qUszTV zhx#ncxbc_p^x@$Ib5jqvU+vmb0K(~;ulLrx(81wvOr}Th1-#>r`-VFB>c{98jRZ8) zD*6lA+Fk;|7=EqJmK5ex(Y=^zl_OR2B+Qcp9}G$f)!(Hna9nJV_B1l{JNS7B36Z;~ zzs5R!sh7%|yR1QQ@zJtOYND;PJYm1ksExOHX3jt89o?iKi;ZWW>g(qSMtc{zTXSf| z)(f$@goAR(bz756y-0Bp8le>vZY!vL4Ee>cx6g4mE7;0-zsX2~O@fCL_a~O3qrt7S z?L(?g(9`dLSpN|^2nw^Ey;Us;eG5G^>*kV7u9*$2)N)2diFwhVlzHj(x88h~(*T{J zbnpFpfwsE0nWRgPzv>maRNdBDTQtjidh$ZTMLV&!;x0n@B+R<}yrfc^1JU?lM4QZ} zQ7ck4ku|~U;n^@hzI2Hq5iD{dx|TTizADv3NBG{x310&v1L;&Kzq9@;S^}Q}p7P-} zdkC<%*gO>n;wXxsLS68=%zov;(?;)tF+_T|snZ%548_U8bLy|YFe)HKb`Pdg+se#6 z3AH=#op^6@@I%|Mz0`-Hb{+3QO9ATOI7>2`g|FB}ed8G^zc<-l)zk`a#R}}varH=C zAa`v7Oq1+-gJl=-R<5%_cNn0r8gowV3BuJcV8nAAzo`-tZfhj?DC4fiv7Oy@ShB+q zkE1t^RPCa#;15;ih#a2VwGvlx;e19-5{;)c_Jh_uz&Q*#iFg}EVfFqq?OA;^h@7Q) z2EJK5SySI+@9$iNGR`)Zy#a5nay(?#H#(H`4(1r)8mRvrAErX|iDo=O`U^J)&I*pG z!y}#QevUUwv@#JSt|KP8$hiT{%uD$5-%9mDzTY(*;eI;;9;b1pbX&X)Kh^6AI7O(c zih&o-=Q-}VMYx|_1yQcCZVe)+6+sSd@{ZKV@n!Pa86Uz`nMC5*P%r7~Cb#2`?l}os zwz>(@-`7PH=(muZgg8nVLn zDRd7R2-ft}^?*AHJgYxDw+FxB^|M4xR#D!#QjXTcjO>C9y z4Nrm0Pm@4xBgDWKbH2rCCS|{tW^ADU4(YS_rYqGv5lP9eg=AVM?QM;UXpAaQ3kWdu z=abMI3@I2 zZ9dPHHXrQ)ruJ#P4^Q6BbKd04G9H!ucv!hlcf;>>GE?kh?>JLS5>iRiQnI+PfXLol z7+!mF0ylkjl}%v(!#WPjOetEED%ZGUIVB}GJiXW;Gk%m`PW>gCVdYXQ-qCOd_&Z@H z{)o@Olj(d4Mc>@cnr*I#;{m<-b_dAe9a23@YB}8zh4@iHV%Yr32)>&Uu9Fq@_HPzTr_Y zPI&~?T=Rs*+?8=}?BOB9JVdva?2#5sCvpbmV&~dNM!@P;7}Q_(c*iK)ex0o={;l56 z%|MZMCiC8;9ZUbzEcHVLj`rbq>FJt6nm-Nng{F*fIrOlmrdH^x>eDuzh|?Yq>g`^c z&H)YOeGjYh;hht}9)87pjL^ z>ahgsJ5ons*e)<+ycE!gjvAHUUL4S*|nBlk zyz*|9?B3?w@20uXFUWAJmjvCWoI9mW(O9XOP>K=Lb$19d57~I0?<1dd zE&Q_Xegi*mD-Iy_UfIq$JD~JYdaY}&f5bhIYH`Knxf$(So+p!~x+NGtWlT8Tm#HYCENUr-0E4~trEJbynDG3}mEn5_lWyEq? z-!ST3NSJ!YHsP3BhuT!gWRV|8o?4!$0=jd+OIV+(PSyeip1b%PVN{Uyf!lwvL$rny zDMpti_C54V`_=-#KQ8+;02k-RfV4?;Jx>b38aypwJdUi2d?))*S7X+*-t8x@P^gOA zQQ=%7^-qNn>7P*bA#@mssUGaiC?R}Y$TY3dd)!6M7_5cpQD*!N@oP>H?f{KZ-5Z~0 zIuk=Di65@(pWr&z3brhB^E!xR4QPwTA7Y7?_g-sM_8jp?P)kyeta>F=zMD?(Wv<(V z>4zS-){%IMFwp6J%awgauO_8Dj_*qG@Z+*q83424oRt?pMoc};{92wErC87;{vgHX z1qu5b`<#oPCU5oFzGTGRwqU(iQ_{<>=~%tb5H;vbKXAy~urpm&)!hrkBA<|YN#YD& zgI)Zvbo}myB|X(AZRbFEmh=bMs74&Cu%uIszkI(bH%gzNf~UMyji8UmyI&m9lIS-T zBuqUOYH4Bd=_LC|U8391x6&7dZKn2l&(L<}50C&!F25>Pd(lE9aeqbL=%+^grP5$}=Z@g9O#Ed7O~V!<{#kwx%E9+zSMP*K$yVe+~>F^tJS(+rkL!7sDkJ`)&lkWllqqg zJr}Eyh=};GVagmwFbT3r-lP^Hs{<@M<-Z0MvCkaSHJSpFv7ahGXuQA<(SV7M-)>cKN#MB{>$Yh|`=!o{*#)ZvwtJ(iELKxVj-Dq|DCeBUU08I&G7+O|2 zIgivTnqVf*ga?y)H(aO9{@5||izV^m=Hju9gW{NMr8e{kHOgocJ!wyRf80{N-Vu|T zGX2z~vkKp_@oJ;6tWsZUo1Ym=Zeq2bADg|dSLJvHY*V1kuAjIVM)8aIemd+XjGc!Xfp(z3KMtooOXPXluXXoOvCg_u%TbR%+w{wY7 zX!J<-FQp{EG?{I0G-GqNNQLO$+>r;(Eh8`p1LadNyENWI^-hxbqYmj)*?zME*wi=N zl5bp$N{)#Q3JO6NeXS+*t@*@!!ynn83{c8$@;Ob--u5L9(i>4Cu~YQ+{iNO3lyze` z1oh5$jJG!}?^xZ&x=e3{4-PXh2fqDo$nJj4mT&c~Gg7{!L?<(0UwygV;UcrZ`o#_E z1~F`E0zkL`siqq?*MLMZ>lx}KZD$^3}?X2M_%I6Cv8Dh}8VWoi1 z8`Bw$yW;*Y4VK+XfepaEfLcv}|Dz&@&)0=fx~9faLU3wmRZS-+#kpX0Wn$iRQ)f|D z{nF!&D@*j}waV=h5b0!3JJ>V5@z;ERA97_Z!%eZ*9{Cdaozc9xZfT>4@#sW zK2qzZf<}Sm7Vg<^i|>rqA)I;9Bu}#7EpU|HnCo|k?4VBcr9#Tn@27Ro8*9IO*UFI3 zJvk#&Xv~%>)Le}F*)O^#BKcZPKxkPl1KsgNVoFj1Wd!NN@XX}CrpQ}whHB3W(qdRf zKj7QZn?lIaSs=%l=gb^$k7J_8Vh4@x;!bIyAA6!T_rkYrSL||)dd0h9Sa>VQm473O zdm{8S;CN$9l)6G1Y!m}G`aWGDyt@YSzUTU42;%svnAuY+|sD;Kw zr)dSI)!uSAqNBh@*r_Bxu0-!dGkyQRn0w2xIGQD3ba4W~-Q6Vw*RV@)mj!|bg1bX- zcXx+naRMZ0$R-4Lx8NZ_a6*EHV7bF<=RN29e%|{$x8T|7o~f>$YN@K3>8@Hr*h-Qr znJ&45Abo=mCRSZ|-r>b-uPv&p4GJ!9n(Jo@u8rOLW!^9%+ zS6ebSB;Tq#=U}(gZVhzbJV1sjihaqRK^Xe!ae)$oQcVJH7mbc<1ux+)!`Hy>r9gdQ zk)By)yzy>nZi4Jj3B8Ua2Q{O9=FhGp7lu?z&lEmukM>riLJBczwn}fs>*2u~J&Rtv zK|B%e^Ug*V3l%ZNi<8TCi?-cwDlC;Ji5k_&$i9AL*5HA7g!$E$dn&}s9nQuQA+}tG zROv#;oQG9f($lnun=l#@uGaNkJfk6ZMEz#Wc1XFO0ttRvVv=fnl93M^Jj_6u6PRDc zAVoYdSDwJ86(#5uvCVw-P||MI<}&3}$EQ+u{;Lh(835ZlB!*0$&}l&kL)M#}^DOLB z+qt}49D0hT*IR#jNbT4hHgOaBUeXW=VZS)jJSK*jRJuqeYZ<}k1Ge0k&S3{O_^7*Y zdQ=+K=9na7hX6sBh0!|vx*>DqSN2TRr%!OZmTi>KR4ILJDscv!W7N7TqA8*P;xC@; z$_b4s1+^ySJl5t&e7OvDnRd2{!S8gbG~lYAFpPu9XCZ=Eax2Jh$rGn5kNr4_j1=L#K{dK+ z&1c#k?y1cY3M))T@Y|^xYe>FLBf)|)KK(hSLZja*3Nf>;4ZP^rBByR9e(aiV(Hh=}aJ^CB*l!EeS!cI4mEf9oS?Qf%CUFh=(X_?w zpL5up5)_x`|4609wogFAliHS$?wjU>6-yZPL5UEk+=(Ma%$hz7hDi)|(9kAo}LqZvZnamgYfTjN{W-_ zqOC zt%FQ7y}?W{PJyJa2S>vj^M2(dg3^@SA>GUL=%i0{)5|rmN%mIU_+l#e;pHFhtXun3 zLD;d1&20DunG0TqOj&&9V(w*(!_8ytNZSHOr2Nl&+pm3PmZQw5Z{QD)-jx1G^D$63 zwO$lSrVh^1i9sU%p#je(`lu_g{_&OmR6_9M{*6GwPx!)^0v!ms#{{dGGL{&2@-g!K zp`hJ(?<>a6pBjzmyt{h>tF#>);Ohub)2b3F({0VqpDIAa>EZQ+NfZa>oBkoqB>m^w z`J)RlXDUOw$MVKr7{{!k6)gRRHYi62lV4&hermb#%jcyumKbDIClglL2*Bv2(_=m2 z%RG3ECwCrz=cz3oaL2!0l#XdikHJG0i(-4;W_;N3%QSm~xaaakaMRe$YmN#R0Xqfw z&;*u7OR2OjEd`CQFuKc8mH$zbo#DeA6UVWKxVuLLWZgV7tBeVkS!CMG*v+SC#EPB- z^`yt}EmuK@lb~#qjy5O)ZdEzBm)SyDP(Rjc{Ow8Hk_$X4k%^IO=Ep1iCuAn=X;-{) zbwYN}e3#v39p6D7^ewT}SZxr|7RC8TbWv3p%ArsySSsc=D8672D^x8^W4D-};y93i z%gA3ZqQ-2f=e^o6`{A7a(qK7QvxO-?vg&grUYC|W#iOZ-o)p_wg__B9yJtVf?=oa2 zYaFaKpQApejlKA(BZ9GAgwNmHZT1@kub62J^c3f?Vzwob>Z?mFBt}k-?WrJsGxX$f z`7)N%76^xA9jEg!PqkL`DyA5gP_53qQo0{mrfzVOgGxtYv3K!`!6T#sK) z3=QszfF$1HA9PK{CuAWckGLs6SbV>F=VL;h!u@U+MJHyP&r6*5eZrttsJ3Gdux3E# z+R`@)3uPQe;x;pM z-QfH19QANbc!|sPRbIKEezx?{y|f`xn=6#7@Qp~?{QfoRamfcQ#%Zy-pHuEH!UyuS z_5@T%ipa+#9OQ*;Kc-~k@kW?~>g;BDdhy+HUp%_P0` zWDD2M;+^UAw1`~ugA0cjSKOCzK|+j3(b&y}Sd&-R^v@eD{KcxEJCmnOz_8@3Jof$gN>g{vq`@QL}I~J_iSRt3Qf5QARh3G0*TCT?^ipQ>6xlVo- z*(PtGt$V*jw?ADaLY(L>d7L1m;LT z4h+-T;>nc@2(GL?jzmv#FDd~1MwF89<6O^l3jcmQ|$;U}qIn(R&bz$a~Y*$jcVNdDA1l`qhV(7My}bK9gub_S4s_-?Cf$x>I%Y+yWM)`QCqts(SUpE3sZ! z$DLKH_B*gbI7yDyC8MKD;TMr9P= z%E!ggBHeVl{cGADf?bXfc1`I9Y%J#e#d}%3VY|P$w=esq3{DhqMW}5j!dZ{_Jlp3r zU(PC6P4qNl$?%964(Prt)s#0aUQc8)FsJybz}jbpp~as14r_N;TacRxTpu7lY+#NY{9SbZ4*llFA0C&_r~plGD=9z>j@28gURT2bP4G=Y&beN5!6)gjc1G z3@CJPJX>WM8#pSLOm+_X4pw5vaQ2WniX*Em0*jvmgzM9oZ3Cagw8WG~jPB+M`o+mV zkJYIbus&j^20~3+Y%3XM#J44)V$(k9y_VVoivM- zzkk-wA`e@!&DeNOl(JK@NCR+Hyi@ZHTju^kr-ynZnOtRH&g_Py`RKFG%`_o{&9_r> z>d56Bl3d@4fo->k4U$i*m)hB8ypMqusZa;`)IQ>0yyLKIWwDsGU(bZwMQ((UE(}qa zG-P*YBE5BLr0PyYa&}oPG!lGYf0?gbZ|{Z-a@C~o_tCEoPpj7^bLdUo3Vy*F8q4{=N3?;3yBFHV2Xv{eKt{tmLfw!C*^?BtkC8$er6m3C z0eVr+Q9^Tg>0($9LWNuRW@`5}@G8tAmb^+8WeTT84AU1r`{~k+KJ0P}pC;3k?4(vy z?jTY7$!!t5-*9Ytz@MAAYRPp1HBWPQPb>5EKsqK@6q^u!vr=tECVo!C;s~+@A<<|; zo1W5bwhD)!;_ml)A41okVHu2!jV)6feIyn=6<@fWsoHgXn30D9?v_>A;e8^Rqwj*R zaklbF4i=l?dTyeZ(f;O(S^q(6i?S}r4HtLbV$Q6;lL2N8?RUC}%P2Vc5jRPMjING9 zh2l{yuOw1PM0s8DwyBakL;o$^$+M0r;g;8BU)Jf7&A7dM|XCRh3?$?hk!+E14*eAKIWn(b_% zddYDUv8ChEUL<{YF?p5pGUBgXRJijX2j_-@8~eGO@-cj}RAor&#FP~tvtQcmqf8Xl z*Uf@)D%LLd+e<&xf3L|@R-Lj;J8`{JiE-&NNIGH+vJb#z54NPc%`U-At@-F!o@c5d zIWcD_VRjCOW_})<(^72Z@N2VBv1QEO`vE@x=4BK8~b|?FImjo6q zjS`s~dTFeB16^)I99}W2=FCyY{#@E)NG`C!)Yctf~!VZfv ze$vZwPJM{Jz`7S7+E|gK7b4f4KE0YIKN%^%<`_O1%+dEA4uoym_3nMh@Lhf(oA?B+ zd2KtQ{l!w{3Dhz(JT~6Jio}(fhtVFz!7+W=pU&-uK`H{C$G1hrOfLU`ChJ3`{56Yt z8e}2T+w3?Of4$)dpBi%ewB^&s&#~Y+bG#T|7`t~jLVwV(xzrS);F6uITq~*l25Ht6J|f-EFW`*q(#xtCyAunY2s~BMVjak?DM>;6VK?TK;kE#pG+W27<>YF&F^r1-$r>>qwVV36cLSG8*Rj^kUXr9 zYj&6TG(76Pb04&HNE5!|oixsvu42|kAYcXMqSQdO&??ay#fG3mrWEE_XmlPwyF9w^ z(lf&);mEBxNQ$YfbXjA$rh_4 z0-2eEsj)c?Jm}S}b(hJYN$57kNF;!zY!2Zd5`%m%wrtnILRMeOFJF}OtIp_(7`4wR z)6k9>&6!M`TAo6NiOIKX&r}RjAR*h%z1xqrN{|?$$w=_R+Ea*SBfq|$l5MVC%|vm zCg!Adj`PBdwp3*Iq9`4sMFScZv@d~iFIXO3q|P8L>nOw+m2^ffB&)5=CM?*Jb?qqa=R z5@a{athS((;Qfrggz#C;Epg&sh2e+Jh3WDEPnBRlAi~dnkb2Z2>|4gmerW88*FQlv zGQ76dL_98Pl52Xm<^hi~7*UX2sqH+C9gk$0ntL+lnTn-RK1XMP$hLWrs)mi+>&J97 zq*~NY06Yy_Mk5}g_y_G4VzD4SO`Ps#W;6#0rhc0u%*i9rV|?srU?T!}33TF4rKcv1inD=NY@^6ESXSd}Lh&(9O5-*0BZ(1JRcqYo ziRp@Jfp3^Hzxp$8^S`1|`$GBwLKy1jfp27q`y(gG9xsqGX?;JJ3FA5{(ph^$G7#O8y4n)T+ZT-`zy}pP>eo&MIIxQFGrPxLi>gVC$&c>juZ| zz@r$X9-62wza5kKsR)(aAj}|QU^KJODX+^O6+}#hXTk`$NaKeWl%wpzwoa|Y#zVvs za9FIFbddC$Yd?FgNo7pcLSL+`g*f%**N|(ISlTSS+8r0Z7)UCXO)LQX2%qo5uISQm zY~kyR>??lp>{62t9!#Zs4<80jeIDFiVMOYRz%*-f;D`&?!ZM4f^wj*8m!uPxq?>_5 zf+5!KUoPh^^AfFM$;;Rni7tnfapa?fKQAu!otvu@ynIIVq@q!NLT-i*F;+Ux6fF0u zVcx6wfNnT)YL0hgK#r)qf4In5en5`7gi4F~O!kOdTkIp@%uNkzbZUozMt)81hyB>3 z*vN-P>5wPan6|-XTA_oGWHM$CvIq4>RW(*sNIw+$6Ri`LuSxQji4%_Pp zi5ez?(qYKD68!QXM@*^MTI1L*o7fc!E&~hB$giMz1I;bn$DFrw$JC$My4@N_#%?=U zG;g$A=rH=8#Hk9EifHZJt))$;`+nph^1})?XI?;)DLMdyNM-UV2rJobs~AH#j@VLH9mT{ zlfo)wFk2xi9ytcAjQ$L49X&35&x3O=`{KPohOd(FmGJrjr86pIGCT}XG=+5dUR{I+ z>vY*_PNv!_v1?G2(}w0mzCkE`x8T(eG{}VV=C$>@rBwx{K}9ZXs4-2uI4I7h20=os zQIiJEHa!Uya3tP!3d~Tok1xQpL^s?b?@Q|_Ei$;VSpE%y#V~m_2=2elDz)7GLSOGU zOMT_U>t@UJG}vpR=dzg#5$jQ`&QiWeLs-tt7Hd(hc9T1!AL+r{Gd}g^HcLQ)w_=v( zy<`680U%7ZT0NU4gLX!?h0|*c?yE{J?Ii(*dYoMwDCsn^;Rf(2?7>%+=FyBaP$el0xWAs*JwRM1s@|I#rwE?b00H6nj87(SI{ zhPw7sd1iNSKy+N4kNb9bv_jGA2i_Dj!YFxsuQQ!7Oj7mm z3~D-=R8&h6?U~9dRTNr%4bQ`^)|d=Vdb-$##YcG8CLD{(K<6?-2DOzaP#GZ*yxK$w%Rg?&rP4U9+I5`x^*@LUE=lRLUzSc=T3_c=%o*w2B?26z(7@X+6 z6rqbC^kaX>jaDhsyhGtR#!w_CM9Qc;^RiOyoF;^rw#NRHmh>%KFIs&i+n3(5O|E2f z`PXsOJ07CxDRY$>ciH}rq$7h#IZ}K*s*U0@&;1q5DzTg&ERNAZH>wBsLz}|XNxw%H z^8X|n-=mV5s*okAUXIgX=4mw28vCT6D_`vzYLy>BoL+|IEN+#K=<6J-ZE z_T)ltN=>BI@d;G{_C7l}dUqKIZf?$c*ZzpzQ4mQO8MSsvd-2Ks z5Sxm8enrkmL@|!D_iy4XIb~HXWnUT7)S3*(oQKNiH7vcDsk>jPaEzb;m zXr*3qj9{9@?9LAsMNXLx-|`TxCq5PC)DbI`j>sTc5-P5UOUo!4Kk-YJRqt~bNUT`L zJ&~~C`L*O4_$iT}+VI83OPg%E{aK4BF;%8W|5eq?=+PO}cn#g@mlf?HP&1Fn@CvM6 zQOr=#H+am+9-NJ1g3XXUl0$4No;y)nRmaZv6E{inQo6XL0!WEf`hw#@74roBlYP5s zRvOI-HPTgd;wFbA(PLnWH@dNHECByiHXkVi{#nSA}zvz$vc)^0CibRPu~ zF>ai$?TMdx4PPGc{8Ay;ER7$rl>}@K7gHuIaTqGY=Z0XZ7`kIC=Q3zkc@f5$5A3F^ z^^hsQ=(88o==RkKufoNA^K~-Z*fa7i>C-k=dfRUS&;_g zMQB0ka~mfazRW-*()l^dgHG&cDg4}xUWuP}`(?ZoVzwS*YmAAu`Wgl5u@WWxWOt2U zmVbFG%ptrYf5ciX_KR6Gu6XrC+i3ENg-`@qN>>_eLwGlO%{lamGY09=*@U}&1_J3}(Sco2iz}{EA$e1&bV*&cfts*|Y2p+im4u*} zEN&;yq|bEmRr}6_s9%Sard2bO@s4E{=M$7MuNHd~>C`p`B#NNTb9n zjD5Oz32^0&(c@Rc=_jt*Uw}awmx(r30{DIX0c;t#2)-jLF?>KbJlctRx7)kV!DL*N zNB(u5NL)>D35j2~5Oa7e6Q$`zv)<^jWwIjY1Ed~Z96PsU_t$FOHR?Doc?pG(xXO%- zn*1Dz7sr3_a<67FboF+12gtoR1=a2q=_5a`iK#OpT;`blGBo$%B1`-#mhe3_#Hkdq z&HTjB-Br1&RX8TU0#A;pM2feHLJy)#zEsQoa@%gz9SC);Dr`SJ{eAWl=as+Zc{gG;p%YcEyE2X{eVu1kB`Hlfae2_PsqTHZPH7#>_Vo~T*C}JiPAZ#9 zfqaIR3eTqd%@La++tfNIhsAB_yYrsCs96goWR#Z3h*nF%E0W|#ga=XRMfJt-hMrm1 zyK~&L!|OL#5L2o)zg#zmFIMzh*eQO6!x*ooXizJ}Mgc z&M@nS#D{=c zR{GK~?-=(2`_(QGr~K=XX(hw>XNvGmULfA&!lL~oDu~{Z#J+&VI-oN1CWqNsN895L z->XIOQH_~@8Qu^dZ%7=uBKgM{espc-W&<>(P#!Vbsx3-#9UgBy4!PxhGEPK1VN#ZlnfXptcLmtVQNSJ?6cS3uo&2}U;`P~<-bAJsdJ>- z!7_<)C^5PyGHDiD7sfdHh5fXq+!W&Y?>B3{+(2MZi!zg{WXm0uq-3qP7V7H?7M^?f z`>ITu_)w7YN1Z`u9@T;2k-ewSAbl5Xlq(vLBMDEs{YJQ!De)_7sbT9o@ zHc>{=;;12{dpbR#tId$Kj1rx@r3ur#z%t+OH>lwNA=Qo_k<<`6>K199p2;m)kKqEJ zNo%Ui%1vt3UL`GLH&9LhceBLM+T29Y=fs6H+GuE_-S2QK!Pyue2m0Eq6wQ#QIWR|>zG2e&}LU53h zKJZAe^XK&qodQLDEzZm3qD(iTk*{M7;CTx(KGzT^GxXH9??+PUP2-N~kGen$?LJ@= zen>J|zTy8$HEI+x`N~C(3_9b>ku*Z{M2Ua_Gy$E)W+uPRxHe|!KJ^UkWM{~l@q&pM z^p`@r`cBHzt;4R^9^jb{_s1#ATjGStzIsxFI|R2pQv=?D*=R>&PVv~RLC1aQML65F zu|C=gch@bXUC~#IK^Dcd;UCu@upQ>|#i-Jj5Hy4(r|IPgvkN=P8R0t7I3ws=QMdRp z_lY4colduvm|}(v;SW-1;%U-w9clwAUxY2Fj>m9^JFq-XX(>EPwe{%hpi|dDPML~ z9h_TUi3(B7U%JhBHZaXHkx4@9<2vDDBl>CnYR7S@ilU92o@ByPj6h?H*tJ_1A>G_D>p zLVjXVRmxRU@30?+*VEsm*7MhzSDbnVq}B+w4w5Hcd4Xx|KG3h}s!MQ4GEzRo?m^u z!pWWqMe%*9G+>SC%3-gdceT%-#iB><5ap(#gRJIW@oPr0-iQ0aN^>Ev! zqAsIeZ;I-BhU3%i(x6y}N!sxMUj`d8?xXP7rI*>6h-F~cd`VPUy#lA(m71A~#Wl=! zG+Lxl8*AxllhvbgfB(uCOS>sMB2|V$T_aR)ITlul4bzyjsSS|wYu@Ze>kD^olzR*U#_Q7PKcrvY|i|YNr?y{zkhF+E$w-SoOWZ*dUbS>>x#2 z^?UIXeE^#^kIEX?sq(@|s}2XJ$`a*;s!ZA=-*ZhP=|MSG=!>MZafirUN83hR|0iU! zmRv%ggXkryD{$02`In2UrkFoG6>crm9s;Fv97aDF`YDHIL1B>mo(qFrNC{&5ka{a{MfGUsAOUL}VeeaaUwTbX@S3>l%1qM`_?e%Wp*rOVfWFt;(C412^K zDxN#uD1$kzLE}AcV5GM6iC1_O8upThtVY z49yx%mQ(Y7ZW&I`<Sc-}@|RB;x)2b)iP_3S^wF5Am&R`%3#u1rdUtQ(V6n)WljFgOV*s zOo95QSUVe{uHPjD8oxbPJ!fEfl#mpa)&60OJ}lM#)IjTOm4}%|--(y!b&I0I+bJAD zoAjBMwrtmU+Uq(oDCuEl&Pn~i7#;pL)qV~kONGLiJV9+Z8nI!@#>05xU;VW7-{E2% zAN(Q)o8u$!z(!SygtM@>U!Fv2y1IoiEE5xM(CT|~(x`?zaPcr<;xe&!z$N&%GJ)t~ zgt-o9sNKU=4tdYMJdCgL-8yRUfNyC-Y)>cF=S+H|bX;*n9=U~d@++Ucw68ClJRLov zINGYz?Z*CMEp=V1h+AYXP+}0o`ZBHsO}T#C7XMQ`I!+0W@Ndx51gELPuj;WfCzrgE z(=I%AJe03xiYa6&sHgpFR}4A2;Db6NN6okni7_7s8Bax(2i;3W6Rn53&A>SkT_8)4 z2p@svyZF7=RuD^ji9E_qc{a@G6tfU-?XTI^L0@^xnd5y5Z_=q?3;n_djY`pq`>l+! zB)HUtAAxwcdlnph?$bXM6R7EvOb2(hBwIzWU!;|T*T-U#s-w`myas#AGT_wXup+wl0hre^rHvz(j=*iK&T`9d6t77eu1e`!W6l(`^G!@uJ7qbIpj$k*Dq|O{3dvv@t3% zrTP&st+ba{+;a`0k&3;hNXzPoOa0|Ld^jR={HmM7@_8Ry7g|P~kCGG%y{4^BvLUx+ zKEpCiq^xUd z%6PPJJ&GBES`A<=jA_6>Mn(1ajqA32xS+@P;Ar{KXNOd$z1Yk!;!+y+di@)3oJ&%K z^4Z?>jd(QDps4qJP4G1(bKws7T|bLyO4AUoXFeB`V~upQjsu8iA2*7EGz^g4W{+IX}Iv`*2m;!{NI94adVn zgiBxS)COPNz;_%i6VqpHb*@_=dwcBoN;P-WfaQ7DoZcJmtX3PZn5vC0O2dxtRlE(T zG*s$JQ8Ss|lfipp1N6pQU)fF8R_EFpq6&yTdgx4;vQU8=iORts{V>{qd6kKS6Jqp6 zEw3zJ=qVLCHkT5dl1OnVml{USE+$htV?t(g#({#4m11s(v{{p$F3eiYp2!qQpJG-6 zDX2!V~U9U4(C<2i{X#pU;%}*lGfE}=S0oAQmM6PIgw^ir4VL7-^)$g zFOt~3obz4zNtU0cUD6}a>sGUeg3Rq-*O{hGMwpTAwo!;$*VQL3bn_bbl$*NYwp`)s zUW|{xM`hgDuouj=7IAL#Op$&8BU*!FM)L8}DlYAl4!F$cX6Nio1MW zCOnf|yJ>WMJLkF7^^h5{ZS^$FQ5em!p`S}}H|nA5bMm~bu*RaN7-){=V<~youXcwH z;}e+YZFS#{Y>Db<7Z`JDbPhZq&f9AkhKKAz$Yt&GD7PAml^$+BXo;<7d*STMR>T}b<=40LwjavtD9<^-=tj5Y*6U~P zU(fcA*gWzo*2Q&m^?EiIUU4sQAVdqS(B0=ZIEkb^X8>2ZYkwB=7 zwtH#=Q_0ji;3bvpe+hx^U9;X_Ao!mefC~hV|JzUM<-GeMj}&xdRnyC43Y8clhmZDO ze;AVAeI$$~R-eIHzo+{QhP?l%w#JTp^h+cFhW-BQ>PZMMaC#W@|LSQAF7FvJcNVoZ z!PQeu0-t~xpD{3*&zMNStftADkWauT=$|>HKQ2MgR!`N|gg_$qcygM5WRUd#KnDTRD$@ReaA2i+{hJ|Ir?k_j{i6uPT5W;2gln|M!_!Jf{ZFa7F^= z9eK{KUuE$wOoX`aod-9$UkrOlBAx`c+Bkl*+B(?v+R-^4X?=c;;|0?Ex4U4FMYY5` zeaDrm1UT%!&i_}YKcKZgASR3(@WYFwOAI0m0fK@cSIdMj!a!kMW$Qz={Ffwe{)%<; zUj_fp=*GOEaZSp(E~R-wHLw!*Yf)qPw(Rho|LY|#Jbi`N2R9x+1A@ z^g;CN;Z`=I*sNj5e@^~S3Z*CjA+|G^3Bo6UK)_H<5EwvUM`nb_#DxHGbzqw9uts+)m9v<|zv=U6WJhFr|8wT)BR&JuON&+R(>OBRV9uyW5783I3`G5U#=OcUyOS9Eo*evnU z^rgSj6~nY|Yd;b>mKZb+e|Kq^zq zM|*1b1`0U2KDc8w+FNnCG1=_9acq~eliokPDAfY#661U9k1xCX@#psspvnHL=6{k% z7We!*+E~RV(=?1qlhLy}YBGmiqfE$;MLy zcmfQW9fVy94%Z-Q#$V?x0075VDsqnvmU2@Ir9 zz1`^Tu|GBj7X!imw<;jd?Lzx3DaReRDKh2_oya3E>?7FVUuftdwDrl)=W0E6Hh%d8 z`~)W5N{&rX9cAY3pQBUt(yji&S#(Pxrke-+e<6)jD>dWzHsT1kq{&rtWH~5eBn}U` zE)O=0g^2~?fI&PF=$=AlldOrni6~5lf)976cYzH1!`&IhhjA#3yOZ=V=0M!+%QwG4 zt&(`bDmTx9m(k)tlb{C~pM{{bZnfKuwJ{<8XT`_^s$w4ZJiQW=D~S8`&cDj)2-f)@ zJSi#M_KTgMIzKwGy*ugWcND)tHC&SbT@Yw1<7j`Un0`mg9y8=W1^!9x%@nq7e~WfB zV@Hkzy##h5yNLbTx)|&P!gTd1!eBtyC>TRIQmU40RSQTCOaKOhrtQGAcg26RpziR{ zCYIpE;ZnF#sWLJMH&E$h`&)5rEth!_7R@-7g@HajVP!j7tLl4~U zfa6Q|ei!y{AQA#Fv9I5ZiD6I2iB0Qo&{n7QnH(x90T_fP2SOzVBcYLi01`-mP)7w} zOb#qRDee3@J`FKrPo#%oRxb|~&6NAaDJ1KjL#`8x;im2b##eJH0+|Pr38f#khhfV1Dz3KSn z>wO{FZX8Ilc>JT<0F8n%guV)^`rS5Fkr~pTza1+glAS1XL~}^m`9&%=shSeLQ9G$< zHa1nn8rpuLvgfoglv%&fj~Q$F6xaSm(wkP&2$yYpDOY5iHlwmOVIyW0}TWSF40>BK9S z7)us8_DjFq1z$^N;?+eeX z3})@{oIBzC34&}L?CekI#C)Hdn2PL>#v>myxi`n;{xGwM@5jVn0K`=YtHA`ZQ_W=s zJc-tjHYMUXrIXsbqYYRO`XWWo1O|f8-4$FF45++bE(+Gwic6%Y|GVtp$5#YZIO`IK zhHx36uM5Jrt&TcuKbam}gtJ${fV;dm5dH$6ETDt0OqAw&=1%)w(gY_LmsVemylHH& zsuHvkq2~8-ANRrFLk0hdjs^_DKYAPZL7KsFc&}q>&|`S?sR3>NTc9)|FRH@}ZT?W` z8Ya0mJmNbV#1wB}wLiWE$cIV5g!+>RDv~Uc>;i}$1_}WIL23b~oUf~so>R@4VN6r( zZMpYQ`8JdRa#U0EH^|ZEvqx)nfO$iQB0=WYCI5c1s7}1m? zt3i`iAT$sf(!a3TQP!eNKNgAkCW;1=@vOUbkgPabR6j8SCZ=oEoaMcuVb=usLIre_ zCUBo1VyGqwG1Y+Kcgh=s{yV8n?ad%0uh^;}whhjvS;XE}u$sMCFyqkl{MZ}ilMw#< z77bw!0VXvvCqN51=AJVEE`Ec^c+Ofj-b?-l^;}q8oMDA9hOi6R*w0_93^+|ur`rFo zP6uR-3+{Q$!A!^k@}E7o1@zo~@9|f`utM1X3tu9bipR_AINPS-wBchxc`=zw>GdUL zOaL-hl2)|w_NzkZJ!d6gKuP>zJ>r9ik%&Q1q#3H}9;2d%UT*O)3Ca+x^_$nu($3?- zgZX=bny=aEhhvaqfbonB!UAR#(CnCufItO+6LkI?gtwTT*iPko$NU?#e(SW#*@>@- zhC0$JWH5e%k||e3e~%rUcn^etG8hCRmIIFHS3dgcNss5L+OR+m&)v>FPtyCBkk-k#9fwDbHLZ{!#2~?n2sKJw zbWb}N#Z*NI1Z<;Jah8W;=^!7P>WRV_1_P*oeg;!Il*GRh)letj+z^bT#{!JZ%vDc- z#X$lR)O(D70h1PErwd-R9$#Vz2tKZ5Ll0<&*GocxOo4UVdBPauFgbUL;(DA7FyQJ9oq zYLp;ZJEXisJunDg6Y9CUez3p!M66b-9XI=Yb1i>`MiV^*1R~#m9>uxklP(DP7mxQz zG^DE3D%>35aY;eUzZm@mFv@!`QGkKL&JB&j0)z@6Kf^$!LZmRDNchx^#;@O?%EH|{ zHVQ2plTIpZ5hRR8oTrt$N2wnLvpqZYrF zdTuK4Z3WRd(zm7k;i+r}xpQR;K3k^hR1<@_6?*apsG#W%0851j0lYkf%qyzp$ zzH*Y&>3JujF;`rF40wC>I#9J7ph)<}7)K9GK2{&CXZxmC=se(m)G=@a_dr65+<&~4 z^O-ul>7?%!nAbnvgZ0t^bM>+s;VCDL`={G-00_XJB#RNHwqMy?+69Y{a_lbvzZyeUQ6aqm;;(R z1i5|;hTUX~)Btb|LLx@RYTI;2^gB;!9qfAElCNIZcp``@U-@qVE7!b$X^#dXpOEq{ z2rY8=E_i49r7Gl}<$psJZ1&#D`4({qjCc_D7O6X4v2Ta%+x&}gED$#k((7JxU}C@e zg6~3`92 zU;ty>bwX_<&zIcMeI1&&M$*k<0Gj^|$hC4Ivt9$yq6ea+z!mI!?Yi^XWx>>CfsY$d zipVO?WeaeG#nkY12br<>GmXSG!N)z+&ic*YwmNp##3XjfsJF?7>O`smw=r}+4$=vq`Hwg`yY(R^NPH4d;jLIINy z5C~|0-P!#N0_j>o=BeLGJBcDJiu=$*(C{ISS@vV^J|~gIzODp6?mv6fuWDMDZIrB% z71&5PAQm=WaB4`*${zs2x;GYyF-!|@j0^otyNqIZAV^RMuMVy8$-dE&H+s{!`b;*< z|4M}WIyFhL=|v*erxK|CX^Jjj$ejHK=?QRM%nnfWrr6Nh@oX5*?(MwnZ^w#HA}TE& zO+RW8r*#JuVq@Mr>V`dYvHWXidpBlH0xbwwQ@J`zhhi0VrC=fZ6;qPFk0;a`WarP>0K%kEf>zy>)q@_hp~AF2Yc1GUYwQ(#*M z*&OvGO`zs-*1XxS(}b5bq%Ps=lK}+n?{@oBn4@Z<+1prnR6mj`2=Sq|YKp4x*}~Au zEvUm1I}ZdR+D(mAe}{rmf!2l+696_(d7p>po*Se^#jHyRF%k8Pad4 z(7#FFx6WUHq~7_!JvBZPcJS_r{v0(WMu1 zj%GaQg7sh1@RP3Y&VZxfYD07uNal;E*h4@dnz<*Go zhtdB<4TfAh!qEq&Dtykp~+p+{R0^s2i1Twu-d<;gbvy(#@CAj5Drvn%cjx3Zii$ILVP??P8tR#woc zgHuK8N4RSKEtFv?msxH632Rp%NzL((2PmlK z-!ByIJL%s~JfM4n6#Q46_XljxY}QA9*zPR=MJS0T63GYmZ#8Q*V%!+2(0&sk7!YENg7P=Py?g#k;peRlln!Z_JsPby86Y8x7xsR^jsHK64aXiblM*kihI^KdKfH) zPuFhxP?B)3xYZwtO$<`+^8jK*2t?6#`C?4GJRjq+;|x83U#HwX-nq*R7=!nZkx0N~ z1K%?Rf&$hL^cfJpof#SeyH}O}0FVn8vnqe9HM|-Y0z<~JD0*j9FmFwa|Nk)e)?rn3 z%>(E@GzbU?D5Z#$q;wp;nOU><8c-LYXKcx1M33em_+TRX@QWY@E1-^Jk)iv6u#w|8 z&c##kbS_4Y`WB^2OKmQFaPD7de;*J}a@1N6I7$j>ja%`zsryykjG3TV${jLCyS!4^ zvb=2uf_RGpv7%-WM1r$bKknj4^UezP7XA3Sa|9y=F$Z!f3KI@&`8>e$nSXq4s-k~j zSE*g;*m$X5lLYK*R*WyhyeDs35wEZyau98GS$z_N9M66t#fCtSFE7jA5DR)XT1_T@ z|7Jxc`yLS({Yqh+?(kvZ#`ggRG`4>Od*x-X4^;y-HMqKk6{H5`ZCb(WNoz<=b6~u} z*s>_dp<>VS3=yT5A4#a+tbO?5pxi;sE~eEPgDcHbAM-ohNdc)rYUhi%g9tVSTNaMg zc_}0$p!c9V5RA7bkQweL`v+AGUUBr5c+>HBBKfRDrV(8{ZHtxQ1_VZMZd&OG{#b{Y z=|^-6oby5mpE}J>tedWM3*-aFw_5V$_Z2ykS>Mwhz|Kqf=N9`Ad~e-TaL{GN_=TqW zLAbzJk4Sz-vUz?WJ;bD{32Z14q=4GM&9Sfd6kXN~GF_o6HyCy6fqi?wQL`!qn$B|o zTm$ZNJ5>QISW;)_&bMecHpEk}8+D6*nD$*6>PenM2A^=Z&Vw*hNe!x+m9(>aAuTZI zdnAdNcD_4PPiL)y@7-uBc+hD3o`TV1CmwG|0XqMtrtA2;4MeY}16y^fUnb2IUGG6(U2m%iZ9u}%)q!_~Y#X$UNC!U3y z@Hk`;S!98KVLgk{vNG$a%GyufRfVwNIHibTKDBcSfX)8Z1~W(5)6Eh;xA$+liFFe9 zFDLH5q8@t>{{qIi>6Pc@2ikZ4Li*1G9Xsxsxz+ytQKHUC-9tBuPLcd2!=2hC(4tXIx@6?cMn8B6-yNsnw@BQ zbM$Op#VtvsDhvk!qP)PUAyGZ!i-KHQO-5Ip{I1kFe$YA5Di?>Zk+2BqoJbluGC$B z4c4T6v;5=}H5sV9H_Y?&&<1@I;>@G7;iFE#RlK1%A1jJXJLe5M=`;K*E=||53}A-T zl4DPzYrgwLM85{K=YInNgji=CeKOaN(cU6u3KoJVDGplGH$NavLK%ARf?x|ds86!4 zHX$9cZ!d?1%Bt5rF1#M6zaV1YRp8omB*TAXyNrb7$?|KwE# zP%wG!a8);|*Kei%q8x~usbcFh`H(Z20-XW|sglAw_Hpbd|FB_z(rc8jv^rEGfcFe2 zk6o6jQk;mI9PEWyOLM>4URCuG)zGbc<7*OpPTtud#^c@i(9w54QMxB@<6%Qi^)spe zPCJC1RL}P!#bp-+rLr}gWoX$2fdA0_go0fQ3j~{0(Loba*3PU%lOQ6bfl(AQLnO$9)dn>6U_^dW6Q_@u~(3)wtX&C{y-pf(ou2u zyT2eI@&8XRw6h}+aEBIoOc7Z`@g1Z9oCNSP zKvUu37Hn;hV5AYy%4Yn^tjt{1;`1LCCjQ0&R8?Fks3%e&lXXeFU ztN{x{0Qf+Jd)}$a4#~z5IXwTDtMfB-qDD)WToE<37<_}Xm9B{`6ySwXP1BoW9rctR z-rHErdL%S)Hj51<^rH&zNGY(v6cezdT-{A?Zs(a|eRmUh@j>Q|Hy2&4khC+f=A^0P zb<3Hd5yNl=RC>oU52^t5xQOuREeg?_lIuW_?m&Zhi+Yg{%d#A~XmCkSTf%AYdDYvV z5fv>WH`;p5J=GDl&Jh(uBDYFe2j{Rrn~5SRU{Cwln2)`puCjic$4_J`0Q4i62uq_} z37iBYFa}~U=!Vxv1LqOWJFEgPxQe}$HxM8+aR%jYLPQWPz-FjC_AaTlse9g3V1$cy z`4XoP?|3p(ujqBIK_H&w+)kuDH}k_|d7R(LW(TM*jm4Y`vi8<1+BSWrAFiErs->V* zHAvN#>H}fek*T0fARYz+Mh`?;QOr}Zbc87GvGW%gBw%%csYp=|5yeVCp9bM|Yq`|N zlSl~E@vQZVSlJ4H!J=u!m=CWVMqq=feILKdZd(2`l?jlan+0~0$4afdfODId?$xQv z%E`uVN3Q>sVQ>;RAc8pDpW8Mqm*5GNwu9VYO?!_`m_dBUnt&CLw~hHFal86aobAr? zH>?cl7n)tx0}V0LJbFPT1EDwYXo(f2Chel*;^AU2#nj7tK+j6lO*?FenQ19D$)$yj zc3>cwAf4n!70e0JPCzeH zNMmVM$#-i~ReiwZob|QNVX6$S9u~~R@GLH~zLgLLJn>=ivSGdtVy2&>5up0dfYO!J z@)lKj{V~6hrx~(2lByDrU&Lymj6vM?Cvj&BzCBbl;UpgJ4{V51ngpK7w#I8aY-!BIQjS zC8Cwzy2eV;wRa`67es*G_&m5Jw4!o9blI`rM>>oeY-L(0id1l(fbj3G6;Bvf$@3VV zR3!;c=H^REQfK2g1e_;=X1MY5yE5Peb*n>pm7-ZMD-hb!0sP6cz&sdK&lx&5&b5IJ zSUt-vRMl~?N$Bn!x4XDHxZigD{FeW-g?9)<(C>n-#6kcfshqPv(Nc<;87=Li23>X>Fst(4D!Q&0x zg~`CMKRMJeU(&Ea59I=Mr3vA>-5UcS1drC`XgIS;EIMmTSRS!^H<}Rp!+*4~1Qeba zPymVfZ$RBV(djQKJpqcTyERTuA_c(`N%Ol%6NRpnD+gILbvk@FHfWE1+?RBkQS!dPHLq-xLRMXHwx@Vwvcqtb-wP}PK)!rlQdBk-f! zO7}+4)4|^cEqMOS0>P@AE_D=Iho$6HG%fdx8#(_ElIdzR%0n9EJ7<=p*Q^tnA6MWuY&heTQh*`bEu!u3$lTA+0#AD#6mU z-rr6F2HU@Br-#zOA0g5m%aXkYL0_ATkt$04$&)lsfIO`i3Iy}PinI&vNtpWDO6l*J zy8;nt>j}U=>Afha0oTb|MENd(?b`|jZ|#! zqlTkh@l#`eob$-Y8U5%PCv?>O3@%@D9f%-ZY>UgdW`~XTSYRPy8F1w_(BlzoW_i-x z8SarJkb)5H+K{_q=_n5uh+vCEEz@xhx)j*wVsvJ*iV~W}R@bU7E@SU-- z)TFUtXMa#%S}!&KSq{(3ezeVBy4*H?)oa&u9UI;MvD%++RCp|X9c4uz5UhdNp~F$R z9c&Q9mvrdrQS7Y(p??r5R&>&fhAL!ds|TkMFo2N|NJm=iO5*FZp+bWqSY%$XX=j?q zgxYZRluRxZ!dqIR`2bfb+@jeKN6^mDVc4a1_BAQ>Cx#B96^;qPcw@u^=teQ0T9WgK z&k!JqLW}&4sH}7HcyAgAfdC^4?X0BJV3XifmK~T|^5A?ITBqCz=#z0?^-WIl8TcRq z(L-!2H}tUhYgGSGvI0AP{0xPR`{<+<)`Z``qyiBMN&*>Dt1pN3Z!AE<3+KB0cy`1L177 zExwuG(Z>Sqa~5}v+&{qO8K`=?7TlDhJVmM&#^=~vG#EQ_ zEm2Ae*CE`PxP+sote$tn4x_6JM@PNSpe&(AR>-q4Hfw@Z3YIV~h{*~j>#>It(t?o| zxhod)l-6q0Em4N5ZVI2k3!-ukEoNw6S=wyeD4Oz_$$YjUH?avYp3*2y%S>xl#0Yxc zCJJ=sSv1qSS=UB99U^@Nt8?i;%7D0Z+(Dogf`>Vn5GvX`m@;gp&!H;_TeAR5cZ%oD zN+>zGG+MyVfb=eK#z9`d15u!RDZ8f29~ApL+WMLnOp`c)X4TI2;6<#Q#?;GyB=SM| ztkMgu=B*YYMv7DN5j27b0hHhuBA+}II0KsW_u+JLc?|;e4UAgT#(S2R1LEFa(j3|x zCA3Lspiy-~IqDS(4cGRpAf#Z1J|d4=tI5uUs@lD5GIC%@LNX_HAI62CNgfJv1KAHP zFDFA;1Jmds1VL9@GgpxFXy^@X>sM&naY{Rt97GVqaQj!i1lDeNgCPvTP;eS+I^<*d zbeC;SRs#2JQ6g!oj08m*)h;N?mK$)tQ1Y@b&~n7Rs}Fj<0_h_vpxz!Z+)dxiiV+Chh+>9;CcA0XYaQC z?$IL=mEC2+M+Un-o(5&D^X^75W$^rqw}!n8e0Qi|g|>`q#E->3;a~Fi@B9NaD&u(ioC+ZCG-zZG2dViCyV>*JR%JeGV?KuIwKffos-gK zZrZyv)K&@fEOm3Ui%4gVfyLs-SJr~T$Q02+F{2G{CAM3yZB(VsTxE0_U>HJAI-J2d z4KX;(x_eI3K+r$h$;< zx@QvY)BYE5UvXJj?O&jiqGa!SJ*Bh0T%|q|i}4b(MAl(EfKK<5E#*D}m=2T@^8NPc^~F&r}Y!8kp}tuYak(iiP3j zQIp$JO)|Q*dVoYUNQ;E@E=xCfRYg~v)*xB%}6JF|4s2!b!()|k|FEV#}5 zKN`Ttpt{yAXa1cXSdd4dkkfneXhioBSj@M^>!|F=d_3zmU2y-);QU|+gCH>6-^io6 zL>(+QPM?eEHB=EaWD>^v;^swCfv9#4G2XW4CH{aGY#-(q1X`M3(}R%By|pZ z)7`-a=I+5rgYgm%P|X?$hBUO-CX@8o`z^475qKhd&J*L&eHM#Jyb1ZC2=wLu09G!E z)jsCzBp;1!4~T-Ixy1L&k{-%%>5*ctm|J~h%k)JvJdpPhoQ|M}sFdc7Jl}poTYDf9 z0qi-OTpm--(J%C9oS?rFK)GN}{VXbnK67rqagds33zvsZdc4w*%OWu|q{g~@ACC<^ z7w{+9c)&&jscT>&{~WQ&3df&S zdM+7%i8^qYZ0<%55C%wtN%WVw{ZKB1VSSg10)|a4g?=7Akw6aVGNf@J1XMVWAoTZunIn+!}7%yvN-o3jq9AS6jJ50QX;t;ZtRS|Rj#ASpMOj5Rh; z6~^1_Cju|X-{@9Xb)xw&+L6Hka+yJOf@y5Dsc;T3Ge$>R4;MI5N@TYE*;v<57Ye_ zZ_Y9Q-eMqD0ZS;iqelXR5Ho4BcIf=Of>eq*9;#)P~O7t@j7FD&Lywq$P z7s9==*mgDd5fS*&=ix`-7>&j}~?2D|U_kFlKw(|JY0lO&RdSYlUm(r%5%jKx;~YMwVfS zR3nuln`cka)kR_UIOpz;v0u)ipuMLsP-`)t_5dg{ax4me!9Z$o@F ztgm>N9`saY0%242E=`eI0$<-p^T4*TtCNFhw34IZ3K8X%N^Tu}B}pw58I`P=f~pf&BdpsMp`5V;~@i zURfq7E!Hz1?&(Y2KrZd>N8JF!9@@0|fpuA@3FKKB8sn58{y(0c#UeuAefGH8|3K1H z^iv2oqkwyFsz)YKW zkN*cnI7fb^1+xuF4Gpk9wlP1JM|inhc?B~tcO@;-hxx<#P)&9&eNFa1dC3g~dEw~) zpg1D9A5ZN1%oSamC^hOZS+gQJHEHl9iJ^ujRbiF6MaL5cR6;%hNTkN&FFe>Bc?4aU z{l{{}U?)K#Ru8gns)GAO-+#IqMo|tYp`Dq_NZ(crTGZbiVQLcOj1;>!B68 zN1sc$=tiF0oK99!o*(GW&T*zkz};jeIV|L1&0{yT~QhSa?q$I(B69}PxqsAx$F?Y^fdK>4#=n@CmX&Wzg-%|+Fd zfk&lYL3C4XVmcYfuGdAiZEa2chIp35?ykNOLNwL&ZCKGBCHICqVowbeagE#sB*eC= zt0(S5H8cO_3=2k&z(SmzJLByaG}rz1>+JN@wUb9DqLwV&`%bREAScM|^VvN>Rg(qB z80dA_;*xz4U5~k@=}AZ{Unu;ofvSYEre0`fL~nKf6AV|snh|F++$aMsrV*;c;a?lu z?NE}n6;iuW!uepE%lFDuhYqYa^%H$hVs9#@=dYim;iT zZPy+(xD5BzM~dGmZ>v;8S8ps~GMC5}I=HV(u9gb~x;i*I+o2W@Xql7rl^&+K?@?PB zmF-6@cN-3N$D7#B9*S^=V)gA0lUxm^itchk+ZdTQ_U*ot3A(OQ0_0ts7vylDKhHePBr@jWG+aSj<%x5r-0P4z8twmNx#N{X>P z#FEh106F_$h3dUP{_d97lzxITm%>!7_e5O19s(x&;LoO#p>6gF#IpfO7 zm*x3|qv8fGhg0iUF9Iu5y?=h$J`}4vNtO^j(p{pM*g+Mymp3OnuSIaHQS`>Y&er8@ zXdfMq{$WTEp?!OKn6uY829O6j4yvbLusW2IQ zFKm39%DKwnT>`hG`@&M)I_t?$N*-r+-w)C9#)gkH3GSg1v?$Tnyk-spsl`46D_rjJEVU(x!uy4nO zql}QRWBa%)FE=-;RI655OHknrR~;I|lfm0ghjfqVgliizB4aZjk1y^UP>PMIRqJHTRM`Cw3j!$_Jr8lUx#}^ zVZ{nsa;bgi{nR)nLWWvy$NKHsJ0mCfkaw)Rj}-LuHz!~x{0rJ6JY>t6Qk-=a^k_uM z#=T8Fc(gg|nlW@@{R`@rXlzbB$>AsS6C%5er-@-_!X=nADFIgrl%(^8Np8QA7n=i6(4;968R(h6F2aIutTsz!) z@K5_h+qj=wKPdEc*{HmyI)j!KVt>JY?h%d*deE z9&wKk9r?^^IQzcoTrv#joJkwFb~GL_zW`B!PJ{-m83ZE&?2q4_cPwxSK%~x5=0_2G z*@YjknMZ0i!e9BOj}CQbr~jC2&CZyW&VZ}DEvPJfD68-1!D_X?Q@rGu-kqIUx&XnQ zfZeW2NTT3vhQ@QCr94hwi~f0Y8jkX5E!ccW!Kr!NT({fy-~s= z3SVO2GW*+W99i|sW8;JCLjxl#8dnY!T>5XxHSHML*H3*scUaL_AP- z;fgp|lR7JW<0CHO5b*gMaJ#pTG~HDz+{$kEA}dOF4FYJt-B&m%{{_tp8&pfEv`+gu zuLp3m_&L9RG8BnSycbpo{Tfz zX~53@3xtnKz6<&#hqsZnyXp%qDvrNE_JQSh1ZJY}MU&rRA#memBqIZ8_B(+dOv9%KQqj zJ}BRI(>uJE6y81U0o2#mGy0zQqxuZ?_?wGDb|>OF6=P30aYVKVhI>P^PJ&rVDvfQ_ zjH|ud^81|~PDL%_m3iPXQATU?%HzyG^V)yrMD4uzS&((7KVb&JFqGuAArWj;I5R;2%CJKcafd zL>-we$4d;VQ|(BfW^a*?3u>e}l2xqF(!4dGFQs_W_q^KvhwEy}^os=4Gg}f}3540w zF$AMOV*-{Tm+vMCXP)^5MJ7=UTjXddS=hK6eo+>bmM2ppbGE5*>%8UfQ^I^yvDaf= zeD5UO-r3+p_@KG)#7`i~TU{NlB!DC{Yhi@GDR9n0jBioP5kG=X9PSKTPya}5kDh;| z;AOkpEB(jt$_V)Vdh9cs+E+f7`L}%3jdGhKD|rCiOcH^U158G)@%2tp0xj5a4MP@Tn{0bjN56H#CLeNKjk(R$%=6~h* z^|nR_8+Lfs*ejIT!6oEX7#FAeU9wkyGlsa2@z88$2cQ2m-e-6!mNxoO)=7KO_)S); z<5xpYt@TG%Bdsm!G1)seg|@$7Sf~VA^3Bm>C~%O-LH8jhECeXqvz53HN2_gg zX`Qy{C1Y_{rHU8rHBnV3{Jh`xbY#akyLKd7(3EP;Ab2HTK>ICSltlbg?QX~3blT>s z;=7joxeF?eEZlq>%H~zMNlSY5=57U6oBB$nHCe*DW*zv^)5bUBO0@1X6^ip-D26bk zK*{Goa{tex^F2N6rg=(+F`v>dmmJs2qW(DfA(d*Az=*r|*&S{4tz0ZySWpeR#fr(M z^`|OsmuD+)^?OE81{9WjS^4525P0hS~f#Q~@EHQEl>&f-UCA`5=H*M*ZaO2zJFL5ha?52?rQD^?M z*uRfSAj%QKjW5MilX2t~Dev9xUG+I`Bpq2%xgv(+nelcUCG4Oq5I^lK?$hnN9Wu8= zev+<2Y)v8WAY-O&G1P6%P-QEQF~zRfRC!>^-3gUVvZN?fv$bE9rn`{~o!Q5Kl|>%~ zEv}-F<;k2`r%HoxR3H9Q{)Dl5WzMzHj5`zFX+PCBtsP?@Z51`>f@OTm?lX41l4gXV z_?*pGvdco-YL+?D7VD?wbP=4y_%?6Mn3Vh6`hD`x6!1h|7h?TXwy{R zH$#dvO3_FCW$67y12_Qdu9G1ujcn9^v@h$wi}B z>}tQU(>Ypmk&OH1WY=y_ZQ`=R1-$&x15O47)*v5kqxc}AhfieF&OFS2;l(10HNv3O zxjL_*Ul}AVE*L`gsfpSDcs(`X*!lgp3$Is`U9uXKi=tb3G%*=-0*7 z06m4r$asbfmTYs;xq>hLt8sRmKp%W`+`vV7d^KEdJWUSk&AWe=caiV-8u+kkFM->@ zqLLT)tra6K&gIWfCe0%Dcc2(N z14Qfde0y%sa|iaAOWqR2&x+RVZQmmZ^1(HX%b(!kikG)!42wyht8a{zQyd4#u7~9^}b5s?=CMVY$yB_Uc6+8!htIic!7Vn7!#Nv1p^$WH1lJIc>kU zFf4?G4sGX5vY}BuSs7rH-M|MAy~8j_=yK!wmM7a4*iJ7}HqGZUsZb zDbxXICv>ksV5MZ}M{Vj~$=#K)S6|J#f?FH#{Yev#wJ(H~3Be#T5U`T^UDElE1RnxL zVu4Wzt7%U536H%?N0XAQPpU1REjw0VKA)U${THrE5x8Nn64QFIqcs+p{Kvl$V8O0) zyno4EOvKSp7~-R&lau)_2up6(tShS4$cUiX+Z!j!ZCDwBAH3+r#HzrJS4ojoYxzM& zhBoD5DCke<30t{4W%2Vq z)X$Fq0u958zfGeOcTAmrn4YkFaCgkI!@=(G{y)7tG<7hCKYAWstT(%EQsUq4?j^Cq zsHkU^Y?xM5iHb;DzO29R zN@_$y9Ql}$kRh=Qb?56&z79tsz7I8*r?}Xa=C+LOKK8DLta-ULe2ri&9MqOxA7L5| z*O`s}Hu)LWal-RrHoW_zh;g7d6F8WIt?00frpg;Ne+ZxdC~>6nWj9moMU1vQ+)Ji3 z%hNoFX*7b-u%NiXa4h8IDo3^r#i^Jj%l+(i0iF55aOb|rWVvD#PoBV3%;x&t?|IdG zhMh%m4>AbY)dJ-hic1(zrsf>=hRSCd$?o|vbk;M)mAaXvKfT@&A?vZmw zbqAI@MY+kleH*!ooW7dYZV%!yX3(QY_L=15+xry1pq8t#QE$XsD^gkN9t=cBInI`_ za7=%M_|BZMzvbld#4Fs4NpGc>g@q}7@*TsR9+f`cvLp(e<_qP2#N7jI=kwUWZJdMl5Y6)Ix zS>E^Oyyuu{%70kUKuIXF$q1f_?ib+jAs=6kedDb?}S&6esXuzg2ceIAz zr0Q9#M|G>0ipM*Le1e+6%XfpOUud);#Z%|EQf_loC*O736X|?(q5Wgc*raLFls@+y z^$Y)Xmfd@1p*cDiuZ3=$)CvpNxlSI+4fhpVr@JWE-&RsnDWjdnU-}Vg%@S_rBa#$^ z1%XKKUaa(Y(vxcFLM=s2x<_iBJ7;n<{` z)trmA$%8Z?(meD%6K>>bC@;S}r&>9LdsX|0n&Y{UAytl!WPx(Aqn_89dcv@G zlVE48O#!w-R!T`J+t4I=)V`N5$3S9z|IdghU$?q*)R;w95icz>_)n>KE! zN+^8QvJ^RX<0DJ1*JoryCWhR7;2mDbz4I;OS=1-8PmCQ?W2&8>xp&>ZUqr=z8FUs- zp32U7EuPCk?QGepB$mW$5F{N{Xi+g&7b#K+myw%)Da zb>wqBS;AxU@lVlrccME)q*vJPC%xW&M;wcg)>4O<=>P6DXGb6;E#h9WVfKtS&M>^F zcS&J%hk9#tTs+w_`v-EXN71Rj_{XESGDAlm!pY{eR26%!n%OliUx z{xg94!o&|<9XpSXo5QP=aaRob{Ygb7Oon9EJDG;aUUI+9v?mA0>FS`$~LVOF5m{whK)T;F0AmqRdBu|`Da>7-EcdlVIYoz{!uD;?M;mwzaWAg&!wQ*0Fq&Cs=IS@U0CvL3WS;Uym8qkD(XdT6Whj>W&035 z@R6i9Zn^y63?=t<&>rHd@p|SzhSJIo_aqq}yHGDW&1R^_@3gMCMmzj@ByQG>UYhfA5Mvq$2-JSfYHHRCM+5_^@`ldU4vLB=TGd{QqNwz73is;H^m{#qrj=v5 zN9C4eLq1WvwvQBzey)9VY-*bqD=ul9-%9R<+(e_Qtf@^oILNiDIB#bA?pG`B7h2e* z!~`3ZRojL=3;t}PA(2-WM_?eB$KVng`L0aR!P3=KEIcksr`tzeu|ytj^cV~A@7B5C ziD1~`cq-wd@NpM8bAa-_s4<%3uDsfobEC;@>2>%s^YnrD^5UITO;6OQhIhEDIz$=e z+2pdzQcVs=l=w=h=c+B=BI^`~UiUlGhd(Xnc4b*cFx7m^ z3P@3Xq4A=v$UP@ke%$-J+k$r4DjQ({qg+-Hy8X z$tvYnV?rLQu=RB0?Z&Tb$5r=?tQHn88G7lWy7Xv}xj6}P=Hi!!-T9C@!vcIrJt-W! z_zG(3ic9LT8f_-ute=q}iyo5O3cMRQWk;nx)ykPuOKb@t9BA{ry;b#sx%3xA2YH7M z*6{TuUS{}t!_G14Iax^4Kzfhfn=zz=nnz$_;gWUs(aZoItBfo=zFnA*tJz8kbE&In z%G687^ixBA|DEYi6Ws~{RPBzrwfK%tl1oPB1=J6|bL05ykR-Ra7Jj-|5^K^v)Yg2E zV|jW0bPb|Y?!}x`T`IlqPq`-s$D6y&l0Jgj`JAw>_960HnTir=ps$J*)fGrSa`jCi zX}_pZ_SRsT;34l4R-QMzOVMZdTdkN67F{3=^?$ZK79Qrb*goy|QSg~)n;N9hm|6Ji zm6f`(i{z6Rbb1dqbyW;GN2GA$ndb(LuG}d|%|8{W+4!mr)*bq^GCECgc)8KpOe6gJ z)wKrCd7m)XMw-C~VJbCzW4H$Iy5F-a`BI>EJHG9ZSI-Yj42UNi+q-rR?IRJyFVr=x zk#>DU1J1(y8J_(oNv|~gTwTW{l{vOm9J9~jVQX?b?@=5XYte1tt*9U6`fwxv0TK76 zyv@0h`3*l`ci3ZRJ!53#?E^h=g?&Eo<+fjtVq;5V|LU%mv7|ListF49OjRxLldMpS zm4a~eDPiRnyoW6}wekPMqPff8O24MphZa?CPf78|$N#WSvb;?K zkpUmpp?6?c>{`Hc(Nzy68M>EDS2AmETs3qTb=_Ib8|W-7Y98&EC1g$-(25*c^Kudt zzDj4l7?)`3d_5tFVB$g-f1*aL`w?$-6_<9=BEbDE4+~j+|fd(xRLx9T69of5nID6h&pq0gl29k7(8JN^%cB*SE+$ zOuugMpp^X8@JY^lTUU*V{e947hHN<8H5X&yUFB-#$?%~vHfQTytNDjZSG+eJTbSIO zDf#HTM7G$gYN3OMe zF8q8$?_|7eEO{!n)vw}4irWX57S2OU{?(O-?Ky$_?TrF^134)`*5V+!uM1!V30{{N zHaOH%^C$XziCeC_*uRw`?NN$v{GKKob7`HiYoS_U!O+|J{7GudsDt%lkqYE`J0rqf zOzNLZ{yxS4-*LP73PV&kTmQmU#pRfei53T6hi6%R<$!nd-uJDu&p(V0mih30`rH}w zwOH3+^c_iNJd+k4BZTc*!SzhNwuw(L+hX_yW6-VIYtdSQ?AKo(MZ21~hs1yDMTb9r z10Lie;NepfB-v@^_PxA6Tci8O=seA4Pu0EorOCYD#i)q5Cm(8P{n@(HE51jU-4oc4 z_|mWd;c%dz$H0f2D=3b1dk2=ceq92uaBO!rh8V%upvzW&mhE z0_Q8^tZEGly$)YL(gL&H;-ct2PVw|ejd0=`r%DkO5!NcDq?tDH#!9Ni)9TN$-Emi2 zlpcJ8>vyu@)04%dM2nM2n=JP<*>Un-jfvNf_4!=eLY{Up z9DD|7u-|3O9QC2FY)>7!eoi+GYAGCYsWNm7_}*l90M^{j!ha#r2;r?$lOJySXS>RS$3eoL)As^IVT$ zxfU>=J4;m6=_>|Q31b!;m%N&-c z7oQF%CRoqoYKIui@A-G;Mde3v^>F_|tXz;9S0q5DaUo8w?lx0iPT#_(?xbPeSJLz_ z@G@e#hL$6-tt91K!B8@(gmKIdkT@|kCaiUGyBg@psH5a|8M%i^>&o%j6X0DD4F^uS zl}6%)-7h$|Hk*1^?PvSCq5~+2gF>E{%yt{W-_I}n99r6*I*@|NoL3HJ+~*r%vc7W6 z?u4{*_WFmiNjgOWv-S1}$h{WvSN;8cK-uS7G<%voI2fze#g)FK-+Zii5PsUK-xe_M z$2`9^Qy~x9FQJ3+Q}@IOxAw}wBo#-xf*8$1Q$tUQ3aY}Of+$D03$2s4DEgY+*XX?B z+-WgjTgzoZyK{XDeYtYbMMcCXxEZ}%)l-}N!s|-9aDRmwDqCZ<*n_=GeOL8~QuJ@$ z5V>l$-9>&Xu+TM>Fi$JX{$=Eo&{qHQ(rdFSW}o3afA)hd@+~c^6ivve-(K zzc!I_qF+({S0&*(zADx{4!)~7O4Eml&fESv_pWgd`OG$s-ae!uOu+k~#o8WV3XlB- zRhYJ)=0a@0rOKle&)0*PW*zAan6_F8}9ooC4B(uhvoJA?n< ztyl1W^7p8~?ESyf_t1+BU}1wqJMr`MJuEB?d`z%t0Vd!GtXF_}od=5yWbZLNbmo1G zeS;6ZV!_)|a{eYplfFMRW;X-3T%*#@QuxjggKqX0oFPW1@ZBOsCkCRCf(`cBbu?y> z!iU8meTi4?q4VP#G6FPuTRS9MN)L45(28ad+XBN91;hJ0RSM0x}?o?cAw)o2_f7>ug; z1>GL)r}C~ESiBS9tueI5cv3f{_+~XyN9j(uH!51qNVz3Y*)MN=;0JG%b9Bh0C_ANG ztJ3?0`mbeOKccK96iue;IhGA+Gl(2?Ofe+`=C?@eFZ3OA;4i9xH%^=GJ--E!N)KL( z^OtD57B0Cg-1z>**A6&4!;AL9hfXd(SmHgUzt+Zw(WnL5)f#>z`7H4f<0GU^+rD>+ ziw2Xda#>1)1a3ffiyB5oS(|Y;_)eL=g&?2pO*sOfKYJ7fr~kpXQ_odI#Otu`q&SAJUkSy^gMdT-$o~@hh{Ip6hrLIwB z!yiN3tf@M@i_B7vUE#()w|RtF%2dW8blTs$h*pM5P9&s9^Q*rjP9r}i?f?eu z-$3#aGQL$cK|5$Du!A+T|G;8mVBD!xsa~LBEIeVfTWQCpVALu|$@>q7IH%dYkViK} z%DuP@OSMq2O$RT$epq3#jcF62EI z_oVn%af*7t{hJsvj2>gnl-I+b-Qj>(H8F^@?j~^2w_H{qo55-7Pw0z5%iYX zCn_@9zmNFluINn?UGRzgSCVL7lz7-4N^kc48zv6DQ{~mck{MW z$g3+%WJMWTp9B+Y0xQ|??akuSYy7^q7VbC^J$VR0t$#NN1l=9lyAc~-)y0BhA>xi( zOb&04(Lhph3Z|l1t8KfCUJrWn%jX57Fhwl+Q)iMb`6CB}-bP%cxLNHX7+3EXHz8Lb=g$X6{;fva-}Ipvb7qJ39_Fc1T573;0`t;bs|^xNb1MO}^u7tsPN4aHT=Z z;E#>(HAP{`xT%zE1Xo}lY)t8a#upw4*o9|hu!=<% z^btjeBOiqoguy~+1A+1HP?1N(kkJfIAN=JATRP)rV7BHxE z1SgJ>{bUS^!1XZCdH;g(btO|Q(f`BTTZYBaZQH_4f`kAGZb5=I4#C~EaT<4N+-W2@ zgb>`_-QC^Y-Gf{30KqL^zkBa{?m6H6cYodW)KgV0Psv=hYOOif7-P=HxI6HNjZkKp z&+ohK<0(W?$Q`7HYfuYeg`Mo>l_eIueBwfu!SWD@%uk>dxFx$t(c24XT47C(Q=Q_m zO^jJ0&=ogAo_t?e5)}S8L#QYvW)1N)GW$q>O+5gaWtMp0wc&}ha~I5+U^?`WI-Hp^ zbo$e}hP}V0EjDX*E5Mijd_@}EC;JhU7T#lGSX7D|eSJ6$07U<{s)Vz+o7SylI(sVQ zOg$=snp5K+9(4%7uai^7$>|2ir*E#Oo-YV3V8vWxTc?aRz_;WlIc^N4@JEq9ncb^F zwABJ0>hmp3evO_eCMR)v+I_$XC$Ee!N>%C`UA(JEajUR5*B7Lt|KVWi#c1&t&@I_xSe%|`ot#?%$AP{|E{n2i0zvc1`h`pT@}tRil)IO|3|;i89GW7DqG~yW5>S8{ zC_EjSZI_~QPg;|{&aN+YBmaonZf)jt@i;meg7080%MmwkAF~w!sR5K50=tdz1HPcc zMAiVJunZ$W)}vy|w%7*CPkUDdn83r${J<7`f&N!Y)h4zs9@+0Uvl}ZF$$R$^wqM03 zfK7xvtRu4i#_a`z3X~P-JvjxnY~v4^g_yj$Du&x6!}*8DTHw7sg1POXTGAkr;R-SL zn9+{WLT9K{?FZ>w+*}f|%;cMM`w@~J*ix)L6PQ!d#o&p=;E9;M7*5)pu)0(-GeXjx z^J$p_MVkijj_toH5ROY`8F`crBy0W%NXw0{vQ-WQ(aMe$$@3<0)0BO$lKl&yq_W$e z)8VNFjap&6WZJ9Iw9ts%Qd_DpW2;w0-^A2g(nSu5REdO`OjKNAi4qw|JqBb*gqZ26 zy^$)3*@HIIbL{EAZPqEO2{(+ZcWJNoVq^}Dgt9zvOvUO*lrD?L$E($hT$O#X9Z6i_ z{$hQeI3rQ==Q?-WpJh?~0(7*X@*oIM1H2qUXjK9+pZpf+`W_iR8use7iJ z$(P8()fy+-y;cJn)0mLh(g^fTN!gjhUU~|296ZC`$gvTVAVxbz>F5q3PWrk}Q%R!`Dwg-zyC+##&f5R6kGsen)0|x?+tP$T=Th zf7r-o7jeb4ef&FTih{dU?l_Yxi7sjet?`D4qL|8FJ^~|Od1Bs7ODK|L;Z-tl1chJ{ zEp~Z1c_h2KR@gLO?MDczSWXFc3WB&CB&!z^q29g(OfRRfcf1`-0z~1Z2t@Zt1`TVnE|62ZORQaxPAesUK2e4b)*#GhS}Dzkq_Q z1K*LXz(rE`FN#j7Y$36<*foL!42m^&(n~};!Vz9VB5ua>5&F_8a796fLMYQ5_?OMXfZ}#yNBA0%K?)ka;=Iq$>;A>>7fI&Ht{89T-g^QFgL1i3n|0nP##IA@ z$6~_*F_Ge@-R+B7NSLC&$&KRj!SG)|0=v_m<&c8Zn)|)uS1pM{jX9LWc*cr<%#Fb72y-9Zg@VRX!X1YpPVWgLA zs_s+?OX%Jb=hsg|I12hc5ymBNk+RF{vSgyHP;kP<;55sP@%@~!zu*G^fe7LfWM8mf zvAFH5g#t!}(3cR|?udEvy!dW;n%$d6QS$J%qUDmu_snPKHIMowFTpem+O8#- zlXsXUBJ^(klE4EZ`kKeJCHcY0Tf9JUyTI$?bf_*x!6iXui!sJj%FFU=A?;Xk`wPCM z$dS}GF^QnnJ>IdD_ z(DjB>l>q%dFE$+z^44&p$?5}cbHh3ok5NFD@x2A`NR zN*n3vQAGzhzY&{M7~few*hm-w2>1dQY#}C!FAL$wkI+g|&ed*o0j&v2aeUJ29#5!o z$EoKIm09;2h5rnr%K}h^$wK^+(@4;q`V-ZWw3GyqLtFA%<+&(ZiPmMmLr1t~gP%?Z z=~C7?uPKL<`XT*S#XmVcm(wAPvpxsKyJ00-zjkI3%O*bPH~IWBp!9wJf|y6z+a;PF z8D(H4eGtxQBPg+atRMhNEY}Wy(YSEBV(L@Yi)cIqTRI~F%^6^i1kOj1E2hD=T7|{DE3#wuY%$Sv@`TW3uuO|pQxuYR`T3H~hteE+^Wwk1 z^4cTK`DKSYi!_#Tqa$*vO^O-k-N5dCXjJmC)rc&2Hyl|}dmvbo^9 z`zlAl$Xe9LF@D3?B8jCsLWiZrQZz3mGQJ*;|JhI${T)CWf)m-D1L%G){KljaLFp%@ ze1Lu)F(GxfpD|Gr3>xJJ5JLwbgww$H_AdicGzAwtF;_H6m!#H6-vrJ{DSo_|TAS1c zrR_$@Qnv&wmiLkzxSD*$uM^DskZtAo89&f3UskkEvOF=6R<;+JF4VYihDT=)^p&%B zKD)}%?cHM8mvk*J{!-mq55m146{vad6Z7h)Go@%LBb>m>pG(>(<5fGx;or0o`zuty zy5%=2ihi&R5&!NC%hqT;UVBb)pZpM*4VE!AmTpnJd$>G*AP#yNUqL*ct(|-ViF6*@ zUH<}(nXl}pqYaK_uZ7Vnb8`cFPVq!@8Vo7fUr+{@c(1C~g3oP#6vY@^$TdnXzl<3> zJzLvGPGYf+k!W02trNAY@rP6nD#ZoN=N?srrwd5Kuggb;Y;PhYWs*X;V26J~j8%^k z}b*?}mvfayRgjO;_2@APas$6*xAe-Q`tSKuME&?U4tYLkI z3|GOq<=#<*Pu>=XH^FjxMAb{o%iEMk=4eeGq3?(*nmU)pM;)HHXHmrEAJ!If;2tpIWr3jCz81@^uS}uDN;pq<5g5oEFIgf z>(PA{1e%jW%lfd|X`QyvG(S+7!Iq0zuWAQ-Hn0J|6q5BqdbrvMBLFsX6&1+x14lX8 zNY5m=!*WSafg@B_~3{NUkR>^LH0qNN;ZRMS)~p)isW=qt!N z8+Rcr-h>O)D%uZ#hSgw*Am&Pd>tC~E8_mKP$U<$%=)20I(R2(aa&U&O;VJH0bd2JY zRg6F($aF&JQXa7}B=qSoK-NC2rB&mN*L%Lbq{Bcs5&eR+km>`&*uH0@I7_5EsY zkCgVo?rSE0RVt%_dc&*odW;w)QDtsIqdP`gSbanm0kyx|Jb6p*uDy0$91~KRs{A~Q zgsO77PyC~x(|!;RF3iVHx+ld;BMdE#Z)Kk%MVdkHV}I7S`U|jsRoFy&*{oS2va~mj zCtokLc|&0QpTX`MlWQzz-Os-mX;Q|t;pMH(VpMjU=ZR2iX|urNlCk~zR#0S*kF{sN{^1w~*pBs@v4UC&6YFp}tBz&A94%hjQe ziS2_wZ6HHS-y@3Zmo6qck1@BB3u|RwgFO%5*{f12xqtXJZ4Bq%>RevVnmW8mb+ne1 zCbqq_*v01Y6)4+~YMh}!7c!QpGQJeJ(7F3mZ^_L8{Au@8OZXzn2+pnZ+?bbX$iwHb zz%XNU7YU(H$lw?H#K5YY`YXt;Z21>ZW(6z2tW?x$8_xcQjPG(Y zEUQ4H`0+MFe{NRSC}?UYa>-ra>vQsCQO*YZ1(-Qlj?LLMg(%xX-NL5ud@(=YaR1IT zC2(tJZVP($?fG@Ys2){%I(aG}&L+8IZ6#}L+`u7DsV!MP(#R5Q5~nfjXP9sb2SU-` zHf^>nJWwF0vfskNDNtJx#t4)=R_~DKXI95GryXPp?_Mze4Y^1vZXnm!O#W6Ca2`{1 zT@?%NATL+2#33l^nFJu<0`k0t6&?ZgD++XUr!lmGt?>y#fIMNiB_%k&A3TG|JiJZP zG8#wcZ$X_XZ#iqZa!q?#t2jO*(_H}?mYeWzOe!@y(1RNn`}XWh0_O7=TaO>L2w{z$z25B-6kndLRkjvKox`-WzPhJ3p$CF7jU+~BP9JD2 zg#7|_xr`DH(br?LOl0;fZ@&<*+-uZ`VY*UK@BHCiUKXpRM)R>4VaN*kQ0qf!d1a8@ zDSM4Lp2+KSAVusu+xr)Q$@P>)LBivkrA|bs7ZBzYS6Zd4ADB*8KrMev>nZkrArn}?7?~262huw=)jnBE&dXzK`Cd9L=F5U> z*bM-PiCK&2edu;|aaeQCesI#w+bkvh#DvG|G{iwPWT;QZwx=oB^1_j!|;S!?Fy9udo|U>L)`* za&>YXJJvXmxKMe_Kjd!kVjp+=6i!>%dfY@G@5FZl_9A{>3?UQ|CsvJNkeFc>Sz#T{ zO)~*C<*qf0B~k?PE}X02q-+mSKezB)$eOSwhe{kSkx}ZXq5C(P%3H{KW@u`#T{KGZ zXXbrp%iM>U1)&zMO^6lm@P3}D>2sCB$j5NIGxM^x4r-VQfoi-o_7e7BoAw!eBe9*3 zF%fgi2B3$&iJSI{O5od^CL)yo!eRNUm4uBMTE6 zq*L-W25tIttSF7X4A!d{RKE{9nJcI3eNy00TOA&gBVtWGW1Uk41%w&QysJ(9o?@Ges!NLqk)Z4wfbG@a0~}NL zW=+PnR4o|WmoKL&RKJ<;Np#&Hgvtq>?c)p;j^RWxjZ_Yb&A+O%+qnxSCP-eC_J(yc z(29+fd7z9EcycYrBjJpXpY(^4#v9qgtBlJ*RMj)6hsqDkB&U(gPnLqK31}-?6gx&E zB$p-?Ddk@WXPY4YGHX+_KvHN0c$4^kSeSDg}Y1a2~ zC1-KaLnXC#A2?D||5=1i%)e25iPNHTHB~s-I;9#*J05a1fm+~VU3j>tjc<~~pr0L6 zq#?jkhZC2o*2W9YciIYdy5*HI|0oNMEQGPU7r8sM^7RYpcT9`K6Od|tU4#sU4CmJ` z5D$^!#q8|F>gi=z7FO6;yefF9eTwRy;c;B8X`$(mjRQvper?%=g@fD)pNW_;-64`| zp-Zh;5#~{K?86VA_qFNR1>l0A_lGds!t_T8G<)oq`44X@l-dO}$F z$wlO#x!a4K&=#4QgIzXJMof7oh0$dtXiW~hP_F8qeL6h*j$!r0cs z^D_#ho+-C!Mx(i#X%NT)o1@UCbtN=yunIR`t$(xtlcg4Fv&zjf3q!=P@KY#q-Wh($ z0RTqDc$|WU-i9@pfmQoI=$1Lg&U%J_V~B`P zj>j_!FMNyMkHm$2BRv-s#ekFkK+0+EeRwihqOABm3dzS(Ivk(fxo+!)m>CGl5rff5C;ikNXx2m;O;uc zI?K~1u$vfnbJ6UWh|Z!o+SQze>HRl*AFxxk(Y}j6JlIu*L=DDvDhztzVP5SfvAcw= zxOx)DhNe>?TNBWkbG_}8{c)MQnr^DSz-Mqzd@7?Rp#OeRZk44#Oorb2<^57deq~5q z9v8TNS_7cL$b8IBV>IJXrLSw=xCo2Xj{8z?wF#3eXn*cGk62w3ca{VxF`dd9;(x|LSt~0L_XBvJ zJfJ-!RihNcrV;?cu&R9j?MFE0)f)@LZdl~G#bkFmpCADw+Zm8MlZ1L0HiK;%am^vl zW>IZS8{3WVhY0Tn=$@rH--0@c^?43KJ}{#U#m-&{c!wKNBbP|bN##Vbv-P&#giKIw zGfKDcNu?t`TtG*fZGYAT!4ScRHuhe21Mketp<6I5 zSyDISr#_6h{rG@cXc6|2em2UP>4U}tB2M>Q)V9HA`|(*Z3)wTOQ?gldus%C~S>x_# zC2N#ac422Dwz@*+)?&ZgdTi}UaaXCm^hZ2o2Cj^EY@&f>1QSY~gusBoTXSl#%;chwK>K_m|D@9|dR4N+Lr3bOx zuhjkFC2!dZ`^ZyXlQ<{u-sRAGL~bip8Adf zV~;vX)9+;*#$E}L*F;*K6r9#6R;CncJqP7fnSzi!glM4Ix}KBH{5T%wK#bRTn7TU2)kbc!AM2(5Lw`$W+n^J}+Y zh|kwOV^VoFl3;b0U87{NrLFkM3asj6JiP1p^kw3Gtm8V#Br?M@yIGqG|61s7)3Non zzG)=1k2-HTyvB~RomlhMtkz$pYI=%+pQmUhBP9pi&@A<4D&j;h3qqAZWwWTATAXgX ziiwzRvNNZaSM#ajp8QqvGXw@mlHG>$cYPzB6B0T!t*FXT?eE`sLu~OB>@Cb6OFX^T zfCDIoeXA|v^B0iaXK2Q=yAReWs;a4BQ%^nrhDBwDq9UE#GizPyY>8_zzGV|AC&Okg z3Wo}C2Kb?4hho98yoC!k1ZDa*4m@bi@N{mH?wgWTqT+SLllc+8vw-(QBj>RZHFc(( zaR4P@evCBi^^AKR{5I%LJP{M-}`7C(w%o`Wx$}i>*$&?lthv^x1A~}?;tgc9~U}?BX6;!?m)S6DC)sI zrSbZKzmofB(brmLl-YV5evOS=@o9_+T3Le`Y&!_Sp#Ds-A;LRYgCg?-1Q`O}*e$b! zoOa7u6qm7SD_edS4PL{PggRTSFap1!rud`^HW`6G*KM0sxkx064$F6bcNB zT(+_v*63RL0U;xIWKS*bjEjp~MlaNanji}Nz_((A zi&pfdHsTX}VKS?(WDV6qk<9bZ3*JrEAs5{YOl!>2L#>^)1f6b^I3srIX3v&N(kT z4;6=8@#&N~zjk9J50mNg;Z}3xQ_!+5%F_M)~eK0pJC-xw_;)fsa;hT3;`Ug&-j+Qr4oOt_E zIy?|USV}`(>BPy2I7T*hu;E0mTI7hBv_yPz8euTEEBYBqGEczP!04b@ZhZ72Qn!Ng{_ z)6UhP?8^i();;*sm%dZ$!&$oAZ>Jo!SZo6LmGe-?4{_WF54o~?MxdinNzbh1HqWAXX6wXfV>-aNZH_7EFLQDR%IaV)+Kb4EM2aILW&=eGsD zT-RKtuN^OAcDTPP)Y@!5=cQV5eO1gOR?k^OZDSSCb| zg~>X>3I8us0|1}lf_0Bj27(Xi538v_APXfwxgMB?V5!`Ca#zy>c6cps?kw%+oP1mX zVRmd@$}&RyXcmNT6zKiSv!pcS(<#a}eGD2mAFpy~ar-&fW745iy6)ok5NJ$%?8JvFv6?RyE32br5O!{V?QIhl&V((YX1@y(R^ zV9I>d`Y-UDjTX_j%`-&ZrX?<8Jer9C(*v;YJa0=#U1UnCDRFmhmZthW7q)ZX|M75+F(R77fbH#aW zVgVH%m*;q1{P{l`(n?#WJ zkNLBWy-X@5UBK_Z?ozkD0<6CS+p_i(14SX#wB&wiC~z|nDwgF?X}LfhstDZ0UIWZe zzPd@-VmnlPJA%Tp&PhLcF~oCLQkK^#(!yNce#=-h?{yenqpOixo(}hb zMAaAz@LOg3!BQk<%Foc0XJODZ^dOLjNFXN$a+0;3f=V@N(qCzwA`PBJHKsl?EBVyC z1orHDrZ{Fn>c3L|Si+MZ+gZ4{%D=YGqximrH&utwGeo0q=S7ThT@~ZAN2RE^Rfffj zVHH?efkjv$D|4$Z#t{<#tYAiXgY5Lj25%D@6S-6k0CfL%gW?{*zvwSJJJ3z}1a(|8n6c?zU-h7}?pz`SPjTY0T;5zq>@q;Nd1K`9Y z$d#tU#IOih;l{oVIdS_sQ7<>24);}px|CDKz9QT@BLvGwyNrGRK(Cpu=+wknMC@&) zUs(3N`|I>)%y|3(XvZfo!JXn;lv(@pIr$>4-CoO% z;L4E%{yBpWCXgM81k?w4>ulz|=P|`QVeVN@yLkvtZV?J)65L15;3s4naBj#W2L=b) zl6-J?OT39X2LIISIlo~B3cp1Myd$7u zm1N1yX`v|&N%#QT@mc-YE;Jm}|5C_2`WFx_+|1^43$u+M0AQ$0g&ZF!7bpv}^ckju zi%)^9G$#Yfh|yLgbij)OOnFTca!ToJ;v8;v!;@Xbd&iYFKLzj8;bCRHby=8R*hOs! zAjk}cRT|cP2%RqmO+gP@JeUeQU^IBC)POaM+4K<^5MdYWvLhw2l)cHkZIE4bTU`at zuSYcAJ35s@e=XEzo{mIdMwGAYh+rMK2jd|T_AxtLm^4i`UZ_-tFh_@a#v=ZP?&dPZ zY3IKThj{bGPUNoY5OC9b`eXwemUCmK2uAg{{?VWQKMMR80J*k}B;JkVEqj`>eg|rG zSD6F_-Z`fjCLCcnJj*-SP(It(lvP;ny?DHz<6b278HJ`C~&CSWi&#N1*PDkCAS6E|Iu_(Uc1y@$K4j_cxE$`nM>Tp%E#wjPW6a z(TF4CVQUQWs3rGt+O4sb(A7B&Wv61;KWZ#+tVZG!VH~N`Bm^v=EmhC;~xXX5>k21OKL2oL&6c9Os}IH=i>X4XA4=dgd(KYm~}UP!60 zQ8UFj;ZPdX#%8VJRvIc9%Y9jSf)7Axnmh@SL`EVP;~yjEgkX!bZvD!-!+0*QP-wz6;j6~UcbdXSs)&a{$HK-10dVA&2Q=HXLc1jhER z%_nLlQ1pD<-dy+4nowcT&dd1OkIrqyz2cHCvaFz_Fg)a?xaV3g{>=y$lk|3p${9Ky z{Dpjp2~ZF+oqtj@VsXUZQdo+(FKg;7} z296DILk2@CTS zKm(R)Pf*Pen8@zvq3kPvQD9m*G*@FR9zN_{!s+cbaJMi5<~BG#;Y-}Jk0g17HtLe6 zRea**x$I5P;F{jLETUGP{)x-yx{({}m4W|dROYH{W@_+~B?`S=a_{xjLsZ~pf~QS9 ztALx}Ai(M3NJdHD;!badnf^5F2luIUfuus>V79o){tT|x6q7Ij9(HU0|MLFOoC_;1 z)>@CoQcF2DAkI{A7a~6JM}=KFPc88d-ak~DM)*Mb5c0+)^oIn(`(bFUg%uSgI5>?7 zNzmfOei&QcsqX~xAf5|O9JIZwr6J_lr|M^zAAfHV$VOXJ!coUHl%zIZe!#?_!09w= z@6_lhiNc|i1!~D_k z*>$!r?+NQw_b2!c>xEM(jYKO>JNRN}C@?$%X5teIE4b!^5W!|nt|H3nFG#~)W3&^p~2t6kptdfz`ezQgHhQ&{hL4cA0hgGU-`e3>XBeS zivEj12a~@?_-8?Yhvl$`@!ZJX{v&@64PYT^b;QAH4;ltbEhn-DV+^1>)PUk7(ogo0W+qCZIpYg9xpNaq37z6(M=AXaR z{5z10B&RjDzcqWulSC*G$gN8=6wwE5;E8!d}3Ew&B{`~glS++2DMx= z|2T9b4HVTzJ`bPG%x}ra+z1Msy=bMEmBE;ujZ(a`*}1Q*UAQ2;P_)6e+dt}AA}GCc zbet6W+BBha-n;4gnNJ{%&wE+tydOcOY5hm%sqou>Z-me8jO^RcvH$gBH^B9u8wh^) z-!J*UZlK7%jb6ShxptUY_92+U)4O-m;cYVG9g251;D4+)sYJR2LC4&_S~TliR~rT* z1MT}SyaY5GqID(Ks@PkSK3Fte!zJc9cMc|=oSK*PJ`pkr4!_x$&0iM|x=v#H z3~#p73?$ZQX3Ca-2%0yTe+haqFvQKXqF-y~Y8+m8)OZYwnniRym(Y3WGUgp_c;2iL zKj!LqA^>$n381+MHl3O>=RCnvZV2|u|4uXjG#eNi==ue&w|64X*&jehy}FE@{{oT; zhnj5W;$1gsc4CXz47*?vdk`a?&w0g%OFIYV4 z&VQFvfv3RwWOA@*%j>mr&V=d$wo65d>zCi8DtyX}8lJW4)b$zt!Hkr@K)HK|viIlb zjj{Zlxy|$Y*OZ2Hu?sfv)hMIK7Sq~M=V|_?tMxOmwu|{Z_`ykL%_R2R56gS`><*Iv z0r(WT=}6|MbFS987lDD$xhsE%-tGDny6FJ;2iNN5$0YoanN2-Rf;avJhRpq^`2FJ& z!TA9IyLdb_16;r(%8I(|tiMSR`!ys)iJfXA^Q#o)k@ zY_jD|R+ovlRGcJoYq)VKi!91AhYLl)r=GpseP6i|XlT!)s`LiJa{Ef$i@&W{A2g|vdu`k{2=HQ@ru%`BVQFpmC~raZ>w? z^v??I|LS|f9&kdkS3sRC0oR;oLYEVd^`Uhu-G?*pQ2#b>&O0{fI?m*8a9-d(U8`lX z2vKqCNgPPxO!G*5=x|@>lm}F*7&?M5gq>x?%#h|r#eb(3j%RPD0f+m?Sv>Bm%mp_O z53f}c89_&FgI+QM2X-n^T{n;V+Cdl9fPu-hQfKP1(2;BjpOwP$P9^h1W&rk_hIe4< z`YlyE2W;r)cqVgkDC_tL@p%4c!^#hDEMfdvX1O zkWtb80HlTcX!_f(B{;TtFW~BayN2?NOWp(USOtx>&S7Mjbt4RG0C&m0v7UgjxGFqx z?4g?1K(J-wqOf*K=wE=c!=v27Hf!8Oo9uEf?{L@iW_6lQnj%SeowX0C1GRF+Z~E^% z-X9kTpW7XhX&x9$Eq8`lWTR^6A7a@ZJln@slhbu`_xs#nvRqdqfgETBgdpRm8OJ$r zL<3$rLIhQONBCal2Z1ohpH|I!@+MYZ-wI@Hb)}R%E_+QVE_Npubr}6wJ_b9wJrh{SfEPd` z4O&tP!*!L!EYbcC6B5j9hhP5!Q0uqi)iI{Fu9-EwOG6H+nW!Fkxqo>#bC4;-6lP}7 zN&W@UJOAXEnQc)+r2n{0MRP7aax}_c7-cIWNlPidi(4CqdbZOXGT$5jCDUA>c)grp|o+T>#)a-PwdV)kmC82f|c zDRX>VfNX$Csj|FB9P`IKCc~sgG*`jxM!oV6U$^Ri_QhVy1#RiOPOZ)?C5#gK_^mtm zB9z8G`cjVd9S`Vye7ZH+ZLz z_K0T42wz2_>t=v2z_MeMFBj$|+c)fs2XT59OuKtopFc+PGp8a30RDMj^~0JnnI8h; z#-~23`wELA3z13aHuL!tq1(r|6}vZ!iJ?u4iosc?7n^W7TkM&M{w+cWR)PjaFA;LK zF1x!hWsb|JUcrwA7x%wyt=tmpN;E^yNFVraToTiM;5iU7o=X7r$BbT!gkgvQ*wlDPRPqs~X|Ru&BnQaGke60(Fzd z1XJz}Q1Z5}A$d6n_)M_CsLed!@CH;A^cN7~d~)xtwxQ&^`KpKo6^MEkx%`MyhOo_E z@P`A!I5Bh-;oMmi>@s-HYZPBMdurx7)RNHfjZSRM&+rYL-&>l*D`ey=RShMyociiF zG&I%OY;O)}-n}_OoQF@nx7zrf%a(iHsmD>g>P>iP&Xh0*Vew!sn@df-rf^coBrTb6 zKC020YWY5YZD`+CTMf-HCT$6gP5O9+r@Ms$T|9c{`|$o|^SbX!^6>5@s8s-#!RA!x za#Q+MewW5pHhgbC0mkfPm0ck`9A##7*8nTmSsiiCdOb#{Z#d0QdG1$nbpFuC*3mkS zL9CW9i||An+^~dD4$9k>%04CD7PKzheg?TO6s6;ErRw@N=P{{m^J$^o&?oV07zW`f zMk03TxkgtjwiAkb;RCVSjn<`645@a*QuW0MjyR&@(G=*QhL zHJ#bB#@s}ZN0utC>FHtQc zrpQ6O2f@%k?(VY1^T+aP28I#5Yi-JctK(hwY<^Ih}}Jw8g*DVW+vy&HK8T6K)(mOLfg?)-?B4Xh~BbD zalSC4s6{Q#(LRz7o)B7@nXQ`8*k&3+c@laGtk{l1UNS7wyxFJcb|JqT{i!vPQESIO zpXRmX6sEp+$DYyNNmFgI8hMakeH>y3O*A=a(aHSfps*x~p(ImliKTeMVgsW|vR`@p z7@7}OYHm{m&Me06`=ILR!GSU^Gn1Qsu3WH%&Nd#6u`duSs7I21SQ`FObtE~HC2re$ zd*a_Slcx^t)xgRV*$dJ0Ms-08PPgG{z9A<1W8bn=Qs^{EKri>n#Ljy{SK8q{Sp`j` zc1#vc5N^o(oLq2iycPy19Fxx9CM*hmM*0(wu6r4M)q=)Q#RNe~i8CfX&$NOa5vWhQ z6qMBZ`pe51OVWqBuPBGP=?;au>6d*p(l7~9K;Rp=aA8>N#PBmfm_0~Lng+NjaZ!bn z-ws@E*mkB+o=@UUt+Ni!>l%0#lkK~AKIl})y0&C4)&Di>W@~wG>vm#!w)v@IbWxct zv#_)BXjD5cu6(~vg}#Dscfw@e*=>`!Vz&YJR78j=-NScGAnW@xiro~}Zr;HGq2iAd z=6m*gsXnqTQ#1q2_-EaPK84O7o3Fp>>*(6Nt^LQpp0{3J+C7++)x6=43VHr2)yq|| zJ@0a}R52*{@)GfrqElvZw%Gm+Ab2FYLbt0~?7y4)4Ft2(fo; zJ`u$PMcogDdXkmwaCj_X7_3knc9Q-D1h8+b+(#CT`#x&h#ol@Q%tO91WqKxhb=DmH zAt4ph&;}ock~&wW2&;RvE^+Y)9a3yh04?%^L>R@dSKzv9IU^J&=qgcyoY+K zFwrsb3_B9-Ft7lIBacAK%Uo;=E@abMa%c9QC?JEno1c{bae* z@$zP4c`egmA6wfsgWmodHTbB9PWAY88wqS%i^k>DcP`QTix@+_fOtl>sToe$F3s!x z9p5$-JD#@4XRCxtvrCC6)%np;noEeIox|TJ=?*(>ir`&?r)t?14~M7YKx~@hiKu0h zVliG?+o+yM{qgW?d40zab*k>&=lrvF&zeEdz!JY{bm}fGJ417QtZXwLllplE9K$y9 zflO)aq?9eKUS#*2QRqV@ha1FuK4q4c?%Q-y;}JpBT@*jO;A z%jU;-b=K82%iZsR&RcC)F`E?!;L%&|!jphh&8F$$u@vY1WpF36ZW zLSO&m4*PZz)kK4J{9yLtxUm33@3`iAbE3D6w|}aQjfSO8>kN5X$z**vAZzU}pj*vx zzPwH=%xe1188ho@NJDi%?Ma|f0@>^HAaO_4H7s$52iG$tjK4Gh}^3 zPOVQQ|4u4JAa_mHYh+V@VD&ZJJ3u%m1H-JW|EU=wuW*l2^IN=rX_H4))m9J;Uxjyq zz^>f+y1^LbwdOvEaR`?jIy+j;_w&fPUh#=ACARn0zW$h?9o1)tZd16OUX#6K+4G38 z=&Lp={*;1a?)(UwuXR=}J^g?SRCzV(!98F2DKC>rhb0(F{UQH7Xkx^>4I~rp1hC$j zJSlFL?ibCCGd1VGOiU&wjJ@>$TIIeYJ){hL^BN^sIf2}@=w)&f5cd7`DqR6G*|i6X zQCWpy6}|4H7rio*;^nIZxw>3uY?k%jK+2{8>&SPri9(Y{c?iGqA6&-cSBe-TVBQC72IeZUUQgFdp9Z7cluA215*$DpWVhy^2W2fu%BEqN62xa5S}( zg~HBha}^3uBg_jcJPf^|1k3U~r7;AnPDK>3z=kwOA5|gJe6>ZsDAhi%&`!yE?3!_u%?8T(h|dJ#WqoZ4 zj(=a!UTaY5aPbFZ$+zfxf=!X~!#Ef+f1k~Bd#!{A%4PP4o2RA6Akj8+a()~PbZsI% z4FdaZ)9FEChI6?5<^21ktrUn|V2{N# zwk$rplO-iuJ8o%&vlSR&6|tsbUo{?m>dRtfSw1tF8R&@P!1Kl1G7HanRODuO7Nas| z@t!zWbCP?fU`=n=hmGBDy@ffuQ^h&kzFN&rN3n~kNCxG#`Y!ol=Zt~AH-UnZQ43>Z zqi?+x_shyRzFAU0!B8c{MEU@iIZ#--vf`v@V@MM(6%Zr>>u;H_u<|) zR8=0Gzz!q`qTYNC_)>xy3)TE}>04q%&@5<^(tE|1X7nGX1ZvFy!Spy<0iB^suZ|Uo;@$fJ*DIs;EVZ~7{X)G|8>WzP+p23m)yCa% z%3rqA`AlCQ+#=m9@sPPVd8cu`6Cw{vg3fDx^}uY08@^Iqx5 z*}x04{`5&acOel-|2o211M4U7tJ>76<+P$JGHe?FnxV=6j9l-F5=Tz7={8M2K>NXe zBY-BN4rrMqY?fe2#4>d+_89IbHNMLq94f9+aqzrHj4v#XV~;Lig2>2~TidRVDP?pi zZ~A>fn3y9JT5Xu|x2x9%+kHe=duLp&T48?yvbN|onJB9oPQpC1c=NbX;~AP6NcLAt zOWcaOBFcDRH|m-Hon9?m{Cf%F=jm zyQmd<&SobYso&xH=4pNLbuNw(JMNs&YadtPQ!H{Xe$B)SKgXjZXKRZ4k^NIZddsKG zsugaB<1tOi{}JxV;&(G%^FiErXm)&UzU)1JsiL~u($B4&`*AQUpC)Z5LY(^u~*~+Q)?m=0zA;J7Ilk&up^aQHlzu0ZYLvo%*q{8>R&}cA&aG}rmkF(h~*ZP z_tDLN@Q?y~6wcq7d()D`ZN5g+JTHHpLFO%8I|ME=^`c`3tQQ|R?=;QZ=@Kg4WxGz< zxHvpHHGmLGRrf5St5pF_Q&W$s*)A$Y zM8TYl%_GXA@t#||wf?(~5Eo($)G;Fu;ug_eIYYyBgVb@)t*7`|O!Cw}Fl&Au30bHD zW8$IIW->AV{S~qOPUa+Tp}XoqpWvN3?Jch5rEvb2XJ(9Vqh%E>1q99R6Joy^K$nlM zAuGCGlKNNQt>GL^Ii(oe{R9MnukTopbc?Y9O23k#UEHO2DNmv_+J&d+(rynW%|97% zCdrbX5l2eX40fz=ClTjL=KVar!9MAoPABv`HTeEJ#A}OufP^HQbrgUhI?= z>5#j;E)bX;Q_rkxKYMq{KGl%^rNrlJt0>C`-EfyiD7AgzvDoNZUn|NyzhhLzJAVBJ zYWQQ2u@k6@6I8}%^QBV%fErNfyiQ9u%JWLX^%#^kH=!A8uU%G5jQP5R8u+L|)Jr zN)&N53;$8=P+)W0&FJHeU3X<6`@BfZ6B_~gxj@;@!f{oP?CPQ93A&^8L(O!mO9yJz zyEnMQ9(ZeLrAM$+ia4u!PDhqy#bNX7^gkP88fLl!vIMxsULI8xcQIh z>`~D|HeV051j%V=vR*}6N|6+Y5eZhi+5>?9^@TKvqe(tAOF?{ z004Jy3+qaJXlHdoiss8fzui;*T1|6w=G@V}_!D+z5$sOCl~oKoCSAuaU;dXP3pMwD zbWgT_+8AsnzWuJ2n3yHsKUf<@MdP>~$e+j=vjGd1?xz_q%WgQ+gIlz*ycQ>kbcqJ7 zhK6!QJn|@m6!ZA==@6g`EK#gb+%BFXn{EUd#ZE}8{2{=Ve)-CsyQCGskA-S9(^}yz zE^@2Nc@r*5MAXf&3T_nsC zc1@pcPdIZsh^e(&duUsB%cIOrwyi$8nk^s>#H|y?&1y2l_G*}Obxm``s&$1^uJKM8 z?e<>pl3&BvnBN(ViwF96)7sSSOeVo#E+_V=#kk^M+kes?Lq(F;gXzaa{TV1gTu}~U zC0Y1k&a%hMEgn55?}DRDf>YsQGteP-i(JICX8_y+heo4}D~7niy5hEi0v+F6>+sD{ z*qWZAil-#WaBq2oA3^r=^T{nmvent%m4-jFi%LL7toU(>@l8)9UPJKCX_&Jjw&?Tq zDX6-+sX^|V+{ACU#G68cPQ}&c%kHGTM_V6Vi0%p`I(OrCn}jr<*{%SnDZB#ZiK}Hy z*h>ytyEr5|636QtlR;;Oi+RA83M;yFB&{}u*nf0{evlrIvHYnQVK$$Nd9>97x_n(w z#qu)#M_~!CIm=^Lpm3Uxgdu9VzgQe^*m%<_Q z`6LnCTCKk)ofCK_$HMNbd_Ltd@09ISE!{D?ytaS-htU=%|Jojj#%WV67xo+0d^ZBT zKq5h4P+LGA1(ZgM>^hLid6-~gvD~Q&6p1fmQPJH%;iAXTA0`W>UJaC2dw>SMsYZA? zo$`Egn&TfpIZsYB_juwK)>MSn^%gw*4;9JINL#Z%J?G1%n<+KEcX)2BzLj8<2rp-0 z6%1#6<)eDyC+xh2-0riRzvjjI%C(y}lW4($&fHEDh1^K|=9|_KR^VapdRo-^6~kPb zWuww#XkhH#nr4EuL=C8_?hHj2XyQsSLhl|Az@9=mZt}APKXiZyzrW23xY`o_=<+21 zjs4^7FOOhbY7PX>o7Yz+{gzJtA?RdtYRTDQy{6 zUZebq^0(U+tT~@^M27n}zNPOuy3n%og^rHnF15Af=L?1r@k1<3NP3AO_%lN{|FX@# zmhwTATtGgF{vqf~L}t;bhUy@|z6?5s|Qp>f9e`ETi69vH3G|{_-Oy zd4qng=>7HZmby1^(0md*D4Ae+cK`L6mX&1he4To_$Mwd^rSLFv5y!b8#>U!XLC>s$pt#p4)HmEPqB`I;9zz-S=Gks)_S@?L%y6A~eMK|H}s-r@MfiuJ2YBL-oGJG$- ze@JKv?h?6JrI#gR#wlcz?}>pWyI>iO^UNlCdGwfdWr`CNr#JDS+M5w**U0Gcg4+u` zRdwcOsuknzBd=h<5ygu{_>vp1gWKHvSErf%e9~zQGr}F^srxG4P`a=l_g(^=<3fHz zu(gz*F`yIZPUN__H978Tq0NzO-uc`Vjc8Eg$fCAVXlP@bO*Wm9S*$AT54zqP<6G2{23f*SqQjHgw`y0 z%SZekfqNb>H9na_*jn4Z>ynFb^M?C2Tp}*Zxt|=#?=5(MxXaBfABuw|SE@~Rb37cz zSDZxM;FSqv8mRso2qd7EZoqs2$H0lnk=cJt-w}t# z{Ddo#41c(DWD{DvSFd@y?Dc-nsTe`Z$bTGPB)4IZwIz6*+BBr*Wl(>E0q+rtHh{V=1v2y<2p`fkSD=cn z9#a9~p+cKAmpcV!ok2@8m)znILPM@`FtF+zcW+&JDeB70BgOT8zJ&JcWhVzb=!wbS zE>lvJnk2oic#fp*X3U3(1E?Ket>VL%PTqLCImv+OtMV&5gnB4%oAK|=iRK?MYbr)^ z&zlw3Zk*-VW*acO|9Hy_;@0h!11o;3+_9P|K72s%&v>IPAJpy~*f_>OE<}!;-txy! zh4$w%&c;q z^2Pt3qvyN!Bt`God3>YYM)?07JqhoM%^UyU(U1QvcJuh&0V`TyBUv3x)tDVQy`A`Z zm=aVb4A-v}?1{}An{S-=piU7=U6eX;gVh0RLcLxeyRGEEcb4H@Z>Mxr4rrL=QZ6UnLducfd3g0cP8~B;tI7MHazhwvAWlgJvM)=)N=&z zFBK5&rK-j@Jpi;_p-r+cyJVvO;>ksACsVUMH74;KrI)3am7&|?)3R+kI<3upW=ICk zmwwai3wFHQ+fh_>dQsgAtO~qauGrm++RVXbq?e40`M8c(`U{{ho?F?`=h;!^F-|wf z$P>>N$NmDY|EQp#lL(U$WyCJRTb{-E+iva%DANuJX_{=rS8jfdPE68s!r@-D_F zd_hUy4AcC;%lL&GK&^DD`D>zyM3aIZE&FsGFo~2mRAg65vO-Zyw&}tr7V^}6xtQB{ z>HbH{Sh`kY1&E3`Pz~(%X(+n*8)q!Z=3A|e@3nt`jceYoYxNjVLqR!-IA(Mwfh?T6 z0E*qX*xqC4UbPBWc5(IhFzm51lt|qRYqq5Un?)y3e&w z%x`E{;(_*DOnjP6i2Dn`Fy)nH$!Ko4!jjjvRP;H8sxJ596J5x;5f&~9%7^rPs_Uz& z28>^>PEaA2=3?EFq~|R)ivm{dfN3w-{_A)VN>y3aN8q%0tkXfzGr2*cmwBf`ziX5! z(WQ3p%V6NEEwbrV|6*G;nryUfb#qkaE@?#GWvlGvLfGcibK0~NF8QGWBbEdxtjrzp zFc}}fpJe#Q$&zWmxmvN9VbQe~(T%n!D#**Ltr)L864#b2@*8!y*H+`JsDV2{1w1&J0jA7MYHXlIma29Ka@~)HH#3y|AM%@Jx98mr4KZiWTi1Wfmw+anBJZGj_ z&em$OpL01HM(-lYHN48N1XOUKfMhlNXd%hgg^2FEZ)^xN!w=a#FN$&))rSRrKmw#h$+{St|%G#E*W4~#V$Y13E40jGX71) z)#V%(^rL_nXBzs#VyDaEN<`MYqc`#8>6t8}0mqEllTbqLI*oYuR_UtH99Tj4a5lTH zDrr906;YI8q5m$)tT5Uh>`0`Iast~lEb;)Q>if9w4p!1f?dv~`fIFQ0p<%;k}PLZU^eVHa9-Ugjmqx1)Y3-#3;?AfYp<=HsmAH?1RGElEBj#QF9Jla1y4qk*%-0ih-l-o#)(YF6W?qG)tQ_`{RQCm6-4T5pSWDNqR`2A>(jT^1;)m1m+Yv@cJGKyKbOI#VsqVnmu9N6 z7J_zUBW&-?#~O0XW$-7|G}xU5#AcEE+OoF$E-fedoH$Qe?{%Q7BWp59q&wW}hp(|Oc zcVyUSqp5hrIhU>Rhw%k&k1{Onf}JaPB;=;TyJ#5x0;V_!&I4bSJz{TNAOAD(odbPt zW9{oGHt@RB3A&X>P)q`9Jxd&{GB~;DsM>;LHo1of3y1vv+-?8`U!@e>G)?m6$beKs z?8hr`ktGJiYR5r(1G4`!aRtL}1G6~0#q9C=E}FYxwuqtv2*^VMagvlDvjWnryEOk}$PJ98O~HVI#AH9UB)DG^XUiJ_iUQcEJ`uK| zc5WA!?9DYXP1k6O9ucZG6-w^)Y6dY(!A$FEle6~-P2XOW>gFB4ojQp;Nr9JFm0__k z3ocX>06&pVyfg!u&KN+2t(ndvU3jPABq3;l|$DV|sFHz|1 z@z|W`=i-_-Y}7<2z7I($h5WpgKbuI8-`=&!F)i+AhYc_FsnGISCFhM4Kg%)hd0p+G z)b=n-hBKf=xW+m+j9^NzkFyn*I1tw}^yp^fgT$z0bTCN$t7jD|9NT!yvNt`HJK?n2uW2pFmNnjg z{zQuqd%doQ6+J#+H`_YK|JHSB&6y+ye3>0xE&Lv)^ZHTnI42c@dhy>p40Y2|Ssnkq z15gzd|M$&*FK2VRZAv}Y=DiX&QxYK1s1To!xd!)D|y8lggJgY2C{iL*(mf_RR9iB zO^SYnJl9|$W_KFd338x4B4HkO@Rw&tRAD}nk;%feq<`_txI3$;Sqd*ivCu8HmuiZy z2Wl|AWh-QK4P zuju|yO3XKimH4!OisH61k+Iw&^Um1D=pj$sVHfo6K%d%vQAbGj{9fE6k0A5K0o?2& z!9#v9Vf7z{L&t|Mto_ltH-LzhFQ1|&Y_iiuAKjklHXy&$ghG^adaFA z4PANxEFbss&kW_5sO+pZQt@6xy-40SdyOuNZiu>Eh@EmQg}F!*W}TUwE%&cD$dBL7 zG_nUF4Rf6gNk53C1zFe8hUv$j;$9|-FSjbd7vh}(#nN>$@DMc839ee2jeYy$iIfyI z@uYgerp66wntmuuMI4pk9uf2AS51fJLqk1;LqwK@u;+lhoW2LH(bEs5M`k|Q!Ycj( z0E$?VBp;T<_Lt(K!2MMty>a&v+R%!_1K!H`z)YhTq#bYh!oi`;J2&(a9qlb*^&PtQ zTN_7>B8mX9wo^46yPGCR98>fN$MqW7Du!aoKkH40I~_DdY=PCX&baK0UB}p(zACBH zQLz6Va&SpvevhEL9kZ_Q{F#TK(lJ-VG+Y zq}_F5z;&+_Yd;jXsc7+zG_Y-nZ1FiP%d*gMUq~qPv${)-1-Mte&u{$Mxf+Yz=eZjs zBG758Bw(szu_JyE`;qXSv{VJnRd@4IOJKIYl?B4o z4)se?%%3R>poN>W>YFt~G~}D+;Gz7Gfm^FIzc2j--1@wF_ud8l9O3>%2ASXo9T_t1 z(&C!IukPESWmL&2{y)o9+xUProXi~biJV6cVrC{L%4VCJ&DifF zL;NLm<}}$CSC26gzDcp)8p->tA^x(hXQD0ssjTu#sbKwIGiSd1D?s@}*B$TE`d}I! zPx|Euj=Jd`!dJlO9{0pG4#{31GrEf&75c_tu+Lr+|y^DNm`om{j3wL*{ zSV8ShV(YIvCKu1EiW*jrZ=<%53<$5;grzmonaR8xIjk{ZA%lJ~a_OYeB<2@;=E5Cf zp=Ml?vwfKf{}+ga%B}kr1sC%lS2b5${hZ%ItC)Rz?8?PkpT7TVu^Csl??n!~C0?^W z{88p>=kBn5Ol>=002yE0o?+ec&`{C2n{#d(d(NVAs4r(iT)0Q&_vJU{%(!=qCu5cp zUpXoxd`wTj+0+PRPQVpUS+1>kX#`lR8he`~ljjGDT-HW1zBJ-qj~5BXB}{k?A75^i ztk`Y6UCScbV_E=-b4lQG&8?VkN@<5N`B^RUjnBP32`Sob1YC1cG7`I;FccG@o8(?P znWw9~6wm}Ico($@!xnKCg#v|0#k9_f={W#uXRj?&h+E|g6e8cV-AJMD0Z-dhW66@J zaX$Evjep6;weu#Vb^p1+k;EC}#BXkNPVX}b6mCJK!sGDC?del+4)hBhXH0adLU>Sc1iq$BNlNJCJ+m;~5|`EM+zGfHe|xop zn+wH2+yhido=8^7-`~K_$$^8wBg|BVNzxl}(+&IlI{|6Yqvu*hI*1fa*7e zBpW*u)3mK?GSZW{U{m6}w43cvhaYM(K(DH8CdU4{6e6^u5-tceX~=eH<)eJ)C-;)4de z#XjefLtX`KOJp%_AWX^L%_x#p4!sw&H;Adu&f&&yT=FnVvth9?dbbc2ci3=Ud$ZP= z&+&^e1U&M@_w&B>y@er1IvF2JT9=(6*{*CGD};G9uPMy>oN;{W*v$JogIGtIGCr-q zP`n_w<|12x7tL1oAL-BK37pTslSw&8+A3D%*teW1GZ@2M*FE)$5_W{0qV8PP!iR_y z??^9y2;X!1a8WK2qwzt0=Pbx<2ef7C=`DS+&eSTE@aBYHEGLK6ex-r?h>Tgg9w3mu zJGbG{ieZ7SQS@@32EH?K;p9ozxnC@jo+&@%k=vGt(rnVX4UtFPO=3hoh5Z^WkhB@T z&)hnFsp%E|Qf_d`cr63)-uN>}#D>*}jVIu%2C!>v5jM<^hC(Kip6cBvZg?7q+}FnN zMqeIw7Lupc)khh`-gM@$VP|U!`~141Exv@q{?#_|vaS$<1Ca3;eCLtQ;+@ z^$T_6O~C)p-!b_?4hkM2$4114Z}(5BxSi;FAP%+k$VM&Yn(T9$hT%zW7;N5g@?Svg z1M1+JR*S!ASO1=&<=~({)q&~Em~;Var1%GF{(1K7Qfe>&5ZfEH!waECl>#d5xeW;W zF~J-U{iPYI^!90EG}V$&Jr>HhloOwGedC`1Q+uC#QByvp9ZMc8_edS87lvXq?;Bw{ zLt31!vIG+yZy3YB#j`PIBI#at8Y+6Mb$sFEeEjCc%>>|+FIU5EQ$+)UpP6$0maKi0 z)kqGgxff|8C+0+2wO7MmXUEpupU=y9(Ar~;lew+}U6JSwM{NR1d zu>C2mVH{4~O>xr7Jl3_=c!4jwsY|i27VIFSjfKhxSdhRK>m{a1*~MEIf5+<)oxg5+ zSJf>sS9O={^gb<;D6BPN3C1YKi_M&}b0x127UoYxCHQ>+J4s@K=?9AaN+k;_6I7(! zv-g65N+~i=8Q02F)#wi9C?|~hdoFozV|cu+7n$D7Z5BX2zMFKvacvcB_r0OuJ$ z#xzwFR{1UMY+lxAvUv=CXv>WIZ09Al1BQi-#F}IqK4NvD~!2rM~nR zFq&MR$n2rbi*?yZd~Q_(`tV$$VrbU2O=VHMTUwuwDFXWvaWY=eU+B9t$QWqeTdXaN zILxrUR9KmEk--!346Hn)F&*WXs#ZfEQtH*jHi00le3v{BiZyCA0Vi`i$mn;=9vVfNeGO}CTVr$=0Dp5sk+mFg8$6E1(S4C6V%?E2qC zuq!B@3SxvQS%N((rP2y;!tJG&MIImZUgBX3mcA6(rZ0Y8oxZ*DMVb)Jg{u7R?%j@gNW8>+zZ#UO>E2hnJXloLBe z3R7%nP+_!le}hh1#Zx{ene?*GghWjd^fNE;Nb}9K`O)vN=3FG^xBPa*soeHb=%F-Y zo+M?d=qelt+1Cz!#%sG{A99`j{4$3bfd(>^KT4uKHx=aRKb;M_b6%9b*j#cUU)AU@ z0K&Ru*M+3=GqliAcj@hZBDLi1SjqndBnvio1%y{0U1$(@t-f!Hb@LfV1evJGFI_Is zn*21yMx;|d(wW-0c6?zeSktch|KrONl?>9PW?6n{E-csy5Xc^@uZ3|`Emoub)*)&H#Eunrax#J--B(1#LACy6WFOBC ze_P+@{5-#^H{hT$F@0cEs_I;rGWb!wJh{}raJWxYJi=r z-!BbMx#fqX+S=@km)8_G%P52RmhLkDW}blTfA7WEZL`Qsb@I*PfTHQoE)L1h_T=FY zo>oHUiM+U$Ohzc)UY{>jHXt*1!!34#KWR&aJ=SvXxuR<^IXY543&4 z@#2U38=O;sWH7yOsJYFjATv%$suqiBUSg0ZM~<-GmkP9zSa&{pp*Z7hyct}RR=i-P z#AM1pqgt;RdkWVJF~E@!e!sd^Y@YSP*_d(9x(XP>^cBK^rl zHlrLoSuWXNt+oM2W0F6Zv{Ca7C_OxN^cq{S#J5yr{?IheWgAtVv{;Z45b*L;Gk0e) zKXU*TKZzZz@r}dtSeIxRg&Vz5;Hxf=MH(6VSNRD_V&<*c&3tP##n1k6%+%mEGPM3W zF|Yn4jwH35RyT8SpFVF%MU4bXmhVWa2L|Ta^`b$)ew&L}I|M6DpOj3#%vKVjQ=v`X z(wlR+VE4~yw3FsC@5i_LrXDw(5c~R4BJdkD{YezDM%gvHk97C`TtJji#HtY1x_l%D zeUm#nnJ_=TlP@3t9P{C&!iBZz^70=UIDL+b%DI{Ou1`p%%uc8@!*3KxZDb=)<+z`< z-eYFgeCFS0qIR`^h@`n#sPF%U>TeZ;+LRj%i|6Z�?^jqp+9`f2}4ePP0S5mHgTz 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 C{{0OA literal 0 HcmV?d00001 diff --git a/examples/screenshots/webgl_buffergeometry_compression.jpg b/examples/screenshots/webgl_buffergeometry_compression.jpg deleted file mode 100644 index 4da713d915df6ad60b5adff074444173aeaf52f8..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12213 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 Urq)mRcS-)g`Sd@341yp34~<~b82|tP diff --git a/examples/screenshots/webgl_geometry_sdf.jpg b/examples/screenshots/webgl_geometry_sdf.jpg deleted file mode 100644 index 82d8696fd181dde3b28491ba1a6abfdcdcb6053c..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 12088 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
  • b*eBlgSWDDB*Lhb>rep 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 b{{Q~!H{+4JH~q5q{=K`ZemD5>`c?i9IsVow literal 0 HcmV?d00001 diff --git a/examples/models/gltf/readyplayer.me.glb b/examples/models/gltf/readyplayer.me.glb new file mode 100644 index 0000000000000000000000000000000000000000..191f8035c711f02bb7929fb7abbbe4cdbc134ca2 GIT binary patch literal 1838884 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

  • BKWc1w#9OZK8S!|9xtxu--I)!H~ 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