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.
- package/README.md +3 -3
- package/dist/cli.js +114 -55
- package/dist/index.js +106 -15
- package/dist/node/compile.d.ts +21 -0
- package/dist/node/index.js +251 -88
- package/dist/render.d.ts +1 -1
- package/dist/scene.d.ts +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -139,7 +139,7 @@ MPD-embedded parts, such as Studio/OMR unofficial parts or stickers, become part
|
|
|
139
139
|
| `ldrawSpace` | `false` | `true` keeps native LDraw space (-Y up). |
|
|
140
140
|
| `scale` | `1` | Uniform scale (1 = 1 LDU; 1 stud = 20 LDU). |
|
|
141
141
|
| `step` | all | Initial build step (inclusive, 0-based). |
|
|
142
|
-
| `lod` | `true` | Distance LOD, re-selected for each camera you render with. Batches are split into spatial clusters (off-screen ones are frustum-culled). Each cluster draws the coarsest simplified mesh (from `lod` packs) whose error stays under `lodPx`,
|
|
142
|
+
| `lod` | `true` | Distance LOD, re-selected for each camera you render with. Batches are split into spatial clusters (off-screen ones are frustum-culled). Each cluster draws the coarsest simplified mesh (from `lod` packs) whose error stays under `lodPx`, swaps closed studs to a 10-triangle square stud then a flat disc, and drops them once their 12-LDU disc is under `lodPx`, and hides edges where a stud spans less than `lodEdgePx`. |
|
|
143
143
|
| `lodPx` | `0.5` | LOD: maximum screen-space error in pixels. |
|
|
144
144
|
| `lodEdgePx` | `0.5` | LOD: draw edge and conditional lines only where one stud (20 LDU) spans at least this many pixels. `0` = always. |
|
|
145
145
|
| `lodEdgeMinPx` | `0.4` | LOD: draw only edge segments at least this many pixels long on screen. `0` = every segment. |
|
|
@@ -190,7 +190,7 @@ Sources: `bench/results/2026-10-18T18-10-46-518Z-falcon-vs-stock.md` (the Falcon
|
|
|
190
190
|
| Millennium Falcon ×19 | 100,054 | 54.2 ms | **19.6 ms** | 2.04 s | **0.38 s** |
|
|
191
191
|
| Millennium Falcon ×75 | 394,950 | 204.7 ms | **29.2 ms** | 2.40 s | **1.03 s** |
|
|
192
192
|
|
|
193
|
-
The benchmark model is a fleet: the LDraw OMR model of set 10179 (UCS Millennium Falcon, 5,266 parts, 251 unique) placed 2, 19 or 75 times on a grid (`apps/demo-site/scripts/build-fleet.ts`). It is a hard case for ldr: dense, detailed ships stay large on screen, so distance LOD can't drop much and the overview still draws ~
|
|
193
|
+
The benchmark model is a fleet: the LDraw OMR model of set 10179 (UCS Millennium Falcon, 5,266 parts, 251 unique) placed 2, 19 or 75 times on a grid (`apps/demo-site/scripts/build-fleet.ts`). It is a hard case for ldr: dense, detailed ships stay large on screen, so distance LOD can't drop much and the overview still draws ~22M triangles (32M before Round 62's cluster-box distances, 27M before Round 63's square-stud mid LOD); on two ships ldr only matches stock instancing per frame (it still loads 14× faster). Datsville, the benchmark until Round 60 (a flat town, 392,514 bricks, mostly baseplates), went from 409.6 to 12.5 ms per frame and 24.7 to 1.6 s load.
|
|
194
194
|
|
|
195
195
|
How much each optimization contributed on Datsville 100k (Rounds 1–20, before the Falcon fleets), in ms per frame: welding 108.1 → 64.6, stud culling → 50.8, underside culling → 41.7, low-detail studs → 31.0, single-sided faces → 30.1. Triangles per frame drop from 142.7M to 59.1M. Distance LOD (Rounds 19–20: simplified and bounding-box levels with a silhouette-coverage error, sub-pixel studs dropped, undersides skipped where they can't be seen) then takes it to 4.4 ms and 4.0M triangles; ≤ 1.5% of pixels differ from full detail (mostly sub-pixel stud moiré).
|
|
196
196
|
|
|
@@ -209,7 +209,7 @@ Reproduce: `cd bench && bun run setup && bun run perf` (regression gate) or `bun
|
|
|
209
209
|
|
|
210
210
|
## LDraw spec compliance
|
|
211
211
|
|
|
212
|
-
- Line types 0–5. BFC: `CERTIFY
|
|
212
|
+
- Line types 0–5. BFC (ldraw.org article 415): `CERTIFY`/`NOCERTIFY` (decided by the first BFC statement before the file's first type 1-5 line, so `0 BFC CCW` alone certifies and a late `CERTIFY` doesn't), `CCW`/`CW`, `CLIP`/`NOCLIP` (polygons drawn while culling is off are visible from both sides, including in subfiles referenced then, which can't turn it back on), `INVERTNEXT` (the immediately following subfile reference only), inverted matrices.
|
|
213
213
|
- MPD: `0 FILE` / `0 NOFILE`, and `0 !DATA` (base64 PNGs). An MPD file is a part or a model by its `!LDRAW_ORG` type, otherwise by whether it has its own geometry. Embedded parts override library parts.
|
|
214
214
|
- Geometry drawn directly in model files (type 2–5 lines outside parts), on by default.
|
|
215
215
|
- `0 STEP`, nested submodel step sequencing, `0 ROTSTEP` (`REL`/`ADD`/`ABS`/`END`), and `0 BUFEXCHG`.
|
package/dist/cli.js
CHANGED
|
@@ -1,18 +1,18 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
// ../../../../../../../tmp/ldr-build-
|
|
3
|
+
// ../../../../../../../tmp/ldr-build-78cdvu/src/cli.ts
|
|
4
4
|
import fs4 from "node:fs";
|
|
5
5
|
import zlib from "node:zlib";
|
|
6
6
|
|
|
7
|
-
// ../../../../../../../tmp/ldr-build-
|
|
7
|
+
// ../../../../../../../tmp/ldr-build-78cdvu/src/node/build-pack.ts
|
|
8
8
|
import fs3 from "node:fs";
|
|
9
9
|
import path3 from "node:path";
|
|
10
10
|
|
|
11
|
-
// ../../../../../../../tmp/ldr-build-
|
|
11
|
+
// ../../../../../../../tmp/ldr-build-78cdvu/src/node/resolver.ts
|
|
12
12
|
import fs from "node:fs";
|
|
13
13
|
import path from "node:path";
|
|
14
14
|
|
|
15
|
-
// ../../../../../../../tmp/ldr-build-
|
|
15
|
+
// ../../../../../../../tmp/ldr-build-78cdvu/src/spec.ts
|
|
16
16
|
var norm = (s) => s.trim().toLowerCase().replace(/\\/g, "/").replace(/\/+/g, "/");
|
|
17
17
|
var COLOUR_ID_RE = /^[A-Za-z][A-Za-z0-9_]*$/;
|
|
18
18
|
var namedCodes = new Map;
|
|
@@ -723,7 +723,7 @@ function fileStepViews(f) {
|
|
|
723
723
|
return out;
|
|
724
724
|
}
|
|
725
725
|
|
|
726
|
-
// ../../../../../../../tmp/ldr-build-
|
|
726
|
+
// ../../../../../../../tmp/ldr-build-78cdvu/src/model.ts
|
|
727
727
|
var CALLOUT_END = 999999;
|
|
728
728
|
var stepKey = (steps) => steps.map((x) => String(x).padStart(6, "0")).join(".") + "~";
|
|
729
729
|
var defLine = new WeakMap;
|
|
@@ -1138,7 +1138,7 @@ function blendedColourHex(code) {
|
|
|
1138
1138
|
return "#" + [0, 1, 2].map((k) => (a[k] + b[k] >> 1).toString(16).padStart(2, "0")).join("").toUpperCase();
|
|
1139
1139
|
}
|
|
1140
1140
|
|
|
1141
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1141
|
+
// ../../../../../../../tmp/ldr-build-78cdvu/src/node/resolver.ts
|
|
1142
1142
|
var TOP_STUD_RE = /^(stud|studa|stud2|stud2a|stud6|stud6a|stud10|stud15|stud2s|stud2s2|stud-logo\d*|stud2-logo\d*)\.dat$/i;
|
|
1143
1143
|
var UNDER_STUD_RE = /^(stud3|stud3a|stud4.*|stud12|stud16.*|stud18a)\.dat$/i;
|
|
1144
1144
|
var norm2 = (ref) => ref.trim().replace(/\\/g, "/").toLowerCase();
|
|
@@ -1465,11 +1465,11 @@ function collectDeps(lib, refs) {
|
|
|
1465
1465
|
return out;
|
|
1466
1466
|
}
|
|
1467
1467
|
|
|
1468
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1468
|
+
// ../../../../../../../tmp/ldr-build-78cdvu/src/node/compile.ts
|
|
1469
1469
|
import fs2 from "node:fs";
|
|
1470
1470
|
import path2 from "node:path";
|
|
1471
1471
|
|
|
1472
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1472
|
+
// ../../../../../../../tmp/ldr-build-78cdvu/src/node/lod.ts
|
|
1473
1473
|
import { MeshoptSimplifier, MeshoptEncoder } from "meshoptimizer";
|
|
1474
1474
|
await Promise.all([MeshoptSimplifier.ready, MeshoptEncoder.ready]);
|
|
1475
1475
|
function reorderMesh(P, N, C, I) {
|
|
@@ -1661,7 +1661,55 @@ function lodChain(P, C, I) {
|
|
|
1661
1661
|
return out;
|
|
1662
1662
|
}
|
|
1663
1663
|
|
|
1664
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1664
|
+
// ../../../../../../../tmp/ldr-build-78cdvu/src/node/compile.ts
|
|
1665
|
+
class BfcState {
|
|
1666
|
+
accum;
|
|
1667
|
+
ccw = true;
|
|
1668
|
+
certified = null;
|
|
1669
|
+
local = true;
|
|
1670
|
+
inv = false;
|
|
1671
|
+
constructor(accum = true) {
|
|
1672
|
+
this.accum = accum;
|
|
1673
|
+
}
|
|
1674
|
+
meta(t) {
|
|
1675
|
+
const o = t.split(/\s+/).slice(2);
|
|
1676
|
+
this.inv = false;
|
|
1677
|
+
if (this.certified === null)
|
|
1678
|
+
this.certified = !o.includes("NOCERTIFY");
|
|
1679
|
+
if (!this.certified)
|
|
1680
|
+
return;
|
|
1681
|
+
for (const w of o) {
|
|
1682
|
+
if (w === "CW")
|
|
1683
|
+
this.ccw = false;
|
|
1684
|
+
else if (w === "CCW")
|
|
1685
|
+
this.ccw = true;
|
|
1686
|
+
else if (w === "CLIP")
|
|
1687
|
+
this.local = true;
|
|
1688
|
+
else if (w === "NOCLIP")
|
|
1689
|
+
this.local = false;
|
|
1690
|
+
else if (w === "INVERTNEXT")
|
|
1691
|
+
this.inv = true;
|
|
1692
|
+
}
|
|
1693
|
+
}
|
|
1694
|
+
line(type) {
|
|
1695
|
+
if (type !== "0" && this.certified === null)
|
|
1696
|
+
this.certified = false;
|
|
1697
|
+
if (type !== "1")
|
|
1698
|
+
this.inv = false;
|
|
1699
|
+
}
|
|
1700
|
+
takeInvert() {
|
|
1701
|
+
const v = this.inv;
|
|
1702
|
+
this.inv = false;
|
|
1703
|
+
return v;
|
|
1704
|
+
}
|
|
1705
|
+
get cull() {
|
|
1706
|
+
return this.accum && this.local;
|
|
1707
|
+
}
|
|
1708
|
+
}
|
|
1709
|
+
var windOrder = (n, flip, cull) => {
|
|
1710
|
+
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];
|
|
1711
|
+
return cull ? flip ? b : f : [...f, ...b];
|
|
1712
|
+
};
|
|
1665
1713
|
function loadColors(root) {
|
|
1666
1714
|
const map = new Map;
|
|
1667
1715
|
for (const l of fs2.readFileSync(path2.join(root, "LDConfig.ldr"), "latin1").split(/\r?\n/)) {
|
|
@@ -1731,54 +1779,48 @@ class Compiler {
|
|
|
1731
1779
|
return this.cache.get(ck);
|
|
1732
1780
|
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 };
|
|
1733
1781
|
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];
|
|
1734
|
-
const walk = (fk, M, color, invert, target, depth, inh = null, scope0 = null) => {
|
|
1782
|
+
const walk = (fk, M, color, invert, target, depth, inh = null, scope0 = null, cull = true) => {
|
|
1735
1783
|
if (depth > 40)
|
|
1736
1784
|
return;
|
|
1737
|
-
|
|
1785
|
+
const bfc = new BfcState(cull);
|
|
1786
|
+
let scope = scope0;
|
|
1738
1787
|
for (const raw of this.lib.read(fk).split(/\r?\n/)) {
|
|
1739
1788
|
const t = raw.trim();
|
|
1740
1789
|
if (!t)
|
|
1741
1790
|
continue;
|
|
1742
1791
|
const c = t[0];
|
|
1792
|
+
if (c === "0" && /^0\s+BFC(\s|$)/.test(t)) {
|
|
1793
|
+
bfc.meta(t);
|
|
1794
|
+
continue;
|
|
1795
|
+
}
|
|
1796
|
+
bfc.line(c);
|
|
1743
1797
|
if (c === "0") {
|
|
1744
1798
|
if (t.includes("!COLOUR") && COLOUR_RE.test(t)) {
|
|
1745
1799
|
scope = defineColour(t, scope);
|
|
1746
1800
|
continue;
|
|
1747
1801
|
}
|
|
1748
|
-
if (/^0\s+BFC/.test(t)) {
|
|
1749
|
-
if (/CERTIFY/.test(t) && !/NOCERTIFY/.test(t))
|
|
1750
|
-
certified = true;
|
|
1751
|
-
if (/\bCW\b/.test(t))
|
|
1752
|
-
ccw = false;
|
|
1753
|
-
if (/\bCCW\b/.test(t))
|
|
1754
|
-
ccw = true;
|
|
1755
|
-
if (/INVERTNEXT/.test(t))
|
|
1756
|
-
invertNext = true;
|
|
1757
|
-
}
|
|
1758
1802
|
continue;
|
|
1759
1803
|
}
|
|
1760
1804
|
if (c === "1") {
|
|
1805
|
+
const invertNext = bfc.takeInvert();
|
|
1761
1806
|
const r = parseType1(t);
|
|
1762
1807
|
if (!r)
|
|
1763
1808
|
continue;
|
|
1764
1809
|
const base = r.name.trim().replace(/\\/g, "/").split("/").pop().toLowerCase();
|
|
1765
1810
|
const isTop = TOP_STUD_RE.test(base), isUnder = UNDER_STUD_RE.test(base);
|
|
1766
1811
|
const ck2 = this.resolve(r.name, isTop);
|
|
1767
|
-
if (!ck2)
|
|
1768
|
-
invertNext = false;
|
|
1812
|
+
if (!ck2)
|
|
1769
1813
|
continue;
|
|
1770
|
-
}
|
|
1771
1814
|
const childColor = r.color === "16" ? color : r.color, childInh = r.color === "16" ? inh : this.local(r.color, scope);
|
|
1772
1815
|
const Mc = compose(M, r.m);
|
|
1773
1816
|
const inv = invert !== invertNext !== det3(r.m) < 0;
|
|
1774
|
-
invertNext = false;
|
|
1775
1817
|
if (isTop && separateStuds) {
|
|
1776
1818
|
out.studs.push({ kind: ck2, color: childInh ? this.studToken(childColor, childInh) : childColor, m: Mc });
|
|
1777
1819
|
fullKind.set(out.studs.length - 1, this.lib.resolve(r.name));
|
|
1778
1820
|
growBox(out.bbox, Mc, this.compile(ck2, false).bbox);
|
|
1779
1821
|
continue;
|
|
1780
1822
|
}
|
|
1781
|
-
walk(ck2, Mc, childColor, inv, isUnder ? "under" : target, depth + 1, childInh, scope);
|
|
1823
|
+
walk(ck2, Mc, childColor, inv, isUnder ? "under" : target, depth + 1, childInh, scope, bfc.cull);
|
|
1782
1824
|
continue;
|
|
1783
1825
|
}
|
|
1784
1826
|
const tok = t.split(/\s+/);
|
|
@@ -1806,22 +1848,40 @@ class Compiler {
|
|
|
1806
1848
|
pts.push(xf(M, v.slice(i * 3, i * 3 + 3)));
|
|
1807
1849
|
for (const p of pts)
|
|
1808
1850
|
grow(out.bbox, p);
|
|
1809
|
-
|
|
1810
|
-
|
|
1811
|
-
order = n === 3 ? [0, 2, 1] : [0, 2, 1, 0, 3, 2];
|
|
1812
|
-
const rgba = this.rgbaAt(tok[1], color, inh, scope, colorOf);
|
|
1813
|
-
const b = out[target];
|
|
1814
|
-
for (const i of order) {
|
|
1851
|
+
const flip = !bfc.ccw !== invert, rgba = this.rgbaAt(tok[1], color, inh, scope, colorOf), b = out[target];
|
|
1852
|
+
for (const i of windOrder(n, flip, true)) {
|
|
1815
1853
|
b.pos.push(...pts[i]);
|
|
1816
1854
|
b.col.push(...rgba);
|
|
1817
1855
|
}
|
|
1856
|
+
if (bfc.cull)
|
|
1857
|
+
culled++;
|
|
1858
|
+
else {
|
|
1859
|
+
const bb = back[target];
|
|
1860
|
+
for (const i of windOrder(n, !flip, true)) {
|
|
1861
|
+
bb.pos.push(...pts[i]);
|
|
1862
|
+
bb.col.push(...rgba);
|
|
1863
|
+
}
|
|
1864
|
+
}
|
|
1818
1865
|
}
|
|
1819
1866
|
}
|
|
1820
|
-
if (!certified)
|
|
1867
|
+
if (!bfc.certified)
|
|
1821
1868
|
out.uncertified = true;
|
|
1822
1869
|
};
|
|
1823
1870
|
const fullKind = new Map;
|
|
1871
|
+
let culled = 0;
|
|
1872
|
+
const back = { body: { pos: [], col: [] }, under: { pos: [], col: [] } };
|
|
1824
1873
|
walk(key, IDENT, "16", false, "body", 0);
|
|
1874
|
+
if (back.body.pos.length || back.under.pos.length) {
|
|
1875
|
+
if (!culled)
|
|
1876
|
+
out.uncertified = true;
|
|
1877
|
+
if (!out.uncertified)
|
|
1878
|
+
for (const t of ["body", "under"]) {
|
|
1879
|
+
for (const x of back[t].pos)
|
|
1880
|
+
out[t].pos.push(x);
|
|
1881
|
+
for (const x of back[t].col)
|
|
1882
|
+
out[t].col.push(x);
|
|
1883
|
+
}
|
|
1884
|
+
}
|
|
1825
1885
|
seatStuds(out, fullKind, (k) => this.compile(k, false).bbox);
|
|
1826
1886
|
if (this.opts.tex && this.hasTex(key))
|
|
1827
1887
|
this.texPass(key, out, separateStuds, colorOf);
|
|
@@ -1906,10 +1966,11 @@ class Compiler {
|
|
|
1906
1966
|
}
|
|
1907
1967
|
texPass(key, out, separateStuds, colorOf) {
|
|
1908
1968
|
const tbody = { pos: [], col: [] }, texb = new Map;
|
|
1909
|
-
const walk = (fk, M, color, invert, target, depth, texIn, inh = null, scope0 = null) => {
|
|
1969
|
+
const walk = (fk, M, color, invert, target, depth, texIn, inh = null, scope0 = null, cull = true) => {
|
|
1910
1970
|
if (depth > 40)
|
|
1911
1971
|
return;
|
|
1912
|
-
|
|
1972
|
+
const bfc = new BfcState(cull);
|
|
1973
|
+
let scope = scope0;
|
|
1913
1974
|
let stack = [];
|
|
1914
1975
|
let next = null;
|
|
1915
1976
|
for (const raw of this.lib.read(fk).split(/\r?\n/)) {
|
|
@@ -1920,7 +1981,13 @@ class Compiler {
|
|
|
1920
1981
|
if (t[0] === "0") {
|
|
1921
1982
|
const m = /^0\s+(\S+)\s*(.*)$/.exec(t);
|
|
1922
1983
|
const kw = (m?.[1] ?? "").toUpperCase(), rest = m?.[2] ?? "";
|
|
1984
|
+
if (m?.[1] === "BFC") {
|
|
1985
|
+
bfc.meta(t);
|
|
1986
|
+
next = null;
|
|
1987
|
+
continue;
|
|
1988
|
+
}
|
|
1923
1989
|
if (kw === "!TEXMAP") {
|
|
1990
|
+
bfc.line("0");
|
|
1924
1991
|
const op = (rest.split(/\s+/)[0] || "").toUpperCase();
|
|
1925
1992
|
next = null;
|
|
1926
1993
|
if (op === "START" || op === "NEXT") {
|
|
@@ -1944,25 +2011,23 @@ class Compiler {
|
|
|
1944
2011
|
next = null;
|
|
1945
2012
|
t = rest.trim();
|
|
1946
2013
|
colon = true;
|
|
1947
|
-
if (!t || t[0] === "0")
|
|
2014
|
+
if (!t || t[0] === "0") {
|
|
2015
|
+
bfc.line("0");
|
|
1948
2016
|
continue;
|
|
2017
|
+
}
|
|
1949
2018
|
} else {
|
|
2019
|
+
bfc.line("0");
|
|
1950
2020
|
if (kw === "!COLOUR")
|
|
1951
2021
|
scope = defineColour(t, scope);
|
|
1952
|
-
if (kw === "BFC") {
|
|
1953
|
-
if (/\bCW\b/.test(t))
|
|
1954
|
-
ccw = false;
|
|
1955
|
-
if (/\bCCW\b/.test(t))
|
|
1956
|
-
ccw = true;
|
|
1957
|
-
if (/INVERTNEXT/.test(t))
|
|
1958
|
-
invertNext = true;
|
|
1959
|
-
}
|
|
1960
2022
|
if (kw === "STEP")
|
|
1961
2023
|
stack = [];
|
|
1962
2024
|
next = null;
|
|
1963
2025
|
continue;
|
|
1964
2026
|
}
|
|
1965
2027
|
}
|
|
2028
|
+
const c = t[0];
|
|
2029
|
+
bfc.line(c);
|
|
2030
|
+
const invertNext = c === "1" && bfc.takeInvert();
|
|
1966
2031
|
let tex = texIn;
|
|
1967
2032
|
if (next) {
|
|
1968
2033
|
tex = next;
|
|
@@ -1977,7 +2042,6 @@ class Compiler {
|
|
|
1977
2042
|
tex = top.map;
|
|
1978
2043
|
}
|
|
1979
2044
|
}
|
|
1980
|
-
const c = t[0];
|
|
1981
2045
|
if (c === "1") {
|
|
1982
2046
|
const r = parseType1(t);
|
|
1983
2047
|
if (!r)
|
|
@@ -1985,15 +2049,12 @@ class Compiler {
|
|
|
1985
2049
|
const base = r.name.trim().replace(/\\/g, "/").split("/").pop().toLowerCase();
|
|
1986
2050
|
const isTop = TOP_STUD_RE.test(base), isUnder = UNDER_STUD_RE.test(base);
|
|
1987
2051
|
const ck2 = this.resolve(r.name, isTop);
|
|
1988
|
-
if (!ck2)
|
|
1989
|
-
invertNext = false;
|
|
2052
|
+
if (!ck2)
|
|
1990
2053
|
continue;
|
|
1991
|
-
}
|
|
1992
2054
|
const inv = invert !== invertNext !== det3(r.m) < 0;
|
|
1993
|
-
invertNext = false;
|
|
1994
2055
|
if (isTop && separateStuds)
|
|
1995
2056
|
continue;
|
|
1996
|
-
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);
|
|
2057
|
+
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);
|
|
1997
2058
|
continue;
|
|
1998
2059
|
}
|
|
1999
2060
|
if (c !== "3" && c !== "4")
|
|
@@ -2004,9 +2065,7 @@ class Compiler {
|
|
|
2004
2065
|
const pts = [];
|
|
2005
2066
|
for (let i = 0;i < n; i++)
|
|
2006
2067
|
pts.push(xf(M, v.slice(i * 3, i * 3 + 3)));
|
|
2007
|
-
|
|
2008
|
-
if (!ccw !== invert)
|
|
2009
|
-
order = n === 3 ? [0, 2, 1] : [0, 2, 1, 0, 3, 2];
|
|
2068
|
+
const order = windOrder(n, !bfc.ccw !== invert, bfc.cull || !!out.uncertified);
|
|
2010
2069
|
const rgba = this.rgbaAt(tok[1], color, inh, scope, colorOf);
|
|
2011
2070
|
if (tex) {
|
|
2012
2071
|
const tk = tex.glossmap ? tex.texture + "\x00" + tex.glossmap : tex.texture;
|
|
@@ -2376,7 +2435,7 @@ function encodePack(parts, studKinds, weld, extra, options = {}) {
|
|
|
2376
2435
|
return Buffer.concat([head, ...chunks.map((c) => new Uint8Array(c.buffer, c.byteOffset, c.byteLength))]);
|
|
2377
2436
|
}
|
|
2378
2437
|
|
|
2379
|
-
// ../../../../../../../tmp/ldr-build-
|
|
2438
|
+
// ../../../../../../../tmp/ldr-build-78cdvu/src/node/build-pack.ts
|
|
2380
2439
|
function packCompilerOpts(o) {
|
|
2381
2440
|
return { studs: o.studs ?? "low", prims: o.primitives ?? "full", weld: o.weld ?? true, separateStuds: true, cond: !!o.cond, tex: !!o.textures };
|
|
2382
2441
|
}
|
|
@@ -2449,7 +2508,7 @@ function buildPack(o) {
|
|
|
2449
2508
|
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 } : {} };
|
|
2450
2509
|
}
|
|
2451
2510
|
|
|
2452
|
-
// ../../../../../../../tmp/ldr-build-
|
|
2511
|
+
// ../../../../../../../tmp/ldr-build-78cdvu/src/cli.ts
|
|
2453
2512
|
var HELP = `ldr pack — build a parts pack for the ldr three.js renderer
|
|
2454
2513
|
|
|
2455
2514
|
Usage:
|