ldr 0.34.11 → 0.34.13

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 CHANGED
@@ -147,7 +147,7 @@ MPD-embedded parts, such as Studio/OMR unofficial parts or stickers, become part
147
147
  | `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. |
148
148
  | `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. |
149
149
 
150
- `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()`.
150
+ `LdrObject`: `object`, `stats` (`instances`, `drawn`, `missing[]`, `studsHidden/Total`, `undersHidden/Total`, `buildMs`, `condBatches`, `texBatches`, `textures`, `glossmaps`, `clusters`), `stepCount`, `stepViews`, `texturesReady`, `setStep(n | null, mask?, ghostAfter?)` (`ghostAfter`: the ghost shows only the steps after it, e.g. `setStep(s - 1, mask, s)` while step s's parts animate in, so none is drawn as a ghost and a solid at once), `setEdges(on)`, `setConditionalLines(on)`, `setCulling(studs, undersides)`, `setSide(side)`, `setLod(on)`, `setGhost(on, { opacity, color, whiten }?)`, `getBox(target?)`, `dispose()`.
151
151
 
152
152
  `setStep` doesn't rebuild anything: it compacts instance buffers, and culling is step-aware (a stud covered only by a later step's part stays visible). `stats` reflect the shown step.
153
153
 
package/dist/cli.js CHANGED
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- // ../../../../../../../tmp/ldr-build-cBWp5F/src/cli.ts
3
+ // ../../../../../../../tmp/ldr-build-s89ZOB/src/cli.ts
4
4
  import fs4 from "node:fs";
5
5
  import zlib from "node:zlib";
6
6
 
7
- // ../../../../../../../tmp/ldr-build-cBWp5F/src/node/build-pack.ts
7
+ // ../../../../../../../tmp/ldr-build-s89ZOB/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-cBWp5F/src/node/resolver.ts
11
+ // ../../../../../../../tmp/ldr-build-s89ZOB/src/node/resolver.ts
12
12
  import fs from "node:fs";
13
13
  import path from "node:path";
14
14
 
