@needle-tools/engine 5.1.12 → 5.1.14

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.
Files changed (149) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/SKILL.md +1 -1
  3. package/dist/gltf-progressive-BnLTsXZw.umd.cjs +10 -0
  4. package/dist/gltf-progressive-D6RT9IkB.min.js +10 -0
  5. package/dist/{gltf-progressive-B4DQEeBz.js → gltf-progressive-DaeP5KBr.js} +527 -514
  6. package/dist/{materialx-BBv-42Th.min.js → materialx-D3ZU4CP6.min.js} +1 -1
  7. package/dist/{materialx-0m1xlF5m.js → materialx-FhjQQgNu.js} +1 -1
  8. package/dist/{materialx-8OpPwNc7.umd.cjs → materialx-RxB3AN7d.umd.cjs} +2 -2
  9. package/dist/{needle-engine.bundle-9m-VdGg2.js → needle-engine.bundle-BEa7CABw.js} +7420 -7254
  10. package/dist/{needle-engine.bundle-BmdWLmLa.min.js → needle-engine.bundle-mkmiuKZB.min.js} +145 -145
  11. package/dist/{needle-engine.bundle-DdH96IqH.umd.cjs → needle-engine.bundle-y1_E7Ovt.umd.cjs} +146 -146
  12. package/dist/needle-engine.d.ts +37 -29
  13. package/dist/needle-engine.js +519 -520
  14. package/dist/needle-engine.min.js +1 -1
  15. package/dist/needle-engine.umd.cjs +1 -1
  16. package/dist/{vendor-DiDMDryv.js → vendor-BVzQovzJ.js} +5161 -5161
  17. package/dist/{vendor-DE_m5MvL.umd.cjs → vendor-C5YVRzxf.umd.cjs} +5 -5
  18. package/dist/{vendor-B7IfFLrR.min.js → vendor-rvNvQ-IU.min.js} +5 -5
  19. package/lib/engine/api.d.ts +4 -3
  20. package/lib/engine/api.js +3 -9
  21. package/lib/engine/api.js.map +1 -1
  22. package/lib/engine/engine_addressables.d.ts +32 -1
  23. package/lib/engine/engine_addressables.js +71 -9
  24. package/lib/engine/engine_addressables.js.map +1 -1
  25. package/lib/engine/engine_application.d.ts +2 -0
  26. package/lib/engine/engine_application.js +7 -3
  27. package/lib/engine/engine_application.js.map +1 -1
  28. package/lib/engine/engine_context.js +25 -1
  29. package/lib/engine/engine_context.js.map +1 -1
  30. package/lib/engine/engine_gameobject.js +1 -1
  31. package/lib/engine/engine_gameobject.js.map +1 -1
  32. package/lib/engine/engine_gltf_builtin_components.js +1 -1
  33. package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
  34. package/lib/engine/engine_init.js +2 -2
  35. package/lib/engine/engine_init.js.map +1 -1
  36. package/lib/engine/engine_input.js +1 -1
  37. package/lib/engine/engine_input.js.map +1 -1
  38. package/lib/engine/engine_instantiate_resolve.js.map +1 -1
  39. package/lib/engine/engine_license.d.ts +7 -7
  40. package/lib/engine/engine_license.js +123 -80
  41. package/lib/engine/engine_license.js.map +1 -1
  42. package/lib/engine/engine_lifecycle_functions_internal.js +20 -2
  43. package/lib/engine/engine_lifecycle_functions_internal.js.map +1 -1
  44. package/lib/engine/engine_materialpropertyblock.js +18 -0
  45. package/lib/engine/engine_materialpropertyblock.js.map +1 -1
  46. package/lib/engine/engine_networking.d.ts +1 -1
  47. package/lib/engine/engine_networking.js +1 -1
  48. package/lib/engine/engine_networking.js.map +1 -1
  49. package/lib/engine/engine_networking_blob.js +3 -3
  50. package/lib/engine/engine_networking_blob.js.map +1 -1
  51. package/lib/engine/engine_networking_streams.d.ts +3 -0
  52. package/lib/engine/engine_networking_streams.js +64 -17
  53. package/lib/engine/engine_networking_streams.js.map +1 -1
  54. package/lib/engine/engine_utils_qrcode.js +2 -2
  55. package/lib/engine/engine_utils_qrcode.js.map +1 -1
  56. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +5 -0
  57. package/lib/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js.map +1 -1
  58. package/lib/engine/webcomponents/fonts.d.ts +1 -1
  59. package/lib/engine/webcomponents/fonts.js +16 -1
  60. package/lib/engine/webcomponents/fonts.js.map +1 -1
  61. package/lib/engine/webcomponents/icons.js +8 -1
  62. package/lib/engine/webcomponents/icons.js.map +1 -1
  63. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js +2 -2
  64. package/lib/engine/webcomponents/needle menu/needle-menu-spatial.js.map +1 -1
  65. package/lib/engine/webcomponents/needle menu/needle-menu.d.ts +5 -0
  66. package/lib/engine/webcomponents/needle menu/needle-menu.js +34 -16
  67. package/lib/engine/webcomponents/needle menu/needle-menu.js.map +1 -1
  68. package/lib/engine/webcomponents/needle-engine.d.ts +1 -0
  69. package/lib/engine/webcomponents/needle-engine.js +18 -6
  70. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  71. package/lib/engine/webcomponents/needle-engine.loading.d.ts +2 -0
  72. package/lib/engine/webcomponents/needle-engine.loading.js +12 -2
  73. package/lib/engine/webcomponents/needle-engine.loading.js.map +1 -1
  74. package/lib/engine/xr/NeedleXRSession.js +11 -10
  75. package/lib/engine/xr/NeedleXRSession.js.map +1 -1
  76. package/lib/engine/xr/TempXRContext.js +2 -2
  77. package/lib/engine/xr/TempXRContext.js.map +1 -1
  78. package/lib/engine-components/AnimationBuilder.d.ts +1 -1
  79. package/lib/engine-components/AnimationBuilder.js.map +1 -1
  80. package/lib/engine-components/AnimatorController.builder.d.ts +2 -2
  81. package/lib/engine-components/AnimatorController.builder.js +2 -2
  82. package/lib/engine-components/AnimatorController.builder.js.map +1 -1
  83. package/lib/engine-components/Component.d.ts +1 -1
  84. package/lib/engine-components/Component.js +1 -1
  85. package/lib/engine-components/Component.js.map +1 -1
  86. package/lib/engine-components/DragControls.d.ts +2 -2
  87. package/lib/engine-components/DragControls.js +2 -2
  88. package/lib/engine-components/DragControls.js.map +1 -1
  89. package/lib/engine-components/DragControlsConstraints.js.map +1 -1
  90. package/lib/engine-components/Light.js +1 -1
  91. package/lib/engine-components/Light.js.map +1 -1
  92. package/lib/engine-components/api.d.ts +2 -2
  93. package/lib/engine-components/api.js +1 -1
  94. package/lib/engine-components/api.js.map +1 -1
  95. package/lib/engine-components/export/usdz/USDZExporter.js +4 -4
  96. package/lib/engine-components/export/usdz/USDZExporter.js.map +1 -1
  97. package/lib/engine-components/export/usdz/extensions/behavior/BehaviourComponents.js.map +1 -1
  98. package/lib/engine-components/postprocessing/index.d.ts +1 -1
  99. package/lib/engine-components/postprocessing/index.js +1 -1
  100. package/lib/engine-components/postprocessing/index.js.map +1 -1
  101. package/lib/engine-components/timeline/TimelineBuilder.d.ts +4 -4
  102. package/lib/engine-components/timeline/TimelineBuilder.js +2 -2
  103. package/lib/engine-components/timeline/TimelineBuilder.js.map +1 -1
  104. package/lib/engine-components/timeline/TimelineTracks.js +24 -15
  105. package/lib/engine-components/timeline/TimelineTracks.js.map +1 -1
  106. package/lib/engine-components/webxr/WebXRImageTracking.utils.js.map +1 -1
  107. package/package.json +2 -2
  108. package/plugins/common/license.js +4 -4
  109. package/plugins/vite/license.js +4 -4
  110. package/src/engine/api.ts +5 -3
  111. package/src/engine/engine_addressables.ts +75 -9
  112. package/src/engine/engine_application.ts +7 -2
  113. package/src/engine/engine_context.ts +25 -1
  114. package/src/engine/engine_gameobject.ts +2 -2
  115. package/src/engine/engine_gltf_builtin_components.ts +1 -1
  116. package/src/engine/engine_init.ts +2 -2
  117. package/src/engine/engine_input.ts +2 -2
  118. package/src/engine/engine_instantiate_resolve.ts +1 -1
  119. package/src/engine/engine_license.ts +115 -77
  120. package/src/engine/engine_lifecycle_functions_internal.ts +21 -2
  121. package/src/engine/engine_materialpropertyblock.ts +21 -0
  122. package/src/engine/engine_networking.ts +2 -2
  123. package/src/engine/engine_networking_blob.ts +3 -3
  124. package/src/engine/engine_networking_streams.ts +61 -17
  125. package/src/engine/engine_utils_qrcode.ts +2 -2
  126. package/src/engine/physics/workers/mesh-bvh/GenerateMeshBVHWorker.js +8 -1
  127. package/src/engine/webcomponents/fonts.ts +16 -1
  128. package/src/engine/webcomponents/icons.ts +8 -1
  129. package/src/engine/webcomponents/needle menu/needle-menu-spatial.ts +2 -2
  130. package/src/engine/webcomponents/needle menu/needle-menu.ts +33 -15
  131. package/src/engine/webcomponents/needle-engine.loading.ts +19 -7
  132. package/src/engine/webcomponents/needle-engine.ts +16 -6
  133. package/src/engine/xr/NeedleXRSession.ts +11 -10
  134. package/src/engine/xr/TempXRContext.ts +2 -2
  135. package/src/engine-components/AnimationBuilder.ts +1 -1
  136. package/src/engine-components/AnimatorController.builder.ts +4 -4
  137. package/src/engine-components/Component.ts +1 -1
  138. package/src/engine-components/DragControls.ts +2 -3
  139. package/src/engine-components/DragControlsConstraints.ts +1 -2
  140. package/src/engine-components/Light.ts +1 -1
  141. package/src/engine-components/api.ts +2 -2
  142. package/src/engine-components/export/usdz/USDZExporter.ts +4 -4
  143. package/src/engine-components/export/usdz/extensions/behavior/BehaviourComponents.ts +1 -1
  144. package/src/engine-components/postprocessing/index.ts +1 -1
  145. package/src/engine-components/timeline/TimelineBuilder.ts +5 -5
  146. package/src/engine-components/timeline/TimelineTracks.ts +25 -17
  147. package/src/engine-components/webxr/WebXRImageTracking.utils.ts +0 -1
  148. package/dist/gltf-progressive-CdjpU5eP.min.js +0 -10
  149. package/dist/gltf-progressive-DeZioRZe.umd.cjs +0 -10
@@ -34,7 +34,7 @@
34
34
  * @module Built-in Components
35
35
  */
36
36
 
37
- export { AnimationBuilder, type AnimationKeyframe, type Tween, type AnimationInterpolation } from "./AnimationBuilder.js";
37
+ export { AnimationBuilder, type AnimationInterpolation,type AnimationKeyframe, type Tween } from "./AnimationBuilder.js";
38
38
  export { AnimatorControllerBuilder, type ConditionMode, type StateOptions, type TransitionOptions } from "./AnimatorController.builder.js";
39
39
  export * from "./codegen/components.js";
40
40
  export { Collider } from "./Collider.js"; // export abstract type
@@ -44,11 +44,11 @@ export { Behaviour, Component, GameObject } from "./Component.js";
44
44
  export { AudioRolloffMode } from "./AudioSource.js";
45
45
  export { ClearFlags } from "./Camera.js"
46
46
  export { DragMode } from "./DragControls.js";
47
- export { ShadowCastingMode, ReflectionProbeUsage } from "./Renderer.js";
48
47
  export type { DropListenerNetworkEventArguments, DropListenerOnDropArguments } from "./DropListener.js";
49
48
  export * from "./export/index.js"
50
49
  export * from "./particlesystem/api.js"
51
50
  export * from "./postprocessing/index.js"
51
+ export { ReflectionProbeUsage,ShadowCastingMode } from "./Renderer.js";
52
52
  export { type ISceneEventListener } from "./SceneSwitcher.js";
53
53
  export * from "./splines/index.js";
54
54
  export * from "./timeline/index.js"
@@ -3,7 +3,7 @@ import { Euler, Material, Matrix4, Mesh, Object3D, Quaternion, Vector3 } from "t
3
3
 
4
4
  import { isDevEnvironment, showBalloonMessage, showBalloonWarning } from "../../../engine/debug/index.js";
5
5
  import { findObjectOfType } from "../../../engine/engine_components.js";
6
- import { _$VfAckLjB } from "../../../engine/engine_license.js";
6
+ import { _$xBhfh } from "../../../engine/engine_license.js";
7
7
  import { serializable } from "../../../engine/engine_serialization.js";
8
8
  import { getFormattedDate, Progress } from "../../../engine/engine_time_utils.js";
9
9
  import { DeviceUtilities, getParam } from "../../../engine/engine_utils.js";
