ldr 0.26.0 → 0.27.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 +3 -1
- package/dist/cli.js +11 -11
- package/dist/index.d.ts +1 -1
- package/dist/index.js +190 -27
- package/dist/node/index.js +198 -35
- package/dist/render.d.ts +9 -2
- package/dist/scene.d.ts +15 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -144,10 +144,12 @@ MPD-embedded parts, such as Studio/OMR unofficial parts or stickers, become part
|
|
|
144
144
|
| `lodEdgeMinPx` | `0.15` | LOD: draw only edge segments at least this many pixels long on screen. `0` = every segment. |
|
|
145
145
|
| `lodUnder` | `true` | LOD: skip undersides that can't be seen (camera behind every bottom face of a cluster's parts, or the body drawn as its closed bounding box). Lossless in the fidelity checks. |
|
|
146
146
|
|
|
147
|
-
`LdrObject`: `object`, `stats` (`instances`, `drawn`, `missing[]`, `studsHidden/Total`, `undersHidden/Total`, `buildMs`, `condBatches`, `texBatches`, `textures`, `glossmaps`, `clusters`), `stepCount`, `stepViews`, `texturesReady`, `setStep(n | null)`, `setEdges(on)`, `setConditionalLines(on)`, `setCulling(studs, undersides)`, `setSide(side)`, `setLod(on)`, `getBox(target?)`, `dispose()`.
|
|
147
|
+
`LdrObject`: `object`, `stats` (`instances`, `drawn`, `missing[]`, `studsHidden/Total`, `undersHidden/Total`, `buildMs`, `condBatches`, `texBatches`, `textures`, `glossmaps`, `clusters`), `stepCount`, `stepViews`, `texturesReady`, `setStep(n | null)`, `setEdges(on)`, `setConditionalLines(on)`, `setCulling(studs, undersides)`, `setSide(side)`, `setLod(on)`, `setGhost(on, { opacity, color, whiten }?)`, `getBox(target?)`, `dispose()`.
|
|
148
148
|
|
|
149
149
|
`setStep` doesn't rebuild anything: it compacts instance buffers, and culling is step-aware (a stud covered only by a later step's part stays visible). `stats` reflect the shown step.
|
|
150
150
|
|
|
151
|
+
`setGhost(true)` draws the steps still to come as a faint, whitened, depth-written ghost (like the LEGO Builder app). It is built once on first use, without edges, with the steps reversed so `setStep` stays a buffer compaction for it too. It honours the booklet isolate mask, and `getBox` ignores it. Off by default. Cost: about the same as drawing the whole model (Titanic, 9.7k bricks: 1.6 ms off, 2.5 ms on, 2.8 ms full model).
|
|
152
|
+
|
|
151
153
|
**Building instructions.** `parseModel(text, name, { callouts: true })` (or `loadModel(url, { callouts: true })`) sequences a
|
|
152
154
|
submodel placed N times in one step like a booklet: the first copy is built step by step (its instances get `mult = N`, the "xN"),
|
|
153
155
|
the other copies appear finished at the end of that step. `planStepViews(instances, pack.header.parts, stepOf, stepCount)` plans a
|
package/dist/cli.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// ../../../../../../../tmp/ldr-build-
|
|
3
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/cli.ts
|
|
4
4
|
import fs4 from "node:fs";
|
|
5
5
|
import zlib from "node:zlib";
|
|
6
6
|
|
|
7
|
-
// ../../../../../../../tmp/ldr-build-
|
|
7
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/node/build-pack.ts
|
|
8
8
|
import fs3 from "node:fs";
|
|
9
9
|
import path3 from "node:path";
|
|
10
10
|
|
|
11
|
-
// ../../../../../../../tmp/ldr-build-
|
|
11
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/node/resolver.ts
|
|
12
12
|
import fs from "node:fs";
|
|
13
13
|
import path from "node:path";
|
|
14
14
|
|
|
15
|
-
// ../../../../../../../tmp/ldr-build-
|
|
15
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/spec.ts
|
|
16
16
|
var norm = (s) => s.trim().toLowerCase().replace(/\\/g, "/").replace(/\/+/g, "/");
|
|
17
17
|
var COLOUR_ID_RE = /^[A-Za-z][A-Za-z0-9_]*$/;
|
|
18
18
|
var namedCodes = new Map;
|
|
@@ -723,7 +723,7 @@ function fileStepViews(f) {
|
|
|
723
723
|
return out;
|
|
724
724
|
}
|
|
725
725
|
|
|
726
|
-
// ../../../../../../../tmp/ldr-build-
|
|
726
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/model.ts
|
|
727
727
|
var CALLOUT_END = 999999;
|
|
728
728
|
var stepKey = (steps) => steps.map((x) => String(x).padStart(6, "0")).join(".") + "~";
|
|
729
729
|
function flatten(doc, opts = {}) {
|
|
@@ -1106,7 +1106,7 @@ function blendedColourHex(code) {
|
|
|
1106
1106
|
return "#" + [0, 1, 2].map((k) => (a[k] + b[k] >> 1).toString(16).padStart(2, "0")).join("").toUpperCase();
|
|
1107
1107
|
}
|
|
1108
1108
|
|
|
1109
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1109
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/node/resolver.ts
|
|
1110
1110
|
var TOP_STUD_RE = /^(stud|studa|stud2|stud2a|stud6|stud6a|stud10|stud15|stud2s|stud2s2|stud-logo\d*|stud2-logo\d*)\.dat$/i;
|
|
1111
1111
|
var UNDER_STUD_RE = /^(stud3|stud3a|stud4.*|stud12|stud16.*|stud18a)\.dat$/i;
|
|
1112
1112
|
var norm2 = (ref) => ref.trim().replace(/\\/g, "/").toLowerCase();
|
|
@@ -1376,11 +1376,11 @@ function collectDeps(lib, refs) {
|
|
|
1376
1376
|
return out;
|
|
1377
1377
|
}
|
|
1378
1378
|
|
|
1379
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1379
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/node/compile.ts
|
|
1380
1380
|
import fs2 from "node:fs";
|
|
1381
1381
|
import path2 from "node:path";
|
|
1382
1382
|
|
|
1383
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1383
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/node/lod.ts
|
|
1384
1384
|
import { MeshoptSimplifier, MeshoptEncoder } from "meshoptimizer";
|
|
1385
1385
|
await Promise.all([MeshoptSimplifier.ready, MeshoptEncoder.ready]);
|
|
1386
1386
|
function reorderMesh(P, N, C, I) {
|
|
@@ -1572,7 +1572,7 @@ function lodChain(P, C, I) {
|
|
|
1572
1572
|
return out;
|
|
1573
1573
|
}
|
|
1574
1574
|
|
|
1575
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1575
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/node/compile.ts
|
|
1576
1576
|
function loadColors(root) {
|
|
1577
1577
|
const map = new Map;
|
|
1578
1578
|
for (const l of fs2.readFileSync(path2.join(root, "LDConfig.ldr"), "latin1").split(/\r?\n/)) {
|
|
@@ -2209,7 +2209,7 @@ function encodePack(parts, studKinds, weld, extra, options = {}) {
|
|
|
2209
2209
|
return Buffer.concat([head, ...chunks.map((c) => new Uint8Array(c.buffer, c.byteOffset, c.byteLength))]);
|
|
2210
2210
|
}
|
|
2211
2211
|
|
|
2212
|
-
// ../../../../../../../tmp/ldr-build-
|
|
2212
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/node/build-pack.ts
|
|
2213
2213
|
function buildPack(o) {
|
|
2214
2214
|
const lib = new Library(o.ldrawRoot);
|
|
2215
2215
|
const refs = new Map;
|
|
@@ -2277,7 +2277,7 @@ function buildPack(o) {
|
|
|
2277
2277
|
return { data: encodePack(parts, kinds, comp.opts.weld, extra, { texture, lod: o.lod !== false, reorder: !!o.reorder }), parts: parts.size, studKinds: kinds.size, missing: [...missing], ...warnings.length ? { warnings } : {} };
|
|
2278
2278
|
}
|
|
2279
2279
|
|
|
2280
|
-
// ../../../../../../../tmp/ldr-build-
|
|
2280
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/cli.ts
|
|
2281
2281
|
var HELP = `ldr pack — build a parts pack for the ldr three.js renderer
|
|
2282
2282
|
|
|
2283
2283
|
Usage:
|
package/dist/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@ export { loadPack, decodePack, buildLdrScene, buildLdrSceneAsync, makeMaterial,
|
|
|
8
8
|
export { precomputeCull, sceneInstances } from "./cull.js";
|
|
9
9
|
export type { Pack, LdrParams, Inst, CullResult, BuildLdrSceneAsyncOptions, GlossMap } from "./render.js";
|
|
10
10
|
export { createLdrObject, createLdrObjectAsync } from "./scene.js";
|
|
11
|
-
export type { LdrObject, LdrObjectOptions, LdrStats, ColorSource } from "./scene.js";
|
|
11
|
+
export type { LdrObject, LdrObjectOptions, LdrStats, ColorSource, GhostOptions } from "./scene.js";
|
|
12
12
|
export { decompressPack, decodeModelText, modelFileName } from "./pack-io.js";
|
|
13
13
|
export { loadModel, loadParts, loadPartsIndex, mergePacks, prepareModel, bodyTriangles, estimateBudgetFromIndex, BudgetError, DEFAULT_PARTS_CDN } from "./cdn.js";
|
|
14
14
|
export type { LoadModelOptions, LoadedModel, LoadPartsOptions, PartsCdnIndex, PrepareOptions, PreparedModel } from "./cdn.js";
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/spec.ts
|
|
2
2
|
var norm = (s) => s.trim().toLowerCase().replace(/\\/g, "/").replace(/\/+/g, "/");
|
|
3
3
|
var COLOUR_ID_RE = /^[A-Za-z][A-Za-z0-9_]*$/;
|
|
4
4
|
var namedCodes = new Map;
|
|
@@ -707,7 +707,7 @@ function fileStepViews(f) {
|
|
|
707
707
|
viewMemo.set(f, out);
|
|
708
708
|
return out;
|
|
709
709
|
}
|
|
710
|
-
// ../../../../../../../tmp/ldr-build-
|
|
710
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/model.ts
|
|
711
711
|
var CALLOUT_END = 999999;
|
|
712
712
|
var stepKey = (steps) => steps.map((x) => String(x).padStart(6, "0")).join(".") + "~";
|
|
713
713
|
function flatten(doc, opts = {}) {
|
|
@@ -1089,7 +1089,7 @@ function blendedColourHex(code) {
|
|
|
1089
1089
|
const a = LDRAW_EXE_16[code - 256 >> 4], b = LDRAW_EXE_16[code - 256 & 15];
|
|
1090
1090
|
return "#" + [0, 1, 2].map((k) => (a[k] + b[k] >> 1).toString(16).padStart(2, "0")).join("").toUpperCase();
|
|
1091
1091
|
}
|
|
1092
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1092
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/instructions.ts
|
|
1093
1093
|
var MIN_VIS = 0.5;
|
|
1094
1094
|
var REORIENT = 0.35;
|
|
1095
1095
|
var deg = Math.PI / 180;
|
|
@@ -1457,10 +1457,10 @@ function planStepViews(insts, parts, stepOf, nSteps, o = {}) {
|
|
|
1457
1457
|
}
|
|
1458
1458
|
};
|
|
1459
1459
|
}
|
|
1460
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1460
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/render.ts
|
|
1461
1461
|
import * as THREE from "three";
|
|
1462
1462
|
|
|
1463
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1463
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/pack-io.ts
|
|
1464
1464
|
import { decompress } from "fzstd";
|
|
1465
1465
|
async function decompressPack(data) {
|
|
1466
1466
|
const u = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
@@ -1483,7 +1483,7 @@ function decodePack(buf) {
|
|
|
1483
1483
|
return { header, arr, bytes: buf.byteLength, buffer: buf };
|
|
1484
1484
|
}
|
|
1485
1485
|
|
|
1486
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1486
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/cull.ts
|
|
1487
1487
|
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;
|
|
1488
1488
|
var prepCache = new WeakMap;
|
|
1489
1489
|
function prepPart(H, part) {
|
|
@@ -1818,7 +1818,7 @@ function precomputeCull(instances, H, useTex = true) {
|
|
|
1818
1818
|
return cullCore(s.all, H, s.nSteps > 1 ? s.stepOf : undefined);
|
|
1819
1819
|
}
|
|
1820
1820
|
|
|
1821
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1821
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/render.ts
|
|
1822
1822
|
async function loadPack(url) {
|
|
1823
1823
|
const res = await fetch(url);
|
|
1824
1824
|
if (!res.ok)
|
|
@@ -1867,6 +1867,10 @@ function flatNormals(pos, idx) {
|
|
|
1867
1867
|
return n;
|
|
1868
1868
|
}
|
|
1869
1869
|
var geomCache = new WeakMap;
|
|
1870
|
+
var DECODE_CHUNK_VERTS = 65536;
|
|
1871
|
+
function geomCached(b, arr) {
|
|
1872
|
+
return !b || !!geomCache.get(arr)?.has(b);
|
|
1873
|
+
}
|
|
1870
1874
|
function geom(b, arr) {
|
|
1871
1875
|
if (!b)
|
|
1872
1876
|
return null;
|
|
@@ -2518,6 +2522,12 @@ class LdrLodRoot extends THREE.LOD {
|
|
|
2518
2522
|
}
|
|
2519
2523
|
}
|
|
2520
2524
|
}
|
|
2525
|
+
function fillBucketIds(bIds, fill, studBucket, j0, j1) {
|
|
2526
|
+
for (let j = j0;j < j1; j++) {
|
|
2527
|
+
const b = studBucket[j];
|
|
2528
|
+
bIds[b][fill[b]++] = j;
|
|
2529
|
+
}
|
|
2530
|
+
}
|
|
2521
2531
|
function* buildStudMeshesGen(insts, H, cull, arr, LOD, color, matOf, steps, colorIndex) {
|
|
2522
2532
|
const bKind = [], bMat = [];
|
|
2523
2533
|
const bAll = [];
|
|
@@ -2595,14 +2605,15 @@ function* buildStudMeshesGen(insts, H, cull, arr, LOD, color, matOf, steps, colo
|
|
|
2595
2605
|
sz[j] = a[2] + a[9] * b0 + a[10] * b1 + a[11] * b2;
|
|
2596
2606
|
}
|
|
2597
2607
|
}
|
|
2608
|
+
yield;
|
|
2598
2609
|
const bIds = bAll.map((n) => new Int32Array(n));
|
|
2599
|
-
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
}
|
|
2610
|
+
const bFill = new Int32Array(bAll.length);
|
|
2611
|
+
for (let j0 = 0;j0 < cull.nStuds; j0 += 262144) {
|
|
2612
|
+
if (j0)
|
|
2613
|
+
yield;
|
|
2614
|
+
fillBucketIds(bIds, bFill, studBucket, j0, Math.min(cull.nStuds, j0 + 262144));
|
|
2605
2615
|
}
|
|
2616
|
+
yield;
|
|
2606
2617
|
const studCl = new Int32Array(cull.nStuds), studSlot = new Int32Array(cull.nStuds);
|
|
2607
2618
|
const sMesh = [];
|
|
2608
2619
|
const allocClusters = (b, kind, g, ids, cs, c0, c1) => {
|
|
@@ -2981,7 +2992,10 @@ function* buildLdrSceneGen(insts, pack, P, color, mark) {
|
|
|
2981
2992
|
const bodyB = textured ? p.tbody : p.body;
|
|
2982
2993
|
const body = geom(bodyB, arr);
|
|
2983
2994
|
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)));
|
|
2995
|
+
let _coopH = 0;
|
|
2984
2996
|
for (const g of groups) {
|
|
2997
|
+
if (_coopH++)
|
|
2998
|
+
yield root;
|
|
2985
2999
|
const ids = Array.from(g, (i) => idsAll[i]);
|
|
2986
3000
|
let bodyIm = null;
|
|
2987
3001
|
const lv0 = [];
|
|
@@ -3102,6 +3116,19 @@ function* buildLdrSceneGen(insts, pack, P, color, mark) {
|
|
|
3102
3116
|
}
|
|
3103
3117
|
if (maxV === 0)
|
|
3104
3118
|
continue;
|
|
3119
|
+
let decV = 0;
|
|
3120
|
+
for (const p of partSet.values())
|
|
3121
|
+
if (p.body)
|
|
3122
|
+
for (const b of LOD && p.body.lod ? [p.body, ...p.body.lod] : [p.body]) {
|
|
3123
|
+
if (geomCached(b, arr))
|
|
3124
|
+
continue;
|
|
3125
|
+
geom(b, arr);
|
|
3126
|
+
decV += geomVerts(b);
|
|
3127
|
+
if (decV >= DECODE_CHUNK_VERTS) {
|
|
3128
|
+
decV = 0;
|
|
3129
|
+
yield root;
|
|
3130
|
+
}
|
|
3131
|
+
}
|
|
3105
3132
|
const bm = new THREE.BatchedMesh(members.length, Math.max(1, maxV), Math.max(1, maxI), mat);
|
|
3106
3133
|
bm.perObjectFrustumCulled = true;
|
|
3107
3134
|
bm.sortObjects = false;
|
|
@@ -3155,6 +3182,7 @@ function* buildLdrSceneGen(insts, pack, P, color, mark) {
|
|
|
3155
3182
|
};
|
|
3156
3183
|
cl.lv.push({ objs: [bm], err: 0 });
|
|
3157
3184
|
if (EDGES) {
|
|
3185
|
+
yield root;
|
|
3158
3186
|
const byPartIds = new Map;
|
|
3159
3187
|
for (const m of live) {
|
|
3160
3188
|
const a = byPartIds.get(m.part) || byPartIds.set(m.part, []).get(m.part);
|
|
@@ -3203,6 +3231,19 @@ function* buildLdrSceneGen(insts, pack, P, color, mark) {
|
|
|
3203
3231
|
}
|
|
3204
3232
|
if (!uV)
|
|
3205
3233
|
continue;
|
|
3234
|
+
let uDecV = 0;
|
|
3235
|
+
for (const p of uPartSet.values())
|
|
3236
|
+
if (p.under)
|
|
3237
|
+
for (const b of LOD && p.under.lod ? [p.under, ...p.under.lod] : [p.under]) {
|
|
3238
|
+
if (geomCached(b, arr))
|
|
3239
|
+
continue;
|
|
3240
|
+
geom(b, arr);
|
|
3241
|
+
uDecV += geomVerts(b);
|
|
3242
|
+
if (uDecV >= DECODE_CHUNK_VERTS) {
|
|
3243
|
+
uDecV = 0;
|
|
3244
|
+
yield root;
|
|
3245
|
+
}
|
|
3246
|
+
}
|
|
3206
3247
|
const ubm = new THREE.BatchedMesh(umembers.length, Math.max(1, uV), Math.max(1, uI), mat);
|
|
3207
3248
|
ubm.perObjectFrustumCulled = true;
|
|
3208
3249
|
ubm.sortObjects = false;
|
|
@@ -3573,18 +3614,23 @@ function yieldToMain() {
|
|
|
3573
3614
|
});
|
|
3574
3615
|
}
|
|
3575
3616
|
async function buildLdrSceneAsync(insts, pack, P, color, mark, opts = {}) {
|
|
3617
|
+
const { value, longestSliceMs, yields } = await runSliced(buildLdrSceneGen(insts, pack, P, color, mark), opts);
|
|
3618
|
+
value.stats = { ...value.stats, longestSliceMs: +longestSliceMs.toFixed(2), buildYields: yields };
|
|
3619
|
+
return value;
|
|
3620
|
+
}
|
|
3621
|
+
async function runSliced(g, opts = {}) {
|
|
3576
3622
|
const sliceMs = opts.sliceMs ?? 8;
|
|
3577
3623
|
const postPaint = opts.postPaintSliceMs ?? Math.max(sliceMs, 24);
|
|
3578
3624
|
let painting = typeof opts.onSlice === "function";
|
|
3579
3625
|
let effective = painting ? sliceMs : postPaint;
|
|
3580
|
-
const g = buildLdrSceneGen(insts, pack, P, color, mark);
|
|
3581
|
-
let r = g.next();
|
|
3582
3626
|
let sliceStart = performance.now();
|
|
3627
|
+
let r = g.next();
|
|
3583
3628
|
let longestSliceMs = 0;
|
|
3584
3629
|
let yields = 0;
|
|
3630
|
+
let maxStep = 0;
|
|
3585
3631
|
while (!r.done) {
|
|
3586
3632
|
const now = performance.now();
|
|
3587
|
-
if (now - sliceStart >= effective) {
|
|
3633
|
+
if (now - sliceStart + Math.min(Math.max(maxStep, effective / 3), effective / 2) >= effective) {
|
|
3588
3634
|
longestSliceMs = Math.max(longestSliceMs, now - sliceStart);
|
|
3589
3635
|
yields++;
|
|
3590
3636
|
if (painting && opts.onSlice) {
|
|
@@ -3597,12 +3643,12 @@ async function buildLdrSceneAsync(insts, pack, P, color, mark, opts = {}) {
|
|
|
3597
3643
|
await yieldToMain();
|
|
3598
3644
|
sliceStart = performance.now();
|
|
3599
3645
|
}
|
|
3646
|
+
const t = performance.now();
|
|
3600
3647
|
r = g.next();
|
|
3648
|
+
maxStep = Math.max(maxStep, performance.now() - t);
|
|
3601
3649
|
}
|
|
3602
3650
|
longestSliceMs = Math.max(longestSliceMs, performance.now() - sliceStart);
|
|
3603
|
-
|
|
3604
|
-
value.stats = { ...value.stats, longestSliceMs: +longestSliceMs.toFixed(2), buildYields: yields };
|
|
3605
|
-
return value;
|
|
3651
|
+
return { value: r.value, longestSliceMs, yields };
|
|
3606
3652
|
}
|
|
3607
3653
|
async function warmPackGeometry(pack, stop = () => false, sliceMs = 8) {
|
|
3608
3654
|
const { header: H, arr } = pack;
|
|
@@ -3626,8 +3672,27 @@ async function warmPackGeometry(pack, stop = () => false, sliceMs = 8) {
|
|
|
3626
3672
|
await new Promise((r) => setTimeout(r, 0));
|
|
3627
3673
|
}
|
|
3628
3674
|
}
|
|
3629
|
-
// ../../../../../../../tmp/ldr-build-
|
|
3675
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/scene.ts
|
|
3630
3676
|
import * as THREE2 from "three";
|
|
3677
|
+
function ghostMaterial(side, g) {
|
|
3678
|
+
const m = new THREE2.MeshStandardMaterial({ color: 16777215, roughness: 0.85, metalness: 0, side, transparent: false, depthWrite: true, opacity: g.opacity });
|
|
3679
|
+
m.blending = THREE2.CustomBlending;
|
|
3680
|
+
m.blendSrc = THREE2.SrcAlphaFactor;
|
|
3681
|
+
m.blendDst = THREE2.OneMinusSrcAlphaFactor;
|
|
3682
|
+
m.blendSrcAlpha = THREE2.OneFactor;
|
|
3683
|
+
m.blendDstAlpha = THREE2.OneMinusSrcAlphaFactor;
|
|
3684
|
+
const tint = new THREE2.Color(g.color);
|
|
3685
|
+
const u = { ldrGhostTint: { value: tint }, ldrGhostMix: { value: g.whiten } };
|
|
3686
|
+
m.onBeforeCompile = (sh) => {
|
|
3687
|
+
Object.assign(sh.uniforms, u);
|
|
3688
|
+
sh.fragmentShader = `uniform vec3 ldrGhostTint; uniform float ldrGhostMix;
|
|
3689
|
+
` + sh.fragmentShader.replace("#include <color_fragment>", `#include <color_fragment>
|
|
3690
|
+
diffuseColor.rgb = mix(diffuseColor.rgb, ldrGhostTint, ldrGhostMix);`);
|
|
3691
|
+
};
|
|
3692
|
+
m.customProgramCacheKey = () => "ldrGhost";
|
|
3693
|
+
m.userData.ldrGhost = u;
|
|
3694
|
+
return m;
|
|
3695
|
+
}
|
|
3631
3696
|
function colorFn(src, pack, fallback) {
|
|
3632
3697
|
const table = new Map;
|
|
3633
3698
|
const put = (k, v) => table.set(String(k), new THREE2.Color(typeof v === "string" ? v : v.hex));
|
|
@@ -3741,6 +3806,75 @@ function createLdrObjectInner(instances, pack, options, progressive) {
|
|
|
3741
3806
|
}
|
|
3742
3807
|
cur = null;
|
|
3743
3808
|
};
|
|
3809
|
+
let ghostOn = false, ghost = null, ghostBuild = null, ghostGen = 0;
|
|
3810
|
+
let shownStep = null, shownMask = null;
|
|
3811
|
+
const ghostOpts = { opacity: 0.2, color: 16777215, whiten: 0.75 };
|
|
3812
|
+
const ghostMats = new Map;
|
|
3813
|
+
const syncGhost = () => {
|
|
3814
|
+
if (!ghost)
|
|
3815
|
+
return;
|
|
3816
|
+
const show = ghostOn && shownStep != null && shownStep < uniq.length - 1;
|
|
3817
|
+
ghost.root.visible = show;
|
|
3818
|
+
if (show)
|
|
3819
|
+
ghost.setStep(uniq.length - 2 - shownStep, shownMask);
|
|
3820
|
+
};
|
|
3821
|
+
const disposeGhost = () => {
|
|
3822
|
+
ghostGen++;
|
|
3823
|
+
ghostBuild = null;
|
|
3824
|
+
if (!ghost)
|
|
3825
|
+
return;
|
|
3826
|
+
object.remove(ghost.root);
|
|
3827
|
+
ghost.root.traverse((x) => {
|
|
3828
|
+
if (x.isInstancedMesh)
|
|
3829
|
+
x.dispose();
|
|
3830
|
+
else if (x.isBatchedMesh)
|
|
3831
|
+
x.dispose();
|
|
3832
|
+
});
|
|
3833
|
+
for (const m of ghostMats.values())
|
|
3834
|
+
m.dispose();
|
|
3835
|
+
ghostMats.clear();
|
|
3836
|
+
ghost = null;
|
|
3837
|
+
};
|
|
3838
|
+
const buildGhost = () => ghostBuild ??= (async () => {
|
|
3839
|
+
const my = ghostGen;
|
|
3840
|
+
const n = uniq.length;
|
|
3841
|
+
const rev = new Int32Array(stepOf.length);
|
|
3842
|
+
for (let k = 0;k < rev.length; k++)
|
|
3843
|
+
rev[k] = n - 1 - stepOf[k];
|
|
3844
|
+
const so = { ...sceneOpts(), edges: false, cond: false, tex: false, steps: rev, cull: undefined };
|
|
3845
|
+
so.cull = cullCore(all, pack.header, rev);
|
|
3846
|
+
const g = await buildLdrSceneAsync(all, pack, so, color, () => {}, { postPaintSliceMs: 12 });
|
|
3847
|
+
if (my !== ghostGen) {
|
|
3848
|
+
g.root.traverse((x) => {
|
|
3849
|
+
if (x.isInstancedMesh || x.isBatchedMesh)
|
|
3850
|
+
x.dispose();
|
|
3851
|
+
});
|
|
3852
|
+
return;
|
|
3853
|
+
}
|
|
3854
|
+
const old = new Set;
|
|
3855
|
+
g.root.traverse((x) => {
|
|
3856
|
+
if (!x.isMesh)
|
|
3857
|
+
return;
|
|
3858
|
+
if (x.material)
|
|
3859
|
+
old.add(x.material);
|
|
3860
|
+
let m = ghostMats.get(x.material?.side ?? THREE2.FrontSide);
|
|
3861
|
+
if (!m)
|
|
3862
|
+
ghostMats.set(x.material?.side ?? THREE2.FrontSide, m = ghostMaterial(x.material?.side ?? THREE2.FrontSide, ghostOpts));
|
|
3863
|
+
x.material = m;
|
|
3864
|
+
x.castShadow = x.receiveShadow = false;
|
|
3865
|
+
x.renderOrder = 1;
|
|
3866
|
+
x.userData.ldrGhost = true;
|
|
3867
|
+
});
|
|
3868
|
+
for (const m of old)
|
|
3869
|
+
m.dispose();
|
|
3870
|
+
g.root.name = "ldr-ghost";
|
|
3871
|
+
if (!lodOn)
|
|
3872
|
+
g.setLod(false);
|
|
3873
|
+
g.setCull(cs, cu);
|
|
3874
|
+
ghost = g;
|
|
3875
|
+
object.add(g.root);
|
|
3876
|
+
syncGhost();
|
|
3877
|
+
})();
|
|
3744
3878
|
const multiStep = uniq.length > 1;
|
|
3745
3879
|
const drawnAt = (step, mask) => all.filter((i, k) => (step == null || stepOf[k] <= step) && (!mask || mask[k]) && pack.header.parts[i.part]).length;
|
|
3746
3880
|
const sceneOpts = () => ({ localColours: localColours.size ? localColours : undefined, cullStuds: cs, cullUnder: cu, edges: o.edges, side, cond: o.conditionalLines, 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 });
|
|
@@ -3773,7 +3907,12 @@ function createLdrObjectInner(instances, pack, options, progressive) {
|
|
|
3773
3907
|
if (!multiStep)
|
|
3774
3908
|
return;
|
|
3775
3909
|
const t0 = performance.now();
|
|
3910
|
+
shownStep = step;
|
|
3911
|
+
shownMask = mask;
|
|
3776
3912
|
Object.assign(stats, cur.setStep(step, mask), { drawn: drawnAt(step, mask), buildMs: performance.now() - t0 });
|
|
3913
|
+
if (ghostOn && step != null && !ghost)
|
|
3914
|
+
buildGhost();
|
|
3915
|
+
syncGhost();
|
|
3777
3916
|
};
|
|
3778
3917
|
const api = { texturesReady: Promise.resolve() };
|
|
3779
3918
|
const finish = () => {
|
|
@@ -3802,10 +3941,31 @@ function createLdrObjectInner(instances, pack, options, progressive) {
|
|
|
3802
3941
|
applyBuilt(buildLdrScene(all, pack, sceneOpts(), color, () => {}), t0);
|
|
3803
3942
|
} else
|
|
3804
3943
|
cur.setCull(a, b);
|
|
3944
|
+
ghost?.setCull(a, b);
|
|
3805
3945
|
},
|
|
3806
3946
|
setLod: (v) => {
|
|
3807
3947
|
lodOn = v;
|
|
3808
3948
|
cur.setLod(v);
|
|
3949
|
+
ghost?.setLod(v);
|
|
3950
|
+
},
|
|
3951
|
+
setGhost: (on, go = {}) => {
|
|
3952
|
+
ghostOn = on && multiStep;
|
|
3953
|
+
Object.assign(ghostOpts, Object.fromEntries(Object.entries(go).filter(([, v]) => v !== undefined)));
|
|
3954
|
+
for (const m of ghostMats.values()) {
|
|
3955
|
+
m.opacity = ghostOpts.opacity;
|
|
3956
|
+
const u = m.userData.ldrGhost;
|
|
3957
|
+
u.ldrGhostTint.value.set(ghostOpts.color);
|
|
3958
|
+
u.ldrGhostMix.value = ghostOpts.whiten;
|
|
3959
|
+
}
|
|
3960
|
+
if (!ghostOn) {
|
|
3961
|
+
syncGhost();
|
|
3962
|
+
return ghostBuild ?? Promise.resolve();
|
|
3963
|
+
}
|
|
3964
|
+
if (shownStep == null && !ghost)
|
|
3965
|
+
return Promise.resolve();
|
|
3966
|
+
const b = buildGhost();
|
|
3967
|
+
syncGhost();
|
|
3968
|
+
return b;
|
|
3809
3969
|
},
|
|
3810
3970
|
setSide: (s) => {
|
|
3811
3971
|
side = s;
|
|
@@ -3819,7 +3979,7 @@ function createLdrObjectInner(instances, pack, options, progressive) {
|
|
|
3819
3979
|
object.updateMatrixWorld(true);
|
|
3820
3980
|
target.makeEmpty();
|
|
3821
3981
|
object.traverse((x) => {
|
|
3822
|
-
if (x.isInstancedMesh && x.count && !x.userData.ldrLod) {
|
|
3982
|
+
if (x.isInstancedMesh && x.count && !x.userData.ldrLod && !x.userData.ldrGhost) {
|
|
3823
3983
|
x.computeBoundingBox();
|
|
3824
3984
|
const b = x.boundingBox.clone().applyMatrix4(x.matrixWorld);
|
|
3825
3985
|
target.union(b);
|
|
@@ -3827,7 +3987,10 @@ function createLdrObjectInner(instances, pack, options, progressive) {
|
|
|
3827
3987
|
});
|
|
3828
3988
|
return target;
|
|
3829
3989
|
},
|
|
3830
|
-
dispose:
|
|
3990
|
+
dispose: () => {
|
|
3991
|
+
disposeGhost();
|
|
3992
|
+
disposeCur();
|
|
3993
|
+
}
|
|
3831
3994
|
});
|
|
3832
3995
|
};
|
|
3833
3996
|
if (!progressive) {
|
|
@@ -3853,10 +4016,10 @@ function createLdrObjectInner(instances, pack, options, progressive) {
|
|
|
3853
4016
|
return finish();
|
|
3854
4017
|
})();
|
|
3855
4018
|
}
|
|
3856
|
-
// ../../../../../../../tmp/ldr-build-
|
|
4019
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/parts-cdn.ts
|
|
3857
4020
|
import { decompress as decompress2 } from "fzstd";
|
|
3858
4021
|
|
|
3859
|
-
// ../../../../../../../tmp/ldr-build-
|
|
4022
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/embedded.ts
|
|
3860
4023
|
function splitFiles(text, fallback) {
|
|
3861
4024
|
const files = new Map;
|
|
3862
4025
|
let cur = null, saw = false;
|
|
@@ -3928,7 +4091,7 @@ function embeddedKeys(text, names, fallback = "main.ldr") {
|
|
|
3928
4091
|
return out;
|
|
3929
4092
|
}
|
|
3930
4093
|
|
|
3931
|
-
// ../../../../../../../tmp/ldr-build-
|
|
4094
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/parts-cdn.ts
|
|
3932
4095
|
var DEFAULT_PARTS_CDN = "https://ldr-demo.vercel.app/cdn/v1/";
|
|
3933
4096
|
var indexCache = new Map;
|
|
3934
4097
|
var shardCache = new Map;
|
|
@@ -4160,10 +4323,10 @@ async function prepareModel(source, o = {}) {
|
|
|
4160
4323
|
return { insts, pack, missing, requests, bytes, cull, timings: { fetchModel: t1 - t0, parse: t2 - t1, parts: t3 - t2, ...cull ? { cull: performance.now() - t3 } : {} } };
|
|
4161
4324
|
}
|
|
4162
4325
|
|
|
4163
|
-
// ../../../../../../../tmp/ldr-build-
|
|
4326
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/load-worker.gen.ts
|
|
4164
4327
|
var load_worker_gen_default = 'var vt=ArrayBuffer,Z=Uint8Array,de=Uint16Array,Ct=Int16Array;var be=Int32Array,Le=function(e,t,n){if(Z.prototype.slice)return Z.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 Z(n-t);return r.set(e.subarray(t,n)),r},ce=function(e,t,n,r){if(Z.prototype.fill)return Z.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},Tt=function(e,t,n,r){if(Z.prototype.copyWithin)return Z.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 Lt=["invalid zstd data","window size too large (>2046MB)","invalid block type","FSE accuracy too high","match distance too far back","unexpected EOF"],J=function(e,t,n){var r=Error(t||Lt[e]);if(r.code=e,Error.captureStackTrace)Error.captureStackTrace(r,J);if(!n)throw r;return r},Ke=function(e,t,n){var r=0,s=0;for(;r<n;++r)s|=e[t++]<<(r<<3);return s},Et=function(e,t){return(e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24)>>>0},St=function(e,t){var n=e[0]|e[1]<<8|e[2]<<16;if(n==3126568&&e[3]==253){var r=e[4],s=r>>5&1,o=r>>2&1,i=r&3,a=r>>6;if(r&8)J(0);var u=6-s,c=i==3?4:i,f=Ke(e,u,c);u+=c;var l=a?1<<a:s,p=Ke(e,u,l)+(a==1&&256),d=p;if(!s){var w=1<<10+(e[5]>>3);d=w+(w>>3)*(e[5]&7)}if(d>2145386496)J(1);var y=new Z((t==1?p||d:t?0:d)+12);return y[0]=1,y[4]=4,y[8]=8,{b:u+l,y:0,l:0,d:f,w:t&&t!=1?t:y.subarray(12),e:d,o:new be(y.buffer,0,3),u:p,c:o,m:Math.min(131072,d)}}else if((n>>4|e[3]<<20)==25481893)return Et(e,4)+8;J(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,s=(e[t]&15)+5;if(s>n)J(3);var o=1<<s,i=o,a=-1,u=-1,c=-1,f=o,l=new vt(512+(o<<2)),p=new Ct(l,0,256),d=new de(l,0,256),w=new de(l,512,o),y=512+(o<<1),L=new Z(l,y,o),g=new Z(l,y+o);while(a<255&&i>0){var m=re(i+1),b=r>>3,h=(1<<m+1)-1,P=(e[b]|e[b+1]<<8|e[b+2]<<16)>>(r&7)&h,A=(1<<m)-1,E=h-i-1,T=P&A;if(T<E)r+=m,P=T;else if(r+=m+1,P>A)P-=E;if(p[++a]=--P,P==-1)i+=P,L[--f]=a;else i-=P;if(!P)do{var B=r>>3;u=(e[B]|e[B+1]<<8)>>(r&7)&3,r+=2,a+=u}while(u==3)}if(a>255||i)J(0);var v=0,F=(o>>1)+(o>>3)+3,Y=o-1;for(var _=0;_<=a;++_){var C=p[_];if(C<1){d[_]=-C;continue}for(c=0;c<C;++c){L[v]=_;do v=v+F&Y;while(v>=f)}}if(v)J(0);for(c=0;c<o;++c){var M=d[L[c]]++,k=g[c]=s-re(M);w[c]=(M<<k)-o}return[r+7>>3,{b:s,s:L,n:g,t:w}]},Pt=function(e,t){var n=0,r=-1,s=new Z(292),o=e[t],i=s.subarray(0,256),a=s.subarray(256,268),u=new de(s.buffer,268);if(o<128){var c=ue(e,t+1,6),f=c[0],l=c[1];t+=o;var p=f<<3,d=e[t];if(!d)J(0);var w=0,y=0,L=l.b,g=L,m=(++t<<3)-8+re(d);for(;;){if(m-=L,m<p)break;var b=m>>3;if(w+=(e[b]|e[b+1]<<8)>>(m&7)&(1<<L)-1,i[++r]=l.s[w],m-=g,m<p)break;b=m>>3,y+=(e[b]|e[b+1]<<8)>>(m&7)&(1<<g)-1,i[++r]=l.s[y],L=l.n[w],w=l.t[w],g=l.n[y],y=l.t[y]}if(++r>255)J(0)}else{r=o-127;for(;n<r;n+=2){var h=e[++t];i[n]=h>>4,i[n+1]=h&15}++t}var P=0;for(n=0;n<r;++n){var A=i[n];if(A>11)J(0);P+=A&&1<<A-1}var E=re(P)+1,T=1<<E,B=T-P;if(B&B-1)J(0);i[r++]=re(B)+1;for(n=0;n<r;++n){var A=i[n];++a[i[n]=A&&E+1-A]}var v=new Z(T<<1),F=v.subarray(0,T),Y=v.subarray(T);u[E]=0;for(n=E;n>0;--n){var _=u[n];ce(Y,n,_,u[n-1]=_+a[n]*(1<<E-n))}if(u[0]!=T)J(0);for(n=0;n<r;++n){var C=i[n];if(C){var M=u[C];ce(F,n,M,u[C]=M+(1<<E-C))}}return[t,{n:Y,b:E,s:F}]},kt=ue(new Z([81,16,99,140,49,198,24,99,12,33,196,24,99,102,102,134,70,146,4]),0,6)[1],It=ue(new Z([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],Bt=ue(new Z([32,132,16,66,102,70,68,68,68,68,36,73,2]),0,5)[1],We=function(e,t){var n=e.length,r=new be(n);for(var s=0;s<n;++s)r[s]=t,t+=1<<e[s];return r},Ee=new Z(new be([0,0,0,0,16843009,50528770,134678020,202050057,269422093]).buffer,0,36),Ft=We(Ee,0),Se=new Z(new be([0,0,0,0,0,0,0,0,16843009,50528770,117769220,185207048,252579084,16]).buffer,0,53),Rt=We(Se,3),le=function(e,t,n){var r=e.length,s=t.length,o=e[r-1],i=(1<<n.b)-1,a=-n.b;if(!o)J(0);var u=0,c=n.b,f=(r<<3)-8+re(o)-c,l=-1;for(;f>a&&l<s;){var p=f>>3,d=(e[p]|e[p+1]<<8|e[p+2]<<16)>>(f&7);u=(u<<c|d)&i,t[++l]=n.s[u],f-=c=n.n[u]}if(f!=a||l+1!=s)J(0)},Dt=function(e,t,n){var r=6,s=t.length,o=s+3>>2,i=o<<1,a=o+i;le(e.subarray(r,r+=e[0]|e[1]<<8),t.subarray(0,o),n),le(e.subarray(r,r+=e[2]|e[3]<<8),t.subarray(o,i),n),le(e.subarray(r,r+=e[4]|e[5]<<8),t.subarray(i,a),n),le(e.subarray(r),t.subarray(a),n)},Ut=function(e,t,n){var r,s=t.b,o=e[s],i=o>>1&3;t.l=o&1;var a=o>>3|e[s+1]<<5|e[s+2]<<13,u=(s+=3)+a;if(i==1){if(s>=e.length)return;if(t.b=s+1,n)return ce(n,e[s],t.y,t.y+=a),n;return ce(new Z(a),e[s])}if(u>e.length)return;if(i==0){if(t.b=u,n)return n.set(e.subarray(s,u),t.y),t.y+=a,n;return Le(e,s,u)}if(i==2){var c=e[s],f=c&3,l=c>>2&3,p=c>>4,d=0,w=0;if(f<2)if(l&1)p|=e[++s]<<4|(l&2&&e[++s]<<12);else p=c>>3;else if(w=l,l<2)p|=(e[++s]&63)<<4,d=e[s]>>6|e[++s]<<2;else if(l==2)p|=e[++s]<<4|(e[++s]&3)<<12,d=e[s]>>2|e[++s]<<6;else p|=e[++s]<<4|(e[++s]&63)<<12,d=e[s]>>6|e[++s]<<2|e[++s]<<10;++s;var y=n?n.subarray(t.y,t.y+t.m):new Z(t.m),L=y.length-p;if(f==0)y.set(e.subarray(s,s+=p),L);else if(f==1)ce(y,e[s++],L);else{var g=t.h;if(f==2){var m=Pt(e,s);d+=s-(s=m[0]),t.h=g=m[1]}else if(!g)J(0);(w?Dt:le)(e.subarray(s,s+=d),y.subarray(L),g)}var b=e[s++];if(b){if(b==255)b=(e[s++]|e[s++]<<8)+32512;else if(b>127)b=b-128<<8|e[s++];var h=e[s++];if(h&3)J(0);var P=[It,Bt,kt];for(var A=2;A>-1;--A){var E=h>>(A<<1)+2&3;if(E==1){var T=new Z([0,0,e[s++]]);P[A]={s:T.subarray(2,3),n:T.subarray(0,1),t:new de(T.buffer,0,1),b:0}}else if(E==2)r=ue(e,s,9-(A&1)),s=r[0],P[A]=r[1];else if(E==3){if(!t.t)J(0);P[A]=t.t[A]}}var B=t.t=P,v=B[0],F=B[1],Y=B[2],_=e[u-1];if(!_)J(0);var C=(u<<3)-8+re(_)-Y.b,M=C>>3,k=0,G=(e[M]|e[M+1]<<8)>>(C&7)&(1<<Y.b)-1;M=(C-=F.b)>>3;var I=(e[M]|e[M+1]<<8)>>(C&7)&(1<<F.b)-1;M=(C-=v.b)>>3;var N=(e[M]|e[M+1]<<8)>>(C&7)&(1<<v.b)-1;for(++b;--b;){var j=Y.s[G],X=Y.n[G],W=v.s[N],S=v.n[N],x=F.s[I],R=F.n[I];M=(C-=x)>>3;var D=1<<x,U=D+((e[M]|e[M+1]<<8|e[M+2]<<16|e[M+3]<<24)>>>(C&7)&D-1);M=(C-=Se[W])>>3;var H=Rt[W]+((e[M]|e[M+1]<<8|e[M+2]<<16)>>(C&7)&(1<<Se[W])-1);M=(C-=Ee[j])>>3;var z=Ft[j]+((e[M]|e[M+1]<<8|e[M+2]<<16)>>(C&7)&(1<<Ee[j])-1);if(M=(C-=X)>>3,G=Y.t[G]+((e[M]|e[M+1]<<8)>>(C&7)&(1<<X)-1),M=(C-=S)>>3,N=v.t[N]+((e[M]|e[M+1]<<8)>>(C&7)&(1<<S)-1),M=(C-=R)>>3,I=F.t[I]+((e[M]|e[M+1]<<8)>>(C&7)&(1<<R)-1),U>3)t.o[2]=t.o[1],t.o[1]=t.o[0],t.o[0]=U-=3;else{var V=U-(z!=0);if(V){if(U=V==3?t.o[0]-1:t.o[V],V>1)t.o[2]=t.o[1];t.o[1]=t.o[0],t.o[0]=U}else U=t.o[0]}for(var A=0;A<z;++A)y[k+A]=y[L+A];k+=z,L+=z;var O=k-U;if(O<0){var K=-O,q=t.e+O;if(K>H)K=H;for(var A=0;A<K;++A)y[k+A]=t.w[q+A];k+=K,H-=K,O=0}for(var A=0;A<H;++A)y[k+A]=y[O+A];k+=H}if(k!=L)while(L<y.length)y[k++]=y[L++];else k=y.length;if(n)t.y+=k;else y=Le(y,0,k)}else if(n){if(t.y+=p,L)for(var A=0;A<p;++A)y[A]=y[L+A]}else if(L)y=Le(y,L);return t.b=u,y}J(2)},Ot=function(e,t){if(e.length==1)return e[0];var n=new Z(t);for(var r=0,s=0;r<e.length;++r){var o=e[r];n.set(o,s),s+=o.length}return n};function ye(e,t){var n=[],r=+!t,s=0,o=0;for(;e.length;){var i=St(e,r||t);if(typeof i=="object"){if(r){if(t=null,i.w.length==i.u)n.push(t=i.w),o+=i.u}else n.push(t),i.e=0;for(;!i.l;){var a=Ut(e,i,t);if(!a)J(5);if(t)i.e=i.y;else n.push(a),o+=a.length,Tt(i.w,0,a.length),i.w.set(a,i.w.length-a.length)}s=i.b+i.c*4}else s=i;e=e.subarray(s)}return Ot(n,o)}async function Nt(e){let t=e instanceof Uint8Array?e:new Uint8Array(e),n=(r)=>r.buffer.slice(r.byteOffset,r.byteOffset+r.byteLength);if(t[0]===40&&t[1]===181&&t[2]===47&&t[3]===253)return n(ye(t));if(t[0]===31&&t[1]===139)return new Response(new Blob([t]).stream().pipeThrough(new DecompressionStream("gzip"))).arrayBuffer();return n(t)}async function Xe(e){return new TextDecoder().decode(await Nt(e))}var Ze=(e)=>decodeURIComponent(e.split(/[?#]/)[0].split("/").pop()||"main.ldr").replace(/\\.(zst|gz)$/i,"")||"main.ldr";function xe(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:(o)=>o&&(o[2]==="f32"?new Float32Array(e,r+o[0],o[1]):o[2]==="u16"?new Uint16Array(e,r+o[0],o[1]):o[2]==="u8"?new Uint8Array(e,r+o[0],o[1]):new Uint32Array(e,r+o[0],o[1])),bytes:e.byteLength,buffer:e}}var Q=(e)=>e.trim().toLowerCase().replace(/\\\\/g,"/").replace(/\\/+/g,"/"),ke=/^[A-Za-z][A-Za-z0-9_]*$/,Pe=new Map;function Ie(e){let t=e.toLowerCase(),n=2166136261;for(let s=0;s<t.length;s++)n^=t.charCodeAt(s),n=Math.imul(n,16777619);let r=-1-(n>>>0&1073741823);if(!Pe.has(r))Pe.set(r,t);return r}function Be(e){let t=e.charCodeAt(0)|32;if(t>=97&&t<=122&&ke.test(e))return Ie(e);if(/^0x/i.test(e))return parseInt(e,16);return+e}var Ye=/^~?\\s*moved\\s+to\\s+(.+)$/i,zt=new Set(["FILE","NOFILE","!DATA","!:","STEP","BFC","ROTSTEP","BUFEXCHG","!TEXMAP"]),st=new Set(["part","subpart","primitive","8_primitive","48_primitive","shortcut","helper"]),$t=new Set(["model","submodel","configuration"]),jt=/^(?:!?LDRAW_ORG|Unofficial|Official\\s+LCAD)\\s+(\\S+)/i;function Je(e){let t=jt.exec(e);if(!t)return;let n=t[1].toLowerCase().replace(/^unofficial_/,"");return st.has(n)||$t.has(n)?n:void 0}function Vt(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 _t(e,t=!1){let n=/^\\s*(\\S+)\\s+(.*)$/.exec(e);if(!n)return null;let r=n[1].toUpperCase(),s=r==="PLANAR"?9:r==="CYLINDRICAL"?10:r==="SPHERICAL"?11:0;if(!s)return null;let o=n[2].trim().split(/\\s+/);if(o.length<s+1)return null;let i=o.slice(0,s).map(Number);if(!i.every(Number.isFinite))return null;let a=n[2].trim();for(let l=0;l<s;l++)a=a.replace(/^\\S+\\s*/,"");let u=Vt(a);if(!u.length)return null;let c={method:r,p1:i.slice(0,3),p2:i.slice(3,6),p3:i.slice(6,9),texture:u[0]};if(s>=10)c.a=i[9];if(s===11)c.b=i[10];let f=u.findIndex((l,p)=>p>0&&l.toUpperCase()==="GLOSSMAP");if(f>0&&u[f+1])c.glossmap=u[f+1];if(t)c.next=!0;return c}var Ht=(e)=>{let t=e.replace(/[^A-Za-z0-9+/]/g,""),n=t+"=".repeat((4-t.length%4)%4),r=atob(n),s=new Uint8Array(r.length);for(let o=0;o<r.length;o++)s[o]=r.charCodeAt(o);return s};function Gt(e){let t=e.length,n=1,r=(c)=>c===32||c===9,s=()=>{while(n<t&&r(e.charCodeAt(n)))n++;let c=n;while(n<t&&!r(e.charCodeAt(n)))n++;return c<n?e.slice(c,n):null},o=s();if(o===null)return null;let i=Array(12);for(let c=0;c<12;c++){let f=s();if(f===null)return null;i[c]=+f}while(n<t&&r(e.charCodeAt(n)))n++;if(n>=t)return null;let a=e.slice(n),u=/[ \\t]{2,}|\\t/.test(a)?a.split(/\\s+/).join(" "):a;return{t:1,color:Be(o),m:i,file:Q(u)}}function qe(e){let t=+e[0];if(!(t>=1&&t<=5)||e.length<2)return null;let n=Be(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 ot(e,t="main.ldr",n={}){let r=!!n.geometryText,s=new Map,o=null,i="",a,u=null,c=[],f=null,l=()=>{if(!u)return;let m=Ht(u.chunks.join("")),b=m[0]===137&&m[1]===80&&m[2]===78&&m[3]===71;(a??=new Map).set(Q(u.name),{name:u.name,bytes:m,...b?{mime:"image/png"}:{}}),u=null},p=!0,d=(m)=>{if(l(),o={name:Q(m),cmds:[]},s.set(o.name,o),!i)i=o.name;c=[],f=null,p=!0},w=!1,y=!1,L=()=>{if(y)return;y=!0,s.clear(),o=null,i=""},g=(m,b)=>{if(f){m.tex=f,f=null;return}let h=c[c.length-1];if(!h)return;if(h.fallback){if(!b)m.fallback=!0}else m.tex=h.map};for(let m of e.split(`\n`)){let b=m.trim();if(!b)continue;if(r&&b.charCodeAt(0)>=50&&b.charCodeAt(0)<=53&&(b.charCodeAt(1)===32||b.charCodeAt(1)===9)){if(u||w)continue;if(!o)d(t);let E=b.slice(2).trimStart(),T=E.search(/\\s/),B={t:b.charCodeAt(0)-48,color:Be(T<0?E:E.slice(0,T)),p:[],src:b};g(B,!1),o.cmds.push(B),p=!1;continue}if(b.charCodeAt(0)===48&&(b.charCodeAt(1)===32||b.charCodeAt(1)===9)){let E=2;while(b.charCodeAt(E)===32||b.charCodeAt(E)===9)E++;let T=E;while(T<b.length&&b.charCodeAt(T)!==32&&b.charCodeAt(T)!==9)T++;let B=b.slice(E,T);if(!zt.has(B)){if(w||u)continue;if(!o)d(t);let v=b.slice(E),F={t:0,text:v};if(B.charCodeAt(0)===33)F.meta=B;if(f=null,p&&!o.org){let _=Je(v);if(_)o.org=_}let Y=v.match(Ye);if(Y&&!o.movedTo){let _=Y[1].trim().replace(/\\\\/g,"/");if(!/\\.(dat|ldr|mpd)$/i.test(_))_+=".dat";o.movedTo=Q(_)}o.cmds.push(F);continue}}if(b.charCodeAt(0)===49&&(b.charCodeAt(1)===32||b.charCodeAt(1)===9)&&!u&&!w){let E=Gt(b);if(E){if(!o)d(t);g(E,!1),o.cmds.push(E),p=!1;continue}}let h=b.split(/\\s+/);if(+h[0]===0){let E=b.slice(1).trim();if(h[1]==="FILE"){L(),w=!1,d(E.slice(5));continue}if(h[1]==="NOFILE"){l(),o=null,w=!0;continue}if(h[1]==="!DATA"){L(),l(),o=null,w=!1,u={name:E.slice(5).trim(),chunks:[]};continue}if(w)continue;if(u){if(h[1]==="!:")u.chunks.push(h.slice(2).join(""));continue}if(!o)d(t);let T={t:0,text:E};if(h[1]==="STEP")T.step=!0,c=[],f=null;else if(h[1]==="BFC")T.bfc=h.slice(2).join(" ");else if(h[1]==="ROTSTEP")if(T.meta="ROTSTEP",T.step=!0,c=[],f=null,(h[2]??"").toUpperCase()==="END")T.rotstep={x:0,y:0,z:0,mode:"END"};else{let v=(h[5]??"REL").toUpperCase();T.rotstep={x:+h[2]||0,y:+h[3]||0,z:+h[4]||0,mode:["REL","ABS","ADD"].includes(v)?v:"REL"}}else if(h[1]==="BUFEXCHG"){T.meta="BUFEXCHG";let v=(h[2]??"").toUpperCase();T.bufexchg={op:v==="RETRIEVE"?"RETRIEVE":"STORE",buf:h[3]??"A"}}else if(h[1]?.startsWith("!"))T.meta=h[1];if(p&&!o.org){let v=Je(E);if(v)o.org=v}if(h[1]==="!TEXMAP"){let v=(h[2]??"").toUpperCase();if(f=null,v==="START"||v==="NEXT"){let F=_t(E.replace(/^!TEXMAP\\s+\\S+/i,""),v==="NEXT");if(T.texmap={op:v,...F?{map:F}:{}},F)if((o.texmaps??=[]).push(F),v==="START")c.push({map:F,fallback:!1});else f=F}else if(v==="FALLBACK"){T.texmap={op:v};let F=c[c.length-1];if(F)F.fallback=!0}else if(v==="END")T.texmap={op:v},c.pop()}else if(h[1]==="!:"){f=null;let v=qe(h.slice(2));if(v)g(v,!0),T.geom=v}else f=null;let B=E.match(Ye);if(B&&!o.movedTo){let v=B[1].trim().replace(/\\\\/g,"/");if(!/\\.(dat|ldr|mpd)$/i.test(v))v+=".dat";o.movedTo=Q(v)}o.cmds.push(T);continue}if(u||w)continue;if(!o)d(t);let A=qe(h);if(!A)continue;g(A,!1),o.cmds.push(A),p=!1}return l(),a?{main:i,files:s,data:a}:{main:i,files:s}}var yn=Math.PI/180;function it(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 at(e,t){let[n,r,s,o,i,a,u,c,f,l,p,d]=e,[w,y,L,g,m,b,h,P,A,E,T,B]=t;return[o*w+i*y+a*L+n,u*w+c*y+f*L+r,l*w+p*y+d*L+s,o*g+i*h+a*E,o*m+i*P+a*T,o*b+i*A+a*B,u*g+c*h+f*E,u*m+c*P+f*T,u*b+c*A+f*B,l*g+p*h+d*E,l*m+p*P+d*T,l*b+p*A+d*B]}var Fe=[0,0,0,1,0,0,0,1,0,0,0,1];var Qe=new WeakMap,Kt=/^(s|8|48)\\//;function Re(e,t){let n=e.files.get(Q(t));if(!n)return"part";let r=Qe.get(n);if(r)return r;if(n.org)r=st.has(n.org)?"part":"model";else if(n.name===e.main)r="model";else r=n.cmds.some((s)=>s.t>=2||s.t===0&&!!s.geom||s.t===1&&Kt.test(s.file))?"part":"model";return Qe.set(n,r),r}var et=new WeakMap;function lt(e){let t=et.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 et.set(e,t),t}var tt=(e)=>e>16777215?"0x"+e.toString(16).toUpperCase():e<0?Pe.get(e)??String(e):String(e),Wt=(e)=>e.t===0?"0 "+e.text:e.t===1?`1 ${tt(e.color)} ${e.m.join(" ")} ${e.file}`:e.src?e.src:`${e.t} ${tt(e.color)} ${e.p.join(" ")}`,De=(e,t)=>`${Q(e)}#${t}`;function Xt(e,t){let n=[],r=0,s=(o)=>!!o&&o.t===0&&o.texmap?.op==="NEXT";for(let o of e.cmds){if(o.t===0){if(o.step){r++;continue}if(o.bfc!==void 0){n.push(o);continue}if(r!==t)continue;if(o.texmap)n.push(o);else if(o.geom){if(o.geom.t>=2)n.push(o);else if(s(n[n.length-1]))n.pop()}continue}if(r!==t)continue;if(o.t===1){if(s(n[n.length-1]))n.pop();continue}n.push(o)}return{name:De(e.name,t),cmds:n}}function ct(e,t){return[`0 ldr: own geometry of ${e.name}, step ${t}`,...Xt(e,t).cmds.map(Wt)].join(`\n`)+`\n`}function Zt(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 ut(e){let[t,n,r,s,o,i,a,u,c,f,l,p]=e,d=u*p-c*l,w=-(a*p-c*f),y=a*l-u*f,L=s*d+o*w+i*y;if(!Number.isFinite(L)||Math.abs(L)<0.000000000001)return null;let g=1/L,m=[d*g,-(o*p-i*l)*g,(o*c-i*u)*g,w*g,(s*p-i*f)*g,-(s*c-i*a)*g,y*g,-(s*l-o*f)*g,(s*u-o*a)*g];return[-(m[0]*t+m[1]*n+m[2]*r),-(m[3]*t+m[4]*n+m[5]*r),-(m[6]*t+m[7]*n+m[8]*r),...m]}var Yt=(e)=>String(+e.toFixed(6)||0),nt=(e)=>\'"\'+e.replace(/\\\\/g,"\\\\\\\\").replace(/"/g,"\\\\\\"")+\'"\';function ft(e,t){let n=[...t.p1,...t.p2,...t.p3,...t.method!=="PLANAR"?[t.a??360]:[],...t.method==="SPHERICAL"?[t.b??180]:[]].map(Yt).join(" "),r=`0 ldr: ${e} with a model-level !TEXMAP\n0 BFC CERTIFY CCW\n0 !TEXMAP START ${t.method} ${n} ${nt(t.texture)}${t.glossmap?" GLOSSMAP "+nt(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-${Zt(r)}`,source:r}}var Jt=(e,t)=>{let n=[,,,,,,,,,];for(let r=0;r<3;r++)for(let s=0;s<3;s++)n[r*3+s]=e[r*3]*t[s]+e[r*3+1]*t[3+s]+e[r*3+2]*t[6+s];return n};function qt(e,t,n){let r=Math.PI/180,s=Math.sin(e*r),o=Math.cos(e*r),i=Math.sin(t*r),a=Math.cos(t*r),u=Math.sin(n*r),c=Math.cos(n*r);return[a*c,-a*u,i,o*u+s*i*c,o*c-s*i*u,-s*a,s*u-o*i*c,s*c+o*i*u,o*a]}var rt=new WeakMap;function pt(e){let t=rt.get(e);if(t)return t;let n=[],r=null;for(let s of e.cmds){if(s.t!==0||!s.step)continue;let o=s.rotstep;if(o)if(o.mode==="END")r=null;else{let i=qt(o.x,o.y,o.z);r=o.mode==="ABS"?{abs:!0,m:i,rotstep:o}:o.mode==="ADD"&&r?{abs:r.abs,m:Jt(r.m,i),rotstep:o}:{abs:!1,m:i,rotstep:o}}n.push(r)}return n.push(r),rt.set(e,n),n}var mt=999999,gt=(e)=>e.map((t)=>String(t).padStart(6,"0")).join(".")+"~";function Qt(e,t={}){let n=[],r=t.maxDepth??64,s=t.looseGeometry!==!1,o=!!t.textures,i=!!t.callouts,a=new Map,u=0,c=(l,p)=>{let d=l.name+"#"+p,w=a.get(d);if(!w){let y;w=Object.assign(()=>y??=ct(l,p),{file:l,step:p}),a.set(d,w)}return w},f=(l,p,d,w,y,L,g,m,b=null,h=[],P=[],A=void 0,E=null)=>{let T=l.files.get(p);if(!T||g>r)return;let B=E,v=0,F=g>0?++u:0,Y=i&&F?[...h,F]:h,_=i&&F?[...P,d]:P,C=i&&!b?new Map:null,M=-1,k=0,G=(S,x,R,D,U,H,z)=>{if(M!==v)M=v,k=0;let V=C?.get(v+"|"+x);if(V)return V.n++,f(S,S===l?x:S.main,R,D,y+"/"+x,[...U,mt],g+1,H,[...U,mt],Y,_,z,B);let O=[...U,k++],K=n.length;f(S,S===l?x:S.main,R,D,y+"/"+x,O,g+1,H,b,Y,_,z,B),C?.set(v+"|"+x,{n:1,from:K,to:n.length})},I=pt(T),N=s?lt(T):[],j=0,X=(S,x,R,D,U,H,z,V)=>{if(b)D=b;let O={part:S,color:x,m:R,step:D[0],steps:D,localStep:U,path:y};if(V)O.colour=V;if(F){if(O.sub=F,i)O.subPath=Y,O.subMats=_}if(H)O.embedded=!0;if(z){let q=ft(S,z);O.texPart=q.name,O.texSource=q.source}let K=I[U];if(K)O.view=K;return n.push(O),O},W=(S)=>{while(j<N.length&&N[j]<=S){let x=N[j++];X(De(T.name,x),w,d,[...L,x],x,!1,null,A).source=c(T,x)}};for(let S of T.cmds){if(S.t===0&&S.step){v++;continue}let x=S;if(x.t>=2||x.t===0&&x.geom&&x.geom.t>=2){W(v);continue}if(x.t===0){if(x.meta==="!COLOUR"){let q=tn(x.text);if(q&&q.code!==16&&q.code!==24)(B=new Map(B??[])).set(q.code,q);continue}if(o&&x.geom?.t===1)x=x.geom;else continue}if(x.t!==1)continue;if(o&&x.fallback)continue;let R=x.color===16?w:x.color,D=x.color===16?A:B?.get(x.color),U=at(d,x.m),H=[...L,v],z=o?x.tex??m:null,V=z?ut(x.m):null,O=z&&V?it(z,V):null;if(l.files.has(x.file)){if(Re(l,x.file)==="model"){G(l,x.file,U,R,H,O,D);continue}X(x.file,R,U,H,v,!0,O,D);continue}let K=t.resolveModel?.(x.file);if(K){G(K,x.file,U,R,H,O,D);continue}X(x.file,R,U,H,v,!1,O,D)}if(W(1/0),C){for(let S of C.values())if(S.n>1)for(let x=S.from;x<S.to;x++)n[x].mult??=S.n}};if(Re(e,e.main)==="part"){if(e.files.get(e.main))n.push({part:e.main,color:16,m:[...Fe],step:0,steps:[0],localStep:0,path:e.main,embedded:!0});return n}return f(e,e.main,Fe,16,e.main,[],0,null),n}function dt(e,t="main.ldr",n){return Qt(ot(e,t,{geometryText:!0}),n)}var en=new Set(["CHROME","PEARLESCENT","RUBBER","MATTE_METALLIC","METAL","MATERIAL"]);function Ue(e){if(!e)return null;if(e.startsWith("#")&&/^#[0-9A-Fa-f]{6}$/.test(e))return e.toUpperCase();if(/^0x[0-9A-Fa-f]{6}$/i.test(e))return("#"+e.slice(2)).toUpperCase();return null}function ht(e,t){let n={value:"#FFFFFF",fraction:0.5};while(t<e.length){let r=e[t].toUpperCase(),s=e[t+1];if(r==="VALUE"){let o=Ue(s);if(o)n.value=o;t+=2}else if(r==="ALPHA")n.alpha=+s,t+=2;else if(r==="LUMINANCE")n.luminance=+s,t+=2;else if(r==="FRACTION")n.fraction=+s,t+=2;else if(r==="VFRACTION")n.vfraction=+s,t+=2;else if(r==="SIZE")n.size=+s,t+=2;else if(r==="MINSIZE")n.minsize=+s,t+=2;else if(r==="MAXSIZE")n.maxsize=+s,t+=2;else break}return{grain:n,next:t}}function tn(e){let t=e.indexOf("!COLOUR");if(t<0)return null;let n=e.slice(t+7).trim().split(/\\s+/).filter(Boolean);if(n.length<2)return null;let r=n[0],s=NaN,o="#FF00FF",i="#333333",a=255,u=0,c={type:"default"},f=1;while(f<n.length){let l=n[f].toUpperCase(),p=n[f+1];if(l==="CODE")s=p!==void 0&&ke.test(p)?Ie(p):p!==void 0&&/^\\d+$/.test(p)?+p:NaN,f+=2;else if(l==="VALUE"){let d=Ue(p);if(d)o=d;f+=2}else if(l==="EDGE")i=Ue(p)??p,f+=2;else if(l==="ALPHA")a=+p,f+=2;else if(l==="LUMINANCE")u=+p,f+=2;else if(l==="CHROME")c={type:"chrome"},f+=1;else if(l==="PEARLESCENT")c={type:"pearlescent"},f+=1;else if(l==="RUBBER")c={type:"rubber"},f+=1;else if(l==="MATTE_METALLIC")c={type:"matte_metallic"},f+=1;else if(l==="METAL")c={type:"metal"},f+=1;else if(l==="MATERIAL"){let d=(n[f+1]||"").toUpperCase();if(d==="GLITTER"){let{grain:w,next:y}=ht(n,f+2);c={type:"glitter",material:w},f=y}else if(d==="SPECKLE"){let{grain:w,next:y}=ht(n,f+2);c={type:"speckle",material:w},f=y}else if(d==="FABRIC"){let w=(n[f+2]||"").toUpperCase(),y=["VELVET","CANVAS","STRING","FUR"].includes(w)?w.toLowerCase():void 0;c={type:"fabric",kind:y},f+=y?3:2}else f=n.length}else if(en.has(l))f+=1;else f+=1}if(Number.isNaN(s)||!o)return null;return{code:s,name:r,hex:o,edge:i,alpha:Number.isFinite(a)?a:255,luminance:Number.isFinite(u)?u:0,finish:c}}function nn(e){let t=Math.max(0,Math.min(1,(e.alpha??255)/255)),n=t<1,r=Math.max(0,Math.min(1,(e.luminance??0)/255)),s={opacity:t,transparent:n,depthWrite:!n,emissive:r,clearcoat:0,clearcoatRoughness:0,sheen:0,sheenRoughness:0};switch(e.finish?.type??"default"){case"chrome":return{...s,metalness:1,roughness:0,finish:"chrome"};case"pearlescent":return{...s,metalness:0.25,roughness:0.3,clearcoat:0.5,clearcoatRoughness:0.25,sheen:0.4,sheenRoughness:0.35,finish:"pearlescent"};case"rubber":return{...s,metalness:0,roughness:0.9,finish:"rubber"};case"matte_metallic":return{...s,metalness:0.4,roughness:0.8,finish:"matte_metallic"};case"metal":return{...s,metalness:0.85,roughness:0.2,finish:"metal"};case"glitter":{let i=e.finish.material,a=i.size??(i.minsize!=null&&i.maxsize!=null?(i.minsize+i.maxsize)/2:1);return{...s,metalness:0.35,roughness:0.25,clearcoat:1,clearcoatRoughness:0.08,particleHex:i.value,particleFraction:i.fraction,particleSize:a,finish:"glitter"}}case"speckle":{let i=e.finish.material,a=i.size??(i.minsize!=null&&i.maxsize!=null?(i.minsize+i.maxsize)/2:1);return{...s,metalness:0.2,roughness:0.55,particleHex:i.value,particleFraction:i.fraction,particleSize:a,finish:"speckle"}}case"fabric":return{...s,metalness:0,roughness:0.85,sheen:0.65,sheenRoughness:0.75,finish:"fabric"};default:return{...s,metalness:0,roughness:0.45,finish:"default"}}}function Oe(e){let t=nn(e),n=!t.transparent?"op":t.opacity>=0.75?"a200":t.opacity>=0.4?"a128":`a${Math.round(t.opacity*255)}`,r=t.emissive>0?`L${Math.round(t.emissive*16)}`:"",s=`${t.finish}:${n}${r}`;if(t.particleHex)s+=`:${t.particleHex}:${(t.particleFraction??0).toFixed(2)}`;return s}function rn(e,t){let n=new Map,r=null,s=!1;for(let o of e.split(/\\r?\\n/)){let i=/^\\s*0\\s+FILE\\s+(.+)$/i.exec(o);if(i){if(!s)n.clear();s=!0,r=[],n.set(Q(i[1]),r);continue}if(/^\\s*0\\s+(NOFILE|!DATA)(\\s|$)/i.test(o)){if(!s)n.clear();s=!0,r=null;continue}if(!r){if(s)continue;r=[],n.set(Q(t),r)}let a=o.trim().replace(/\\s+/g," ");if(a)r.push(a)}return n}var sn=(e)=>{if(!e.startsWith("1 "))return null;let t=e.split(" ");return t.length>=15?Q(t.slice(14).join(" ")):null};function on(e){let t=2166136261,n=1523705862;for(let r=0;r<e.length;r++){let s=e.charCodeAt(r);t=Math.imul(t^s,16777619),n=Math.imul(n^s,16777629)^n>>>15}return(t>>>0).toString(16).padStart(8,"0")+(n>>>0).toString(16).padStart(8,"0")}function bt(e,t,n="main.ldr"){let r=rn(e,n),s=new Map;for(let o of t){let i=Q(o);if(!r.has(i)||s.has(i))continue;let a=new Set([i]),u=[i];while(u.length)for(let f of r.get(u.pop())){let l=sn(f);if(l&&r.has(l)&&!a.has(l))a.add(l),u.push(l)}let c=[i,...[...a].filter((f)=>f!==i).sort()].map((f)=>"0 FILE "+(f===i?"":f)+`\n`+r.get(f).join(`\n`)).join(`\n`);s.set(i,`emb/${on(c)}.dat`)}return s}var yt=(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,xt=new WeakMap;function Ne(e,t){let n=xt.get(e);if(!n)xt.set(e,n=new Map);let r=n.get(t);if(r!==void 0)return r;let s=e.parts[t];if(!s)return n.set(t,null),null;let o=s.studs.length,i=new Float64Array(o*12),a=[],u=[];s.studs.forEach((p,d)=>{a.push(p[0]),u.push(p[1]);for(let w=0;w<12;w++)i[d*12+w]=p[2+w]});let c=null,f=0,l=0;if(s.mask){f=s.mask[0],l=s.mask[1];let p=s.mask[2];c=new Uint8Array(p.length);for(let d=0;d<p.length;d++)c[d]=p.charCodeAt(d)===49?1:0}return n.set(t,r={nStuds:o,studM:i,kind:a,color:u,mask:c,nx:f,nz:l}),r}var ie=1073741824;class ze{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),s=this.used,o=this.a,i=this.b,a=this.c;for(;;){if(!s[r])return-1;if(o[r]===e&&i[r]===t&&a[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 s=this.slot(e,t,n),o=this.used,i=this.a,a=this.b,u=this.c;for(;;){if(!o[s])return o[s]=1,i[s]=e,a[s]=t,u[s]=n,this.vals[s]=r,this.size++,-1;if(i[s]===e&&a[s]===t&&u[s]===n){let c=this.vals[s];return this.vals[s]=r,c}s=s+1&this.mask}}grow(){let{a:e,b:t,c:n,vals:r,used:s}=this,o=s.length*2;this.a=new Int32Array(o),this.b=new Int32Array(o),this.c=new Int32Array(o),this.vals=new Int32Array(o),this.used=new Uint8Array(o),this.mask=o-1,this.size=0;for(let i=0;i<s.length;i++)if(s[i])this.put(e[i],t[i],n[i],r[i])}}var we=(e,t,n)=>e>-ie&&e<ie&&t>-ie&&t<ie&&n>-ie&&n<ie,fe=2147483647;function an(e,t,n){let s=[],o=[],i=[],a=[],u=[],c=[],f=[],l=[],p=new ze(e.length*2),d=[],w=[];for(let C=0;C<e.length;C++){let M=e[C],k=M.m,G=t.parts[M.part];if(!G||!G.mask||!yt(k))continue;let I=G.bbox,N=1/0,j=-1/0,X=1/0,W=-1/0;for(let R=0;R<2;R++)for(let D=0;D<2;D++){let U=R?I[3]:I[0],H=D?I[5]:I[2],z=k[0]+k[3]*U+k[5]*H,V=k[2]+k[9]*U+k[11]*H;if(z<N)N=z;if(z>j)j=z;if(V<X)X=V;if(V>W)W=V}let S=u.length;s.push(N),o.push(j),i.push(X),a.push(W),u.push(C),c.push(Ne(t,M.part)),f.push(I[0]),l.push(I[2]);let x=Math.round((k[1]+I[4])*2);for(let R=Math.floor(N/40);R<=Math.floor(j/40);R++)for(let D=Math.floor(X/40);D<=Math.floor(W/40);D++){if(!we(x,R,D))continue;let U=w.length;w.push(S),d.push(p.put(x,R,D,U))}}let y=[0,5,-5,5,-5],L=[0,5,5,-5,-5],g=NaN,m=NaN,b=NaN,h=-1,P=(C,M,k,G)=>{let I=Math.round(M*2),N=Math.floor(C/40),j=Math.floor(k/40);if(!we(I,N,j))return fe;let X=fe;if(I!==g||N!==m||j!==b)g=I,m=N,b=j,h=p.get(I,N,j);for(let W=h;W>=0;W=d[W]){let S=w[W];if(u[S]===G||!(C-6>=s[S]-0.5&&C+6<=o[S]+0.5&&k-6>=i[S]-0.5&&k+6<=a[S]+0.5))continue;let x=e[u[S]].m,R=c[S],D=f[S],U=l[S],H=C-x[0],z=M-x[1],V=k-x[2],O=x[3]*H+x[6]*z+x[9]*V,K=x[5]*H+x[8]*z+x[11]*V,{nx:q,nz:se,mask:ae}=R,oe=!0;for(let ee=0;ee<5;ee++){let te=Math.floor((O+y[ee]-D)/20),ne=Math.floor((K+L[ee]-U)/20);if(te<0||ne<0||te>=q||ne>=se||ae[te*se+ne]!==1){oe=!1;break}}if(oe){if(!n)return 0;let ee=n[u[S]];if(ee<X)X=ee}}return X},A=0;for(let C of e){let M=Ne(t,C.part);if(M)A+=M.nStuds}let E=new Uint8Array(A),T=new Uint8Array(A),B=new ze(A),v=0,F=n?new Int32Array(A).fill(fe):void 0;for(let C=0,M=0;C<e.length;C++){let k=e[C],G=Ne(t,k.part);if(!G)continue;let I=k.m,N=G.studM,j=I[0],X=I[1],W=I[2],S=I[3],x=I[4],R=I[5],D=I[6],U=I[7],H=I[8],z=I[9],V=I[10],O=I[11];for(let K=0;K<G.nStuds;K++,M++){let q=K*12,se=N[q+4],ae=N[q+7],oe=N[q+10];if(!(Math.abs(D*se+U*ae+H*oe-1)<0.001&&Math.abs(S*se+x*ae+R*oe)<0.001&&Math.abs(z*se+V*ae+O*oe)<0.001))continue;T[M]=1;let ee=N[q],te=N[q+1],ne=N[q+2],$e=j+S*ee+x*te+R*ne,je=X+D*ee+U*te+H*ne,Ve=W+z*ee+V*te+O*ne,_e=P($e,je,Ve,C);if(_e!==fe){if(E[M]=1,v++,F)F[M]=_e}let me=Math.round($e),he=Math.round(je),ge=Math.round(Ve);if(!we(me,he,ge))continue;if(!n){B.put(me,he,ge,1);continue}let He=n[C],Ge=B.get(me,he,ge);if(Ge<0||He<Ge)B.put(me,he,ge,He)}}let Y=new Uint8Array(e.length),_=n?new Int32Array(e.length).fill(fe):void 0;for(let C=0;C<e.length;C++){let M=e[C],k=t.parts[M.part];if(!k||!k.under||!yt(M.m))continue;let G=k.bbox,I=Math.round((G[3]-G[0])/20),N=Math.round((G[5]-G[2])/20);if(!I||!N||I*N>4096)continue;let j=M.m,X=!0,W=0;for(let S=0;S<I&&X;S++)for(let x=0;x<N;x++){let R=G[0]+10+20*S,D=G[2]+10+20*x,U=j[0]+j[3]*R+j[5]*D,H=j[2]+j[9]*R+j[11]*D,z=Math.round(U),V=Math.round(j[1]+G[4]),O=Math.round(H),K=we(z,V,O)?B.get(z,V,O):-1;if(K<0){X=!1;break}if(K>W)W=K}if(X){if(Y[C]=1,_)_[C]=W}}return{nStuds:A,studHidden:E,studUp:T,underHidden:Y,studsHidden:v,studHideStep:F,underHideStep:_}}function ln(e,t,n){let r=(l)=>n&&l.texPart&&t.parts[l.texPart]?l.texPart:l.part,s=new Map,o=new Map,i=(l)=>{let p=l.colour;if(!p)return String(l.color);let d=o.get(p);if(d!==void 0)return d;let w=t.colorTable?.[l.color],y=w?.hex??t.colors?.[l.color],L=w?Oe({alpha:w.alpha??255,luminance:w.luminance??0,finish:w.finish??{type:"default"}}):"default:op",g=Oe(p);if(d=y&&y.toUpperCase()===p.hex.toUpperCase()&&L===g?String(l.color):p.hex.toUpperCase()+"/"+g,d!==String(l.color))s.set(d,p);return o.set(p,d),d},a=e.map((l)=>({part:r(l),color:i(l),m:l.m,steps:l.steps})),u=a.map((l)=>gt(l.steps)),c=[...new Set(u)].sort(),f=new Map(c.map((l,p)=>[l,p]));return{all:a,stepOf:u.map((l)=>f.get(l)),nSteps:c.length,localColours:s}}function Ae(e,t,n=!0){let r=ln(e,t,n);return an(r.all,t,r.nSteps>1?r.stepOf:void 0)}var Te="https://ldr-demo.vercel.app/cdn/v1/",ve=new Map,Me=new Map;function At(e=Te,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 cn=(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"),Ce=(e,t)=>cn(e)?[e[0]+t,e[1],e[2]]:Array.isArray(e)?e.map((n)=>Ce(n,t)):e&&typeof e==="object"?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,Ce(r,t)])):e;function un(e,t={}){let n=[],r=0,s={},o={};for(let p of e){let d=p.buffer;if(!d)throw Error("ldr: mergePacks needs packs from decodePack/loadPack");let w=new DataView(d).getUint32(0,!0),y=new Uint8Array(d,4+w),L=r;n.push(y),r+=y.byteLength;let g=(4-r%4)%4;if(g)n.push(new Uint8Array(g)),r+=g;for(let[m,b]of Object.entries(p.header.parts??{}))if(!(m in s))s[m]=Ce(b,L);for(let[m,b]of Object.entries(p.header.studKinds??{}))if(!(m in o))o[m]=Ce(b,L)}let i=e[0]?.header??{version:1,weld:!0},a=new TextEncoder().encode(JSON.stringify({...i,parts:s,studKinds:o,...t})),u=(4-(4+a.length)%4)%4,c=4+a.length+u,f=new Uint8Array(c+r);new DataView(f.buffer).setUint32(0,a.length+u,!0),f.set(a,4),f.fill(32,4+a.length,c);let l=c;for(let p of n)f.set(p,l),l+=p.byteLength;return xe(f.buffer)}async function fn(e,t={}){e=[...e];try{return await wt(e,t)}catch(n){let r=t.cdn??Te,s=t.fetch??fetch;ve.delete(r);let o=(i,a)=>s(i,{...a,cache:"reload"});try{return await wt(e,{...t,fetch:o})}catch{throw n}}}async function wt(e,t){let n=t.cdn??Te,r=t.fetch??fetch,s=t.gap??16384,o=await At(n,r),i=[...new Set([...e].map(Q))],a=[],u=[];for(let g of i){if(Me.has(n+g))continue;let m=o.parts[g];if(m)u.push({name:g,off:m[0],len:m[1],file:m[2]??0});else a.push(g)}u.sort((g,m)=>g.file-m.file||g.off-m.off);let c=[];for(let g of u){let m=c[c.length-1];if(m&&m.file===g.file&&g.off-m.end<=s)m.end=Math.max(m.end,g.off+g.len),m.items.push(g);else c.push({file:g.file,start:g.off,end:g.off+g.len,items:[g]})}let f=0,l=0,p=0,d=new Map,w=async()=>{while(p<c.length){let g=c[p++],m=d.get(g.file);if(m)m=m.subarray(g.start,g.end);else{let b=await r(new URL(o.archives[g.file],n).href,{headers:{Range:`bytes=${g.start}-${g.end-1}`,"Accept-Encoding":"identity"}});if(!b.ok)throw Error(`ldr: parts CDN ${b.status}`);if(l++,m=new Uint8Array(await b.arrayBuffer()),f+=m.byteLength,b.status===200)d.set(g.file,m),m=m.subarray(g.start,g.end)}for(let b of g.items){let h=ye(m.subarray(b.off-g.start,b.off-g.start+b.len)),P=h.buffer.slice(h.byteOffset,h.byteOffset+h.byteLength);Me.set(n+b.name,xe(P))}}};await Promise.all(Array.from({length:Math.min(t.concurrency??24,c.length)},w));let y=i.filter((g)=>Me.has(n+g)).map((g)=>Me.get(n+g));return{pack:y.length?un(y,{colors:o.colors}):xe(pn(o.colors)),missing:a,requests:l,bytes:f}}function pn(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}function mn(e,t){let n=t.header.parts;if(!n)return 0;let r=0;for(let s of e){let o=n[s.part]?.body?.tris;if(o)r+=o}return r}function hn(e,t,n){let r=0,s=0,o=!1,i=new Set;for(let a of e){let u=a.embedded?t.get(a.part):Q(a.part),c=u?n.parts[u]:void 0;if(!c)continue;if(c[3]!=null)o=!0,r+=c[3];if(!i.has(u))i.add(u),s+=c[1]}return{bodyTris:r,packBytes:s,known:o}}class pe extends Error{code="ldr-budget";bodyTris;packBytes;maxBodyTris;maxPackBytes;constructor(e){let t=[e.maxBodyTris!=null&&e.bodyTris>e.maxBodyTris?`${e.bodyTris} triangles (limit ${e.maxBodyTris})`:"",e.maxPackBytes!=null&&e.packBytes>e.maxPackBytes?`${(e.packBytes/1e6).toFixed(1)} MB parts pack (limit ${(e.maxPackBytes/1e6).toFixed(0)} MB)`:""].filter(Boolean).join(", ");super(`ldr: model exceeds device budget: ${t}`);this.name="BudgetError",this.bodyTris=e.bodyTris,this.packBytes=e.packBytes,this.maxBodyTris=e.maxBodyTris,this.maxPackBytes=e.maxPackBytes}}async function Mt(e,t={}){let n=performance.now(),r=t.fetch??fetch,s=At(t.cdn??Te,r);s.catch(()=>{});let o=t.text?e:await r(e).then(async(h)=>{if(!h.ok)throw Error(`ldr: ${h.status} fetching ${e}`);return Xe(await h.arrayBuffer())}),i=performance.now(),a=t.name??(t.text?"main.ldr":Ze(e)),u=dt(o,a,{looseGeometry:!1,callouts:t.callouts}),c=performance.now();t.onParsed?.(u),await s;let f=bt(o,new Set(u.filter((h)=>h.embedded).map((h)=>h.part)),a),l=(h,P)=>t.maxBodyTris!=null&&h>t.maxBodyTris||t.maxPackBytes!=null&&P>t.maxPackBytes;if(t.maxBodyTris!=null||t.maxPackBytes!=null){let h=hn(u,f,await s);if(l(h.known?h.bodyTris:0,h.packBytes))throw new pe({bodyTris:h.bodyTris,packBytes:h.packBytes,maxBodyTris:t.maxBodyTris,maxPackBytes:t.maxPackBytes})}let{pack:p,missing:d,requests:w,bytes:y}=await fn([...u.filter((h)=>!h.embedded).map((h)=>h.part),...f.values()],t),L=new Map([...f].map(([h,P])=>[P,h])),g=d.map((h)=>L.get(h)??h);for(let[h,P]of f){let A=p.header.parts[P];if(A)p.header.parts[h]=A}let m=performance.now();if(t.maxBodyTris!=null||t.maxPackBytes!=null){let h=p.buffer?.byteLength??p.bytes??0,P=mn(u,p);if(l(P,h))throw new pe({bodyTris:P,packBytes:h,maxBodyTris:t.maxBodyTris,maxPackBytes:t.maxPackBytes})}let b=t.cull?Ae(u,p.header,t.textures!==!1):void 0;return{insts:u,pack:p,missing:g,requests:w,bytes:y,cull:b,timings:{fetchModel:i-n,parse:c-i,parts:m-c,...b?{cull:performance.now()-m}:{}}}}self.onmessage=async(e)=>{let{id:t,source:n,opts:r}=e.data;try{let s=await Mt(n,{...r,cull:!1,onParsed:(f)=>self.postMessage({id:t,insts:f})}),o=s.pack.buffer;if(self.postMessage({id:t,buffer:o,missing:s.missing,requests:s.requests,bytes:s.bytes,timings:s.timings},[o]),!r.cull)return;let i=performance.now(),a=Ae(s.insts,s.pack.header,r.textures!==!1),u=performance.now()-i,c=[];for(let f of[a.studHidden,a.studUp,a.underHidden,a.studHideStep,a.underHideStep])if(f)c.push(f.buffer);self.postMessage({id:t,cull:a,ms:u},c)}catch(s){if(s instanceof pe||s?.code==="ldr-budget")self.postMessage({id:t,phase:"error",error:String(s?.message??s),budget:{bodyTris:s.bodyTris,packBytes:s.packBytes,maxBodyTris:s.maxBodyTris,maxPackBytes:s.maxPackBytes}});else self.postMessage({id:t,phase:"error",error:String(s?.message??s)})}};\n';
|
|
4165
4328
|
|
|
4166
|
-
// ../../../../../../../tmp/ldr-build-
|
|
4329
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/cdn.ts
|
|
4167
4330
|
var worker;
|
|
4168
4331
|
var seq = 0;
|
|
4169
4332
|
var pending = new Map;
|
package/dist/node/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/spec.ts
|
|
2
2
|
var norm = (s) => s.trim().toLowerCase().replace(/\\/g, "/").replace(/\/+/g, "/");
|
|
3
3
|
var COLOUR_ID_RE = /^[A-Za-z][A-Za-z0-9_]*$/;
|
|
4
4
|
var namedCodes = new Map;
|
|
@@ -708,7 +708,7 @@ function fileStepViews(f) {
|
|
|
708
708
|
viewMemo.set(f, out);
|
|
709
709
|
return out;
|
|
710
710
|
}
|
|
711
|
-
// ../../../../../../../tmp/ldr-build-
|
|
711
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/model.ts
|
|
712
712
|
var CALLOUT_END = 999999;
|
|
713
713
|
var stepKey = (steps) => steps.map((x) => String(x).padStart(6, "0")).join(".") + "~";
|
|
714
714
|
function flatten(doc, opts = {}) {
|
|
@@ -1090,7 +1090,7 @@ function blendedColourHex(code) {
|
|
|
1090
1090
|
const a = LDRAW_EXE_16[code - 256 >> 4], b = LDRAW_EXE_16[code - 256 & 15];
|
|
1091
1091
|
return "#" + [0, 1, 2].map((k) => (a[k] + b[k] >> 1).toString(16).padStart(2, "0")).join("").toUpperCase();
|
|
1092
1092
|
}
|
|
1093
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1093
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/instructions.ts
|
|
1094
1094
|
var MIN_VIS = 0.5;
|
|
1095
1095
|
var REORIENT = 0.35;
|
|
1096
1096
|
var deg = Math.PI / 180;
|
|
@@ -1458,10 +1458,10 @@ function planStepViews(insts, parts, stepOf, nSteps, o = {}) {
|
|
|
1458
1458
|
}
|
|
1459
1459
|
};
|
|
1460
1460
|
}
|
|
1461
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1461
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/render.ts
|
|
1462
1462
|
import * as THREE from "three";
|
|
1463
1463
|
|
|
1464
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1464
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/pack-io.ts
|
|
1465
1465
|
import { decompress } from "fzstd";
|
|
1466
1466
|
async function decompressPack(data) {
|
|
1467
1467
|
const u = data instanceof Uint8Array ? data : new Uint8Array(data);
|
|
@@ -1484,7 +1484,7 @@ function decodePack(buf) {
|
|
|
1484
1484
|
return { header, arr, bytes: buf.byteLength, buffer: buf };
|
|
1485
1485
|
}
|
|
1486
1486
|
|
|
1487
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1487
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/cull.ts
|
|
1488
1488
|
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;
|
|
1489
1489
|
var prepCache = new WeakMap;
|
|
1490
1490
|
function prepPart(H, part) {
|
|
@@ -1819,7 +1819,7 @@ function precomputeCull(instances, H, useTex = true) {
|
|
|
1819
1819
|
return cullCore(s.all, H, s.nSteps > 1 ? s.stepOf : undefined);
|
|
1820
1820
|
}
|
|
1821
1821
|
|
|
1822
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1822
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/render.ts
|
|
1823
1823
|
async function loadPack(url) {
|
|
1824
1824
|
const res = await fetch(url);
|
|
1825
1825
|
if (!res.ok)
|
|
@@ -1868,6 +1868,10 @@ function flatNormals(pos, idx) {
|
|
|
1868
1868
|
return n;
|
|
1869
1869
|
}
|
|
1870
1870
|
var geomCache = new WeakMap;
|
|
1871
|
+
var DECODE_CHUNK_VERTS = 65536;
|
|
1872
|
+
function geomCached(b, arr) {
|
|
1873
|
+
return !b || !!geomCache.get(arr)?.has(b);
|
|
1874
|
+
}
|
|
1871
1875
|
function geom(b, arr) {
|
|
1872
1876
|
if (!b)
|
|
1873
1877
|
return null;
|
|
@@ -2519,6 +2523,12 @@ class LdrLodRoot extends THREE.LOD {
|
|
|
2519
2523
|
}
|
|
2520
2524
|
}
|
|
2521
2525
|
}
|
|
2526
|
+
function fillBucketIds(bIds, fill, studBucket, j0, j1) {
|
|
2527
|
+
for (let j = j0;j < j1; j++) {
|
|
2528
|
+
const b = studBucket[j];
|
|
2529
|
+
bIds[b][fill[b]++] = j;
|
|
2530
|
+
}
|
|
2531
|
+
}
|
|
2522
2532
|
function* buildStudMeshesGen(insts, H, cull, arr, LOD, color, matOf, steps, colorIndex) {
|
|
2523
2533
|
const bKind = [], bMat = [];
|
|
2524
2534
|
const bAll = [];
|
|
@@ -2596,14 +2606,15 @@ function* buildStudMeshesGen(insts, H, cull, arr, LOD, color, matOf, steps, colo
|
|
|
2596
2606
|
sz[j] = a[2] + a[9] * b0 + a[10] * b1 + a[11] * b2;
|
|
2597
2607
|
}
|
|
2598
2608
|
}
|
|
2609
|
+
yield;
|
|
2599
2610
|
const bIds = bAll.map((n) => new Int32Array(n));
|
|
2600
|
-
|
|
2601
|
-
|
|
2602
|
-
|
|
2603
|
-
|
|
2604
|
-
|
|
2605
|
-
}
|
|
2611
|
+
const bFill = new Int32Array(bAll.length);
|
|
2612
|
+
for (let j0 = 0;j0 < cull.nStuds; j0 += 262144) {
|
|
2613
|
+
if (j0)
|
|
2614
|
+
yield;
|
|
2615
|
+
fillBucketIds(bIds, bFill, studBucket, j0, Math.min(cull.nStuds, j0 + 262144));
|
|
2606
2616
|
}
|
|
2617
|
+
yield;
|
|
2607
2618
|
const studCl = new Int32Array(cull.nStuds), studSlot = new Int32Array(cull.nStuds);
|
|
2608
2619
|
const sMesh = [];
|
|
2609
2620
|
const allocClusters = (b, kind, g, ids, cs, c0, c1) => {
|
|
@@ -2982,7 +2993,10 @@ function* buildLdrSceneGen(insts, pack, P, color, mark) {
|
|
|
2982
2993
|
const bodyB = textured ? p.tbody : p.body;
|
|
2983
2994
|
const body = geom(bodyB, arr);
|
|
2984
2995
|
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)));
|
|
2996
|
+
let _coopH = 0;
|
|
2985
2997
|
for (const g of groups) {
|
|
2998
|
+
if (_coopH++)
|
|
2999
|
+
yield root;
|
|
2986
3000
|
const ids = Array.from(g, (i) => idsAll[i]);
|
|
2987
3001
|
let bodyIm = null;
|
|
2988
3002
|
const lv0 = [];
|
|
@@ -3103,6 +3117,19 @@ function* buildLdrSceneGen(insts, pack, P, color, mark) {
|
|
|
3103
3117
|
}
|
|
3104
3118
|
if (maxV === 0)
|
|
3105
3119
|
continue;
|
|
3120
|
+
let decV = 0;
|
|
3121
|
+
for (const p of partSet.values())
|
|
3122
|
+
if (p.body)
|
|
3123
|
+
for (const b of LOD && p.body.lod ? [p.body, ...p.body.lod] : [p.body]) {
|
|
3124
|
+
if (geomCached(b, arr))
|
|
3125
|
+
continue;
|
|
3126
|
+
geom(b, arr);
|
|
3127
|
+
decV += geomVerts(b);
|
|
3128
|
+
if (decV >= DECODE_CHUNK_VERTS) {
|
|
3129
|
+
decV = 0;
|
|
3130
|
+
yield root;
|
|
3131
|
+
}
|
|
3132
|
+
}
|
|
3106
3133
|
const bm = new THREE.BatchedMesh(members.length, Math.max(1, maxV), Math.max(1, maxI), mat);
|
|
3107
3134
|
bm.perObjectFrustumCulled = true;
|
|
3108
3135
|
bm.sortObjects = false;
|
|
@@ -3156,6 +3183,7 @@ function* buildLdrSceneGen(insts, pack, P, color, mark) {
|
|
|
3156
3183
|
};
|
|
3157
3184
|
cl.lv.push({ objs: [bm], err: 0 });
|
|
3158
3185
|
if (EDGES) {
|
|
3186
|
+
yield root;
|
|
3159
3187
|
const byPartIds = new Map;
|
|
3160
3188
|
for (const m of live) {
|
|
3161
3189
|
const a = byPartIds.get(m.part) || byPartIds.set(m.part, []).get(m.part);
|
|
@@ -3204,6 +3232,19 @@ function* buildLdrSceneGen(insts, pack, P, color, mark) {
|
|
|
3204
3232
|
}
|
|
3205
3233
|
if (!uV)
|
|
3206
3234
|
continue;
|
|
3235
|
+
let uDecV = 0;
|
|
3236
|
+
for (const p of uPartSet.values())
|
|
3237
|
+
if (p.under)
|
|
3238
|
+
for (const b of LOD && p.under.lod ? [p.under, ...p.under.lod] : [p.under]) {
|
|
3239
|
+
if (geomCached(b, arr))
|
|
3240
|
+
continue;
|
|
3241
|
+
geom(b, arr);
|
|
3242
|
+
uDecV += geomVerts(b);
|
|
3243
|
+
if (uDecV >= DECODE_CHUNK_VERTS) {
|
|
3244
|
+
uDecV = 0;
|
|
3245
|
+
yield root;
|
|
3246
|
+
}
|
|
3247
|
+
}
|
|
3207
3248
|
const ubm = new THREE.BatchedMesh(umembers.length, Math.max(1, uV), Math.max(1, uI), mat);
|
|
3208
3249
|
ubm.perObjectFrustumCulled = true;
|
|
3209
3250
|
ubm.sortObjects = false;
|
|
@@ -3574,18 +3615,23 @@ function yieldToMain() {
|
|
|
3574
3615
|
});
|
|
3575
3616
|
}
|
|
3576
3617
|
async function buildLdrSceneAsync(insts, pack, P, color, mark, opts = {}) {
|
|
3618
|
+
const { value, longestSliceMs, yields } = await runSliced(buildLdrSceneGen(insts, pack, P, color, mark), opts);
|
|
3619
|
+
value.stats = { ...value.stats, longestSliceMs: +longestSliceMs.toFixed(2), buildYields: yields };
|
|
3620
|
+
return value;
|
|
3621
|
+
}
|
|
3622
|
+
async function runSliced(g, opts = {}) {
|
|
3577
3623
|
const sliceMs = opts.sliceMs ?? 8;
|
|
3578
3624
|
const postPaint = opts.postPaintSliceMs ?? Math.max(sliceMs, 24);
|
|
3579
3625
|
let painting = typeof opts.onSlice === "function";
|
|
3580
3626
|
let effective = painting ? sliceMs : postPaint;
|
|
3581
|
-
const g = buildLdrSceneGen(insts, pack, P, color, mark);
|
|
3582
|
-
let r = g.next();
|
|
3583
3627
|
let sliceStart = performance.now();
|
|
3628
|
+
let r = g.next();
|
|
3584
3629
|
let longestSliceMs = 0;
|
|
3585
3630
|
let yields = 0;
|
|
3631
|
+
let maxStep = 0;
|
|
3586
3632
|
while (!r.done) {
|
|
3587
3633
|
const now = performance.now();
|
|
3588
|
-
if (now - sliceStart >= effective) {
|
|
3634
|
+
if (now - sliceStart + Math.min(Math.max(maxStep, effective / 3), effective / 2) >= effective) {
|
|
3589
3635
|
longestSliceMs = Math.max(longestSliceMs, now - sliceStart);
|
|
3590
3636
|
yields++;
|
|
3591
3637
|
if (painting && opts.onSlice) {
|
|
@@ -3598,12 +3644,12 @@ async function buildLdrSceneAsync(insts, pack, P, color, mark, opts = {}) {
|
|
|
3598
3644
|
await yieldToMain();
|
|
3599
3645
|
sliceStart = performance.now();
|
|
3600
3646
|
}
|
|
3647
|
+
const t = performance.now();
|
|
3601
3648
|
r = g.next();
|
|
3649
|
+
maxStep = Math.max(maxStep, performance.now() - t);
|
|
3602
3650
|
}
|
|
3603
3651
|
longestSliceMs = Math.max(longestSliceMs, performance.now() - sliceStart);
|
|
3604
|
-
|
|
3605
|
-
value.stats = { ...value.stats, longestSliceMs: +longestSliceMs.toFixed(2), buildYields: yields };
|
|
3606
|
-
return value;
|
|
3652
|
+
return { value: r.value, longestSliceMs, yields };
|
|
3607
3653
|
}
|
|
3608
3654
|
async function warmPackGeometry(pack, stop = () => false, sliceMs = 8) {
|
|
3609
3655
|
const { header: H, arr } = pack;
|
|
@@ -3627,8 +3673,27 @@ async function warmPackGeometry(pack, stop = () => false, sliceMs = 8) {
|
|
|
3627
3673
|
await new Promise((r) => setTimeout(r, 0));
|
|
3628
3674
|
}
|
|
3629
3675
|
}
|
|
3630
|
-
// ../../../../../../../tmp/ldr-build-
|
|
3676
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/scene.ts
|
|
3631
3677
|
import * as THREE2 from "three";
|
|
3678
|
+
function ghostMaterial(side, g) {
|
|
3679
|
+
const m = new THREE2.MeshStandardMaterial({ color: 16777215, roughness: 0.85, metalness: 0, side, transparent: false, depthWrite: true, opacity: g.opacity });
|
|
3680
|
+
m.blending = THREE2.CustomBlending;
|
|
3681
|
+
m.blendSrc = THREE2.SrcAlphaFactor;
|
|
3682
|
+
m.blendDst = THREE2.OneMinusSrcAlphaFactor;
|
|
3683
|
+
m.blendSrcAlpha = THREE2.OneFactor;
|
|
3684
|
+
m.blendDstAlpha = THREE2.OneMinusSrcAlphaFactor;
|
|
3685
|
+
const tint = new THREE2.Color(g.color);
|
|
3686
|
+
const u = { ldrGhostTint: { value: tint }, ldrGhostMix: { value: g.whiten } };
|
|
3687
|
+
m.onBeforeCompile = (sh) => {
|
|
3688
|
+
Object.assign(sh.uniforms, u);
|
|
3689
|
+
sh.fragmentShader = `uniform vec3 ldrGhostTint; uniform float ldrGhostMix;
|
|
3690
|
+
` + sh.fragmentShader.replace("#include <color_fragment>", `#include <color_fragment>
|
|
3691
|
+
diffuseColor.rgb = mix(diffuseColor.rgb, ldrGhostTint, ldrGhostMix);`);
|
|
3692
|
+
};
|
|
3693
|
+
m.customProgramCacheKey = () => "ldrGhost";
|
|
3694
|
+
m.userData.ldrGhost = u;
|
|
3695
|
+
return m;
|
|
3696
|
+
}
|
|
3632
3697
|
function colorFn(src, pack, fallback) {
|
|
3633
3698
|
const table = new Map;
|
|
3634
3699
|
const put = (k, v) => table.set(String(k), new THREE2.Color(typeof v === "string" ? v : v.hex));
|
|
@@ -3742,6 +3807,75 @@ function createLdrObjectInner(instances, pack, options, progressive) {
|
|
|
3742
3807
|
}
|
|
3743
3808
|
cur = null;
|
|
3744
3809
|
};
|
|
3810
|
+
let ghostOn = false, ghost = null, ghostBuild = null, ghostGen = 0;
|
|
3811
|
+
let shownStep = null, shownMask = null;
|
|
3812
|
+
const ghostOpts = { opacity: 0.2, color: 16777215, whiten: 0.75 };
|
|
3813
|
+
const ghostMats = new Map;
|
|
3814
|
+
const syncGhost = () => {
|
|
3815
|
+
if (!ghost)
|
|
3816
|
+
return;
|
|
3817
|
+
const show = ghostOn && shownStep != null && shownStep < uniq.length - 1;
|
|
3818
|
+
ghost.root.visible = show;
|
|
3819
|
+
if (show)
|
|
3820
|
+
ghost.setStep(uniq.length - 2 - shownStep, shownMask);
|
|
3821
|
+
};
|
|
3822
|
+
const disposeGhost = () => {
|
|
3823
|
+
ghostGen++;
|
|
3824
|
+
ghostBuild = null;
|
|
3825
|
+
if (!ghost)
|
|
3826
|
+
return;
|
|
3827
|
+
object.remove(ghost.root);
|
|
3828
|
+
ghost.root.traverse((x) => {
|
|
3829
|
+
if (x.isInstancedMesh)
|
|
3830
|
+
x.dispose();
|
|
3831
|
+
else if (x.isBatchedMesh)
|
|
3832
|
+
x.dispose();
|
|
3833
|
+
});
|
|
3834
|
+
for (const m of ghostMats.values())
|
|
3835
|
+
m.dispose();
|
|
3836
|
+
ghostMats.clear();
|
|
3837
|
+
ghost = null;
|
|
3838
|
+
};
|
|
3839
|
+
const buildGhost = () => ghostBuild ??= (async () => {
|
|
3840
|
+
const my = ghostGen;
|
|
3841
|
+
const n = uniq.length;
|
|
3842
|
+
const rev = new Int32Array(stepOf.length);
|
|
3843
|
+
for (let k = 0;k < rev.length; k++)
|
|
3844
|
+
rev[k] = n - 1 - stepOf[k];
|
|
3845
|
+
const so = { ...sceneOpts(), edges: false, cond: false, tex: false, steps: rev, cull: undefined };
|
|
3846
|
+
so.cull = cullCore(all, pack.header, rev);
|
|
3847
|
+
const g = await buildLdrSceneAsync(all, pack, so, color, () => {}, { postPaintSliceMs: 12 });
|
|
3848
|
+
if (my !== ghostGen) {
|
|
3849
|
+
g.root.traverse((x) => {
|
|
3850
|
+
if (x.isInstancedMesh || x.isBatchedMesh)
|
|
3851
|
+
x.dispose();
|
|
3852
|
+
});
|
|
3853
|
+
return;
|
|
3854
|
+
}
|
|
3855
|
+
const old = new Set;
|
|
3856
|
+
g.root.traverse((x) => {
|
|
3857
|
+
if (!x.isMesh)
|
|
3858
|
+
return;
|
|
3859
|
+
if (x.material)
|
|
3860
|
+
old.add(x.material);
|
|
3861
|
+
let m = ghostMats.get(x.material?.side ?? THREE2.FrontSide);
|
|
3862
|
+
if (!m)
|
|
3863
|
+
ghostMats.set(x.material?.side ?? THREE2.FrontSide, m = ghostMaterial(x.material?.side ?? THREE2.FrontSide, ghostOpts));
|
|
3864
|
+
x.material = m;
|
|
3865
|
+
x.castShadow = x.receiveShadow = false;
|
|
3866
|
+
x.renderOrder = 1;
|
|
3867
|
+
x.userData.ldrGhost = true;
|
|
3868
|
+
});
|
|
3869
|
+
for (const m of old)
|
|
3870
|
+
m.dispose();
|
|
3871
|
+
g.root.name = "ldr-ghost";
|
|
3872
|
+
if (!lodOn)
|
|
3873
|
+
g.setLod(false);
|
|
3874
|
+
g.setCull(cs, cu);
|
|
3875
|
+
ghost = g;
|
|
3876
|
+
object.add(g.root);
|
|
3877
|
+
syncGhost();
|
|
3878
|
+
})();
|
|
3745
3879
|
const multiStep = uniq.length > 1;
|
|
3746
3880
|
const drawnAt = (step, mask) => all.filter((i, k) => (step == null || stepOf[k] <= step) && (!mask || mask[k]) && pack.header.parts[i.part]).length;
|
|
3747
3881
|
const sceneOpts = () => ({ localColours: localColours.size ? localColours : undefined, cullStuds: cs, cullUnder: cu, edges: o.edges, side, cond: o.conditionalLines, 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 });
|
|
@@ -3774,7 +3908,12 @@ function createLdrObjectInner(instances, pack, options, progressive) {
|
|
|
3774
3908
|
if (!multiStep)
|
|
3775
3909
|
return;
|
|
3776
3910
|
const t0 = performance.now();
|
|
3911
|
+
shownStep = step;
|
|
3912
|
+
shownMask = mask;
|
|
3777
3913
|
Object.assign(stats, cur.setStep(step, mask), { drawn: drawnAt(step, mask), buildMs: performance.now() - t0 });
|
|
3914
|
+
if (ghostOn && step != null && !ghost)
|
|
3915
|
+
buildGhost();
|
|
3916
|
+
syncGhost();
|
|
3778
3917
|
};
|
|
3779
3918
|
const api = { texturesReady: Promise.resolve() };
|
|
3780
3919
|
const finish = () => {
|
|
@@ -3803,10 +3942,31 @@ function createLdrObjectInner(instances, pack, options, progressive) {
|
|
|
3803
3942
|
applyBuilt(buildLdrScene(all, pack, sceneOpts(), color, () => {}), t0);
|
|
3804
3943
|
} else
|
|
3805
3944
|
cur.setCull(a, b);
|
|
3945
|
+
ghost?.setCull(a, b);
|
|
3806
3946
|
},
|
|
3807
3947
|
setLod: (v) => {
|
|
3808
3948
|
lodOn = v;
|
|
3809
3949
|
cur.setLod(v);
|
|
3950
|
+
ghost?.setLod(v);
|
|
3951
|
+
},
|
|
3952
|
+
setGhost: (on, go = {}) => {
|
|
3953
|
+
ghostOn = on && multiStep;
|
|
3954
|
+
Object.assign(ghostOpts, Object.fromEntries(Object.entries(go).filter(([, v]) => v !== undefined)));
|
|
3955
|
+
for (const m of ghostMats.values()) {
|
|
3956
|
+
m.opacity = ghostOpts.opacity;
|
|
3957
|
+
const u = m.userData.ldrGhost;
|
|
3958
|
+
u.ldrGhostTint.value.set(ghostOpts.color);
|
|
3959
|
+
u.ldrGhostMix.value = ghostOpts.whiten;
|
|
3960
|
+
}
|
|
3961
|
+
if (!ghostOn) {
|
|
3962
|
+
syncGhost();
|
|
3963
|
+
return ghostBuild ?? Promise.resolve();
|
|
3964
|
+
}
|
|
3965
|
+
if (shownStep == null && !ghost)
|
|
3966
|
+
return Promise.resolve();
|
|
3967
|
+
const b = buildGhost();
|
|
3968
|
+
syncGhost();
|
|
3969
|
+
return b;
|
|
3810
3970
|
},
|
|
3811
3971
|
setSide: (s) => {
|
|
3812
3972
|
side = s;
|
|
@@ -3820,7 +3980,7 @@ function createLdrObjectInner(instances, pack, options, progressive) {
|
|
|
3820
3980
|
object.updateMatrixWorld(true);
|
|
3821
3981
|
target.makeEmpty();
|
|
3822
3982
|
object.traverse((x) => {
|
|
3823
|
-
if (x.isInstancedMesh && x.count && !x.userData.ldrLod) {
|
|
3983
|
+
if (x.isInstancedMesh && x.count && !x.userData.ldrLod && !x.userData.ldrGhost) {
|
|
3824
3984
|
x.computeBoundingBox();
|
|
3825
3985
|
const b = x.boundingBox.clone().applyMatrix4(x.matrixWorld);
|
|
3826
3986
|
target.union(b);
|
|
@@ -3828,7 +3988,10 @@ function createLdrObjectInner(instances, pack, options, progressive) {
|
|
|
3828
3988
|
});
|
|
3829
3989
|
return target;
|
|
3830
3990
|
},
|
|
3831
|
-
dispose:
|
|
3991
|
+
dispose: () => {
|
|
3992
|
+
disposeGhost();
|
|
3993
|
+
disposeCur();
|
|
3994
|
+
}
|
|
3832
3995
|
});
|
|
3833
3996
|
};
|
|
3834
3997
|
if (!progressive) {
|
|
@@ -3854,10 +4017,10 @@ function createLdrObjectInner(instances, pack, options, progressive) {
|
|
|
3854
4017
|
return finish();
|
|
3855
4018
|
})();
|
|
3856
4019
|
}
|
|
3857
|
-
// ../../../../../../../tmp/ldr-build-
|
|
4020
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/parts-cdn.ts
|
|
3858
4021
|
import { decompress as decompress2 } from "fzstd";
|
|
3859
4022
|
|
|
3860
|
-
// ../../../../../../../tmp/ldr-build-
|
|
4023
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/embedded.ts
|
|
3861
4024
|
function splitFiles(text, fallback) {
|
|
3862
4025
|
const files = new Map;
|
|
3863
4026
|
let cur = null, saw = false;
|
|
@@ -3929,7 +4092,7 @@ function embeddedKeys(text, names, fallback = "main.ldr") {
|
|
|
3929
4092
|
return out;
|
|
3930
4093
|
}
|
|
3931
4094
|
|
|
3932
|
-
// ../../../../../../../tmp/ldr-build-
|
|
4095
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/parts-cdn.ts
|
|
3933
4096
|
var DEFAULT_PARTS_CDN = "https://ldr-demo.vercel.app/cdn/v1/";
|
|
3934
4097
|
var indexCache = new Map;
|
|
3935
4098
|
var shardCache = new Map;
|
|
@@ -4161,10 +4324,10 @@ async function prepareModel(source, o = {}) {
|
|
|
4161
4324
|
return { insts, pack, missing, requests, bytes, cull, timings: { fetchModel: t1 - t0, parse: t2 - t1, parts: t3 - t2, ...cull ? { cull: performance.now() - t3 } : {} } };
|
|
4162
4325
|
}
|
|
4163
4326
|
|
|
4164
|
-
// ../../../../../../../tmp/ldr-build-
|
|
4327
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/load-worker.gen.ts
|
|
4165
4328
|
var load_worker_gen_default = 'var vt=ArrayBuffer,Z=Uint8Array,de=Uint16Array,Ct=Int16Array;var be=Int32Array,Le=function(e,t,n){if(Z.prototype.slice)return Z.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 Z(n-t);return r.set(e.subarray(t,n)),r},ce=function(e,t,n,r){if(Z.prototype.fill)return Z.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},Tt=function(e,t,n,r){if(Z.prototype.copyWithin)return Z.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 Lt=["invalid zstd data","window size too large (>2046MB)","invalid block type","FSE accuracy too high","match distance too far back","unexpected EOF"],J=function(e,t,n){var r=Error(t||Lt[e]);if(r.code=e,Error.captureStackTrace)Error.captureStackTrace(r,J);if(!n)throw r;return r},Ke=function(e,t,n){var r=0,s=0;for(;r<n;++r)s|=e[t++]<<(r<<3);return s},Et=function(e,t){return(e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24)>>>0},St=function(e,t){var n=e[0]|e[1]<<8|e[2]<<16;if(n==3126568&&e[3]==253){var r=e[4],s=r>>5&1,o=r>>2&1,i=r&3,a=r>>6;if(r&8)J(0);var u=6-s,c=i==3?4:i,f=Ke(e,u,c);u+=c;var l=a?1<<a:s,p=Ke(e,u,l)+(a==1&&256),d=p;if(!s){var w=1<<10+(e[5]>>3);d=w+(w>>3)*(e[5]&7)}if(d>2145386496)J(1);var y=new Z((t==1?p||d:t?0:d)+12);return y[0]=1,y[4]=4,y[8]=8,{b:u+l,y:0,l:0,d:f,w:t&&t!=1?t:y.subarray(12),e:d,o:new be(y.buffer,0,3),u:p,c:o,m:Math.min(131072,d)}}else if((n>>4|e[3]<<20)==25481893)return Et(e,4)+8;J(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,s=(e[t]&15)+5;if(s>n)J(3);var o=1<<s,i=o,a=-1,u=-1,c=-1,f=o,l=new vt(512+(o<<2)),p=new Ct(l,0,256),d=new de(l,0,256),w=new de(l,512,o),y=512+(o<<1),L=new Z(l,y,o),g=new Z(l,y+o);while(a<255&&i>0){var m=re(i+1),b=r>>3,h=(1<<m+1)-1,P=(e[b]|e[b+1]<<8|e[b+2]<<16)>>(r&7)&h,A=(1<<m)-1,E=h-i-1,T=P&A;if(T<E)r+=m,P=T;else if(r+=m+1,P>A)P-=E;if(p[++a]=--P,P==-1)i+=P,L[--f]=a;else i-=P;if(!P)do{var B=r>>3;u=(e[B]|e[B+1]<<8)>>(r&7)&3,r+=2,a+=u}while(u==3)}if(a>255||i)J(0);var v=0,F=(o>>1)+(o>>3)+3,Y=o-1;for(var _=0;_<=a;++_){var C=p[_];if(C<1){d[_]=-C;continue}for(c=0;c<C;++c){L[v]=_;do v=v+F&Y;while(v>=f)}}if(v)J(0);for(c=0;c<o;++c){var M=d[L[c]]++,k=g[c]=s-re(M);w[c]=(M<<k)-o}return[r+7>>3,{b:s,s:L,n:g,t:w}]},Pt=function(e,t){var n=0,r=-1,s=new Z(292),o=e[t],i=s.subarray(0,256),a=s.subarray(256,268),u=new de(s.buffer,268);if(o<128){var c=ue(e,t+1,6),f=c[0],l=c[1];t+=o;var p=f<<3,d=e[t];if(!d)J(0);var w=0,y=0,L=l.b,g=L,m=(++t<<3)-8+re(d);for(;;){if(m-=L,m<p)break;var b=m>>3;if(w+=(e[b]|e[b+1]<<8)>>(m&7)&(1<<L)-1,i[++r]=l.s[w],m-=g,m<p)break;b=m>>3,y+=(e[b]|e[b+1]<<8)>>(m&7)&(1<<g)-1,i[++r]=l.s[y],L=l.n[w],w=l.t[w],g=l.n[y],y=l.t[y]}if(++r>255)J(0)}else{r=o-127;for(;n<r;n+=2){var h=e[++t];i[n]=h>>4,i[n+1]=h&15}++t}var P=0;for(n=0;n<r;++n){var A=i[n];if(A>11)J(0);P+=A&&1<<A-1}var E=re(P)+1,T=1<<E,B=T-P;if(B&B-1)J(0);i[r++]=re(B)+1;for(n=0;n<r;++n){var A=i[n];++a[i[n]=A&&E+1-A]}var v=new Z(T<<1),F=v.subarray(0,T),Y=v.subarray(T);u[E]=0;for(n=E;n>0;--n){var _=u[n];ce(Y,n,_,u[n-1]=_+a[n]*(1<<E-n))}if(u[0]!=T)J(0);for(n=0;n<r;++n){var C=i[n];if(C){var M=u[C];ce(F,n,M,u[C]=M+(1<<E-C))}}return[t,{n:Y,b:E,s:F}]},kt=ue(new Z([81,16,99,140,49,198,24,99,12,33,196,24,99,102,102,134,70,146,4]),0,6)[1],It=ue(new Z([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],Bt=ue(new Z([32,132,16,66,102,70,68,68,68,68,36,73,2]),0,5)[1],We=function(e,t){var n=e.length,r=new be(n);for(var s=0;s<n;++s)r[s]=t,t+=1<<e[s];return r},Ee=new Z(new be([0,0,0,0,16843009,50528770,134678020,202050057,269422093]).buffer,0,36),Ft=We(Ee,0),Se=new Z(new be([0,0,0,0,0,0,0,0,16843009,50528770,117769220,185207048,252579084,16]).buffer,0,53),Rt=We(Se,3),le=function(e,t,n){var r=e.length,s=t.length,o=e[r-1],i=(1<<n.b)-1,a=-n.b;if(!o)J(0);var u=0,c=n.b,f=(r<<3)-8+re(o)-c,l=-1;for(;f>a&&l<s;){var p=f>>3,d=(e[p]|e[p+1]<<8|e[p+2]<<16)>>(f&7);u=(u<<c|d)&i,t[++l]=n.s[u],f-=c=n.n[u]}if(f!=a||l+1!=s)J(0)},Dt=function(e,t,n){var r=6,s=t.length,o=s+3>>2,i=o<<1,a=o+i;le(e.subarray(r,r+=e[0]|e[1]<<8),t.subarray(0,o),n),le(e.subarray(r,r+=e[2]|e[3]<<8),t.subarray(o,i),n),le(e.subarray(r,r+=e[4]|e[5]<<8),t.subarray(i,a),n),le(e.subarray(r),t.subarray(a),n)},Ut=function(e,t,n){var r,s=t.b,o=e[s],i=o>>1&3;t.l=o&1;var a=o>>3|e[s+1]<<5|e[s+2]<<13,u=(s+=3)+a;if(i==1){if(s>=e.length)return;if(t.b=s+1,n)return ce(n,e[s],t.y,t.y+=a),n;return ce(new Z(a),e[s])}if(u>e.length)return;if(i==0){if(t.b=u,n)return n.set(e.subarray(s,u),t.y),t.y+=a,n;return Le(e,s,u)}if(i==2){var c=e[s],f=c&3,l=c>>2&3,p=c>>4,d=0,w=0;if(f<2)if(l&1)p|=e[++s]<<4|(l&2&&e[++s]<<12);else p=c>>3;else if(w=l,l<2)p|=(e[++s]&63)<<4,d=e[s]>>6|e[++s]<<2;else if(l==2)p|=e[++s]<<4|(e[++s]&3)<<12,d=e[s]>>2|e[++s]<<6;else p|=e[++s]<<4|(e[++s]&63)<<12,d=e[s]>>6|e[++s]<<2|e[++s]<<10;++s;var y=n?n.subarray(t.y,t.y+t.m):new Z(t.m),L=y.length-p;if(f==0)y.set(e.subarray(s,s+=p),L);else if(f==1)ce(y,e[s++],L);else{var g=t.h;if(f==2){var m=Pt(e,s);d+=s-(s=m[0]),t.h=g=m[1]}else if(!g)J(0);(w?Dt:le)(e.subarray(s,s+=d),y.subarray(L),g)}var b=e[s++];if(b){if(b==255)b=(e[s++]|e[s++]<<8)+32512;else if(b>127)b=b-128<<8|e[s++];var h=e[s++];if(h&3)J(0);var P=[It,Bt,kt];for(var A=2;A>-1;--A){var E=h>>(A<<1)+2&3;if(E==1){var T=new Z([0,0,e[s++]]);P[A]={s:T.subarray(2,3),n:T.subarray(0,1),t:new de(T.buffer,0,1),b:0}}else if(E==2)r=ue(e,s,9-(A&1)),s=r[0],P[A]=r[1];else if(E==3){if(!t.t)J(0);P[A]=t.t[A]}}var B=t.t=P,v=B[0],F=B[1],Y=B[2],_=e[u-1];if(!_)J(0);var C=(u<<3)-8+re(_)-Y.b,M=C>>3,k=0,G=(e[M]|e[M+1]<<8)>>(C&7)&(1<<Y.b)-1;M=(C-=F.b)>>3;var I=(e[M]|e[M+1]<<8)>>(C&7)&(1<<F.b)-1;M=(C-=v.b)>>3;var N=(e[M]|e[M+1]<<8)>>(C&7)&(1<<v.b)-1;for(++b;--b;){var j=Y.s[G],X=Y.n[G],W=v.s[N],S=v.n[N],x=F.s[I],R=F.n[I];M=(C-=x)>>3;var D=1<<x,U=D+((e[M]|e[M+1]<<8|e[M+2]<<16|e[M+3]<<24)>>>(C&7)&D-1);M=(C-=Se[W])>>3;var H=Rt[W]+((e[M]|e[M+1]<<8|e[M+2]<<16)>>(C&7)&(1<<Se[W])-1);M=(C-=Ee[j])>>3;var z=Ft[j]+((e[M]|e[M+1]<<8|e[M+2]<<16)>>(C&7)&(1<<Ee[j])-1);if(M=(C-=X)>>3,G=Y.t[G]+((e[M]|e[M+1]<<8)>>(C&7)&(1<<X)-1),M=(C-=S)>>3,N=v.t[N]+((e[M]|e[M+1]<<8)>>(C&7)&(1<<S)-1),M=(C-=R)>>3,I=F.t[I]+((e[M]|e[M+1]<<8)>>(C&7)&(1<<R)-1),U>3)t.o[2]=t.o[1],t.o[1]=t.o[0],t.o[0]=U-=3;else{var V=U-(z!=0);if(V){if(U=V==3?t.o[0]-1:t.o[V],V>1)t.o[2]=t.o[1];t.o[1]=t.o[0],t.o[0]=U}else U=t.o[0]}for(var A=0;A<z;++A)y[k+A]=y[L+A];k+=z,L+=z;var O=k-U;if(O<0){var K=-O,q=t.e+O;if(K>H)K=H;for(var A=0;A<K;++A)y[k+A]=t.w[q+A];k+=K,H-=K,O=0}for(var A=0;A<H;++A)y[k+A]=y[O+A];k+=H}if(k!=L)while(L<y.length)y[k++]=y[L++];else k=y.length;if(n)t.y+=k;else y=Le(y,0,k)}else if(n){if(t.y+=p,L)for(var A=0;A<p;++A)y[A]=y[L+A]}else if(L)y=Le(y,L);return t.b=u,y}J(2)},Ot=function(e,t){if(e.length==1)return e[0];var n=new Z(t);for(var r=0,s=0;r<e.length;++r){var o=e[r];n.set(o,s),s+=o.length}return n};function ye(e,t){var n=[],r=+!t,s=0,o=0;for(;e.length;){var i=St(e,r||t);if(typeof i=="object"){if(r){if(t=null,i.w.length==i.u)n.push(t=i.w),o+=i.u}else n.push(t),i.e=0;for(;!i.l;){var a=Ut(e,i,t);if(!a)J(5);if(t)i.e=i.y;else n.push(a),o+=a.length,Tt(i.w,0,a.length),i.w.set(a,i.w.length-a.length)}s=i.b+i.c*4}else s=i;e=e.subarray(s)}return Ot(n,o)}async function Nt(e){let t=e instanceof Uint8Array?e:new Uint8Array(e),n=(r)=>r.buffer.slice(r.byteOffset,r.byteOffset+r.byteLength);if(t[0]===40&&t[1]===181&&t[2]===47&&t[3]===253)return n(ye(t));if(t[0]===31&&t[1]===139)return new Response(new Blob([t]).stream().pipeThrough(new DecompressionStream("gzip"))).arrayBuffer();return n(t)}async function Xe(e){return new TextDecoder().decode(await Nt(e))}var Ze=(e)=>decodeURIComponent(e.split(/[?#]/)[0].split("/").pop()||"main.ldr").replace(/\\.(zst|gz)$/i,"")||"main.ldr";function xe(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:(o)=>o&&(o[2]==="f32"?new Float32Array(e,r+o[0],o[1]):o[2]==="u16"?new Uint16Array(e,r+o[0],o[1]):o[2]==="u8"?new Uint8Array(e,r+o[0],o[1]):new Uint32Array(e,r+o[0],o[1])),bytes:e.byteLength,buffer:e}}var Q=(e)=>e.trim().toLowerCase().replace(/\\\\/g,"/").replace(/\\/+/g,"/"),ke=/^[A-Za-z][A-Za-z0-9_]*$/,Pe=new Map;function Ie(e){let t=e.toLowerCase(),n=2166136261;for(let s=0;s<t.length;s++)n^=t.charCodeAt(s),n=Math.imul(n,16777619);let r=-1-(n>>>0&1073741823);if(!Pe.has(r))Pe.set(r,t);return r}function Be(e){let t=e.charCodeAt(0)|32;if(t>=97&&t<=122&&ke.test(e))return Ie(e);if(/^0x/i.test(e))return parseInt(e,16);return+e}var Ye=/^~?\\s*moved\\s+to\\s+(.+)$/i,zt=new Set(["FILE","NOFILE","!DATA","!:","STEP","BFC","ROTSTEP","BUFEXCHG","!TEXMAP"]),st=new Set(["part","subpart","primitive","8_primitive","48_primitive","shortcut","helper"]),$t=new Set(["model","submodel","configuration"]),jt=/^(?:!?LDRAW_ORG|Unofficial|Official\\s+LCAD)\\s+(\\S+)/i;function Je(e){let t=jt.exec(e);if(!t)return;let n=t[1].toLowerCase().replace(/^unofficial_/,"");return st.has(n)||$t.has(n)?n:void 0}function Vt(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 _t(e,t=!1){let n=/^\\s*(\\S+)\\s+(.*)$/.exec(e);if(!n)return null;let r=n[1].toUpperCase(),s=r==="PLANAR"?9:r==="CYLINDRICAL"?10:r==="SPHERICAL"?11:0;if(!s)return null;let o=n[2].trim().split(/\\s+/);if(o.length<s+1)return null;let i=o.slice(0,s).map(Number);if(!i.every(Number.isFinite))return null;let a=n[2].trim();for(let l=0;l<s;l++)a=a.replace(/^\\S+\\s*/,"");let u=Vt(a);if(!u.length)return null;let c={method:r,p1:i.slice(0,3),p2:i.slice(3,6),p3:i.slice(6,9),texture:u[0]};if(s>=10)c.a=i[9];if(s===11)c.b=i[10];let f=u.findIndex((l,p)=>p>0&&l.toUpperCase()==="GLOSSMAP");if(f>0&&u[f+1])c.glossmap=u[f+1];if(t)c.next=!0;return c}var Ht=(e)=>{let t=e.replace(/[^A-Za-z0-9+/]/g,""),n=t+"=".repeat((4-t.length%4)%4),r=atob(n),s=new Uint8Array(r.length);for(let o=0;o<r.length;o++)s[o]=r.charCodeAt(o);return s};function Gt(e){let t=e.length,n=1,r=(c)=>c===32||c===9,s=()=>{while(n<t&&r(e.charCodeAt(n)))n++;let c=n;while(n<t&&!r(e.charCodeAt(n)))n++;return c<n?e.slice(c,n):null},o=s();if(o===null)return null;let i=Array(12);for(let c=0;c<12;c++){let f=s();if(f===null)return null;i[c]=+f}while(n<t&&r(e.charCodeAt(n)))n++;if(n>=t)return null;let a=e.slice(n),u=/[ \\t]{2,}|\\t/.test(a)?a.split(/\\s+/).join(" "):a;return{t:1,color:Be(o),m:i,file:Q(u)}}function qe(e){let t=+e[0];if(!(t>=1&&t<=5)||e.length<2)return null;let n=Be(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 ot(e,t="main.ldr",n={}){let r=!!n.geometryText,s=new Map,o=null,i="",a,u=null,c=[],f=null,l=()=>{if(!u)return;let m=Ht(u.chunks.join("")),b=m[0]===137&&m[1]===80&&m[2]===78&&m[3]===71;(a??=new Map).set(Q(u.name),{name:u.name,bytes:m,...b?{mime:"image/png"}:{}}),u=null},p=!0,d=(m)=>{if(l(),o={name:Q(m),cmds:[]},s.set(o.name,o),!i)i=o.name;c=[],f=null,p=!0},w=!1,y=!1,L=()=>{if(y)return;y=!0,s.clear(),o=null,i=""},g=(m,b)=>{if(f){m.tex=f,f=null;return}let h=c[c.length-1];if(!h)return;if(h.fallback){if(!b)m.fallback=!0}else m.tex=h.map};for(let m of e.split(`\n`)){let b=m.trim();if(!b)continue;if(r&&b.charCodeAt(0)>=50&&b.charCodeAt(0)<=53&&(b.charCodeAt(1)===32||b.charCodeAt(1)===9)){if(u||w)continue;if(!o)d(t);let E=b.slice(2).trimStart(),T=E.search(/\\s/),B={t:b.charCodeAt(0)-48,color:Be(T<0?E:E.slice(0,T)),p:[],src:b};g(B,!1),o.cmds.push(B),p=!1;continue}if(b.charCodeAt(0)===48&&(b.charCodeAt(1)===32||b.charCodeAt(1)===9)){let E=2;while(b.charCodeAt(E)===32||b.charCodeAt(E)===9)E++;let T=E;while(T<b.length&&b.charCodeAt(T)!==32&&b.charCodeAt(T)!==9)T++;let B=b.slice(E,T);if(!zt.has(B)){if(w||u)continue;if(!o)d(t);let v=b.slice(E),F={t:0,text:v};if(B.charCodeAt(0)===33)F.meta=B;if(f=null,p&&!o.org){let _=Je(v);if(_)o.org=_}let Y=v.match(Ye);if(Y&&!o.movedTo){let _=Y[1].trim().replace(/\\\\/g,"/");if(!/\\.(dat|ldr|mpd)$/i.test(_))_+=".dat";o.movedTo=Q(_)}o.cmds.push(F);continue}}if(b.charCodeAt(0)===49&&(b.charCodeAt(1)===32||b.charCodeAt(1)===9)&&!u&&!w){let E=Gt(b);if(E){if(!o)d(t);g(E,!1),o.cmds.push(E),p=!1;continue}}let h=b.split(/\\s+/);if(+h[0]===0){let E=b.slice(1).trim();if(h[1]==="FILE"){L(),w=!1,d(E.slice(5));continue}if(h[1]==="NOFILE"){l(),o=null,w=!0;continue}if(h[1]==="!DATA"){L(),l(),o=null,w=!1,u={name:E.slice(5).trim(),chunks:[]};continue}if(w)continue;if(u){if(h[1]==="!:")u.chunks.push(h.slice(2).join(""));continue}if(!o)d(t);let T={t:0,text:E};if(h[1]==="STEP")T.step=!0,c=[],f=null;else if(h[1]==="BFC")T.bfc=h.slice(2).join(" ");else if(h[1]==="ROTSTEP")if(T.meta="ROTSTEP",T.step=!0,c=[],f=null,(h[2]??"").toUpperCase()==="END")T.rotstep={x:0,y:0,z:0,mode:"END"};else{let v=(h[5]??"REL").toUpperCase();T.rotstep={x:+h[2]||0,y:+h[3]||0,z:+h[4]||0,mode:["REL","ABS","ADD"].includes(v)?v:"REL"}}else if(h[1]==="BUFEXCHG"){T.meta="BUFEXCHG";let v=(h[2]??"").toUpperCase();T.bufexchg={op:v==="RETRIEVE"?"RETRIEVE":"STORE",buf:h[3]??"A"}}else if(h[1]?.startsWith("!"))T.meta=h[1];if(p&&!o.org){let v=Je(E);if(v)o.org=v}if(h[1]==="!TEXMAP"){let v=(h[2]??"").toUpperCase();if(f=null,v==="START"||v==="NEXT"){let F=_t(E.replace(/^!TEXMAP\\s+\\S+/i,""),v==="NEXT");if(T.texmap={op:v,...F?{map:F}:{}},F)if((o.texmaps??=[]).push(F),v==="START")c.push({map:F,fallback:!1});else f=F}else if(v==="FALLBACK"){T.texmap={op:v};let F=c[c.length-1];if(F)F.fallback=!0}else if(v==="END")T.texmap={op:v},c.pop()}else if(h[1]==="!:"){f=null;let v=qe(h.slice(2));if(v)g(v,!0),T.geom=v}else f=null;let B=E.match(Ye);if(B&&!o.movedTo){let v=B[1].trim().replace(/\\\\/g,"/");if(!/\\.(dat|ldr|mpd)$/i.test(v))v+=".dat";o.movedTo=Q(v)}o.cmds.push(T);continue}if(u||w)continue;if(!o)d(t);let A=qe(h);if(!A)continue;g(A,!1),o.cmds.push(A),p=!1}return l(),a?{main:i,files:s,data:a}:{main:i,files:s}}var yn=Math.PI/180;function it(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 at(e,t){let[n,r,s,o,i,a,u,c,f,l,p,d]=e,[w,y,L,g,m,b,h,P,A,E,T,B]=t;return[o*w+i*y+a*L+n,u*w+c*y+f*L+r,l*w+p*y+d*L+s,o*g+i*h+a*E,o*m+i*P+a*T,o*b+i*A+a*B,u*g+c*h+f*E,u*m+c*P+f*T,u*b+c*A+f*B,l*g+p*h+d*E,l*m+p*P+d*T,l*b+p*A+d*B]}var Fe=[0,0,0,1,0,0,0,1,0,0,0,1];var Qe=new WeakMap,Kt=/^(s|8|48)\\//;function Re(e,t){let n=e.files.get(Q(t));if(!n)return"part";let r=Qe.get(n);if(r)return r;if(n.org)r=st.has(n.org)?"part":"model";else if(n.name===e.main)r="model";else r=n.cmds.some((s)=>s.t>=2||s.t===0&&!!s.geom||s.t===1&&Kt.test(s.file))?"part":"model";return Qe.set(n,r),r}var et=new WeakMap;function lt(e){let t=et.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 et.set(e,t),t}var tt=(e)=>e>16777215?"0x"+e.toString(16).toUpperCase():e<0?Pe.get(e)??String(e):String(e),Wt=(e)=>e.t===0?"0 "+e.text:e.t===1?`1 ${tt(e.color)} ${e.m.join(" ")} ${e.file}`:e.src?e.src:`${e.t} ${tt(e.color)} ${e.p.join(" ")}`,De=(e,t)=>`${Q(e)}#${t}`;function Xt(e,t){let n=[],r=0,s=(o)=>!!o&&o.t===0&&o.texmap?.op==="NEXT";for(let o of e.cmds){if(o.t===0){if(o.step){r++;continue}if(o.bfc!==void 0){n.push(o);continue}if(r!==t)continue;if(o.texmap)n.push(o);else if(o.geom){if(o.geom.t>=2)n.push(o);else if(s(n[n.length-1]))n.pop()}continue}if(r!==t)continue;if(o.t===1){if(s(n[n.length-1]))n.pop();continue}n.push(o)}return{name:De(e.name,t),cmds:n}}function ct(e,t){return[`0 ldr: own geometry of ${e.name}, step ${t}`,...Xt(e,t).cmds.map(Wt)].join(`\n`)+`\n`}function Zt(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 ut(e){let[t,n,r,s,o,i,a,u,c,f,l,p]=e,d=u*p-c*l,w=-(a*p-c*f),y=a*l-u*f,L=s*d+o*w+i*y;if(!Number.isFinite(L)||Math.abs(L)<0.000000000001)return null;let g=1/L,m=[d*g,-(o*p-i*l)*g,(o*c-i*u)*g,w*g,(s*p-i*f)*g,-(s*c-i*a)*g,y*g,-(s*l-o*f)*g,(s*u-o*a)*g];return[-(m[0]*t+m[1]*n+m[2]*r),-(m[3]*t+m[4]*n+m[5]*r),-(m[6]*t+m[7]*n+m[8]*r),...m]}var Yt=(e)=>String(+e.toFixed(6)||0),nt=(e)=>\'"\'+e.replace(/\\\\/g,"\\\\\\\\").replace(/"/g,"\\\\\\"")+\'"\';function ft(e,t){let n=[...t.p1,...t.p2,...t.p3,...t.method!=="PLANAR"?[t.a??360]:[],...t.method==="SPHERICAL"?[t.b??180]:[]].map(Yt).join(" "),r=`0 ldr: ${e} with a model-level !TEXMAP\n0 BFC CERTIFY CCW\n0 !TEXMAP START ${t.method} ${n} ${nt(t.texture)}${t.glossmap?" GLOSSMAP "+nt(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-${Zt(r)}`,source:r}}var Jt=(e,t)=>{let n=[,,,,,,,,,];for(let r=0;r<3;r++)for(let s=0;s<3;s++)n[r*3+s]=e[r*3]*t[s]+e[r*3+1]*t[3+s]+e[r*3+2]*t[6+s];return n};function qt(e,t,n){let r=Math.PI/180,s=Math.sin(e*r),o=Math.cos(e*r),i=Math.sin(t*r),a=Math.cos(t*r),u=Math.sin(n*r),c=Math.cos(n*r);return[a*c,-a*u,i,o*u+s*i*c,o*c-s*i*u,-s*a,s*u-o*i*c,s*c+o*i*u,o*a]}var rt=new WeakMap;function pt(e){let t=rt.get(e);if(t)return t;let n=[],r=null;for(let s of e.cmds){if(s.t!==0||!s.step)continue;let o=s.rotstep;if(o)if(o.mode==="END")r=null;else{let i=qt(o.x,o.y,o.z);r=o.mode==="ABS"?{abs:!0,m:i,rotstep:o}:o.mode==="ADD"&&r?{abs:r.abs,m:Jt(r.m,i),rotstep:o}:{abs:!1,m:i,rotstep:o}}n.push(r)}return n.push(r),rt.set(e,n),n}var mt=999999,gt=(e)=>e.map((t)=>String(t).padStart(6,"0")).join(".")+"~";function Qt(e,t={}){let n=[],r=t.maxDepth??64,s=t.looseGeometry!==!1,o=!!t.textures,i=!!t.callouts,a=new Map,u=0,c=(l,p)=>{let d=l.name+"#"+p,w=a.get(d);if(!w){let y;w=Object.assign(()=>y??=ct(l,p),{file:l,step:p}),a.set(d,w)}return w},f=(l,p,d,w,y,L,g,m,b=null,h=[],P=[],A=void 0,E=null)=>{let T=l.files.get(p);if(!T||g>r)return;let B=E,v=0,F=g>0?++u:0,Y=i&&F?[...h,F]:h,_=i&&F?[...P,d]:P,C=i&&!b?new Map:null,M=-1,k=0,G=(S,x,R,D,U,H,z)=>{if(M!==v)M=v,k=0;let V=C?.get(v+"|"+x);if(V)return V.n++,f(S,S===l?x:S.main,R,D,y+"/"+x,[...U,mt],g+1,H,[...U,mt],Y,_,z,B);let O=[...U,k++],K=n.length;f(S,S===l?x:S.main,R,D,y+"/"+x,O,g+1,H,b,Y,_,z,B),C?.set(v+"|"+x,{n:1,from:K,to:n.length})},I=pt(T),N=s?lt(T):[],j=0,X=(S,x,R,D,U,H,z,V)=>{if(b)D=b;let O={part:S,color:x,m:R,step:D[0],steps:D,localStep:U,path:y};if(V)O.colour=V;if(F){if(O.sub=F,i)O.subPath=Y,O.subMats=_}if(H)O.embedded=!0;if(z){let q=ft(S,z);O.texPart=q.name,O.texSource=q.source}let K=I[U];if(K)O.view=K;return n.push(O),O},W=(S)=>{while(j<N.length&&N[j]<=S){let x=N[j++];X(De(T.name,x),w,d,[...L,x],x,!1,null,A).source=c(T,x)}};for(let S of T.cmds){if(S.t===0&&S.step){v++;continue}let x=S;if(x.t>=2||x.t===0&&x.geom&&x.geom.t>=2){W(v);continue}if(x.t===0){if(x.meta==="!COLOUR"){let q=tn(x.text);if(q&&q.code!==16&&q.code!==24)(B=new Map(B??[])).set(q.code,q);continue}if(o&&x.geom?.t===1)x=x.geom;else continue}if(x.t!==1)continue;if(o&&x.fallback)continue;let R=x.color===16?w:x.color,D=x.color===16?A:B?.get(x.color),U=at(d,x.m),H=[...L,v],z=o?x.tex??m:null,V=z?ut(x.m):null,O=z&&V?it(z,V):null;if(l.files.has(x.file)){if(Re(l,x.file)==="model"){G(l,x.file,U,R,H,O,D);continue}X(x.file,R,U,H,v,!0,O,D);continue}let K=t.resolveModel?.(x.file);if(K){G(K,x.file,U,R,H,O,D);continue}X(x.file,R,U,H,v,!1,O,D)}if(W(1/0),C){for(let S of C.values())if(S.n>1)for(let x=S.from;x<S.to;x++)n[x].mult??=S.n}};if(Re(e,e.main)==="part"){if(e.files.get(e.main))n.push({part:e.main,color:16,m:[...Fe],step:0,steps:[0],localStep:0,path:e.main,embedded:!0});return n}return f(e,e.main,Fe,16,e.main,[],0,null),n}function dt(e,t="main.ldr",n){return Qt(ot(e,t,{geometryText:!0}),n)}var en=new Set(["CHROME","PEARLESCENT","RUBBER","MATTE_METALLIC","METAL","MATERIAL"]);function Ue(e){if(!e)return null;if(e.startsWith("#")&&/^#[0-9A-Fa-f]{6}$/.test(e))return e.toUpperCase();if(/^0x[0-9A-Fa-f]{6}$/i.test(e))return("#"+e.slice(2)).toUpperCase();return null}function ht(e,t){let n={value:"#FFFFFF",fraction:0.5};while(t<e.length){let r=e[t].toUpperCase(),s=e[t+1];if(r==="VALUE"){let o=Ue(s);if(o)n.value=o;t+=2}else if(r==="ALPHA")n.alpha=+s,t+=2;else if(r==="LUMINANCE")n.luminance=+s,t+=2;else if(r==="FRACTION")n.fraction=+s,t+=2;else if(r==="VFRACTION")n.vfraction=+s,t+=2;else if(r==="SIZE")n.size=+s,t+=2;else if(r==="MINSIZE")n.minsize=+s,t+=2;else if(r==="MAXSIZE")n.maxsize=+s,t+=2;else break}return{grain:n,next:t}}function tn(e){let t=e.indexOf("!COLOUR");if(t<0)return null;let n=e.slice(t+7).trim().split(/\\s+/).filter(Boolean);if(n.length<2)return null;let r=n[0],s=NaN,o="#FF00FF",i="#333333",a=255,u=0,c={type:"default"},f=1;while(f<n.length){let l=n[f].toUpperCase(),p=n[f+1];if(l==="CODE")s=p!==void 0&&ke.test(p)?Ie(p):p!==void 0&&/^\\d+$/.test(p)?+p:NaN,f+=2;else if(l==="VALUE"){let d=Ue(p);if(d)o=d;f+=2}else if(l==="EDGE")i=Ue(p)??p,f+=2;else if(l==="ALPHA")a=+p,f+=2;else if(l==="LUMINANCE")u=+p,f+=2;else if(l==="CHROME")c={type:"chrome"},f+=1;else if(l==="PEARLESCENT")c={type:"pearlescent"},f+=1;else if(l==="RUBBER")c={type:"rubber"},f+=1;else if(l==="MATTE_METALLIC")c={type:"matte_metallic"},f+=1;else if(l==="METAL")c={type:"metal"},f+=1;else if(l==="MATERIAL"){let d=(n[f+1]||"").toUpperCase();if(d==="GLITTER"){let{grain:w,next:y}=ht(n,f+2);c={type:"glitter",material:w},f=y}else if(d==="SPECKLE"){let{grain:w,next:y}=ht(n,f+2);c={type:"speckle",material:w},f=y}else if(d==="FABRIC"){let w=(n[f+2]||"").toUpperCase(),y=["VELVET","CANVAS","STRING","FUR"].includes(w)?w.toLowerCase():void 0;c={type:"fabric",kind:y},f+=y?3:2}else f=n.length}else if(en.has(l))f+=1;else f+=1}if(Number.isNaN(s)||!o)return null;return{code:s,name:r,hex:o,edge:i,alpha:Number.isFinite(a)?a:255,luminance:Number.isFinite(u)?u:0,finish:c}}function nn(e){let t=Math.max(0,Math.min(1,(e.alpha??255)/255)),n=t<1,r=Math.max(0,Math.min(1,(e.luminance??0)/255)),s={opacity:t,transparent:n,depthWrite:!n,emissive:r,clearcoat:0,clearcoatRoughness:0,sheen:0,sheenRoughness:0};switch(e.finish?.type??"default"){case"chrome":return{...s,metalness:1,roughness:0,finish:"chrome"};case"pearlescent":return{...s,metalness:0.25,roughness:0.3,clearcoat:0.5,clearcoatRoughness:0.25,sheen:0.4,sheenRoughness:0.35,finish:"pearlescent"};case"rubber":return{...s,metalness:0,roughness:0.9,finish:"rubber"};case"matte_metallic":return{...s,metalness:0.4,roughness:0.8,finish:"matte_metallic"};case"metal":return{...s,metalness:0.85,roughness:0.2,finish:"metal"};case"glitter":{let i=e.finish.material,a=i.size??(i.minsize!=null&&i.maxsize!=null?(i.minsize+i.maxsize)/2:1);return{...s,metalness:0.35,roughness:0.25,clearcoat:1,clearcoatRoughness:0.08,particleHex:i.value,particleFraction:i.fraction,particleSize:a,finish:"glitter"}}case"speckle":{let i=e.finish.material,a=i.size??(i.minsize!=null&&i.maxsize!=null?(i.minsize+i.maxsize)/2:1);return{...s,metalness:0.2,roughness:0.55,particleHex:i.value,particleFraction:i.fraction,particleSize:a,finish:"speckle"}}case"fabric":return{...s,metalness:0,roughness:0.85,sheen:0.65,sheenRoughness:0.75,finish:"fabric"};default:return{...s,metalness:0,roughness:0.45,finish:"default"}}}function Oe(e){let t=nn(e),n=!t.transparent?"op":t.opacity>=0.75?"a200":t.opacity>=0.4?"a128":`a${Math.round(t.opacity*255)}`,r=t.emissive>0?`L${Math.round(t.emissive*16)}`:"",s=`${t.finish}:${n}${r}`;if(t.particleHex)s+=`:${t.particleHex}:${(t.particleFraction??0).toFixed(2)}`;return s}function rn(e,t){let n=new Map,r=null,s=!1;for(let o of e.split(/\\r?\\n/)){let i=/^\\s*0\\s+FILE\\s+(.+)$/i.exec(o);if(i){if(!s)n.clear();s=!0,r=[],n.set(Q(i[1]),r);continue}if(/^\\s*0\\s+(NOFILE|!DATA)(\\s|$)/i.test(o)){if(!s)n.clear();s=!0,r=null;continue}if(!r){if(s)continue;r=[],n.set(Q(t),r)}let a=o.trim().replace(/\\s+/g," ");if(a)r.push(a)}return n}var sn=(e)=>{if(!e.startsWith("1 "))return null;let t=e.split(" ");return t.length>=15?Q(t.slice(14).join(" ")):null};function on(e){let t=2166136261,n=1523705862;for(let r=0;r<e.length;r++){let s=e.charCodeAt(r);t=Math.imul(t^s,16777619),n=Math.imul(n^s,16777629)^n>>>15}return(t>>>0).toString(16).padStart(8,"0")+(n>>>0).toString(16).padStart(8,"0")}function bt(e,t,n="main.ldr"){let r=rn(e,n),s=new Map;for(let o of t){let i=Q(o);if(!r.has(i)||s.has(i))continue;let a=new Set([i]),u=[i];while(u.length)for(let f of r.get(u.pop())){let l=sn(f);if(l&&r.has(l)&&!a.has(l))a.add(l),u.push(l)}let c=[i,...[...a].filter((f)=>f!==i).sort()].map((f)=>"0 FILE "+(f===i?"":f)+`\n`+r.get(f).join(`\n`)).join(`\n`);s.set(i,`emb/${on(c)}.dat`)}return s}var yt=(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,xt=new WeakMap;function Ne(e,t){let n=xt.get(e);if(!n)xt.set(e,n=new Map);let r=n.get(t);if(r!==void 0)return r;let s=e.parts[t];if(!s)return n.set(t,null),null;let o=s.studs.length,i=new Float64Array(o*12),a=[],u=[];s.studs.forEach((p,d)=>{a.push(p[0]),u.push(p[1]);for(let w=0;w<12;w++)i[d*12+w]=p[2+w]});let c=null,f=0,l=0;if(s.mask){f=s.mask[0],l=s.mask[1];let p=s.mask[2];c=new Uint8Array(p.length);for(let d=0;d<p.length;d++)c[d]=p.charCodeAt(d)===49?1:0}return n.set(t,r={nStuds:o,studM:i,kind:a,color:u,mask:c,nx:f,nz:l}),r}var ie=1073741824;class ze{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),s=this.used,o=this.a,i=this.b,a=this.c;for(;;){if(!s[r])return-1;if(o[r]===e&&i[r]===t&&a[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 s=this.slot(e,t,n),o=this.used,i=this.a,a=this.b,u=this.c;for(;;){if(!o[s])return o[s]=1,i[s]=e,a[s]=t,u[s]=n,this.vals[s]=r,this.size++,-1;if(i[s]===e&&a[s]===t&&u[s]===n){let c=this.vals[s];return this.vals[s]=r,c}s=s+1&this.mask}}grow(){let{a:e,b:t,c:n,vals:r,used:s}=this,o=s.length*2;this.a=new Int32Array(o),this.b=new Int32Array(o),this.c=new Int32Array(o),this.vals=new Int32Array(o),this.used=new Uint8Array(o),this.mask=o-1,this.size=0;for(let i=0;i<s.length;i++)if(s[i])this.put(e[i],t[i],n[i],r[i])}}var we=(e,t,n)=>e>-ie&&e<ie&&t>-ie&&t<ie&&n>-ie&&n<ie,fe=2147483647;function an(e,t,n){let s=[],o=[],i=[],a=[],u=[],c=[],f=[],l=[],p=new ze(e.length*2),d=[],w=[];for(let C=0;C<e.length;C++){let M=e[C],k=M.m,G=t.parts[M.part];if(!G||!G.mask||!yt(k))continue;let I=G.bbox,N=1/0,j=-1/0,X=1/0,W=-1/0;for(let R=0;R<2;R++)for(let D=0;D<2;D++){let U=R?I[3]:I[0],H=D?I[5]:I[2],z=k[0]+k[3]*U+k[5]*H,V=k[2]+k[9]*U+k[11]*H;if(z<N)N=z;if(z>j)j=z;if(V<X)X=V;if(V>W)W=V}let S=u.length;s.push(N),o.push(j),i.push(X),a.push(W),u.push(C),c.push(Ne(t,M.part)),f.push(I[0]),l.push(I[2]);let x=Math.round((k[1]+I[4])*2);for(let R=Math.floor(N/40);R<=Math.floor(j/40);R++)for(let D=Math.floor(X/40);D<=Math.floor(W/40);D++){if(!we(x,R,D))continue;let U=w.length;w.push(S),d.push(p.put(x,R,D,U))}}let y=[0,5,-5,5,-5],L=[0,5,5,-5,-5],g=NaN,m=NaN,b=NaN,h=-1,P=(C,M,k,G)=>{let I=Math.round(M*2),N=Math.floor(C/40),j=Math.floor(k/40);if(!we(I,N,j))return fe;let X=fe;if(I!==g||N!==m||j!==b)g=I,m=N,b=j,h=p.get(I,N,j);for(let W=h;W>=0;W=d[W]){let S=w[W];if(u[S]===G||!(C-6>=s[S]-0.5&&C+6<=o[S]+0.5&&k-6>=i[S]-0.5&&k+6<=a[S]+0.5))continue;let x=e[u[S]].m,R=c[S],D=f[S],U=l[S],H=C-x[0],z=M-x[1],V=k-x[2],O=x[3]*H+x[6]*z+x[9]*V,K=x[5]*H+x[8]*z+x[11]*V,{nx:q,nz:se,mask:ae}=R,oe=!0;for(let ee=0;ee<5;ee++){let te=Math.floor((O+y[ee]-D)/20),ne=Math.floor((K+L[ee]-U)/20);if(te<0||ne<0||te>=q||ne>=se||ae[te*se+ne]!==1){oe=!1;break}}if(oe){if(!n)return 0;let ee=n[u[S]];if(ee<X)X=ee}}return X},A=0;for(let C of e){let M=Ne(t,C.part);if(M)A+=M.nStuds}let E=new Uint8Array(A),T=new Uint8Array(A),B=new ze(A),v=0,F=n?new Int32Array(A).fill(fe):void 0;for(let C=0,M=0;C<e.length;C++){let k=e[C],G=Ne(t,k.part);if(!G)continue;let I=k.m,N=G.studM,j=I[0],X=I[1],W=I[2],S=I[3],x=I[4],R=I[5],D=I[6],U=I[7],H=I[8],z=I[9],V=I[10],O=I[11];for(let K=0;K<G.nStuds;K++,M++){let q=K*12,se=N[q+4],ae=N[q+7],oe=N[q+10];if(!(Math.abs(D*se+U*ae+H*oe-1)<0.001&&Math.abs(S*se+x*ae+R*oe)<0.001&&Math.abs(z*se+V*ae+O*oe)<0.001))continue;T[M]=1;let ee=N[q],te=N[q+1],ne=N[q+2],$e=j+S*ee+x*te+R*ne,je=X+D*ee+U*te+H*ne,Ve=W+z*ee+V*te+O*ne,_e=P($e,je,Ve,C);if(_e!==fe){if(E[M]=1,v++,F)F[M]=_e}let me=Math.round($e),he=Math.round(je),ge=Math.round(Ve);if(!we(me,he,ge))continue;if(!n){B.put(me,he,ge,1);continue}let He=n[C],Ge=B.get(me,he,ge);if(Ge<0||He<Ge)B.put(me,he,ge,He)}}let Y=new Uint8Array(e.length),_=n?new Int32Array(e.length).fill(fe):void 0;for(let C=0;C<e.length;C++){let M=e[C],k=t.parts[M.part];if(!k||!k.under||!yt(M.m))continue;let G=k.bbox,I=Math.round((G[3]-G[0])/20),N=Math.round((G[5]-G[2])/20);if(!I||!N||I*N>4096)continue;let j=M.m,X=!0,W=0;for(let S=0;S<I&&X;S++)for(let x=0;x<N;x++){let R=G[0]+10+20*S,D=G[2]+10+20*x,U=j[0]+j[3]*R+j[5]*D,H=j[2]+j[9]*R+j[11]*D,z=Math.round(U),V=Math.round(j[1]+G[4]),O=Math.round(H),K=we(z,V,O)?B.get(z,V,O):-1;if(K<0){X=!1;break}if(K>W)W=K}if(X){if(Y[C]=1,_)_[C]=W}}return{nStuds:A,studHidden:E,studUp:T,underHidden:Y,studsHidden:v,studHideStep:F,underHideStep:_}}function ln(e,t,n){let r=(l)=>n&&l.texPart&&t.parts[l.texPart]?l.texPart:l.part,s=new Map,o=new Map,i=(l)=>{let p=l.colour;if(!p)return String(l.color);let d=o.get(p);if(d!==void 0)return d;let w=t.colorTable?.[l.color],y=w?.hex??t.colors?.[l.color],L=w?Oe({alpha:w.alpha??255,luminance:w.luminance??0,finish:w.finish??{type:"default"}}):"default:op",g=Oe(p);if(d=y&&y.toUpperCase()===p.hex.toUpperCase()&&L===g?String(l.color):p.hex.toUpperCase()+"/"+g,d!==String(l.color))s.set(d,p);return o.set(p,d),d},a=e.map((l)=>({part:r(l),color:i(l),m:l.m,steps:l.steps})),u=a.map((l)=>gt(l.steps)),c=[...new Set(u)].sort(),f=new Map(c.map((l,p)=>[l,p]));return{all:a,stepOf:u.map((l)=>f.get(l)),nSteps:c.length,localColours:s}}function Ae(e,t,n=!0){let r=ln(e,t,n);return an(r.all,t,r.nSteps>1?r.stepOf:void 0)}var Te="https://ldr-demo.vercel.app/cdn/v1/",ve=new Map,Me=new Map;function At(e=Te,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 cn=(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"),Ce=(e,t)=>cn(e)?[e[0]+t,e[1],e[2]]:Array.isArray(e)?e.map((n)=>Ce(n,t)):e&&typeof e==="object"?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,Ce(r,t)])):e;function un(e,t={}){let n=[],r=0,s={},o={};for(let p of e){let d=p.buffer;if(!d)throw Error("ldr: mergePacks needs packs from decodePack/loadPack");let w=new DataView(d).getUint32(0,!0),y=new Uint8Array(d,4+w),L=r;n.push(y),r+=y.byteLength;let g=(4-r%4)%4;if(g)n.push(new Uint8Array(g)),r+=g;for(let[m,b]of Object.entries(p.header.parts??{}))if(!(m in s))s[m]=Ce(b,L);for(let[m,b]of Object.entries(p.header.studKinds??{}))if(!(m in o))o[m]=Ce(b,L)}let i=e[0]?.header??{version:1,weld:!0},a=new TextEncoder().encode(JSON.stringify({...i,parts:s,studKinds:o,...t})),u=(4-(4+a.length)%4)%4,c=4+a.length+u,f=new Uint8Array(c+r);new DataView(f.buffer).setUint32(0,a.length+u,!0),f.set(a,4),f.fill(32,4+a.length,c);let l=c;for(let p of n)f.set(p,l),l+=p.byteLength;return xe(f.buffer)}async function fn(e,t={}){e=[...e];try{return await wt(e,t)}catch(n){let r=t.cdn??Te,s=t.fetch??fetch;ve.delete(r);let o=(i,a)=>s(i,{...a,cache:"reload"});try{return await wt(e,{...t,fetch:o})}catch{throw n}}}async function wt(e,t){let n=t.cdn??Te,r=t.fetch??fetch,s=t.gap??16384,o=await At(n,r),i=[...new Set([...e].map(Q))],a=[],u=[];for(let g of i){if(Me.has(n+g))continue;let m=o.parts[g];if(m)u.push({name:g,off:m[0],len:m[1],file:m[2]??0});else a.push(g)}u.sort((g,m)=>g.file-m.file||g.off-m.off);let c=[];for(let g of u){let m=c[c.length-1];if(m&&m.file===g.file&&g.off-m.end<=s)m.end=Math.max(m.end,g.off+g.len),m.items.push(g);else c.push({file:g.file,start:g.off,end:g.off+g.len,items:[g]})}let f=0,l=0,p=0,d=new Map,w=async()=>{while(p<c.length){let g=c[p++],m=d.get(g.file);if(m)m=m.subarray(g.start,g.end);else{let b=await r(new URL(o.archives[g.file],n).href,{headers:{Range:`bytes=${g.start}-${g.end-1}`,"Accept-Encoding":"identity"}});if(!b.ok)throw Error(`ldr: parts CDN ${b.status}`);if(l++,m=new Uint8Array(await b.arrayBuffer()),f+=m.byteLength,b.status===200)d.set(g.file,m),m=m.subarray(g.start,g.end)}for(let b of g.items){let h=ye(m.subarray(b.off-g.start,b.off-g.start+b.len)),P=h.buffer.slice(h.byteOffset,h.byteOffset+h.byteLength);Me.set(n+b.name,xe(P))}}};await Promise.all(Array.from({length:Math.min(t.concurrency??24,c.length)},w));let y=i.filter((g)=>Me.has(n+g)).map((g)=>Me.get(n+g));return{pack:y.length?un(y,{colors:o.colors}):xe(pn(o.colors)),missing:a,requests:l,bytes:f}}function pn(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}function mn(e,t){let n=t.header.parts;if(!n)return 0;let r=0;for(let s of e){let o=n[s.part]?.body?.tris;if(o)r+=o}return r}function hn(e,t,n){let r=0,s=0,o=!1,i=new Set;for(let a of e){let u=a.embedded?t.get(a.part):Q(a.part),c=u?n.parts[u]:void 0;if(!c)continue;if(c[3]!=null)o=!0,r+=c[3];if(!i.has(u))i.add(u),s+=c[1]}return{bodyTris:r,packBytes:s,known:o}}class pe extends Error{code="ldr-budget";bodyTris;packBytes;maxBodyTris;maxPackBytes;constructor(e){let t=[e.maxBodyTris!=null&&e.bodyTris>e.maxBodyTris?`${e.bodyTris} triangles (limit ${e.maxBodyTris})`:"",e.maxPackBytes!=null&&e.packBytes>e.maxPackBytes?`${(e.packBytes/1e6).toFixed(1)} MB parts pack (limit ${(e.maxPackBytes/1e6).toFixed(0)} MB)`:""].filter(Boolean).join(", ");super(`ldr: model exceeds device budget: ${t}`);this.name="BudgetError",this.bodyTris=e.bodyTris,this.packBytes=e.packBytes,this.maxBodyTris=e.maxBodyTris,this.maxPackBytes=e.maxPackBytes}}async function Mt(e,t={}){let n=performance.now(),r=t.fetch??fetch,s=At(t.cdn??Te,r);s.catch(()=>{});let o=t.text?e:await r(e).then(async(h)=>{if(!h.ok)throw Error(`ldr: ${h.status} fetching ${e}`);return Xe(await h.arrayBuffer())}),i=performance.now(),a=t.name??(t.text?"main.ldr":Ze(e)),u=dt(o,a,{looseGeometry:!1,callouts:t.callouts}),c=performance.now();t.onParsed?.(u),await s;let f=bt(o,new Set(u.filter((h)=>h.embedded).map((h)=>h.part)),a),l=(h,P)=>t.maxBodyTris!=null&&h>t.maxBodyTris||t.maxPackBytes!=null&&P>t.maxPackBytes;if(t.maxBodyTris!=null||t.maxPackBytes!=null){let h=hn(u,f,await s);if(l(h.known?h.bodyTris:0,h.packBytes))throw new pe({bodyTris:h.bodyTris,packBytes:h.packBytes,maxBodyTris:t.maxBodyTris,maxPackBytes:t.maxPackBytes})}let{pack:p,missing:d,requests:w,bytes:y}=await fn([...u.filter((h)=>!h.embedded).map((h)=>h.part),...f.values()],t),L=new Map([...f].map(([h,P])=>[P,h])),g=d.map((h)=>L.get(h)??h);for(let[h,P]of f){let A=p.header.parts[P];if(A)p.header.parts[h]=A}let m=performance.now();if(t.maxBodyTris!=null||t.maxPackBytes!=null){let h=p.buffer?.byteLength??p.bytes??0,P=mn(u,p);if(l(P,h))throw new pe({bodyTris:P,packBytes:h,maxBodyTris:t.maxBodyTris,maxPackBytes:t.maxPackBytes})}let b=t.cull?Ae(u,p.header,t.textures!==!1):void 0;return{insts:u,pack:p,missing:g,requests:w,bytes:y,cull:b,timings:{fetchModel:i-n,parse:c-i,parts:m-c,...b?{cull:performance.now()-m}:{}}}}self.onmessage=async(e)=>{let{id:t,source:n,opts:r}=e.data;try{let s=await Mt(n,{...r,cull:!1,onParsed:(f)=>self.postMessage({id:t,insts:f})}),o=s.pack.buffer;if(self.postMessage({id:t,buffer:o,missing:s.missing,requests:s.requests,bytes:s.bytes,timings:s.timings},[o]),!r.cull)return;let i=performance.now(),a=Ae(s.insts,s.pack.header,r.textures!==!1),u=performance.now()-i,c=[];for(let f of[a.studHidden,a.studUp,a.underHidden,a.studHideStep,a.underHideStep])if(f)c.push(f.buffer);self.postMessage({id:t,cull:a,ms:u},c)}catch(s){if(s instanceof pe||s?.code==="ldr-budget")self.postMessage({id:t,phase:"error",error:String(s?.message??s),budget:{bodyTris:s.bodyTris,packBytes:s.packBytes,maxBodyTris:s.maxBodyTris,maxPackBytes:s.maxPackBytes}});else self.postMessage({id:t,phase:"error",error:String(s?.message??s)})}};\n';
|
|
4166
4329
|
|
|
4167
|
-
// ../../../../../../../tmp/ldr-build-
|
|
4330
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/cdn.ts
|
|
4168
4331
|
var worker;
|
|
4169
4332
|
var seq = 0;
|
|
4170
4333
|
var pending = new Map;
|
|
@@ -4277,7 +4440,7 @@ async function loadModel(source, o = {}) {
|
|
|
4277
4440
|
timings: { ...prep.timings, parts: t3 - t0 - prep.timings.fetchModel - prep.timings.parse, build: t4 - t3, total: t4 - t0 }
|
|
4278
4441
|
});
|
|
4279
4442
|
}
|
|
4280
|
-
// ../../../../../../../tmp/ldr-build-
|
|
4443
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/node/library.ts
|
|
4281
4444
|
import { existsSync, readFileSync } from "fs";
|
|
4282
4445
|
import { join } from "path";
|
|
4283
4446
|
var xf = (m, x, y, z) => [m[3] * x + m[4] * y + m[5] * z + m[0], m[6] * x + m[7] * y + m[8] * z + m[1], m[9] * x + m[10] * y + m[11] * z + m[2]];
|
|
@@ -4531,11 +4694,11 @@ class Library {
|
|
|
4531
4694
|
return insts;
|
|
4532
4695
|
}
|
|
4533
4696
|
}
|
|
4534
|
-
// ../../../../../../../tmp/ldr-build-
|
|
4697
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/node/build-pack.ts
|
|
4535
4698
|
import fs3 from "node:fs";
|
|
4536
4699
|
import path3 from "node:path";
|
|
4537
4700
|
|
|
4538
|
-
// ../../../../../../../tmp/ldr-build-
|
|
4701
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/node/resolver.ts
|
|
4539
4702
|
import fs from "node:fs";
|
|
4540
4703
|
import path from "node:path";
|
|
4541
4704
|
var TOP_STUD_RE = /^(stud|studa|stud2|stud2a|stud6|stud6a|stud10|stud15|stud2s|stud2s2|stud-logo\d*|stud2-logo\d*)\.dat$/i;
|
|
@@ -4807,11 +4970,11 @@ function collectDeps(lib, refs) {
|
|
|
4807
4970
|
return out;
|
|
4808
4971
|
}
|
|
4809
4972
|
|
|
4810
|
-
// ../../../../../../../tmp/ldr-build-
|
|
4973
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/node/compile.ts
|
|
4811
4974
|
import fs2 from "node:fs";
|
|
4812
4975
|
import path2 from "node:path";
|
|
4813
4976
|
|
|
4814
|
-
// ../../../../../../../tmp/ldr-build-
|
|
4977
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/node/lod.ts
|
|
4815
4978
|
import { MeshoptSimplifier, MeshoptEncoder } from "meshoptimizer";
|
|
4816
4979
|
await Promise.all([MeshoptSimplifier.ready, MeshoptEncoder.ready]);
|
|
4817
4980
|
function reorderMesh(P, N, C, I) {
|
|
@@ -5003,7 +5166,7 @@ function lodChain(P, C, I) {
|
|
|
5003
5166
|
return out;
|
|
5004
5167
|
}
|
|
5005
5168
|
|
|
5006
|
-
// ../../../../../../../tmp/ldr-build-
|
|
5169
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/node/compile.ts
|
|
5007
5170
|
function loadColors(root) {
|
|
5008
5171
|
const map = new Map;
|
|
5009
5172
|
for (const l of fs2.readFileSync(path2.join(root, "LDConfig.ldr"), "latin1").split(/\r?\n/)) {
|
|
@@ -5640,7 +5803,7 @@ function encodePack(parts, studKinds, weld, extra, options = {}) {
|
|
|
5640
5803
|
return Buffer.concat([head, ...chunks.map((c) => new Uint8Array(c.buffer, c.byteOffset, c.byteLength))]);
|
|
5641
5804
|
}
|
|
5642
5805
|
|
|
5643
|
-
// ../../../../../../../tmp/ldr-build-
|
|
5806
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/node/build-pack.ts
|
|
5644
5807
|
function buildPack(o) {
|
|
5645
5808
|
const lib = new Library2(o.ldrawRoot);
|
|
5646
5809
|
const refs = new Map;
|
|
@@ -5707,7 +5870,7 @@ function buildPack(o) {
|
|
|
5707
5870
|
const warnings = [...lib.conflicts].map((n) => `${n}: defined differently by two models; the first definition is used`);
|
|
5708
5871
|
return { data: encodePack(parts, kinds, comp.opts.weld, extra, { texture, lod: o.lod !== false, reorder: !!o.reorder }), parts: parts.size, studKinds: kinds.size, missing: [...missing], ...warnings.length ? { warnings } : {} };
|
|
5709
5872
|
}
|
|
5710
|
-
// ../../../../../../../tmp/ldr-build-
|
|
5873
|
+
// ../../../../../../../tmp/ldr-build-95sBCS/src/node/promote.ts
|
|
5711
5874
|
var GEOM = /^\s*[2-5]\s/;
|
|
5712
5875
|
var REF = /^\s*1\s/;
|
|
5713
5876
|
var FILE = /^\s*0\s+FILE\s+(.+?)\s*$/i;
|
package/dist/render.d.ts
CHANGED
|
@@ -89,10 +89,11 @@ export declare function computeCulling(insts: Inst[], H: any): {
|
|
|
89
89
|
/** Drive buildLdrSceneGen to completion without yielding (same as pre-Round-33 sync build). */
|
|
90
90
|
export declare function buildLdrScene(insts: Inst[], pack: Pack, P: LdrParams, color: (c: string) => THREE.Color, mark: (k: string) => void): any;
|
|
91
91
|
export type BuildLdrSceneAsyncOptions = {
|
|
92
|
-
/**
|
|
92
|
+
/** Cap on contiguous main-thread work between yields while mid-build paints are active (ms). Default 8. The build yields before a
|
|
93
|
+
* step that would likely overrun it (reserve: the longest step so far, between a third and half of the cap). */
|
|
93
94
|
sliceMs?: number;
|
|
94
95
|
/**
|
|
95
|
-
*
|
|
96
|
+
* Cap after mid-build paints stop (onSlice returned false, or no onSlice). Default max(sliceMs, 24). Same predictive yield as sliceMs.
|
|
96
97
|
* Larger slices cut yield/timer overhead on the remaining build without changing the sync path.
|
|
97
98
|
*/
|
|
98
99
|
postPaintSliceMs?: number;
|
|
@@ -108,4 +109,10 @@ export type BuildLdrSceneAsyncOptions = {
|
|
|
108
109
|
* After onSlice returns false (TTFP done), slices coarsen to postPaintSliceMs and paints stop — cuts total loadMs.
|
|
109
110
|
*/
|
|
110
111
|
export declare function buildLdrSceneAsync(insts: Inst[], pack: Pack, P: LdrParams, color: (c: string) => THREE.Color, mark: (k: string) => void, opts?: BuildLdrSceneAsyncOptions): Promise<any>;
|
|
112
|
+
/** Drives a build generator in main-thread slices (see BuildLdrSceneAsyncOptions); internal, exported for tests. */
|
|
113
|
+
export declare function runSliced<R>(g: Generator<THREE.Object3D, R, void>, opts?: BuildLdrSceneAsyncOptions): Promise<{
|
|
114
|
+
value: R;
|
|
115
|
+
longestSliceMs: number;
|
|
116
|
+
yields: number;
|
|
117
|
+
}>;
|
|
111
118
|
export declare function warmPackGeometry(pack: Pack, stop?: () => boolean, sliceMs?: number): Promise<void>;
|
package/dist/scene.d.ts
CHANGED
|
@@ -51,9 +51,9 @@ export interface LdrObjectOptions {
|
|
|
51
51
|
/** LOD: skip undersides that can't be seen: while the camera is behind every bottom face of a cluster's (same-orientation) parts and
|
|
52
52
|
* studs are under 4 px, or where the body is drawn as its closed bounding box. Default true. */
|
|
53
53
|
lodUnder?: boolean;
|
|
54
|
-
/** Progressive build (createLdrObjectAsync / loadModel):
|
|
54
|
+
/** Progressive build (createLdrObjectAsync / loadModel): cap on each main-thread slice while mid-build paints are active, ms (the build yields before a step that would likely overrun it). Default 8. */
|
|
55
55
|
sliceMs?: number;
|
|
56
|
-
/** Progressive build:
|
|
56
|
+
/** Progressive build: slice cap after paints stop (onSlice returned false / no onSlice). Default max(sliceMs, 24). */
|
|
57
57
|
postPaintSliceMs?: number;
|
|
58
58
|
/**
|
|
59
59
|
* Progressive build: called after each yield while paints are enabled; live object holds finished batches — render for TTFP.
|
|
@@ -108,10 +108,23 @@ export interface LdrObject {
|
|
|
108
108
|
setSide(side: "front" | "double"): void;
|
|
109
109
|
/** Turn distance LOD on/off (off = full detail and edges everywhere). Only has an effect if the object was built with `lod` (default). */
|
|
110
110
|
setLod(on: boolean): void;
|
|
111
|
+
/** Ghost overlay of the upcoming steps (like the LEGO Builder app): while a step is shown with `setStep`, the parts of later steps
|
|
112
|
+
* are drawn as a faint, whitish, depth-tested ghost of the finished model; built parts draw as usual. Built lazily (a second,
|
|
113
|
+
* edge-free copy of the scene with the steps reversed, so its step-aware culling matches the ghosted set) the first time it is
|
|
114
|
+
* needed, with yields like the progressive build; resolves when it is ready. No effect on single-step models. */
|
|
115
|
+
setGhost(on: boolean, options?: GhostOptions): Promise<void>;
|
|
111
116
|
/** Bounding box in the object's parent space. */
|
|
112
117
|
getBox(target?: THREE.Box3): THREE.Box3;
|
|
113
118
|
dispose(): void;
|
|
114
119
|
}
|
|
120
|
+
export interface GhostOptions {
|
|
121
|
+
/** Ghost opacity, 0-1. Default 0.2. */
|
|
122
|
+
opacity?: number;
|
|
123
|
+
/** Ghost tint (mixed with each part's own colour by `whiten`). Default white. */
|
|
124
|
+
color?: THREE.ColorRepresentation;
|
|
125
|
+
/** How far each part's colour is pushed towards `color`, 0-1. Default 0.75. */
|
|
126
|
+
whiten?: number;
|
|
127
|
+
}
|
|
115
128
|
/**
|
|
116
129
|
* Build a three.js object for a flattened model using a parts pack.
|
|
117
130
|
* Instances whose part is not in the pack are skipped and listed in `stats.missing`.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ldr",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.0",
|
|
4
4
|
"description": "High-performance LEGO (LDraw) rendering for three.js: instanced parts packs, hidden stud/tube culling, low-detail studs, indexed edges, build steps.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Evan Bacon",
|