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.
@@ -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) {
@@ -413,6 +455,7 @@ function transformTexMap(map, m) {
413
455
  const x = (q) => [m[3] * q[0] + m[4] * q[1] + m[5] * q[2] + m[0], m[6] * q[0] + m[7] * q[1] + m[8] * q[2] + m[1], m[9] * q[0] + m[10] * q[1] + m[11] * q[2] + m[2]];
414
456
  return { ...map, p1: x(map.p1), p2: x(map.p2), p3: x(map.p3) };
415
457
  }
458
+ var STUB_OVERRIDES = { "32531.dat": "32531a.dat" };
416
459
  function mul(a, b) {
417
460
  const [ax, ay, az, a0, a1, a2, a3, a4, a5, a6, a7, a8] = a, [bx, by, bz, b0, b1, b2, b3, b4, b5, b6, b7, b8] = b;
418
461
  return [
@@ -647,12 +690,15 @@ function fileStepViews(f) {
647
690
  viewMemo.set(f, out);
648
691
  return out;
649
692
  }
650
- // ../../../../../../../tmp/ldr-build-pIke9r/src/model.ts
693
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/model.ts
694
+ var CALLOUT_END = 999999;
695
+ var stepKey = (steps) => steps.map((x) => String(x).padStart(6, "0")).join(".") + "~";
651
696
  function flatten(doc, opts = {}) {
652
697
  const out = [];
653
698
  const maxDepth = opts.maxDepth ?? 64;
654
- const loose = opts.looseGeometry !== false, tx = !!opts.textures;
699
+ const loose = opts.looseGeometry !== false, tx = !!opts.textures, co = !!opts.callouts;
655
700
  const src = new Map;
701
+ let subs = 0;
656
702
  const lazy = (f, k) => {
657
703
  const key = f.name + "#" + k;
658
704
  let fn = src.get(key);
@@ -663,16 +709,44 @@ function flatten(doc, opts = {}) {
663
709
  }
664
710
  return fn;
665
711
  };
666
- const walk = (d, fname, m, color, path, stepPath, depth, texIn) => {
712
+ const walk = (d, fname, m, color, path, stepPath, depth, texIn, fixed = null, subPath = [], subMats = []) => {
667
713
  const f = d.files.get(fname);
668
714
  if (!f || depth > maxDepth)
669
715
  return;
670
716
  let s = 0;
717
+ const subId = depth > 0 ? ++subs : 0;
718
+ const sp0 = co && subId ? [...subPath, subId] : subPath;
719
+ const sm0 = co && subId ? [...subMats, m] : subMats;
720
+ const groups = co && !fixed ? new Map : null;
721
+ let ordStep = -1, ord = 0;
722
+ const sub = (sd, file, mm, col, sp, lt) => {
723
+ if (ordStep !== s) {
724
+ ordStep = s;
725
+ ord = 0;
726
+ }
727
+ const g = groups?.get(s + "|" + file);
728
+ if (g) {
729
+ g.n++;
730
+ return walk(sd, sd === d ? file : sd.main, mm, col, path + "/" + file, [...sp, CALLOUT_END], depth + 1, lt, [...sp, CALLOUT_END], sp0, sm0);
731
+ }
732
+ const spo = [...sp, ord++], from = out.length;
733
+ walk(sd, sd === d ? file : sd.main, mm, col, path + "/" + file, spo, depth + 1, lt, fixed, sp0, sm0);
734
+ groups?.set(s + "|" + file, { n: 1, from, to: out.length });
735
+ };
671
736
  const views = fileStepViews(f);
672
737
  const ls = loose ? looseSteps(f) : [];
673
738
  let li = 0;
674
739
  const emit = (part, col, mm, sp, k, embedded, tex) => {
740
+ if (fixed)
741
+ sp = fixed;
675
742
  const i = { part, color: col, m: mm, step: sp[0], steps: sp, localStep: k, path };
743
+ if (subId) {
744
+ i.sub = subId;
745
+ if (co) {
746
+ i.subPath = sp0;
747
+ i.subMats = sm0;
748
+ }
749
+ }
676
750
  if (embedded)
677
751
  i.embedded = true;
678
752
  if (tex) {
@@ -718,7 +792,7 @@ function flatten(doc, opts = {}) {
718
792
  const lt = tex && local ? transformTexMap(tex, local) : null;
719
793
  if (d.files.has(c.file)) {
720
794
  if (fileKind(d, c.file) === "model") {
721
- walk(d, c.file, mm, col, path + "/" + c.file, sp, depth + 1, lt);
795
+ sub(d, c.file, mm, col, sp, lt);
722
796
  continue;
723
797
  }
724
798
  emit(c.file, col, mm, sp, s, true, lt);
@@ -726,12 +800,18 @@ function flatten(doc, opts = {}) {
726
800
  }
727
801
  const ext = opts.resolveModel?.(c.file);
728
802
  if (ext) {
729
- walk(ext, ext.main, mm, col, path + "/" + c.file, sp, depth + 1, lt);
803
+ sub(ext, c.file, mm, col, sp, lt);
730
804
  continue;
731
805
  }
732
806
  emit(c.file, col, mm, sp, s, false, lt);
733
807
  }
734
808
  flushLoose(Infinity);
809
+ if (groups) {
810
+ for (const g of groups.values())
811
+ if (g.n > 1)
812
+ for (let j = g.from;j < g.to; j++)
813
+ out[j].mult ??= g.n;
814
+ }
735
815
  };
736
816
  if (fileKind(doc, doc.main) === "part") {
737
817
  const f = doc.files.get(doc.main);
@@ -743,10 +823,10 @@ function flatten(doc, opts = {}) {
743
823
  return out;
744
824
  }
745
825
  function parseModel(text, name = "main.ldr", opts) {
746
- return flatten(parse(text, name), opts);
826
+ return flatten(parse(text, name, { geometryText: true }), opts);
747
827
  }
748
828
  function sequenceSteps(insts) {
749
- const key = (i) => i.steps.map((x) => String(x).padStart(6, "0")).join(".");
829
+ const key = (i) => stepKey(i.steps);
750
830
  const uniq = [...new Set(insts.map(key))].sort();
751
831
  const rank = new Map(uniq.map((k, j) => [k, j]));
752
832
  const stepOf = new Int32Array(insts.length);
@@ -768,326 +848,397 @@ function parseLDConfig(text) {
768
848
  }
769
849
  return out;
770
850
  }
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;
851
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/instructions.ts
852
+ var MIN_VIS = 0.5;
853
+ var REORIENT = 0.35;
854
+ var deg = Math.PI / 180;
855
+ function viewDir(azimuthDeg, elevationDeg) {
856
+ const a = azimuthDeg * deg, e = elevationDeg * deg;
857
+ return [Math.sin(a) * Math.cos(e), -Math.sin(e), -Math.cos(a) * Math.cos(e)];
868
858
  }
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;
859
+ function isolateMask(insts, sub) {
860
+ const m = new Uint8Array(insts.length);
861
+ insts.forEach((i, k) => {
862
+ if (i.subPath?.includes(sub))
863
+ m[k] = 1;
864
+ });
887
865
  return m;
888
866
  }
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);
867
+ function commonSub(insts, ids, whole) {
868
+ const path = insts[ids[0]]?.subPath;
869
+ if (!path)
870
+ return;
871
+ let n = path.length;
872
+ for (const id of ids) {
873
+ const p = insts[id].subPath;
874
+ if (!p)
875
+ return;
876
+ let j = 0;
877
+ while (j < n && j < p.length && p[j] === path[j])
878
+ j++;
879
+ n = j;
880
+ if (!n)
881
+ return;
926
882
  }
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);
883
+ return whole(path[n - 1]) ? undefined : path[n - 1];
931
884
  }
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);
885
+ function instanceBoxes(insts, parts) {
886
+ return insts.map((i) => {
887
+ const b = parts[i.part]?.bbox;
888
+ if (!b)
889
+ return null;
890
+ const m = i.m;
891
+ const o = new Float64Array([Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity]);
892
+ for (let c = 0;c < 8; c++) {
893
+ const x = c & 1 ? b[3] : b[0], y = c & 2 ? b[4] : b[1], z = c & 4 ? b[5] : b[2];
894
+ 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];
895
+ for (let k = 0;k < 3; k++) {
896
+ if (w[k] < o[k])
897
+ o[k] = w[k];
898
+ if (w[k] > o[k + 3])
899
+ o[k + 3] = w[k];
900
+ }
901
+ }
940
902
  return o;
903
+ });
904
+ }
905
+
906
+ class BoxGrid {
907
+ cells = new Map;
908
+ boxes;
909
+ cell;
910
+ stamp;
911
+ q = 0;
912
+ lo;
913
+ hi;
914
+ constructor(boxes, cell) {
915
+ this.boxes = boxes;
916
+ this.cell = cell;
917
+ this.stamp = new Int32Array(boxes.length);
918
+ this.lo = [Infinity, Infinity, Infinity];
919
+ this.hi = [-Infinity, -Infinity, -Infinity];
920
+ for (const b of boxes)
921
+ if (b)
922
+ for (let k = 0;k < 3; k++) {
923
+ this.lo[k] = Math.min(this.lo[k], b[k]);
924
+ this.hi[k] = Math.max(this.hi[k], b[k + 3]);
925
+ }
941
926
  }
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;
927
+ key(i, j, k) {
928
+ return (i + 1024) * 4194304 + (j + 1024) * 2048 + (k + 1024);
956
929
  }
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];
930
+ add(id) {
931
+ const b = this.boxes[id];
932
+ if (!b)
933
+ return;
934
+ const c = this.cell;
935
+ for (let i = Math.floor(b[0] / c);i <= Math.floor(b[3] / c); i++)
936
+ for (let j = Math.floor(b[1] / c);j <= Math.floor(b[4] / c); j++)
937
+ for (let k = Math.floor(b[2] / c);k <= Math.floor(b[5] / c); k++) {
938
+ const key = this.key(i, j, k);
939
+ let l = this.cells.get(key);
940
+ if (!l)
941
+ this.cells.set(key, l = []);
942
+ l.push(id);
943
+ }
944
+ }
945
+ inside(p, self) {
946
+ const c = this.cell;
947
+ const l = this.cells.get(this.key(Math.floor(p[0] / c), Math.floor(p[1] / c), Math.floor(p[2] / c)));
948
+ if (!l)
949
+ return false;
950
+ for (const id of l) {
951
+ if (id === self)
952
+ continue;
953
+ const b = this.boxes[id];
954
+ 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])
955
+ return true;
956
+ }
957
+ return false;
958
+ }
959
+ hits(p, d, self, eps = 0.5) {
960
+ const c = this.cell, q = ++this.q;
961
+ let i = Math.floor(p[0] / c), j = Math.floor(p[1] / c), k = Math.floor(p[2] / c);
962
+ const step = d.map((v) => v > 0 ? 1 : v < 0 ? -1 : 0);
963
+ const idx = [i, j, k];
964
+ const tMax = [0, 1, 2].map((a) => d[a] === 0 ? Infinity : ((idx[a] + (d[a] > 0 ? 1 : 0)) * c - p[a]) / d[a]);
965
+ const tDelta = [0, 1, 2].map((a) => d[a] === 0 ? Infinity : c / Math.abs(d[a]));
966
+ 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);
967
+ for (let n = 0;n < 4096; n++) {
968
+ const l = this.cells.get(this.key(idx[0], idx[1], idx[2]));
969
+ if (l)
970
+ for (const id of l) {
971
+ if (id === self || this.stamp[id] === q)
972
+ continue;
973
+ this.stamp[id] = q;
974
+ if (rayBox(p, d, this.boxes[id], eps))
975
+ return true;
976
+ }
977
+ const a = tMax[0] < tMax[1] ? tMax[0] < tMax[2] ? 0 : 2 : tMax[1] < tMax[2] ? 1 : 2;
978
+ idx[a] += step[a];
979
+ tMax[a] += tDelta[a];
980
+ if (step[a] === 0 || idx[a] === bound[a])
981
+ return false;
982
+ }
983
+ return false;
969
984
  }
970
- return out;
971
985
  }
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;
986
+ function rayBox(p, d, b, eps) {
987
+ let t0 = 0.000001, t1 = Infinity;
988
+ for (let a = 0;a < 3; a++) {
989
+ const lo = b[a] + eps, hi = b[a + 3] - eps;
990
+ if (d[a] === 0) {
991
+ if (p[a] <= lo || p[a] >= hi)
992
+ return false;
993
+ continue;
994
+ }
995
+ let ta = (lo - p[a]) / d[a], tb = (hi - p[a]) / d[a];
996
+ if (ta > tb)
997
+ [ta, tb] = [tb, ta];
998
+ if (ta > t0)
999
+ t0 = ta;
1000
+ if (tb < t1)
1001
+ t1 = tb;
1002
+ if (t0 > t1)
1003
+ return false;
1004
+ }
1005
+ return true;
996
1006
  }
997
- function createInstancedConditionalEdges(cond, im, material = condLineMat()) {
998
- return condEdges(condBuffers(cond), im, material);
1007
+ function boxVisibility(grid, id, d, n = 3) {
1008
+ const b = grid.boxes[id];
1009
+ let vis = 0, tot = 0;
1010
+ for (let a = 0;a < 3; a++)
1011
+ for (const side of [-1, 1]) {
1012
+ const cos = side * d[a];
1013
+ if (cos <= 0.02)
1014
+ continue;
1015
+ const u = (a + 1) % 3, v = (a + 2) % 3;
1016
+ const area = (b[u + 3] - b[u]) * (b[v + 3] - b[v]);
1017
+ if (area <= 0)
1018
+ continue;
1019
+ const w = area * cos / (n * n);
1020
+ const p = [0, 0, 0], q = [0, 0, 0];
1021
+ p[a] = side > 0 ? b[a + 3] + 0.25 : b[a] - 0.25;
1022
+ q[a] = side > 0 ? b[a + 3] + 1 : b[a] - 1;
1023
+ for (let s = 0;s < n; s++)
1024
+ for (let t = 0;t < n; t++) {
1025
+ p[u] = q[u] = b[u] + (s + 0.5) / n * (b[u + 3] - b[u]);
1026
+ p[v] = q[v] = b[v] + (t + 0.5) / n * (b[v + 3] - b[v]);
1027
+ if (grid.inside(q, id))
1028
+ continue;
1029
+ tot += w;
1030
+ if (!grid.hits(p, d, id))
1031
+ vis += w;
1032
+ }
1033
+ }
1034
+ return tot ? vis / tot : -1;
999
1035
  }
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;
1036
+ 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;
1037
+ var spread = (l, max) => l.length <= max ? l : Array.from({ length: max }, (_, i) => l[Math.floor((i + 0.5) * l.length / max)]);
1038
+ function planStepViews(insts, parts, stepOf, nSteps, o = {}) {
1039
+ const boxes = instanceBoxes(insts, parts);
1040
+ const byStep = Array.from({ length: nSteps }, () => []);
1041
+ for (let k = 0;k < insts.length; k++)
1042
+ if (boxes[k])
1043
+ byStep[stepOf[k]]?.push(k);
1044
+ let nBoxed = 0;
1045
+ for (const b of boxes)
1046
+ if (b)
1047
+ nBoxed++;
1048
+ const isoCache = new Map;
1049
+ const isoParts = (u) => {
1050
+ let l = isoCache.get(u);
1051
+ if (!l) {
1052
+ l = [];
1053
+ for (let k = 0;k < insts.length; k++)
1054
+ if (boxes[k] && insts[k].subPath?.includes(u))
1055
+ l.push(k);
1056
+ isoCache.set(u, l);
1008
1057
  }
1009
- side[l * 2 + 1] = 1;
1058
+ return l;
1059
+ };
1060
+ const subParts = new Map;
1061
+ for (let k = 0;k < insts.length; k++) {
1062
+ const u = insts[k].sub;
1063
+ if (u !== undefined && boxes[k])
1064
+ (subParts.get(u) ?? subParts.set(u, []).get(u)).push(k);
1010
1065
  }
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;
1066
+ let size = 0;
1067
+ for (const b of boxes)
1068
+ if (b)
1069
+ size = Math.max(size, b[3] - b[0], b[4] - b[1], b[5] - b[2]);
1070
+ let ext = 0;
1071
+ for (const b of boxes)
1072
+ if (b)
1073
+ 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]));
1074
+ const grid = new BoxGrid(boxes, Math.max(20, Math.min(160, size || 40), ext / 1000));
1075
+ const def = viewDir(o.azimuth ?? 45, o.elevation ?? 30), minVis = o.minVis ?? MIN_VIS, reorient = o.reorient ?? REORIENT, turn = o.turnCost ?? 0.002;
1076
+ const above = [], below = [];
1077
+ for (let az = 0;az < 360; az += 45) {
1078
+ for (const el of [15, 30, 50])
1079
+ above.push(viewDir(az, el));
1080
+ below.push(viewDir(az, -30));
1081
+ }
1082
+ const built = [Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity];
1083
+ const views = [];
1084
+ let prevMain = def;
1085
+ const prevIso = new Map;
1086
+ const local = new Map;
1087
+ const localOf = (u) => {
1088
+ let l = local.get(u);
1089
+ if (l)
1090
+ return l;
1091
+ const k0 = isoParts(u)[0];
1092
+ const i0 = insts[k0];
1093
+ const P = i0.subMats?.[i0.subPath.indexOf(u)] ?? null;
1094
+ const inv = P ? invert(P) : null;
1095
+ const lb = new Array(insts.length).fill(null);
1096
+ const own = isoParts(u);
1097
+ const loc = instanceBoxes(own.map((k) => ({ part: insts[k].part, m: inv ? mul(inv, insts[k].m) : insts[k].m })), parts);
1098
+ own.forEach((k, j) => lb[k] = loc[j]);
1099
+ local.set(u, l = { boxes: lb, P: P && inv ? [...P] : [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1] });
1100
+ return l;
1101
+ };
1102
+ let g = grid;
1103
+ const score = (ids, d) => {
1104
+ let mn = 1, sum = 0, n = 0;
1105
+ for (const id of ids) {
1106
+ const v = boxVisibility(g, id, d);
1107
+ if (v < 0)
1108
+ continue;
1109
+ mn = Math.min(mn, v);
1110
+ sum += v;
1111
+ n++;
1112
+ }
1113
+ return { mn: n ? mn : 1, mean: n ? sum / n : 1 };
1114
+ };
1115
+ const pref = (d) => {
1116
+ const h = Math.hypot(d[0], d[2]) || 1, el = Math.asin(Math.max(-1, Math.min(1, -d[1]))) / deg;
1117
+ return Math.abs(d[0] / h * (d[2] / h)) + 0.5 * Math.max(0, -d[2] / h) - Math.abs(el - 30) / 90;
1118
+ };
1119
+ const next = () => {
1120
+ const s = views.length, add = byStep[s];
1121
+ for (const id of add) {
1122
+ grid.add(id);
1123
+ const b = boxes[id];
1124
+ for (let k = 0;k < 3; k++) {
1125
+ built[k] = Math.min(built[k], b[k]);
1126
+ built[k + 3] = Math.max(built[k + 3], b[k + 3]);
1127
+ }
1128
+ }
1129
+ const iso = add.length ? commonSub(insts, add, (u) => isoParts(u).length >= nBoxed) : undefined;
1130
+ let isoBox = null;
1131
+ g = grid;
1132
+ if (iso !== undefined) {
1133
+ const L = localOf(iso);
1134
+ const own = isoParts(iso).filter((id) => stepOf[id] <= s);
1135
+ g = new BoxGrid(L.boxes, grid.cell);
1136
+ for (const id of own)
1137
+ g.add(id);
1138
+ isoBox = [Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity];
1139
+ for (const id of own) {
1140
+ const b = L.boxes[id];
1141
+ for (let k = 0;k < 3; k++) {
1142
+ isoBox[k] = Math.min(isoBox[k], b[k]);
1143
+ isoBox[k + 3] = Math.max(isoBox[k + 3], b[k + 3]);
1144
+ }
1145
+ }
1146
+ }
1147
+ const prev = iso !== undefined ? prevIso.get(iso) ?? def : prevMain, ref = isoBox ?? built;
1148
+ const ids = spread(add, 24);
1149
+ let dir = o.fixed?.(s) ?? null, r = dir ? score(ids, dir) : score(ids, prev);
1150
+ if (!dir) {
1151
+ dir = prev;
1152
+ if (r.mean >= minVis && prev !== def) {
1153
+ const v = score(ids, def);
1154
+ if (v.mean >= minVis) {
1155
+ dir = def;
1156
+ r = v;
1157
+ }
1158
+ }
1159
+ if (r.mean < minVis) {
1160
+ let best = -Infinity;
1161
+ 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];
1162
+ let amax = 0;
1163
+ for (const d of above)
1164
+ amax = Math.max(amax, area(d));
1165
+ const consider = (cands) => {
1166
+ for (const d of cands) {
1167
+ const v = score(ids, d);
1168
+ const sc = v.mean + 0.3 * v.mn + 0.25 * pref(d) + 0.15 * (amax ? area(d) / amax : 1) - turn * angle(prev, d);
1169
+ if (sc > best) {
1170
+ best = sc;
1171
+ dir = d;
1172
+ r = v;
1173
+ }
1174
+ }
1175
+ };
1176
+ consider([prev, ...above]);
1177
+ if (r.mean < reorient)
1178
+ consider(below);
1179
+ }
1180
+ }
1181
+ const diag = (b) => Math.hypot(b[3] - b[0], b[4] - b[1], b[5] - b[2]);
1182
+ let fb = built;
1183
+ const sub = add.length ? insts[add[0]].sub : undefined;
1184
+ if (isoBox)
1185
+ fb = isoBox;
1186
+ else if (sub !== undefined && add.every((id) => insts[id].sub === sub)) {
1187
+ const sb = [Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity];
1188
+ for (const id of subParts.get(sub) ?? []) {
1189
+ if (stepOf[id] > s)
1190
+ continue;
1191
+ const b = boxes[id];
1192
+ for (let k = 0;k < 3; k++) {
1193
+ sb[k] = Math.min(sb[k], b[k]);
1194
+ sb[k + 3] = Math.max(sb[k + 3], b[k + 3]);
1195
+ }
1196
+ }
1197
+ if (isFinite(sb[0]) && diag(sb) * 2.5 < diag(built)) {
1198
+ const g = diag(sb) * 0.35;
1199
+ fb = sb.map((v, k) => k < 3 ? v - g : v + g);
1200
+ }
1201
+ }
1202
+ const target = isFinite(fb[0]) ? [(fb[0] + fb[3]) / 2, (fb[1] + fb[4]) / 2, (fb[2] + fb[5]) / 2] : [0, 0, 0];
1203
+ 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 } : {} });
1204
+ if (iso !== undefined)
1205
+ prevIso.set(iso, dir);
1206
+ else
1207
+ prevMain = dir;
1208
+ };
1209
+ return {
1210
+ stepCount: nSteps,
1211
+ view(step) {
1212
+ step = Math.max(0, Math.min(nSteps - 1, step));
1213
+ while (views.length <= step)
1214
+ next();
1215
+ return views[step];
1216
+ }
1032
1217
  };
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
1218
  }
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;
1219
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/render.ts
1220
+ import * as THREE from "three";
1221
+
1222
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/pack-io.ts
1223
+ import { decompress } from "fzstd";
1224
+ async function decompressPack(data) {
1225
+ const u = data instanceof Uint8Array ? data : new Uint8Array(data);
1226
+ const own = (o) => o.buffer.slice(o.byteOffset, o.byteOffset + o.byteLength);
1227
+ if (u[0] === 40 && u[1] === 181 && u[2] === 47 && u[3] === 253)
1228
+ return own(decompress(u));
1229
+ if (u[0] === 31 && u[1] === 139)
1230
+ return new Response(new Blob([u]).stream().pipeThrough(new DecompressionStream("gzip"))).arrayBuffer();
1231
+ return own(u);
1080
1232
  }
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);
1233
+ function decodePack(buf) {
1234
+ const hl = new DataView(buf).getUint32(0, true);
1235
+ const header = JSON.parse(new TextDecoder().decode(new Uint8Array(buf, 4, hl)));
1236
+ const base = 4 + hl;
1237
+ 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]));
1238
+ return { header, arr, bytes: buf.byteLength, buffer: buf };
1090
1239
  }
