"""Headless Blender: dump the Mako's meshes as world triangles with their material names (a diagnostic: the Mako was built after the four-view sheet of the same design, so rendering it through this picture's camera shows where the picture differs). blender -b ../../tender-mako/Tender_Mako.blend --python tg_dump_mako.py -> build/checks/mako_tris.npz (the .blend is not saved) """ import bpy import os import numpy as np HERE = os.path.dirname(os.path.abspath(__file__)) out = os.path.join(HERE, "checks") os.makedirs(out, exist_ok=True) dg = bpy.context.evaluated_depsgraph_get() tris, mats, objs = [], [], [] for ob in bpy.context.scene.objects: if ob.type != "MESH" or ob.name.startswith("UCX_") or not ob.visible_get(): continue ev = ob.evaluated_get(dg) me = ev.to_mesh() me.calc_loop_triangles() M = np.array(ob.matrix_world) co = np.empty(len(me.vertices) * 3) me.vertices.foreach_get("co", co) co = co.reshape(-1, 3) @ M[:3, :3].T + M[:3, 3] lt = np.empty(len(me.loop_triangles) * 3, np.int32) me.loop_triangles.foreach_get("vertices", lt) mi = np.empty(len(me.loop_triangles), np.int32) me.loop_triangles.foreach_get("material_index", mi) names = [s.material.name if s.material else "none" for s in ob.material_slots] or ["none"] tris.append(co[lt.reshape(-1, 3)]) mats += [names[min(i, len(names) - 1)] for i in mi] objs += [ob.name] * len(mi) ev.to_mesh_clear() np.savez_compressed(os.path.join(out, "mako_tris.npz"), tris=np.concatenate(tris), mats=np.array(mats), objs=np.array(objs)) print("DUMPED", sum(len(t) for t in tris), sorted(set(mats)))