@luminocity/lemonate-engine 26.4.8 → 26.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,10 +1,11 @@
1
1
  import { tools as tools$1, Field, EventEmitter, Proxifier, Block, Script, TemplateFactory, getDatatypeByName, InvalidArgumentException, LoaderException, InvalidStateException, ItemVisibility, QuotaExceededException, ApiClient, Storage } from '@luminocity/lemonate-gateway';
2
2
  export * from '@luminocity/lemonate-gateway';
3
3
  import * as THREE from 'three';
4
- import { Vector3, Object3D, BufferGeometry, MeshBasicMaterial, Mesh, BufferAttribute, BoxGeometry, CylinderGeometry, Raycaster, Quaternion, Euler, Matrix4, LineBasicMaterial, Float32BufferAttribute, OctahedronGeometry, Line, TorusGeometry, SphereGeometry, PlaneGeometry, DoubleSide, Vector2, LineSegments, Box3, TrianglesDrawMode, TriangleFanDrawMode, TriangleStripDrawMode, EdgesGeometry, Uint16BufferAttribute, Color, PointLightHelper as PointLightHelper$1, DirectionalLightHelper as DirectionalLightHelper$1, SpotLightHelper as SpotLightHelper$1, HemisphereLightHelper as HemisphereLightHelper$1, CameraHelper as CameraHelper$1, AxesHelper, Scene, SkinnedMesh, CanvasTexture, RepeatWrapping, LinearFilter, UnsignedIntType, UnsignedByteType, FloatType, HalfFloatType, PMREMGenerator, Vector4, ShaderMaterial, OrthographicCamera, AddEquation, OneMinusSrcAlphaFactor, SrcAlphaFactor, CustomBlending, DataTextureLoader, DataUtils, LinearSRGBColorSpace, AudioLoader, NoColorSpace, SRGBColorSpace, ImageBitmapLoader, TextureLoader, NoBlending, Uniform, RGBADepthPacking, PerspectiveCamera, Clock as Clock$1, UniformsUtils, GLSL3, WebGLRenderTarget, RGBAFormat, NearestFilter, MeshNormalMaterial, MeshDepthMaterial, DataTexture, RedFormat, RGFormat, REVISION, LessDepth, GreaterDepth, GreaterEqualDepth, LessEqualDepth, NotEqualDepth, EqualDepth, AlwaysDepth, NeverDepth, IcosahedronGeometry, Light, DepthTexture, DepthFormat, LinearMipMapLinearFilter, MirroredRepeatWrapping, ClampToEdgeWrapping, LinearMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipMapNearestFilter, FileLoader, GLSL1, SpriteMaterial, Loader, MeshPhysicalMaterial, Points, PointsMaterial, MeshToonMaterial, MeshMatcapMaterial, MeshLambertMaterial, MeshPhongMaterial, Matrix3, TangentSpaceNormalMap, ObjectSpaceNormalMap, FrontSide, BackSide, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NormalBlending, SrcAlphaSaturateFactor, OneMinusDstColorFactor, DstColorFactor, OneMinusDstAlphaFactor, DstAlphaFactor, OneMinusSrcColorFactor, SrcColorFactor, OneFactor, ZeroFactor, MaxEquation, MinEquation, ReverseSubtractEquation, SubtractEquation, AddOperation, MixOperation, MultiplyOperation, Group, Material, LoaderUtils, SpotLight, PointLight, DirectionalLight, InstancedMesh, InstancedBufferAttribute, InterleavedBuffer, InterleavedBufferAttribute, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestMipmapNearestFilter, MeshStandardMaterial, PropertyBinding, LineLoop, MathUtils, Skeleton, AnimationClip, Bone, InterpolateDiscrete, InterpolateLinear, Texture, VectorKeyframeTrack, NumberKeyframeTrack, QuaternionKeyframeTrack, ColorManagement, Interpolant, Sphere, Curve, EquirectangularReflectionMapping, AmbientLight, ShapeUtils, CompressedCubeTexture, CompressedArrayTexture, CompressedTexture, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_BPTC_Format, RED_GREEN_RGTC2_Format, SIGNED_RED_GREEN_RGTC2_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, RGBA_S3TC_DXT3_Format, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_4x4_Format, SIGNED_RG11_EAC_Format, RG11_EAC_Format, SIGNED_R11_EAC_Format, R11_EAC_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, RGBFormat, UnsignedInt101111Type, UnsignedInt5999Type, Data3DTexture, RGB_PVRTC_4BPPV1_Format, RGB_ETC1_Format, RGBA_S3TC_DXT5_Format, RGB_BPTC_UNSIGNED_Format, LOD as LOD$1, Sprite, WebGLRenderer, VSMShadowMap, PCFSoftShadowMap, PCFShadowMap, BasicShadowMap, ReinhardToneMapping, LoadingManager as LoadingManager$1, ACESFilmicToneMapping, CineonToneMapping, LinearToneMapping, NoToneMapping, SkeletonHelper, AnimationMixer, LoopOnce, LoopRepeat, HemisphereLight, Camera, ShapePath, ExtrudeGeometry, ConeGeometry, RingGeometry, ShaderChunk, RawShaderMaterial, Audio, PositionalAudio, DynamicDrawUsage, EventDispatcher, MOUSE, TOUCH, Spherical, VideoTexture, AudioListener, Source, ImageUtils, NearestMipMapLinearFilter } from 'three';
4
+ import { Vector3, Object3D, BufferGeometry, MeshBasicMaterial, Mesh, BufferAttribute, BoxGeometry, CylinderGeometry, Raycaster, Quaternion, Euler, Matrix4, LineBasicMaterial, Float32BufferAttribute, OctahedronGeometry, Line, TorusGeometry, SphereGeometry, PlaneGeometry, DoubleSide, Vector2, LineSegments, Box3, TrianglesDrawMode, TriangleFanDrawMode, TriangleStripDrawMode, EdgesGeometry, Uint16BufferAttribute, Color, PointLightHelper as PointLightHelper$1, DirectionalLightHelper as DirectionalLightHelper$1, SpotLightHelper as SpotLightHelper$1, HemisphereLightHelper as HemisphereLightHelper$1, CameraHelper as CameraHelper$1, AxesHelper, Scene, SkinnedMesh, CanvasTexture, RepeatWrapping, LinearFilter, UnsignedIntType, UnsignedByteType, FloatType, HalfFloatType, PMREMGenerator, Vector4, ShaderMaterial, OrthographicCamera, AddEquation, OneMinusSrcAlphaFactor, SrcAlphaFactor, CustomBlending, DataTextureLoader, DataUtils, LinearSRGBColorSpace, AudioLoader, NoColorSpace, SRGBColorSpace, ImageBitmapLoader, TextureLoader, NoBlending, Uniform, RGBADepthPacking, PerspectiveCamera, Timer as Timer$1, UniformsUtils, GLSL3, WebGLRenderTarget, RGBAFormat, NearestFilter, MeshNormalMaterial, MeshDepthMaterial, DataTexture, RedFormat, RGFormat, REVISION, LessDepth, GreaterDepth, GreaterEqualDepth, LessEqualDepth, NotEqualDepth, EqualDepth, AlwaysDepth, NeverDepth, IcosahedronGeometry, Light, DepthTexture, DepthFormat, LinearMipMapLinearFilter, MirroredRepeatWrapping, ClampToEdgeWrapping, LinearMipMapNearestFilter, NearestMipmapLinearFilter, NearestMipMapNearestFilter, FileLoader, GLSL1, SpriteMaterial, Loader, MeshPhysicalMaterial, Points, PointsMaterial, MeshToonMaterial, MeshMatcapMaterial, MeshLambertMaterial, MeshPhongMaterial, Matrix3, TangentSpaceNormalMap, ObjectSpaceNormalMap, FrontSide, BackSide, MultiplyBlending, SubtractiveBlending, AdditiveBlending, NormalBlending, SrcAlphaSaturateFactor, OneMinusDstColorFactor, DstColorFactor, OneMinusDstAlphaFactor, DstAlphaFactor, OneMinusSrcColorFactor, SrcColorFactor, OneFactor, ZeroFactor, MaxEquation, MinEquation, ReverseSubtractEquation, SubtractEquation, AddOperation, MixOperation, MultiplyOperation, Group, Material, LoaderUtils, SpotLight, PointLight, DirectionalLight, InstancedMesh, InstancedBufferAttribute, InterleavedBuffer, InterleavedBufferAttribute, LinearMipmapLinearFilter, LinearMipmapNearestFilter, NearestMipmapNearestFilter, MeshStandardMaterial, PropertyBinding, LineLoop, MathUtils, Skeleton, AnimationClip, Bone, InterpolateDiscrete, InterpolateLinear, Texture, VectorKeyframeTrack, NumberKeyframeTrack, QuaternionKeyframeTrack, ColorManagement, Interpolant, Sphere, Curve, EquirectangularReflectionMapping, AmbientLight, ShapeUtils, CompressedCubeTexture, CompressedArrayTexture, CompressedTexture, RGBA_PVRTC_2BPPV1_Format, RGBA_PVRTC_4BPPV1_Format, RGBA_BPTC_Format, RED_GREEN_RGTC2_Format, SIGNED_RED_GREEN_RGTC2_Format, RED_RGTC1_Format, SIGNED_RED_RGTC1_Format, RGBA_S3TC_DXT5_Format, RGB_S3TC_DXT1_Format, RGBA_S3TC_DXT1_Format, RGBA_ASTC_6x6_Format, RGBA_ASTC_4x4_Format, SIGNED_RG11_EAC_Format, RG11_EAC_Format, SIGNED_R11_EAC_Format, R11_EAC_Format, RGB_ETC2_Format, RGBA_ETC2_EAC_Format, RGBFormat, UnsignedInt101111Type, UnsignedInt5999Type, UnsignedShortType, Data3DTexture, RGB_PVRTC_4BPPV1_Format, RGB_ETC1_Format, RGB_BPTC_UNSIGNED_Format, LOD as LOD$1, UniformsLib, UniformsGroup, Compatibility, Sprite, WebGLRenderer, VSMShadowMap, PCFSoftShadowMap, PCFShadowMap, BasicShadowMap, ReinhardToneMapping, LoadingManager as LoadingManager$1, ACESFilmicToneMapping, CineonToneMapping, LinearToneMapping, NoToneMapping, SkeletonHelper, AnimationMixer, LoopOnce, LoopRepeat, HemisphereLight, Camera, ShapePath, ExtrudeGeometry, ConeGeometry, RingGeometry, ShaderChunk, RawShaderMaterial, Audio, PositionalAudio, DynamicDrawUsage, EventDispatcher, MOUSE, TOUCH, Spherical, VideoTexture, AudioListener, Source, ImageUtils, NearestMipMapLinearFilter } from 'three';
5
5
  import { diff } from 'deep-diff';
6
6
  import * as opentype from 'opentype.js';
7
- import { WebGPURenderer } from 'three/webgpu';
7
+ import { workingToColorSpace, context, reference, fog, densityFogFactor, rangeFogFactor, cubeTexture, texture } from 'three/tsl';
8
+ import { NodeFrame, WebGLCapabilities, InspectorBase, BasicNodeLibrary, Lighting, NodeUtils, GLSLNodeBuilder } from 'three/webgpu';
8
9
  import { WebIO } from '@gltf-transform/core';
9
10
  import { KHRDracoMeshCompression } from '@gltf-transform/extensions';
10
11
 
@@ -6187,8 +6188,7 @@ function mergeGeometries$1( geometries, useGroups = false ) {
6187
6188
  for ( const name in morphAttributes ) {
6188
6189
 
6189
6190
  const numMorphTargets = morphAttributes[ name ][ 0 ].length;
6190
-
6191
- if ( numMorphTargets === 0 ) break;
6191
+ if ( numMorphTargets === 0 ) continue;
6192
6192
 
6193
6193
  mergedGeometry.morphAttributes = mergedGeometry.morphAttributes || {};
6194
6194
  mergedGeometry.morphAttributes[ name ] = [];
@@ -11390,12 +11390,12 @@ class Item extends EventEmitter {
11390
11390
  }
11391
11391
  }
11392
11392
 
11393
- var engine$1 = "26.4.8";
11393
+ var engine$1 = "26.5.0";
11394
11394
  var bullet = "3.26";
11395
11395
  var lua = "5.4.3";
11396
11396
  var packageVersionInfo = {
11397
11397
  engine: engine$1,
11398
- "three.js": "0.182.0",
11398
+ "three.js": "0.184.0",
11399
11399
  bullet: bullet,
11400
11400
  lua: lua
11401
11401
  };
@@ -11493,7 +11493,7 @@ class HDRLoader extends DataTextureLoader {
11493
11493
 
11494
11494
  s += chunk; len += chunk.length;
11495
11495
  p += chunkSize;
11496
- chunk += String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) );
11496
+ chunk = String.fromCharCode.apply( null, new Uint16Array( buffer.subarray( p, p + chunkSize ) ) );
11497
11497
 
11498
11498
  }
11499
11499
 
