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