ldr 0.32.0 → 0.33.1

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-MGO8Dx/src/spec.ts
1
+ // ../../../../../../../tmp/ldr-build-78cdvu/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-MGO8Dx/src/model.ts
711
+ // ../../../../../../../tmp/ldr-build-78cdvu/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
  var defLine = new WeakMap;
@@ -1122,7 +1122,7 @@ function blendedColourHex(code) {
1122
1122
  const a = LDRAW_EXE_16[code - 256 >> 4], b = LDRAW_EXE_16[code - 256 & 15];
1123
1123
  return "#" + [0, 1, 2].map((k) => (a[k] + b[k] >> 1).toString(16).padStart(2, "0")).join("").toUpperCase();
1124
1124
  }
1125
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/instructions.ts
1125
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/instructions.ts
1126
1126
  var MIN_VIS = 0.5;
1127
1127
  var REORIENT = 0.35;
1128
1128
  var deg = Math.PI / 180;
@@ -1490,10 +1490,10 @@ function planStepViews(insts, parts, stepOf, nSteps, o = {}) {
1490
1490
  }
1491
1491
  };
1492
1492
  }
1493
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/render.ts
1493
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/render.ts
1494
1494
  import * as THREE from "three";
1495
1495
 
1496
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/pack-io.ts
1496
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/pack-io.ts
1497
1497
  import { decompress } from "fzstd";