1240
+
1241
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/cull.ts
1091
1242
  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
1243
  var prepCache = new WeakMap;
1093
1244
  function prepPart(H, part) {
@@ -1133,76 +1284,84 @@ function mul12To(a, b, bo, w, ao = 0) {
1133
1284
  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
1285
  }
1135
1286
  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
- };
1287
+ var BIG = 1073741824;
1141
1288
 
1142
- class NumTable {
1143
- keys;
1289
+ class Int3Table {
1290
+ a;
1291
+ b;
1292
+ c;
1144
1293
  vals;
1294
+ used;
1145
1295
  mask;
1146
1296
  size = 0;
1147
1297
  constructor(cap = 1024) {
1148
1298
  let n = 1024;
1149
1299
  while (n < cap * 2)
1150
1300
  n *= 2;
1151
- this.keys = new Float64Array(n).fill(-1);
1301
+ this.a = new Int32Array(n);
1302
+ this.b = new Int32Array(n);
1303
+ this.c = new Int32Array(n);
1152
1304
  this.vals = new Int32Array(n);
1305
+ this.used = new Uint8Array(n);
1153
1306
  this.mask = n - 1;
1154
1307
  }
1155
- slot(k) {
1156
- const lo = k >>> 0, hi = k / 4294967296 >>> 0;
1157
- let h = Math.imul(lo ^ Math.imul(hi, 2654435761), 2246822507);
1308
+ slot(x, y, z) {
1309
+ let h = Math.imul(x, 2654435761) ^ Math.imul(y, 2246822507) ^ Math.imul(z, 3266489909);
1158
1310
  h ^= h >>> 15;
1311
+ h = Math.imul(h, 739982445);
1312
+ h ^= h >>> 12;
1159
1313
  return h & this.mask;
1160
1314
  }
1161
- get(k) {
1162
- const K = this.keys;
1163
- let i = this.slot(k);
1315
+ get(x, y, z) {
1316
+ let i = this.slot(x, y, z);
1317
+ const U = this.used, A = this.a, B = this.b, C = this.c;
1164
1318
  for (;; ) {
1165
- const x = K[i];
1166
- if (x === k)
1167
- return this.vals[i];
1168
- if (x === -1)
1319
+ if (!U[i])
1169
1320
  return -1;
1321
+ if (A[i] === x && B[i] === y && C[i] === z)
1322
+ return this.vals[i];
1170
1323
  i = i + 1 & this.mask;
1171
1324
  }
1172
1325
  }
1173
- put(k, v) {
1174
- if ((this.size + 1) * 2 > this.keys.length)
1326
+ put(x, y, z, v) {
1327
+ if ((this.size + 1) * 2 > this.used.length)
1175
1328
  this.grow();
1176
- const K = this.keys;
1177
- let i = this.slot(k);
1329
+ let i = this.slot(x, y, z);
1330
+ const U = this.used, A = this.a, B = this.b, C = this.c;
1178
1331
  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;
1332
+ if (!U[i]) {
1333
+ U[i] = 1;
1334
+ A[i] = x;
1335
+ B[i] = y;
1336
+ C[i] = z;
1187
1337
  this.vals[i] = v;
1188
1338
  this.size++;
1189
1339
  return -1;
1190
1340
  }
1341
+ if (A[i] === x && B[i] === y && C[i] === z) {
1342
+ const o = this.vals[i];
1343
+ this.vals[i] = v;
1344
+ return o;
1345
+ }
1191
1346
  i = i + 1 & this.mask;
1192
1347
  }
1193
1348
  }
1194
1349
  grow() {
1195
- const ok = this.keys, ov = this.vals;
1196
- const n = ok.length * 2;
1197
- this.keys = new Float64Array(n).fill(-1);
1350
+ const { a, b, c, vals, used } = this;
1351
+ const n = used.length * 2;
1352
+ this.a = new Int32Array(n);
1353
+ this.b = new Int32Array(n);
1354
+ this.c = new Int32Array(n);
1198
1355
  this.vals = new Int32Array(n);
1356
+ this.used = new Uint8Array(n);
1199
1357
  this.mask = n - 1;
1200
1358
  this.size = 0;
1201
- for (let i = 0;i < ok.length; i++)
1202
- if (ok[i] !== -1)
1203
- this.put(ok[i], ov[i]);
1359
+ for (let i = 0;i < used.length; i++)
1360
+ if (used[i])
1361
+ this.put(a[i], b[i], c[i], vals[i]);
1204
1362
  }
1205
1363
  }
1364
+ var inRange = (x, y, z) => x > -BIG && x < BIG && y > -BIG && y < BIG && z > -BIG && z < BIG;
1206
1365
  var STEP_NEVER = 2147483647;
1207
1366
  function forEachStud(insts, H, fn) {
1208
1367
  const w = new Float64Array(12);
@@ -1222,7 +1381,7 @@ function forEachStud(insts, H, fn) {
1222
1381
  function cullCore(insts, H, steps) {
1223
1382
  const CELL = 40;
1224
1383
  const rx0 = [], rx1 = [], rz0 = [], rz1 = [], rInst = [], rPrep = [], rBx = [], rBz = [];
1225
- const cells = new NumTable(insts.length * 2);
1384
+ const cells = new Int3Table(insts.length * 2);
1226
1385
  const nextE = [], rectE = [];
1227
1386
  for (let idx = 0;idx < insts.length; idx++) {
1228
1387
  const it = insts[idx];
@@ -1257,21 +1416,27 @@ function cullCore(insts, H, steps) {
1257
1416
  const lv2 = Math.round((m[1] + b[4]) * 2);
1258
1417
  for (let cx = Math.floor(x0 / CELL);cx <= Math.floor(x1 / CELL); cx++)
1259
1418
  for (let cz = Math.floor(z0 / CELL);cz <= Math.floor(z1 / CELL); cz++) {
1260
- const k = cellKey(lv2, cx, cz);
1261
- if (k < 0)
1419
+ if (!inRange(lv2, cx, cz))
1262
1420
  continue;
1263
1421
  const e = rectE.length;
1264
1422
  rectE.push(ri);
1265
- nextE.push(cells.put(k, e));
1423
+ nextE.push(cells.put(lv2, cx, cz, e));
1266
1424
  }
1267
1425
  }
1268
1426
  const SX = [0, 5, -5, 5, -5], SZ = [0, 5, 5, -5, -5];
1427
+ let kl = NaN, kx = NaN, kz = NaN, ke = -1;
1269
1428
  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)
1429
+ const l2 = Math.round(y * 2), gx = Math.floor(x / CELL), gz = Math.floor(z / CELL);
1430
+ if (!inRange(l2, gx, gz))
1272
1431
  return STEP_NEVER;
1273
1432
  let best = STEP_NEVER;
1274
- for (let e = cells.get(k);e >= 0; e = nextE[e]) {
1433
+ if (l2 !== kl || gx !== kx || gz !== kz) {
1434
+ kl = l2;
1435
+ kx = gx;
1436
+ kz = gz;
1437
+ ke = cells.get(l2, gx, gz);
1438
+ }
1439
+ for (let e = ke;e >= 0; e = nextE[e]) {
1275
1440
  const ri = rectE[e];
1276
1441
  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
1442
  continue;
@@ -1299,71 +1464,448 @@ function cullCore(insts, H, steps) {
1299
1464
  }
1300
1465
  return best;
1301
1466
  };
1302
- let nStuds = 0;
1303
- for (const it of insts) {
1304
- const pp = prepPart(H, it.part);
1305
- if (pp)
1306
- nStuds += pp.nStuds;
1467
+ let nStuds = 0;
1468
+ for (const it of insts) {
1469
+ const pp = prepPart(H, it.part);
1470
+ if (pp)
1471
+ nStuds += pp.nStuds;
1472
+ }
1473
+ const studHidden = new Uint8Array(nStuds), studUp = new Uint8Array(nStuds);
1474
+ const tops = new Int3Table(nStuds);
1475
+ let studsHidden = 0;
1476
+ const studHideStep = steps ? new Int32Array(nStuds).fill(STEP_NEVER) : undefined;
1477
+ for (let idx = 0, j = 0;idx < insts.length; idx++) {
1478
+ const it = insts[idx];
1479
+ const pp = prepPart(H, it.part);
1480
+ if (!pp)
1481
+ continue;
1482
+ const m = it.m, S = pp.studM;
1483
+ 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];
1484
+ for (let s = 0;s < pp.nStuds; s++, j++) {
1485
+ const o = s * 12;
1486
+ const b4 = S[o + 4], b7 = S[o + 7], b10 = S[o + 10];
1487
+ 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))
1488
+ continue;
1489
+ studUp[j] = 1;
1490
+ const b0 = S[o], b1 = S[o + 1], b2 = S[o + 2];
1491
+ 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;
1492
+ const cs = coverStep(x, y, z, idx);
1493
+ if (cs !== STEP_NEVER) {
1494
+ studHidden[j] = 1;
1495
+ studsHidden++;
1496
+ if (studHideStep)
1497
+ studHideStep[j] = cs;
1498
+ }
1499
+ const rx = Math.round(x), ry = Math.round(y), rz = Math.round(z);
1500
+ if (!inRange(rx, ry, rz))
1501
+ continue;
1502
+ if (!steps) {
1503
+ tops.put(rx, ry, rz, 1);
1504
+ continue;
1505
+ }
1506
+ const st = steps[idx], t = tops.get(rx, ry, rz);
1507
+ if (t < 0 || st < t)
1508
+ tops.put(rx, ry, rz, st);
1509
+ }
1510
+ }
1511
+ const underHidden = new Uint8Array(insts.length);
1512
+ const underHideStep = steps ? new Int32Array(insts.length).fill(STEP_NEVER) : undefined;
1513
+ for (let idx = 0;idx < insts.length; idx++) {
1514
+ const it = insts[idx];
1515
+ const p = H.parts[it.part];
1516
+ if (!p || !p.under || !upright(it.m))
1517
+ continue;
1518
+ const b = p.bbox;
1519
+ const nx = Math.round((b[3] - b[0]) / 20), nz = Math.round((b[5] - b[2]) / 20);
1520
+ if (!nx || !nz || nx * nz > 4096)
1521
+ continue;
1522
+ const m = it.m;
1523
+ let all = true, at = 0;
1524
+ for (let a = 0;a < nx && all; a++)
1525
+ for (let c = 0;c < nz; c++) {
1526
+ const lx = b[0] + 10 + 20 * a, lz = b[2] + 10 + 20 * c;
1527
+ const x = m[0] + m[3] * lx + m[5] * lz, z = m[2] + m[9] * lx + m[11] * lz;
1528
+ const rx = Math.round(x), ry = Math.round(m[1] + b[4]), rz = Math.round(z);
1529
+ const t = inRange(rx, ry, rz) ? tops.get(rx, ry, rz) : -1;
1530
+ if (t < 0) {
1531
+ all = false;
1532
+ break;
1533
+ }
1534
+ if (t > at)
1535
+ at = t;
1536
+ }
1537
+ if (all) {
1538
+ underHidden[idx] = 1;
1539
+ if (underHideStep)
1540
+ underHideStep[idx] = at;
1541
+ }
1542
+ }
1543
+ return { nStuds, studHidden, studUp, underHidden, studsHidden, studHideStep, underHideStep };
1544
+ }
1545
+ function sceneInstances(instances, H, useTex) {
1546
+ const pick = (i) => useTex && i.texPart && H.parts[i.texPart] ? i.texPart : i.part;
1547
+ const all = instances.map((i) => ({ part: pick(i), color: String(i.color), m: i.m, steps: i.steps }));
1548
+ const keys = all.map((i) => stepKey(i.steps));
1549
+ const uniq = [...new Set(keys)].sort();
1550
+ const rank = new Map(uniq.map((k, j) => [k, j]));
1551
+ return { all, stepOf: keys.map((k) => rank.get(k)), nSteps: uniq.length };
1552
+ }
1553
+ function precomputeCull(instances, H, useTex = true) {
1554
+ const s = sceneInstances(instances, H, useTex);
1555
+ return cullCore(s.all, H, s.nSteps > 1 ? s.stepOf : undefined);
1556
+ }
1557
+
1558
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/render.ts
1559
+ async function loadPack(url) {
1560
+ const res = await fetch(url);
1561
+ if (!res.ok)
1562
+ throw new Error(`ldr: ${res.status} fetching ${url}`);
1563
+ return decodePack(await decompressPack(await res.arrayBuffer()));
1564
+ }
1565
+ var toI8 = (a) => {
1566
+ const o = new Int8Array(a.length);
1567
+ for (let i = 0;i < a.length; i++)
1568
+ o[i] = Math.round(Math.max(-1, Math.min(1, a[i])) * 127);
1569
+ return o;
1570
+ };
1571
+ var toU8 = (a) => {
1572
+ const o = new Uint8Array(a.length);
1573
+ for (let i = 0;i < a.length; i++)
1574
+ o[i] = Math.round(Math.max(0, Math.min(1, a[i])) * 255);
1575
+ return o;
1576
+ };
1577
+ function flatNormals(pos, idx) {
1578
+ const n = new Float32Array(pos.length);
1579
+ for (let t = 0;t < idx.length; t += 3) {
1580
+ const a = idx[t] * 3, b = idx[t + 1] * 3, c = idx[t + 2] * 3;
1581
+ 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];
1582
+ let nx = uy * vz - uz * vy, ny = uz * vx - ux * vz, nz = ux * vy - uy * vx;
1583
+ const l = Math.hypot(nx, ny, nz) || 1;
1584
+ nx /= l;
1585
+ ny /= l;
1586
+ nz /= l;
1587
+ for (const o of [a, b, c]) {
1588
+ n[o] = nx;
1589
+ n[o + 1] = ny;
1590
+ n[o + 2] = nz;
1591
+ }
1592
+ }
1593
+ return n;
1594
+ }
1595
+ var geomCache = new WeakMap;
1596
+ function geom(b, arr) {
1597
+ if (!b)
1598
+ return null;
1599
+ let c = geomCache.get(arr);
1600
+ if (!c)
1601
+ geomCache.set(arr, c = new Map);
1602
+ let g = c.get(b);
1603
+ if (g)
1604
+ return g;
1605
+ g = new THREE.BufferGeometry;
1606
+ g.setAttribute("position", new THREE.BufferAttribute(arr(b.pos), 3));
1607
+ const nrm = b.nrm ? arr(b.nrm) : flatNormals(arr(b.pos), arr(b.idx));
1608
+ const col = arr(b.col);
1609
+ g.setAttribute("normal", new THREE.BufferAttribute(toI8(nrm), 3, true));
1610
+ g.setAttribute("ldrColor", new THREE.BufferAttribute(col instanceof Uint8Array ? col : toU8(col), 4, true));
1611
+ if (b.idx)
1612
+ g.setIndex(new THREE.BufferAttribute(arr(b.idx), 1));
1613
+ if (b.uv)
1614
+ g.setAttribute("ldrUV", new THREE.BufferAttribute(arr(b.uv), 2));
1615
+ c.set(b, g);
1616
+ return g;
1617
+ }
1618
+ function makeMaterial(side) {
1619
+ const m = new THREE.MeshStandardMaterial({ vertexColors: true, roughness: 0.45, side });
1620
+ m.onBeforeCompile = (s) => {
1621
+ s.vertexShader = `attribute vec4 ldrColor;
1622
+ ` + s.vertexShader.replace("#include <color_vertex>", `#include <color_vertex>
1623
+ #ifdef USE_INSTANCING_COLOR
1624
+ vColor.rgb = ldrColor.a > 0.5 ? pow(ldrColor.rgb, vec3(2.2)) : instanceColor.rgb; // baked LDConfig colours are sRGB
1625
+ #else
1626
+ vColor.rgb = pow(ldrColor.rgb, vec3(2.2));
1627
+ #endif`);
1628
+ };
1629
+ m.customProgramCacheKey = () => "ldrColor";
1630
+ return m;
1631
+ }
1632
+ function makeTexturedMaterial(side, map, wrapU = false) {
1633
+ const m = makeMaterial(side);
1634
+ const base = m.onBeforeCompile;
1635
+ m.onBeforeCompile = (sh, r) => {
1636
+ base.call(m, sh, r);
1637
+ sh.uniforms.ldrMap = { value: map };
1638
+ sh.uniforms.ldrWrapU = { value: wrapU ? 1 : 0 };
1639
+ sh.vertexShader = `attribute vec2 ldrUV; varying vec2 vLdrUV;
1640
+ ` + sh.vertexShader.replace("#include <uv_vertex>", `#include <uv_vertex>
1641
+ vLdrUV = ldrUV;`);
1642
+ sh.fragmentShader = `uniform sampler2D ldrMap; uniform int ldrWrapU; varying vec2 vLdrUV;
1643
+ ` + sh.fragmentShader.replace("#include <color_fragment>", `#include <color_fragment>
1644
+ { vec2 uv = vec2(ldrWrapU == 1 ? fract(vLdrUV.x) : vLdrUV.x, vLdrUV.y); vec4 t = texture2D(ldrMap, uv);
1645
+ float inside = step(0.0, uv.x) * step(uv.x, 1.0) * step(0.0, uv.y) * step(uv.y, 1.0);
1646
+ diffuseColor.rgb = mix(diffuseColor.rgb, t.rgb, t.a * inside); }`);
1647
+ };
1648
+ m.customProgramCacheKey = () => "ldrColorTex";
1649
+ m.userData.ldrMap = map;
1650
+ return m;
1651
+ }
1652
+ function packTexture(pack, i) {
1653
+ const t = new THREE.Texture;
1654
+ t.flipY = false;
1655
+ t.colorSpace = THREE.SRGBColorSpace;
1656
+ t.wrapS = t.wrapT = THREE.ClampToEdgeWrapping;
1657
+ const e = pack.header.textures?.[i];
1658
+ const bytes = e?.data ? pack.arr(e.data) : null;
1659
+ if (!bytes || typeof createImageBitmap === "undefined")
1660
+ return { texture: t, ready: Promise.resolve() };
1661
+ const ready = createImageBitmap(new Blob([bytes], { type: e.mime || "image/png" }), { premultiplyAlpha: "none", colorSpaceConversion: "none" }).then((img) => {
1662
+ t.image = img;
1663
+ t.needsUpdate = true;
1664
+ }).catch(() => {});
1665
+ return { texture: t, ready };
1666
+ }
1667
+ var sharedLineMat = () => new THREE.ShaderMaterial({
1668
+ vertexShader: `attribute mat4 instanceMatrix; void main(){ gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4(position,1.0); }`,
1669
+ fragmentShader: `void main(){ gl_FragColor = vec4(0.13,0.13,0.13,1.0); }`
1670
+ });
1671
+ var weldLines = (pos, byLength = false) => {
1672
+ const map = new Map;
1673
+ const P = [];
1674
+ const I = [];
1675
+ const n = Math.floor(pos.length / 6);
1676
+ const len = new Float32Array(n);
1677
+ for (let s = 0;s < n; s++) {
1678
+ const o = s * 6;
1679
+ len[s] = Math.hypot(pos[o + 3] - pos[o], pos[o + 4] - pos[o + 1], pos[o + 5] - pos[o + 2]);
1680
+ }
1681
+ const order = Array.from({ length: n }, (_, s) => s);
1682
+ if (byLength)
1683
+ order.sort((a, b) => len[b] - len[a]);
1684
+ for (const sg of order)
1685
+ for (let e = 0;e < 2; e++) {
1686
+ const i = sg * 6 + e * 3;
1687
+ const k = pos[i].toFixed(2) + "," + pos[i + 1].toFixed(2) + "," + pos[i + 2].toFixed(2);
1688
+ let j = map.get(k);
1689
+ if (j === undefined) {
1690
+ j = P.length / 3;
1691
+ map.set(k, j);
1692
+ P.push(pos[i], pos[i + 1], pos[i + 2]);
1693
+ }
1694
+ I.push(j);
1695
+ }
1696
+ return { P: new Float32Array(P), I: P.length / 3 < 65536 ? new Uint16Array(I) : new Uint32Array(I), lens: Float32Array.from(order, (sg) => len[sg]) };
1697
+ };
1698
+ function createInstancedEdges(pos, im, material = sharedLineMat()) {
1699
+ return sharedLines(pos, im, material);
1700
+ }
1701
+ function conditionalLines(pack, entry, which = "all") {
1702
+ if (which === "all") {
1703
+ const a = conditionalLines(pack, entry, "body"), b = conditionalLines(pack, entry, "under");
1704
+ if (!a || !b)
1705
+ return a ?? b;
1706
+ const o = new Float32Array(a.length + b.length);
1707
+ o.set(a);
1708
+ o.set(b, a.length);
1709
+ return o;
1710
+ }
1711
+ const c = which === "under" ? entry?.condlu : entry?.condl;
1712
+ if (!c)
1713
+ return null;
1714
+ const { arr } = pack;
1715
+ if (c.raw)
1716
+ return arr(c.raw);
1717
+ const pools = [entry.body ? arr(entry.body.pos) : [], entry.under ? arr(entry.under.pos) : [], entry.edges ? arr(entry.edges) : [], c.x ? arr(c.x) : []];
1718
+ const idx = arr(c.idx);
1719
+ const out = new Float32Array(idx.length * 3);
1720
+ const starts = [];
1721
+ let base = 0;
1722
+ for (const p of pools) {
1723
+ starts.push(base);
1724
+ base += p.length / 3;
1725
+ }
1726
+ let prev = 0;
1727
+ for (let i = 0;i < idx.length; i++) {
1728
+ const z = idx[i];
1729
+ const j = prev + (z & 1 ? -(z + 1) / 2 : z / 2);
1730
+ prev = j;
1731
+ let k = 3;
1732
+ while (k > 0 && j < starts[k])
1733
+ k--;
1734
+ const p = pools[k], o = (j - starts[k]) * 3;
1735
+ out[i * 3] = p[o];
1736
+ out[i * 3 + 1] = p[o + 1];
1737
+ out[i * 3 + 2] = p[o + 2];
1738
+ }
1739
+ return out;
1740
+ }
1741
+ var condLineMat = () => new THREE.ShaderMaterial({
1742
+ uniforms: { ldrViewProj: { value: new THREE.Matrix4 } },
1743
+ vertexShader: `uniform mat4 ldrViewProj; attribute mat4 instanceMatrix; attribute vec3 ldrP1; attribute vec3 ldrC0; attribute vec3 ldrC1; attribute float ldrSide;
1744
+ void main(){
1745
+ mat4 mvp = ldrViewProj * instanceMatrix;
1746
+ 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);
1747
+ vec2 A = a.xy / a.w, B = b.xy / b.w, C0 = c0.xy / c0.w, C1 = c1.xy / c1.w, d = B - A;
1748
+ 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);
1749
+ gl_Position = s0 * s1 >= 0.0 ? (ldrSide > 0.5 ? b : a) : vec4(2.0, 2.0, 2.0, 1.0);
1750
+ }`,
1751
+ fragmentShader: `void main(){ gl_FragColor = vec4(0.13,0.13,0.13,1.0); }`
1752
+ });
1753
+ function conditionalLineVisible(cond, i, mvp) {
1754
+ const e = mvp.elements;
1755
+ const pr = (o) => {
1756
+ const x = cond[o], y = cond[o + 1], z = cond[o + 2];
1757
+ const w = e[3] * x + e[7] * y + e[11] * z + e[15];
1758
+ 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];
1759
+ };
1760
+ const o = i * 12;
1761
+ const A = pr(o), B = pr(o + 3), C0 = pr(o + 6), C1 = pr(o + 9);
1762
+ const dx = B[0] - A[0], dy = B[1] - A[1];
1763
+ const s0 = dx * (C0[1] - A[1]) - dy * (C0[0] - A[0]), s1 = dx * (C1[1] - A[1]) - dy * (C1[0] - A[0]);
1764
+ return s0 * s1 >= 0;
1765
+ }
1766
+ function createInstancedConditionalEdges(cond, im, material = condLineMat()) {
1767
+ return condEdges(condBuffers(cond), im, material);
1768
+ }
1769
+ function condBuffers(cond) {
1770
+ const n = Math.floor(cond.length / 12);
1771
+ const buf = new Float32Array(n * 24), side = new Float32Array(n * 2);
1772
+ for (let l = 0;l < n; l++) {
1773
+ for (let k = 0;k < 12; k++) {
1774
+ const v = cond[l * 12 + k];
1775
+ buf[l * 24 + k] = v;
1776
+ buf[l * 24 + 12 + k] = v;
1777
+ }
1778
+ side[l * 2 + 1] = 1;
1307
1779
  }
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)
1780
+ return { ib: new THREE.InterleavedBuffer(buf, 12), side: new THREE.BufferAttribute(side, 1) };
1781
+ }
1782
+ function condEdges({ ib, side }, im, material) {
1783
+ const g = new THREE.InstancedBufferGeometry;
1784
+ g.setAttribute("position", new THREE.InterleavedBufferAttribute(ib, 3, 0));
1785
+ g.setAttribute("ldrP1", new THREE.InterleavedBufferAttribute(ib, 3, 3));
1786
+ g.setAttribute("ldrC0", new THREE.InterleavedBufferAttribute(ib, 3, 6));
1787
+ g.setAttribute("ldrC1", new THREE.InterleavedBufferAttribute(ib, 3, 9));
1788
+ g.setAttribute("ldrSide", side);
1789
+ g.setAttribute("instanceMatrix", im.instanceMatrix);
1790
+ g.instanceCount = im.count;
1791
+ const l = new THREE.LineSegments(g, material);
1792
+ l.frustumCulled = false;
1793
+ l.name = "ldrCondLines";
1794
+ l.onBeforeRender = (_r, _s, cam, _g, mat) => {
1795
+ const u = mat.uniforms?.ldrViewProj;
1796
+ if (!u)
1325
1797
  return;
1326
- if (!steps) {
1327
- tops.put(k, 1);
1798
+ l.modelViewMatrix.multiplyMatrices(cam.matrixWorldInverse, l.matrixWorld);
1799
+ u.value.multiplyMatrices(cam.projectionMatrix, l.modelViewMatrix);
1800
+ mat.uniformsNeedUpdate = true;
1801
+ };
1802
+ return l;
1803
+ }
1804
+ function sharedLines(pos, im, material = sharedLineMat()) {
1805
+ const { P, I } = weldLines(pos);
1806
+ const g = new THREE.InstancedBufferGeometry;
1807
+ g.setAttribute("position", new THREE.BufferAttribute(P, 3));
1808
+ g.setIndex(new THREE.BufferAttribute(I, 1));
1809
+ g.setAttribute("instanceMatrix", im.instanceMatrix);
1810
+ g.instanceCount = im.count;
1811
+ const l = new THREE.LineSegments(g, material);
1812
+ l.frustumCulled = false;
1813
+ return l;
1814
+ }
1815
+ function writeM4(t, o, m, mo = 0) {
1816
+ t[o] = m[mo + 3];
1817
+ t[o + 1] = m[mo + 6];
1818
+ t[o + 2] = m[mo + 9];
1819
+ t[o + 3] = 0;
1820
+ t[o + 4] = m[mo + 4];
1821
+ t[o + 5] = m[mo + 7];
1822
+ t[o + 6] = m[mo + 10];
1823
+ t[o + 7] = 0;
1824
+ t[o + 8] = m[mo + 5];
1825
+ t[o + 9] = m[mo + 8];
1826
+ t[o + 10] = m[mo + 11];
1827
+ t[o + 11] = 0;
1828
+ t[o + 12] = m[mo];
1829
+ t[o + 13] = m[mo + 1];
1830
+ t[o + 14] = m[mo + 2];
1831
+ t[o + 15] = 1;
1832
+ }
1833
+ function newIM(g, mat, n) {
1834
+ const im = new THREE.InstancedMesh(g, mat, 0);
1835
+ im.instanceMatrix = new THREE.InstancedBufferAttribute(new Float32Array(n * 16), 16);
1836
+ im.count = n;
1837
+ return im;
1838
+ }
1839
+ function instancedBoundingSphere(im) {
1840
+ const g = im.geometry;
1841
+ if (!g.boundingSphere)
1842
+ g.computeBoundingSphere();
1843
+ const gs = g.boundingSphere;
1844
+ const gx = gs.center.x, gy = gs.center.y, gz = gs.center.z, gr = gs.radius;
1845
+ const A = im.instanceMatrix.array;
1846
+ let cx = 0, cy = 0, cz = 0, r = -1;
1847
+ const expand = (px, py, pz) => {
1848
+ if (r < 0) {
1849
+ cx = px;
1850
+ cy = py;
1851
+ cz = pz;
1852
+ r = 0;
1328
1853
  return;
1329
1854
  }
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))
1855
+ const vx = px - cx, vy = py - cy, vz = pz - cz;
1856
+ const l2 = vx * vx + vy * vy + vz * vz;
1857
+ if (l2 > r * r) {
1858
+ const l = Math.sqrt(l2);
1859
+ const d = (l - r) * 0.5;
1860
+ const f = d / l;
1861
+ cx += vx * f;
1862
+ cy += vy * f;
1863
+ cz += vz * f;
1864
+ r += d;
1865
+ }
1866
+ };
1867
+ for (let i = 0, n = im.count;i < n; i++) {
1868
+ const o = i * 16;
1869
+ 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];
1870
+ const w = 1 / (e3 * gx + e7 * gy + e11 * gz + A[o + 15]);
1871
+ 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;
1872
+ 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));
1873
+ if (r < 0) {
1874
+ cx = x;
1875
+ cy = y;
1876
+ cz = z;
1877
+ r = sr;
1340
1878
  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)
