main
John Lauer 3D model from KiCad's own package generator at the datasheet's values: radiused gull-wing leads in matte tin, reviewed… 9ad862b
#!/usr/bin/env python3
"""Give a chip GLB physical materials, by the part each material is used on.
step2glb writes base colours only, so glTF's defaults (metallic 1, roughness 1) make every part a flat
rough metal. This sets, per part (node name from the STEP assembly):
  pins            -> "Adom.Leads (matte tin)": metallic 1.0, roughness 0.35, tin colour
  body            -> "Adom.Body (epoxy)": metallic 0.0, roughness 0.55, colour kept
  mark            -> "Adom.Pin1Mark": metallic 0.0, roughness 0.6, colour kept
  Adom.LaserEtch  -> metallic 0.0, roughness 0.7, colour kept (the reviewed mark)
Geometry, node transforms and the etch colour are untouched. Each material is used by one part only.
usage: materials.py in.glb [out.glb]   (in place when out is omitted)"""
import sys
from pygltflib import GLTF2, Material, PbrMetallicRoughness

TIN = [0.72, 0.72, 0.70, 1.0]          # linear; about sRGB 0.86 / 0.86 / 0.85, bright matte tin
SPEC = {
    "pins": ("Adom.Leads (matte tin)", 1.0, 0.35, TIN),
    "body": ("Adom.Body (epoxy)", 0.0, 0.55, None),
    "mark": ("Adom.Pin1Mark", 0.0, 0.6, None),
    "Adom.LaserEtch": (None, 0.0, 0.7, None),
}

def main(src, out):
    g = GLTF2().load(src)
    used = {}
    for n in g.nodes:
        if n.mesh is None:
            continue
        key = next((k for k in SPEC if (n.name or "").startswith(k)), None)
        for p in g.meshes[n.mesh].primitives:
            if p.material is None:
                continue
            used.setdefault(p.material, set()).add(key)
            if key is None:
                continue
            # give this part its own material when another part shares it
            if len(used[p.material]) > 1:
                m = g.materials[p.material]
                g.materials.append(Material(name=m.name, pbrMetallicRoughness=PbrMetallicRoughness(
                    baseColorFactor=list(m.pbrMetallicRoughness.baseColorFactor)), doubleSided=m.doubleSided))
                p.material = len(g.materials) - 1
                used[p.material] = {key}
            name, metal, rough, col = SPEC[key]
            m = g.materials[p.material]
            pbr = m.pbrMetallicRoughness or PbrMetallicRoughness()
            pbr.metallicFactor, pbr.roughnessFactor = metal, rough
            if col:
                pbr.baseColorFactor = col
            m.pbrMetallicRoughness = pbr
            if name:
                m.name = name
    missing = [k for k in ("pins", "body") if not any(k in s for s in used.values())]
    if missing:
        sys.exit(f"ERROR: {src}: no {missing} part found (node names must come from the STEP assembly)")
    g.save(out)
    print(f"OK: {out}: " + ", ".join(f"{m.name} m{m.pbrMetallicRoughness.metallicFactor} r{m.pbrMetallicRoughness.roughnessFactor}" for m in g.materials))

if __name__ == "__main__":
    main(sys.argv[1], sys.argv[2] if len(sys.argv) > 2 else sys.argv[1])