main
John Lauer LODs, models.json, verification log, provenance and tools, README, license c543194 17h ago
#!/usr/bin/env python3
"""Give the CX3225GA GLB physical materials, by the part each material is used on.
step2glb writes base colours only, so glTF's defaults (metallic 1, roughness 1) render every part as
rough metal. This sets, per node name from the STEP assembly (build_cx3225ga.py):
  base          -> "Adom.Body (ceramic)": metallic 0.0, roughness 0.7, colour kept
  seal_ring     -> "Adom.SealRing": metallic 1.0, roughness 0.45, colour kept
  lid           -> "Adom.Lid (black)": metallic 0.0, roughness 0.6, colour kept
  electrode_*   -> "Adom.Terminals (gold)": metallic 1.0, roughness 0.3, colour kept
  Adom.LaserEtch-> metallic 0.0, roughness 0.7, colour kept (the virtual MPN mark)
Geometry and node transforms are untouched.
usage: materials.py in.glb [out.glb]   (in place when out is omitted)"""
import sys
from pygltflib import GLTF2, Material, PbrMetallicRoughness

SPEC = {
    "base": ("Adom.Body (ceramic)", 0.0, 0.7),
    "seal_ring": ("Adom.SealRing", 1.0, 0.45),
    "lid": ("Adom.Lid (black)", 0.0, 0.6),
    "electrode": ("Adom.Terminals (gold)", 1.0, 0.3),
    "Adom.LaserEtch": (None, 0.0, 0.7),
}


def main(src, out):
    g = GLTF2().load(src)
    done = {}
    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)
        if key is None:
            continue
        name, metal, rough = SPEC[key]
        for p in g.meshes[n.mesh].primitives:
            if p.material is None:
                continue
            if (key, p.material) in done:
                p.material = done[(key, p.material)]
                continue
            old = g.materials[p.material]
            col = (old.pbrMetallicRoughness.baseColorFactor if old.pbrMetallicRoughness else None) or [0.5, 0.5, 0.5, 1]
            m = Material(name=name or old.name, pbrMetallicRoughness=PbrMetallicRoughness(
                baseColorFactor=col, metallicFactor=metal, roughnessFactor=rough), doubleSided=old.doubleSided,
                alphaMode=old.alphaMode)
            g.materials.append(m)
            done[(key, p.material)] = len(g.materials) - 1
            p.material = len(g.materials) - 1
    # drop materials no primitive uses any more
    used = sorted({p.material for m in g.meshes for p in m.primitives if p.material is not None})
    remap = {o: i for i, o in enumerate(used)}
    g.materials = [g.materials[o] for o in used]
    for m in g.meshes:
        for p in m.primitives:
            if p.material is not None:
                p.material = remap[p.material]
    g.save(out)
    print("OK", out, [m.name for m in g.materials])


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