@@ -277,7 +277,7 @@ export class USDZExporter extends Behaviour {
277
277
  let name = this.exportFileName ?? this.objectToExport?.name ?? this.name;
278
278
  name += "-" + getFormattedDate(); // seems iOS caches the file in some cases, this ensures we always have a fresh file
279
279
 
280
- if (!_$VfAckLjB()) {
280
+ if (!_$xBhfh()) {
281
281
  if (name !== "") name += "-";
282
282
  name += "MadeWithNeedle";
283
283
  }
@@ -682,7 +682,7 @@ export class USDZExporter extends Behaviour {
682
682
  if (debug)
683
683
  showBalloonMessage("Quicklook url: " + callToActionURL);
684
684
  if (callToActionURL) {
685
- if (!_$VfAckLjB()) {
685
+ if (!_$xBhfh()) {
686
686
  console.warn("Quicklook closed: custom redirects require a Needle Engine Pro license: https://needle.tools/pricing", callToActionURL)
687
687
  }
688
688
  else {
@@ -697,7 +697,7 @@ export class USDZExporter extends Behaviour {
697
697
  private buildQuicklookOverlay(): CustomBranding {
698
698
  const obj: CustomBranding = {};
699
699
  if (this.customBranding) Object.assign(obj, this.customBranding);
700
- if (!_$VfAckLjB()) {
700
+ if (!_$xBhfh()) {
701
701
  console.log("Custom Quicklook banner text requires pro license: https://needle.tools/pricing");
702
702
  obj.callToAction = "Close";
703
703
  obj.checkoutTitle = "🌵 Made with Needle";
@@ -3,6 +3,7 @@ import { AnimationClip, Material, Matrix4, Mesh, Object3D, Quaternion, Vector3 }
3
3
  import { isDevEnvironment, showBalloonWarning } from "../../../../../engine/debug/index.js";
4
4
  import { serializable } from "../../../../../engine/engine_serialization_decorator.js";
5
5
  import { getWorldPosition, getWorldQuaternion, getWorldScale, setWorldPosition, setWorldQuaternion, setWorldScale } from "../../../../../engine/engine_three_utils.js";
6
+ import type { ComponentInit } from "../../../../../engine/engine_types.js";
6
7
  import { getParam } from "../../../../../engine/engine_utils.js";
7
8
  import { compareAssociation } from "../../../../../engine/extensions/extension_utils.js";
8
9
  import type { State } from "../../../../../engine/extensions/NEEDLE_animator_controller_model.js";
@@ -11,7 +12,6 @@ import { Animation } from "../../../../Animation.js";
11
12
  import { Animator } from "../../../../Animator.js";
12
13
  import { AudioSource } from "../../../../AudioSource.js";
13
14
  import { Behaviour, GameObject } from "../../../../Component.js";
14
- import type { ComponentInit } from "../../../../../engine/engine_types.js";
15
15
  import { Rigidbody } from "../../../../RigidBody.js";
16
16
  import type { IPointerClickHandler, PointerEventData } from "../../../../ui/PointerEvents.js";
17
17
  import { makeNameSafeForUSD, USDDocument, USDObject, USDZExporterContext } from "../../ThreeUSDZExporter.js";
@@ -4,8 +4,8 @@ export { PostProcessingEffectOrder } from "./utils.js";
4
4
  /* Effect option enums. The effect components themselves are exported from
5
5
  codegen/components.ts, but these were unreachable: `DepthOfField.mode`
6
6
  could not be set to a named value from outside the package. */
7
- export { DepthOfFieldMode } from "./Effects/DepthOfField.js";
8
7
  export { QualityLevel } from "./Effects/Antialiasing.js";
8
+ export { DepthOfFieldMode } from "./Effects/DepthOfField.js";
9
9
  export { ScreenSpaceAmbientOcclusionN8QualityMode } from "./Effects/ScreenspaceAmbientOcclusionN8.js";
10
10
  export { NEToneMappingMode } from "./Effects/Tonemapping.utils.js";
11
11
  export { PostProcessingManager } from "./Volume.js"
@@ -1,19 +1,19 @@
1
- import { AnimationClip, Object3D } from "three";
2
1
  import type { Light, Material, PerspectiveCamera } from "three";
2
+ import { AnimationClip, Object3D } from "three";
3
3
 
4
+ import { InstantiateIdProvider } from "../../engine/engine_networking_instantiate.js";
5
+ import { type AnimationKeyframe, type ColorValue,type EulerValue, isTrackDescriptor, type QuatValue, resolveToClip, track as trackFn, type TrackDescriptor, type TrackOptions, type Tween, type Vec3Value } from "../AnimationBuilder.js";
4
6
  import type { Animator } from "../Animator.js";
5
7
  import type { AudioSource } from "../AudioSource.js";
6
8
  import { GameObject } from "../Component.js";
7
- import { InstantiateIdProvider } from "../../engine/engine_networking_instantiate.js";
8
9
  import { EventList } from "../EventList.js";
9
- import { isTrackDescriptor, resolveToClip, track as trackFn, type TrackDescriptor, type TrackOptions, type AnimationKeyframe, type Tween, type Vec3Value, type QuatValue, type EulerValue, type ColorValue } from "../AnimationBuilder.js";
10
10
 
11
11
  /** Keyframe array or tween shorthand */
12
12
  type KF<V> = AnimationKeyframe<V>[] | Tween<V>;
13
- import { SignalAsset, SignalReceiver, SignalReceiverEvent } from "./SignalAsset.js";
14
13
  import type { PlayableDirector } from "./PlayableDirector.js";
14
+ import { SignalAsset, SignalReceiver, SignalReceiverEvent } from "./SignalAsset.js";
15
+ import type { AnimationClipModel, AudioClipModel, ClipModel, ControlClipModel, MarkerModel, SignalMarkerModel, TimelineAssetModel, TrackModel, TrackOffset } from "./TimelineModels.js";
15
16
  import { ClipExtrapolation, TrackType } from "./TimelineModels.js";
16
- import type { TimelineAssetModel, TrackModel, ClipModel, AnimationClipModel, AudioClipModel, ControlClipModel, MarkerModel, SignalMarkerModel, TrackOffset } from "./TimelineModels.js";
17
17
  import { MarkerType } from "./TimelineModels.js";
18
18
 
19
19
  /**
@@ -1,6 +1,7 @@
1
1
  import { AnimationAction, AnimationClip, AnimationMixer, Audio, AudioListener, AudioLoader, Euler, Object3D, Quaternion, QuaternionKeyframeTrack, Vector3, VectorKeyframeTrack } from "three";
2
2
 
3
3
  import { isDevEnvironment } from "../../engine/debug/index.js";
4
+ import { AnimationUtils } from "../../engine/engine_animation.js";
4
5
  import { Context } from "../../engine/engine_setup.js";
5
6
  import type { Constructor } from "../../engine/engine_types.js";
6
7
  import { getParam, resolveUrl } from "../../engine/engine_utils.js";
@@ -9,9 +10,8 @@ import { AudioSource } from "../AudioSource.js";
9
10
  import { GameObject } from "../Component.js";
10
11
  import type { PlayableDirector } from "./PlayableDirector.js";
11
12
  import { SignalReceiver } from "./SignalAsset.js";
12
- import * as Models from "./TimelineModels.js";
13
13
  import type { TimelineBuilder } from "./TimelineBuilder.js";
14
- import { AnimationUtils } from "../../engine/engine_animation.js";
14
+ import * as Models from "./TimelineModels.js";
15
15
 
16
16
  const debug = getParam("debugtimeline");
17
17
 
@@ -722,6 +722,20 @@ export class TimelineAudioTrack extends TimelineTrackHandler {
722
722
  audio.playbackRate = this.director.context.time.timeScale * this.director.speed;
723
723
  audio.loop = asset.loop;
724
724
  if (time >= model.start && time <= model.end && time < this.director.duration) {
725
+ let vol = asset.volume as number;
726
+ if (this.track.volume !== undefined)
727
+ vol *= this.track.volume;
728
+ if (isMuted) vol = 0;
729
+ if (model.easeInDuration > 0) {
730
+ const easeIn = Math.min((time - model.start) / model.easeInDuration, 1);
731
+ vol *= easeIn;
732
+ }
733
+ if (model.easeOutDuration > 0) {
734
+ const easeOut = Math.min((model.end - time) / model.easeOutDuration, 1);
735
+ vol *= easeOut;
736
+ }
737
+ vol *= this.director.weight;
738
+
725
739
  if (!audio.isPlaying || !this.director.isPlaying) {
726
740
  // if the timeline is paused we trigger the audio clip once when the model is entered
727
741
  // we dont playback the audio clip if we scroll back in time
@@ -733,6 +747,11 @@ export class TimelineAudioTrack extends TimelineTrackHandler {
733
747
  audio.offset = model.clipIn + (time - model.start) * model.timeScale;
734
748
  else audio.offset = 0;
735
749
  if (debug) console.log("Timeline Audio (" + this.track.name + ") play with offset " + audio.offset + " - " + model.asset.clip);
750
+ // Audio.setVolume() fades over 10 ms. Set the initial gain immediately
751
+ // before starting the source so short muted clips cannot be heard.
752
+ const gain = audio.gain.gain;
753
+ gain.cancelScheduledValues(audio.context.currentTime);
754
+ gain.setValueAtTime(vol, audio.context.currentTime);
736
755
  audio.play(playTimeOffset);
737
756
  model._didTriggerPlay = true;
738
757
  }
@@ -750,24 +769,13 @@ export class TimelineAudioTrack extends TimelineTrackHandler {
750
769
  if (diff > 0.3) {
751
770
  audio.offset = targetOffset;
752
771
  audio.stop();
772
+ const gain = audio.gain.gain;
773
+ gain.cancelScheduledValues(audio.context.currentTime);
774
+ gain.setValueAtTime(vol, audio.context.currentTime);
753
775
  audio.play(playTimeOffset);
754
776
  }
755
777
  }
756
- let vol = asset.volume as number;
757
-
758
- if (this.track.volume !== undefined)
759
- vol *= this.track.volume;
760
-
761
- if (isMuted) vol = 0;
762
- if (model.easeInDuration > 0) {
763
- const easeIn = Math.min((time - model.start) / model.easeInDuration, 1);
764
- vol *= easeIn;
765
- }
766
- if (model.easeOutDuration > 0) {
767
- const easeOut = Math.min((model.end - time) / model.easeOutDuration, 1);
768
- vol *= easeOut;
769
- }
770
- audio.setVolume(vol * this.director.weight);
778
+ audio.setVolume(vol);
771
779
  }
772
780
  else {
773
781
  model._didTriggerPlay = false;
@@ -1,6 +1,5 @@
1
1
  import { isDevEnvironment } from "../../engine/debug/index.js";
2
2
  import { getParam } from "../../engine/engine_utils.js";
3
-
4
3
  import type { WebXRImageTrackingModel } from "./WebXRImageTracking.js";
5
4
 
6
5
  // Kept in a dedicated module (with only lightweight imports) so the marker-loading logic can be unit
@@ -1,10 +0,0 @@
1
- import{RedFormat as Qe,RedIntegerFormat as Je,RGFormat as Ze,RGIntegerFormat as et,RGBFormat as tt,RGBAFormat as rt,RGBAIntegerFormat as st,BufferGeometry as z,Mesh as V,Box3 as ie,Vector3 as k,Sphere as Oe,CompressedTexture as ot,Texture as I,Matrix3 as nt,InterleavedBuffer as it,InterleavedBufferAttribute as at,BufferAttribute as lt,TextureLoader as ut,Matrix4 as ke,THREE as ct,Color as Re}from"./three-core.min.js";import{DRACOLoader as dt,KTX2Loader as ht,MeshoptDecoder as gt,GLTFLoader as he}from"./three-examples.min.js";const ft="";globalThis.GLTF_PROGRESSIVE_VERSION=ft,console.debug("[gltf-progressive] version -");let P="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",H="https://cdn.needle.tools/static/three/0.179.1/basis2/";const mt=P,pt=H,Pe=new URL(P+"draco_decoder.js");Pe.searchParams.append("range","true"),fetch(Pe,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(n=>{console.debug(`Failed to fetch remote Draco decoder from ${P} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),P===mt&&Ce("./include/draco/"),H===pt&&Ae("./include/ktx2/")}).finally(()=>{Ie()});const xt=()=>({dracoDecoderPath:P,ktx2TranscoderPath:H});function Ce(n){P=n,O&&O[fe]!=P?(console.debug("Updating Draco decoder path to "+n),O[fe]=P,O.setDecoderPath(P),O.preload()):console.debug("Setting Draco decoder path to "+n)}function Ae(n){H=n,C&&C.transcoderPath!=H?(console.debug("Updating KTX2 transcoder path to "+n),C.setTranscoderPath(H),C.init()):console.debug("Setting KTX2 transcoder path to "+n)}function ae(n){return Ie(),n?C.detectSupport(n):n!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:O,ktx2Loader:C,meshoptDecoder:le}}function ge(n){n.dracoLoader||n.setDRACOLoader(O),n.ktx2Loader||n.setKTX2Loader(C),n.meshoptDecoder||n.setMeshoptDecoder(le)}const fe=Symbol("dracoDecoderPath");let O,le,C;function Ie(){O||(O=new dt,O[fe]=P,O.setDecoderPath(P),O.setDecoderConfig({type:"js"}),O.preload()),C||(C=new ht,C.setTranscoderPath(H),C.init()),le||(le=gt)}const me=new WeakMap;function pe(n,t){let e=me.get(n);e?e=Object.assign(e,t):e=t,me.set(n,e)}const yt=he.prototype.load;function vt(...n){const t=me.get(this);let e=n[0];const r=wt(e);if(r?.hostname.endsWith("needle.tools")){const s=t?.progressive!==void 0?t.progressive:!0,o=t?.usecase?t.usecase:"default";s?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${o}`:this.requestHeader.Accept=`*/*;usecase=${o}`,e=r.toString()}return n[0]=e,yt?.call(this,...n)}he.prototype.load=vt;function wt(n){try{if(n instanceof URL)return n;const t=globalThis.location?.href;return t?new URL(n,t):new URL(n)}catch{return null}}function Ee(n){return n!=null&&n.data!=null}function xe(n){const t=n.source?.data;return t!=null&&typeof t=="object"?t:null}function Lt(n){const t=n.image;return t!=null&&typeof t=="object"?t:null}function ye(n){const t=Lt(n),e=xe(n);return{width:t?.width||e?.width||0,height:t?.height||e?.height||0}}q("debugprogressive");function q(n){const t=globalThis.location?.href;if(!t)return!1;const e=new URL(t).searchParams.get(n);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function bt(n,t){if(t===void 0||n===void 0||t.startsWith("./")||t.startsWith("http")||t.startsWith("data:")||t.startsWith("blob:"))return t;const e=n.lastIndexOf("/");if(e>=0){const r=n.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}function ve(){if(ee!==void 0)return ee;const n=globalThis.navigator?.userAgent||"";return ee=/iPhone|iPad|iPod|Android|IEMobile/i.test(n),q("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",ee),ee}let ee;function $e(){const n=globalThis.location?.href;if(!n)return!1;const t=new URL(n),e=t.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(t.hostname);return t.hostname==="127.0.0.1"||e}class Mt{constructor(t,e={}){this.maxConcurrent=t,this.debug=e.debug??!1,typeof globalThis.requestAnimationFrame=="function"?globalThis.requestAnimationFrame(this.tick):setTimeout(this.tick,0)}_running=new Map;_queue=[];debug=!1;tick=()=>{this.internalUpdate(),setTimeout(this.tick,10)};slot(t){return this.debug&&console.debug(`[PromiseQueue]: Requesting slot for key ${t}, running: ${this._running.size}, waiting: ${this._queue.length}`),new Promise(e=>{this._queue.push({key:t,resolve:e})})}add(t,e){this._running.has(t)||(this._running.set(t,e),e.finally(()=>{this._running.delete(t),this.debug&&console.debug(`[PromiseQueue]: Promise finished now running: ${this._running.size}, waiting: ${this._queue.length}. (finished ${t})`)}),this.debug&&console.debug(`[PromiseQueue]: Added new promise, now running: ${this._running.size}, waiting: ${this._queue.length}. (added ${t})`))}internalUpdate(){const t=this.maxConcurrent-this._running.size;for(let e=0;e<t&&this._queue.length>0;e++){this.debug&&console.debug(`[PromiseQueue]: Running ${this._running.size} promises, waiting for ${this._queue.length} more.`);const{key:r,resolve:s}=this._queue.shift();s({use:o=>this.add(r,o)})}}}function Dt(n){const t=n.image,e=t?.width??0,r=t?.height??0,s=t?.depth??1,o=Math.floor(Math.log2(Math.max(e,r,s)))+1,i=_t(n);return e*r*s*i*(1-Math.pow(.25,o))/(1-.25)}function _t(n){let t=4;const e=n.format;e===Qe||e===Je?t=1:e===Ze||e===et?t=2:e===tt||e===1029?t=3:(e===rt||e===st)&&(t=4);let r=1;const s=n.type;return s===1009||s===1010?r=1:s===1011||s===1012?r=2:s===1013||s===1014||s===1015?r=4:s===1016&&(r=2),t*r}const Tt=typeof window>"u"&&typeof document>"u",we=Symbol("needle:raycast-mesh");function Y(n){return n?.[we]instanceof z?n[we]:null}function St(n,t){if((n.type==="Mesh"||n.type==="SkinnedMesh")&&!Y(n)){const e=kt(t);e.userData={isRaycastMesh:!0},n[we]=e}}function Ot(n=!0){if(n){if(te)return;const t=te=V.prototype.raycast;V.prototype.raycast=function(e,r){const s=this,o=Y(s);let i;o&&s.isMesh&&(i=s.geometry,s.geometry=o),t.call(this,e,r),i&&(s.geometry=i)}}else{if(!te)return;V.prototype.raycast=te,te=null}}let te=null;function kt(n){const t=new z;for(const e in n.attributes)t.setAttribute(e,n.getAttribute(e));return t.setIndex(n.getIndex()),t}const $=new Array,g=q("debugprogressive");let re,X=-1;if(g&&typeof window<"u"){let n=function(){X+=1,X>=t&&(X=-1),console.log(`Toggle LOD level [${X}]`)};window.addEventListener("keyup",e=>{e.key==="p"&&n(),e.key==="w"&&(re=!re,console.log(`Toggle wireframe [${re}]`));const r=parseInt(e.key);!isNaN(r)&&r>=0&&(X=r,console.log(`Set LOD level to [${X}]`))})}function Be(n){if(g&&re!==void 0)if(Array.isArray(n))for(const t of n)Be(t);else n&&"wireframe"in n&&(n.wireframe=re===!0)}const se=new Array;let Rt=0;const Pt=ve()?2:10;function Ct(n){if(se.length<Pt){const e=se.length;g&&console.warn(`[Worker] Creating new worker #${e}`);const r=Se.createWorker(n||{});return se.push(r),r}const t=Rt++%se.length;return se[t]}class Se{constructor(t,e){this.worker=t,this._debug=e.debug??!1,t.onmessage=r=>{const s=r.data;switch(this._debug&&console.log("[Worker] EVENT",s),s.type){case"loaded-gltf":for(const o of this._running)if(o.url===s.result.url){At(s.result),o.resolve(s.result);const i=o.url;i.startsWith("blob:")&&URL.revokeObjectURL(i)}}},t.onerror=r=>{console.error("[Worker] Error in gltf-progressive worker:",r)},t.postMessage({type:"init"})}static async createWorker(t){const e=new Worker(URL.createObjectURL(new Blob([`import '${new URL("./gltf-progressive.worker-BqODMeeW.js",import.meta.url).toString()}';`],{type:"text/javascript"})),{type:"module"});return new Se(e,t)}_running=[];_webglRenderer=null;async load(t,e){const r=xt();let s=e?.renderer;s||(this._webglRenderer??=(async()=>{const{WebGLRenderer:a}=await import("./three-core.min.js").then(l=>l.THREE);return new a})(),s=await this._webglRenderer);const o=ae(s).ktx2Loader.workerConfig;if(t instanceof URL)t=t.toString();else if(t.startsWith("file:"))t=URL.createObjectURL(new Blob([t]));else if(!t.startsWith("blob:")&&!t.startsWith("http:")&&!t.startsWith("https:")){const a=globalThis.location?.href;a&&(t=new URL(t,a).toString())}const i={type:"load",url:t,dracoDecoderPath:r.dracoDecoderPath,ktx2TranscoderPath:r.ktx2TranscoderPath,ktx2LoaderConfig:o};return this._debug&&console.debug("[Worker] Sending load request",i),this.worker.postMessage(i),new Promise(a=>{this._running.push({url:t.toString(),resolve:a})})}_debug=!1}function At(n){for(const t of n.geometries){const e=t.geometry,r=new z;if(r.name=e.name||"",e.index){const s=e.index;r.setIndex(Le(s))}for(const s in e.attributes){const o=e.attributes[s],i=Le(o);r.setAttribute(s,i)}if(e.morphAttributes)for(const s in e.morphAttributes){const o=e.morphAttributes[s].map(i=>Le(i));r.morphAttributes[s]=o}if(r.morphTargetsRelative=e.morphTargetsRelative??!1,r.boundingBox=new ie,r.boundingBox.min=new k(e.boundingBox?.min.x,e.boundingBox?.min.y,e.boundingBox?.min.z),r.boundingBox.max=new k(e.boundingBox?.max.x,e.boundingBox?.max.y,e.boundingBox?.max.z),r.boundingSphere=new Oe(new k(e.boundingSphere?.center.x,e.boundingSphere?.center.y,e.boundingSphere?.center.z),e.boundingSphere?.radius),e.groups)for(const s of e.groups)r.addGroup(s.start,s.count,s.materialIndex);e.userData&&(r.userData=e.userData),t.geometry=r}for(const t of n.textures){const e=t.texture;let r=null;if(e.isCompressedTexture){const s=e.mipmaps,{width:o,height:i}=ye(e);r=new ot(s,o,i,e.format,e.type,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.anisotropy,e.colorSpace)}else r=new I(e.image,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),r.mipmaps=e.mipmaps,r.channel=e.channel,r.source.data=e.source.data,r.flipY=e.flipY,r.premultiplyAlpha=e.premultiplyAlpha,r.unpackAlignment=e.unpackAlignment,r.matrix=new nt(...e.matrix.elements);if(!r){console.error("[Worker] Failed to create new texture from received data. Texture is not a CompressedTexture or Texture.");continue}t.texture=r}return n}function Le(n){let t=n;if("isInterleavedBufferAttribute"in n&&n.isInterleavedBufferAttribute){const e=n.data,r=e.array,s=new it(r,e.stride);t=new at(s,n.itemSize,r.byteOffset,n.normalized),t.offset=n.offset}else"isBufferAttribute"in n&&n.isBufferAttribute&&(t=new lt(n.array,n.itemSize,n.normalized),t.usage=n.usage,t.gpuType=n.gpuType,t.updateRanges=n.updateRanges);return t}const It=q("gltf-progressive-worker");q("gltf-progressive-reduce-mipmaps");const oe=q("gltf-progressive-gc"),be=Symbol("needle-progressive-texture"),B="NEEDLE_progressive";class f{get name(){return B}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e?.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){return this.getAssignedLODInformation(t)?.index??-1}static getMaterialMinMaxLODsCount(t,e){const r=this,s="LODS:minmax",o=t[s];if(o!=null)return o;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const a of t)this.getMaterialMinMaxLODsCount(a,e);return t[s]=e,e}if(g==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const a=t;for(const l of Object.keys(a.uniforms)){const u=a.uniforms[l].value;u?.isTexture===!0&&i(u,e)}}else if(t.isMaterial)for(const a of Object.keys(t)){const l=t[a];l?.isTexture===!0&&i(l,e)}else g&&console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);return t[s]=e,e;function i(a,l){const u=r.getAssignedLODInformation(a);if(u){const c=r.lodInfos.get(u.key);if(c&&c.lods){l.min_count=Math.min(l.min_count,c.lods.length),l.max_count=Math.max(l.max_count,c.lods.length);for(let d=0;d<c.lods.length;d++){const p=c.lods[d];p.width&&(l.lods[d]=l.lods[d]||{min_height:1/0,max_height:0},l.lods[d].min_height=Math.min(l.lods[d].min_height,p.height),l.lods[d].max_height=Math.max(l.lods[d].max_height,p.height))}}}}}static hasLODLevelAvailable(t,e){if(Array.isArray(t)){for(const o of t)if(this.hasLODLevelAvailable(o,e))return!0;return!1}if(t.isMaterial===!0){for(const o of Object.keys(t)){const i=t[o];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const o of t.children)if(o.isMesh===!0&&this.hasLODLevelAvailable(o,e))return!0}let r,s;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&r?.userData?.LODS){const o=r.userData.LODS;if(s=this.lodInfos.get(o.key),e===void 0)return s!=null;if(s)return Array.isArray(s.lods)?e<s.lods.length:e===0}return!1}static assignMeshLOD(t,e,r){if(!t)return Promise.resolve(null);if(t instanceof V||t.isMesh===!0){const s=t.geometry,o=this.getAssignedLODInformation(s);if(!o)return Promise.resolve(null);for(const a of $)a.onBeforeGetLODMesh?.(t,e);t["LOD:requested level"]=e;const i=()=>t["LOD:requested level"]===e||this.shouldApplyStaleMeshLOD(t,e);return f.getOrLoadLOD(s,e,{isCurrent:i}).then(a=>{if(Array.isArray(a)){const u=o.index||0;a=a[u]}const l=t["LOD:requested level"]===e;return(l||this.shouldApplyStaleMeshLOD(t,e))&&(l&&delete t["LOD:requested level"],a&&s!=a&&(a?.isBufferGeometry?typeof r?.apply=="function"?r.apply(a,e,t):r?.apply!==!1&&(t.geometry=a):g&&console.error("Invalid LOD geometry",a))),a}).catch(a=>(console.error("Error loading mesh LOD",t,a),null))}else g&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0,r){if(!t)return Promise.resolve(null);const s=r?.force===!0;if(t.isMesh===!0){const o=t;if(Array.isArray(o.material)){const i=new Array;for(const a of o.material){const l=this.assignTextureLOD(a,e,r);i.push(l)}return Promise.all(i).then(a=>{const l=new Array;for(const u of a)Array.isArray(u)&&l.push(...u);return l})}else return this.assignTextureLOD(o.material,e,r)}if(t.isMaterial===!0){const o=t,i=[],a=new Array;if(this.trackCurrentMaterialTextureSlots(o),o.uniforms&&(o.isRawShaderMaterial||o.isShaderMaterial===!0)){const l=o;for(const u of Object.keys(l.uniforms)){const c=l.uniforms[u].value;if(c?.isTexture===!0){const d=this.assignTextureLODForSlot(c,e,o,u,s).then(p=>(p&&l.uniforms[u].value!=p&&(l.uniforms[u].value=p,l.uniformsNeedUpdate=!0),p));i.push(d),a.push(u)}}}else for(const l of Object.keys(o)){const u=o[l];if(u?.isTexture===!0){const c=this.assignTextureLODForSlot(u,e,o,l,s);i.push(c),a.push(l)}}return Promise.all(i).then(l=>{const u=new Array;for(let c=0;c<l.length;c++){const d=l[c],p=a[c];d&&d.isTexture===!0?u.push({material:o,slot:p,texture:d,level:e}):u.push({material:o,slot:p,texture:null,level:e})}return u})}if(t instanceof I||t.isTexture===!0){const o=t;return this.assignTextureLODForSlot(o,e,null,null,s)}return Promise.resolve(null)}static set maxConcurrentLoadingTasks(t){f.queue.maxConcurrent=t}static get maxConcurrentLoadingTasks(){return f.queue.maxConcurrent}static assignTextureLODForSlot(t,e,r,s,o){if(t?.isTexture!==!0)return Promise.resolve(null);if(s==="glyphMap")return Promise.resolve(t);const i=this.getAssignedLODInformation(t);if(i&&(i.level===e||!o&&i.level<e))return Promise.resolve(t);if(r&&s){const d=this.getPendingTextureSlotRequest(r,s);if(d&&d.level===e&&d.force===o)return d.promise}const a=r&&s?this.nextTextureSlotRequestId(r,s,e,o):0,l=()=>!r||!s||this.getLatestTextureSlotRequest(r,s)?.id===a,u=()=>l()||this.shouldApplyStaleTextureSlotLOD(r,s,e,o),c=f.getOrLoadLOD(t,e,{isCurrent:u}).then(d=>{if(!l()&&!this.shouldApplyStaleTextureSlotLOD(r,s,e,o))return null;if(Array.isArray(d))return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."),null;if(d?.isTexture===!0){if(d!=t&&r&&s){const p=this.getMaterialTextureSlot(r,s)??t;if(p&&!o){const m=this.getAssignedLODInformation(p);if(m&&m?.level<e)return g==="verbose"&&console.warn("Assigned texture level is already higher: ",m.level,e,r,p,d),null}this.assignTrackedTextureSlot(r,s,d)}return d}else g=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(d=>(console.error("Error loading LOD",t,d),null));return r&&s&&this.setPendingTextureSlotRequest(r,s,e,o,a,c),c}static trackedTextureSlots=new WeakMap;static pendingTextureSlotRequests=new WeakMap;static latestTextureSlotRequests=new WeakMap;static textureSlotRequestId=0;static trackCurrentMaterialTextureSlots(t){if(t.uniforms&&(t.isRawShaderMaterial||t.isShaderMaterial===!0)){const e=t;for(const r of Object.keys(e.uniforms)){const s=e.uniforms[r].value;s?.isTexture===!0&&this.ensureTrackedTextureSlot(t,r,s)}return}for(const e of Object.keys(t)){const r=t[e];r?.isTexture===!0&&this.ensureTrackedTextureSlot(t,e,r)}}static getPendingTextureSlotRequest(t,e){return this.pendingTextureSlotRequests.get(t)?.get(e)}static nextTextureSlotRequestId(t,e,r,s){let o=this.latestTextureSlotRequests.get(t);o||(o=new Map,this.latestTextureSlotRequests.set(t,o));const i=++this.textureSlotRequestId;return o.set(e,{id:i,level:r,force:s}),i}static getLatestTextureSlotRequest(t,e){return this.latestTextureSlotRequests.get(t)?.get(e)}static shouldApplyStaleTextureSlotLOD(t,e,r,s){if(!t||!e)return!1;const o=this.getLatestTextureSlotRequest(t,e),i=this.getMaterialTextureSlot(t,e),a=this.getAssignedLODInformation(i)?.level??1/0;return r>=a?!1:s?o?r>=o.level:!1:!0}static shouldApplyStaleMeshLOD(t,e){const r=t["LOD:requested level"];if(typeof r!="number")return!1;const s=this.getAssignedLODInformation(t.geometry)?.level??1/0;return e<s&&e>=r}static setPendingTextureSlotRequest(t,e,r,s,o,i){let a=this.pendingTextureSlotRequests.get(t);a||(a=new Map,this.pendingTextureSlotRequests.set(t,a));const l={level:r,force:s,id:o,promise:i};a.set(e,l),i.finally(()=>{a.get(e)?.id===o&&a.delete(e)})}static getMaterialTextureSlot(t,e){const r=t.uniforms?.[e];if(r?.value?.isTexture===!0)return r.value;const s=t[e];return s?.isTexture===!0?s:null}static setMaterialTextureSlot(t,e,r){const s=t.uniforms?.[e];if(s?.value?.isTexture===!0){s.value=r,t.uniformsNeedUpdate=!0;return}t[e]=r}static assignTrackedTextureSlot(t,e,r){let s=this.trackedTextureSlots.get(t);s||(s=new Map,this.trackedTextureSlots.set(t,s));const o=this.getMaterialTextureSlot(t,e);let i=s.get(e);!i&&o?i=this.ensureTrackedTextureSlot(t,e,o):i&&o&&i!==o&&(this.releaseTrackedTextureSlot(t,e,i),i=this.ensureTrackedTextureSlot(t,e,o)),!(i===r&&o===r)&&(i&&i!==r&&this.releaseTrackedTextureSlot(t,e,i),i!==r&&(this.trackTextureUsage(r),s.set(e,r)),o!==r&&this.setMaterialTextureSlot(t,e,r))}static ensureTrackedTextureSlot(t,e,r){let s=this.trackedTextureSlots.get(t);s||(s=new Map,this.trackedTextureSlots.set(t,s));const o=s.get(e);return o===r?o:(o&&this.releaseTrackedTextureSlot(t,e,o),this.trackTextureUsage(r),s.set(e,r),r)}static releaseTrackedTextureSlot(t,e,r){const s=this.trackedTextureSlots.get(t);if(s?.get(e)===r&&s.delete(e),this.untrackTextureUsage(r)&&(g||oe)){const o=this.getAssignedLODInformation(r);console.log(`[gltf-progressive] Disposed old texture LOD ${o?.level??"?"} for ${t.name||t.type}.${e}`,r.uuid)}}parser;url;constructor(t){const e=t.options.path;g&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}_isLoadingMesh;loadMesh=t=>{if(this._isLoadingMesh)return null;const e=this.parser.json.meshes[t]?.extensions?.[B];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>(this._isLoadingMesh=!1,r&&f.registerMesh(this.url,e.guid,r,e.lods?.length,0,e),r))):null};afterRoot(t){return g&&console.log("AFTER",this.url,t),this.parser.json.textures?.forEach((e,r)=>{if(e?.extensions){const s=e?.extensions[B];if(s){if(!s.lods){g&&console.warn("Texture has no LODs",s);return}let o=!1;for(const i of this.parser.associations.keys())i.isTexture===!0&&this.parser.associations.get(i)?.textures===r&&(o=!0,f.registerTexture(this.url,i,s.lods?.length,r,s));o||this.parser.getDependency("texture",r).then(i=>{i&&f.registerTexture(this.url,i,s.lods?.length,r,s)})}}}),this.parser.json.meshes?.forEach((e,r)=>{if(e?.extensions){const s=e?.extensions[B];if(s&&s.lods){for(const o of this.parser.associations.keys())if(o.isMesh){const i=this.parser.associations.get(o);i?.meshes===r&&f.registerMesh(this.url,s.guid,o,s.lods.length,i.primitives,s)}}}}),null}static registerTexture=(t,e,r,s,o)=>{if(!e){g&&console.error("!! gltf-progressive: Called register texture without texture");return}if(g){const{width:a,height:l}=ye(e);console.log(`> gltf-progressive: register texture[${s}] "${e.name||e.uuid}", Current: ${a}x${l}, Max: ${o.lods[0]?.width}x${o.lods[0]?.height}, uuid: ${e.uuid}`,o,e)}e.source&&(e.source[be]=o);const i=o.guid;f.assignLODInformation(t,e,i,r,s),f.lodInfos.set(i,o),f.lowresCache.set(i,new WeakRef(e))};static registerMesh=(t,e,r,s,o,i)=>{const a=r.geometry;if(!a){g&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),g&&console.log("> Progressive: register mesh "+r.name,{index:o,uuid:r.uuid},i,r),f.assignLODInformation(t,a,e,s,o),f.lodInfos.set(e,i);let l=f.lowresCache.get(e)?.deref();l?l.push(r.geometry):l=[r.geometry],f.lowresCache.set(e,new WeakRef(l)),s>0&&!Y(r)&&St(r,a);for(const u of $)u.onRegisteredNewMesh?.(r,i)};static dispose(t){if(t){this.lodInfos.delete(t);const e=this.lowresCache.get(t);if(e){const r=e.deref();if(r){if(r.isTexture){const s=r;this.textureRefCounts.delete(s.uuid),s.dispose()}else if(Array.isArray(r))for(const s of r)s.dispose()}this.lowresCache.delete(t)}for(const[r,s]of this.cache)r.includes(t)&&(this._disposeCacheEntry(s),this.cache.delete(r))}else{this.lodInfos.clear();for(const[,e]of this.lowresCache){const r=e.deref();if(r){if(r.isTexture){const s=r;this.textureRefCounts.delete(s.uuid),s.dispose()}else if(Array.isArray(r))for(const s of r)s.dispose()}}this.lowresCache.clear();for(const[,e]of this.cache)this._disposeCacheEntry(e);this.cache.clear(),this.textureRefCounts.clear(),this.trackedTextureSlots=new WeakMap,this.pendingTextureSlotRequests=new WeakMap,this.latestTextureSlotRequests=new WeakMap,this.textureSlotRequestId=0}}static _disposeCacheEntry(t){if(t instanceof WeakRef){const e=t.deref();e&&(e.isTexture&&this.textureRefCounts.delete(e.uuid),e.dispose())}else t.then(e=>{if(e)if(Array.isArray(e))for(const r of e)r.dispose();else e.isTexture&&this.textureRefCounts.delete(e.uuid),e.dispose()}).catch(()=>{})}static lodInfos=new Map;static cache=new Map;static lowresCache=new Map;static textureRefCounts=new Map;static _resourceRegistry=new FinalizationRegistry(t=>{const e=f.cache.get(t);(g||oe)&&console.debug(`[gltf-progressive] Memory: Resource GC'd
2
- ${t}`),e instanceof WeakRef&&(e.deref()||(f.cache.delete(t),(g||oe)&&console.log("[gltf-progressive] \u21AA Cache entry deleted (GC)")))});static trackTextureUsage(t){const e=t.uuid,r=this.textureRefCounts.get(e)||0;this.textureRefCounts.set(e,r+1),g==="verbose"&&console.log(`[gltf-progressive] Track texture ${e}, refCount: ${r} \u2192 ${r+1}`)}static untrackTextureUsage(t){const e=t.uuid,r=this.textureRefCounts.get(e);if(!r)return(g==="verbose"||oe)&&o("[gltf-progressive] Memory: Untrack untracked texture (dispose immediately)",0),t.dispose(),!0;const s=r-1;if(s<=0)return this.textureRefCounts.delete(e),(g||oe)&&o("[gltf-progressive] Memory: Dispose texture",s),t.dispose(),!0;return this.textureRefCounts.set(e,s),g==="verbose"&&o("[gltf-progressive] Memory: Untrack texture",s),!1;function o(i,a){let{width:l,height:u}=ye(t);const c=l&&u?`${l}x${u}`:"N/A";let d="N/A";l&&u&&(d=`~${(Dt(t)/(1024*1024)).toFixed(2)} MB`),console.log(`${i} \u2014 ${t.name} ${c} (${d}), refCount: ${r} \u2192 ${a}
3
- ${e}`)}}static workers=[];static _workersIndex=0;static async getOrLoadLOD(t,e,r){const s=g=="verbose",o=this.getAssignedLODInformation(t);if(!o)return g&&console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`,t),null;const i=o?.key;let a;if(t.isTexture===!0){const l=t;l.source&&l.source[be]&&(a=l.source[be])}if(a||(a=f.lodInfos.get(i)),!a)g&&console.warn(`Can not load LOD ${e}: no LOD info found for "${i}" ${t.name}`,t.type,f.lodInfos);else{if(e>0){let c=!1;const d=Array.isArray(a.lods);if(d&&e>=a.lods.length?c=!0:d||(c=!0),c){const p=this.lowresCache.get(i);if(p){const m=p.deref();if(m)return m;this.lowresCache.delete(i),g&&console.log(`[gltf-progressive] Lowres cache entry was GC'd: ${i}`)}return null}}const l=Array.isArray(a.lods)?a.lods[e]?.path:a.lods;if(!l)return g&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const u=bt(o.url,l);if(u.endsWith(".glb")||u.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const c=u+"_"+a.guid,d=await this.tryResolveLODCacheEntry(this.cache.get(c),c,u,t,e,s);if(d.found)return d.value;if(r?.isCurrent?.()===!1)return s&&console.log(`Skipping stale LOD ${e} request before queue: ${u}`),null;const p=await this.queue.slot(u);if(r?.isCurrent?.()===!1)return s&&console.log(`Skipping stale LOD ${e} request after queue: ${u}`),null;const m=await this.tryResolveLODCacheEntry(this.cache.get(c),c,u,t,e,s);if(m.found)return m.value;if(!p.use)return g&&console.log(`LOD ${e} was aborted: ${u}`),null;const w=a,h=new Promise(async(D,j)=>{if(It){const b=await(await Ct({})).load(u);if(b.textures.length>0)for(const x of b.textures){let v=x.texture;return f.assignLODInformation(o.url,v,i,e,void 0),t instanceof I&&(v=this.copySettings(t,v)),v&&(v.guid=w.guid),D(v)}if(b.geometries.length>0){const x=new Array;for(const v of b.geometries){const R=v.geometry;f.assignLODInformation(o.url,R,i,e,v.primitiveIndex),x.push(R)}return D(x)}return D(null)}const E=new he;ge(E),g&&(await new Promise(b=>setTimeout(b,1e3)),s&&console.warn("Start loading (delayed) "+u,w.guid));let L=u;if(w&&Array.isArray(w.lods)){const b=w.lods[e];b.hash&&(L+="?v="+b.hash)}const y=await E.loadAsync(L).catch(b=>(console.error(`Error loading LOD ${e} from ${u}
4
- `,b),D(null)));if(!y)return D(null);const T=y.parser;s&&console.log("Loading finished "+u,w.guid);let S=0;if(y.parser.json.textures){let b=!1;for(const x of y.parser.json.textures){if(x?.extensions){const v=x?.extensions[B];if(v?.guid&&v.guid===w.guid){b=!0;break}}S++}if(b){let x=await T.getDependency("texture",S);return x&&f.assignLODInformation(o.url,x,i,e,void 0),s&&console.log('change "'+t.name+'" \u2192 "'+x.name+'"',u,S,x,c),t instanceof I&&(x=this.copySettings(t,x)),x&&(x.guid=w.guid),D(x)}else g&&console.warn("Could not find texture with guid",w.guid,y.parser.json)}if(S=0,y.parser.json.meshes){let b=!1;for(const x of y.parser.json.meshes){if(x?.extensions){const v=x?.extensions[B];if(v?.guid&&v.guid===w.guid){b=!0;break}}S++}if(b){const x=await T.getDependency("mesh",S);if(s&&console.log(`Loaded Mesh "${x.name}"`,u,S,x,c),x.isMesh===!0){const v=x.geometry;return f.assignLODInformation(o.url,v,i,e,0),D(v)}else{const v=new Array;for(let R=0;R<x.children.length;R++){const F=x.children[R];if(F.isMesh===!0){const N=F.geometry;f.assignLODInformation(o.url,N,i,e,R),v.push(N)}}return D(v)}}else g&&console.warn("Could not find mesh with guid",w.guid,y.parser.json)}return D(null)});this.cache.set(c,h),p.use(h);const M=await h;return M!=null?M instanceof I?(this.cache.set(c,new WeakRef(M)),f._resourceRegistry.register(M,c)):Array.isArray(M)?this.cache.set(c,Promise.resolve(M)):this.cache.set(c,Promise.resolve(M)):this.cache.set(c,Promise.resolve(null)),M}else if(t instanceof I){if(r?.isCurrent?.()===!1)return s&&console.log(`Skipping stale texture LOD ${e} request: ${u}`),null;s&&console.log("Load texture from uri: "+u);const c=await new ut().loadAsync(u);return r?.isCurrent?.()===!1?(c?.dispose(),null):(c?(c.guid=a.guid,c.flipY=!1,c.needsUpdate=!0,c.colorSpace=t.colorSpace,s&&console.log(a,c)):g&&console.warn("failed loading",u),c)}}return null}static async tryResolveLODCacheEntry(t,e,r,s,o,i){if(t===void 0)return{found:!1};if(i&&console.log(`LOD ${o} was already loading/loaded: ${e}`),t instanceof WeakRef){const u=t.deref();if(u){let c=u,d=!1;if(c instanceof I&&s instanceof I?Ee(c.image)||xe(c)?c=this.copySettings(s,c):d=!0:c instanceof z&&s instanceof z&&(c.attributes.position?.array||(d=!0)),!d)return{found:!0,value:c}}return this.cache.delete(e),g&&console.log(`[gltf-progressive] Re-loading GC'd/disposed resource: ${e}`),{found:!1}}let a=await t.catch(u=>(console.error(`Error loading LOD ${o} from ${r}
5
- `,u),null)),l=!1;return a==null||(a instanceof I&&s instanceof I?Ee(a.image)||xe(a)?a=this.copySettings(s,a):(l=!0,this.cache.delete(e)):a instanceof z&&s instanceof z&&(a.attributes.position?.array||(l=!0,this.cache.delete(e)))),l?{found:!1}:{found:!0,value:a}}static _queue;static get queue(){return this._queue??=new Mt(ve()?20:50,{debug:g!=!1})}static assignLODInformation(t,e,r,s,o){if(!e)return;e.userData||(e.userData={});const i=new Et(t,r,s,o);e.userData.LODS=i,"source"in e&&typeof e.source=="object"&&(e.source.LODS=i)}static getAssignedLODInformation(t){return t?t.userData?.LODS?t.userData.LODS:"source"in t&&t.source?.LODS?t.source.LODS:null:null}static copySettings(t,e){return e?(g==="verbose"&&console.debug(`Copy texture settings
6
- `,t.uuid,`
7
- `,e.uuid),e=e.clone(),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e):t}}class Et{url;key;level;index;constructor(t,e,r,s){this.url=t,this.key=e,this.level=r,s!=null&&(this.index=s)}}class ue{static addPromise=(t,e,r,s)=>{s.forEach(o=>{o.add(t,e,r)})};ready;get awaitedCount(){return this._addedCount}get resolvedCount(){return this._resolvedCount}get currentlyAwaiting(){return this._awaiting.length}_resolve;_signal;_frame_start;_frames_to_capture;_resolved=!1;_addedCount=0;_resolvedCount=0;_awaiting=[];_maxPromisesPerObject=1;constructor(t,e){const r=Math.max(e.frames??2,2);this._frame_start=e.waitForFirstCapture?void 0:t,this._frames_to_capture=r,this.ready=new Promise(s=>{this._resolve=s}),this.ready.finally(()=>{this._resolved=!0,this._awaiting.length=0}),this._signal=e.signal,this._signal?.addEventListener("abort",()=>{this.resolveNow()}),this._maxPromisesPerObject=Math.max(1,e.maxPromisesPerObject??1)}_currentFrame=0;update(t){this._currentFrame=t,this._frame_start===void 0&&this._addedCount>0&&(this._frame_start=t),(this._signal?.aborted||this._awaiting.length===0&&this._frame_start!==void 0&&t>this._frame_start+this._frames_to_capture)&&this.resolveNow()}_seen=new WeakMap;add(t,e,r){if(this._resolved){g&&console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");return}if(!(this._frame_start!==void 0&&this._currentFrame>this._frame_start+this._frames_to_capture)){if(this._maxPromisesPerObject>=1)if(this._seen.has(e)){const s=this._seen.get(e);if(s>=this._maxPromisesPerObject){g&&console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");return}this._seen.set(e,s+1)}else this._seen.set(e,1);this._awaiting.push(r),this._addedCount++,r.finally(()=>{this._resolvedCount++,this._awaiting.splice(this._awaiting.indexOf(r),1)})}}resolveNow(){this._resolved||this._resolve?.({awaited_count:this._addedCount,resolved_count:this._resolvedCount,cancelled:this._signal?.aborted??!1})}}const A=q("debugprogressive"),$t=A==="colors",Bt=q("noprogressive"),Me=Symbol("Needle:LODSManager"),De=Symbol("Needle:LODState"),U=Symbol("Needle:CurrentLOD"),Ge=ct,_={mesh_lod:-1,texture_lod:-1},Gt=new Re,qe=[3526751,11065402,15978811,15897394,15749691,11032304,4827122,3332036,16739229,7306743,14053330,3516499,12035359,14703919,3963096,42662,14100029,8344319,4633680,16229681,3120096,12076434,9083434,2060171,15751837,10182117,48121,62932,16704576,15817653,5083278,5592405];function qt(){const n=Ge.Timer||Ge.Clock;return new n}const _e=new ie,W=new ie,Ue=new ie,Ut=new k,Wt=new k,jt=new ke,G=new k,Q=new k,J=new k,Z=new k;function Ft(n,t){const e=n.min,r=n.max,s=(e.x+r.x)*.5,o=(e.y+r.y)*.5;return G.set(s,o,e.z).applyMatrix4(t).z<0}function We(n){const{geometry:t,matrixWorld:e,camera:r,projectionScreenMatrix:s,desiredDensity:o,canvasHeight:i=0,currentLevel:a=-1,xrEnabled:l=!1,debugDrawLine:u,warnMissingPrimitiveDensities:c=!1}=n,d=f.getMeshLODExtension(t)?.lods,p=f.getPrimitiveIndex(t),m=n.target??{level:a,primitiveIndex:p,screenCoverage:0,screenspaceVolume:new k,centrality:1};m.level=a,m.primitiveIndex=p,m.screenCoverage=0,m.screenspaceVolume.set(0,0,0),m.centrality=1;let w=n.boundingBox??t.boundingBox;if(w||(t.computeBoundingBox(),w=t.boundingBox),!w)return m;if(_e.copy(w).applyMatrix4(e),r.isPerspectiveCamera&&Ft(_e,s))return m.level=0,m.screenCoverage=1/0,m.screenspaceVolume.set(1/0,1/0,1/0),m;if(W.copy(_e).applyMatrix4(s),l&&r.isPerspectiveCamera&&r.fov>70){const L=W.min,y=W.max;let T=L.x,S=L.y,b=y.x,x=y.y;const v=2,R=1.5,F=(L.x+y.x)*.5,N=(L.y+y.y)*.5;T=(T-F)*v+F,S=(S-N)*v+N,b=(b-F)*v+F,x=(x-N)*v+N;const Ke=T<0&&b>0?0:Math.min(Math.abs(L.x),Math.abs(y.x)),Ye=S<0&&x>0?0:Math.min(Math.abs(L.y),Math.abs(y.y)),de=Math.max(Ke,Ye);m.centrality=(R-de)*(R-de)*(R-de)}const h=W.getSize(Ut);h.multiplyScalar(.5),globalThis.screen?.availHeight>0&&i>0&&h.multiplyScalar(i/globalThis.screen.availHeight),r.isPerspectiveCamera&&(h.x*=r.aspect),Ue.copy(w).applyMatrix4(e).applyMatrix4(r.matrixWorldInverse);const M=Ue.getSize(Wt),D=Math.max(h.x,h.y),j=Math.max(M.x,M.y);D!==0&&j!==0&&(h.z=M.z/j*D);const E=Math.max(h.x,h.y,h.z)*m.centrality;if(m.screenCoverage=E,m.screenspaceVolume.copy(h),E<=0)return m;if(u){const L=jt.copy(s);L.invert(),G.copy(W.min),Q.copy(W.max),Q.x=G.x,J.copy(W.max),J.y=G.y,Z.copy(W.max);const y=(G.z+Z.z)*.5;G.z=Q.z=J.z=Z.z=y,G.applyMatrix4(L),Q.applyMatrix4(L),J.applyMatrix4(L),Z.applyMatrix4(L),u(G,Q,255),u(G,J,255),u(Q,Z,255),u(J,Z,255)}if(d?.length)for(let L=0;L<d.length;L++){const y=d[L],T=y.densities?.[p]||y.density||1e-5;if(p>0&&c&&$e()&&!y.densities&&!globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"]&&(globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"]=!0,console.warn("[Needle Progressive] Detected usage of mesh without primitive densities. This might cause incorrect LOD level selection: Consider re-optimizing your model by updating your Needle Integration, Needle glTF Pipeline or running optimization again on Needle Cloud.")),T/E<o){m.level=L;break}}return m}let ne=class K{static debugDrawLine;static getObjectLODState(t){return t[De]}static addPlugin(t){$.push(t)}static removePlugin(t){const e=$.indexOf(t);e>=0&&$.splice(e,1)}static getPlugins(){return $}static get(t,e){if(t[Me])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[Me];const r=new K(t,{engine:"unknown",...e});return t[Me]=r,r}renderer;context;projectionScreenMatrix=new ke;get plugins(){return $}overrideLodLevel=void 0;targetTriangleDensity=2e5;skinnedMeshAutoUpdateBoundsInterval=30;updateInterval="auto";#e=1;pause=!1;manual=!1;_newPromiseGroups=[];_promiseGroupIds=0;awaitLoading(t){const e=this._promiseGroupIds++,r=new ue(this.#s,{...t});this._newPromiseGroups.push(r);const s=performance.now();return r.ready.finally(()=>{const o=this._newPromiseGroups.indexOf(r);o>=0&&(this._newPromiseGroups.splice(o,1),$e()&&performance.measure("LODsManager:awaitLoading",{start:s,detail:{id:e,name:t?.name,awaited:r.awaitedCount,resolved:r.resolvedCount}}))}),r.ready}trackLoadingPromise(t,e,r){return ue.addPromise(t,e,r,this._newPromiseGroups),r}_postprocessPromiseGroups(){if(this._newPromiseGroups.length!==0)for(let t=this._newPromiseGroups.length-1;t>=0;t--)this._newPromiseGroups[t].update(this.#s)}_lodchangedlisteners=[];addEventListener(t,e){return t==="changed"?(this._lodchangedlisteners.push(e),()=>{this.removeEventListener(t,e)}):()=>{}}removeEventListener(t,e){let r=!1;if(t==="changed"){const s=this._lodchangedlisteners.indexOf(e);s>=0&&(this._lodchangedlisteners.splice(s,1),r=!0)}return r}constructor(t,e){this.renderer=t,this.context={...e}}#t;#s=0;#o=0;#i=0;#r=0;#n=qt();_fpsBuffer=[60,60,60,60,60];enable(){if(this.#t)return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;this.#t=this.renderer.render;const e=this;ae(this.renderer),this.renderer.render=function(r,s){const o=e.renderer.getRenderTarget();(o==null||"isXRRenderTarget"in o&&o.isXRRenderTarget)&&(t=0,e.#s+=1,e.#n.update?.(),e.#o=Math.max(e.#n.getDelta(),1/1e3),e.#i+=e.#o,e._fpsBuffer.shift(),e._fpsBuffer.push(1/e.#o),e.#r=e._fpsBuffer.reduce((a,l)=>a+l)/e._fpsBuffer.length,A&&e.#s%200===0&&console.log("FPS",Math.round(e.#r),"Interval:",e.#e));const i=t++;e.#t.call(this,r,s),e.onAfterRender(r,s,i)}}disable(){this.#t&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=this.#t,this.#t=void 0)}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,r){if(this.pause)return;const s=this.getRenderList(t,e,r);if(!s)return;const o=s.opaque;let i=!0;if(o.length===1){const a=o[0].material;(a.name==="EffectMaterial"||a.name==="CopyShader")&&(i=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(i=!1),i){if(Bt||(this.updateInterval==="auto"?this.#r<40&&this.#e<10?(this.#e+=1,A&&console.warn("\u2193 Reducing LOD updates",this.#e,this.#r.toFixed(0))):this.#r>=60&&this.#e>1&&(this.#e-=1,A&&console.warn("\u2191 Increasing LOD updates",this.#e,this.#r.toFixed(0))):this.#e=this.updateInterval,this.#e>0&&this.#s%this.#e!=0))return;this.internalUpdate(t,e),this._postprocessPromiseGroups()}}internalUpdate(t,e){const r=this.getRenderList(t,e,0);if(!r)return;const s=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const o=this.targetTriangleDensity;for(const l of s){if(l.material&&(l.geometry?.type==="BoxGeometry"||l.geometry?.type==="BufferGeometry")&&(l.material.name==="SphericalGaussianBlur"||l.material.name=="BackgroundCubeMaterial"||l.material.name==="CubemapFromEquirect"||l.material.name==="EquirectangularToCubeUV")){A&&(l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",l,l.material.name,l.material.type)));continue}switch(l.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const u=l.object;(u instanceof V||u.isMesh)&&this.updateLODs(t,e,u,o)}const i=r.transparent;for(const l of i){const u=l.object;(u instanceof V||u.isMesh)&&this.updateLODs(t,e,u,o)}const a=r.transmissive;for(const l of a){const u=l.object;(u instanceof V||u.isMesh)&&this.updateLODs(t,e,u,o)}}getRenderList(t,e,r){const s=this.renderer;let o=null;if(s.isWebGPURenderer===!0){const i=s._renderLists;if(!i)return null;o=i.get(t,e)}else if(s.isWebGLRenderer===!0){const i=s.renderLists;if(!i)return null;o=i.get(t,r)}return o?{opaque:o.opaque||[],transparent:o.transparent||[],transmissive:o.transmissive||o.transparentDoublePass||[],transparentDoublePass:o.transparentDoublePass||[]}:null}updateLODs(t,e,r,s){r.userData||(r.userData={});let o=r[De];if(o||(o=new Nt,r[De]=o),o.frames++<2)return;for(const a of $)a.onBeforeUpdateLOD?.(this.renderer,t,e,r);const i=this.overrideLodLevel!==void 0?this.overrideLodLevel:X;i>=0?(_.mesh_lod=i,_.texture_lod=i):(this.calculateLodLevel(e,r,o,s,_),_.mesh_lod=Math.round(_.mesh_lod),_.texture_lod=Math.round(_.texture_lod)),_.mesh_lod>=0&&this.loadProgressiveMeshes(r,_.mesh_lod),r.material&&_.texture_lod>=0&&this.loadProgressiveTextures(r.material,_.texture_lod,i),g&&r.material&&!r.isGizmo&&Be(r.material),$t&&r.material&&!r.isGizmo&&!r.isBatchedMesh&&je(r.material,_.mesh_lod);for(const a of $)a.onAfterUpdatedLOD?.(this.renderer,t,e,r,_);o.lastLodLevel_Mesh=_.mesh_lod,o.lastLodLevel_Texture=_.texture_lod}loadProgressiveTextures(t,e,r){if(!t)return;if(Array.isArray(t)){for(const i of t)this.loadProgressiveTextures(i,e,r);return}let s=!1;(t[U]===void 0||e<t[U])&&(s=!0);const o=r!==void 0&&r>=0;if(o&&(s=t[U]!=r,e=r),s){t[U]=e;const i=o?{force:!0}:void 0,a=f.assignTextureLOD(t,e,i).then(l=>{this._lodchangedlisteners.forEach(u=>u({type:"texture",level:e,object:t}))});ue.addPromise("texture",t,a,this._newPromiseGroups)}}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let r=t[U]!==e;const s=t["DEBUG:LOD"];if(s!=null&&(r=t[U]!=s,e=s),r){t[U]=e;const o=t.geometry,i=f.assignMeshLOD(t,e).then(a=>(a&&t[U]==e&&o!=t.geometry&&this._lodchangedlisteners.forEach(l=>l({type:"mesh",level:e,object:t})),a));return ue.addPromise("mesh",t,i,this._newPromiseGroups),i}return Promise.resolve(null)}_sphere=new Oe;_tempWorldPosition=new k;static skinnedMeshBoundsFrameOffsetCounter=0;static $skinnedMeshBoundsOffset=Symbol("gltf-progressive-skinnedMeshBoundsOffset");calculateLodLevel(t,e,r,s,o){if(!e){o.mesh_lod=-1,o.texture_lod=-1;return}if(!t){o.mesh_lod=-1,o.texture_lod=-1;return}let i=10+1,a=!1;if(A&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const l=f.getMeshLODExtension(e.geometry)?.lods,u=f.getPrimitiveIndex(e.geometry),c=l&&l.length>0,d=f.getMaterialMinMaxLODsCount(e.material),p=d.min_count!==1/0&&d.min_count>=0&&d.max_count>=0;if(!c&&!p){o.mesh_lod=0,o.texture_lod=0;return}c||(a=!0,i=0);const m=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let w=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const h=e;if(!h.boundingBox)h.computeBoundingBox();else if(this.skinnedMeshAutoUpdateBoundsInterval>0){if(!h[K.$skinnedMeshBoundsOffset]){const D=K.skinnedMeshBoundsFrameOffsetCounter++;h[K.$skinnedMeshBoundsOffset]=D}const M=h[K.$skinnedMeshBoundsOffset];if((r.frames+M)%this.skinnedMeshAutoUpdateBoundsInterval===0){const D=Y(h),j=h.geometry;D&&(h.geometry=D),h.computeBoundingBox(),h.geometry=j}}w=h.boundingBox}if(w){if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const M=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(M)){o.mesh_lod=0,o.texture_lod=0;return}}const h=We({geometry:e.geometry,matrixWorld:e.matrixWorld,camera:t,projectionScreenMatrix:this.projectionScreenMatrix,desiredDensity:s,canvasHeight:m,currentLevel:r.lastLodLevel_Mesh,boundingBox:w,xrEnabled:this.renderer.xr.enabled,debugDrawLine:A?K.debugDrawLine:void 0,warnMissingPrimitiveDensities:!0});if(r.lastCentrality=h.centrality,r.lastScreenCoverage=h.screenCoverage,r.lastScreenspaceVolume.copy(h.screenspaceVolume),h.screenCoverage===1/0){o.mesh_lod=0,o.texture_lod=0;return}h.level>=0&&h.level<i&&(i=h.level,a=!0)}if(a?o.mesh_lod=i:o.mesh_lod=r.lastLodLevel_Mesh,A&&o.mesh_lod!=r.lastLodLevel_Mesh){const h=l?.[o.mesh_lod];h&&console.log(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${o.mesh_lod} (density: ${h.densities?.[u].toFixed(0)}) | ${e.name}`)}if(p){const h="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(o.texture_lod=d.max_count-1,A){const M=d.lods[d.max_count-1];A&&console.log(`First Texture LOD ${o.texture_lod} (${M.max_height}px) - ${e.name}`)}}else{const M=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let D=r.lastScreenCoverage*4;this.context?.engine==="model-viewer"&&(D*=1.5);const j=this.renderer.getPixelRatio?.()||globalThis.devicePixelRatio||1,E=m/j*D;let L=!1;for(let y=d.lods.length-1;y>=0;y--){const T=d.lods[y];if(!(h&&T.max_height>=2048)&&!(ve()&&T.max_height>4096)&&(T.max_height>E||!L&&y===0)){if(L=!0,o.texture_lod=y,A&&o.texture_lod<r.lastLodLevel_Texture){const S=T.max_height;console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${o.texture_lod} = ${S}px
8
- Screensize: ${E.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${M.toFixed(1)}
9
- ${e.name}`)}break}}}}else o.texture_lod=0}};class Nt{frames=0;lastLodLevel_Mesh=-1;lastLodLevel_Texture=-1;lastScreenCoverage=0;lastScreenspaceVolume=new k;lastCentrality=0}function je(n,t){if(!(t<0)){if(Array.isArray(n)){for(const e of n)je(e,t);return}"color"in n&&n.color instanceof Re&&(n.color.copy(Fe(t,Gt)),n.needsUpdate=!0)}}function Fe(n,t){const e=Math.max(0,Math.min(qe.length-1,Math.floor(n)));return t.setHex(qe[e])}const Ne=Symbol("NEEDLE_mesh_lod"),ce=Symbol("NEEDLE_texture_lod");let Te=null;function ze(){const n=zt();n&&(n.mapURLs(function(t){return Ve(),t}),Ve(),Te?.disconnect(),Te=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(r=>{r instanceof HTMLElement&&r.tagName.toLowerCase()==="model-viewer"&&Xe(r)})})}),Te.observe(document,{childList:!0,subtree:!0}))}function zt(){return typeof customElements>"u"?null:customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),ze()}),null)}function Ve(){typeof document>"u"||document.querySelectorAll("model-viewer").forEach(n=>{Xe(n)})}const He=new WeakSet;let Vt=0;function Xe(n){if(!n||He.has(n))return null;He.add(n),console.debug("[gltf-progressive] found new model-viewer..."+ ++Vt+`
10
- `,n.getAttribute("src"));let t=null,e=null,r=null;for(let s=n;s!=null;s=Object.getPrototypeOf(s)){const o=Object.getOwnPropertySymbols(s),i=o.find(u=>u.toString()=="Symbol(renderer)"),a=o.find(u=>u.toString()=="Symbol(scene)"),l=o.find(u=>u.toString()=="Symbol(needsRender)");!t&&i!=null&&(t=n[i].threeRenderer),!e&&a!=null&&(e=n[a]),!r&&l!=null&&(r=n[l])}if(t&&e){let s=function(){if(r){let i=0;const a=setInterval(()=>{if(i++>5){clearInterval(a);return}r?.call(n)},300)}};console.debug("[gltf-progressive] setup model-viewer");const o=ne.get(t,{engine:"model-viewer"});return ne.addPlugin(new Ht),o.enable(),o.addEventListener("changed",()=>{r?.call(n)}),n.addEventListener("model-visibility",i=>{i.detail.visible&&r?.call(n)}),n.addEventListener("load",()=>{s()}),()=>{o.disable()}}return null}class Ht{_didWarnAboutMissingUrl=!1;onBeforeUpdateLOD(t,e,r,s){this.tryParseMeshLOD(e,s),this.tryParseTextureLOD(e,s)}getUrl(t){if(!t)return null;let e=t.getAttribute("src");return e||(e=t.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",t),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(t){return t._currentGLTF}tryGetCurrentModelViewer(t){return t.element}tryParseTextureLOD(t,e){if(e[ce]==!0)return;e[ce]=!0;const r=this.tryGetCurrentGLTF(t),s=this.tryGetCurrentModelViewer(t),o=this.getUrl(s);if(o&&r&&e.material){let i=function(l){if(l[ce]==!0)return;l[ce]=!0,l.userData&&(l.userData.LOD=-1);const u=Object.keys(l);for(let c=0;c<u.length;c++){const d=u[c],p=l[d];if(p?.isTexture===!0){const m=p.userData?.associations?.textures;if(m==null)continue;const w=r.parser.json.textures[m];if(!w){console.warn("Texture data not found for texture index "+m);continue}if(w?.extensions?.[B]){const h=w.extensions[B];h&&o&&f.registerTexture(o,p,h.lods.length,m,h)}}}};const a=e.material;if(Array.isArray(a))for(const l of a)i(l);else i(a)}}tryParseMeshLOD(t,e){if(e[Ne]==!0)return;e[Ne]=!0;const r=this.tryGetCurrentModelViewer(t),s=this.getUrl(r);if(!s)return;const o=e.userData?.gltfExtensions?.[B];if(o&&s){const i=e.uuid;f.registerMesh(s,i,e,0,o.lods.length,o)}}}function Xt(...n){let t,e,r,s;switch(n.length){case 2:[r,e]=n,s={};break;case 3:[r,e,s]=n;break;case 4:[t,e,r,s]=n;break;default:throw new Error("Invalid arguments")}ae(e),ge(r),pe(r,{progressive:!0,...s?.hints}),r.register(i=>new f(i));const o=ne.get(e);return s?.enableLODsManager!==!1&&o.enable(),o}if(ze(),!Tt){const n={gltfProgressive:{useNeedleProgressive:Xt,LODsManager:ne,configureLoader:pe,getRaycastMesh:Y,useRaycastMeshes:Ot}};if(!globalThis.Needle)globalThis.Needle=n;else for(const t in n)globalThis.Needle[t]=n[t]}export{ne as LODsManager,f as NEEDLE_progressive,ge as addDracoAndKTX2Loaders,We as calculateMeshLODLevel,pe as configureLoader,ae as createLoaders,Fe as getLODColor,Y as getRaycastMesh,Ce as setDracoDecoderLocation,Ae as setKTX2TranscoderLocation};
@@ -1,10 +0,0 @@
1
- "use strict";const d=require("./three-core.umd.cjs"),Y=require("./three-examples.umd.cjs");var ce=typeof document<"u"?document.currentScript:null;const Ne="";globalThis.GLTF_PROGRESSIVE_VERSION=Ne;console.debug("[gltf-progressive] version -");let I="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",X="https://cdn.needle.tools/static/three/0.179.1/basis2/";const Xe=I,je=X,Ae=new URL(I+"draco_decoder.js");Ae.searchParams.append("range","true");fetch(Ae,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(o=>{console.debug(`Failed to fetch remote Draco decoder from ${I} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),I===Xe&&Ie("./include/draco/"),X===je&&$e("./include/ktx2/")}).finally(()=>{Be()});const Ke=()=>({dracoDecoderPath:I,ktx2TranscoderPath:X});function Ie(o){I=o,P&&P[ye]!=I?(console.debug("Updating Draco decoder path to "+o),P[ye]=I,P.setDecoderPath(I),P.preload()):console.debug("Setting Draco decoder path to "+o)}function $e(o){X=o,$&&$.transcoderPath!=X?(console.debug("Updating KTX2 transcoder path to "+o),$.setTranscoderPath(X),$.init()):console.debug("Setting KTX2 transcoder path to "+o)}function le(o){return Be(),o?$.detectSupport(o):o!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:P,ktx2Loader:$,meshoptDecoder:ae}}function Me(o){o.dracoLoader||o.setDRACOLoader(P),o.ktx2Loader||o.setKTX2Loader($),o.meshoptDecoder||o.setMeshoptDecoder(ae)}const ye=Symbol("dracoDecoderPath");let P,ae,$;function Be(){P||(P=new Y.DRACOLoader,P[ye]=I,P.setDecoderPath(I),P.setDecoderConfig({type:"js"}),P.preload()),$||($=new Y.KTX2Loader,$.setTranscoderPath(X),$.init()),ae||(ae=Y.MeshoptDecoder)}const xe=new WeakMap;function ve(o,t){let e=xe.get(o);e?e=Object.assign(e,t):e=t,xe.set(o,e)}const He=Y.GLTFLoader.prototype.load;function Ye(...o){const t=xe.get(this);let e=o[0];const s=Qe(e);if(s?.hostname.endsWith("needle.tools")){const n=t?.progressive!==void 0?t.progressive:!0,i=t?.usecase?t.usecase:"default";n?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${i}`:this.requestHeader.Accept=`*/*;usecase=${i}`,e=s.toString()}return o[0]=e,He?.call(this,...o)}Y.GLTFLoader.prototype.load=Ye;function Qe(o){try{if(o instanceof URL)return o;const t=globalThis.location?.href;return t?new URL(o,t):new URL(o)}catch{return null}}function be(o){return o!=null&&o.data!=null}function Le(o){const t=o.source?.data;return t!=null&&typeof t=="object"?t:null}function Je(o){const t=o.image;return t!=null&&typeof t=="object"?t:null}function we(o){const t=Je(o),e=Le(o);return{width:t?.width||e?.width||0,height:t?.height||e?.height||0}}V("debugprogressive");function V(o){const t=globalThis.location?.href;if(!t)return!1;const s=new URL(t).searchParams.get(o);return s==null||s==="0"||s==="false"?!1:s===""?!0:s}function Ze(o,t){if(t===void 0||o===void 0||t.startsWith("./")||t.startsWith("http")||t.startsWith("data:")||t.startsWith("blob:"))return t;const e=o.lastIndexOf("/");if(e>=0){const s=o.substring(0,e+1);for(;s.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return s+t}return t}function _e(){if(J!==void 0)return J;const o=globalThis.navigator?.userAgent||"";return J=/iPhone|iPad|iPod|Android|IEMobile/i.test(o),V("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",J),J}let J;function Ge(){const o=globalThis.location?.href;if(!o)return!1;const t=new URL(o),e=t.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(t.hostname);return t.hostname==="127.0.0.1"||e}class et{constructor(t,e={}){this.maxConcurrent=t,this.debug=e.debug??!1,typeof globalThis.requestAnimationFrame=="function"?globalThis.requestAnimationFrame(this.tick):setTimeout(this.tick,0)}_running=new Map;_queue=[];debug=!1;tick=()=>{this.internalUpdate(),setTimeout(this.tick,10)};slot(t){return this.debug&&console.debug(`[PromiseQueue]: Requesting slot for key ${t}, running: ${this._running.size}, waiting: ${this._queue.length}`),new Promise(e=>{this._queue.push({key:t,resolve:e})})}add(t,e){this._running.has(t)||(this._running.set(t,e),e.finally(()=>{this._running.delete(t),this.debug&&console.debug(`[PromiseQueue]: Promise finished now running: ${this._running.size}, waiting: ${this._queue.length}. (finished ${t})`)}),this.debug&&console.debug(`[PromiseQueue]: Added new promise, now running: ${this._running.size}, waiting: ${this._queue.length}. (added ${t})`))}internalUpdate(){const t=this.maxConcurrent-this._running.size;for(let e=0;e<t&&this._queue.length>0;e++){this.debug&&console.debug(`[PromiseQueue]: Running ${this._running.size} promises, waiting for ${this._queue.length} more.`);const{key:s,resolve:r}=this._queue.shift();r({use:n=>this.add(s,n)})}}}function tt(o){const t=o.image,e=t?.width??0,s=t?.height??0,r=t?.depth??1,n=Math.floor(Math.log2(Math.max(e,s,r)))+1,i=st(o);return e*s*r*i*(1-Math.pow(.25,n))/(1-.25)}function st(o){let t=4;const e=o.format;e===d.RedFormat||e===d.RedIntegerFormat?t=1:e===d.RGFormat||e===d.RGIntegerFormat?t=2:e===d.RGBFormat||e===1029?t=3:(e===d.RGBAFormat||e===d.RGBAIntegerFormat)&&(t=4);let s=1;const r=o.type;return r===1009||r===1010?s=1:r===1011||r===1012?s=2:r===1013||r===1014||r===1015?s=4:r===1016&&(s=2),t*s}const rt=typeof window>"u"&&typeof document>"u",De=Symbol("needle:raycast-mesh");function Q(o){return o?.[De]instanceof d.BufferGeometry?o[De]:null}function nt(o,t){if((o.type==="Mesh"||o.type==="SkinnedMesh")&&!Q(o)){const s=it(t);s.userData={isRaycastMesh:!0},o[De]=s}}function ot(o=!0){if(o){if(Z)return;const t=Z=d.Mesh.prototype.raycast;d.Mesh.prototype.raycast=function(e,s){const r=this,n=Q(r);let i;n&&r.isMesh&&(i=r.geometry,r.geometry=n),t.call(this,e,s),i&&(r.geometry=i)}}else{if(!Z)return;d.Mesh.prototype.raycast=Z,Z=null}}let Z=null;function it(o){const t=new d.BufferGeometry;for(const e in o.attributes)t.setAttribute(e,o.getAttribute(e));return t.setIndex(o.getIndex()),t}const q=new Array,g=V("debugprogressive");let se,E=-1;if(g&&typeof window<"u"){let o=function(){E+=1,E>=t&&(E=-1),console.log(`Toggle LOD level [${E}]`)};const t=6;window.addEventListener("keyup",e=>{e.key==="p"&&o(),e.key==="w"&&(se=!se,console.log(`Toggle wireframe [${se}]`));const s=parseInt(e.key);!isNaN(s)&&s>=0&&(E=s,console.log(`Set LOD level to [${E}]`))})}function qe(o){if(g&&se!==void 0)if(Array.isArray(o))for(const t of o)qe(t);else o&&"wireframe"in o&&(o.wireframe=se===!0)}const ee=new Array;let at=0;const lt=_e()?2:10;function ut(o){if(ee.length<lt){const s=ee.length;g&&console.warn(`[Worker] Creating new worker #${s}`);const r=Te.createWorker(o||{});return ee.push(r),r}const t=at++%ee.length;return ee[t]}class Te{constructor(t,e){this.worker=t,this._debug=e.debug??!1,t.onmessage=s=>{const r=s.data;switch(this._debug&&console.log("[Worker] EVENT",r),r.type){case"loaded-gltf":for(const n of this._running)if(n.url===r.result.url){ct(r.result),n.resolve(r.result);const i=n.url;i.startsWith("blob:")&&URL.revokeObjectURL(i)}}},t.onerror=s=>{console.error("[Worker] Error in gltf-progressive worker:",s)},t.postMessage({type:"init"})}static async createWorker(t){const e=new Worker(new URL("/gltf-progressive.worker-BqODMeeW.js",typeof document>"u"?require("url").pathToFileURL(__filename).href:ce&&ce.tagName.toUpperCase()==="SCRIPT"&&ce.src||new URL("gltf-progressive-DeZioRZe.umd.cjs",document.baseURI).href),{type:"module"});return new Te(e,t)}_running=[];_webglRenderer=null;async load(t,e){const s=Ke();let r=e?.renderer;r||(this._webglRenderer??=(async()=>{const{WebGLRenderer:u}=await Promise.resolve().then(()=>require("./three-core.umd.cjs")).then(c=>c.THREE);return new u})(),r=await this._webglRenderer);const a=le(r).ktx2Loader.workerConfig;if(t instanceof URL)t=t.toString();else if(t.startsWith("file:"))t=URL.createObjectURL(new Blob([t]));else if(!t.startsWith("blob:")&&!t.startsWith("http:")&&!t.startsWith("https:")){const u=globalThis.location?.href;u&&(t=new URL(t,u).toString())}const l={type:"load",url:t,dracoDecoderPath:s.dracoDecoderPath,ktx2TranscoderPath:s.ktx2TranscoderPath,ktx2LoaderConfig:a};return this._debug&&console.debug("[Worker] Sending load request",l),this.worker.postMessage(l),new Promise(u=>{this._running.push({url:t.toString(),resolve:u})})}_debug=!1}function ct(o){for(const t of o.geometries){const e=t.geometry,s=new d.BufferGeometry;if(s.name=e.name||"",e.index){const r=e.index;s.setIndex(fe(r))}for(const r in e.attributes){const n=e.attributes[r],i=fe(n);s.setAttribute(r,i)}if(e.morphAttributes)for(const r in e.morphAttributes){const i=e.morphAttributes[r].map(a=>fe(a));s.morphAttributes[r]=i}if(s.morphTargetsRelative=e.morphTargetsRelative??!1,s.boundingBox=new d.Box3,s.boundingBox.min=new d.Vector3(e.boundingBox?.min.x,e.boundingBox?.min.y,e.boundingBox?.min.z),s.boundingBox.max=new d.Vector3(e.boundingBox?.max.x,e.boundingBox?.max.y,e.boundingBox?.max.z),s.boundingSphere=new d.Sphere(new d.Vector3(e.boundingSphere?.center.x,e.boundingSphere?.center.y,e.boundingSphere?.center.z),e.boundingSphere?.radius),e.groups)for(const r of e.groups)s.addGroup(r.start,r.count,r.materialIndex);e.userData&&(s.userData=e.userData),t.geometry=s}for(const t of o.textures){const e=t.texture;let s=null;if(e.isCompressedTexture){const r=e.mipmaps,{width:n,height:i}=we(e);s=new d.CompressedTexture(r,n,i,e.format,e.type,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.anisotropy,e.colorSpace)}else s=new d.Texture(e.image,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.format,e.type,e.anisotropy,e.colorSpace),s.mipmaps=e.mipmaps,s.channel=e.channel,s.source.data=e.source.data,s.flipY=e.flipY,s.premultiplyAlpha=e.premultiplyAlpha,s.unpackAlignment=e.unpackAlignment,s.matrix=new d.Matrix3(...e.matrix.elements);if(!s){console.error("[Worker] Failed to create new texture from received data. Texture is not a CompressedTexture or Texture.");continue}t.texture=s}return o}function fe(o){let t=o;if("isInterleavedBufferAttribute"in o&&o.isInterleavedBufferAttribute){const e=o.data,s=e.array,r=new d.InterleavedBuffer(s,e.stride);t=new d.InterleavedBufferAttribute(r,o.itemSize,s.byteOffset,o.normalized),t.offset=o.offset}else"isBufferAttribute"in o&&o.isBufferAttribute&&(t=new d.BufferAttribute(o.array,o.itemSize,o.normalized),t.usage=o.usage,t.gpuType=o.gpuType,t.updateRanges=o.updateRanges);return t}const ft=V("gltf-progressive-worker");V("gltf-progressive-reduce-mipmaps");const te=V("gltf-progressive-gc"),de=Symbol("needle-progressive-texture"),F="NEEDLE_progressive";class p{get name(){return F}static getMeshLODExtension(t){const e=this.getAssignedLODInformation(t);return e?.key?this.lodInfos.get(e.key):null}static getPrimitiveIndex(t){const e=this.getAssignedLODInformation(t)?.index;return e??-1}static getMaterialMinMaxLODsCount(t,e){const s=this,r="LODS:minmax",n=t[r];if(n!=null)return n;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const a of t)this.getMaterialMinMaxLODsCount(a,e);return t[r]=e,e}if(g==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const a=t;for(const l of Object.keys(a.uniforms)){const u=a.uniforms[l].value;u?.isTexture===!0&&i(u,e)}}else if(t.isMaterial)for(const a of Object.keys(t)){const l=t[a];l?.isTexture===!0&&i(l,e)}else g&&console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);return t[r]=e,e;function i(a,l){const u=s.getAssignedLODInformation(a);if(u){const c=s.lodInfos.get(u.key);if(c&&c.lods){l.min_count=Math.min(l.min_count,c.lods.length),l.max_count=Math.max(l.max_count,c.lods.length);for(let f=0;f<c.lods.length;f++){const h=c.lods[f];h.width&&(l.lods[f]=l.lods[f]||{min_height:1/0,max_height:0},l.lods[f].min_height=Math.min(l.lods[f].min_height,h.height),l.lods[f].max_height=Math.max(l.lods[f].max_height,h.height))}}}}}static hasLODLevelAvailable(t,e){if(Array.isArray(t)){for(const n of t)if(this.hasLODLevelAvailable(n,e))return!0;return!1}if(t.isMaterial===!0){for(const n of Object.keys(t)){const i=t[n];if(i&&i.isTexture&&this.hasLODLevelAvailable(i,e))return!0}return!1}else if(t.isGroup===!0){for(const n of t.children)if(n.isMesh===!0&&this.hasLODLevelAvailable(n,e))return!0}let s,r;if(t.isMesh?s=t.geometry:(t.isBufferGeometry||t.isTexture)&&(s=t),s&&s?.userData?.LODS){const n=s.userData.LODS;if(r=this.lodInfos.get(n.key),e===void 0)return r!=null;if(r)return Array.isArray(r.lods)?e<r.lods.length:e===0}return!1}static assignMeshLOD(t,e,s){if(!t)return Promise.resolve(null);if(t instanceof d.Mesh||t.isMesh===!0){const r=t.geometry,n=this.getAssignedLODInformation(r);if(!n)return Promise.resolve(null);for(const a of q)a.onBeforeGetLODMesh?.(t,e);t["LOD:requested level"]=e;const i=()=>t["LOD:requested level"]===e||this.shouldApplyStaleMeshLOD(t,e);return p.getOrLoadLOD(r,e,{isCurrent:i}).then(a=>{if(Array.isArray(a)){const u=n.index||0;a=a[u]}const l=t["LOD:requested level"]===e;return(l||this.shouldApplyStaleMeshLOD(t,e))&&(l&&delete t["LOD:requested level"],a&&r!=a&&(a?.isBufferGeometry?typeof s?.apply=="function"?s.apply(a,e,t):s?.apply!==!1&&(t.geometry=a):g&&console.error("Invalid LOD geometry",a))),a}).catch(a=>(console.error("Error loading mesh LOD",t,a),null))}else g&&console.error("Invalid call to assignMeshLOD: Request mesh LOD but the object is not a mesh",t);return Promise.resolve(null)}static assignTextureLOD(t,e=0,s){if(!t)return Promise.resolve(null);const r=s?.force===!0;if(t.isMesh===!0){const n=t;if(Array.isArray(n.material)){const i=new Array;for(const a of n.material){const l=this.assignTextureLOD(a,e,s);i.push(l)}return Promise.all(i).then(a=>{const l=new Array;for(const u of a)Array.isArray(u)&&l.push(...u);return l})}else return this.assignTextureLOD(n.material,e,s)}if(t.isMaterial===!0){const n=t,i=[],a=new Array;if(this.trackCurrentMaterialTextureSlots(n),n.uniforms&&(n.isRawShaderMaterial||n.isShaderMaterial===!0)){const l=n;for(const u of Object.keys(l.uniforms)){const c=l.uniforms[u].value;if(c?.isTexture===!0){const f=this.assignTextureLODForSlot(c,e,n,u,r).then(h=>(h&&l.uniforms[u].value!=h&&(l.uniforms[u].value=h,l.uniformsNeedUpdate=!0),h));i.push(f),a.push(u)}}}else for(const l of Object.keys(n)){const u=n[l];if(u?.isTexture===!0){const c=this.assignTextureLODForSlot(u,e,n,l,r);i.push(c),a.push(l)}}return Promise.all(i).then(l=>{const u=new Array;for(let c=0;c<l.length;c++){const f=l[c],h=a[c];f&&f.isTexture===!0?u.push({material:n,slot:h,texture:f,level:e}):u.push({material:n,slot:h,texture:null,level:e})}return u})}if(t instanceof d.Texture||t.isTexture===!0){const n=t;return this.assignTextureLODForSlot(n,e,null,null,r)}return Promise.resolve(null)}static set maxConcurrentLoadingTasks(t){p.queue.maxConcurrent=t}static get maxConcurrentLoadingTasks(){return p.queue.maxConcurrent}static assignTextureLODForSlot(t,e,s,r,n){if(t?.isTexture!==!0)return Promise.resolve(null);if(r==="glyphMap")return Promise.resolve(t);const i=this.getAssignedLODInformation(t);if(i&&(i.level===e||!n&&i.level<e))return Promise.resolve(t);if(s&&r){const f=this.getPendingTextureSlotRequest(s,r);if(f&&f.level===e&&f.force===n)return f.promise}const a=s&&r?this.nextTextureSlotRequestId(s,r,e,n):0,l=()=>!s||!r||this.getLatestTextureSlotRequest(s,r)?.id===a,u=()=>l()||this.shouldApplyStaleTextureSlotLOD(s,r,e,n),c=p.getOrLoadLOD(t,e,{isCurrent:u}).then(f=>{if(!l()&&!this.shouldApplyStaleTextureSlotLOD(s,r,e,n))return null;if(Array.isArray(f))return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."),null;if(f?.isTexture===!0){if(f!=t&&s&&r){const h=this.getMaterialTextureSlot(s,r)??t;if(h&&!n){const m=this.getAssignedLODInformation(h);if(m&&m?.level<e)return g==="verbose"&&console.warn("Assigned texture level is already higher: ",m.level,e,s,h,f),null}this.assignTrackedTextureSlot(s,r,f)}return f}else g=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(f=>(console.error("Error loading LOD",t,f),null));return s&&r&&this.setPendingTextureSlotRequest(s,r,e,n,a,c),c}static trackedTextureSlots=new WeakMap;static pendingTextureSlotRequests=new WeakMap;static latestTextureSlotRequests=new WeakMap;static textureSlotRequestId=0;static trackCurrentMaterialTextureSlots(t){if(t.uniforms&&(t.isRawShaderMaterial||t.isShaderMaterial===!0)){const e=t;for(const s of Object.keys(e.uniforms)){const r=e.uniforms[s].value;r?.isTexture===!0&&this.ensureTrackedTextureSlot(t,s,r)}return}for(const e of Object.keys(t)){const s=t[e];s?.isTexture===!0&&this.ensureTrackedTextureSlot(t,e,s)}}static getPendingTextureSlotRequest(t,e){return this.pendingTextureSlotRequests.get(t)?.get(e)}static nextTextureSlotRequestId(t,e,s,r){let n=this.latestTextureSlotRequests.get(t);n||(n=new Map,this.latestTextureSlotRequests.set(t,n));const i=++this.textureSlotRequestId;return n.set(e,{id:i,level:s,force:r}),i}static getLatestTextureSlotRequest(t,e){return this.latestTextureSlotRequests.get(t)?.get(e)}static shouldApplyStaleTextureSlotLOD(t,e,s,r){if(!t||!e)return!1;const n=this.getLatestTextureSlotRequest(t,e),i=this.getMaterialTextureSlot(t,e),a=this.getAssignedLODInformation(i)?.level??1/0;return s>=a?!1:r?n?s>=n.level:!1:!0}static shouldApplyStaleMeshLOD(t,e){const s=t["LOD:requested level"];if(typeof s!="number")return!1;const r=this.getAssignedLODInformation(t.geometry)?.level??1/0;return e<r&&e>=s}static setPendingTextureSlotRequest(t,e,s,r,n,i){let a=this.pendingTextureSlotRequests.get(t);a||(a=new Map,this.pendingTextureSlotRequests.set(t,a));const l={level:s,force:r,id:n,promise:i};a.set(e,l),i.finally(()=>{a.get(e)?.id===n&&a.delete(e)})}static getMaterialTextureSlot(t,e){const r=t.uniforms?.[e];if(r?.value?.isTexture===!0)return r.value;const n=t[e];return n?.isTexture===!0?n:null}static setMaterialTextureSlot(t,e,s){const n=t.uniforms?.[e];if(n?.value?.isTexture===!0){n.value=s,t.uniformsNeedUpdate=!0;return}t[e]=s}static assignTrackedTextureSlot(t,e,s){let r=this.trackedTextureSlots.get(t);r||(r=new Map,this.trackedTextureSlots.set(t,r));const n=this.getMaterialTextureSlot(t,e);let i=r.get(e);!i&&n?i=this.ensureTrackedTextureSlot(t,e,n):i&&n&&i!==n&&(this.releaseTrackedTextureSlot(t,e,i),i=this.ensureTrackedTextureSlot(t,e,n)),!(i===s&&n===s)&&(i&&i!==s&&this.releaseTrackedTextureSlot(t,e,i),i!==s&&(this.trackTextureUsage(s),r.set(e,s)),n!==s&&this.setMaterialTextureSlot(t,e,s))}static ensureTrackedTextureSlot(t,e,s){let r=this.trackedTextureSlots.get(t);r||(r=new Map,this.trackedTextureSlots.set(t,r));const n=r.get(e);return n===s?n:(n&&this.releaseTrackedTextureSlot(t,e,n),this.trackTextureUsage(s),r.set(e,s),s)}static releaseTrackedTextureSlot(t,e,s){const r=this.trackedTextureSlots.get(t);if(r?.get(e)===s&&r.delete(e),this.untrackTextureUsage(s)&&(g||te)){const i=this.getAssignedLODInformation(s);console.log(`[gltf-progressive] Disposed old texture LOD ${i?.level??"?"} for ${t.name||t.type}.${e}`,s.uuid)}}parser;url;constructor(t){const e=t.options.path;g&&console.log("Progressive extension registered for",e),this.parser=t,this.url=e}_isLoadingMesh;loadMesh=t=>{if(this._isLoadingMesh)return null;const e=this.parser.json.meshes[t]?.extensions?.[F];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(s=>(this._isLoadingMesh=!1,s&&p.registerMesh(this.url,e.guid,s,e.lods?.length,0,e),s))):null};afterRoot(t){return g&&console.log("AFTER",this.url,t),this.parser.json.textures?.forEach((e,s)=>{if(e?.extensions){const r=e?.extensions[F];if(r){if(!r.lods){g&&console.warn("Texture has no LODs",r);return}let n=!1;for(const i of this.parser.associations.keys())i.isTexture===!0&&this.parser.associations.get(i)?.textures===s&&(n=!0,p.registerTexture(this.url,i,r.lods?.length,s,r));n||this.parser.getDependency("texture",s).then(i=>{i&&p.registerTexture(this.url,i,r.lods?.length,s,r)})}}}),this.parser.json.meshes?.forEach((e,s)=>{if(e?.extensions){const r=e?.extensions[F];if(r&&r.lods){for(const n of this.parser.associations.keys())if(n.isMesh){const i=this.parser.associations.get(n);i?.meshes===s&&p.registerMesh(this.url,r.guid,n,r.lods.length,i.primitives,r)}}}}),null}static registerTexture=(t,e,s,r,n)=>{if(!e){g&&console.error("!! gltf-progressive: Called register texture without texture");return}if(g){const{width:a,height:l}=we(e);console.log(`> gltf-progressive: register texture[${r}] "${e.name||e.uuid}", Current: ${a}x${l}, Max: ${n.lods[0]?.width}x${n.lods[0]?.height}, uuid: ${e.uuid}`,n,e)}e.source&&(e.source[de]=n);const i=n.guid;p.assignLODInformation(t,e,i,s,r),p.lodInfos.set(i,n),p.lowresCache.set(i,new WeakRef(e))};static registerMesh=(t,e,s,r,n,i)=>{const a=s.geometry;if(!a){g&&console.warn("gltf-progressive: Register mesh without geometry");return}a.userData||(a.userData={}),g&&console.log("> Progressive: register mesh "+s.name,{index:n,uuid:s.uuid},i,s),p.assignLODInformation(t,a,e,r,n),p.lodInfos.set(e,i);let u=p.lowresCache.get(e)?.deref();u?u.push(s.geometry):u=[s.geometry],p.lowresCache.set(e,new WeakRef(u)),r>0&&!Q(s)&&nt(s,a);for(const c of q)c.onRegisteredNewMesh?.(s,i)};static dispose(t){if(t){this.lodInfos.delete(t);const e=this.lowresCache.get(t);if(e){const s=e.deref();if(s){if(s.isTexture){const r=s;this.textureRefCounts.delete(r.uuid),r.dispose()}else if(Array.isArray(s))for(const r of s)r.dispose()}this.lowresCache.delete(t)}for(const[s,r]of this.cache)s.includes(t)&&(this._disposeCacheEntry(r),this.cache.delete(s))}else{this.lodInfos.clear();for(const[,e]of this.lowresCache){const s=e.deref();if(s){if(s.isTexture){const r=s;this.textureRefCounts.delete(r.uuid),r.dispose()}else if(Array.isArray(s))for(const r of s)r.dispose()}}this.lowresCache.clear();for(const[,e]of this.cache)this._disposeCacheEntry(e);this.cache.clear(),this.textureRefCounts.clear(),this.trackedTextureSlots=new WeakMap,this.pendingTextureSlotRequests=new WeakMap,this.latestTextureSlotRequests=new WeakMap,this.textureSlotRequestId=0}}static _disposeCacheEntry(t){if(t instanceof WeakRef){const e=t.deref();e&&(e.isTexture&&this.textureRefCounts.delete(e.uuid),e.dispose())}else t.then(e=>{if(e)if(Array.isArray(e))for(const s of e)s.dispose();else e.isTexture&&this.textureRefCounts.delete(e.uuid),e.dispose()}).catch(()=>{})}static lodInfos=new Map;static cache=new Map;static lowresCache=new Map;static textureRefCounts=new Map;static _resourceRegistry=new FinalizationRegistry(t=>{const e=p.cache.get(t);(g||te)&&console.debug(`[gltf-progressive] Memory: Resource GC'd
2
- ${t}`),e instanceof WeakRef&&(e.deref()||(p.cache.delete(t),(g||te)&&console.log("[gltf-progressive] ↪ Cache entry deleted (GC)")))});static trackTextureUsage(t){const e=t.uuid,s=this.textureRefCounts.get(e)||0;this.textureRefCounts.set(e,s+1),g==="verbose"&&console.log(`[gltf-progressive] Track texture ${e}, refCount: ${s} → ${s+1}`)}static untrackTextureUsage(t){const e=t.uuid,s=this.textureRefCounts.get(e);if(!s)return(g==="verbose"||te)&&n("[gltf-progressive] Memory: Untrack untracked texture (dispose immediately)",0),t.dispose(),!0;const r=s-1;if(r<=0)return this.textureRefCounts.delete(e),(g||te)&&n("[gltf-progressive] Memory: Dispose texture",r),t.dispose(),!0;return this.textureRefCounts.set(e,r),g==="verbose"&&n("[gltf-progressive] Memory: Untrack texture",r),!1;function n(i,a){let{width:l,height:u}=we(t);const c=l&&u?`${l}x${u}`:"N/A";let f="N/A";l&&u&&(f=`~${(tt(t)/(1024*1024)).toFixed(2)} MB`),console.log(`${i} — ${t.name} ${c} (${f}), refCount: ${s} → ${a}
3
- ${e}`)}}static workers=[];static _workersIndex=0;static async getOrLoadLOD(t,e,s){const r=g=="verbose",n=this.getAssignedLODInformation(t);if(!n)return g&&console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`,t),null;const i=n?.key;let a;if(t.isTexture===!0){const u=t;u.source&&u.source[de]&&(a=u.source[de])}if(a||(a=p.lodInfos.get(i)),!a)g&&console.warn(`Can not load LOD ${e}: no LOD info found for "${i}" ${t.name}`,t.type,p.lodInfos);else{if(e>0){let f=!1;const h=Array.isArray(a.lods);if(h&&e>=a.lods.length?f=!0:h||(f=!0),f){const m=this.lowresCache.get(i);if(m){const b=m.deref();if(b)return b;this.lowresCache.delete(i),g&&console.log(`[gltf-progressive] Lowres cache entry was GC'd: ${i}`)}return null}}const u=Array.isArray(a.lods)?a.lods[e]?.path:a.lods;if(!u)return g&&!a["missing:uri"]&&(a["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,a)),null;const c=Ze(n.url,u);if(c.endsWith(".glb")||c.endsWith(".gltf")){if(!a.guid)return console.warn("missing pointer for glb/gltf texture",a),null;const f=c+"_"+a.guid,h=await this.tryResolveLODCacheEntry(this.cache.get(f),f,c,t,e,r);if(h.found)return h.value;if(s?.isCurrent?.()===!1)return r&&console.log(`Skipping stale LOD ${e} request before queue: ${c}`),null;const m=await this.queue.slot(c);if(s?.isCurrent?.()===!1)return r&&console.log(`Skipping stale LOD ${e} request after queue: ${c}`),null;const b=await this.tryResolveLODCacheEntry(this.cache.get(f),f,c,t,e,r);if(b.found)return b.value;if(!m.use)return g&&console.log(`LOD ${e} was aborted: ${c}`),null;const x=a,L=new Promise(async(w,W)=>{if(ft){const y=await(await ut({})).load(c);if(y.textures.length>0)for(const v of y.textures){let T=v.texture;return p.assignLODInformation(n.url,T,i,e,void 0),t instanceof d.Texture&&(T=this.copySettings(t,T)),T&&(T.guid=x.guid),w(T)}if(y.geometries.length>0){const v=new Array;for(const T of y.geometries){const B=T.geometry;p.assignLODInformation(n.url,B,i,e,T.primitiveIndex),v.push(B)}return w(v)}return w(null)}const M=new Y.GLTFLoader;Me(M),g&&(await new Promise(_=>setTimeout(_,1e3)),r&&console.warn("Start loading (delayed) "+c,x.guid));let O=c;if(x&&Array.isArray(x.lods)){const _=x.lods[e];_.hash&&(O+="?v="+_.hash)}const S=await M.loadAsync(O).catch(_=>(console.error(`Error loading LOD ${e} from ${c}
4
- `,_),w(null)));if(!S)return w(null);const k=S.parser;r&&console.log("Loading finished "+c,x.guid);let R=0;if(S.parser.json.textures){let _=!1;for(const y of S.parser.json.textures){if(y?.extensions){const v=y?.extensions[F];if(v?.guid&&v.guid===x.guid){_=!0;break}}R++}if(_){let y=await k.getDependency("texture",R);return y&&p.assignLODInformation(n.url,y,i,e,void 0),r&&console.log('change "'+t.name+'" → "'+y.name+'"',c,R,y,f),t instanceof d.Texture&&(y=this.copySettings(t,y)),y&&(y.guid=x.guid),w(y)}else g&&console.warn("Could not find texture with guid",x.guid,S.parser.json)}if(R=0,S.parser.json.meshes){let _=!1;for(const y of S.parser.json.meshes){if(y?.extensions){const v=y?.extensions[F];if(v?.guid&&v.guid===x.guid){_=!0;break}}R++}if(_){const y=await k.getDependency("mesh",R);if(r&&console.log(`Loaded Mesh "${y.name}"`,c,R,y,f),y.isMesh===!0){const v=y.geometry;return p.assignLODInformation(n.url,v,i,e,0),w(v)}else{const v=new Array;for(let T=0;T<y.children.length;T++){const B=y.children[T];if(B.isMesh===!0){const ne=B.geometry;p.assignLODInformation(n.url,ne,i,e,T),v.push(ne)}}return w(v)}}else g&&console.warn("Could not find mesh with guid",x.guid,S.parser.json)}return w(null)});this.cache.set(f,L),m.use(L);const D=await L;return D!=null?D instanceof d.Texture?(this.cache.set(f,new WeakRef(D)),p._resourceRegistry.register(D,f)):Array.isArray(D)?this.cache.set(f,Promise.resolve(D)):this.cache.set(f,Promise.resolve(D)):this.cache.set(f,Promise.resolve(null)),D}else if(t instanceof d.Texture){if(s?.isCurrent?.()===!1)return r&&console.log(`Skipping stale texture LOD ${e} request: ${c}`),null;r&&console.log("Load texture from uri: "+c);const h=await new d.TextureLoader().loadAsync(c);return s?.isCurrent?.()===!1?(h?.dispose(),null):(h?(h.guid=a.guid,h.flipY=!1,h.needsUpdate=!0,h.colorSpace=t.colorSpace,r&&console.log(a,h)):g&&console.warn("failed loading",c),h)}}return null}static async tryResolveLODCacheEntry(t,e,s,r,n,i){if(t===void 0)return{found:!1};if(i&&console.log(`LOD ${n} was already loading/loaded: ${e}`),t instanceof WeakRef){const u=t.deref();if(u){let c=u,f=!1;if(c instanceof d.Texture&&r instanceof d.Texture?be(c.image)||Le(c)?c=this.copySettings(r,c):f=!0:c instanceof d.BufferGeometry&&r instanceof d.BufferGeometry&&(c.attributes.position?.array||(f=!0)),!f)return{found:!0,value:c}}return this.cache.delete(e),g&&console.log(`[gltf-progressive] Re-loading GC'd/disposed resource: ${e}`),{found:!1}}let a=await t.catch(u=>(console.error(`Error loading LOD ${n} from ${s}
5
- `,u),null)),l=!1;return a==null||(a instanceof d.Texture&&r instanceof d.Texture?be(a.image)||Le(a)?a=this.copySettings(r,a):(l=!0,this.cache.delete(e)):a instanceof d.BufferGeometry&&r instanceof d.BufferGeometry&&(a.attributes.position?.array||(l=!0,this.cache.delete(e)))),l?{found:!1}:{found:!0,value:a}}static _queue;static get queue(){return this._queue??=new et(_e()?20:50,{debug:g!=!1})}static assignLODInformation(t,e,s,r,n){if(!e)return;e.userData||(e.userData={});const i=new dt(t,s,r,n);e.userData.LODS=i,"source"in e&&typeof e.source=="object"&&(e.source.LODS=i)}static getAssignedLODInformation(t){return t?t.userData?.LODS?t.userData.LODS:"source"in t&&t.source?.LODS?t.source.LODS:null:null}static copySettings(t,e){return e?(g==="verbose"&&console.debug(`Copy texture settings
6
- `,t.uuid,`
7
- `,e.uuid),e=e.clone(),e.offset=t.offset,e.repeat=t.repeat,e.colorSpace=t.colorSpace,e.magFilter=t.magFilter,e.minFilter=t.minFilter,e.wrapS=t.wrapS,e.wrapT=t.wrapT,e.flipY=t.flipY,e.anisotropy=t.anisotropy,e.mipmaps||(e.generateMipmaps=t.generateMipmaps),e):t}}class dt{url;key;level;index;constructor(t,e,s,r){this.url=t,this.key=e,this.level=s,r!=null&&(this.index=r)}}class oe{static addPromise=(t,e,s,r)=>{r.forEach(n=>{n.add(t,e,s)})};ready;get awaitedCount(){return this._addedCount}get resolvedCount(){return this._resolvedCount}get currentlyAwaiting(){return this._awaiting.length}_resolve;_signal;_frame_start;_frames_to_capture;_resolved=!1;_addedCount=0;_resolvedCount=0;_awaiting=[];_maxPromisesPerObject=1;constructor(t,e){const r=Math.max(e.frames??2,2);this._frame_start=e.waitForFirstCapture?void 0:t,this._frames_to_capture=r,this.ready=new Promise(n=>{this._resolve=n}),this.ready.finally(()=>{this._resolved=!0,this._awaiting.length=0}),this._signal=e.signal,this._signal?.addEventListener("abort",()=>{this.resolveNow()}),this._maxPromisesPerObject=Math.max(1,e.maxPromisesPerObject??1)}_currentFrame=0;update(t){this._currentFrame=t,this._frame_start===void 0&&this._addedCount>0&&(this._frame_start=t),(this._signal?.aborted||this._awaiting.length===0&&this._frame_start!==void 0&&t>this._frame_start+this._frames_to_capture)&&this.resolveNow()}_seen=new WeakMap;add(t,e,s){if(this._resolved){g&&console.warn("PromiseGroup: Trying to add a promise to a resolved group, ignoring.");return}if(!(this._frame_start!==void 0&&this._currentFrame>this._frame_start+this._frames_to_capture)){if(this._maxPromisesPerObject>=1)if(this._seen.has(e)){const r=this._seen.get(e);if(r>=this._maxPromisesPerObject){g&&console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");return}this._seen.set(e,r+1)}else this._seen.set(e,1);this._awaiting.push(s),this._addedCount++,s.finally(()=>{this._resolvedCount++,this._awaiting.splice(this._awaiting.indexOf(s),1)})}}resolveNow(){this._resolved||this._resolve?.({awaited_count:this._addedCount,resolved_count:this._resolvedCount,cancelled:this._signal?.aborted??!1})}}const A=V("debugprogressive"),ht=A==="colors",gt=V("noprogressive"),he=Symbol("Needle:LODSManager"),ge=Symbol("Needle:LODState"),U=Symbol("Needle:CurrentLOD"),Oe=d.THREE,C={mesh_lod:-1,texture_lod:-1},pt=new d.Color,Se=[3526751,11065402,15978811,15897394,15749691,11032304,4827122,3332036,16739229,7306743,14053330,3516499,12035359,14703919,3963096,42662,14100029,8344319,4633680,16229681,3120096,12076434,9083434,2060171,15751837,10182117,48121,62932,16704576,15817653,5083278,5592405];function mt(){const o=Oe.Timer||Oe.Clock;return new o}const pe=new d.Box3,z=new d.Box3,Re=new d.Box3,yt=new d.Vector3,xt=new d.Vector3,Lt=new d.Matrix4,G=new d.Vector3,j=new d.Vector3,K=new d.Vector3,H=new d.Vector3;function wt(o,t){const e=o.min,s=o.max,r=(e.x+s.x)*.5,n=(e.y+s.y)*.5;return G.set(r,n,e.z).applyMatrix4(t).z<0}function Fe(o){const{geometry:t,matrixWorld:e,camera:s,projectionScreenMatrix:r,desiredDensity:n,canvasHeight:i=0,currentLevel:a=-1,xrEnabled:l=!1,debugDrawLine:u,warnMissingPrimitiveDensities:c=!1}=o,f=p.getMeshLODExtension(t)?.lods,h=p.getPrimitiveIndex(t),m=o.target??{level:a,primitiveIndex:h,screenCoverage:0,screenspaceVolume:new d.Vector3,centrality:1};m.level=a,m.primitiveIndex=h,m.screenCoverage=0,m.screenspaceVolume.set(0,0,0),m.centrality=1;let b=o.boundingBox??t.boundingBox;if(b||(t.computeBoundingBox(),b=t.boundingBox),!b)return m;if(pe.copy(b).applyMatrix4(e),s.isPerspectiveCamera&&wt(pe,r))return m.level=0,m.screenCoverage=1/0,m.screenspaceVolume.set(1/0,1/0,1/0),m;if(z.copy(pe).applyMatrix4(r),l&&s.isPerspectiveCamera&&s.fov>70){const M=z.min,O=z.max;let S=M.x,k=M.y,R=O.x,_=O.y;const y=2,v=1.5,T=(M.x+O.x)*.5,B=(M.y+O.y)*.5;S=(S-T)*y+T,k=(k-B)*y+B,R=(R-T)*y+T,_=(_-B)*y+B;const ne=S<0&&R>0?0:Math.min(Math.abs(M.x),Math.abs(O.x)),Ee=k<0&&_>0?0:Math.min(Math.abs(M.y),Math.abs(O.y)),ue=Math.max(ne,Ee);m.centrality=(v-ue)*(v-ue)*(v-ue)}const x=z.getSize(yt);x.multiplyScalar(.5),globalThis.screen?.availHeight>0&&i>0&&x.multiplyScalar(i/globalThis.screen.availHeight),s.isPerspectiveCamera&&(x.x*=s.aspect),Re.copy(b).applyMatrix4(e).applyMatrix4(s.matrixWorldInverse);const L=Re.getSize(xt),D=Math.max(x.x,x.y),w=Math.max(L.x,L.y);D!==0&&w!==0&&(x.z=L.z/w*D);const W=Math.max(x.x,x.y,x.z)*m.centrality;if(m.screenCoverage=W,m.screenspaceVolume.copy(x),W<=0)return m;if(u){const M=Lt.copy(r);M.invert(),G.copy(z.min),j.copy(z.max),j.x=G.x,K.copy(z.max),K.y=G.y,H.copy(z.max);const O=(G.z+H.z)*.5;G.z=j.z=K.z=H.z=O,G.applyMatrix4(M),j.applyMatrix4(M),K.applyMatrix4(M),H.applyMatrix4(M),u(G,j,255),u(G,K,255),u(j,H,255),u(K,H,255)}if(f?.length)for(let M=0;M<f.length;M++){const O=f[M],S=O.densities?.[h]||O.density||1e-5;if(h>0&&c&&Ge()&&!O.densities&&!globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"]&&(globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"]=!0,console.warn("[Needle Progressive] Detected usage of mesh without primitive densities. This might cause incorrect LOD level selection: Consider re-optimizing your model by updating your Needle Integration, Needle glTF Pipeline or running optimization again on Needle Cloud.")),S/W<n){m.level=M;break}}return m}let re=class N{static debugDrawLine;static getObjectLODState(t){return t[ge]}static addPlugin(t){q.push(t)}static removePlugin(t){const e=q.indexOf(t);e>=0&&q.splice(e,1)}static getPlugins(){return q}static get(t,e){if(t[he])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[he];const s=new N(t,{engine:"unknown",...e});return t[he]=s,s}renderer;context;projectionScreenMatrix=new d.Matrix4;get plugins(){return q}overrideLodLevel=void 0;targetTriangleDensity=2e5;skinnedMeshAutoUpdateBoundsInterval=30;updateInterval="auto";#e=1;pause=!1;manual=!1;_newPromiseGroups=[];_promiseGroupIds=0;awaitLoading(t){const e=this._promiseGroupIds++,s=new oe(this.#r,{...t});this._newPromiseGroups.push(s);const r=performance.now();return s.ready.finally(()=>{const n=this._newPromiseGroups.indexOf(s);n>=0&&(this._newPromiseGroups.splice(n,1),Ge()&&performance.measure("LODsManager:awaitLoading",{start:r,detail:{id:e,name:t?.name,awaited:s.awaitedCount,resolved:s.resolvedCount}}))}),s.ready}trackLoadingPromise(t,e,s){return oe.addPromise(t,e,s,this._newPromiseGroups),s}_postprocessPromiseGroups(){if(this._newPromiseGroups.length!==0)for(let t=this._newPromiseGroups.length-1;t>=0;t--)this._newPromiseGroups[t].update(this.#r)}_lodchangedlisteners=[];addEventListener(t,e){return t==="changed"?(this._lodchangedlisteners.push(e),()=>{this.removeEventListener(t,e)}):()=>{}}removeEventListener(t,e){let s=!1;if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&(this._lodchangedlisteners.splice(r,1),s=!0)}return s}constructor(t,e){this.renderer=t,this.context={...e}}#t;#r=0;#n=0;#i=0;#s=0;#o=mt();_fpsBuffer=[60,60,60,60,60];enable(){if(this.#t)return;console.debug("[gltf-progressive] Enabling LODsManager for renderer");let t=0;this.#t=this.renderer.render;const e=this;le(this.renderer),this.renderer.render=function(s,r){const n=e.renderer.getRenderTarget();(n==null||"isXRRenderTarget"in n&&n.isXRRenderTarget)&&(t=0,e.#r+=1,e.#o.update?.(),e.#n=Math.max(e.#o.getDelta(),1/1e3),e.#i+=e.#n,e._fpsBuffer.shift(),e._fpsBuffer.push(1/e.#n),e.#s=e._fpsBuffer.reduce((a,l)=>a+l)/e._fpsBuffer.length,A&&e.#r%200===0&&console.log("FPS",Math.round(e.#s),"Interval:",e.#e));const i=t++;e.#t.call(this,s,r),e.onAfterRender(s,r,i)}}disable(){this.#t&&(console.debug("[gltf-progressive] Disabling LODsManager for renderer"),this.renderer.render=this.#t,this.#t=void 0)}update(t,e){this.internalUpdate(t,e)}onAfterRender(t,e,s){if(this.pause)return;const r=this.getRenderList(t,e,s);if(!r)return;const n=r.opaque;let i=!0;if(n.length===1){const a=n[0].material;(a.name==="EffectMaterial"||a.name==="CopyShader")&&(i=!1)}if((e.parent&&e.parent.type==="CubeCamera"||s>=1&&e.type==="OrthographicCamera")&&(i=!1),i){if(gt||(this.updateInterval==="auto"?this.#s<40&&this.#e<10?(this.#e+=1,A&&console.warn("↓ Reducing LOD updates",this.#e,this.#s.toFixed(0))):this.#s>=60&&this.#e>1&&(this.#e-=1,A&&console.warn("↑ Increasing LOD updates",this.#e,this.#s.toFixed(0))):this.#e=this.updateInterval,this.#e>0&&this.#r%this.#e!=0))return;this.internalUpdate(t,e),this._postprocessPromiseGroups()}}internalUpdate(t,e){const s=this.getRenderList(t,e,0);if(!s)return;const r=s.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const n=this.targetTriangleDensity;for(const l of r){if(l.material&&(l.geometry?.type==="BoxGeometry"||l.geometry?.type==="BufferGeometry")&&(l.material.name==="SphericalGaussianBlur"||l.material.name=="BackgroundCubeMaterial"||l.material.name==="CubemapFromEquirect"||l.material.name==="EquirectangularToCubeUV")){A&&(l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(l.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",l,l.material.name,l.material.type)));continue}switch(l.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}const u=l.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,n)}const i=s.transparent;for(const l of i){const u=l.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,n)}const a=s.transmissive;for(const l of a){const u=l.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,n)}}getRenderList(t,e,s){const r=this.renderer;let n=null;if(r.isWebGPURenderer===!0){const i=r._renderLists;if(!i)return null;n=i.get(t,e)}else if(r.isWebGLRenderer===!0){const i=r.renderLists;if(!i)return null;n=i.get(t,s)}return n?{opaque:n.opaque||[],transparent:n.transparent||[],transmissive:n.transmissive||n.transparentDoublePass||[],transparentDoublePass:n.transparentDoublePass||[]}:null}updateLODs(t,e,s,r){s.userData||(s.userData={});let n=s[ge];if(n||(n=new Dt,s[ge]=n),n.frames++<2)return;for(const a of q)a.onBeforeUpdateLOD?.(this.renderer,t,e,s);const i=this.overrideLodLevel!==void 0?this.overrideLodLevel:E;i>=0?(C.mesh_lod=i,C.texture_lod=i):(this.calculateLodLevel(e,s,n,r,C),C.mesh_lod=Math.round(C.mesh_lod),C.texture_lod=Math.round(C.texture_lod)),C.mesh_lod>=0&&this.loadProgressiveMeshes(s,C.mesh_lod),s.material&&C.texture_lod>=0&&this.loadProgressiveTextures(s.material,C.texture_lod,i),g&&s.material&&!s.isGizmo&&qe(s.material),ht&&s.material&&!s.isGizmo&&!s.isBatchedMesh&&We(s.material,C.mesh_lod);for(const a of q)a.onAfterUpdatedLOD?.(this.renderer,t,e,s,C);n.lastLodLevel_Mesh=C.mesh_lod,n.lastLodLevel_Texture=C.texture_lod}loadProgressiveTextures(t,e,s){if(!t)return;if(Array.isArray(t)){for(const i of t)this.loadProgressiveTextures(i,e,s);return}let r=!1;(t[U]===void 0||e<t[U])&&(r=!0);const n=s!==void 0&&s>=0;if(n&&(r=t[U]!=s,e=s),r){t[U]=e;const i=n?{force:!0}:void 0,a=p.assignTextureLOD(t,e,i).then(l=>{this._lodchangedlisteners.forEach(u=>u({type:"texture",level:e,object:t}))});oe.addPromise("texture",t,a,this._newPromiseGroups)}}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let s=t[U]!==e;const r=t["DEBUG:LOD"];if(r!=null&&(s=t[U]!=r,e=r),s){t[U]=e;const n=t.geometry,i=p.assignMeshLOD(t,e).then(a=>(a&&t[U]==e&&n!=t.geometry&&this._lodchangedlisteners.forEach(l=>l({type:"mesh",level:e,object:t})),a));return oe.addPromise("mesh",t,i,this._newPromiseGroups),i}return Promise.resolve(null)}_sphere=new d.Sphere;_tempWorldPosition=new d.Vector3;static skinnedMeshBoundsFrameOffsetCounter=0;static $skinnedMeshBoundsOffset=Symbol("gltf-progressive-skinnedMeshBoundsOffset");calculateLodLevel(t,e,s,r,n){if(!e){n.mesh_lod=-1,n.texture_lod=-1;return}if(!t){n.mesh_lod=-1,n.texture_lod=-1;return}let a=10+1,l=!1;if(A&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=p.getMeshLODExtension(e.geometry)?.lods,c=p.getPrimitiveIndex(e.geometry),f=u&&u.length>0,h=p.getMaterialMinMaxLODsCount(e.material),m=h.min_count!==1/0&&h.min_count>=0&&h.max_count>=0;if(!f&&!m){n.mesh_lod=0,n.texture_lod=0;return}f||(l=!0,a=0);const b=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let x=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const L=e;if(!L.boundingBox)L.computeBoundingBox();else if(this.skinnedMeshAutoUpdateBoundsInterval>0){if(!L[N.$skinnedMeshBoundsOffset]){const w=N.skinnedMeshBoundsFrameOffsetCounter++;L[N.$skinnedMeshBoundsOffset]=w}const D=L[N.$skinnedMeshBoundsOffset];if((s.frames+D)%this.skinnedMeshAutoUpdateBoundsInterval===0){const w=Q(L),W=L.geometry;w&&(L.geometry=w),L.computeBoundingBox(),L.geometry=W}}x=L.boundingBox}if(x){if(e.geometry.attributes.color&&e.geometry.attributes.color.count<100&&e.geometry.boundingSphere){this._sphere.copy(e.geometry.boundingSphere),this._sphere.applyMatrix4(e.matrixWorld);const w=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(w)){n.mesh_lod=0,n.texture_lod=0;return}}const L=Fe({geometry:e.geometry,matrixWorld:e.matrixWorld,camera:t,projectionScreenMatrix:this.projectionScreenMatrix,desiredDensity:r,canvasHeight:b,currentLevel:s.lastLodLevel_Mesh,boundingBox:x,xrEnabled:this.renderer.xr.enabled,debugDrawLine:A?N.debugDrawLine:void 0,warnMissingPrimitiveDensities:!0});if(s.lastCentrality=L.centrality,s.lastScreenCoverage=L.screenCoverage,s.lastScreenspaceVolume.copy(L.screenspaceVolume),L.screenCoverage===1/0){n.mesh_lod=0,n.texture_lod=0;return}L.level>=0&&L.level<a&&(a=L.level,l=!0)}if(l?n.mesh_lod=a:n.mesh_lod=s.lastLodLevel_Mesh,A&&n.mesh_lod!=s.lastLodLevel_Mesh){const D=u?.[n.mesh_lod];D&&console.log(`Mesh LOD changed: ${s.lastLodLevel_Mesh} → ${n.mesh_lod} (density: ${D.densities?.[c].toFixed(0)}) | ${e.name}`)}if(m){const L="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(s.lastLodLevel_Texture<0){if(n.texture_lod=h.max_count-1,A){const D=h.lods[h.max_count-1];A&&console.log(`First Texture LOD ${n.texture_lod} (${D.max_height}px) - ${e.name}`)}}else{const D=s.lastScreenspaceVolume.x+s.lastScreenspaceVolume.y+s.lastScreenspaceVolume.z;let w=s.lastScreenCoverage*4;this.context?.engine==="model-viewer"&&(w*=1.5);const W=this.renderer.getPixelRatio?.()||globalThis.devicePixelRatio||1,O=b/W*w;let S=!1;for(let k=h.lods.length-1;k>=0;k--){const R=h.lods[k];if(!(L&&R.max_height>=2048)&&!(_e()&&R.max_height>4096)&&(R.max_height>O||!S&&k===0)){if(S=!0,n.texture_lod=k,A&&n.texture_lod<s.lastLodLevel_Texture){const _=R.max_height;console.log(`Texture LOD changed: ${s.lastLodLevel_Texture} → ${n.texture_lod} = ${_}px
8
- Screensize: ${O.toFixed(0)}px, Coverage: ${(100*s.lastScreenCoverage).toFixed(2)}%, Volume ${D.toFixed(1)}
9
- ${e.name}`)}break}}}}else n.texture_lod=0}};class Dt{frames=0;lastLodLevel_Mesh=-1;lastLodLevel_Texture=-1;lastScreenCoverage=0;lastScreenspaceVolume=new d.Vector3;lastCentrality=0}function We(o,t){if(!(t<0)){if(Array.isArray(o)){for(const e of o)We(e,t);return}"color"in o&&o.color instanceof d.Color&&(o.color.copy(Ue(t,pt)),o.needsUpdate=!0)}}function Ue(o,t){const e=Math.max(0,Math.min(Se.length-1,Math.floor(o)));return t.setHex(Se[e])}const Ce=Symbol("NEEDLE_mesh_lod"),ie=Symbol("NEEDLE_texture_lod");let me=null;function ze(){const o=Mt();o&&(o.mapURLs(function(t){return Pe(),t}),Pe(),me?.disconnect(),me=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(s=>{s instanceof HTMLElement&&s.tagName.toLowerCase()==="model-viewer"&&Ve(s)})})}),me.observe(document,{childList:!0,subtree:!0}))}function Mt(){if(typeof customElements>"u")return null;const o=customElements.get("model-viewer");return o||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),ze()}),null)}function Pe(){if(typeof document>"u")return;document.querySelectorAll("model-viewer").forEach(t=>{Ve(t)})}const ke=new WeakSet;let vt=0;function Ve(o){if(!o||ke.has(o))return null;ke.add(o),console.debug("[gltf-progressive] found new model-viewer..."+ ++vt+`
10
- `,o.getAttribute("src"));let t=null,e=null,s=null;for(let r=o;r!=null;r=Object.getPrototypeOf(r)){const n=Object.getOwnPropertySymbols(r),i=n.find(u=>u.toString()=="Symbol(renderer)"),a=n.find(u=>u.toString()=="Symbol(scene)"),l=n.find(u=>u.toString()=="Symbol(needsRender)");!t&&i!=null&&(t=o[i].threeRenderer),!e&&a!=null&&(e=o[a]),!s&&l!=null&&(s=o[l])}if(t&&e){let r=function(){if(s){let i=0;const a=setInterval(()=>{if(i++>5){clearInterval(a);return}s?.call(o)},300)}};console.debug("[gltf-progressive] setup model-viewer");const n=re.get(t,{engine:"model-viewer"});return re.addPlugin(new _t),n.enable(),n.addEventListener("changed",()=>{s?.call(o)}),o.addEventListener("model-visibility",i=>{i.detail.visible&&s?.call(o)}),o.addEventListener("load",()=>{r()}),()=>{n.disable()}}return null}class _t{_didWarnAboutMissingUrl=!1;onBeforeUpdateLOD(t,e,s,r){this.tryParseMeshLOD(e,r),this.tryParseTextureLOD(e,r)}getUrl(t){if(!t)return null;let e=t.getAttribute("src");return e||(e=t.src),e||(this._didWarnAboutMissingUrl||console.warn("No url found in modelviewer",t),this._didWarnAboutMissingUrl=!0),e}tryGetCurrentGLTF(t){return t._currentGLTF}tryGetCurrentModelViewer(t){return t.element}tryParseTextureLOD(t,e){if(e[ie]==!0)return;e[ie]=!0;const s=this.tryGetCurrentGLTF(t),r=this.tryGetCurrentModelViewer(t),n=this.getUrl(r);if(n&&s&&e.material){let i=function(l){if(l[ie]==!0)return;l[ie]=!0,l.userData&&(l.userData.LOD=-1);const u=Object.keys(l);for(let c=0;c<u.length;c++){const f=u[c],h=l[f];if(h?.isTexture===!0){const m=h.userData?.associations?.textures;if(m==null)continue;const b=s.parser.json.textures[m];if(!b){console.warn("Texture data not found for texture index "+m);continue}if(b?.extensions?.[F]){const x=b.extensions[F];x&&n&&p.registerTexture(n,h,x.lods.length,m,x)}}}};const a=e.material;if(Array.isArray(a))for(const l of a)i(l);else i(a)}}tryParseMeshLOD(t,e){if(e[Ce]==!0)return;e[Ce]=!0;const s=this.tryGetCurrentModelViewer(t),r=this.getUrl(s);if(!r)return;const n=e.userData?.gltfExtensions?.[F];if(n&&r){const i=e.uuid;p.registerMesh(r,i,e,0,n.lods.length,n)}}}function Tt(...o){let t,e,s,r;switch(o.length){case 2:[s,e]=o,r={};break;case 3:[s,e,r]=o;break;case 4:[t,e,s,r]=o;break;default:throw new Error("Invalid arguments")}le(e),Me(s),ve(s,{progressive:!0,...r?.hints}),s.register(i=>new p(i));const n=re.get(e);return r?.enableLODsManager!==!1&&n.enable(),n}ze();if(!rt){const o={gltfProgressive:{useNeedleProgressive:Tt,LODsManager:re,configureLoader:ve,getRaycastMesh:Q,useRaycastMeshes:ot}};if(!globalThis.Needle)globalThis.Needle=o;else for(const t in o)globalThis.Needle[t]=o[t]}exports.LODsManager=re;exports.NEEDLE_progressive=p;exports.addDracoAndKTX2Loaders=Me;exports.calculateMeshLODLevel=Fe;exports.configureLoader=ve;exports.createLoaders=le;exports.getLODColor=Ue;exports.getRaycastMesh=Q;exports.setDracoDecoderLocation=Ie;exports.setKTX2TranscoderLocation=$e;