ldr 0.8.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,4 @@
1
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/spec.ts
1
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/spec.ts
2
2
  var norm = (s) => s.trim().toLowerCase().replace(/\\/g, "/").replace(/\/+/g, "/");
3
3
  function parseColor(tok) {
4
4
  if (/^0x/i.test(tok))
@@ -690,7 +690,7 @@ function fileStepViews(f) {
690
690
  viewMemo.set(f, out);
691
691
  return out;
692
692
  }
693
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/model.ts
693
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/model.ts
694
694
  var CALLOUT_END = 999999;
695
695
  var stepKey = (steps) => steps.map((x) => String(x).padStart(6, "0")).join(".") + "~";
696
696
  function flatten(doc, opts = {}) {
@@ -848,7 +848,7 @@ function parseLDConfig(text) {
848
848
  }
849
849
  return out;
850
850
  }
851
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/instructions.ts
851
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/instructions.ts
852
852
  var MIN_VIS = 0.5;
853
853
  var REORIENT = 0.35;
854
854
  var deg = Math.PI / 180;
@@ -1216,10 +1216,10 @@ function planStepViews(insts, parts, stepOf, nSteps, o = {}) {
1216
1216
  }
1217
1217
  };
1218
1218
  }
1219
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/render.ts
1219
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/render.ts
1220
1220
  import * as THREE from "three";
1221
1221
 
1222
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/pack-io.ts
1222
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/pack-io.ts
1223
1223
  import { decompress } from "fzstd";