1498
1498
  async function decompressPack(data) {
1499
1499
  const u = data instanceof Uint8Array ? data : new Uint8Array(data);
@@ -1516,7 +1516,7 @@ function decodePack(buf) {
1516
1516
  return { header, arr, bytes: buf.byteLength, buffer: buf };
1517
1517
  }
1518
1518
 
1519
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/cull.ts
1519
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/cull.ts
1520
1520
  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;
1521
1521
  var prepCache = new WeakMap;
1522
1522
  function prepPart(H, part) {
@@ -1864,7 +1864,7 @@ function precomputeCull(instances, H, useTex = true) {
1864
1864
  return cullCore(s.all, H, s.nSteps > 1 ? s.stepOf : undefined);
1865
1865
  }
1866
1866
 
1867
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/render.ts
1867
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/render.ts
1868
1868
  async function loadPack(url) {
1869
1869
  const res = await fetch(url);
1870
1870
  if (!res.ok)
@@ -2521,6 +2521,81 @@ function studDiscGeom() {
2521
2521
  g.computeBoundingBox();
2522
2522
  return _studDisc = g;
2523
2523
  }
2524
+ var _studBox = new Map;
2525
+ function studBoxGeom(w) {
2526
+ let g = _studBox.get(w);
2527
+ if (g)
2528
+ return g;
2529
+ const y = -4, s = Math.SQRT1_2;
2530
+ const C = [[-w, -w], [w, -w], [w, w], [-w, w]];
2531
+ const pos = [], nrm = [], idx = [];
2532
+ for (const [x, z] of C) {
2533
+ pos.push(x, y, z);
2534
+ nrm.push(0, -1, 0);
2535
+ }
2536
+ for (const [x, z] of C) {
2537
+ pos.push(x, y, z, x, 0, z);
2538
+ nrm.push(Math.sign(x) * s, 0, Math.sign(z) * s, Math.sign(x) * s, 0, Math.sign(z) * s);
2539
+ }
2540
+ const tri = (a, b, c, out) => {
2541
+ const P = (i) => pos.slice(i * 3, i * 3 + 3);
2542
+ const [A, B, Cc] = [P(a), P(b), P(c)];
2543
+ const u = [B[0] - A[0], B[1] - A[1], B[2] - A[2]], v = [Cc[0] - A[0], Cc[1] - A[1], Cc[2] - A[2]];
2544
+ const n = [u[1] * v[2] - u[2] * v[1], u[2] * v[0] - u[0] * v[2], u[0] * v[1] - u[1] * v[0]];
2545
+ if (n[0] * out[0] + n[1] * out[1] + n[2] * out[2] < 0)
2546
+ idx.push(a, c, b);
2547
+ else
2548
+ idx.push(a, b, c);
2549
+ };
2550
+ tri(0, 1, 2, [0, -1, 0]);
2551
+ tri(0, 2, 3, [0, -1, 0]);
2552
+ for (let i = 0;i < 4; i++) {
2553
+ const j = (i + 1) % 4;
2554
+ const ti = 4 + i * 2, bi = ti + 1, tj = 4 + j * 2, bj = tj + 1;
2555
+ const out = [(C[i][0] + C[j][0]) / 2, 0, (C[i][1] + C[j][1]) / 2];
2556
+ tri(ti, tj, bj, out);
2557
+ tri(ti, bj, bi, out);
2558
+ }
2559
+ const col = new Uint8Array(12 * 4);
2560
+ for (let i = 0;i < 12; i++) {
2561
+ col[i * 4] = 255;
2562
+ col[i * 4 + 1] = 255;
2563
+ col[i * 4 + 2] = 255;
2564
+ col[i * 4 + 3] = 0;
2565
+ }
2566
+ g = new THREE.BufferGeometry;
2567
+ g.setAttribute("position", new THREE.Float16BufferAttribute(toF16(new Float32Array(pos)), 3));
2568
+ g.setAttribute("normal", new THREE.BufferAttribute(toI8(new Float32Array(nrm)), 3, true));
2569
+ g.setAttribute("ldrColor", new THREE.BufferAttribute(col, 4, true));
2570
+ g.setIndex(new THREE.BufferAttribute(new Uint16Array(idx), 1));
2571
+ g.computeBoundingSphere();
2572
+ g.computeBoundingBox();
2573
+ _studBox.set(w, g);
2574
+ return g;
2575
+ }
2576
+ var _topClosed = new WeakMap;
2577
+ function studTopClosed(b, arr) {
2578
+ if (!b)
2579
+ return false;
2580
+ let v = _topClosed.get(b);
2581
+ if (v !== undefined)
2582
+ return v;
2583
+ v = false;
2584
+ const p = arr(b.pos);
2585
+ const ix = b.idx ? arr(b.idx) : Array.from({ length: p.length / 3 }, (_, i) => i);
2586
+ const top = (i) => Math.abs(p[i * 3 + 1] + 4) < 0.05;
2587
+ for (let t = 0;t + 2 < ix.length && !v; t += 3) {
2588
+ const a = ix[t], c = ix[t + 1], d = ix[t + 2];
2589
+ if (!top(a) || !top(c) || !top(d))
2590
+ continue;
2591
+ const s = (i, j) => p[i * 3] * p[j * 3 + 2] - p[i * 3 + 2] * p[j * 3];
2592
+ const e1 = s(a, c), e2 = s(c, d), e3 = s(d, a);
2593
+ if (e1 >= 0 && e2 >= 0 && e3 >= 0 || e1 <= 0 && e2 <= 0 && e3 <= 0)
2594
+ v = true;
2595
+ }
2596
+ _topClosed.set(b, v);
2597
+ return v;
2598
+ }
2524
2599
 
2525
2600
  class LdrLodRoot extends THREE.LOD {
2526
2601
  clusters = [];
@@ -3470,6 +3545,8 @@ function* buildLdrSceneGen(insts, pack, P, color, mark) {
3470
3545
  const sKind = sMesh.map((x) => x?.kind ?? "");
3471
3546
  const sVis = sMesh.map((x) => x?.vis ?? 0);
3472
3547
  const STUD_ERR = 12;
3548
+ const STUD_BOX_ERR = 2.49;
3549
+ const STUD_BOX_W_LOW = 5.317;
3473
3550
  const STUD_DISC_ERR = 8;
3474
3551
  let _coopS = 0;
3475
3552
  for (let ci = 0;ci < sMesh.length; ci++) {
@@ -3488,9 +3565,23 @@ function* buildLdrSceneGen(insts, pack, P, color, mark) {
3488
3565
  im.userData.ldrStud = true;
3489
3566
  root.add(im);
3490
3567
  const cl = newCluster(im.boundingSphere, im);
3491
- cl.studEdge0 = true;
3568
+ cl.studLineLv = 0;
3492
3569
  cl.lv.push({ objs: [im], err: 0 });
3493
3570
  const discObjs = [];
3571
+ if (LOD && studTopClosed(k.body, arr) && (im.geometry.getIndex()?.count ?? im.geometry.getAttribute("position").count) > 30) {
3572
+ const box = new THREE.InstancedMesh(studBoxGeom(/(^|[\\/])8[\\/]/.test(kind) ? STUD_BOX_W_LOW : 6), im.material, 0);
3573
+ box.userData = { ldrStud: true, ldrLod: true };
3574
+ box.instanceMatrix = im.instanceMatrix;
3575
+ box.count = im.count;
3576
+ box.instanceColor = im.instanceColor;
3577
+ box.boundingSphere = im.boundingSphere;
3578
+ box.visible = false;
3579
+ box.onBeforeRender = trackVp;
3580
+ root.add(box);
3581
+ discObjs.push(box);
3582
+ cl.lv.push({ objs: [box], err: STUD_BOX_ERR });
3583
+ cl.studLineLv = 1;
3584
+ }
3494
3585
  if (LOD) {
3495
3586
  const disc = new THREE.InstancedMesh(studDiscGeom(), im.material, 0);
3496
3587
  disc.userData = { ldrStud: true, ldrLod: true };
@@ -3533,7 +3624,7 @@ function* buildLdrSceneGen(insts, pack, P, color, mark) {
3533
3624
  for (const o of l.objs)
3534
3625
  o.visible = i === c.cur;
3535
3626
  });
3536
- const lineVis = edgesOn && c.edgeOk && c.cur >= 0 && (c.studEdge0 ? c.cur === 0 : c.cur === 0 || !LOD || (c.setMergedLevel ? true : c.lv[c.cur].objs.length > 0));
3627
+ const lineVis = edgesOn && c.edgeOk && c.cur >= 0 && (c.studLineLv !== undefined ? c.cur <= c.studLineLv : c.cur === 0 || !LOD || (c.setMergedLevel ? true : c.lv[c.cur].objs.length > 0));
3537
3628
  for (const o of c.lines)
3538
3629
  o.visible = lineVis;
3539
3630
  for (const o of c.cond)
@@ -3764,7 +3855,7 @@ async function warmPackGeometry(pack, stop = () => false, sliceMs = 8) {
3764
3855
  await new Promise((r) => setTimeout(r, 0));
3765
3856
  }
3766
3857
  }
3767
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/scene.ts
3858
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/scene.ts
3768
3859
  import * as THREE2 from "three";
3769
3860
  var _box = new THREE2.Box3;
3770
3861
  var _m4 = new THREE2.Matrix4;
@@ -4119,10 +4210,10 @@ function createLdrObjectInner(instances, pack, options, progressive) {
4119
4210
  return finish();
4120
4211
  })();
4121
4212
  }
4122
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/parts-cdn.ts
4213
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/parts-cdn.ts
4123
4214
  import { decompress as decompress2 } from "fzstd";
4124
4215
 
4125
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/embedded.ts
4216
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/embedded.ts
4126
4217
  function splitFiles(text, fallback) {
4127
4218
  const files = new Map;
4128
4219
  let cur = null, saw = false;
@@ -4194,7 +4285,7 @@ function embeddedKeys(text, names, fallback = "main.ldr") {
4194
4285
  return out;
4195
4286
  }
4196
4287
 
4197
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/parts-cdn.ts
4288
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/parts-cdn.ts
4198
4289
  var DEFAULT_PARTS_CDN = "https://ldr-demo.vercel.app/cdn/v1/";
4199
4290
  var indexCache = new Map;
4200
4291
  var shardCache = new Map;
@@ -4448,10 +4539,10 @@ async function prepareModel(source, o = {}) {
4448
4539
  return { insts, pack, tier, missing, requests, bytes, cull, timings: { fetchModel: t1 - t0, parse: t2 - t1, parts: t3 - t2, ...cull ? { cull: performance.now() - t3 } : {} } };
4449
4540
  }
4450
4541
 
4451
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/load-worker.gen.ts
4542
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/load-worker.gen.ts
4452
4543
  var load_worker_gen_default = 'var Pt=ArrayBuffer,Y=Uint8Array,be=Uint16Array,kt=Int16Array;var ye=Int32Array,Pe=function(e,t,n){if(Y.prototype.slice)return Y.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 Y(n-t);return r.set(e.subarray(t,n)),r},fe=function(e,t,n,r){if(Y.prototype.fill)return Y.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},It=function(e,t,n,r){if(Y.prototype.copyWithin)return Y.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 Rt=["invalid zstd data","window size too large (>2046MB)","invalid block type","FSE accuracy too high","match distance too far back","unexpected EOF"],q=function(e,t,n){var r=Error(t||Rt[e]);if(r.code=e,Error.captureStackTrace)Error.captureStackTrace(r,q);if(!n)throw r;return r},Ye=function(e,t,n){var r=0,s=0;for(;r<n;++r)s|=e[t++]<<(r<<3);return s},Bt=function(e,t){return(e[t]|e[t+1]<<8|e[t+2]<<16|e[t+3]<<24)>>>0},Ft=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)q(0);var f=6-s,c=i==3?4:i,u=Ye(e,f,c);f+=c;var a=l?1<<l:s,p=Ye(e,f,a)+(l==1&&256),d=p;if(!s){var y=1<<10+(e[5]>>3);d=y+(y>>3)*(e[5]&7)}if(d>2145386496)q(1);var b=new Y((t==1?p||d:t?0:d)+12);return b[0]=1,b[4]=4,b[8]=8,{b:f+a,y:0,l:0,d:u,w:t&&t!=1?t:b.subarray(12),e:d,o:new ye(b.buffer,0,3),u:p,c:o,m:Math.min(131072,d)}}else if((n>>4|e[3]<<20)==25481893)return Bt(e,4)+8;q(0)},oe=function(e){var t=0;for(;1<<t<=e;++t);return t-1},pe=function(e,t,n){var r=(t<<3)+4,s=(e[t]&15)+5;if(s>n)q(3);var o=1<<s,i=o,l=-1,f=-1,c=-1,u=o,a=new Pt(512+(o<<2)),p=new kt(a,0,256),d=new be(a,0,256),y=new be(a,512,o),b=512+(o<<1),C=new Y(a,b,o),v=new Y(a,b+o);while(l<255&&i>0){var m=oe(i+1),g=r>>3,w=(1<<m+1)-1,F=(e[g]|e[g+1]<<8|e[g+2]<<16)>>(r&7)&w,A=(1<<m)-1,T=w-i-1,M=F&A;if(M<T)r+=m,F=M;else if(r+=m+1,F>A)F-=T;if(p[++l]=--F,F==-1)i+=F,C[--u]=l;else i-=F;if(!F)do{var k=r>>3;f=(e[k]|e[k+1]<<8)>>(r&7)&3,r+=2,l+=f}while(f==3)}if(l>255||i)q(0);var h=0,S=(o>>1)+(o>>3)+3,_=o-1;for(var j=0;j<=l;++j){var D=p[j];if(D<1){d[j]=-D;continue}for(c=0;c<D;++c){C[h]=j;do h=h+S&_;while(h>=u)}}if(h)q(0);for(c=0;c<o;++c){var E=d[C[c]]++,L=v[c]=s-oe(E);y[c]=(E<<L)-o}return[r+7>>3,{b:s,s:C,n:v,t:y}]},Dt=function(e,t){var n=0,r=-1,s=new Y(292),o=e[t],i=s.subarray(0,256),l=s.subarray(256,268),f=new be(s.buffer,268);if(o<128){var c=pe(e,t+1,6),u=c[0],a=c[1];t+=o;var p=u<<3,d=e[t];if(!d)q(0);var y=0,b=0,C=a.b,v=C,m=(++t<<3)-8+oe(d);for(;;){if(m-=C,m<p)break;var g=m>>3;if(y+=(e[g]|e[g+1]<<8)>>(m&7)&(1<<C)-1,i[++r]=a.s[y],m-=v,m<p)break;g=m>>3,b+=(e[g]|e[g+1]<<8)>>(m&7)&(1<<v)-1,i[++r]=a.s[b],C=a.n[y],y=a.t[y],v=a.n[b],b=a.t[b]}if(++r>255)q(0)}else{r=o-127;for(;n<r;n+=2){var w=e[++t];i[n]=w>>4,i[n+1]=w&15}++t}var F=0;for(n=0;n<r;++n){var A=i[n];if(A>11)q(0);F+=A&&1<<A-1}var T=oe(F)+1,M=1<<T,k=M-F;if(k&k-1)q(0);i[r++]=oe(k)+1;for(n=0;n<r;++n){var A=i[n];++l[i[n]=A&&T+1-A]}var h=new Y(M<<1),S=h.subarray(0,M),_=h.subarray(M);f[T]=0;for(n=T;n>0;--n){var j=f[n];fe(_,n,j,f[n-1]=j+l[n]*(1<<T-n))}if(f[0]!=M)q(0);for(n=0;n<r;++n){var D=i[n];if(D){var E=f[D];fe(S,n,E,f[D]=E+(1<<T-D))}}return[t,{n:_,b:T,s:S}]},Ut=pe(new Y([81,16,99,140,49,198,24,99,12,33,196,24,99,102,102,134,70,146,4]),0,6)[1],Ot=pe(new Y([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],Nt=pe(new Y([32,132,16,66,102,70,68,68,68,68,36,73,2]),0,5)[1],qe=function(e,t){var n=e.length,r=new ye(n);for(var s=0;s<n;++s)r[s]=t,t+=1<<e[s];return r},ke=new Y(new ye([0,0,0,0,16843009,50528770,134678020,202050057,269422093]).buffer,0,36),zt=qe(ke,0),Ie=new Y(new ye([0,0,0,0,0,0,0,0,16843009,50528770,117769220,185207048,252579084,16]).buffer,0,53),$t=qe(Ie,3),ue=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)q(0);var f=0,c=n.b,u=(r<<3)-8+oe(o)-c,a=-1;for(;u>l&&a<s;){var p=u>>3,d=(e[p]|e[p+1]<<8|e[p+2]<<16)>>(u&7);f=(f<<c|d)&i,t[++a]=n.s[f],u-=c=n.n[f]}if(u!=l||a+1!=s)q(0)},jt=function(e,t,n){var r=6,s=t.length,o=s+3>>2,i=o<<1,l=o+i;ue(e.subarray(r,r+=e[0]|e[1]<<8),t.subarray(0,o),n),ue(e.subarray(r,r+=e[2]|e[3]<<8),t.subarray(o,i),n),ue(e.subarray(r,r+=e[4]|e[5]<<8),t.subarray(i,l),n),ue(e.subarray(r),t.subarray(l),n)},Vt=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,f=(s+=3)+l;if(i==1){if(s>=e.length)return;if(t.b=s+1,n)return fe(n,e[s],t.y,t.y+=l),n;return fe(new Y(l),e[s])}if(f>e.length)return;if(i==0){if(t.b=f,n)return n.set(e.subarray(s,f),t.y),t.y+=l,n;return Pe(e,s,f)}if(i==2){var c=e[s],u=c&3,a=c>>2&3,p=c>>4,d=0,y=0;if(u<2)if(a&1)p|=e[++s]<<4|(a&2&&e[++s]<<12);else p=c>>3;else if(y=a,a<2)p|=(e[++s]&63)<<4,d=e[s]>>6|e[++s]<<2;else if(a==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 b=n?n.subarray(t.y,t.y+t.m):new Y(t.m),C=b.length-p;if(u==0)b.set(e.subarray(s,s+=p),C);else if(u==1)fe(b,e[s++],C);else{var v=t.h;if(u==2){var m=Dt(e,s);d+=s-(s=m[0]),t.h=v=m[1]}else if(!v)q(0);(y?jt:ue)(e.subarray(s,s+=d),b.subarray(C),v)}var g=e[s++];if(g){if(g==255)g=(e[s++]|e[s++]<<8)+32512;else if(g>127)g=g-128<<8|e[s++];var w=e[s++];if(w&3)q(0);var F=[Ot,Nt,Ut];for(var A=2;A>-1;--A){var T=w>>(A<<1)+2&3;if(T==1){var M=new Y([0,0,e[s++]]);F[A]={s:M.subarray(2,3),n:M.subarray(0,1),t:new be(M.buffer,0,1),b:0}}else if(T==2)r=pe(e,s,9-(A&1)),s=r[0],F[A]=r[1];else if(T==3){if(!t.t)q(0);F[A]=t.t[A]}}var k=t.t=F,h=k[0],S=k[1],_=k[2],j=e[f-1];if(!j)q(0);var D=(f<<3)-8+oe(j)-_.b,E=D>>3,L=0,O=(e[E]|e[E+1]<<8)>>(D&7)&(1<<_.b)-1;E=(D-=S.b)>>3;var H=(e[E]|e[E+1]<<8)>>(D&7)&(1<<S.b)-1;E=(D-=h.b)>>3;var W=(e[E]|e[E+1]<<8)>>(D&7)&(1<<h.b)-1;for(++g;--g;){var R=_.s[O],G=_.n[O],K=h.s[W],P=h.n[W],x=S.s[H],N=S.n[H];E=(D-=x)>>3;var U=1<<x,I=U+((e[E]|e[E+1]<<8|e[E+2]<<16|e[E+3]<<24)>>>(D&7)&U-1);E=(D-=Ie[K])>>3;var z=$t[K]+((e[E]|e[E+1]<<8|e[E+2]<<16)>>(D&7)&(1<<Ie[K])-1);E=(D-=ke[R])>>3;var X=zt[R]+((e[E]|e[E+1]<<8|e[E+2]<<16)>>(D&7)&(1<<ke[R])-1);if(E=(D-=G)>>3,O=_.t[O]+((e[E]|e[E+1]<<8)>>(D&7)&(1<<G)-1),E=(D-=P)>>3,W=h.t[W]+((e[E]|e[E+1]<<8)>>(D&7)&(1<<P)-1),E=(D-=N)>>3,H=S.t[H]+((e[E]|e[E+1]<<8)>>(D&7)&(1<<N)-1),I>3)t.o[2]=t.o[1],t.o[1]=t.o[0],t.o[0]=I-=3;else{var Z=I-(X!=0);if(Z){if(I=Z==3?t.o[0]-1:t.o[Z],Z>1)t.o[2]=t.o[1];t.o[1]=t.o[0],t.o[0]=I}else I=t.o[0]}for(var A=0;A<X;++A)b[L+A]=b[C+A];L+=X,C+=X;var V=L-I;if(V<0){var B=-V,Q=t.e+V;if(B>z)B=z;for(var A=0;A<B;++A)b[L+A]=t.w[Q+A];L+=B,z-=B,V=0}for(var A=0;A<z;++A)b[L+A]=b[V+A];L+=z}if(L!=C)while(C<b.length)b[L++]=b[C++];else L=b.length;if(n)t.y+=L;else b=Pe(b,0,L)}else if(n){if(t.y+=p,C)for(var A=0;A<p;++A)b[A]=b[C+A]}else if(C)b=Pe(b,C);return t.b=f,b}q(2)},_t=function(e,t){if(e.length==1)return e[0];var n=new Y(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 xe(e,t){var n=[],r=+!t,s=0,o=0;for(;e.length;){var i=Ft(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=Vt(e,i,t);if(!l)q(5);if(t)i.e=i.y;else n.push(l),o+=l.length,It(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 _t(n,o)}async function Ht(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(xe(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 Je(e){return new TextDecoder().decode(await Ht(e))}var Qe=(e)=>decodeURIComponent(e.split(/[?#]/)[0].split("/").pop()||"main.ldr").replace(/\\.(zst|gz)$/i,"")||"main.ldr";function we(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,"/"),Be=/^[A-Za-z][A-Za-z0-9_]*$/,Re=new Map;function Fe(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(!Re.has(r))Re.set(r,t);return r}function De(e){let t=e.charCodeAt(0)|32;if(t>=97&&t<=122&&Be.test(e))return Fe(e);if(/^0x/i.test(e))return parseInt(e,16);return+e}var et=/^~?\\s*moved\\s+to\\s+(.+)$/i,Gt=new Set(["FILE","NOFILE","!DATA","!:","STEP","BFC","ROTSTEP","BUFEXCHG","!TEXMAP"]),lt=new Set(["part","subpart","primitive","8_primitive","48_primitive","shortcut","helper"]),Wt=new Set(["model","submodel","configuration"]),Kt=/^(?:!?LDRAW_ORG|Unofficial|Official\\s+LCAD)\\s+(\\S+)/i;function tt(e){let t=Kt.exec(e);if(!t)return;let n=t[1].toLowerCase().replace(/^unofficial_/,"");return lt.has(n)||Wt.has(n)?n:void 0}function Xt(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 Zt(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 a=0;a<s;a++)l=l.replace(/^\\S+\\s*/,"");let f=Xt(l);if(!f.length)return null;let c={method:r,p1:i.slice(0,3),p2:i.slice(3,6),p3:i.slice(6,9),texture:f[0]};if(s>=10)c.a=i[9];if(s===11)c.b=i[10];let u=f.findIndex((a,p)=>p>0&&a.toUpperCase()==="GLOSSMAP");if(u>0&&f[u+1])c.glossmap=f[u+1];if(t)c.next=!0;return c}var Yt=(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 qt(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 u=s();if(u===null)return null;i[c]=+u}while(n<t&&r(e.charCodeAt(n)))n++;if(n>=t)return null;let l=e.slice(n),f=/[ \\t]{2,}|\\t/.test(l)?l.split(/\\s+/).join(" "):l;return{t:1,color:De(o),m:i,file:J(f)}}function nt(e){let t=+e[0];if(!(t>=1&&t<=5)||e.length<2)return null;let n=De(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 ct(e,t="main.ldr",n={}){let r=!!n.geometryText,s=new Map,o=null,i="",l,f=null,c=[],u=null,a=()=>{if(!f)return;let m=Yt(f.chunks.join("")),g=m[0]===137&&m[1]===80&&m[2]===78&&m[3]===71;(l??=new Map).set(J(f.name),{name:f.name,bytes:m,...g?{mime:"image/png"}:{}}),f=null},p=!0,d=(m)=>{if(a(),o={name:J(m),cmds:[]},s.set(o.name,o),!i)i=o.name;c=[],u=null,p=!0},y=!1,b=!1,C=()=>{if(b)return;b=!0,s.clear(),o=null,i=""},v=(m,g)=>{if(u){m.tex=u,u=null;return}let w=c[c.length-1];if(!w)return;if(w.fallback){if(!g)m.fallback=!0}else m.tex=w.map};for(let m of e.split(`\n`)){let g=m.trim();if(!g)continue;if(r&&g.charCodeAt(0)>=50&&g.charCodeAt(0)<=53&&(g.charCodeAt(1)===32||g.charCodeAt(1)===9)){if(f||y)continue;if(!o)d(t);let T=g.slice(2).trimStart(),M=T.search(/\\s/),k={t:g.charCodeAt(0)-48,color:De(M<0?T:T.slice(0,M)),p:[],src:g};v(k,!1),o.cmds.push(k),p=!1;continue}if(g.charCodeAt(0)===48&&(g.charCodeAt(1)===32||g.charCodeAt(1)===9)){let T=2;while(g.charCodeAt(T)===32||g.charCodeAt(T)===9)T++;let M=T;while(M<g.length&&g.charCodeAt(M)!==32&&g.charCodeAt(M)!==9)M++;let k=g.slice(T,M);if(!Gt.has(k)){if(y||f)continue;if(!o)d(t);let h=g.slice(T),S={t:0,text:h};if(k.charCodeAt(0)===33)S.meta=k;if(u=null,p&&!o.org){let j=tt(h);if(j)o.org=j}let _=h.match(et);if(_&&!o.movedTo){let j=_[1].trim().replace(/\\\\/g,"/");if(!/\\.(dat|ldr|mpd)$/i.test(j))j+=".dat";o.movedTo=J(j)}o.cmds.push(S);continue}}if(g.charCodeAt(0)===49&&(g.charCodeAt(1)===32||g.charCodeAt(1)===9)&&!f&&!y){let T=qt(g);if(T){if(!o)d(t);v(T,!1),o.cmds.push(T),p=!1;continue}}let w=g.split(/\\s+/);if(+w[0]===0){let T=g.slice(1).trim();if(w[1]==="FILE"){C(),y=!1,d(T.slice(5));continue}if(w[1]==="NOFILE"){a(),o=null,y=!0;continue}if(w[1]==="!DATA"){C(),a(),o=null,y=!1,f={name:T.slice(5).trim(),chunks:[]};continue}if(y)continue;if(f){if(w[1]==="!:")f.chunks.push(w.slice(2).join(""));continue}if(!o)d(t);let M={t:0,text:T};if(w[1]==="STEP")M.step=!0,c=[],u=null;else if(w[1]==="BFC")M.bfc=w.slice(2).join(" ");else if(w[1]==="ROTSTEP")if(M.meta="ROTSTEP",M.step=!0,c=[],u=null,(w[2]??"").toUpperCase()==="END")M.rotstep={x:0,y:0,z:0,mode:"END"};else{let h=(w[5]??"REL").toUpperCase();M.rotstep={x:+w[2]||0,y:+w[3]||0,z:+w[4]||0,mode:["REL","ABS","ADD"].includes(h)?h:"REL"}}else if(w[1]==="BUFEXCHG"){M.meta="BUFEXCHG";let h=(w[2]??"").toUpperCase();M.bufexchg={op:h==="RETRIEVE"?"RETRIEVE":"STORE",buf:w[3]??"A"}}else if(w[1]?.startsWith("!"))M.meta=w[1];if(p&&!o.org){let h=tt(T);if(h)o.org=h}if(w[1]==="!TEXMAP"){let h=(w[2]??"").toUpperCase();if(u=null,h==="START"||h==="NEXT"){let S=Zt(T.replace(/^!TEXMAP\\s+\\S+/i,""),h==="NEXT");if(M.texmap={op:h,...S?{map:S}:{}},S)if((o.texmaps??=[]).push(S),h==="START")c.push({map:S,fallback:!1});else u=S}else if(h==="FALLBACK"){M.texmap={op:h};let S=c[c.length-1];if(S)S.fallback=!0}else if(h==="END")M.texmap={op:h},c.pop()}else if(w[1]==="!:"){u=null;let h=nt(w.slice(2));if(h)v(h,!0),M.geom=h}else u=null;let k=T.match(et);if(k&&!o.movedTo){let h=k[1].trim().replace(/\\\\/g,"/");if(!/\\.(dat|ldr|mpd)$/i.test(h))h+=".dat";o.movedTo=J(h)}o.cmds.push(M);continue}if(f||y)continue;if(!o)d(t);let A=nt(w);if(!A)continue;v(A,!1),o.cmds.push(A),p=!1}return a(),l?{main:i,files:s,data:l}:{main:i,files:s}}var Cn=Math.PI/180;function ut(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 ft(e,t){let[n,r,s,o,i,l,f,c,u,a,p,d]=e,[y,b,C,v,m,g,w,F,A,T,M,k]=t;return[o*y+i*b+l*C+n,f*y+c*b+u*C+r,a*y+p*b+d*C+s,o*v+i*w+l*T,o*m+i*F+l*M,o*g+i*A+l*k,f*v+c*w+u*T,f*m+c*F+u*M,f*g+c*A+u*k,a*v+p*w+d*T,a*m+p*F+d*M,a*g+p*A+d*k]}var Ue=[0,0,0,1,0,0,0,1,0,0,0,1];var rt=new WeakMap,Jt=/^(s|8|48)\\//;function Oe(e,t){let n=e.files.get(J(t));if(!n)return"part";let r=rt.get(n);if(r)return r;if(n.org)r=lt.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&&Jt.test(s.file))?"part":"model";return rt.set(n,r),r}var st=new WeakMap;function pt(e){let t=st.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 st.set(e,t),t}var ot=(e)=>e>16777215?"0x"+e.toString(16).toUpperCase():e<0?Re.get(e)??String(e):String(e),Qt=(e)=>e.t===0?"0 "+e.text:e.t===1?`1 ${ot(e.color)} ${e.m.join(" ")} ${e.file}`:e.src?e.src:`${e.t} ${ot(e.color)} ${e.p.join(" ")}`,Ne=(e,t)=>`${J(e)}#${t}`;function en(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||o.meta==="!COLOUR"){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:Ne(e.name,t),cmds:n}}function mt(e,t){return[`0 ldr: own geometry of ${e.name}, step ${t}`,...en(e,t).cmds.map(Qt)].join(`\n`)+`\n`}function ze(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 ht(e){let[t,n,r,s,o,i,l,f,c,u,a,p]=e,d=f*p-c*a,y=-(l*p-c*u),b=l*a-f*u,C=s*d+o*y+i*b;if(!Number.isFinite(C)||Math.abs(C)<0.000000000001)return null;let v=1/C,m=[d*v,-(o*p-i*a)*v,(o*c-i*f)*v,y*v,(s*p-i*u)*v,-(s*c-i*l)*v,b*v,-(s*a-o*u)*v,(s*f-o*l)*v];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 tn=(e)=>String(+e.toFixed(6)||0),it=(e)=>\'"\'+e.replace(/\\\\/g,"\\\\\\\\").replace(/"/g,"\\\\\\"")+\'"\';function gt(e,t){let n=[...t.p1,...t.p2,...t.p3,...t.method!=="PLANAR"?[t.a??360]:[],...t.method==="SPHERICAL"?[t.b??180]:[]].map(tn).join(" "),r=`0 ldr: ${e} with a model-level !TEXMAP\n0 BFC CERTIFY CCW\n0 !TEXMAP START ${t.method} ${n} ${it(t.texture)}${t.glossmap?" GLOSSMAP "+it(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-${ze(r)}`,source:r}}var nn=(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 rn(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),f=Math.sin(n*r),c=Math.cos(n*r);return[l*c,-l*f,i,o*f+s*i*c,o*c-s*i*f,-s*l,s*f-o*i*c,s*c+o*i*f,o*l]}var at=new WeakMap;function dt(e){let t=at.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=rn(o.x,o.y,o.z);r=o.mode==="ABS"?{abs:!0,m:i,rotstep:o}:o.mode==="ADD"&&r?{abs:r.abs,m:nn(r.m,i),rotstep:o}:{abs:!1,m:i,rotstep:o}}n.push(r)}return n.push(r),at.set(e,n),n}var bt=999999,wt=(e)=>e.map((t)=>String(t).padStart(6,"0")).join(".")+"~",Mt=new WeakMap,yt=new WeakMap;function sn(e,t){let n=yt.get(t);if(!n)n={head:[...t.values()].map((o)=>{let i=Mt.get(o)??"",l=i.indexOf("!COLOUR");return l<0?"":"0 "+i.slice(l).trim().replace(/\\s+/g," ")}).filter(Boolean).join(`\n`),parts:new Map},yt.set(t,n);let r=n.parts.get(e);if(!r){let s=J(e),o=`0 ldr: ${s} placed in a model\'s !COLOUR scope\n0 BFC CERTIFY CCW\n${n.head}\n1 16 0 0 0 1 0 0 0 1 0 0 0 1 ${s}\n`;r={name:`${s}#col-${ze(o)}`,source:o},n.parts.set(e,r)}return r}function on(e,t={}){let n=[],r=t.maxDepth??64,s=t.looseGeometry!==!1,o=!!t.textures,i=!!t.callouts,l=new Map,f=0,c=(a,p)=>{let d=a.name+"#"+p,y=l.get(d);if(!y){let b;y=Object.assign(()=>b??=mt(a,p),{file:a,step:p}),l.set(d,y)}return y},u=(a,p,d,y,b,C,v,m,g=null,w=[],F=[],A=void 0,T=null)=>{let M=a.files.get(p);if(!M||v>r)return;let k=T,h=0,S=v>0?++f:0,_=i&&S?[...w,S]:w,j=i&&S?[...F,d]:F,D=i&&!g?new Map:null,E=-1,L=0,O=(P,x,N,U,I,z,X)=>{if(E!==h)E=h,L=0;let Z=D?.get(h+"|"+x);if(Z)return Z.n++,u(P,P===a?x:P.main,N,U,b+"/"+x,[...I,bt],v+1,z,[...I,bt],_,j,X,k);let V=[...I,L++],B=n.length;u(P,P===a?x:P.main,N,U,b+"/"+x,V,v+1,z,g,_,j,X,k),D?.set(h+"|"+x,{n:1,from:B,to:n.length})},H=dt(M),W=s?pt(M):[],R=0,G=(P,x,N,U,I,z,X,Z,V)=>{if(g)U=g;let B={part:P,color:x,m:N,step:U[0],steps:U,localStep:I,path:b};if(Z)B.colour=Z;if(S){if(B.sub=S,i)B.subPath=_,B.subMats=j}if(z)B.embedded=!0;if(X){let ee=gt(P,X);B.texPart=ee.name,B.texSource=ee.source}else if(V){let ee=sn(P,V);B.colPart=ee.name,B.colSource=ee.source}let Q=H[I];if(Q)B.view=Q;return n.push(B),B},K=(P)=>{while(R<W.length&&W[R]<=P){let x=W[R++];G(Ne(M.name,x),y,d,[...C,x],x,!1,null,A,T).source=c(M,x)}};for(let P of M.cmds){if(P.t===0&&P.step){h++;continue}let x=P;if(x.t>=2||x.t===0&&x.geom&&x.geom.t>=2){K(h);continue}if(x.t===0){if(x.meta==="!COLOUR"){let Q=ln(x.text);if(Q&&Q.code!==16&&Q.code!==24)Mt.set(Q,x.text),(k=new Map(k??[])).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 N=x.color===16?y:x.color,U=x.color===16?A:k?.get(x.color),I=ft(d,x.m),z=[...C,h],X=o?x.tex??m:null,Z=X?ht(x.m):null,V=X&&Z?ut(X,Z):null;if(a.files.has(x.file)){if(Oe(a,x.file)==="model"){O(a,x.file,I,N,z,V,U);continue}G(x.file,N,I,z,h,!0,V,U,k);continue}let B=t.resolveModel?.(x.file);if(B){O(B,x.file,I,N,z,V,U);continue}G(x.file,N,I,z,h,!1,V,U,k)}if(K(1/0),D){for(let P of D.values())if(P.n>1)for(let x=P.from;x<P.to;x++)n[x].mult??=P.n}};if(Oe(e,e.main)==="part"){if(e.files.get(e.main))n.push({part:e.main,color:16,m:[...Ue],step:0,steps:[0],localStep:0,path:e.main,embedded:!0});return n}return u(e,e.main,Ue,16,e.main,[],0,null),n}function At(e,t="main.ldr",n){return on(ct(e,t,{geometryText:!0}),n)}var an=new Set(["CHROME","PEARLESCENT","RUBBER","MATTE_METALLIC","METAL","MATERIAL"]);function $e(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 xt(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=$e(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 ln(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",l=255,f=0,c={type:"default"},u=1;while(u<n.length){let a=n[u].toUpperCase(),p=n[u+1];if(a==="CODE")s=p!==void 0&&Be.test(p)?Fe(p):p!==void 0&&/^\\d+$/.test(p)?+p:NaN,u+=2;else if(a==="VALUE"){let d=$e(p);if(d)o=d;u+=2}else if(a==="EDGE")i=$e(p)??p,u+=2;else if(a==="ALPHA")l=+p,u+=2;else if(a==="LUMINANCE")f=+p,u+=2;else if(a==="CHROME")c={type:"chrome"},u+=1;else if(a==="PEARLESCENT")c={type:"pearlescent"},u+=1;else if(a==="RUBBER")c={type:"rubber"},u+=1;else if(a==="MATTE_METALLIC")c={type:"matte_metallic"},u+=1;else if(a==="METAL")c={type:"metal"},u+=1;else if(a==="MATERIAL"){let d=(n[u+1]||"").toUpperCase();if(d==="GLITTER"){let{grain:y,next:b}=xt(n,u+2);c={type:"glitter",material:y},u=b}else if(d==="SPECKLE"){let{grain:y,next:b}=xt(n,u+2);c={type:"speckle",material:y},u=b}else if(d==="FABRIC"){let y=(n[u+2]||"").toUpperCase(),b=["VELVET","CANVAS","STRING","FUR"].includes(y)?y.toLowerCase():void 0;c={type:"fabric",kind:b},u+=b?3:2}else u=n.length}else if(an.has(a))u+=1;else u+=1}if(Number.isNaN(s)||!o)return null;return{code:s,name:r,hex:o,edge:i,alpha:Number.isFinite(l)?l:255,luminance:Number.isFinite(f)?f:0,finish:c}}function cn(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,l=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:l,finish:"glitter"}}case"speckle":{let i=e.finish.material,l=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:l,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 je(e){let t=cn(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 un(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 fn=(e)=>{if(!e.startsWith("1 "))return null;let t=e.split(" ");return t.length>=15?J(t.slice(14).join(" ")):null};function pn(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 vt(e,t,n="main.ldr"){let r=un(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]),f=[i];while(f.length)for(let u of r.get(f.pop())){let a=fn(u);if(a&&r.has(a)&&!l.has(a))l.add(a),f.push(a)}let c=[i,...[...l].filter((u)=>u!==i).sort()].map((u)=>"0 FILE "+(u===i?"":u)+`\n`+r.get(u).join(`\n`)).join(`\n`);s.set(i,`emb/${pn(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,Tt=new WeakMap;function Ve(e,t){let n=Tt.get(e);if(!n)Tt.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=[],f=[];s.studs.forEach((p,d)=>{l.push(p[0]),f.push(p[1]);for(let y=0;y<12;y++)i[d*12+y]=p[2+y]});let c=null,u=0,a=0;if(s.mask){u=s.mask[0],a=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:l,color:f,mask:c,nx:u,nz:a}),r}var le=1073741824;class _e{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,f=this.c;for(;;){if(!o[s])return o[s]=1,i[s]=e,l[s]=t,f[s]=n,this.vals[s]=r,this.size++,-1;if(i[s]===e&&l[s]===t&&f[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 Me=(e,t,n)=>e>-le&&e<le&&t>-le&&t<le&&n>-le&&n<le,me=2147483647;function mn(e,t){let n=e.colorTable?.[t];if(n)return(n.alpha??255)<255;return t.charCodeAt(0)===35&&/\\/[^:/]*:a\\d/.test(t)}function hn(e,t,n){let s=new Map,o=(L)=>{let O=s.get(L);if(O===void 0)s.set(L,O=mn(t,L));return O},i=[],l=[],f=[],c=[],u=[],a=[],p=[],d=[],y=new _e(e.length*2),b=[],C=[];for(let L=0;L<e.length;L++){let O=e[L],H=O.m,W=t.parts[O.part];if(!W||!W.mask||!Ct(H)||o(O.color))continue;let R=W.bbox,G=1/0,K=-1/0,P=1/0,x=-1/0;for(let I=0;I<2;I++)for(let z=0;z<2;z++){let X=I?R[3]:R[0],Z=z?R[5]:R[2],V=H[0]+H[3]*X+H[5]*Z,B=H[2]+H[9]*X+H[11]*Z;if(V<G)G=V;if(V>K)K=V;if(B<P)P=B;if(B>x)x=B}let N=u.length;i.push(G),l.push(K),f.push(P),c.push(x),u.push(L),a.push(Ve(t,O.part)),p.push(R[0]),d.push(R[2]);let U=Math.round((H[1]+R[4])*2);for(let I=Math.floor(G/40);I<=Math.floor(K/40);I++)for(let z=Math.floor(P/40);z<=Math.floor(x/40);z++){if(!Me(U,I,z))continue;let X=C.length;C.push(N),b.push(y.put(U,I,z,X))}}let v=[0,5,-5,5,-5],m=[0,5,5,-5,-5],g=NaN,w=NaN,F=NaN,A=-1,T=(L,O,H,W)=>{let R=Math.round(O*2),G=Math.floor(L/40),K=Math.floor(H/40);if(!Me(R,G,K))return me;let P=me;if(R!==g||G!==w||K!==F)g=R,w=G,F=K,A=y.get(R,G,K);for(let x=A;x>=0;x=b[x]){let N=C[x];if(u[N]===W||!(L-6>=i[N]-0.5&&L+6<=l[N]+0.5&&H-6>=f[N]-0.5&&H+6<=c[N]+0.5))continue;let U=e[u[N]].m,I=a[N],z=p[N],X=d[N],Z=L-U[0],V=O-U[1],B=H-U[2],Q=U[3]*Z+U[6]*V+U[9]*B,ee=U[5]*Z+U[8]*V+U[11]*B,{nx:ne,nz:ie,mask:ce}=I,ae=!0;for(let te=0;te<5;te++){let re=Math.floor((Q+v[te]-z)/20),se=Math.floor((ee+m[te]-X)/20);if(re<0||se<0||re>=ne||se>=ie||ce[re*ie+se]!==1){ae=!1;break}}if(ae){if(!n)return 0;let te=n[u[N]];if(te<P)P=te}}return P},M=0;for(let L of e){let O=Ve(t,L.part);if(O)M+=O.nStuds}let k=new Uint8Array(M),h=new Uint8Array(M),S=new _e(M),_=0,j=n?new Int32Array(M).fill(me):void 0;for(let L=0,O=0;L<e.length;L++){let H=e[L],W=Ve(t,H.part);if(!W)continue;let R=H.m,G=W.studM,K=R[0],P=R[1],x=R[2],N=R[3],U=R[4],I=R[5],z=R[6],X=R[7],Z=R[8],V=R[9],B=R[10],Q=R[11];for(let ee=0;ee<W.nStuds;ee++,O++){let ne=ee*12,ie=G[ne+4],ce=G[ne+7],ae=G[ne+10];if(!(Math.abs(z*ie+X*ce+Z*ae-1)<0.001&&Math.abs(N*ie+U*ce+I*ae)<0.001&&Math.abs(V*ie+B*ce+Q*ae)<0.001))continue;h[O]=1;let te=G[ne],re=G[ne+1],se=G[ne+2],He=K+N*te+U*re+I*se,Ge=P+z*te+X*re+Z*se,We=x+V*te+B*re+Q*se,Ke=T(He,Ge,We,L);if(Ke!==me){if(k[O]=1,_++,j)j[O]=Ke}let he=Math.round(He),ge=Math.round(Ge),de=Math.round(We);if(!Me(he,ge,de))continue;if(!n){S.put(he,ge,de,1);continue}let Xe=n[L],Ze=S.get(he,ge,de);if(Ze<0||Xe<Ze)S.put(he,ge,de,Xe)}}let D=new Uint8Array(e.length),E=n?new Int32Array(e.length).fill(me):void 0;for(let L=0;L<e.length;L++){let O=e[L],H=t.parts[O.part];if(!H||!H.under||!Ct(O.m)||o(O.color))continue;let W=H.bbox,R=Math.round((W[3]-W[0])/20),G=Math.round((W[5]-W[2])/20);if(!R||!G||R*G>4096)continue;let K=O.m,P=!0,x=0;for(let N=0;N<R&&P;N++)for(let U=0;U<G;U++){let I=W[0]+10+20*N,z=W[2]+10+20*U,X=K[0]+K[3]*I+K[5]*z,Z=K[2]+K[9]*I+K[11]*z,V=Math.round(X),B=Math.round(K[1]+W[4]),Q=Math.round(Z),ee=Me(V,B,Q)?S.get(V,B,Q):-1;if(ee<0){P=!1;break}if(ee>x)x=ee}if(P){if(D[L]=1,E)E[L]=x}}return{nStuds:M,studHidden:k,studUp:h,underHidden:D,studsHidden:_,studHideStep:j,underHideStep:E}}function gn(e,t,n){let r=(a)=>a.colPart&&t.parts[a.colPart]?a.colPart:n&&a.texPart&&t.parts[a.texPart]?a.texPart:a.part,s=new Map,o=new Map,i=(a)=>{let p=a.colour;if(!p)return String(a.color);let d=o.get(p);if(d!==void 0)return d;let y=t.colorTable?.[a.color],b=y?.hex??t.colors?.[a.color],C=y?je({alpha:y.alpha??255,luminance:y.luminance??0,finish:y.finish??{type:"default"}}):"default:op",v=je(p);if(d=b&&b.toUpperCase()===p.hex.toUpperCase()&&C===v?String(a.color):p.hex.toUpperCase()+"/"+v,d!==String(a.color))s.set(d,p);return o.set(p,d),d},l=e.map((a)=>({part:r(a),color:i(a),m:a.m,steps:a.steps})),f=l.map((a)=>wt(a.steps)),c=[...new Set(f)].sort(),u=new Map(c.map((a,p)=>[a,p]));return{all:l,stepOf:f.map((a)=>u.get(a)),nSteps:c.length,localColours:s}}function Ae(e,t,n=!0){let r=gn(e,t,n);return hn(r.all,t,r.nSteps>1?r.stepOf:void 0)}var Se="https://ldr-demo.vercel.app/cdn/v1/",Ce=new Map,ve=new Map;function Te(e=Se,t=fetch){let n=Ce.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(()=>Ce.delete(e)),Ce.set(e,n);return n}var dn=(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"),Le=(e,t)=>dn(e)?[e[0]+t,e[1],e[2]]:Array.isArray(e)?e.map((n)=>Le(n,t)):e&&typeof e==="object"?Object.fromEntries(Object.entries(e).map(([n,r])=>[n,Le(r,t)])):e;function bn(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 y=new DataView(d).getUint32(0,!0),b=new Uint8Array(d,4+y),C=r;n.push(b),r+=b.byteLength;let v=(4-r%4)%4;if(v)n.push(new Uint8Array(v)),r+=v;for(let[m,g]of Object.entries(p.header.parts??{}))if(!(m in s))s[m]=Le(g,C);for(let[m,g]of Object.entries(p.header.studKinds??{}))if(!(m in o))o[m]=Le(g,C)}let i=e[0]?.header??{version:1,weld:!0},l=new TextEncoder().encode(JSON.stringify({...i,parts:s,studKinds:o,...t})),f=(4-(4+l.length)%4)%4,c=4+l.length+f,u=new Uint8Array(c+r);new DataView(u.buffer).setUint32(0,l.length+f,!0),u.set(l,4),u.fill(32,4+l.length,c);let a=c;for(let p of n)u.set(p,a),a+=p.byteLength;return we(u.buffer)}async function yn(e,t={}){e=[...e];try{return await Lt(e,t)}catch(n){let r=t.cdn??Se,s=t.fetch??fetch;Ce.delete(r);let o=(i,l)=>s(i,{...l,cache:"reload"});try{return await Lt(e,{...t,fetch:o})}catch{throw n}}}async function Lt(e,t){let n=t.cdn??Se,r=t.fetch??fetch,s=t.gap??16384,o=await Te(n,r),i=[...new Set([...e].map(J))],l=[],f=[];for(let m of i){if(ve.has(n+m))continue;let g=o.parts[m];if(g)f.push({name:m,off:g[0],len:g[1],file:g[2]??0});else l.push(m)}f.sort((m,g)=>m.file-g.file||m.off-g.off);let c=[];for(let m of f){let g=c[c.length-1];if(g&&g.file===m.file&&m.off-g.end<=s)g.end=Math.max(g.end,m.off+m.len),g.items.push(m);else c.push({file:m.file,start:m.off,end:m.off+m.len,items:[m]})}let u=0,a=0,p=0,d=new Map,y=async()=>{while(p<c.length){let m=c[p++],g=d.get(m.file);if(g)g=g.subarray(m.start,m.end);else{let w=await r(new URL(o.archives[m.file],n).href,{headers:{Range:`bytes=${m.start}-${m.end-1}`,"Accept-Encoding":"identity"}});if(!w.ok)throw Error(`ldr: parts CDN ${w.status}`);if(a++,g=new Uint8Array(await w.arrayBuffer()),u+=g.byteLength,w.status===200)d.set(m.file,g),g=g.subarray(m.start,m.end)}for(let w of m.items){let F=xe(g.subarray(w.off-m.start,w.off-m.start+w.len)),A=F.buffer.slice(F.byteOffset,F.byteOffset+F.byteLength);ve.set(n+w.name,we(A))}}};await Promise.all(Array.from({length:Math.min(t.concurrency??24,c.length)},y));let b=i.filter((m)=>ve.has(n+m)).map((m)=>ve.get(n+m)),C={colors:o.colors,...o.colorTable?{colorTable:o.colorTable}:{}};return{pack:b.length?bn(b,C):we(xn(C)),missing:l,requests:a,bytes:u}}function xn(e){let t=new TextEncoder().encode(JSON.stringify({version:1,weld:!0,parts:{},studKinds:{},...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 wn(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 St(e,t,n){let r=0,s=0,o=!1,i=new Set;for(let l of e){let f=l.embedded?t.get(l.part):J(l.part),c=f?n.parts[f]:void 0;if(!c)continue;if(c[3]!=null)o=!0,r+=c[3];if(!i.has(f))i.add(f),s+=c[1]}return{bodyTris:r,packBytes:s,known:o}}class Ee 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 Et(e,t={}){let n=performance.now(),r=t.fetch??fetch,s=Te(t.cdn??Se,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 Je(await h.arrayBuffer())}),i=performance.now(),l=t.name??(t.text?"main.ldr":Qe(e)),f=At(o,l,{looseGeometry:!1,callouts:t.callouts}),c=performance.now();t.onParsed?.(f),await s;let u=vt(o,new Set(f.filter((h)=>h.embedded).map((h)=>h.part)),l),a=(h,S)=>t.maxBodyTris!=null&&h>t.maxBodyTris||t.maxPackBytes!=null&&S>t.maxPackBytes,p=t.maxBodyTris!=null||t.maxPackBytes!=null,d=(h)=>new Ee({...h,maxBodyTris:t.maxBodyTris,maxPackBytes:t.maxPackBytes}),y="full";if(p){let h=St(f,u,await s);if(a(h.known?h.bodyTris:0,h.packBytes)){if(!t.lowCdn)throw d(h);let S=await Te(t.lowCdn,r).catch(()=>null);if(!S)throw d(h);let _=St(f,u,S);if(a(_.known?_.bodyTris:0,_.packBytes))throw d(_);y="low"}}let b=[...f.filter((h)=>!h.embedded).map((h)=>h.part),...u.values()],C=async()=>{let h=await yn(b,y==="low"?{...t,cdn:t.lowCdn}:t);for(let[S,_]of u){let j=h.pack.header.parts[_];if(j)h.pack.header.parts[S]=j}return{...h,packBytes:h.pack.buffer?.byteLength??h.pack.bytes??0,bodyTris:wn(f,h.pack)}},v=await C();if(p&&a(v.bodyTris,v.packBytes)&&y==="full"&&t.lowCdn&&await Te(t.lowCdn,r).then(()=>!0,()=>!1)){y="low";let h=v;v=await C(),v.requests+=h.requests,v.bytes+=h.bytes}if(p&&a(v.bodyTris,v.packBytes))throw d(v);let{pack:m,missing:g,requests:w,bytes:F}=v,A=new Map([...u].map(([h,S])=>[S,h])),T=g.map((h)=>A.get(h)??h),M=performance.now(),k=t.cull?Ae(f,m.header,t.textures!==!1):void 0;return{insts:f,pack:m,tier:y,missing:T,requests:w,bytes:F,cull:k,timings:{fetchModel:i-n,parse:c-i,parts:M-c,...k?{cull:performance.now()-M}:{}}}}self.onmessage=async(e)=>{let{id:t,source:n,opts:r}=e.data;try{let s=await Et(n,{...r,cull:!1,onParsed:(u)=>self.postMessage({id:t,insts:u})}),o=s.pack.buffer;if(self.postMessage({id:t,buffer:o,tier:s.tier,missing:s.missing,requests:s.requests,bytes:s.bytes,timings:s.timings},[o]),!r.cull)return;let i=performance.now(),l=Ae(s.insts,s.pack.header,r.textures!==!1),f=performance.now()-i,c=[];for(let u of[l.studHidden,l.studUp,l.underHidden,l.studHideStep,l.underHideStep])if(u)c.push(u.buffer);self.postMessage({id:t,cull:l,ms:f},c)}catch(s){if(s instanceof Ee||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';
4453
4544
 
4454
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/cdn.ts
4545
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/cdn.ts
4455
4546
  var worker;
4456
4547
  var seq = 0;
4457
4548
  var pending = new Map;
@@ -4565,7 +4656,7 @@ async function loadModel(source, o = {}) {
4565
4656
  timings: { ...prep.timings, parts: t3 - t0 - prep.timings.fetchModel - prep.timings.parse, build: t4 - t3, total: t4 - t0 }
4566
4657
  });
4567
4658
  }
4568
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/node/library.ts
4659
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/node/library.ts
4569
4660
  import { existsSync, readFileSync } from "fs";
4570
4661
  import { join } from "path";
4571
4662
  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]];
@@ -4709,7 +4800,7 @@ class Library {
4709
4800
  const f = doc.files.get(fname);
4710
4801
  if (!f)
4711
4802
  return;
4712
- let ccw = true, invertNext = false, clipLocal = clip, scope = scope0;
4803
+ let ccw = true, invertNext = false, clipLocal = true, certified = null, scope = scope0;
4713
4804
  const flip = inv !== det(m) < 0;
4714
4805
  const cc = (c) => {
4715
4806
  if (c === 16)
@@ -4732,37 +4823,50 @@ class Library {
4732
4823
  if (tx && c.geom)
4733
4824
  c = c.geom;
4734
4825
  else {
4735
- if (c.meta === "!COLOUR") {
4736
- const d = parseColourLine(c.text);
4737
- if (d && d.code !== 16 && d.code !== 24)
4738
- (scope = new Map(scope ?? [])).set(d.code, d);
4826
+ if (c.bfc === undefined) {
4827
+ invertNext = false;
4828
+ if (c.meta === "!COLOUR") {
4829
+ const d = parseColourLine(c.text);
4830
+ if (d && d.code !== 16 && d.code !== 24)
4831
+ (scope = new Map(scope ?? [])).set(d.code, d);
4832
+ }
4739
4833
  continue;
4740
4834
  }
4741
- if (c.bfc) {
4742
- if (c.bfc.includes("CW") && !c.bfc.includes("CCW"))
4743
- ccw = false;
4744
- if (c.bfc.includes("CCW"))
4745
- ccw = true;
4746
- if (c.bfc.includes("INVERTNEXT"))
4747
- invertNext = true;
4748
- if (/\bNOCLIP\b/.test(c.bfc))
4749
- clipLocal = false;
4750
- else if (/\bCLIP\b/.test(c.bfc))
4751
- clipLocal = true;
4752
- }
4835
+ const o = c.bfc.split(/\s+/);
4836
+ invertNext = false;
4837
+ if (certified === null)
4838
+ certified = !o.includes("NOCERTIFY");
4839
+ if (certified)
4840
+ for (const w of o) {
4841
+ if (w === "CW")
4842
+ ccw = false;
4843
+ else if (w === "CCW")
4844
+ ccw = true;
4845
+ else if (w === "CLIP")
4846
+ clipLocal = true;
4847
+ else if (w === "NOCLIP")
4848
+ clipLocal = false;
4849
+ else if (w === "INVERTNEXT")
4850
+ invertNext = true;
4851
+ }
4753
4852
  continue;
4754
4853
  }
4755
4854
  }
4756
- if (c.t === 0)
4855
+ if (c.t === 0) {
4856
+ invertNext = false;
4757
4857
  continue;
4858
+ }
4859
+ if (certified === null)
4860
+ certified = false;
4861
+ const cull = clip && clipLocal, invertThis = c.t === 1 && invertNext;
4862
+ invertNext = false;
4758
4863
  if (tx && c.fallback)
4759
4864
  continue;
4760
4865
  const tex = tx ? c.tex ? transformTexMap(c.tex, m) : texIn : null;
4761
4866
  if (c.t === 1) {
4762
4867
  const sub = doc.files.has(c.file) ? doc : this.where(c.file)?.doc;
4763
4868
  if (sub)
4764
- this.emit(sub, sub === doc ? c.file : sub.main, mul(m, c.m), cc(c.color), inv !== invertNext, clipLocal, pos, col, edges, cond, tx, tex, scope);
4765
- invertNext = false;
4869
+ this.emit(sub, sub === doc ? c.file : sub.main, mul(m, c.m), cc(c.color), inv !== invertThis, cull, pos, col, edges, cond, tx, tex, scope);
4766
4870
  continue;
4767
4871
  }
4768
4872
  const p = c.p, v = [];
@@ -4796,7 +4900,7 @@ class Library {
4796
4900
  tri(w[0], w[2], w[3]);
4797
4901
  };
4798
4902
  emitFace(ordered);
4799
- if (!clipLocal)
4903
+ if (!cull)
4800
4904
  emitFace([...ordered].reverse());
4801
4905
  }
4802
4906
  }
@@ -4848,11 +4952,11 @@ class Library {
4848
4952
  return insts;
4849
4953
  }
4850
4954
  }
4851
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/node/build-pack.ts
4955
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/node/build-pack.ts
4852
4956
  import fs3 from "node:fs";
4853
4957
  import path3 from "node:path";
4854
4958
 
4855
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/node/resolver.ts
4959
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/node/resolver.ts
4856
4960
  import fs from "node:fs";
4857
4961
  import path from "node:path";
4858
4962
  var TOP_STUD_RE = /^(stud|studa|stud2|stud2a|stud6|stud6a|stud10|stud15|stud2s|stud2s2|stud-logo\d*|stud2-logo\d*)\.dat$/i;
@@ -5181,11 +5285,11 @@ function collectDeps(lib, refs) {
5181
5285
  return out;
5182
5286
  }
5183
5287
 
5184
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/node/compile.ts
5288
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/node/compile.ts
5185
5289
  import fs2 from "node:fs";
5186
5290
  import path2 from "node:path";
5187
5291
 
5188
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/node/lod.ts
5292
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/node/lod.ts
5189
5293
  import { MeshoptSimplifier, MeshoptEncoder } from "meshoptimizer";
5190
5294
  await Promise.all([MeshoptSimplifier.ready, MeshoptEncoder.ready]);
5191
5295
  function reorderMesh(P, N, C, I) {
@@ -5377,7 +5481,55 @@ function lodChain(P, C, I) {
5377
5481
  return out;
5378
5482
  }
5379
5483
 
5380
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/node/compile.ts
5484
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/node/compile.ts
5485
+ class BfcState {
5486
+ accum;
5487
+ ccw = true;
5488
+ certified = null;
5489
+ local = true;
5490
+ inv = false;
5491
+ constructor(accum = true) {
5492
+ this.accum = accum;
5493
+ }
5494
+ meta(t) {
5495
+ const o = t.split(/\s+/).slice(2);
5496
+ this.inv = false;
5497
+ if (this.certified === null)
5498
+ this.certified = !o.includes("NOCERTIFY");
5499
+ if (!this.certified)
5500
+ return;
5501
+ for (const w of o) {
5502
+ if (w === "CW")
5503
+ this.ccw = false;
5504
+ else if (w === "CCW")
5505
+ this.ccw = true;
5506
+ else if (w === "CLIP")
5507
+ this.local = true;
5508
+ else if (w === "NOCLIP")
5509
+ this.local = false;
5510
+ else if (w === "INVERTNEXT")
5511
+ this.inv = true;
5512
+ }
5513
+ }
5514
+ line(type) {
5515
+ if (type !== "0" && this.certified === null)
5516
+ this.certified = false;
5517
+ if (type !== "1")
5518
+ this.inv = false;
5519
+ }
5520
+ takeInvert() {
5521
+ const v = this.inv;
5522
+ this.inv = false;
5523
+ return v;
5524
+ }
5525
+ get cull() {
5526
+ return this.accum && this.local;
5527
+ }
5528
+ }
5529
+ var windOrder = (n, flip, cull) => {
5530
+ const f = n === 3 ? [0, 1, 2] : [0, 1, 2, 0, 2, 3], b = n === 3 ? [0, 2, 1] : [0, 2, 1, 0, 3, 2];
5531
+ return cull ? flip ? b : f : [...f, ...b];
5532
+ };
5381
5533
  function loadColors(root) {
5382
5534
  const map = new Map;
5383
5535
  for (const l of fs2.readFileSync(path2.join(root, "LDConfig.ldr"), "latin1").split(/\r?\n/)) {
@@ -5447,54 +5599,48 @@ class Compiler {
5447
5599
  return this.cache.get(ck);
5448
5600
  const out = { body: { pos: [], col: [] }, under: { pos: [], col: [] }, edges: [], condLines: 0, cond: this.opts.cond ? [] : undefined, condUnder: this.opts.cond ? [] : undefined, studs: [], bbox: [Infinity, Infinity, Infinity, -Infinity, -Infinity, -Infinity], fullBottom: false };
5449
5601
  const colorOf = (code) => code === "16" ? [1, 1, 1, 0] : [...this.colors.get(code) || (code.startsWith("0x2") ? [parseInt(code.slice(3, 5), 16) / 255, parseInt(code.slice(5, 7), 16) / 255, parseInt(code.slice(7, 9), 16) / 255] : blendedRgb(code) ?? [1, 0, 1]), 1];
5450
- const walk = (fk, M, color, invert, target, depth, inh = null, scope0 = null) => {
5602
+ const walk = (fk, M, color, invert, target, depth, inh = null, scope0 = null, cull = true) => {
5451
5603
  if (depth > 40)
5452
5604
  return;
5453
- let ccw = true, certified = false, invertNext = false, scope = scope0;
5605
+ const bfc = new BfcState(cull);
5606
+ let scope = scope0;
5454
5607
  for (const raw of this.lib.read(fk).split(/\r?\n/)) {
5455
5608
  const t = raw.trim();
5456
5609
  if (!t)
5457
5610
  continue;
5458
5611
  const c = t[0];
5612
+ if (c === "0" && /^0\s+BFC(\s|$)/.test(t)) {
5613
+ bfc.meta(t);
5614
+ continue;
5615
+ }
5616
+ bfc.line(c);
5459
5617
  if (c === "0") {
5460
5618
  if (t.includes("!COLOUR") && COLOUR_RE.test(t)) {
5461
5619
  scope = defineColour(t, scope);
5462
5620
  continue;
5463
5621
  }
5464
- if (/^0\s+BFC/.test(t)) {
5465
- if (/CERTIFY/.test(t) && !/NOCERTIFY/.test(t))
5466
- certified = true;
5467
- if (/\bCW\b/.test(t))
5468
- ccw = false;
5469
- if (/\bCCW\b/.test(t))
5470
- ccw = true;
5471
- if (/INVERTNEXT/.test(t))
5472
- invertNext = true;
5473
- }
5474
5622
  continue;
5475
5623
  }
5476
5624
  if (c === "1") {
5625
+ const invertNext = bfc.takeInvert();
5477
5626
  const r = parseType1(t);
5478
5627
  if (!r)
5479
5628
  continue;
5480
5629
  const base = r.name.trim().replace(/\\/g, "/").split("/").pop().toLowerCase();
5481
5630
  const isTop = TOP_STUD_RE.test(base), isUnder = UNDER_STUD_RE.test(base);
5482
5631
  const ck2 = this.resolve(r.name, isTop);
5483
- if (!ck2) {
5484
- invertNext = false;
5632
+ if (!ck2)
5485
5633
  continue;
5486
- }
5487
5634
  const childColor = r.color === "16" ? color : r.color, childInh = r.color === "16" ? inh : this.local(r.color, scope);
5488
5635
  const Mc = compose(M, r.m);
5489
5636
  const inv = invert !== invertNext !== det3(r.m) < 0;
5490
- invertNext = false;
5491
5637
  if (isTop && separateStuds) {
5492
5638
  out.studs.push({ kind: ck2, color: childInh ? this.studToken(childColor, childInh) : childColor, m: Mc });
5493
5639
  fullKind.set(out.studs.length - 1, this.lib.resolve(r.name));
5494
5640
  growBox(out.bbox, Mc, this.compile(ck2, false).bbox);
5495
5641
  continue;
5496
5642
  }
5497
- walk(ck2, Mc, childColor, inv, isUnder ? "under" : target, depth + 1, childInh, scope);
5643
+ walk(ck2, Mc, childColor, inv, isUnder ? "under" : target, depth + 1, childInh, scope, bfc.cull);
5498
5644
  continue;
5499
5645
  }
5500
5646
  const tok = t.split(/\s+/);
@@ -5522,22 +5668,40 @@ class Compiler {
5522
5668
  pts.push(xf2(M, v.slice(i * 3, i * 3 + 3)));
5523
5669
  for (const p of pts)
5524
5670
  grow(out.bbox, p);
5525
- let order = n === 3 ? [0, 1, 2] : [0, 1, 2, 0, 2, 3];
5526
- if (!ccw !== invert)
5527
- order = n === 3 ? [0, 2, 1] : [0, 2, 1, 0, 3, 2];
5528
- const rgba = this.rgbaAt(tok[1], color, inh, scope, colorOf);
5529
- const b = out[target];
5530
- for (const i of order) {
5671
+ const flip = !bfc.ccw !== invert, rgba = this.rgbaAt(tok[1], color, inh, scope, colorOf), b = out[target];
5672
+ for (const i of windOrder(n, flip, true)) {
5531
5673
  b.pos.push(...pts[i]);
5532
5674
  b.col.push(...rgba);
5533
5675
  }
5676
+ if (bfc.cull)
5677
+ culled++;
5678
+ else {
5679
+ const bb = back[target];
5680
+ for (const i of windOrder(n, !flip, true)) {
5681
+ bb.pos.push(...pts[i]);
5682
+ bb.col.push(...rgba);
5683
+ }
5684
+ }
5534
5685
  }
5535
5686
  }
5536
- if (!certified)
5687
+ if (!bfc.certified)
5537
5688
  out.uncertified = true;
5538
5689
  };
5539
5690
  const fullKind = new Map;
5691
+ let culled = 0;
5692
+ const back = { body: { pos: [], col: [] }, under: { pos: [], col: [] } };
5540
5693
  walk(key, IDENT, "16", false, "body", 0);
5694
+ if (back.body.pos.length || back.under.pos.length) {
5695
+ if (!culled)
5696
+ out.uncertified = true;
5697
+ if (!out.uncertified)
5698
+ for (const t of ["body", "under"]) {
5699
+ for (const x of back[t].pos)
5700
+ out[t].pos.push(x);
5701
+ for (const x of back[t].col)
5702
+ out[t].col.push(x);
5703
+ }
5704
+ }
5541
5705
  seatStuds(out, fullKind, (k) => this.compile(k, false).bbox);
5542
5706
  if (this.opts.tex && this.hasTex(key))
5543
5707
  this.texPass(key, out, separateStuds, colorOf);
@@ -5622,10 +5786,11 @@ class Compiler {
5622
5786
  }
5623
5787
  texPass(key, out, separateStuds, colorOf) {
5624
5788
  const tbody = { pos: [], col: [] }, texb = new Map;
5625
- const walk = (fk, M, color, invert, target, depth, texIn, inh = null, scope0 = null) => {
5789
+ const walk = (fk, M, color, invert, target, depth, texIn, inh = null, scope0 = null, cull = true) => {
5626
5790
  if (depth > 40)
5627
5791
  return;
5628
- let ccw = true, invertNext = false, scope = scope0;
5792
+ const bfc = new BfcState(cull);
5793
+ let scope = scope0;
5629
5794
  let stack = [];
5630
5795
  let next = null;
5631
5796
  for (const raw of this.lib.read(fk).split(/\r?\n/)) {
@@ -5636,7 +5801,13 @@ class Compiler {
5636
5801
  if (t[0] === "0") {
5637
5802
  const m = /^0\s+(\S+)\s*(.*)$/.exec(t);
5638
5803
  const kw = (m?.[1] ?? "").toUpperCase(), rest = m?.[2] ?? "";
5804
+ if (m?.[1] === "BFC") {
5805
+ bfc.meta(t);
5806
+ next = null;
5807
+ continue;
5808
+ }
5639
5809
  if (kw === "!TEXMAP") {
5810
+ bfc.line("0");
5640
5811
  const op = (rest.split(/\s+/)[0] || "").toUpperCase();
5641
5812
  next = null;
5642
5813
  if (op === "START" || op === "NEXT") {
@@ -5660,25 +5831,23 @@ class Compiler {
5660
5831
  next = null;
5661
5832
  t = rest.trim();
5662
5833
  colon = true;
5663
- if (!t || t[0] === "0")
5834
+ if (!t || t[0] === "0") {
5835
+ bfc.line("0");
5664
5836
  continue;
5837
+ }
5665
5838
  } else {
5839
+ bfc.line("0");
5666
5840
  if (kw === "!COLOUR")
5667
5841
  scope = defineColour(t, scope);
5668
- if (kw === "BFC") {
5669
- if (/\bCW\b/.test(t))
5670
- ccw = false;
5671
- if (/\bCCW\b/.test(t))
5672
- ccw = true;
5673
- if (/INVERTNEXT/.test(t))
5674
- invertNext = true;
5675
- }
5676
5842
  if (kw === "STEP")
5677
5843
  stack = [];
5678
5844
  next = null;
5679
5845
  continue;
5680
5846
  }
5681
5847
  }
5848
+ const c = t[0];
5849
+ bfc.line(c);
5850
+ const invertNext = c === "1" && bfc.takeInvert();
5682
5851
  let tex = texIn;
5683
5852
  if (next) {
5684
5853
  tex = next;
@@ -5693,7 +5862,6 @@ class Compiler {
5693
5862
  tex = top.map;
5694
5863
  }
5695
5864
  }
5696
- const c = t[0];
5697
5865
  if (c === "1") {
5698
5866
  const r = parseType1(t);
5699
5867
  if (!r)
@@ -5701,15 +5869,12 @@ class Compiler {
5701
5869
  const base = r.name.trim().replace(/\\/g, "/").split("/").pop().toLowerCase();
5702
5870
  const isTop = TOP_STUD_RE.test(base), isUnder = UNDER_STUD_RE.test(base);
5703
5871
  const ck2 = this.resolve(r.name, isTop);
5704
- if (!ck2) {
5705
- invertNext = false;
5872
+ if (!ck2)
5706
5873
  continue;
5707
- }
5708
5874
  const inv = invert !== invertNext !== det3(r.m) < 0;
5709
- invertNext = false;
5710
5875
  if (isTop && separateStuds)
5711
5876
  continue;
5712
- walk(ck2, compose(M, r.m), r.color === "16" ? color : r.color, inv, isUnder ? "under" : target, depth + 1, tex, r.color === "16" ? inh : this.local(r.color, scope), scope);
5877
+ walk(ck2, compose(M, r.m), r.color === "16" ? color : r.color, inv, isUnder ? "under" : target, depth + 1, tex, r.color === "16" ? inh : this.local(r.color, scope), scope, bfc.cull);
5713
5878
  continue;
5714
5879
  }
5715
5880
  if (c !== "3" && c !== "4")
@@ -5720,9 +5885,7 @@ class Compiler {
5720
5885
  const pts = [];
5721
5886
  for (let i = 0;i < n; i++)
5722
5887
  pts.push(xf2(M, v.slice(i * 3, i * 3 + 3)));
5723
- let order = n === 3 ? [0, 1, 2] : [0, 1, 2, 0, 2, 3];
5724
- if (!ccw !== invert)
5725
- order = n === 3 ? [0, 2, 1] : [0, 2, 1, 0, 3, 2];
5888
+ const order = windOrder(n, !bfc.ccw !== invert, bfc.cull || !!out.uncertified);
5726
5889
  const rgba = this.rgbaAt(tok[1], color, inh, scope, colorOf);
5727
5890
  if (tex) {
5728
5891
  const tk = tex.glossmap ? tex.texture + "\x00" + tex.glossmap : tex.texture;
@@ -6092,7 +6255,7 @@ function encodePack(parts, studKinds, weld, extra, options = {}) {
6092
6255
  return Buffer.concat([head, ...chunks.map((c) => new Uint8Array(c.buffer, c.byteOffset, c.byteLength))]);
6093
6256
  }
6094
6257
 
6095
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/node/build-pack.ts
6258
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/node/build-pack.ts
6096
6259
  function packCompilerOpts(o) {
6097
6260
  return { studs: o.studs ?? "low", prims: o.primitives ?? "full", weld: o.weld ?? true, separateStuds: true, cond: !!o.cond, tex: !!o.textures };
6098
6261
  }
@@ -6164,7 +6327,7 @@ function buildPack(o) {
6164
6327
  const warnings = [...lib.conflicts].map((n) => `${n}: defined differently by two models; the first definition is used`);
6165
6328
  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 } : {} };
6166
6329
  }
6167
- // ../../../../../../../tmp/ldr-build-MGO8Dx/src/node/promote.ts
6330
+ // ../../../../../../../tmp/ldr-build-78cdvu/src/node/promote.ts
6168
6331
  var GEOM = /^\s*[2-5]\s/;
6169
6332
  var REF = /^\s*1\s/;
6170
6333
  var FILE = /^\s*0\s+FILE\s+(.+?)\s*$/i;