ldr 0.33.15 → 0.34.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/NOTICE.md ADDED
@@ -0,0 +1,21 @@
1
+ # Notices and third-party attribution
2
+
3
+ `ldr` source code is MIT-licensed (see [LICENSE](LICENSE)). This repository and the artifacts it builds also include or fetch
4
+ third-party material under its own terms:
5
+
6
+ | Material | Where | License / terms | What we do |
7
+ |---|---|---|---|
8
+ | **LDraw.org Parts Library** | Small frozen subsets committed as test fixtures (`packages/ldr/test/fixtures/ldraw-mini`, `packages/ldr-eval/test/fixtures/ldraw-mini`, a few files in `packages/ldr/test/fixtures`). The full library is **not** committed; it is downloaded from <https://library.ldraw.org/library/updates/complete.zip> by CI and by developers (`LDRAW_DIR`). Parts packs / the demo parts CDN contain geometry compiled from it. | CC BY 2.0 (older files, "Redistributable under CCAL version 2.0") / CC BY 4.0 (newer files); each file keeps its `0 !LICENSE` and `0 Author:` header lines. See <https://www.ldraw.org/legal-info>. | Credit: "LDraw.org Parts Library (CC BY 2.0 / CC BY 4.0)". Apps that ship packs should carry the same credit. |
9
+ | **LDraw Official Model Repository (OMR)** | `models/sources/omr.json` and `models/catalog.json` hold metadata only (set number, name, author, license, source URL). Model files are **not** committed; the demo build downloads them from LDraw.org. | CC BY 2.0 / CC BY 4.0 per file; author named per model. | Author, license and source are shown wherever a model is shown. |
10
+ | **Rebrickable** set and inventory data | Fetched at build time by the demo / MCP server (not committed). | Rebrickable's downloads page permits use of the CSV files for any purpose; credit Rebrickable. | Credited in the demo and MCP output. |
11
+ | **OpenStreetMap / OpenFreeMap / OpenMapTiles / Overture Maps** | City mode fetches data at runtime (not committed). | ODbL 1.0 (OSM, Overture buildings); OpenMapTiles schema attribution. | Attribution embedded in generated models and shown in the demo. |
12
+ | **Poly Haven** models (MCP `sculpt_model`) | Fetched at runtime. | CC0. | — |
13
+
14
+ ## Trademarks
15
+
16
+ LEGO® is a trademark of the LEGO Group of companies, which does not sponsor, authorize or endorse this project. `ldr` is an
17
+ independent, unofficial project and is not affiliated with the LEGO Group. Set numbers and names are used only to identify the sets
18
+ that community-made LDraw models replicate. LDraw™ is a trademark of the Estate of James Jessiman.
19
+
20
+ No LEGO building instructions, box art, product photography or other LEGO Group copyrighted material is distributed in this
21
+ repository. Screenshots in `docs/` are renders made with `ldr` of community LDraw models (credited above).
package/README.md CHANGED
@@ -161,6 +161,18 @@ parts added underneath), preferring front three-quarter views and small turns (t
161
161
  `isolate` is set while a sub-assembly is being built: show it on its own with `setStep(step, isolateMask(instances, view.isolate))`.
162
162
  Visibility is measured on part bounding boxes, so it needs no GPU and also runs in Node.
163
163
 
164
+ **AR Quick Look (USDZ).** `toUSDZ(instances, pack, { maxTriangles?, yUp?, scale? })` → `{ data, triangles, meshes, level }` builds a
165
+ USDZ in the browser (no three.js, no network): one mesh + `UsdPreviewSurface` per colour (LEGO colours in linear RGB, transparent
166
+ colours with `opacity`, chrome / metal as metallic), studs and undersides hidden by neighbours dropped, real size (1 LDU = 0.4 mm,
167
+ Y up, standing on y = 0, centred). It takes the finest pack LOD level (then square studs, then no studs) that fits `maxTriangles`
168
+ (default 200 000). Open it on iOS / iPadOS Safari (feature-detect with `document.createElement("a").relList.supports("ar")`):
169
+
170
+ ```js
171
+ const { data } = toUSDZ(model.instances, model.pack);
172
+ const a = document.createElement("a"); a.rel = "ar"; a.href = URL.createObjectURL(new Blob([data], { type: "model/vnd.usdz+zip" }));
173
+ a.append(document.createElement("img")); a.click(); // Quick Look needs the <img> child
174
+ ```
175
+
164
176
  ### `ldr/node` (Node / Bun only)
165
177
 
166
178
  Everything above, plus:
@@ -182,7 +194,7 @@ All numbers below were measured with the harness in [`bench/`](https://github.co
182
194
  - **Baseline:** three.js geometry from `LDrawLoader` merged per part and drawn with `InstancedMesh`, which is the fastest stock approach. Stock `LDrawLoader` scenes crash the tab (OOM) at 50k bricks and above.
183
195
  - **ldr settings:** the defaults: LOD pack, distance LOD, low-detail studs, stud and underside culling, single-sided faces, no edges.
184
196
 
185
- Sources: `bench/results/2026-10-18T18-10-46-518Z-falcon-vs-stock.md` (the Falcon rows), `bench/results/latest-perf.md` (the regression gate, `bench/baselines/darwin-apple-m4-pro.json`), `latest-mac-ablation.md`, and `research.md` §7 and Round 19.
197
+ Sources: `bench/results/2026-10-18T18-10-46-518Z-falcon-vs-stock.md` (the Falcon rows), `bench/results/latest-perf.md` (the regression gate, `bench/baselines/darwin-apple-m4-pro.json`), `latest-mac-ablation.md`.
186
198
 
187
199
  | model | bricks | baseline frame | **ldr frame** | baseline load | **ldr load** |
188
200
  |---|---|---|---|---|---|
package/dist/cli.js CHANGED
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // ../../../../../../../tmp/ldr-build-uD3Q4M/src/cli.ts
3
+ // ../../../../../../../tmp/ldr-build-yF6ijm/src/cli.ts
4
4
  import fs4 from "node:fs";
5
5
  import zlib from "node:zlib";
6
6
 
7
- // ../../../../../../../tmp/ldr-build-uD3Q4M/src/node/build-pack.ts
7
+ // ../../../../../../../tmp/ldr-build-yF6ijm/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-uD3Q4M/src/node/resolver.ts
11
+ // ../../../../../../../tmp/ldr-build-yF6ijm/src/node/resolver.ts
12
12
  import fs from "node:fs";
13
13
  import path from "node:path";
14
14
 
15
- // ../../../../../../../tmp/ldr-build-uD3Q4M/src/spec.ts
15
+ // ../../../../../../../tmp/ldr-build-yF6ijm/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;
@@ -848,7 +848,7 @@ function fileStepViews(f) {
848
848
  return out;
849
849
  }
850
850
 
851
- // ../../../../../../../tmp/ldr-build-uD3Q4M/src/model.ts
851
+ // ../../../../../../../tmp/ldr-build-yF6ijm/src/model.ts
852
852
  class ModelLimitError extends Error {
853
853
  limit;
854
854
  code = "ldr-model-limit";
@@ -1290,7 +1290,7 @@ function blendedColourHex(code) {
1290
1290
  return "#" + [0, 1, 2].map((k) => (a[k] + b[k] >> 1).toString(16).padStart(2, "0")).join("").toUpperCase();
1291
1291
  }
1292
1292
 
1293
- // ../../../../../../../tmp/ldr-build-uD3Q4M/src/node/resolver.ts
1293
+ // ../../../../../../../tmp/ldr-build-yF6ijm/src/node/resolver.ts
1294
1294
  var TOP_STUD_RE = /^(stud|studa|stud2|stud2a|stud6|stud6a|stud10|stud15|stud2s|stud2s2|stud-logo\d*|stud2-logo\d*)\.dat$/i;
1295
1295
  var UNDER_STUD_RE = /^(stud3|stud3a|stud4.*|stud12|stud16.*|stud18a)\.dat$/i;
1296
1296
  var norm2 = (ref) => ref.trim().replace(/\\/g, "/").toLowerCase();
@@ -1617,11 +1617,11 @@ function collectDeps(lib, refs) {
1617
1617
  return out;
1618
1618
  }
1619
1619
 
1620
- // ../../../../../../../tmp/ldr-build-uD3Q4M/src/node/compile.ts
1620
+ // ../../../../../../../tmp/ldr-build-yF6ijm/src/node/compile.ts
1621
1621
  import fs2 from "node:fs";
1622
1622
  import path2 from "node:path";
1623
1623
 
1624
- // ../../../../../../../tmp/ldr-build-uD3Q4M/src/node/lod.ts
1624
+ // ../../../../../../../tmp/ldr-build-yF6ijm/src/node/lod.ts
1625
1625
  import { MeshoptSimplifier, MeshoptEncoder } from "meshoptimizer";
1626
1626
  await Promise.all([MeshoptSimplifier.ready, MeshoptEncoder.ready]);
1627
1627
  function reorderMesh(P, N, C, I) {
@@ -1927,7 +1927,7 @@ function levelLines(P, I, E, err, always, tol = 0.01) {
1927
1927
  return out;
1928
1928
  }
1929
1929
 
1930
- // ../../../../../../../tmp/ldr-build-uD3Q4M/src/node/compile.ts
1930
+ // ../../../../../../../tmp/ldr-build-yF6ijm/src/node/compile.ts
1931
1931
  class BfcState {
1932
1932
  accum;
1933
1933
  ccw = true;
@@ -2871,7 +2871,7 @@ function encodePack(parts, studKinds, weld, extra, options = {}) {
2871
2871
  return Buffer.concat([head, ...chunks.map((c) => new Uint8Array(c.buffer, c.byteOffset, c.byteLength))]);
2872
2872
  }
2873
2873
 
2874
- // ../../../../../../../tmp/ldr-build-uD3Q4M/src/node/build-pack.ts
2874
+ // ../../../../../../../tmp/ldr-build-yF6ijm/src/node/build-pack.ts
2875
2875
  function packCompilerOpts(o) {
2876
2876
  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 } : {} };
2877
2877
  }
@@ -2944,7 +2944,7 @@ function buildPack(o) {
2944
2944
  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 } : {} };
2945
2945
  }
2946
2946
 
2947
- // ../../../../../../../tmp/ldr-build-uD3Q4M/src/cli.ts
2947
+ // ../../../../../../../tmp/ldr-build-yF6ijm/src/cli.ts
2948
2948
  var HELP = `ldr pack — build a parts pack for the ldr three.js renderer
2949
2949
 
2950
2950
  Usage:
package/dist/index.d.ts CHANGED
@@ -13,3 +13,4 @@ export { decompressPack, decodeModelText, modelFileName } from "./pack-io.js";
13
13
  export { loadModel, loadParts, loadPartsIndex, mergePacks, prepareModel, bodyTriangles, estimateBudgetFromIndex, BudgetError, DEFAULT_PARTS_CDN } from "./cdn.js";
14
14
  export type { LoadModelOptions, LoadedModel, LoadPartsOptions, PartsCdnIndex, PrepareOptions, PreparedModel } from "./cdn.js";
15
15
  export { embeddedKeys } from "./embedded.js";
16
+ export { toUSDZ, zipStored, type UsdzOptions, type UsdzResult } from "./usdz.js";