1879
+ }
1880
+ if (x === cx && y === cy && z === cz) {
1881
+ r = Math.max(r, sr);
1344
1882
  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
1883
  }
1884
+ let dx = x - cx, dy = y - cy, dz = z - cz;
1885
+ const inv = 1 / (Math.sqrt(dx * dx + dy * dy + dz * dz) || 1);
1886
+ dx = dx * inv * sr;
1887
+ dy = dy * inv * sr;
1888
+ dz = dz * inv * sr;
1889
+ expand(x + dx, y + dy, z + dz);
1890
+ expand(x - dx, y - dy, z - dz);
1365
1891
  }
1366
- return { nStuds, studHidden, studUp, underHidden, studsHidden, studHideStep, underHideStep };
1892
+ const sph = im.boundingSphere ?? new THREE.Sphere;
1893
+ sph.center.set(cx, cy, cz);
1894
+ sph.radius = r;
1895
+ if (r < 0)
1896
+ sph.makeEmpty();
1897
+ im.boundingSphere = sph;
1898
+ return sph;
1899
+ }
1900
+ function fillInstances(im, ids, insts, color) {
1901
+ const M = im.instanceMatrix.array;
1902
+ const C = new Float32Array(ids.length * 3);
1903
+ for (let k = 0;k < ids.length; k++) {
1904
+ const it = insts[ids[k]];
1905
+ writeM4(M, k * 16, it.m);
1906
+ color(it.color).toArray(C, k * 3);
1907
+ }
1908
+ im.instanceColor = new THREE.InstancedBufferAttribute(C, 3);
1367
1909
  }
