@needle-tools/engine 4.8.8 → 4.8.9-next.5e888f7

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 (137) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +50 -45
  3. package/components.needle.json +1 -1
  4. package/dist/gltf-progressive-DWiyqrwB.umd.cjs +8 -0
  5. package/dist/gltf-progressive-DhE1A6hX.min.js +8 -0
  6. package/dist/{gltf-progressive-BcHT3Nyo.js → gltf-progressive-egsMzRdv.js} +384 -369
  7. package/dist/{needle-engine.bundle-CK8rTkFm.umd.cjs → needle-engine.bundle-B8QgMEWj.umd.cjs} +145 -145
  8. package/dist/{needle-engine.bundle-C071tpzX.js → needle-engine.bundle-CBk4h0tH.js} +8352 -8106
  9. package/dist/{needle-engine.bundle--H5L0liy.min.js → needle-engine.bundle-CF7LvCm4.min.js} +148 -148
  10. package/dist/needle-engine.d.ts +7 -0
  11. package/dist/needle-engine.js +305 -301
  12. package/dist/needle-engine.min.js +1 -1
  13. package/dist/needle-engine.umd.cjs +1 -1
  14. package/dist/{postprocessing-Ywv5oKkX.min.js → postprocessing-B_FzkwDz.min.js} +1 -1
  15. package/dist/{postprocessing-ORx-0eCx.js → postprocessing-DP1U_BpT.js} +2 -2
  16. package/dist/{postprocessing-CVb_x9YY.umd.cjs → postprocessing-DTX5VXrj.umd.cjs} +1 -1
  17. package/dist/{three-Dceyffus.umd.cjs → three-BK56xWDs.umd.cjs} +24 -24
  18. package/dist/{three-BRSLmpyi.js → three-CsHK73Zc.js} +1 -0
  19. package/dist/{three-CsmWHVn7.min.js → three-TNFQHSFa.min.js} +25 -25
  20. package/dist/{three-examples-BX_Sktc9.min.js → three-examples-Bph291U2.min.js} +1 -1
  21. package/dist/{three-examples-CNexix3E.js → three-examples-BvMpKSun.js} +1 -1
  22. package/dist/{three-examples-DWxXVnws.umd.cjs → three-examples-C9WfZu-X.umd.cjs} +1 -1
  23. package/dist/{three-mesh-ui-gqAXlGNB.js → three-mesh-ui-CN6aRT7i.js} +1 -1
  24. package/dist/{three-mesh-ui-Cdh2iW8b.umd.cjs → three-mesh-ui-DnxkZWNA.umd.cjs} +1 -1
  25. package/dist/{three-mesh-ui-Bwy12Qvg.min.js → three-mesh-ui-n_qS2BM-.min.js} +1 -1
  26. package/dist/{vendor-xfQ8tKF3.umd.cjs → vendor-8le8g4MS.umd.cjs} +1 -1
  27. package/dist/{vendor-Z4SPrTcP.js → vendor-Msb9AgYE.js} +1 -1
  28. package/dist/{vendor-C43vobGc.min.js → vendor-yDFiCnCw.min.js} +1 -1
  29. package/lib/engine/codegen/register_types.js +4 -0
  30. package/lib/engine/codegen/register_types.js.map +1 -1
  31. package/lib/engine/engine_addressables.js +2 -0
  32. package/lib/engine/engine_addressables.js.map +1 -1
  33. package/lib/engine/engine_animation.js +4 -4
  34. package/lib/engine/engine_animation.js.map +1 -1
  35. package/lib/engine/engine_assetdatabase.js +6 -6
  36. package/lib/engine/engine_assetdatabase.js.map +1 -1
  37. package/lib/engine/engine_camera.d.ts +15 -2
  38. package/lib/engine/engine_camera.js +9 -2
  39. package/lib/engine/engine_camera.js.map +1 -1
  40. package/lib/engine/engine_context.d.ts +8 -2
  41. package/lib/engine/engine_context.js +21 -3
  42. package/lib/engine/engine_context.js.map +1 -1
  43. package/lib/engine/engine_create_objects.d.ts +3 -3
  44. package/lib/engine/engine_create_objects.js +5 -4
  45. package/lib/engine/engine_create_objects.js.map +1 -1
  46. package/lib/engine/engine_gameobject.js +2 -2
  47. package/lib/engine/engine_gameobject.js.map +1 -1
  48. package/lib/engine/engine_gltf_builtin_components.js +11 -11
  49. package/lib/engine/engine_gltf_builtin_components.js.map +1 -1
  50. package/lib/engine/engine_loaders.callbacks.d.ts +1 -0
  51. package/lib/engine/engine_loaders.callbacks.js +1 -0
  52. package/lib/engine/engine_loaders.callbacks.js.map +1 -1
  53. package/lib/engine/extensions/NEEDLE_lighting_settings.js +5 -2
  54. package/lib/engine/extensions/NEEDLE_lighting_settings.js.map +1 -1
  55. package/lib/engine/extensions/NEEDLE_lightmaps.js +1 -1
  56. package/lib/engine/extensions/NEEDLE_lightmaps.js.map +1 -1
  57. package/lib/engine/js-extensions/Object3D.d.ts +1 -1
  58. package/lib/engine/js-extensions/Vector.d.ts +5 -0
  59. package/lib/engine/js-extensions/Vector.js.map +1 -1
  60. package/lib/engine/js-extensions/index.d.ts +2 -1
  61. package/lib/engine/js-extensions/index.js +1 -1
  62. package/lib/engine/js-extensions/index.js.map +1 -1
  63. package/lib/engine/webcomponents/needle-engine.d.ts +2 -2
  64. package/lib/engine/webcomponents/needle-engine.js +11 -18
  65. package/lib/engine/webcomponents/needle-engine.js.map +1 -1
  66. package/lib/engine-components/Camera.d.ts +2 -0
  67. package/lib/engine-components/Camera.js +5 -1
  68. package/lib/engine-components/Camera.js.map +1 -1
  69. package/lib/engine-components/ContactShadows.d.ts +12 -2
  70. package/lib/engine-components/ContactShadows.js +24 -4
  71. package/lib/engine-components/ContactShadows.js.map +1 -1
  72. package/lib/engine-components/DropListener.d.ts +4 -3
  73. package/lib/engine-components/DropListener.js +4 -3
  74. package/lib/engine-components/DropListener.js.map +1 -1
  75. package/lib/engine-components/NestedGltf.d.ts +9 -4
  76. package/lib/engine-components/NestedGltf.js +32 -26
  77. package/lib/engine-components/NestedGltf.js.map +1 -1
  78. package/lib/engine-components/OrbitControls.d.ts +29 -6
  79. package/lib/engine-components/OrbitControls.js +45 -9
  80. package/lib/engine-components/OrbitControls.js.map +1 -1
  81. package/lib/engine-components/Renderer.js +2 -1
  82. package/lib/engine-components/Renderer.js.map +1 -1
  83. package/lib/engine-components/Skybox.js +8 -9
  84. package/lib/engine-components/Skybox.js.map +1 -1
  85. package/lib/engine-components/api.d.ts +2 -0
  86. package/lib/engine-components/api.js +1 -0
  87. package/lib/engine-components/api.js.map +1 -1
  88. package/lib/engine-components/codegen/components.d.ts +3 -0
  89. package/lib/engine-components/codegen/components.js +3 -0
  90. package/lib/engine-components/codegen/components.js.map +1 -1
  91. package/lib/engine-components/export/usdz/extensions/behavior/Behaviour.d.ts +1 -1
  92. package/lib/engine-components/splines/Spline.d.ts +58 -0
  93. package/lib/engine-components/splines/Spline.js +270 -0
  94. package/lib/engine-components/splines/Spline.js.map +1 -0
  95. package/lib/engine-components/splines/SplineUtils.d.ts +12 -0
  96. package/lib/engine-components/splines/SplineUtils.js +33 -0
  97. package/lib/engine-components/splines/SplineUtils.js.map +1 -0
  98. package/lib/engine-components/splines/SplineWalker.d.ts +47 -0
  99. package/lib/engine-components/splines/SplineWalker.js +113 -0
  100. package/lib/engine-components/splines/SplineWalker.js.map +1 -0
  101. package/lib/engine-components/splines/index.d.ts +3 -0
  102. package/lib/engine-components/splines/index.js +4 -0
  103. package/lib/engine-components/splines/index.js.map +1 -0
  104. package/package.json +4 -4
  105. package/plugins/common/files.js +6 -3
  106. package/plugins/vite/alias.js +3 -2
  107. package/plugins/vite/editor-connection.js +4 -4
  108. package/src/engine/codegen/register_types.ts +4 -0
  109. package/src/engine/engine_addressables.ts +2 -0
  110. package/src/engine/engine_animation.ts +4 -4
  111. package/src/engine/engine_assetdatabase.ts +7 -7
  112. package/src/engine/engine_camera.ts +15 -3
  113. package/src/engine/engine_context.ts +22 -4
  114. package/src/engine/engine_create_objects.ts +8 -7
  115. package/src/engine/engine_gameobject.ts +2 -2
  116. package/src/engine/engine_gltf_builtin_components.ts +12 -11
  117. package/src/engine/engine_loaders.callbacks.ts +1 -0
  118. package/src/engine/extensions/NEEDLE_lighting_settings.ts +5 -2
  119. package/src/engine/extensions/NEEDLE_lightmaps.ts +1 -1
  120. package/src/engine/js-extensions/Vector.ts +6 -0
  121. package/src/engine/js-extensions/index.ts +3 -2
  122. package/src/engine/webcomponents/needle-engine.ts +10 -17
  123. package/src/engine-components/Camera.ts +7 -1
  124. package/src/engine-components/ContactShadows.ts +27 -6
  125. package/src/engine-components/DropListener.ts +4 -3
  126. package/src/engine-components/NestedGltf.ts +33 -24
  127. package/src/engine-components/OrbitControls.ts +67 -21
  128. package/src/engine-components/Renderer.ts +2 -1
  129. package/src/engine-components/Skybox.ts +9 -10
  130. package/src/engine-components/api.ts +3 -1
  131. package/src/engine-components/codegen/components.ts +3 -0
  132. package/src/engine-components/splines/Spline.ts +284 -0
  133. package/src/engine-components/splines/SplineUtils.ts +32 -0
  134. package/src/engine-components/splines/SplineWalker.ts +106 -0
  135. package/src/engine-components/splines/index.ts +3 -0
  136. package/dist/gltf-progressive-CH3Q4H06.umd.cjs +0 -8
  137. package/dist/gltf-progressive-DR6HqF_h.min.js +0 -8
