(context, bake=False, keep=False, symmetry=False)
| 75 | |
| 76 | |
| 77 | def align(context, bake=False, keep=False, symmetry=False): |
| 78 | keep_bucket = [] |
| 79 | for m in context.selected_objects: |
| 80 | if m.type != "MESH": |
| 81 | continue |
| 82 | |
| 83 | polys = m.data.polygons |
| 84 | if len(polys) == 0: |
| 85 | continue |
| 86 | |
| 87 | global_matrix = np.array(m.matrix_basis) |
| 88 | areas = np.array([p.area for p in polys]) |
| 89 | normals = np.array([list(p.normal) |
| 90 | for p in polys]) @ global_matrix[:3, :3].T |
| 91 | normals = normals / np.linalg.norm(normals, axis=1).reshape(-1, 1) |
| 92 | |
| 93 | if symmetry: |
| 94 | verts = m.data.vertices |
| 95 | normals_vert = np.array([list(v.normal) |
| 96 | for v in verts]) @ global_matrix[:3, :3].T |
| 97 | normals_vert = normals_vert / \ |
| 98 | np.linalg.norm(normals_vert, axis=1).reshape(-1, 1) |
| 99 | positions_vert = np.array([list(v.co) |
| 100 | for v in verts]) @ global_matrix[:3, :3].T |
| 101 | plane = get_symmetry_plane(normals_vert, positions_vert) |
| 102 | model = get_matrix(areas, normals, fixed_axis=plane[0:3]) |
| 103 | |
| 104 | else: |
| 105 | model = get_matrix(areas, normals) |
| 106 | |
| 107 | global_matrix[:3, :3] = model@global_matrix[:3, :3] |
| 108 | |
| 109 | m.matrix_basis = global_matrix.T |
| 110 | |
| 111 | if keep: |
| 112 | keep_bucket.append((m, model)) |
| 113 | |
| 114 | if bake: |
| 115 | bpy.ops.object.transform_apply( |
| 116 | location=False, rotation=True, scale=False) |
| 117 | |
| 118 | if keep: |
| 119 | for m, model in keep_bucket: |
| 120 | global_matrix = np.array(m.matrix_basis) |
| 121 | global_matrix[:3, :3] = model.T@global_matrix[:3, :3] |
| 122 | m.matrix_basis = global_matrix.T |
| 123 | |
| 124 | |
| 125 | def get_symmetry_plane(normals, positions): |
no test coverage detected