ldr 0.5.1 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +12 -10
- package/dist/cdn.d.ts +8 -41
- package/dist/cli.js +157 -30
- package/dist/cull.d.ts +68 -0
- package/dist/index.d.ts +4 -3
- package/dist/index.js +844 -500
- package/dist/load-worker.d.ts +1 -0
- package/dist/load-worker.gen.d.ts +2 -0
- package/dist/node/index.js +970 -541
- package/dist/pack-io.d.ts +9 -0
- package/dist/parts-cdn.d.ts +64 -0
- package/dist/render.d.ts +23 -43
- package/dist/scene.d.ts +10 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1
|
+
// ../../../../../../../tmp/ldr-build-NB5kkP/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(
|
|
187
|
+
for (const raw of src.split(`
|
|
188
|
+
`)) {
|
|
158
189
|
const line = raw.trim();
|
|
159
190
|
if (!line)
|
|
160
191
|
continue;
|
|
@@ -205,6 +236,17 @@ function parse(src, name = "main.ldr", popts = {}) {
|
|
|
205
236
|
continue;
|
|
206
237
|
}
|
|
207
238
|
}
|
|
239
|
+
if (line.charCodeAt(0) === 49 && (line.charCodeAt(1) === 32 || line.charCodeAt(1) === 9) && !dataCur && !skip) {
|
|
240
|
+
const g = type1Fast(line);
|
|
241
|
+
if (g) {
|
|
242
|
+
if (!cur)
|
|
243
|
+
start(name);
|
|
244
|
+
annotate(g, false);
|
|
245
|
+
cur.cmds.push(g);
|
|
246
|
+
inHeader = false;
|
|
247
|
+
continue;
|
|
248
|
+
}
|
|
249
|
+
}
|
|
208
250
|
const tk = line.split(/\s+/);
|
|
209
251
|
const t = +tk[0];
|
|
210
252
|
if (t === 0) {
|
|
@@ -647,7 +689,7 @@ function fileStepViews(f) {
|
|
|
647
689
|
viewMemo.set(f, out);
|
|
648
690
|
return out;
|
|
649
691
|
}
|
|
650
|
-
// ../../../../../../../tmp/ldr-build-
|
|
692
|
+
// ../../../../../../../tmp/ldr-build-NB5kkP/src/model.ts
|
|
651
693
|
function flatten(doc, opts = {}) {
|
|
652
694
|
const out = [];
|
|
653
695
|
const maxDepth = opts.maxDepth ?? 64;
|
|
@@ -743,7 +785,7 @@ function flatten(doc, opts = {}) {
|
|
|
743
785
|
return out;
|
|
744
786
|
}
|
|
745
787
|
function parseModel(text, name = "main.ldr", opts) {
|
|
746
|
-
return flatten(parse(text, name), opts);
|
|
788
|
+
return flatten(parse(text, name, { geometryText: true }), opts);
|
|
747
789
|
}
|
|
748
790
|
function sequenceSteps(insts) {
|
|
749
791
|
const key = (i) => i.steps.map((x) => String(x).padStart(6, "0")).join(".");
|
|
@@ -768,28 +810,19 @@ function parseLDConfig(text) {
|
|
|
768
810
|
}
|
|
769
811
|
return out;
|
|
770
812
|
}
|
|
771
|
-
// ../../../../../../../tmp/ldr-build-
|
|
813
|
+
// ../../../../../../../tmp/ldr-build-NB5kkP/src/render.ts
|
|
772
814
|
import * as THREE from "three";
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
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);
|
|
815
|
+
|
|
816
|
+
// ../../../../../../../tmp/ldr-build-NB5kkP/src/pack-io.ts
|
|
817
|
+
import { decompress } from "fzstd";
|
|
818
|
+
async function decompressPack(data) {
|
|
819
|
+
const u = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
820
|
+
const own = (o) => o.buffer.slice(o.byteOffset, o.byteOffset + o.byteLength);
|
|
821
|
+
if (u[0] === 40 && u[1] === 181 && u[2] === 47 && u[3] === 253)
|
|
822
|
+
return own(decompress(u));
|
|
823
|
+
if (u[0] === 31 && u[1] === 139)
|
|
824
|
+
return new Response(new Blob([u]).stream().pipeThrough(new DecompressionStream("gzip"))).arrayBuffer();
|
|
825
|
+
return own(u);
|
|
793
826
|
}
|
|
794
827
|
function decodePack(buf) {
|
|
795
828
|
const hl = new DataView(buf).getUint32(0, true);
|
|
@@ -798,6 +831,331 @@ function decodePack(buf) {
|
|
|
798
831
|
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
832
|
return { header, arr, bytes: buf.byteLength, buffer: buf };
|
|
800
833
|
}
|
|
834
|
+
|
|
835
|
+
// ../../../../../../../tmp/ldr-build-NB5kkP/src/cull.ts
|
|
836
|
+
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;
|
|
837
|
+
var prepCache = new WeakMap;
|
|
838
|
+
function prepPart(H, part) {
|
|
839
|
+
let c = prepCache.get(H);
|
|
840
|
+
if (!c)
|
|
841
|
+
prepCache.set(H, c = new Map);
|
|
842
|
+
let r = c.get(part);
|
|
843
|
+
if (r !== undefined)
|
|
844
|
+
return r;
|
|
845
|
+
const p = H.parts[part];
|
|
846
|
+
if (!p) {
|
|
847
|
+
c.set(part, null);
|
|
848
|
+
return null;
|
|
849
|
+
}
|
|
850
|
+
const n = p.studs.length;
|
|
851
|
+
const studM = new Float64Array(n * 12);
|
|
852
|
+
const kind = [], color = [];
|
|
853
|
+
p.studs.forEach((s, i) => {
|
|
854
|
+
kind.push(s[0]);
|
|
855
|
+
color.push(s[1]);
|
|
856
|
+
for (let k = 0;k < 12; k++)
|
|
857
|
+
studM[i * 12 + k] = s[2 + k];
|
|
858
|
+
});
|
|
859
|
+
let mask = null, nx = 0, nz = 0;
|
|
860
|
+
if (p.mask) {
|
|
861
|
+
nx = p.mask[0];
|
|
862
|
+
nz = p.mask[1];
|
|
863
|
+
const bits = p.mask[2];
|
|
864
|
+
mask = new Uint8Array(bits.length);
|
|
865
|
+
for (let i = 0;i < bits.length; i++)
|
|
866
|
+
mask[i] = bits.charCodeAt(i) === 49 ? 1 : 0;
|
|
867
|
+
}
|
|
868
|
+
c.set(part, r = { nStuds: n, studM, kind, color, mask, nx, nz });
|
|
869
|
+
return r;
|
|
870
|
+
}
|
|
871
|
+
function mul12To(a, b, bo, w, ao = 0) {
|
|
872
|
+
const b0 = b[bo], b1 = b[bo + 1], b2 = b[bo + 2];
|
|
873
|
+
w[0] = a[ao] + a[ao + 3] * b0 + a[ao + 4] * b1 + a[ao + 5] * b2;
|
|
874
|
+
w[1] = a[ao + 1] + a[ao + 6] * b0 + a[ao + 7] * b1 + a[ao + 8] * b2;
|
|
875
|
+
w[2] = a[ao + 2] + a[ao + 9] * b0 + a[ao + 10] * b1 + a[ao + 11] * b2;
|
|
876
|
+
for (let i = 0;i < 3; i++)
|
|
877
|
+
for (let j = 0;j < 3; j++)
|
|
878
|
+
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];
|
|
879
|
+
}
|
|
880
|
+
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]);
|
|
881
|
+
var BIG = 1073741824;
|
|
882
|
+
|
|
883
|
+
class Int3Table {
|
|
884
|
+
a;
|
|
885
|
+
b;
|
|
886
|
+
c;
|
|
887
|
+
vals;
|
|
888
|
+
used;
|
|
889
|
+
mask;
|
|
890
|
+
size = 0;
|
|
891
|
+
constructor(cap = 1024) {
|
|
892
|
+
let n = 1024;
|
|
893
|
+
while (n < cap * 2)
|
|
894
|
+
n *= 2;
|
|
895
|
+
this.a = new Int32Array(n);
|
|
896
|
+
this.b = new Int32Array(n);
|
|
897
|
+
this.c = new Int32Array(n);
|
|
898
|
+
this.vals = new Int32Array(n);
|
|
899
|
+
this.used = new Uint8Array(n);
|
|
900
|
+
this.mask = n - 1;
|
|
901
|
+
}
|
|
902
|
+
slot(x, y, z) {
|
|
903
|
+
let h = Math.imul(x, 2654435761) ^ Math.imul(y, 2246822507) ^ Math.imul(z, 3266489909);
|
|
904
|
+
h ^= h >>> 15;
|
|
905
|
+
h = Math.imul(h, 739982445);
|
|
906
|
+
h ^= h >>> 12;
|
|
907
|
+
return h & this.mask;
|
|
908
|
+
}
|
|
909
|
+
get(x, y, z) {
|
|
910
|
+
let i = this.slot(x, y, z);
|
|
911
|
+
const U = this.used, A = this.a, B = this.b, C = this.c;
|
|
912
|
+
for (;; ) {
|
|
913
|
+
if (!U[i])
|
|
914
|
+
return -1;
|
|
915
|
+
if (A[i] === x && B[i] === y && C[i] === z)
|
|
916
|
+
return this.vals[i];
|
|
917
|
+
i = i + 1 & this.mask;
|
|
918
|
+
}
|
|
919
|
+
}
|
|
920
|
+
put(x, y, z, v) {
|
|
921
|
+
if ((this.size + 1) * 2 > this.used.length)
|
|
922
|
+
this.grow();
|
|
923
|
+
let i = this.slot(x, y, z);
|
|
924
|
+
const U = this.used, A = this.a, B = this.b, C = this.c;
|
|
925
|
+
for (;; ) {
|
|
926
|
+
if (!U[i]) {
|
|
927
|
+
U[i] = 1;
|
|
928
|
+
A[i] = x;
|
|
929
|
+
B[i] = y;
|
|
930
|
+
C[i] = z;
|
|
931
|
+
this.vals[i] = v;
|
|
932
|
+
this.size++;
|
|
933
|
+
return -1;
|
|
934
|
+
}
|
|
935
|
+
if (A[i] === x && B[i] === y && C[i] === z) {
|
|
936
|
+
const o = this.vals[i];
|
|
937
|
+
this.vals[i] = v;
|
|
938
|
+
return o;
|
|
939
|
+
}
|
|
940
|
+
i = i + 1 & this.mask;
|
|
941
|
+
}
|
|
942
|
+
}
|
|
943
|
+
grow() {
|
|
944
|
+
const { a, b, c, vals, used } = this;
|
|
945
|
+
const n = used.length * 2;
|
|
946
|
+
this.a = new Int32Array(n);
|
|
947
|
+
this.b = new Int32Array(n);
|
|
948
|
+
this.c = new Int32Array(n);
|
|
949
|
+
this.vals = new Int32Array(n);
|
|
950
|
+
this.used = new Uint8Array(n);
|
|
951
|
+
this.mask = n - 1;
|
|
952
|
+
this.size = 0;
|
|
953
|
+
for (let i = 0;i < used.length; i++)
|
|
954
|
+
if (used[i])
|
|
955
|
+
this.put(a[i], b[i], c[i], vals[i]);
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
var inRange = (x, y, z) => x > -BIG && x < BIG && y > -BIG && y < BIG && z > -BIG && z < BIG;
|
|
959
|
+
var STEP_NEVER = 2147483647;
|
|
960
|
+
function forEachStud(insts, H, fn) {
|
|
961
|
+
const w = new Float64Array(12);
|
|
962
|
+
let j = 0;
|
|
963
|
+
for (let idx = 0;idx < insts.length; idx++) {
|
|
964
|
+
const it = insts[idx];
|
|
965
|
+
const pp = prepPart(H, it.part);
|
|
966
|
+
if (!pp)
|
|
967
|
+
continue;
|
|
968
|
+
for (let s = 0;s < pp.nStuds; s++) {
|
|
969
|
+
mul12To(it.m, pp.studM, s * 12, w);
|
|
970
|
+
const c = pp.color[s];
|
|
971
|
+
fn(j++, idx, w, pp.kind[s], c === "16" ? it.color : c, s);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
}
|
|
975
|
+
function cullCore(insts, H, steps) {
|
|
976
|
+
const CELL = 40;
|
|
977
|
+
const rx0 = [], rx1 = [], rz0 = [], rz1 = [], rInst = [], rPrep = [], rBx = [], rBz = [];
|
|
978
|
+
const cells = new Int3Table(insts.length * 2);
|
|
979
|
+
const nextE = [], rectE = [];
|
|
980
|
+
for (let idx = 0;idx < insts.length; idx++) {
|
|
981
|
+
const it = insts[idx];
|
|
982
|
+
const m = it.m;
|
|
983
|
+
const p = H.parts[it.part];
|
|
984
|
+
if (!p || !p.mask || !upright(m))
|
|
985
|
+
continue;
|
|
986
|
+
const b = p.bbox;
|
|
987
|
+
let x0 = Infinity, x1 = -Infinity, z0 = Infinity, z1 = -Infinity;
|
|
988
|
+
for (let cxi = 0;cxi < 2; cxi++)
|
|
989
|
+
for (let czi = 0;czi < 2; czi++) {
|
|
990
|
+
const x = cxi ? b[3] : b[0], z = czi ? b[5] : b[2];
|
|
991
|
+
const wx = m[0] + m[3] * x + m[5] * z, wz = m[2] + m[9] * x + m[11] * z;
|
|
992
|
+
if (wx < x0)
|
|
993
|
+
x0 = wx;
|
|
994
|
+
if (wx > x1)
|
|
995
|
+
x1 = wx;
|
|
996
|
+
if (wz < z0)
|
|
997
|
+
z0 = wz;
|
|
998
|
+
if (wz > z1)
|
|
999
|
+
z1 = wz;
|
|
1000
|
+
}
|
|
1001
|
+
const ri = rInst.length;
|
|
1002
|
+
rx0.push(x0);
|
|
1003
|
+
rx1.push(x1);
|
|
1004
|
+
rz0.push(z0);
|
|
1005
|
+
rz1.push(z1);
|
|
1006
|
+
rInst.push(idx);
|
|
1007
|
+
rPrep.push(prepPart(H, it.part));
|
|
1008
|
+
rBx.push(b[0]);
|
|
1009
|
+
rBz.push(b[2]);
|
|
1010
|
+
const lv2 = Math.round((m[1] + b[4]) * 2);
|
|
1011
|
+
for (let cx = Math.floor(x0 / CELL);cx <= Math.floor(x1 / CELL); cx++)
|
|
1012
|
+
for (let cz = Math.floor(z0 / CELL);cz <= Math.floor(z1 / CELL); cz++) {
|
|
1013
|
+
if (!inRange(lv2, cx, cz))
|
|
1014
|
+
continue;
|
|
1015
|
+
const e = rectE.length;
|
|
1016
|
+
rectE.push(ri);
|
|
1017
|
+
nextE.push(cells.put(lv2, cx, cz, e));
|
|
1018
|
+
}
|
|
1019
|
+
}
|
|
1020
|
+
const SX = [0, 5, -5, 5, -5], SZ = [0, 5, 5, -5, -5];
|
|
1021
|
+
let kl = NaN, kx = NaN, kz = NaN, ke = -1;
|
|
1022
|
+
const coverStep = (x, y, z, self) => {
|
|
1023
|
+
const l2 = Math.round(y * 2), gx = Math.floor(x / CELL), gz = Math.floor(z / CELL);
|
|
1024
|
+
if (!inRange(l2, gx, gz))
|
|
1025
|
+
return STEP_NEVER;
|
|
1026
|
+
let best = STEP_NEVER;
|
|
1027
|
+
if (l2 !== kl || gx !== kx || gz !== kz) {
|
|
1028
|
+
kl = l2;
|
|
1029
|
+
kx = gx;
|
|
1030
|
+
kz = gz;
|
|
1031
|
+
ke = cells.get(l2, gx, gz);
|
|
1032
|
+
}
|
|
1033
|
+
for (let e = ke;e >= 0; e = nextE[e]) {
|
|
1034
|
+
const ri = rectE[e];
|
|
1035
|
+
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))
|
|
1036
|
+
continue;
|
|
1037
|
+
const m = insts[rInst[ri]].m;
|
|
1038
|
+
const pp = rPrep[ri];
|
|
1039
|
+
const bx = rBx[ri], bz = rBz[ri];
|
|
1040
|
+
const dx = x - m[0], dy = y - m[1], dz = z - m[2];
|
|
1041
|
+
const lx = m[3] * dx + m[6] * dy + m[9] * dz, lz = m[5] * dx + m[8] * dy + m[11] * dz;
|
|
1042
|
+
const { nx, nz, mask: bits } = pp;
|
|
1043
|
+
let ok = true;
|
|
1044
|
+
for (let s = 0;s < 5; s++) {
|
|
1045
|
+
const ca = Math.floor((lx + SX[s] - bx) / 20), cb = Math.floor((lz + SZ[s] - bz) / 20);
|
|
1046
|
+
if (ca < 0 || cb < 0 || ca >= nx || cb >= nz || bits[ca * nz + cb] !== 1) {
|
|
1047
|
+
ok = false;
|
|
1048
|
+
break;
|
|
1049
|
+
}
|
|
1050
|
+
}
|
|
1051
|
+
if (ok) {
|
|
1052
|
+
if (!steps)
|
|
1053
|
+
return 0;
|
|
1054
|
+
const st = steps[rInst[ri]];
|
|
1055
|
+
if (st < best)
|
|
1056
|
+
best = st;
|
|
1057
|
+
}
|
|
1058
|
+
}
|
|
1059
|
+
return best;
|
|
1060
|
+
};
|
|
1061
|
+
let nStuds = 0;
|
|
1062
|
+
for (const it of insts) {
|
|
1063
|
+
const pp = prepPart(H, it.part);
|
|
1064
|
+
if (pp)
|
|
1065
|
+
nStuds += pp.nStuds;
|
|
1066
|
+
}
|
|
1067
|
+
const studHidden = new Uint8Array(nStuds), studUp = new Uint8Array(nStuds);
|
|
1068
|
+
const tops = new Int3Table(nStuds);
|
|
1069
|
+
let studsHidden = 0;
|
|
1070
|
+
const studHideStep = steps ? new Int32Array(nStuds).fill(STEP_NEVER) : undefined;
|
|
1071
|
+
for (let idx = 0, j = 0;idx < insts.length; idx++) {
|
|
1072
|
+
const it = insts[idx];
|
|
1073
|
+
const pp = prepPart(H, it.part);
|
|
1074
|
+
if (!pp)
|
|
1075
|
+
continue;
|
|
1076
|
+
const m = it.m, S = pp.studM;
|
|
1077
|
+
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];
|
|
1078
|
+
for (let s = 0;s < pp.nStuds; s++, j++) {
|
|
1079
|
+
const o = s * 12;
|
|
1080
|
+
const b4 = S[o + 4], b7 = S[o + 7], b10 = S[o + 10];
|
|
1081
|
+
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))
|
|
1082
|
+
continue;
|
|
1083
|
+
studUp[j] = 1;
|
|
1084
|
+
const b0 = S[o], b1 = S[o + 1], b2 = S[o + 2];
|
|
1085
|
+
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;
|
|
1086
|
+
const cs = coverStep(x, y, z, idx);
|
|
1087
|
+
if (cs !== STEP_NEVER) {
|
|
1088
|
+
studHidden[j] = 1;
|
|
1089
|
+
studsHidden++;
|
|
1090
|
+
if (studHideStep)
|
|
1091
|
+
studHideStep[j] = cs;
|
|
1092
|
+
}
|
|
1093
|
+
const rx = Math.round(x), ry = Math.round(y), rz = Math.round(z);
|
|
1094
|
+
if (!inRange(rx, ry, rz))
|
|
1095
|
+
continue;
|
|
1096
|
+
if (!steps) {
|
|
1097
|
+
tops.put(rx, ry, rz, 1);
|
|
1098
|
+
continue;
|
|
1099
|
+
}
|
|
1100
|
+
const st = steps[idx], t = tops.get(rx, ry, rz);
|
|
1101
|
+
if (t < 0 || st < t)
|
|
1102
|
+
tops.put(rx, ry, rz, st);
|
|
1103
|
+
}
|
|
1104
|
+
}
|
|
1105
|
+
const underHidden = new Uint8Array(insts.length);
|
|
1106
|
+
const underHideStep = steps ? new Int32Array(insts.length).fill(STEP_NEVER) : undefined;
|
|
1107
|
+
for (let idx = 0;idx < insts.length; idx++) {
|
|
1108
|
+
const it = insts[idx];
|
|
1109
|
+
const p = H.parts[it.part];
|
|
1110
|
+
if (!p || !p.under || !upright(it.m))
|
|
1111
|
+
continue;
|
|
1112
|
+
const b = p.bbox;
|
|
1113
|
+
const nx = Math.round((b[3] - b[0]) / 20), nz = Math.round((b[5] - b[2]) / 20);
|
|
1114
|
+
if (!nx || !nz || nx * nz > 4096)
|
|
1115
|
+
continue;
|
|
1116
|
+
const m = it.m;
|
|
1117
|
+
let all = true, at = 0;
|
|
1118
|
+
for (let a = 0;a < nx && all; a++)
|
|
1119
|
+
for (let c = 0;c < nz; c++) {
|
|
1120
|
+
const lx = b[0] + 10 + 20 * a, lz = b[2] + 10 + 20 * c;
|
|
1121
|
+
const x = m[0] + m[3] * lx + m[5] * lz, z = m[2] + m[9] * lx + m[11] * lz;
|
|
1122
|
+
const rx = Math.round(x), ry = Math.round(m[1] + b[4]), rz = Math.round(z);
|
|
1123
|
+
const t = inRange(rx, ry, rz) ? tops.get(rx, ry, rz) : -1;
|
|
1124
|
+
if (t < 0) {
|
|
1125
|
+
all = false;
|
|
1126
|
+
break;
|
|
1127
|
+
}
|
|
1128
|
+
if (t > at)
|
|
1129
|
+
at = t;
|
|
1130
|
+
}
|
|
1131
|
+
if (all) {
|
|
1132
|
+
underHidden[idx] = 1;
|
|
1133
|
+
if (underHideStep)
|
|
1134
|
+
underHideStep[idx] = at;
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
return { nStuds, studHidden, studUp, underHidden, studsHidden, studHideStep, underHideStep };
|
|
1138
|
+
}
|
|
1139
|
+
function sceneInstances(instances, H, useTex) {
|
|
1140
|
+
const pick = (i) => useTex && i.texPart && H.parts[i.texPart] ? i.texPart : i.part;
|
|
1141
|
+
const all = instances.map((i) => ({ part: pick(i), color: String(i.color), m: i.m, steps: i.steps }));
|
|
1142
|
+
const keys = all.map((i) => i.steps.map((x) => String(x).padStart(6, "0")).join("."));
|
|
1143
|
+
const uniq = [...new Set(keys)].sort();
|
|
1144
|
+
const rank = new Map(uniq.map((k, j) => [k, j]));
|
|
1145
|
+
return { all, stepOf: keys.map((k) => rank.get(k)), nSteps: uniq.length };
|
|
1146
|
+
}
|
|
1147
|
+
function precomputeCull(instances, H, useTex = true) {
|
|
1148
|
+
const s = sceneInstances(instances, H, useTex);
|
|
1149
|
+
return cullCore(s.all, H, s.nSteps > 1 ? s.stepOf : undefined);
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
// ../../../../../../../tmp/ldr-build-NB5kkP/src/render.ts
|
|
1153
|
+
async function loadPack(url) {
|
|
1154
|
+
const res = await fetch(url);
|
|
1155
|
+
if (!res.ok)
|
|
1156
|
+
throw new Error(`ldr: ${res.status} fetching ${url}`);
|
|
1157
|
+
return decodePack(await decompressPack(await res.arrayBuffer()));
|
|
1158
|
+
}
|
|
801
1159
|
var toI8 = (a) => {
|
|
802
1160
|
const o = new Int8Array(a.length);
|
|
803
1161
|
for (let i = 0;i < a.length; i++)
|
|
@@ -829,27 +1187,26 @@ function flatNormals(pos, idx) {
|
|
|
829
1187
|
return n;
|
|
830
1188
|
}
|
|
831
1189
|
var geomCache = new WeakMap;
|
|
832
|
-
function geom(b, arr
|
|
1190
|
+
function geom(b, arr) {
|
|
833
1191
|
if (!b)
|
|
834
1192
|
return null;
|
|
835
1193
|
let c = geomCache.get(arr);
|
|
836
1194
|
if (!c)
|
|
837
1195
|
geomCache.set(arr, c = new Map);
|
|
838
|
-
|
|
839
|
-
let g = c.get(ck);
|
|
1196
|
+
let g = c.get(b);
|
|
840
1197
|
if (g)
|
|
841
1198
|
return g;
|
|
842
1199
|
g = new THREE.BufferGeometry;
|
|
843
1200
|
g.setAttribute("position", new THREE.BufferAttribute(arr(b.pos), 3));
|
|
844
1201
|
const nrm = b.nrm ? arr(b.nrm) : flatNormals(arr(b.pos), arr(b.idx));
|
|
845
1202
|
const col = arr(b.col);
|
|
846
|
-
g.setAttribute("normal",
|
|
847
|
-
g.setAttribute("ldrColor",
|
|
1203
|
+
g.setAttribute("normal", new THREE.BufferAttribute(toI8(nrm), 3, true));
|
|
1204
|
+
g.setAttribute("ldrColor", new THREE.BufferAttribute(col instanceof Uint8Array ? col : toU8(col), 4, true));
|
|
848
1205
|
if (b.idx)
|
|
849
1206
|
g.setIndex(new THREE.BufferAttribute(arr(b.idx), 1));
|
|
850
1207
|
if (b.uv)
|
|
851
1208
|
g.setAttribute("ldrUV", new THREE.BufferAttribute(arr(b.uv), 2));
|
|
852
|
-
c.set(
|
|
1209
|
+
c.set(b, g);
|
|
853
1210
|
return g;
|
|
854
1211
|
}
|
|
855
1212
|
function makeMaterial(side) {
|
|
@@ -901,30 +1258,36 @@ function packTexture(pack, i) {
|
|
|
901
1258
|
}).catch(() => {});
|
|
902
1259
|
return { texture: t, ready };
|
|
903
1260
|
}
|
|
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
1261
|
var sharedLineMat = () => new THREE.ShaderMaterial({
|
|
910
1262
|
vertexShader: `attribute mat4 instanceMatrix; void main(){ gl_Position = projectionMatrix * modelViewMatrix * instanceMatrix * vec4(position,1.0); }`,
|
|
911
1263
|
fragmentShader: `void main(){ gl_FragColor = vec4(0.13,0.13,0.13,1.0); }`
|
|
912
1264
|
});
|
|
913
|
-
var weldLines = (pos) => {
|
|
1265
|
+
var weldLines = (pos, byLength = false) => {
|
|
914
1266
|
const map = new Map;
|
|
915
1267
|
const P = [];
|
|
916
1268
|
const I = [];
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
map.set(k, j);
|
|
923
|
-
P.push(pos[i], pos[i + 1], pos[i + 2]);
|
|
924
|
-
}
|
|
925
|
-
I.push(j);
|
|
1269
|
+
const n = Math.floor(pos.length / 6);
|
|
1270
|
+
const len = new Float32Array(n);
|
|
1271
|
+
for (let s = 0;s < n; s++) {
|
|
1272
|
+
const o = s * 6;
|
|
1273
|
+
len[s] = Math.hypot(pos[o + 3] - pos[o], pos[o + 4] - pos[o + 1], pos[o + 5] - pos[o + 2]);
|
|
926
1274
|
}
|
|
927
|
-
|
|
1275
|
+
const order = Array.from({ length: n }, (_, s) => s);
|
|
1276
|
+
if (byLength)
|
|
1277
|
+
order.sort((a, b) => len[b] - len[a]);
|
|
1278
|
+
for (const sg of order)
|
|
1279
|
+
for (let e = 0;e < 2; e++) {
|
|
1280
|
+
const i = sg * 6 + e * 3;
|
|
1281
|
+
const k = pos[i].toFixed(2) + "," + pos[i + 1].toFixed(2) + "," + pos[i + 2].toFixed(2);
|
|
1282
|
+
let j = map.get(k);
|
|
1283
|
+
if (j === undefined) {
|
|
1284
|
+
j = P.length / 3;
|
|
1285
|
+
map.set(k, j);
|
|
1286
|
+
P.push(pos[i], pos[i + 1], pos[i + 2]);
|
|
1287
|
+
}
|
|
1288
|
+
I.push(j);
|
|
1289
|
+
}
|
|
1290
|
+
return { P: new Float32Array(P), I: P.length / 3 < 65536 ? new Uint16Array(I) : new Uint32Array(I), lens: Float32Array.from(order, (sg) => len[sg]) };
|
|
928
1291
|
};
|
|
929
1292
|
function createInstancedEdges(pos, im, material = sharedLineMat()) {
|
|
930
1293
|
return sharedLines(pos, im, material);
|
|
@@ -1001,369 +1364,142 @@ function condBuffers(cond) {
|
|
|
1001
1364
|
const n = Math.floor(cond.length / 12);
|
|
1002
1365
|
const buf = new Float32Array(n * 24), side = new Float32Array(n * 2);
|
|
1003
1366
|
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;
|
|
1008
|
-
}
|
|
1009
|
-
side[l * 2 + 1] = 1;
|
|
1010
|
-
}
|
|
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;
|
|
1032
|
-
};
|
|
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
|
-
}
|
|
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;
|
|
1080
|
-
}
|
|
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);
|
|
1090
|
-
}
|
|
1091
|
-
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
|
-
var prepCache = new WeakMap;
|
|
1093
|
-
function prepPart(H, part) {
|
|
1094
|
-
let c = prepCache.get(H);
|
|
1095
|
-
if (!c)
|
|
1096
|
-
prepCache.set(H, c = new Map);
|
|
1097
|
-
let r = c.get(part);
|
|
1098
|
-
if (r !== undefined)
|
|
1099
|
-
return r;
|
|
1100
|
-
const p = H.parts[part];
|
|
1101
|
-
if (!p) {
|
|
1102
|
-
c.set(part, null);
|
|
1103
|
-
return null;
|
|
1104
|
-
}
|
|
1105
|
-
const n = p.studs.length;
|
|
1106
|
-
const studM = new Float64Array(n * 12);
|
|
1107
|
-
const kind = [], color = [];
|
|
1108
|
-
p.studs.forEach((s, i) => {
|
|
1109
|
-
kind.push(s[0]);
|
|
1110
|
-
color.push(s[1]);
|
|
1111
|
-
for (let k = 0;k < 12; k++)
|
|
1112
|
-
studM[i * 12 + k] = s[2 + k];
|
|
1113
|
-
});
|
|
1114
|
-
let mask = null, nx = 0, nz = 0;
|
|
1115
|
-
if (p.mask) {
|
|
1116
|
-
nx = p.mask[0];
|
|
1117
|
-
nz = p.mask[1];
|
|
1118
|
-
const bits = p.mask[2];
|
|
1119
|
-
mask = new Uint8Array(bits.length);
|
|
1120
|
-
for (let i = 0;i < bits.length; i++)
|
|
1121
|
-
mask[i] = bits.charCodeAt(i) === 49 ? 1 : 0;
|
|
1122
|
-
}
|
|
1123
|
-
c.set(part, r = { nStuds: n, studM, kind, color, mask, nx, nz });
|
|
1124
|
-
return r;
|
|
1125
|
-
}
|
|
1126
|
-
function mul12To(a, b, bo, w, ao = 0) {
|
|
1127
|
-
const b0 = b[bo], b1 = b[bo + 1], b2 = b[bo + 2];
|
|
1128
|
-
w[0] = a[ao] + a[ao + 3] * b0 + a[ao + 4] * b1 + a[ao + 5] * b2;
|
|
1129
|
-
w[1] = a[ao + 1] + a[ao + 6] * b0 + a[ao + 7] * b1 + a[ao + 8] * b2;
|
|
1130
|
-
w[2] = a[ao + 2] + a[ao + 9] * b0 + a[ao + 10] * b1 + a[ao + 11] * b2;
|
|
1131
|
-
for (let i = 0;i < 3; i++)
|
|
1132
|
-
for (let j = 0;j < 3; j++)
|
|
1133
|
-
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
|
-
}
|
|
1135
|
-
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
|
-
};
|
|
1141
|
-
|
|
1142
|
-
class NumTable {
|
|
1143
|
-
keys;
|
|
1144
|
-
vals;
|
|
1145
|
-
mask;
|
|
1146
|
-
size = 0;
|
|
1147
|
-
constructor(cap = 1024) {
|
|
1148
|
-
let n = 1024;
|
|
1149
|
-
while (n < cap * 2)
|
|
1150
|
-
n *= 2;
|
|
1151
|
-
this.keys = new Float64Array(n).fill(-1);
|
|
1152
|
-
this.vals = new Int32Array(n);
|
|
1153
|
-
this.mask = n - 1;
|
|
1154
|
-
}
|
|
1155
|
-
slot(k) {
|
|
1156
|
-
const lo = k >>> 0, hi = k / 4294967296 >>> 0;
|
|
1157
|
-
let h = Math.imul(lo ^ Math.imul(hi, 2654435761), 2246822507);
|
|
1158
|
-
h ^= h >>> 15;
|
|
1159
|
-
return h & this.mask;
|
|
1160
|
-
}
|
|
1161
|
-
get(k) {
|
|
1162
|
-
const K = this.keys;
|
|
1163
|
-
let i = this.slot(k);
|
|
1164
|
-
for (;; ) {
|
|
1165
|
-
const x = K[i];
|
|
1166
|
-
if (x === k)
|
|
1167
|
-
return this.vals[i];
|
|
1168
|
-
if (x === -1)
|
|
1169
|
-
return -1;
|
|
1170
|
-
i = i + 1 & this.mask;
|
|
1171
|
-
}
|
|
1172
|
-
}
|
|
1173
|
-
put(k, v) {
|
|
1174
|
-
if ((this.size + 1) * 2 > this.keys.length)
|
|
1175
|
-
this.grow();
|
|
1176
|
-
const K = this.keys;
|
|
1177
|
-
let i = this.slot(k);
|
|
1178
|
-
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;
|
|
1187
|
-
this.vals[i] = v;
|
|
1188
|
-
this.size++;
|
|
1189
|
-
return -1;
|
|
1190
|
-
}
|
|
1191
|
-
i = i + 1 & this.mask;
|
|
1192
|
-
}
|
|
1193
|
-
}
|
|
1194
|
-
grow() {
|
|
1195
|
-
const ok = this.keys, ov = this.vals;
|
|
1196
|
-
const n = ok.length * 2;
|
|
1197
|
-
this.keys = new Float64Array(n).fill(-1);
|
|
1198
|
-
this.vals = new Int32Array(n);
|
|
1199
|
-
this.mask = n - 1;
|
|
1200
|
-
this.size = 0;
|
|
1201
|
-
for (let i = 0;i < ok.length; i++)
|
|
1202
|
-
if (ok[i] !== -1)
|
|
1203
|
-
this.put(ok[i], ov[i]);
|
|
1204
|
-
}
|
|
1205
|
-
}
|
|
1206
|
-
var STEP_NEVER = 2147483647;
|
|
1207
|
-
function forEachStud(insts, H, fn) {
|
|
1208
|
-
const w = new Float64Array(12);
|
|
1209
|
-
let j = 0;
|
|
1210
|
-
for (let idx = 0;idx < insts.length; idx++) {
|
|
1211
|
-
const it = insts[idx];
|
|
1212
|
-
const pp = prepPart(H, it.part);
|
|
1213
|
-
if (!pp)
|
|
1214
|
-
continue;
|
|
1215
|
-
for (let s = 0;s < pp.nStuds; s++) {
|
|
1216
|
-
mul12To(it.m, pp.studM, s * 12, w);
|
|
1217
|
-
const c = pp.color[s];
|
|
1218
|
-
fn(j++, idx, w, pp.kind[s], c === "16" ? it.color : c, s);
|
|
1367
|
+
for (let k = 0;k < 12; k++) {
|
|
1368
|
+
const v = cond[l * 12 + k];
|
|
1369
|
+
buf[l * 24 + k] = v;
|
|
1370
|
+
buf[l * 24 + 12 + k] = v;
|
|
1219
1371
|
}
|
|
1372
|
+
side[l * 2 + 1] = 1;
|
|
1220
1373
|
}
|
|
1374
|
+
return { ib: new THREE.InterleavedBuffer(buf, 12), side: new THREE.BufferAttribute(side, 1) };
|
|
1221
1375
|
}
|
|
1222
|
-
function
|
|
1223
|
-
const
|
|
1224
|
-
|
|
1225
|
-
|
|
1226
|
-
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
if (wx > x1)
|
|
1242
|
-
x1 = wx;
|
|
1243
|
-
if (wz < z0)
|
|
1244
|
-
z0 = wz;
|
|
1245
|
-
if (wz > z1)
|
|
1246
|
-
z1 = wz;
|
|
1247
|
-
}
|
|
1248
|
-
const ri = rInst.length;
|
|
1249
|
-
rx0.push(x0);
|
|
1250
|
-
rx1.push(x1);
|
|
1251
|
-
rz0.push(z0);
|
|
1252
|
-
rz1.push(z1);
|
|
1253
|
-
rInst.push(idx);
|
|
1254
|
-
rPrep.push(prepPart(H, it.part));
|
|
1255
|
-
rBx.push(b[0]);
|
|
1256
|
-
rBz.push(b[2]);
|
|
1257
|
-
const lv2 = Math.round((m[1] + b[4]) * 2);
|
|
1258
|
-
for (let cx = Math.floor(x0 / CELL);cx <= Math.floor(x1 / CELL); cx++)
|
|
1259
|
-
for (let cz = Math.floor(z0 / CELL);cz <= Math.floor(z1 / CELL); cz++) {
|
|
1260
|
-
const k = cellKey(lv2, cx, cz);
|
|
1261
|
-
if (k < 0)
|
|
1262
|
-
continue;
|
|
1263
|
-
const e = rectE.length;
|
|
1264
|
-
rectE.push(ri);
|
|
1265
|
-
nextE.push(cells.put(k, e));
|
|
1266
|
-
}
|
|
1267
|
-
}
|
|
1268
|
-
const SX = [0, 5, -5, 5, -5], SZ = [0, 5, 5, -5, -5];
|
|
1269
|
-
const coverStep = (x, y, z, self) => {
|
|
1270
|
-
const k = cellKey(Math.round(y * 2), Math.floor(x / CELL), Math.floor(z / CELL));
|
|
1271
|
-
if (k < 0)
|
|
1272
|
-
return STEP_NEVER;
|
|
1273
|
-
let best = STEP_NEVER;
|
|
1274
|
-
for (let e = cells.get(k);e >= 0; e = nextE[e]) {
|
|
1275
|
-
const ri = rectE[e];
|
|
1276
|
-
if (rInst[ri] === self || !(x - 6 >= rx0[ri] - 0.5 && x + 6 <= rx1[ri] + 0.5 && z - 6 >= rz0[ri] - 0.5 && z + 6 <= rz1[ri] + 0.5))
|
|
1277
|
-
continue;
|
|
1278
|
-
const m = insts[rInst[ri]].m;
|
|
1279
|
-
const pp = rPrep[ri];
|
|
1280
|
-
const bx = rBx[ri], bz = rBz[ri];
|
|
1281
|
-
const dx = x - m[0], dy = y - m[1], dz = z - m[2];
|
|
1282
|
-
const lx = m[3] * dx + m[6] * dy + m[9] * dz, lz = m[5] * dx + m[8] * dy + m[11] * dz;
|
|
1283
|
-
const { nx, nz, mask: bits } = pp;
|
|
1284
|
-
let ok = true;
|
|
1285
|
-
for (let s = 0;s < 5; s++) {
|
|
1286
|
-
const ca = Math.floor((lx + SX[s] - bx) / 20), cb = Math.floor((lz + SZ[s] - bz) / 20);
|
|
1287
|
-
if (ca < 0 || cb < 0 || ca >= nx || cb >= nz || bits[ca * nz + cb] !== 1) {
|
|
1288
|
-
ok = false;
|
|
1289
|
-
break;
|
|
1290
|
-
}
|
|
1291
|
-
}
|
|
1292
|
-
if (ok) {
|
|
1293
|
-
if (!steps)
|
|
1294
|
-
return 0;
|
|
1295
|
-
const st = steps[rInst[ri]];
|
|
1296
|
-
if (st < best)
|
|
1297
|
-
best = st;
|
|
1298
|
-
}
|
|
1299
|
-
}
|
|
1300
|
-
return best;
|
|
1376
|
+
function condEdges({ ib, side }, im, material) {
|
|
1377
|
+
const g = new THREE.InstancedBufferGeometry;
|
|
1378
|
+
g.setAttribute("position", new THREE.InterleavedBufferAttribute(ib, 3, 0));
|
|
1379
|
+
g.setAttribute("ldrP1", new THREE.InterleavedBufferAttribute(ib, 3, 3));
|
|
1380
|
+
g.setAttribute("ldrC0", new THREE.InterleavedBufferAttribute(ib, 3, 6));
|
|
1381
|
+
g.setAttribute("ldrC1", new THREE.InterleavedBufferAttribute(ib, 3, 9));
|
|
1382
|
+
g.setAttribute("ldrSide", side);
|
|
1383
|
+
g.setAttribute("instanceMatrix", im.instanceMatrix);
|
|
1384
|
+
g.instanceCount = im.count;
|
|
1385
|
+
const l = new THREE.LineSegments(g, material);
|
|
1386
|
+
l.frustumCulled = false;
|
|
1387
|
+
l.name = "ldrCondLines";
|
|
1388
|
+
l.onBeforeRender = (_r, _s, cam, _g, mat) => {
|
|
1389
|
+
const u = mat.uniforms?.ldrViewProj;
|
|
1390
|
+
if (!u)
|
|
1391
|
+
return;
|
|
1392
|
+
l.modelViewMatrix.multiplyMatrices(cam.matrixWorldInverse, l.matrixWorld);
|
|
1393
|
+
u.value.multiplyMatrices(cam.projectionMatrix, l.modelViewMatrix);
|
|
1394
|
+
mat.uniformsNeedUpdate = true;
|
|
1301
1395
|
};
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
const
|
|
1312
|
-
|
|
1313
|
-
|
|
1396
|
+
return l;
|
|
1397
|
+
}
|
|
1398
|
+
function sharedLines(pos, im, material = sharedLineMat()) {
|
|
1399
|
+
const { P, I } = weldLines(pos);
|
|
1400
|
+
const g = new THREE.InstancedBufferGeometry;
|
|
1401
|
+
g.setAttribute("position", new THREE.BufferAttribute(P, 3));
|
|
1402
|
+
g.setIndex(new THREE.BufferAttribute(I, 1));
|
|
1403
|
+
g.setAttribute("instanceMatrix", im.instanceMatrix);
|
|
1404
|
+
g.instanceCount = im.count;
|
|
1405
|
+
const l = new THREE.LineSegments(g, material);
|
|
1406
|
+
l.frustumCulled = false;
|
|
1407
|
+
return l;
|
|
1408
|
+
}
|
|
1409
|
+
function writeM4(t, o, m, mo = 0) {
|
|
1410
|
+
t[o] = m[mo + 3];
|
|
1411
|
+
t[o + 1] = m[mo + 6];
|
|
1412
|
+
t[o + 2] = m[mo + 9];
|
|
1413
|
+
t[o + 3] = 0;
|
|
1414
|
+
t[o + 4] = m[mo + 4];
|
|
1415
|
+
t[o + 5] = m[mo + 7];
|
|
1416
|
+
t[o + 6] = m[mo + 10];
|
|
1417
|
+
t[o + 7] = 0;
|
|
1418
|
+
t[o + 8] = m[mo + 5];
|
|
1419
|
+
t[o + 9] = m[mo + 8];
|
|
1420
|
+
t[o + 10] = m[mo + 11];
|
|
1421
|
+
t[o + 11] = 0;
|
|
1422
|
+
t[o + 12] = m[mo];
|
|
1423
|
+
t[o + 13] = m[mo + 1];
|
|
1424
|
+
t[o + 14] = m[mo + 2];
|
|
1425
|
+
t[o + 15] = 1;
|
|
1426
|
+
}
|
|
1427
|
+
function newIM(g, mat, n) {
|
|
1428
|
+
const im = new THREE.InstancedMesh(g, mat, 0);
|
|
1429
|
+
im.instanceMatrix = new THREE.InstancedBufferAttribute(new Float32Array(n * 16), 16);
|
|
1430
|
+
im.count = n;
|
|
1431
|
+
return im;
|
|
1432
|
+
}
|
|
1433
|
+
function instancedBoundingSphere(im) {
|
|
1434
|
+
const g = im.geometry;
|
|
1435
|
+
if (!g.boundingSphere)
|
|
1436
|
+
g.computeBoundingSphere();
|
|
1437
|
+
const gs = g.boundingSphere;
|
|
1438
|
+
const gx = gs.center.x, gy = gs.center.y, gz = gs.center.z, gr = gs.radius;
|
|
1439
|
+
const A = im.instanceMatrix.array;
|
|
1440
|
+
let cx = 0, cy = 0, cz = 0, r = -1;
|
|
1441
|
+
const expand = (px, py, pz) => {
|
|
1442
|
+
if (r < 0) {
|
|
1443
|
+
cx = px;
|
|
1444
|
+
cy = py;
|
|
1445
|
+
cz = pz;
|
|
1446
|
+
r = 0;
|
|
1314
1447
|
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
1448
|
}
|
|
1323
|
-
const
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1449
|
+
const vx = px - cx, vy = py - cy, vz = pz - cz;
|
|
1450
|
+
const l2 = vx * vx + vy * vy + vz * vz;
|
|
1451
|
+
if (l2 > r * r) {
|
|
1452
|
+
const l = Math.sqrt(l2);
|
|
1453
|
+
const d = (l - r) * 0.5;
|
|
1454
|
+
const f = d / l;
|
|
1455
|
+
cx += vx * f;
|
|
1456
|
+
cy += vy * f;
|
|
1457
|
+
cz += vz * f;
|
|
1458
|
+
r += d;
|
|
1329
1459
|
}
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1460
|
+
};
|
|
1461
|
+
for (let i = 0, n = im.count;i < n; i++) {
|
|
1462
|
+
const o = i * 16;
|
|
1463
|
+
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];
|
|
1464
|
+
const w = 1 / (e3 * gx + e7 * gy + e11 * gz + A[o + 15]);
|
|
1465
|
+
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;
|
|
1466
|
+
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));
|
|
1467
|
+
if (r < 0) {
|
|
1468
|
+
cx = x;
|
|
1469
|
+
cy = y;
|
|
1470
|
+
cz = z;
|
|
1471
|
+
r = sr;
|
|
1340
1472
|
continue;
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1473
|
+
}
|
|
1474
|
+
if (x === cx && y === cy && z === cz) {
|
|
1475
|
+
r = Math.max(r, sr);
|
|
1344
1476
|
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
1477
|
}
|
|
1478
|
+
let dx = x - cx, dy = y - cy, dz = z - cz;
|
|
1479
|
+
const inv = 1 / (Math.sqrt(dx * dx + dy * dy + dz * dz) || 1);
|
|
1480
|
+
dx = dx * inv * sr;
|
|
1481
|
+
dy = dy * inv * sr;
|
|
1482
|
+
dz = dz * inv * sr;
|
|
1483
|
+
expand(x + dx, y + dy, z + dz);
|
|
1484
|
+
expand(x - dx, y - dy, z - dz);
|
|
1365
1485
|
}
|
|
1366
|
-
|
|
1486
|
+
const sph = im.boundingSphere ?? new THREE.Sphere;
|
|
1487
|
+
sph.center.set(cx, cy, cz);
|
|
1488
|
+
sph.radius = r;
|
|
1489
|
+
if (r < 0)
|
|
1490
|
+
sph.makeEmpty();
|
|
1491
|
+
im.boundingSphere = sph;
|
|
1492
|
+
return sph;
|
|
1493
|
+
}
|
|
1494
|
+
function fillInstances(im, ids, insts, color) {
|
|
1495
|
+
const M = im.instanceMatrix.array;
|
|
1496
|
+
const C = new Float32Array(ids.length * 3);
|
|
1497
|
+
for (let k = 0;k < ids.length; k++) {
|
|
1498
|
+
const it = insts[ids[k]];
|
|
1499
|
+
writeM4(M, k * 16, it.m);
|
|
1500
|
+
color(it.color).toArray(C, k * 3);
|
|
1501
|
+
}
|
|
1502
|
+
im.instanceColor = new THREE.InstancedBufferAttribute(C, 3);
|
|
1367
1503
|
}
|
|
1368
1504
|
function computeCulling(insts, H) {
|
|
1369
1505
|
const c = cullCore(insts, H);
|
|
@@ -1419,7 +1555,8 @@ class LdrLodRoot extends THREE.LOD {
|
|
|
1419
1555
|
clusters = [];
|
|
1420
1556
|
vpH = 1080;
|
|
1421
1557
|
px = 0.5;
|
|
1422
|
-
edgePpl = 0.
|
|
1558
|
+
edgePpl = 0.5 / 20;
|
|
1559
|
+
edgeMinPx = 0.15;
|
|
1423
1560
|
enabled = true;
|
|
1424
1561
|
apply = () => {};
|
|
1425
1562
|
inv = new THREE.Matrix4;
|
|
@@ -1449,37 +1586,90 @@ class LdrLodRoot extends THREE.LOD {
|
|
|
1449
1586
|
L = i;
|
|
1450
1587
|
break;
|
|
1451
1588
|
}
|
|
1589
|
+
if (c.below !== undefined && x * c.ax[0] + y * c.ax[1] + z * c.ax[2] < c.below - 1 && ppl * 20 < 4)
|
|
1590
|
+
L = -1;
|
|
1591
|
+
if (c.boxErr !== undefined && c.boxErr * ppl <= tau)
|
|
1592
|
+
L = -1;
|
|
1452
1593
|
const e = ppl >= eppl;
|
|
1453
1594
|
if (L !== c.cur || e !== c.edgeOk) {
|
|
1454
1595
|
c.cur = L;
|
|
1455
1596
|
c.edgeOk = e;
|
|
1456
1597
|
this.apply(c);
|
|
1457
1598
|
}
|
|
1599
|
+
if (e && c.lines.length) {
|
|
1600
|
+
const minLen = this.edgeMinPx / ppl;
|
|
1601
|
+
for (const l of c.lines) {
|
|
1602
|
+
const lens = l.userData.ldrLens;
|
|
1603
|
+
if (!lens)
|
|
1604
|
+
continue;
|
|
1605
|
+
let lo = 0, hi = lens.length;
|
|
1606
|
+
while (lo < hi) {
|
|
1607
|
+
const mid = lo + hi >> 1;
|
|
1608
|
+
if (lens[mid] >= minLen)
|
|
1609
|
+
lo = mid + 1;
|
|
1610
|
+
else
|
|
1611
|
+
hi = mid;
|
|
1612
|
+
}
|
|
1613
|
+
l.geometry.drawRange.count = lo * 2;
|
|
1614
|
+
}
|
|
1615
|
+
}
|
|
1458
1616
|
}
|
|
1459
1617
|
}
|
|
1460
1618
|
}
|
|
1461
|
-
function buildStudMeshes(insts, H, cull, arr,
|
|
1619
|
+
function buildStudMeshes(insts, H, cull, arr, LOD, color, matF, matB, steps, colorIndex) {
|
|
1462
1620
|
const bucketOf = new Map;
|
|
1463
1621
|
const bKind = [], bMirror = [];
|
|
1464
1622
|
const bAll = [];
|
|
1465
1623
|
const studBucket = new Uint16Array(cull.nStuds);
|
|
1466
1624
|
const sx = new Float32Array(cull.nStuds), sz = new Float32Array(cull.nStuds);
|
|
1467
|
-
|
|
1468
|
-
|
|
1469
|
-
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1473
|
-
|
|
1474
|
-
|
|
1475
|
-
|
|
1476
|
-
|
|
1625
|
+
const kindIds = new Map;
|
|
1626
|
+
const kindNames = [];
|
|
1627
|
+
const bucketOfKM = [];
|
|
1628
|
+
const partStud = new Map;
|
|
1629
|
+
for (let idx = 0, j = 0;idx < insts.length; idx++) {
|
|
1630
|
+
const it = insts[idx];
|
|
1631
|
+
const pp = prepPart(H, it.part);
|
|
1632
|
+
if (!pp || !pp.nStuds)
|
|
1633
|
+
continue;
|
|
1634
|
+
const a = it.m;
|
|
1635
|
+
let ps = partStud.get(pp);
|
|
1636
|
+
if (!ps) {
|
|
1637
|
+
const kid = new Int32Array(pp.nStuds), neg = new Uint8Array(pp.nStuds);
|
|
1638
|
+
for (let si = 0;si < pp.nStuds; si++) {
|
|
1639
|
+
const kn = pp.kind[si];
|
|
1640
|
+
let id = kindIds.get(kn);
|
|
1641
|
+
if (id === undefined) {
|
|
1642
|
+
id = kindNames.length;
|
|
1643
|
+
kindIds.set(kn, id);
|
|
1644
|
+
kindNames.push(kn);
|
|
1645
|
+
}
|
|
1646
|
+
kid[si] = id;
|
|
1647
|
+
neg[si] = det12(pp.studM.subarray(si * 12, si * 12 + 12)) < 0 ? 1 : 0;
|
|
1648
|
+
}
|
|
1649
|
+
partStud.set(pp, ps = { kid, neg });
|
|
1477
1650
|
}
|
|
1478
|
-
|
|
1479
|
-
|
|
1480
|
-
|
|
1481
|
-
|
|
1482
|
-
|
|
1651
|
+
const instNeg = det12(a) < 0 ? 1 : 0;
|
|
1652
|
+
const B = pp.studM;
|
|
1653
|
+
for (let si = 0;si < pp.nStuds; si++, j++) {
|
|
1654
|
+
const o = si * 12, b0 = B[o], b1 = B[o + 1], b2 = B[o + 2];
|
|
1655
|
+
const neg = (instNeg ^ ps.neg[si]) === 1;
|
|
1656
|
+
const km = ps.kid[si] * 2 + (neg ? 1 : 0);
|
|
1657
|
+
let b = bucketOfKM[km];
|
|
1658
|
+
if (b === undefined) {
|
|
1659
|
+
const kn = kindNames[ps.kid[si]];
|
|
1660
|
+
b = bKind.length;
|
|
1661
|
+
bucketOfKM[km] = b;
|
|
1662
|
+
bucketOf.set(neg ? kn + "#m" : kn, b);
|
|
1663
|
+
bKind.push(kn);
|
|
1664
|
+
bMirror.push(neg);
|
|
1665
|
+
bAll.push(0);
|
|
1666
|
+
}
|
|
1667
|
+
studBucket[j] = b;
|
|
1668
|
+
bAll[b]++;
|
|
1669
|
+
sx[j] = a[0] + a[3] * b0 + a[4] * b1 + a[5] * b2;
|
|
1670
|
+
sz[j] = a[2] + a[9] * b0 + a[10] * b1 + a[11] * b2;
|
|
1671
|
+
}
|
|
1672
|
+
}
|
|
1483
1673
|
const bIds = bAll.map((n) => new Int32Array(n));
|
|
1484
1674
|
{
|
|
1485
1675
|
const f = bAll.map(() => 0);
|
|
@@ -1491,7 +1681,7 @@ function buildStudMeshes(insts, H, cull, arr, Q, LOD, color, matF, matB, steps,
|
|
|
1491
1681
|
const studCl = new Int32Array(cull.nStuds), studSlot = new Int32Array(cull.nStuds);
|
|
1492
1682
|
const sMesh = [];
|
|
1493
1683
|
bKind.forEach((kind, b) => {
|
|
1494
|
-
const g = geom(H.studKinds[kind].body, arr
|
|
1684
|
+
const g = geom(H.studKinds[kind].body, arr);
|
|
1495
1685
|
const ids = bIds[b];
|
|
1496
1686
|
for (const c of gridClusters(ids.length, (i) => sx[ids[i]], (i) => sz[ids[i]], LOD ? 16384 : Infinity)) {
|
|
1497
1687
|
const ci = sMesh.length;
|
|
@@ -1515,6 +1705,13 @@ function buildStudMeshes(insts, H, cull, arr, Q, LOD, color, matF, matB, steps,
|
|
|
1515
1705
|
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
1706
|
}
|
|
1517
1707
|
});
|
|
1708
|
+
const colCache = new Map;
|
|
1709
|
+
const colorOf = (c) => {
|
|
1710
|
+
let x = colCache.get(c);
|
|
1711
|
+
if (!x)
|
|
1712
|
+
colCache.set(c, x = color(c));
|
|
1713
|
+
return x;
|
|
1714
|
+
};
|
|
1518
1715
|
forEachStud(insts, H, (j, owner, w, _kind, col, si) => {
|
|
1519
1716
|
const sm = sMesh[studCl[j]];
|
|
1520
1717
|
if (!sm)
|
|
@@ -1530,18 +1727,46 @@ function buildStudMeshes(insts, H, cull, arr, Q, LOD, color, matF, matB, steps,
|
|
|
1530
1727
|
t.col[slot] = colorIndex(col);
|
|
1531
1728
|
}
|
|
1532
1729
|
writeM4(im.instanceMatrix.array, slot * 16, w);
|
|
1533
|
-
|
|
1730
|
+
colorOf(col).toArray(im.instanceColor.array, slot * 3);
|
|
1534
1731
|
});
|
|
1535
1732
|
return sMesh;
|
|
1536
1733
|
}
|
|
1734
|
+
function undersideGroups(ids, insts) {
|
|
1735
|
+
const by = new Map;
|
|
1736
|
+
const rest = [];
|
|
1737
|
+
for (const id of ids) {
|
|
1738
|
+
const m = insts[id].m;
|
|
1739
|
+
const l = Math.hypot(m[4], m[7], m[10]);
|
|
1740
|
+
if (!(l > 0.000001)) {
|
|
1741
|
+
rest.push(id);
|
|
1742
|
+
continue;
|
|
1743
|
+
}
|
|
1744
|
+
const ax = [m[4] / l, m[7] / l, m[10] / l, l];
|
|
1745
|
+
const k = ax.map((v) => Math.round(v * 1000)).join();
|
|
1746
|
+
let g = by.get(k);
|
|
1747
|
+
if (!g) {
|
|
1748
|
+
if (by.size >= 12) {
|
|
1749
|
+
rest.push(id);
|
|
1750
|
+
continue;
|
|
1751
|
+
}
|
|
1752
|
+
by.set(k, g = { ids: [], ax });
|
|
1753
|
+
}
|
|
1754
|
+
g.ids.push(id);
|
|
1755
|
+
}
|
|
1756
|
+
const out = [...by.values()];
|
|
1757
|
+
if (rest.length)
|
|
1758
|
+
out.push({ ids: rest, ax: null });
|
|
1759
|
+
return out;
|
|
1760
|
+
}
|
|
1537
1761
|
function buildLdrScene(insts, pack, P, color, mark) {
|
|
1538
1762
|
const { header: H, arr } = pack;
|
|
1539
|
-
const Q = P.quant !== false;
|
|
1540
1763
|
const LOD = P.lod !== false;
|
|
1764
|
+
const EDGES = !!P.edges;
|
|
1541
1765
|
const root = new LdrLodRoot;
|
|
1542
1766
|
root.enabled = LOD;
|
|
1543
1767
|
root.px = P.lodPx ?? 0.5;
|
|
1544
1768
|
root.edgePpl = (P.lodEdgePx ?? 0.5) / 20;
|
|
1769
|
+
root.edgeMinPx = P.lodEdgeMinPx ?? 0.15;
|
|
1545
1770
|
const trackVp = (r) => {
|
|
1546
1771
|
const rt = r.getRenderTarget();
|
|
1547
1772
|
const h = rt ? rt.height : r.getContext().drawingBufferHeight;
|
|
@@ -1559,7 +1784,7 @@ function buildLdrScene(insts, pack, P, color, mark) {
|
|
|
1559
1784
|
}
|
|
1560
1785
|
});
|
|
1561
1786
|
const steps = P.steps;
|
|
1562
|
-
let cull = cullCore(insts, H, steps);
|
|
1787
|
+
let cull = P.cull ?? cullCore(insts, H, steps);
|
|
1563
1788
|
mark("culling");
|
|
1564
1789
|
const stepBatches = [];
|
|
1565
1790
|
const instM = steps ? new Float64Array(insts.length * 12) : null;
|
|
@@ -1585,7 +1810,7 @@ function buildLdrScene(insts, pack, P, color, mark) {
|
|
|
1585
1810
|
});
|
|
1586
1811
|
const edgeObjs = [];
|
|
1587
1812
|
const condObjs = [];
|
|
1588
|
-
const wantCond = P.cond !== false &&
|
|
1813
|
+
const wantCond = P.cond !== false && EDGES;
|
|
1589
1814
|
let condMat = null;
|
|
1590
1815
|
const cmat = () => condMat ??= condLineMat();
|
|
1591
1816
|
let lineMatShared = null;
|
|
@@ -1616,8 +1841,8 @@ function buildLdrScene(insts, pack, P, color, mark) {
|
|
|
1616
1841
|
const addLines = (ref, im, cl) => {
|
|
1617
1842
|
let w = lineCache.get(ref);
|
|
1618
1843
|
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) });
|
|
1844
|
+
const r = weldLines(arr(ref), LOD);
|
|
1845
|
+
lineCache.set(ref, w = { P: new THREE.BufferAttribute(r.P, 3), I: new THREE.BufferAttribute(r.I, 1), lens: r.lens });
|
|
1621
1846
|
}
|
|
1622
1847
|
const g = new THREE.InstancedBufferGeometry;
|
|
1623
1848
|
g.setAttribute("position", w.P);
|
|
@@ -1626,6 +1851,8 @@ function buildLdrScene(insts, pack, P, color, mark) {
|
|
|
1626
1851
|
g.instanceCount = im.count;
|
|
1627
1852
|
const l = new THREE.LineSegments(g, lmat());
|
|
1628
1853
|
l.frustumCulled = false;
|
|
1854
|
+
if (LOD)
|
|
1855
|
+
l.userData.ldrLens = w.lens;
|
|
1629
1856
|
edgeObjs.push(l);
|
|
1630
1857
|
cl.lines.push(l);
|
|
1631
1858
|
root.add(l);
|
|
@@ -1633,7 +1860,6 @@ function buildLdrScene(insts, pack, P, color, mark) {
|
|
|
1633
1860
|
};
|
|
1634
1861
|
const stats = { studsTotal: cull.nStuds, studsHidden: cull.studsHidden, undersTotal: 0, undersHidden: 0 };
|
|
1635
1862
|
const toggles = [];
|
|
1636
|
-
const studMeshes = [];
|
|
1637
1863
|
const countTo = (objs) => ({ set count(n) {
|
|
1638
1864
|
for (const o of objs()) {
|
|
1639
1865
|
if (o.isInstancedMesh)
|
|
@@ -1668,8 +1894,9 @@ function buildLdrScene(insts, pack, P, color, mark) {
|
|
|
1668
1894
|
root.clusters.push(c);
|
|
1669
1895
|
return c;
|
|
1670
1896
|
};
|
|
1671
|
-
const lodLevels = (b, base, mat) => !LOD ||
|
|
1672
|
-
const im = new THREE.InstancedMesh(geom(l, arr
|
|
1897
|
+
const lodLevels = (b, base, mat) => !LOD || !b?.lod ? [] : b.lod.map((l) => {
|
|
1898
|
+
const im = new THREE.InstancedMesh(geom(l, arr), mat, 0);
|
|
1899
|
+
im.userData = { ...base.userData };
|
|
1673
1900
|
im.instanceMatrix = base.instanceMatrix;
|
|
1674
1901
|
im.count = base.count;
|
|
1675
1902
|
im.instanceColor = base.instanceColor;
|
|
@@ -1685,10 +1912,10 @@ function buildLdrScene(insts, pack, P, color, mark) {
|
|
|
1685
1912
|
for (const [pk, idsAll] of byPart) {
|
|
1686
1913
|
const part = pk.replace(/#m$/, "");
|
|
1687
1914
|
const p = H.parts[part];
|
|
1688
|
-
const mat =
|
|
1915
|
+
const mat = p.uncert ? (nUncert++, matD) : pk.endsWith("#m") ? matB : matF;
|
|
1689
1916
|
const textured = wantTex && !!p.tex;
|
|
1690
1917
|
const bodyB = textured ? p.tbody : p.body;
|
|
1691
|
-
const body = geom(bodyB, arr
|
|
1918
|
+
const body = geom(bodyB, arr);
|
|
1692
1919
|
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
1920
|
for (const g of groups) {
|
|
1694
1921
|
const ids = Array.from(g, (i) => idsAll[i]);
|
|
@@ -1696,7 +1923,8 @@ function buildLdrScene(insts, pack, P, color, mark) {
|
|
|
1696
1923
|
const lv0 = [];
|
|
1697
1924
|
const place = (im) => {
|
|
1698
1925
|
fillInstances(im, ids, insts, color);
|
|
1699
|
-
im
|
|
1926
|
+
instancedBoundingSphere(im);
|
|
1927
|
+
im.userData.ldrPart = part;
|
|
1700
1928
|
root.add(im);
|
|
1701
1929
|
};
|
|
1702
1930
|
if (body) {
|
|
@@ -1706,7 +1934,7 @@ function buildLdrScene(insts, pack, P, color, mark) {
|
|
|
1706
1934
|
}
|
|
1707
1935
|
if (textured)
|
|
1708
1936
|
for (const tb of p.tex) {
|
|
1709
|
-
const gg = geom(tb, arr
|
|
1937
|
+
const gg = geom(tb, arr);
|
|
1710
1938
|
const im = newIM(gg, texMat(tb.t, mat, !!tb.wrapU), ids.length);
|
|
1711
1939
|
texBatches++;
|
|
1712
1940
|
lv0.push(im);
|
|
@@ -1724,49 +1952,57 @@ function buildLdrScene(insts, pack, P, color, mark) {
|
|
|
1724
1952
|
const cl = newCluster(bodyIm.boundingSphere);
|
|
1725
1953
|
lv0.forEach((o) => o.onBeforeRender = trackVp);
|
|
1726
1954
|
cl.lv.push({ objs: lv0, err: 0 }, ...textured ? [] : lodLevels(p.body, bodyIm, mat));
|
|
1727
|
-
if (
|
|
1955
|
+
if (EDGES && p.edges)
|
|
1728
1956
|
addLines(p.edges, bodyIm, cl);
|
|
1729
1957
|
addCond(p, bodyIm, cl);
|
|
1730
1958
|
if (steps)
|
|
1731
1959
|
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
1960
|
}
|
|
1743
|
-
const under = geom(p.under, arr
|
|
1744
|
-
|
|
1745
|
-
|
|
1746
|
-
const
|
|
1747
|
-
|
|
1748
|
-
stats.
|
|
1749
|
-
|
|
1961
|
+
const under = geom(p.under, arr);
|
|
1962
|
+
const uGroups = !under ? [] : LOD && P.lodUnder !== false ? undersideGroups(ids, insts) : [{ ids, ax: null }];
|
|
1963
|
+
for (const { ids: uids, ax } of uGroups) {
|
|
1964
|
+
const ord = [...uids.filter((i) => !cull.underHidden[i]), ...uids.filter((i) => cull.underHidden[i])];
|
|
1965
|
+
const vis = uids.length - uids.reduce((a, i) => a + cull.underHidden[i], 0);
|
|
1966
|
+
stats.undersTotal += uids.length;
|
|
1967
|
+
stats.undersHidden += uids.length - vis;
|
|
1968
|
+
const im = newIM(under, mat, uids.length);
|
|
1750
1969
|
fillInstances(im, ord, insts, color);
|
|
1751
1970
|
im.onBeforeRender = trackVp;
|
|
1752
|
-
im.
|
|
1753
|
-
im.
|
|
1971
|
+
im.userData.ldrUnder = true;
|
|
1972
|
+
im.userData.ldrPart = part;
|
|
1973
|
+
instancedBoundingSphere(im);
|
|
1974
|
+
im.count = P.cullUnder ? vis : uids.length;
|
|
1754
1975
|
root.add(im);
|
|
1755
1976
|
const cl = newCluster(im.boundingSphere);
|
|
1756
1977
|
cl.lv.push({ objs: [im], err: 0 }, ...lodLevels(p.under, im, mat));
|
|
1978
|
+
{
|
|
1979
|
+
const bl = p.body?.lod;
|
|
1980
|
+
const last = bl?.[bl.length - 1];
|
|
1981
|
+
if (LOD && P.lodUnder !== false && last && last.tris === 12)
|
|
1982
|
+
cl.boxErr = last.err;
|
|
1983
|
+
}
|
|
1984
|
+
if (ax) {
|
|
1985
|
+
let below = Infinity;
|
|
1986
|
+
for (const id of uids) {
|
|
1987
|
+
const m = insts[id].m;
|
|
1988
|
+
below = Math.min(below, m[0] * ax[0] + m[1] * ax[1] + m[2] * ax[2] + p.bbox[4] * ax[3]);
|
|
1989
|
+
}
|
|
1990
|
+
cl.below = below;
|
|
1991
|
+
cl.ax = ax.slice(0, 3);
|
|
1992
|
+
}
|
|
1757
1993
|
addCond(p, im, cl, "under");
|
|
1758
1994
|
const objs = [...cl.lv.flatMap((l) => l.objs), ...cl.cond];
|
|
1759
1995
|
objs.forEach((o) => {
|
|
1760
1996
|
if (!o.isInstancedMesh)
|
|
1761
1997
|
o.geometry.instanceCount = im.count;
|
|
1762
1998
|
});
|
|
1763
|
-
toggles.push({ mesh: countTo(() => objs), all:
|
|
1999
|
+
toggles.push({ mesh: countTo(() => objs), all: uids.length, visible: vis, flag: "under" });
|
|
1764
2000
|
if (steps)
|
|
1765
2001
|
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
2002
|
}
|
|
1767
2003
|
}
|
|
1768
2004
|
}
|
|
1769
|
-
const sMesh = buildStudMeshes(insts, H, cull, arr,
|
|
2005
|
+
const sMesh = buildStudMeshes(insts, H, cull, arr, LOD, color, matF, matB, steps, steps && colorIndex);
|
|
1770
2006
|
const sKind = sMesh.map((x) => x?.kind ?? "");
|
|
1771
2007
|
const sVis = sMesh.map((x) => x?.vis ?? 0);
|
|
1772
2008
|
const STUD_ERR = 12;
|
|
@@ -1777,26 +2013,19 @@ function buildLdrScene(insts, pack, P, color, mark) {
|
|
|
1777
2013
|
const kind = sKind[ci];
|
|
1778
2014
|
const k = H.studKinds[kind];
|
|
1779
2015
|
const vis = sVis[ci], all = im.instanceMatrix.count;
|
|
1780
|
-
im
|
|
2016
|
+
instancedBoundingSphere(im);
|
|
1781
2017
|
im.count = P.cullStuds ? vis : all;
|
|
1782
2018
|
im.onBeforeRender = trackVp;
|
|
1783
2019
|
im.userData.ldrStud = true;
|
|
1784
2020
|
root.add(im);
|
|
1785
|
-
studMeshes.push({ im, kind });
|
|
1786
2021
|
const cl = newCluster(im.boundingSphere);
|
|
1787
2022
|
cl.lv.push({ objs: [im], err: 0 });
|
|
1788
|
-
if (LOD
|
|
2023
|
+
if (LOD)
|
|
1789
2024
|
cl.lv.push({ objs: [], err: STUD_ERR });
|
|
1790
|
-
if (
|
|
2025
|
+
if (EDGES && k.edges)
|
|
1791
2026
|
addLines(k.edges, im, cl);
|
|
1792
2027
|
if (P.condStuds !== false)
|
|
1793
2028
|
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
2029
|
const objs = [im, ...cl.lines, ...cl.cond];
|
|
1801
2030
|
objs.forEach((o) => {
|
|
1802
2031
|
if (!o.isInstancedMesh)
|
|
@@ -1814,7 +2043,7 @@ function buildLdrScene(insts, pack, P, color, mark) {
|
|
|
1814
2043
|
for (const o of l.objs)
|
|
1815
2044
|
o.visible = i === c.cur;
|
|
1816
2045
|
});
|
|
1817
|
-
const lineVis = edgesOn && c.edgeOk && (c.cur === 0 || !LOD || c.lv[c.cur].objs.length > 0);
|
|
2046
|
+
const lineVis = edgesOn && c.edgeOk && c.cur >= 0 && (c.cur === 0 || !LOD || c.lv[c.cur].objs.length > 0);
|
|
1818
2047
|
for (const o of c.lines)
|
|
1819
2048
|
o.visible = lineVis;
|
|
1820
2049
|
for (const o of c.cond)
|
|
@@ -1924,21 +2153,14 @@ function buildLdrScene(insts, pack, P, color, mark) {
|
|
|
1924
2153
|
m.needsUpdate = true;
|
|
1925
2154
|
}
|
|
1926
2155
|
};
|
|
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
2156
|
const setLod = (on) => {
|
|
1937
2157
|
root.enabled = on && LOD;
|
|
1938
2158
|
if (!root.enabled) {
|
|
1939
2159
|
for (const c of root.clusters) {
|
|
1940
2160
|
c.cur = 0;
|
|
1941
2161
|
c.edgeOk = true;
|
|
2162
|
+
for (const l of c.lines)
|
|
2163
|
+
l.geometry.drawRange.count = Infinity;
|
|
1942
2164
|
}
|
|
1943
2165
|
refresh();
|
|
1944
2166
|
}
|
|
@@ -1946,9 +2168,31 @@ function buildLdrScene(insts, pack, P, color, mark) {
|
|
|
1946
2168
|
insts = null;
|
|
1947
2169
|
cull = null;
|
|
1948
2170
|
byPart.clear();
|
|
1949
|
-
return { root, stats, setCull, setSide, setEdges, setCond,
|
|
2171
|
+
return { root, stats, setCull, setSide, setEdges, setCond, setLod, setStep, box, texturesReady };
|
|
2172
|
+
}
|
|
2173
|
+
async function warmPackGeometry(pack, stop = () => false, sliceMs = 8) {
|
|
2174
|
+
const { header: H, arr } = pack;
|
|
2175
|
+
const list = [];
|
|
2176
|
+
for (const p of Object.values(H.parts ?? {}))
|
|
2177
|
+
for (const b of [p.body, p.under])
|
|
2178
|
+
if (b) {
|
|
2179
|
+
list.push(b);
|
|
2180
|
+
for (const l of b.lod ?? [])
|
|
2181
|
+
list.push(l);
|
|
2182
|
+
}
|
|
2183
|
+
for (const k of Object.values(H.studKinds ?? {}))
|
|
2184
|
+
if (k?.body)
|
|
2185
|
+
list.push(k.body);
|
|
2186
|
+
let i = 0;
|
|
2187
|
+
while (i < list.length && !stop()) {
|
|
2188
|
+
const t = performance.now();
|
|
2189
|
+
while (i < list.length && performance.now() - t < sliceMs)
|
|
2190
|
+
geom(list[i++], arr);
|
|
2191
|
+
if (i < list.length)
|
|
2192
|
+
await new Promise((r) => setTimeout(r, 0));
|
|
2193
|
+
}
|
|
1950
2194
|
}
|
|
1951
|
-
// ../../../../../../../tmp/ldr-build-
|
|
2195
|
+
// ../../../../../../../tmp/ldr-build-NB5kkP/src/scene.ts
|
|
1952
2196
|
import * as THREE2 from "three";
|
|
1953
2197
|
function colorFn(src, pack, fallback) {
|
|
1954
2198
|
const table = new Map;
|
|
@@ -1993,12 +2237,8 @@ function createLdrObject(instances, pack, options = {}) {
|
|
|
1993
2237
|
const o = { edges: true, conditionalLines: true, cullStuds: true, cullUndersides: true, side: "front", material: "plastic", ...options };
|
|
1994
2238
|
const color = colorFn(o.colors, pack, new THREE2.Color(o.fallbackColor ?? 10528169));
|
|
1995
2239
|
const useTex = o.textures !== false;
|
|
1996
|
-
const
|
|
1997
|
-
const
|
|
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)));
|
|
2240
|
+
const { all, stepOf, nSteps } = sceneInstances(instances, pack.header, useTex);
|
|
2241
|
+
const uniq = { length: nSteps };
|
|
2002
2242
|
const stepViews = new Array(uniq.length).fill(null);
|
|
2003
2243
|
instances.forEach((i, k) => {
|
|
2004
2244
|
if (i.view)
|
|
@@ -2037,7 +2277,7 @@ function createLdrObject(instances, pack, options = {}) {
|
|
|
2037
2277
|
const drawnAt = (step) => all.filter((i, k) => (step == null || stepOf[k] <= step) && pack.header.parts[i.part]).length;
|
|
2038
2278
|
const build = () => {
|
|
2039
2279
|
const t0 = performance.now();
|
|
2040
|
-
cur = buildLdrScene(all, pack, {
|
|
2280
|
+
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
2281
|
pairs.clear();
|
|
2042
2282
|
if (o.material === "plastic")
|
|
2043
2283
|
cur.root.traverse((x) => {
|
|
@@ -2108,18 +2348,7 @@ function createLdrObject(instances, pack, options = {}) {
|
|
|
2108
2348
|
dispose: disposeCur
|
|
2109
2349
|
});
|
|
2110
2350
|
}
|
|
2111
|
-
// ../../../../../../../tmp/ldr-build-
|
|
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
|
|
2351
|
+
// ../../../../../../../tmp/ldr-build-NB5kkP/src/parts-cdn.ts
|
|
2123
2352
|
import { decompress as decompress2 } from "fzstd";
|
|
2124
2353
|
var DEFAULT_PARTS_CDN = "https://ldr-demo.vercel.app/cdn/v1/";
|
|
2125
2354
|
var indexCache = new Map;
|
|
@@ -2180,7 +2409,7 @@ function mergePacks(packs, extra = {}) {
|
|
|
2180
2409
|
return decodePack(out.buffer);
|
|
2181
2410
|
}
|
|
2182
2411
|
async function loadParts(names, o = {}) {
|
|
2183
|
-
const cdn = o.cdn ?? DEFAULT_PARTS_CDN, f = o.fetch ?? fetch, gap = o.gap ??
|
|
2412
|
+
const cdn = o.cdn ?? DEFAULT_PARTS_CDN, f = o.fetch ?? fetch, gap = o.gap ?? 16384;
|
|
2184
2413
|
const idx = await loadPartsIndex(cdn, f);
|
|
2185
2414
|
const want = [...new Set([...names].map(norm))];
|
|
2186
2415
|
const missing = [];
|
|
@@ -2223,7 +2452,7 @@ async function loadParts(names, o = {}) {
|
|
|
2223
2452
|
}
|
|
2224
2453
|
}
|
|
2225
2454
|
};
|
|
2226
|
-
await Promise.all(Array.from({ length: Math.min(o.concurrency ??
|
|
2455
|
+
await Promise.all(Array.from({ length: Math.min(o.concurrency ?? 24, groups.length) }, worker));
|
|
2227
2456
|
const shards = want.filter((n) => shardCache.has(cdn + n)).map((n) => shardCache.get(cdn + n));
|
|
2228
2457
|
const pack = shards.length ? mergePacks(shards, { colors: idx.colors }) : decodePack(emptyPack(idx.colors));
|
|
2229
2458
|
return { pack, missing, requests: groups.length, bytes };
|
|
@@ -2236,10 +2465,11 @@ function emptyPack(colors) {
|
|
|
2236
2465
|
b.set(h, 4);
|
|
2237
2466
|
return b.buffer;
|
|
2238
2467
|
}
|
|
2239
|
-
async function
|
|
2468
|
+
async function prepareModel(source, o = {}) {
|
|
2240
2469
|
const t0 = performance.now();
|
|
2241
2470
|
const f = o.fetch ?? fetch;
|
|
2242
2471
|
const idxP = loadPartsIndex(o.cdn ?? DEFAULT_PARTS_CDN, f);
|
|
2472
|
+
idxP.catch(() => {});
|
|
2243
2473
|
const text = o.text ? source : await f(source).then((r) => {
|
|
2244
2474
|
if (!r.ok)
|
|
2245
2475
|
throw new Error(`ldr: ${r.status} fetching ${source}`);
|
|
@@ -2249,15 +2479,125 @@ async function loadModel(source, o = {}) {
|
|
|
2249
2479
|
const name = o.name ?? (o.text ? "main.ldr" : decodeURIComponent(source.split(/[?#]/)[0].split("/").pop() || "main.ldr"));
|
|
2250
2480
|
const insts = parseModel(text, name, { looseGeometry: false });
|
|
2251
2481
|
const t2 = performance.now();
|
|
2482
|
+
o.onParsed?.(insts);
|
|
2252
2483
|
await idxP;
|
|
2253
2484
|
const { pack, missing, requests, bytes } = await loadParts(insts.filter((i) => !i.embedded).map((i) => i.part), o);
|
|
2254
2485
|
const t3 = performance.now();
|
|
2255
|
-
const
|
|
2256
|
-
|
|
2486
|
+
const cull = o.cull ? precomputeCull(insts, pack.header, o.textures !== false) : undefined;
|
|
2487
|
+
return { insts, pack, missing, requests, bytes, cull, timings: { fetchModel: t1 - t0, parse: t2 - t1, parts: t3 - t2, ...cull ? { cull: performance.now() - t3 } : {} } };
|
|
2488
|
+
}
|
|
2489
|
+
|
|
2490
|
+
// ../../../../../../../tmp/ldr-build-NB5kkP/src/load-worker.gen.ts
|
|
2491
|
+
var load_worker_gen_default = 'var ut=ArrayBuffer,j=Uint8Array,ge=Uint16Array,ft=Int16Array;var be=Int32Array,Ae=function(e,t,n){if(j.prototype.slice)return j.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 j(n-t);return r.set(e.subarray(t,n)),r},ce=function(e,t,n,r){if(j.prototype.fill)return j.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},pt=function(e,t,n,r){if(j.prototype.copyWithin)return j.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 mt=["invalid zstd data","window size too large (>2046MB)","invalid block type","FSE accuracy too high","match distance too far back","unexpected EOF"],V=function(e,t,n){var r=Error(t||mt[e]);if(r.code=e,Error.captureStackTrace)Error.captureStackTrace(r,V);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},ht=function(e,t){return(e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24)>>>0},gt=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)V(0);var a=6-o,l=i==3?4:i,f=Ne(e,a,l);a+=l;var g=c?1<<c:o,p=Ne(e,a,g)+(c==1&&256),y=p;if(!o){var C=1<<10+(e[5]>>3);y=C+(C>>3)*(e[5]&7)}if(y>2145386496)V(1);var u=new j((t==1?p||y:t?0:y)+12);return u[0]=1,u[4]=4,u[8]=8,{b:a+g,y:0,l:0,d:f,w:t&&t!=1?t:u.subarray(12),e:y,o:new be(u.buffer,0,3),u:p,c:s,m:Math.min(131072,y)}}else if((n>>4|e[3]<<20)==25481893)return ht(e,4)+8;V(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)V(3);var s=1<<o,i=s,c=-1,a=-1,l=-1,f=s,g=new ut(512+(s<<2)),p=new ft(g,0,256),y=new ge(g,0,256),C=new ge(g,512,s),u=512+(s<<1),m=new j(g,u,s),P=new j(g,u+s);while(c<255&&i>0){var b=re(i+1),d=r>>3,S=(1<<b+1)-1,k=(e[d]|e[d+1]<<8|e[d+2]<<16)>>(r&7)&S,w=(1<<b)-1,E=S-i-1,M=k&w;if(M<E)r+=b,k=M;else if(r+=b+1,k>w)k-=E;if(p[++c]=--k,k==-1)i+=k,m[--f]=c;else i-=k;if(!k)do{var x=r>>3;a=(e[x]|e[x+1]<<8)>>(r&7)&3,r+=2,c+=a}while(a==3)}if(c>255||i)V(0);var A=0,L=(s>>1)+(s>>3)+3,D=s-1;for(var F=0;F<=c;++F){var v=p[F];if(v<1){y[F]=-v;continue}for(l=0;l<v;++l){m[A]=F;do A=A+L&D;while(A>=f)}}if(A)V(0);for(l=0;l<s;++l){var h=y[m[l]]++,T=P[l]=o-re(h);C[l]=(h<<T)-s}return[r+7>>3,{b:o,s:m,n:P,t:C}]},bt=function(e,t){var n=0,r=-1,o=new j(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],g=l[1];t+=s;var p=f<<3,y=e[t];if(!y)V(0);var C=0,u=0,m=g.b,P=m,b=(++t<<3)-8+re(y);for(;;){if(b-=m,b<p)break;var d=b>>3;if(C+=(e[d]|e[d+1]<<8)>>(b&7)&(1<<m)-1,i[++r]=g.s[C],b-=P,b<p)break;d=b>>3,u+=(e[d]|e[d+1]<<8)>>(b&7)&(1<<P)-1,i[++r]=g.s[u],m=g.n[C],C=g.t[C],P=g.n[u],u=g.t[u]}if(++r>255)V(0)}else{r=s-127;for(;n<r;n+=2){var S=e[++t];i[n]=S>>4,i[n+1]=S&15}++t}var k=0;for(n=0;n<r;++n){var w=i[n];if(w>11)V(0);k+=w&&1<<w-1}var E=re(k)+1,M=1<<E,x=M-k;if(x&x-1)V(0);i[r++]=re(x)+1;for(n=0;n<r;++n){var w=i[n];++c[i[n]=w&&E+1-w]}var A=new j(M<<1),L=A.subarray(0,M),D=A.subarray(M);a[E]=0;for(n=E;n>0;--n){var F=a[n];ce(D,n,F,a[n-1]=F+c[n]*(1<<E-n))}if(a[0]!=M)V(0);for(n=0;n<r;++n){var v=i[n];if(v){var h=a[v];ce(L,n,h,a[v]=h+(1<<E-v))}}return[t,{n:D,b:E,s:L}]},dt=ue(new j([81,16,99,140,49,198,24,99,12,33,196,24,99,102,102,134,70,146,4]),0,6)[1],yt=ue(new j([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],xt=ue(new j([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},Me=new j(new be([0,0,0,0,16843009,50528770,134678020,202050057,269422093]).buffer,0,36),wt=$e(Me,0),Se=new j(new be([0,0,0,0,0,0,0,0,16843009,50528770,117769220,185207048,252579084,16]).buffer,0,53),vt=$e(Se,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)V(0);var a=0,l=n.b,f=(r<<3)-8+re(s)-l,g=-1;for(;f>c&&g<o;){var p=f>>3,y=(e[p]|e[p+1]<<8|e[p+2]<<16)>>(f&7);a=(a<<l|y)&i,t[++g]=n.s[a],f-=l=n.n[a]}if(f!=c||g+1!=o)V(0)},At=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)},Mt=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 j(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 Ae(e,o,a)}if(i==2){var l=e[o],f=l&3,g=l>>2&3,p=l>>4,y=0,C=0;if(f<2)if(g&1)p|=e[++o]<<4|(g&2&&e[++o]<<12);else p=l>>3;else if(C=g,g<2)p|=(e[++o]&63)<<4,y=e[o]>>6|e[++o]<<2;else if(g==2)p|=e[++o]<<4|(e[++o]&3)<<12,y=e[o]>>2|e[++o]<<6;else p|=e[++o]<<4|(e[++o]&63)<<12,y=e[o]>>6|e[++o]<<2|e[++o]<<10;++o;var u=n?n.subarray(t.y,t.y+t.m):new j(t.m),m=u.length-p;if(f==0)u.set(e.subarray(o,o+=p),m);else if(f==1)ce(u,e[o++],m);else{var P=t.h;if(f==2){var b=bt(e,o);y+=o-(o=b[0]),t.h=P=b[1]}else if(!P)V(0);(C?At:le)(e.subarray(o,o+=y),u.subarray(m),P)}var d=e[o++];if(d){if(d==255)d=(e[o++]|e[o++]<<8)+32512;else if(d>127)d=d-128<<8|e[o++];var S=e[o++];if(S&3)V(0);var k=[yt,xt,dt];for(var w=2;w>-1;--w){var E=S>>(w<<1)+2&3;if(E==1){var M=new j([0,0,e[o++]]);k[w]={s:M.subarray(2,3),n:M.subarray(0,1),t:new ge(M.buffer,0,1),b:0}}else if(E==2)r=ue(e,o,9-(w&1)),o=r[0],k[w]=r[1];else if(E==3){if(!t.t)V(0);k[w]=t.t[w]}}var x=t.t=k,A=x[0],L=x[1],D=x[2],F=e[a-1];if(!F)V(0);var v=(a<<3)-8+re(F)-D.b,h=v>>3,T=0,R=(e[h]|e[h+1]<<8)>>(v&7)&(1<<D.b)-1;h=(v-=L.b)>>3;var I=(e[h]|e[h+1]<<8)>>(v&7)&(1<<L.b)-1;h=(v-=A.b)>>3;var U=(e[h]|e[h+1]<<8)>>(v&7)&(1<<A.b)-1;for(++d;--d;){var O=D.s[R],K=D.n[R],H=A.s[U],z=A.n[U],B=L.s[I],N=L.n[I];h=(v-=B)>>3;var G=1<<B,X=G+((e[h]|e[h+1]<<8|e[h+2]<<16|e[h+3]<<24)>>>(v&7)&G-1);h=(v-=Se[H])>>3;var Y=vt[H]+((e[h]|e[h+1]<<8|e[h+2]<<16)>>(v&7)&(1<<Se[H])-1);h=(v-=Me[O])>>3;var W=wt[O]+((e[h]|e[h+1]<<8|e[h+2]<<16)>>(v&7)&(1<<Me[O])-1);if(h=(v-=K)>>3,R=D.t[R]+((e[h]|e[h+1]<<8)>>(v&7)&(1<<K)-1),h=(v-=z)>>3,U=A.t[U]+((e[h]|e[h+1]<<8)>>(v&7)&(1<<z)-1),h=(v-=N)>>3,I=L.t[I]+((e[h]|e[h+1]<<8)>>(v&7)&(1<<N)-1),X>3)t.o[2]=t.o[1],t.o[1]=t.o[0],t.o[0]=X-=3;else{var _=X-(W!=0);if(_){if(X=_==3?t.o[0]-1:t.o[_],_>1)t.o[2]=t.o[1];t.o[1]=t.o[0],t.o[0]=X}else X=t.o[0]}for(var w=0;w<W;++w)u[T+w]=u[m+w];T+=W,m+=W;var Z=T-X;if(Z<0){var J=-Z,ee=t.e+Z;if(J>Y)J=Y;for(var w=0;w<J;++w)u[T+w]=t.w[ee+w];T+=J,Y-=J,Z=0}for(var w=0;w<Y;++w)u[T+w]=u[Z+w];T+=Y}if(T!=m)while(m<u.length)u[T++]=u[m++];else T=u.length;if(n)t.y+=T;else u=Ae(u,0,T)}else if(n){if(t.y+=p,m)for(var w=0;w<p;++w)u[w]=u[m+w]}else if(m)u=Ae(u,m);return t.b=a,u}V(2)},St=function(e,t){if(e.length==1)return e[0];var n=new j(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=gt(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=Mt(e,i,t);if(!c)V(5);if(t)i.e=i.y;else n.push(c),s+=c.length,pt(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 St(n,s)}function de(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 Ce(e){if(/^0x/i.test(e))return parseInt(e,16);return+e}var Ve=/^~?\\s*moved\\s+to\\s+(.+)$/i,Ct=new Set(["FILE","NOFILE","!DATA","!:","STEP","BFC","ROTSTEP","BUFEXCHG","!TEXMAP"]),Je=new Set(["part","subpart","primitive","8_primitive","48_primitive","shortcut","helper"]),Pt=new Set(["model","submodel","configuration"]),Et=/^(?:!?LDRAW_ORG|Unofficial|Official\\s+LCAD)\\s+(\\S+)/i;function He(e){let t=Et.exec(e);if(!t)return;let n=t[1].toLowerCase().replace(/^unofficial_/,"");return Je.has(n)||Pt.has(n)?n:void 0}function Tt(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 Lt(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 g=0;g<o;g++)c=c.replace(/^\\S+\\s*/,"");let a=Tt(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((g,p)=>p>0&&g.toUpperCase()==="GLOSSMAP");if(f>0&&a[f+1])l.glossmap=a[f+1];if(t)l.next=!0;return l}var It=(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 kt(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:Ce(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=Ce(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,g=()=>{if(!a)return;let b=It(a.chunks.join("")),d=b[0]===137&&b[1]===80&&b[2]===78&&b[3]===71;(c??=new Map).set(q(a.name),{name:a.name,bytes:b,...d?{mime:"image/png"}:{}}),a=null},p=!0,y=(b)=>{if(g(),s={name:q(b),cmds:[]},o.set(s.name,s),!i)i=s.name;l=[],f=null,p=!0},C=!1,u=!1,m=()=>{if(u)return;u=!0,o.clear(),s=null,i=""},P=(b,d)=>{if(f){b.tex=f,f=null;return}let S=l[l.length-1];if(!S)return;if(S.fallback){if(!d)b.fallback=!0}else b.tex=S.map};for(let b of e.split(`\n`)){let d=b.trim();if(!d)continue;if(r&&d.charCodeAt(0)>=50&&d.charCodeAt(0)<=53&&(d.charCodeAt(1)===32||d.charCodeAt(1)===9)){if(a||C)continue;if(!s)y(t);let E=d.slice(2).trimStart(),M=E.search(/\\s/),x={t:d.charCodeAt(0)-48,color:Ce(M<0?E:E.slice(0,M)),p:[],src:d};P(x,!1),s.cmds.push(x),p=!1;continue}if(d.charCodeAt(0)===48&&(d.charCodeAt(1)===32||d.charCodeAt(1)===9)){let E=2;while(d.charCodeAt(E)===32||d.charCodeAt(E)===9)E++;let M=E;while(M<d.length&&d.charCodeAt(M)!==32&&d.charCodeAt(M)!==9)M++;let x=d.slice(E,M);if(!Ct.has(x)){if(C||a)continue;if(!s)y(t);let A=d.slice(E),L={t:0,text:A};if(x.charCodeAt(0)===33)L.meta=x;if(f=null,p&&!s.org){let F=He(A);if(F)s.org=F}let D=A.match(Ve);if(D&&!s.movedTo){let F=D[1].trim().replace(/\\\\/g,"/");if(!/\\.(dat|ldr|mpd)$/i.test(F))F+=".dat";s.movedTo=q(F)}s.cmds.push(L);continue}}if(d.charCodeAt(0)===49&&(d.charCodeAt(1)===32||d.charCodeAt(1)===9)&&!a&&!C){let E=kt(d);if(E){if(!s)y(t);P(E,!1),s.cmds.push(E),p=!1;continue}}let S=d.split(/\\s+/);if(+S[0]===0){let E=d.slice(1).trim();if(S[1]==="FILE"){m(),C=!1,y(E.slice(5));continue}if(S[1]==="NOFILE"){g(),s=null,C=!0;continue}if(S[1]==="!DATA"){m(),g(),s=null,C=!1,a={name:E.slice(5).trim(),chunks:[]};continue}if(C)continue;if(a){if(S[1]==="!:")a.chunks.push(S.slice(2).join(""));continue}if(!s)y(t);let M={t:0,text:E};if(S[1]==="STEP")M.step=!0,l=[],f=null;else if(S[1]==="BFC")M.bfc=S.slice(2).join(" ");else if(S[1]==="ROTSTEP")if(M.meta="ROTSTEP",M.step=!0,l=[],f=null,(S[2]??"").toUpperCase()==="END")M.rotstep={x:0,y:0,z:0,mode:"END"};else{let A=(S[5]??"REL").toUpperCase();M.rotstep={x:+S[2]||0,y:+S[3]||0,z:+S[4]||0,mode:["REL","ABS","ADD"].includes(A)?A:"REL"}}else if(S[1]==="BUFEXCHG"){M.meta="BUFEXCHG";let A=(S[2]??"").toUpperCase();M.bufexchg={op:A==="RETRIEVE"?"RETRIEVE":"STORE",buf:S[3]??"A"}}else if(S[1]?.startsWith("!"))M.meta=S[1];if(p&&!s.org){let A=He(E);if(A)s.org=A}if(S[1]==="!TEXMAP"){let A=(S[2]??"").toUpperCase();if(f=null,A==="START"||A==="NEXT"){let L=Lt(E.replace(/^!TEXMAP\\s+\\S+/i,""),A==="NEXT");if(M.texmap={op:A,...L?{map:L}:{}},L)if((s.texmaps??=[]).push(L),A==="START")l.push({map:L,fallback:!1});else f=L}else if(A==="FALLBACK"){M.texmap={op:A};let L=l[l.length-1];if(L)L.fallback=!0}else if(A==="END")M.texmap={op:A},l.pop()}else if(S[1]==="!:"){f=null;let A=Ge(S.slice(2));if(A)P(A,!0),M.geom=A}else f=null;let x=E.match(Ve);if(x&&!s.movedTo){let A=x[1].trim().replace(/\\\\/g,"/");if(!/\\.(dat|ldr|mpd)$/i.test(A))A+=".dat";s.movedTo=q(A)}s.cmds.push(M);continue}if(a||C)continue;if(!s)y(t);let w=Ge(S);if(!w)continue;P(w,!1),s.cmds.push(w),p=!1}return g(),c?{main:i,files:o,data:c}:{main:i,files:o}}var Kt=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,g,p,y]=e,[C,u,m,P,b,d,S,k,w,E,M,x]=t;return[s*C+i*u+c*m+n,a*C+l*u+f*m+r,g*C+p*u+y*m+o,s*P+i*S+c*E,s*b+i*k+c*M,s*d+i*w+c*x,a*P+l*S+f*E,a*b+l*k+f*M,a*d+l*w+f*x,g*P+p*S+y*E,g*b+p*k+y*M,g*d+p*w+y*x]}var Pe=[0,0,0,1,0,0,0,1,0,0,0,1];var Xe=new WeakMap,Ft=/^(s|8|48)\\//;function Ee(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&&Ft.test(o.file))?"part":"model";return Xe.set(n,r),r}var We=new WeakMap;function et(e){let t=We.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 We.set(e,t),t}var _e=(e)=>e>16777215?"0x"+e.toString(16).toUpperCase():String(e),Rt=(e)=>e.t===0?"0 "+e.text:e.t===1?`1 ${_e(e.color)} ${e.m.join(" ")} ${e.file}`:e.src?e.src:`${e.t} ${_e(e.color)} ${e.p.join(" ")}`,Te=(e,t)=>`${q(e)}#${t}`;function Ut(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:Te(e.name,t),cmds:n}}function tt(e,t){return[`0 ldr: own geometry of ${e.name}, step ${t}`,...Ut(e,t).cmds.map(Rt)].join(`\n`)+`\n`}function Dt(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,g,p]=e,y=a*p-l*g,C=-(c*p-l*f),u=c*g-a*f,m=o*y+s*C+i*u;if(!Number.isFinite(m)||Math.abs(m)<0.000000000001)return null;let P=1/m,b=[y*P,-(s*p-i*g)*P,(s*l-i*a)*P,C*P,(o*p-i*f)*P,-(o*l-i*c)*P,u*P,-(o*g-s*f)*P,(o*a-s*c)*P];return[-(b[0]*t+b[1]*n+b[2]*r),-(b[3]*t+b[4]*n+b[5]*r),-(b[6]*t+b[7]*n+b[8]*r),...b]}var Ot=(e)=>String(+e.toFixed(6)||0),Ke=(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(Ot).join(" "),r=`0 ldr: ${e} with a model-level !TEXMAP\n0 BFC CERTIFY CCW\n0 !TEXMAP START ${t.method} ${n} ${Ke(t.texture)}${t.glossmap?" GLOSSMAP "+Ke(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-${Dt(r)}`,source:r}}var zt=(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 Bt(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=Bt(s.x,s.y,s.z);r=s.mode==="ABS"?{abs:!0,m:i,rotstep:s}:s.mode==="ADD"&&r?{abs:r.abs,m:zt(r.m,i),rotstep:s}:{abs:!1,m:i,rotstep:s}}n.push(r)}return n.push(r),Ye.set(e,n),n}function Nt(e,t={}){let n=[],r=t.maxDepth??64,o=t.looseGeometry!==!1,s=!!t.textures,i=new Map,c=(l,f)=>{let g=l.name+"#"+f,p=i.get(g);if(!p){let y;p=Object.assign(()=>y??=tt(l,f),{file:l,step:f}),i.set(g,p)}return p},a=(l,f,g,p,y,C,u,m)=>{let P=l.files.get(f);if(!P||u>r)return;let b=0,d=ot(P),S=o?et(P):[],k=0,w=(M,x,A,L,D,F,v)=>{let h={part:M,color:x,m:A,step:L[0],steps:L,localStep:D,path:y};if(F)h.embedded=!0;if(v){let R=rt(M,v);h.texPart=R.name,h.texSource=R.source}let T=d[D];if(T)h.view=T;return n.push(h),h},E=(M)=>{while(k<S.length&&S[k]<=M){let x=S[k++];w(Te(P.name,x),p,g,[...C,x],x,!1,null).source=c(P,x)}};for(let M of P.cmds){if(M.t===0&&M.step){b++;continue}let x=M;if(x.t>=2||x.t===0&&x.geom&&x.geom.t>=2){E(b);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 A=x.color===16?p:x.color,L=Qe(g,x.m),D=[...C,b],F=s?x.tex??m:null,v=F?nt(x.m):null,h=F&&v?qe(F,v):null;if(l.files.has(x.file)){if(Ee(l,x.file)==="model"){a(l,x.file,L,A,y+"/"+x.file,D,u+1,h);continue}w(x.file,A,L,D,b,!0,h);continue}let T=t.resolveModel?.(x.file);if(T){a(T,T.main,L,A,y+"/"+x.file,D,u+1,h);continue}w(x.file,A,L,D,b,!1,h)}E(1/0)};if(Ee(e,e.main)==="part"){if(e.files.get(e.main))n.push({part:e.main,color:16,m:[...Pe],step:0,steps:[0],localStep:0,path:e.main,embedded:!0});return n}return a(e,e.main,Pe,16,e.main,[],0,null),n}function st(e,t="main.ldr",n){return Nt(Ze(e,t,{geometryText:!0}),n)}var it=(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,at=new WeakMap;function Le(e,t){let n=at.get(e);if(!n)at.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((p,y)=>{c.push(p[0]),a.push(p[1]);for(let C=0;C<12;C++)i[y*12+C]=p[2+C]});let l=null,f=0,g=0;if(o.mask){f=o.mask[0],g=o.mask[1];let p=o.mask[2];l=new Uint8Array(p.length);for(let y=0;y<p.length;y++)l[y]=p.charCodeAt(y)===49?1:0}return n.set(t,r={nStuds:s,studM:i,kind:c,color:a,mask:l,nx:f,nz:g}),r}var ie=1073741824;class Ie{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 ye=(e,t,n)=>e>-ie&&e<ie&&t>-ie&&t<ie&&n>-ie&&n<ie,fe=2147483647;function $t(e,t,n){let o=[],s=[],i=[],c=[],a=[],l=[],f=[],g=[],p=new Ie(e.length*2),y=[],C=[];for(let v=0;v<e.length;v++){let h=e[v],T=h.m,R=t.parts[h.part];if(!R||!R.mask||!it(T))continue;let I=R.bbox,U=1/0,O=-1/0,K=1/0,H=-1/0;for(let N=0;N<2;N++)for(let G=0;G<2;G++){let X=N?I[3]:I[0],Y=G?I[5]:I[2],W=T[0]+T[3]*X+T[5]*Y,_=T[2]+T[9]*X+T[11]*Y;if(W<U)U=W;if(W>O)O=W;if(_<K)K=_;if(_>H)H=_}let z=a.length;o.push(U),s.push(O),i.push(K),c.push(H),a.push(v),l.push(Le(t,h.part)),f.push(I[0]),g.push(I[2]);let B=Math.round((T[1]+I[4])*2);for(let N=Math.floor(U/40);N<=Math.floor(O/40);N++)for(let G=Math.floor(K/40);G<=Math.floor(H/40);G++){if(!ye(B,N,G))continue;let X=C.length;C.push(z),y.push(p.put(B,N,G,X))}}let u=[0,5,-5,5,-5],m=[0,5,5,-5,-5],P=NaN,b=NaN,d=NaN,S=-1,k=(v,h,T,R)=>{let I=Math.round(h*2),U=Math.floor(v/40),O=Math.floor(T/40);if(!ye(I,U,O))return fe;let K=fe;if(I!==P||U!==b||O!==d)P=I,b=U,d=O,S=p.get(I,U,O);for(let H=S;H>=0;H=y[H]){let z=C[H];if(a[z]===R||!(v-6>=o[z]-0.5&&v+6<=s[z]+0.5&&T-6>=i[z]-0.5&&T+6<=c[z]+0.5))continue;let B=e[a[z]].m,N=l[z],G=f[z],X=g[z],Y=v-B[0],W=h-B[1],_=T-B[2],Z=B[3]*Y+B[6]*W+B[9]*_,J=B[5]*Y+B[8]*W+B[11]*_,{nx:ee,nz:oe,mask:ae}=N,se=!0;for(let Q=0;Q<5;Q++){let te=Math.floor((Z+u[Q]-G)/20),ne=Math.floor((J+m[Q]-X)/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[z]];if(Q<K)K=Q}}return K},w=0;for(let v of e){let h=Le(t,v.part);if(h)w+=h.nStuds}let E=new Uint8Array(w),M=new Uint8Array(w),x=new Ie(w),A=0,L=n?new Int32Array(w).fill(fe):void 0;for(let v=0,h=0;v<e.length;v++){let T=e[v],R=Le(t,T.part);if(!R)continue;let I=T.m,U=R.studM,O=I[0],K=I[1],H=I[2],z=I[3],B=I[4],N=I[5],G=I[6],X=I[7],Y=I[8],W=I[9],_=I[10],Z=I[11];for(let J=0;J<R.nStuds;J++,h++){let ee=J*12,oe=U[ee+4],ae=U[ee+7],se=U[ee+10];if(!(Math.abs(G*oe+X*ae+Y*se-1)<0.001&&Math.abs(z*oe+B*ae+N*se)<0.001&&Math.abs(W*oe+_*ae+Z*se)<0.001))continue;M[h]=1;let Q=U[ee],te=U[ee+1],ne=U[ee+2],Re=O+z*Q+B*te+N*ne,Ue=K+G*Q+X*te+Y*ne,De=H+W*Q+_*te+Z*ne,Oe=k(Re,Ue,De,v);if(Oe!==fe){if(E[h]=1,A++,L)L[h]=Oe}let pe=Math.round(Re),me=Math.round(Ue),he=Math.round(De);if(!ye(pe,me,he))continue;if(!n){x.put(pe,me,he,1);continue}let ze=n[v],Be=x.get(pe,me,he);if(Be<0||ze<Be)x.put(pe,me,he,ze)}}let D=new Uint8Array(e.length),F=n?new Int32Array(e.length).fill(fe):void 0;for(let v=0;v<e.length;v++){let h=e[v],T=t.parts[h.part];if(!T||!T.under||!it(h.m))continue;let R=T.bbox,I=Math.round((R[3]-R[0])/20),U=Math.round((R[5]-R[2])/20);if(!I||!U||I*U>4096)continue;let O=h.m,K=!0,H=0;for(let z=0;z<I&&K;z++)for(let B=0;B<U;B++){let N=R[0]+10+20*z,G=R[2]+10+20*B,X=O[0]+O[3]*N+O[5]*G,Y=O[2]+O[9]*N+O[11]*G,W=Math.round(X),_=Math.round(O[1]+R[4]),Z=Math.round(Y),J=ye(W,_,Z)?x.get(W,_,Z):-1;if(J<0){K=!1;break}if(J>H)H=J}if(K){if(D[v]=1,F)F[v]=H}}return{nStuds:w,studHidden:E,studUp:M,underHidden:D,studsHidden:A,studHideStep:L,underHideStep:F}}function jt(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)=>a.steps.map((l)=>String(l).padStart(6,"0")).join(".")),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=jt(e,t,n);return $t(r.all,t,r.nSteps>1?r.stepOf:void 0)}var Fe="https://ldr-demo.vercel.app/cdn/v1/",ke=new Map,we=new Map;function lt(e=Fe,t=fetch){let n=ke.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(()=>ke.delete(e)),ke.set(e,n);return n}var Vt=(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"),ve=(e,t)=>Vt(e)?[e[0]+t,e[1],e[2]]:Array.isArray(e)?e.map((n)=>ve(n,t)):e&&typeof e==="object"?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,ve(r,t)])):e;function Ht(e,t={}){let n=[],r=0,o={},s={};for(let p of e){let y=p.buffer;if(!y)throw Error("ldr: mergePacks needs packs from decodePack/loadPack");let C=new DataView(y).getUint32(0,!0),u=new Uint8Array(y,4+C),m=r;n.push(u),r+=u.byteLength;let P=(4-r%4)%4;if(P)n.push(new Uint8Array(P)),r+=P;for(let[b,d]of Object.entries(p.header.parts??{}))if(!(b in o))o[b]=ve(d,m);for(let[b,d]of Object.entries(p.header.studKinds??{}))if(!(b in s))s[b]=ve(d,m)}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 g=l;for(let p of n)f.set(p,g),g+=p.byteLength;return de(f.buffer)}async function Gt(e,t={}){let n=t.cdn??Fe,r=t.fetch??fetch,o=t.gap??16384,s=await lt(n,r),i=[...new Set([...e].map(q))],c=[],a=[];for(let u of i){if(we.has(n+u))continue;let m=s.parts[u];if(m)a.push({name:u,off:m[0],len:m[1],file:m[2]??0});else c.push(u)}a.sort((u,m)=>u.file-m.file||u.off-m.off);let l=[];for(let u of a){let m=l[l.length-1];if(m&&m.file===u.file&&u.off-m.end<=o)m.end=Math.max(m.end,u.off+u.len),m.items.push(u);else l.push({file:u.file,start:u.off,end:u.off+u.len,items:[u]})}let f=0,g=0,p=async()=>{while(g<l.length){let u=l[g++],m=await r(new URL(s.archives[u.file],n).href,{headers:{Range:`bytes=${u.start}-${u.end-1}`}});if(!m.ok)throw Error(`ldr: parts CDN ${m.status}`);let P=new Uint8Array(await m.arrayBuffer());if(m.status===200)P=P.subarray(u.start,u.end);f+=P.byteLength;for(let b of u.items){let d=je(P.subarray(b.off-u.start,b.off-u.start+b.len)),S=d.buffer.slice(d.byteOffset,d.byteOffset+d.byteLength);we.set(n+b.name,de(S))}}};await Promise.all(Array.from({length:Math.min(t.concurrency??24,l.length)},p));let y=i.filter((u)=>we.has(n+u)).map((u)=>we.get(n+u));return{pack:y.length?Ht(y,{colors:s.colors}):de(Xt(s.colors)),missing:c,requests:l.length,bytes:f}}function Xt(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 ct(e,t={}){let n=performance.now(),r=t.fetch??fetch,o=lt(t.cdn??Fe,r);o.catch(()=>{});let s=t.text?e:await r(e).then((m)=>{if(!m.ok)throw Error(`ldr: ${m.status} fetching ${e}`);return m.text()}),i=performance.now(),c=t.name??(t.text?"main.ldr":decodeURIComponent(e.split(/[?#]/)[0].split("/").pop()||"main.ldr")),a=st(s,c,{looseGeometry:!1}),l=performance.now();t.onParsed?.(a),await o;let{pack:f,missing:g,requests:p,bytes:y}=await Gt(a.filter((m)=>!m.embedded).map((m)=>m.part),t),C=performance.now(),u=t.cull?xe(a,f.header,t.textures!==!1):void 0;return{insts:a,pack:f,missing:g,requests:p,bytes:y,cull:u,timings:{fetchModel:i-n,parse:l-i,parts:C-l,...u?{cull:performance.now()-C}:{}}}}self.onmessage=async(e)=>{let{id:t,source:n,opts:r}=e.data;try{let o=await ct(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';
|
|
2492
|
+
|
|
2493
|
+
// ../../../../../../../tmp/ldr-build-NB5kkP/src/cdn.ts
|
|
2494
|
+
var worker;
|
|
2495
|
+
var seq = 0;
|
|
2496
|
+
var pending = new Map;
|
|
2497
|
+
var pendingInsts = new Map;
|
|
2498
|
+
var pendingCull = new Map;
|
|
2499
|
+
function getWorker() {
|
|
2500
|
+
if (worker !== undefined)
|
|
2501
|
+
return worker;
|
|
2502
|
+
try {
|
|
2503
|
+
if (typeof Worker === "undefined" || typeof Blob === "undefined" || typeof URL?.createObjectURL !== "function" || !load_worker_gen_default)
|
|
2504
|
+
return worker = null;
|
|
2505
|
+
const url = URL.createObjectURL(new Blob([load_worker_gen_default], { type: "text/javascript" }));
|
|
2506
|
+
const w = new Worker(url, { type: "module", name: "ldr-load" });
|
|
2507
|
+
w.onmessage = (e) => {
|
|
2508
|
+
const d = e.data;
|
|
2509
|
+
if (d.insts) {
|
|
2510
|
+
pendingInsts.get(d.id)?.(d.insts);
|
|
2511
|
+
pendingInsts.delete(d.id);
|
|
2512
|
+
return;
|
|
2513
|
+
}
|
|
2514
|
+
const map = d.cull || d.error && !pending.has(d.id) ? pendingCull : pending;
|
|
2515
|
+
const p = map.get(d.id);
|
|
2516
|
+
if (!p)
|
|
2517
|
+
return;
|
|
2518
|
+
map.delete(d.id);
|
|
2519
|
+
d.error ? p.rej(new Error(d.error)) : p.res(d);
|
|
2520
|
+
};
|
|
2521
|
+
w.onerror = (e) => {
|
|
2522
|
+
e.preventDefault?.();
|
|
2523
|
+
worker = null;
|
|
2524
|
+
w.terminate();
|
|
2525
|
+
const err = new Error("ldr: load worker failed: " + (e.message || "error"));
|
|
2526
|
+
err.workerFailed = true;
|
|
2527
|
+
for (const m of [pending, pendingCull]) {
|
|
2528
|
+
for (const p of m.values())
|
|
2529
|
+
p.rej(err);
|
|
2530
|
+
m.clear();
|
|
2531
|
+
}
|
|
2532
|
+
};
|
|
2533
|
+
return worker = w;
|
|
2534
|
+
} catch {
|
|
2535
|
+
return worker = null;
|
|
2536
|
+
}
|
|
2537
|
+
}
|
|
2538
|
+
var abs = (u) => {
|
|
2539
|
+
try {
|
|
2540
|
+
return new URL(u, globalThis.location?.href).href;
|
|
2541
|
+
} catch {
|
|
2542
|
+
return u;
|
|
2543
|
+
}
|
|
2544
|
+
};
|
|
2545
|
+
function prepareInWorker(w, source, o) {
|
|
2546
|
+
const id = ++seq;
|
|
2547
|
+
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 };
|
|
2548
|
+
const name = o.name ?? (o.text ? undefined : decodeURIComponent(source.split(/[?#]/)[0].split("/").pop() || "main.ldr"));
|
|
2549
|
+
let insts;
|
|
2550
|
+
pendingInsts.set(id, (v) => {
|
|
2551
|
+
insts = v;
|
|
2552
|
+
});
|
|
2553
|
+
const cull = new Promise((res, rej) => pendingCull.set(id, { res, rej }));
|
|
2554
|
+
cull.catch(() => {});
|
|
2555
|
+
return new Promise((res, rej) => {
|
|
2556
|
+
pending.set(id, { res, rej });
|
|
2557
|
+
w.postMessage({ id, source: o.text ? source : abs(source), opts: { ...opts, name } });
|
|
2558
|
+
}).then(async (d) => {
|
|
2559
|
+
const pack = decodePack(d.buffer);
|
|
2560
|
+
let done = false;
|
|
2561
|
+
cull.then(() => done = true, () => done = true);
|
|
2562
|
+
await warmPackGeometry(pack, () => done);
|
|
2563
|
+
const c = await cull;
|
|
2564
|
+
pendingInsts.delete(id);
|
|
2565
|
+
return { insts, pack, missing: d.missing, requests: d.requests, bytes: d.bytes, timings: { ...d.timings, cull: c.ms }, cull: c.cull };
|
|
2566
|
+
}, (e) => {
|
|
2567
|
+
pendingCull.delete(id);
|
|
2568
|
+
pendingInsts.delete(id);
|
|
2569
|
+
throw e;
|
|
2570
|
+
});
|
|
2571
|
+
}
|
|
2572
|
+
async function loadModel(source, o = {}) {
|
|
2573
|
+
const t0 = performance.now();
|
|
2574
|
+
const w = o.worker !== false && !o.fetch ? getWorker() : null;
|
|
2575
|
+
let prep, ranIn = "main";
|
|
2576
|
+
if (w) {
|
|
2577
|
+
try {
|
|
2578
|
+
prep = await prepareInWorker(w, source, o);
|
|
2579
|
+
ranIn = "worker";
|
|
2580
|
+
} catch (e) {
|
|
2581
|
+
if (!e?.workerFailed)
|
|
2582
|
+
throw e;
|
|
2583
|
+
prep = await prepareModel(source, o);
|
|
2584
|
+
}
|
|
2585
|
+
} else
|
|
2586
|
+
prep = await prepareModel(source, o);
|
|
2587
|
+
const t3 = performance.now();
|
|
2588
|
+
const obj = createLdrObject(prep.insts, prep.pack, prep.cull ? { ...o, precomputedCull: prep.cull } : o);
|
|
2589
|
+
for (const m of prep.missing)
|
|
2257
2590
|
if (!obj.stats.missing.includes(m))
|
|
2258
2591
|
obj.stats.missing.push(m);
|
|
2259
2592
|
const t4 = performance.now();
|
|
2260
|
-
return Object.assign(obj, {
|
|
2593
|
+
return Object.assign(obj, {
|
|
2594
|
+
pack: prep.pack,
|
|
2595
|
+
instances: prep.insts,
|
|
2596
|
+
requests: prep.requests,
|
|
2597
|
+
bytes: prep.bytes,
|
|
2598
|
+
ranIn,
|
|
2599
|
+
timings: { ...prep.timings, parts: t3 - t0 - prep.timings.fetchModel - prep.timings.parse, build: t4 - t3, total: t4 - t0 }
|
|
2600
|
+
});
|
|
2261
2601
|
}
|
|
2262
2602
|
export {
|
|
2263
2603
|
DEFAULT_PARTS_CDN,
|
|
@@ -2297,13 +2637,17 @@ export {
|
|
|
2297
2637
|
parseLDConfig,
|
|
2298
2638
|
parseModel,
|
|
2299
2639
|
parseTexMap,
|
|
2640
|
+
precomputeCull,
|
|
2641
|
+
prepareModel,
|
|
2300
2642
|
resolveTexture,
|
|
2301
2643
|
rotStepMatrix,
|
|
2644
|
+
sceneInstances,
|
|
2302
2645
|
sequenceSteps,
|
|
2303
2646
|
smoothNormals,
|
|
2304
2647
|
stepViewMatrix,
|
|
2305
2648
|
texWrapper,
|
|
2306
2649
|
texmapTriangleUV,
|
|
2307
2650
|
texmapUV,
|
|
2308
|
-
transformTexMap
|
|
2651
|
+
transformTexMap,
|
|
2652
|
+
warmPackGeometry
|
|
2309
2653
|
};
|