@@ -0,0 +1,106 @@
1
+
2
+ import { Object3D } from "three"
3
+
4
+ import { Mathf } from "../../engine/engine_math.js";
5
+ import { serializeable } from "../../engine/engine_serialization_decorator.js";
6
+ import { Behaviour } from "../Component.js";
7
+ import { SplineContainer } from "./Spline.js";
8
+
9
+ /**
10
+ * Moves an object along a spline. Use this with a SplineContainer component.
11
+ */
12
+ export class SplineWalker extends Behaviour {
13
+
14
+ /**
15
+ * The spline to use/walk along. Add a SplineContainer component to an object and assign it here.
16
+ */
17
+ @serializeable(SplineContainer)
18
+ spline: SplineContainer | null = null;
19
+
20
+ /** The object to move along the spline. If object is undefined then the spline walker will use the gameObject the component has been added to
21
+ * @default undefined
22
+ */
23
+ @serializeable(Object3D)
24
+ object?: Object3D | null = undefined;
25
+
26
+ /** The object to look at while moving along the spline
27
+ * @default null
28
+ */
29
+ @serializeable(Object3D)
30
+ lookAt: Object3D | null = null;
31
+
32
+ /**
33
+ * When clamp is set to true, the position01 value will be clamped between 0 and 1 and the object will not loop the spline.
34
+ * @default false
35
+ */
36
+ @serializeable()
37
+ clamp: boolean = false;
38
+
39
+ /** The current position on the spline. The value ranges from 0 (start of the spline curve) to 1 (end of the spline curve)
40
+ * @default 0
41
+ */
42
+ // @type float
43
+ @serializeable()
44
+ get position01(): number {
45
+ return this._position01;
46
+ }
47
+ set position01(v: number) {
48
+ this._position01 = v;
49
+ this.updateFromPosition();
50
+ }
51
+
52
+ /** Resets the position to 0 */
53
+ reset() {
54
+ this._position01 = 0;
55
+ }
56
+
57
+ /**
58
+ * If true the SplineWalker will automatically move along the spline
59
+ * @default true
60
+ */
61
+ @serializeable()
62
+ autoRun: boolean = true;
63
+
64
+ /**
65
+ * The duration in seconds it takes to complete the whole spline when autoWalk is enabled.
66
+ * @default 10
67
+ */
68
+ @serializeable()
69
+ duration: number = 10;
70
+
71
+
72
+ // #region internal
73
+
74
+ private _position01: number = 0;
75
+
76
+ /** @internal */
77
+ start() {
78
+ if(this.object === undefined) this.object = this.gameObject;
79
+ this.updateFromPosition();
80
+ }
81
+
82
+ update() {
83
+ if (this.autoRun) {
84
+ this._position01 += this.context.time.deltaTime / this.duration;
85
+ this.updateFromPosition();
86
+ }
87
+ }
88
+
89
+
90
+ private updateFromPosition() {
91
+ if (!this.spline || !this.spline.curve) return;
92
+ if (!this.object) return;
93
+
94
+ if (this.clamp) this._position01 = Mathf.clamp01(this._position01);
95
+ else this._position01 = this._position01 % 1;
96
+
97
+ const t = this._position01 >= 1 ? 1 : this._position01 % 1;
98
+ const pt = this.spline.getPointAt(t);
99
+ this.object.worldPosition = pt;
100
+ if (!this.lookAt) {
101
+ const tan = this.spline.getTangentAt(t);
102
+ this.object.lookAt(pt.add(tan));
103
+ }
104
+ else this.object.lookAt(this.lookAt.worldPosition);
105
+ }
106
+ }
@@ -0,0 +1,3 @@
1
+ export { SplineContainer } from "./Spline.js";
2
+ export { SplineUtils } from "./SplineUtils.js";
3
+ export { SplineWalker } from "./SplineWalker.js";
@@ -1,8 +0,0 @@
1
- "use strict";const d=require("./three-Dceyffus.umd.cjs"),q=require("./three-examples-DWxXVnws.umd.cjs");var ae=typeof document<"u"?document.currentScript:null;const be="3.3.2";globalThis.GLTF_PROGRESSIVE_VERSION=be;console.debug(`[gltf-progressive] version ${be}`);let k="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",N="https://cdn.needle.tools/static/three/0.179.1/basis2/";const Be=k,$e=N,ve=new URL(k+"draco_decoder.js");ve.searchParams.append("range","true");fetch(ve,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(i=>{console.debug(`Failed to fetch remote Draco decoder from ${k} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),k===Be&&Oe("./include/draco/"),N===$e&&Se("./include/ktx2/")}).finally(()=>{Te()});const Ge=()=>({dracoDecoderPath:k,ktx2TranscoderPath:N});function Oe(i){k=i,A&&A[ge]!=k?(console.debug("Updating Draco decoder path to "+i),A[ge]=k,A.setDecoderPath(k),A.preload()):console.debug("Setting Draco decoder path to "+i)}function Se(i){N=i,R&&R.transcoderPath!=N?(console.debug("Updating KTX2 transcoder path to "+i),R.setTranscoderPath(N),R.init()):console.debug("Setting KTX2 transcoder path to "+i)}function ne(i){return Te(),i?R.detectSupport(i):i!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:A,ktx2Loader:R,meshoptDecoder:se}}function ye(i){i.dracoLoader||i.setDRACOLoader(A),i.ktx2Loader||i.setKTX2Loader(R),i.meshoptDecoder||i.setMeshoptDecoder(se)}const ge=Symbol("dracoDecoderPath");let A,se,R;function Te(){A||(A=new q.DRACOLoader,A[ge]=k,A.setDecoderPath(k),A.setDecoderConfig({type:"js"}),A.preload()),R||(R=new q.KTX2Loader,R.setTranscoderPath(N),R.init()),se||(se=q.MeshoptDecoder)}const pe=new WeakMap;function xe(i,t){let e=pe.get(i);e?e=Object.assign(e,t):e=t,pe.set(i,e)}const Fe=q.GLTFLoader.prototype.load;function Ue(...i){const t=pe.get(this);let e=i[0];const r=new URL(e,window.location.href);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 i[0]=e,Fe?.call(this,...i)}q.GLTFLoader.prototype.load=Ue;V("debugprogressive");function V(i){if(typeof window>"u")return!1;const e=new URL(window.location.href).searchParams.get(i);return e==null||e==="0"||e==="false"?!1:e===""?!0:e}function Ee(i,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||i===void 0)return t;const e=i.lastIndexOf("/");if(e>=0){const r=i.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}let j;function Pe(){return j!==void 0||(j=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),V("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",j)),j}function Le(){if(typeof window>"u")return!1;const i=new URL(window.location.href),t=i.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(i.hostname);return i.hostname==="127.0.0.1"||t}class We{maxConcurrent;_running=new Map;_queue=[];debug=!1;constructor(t=100,e={}){this.maxConcurrent=t,this.debug=e.debug??!1,window.requestAnimationFrame(this.tick)}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:n}=this._queue.shift();n({use:s=>this.add(r,s)})}}}const ze=typeof window>"u"&&typeof document>"u",me=Symbol("needle:raycast-mesh");function X(i){return i?.[me]instanceof d.BufferGeometry?i[me]:null}function Ne(i,t){if((i.type==="Mesh"||i.type==="SkinnedMesh")&&!X(i)){const r=qe(t);r.userData={isRaycastMesh:!0},i[me]=r}}function Ve(i=!0){if(i){if(Y)return;const t=Y=d.Mesh.prototype.raycast;d.Mesh.prototype.raycast=function(e,r){const n=this,s=X(n);let o;s&&n.isMesh&&(o=n.geometry,n.geometry=s),t.call(this,e,r),o&&(n.geometry=o)}}else{if(!Y)return;d.Mesh.prototype.raycast=Y,Y=null}}let Y=null;function qe(i){const t=new d.BufferGeometry;for(const e in i.attributes)t.setAttribute(e,i.getAttribute(e));return t.setIndex(i.getIndex()),t}const E=new Array,p=V("debugprogressive");let re,z=-1;if(p){let t=function(){z+=1,z>=i&&(z=-1),console.log(`Toggle LOD level [${z}]`)},i=6;window.addEventListener("keyup",e=>{e.key==="p"&&t(),e.key==="w"&&(re=!re,console.log(`Toggle wireframe [${re}]`));const r=parseInt(e.key);!isNaN(r)&&r>=0&&(z=r,console.log(`Set LOD level to [${z}]`))})}function Ae(i){if(p)if(Array.isArray(i))for(const t of i)Ae(t);else i&&"wireframe"in i&&(i.wireframe=re===!0)}const H=new Array;let Xe=0;const Ke=Pe()?2:10;function je(i){if(H.length<Ke){const r=H.length;p&&console.warn(`[Worker] Creating new worker #${r}`);const n=we.createWorker(i||{});return H.push(n),n}const t=Xe++%H.length;return H[t]}class we{worker;static async createWorker(t){const e=new Worker(new URL("/loader.worker-CiTwpNPW.js",typeof document>"u"?require("url").pathToFileURL(__filename).href:ae&&ae.tagName.toUpperCase()==="SCRIPT"&&ae.src||new URL("gltf-progressive-CH3Q4H06.umd.cjs",document.baseURI).href),{type:"module"});return new we(e,t)}_running=[];_webglRenderer=null;async load(t,e){const r=Ge();let n=e?.renderer;n||(this._webglRenderer??=(async()=>{const{WebGLRenderer:u}=await Promise.resolve().then(()=>require("./three-Dceyffus.umd.cjs")).then(c=>c.THREE);return new u})(),n=await this._webglRenderer);const l=ne(n).ktx2Loader.workerConfig;t instanceof URL?t=t.toString():t.startsWith("file:")?t=URL.createObjectURL(new Blob([t])):!t.startsWith("blob:")&&!t.startsWith("http:")&&!t.startsWith("https:")&&(t=new URL(t,window.location.href).toString());const a={type:"load",url:t,dracoDecoderPath:r.dracoDecoderPath,ktx2TranscoderPath:r.ktx2TranscoderPath,ktx2LoaderConfig:l};return this._debug&&console.debug("[Worker] Sending load request",a),this.worker.postMessage(a),new Promise(u=>{this._running.push({url:t.toString(),resolve:u})})}_debug=!1;constructor(t,e){this.worker=t,this._debug=e.debug??!1,t.onmessage=r=>{const n=r.data;switch(this._debug&&console.log("[Worker] EVENT",n),n.type){case"loaded-gltf":for(const s of this._running)if(s.url===n.result.url){Ye(n.result),s.resolve(n.result);const o=s.url;o.startsWith("blob:")&&URL.revokeObjectURL(o)}}},t.onerror=r=>{console.error("[Worker] Error in gltf-progressive worker:",r)},t.postMessage({type:"init"})}}function Ye(i){for(const t of i.geometries){const e=t.geometry,r=new d.BufferGeometry;if(r.name=e.name||"",e.index){const n=e.index;r.setIndex(le(n))}for(const n in e.attributes){const s=e.attributes[n],o=le(s);r.setAttribute(n,o)}if(e.morphAttributes)for(const n in e.morphAttributes){const o=e.morphAttributes[n].map(l=>le(l));r.morphAttributes[n]=o}if(r.morphTargetsRelative=e.morphTargetsRelative??!1,r.boundingBox=new d.Box3,r.boundingBox.min=new d.Vector3(e.boundingBox?.min.x,e.boundingBox?.min.y,e.boundingBox?.min.z),r.boundingBox.max=new d.Vector3(e.boundingBox?.max.x,e.boundingBox?.max.y,e.boundingBox?.max.z),r.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 n of e.groups)r.addGroup(n.start,n.count,n.materialIndex);e.userData&&(r.userData=e.userData),t.geometry=r}for(const t of i.textures){const e=t.texture;let r=null;if(e.isCompressedTexture){const n=e.mipmaps,s=e.image?.width||e.source?.data?.width||-1,o=e.image?.height||e.source?.data?.height||-1;r=new d.CompressedTexture(n,s,o,e.format,e.type,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.anisotropy,e.colorSpace)}else r=new d.Texture(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 d.Matrix3(...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 i}function le(i){let t=i;if("isInterleavedBufferAttribute"in i&&i.isInterleavedBufferAttribute){const e=i.data,r=e.array,n=new d.InterleavedBuffer(r,e.stride);t=new d.InterleavedBufferAttribute(n,i.itemSize,r.byteOffset,i.normalized),t.offset=i.offset}else"isBufferAttribute"in i&&i.isBufferAttribute&&(t=new d.BufferAttribute(i.array,i.itemSize,i.normalized),t.usage=i.usage,t.gpuType=i.gpuType,t.updateRanges=i.updateRanges);return t}const He=V("gltf-progressive-worker"),Qe=V("gltf-progressive-reduce-mipmaps"),ue=Symbol("needle-progressive-texture"),F="NEEDLE_progressive";class x{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 r=this,n="LODS:minmax",s=t[n];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const l of t)this.getMaterialMinMaxLODsCount(l,e);return t[n]=e,e}if(p==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const l=t;for(const a of Object.keys(l.uniforms)){const u=l.uniforms[a].value;u?.isTexture===!0&&o(u,e)}}else if(t.isMaterial)for(const l of Object.keys(t)){const a=t[l];a?.isTexture===!0&&o(a,e)}else p&&console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);return t[n]=e,e;function o(l,a){const u=r.getAssignedLODInformation(l);if(u){const c=r.lodInfos.get(u.key);if(c&&c.lods){a.min_count=Math.min(a.min_count,c.lods.length),a.max_count=Math.max(a.max_count,c.lods.length);for(let m=0;m<c.lods.length;m++){const _=c.lods[m];_.width&&(a.lods[m]=a.lods[m]||{min_height:1/0,max_height:0},a.lods[m].min_height=Math.min(a.lods[m].min_height,_.height),a.lods[m].max_height=Math.max(a.lods[m].max_height,_.height))}}}}}static hasLODLevelAvailable(t,e){if(Array.isArray(t)){for(const s of t)if(this.hasLODLevelAvailable(s,e))return!0;return!1}if(t.isMaterial===!0){for(const s of Object.keys(t)){const o=t[s];if(o&&o.isTexture&&this.hasLODLevelAvailable(o,e))return!0}return!1}else if(t.isGroup===!0){for(const s of t.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let r,n;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&r?.userData?.LODS){const s=r.userData.LODS;if(n=this.lodInfos.get(s.key),e===void 0)return n!=null;if(n)return Array.isArray(n.lods)?e<n.lods.length:e===0}return!1}static assignMeshLOD(t,e){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 s of E)s.onBeforeGetLODMesh?.(t,e);return t["LOD:requested level"]=e,x.getOrLoadLOD(r,e).then(s=>{if(Array.isArray(s)){const o=n.index||0;s=s[o]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],s&&r!=s&&(s?.isBufferGeometry?t.geometry=s:p&&console.error("Invalid LOD geometry",s))),s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else p&&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){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const n=new Array;for(const s of r.material){const o=this.assignTextureLOD(s,e);n.push(o)}return Promise.all(n).then(s=>{const o=new Array;for(const l of s)Array.isArray(l)&&o.push(...l);return o})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,n=[],s=new Array;if(r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const o=r;for(const l of Object.keys(o.uniforms)){const a=o.uniforms[l].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,l).then(c=>(c&&o.uniforms[l].value!=c&&(o.uniforms[l].value=c,o.uniformsNeedUpdate=!0),c));n.push(u),s.push(l)}}}else for(const o of Object.keys(r)){const l=r[o];if(l?.isTexture===!0){const a=this.assignTextureLODForSlot(l,e,r,o);n.push(a),s.push(o)}}return Promise.all(n).then(o=>{const l=new Array;for(let a=0;a<o.length;a++){const u=o[a],c=s[a];u&&u.isTexture===!0?l.push({material:r,slot:c,texture:u,level:e}):l.push({material:r,slot:c,texture:null,level:e})}return l})}if(t instanceof d.Texture||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):x.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."),null;if(s?.isTexture===!0){if(s!=t&&r&&n){const o=r[n];if(o&&!p){const l=this.getAssignedLODInformation(o);if(l&&l?.level<e)return p==="verbose"&&console.warn("Assigned texture level is already higher: ",l.level,e,r,o,s),null}if(Qe&&s.mipmaps){const l=s.mipmaps.length;s.mipmaps.length=Math.min(s.mipmaps.length,3),l!==s.mipmaps.length&&p&&console.debug(`Reduced mipmap count from ${l} to ${s.mipmaps.length} for ${s.uuid}: ${s.image?.width}x${s.image?.height}.`)}r[n]=s}return s}else p=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}parser;url;constructor(t){const e=t.options.path;p&&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(r=>(this._isLoadingMesh=!1,r&&x.registerMesh(this.url,e.guid,r,e.lods?.length,0,e),r))):null};afterRoot(t){return p&&console.log("AFTER",this.url,t),this.parser.json.textures?.forEach((e,r)=>{if(e?.extensions){const n=e?.extensions[F];if(n){if(!n.lods){p&&console.warn("Texture has no LODs",n);return}let s=!1;for(const o of this.parser.associations.keys())o.isTexture===!0&&this.parser.associations.get(o)?.textures===r&&(s=!0,x.registerTexture(this.url,o,n.lods?.length,r,n));s||this.parser.getDependency("texture",r).then(o=>{o&&x.registerTexture(this.url,o,n.lods?.length,r,n)})}}}),this.parser.json.meshes?.forEach((e,r)=>{if(e?.extensions){const n=e?.extensions[F];if(n&&n.lods){for(const s of this.parser.associations.keys())if(s.isMesh){const o=this.parser.associations.get(s);o?.meshes===r&&x.registerMesh(this.url,n.guid,s,n.lods.length,o.primitives,n)}}}}),null}static registerTexture=(t,e,r,n,s)=>{if(!e){p&&console.error("gltf-progressive: Called register texture without texture");return}if(p){const l=e.image?.width||e.source?.data?.width||0,a=e.image?.height||e.source?.data?.height||0;console.log(`> Progressive: register texture[${n}] "${e.name||e.uuid}", Current: ${l}x${a}, Max: ${s.lods[0]?.width}x${s.lods[0]?.height}, uuid: ${e.uuid}`,s,e)}e.source&&(e.source[ue]=s);const o=s.guid;x.assignLODInformation(t,e,o,r,n),x.lodInfos.set(o,s),x.lowresCache.set(o,e)};static registerMesh=(t,e,r,n,s,o)=>{const l=r.geometry;if(!l){p&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),p&&console.log("> Progressive: register mesh "+r.name,{index:s,uuid:r.uuid},o,r),x.assignLODInformation(t,l,e,n,s),x.lodInfos.set(e,o);let a=x.lowresCache.get(e);a?a.push(r.geometry):a=[r.geometry],x.lowresCache.set(e,a),n>0&&!X(r)&&Ne(r,l);for(const u of E)u.onRegisteredNewMesh?.(r,o)};static lodInfos=new Map;static previouslyLoaded=new Map;static lowresCache=new Map;static workers=[];static _workersIndex=0;static async getOrLoadLOD(t,e){const r=p=="verbose",n=this.getAssignedLODInformation(t);if(!n)return p&&console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`,t),null;const s=n?.key;let o;if(t.isTexture===!0){const a=t;a.source&&a.source[ue]&&(o=a.source[ue])}if(o||(o=x.lodInfos.get(s)),o){if(e>0){let c=!1;const m=Array.isArray(o.lods);if(m&&e>=o.lods.length?c=!0:m||(c=!0),c)return this.lowresCache.get(s)}const a=Array.isArray(o.lods)?o.lods[e]?.path:o.lods;if(!a)return p&&!o["missing:uri"]&&(o["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,o)),null;const u=Ee(n.url,a);if(u.endsWith(".glb")||u.endsWith(".gltf")){if(!o.guid)return console.warn("missing pointer for glb/gltf texture",o),null;const c=u+"_"+o.guid,m=await this.queue.slot(u),_=this.previouslyLoaded.get(c);if(_!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${c}`);let f=await _.catch(S=>(console.error(`Error loading LOD ${e} from ${u}
2
- `,S),null)),w=!1;if(f==null||(f instanceof d.Texture&&t instanceof d.Texture?f.image?.data||f.source?.data?f=this.copySettings(t,f):(w=!0,this.previouslyLoaded.delete(c)):f instanceof d.BufferGeometry&&t instanceof d.BufferGeometry&&(f.attributes.position?.array||(w=!0,this.previouslyLoaded.delete(c)))),!w)return f}if(!m.use)return p&&console.log(`LOD ${e} was aborted: ${u}`),null;const M=o,C=new Promise(async(f,w)=>{if(He){const y=await(await je({})).load(u);if(y.textures.length>0)for(const h of y.textures){let g=h.texture;return x.assignLODInformation(n.url,g,s,e,void 0),t instanceof d.Texture&&(g=this.copySettings(t,g)),g&&(g.guid=M.guid),f(g)}if(y.geometries.length>0){const h=new Array;for(const g of y.geometries){const b=g.geometry;x.assignLODInformation(n.url,b,s,e,g.primitiveIndex),h.push(b)}return f(h)}return f(null)}const S=new q.GLTFLoader;ye(S),p&&(await new Promise(L=>setTimeout(L,1e3)),r&&console.warn("Start loading (delayed) "+u,M.guid));let B=u;if(M&&Array.isArray(M.lods)){const L=M.lods[e];L.hash&&(B+="?v="+L.hash)}const D=await S.loadAsync(B).catch(L=>(console.error(`Error loading LOD ${e} from ${u}
3
- `,L),f(null)));if(!D)return f(null);const W=D.parser;r&&console.log("Loading finished "+u,M.guid);let T=0;if(D.parser.json.textures){let L=!1;for(const y of D.parser.json.textures){if(y?.extensions){const h=y?.extensions[F];if(h?.guid&&h.guid===M.guid){L=!0;break}}T++}if(L){let y=await W.getDependency("texture",T);return y&&x.assignLODInformation(n.url,y,s,e,void 0),r&&console.log('change "'+t.name+'" → "'+y.name+'"',u,T,y,c),t instanceof d.Texture&&(y=this.copySettings(t,y)),y&&(y.guid=M.guid),f(y)}else p&&console.warn("Could not find texture with guid",M.guid,D.parser.json)}if(T=0,D.parser.json.meshes){let L=!1;for(const y of D.parser.json.meshes){if(y?.extensions){const h=y?.extensions[F];if(h?.guid&&h.guid===M.guid){L=!0;break}}T++}if(L){const y=await W.getDependency("mesh",T);if(r&&console.log(`Loaded Mesh "${y.name}"`,u,T,y,c),y.isMesh===!0){const h=y.geometry;return x.assignLODInformation(n.url,h,s,e,0),f(h)}else{const h=new Array;for(let g=0;g<y.children.length;g++){const b=y.children[g];if(b.isMesh===!0){const O=b.geometry;x.assignLODInformation(n.url,O,s,e,g),h.push(O)}}return f(h)}}else p&&console.warn("Could not find mesh with guid",M.guid,D.parser.json)}return f(null)});return this.previouslyLoaded.set(c,C),m.use(C),await C}else if(t instanceof d.Texture){r&&console.log("Load texture from uri: "+u);const m=await new d.TextureLoader().loadAsync(u);return m?(m.guid=o.guid,m.flipY=!1,m.needsUpdate=!0,m.colorSpace=t.colorSpace,r&&console.log(o,m)):p&&console.warn("failed loading",u),m}}else p&&console.warn(`Can not load LOD ${e}: no LOD info found for "${s}" ${t.name}`,t.type);return null}static maxConcurrent=50;static queue=new We(x.maxConcurrent,{debug:p!=!1});static assignLODInformation(t,e,r,n,s){if(!e)return;e.userData||(e.userData={});const o=new Je(t,r,n,s);e.userData.LODS=o,"source"in e&&typeof e.source=="object"&&(e.source.LODS=o)}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?(p==="verbose"&&console.debug(`Copy texture settings
4
- `,t.uuid,`
5
- `,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 Je{url;key;level;index;constructor(t,e,r,n){this.url=t,this.key=e,this.level=r,n!=null&&(this.index=n)}}class de{static addPromise=(t,e,r,n)=>{n.forEach(s=>{s.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 n=Math.max(e.frames??2,2);this._frame_start=e.waitForFirstCapture?void 0:t,this._frames_to_capture=n,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){p&&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)){let n=this._seen.get(e);if(n>=this._maxPromisesPerObject){p&&console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");return}this._seen.set(e,n+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 I=V("debugprogressive"),Ze=V("noprogressive"),ce=Symbol("Needle:LODSManager"),fe=Symbol("Needle:LODState"),U=Symbol("Needle:CurrentLOD"),P={mesh_lod:-1,texture_lod:-1};let Q=class v{static debugDrawLine;static getObjectLODState(t){return t[fe]}static addPlugin(t){E.push(t)}static removePlugin(t){const e=E.indexOf(t);e>=0&&E.splice(e,1)}static get(t,e){if(t[ce])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[ce];const r=new v(t,{engine:"unknown",...e});return t[ce]=r,r}renderer;context;projectionScreenMatrix=new d.Matrix4;get plugins(){return E}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 de(this.#s,{...t});this._newPromiseGroups.push(r);const n=performance.now();return r.ready.finally(()=>{const s=this._newPromiseGroups.indexOf(r);s>=0&&(this._newPromiseGroups.splice(s,1),Le()&&performance.measure("LODsManager:awaitLoading",{start:n,detail:{id:e,name:t?.name,awaited:r.awaitedCount,resolved:r.resolvedCount}}))}),r.ready}_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){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}constructor(t,e){this.renderer=t,this.context={...e}}#t;#o=new d.Clock;#s=0;#n=0;#i=0;#r=0;_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;ne(this.renderer),this.renderer.render=function(r,n){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,e.#s+=1,e.#n=e.#o.getDelta(),e.#i+=e.#n,e._fpsBuffer.shift(),e._fpsBuffer.push(1/e.#n),e.#r=e._fpsBuffer.reduce((l,a)=>l+a)/e._fpsBuffer.length,I&&e.#s%200===0&&console.log("FPS",Math.round(e.#r),"Interval:",e.#e));const o=t++;e.#t.call(this,r,n),e.onAfterRender(r,n,o)}}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.renderer.renderLists.get(t,0).opaque;let o=!0;if(s.length===1){const l=s[0].material;(l.name==="EffectMaterial"||l.name==="CopyShader")&&(o=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(o=!1),o){if(Ze||(this.updateInterval==="auto"?this.#r<40&&this.#e<10?(this.#e+=1,I&&console.warn("↓ Reducing LOD updates",this.#e,this.#r.toFixed(0))):this.#r>=60&&this.#e>1&&(this.#e-=1,I&&console.warn("↑ 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.renderer.renderLists.get(t,0),n=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const s=this.targetTriangleDensity;for(const a of n){if(a.material&&(a.geometry?.type==="BoxGeometry"||a.geometry?.type==="BufferGeometry")&&(a.material.name==="SphericalGaussianBlur"||a.material.name=="BackgroundCubeMaterial"||a.material.name==="CubemapFromEquirect"||a.material.name==="EquirectangularToCubeUV")){I&&(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",a,a.material.name,a.material.type)));continue}switch(a.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(I==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const c=Math.random()*16777215,m=new d.MeshStandardMaterial({color:c});a.object.material=m}const u=a.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,s)}const o=r.transparent;for(const a of o){const u=a.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,s)}const l=r.transmissive;for(const a of l){const u=a.object;(u instanceof d.Mesh||u.isMesh)&&this.updateLODs(t,e,u,s)}}updateLODs(t,e,r,n){r.userData||(r.userData={});let s=r[fe];if(s||(s=new et,r[fe]=s),s.frames++<2)return;for(const l of E)l.onBeforeUpdateLOD?.(this.renderer,t,e,r);const o=this.overrideLodLevel!==void 0?this.overrideLodLevel:z;o>=0?(P.mesh_lod=o,P.texture_lod=o):(this.calculateLodLevel(e,r,s,n,P),P.mesh_lod=Math.round(P.mesh_lod),P.texture_lod=Math.round(P.texture_lod)),P.mesh_lod>=0&&this.loadProgressiveMeshes(r,P.mesh_lod),r.material&&P.texture_lod>=0&&this.loadProgressiveTextures(r.material,P.texture_lod,o),p&&r.material&&!r.isGizmo&&Ae(r.material);for(const l of E)l.onAfterUpdatedLOD?.(this.renderer,t,e,r,P);s.lastLodLevel_Mesh=P.mesh_lod,s.lastLodLevel_Texture=P.texture_lod}loadProgressiveTextures(t,e,r){if(!t)return;if(Array.isArray(t)){for(const s of t)this.loadProgressiveTextures(s,e);return}let n=!1;if((t[U]===void 0||e<t[U])&&(n=!0),r!==void 0&&r>=0&&(n=t[U]!=r,e=r),n){t[U]=e;const s=x.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(l=>l({type:"texture",level:e,object:t}))});de.addPromise("texture",t,s,this._newPromiseGroups)}}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let r=t[U]!==e;const n=t["DEBUG:LOD"];if(n!=null&&(r=t[U]!=n,e=n),r){t[U]=e;const s=t.geometry,o=x.assignMeshLOD(t,e).then(l=>(l&&t[U]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(a=>a({type:"mesh",level:e,object:t})),l));return de.addPromise("mesh",t,o,this._newPromiseGroups),o}return Promise.resolve(null)}_sphere=new d.Sphere;_tempBox=new d.Box3;_tempBox2=new d.Box3;tempMatrix=new d.Matrix4;_tempWorldPosition=new d.Vector3;_tempBoxSize=new d.Vector3;_tempBox2Size=new d.Vector3;static corner0=new d.Vector3;static corner1=new d.Vector3;static corner2=new d.Vector3;static corner3=new d.Vector3;static _tempPtInside=new d.Vector3;static isInside(t,e){const r=t.min,n=t.max,s=(r.x+n.x)*.5,o=(r.y+n.y)*.5;return this._tempPtInside.set(s,o,r.z).applyMatrix4(e).z<0}static skinnedMeshBoundsFrameOffsetCounter=0;static $skinnedMeshBoundsOffset=Symbol("gltf-progressive-skinnedMeshBoundsOffset");calculateLodLevel(t,e,r,n,s){if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let l=10+1,a=!1;if(I&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const u=x.getMeshLODExtension(e.geometry)?.lods,c=x.getPrimitiveIndex(e.geometry),m=u&&u.length>0,_=x.getMaterialMinMaxLODsCount(e.material),M=_.min_count!==1/0&&_.min_count>=0&&_.max_count>=0;if(!m&&!M){s.mesh_lod=0,s.texture_lod=0;return}m||(a=!0,l=0);const C=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let G=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const f=e;if(!f.boundingBox)f.computeBoundingBox();else if(this.skinnedMeshAutoUpdateBoundsInterval>0){if(!f[v.$skinnedMeshBoundsOffset]){const S=v.skinnedMeshBoundsFrameOffsetCounter++;f[v.$skinnedMeshBoundsOffset]=S}const w=f[v.$skinnedMeshBoundsOffset];if((r.frames+w)%this.skinnedMeshAutoUpdateBoundsInterval===0){const S=X(f),B=f.geometry;S&&(f.geometry=S),f.computeBoundingBox(),f.geometry=B}}G=f.boundingBox}if(G){const f=t;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 h=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(h)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(G),this._tempBox.applyMatrix4(e.matrixWorld),f.isPerspectiveCamera&&v.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&f.isPerspectiveCamera&&f.fov>70){const h=this._tempBox.min,g=this._tempBox.max;let b=h.x,O=h.y,$=g.x,K=g.y;const J=2,oe=1.5,Z=(h.x+g.x)*.5,ee=(h.y+g.y)*.5;b=(b-Z)*J+Z,O=(O-ee)*J+ee,$=($-Z)*J+Z,K=(K-ee)*J+ee;const ke=b<0&&$>0?0:Math.min(Math.abs(h.x),Math.abs(g.x)),Re=O<0&&K>0?0:Math.min(Math.abs(h.y),Math.abs(g.y)),ie=Math.max(ke,Re);r.lastCentrality=(oe-ie)*(oe-ie)*(oe-ie)}else r.lastCentrality=1;const w=this._tempBox.getSize(this._tempBoxSize);w.multiplyScalar(.5),screen.availHeight>0&&C>0&&w.multiplyScalar(C/screen.availHeight),t.isPerspectiveCamera?w.x*=t.aspect:t.isOrthographicCamera;const S=t.matrixWorldInverse,B=this._tempBox2;B.copy(G),B.applyMatrix4(e.matrixWorld),B.applyMatrix4(S);const D=B.getSize(this._tempBox2Size),W=Math.max(D.x,D.y);if(Math.max(w.x,w.y)!=0&&W!=0&&(w.z=D.z/Math.max(D.x,D.y)*Math.max(w.x,w.y)),r.lastScreenCoverage=Math.max(w.x,w.y,w.z),r.lastScreenspaceVolume.copy(w),r.lastScreenCoverage*=r.lastCentrality,I&&v.debugDrawLine){const h=this.tempMatrix.copy(this.projectionScreenMatrix);h.invert();const g=v.corner0,b=v.corner1,O=v.corner2,$=v.corner3;g.copy(this._tempBox.min),b.copy(this._tempBox.max),b.x=g.x,O.copy(this._tempBox.max),O.y=g.y,$.copy(this._tempBox.max);const K=(g.z+$.z)*.5;g.z=b.z=O.z=$.z=K,g.applyMatrix4(h),b.applyMatrix4(h),O.applyMatrix4(h),$.applyMatrix4(h),v.debugDrawLine(g,b,255),v.debugDrawLine(g,O,255),v.debugDrawLine(b,$,255),v.debugDrawLine(O,$,255)}let L=999;if(u&&r.lastScreenCoverage>0)for(let h=0;h<u.length;h++){const g=u[h],O=(g.densities?.[c]||g.density||1e-5)/r.lastScreenCoverage;if(c>0&&Le()&&!g.densities&&!globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"]&&(window["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.")),O<n){L=h;break}}L<l&&(l=L,a=!0)}if(a?s.mesh_lod=l:s.mesh_lod=r.lastLodLevel_Mesh,I&&s.mesh_lod!=r.lastLodLevel_Mesh){const w=u?.[s.mesh_lod];w&&console.debug(`Mesh LOD changed: ${r.lastLodLevel_Mesh} → ${s.mesh_lod} (density: ${w.densities?.[c].toFixed(0)}) | ${e.name}`)}if(M){const f="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=_.max_count-1,I){const w=_.lods[_.max_count-1];I&&console.log(`First Texture LOD ${s.texture_lod} (${w.max_height}px) - ${e.name}`)}}else{const w=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let S=r.lastScreenCoverage*4;this.context?.engine==="model-viewer"&&(S*=1.5);const D=C/window.devicePixelRatio*S;let W=!1;for(let T=_.lods.length-1;T>=0;T--){const L=_.lods[T];if(!(f&&L.max_height>=2048)&&!(Pe()&&L.max_height>4096)&&(L.max_height>D||!W&&T===0)){if(W=!0,s.texture_lod=T,I&&s.texture_lod<r.lastLodLevel_Texture){const y=L.max_height;console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} → ${s.texture_lod} = ${y}px
6
- Screensize: ${D.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${w.toFixed(1)}
7
- ${e.name}`)}break}}}}else s.texture_lod=0}};class et{frames=0;lastLodLevel_Mesh=-1;lastLodLevel_Texture=-1;lastScreenCoverage=0;lastScreenspaceVolume=new d.Vector3;lastCentrality=0}const _e=Symbol("NEEDLE_mesh_lod"),te=Symbol("NEEDLE_texture_lod");let he=null;function Ce(){const i=tt();i&&(i.mapURLs(function(t){return Me(),t}),Me(),he?.disconnect(),he=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(r=>{r instanceof HTMLElement&&r.tagName.toLowerCase()==="model-viewer"&&Ie(r)})})}),he.observe(document,{childList:!0,subtree:!0}))}function tt(){if(typeof customElements>"u")return null;const i=customElements.get("model-viewer");return i||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Ce()}),null)}function Me(){if(typeof document>"u")return;document.querySelectorAll("model-viewer").forEach(t=>{Ie(t)})}const De=new WeakSet;let rt=0;function Ie(i){if(!i||De.has(i))return null;De.add(i),console.debug("[gltf-progressive] found new model-viewer..."+ ++rt+`
8
- `,i.getAttribute("src"));let t=null,e=null,r=null;for(let n=i;n!=null;n=Object.getPrototypeOf(n)){const s=Object.getOwnPropertySymbols(n),o=s.find(u=>u.toString()=="Symbol(renderer)"),l=s.find(u=>u.toString()=="Symbol(scene)"),a=s.find(u=>u.toString()=="Symbol(needsRender)");!t&&o!=null&&(t=i[o].threeRenderer),!e&&l!=null&&(e=i[l]),!r&&a!=null&&(r=i[a])}if(t&&e){let s=function(){if(r){let o=0,l=setInterval(()=>{if(o++>5){clearInterval(l);return}r?.call(i)},300)}};console.debug("[gltf-progressive] setup model-viewer");const n=Q.get(t,{engine:"model-viewer"});return Q.addPlugin(new st),n.enable(),n.addEventListener("changed",()=>{r?.call(i)}),i.addEventListener("model-visibility",o=>{o.detail.visible&&r?.call(i)}),i.addEventListener("load",()=>{s()}),()=>{n.disable()}}return null}class st{_didWarnAboutMissingUrl=!1;onBeforeUpdateLOD(t,e,r,n){this.tryParseMeshLOD(e,n),this.tryParseTextureLOD(e,n)}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[te]==!0)return;e[te]=!0;const r=this.tryGetCurrentGLTF(t),n=this.tryGetCurrentModelViewer(t),s=this.getUrl(n);if(s&&r&&e.material){let l=function(a){if(a[te]==!0)return;a[te]=!0,a.userData&&(a.userData.LOD=-1);const u=Object.keys(a);for(let c=0;c<u.length;c++){const m=u[c],_=a[m];if(_?.isTexture===!0){const M=_.userData?.associations?.textures;if(M==null)continue;const C=r.parser.json.textures[M];if(!C){console.warn("Texture data not found for texture index "+M);continue}if(C?.extensions?.[F]){const G=C.extensions[F];G&&s&&x.registerTexture(s,_,G.lods.length,M,G)}}}};const o=e.material;if(Array.isArray(o))for(const a of o)l(a);else l(o)}}tryParseMeshLOD(t,e){if(e[_e]==!0)return;e[_e]=!0;const r=this.tryGetCurrentModelViewer(t),n=this.getUrl(r);if(!n)return;const s=e.userData?.gltfExtensions?.[F];if(s&&n){const o=e.uuid;x.registerMesh(n,o,e,0,s.lods.length,s)}}}function nt(...i){let t,e,r,n;switch(i.length){case 2:[r,e]=i,n={};break;case 3:[r,e,n]=i;break;case 4:[t,e,r,n]=i;break;default:throw new Error("Invalid arguments")}ne(e),ye(r),xe(r,{progressive:!0,...n?.hints}),r.register(o=>new x(o));const s=Q.get(e);return n?.enableLODsManager!==!1&&s.enable(),s}Ce();if(!ze){const i={gltfProgressive:{useNeedleProgressive:nt,LODsManager:Q,configureLoader:xe,getRaycastMesh:X,useRaycastMeshes:Ve}};if(!globalThis.Needle)globalThis.Needle=i;else for(const t in i)globalThis.Needle[t]=i[t]}exports.LODsManager=Q;exports.NEEDLE_progressive=x;exports.addDracoAndKTX2Loaders=ye;exports.configureLoader=xe;exports.createLoaders=ne;exports.getRaycastMesh=X;exports.setDracoDecoderLocation=Oe;exports.setKTX2TranscoderLocation=Se;
@@ -1,8 +0,0 @@
1
- import{BufferGeometry as V,Mesh as j,Box3 as ie,Vector3 as I,Sphere as ve,CompressedTexture as Re,Texture as N,Matrix3 as Ge,InterleavedBuffer as je,InterleavedBufferAttribute as Ne,BufferAttribute as Ue,TextureLoader as Fe,Matrix4 as Le,Clock as We,MeshStandardMaterial as ze}from"./three-CsmWHVn7.min.js";import{DRACOLoader as qe,KTX2Loader as Ve,MeshoptDecoder as Xe,GLTFLoader as ae}from"./three-examples-BX_Sktc9.min.js";const _e="3.3.2";globalThis.GLTF_PROGRESSIVE_VERSION=_e,console.debug(`[gltf-progressive] version ${_e}`);let k="https://www.gstatic.com/draco/versioned/decoders/1.5.7/",U="https://cdn.needle.tools/static/three/0.179.1/basis2/";const Ke=k,He=U,be=new URL(k+"draco_decoder.js");be.searchParams.append("range","true"),fetch(be,{method:"GET",headers:{Range:"bytes=0-1"}}).catch(i=>{console.debug(`Failed to fetch remote Draco decoder from ${k} (offline: ${typeof navigator<"u"?navigator.onLine:"unknown"})`),k===Ke&&De("./include/draco/"),U===He&&Me("./include/ktx2/")}).finally(()=>{Oe()});const Ye=()=>({dracoDecoderPath:k,ktx2TranscoderPath:U});function De(i){k=i,P&&P[ue]!=k?(console.debug("Updating Draco decoder path to "+i),P[ue]=k,P.setDecoderPath(k),P.preload()):console.debug("Setting Draco decoder path to "+i)}function Me(i){U=i,C&&C.transcoderPath!=U?(console.debug("Updating KTX2 transcoder path to "+i),C.setTranscoderPath(U),C.init()):console.debug("Setting KTX2 transcoder path to "+i)}function Z(i){return Oe(),i?C.detectSupport(i):i!==null&&console.warn("No renderer provided to detect ktx2 support - loading KTX2 textures might fail"),{dracoLoader:P,ktx2Loader:C,meshoptDecoder:ee}}function le(i){i.dracoLoader||i.setDRACOLoader(P),i.ktx2Loader||i.setKTX2Loader(C),i.meshoptDecoder||i.setMeshoptDecoder(ee)}const ue=Symbol("dracoDecoderPath");let P,ee,C;function Oe(){P||(P=new qe,P[ue]=k,P.setDecoderPath(k),P.setDecoderConfig({type:"js"}),P.preload()),C||(C=new Ve,C.setTranscoderPath(U),C.init()),ee||(ee=Xe)}const de=new WeakMap;function ce(i,t){let e=de.get(i);e?e=Object.assign(e,t):e=t,de.set(i,e)}const Qe=ae.prototype.load;function Je(...i){const t=de.get(this);let e=i[0];const r=new URL(e,window.location.href);if(r.hostname.endsWith("needle.tools")){const n=t?.progressive!==void 0?t.progressive:!0,s=t?.usecase?t.usecase:"default";n?this.requestHeader.Accept=`*/*;progressive=allowed;usecase=${s}`:this.requestHeader.Accept=`*/*;usecase=${s}`,e=r.toString()}return i[0]=e,Qe?.call(this,...i)}ae.prototype.load=Je,F("debugprogressive");function F(i){if(typeof window>"u")return!1;const t=new URL(window.location.href).searchParams.get(i);return t==null||t==="0"||t==="false"?!1:t===""?!0:t}function Ze(i,t){if(t===void 0||t.startsWith("./")||t.startsWith("http")||i===void 0)return t;const e=i.lastIndexOf("/");if(e>=0){const r=i.substring(0,e+1);for(;r.endsWith("/")&&t.startsWith("/");)t=t.substring(1);return r+t}return t}let te;function Se(){return te!==void 0||(te=/iPhone|iPad|iPod|Android|IEMobile/i.test(navigator.userAgent),F("debugprogressive")&&console.log("[glTF Progressive]: isMobileDevice",te)),te}function Pe(){if(typeof window>"u")return!1;const i=new URL(window.location.href),t=i.hostname==="localhost"||/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/.test(i.hostname);return i.hostname==="127.0.0.1"||t}class et{maxConcurrent;_running=new Map;_queue=[];debug=!1;constructor(t=100,e={}){this.maxConcurrent=t,this.debug=e.debug??!1,window.requestAnimationFrame(this.tick)}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:n}=this._queue.shift();n({use:s=>this.add(r,s)})}}}const tt=typeof window>"u"&&typeof document>"u",he=Symbol("needle:raycast-mesh");function z(i){return i?.[he]instanceof V?i[he]:null}function rt(i,t){if((i.type==="Mesh"||i.type==="SkinnedMesh")&&!z(i)){const e=nt(t);e.userData={isRaycastMesh:!0},i[he]=e}}function st(i=!0){if(i){if(X)return;const t=X=j.prototype.raycast;j.prototype.raycast=function(e,r){const n=this,s=z(n);let o;s&&n.isMesh&&(o=n.geometry,n.geometry=s),t.call(this,e,r),o&&(n.geometry=o)}}else{if(!X)return;j.prototype.raycast=X,X=null}}let X=null;function nt(i){const t=new V;for(const e in i.attributes)t.setAttribute(e,i.getAttribute(e));return t.setIndex(i.getIndex()),t}const R=new Array,h=F("debugprogressive");let re,W=-1;if(h){let i=function(){W+=1,W>=t&&(W=-1),console.log(`Toggle LOD level [${W}]`)},t=6;window.addEventListener("keyup",e=>{e.key==="p"&&i(),e.key==="w"&&(re=!re,console.log(`Toggle wireframe [${re}]`));const r=parseInt(e.key);!isNaN(r)&&r>=0&&(W=r,console.log(`Set LOD level to [${W}]`))})}function Te(i){if(h)if(Array.isArray(i))for(const t of i)Te(t);else i&&"wireframe"in i&&(i.wireframe=re===!0)}const K=new Array;let ot=0;const it=Se()?2:10;function at(i){if(K.length<it){const e=K.length;h&&console.warn(`[Worker] Creating new worker #${e}`);const r=ye.createWorker(i||{});return K.push(r),r}const t=ot++%K.length;return K[t]}class ye{worker;static async createWorker(t){const e=new Worker(URL.createObjectURL(new Blob([`import '${new URL("./loader.worker-CiTwpNPW.js",import.meta.url).toString()}';`],{type:"text/javascript"})),{type:"module"});return new ye(e,t)}_running=[];_webglRenderer=null;async load(t,e){const r=Ye();let n=e?.renderer;n||(this._webglRenderer??=(async()=>{const{WebGLRenderer:l}=await import("./three-CsmWHVn7.min.js").then(a=>a.THREE);return new l})(),n=await this._webglRenderer);const s=Z(n).ktx2Loader.workerConfig;t instanceof URL?t=t.toString():t.startsWith("file:")?t=URL.createObjectURL(new Blob([t])):!t.startsWith("blob:")&&!t.startsWith("http:")&&!t.startsWith("https:")&&(t=new URL(t,window.location.href).toString());const o={type:"load",url:t,dracoDecoderPath:r.dracoDecoderPath,ktx2TranscoderPath:r.ktx2TranscoderPath,ktx2LoaderConfig:s};return this._debug&&console.debug("[Worker] Sending load request",o),this.worker.postMessage(o),new Promise(l=>{this._running.push({url:t.toString(),resolve:l})})}_debug=!1;constructor(t,e){this.worker=t,this._debug=e.debug??!1,t.onmessage=r=>{const n=r.data;switch(this._debug&&console.log("[Worker] EVENT",n),n.type){case"loaded-gltf":for(const s of this._running)if(s.url===n.result.url){lt(n.result),s.resolve(n.result);const o=s.url;o.startsWith("blob:")&&URL.revokeObjectURL(o)}}},t.onerror=r=>{console.error("[Worker] Error in gltf-progressive worker:",r)},t.postMessage({type:"init"})}}function lt(i){for(const t of i.geometries){const e=t.geometry,r=new V;if(r.name=e.name||"",e.index){const n=e.index;r.setIndex(ge(n))}for(const n in e.attributes){const s=e.attributes[n],o=ge(s);r.setAttribute(n,o)}if(e.morphAttributes)for(const n in e.morphAttributes){const s=e.morphAttributes[n].map(o=>ge(o));r.morphAttributes[n]=s}if(r.morphTargetsRelative=e.morphTargetsRelative??!1,r.boundingBox=new ie,r.boundingBox.min=new I(e.boundingBox?.min.x,e.boundingBox?.min.y,e.boundingBox?.min.z),r.boundingBox.max=new I(e.boundingBox?.max.x,e.boundingBox?.max.y,e.boundingBox?.max.z),r.boundingSphere=new ve(new I(e.boundingSphere?.center.x,e.boundingSphere?.center.y,e.boundingSphere?.center.z),e.boundingSphere?.radius),e.groups)for(const n of e.groups)r.addGroup(n.start,n.count,n.materialIndex);e.userData&&(r.userData=e.userData),t.geometry=r}for(const t of i.textures){const e=t.texture;let r=null;if(e.isCompressedTexture){const n=e.mipmaps,s=e.image?.width||e.source?.data?.width||-1,o=e.image?.height||e.source?.data?.height||-1;r=new Re(n,s,o,e.format,e.type,e.mapping,e.wrapS,e.wrapT,e.magFilter,e.minFilter,e.anisotropy,e.colorSpace)}else r=new N(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 Ge(...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 i}function ge(i){let t=i;if("isInterleavedBufferAttribute"in i&&i.isInterleavedBufferAttribute){const e=i.data,r=e.array,n=new je(r,e.stride);t=new Ne(n,i.itemSize,r.byteOffset,i.normalized),t.offset=i.offset}else"isBufferAttribute"in i&&i.isBufferAttribute&&(t=new Ue(i.array,i.itemSize,i.normalized),t.usage=i.usage,t.gpuType=i.gpuType,t.updateRanges=i.updateRanges);return t}const ut=F("gltf-progressive-worker"),dt=F("gltf-progressive-reduce-mipmaps"),fe=Symbol("needle-progressive-texture"),$="NEEDLE_progressive";class g{get name(){return $}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,n="LODS:minmax",s=t[n];if(s!=null)return s;if(e||(e={min_count:1/0,max_count:0,lods:[]}),Array.isArray(t)){for(const l of t)this.getMaterialMinMaxLODsCount(l,e);return t[n]=e,e}if(h==="verbose"&&console.log("getMaterialMinMaxLODsCount",t),t.type==="ShaderMaterial"||t.type==="RawShaderMaterial"){const l=t;for(const a of Object.keys(l.uniforms)){const u=l.uniforms[a].value;u?.isTexture===!0&&o(u,e)}}else if(t.isMaterial)for(const l of Object.keys(t)){const a=t[l];a?.isTexture===!0&&o(a,e)}else h&&console.warn(`[getMaterialMinMaxLODsCount] Unsupported material type: ${t.type}`);return t[n]=e,e;function o(l,a){const u=r.getAssignedLODInformation(l);if(u){const f=r.lodInfos.get(u.key);if(f&&f.lods){a.min_count=Math.min(a.min_count,f.lods.length),a.max_count=Math.max(a.max_count,f.lods.length);for(let w=0;w<f.lods.length;w++){const v=f.lods[w];v.width&&(a.lods[w]=a.lods[w]||{min_height:1/0,max_height:0},a.lods[w].min_height=Math.min(a.lods[w].min_height,v.height),a.lods[w].max_height=Math.max(a.lods[w].max_height,v.height))}}}}}static hasLODLevelAvailable(t,e){if(Array.isArray(t)){for(const s of t)if(this.hasLODLevelAvailable(s,e))return!0;return!1}if(t.isMaterial===!0){for(const s of Object.keys(t)){const o=t[s];if(o&&o.isTexture&&this.hasLODLevelAvailable(o,e))return!0}return!1}else if(t.isGroup===!0){for(const s of t.children)if(s.isMesh===!0&&this.hasLODLevelAvailable(s,e))return!0}let r,n;if(t.isMesh?r=t.geometry:(t.isBufferGeometry||t.isTexture)&&(r=t),r&&r?.userData?.LODS){const s=r.userData.LODS;if(n=this.lodInfos.get(s.key),e===void 0)return n!=null;if(n)return Array.isArray(n.lods)?e<n.lods.length:e===0}return!1}static assignMeshLOD(t,e){if(!t)return Promise.resolve(null);if(t instanceof j||t.isMesh===!0){const r=t.geometry,n=this.getAssignedLODInformation(r);if(!n)return Promise.resolve(null);for(const s of R)s.onBeforeGetLODMesh?.(t,e);return t["LOD:requested level"]=e,g.getOrLoadLOD(r,e).then(s=>{if(Array.isArray(s)){const o=n.index||0;s=s[o]}return t["LOD:requested level"]===e&&(delete t["LOD:requested level"],s&&r!=s&&(s?.isBufferGeometry?t.geometry=s:h&&console.error("Invalid LOD geometry",s))),s}).catch(s=>(console.error("Error loading mesh LOD",t,s),null))}else h&&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){if(!t)return Promise.resolve(null);if(t.isMesh===!0){const r=t;if(Array.isArray(r.material)){const n=new Array;for(const s of r.material){const o=this.assignTextureLOD(s,e);n.push(o)}return Promise.all(n).then(s=>{const o=new Array;for(const l of s)Array.isArray(l)&&o.push(...l);return o})}else return this.assignTextureLOD(r.material,e)}if(t.isMaterial===!0){const r=t,n=[],s=new Array;if(r.uniforms&&(r.isRawShaderMaterial||r.isShaderMaterial===!0)){const o=r;for(const l of Object.keys(o.uniforms)){const a=o.uniforms[l].value;if(a?.isTexture===!0){const u=this.assignTextureLODForSlot(a,e,r,l).then(f=>(f&&o.uniforms[l].value!=f&&(o.uniforms[l].value=f,o.uniformsNeedUpdate=!0),f));n.push(u),s.push(l)}}}else for(const o of Object.keys(r)){const l=r[o];if(l?.isTexture===!0){const a=this.assignTextureLODForSlot(l,e,r,o);n.push(a),s.push(o)}}return Promise.all(n).then(o=>{const l=new Array;for(let a=0;a<o.length;a++){const u=o[a],f=s[a];u&&u.isTexture===!0?l.push({material:r,slot:f,texture:u,level:e}):l.push({material:r,slot:f,texture:null,level:e})}return l})}if(t instanceof N||t.isTexture===!0){const r=t;return this.assignTextureLODForSlot(r,e,null,null)}return Promise.resolve(null)}static assignTextureLODForSlot(t,e,r,n){return t?.isTexture!==!0?Promise.resolve(null):n==="glyphMap"?Promise.resolve(t):g.getOrLoadLOD(t,e).then(s=>{if(Array.isArray(s))return console.warn("Progressive: Got an array of textures for a texture slot, this should not happen..."),null;if(s?.isTexture===!0){if(s!=t&&r&&n){const o=r[n];if(o&&!h){const l=this.getAssignedLODInformation(o);if(l&&l?.level<e)return h==="verbose"&&console.warn("Assigned texture level is already higher: ",l.level,e,r,o,s),null}if(dt&&s.mipmaps){const l=s.mipmaps.length;s.mipmaps.length=Math.min(s.mipmaps.length,3),l!==s.mipmaps.length&&h&&console.debug(`Reduced mipmap count from ${l} to ${s.mipmaps.length} for ${s.uuid}: ${s.image?.width}x${s.image?.height}.`)}r[n]=s}return s}else h=="verbose"&&console.warn("No LOD found for",t,e);return null}).catch(s=>(console.error("Error loading LOD",t,s),null))}parser;url;constructor(t){const e=t.options.path;h&&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?.[$];return e?(this._isLoadingMesh=!0,this.parser.getDependency("mesh",t).then(r=>(this._isLoadingMesh=!1,r&&g.registerMesh(this.url,e.guid,r,e.lods?.length,0,e),r))):null};afterRoot(t){return h&&console.log("AFTER",this.url,t),this.parser.json.textures?.forEach((e,r)=>{if(e?.extensions){const n=e?.extensions[$];if(n){if(!n.lods){h&&console.warn("Texture has no LODs",n);return}let s=!1;for(const o of this.parser.associations.keys())o.isTexture===!0&&this.parser.associations.get(o)?.textures===r&&(s=!0,g.registerTexture(this.url,o,n.lods?.length,r,n));s||this.parser.getDependency("texture",r).then(o=>{o&&g.registerTexture(this.url,o,n.lods?.length,r,n)})}}}),this.parser.json.meshes?.forEach((e,r)=>{if(e?.extensions){const n=e?.extensions[$];if(n&&n.lods){for(const s of this.parser.associations.keys())if(s.isMesh){const o=this.parser.associations.get(s);o?.meshes===r&&g.registerMesh(this.url,n.guid,s,n.lods.length,o.primitives,n)}}}}),null}static registerTexture=(t,e,r,n,s)=>{if(!e){h&&console.error("gltf-progressive: Called register texture without texture");return}if(h){const l=e.image?.width||e.source?.data?.width||0,a=e.image?.height||e.source?.data?.height||0;console.log(`> Progressive: register texture[${n}] "${e.name||e.uuid}", Current: ${l}x${a}, Max: ${s.lods[0]?.width}x${s.lods[0]?.height}, uuid: ${e.uuid}`,s,e)}e.source&&(e.source[fe]=s);const o=s.guid;g.assignLODInformation(t,e,o,r,n),g.lodInfos.set(o,s),g.lowresCache.set(o,e)};static registerMesh=(t,e,r,n,s,o)=>{const l=r.geometry;if(!l){h&&console.warn("gltf-progressive: Register mesh without geometry");return}l.userData||(l.userData={}),h&&console.log("> Progressive: register mesh "+r.name,{index:s,uuid:r.uuid},o,r),g.assignLODInformation(t,l,e,n,s),g.lodInfos.set(e,o);let a=g.lowresCache.get(e);a?a.push(r.geometry):a=[r.geometry],g.lowresCache.set(e,a),n>0&&!z(r)&&rt(r,l);for(const u of R)u.onRegisteredNewMesh?.(r,o)};static lodInfos=new Map;static previouslyLoaded=new Map;static lowresCache=new Map;static workers=[];static _workersIndex=0;static async getOrLoadLOD(t,e){const r=h=="verbose",n=this.getAssignedLODInformation(t);if(!n)return h&&console.warn(`[gltf-progressive] No LOD information found: ${t.name}, uuid: ${t.uuid}, type: ${t.type}`,t),null;const s=n?.key;let o;if(t.isTexture===!0){const l=t;l.source&&l.source[fe]&&(o=l.source[fe])}if(o||(o=g.lodInfos.get(s)),o){if(e>0){let u=!1;const f=Array.isArray(o.lods);if(f&&e>=o.lods.length?u=!0:f||(u=!0),u)return this.lowresCache.get(s)}const l=Array.isArray(o.lods)?o.lods[e]?.path:o.lods;if(!l)return h&&!o["missing:uri"]&&(o["missing:uri"]=!0,console.warn("Missing uri for progressive asset for LOD "+e,o)),null;const a=Ze(n.url,l);if(a.endsWith(".glb")||a.endsWith(".gltf")){if(!o.guid)return console.warn("missing pointer for glb/gltf texture",o),null;const u=a+"_"+o.guid,f=await this.queue.slot(a),w=this.previouslyLoaded.get(u);if(w!==void 0){r&&console.log(`LOD ${e} was already loading/loaded: ${u}`);let p=await w.catch(y=>(console.error(`Error loading LOD ${e} from ${a}
2
- `,y),null)),m=!1;if(p==null||(p instanceof N&&t instanceof N?p.image?.data||p.source?.data?p=this.copySettings(t,p):(m=!0,this.previouslyLoaded.delete(u)):p instanceof V&&t instanceof V&&(p.attributes.position?.array||(m=!0,this.previouslyLoaded.delete(u)))),!m)return p}if(!f.use)return h&&console.log(`LOD ${e} was aborted: ${a}`),null;const v=o,T=new Promise(async(p,m)=>{if(ut){const x=await(await at({})).load(a);if(x.textures.length>0)for(const d of x.textures){let c=d.texture;return g.assignLODInformation(n.url,c,s,e,void 0),t instanceof N&&(c=this.copySettings(t,c)),c&&(c.guid=v.guid),p(c)}if(x.geometries.length>0){const d=new Array;for(const c of x.geometries){const L=c.geometry;g.assignLODInformation(n.url,L,s,e,c.primitiveIndex),d.push(L)}return p(d)}return p(null)}const y=new ae;le(y),h&&(await new Promise(x=>setTimeout(x,1e3)),r&&console.warn("Start loading (delayed) "+a,v.guid));let A=a;if(v&&Array.isArray(v.lods)){const x=v.lods[e];x.hash&&(A+="?v="+x.hash)}const _=await y.loadAsync(A).catch(x=>(console.error(`Error loading LOD ${e} from ${a}
3
- `,x),p(null)));if(!_)return p(null);const E=_.parser;r&&console.log("Loading finished "+a,v.guid);let D=0;if(_.parser.json.textures){let x=!1;for(const d of _.parser.json.textures){if(d?.extensions){const c=d?.extensions[$];if(c?.guid&&c.guid===v.guid){x=!0;break}}D++}if(x){let d=await E.getDependency("texture",D);return d&&g.assignLODInformation(n.url,d,s,e,void 0),r&&console.log('change "'+t.name+'" \u2192 "'+d.name+'"',a,D,d,u),t instanceof N&&(d=this.copySettings(t,d)),d&&(d.guid=v.guid),p(d)}else h&&console.warn("Could not find texture with guid",v.guid,_.parser.json)}if(D=0,_.parser.json.meshes){let x=!1;for(const d of _.parser.json.meshes){if(d?.extensions){const c=d?.extensions[$];if(c?.guid&&c.guid===v.guid){x=!0;break}}D++}if(x){const d=await E.getDependency("mesh",D);if(r&&console.log(`Loaded Mesh "${d.name}"`,a,D,d,u),d.isMesh===!0){const c=d.geometry;return g.assignLODInformation(n.url,c,s,e,0),p(c)}else{const c=new Array;for(let L=0;L<d.children.length;L++){const O=d.children[L];if(O.isMesh===!0){const S=O.geometry;g.assignLODInformation(n.url,S,s,e,L),c.push(S)}}return p(c)}}else h&&console.warn("Could not find mesh with guid",v.guid,_.parser.json)}return p(null)});return this.previouslyLoaded.set(u,T),f.use(T),await T}else if(t instanceof N){r&&console.log("Load texture from uri: "+a);const u=await new Fe().loadAsync(a);return u?(u.guid=o.guid,u.flipY=!1,u.needsUpdate=!0,u.colorSpace=t.colorSpace,r&&console.log(o,u)):h&&console.warn("failed loading",a),u}}else h&&console.warn(`Can not load LOD ${e}: no LOD info found for "${s}" ${t.name}`,t.type);return null}static maxConcurrent=50;static queue=new et(g.maxConcurrent,{debug:h!=!1});static assignLODInformation(t,e,r,n,s){if(!e)return;e.userData||(e.userData={});const o=new ct(t,r,n,s);e.userData.LODS=o,"source"in e&&typeof e.source=="object"&&(e.source.LODS=o)}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?(h==="verbose"&&console.debug(`Copy texture settings
4
- `,t.uuid,`
5
- `,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 ct{url;key;level;index;constructor(t,e,r,n){this.url=t,this.key=e,this.level=r,n!=null&&(this.index=n)}}class me{static addPromise=(t,e,r,n)=>{n.forEach(s=>{s.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(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,r){if(this._resolved){h&&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)){let n=this._seen.get(e);if(n>=this._maxPromisesPerObject){h&&console.warn("PromiseGroup: Already awaiting object ignoring new promise for it.");return}this._seen.set(e,n+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 B=F("debugprogressive"),ht=F("noprogressive"),pe=Symbol("Needle:LODSManager"),xe=Symbol("Needle:LODState"),G=Symbol("Needle:CurrentLOD"),M={mesh_lod:-1,texture_lod:-1};let H=class b{static debugDrawLine;static getObjectLODState(t){return t[xe]}static addPlugin(t){R.push(t)}static removePlugin(t){const e=R.indexOf(t);e>=0&&R.splice(e,1)}static get(t,e){if(t[pe])return console.debug("[gltf-progressive] LODsManager already exists for this renderer"),t[pe];const r=new b(t,{engine:"unknown",...e});return t[pe]=r,r}renderer;context;projectionScreenMatrix=new Le;get plugins(){return R}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 me(this.#s,{...t});this._newPromiseGroups.push(r);const n=performance.now();return r.ready.finally(()=>{const s=this._newPromiseGroups.indexOf(r);s>=0&&(this._newPromiseGroups.splice(s,1),Pe()&&performance.measure("LODsManager:awaitLoading",{start:n,detail:{id:e,name:t?.name,awaited:r.awaitedCount,resolved:r.resolvedCount}}))}),r.ready}_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){t==="changed"&&this._lodchangedlisteners.push(e)}removeEventListener(t,e){if(t==="changed"){const r=this._lodchangedlisteners.indexOf(e);r>=0&&this._lodchangedlisteners.splice(r,1)}}constructor(t,e){this.renderer=t,this.context={...e}}#t;#o=new We;#s=0;#n=0;#i=0;#r=0;_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;Z(this.renderer),this.renderer.render=function(r,n){const s=e.renderer.getRenderTarget();(s==null||"isXRRenderTarget"in s&&s.isXRRenderTarget)&&(t=0,e.#s+=1,e.#n=e.#o.getDelta(),e.#i+=e.#n,e._fpsBuffer.shift(),e._fpsBuffer.push(1/e.#n),e.#r=e._fpsBuffer.reduce((l,a)=>l+a)/e._fpsBuffer.length,B&&e.#s%200===0&&console.log("FPS",Math.round(e.#r),"Interval:",e.#e));const o=t++;e.#t.call(this,r,n),e.onAfterRender(r,n,o)}}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 n=this.renderer.renderLists.get(t,0).opaque;let s=!0;if(n.length===1){const o=n[0].material;(o.name==="EffectMaterial"||o.name==="CopyShader")&&(s=!1)}if((e.parent&&e.parent.type==="CubeCamera"||r>=1&&e.type==="OrthographicCamera")&&(s=!1),s){if(ht||(this.updateInterval==="auto"?this.#r<40&&this.#e<10?(this.#e+=1,B&&console.warn("\u2193 Reducing LOD updates",this.#e,this.#r.toFixed(0))):this.#r>=60&&this.#e>1&&(this.#e-=1,B&&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.renderer.renderLists.get(t,0),n=r.opaque;this.projectionScreenMatrix.multiplyMatrices(e.projectionMatrix,e.matrixWorldInverse);const s=this.targetTriangleDensity;for(const a of n){if(a.material&&(a.geometry?.type==="BoxGeometry"||a.geometry?.type==="BufferGeometry")&&(a.material.name==="SphericalGaussianBlur"||a.material.name=="BackgroundCubeMaterial"||a.material.name==="CubemapFromEquirect"||a.material.name==="EquirectangularToCubeUV")){B&&(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]||(a.material["NEEDLE_PROGRESSIVE:IGNORE-WARNING"]=!0,console.warn("Ignoring skybox or BLIT object",a,a.material.name,a.material.type)));continue}switch(a.material.type){case"LineBasicMaterial":case"LineDashedMaterial":case"PointsMaterial":case"ShadowMaterial":case"MeshDistanceMaterial":case"MeshDepthMaterial":continue}if(B==="color"&&a.material&&!a.object.progressive_debug_color){a.object.progressive_debug_color=!0;const f=Math.random()*16777215,w=new ze({color:f});a.object.material=w}const u=a.object;(u instanceof j||u.isMesh)&&this.updateLODs(t,e,u,s)}const o=r.transparent;for(const a of o){const u=a.object;(u instanceof j||u.isMesh)&&this.updateLODs(t,e,u,s)}const l=r.transmissive;for(const a of l){const u=a.object;(u instanceof j||u.isMesh)&&this.updateLODs(t,e,u,s)}}updateLODs(t,e,r,n){r.userData||(r.userData={});let s=r[xe];if(s||(s=new gt,r[xe]=s),s.frames++<2)return;for(const l of R)l.onBeforeUpdateLOD?.(this.renderer,t,e,r);const o=this.overrideLodLevel!==void 0?this.overrideLodLevel:W;o>=0?(M.mesh_lod=o,M.texture_lod=o):(this.calculateLodLevel(e,r,s,n,M),M.mesh_lod=Math.round(M.mesh_lod),M.texture_lod=Math.round(M.texture_lod)),M.mesh_lod>=0&&this.loadProgressiveMeshes(r,M.mesh_lod),r.material&&M.texture_lod>=0&&this.loadProgressiveTextures(r.material,M.texture_lod,o),h&&r.material&&!r.isGizmo&&Te(r.material);for(const l of R)l.onAfterUpdatedLOD?.(this.renderer,t,e,r,M);s.lastLodLevel_Mesh=M.mesh_lod,s.lastLodLevel_Texture=M.texture_lod}loadProgressiveTextures(t,e,r){if(!t)return;if(Array.isArray(t)){for(const s of t)this.loadProgressiveTextures(s,e);return}let n=!1;if((t[G]===void 0||e<t[G])&&(n=!0),r!==void 0&&r>=0&&(n=t[G]!=r,e=r),n){t[G]=e;const s=g.assignTextureLOD(t,e).then(o=>{this._lodchangedlisteners.forEach(l=>l({type:"texture",level:e,object:t}))});me.addPromise("texture",t,s,this._newPromiseGroups)}}loadProgressiveMeshes(t,e){if(!t)return Promise.resolve(null);let r=t[G]!==e;const n=t["DEBUG:LOD"];if(n!=null&&(r=t[G]!=n,e=n),r){t[G]=e;const s=t.geometry,o=g.assignMeshLOD(t,e).then(l=>(l&&t[G]==e&&s!=t.geometry&&this._lodchangedlisteners.forEach(a=>a({type:"mesh",level:e,object:t})),l));return me.addPromise("mesh",t,o,this._newPromiseGroups),o}return Promise.resolve(null)}_sphere=new ve;_tempBox=new ie;_tempBox2=new ie;tempMatrix=new Le;_tempWorldPosition=new I;_tempBoxSize=new I;_tempBox2Size=new I;static corner0=new I;static corner1=new I;static corner2=new I;static corner3=new I;static _tempPtInside=new I;static isInside(t,e){const r=t.min,n=t.max,s=(r.x+n.x)*.5,o=(r.y+n.y)*.5;return this._tempPtInside.set(s,o,r.z).applyMatrix4(e).z<0}static skinnedMeshBoundsFrameOffsetCounter=0;static $skinnedMeshBoundsOffset=Symbol("gltf-progressive-skinnedMeshBoundsOffset");calculateLodLevel(t,e,r,n,s){if(!e){s.mesh_lod=-1,s.texture_lod=-1;return}if(!t){s.mesh_lod=-1,s.texture_lod=-1;return}let o=10+1,l=!1;if(B&&e["DEBUG:LOD"]!=null)return e["DEBUG:LOD"];const a=g.getMeshLODExtension(e.geometry)?.lods,u=g.getPrimitiveIndex(e.geometry),f=a&&a.length>0,w=g.getMaterialMinMaxLODsCount(e.material),v=w.min_count!==1/0&&w.min_count>=0&&w.max_count>=0;if(!f&&!v){s.mesh_lod=0,s.texture_lod=0;return}f||(l=!0,o=0);const T=this.renderer.domElement.clientHeight||this.renderer.domElement.height;let p=e.geometry.boundingBox;if(e.type==="SkinnedMesh"){const m=e;if(!m.boundingBox)m.computeBoundingBox();else if(this.skinnedMeshAutoUpdateBoundsInterval>0){if(!m[b.$skinnedMeshBoundsOffset]){const A=b.skinnedMeshBoundsFrameOffsetCounter++;m[b.$skinnedMeshBoundsOffset]=A}const y=m[b.$skinnedMeshBoundsOffset];if((r.frames+y)%this.skinnedMeshAutoUpdateBoundsInterval===0){const A=z(m),_=m.geometry;A&&(m.geometry=A),m.computeBoundingBox(),m.geometry=_}}p=m.boundingBox}if(p){const m=t;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 d=t.getWorldPosition(this._tempWorldPosition);if(this._sphere.containsPoint(d)){s.mesh_lod=0,s.texture_lod=0;return}}if(this._tempBox.copy(p),this._tempBox.applyMatrix4(e.matrixWorld),m.isPerspectiveCamera&&b.isInside(this._tempBox,this.projectionScreenMatrix)){s.mesh_lod=0,s.texture_lod=0;return}if(this._tempBox.applyMatrix4(this.projectionScreenMatrix),this.renderer.xr.enabled&&m.isPerspectiveCamera&&m.fov>70){const d=this._tempBox.min,c=this._tempBox.max;let L=d.x,O=d.y,S=c.x,q=c.y;const Y=2,ne=1.5,Q=(d.x+c.x)*.5,J=(d.y+c.y)*.5;L=(L-Q)*Y+Q,O=(O-J)*Y+J,S=(S-Q)*Y+Q,q=(q-J)*Y+J;const Be=L<0&&S>0?0:Math.min(Math.abs(d.x),Math.abs(c.x)),$e=O<0&&q>0?0:Math.min(Math.abs(d.y),Math.abs(c.y)),oe=Math.max(Be,$e);r.lastCentrality=(ne-oe)*(ne-oe)*(ne-oe)}else r.lastCentrality=1;const y=this._tempBox.getSize(this._tempBoxSize);y.multiplyScalar(.5),screen.availHeight>0&&T>0&&y.multiplyScalar(T/screen.availHeight),t.isPerspectiveCamera?y.x*=t.aspect:t.isOrthographicCamera;const A=t.matrixWorldInverse,_=this._tempBox2;_.copy(p),_.applyMatrix4(e.matrixWorld),_.applyMatrix4(A);const E=_.getSize(this._tempBox2Size),D=Math.max(E.x,E.y);if(Math.max(y.x,y.y)!=0&&D!=0&&(y.z=E.z/Math.max(E.x,E.y)*Math.max(y.x,y.y)),r.lastScreenCoverage=Math.max(y.x,y.y,y.z),r.lastScreenspaceVolume.copy(y),r.lastScreenCoverage*=r.lastCentrality,B&&b.debugDrawLine){const d=this.tempMatrix.copy(this.projectionScreenMatrix);d.invert();const c=b.corner0,L=b.corner1,O=b.corner2,S=b.corner3;c.copy(this._tempBox.min),L.copy(this._tempBox.max),L.x=c.x,O.copy(this._tempBox.max),O.y=c.y,S.copy(this._tempBox.max);const q=(c.z+S.z)*.5;c.z=L.z=O.z=S.z=q,c.applyMatrix4(d),L.applyMatrix4(d),O.applyMatrix4(d),S.applyMatrix4(d),b.debugDrawLine(c,L,255),b.debugDrawLine(c,O,255),b.debugDrawLine(L,S,255),b.debugDrawLine(O,S,255)}let x=999;if(a&&r.lastScreenCoverage>0)for(let d=0;d<a.length;d++){const c=a[d],L=(c.densities?.[u]||c.density||1e-5)/r.lastScreenCoverage;if(u>0&&Pe()&&!c.densities&&!globalThis["NEEDLE:MISSING_LOD_PRIMITIVE_DENSITIES"]&&(window["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.")),L<n){x=d;break}}x<o&&(o=x,l=!0)}if(l?s.mesh_lod=o:s.mesh_lod=r.lastLodLevel_Mesh,B&&s.mesh_lod!=r.lastLodLevel_Mesh){const m=a?.[s.mesh_lod];m&&console.debug(`Mesh LOD changed: ${r.lastLodLevel_Mesh} \u2192 ${s.mesh_lod} (density: ${m.densities?.[u].toFixed(0)}) | ${e.name}`)}if(v){const m="saveData"in globalThis.navigator&&globalThis.navigator.saveData===!0;if(r.lastLodLevel_Texture<0){if(s.texture_lod=w.max_count-1,B){const y=w.lods[w.max_count-1];B&&console.log(`First Texture LOD ${s.texture_lod} (${y.max_height}px) - ${e.name}`)}}else{const y=r.lastScreenspaceVolume.x+r.lastScreenspaceVolume.y+r.lastScreenspaceVolume.z;let A=r.lastScreenCoverage*4;this.context?.engine==="model-viewer"&&(A*=1.5);const _=T/window.devicePixelRatio*A;let E=!1;for(let D=w.lods.length-1;D>=0;D--){const x=w.lods[D];if(!(m&&x.max_height>=2048)&&!(Se()&&x.max_height>4096)&&(x.max_height>_||!E&&D===0)){if(E=!0,s.texture_lod=D,B&&s.texture_lod<r.lastLodLevel_Texture){const d=x.max_height;console.log(`Texture LOD changed: ${r.lastLodLevel_Texture} \u2192 ${s.texture_lod} = ${d}px
6
- Screensize: ${_.toFixed(0)}px, Coverage: ${(100*r.lastScreenCoverage).toFixed(2)}%, Volume ${y.toFixed(1)}
7
- ${e.name}`)}break}}}}else s.texture_lod=0}};class gt{frames=0;lastLodLevel_Mesh=-1;lastLodLevel_Texture=-1;lastScreenCoverage=0;lastScreenspaceVolume=new I;lastCentrality=0}const Ae=Symbol("NEEDLE_mesh_lod"),se=Symbol("NEEDLE_texture_lod");let we=null;function Ie(){const i=ft();i&&(i.mapURLs(function(t){return Ee(),t}),Ee(),we?.disconnect(),we=new MutationObserver(t=>{t.forEach(e=>{e.addedNodes.forEach(r=>{r instanceof HTMLElement&&r.tagName.toLowerCase()==="model-viewer"&&Ce(r)})})}),we.observe(document,{childList:!0,subtree:!0}))}function ft(){return typeof customElements>"u"?null:customElements.get("model-viewer")||(customElements.whenDefined("model-viewer").then(()=>{console.debug("[gltf-progressive] model-viewer defined"),Ie()}),null)}function Ee(){typeof document>"u"||document.querySelectorAll("model-viewer").forEach(i=>{Ce(i)})}const ke=new WeakSet;let mt=0;function Ce(i){if(!i||ke.has(i))return null;ke.add(i),console.debug("[gltf-progressive] found new model-viewer..."+ ++mt+`
8
- `,i.getAttribute("src"));let t=null,e=null,r=null;for(let n=i;n!=null;n=Object.getPrototypeOf(n)){const s=Object.getOwnPropertySymbols(n),o=s.find(u=>u.toString()=="Symbol(renderer)"),l=s.find(u=>u.toString()=="Symbol(scene)"),a=s.find(u=>u.toString()=="Symbol(needsRender)");!t&&o!=null&&(t=i[o].threeRenderer),!e&&l!=null&&(e=i[l]),!r&&a!=null&&(r=i[a])}if(t&&e){let n=function(){if(r){let o=0,l=setInterval(()=>{if(o++>5){clearInterval(l);return}r?.call(i)},300)}};console.debug("[gltf-progressive] setup model-viewer");const s=H.get(t,{engine:"model-viewer"});return H.addPlugin(new pt),s.enable(),s.addEventListener("changed",()=>{r?.call(i)}),i.addEventListener("model-visibility",o=>{o.detail.visible&&r?.call(i)}),i.addEventListener("load",()=>{n()}),()=>{s.disable()}}return null}class pt{_didWarnAboutMissingUrl=!1;onBeforeUpdateLOD(t,e,r,n){this.tryParseMeshLOD(e,n),this.tryParseTextureLOD(e,n)}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[se]==!0)return;e[se]=!0;const r=this.tryGetCurrentGLTF(t),n=this.tryGetCurrentModelViewer(t),s=this.getUrl(n);if(s&&r&&e.material){let o=function(a){if(a[se]==!0)return;a[se]=!0,a.userData&&(a.userData.LOD=-1);const u=Object.keys(a);for(let f=0;f<u.length;f++){const w=u[f],v=a[w];if(v?.isTexture===!0){const T=v.userData?.associations?.textures;if(T==null)continue;const p=r.parser.json.textures[T];if(!p){console.warn("Texture data not found for texture index "+T);continue}if(p?.extensions?.[$]){const m=p.extensions[$];m&&s&&g.registerTexture(s,v,m.lods.length,T,m)}}}};const l=e.material;if(Array.isArray(l))for(const a of l)o(a);else o(l)}}tryParseMeshLOD(t,e){if(e[Ae]==!0)return;e[Ae]=!0;const r=this.tryGetCurrentModelViewer(t),n=this.getUrl(r);if(!n)return;const s=e.userData?.gltfExtensions?.[$];if(s&&n){const o=e.uuid;g.registerMesh(n,o,e,0,s.lods.length,s)}}}function xt(...i){let t,e,r,n;switch(i.length){case 2:[r,e]=i,n={};break;case 3:[r,e,n]=i;break;case 4:[t,e,r,n]=i;break;default:throw new Error("Invalid arguments")}Z(e),le(r),ce(r,{progressive:!0,...n?.hints}),r.register(o=>new g(o));const s=H.get(e);return n?.enableLODsManager!==!1&&s.enable(),s}if(Ie(),!tt){const i={gltfProgressive:{useNeedleProgressive:xt,LODsManager:H,configureLoader:ce,getRaycastMesh:z,useRaycastMeshes:st}};if(!globalThis.Needle)globalThis.Needle=i;else for(const t in i)globalThis.Needle[t]=i[t]}export{H as LODsManager,g as NEEDLE_progressive,le as addDracoAndKTX2Loaders,ce as configureLoader,Z as createLoaders,z as getRaycastMesh,De as setDracoDecoderLocation,Me as setKTX2TranscoderLocation};