forked from s-macke/starflight-reverse
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathuvmapper-blender.py
184 lines (143 loc) · 5.82 KB
/
uvmapper-blender.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
import bpy
import bmesh
import numpy as np
from scipy.spatial import ConvexHull
# Ensure we are in object mode
bpy.ops.object.mode_set(mode='OBJECT')
# Get the active mesh object
obj = bpy.context.object
# Ensure the object is a mesh
if obj.type != 'MESH':
raise TypeError("Active object is not a mesh")
# Get the mesh data
mesh = obj.data
# Ensure there is at least one polygon selected
if not any(p.select for p in mesh.polygons):
raise ValueError("No polygon selected")
# Find the first selected polygon
selected_poly = next(p for p in mesh.polygons if p.select)
# Enter edit mode
bpy.ops.object.mode_set(mode='EDIT')
# Create a bmesh object and load the mesh data
bm = bmesh.from_edit_mesh(mesh)
bm.verts.ensure_lookup_table()
bm.edges.ensure_lookup_table()
bm.faces.ensure_lookup_table()
# Get vertices and edges from the selected face
vertices = {v.index: obj.matrix_world @ v.co for v in bm.verts if v.select}
edges = [(e.verts[0].index, e.verts[1].index) for e in bm.edges if e.select]
print("Vertices:")
for vid, coord in vertices.items():
print(f"Vertex {vid}: {coord}")
print("\nEdges:")
for edge in edges:
print(f"Edge: {edge}")
# Compute the normal vector and plane equation
vertex_ids = list(vertices.keys())
p1, p2, p3 = np.array(vertices[vertex_ids[0]]), np.array(vertices[vertex_ids[1]]), np.array(vertices[vertex_ids[2]])
v1, v2 = p2 - p1, p3 - p1
normal = np.cross(v1, v2)
A, B, C = normal
D = -np.dot(normal, p1)
# Function to project a point onto the plane
def project_point(point):
x, y, z = point
t = (A*x + B*y + C*z + D) / (A**2 + B**2 + C**2)
return (x - A*t, y - B*t, z - C*t)
# Project vertices onto the plane and extract 2D coordinates
projected_vertices = {vid: project_point(np.array(v))[:2] for vid, v in vertices.items()}
# Compute the convex hull
points = np.array(list(projected_vertices.values()))
hull = ConvexHull(points)
# Map hull indices to vertex IDs
hull_indices = [list(projected_vertices.keys())[i] for i in hull.vertices]
# Reorder hull indices based on the prompt instructions
# Extract coordinates from projected_vertices using hull_indices
coords = [projected_vertices[idx] for idx in hull_indices]
# Sort hull_indices based on the x and y values assuming bottom right axes are both positive
sorted_hull_indices = sorted(hull_indices, key=lambda idx: (projected_vertices[idx][0], projected_vertices[idx][1]))
# Update hull_indices with the new sorted order
hull_indices = sorted_hull_indices
quadrilateral_edges = []
current_vertex = hull_indices[0]
last_vertex = 0
edge_num = 0
quadrilateral_edges = [[] for _ in range(4)]
while True:
neighbors = []
for edge in edges:
if current_vertex in edge:
if edge[0] == current_vertex:
neighbors.append(edge[1])
else:
neighbors.append(edge[0])
next_vertex = next(neighbor for neighbor in neighbors if neighbor != last_vertex)
last_vertex = current_vertex
quadrilateral_edges[edge_num].append(current_vertex)
if next_vertex in hull_indices:
quadrilateral_edges[edge_num].append(next_vertex)
edge_num += 1
current_vertex = next_vertex
if last_vertex != 0 and current_vertex == hull_indices[0]:
break
quadrilateral_points = []
for quad_edges in quadrilateral_edges:
edge_points = []
for vid in quad_edges:
edge_points.append((vid, projected_vertices[vid]))
quadrilateral_points.append(edge_points)
# quadrilateral_edges 0 is the top side, uv's 0,0 to 1,0
# quadrilateral_edges 1 is the right side, uv's 1,0 to 1,1
# quadrilateral_edges 2 is the bottom side, uv's 0,1 to 1,1
# quadrilateral_edges 3 is the left side, uv's 0,0 to 0,1
# Compute UV coordinates for each vertex based on their position along the quadrilateral edges
uv_coordinates = {}
for edge_index, quad_edge in enumerate(quadrilateral_points):
if edge_index == 0: # Top side, UVs from (0,0) to (1,0)
start_uv = np.array([0, 0])
end_uv = np.array([1, 0])
elif edge_index == 1: # Right side, UVs from (1,0) to (1,1)
start_uv = np.array([1, 0])
end_uv = np.array([1, 1])
elif edge_index == 2: # Bottom side, UVs from (1,1) to (0,1)
start_uv = np.array([1, 1])
end_uv = np.array([0, 1])
elif edge_index == 3: # Left side, UVs from (0,1) to (0,0)
start_uv = np.array([0, 1])
end_uv = np.array([0, 0])
for i, (vid, vertex) in enumerate(quad_edge):
if i == 0:
uv_coordinates[vid] = tuple(start_uv)
else:
# Calculate the UV based on the linear interpolation between start_uv and end_uv
t = i / (len(quad_edge) - 1)
interpolated_uv = (1 - t) * start_uv + t * end_uv
uv_coordinates[vid] = tuple(interpolated_uv)
# Assign material "RingOne" to the face and set the vertex UVs
material_name = "RingOne"
material = bpy.data.materials.get(material_name)
if material is None:
material = bpy.data.materials.new(name=material_name)
# Ensure the material is linked to the object
if material_name not in obj.data.materials:
obj.data.materials.append(material)
# Get the material index
material_index = obj.data.materials.find(material_name)
# Assign the material to the selected polygon
selected_poly.material_index = material_index
# Ensure the object has a UV map, if not, create one
if not obj.data.uv_layers:
obj.data.uv_layers.new()
uv_layer = obj.data.uv_layers.active.data
# Print out the uv_coordinates
for vertex_id, uv in uv_coordinates.items():
print(f"Vertex {vertex_id}: UV = {uv}")
# Get the active UV layer
uv_layer = bm.loops.layers.uv.active
# Assign UV coordinates to the vertices of the selected polygon
for loop in bm.faces[selected_poly.index].loops:
uv_coord = uv_coordinates[loop.vert.index]
loop[uv_layer].uv = uv_coord
# Update the mesh
bmesh.update_edit_mesh(mesh)
bpy.ops.object.mode_set(mode='OBJECT')