bioops-twin / generate_obj_improved.py
BioOps Team
Update centrifuge 3D model to v3 GLB with materials
17e2e1f
Raw
History Blame Contribute Delete
5.81 kB
import math
import os
filepath = "/mnt/36270add-d8d7-4990-b2b6-c9c5f803b31b/Hackatones/Transforming Enterprise Through AI/Repo/assets/centrifuge_v2.obj"
mtlpath = "/mnt/36270add-d8d7-4990-b2b6-c9c5f803b31b/Hackatones/Transforming Enterprise Through AI/Repo/assets/centrifuge_v2.mtl"
with open(mtlpath, 'w') as f:
f.write("""newmtl RotorBody
Kd 0.75 0.75 0.78
Ks 0.3 0.3 0.3
Ns 30
newmtl RotorHub
Kd 0.25 0.25 0.25
Ks 0.8 0.8 0.8
Ns 100
newmtl Tube
Kd 0.15 0.45 0.85
Ks 0.9 0.9 0.9
Ns 80
newmtl TubeCap
Kd 0.9 0.1 0.1
Ks 0.5 0.5 0.5
Ns 50
""")
vertices = []
faces_and_mtls = []
def add_vertex(x, y, z):
vertices.append((x, y, z))
return len(vertices)
def add_face(v_indices):
faces_and_mtls.append(v_indices)
def set_material(name):
faces_and_mtls.append(f"usemtl {name}")
def multiply_matrix_vector(matrix, vector):
return [
matrix[0][0]*vector[0] + matrix[0][1]*vector[1] + matrix[0][2]*vector[2],
matrix[1][0]*vector[0] + matrix[1][1]*vector[1] + matrix[1][2]*vector[2],
matrix[2][0]*vector[0] + matrix[2][1]*vector[1] + matrix[2][2]*vector[2]
]
def create_rotated_cylinder(cx, cy, cz, r_bottom, r_top, h, angle_y, angle_tilt, segments=24):
mat_tilt = [
[1, 0, 0],
[0, math.cos(angle_tilt), -math.sin(angle_tilt)],
[0, math.sin(angle_tilt), math.cos(angle_tilt)]
]
mat_y = [
[math.cos(angle_y), 0, math.sin(angle_y)],
[0, 1, 0],
[-math.sin(angle_y), 0, math.cos(angle_y)]
]
def transform(x, y, z):
v = [x, y, z]
v = multiply_matrix_vector(mat_tilt, v)
v = multiply_matrix_vector(mat_y, v)
return (v[0]+cx, v[1]+cy, v[2]+cz)
bc = add_vertex(*transform(0, 0, 0))
tc = add_vertex(*transform(0, h, 0))
base_indices = []
top_indices = []
for i in range(segments):
theta = 2.0 * math.pi * i / segments
lx = r_bottom * math.cos(theta)
lz = r_bottom * math.sin(theta)
base_indices.append(add_vertex(*transform(lx, 0, lz)))
tx = r_top * math.cos(theta)
tz = r_top * math.sin(theta)
top_indices.append(add_vertex(*transform(tx, h, tz)))
for i in range(segments):
n1 = i
n2 = (i+1)%segments
add_face([bc, base_indices[n2], base_indices[n1]])
for i in range(segments):
n1 = i
n2 = (i+1)%segments
add_face([tc, top_indices[n1], top_indices[n2]])
for i in range(segments):
n1 = i
n2 = (i+1)%segments
add_face([base_indices[n1], base_indices[n2], top_indices[n2], top_indices[n1]])
def create_cylinder(x, y, z, r_bottom, r_top, h, segments=48):
create_rotated_cylinder(x, y, z, r_bottom, r_top, h, 0, 0, segments)
# Build the geometry
set_material("RotorBody")
# Base flat cylinder
create_cylinder(0, 0, 0, 1.2, 1.2, 0.15, 64)
# Main conical body
create_cylinder(0, 0.15, 0, 1.2, 0.7, 0.6, 64)
# Top flat part
create_cylinder(0, 0.75, 0, 0.7, 0.6, 0.1, 64)
set_material("RotorHub")
# Hub spindle
create_cylinder(0, 0.85, 0, 0.15, 0.15, 0.15, 32)
# Spindle nut
create_cylinder(0, 1.0, 0, 0.08, 0.08, 0.08, 16)
# Create tubes (angled)
num_tubes = 12
tube_radius = 0.14
tube_height = 0.4
tilt = math.radians(40) # 40 degrees tilt
for i in range(num_tubes):
angle_y = 2.0 * math.pi * i / num_tubes
# Position: shift outwards and upwards
# We want the tubes to be embedded in the sloped face.
# The sloped face goes from r=1.2 at y=0.15 to r=0.7 at y=0.75.
# Let's put the center of the tube cap at r=0.8, y=0.65
r_pos = 0.85
y_pos = 0.6
cx = r_pos * math.cos(angle_y)
cz = -r_pos * math.sin(angle_y) # negative to match rotation direction if needed
set_material("Tube")
# Actually the tube goes INWARDS. So the cylinder should start at cap and go down?
# Our cylinder starts at (cx, cy, cz) and goes UP locally.
# If we want it to go down, we can start low and go up to cap.
# Let's start the tube deep inside and go up to the cap surface.
# To do this, we'll start at cx, cy, cz and go UP by tube_height.
# Wait, the tilt is around X axis. Positive tilt tilts +Y towards +Z.
# Let's just adjust the start position so it protrudes perfectly.
start_r = 0.5
start_y = 0.3
sx = start_r * math.cos(angle_y)
sz = start_r * math.sin(angle_y)
create_rotated_cylinder(sx, start_y, sz, tube_radius, tube_radius, tube_height, -angle_y, tilt, 16)
# Add a tube cap
set_material("TubeCap")
# Cap is at local top.
# We can just create another small cylinder at the top of the tube.
# The local Y of the top is tube_height. We can just shift our start position locally.
# Local shift:
# v = [0, tube_height, 0]
# transformed:
mat_tilt = [
[1, 0, 0],
[0, math.cos(tilt), -math.sin(tilt)],
[0, math.sin(tilt), math.cos(tilt)]
]
mat_y = [
[math.cos(-angle_y), 0, math.sin(-angle_y)],
[0, 1, 0],
[-math.sin(-angle_y), 0, math.cos(-angle_y)]
]
v = multiply_matrix_vector(mat_tilt, [0, tube_height, 0])
v = multiply_matrix_vector(mat_y, v)
cap_x = sx + v[0]
cap_y = start_y + v[1]
cap_z = sz + v[2]
create_rotated_cylinder(cap_x, cap_y, cap_z, tube_radius*1.1, tube_radius*1.1, 0.05, -angle_y, tilt, 16)
with open(filepath, 'w') as f:
f.write(f"mtllib centrifuge_v2.mtl\n")
f.write("o CentrifugeRotor\n")
for v in vertices:
f.write(f"v {v[0]:.5f} {v[1]:.5f} {v[2]:.5f}\n")
for item in faces_and_mtls:
if isinstance(item, str):
f.write(item + "\n")
else:
f.write("f " + " ".join(str(idx) for idx in item) + "\n")
print("Detailed 3D model generated.")