# Grouper (copied from the Critique's round 2 cr2_collar_rays.py, output to build/checks; read-only): dense rays at the four claw pockets from 24 eye points above and round the collar: # back faces seen (holes or inside surfaces) and what the rays hit first. import bpy, json, os, math, collections from mathutils import Vector from mathutils.bvhtree import BVHTree ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) dg = bpy.context.evaluated_depsgraph_get() verts, polys, owner = [], [], [] for nm in ["SM_Grouper_Hull", "SM_Grouper_Hatch", "SM_Grouper_Cabin", "SM_Grouper_Antenna"]: o = bpy.data.objects[nm]; ev = o.evaluated_get(dg); me = ev.to_mesh(); M = ev.matrix_world b = len(verts); verts += [M @ v.co for v in me.vertices] for p in me.polygons: polys.append([b + i for i in p.vertices]); owner.append(nm) ev.to_mesh_clear() bvh = BVHTree.FromPolygons(verts, polys) res = {} for ang in (45, 135, 225, 315): a = math.radians(ang) P = Vector((0.55 * math.cos(a), -0.09 + 0.55 * math.sin(a), 1.12)) back = 0; tot = 0; pts = [] for e in range(24): az = a + math.radians(-70 + 140 * (e % 6) / 5); el = math.radians(15 + 20 * (e // 6)) eye = P + Vector((math.cos(az) * math.cos(el), math.sin(az) * math.cos(el), math.sin(el))) * 2.5 fwd = (P - eye).normalized(); r = fwd.cross(Vector((0, 0, 1))).normalized(); u = r.cross(fwd) for i in range(-30, 31): for k in range(-30, 31): d = (fwd + r * i * 0.004 + u * k * 0.004).normalized() loc, n, fi, dist = bvh.ray_cast(eye, d) if loc is None: continue tot += 1 if n.dot(d) > 0.05: back += 1 if len(pts) < 8: pts.append([round(x, 3) for x in loc] + [owner[fi]]) res[ang] = dict(rays=tot, back_face_hits=back, pct=round(100 * back / max(1, tot), 2), where=pts) json.dump(res, open(os.path.join(ROOT, "build", "checks", "collar_rays.json"), "w"), indent=1) print("CR2 COLLAR", json.dumps({k: (v["back_face_hits"], v["pct"]) for k, v in res.items()})) for k, v in res.items(): print(k, v["where"][:5])