1368
1910
  function computeCulling(insts, H) {
1369
1911
  const c = cullCore(insts, H);
@@ -1419,7 +1961,8 @@ class LdrLodRoot extends THREE.LOD {
1419
1961
  clusters = [];
1420
1962
  vpH = 1080;
1421
1963
  px = 0.5;
1422
- edgePpl = 0.025;
1964
+ edgePpl = 0.5 / 20;
1965
+ edgeMinPx = 0.15;
1423
1966
  enabled = true;
1424
1967
  apply = () => {};
1425
1968
  inv = new THREE.Matrix4;
@@ -1449,37 +1992,90 @@ class LdrLodRoot extends THREE.LOD {
1449
1992
  L = i;
1450
1993
  break;
1451
1994
  }
1995
+ if (c.below !== undefined && x * c.ax[0] + y * c.ax[1] + z * c.ax[2] < c.below - 1 && ppl * 20 < 4)
1996
+ L = -1;
1997
+ if (c.boxErr !== undefined && c.boxErr * ppl <= tau)
1998
+ L = -1;
1452
1999
  const e = ppl >= eppl;
1453
2000
  if (L !== c.cur || e !== c.edgeOk) {
1454
2001
  c.cur = L;
1455
2002
  c.edgeOk = e;
1456
2003
  this.apply(c);
1457
2004
  }
2005
+ if (e && c.lines.length) {
2006
+ const minLen = this.edgeMinPx / ppl;
2007
+ for (const l of c.lines) {
2008
+ const lens = l.userData.ldrLens;
2009
+ if (!lens)
2010
+ continue;
2011
+ let lo = 0, hi = lens.length;
2012
+ while (lo < hi) {
2013
+ const mid = lo + hi >> 1;
2014
+ if (lens[mid] >= minLen)
2015
+ lo = mid + 1;
2016
+ else
2017
+ hi = mid;
2018
+ }
2019
+ l.geometry.drawRange.count = lo * 2;
2020
+ }
2021
+ }
1458
2022
  }
1459
2023
  }
