ldr 0.33.10 → 0.33.12
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 -2
- package/dist/cli.js +11 -11
- package/dist/cull.d.ts +11 -7
- package/dist/index.js +153 -88
- package/dist/load-worker.gen.d.ts +1 -1
- package/dist/node/index.js +161 -96
- package/dist/render.d.ts +4 -1
- package/dist/scene.d.ts +3 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -143,6 +143,7 @@ MPD-embedded parts, such as Studio/OMR unofficial parts or stickers, become part
|
|
|
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. |
|
|
146
|
+
| `lodEdgeCap` | `0.75` | LOD: a part draws at most `lodEdgeCap` × d² of its edge segments (its longest), d = its size on screen in pixels. `0` = no cap. |
|
|
146
147
|
| `lodUnder` | `true` | LOD: skip undersides that can't be seen (camera behind every bottom face of a cluster's parts, or the body drawn as its closed bounding box). Lossless in the fidelity checks. |
|
|
147
148
|
|
|
148
149
|
`LdrObject`: `object`, `stats` (`instances`, `drawn`, `missing[]`, `studsHidden/Total`, `undersHidden/Total`, `buildMs`, `condBatches`, `texBatches`, `textures`, `glossmaps`, `clusters`), `stepCount`, `stepViews`, `texturesReady`, `setStep(n | null)`, `setEdges(on)`, `setConditionalLines(on)`, `setCulling(studs, undersides)`, `setSide(side)`, `setLod(on)`, `setGhost(on, { opacity, color, whiten }?)`, `getBox(target?)`, `dispose()`.
|
|
@@ -201,7 +202,7 @@ How much each optimization contributed on Datsville 100k (Rounds 1–20, before
|
|
|
201
202
|
- Full Datsville: **1.7 → 9.9 fps**.
|
|
202
203
|
- Datsville 100k: **8 → 43.5 fps**.
|
|
203
204
|
- **Conditional lines** (opt-in `cond` packs) cost **+12–14 %** frame time on Datsville 10k and 100k (M4 Pro, before Round 60), and add 7–14 % to the zstd pack size.
|
|
204
|
-
- **Edges:** with LOD, edges take the Falcon fleet from 9.8 → 12.9 ms (19 ships) and 18.3 → 22.9 ms (75 ships) on the Mac Mini M6 (Round 67); before Round 62 they cost 12.8 → 33.3 and 19.3 → 45.1 ms there. A simplified level draws its own outline: square studs a square per stud loop (8 segments instead of 16-32), bodies at their bounding-box level the box's 12 edges, and a line batch whose edge LOD leaves no segment issues no draw. Each cluster draws only edge segments at least 0.4 px long on screen (`lodEdgeMinPx`; 0.15 px until Round 62, when 85% of the segments drawn at the fleet overview were 0.15–0.5 px long and each darkened a whole pixel, so far ships looked charcoal) and none where bricks are sub-pixel (`lodEdgePx`). Far views drawn with edges get lighter: 2.6% of pixels differ from every-edge rendering on the 19-ship overview, 0.8% on the SF city, up to 4.7% on Datsville overviews. `lodEdgeMinPx: 0, lodEdgePx: 0` keeps every edge.
|
|
205
|
+
- **Edges:** with LOD, edges take the Falcon fleet from 9.8 → 12.9 ms (19 ships) and 18.3 → 22.9 ms (75 ships) on the Mac Mini M6 (Round 67); before Round 62 they cost 12.8 → 33.3 and 19.3 → 45.1 ms there. A simplified level draws its own outline: square studs a square per stud loop (8 segments instead of 16-32), bodies at their bounding-box level the box's 12 edges, and a line batch whose edge LOD leaves no segment issues no draw. Each cluster draws only edge segments at least 0.4 px long on screen (`lodEdgeMinPx`; 0.15 px until Round 62, when 85% of the segments drawn at the fleet overview were 0.15–0.5 px long and each darkened a whole pixel, so far ships looked charcoal) and none where bricks are sub-pixel (`lodEdgePx`). A part also draws at most 0.75 × d² of its segments, its longest, d = its size in pixels (`lodEdgeCap`, Round 72), so a 6 px technic beam no longer draws ~100 segments into ~20 pixels. Far views drawn with edges get lighter: 2.6% of pixels differ from every-edge rendering on the 19-ship overview, 0.8% on the SF city, up to 4.7% on Datsville overviews. `lodEdgeMinPx: 0, lodEdgePx: 0, lodEdgeCap: 0` keeps every edge.
|
|
205
206
|
- **Build steps:** `setStep` takes 39 ms on the 19-ship fleet (26,619 steps); on Datsville 100k it went from a full rebuild (752 ms) to 66 ms.
|
|
206
207
|
- **Visual fidelity:** pixel diffs show culling and single-sided faces are lossless (≤ 0.009 % of pixels differ). Low-detail studs only change stud silhouettes.
|
|
207
208
|
|
|
@@ -228,7 +229,7 @@ Reproduce: `cd bench && bun run setup && bun run perf` (regression gate) or `bun
|
|
|
228
229
|
- **ROTSTEP** is reported (`stepViews`, `instance.view`), not applied; `planStepViews` takes a `fixed(step)` override if you want to honour it.
|
|
229
230
|
- **Packs are static:** they hold only the parts they were built for. A model that uses parts missing from the pack lists them in `stats.missing`.
|
|
230
231
|
- **Occlusion culling:** beyond hidden studs and undersides there is no occlusion culling (bricks enclosed by other bricks are still drawn). Frustum culling and LOD apply per spatial cluster.
|
|
231
|
-
- **LOD and edges:** edge LOD drops sub-pixel edge segments and hides edges where bricks are a fraction of a pixel, which visibly lightens far-away views drawn with edges (2.6% of pixels on the 19-ship Falcon overview, up to 4.7% on Datsville overviews). Set `lodEdgeMinPx: 0, lodEdgePx: 0` to keep every edge (much slower on large models), or `lod: false` to turn LOD off entirely.
|
|
232
|
+
- **LOD and edges:** edge LOD drops sub-pixel edge segments and hides edges where bricks are a fraction of a pixel, which visibly lightens far-away views drawn with edges (2.6% of pixels on the 19-ship Falcon overview, up to 4.7% on Datsville overviews). Set `lodEdgeMinPx: 0, lodEdgePx: 0, lodEdgeCap: 0` to keep every edge (much slower on large models), or `lod: false` to turn LOD off entirely.
|
|
232
233
|
|
|
233
234
|
## Attribution and license
|
|
234
235
|
|
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-HYKc29/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-HYKc29/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-HYKc29/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-HYKc29/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;
|
|
@@ -817,7 +817,7 @@ function fileStepViews(f) {
|
|
|
817
817
|
return out;
|
|
818
818
|
}
|
|
819
819
|
|
|
820
|
-
// ../../../../../../../tmp/ldr-build-
|
|
820
|
+
// ../../../../../../../tmp/ldr-build-HYKc29/src/model.ts
|
|
821
821
|
class ModelLimitError extends Error {
|
|
822
822
|
limit;
|
|
823
823
|
code = "ldr-model-limit";
|
|
@@ -1259,7 +1259,7 @@ function blendedColourHex(code) {
|
|
|
1259
1259
|
return "#" + [0, 1, 2].map((k) => (a[k] + b[k] >> 1).toString(16).padStart(2, "0")).join("").toUpperCase();
|
|
1260
1260
|
}
|
|
1261
1261
|
|
|
1262
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1262
|
+
// ../../../../../../../tmp/ldr-build-HYKc29/src/node/resolver.ts
|
|
1263
1263
|
var TOP_STUD_RE = /^(stud|studa|stud2|stud2a|stud6|stud6a|stud10|stud15|stud2s|stud2s2|stud-logo\d*|stud2-logo\d*)\.dat$/i;
|
|
1264
1264
|
var UNDER_STUD_RE = /^(stud3|stud3a|stud4.*|stud12|stud16.*|stud18a)\.dat$/i;
|
|
1265
1265
|
var norm2 = (ref) => ref.trim().replace(/\\/g, "/").toLowerCase();
|
|
@@ -1586,11 +1586,11 @@ function collectDeps(lib, refs) {
|
|
|
1586
1586
|
return out;
|
|
1587
1587
|
}
|
|
1588
1588
|
|
|
1589
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1589
|
+
// ../../../../../../../tmp/ldr-build-HYKc29/src/node/compile.ts
|
|
1590
1590
|
import fs2 from "node:fs";
|
|
1591
1591
|
import path2 from "node:path";
|
|
1592
1592
|
|
|
1593
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1593
|
+
// ../../../../../../../tmp/ldr-build-HYKc29/src/node/lod.ts
|
|
1594
1594
|
import { MeshoptSimplifier, MeshoptEncoder } from "meshoptimizer";
|
|
1595
1595
|
await Promise.all([MeshoptSimplifier.ready, MeshoptEncoder.ready]);
|
|
1596
1596
|
function reorderMesh(P, N, C, I) {
|
|
@@ -1896,7 +1896,7 @@ function levelLines(P, I, E, err, always, tol = 0.01) {
|
|
|
1896
1896
|
return out;
|
|
1897
1897
|
}
|
|
1898
1898
|
|
|
1899
|
-
// ../../../../../../../tmp/ldr-build-
|
|
1899
|
+
// ../../../../../../../tmp/ldr-build-HYKc29/src/node/compile.ts
|
|
1900
1900
|
class BfcState {
|
|
1901
1901
|
accum;
|
|
1902
1902
|
ccw = true;
|
|
@@ -2840,7 +2840,7 @@ function encodePack(parts, studKinds, weld, extra, options = {}) {
|
|
|
2840
2840
|
return Buffer.concat([head, ...chunks.map((c) => new Uint8Array(c.buffer, c.byteOffset, c.byteLength))]);
|
|
2841
2841
|
}
|
|
2842
2842
|
|
|
2843
|
-
// ../../../../../../../tmp/ldr-build-
|
|
2843
|
+
// ../../../../../../../tmp/ldr-build-HYKc29/src/node/build-pack.ts
|
|
2844
2844
|
function packCompilerOpts(o) {
|
|
2845
2845
|
return { studs: o.studs ?? "low", prims: o.primitives ?? "full", weld: o.weld ?? true, separateStuds: true, cond: !!o.cond, tex: !!o.textures, ...o.partWorkLimit ? { workLimit: o.partWorkLimit } : {} };
|
|
2846
2846
|
}
|
|
@@ -2913,7 +2913,7 @@ function buildPack(o) {
|
|
|
2913
2913
|
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 } : {} };
|
|
2914
2914
|
}
|
|
2915
2915
|
|
|
2916
|
-
// ../../../../../../../tmp/ldr-build-
|
|
2916
|
+
// ../../../../../../../tmp/ldr-build-HYKc29/src/cli.ts
|
|
2917
2917
|
var HELP = `ldr pack — build a parts pack for the ldr three.js renderer
|
|
2918
2918
|
|
|
2919
2919
|
Usage:
|
package/dist/cull.d.ts
CHANGED
|
@@ -21,17 +21,21 @@ export declare function mul12To(a: ArrayLike<number>, b: ArrayLike<number>, bo:
|
|
|
21
21
|
export declare const det12: (m: ArrayLike<number>) => number;
|
|
22
22
|
/** Singular placement (determinant ~0, relative to the row lengths): BFC can't cull it (article 415 "Degenerate Matrices"). */
|
|
23
23
|
export declare const singular12: (m: ArrayLike<number>, d?: number) => boolean;
|
|
24
|
-
/** Open-addressing hash table from int32 triples to int32 values (-1 = absent); grows as needed.
|
|
24
|
+
/** Open-addressing hash table from int32 triples to int32 values (-1 = absent); grows as needed. Keys and value sit interleaved in one
|
|
25
|
+
* Int32Array (x, y, z, value), and a byte per slot holds 8 more bits of the key's hash (0 = empty), so a miss usually reads only the
|
|
26
|
+
* byte array and a hit one cache line of the keys, where five parallel arrays cost five. With `shift` >= 0, keys close in x / z (a
|
|
27
|
+
* 4 x 4 block of (1 << shift)-unit squares) start in neighbouring slots, so the studs of one brick, or the cells under it, share cache
|
|
28
|
+
* lines. The stud-top table of a 400k-brick city has millions of entries and its lookups were the culling pass's biggest cost
|
|
29
|
+
* (Round 73). */
|
|
25
30
|
export declare class Int3Table {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
c: Int32Array;
|
|
29
|
-
vals: Int32Array;
|
|
30
|
-
used: Uint8Array;
|
|
31
|
+
t: Int32Array;
|
|
32
|
+
tag: Uint8Array;
|
|
31
33
|
mask: number;
|
|
32
34
|
size: number;
|
|
33
|
-
|
|
35
|
+
shift: number;
|
|
36
|
+
constructor(cap?: number, shift?: number);
|
|
34
37
|
private slot;
|
|
38
|
+
private static tagOf;
|
|
35
39
|
get(x: number, y: number, z: number): number;
|
|
36
40
|
/** Sets (x, y, z) -> v and returns the previous value (-1 if none). */
|
|
37
41
|
put(x: number, y: number, z: number, v: number): number;
|