"""Exterior of the Mako in its own frame (hatch shut, stern arms stowed, cabin left out), for sweep_check.py and clamp_check.py: checks/mako_points.npy every 2nd vertex (the moon pool at BOARD, the carousel sweep) checks/mako_tris.npz all triangles (the docking clamp) Runs in an open Blender or headless (blender -b Tender_Mako.blend --python build/dump_mako.py); leaves the rig as it found it.""" import bpy, numpy as np, os HERE = r"D:\HADAL - The Descent\models\tender-mako\build" root = bpy.data.objects["Mako_Root"] PROPS = ("hatch_open_deg", "arms_out_deg", "rotor_turns") def refresh_drivers(): for ob in bpy.data.objects: if ob.animation_data: for fc in ob.animation_data.drivers: fc.driver.expression = fc.driver.expression fc.driver.is_valid = True def collect(): V, T, NAMES, OFF, P = [], [], [], 0, [] dg = bpy.context.evaluated_depsgraph_get() for o in bpy.data.objects: if o.type == 'MESH' and o.name.startswith("SM_Mako") and o.name != "SM_Mako_Cabin": ev = o.evaluated_get(dg) me = o.data me.calc_loop_triangles() M = np.array(ev.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] tr = np.empty(len(me.loop_triangles) * 3, np.int64); me.loop_triangles.foreach_get("vertices", tr) V.append(co); T.append(tr.reshape(-1, 3) + OFF); NAMES += [o.name] * len(me.loop_triangles); OFF += len(co) P.append(co[::2]) return V, T, NAMES, P keep = {k: root.get(k, 0.0) for k in PROPS} refresh_drivers() for k in PROPS: root[k] = 0.0 root.update_tag() for ob in root.children: ob.update_tag() bpy.context.view_layer.update() V, T, NAMES, P = collect() np.save(os.path.join(HERE, "checks", "mako_points.npy"), np.concatenate(P)) np.savez(os.path.join(HERE, "checks", "mako_tris.npz"), v=np.concatenate(V), t=np.concatenate(T), names=np.array(NAMES)) for k, v in keep.items(): root[k] = v root.update_tag(); bpy.context.view_layer.update() print("DUMP", sum(len(v) for v in V), sum(len(t) for t in T))