1460
2024
  }
1461
- function buildStudMeshes(insts, H, cull, arr, Q, LOD, color, matF, matB, steps, colorIndex) {
2025
+ function buildStudMeshes(insts, H, cull, arr, LOD, color, matF, matB, steps, colorIndex) {
1462
2026
  const bucketOf = new Map;
1463
2027
  const bKind = [], bMirror = [];
1464
2028
  const bAll = [];
1465
2029
  const studBucket = new Uint16Array(cull.nStuds);
1466
2030
  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
- });
2031
+ const kindIds = new Map;
2032
+ const kindNames = [];
2033
+ const bucketOfKM = [];
2034
+ const partStud = new Map;
2035
+ for (let idx = 0, j = 0;idx < insts.length; idx++) {
2036
+ const it = insts[idx];
2037
+ const pp = prepPart(H, it.part);
2038
+ if (!pp || !pp.nStuds)
2039
+ continue;
2040
+ const a = it.m;
2041
+ let ps = partStud.get(pp);
2042
+ if (!ps) {
2043
+ const kid = new Int32Array(pp.nStuds), neg = new Uint8Array(pp.nStuds);
2044
+ for (let si = 0;si < pp.nStuds; si++) {
2045
+ const kn = pp.kind[si];
2046
+ let id = kindIds.get(kn);
2047
+ if (id === undefined) {
2048
+ id = kindNames.length;
2049
+ kindIds.set(kn, id);
2050
+ kindNames.push(kn);
2051
+ }
2052
+ kid[si] = id;
2053
+ neg[si] = det12(pp.studM.subarray(si * 12, si * 12 + 12)) < 0 ? 1 : 0;
2054
+ }
2055
+ partStud.set(pp, ps = { kid, neg });
2056
+ }
2057
+ const instNeg = det12(a) < 0 ? 1 : 0;
2058
+ const B = pp.studM;
2059
+ for (let si = 0;si < pp.nStuds; si++, j++) {
2060
+ const o = si * 12, b0 = B[o], b1 = B[o + 1], b2 = B[o + 2];
2061
+ const neg = (instNeg ^ ps.neg[si]) === 1;
2062
+ const km = ps.kid[si] * 2 + (neg ? 1 : 0);
2063
+ let b = bucketOfKM[km];
2064
+ if (b === undefined) {
2065
+ const kn = kindNames[ps.kid[si]];
2066
+ b = bKind.length;
2067
+ bucketOfKM[km] = b;
2068
+ bucketOf.set(neg ? kn + "#m" : kn, b);
2069
+ bKind.push(kn);
2070
+ bMirror.push(neg);
2071
+ bAll.push(0);
2072
+ }
2073
+ studBucket[j] = b;
2074
+ bAll[b]++;
2075
+ sx[j] = a[0] + a[3] * b0 + a[4] * b1 + a[5] * b2;
2076
+ sz[j] = a[2] + a[9] * b0 + a[10] * b1 + a[11] * b2;
2077
+ }
2078
+ }
1483
2079
  const bIds = bAll.map((n) => new Int32Array(n));
1484
2080
  {
1485
2081
  const f = bAll.map(() => 0);
@@ -1491,7 +2087,7 @@ function buildStudMeshes(insts, H, cull, arr, Q, LOD, color, matF, matB, steps,
1491
2087
  const studCl = new Int32Array(cull.nStuds), studSlot = new Int32Array(cull.nStuds);
1492
2088
  const sMesh = [];
1493
2089
  bKind.forEach((kind, b) => {
1494
- const g = geom(H.studKinds[kind].body, arr, Q);
2090
+ const g = geom(H.studKinds[kind].body, arr);
1495
2091
  const ids = bIds[b];
1496
2092
  for (const c of gridClusters(ids.length, (i) => sx[ids[i]], (i) => sz[ids[i]], LOD ? 16384 : Infinity)) {
1497
2093
  const ci = sMesh.length;
@@ -1515,6 +2111,13 @@ function buildStudMeshes(insts, H, cull, arr, Q, LOD, color, matF, matB, steps,
1515
2111
  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
2112
  }
1517
2113
  });
2114
+ const colCache = new Map;
2115
+ const colorOf = (c) => {
2116
+ let x = colCache.get(c);
2117
+ if (!x)
2118
+ colCache.set(c, x = color(c));
2119
+ return x;
2120
+ };
1518
2121
  forEachStud(insts, H, (j, owner, w, _kind, col, si) => {
1519
2122
  const sm = sMesh[studCl[j]];
1520
2123
  if (!sm)
@@ -1530,18 +2133,46 @@ function buildStudMeshes(insts, H, cull, arr, Q, LOD, color, matF, matB, steps,
1530
2133
  t.col[slot] = colorIndex(col);
1531
2134
  }
1532
2135
  writeM4(im.instanceMatrix.array, slot * 16, w);
1533
- color(col).toArray(im.instanceColor.array, slot * 3);
2136
+ colorOf(col).toArray(im.instanceColor.array, slot * 3);
1534
2137
  });
1535
2138
  return sMesh;
1536
2139
  }
2140
+ function undersideGroups(ids, insts) {
2141
+ const by = new Map;
2142
+ const rest = [];
2143
+ for (const id of ids) {
2144
+ const m = insts[id].m;
2145
+ const l = Math.hypot(m[4], m[7], m[10]);
2146
+ if (!(l > 0.000001)) {
2147
+ rest.push(id);
2148
+ continue;
2149
+ }
2150
+ const ax = [m[4] / l, m[7] / l, m[10] / l, l];
2151
+ const k = ax.map((v) => Math.round(v * 1000)).join();
2152
+ let g = by.get(k);
2153
+ if (!g) {
2154
+ if (by.size >= 12) {
2155
+ rest.push(id);
2156
+ continue;
2157
+ }
2158
+ by.set(k, g = { ids: [], ax });
2159
+ }
2160
+ g.ids.push(id);
2161
+ }
2162
+ const out = [...by.values()];
2163
+ if (rest.length)
2164
+ out.push({ ids: rest, ax: null });
2165
+ return out;
2166
+ }
1537
2167
  function buildLdrScene(insts, pack, P, color, mark) {
1538
2168
  const { header: H, arr } = pack;
1539
- const Q = P.quant !== false;
1540
2169
  const LOD = P.lod !== false;
2170
+ const EDGES = !!P.edges;
1541
2171
  const root = new LdrLodRoot;
1542
2172
  root.enabled = LOD;
1543
2173
  root.px = P.lodPx ?? 0.5;
1544
2174
  root.edgePpl = (P.lodEdgePx ?? 0.5) / 20;
2175
+ root.edgeMinPx = P.lodEdgeMinPx ?? 0.15;
1545
2176
  const trackVp = (r) => {
1546
2177
  const rt = r.getRenderTarget();
1547
2178
  const h = rt ? rt.height : r.getContext().drawingBufferHeight;
@@ -1559,7 +2190,7 @@ function buildLdrScene(insts, pack, P, color, mark) {
1559
2190
  }
1560
2191
  });
1561
2192
  const steps = P.steps;
1562
- let cull = cullCore(insts, H, steps);
2193
+ let cull = P.cull ?? cullCore(insts, H, steps);
1563
2194
  mark("culling");
1564
2195
  const stepBatches = [];
1565
2196
  const instM = steps ? new Float64Array(insts.length * 12) : null;
@@ -1585,7 +2216,7 @@ function buildLdrScene(insts, pack, P, color, mark) {
1585
2216
  });
1586
2217
  const edgeObjs = [];
1587
2218
  const condObjs = [];
1588
- const wantCond = P.cond !== false && (P.edges === "idx" || P.edges === true);
2219
+ const wantCond = P.cond !== false && EDGES;
1589
2220
  let condMat = null;
1590
2221
  const cmat = () => condMat ??= condLineMat();
1591
2222
  let lineMatShared = null;
@@ -1616,8 +2247,8 @@ function buildLdrScene(insts, pack, P, color, mark) {
1616
2247
  const addLines = (ref, im, cl) => {
1617
2248
  let w = lineCache.get(ref);
1618
2249
  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) });
2250
+ const r = weldLines(arr(ref), LOD);
2251
+ lineCache.set(ref, w = { P: new THREE.BufferAttribute(r.P, 3), I: new THREE.BufferAttribute(r.I, 1), lens: r.lens });
1621
2252
  }
1622
2253
  const g = new THREE.InstancedBufferGeometry;
1623
2254
  g.setAttribute("position", w.P);
