"""Tiger: the cockpit and the rear bay inside the skin, the Mako's check (no cabin vertex within 5 mm of the skin or the glass, contacts listed), and whether any cabin vertex can be seen from outside (a free line of sight along +x, -x or +z past the hull and the glass). Read-only: blender -b Tender_Tiger.blend --python build/tg_cabin_check.py -> build/checks/cabin.json""" import bpy, os, json import numpy as np from mathutils import Vector from mathutils.bvhtree import BVHTree HERE = os.path.dirname(os.path.abspath(__file__)) D = bpy.data dg = bpy.context.evaluated_depsgraph_get() def geo(o): e = o.evaluated_get(dg) me = e.to_mesh() me.calc_loop_triangles() M = e.matrix_world vs = [M @ v.co for v in me.vertices] ts = [tuple(t.vertices) for t in me.loop_triangles] mi = [t.material_index for t in me.loop_triangles] mats = [m.name if m else None for m in me.materials] e.to_mesh_clear() return vs, ts, mi, mats cv, ct, cmi, cm = geo(D.objects["SM_Tiger_Cabin"]) C = BVHTree.FromPolygons(cv, ct) crossings, near, where = {}, {}, {} trees = [] for n in ("SM_Tiger_Hull", "SM_Tiger_Glass"): hv, ht, hmi, hm = geo(D.objects[n]) H = BVHTree.FromPolygons(hv, ht) trees.append(H) for i, j in C.overlap(H): k = "%s x %s" % (cm[cmi[i]], hm[hmi[j]]) crossings[k] = crossings.get(k, 0) + 1 c = (cv[ct[i][0]] + cv[ct[i][1]] + cv[ct[i][2]]) / 3 where.setdefault(k, []).append([round(c.x, 3), round(c.y, 3), round(c.z, 3)]) for q in cv: r = H.find_nearest(q) if r[0] is not None and r[3] < 0.005: near[n] = near.get(n, 0) + 1 least = min(min(t.find_nearest(q)[3] for q in cv) for t in trees) seen = 0 for q in cv: for dvec in (Vector((1, 0, 0)), Vector((-1, 0, 0)), Vector((0, 0, 1))): if all(t.ray_cast(q, dvec)[0] is None for t in trees): seen += 1 break box = {k: [np.round(np.min(v, 0), 3).tolist(), np.round(np.max(v, 0), 3).tolist()] for k, v in where.items()} out = {"cabin_vertices": len(cv), "crossing_pairs": crossings, "crossing_boxes": box, "vertices_within_5mm": near, "least_gap_m": round(least, 4), "vertices_seen_from_outside": seen} json.dump(out, open(os.path.join(HERE, "checks", "cabin.json"), "w"), indent=1) print("CABIN", json.dumps(out))