ldr 0.5.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -1,4 +1,4 @@
1
- // ../../../../../../../tmp/ldr-build-pIke9r/src/spec.ts
1
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/spec.ts
2
2
  var norm = (s) => s.trim().toLowerCase().replace(/\\/g, "/").replace(/\/+/g, "/");
3
3
  function parseColor(tok) {
4
4
  if (/^0x/i.test(tok))
@@ -86,6 +86,36 @@ var b64 = (s) => {
86
86
  out[i] = bin.charCodeAt(i);
87
87
  return out;
88
88
  };
89
+ function type1Fast(line) {
90
+ const n = line.length;
91
+ let i = 1;
92
+ const ws = (c) => c === 32 || c === 9;
93
+ const next = () => {
94
+ while (i < n && ws(line.charCodeAt(i)))
95
+ i++;
96
+ const a = i;
97
+ while (i < n && !ws(line.charCodeAt(i)))
98
+ i++;
99
+ return a < i ? line.slice(a, i) : null;
100
+ };
101
+ const ct = next();
102
+ if (ct === null)
103
+ return null;
104
+ const m = new Array(12);
105
+ for (let k = 0;k < 12; k++) {
106
+ const t = next();
107
+ if (t === null)
108
+ return null;
109
+ m[k] = +t;
110
+ }
111
+ while (i < n && ws(line.charCodeAt(i)))
112
+ i++;
113
+ if (i >= n)
114
+ return null;
115
+ const rest = line.slice(i);
116
+ const file = /[ \t]{2,}|\t/.test(rest) ? rest.split(/\s+/).join(" ") : rest;
117
+ return { t: 1, color: parseColor(ct), m, file: norm(file) };
118
+ }
89
119
  function geomLine(tk) {
90
120
  const t = +tk[0];
91
121
  if (!(t >= 1 && t <= 5) || tk.length < 2)
@@ -154,7 +184,8 @@ function parse(src, name = "main.ldr", popts = {}) {
154
184
  } else
155
185
  c.tex = top.map;
156
186
  };
157
- for (const raw of src.split(/\r?\n/)) {
187
+ for (const raw of src.split(`
188
+ `)) {
158
189
  const line = raw.trim();
159
190
  if (!line)
160
191
  continue;
@@ -205,6 +236,17 @@ function parse(src, name = "main.ldr", popts = {}) {
205
236
  continue;
206
237
  }
207
238
  }
239
+ if (line.charCodeAt(0) === 49 && (line.charCodeAt(1) === 32 || line.charCodeAt(1) === 9) && !dataCur && !skip) {
240
+ const g = type1Fast(line);
241
+ if (g) {
242
+ if (!cur)
243
+ start(name);
244
+ annotate(g, false);
245
+ cur.cmds.push(g);
246
+ inHeader = false;
247
+ continue;
248
+ }
249
+ }
208
250
  const tk = line.split(/\s+/);
209
251
  const t = +tk[0];
210
252
  if (t === 0) {
@@ -647,12 +689,15 @@ function fileStepViews(f) {
647
689
  viewMemo.set(f, out);
648
690
  return out;
649
691
  }
650
- // ../../../../../../../tmp/ldr-build-pIke9r/src/model.ts
692
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/model.ts
693
+ var CALLOUT_END = 999999;
694
+ var stepKey = (steps) => steps.map((x) => String(x).padStart(6, "0")).join(".") + "~";
651
695
  function flatten(doc, opts = {}) {
652
696
  const out = [];
653
697
  const maxDepth = opts.maxDepth ?? 64;
654
- const loose = opts.looseGeometry !== false, tx = !!opts.textures;
698
+ const loose = opts.looseGeometry !== false, tx = !!opts.textures, co = !!opts.callouts;
655
699
  const src = new Map;
700
+ let subs = 0;
656
701
  const lazy = (f, k) => {
657
702
  const key = f.name + "#" + k;
658
703
  let fn = src.get(key);
@@ -663,16 +708,44 @@ function flatten(doc, opts = {}) {
663
708
  }
664
709
  return fn;
665
710
  };
666
- const walk = (d, fname, m, color, path, stepPath, depth, texIn) => {
711
+ const walk = (d, fname, m, color, path, stepPath, depth, texIn, fixed = null, subPath = [], subMats = []) => {
667
712
  const f = d.files.get(fname);
668
713
  if (!f || depth > maxDepth)
669
714
  return;
670
715
  let s = 0;
716
+ const subId = depth > 0 ? ++subs : 0;
717
+ const sp0 = co && subId ? [...subPath, subId] : subPath;
718
+ const sm0 = co && subId ? [...subMats, m] : subMats;
719
+ const groups = co && !fixed ? new Map : null;
720
+ let ordStep = -1, ord = 0;
721
+ const sub = (sd, file, mm, col, sp, lt) => {
722
+ if (ordStep !== s) {
723
+ ordStep = s;
724
+ ord = 0;
725
+ }
726
+ const g = groups?.get(s + "|" + file);
727
+ if (g) {
728
+ g.n++;
729
+ return walk(sd, sd === d ? file : sd.main, mm, col, path + "/" + file, [...sp, CALLOUT_END], depth + 1, lt, [...sp, CALLOUT_END], sp0, sm0);
730
+ }
731
+ const spo = [...sp, ord++], from = out.length;
732
+ walk(sd, sd === d ? file : sd.main, mm, col, path + "/" + file, spo, depth + 1, lt, fixed, sp0, sm0);
733
+ groups?.set(s + "|" + file, { n: 1, from, to: out.length });
734
+ };
671
735
  const views = fileStepViews(f);
672
736
  const ls = loose ? looseSteps(f) : [];
673
737
  let li = 0;
674
738
  const emit = (part, col, mm, sp, k, embedded, tex) => {
739
+ if (fixed)
740
+ sp = fixed;
675
741
  const i = { part, color: col, m: mm, step: sp[0], steps: sp, localStep: k, path };
742
+ if (subId) {
743
+ i.sub = subId;
744
+ if (co) {
745
+ i.subPath = sp0;
746
+ i.subMats = sm0;
747
+ }
748
+ }
676
749
  if (embedded)
677
750
  i.embedded = true;
678
751
  if (tex) {
@@ -718,7 +791,7 @@ function flatten(doc, opts = {}) {
718
791
  const lt = tex && local ? transformTexMap(tex, local) : null;
719
792
  if (d.files.has(c.file)) {
720
793
  if (fileKind(d, c.file) === "model") {
721
- walk(d, c.file, mm, col, path + "/" + c.file, sp, depth + 1, lt);
794
+ sub(d, c.file, mm, col, sp, lt);
722
795
  continue;
723
796
  }
724
797
  emit(c.file, col, mm, sp, s, true, lt);
@@ -726,12 +799,18 @@ function flatten(doc, opts = {}) {
726
799
  }
727
800
  const ext = opts.resolveModel?.(c.file);
728
801
  if (ext) {
729
- walk(ext, ext.main, mm, col, path + "/" + c.file, sp, depth + 1, lt);
802
+ sub(ext, c.file, mm, col, sp, lt);
730
803
  continue;
731
804
  }
732
805
  emit(c.file, col, mm, sp, s, false, lt);
733
806
  }
734
807
  flushLoose(Infinity);
808
+ if (groups) {
809
+ for (const g of groups.values())
810
+ if (g.n > 1)
811
+ for (let j = g.from;j < g.to; j++)
812
+ out[j].mult ??= g.n;
813
+ }
735
814
  };
736
815
  if (fileKind(doc, doc.main) === "part") {
737
816
  const f = doc.files.get(doc.main);
@@ -743,10 +822,10 @@ function flatten(doc, opts = {}) {
743
822
  return out;
744
823
  }
745
824
  function parseModel(text, name = "main.ldr", opts) {
746
- return flatten(parse(text, name), opts);
825
+ return flatten(parse(text, name, { geometryText: true }), opts);
747
826
  }
748
827
  function sequenceSteps(insts) {
749
- const key = (i) => i.steps.map((x) => String(x).padStart(6, "0")).join(".");
828
+ const key = (i) => stepKey(i.steps);
750
829
  const uniq = [...new Set(insts.map(key))].sort();
751
830
  const rank = new Map(uniq.map((k, j) => [k, j]));
752
831
  const stepOf = new Int32Array(insts.length);
@@ -768,326 +847,397 @@ function parseLDConfig(text) {
768
847
  }
769
848
  return out;
770
849
  }
771
- // ../../../../../../../tmp/ldr-build-pIke9r/src/render.ts
772
- import * as THREE from "three";
773
- async function loadPack(url) {
774
- const res = await fetch(url);
775
- const t0 = performance.now();
776
- let buf;
777
- if (url.endsWith(".gz"))
778
- buf = await new Response(res.body.pipeThrough(new DecompressionStream("gzip"))).arrayBuffer();
779
- else if (url.endsWith(".br"))
780
- buf = await new Response(res.body.pipeThrough(new DecompressionStream("brotli"))).arrayBuffer();
781
- else if (url.endsWith(".zst")) {
782
- const raw = new Uint8Array(await res.arrayBuffer());
783
- const t1 = performance.now();
784
- const { decompress } = await import("fzstd");
785
- const o = decompress(raw);
786
- buf = o.buffer.slice(o.byteOffset, o.byteOffset + o.byteLength);
787
- globalThis.__decodeMs = performance.now() - t1;
788
- } else
789
- buf = await res.arrayBuffer();
790
- if (!url.endsWith(".zst"))
791
- globalThis.__decodeMs = performance.now() - t0;
792
- return decodePack(buf);
793
- }
794
- function decodePack(buf) {
795
- const hl = new DataView(buf).getUint32(0, true);
796
- const header = JSON.parse(new TextDecoder().decode(new Uint8Array(buf, 4, hl)));
797
- const base = 4 + hl;
798
- const arr = (r) => r && (r[2] === "f32" ? new Float32Array(buf, base + r[0], r[1]) : r[2] === "u16" ? new Uint16Array(buf, base + r[0], r[1]) : r[2] === "u8" ? new Uint8Array(buf, base + r[0], r[1]) : new Uint32Array(buf, base + r[0], r[1]));
799
- return { header, arr, bytes: buf.byteLength, buffer: buf };
800
- }
801
- var toI8 = (a) => {
802
- const o = new Int8Array(a.length);
803
- for (let i = 0;i < a.length; i++)
804
- o[i] = Math.round(Math.max(-1, Math.min(1, a[i])) * 127);
805
- return o;
806
- };
807
- var toU8 = (a) => {
808
- const o = new Uint8Array(a.length);
809
- for (let i = 0;i < a.length; i++)
810
- o[i] = Math.round(Math.max(0, Math.min(1, a[i])) * 255);
811
- return o;
812
- };
813
- function flatNormals(pos, idx) {
814
- const n = new Float32Array(pos.length);
815
- for (let t = 0;t < idx.length; t += 3) {
816
- const a = idx[t] * 3, b = idx[t + 1] * 3, c = idx[t + 2] * 3;
817
- const ux = pos[b] - pos[a], uy = pos[b + 1] - pos[a + 1], uz = pos[b + 2] - pos[a + 2], vx = pos[c] - pos[a], vy = pos[c + 1] - pos[a + 1], vz = pos[c + 2] - pos[a + 2];
818
- let nx = uy * vz - uz * vy, ny = uz * vx - ux * vz, nz = ux * vy - uy * vx;
819
- const l = Math.hypot(nx, ny, nz) || 1;
820
- nx /= l;
821
- ny /= l;
822
- nz /= l;
823
- for (const o of [a, b, c]) {
824
- n[o] = nx;
825
- n[o + 1] = ny;
826
- n[o + 2] = nz;
827
- }
828
- }
829
- return n;
830
- }
831
- var geomCache = new WeakMap;
832
- function geom(b, arr, quant = true) {
833
- if (!b)
834
- return null;
835
- let c = geomCache.get(arr);
836
- if (!c)
837
- geomCache.set(arr, c = new Map);
838
- const ck = quant ? b : b.pos;
839
- let g = c.get(ck);
840
- if (g)
841
- return g;
842
- g = new THREE.BufferGeometry;
843
- g.setAttribute("position", new THREE.BufferAttribute(arr(b.pos), 3));
844
- const nrm = b.nrm ? arr(b.nrm) : flatNormals(arr(b.pos), arr(b.idx));
845
- const col = arr(b.col);
846
- g.setAttribute("normal", quant ? new THREE.BufferAttribute(toI8(nrm), 3, true) : new THREE.BufferAttribute(nrm, 3));
847
- g.setAttribute("ldrColor", col instanceof Uint8Array ? new THREE.BufferAttribute(col, 4, true) : quant ? new THREE.BufferAttribute(toU8(col), 4, true) : new THREE.BufferAttribute(col, 4));
848
- if (b.idx)
849
- g.setIndex(new THREE.BufferAttribute(arr(b.idx), 1));
850
- if (b.uv)
851
- g.setAttribute("ldrUV", new THREE.BufferAttribute(arr(b.uv), 2));
852
- c.set(ck, g);
853
- return g;
854
- }
855
- function makeMaterial(side) {
856
- const m = new THREE.MeshStandardMaterial({ vertexColors: true, roughness: 0.45, side });
857
- m.onBeforeCompile = (s) => {
858
- s.vertexShader = `attribute vec4 ldrColor;
859
- ` + s.vertexShader.replace("#include <color_vertex>", `#include <color_vertex>
860
- #ifdef USE_INSTANCING_COLOR
861
- vColor.rgb = ldrColor.a > 0.5 ? pow(ldrColor.rgb, vec3(2.2)) : instanceColor.rgb; // baked LDConfig colours are sRGB
862
- #else
863
- vColor.rgb = pow(ldrColor.rgb, vec3(2.2));
864
- #endif`);
865
- };
866
- m.customProgramCacheKey = () => "ldrColor";
867
- return m;
850
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/instructions.ts
851
+ var MIN_VIS = 0.5;
852
+ var REORIENT = 0.35;
853
+ var deg = Math.PI / 180;
854
+ function viewDir(azimuthDeg, elevationDeg) {
855
+ const a = azimuthDeg * deg, e = elevationDeg * deg;
856
+ return [Math.sin(a) * Math.cos(e), -Math.sin(e), -Math.cos(a) * Math.cos(e)];
868
857
  }
869
- function makeTexturedMaterial(side, map, wrapU = false) {
870
- const m = makeMaterial(side);
871
- const base = m.onBeforeCompile;
872
- m.onBeforeCompile = (sh, r) => {
873
- base.call(m, sh, r);
874
- sh.uniforms.ldrMap = { value: map };
875
- sh.uniforms.ldrWrapU = { value: wrapU ? 1 : 0 };
876
- sh.vertexShader = `attribute vec2 ldrUV; varying vec2 vLdrUV;
877
- ` + sh.vertexShader.replace("#include <uv_vertex>", `#include <uv_vertex>
878
- vLdrUV = ldrUV;`);
879
- sh.fragmentShader = `uniform sampler2D ldrMap; uniform int ldrWrapU; varying vec2 vLdrUV;
880
- ` + sh.fragmentShader.replace("#include <color_fragment>", `#include <color_fragment>
881
- { vec2 uv = vec2(ldrWrapU == 1 ? fract(vLdrUV.x) : vLdrUV.x, vLdrUV.y); vec4 t = texture2D(ldrMap, uv);
882
- float inside = step(0.0, uv.x) * step(uv.x, 1.0) * step(0.0, uv.y) * step(uv.y, 1.0);
883
- diffuseColor.rgb = mix(diffuseColor.rgb, t.rgb, t.a * inside); }`);
884
- };
885
- m.customProgramCacheKey = () => "ldrColorTex";
886
- m.userData.ldrMap = map;
858
+ function isolateMask(insts, sub) {
859
+ const m = new Uint8Array(insts.length);
860
+ insts.forEach((i, k) => {
861
+ if (i.subPath?.includes(sub))
862
+ m[k] = 1;
863
+ });
887
864
  return m;
888
865
  }
889
- function packTexture(pack, i) {
890
- const t = new THREE.Texture;
891
- t.flipY = false;
892
- t.colorSpace = THREE.SRGBColorSpace;
893
- t.wrapS = t.wrapT = THREE.ClampToEdgeWrapping;
894
- const e = pack.header.textures?.[i];
895
- const bytes = e?.data ? pack.arr(e.data) : null;
896
- if (!bytes || typeof createImageBitmap === "undefined")
897
- return { texture: t, ready: Promise.resolve() };
898
- const ready = createImageBitmap(new Blob([bytes], { type: e.mime || "image/png" }), { premultiplyAlpha: "none", colorSpaceConversion: "none" }).then((img) => {
899
- t.image = img;
900
- t.needsUpdate = true;
901
- }).catch(() => {});
902
- return { texture: t, ready };
903
- }
904
- var lineMat = () => new THREE.ShaderMaterial({
905
- vertexShader: `attribute vec4 im0; attribute vec4 im1; attribute vec4 im2; attribute vec4 im3;
906
- void main(){ gl_Position = projectionMatrix * modelViewMatrix * mat4(im0,im1,im2,im3) * vec4(position,1.0); }`,
907
- fragmentShader: `void main(){ gl_FragColor = vec4(0.13,0.13,0.13,1.0); }`
908
- });
909
- var sharedLineMat = () => new THREE.ShaderMaterial({
910
- vertexShader: `attribute mat4 instanceMatrix; void main(){ gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4(position,1.0); }`,
911
- fragmentShader: `void main(){ gl_FragColor = vec4(0.13,0.13,0.13,1.0); }`
912
- });
913
- var weldLines = (pos) => {
914
- const map = new Map;
915
- const P = [];
916
- const I = [];
917
- for (let i = 0;i < pos.length; i += 3) {
918
- const k = pos[i].toFixed(2) + "," + pos[i + 1].toFixed(2) + "," + pos[i + 2].toFixed(2);
919
- let j = map.get(k);
920
- if (j === undefined) {
921
- j = P.length / 3;
922
- map.set(k, j);
923
- P.push(pos[i], pos[i + 1], pos[i + 2]);
924
- }
925
- I.push(j);
866
+ function commonSub(insts, ids, whole) {
867
+ const path = insts[ids[0]]?.subPath;
868
+ if (!path)
869
+ return;
870
+ let n = path.length;
871
+ for (const id of ids) {
872
+ const p = insts[id].subPath;
873
+ if (!p)
874
+ return;
875
+ let j = 0;
876
+ while (j < n && j < p.length && p[j] === path[j])
877
+ j++;
878
+ n = j;
879
+ if (!n)
880
+ return;
926
881
  }
927
- return { P: new Float32Array(P), I: P.length / 3 < 65536 ? new Uint16Array(I) : new Uint32Array(I) };
928
- };
929
- function createInstancedEdges(pos, im, material = sharedLineMat()) {
930
- return sharedLines(pos, im, material);
882
+ return whole(path[n - 1]) ? undefined : path[n - 1];
931
883
  }
932
- function conditionalLines(pack, entry, which = "all") {
933
- if (which === "all") {
934
- const a = conditionalLines(pack, entry, "body"), b = conditionalLines(pack, entry, "under");
935
- if (!a || !b)
936
- return a ?? b;
937
- const o = new Float32Array(a.length + b.length);
938
- o.set(a);
939
- o.set(b, a.length);
884
+ function instanceBoxes(insts, parts) {
885
+ return insts.map((i) => {
886
+ const b = parts[i.part]?.bbox;
887
+ if (!b)
888
+ return null;
889
+ const m = i.m;
890
+ const o = new Float64Array([Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity]);
891
+ for (let c = 0;c < 8; c++) {
892
+ const x = c & 1 ? b[3] : b[0], y = c & 2 ? b[4] : b[1], z = c & 4 ? b[5] : b[2];
893
+ const w = [m[0] + m[3] * x + m[4] * y + m[5] * z, m[1] + m[6] * x + m[7] * y + m[8] * z, m[2] + m[9] * x + m[10] * y + m[11] * z];
894
+ for (let k = 0;k < 3; k++) {
895
+ if (w[k] < o[k])
896
+ o[k] = w[k];
897
+ if (w[k] > o[k + 3])
898
+ o[k + 3] = w[k];
899
+ }
900
+ }
940
901
  return o;
902
+ });
903
+ }
904
+
905
+ class BoxGrid {
906
+ cells = new Map;
907
+ boxes;
908
+ cell;
909
+ stamp;
910
+ q = 0;
911
+ lo;
912
+ hi;
913
+ constructor(boxes, cell) {
914
+ this.boxes = boxes;
915
+ this.cell = cell;
916
+ this.stamp = new Int32Array(boxes.length);
917
+ this.lo = [Infinity, Infinity, Infinity];
918
+ this.hi = [-Infinity, -Infinity, -Infinity];
919
+ for (const b of boxes)
920
+ if (b)
921
+ for (let k = 0;k < 3; k++) {
922
+ this.lo[k] = Math.min(this.lo[k], b[k]);
923
+ this.hi[k] = Math.max(this.hi[k], b[k + 3]);
924
+ }
941
925
  }
942
- const c = which === "under" ? entry?.condlu : entry?.condl;
943
- if (!c)
944
- return null;
945
- const { arr } = pack;
946
- if (c.raw)
947
- return arr(c.raw);
948
- const pools = [entry.body ? arr(entry.body.pos) : [], entry.under ? arr(entry.under.pos) : [], entry.edges ? arr(entry.edges) : [], c.x ? arr(c.x) : []];
949
- const idx = arr(c.idx);
950
- const out = new Float32Array(idx.length * 3);
951
- const starts = [];
952
- let base = 0;
953
- for (const p of pools) {
954
- starts.push(base);
955
- base += p.length / 3;
926
+ key(i, j, k) {
927
+ return (i + 1024) * 4194304 + (j + 1024) * 2048 + (k + 1024);
956
928
  }
957
- let prev = 0;
958
- for (let i = 0;i < idx.length; i++) {
959
- const z = idx[i];
960
- const j = prev + (z & 1 ? -(z + 1) / 2 : z / 2);
961
- prev = j;
962
- let k = 3;
963
- while (k > 0 && j < starts[k])
964
- k--;
965
- const p = pools[k], o = (j - starts[k]) * 3;
966
- out[i * 3] = p[o];
967
- out[i * 3 + 1] = p[o + 1];
968
- out[i * 3 + 2] = p[o + 2];
929
+ add(id) {
930
+ const b = this.boxes[id];
931
+ if (!b)
932
+ return;
933
+ const c = this.cell;
934
+ for (let i = Math.floor(b[0] / c);i <= Math.floor(b[3] / c); i++)
935
+ for (let j = Math.floor(b[1] / c);j <= Math.floor(b[4] / c); j++)
936
+ for (let k = Math.floor(b[2] / c);k <= Math.floor(b[5] / c); k++) {
937
+ const key = this.key(i, j, k);
938
+ let l = this.cells.get(key);
939
+ if (!l)
940
+ this.cells.set(key, l = []);
941
+ l.push(id);
942
+ }
943
+ }
944
+ inside(p, self) {
945
+ const c = this.cell;
946
+ const l = this.cells.get(this.key(Math.floor(p[0] / c), Math.floor(p[1] / c), Math.floor(p[2] / c)));
947
+ if (!l)
948
+ return false;
949
+ for (const id of l) {
950
+ if (id === self)
951
+ continue;
952
+ const b = this.boxes[id];
953
+ if (p[0] > b[0] && p[0] < b[3] && p[1] > b[1] && p[1] < b[4] && p[2] > b[2] && p[2] < b[5])
954
+ return true;
955
+ }
956
+ return false;
957
+ }
958
+ hits(p, d, self, eps = 0.5) {
959
+ const c = this.cell, q = ++this.q;
960
+ let i = Math.floor(p[0] / c), j = Math.floor(p[1] / c), k = Math.floor(p[2] / c);
961
+ const step = d.map((v) => v > 0 ? 1 : v < 0 ? -1 : 0);
962
+ const idx = [i, j, k];
963
+ const tMax = [0, 1, 2].map((a) => d[a] === 0 ? Infinity : ((idx[a] + (d[a] > 0 ? 1 : 0)) * c - p[a]) / d[a]);
964
+ const tDelta = [0, 1, 2].map((a) => d[a] === 0 ? Infinity : c / Math.abs(d[a]));
965
+ const bound = [0, 1, 2].map((a) => d[a] > 0 ? Math.floor(this.hi[a] / c) + 1 : d[a] < 0 ? Math.floor(this.lo[a] / c) - 1 : 0);
966
+ for (let n = 0;n < 4096; n++) {
967
+ const l = this.cells.get(this.key(idx[0], idx[1], idx[2]));
968
+ if (l)
969
+ for (const id of l) {
970
+ if (id === self || this.stamp[id] === q)
971
+ continue;
972
+ this.stamp[id] = q;
973
+ if (rayBox(p, d, this.boxes[id], eps))
974
+ return true;
975
+ }
976
+ const a = tMax[0] < tMax[1] ? tMax[0] < tMax[2] ? 0 : 2 : tMax[1] < tMax[2] ? 1 : 2;
977
+ idx[a] += step[a];
978
+ tMax[a] += tDelta[a];
979
+ if (step[a] === 0 || idx[a] === bound[a])
980
+ return false;
981
+ }
982
+ return false;
969
983
  }
970
- return out;
971
984
  }
972
- var condLineMat = () => new THREE.ShaderMaterial({
973
- uniforms: { ldrViewProj: { value: new THREE.Matrix4 } },
974
- vertexShader: `uniform mat4 ldrViewProj; attribute mat4 instanceMatrix; attribute vec3 ldrP1; attribute vec3 ldrC0; attribute vec3 ldrC1; attribute float ldrSide;
975
- void main(){
976
- mat4 mvp = ldrViewProj * instanceMatrix;
977
- vec4 a = mvp * vec4(position, 1.0), b = mvp * vec4(ldrP1, 1.0), c0 = mvp * vec4(ldrC0, 1.0), c1 = mvp * vec4(ldrC1, 1.0);
978
- vec2 A = a.xy / a.w, B = b.xy / b.w, C0 = c0.xy / c0.w, C1 = c1.xy / c1.w, d = B - A;
979
- float s0 = d.x * (C0.y - A.y) - d.y * (C0.x - A.x), s1 = d.x * (C1.y - A.y) - d.y * (C1.x - A.x);
980
- gl_Position = s0 * s1 >= 0.0 ? (ldrSide > 0.5 ? b : a) : vec4(2.0, 2.0, 2.0, 1.0);
981
- }`,
982
- fragmentShader: `void main(){ gl_FragColor = vec4(0.13,0.13,0.13,1.0); }`
983
- });
984
- function conditionalLineVisible(cond, i, mvp) {
985
- const e = mvp.elements;
986
- const pr = (o) => {
987
- const x = cond[o], y = cond[o + 1], z = cond[o + 2];
988
- const w = e[3] * x + e[7] * y + e[11] * z + e[15];
989
- return [(e[0] * x + e[4] * y + e[8] * z + e[12]) / w, (e[1] * x + e[5] * y + e[9] * z + e[13]) / w];
990
- };
991
- const o = i * 12;
992
- const A = pr(o), B = pr(o + 3), C0 = pr(o + 6), C1 = pr(o + 9);
993
- const dx = B[0] - A[0], dy = B[1] - A[1];
994
- const s0 = dx * (C0[1] - A[1]) - dy * (C0[0] - A[0]), s1 = dx * (C1[1] - A[1]) - dy * (C1[0] - A[0]);
995
- return s0 * s1 >= 0;
985
+ function rayBox(p, d, b, eps) {
986
+ let t0 = 0.000001, t1 = Infinity;
987
+ for (let a = 0;a < 3; a++) {
988
+ const lo = b[a] + eps, hi = b[a + 3] - eps;
989
+ if (d[a] === 0) {
990
+ if (p[a] <= lo || p[a] >= hi)
991
+ return false;
992
+ continue;
993
+ }
994
+ let ta = (lo - p[a]) / d[a], tb = (hi - p[a]) / d[a];
995
+ if (ta > tb)
996
+ [ta, tb] = [tb, ta];
997
+ if (ta > t0)
998
+ t0 = ta;
999
+ if (tb < t1)
1000
+ t1 = tb;
1001
+ if (t0 > t1)
1002
+ return false;
1003
+ }
1004
+ return true;
996
1005
  }
997
- function createInstancedConditionalEdges(cond, im, material = condLineMat()) {
998
- return condEdges(condBuffers(cond), im, material);
1006
+ function boxVisibility(grid, id, d, n = 3) {
1007
+ const b = grid.boxes[id];
1008
+ let vis = 0, tot = 0;
1009
+ for (let a = 0;a < 3; a++)
1010
+ for (const side of [-1, 1]) {
1011
+ const cos = side * d[a];
1012
+ if (cos <= 0.02)
1013
+ continue;
1014
+ const u = (a + 1) % 3, v = (a + 2) % 3;
1015
+ const area = (b[u + 3] - b[u]) * (b[v + 3] - b[v]);
1016
+ if (area <= 0)
1017
+ continue;
1018
+ const w = area * cos / (n * n);
1019
+ const p = [0, 0, 0], q = [0, 0, 0];
1020
+ p[a] = side > 0 ? b[a + 3] + 0.25 : b[a] - 0.25;
1021
+ q[a] = side > 0 ? b[a + 3] + 1 : b[a] - 1;
1022
+ for (let s = 0;s < n; s++)
1023
+ for (let t = 0;t < n; t++) {
1024
+ p[u] = q[u] = b[u] + (s + 0.5) / n * (b[u + 3] - b[u]);
1025
+ p[v] = q[v] = b[v] + (t + 0.5) / n * (b[v + 3] - b[v]);
1026
+ if (grid.inside(q, id))
1027
+ continue;
1028
+ tot += w;
1029
+ if (!grid.hits(p, d, id))
1030
+ vis += w;
1031
+ }
1032
+ }
1033
+ return tot ? vis / tot : -1;
999
1034
  }
1000
- function condBuffers(cond) {
1001
- const n = Math.floor(cond.length / 12);
1002
- const buf = new Float32Array(n * 24), side = new Float32Array(n * 2);
1003
- for (let l = 0;l < n; l++) {
1004
- for (let k = 0;k < 12; k++) {
1005
- const v = cond[l * 12 + k];
1006
- buf[l * 24 + k] = v;
1007
- buf[l * 24 + 12 + k] = v;
1035
+ var angle = (a, b) => Math.acos(Math.max(-1, Math.min(1, a[0] * b[0] + a[1] * b[1] + a[2] * b[2]))) / deg;
1036
+ var spread = (l, max) => l.length <= max ? l : Array.from({ length: max }, (_, i) => l[Math.floor((i + 0.5) * l.length / max)]);
1037
+ function planStepViews(insts, parts, stepOf, nSteps, o = {}) {
1038
+ const boxes = instanceBoxes(insts, parts);
1039
+ const byStep = Array.from({ length: nSteps }, () => []);
1040
+ for (let k = 0;k < insts.length; k++)
1041
+ if (boxes[k])
1042
+ byStep[stepOf[k]]?.push(k);
1043
+ let nBoxed = 0;
1044
+ for (const b of boxes)
1045
+ if (b)
1046
+ nBoxed++;
1047
+ const isoCache = new Map;
1048
+ const isoParts = (u) => {
1049
+ let l = isoCache.get(u);
1050
+ if (!l) {
1051
+ l = [];
1052
+ for (let k = 0;k < insts.length; k++)
1053
+ if (boxes[k] && insts[k].subPath?.includes(u))
1054
+ l.push(k);
1055
+ isoCache.set(u, l);
1008
1056
  }
1009
- side[l * 2 + 1] = 1;
1057
+ return l;
1058
+ };
1059
+ const subParts = new Map;
1060
+ for (let k = 0;k < insts.length; k++) {
1061
+ const u = insts[k].sub;
1062
+ if (u !== undefined && boxes[k])
1063
+ (subParts.get(u) ?? subParts.set(u, []).get(u)).push(k);
1010
1064
  }
1011
- return { ib: new THREE.InterleavedBuffer(buf, 12), side: new THREE.BufferAttribute(side, 1) };
1012
- }
1013
- function condEdges({ ib, side }, im, material) {
1014
- const g = new THREE.InstancedBufferGeometry;
1015
- g.setAttribute("position", new THREE.InterleavedBufferAttribute(ib, 3, 0));
1016
- g.setAttribute("ldrP1", new THREE.InterleavedBufferAttribute(ib, 3, 3));
1017
- g.setAttribute("ldrC0", new THREE.InterleavedBufferAttribute(ib, 3, 6));
1018
- g.setAttribute("ldrC1", new THREE.InterleavedBufferAttribute(ib, 3, 9));
1019
- g.setAttribute("ldrSide", side);
1020
- g.setAttribute("instanceMatrix", im.instanceMatrix);
1021
- g.instanceCount = im.count;
1022
- const l = new THREE.LineSegments(g, material);
1023
- l.frustumCulled = false;
1024
- l.name = "ldrCondLines";
1025
- l.onBeforeRender = (_r, _s, cam, _g, mat) => {
1026
- const u = mat.uniforms?.ldrViewProj;
1027
- if (!u)
1028
- return;
1029
- l.modelViewMatrix.multiplyMatrices(cam.matrixWorldInverse, l.matrixWorld);
1030
- u.value.multiplyMatrices(cam.projectionMatrix, l.modelViewMatrix);
1031
- mat.uniformsNeedUpdate = true;
1065
+ let size = 0;
1066
+ for (const b of boxes)
1067
+ if (b)
1068
+ size = Math.max(size, b[3] - b[0], b[4] - b[1], b[5] - b[2]);
1069
+ let ext = 0;
1070
+ for (const b of boxes)
1071
+ if (b)
1072
+ ext = Math.max(ext, Math.abs(b[0]), Math.abs(b[2]), Math.abs(b[3]), Math.abs(b[5]), Math.abs(b[1]), Math.abs(b[4]));
1073
+ const grid = new BoxGrid(boxes, Math.max(20, Math.min(160, size || 40), ext / 1000));
1074
+ const def = viewDir(o.azimuth ?? 45, o.elevation ?? 30), minVis = o.minVis ?? MIN_VIS, reorient = o.reorient ?? REORIENT, turn = o.turnCost ?? 0.002;
1075
+ const above = [], below = [];
1076
+ for (let az = 0;az < 360; az += 45) {
1077
+ for (const el of [15, 30, 50])
1078
+ above.push(viewDir(az, el));
1079
+ below.push(viewDir(az, -30));
1080
+ }
1081
+ const built = [Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity];
1082
+ const views = [];
1083
+ let prevMain = def;
1084
+ const prevIso = new Map;
1085
+ const local = new Map;
1086
+ const localOf = (u) => {
1087
+ let l = local.get(u);
1088
+ if (l)
1089
+ return l;
1090
+ const k0 = isoParts(u)[0];
1091
+ const i0 = insts[k0];
1092
+ const P = i0.subMats?.[i0.subPath.indexOf(u)] ?? null;
1093
+ const inv = P ? invert(P) : null;
1094
+ const lb = new Array(insts.length).fill(null);
1095
+ const own = isoParts(u);
1096
+ const loc = instanceBoxes(own.map((k) => ({ part: insts[k].part, m: inv ? mul(inv, insts[k].m) : insts[k].m })), parts);
1097
+ own.forEach((k, j) => lb[k] = loc[j]);
1098
+ local.set(u, l = { boxes: lb, P: P && inv ? [...P] : [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1] });
1099
+ return l;
1100
+ };
1101
+ let g = grid;
1102
+ const score = (ids, d) => {
1103
+ let mn = 1, sum = 0, n = 0;
1104
+ for (const id of ids) {
1105
+ const v = boxVisibility(g, id, d);
1106
+ if (v < 0)
1107
+ continue;
1108
+ mn = Math.min(mn, v);
1109
+ sum += v;
1110
+ n++;
1111
+ }
1112
+ return { mn: n ? mn : 1, mean: n ? sum / n : 1 };
1113
+ };
1114
+ const pref = (d) => {
1115
+ const h = Math.hypot(d[0], d[2]) || 1, el = Math.asin(Math.max(-1, Math.min(1, -d[1]))) / deg;
1116
+ return Math.abs(d[0] / h * (d[2] / h)) + 0.5 * Math.max(0, -d[2] / h) - Math.abs(el - 30) / 90;
1117
+ };
1118
+ const next = () => {
1119
+ const s = views.length, add = byStep[s];
1120
+ for (const id of add) {
1121
+ grid.add(id);
1122
+ const b = boxes[id];
1123
+ for (let k = 0;k < 3; k++) {
1124
+ built[k] = Math.min(built[k], b[k]);
1125
+ built[k + 3] = Math.max(built[k + 3], b[k + 3]);
1126
+ }
1127
+ }
1128
+ const iso = add.length ? commonSub(insts, add, (u) => isoParts(u).length >= nBoxed) : undefined;
1129
+ let isoBox = null;
1130
+ g = grid;
1131
+ if (iso !== undefined) {
1132
+ const L = localOf(iso);
1133
+ const own = isoParts(iso).filter((id) => stepOf[id] <= s);
1134
+ g = new BoxGrid(L.boxes, grid.cell);
1135
+ for (const id of own)
1136
+ g.add(id);
1137
+ isoBox = [Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity];
1138
+ for (const id of own) {
1139
+ const b = L.boxes[id];
1140
+ for (let k = 0;k < 3; k++) {
1141
+ isoBox[k] = Math.min(isoBox[k], b[k]);
1142
+ isoBox[k + 3] = Math.max(isoBox[k + 3], b[k + 3]);
1143
+ }
1144
+ }
1145
+ }
1146
+ const prev = iso !== undefined ? prevIso.get(iso) ?? def : prevMain, ref = isoBox ?? built;
1147
+ const ids = spread(add, 24);
1148
+ let dir = o.fixed?.(s) ?? null, r = dir ? score(ids, dir) : score(ids, prev);
1149
+ if (!dir) {
1150
+ dir = prev;
1151
+ if (r.mean >= minVis && prev !== def) {
1152
+ const v = score(ids, def);
1153
+ if (v.mean >= minVis) {
1154
+ dir = def;
1155
+ r = v;
1156
+ }
1157
+ }
1158
+ if (r.mean < minVis) {
1159
+ let best = -Infinity;
1160
+ const ex = [ref[3] - ref[0], ref[4] - ref[1], ref[5] - ref[2]], area = (d) => Math.abs(d[0]) * ex[1] * ex[2] + Math.abs(d[1]) * ex[0] * ex[2] + Math.abs(d[2]) * ex[0] * ex[1];
1161
+ let amax = 0;
1162
+ for (const d of above)
1163
+ amax = Math.max(amax, area(d));
1164
+ const consider = (cands) => {
1165
+ for (const d of cands) {
1166
+ const v = score(ids, d);
1167
+ const sc = v.mean + 0.3 * v.mn + 0.25 * pref(d) + 0.15 * (amax ? area(d) / amax : 1) - turn * angle(prev, d);
1168
+ if (sc > best) {
1169
+ best = sc;
1170
+ dir = d;
1171
+ r = v;
1172
+ }
1173
+ }
1174
+ };
1175
+ consider([prev, ...above]);
1176
+ if (r.mean < reorient)
1177
+ consider(below);
1178
+ }
1179
+ }
1180
+ const diag = (b) => Math.hypot(b[3] - b[0], b[4] - b[1], b[5] - b[2]);
1181
+ let fb = built;
1182
+ const sub = add.length ? insts[add[0]].sub : undefined;
1183
+ if (isoBox)
1184
+ fb = isoBox;
1185
+ else if (sub !== undefined && add.every((id) => insts[id].sub === sub)) {
1186
+ const sb = [Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity];
1187
+ for (const id of subParts.get(sub) ?? []) {
1188
+ if (stepOf[id] > s)
1189
+ continue;
1190
+ const b = boxes[id];
1191
+ for (let k = 0;k < 3; k++) {
1192
+ sb[k] = Math.min(sb[k], b[k]);
1193
+ sb[k + 3] = Math.max(sb[k + 3], b[k + 3]);
1194
+ }
1195
+ }
1196
+ if (isFinite(sb[0]) && diag(sb) * 2.5 < diag(built)) {
1197
+ const g = diag(sb) * 0.35;
1198
+ fb = sb.map((v, k) => k < 3 ? v - g : v + g);
1199
+ }
1200
+ }
1201
+ const target = isFinite(fb[0]) ? [(fb[0] + fb[3]) / 2, (fb[1] + fb[4]) / 2, (fb[2] + fb[5]) / 2] : [0, 0, 0];
1202
+ views.push({ dir, target, radius: isFinite(fb[0]) ? diag(fb) / 2 : 1, minVis: r.mn, meanVis: r.mean, below: dir[1] > 0, ...iso !== undefined ? { isolate: iso, frame: localOf(iso).P } : {} });
1203
+ if (iso !== undefined)
1204
+ prevIso.set(iso, dir);
1205
+ else
1206
+ prevMain = dir;
1207
+ };
1208
+ return {
1209
+ stepCount: nSteps,
1210
+ view(step) {
1211
+ step = Math.max(0, Math.min(nSteps - 1, step));
1212
+ while (views.length <= step)
1213
+ next();
1214
+ return views[step];
1215
+ }
1032
1216
  };
1033
- return l;
1034
- }
1035
- function sharedLines(pos, im, material = sharedLineMat()) {
1036
- const { P, I } = weldLines(pos);
1037
- const g = new THREE.InstancedBufferGeometry;
1038
- g.setAttribute("position", new THREE.BufferAttribute(P, 3));
1039
- g.setIndex(new THREE.BufferAttribute(I, 1));
1040
- g.setAttribute("instanceMatrix", im.instanceMatrix);
1041
- g.instanceCount = im.count;
1042
- const l = new THREE.LineSegments(g, material);
1043
- l.frustumCulled = false;
1044
- return l;
1045
- }
1046
- function instancedLines(pos, mats, count) {
1047
- const g = new THREE.InstancedBufferGeometry;
1048
- g.setAttribute("position", new THREE.BufferAttribute(pos, 3));
1049
- const ib = new THREE.InstancedInterleavedBuffer(mats, 16);
1050
- for (let i = 0;i < 4; i++)
1051
- g.setAttribute("im" + i, new THREE.InterleavedBufferAttribute(ib, 4, i * 4));
1052
- g.instanceCount = count;
1053
- const l = new THREE.LineSegments(g, lineMat());
1054
- l.frustumCulled = false;
1055
- return l;
1056
- }
1057
- function writeM4(t, o, m, mo = 0) {
1058
- t[o] = m[mo + 3];
1059
- t[o + 1] = m[mo + 6];
1060
- t[o + 2] = m[mo + 9];
1061
- t[o + 3] = 0;
1062
- t[o + 4] = m[mo + 4];
1063
- t[o + 5] = m[mo + 7];
1064
- t[o + 6] = m[mo + 10];
1065
- t[o + 7] = 0;
1066
- t[o + 8] = m[mo + 5];
1067
- t[o + 9] = m[mo + 8];
1068
- t[o + 10] = m[mo + 11];
1069
- t[o + 11] = 0;
1070
- t[o + 12] = m[mo];
1071
- t[o + 13] = m[mo + 1];
1072
- t[o + 14] = m[mo + 2];
1073
- t[o + 15] = 1;
1074
1217
  }
1075
- function newIM(g, mat, n) {
1076
- const im = new THREE.InstancedMesh(g, mat, 0);
1077
- im.instanceMatrix = new THREE.InstancedBufferAttribute(new Float32Array(n * 16), 16);
1078
- im.count = n;
1079
- return im;
1218
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/render.ts
1219
+ import * as THREE from "three";
1220
+
1221
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/pack-io.ts
1222
+ import { decompress } from "fzstd";
1223
+ async function decompressPack(data) {
1224
+ const u = data instanceof Uint8Array ? data : new Uint8Array(data);
1225
+ const own = (o) => o.buffer.slice(o.byteOffset, o.byteOffset + o.byteLength);
1226
+ if (u[0] === 40 && u[1] === 181 && u[2] === 47 && u[3] === 253)
1227
+ return own(decompress(u));
1228
+ if (u[0] === 31 && u[1] === 139)
1229
+ return new Response(new Blob([u]).stream().pipeThrough(new DecompressionStream("gzip"))).arrayBuffer();
1230
+ return own(u);
1080
1231
  }
1081
- function fillInstances(im, ids, insts, color) {
1082
- const M = im.instanceMatrix.array;
1083
- const C = new Float32Array(ids.length * 3);
1084
- for (let k = 0;k < ids.length; k++) {
1085
- const it = insts[ids[k]];
1086
- writeM4(M, k * 16, it.m);
1087
- color(it.color).toArray(C, k * 3);
1088
- }
1089
- im.instanceColor = new THREE.InstancedBufferAttribute(C, 3);
1232
+ function decodePack(buf) {
1233
+ const hl = new DataView(buf).getUint32(0, true);
1234
+ const header = JSON.parse(new TextDecoder().decode(new Uint8Array(buf, 4, hl)));
1235
+ const base = 4 + hl;
1236
+ const arr = (r) => r && (r[2] === "f32" ? new Float32Array(buf, base + r[0], r[1]) : r[2] === "u16" ? new Uint16Array(buf, base + r[0], r[1]) : r[2] === "u8" ? new Uint8Array(buf, base + r[0], r[1]) : new Uint32Array(buf, base + r[0], r[1]));
1237
+ return { header, arr, bytes: buf.byteLength, buffer: buf };
1090
1238
  }
1239
+
1240
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/cull.ts
1091
1241
  var upright = (m, o = 0) => Math.abs(m[o + 7] - 1) < 0.001 && Math.abs(m[o + 4]) < 0.001 && Math.abs(m[o + 10]) < 0.001;
1092
1242
  var prepCache = new WeakMap;
1093
1243
  function prepPart(H, part) {
@@ -1133,76 +1283,84 @@ function mul12To(a, b, bo, w, ao = 0) {
1133
1283
  w[3 + i * 3 + j] = a[ao + 3 + i * 3] * b[bo + 3 + j] + a[ao + 4 + i * 3] * b[bo + 6 + j] + a[ao + 5 + i * 3] * b[bo + 9 + j];
1134
1284
  }
1135
1285
  var det12 = (m) => m[3] * (m[7] * m[11] - m[8] * m[10]) - m[4] * (m[6] * m[11] - m[8] * m[9]) + m[5] * (m[6] * m[10] - m[7] * m[9]);
1136
- var cellKey = (lv2, cx, cz) => lv2 < -1048576 || lv2 >= 1048576 || cx < -32768 || cx >= 32768 || cz < -32768 || cz >= 32768 ? -1 : (lv2 + 1048576) * 4294967296 + (cx + 32768) * 65536 + (cz + 32768);
1137
- var topKey = (x, y, z) => {
1138
- const rx = Math.round(x), ry = Math.round(y), rz = Math.round(z);
1139
- return rx < -131072 || rx >= 131072 || ry < -65536 || ry >= 65536 || rz < -131072 || rz >= 131072 ? -1 : (rx + 131072) * 34359738368 + (ry + 65536) * 262144 + (rz + 131072);
1140
- };
1286
+ var BIG = 1073741824;
1141
1287
 
1142
- class NumTable {
1143
- keys;
1288
+ class Int3Table {
1289
+ a;
1290
+ b;
1291
+ c;
1144
1292
  vals;
1293
+ used;
1145
1294
  mask;
1146
1295
  size = 0;
1147
1296
  constructor(cap = 1024) {
1148
1297
  let n = 1024;
1149
1298
  while (n < cap * 2)
1150
1299
  n *= 2;
1151
- this.keys = new Float64Array(n).fill(-1);
1300
+ this.a = new Int32Array(n);
1301
+ this.b = new Int32Array(n);
1302
+ this.c = new Int32Array(n);
1152
1303
  this.vals = new Int32Array(n);
1304
+ this.used = new Uint8Array(n);
1153
1305
  this.mask = n - 1;
1154
1306
  }
1155
- slot(k) {
1156
- const lo = k >>> 0, hi = k / 4294967296 >>> 0;
1157
- let h = Math.imul(lo ^ Math.imul(hi, 2654435761), 2246822507);
1307
+ slot(x, y, z) {
1308
+ let h = Math.imul(x, 2654435761) ^ Math.imul(y, 2246822507) ^ Math.imul(z, 3266489909);
1158
1309
  h ^= h >>> 15;
1310
+ h = Math.imul(h, 739982445);
1311
+ h ^= h >>> 12;
1159
1312
  return h & this.mask;
1160
1313
  }
1161
- get(k) {
1162
- const K = this.keys;
1163
- let i = this.slot(k);
1314
+ get(x, y, z) {
1315
+ let i = this.slot(x, y, z);
1316
+ const U = this.used, A = this.a, B = this.b, C = this.c;
1164
1317
  for (;; ) {
1165
- const x = K[i];
1166
- if (x === k)
1167
- return this.vals[i];
1168
- if (x === -1)
1318
+ if (!U[i])
1169
1319
  return -1;
1320
+ if (A[i] === x && B[i] === y && C[i] === z)
1321
+ return this.vals[i];
1170
1322
  i = i + 1 & this.mask;
1171
1323
  }
1172
1324
  }
1173
- put(k, v) {
1174
- if ((this.size + 1) * 2 > this.keys.length)
1325
+ put(x, y, z, v) {
1326
+ if ((this.size + 1) * 2 > this.used.length)
1175
1327
  this.grow();
1176
- const K = this.keys;
1177
- let i = this.slot(k);
1328
+ let i = this.slot(x, y, z);
1329
+ const U = this.used, A = this.a, B = this.b, C = this.c;
1178
1330
  for (;; ) {
1179
- const x = K[i];
1180
- if (x === k) {
1181
- const o = this.vals[i];
1182
- this.vals[i] = v;
1183
- return o;
1184
- }
1185
- if (x === -1) {
1186
- K[i] = k;
1331
+ if (!U[i]) {
1332
+ U[i] = 1;
1333
+ A[i] = x;
1334
+ B[i] = y;
1335
+ C[i] = z;
1187
1336
  this.vals[i] = v;
1188
1337
  this.size++;
1189
1338
  return -1;
1190
1339
  }
1340
+ if (A[i] === x && B[i] === y && C[i] === z) {
1341
+ const o = this.vals[i];
1342
+ this.vals[i] = v;
1343
+ return o;
1344
+ }
1191
1345
  i = i + 1 & this.mask;
1192
1346
  }
1193
1347
  }
1194
1348
  grow() {
1195
- const ok = this.keys, ov = this.vals;
1196
- const n = ok.length * 2;
1197
- this.keys = new Float64Array(n).fill(-1);
1349
+ const { a, b, c, vals, used } = this;
1350
+ const n = used.length * 2;
1351
+ this.a = new Int32Array(n);
1352
+ this.b = new Int32Array(n);
1353
+ this.c = new Int32Array(n);
1198
1354
  this.vals = new Int32Array(n);
1355
+ this.used = new Uint8Array(n);
1199
1356
  this.mask = n - 1;
1200
1357
  this.size = 0;
1201
- for (let i = 0;i < ok.length; i++)
1202
- if (ok[i] !== -1)
1203
- this.put(ok[i], ov[i]);
1358
+ for (let i = 0;i < used.length; i++)
1359
+ if (used[i])
1360
+ this.put(a[i], b[i], c[i], vals[i]);
1204
1361
  }
1205
1362
  }
1363
+ var inRange = (x, y, z) => x > -BIG && x < BIG && y > -BIG && y < BIG && z > -BIG && z < BIG;
1206
1364
  var STEP_NEVER = 2147483647;
1207
1365
  function forEachStud(insts, H, fn) {
1208
1366
  const w = new Float64Array(12);
@@ -1222,7 +1380,7 @@ function forEachStud(insts, H, fn) {
1222
1380
  function cullCore(insts, H, steps) {
1223
1381
  const CELL = 40;
1224
1382
  const rx0 = [], rx1 = [], rz0 = [], rz1 = [], rInst = [], rPrep = [], rBx = [], rBz = [];
1225
- const cells = new NumTable(insts.length * 2);
1383
+ const cells = new Int3Table(insts.length * 2);
1226
1384
  const nextE = [], rectE = [];
1227
1385
  for (let idx = 0;idx < insts.length; idx++) {
1228
1386
  const it = insts[idx];
@@ -1257,113 +1415,496 @@ function cullCore(insts, H, steps) {
1257
1415
  const lv2 = Math.round((m[1] + b[4]) * 2);
1258
1416
  for (let cx = Math.floor(x0 / CELL);cx <= Math.floor(x1 / CELL); cx++)
1259
1417
  for (let cz = Math.floor(z0 / CELL);cz <= Math.floor(z1 / CELL); cz++) {
1260
- const k = cellKey(lv2, cx, cz);
1261
- if (k < 0)
1418
+ if (!inRange(lv2, cx, cz))
1262
1419
  continue;
1263
1420
  const e = rectE.length;
1264
1421
  rectE.push(ri);
1265
- nextE.push(cells.put(k, e));
1422
+ nextE.push(cells.put(lv2, cx, cz, e));
1423
+ }
1424
+ }
1425
+ const SX = [0, 5, -5, 5, -5], SZ = [0, 5, 5, -5, -5];
1426
+ let kl = NaN, kx = NaN, kz = NaN, ke = -1;
1427
+ const coverStep = (x, y, z, self) => {
1428
+ const l2 = Math.round(y * 2), gx = Math.floor(x / CELL), gz = Math.floor(z / CELL);
1429
+ if (!inRange(l2, gx, gz))
1430
+ return STEP_NEVER;
1431
+ let best = STEP_NEVER;
1432
+ if (l2 !== kl || gx !== kx || gz !== kz) {
1433
+ kl = l2;
1434
+ kx = gx;
1435
+ kz = gz;
1436
+ ke = cells.get(l2, gx, gz);
1437
+ }
1438
+ for (let e = ke;e >= 0; e = nextE[e]) {
1439
+ const ri = rectE[e];
1440
+ if (rInst[ri] === self || !(x - 6 >= rx0[ri] - 0.5 && x + 6 <= rx1[ri] + 0.5 && z - 6 >= rz0[ri] - 0.5 && z + 6 <= rz1[ri] + 0.5))
1441
+ continue;
1442
+ const m = insts[rInst[ri]].m;
1443
+ const pp = rPrep[ri];
1444
+ const bx = rBx[ri], bz = rBz[ri];
1445
+ const dx = x - m[0], dy = y - m[1], dz = z - m[2];
1446
+ const lx = m[3] * dx + m[6] * dy + m[9] * dz, lz = m[5] * dx + m[8] * dy + m[11] * dz;
1447
+ const { nx, nz, mask: bits } = pp;
1448
+ let ok = true;
1449
+ for (let s = 0;s < 5; s++) {
1450
+ const ca = Math.floor((lx + SX[s] - bx) / 20), cb = Math.floor((lz + SZ[s] - bz) / 20);
1451
+ if (ca < 0 || cb < 0 || ca >= nx || cb >= nz || bits[ca * nz + cb] !== 1) {
1452
+ ok = false;
1453
+ break;
1454
+ }
1266
1455
  }
1456
+ if (ok) {
1457
+ if (!steps)
1458
+ return 0;
1459
+ const st = steps[rInst[ri]];
1460
+ if (st < best)
1461
+ best = st;
1462
+ }
1463
+ }
1464
+ return best;
1465
+ };
1466
+ let nStuds = 0;
1467
+ for (const it of insts) {
1468
+ const pp = prepPart(H, it.part);
1469
+ if (pp)
1470
+ nStuds += pp.nStuds;
1471
+ }
1472
+ const studHidden = new Uint8Array(nStuds), studUp = new Uint8Array(nStuds);
1473
+ const tops = new Int3Table(nStuds);
1474
+ let studsHidden = 0;
1475
+ const studHideStep = steps ? new Int32Array(nStuds).fill(STEP_NEVER) : undefined;
1476
+ for (let idx = 0, j = 0;idx < insts.length; idx++) {
1477
+ const it = insts[idx];
1478
+ const pp = prepPart(H, it.part);
1479
+ if (!pp)
1480
+ continue;
1481
+ const m = it.m, S = pp.studM;
1482
+ const m0 = m[0], m1 = m[1], m2 = m[2], m3 = m[3], m4 = m[4], m5 = m[5], m6 = m[6], m7 = m[7], m8 = m[8], m9 = m[9], m10 = m[10], m11 = m[11];
1483
+ for (let s = 0;s < pp.nStuds; s++, j++) {
1484
+ const o = s * 12;
1485
+ const b4 = S[o + 4], b7 = S[o + 7], b10 = S[o + 10];
1486
+ if (!(Math.abs(m6 * b4 + m7 * b7 + m8 * b10 - 1) < 0.001 && Math.abs(m3 * b4 + m4 * b7 + m5 * b10) < 0.001 && Math.abs(m9 * b4 + m10 * b7 + m11 * b10) < 0.001))
1487
+ continue;
1488
+ studUp[j] = 1;
1489
+ const b0 = S[o], b1 = S[o + 1], b2 = S[o + 2];
1490
+ const x = m0 + m3 * b0 + m4 * b1 + m5 * b2, y = m1 + m6 * b0 + m7 * b1 + m8 * b2, z = m2 + m9 * b0 + m10 * b1 + m11 * b2;
1491
+ const cs = coverStep(x, y, z, idx);
1492
+ if (cs !== STEP_NEVER) {
1493
+ studHidden[j] = 1;
1494
+ studsHidden++;
1495
+ if (studHideStep)
1496
+ studHideStep[j] = cs;
1497
+ }
1498
+ const rx = Math.round(x), ry = Math.round(y), rz = Math.round(z);
1499
+ if (!inRange(rx, ry, rz))
1500
+ continue;
1501
+ if (!steps) {
1502
+ tops.put(rx, ry, rz, 1);
1503
+ continue;
1504
+ }
1505
+ const st = steps[idx], t = tops.get(rx, ry, rz);
1506
+ if (t < 0 || st < t)
1507
+ tops.put(rx, ry, rz, st);
1508
+ }
1509
+ }
1510
+ const underHidden = new Uint8Array(insts.length);
1511
+ const underHideStep = steps ? new Int32Array(insts.length).fill(STEP_NEVER) : undefined;
1512
+ for (let idx = 0;idx < insts.length; idx++) {
1513
+ const it = insts[idx];
1514
+ const p = H.parts[it.part];
1515
+ if (!p || !p.under || !upright(it.m))
1516
+ continue;
1517
+ const b = p.bbox;
1518
+ const nx = Math.round((b[3] - b[0]) / 20), nz = Math.round((b[5] - b[2]) / 20);
1519
+ if (!nx || !nz || nx * nz > 4096)
1520
+ continue;
1521
+ const m = it.m;
1522
+ let all = true, at = 0;
1523
+ for (let a = 0;a < nx && all; a++)
1524
+ for (let c = 0;c < nz; c++) {
1525
+ const lx = b[0] + 10 + 20 * a, lz = b[2] + 10 + 20 * c;
1526
+ const x = m[0] + m[3] * lx + m[5] * lz, z = m[2] + m[9] * lx + m[11] * lz;
1527
+ const rx = Math.round(x), ry = Math.round(m[1] + b[4]), rz = Math.round(z);
1528
+ const t = inRange(rx, ry, rz) ? tops.get(rx, ry, rz) : -1;
1529
+ if (t < 0) {
1530
+ all = false;
1531
+ break;
1532
+ }
1533
+ if (t > at)
1534
+ at = t;
1535
+ }
1536
+ if (all) {
1537
+ underHidden[idx] = 1;
1538
+ if (underHideStep)
1539
+ underHideStep[idx] = at;
1540
+ }
1541
+ }
1542
+ return { nStuds, studHidden, studUp, underHidden, studsHidden, studHideStep, underHideStep };
1543
+ }
1544
+ function sceneInstances(instances, H, useTex) {
1545
+ const pick = (i) => useTex && i.texPart && H.parts[i.texPart] ? i.texPart : i.part;
1546
+ const all = instances.map((i) => ({ part: pick(i), color: String(i.color), m: i.m, steps: i.steps }));
1547
+ const keys = all.map((i) => stepKey(i.steps));
1548
+ const uniq = [...new Set(keys)].sort();
1549
+ const rank = new Map(uniq.map((k, j) => [k, j]));
1550
+ return { all, stepOf: keys.map((k) => rank.get(k)), nSteps: uniq.length };
1551
+ }
1552
+ function precomputeCull(instances, H, useTex = true) {
1553
+ const s = sceneInstances(instances, H, useTex);
1554
+ return cullCore(s.all, H, s.nSteps > 1 ? s.stepOf : undefined);
1555
+ }
1556
+
1557
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/render.ts
1558
+ async function loadPack(url) {
1559
+ const res = await fetch(url);
1560
+ if (!res.ok)
1561
+ throw new Error(`ldr: ${res.status} fetching ${url}`);
1562
+ return decodePack(await decompressPack(await res.arrayBuffer()));
1563
+ }
1564
+ var toI8 = (a) => {
1565
+ const o = new Int8Array(a.length);
1566
+ for (let i = 0;i < a.length; i++)
1567
+ o[i] = Math.round(Math.max(-1, Math.min(1, a[i])) * 127);
1568
+ return o;
1569
+ };
1570
+ var toU8 = (a) => {
1571
+ const o = new Uint8Array(a.length);
1572
+ for (let i = 0;i < a.length; i++)
1573
+ o[i] = Math.round(Math.max(0, Math.min(1, a[i])) * 255);
1574
+ return o;
1575
+ };
1576
+ function flatNormals(pos, idx) {
1577
+ const n = new Float32Array(pos.length);
1578
+ for (let t = 0;t < idx.length; t += 3) {
1579
+ const a = idx[t] * 3, b = idx[t + 1] * 3, c = idx[t + 2] * 3;
1580
+ const ux = pos[b] - pos[a], uy = pos[b + 1] - pos[a + 1], uz = pos[b + 2] - pos[a + 2], vx = pos[c] - pos[a], vy = pos[c + 1] - pos[a + 1], vz = pos[c + 2] - pos[a + 2];
1581
+ let nx = uy * vz - uz * vy, ny = uz * vx - ux * vz, nz = ux * vy - uy * vx;
1582
+ const l = Math.hypot(nx, ny, nz) || 1;
1583
+ nx /= l;
1584
+ ny /= l;
1585
+ nz /= l;
1586
+ for (const o of [a, b, c]) {
1587
+ n[o] = nx;
1588
+ n[o + 1] = ny;
1589
+ n[o + 2] = nz;
1590
+ }
1591
+ }
1592
+ return n;
1593
+ }
1594
+ var geomCache = new WeakMap;
1595
+ function geom(b, arr) {
1596
+ if (!b)
1597
+ return null;
1598
+ let c = geomCache.get(arr);
1599
+ if (!c)
1600
+ geomCache.set(arr, c = new Map);
1601
+ let g = c.get(b);
1602
+ if (g)
1603
+ return g;
1604
+ g = new THREE.BufferGeometry;
1605
+ g.setAttribute("position", new THREE.BufferAttribute(arr(b.pos), 3));
1606
+ const nrm = b.nrm ? arr(b.nrm) : flatNormals(arr(b.pos), arr(b.idx));
1607
+ const col = arr(b.col);
1608
+ g.setAttribute("normal", new THREE.BufferAttribute(toI8(nrm), 3, true));
1609
+ g.setAttribute("ldrColor", new THREE.BufferAttribute(col instanceof Uint8Array ? col : toU8(col), 4, true));
1610
+ if (b.idx)
1611
+ g.setIndex(new THREE.BufferAttribute(arr(b.idx), 1));
1612
+ if (b.uv)
1613
+ g.setAttribute("ldrUV", new THREE.BufferAttribute(arr(b.uv), 2));
1614
+ c.set(b, g);
1615
+ return g;
1616
+ }
1617
+ function makeMaterial(side) {
1618
+ const m = new THREE.MeshStandardMaterial({ vertexColors: true, roughness: 0.45, side });
1619
+ m.onBeforeCompile = (s) => {
1620
+ s.vertexShader = `attribute vec4 ldrColor;
1621
+ ` + s.vertexShader.replace("#include <color_vertex>", `#include <color_vertex>
1622
+ #ifdef USE_INSTANCING_COLOR
1623
+ vColor.rgb = ldrColor.a > 0.5 ? pow(ldrColor.rgb, vec3(2.2)) : instanceColor.rgb; // baked LDConfig colours are sRGB
1624
+ #else
1625
+ vColor.rgb = pow(ldrColor.rgb, vec3(2.2));
1626
+ #endif`);
1627
+ };
1628
+ m.customProgramCacheKey = () => "ldrColor";
1629
+ return m;
1630
+ }
1631
+ function makeTexturedMaterial(side, map, wrapU = false) {
1632
+ const m = makeMaterial(side);
1633
+ const base = m.onBeforeCompile;
1634
+ m.onBeforeCompile = (sh, r) => {
1635
+ base.call(m, sh, r);
1636
+ sh.uniforms.ldrMap = { value: map };
1637
+ sh.uniforms.ldrWrapU = { value: wrapU ? 1 : 0 };
1638
+ sh.vertexShader = `attribute vec2 ldrUV; varying vec2 vLdrUV;
1639
+ ` + sh.vertexShader.replace("#include <uv_vertex>", `#include <uv_vertex>
1640
+ vLdrUV = ldrUV;`);
1641
+ sh.fragmentShader = `uniform sampler2D ldrMap; uniform int ldrWrapU; varying vec2 vLdrUV;
1642
+ ` + sh.fragmentShader.replace("#include <color_fragment>", `#include <color_fragment>
1643
+ { vec2 uv = vec2(ldrWrapU == 1 ? fract(vLdrUV.x) : vLdrUV.x, vLdrUV.y); vec4 t = texture2D(ldrMap, uv);
1644
+ float inside = step(0.0, uv.x) * step(uv.x, 1.0) * step(0.0, uv.y) * step(uv.y, 1.0);
1645
+ diffuseColor.rgb = mix(diffuseColor.rgb, t.rgb, t.a * inside); }`);
1646
+ };
1647
+ m.customProgramCacheKey = () => "ldrColorTex";
1648
+ m.userData.ldrMap = map;
1649
+ return m;
1650
+ }
1651
+ function packTexture(pack, i) {
1652
+ const t = new THREE.Texture;
1653
+ t.flipY = false;
1654
+ t.colorSpace = THREE.SRGBColorSpace;
1655
+ t.wrapS = t.wrapT = THREE.ClampToEdgeWrapping;
1656
+ const e = pack.header.textures?.[i];
1657
+ const bytes = e?.data ? pack.arr(e.data) : null;
1658
+ if (!bytes || typeof createImageBitmap === "undefined")
1659
+ return { texture: t, ready: Promise.resolve() };
1660
+ const ready = createImageBitmap(new Blob([bytes], { type: e.mime || "image/png" }), { premultiplyAlpha: "none", colorSpaceConversion: "none" }).then((img) => {
1661
+ t.image = img;
1662
+ t.needsUpdate = true;
1663
+ }).catch(() => {});
1664
+ return { texture: t, ready };
1665
+ }
1666
+ var sharedLineMat = () => new THREE.ShaderMaterial({
1667
+ vertexShader: `attribute mat4 instanceMatrix; void main(){ gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4(position,1.0); }`,
1668
+ fragmentShader: `void main(){ gl_FragColor = vec4(0.13,0.13,0.13,1.0); }`
1669
+ });
1670
+ var weldLines = (pos, byLength = false) => {
1671
+ const map = new Map;
1672
+ const P = [];
1673
+ const I = [];
1674
+ const n = Math.floor(pos.length / 6);
1675
+ const len = new Float32Array(n);
1676
+ for (let s = 0;s < n; s++) {
1677
+ const o = s * 6;
1678
+ len[s] = Math.hypot(pos[o + 3] - pos[o], pos[o + 4] - pos[o + 1], pos[o + 5] - pos[o + 2]);
1679
+ }
1680
+ const order = Array.from({ length: n }, (_, s) => s);
1681
+ if (byLength)
1682
+ order.sort((a, b) => len[b] - len[a]);
1683
+ for (const sg of order)
1684
+ for (let e = 0;e < 2; e++) {
1685
+ const i = sg * 6 + e * 3;
1686
+ const k = pos[i].toFixed(2) + "," + pos[i + 1].toFixed(2) + "," + pos[i + 2].toFixed(2);
1687
+ let j = map.get(k);
1688
+ if (j === undefined) {
1689
+ j = P.length / 3;
1690
+ map.set(k, j);
1691
+ P.push(pos[i], pos[i + 1], pos[i + 2]);
1692
+ }
1693
+ I.push(j);
1694
+ }
1695
+ return { P: new Float32Array(P), I: P.length / 3 < 65536 ? new Uint16Array(I) : new Uint32Array(I), lens: Float32Array.from(order, (sg) => len[sg]) };
1696
+ };
1697
+ function createInstancedEdges(pos, im, material = sharedLineMat()) {
1698
+ return sharedLines(pos, im, material);
1699
+ }
1700
+ function conditionalLines(pack, entry, which = "all") {
1701
+ if (which === "all") {
1702
+ const a = conditionalLines(pack, entry, "body"), b = conditionalLines(pack, entry, "under");
1703
+ if (!a || !b)
1704
+ return a ?? b;
1705
+ const o = new Float32Array(a.length + b.length);
1706
+ o.set(a);
1707
+ o.set(b, a.length);
1708
+ return o;
1709
+ }
1710
+ const c = which === "under" ? entry?.condlu : entry?.condl;
1711
+ if (!c)
1712
+ return null;
1713
+ const { arr } = pack;
1714
+ if (c.raw)
1715
+ return arr(c.raw);
1716
+ const pools = [entry.body ? arr(entry.body.pos) : [], entry.under ? arr(entry.under.pos) : [], entry.edges ? arr(entry.edges) : [], c.x ? arr(c.x) : []];
1717
+ const idx = arr(c.idx);
1718
+ const out = new Float32Array(idx.length * 3);
1719
+ const starts = [];
1720
+ let base = 0;
1721
+ for (const p of pools) {
1722
+ starts.push(base);
1723
+ base += p.length / 3;
1724
+ }
1725
+ let prev = 0;
1726
+ for (let i = 0;i < idx.length; i++) {
1727
+ const z = idx[i];
1728
+ const j = prev + (z & 1 ? -(z + 1) / 2 : z / 2);
1729
+ prev = j;
1730
+ let k = 3;
1731
+ while (k > 0 && j < starts[k])
1732
+ k--;
1733
+ const p = pools[k], o = (j - starts[k]) * 3;
1734
+ out[i * 3] = p[o];
1735
+ out[i * 3 + 1] = p[o + 1];
1736
+ out[i * 3 + 2] = p[o + 2];
1267
1737
  }
1268
- const SX = [0, 5, -5, 5, -5], SZ = [0, 5, 5, -5, -5];
1269
- const coverStep = (x, y, z, self) => {
1270
- const k = cellKey(Math.round(y * 2), Math.floor(x / CELL), Math.floor(z / CELL));
1271
- if (k < 0)
1272
- return STEP_NEVER;
1273
- let best = STEP_NEVER;
1274
- for (let e = cells.get(k);e >= 0; e = nextE[e]) {
1275
- const ri = rectE[e];
1276
- if (rInst[ri] === self || !(x - 6 >= rx0[ri] - 0.5 && x + 6 <= rx1[ri] + 0.5 && z - 6 >= rz0[ri] - 0.5 && z + 6 <= rz1[ri] + 0.5))
1277
- continue;
1278
- const m = insts[rInst[ri]].m;
1279
- const pp = rPrep[ri];
1280
- const bx = rBx[ri], bz = rBz[ri];
1281
- const dx = x - m[0], dy = y - m[1], dz = z - m[2];
1282
- const lx = m[3] * dx + m[6] * dy + m[9] * dz, lz = m[5] * dx + m[8] * dy + m[11] * dz;
1283
- const { nx, nz, mask: bits } = pp;
1284
- let ok = true;
1285
- for (let s = 0;s < 5; s++) {
1286
- const ca = Math.floor((lx + SX[s] - bx) / 20), cb = Math.floor((lz + SZ[s] - bz) / 20);
1287
- if (ca < 0 || cb < 0 || ca >= nx || cb >= nz || bits[ca * nz + cb] !== 1) {
1288
- ok = false;
1289
- break;
1290
- }
1291
- }
1292
- if (ok) {
1293
- if (!steps)
1294
- return 0;
1295
- const st = steps[rInst[ri]];
1296
- if (st < best)
1297
- best = st;
1298
- }
1299
- }
1300
- return best;
1738
+ return out;
1739
+ }
1740
+ var condLineMat = () => new THREE.ShaderMaterial({
1741
+ uniforms: { ldrViewProj: { value: new THREE.Matrix4 } },
1742
+ vertexShader: `uniform mat4 ldrViewProj; attribute mat4 instanceMatrix; attribute vec3 ldrP1; attribute vec3 ldrC0; attribute vec3 ldrC1; attribute float ldrSide;
1743
+ void main(){
1744
+ mat4 mvp = ldrViewProj * instanceMatrix;
1745
+ vec4 a = mvp * vec4(position, 1.0), b = mvp * vec4(ldrP1, 1.0), c0 = mvp * vec4(ldrC0, 1.0), c1 = mvp * vec4(ldrC1, 1.0);
1746
+ vec2 A = a.xy / a.w, B = b.xy / b.w, C0 = c0.xy / c0.w, C1 = c1.xy / c1.w, d = B - A;
1747
+ float s0 = d.x * (C0.y - A.y) - d.y * (C0.x - A.x), s1 = d.x * (C1.y - A.y) - d.y * (C1.x - A.x);
1748
+ gl_Position = s0 * s1 >= 0.0 ? (ldrSide > 0.5 ? b : a) : vec4(2.0, 2.0, 2.0, 1.0);
1749
+ }`,
1750
+ fragmentShader: `void main(){ gl_FragColor = vec4(0.13,0.13,0.13,1.0); }`
1751
+ });
1752
+ function conditionalLineVisible(cond, i, mvp) {
1753
+ const e = mvp.elements;
1754
+ const pr = (o) => {
1755
+ const x = cond[o], y = cond[o + 1], z = cond[o + 2];
1756
+ const w = e[3] * x + e[7] * y + e[11] * z + e[15];
1757
+ return [(e[0] * x + e[4] * y + e[8] * z + e[12]) / w, (e[1] * x + e[5] * y + e[9] * z + e[13]) / w];
1301
1758
  };
1302
- let nStuds = 0;
1303
- for (const it of insts) {
1304
- const pp = prepPart(H, it.part);
1305
- if (pp)
1306
- nStuds += pp.nStuds;
1759
+ const o = i * 12;
1760
+ const A = pr(o), B = pr(o + 3), C0 = pr(o + 6), C1 = pr(o + 9);
1761
+ const dx = B[0] - A[0], dy = B[1] - A[1];
1762
+ const s0 = dx * (C0[1] - A[1]) - dy * (C0[0] - A[0]), s1 = dx * (C1[1] - A[1]) - dy * (C1[0] - A[0]);
1763
+ return s0 * s1 >= 0;
1764
+ }
1765
+ function createInstancedConditionalEdges(cond, im, material = condLineMat()) {
1766
+ return condEdges(condBuffers(cond), im, material);
1767
+ }
1768
+ function condBuffers(cond) {
1769
+ const n = Math.floor(cond.length / 12);
1770
+ const buf = new Float32Array(n * 24), side = new Float32Array(n * 2);
1771
+ for (let l = 0;l < n; l++) {
1772
+ for (let k = 0;k < 12; k++) {
1773
+ const v = cond[l * 12 + k];
1774
+ buf[l * 24 + k] = v;
1775
+ buf[l * 24 + 12 + k] = v;
1776
+ }
1777
+ side[l * 2 + 1] = 1;
1307
1778
  }
1308
- const studHidden = new Uint8Array(nStuds), studUp = new Uint8Array(nStuds);
1309
- const tops = new NumTable(nStuds);
1310
- let studsHidden = 0;
1311
- const studHideStep = steps ? new Int32Array(nStuds).fill(STEP_NEVER) : undefined;
1312
- forEachStud(insts, H, (j, idx, w) => {
1313
- if (!upright(w))
1314
- return;
1315
- studUp[j] = 1;
1316
- const cs = coverStep(w[0], w[1], w[2], idx);
1317
- if (cs !== STEP_NEVER) {
1318
- studHidden[j] = 1;
1319
- studsHidden++;
1320
- if (studHideStep)
1321
- studHideStep[j] = cs;
1322
- }
1323
- const k = topKey(w[0], w[1], w[2]);
1324
- if (k < 0)
1779
+ return { ib: new THREE.InterleavedBuffer(buf, 12), side: new THREE.BufferAttribute(side, 1) };
1780
+ }
1781
+ function condEdges({ ib, side }, im, material) {
1782
+ const g = new THREE.InstancedBufferGeometry;
1783
+ g.setAttribute("position", new THREE.InterleavedBufferAttribute(ib, 3, 0));
1784
+ g.setAttribute("ldrP1", new THREE.InterleavedBufferAttribute(ib, 3, 3));
1785
+ g.setAttribute("ldrC0", new THREE.InterleavedBufferAttribute(ib, 3, 6));
1786
+ g.setAttribute("ldrC1", new THREE.InterleavedBufferAttribute(ib, 3, 9));
1787
+ g.setAttribute("ldrSide", side);
1788
+ g.setAttribute("instanceMatrix", im.instanceMatrix);
1789
+ g.instanceCount = im.count;
1790
+ const l = new THREE.LineSegments(g, material);
1791
+ l.frustumCulled = false;
1792
+ l.name = "ldrCondLines";
1793
+ l.onBeforeRender = (_r, _s, cam, _g, mat) => {
1794
+ const u = mat.uniforms?.ldrViewProj;
1795
+ if (!u)
1325
1796
  return;
1326
- if (!steps) {
1327
- tops.put(k, 1);
1797
+ l.modelViewMatrix.multiplyMatrices(cam.matrixWorldInverse, l.matrixWorld);
1798
+ u.value.multiplyMatrices(cam.projectionMatrix, l.modelViewMatrix);
1799
+ mat.uniformsNeedUpdate = true;
1800
+ };
1801
+ return l;
1802
+ }
1803
+ function sharedLines(pos, im, material = sharedLineMat()) {
1804
+ const { P, I } = weldLines(pos);
1805
+ const g = new THREE.InstancedBufferGeometry;
1806
+ g.setAttribute("position", new THREE.BufferAttribute(P, 3));
1807
+ g.setIndex(new THREE.BufferAttribute(I, 1));
1808
+ g.setAttribute("instanceMatrix", im.instanceMatrix);
1809
+ g.instanceCount = im.count;
1810
+ const l = new THREE.LineSegments(g, material);
1811
+ l.frustumCulled = false;
1812
+ return l;
1813
+ }
1814
+ function writeM4(t, o, m, mo = 0) {
1815
+ t[o] = m[mo + 3];
1816
+ t[o + 1] = m[mo + 6];
1817
+ t[o + 2] = m[mo + 9];
1818
+ t[o + 3] = 0;
1819
+ t[o + 4] = m[mo + 4];
1820
+ t[o + 5] = m[mo + 7];
1821
+ t[o + 6] = m[mo + 10];
1822
+ t[o + 7] = 0;
1823
+ t[o + 8] = m[mo + 5];
1824
+ t[o + 9] = m[mo + 8];
1825
+ t[o + 10] = m[mo + 11];
1826
+ t[o + 11] = 0;
1827
+ t[o + 12] = m[mo];
1828
+ t[o + 13] = m[mo + 1];
1829
+ t[o + 14] = m[mo + 2];
1830
+ t[o + 15] = 1;
1831
+ }
1832
+ function newIM(g, mat, n) {
1833
+ const im = new THREE.InstancedMesh(g, mat, 0);
1834
+ im.instanceMatrix = new THREE.InstancedBufferAttribute(new Float32Array(n * 16), 16);
1835
+ im.count = n;
1836
+ return im;
1837
+ }
1838
+ function instancedBoundingSphere(im) {
1839
+ const g = im.geometry;
1840
+ if (!g.boundingSphere)
1841
+ g.computeBoundingSphere();
1842
+ const gs = g.boundingSphere;
1843
+ const gx = gs.center.x, gy = gs.center.y, gz = gs.center.z, gr = gs.radius;
1844
+ const A = im.instanceMatrix.array;
1845
+ let cx = 0, cy = 0, cz = 0, r = -1;
1846
+ const expand = (px, py, pz) => {
1847
+ if (r < 0) {
1848
+ cx = px;
1849
+ cy = py;
1850
+ cz = pz;
1851
+ r = 0;
1328
1852
  return;
1329
1853
  }
1330
- const st = steps[idx], o = tops.get(k);
1331
- if (o < 0 || st < o)
1332
- tops.put(k, st);
1333
- });
1334
- const underHidden = new Uint8Array(insts.length);
1335
- const underHideStep = steps ? new Int32Array(insts.length).fill(STEP_NEVER) : undefined;
1336
- for (let idx = 0;idx < insts.length; idx++) {
1337
- const it = insts[idx];
1338
- const p = H.parts[it.part];
1339
- if (!p || !p.under || !upright(it.m))
1854
+ const vx = px - cx, vy = py - cy, vz = pz - cz;
1855
+ const l2 = vx * vx + vy * vy + vz * vz;
1856
+ if (l2 > r * r) {
1857
+ const l = Math.sqrt(l2);
1858
+ const d = (l - r) * 0.5;
1859
+ const f = d / l;
1860
+ cx += vx * f;
1861
+ cy += vy * f;
1862
+ cz += vz * f;
1863
+ r += d;
1864
+ }
1865
+ };
1866
+ for (let i = 0, n = im.count;i < n; i++) {
1867
+ const o = i * 16;
1868
+ const e0 = A[o], e1 = A[o + 1], e2 = A[o + 2], e3 = A[o + 3], e4 = A[o + 4], e5 = A[o + 5], e6 = A[o + 6], e7 = A[o + 7], e8 = A[o + 8], e9 = A[o + 9], e10 = A[o + 10], e11 = A[o + 11];
1869
+ const w = 1 / (e3 * gx + e7 * gy + e11 * gz + A[o + 15]);
1870
+ const x = (e0 * gx + e4 * gy + e8 * gz + A[o + 12]) * w, y = (e1 * gx + e5 * gy + e9 * gz + A[o + 13]) * w, z = (e2 * gx + e6 * gy + e10 * gz + A[o + 14]) * w;
1871
+ const sr = gr * Math.sqrt(Math.max(e0 * e0 + e1 * e1 + e2 * e2, e4 * e4 + e5 * e5 + e6 * e6, e8 * e8 + e9 * e9 + e10 * e10));
1872
+ if (r < 0) {
1873
+ cx = x;
1874
+ cy = y;
1875
+ cz = z;
1876
+ r = sr;
1340
1877
  continue;
1341
- const b = p.bbox;
1342
- const nx = Math.round((b[3] - b[0]) / 20), nz = Math.round((b[5] - b[2]) / 20);
1343
- if (!nx || !nz || nx * nz > 4096)
1878
+ }
1879
+ if (x === cx && y === cy && z === cz) {
1880
+ r = Math.max(r, sr);
1344
1881
  continue;
1345
- const m = it.m;
1346
- let all = true, at = 0;
1347
- for (let a = 0;a < nx && all; a++)
1348
- for (let c = 0;c < nz; c++) {
1349
- const lx = b[0] + 10 + 20 * a, lz = b[2] + 10 + 20 * c;
1350
- const x = m[0] + m[3] * lx + m[5] * lz, z = m[2] + m[9] * lx + m[11] * lz;
1351
- const k = topKey(x, m[1] + b[4], z);
1352
- const t = k < 0 ? -1 : tops.get(k);
1353
- if (t < 0) {
1354
- all = false;
1355
- break;
1356
- }
1357
- if (t > at)
1358
- at = t;
1359
- }
1360
- if (all) {
1361
- underHidden[idx] = 1;
1362
- if (underHideStep)
1363
- underHideStep[idx] = at;
1364
1882
  }
1883
+ let dx = x - cx, dy = y - cy, dz = z - cz;
1884
+ const inv = 1 / (Math.sqrt(dx * dx + dy * dy + dz * dz) || 1);
1885
+ dx = dx * inv * sr;
1886
+ dy = dy * inv * sr;
1887
+ dz = dz * inv * sr;
1888
+ expand(x + dx, y + dy, z + dz);
1889
+ expand(x - dx, y - dy, z - dz);
1365
1890
  }
1366
- return { nStuds, studHidden, studUp, underHidden, studsHidden, studHideStep, underHideStep };
1891
+ const sph = im.boundingSphere ?? new THREE.Sphere;
1892
+ sph.center.set(cx, cy, cz);
1893
+ sph.radius = r;
1894
+ if (r < 0)
1895
+ sph.makeEmpty();
1896
+ im.boundingSphere = sph;
1897
+ return sph;
1898
+ }
1899
+ function fillInstances(im, ids, insts, color) {
1900
+ const M = im.instanceMatrix.array;
1901
+ const C = new Float32Array(ids.length * 3);
1902
+ for (let k = 0;k < ids.length; k++) {
1903
+ const it = insts[ids[k]];
1904
+ writeM4(M, k * 16, it.m);
1905
+ color(it.color).toArray(C, k * 3);
1906
+ }
1907
+ im.instanceColor = new THREE.InstancedBufferAttribute(C, 3);
1367
1908
  }
1368
1909
  function computeCulling(insts, H) {
1369
1910
  const c = cullCore(insts, H);
@@ -1419,7 +1960,8 @@ class LdrLodRoot extends THREE.LOD {
1419
1960
  clusters = [];
1420
1961
  vpH = 1080;
1421
1962
  px = 0.5;
1422
- edgePpl = 0.025;
1963
+ edgePpl = 0.5 / 20;
1964
+ edgeMinPx = 0.15;
1423
1965
  enabled = true;
1424
1966
  apply = () => {};
1425
1967
  inv = new THREE.Matrix4;
@@ -1449,37 +1991,90 @@ class LdrLodRoot extends THREE.LOD {
1449
1991
  L = i;
1450
1992
  break;
1451
1993
  }
1994
+ if (c.below !== undefined && x * c.ax[0] + y * c.ax[1] + z * c.ax[2] < c.below - 1 && ppl * 20 < 4)
1995
+ L = -1;
1996
+ if (c.boxErr !== undefined && c.boxErr * ppl <= tau)
1997
+ L = -1;
1452
1998
  const e = ppl >= eppl;
1453
1999
  if (L !== c.cur || e !== c.edgeOk) {
1454
2000
  c.cur = L;
1455
2001
  c.edgeOk = e;
1456
2002
  this.apply(c);
1457
2003
  }
2004
+ if (e && c.lines.length) {
2005
+ const minLen = this.edgeMinPx / ppl;
2006
+ for (const l of c.lines) {
2007
+ const lens = l.userData.ldrLens;
2008
+ if (!lens)
2009
+ continue;
2010
+ let lo = 0, hi = lens.length;
2011
+ while (lo < hi) {
2012
+ const mid = lo + hi >> 1;
2013
+ if (lens[mid] >= minLen)
2014
+ lo = mid + 1;
2015
+ else
2016
+ hi = mid;
2017
+ }
2018
+ l.geometry.drawRange.count = lo * 2;
2019
+ }
2020
+ }
1458
2021
  }
1459
2022
  }
1460
2023
  }
1461
- function buildStudMeshes(insts, H, cull, arr, Q, LOD, color, matF, matB, steps, colorIndex) {
2024
+ function buildStudMeshes(insts, H, cull, arr, LOD, color, matF, matB, steps, colorIndex) {
1462
2025
  const bucketOf = new Map;
1463
2026
  const bKind = [], bMirror = [];
1464
2027
  const bAll = [];
1465
2028
  const studBucket = new Uint16Array(cull.nStuds);
1466
2029
  const sx = new Float32Array(cull.nStuds), sz = new Float32Array(cull.nStuds);
1467
- forEachStud(insts, H, (j, _i, w, kind) => {
1468
- const neg = det12(w) < 0;
1469
- const k = neg ? kind + "#m" : kind;
1470
- let b = bucketOf.get(k);
1471
- if (b === undefined) {
1472
- b = bKind.length;
1473
- bucketOf.set(k, b);
1474
- bKind.push(kind);
1475
- bMirror.push(neg);
1476
- bAll.push(0);
1477
- }
1478
- studBucket[j] = b;
1479
- bAll[b]++;
1480
- sx[j] = w[0];
1481
- sz[j] = w[2];
1482
- });
2030
+ const kindIds = new Map;
2031
+ const kindNames = [];
2032
+ const bucketOfKM = [];
2033
+ const partStud = new Map;
2034
+ for (let idx = 0, j = 0;idx < insts.length; idx++) {
2035
+ const it = insts[idx];
2036
+ const pp = prepPart(H, it.part);
2037
+ if (!pp || !pp.nStuds)
2038
+ continue;
2039
+ const a = it.m;
2040
+ let ps = partStud.get(pp);
2041
+ if (!ps) {
2042
+ const kid = new Int32Array(pp.nStuds), neg = new Uint8Array(pp.nStuds);
2043
+ for (let si = 0;si < pp.nStuds; si++) {
2044
+ const kn = pp.kind[si];
2045
+ let id = kindIds.get(kn);
2046
+ if (id === undefined) {
2047
+ id = kindNames.length;
2048
+ kindIds.set(kn, id);
2049
+ kindNames.push(kn);
2050
+ }
2051
+ kid[si] = id;
2052
+ neg[si] = det12(pp.studM.subarray(si * 12, si * 12 + 12)) < 0 ? 1 : 0;
2053
+ }
2054
+ partStud.set(pp, ps = { kid, neg });
2055
+ }
2056
+ const instNeg = det12(a) < 0 ? 1 : 0;
2057
+ const B = pp.studM;
2058
+ for (let si = 0;si < pp.nStuds; si++, j++) {
2059
+ const o = si * 12, b0 = B[o], b1 = B[o + 1], b2 = B[o + 2];
2060
+ const neg = (instNeg ^ ps.neg[si]) === 1;
2061
+ const km = ps.kid[si] * 2 + (neg ? 1 : 0);
2062
+ let b = bucketOfKM[km];
2063
+ if (b === undefined) {
2064
+ const kn = kindNames[ps.kid[si]];
2065
+ b = bKind.length;
2066
+ bucketOfKM[km] = b;
2067
+ bucketOf.set(neg ? kn + "#m" : kn, b);
2068
+ bKind.push(kn);
2069
+ bMirror.push(neg);
2070
+ bAll.push(0);
2071
+ }
2072
+ studBucket[j] = b;
2073
+ bAll[b]++;
2074
+ sx[j] = a[0] + a[3] * b0 + a[4] * b1 + a[5] * b2;
2075
+ sz[j] = a[2] + a[9] * b0 + a[10] * b1 + a[11] * b2;
2076
+ }
2077
+ }
1483
2078
  const bIds = bAll.map((n) => new Int32Array(n));
1484
2079
  {
1485
2080
  const f = bAll.map(() => 0);
@@ -1491,7 +2086,7 @@ function buildStudMeshes(insts, H, cull, arr, Q, LOD, color, matF, matB, steps,
1491
2086
  const studCl = new Int32Array(cull.nStuds), studSlot = new Int32Array(cull.nStuds);
1492
2087
  const sMesh = [];
1493
2088
  bKind.forEach((kind, b) => {
1494
- const g = geom(H.studKinds[kind].body, arr, Q);
2089
+ const g = geom(H.studKinds[kind].body, arr);
1495
2090
  const ids = bIds[b];
1496
2091
  for (const c of gridClusters(ids.length, (i) => sx[ids[i]], (i) => sz[ids[i]], LOD ? 16384 : Infinity)) {
1497
2092
  const ci = sMesh.length;
@@ -1515,6 +2110,13 @@ function buildStudMeshes(insts, H, cull, arr, Q, LOD, color, matF, matB, steps,
1515
2110
  sMesh.push({ im, kind, vis: v, ...steps ? { slots: { own: new Int32Array(n), hide: new Int32Array(n), inst: new Int32Array(n), stud: new Int16Array(n), col: new Uint16Array(n) } } : {} });
1516
2111
  }
1517
2112
  });
2113
+ const colCache = new Map;
2114
+ const colorOf = (c) => {
2115
+ let x = colCache.get(c);
2116
+ if (!x)
2117
+ colCache.set(c, x = color(c));
2118
+ return x;
2119
+ };
1518
2120
  forEachStud(insts, H, (j, owner, w, _kind, col, si) => {
1519
2121
  const sm = sMesh[studCl[j]];
1520
2122
  if (!sm)
@@ -1530,18 +2132,46 @@ function buildStudMeshes(insts, H, cull, arr, Q, LOD, color, matF, matB, steps,
1530
2132
  t.col[slot] = colorIndex(col);
1531
2133
  }
1532
2134
  writeM4(im.instanceMatrix.array, slot * 16, w);
1533
- color(col).toArray(im.instanceColor.array, slot * 3);
2135
+ colorOf(col).toArray(im.instanceColor.array, slot * 3);
1534
2136
  });
1535
2137
  return sMesh;
1536
2138
  }
2139
+ function undersideGroups(ids, insts) {
2140
+ const by = new Map;
2141
+ const rest = [];
2142
+ for (const id of ids) {
2143
+ const m = insts[id].m;
2144
+ const l = Math.hypot(m[4], m[7], m[10]);
2145
+ if (!(l > 0.000001)) {
2146
+ rest.push(id);
2147
+ continue;
2148
+ }
2149
+ const ax = [m[4] / l, m[7] / l, m[10] / l, l];
2150
+ const k = ax.map((v) => Math.round(v * 1000)).join();
2151
+ let g = by.get(k);
2152
+ if (!g) {
2153
+ if (by.size >= 12) {
2154
+ rest.push(id);
2155
+ continue;
2156
+ }
2157
+ by.set(k, g = { ids: [], ax });
2158
+ }
2159
+ g.ids.push(id);
2160
+ }
2161
+ const out = [...by.values()];
2162
+ if (rest.length)
2163
+ out.push({ ids: rest, ax: null });
2164
+ return out;
2165
+ }
1537
2166
  function buildLdrScene(insts, pack, P, color, mark) {
1538
2167
  const { header: H, arr } = pack;
1539
- const Q = P.quant !== false;
1540
2168
  const LOD = P.lod !== false;
2169
+ const EDGES = !!P.edges;
1541
2170
  const root = new LdrLodRoot;
1542
2171
  root.enabled = LOD;
1543
2172
  root.px = P.lodPx ?? 0.5;
1544
2173
  root.edgePpl = (P.lodEdgePx ?? 0.5) / 20;
2174
+ root.edgeMinPx = P.lodEdgeMinPx ?? 0.15;
1545
2175
  const trackVp = (r) => {
1546
2176
  const rt = r.getRenderTarget();
1547
2177
  const h = rt ? rt.height : r.getContext().drawingBufferHeight;
@@ -1559,7 +2189,7 @@ function buildLdrScene(insts, pack, P, color, mark) {
1559
2189
  }
1560
2190
  });
1561
2191
  const steps = P.steps;
1562
- let cull = cullCore(insts, H, steps);
2192
+ let cull = P.cull ?? cullCore(insts, H, steps);
1563
2193
  mark("culling");
1564
2194
  const stepBatches = [];
1565
2195
  const instM = steps ? new Float64Array(insts.length * 12) : null;
@@ -1585,7 +2215,7 @@ function buildLdrScene(insts, pack, P, color, mark) {
1585
2215
  });
1586
2216
  const edgeObjs = [];
1587
2217
  const condObjs = [];
1588
- const wantCond = P.cond !== false && (P.edges === "idx" || P.edges === true);
2218
+ const wantCond = P.cond !== false && EDGES;
1589
2219
  let condMat = null;
1590
2220
  const cmat = () => condMat ??= condLineMat();
1591
2221
  let lineMatShared = null;
@@ -1616,8 +2246,8 @@ function buildLdrScene(insts, pack, P, color, mark) {
1616
2246
  const addLines = (ref, im, cl) => {
1617
2247
  let w = lineCache.get(ref);
1618
2248
  if (!w) {
1619
- const r = weldLines(arr(ref));
1620
- lineCache.set(ref, w = { P: new THREE.BufferAttribute(r.P, 3), I: new THREE.BufferAttribute(r.I, 1) });
2249
+ const r = weldLines(arr(ref), LOD);
2250
+ lineCache.set(ref, w = { P: new THREE.BufferAttribute(r.P, 3), I: new THREE.BufferAttribute(r.I, 1), lens: r.lens });
1621
2251
  }
1622
2252
  const g = new THREE.InstancedBufferGeometry;
1623
2253
  g.setAttribute("position", w.P);
@@ -1626,6 +2256,8 @@ function buildLdrScene(insts, pack, P, color, mark) {
1626
2256
  g.instanceCount = im.count;
1627
2257
  const l = new THREE.LineSegments(g, lmat());
1628
2258
  l.frustumCulled = false;
2259
+ if (LOD)
2260
+ l.userData.ldrLens = w.lens;
1629
2261
  edgeObjs.push(l);
1630
2262
  cl.lines.push(l);
1631
2263
  root.add(l);
@@ -1633,7 +2265,6 @@ function buildLdrScene(insts, pack, P, color, mark) {
1633
2265
  };
1634
2266
  const stats = { studsTotal: cull.nStuds, studsHidden: cull.studsHidden, undersTotal: 0, undersHidden: 0 };
1635
2267
  const toggles = [];
1636
- const studMeshes = [];
1637
2268
  const countTo = (objs) => ({ set count(n) {
1638
2269
  for (const o of objs()) {
1639
2270
  if (o.isInstancedMesh)
@@ -1668,8 +2299,9 @@ function buildLdrScene(insts, pack, P, color, mark) {
1668
2299
  root.clusters.push(c);
1669
2300
  return c;
1670
2301
  };
1671
- const lodLevels = (b, base, mat) => !LOD || P.lodMesh === false || !b?.lod ? [] : b.lod.map((l) => {
1672
- const im = new THREE.InstancedMesh(geom(l, arr, Q), mat, 0);
2302
+ const lodLevels = (b, base, mat) => !LOD || !b?.lod ? [] : b.lod.map((l) => {
2303
+ const im = new THREE.InstancedMesh(geom(l, arr), mat, 0);
2304
+ im.userData = { ...base.userData };
1673
2305
  im.instanceMatrix = base.instanceMatrix;
1674
2306
  im.count = base.count;
1675
2307
  im.instanceColor = base.instanceColor;
@@ -1685,10 +2317,10 @@ function buildLdrScene(insts, pack, P, color, mark) {
1685
2317
  for (const [pk, idsAll] of byPart) {
1686
2318
  const part = pk.replace(/#m$/, "");
1687
2319
  const p = H.parts[part];
1688
- const mat = P.uncertDouble !== false && p.uncert ? (nUncert++, matD) : pk.endsWith("#m") ? matB : matF;
2320
+ const mat = p.uncert ? (nUncert++, matD) : pk.endsWith("#m") ? matB : matF;
1689
2321
  const textured = wantTex && !!p.tex;
1690
2322
  const bodyB = textured ? p.tbody : p.body;
1691
- const body = geom(bodyB, arr, Q);
2323
+ const body = geom(bodyB, arr);
1692
2324
  const groups = gridClusters(idsAll.length, (i) => insts[idsAll[i]].m[0], (i) => insts[idsAll[i]].m[2], textured ? Infinity : kFor(tris(p.body) + tris(p.under)));
1693
2325
  for (const g of groups) {
1694
2326
  const ids = Array.from(g, (i) => idsAll[i]);
@@ -1696,7 +2328,8 @@ function buildLdrScene(insts, pack, P, color, mark) {
1696
2328
  const lv0 = [];
1697
2329
  const place = (im) => {
1698
2330
  fillInstances(im, ids, insts, color);
1699
- im.computeBoundingSphere();
2331
+ instancedBoundingSphere(im);
2332
+ im.userData.ldrPart = part;
1700
2333
  root.add(im);
1701
2334
  };
1702
2335
  if (body) {
@@ -1706,7 +2339,7 @@ function buildLdrScene(insts, pack, P, color, mark) {
1706
2339
  }
1707
2340
  if (textured)
1708
2341
  for (const tb of p.tex) {
1709
- const gg = geom(tb, arr, Q);
2342
+ const gg = geom(tb, arr);
1710
2343
  const im = newIM(gg, texMat(tb.t, mat, !!tb.wrapU), ids.length);
1711
2344
  texBatches++;
1712
2345
  lv0.push(im);
@@ -1724,49 +2357,57 @@ function buildLdrScene(insts, pack, P, color, mark) {
1724
2357
  const cl = newCluster(bodyIm.boundingSphere);
1725
2358
  lv0.forEach((o) => o.onBeforeRender = trackVp);
1726
2359
  cl.lv.push({ objs: lv0, err: 0 }, ...textured ? [] : lodLevels(p.body, bodyIm, mat));
1727
- if (P.edges === "idx" && p.edges)
2360
+ if (EDGES && p.edges)
1728
2361
  addLines(p.edges, bodyIm, cl);
1729
2362
  addCond(p, bodyIm, cl);
1730
2363
  if (steps)
1731
2364
  stepBatches.push({ im: bodyIm, objs: [...cl.lv.flatMap((l) => l.objs), ...cl.lines, ...cl.cond], own: Int32Array.from(ids, (id) => steps[id]), hide: null, flag: "body", inst: Int32Array.from(ids), stud: null, col: Uint16Array.from(ids, (id) => instCol[id]) });
1732
- if (P.edges === true && p.edges) {
1733
- const mats = new Float32Array(ids.length * 16);
1734
- ids.forEach((id, k) => writeM4(mats, k * 16, insts[id].m));
1735
- {
1736
- const l = instancedLines(arr(p.edges), mats, ids.length);
1737
- edgeObjs.push(l);
1738
- cl.lines.push(l);
1739
- root.add(l);
1740
- }
1741
- }
1742
2365
  }
1743
- const under = geom(p.under, arr, Q);
1744
- if (under) {
1745
- const ord = [...ids.filter((i) => !cull.underHidden[i]), ...ids.filter((i) => cull.underHidden[i])];
1746
- const vis = ids.length - ids.reduce((a, i) => a + cull.underHidden[i], 0);
1747
- stats.undersTotal += ids.length;
1748
- stats.undersHidden += ids.length - vis;
1749
- const im = newIM(under, mat, ids.length);
2366
+ const under = geom(p.under, arr);
2367
+ const uGroups = !under ? [] : LOD && P.lodUnder !== false ? undersideGroups(ids, insts) : [{ ids, ax: null }];
2368
+ for (const { ids: uids, ax } of uGroups) {
2369
+ const ord = [...uids.filter((i) => !cull.underHidden[i]), ...uids.filter((i) => cull.underHidden[i])];
2370
+ const vis = uids.length - uids.reduce((a, i) => a + cull.underHidden[i], 0);
2371
+ stats.undersTotal += uids.length;
2372
+ stats.undersHidden += uids.length - vis;
2373
+ const im = newIM(under, mat, uids.length);
1750
2374
  fillInstances(im, ord, insts, color);
1751
2375
  im.onBeforeRender = trackVp;
1752
- im.computeBoundingSphere();
1753
- im.count = P.cullUnder ? vis : ids.length;
2376
+ im.userData.ldrUnder = true;
2377
+ im.userData.ldrPart = part;
2378
+ instancedBoundingSphere(im);
2379
+ im.count = P.cullUnder ? vis : uids.length;
1754
2380
  root.add(im);
1755
2381
  const cl = newCluster(im.boundingSphere);
1756
2382
  cl.lv.push({ objs: [im], err: 0 }, ...lodLevels(p.under, im, mat));
2383
+ {
2384
+ const bl = p.body?.lod;
2385
+ const last = bl?.[bl.length - 1];
2386
+ if (LOD && P.lodUnder !== false && last && last.tris === 12)
2387
+ cl.boxErr = last.err;
2388
+ }
2389
+ if (ax) {
2390
+ let below = Infinity;
2391
+ for (const id of uids) {
2392
+ const m = insts[id].m;
2393
+ below = Math.min(below, m[0] * ax[0] + m[1] * ax[1] + m[2] * ax[2] + p.bbox[4] * ax[3]);
2394
+ }
2395
+ cl.below = below;
2396
+ cl.ax = ax.slice(0, 3);
2397
+ }
1757
2398
  addCond(p, im, cl, "under");
1758
2399
  const objs = [...cl.lv.flatMap((l) => l.objs), ...cl.cond];
1759
2400
  objs.forEach((o) => {
1760
2401
  if (!o.isInstancedMesh)
1761
2402
  o.geometry.instanceCount = im.count;
1762
2403
  });
1763
- toggles.push({ mesh: countTo(() => objs), all: ids.length, visible: vis, flag: "under" });
2404
+ toggles.push({ mesh: countTo(() => objs), all: uids.length, visible: vis, flag: "under" });
1764
2405
  if (steps)
1765
2406
  stepBatches.push({ im, objs, own: Int32Array.from(ord, (id) => steps[id]), hide: Int32Array.from(ord, (id) => cull.underHideStep[id]), flag: "under", inst: Int32Array.from(ord), stud: null, col: Uint16Array.from(ord, (id) => instCol[id]) });
1766
2407
  }
1767
2408
  }
1768
2409
  }
1769
- const sMesh = buildStudMeshes(insts, H, cull, arr, Q, LOD, color, matF, matB, steps, steps && colorIndex);
2410
+ const sMesh = buildStudMeshes(insts, H, cull, arr, LOD, color, matF, matB, steps, steps && colorIndex);
1770
2411
  const sKind = sMesh.map((x) => x?.kind ?? "");
1771
2412
  const sVis = sMesh.map((x) => x?.vis ?? 0);
1772
2413
  const STUD_ERR = 12;
@@ -1777,26 +2418,19 @@ function buildLdrScene(insts, pack, P, color, mark) {
1777
2418
  const kind = sKind[ci];
1778
2419
  const k = H.studKinds[kind];
1779
2420
  const vis = sVis[ci], all = im.instanceMatrix.count;
1780
- im.computeBoundingSphere();
2421
+ instancedBoundingSphere(im);
1781
2422
  im.count = P.cullStuds ? vis : all;
1782
2423
  im.onBeforeRender = trackVp;
1783
2424
  im.userData.ldrStud = true;
1784
2425
  root.add(im);
1785
- studMeshes.push({ im, kind });
1786
2426
  const cl = newCluster(im.boundingSphere);
1787
2427
  cl.lv.push({ objs: [im], err: 0 });
1788
- if (LOD && P.lodStuds !== false)
2428
+ if (LOD)
1789
2429
  cl.lv.push({ objs: [], err: STUD_ERR });
1790
- if (P.edges === "idx" && k.edges)
2430
+ if (EDGES && k.edges)
1791
2431
  addLines(k.edges, im, cl);
1792
2432
  if (P.condStuds !== false)
1793
2433
  addCond(k, im, cl);
1794
- if (P.edges === true && k.edges) {
1795
- const l = instancedLines(arr(k.edges), im.instanceMatrix.array.slice(), im.count);
1796
- edgeObjs.push(l);
1797
- cl.lines.push(l);
1798
- root.add(l);
1799
- }
1800
2434
  const objs = [im, ...cl.lines, ...cl.cond];
1801
2435
  objs.forEach((o) => {
1802
2436
  if (!o.isInstancedMesh)
@@ -1814,7 +2448,7 @@ function buildLdrScene(insts, pack, P, color, mark) {
1814
2448
  for (const o of l.objs)
1815
2449
  o.visible = i === c.cur;
1816
2450
  });
1817
- const lineVis = edgesOn && c.edgeOk && (c.cur === 0 || !LOD || c.lv[c.cur].objs.length > 0);
2451
+ const lineVis = edgesOn && c.edgeOk && c.cur >= 0 && (c.cur === 0 || !LOD || c.lv[c.cur].objs.length > 0);
1818
2452
  for (const o of c.lines)
1819
2453
  o.visible = lineVis;
1820
2454
  for (const o of c.cond)
@@ -1836,9 +2470,10 @@ function buildLdrScene(insts, pack, P, color, mark) {
1836
2470
  stats.clusters = root.clusters.length;
1837
2471
  const texturesReady = Promise.all(pending).then(() => {});
1838
2472
  let stepS = STEP_NEVER - 1, cullS = !!P.cullStuds, cullU = !!P.cullUnder;
2473
+ let only = null;
1839
2474
  const applySteps = () => {
1840
2475
  const st = { studsTotal: 0, studsHidden: 0, undersTotal: 0, undersHidden: 0 };
1841
- const S = stepS;
2476
+ const S = stepS, O = only;
1842
2477
  const wm = new Float64Array(12);
1843
2478
  for (const b of stepBatches) {
1844
2479
  const MA = b.im.instanceMatrix.array, CA = b.im.instanceColor.array;
@@ -1861,6 +2496,8 @@ function buildLdrScene(insts, pack, P, color, mark) {
1861
2496
  if (useHide && hid)
1862
2497
  continue;
1863
2498
  const n = inst[i];
2499
+ if (O && !O[n])
2500
+ continue;
1864
2501
  if (stud) {
1865
2502
  mul12To(instM, instPP[n].studM, stud[i] * 12, wm, n * 12);
1866
2503
  writeM4(MA, w * 16, wm);
@@ -1890,10 +2527,11 @@ function buildLdrScene(insts, pack, P, color, mark) {
1890
2527
  for (const t of toggles)
1891
2528
  t.mesh.count = (t.flag === "studs" ? studs : under) ? t.visible : t.all;
1892
2529
  };
1893
- const setStep = (s) => {
2530
+ const setStep = (s, mask = null) => {
1894
2531
  if (!steps)
1895
2532
  throw new Error("buildLdrScene: setStep needs P.steps");
1896
2533
  stepS = s == null ? STEP_NEVER - 1 : s;
2534
+ only = mask;
1897
2535
  return applySteps();
1898
2536
  };
1899
2537
  const box = new THREE.Box3;
@@ -1924,21 +2562,14 @@ function buildLdrScene(insts, pack, P, color, mark) {
1924
2562
  m.needsUpdate = true;
1925
2563
  }
1926
2564
  };
1927
- const swapStuds = (alt) => {
1928
- const saved = studMeshes.map((s) => s.im.geometry);
1929
- for (const s of studMeshes) {
1930
- const k2 = alt.header.studKinds[s.kind] ? s.kind : Object.keys(alt.header.studKinds).find((k) => k.replace("p/8/", "p/") === s.kind.replace("p/8/", "p/"));
1931
- if (k2)
1932
- s.im.geometry = geom(alt.header.studKinds[k2].body, alt.arr, Q);
1933
- }
1934
- return () => studMeshes.forEach((s, i) => s.im.geometry = saved[i]);
1935
- };
1936
2565
  const setLod = (on) => {
1937
2566
  root.enabled = on && LOD;
1938
2567
  if (!root.enabled) {
1939
2568
  for (const c of root.clusters) {
1940
2569
  c.cur = 0;
1941
2570
  c.edgeOk = true;
2571
+ for (const l of c.lines)
2572
+ l.geometry.drawRange.count = Infinity;
1942
2573
  }
1943
2574
  refresh();
1944
2575
  }
@@ -1946,9 +2577,31 @@ function buildLdrScene(insts, pack, P, color, mark) {
1946
2577
  insts = null;
1947
2578
  cull = null;
1948
2579
  byPart.clear();
1949
- return { root, stats, setCull, setSide, setEdges, setCond, swapStuds, setLod, setStep, box, texturesReady };
2580
+ return { root, stats, setCull, setSide, setEdges, setCond, setLod, setStep, box, texturesReady };
2581
+ }
2582
+ async function warmPackGeometry(pack, stop = () => false, sliceMs = 8) {
2583
+ const { header: H, arr } = pack;
2584
+ const list = [];
2585
+ for (const p of Object.values(H.parts ?? {}))
2586
+ for (const b of [p.body, p.under])
2587
+ if (b) {
2588
+ list.push(b);
2589
+ for (const l of b.lod ?? [])
2590
+ list.push(l);
2591
+ }
2592
+ for (const k of Object.values(H.studKinds ?? {}))
2593
+ if (k?.body)
2594
+ list.push(k.body);
2595
+ let i = 0;
2596
+ while (i < list.length && !stop()) {
2597
+ const t = performance.now();
2598
+ while (i < list.length && performance.now() - t < sliceMs)
2599
+ geom(list[i++], arr);
2600
+ if (i < list.length)
2601
+ await new Promise((r) => setTimeout(r, 0));
2602
+ }
1950
2603
  }
1951
- // ../../../../../../../tmp/ldr-build-pIke9r/src/scene.ts
2604
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/scene.ts
1952
2605
  import * as THREE2 from "three";
1953
2606
  function colorFn(src, pack, fallback) {
1954
2607
  const table = new Map;
@@ -1993,12 +2646,8 @@ function createLdrObject(instances, pack, options = {}) {
1993
2646
  const o = { edges: true, conditionalLines: true, cullStuds: true, cullUndersides: true, side: "front", material: "plastic", ...options };
1994
2647
  const color = colorFn(o.colors, pack, new THREE2.Color(o.fallbackColor ?? 10528169));
1995
2648
  const useTex = o.textures !== false;
1996
- const pick = (i) => useTex && i.texPart && pack.header.parts[i.texPart] ? i.texPart : i.part;
1997
- const all = instances.map((i) => ({ part: pick(i), color: String(i.color), m: i.m, steps: i.steps }));
1998
- const key = (i) => i.steps.map((x) => String(x).padStart(6, "0")).join(".");
1999
- const uniq = [...new Set(all.map(key))].sort();
2000
- const rank = new Map(uniq.map((k, j) => [k, j]));
2001
- const stepOf = all.map((i) => rank.get(key(i)));
2649
+ const { all, stepOf, nSteps } = sceneInstances(instances, pack.header, useTex);
2650
+ const uniq = { length: nSteps };
2002
2651
  const stepViews = new Array(uniq.length).fill(null);
2003
2652
  instances.forEach((i, k) => {
2004
2653
  if (i.view)
@@ -2034,10 +2683,10 @@ function createLdrObject(instances, pack, options = {}) {
2034
2683
  cur = null;
2035
2684
  };
2036
2685
  const multiStep = uniq.length > 1;
2037
- const drawnAt = (step) => all.filter((i, k) => (step == null || stepOf[k] <= step) && pack.header.parts[i.part]).length;
2686
+ const drawnAt = (step, mask) => all.filter((i, k) => (step == null || stepOf[k] <= step) && (!mask || mask[k]) && pack.header.parts[i.part]).length;
2038
2687
  const build = () => {
2039
2688
  const t0 = performance.now();
2040
- cur = buildLdrScene(all, pack, { pack: "", cullStuds: cs, cullUnder: cu, edges: edges ? "idx" : false, side, cond, condStuds: o.conditionalStudLines !== false, tex: o.textures !== false, lod: o.lod !== false, lodPx: o.lodPx, lodEdgePx: o.lodEdgePx, steps: multiStep ? stepOf : undefined }, color, () => {});
2689
+ cur = buildLdrScene(all, pack, { cullStuds: cs, cullUnder: cu, edges, side, cond, condStuds: o.conditionalStudLines !== false, tex: o.textures !== false, lod: o.lod !== false, lodPx: o.lodPx, lodEdgePx: o.lodEdgePx, lodEdgeMinPx: o.lodEdgeMinPx, lodUnder: o.lodUnder, steps: multiStep ? stepOf : undefined, cull: o.precomputedCull }, color, () => {});
2041
2690
  pairs.clear();
2042
2691
  if (o.material === "plastic")
2043
2692
  cur.root.traverse((x) => {
@@ -2055,11 +2704,11 @@ function createLdrObject(instances, pack, options = {}) {
2055
2704
  Object.assign(stats, { drawn: drawnAt(null), studsTotal: cur.stats.studsTotal, studsHidden: cur.stats.studsHidden, undersTotal: cur.stats.undersTotal, undersHidden: cur.stats.undersHidden, condBatches: cur.stats.condBatches ?? 0, texBatches: cur.stats.texBatches ?? 0, textures: cur.stats.textures ?? 0, clusters: cur.stats.clusters ?? 0, buildMs: performance.now() - t0 });
2056
2705
  api.texturesReady = cur.texturesReady;
2057
2706
  };
2058
- const setStep = (step) => {
2707
+ const setStep = (step, mask = null) => {
2059
2708
  if (!multiStep)
2060
2709
  return;
2061
2710
  const t0 = performance.now();
2062
- Object.assign(stats, cur.setStep(step), { drawn: drawnAt(step), buildMs: performance.now() - t0 });
2711
+ Object.assign(stats, cur.setStep(step, mask), { drawn: drawnAt(step, mask), buildMs: performance.now() - t0 });
2063
2712
  };
2064
2713
  const api = { texturesReady: Promise.resolve() };
2065
2714
  build();
@@ -2108,18 +2757,7 @@ function createLdrObject(instances, pack, options = {}) {
2108
2757
  dispose: disposeCur
2109
2758
  });
2110
2759
  }
2111
- // ../../../../../../../tmp/ldr-build-pIke9r/src/pack-io.ts
2112
- import { decompress } from "fzstd";
2113
- async function decompressPack(data) {
2114
- const u = data instanceof Uint8Array ? data : new Uint8Array(data);
2115
- const own = (o) => o.buffer.slice(o.byteOffset, o.byteOffset + o.byteLength);
2116
- if (u[0] === 40 && u[1] === 181 && u[2] === 47 && u[3] === 253)
2117
- return own(decompress(u));
2118
- if (u[0] === 31 && u[1] === 139)
2119
- return new Response(new Blob([u]).stream().pipeThrough(new DecompressionStream("gzip"))).arrayBuffer();
2120
- return own(u);
2121
- }
2122
- // ../../../../../../../tmp/ldr-build-pIke9r/src/cdn.ts
2760
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/parts-cdn.ts
2123
2761
  import { decompress as decompress2 } from "fzstd";
2124
2762
  var DEFAULT_PARTS_CDN = "https://ldr-demo.vercel.app/cdn/v1/";
2125
2763
  var indexCache = new Map;
@@ -2180,7 +2818,22 @@ function mergePacks(packs, extra = {}) {
2180
2818
  return decodePack(out.buffer);
2181
2819
  }
2182
2820
  async function loadParts(names, o = {}) {
2183
- const cdn = o.cdn ?? DEFAULT_PARTS_CDN, f = o.fetch ?? fetch, gap = o.gap ?? 65536;
2821
+ names = [...names];
2822
+ try {
2823
+ return await loadPartsOnce(names, o);
2824
+ } catch (e) {
2825
+ const cdn = o.cdn ?? DEFAULT_PARTS_CDN, f = o.fetch ?? fetch;
2826
+ indexCache.delete(cdn);
2827
+ const fresh = (u, i) => f(u, { ...i, cache: "reload" });
2828
+ try {
2829
+ return await loadPartsOnce(names, { ...o, fetch: fresh });
2830
+ } catch {
2831
+ throw e;
2832
+ }
2833
+ }
2834
+ }
2835
+ async function loadPartsOnce(names, o) {
2836
+ const cdn = o.cdn ?? DEFAULT_PARTS_CDN, f = o.fetch ?? fetch, gap = o.gap ?? 16384;
2184
2837
  const idx = await loadPartsIndex(cdn, f);
2185
2838
  const want = [...new Set([...names].map(norm))];
2186
2839
  const missing = [];
@@ -2223,7 +2876,7 @@ async function loadParts(names, o = {}) {
2223
2876
  }
2224
2877
  }
2225
2878
  };
2226
- await Promise.all(Array.from({ length: Math.min(o.concurrency ?? 6, groups.length) }, worker));
2879
+ await Promise.all(Array.from({ length: Math.min(o.concurrency ?? 24, groups.length) }, worker));
2227
2880
  const shards = want.filter((n) => shardCache.has(cdn + n)).map((n) => shardCache.get(cdn + n));
2228
2881
  const pack = shards.length ? mergePacks(shards, { colors: idx.colors }) : decodePack(emptyPack(idx.colors));
2229
2882
  return { pack, missing, requests: groups.length, bytes };
@@ -2236,10 +2889,11 @@ function emptyPack(colors) {
2236
2889
  b.set(h, 4);
2237
2890
  return b.buffer;
2238
2891
  }
2239
- async function loadModel(source, o = {}) {
2892
+ async function prepareModel(source, o = {}) {
2240
2893
  const t0 = performance.now();
2241
2894
  const f = o.fetch ?? fetch;
2242
2895
  const idxP = loadPartsIndex(o.cdn ?? DEFAULT_PARTS_CDN, f);
2896
+ idxP.catch(() => {});
2243
2897
  const text = o.text ? source : await f(source).then((r) => {
2244
2898
  if (!r.ok)
2245
2899
  throw new Error(`ldr: ${r.status} fetching ${source}`);
@@ -2247,21 +2901,134 @@ async function loadModel(source, o = {}) {
2247
2901
  });
2248
2902
  const t1 = performance.now();
2249
2903
  const name = o.name ?? (o.text ? "main.ldr" : decodeURIComponent(source.split(/[?#]/)[0].split("/").pop() || "main.ldr"));
2250
- const insts = parseModel(text, name, { looseGeometry: false });
2904
+ const insts = parseModel(text, name, { looseGeometry: false, callouts: o.callouts });
2251
2905
  const t2 = performance.now();
2906
+ o.onParsed?.(insts);
2252
2907
  await idxP;
2253
2908
  const { pack, missing, requests, bytes } = await loadParts(insts.filter((i) => !i.embedded).map((i) => i.part), o);
2254
2909
  const t3 = performance.now();
2255
- const obj = createLdrObject(insts, pack, o);
2256
- for (const m of missing)
2910
+ const cull = o.cull ? precomputeCull(insts, pack.header, o.textures !== false) : undefined;
2911
+ return { insts, pack, missing, requests, bytes, cull, timings: { fetchModel: t1 - t0, parse: t2 - t1, parts: t3 - t2, ...cull ? { cull: performance.now() - t3 } : {} } };
2912
+ }
2913
+
2914
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/load-worker.gen.ts
2915
+ var load_worker_gen_default = 'var mt=ArrayBuffer,_=Uint8Array,ge=Uint16Array,ht=Int16Array;var be=Int32Array,Se=function(e,t,n){if(_.prototype.slice)return _.prototype.slice.call(e,t,n);if(t==null||t<0)t=0;if(n==null||n>e.length)n=e.length;var r=new _(n-t);return r.set(e.subarray(t,n)),r},ce=function(e,t,n,r){if(_.prototype.fill)return _.prototype.fill.call(e,t,n,r);if(n==null||n<0)n=0;if(r==null||r>e.length)r=e.length;for(;n<r;++n)e[n]=t;return e},gt=function(e,t,n,r){if(_.prototype.copyWithin)return _.prototype.copyWithin.call(e,t,n,r);if(n==null||n<0)n=0;if(r==null||r>e.length)r=e.length;while(n<r)e[t++]=e[n++]};var bt=["invalid zstd data","window size too large (>2046MB)","invalid block type","FSE accuracy too high","match distance too far back","unexpected EOF"],K=function(e,t,n){var r=Error(t||bt[e]);if(r.code=e,Error.captureStackTrace)Error.captureStackTrace(r,K);if(!n)throw r;return r},Ne=function(e,t,n){var r=0,o=0;for(;r<n;++r)o|=e[t++]<<(r<<3);return o},yt=function(e,t){return(e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24)>>>0},dt=function(e,t){var n=e[0]|e[1]<<8|e[2]<<16;if(n==3126568&&e[3]==253){var r=e[4],o=r>>5&1,s=r>>2&1,i=r&3,c=r>>6;if(r&8)K(0);var a=6-o,l=i==3?4:i,f=Ne(e,a,l);a+=l;var p=c?1<<c:o,m=Ne(e,a,p)+(c==1&&256),b=m;if(!o){var A=1<<10+(e[5]>>3);b=A+(A>>3)*(e[5]&7)}if(b>2145386496)K(1);var u=new _((t==1?m||b:t?0:b)+12);return u[0]=1,u[4]=4,u[8]=8,{b:a+p,y:0,l:0,d:f,w:t&&t!=1?t:u.subarray(12),e:b,o:new be(u.buffer,0,3),u:m,c:s,m:Math.min(131072,b)}}else if((n>>4|e[3]<<20)==25481893)return yt(e,4)+8;K(0)},re=function(e){var t=0;for(;1<<t<=e;++t);return t-1},ue=function(e,t,n){var r=(t<<3)+4,o=(e[t]&15)+5;if(o>n)K(3);var s=1<<o,i=s,c=-1,a=-1,l=-1,f=s,p=new mt(512+(s<<2)),m=new ht(p,0,256),b=new ge(p,0,256),A=new ge(p,512,s),u=512+(s<<1),h=new _(p,u,s),E=new _(p,u+s);while(c<255&&i>0){var y=re(i+1),g=r>>3,C=(1<<y+1)-1,B=(e[g]|e[g+1]<<8|e[g+2]<<16)>>(r&7)&C,d=(1<<y)-1,M=C-i-1,P=B&d;if(P<M)r+=y,B=P;else if(r+=y+1,B>d)B-=M;if(m[++c]=--B,B==-1)i+=B,h[--f]=c;else i-=B;if(!B)do{var F=r>>3;a=(e[F]|e[F+1]<<8)>>(r&7)&3,r+=2,c+=a}while(a==3)}if(c>255||i)K(0);var S=0,U=(s>>1)+(s>>3)+3,W=s-1;for(var H=0;H<=c;++H){var v=m[H];if(v<1){b[H]=-v;continue}for(l=0;l<v;++l){h[S]=H;do S=S+U&W;while(S>=f)}}if(S)K(0);for(l=0;l<s;++l){var w=b[h[l]]++,L=E[l]=o-re(w);A[l]=(w<<L)-s}return[r+7>>3,{b:o,s:h,n:E,t:A}]},xt=function(e,t){var n=0,r=-1,o=new _(292),s=e[t],i=o.subarray(0,256),c=o.subarray(256,268),a=new ge(o.buffer,268);if(s<128){var l=ue(e,t+1,6),f=l[0],p=l[1];t+=s;var m=f<<3,b=e[t];if(!b)K(0);var A=0,u=0,h=p.b,E=h,y=(++t<<3)-8+re(b);for(;;){if(y-=h,y<m)break;var g=y>>3;if(A+=(e[g]|e[g+1]<<8)>>(y&7)&(1<<h)-1,i[++r]=p.s[A],y-=E,y<m)break;g=y>>3,u+=(e[g]|e[g+1]<<8)>>(y&7)&(1<<E)-1,i[++r]=p.s[u],h=p.n[A],A=p.t[A],E=p.n[u],u=p.t[u]}if(++r>255)K(0)}else{r=s-127;for(;n<r;n+=2){var C=e[++t];i[n]=C>>4,i[n+1]=C&15}++t}var B=0;for(n=0;n<r;++n){var d=i[n];if(d>11)K(0);B+=d&&1<<d-1}var M=re(B)+1,P=1<<M,F=P-B;if(F&F-1)K(0);i[r++]=re(F)+1;for(n=0;n<r;++n){var d=i[n];++c[i[n]=d&&M+1-d]}var S=new _(P<<1),U=S.subarray(0,P),W=S.subarray(P);a[M]=0;for(n=M;n>0;--n){var H=a[n];ce(W,n,H,a[n-1]=H+c[n]*(1<<M-n))}if(a[0]!=P)K(0);for(n=0;n<r;++n){var v=i[n];if(v){var w=a[v];ce(U,n,w,a[v]=w+(1<<M-v))}}return[t,{n:W,b:M,s:U}]},wt=ue(new _([81,16,99,140,49,198,24,99,12,33,196,24,99,102,102,134,70,146,4]),0,6)[1],vt=ue(new _([33,20,196,24,99,140,33,132,16,66,8,33,132,16,66,8,33,68,68,68,68,68,68,68,68,36,9]),0,6)[1],At=ue(new _([32,132,16,66,102,70,68,68,68,68,36,73,2]),0,5)[1],$e=function(e,t){var n=e.length,r=new be(n);for(var o=0;o<n;++o)r[o]=t,t+=1<<e[o];return r},Ce=new _(new be([0,0,0,0,16843009,50528770,134678020,202050057,269422093]).buffer,0,36),Mt=$e(Ce,0),Pe=new _(new be([0,0,0,0,0,0,0,0,16843009,50528770,117769220,185207048,252579084,16]).buffer,0,53),St=$e(Pe,3),le=function(e,t,n){var r=e.length,o=t.length,s=e[r-1],i=(1<<n.b)-1,c=-n.b;if(!s)K(0);var a=0,l=n.b,f=(r<<3)-8+re(s)-l,p=-1;for(;f>c&&p<o;){var m=f>>3,b=(e[m]|e[m+1]<<8|e[m+2]<<16)>>(f&7);a=(a<<l|b)&i,t[++p]=n.s[a],f-=l=n.n[a]}if(f!=c||p+1!=o)K(0)},Ct=function(e,t,n){var r=6,o=t.length,s=o+3>>2,i=s<<1,c=s+i;le(e.subarray(r,r+=e[0]|e[1]<<8),t.subarray(0,s),n),le(e.subarray(r,r+=e[2]|e[3]<<8),t.subarray(s,i),n),le(e.subarray(r,r+=e[4]|e[5]<<8),t.subarray(i,c),n),le(e.subarray(r),t.subarray(c),n)},Pt=function(e,t,n){var r,o=t.b,s=e[o],i=s>>1&3;t.l=s&1;var c=s>>3|e[o+1]<<5|e[o+2]<<13,a=(o+=3)+c;if(i==1){if(o>=e.length)return;if(t.b=o+1,n)return ce(n,e[o],t.y,t.y+=c),n;return ce(new _(c),e[o])}if(a>e.length)return;if(i==0){if(t.b=a,n)return n.set(e.subarray(o,a),t.y),t.y+=c,n;return Se(e,o,a)}if(i==2){var l=e[o],f=l&3,p=l>>2&3,m=l>>4,b=0,A=0;if(f<2)if(p&1)m|=e[++o]<<4|(p&2&&e[++o]<<12);else m=l>>3;else if(A=p,p<2)m|=(e[++o]&63)<<4,b=e[o]>>6|e[++o]<<2;else if(p==2)m|=e[++o]<<4|(e[++o]&3)<<12,b=e[o]>>2|e[++o]<<6;else m|=e[++o]<<4|(e[++o]&63)<<12,b=e[o]>>6|e[++o]<<2|e[++o]<<10;++o;var u=n?n.subarray(t.y,t.y+t.m):new _(t.m),h=u.length-m;if(f==0)u.set(e.subarray(o,o+=m),h);else if(f==1)ce(u,e[o++],h);else{var E=t.h;if(f==2){var y=xt(e,o);b+=o-(o=y[0]),t.h=E=y[1]}else if(!E)K(0);(A?Ct:le)(e.subarray(o,o+=b),u.subarray(h),E)}var g=e[o++];if(g){if(g==255)g=(e[o++]|e[o++]<<8)+32512;else if(g>127)g=g-128<<8|e[o++];var C=e[o++];if(C&3)K(0);var B=[vt,At,wt];for(var d=2;d>-1;--d){var M=C>>(d<<1)+2&3;if(M==1){var P=new _([0,0,e[o++]]);B[d]={s:P.subarray(2,3),n:P.subarray(0,1),t:new ge(P.buffer,0,1),b:0}}else if(M==2)r=ue(e,o,9-(d&1)),o=r[0],B[d]=r[1];else if(M==3){if(!t.t)K(0);B[d]=t.t[d]}}var F=t.t=B,S=F[0],U=F[1],W=F[2],H=e[a-1];if(!H)K(0);var v=(a<<3)-8+re(H)-W.b,w=v>>3,L=0,V=(e[w]|e[w+1]<<8)>>(v&7)&(1<<W.b)-1;w=(v-=U.b)>>3;var I=(e[w]|e[w+1]<<8)>>(v&7)&(1<<U.b)-1;w=(v-=S.b)>>3;var N=(e[w]|e[w+1]<<8)>>(v&7)&(1<<S.b)-1;for(++g;--g;){var T=W.s[V],x=W.n[V],z=S.s[N],R=S.n[N],D=U.s[I],O=U.n[I];w=(v-=D)>>3;var j=1<<D,k=j+((e[w]|e[w+1]<<8|e[w+2]<<16|e[w+3]<<24)>>>(v&7)&j-1);w=(v-=Pe[z])>>3;var G=St[z]+((e[w]|e[w+1]<<8|e[w+2]<<16)>>(v&7)&(1<<Pe[z])-1);w=(v-=Ce[T])>>3;var X=Mt[T]+((e[w]|e[w+1]<<8|e[w+2]<<16)>>(v&7)&(1<<Ce[T])-1);if(w=(v-=x)>>3,V=W.t[V]+((e[w]|e[w+1]<<8)>>(v&7)&(1<<x)-1),w=(v-=R)>>3,N=S.t[N]+((e[w]|e[w+1]<<8)>>(v&7)&(1<<R)-1),w=(v-=O)>>3,I=U.t[I]+((e[w]|e[w+1]<<8)>>(v&7)&(1<<O)-1),k>3)t.o[2]=t.o[1],t.o[1]=t.o[0],t.o[0]=k-=3;else{var Y=k-(X!=0);if(Y){if(k=Y==3?t.o[0]-1:t.o[Y],Y>1)t.o[2]=t.o[1];t.o[1]=t.o[0],t.o[0]=k}else k=t.o[0]}for(var d=0;d<X;++d)u[L+d]=u[h+d];L+=X,h+=X;var Z=L-k;if(Z<0){var J=-Z,ee=t.e+Z;if(J>G)J=G;for(var d=0;d<J;++d)u[L+d]=t.w[ee+d];L+=J,G-=J,Z=0}for(var d=0;d<G;++d)u[L+d]=u[Z+d];L+=G}if(L!=h)while(h<u.length)u[L++]=u[h++];else L=u.length;if(n)t.y+=L;else u=Se(u,0,L)}else if(n){if(t.y+=m,h)for(var d=0;d<m;++d)u[d]=u[h+d]}else if(h)u=Se(u,h);return t.b=a,u}K(2)},Et=function(e,t){if(e.length==1)return e[0];var n=new _(t);for(var r=0,o=0;r<e.length;++r){var s=e[r];n.set(s,o),o+=s.length}return n};function je(e,t){var n=[],r=+!t,o=0,s=0;for(;e.length;){var i=dt(e,r||t);if(typeof i=="object"){if(r){if(t=null,i.w.length==i.u)n.push(t=i.w),s+=i.u}else n.push(t),i.e=0;for(;!i.l;){var c=Pt(e,i,t);if(!c)K(5);if(t)i.e=i.y;else n.push(c),s+=c.length,gt(i.w,0,c.length),i.w.set(c,i.w.length-c.length)}o=i.b+i.c*4}else o=i;e=e.subarray(o)}return Et(n,s)}function ye(e){let t=new DataView(e).getUint32(0,!0),n=JSON.parse(new TextDecoder().decode(new Uint8Array(e,4,t))),r=4+t;return{header:n,arr:(s)=>s&&(s[2]==="f32"?new Float32Array(e,r+s[0],s[1]):s[2]==="u16"?new Uint16Array(e,r+s[0],s[1]):s[2]==="u8"?new Uint8Array(e,r+s[0],s[1]):new Uint32Array(e,r+s[0],s[1])),bytes:e.byteLength,buffer:e}}var q=(e)=>e.trim().toLowerCase().replace(/\\\\/g,"/").replace(/\\/+/g,"/");function Ee(e){if(/^0x/i.test(e))return parseInt(e,16);return+e}var Ve=/^~?\\s*moved\\s+to\\s+(.+)$/i,Tt=new Set(["FILE","NOFILE","!DATA","!:","STEP","BFC","ROTSTEP","BUFEXCHG","!TEXMAP"]),Je=new Set(["part","subpart","primitive","8_primitive","48_primitive","shortcut","helper"]),Lt=new Set(["model","submodel","configuration"]),It=/^(?:!?LDRAW_ORG|Unofficial|Official\\s+LCAD)\\s+(\\S+)/i;function He(e){let t=It.exec(e);if(!t)return;let n=t[1].toLowerCase().replace(/^unofficial_/,"");return Je.has(n)||Lt.has(n)?n:void 0}function kt(e){let t=[],n=0;while(n<e.length){while(e[n]===" "||e[n]==="\\t")n++;if(n>=e.length)break;if(e[n]===\'"\'){let r="";n++;while(n<e.length&&e[n]!==\'"\'){if(e[n]==="\\\\"&&n+1<e.length)n++;r+=e[n++]}n++,t.push(r)}else{let r=n;while(r<e.length&&e[r]!==" "&&e[r]!=="\\t")r++;t.push(e.slice(n,r)),n=r}}return t}function Rt(e,t=!1){let n=/^\\s*(\\S+)\\s+(.*)$/.exec(e);if(!n)return null;let r=n[1].toUpperCase(),o=r==="PLANAR"?9:r==="CYLINDRICAL"?10:r==="SPHERICAL"?11:0;if(!o)return null;let s=n[2].trim().split(/\\s+/);if(s.length<o+1)return null;let i=s.slice(0,o).map(Number);if(!i.every(Number.isFinite))return null;let c=n[2].trim();for(let p=0;p<o;p++)c=c.replace(/^\\S+\\s*/,"");let a=kt(c);if(!a.length)return null;let l={method:r,p1:i.slice(0,3),p2:i.slice(3,6),p3:i.slice(6,9),texture:a[0]};if(o>=10)l.a=i[9];if(o===11)l.b=i[10];let f=a.findIndex((p,m)=>m>0&&p.toUpperCase()==="GLOSSMAP");if(f>0&&a[f+1])l.glossmap=a[f+1];if(t)l.next=!0;return l}var Dt=(e)=>{let t=e.replace(/[^A-Za-z0-9+/]/g,""),n=t+"=".repeat((4-t.length%4)%4),r=atob(n),o=new Uint8Array(r.length);for(let s=0;s<r.length;s++)o[s]=r.charCodeAt(s);return o};function Ft(e){let t=e.length,n=1,r=(l)=>l===32||l===9,o=()=>{while(n<t&&r(e.charCodeAt(n)))n++;let l=n;while(n<t&&!r(e.charCodeAt(n)))n++;return l<n?e.slice(l,n):null},s=o();if(s===null)return null;let i=Array(12);for(let l=0;l<12;l++){let f=o();if(f===null)return null;i[l]=+f}while(n<t&&r(e.charCodeAt(n)))n++;if(n>=t)return null;let c=e.slice(n),a=/[ \\t]{2,}|\\t/.test(c)?c.split(/\\s+/).join(" "):c;return{t:1,color:Ee(s),m:i,file:q(a)}}function Ge(e){let t=+e[0];if(!(t>=1&&t<=5)||e.length<2)return null;let n=Ee(e[1]),r=e.slice(2).map(Number);if(t===1)return{t:1,color:n,m:r.slice(0,12),file:q(e.slice(14).join(" "))};if(t===2)return{t:2,color:n,p:r.slice(0,6)};if(t===3)return{t:3,color:n,p:r.slice(0,9)};if(t===4)return{t:4,color:n,p:r.slice(0,12)};return{t:5,color:n,p:r.slice(0,12)}}function Ze(e,t="main.ldr",n={}){let r=!!n.geometryText,o=new Map,s=null,i="",c,a=null,l=[],f=null,p=()=>{if(!a)return;let y=Dt(a.chunks.join("")),g=y[0]===137&&y[1]===80&&y[2]===78&&y[3]===71;(c??=new Map).set(q(a.name),{name:a.name,bytes:y,...g?{mime:"image/png"}:{}}),a=null},m=!0,b=(y)=>{if(p(),s={name:q(y),cmds:[]},o.set(s.name,s),!i)i=s.name;l=[],f=null,m=!0},A=!1,u=!1,h=()=>{if(u)return;u=!0,o.clear(),s=null,i=""},E=(y,g)=>{if(f){y.tex=f,f=null;return}let C=l[l.length-1];if(!C)return;if(C.fallback){if(!g)y.fallback=!0}else y.tex=C.map};for(let y of e.split(`\n`)){let g=y.trim();if(!g)continue;if(r&&g.charCodeAt(0)>=50&&g.charCodeAt(0)<=53&&(g.charCodeAt(1)===32||g.charCodeAt(1)===9)){if(a||A)continue;if(!s)b(t);let M=g.slice(2).trimStart(),P=M.search(/\\s/),F={t:g.charCodeAt(0)-48,color:Ee(P<0?M:M.slice(0,P)),p:[],src:g};E(F,!1),s.cmds.push(F),m=!1;continue}if(g.charCodeAt(0)===48&&(g.charCodeAt(1)===32||g.charCodeAt(1)===9)){let M=2;while(g.charCodeAt(M)===32||g.charCodeAt(M)===9)M++;let P=M;while(P<g.length&&g.charCodeAt(P)!==32&&g.charCodeAt(P)!==9)P++;let F=g.slice(M,P);if(!Tt.has(F)){if(A||a)continue;if(!s)b(t);let S=g.slice(M),U={t:0,text:S};if(F.charCodeAt(0)===33)U.meta=F;if(f=null,m&&!s.org){let H=He(S);if(H)s.org=H}let W=S.match(Ve);if(W&&!s.movedTo){let H=W[1].trim().replace(/\\\\/g,"/");if(!/\\.(dat|ldr|mpd)$/i.test(H))H+=".dat";s.movedTo=q(H)}s.cmds.push(U);continue}}if(g.charCodeAt(0)===49&&(g.charCodeAt(1)===32||g.charCodeAt(1)===9)&&!a&&!A){let M=Ft(g);if(M){if(!s)b(t);E(M,!1),s.cmds.push(M),m=!1;continue}}let C=g.split(/\\s+/);if(+C[0]===0){let M=g.slice(1).trim();if(C[1]==="FILE"){h(),A=!1,b(M.slice(5));continue}if(C[1]==="NOFILE"){p(),s=null,A=!0;continue}if(C[1]==="!DATA"){h(),p(),s=null,A=!1,a={name:M.slice(5).trim(),chunks:[]};continue}if(A)continue;if(a){if(C[1]==="!:")a.chunks.push(C.slice(2).join(""));continue}if(!s)b(t);let P={t:0,text:M};if(C[1]==="STEP")P.step=!0,l=[],f=null;else if(C[1]==="BFC")P.bfc=C.slice(2).join(" ");else if(C[1]==="ROTSTEP")if(P.meta="ROTSTEP",P.step=!0,l=[],f=null,(C[2]??"").toUpperCase()==="END")P.rotstep={x:0,y:0,z:0,mode:"END"};else{let S=(C[5]??"REL").toUpperCase();P.rotstep={x:+C[2]||0,y:+C[3]||0,z:+C[4]||0,mode:["REL","ABS","ADD"].includes(S)?S:"REL"}}else if(C[1]==="BUFEXCHG"){P.meta="BUFEXCHG";let S=(C[2]??"").toUpperCase();P.bufexchg={op:S==="RETRIEVE"?"RETRIEVE":"STORE",buf:C[3]??"A"}}else if(C[1]?.startsWith("!"))P.meta=C[1];if(m&&!s.org){let S=He(M);if(S)s.org=S}if(C[1]==="!TEXMAP"){let S=(C[2]??"").toUpperCase();if(f=null,S==="START"||S==="NEXT"){let U=Rt(M.replace(/^!TEXMAP\\s+\\S+/i,""),S==="NEXT");if(P.texmap={op:S,...U?{map:U}:{}},U)if((s.texmaps??=[]).push(U),S==="START")l.push({map:U,fallback:!1});else f=U}else if(S==="FALLBACK"){P.texmap={op:S};let U=l[l.length-1];if(U)U.fallback=!0}else if(S==="END")P.texmap={op:S},l.pop()}else if(C[1]==="!:"){f=null;let S=Ge(C.slice(2));if(S)E(S,!0),P.geom=S}else f=null;let F=M.match(Ve);if(F&&!s.movedTo){let S=F[1].trim().replace(/\\\\/g,"/");if(!/\\.(dat|ldr|mpd)$/i.test(S))S+=".dat";s.movedTo=q(S)}s.cmds.push(P);continue}if(a||A)continue;if(!s)b(t);let d=Ge(C);if(!d)continue;E(d,!1),s.cmds.push(d),m=!1}return p(),c?{main:i,files:o,data:c}:{main:i,files:o}}var Zt=Math.PI/180;function qe(e,t){let n=(r)=>[t[3]*r[0]+t[4]*r[1]+t[5]*r[2]+t[0],t[6]*r[0]+t[7]*r[1]+t[8]*r[2]+t[1],t[9]*r[0]+t[10]*r[1]+t[11]*r[2]+t[2]];return{...e,p1:n(e.p1),p2:n(e.p2),p3:n(e.p3)}}function Qe(e,t){let[n,r,o,s,i,c,a,l,f,p,m,b]=e,[A,u,h,E,y,g,C,B,d,M,P,F]=t;return[s*A+i*u+c*h+n,a*A+l*u+f*h+r,p*A+m*u+b*h+o,s*E+i*C+c*M,s*y+i*B+c*P,s*g+i*d+c*F,a*E+l*C+f*M,a*y+l*B+f*P,a*g+l*d+f*F,p*E+m*C+b*M,p*y+m*B+b*P,p*g+m*d+b*F]}var Te=[0,0,0,1,0,0,0,1,0,0,0,1];var Xe=new WeakMap,Ut=/^(s|8|48)\\//;function Le(e,t){let n=e.files.get(q(t));if(!n)return"part";let r=Xe.get(n);if(r)return r;if(n.org)r=Je.has(n.org)?"part":"model";else if(n.name===e.main)r="model";else r=n.cmds.some((o)=>o.t>=2||o.t===0&&!!o.geom||o.t===1&&Ut.test(o.file))?"part":"model";return Xe.set(n,r),r}var _e=new WeakMap;function et(e){let t=_e.get(e);if(t)return t;t=[];let n=0;for(let r of e.cmds){if(r.t===0&&r.step){n++;continue}if((r.t>=2||r.t===0&&r.geom&&r.geom.t>=2)&&t[t.length-1]!==n)t.push(n)}return _e.set(e,t),t}var Ke=(e)=>e>16777215?"0x"+e.toString(16).toUpperCase():String(e),Ot=(e)=>e.t===0?"0 "+e.text:e.t===1?`1 ${Ke(e.color)} ${e.m.join(" ")} ${e.file}`:e.src?e.src:`${e.t} ${Ke(e.color)} ${e.p.join(" ")}`,Ie=(e,t)=>`${q(e)}#${t}`;function zt(e,t){let n=[],r=0,o=(s)=>!!s&&s.t===0&&s.texmap?.op==="NEXT";for(let s of e.cmds){if(s.t===0){if(s.step){r++;continue}if(s.bfc!==void 0){n.push(s);continue}if(r!==t)continue;if(s.texmap)n.push(s);else if(s.geom){if(s.geom.t>=2)n.push(s);else if(o(n[n.length-1]))n.pop()}continue}if(r!==t)continue;if(s.t===1){if(o(n[n.length-1]))n.pop();continue}n.push(s)}return{name:Ie(e.name,t),cmds:n}}function tt(e,t){return[`0 ldr: own geometry of ${e.name}, step ${t}`,...zt(e,t).cmds.map(Ot)].join(`\n`)+`\n`}function Bt(e){let t=2166136261;for(let n=0;n<e.length;n++)t^=e.charCodeAt(n),t=Math.imul(t,16777619);return(t>>>0).toString(16).padStart(8,"0")}function nt(e){let[t,n,r,o,s,i,c,a,l,f,p,m]=e,b=a*m-l*p,A=-(c*m-l*f),u=c*p-a*f,h=o*b+s*A+i*u;if(!Number.isFinite(h)||Math.abs(h)<0.000000000001)return null;let E=1/h,y=[b*E,-(s*m-i*p)*E,(s*l-i*a)*E,A*E,(o*m-i*f)*E,-(o*l-i*c)*E,u*E,-(o*p-s*f)*E,(o*a-s*c)*E];return[-(y[0]*t+y[1]*n+y[2]*r),-(y[3]*t+y[4]*n+y[5]*r),-(y[6]*t+y[7]*n+y[8]*r),...y]}var Nt=(e)=>String(+e.toFixed(6)||0),We=(e)=>\'"\'+e.replace(/\\\\/g,"\\\\\\\\").replace(/"/g,"\\\\\\"")+\'"\';function rt(e,t){let n=[...t.p1,...t.p2,...t.p3,...t.method!=="PLANAR"?[t.a??360]:[],...t.method==="SPHERICAL"?[t.b??180]:[]].map(Nt).join(" "),r=`0 ldr: ${e} with a model-level !TEXMAP\n0 BFC CERTIFY CCW\n0 !TEXMAP START ${t.method} ${n} ${We(t.texture)}${t.glossmap?" GLOSSMAP "+We(t.glossmap):""}\n1 16 0 0 0 1 0 0 0 1 0 0 0 1 ${q(e)}\n0 !TEXMAP END\n`;return{name:`${q(e)}#tex-${Bt(r)}`,source:r}}var $t=(e,t)=>{let n=[,,,,,,,,,];for(let r=0;r<3;r++)for(let o=0;o<3;o++)n[r*3+o]=e[r*3]*t[o]+e[r*3+1]*t[3+o]+e[r*3+2]*t[6+o];return n};function jt(e,t,n){let r=Math.PI/180,o=Math.sin(e*r),s=Math.cos(e*r),i=Math.sin(t*r),c=Math.cos(t*r),a=Math.sin(n*r),l=Math.cos(n*r);return[c*l,-c*a,i,s*a+o*i*l,s*l-o*i*a,-o*c,o*a-s*i*l,o*l+s*i*a,s*c]}var Ye=new WeakMap;function ot(e){let t=Ye.get(e);if(t)return t;let n=[],r=null;for(let o of e.cmds){if(o.t!==0||!o.step)continue;let s=o.rotstep;if(s)if(s.mode==="END")r=null;else{let i=jt(s.x,s.y,s.z);r=s.mode==="ABS"?{abs:!0,m:i,rotstep:s}:s.mode==="ADD"&&r?{abs:r.abs,m:$t(r.m,i),rotstep:s}:{abs:!1,m:i,rotstep:s}}n.push(r)}return n.push(r),Ye.set(e,n),n}var st=999999,it=(e)=>e.map((t)=>String(t).padStart(6,"0")).join(".")+"~";function Vt(e,t={}){let n=[],r=t.maxDepth??64,o=t.looseGeometry!==!1,s=!!t.textures,i=!!t.callouts,c=new Map,a=0,l=(p,m)=>{let b=p.name+"#"+m,A=c.get(b);if(!A){let u;A=Object.assign(()=>u??=tt(p,m),{file:p,step:m}),c.set(b,A)}return A},f=(p,m,b,A,u,h,E,y,g=null,C=[],B=[])=>{let d=p.files.get(m);if(!d||E>r)return;let M=0,P=E>0?++a:0,F=i&&P?[...C,P]:C,S=i&&P?[...B,b]:B,U=i&&!g?new Map:null,W=-1,H=0,v=(T,x,z,R,D,O)=>{if(W!==M)W=M,H=0;let j=U?.get(M+"|"+x);if(j)return j.n++,f(T,T===p?x:T.main,z,R,u+"/"+x,[...D,st],E+1,O,[...D,st],F,S);let k=[...D,H++],G=n.length;f(T,T===p?x:T.main,z,R,u+"/"+x,k,E+1,O,g,F,S),U?.set(M+"|"+x,{n:1,from:G,to:n.length})},w=ot(d),L=o?et(d):[],V=0,I=(T,x,z,R,D,O,j)=>{if(g)R=g;let k={part:T,color:x,m:z,step:R[0],steps:R,localStep:D,path:u};if(P){if(k.sub=P,i)k.subPath=F,k.subMats=S}if(O)k.embedded=!0;if(j){let X=rt(T,j);k.texPart=X.name,k.texSource=X.source}let G=w[D];if(G)k.view=G;return n.push(k),k},N=(T)=>{while(V<L.length&&L[V]<=T){let x=L[V++];I(Ie(d.name,x),A,b,[...h,x],x,!1,null).source=l(d,x)}};for(let T of d.cmds){if(T.t===0&&T.step){M++;continue}let x=T;if(x.t>=2||x.t===0&&x.geom&&x.geom.t>=2){N(M);continue}if(x.t===0)if(s&&x.geom?.t===1)x=x.geom;else continue;if(x.t!==1)continue;if(s&&x.fallback)continue;let z=x.color===16?A:x.color,R=Qe(b,x.m),D=[...h,M],O=s?x.tex??y:null,j=O?nt(x.m):null,k=O&&j?qe(O,j):null;if(p.files.has(x.file)){if(Le(p,x.file)==="model"){v(p,x.file,R,z,D,k);continue}I(x.file,z,R,D,M,!0,k);continue}let G=t.resolveModel?.(x.file);if(G){v(G,x.file,R,z,D,k);continue}I(x.file,z,R,D,M,!1,k)}if(N(1/0),U){for(let T of U.values())if(T.n>1)for(let x=T.from;x<T.to;x++)n[x].mult??=T.n}};if(Le(e,e.main)==="part"){if(e.files.get(e.main))n.push({part:e.main,color:16,m:[...Te],step:0,steps:[0],localStep:0,path:e.main,embedded:!0});return n}return f(e,e.main,Te,16,e.main,[],0,null),n}function at(e,t="main.ldr",n){return Vt(Ze(e,t,{geometryText:!0}),n)}var lt=(e,t=0)=>Math.abs(e[t+7]-1)<0.001&&Math.abs(e[t+4])<0.001&&Math.abs(e[t+10])<0.001,ct=new WeakMap;function ke(e,t){let n=ct.get(e);if(!n)ct.set(e,n=new Map);let r=n.get(t);if(r!==void 0)return r;let o=e.parts[t];if(!o)return n.set(t,null),null;let s=o.studs.length,i=new Float64Array(s*12),c=[],a=[];o.studs.forEach((m,b)=>{c.push(m[0]),a.push(m[1]);for(let A=0;A<12;A++)i[b*12+A]=m[2+A]});let l=null,f=0,p=0;if(o.mask){f=o.mask[0],p=o.mask[1];let m=o.mask[2];l=new Uint8Array(m.length);for(let b=0;b<m.length;b++)l[b]=m.charCodeAt(b)===49?1:0}return n.set(t,r={nStuds:s,studM:i,kind:c,color:a,mask:l,nx:f,nz:p}),r}var ie=1073741824;class Re{a;b;c;vals;used;mask;size=0;constructor(e=1024){let t=1024;while(t<e*2)t*=2;this.a=new Int32Array(t),this.b=new Int32Array(t),this.c=new Int32Array(t),this.vals=new Int32Array(t),this.used=new Uint8Array(t),this.mask=t-1}slot(e,t,n){let r=Math.imul(e,2654435761)^Math.imul(t,2246822507)^Math.imul(n,3266489909);return r^=r>>>15,r=Math.imul(r,739982445),r^=r>>>12,r&this.mask}get(e,t,n){let r=this.slot(e,t,n),o=this.used,s=this.a,i=this.b,c=this.c;for(;;){if(!o[r])return-1;if(s[r]===e&&i[r]===t&&c[r]===n)return this.vals[r];r=r+1&this.mask}}put(e,t,n,r){if((this.size+1)*2>this.used.length)this.grow();let o=this.slot(e,t,n),s=this.used,i=this.a,c=this.b,a=this.c;for(;;){if(!s[o])return s[o]=1,i[o]=e,c[o]=t,a[o]=n,this.vals[o]=r,this.size++,-1;if(i[o]===e&&c[o]===t&&a[o]===n){let l=this.vals[o];return this.vals[o]=r,l}o=o+1&this.mask}}grow(){let{a:e,b:t,c:n,vals:r,used:o}=this,s=o.length*2;this.a=new Int32Array(s),this.b=new Int32Array(s),this.c=new Int32Array(s),this.vals=new Int32Array(s),this.used=new Uint8Array(s),this.mask=s-1,this.size=0;for(let i=0;i<o.length;i++)if(o[i])this.put(e[i],t[i],n[i],r[i])}}var de=(e,t,n)=>e>-ie&&e<ie&&t>-ie&&t<ie&&n>-ie&&n<ie,fe=2147483647;function Ht(e,t,n){let o=[],s=[],i=[],c=[],a=[],l=[],f=[],p=[],m=new Re(e.length*2),b=[],A=[];for(let v=0;v<e.length;v++){let w=e[v],L=w.m,V=t.parts[w.part];if(!V||!V.mask||!lt(L))continue;let I=V.bbox,N=1/0,T=-1/0,x=1/0,z=-1/0;for(let O=0;O<2;O++)for(let j=0;j<2;j++){let k=O?I[3]:I[0],G=j?I[5]:I[2],X=L[0]+L[3]*k+L[5]*G,Y=L[2]+L[9]*k+L[11]*G;if(X<N)N=X;if(X>T)T=X;if(Y<x)x=Y;if(Y>z)z=Y}let R=a.length;o.push(N),s.push(T),i.push(x),c.push(z),a.push(v),l.push(ke(t,w.part)),f.push(I[0]),p.push(I[2]);let D=Math.round((L[1]+I[4])*2);for(let O=Math.floor(N/40);O<=Math.floor(T/40);O++)for(let j=Math.floor(x/40);j<=Math.floor(z/40);j++){if(!de(D,O,j))continue;let k=A.length;A.push(R),b.push(m.put(D,O,j,k))}}let u=[0,5,-5,5,-5],h=[0,5,5,-5,-5],E=NaN,y=NaN,g=NaN,C=-1,B=(v,w,L,V)=>{let I=Math.round(w*2),N=Math.floor(v/40),T=Math.floor(L/40);if(!de(I,N,T))return fe;let x=fe;if(I!==E||N!==y||T!==g)E=I,y=N,g=T,C=m.get(I,N,T);for(let z=C;z>=0;z=b[z]){let R=A[z];if(a[R]===V||!(v-6>=o[R]-0.5&&v+6<=s[R]+0.5&&L-6>=i[R]-0.5&&L+6<=c[R]+0.5))continue;let D=e[a[R]].m,O=l[R],j=f[R],k=p[R],G=v-D[0],X=w-D[1],Y=L-D[2],Z=D[3]*G+D[6]*X+D[9]*Y,J=D[5]*G+D[8]*X+D[11]*Y,{nx:ee,nz:oe,mask:ae}=O,se=!0;for(let Q=0;Q<5;Q++){let te=Math.floor((Z+u[Q]-j)/20),ne=Math.floor((J+h[Q]-k)/20);if(te<0||ne<0||te>=ee||ne>=oe||ae[te*oe+ne]!==1){se=!1;break}}if(se){if(!n)return 0;let Q=n[a[R]];if(Q<x)x=Q}}return x},d=0;for(let v of e){let w=ke(t,v.part);if(w)d+=w.nStuds}let M=new Uint8Array(d),P=new Uint8Array(d),F=new Re(d),S=0,U=n?new Int32Array(d).fill(fe):void 0;for(let v=0,w=0;v<e.length;v++){let L=e[v],V=ke(t,L.part);if(!V)continue;let I=L.m,N=V.studM,T=I[0],x=I[1],z=I[2],R=I[3],D=I[4],O=I[5],j=I[6],k=I[7],G=I[8],X=I[9],Y=I[10],Z=I[11];for(let J=0;J<V.nStuds;J++,w++){let ee=J*12,oe=N[ee+4],ae=N[ee+7],se=N[ee+10];if(!(Math.abs(j*oe+k*ae+G*se-1)<0.001&&Math.abs(R*oe+D*ae+O*se)<0.001&&Math.abs(X*oe+Y*ae+Z*se)<0.001))continue;P[w]=1;let Q=N[ee],te=N[ee+1],ne=N[ee+2],De=T+R*Q+D*te+O*ne,Fe=x+j*Q+k*te+G*ne,Ue=z+X*Q+Y*te+Z*ne,Oe=B(De,Fe,Ue,v);if(Oe!==fe){if(M[w]=1,S++,U)U[w]=Oe}let pe=Math.round(De),me=Math.round(Fe),he=Math.round(Ue);if(!de(pe,me,he))continue;if(!n){F.put(pe,me,he,1);continue}let ze=n[v],Be=F.get(pe,me,he);if(Be<0||ze<Be)F.put(pe,me,he,ze)}}let W=new Uint8Array(e.length),H=n?new Int32Array(e.length).fill(fe):void 0;for(let v=0;v<e.length;v++){let w=e[v],L=t.parts[w.part];if(!L||!L.under||!lt(w.m))continue;let V=L.bbox,I=Math.round((V[3]-V[0])/20),N=Math.round((V[5]-V[2])/20);if(!I||!N||I*N>4096)continue;let T=w.m,x=!0,z=0;for(let R=0;R<I&&x;R++)for(let D=0;D<N;D++){let O=V[0]+10+20*R,j=V[2]+10+20*D,k=T[0]+T[3]*O+T[5]*j,G=T[2]+T[9]*O+T[11]*j,X=Math.round(k),Y=Math.round(T[1]+V[4]),Z=Math.round(G),J=de(X,Y,Z)?F.get(X,Y,Z):-1;if(J<0){x=!1;break}if(J>z)z=J}if(x){if(W[v]=1,H)H[v]=z}}return{nStuds:d,studHidden:M,studUp:P,underHidden:W,studsHidden:S,studHideStep:U,underHideStep:H}}function Gt(e,t,n){let r=(a)=>n&&a.texPart&&t.parts[a.texPart]?a.texPart:a.part,o=e.map((a)=>({part:r(a),color:String(a.color),m:a.m,steps:a.steps})),s=o.map((a)=>it(a.steps)),i=[...new Set(s)].sort(),c=new Map(i.map((a,l)=>[a,l]));return{all:o,stepOf:s.map((a)=>c.get(a)),nSteps:i.length}}function xe(e,t,n=!0){let r=Gt(e,t,n);return Ht(r.all,t,r.nSteps>1?r.stepOf:void 0)}var Me="https://ldr-demo.vercel.app/cdn/v1/",ve=new Map,we=new Map;function ft(e=Me,t=fetch){let n=ve.get(e);if(!n)n=t(e+"parts.json").then((r)=>{if(!r.ok)throw Error(`ldr: parts CDN index ${r.status} (${e}parts.json)`);return r.json()}),n.catch(()=>ve.delete(e)),ve.set(e,n);return n}var Xt=(e)=>Array.isArray(e)&&e.length===3&&typeof e[0]==="number"&&typeof e[1]==="number"&&(e[2]==="f32"||e[2]==="u16"||e[2]==="u8"||e[2]==="u32"),Ae=(e,t)=>Xt(e)?[e[0]+t,e[1],e[2]]:Array.isArray(e)?e.map((n)=>Ae(n,t)):e&&typeof e==="object"?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,Ae(r,t)])):e;function _t(e,t={}){let n=[],r=0,o={},s={};for(let m of e){let b=m.buffer;if(!b)throw Error("ldr: mergePacks needs packs from decodePack/loadPack");let A=new DataView(b).getUint32(0,!0),u=new Uint8Array(b,4+A),h=r;n.push(u),r+=u.byteLength;let E=(4-r%4)%4;if(E)n.push(new Uint8Array(E)),r+=E;for(let[y,g]of Object.entries(m.header.parts??{}))if(!(y in o))o[y]=Ae(g,h);for(let[y,g]of Object.entries(m.header.studKinds??{}))if(!(y in s))s[y]=Ae(g,h)}let i=e[0]?.header??{version:1,weld:!0},c=new TextEncoder().encode(JSON.stringify({...i,parts:o,studKinds:s,...t})),a=(4-(4+c.length)%4)%4,l=4+c.length+a,f=new Uint8Array(l+r);new DataView(f.buffer).setUint32(0,c.length+a,!0),f.set(c,4),f.fill(32,4+c.length,l);let p=l;for(let m of n)f.set(m,p),p+=m.byteLength;return ye(f.buffer)}async function Kt(e,t={}){e=[...e];try{return await ut(e,t)}catch(n){let r=t.cdn??Me,o=t.fetch??fetch;ve.delete(r);let s=(i,c)=>o(i,{...c,cache:"reload"});try{return await ut(e,{...t,fetch:s})}catch{throw n}}}async function ut(e,t){let n=t.cdn??Me,r=t.fetch??fetch,o=t.gap??16384,s=await ft(n,r),i=[...new Set([...e].map(q))],c=[],a=[];for(let u of i){if(we.has(n+u))continue;let h=s.parts[u];if(h)a.push({name:u,off:h[0],len:h[1],file:h[2]??0});else c.push(u)}a.sort((u,h)=>u.file-h.file||u.off-h.off);let l=[];for(let u of a){let h=l[l.length-1];if(h&&h.file===u.file&&u.off-h.end<=o)h.end=Math.max(h.end,u.off+u.len),h.items.push(u);else l.push({file:u.file,start:u.off,end:u.off+u.len,items:[u]})}let f=0,p=0,m=async()=>{while(p<l.length){let u=l[p++],h=await r(new URL(s.archives[u.file],n).href,{headers:{Range:`bytes=${u.start}-${u.end-1}`}});if(!h.ok)throw Error(`ldr: parts CDN ${h.status}`);let E=new Uint8Array(await h.arrayBuffer());if(h.status===200)E=E.subarray(u.start,u.end);f+=E.byteLength;for(let y of u.items){let g=je(E.subarray(y.off-u.start,y.off-u.start+y.len)),C=g.buffer.slice(g.byteOffset,g.byteOffset+g.byteLength);we.set(n+y.name,ye(C))}}};await Promise.all(Array.from({length:Math.min(t.concurrency??24,l.length)},m));let b=i.filter((u)=>we.has(n+u)).map((u)=>we.get(n+u));return{pack:b.length?_t(b,{colors:s.colors}):ye(Wt(s.colors)),missing:c,requests:l.length,bytes:f}}function Wt(e){let t=new TextEncoder().encode(JSON.stringify({version:1,weld:!0,parts:{},studKinds:{},colors:e})),n=(4-(4+t.length)%4)%4,r=new Uint8Array(4+t.length+n).fill(32);return new DataView(r.buffer).setUint32(0,t.length+n,!0),r.set(t,4),r.buffer}async function pt(e,t={}){let n=performance.now(),r=t.fetch??fetch,o=ft(t.cdn??Me,r);o.catch(()=>{});let s=t.text?e:await r(e).then((h)=>{if(!h.ok)throw Error(`ldr: ${h.status} fetching ${e}`);return h.text()}),i=performance.now(),c=t.name??(t.text?"main.ldr":decodeURIComponent(e.split(/[?#]/)[0].split("/").pop()||"main.ldr")),a=at(s,c,{looseGeometry:!1,callouts:t.callouts}),l=performance.now();t.onParsed?.(a),await o;let{pack:f,missing:p,requests:m,bytes:b}=await Kt(a.filter((h)=>!h.embedded).map((h)=>h.part),t),A=performance.now(),u=t.cull?xe(a,f.header,t.textures!==!1):void 0;return{insts:a,pack:f,missing:p,requests:m,bytes:b,cull:u,timings:{fetchModel:i-n,parse:l-i,parts:A-l,...u?{cull:performance.now()-A}:{}}}}self.onmessage=async(e)=>{let{id:t,source:n,opts:r}=e.data;try{let o=await pt(n,{...r,cull:!1,onParsed:(f)=>self.postMessage({id:t,insts:f})}),s=o.pack.buffer;if(self.postMessage({id:t,buffer:s,missing:o.missing,requests:o.requests,bytes:o.bytes,timings:o.timings},[s]),!r.cull)return;let i=performance.now(),c=xe(o.insts,o.pack.header,r.textures!==!1),a=performance.now()-i,l=[];for(let f of[c.studHidden,c.studUp,c.underHidden,c.studHideStep,c.underHideStep])if(f)l.push(f.buffer);self.postMessage({id:t,cull:c,ms:a},l)}catch(o){self.postMessage({id:t,phase:"error",error:String(o?.message??o)})}};\n';
2916
+
2917
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/cdn.ts
2918
+ var worker;
2919
+ var seq = 0;
2920
+ var pending = new Map;
2921
+ var pendingInsts = new Map;
2922
+ var pendingCull = new Map;
2923
+ function getWorker() {
2924
+ if (worker !== undefined)
2925
+ return worker;
2926
+ try {
2927
+ if (typeof Worker === "undefined" || typeof Blob === "undefined" || typeof URL?.createObjectURL !== "function" || !load_worker_gen_default)
2928
+ return worker = null;
2929
+ const url = URL.createObjectURL(new Blob([load_worker_gen_default], { type: "text/javascript" }));
2930
+ const w = new Worker(url, { type: "module", name: "ldr-load" });
2931
+ w.onmessage = (e) => {
2932
+ const d = e.data;
2933
+ if (d.insts) {
2934
+ pendingInsts.get(d.id)?.(d.insts);
2935
+ pendingInsts.delete(d.id);
2936
+ return;
2937
+ }
2938
+ const map = d.cull || d.error && !pending.has(d.id) ? pendingCull : pending;
2939
+ const p = map.get(d.id);
2940
+ if (!p)
2941
+ return;
2942
+ map.delete(d.id);
2943
+ d.error ? p.rej(new Error(d.error)) : p.res(d);
2944
+ };
2945
+ w.onerror = (e) => {
2946
+ e.preventDefault?.();
2947
+ worker = null;
2948
+ w.terminate();
2949
+ const err = new Error("ldr: load worker failed: " + (e.message || "error"));
2950
+ err.workerFailed = true;
2951
+ for (const m of [pending, pendingCull]) {
2952
+ for (const p of m.values())
2953
+ p.rej(err);
2954
+ m.clear();
2955
+ }
2956
+ };
2957
+ return worker = w;
2958
+ } catch {
2959
+ return worker = null;
2960
+ }
2961
+ }
2962
+ var abs = (u) => {
2963
+ try {
2964
+ return new URL(u, globalThis.location?.href).href;
2965
+ } catch {
2966
+ return u;
2967
+ }
2968
+ };
2969
+ function prepareInWorker(w, source, o) {
2970
+ const id = ++seq;
2971
+ const opts = { cdn: abs(o.cdn ?? DEFAULT_PARTS_CDN), gap: o.gap, concurrency: o.concurrency, text: o.text, name: o.name, cull: true, textures: o.textures, callouts: o.callouts };
2972
+ const name = o.name ?? (o.text ? undefined : decodeURIComponent(source.split(/[?#]/)[0].split("/").pop() || "main.ldr"));
2973
+ let insts;
2974
+ pendingInsts.set(id, (v) => {
2975
+ insts = v;
2976
+ });
2977
+ const cull = new Promise((res, rej) => pendingCull.set(id, { res, rej }));
2978
+ cull.catch(() => {});
2979
+ return new Promise((res, rej) => {
2980
+ pending.set(id, { res, rej });
2981
+ w.postMessage({ id, source: o.text ? source : abs(source), opts: { ...opts, name } });
2982
+ }).then(async (d) => {
2983
+ const pack = decodePack(d.buffer);
2984
+ let done = false;
2985
+ cull.then(() => done = true, () => done = true);
2986
+ await warmPackGeometry(pack, () => done);
2987
+ const c = await cull;
2988
+ pendingInsts.delete(id);
2989
+ return { insts, pack, missing: d.missing, requests: d.requests, bytes: d.bytes, timings: { ...d.timings, cull: c.ms }, cull: c.cull };
2990
+ }, (e) => {
2991
+ pendingCull.delete(id);
2992
+ pendingInsts.delete(id);
2993
+ throw e;
2994
+ });
2995
+ }
2996
+ async function loadModel(source, o = {}) {
2997
+ const t0 = performance.now();
2998
+ const w = o.worker !== false && !o.fetch ? getWorker() : null;
2999
+ let prep, ranIn = "main";
3000
+ if (w) {
3001
+ try {
3002
+ prep = await prepareInWorker(w, source, o);
3003
+ ranIn = "worker";
3004
+ } catch (e) {
3005
+ if (!e?.workerFailed)
3006
+ throw e;
3007
+ prep = await prepareModel(source, o);
3008
+ }
3009
+ } else
3010
+ prep = await prepareModel(source, o);
3011
+ const t3 = performance.now();
3012
+ const obj = createLdrObject(prep.insts, prep.pack, prep.cull ? { ...o, precomputedCull: prep.cull } : o);
3013
+ for (const m of prep.missing)
2257
3014
  if (!obj.stats.missing.includes(m))
2258
3015
  obj.stats.missing.push(m);
2259
3016
  const t4 = performance.now();
2260
- return Object.assign(obj, { pack, instances: insts, requests, bytes, timings: { fetchModel: t1 - t0, parse: t2 - t1, parts: t3 - t2, build: t4 - t3, total: t4 - t0 } });
3017
+ return Object.assign(obj, {
3018
+ pack: prep.pack,
3019
+ instances: prep.insts,
3020
+ requests: prep.requests,
3021
+ bytes: prep.bytes,
3022
+ ranIn,
3023
+ timings: { ...prep.timings, parts: t3 - t0 - prep.timings.fetchModel - prep.timings.parse, build: t4 - t3, total: t4 - t0 }
3024
+ });
2261
3025
  }
2262
3026
  export {
3027
+ CALLOUT_END,
2263
3028
  DEFAULT_PARTS_CDN,
2264
3029
  I as IDENTITY,
3030
+ MIN_VIS,
3031
+ REORIENT,
2265
3032
  buildLdrScene,
2266
3033
  colorToken,
2267
3034
  computeCulling,
@@ -2278,8 +3045,10 @@ export {
2278
3045
  flatten,
2279
3046
  forEachStud,
2280
3047
  hash32,
3048
+ instanceBoxes,
2281
3049
  invert,
2282
3050
  isDirectColor,
3051
+ isolateMask,
2283
3052
  loadModel,
2284
3053
  loadPack,
2285
3054
  loadParts,
@@ -2297,13 +3066,20 @@ export {
2297
3066
  parseLDConfig,
2298
3067
  parseModel,
2299
3068
  parseTexMap,
3069
+ planStepViews,
3070
+ precomputeCull,
3071
+ prepareModel,
2300
3072
  resolveTexture,
2301
3073
  rotStepMatrix,
3074
+ sceneInstances,
2302
3075
  sequenceSteps,
2303
3076
  smoothNormals,
3077
+ stepKey,
2304
3078
  stepViewMatrix,
2305
3079
  texWrapper,
2306
3080
  texmapTriangleUV,
2307
3081
  texmapUV,
2308
- transformTexMap
3082
+ transformTexMap,
3083
+ viewDir,
3084
+ warmPackGeometry
2309
3085
  };