#!/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' # 设置拱门参数 bpy.context.scene.sna_arch_settings = True # 启用拱门设置 bpy.context.scene.sna_arch_placement = 'NONE' # 设置为后墙拱门BACK 不设置拱门NONE bpy.context.scene.sna_arch_width = 1.2 # 拱门宽度1.2米 bpy.context.scene.sna_arch_height = 2.4 # 拱门高度2.4米 bpy.context.scene.sna_arch_thickness = 0.10 # 拱门厚度0.1米 # 找到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_door_with_archimesh(): """使用archimesh插件创建门""" try: print("开始创建archimesh门...") # 检查archimesh插件是否可用 if not hasattr(bpy.ops.mesh, 'archimesh_door'): 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_door() if result == {'FINISHED'}: print("archimesh门创建完成!") # 等待一帧以确保对象创建完成 bpy.context.view_layer.update() # 找到刚创建的门组对象(Door_Group) door_group = None for obj in bpy.data.objects: if obj.name == "Door_Group": door_group = obj break if door_group: print(f"找到门组: {door_group.name}") # 查找主门对象(DoorFrame) main_door_obj = None for obj in bpy.data.objects: if obj.name == "DoorFrame": main_door_obj = obj break if main_door_obj and hasattr(main_door_obj, 'DoorObjectGenerator'): # 获取门属性 door_props = main_door_obj.DoorObjectGenerator[0] print("设置门属性...") print(f"找到主门对象: {main_door_obj.name}") # 先设置基本属性 door_props.frame_width = 1.0 # 门框宽度 door_props.frame_height = 2.1 # 门框高度 door_props.frame_thick = 0.08 # 门框厚度 door_props.openside = '1' # 右侧开门 # 设置门模型和把手(这些会触发update_object回调) print("设置门模型为2...") door_props.model = '2' # 门模型2 print("设置门把手为1...") door_props.handle = '1' # 门把手1 print(f"门属性设置完成:") print(f" - 门框宽度: {door_props.frame_width}") print(f" - 门框高度: {door_props.frame_height}") print(f" - 门框厚度: {door_props.frame_thick}") print(f" - 开门方向: {door_props.openside}") print(f" - 门模型: {door_props.model}") print(f" - 门把手: {door_props.handle}") # 等待更新完成 bpy.context.view_layer.update() # 验证设置是否生效 print("验证门属性设置:") print(f" - 当前门模型: {door_props.model}") print(f" - 当前门把手: {door_props.handle}") # 强制触发更新(如果需要) try: # 重新设置属性以触发更新 current_model = door_props.model current_handle = door_props.handle door_props.model = '1' # 临时设置为其他值 bpy.context.view_layer.update() door_props.model = current_model # 设置回目标值 bpy.context.view_layer.update() print("已强制触发门模型更新") except Exception as update_error: print(f"强制更新时出现错误: {update_error}") # 在修改门全部属性后进行位移和旋转 print("开始移动和旋转门组...") try: door_group1 = None for obj in bpy.data.objects: if obj.name == "Door_Group": door_group1 = obj break # 设置位置 door_group1.location = (0.0, 6.0, 0.0) print(f"已将门组移动到位置: {door_group1.location}") # 设置旋转 door_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("警告: 未找到主门对象或DoorObjectGenerator属性") # 尝试查找其他可能的门属性 for obj in bpy.data.objects: if hasattr(obj, 'archimesh_door'): print(f"找到archimesh_door属性在对象: {obj.name}") # 打印门组的所有子对象信息 print("门组包含的对象:") for obj in bpy.data.objects: if obj.parent == door_group: print(f" - {obj.name} (位置: {obj.location})") return True else: print("警告: 未找到Door_Group对象") # 尝试查找其他可能的门对象 door_objects = [obj for obj in bpy.data.objects if "Door" in obj.name] if door_objects: print("找到的门相关对象:") for obj in door_objects: print(f" - {obj.name} (类型: {obj.type})") # 尝试移动第一个找到的门对象 first_door = door_objects[0] first_door.location = (0.0, 2.0, 0.0) print(f"已移动 {first_door.name} 到位置: {first_door.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 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 = False # 启用窗台 #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") # 启用Freestyle线条渲染 # scene.render.use_freestyle = True # print("已启用Freestyle线条渲染") # # 配置Freestyle线条设置 # if hasattr(scene, 'view_layers'): # view_layer = scene.view_layers[0] # 获取第一个视图层 # view_layer.use_freestyle = True # # 获取Freestyle线条设置 # freestyle = view_layer.freestyle_settings # # 启用线条渲染 # freestyle.use_smoothness = True # freestyle.use_culling = True # 设置线条宽度 - 使用正确的API 没有生效 # 设置世界环境 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 = 8.0 # 强度8 # 创建世界输出节点 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" - 强度: 8.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(30)) # 相机旋转 # 设置为透视投影 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})") # 设置蜡笔-场景线条画 print("设置蜡笔-场景线条画...") try: # 启用蜡笔渲染 - 在Blender 4.2中使用不同的属性 if hasattr(bpy.context.scene.render, 'use_grease_pencil'): bpy.context.scene.render.use_grease_pencil = True print("已启用蜡笔渲染") else: # 在Blender 4.2中,蜡笔渲染可能默认启用 print("蜡笔渲染已默认启用") # 创建蜡笔对象(如果不存在)- 使用LINEART SCENE类型 grease_pencil_name = "Grease_pencil" grease_pencil_obj = None # 检查是否已存在蜡笔对象 for obj in bpy.data.objects: if obj.name == grease_pencil_name and obj.type == 'GPENCIL': grease_pencil_obj = obj print(f"找到现有蜡笔对象: {grease_pencil_name}") break if grease_pencil_obj is None: # 创建新的蜡笔对象 bpy.ops.object.gpencil_add(type='LINEART_SCENE') grease_pencil_obj = bpy.context.active_object grease_pencil_obj.name = grease_pencil_name # 等待一帧以确保数据创建完成 bpy.context.view_layer.update() print(f"已创建蜡笔场景线条画对象: {grease_pencil_name}") # 设置笔画厚度缩放为0.38 if grease_pencil_obj and grease_pencil_obj.data: grease_pencil_data = grease_pencil_obj.data grease_pencil_data.pixel_factor = 0.38 print(f"已设置蜡笔笔画厚度缩放: {grease_pencil_data.pixel_factor}") else: print("警告: 未找到蜡笔数据") # 确保蜡笔对象在渲染时可见 if grease_pencil_obj: grease_pencil_obj.hide_render = False grease_pencil_obj.hide_viewport = False print("蜡笔对象已设置为可见") print("蜡笔-场景线条画设置完成") except Exception as e: print(f"设置蜡笔时出现错误: {e}") print("继续执行其他设置...") # 创建第一个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("落地窗创建失败,但继续执行") # 不中断执行,窗户创建失败不影响渲染 # 2. 创建门 print("2. 创建archimesh门...") if not create_door_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()