Spaces:
Paused
Paused
Add code/cube3d/render/render_fbx.py
Browse files- code/cube3d/render/render_fbx.py +107 -0
code/cube3d/render/render_fbx.py
ADDED
|
@@ -0,0 +1,107 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import bpy
|
| 2 |
+
import os
|
| 3 |
+
from mathutils import Vector
|
| 4 |
+
|
| 5 |
+
# 输入 .fbx 文件所在文件夹路径
|
| 6 |
+
fbx_folder = "/public/home/wangshuo/gap/assembly/data/ldr2fbx/" # 替换为你的文件夹路径
|
| 7 |
+
output_folder = "/public/home/wangshuo/gap/assembly/data/ldr2fbx/output_images/" # 输出图片的文件夹路径
|
| 8 |
+
|
| 9 |
+
# 创建输出文件夹(如果不存在)
|
| 10 |
+
if not os.path.exists(output_folder):
|
| 11 |
+
os.makedirs(output_folder)
|
| 12 |
+
|
| 13 |
+
# 获取文件夹中所有的 .fbx 文件
|
| 14 |
+
fbx_files = [f for f in os.listdir(fbx_folder) if f.endswith('.fbx')]
|
| 15 |
+
|
| 16 |
+
for fbx_file in fbx_files:
|
| 17 |
+
fbx_path = os.path.join(fbx_folder, fbx_file)
|
| 18 |
+
|
| 19 |
+
# 获取文件名前缀,用作图片文件名
|
| 20 |
+
output_png = os.path.join(output_folder, f"{os.path.splitext(fbx_file)[0]}.png")
|
| 21 |
+
|
| 22 |
+
# 检查文件是否存在
|
| 23 |
+
if not os.path.exists(fbx_path):
|
| 24 |
+
print(f"FBX file not found at {fbx_path}")
|
| 25 |
+
continue
|
| 26 |
+
|
| 27 |
+
# 清空场景
|
| 28 |
+
bpy.ops.object.select_all(action='SELECT')
|
| 29 |
+
bpy.ops.object.delete()
|
| 30 |
+
|
| 31 |
+
# 导入 .fbx 文件
|
| 32 |
+
bpy.ops.import_scene.fbx(filepath=fbx_path)
|
| 33 |
+
|
| 34 |
+
# 获取场景中的第一个物体
|
| 35 |
+
target_object = bpy.context.scene.objects[0] # 获取场景中的第一个物体
|
| 36 |
+
|
| 37 |
+
# 计算物体的边界框(bounding box)
|
| 38 |
+
bbox = [target_object.matrix_world @ Vector(corner) for corner in target_object.bound_box]
|
| 39 |
+
min_x = min(v.x for v in bbox)
|
| 40 |
+
max_x = max(v.x for v in bbox)
|
| 41 |
+
min_y = min(v.y for v in bbox)
|
| 42 |
+
max_y = max(v.y for v in bbox)
|
| 43 |
+
min_z = min(v.z for v in bbox)
|
| 44 |
+
max_z = max(v.z for v in bbox)
|
| 45 |
+
|
| 46 |
+
# 计算物体的中心点和大小
|
| 47 |
+
center = (min_x + max_x) / 2, (min_y + max_y) / 2, (min_z + max_z) / 2
|
| 48 |
+
size = max(max_x - min_x, max_y - min_y, max_z - min_z)
|
| 49 |
+
|
| 50 |
+
# 确保场景中有一个相机
|
| 51 |
+
camera = bpy.context.scene.camera
|
| 52 |
+
if not camera:
|
| 53 |
+
bpy.ops.object.camera_add(location=(0, -8, 5))
|
| 54 |
+
camera = bpy.context.object # 设置相机为当前场景的相机
|
| 55 |
+
bpy.context.scene.camera = camera # 设置当前相机
|
| 56 |
+
|
| 57 |
+
# 设置相机位置(确保相机能看到整个物体)
|
| 58 |
+
camera.location = (center[0], center[1] - size * 6, center[2] + size) # 距离物体足够远
|
| 59 |
+
camera.rotation_euler = (1.1, 0, 0) # 使相机朝向物体
|
| 60 |
+
|
| 61 |
+
|
| 62 |
+
# 使用 Track To 约束让相机始终朝向物体
|
| 63 |
+
track_to_constraint = camera.constraints.new(type='TRACK_TO')
|
| 64 |
+
track_to_constraint.target = target_object
|
| 65 |
+
track_to_constraint.up_axis = 'UP_Y' # 确保相机正确对齐
|
| 66 |
+
track_to_constraint.track_axis = 'TRACK_NEGATIVE_Z' # 改为 track_axis
|
| 67 |
+
|
| 68 |
+
# # 更新相机,确保 Track To 约束生效后才进行旋转
|
| 69 |
+
# bpy.context.view_layer.update()
|
| 70 |
+
|
| 71 |
+
# # 在 Track To 约束生效后,绕 Z 轴旋转相机 45 度
|
| 72 |
+
# camera.rotation_euler[2] += 3.14 / 4 # 让相机绕 Z 轴旋转 45 度
|
| 73 |
+
|
| 74 |
+
|
| 75 |
+
# 设置渲染引擎(可以使用 Cycles 或 Eevee)
|
| 76 |
+
scene = bpy.context.scene
|
| 77 |
+
scene.render.engine = "CYCLES" # 或 "BLENDER_EEVEE"
|
| 78 |
+
scene.cycles.samples = 128 # 增加样本数
|
| 79 |
+
scene.render.resolution_x = 1024 # 设置分辨率
|
| 80 |
+
scene.render.resolution_y = 1024
|
| 81 |
+
scene.render.filepath = output_png
|
| 82 |
+
|
| 83 |
+
scene.cycles.device = 'GPU' # 设置为 GPU
|
| 84 |
+
if bpy.context.scene.cycles.device == 'GPU':
|
| 85 |
+
print("GPU rendering enabled")
|
| 86 |
+
else:
|
| 87 |
+
print("GPU not available, using CPU instead")
|
| 88 |
+
|
| 89 |
+
# 添加太阳光源
|
| 90 |
+
bpy.ops.object.light_add(type='SUN', location=(5, -5, 10))
|
| 91 |
+
light = bpy.context.object
|
| 92 |
+
light.data.energy = 10 # 增加光源强度
|
| 93 |
+
|
| 94 |
+
# 设置背景色(白色背景)
|
| 95 |
+
if scene.world is None:
|
| 96 |
+
bpy.ops.world.new() # 创建一个新的世界背景设置
|
| 97 |
+
scene.world.color = (1, 1, 1) # 设置背景颜色为白色
|
| 98 |
+
|
| 99 |
+
# 启用环境光
|
| 100 |
+
scene.world.use_nodes = True
|
| 101 |
+
world_nodes = scene.world.node_tree.nodes
|
| 102 |
+
background_node = world_nodes.get("Background")
|
| 103 |
+
background_node.inputs["Color"].default_value = (1, 1, 1, 1) # 设置背景为白色
|
| 104 |
+
|
| 105 |
+
# 渲染
|
| 106 |
+
bpy.ops.render.render(write_still=True)
|
| 107 |
+
print(f"Rendering complete for {fbx_file}, saved as {output_png}")
|