91 lines
2.3 KiB
Python
91 lines
2.3 KiB
Python
import bpy
|
|
import bmesh
|
|
from mathutils import Vector
|
|
from collections import defaultdict
|
|
from dataclasses import dataclass
|
|
|
|
def sprint(*text):
|
|
screen = bpy.data.screens['Scripting']
|
|
for area in screen.areas:
|
|
if area.type != "CONSOLE":
|
|
continue
|
|
override = {'screen': screen, 'area': area}
|
|
with bpy.context.temp_override(**override):
|
|
bpy.ops.console.scrollback_append(text=" ".join(map(str, text)))
|
|
|
|
print = sprint
|
|
|
|
def face_indicators(light: Vector,
|
|
position: list[Vector],
|
|
polygon_normal: list[Vector],
|
|
mesh: bpy.types.Mesh,
|
|
# outputs
|
|
indicators: list[float]):
|
|
for i in range(len(mesh.polygons)):
|
|
n = polygon_normal[i]
|
|
p = position[mesh.polygons[i].a]
|
|
indicator = dot(n, (light - p))
|
|
indicators[i] = indicator
|
|
|
|
@dataclass
|
|
class Edge:
|
|
a: int # vertex index
|
|
b: int # vertex index
|
|
|
|
@dataclass
|
|
class PolygonIndex:
|
|
a: int
|
|
b: int
|
|
|
|
@dataclass
|
|
class EdgePolygon:
|
|
edge: Edge
|
|
polygon_index: PolygonIndex
|
|
|
|
def build_edge_polygons(mesh: bpy.types.Mesh):
|
|
by_edge = defaultdict(list)
|
|
for i, polygon in enumerate(mesh.polygons):
|
|
for edge in polygon.edge_keys:
|
|
by_edge[frozenset(edge)].append(i)
|
|
|
|
assert all(len(p) == 2 for p in by_edge.values())
|
|
|
|
return [
|
|
EdgePolygon(Edge(*edge), PolygonIndex(*polygons))
|
|
for edge, polygons in by_edge.items()
|
|
]
|
|
|
|
def object_silhouette(indicators: list[float],
|
|
mesh: bpy.types.Mesh,
|
|
# outputs
|
|
edge_indices: list[int]):
|
|
ix = 0
|
|
|
|
edge_polygons = build_edge_polygons(mesh)
|
|
|
|
for i in range(len(edge_polygons)):
|
|
ep = edge_polygons[i]
|
|
if (indicators[ep.polygon_index.a] > 0) != (indicators[ep.polygon_index.b]):
|
|
edge_indices[ix] = i
|
|
ix += 1
|
|
|
|
return ix
|
|
|
|
def select_edge(bm, edge):
|
|
for e in bm.edges:
|
|
if frozenset((e.verts[0].index, e.verts[1].index)) == frozenset(edge):
|
|
e.select = True
|
|
|
|
def select():
|
|
light = bpy.data.objects['Light']
|
|
torus = bpy.data.objects['Torus']
|
|
|
|
position = [0] * len(
|
|
|
|
obj = bpy.context.edit_object
|
|
bm = bmesh.from_edit_mesh(obj.data)
|
|
|
|
|
|
|
|
bmesh.update_edit_mesh(obj.data)
|