Repository navigation
Expand file tree
/
Copy pathextrudePlusPyramids.py
More file actions
138 lines (117 loc) · 4.48 KB
/
Copy pathextrudePlusPyramids.py
File metadata and controls
138 lines (117 loc) · 4.48 KB
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
import math
def read_obj(path):
vertices = []
faces = []
materials = []
current_material = None
with open(path, 'r') as f:
for line in f:
if line.startswith('v '):
_, x, y, z = line.strip().split()
vertices.append([float(x), float(y), float(z)])
elif line.startswith('f '):
parts = line.strip().split()[1:]
face = []
for part in parts:
indices = part.split('/')
v_idx = int(indices[0]) - 1
t_idx = int(indices[1]) - 1 if len(indices) > 1 and indices[1] else None
n_idx = int(indices[2]) - 1 if len(indices) > 2 and indices[2] else None
face.append((v_idx, t_idx, n_idx))
faces.append((face, current_material))
elif line.startswith('usemtl '):
parts = line.strip().split()
if len(parts) > 1:
current_material = parts[1]
else:
current_material = None
elif line.startswith('mtllib '):
materials.append(line.strip().split()[1])
return vertices, faces, materials
def write_obj(path, vertices, faces, materials=None):
with open(path, 'w') as f:
f.write('# Generated by extrusion script\n')
for v in vertices:
f.write(f'v {v[0]} {v[1]} {v[2]}\n')
if materials:
for mat in materials:
f.write(f'mtllib {mat}\n')
for face in faces:
face_indices, mat_name = face
if mat_name:
f.write(f'usemtl {mat_name}\n')
face_str = ' '.join([
f'{v+1}/{t+1 if t is not None else ""}/{n+1 if n is not None else ""}'
for v, t, n in face_indices
])
f.write(f'f {face_str}\n')
def cross(a, b):
return [
a[1]*b[2] - a[2]*b[1],
a[2]*b[0] - a[0]*b[2],
a[0]*b[1] - a[1]*b[0]
]
def normalize(v):
length = math.sqrt(sum(x*x for x in v))
if length == 0:
return [0, 0, 0]
return [x / length for x in v]
def vec_add(a, b):
return [a[i] + b[i] for i in range(len(a))]
def vec_sub(a, b):
return [a[i] - b[i] for i in range(len(a))]
def compute_face_normal(v1, v2, v3):
edge1 = vec_sub(v2, v1)
edge2 = vec_sub(v3, v1)
normal = cross(edge1, edge2)
return normalize(normal)
def compute_centroid(vertices, face_indices):
num_verts = len(face_indices)
centroid = [0.0, 0.0, 0.0]
for idx, _, _ in face_indices:
v = vertices[idx]
centroid = vec_add(centroid, v)
centroid = [c / num_verts for c in centroid]
return centroid
def extrude_face_to_pyramid(vertices, face_indices, height=3.0):
# Compute face centroid
centroid = compute_centroid(vertices, face_indices)
# Compute face normal
v0, _, _ = face_indices[0]
v1, _, _ = face_indices[1]
v2, _, _ = face_indices[2]
normal = compute_face_normal(vertices[v0], vertices[v1], vertices[v2])
# Scale normal by extrusion height
extrusion_vector = [n * height for n in normal]
# Extrude centroid
apex = vec_add(centroid, extrusion_vector)
return apex
def extrude_mesh_to_pyramids(vertices, faces, height=3.0):
new_vertices = []
new_faces = []
for face in faces:
face_indices, mat_name = face
if mat_name == 'roof':
# Compute apex of the pyramid
apex = extrude_face_to_pyramid(vertices, face_indices, height)
apex_index = len(vertices) + len(new_vertices)
new_vertices.append(apex)
# Create triangular faces from original vertices to apex
num_verts = len(face_indices)
for i in range(num_verts):
v1, t1, n1 = face_indices[i]
v2, t2, n2 = face_indices[(i+1) % num_verts]
new_faces.append(([(v1, t1, n1), (v2, t2, n2), (apex_index, None, None)], mat_name))
else:
new_faces.append((face_indices, mat_name))
return new_vertices, new_faces
# Main process
input_path = 'scuolaColorata.obj.txt'
output_path = 'scuolaColorata_pyramids.obj'
vertices, faces, materials = read_obj(input_path)
new_vertices, new_faces = extrude_mesh_to_pyramids(vertices, faces, height=8.0)
# Combine everything
final_vertices = vertices + new_vertices
final_faces = new_faces
write_obj(output_path, final_vertices, final_faces, materials)
print(f"Saved extruded mesh to '{output_path}'")