15
- // ../../../../../../../tmp/ldr-build-cBWp5F/src/spec.ts
15
+ // ../../../../../../../tmp/ldr-build-s89ZOB/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-cBWp5F/src/model.ts
851
+ // ../../../../../../../tmp/ldr-build-s89ZOB/src/model.ts
852
852
  class ModelLimitError extends Error {
853
853
  limit;
854
854
  code = "ldr-model-limit";
@@ -898,6 +898,15 @@ function flatten(doc, opts = {}) {
898
898
  const loose = opts.looseGeometry !== false, tx = !!opts.textures, co = !!opts.callouts;
899
899
  const src = new Map;
900
900
  let subs = 0;
901
+ const stepSingles = [];
902
+ const stepPathOf = (path, s) => {
903
+ if (path.length)
904
+ return [...path, s];
905
+ let a = stepSingles[s];
906
+ if (!a)
907
+ stepSingles[s] = a = [s];
908
+ return a;
909
+ };
901
910
  const open = new Set;
902
911
  const maxN = opts.maxInstances ?? 2000000;
903
912
  let work = 0;
@@ -977,7 +986,7 @@ function flatten(doc, opts = {}) {
977
986
  const flushLoose = (upTo) => {
978
987
  while (li < ls.length && ls[li] <= upTo) {
979
988
  const k = ls[li++];
980
- emit(loosePartName(f.name, k), color, m, [...stepPath, k], k, false, null, colour, scope0).source = lazy(f, k);
989
+ emit(loosePartName(f.name, k), color, m, stepPathOf(stepPath, k), k, false, null, colour, scope0).source = lazy(f, k);
981
990
  }
982
991
  };
983
992
  for (const c0 of f.cmds) {
@@ -1008,10 +1017,10 @@ function flatten(doc, opts = {}) {
1008
1017
  continue;
1009
1018
  if (tx && c.fallback)
1010
1019
  continue;
1011
- const mm = mul(m, c.m);
1020
+ const mm = m === I ? c.m : mul(m, c.m);
1012
1021
  if (!inRange12(mm))
1013
1022
  continue;
1014
- const col = c.color === 16 ? color : c.color, cd = c.color === 16 ? colour : scope?.get(c.color), sp = [...stepPath, s];
1023
+ const col = c.color === 16 ? color : c.color, cd = c.color === 16 ? colour : scope?.get(c.color), sp = stepPathOf(stepPath, s);
1015
1024
  const tex = tx ? c.tex ?? texIn : null;
1016
1025
  const local = tex ? invert(c.m) : null;
1017
1026
  const lt = tex && local ? transformTexMap(tex, local) : null;
@@ -1290,7 +1299,7 @@ function blendedColourHex(code) {
1290
1299
  return "#" + [0, 1, 2].map((k) => (a[k] + b[k] >> 1).toString(16).padStart(2, "0")).join("").toUpperCase();
1291
1300
  }
1292
1301
 
1293
- // ../../../../../../../tmp/ldr-build-cBWp5F/src/node/resolver.ts
1302
+ // ../../../../../../../tmp/ldr-build-s89ZOB/src/node/resolver.ts
1294
1303
  var TOP_STUD_RE = /^(stud|studa|stud2|stud2a|stud6|stud6a|stud10|stud15|stud2s|stud2s2|stud-logo\d*|stud2-logo\d*)\.dat$/i;
1295
1304
  var UNDER_STUD_RE = /^(stud3|stud3a|stud4.*|stud12|stud16.*|stud18a)\.dat$/i;
1296
1305
  var norm2 = (ref) => ref.trim().replace(/\\/g, "/").toLowerCase();
@@ -1617,11 +1626,11 @@ function collectDeps(lib, refs) {
1617
1626
  return out;
1618
1627
  }
1619
1628
 
1620
- // ../../../../../../../tmp/ldr-build-cBWp5F/src/node/compile.ts
1629
+ // ../../../../../../../tmp/ldr-build-s89ZOB/src/node/compile.ts
1621
1630
  import fs2 from "node:fs";
1622
1631
  import path2 from "node:path";
1623
1632
 
1624
- // ../../../../../../../tmp/ldr-build-cBWp5F/src/node/lod.ts
1633
+ // ../../../../../../../tmp/ldr-build-s89ZOB/src/node/lod.ts
1625
1634
  import { MeshoptSimplifier, MeshoptEncoder } from "meshoptimizer";
1626
1635
  await Promise.all([MeshoptSimplifier.ready, MeshoptEncoder.ready]);
1627
1636
  function reorderMesh(P, N, C, I) {
@@ -1927,7 +1936,7 @@ function levelLines(P, I, E, err, always, tol = 0.01) {
1927
1936
  return out;
1928
1937
  }
1929
1938
 
1930
- // ../../../../../../../tmp/ldr-build-cBWp5F/src/node/compile.ts
1939
+ // ../../../../../../../tmp/ldr-build-s89ZOB/src/node/compile.ts
1931
1940
  class BfcState {
1932
1941
  accum;
1933
1942
  ccw = true;
@@ -2230,6 +2239,22 @@ class Compiler {
2230
2239
  seatStuds(out, fullKind, (k) => this.compile(k, false).bbox);
2231
2240
  if (this.opts.tex && this.hasTex(key))
2232
2241
  this.texPass(key, out, separateStuds, colorOf);
2242
+ const cap = OPEN_BOTTOM[key.replace(/^.*[\\/]/, "").toLowerCase()];
2243
+ if (cap && isFinite(out.bbox[0])) {
2244
+ const [cx0, cz0, cx1, cz1] = cap, y = out.bbox[4], b = out.body, per = b.col.length / (b.pos.length / 3);
2245
+ let v = -1;
2246
+ for (let i = 1;i < b.pos.length; i += 3)
2247
+ if (Math.abs(b.pos[i] - y) < 0.01) {
2248
+ v = (i - 1) / 3;
2249
+ break;
2250
+ }
2251
+ if (v >= 0) {
2252
+ const rgba = b.col.slice(v * per, v * per + per);
2253
+ b.pos.push(cx0, y, cz0, cx0, y, cz1, cx1, y, cz1, cx0, y, cz0, cx1, y, cz1, cx1, y, cz0);
2254
+ for (let k = 0;k < 6; k++)
2255
+ b.col.push(...rgba);
2256
+ }
2257
+ }
2233
2258
  const [x0, y0, z0, x1, y1, z1] = out.bbox;
2234
2259
  let ax0 = Infinity, ax1 = -Infinity, az0 = Infinity, az1 = -Infinity;
2235
2260
  for (const b of [out.body, out.under])
@@ -2455,6 +2480,7 @@ class Compiler {
2455
2480
  }
2456
2481
  }
2457
2482
  }
2483
+ var OPEN_BOTTOM = { "11477.dat": [-10, -20, 10, 20] };
2458
2484
  function underEnclosed(c) {
2459
2485
  const u = c.under.pos;
2460
2486
  let uy0 = Infinity, uy1 = -Infinity, ux0 = Infinity, ux1 = -Infinity, uz0 = Infinity, uz1 = -Infinity;
@@ -2871,7 +2897,7 @@ function encodePack(parts, studKinds, weld, extra, options = {}) {
2871
2897
  return Buffer.concat([head, ...chunks.map((c) => new Uint8Array(c.buffer, c.byteOffset, c.byteLength))]);
2872
2898
  }
2873
2899
 
2874
- // ../../../../../../../tmp/ldr-build-cBWp5F/src/node/build-pack.ts
2900
+ // ../../../../../../../tmp/ldr-build-s89ZOB/src/node/build-pack.ts
2875
2901
  function packCompilerOpts(o) {
2876
2902
  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
2903
  }
@@ -2944,7 +2970,7 @@ function buildPack(o) {
2944
2970
  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
2971
  }
2946
2972
 
2947
- // ../../../../../../../tmp/ldr-build-cBWp5F/src/cli.ts
2973
+ // ../../../../../../../tmp/ldr-build-s89ZOB/src/cli.ts
2948
2974
  var HELP = `ldr pack — build a parts pack for the ldr three.js renderer
2949
2975
 
2950
2976
  Usage:
package/dist/index.d.ts CHANGED
@@ -6,8 +6,9 @@ export type { StepCameraView, StepCameraOptions, Vec3 } from "./instructions.js"
6
6
  export type { PartInstance, FlattenOptions, LDrawColor, LDrawFinish, LDrawFinishType, LDrawMaterialGrain, ColourSurface } from "./model.js";
7
7
  export { loadPack, decodePack, buildLdrScene, buildLdrSceneAsync, makeMaterial, makeFinishMaterial, createInstancedEdges, computeCulling, cullCore, forEachStud, conditionalLines, createInstancedConditionalEdges, conditionalLineVisible, warmPackGeometry, makeTexturedMaterial, packTexture, pngHasAlpha } from "./render.js";
8
8
  export { precomputeCull, sceneInstances } from "./cull.js";
9
- export type { Pack, LdrParams, Inst, CullResult, BuildLdrSceneAsyncOptions, GlossMap } from "./render.js";
9
+ export type { StudMask, Pack, LdrParams, Inst, CullResult, BuildLdrSceneAsyncOptions, GlossMap } from "./render.js";
10
10
  export { createLdrObject, createLdrObjectAsync } from "./scene.js";
11
+ export { studDecalUniforms, type StudDecalUniforms } from "./stud-decal.js";
11
12
  export type { LdrObject, LdrObjectOptions, LdrStats, ColorSource, GhostOptions } from "./scene.js";
12
13
  export { decompressPack, decodeModelText, modelFileName } from "./pack-io.js";
13
14
  export { loadModel, loadParts, loadPartsIndex, mergePacks, prepareModel, bodyTriangles, estimateBudgetFromIndex, BudgetError, DEFAULT_PARTS_CDN } from "./cdn.js";