@@ -17928,7 +17928,7 @@ class ComposerNodeClass {
17928
17928
  webGlRenderer;
17929
17929
  connections = [];
17930
17930
  dependencies = new Map();
17931
- clock;
17931
+ timer = new Timer$1();
17932
17932
  nameField;
17933
17933
  name = "";
17934
17934
  extendBaseShader = false;
@@ -17948,12 +17948,7 @@ class ComposerNodeClass {
17948
17948
  this.engine = engine;
17949
17949
  this.renderer = this.engine.renderer;
17950
17950
  this.webGlRenderer = this.renderer.webGlRenderer;
17951
- this.connections = [];
17952
- this.dependencies = new Map();
17953
- this.clock = new Clock$1();
17954
17951
  this.nameField = this.block.getField("Name");
17955
- this.extendBaseShader = false;
17956
- this.blendMode = null;
17957
17952
  }
17958
17953
  dispose() {
17959
17954
  if (this.fsQuad) {
@@ -18092,7 +18087,7 @@ class ComposerNodeClass {
18092
18087
  this.uniforms.aspect.value = width / height;
18093
18088
  }
18094
18089
  _getDeltaTime() {
18095
- return this.clock.getDelta();
18090
+ return this.timer.getDelta();
18096
18091
  }
18097
18092
  _allocateTarget(name, width, height, needsDepthTexture) {
18098
18093
  return this.composer._allocateTarget(this, name, width, height, needsDepthTexture);
@@ -49141,7 +49136,7 @@ class OBJLoader extends Loader {
49141
49136
  /**
49142
49137
  * A loader for the glTF 2.0 format.
49143
49138
  *
49144
- * [glTF](https://www.khronos.org/gltf/} (GL Transmission Format) is an [open format specification]{@link https://github.com/KhronosGroup/glTF/tree/main/specification/2.0)
49139
+ * [glTF](https://www.khronos.org/gltf/) (GL Transmission Format) is an [open format specification]{@link https://github.com/KhronosGroup/glTF/tree/main/specification/2.0)
49145
49140
  * for efficient delivery and loading of 3D content. Assets may be provided either in JSON (.gltf) or binary (.glb)
49146
49141
  * format. External files store textures (.jpg, .png) and additional binary data (.bin). A glTF asset may deliver
49147
49142
  * one or more scenes, including meshes, materials, textures, skins, skeletons, morph targets, animations, lights,
@@ -49153,8 +49148,11 @@ class OBJLoader extends Loader {
49153
49148
  *
49154
49149
  * `GLTFLoader` supports the following glTF 2.0 extensions:
49155
49150
  * - KHR_draco_mesh_compression
49151
+ * - KHR_lights_punctual
49152
+ * - KHR_materials_anisotropy
49156
49153
  * - KHR_materials_clearcoat
49157
49154
  * - KHR_materials_dispersion
49155
+ * - KHR_materials_emissive_strength
49158
49156
  * - KHR_materials_ior
49159
49157
  * - KHR_materials_specular
49160
49158
  * - KHR_materials_transmission
@@ -49162,12 +49160,14 @@ class OBJLoader extends Loader {
49162
49160
  * - KHR_materials_unlit
49163
49161
  * - KHR_materials_volume
49164
49162
  * - KHR_mesh_quantization
49165
- * - KHR_lights_punctual
49163
+ * - KHR_meshopt_compression
49166
49164
  * - KHR_texture_basisu
49167
49165
  * - KHR_texture_transform
49168
- * - EXT_texture_webp
49166
+ * - EXT_materials_bump
49169
49167
  * - EXT_meshopt_compression
49170
49168
  * - EXT_mesh_gpu_instancing
49169
+ * - EXT_texture_avif
49170
+ * - EXT_texture_webp
49171
49171
  *
49172
49172
  * The following glTF 2.0 extension is supported by an external user plugin:
49173
49173
  * - [KHR_materials_variants](https://github.com/takahirox/three-gltf-extensions)
@@ -49299,7 +49299,13 @@ class GLTFLoader extends Loader {
49299
49299
 
49300
49300
  this.register( function ( parser ) {
49301
49301
 
49302
- return new GLTFMeshoptCompression( parser );
49302
+ return new GLTFMeshoptCompression( parser, EXTENSIONS.EXT_MESHOPT_COMPRESSION );
49303
+
49304
+ } );
49305
+
49306
+ this.register( function ( parser ) {
49307
+
49308
+ return new GLTFMeshoptCompression( parser, EXTENSIONS.KHR_MESHOPT_COMPRESSION );
49303
49309
 
49304
49310
  } );
49305
49311
 
@@ -49478,7 +49484,7 @@ class GLTFLoader extends Loader {
49478
49484
  }
49479
49485
 
49480
49486
  /**
49481
- * Parses the given FBX data and returns the resulting group.
49487
+ * Parses the given glTF data and returns the resulting group.
49482
49488
  *
49483
49489
  * @param {string|ArrayBuffer} data - The raw glTF data.
49484
49490
  * @param {string} path - The URL base path.
@@ -49670,6 +49676,20 @@ function GLTFRegistry() {
49670
49676
  /********** EXTENSIONS ***********/
49671
49677
  /*********************************/
49672
49678
 
49679
+ function getMaterialExtension( parser, materialIndex, extensionName ) {
49680
+
49681
+ const materialDef = parser.json.materials[ materialIndex ];
49682
+
49683
+ if ( materialDef.extensions && materialDef.extensions[ extensionName ] ) {
49684
+
49685
+ return materialDef.extensions[ extensionName ];
49686
+
49687
+ }
49688
+
49689
+ return null;
49690
+
49691
+ }
49692
+
49673
49693
  const EXTENSIONS = {
49674
49694
  KHR_BINARY_GLTF: 'KHR_binary_glTF',
49675
49695
  KHR_DRACO_MESH_COMPRESSION: 'KHR_draco_mesh_compression',
@@ -49692,6 +49712,7 @@ const EXTENSIONS = {
49692
49712
  EXT_TEXTURE_WEBP: 'EXT_texture_webp',
49693
49713
  EXT_TEXTURE_AVIF: 'EXT_texture_avif',
49694
49714
  EXT_MESHOPT_COMPRESSION: 'EXT_meshopt_compression',
49715
+ KHR_MESHOPT_COMPRESSION: 'KHR_meshopt_compression',
49695
49716
  EXT_MESH_GPU_INSTANCING: 'EXT_mesh_gpu_instancing'
49696
49717
  };
49697
49718
 
@@ -49906,20 +49927,13 @@ let GLTFMaterialsEmissiveStrengthExtension$1 = class GLTFMaterialsEmissiveStreng
49906
49927
 
49907
49928
  extendMaterialParams( materialIndex, materialParams ) {
49908
49929
 
49909
- const parser = this.parser;
49910
- const materialDef = parser.json.materials[ materialIndex ];
49911
-
49912
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
49930
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
49913
49931
 
49914
- return Promise.resolve();
49932
+ if ( extension === null ) return Promise.resolve();
49915
49933
 
49916
- }
49917
-
49918
- const emissiveStrength = materialDef.extensions[ this.name ].emissiveStrength;
49919
-
49920
- if ( emissiveStrength !== undefined ) {
49934
+ if ( extension.emissiveStrength !== undefined ) {
49921
49935
 
49922
- materialParams.emissiveIntensity = emissiveStrength;
49936
+ materialParams.emissiveIntensity = extension.emissiveStrength;
49923
49937
 
49924
49938
  }
49925
49939
 
@@ -49947,30 +49961,20 @@ let GLTFMaterialsClearcoatExtension$1 = class GLTFMaterialsClearcoatExtension {
49947
49961
 
49948
49962
  getMaterialType( materialIndex ) {
49949
49963
 
49950
- const parser = this.parser;
49951
- const materialDef = parser.json.materials[ materialIndex ];
49952
-
49953
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
49964
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
49954
49965
 
49955
- return MeshPhysicalMaterial;
49966
+ return extension !== null ? MeshPhysicalMaterial : null;
49956
49967
 
49957
49968
  }
49958
49969
 
49959
49970
  extendMaterialParams( materialIndex, materialParams ) {
49960
49971
 
49961
- const parser = this.parser;
49962
- const materialDef = parser.json.materials[ materialIndex ];
49963
-
49964
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
49972
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
49965
49973
 
49966
- return Promise.resolve();
49967
-
49968
- }
49974
+ if ( extension === null ) return Promise.resolve();
49969
49975
 
49970
49976
  const pending = [];
49971
49977
 
49972
- const extension = materialDef.extensions[ this.name ];
49973
-
49974
49978
  if ( extension.clearcoatFactor !== undefined ) {
49975
49979
 
49976
49980
  materialParams.clearcoat = extension.clearcoatFactor;
@@ -49979,7 +49983,7 @@ let GLTFMaterialsClearcoatExtension$1 = class GLTFMaterialsClearcoatExtension {
49979
49983
 
49980
49984
  if ( extension.clearcoatTexture !== undefined ) {
49981
49985
 
49982
- pending.push( parser.assignTexture( materialParams, 'clearcoatMap', extension.clearcoatTexture ) );
49986
+ pending.push( this.parser.assignTexture( materialParams, 'clearcoatMap', extension.clearcoatTexture ) );
49983
49987
 
49984
49988
  }
49985
49989
 
@@ -49991,13 +49995,13 @@ let GLTFMaterialsClearcoatExtension$1 = class GLTFMaterialsClearcoatExtension {
49991
49995
 
49992
49996
  if ( extension.clearcoatRoughnessTexture !== undefined ) {
49993
49997
 
49994
- pending.push( parser.assignTexture( materialParams, 'clearcoatRoughnessMap', extension.clearcoatRoughnessTexture ) );
49998
+ pending.push( this.parser.assignTexture( materialParams, 'clearcoatRoughnessMap', extension.clearcoatRoughnessTexture ) );
49995
49999
 
49996
50000
  }
49997
50001
 
49998
50002
  if ( extension.clearcoatNormalTexture !== undefined ) {
49999
50003
 
50000
- pending.push( parser.assignTexture( materialParams, 'clearcoatNormalMap', extension.clearcoatNormalTexture ) );
50004
+ pending.push( this.parser.assignTexture( materialParams, 'clearcoatNormalMap', extension.clearcoatNormalTexture ) );
50001
50005
 
50002
50006
  if ( extension.clearcoatNormalTexture.scale !== undefined ) {
50003
50007
 
@@ -50033,27 +50037,17 @@ let GLTFMaterialsDispersionExtension$1 = class GLTFMaterialsDispersionExtension
50033
50037
 
50034
50038
  getMaterialType( materialIndex ) {
50035
50039
 
50036
- const parser = this.parser;
50037
- const materialDef = parser.json.materials[ materialIndex ];
50038
-
50039
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
50040
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50040
50041
 
50041
- return MeshPhysicalMaterial;
50042
+ return extension !== null ? MeshPhysicalMaterial : null;
50042
50043
 
50043
50044
  }
50044
50045
 
50045
50046
  extendMaterialParams( materialIndex, materialParams ) {
50046
50047
 
50047
- const parser = this.parser;
50048
- const materialDef = parser.json.materials[ materialIndex ];
50048
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50049
50049
 
50050
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
50051
-
50052
- return Promise.resolve();
50053
-
50054
- }
50055
-
50056
- const extension = materialDef.extensions[ this.name ];
50050
+ if ( extension === null ) return Promise.resolve();
50057
50051
 
50058
50052
  materialParams.dispersion = extension.dispersion !== undefined ? extension.dispersion : 0;
50059
50053
 
@@ -50081,30 +50075,20 @@ let GLTFMaterialsIridescenceExtension$1 = class GLTFMaterialsIridescenceExtensio
50081
50075
 
50082
50076
  getMaterialType( materialIndex ) {
50083
50077
 
50084
- const parser = this.parser;
50085
- const materialDef = parser.json.materials[ materialIndex ];
50078
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50086
50079
 
50087
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
50088
-
50089
- return MeshPhysicalMaterial;
50080
+ return extension !== null ? MeshPhysicalMaterial : null;
50090
50081
 
50091
50082
  }
50092
50083
 
50093
50084
  extendMaterialParams( materialIndex, materialParams ) {
50094
50085
 
50095
- const parser = this.parser;
50096
- const materialDef = parser.json.materials[ materialIndex ];
50097
-
50098
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
50099
-
50100
- return Promise.resolve();
50086
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50101
50087
 
50102
- }
50088
+ if ( extension === null ) return Promise.resolve();
50103
50089
 
50104
50090
  const pending = [];
50105
50091
 
50106
- const extension = materialDef.extensions[ this.name ];
50107
-
50108
50092
  if ( extension.iridescenceFactor !== undefined ) {
50109
50093
 
50110
50094
  materialParams.iridescence = extension.iridescenceFactor;
@@ -50113,7 +50097,7 @@ let GLTFMaterialsIridescenceExtension$1 = class GLTFMaterialsIridescenceExtensio
50113
50097
 
50114
50098
  if ( extension.iridescenceTexture !== undefined ) {
50115
50099
 
50116
- pending.push( parser.assignTexture( materialParams, 'iridescenceMap', extension.iridescenceTexture ) );
50100
+ pending.push( this.parser.assignTexture( materialParams, 'iridescenceMap', extension.iridescenceTexture ) );
50117
50101
 
50118
50102
  }
50119
50103
 
@@ -50143,7 +50127,7 @@ let GLTFMaterialsIridescenceExtension$1 = class GLTFMaterialsIridescenceExtensio
50143
50127
 
50144
50128
  if ( extension.iridescenceThicknessTexture !== undefined ) {
50145
50129
 
50146
- pending.push( parser.assignTexture( materialParams, 'iridescenceThicknessMap', extension.iridescenceThicknessTexture ) );
50130
+ pending.push( this.parser.assignTexture( materialParams, 'iridescenceThicknessMap', extension.iridescenceThicknessTexture ) );
50147
50131
 
50148
50132
  }
50149
50133
 
@@ -50171,25 +50155,17 @@ let GLTFMaterialsSheenExtension$1 = class GLTFMaterialsSheenExtension {
50171
50155
 
50172
50156
  getMaterialType( materialIndex ) {
50173
50157
 
50174
- const parser = this.parser;
50175
- const materialDef = parser.json.materials[ materialIndex ];
50176
-
50177
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
50158
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50178
50159
 
50179
- return MeshPhysicalMaterial;
50160
+ return extension !== null ? MeshPhysicalMaterial : null;
50180
50161
 
50181
50162
  }
50182
50163
 
50183
50164
  extendMaterialParams( materialIndex, materialParams ) {
50184
50165
 
50185
- const parser = this.parser;
50186
- const materialDef = parser.json.materials[ materialIndex ];
50187
-
50188
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
50166
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50189
50167
 
50190
- return Promise.resolve();
50191
-
50192
- }
50168
+ if ( extension === null ) return Promise.resolve();
50193
50169
 
50194
50170
  const pending = [];
50195
50171
 
@@ -50197,8 +50173,6 @@ let GLTFMaterialsSheenExtension$1 = class GLTFMaterialsSheenExtension {
50197
50173
  materialParams.sheenRoughness = 0;
50198
50174
  materialParams.sheen = 1;
50199
50175
 
50200
- const extension = materialDef.extensions[ this.name ];
50201
-
50202
50176
  if ( extension.sheenColorFactor !== undefined ) {
50203
50177
 
50204
50178
  const colorFactor = extension.sheenColorFactor;
@@ -50214,13 +50188,13 @@ let GLTFMaterialsSheenExtension$1 = class GLTFMaterialsSheenExtension {
50214
50188
 
50215
50189
  if ( extension.sheenColorTexture !== undefined ) {
50216
50190
 
50217
- pending.push( parser.assignTexture( materialParams, 'sheenColorMap', extension.sheenColorTexture, SRGBColorSpace ) );
50191
+ pending.push( this.parser.assignTexture( materialParams, 'sheenColorMap', extension.sheenColorTexture, SRGBColorSpace ) );
50218
50192
 
50219
50193
  }
50220
50194
 
50221
50195
  if ( extension.sheenRoughnessTexture !== undefined ) {
50222
50196
 
50223
- pending.push( parser.assignTexture( materialParams, 'sheenRoughnessMap', extension.sheenRoughnessTexture ) );
50197
+ pending.push( this.parser.assignTexture( materialParams, 'sheenRoughnessMap', extension.sheenRoughnessTexture ) );
50224
50198
 
50225
50199
  }
50226
50200
 
@@ -50249,30 +50223,20 @@ let GLTFMaterialsTransmissionExtension$1 = class GLTFMaterialsTransmissionExtens
50249
50223
 
50250
50224
  getMaterialType( materialIndex ) {
50251
50225
 
50252
- const parser = this.parser;
50253
- const materialDef = parser.json.materials[ materialIndex ];
50254
-
50255
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
50226
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50256
50227
 
50257
- return MeshPhysicalMaterial;
50228
+ return extension !== null ? MeshPhysicalMaterial : null;
50258
50229
 
50259
50230
  }
50260
50231
 
50261
50232
  extendMaterialParams( materialIndex, materialParams ) {
50262
50233
 
50263
- const parser = this.parser;
50264
- const materialDef = parser.json.materials[ materialIndex ];
50265
-
50266
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
50234
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50267
50235
 
50268
- return Promise.resolve();
50269
-
50270
- }
50236
+ if ( extension === null ) return Promise.resolve();
50271
50237
 
50272
50238
  const pending = [];
50273
50239
 
50274
- const extension = materialDef.extensions[ this.name ];
50275
-
50276
50240
  if ( extension.transmissionFactor !== undefined ) {
50277
50241
 
50278
50242
  materialParams.transmission = extension.transmissionFactor;
@@ -50281,7 +50245,7 @@ let GLTFMaterialsTransmissionExtension$1 = class GLTFMaterialsTransmissionExtens
50281
50245
 
50282
50246
  if ( extension.transmissionTexture !== undefined ) {
50283
50247
 
50284
- pending.push( parser.assignTexture( materialParams, 'transmissionMap', extension.transmissionTexture ) );
50248
+ pending.push( this.parser.assignTexture( materialParams, 'transmissionMap', extension.transmissionTexture ) );
50285
50249
 
50286
50250
  }
50287
50251
 
@@ -50309,35 +50273,25 @@ let GLTFMaterialsVolumeExtension$1 = class GLTFMaterialsVolumeExtension {
50309
50273
 
50310
50274
  getMaterialType( materialIndex ) {
50311
50275
 
50312
- const parser = this.parser;
50313
- const materialDef = parser.json.materials[ materialIndex ];
50314
-
50315
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
50276
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50316
50277
 
50317
- return MeshPhysicalMaterial;
50278
+ return extension !== null ? MeshPhysicalMaterial : null;
50318
50279
 
50319
50280
  }
50320
50281
 
50321
50282
  extendMaterialParams( materialIndex, materialParams ) {
50322
50283
 
50323
- const parser = this.parser;
50324
- const materialDef = parser.json.materials[ materialIndex ];
50325
-
50326
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
50284
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50327
50285
 
50328
- return Promise.resolve();
50329
-
50330
- }
50286
+ if ( extension === null ) return Promise.resolve();
50331
50287
 
50332
50288
  const pending = [];
50333
50289
 
50334
- const extension = materialDef.extensions[ this.name ];
50335
-
50336
50290
  materialParams.thickness = extension.thicknessFactor !== undefined ? extension.thicknessFactor : 0;
50337
50291
 
50338
50292
  if ( extension.thicknessTexture !== undefined ) {
50339
50293
 
50340
- pending.push( parser.assignTexture( materialParams, 'thicknessMap', extension.thicknessTexture ) );
50294
+ pending.push( this.parser.assignTexture( materialParams, 'thicknessMap', extension.thicknessTexture ) );
50341
50295
 
50342
50296
  }
50343
50297
 
@@ -50370,30 +50324,22 @@ let GLTFMaterialsIorExtension$1 = class GLTFMaterialsIorExtension {
50370
50324
 
50371
50325
  getMaterialType( materialIndex ) {
50372
50326
 
50373
- const parser = this.parser;
50374
- const materialDef = parser.json.materials[ materialIndex ];
50375
-
50376
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
50327
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50377
50328
 
50378
- return MeshPhysicalMaterial;
50329
+ return extension !== null ? MeshPhysicalMaterial : null;
50379
50330
 
50380
50331
  }
50381
50332
 
50382
50333
  extendMaterialParams( materialIndex, materialParams ) {
50383
50334
 
50384
- const parser = this.parser;
50385
- const materialDef = parser.json.materials[ materialIndex ];
50386
-
50387
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
50388
-
50389
- return Promise.resolve();
50335
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50390
50336
 
50391
- }
50392
-
50393
- const extension = materialDef.extensions[ this.name ];
50337
+ if ( extension === null ) return Promise.resolve();
50394
50338
 
50395
50339
  materialParams.ior = extension.ior !== undefined ? extension.ior : 1.5;
50396
50340
 
50341
+ if ( materialParams.ior === 0 ) materialParams.ior = 1000; // see #26167
50342
+
50397
50343
  return Promise.resolve();
50398
50344
 
50399
50345
  }
@@ -50418,35 +50364,25 @@ let GLTFMaterialsSpecularExtension$1 = class GLTFMaterialsSpecularExtension {
50418
50364
 
50419
50365
  getMaterialType( materialIndex ) {
50420
50366
 
50421
- const parser = this.parser;
50422
- const materialDef = parser.json.materials[ materialIndex ];
50423
-
50424
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
50367
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50425
50368
 
50426
- return MeshPhysicalMaterial;
50369
+ return extension !== null ? MeshPhysicalMaterial : null;
50427
50370
 
50428
50371
  }
50429
50372
 
50430
50373
  extendMaterialParams( materialIndex, materialParams ) {
50431
50374
 
50432
- const parser = this.parser;
50433
- const materialDef = parser.json.materials[ materialIndex ];
50434
-
50435
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
50436
-
50437
- return Promise.resolve();
50375
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50438
50376
 
50439
- }
50377
+ if ( extension === null ) return Promise.resolve();
50440
50378
 
50441
50379
  const pending = [];
50442
50380
 
50443
- const extension = materialDef.extensions[ this.name ];
50444
-
50445
50381
  materialParams.specularIntensity = extension.specularFactor !== undefined ? extension.specularFactor : 1.0;
50446
50382
 
50447
50383
  if ( extension.specularTexture !== undefined ) {
50448
50384
 
50449
- pending.push( parser.assignTexture( materialParams, 'specularIntensityMap', extension.specularTexture ) );
50385
+ pending.push( this.parser.assignTexture( materialParams, 'specularIntensityMap', extension.specularTexture ) );
50450
50386
 
50451
50387
  }
50452
50388
 
@@ -50455,7 +50391,7 @@ let GLTFMaterialsSpecularExtension$1 = class GLTFMaterialsSpecularExtension {
50455
50391
 
50456
50392
  if ( extension.specularColorTexture !== undefined ) {
50457
50393
 
50458
- pending.push( parser.assignTexture( materialParams, 'specularColorMap', extension.specularColorTexture, SRGBColorSpace ) );
50394
+ pending.push( this.parser.assignTexture( materialParams, 'specularColorMap', extension.specularColorTexture, SRGBColorSpace ) );
50459
50395
 
50460
50396
  }
50461
50397
 
@@ -50484,35 +50420,25 @@ let GLTFMaterialsBumpExtension$1 = class GLTFMaterialsBumpExtension {
50484
50420
 
50485
50421
  getMaterialType( materialIndex ) {
50486
50422
 
50487
- const parser = this.parser;
50488
- const materialDef = parser.json.materials[ materialIndex ];
50423
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50489
50424
 
50490
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
50491
-
50492
- return MeshPhysicalMaterial;
50425
+ return extension !== null ? MeshPhysicalMaterial : null;
50493
50426
 
50494
50427
  }
50495
50428
 
50496
50429
  extendMaterialParams( materialIndex, materialParams ) {
50497
50430
 
50498
- const parser = this.parser;
50499
- const materialDef = parser.json.materials[ materialIndex ];
50500
-
50501
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
50431
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50502
50432
 
50503
- return Promise.resolve();
50504
-
50505
- }
50433
+ if ( extension === null ) return Promise.resolve();
50506
50434
 
50507
50435
  const pending = [];
50508
50436
 
50509
- const extension = materialDef.extensions[ this.name ];
50510
-
50511
50437
  materialParams.bumpScale = extension.bumpFactor !== undefined ? extension.bumpFactor : 1.0;
50512
50438
 
50513
50439
  if ( extension.bumpTexture !== undefined ) {
50514
50440
 
50515
- pending.push( parser.assignTexture( materialParams, 'bumpMap', extension.bumpTexture ) );
50441
+ pending.push( this.parser.assignTexture( materialParams, 'bumpMap', extension.bumpTexture ) );
50516
50442
 
50517
50443
  }
50518
50444
 
@@ -50540,30 +50466,20 @@ let GLTFMaterialsAnisotropyExtension$1 = class GLTFMaterialsAnisotropyExtension
50540
50466
 
50541
50467
  getMaterialType( materialIndex ) {
50542
50468
 
50543
- const parser = this.parser;
50544
- const materialDef = parser.json.materials[ materialIndex ];
50545
-
50546
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) return null;
50469
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50547
50470
 
50548
- return MeshPhysicalMaterial;
50471
+ return extension !== null ? MeshPhysicalMaterial : null;
50549
50472
 
50550
50473
  }
50551
50474
 
50552
50475
  extendMaterialParams( materialIndex, materialParams ) {
50553
50476
 
50554
- const parser = this.parser;
50555
- const materialDef = parser.json.materials[ materialIndex ];
50556
-
50557
- if ( ! materialDef.extensions || ! materialDef.extensions[ this.name ] ) {
50477
+ const extension = getMaterialExtension( this.parser, materialIndex, this.name );
50558
50478
 
50559
- return Promise.resolve();
50560
-
50561
- }
50479
+ if ( extension === null ) return Promise.resolve();
50562
50480
 
50563
50481
  const pending = [];
50564
50482
 
50565
- const extension = materialDef.extensions[ this.name ];
50566
-
50567
50483
  if ( extension.anisotropyStrength !== undefined ) {
50568
50484
 
50569
50485
  materialParams.anisotropy = extension.anisotropyStrength;
@@ -50578,7 +50494,7 @@ let GLTFMaterialsAnisotropyExtension$1 = class GLTFMaterialsAnisotropyExtension
50578
50494
 
50579
50495
  if ( extension.anisotropyTexture !== undefined ) {
50580
50496
 
50581
- pending.push( parser.assignTexture( materialParams, 'anisotropyMap', extension.anisotropyTexture ) );
50497
+ pending.push( this.parser.assignTexture( materialParams, 'anisotropyMap', extension.anisotropyTexture ) );
50582
50498
 
50583
50499
  }
50584
50500
 
@@ -50744,9 +50660,9 @@ class GLTFTextureAVIFExtension {
50744
50660
  */
50745
50661
  class GLTFMeshoptCompression {
50746
50662
 
50747
- constructor( parser ) {
50663
+ constructor( parser, name ) {
50748
50664
 
50749
- this.name = EXTENSIONS.EXT_MESHOPT_COMPRESSION;
50665
+ this.name = name;
50750
50666
  this.parser = parser;
50751
50667
 
50752
50668
  }
@@ -51720,7 +51636,7 @@ class GLTFParser {
51720
51636
  let isFirefox = false;
51721
51637
  let firefoxVersion = -1;
51722
51638
 
51723
- if ( typeof navigator !== 'undefined' ) {
51639
+ if ( typeof navigator !== 'undefined' && typeof navigator.userAgent !== 'undefined' ) {
51724
51640
 
51725
51641
  const userAgent = navigator.userAgent;
51726
51642
 
@@ -53377,6 +53293,28 @@ class GLTFParser {
53377
53293
 
53378
53294
  }
53379
53295
 
53296
+ // Reconstruct pivot from container pattern created by GLTFExporter
53297
+ // The container has position+pivot, rotation, scale; child has -pivot offset and mesh
53298
+ if ( node.userData.pivot !== undefined && children.length > 0 ) {
53299
+
53300
+ const pivot = node.userData.pivot;
53301
+ const pivotChild = children[ 0 ];
53302
+
53303
+ // Set pivot on container and adjust transforms
53304
+ node.pivot = new Vector3().fromArray( pivot );
53305
+
53306
+ // Adjust container position: stored as position + pivot, so subtract pivot
53307
+ node.position.x -= pivot[ 0 ];
53308
+ node.position.y -= pivot[ 1 ];
53309
+ node.position.z -= pivot[ 2 ];
53310
+
53311
+ // Remove the child's -pivot offset since pivot now handles it
53312
+ pivotChild.position.set( 0, 0, 0 );
53313
+
53314
+ delete node.userData.pivot;
53315
+
53316
+ }
53317
+
53380
53318
  return node;
53381
53319
 
53382
53320
  } );
@@ -53568,7 +53506,20 @@ class GLTFParser {
53568
53506
 
53569
53507
  for ( let i = 0, il = nodes.length; i < il; i ++ ) {
53570
53508
 
53571
- scene.add( nodes[ i ] );
53509
+ const node = nodes[ i ];
53510
+
53511
+ // If the node already has a parent, it means it's being reused across multiple scenes.
53512
+ // Clone it to avoid the second scene's add() removing it from the first scene.
53513
+ // See: https://github.com/mrdoob/three.js/issues/27993
53514
+ if ( node.parent !== null ) {
53515
+
53516
+ scene.add( clone( node ) );
53517
+
53518
+ } else {
53519
+
53520
+ scene.add( node );
53521
+
53522
+ }
53572
53523
 
53573
53524
  }
53574
53525
 
@@ -53619,17 +53570,28 @@ class GLTFParser {
53619
53570
  const targetName = node.name ? node.name : node.uuid;
53620
53571
  const targetNames = [];
53621
53572
 
53573
+ function collectMorphTargets( object ) {
53574
+
53575
+ if ( object.morphTargetInfluences ) {
53576
+
53577
+ targetNames.push( object.name ? object.name : object.uuid );
53578
+
53579
+ }
53580
+
53581
+ }
53582
+
53583
+
53622
53584
  if ( PATH_PROPERTIES$1[ target.path ] === PATH_PROPERTIES$1.weights ) {
53623
53585
 
53624
- node.traverse( function ( object ) {
53586
+ collectMorphTargets( node );
53625
53587
 
53626
- if ( object.morphTargetInfluences ) {
53588
+ // for multi-primitive meshes, the node is a Group containing the sub-meshes
53627
53589
 
53628
- targetNames.push( object.name ? object.name : object.uuid );
53590
+ if ( node.isGroup ) {
53629
53591
 
53630
- }
53592
+ node.children.forEach( collectMorphTargets );
53631
53593
 
53632
- } );
53594
+ }
53633
53595
 
53634
53596
  } else {
53635
53597
 
@@ -57157,7 +57119,8 @@ class FBXTreeParser {
57157
57119
 
57158
57120
  }
57159
57121
 
57160
- // the transparency handling is implemented based on Blender/Unity's approach: https://github.com/sobotka/blender-addons/blob/7d80f2f97161fc8e353a657b179b9aa1f8e5280b/io_scene_fbx/import_fbx.py#L1444-L1459
57122
+ // the transparency handling is implemented based on Blender's approach:
57123
+ // https://github.com/blender/blender/blob/main/scripts/addons_core/io_scene_fbx/import_fbx.py
57161
57124
 
57162
57125
  parameters.opacity = 1 - ( materialNode.TransparencyFactor ? parseFloat( materialNode.TransparencyFactor.value ) : 0 );
57163
57126
 
@@ -57167,7 +57130,10 @@ class FBXTreeParser {
57167
57130
 
57168
57131
  if ( parameters.opacity === null ) {
57169
57132
 
57170
- parameters.opacity = 1 - ( materialNode.TransparentColor ? parseFloat( materialNode.TransparentColor.value[ 0 ] ) : 0 );
57133
+ // Default to opaque. Some exporters (e.g. 3ds Max) define TransparentColor
57134
+ // as white (1,1,1) without intending transparency, which makes the Unity-style
57135
+ // fallback of `1 - TransparentColor.r` produce incorrect zero opacity.
57136
+ parameters.opacity = 1;
57171
57137
 
57172
57138
  }
57173
57139
 
@@ -57380,8 +57346,6 @@ class FBXTreeParser {
57380
57346
  indices: [],
57381
57347
  weights: [],
57382
57348
  transformLink: new Matrix4().fromArray( boneNode.TransformLink.a ),
57383
- // transform: new Matrix4().fromArray( boneNode.Transform.a ),
57384
- // linkMode: boneNode.Mode,
57385
57349
 
57386
57350
  };
57387
57351
 
@@ -57474,8 +57438,6 @@ class FBXTreeParser {
57474
57438
 
57475
57439
  } );
57476
57440
 
57477
- this.bindSkeleton( deformers.skeletons, geometryMap, modelMap );
57478
-
57479
57441
  this.addGlobalSceneSettings();
57480
57442
 
57481
57443
  sceneGraph.traverse( function ( node ) {
@@ -57498,6 +57460,64 @@ class FBXTreeParser {
57498
57460
 
57499
57461
  } );
57500
57462
 
57463
+ // Like Blender's FBX importer, use the BindPose section to set the
57464
+ // rest pose for bones that are not part of a skin cluster. The BindPose
57465
+ // provides a more authoritative rest pose than the Lcl properties which
57466
+ // may represent an animation frame rather than the true rest state.
57467
+ // Bones WITH clusters will get their bind pose from TransformLink
57468
+ // (set via bindSkeleton below), which takes priority.
57469
+ const bindPoseMatrices = this.parsePoseNodes();
57470
+ const clusterBoneIDs = new Set();
57471
+
57472
+ for ( const ID in deformers.skeletons ) {
57473
+
57474
+ deformers.skeletons[ ID ].rawBones.forEach( function ( _, i ) {
57475
+
57476
+ const bone = deformers.skeletons[ ID ].bones[ i ];
57477
+ if ( bone ) clusterBoneIDs.add( bone.ID );
57478
+
57479
+ } );
57480
+
57481
+ }
57482
+
57483
+ const tempMatrix = new Matrix4();
57484
+
57485
+ sceneGraph.traverse( function ( node ) {
57486
+
57487
+ if ( node.isBone && node.ID !== undefined && ! clusterBoneIDs.has( node.ID ) ) {
57488
+
57489
+ const bindPose = bindPoseMatrices[ node.ID ];
57490
+
57491
+ if ( bindPose !== undefined ) {
57492
+
57493
+ if ( node.parent ) {
57494
+
57495
+ tempMatrix.copy( node.parent.matrixWorld ).invert();
57496
+ tempMatrix.multiply( bindPose );
57497
+
57498
+ } else {
57499
+
57500
+ tempMatrix.copy( bindPose );
57501
+
57502
+ }
57503
+
57504
+ tempMatrix.decompose( node.position, node.quaternion, node.scale );
57505
+ node.updateMatrix();
57506
+ node.matrixWorld.copy( bindPose );
57507
+
57508
+ }
57509
+
57510
+ }
57511
+
57512
+ } );
57513
+
57514
+ // Bind skeletons after transforms are applied so that bind matrices
57515
+ // are computed from the final scene state. This ensures the rest pose
57516
+ // is correct even when the FBX file's Cluster TransformLink matrices
57517
+ // differ from the reconstructed bone transforms (common in files
57518
+ // without a BindPose section).
57519
+ this.bindSkeleton( deformers.skeletons, geometryMap, modelMap );
57520
+
57501
57521
  const animations = new AnimationParser().parse();
57502
57522
 
57503
57523
  // if all the models where already combined in a single group, just return that
@@ -57510,6 +57530,24 @@ class FBXTreeParser {
57510
57530
 
57511
57531
  sceneGraph.animations = animations;
57512
57532
 
57533
+ // Apply coordinate system correction. FBX files can use different
57534
+ // up-axis conventions (Y-up or Z-up). Three.js uses Y-up, so rotate
57535
+ // the scene when the file uses Z-up (UpAxis === 2).
57536
+
57537
+ if ( 'GlobalSettings' in fbxTree && 'UpAxis' in fbxTree.GlobalSettings ) {
57538
+
57539
+ const upAxis = fbxTree.GlobalSettings.UpAxis.value;
57540
+
57541
+ if ( upAxis === 2 ) {
57542
+
57543
+ console.warn( 'THREE.FBXLoader: You are loading an asset with a Z-UP coordinate system. The loader just rotates the asset to transform it into Y-UP. The vertex data are not converted.' );
57544
+
57545
+ sceneGraph.rotation.set( - Math.PI / 2, 0, 0 );
57546
+
57547
+ }
57548
+
57549
+ }
57550
+
57513
57551
  }
57514
57552
 
57515
57553
  // parse nodes in FBXTree.Objects.Model
@@ -57792,21 +57830,24 @@ class FBXTreeParser {
57792
57830
 
57793
57831
  case 2: // Spot
57794
57832
  let angle = Math.PI / 3;
57833
+ let penumbra = 0;
57795
57834
 
57796
- if ( lightAttribute.InnerAngle !== undefined ) {
57835
+ if ( lightAttribute.OuterAngle !== undefined ) {
57797
57836
 
57798
- angle = MathUtils.degToRad( lightAttribute.InnerAngle.value );
57837
+ angle = MathUtils.degToRad( lightAttribute.OuterAngle.value );
57799
57838
 
57800
- }
57839
+ if ( lightAttribute.InnerAngle !== undefined ) {
57801
57840
 
57802
- let penumbra = 0;
57803
- if ( lightAttribute.OuterAngle !== undefined ) {
57841
+ penumbra = 1 - ( lightAttribute.InnerAngle.value / lightAttribute.OuterAngle.value );
57842
+ penumbra = Math.max( 0, penumbra ); // penumbra must be in the range [0,1]
57843
+
57844
+ }
57845
+
57846
+ } else if ( lightAttribute.InnerAngle !== undefined ) {
57804
57847
 
57805
- // TODO: this is not correct - FBX calculates outer and inner angle in degrees
57806
- // with OuterAngle > InnerAngle && OuterAngle <= Math.PI
57807
- // while three.js uses a penumbra between (0, 1) to attenuate the inner angle
57808
- penumbra = MathUtils.degToRad( lightAttribute.OuterAngle.value );
57809
- penumbra = Math.max( penumbra, 1 );
57848
+ // fallback if only InnerAngle is defined
57849
+
57850
+ angle = MathUtils.degToRad( lightAttribute.InnerAngle.value );
57810
57851
 
57811
57852
  }
57812
57853
 
@@ -58016,12 +58057,30 @@ class FBXTreeParser {
58016
58057
 
58017
58058
  bindSkeleton( skeletons, geometryMap, modelMap ) {
58018
58059
 
58019
- const bindMatrices = this.parsePoseNodes();
58020
-
58021
58060
  for ( const ID in skeletons ) {
58022
58061
 
58023
58062
  const skeleton = skeletons[ ID ];
58024
58063
 
58064
+ // Compute bone inverses from TransformLink rather than from the
58065
+ // bones' current matrixWorld. The TransformLink matrices represent
58066
+ // each bone's global transform at the time the skin weights were
58067
+ // painted, which may differ from the scene-reconstructed transforms.
58068
+ const boneInverses = [];
58069
+
58070
+ for ( let i = 0, l = skeleton.bones.length; i < l; i ++ ) {
58071
+
58072
+ const inverse = new Matrix4();
58073
+
58074
+ if ( skeleton.bones[ i ] && skeleton.rawBones[ i ] ) {
58075
+
58076
+ inverse.copy( skeleton.rawBones[ i ].transformLink ).invert();
58077
+
58078
+ }
58079
+
58080
+ boneInverses.push( inverse );
58081
+
58082
+ }
58083
+
58025
58084
  const parents = connections.get( parseInt( skeleton.ID ) ).parents;
58026
58085
 
58027
58086
  parents.forEach( function ( parent ) {
@@ -58037,7 +58096,16 @@ class FBXTreeParser {
58037
58096
 
58038
58097
  const model = modelMap.get( geoConnParent.ID );
58039
58098
 
58040
- model.bind( new Skeleton( skeleton.bones ), bindMatrices[ geoConnParent.ID ] );
58099
+ // Use the mesh's current matrixWorld as bind matrix.
58100
+ // The BindPose section is intentionally not used here
58101
+ // since it may contain scale/rotation from the model
58102
+ // hierarchy that is inconsistent with the TransformLink-
58103
+ // based bone inverses. Always provide a bind matrix to
58104
+ // prevent bind() from calling calculateInverses() which
58105
+ // would overwrite the bone inverses computed above.
58106
+ model.updateMatrixWorld( true );
58107
+
58108
+ model.bind( new Skeleton( skeleton.bones, boneInverses ), model.matrixWorld );
58041
58109
 
58042
58110
  }
58043
58111
 
@@ -58051,6 +58119,7 @@ class FBXTreeParser {
58051
58119
 
58052
58120
  }
58053
58121
 
58122
+ // Parse BindPose nodes and return a map of node ID to bind matrix.
58054
58123
  parsePoseNodes() {
58055
58124
 
58056
58125
  const bindMatrices = {};
@@ -58813,6 +58882,13 @@ class GeometryParser {
58813
58882
  parentGeo.morphAttributes.position = [];
58814
58883
  // parentGeo.morphAttributes.normal = []; // not implemented
58815
58884
 
58885
+ // Morph attribute positions are stored as deltas (morphTargetsRelative = true), so the
58886
+ // translation component of the geometric transform must not be applied to them — only the
58887
+ // rotation/scale part. Otherwise every delta gets the geometric translation added, which
58888
+ // shifts morphed vertices away from their intended position by `weight * translation` as
58889
+ // the influence increases.
58890
+ const morphPreTransform = preTransform.clone().setPosition( 0, 0, 0 );
58891
+
58816
58892
  const scope = this;
58817
58893
  morphTargets.forEach( function ( morphTarget ) {
58818
58894
 
@@ -58822,7 +58898,7 @@ class GeometryParser {
58822
58898
 
58823
58899
  if ( morphGeoNode !== undefined ) {
58824
58900
 
58825
- scope.genMorphGeometry( parentGeo, parentGeoNode, morphGeoNode, preTransform, rawTarget.name );
58901
+ scope.genMorphGeometry( parentGeo, parentGeoNode, morphGeoNode, morphPreTransform, rawTarget.name );
58826
58902
 
58827
58903
  }
58828
58904
 
@@ -59217,11 +59293,15 @@ class AnimationParser {
59217
59293
 
59218
59294
  if ( layerCurveNodes[ i ] === undefined ) {
59219
59295
 
59220
- const modelID = connections.get( child.ID ).parents.filter( function ( parent ) {
59296
+ const filteredParents = connections.get( child.ID ).parents.filter( function ( parent ) {
59221
59297
 
59222
59298
  return parent.relationship !== undefined;
59223
59299
 
59224
- } )[ 0 ].ID;
59300
+ } );
59301
+
59302
+ if ( filteredParents.length === 0 ) return;
59303
+
59304
+ const modelID = filteredParents[ 0 ].ID;
59225
59305
 
59226
59306
  if ( modelID !== undefined ) {
59227
59307
 
@@ -59250,7 +59330,13 @@ class AnimationParser {
59250
59330
 
59251
59331
  node.transform = child.matrix;
59252
59332
 
59253
- if ( child.userData.transformData ) node.eulerOrder = child.userData.transformData.eulerOrder;
59333
+ if ( child.userData.transformData ) {
59334
+
59335
+ node.eulerOrder = child.userData.transformData.eulerOrder;
59336
+
59337
+ if ( child.userData.transformData.rotation ) node.initialRotation = child.userData.transformData.rotation;
59338
+
59339
+ }
59254
59340
 
59255
59341
  }
59256
59342
 
@@ -59275,11 +59361,15 @@ class AnimationParser {
59275
59361
 
59276
59362
  if ( layerCurveNodes[ i ] === undefined ) {
59277
59363
 
59278
- const deformerID = connections.get( child.ID ).parents.filter( function ( parent ) {
59364
+ const filteredParents = connections.get( child.ID ).parents.filter( function ( parent ) {
59279
59365
 
59280
59366
  return parent.relationship !== undefined;
59281
59367
 
59282
- } )[ 0 ].ID;
59368
+ } );
59369
+
59370
+ if ( filteredParents.length === 0 ) return;
59371
+
59372
+ const deformerID = filteredParents[ 0 ].ID;
59283
59373
 
59284
59374
  const morpherID = connections.get( deformerID ).parents[ 0 ].ID;
59285
59375
  const geoID = connections.get( morpherID ).parents[ 0 ].ID;
@@ -59390,7 +59480,7 @@ class AnimationParser {
59390
59480
 
59391
59481
  if ( rawTracks.R !== undefined && Object.keys( rawTracks.R.curves ).length > 0 ) {
59392
59482
 
59393
- const rotationTrack = this.generateRotationTrack( rawTracks.modelName, rawTracks.R.curves, rawTracks.preRotation, rawTracks.postRotation, rawTracks.eulerOrder );
59483
+ const rotationTrack = this.generateRotationTrack( rawTracks.modelName, rawTracks.R.curves, rawTracks.preRotation, rawTracks.postRotation, rawTracks.eulerOrder, rawTracks.initialRotation );
59394
59484
  if ( rotationTrack !== undefined ) tracks.push( rotationTrack );
59395
59485
 
59396
59486
  }
@@ -59422,17 +59512,33 @@ class AnimationParser {
59422
59512
 
59423
59513
  }
59424
59514
 
59425
- generateRotationTrack( modelName, curves, preRotation, postRotation, eulerOrder ) {
59515
+ generateRotationTrack( modelName, curves, preRotation, postRotation, eulerOrder, initialRotation ) {
59426
59516
 
59427
59517
  let times;
59428
59518
  let values;
59429
59519
 
59430
- if ( curves.x !== undefined && curves.y !== undefined && curves.z !== undefined ) {
59520
+ if ( curves.x !== undefined || curves.y !== undefined || curves.z !== undefined ) {
59431
59521
 
59432
- const result = this.interpolateRotations( curves.x, curves.y, curves.z, eulerOrder );
59522
+ // Get merged, sorted, unique times from all available curves
59523
+ const mergedTimes = this.getTimesForAllAxes( curves );
59433
59524
 
59434
- times = result[ 0 ];
59435
- values = result[ 1 ];
59525
+ if ( mergedTimes.length > 0 ) {
59526
+
59527
+ const initialRot = initialRotation || [ 0, 0, 0 ];
59528
+
59529
+ // Synchronize all curves to the merged time array.
59530
+ // Missing axes are filled with constant values from the initial rotation (Lcl Rotation).
59531
+ // Existing curves at different times are linearly interpolated.
59532
+ const syncX = this.synchronizeCurve( curves.x, mergedTimes, initialRot[ 0 ] );
59533
+ const syncY = this.synchronizeCurve( curves.y, mergedTimes, initialRot[ 1 ] );
59534
+ const syncZ = this.synchronizeCurve( curves.z, mergedTimes, initialRot[ 2 ] );
59535
+
59536
+ const result = this.interpolateRotations( syncX, syncY, syncZ, eulerOrder );
59537
+
59538
+ times = result[ 0 ];
59539
+ values = result[ 1 ];
59540
+
59541
+ }
59436
59542
 
59437
59543
  }
59438
59544
 
@@ -59464,7 +59570,7 @@ class AnimationParser {
59464
59570
 
59465
59571
  const quaternionValues = [];
59466
59572
 
59467
- if ( ! values || ! times ) return new QuaternionKeyframeTrack( modelName + '.quaternion', [ 0 ], [ 0 ] );
59573
+ if ( ! values || ! times ) return undefined;
59468
59574
 
59469
59575
  for ( let i = 0; i < values.length; i += 3 ) {
59470
59576
 
@@ -59617,6 +59723,62 @@ class AnimationParser {
59617
59723
 
59618
59724
  }
59619
59725
 
59726
+ // Synchronize a curve to a target time array using linear interpolation.
59727
+ // If the curve is undefined (axis not animated), returns constant values from initialValue.
59728
+ synchronizeCurve( curve, targetTimes, initialValue ) {
59729
+
59730
+ if ( curve === undefined ) {
59731
+
59732
+ return { times: targetTimes, values: targetTimes.map( () => initialValue ) };
59733
+
59734
+ }
59735
+
59736
+ // If the curve already has the same number of keyframes as the target, assume times match
59737
+ if ( curve.times.length === targetTimes.length ) return curve;
59738
+
59739
+ // Linearly interpolate curve values at each target time
59740
+ const values = [];
59741
+
59742
+ for ( let i = 0; i < targetTimes.length; i ++ ) {
59743
+
59744
+ values.push( this.sampleCurveValue( curve, targetTimes[ i ], initialValue ) );
59745
+
59746
+ }
59747
+
59748
+ return { times: targetTimes, values: values };
59749
+
59750
+ }
59751
+
59752
+ // Sample a single value from a curve at a given time using linear interpolation
59753
+ sampleCurveValue( curve, time, initialValue ) {
59754
+
59755
+ const times = curve.times;
59756
+ const values = curve.values;
59757
+
59758
+ // Before first keyframe
59759
+ if ( time <= times[ 0 ] ) return values[ 0 ];
59760
+
59761
+ // After last keyframe
59762
+ if ( time >= times[ times.length - 1 ] ) return values[ values.length - 1 ];
59763
+
59764
+ // Find surrounding keyframes and linearly interpolate
59765
+ for ( let i = 0; i < times.length - 1; i ++ ) {
59766
+
59767
+ if ( time >= times[ i ] && time <= times[ i + 1 ] ) {
59768
+
59769
+ if ( times[ i ] === time ) return values[ i ];
59770
+
59771
+ const alpha = ( time - times[ i ] ) / ( times[ i + 1 ] - times[ i ] );
59772
+ return values[ i ] * ( 1 - alpha ) + values[ i + 1 ] * alpha;
59773
+
59774
+ }
59775
+
59776
+ }
59777
+
59778
+ return initialValue;
59779
+
59780
+ }
59781
+
59620
59782
  // Rotations are defined as Euler angles which can have values of any size
59621
59783
  // These will be converted to quaternions which don't support values greater than
59622
59784
  // PI, so we'll interpolate large rotations
@@ -59686,7 +59848,7 @@ class AnimationParser {
59686
59848
  const Q2 = new Quaternion().setFromEuler( E2 );
59687
59849
 
59688
59850
  // Check unroll
59689
- if ( Q1.dot( Q2 ) ) {
59851
+ if ( Q1.dot( Q2 ) < 0 ) {
59690
59852
 
59691
59853
  Q2.set( - Q2.x, - Q2.y, - Q2.z, - Q2.w );
59692
59854
 
@@ -61100,7 +61262,7 @@ class WorkerPool {
61100
61262
 
61101
61263
  }
61102
61264
 
61103
- const t=0,n=2,u=1,y=2,S=0,E=1,X=10,it=0,ht=9,gt=15,xt=16,dt=22,Ft=37,Et=43,te=76,ae=83,ue=97,ye=100,de=103,Ae=109,We=122,He=123,qe=131,Je=132,Qe=133,Ze=134,en=137,nn=138,sn=139,an=140,rn=141,on=142,cn=145,Un=146,pn=148,xn=152,yn=153,bn=154,mn=155,dn=156,Dn=157,wn=158,Vn=165,Cn=166,ri=1000054e3,oi=1000054001,ci=1000054004,Ui=1000054005,_i=1000066e3,yi=1000066004;class Ci{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=0){const n=this._offset;let i=0;for(;this._dataView.getUint8(this._offset)!==e&&i<t;)i++,this._offset++;return i<t&&this._offset++,new Uint8Array(this._dataView.buffer,this._dataView.byteOffset+n,i)}}const Oi=[171,75,84,88,32,50,48,187,13,10,26,10];function Si(t){return (new TextDecoder).decode(t)}function Mi(t){const e=new Uint8Array(t.buffer,t.byteOffset,Oi.length);if(e[0]!==Oi[0]||e[1]!==Oi[1]||e[2]!==Oi[2]||e[3]!==Oi[3]||e[4]!==Oi[4]||e[5]!==Oi[5]||e[6]!==Oi[6]||e[7]!==Oi[7]||e[8]!==Oi[8]||e[9]!==Oi[9]||e[10]!==Oi[10]||e[11]!==Oi[11])throw new Error("Missing KTX 2.0 identifier.");const n={vkFormat:0,typeSize:1,pixelWidth:0,pixelHeight:0,pixelDepth:0,layerCount:0,faceCount:1,levelCount:0,supercompressionScheme:0,levels:[],dataFormatDescriptor:[{vendorId:0,descriptorType: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:[]}],keyValue:{},globalData:null},i=17*Uint32Array.BYTES_PER_ELEMENT,s=new Ci(t,Oi.length,i,true);n.vkFormat=s._nextUint32(),n.typeSize=s._nextUint32(),n.pixelWidth=s._nextUint32(),n.pixelHeight=s._nextUint32(),n.pixelDepth=s._nextUint32(),n.layerCount=s._nextUint32(),n.faceCount=s._nextUint32(),n.levelCount=s._nextUint32(),n.supercompressionScheme=s._nextUint32();const a=s._nextUint32(),r=s._nextUint32(),o=s._nextUint32(),l=s._nextUint32(),f=s._nextUint64(),c=s._nextUint64(),U=3*Math.max(n.levelCount,1)*8,h=new Ci(t,Oi.length+i,U,true);for(let e=0,i=Math.max(n.levelCount,1);e<i;e++)n.levels.push({levelData:new Uint8Array(t.buffer,t.byteOffset+h._nextUint64(),h._nextUint64()),uncompressedByteLength:h._nextUint64()});const p=new Ci(t,a,r,true);p._skip(4);const _=p._nextUint16(),u=p._nextUint16(),g=p._nextUint16(),x=p._nextUint16(),y={vendorId:_,descriptorType:u,versionNumber:g,colorModel:p._nextUint8(),colorPrimaries:p._nextUint8(),transferFunction:p._nextUint8(),flags:p._nextUint8(),texelBlockDimension:[p._nextUint8(),p._nextUint8(),p._nextUint8(),p._nextUint8()],bytesPlane:[p._nextUint8(),p._nextUint8(),p._nextUint8(),p._nextUint8(),p._nextUint8(),p._nextUint8(),p._nextUint8(),p._nextUint8()],samples:[]},b=(x/4-6)/4;for(let t=0;t<b;t++){const e={bitOffset:p._nextUint16(),bitLength:p._nextUint8(),channelType:p._nextUint8(),samplePosition:[p._nextUint8(),p._nextUint8(),p._nextUint8(),p._nextUint8()],sampleLower:Number.NEGATIVE_INFINITY,sampleUpper:Number.POSITIVE_INFINITY};64&e.channelType?(e.sampleLower=p._nextInt32(),e.sampleUpper=p._nextInt32()):(e.sampleLower=p._nextUint32(),e.sampleUpper=p._nextUint32()),y.samples[t]=e;}n.dataFormatDescriptor.length=0,n.dataFormatDescriptor.push(y);const m=new Ci(t,o,l,true);for(;m._offset<l;){const t=m._nextUint32(),e=m._scan(t),i=Si(e);if(n.keyValue[i]=m._nextUint8Array(t-e.byteLength-1),i.match(/^ktx/i)){const t=Si(n.keyValue[i]);n.keyValue[i]=t.substring(0,t.lastIndexOf("\0"));}m._skip(t%4?4-t%4:0);}if(c<=0)return n;const d=new Ci(t,f,c,true),D=d._nextUint16(),w=d._nextUint16(),v=d._nextUint32(),B=d._nextUint32(),L=d._nextUint32(),A=d._nextUint32(),k=[];for(let t=0,e=Math.max(n.levelCount,1);t<e;t++)k.push({imageFlags:d._nextUint32(),rgbSliceByteOffset:d._nextUint32(),rgbSliceByteLength:d._nextUint32(),alphaSliceByteOffset:d._nextUint32(),alphaSliceByteLength:d._nextUint32()});const I=f+d._offset,V=I+v,C=V+B,F=C+L,O=new Uint8Array(t.buffer,t.byteOffset+I,v),T=new Uint8Array(t.buffer,t.byteOffset+V,B),S=new Uint8Array(t.buffer,t.byteOffset+C,L),E=new Uint8Array(t.buffer,t.byteOffset+F,A);return n.globalData={endpointCount:D,selectorCount:w,imageDescs:k,endpointsData:O,selectorsData:T,tablesData:S,extendedData:E},n}
61265
+ const t=0,n=2,u=1,y=2,S=0,E=1,X=10,it=0,ht=9,gt=15,xt=16,dt=22,Ft=37,Et=43,te=76,ae=83,Ue=91,ue=97,ye=100,de=103,Ae=109,We=122,He=123,qe=131,Je=132,Qe=133,Ze=134,en=137,nn=138,sn=139,an=140,rn=141,on=142,cn=145,Un=146,pn=148,xn=152,yn=153,bn=154,mn=155,dn=156,Dn=157,wn=158,Vn=165,Cn=166,ri=1000054e3,oi=1000054001,ci=1000054004,Ui=1000054005,_i=1000066e3,yi=1000066004;class Ci{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=0){const n=this._offset;let i=0;for(;this._dataView.getUint8(this._offset)!==e&&i<t;)i++,this._offset++;return i<t&&this._offset++,new Uint8Array(this._dataView.buffer,this._dataView.byteOffset+n,i)}}const Oi=[171,75,84,88,32,50,48,187,13,10,26,10];function Si(t){return (new TextDecoder).decode(t)}function Mi(t){const e=new Uint8Array(t.buffer,t.byteOffset,Oi.length);if(e[0]!==Oi[0]||e[1]!==Oi[1]||e[2]!==Oi[2]||e[3]!==Oi[3]||e[4]!==Oi[4]||e[5]!==Oi[5]||e[6]!==Oi[6]||e[7]!==Oi[7]||e[8]!==Oi[8]||e[9]!==Oi[9]||e[10]!==Oi[10]||e[11]!==Oi[11])throw new Error("Missing KTX 2.0 identifier.");const n={vkFormat:0,typeSize:1,pixelWidth:0,pixelHeight:0,pixelDepth:0,layerCount:0,faceCount:1,levelCount:0,supercompressionScheme:0,levels:[],dataFormatDescriptor:[{vendorId:0,descriptorType: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:[]}],keyValue:{},globalData:null},i=17*Uint32Array.BYTES_PER_ELEMENT,s=new Ci(t,Oi.length,i,true);n.vkFormat=s._nextUint32(),n.typeSize=s._nextUint32(),n.pixelWidth=s._nextUint32(),n.pixelHeight=s._nextUint32(),n.pixelDepth=s._nextUint32(),n.layerCount=s._nextUint32(),n.faceCount=s._nextUint32(),n.levelCount=s._nextUint32(),n.supercompressionScheme=s._nextUint32();const a=s._nextUint32(),r=s._nextUint32(),o=s._nextUint32(),l=s._nextUint32(),f=s._nextUint64(),c=s._nextUint64(),U=3*Math.max(n.levelCount,1)*8,h=new Ci(t,Oi.length+i,U,true);for(let e=0,i=Math.max(n.levelCount,1);e<i;e++)n.levels.push({levelData:new Uint8Array(t.buffer,t.byteOffset+h._nextUint64(),h._nextUint64()),uncompressedByteLength:h._nextUint64()});const p=new Ci(t,a,r,true);p._skip(4);const _=p._nextUint16(),u=p._nextUint16(),g=p._nextUint16(),x=p._nextUint16(),y={vendorId:_,descriptorType:u,versionNumber:g,colorModel:p._nextUint8(),colorPrimaries:p._nextUint8(),transferFunction:p._nextUint8(),flags:p._nextUint8(),texelBlockDimension:[p._nextUint8(),p._nextUint8(),p._nextUint8(),p._nextUint8()],bytesPlane:[p._nextUint8(),p._nextUint8(),p._nextUint8(),p._nextUint8(),p._nextUint8(),p._nextUint8(),p._nextUint8(),p._nextUint8()],samples:[]},b=(x/4-6)/4;for(let t=0;t<b;t++){const e={bitOffset:p._nextUint16(),bitLength:p._nextUint8(),channelType:p._nextUint8(),samplePosition:[p._nextUint8(),p._nextUint8(),p._nextUint8(),p._nextUint8()],sampleLower:Number.NEGATIVE_INFINITY,sampleUpper:Number.POSITIVE_INFINITY};64&e.channelType?(e.sampleLower=p._nextInt32(),e.sampleUpper=p._nextInt32()):(e.sampleLower=p._nextUint32(),e.sampleUpper=p._nextUint32()),y.samples[t]=e;}n.dataFormatDescriptor.length=0,n.dataFormatDescriptor.push(y);const m=new Ci(t,o,l,true);for(;m._offset<l;){const t=m._nextUint32(),e=m._scan(t),i=Si(e);if(n.keyValue[i]=m._nextUint8Array(t-e.byteLength-1),i.match(/^ktx/i)){const t=Si(n.keyValue[i]);n.keyValue[i]=t.substring(0,t.lastIndexOf("\0"));}m._skip(t%4?4-t%4:0);}if(c<=0)return n;const d=new Ci(t,f,c,true),D=d._nextUint16(),w=d._nextUint16(),v=d._nextUint32(),B=d._nextUint32(),L=d._nextUint32(),A=d._nextUint32(),k=[];for(let t=0,e=Math.max(n.levelCount,1);t<e;t++)k.push({imageFlags:d._nextUint32(),rgbSliceByteOffset:d._nextUint32(),rgbSliceByteLength:d._nextUint32(),alphaSliceByteOffset:d._nextUint32(),alphaSliceByteLength:d._nextUint32()});const I=f+d._offset,V=I+v,C=V+B,F=C+L,O=new Uint8Array(t.buffer,t.byteOffset+I,v),T=new Uint8Array(t.buffer,t.byteOffset+V,B),S=new Uint8Array(t.buffer,t.byteOffset+C,L),E=new Uint8Array(t.buffer,t.byteOffset+F,A);return n.globalData={endpointCount:D,selectorCount:w,imageDescs:k,endpointsData:O,selectorsData:T,tablesData:S,extendedData:E},n}
61104
61266
 
61105
61267
  var global$1 = (typeof global !== "undefined" ? global :
61106
61268
  typeof self !== "undefined" ? self :
@@ -63273,6 +63435,7 @@ class KTX2Loader extends Loader {
63273
63435
  };
63274
63436
 
63275
63437
  if ( typeof navigator !== 'undefined' &&
63438
+ typeof navigator.platform !== 'undefined' && typeof navigator.userAgent !== 'undefined' &&
63276
63439
  navigator.platform.indexOf( 'Linux' ) >= 0 && navigator.userAgent.indexOf( 'Firefox' ) >= 0 &&
63277
63440
  this.workerConfig.astcSupported && this.workerConfig.etc2Supported &&
63278
63441
  this.workerConfig.bptcSupported && this.workerConfig.dxtSupported ) {
@@ -63985,6 +64148,8 @@ const FORMAT_MAP = {
63985
64148
  [ ae ]: RGFormat,
63986
64149
  [ te ]: RedFormat,
63987
64150
 
64151
+ [ Ue ]: RGBAFormat,
64152
+
63988
64153
  [ Et ]: RGBAFormat,
63989
64154
  [ Ft ]: RGBAFormat,
63990
64155
  [ dt ]: RGFormat,
@@ -64014,8 +64179,8 @@ const FORMAT_MAP = {
64014
64179
  [ Je ]: RGB_S3TC_DXT1_Format,
64015
64180
  [ qe ]: RGB_S3TC_DXT1_Format,
64016
64181
 
64017
- [ nn ]: RGBA_S3TC_DXT3_Format,
64018
- [ en ]: RGBA_S3TC_DXT3_Format,
64182
+ [ nn ]: RGBA_S3TC_DXT5_Format,
64183
+ [ en ]: RGBA_S3TC_DXT5_Format,
64019
64184
 
64020
64185
  [ an ]: SIGNED_RED_RGTC1_Format,
64021
64186
  [ sn ]: RED_RGTC1_Format,
@@ -64043,6 +64208,8 @@ const TYPE_MAP = {
64043
64208
  [ ae ]: HalfFloatType,
64044
64209
  [ te ]: HalfFloatType,
64045
64210
 
64211
+ [ Ue ]: UnsignedShortType,
64212
+
64046
64213
  [ Et ]: UnsignedByteType,
64047
64214
  [ Ft ]: UnsignedByteType,
64048
64215
  [ dt ]: UnsignedByteType,
@@ -64056,9 +64223,9 @@ const TYPE_MAP = {
64056
64223
  [ xn ]: UnsignedByteType,
64057
64224
  [ pn ]: UnsignedByteType,
64058
64225
  [ yn ]: UnsignedByteType,
64059
- [ yn ]: UnsignedByteType,
64060
- [ mn ]: UnsignedByteType,
64226
+ [ bn ]: UnsignedByteType,
64061
64227
  [ mn ]: UnsignedByteType,
64228
+ [ dn ]: UnsignedByteType,
64062
64229
 
64063
64230
  [ _i ]: HalfFloatType,
64064
64231
  [ wn ]: UnsignedByteType,
@@ -64170,7 +64337,7 @@ async function createRawTexture( container ) {
64170
64337
 
64171
64338
  );
64172
64339
 
64173
- } else if ( TYPE_MAP[ vkFormat ] === HalfFloatType ) {
64340
+ } else if ( TYPE_MAP[ vkFormat ] === HalfFloatType || TYPE_MAP[ vkFormat ] === UnsignedShortType ) {
64174
64341
 
64175
64342
  data = new Uint16Array(
64176
64343
 
@@ -64270,14 +64437,14 @@ function parseColorSpace( container ) {
64270
64437
  }
64271
64438
 
64272
64439
  // This file is part of meshoptimizer library and is distributed under the terms of MIT License.
64273
- // Copyright (C) 2016-2024, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
64440
+ // Copyright (C) 2016-2026, by Arseny Kapoulkine (arseny.kapoulkine@gmail.com)
64274
64441
  var MeshoptDecoder = (function () {
64275
- // Built with clang version 18.1.2
64276
- // Built from meshoptimizer 0.22
64442
+ // Built with clang version 22.1.0-wasi-sdk
64443
+ // Built from meshoptimizer 1.1
64277
64444
  var wasm_base =
64278
- 'b9H79Tebbbe8Fv9Gbb9Gvuuuuueu9Giuuub9Geueu9Giuuueuikqbeeedddillviebeoweuec:q:Odkr;leDo9TW9T9VV95dbH9F9F939H79T9F9J9H229F9Jt9VV7bb8A9TW79O9V9Wt9F9KW9J9V9KW9wWVtW949c919M9MWVbeY9TW79O9V9Wt9F9KW9J9V9KW69U9KW949c919M9MWVbdE9TW79O9V9Wt9F9KW9J9V9KW69U9KW949tWG91W9U9JWbiL9TW79O9V9Wt9F9KW9J9V9KWS9P2tWV9p9JtblK9TW79O9V9Wt9F9KW9J9V9KWS9P2tWV9r919HtbvL9TW79O9V9Wt9F9KW9J9V9KWS9P2tWVT949Wbol79IV9Rbrq;w8Wqdbk;esezu8Jjjjjbcj;eb9Rgv8Kjjjjbc9:hodnadcefal0mbcuhoaiRbbc:Ge9hmbavaialfgrad9Radz1jjjbhwcj;abad9Uc;WFbGgocjdaocjd6EhDaicefhocbhqdnindndndnaeaq9nmbaDaeaq9RaqaDfae6Egkcsfglcl4cifcd4hxalc9WGgmTmecbhPawcjdfhsaohzinaraz9Rax6mvarazaxfgo9RcK6mvczhlcbhHinalgic9WfgOawcj;cbffhldndndndndnazaOco4fRbbaHcoG4ciGPlbedibkal9cb83ibalcwf9cb83ibxikalaoRblaoRbbgOco4gAaAciSgAE86bbawcj;cbfaifglcGfaoclfaAfgARbbaOcl4ciGgCaCciSgCE86bbalcVfaAaCfgARbbaOcd4ciGgCaCciSgCE86bbalc7faAaCfgARbbaOciGgOaOciSgOE86bbalctfaAaOfgARbbaoRbegOco4gCaCciSgCE86bbalc91faAaCfgARbbaOcl4ciGgCaCciSgCE86bbalc4faAaCfgARbbaOcd4ciGgCaCciSgCE86bbalc93faAaCfgARbbaOciGgOaOciSgOE86bbalc94faAaOfgARbbaoRbdgOco4gCaCciSgCE86bbalc95faAaCfgARbbaOcl4ciGgCaCciSgCE86bbalc96faAaCfgARbbaOcd4ciGgCaCciSgCE86bbalc97faAaCfgARbbaOciGgOaOciSgOE86bbalc98faAaOfgORbbaoRbigoco4gAaAciSgAE86bbalc99faOaAfgORbbaocl4ciGgAaAciSgAE86bbalc9:faOaAfgORbbaocd4ciGgAaAciSgAE86bbalcufaOaAfglRbbaociGgoaociSgoE86bbalaofhoxdkalaoRbwaoRbbgOcl4gAaAcsSgAE86bbawcj;cbfaifglcGfaocwfaAfgARbbaOcsGgOaOcsSgOE86bbalcVfaAaOfgORbbaoRbegAcl4gCaCcsSgCE86bbalc7faOaCfgORbbaAcsGgAaAcsSgAE86bbalctfaOaAfgORbbaoRbdgAcl4gCaCcsSgCE86bbalc91faOaCfgORbbaAcsGgAaAcsSgAE86bbalc4faOaAfgORbbaoRbigAcl4gCaCcsSgCE86bbalc93faOaCfgORbbaAcsGgAaAcsSgAE86bbalc94faOaAfgORbbaoRblgAcl4gCaCcsSgCE86bbalc95faOaCfgORbbaAcsGgAaAcsSgAE86bbalc96faOaAfgORbbaoRbvgAcl4gCaCcsSgCE86bbalc97faOaCfgORbbaAcsGgAaAcsSgAE86bbalc98faOaAfgORbbaoRbogAcl4gCaCcsSgCE86bbalc99faOaCfgORbbaAcsGgAaAcsSgAE86bbalc9:faOaAfgORbbaoRbrgocl4gAaAcsSgAE86bbalcufaOaAfglRbbaocsGgoaocsSgoE86bbalaofhoxekalao8Pbb83bbalcwfaocwf8Pbb83bbaoczfhokdnaiam9pmbaHcdfhHaiczfhlarao9RcL0mekkaiam6mvaoTmvdnakTmbawaPfRbbhHawcj;cbfhlashiakhOinaialRbbgzce4cbazceG9R7aHfgH86bbaiadfhialcefhlaOcufgOmbkkascefhsaohzaPcefgPad9hmbxikkcbc99arao9Radcaadca0ESEhoxlkaoaxad2fhCdnakmbadhlinaoTmlarao9Rax6mlaoaxfhoalcufglmbkaChoxekcbhmawcjdfhAinarao9Rax6miawamfRbbhHawcj;cbfhlaAhiakhOinaialRbbgzce4cbazceG9R7aHfgH86bbaiadfhialcefhlaOcufgOmbkaAcefhAaoaxfhoamcefgmad9hmbkaChokabaqad2fawcjdfakad2z1jjjb8Aawawcjdfakcufad2fadz1jjjb8Aakaqfhqaombkc9:hoxekc9:hokavcj;ebf8Kjjjjbaok;cseHu8Jjjjjbc;ae9Rgv8Kjjjjbc9:hodnaeci9UgrcHfal0mbcuhoaiRbbgwc;WeGc;Ge9hmbawcsGgwce0mbavc;abfcFecjez:jjjjb8AavcUf9cu83ibavc8Wf9cu83ibavcyf9cu83ibavcaf9cu83ibavcKf9cu83ibavczf9cu83ibav9cu83iwav9cu83ibaialfc9WfhDaicefgqarfhidnaeTmbcmcsawceSEhkcbhxcbhmcbhPcbhwcbhlindnaiaD9nmbc9:hoxikdndnaqRbbgoc;Ve0mbavc;abfalaocu7gscl4fcsGcitfgzydlhrazydbhzdnaocsGgHak9pmbavawasfcsGcdtfydbaxaHEhoaHThsdndnadcd9hmbabaPcetfgHaz87ebaHclfao87ebaHcdfar87ebxekabaPcdtfgHazBdbaHcwfaoBdbaHclfarBdbkaxasfhxcdhHavawcdtfaoBdbawasfhwcehsalhOxdkdndnaHcsSmbaHc987aHamffcefhoxekaicefhoai8SbbgHcFeGhsdndnaHcu9mmbaohixekaicvfhiascFbGhscrhHdninao8SbbgOcFbGaHtasVhsaOcu9kmeaocefhoaHcrfgHc8J9hmbxdkkaocefhikasce4cbasceG9R7amfhokdndnadcd9hmbabaPcetfgHaz87ebaHclfao87ebaHcdfar87ebxekabaPcdtfgHazBdbaHcwfaoBdbaHclfarBdbkcdhHavawcdtfaoBdbcehsawcefhwalhOaohmxekdnaocpe0mbaxcefgHavawaDaocsGfRbbgocl49RcsGcdtfydbaocz6gzEhravawao9RcsGcdtfydbaHazfgAaocsGgHEhoaHThCdndnadcd9hmbabaPcetfgHax87ebaHclfao87ebaHcdfar87ebxekabaPcdtfgHaxBdbaHcwfaoBdbaHclfarBdbkcdhsavawcdtfaxBdbavawcefgwcsGcdtfarBdbcihHavc;abfalcitfgOaxBdlaOarBdbavawazfgwcsGcdtfaoBdbalcefcsGhOawaCfhwaxhzaAaCfhxxekaxcbaiRbbgOEgzaoc;:eSgHfhraOcsGhCaOcl4hAdndnaOcs0mbarcefhoxekarhoavawaA9RcsGcdtfydbhrkdndnaCmbaocefhxxekaohxavawaO9RcsGcdtfydbhokdndnaHTmbaicefhHxekaicdfhHai8SbegscFeGhzdnascu9kmbaicofhXazcFbGhzcrhidninaH8SbbgscFbGaitazVhzascu9kmeaHcefhHaicrfgic8J9hmbkaXhHxekaHcefhHkazce4cbazceG9R7amfgmhzkdndnaAcsSmbaHhsxekaHcefhsaH8SbbgicFeGhrdnaicu9kmbaHcvfhXarcFbGhrcrhidninas8SbbgHcFbGaitarVhraHcu9kmeascefhsaicrfgic8J9hmbkaXhsxekascefhskarce4cbarceG9R7amfgmhrkdndnaCcsSmbashixekascefhias8SbbgocFeGhHdnaocu9kmbascvfhXaHcFbGhHcrhodninai8SbbgscFbGaotaHVhHascu9kmeaicefhiaocrfgoc8J9hmbkaXhixekaicefhikaHce4cbaHceG9R7amfgmhokdndnadcd9hmbabaPcetfgHaz87ebaHclfao87ebaHcdfar87ebxekabaPcdtfgHazBdbaHcwfaoBdbaHclfarBdbkcdhsavawcdtfazBdbavawcefgwcsGcdtfarBdbcihHavc;abfalcitfgXazBdlaXarBdbavawaOcz6aAcsSVfgwcsGcdtfaoBdbawaCTaCcsSVfhwalcefcsGhOkaqcefhqavc;abfaOcitfgOarBdlaOaoBdbavc;abfalasfcsGcitfgraoBdlarazBdbawcsGhwalaHfcsGhlaPcifgPae6mbkkcbc99aiaDSEhokavc;aef8Kjjjjbaok:flevu8Jjjjjbcz9Rhvc9:hodnaecvfal0mbcuhoaiRbbc;:eGc;qe9hmbav9cb83iwaicefhraialfc98fhwdnaeTmbdnadcdSmbcbhDindnaraw6mbc9:skarcefhoar8SbbglcFeGhidndnalcu9mmbaohrxekarcvfhraicFbGhicrhldninao8SbbgdcFbGaltaiVhiadcu9kmeaocefhoalcrfglc8J9hmbxdkkaocefhrkabaDcdtfaic8Etc8F91aicd47avcwfaiceGcdtVgoydbfglBdbaoalBdbaDcefgDae9hmbxdkkcbhDindnaraw6mbc9:skarcefhoar8SbbglcFeGhidndnalcu9mmbaohrxekarcvfhraicFbGhicrhldninao8SbbgdcFbGaltaiVhiadcu9kmeaocefhoalcrfglc8J9hmbxdkkaocefhrkabaDcetfaic8Etc8F91aicd47avcwfaiceGcdtVgoydbfgl87ebaoalBdbaDcefgDae9hmbkkcbc99arawSEhokaok:Lvoeue99dud99eud99dndnadcl9hmbaeTmeindndnabcdfgd8Sbb:Yab8Sbbgi:Ygl:l:tabcefgv8Sbbgo:Ygr:l:tgwJbb;:9cawawNJbbbbawawJbbbb9GgDEgq:mgkaqaicb9iEalMgwawNakaqaocb9iEarMgqaqNMM:r:vglNJbbbZJbbb:;aDEMgr:lJbbb9p9DTmbar:Ohixekcjjjj94hikadai86bbdndnaqalNJbbbZJbbb:;aqJbbbb9GEMgq:lJbbb9p9DTmbaq:Ohdxekcjjjj94hdkavad86bbdndnawalNJbbbZJbbb:;awJbbbb9GEMgw:lJbbb9p9DTmbaw:Ohdxekcjjjj94hdkabad86bbabclfhbaecufgembxdkkaeTmbindndnabclfgd8Ueb:Yab8Uebgi:Ygl:l:tabcdfgv8Uebgo:Ygr:l:tgwJb;:FSawawNJbbbbawawJbbbb9GgDEgq:mgkaqaicb9iEalMgwawNakaqaocb9iEarMgqaqNMM:r:vglNJbbbZJbbb:;aDEMgr:lJbbb9p9DTmbar:Ohixekcjjjj94hikadai87ebdndnaqalNJbbbZJbbb:;aqJbbbb9GEMgq:lJbbb9p9DTmbaq:Ohdxekcjjjj94hdkavad87ebdndnawalNJbbbZJbbb:;awJbbbb9GEMgw:lJbbb9p9DTmbaw:Ohdxekcjjjj94hdkabad87ebabcwfhbaecufgembkkk;oiliui99iue99dnaeTmbcbhiabhlindndnJ;Zl81Zalcof8UebgvciV:Y:vgoal8Ueb:YNgrJb;:FSNJbbbZJbbb:;arJbbbb9GEMgw:lJbbb9p9DTmbaw:OhDxekcjjjj94hDkalclf8Uebhqalcdf8UebhkabaiavcefciGfcetfaD87ebdndnaoak:YNgwJb;:FSNJbbbZJbbb:;awJbbbb9GEMgx:lJbbb9p9DTmbax:OhDxekcjjjj94hDkabaiavciGfgkcd7cetfaD87ebdndnaoaq:YNgoJb;:FSNJbbbZJbbb:;aoJbbbb9GEMgx:lJbbb9p9DTmbax:OhDxekcjjjj94hDkabaiavcufciGfcetfaD87ebdndnJbbjZararN:tawawN:taoaoN:tgrJbbbbarJbbbb9GE:rJb;:FSNJbbbZMgr:lJbbb9p9DTmbar:Ohvxekcjjjj94hvkabakcetfav87ebalcwfhlaiclfhiaecufgembkkk9mbdnadcd4ae2gdTmbinababydbgecwtcw91:Yaece91cjjj98Gcjjj;8if::NUdbabclfhbadcufgdmbkkk9teiucbcbydj1jjbgeabcifc98GfgbBdj1jjbdndnabZbcztgd9nmbcuhiabad9RcFFifcz4nbcuSmekaehikaik;LeeeudndnaeabVciGTmbabhixekdndnadcz9pmbabhixekabhiinaiaeydbBdbaiclfaeclfydbBdbaicwfaecwfydbBdbaicxfaecxfydbBdbaeczfheaiczfhiadc9Wfgdcs0mbkkadcl6mbinaiaeydbBdbaeclfheaiclfhiadc98fgdci0mbkkdnadTmbinaiaeRbb86bbaicefhiaecefheadcufgdmbkkabk;aeedudndnabciGTmbabhixekaecFeGc:b:c:ew2hldndnadcz9pmbabhixekabhiinaialBdbaicxfalBdbaicwfalBdbaiclfalBdbaiczfhiadc9Wfgdcs0mbkkadcl6mbinaialBdbaiclfhiadc98fgdci0mbkkdnadTmbinaiae86bbaicefhiadcufgdmbkkabkkkebcjwklzNbb'; // embed! base
64445
+ 'b9H79Tebbbe8Fv9Gbb9Gvuuuuueu9Giuuub9Geueu9Giuuueuixkbeeeddddillviebeoweuecj:Gdkr;Neqo9TW9T9VV95dbH9F9F939H79T9F9J9H229F9Jt9VV7bb8A9TW79O9V9Wt9F9KW9J9V9KW9wWVtW949c919M9MWVbeY9TW79O9V9Wt9F9KW9J9V9KW69U9KW949c919M9MWVbdE9TW79O9V9Wt9F9KW9J9V9KW69U9KW949tWG91W9U9JWbiL9TW79O9V9Wt9F9KW9J9V9KWS9P2tWV9p9JtblK9TW79O9V9Wt9F9KW9J9V9KWS9P2tWV9r919HtbvL9TW79O9V9Wt9F9KW9J9V9KWS9P2tWVT949WboY9TW79O9V9Wt9F9KW9J9V9KWS9P2tWVJ9V29VVbrl79IV9Rbwq:VZkdbk:XYi5ud9:du8Jjjjjbcj;kb9Rgv8Kjjjjbc9:hodnalTmbcuhoaiRbbgrc;WeGc:Ge9hmbarcsGgwce0mbc9:hoalcufadcd4cbawEgDadfgrcKcaawEgqaraq0Egk6mbaicefhxcj;abad9Uc;WFbGcjdadca0EhmaialfgPar9Rgoadfhsavaoadz:jjjjbgzceVhHcbhOdndninaeaO9nmeaPax9RaD6mdamaeaO9RaOamfgoae6EgAcsfglc9WGhCabaOad2fhXaAcethQaxaDfhiaOaeaoaeao6E9RhLalcl4cifcd4hKazcj;cbfaAfhYcbh8AazcjdfhEaHh3incbh5dnawTmbaxa8Acd4fRbbh5kcbh8Eazcj;cbfhqinaih8Fdndndndna5a8Ecet4ciGgoc9:fPdebdkaPa8F9RaA6mrazcj;cbfa8EaA2fa8FaAz:jjjjb8Aa8FaAfhixdkazcj;cbfa8EaA2fcbaAz:kjjjb8Aa8FhixekaPa8F9RaK6mva8FaKfhidnaCTmbaPai9RcK6mbaocdtc:q:G:cjbfcj:G:cjbawEhaczhrcbhlinargoc9Wfghaqfhrdndndndndndnaaa8Fahco4fRbbalcoG4ciGcdtfydbPDbedvivvvlvkar9cb83bwar9cb83bbxlkarcbaiRbdai8Xbb9c:c:qj:bw9:9c:q;c1:I1e:d9c:b:c:e1z9:gg9cjjjjjz:dg8J9qE86bbaqaofgrcGfcbaicdfa8J9c8N1:NfghRbbag9cjjjjjw:dg8J9qE86bbarcVfcbaha8J9c8M1:NfghRbbag9cjjjjjl:dg8J9qE86bbarc7fcbaha8J9c8L1:NfghRbbag9cjjjjjd:dg8J9qE86bbarctfcbaha8J9c8K1:NfghRbbag9cjjjjje:dg8J9qE86bbarc91fcbaha8J9c8J1:NfghRbbag9cjjjj;ab:dg8J9qE86bbarc4fcbaha8J9cg1:NfghRbbag9cjjjja:dg8J9qE86bbarc93fcbaha8J9ch1:NfghRbbag9cjjjjz:dgg9qE86bbarc94fcbahag9ca1:NfghRbbai8Xbe9c:c:qj:bw9:9c:q;c1:I1e:d9c:b:c:e1z9:gg9cjjjjjz:dg8J9qE86bbarc95fcbaha8J9c8N1:NfgiRbbag9cjjjjjw:dg8J9qE86bbarc96fcbaia8J9c8M1:NfgiRbbag9cjjjjjl:dg8J9qE86bbarc97fcbaia8J9c8L1:NfgiRbbag9cjjjjjd:dg8J9qE86bbarc98fcbaia8J9c8K1:NfgiRbbag9cjjjjje:dg8J9qE86bbarc99fcbaia8J9c8J1:NfgiRbbag9cjjjj;ab:dg8J9qE86bbarc9:fcbaia8J9cg1:NfgiRbbag9cjjjja:dg8J9qE86bbarcufcbaia8J9ch1:NfgiRbbag9cjjjjz:dgg9qE86bbaiag9ca1:NfhixikaraiRblaiRbbghco4g8Ka8KciSg8KE86bbaqaofgrcGfaiclfa8Kfg8KRbbahcl4ciGg8La8LciSg8LE86bbarcVfa8Ka8Lfg8KRbbahcd4ciGg8La8LciSg8LE86bbarc7fa8Ka8Lfg8KRbbahciGghahciSghE86bbarctfa8Kahfg8KRbbaiRbeghco4g8La8LciSg8LE86bbarc91fa8Ka8Lfg8KRbbahcl4ciGg8La8LciSg8LE86bbarc4fa8Ka8Lfg8KRbbahcd4ciGg8La8LciSg8LE86bbarc93fa8Ka8Lfg8KRbbahciGghahciSghE86bbarc94fa8Kahfg8KRbbaiRbdghco4g8La8LciSg8LE86bbarc95fa8Ka8Lfg8KRbbahcl4ciGg8La8LciSg8LE86bbarc96fa8Ka8Lfg8KRbbahcd4ciGg8La8LciSg8LE86bbarc97fa8Ka8Lfg8KRbbahciGghahciSghE86bbarc98fa8KahfghRbbaiRbigico4g8Ka8KciSg8KE86bbarc99faha8KfghRbbaicl4ciGg8Ka8KciSg8KE86bbarc9:faha8KfghRbbaicd4ciGg8Ka8KciSg8KE86bbarcufaha8KfgrRbbaiciGgiaiciSgiE86bbaraifhixdkaraiRbwaiRbbghcl4g8Ka8KcsSg8KE86bbaqaofgrcGfaicwfa8Kfg8KRbbahcsGghahcsSghE86bbarcVfa8KahfghRbbaiRbeg8Kcl4g8La8LcsSg8LE86bbarc7faha8LfghRbba8KcsGg8Ka8KcsSg8KE86bbarctfaha8KfghRbbaiRbdg8Kcl4g8La8LcsSg8LE86bbarc91faha8LfghRbba8KcsGg8Ka8KcsSg8KE86bbarc4faha8KfghRbbaiRbig8Kcl4g8La8LcsSg8LE86bbarc93faha8LfghRbba8KcsGg8Ka8KcsSg8KE86bbarc94faha8KfghRbbaiRblg8Kcl4g8La8LcsSg8LE86bbarc95faha8LfghRbba8KcsGg8Ka8KcsSg8KE86bbarc96faha8KfghRbbaiRbvg8Kcl4g8La8LcsSg8LE86bbarc97faha8LfghRbba8KcsGg8Ka8KcsSg8KE86bbarc98faha8KfghRbbaiRbog8Kcl4g8La8LcsSg8LE86bbarc99faha8LfghRbba8KcsGg8Ka8KcsSg8KE86bbarc9:faha8KfghRbbaiRbrgicl4g8Ka8KcsSg8KE86bbarcufaha8KfgrRbbaicsGgiaicsSgiE86bbaraifhixekarai8Pbw83bwarai8Pbb83bbaiczfhikdnaoaC9pmbalcdfhlaoczfhraPai9RcL0mekkaoaC6moaimexokaCmva8FTmvkaqaAfhqa8Ecefg8Ecl9hmbkdndndndnawTmbasa8Acd4fRbbgociGPlbedrbkaATmdaza8Afh8Fazcj;cbfhhcbh8EaEhaina8FRbbhraahocbhlinaoahalfRbbgqce4cbaqceG9R7arfgr86bbaoadfhoaAalcefgl9hmbkaacefhaa8Fcefh8FahaAfhha8Ecefg8Ecl9hmbxikkaATmeaza8Afhaazcj;cbfhhcbhoceh8EaYh8FinaEaofhlaa8Vbbhrcbhoinala8FaofRbbcwtahaofRbbgqVc;:FiGce4cbaqceG9R7arfgr87bbaladfhlaLaocefgofmbka8FaQfh8FcdhoaacdfhaahaQfhha8EceGhlcbh8EalmbxdkkaATmbaocl4h8Eaza8AfRbbhqcwhoa3hlinalRbbaotaqVhqalcefhlaocwfgoca9hmbkcbhhaEh8FaYhainazcj;cbfahfRbbhrcwhoaahlinalRbbaotarVhralaAfhlaocwfgoca9hmbkara8E94aq7hqcbhoa8Fhlinalaqao486bbalcefhlaocwfgoca9hmbka8Fadfh8FaacefhaahcefghaA9hmbkkaEclfhEa3clfh3a8Aclfg8Aad6mbkaXazcjdfaAad2z:jjjjb8AazazcjdfaAcufad2fadz:jjjjb8AaAaOfhOaihxaimbkc9:hoxdkcbc99aPax9RakSEhoxekc9:hokavcj;kbf8Kjjjjbaok:ysezu8Jjjjjbc;ae9Rgv8Kjjjjbc9:hodnalaeci9UgrcHf6mbcuhoaiRbbgwc;WeGc;Ge9hmbawcsGgDce0mbavc;abfcFecjez:kjjjb8Aav9cu83iUav9cu83i8Wav9cu83iyav9cu83iaav9cu83iKav9cu83izav9cu83iwav9cu83ibaialfc9WfhqaicefgwarfhldnaeTmbcmcsaDceSEhkcbhxcbhmcbhrcbhicbhoindnalaq9nmbc9:hoxikdndnawRbbgDc;Ve0mbavc;abfaoaDcu7gPcl4fcsGcitfgsydlhzasydbhHdndnaDcsGgsak9pmbavaiaPfcsGcdtfydbaxasEhDaxasTgOfhxxekdndnascsSmbcehOasc987asamffcefhDxekalcefhDal8SbbgscFeGhPdndnascu9mmbaDhlxekalcvfhlaPcFbGhPcrhsdninaD8SbbgOcFbGastaPVhPaOcu9kmeaDcefhDascrfgsc8J9hmbxdkkaDcefhlkcehOaPce4cbaPceG9R7amfhDkaDhmkavc;abfaocitfgsaDBdbasazBdlavaicdtfaDBdbavc;abfaocefcsGcitfgsaHBdbasaDBdlaocdfhoaOaifhidnadcd9hmbabarcetfgsaH87ebasclfaD87ebascdfaz87ebxdkabarcdtfgsaHBdbascwfaDBdbasclfazBdbxekdnaDcpe0mbavaiaqaDcsGfRbbgscl4gP9RcsGcdtfydbaxcefgOaPEhDavaias9RcsGcdtfydbaOaPTgzfgOascsGgPEhsaPThPdndnadcd9hmbabarcetfgHax87ebaHclfas87ebaHcdfaD87ebxekabarcdtfgHaxBdbaHcwfasBdbaHclfaDBdbkavaicdtfaxBdbavc;abfaocitfgHaDBdbaHaxBdlavaicefgicsGcdtfaDBdbavc;abfaocefcsGcitfgHasBdbaHaDBdlavaiazfgicsGcdtfasBdbavc;abfaocdfcsGcitfgDaxBdbaDasBdlaocifhoaiaPfhiaOaPfhxxekaxcbalRbbgsEgHaDc;:eSgDfhOascsGhAdndnascl4gCmbaOcefhzxekaOhzavaiaC9RcsGcdtfydbhOkdndnaAmbazcefhxxekazhxavaias9RcsGcdtfydbhzkdndnaDTmbalcefhDxekalcdfhDal8SbegPcFeGhsdnaPcu9kmbalcofhHascFbGhscrhldninaD8SbbgPcFbGaltasVhsaPcu9kmeaDcefhDalcrfglc8J9hmbkaHhDxekaDcefhDkasce4cbasceG9R7amfgmhHkdndnaCcsSmbaDhsxekaDcefhsaD8SbbglcFeGhPdnalcu9kmbaDcvfhOaPcFbGhPcrhldninas8SbbgDcFbGaltaPVhPaDcu9kmeascefhsalcrfglc8J9hmbkaOhsxekascefhskaPce4cbaPceG9R7amfgmhOkdndnaAcsSmbashlxekascefhlas8SbbgDcFeGhPdnaDcu9kmbascvfhzaPcFbGhPcrhDdninal8SbbgscFbGaDtaPVhPascu9kmealcefhlaDcrfgDc8J9hmbkazhlxekalcefhlkaPce4cbaPceG9R7amfgmhzkdndnadcd9hmbabarcetfgDaH87ebaDclfaz87ebaDcdfaO87ebxekabarcdtfgDaHBdbaDcwfazBdbaDclfaOBdbkavc;abfaocitfgDaOBdbaDaHBdlavaicdtfaHBdbavc;abfaocefcsGcitfgDazBdbaDaOBdlavaicefgicsGcdtfaOBdbavc;abfaocdfcsGcitfgDaHBdbaDazBdlavaiaCTaCcsSVfgicsGcdtfazBdbaiaATaAcsSVfhiaocifhokawcefhwaocsGhoaicsGhiarcifgrae6mbkkcbc99alaqSEhokavc;aef8Kjjjjbaok:clevu8Jjjjjbcz9Rhvdnalaecvf9pmbc9:skdnaiRbbc;:eGc;qeSmbcuskav9cb83iwaicefhoaialfc98fhrdnaeTmbdnadcdSmbcbhwindnaoar6mbc9:skaocefhlao8SbbgicFeGhddndnaicu9mmbalhoxekaocvfhoadcFbGhdcrhidninal8SbbgDcFbGaitadVhdaDcu9kmealcefhlaicrfgic8J9hmbxdkkalcefhokabawcdtfadc8Etc8F91adcd47avcwfadceGcdtVglydbfgiBdbalaiBdbawcefgwae9hmbxdkkcbhwindnaoar6mbc9:skaocefhlao8SbbgicFeGhddndnaicu9mmbalhoxekaocvfhoadcFbGhdcrhidninal8SbbgDcFbGaitadVhdaDcu9kmealcefhlaicrfgic8J9hmbxdkkalcefhokabawcetfadc8Etc8F91adcd47avcwfadceGcdtVglydbfgi87ebalaiBdbawcefgwae9hmbkkcbc99aoarSEk:Lvoeue99dud99eud99dndnadcl9hmbaeTmeindndnabcdfgd8Sbb:Yab8Sbbgi:Ygl:l:tabcefgv8Sbbgo:Ygr:l:tgwJbb;:9cawawNJbbbbawawJbbbb9GgDEgq:mgkaqaicb9iEalMgwawNakaqaocb9iEarMgqaqNMM:r:vglNJbbbZJbbb:;aDEMgr:lJbbb9p9DTmbar:Ohixekcjjjj94hikadai86bbdndnaqalNJbbbZJbbb:;aqJbbbb9GEMgq:lJbbb9p9DTmbaq:Ohdxekcjjjj94hdkavad86bbdndnawalNJbbbZJbbb:;awJbbbb9GEMgw:lJbbb9p9DTmbaw:Ohdxekcjjjj94hdkabad86bbabclfhbaecufgembxdkkaeTmbindndnabclfgd8Ueb:Yab8Uebgi:Ygl:l:tabcdfgv8Uebgo:Ygr:l:tgwJb;:FSawawNJbbbbawawJbbbb9GgDEgq:mgkaqaicb9iEalMgwawNakaqaocb9iEarMgqaqNMM:r:vglNJbbbZJbbb:;aDEMgr:lJbbb9p9DTmbar:Ohixekcjjjj94hikadai87ebdndnaqalNJbbbZJbbb:;aqJbbbb9GEMgq:lJbbb9p9DTmbaq:Ohdxekcjjjj94hdkavad87ebdndnawalNJbbbZJbbb:;awJbbbb9GEMgw:lJbbb9p9DTmbaw:Ohdxekcjjjj94hdkabad87ebabcwfhbaecufgembkkk:4ioiue99dud99dud99dnaeTmbcbhiabhlindndnal8Uebgv:YgoJ:ji:1Salcof8UebgrciVgw:Y:vgDNJbbbZJbbb:;avcu9kEMgq:lJbbb9p9DTmbaq:Ohkxekcjjjj94hkkalclf8Uebhvalcdf8UebhxalarcefciGcetfak87ebdndnax:YgqaDNJbbbZJbbb:;axcu9kEMgm:lJbbb9p9DTmbam:Ohxxekcjjjj94hxkabaiarciGgkfcd7cetfax87ebdndnav:YgmaDNJbbbZJbbb:;avcu9kEMgP:lJbbb9p9DTmbaP:Ohvxekcjjjj94hvkalarcufciGcetfav87ebdndnawaw2:ZgPaPMaoaoN:taqaqN:tamamN:tgoJbbbbaoJbbbb9GE:raDNJbbbZMgD:lJbbb9p9DTmbaD:Ohrxekcjjjj94hrkalakcetfar87ebalcwfhlaiclfhiaecufgembkkk9mbdnadcd4ae2gdTmbinababydbgecwtcw91:Yaece91cjjj98Gcjjj;8if::NUdbabclfhbadcufgdmbkkk:Tvirud99eudndnadcl9hmbaeTmeindndnabRbbgiabcefgl8Sbbgvabcdfgo8Sbbgrf9R:YJbbuJabcifgwRbbgdce4adVgDcd4aDVgDcl4aDVgD:Z:vgqNJbbbZMgk:lJbbb9p9DTmbak:Ohxxekcjjjj94hxkaoax86bbdndnaraif:YaqNJbbbZMgk:lJbbb9p9DTmbak:Ohoxekcjjjj94hokalao86bbdndnavaifar9R:YaqNJbbbZMgk:lJbbb9p9DTmbak:Ohixekcjjjj94hikabai86bbdndnaDadcetGadceGV:ZaqNJbbbZMgq:lJbbb9p9DTmbaq:Ohdxekcjjjj94hdkawad86bbabclfhbaecufgembxdkkaeTmbindndnab8Vebgiabcdfgl8Uebgvabclfgo8Uebgrf9R:YJbFu9habcofgw8Vebgdce4adVgDcd4aDVgDcl4aDVgDcw4aDVgD:Z:vgqNJbbbZMgk:lJbbb9p9DTmbak:Ohxxekcjjjj94hxkaoax87ebdndnaraif:YaqNJbbbZMgk:lJbbb9p9DTmbak:Ohoxekcjjjj94hokalao87ebdndnavaifar9R:YaqNJbbbZMgk:lJbbb9p9DTmbak:Ohixekcjjjj94hikabai87ebdndnaDadcetGadceGV:ZaqNJbbbZMgq:lJbbb9p9DTmbaq:Ohdxekcjjjj94hdkawad87ebabcwfhbaecufgembkkk9teiucbcbyd:K:G:cjbgeabcifc98GfgbBd:K:G:cjbdndnabZbcztgd9nmbcuhiabad9RcFFifcz4nbcuSmekaehikaik;LeeeudndnaeabVciGTmbabhixekdndnadcz9pmbabhixekabhiinaiaeydbBdbaiclfaeclfydbBdbaicwfaecwfydbBdbaicxfaecxfydbBdbaeczfheaiczfhiadc9Wfgdcs0mbkkadcl6mbinaiaeydbBdbaeclfheaiclfhiadc98fgdci0mbkkdnadTmbinaiaeRbb86bbaicefhiaecefheadcufgdmbkkabk;aeedudndnabciGTmbabhixekaecFeGc:b:c:ew2hldndnadcz9pmbabhixekabhiinaialBdbaicxfalBdbaicwfalBdbaiclfalBdbaiczfhiadc9Wfgdcs0mbkkadcl6mbinaialBdbaiclfhiadc98fgdci0mbkkdnadTmbinaiae86bbaicefhiadcufgdmbkkabkk83dbcj:Gdk8Kbbbbdbbblbbbwbbbbbbbebbbdbbblbbbwbbbbc:K:Gdkl8W:qbb'; // embed! base
64279
64446
  var wasm_simd =
64280
- 'b9H79TebbbeKl9Gbb9Gvuuuuueu9Giuuub9Geueuikqbbebeedddilve9Weeeviebeoweuec:q:6dkr;leDo9TW9T9VV95dbH9F9F939H79T9F9J9H229F9Jt9VV7bb8A9TW79O9V9Wt9F9KW9J9V9KW9wWVtW949c919M9MWVbdY9TW79O9V9Wt9F9KW9J9V9KW69U9KW949c919M9MWVblE9TW79O9V9Wt9F9KW9J9V9KW69U9KW949tWG91W9U9JWbvL9TW79O9V9Wt9F9KW9J9V9KWS9P2tWV9p9JtboK9TW79O9V9Wt9F9KW9J9V9KWS9P2tWV9r919HtbrL9TW79O9V9Wt9F9KW9J9V9KWS9P2tWVT949Wbwl79IV9RbDq:p9sqlbzik9:evu8Jjjjjbcz9Rhbcbheincbhdcbhiinabcwfadfaicjuaead4ceGglE86bbaialfhiadcefgdcw9hmbkaec:q:yjjbfai86bbaecitc:q1jjbfab8Piw83ibaecefgecjd9hmbkk:N8JlHud97euo978Jjjjjbcj;kb9Rgv8Kjjjjbc9:hodnadcefal0mbcuhoaiRbbc:Ge9hmbavaialfgrad9Rad;8qbbcj;abad9UhlaicefhodnaeTmbadTmbalc;WFbGglcjdalcjd6EhwcbhDinawaeaD9RaDawfae6Egqcsfglc9WGgkci2hxakcethmalcl4cifcd4hPabaDad2fhsakc;ab6hzcbhHincbhOaohAdndninaraA9RaP6meavcj;cbfaOak2fhCaAaPfhocbhidnazmbarao9Rc;Gb6mbcbhlinaCalfhidndndndndnaAalco4fRbbgXciGPlbedibkaipxbbbbbbbbbbbbbbbbpklbxikaiaopbblaopbbbgQclp:meaQpmbzeHdOiAlCvXoQrLgQcdp:meaQpmbzeHdOiAlCvXoQrLpxiiiiiiiiiiiiiiiip9ogLpxiiiiiiiiiiiiiiiip8JgQp5b9cjF;8;4;W;G;ab9:9cU1:NgKcitc:q1jjbfpbibaKc:q:yjjbfpbbbgYaYpmbbbbbbbbbbbbbbbbaQp5e9cjF;8;4;W;G;ab9:9cU1:NgKcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPaLaQp9spklbaoclfaYpQbfaKc:q:yjjbfRbbfhoxdkaiaopbbwaopbbbgQclp:meaQpmbzeHdOiAlCvXoQrLpxssssssssssssssssp9ogLpxssssssssssssssssp8JgQp5b9cjF;8;4;W;G;ab9:9cU1:NgKcitc:q1jjbfpbibaKc:q:yjjbfpbbbgYaYpmbbbbbbbbbbbbbbbbaQp5e9cjF;8;4;W;G;ab9:9cU1:NgKcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPaLaQp9spklbaocwfaYpQbfaKc:q:yjjbfRbbfhoxekaiaopbbbpklbaoczfhokdndndndndnaXcd4ciGPlbedibkaipxbbbbbbbbbbbbbbbbpklzxikaiaopbblaopbbbgQclp:meaQpmbzeHdOiAlCvXoQrLgQcdp:meaQpmbzeHdOiAlCvXoQrLpxiiiiiiiiiiiiiiiip9ogLpxiiiiiiiiiiiiiiiip8JgQp5b9cjF;8;4;W;G;ab9:9cU1:NgKcitc:q1jjbfpbibaKc:q:yjjbfpbbbgYaYpmbbbbbbbbbbbbbbbbaQp5e9cjF;8;4;W;G;ab9:9cU1:NgKcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPaLaQp9spklzaoclfaYpQbfaKc:q:yjjbfRbbfhoxdkaiaopbbwaopbbbgQclp:meaQpmbzeHdOiAlCvXoQrLpxssssssssssssssssp9ogLpxssssssssssssssssp8JgQp5b9cjF;8;4;W;G;ab9:9cU1:NgKcitc:q1jjbfpbibaKc:q:yjjbfpbbbgYaYpmbbbbbbbbbbbbbbbbaQp5e9cjF;8;4;W;G;ab9:9cU1:NgKcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPaLaQp9spklzaocwfaYpQbfaKc:q:yjjbfRbbfhoxekaiaopbbbpklzaoczfhokdndndndndnaXcl4ciGPlbedibkaipxbbbbbbbbbbbbbbbbpklaxikaiaopbblaopbbbgQclp:meaQpmbzeHdOiAlCvXoQrLgQcdp:meaQpmbzeHdOiAlCvXoQrLpxiiiiiiiiiiiiiiiip9ogLpxiiiiiiiiiiiiiiiip8JgQp5b9cjF;8;4;W;G;ab9:9cU1:NgKcitc:q1jjbfpbibaKc:q:yjjbfpbbbgYaYpmbbbbbbbbbbbbbbbbaQp5e9cjF;8;4;W;G;ab9:9cU1:NgKcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPaLaQp9spklaaoclfaYpQbfaKc:q:yjjbfRbbfhoxdkaiaopbbwaopbbbgQclp:meaQpmbzeHdOiAlCvXoQrLpxssssssssssssssssp9ogLpxssssssssssssssssp8JgQp5b9cjF;8;4;W;G;ab9:9cU1:NgKcitc:q1jjbfpbibaKc:q:yjjbfpbbbgYaYpmbbbbbbbbbbbbbbbbaQp5e9cjF;8;4;W;G;ab9:9cU1:NgKcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPaLaQp9spklaaocwfaYpQbfaKc:q:yjjbfRbbfhoxekaiaopbbbpklaaoczfhokdndndndndnaXco4Plbedibkaipxbbbbbbbbbbbbbbbbpkl8WxikaiaopbblaopbbbgQclp:meaQpmbzeHdOiAlCvXoQrLgQcdp:meaQpmbzeHdOiAlCvXoQrLpxiiiiiiiiiiiiiiiip9ogLpxiiiiiiiiiiiiiiiip8JgQp5b9cjF;8;4;W;G;ab9:9cU1:NgXcitc:q1jjbfpbibaXc:q:yjjbfpbbbgYaYpmbbbbbbbbbbbbbbbbaQp5e9cjF;8;4;W;G;ab9:9cU1:NgXcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPaLaQp9spkl8WaoclfaYpQbfaXc:q:yjjbfRbbfhoxdkaiaopbbwaopbbbgQclp:meaQpmbzeHdOiAlCvXoQrLpxssssssssssssssssp9ogLpxssssssssssssssssp8JgQp5b9cjF;8;4;W;G;ab9:9cU1:NgXcitc:q1jjbfpbibaXc:q:yjjbfpbbbgYaYpmbbbbbbbbbbbbbbbbaQp5e9cjF;8;4;W;G;ab9:9cU1:NgXcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPaLaQp9spkl8WaocwfaYpQbfaXc:q:yjjbfRbbfhoxekaiaopbbbpkl8Waoczfhokalc;abfhialcjefak0meaihlarao9Rc;Fb0mbkkdnaiak9pmbaici4hlinarao9RcK6miaCaifhXdndndndndnaAaico4fRbbalcoG4ciGPlbedibkaXpxbbbbbbbbbbbbbbbbpkbbxikaXaopbblaopbbbgQclp:meaQpmbzeHdOiAlCvXoQrLgQcdp:meaQpmbzeHdOiAlCvXoQrLpxiiiiiiiiiiiiiiiip9ogLpxiiiiiiiiiiiiiiiip8JgQp5b9cjF;8;4;W;G;ab9:9cU1:NgKcitc:q1jjbfpbibaKc:q:yjjbfpbbbgYaYpmbbbbbbbbbbbbbbbbaQp5e9cjF;8;4;W;G;ab9:9cU1:NgKcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPaLaQp9spkbbaoclfaYpQbfaKc:q:yjjbfRbbfhoxdkaXaopbbwaopbbbgQclp:meaQpmbzeHdOiAlCvXoQrLpxssssssssssssssssp9ogLpxssssssssssssssssp8JgQp5b9cjF;8;4;W;G;ab9:9cU1:NgKcitc:q1jjbfpbibaKc:q:yjjbfpbbbgYaYpmbbbbbbbbbbbbbbbbaQp5e9cjF;8;4;W;G;ab9:9cU1:NgKcitc:q1jjbfpbibp9UpmbedilvorzHOACXQLpPaLaQp9spkbbaocwfaYpQbfaKc:q:yjjbfRbbfhoxekaXaopbbbpkbbaoczfhokalcdfhlaiczfgiak6mbkkaoTmeaohAaOcefgOclSmdxbkkc9:hoxlkdnakTmbavcjdfaHfhiavaHfpbdbhYcbhXinaiavcj;cbfaXfglpblbgLcep9TaLpxeeeeeeeeeeeeeeeegQp9op9Hp9rgLalakfpblbg8Acep9Ta8AaQp9op9Hp9rg8ApmbzeHdOiAlCvXoQrLgEalamfpblbg3cep9Ta3aQp9op9Hp9rg3alaxfpblbg5cep9Ta5aQp9op9Hp9rg5pmbzeHdOiAlCvXoQrLg8EpmbezHdiOAlvCXorQLgQaQpmbedibedibedibediaYp9UgYp9AdbbaiadfglaYaQaQpmlvorlvorlvorlvorp9UgYp9AdbbaladfglaYaQaQpmwDqkwDqkwDqkwDqkp9UgYp9AdbbaladfglaYaQaQpmxmPsxmPsxmPsxmPsp9UgYp9AdbbaladfglaYaEa8EpmwDKYqk8AExm35Ps8E8FgQaQpmbedibedibedibedip9UgYp9AdbbaladfglaYaQaQpmlvorlvorlvorlvorp9UgYp9AdbbaladfglaYaQaQpmwDqkwDqkwDqkwDqkp9UgYp9AdbbaladfglaYaQaQpmxmPsxmPsxmPsxmPsp9UgYp9AdbbaladfglaYaLa8ApmwKDYq8AkEx3m5P8Es8FgLa3a5pmwKDYq8AkEx3m5P8Es8Fg8ApmbezHdiOAlvCXorQLgQaQpmbedibedibedibedip9UgYp9AdbbaladfglaYaQaQpmlvorlvorlvorlvorp9UgYp9AdbbaladfglaYaQaQpmwDqkwDqkwDqkwDqkp9UgYp9AdbbaladfglaYaQaQpmxmPsxmPsxmPsxmPsp9UgYp9AdbbaladfglaYaLa8ApmwDKYqk8AExm35Ps8E8FgQaQpmbedibedibedibedip9UgYp9AdbbaladfglaYaQaQpmlvorlvorlvorlvorp9UgYp9AdbbaladfglaYaQaQpmwDqkwDqkwDqkwDqkp9UgYp9AdbbaladfglaYaQaQpmxmPsxmPsxmPsxmPsp9UgYp9AdbbaladfhiaXczfgXak6mbkkaHclfgHad6mbkasavcjdfaqad2;8qbbavavcjdfaqcufad2fad;8qbbaqaDfgDae6mbkkcbc99arao9Radcaadca0ESEhokavcj;kbf8Kjjjjbaokwbz:bjjjbk::seHu8Jjjjjbc;ae9Rgv8Kjjjjbc9:hodnaeci9UgrcHfal0mbcuhoaiRbbgwc;WeGc;Ge9hmbawcsGgwce0mbavc;abfcFecje;8kbavcUf9cu83ibavc8Wf9cu83ibavcyf9cu83ibavcaf9cu83ibavcKf9cu83ibavczf9cu83ibav9cu83iwav9cu83ibaialfc9WfhDaicefgqarfhidnaeTmbcmcsawceSEhkcbhxcbhmcbhPcbhwcbhlindnaiaD9nmbc9:hoxikdndnaqRbbgoc;Ve0mbavc;abfalaocu7gscl4fcsGcitfgzydlhrazydbhzdnaocsGgHak9pmbavawasfcsGcdtfydbaxaHEhoaHThsdndnadcd9hmbabaPcetfgHaz87ebaHclfao87ebaHcdfar87ebxekabaPcdtfgHazBdbaHcwfaoBdbaHclfarBdbkaxasfhxcdhHavawcdtfaoBdbawasfhwcehsalhOxdkdndnaHcsSmbaHc987aHamffcefhoxekaicefhoai8SbbgHcFeGhsdndnaHcu9mmbaohixekaicvfhiascFbGhscrhHdninao8SbbgOcFbGaHtasVhsaOcu9kmeaocefhoaHcrfgHc8J9hmbxdkkaocefhikasce4cbasceG9R7amfhokdndnadcd9hmbabaPcetfgHaz87ebaHclfao87ebaHcdfar87ebxekabaPcdtfgHazBdbaHcwfaoBdbaHclfarBdbkcdhHavawcdtfaoBdbcehsawcefhwalhOaohmxekdnaocpe0mbaxcefgHavawaDaocsGfRbbgocl49RcsGcdtfydbaocz6gzEhravawao9RcsGcdtfydbaHazfgAaocsGgHEhoaHThCdndnadcd9hmbabaPcetfgHax87ebaHclfao87ebaHcdfar87ebxekabaPcdtfgHaxBdbaHcwfaoBdbaHclfarBdbkcdhsavawcdtfaxBdbavawcefgwcsGcdtfarBdbcihHavc;abfalcitfgOaxBdlaOarBdbavawazfgwcsGcdtfaoBdbalcefcsGhOawaCfhwaxhzaAaCfhxxekaxcbaiRbbgOEgzaoc;:eSgHfhraOcsGhCaOcl4hAdndnaOcs0mbarcefhoxekarhoavawaA9RcsGcdtfydbhrkdndnaCmbaocefhxxekaohxavawaO9RcsGcdtfydbhokdndnaHTmbaicefhHxekaicdfhHai8SbegscFeGhzdnascu9kmbaicofhXazcFbGhzcrhidninaH8SbbgscFbGaitazVhzascu9kmeaHcefhHaicrfgic8J9hmbkaXhHxekaHcefhHkazce4cbazceG9R7amfgmhzkdndnaAcsSmbaHhsxekaHcefhsaH8SbbgicFeGhrdnaicu9kmbaHcvfhXarcFbGhrcrhidninas8SbbgHcFbGaitarVhraHcu9kmeascefhsaicrfgic8J9hmbkaXhsxekascefhskarce4cbarceG9R7amfgmhrkdndnaCcsSmbashixekascefhias8SbbgocFeGhHdnaocu9kmbascvfhXaHcFbGhHcrhodninai8SbbgscFbGaotaHVhHascu9kmeaicefhiaocrfgoc8J9hmbkaXhixekaicefhikaHce4cbaHceG9R7amfgmhokdndnadcd9hmbabaPcetfgHaz87ebaHclfao87ebaHcdfar87ebxekabaPcdtfgHazBdbaHcwfaoBdbaHclfarBdbkcdhsavawcdtfazBdbavawcefgwcsGcdtfarBdbcihHavc;abfalcitfgXazBdlaXarBdbavawaOcz6aAcsSVfgwcsGcdtfaoBdbawaCTaCcsSVfhwalcefcsGhOkaqcefhqavc;abfaOcitfgOarBdlaOaoBdbavc;abfalasfcsGcitfgraoBdlarazBdbawcsGhwalaHfcsGhlaPcifgPae6mbkkcbc99aiaDSEhokavc;aef8Kjjjjbaok:flevu8Jjjjjbcz9Rhvc9:hodnaecvfal0mbcuhoaiRbbc;:eGc;qe9hmbav9cb83iwaicefhraialfc98fhwdnaeTmbdnadcdSmbcbhDindnaraw6mbc9:skarcefhoar8SbbglcFeGhidndnalcu9mmbaohrxekarcvfhraicFbGhicrhldninao8SbbgdcFbGaltaiVhiadcu9kmeaocefhoalcrfglc8J9hmbxdkkaocefhrkabaDcdtfaic8Etc8F91aicd47avcwfaiceGcdtVgoydbfglBdbaoalBdbaDcefgDae9hmbxdkkcbhDindnaraw6mbc9:skarcefhoar8SbbglcFeGhidndnalcu9mmbaohrxekarcvfhraicFbGhicrhldninao8SbbgdcFbGaltaiVhiadcu9kmeaocefhoalcrfglc8J9hmbxdkkaocefhrkabaDcetfaic8Etc8F91aicd47avcwfaiceGcdtVgoydbfgl87ebaoalBdbaDcefgDae9hmbkkcbc99arawSEhokaok:wPliuo97eue978Jjjjjbca9Rhiaec98Ghldndnadcl9hmbdnalTmbcbhvabhdinadadpbbbgocKp:RecKp:Sep;6egraocwp:RecKp:Sep;6earp;Geaoczp:RecKp:Sep;6egwp;Gep;Kep;LegDpxbbbbbbbbbbbbbbbbp:2egqarpxbbbjbbbjbbbjbbbjgkp9op9rp;Kegrpxbb;:9cbb;:9cbb;:9cbb;:9cararp;MeaDaDp;Meawaqawakp9op9rp;Kegrarp;Mep;Kep;Kep;Jep;Negwp;Mepxbbn0bbn0bbn0bbn0gqp;KepxFbbbFbbbFbbbFbbbp9oaopxbbbFbbbFbbbFbbbFp9op9qarawp;Meaqp;Kecwp:RepxbFbbbFbbbFbbbFbbp9op9qaDawp;Meaqp;Keczp:RepxbbFbbbFbbbFbbbFbp9op9qpkbbadczfhdavclfgval6mbkkalaeSmeaipxbbbbbbbbbbbbbbbbgqpklbaiabalcdtfgdaeciGglcdtgv;8qbbdnalTmbaiaipblbgocKp:RecKp:Sep;6egraocwp:RecKp:Sep;6earp;Geaoczp:RecKp:Sep;6egwp;Gep;Kep;LegDaqp:2egqarpxbbbjbbbjbbbjbbbjgkp9op9rp;Kegrpxbb;:9cbb;:9cbb;:9cbb;:9cararp;MeaDaDp;Meawaqawakp9op9rp;Kegrarp;Mep;Kep;Kep;Jep;Negwp;Mepxbbn0bbn0bbn0bbn0gqp;KepxFbbbFbbbFbbbFbbbp9oaopxbbbFbbbFbbbFbbbFp9op9qarawp;Meaqp;Kecwp:RepxbFbbbFbbbFbbbFbbp9op9qaDawp;Meaqp;Keczp:RepxbbFbbbFbbbFbbbFbp9op9qpklbkadaiav;8qbbskdnalTmbcbhvabhdinadczfgxaxpbbbgopxbbbbbbFFbbbbbbFFgkp9oadpbbbgDaopmbediwDqkzHOAKY8AEgwczp:Reczp:Sep;6egraDaopmlvorxmPsCXQL358E8FpxFubbFubbFubbFubbp9op;6eawczp:Sep;6egwp;Gearp;Gep;Kep;Legopxbbbbbbbbbbbbbbbbp:2egqarpxbbbjbbbjbbbjbbbjgmp9op9rp;Kegrpxb;:FSb;:FSb;:FSb;:FSararp;Meaoaop;Meawaqawamp9op9rp;Kegrarp;Mep;Kep;Kep;Jep;Negwp;Mepxbbn0bbn0bbn0bbn0gqp;KepxFFbbFFbbFFbbFFbbp9oaoawp;Meaqp;Keczp:Rep9qgoarawp;Meaqp;KepxFFbbFFbbFFbbFFbbp9ogrpmwDKYqk8AExm35Ps8E8Fp9qpkbbadaDakp9oaoarpmbezHdiOAlvCXorQLp9qpkbbadcafhdavclfgval6mbkkalaeSmbaiaeciGgvcitgdfcbcaad9R;8kbaiabalcitfglad;8qbbdnavTmbaiaipblzgopxbbbbbbFFbbbbbbFFgkp9oaipblbgDaopmbediwDqkzHOAKY8AEgwczp:Reczp:Sep;6egraDaopmlvorxmPsCXQL358E8FpxFubbFubbFubbFubbp9op;6eawczp:Sep;6egwp;Gearp;Gep;Kep;Legopxbbbbbbbbbbbbbbbbp:2egqarpxbbbjbbbjbbbjbbbjgmp9op9rp;Kegrpxb;:FSb;:FSb;:FSb;:FSararp;Meaoaop;Meawaqawamp9op9rp;Kegrarp;Mep;Kep;Kep;Jep;Negwp;Mepxbbn0bbn0bbn0bbn0gqp;KepxFFbbFFbbFFbbFFbbp9oaoawp;Meaqp;Keczp:Rep9qgoarawp;Meaqp;KepxFFbbFFbbFFbbFFbbp9ogrpmwDKYqk8AExm35Ps8E8Fp9qpklzaiaDakp9oaoarpmbezHdiOAlvCXorQLp9qpklbkalaiad;8qbbkk;4wllue97euv978Jjjjjbc8W9Rhidnaec98GglTmbcbhvabhoinaiaopbbbgraoczfgwpbbbgDpmlvorxmPsCXQL358E8Fgqczp:Segkclp:RepklbaopxbbjZbbjZbbjZbbjZpx;Zl81Z;Zl81Z;Zl81Z;Zl81Zakpxibbbibbbibbbibbbp9qp;6ep;NegkaraDpmbediwDqkzHOAKY8AEgrczp:Reczp:Sep;6ep;MegDaDp;Meakarczp:Sep;6ep;Megxaxp;Meakaqczp:Reczp:Sep;6ep;Megqaqp;Mep;Kep;Kep;Lepxbbbbbbbbbbbbbbbbp:4ep;Jepxb;:FSb;:FSb;:FSb;:FSgkp;Mepxbbn0bbn0bbn0bbn0grp;KepxFFbbFFbbFFbbFFbbgmp9oaxakp;Mearp;Keczp:Rep9qgxaDakp;Mearp;Keamp9oaqakp;Mearp;Keczp:Rep9qgkpmbezHdiOAlvCXorQLgrp5baipblbpEb:T:j83ibaocwfarp5eaipblbpEe:T:j83ibawaxakpmwDKYqk8AExm35Ps8E8Fgkp5baipblbpEd:T:j83ibaocKfakp5eaipblbpEi:T:j83ibaocafhoavclfgval6mbkkdnalaeSmbaiaeciGgvcitgofcbcaao9R;8kbaiabalcitfgwao;8qbbdnavTmbaiaipblbgraipblzgDpmlvorxmPsCXQL358E8Fgqczp:Segkclp:RepklaaipxbbjZbbjZbbjZbbjZpx;Zl81Z;Zl81Z;Zl81Z;Zl81Zakpxibbbibbbibbbibbbp9qp;6ep;NegkaraDpmbediwDqkzHOAKY8AEgrczp:Reczp:Sep;6ep;MegDaDp;Meakarczp:Sep;6ep;Megxaxp;Meakaqczp:Reczp:Sep;6ep;Megqaqp;Mep;Kep;Kep;Lepxbbbbbbbbbbbbbbbbp:4ep;Jepxb;:FSb;:FSb;:FSb;:FSgkp;Mepxbbn0bbn0bbn0bbn0grp;KepxFFbbFFbbFFbbFFbbgmp9oaxakp;Mearp;Keczp:Rep9qgxaDakp;Mearp;Keamp9oaqakp;Mearp;Keczp:Rep9qgkpmbezHdiOAlvCXorQLgrp5baipblapEb:T:j83ibaiarp5eaipblapEe:T:j83iwaiaxakpmwDKYqk8AExm35Ps8E8Fgkp5baipblapEd:T:j83izaiakp5eaipblapEi:T:j83iKkawaiao;8qbbkk:Pddiue978Jjjjjbc;ab9Rhidnadcd4ae2glc98GgvTmbcbheabhdinadadpbbbgocwp:Recwp:Sep;6eaocep:SepxbbjFbbjFbbjFbbjFp9opxbbjZbbjZbbjZbbjZp:Uep;Mepkbbadczfhdaeclfgeav6mbkkdnavalSmbaialciGgecdtgdVcbc;abad9R;8kbaiabavcdtfgvad;8qbbdnaeTmbaiaipblbgocwp:Recwp:Sep;6eaocep:SepxbbjFbbjFbbjFbbjFp9opxbbjZbbjZbbjZbbjZp:Uep;Mepklbkavaiad;8qbbkk9teiucbcbydj1jjbgeabcifc98GfgbBdj1jjbdndnabZbcztgd9nmbcuhiabad9RcFFifcz4nbcuSmekaehikaikkkebcjwklz:Dbb'; // embed! simd
64447
+ 'b9H79TebbbeKl9Gbb9Gvuuuuueu9Giuuub9Geueuixkbbebeeddddilve9Weeeviebeoweuecj:Gdkr;Neqo9TW9T9VV95dbH9F9F939H79T9F9J9H229F9Jt9VV7bb8A9TW79O9V9Wt9F9KW9J9V9KW9wWVtW949c919M9MWVbdY9TW79O9V9Wt9F9KW9J9V9KW69U9KW949c919M9MWVblE9TW79O9V9Wt9F9KW9J9V9KW69U9KW949tWG91W9U9JWbvL9TW79O9V9Wt9F9KW9J9V9KWS9P2tWV9p9JtboK9TW79O9V9Wt9F9KW9J9V9KWS9P2tWV9r919HtbrL9TW79O9V9Wt9F9KW9J9V9KWS9P2tWVT949WbwY9TW79O9V9Wt9F9KW9J9V9KWS9P2tWVJ9V29VVbDl79IV9Rbqq:W9Dklbzik94evu8Jjjjjbcz9Rhbcbheincbhdcbhiinabcwfadfaicjuaead4ceGglE86bbaialfhiadcefgdcw9hmbkaeai86b:q:W:cjbaecitab8Piw83i:q:G:cjbaecefgecjd9hmbkk:JBl8Aud97dur978Jjjjjbcj;kb9Rgv8Kjjjjbc9:hodnalTmbcuhoaiRbbgrc;WeGc:Ge9hmbarcsGgwce0mbc9:hoalcufadcd4cbawEgDadfgrcKcaawEgqaraq0Egk6mbaialfgxar9RhodnadTgmmbavaoad;8qbbkaicefhPcj;abad9Uc;WFbGcjdadca0EhsdndndnadTmbaoadfhzcbhHinaeaH9nmdaxaP9RaD6miabaHad2fhOaPaDfhAasaeaH9RaHasfae6EgCcsfgocl4cifcd4hXavcj;cbfaoc9WGgQcetfhLavcj;cbfaQci2fhKavcj;cbfaQfhYcbh8Aaoc;ab6hEincbh3dnawTmbaPa8Acd4fRbbh3kcbh5avcj;cbfh8Eindndndndna3a5cet4ciGgoc9:fPdebdkaxaA9RaQ6mwdnaQTmbavcj;cbfa5aQ2faAaQ;8qbbkaAaCfhAxdkaQTmeavcj;cbfa5aQ2fcbaQ;8kbxekaxaA9RaX6moaoclVcbawEhraAaXfhocbhidnaEmbaxao9Rc;Gb6mbcbhlina8EalfhidndndndndndnaAalco4fRbbgqciGarfPDbedibledibkaipxbbbbbbbbbbbbbbbbpklbxlkaiaopbblaopbbbg8Fclp:mea8FpmbzeHdOiAlCvXoQrLg8Fcdp:mea8FpmbzeHdOiAlCvXoQrLpxiiiiiiiiiiiiiiiip9ogapxiiiiiiiiiiiiiiiip8Jg8Fp5b9cjF;8;4;W;G;ab9:9cU1:Nghcitpbi:q:G:cjbahRb:q:W:cjbghpsa8Fp5e9cjF;8;4;W;G;ab9:9cU1:Nggcitpbi:q:G:cjbp9UpmbedilvorzHOACXQLpPaaa8Fp9spklbahaoclffagRb:q:W:cjbfhoxikaiaopbbwaopbbbg8Fclp:mea8FpmbzeHdOiAlCvXoQrLpxssssssssssssssssp9ogapxssssssssssssssssp8Jg8Fp5b9cjF;8;4;W;G;ab9:9cU1:Nghcitpbi:q:G:cjbahRb:q:W:cjbghpsa8Fp5e9cjF;8;4;W;G;ab9:9cU1:Nggcitpbi:q:G:cjbp9UpmbedilvorzHOACXQLpPaaa8Fp9spklbahaocwffagRb:q:W:cjbfhoxdkaiaopbbbpklbaoczfhoxekaiaopbbdaoRbbghcitpbi:q:G:cjbahRb:q:W:cjbghpsaoRbeggcitpbi:q:G:cjbp9UpmbedilvorzHOACXQLpPpklbahaocdffagRb:q:W:cjbfhokdndndndndndnaqcd4ciGarfPDbedibledibkaiczfpxbbbbbbbbbbbbbbbbpklbxlkaiczfaopbblaopbbbg8Fclp:mea8FpmbzeHdOiAlCvXoQrLg8Fcdp:mea8FpmbzeHdOiAlCvXoQrLpxiiiiiiiiiiiiiiiip9ogapxiiiiiiiiiiiiiiiip8Jg8Fp5b9cjF;8;4;W;G;ab9:9cU1:Nghcitpbi:q:G:cjbahRb:q:W:cjbghpsa8Fp5e9cjF;8;4;W;G;ab9:9cU1:Nggcitpbi:q:G:cjbp9UpmbedilvorzHOACXQLpPaaa8Fp9spklbahaoclffagRb:q:W:cjbfhoxikaiczfaopbbwaopbbbg8Fclp:mea8FpmbzeHdOiAlCvXoQrLpxssssssssssssssssp9ogapxssssssssssssssssp8Jg8Fp5b9cjF;8;4;W;G;ab9:9cU1:Nghcitpbi:q:G:cjbahRb:q:W:cjbghpsa8Fp5e9cjF;8;4;W;G;ab9:9cU1:Nggcitpbi:q:G:cjbp9UpmbedilvorzHOACXQLpPaaa8Fp9spklbahaocwffagRb:q:W:cjbfhoxdkaiczfaopbbbpklbaoczfhoxekaiczfaopbbdaoRbbghcitpbi:q:G:cjbahRb:q:W:cjbghpsaoRbeggcitpbi:q:G:cjbp9UpmbedilvorzHOACXQLpPpklbahaocdffagRb:q:W:cjbfhokdndndndndndnaqcl4ciGarfPDbedibledibkaicafpxbbbbbbbbbbbbbbbbpklbxlkaicafaopbblaopbbbg8Fclp:mea8FpmbzeHdOiAlCvXoQrLg8Fcdp:mea8FpmbzeHdOiAlCvXoQrLpxiiiiiiiiiiiiiiiip9ogapxiiiiiiiiiiiiiiiip8Jg8Fp5b9cjF;8;4;W;G;ab9:9cU1:Nghcitpbi:q:G:cjbahRb:q:W:cjbghpsa8Fp5e9cjF;8;4;W;G;ab9:9cU1:Nggcitpbi:q:G:cjbp9UpmbedilvorzHOACXQLpPaaa8Fp9spklbahaoclffagRb:q:W:cjbfhoxikaicafaopbbwaopbbbg8Fclp:mea8FpmbzeHdOiAlCvXoQrLpxssssssssssssssssp9ogapxssssssssssssssssp8Jg8Fp5b9cjF;8;4;W;G;ab9:9cU1:Nghcitpbi:q:G:cjbahRb:q:W:cjbghpsa8Fp5e9cjF;8;4;W;G;ab9:9cU1:Nggcitpbi:q:G:cjbp9UpmbedilvorzHOACXQLpPaaa8Fp9spklbahaocwffagRb:q:W:cjbfhoxdkaicafaopbbbpklbaoczfhoxekaicafaopbbdaoRbbghcitpbi:q:G:cjbahRb:q:W:cjbghpsaoRbeggcitpbi:q:G:cjbp9UpmbedilvorzHOACXQLpPpklbahaocdffagRb:q:W:cjbfhokdndndndndndnaqco4arfPDbedibledibkaic8Wfpxbbbbbbbbbbbbbbbbpklbxlkaic8Wfaopbblaopbbbg8Fclp:mea8FpmbzeHdOiAlCvXoQrLg8Fcdp:mea8FpmbzeHdOiAlCvXoQrLpxiiiiiiiiiiiiiiiip9ogapxiiiiiiiiiiiiiiiip8Jg8Fp5b9cjF;8;4;W;G;ab9:9cU1:Ngicitpbi:q:G:cjbaiRb:q:W:cjbgipsa8Fp5e9cjF;8;4;W;G;ab9:9cU1:Ngqcitpbi:q:G:cjbp9UpmbedilvorzHOACXQLpPaaa8Fp9spklbaiaoclffaqRb:q:W:cjbfhoxikaic8Wfaopbbwaopbbbg8Fclp:mea8FpmbzeHdOiAlCvXoQrLpxssssssssssssssssp9ogapxssssssssssssssssp8Jg8Fp5b9cjF;8;4;W;G;ab9:9cU1:Ngicitpbi:q:G:cjbaiRb:q:W:cjbgipsa8Fp5e9cjF;8;4;W;G;ab9:9cU1:Ngqcitpbi:q:G:cjbp9UpmbedilvorzHOACXQLpPaaa8Fp9spklbaiaocwffaqRb:q:W:cjbfhoxdkaic8Wfaopbbbpklbaoczfhoxekaic8WfaopbbdaoRbbgicitpbi:q:G:cjbaiRb:q:W:cjbgipsaoRbegqcitpbi:q:G:cjbp9UpmbedilvorzHOACXQLpPpklbaiaocdffaqRb:q:W:cjbfhokalc;abfhialcjefaQ0meaihlaxao9Rc;Fb0mbkkdnaiaQ9pmbaici4hlinaxao9RcK6mwa8EaifhqdndndndndndnaAaico4fRbbalcoG4ciGarfPDbedibledibkaqpxbbbbbbbbbbbbbbbbpkbbxlkaqaopbblaopbbbg8Fclp:mea8FpmbzeHdOiAlCvXoQrLg8Fcdp:mea8FpmbzeHdOiAlCvXoQrLpxiiiiiiiiiiiiiiiip9ogapxiiiiiiiiiiiiiiiip8Jg8Fp5b9cjF;8;4;W;G;ab9:9cU1:Nghcitpbi:q:G:cjbahRb:q:W:cjbghpsa8Fp5e9cjF;8;4;W;G;ab9:9cU1:Nggcitpbi:q:G:cjbp9UpmbedilvorzHOACXQLpPaaa8Fp9spkbbahaoclffagRb:q:W:cjbfhoxikaqaopbbwaopbbbg8Fclp:mea8FpmbzeHdOiAlCvXoQrLpxssssssssssssssssp9ogapxssssssssssssssssp8Jg8Fp5b9cjF;8;4;W;G;ab9:9cU1:Nghcitpbi:q:G:cjbahRb:q:W:cjbghpsa8Fp5e9cjF;8;4;W;G;ab9:9cU1:Nggcitpbi:q:G:cjbp9UpmbedilvorzHOACXQLpPaaa8Fp9spkbbahaocwffagRb:q:W:cjbfhoxdkaqaopbbbpkbbaoczfhoxekaqaopbbdaoRbbghcitpbi:q:G:cjbahRb:q:W:cjbghpsaoRbeggcitpbi:q:G:cjbp9UpmbedilvorzHOACXQLpPpkbbahaocdffagRb:q:W:cjbfhokalcdfhlaiczfgiaQ6mbkkaohAaoTmoka8EaQfh8Ea5cefg5cl9hmbkdndndndnawTmbaza8Acd4fRbbglciGPlbedwbkaQTmdavcjdfa8Afhlava8Afpbdbh8Jcbhoinalavcj;cbfaofpblbg8KaYaofpblbg8LpmbzeHdOiAlCvXoQrLg8MaLaofpblbg8NaKaofpblbgypmbzeHdOiAlCvXoQrLg8PpmbezHdiOAlvCXorQLg8Fcep9Ta8Fpxeeeeeeeeeeeeeeeegap9op9Hp9rg8Fa8Jp9Ug8Jp9Abbbaladfgla8Ja8Fa8Fpmlvorlvorlvorlvorp9Ug8Jp9Abbbaladfgla8Ja8Fa8FpmwDqkwDqkwDqkwDqkp9Ug8Jp9Abbbaladfgla8Ja8Fa8FpmxmPsxmPsxmPsxmPsp9Ug8Jp9Abbbaladfgla8Ja8Ma8PpmwDKYqk8AExm35Ps8E8Fg8Fcep9Ta8Faap9op9Hp9rg8Fp9Ug8Jp9Abbbaladfgla8Ja8Fa8Fpmlvorlvorlvorlvorp9Ug8Jp9Abbbaladfgla8Ja8Fa8FpmwDqkwDqkwDqkwDqkp9Ug8Jp9Abbbaladfgla8Ja8Fa8FpmxmPsxmPsxmPsxmPsp9Ug8Jp9Abbbaladfgla8Ja8Ka8LpmwKDYq8AkEx3m5P8Es8Fg8Ka8NaypmwKDYq8AkEx3m5P8Es8Fg8LpmbezHdiOAlvCXorQLg8Fcep9Ta8Faap9op9Hp9rg8Fp9Ug8Jp9Abbbaladfgla8Ja8Fa8Fpmlvorlvorlvorlvorp9Ug8Jp9Abbbaladfgla8Ja8Fa8FpmwDqkwDqkwDqkwDqkp9Ug8Jp9Abbbaladfgla8Ja8Fa8FpmxmPsxmPsxmPsxmPsp9Ug8Jp9Abbbaladfgla8Ja8Ka8LpmwDKYqk8AExm35Ps8E8Fg8Fcep9Ta8Faap9op9Hp9rg8Fp9Ugap9Abbbaladfglaaa8Fa8Fpmlvorlvorlvorlvorp9Ugap9Abbbaladfglaaa8Fa8FpmwDqkwDqkwDqkwDqkp9Ugap9Abbbaladfglaaa8Fa8FpmxmPsxmPsxmPsxmPsp9Ug8Jp9AbbbaladfhlaoczfgoaQ6mbxikkaQTmeavcjdfa8Afhlava8Afpbdbh8Jcbhoinalavcj;cbfaofpblbg8KaYaofpblbg8LpmbzeHdOiAlCvXoQrLg8MaLaofpblbg8NaKaofpblbgypmbzeHdOiAlCvXoQrLg8PpmbezHdiOAlvCXorQLg8Fcep:nea8Fpxebebebebebebebebgap9op:bep9rg8Fa8Jp:oeg8Jp9Abbbaladfgla8Ja8Fa8Fpmlvorlvorlvorlvorp:oeg8Jp9Abbbaladfgla8Ja8Fa8FpmwDqkwDqkwDqkwDqkp:oeg8Jp9Abbbaladfgla8Ja8Fa8FpmxmPsxmPsxmPsxmPsp:oeg8Jp9Abbbaladfgla8Ja8Ma8PpmwDKYqk8AExm35Ps8E8Fg8Fcep:nea8Faap9op:bep9rg8Fp:oeg8Jp9Abbbaladfgla8Ja8Fa8Fpmlvorlvorlvorlvorp:oeg8Jp9Abbbaladfgla8Ja8Fa8FpmwDqkwDqkwDqkwDqkp:oeg8Jp9Abbbaladfgla8Ja8Fa8FpmxmPsxmPsxmPsxmPsp:oeg8Jp9Abbbaladfgla8Ja8Ka8LpmwKDYq8AkEx3m5P8Es8Fg8Ka8NaypmwKDYq8AkEx3m5P8Es8Fg8LpmbezHdiOAlvCXorQLg8Fcep:nea8Faap9op:bep9rg8Fp:oeg8Jp9Abbbaladfgla8Ja8Fa8Fpmlvorlvorlvorlvorp:oeg8Jp9Abbbaladfgla8Ja8Fa8FpmwDqkwDqkwDqkwDqkp:oeg8Jp9Abbbaladfgla8Ja8Fa8FpmxmPsxmPsxmPsxmPsp:oeg8Jp9Abbbaladfgla8Ja8Ka8LpmwDKYqk8AExm35Ps8E8Fg8Fcep:nea8Faap9op:bep9rg8Fp:oegap9Abbbaladfglaaa8Fa8Fpmlvorlvorlvorlvorp:oegap9Abbbaladfglaaa8Fa8FpmwDqkwDqkwDqkwDqkp:oegap9Abbbaladfglaaa8Fa8FpmxmPsxmPsxmPsxmPsp:oeg8Jp9AbbbaladfhlaoczfgoaQ6mbxdkkaQTmbcbhocbalcl4gl9Rc8FGhiavcjdfa8Afhrava8Afpbdbhainaravcj;cbfaofpblbg8JaYaofpblbg8KpmbzeHdOiAlCvXoQrLg8LaLaofpblbg8MaKaofpblbg8NpmbzeHdOiAlCvXoQrLgypmbezHdiOAlvCXorQLg8Faip:Rea8Falp:Tep9qg8Faap9rgap9Abbbaradfgraaa8Fa8Fpmlvorlvorlvorlvorp9rgap9Abbbaradfgraaa8Fa8FpmwDqkwDqkwDqkwDqkp9rgap9Abbbaradfgraaa8Fa8FpmxmPsxmPsxmPsxmPsp9rgap9Abbbaradfgraaa8LaypmwDKYqk8AExm35Ps8E8Fg8Faip:Rea8Falp:Tep9qg8Fp9rgap9Abbbaradfgraaa8Fa8Fpmlvorlvorlvorlvorp9rgap9Abbbaradfgraaa8Fa8FpmwDqkwDqkwDqkwDqkp9rgap9Abbbaradfgraaa8Fa8FpmxmPsxmPsxmPsxmPsp9rgap9Abbbaradfgraaa8Ja8KpmwKDYq8AkEx3m5P8Es8Fg8Ja8Ma8NpmwKDYq8AkEx3m5P8Es8Fg8KpmbezHdiOAlvCXorQLg8Faip:Rea8Falp:Tep9qg8Fp9rgap9Abbbaradfgraaa8Fa8Fpmlvorlvorlvorlvorp9rgap9Abbbaradfgraaa8Fa8FpmwDqkwDqkwDqkwDqkp9rgap9Abbbaradfgraaa8Fa8FpmxmPsxmPsxmPsxmPsp9rgap9Abbbaradfgraaa8Ja8KpmwDKYqk8AExm35Ps8E8Fg8Faip:Rea8Falp:Tep9qg8Fp9rgap9Abbbaradfgraaa8Fa8Fpmlvorlvorlvorlvorp9rgap9Abbbaradfgraaa8Fa8FpmwDqkwDqkwDqkwDqkp9rgap9Abbbaradfgraaa8Fa8FpmxmPsxmPsxmPsxmPsp9rgap9AbbbaradfhraoczfgoaQ6mbkka8Aclfg8Aad6mbkdnaCad2goTmbaOavcjdfao;8qbbkdnammbavavcjdfaCcufad2fad;8qbbkaCaHfhHc9:hoaAhPaAmbxlkkaeTmbaDalfhrcbhocuhlinaralaD9RglfaD6mdasaeao9Raoasfae6Eaofgoae6mbkaial9RhPkcbc99axaP9RakSEhoxekc9:hokavcj;kbf8Kjjjjbaokwbz:bjjjbkNsezu8Jjjjjbc;ae9Rgv8Kjjjjbc9:hodnalaeci9UgrcHf6mbcuhoaiRbbgwc;WeGc;Ge9hmbawcsGgDce0mbavc;abfcFecje;8kbav9cu83iUav9cu83i8Wav9cu83iyav9cu83iaav9cu83iKav9cu83izav9cu83iwav9cu83ibaialfc9WfhqaicefgwarfhldnaeTmbcmcsaDceSEhkcbhxcbhmcbhrcbhicbhoindnalaq9nmbc9:hoxikdndnawRbbgDc;Ve0mbavc;abfaoaDcu7gPcl4fcsGcitfgsydlhzasydbhHdndnaDcsGgsak9pmbavaiaPfcsGcdtfydbaxasEhDaxasTgOfhxxekdndnascsSmbcehOasc987asamffcefhDxekalcefhDal8SbbgscFeGhPdndnascu9mmbaDhlxekalcvfhlaPcFbGhPcrhsdninaD8SbbgOcFbGastaPVhPaOcu9kmeaDcefhDascrfgsc8J9hmbxdkkaDcefhlkcehOaPce4cbaPceG9R7amfhDkaDhmkavc;abfaocitfgsaDBdbasazBdlavaicdtfaDBdbavc;abfaocefcsGcitfgsaHBdbasaDBdlaocdfhoaOaifhidnadcd9hmbabarcetfgsaH87ebasclfaD87ebascdfaz87ebxdkabarcdtfgsaHBdbascwfaDBdbasclfazBdbxekdnaDcpe0mbavaiaqaDcsGfRbbgscl4gP9RcsGcdtfydbaxcefgOaPEhDavaias9RcsGcdtfydbaOaPTgzfgOascsGgPEhsaPThPdndnadcd9hmbabarcetfgHax87ebaHclfas87ebaHcdfaD87ebxekabarcdtfgHaxBdbaHcwfasBdbaHclfaDBdbkavaicdtfaxBdbavc;abfaocitfgHaDBdbaHaxBdlavaicefgicsGcdtfaDBdbavc;abfaocefcsGcitfgHasBdbaHaDBdlavaiazfgicsGcdtfasBdbavc;abfaocdfcsGcitfgDaxBdbaDasBdlaocifhoaiaPfhiaOaPfhxxekaxcbalRbbgsEgHaDc;:eSgDfhOascsGhAdndnascl4gCmbaOcefhzxekaOhzavaiaC9RcsGcdtfydbhOkdndnaAmbazcefhxxekazhxavaias9RcsGcdtfydbhzkdndnaDTmbalcefhDxekalcdfhDal8SbegPcFeGhsdnaPcu9kmbalcofhHascFbGhscrhldninaD8SbbgPcFbGaltasVhsaPcu9kmeaDcefhDalcrfglc8J9hmbkaHhDxekaDcefhDkasce4cbasceG9R7amfgmhHkdndnaCcsSmbaDhsxekaDcefhsaD8SbbglcFeGhPdnalcu9kmbaDcvfhOaPcFbGhPcrhldninas8SbbgDcFbGaltaPVhPaDcu9kmeascefhsalcrfglc8J9hmbkaOhsxekascefhskaPce4cbaPceG9R7amfgmhOkdndnaAcsSmbashlxekascefhlas8SbbgDcFeGhPdnaDcu9kmbascvfhzaPcFbGhPcrhDdninal8SbbgscFbGaDtaPVhPascu9kmealcefhlaDcrfgDc8J9hmbkazhlxekalcefhlkaPce4cbaPceG9R7amfgmhzkdndnadcd9hmbabarcetfgDaH87ebaDclfaz87ebaDcdfaO87ebxekabarcdtfgDaHBdbaDcwfazBdbaDclfaOBdbkavc;abfaocitfgDaOBdbaDaHBdlavaicdtfaHBdbavc;abfaocefcsGcitfgDazBdbaDaOBdlavaicefgicsGcdtfaOBdbavc;abfaocdfcsGcitfgDaHBdbaDazBdlavaiaCTaCcsSVfgicsGcdtfazBdbaiaATaAcsSVfhiaocifhokawcefhwaocsGhoaicsGhiarcifgrae6mbkkcbc99alaqSEhokavc;aef8Kjjjjbaok:clevu8Jjjjjbcz9Rhvdnalaecvf9pmbc9:skdnaiRbbc;:eGc;qeSmbcuskav9cb83iwaicefhoaialfc98fhrdnaeTmbdnadcdSmbcbhwindnaoar6mbc9:skaocefhlao8SbbgicFeGhddndnaicu9mmbalhoxekaocvfhoadcFbGhdcrhidninal8SbbgDcFbGaitadVhdaDcu9kmealcefhlaicrfgic8J9hmbxdkkalcefhokabawcdtfadc8Etc8F91adcd47avcwfadceGcdtVglydbfgiBdbalaiBdbawcefgwae9hmbxdkkcbhwindnaoar6mbc9:skaocefhlao8SbbgicFeGhddndnaicu9mmbalhoxekaocvfhoadcFbGhdcrhidninal8SbbgDcFbGaitadVhdaDcu9kmealcefhlaicrfgic8J9hmbxdkkalcefhokabawcetfadc8Etc8F91adcd47avcwfadceGcdtVglydbfgi87ebalaiBdbawcefgwae9hmbkkcbc99aoarSEk;Toio97eue97aec98Ghedndnadcl9hmbaeTmecbhdinababpbbbgicKp:RecKp:Sep;6eglaicwp:RecKp:Sep;6ealp;Geaiczp:RecKp:Sep;6egvp;Gep;Kep;Legopxbbbbbbbbbbbbbbbbp:2egralpxbbbjbbbjbbbjbbbjgwp9op9rp;Keglpxbb;:9cbb;:9cbb;:9cbb;:9calalp;Meaoaop;Meavaravawp9op9rp;Keglalp;Mep;Kep;Kep;Jep;Negvp;Mepxbbn0bbn0bbn0bbn0grp;KepxFbbbFbbbFbbbFbbbp9oaipxbbbFbbbFbbbFbbbFp9op9qalavp;Mearp;Kecwp:RepxbFbbbFbbbFbbbFbbp9op9qaoavp;Mearp;Keczp:RepxbbFbbbFbbbFbbbFbp9op9qpkbbabczfhbadclfgdae6mbxdkkaeTmbcbhdinabczfgDaDpbbbgipxbbbbbbFFbbbbbbFFgwp9oabpbbbgoaipmbediwDqkzHOAKY8AEgvczp:Reczp:Sep;6eglaoaipmlvorxmPsCXQL358E8FpxFubbFubbFubbFubbp9op;6eavczp:Sep;6egvp;Gealp;Gep;Kep;Legipxbbbbbbbbbbbbbbbbp:2egralpxbbbjbbbjbbbjbbbjgqp9op9rp;Keglpxb;:FSb;:FSb;:FSb;:FSalalp;Meaiaip;Meavaravaqp9op9rp;Keglalp;Mep;Kep;Kep;Jep;Negvp;Mepxbbn0bbn0bbn0bbn0grp;KepxFFbbFFbbFFbbFFbbp9oaiavp;Mearp;Keczp:Rep9qgialavp;Mearp;KepxFFbbFFbbFFbbFFbbp9oglpmwDKYqk8AExm35Ps8E8Fp9qpkbbabaoawp9oaialpmbezHdiOAlvCXorQLp9qpkbbabcafhbadclfgdae6mbkkk;2ileue97euo97dnaec98GgiTmbcbheinabcKfpx:ji:1S:ji:1S:ji:1S:ji:1SabpbbbglabczfgvpbbbgopmlvorxmPsCXQL358E8Fgrczp:Segwpxibbbibbbibbbibbbp9qp;6egDp;NegqaDaDp;MegDaDp;KealaopmbediwDqkzHOAKY8AEgDczp:Reczp:Sep;6eglalp;MeaDczp:Sep;6egoaop;Mearczp:Reczp:Sep;6egrarp;Mep;Kep;Kep;Lepxbbbbbbbbbbbbbbbbp:4ep;Jep;Mepxbbn0bbn0bbn0bbn0gDp;KepxFFbbFFbbFFbbFFbbgkp9oaqaop;MeaDp;Keczp:Rep9qgoaqalp;MeaDp;Keakp9oaqarp;MeaDp;Keczp:Rep9qgDpmwDKYqk8AExm35Ps8E8Fglp5eawclp:RegqpEi:T:j83ibavalp5baqpEd:T:j83ibabcwfaoaDpmbezHdiOAlvCXorQLgDp5eaqpEe:T:j83ibabaDp5baqpEb:T:j83ibabcafhbaeclfgeai6mbkkkuee97dnadcd4ae2c98GgeTmbcbhdinababpbbbgicwp:Recwp:Sep;6eaicep:SepxbbjFbbjFbbjFbbjFp9opxbbjZbbjZbbjZbbjZp:Uep;Mepkbbabczfhbadclfgdae6mbkkk:Sodw97euaec98Ghedndnadcl9hmbaeTmecbhdinabpxbbuJbbuJbbuJbbuJabpbbbgicKp:TeglaicYp:Tep9qgvcdp:Teavp9qgvclp:Teavp9qgop;6ep;Negvaicwp:RecKp:SegraipxFbbbFbbbFbbbFbbbgwp9ogDp:Uep;6ep;Mepxbbn0bbn0bbn0bbn0gqp;Kecwp:RepxbFbbbFbbbFbbbFbbp9oavaDarp:Xeaiczp:RecKp:Segip:Uep;6ep;Meaqp;Keawp9op9qavaDaraip:Uep:Xep;6ep;Meaqp;Keczp:RepxbbFbbbFbbbFbbbFbp9op9qavaoalcep:Rep9oalpxebbbebbbebbbebbbp9op9qp;6ep;Meaqp;KecKp:Rep9qpkbbabczfhbadclfgdae6mbxdkkaeTmbcbhdinabczfgkpxbFu9hbFu9hbFu9hbFu9habpbbbglakpbbbgrpmlvorxmPsCXQL358E8Fgvczp:TegqavcHp:Tep9qgicdp:Teaip9qgiclp:Teaip9qgicwp:Teaip9qgop;6ep;NegialarpmbediwDqkzHOAKY8AEgDpxFFbbFFbbFFbbFFbbglp9ograDczp:Segwp:Ueavczp:Reczp:SegDp:Xep;6ep;Mepxbbn0bbn0bbn0bbn0gvp;Kealp9oaiarawaDp:Uep:Xep;6ep;Meavp;Keczp:Rep9qgwaiaoaqcep:Rep9oaqpxebbbebbbebbbebbbp9op9qp;6ep;Meavp;Keczp:ReaiaDarp:Uep;6ep;Meavp;Kealp9op9qgipmwDKYqk8AExm35Ps8E8FpkbbabawaipmbezHdiOAlvCXorQLpkbbabcafhbadclfgdae6mbkkk9teiucbcbydj:G:cjbgeabcifc98GfgbBdj:G:cjbdndnabZbcztgd9nmbcuhiabad9RcFFifcz4nbcuSmekaehikaikkxebcj:Gdklz:zbb'; // embed! simd
64281
64448
 
64282
64449
  var detector = new Uint8Array([
64283
64450
  0, 97, 115, 109, 1, 0, 0, 0, 1, 4, 1, 96, 0, 0, 3, 3, 2, 0, 0, 5, 3, 1, 0, 1, 12, 1, 0, 10, 22, 2, 12, 0, 65, 0, 65, 0, 65, 0, 252, 10, 0, 0,
@@ -64339,6 +64506,7 @@ var MeshoptDecoder = (function () {
64339
64506
  OCTAHEDRAL: 'meshopt_decodeFilterOct',
64340
64507
  QUATERNION: 'meshopt_decodeFilterQuat',
64341
64508
  EXPONENTIAL: 'meshopt_decodeFilterExp',
64509
+ COLOR: 'meshopt_decodeFilterColor',
64342
64510
  };
64343
64511
 
64344
64512
  var decoders = {
@@ -64417,10 +64585,10 @@ var MeshoptDecoder = (function () {
64417
64585
 
64418
64586
  function workerProcess(event) {
64419
64587
  var data = event.data;
64420
- if (!data.id) {
64421
- return self.close();
64422
- }
64423
64588
  self.ready.then(function (instance) {
64589
+ if (!data.id) {
64590
+ return self.close();
64591
+ }
64424
64592
  try {
64425
64593
  var target = new Uint8Array(data.count * data.size);
64426
64594
  decode(instance, instance.exports[data.mode], target, data.count, data.size, data.source, instance.exports[data.filter]);
@@ -66341,6 +66509,584 @@ const _Stats = class _Stats2 {
66341
66509
  _Stats.Panel = Panel;
66342
66510
  let Stats = _Stats;
66343
66511
 
66512
+ // Limitations
66513
+ // - VSM shadows not supported
66514
+ // - MRT not supported
66515
+ // - Transmission not supported
66516
+ // - WebGPU postprocessing stack not supported
66517
+ // - Storage textures not supported
66518
+ // - Fog / environment do not automatically update - must call "dispose"
66519
+ // - instanced mesh geometry cannot be shared
66520
+ // - Node materials cannot be used with "compile" function
66521
+
66522
+ // hash any object parameters that will impact the resulting shader so we can force
66523
+ // a program update
66524
+ function getObjectHash( object ) {
66525
+
66526
+ return '' + object.receiveShadow;
66527
+
66528
+ }
66529
+
66530
+ // Mirrors WebGLUniforms.seqWithValue from WebGLRenderer
66531
+ function generateUniformsList( program, uniforms ) {
66532
+
66533
+ const progUniforms = program.getUniforms();
66534
+ const uniformsList = [];
66535
+
66536
+ for ( let i = 0; i < progUniforms.seq.length; i ++ ) {
66537
+
66538
+ const u = progUniforms.seq[ i ];
66539
+ if ( u.id in uniforms ) uniformsList.push( u );
66540
+
66541
+ }
66542
+
66543
+ return uniformsList;
66544
+
66545
+ }
66546
+
66547
+ // overrides shadow nodes to use the built in shadow textures
66548
+ class WebGLNodeBuilder extends GLSLNodeBuilder {
66549
+
66550
+ addNode( node ) {
66551
+
66552
+ if ( node.isShadowNode ) {
66553
+
66554
+ node.setupRenderTarget = shadow => {
66555
+
66556
+ return { shadowMap: shadow.map, depthTexture: shadow.map.depthTexture };
66557
+
66558
+ };
66559
+
66560
+ node.updateBefore = () => {
66561
+
66562
+ // no need to rerender shadows since WebGLRenderer is handling it
66563
+
66564
+ };
66565
+
66566
+ }
66567
+
66568
+ super.addNode( node );
66569
+
66570
+ }
66571
+
66572
+ }
66573
+
66574
+ // produce and update reusable nodes for a scene
66575
+ class SceneContext {
66576
+
66577
+ constructor( renderer, scene ) {
66578
+
66579
+ // TODO: can / should we update the fog and environment node every frame for recompile?
66580
+ this.renderer = renderer;
66581
+ this.scene = scene;
66582
+ this.lightsNode = renderer.lighting.getNode( scene );
66583
+ this.fogNode = null;
66584
+ this.environmentNode = null;
66585
+ this.prevFog = null;
66586
+ this.prevEnvironment = null;
66587
+
66588
+ }
66589
+
66590
+ getCacheKey() {
66591
+
66592
+ const { lightsNode, environmentNode, fogNode } = this;
66593
+ const lightsHash = lightsNode.getCacheKey();
66594
+ const envHash = environmentNode ? environmentNode.getCacheKey : 0;
66595
+ const fogHash = fogNode ? fogNode.getCacheKey() : 0;
66596
+ return NodeUtils.hashArray( [ lightsHash, envHash, fogHash ] );
66597
+
66598
+ }
66599
+
66600
+ update() {
66601
+
66602
+ const { scene, lightsNode } = this;
66603
+
66604
+ // update lighting
66605
+ const sceneLights = [];
66606
+ scene.traverse( object => {
66607
+
66608
+ if ( object.isLight ) {
66609
+
66610
+ sceneLights.push( object );
66611
+
66612
+ }
66613
+
66614
+ } );
66615
+
66616
+ lightsNode.setLights( sceneLights );
66617
+
66618
+ // update fog
66619
+ if ( this.prevFog !== scene.fog ) {
66620
+
66621
+ this.fogNode = this.getFogNode();
66622
+ this.prevFog = scene.fog;
66623
+
66624
+ }
66625
+
66626
+ // update environment
66627
+ if ( this.prevEnvironment !== scene.environment ) {
66628
+
66629
+ this.environmentNode = this.getEnvironmentNode();
66630
+ this.prevEnvironment = scene.environment;
66631
+
66632
+ }
66633
+
66634
+ }
66635
+
66636
+ getFogNode() {
66637
+
66638
+ const { scene } = this;
66639
+ if ( scene.fog && scene.fog.isFogExp2 ) {
66640
+
66641
+ const color = reference( 'color', 'color', scene.fog );
66642
+ const density = reference( 'density', 'float', scene.fog );
66643
+ return fog( color, densityFogFactor( density ) );
66644
+
66645
+ } else if ( scene.fog && scene.fog.isFog ) {
66646
+
66647
+ const color = reference( 'color', 'color', scene.fog );
66648
+ const near = reference( 'near', 'float', scene.fog );
66649
+ const far = reference( 'far', 'float', scene.fog );
66650
+ return fog( color, rangeFogFactor( near, far ) );
66651
+
66652
+ } else {
66653
+
66654
+ return null;
66655
+
66656
+ }
66657
+
66658
+ }
66659
+
66660
+ getEnvironmentNode() {
66661
+
66662
+ const { scene } = this;
66663
+ if ( scene.environment && scene.environment.isCubeTexture ) {
66664
+
66665
+ return cubeTexture( scene.environment );
66666
+
66667
+ } else if ( scene.environment && scene.environment.isTexture ) {
66668
+
66669
+ return texture( scene.environment );
66670
+
66671
+ } else {
66672
+
66673
+ return null;
66674
+
66675
+ }
66676
+
66677
+ }
66678
+
66679
+ }
66680
+
66681
+ class RendererProxy {
66682
+
66683
+ constructor( renderer ) {
66684
+
66685
+ const backend = {
66686
+ isWebGPUBackend: false,
66687
+ extensions: renderer.extensions,
66688
+ gl: renderer.getContext(),
66689
+ capabilities: null,
66690
+ };
66691
+
66692
+ backend.capabilities = new WebGLCapabilities( backend );
66693
+
66694
+ this.contextNode = context();
66695
+ this.inspector = new InspectorBase();
66696
+ this.library = new BasicNodeLibrary();
66697
+ this.lighting = new Lighting();
66698
+ this.backend = backend;
66699
+
66700
+ const self = this;
66701
+ return new Proxy( renderer, {
66702
+
66703
+ get( target, property ) {
66704
+
66705
+ return Reflect.get( property in self ? self : target, property );
66706
+
66707
+ },
66708
+
66709
+ set( target, property, value ) {
66710
+
66711
+ return Reflect.set( property in self ? self : target, property, value );
66712
+
66713
+ }
66714
+
66715
+ } );
66716
+
66717
+ }
66718
+
66719
+ hasInitialized() {
66720
+
66721
+ return true;
66722
+
66723
+ }
66724
+
66725
+ getMRT() {
66726
+
66727
+ return null;
66728
+
66729
+ }
66730
+
66731
+ hasCompatibility( name ) {
66732
+
66733
+ if ( name === Compatibility.TEXTURE_COMPARE ) {
66734
+
66735
+ return true;
66736
+
66737
+ }
66738
+
66739
+ return false;
66740
+
66741
+ }
66742
+
66743
+ getCacheKey() {
66744
+
66745
+ return this.toneMapping + this.outputColorSpace;
66746
+
66747
+ }
66748
+
66749
+ }
66750
+
66751
+ /**
66752
+ * Compatibility loader and builder for TSL Node materials in WebGLRenderer.
66753
+ */
66754
+ class WebGLNodesHandler {
66755
+
66756
+ /**
66757
+ * Constructs a new WebGL node adapter.
66758
+ */
66759
+ constructor() {
66760
+
66761
+ this.renderer = null;
66762
+ this.nodeFrame = new NodeFrame();
66763
+ this.sceneContexts = new WeakMap();
66764
+ this.programCache = new Map();
66765
+ this.renderStack = [];
66766
+
66767
+ const self = this;
66768
+ this.onDisposeMaterialCallback = function () {
66769
+
66770
+ // dispose of all the uniform groups
66771
+ const { programCache } = self;
66772
+ if ( programCache.has( this ) ) {
66773
+
66774
+ self.programCache.get( this ).forEach( ( { uniformsGroups } ) => {
66775
+
66776
+ uniformsGroups.forEach( u => u.dispose() );
66777
+
66778
+ } );
66779
+
66780
+ self.programCache.delete( this );
66781
+
66782
+ }
66783
+
66784
+ this.removeEventListener( 'dispose', self.onDisposeMaterialCallback );
66785
+
66786
+ };
66787
+
66788
+ this.getOutputCallback = function ( outputNode ) {
66789
+
66790
+ // apply tone mapping and color spaces to the output
66791
+ const { outputColorSpace, toneMapping } = self.renderer;
66792
+ outputNode = outputNode.toneMapping( toneMapping );
66793
+ outputNode = workingToColorSpace( outputNode, outputColorSpace );
66794
+
66795
+ return outputNode;
66796
+
66797
+ };
66798
+
66799
+ this.onBeforeRenderCallback = function ( renderer, scene, camera, geometry, object ) {
66800
+
66801
+ // update node frame references for update nodes
66802
+ const { nodeFrame } = self;
66803
+ nodeFrame.material = this;
66804
+ nodeFrame.object = object;
66805
+
66806
+ // increment "frame" here to force uniform buffers to update for the material, which otherwise only get
66807
+ // updated once per frame.
66808
+ renderer.info.render.frame ++;
66809
+
66810
+ // update the uniform groups and nodes for the program if they're available before rendering
66811
+ if ( renderer.properties.has( this ) ) {
66812
+
66813
+ const currentProgram = renderer.properties.get( this ).currentProgram;
66814
+ const programs = self.programCache.get( this );
66815
+ if ( programs && programs.has( currentProgram ) ) {
66816
+
66817
+ // update the nodes for the current object
66818
+ const { updateNodes } = programs.get( currentProgram );
66819
+ self.updateNodes( updateNodes );
66820
+
66821
+ }
66822
+
66823
+ }
66824
+
66825
+ const objectHash = getObjectHash( object );
66826
+ if ( this.prevObjectHash !== objectHash ) {
66827
+
66828
+ this.prevObjectHash = objectHash;
66829
+ this.needsUpdate = true;
66830
+
66831
+ }
66832
+
66833
+ };
66834
+
66835
+ this.customProgramCacheKeyCallback = function () {
66836
+
66837
+ const { renderStack, renderer, nodeFrame } = self;
66838
+ const sceneHash = renderStack[ renderStack.length - 1 ].sceneContext.getCacheKey();
66839
+ const materialHash = this.constructor.prototype.customProgramCacheKey.call( this );
66840
+ const rendererHash = renderer.getCacheKey();
66841
+
66842
+ return materialHash + sceneHash + rendererHash + getObjectHash( nodeFrame.object );
66843
+
66844
+ };
66845
+
66846
+ }
66847
+
66848
+ setRenderer( renderer ) {
66849
+
66850
+ const rendererProxy = new RendererProxy( renderer );
66851
+ this.nodeFrame.renderer = rendererProxy;
66852
+ this.renderer = rendererProxy;
66853
+
66854
+ }
66855
+
66856
+ onUpdateProgram( material, program, materialProperties ) {
66857
+
66858
+ const { programCache } = this;
66859
+ if ( ! programCache.has( material ) ) {
66860
+
66861
+ programCache.set( material, new Map() );
66862
+
66863
+ }
66864
+
66865
+ const programs = programCache.get( material );
66866
+ if ( ! programs.has( program ) ) {
66867
+
66868
+ const builder = material._latestBuilder;
66869
+ const uniforms = materialProperties.uniforms;
66870
+ programs.set( program, {
66871
+ uniformsGroups: this.collectUniformsGroups( builder ),
66872
+ uniforms: uniforms,
66873
+ uniformsList: generateUniformsList( program, uniforms ),
66874
+ updateNodes: builder.updateNodes,
66875
+ } );
66876
+
66877
+ }
66878
+
66879
+ const { uniformsGroups, uniforms, uniformsList, updateNodes } = programs.get( program );
66880
+ material.uniformsGroups = uniformsGroups;
66881
+ materialProperties.uniforms = uniforms;
66882
+ materialProperties.uniformsList = uniformsList;
66883
+ this.updateNodes( updateNodes );
66884
+
66885
+ }
66886
+
66887
+
66888
+ renderStart( scene, camera ) {
66889
+
66890
+ const { nodeFrame, renderStack, renderer, sceneContexts } = this;
66891
+ nodeFrame.update();
66892
+ nodeFrame.camera = camera;
66893
+ nodeFrame.scene = scene;
66894
+ nodeFrame.frameId ++;
66895
+
66896
+ let sceneContext = sceneContexts.get( scene );
66897
+ if ( ! sceneContext ) {
66898
+
66899
+ sceneContext = new SceneContext( renderer, scene );
66900
+ sceneContexts.set( scene, sceneContext );
66901
+
66902
+ }
66903
+
66904
+ sceneContext.update();
66905
+ renderStack.push( { sceneContext, camera } );
66906
+
66907
+ // ensure all node material callbacks are initialized before
66908
+ // traversal and build
66909
+ const {
66910
+ customProgramCacheKeyCallback,
66911
+ onBeforeRenderCallback,
66912
+ } = this;
66913
+
66914
+ scene.traverse( object => {
66915
+
66916
+ if ( object.material && object.material.isNodeMaterial ) {
66917
+
66918
+ object.material.customProgramCacheKey = customProgramCacheKeyCallback;
66919
+ object.material.onBeforeRender = onBeforeRenderCallback;
66920
+
66921
+ }
66922
+
66923
+ } );
66924
+
66925
+ }
66926
+
66927
+ renderEnd() {
66928
+
66929
+ const { nodeFrame, renderStack } = this;
66930
+
66931
+ renderStack.pop();
66932
+
66933
+ const frame = renderStack[ renderStack.length - 1 ];
66934
+ if ( frame ) {
66935
+
66936
+ const { camera, sceneContext } = frame;
66937
+ nodeFrame.camera = camera;
66938
+ nodeFrame.scene = sceneContext.scene;
66939
+
66940
+ }
66941
+
66942
+ }
66943
+
66944
+ build( material, object, parameters ) {
66945
+
66946
+ const {
66947
+ nodeFrame,
66948
+ renderer,
66949
+ getOutputCallback,
66950
+ onDisposeMaterialCallback,
66951
+ renderStack,
66952
+ } = this;
66953
+
66954
+ const {
66955
+ camera,
66956
+ sceneContext,
66957
+ } = renderStack[ renderStack.length - 1 ];
66958
+
66959
+ const {
66960
+ fogNode,
66961
+ environmentNode,
66962
+ lightsNode,
66963
+ scene,
66964
+ } = sceneContext;
66965
+
66966
+ // prepare the frame
66967
+ nodeFrame.material = material;
66968
+ nodeFrame.object = object;
66969
+
66970
+ // create & run the builder
66971
+ const builder = new WebGLNodeBuilder( object, renderer );
66972
+ builder.scene = scene;
66973
+ builder.camera = camera;
66974
+ builder.material = material;
66975
+ builder.fogNode = fogNode;
66976
+ builder.environmentNode = environmentNode;
66977
+ builder.lightsNode = lightsNode;
66978
+ builder.context.getOutput = getOutputCallback;
66979
+ builder.build();
66980
+
66981
+ // update the shader parameters and geometry for program creation and rendering
66982
+ this.updateShaderParameters( builder, parameters );
66983
+ this.updateGeometryAttributes( builder, object.geometry );
66984
+
66985
+ // reset node frame settings to account for any intermediate renders
66986
+ nodeFrame.material = material;
66987
+ nodeFrame.object = object;
66988
+
66989
+ // set up callbacks for uniforms and node updates
66990
+ material._latestBuilder = builder;
66991
+ material.addEventListener( 'dispose', onDisposeMaterialCallback );
66992
+ this.updateNodes( builder.updateNodes );
66993
+
66994
+ }
66995
+
66996
+ updateGeometryAttributes( builder, geometry ) {
66997
+
66998
+ // TODO: this may cause issues if the material / geometry is used in multiple places
66999
+
67000
+ // add instancing attributes
67001
+ builder.bufferAttributes.forEach( v => {
67002
+
67003
+ geometry.setAttribute( v.name, v.node.attribute );
67004
+
67005
+ } );
67006
+
67007
+ // force WebGLAttributes & WebGLBindingStates to refresh
67008
+ // could be fixed by running "build" sooner? Or calling "WebGLAttributes" separately for those
67009
+ // associated with a material?
67010
+ queueMicrotask( () => geometry.dispose() );
67011
+
67012
+ }
67013
+
67014
+ updateShaderParameters( builder, parameters ) {
67015
+
67016
+ // set up shaders
67017
+ parameters.isRawShaderMaterial = true;
67018
+ parameters.glslVersion = GLSL3;
67019
+ parameters.vertexShader = builder.vertexShader.replace( /#version 300 es/, '' );
67020
+ parameters.fragmentShader = builder.fragmentShader.replace( /#version 300 es/, '' );
67021
+
67022
+ // add uniforms accessed by WebGLRenderer
67023
+ parameters.uniforms = {
67024
+ fogColor: { value: new Color() },
67025
+ fogNear: { value: 0 },
67026
+ fogFar: { value: 0 },
67027
+ envMapIntensity: { value: 0 },
67028
+ ...UniformsUtils.clone( UniformsLib.lights )
67029
+ };
67030
+
67031
+ // init uniforms
67032
+ const builderUniforms = [ ...builder.uniforms.vertex, ...builder.uniforms.fragment ];
67033
+ for ( const uniform of builderUniforms ) {
67034
+
67035
+ parameters.uniforms[ uniform.name ] = uniform.node;
67036
+
67037
+ }
67038
+
67039
+ }
67040
+
67041
+ collectUniformsGroups( builder ) {
67042
+
67043
+ // create UniformsGroups for regular grouped uniforms
67044
+ const uniformsGroups = [];
67045
+ for ( const key in builder.uniformGroups ) {
67046
+
67047
+ const { uniforms } = builder.uniformGroups[ key ];
67048
+ const group = new UniformsGroup();
67049
+ group.name = key;
67050
+ group.uniforms = uniforms.map( node => node.nodeUniform );
67051
+ uniformsGroups.push( group );
67052
+
67053
+ }
67054
+
67055
+ // init uniforms
67056
+ const builderUniforms = [ ...builder.uniforms.vertex, ...builder.uniforms.fragment ];
67057
+ for ( const uniform of builderUniforms ) {
67058
+
67059
+ if ( uniform.type === 'buffer' ) {
67060
+
67061
+ // buffer uniforms are all nested in groups
67062
+ const group = new UniformsGroup();
67063
+ group.name = uniform.node.name;
67064
+ group.uniforms = [ uniform ];
67065
+ uniformsGroups.push( group );
67066
+
67067
+ }
67068
+
67069
+ }
67070
+
67071
+ return uniformsGroups;
67072
+
67073
+ }
67074
+
67075
+ updateNodes( updateNodes ) {
67076
+
67077
+ // update nodes for render
67078
+ const { nodeFrame } = this;
67079
+ nodeFrame.renderId ++;
67080
+ for ( const node of updateNodes ) {
67081
+
67082
+ nodeFrame.updateNode( node );
67083
+
67084
+ }
67085
+
67086
+ }
67087
+
67088
+ }
67089
+
66344
67090
  // -----------------------------------------------------------------------------------------------------------
66345
67091
  // __ ______ __ __ ______ __ __ ______ ______ ______
66346
67092
  // /\ \ /\ ___\ /\ "-./ \ /\ __ \ /\ "-.\ \ /\ __ \ /\__ _\ /\ ___\
@@ -68260,7 +69006,7 @@ class Renderer {
68260
69006
  options;
68261
69007
  renderView = null;
68262
69008
  webGlRenderer;
68263
- //webGpuRenderer: WebGPURenderer;
69009
+ webGlNodesHandler;
68264
69010
  raycaster;
68265
69011
  renderers = {};
68266
69012
  requestFrameFuncs = [];
@@ -68337,7 +69083,8 @@ class Renderer {
68337
69083
  this.layers.push(`Layer ${i + 1}`);
68338
69084
  }
68339
69085
  this.webGlRenderer = this._createWebGlRenderer(options);
68340
- //this.webGpuRenderer = this._createWebGpuRenderer();
69086
+ this.webGlNodesHandler = new WebGLNodesHandler();
69087
+ this.webGlRenderer.setNodesHandler(this.webGlNodesHandler);
68341
69088
  this.setDevicePixelRatio();
68342
69089
  this.setShadowType(ShadowMode.Pcf);
68343
69090
  this.setRendererSettings();
@@ -68410,22 +69157,6 @@ class Renderer {
68410
69157
  webGlRenderer.setSize(this.width, this.height);
68411
69158
  return webGlRenderer;
68412
69159
  }
68413
- _createWebGpuRenderer() {
68414
- const gl = this.webGlRenderer.getContext();
68415
- if (!gl) {
68416
- throw new Error('Renderer._createWebGpuRenderer: WebGL2 context required.');
68417
- }
68418
- const webGpuRenderer = new WebGPURenderer({
68419
- forceWebGL: true,
68420
- canvas: this.webGlRenderer.domElement,
68421
- context: gl,
68422
- depth: true,
68423
- antialias: false,
68424
- alpha: true
68425
- });
68426
- webGpuRenderer.setSize(this.width, this.height);
68427
- return webGpuRenderer;
68428
- }
68429
69160
  async init() {
68430
69161
  try {
68431
69162
  await loadFontFace("OpenSansRegular", openSansRegularUrl);
@@ -68438,9 +69169,6 @@ class Renderer {
68438
69169
  getWebGLRenderer() {
68439
69170
  return this.webGlRenderer;
68440
69171
  }
68441
- /*getWebGPURenderer(): WebGPURenderer {
68442
- return this.webGpuRenderer;
68443
- }*/
68444
69172
  hookEvents() {
68445
69173
  if (this.renderView) {
68446
69174
  // We have to remember the pressed buttons of the pointer controller because we will only ever receive a single
@@ -76649,6 +77377,22 @@ class TextGeometry extends ExtrudeGeometry {
76649
77377
 
76650
77378
  }
76651
77379
 
77380
+ toJSON() {
77381
+
77382
+ const data = super.toJSON();
77383
+ return data;
77384
+
77385
+ }
77386
+
77387
+ static fromJSON( data ) {
77388
+
77389
+ const options = data.options;
77390
+
77391
+ options.font = new Font( options.font.data );
77392
+ return new TextGeometry( options.text, options );
77393
+
77394
+ }
77395
+
76652
77396
  }
76653
77397
 
76654
77398
  var glyphs = {
@@ -80733,6 +81477,16 @@ class SgTorus extends SgProceduralGeometryItem {
80733
81477
  * sky.scale.setScalar( 10000 );
80734
81478
  * scene.add( sky );
80735
81479
  * ```
81480
+ *
81481
+ * It can be useful to hide the sun disc when generating an environment map to avoid artifacts
81482
+ *
81483
+ * ```js
81484
+ * // disable before rendering environment map
81485
+ * sky.material.uniforms.showSunDisc.value = false;
81486
+ * // ...
81487
+ * // re-enable before scene sky box rendering
81488
+ * sky.material.uniforms.showSunDisc.value = true;
81489
+ * ```
80736
81490
  *
80737
81491
  * @augments Mesh
80738
81492
  * @three_import import { Sky } from 'three/addons/objects/Sky.js';
@@ -80780,7 +81534,14 @@ Sky.SkyShader = {
80780
81534
  'mieCoefficient': { value: 0.005 },
80781
81535
  'mieDirectionalG': { value: 0.8 },
80782
81536
  'sunPosition': { value: new Vector3() },
80783
- 'up': { value: new Vector3( 0, 1, 0 ) }
81537
+ 'up': { value: new Vector3( 0, 1, 0 ) },
81538
+ 'cloudScale': { value: 0.0002 },
81539
+ 'cloudSpeed': { value: 0.0001 },
81540
+ 'cloudCoverage': { value: 0.4 },
81541
+ 'cloudDensity': { value: 0.4 },
81542
+ 'cloudElevation': { value: 0.5 },
81543
+ 'showSunDisc': { value: 1 },
81544
+ 'time': { value: 0.0 }
80784
81545
  },
80785
81546
 
80786
81547
  vertexShader: /* glsl */`
@@ -80858,13 +81619,46 @@ Sky.SkyShader = {
80858
81619
  fragmentShader: /* glsl */`
80859
81620
  varying vec3 vWorldPosition;
80860
81621
  varying vec3 vSunDirection;
80861
- varying float vSunfade;
80862
81622
  varying vec3 vBetaR;
80863
81623
  varying vec3 vBetaM;
80864
81624
  varying float vSunE;
80865
81625
 
80866
81626
  uniform float mieDirectionalG;
80867
81627
  uniform vec3 up;
81628
+ uniform float cloudScale;
81629
+ uniform float cloudSpeed;
81630
+ uniform float cloudCoverage;
81631
+ uniform float cloudDensity;
81632
+ uniform float cloudElevation;
81633
+ uniform float showSunDisc;
81634
+ uniform float time;
81635
+
81636
+ // Cloud noise functions
81637
+ float hash( vec2 p ) {
81638
+ return fract( sin( dot( p, vec2( 127.1, 311.7 ) ) ) * 43758.5453123 );
81639
+ }
81640
+
81641
+ float noise( vec2 p ) {
81642
+ vec2 i = floor( p );
81643
+ vec2 f = fract( p );
81644
+ f = f * f * ( 3.0 - 2.0 * f );
81645
+ float a = hash( i );
81646
+ float b = hash( i + vec2( 1.0, 0.0 ) );
81647
+ float c = hash( i + vec2( 0.0, 1.0 ) );
81648
+ float d = hash( i + vec2( 1.0, 1.0 ) );
81649
+ return mix( mix( a, b, f.x ), mix( c, d, f.x ), f.y );
81650
+ }
81651
+
81652
+ float fbm( vec2 p ) {
81653
+ float value = 0.0;
81654
+ float amplitude = 0.5;
81655
+ for ( int i = 0; i < 5; i ++ ) {
81656
+ value += amplitude * noise( p );
81657
+ p *= 2.0;
81658
+ amplitude *= 0.5;
81659
+ }
81660
+ return value;
81661
+ }
80868
81662
 
80869
81663
  // constants for atmospheric scattering
80870
81664
  const float pi = 3.141592653589793238462643383279502884197169;
@@ -80926,14 +81720,48 @@ Sky.SkyShader = {
80926
81720
  vec3 L0 = vec3( 0.1 ) * Fex;
80927
81721
 
80928
81722
  // composition + solar disc
80929
- float sundisk = smoothstep( sunAngularDiameterCos, sunAngularDiameterCos + 0.00002, cosTheta );
80930
- L0 += ( vSunE * 19000.0 * Fex ) * sundisk;
81723
+ float sundisc = smoothstep( sunAngularDiameterCos, sunAngularDiameterCos + 0.00002, cosTheta ) * showSunDisc;
81724
+ L0 += ( vSunE * 19000.0 * Fex ) * sundisc;
80931
81725
 
80932
81726
  vec3 texColor = ( Lin + L0 ) * 0.04 + vec3( 0.0, 0.0003, 0.00075 );
80933
81727
 
80934
- vec3 retColor = pow( texColor, vec3( 1.0 / ( 1.2 + ( 1.2 * vSunfade ) ) ) );
81728
+ // Clouds
81729
+ if ( direction.y > 0.0 && cloudCoverage > 0.0 ) {
81730
+
81731
+ // Project to cloud plane (higher elevation = clouds appear lower/closer)
81732
+ float elevation = mix( 1.0, 0.1, cloudElevation );
81733
+ vec2 cloudUV = direction.xz / ( direction.y * elevation );
81734
+ cloudUV *= cloudScale;
81735
+ cloudUV += time * cloudSpeed;
81736
+
81737
+ // Multi-octave noise for fluffy clouds
81738
+ float cloudNoise = fbm( cloudUV * 1000.0 );
81739
+ cloudNoise += 0.5 * fbm( cloudUV * 2000.0 + 3.7 );
81740
+ cloudNoise = cloudNoise * 0.5 + 0.5;
81741
+
81742
+ // Apply coverage threshold
81743
+ float cloudMask = smoothstep( 1.0 - cloudCoverage, 1.0 - cloudCoverage + 0.3, cloudNoise );
81744
+
81745
+ // Fade clouds near horizon (adjusted by elevation)
81746
+ float horizonFade = smoothstep( 0.0, 0.1 + 0.2 * cloudElevation, direction.y );
81747
+ cloudMask *= horizonFade;
81748
+
81749
+ // Cloud lighting based on sun position
81750
+ float sunInfluence = dot( direction, vSunDirection ) * 0.5 + 0.5;
81751
+ float daylight = max( 0.0, vSunDirection.y * 2.0 );
80935
81752
 
80936
- gl_FragColor = vec4( retColor, 1.0 );
81753
+ // Base cloud color affected by atmosphere
81754
+ vec3 atmosphereColor = Lin * 0.04;
81755
+ vec3 cloudColor = mix( vec3( 0.3 ), vec3( 1.0 ), daylight );
81756
+ cloudColor = mix( cloudColor, atmosphereColor + vec3( 1.0 ), sunInfluence * 0.5 );
81757
+ cloudColor *= vSunE * 0.00002;
81758
+
81759
+ // Blend clouds with sky
81760
+ texColor = mix( texColor, cloudColor, cloudMask * cloudDensity );
81761
+
81762
+ }
81763
+
81764
+ gl_FragColor = vec4( texColor, 1.0 );
80937
81765
 
80938
81766
  #include <tonemapping_fragment>
80939
81767
  #include <colorspace_fragment>
@@ -80992,12 +81820,24 @@ class SgSky extends SgItem {
80992
81820
  const mieDirectionalG = this.getFieldValue("MieDirectionalG");
80993
81821
  const inclination = this.getFieldValue("Inclination");
80994
81822
  const azimuth = this.getFieldValue("Azimuth");
81823
+ const showSunDisc = this.getFieldValue("ShowSunDisc");
81824
+ const cloudScale = this.getFieldValue("CloudScale");
81825
+ const cloudSpeed = this.getFieldValue("CloudSpeed");
81826
+ const cloudCoverage = this.getFieldValue("CloudCoverage");
81827
+ const cloudDensity = this.getFieldValue("CloudDensity");
81828
+ const cloudElevation = this.getFieldValue("CloudElevation");
80995
81829
  await this.recreateObject(async () => {
80996
81830
  this.mesh = new Sky();
80997
81831
  this.mesh.scale.setScalar(size);
80998
81832
  this.inclination = inclination;
80999
81833
  this.azimuth = azimuth;
81000
81834
  this.size = size;
81835
+ this.setUniformValue("cloudScale", cloudScale / 100);
81836
+ this.setUniformValue("cloudSpeed", cloudSpeed / 100);
81837
+ this.setUniformValue("cloudCoverage", cloudCoverage);
81838
+ this.setUniformValue("cloudDensity", cloudDensity);
81839
+ this.setUniformValue("cloudElevation", cloudElevation);
81840
+ this.setUniformValue("showSunDisc", showSunDisc);
81001
81841
  this.setUniformValue("turbidity", turbidity);
81002
81842
  this.setUniformValue("rayleigh", rayleigh);
81003
81843
  this.setUniformValue("mieCoefficient", mieCoefficient);
@@ -81027,6 +81867,9 @@ class SgSky extends SgItem {
81027
81867
  console.log("Could not find object to set uniform on");
81028
81868
  }
81029
81869
  }
81870
+ update(deltaTimeMs) {
81871
+ this.setUniformValue("time", performance.now() * 0.001);
81872
+ }
81030
81873
  updateEvent(field, value, type, oldValue) {
81031
81874
  if (super.updateEvent(field, value, type, oldValue))
81032
81875
  return true;
@@ -81058,6 +81901,24 @@ class SgSky extends SgItem {
81058
81901
  this.azimuth = value;
81059
81902
  this.setSunPosition(this.inclination, this.azimuth);
81060
81903
  break;
81904
+ case "ShowSunDisc":
81905
+ this.setUniformValue("showSunDisc", value);
81906
+ break;
81907
+ case "CloudScale":
81908
+ this.setUniformValue("cloudScale", value / 100);
81909
+ break;
81910
+ case "CloudSpeed":
81911
+ this.setUniformValue("cloudSpeed", value / 100);
81912
+ break;
81913
+ case "CloudCoverage":
81914
+ this.setUniformValue("cloudCoverage", value);
81915
+ break;
81916
+ case "CloudDensity":
81917
+ this.setUniformValue("cloudDensity", value);
81918
+ break;
81919
+ case "CloudElevation":
81920
+ this.setUniformValue("cloudElevation", value);
81921
+ break;
81061
81922
  default:
81062
81923
  return false;
81063
81924
  }
@@ -84018,7 +84879,7 @@ class ParticleSystem {
84018
84879
  particleCount;
84019
84880
  width;
84020
84881
  height;
84021
- time = new Clock$1();
84882
+ timer = new Timer$1();
84022
84883
  elapsedTime = 0;
84023
84884
  timeSinceLastSpawn = 0;
84024
84885
  isRunning = true;
@@ -84610,7 +85471,7 @@ class ParticleSystem {
84610
85471
  this.elapsedTime = 0;
84611
85472
  this.timeSinceLastSpawn = this.spawnRate; // force spawn at the next update
84612
85473
  this.emissionCounter = 0;
84613
- this.time.start(); // reset the simulation clock
85474
+ this.timer.reset(); // reset the simulation clock
84614
85475
  }
84615
85476
  killAllParticles() {
84616
85477
  this.simulation.killAllParticles();
@@ -84636,7 +85497,7 @@ class ParticleSystem {
84636
85497
  render(delta) {
84637
85498
  if (!this.isRunning || this.isPaused)
84638
85499
  return;
84639
- delta ??= this.time.getDelta();
85500
+ delta ??= this.timer.getDelta();
84640
85501
  if (this.duration !== -1 && this.elapsedTime > this.duration) {
84641
85502
  this.killAllParticles();
84642
85503
  this.hideParticles();
@@ -85949,7 +86810,7 @@ class SgAudio extends SgItem {
85949
86810
  if (!this.stereoPanner) {
85950
86811
  this.stereoPanner = this.audio.context.createStereoPanner();
85951
86812
  }
85952
- this.audio.filters = [this.stereoPanner];
86813
+ this.audio.setFilters([this.stereoPanner]);
85953
86814
  }
85954
86815
  }
85955
86816
  enumerateItemChildren() {
@@ -86131,7 +86992,7 @@ class SgAudio extends SgItem {
86131
86992
  _setAudioProps() {
86132
86993
  if (!this.audio)
86133
86994
  return;
86134
- this.audio.loop = this.getFieldValue("Loop");
86995
+ this.audio.setLoop(this.getFieldValue("Loop"));
86135
86996
  const loopSection = this.getFieldValue("LoopSection");
86136
86997
  if (loopSection) {
86137
86998
  this.audio.setLoopStart(this.getFieldValue("LoopStart"));
@@ -111063,6 +111924,7 @@ const KHR_mesh_quantization_ExtraAttrTypes = {
111063
111924
  * - KHR_texture_transform
111064
111925
  * - EXT_materials_bump
111065
111926
  * - EXT_mesh_gpu_instancing
111927
+ * - EXT_texture_webp
111066
111928
  *
111067
111929
  * The following glTF 2.0 extension is supported by an external user plugin:
111068
111930
  *
@@ -112505,15 +113367,30 @@ class GLTFWriter {
112505
113367
 
112506
113368
  }
112507
113369
 
112508
- let mimeType = map.userData.mimeType;
113370
+ const mimeType = map.userData.mimeType;
112509
113371
 
112510
- if ( mimeType === 'image/webp' ) mimeType = 'image/png';
113372
+ const imageIndex = this.processImage( map.image, map.format, map.flipY, mimeType );
112511
113373
 
112512
113374
  const textureDef = {
112513
- sampler: this.processSampler( map ),
112514
- source: this.processImage( map.image, map.format, map.flipY, mimeType )
113375
+ sampler: this.processSampler( map )
112515
113376
  };
112516
113377
 
113378
+ if ( mimeType === 'image/webp' ) {
113379
+
113380
+ textureDef.extensions = textureDef.extensions || {};
113381
+ textureDef.extensions[ 'EXT_texture_webp' ] = {
113382
+ source: imageIndex
113383
+ };
113384
+
113385
+ this.extensionsUsed[ 'EXT_texture_webp' ] = true;
113386
+ this.extensionsRequired[ 'EXT_texture_webp' ] = true;
113387
+
113388
+ } else {
113389
+
113390
+ textureDef.source = imageIndex;
113391
+
113392
+ }
113393
+
112517
113394
  if ( map.name ) textureDef.name = map.name;
112518
113395
 
112519
113396
  await this._invokeAllAsync( async function ( ext ) {
@@ -112804,7 +113681,7 @@ class GLTFWriter {
112804
113681
  const validVertexAttributes =
112805
113682
  /^(POSITION|NORMAL|TANGENT|TEXCOORD_\d+|COLOR_\d+|JOINTS_\d+|WEIGHTS_\d+)$/;
112806
113683
 
112807
- if ( ! validVertexAttributes.test( attributeName ) ) attributeName = '_' + attributeName;
113684
+ if ( ! validVertexAttributes.test( attributeName ) && ! attributeName.startsWith( '_' ) ) attributeName = '_' + attributeName;
112808
113685
 
112809
113686
  if ( cache.attributes.has( this.getUID( attribute ) ) ) {
112810
113687
 
@@ -112824,12 +113701,12 @@ class GLTFWriter {
112824
113701
  ! ( array instanceof Uint8Array ) ) {
112825
113702
 
112826
113703
  console.warn( 'GLTFExporter: Attribute "skinIndex" converted to type UNSIGNED_SHORT.' );
112827
- modifiedAttribute = new BufferAttribute( new Uint16Array( array ), attribute.itemSize, attribute.normalized );
113704
+ modifiedAttribute = GLTFExporter.Utils.toTypedBufferAttribute( attribute, Uint16Array );
112828
113705
 
112829
113706
  } else if ( ( array instanceof Uint32Array || array instanceof Int32Array ) && ! attributeName.startsWith( '_' ) ) {
112830
113707
 
112831
113708
  console.warn( `GLTFExporter: Attribute "${ attributeName }" converted to type FLOAT.` );
112832
- modifiedAttribute = GLTFExporter.Utils.toFloat32BufferAttribute( attribute );
113709
+ modifiedAttribute = GLTFExporter.Utils.toTypedBufferAttribute( attribute, Float32Array );
112833
113710
 
112834
113711
  }
112835
113712
 
@@ -113327,6 +114204,13 @@ class GLTFWriter {
113327
114204
 
113328
114205
  if ( ! json.nodes ) json.nodes = [];
113329
114206
 
114207
+ // Handle pivot by creating a container node
114208
+ if ( object.pivot !== null ) {
114209
+
114210
+ return await this._processNodeWithPivotAsync( object );
114211
+
114212
+ }
114213
+
113330
114214
  const nodeDef = {};
113331
114215
 
113332
114216
  if ( options.trs ) {
@@ -113423,6 +114307,126 @@ class GLTFWriter {
113423
114307
 
113424
114308
  }
113425
114309
 
114310
+ /**
114311
+ * Process Object3D node with pivot using container approach
114312
+ * @param {THREE.Object3D} object Object3D with pivot
114313
+ * @return {Promise<number>} Index of the container node
114314
+ */
114315
+ async _processNodeWithPivotAsync( object ) {
114316
+
114317
+ const json = this.json;
114318
+ const options = this.options;
114319
+ const nodeMap = this.nodeMap;
114320
+
114321
+ const pivot = object.pivot;
114322
+
114323
+ // Container node: holds position + pivot offset, rotation, scale
114324
+ // Animations will target this node
114325
+ const containerDef = {};
114326
+
114327
+ const rotation = object.quaternion.toArray();
114328
+ const position = [
114329
+ object.position.x + pivot.x,
114330
+ object.position.y + pivot.y,
114331
+ object.position.z + pivot.z
114332
+ ];
114333
+ const scale = object.scale.toArray();
114334
+
114335
+ if ( ! equalArray( rotation, [ 0, 0, 0, 1 ] ) ) {
114336
+
114337
+ containerDef.rotation = rotation;
114338
+
114339
+ }
114340
+
114341
+ if ( ! equalArray( position, [ 0, 0, 0 ] ) ) {
114342
+
114343
+ containerDef.translation = position;
114344
+
114345
+ }
114346
+
114347
+ if ( ! equalArray( scale, [ 1, 1, 1 ] ) ) {
114348
+
114349
+ containerDef.scale = scale;
114350
+
114351
+ }
114352
+
114353
+ // Store pivot in extras for round-trip reconstruction
114354
+ containerDef.extras = { pivot: pivot.toArray() };
114355
+
114356
+ if ( object.name !== '' ) containerDef.name = String( object.name );
114357
+
114358
+ this.serializeUserData( object, containerDef );
114359
+
114360
+ const containerIndex = json.nodes.push( containerDef ) - 1;
114361
+
114362
+ // Map original object to container so animations target it
114363
+ nodeMap.set( object, containerIndex );
114364
+
114365
+ // Child node: holds mesh with -pivot offset
114366
+ const childDef = {};
114367
+
114368
+ const childPosition = [ - pivot.x, - pivot.y, - pivot.z ];
114369
+
114370
+ if ( ! equalArray( childPosition, [ 0, 0, 0 ] ) ) {
114371
+
114372
+ childDef.translation = childPosition;
114373
+
114374
+ }
114375
+
114376
+ if ( object.isMesh || object.isLine || object.isPoints ) {
114377
+
114378
+ const meshIndex = await this.processMeshAsync( object );
114379
+
114380
+ if ( meshIndex !== null ) childDef.mesh = meshIndex;
114381
+
114382
+ } else if ( object.isCamera ) {
114383
+
114384
+ childDef.camera = this.processCamera( object );
114385
+
114386
+ }
114387
+
114388
+ if ( object.isSkinnedMesh ) this.skins.push( object );
114389
+
114390
+ const childIndex = json.nodes.push( childDef ) - 1;
114391
+
114392
+ // Build children array for container
114393
+ const containerChildren = [ childIndex ];
114394
+
114395
+ // Process object's children as children of the child node
114396
+ if ( object.children.length > 0 ) {
114397
+
114398
+ const grandchildren = [];
114399
+
114400
+ for ( let i = 0, l = object.children.length; i < l; i ++ ) {
114401
+
114402
+ const child = object.children[ i ];
114403
+
114404
+ if ( child.visible || options.onlyVisible === false ) {
114405
+
114406
+ const childNodeIndex = await this.processNodeAsync( child );
114407
+
114408
+ if ( childNodeIndex !== null ) grandchildren.push( childNodeIndex );
114409
+
114410
+ }
114411
+
114412
+ }
114413
+
114414
+ if ( grandchildren.length > 0 ) childDef.children = grandchildren;
114415
+
114416
+ }
114417
+
114418
+ containerDef.children = containerChildren;
114419
+
114420
+ await this._invokeAllAsync( function ( ext ) {
114421
+
114422
+ ext.writeNode && ext.writeNode( object, containerDef );
114423
+
114424
+ } );
114425
+
114426
+ return containerIndex;
114427
+
114428
+ }
114429
+
113426
114430
  /**
113427
114431
  * Process Scene
113428
114432
  * @param {Scene} scene Scene to process
@@ -114510,9 +115514,9 @@ GLTFExporter.Utils = {
114510
115514
 
114511
115515
  },
114512
115516
 
114513
- toFloat32BufferAttribute: function ( srcAttribute ) {
115517
+ toTypedBufferAttribute: function ( srcAttribute, TypedArray ) {
114514
115518
 
114515
- const dstAttribute = new BufferAttribute( new Float32Array( srcAttribute.count * srcAttribute.itemSize ), srcAttribute.itemSize, false );
115519
+ const dstAttribute = new BufferAttribute( new TypedArray( srcAttribute.count * srcAttribute.itemSize ), srcAttribute.itemSize, false );
114516
115520
 
114517
115521
  if ( ! srcAttribute.normalized && ! srcAttribute.isInterleavedBufferAttribute ) {
114518
115522