@@ -1626,6 +2257,8 @@ function buildLdrScene(insts, pack, P, color, mark) {
1626
2257
  g.instanceCount = im.count;
1627
2258
  const l = new THREE.LineSegments(g, lmat());
1628
2259
  l.frustumCulled = false;
2260
+ if (LOD)
2261
+ l.userData.ldrLens = w.lens;
1629
2262
  edgeObjs.push(l);
1630
2263
  cl.lines.push(l);
1631
2264
  root.add(l);
@@ -1633,7 +2266,6 @@ function buildLdrScene(insts, pack, P, color, mark) {
1633
2266
  };
1634
2267
  const stats = { studsTotal: cull.nStuds, studsHidden: cull.studsHidden, undersTotal: 0, undersHidden: 0 };
1635
2268
  const toggles = [];
1636
- const studMeshes = [];
1637
2269
  const countTo = (objs) => ({ set count(n) {
1638
2270
  for (const o of objs()) {
1639
2271
  if (o.isInstancedMesh)
@@ -1668,8 +2300,9 @@ function buildLdrScene(insts, pack, P, color, mark) {
1668
2300
  root.clusters.push(c);
1669
2301
  return c;
1670
2302
  };
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);
2303
+ const lodLevels = (b, base, mat) => !LOD || !b?.lod ? [] : b.lod.map((l) => {
2304
+ const im = new THREE.InstancedMesh(geom(l, arr), mat, 0);
2305
+ im.userData = { ...base.userData };
1673
2306
  im.instanceMatrix = base.instanceMatrix;
1674
2307
  im.count = base.count;
1675
2308
  im.instanceColor = base.instanceColor;
@@ -1685,10 +2318,10 @@ function buildLdrScene(insts, pack, P, color, mark) {
1685
2318
  for (const [pk, idsAll] of byPart) {
1686
2319
  const part = pk.replace(/#m$/, "");
1687
2320
  const p = H.parts[part];
1688
- const mat = P.uncertDouble !== false && p.uncert ? (nUncert++, matD) : pk.endsWith("#m") ? matB : matF;
2321
+ const mat = p.uncert ? (nUncert++, matD) : pk.endsWith("#m") ? matB : matF;
1689
2322
  const textured = wantTex && !!p.tex;
1690
2323
  const bodyB = textured ? p.tbody : p.body;
1691
- const body = geom(bodyB, arr, Q);
2324
+ const body = geom(bodyB, arr);
1692
2325
  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
2326
  for (const g of groups) {
1694
2327
  const ids = Array.from(g, (i) => idsAll[i]);
@@ -1696,7 +2329,8 @@ function buildLdrScene(insts, pack, P, color, mark) {
1696
2329
  const lv0 = [];
1697
2330
  const place = (im) => {
1698
2331
  fillInstances(im, ids, insts, color);
1699
- im.computeBoundingSphere();
2332
+ instancedBoundingSphere(im);
2333
+ im.userData.ldrPart = part;
1700
2334
  root.add(im);
1701
2335
  };
1702
2336
  if (body) {
@@ -1706,7 +2340,7 @@ function buildLdrScene(insts, pack, P, color, mark) {
1706
2340
  }
1707
2341
  if (textured)
1708
2342
  for (const tb of p.tex) {
1709
- const gg = geom(tb, arr, Q);
2343
+ const gg = geom(tb, arr);
1710
2344
  const im = newIM(gg, texMat(tb.t, mat, !!tb.wrapU), ids.length);
1711
2345
  texBatches++;
1712
2346
  lv0.push(im);
@@ -1724,49 +2358,57 @@ function buildLdrScene(insts, pack, P, color, mark) {
1724
2358
  const cl = newCluster(bodyIm.boundingSphere);
1725
2359
  lv0.forEach((o) => o.onBeforeRender = trackVp);
1726
2360
  cl.lv.push({ objs: lv0, err: 0 }, ...textured ? [] : lodLevels(p.body, bodyIm, mat));
1727
- if (P.edges === "idx" && p.edges)
2361
+ if (EDGES && p.edges)
1728
2362
  addLines(p.edges, bodyIm, cl);
1729
2363
  addCond(p, bodyIm, cl);
1730
2364
  if (steps)
1731
2365
  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
2366
  }
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);
2367
+ const under = geom(p.under, arr);
2368
+ const uGroups = !under ? [] : LOD && P.lodUnder !== false ? undersideGroups(ids, insts) : [{ ids, ax: null }];
2369
+ for (const { ids: uids, ax } of uGroups) {
2370
+ const ord = [...uids.filter((i) => !cull.underHidden[i]), ...uids.filter((i) => cull.underHidden[i])];
2371
+ const vis = uids.length - uids.reduce((a, i) => a + cull.underHidden[i], 0);
2372
+ stats.undersTotal += uids.length;
2373
+ stats.undersHidden += uids.length - vis;
2374
+ const im = newIM(under, mat, uids.length);
1750
2375
  fillInstances(im, ord, insts, color);
1751
2376
  im.onBeforeRender = trackVp;
1752
- im.computeBoundingSphere();
1753
- im.count = P.cullUnder ? vis : ids.length;
2377
+ im.userData.ldrUnder = true;
2378
+ im.userData.ldrPart = part;
2379
+ instancedBoundingSphere(im);
2380
+ im.count = P.cullUnder ? vis : uids.length;
1754
2381
  root.add(im);
1755
2382
  const cl = newCluster(im.boundingSphere);
1756
2383
  cl.lv.push({ objs: [im], err: 0 }, ...lodLevels(p.under, im, mat));
2384
+ {
2385
+ const bl = p.body?.lod;
2386
+ const last = bl?.[bl.length - 1];
2387
+ if (LOD && P.lodUnder !== false && last && last.tris === 12)
2388
+ cl.boxErr = last.err;
2389
+ }
2390
+ if (ax) {
2391
+ let below = Infinity;
2392
+ for (const id of uids) {
2393
+ const m = insts[id].m;
2394
+ below = Math.min(below, m[0] * ax[0] + m[1] * ax[1] + m[2] * ax[2] + p.bbox[4] * ax[3]);
2395
+ }
2396
+ cl.below = below;
2397
+ cl.ax = ax.slice(0, 3);
2398
+ }
1757
2399
  addCond(p, im, cl, "under");
1758
2400
  const objs = [...cl.lv.flatMap((l) => l.objs), ...cl.cond];
1759
2401
  objs.forEach((o) => {
1760
2402
  if (!o.isInstancedMesh)
1761
2403
  o.geometry.instanceCount = im.count;
1762
2404
  });
1763
- toggles.push({ mesh: countTo(() => objs), all: ids.length, visible: vis, flag: "under" });
2405
+ toggles.push({ mesh: countTo(() => objs), all: uids.length, visible: vis, flag: "under" });
1764
2406
  if (steps)
1765
2407
  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
2408
  }
1767
2409
  }
1768
2410
  }
1769
- const sMesh = buildStudMeshes(insts, H, cull, arr, Q, LOD, color, matF, matB, steps, steps && colorIndex);
2411
+ const sMesh = buildStudMeshes(insts, H, cull, arr, LOD, color, matF, matB, steps, steps && colorIndex);
1770
2412
  const sKind = sMesh.map((x) => x?.kind ?? "");
1771
2413
  const sVis = sMesh.map((x) => x?.vis ?? 0);
1772
2414
  const STUD_ERR = 12;
@@ -1777,26 +2419,19 @@ function buildLdrScene(insts, pack, P, color, mark) {
1777
2419
  const kind = sKind[ci];
1778
2420
  const k = H.studKinds[kind];
1779
2421
  const vis = sVis[ci], all = im.instanceMatrix.count;
1780
- im.computeBoundingSphere();
2422
+ instancedBoundingSphere(im);
1781
2423
  im.count = P.cullStuds ? vis : all;
1782
2424
  im.onBeforeRender = trackVp;
1783
2425
  im.userData.ldrStud = true;
1784
2426
  root.add(im);
1785
- studMeshes.push({ im, kind });
1786
2427
  const cl = newCluster(im.boundingSphere);
1787
2428
  cl.lv.push({ objs: [im], err: 0 });
1788
- if (LOD && P.lodStuds !== false)
2429
+ if (LOD)
1789
2430
  cl.lv.push({ objs: [], err: STUD_ERR });
1790
- if (P.edges === "idx" && k.edges)
2431
+ if (EDGES && k.edges)
1791
2432
  addLines(k.edges, im, cl);
1792
2433
  if (P.condStuds !== false)
1793
2434
  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
2435
  const objs = [im, ...cl.lines, ...cl.cond];
1801
2436
  objs.forEach((o) => {
1802
2437
  if (!o.isInstancedMesh)
@@ -1814,7 +2449,7 @@ function buildLdrScene(insts, pack, P, color, mark) {
1814
2449
  for (const o of l.objs)
1815
2450
  o.visible = i === c.cur;
1816
2451
  });
1817
- const lineVis = edgesOn && c.edgeOk && (c.cur === 0 || !LOD || c.lv[c.cur].objs.length > 0);
2452
+ const lineVis = edgesOn && c.edgeOk && c.cur >= 0 && (c.cur === 0 || !LOD || c.lv[c.cur].objs.length > 0);
1818
2453
  for (const o of c.lines)
1819
2454
  o.visible = lineVis;
1820
2455
  for (const o of c.cond)
@@ -1836,9 +2471,10 @@ function buildLdrScene(insts, pack, P, color, mark) {
1836
2471
  stats.clusters = root.clusters.length;
1837
2472
  const texturesReady = Promise.all(pending).then(() => {});
1838
2473
  let stepS = STEP_NEVER - 1, cullS = !!P.cullStuds, cullU = !!P.cullUnder;
2474
+ let only = null;
1839
2475
  const applySteps = () => {
1840
2476
  const st = { studsTotal: 0, studsHidden: 0, undersTotal: 0, undersHidden: 0 };
1841
- const S = stepS;
2477
+ const S = stepS, O = only;
1842
2478
  const wm = new Float64Array(12);
1843
2479
  for (const b of stepBatches) {
1844
2480
  const MA = b.im.instanceMatrix.array, CA = b.im.instanceColor.array;
@@ -1861,6 +2497,8 @@ function buildLdrScene(insts, pack, P, color, mark) {
1861
2497
  if (useHide && hid)
1862
2498
  continue;
1863
2499
  const n = inst[i];
2500
+ if (O && !O[n])
2501
+ continue;
1864
2502
  if (stud) {
1865
2503
  mul12To(instM, instPP[n].studM, stud[i] * 12, wm, n * 12);
1866
2504
  writeM4(MA, w * 16, wm);
@@ -1890,10 +2528,11 @@ function buildLdrScene(insts, pack, P, color, mark) {
1890
2528
  for (const t of toggles)
1891
2529
  t.mesh.count = (t.flag === "studs" ? studs : under) ? t.visible : t.all;
1892
2530
  };
1893
- const setStep = (s) => {
2531
+ const setStep = (s, mask = null) => {
1894
2532
  if (!steps)
1895
2533
  throw new Error("buildLdrScene: setStep needs P.steps");
1896
2534
  stepS = s == null ? STEP_NEVER - 1 : s;
2535
+ only = mask;
1897
2536
  return applySteps();
1898
2537
  };
1899
2538
  const box = new THREE.Box3;
@@ -1924,21 +2563,14 @@ function buildLdrScene(insts, pack, P, color, mark) {
1924
2563
  m.needsUpdate = true;
1925
2564
  }
1926
2565
  };
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
2566
  const setLod = (on) => {
1937
2567
  root.enabled = on && LOD;
1938
2568
  if (!root.enabled) {
1939
2569
  for (const c of root.clusters) {
1940
2570
  c.cur = 0;
1941
2571
  c.edgeOk = true;
2572
+ for (const l of c.lines)
2573
+ l.geometry.drawRange.count = Infinity;
1942
2574
  }
1943
2575
  refresh();
1944
2576
  }
@@ -1946,9 +2578,31 @@ function buildLdrScene(insts, pack, P, color, mark) {
1946
2578
  insts = null;
1947
2579
  cull = null;
1948
2580
  byPart.clear();
1949
- return { root, stats, setCull, setSide, setEdges, setCond, swapStuds, setLod, setStep, box, texturesReady };
2581
+ return { root, stats, setCull, setSide, setEdges, setCond, setLod, setStep, box, texturesReady };
2582
+ }
2583
+ async function warmPackGeometry(pack, stop = () => false, sliceMs = 8) {
2584
+ const { header: H, arr } = pack;
2585
+ const list = [];
2586
+ for (const p of Object.values(H.parts ?? {}))
2587
+ for (const b of [p.body, p.under])
2588
+ if (b) {
2589
+ list.push(b);
2590
+ for (const l of b.lod ?? [])
2591
+ list.push(l);
2592
+ }
2593
+ for (const k of Object.values(H.studKinds ?? {}))
2594
+ if (k?.body)
2595
+ list.push(k.body);
2596
+ let i = 0;
2597
+ while (i < list.length && !stop()) {
2598
+ const t = performance.now();
2599
+ while (i < list.length && performance.now() - t < sliceMs)
2600
+ geom(list[i++], arr);
2601
+ if (i < list.length)
2602
+ await new Promise((r) => setTimeout(r, 0));
2603
+ }
1950
2604
  }
1951
- // ../../../../../../../tmp/ldr-build-pIke9r/src/scene.ts
2605
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/scene.ts
1952
2606
  import * as THREE2 from "three";
1953
2607
  function colorFn(src, pack, fallback) {
1954
2608
  const table = new Map;
@@ -1993,12 +2647,8 @@ function createLdrObject(instances, pack, options = {}) {
1993
2647
  const o = { edges: true, conditionalLines: true, cullStuds: true, cullUndersides: true, side: "front", material: "plastic", ...options };
1994
2648
  const color = colorFn(o.colors, pack, new THREE2.Color(o.fallbackColor ?? 10528169));
1995
2649
  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)));
2650
+ const { all, stepOf, nSteps } = sceneInstances(instances, pack.header, useTex);
2651
+ const uniq = { length: nSteps };
2002
2652
  const stepViews = new Array(uniq.length).fill(null);
2003
2653
  instances.forEach((i, k) => {
2004
2654
  if (i.view)
@@ -2034,10 +2684,10 @@ function createLdrObject(instances, pack, options = {}) {
2034
2684
  cur = null;
2035
2685
  };
2036
2686
  const multiStep = uniq.length > 1;
2037
- const drawnAt = (step) => all.filter((i, k) => (step == null || stepOf[k] <= step) && pack.header.parts[i.part]).length;
2687
+ const drawnAt = (step, mask) => all.filter((i, k) => (step == null || stepOf[k] <= step) && (!mask || mask[k]) && pack.header.parts[i.part]).length;
2038
2688
  const build = () => {
2039
2689
  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, () => {});
2690
+ 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
2691
  pairs.clear();
2042
2692
  if (o.material === "plastic")
2043
2693
  cur.root.traverse((x) => {
@@ -2055,11 +2705,11 @@ function createLdrObject(instances, pack, options = {}) {
2055
2705
  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
2706
  api.texturesReady = cur.texturesReady;
2057
2707
  };
2058
- const setStep = (step) => {
2708
+ const setStep = (step, mask = null) => {
2059
2709
  if (!multiStep)
2060
2710
  return;
2061
2711
  const t0 = performance.now();
2062
- Object.assign(stats, cur.setStep(step), { drawn: drawnAt(step), buildMs: performance.now() - t0 });
2712
+ Object.assign(stats, cur.setStep(step, mask), { drawn: drawnAt(step, mask), buildMs: performance.now() - t0 });
2063
2713
  };
2064
2714
  const api = { texturesReady: Promise.resolve() };
2065
2715
  build();
@@ -2108,18 +2758,7 @@ function createLdrObject(instances, pack, options = {}) {
2108
2758
  dispose: disposeCur
2109
2759
  });
2110
2760
  }
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
2761
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/parts-cdn.ts
2123
2762
  import { decompress as decompress2 } from "fzstd";
2124
2763
  var DEFAULT_PARTS_CDN = "https://ldr-demo.vercel.app/cdn/v1/";
2125
2764
  var indexCache = new Map;
@@ -2180,7 +2819,22 @@ function mergePacks(packs, extra = {}) {
2180
2819
  return decodePack(out.buffer);
2181
2820
  }
2182
2821
  async function loadParts(names, o = {}) {
2183
- const cdn = o.cdn ?? DEFAULT_PARTS_CDN, f = o.fetch ?? fetch, gap = o.gap ?? 65536;
2822
+ names = [...names];
2823
+ try {
2824
+ return await loadPartsOnce(names, o);
2825
+ } catch (e) {
2826
+ const cdn = o.cdn ?? DEFAULT_PARTS_CDN, f = o.fetch ?? fetch;
2827
+ indexCache.delete(cdn);
2828
+ const fresh = (u, i) => f(u, { ...i, cache: "reload" });
2829
+ try {
2830
+ return await loadPartsOnce(names, { ...o, fetch: fresh });
2831
+ } catch {
2832
+ throw e;
2833
+ }
2834
+ }
2835
+ }
2836
+ async function loadPartsOnce(names, o) {
2837
+ const cdn = o.cdn ?? DEFAULT_PARTS_CDN, f = o.fetch ?? fetch, gap = o.gap ?? 16384;
2184
2838
  const idx = await loadPartsIndex(cdn, f);
2185
2839
  const want = [...new Set([...names].map(norm))];
2186
2840
  const missing = [];
@@ -2223,7 +2877,7 @@ async function loadParts(names, o = {}) {
2223
2877
  }
2224
2878
  }
2225
2879
  };
2226
- await Promise.all(Array.from({ length: Math.min(o.concurrency ?? 6, groups.length) }, worker));
2880
+ await Promise.all(Array.from({ length: Math.min(o.concurrency ?? 24, groups.length) }, worker));
2227
2881
  const shards = want.filter((n) => shardCache.has(cdn + n)).map((n) => shardCache.get(cdn + n));
2228
2882
  const pack = shards.length ? mergePacks(shards, { colors: idx.colors }) : decodePack(emptyPack(idx.colors));
2229
2883
  return { pack, missing, requests: groups.length, bytes };
@@ -2236,10 +2890,11 @@ function emptyPack(colors) {
2236
2890
  b.set(h, 4);
2237
2891
  return b.buffer;
2238
2892
  }
2239
- async function loadModel(source, o = {}) {
2893
+ async function prepareModel(source, o = {}) {
2240
2894
  const t0 = performance.now();
2241
2895
  const f = o.fetch ?? fetch;
2242
2896
  const idxP = loadPartsIndex(o.cdn ?? DEFAULT_PARTS_CDN, f);
2897
+ idxP.catch(() => {});
2243
2898
  const text = o.text ? source : await f(source).then((r) => {
2244
2899
  if (!r.ok)
2245
2900
  throw new Error(`ldr: ${r.status} fetching ${source}`);
@@ -2247,23 +2902,140 @@ async function loadModel(source, o = {}) {
2247
2902
  });
2248
2903
  const t1 = performance.now();
2249
2904
  const name = o.name ?? (o.text ? "main.ldr" : decodeURIComponent(source.split(/[?#]/)[0].split("/").pop() || "main.ldr"));
2250
- const insts = parseModel(text, name, { looseGeometry: false });
2905
+ const insts = parseModel(text, name, { looseGeometry: false, callouts: o.callouts });
2251
2906
  const t2 = performance.now();
2907
+ o.onParsed?.(insts);
2252
2908
  await idxP;
2253
2909
  const { pack, missing, requests, bytes } = await loadParts(insts.filter((i) => !i.embedded).map((i) => i.part), o);
2254
2910
  const t3 = performance.now();
2255
- const obj = createLdrObject(insts, pack, o);
2256
- for (const m of missing)
2911
+ const cull = o.cull ? precomputeCull(insts, pack.header, o.textures !== false) : undefined;
2912
+ return { insts, pack, missing, requests, bytes, cull, timings: { fetchModel: t1 - t0, parse: t2 - t1, parts: t3 - t2, ...cull ? { cull: performance.now() - t3 } : {} } };
2913
+ }
2914
+
2915
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/load-worker.gen.ts
2916
+ 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';
2917
+
2918
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/cdn.ts
2919
+ var worker;
2920
+ var seq = 0;
2921
+ var pending = new Map;
2922
+ var pendingInsts = new Map;
2923
+ var pendingCull = new Map;
2924
+ function getWorker() {
2925
+ if (worker !== undefined)
2926
+ return worker;
2927
+ try {
2928
+ if (typeof Worker === "undefined" || typeof Blob === "undefined" || typeof URL?.createObjectURL !== "function" || !load_worker_gen_default)
2929
+ return worker = null;
2930
+ const url = URL.createObjectURL(new Blob([load_worker_gen_default], { type: "text/javascript" }));
2931
+ const w = new Worker(url, { type: "module", name: "ldr-load" });
2932
+ w.onmessage = (e) => {
2933
+ const d = e.data;
2934
+ if (d.insts) {
2935
+ pendingInsts.get(d.id)?.(d.insts);
2936
+ pendingInsts.delete(d.id);
2937
+ return;
2938
+ }
2939
+ const map = d.cull || d.error && !pending.has(d.id) ? pendingCull : pending;
2940
+ const p = map.get(d.id);
2941
+ if (!p)
2942
+ return;
2943
+ map.delete(d.id);
2944
+ d.error ? p.rej(new Error(d.error)) : p.res(d);
2945
+ };
2946
+ w.onerror = (e) => {
2947
+ e.preventDefault?.();
2948
+ worker = null;
2949
+ w.terminate();
2950
+ const err = new Error("ldr: load worker failed: " + (e.message || "error"));
2951
+ err.workerFailed = true;
2952
+ for (const m of [pending, pendingCull]) {
2953
+ for (const p of m.values())
2954
+ p.rej(err);
2955
+ m.clear();
2956
+ }
2957
+ };
2958
+ return worker = w;
2959
+ } catch {
2960
+ return worker = null;
2961
+ }
2962
+ }
2963
+ var abs = (u) => {
2964
+ try {
2965
+ return new URL(u, globalThis.location?.href).href;
2966
+ } catch {
2967
+ return u;
2968
+ }
2969
+ };
2970
+ function prepareInWorker(w, source, o) {
2971
+ const id = ++seq;
2972
+ 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 };
2973
+ const name = o.name ?? (o.text ? undefined : decodeURIComponent(source.split(/[?#]/)[0].split("/").pop() || "main.ldr"));
2974
+ let insts;
2975
+ pendingInsts.set(id, (v) => {
2976
+ insts = v;
2977
+ });
2978
+ const cull = new Promise((res, rej) => pendingCull.set(id, { res, rej }));
2979
+ cull.catch(() => {});
2980
+ return new Promise((res, rej) => {
2981
+ pending.set(id, { res, rej });
2982
+ w.postMessage({ id, source: o.text ? source : abs(source), opts: { ...opts, name } });
2983
+ }).then(async (d) => {
2984
+ const pack = decodePack(d.buffer);
2985
+ let done = false;
2986
+ cull.then(() => done = true, () => done = true);
2987
+ await warmPackGeometry(pack, () => done);
2988
+ const c = await cull;
2989
+ pendingInsts.delete(id);
2990
+ return { insts, pack, missing: d.missing, requests: d.requests, bytes: d.bytes, timings: { ...d.timings, cull: c.ms }, cull: c.cull };
2991
+ }, (e) => {
2992
+ pendingCull.delete(id);
2993
+ pendingInsts.delete(id);
2994
+ throw e;
2995
+ });
2996
+ }
2997
+ async function loadModel(source, o = {}) {
2998
+ const t0 = performance.now();
2999
+ const w = o.worker !== false && !o.fetch ? getWorker() : null;
3000
+ let prep, ranIn = "main";
3001
+ if (w) {
3002
+ try {
3003
+ prep = await prepareInWorker(w, source, o);
3004
+ ranIn = "worker";
3005
+ } catch (e) {
3006
+ if (!e?.workerFailed)
3007
+ throw e;
3008
+ prep = await prepareModel(source, o);
3009
+ }
3010
+ } else
3011
+ prep = await prepareModel(source, o);
3012
+ const t3 = performance.now();
3013
+ const obj = createLdrObject(prep.insts, prep.pack, prep.cull ? { ...o, precomputedCull: prep.cull } : o);
3014
+ for (const m of prep.missing)
2257
3015
  if (!obj.stats.missing.includes(m))
2258
3016
  obj.stats.missing.push(m);
2259
3017
  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 } });
3018
+ return Object.assign(obj, {
3019
+ pack: prep.pack,
3020
+ instances: prep.insts,
3021
+ requests: prep.requests,
3022
+ bytes: prep.bytes,
3023
+ ranIn,
3024
+ timings: { ...prep.timings, parts: t3 - t0 - prep.timings.fetchModel - prep.timings.parse, build: t4 - t3, total: t4 - t0 }
3025
+ });
2261
3026
  }
2262
- // ../../../../../../../tmp/ldr-build-pIke9r/src/node/library.ts
3027
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/node/library.ts
2263
3028
  import { existsSync, readFileSync } from "fs";
2264
3029
  import { join } from "path";
2265
3030
  var xf = (m, x, y, z) => [m[3] * x + m[4] * y + m[5] * z + m[0], m[6] * x + m[7] * y + m[8] * z + m[1], m[9] * x + m[10] * y + m[11] * z + m[2]];
2266
3031
  var det = (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]);
3032
+ var IDENTITY12 = [0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1];
3033
+ function isPlainAlias(f, target) {
3034
+ if (STUB_OVERRIDES[norm(f.name)] === target)
3035
+ return true;
3036
+ const refs = f.cmds.filter((c) => c.t === 1);
3037
+ return refs.length <= 1 && refs.every((c) => norm(c.file) === target && c.m.every((v, k) => Math.abs(v - IDENTITY12[k]) < 0.000001));
3038
+ }
2267
3039
 
2268
3040
  class Library {
2269
3041
  root;
@@ -2297,7 +3069,7 @@ class Library {
2297
3069
  if (!hit)
2298
3070
  return null;
2299
3071
  const file = hit.doc.files.get(hit.doc.main);
2300
- if (file?.movedTo && file.movedTo !== name) {
3072
+ if (file?.movedTo && file.movedTo !== name && isPlainAlias(file, file.movedTo)) {
2301
3073
  const target = this.where(file.movedTo, seen);
2302
3074
  if (target)
2303
3075
  return { ...target, aliasOf: name };
@@ -2511,11 +3283,11 @@ class Library {
2511
3283
  return insts;
2512
3284
  }
2513
3285
  }
2514
- // ../../../../../../../tmp/ldr-build-pIke9r/src/node/build-pack.ts
3286
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/node/build-pack.ts
2515
3287
  import fs3 from "node:fs";
2516
3288
  import path3 from "node:path";
2517
3289
 
2518
- // ../../../../../../../tmp/ldr-build-pIke9r/src/node/resolver.ts
3290
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/node/resolver.ts
2519
3291
  import fs from "node:fs";
2520
3292
  import path from "node:path";
2521
3293
  var TOP_STUD_RE = /^(stud|studa|stud2|stud2a|stud6|stud6a|stud10|stud15|stud2s|stud2s2|stud-logo\d*|stud2-logo\d*)\.dat$/i;
@@ -2587,7 +3359,7 @@ class Library2 {
2587
3359
  return key;
2588
3360
  }
2589
3361
  resolve(ref) {
2590
- const n = norm2(ref);
3362
+ const n0 = norm2(ref), n = STUB_OVERRIDES[n0] ?? n0;
2591
3363
  if (this.virtual.size && this.virtual.has(n))
2592
3364
  return "mpd/" + n;
2593
3365
  for (const pre of ["parts/", "p/", "models/"])
@@ -2787,11 +3559,11 @@ function collectDeps(lib, refs) {
2787
3559
  return out;
2788
3560
  }
2789
3561
 
2790
- // ../../../../../../../tmp/ldr-build-pIke9r/src/node/compile.ts
3562
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/node/compile.ts
2791
3563
  import fs2 from "node:fs";
2792
3564
  import path2 from "node:path";
2793
3565
 
2794
- // ../../../../../../../tmp/ldr-build-pIke9r/src/node/lod.ts
3566
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/node/lod.ts
2795
3567
  import { MeshoptSimplifier, MeshoptEncoder } from "meshoptimizer";
2796
3568
  await Promise.all([MeshoptSimplifier.ready, MeshoptEncoder.ready]);
2797
3569
  function reorderMesh(P, N, C, I) {
@@ -2814,8 +3586,10 @@ function reorderMesh(P, N, C, I) {
2814
3586
  }
2815
3587
  return { P: P2, N: N2, C: C2, I: idx };
2816
3588
  }
2817
- var TARGETS = [0.25, 0.08];
3589
+ var TARGETS = [0.25, 0.08, 0.025];
2818
3590
  var MIN_TRIS = 64;
3591
+ var MIN_BOX_TRIS = 24;
3592
+ var COVERAGE_WEIGHT = Number(process.env.LDR_LOD_COVERAGE ?? 0.5);
2819
3593
  function flatMesh(tris) {
2820
3594
  const map = new Map;
2821
3595
  const P = [], N = [], C = [], I = [];
@@ -2845,9 +3619,62 @@ function flatMesh(tris) {
2845
3619
  }
2846
3620
  return { P: new Float32Array(P), N: new Float32Array(N), C: new Float32Array(C), I: new Uint32Array(I) };
2847
3621
  }
3622
+ var G = 64;
3623
+ function silhouettes(P, I, box) {
3624
+ const masks = [0, 1, 2].map(() => new Uint8Array(G * G));
3625
+ for (let ax = 0;ax < 3; ax++) {
3626
+ const u = (ax + 1) % 3, v = (ax + 2) % 3;
3627
+ const m = masks[ax];
3628
+ const su = (box.hi[u] - box.lo[u]) / G || 1, sv = (box.hi[v] - box.lo[v]) / G || 1;
3629
+ for (let t = 0;t < I.length; t += 3) {
3630
+ const p = [I[t], I[t + 1], I[t + 2]].map((k) => [(P[k * 3 + u] - box.lo[u]) / su, (P[k * 3 + v] - box.lo[v]) / sv]);
3631
+ const area = (p[1][0] - p[0][0]) * (p[2][1] - p[0][1]) - (p[2][0] - p[0][0]) * (p[1][1] - p[0][1]);
3632
+ if (Math.abs(area) < 0.000000000001)
3633
+ continue;
3634
+ const x0 = Math.max(0, Math.floor(Math.min(p[0][0], p[1][0], p[2][0]))), x1 = Math.min(G - 1, Math.ceil(Math.max(p[0][0], p[1][0], p[2][0])));
3635
+ const y0 = Math.max(0, Math.floor(Math.min(p[0][1], p[1][1], p[2][1]))), y1 = Math.min(G - 1, Math.ceil(Math.max(p[0][1], p[1][1], p[2][1])));
3636
+ for (let y = y0;y <= y1; y++)
3637
+ for (let x = x0;x <= x1; x++) {
3638
+ if (m[y * G + x])
3639
+ continue;
3640
+ const cx = x + 0.5, cy = y + 0.5;
3641
+ let inside = true;
3642
+ for (let e = 0;e < 3 && inside; e++) {
3643
+ const a0 = p[e], a1 = p[(e + 1) % 3];
3644
+ const w = (a1[0] - a0[0]) * (cy - a0[1]) - (cx - a0[0]) * (a1[1] - a0[1]);
3645
+ if (w * area < 0)
3646
+ inside = false;
3647
+ }
3648
+ if (inside)
3649
+ m[y * G + x] = 1;
3650
+ }
3651
+ }
3652
+ }
3653
+ return masks;
3654
+ }
3655
+ function silhouetteDiff(a, b) {
3656
+ let worst = 0;
3657
+ for (let ax = 0;ax < 3; ax++) {
3658
+ let d = 0;
3659
+ for (let i = 0;i < G * G; i++)
3660
+ d += a[ax][i] ^ b[ax][i];
3661
+ worst = Math.max(worst, d / (G * G));
3662
+ }
3663
+ return worst;
3664
+ }
3665
+ function boxMesh(box, col) {
3666
+ const [x0, y0, z0] = box.lo, [x1, y1, z1] = box.hi;
3667
+ const c = [[x0, y0, z0], [x1, y0, z0], [x1, y1, z0], [x0, y1, z0], [x0, y0, z1], [x1, y0, z1], [x1, y1, z1], [x0, y1, z1]];
3668
+ const quads = [[0, 3, 2, 1], [4, 5, 6, 7], [0, 1, 5, 4], [3, 7, 6, 2], [0, 4, 7, 3], [1, 2, 6, 5]];
3669
+ const p = new Float32Array(c.flat());
3670
+ const idx = [];
3671
+ for (const q of quads)
3672
+ idx.push(q[0], q[1], q[2], q[0], q[2], q[3]);
3673
+ return flatMesh([{ p, i: Uint32Array.from(idx), col }]);
3674
+ }
2848
3675
  function lodChain(P, C, I) {
2849
3676
  const nTris = I.length / 3;
2850
- if (nTris < MIN_TRIS)
3677
+ if (nTris < MIN_BOX_TRIS)
2851
3678
  return [];
2852
3679
  const groups = new Map;
2853
3680
  for (let t = 0;t < I.length; t += 3) {
@@ -2878,27 +3705,57 @@ function lodChain(P, C, I) {
2878
3705
  });
2879
3706
  const out = [];
2880
3707
  let prevTris = nTris;
2881
- for (let li = 0;li < TARGETS.length; li++) {
2882
- let err = 0;
2883
- const parts = [];
2884
- for (const g of welded) {
2885
- const target = Math.max(3, Math.floor(g.i.length * TARGETS[li] / 3) * 3);
2886
- const [idx, e] = MeshoptSimplifier.simplify(g.i, g.p, 3, target, 1e9, li ? ["ErrorAbsolute", "Prune"] : ["ErrorAbsolute"]);
2887
- err = Math.max(err, e);
2888
- if (idx.length)
2889
- parts.push({ p: g.p, i: idx, col: g.col });
2890
- }
2891
- const m = flatMesh(parts);
2892
- const t = m.I.length / 3;
2893
- if (t > prevTris * 0.7 || !t)
2894
- continue;
2895
- out.push({ ...m, err: +Math.max(err, 0.001).toFixed(3) });
2896
- prevTris = t;
3708
+ const lo = [Infinity, Infinity, Infinity], hi = [-Infinity, -Infinity, -Infinity];
3709
+ for (let v = 0;v < P.length; v += 3)
3710
+ for (let k = 0;k < 3; k++) {
3711
+ lo[k] = Math.min(lo[k], P[v + k]);
3712
+ hi[k] = Math.max(hi[k], P[v + k]);
3713
+ }
3714
+ const box = { lo, hi };
3715
+ const diag = Math.hypot(hi[0] - lo[0], hi[1] - lo[1], hi[2] - lo[2]);
3716
+ const S0 = silhouettes(P, I, box);
3717
+ const coverageErr = (m) => COVERAGE_WEIGHT * silhouetteDiff(S0, silhouettes(m.P, m.I, box)) * diag;
3718
+ for (let li = 0;li < (nTris >= MIN_TRIS ? TARGETS.length : 0); li++) {
3719
+ let best = null;
3720
+ for (const sloppy of [false, true]) {
3721
+ let err = 0;
3722
+ const parts = [];
3723
+ for (const g of welded) {
3724
+ const target = Math.max(3, Math.floor(g.i.length * TARGETS[li] / 3) * 3);
3725
+ const [idx, e] = sloppy ? MeshoptSimplifier.simplifySloppy(g.i, g.p, 3, null, target, 1e9) : MeshoptSimplifier.simplify(g.i, g.p, 3, target, 1e9, li ? ["ErrorAbsolute", "Prune"] : ["ErrorAbsolute"]);
3726
+ err = Math.max(err, sloppy ? e * MeshoptSimplifier.getScale(g.p, 3) : e);
3727
+ if (idx.length)
3728
+ parts.push({ p: g.p, i: idx, col: g.col });
3729
+ }
3730
+ const m = flatMesh(parts);
3731
+ const t = m.I.length / 3;
3732
+ if (!t || t > prevTris * 0.7)
3733
+ continue;
3734
+ const e = +Math.max(err, coverageErr(m), 0.001).toFixed(3);
3735
+ if (!best || e < best.err)
3736
+ best = { ...m, err: e };
3737
+ }
3738
+ if (best) {
3739
+ out.push(best);
3740
+ prevTris = best.I.length / 3;
3741
+ }
3742
+ }
3743
+ if (prevTris * 0.7 >= 12) {
3744
+ const main = welded.reduce((a, g) => g.i.length > a.i.length ? g : a);
3745
+ const m = boxMesh(box, main.col);
3746
+ let inner = 0;
3747
+ for (let v = 0;v < P.length; v += 3) {
3748
+ let d = Infinity;
3749
+ for (let k = 0;k < 3; k++)
3750
+ d = Math.min(d, P[v + k] - lo[k], hi[k] - P[v + k]);
3751
+ inner = Math.max(inner, d);
3752
+ }
3753
+ out.push({ ...m, err: +Math.max(inner, coverageErr(m) / COVERAGE_WEIGHT, out.length ? out[out.length - 1].err : 0, 0.001).toFixed(3) });
2897
3754
  }
2898
3755
  return out;
2899
3756
  }
2900
3757
 
2901
- // ../../../../../../../tmp/ldr-build-pIke9r/src/node/compile.ts
3758
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/node/compile.ts
2902
3759
  function loadColors(root) {
2903
3760
  const map = new Map;
2904
3761
  for (const l of fs2.readFileSync(path2.join(root, "LDConfig.ldr"), "latin1").split(/\r?\n/)) {
@@ -3481,7 +4338,7 @@ function encodePack(parts, studKinds, weld, extra, options = {}) {
3481
4338
  return Buffer.concat([head, ...chunks.map((c) => new Uint8Array(c.buffer, c.byteOffset, c.byteLength))]);
3482
4339
  }
3483
4340
 
3484
- // ../../../../../../../tmp/ldr-build-pIke9r/src/node/build-pack.ts
4341
+ // ../../../../../../../tmp/ldr-build-zzND7A/src/node/build-pack.ts
3485
4342
  function buildPack(o) {
3486
4343
  const lib = new Library2(o.ldrawRoot);
3487
4344
  const refs = new Map;
@@ -3544,10 +4401,13 @@ function buildPack(o) {
3544
4401
  return { data: encodePack(parts, kinds, comp.opts.weld, extra, { texture, lod: o.lod !== false, reorder: !!o.reorder }), parts: parts.size, studKinds: kinds.size, missing: [...missing], ...warnings.length ? { warnings } : {} };
3545
4402
  }
3546
4403
  export {
4404
+ CALLOUT_END,
3547
4405
  Compiler,
3548
4406
  DEFAULT_PARTS_CDN,
3549
4407
  I as IDENTITY,
3550
4408
  Library,
4409
+ MIN_VIS,
4410
+ REORIENT,
3551
4411
  Library2 as ResolverLibrary,
3552
4412
  buildLdrScene,
3553
4413
  buildPack,
@@ -3569,8 +4429,10 @@ export {
3569
4429
  flatten2 as flattenWithLibrary,
3570
4430
  forEachStud,
3571
4431
  hash32,
4432
+ instanceBoxes,
3572
4433
  invert,
3573
4434
  isDirectColor,
4435
+ isolateMask,
3574
4436
  loadColors,
3575
4437
  loadModel,
3576
4438
  loadPack,
@@ -3589,15 +4451,22 @@ export {
3589
4451
  parseLDConfig,
3590
4452
  parseModel,
3591
4453
  parseTexMap,
4454
+ planStepViews,
4455
+ precomputeCull,
4456
+ prepareModel,
3592
4457
  resolveTexture,
3593
4458
  rotStepMatrix,
4459
+ sceneInstances,
3594
4460
  sequenceSteps,
3595
4461
  smoothNormals,
3596
4462
  splitModel,
4463
+ stepKey,
3597
4464
  stepViewMatrix,
3598
4465
  texWrapper,
3599
4466
  texmapTriangleUV,
3600
4467
  texmapUV,
3601
4468
  transformTexMap,
4469
+ viewDir,
4470
+ warmPackGeometry,
3602
4471
  writePack
3603
4472
  };