Files
FiDA-3D-Trellis/render_model.py
2026-04-13 11:21:42 +08:00

117 lines
3.2 KiB
Python
Executable File

import subprocess
import bpy
import os
import sys
from mathutils import Vector
def clear_scene():
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete(use_global=False)
def import_model(model_path):
ext = os.path.splitext(model_path)[1].lower()
if ext == ".obj":
bpy.ops.wm.obj_import(filepath=model_path)
elif ext in [".glb", ".gltf"]:
bpy.ops.import_scene.gltf(filepath=model_path)
else:
raise ValueError(f"Unsupported format: {ext}")
def get_scene_bbox():
objs = [obj for obj in bpy.context.scene.objects if obj.type == 'MESH']
if not objs:
raise RuntimeError("No mesh objects found")
min_corner = Vector((float("inf"), float("inf"), float("inf")))
max_corner = Vector((float("-inf"), float("-inf"), float("-inf")))
for obj in objs:
for v in obj.bound_box:
world_v = obj.matrix_world @ Vector(v)
min_corner.x = min(min_corner.x, world_v.x)
min_corner.y = min(min_corner.y, world_v.y)
min_corner.z = min(min_corner.z, world_v.z)
max_corner.x = max(max_corner.x, world_v.x)
max_corner.y = max(max_corner.y, world_v.y)
max_corner.z = max(max_corner.z, world_v.z)
return min_corner, max_corner
def normalize_model():
min_corner, max_corner = get_scene_bbox()
center = (min_corner + max_corner) / 2
size = max(max_corner.x - min_corner.x,
max(max_corner.y - min_corner.y, max_corner.z - min_corner.z))
objs = [obj for obj in bpy.context.scene.objects if obj.type == 'MESH']
for obj in objs:
obj.location -= center
if size > 0:
scale = 2.0 / size
for obj in objs:
obj.scale *= scale
bpy.context.view_layer.update()
def add_camera():
bpy.ops.object.camera_add(location=(2.5, -2.5, 2.0))
cam = bpy.context.active_object
direction = Vector((0, 0, 0)) - cam.location
cam.rotation_euler = direction.to_track_quat('-Z', 'Y').to_euler()
bpy.context.scene.camera = cam
def add_light():
bpy.ops.object.light_add(type='SUN', location=(5, -5, 8))
bpy.context.active_object.data.energy = 3.0
bpy.ops.object.light_add(type='AREA', location=(3, -3, 3))
area = bpy.context.active_object
area.data.energy = 3000
area.data.size = 5
def setup_render(output_path, resolution=1024):
scene = bpy.context.scene
scene.render.engine = 'CYCLES'
scene.cycles.samples = 128
scene.render.filepath = output_path
scene.render.image_settings.file_format = 'PNG'
scene.render.resolution_x = resolution
scene.render.resolution_y = resolution
scene.render.film_transparent = True
def parse_args():
argv = sys.argv
argv = argv[argv.index("--") + 1:] if "--" in argv else []
if len(argv) < 2:
raise ValueError("Usage: blender -b -P render_model.py -- model_path output_path")
return argv[0], argv[1]
def get_static_model_image():
model_path, output_path = parse_args()
clear_scene()
import_model(model_path)
normalize_model()
add_camera()
add_light()
setup_render(output_path)
bpy.ops.render.render(write_still=True)
print(f"Saved to {output_path}")
if __name__ == "__main__":
get_static_model_image()