main
John Lauer Add KiCad symbol and footprint, viewers, provenance, README, models.json and verification log 354b2dd 11h ago
// LOD derivation for a chip GLB (glTF Transform 4.1 + meshoptimizer), per wiki-component-lod:
//   batch:    join primitives per material inside each named part (body, pins, mark, Adom.LaserEtch stay
//             separate nodes), dedup, prune; geometry unchanged (lossless batching)
//   simplify: weld then error-bounded meshopt simplification to a target ratio (lower levels only)
//   quantize: KHR_mesh_quantization
// usage: node lod.mjs in.glb out.glb [--simplify ratio:error] [--quantize]
import { NodeIO } from '@gltf-transform/core';
import { ALL_EXTENSIONS } from '@gltf-transform/extensions';
import { dedup, join, prune, weld, simplify, quantize } from '@gltf-transform/functions';
import { MeshoptSimplifier } from 'meshoptimizer';

const [, , src, out, ...opts] = process.argv;
const io = new NodeIO().registerExtensions(ALL_EXTENSIONS);
const doc = await io.read(src);
const before = count(doc);
const steps = [dedup(), join({ keepNamed: true }), prune()];
const si = opts.indexOf('--simplify');
if (si >= 0) {
  const [ratio, error] = opts[si + 1].split(':').map(Number);
  await MeshoptSimplifier.ready;
  steps.push(weld(), simplify({ simplifier: MeshoptSimplifier, ratio, error, lockBorder: false }), prune());
}
if (opts.includes('--quantize')) steps.push(quantize());
await doc.transform(...steps);
await io.write(out, doc);
console.log(JSON.stringify({ out, before, after: count(doc), nodes: doc.getRoot().listNodes().filter(n => n.getMesh()).map(n => n.getName()) }));

function count(d) {
  let prims = 0, tris = 0;
  for (const m of d.getRoot().listMeshes()) for (const p of m.listPrimitives()) {
    prims++; const i = p.getIndices(); tris += (i ? i.getCount() : p.getAttribute('POSITION').getCount()) / 3;
  }
  return { prims, tris };
}