1224
1224
  async function decompressPack(data) {
1225
1225
  const u = data instanceof Uint8Array ? data : new Uint8Array(data);
@@ -1238,7 +1238,7 @@ function decodePack(buf) {
1238
1238
  return { header, arr, bytes: buf.byteLength, buffer: buf };
1239
1239
  }
1240
1240
 
1241
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/cull.ts
1241
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/cull.ts
1242
1242
  var upright = (m, o = 0) => Math.abs(m[o + 7] - 1) < 0.001 && Math.abs(m[o + 4]) < 0.001 && Math.abs(m[o + 10]) < 0.001;
1243
1243
  var prepCache = new WeakMap;
1244
1244
  function prepPart(H, part) {
@@ -1555,7 +1555,7 @@ function precomputeCull(instances, H, useTex = true) {
1555
1555
  return cullCore(s.all, H, s.nSteps > 1 ? s.stepOf : undefined);
1556
1556
  }
1557
1557
 
1558
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/render.ts
1558
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/render.ts
1559
1559
  async function loadPack(url) {
1560
1560
  const res = await fetch(url);
1561
1561
  if (!res.ok)
@@ -1620,7 +1620,9 @@ function makeMaterial(side) {
1620
1620
  m.onBeforeCompile = (s) => {
1621
1621
  s.vertexShader = `attribute vec4 ldrColor;
1622
1622
  ` + s.vertexShader.replace("#include <color_vertex>", `#include <color_vertex>
1623
- #ifdef USE_INSTANCING_COLOR
1623
+ #ifdef USE_BATCHING_COLOR
1624
+ vColor.rgb = ldrColor.a > 0.5 ? pow(ldrColor.rgb, vec3(2.2)) : getBatchingColor(getIndirectIndex(gl_DrawID)).rgb;
1625
+ #elif defined(USE_INSTANCING_COLOR)
1624
1626
  vColor.rgb = ldrColor.a > 0.5 ? pow(ldrColor.rgb, vec3(2.2)) : instanceColor.rgb; // baked LDConfig colours are sRGB
1625
1627
  #else
1626
1628
  vColor.rgb = pow(ldrColor.rgb, vec3(2.2));
@@ -1996,6 +1998,24 @@ class LdrLodRoot extends THREE.LOD {
1996
1998
  L = -1;
1997
1999
  if (c.boxErr !== undefined && c.boxErr * ppl <= tau)
1998
2000
  L = -1;
2001
+ if (c.mergedLod && L >= 0) {
2002
+ const { bm, gids, errs, underHid, cullUnder } = c.mergedLod;
2003
+ for (let i = 0;i < gids.length; i++) {
2004
+ let Li = 0;
2005
+ const er = errs[i];
2006
+ for (let j = er.length - 1;j > 0; j--)
2007
+ if (er[j] * ppl <= tau) {
2008
+ Li = j;
2009
+ break;
2010
+ }
2011
+ const gd = gids[i];
2012
+ if (gd?.length)
2013
+ bm.setGeometryIdAt(i, gd[Math.min(Li, gd.length - 1)]);
2014
+ if (underHid && !bm.userData._stepMode)
2015
+ bm.setVisibleAt(i, !(cullUnder && underHid[i]));
2016
+ }
2017
+ L = 0;
2018
+ }
1999
2019
  const e = ppl >= eppl;
2000
2020
  if (L !== c.cur || e !== c.edgeOk) {
2001
2021
  c.cur = L;
@@ -2193,6 +2213,7 @@ function buildLdrScene(insts, pack, P, color, mark) {
2193
2213
  let cull = P.cull ?? cullCore(insts, H, steps);
2194
2214
  mark("culling");
2195
2215
  const stepBatches = [];
2216
+ const stepBatched = [];
2196
2217
  const instM = steps ? new Float64Array(insts.length * 12) : null;
2197
2218
  const instPP = [];
2198
2219
  const palette = [];
@@ -2315,96 +2336,359 @@ function buildLdrScene(insts, pack, P, color, mark) {
2315
2336
  });
2316
2337
  const tris = (b) => b ? b.tris ?? 0 : 0;
2317
2338
  const kFor = (t) => LOD ? Math.max(256, Math.min(16384, Math.round(262144 / Math.max(1, t)))) : Infinity;
2339
+ const MERGE_MAX = 16;
2340
+ const geomVerts = (b) => {
2341
+ if (!b)
2342
+ return 0;
2343
+ const p = arr(b.pos);
2344
+ return p.length / 3;
2345
+ };
2346
+ const geomIdx = (b) => {
2347
+ if (!b)
2348
+ return 0;
2349
+ if (!b.idx)
2350
+ return geomVerts(b);
2351
+ return arr(b.idx).length;
2352
+ };
2353
+ const coldByMat = new Map;
2318
2354
  for (const [pk, idsAll] of byPart) {
2319
2355
  const part = pk.replace(/#m$/, "");
2320
2356
  const p = H.parts[part];
2321
2357
  const mat = p.uncert ? (nUncert++, matD) : pk.endsWith("#m") ? matB : matF;
2322
2358
  const textured = wantTex && !!p.tex;
2323
- const bodyB = textured ? p.tbody : p.body;
2324
- const body = geom(bodyB, arr);
2325
- const groups = gridClusters(idsAll.length, (i) => insts[idsAll[i]].m[0], (i) => insts[idsAll[i]].m[2], textured ? Infinity : kFor(tris(p.body) + tris(p.under)));
2326
- for (const g of groups) {
2327
- const ids = Array.from(g, (i) => idsAll[i]);
2328
- let bodyIm = null;
2329
- const lv0 = [];
2330
- const place = (im) => {
2331
- fillInstances(im, ids, insts, color);
2332
- instancedBoundingSphere(im);
2333
- im.userData.ldrPart = part;
2334
- root.add(im);
2335
- };
2336
- if (body) {
2337
- const im = bodyIm = newIM(body, mat, ids.length);
2338
- place(im);
2339
- lv0.push(im);
2340
- }
2341
- if (textured)
2342
- for (const tb of p.tex) {
2343
- const gg = geom(tb, arr);
2344
- const im = newIM(gg, texMat(tb.t, mat, !!tb.wrapU), ids.length);
2345
- texBatches++;
2359
+ if (textured || idsAll.length > MERGE_MAX) {
2360
+ const bodyB = textured ? p.tbody : p.body;
2361
+ const body = geom(bodyB, arr);
2362
+ 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)));
2363
+ for (const g of groups) {
2364
+ const ids = Array.from(g, (i) => idsAll[i]);
2365
+ let bodyIm = null;
2366
+ const lv0 = [];
2367
+ const place = (im) => {
2368
+ fillInstances(im, ids, insts, color);
2369
+ instancedBoundingSphere(im);
2370
+ im.userData.ldrPart = part;
2371
+ root.add(im);
2372
+ };
2373
+ if (body) {
2374
+ const im = bodyIm = newIM(body, mat, ids.length);
2375
+ place(im);
2346
2376
  lv0.push(im);
2347
- if (bodyIm) {
2348
- im.instanceMatrix = bodyIm.instanceMatrix;
2349
- im.instanceColor = bodyIm.instanceColor;
2350
- im.boundingSphere = bodyIm.boundingSphere;
2351
- root.add(im);
2352
- } else {
2353
- place(im);
2354
- bodyIm = im;
2377
+ }
2378
+ if (textured)
2379
+ for (const tb of p.tex) {
2380
+ const gg = geom(tb, arr);
2381
+ const im = newIM(gg, texMat(tb.t, mat, !!tb.wrapU), ids.length);
2382
+ texBatches++;
2383
+ lv0.push(im);
2384
+ if (bodyIm) {
2385
+ im.instanceMatrix = bodyIm.instanceMatrix;
2386
+ im.instanceColor = bodyIm.instanceColor;
2387
+ im.boundingSphere = bodyIm.boundingSphere;
2388
+ root.add(im);
2389
+ } else {
2390
+ place(im);
2391
+ bodyIm = im;
2392
+ }
2355
2393
  }
2394
+ if (bodyIm) {
2395
+ const cl = newCluster(bodyIm.boundingSphere);
2396
+ lv0.forEach((o) => o.onBeforeRender = trackVp);
2397
+ cl.lv.push({ objs: lv0, err: 0 }, ...textured ? [] : lodLevels(p.body, bodyIm, mat));
2398
+ if (EDGES && p.edges)
2399
+ addLines(p.edges, bodyIm, cl);
2400
+ addCond(p, bodyIm, cl);
2401
+ if (steps)
2402
+ stepBatches.push({ im: bodyIm, objs: [...cl.lv.flatMap((l) => l.objs), ...cl.lines, ...cl.cond], own: Int32Array.from(ids, (id) => steps[id]), hide: null, flag: "body", inst: Int32Array.from(ids), stud: null, col: Uint16Array.from(ids, (id) => instCol[id]) });
2403
+ }
2404
+ const under = geom(p.under, arr);
2405
+ const uGroups = !under ? [] : LOD && P.lodUnder !== false ? undersideGroups(ids, insts) : [{ ids, ax: null }];
2406
+ for (const { ids: uids, ax } of uGroups) {
2407
+ const ord = [...uids.filter((i) => !cull.underHidden[i]), ...uids.filter((i) => cull.underHidden[i])];
2408
+ const vis = uids.length - uids.reduce((a, i) => a + cull.underHidden[i], 0);
2409
+ stats.undersTotal += uids.length;
2410
+ stats.undersHidden += uids.length - vis;
2411
+ const im = newIM(under, mat, uids.length);
2412
+ fillInstances(im, ord, insts, color);
2413
+ im.onBeforeRender = trackVp;
2414
+ im.userData.ldrUnder = true;
2415
+ im.userData.ldrPart = part;
2416
+ instancedBoundingSphere(im);
2417
+ im.count = P.cullUnder ? vis : uids.length;
2418
+ root.add(im);
2419
+ const cl = newCluster(im.boundingSphere);
2420
+ cl.lv.push({ objs: [im], err: 0 }, ...lodLevels(p.under, im, mat));
2421
+ {
2422
+ const bl = p.body?.lod;
2423
+ const last = bl?.[bl.length - 1];
2424
+ if (LOD && P.lodUnder !== false && last && last.tris === 12)
2425
+ cl.boxErr = last.err;
2426
+ }
2427
+ if (ax) {
2428
+ let below = Infinity;
2429
+ for (const id of uids) {
2430
+ const m = insts[id].m;
2431
+ below = Math.min(below, m[0] * ax[0] + m[1] * ax[1] + m[2] * ax[2] + p.bbox[4] * ax[3]);
2432
+ }
2433
+ cl.below = below;
2434
+ cl.ax = ax.slice(0, 3);
2435
+ }
2436
+ addCond(p, im, cl, "under");
2437
+ const objs = [...cl.lv.flatMap((l) => l.objs), ...cl.cond];
2438
+ objs.forEach((o) => {
2439
+ if (!o.isInstancedMesh)
2440
+ o.geometry.instanceCount = im.count;
2441
+ });
2442
+ toggles.push({ mesh: countTo(() => objs), all: uids.length, visible: vis, flag: "under" });
2443
+ if (steps)
2444
+ stepBatches.push({ im, objs, own: Int32Array.from(ord, (id) => steps[id]), hide: Int32Array.from(ord, (id) => cull.underHideStep[id]), flag: "under", inst: Int32Array.from(ord), stud: null, col: Uint16Array.from(ord, (id) => instCol[id]) });
2356
2445
  }
2357
- if (bodyIm) {
2358
- const cl = newCluster(bodyIm.boundingSphere);
2359
- lv0.forEach((o) => o.onBeforeRender = trackVp);
2360
- cl.lv.push({ objs: lv0, err: 0 }, ...textured ? [] : lodLevels(p.body, bodyIm, mat));
2361
- if (EDGES && p.edges)
2362
- addLines(p.edges, bodyIm, cl);
2363
- addCond(p, bodyIm, cl);
2364
- if (steps)
2365
- stepBatches.push({ im: bodyIm, objs: [...cl.lv.flatMap((l) => l.objs), ...cl.lines, ...cl.cond], own: Int32Array.from(ids, (id) => steps[id]), hide: null, flag: "body", inst: Int32Array.from(ids), stud: null, col: Uint16Array.from(ids, (id) => instCol[id]) });
2366
2446
  }
2367
- const under = geom(p.under, arr);
2368
- const uGroups = !under ? [] : LOD && P.lodUnder !== false ? undersideGroups(ids, insts) : [{ ids, ax: null }];
2369
- for (const { ids: uids, ax } of uGroups) {
2370
- const ord = [...uids.filter((i) => !cull.underHidden[i]), ...uids.filter((i) => cull.underHidden[i])];
2371
- const vis = uids.length - uids.reduce((a, i) => a + cull.underHidden[i], 0);
2372
- stats.undersTotal += uids.length;
2373
- stats.undersHidden += uids.length - vis;
2374
- const im = newIM(under, mat, uids.length);
2375
- fillInstances(im, ord, insts, color);
2376
- im.onBeforeRender = trackVp;
2377
- im.userData.ldrUnder = true;
2378
- im.userData.ldrPart = part;
2379
- instancedBoundingSphere(im);
2380
- im.count = P.cullUnder ? vis : uids.length;
2381
- root.add(im);
2382
- const cl = newCluster(im.boundingSphere);
2383
- cl.lv.push({ objs: [im], err: 0 }, ...lodLevels(p.under, im, mat));
2384
- {
2385
- const bl = p.body?.lod;
2386
- const last = bl?.[bl.length - 1];
2387
- if (LOD && P.lodUnder !== false && last && last.tris === 12)
2388
- cl.boxErr = last.err;
2447
+ } else {
2448
+ const list = coldByMat.get(mat) || coldByMat.set(mat, []).get(mat);
2449
+ list.push({ part, p, mat, ids: idsAll });
2450
+ }
2451
+ }
2452
+ const tmpM = new THREE.Matrix4;
2453
+ const tmpC = new THREE.Color;
2454
+ for (const [mat, items] of coldByMat) {
2455
+ const entries = [];
2456
+ for (const it of items)
2457
+ for (const id of it.ids)
2458
+ entries.push({ id, part: it.part, p: it.p });
2459
+ if (!entries.length)
2460
+ continue;
2461
+ const groups = gridClusters(entries.length, (i) => insts[entries[i].id].m[0], (i) => insts[entries[i].id].m[2], LOD ? 256 : Infinity);
2462
+ for (const g of groups) {
2463
+ const members = Array.from(g, (i) => entries[i]);
2464
+ const partSet = new Map;
2465
+ for (const m of members)
2466
+ partSet.set(m.part, m.p);
2467
+ let maxV = 0, maxI = 0;
2468
+ for (const p of partSet.values()) {
2469
+ for (const b of [p.body, ...p.body?.lod ?? []]) {
2470
+ maxV += geomVerts(b);
2471
+ maxI += geomIdx(b);
2389
2472
  }
2390
- if (ax) {
2391
- let below = Infinity;
2392
- for (const id of uids) {
2393
- const m = insts[id].m;
2394
- below = Math.min(below, m[0] * ax[0] + m[1] * ax[1] + m[2] * ax[2] + p.bbox[4] * ax[3]);
2473
+ }
2474
+ if (maxV === 0)
2475
+ continue;
2476
+ const bm = new THREE.BatchedMesh(members.length, Math.max(1, maxV), Math.max(1, maxI), mat);
2477
+ bm.perObjectFrustumCulled = true;
2478
+ bm.sortObjects = false;
2479
+ bm.frustumCulled = true;
2480
+ bm.userData.ldrMerged = true;
2481
+ bm.onBeforeRender = trackVp;
2482
+ root.add(bm);
2483
+ const gidsByPart = new Map;
2484
+ for (const [part, p] of partSet) {
2485
+ const body = geom(p.body, arr);
2486
+ if (!body) {
2487
+ gidsByPart.set(part, []);
2488
+ continue;
2489
+ }
2490
+ const ids = [bm.addGeometry(body)];
2491
+ if (LOD && p.body?.lod)
2492
+ for (const l of p.body.lod)
2493
+ ids.push(bm.addGeometry(geom(l, arr)));
2494
+ gidsByPart.set(part, ids);
2495
+ }
2496
+ const live = members.filter((m) => (gidsByPart.get(m.part)?.length ?? 0) > 0);
2497
+ const instGids = new Array(live.length);
2498
+ const ownArr = steps ? new Int32Array(live.length) : null;
2499
+ const instArr = steps ? new Int32Array(live.length) : null;
2500
+ const m16 = new Float32Array(16);
2501
+ for (let i = 0;i < live.length; i++) {
2502
+ const { id, part, p } = live[i];
2503
+ const gids = gidsByPart.get(part);
2504
+ const iid = bm.addInstance(gids[0]);
2505
+ writeM4(m16, 0, insts[id].m);
2506
+ tmpM.fromArray(m16);
2507
+ bm.setMatrixAt(iid, tmpM);
2508
+ tmpC.copy(color(insts[id].color));
2509
+ bm.setColorAt(iid, tmpC);
2510
+ instGids[iid] = gids;
2511
+ if (ownArr) {
2512
+ ownArr[iid] = steps[id];
2513
+ instArr[iid] = id;
2514
+ }
2515
+ }
2516
+ members.length = 0;
2517
+ members.push(...live);
2518
+ bm.computeBoundingSphere();
2519
+ const cl = newCluster(bm.boundingSphere ?? new THREE.Sphere);
2520
+ const bodyErrs = live.map(({ p }) => [0, ...(p.body?.lod ?? []).map((l) => l.err)]);
2521
+ bm.userData.ldrMergeGids = instGids;
2522
+ cl.mergedLod = { bm, gids: instGids, errs: bodyErrs };
2523
+ cl.setMergedLevel = (L) => {
2524
+ bm.visible = L >= 0;
2525
+ };
2526
+ cl.lv.push({ objs: [bm], err: 0 });
2527
+ if (EDGES) {
2528
+ const byPartIds = new Map;
2529
+ for (const m of live) {
2530
+ const a = byPartIds.get(m.part) || byPartIds.set(m.part, []).get(m.part);
2531
+ a.push(m.id);
2532
+ }
2533
+ for (const [partName, ids] of byPartIds) {
2534
+ const pp = partSet.get(partName);
2535
+ if (!pp)
2536
+ continue;
2537
+ if (!pp.edges && !(wantCond && (pp.condl || pp.condlu)))
2538
+ continue;
2539
+ const ghost = newIM(geom(pp.body, arr) || new THREE.BufferGeometry, mat, ids.length);
2540
+ fillInstances(ghost, ids, insts, color);
2541
+ const nL = cl.lines.length, nC = cl.cond.length;
2542
+ if (pp.edges)
2543
+ addLines(pp.edges, ghost, cl);
2544
+ addCond(pp, ghost, cl);
2545
+ if (steps)
2546
+ stepBatches.push({ im: ghost, objs: [ghost, ...cl.lines.slice(nL), ...cl.cond.slice(nC)], own: Int32Array.from(ids, (id) => steps[id]), hide: null, flag: "body", inst: Int32Array.from(ids), stud: null, col: Uint16Array.from(ids, (id) => instCol[id]) });
2547
+ }
2548
+ }
2549
+ if (steps && ownArr)
2550
+ stepBatched.push({ bm, own: ownArr, hide: null, flag: "body", inst: instArr });
2551
+ const withUnder = members.filter((m) => m.p.under);
2552
+ if (withUnder.length) {
2553
+ const uEntries = withUnder.map((m) => m.id);
2554
+ const uGroups = LOD && P.lodUnder !== false ? undersideGroups(uEntries, insts) : [{ ids: uEntries, ax: null }];
2555
+ for (const { ids: uids, ax } of uGroups) {
2556
+ const byId = new Map(members.map((m) => [m.id, m]));
2557
+ const umembers = uids.map((id) => {
2558
+ const m = byId.get(id);
2559
+ return { ...m, hid: !!cull.underHidden[id] };
2560
+ });
2561
+ stats.undersTotal += umembers.length;
2562
+ stats.undersHidden += umembers.filter((m) => m.hid).length;
2563
+ const uPartSet = new Map;
2564
+ for (const m of umembers)
2565
+ uPartSet.set(m.part, m.p);
2566
+ let uV = 0, uI = 0;
2567
+ for (const p of uPartSet.values())
2568
+ for (const b of [p.under, ...p.under?.lod ?? []]) {
2569
+ uV += geomVerts(b);
2570
+ uI += geomIdx(b);
2571
+ }
2572
+ if (!uV)
2573
+ continue;
2574
+ const ubm = new THREE.BatchedMesh(umembers.length, Math.max(1, uV), Math.max(1, uI), mat);
2575
+ ubm.perObjectFrustumCulled = true;
2576
+ ubm.sortObjects = false;
2577
+ ubm.frustumCulled = true;
2578
+ ubm.userData.ldrMerged = true;
2579
+ ubm.userData.ldrUnder = true;
2580
+ ubm.onBeforeRender = trackVp;
2581
+ root.add(ubm);
2582
+ const uGidsByPart = new Map;
2583
+ for (const [part, p] of uPartSet) {
2584
+ const u = geom(p.under, arr);
2585
+ if (!u) {
2586
+ uGidsByPart.set(part, []);
2587
+ continue;
2588
+ }
2589
+ const ids = [ubm.addGeometry(u)];
2590
+ if (LOD && p.under?.lod)
2591
+ for (const l of p.under.lod)
2592
+ ids.push(ubm.addGeometry(geom(l, arr)));
2593
+ uGidsByPart.set(part, ids);
2594
+ }
2595
+ const uLive = umembers.filter((m) => (uGidsByPart.get(m.part)?.length ?? 0) > 0);
2596
+ const uInstGids = new Array(uLive.length);
2597
+ const uOwn = steps ? new Int32Array(uLive.length) : null;
2598
+ const uInst = steps ? new Int32Array(uLive.length) : null;
2599
+ const uHide = steps ? new Int32Array(uLive.length) : null;
2600
+ const uHid = new Uint8Array(uLive.length);
2601
+ for (let i = 0;i < uLive.length; i++) {
2602
+ const { id, part, p, hid } = uLive[i];
2603
+ const gids = uGidsByPart.get(part);
2604
+ const iid = ubm.addInstance(gids[0]);
2605
+ writeM4(m16, 0, insts[id].m);
2606
+ tmpM.fromArray(m16);
2607
+ ubm.setMatrixAt(iid, tmpM);
2608
+ tmpC.copy(color(insts[id].color));
2609
+ ubm.setColorAt(iid, tmpC);
2610
+ uInstGids[iid] = gids;
2611
+ uHid[iid] = hid ? 1 : 0;
2612
+ if (P.cullUnder && hid)
2613
+ ubm.setVisibleAt(iid, false);
2614
+ if (uOwn) {
2615
+ uOwn[iid] = steps[id];
2616
+ uInst[iid] = id;
2617
+ uHide[iid] = cull.underHideStep[id];
2618
+ }
2619
+ }
2620
+ umembers.length = 0;
2621
+ umembers.push(...uLive);
2622
+ ubm.computeBoundingSphere();
2623
+ const ucl = newCluster(ubm.boundingSphere ?? new THREE.Sphere);
2624
+ const uErrs = uLive.map(({ p }) => [0, ...(p.under?.lod ?? []).map((l) => l.err)]);
2625
+ ubm.userData._stepMode = !!steps;
2626
+ ubm.userData.ldrMergeGids = uInstGids;
2627
+ ucl.mergedLod = { bm: ubm, gids: uInstGids, errs: uErrs, underHid: uHid, cullUnder: !!P.cullUnder };
2628
+ ucl.setMergedLevel = (L) => {
2629
+ ubm.visible = L >= 0;
2630
+ };
2631
+ ucl.lv.push({ objs: [ubm], err: 0 });
2632
+ const underGhostCounts = [];
2633
+ if (wantCond) {
2634
+ const uByPart = new Map;
2635
+ for (const m of uLive) {
2636
+ const a = uByPart.get(m.part) || uByPart.set(m.part, []).get(m.part);
2637
+ a.push(m.id);
2638
+ }
2639
+ for (const [partName, ids] of uByPart) {
2640
+ const pp = uPartSet.get(partName);
2641
+ if (!pp?.condlu)
2642
+ continue;
2643
+ const ord = [...ids.filter((id) => !cull.underHidden[id]), ...ids.filter((id) => cull.underHidden[id])];
2644
+ const vis = ids.length - ids.reduce((a, id) => a + cull.underHidden[id], 0);
2645
+ const ghost = newIM(geom(pp.under, arr) || new THREE.BufferGeometry, mat, ord.length);
2646
+ fillInstances(ghost, ord, insts, color);
2647
+ const nC = ucl.cond.length;
2648
+ addCond(pp, ghost, ucl, "under");
2649
+ const lineObjs = ucl.cond.slice(nC);
2650
+ const setN = (n) => {
2651
+ ghost.count = n;
2652
+ for (const o of lineObjs)
2653
+ o.geometry.instanceCount = n;
2654
+ };
2655
+ setN(P.cullUnder ? vis : ord.length);
2656
+ underGhostCounts.push({ set: setN, all: ord.length, vis });
2657
+ if (steps)
2658
+ stepBatches.push({ im: ghost, objs: [ghost, ...lineObjs], own: Int32Array.from(ord, (id) => steps[id]), hide: Int32Array.from(ord, (id) => cull.underHideStep[id]), flag: "under", inst: Int32Array.from(ord), stud: null, col: Uint16Array.from(ord, (id) => instCol[id]) });
2659
+ }
2395
2660
  }
2396
- cl.below = below;
2397
- cl.ax = ax.slice(0, 3);
2661
+ {
2662
+ const sample = umembers[0]?.p;
2663
+ const bl = sample?.body?.lod;
2664
+ const last = bl?.[bl.length - 1];
2665
+ if (LOD && P.lodUnder !== false && last && last.tris === 12)
2666
+ ucl.boxErr = last.err;
2667
+ }
2668
+ if (ax) {
2669
+ let below = Infinity;
2670
+ for (const { id, p } of umembers) {
2671
+ const m = insts[id].m;
2672
+ below = Math.min(below, m[0] * ax[0] + m[1] * ax[1] + m[2] * ax[2] + p.bbox[4] * ax[3]);
2673
+ }
2674
+ ucl.below = below;
2675
+ ucl.ax = ax.slice(0, 3);
2676
+ }
2677
+ toggles.push({
2678
+ mesh: { set count(n) {
2679
+ const showAll = n >= umembers.length;
2680
+ for (let i = 0;i < uHid.length; i++)
2681
+ ubm.setVisibleAt(i, showAll || !uHid[i]);
2682
+ for (const g of underGhostCounts)
2683
+ g.set(showAll ? g.all : g.vis);
2684
+ } },
2685
+ all: umembers.length,
2686
+ visible: umembers.length - umembers.filter((m) => m.hid).length,
2687
+ flag: "under"
2688
+ });
2689
+ if (steps && uOwn)
2690
+ stepBatched.push({ bm: ubm, own: uOwn, hide: uHide, flag: "under", inst: uInst, underHidden: uHid });
2398
2691
  }
2399
- addCond(p, im, cl, "under");
2400
- const objs = [...cl.lv.flatMap((l) => l.objs), ...cl.cond];
2401
- objs.forEach((o) => {
2402
- if (!o.isInstancedMesh)
2403
- o.geometry.instanceCount = im.count;
2404
- });
2405
- toggles.push({ mesh: countTo(() => objs), all: uids.length, visible: vis, flag: "under" });
2406
- if (steps)
2407
- stepBatches.push({ im, objs, own: Int32Array.from(ord, (id) => steps[id]), hide: Int32Array.from(ord, (id) => cull.underHideStep[id]), flag: "under", inst: Int32Array.from(ord), stud: null, col: Uint16Array.from(ord, (id) => instCol[id]) });
2408
2692
  }
2409
2693
  }
2410
2694
  }
@@ -2445,11 +2729,14 @@ function buildLdrScene(insts, pack, P, color, mark) {
2445
2729
  stats.uncertBatches = nUncert;
2446
2730
  let condOn = true, edgesOn = true;
2447
2731
  root.apply = (c) => {
2448
- c.lv.forEach((l, i) => {
2449
- for (const o of l.objs)
2450
- o.visible = i === c.cur;
2451
- });
2452
- const lineVis = edgesOn && c.edgeOk && c.cur >= 0 && (c.cur === 0 || !LOD || c.lv[c.cur].objs.length > 0);
2732
+ if (c.setMergedLevel)
2733
+ c.setMergedLevel(c.cur);
2734
+ else
2735
+ c.lv.forEach((l, i) => {
2736
+ for (const o of l.objs)
2737
+ o.visible = i === c.cur;
2738
+ });
2739
+ const lineVis = edgesOn && c.edgeOk && c.cur >= 0 && (c.cur === 0 || !LOD || (c.setMergedLevel ? true : c.lv[c.cur].objs.length > 0));
2453
2740
  for (const o of c.lines)
2454
2741
  o.visible = lineVis;
2455
2742
  for (const o of c.cond)
@@ -2516,6 +2803,20 @@ function buildLdrScene(insts, pack, P, color, mark) {
2516
2803
  o.geometry.instanceCount = w;
2517
2804
  }
2518
2805
  }
2806
+ for (const b of stepBatched) {
2807
+ const useHide = b.flag === "under" ? cullU : false;
2808
+ const { own, hide, inst, bm } = b;
2809
+ for (let i = 0;i < own.length; i++) {
2810
+ const hid = !!hide && hide[i] <= S;
2811
+ if (b.flag === "under") {
2812
+ st.undersTotal++;
2813
+ if (hid)
2814
+ st.undersHidden++;
2815
+ }
2816
+ const on = own[i] <= S && !(useHide && hid) && !(O && !O[inst[i]]);
2817
+ bm.setVisibleAt(i, on);
2818
+ }
2819
+ }
2519
2820
  return st;
2520
2821
  };
2521
2822
  const setCull = (studs, under) => {
@@ -2571,6 +2872,12 @@ function buildLdrScene(insts, pack, P, color, mark) {
2571
2872
  c.edgeOk = true;
2572
2873
  for (const l of c.lines)
2573
2874
  l.geometry.drawRange.count = Infinity;
2875
+ if (c.mergedLod) {
2876
+ const { bm, gids } = c.mergedLod;
2877
+ for (let i = 0;i < gids.length; i++)
2878
+ if (gids[i]?.length)
2879
+ bm.setGeometryIdAt(i, gids[i][0]);
2880
+ }
2574
2881
  }
2575
2882
  refresh();
2576
2883
  }
@@ -2602,7 +2909,7 @@ async function warmPackGeometry(pack, stop = () => false, sliceMs = 8) {
2602
2909
  await new Promise((r) => setTimeout(r, 0));
2603
2910
  }
2604
2911
  }
2605
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/scene.ts
2912
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/scene.ts
2606
2913
  import * as THREE2 from "three";
2607
2914
  function colorFn(src, pack, fallback) {
2608
2915
  const table = new Map;
@@ -2758,10 +3065,10 @@ function createLdrObject(instances, pack, options = {}) {
2758
3065
  dispose: disposeCur
2759
3066
  });
2760
3067
  }
2761
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/parts-cdn.ts
3068
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/parts-cdn.ts
2762
3069
  import { decompress as decompress2 } from "fzstd";
2763
3070
 
2764
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/embedded.ts
3071
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/embedded.ts
2765
3072
  function splitFiles(text, fallback) {
2766
3073
  const files = new Map;
2767
3074
  let cur = null, saw = false;
@@ -2833,7 +3140,7 @@ function embeddedKeys(text, names, fallback = "main.ldr") {
2833
3140
  return out;
2834
3141
  }
2835
3142
 
2836
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/parts-cdn.ts
3143
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/parts-cdn.ts
2837
3144
  var DEFAULT_PARTS_CDN = "https://ldr-demo.vercel.app/cdn/v1/";
2838
3145
  var indexCache = new Map;
2839
3146
  var shardCache = new Map;
@@ -2993,10 +3300,10 @@ async function prepareModel(source, o = {}) {
2993
3300
  return { insts, pack, missing, requests, bytes, cull, timings: { fetchModel: t1 - t0, parse: t2 - t1, parts: t3 - t2, ...cull ? { cull: performance.now() - t3 } : {} } };
2994
3301
  }
2995
3302
 
2996
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/load-worker.gen.ts
3303
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/load-worker.gen.ts
2997
3304
  var load_worker_gen_default = 'var ht=ArrayBuffer,X=Uint8Array,ge=Uint16Array,gt=Int16Array;var be=Int32Array,Se=function(e,t,n){if(X.prototype.slice)return X.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 X(n-t);return r.set(e.subarray(t,n)),r},ce=function(e,t,n,r){if(X.prototype.fill)return X.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},bt=function(e,t,n,r){if(X.prototype.copyWithin)return X.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 dt=["invalid zstd data","window size too large (>2046MB)","invalid block type","FSE accuracy too high","match distance too far back","unexpected EOF"],W=function(e,t,n){var r=Error(t||dt[e]);if(r.code=e,Error.captureStackTrace)Error.captureStackTrace(r,W);if(!n)throw r;return r},Be=function(e,t,n){var r=0,s=0;for(;r<n;++r)s|=e[t++]<<(r<<3);return s},yt=function(e,t){return(e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24)>>>0},xt=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,l=r>>6;if(r&8)W(0);var a=6-s,c=i==3?4:i,p=Be(e,a,c);a+=c;var m=l?1<<l:s,h=Be(e,a,m)+(l==1&&256),d=h;if(!s){var S=1<<10+(e[5]>>3);d=S+(S>>3)*(e[5]&7)}if(d>2145386496)W(1);var u=new X((t==1?h||d:t?0:d)+12);return u[0]=1,u[4]=4,u[8]=8,{b:a+m,y:0,l:0,d:p,w:t&&t!=1?t:u.subarray(12),e:d,o:new be(u.buffer,0,3),u:h,c:o,m:Math.min(131072,d)}}else if((n>>4|e[3]<<20)==25481893)return yt(e,4)+8;W(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)W(3);var o=1<<s,i=o,l=-1,a=-1,c=-1,p=o,m=new ht(512+(o<<2)),h=new gt(m,0,256),d=new ge(m,0,256),S=new ge(m,512,o),u=512+(o<<1),b=new X(m,u,o),P=new X(m,u+o);while(l<255&&i>0){var g=re(i+1),f=r>>3,A=(1<<g+1)-1,O=(e[f]|e[f+1]<<8|e[f+2]<<16)>>(r&7)&A,y=(1<<g)-1,M=A-i-1,E=O&y;if(E<M)r+=g,O=E;else if(r+=g+1,O>y)O-=M;if(h[++l]=--O,O==-1)i+=O,b[--p]=l;else i-=O;if(!O)do{var D=r>>3;a=(e[D]|e[D+1]<<8)>>(r&7)&3,r+=2,l+=a}while(a==3)}if(l>255||i)W(0);var C=0,U=(o>>1)+(o>>3)+3,_=o-1;for(var H=0;H<=l;++H){var v=h[H];if(v<1){d[H]=-v;continue}for(c=0;c<v;++c){b[C]=H;do C=C+U&_;while(C>=p)}}if(C)W(0);for(c=0;c<o;++c){var w=d[b[c]]++,L=P[c]=s-re(w);S[c]=(w<<L)-o}return[r+7>>3,{b:s,s:b,n:P,t:S}]},wt=function(e,t){var n=0,r=-1,s=new X(292),o=e[t],i=s.subarray(0,256),l=s.subarray(256,268),a=new ge(s.buffer,268);if(o<128){var c=ue(e,t+1,6),p=c[0],m=c[1];t+=o;var h=p<<3,d=e[t];if(!d)W(0);var S=0,u=0,b=m.b,P=b,g=(++t<<3)-8+re(d);for(;;){if(g-=b,g<h)break;var f=g>>3;if(S+=(e[f]|e[f+1]<<8)>>(g&7)&(1<<b)-1,i[++r]=m.s[S],g-=P,g<h)break;f=g>>3,u+=(e[f]|e[f+1]<<8)>>(g&7)&(1<<P)-1,i[++r]=m.s[u],b=m.n[S],S=m.t[S],P=m.n[u],u=m.t[u]}if(++r>255)W(0)}else{r=o-127;for(;n<r;n+=2){var A=e[++t];i[n]=A>>4,i[n+1]=A&15}++t}var O=0;for(n=0;n<r;++n){var y=i[n];if(y>11)W(0);O+=y&&1<<y-1}var M=re(O)+1,E=1<<M,D=E-O;if(D&D-1)W(0);i[r++]=re(D)+1;for(n=0;n<r;++n){var y=i[n];++l[i[n]=y&&M+1-y]}var C=new X(E<<1),U=C.subarray(0,E),_=C.subarray(E);a[M]=0;for(n=M;n>0;--n){var H=a[n];ce(_,n,H,a[n-1]=H+l[n]*(1<<M-n))}if(a[0]!=E)W(0);for(n=0;n<r;++n){var v=i[n];if(v){var w=a[v];ce(U,n,w,a[v]=w+(1<<M-v))}}return[t,{n:_,b:M,s:U}]},At=ue(new X([81,16,99,140,49,198,24,99,12,33,196,24,99,102,102,134,70,146,4]),0,6)[1],vt=ue(new X([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],Mt=ue(new X([32,132,16,66,102,70,68,68,68,68,36,73,2]),0,5)[1],$e=function(e,t){var n=e.length,r=new be(n);for(var s=0;s<n;++s)r[s]=t,t+=1<<e[s];return r},Ce=new X(new be([0,0,0,0,16843009,50528770,134678020,202050057,269422093]).buffer,0,36),St=$e(Ce,0),Pe=new X(new be([0,0,0,0,0,0,0,0,16843009,50528770,117769220,185207048,252579084,16]).buffer,0,53),Ct=$e(Pe,3),le=function(e,t,n){var r=e.length,s=t.length,o=e[r-1],i=(1<<n.b)-1,l=-n.b;if(!o)W(0);var a=0,c=n.b,p=(r<<3)-8+re(o)-c,m=-1;for(;p>l&&m<s;){var h=p>>3,d=(e[h]|e[h+1]<<8|e[h+2]<<16)>>(p&7);a=(a<<c|d)&i,t[++m]=n.s[a],p-=c=n.n[a]}if(p!=l||m+1!=s)W(0)},Pt=function(e,t,n){var r=6,s=t.length,o=s+3>>2,i=o<<1,l=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,l),n),le(e.subarray(r),t.subarray(l),n)},Et=function(e,t,n){var r,s=t.b,o=e[s],i=o>>1&3;t.l=o&1;var l=o>>3|e[s+1]<<5|e[s+2]<<13,a=(s+=3)+l;if(i==1){if(s>=e.length)return;if(t.b=s+1,n)return ce(n,e[s],t.y,t.y+=l),n;return ce(new X(l),e[s])}if(a>e.length)return;if(i==0){if(t.b=a,n)return n.set(e.subarray(s,a),t.y),t.y+=l,n;return Se(e,s,a)}if(i==2){var c=e[s],p=c&3,m=c>>2&3,h=c>>4,d=0,S=0;if(p<2)if(m&1)h|=e[++s]<<4|(m&2&&e[++s]<<12);else h=c>>3;else if(S=m,m<2)h|=(e[++s]&63)<<4,d=e[s]>>6|e[++s]<<2;else if(m==2)h|=e[++s]<<4|(e[++s]&3)<<12,d=e[s]>>2|e[++s]<<6;else h|=e[++s]<<4|(e[++s]&63)<<12,d=e[s]>>6|e[++s]<<2|e[++s]<<10;++s;var u=n?n.subarray(t.y,t.y+t.m):new X(t.m),b=u.length-h;if(p==0)u.set(e.subarray(s,s+=h),b);else if(p==1)ce(u,e[s++],b);else{var P=t.h;if(p==2){var g=wt(e,s);d+=s-(s=g[0]),t.h=P=g[1]}else if(!P)W(0);(S?Pt:le)(e.subarray(s,s+=d),u.subarray(b),P)}var f=e[s++];if(f){if(f==255)f=(e[s++]|e[s++]<<8)+32512;else if(f>127)f=f-128<<8|e[s++];var A=e[s++];if(A&3)W(0);var O=[vt,Mt,At];for(var y=2;y>-1;--y){var M=A>>(y<<1)+2&3;if(M==1){var E=new X([0,0,e[s++]]);O[y]={s:E.subarray(2,3),n:E.subarray(0,1),t:new ge(E.buffer,0,1),b:0}}else if(M==2)r=ue(e,s,9-(y&1)),s=r[0],O[y]=r[1];else if(M==3){if(!t.t)W(0);O[y]=t.t[y]}}var D=t.t=O,C=D[0],U=D[1],_=D[2],H=e[a-1];if(!H)W(0);var v=(a<<3)-8+re(H)-_.b,w=v>>3,L=0,V=(e[w]|e[w+1]<<8)>>(v&7)&(1<<_.b)-1;w=(v-=U.b)>>3;var I=(e[w]|e[w+1]<<8)>>(v&7)&(1<<U.b)-1;w=(v-=C.b)>>3;var B=(e[w]|e[w+1]<<8)>>(v&7)&(1<<C.b)-1;for(++f;--f;){var T=_.s[V],x=_.n[V],N=C.s[B],F=C.n[B],R=U.s[I],z=U.n[I];w=(v-=R)>>3;var j=1<<R,k=j+((e[w]|e[w+1]<<8|e[w+2]<<16|e[w+3]<<24)>>>(v&7)&j-1);w=(v-=Pe[N])>>3;var G=Ct[N]+((e[w]|e[w+1]<<8|e[w+2]<<16)>>(v&7)&(1<<Pe[N])-1);w=(v-=Ce[T])>>3;var K=St[T]+((e[w]|e[w+1]<<8|e[w+2]<<16)>>(v&7)&(1<<Ce[T])-1);if(w=(v-=x)>>3,V=_.t[V]+((e[w]|e[w+1]<<8)>>(v&7)&(1<<x)-1),w=(v-=F)>>3,B=C.t[B]+((e[w]|e[w+1]<<8)>>(v&7)&(1<<F)-1),w=(v-=z)>>3,I=U.t[I]+((e[w]|e[w+1]<<8)>>(v&7)&(1<<z)-1),k>3)t.o[2]=t.o[1],t.o[1]=t.o[0],t.o[0]=k-=3;else{var Y=k-(K!=0);if(Y){if(k=Y==3?t.o[0]-1:t.o[Y],Y>1)t.o[2]=t.o[1];t.o[1]=t.o[0],t.o[0]=k}else k=t.o[0]}for(var y=0;y<K;++y)u[L+y]=u[b+y];L+=K,b+=K;var q=L-k;if(q<0){var Z=-q,ee=t.e+q;if(Z>G)Z=G;for(var y=0;y<Z;++y)u[L+y]=t.w[ee+y];L+=Z,G-=Z,q=0}for(var y=0;y<G;++y)u[L+y]=u[q+y];L+=G}if(L!=b)while(b<u.length)u[L++]=u[b++];else L=u.length;if(n)t.y+=L;else u=Se(u,0,L)}else if(n){if(t.y+=h,b)for(var y=0;y<h;++y)u[y]=u[b+y]}else if(b)u=Se(u,b);return t.b=a,u}W(2)},Tt=function(e,t){if(e.length==1)return e[0];var n=new X(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 je(e,t){var n=[],r=+!t,s=0,o=0;for(;e.length;){var i=xt(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 l=Et(e,i,t);if(!l)W(5);if(t)i.e=i.y;else n.push(l),o+=l.length,bt(i.w,0,l.length),i.w.set(l,i.w.length-l.length)}s=i.b+i.c*4}else s=i;e=e.subarray(s)}return Tt(n,o)}function de(e){let t=new DataView(e).getUint32(0,!0),n=JSON.parse(new TextDecoder().decode(new Uint8Array(e,4,t))),r=4+t;return{header:n,arr:(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 J=(e)=>e.trim().toLowerCase().replace(/\\\\/g,"/").replace(/\\/+/g,"/");function Ee(e){if(/^0x/i.test(e))return parseInt(e,16);return+e}var Ve=/^~?\\s*moved\\s+to\\s+(.+)$/i,Lt=new Set(["FILE","NOFILE","!DATA","!:","STEP","BFC","ROTSTEP","BUFEXCHG","!TEXMAP"]),Je=new Set(["part","subpart","primitive","8_primitive","48_primitive","shortcut","helper"]),It=new Set(["model","submodel","configuration"]),kt=/^(?:!?LDRAW_ORG|Unofficial|Official\\s+LCAD)\\s+(\\S+)/i;function He(e){let t=kt.exec(e);if(!t)return;let n=t[1].toLowerCase().replace(/^unofficial_/,"");return Je.has(n)||It.has(n)?n:void 0}function Ft(e){let t=[],n=0;while(n<e.length){while(e[n]===" "||e[n]==="\\t")n++;if(n>=e.length)break;if(e[n]===\'"\'){let r="";n++;while(n<e.length&&e[n]!==\'"\'){if(e[n]==="\\\\"&&n+1<e.length)n++;r+=e[n++]}n++,t.push(r)}else{let r=n;while(r<e.length&&e[r]!==" "&&e[r]!=="\\t")r++;t.push(e.slice(n,r)),n=r}}return t}function Rt(e,t=!1){let n=/^\\s*(\\S+)\\s+(.*)$/.exec(e);if(!n)return null;let r=n[1].toUpperCase(),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 l=n[2].trim();for(let m=0;m<s;m++)l=l.replace(/^\\S+\\s*/,"");let a=Ft(l);if(!a.length)return null;let c={method:r,p1:i.slice(0,3),p2:i.slice(3,6),p3:i.slice(6,9),texture:a[0]};if(s>=10)c.a=i[9];if(s===11)c.b=i[10];let p=a.findIndex((m,h)=>h>0&&m.toUpperCase()==="GLOSSMAP");if(p>0&&a[p+1])c.glossmap=a[p+1];if(t)c.next=!0;return c}var Dt=(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 Ut(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 p=s();if(p===null)return null;i[c]=+p}while(n<t&&r(e.charCodeAt(n)))n++;if(n>=t)return null;let l=e.slice(n),a=/[ \\t]{2,}|\\t/.test(l)?l.split(/\\s+/).join(" "):l;return{t:1,color:Ee(o),m:i,file:J(a)}}function Ge(e){let t=+e[0];if(!(t>=1&&t<=5)||e.length<2)return null;let n=Ee(e[1]),r=e.slice(2).map(Number);if(t===1)return{t:1,color:n,m:r.slice(0,12),file:J(e.slice(14).join(" "))};if(t===2)return{t:2,color:n,p:r.slice(0,6)};if(t===3)return{t:3,color:n,p:r.slice(0,9)};if(t===4)return{t:4,color:n,p:r.slice(0,12)};return{t:5,color:n,p:r.slice(0,12)}}function Ze(e,t="main.ldr",n={}){let r=!!n.geometryText,s=new Map,o=null,i="",l,a=null,c=[],p=null,m=()=>{if(!a)return;let g=Dt(a.chunks.join("")),f=g[0]===137&&g[1]===80&&g[2]===78&&g[3]===71;(l??=new Map).set(J(a.name),{name:a.name,bytes:g,...f?{mime:"image/png"}:{}}),a=null},h=!0,d=(g)=>{if(m(),o={name:J(g),cmds:[]},s.set(o.name,o),!i)i=o.name;c=[],p=null,h=!0},S=!1,u=!1,b=()=>{if(u)return;u=!0,s.clear(),o=null,i=""},P=(g,f)=>{if(p){g.tex=p,p=null;return}let A=c[c.length-1];if(!A)return;if(A.fallback){if(!f)g.fallback=!0}else g.tex=A.map};for(let g of e.split(`\n`)){let f=g.trim();if(!f)continue;if(r&&f.charCodeAt(0)>=50&&f.charCodeAt(0)<=53&&(f.charCodeAt(1)===32||f.charCodeAt(1)===9)){if(a||S)continue;if(!o)d(t);let M=f.slice(2).trimStart(),E=M.search(/\\s/),D={t:f.charCodeAt(0)-48,color:Ee(E<0?M:M.slice(0,E)),p:[],src:f};P(D,!1),o.cmds.push(D),h=!1;continue}if(f.charCodeAt(0)===48&&(f.charCodeAt(1)===32||f.charCodeAt(1)===9)){let M=2;while(f.charCodeAt(M)===32||f.charCodeAt(M)===9)M++;let E=M;while(E<f.length&&f.charCodeAt(E)!==32&&f.charCodeAt(E)!==9)E++;let D=f.slice(M,E);if(!Lt.has(D)){if(S||a)continue;if(!o)d(t);let C=f.slice(M),U={t:0,text:C};if(D.charCodeAt(0)===33)U.meta=D;if(p=null,h&&!o.org){let H=He(C);if(H)o.org=H}let _=C.match(Ve);if(_&&!o.movedTo){let H=_[1].trim().replace(/\\\\/g,"/");if(!/\\.(dat|ldr|mpd)$/i.test(H))H+=".dat";o.movedTo=J(H)}o.cmds.push(U);continue}}if(f.charCodeAt(0)===49&&(f.charCodeAt(1)===32||f.charCodeAt(1)===9)&&!a&&!S){let M=Ut(f);if(M){if(!o)d(t);P(M,!1),o.cmds.push(M),h=!1;continue}}let A=f.split(/\\s+/);if(+A[0]===0){let M=f.slice(1).trim();if(A[1]==="FILE"){b(),S=!1,d(M.slice(5));continue}if(A[1]==="NOFILE"){m(),o=null,S=!0;continue}if(A[1]==="!DATA"){b(),m(),o=null,S=!1,a={name:M.slice(5).trim(),chunks:[]};continue}if(S)continue;if(a){if(A[1]==="!:")a.chunks.push(A.slice(2).join(""));continue}if(!o)d(t);let E={t:0,text:M};if(A[1]==="STEP")E.step=!0,c=[],p=null;else if(A[1]==="BFC")E.bfc=A.slice(2).join(" ");else if(A[1]==="ROTSTEP")if(E.meta="ROTSTEP",E.step=!0,c=[],p=null,(A[2]??"").toUpperCase()==="END")E.rotstep={x:0,y:0,z:0,mode:"END"};else{let C=(A[5]??"REL").toUpperCase();E.rotstep={x:+A[2]||0,y:+A[3]||0,z:+A[4]||0,mode:["REL","ABS","ADD"].includes(C)?C:"REL"}}else if(A[1]==="BUFEXCHG"){E.meta="BUFEXCHG";let C=(A[2]??"").toUpperCase();E.bufexchg={op:C==="RETRIEVE"?"RETRIEVE":"STORE",buf:A[3]??"A"}}else if(A[1]?.startsWith("!"))E.meta=A[1];if(h&&!o.org){let C=He(M);if(C)o.org=C}if(A[1]==="!TEXMAP"){let C=(A[2]??"").toUpperCase();if(p=null,C==="START"||C==="NEXT"){let U=Rt(M.replace(/^!TEXMAP\\s+\\S+/i,""),C==="NEXT");if(E.texmap={op:C,...U?{map:U}:{}},U)if((o.texmaps??=[]).push(U),C==="START")c.push({map:U,fallback:!1});else p=U}else if(C==="FALLBACK"){E.texmap={op:C};let U=c[c.length-1];if(U)U.fallback=!0}else if(C==="END")E.texmap={op:C},c.pop()}else if(A[1]==="!:"){p=null;let C=Ge(A.slice(2));if(C)P(C,!0),E.geom=C}else p=null;let D=M.match(Ve);if(D&&!o.movedTo){let C=D[1].trim().replace(/\\\\/g,"/");if(!/\\.(dat|ldr|mpd)$/i.test(C))C+=".dat";o.movedTo=J(C)}o.cmds.push(E);continue}if(a||S)continue;if(!o)d(t);let y=Ge(A);if(!y)continue;P(y,!1),o.cmds.push(y),h=!1}return m(),l?{main:i,files:s,data:l}:{main:i,files:s}}var tn=Math.PI/180;function qe(e,t){let n=(r)=>[t[3]*r[0]+t[4]*r[1]+t[5]*r[2]+t[0],t[6]*r[0]+t[7]*r[1]+t[8]*r[2]+t[1],t[9]*r[0]+t[10]*r[1]+t[11]*r[2]+t[2]];return{...e,p1:n(e.p1),p2:n(e.p2),p3:n(e.p3)}}function Qe(e,t){let[n,r,s,o,i,l,a,c,p,m,h,d]=e,[S,u,b,P,g,f,A,O,y,M,E,D]=t;return[o*S+i*u+l*b+n,a*S+c*u+p*b+r,m*S+h*u+d*b+s,o*P+i*A+l*M,o*g+i*O+l*E,o*f+i*y+l*D,a*P+c*A+p*M,a*g+c*O+p*E,a*f+c*y+p*D,m*P+h*A+d*M,m*g+h*O+d*E,m*f+h*y+d*D]}var Te=[0,0,0,1,0,0,0,1,0,0,0,1];var Ke=new WeakMap,Ot=/^(s|8|48)\\//;function Le(e,t){let n=e.files.get(J(t));if(!n)return"part";let r=Ke.get(n);if(r)return r;if(n.org)r=Je.has(n.org)?"part":"model";else if(n.name===e.main)r="model";else r=n.cmds.some((s)=>s.t>=2||s.t===0&&!!s.geom||s.t===1&&Ot.test(s.file))?"part":"model";return Ke.set(n,r),r}var Xe=new WeakMap;function et(e){let t=Xe.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 Xe.set(e,t),t}var We=(e)=>e>16777215?"0x"+e.toString(16).toUpperCase():String(e),zt=(e)=>e.t===0?"0 "+e.text:e.t===1?`1 ${We(e.color)} ${e.m.join(" ")} ${e.file}`:e.src?e.src:`${e.t} ${We(e.color)} ${e.p.join(" ")}`,Ie=(e,t)=>`${J(e)}#${t}`;function Nt(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:Ie(e.name,t),cmds:n}}function tt(e,t){return[`0 ldr: own geometry of ${e.name}, step ${t}`,...Nt(e,t).cmds.map(zt)].join(`\n`)+`\n`}function Bt(e){let t=2166136261;for(let n=0;n<e.length;n++)t^=e.charCodeAt(n),t=Math.imul(t,16777619);return(t>>>0).toString(16).padStart(8,"0")}function nt(e){let[t,n,r,s,o,i,l,a,c,p,m,h]=e,d=a*h-c*m,S=-(l*h-c*p),u=l*m-a*p,b=s*d+o*S+i*u;if(!Number.isFinite(b)||Math.abs(b)<0.000000000001)return null;let P=1/b,g=[d*P,-(o*h-i*m)*P,(o*c-i*a)*P,S*P,(s*h-i*p)*P,-(s*c-i*l)*P,u*P,-(s*m-o*p)*P,(s*a-o*l)*P];return[-(g[0]*t+g[1]*n+g[2]*r),-(g[3]*t+g[4]*n+g[5]*r),-(g[6]*t+g[7]*n+g[8]*r),...g]}var $t=(e)=>String(+e.toFixed(6)||0),_e=(e)=>\'"\'+e.replace(/\\\\/g,"\\\\\\\\").replace(/"/g,"\\\\\\"")+\'"\';function rt(e,t){let n=[...t.p1,...t.p2,...t.p3,...t.method!=="PLANAR"?[t.a??360]:[],...t.method==="SPHERICAL"?[t.b??180]:[]].map($t).join(" "),r=`0 ldr: ${e} with a model-level !TEXMAP\n0 BFC CERTIFY CCW\n0 !TEXMAP START ${t.method} ${n} ${_e(t.texture)}${t.glossmap?" GLOSSMAP "+_e(t.glossmap):""}\n1 16 0 0 0 1 0 0 0 1 0 0 0 1 ${J(e)}\n0 !TEXMAP END\n`;return{name:`${J(e)}#tex-${Bt(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 Vt(e,t,n){let r=Math.PI/180,s=Math.sin(e*r),o=Math.cos(e*r),i=Math.sin(t*r),l=Math.cos(t*r),a=Math.sin(n*r),c=Math.cos(n*r);return[l*c,-l*a,i,o*a+s*i*c,o*c-s*i*a,-s*l,s*a-o*i*c,s*c+o*i*a,o*l]}var Ye=new WeakMap;function st(e){let t=Ye.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=Vt(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),Ye.set(e,n),n}var ot=999999,it=(e)=>e.map((t)=>String(t).padStart(6,"0")).join(".")+"~";function Ht(e,t={}){let n=[],r=t.maxDepth??64,s=t.looseGeometry!==!1,o=!!t.textures,i=!!t.callouts,l=new Map,a=0,c=(m,h)=>{let d=m.name+"#"+h,S=l.get(d);if(!S){let u;S=Object.assign(()=>u??=tt(m,h),{file:m,step:h}),l.set(d,S)}return S},p=(m,h,d,S,u,b,P,g,f=null,A=[],O=[])=>{let y=m.files.get(h);if(!y||P>r)return;let M=0,E=P>0?++a:0,D=i&&E?[...A,E]:A,C=i&&E?[...O,d]:O,U=i&&!f?new Map:null,_=-1,H=0,v=(T,x,N,F,R,z)=>{if(_!==M)_=M,H=0;let j=U?.get(M+"|"+x);if(j)return j.n++,p(T,T===m?x:T.main,N,F,u+"/"+x,[...R,ot],P+1,z,[...R,ot],D,C);let k=[...R,H++],G=n.length;p(T,T===m?x:T.main,N,F,u+"/"+x,k,P+1,z,f,D,C),U?.set(M+"|"+x,{n:1,from:G,to:n.length})},w=st(y),L=s?et(y):[],V=0,I=(T,x,N,F,R,z,j)=>{if(f)F=f;let k={part:T,color:x,m:N,step:F[0],steps:F,localStep:R,path:u};if(E){if(k.sub=E,i)k.subPath=D,k.subMats=C}if(z)k.embedded=!0;if(j){let K=rt(T,j);k.texPart=K.name,k.texSource=K.source}let G=w[R];if(G)k.view=G;return n.push(k),k},B=(T)=>{while(V<L.length&&L[V]<=T){let x=L[V++];I(Ie(y.name,x),S,d,[...b,x],x,!1,null).source=c(y,x)}};for(let T of y.cmds){if(T.t===0&&T.step){M++;continue}let x=T;if(x.t>=2||x.t===0&&x.geom&&x.geom.t>=2){B(M);continue}if(x.t===0)if(o&&x.geom?.t===1)x=x.geom;else continue;if(x.t!==1)continue;if(o&&x.fallback)continue;let N=x.color===16?S:x.color,F=Qe(d,x.m),R=[...b,M],z=o?x.tex??g:null,j=z?nt(x.m):null,k=z&&j?qe(z,j):null;if(m.files.has(x.file)){if(Le(m,x.file)==="model"){v(m,x.file,F,N,R,k);continue}I(x.file,N,F,R,M,!0,k);continue}let G=t.resolveModel?.(x.file);if(G){v(G,x.file,F,N,R,k);continue}I(x.file,N,F,R,M,!1,k)}if(B(1/0),U){for(let T of U.values())if(T.n>1)for(let x=T.from;x<T.to;x++)n[x].mult??=T.n}};if(Le(e,e.main)==="part"){if(e.files.get(e.main))n.push({part:e.main,color:16,m:[...Te],step:0,steps:[0],localStep:0,path:e.main,embedded:!0});return n}return p(e,e.main,Te,16,e.main,[],0,null),n}function at(e,t="main.ldr",n){return Ht(Ze(e,t,{geometryText:!0}),n)}function Gt(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(J(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(J(t),r)}let l=o.trim().replace(/\\s+/g," ");if(l)r.push(l)}return n}var Kt=(e)=>{if(!e.startsWith("1 "))return null;let t=e.split(" ");return t.length>=15?J(t.slice(14).join(" ")):null};function Xt(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 lt(e,t,n="main.ldr"){let r=Gt(e,n),s=new Map;for(let o of t){let i=J(o);if(!r.has(i)||s.has(i))continue;let l=new Set([i]),a=[i];while(a.length)for(let p of r.get(a.pop())){let m=Kt(p);if(m&&r.has(m)&&!l.has(m))l.add(m),a.push(m)}let c=[i,...[...l].filter((p)=>p!==i).sort()].map((p)=>"0 FILE "+(p===i?"":p)+`\n`+r.get(p).join(`\n`)).join(`\n`);s.set(i,`emb/${Xt(c)}.dat`)}return s}var ct=(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,ut=new WeakMap;function ke(e,t){let n=ut.get(e);if(!n)ut.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),l=[],a=[];s.studs.forEach((h,d)=>{l.push(h[0]),a.push(h[1]);for(let S=0;S<12;S++)i[d*12+S]=h[2+S]});let c=null,p=0,m=0;if(s.mask){p=s.mask[0],m=s.mask[1];let h=s.mask[2];c=new Uint8Array(h.length);for(let d=0;d<h.length;d++)c[d]=h.charCodeAt(d)===49?1:0}return n.set(t,r={nStuds:o,studM:i,kind:l,color:a,mask:c,nx:p,nz:m}),r}var ie=1073741824;class Fe{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,l=this.c;for(;;){if(!s[r])return-1;if(o[r]===e&&i[r]===t&&l[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,l=this.b,a=this.c;for(;;){if(!o[s])return o[s]=1,i[s]=e,l[s]=t,a[s]=n,this.vals[s]=r,this.size++,-1;if(i[s]===e&&l[s]===t&&a[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 ye=(e,t,n)=>e>-ie&&e<ie&&t>-ie&&t<ie&&n>-ie&&n<ie,fe=2147483647;function Wt(e,t,n){let s=[],o=[],i=[],l=[],a=[],c=[],p=[],m=[],h=new Fe(e.length*2),d=[],S=[];for(let v=0;v<e.length;v++){let w=e[v],L=w.m,V=t.parts[w.part];if(!V||!V.mask||!ct(L))continue;let I=V.bbox,B=1/0,T=-1/0,x=1/0,N=-1/0;for(let z=0;z<2;z++)for(let j=0;j<2;j++){let k=z?I[3]:I[0],G=j?I[5]:I[2],K=L[0]+L[3]*k+L[5]*G,Y=L[2]+L[9]*k+L[11]*G;if(K<B)B=K;if(K>T)T=K;if(Y<x)x=Y;if(Y>N)N=Y}let F=a.length;s.push(B),o.push(T),i.push(x),l.push(N),a.push(v),c.push(ke(t,w.part)),p.push(I[0]),m.push(I[2]);let R=Math.round((L[1]+I[4])*2);for(let z=Math.floor(B/40);z<=Math.floor(T/40);z++)for(let j=Math.floor(x/40);j<=Math.floor(N/40);j++){if(!ye(R,z,j))continue;let k=S.length;S.push(F),d.push(h.put(R,z,j,k))}}let u=[0,5,-5,5,-5],b=[0,5,5,-5,-5],P=NaN,g=NaN,f=NaN,A=-1,O=(v,w,L,V)=>{let I=Math.round(w*2),B=Math.floor(v/40),T=Math.floor(L/40);if(!ye(I,B,T))return fe;let x=fe;if(I!==P||B!==g||T!==f)P=I,g=B,f=T,A=h.get(I,B,T);for(let N=A;N>=0;N=d[N]){let F=S[N];if(a[F]===V||!(v-6>=s[F]-0.5&&v+6<=o[F]+0.5&&L-6>=i[F]-0.5&&L+6<=l[F]+0.5))continue;let R=e[a[F]].m,z=c[F],j=p[F],k=m[F],G=v-R[0],K=w-R[1],Y=L-R[2],q=R[3]*G+R[6]*K+R[9]*Y,Z=R[5]*G+R[8]*K+R[11]*Y,{nx:ee,nz:se,mask:ae}=z,oe=!0;for(let Q=0;Q<5;Q++){let te=Math.floor((q+u[Q]-j)/20),ne=Math.floor((Z+b[Q]-k)/20);if(te<0||ne<0||te>=ee||ne>=se||ae[te*se+ne]!==1){oe=!1;break}}if(oe){if(!n)return 0;let Q=n[a[F]];if(Q<x)x=Q}}return x},y=0;for(let v of e){let w=ke(t,v.part);if(w)y+=w.nStuds}let M=new Uint8Array(y),E=new Uint8Array(y),D=new Fe(y),C=0,U=n?new Int32Array(y).fill(fe):void 0;for(let v=0,w=0;v<e.length;v++){let L=e[v],V=ke(t,L.part);if(!V)continue;let I=L.m,B=V.studM,T=I[0],x=I[1],N=I[2],F=I[3],R=I[4],z=I[5],j=I[6],k=I[7],G=I[8],K=I[9],Y=I[10],q=I[11];for(let Z=0;Z<V.nStuds;Z++,w++){let ee=Z*12,se=B[ee+4],ae=B[ee+7],oe=B[ee+10];if(!(Math.abs(j*se+k*ae+G*oe-1)<0.001&&Math.abs(F*se+R*ae+z*oe)<0.001&&Math.abs(K*se+Y*ae+q*oe)<0.001))continue;E[w]=1;let Q=B[ee],te=B[ee+1],ne=B[ee+2],Re=T+F*Q+R*te+z*ne,De=x+j*Q+k*te+G*ne,Ue=N+K*Q+Y*te+q*ne,Oe=O(Re,De,Ue,v);if(Oe!==fe){if(M[w]=1,C++,U)U[w]=Oe}let pe=Math.round(Re),me=Math.round(De),he=Math.round(Ue);if(!ye(pe,me,he))continue;if(!n){D.put(pe,me,he,1);continue}let ze=n[v],Ne=D.get(pe,me,he);if(Ne<0||ze<Ne)D.put(pe,me,he,ze)}}let _=new Uint8Array(e.length),H=n?new Int32Array(e.length).fill(fe):void 0;for(let v=0;v<e.length;v++){let w=e[v],L=t.parts[w.part];if(!L||!L.under||!ct(w.m))continue;let V=L.bbox,I=Math.round((V[3]-V[0])/20),B=Math.round((V[5]-V[2])/20);if(!I||!B||I*B>4096)continue;let T=w.m,x=!0,N=0;for(let F=0;F<I&&x;F++)for(let R=0;R<B;R++){let z=V[0]+10+20*F,j=V[2]+10+20*R,k=T[0]+T[3]*z+T[5]*j,G=T[2]+T[9]*z+T[11]*j,K=Math.round(k),Y=Math.round(T[1]+V[4]),q=Math.round(G),Z=ye(K,Y,q)?D.get(K,Y,q):-1;if(Z<0){x=!1;break}if(Z>N)N=Z}if(x){if(_[v]=1,H)H[v]=N}}return{nStuds:y,studHidden:M,studUp:E,underHidden:_,studsHidden:C,studHideStep:U,underHideStep:H}}function _t(e,t,n){let r=(a)=>n&&a.texPart&&t.parts[a.texPart]?a.texPart:a.part,s=e.map((a)=>({part:r(a),color:String(a.color),m:a.m,steps:a.steps})),o=s.map((a)=>it(a.steps)),i=[...new Set(o)].sort(),l=new Map(i.map((a,c)=>[a,c]));return{all:s,stepOf:o.map((a)=>l.get(a)),nSteps:i.length}}function xe(e,t,n=!0){let r=_t(e,t,n);return Wt(r.all,t,r.nSteps>1?r.stepOf:void 0)}var Me="https://ldr-demo.vercel.app/cdn/v1/",Ae=new Map,we=new Map;function pt(e=Me,t=fetch){let n=Ae.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(()=>Ae.delete(e)),Ae.set(e,n);return n}var Yt=(e)=>Array.isArray(e)&&e.length===3&&typeof e[0]==="number"&&typeof e[1]==="number"&&(e[2]==="f32"||e[2]==="u16"||e[2]==="u8"||e[2]==="u32"),ve=(e,t)=>Yt(e)?[e[0]+t,e[1],e[2]]:Array.isArray(e)?e.map((n)=>ve(n,t)):e&&typeof e==="object"?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,ve(r,t)])):e;function Jt(e,t={}){let n=[],r=0,s={},o={};for(let h of e){let d=h.buffer;if(!d)throw Error("ldr: mergePacks needs packs from decodePack/loadPack");let S=new DataView(d).getUint32(0,!0),u=new Uint8Array(d,4+S),b=r;n.push(u),r+=u.byteLength;let P=(4-r%4)%4;if(P)n.push(new Uint8Array(P)),r+=P;for(let[g,f]of Object.entries(h.header.parts??{}))if(!(g in s))s[g]=ve(f,b);for(let[g,f]of Object.entries(h.header.studKinds??{}))if(!(g in o))o[g]=ve(f,b)}let i=e[0]?.header??{version:1,weld:!0},l=new TextEncoder().encode(JSON.stringify({...i,parts:s,studKinds:o,...t})),a=(4-(4+l.length)%4)%4,c=4+l.length+a,p=new Uint8Array(c+r);new DataView(p.buffer).setUint32(0,l.length+a,!0),p.set(l,4),p.fill(32,4+l.length,c);let m=c;for(let h of n)p.set(h,m),m+=h.byteLength;return de(p.buffer)}async function Zt(e,t={}){e=[...e];try{return await ft(e,t)}catch(n){let r=t.cdn??Me,s=t.fetch??fetch;Ae.delete(r);let o=(i,l)=>s(i,{...l,cache:"reload"});try{return await ft(e,{...t,fetch:o})}catch{throw n}}}async function ft(e,t){let n=t.cdn??Me,r=t.fetch??fetch,s=t.gap??16384,o=await pt(n,r),i=[...new Set([...e].map(J))],l=[],a=[];for(let u of i){if(we.has(n+u))continue;let b=o.parts[u];if(b)a.push({name:u,off:b[0],len:b[1],file:b[2]??0});else l.push(u)}a.sort((u,b)=>u.file-b.file||u.off-b.off);let c=[];for(let u of a){let b=c[c.length-1];if(b&&b.file===u.file&&u.off-b.end<=s)b.end=Math.max(b.end,u.off+u.len),b.items.push(u);else c.push({file:u.file,start:u.off,end:u.off+u.len,items:[u]})}let p=0,m=0,h=async()=>{while(m<c.length){let u=c[m++],b=await r(new URL(o.archives[u.file],n).href,{headers:{Range:`bytes=${u.start}-${u.end-1}`}});if(!b.ok)throw Error(`ldr: parts CDN ${b.status}`);let P=new Uint8Array(await b.arrayBuffer());if(b.status===200)P=P.subarray(u.start,u.end);p+=P.byteLength;for(let g of u.items){let f=je(P.subarray(g.off-u.start,g.off-u.start+g.len)),A=f.buffer.slice(f.byteOffset,f.byteOffset+f.byteLength);we.set(n+g.name,de(A))}}};await Promise.all(Array.from({length:Math.min(t.concurrency??24,c.length)},h));let d=i.filter((u)=>we.has(n+u)).map((u)=>we.get(n+u));return{pack:d.length?Jt(d,{colors:o.colors}):de(qt(o.colors)),missing:l,requests:c.length,bytes:p}}function qt(e){let t=new TextEncoder().encode(JSON.stringify({version:1,weld:!0,parts:{},studKinds:{},colors:e})),n=(4-(4+t.length)%4)%4,r=new Uint8Array(4+t.length+n).fill(32);return new DataView(r.buffer).setUint32(0,t.length+n,!0),r.set(t,4),r.buffer}async function mt(e,t={}){let n=performance.now(),r=t.fetch??fetch,s=pt(t.cdn??Me,r);s.catch(()=>{});let o=t.text?e:await r(e).then((f)=>{if(!f.ok)throw Error(`ldr: ${f.status} fetching ${e}`);return f.text()}),i=performance.now(),l=t.name??(t.text?"main.ldr":decodeURIComponent(e.split(/[?#]/)[0].split("/").pop()||"main.ldr")),a=at(o,l,{looseGeometry:!1,callouts:t.callouts}),c=performance.now();t.onParsed?.(a),await s;let p=lt(o,new Set(a.filter((f)=>f.embedded).map((f)=>f.part)),l),{pack:m,missing:h,requests:d,bytes:S}=await Zt([...a.filter((f)=>!f.embedded).map((f)=>f.part),...p.values()],t),u=new Map([...p].map(([f,A])=>[A,f])),b=h.map((f)=>u.get(f)??f);for(let[f,A]of p){let O=m.header.parts[A];if(O)m.header.parts[f]=O}let P=performance.now(),g=t.cull?xe(a,m.header,t.textures!==!1):void 0;return{insts:a,pack:m,missing:b,requests:d,bytes:S,cull:g,timings:{fetchModel:i-n,parse:c-i,parts:P-c,...g?{cull:performance.now()-P}:{}}}}self.onmessage=async(e)=>{let{id:t,source:n,opts:r}=e.data;try{let s=await mt(n,{...r,cull:!1,onParsed:(p)=>self.postMessage({id:t,insts:p})}),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(),l=xe(s.insts,s.pack.header,r.textures!==!1),a=performance.now()-i,c=[];for(let p of[l.studHidden,l.studUp,l.underHidden,l.studHideStep,l.underHideStep])if(p)c.push(p.buffer);self.postMessage({id:t,cull:l,ms:a},c)}catch(s){self.postMessage({id:t,phase:"error",error:String(s?.message??s)})}};\n';
2998
3305
 
2999
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/cdn.ts
3306
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/cdn.ts
3000
3307
  var worker;
3001
3308
  var seq = 0;
3002
3309
  var pending = new Map;
@@ -3105,7 +3412,7 @@ async function loadModel(source, o = {}) {
3105
3412
  timings: { ...prep.timings, parts: t3 - t0 - prep.timings.fetchModel - prep.timings.parse, build: t4 - t3, total: t4 - t0 }
3106
3413
  });
3107
3414
  }
3108
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/node/library.ts
3415
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/node/library.ts
3109
3416
  import { existsSync, readFileSync } from "fs";
3110
3417
  import { join } from "path";
3111
3418
  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]];
@@ -3364,11 +3671,11 @@ class Library {
3364
3671
  return insts;
3365
3672
  }
3366
3673
  }
3367
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/node/build-pack.ts
3674
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/node/build-pack.ts
3368
3675
  import fs3 from "node:fs";
3369
3676
  import path3 from "node:path";
3370
3677
 
3371
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/node/resolver.ts
3678
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/node/resolver.ts
3372
3679
  import fs from "node:fs";
3373
3680
  import path from "node:path";
3374
3681
  var TOP_STUD_RE = /^(stud|studa|stud2|stud2a|stud6|stud6a|stud10|stud15|stud2s|stud2s2|stud-logo\d*|stud2-logo\d*)\.dat$/i;
@@ -3640,11 +3947,11 @@ function collectDeps(lib, refs) {
3640
3947
  return out;
3641
3948
  }
3642
3949
 
3643
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/node/compile.ts
3950
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/node/compile.ts
3644
3951
  import fs2 from "node:fs";
3645
3952
  import path2 from "node:path";
3646
3953
 
3647
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/node/lod.ts
3954
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/node/lod.ts
3648
3955
  import { MeshoptSimplifier, MeshoptEncoder } from "meshoptimizer";
3649
3956
  await Promise.all([MeshoptSimplifier.ready, MeshoptEncoder.ready]);
3650
3957
  function reorderMesh(P, N, C, I) {
@@ -3836,7 +4143,7 @@ function lodChain(P, C, I) {
3836
4143
  return out;
3837
4144
  }
3838
4145
 
3839
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/node/compile.ts
4146
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/node/compile.ts
3840
4147
  function loadColors(root) {
3841
4148
  const map = new Map;
3842
4149
  for (const l of fs2.readFileSync(path2.join(root, "LDConfig.ldr"), "latin1").split(/\r?\n/)) {
@@ -4419,7 +4726,7 @@ function encodePack(parts, studKinds, weld, extra, options = {}) {
4419
4726
  return Buffer.concat([head, ...chunks.map((c) => new Uint8Array(c.buffer, c.byteOffset, c.byteLength))]);
4420
4727
  }
4421
4728
 
4422
- // ../../../../../../../tmp/ldr-build-eZnTdy/src/node/build-pack.ts
4729
+ // ../../../../../../../tmp/ldr-build-sEUhaY/src/node/build-pack.ts
4423
4730
  function buildPack(o) {
4424
4731
  const lib = new Library2(o.ldrawRoot);
4425
4732
  const refs = new Map;