774 lines
30 KiB
Python
774 lines
30 KiB
Python
#!/usr/bin/env python3
|
||
# -*- coding: utf-8 -*-
|
||
"""
|
||
Blender 4.2兼容版自动化脚本(白模版本)
|
||
自动创建等轴测房间并渲染白模
|
||
"""
|
||
|
||
import subprocess
|
||
import os
|
||
import sys
|
||
|
||
# Blender可执行文件路径
|
||
BLENDER_PATH = r"D:\Program Files\Blender Foundation\blender-4.2.11-windows-x64\blender.exe"
|
||
|
||
# 简化版Blender脚本(只渲染白模)
|
||
BLENDER_SIMPLE_SCRIPT = '''
|
||
import bpy
|
||
import bmesh
|
||
import os
|
||
import math
|
||
import time
|
||
|
||
def disable_problematic_addons():
|
||
"""禁用可能导致问题的插件"""
|
||
try:
|
||
# 禁用可能冲突的插件
|
||
problematic_addons = ['bl_tool']
|
||
for addon in problematic_addons:
|
||
if addon in bpy.context.preferences.addons:
|
||
bpy.ops.preferences.addon_disable(module=addon)
|
||
print(f"已禁用插件: {addon}")
|
||
except:
|
||
pass
|
||
|
||
def create_isometric_room():
|
||
"""创建等轴测房间,使用isometric_room_gen插件"""
|
||
try:
|
||
# 禁用问题插件
|
||
#disable_problematic_addons()
|
||
|
||
# 清除默认立方体
|
||
if "Cube" in bpy.data.objects:
|
||
bpy.data.objects.remove(bpy.data.objects["Cube"], do_unlink=True)
|
||
|
||
# 设置3D游标位置到原点
|
||
bpy.context.scene.cursor.location = (0.0, 0.0, 0.0)
|
||
|
||
# 检查isometric_room_gen插件
|
||
if not hasattr(bpy.context.scene, 'sna_room_width'):
|
||
print("错误: isometric_room_gen插件未正确加载")
|
||
return False
|
||
|
||
# 设置isometric_room_gen插件参数
|
||
# 房间设置
|
||
bpy.context.scene.sna_wall_thickness = 0.10 # 墙体厚度10cm
|
||
bpy.context.scene.sna_room_width = 5.0 # 房间宽度8米
|
||
bpy.context.scene.sna_room_depth = 8.0 # 房间深度4米
|
||
bpy.context.scene.sna_room_height = 3.0 # 房间高度3米
|
||
|
||
# 窗户设置 - 不设置窗户
|
||
bpy.context.scene.sna_windows_enum = 'NONE' # 无窗户
|
||
|
||
# 设置房间类型为方形
|
||
bpy.context.scene.sna_style = 'Square'
|
||
|
||
# 找到3D视图区域
|
||
view3d_area = None
|
||
for area in bpy.context.screen.areas:
|
||
if area.type == 'VIEW_3D':
|
||
view3d_area = area
|
||
break
|
||
|
||
if view3d_area is None:
|
||
print("错误: 找不到3D视图区域")
|
||
return False
|
||
|
||
# 临时切换到3D视图上下文
|
||
with bpy.context.temp_override(area=view3d_area):
|
||
# 使用isometric_room_gen插件创建房间
|
||
result = bpy.ops.sna.gen_room_1803a()
|
||
|
||
if result == {'FINISHED'}:
|
||
print("等轴测房间创建完成!")
|
||
print(f"房间尺寸: {bpy.context.scene.sna_room_width}m x {bpy.context.scene.sna_room_depth}m x {bpy.context.scene.sna_room_height}m")
|
||
print(f"墙体厚度: {bpy.context.scene.sna_wall_thickness}m")
|
||
|
||
# 将生成的房间在Z轴上向下移动墙体厚度的距离
|
||
wall_thickness = bpy.context.scene.sna_wall_thickness
|
||
|
||
# 查找生成的房间对象
|
||
room_object = None
|
||
for obj in bpy.data.objects:
|
||
if obj.name == "IRG_IsoRoom_WithCeiling":
|
||
room_object = obj
|
||
break
|
||
|
||
|
||
return True
|
||
else:
|
||
print("房间创建失败")
|
||
return False
|
||
|
||
except Exception as e:
|
||
print(f"创建房间时出现错误: {str(e)}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def create_window_with_archimesh():
|
||
"""使用archimesh插件创建落地窗"""
|
||
try:
|
||
print("开始创建archimesh落地窗...")
|
||
|
||
# 检查archimesh插件是否可用
|
||
if not hasattr(bpy.ops.mesh, 'archimesh_winpanel'):
|
||
print("错误: archimesh插件未正确加载")
|
||
print("请确保archimesh插件已安装并启用")
|
||
return False
|
||
|
||
# 设置3D游标到原点
|
||
bpy.context.scene.cursor.location = (0.0, 0.0, 0.0)
|
||
|
||
# 找到3D视图区域
|
||
view3d_area = None
|
||
for area in bpy.context.screen.areas:
|
||
if area.type == 'VIEW_3D':
|
||
view3d_area = area
|
||
break
|
||
|
||
if view3d_area is None:
|
||
print("错误: 找不到3D视图区域")
|
||
return False
|
||
|
||
# 临时切换到3D视图上下文
|
||
with bpy.context.temp_override(area=view3d_area):
|
||
# 创建窗户
|
||
result = bpy.ops.mesh.archimesh_winpanel()
|
||
|
||
if result == {'FINISHED'}:
|
||
print("archimesh落地窗创建完成!")
|
||
|
||
# 等待一帧以确保对象创建完成
|
||
bpy.context.view_layer.update()
|
||
|
||
# 找到刚创建的窗户组对象(Window_Group)
|
||
window_group = None
|
||
for obj in bpy.data.objects:
|
||
if obj.name == "Window_Group":
|
||
window_group = obj
|
||
break
|
||
|
||
if window_group:
|
||
print(f"找到窗户组: {window_group.name}")
|
||
|
||
# 查找主窗户对象(Window)
|
||
main_window_obj = None
|
||
for obj in bpy.data.objects:
|
||
if obj.name == "Window":
|
||
main_window_obj = obj
|
||
break
|
||
|
||
if main_window_obj and hasattr(main_window_obj, 'WindowPanelGenerator'):
|
||
# 获取窗户属性
|
||
window_props = main_window_obj.WindowPanelGenerator[0]
|
||
|
||
print("设置窗户属性...")
|
||
print(f"找到主窗户对象: {main_window_obj.name}")
|
||
|
||
# 设置窗户的基本属性
|
||
window_props.gen = 4 # 4扇窗户(水平)
|
||
window_props.yuk = 1 # 1行(垂直)
|
||
window_props.kl1 = 5 # 外框厚度5cm
|
||
window_props.kl2 = 5 # 竖框厚度5cm
|
||
window_props.fk = 2 # 内框厚度2cm
|
||
|
||
# 设置窗户尺寸
|
||
window_props.gnx0 = 80 # 第1扇窗户宽度80cm
|
||
window_props.gnx1 = 80 # 第2扇窗户宽度80cm
|
||
window_props.gnx2 = 80 # 第3扇窗户宽度80cm
|
||
window_props.gnx3 = 80 # 第4扇窗户宽度80cm
|
||
window_props.gny0 = 250 # 窗户高度250cm(落地窗)
|
||
|
||
# 设置窗户类型为平窗
|
||
window_props.UST = '1' # 平窗
|
||
window_props.r = 0 # 旋转角度0度
|
||
|
||
# 设置窗台
|
||
window_props.mr = True # 启用窗台
|
||
window_props.mr1 = 4 # 窗台高度4cm
|
||
window_props.mr2 = 4 # 窗台深度4cm
|
||
window_props.mr3 = 20 # 窗台宽度20cm
|
||
window_props.mr4 = 0 # 窗台延伸0cm
|
||
|
||
# 设置材质
|
||
window_props.mt1 = '1' # 外框材质PVC
|
||
window_props.mt2 = '1' # 内框材质塑料
|
||
|
||
# 设置窗户开启状态
|
||
window_props.k00 = True # 第1扇窗户开启
|
||
window_props.k01 = True # 第2扇窗户开启
|
||
window_props.k02 = True # 第3扇窗户开启
|
||
window_props.k03 = True # 第4扇窗户开启(如果有的话)
|
||
|
||
print(f"窗户属性设置完成:")
|
||
print(f" - 水平扇数: {window_props.gen}")
|
||
print(f" - 垂直行数: {window_props.yuk}")
|
||
print(f" - 外框厚度: {window_props.kl1}cm")
|
||
print(f" - 竖框厚度: {window_props.kl2}cm")
|
||
print(f" - 内框厚度: {window_props.fk}cm")
|
||
print(f" - 窗户高度: {window_props.gny0}cm")
|
||
print(f" - 窗户类型: 平窗")
|
||
print(f" - 窗台: 启用")
|
||
print(f" - 窗户开启状态: k00={window_props.k00}, k01={window_props.k01}, k02={window_props.k02}, k03={window_props.k03}")
|
||
|
||
|
||
# 修复窗户玻璃材质
|
||
print("修复窗户玻璃材质...")
|
||
fix_window_glass_material()
|
||
|
||
# 等待更新完成
|
||
bpy.context.view_layer.update()
|
||
|
||
# 强制触发更新(如果需要)
|
||
try:
|
||
# 重新设置属性以触发更新
|
||
current_gen = window_props.gen
|
||
current_gny0 = window_props.gny0
|
||
|
||
window_props.gen = 2 # 临时设置为其他值
|
||
bpy.context.view_layer.update()
|
||
|
||
window_props.gen = current_gen # 设置回目标值
|
||
bpy.context.view_layer.update()
|
||
|
||
print("已强制触发窗户更新")
|
||
|
||
except Exception as update_error:
|
||
print(f"强制更新时出现错误: {update_error}")
|
||
|
||
# 在修改落地窗全部属性后进行位移和旋转
|
||
print("开始移动和旋转窗户组...")
|
||
try:
|
||
window_group1 = None
|
||
|
||
for obj in bpy.data.objects:
|
||
if obj.name == "Window_Group":
|
||
window_group1 = obj
|
||
break
|
||
|
||
# 设置位置
|
||
window_group1.location = (0, 4.0, 0.0)
|
||
print(f"已将窗户组移动到位置: {window_group1.location}")
|
||
|
||
# 设置旋转
|
||
window_group1.rotation_euler = (math.radians(0), math.radians(0), math.radians(90)) # 旋转(0, 0, 90度)
|
||
print(f"已将窗户组旋转到: (0°, 0°, 90°)")
|
||
|
||
# 强制更新
|
||
bpy.context.view_layer.update()
|
||
print("窗户组位移和旋转完成")
|
||
|
||
except Exception as move_error:
|
||
print(f"移动和旋转窗户组时出现错误: {move_error}")
|
||
|
||
else:
|
||
print("警告: 未找到主窗户对象或WindowPanelGenerator属性")
|
||
# 尝试查找其他可能的窗户属性
|
||
for obj in bpy.data.objects:
|
||
if hasattr(obj, 'archimesh_window'):
|
||
print(f"找到archimesh_window属性在对象: {obj.name}")
|
||
|
||
# 打印窗户组的所有子对象信息
|
||
print("窗户组包含的对象:")
|
||
for obj in bpy.data.objects:
|
||
if obj.parent == window_group:
|
||
print(f" - {obj.name} (位置: {obj.location})")
|
||
|
||
|
||
return True
|
||
else:
|
||
print("警告: 未找到Window_Group对象")
|
||
# 尝试查找其他可能的窗户对象
|
||
window_objects = [obj for obj in bpy.data.objects if "Window" in obj.name]
|
||
if window_objects:
|
||
print("找到的窗户相关对象:")
|
||
for obj in window_objects:
|
||
print(f" - {obj.name} (类型: {obj.type})")
|
||
|
||
# 尝试移动第一个找到的窗户对象
|
||
first_window = window_objects[0]
|
||
first_window.location = (0.0, 1.96, 0.0)
|
||
print(f"已移动 {first_window.name} 到位置: {first_window.location}")
|
||
return True
|
||
else:
|
||
print("未找到任何窗户相关对象")
|
||
return False
|
||
|
||
|
||
|
||
else:
|
||
print("窗户创建失败")
|
||
return False
|
||
|
||
except Exception as e:
|
||
print(f"创建窗户时出现错误: {str(e)}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
|
||
def fix_window_glass_material():
|
||
"""修复窗户玻璃材质,将其改为高透BSDF"""
|
||
try:
|
||
print("开始修复窗户玻璃材质...")
|
||
|
||
# 查找Window_Group下的Window对象
|
||
window_group = None
|
||
for obj in bpy.data.objects:
|
||
if obj.name == "Window_Group":
|
||
window_group = obj
|
||
break
|
||
|
||
if not window_group:
|
||
print("未找到Window_Group对象")
|
||
return False
|
||
|
||
# 查找Window对象(Window_Group的子对象)
|
||
window_obj = None
|
||
for obj in bpy.data.objects:
|
||
if obj.name == "Window" and obj.parent == window_group:
|
||
window_obj = obj
|
||
break
|
||
|
||
|
||
if not window_obj:
|
||
print("未找到Window对象")
|
||
return False
|
||
|
||
print(f"找到Window对象: {window_obj.name}")
|
||
|
||
# 检查Window对象的材质
|
||
if not window_obj.material_slots:
|
||
print("Window对象没有材质槽")
|
||
return False
|
||
|
||
# 遍历所有材质槽
|
||
for slot in window_obj.material_slots:
|
||
if slot.material and "Glass" in slot.material.name:
|
||
print(f"找到Glass材质: {slot.material.name}")
|
||
|
||
# 启用节点编辑
|
||
slot.material.use_nodes = True
|
||
|
||
# 清除所有现有节点
|
||
slot.material.node_tree.nodes.clear()
|
||
|
||
# 创建半透BSDF节点
|
||
translucent_bsdf = slot.material.node_tree.nodes.new(type='ShaderNodeBsdfTranslucent')
|
||
translucent_bsdf.location = (0, 0)
|
||
|
||
# 设置半透BSDF参数
|
||
translucent_bsdf.inputs['Color'].default_value = (0.95, 0.98, 1.0, 1.0) # 几乎无色
|
||
# 半透BSDF节点没有Weight参数,只有Color参数
|
||
|
||
# 创建材质输出节点
|
||
material_output = slot.material.node_tree.nodes.new(type='ShaderNodeOutputMaterial')
|
||
material_output.location = (300, 0)
|
||
|
||
# 连接节点
|
||
slot.material.node_tree.links.new(
|
||
translucent_bsdf.outputs['BSDF'],
|
||
material_output.inputs['Surface']
|
||
)
|
||
|
||
# 设置材质混合模式为Alpha Blend
|
||
slot.material.blend_method = 'BLEND'
|
||
|
||
print(f"已成功修改Glass材质为半透BSDF")
|
||
print(f" - 半透颜色: 几乎无色")
|
||
print(f" - 混合模式: Alpha Blend")
|
||
|
||
return True
|
||
|
||
print("未找到Glass材质")
|
||
return False
|
||
|
||
except Exception as e:
|
||
print(f"修复玻璃材质时出现错误: {str(e)}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
def setup_render_settings():
|
||
"""设置渲染参数(EEVEE渲染,优化速度)"""
|
||
scene = bpy.context.scene
|
||
|
||
# 设置渲染引擎为EEVEE
|
||
scene.render.engine = 'BLENDER_EEVEE_NEXT'
|
||
print("已设置渲染引擎为EEVEE")
|
||
|
||
# 设置世界环境
|
||
if hasattr(scene, 'world') and scene.world:
|
||
# 启用世界节点
|
||
scene.world.use_nodes = True
|
||
|
||
# 清除现有节点
|
||
scene.world.node_tree.nodes.clear()
|
||
|
||
# 创建自发光节点
|
||
emission_node = scene.world.node_tree.nodes.new(type='ShaderNodeEmission')
|
||
emission_node.location = (0, 0)
|
||
|
||
# 设置HSV颜色:色相0,饱和度0,明度0.051,Alpha 1
|
||
# 转换为RGB:HSV(0, 0, 0.051) = RGB(0.051, 0.051, 0.051)
|
||
emission_node.inputs['Color'].default_value = (0.051, 0.051, 0.051, 1.0) # 深灰色
|
||
emission_node.inputs['Strength'].default_value = 7.0 # 强度7
|
||
|
||
# 创建世界输出节点
|
||
world_output = scene.world.node_tree.nodes.new(type='ShaderNodeOutputWorld')
|
||
world_output.location = (300, 0)
|
||
|
||
# 连接节点
|
||
scene.world.node_tree.links.new(
|
||
emission_node.outputs['Emission'],
|
||
world_output.inputs['Surface']
|
||
)
|
||
|
||
print("已设置世界环境为自发光")
|
||
print(f" - 颜色: HSV(0, 0, 0.051) = RGB(0.051, 0.051, 0.051)")
|
||
print(f" - 强度: 7.0")
|
||
|
||
# 设置EEVEE采样(降低采样数提高速度)
|
||
try:
|
||
if hasattr(scene.eevee, 'taa_render_samples'):
|
||
scene.eevee.taa_render_samples = 32 # 从64降低到32
|
||
print(f"已设置EEVEE渲染采样: {scene.eevee.taa_render_samples}")
|
||
elif hasattr(scene.eevee, 'taa_samples'):
|
||
scene.eevee.taa_samples = 32 # 从64降低到32
|
||
print(f"已设置EEVEE采样: {scene.eevee.taa_samples}")
|
||
else:
|
||
print("警告: 无法找到EEVEE采样设置,使用默认值")
|
||
|
||
# 启用屏幕空间反射(简化设置)
|
||
if hasattr(scene.eevee, 'use_ssr'):
|
||
scene.eevee.use_ssr = True
|
||
print("已启用屏幕空间反射")
|
||
|
||
# 启用环境光遮蔽(简化设置)
|
||
if hasattr(scene.eevee, 'use_gtao'):
|
||
scene.eevee.use_gtao = True
|
||
print("已启用环境光遮蔽")
|
||
|
||
# 启用透明渲染(必要)
|
||
if hasattr(scene.eevee, 'use_transparent'):
|
||
scene.eevee.use_transparent = True
|
||
print("已启用透明渲染")
|
||
|
||
# 设置透明混合模式(必要)
|
||
if hasattr(scene.render, 'film_transparent'):
|
||
scene.render.film_transparent = True
|
||
print("已启用透明背景")
|
||
|
||
except AttributeError as e:
|
||
print(f"EEVEE设置警告: {e}")
|
||
print("使用默认EEVEE渲染设置")
|
||
|
||
# 设置分辨率
|
||
scene.render.resolution_x = 1080 # 宽度:1080px
|
||
scene.render.resolution_y = 2400 # 高度:2400px
|
||
scene.render.resolution_percentage = 100
|
||
|
||
# 设置输出格式
|
||
scene.render.image_settings.file_format = 'PNG'
|
||
scene.render.image_settings.color_mode = 'RGBA' # 支持透明
|
||
|
||
# 设置输出路径到桌面
|
||
desktop_path = os.path.join(os.path.expanduser("~"), "Desktop")
|
||
timestamp = time.strftime("%m%d_%H%M%S") # 日期_时分秒格式
|
||
filename = f"isometric_{timestamp}.png"
|
||
scene.render.filepath = os.path.join(desktop_path, filename)
|
||
|
||
print(f"EEVEE渲染设置完成,输出路径: {scene.render.filepath}")
|
||
return scene.render.filepath
|
||
|
||
def setup_camera_and_lighting():
|
||
"""设置摄像机和照明(160W点光源 + 150W日光)"""
|
||
# 计算灯光高度(房间高度减一米)
|
||
room_height = 3.0
|
||
light_height = room_height - 1.0
|
||
|
||
# 设置摄像机
|
||
camera = None
|
||
if "Camera" in bpy.data.objects:
|
||
camera = bpy.data.objects["Camera"]
|
||
elif "Isometric Camera" in bpy.data.objects:
|
||
camera = bpy.data.objects["Isometric Camera"]
|
||
else:
|
||
# 创建新摄像机
|
||
bpy.ops.object.camera_add(location=(7, -7, 5))
|
||
camera = bpy.context.active_object
|
||
camera.name = "Isometric Camera"
|
||
|
||
# 设置摄像机位置和旋转
|
||
# 房间宽度5.0米,相机位置调整为(房间宽度-1, 1, 1.3)
|
||
room_width = 5.0
|
||
camera.location = (room_width - 1, 1, 1.3) # 相机位置:(4, 1, 1.3)
|
||
camera.rotation_euler = (math.radians(90), math.radians(0), math.radians(45)) # 相机旋转
|
||
|
||
# 设置为透视投影
|
||
camera.data.type = 'PERSP'
|
||
camera.data.lens = 35.0 # 35mm焦距
|
||
camera.data.sensor_width = 35.0 # 35mm传感器
|
||
camera.data.sensor_fit = 'AUTO' # 自动适配
|
||
|
||
# 设置为场景的活动摄像机
|
||
bpy.context.scene.camera = camera
|
||
print("摄像机设置完成")
|
||
print(f"相机位置: ({camera.location.x}, {camera.location.y}, {camera.location.z})")
|
||
|
||
# 隐藏ISO Emission灯光(如果存在)
|
||
light_objects = ["ISO Emission Left", "ISO Emission Right"]
|
||
for obj_name in light_objects:
|
||
if obj_name in bpy.data.objects:
|
||
light_obj = bpy.data.objects[obj_name]
|
||
# 隐藏发光对象
|
||
light_obj.hide_render = True
|
||
light_obj.hide_viewport = True
|
||
print(f"已隐藏 {obj_name}")
|
||
|
||
# 创建第一个160W点光源(房间中心)
|
||
# try:
|
||
# # 计算点光源位置(房间中心上方)
|
||
# room_length = 4.0 # Y轴
|
||
# room_width = 8.0 # X轴(4+4)
|
||
|
||
# # 第一个点光源位置:房间中心上方
|
||
# light_x = 0 # X轴中心
|
||
# light_y = 0 # Y轴中心
|
||
# light_z = light_height
|
||
|
||
# # 创建第一个点光源
|
||
# bpy.ops.object.light_add(type='POINT', location=(light_x, light_y, light_z))
|
||
# point_light1 = bpy.context.active_object
|
||
# point_light1.name = "Main Point Light"
|
||
# point_light1.data.energy = 160 # 160W
|
||
|
||
# # 设置软衰减(简化设置)
|
||
# point_light1.data.shadow_soft_size = 0.5 # 0.5米半径,产生柔和阴影
|
||
# point_light1.data.use_shadow = True # 启用阴影
|
||
|
||
# print(f"已创建第一个点光源(160W)")
|
||
# print(f"点光源位置: x={light_x}, y={light_y}, z={light_z}")
|
||
|
||
# except Exception as e:
|
||
# print(f"创建第一个点光源时出错: {e}")
|
||
|
||
# 创建第二个150W日光(位置12, 7, 6)
|
||
try:
|
||
# 第二个光源位置 - 调整到窗户后方更远的位置
|
||
light2_x = -6
|
||
light2_y = 7 # 让日光更远
|
||
light2_z = 6 # 提高高度
|
||
|
||
# 创建日光
|
||
bpy.ops.object.light_add(type='SUN', location=(light2_x, light2_y, light2_z))
|
||
sun_light = bpy.context.active_object
|
||
sun_light.name = "Sun Light"
|
||
sun_light.data.energy = 20
|
||
|
||
# 调整日光旋转角度,让光线更直接地照射窗户
|
||
sun_light.rotation_euler = (math.radians(0), math.radians(-60), math.radians(0)) # 简化旋转角度
|
||
|
||
# 设置日光属性(简化设置)
|
||
sun_light.data.angle = 0.05 # 从0.1改为0.05,让阴影更锐利
|
||
sun_light.data.use_shadow = True # 启用阴影
|
||
|
||
print(f"已创建日光(20W)")
|
||
print(f"日光位置: x={light2_x}, y={light2_y}, z={light2_z}")
|
||
print(f"日光旋转: x={-70}°, y={0}°, z={0}°")
|
||
|
||
except Exception as e:
|
||
print(f"创建日光时出错: {e}")
|
||
|
||
print("照明设置完成")
|
||
print("灯光类型: 点光源 + 日光")
|
||
print(f"衰减类型: 点光源软衰减 + 日光平行光")
|
||
print(f"阴影设置: 启用,柔和阴影")
|
||
print(f"主灯光高度: {light_height}米 (房间高度减一米)")
|
||
print(f"日光位置: (0, 10, 6)米,旋转: (-70°, 0°, 0°)")
|
||
|
||
def render_scene():
|
||
"""渲染场景"""
|
||
print("开始EEVEE渲染...")
|
||
|
||
# 执行渲染
|
||
bpy.ops.render.render(write_still=True)
|
||
print(f"EEVEE渲染完成! 图片保存在: {bpy.context.scene.render.filepath}")
|
||
return bpy.context.scene.render.filepath
|
||
|
||
def main():
|
||
"""主函数"""
|
||
print("=" * 60)
|
||
print("开始自动创建等轴测房间并EEVEE渲染")
|
||
print("=" * 60)
|
||
|
||
try:
|
||
# 1. 创建房间
|
||
print("1. 创建等轴测房间...")
|
||
if not create_isometric_room():
|
||
print("房间创建失败,停止执行")
|
||
return False
|
||
|
||
# 2. 创建落地窗
|
||
print("2. 创建archimesh落地窗...")
|
||
if not create_window_with_archimesh():
|
||
print("落地窗创建失败,但继续执行")
|
||
# 不中断执行,窗户创建失败不影响渲染
|
||
|
||
# 3. 设置渲染参数(EEVEE)
|
||
print("3. 设置EEVEE渲染参数...")
|
||
output_path = setup_render_settings()
|
||
|
||
# 4. 设置摄像机和照明
|
||
print("4. 设置摄像机和照明...")
|
||
setup_camera_and_lighting()
|
||
|
||
# 5. 渲染场景
|
||
print("5. 开始EEVEE渲染...")
|
||
final_path = render_scene()
|
||
|
||
print("=" * 60)
|
||
print("EEVEE渲染完成!")
|
||
print(f"渲染图片已保存到桌面: {final_path}")
|
||
print("=" * 60)
|
||
|
||
return True
|
||
|
||
except Exception as e:
|
||
print(f"执行过程中出现错误: {str(e)}")
|
||
import traceback
|
||
traceback.print_exc()
|
||
return False
|
||
|
||
# 执行主函数
|
||
if __name__ == "__main__":
|
||
main()
|
||
'''
|
||
|
||
|
||
def check_blender_exists():
|
||
"""检查Blender是否存在于指定路径"""
|
||
if not os.path.exists(BLENDER_PATH):
|
||
print(f"错误: 在路径 '{BLENDER_PATH}' 找不到Blender")
|
||
print("请检查Blender安装路径是否正确")
|
||
return False
|
||
return True
|
||
|
||
|
||
def create_temp_script():
|
||
"""创建临时的Blender脚本文件"""
|
||
script_path = os.path.join(os.getcwd(), "temp_simple_blender_script.py")
|
||
with open(script_path, 'w', encoding='utf-8') as f:
|
||
f.write(BLENDER_SIMPLE_SCRIPT)
|
||
return script_path
|
||
|
||
|
||
def launch_blender_simple():
|
||
"""启动Blender并执行简化版自动化脚本"""
|
||
if not check_blender_exists():
|
||
return False
|
||
|
||
# 创建临时脚本文件
|
||
script_path = create_temp_script()
|
||
|
||
try:
|
||
print("正在启动Blender(白模版本)...")
|
||
print(f"Blender路径: {BLENDER_PATH}")
|
||
print("特点:")
|
||
print("- 不设置材质,使用默认白色材质")
|
||
print("- 快速渲染")
|
||
print("- 兼容Blender 4.2")
|
||
print("- 自动保存到桌面")
|
||
|
||
# 构建命令行参数
|
||
cmd = [
|
||
BLENDER_PATH,
|
||
"--background", # 后台运行模式
|
||
"--disable-crash-handler", # 禁用崩溃处理器
|
||
"--python", script_path # 执行Python脚本
|
||
]
|
||
|
||
print("\n开始执行白模渲染流程...")
|
||
|
||
# 启动Blender并等待完成
|
||
process = subprocess.run(
|
||
cmd,
|
||
capture_output=True,
|
||
text=True,
|
||
encoding='utf-8',
|
||
timeout=300 # 5分钟超时
|
||
)
|
||
|
||
# 输出结果
|
||
if process.stdout:
|
||
print("Blender输出:")
|
||
# 过滤掉重复的错误信息
|
||
lines = process.stdout.split('\n')
|
||
filtered_lines = []
|
||
for line in lines:
|
||
if not ("AttributeError: 'NoneType' object has no attribute 'idname'" in line or
|
||
"Error in bpy.app.handlers.depsgraph_update_post" in line):
|
||
filtered_lines.append(line)
|
||
print('\n'.join(filtered_lines))
|
||
|
||
if process.stderr and not "rotate_tool.py" in process.stderr:
|
||
print("重要错误信息:")
|
||
print(process.stderr)
|
||
|
||
if process.returncode == 0:
|
||
print("\n✅ 白模渲染执行成功!")
|
||
print("白模图片应该已经保存到桌面")
|
||
return True
|
||
else:
|
||
print(f"\n❌ 执行失败,返回码: {process.returncode}")
|
||
return False
|
||
|
||
except subprocess.TimeoutExpired:
|
||
print("\n⏰ 执行超时(5分钟),可能Blender仍在运行")
|
||
print("请检查桌面是否有生成的图片")
|
||
return False
|
||
except Exception as e:
|
||
print(f"启动Blender时出现错误: {str(e)}")
|
||
return False
|
||
|
||
finally:
|
||
# 清理临时文件
|
||
try:
|
||
if os.path.exists(script_path):
|
||
os.remove(script_path)
|
||
print(f"已清理临时文件: {script_path}")
|
||
except:
|
||
pass
|
||
|
||
|
||
def main():
|
||
"""主函数"""
|
||
print("=" * 70)
|
||
print("Blender 4.2兼容版自动化脚本 - 白模渲染")
|
||
print("=" * 70)
|
||
print("特点:")
|
||
print("✓ 移除所有材质设置")
|
||
print("✓ 使用默认白色材质")
|
||
print("✓ 快速渲染")
|
||
print("✓ 兼容Blender 4.2")
|
||
print("✓ 自动保存到桌面")
|
||
print("=" * 70)
|
||
|
||
success = launch_blender_simple()
|
||
|
||
if success:
|
||
print("\n🎉 白模渲染完成!")
|
||
print("请检查桌面上的渲染图片")
|
||
print("图片文件名格式: isometric_room_white_[时间戳].png")
|
||
else:
|
||
print("\n❌ 执行失败!")
|
||
print("可能的解决方案:")
|
||
print("1. 确保Isometquick插件已正确安装")
|
||
print("2. 禁用可能冲突的其他插件")
|
||
print("3. 检查磁盘空间是否足够")
|
||
|
||
|
||
if __name__ == "__main__":
|
||
main()
|