diff --git a/.DS_Store b/.DS_Store index 02243c8..f306aae 100644 Binary files a/.DS_Store and b/.DS_Store differ diff --git a/README_fused_system.md b/README_fused_system.md new file mode 100644 index 0000000..44db4d8 --- /dev/null +++ b/README_fused_system.md @@ -0,0 +1,157 @@ +# 融合光学系统脚本 + +这个脚本将 `toModel.py` 和 `light_path_simple.py` 两个脚本的功能融合在一起,在一个场景中同时显示光学系统的几何体和光路可视化。 + +## 功能特点 + +- 🔧 **光学系统几何体**: 创建平面、抛物面、双曲面等光学元件 +- 💡 **光路可视化**: 显示发光的光路曲线 +- 🎨 **材质系统**: 金属、透明、发光等不同材质 +- 📁 **文件组织**: 使用集合(Collection)组织不同类型的对象 +- 📤 **多格式导出**: 支持 OBJ、GLB、Blend 文件导出 +- 🖼️ **高质量渲染**: 使用 Cycles 渲染引擎 + +## 文件结构 + +``` +├── fused_optical_system.py # 主要的融合脚本 +├── run_fused_system.py # 运行辅助脚本 +├── README_fused_system.md # 本说明文件 +├── e8caffb4622e03b1495bbc1ed13fce13.json # 光学系统数据 +└── miao_light_path_tsingtao.json # 光路数据 +``` + +## 使用方法 + +### 方法 1: 使用运行辅助脚本(推荐) + +```bash +python3 run_fused_system.py +``` + +这个脚本会自动: + +- 检测 Blender 安装 +- 检查必要的 JSON 文件 +- 运行融合脚本 +- 显示执行结果 + +### 方法 2: 直接使用 Blender 命令 + +```bash +blender --background --python fused_optical_system.py -- [optical_json_path] [light_path_json_path] +``` + +参数说明: + +- `optical_json_path`: 光学系统 JSON 文件路径(可选,默认:`./e8caffb4622e03b1495bbc1ed13fce13.json`) +- `light_path_json_path`: 光路 JSON 文件路径(可选,默认:`./miao_light_path_tsingtao.json`) + +### 方法 3: 在 Blender 中运行 + +1. 打开 Blender +2. 切换到 Scripting 工作区 +3. 打开 `fused_optical_system.py` 文件 +4. 点击运行按钮 + +## 输出文件 + +脚本执行完成后会生成以下文件: + +- **`fused_optical_system.blend`** - Blender 工程文件,包含完整的场景 +- **`fused_optical_system.glb`** - Web 友好的 3D 模型格式 +- **`fused_optical_system.obj`** - 通用的 3D 模型格式 +- **`fused_optical_system_render.png`** - 高质量渲染图像 + +## 场景组织 + +融合后的场景使用集合(Collection)来组织对象: + +- **OpticalSystem**: 包含所有光学系统几何体 +- **LightPaths**: 包含所有光路可视化对象 + +## 材质系统 + +- **金属材质**: 用于光学元件表面 +- **透明材质**: 用于"nothing"类型的对象 +- **发光材质**: 用于特殊发光对象 +- **光路材质**: 用于光路曲线,具有发光效果 + +## 光路可视化 + +- 支持多种颜色方案(红、绿、蓝、黄、紫、青、橙、粉) +- 发光强度增强,确保在场景中清晰可见 +- 自动限制光路数量(最多 20 条)以避免场景过于复杂 +- 曲线厚度适中,既清晰又不会遮挡几何体 + +## 相机和灯光设置 + +- **相机位置**: (20, -20, 15),角度适合观察整个系统 +- **主灯光**: 太阳光,提供主要照明 +- **环境光**: 区域光,提供柔和的环境照明 +- **背景**: 深蓝色背景,突出光路效果 + +## 渲染设置 + +- **渲染引擎**: Cycles(提供更好的材质和光照效果) +- **分辨率**: 1920x1080(全高清) +- **输出格式**: PNG + +## 故障排除 + +### 常见问题 + +1. **找不到 Blender** + + - 确保 Blender 已安装 + - 将 Blender 添加到系统 PATH 中 + - 或手动指定 Blender 安装路径 + +2. **缺少 JSON 文件** + + - 确保 `e8caffb4622e03b1495bbc1ed13fce13.json` 存在 + - 确保 `miao_light_path_tsingtao.json` 存在 + +3. **脚本执行失败** + + - 检查 JSON 文件格式是否正确 + - 查看错误输出信息 + - 确保有足够的磁盘空间 + +4. **渲染失败** + - 检查是否有足够的系统内存 + - 确保输出目录可写 + - 检查 Blender 版本兼容性 + +### 调试模式 + +如果需要调试,可以在 Blender 中直接运行脚本,这样可以看到更详细的错误信息。 + +## 性能优化 + +- 光路数量限制在 20 条以内 +- 使用适当的几何体分辨率 +- 优化材质节点设置 +- 合理的灯光配置 + +## 扩展功能 + +可以基于这个融合脚本进一步扩展: + +- 添加动画效果 +- 支持更多几何体类型 +- 自定义材质和纹理 +- 添加交互式控制 +- 支持实时渲染 + +## 技术细节 + +- **Python 版本**: 3.7+ +- **Blender 版本**: 2.80+ +- **依赖库**: bpy, json, mathutils, bmesh, numpy +- **渲染引擎**: Cycles +- **文件格式**: 支持 OBJ、GLB、Blend + +## 许可证 + +本脚本遵循与原始脚本相同的许可证条款。 diff --git a/fused_optical_system.blend b/fused_optical_system.blend new file mode 100644 index 0000000..9aff241 Binary files /dev/null and b/fused_optical_system.blend differ diff --git a/fused_optical_system.glb b/fused_optical_system.glb new file mode 100644 index 0000000..1b23d28 Binary files /dev/null and b/fused_optical_system.glb differ diff --git a/fused_optical_system.py b/fused_optical_system.py new file mode 100644 index 0000000..31e00a7 --- /dev/null +++ b/fused_optical_system.py @@ -0,0 +1,558 @@ +#!/usr/bin/env python3 +""" +融合光学系统脚本 +将光学系统几何体和光路可视化合并到一个场景中 + +使用方法: +blender --background --python fused_optical_system.py -- [optical_json_path] [light_path_json_path] + +输出文件: +- fused_optical_system.blend - Blender工程文件 +- fused_optical_system.glb - Web友好格式 +- fused_optical_system_render.png - 渲染图像 +""" + +import bpy +import json +import mathutils +import os +import bmesh +import sys +import numpy as np + +# 获取命令行参数 +def get_json_paths(): + """从命令行参数获取JSON文件路径""" + optical_json = "./e8caffb4622e03b1495bbc1ed13fce13.json" + light_path_json = "./miao_light_path_tsingtao.json" + + if len(sys.argv) > 5: # Blender传递的参数格式: blender --background --python script.py -- optical_json light_path_json + # 查找 -- 分隔符后的参数 + for i, arg in enumerate(sys.argv): + if arg == "--" and i + 1 < len(sys.argv): + if i + 2 < len(sys.argv): + optical_json = sys.argv[i + 1] + light_path_json = sys.argv[i + 2] + else: + optical_json = sys.argv[i + 1] + break + + return optical_json, light_path_json + +# 清空场景 +bpy.ops.wm.read_factory_settings(use_empty=True) + +# 设置渲染引擎为Cycles(更好的材质渲染) +bpy.context.scene.render.engine = 'CYCLES' + +# 获取JSON文件路径 +optical_json_path, light_path_json_path = get_json_paths() +print(f"光学系统JSON文件:{optical_json_path}") +print(f"光路JSON文件:{light_path_json_path}") + +# ==================== 光学系统几何体部分 ==================== + +def create_metal_material(): + """创建金属材质""" + mat = bpy.data.materials.new(name="metal") + mat.use_nodes = True + bsdf = mat.node_tree.nodes["Principled BSDF"] + bsdf.inputs["Metallic"].default_value = 1.0 + bsdf.inputs["Roughness"].default_value = 0.2 + bsdf.inputs["Base Color"].default_value = (0.8, 0.8, 0.9, 1.0) # 淡蓝色金属 + return mat + +def create_nothing_material(): + """创建透明材质(用于 nothing)""" + mat = bpy.data.materials.new(name="nothing") + mat.use_nodes = True + bsdf = mat.node_tree.nodes["Principled BSDF"] + bsdf.inputs["Alpha"].default_value = 0.1 + bsdf.inputs["Base Color"].default_value = (1.0, 1.0, 1.0, 0.1) + mat.blend_method = 'BLEND' + mat.show_transparent_back = False + return mat + +def create_emissive_material(): + """创建发光材质(用于特殊对象)""" + mat = bpy.data.materials.new(name="emissive") + mat.use_nodes = True + bsdf = mat.node_tree.nodes["Principled BSDF"] + try: + if "Emission" in bsdf.inputs: + bsdf.inputs["Emission"].default_value = (1.0, 0.8, 0.2, 1.0) + elif "Emission Color" in bsdf.inputs: + bsdf.inputs["Emission Color"].default_value = (1.0, 0.8, 0.2, 1.0) + + if "Emission Strength" in bsdf.inputs: + bsdf.inputs["Emission Strength"].default_value = 2.0 + else: + # 备用方案:使用较亮的基础颜色 + bsdf.inputs["Base Color"].default_value = (1.0, 0.8, 0.2, 1.0) + except Exception as e: + print(f"设置发光材质时出错: {e}") + # 备用方案:创建简单的明亮材质 + bsdf.inputs["Base Color"].default_value = (1.0, 0.8, 0.2, 1.0) + bsdf.inputs["Roughness"].default_value = 0.1 + + return mat + +def create_parabolic_surface(face_f, size=1.0, resolution=32): + """创建更精确的抛物面""" + bm = bmesh.new() + + # 创建抛物面网格 + for i in range(resolution): + for j in range(resolution): + u = (i / (resolution - 1) - 0.5) * size + v = (j / (resolution - 1) - 0.5) * size + + # 抛物面方程: z = (u^2 + v^2) / (4*f) + if face_f > 0 and face_f < 1e9: # 避免除零和无限大 + z = (u*u + v*v) / (4 * face_f) + else: + z = 0 + + bm.verts.new((u, v, z)) + + bm.verts.ensure_lookup_table() + + # 创建面 + for i in range(resolution - 1): + for j in range(resolution - 1): + v1 = i * resolution + j + v2 = i * resolution + j + 1 + v3 = (i + 1) * resolution + j + 1 + v4 = (i + 1) * resolution + j + + bm.faces.new([bm.verts[v1], bm.verts[v2], bm.verts[v3], bm.verts[v4]]) + + # 创建网格对象 + mesh = bpy.data.meshes.new("parabolic_surface") + bm.to_mesh(mesh) + bm.free() + + obj = bpy.data.objects.new("parabolic_surface", mesh) + bpy.context.collection.objects.link(obj) + + return obj + +def create_hyperbolic_surface(face_f, face_g, size=1.0, resolution=32): + """创建双曲面""" + bm = bmesh.new() + + # 创建双曲面网格 + for i in range(resolution): + for j in range(resolution): + u = (i / (resolution - 1) - 0.5) * size + v = (j / (resolution - 1) - 0.5) * size + + # 双曲面方程: z^2/f^2 - (u^2 + v^2)/g^2 = 1 + if abs(face_g) > 0.1 and abs(face_f) > 0.1: + try: + z_squared = face_f * face_f * (1 + (u*u + v*v) / (face_g * face_g)) + if z_squared >= 0: + z = (face_f if face_f > 0 else -face_f) * (z_squared ** 0.5) + else: + z = 0 + except: + z = 0 + else: + z = 0 + + bm.verts.new((u, v, z)) + + bm.verts.ensure_lookup_table() + + # 创建面 + for i in range(resolution - 1): + for j in range(resolution - 1): + v1 = i * resolution + j + v2 = i * resolution + j + 1 + v3 = (i + 1) * resolution + j + 1 + v4 = (i + 1) * resolution + j + + bm.faces.new([bm.verts[v1], bm.verts[v2], bm.verts[v3], bm.verts[v4]]) + + mesh = bpy.data.meshes.new("hyperbolic_surface") + bm.to_mesh(mesh) + bm.free() + + obj = bpy.data.objects.new("hyperbolic_surface", mesh) + bpy.context.collection.objects.link(obj) + + return obj + +def create_geometry(obj_data): + """根据面类型创建物体""" + face_geom = obj_data.get("face_geometry", "plane") + face_type = obj_data.get("face_type", "") + name = obj_data.get("name", "noname") + pos = obj_data["p"] + quat = obj_data["q"] + material_name = obj_data.get("draw_material", "metal") + face_f = obj_data.get("face_f", 1.0) + face_g = obj_data.get("face_g", 1.0) + + print(f"创建光学对象: {name} ({face_geom})") + + mesh = None + + try: + if face_geom == "plane": + # 创建圆形平面而不是方形 + bpy.ops.mesh.primitive_circle_add(vertices=32, radius=0.5) + mesh = bpy.context.active_object + # 填充圆形 + bpy.ops.object.mode_set(mode='EDIT') + bpy.ops.mesh.edge_face_add() + bpy.ops.object.mode_set(mode='OBJECT') + elif face_geom == "circle": + # 创建圆形平面 + bpy.ops.mesh.primitive_circle_add(vertices=32, radius=0.5) + mesh = bpy.context.active_object + # 填充圆形 + bpy.ops.object.mode_set(mode='EDIT') + bpy.ops.mesh.edge_face_add() + bpy.ops.object.mode_set(mode='OBJECT') + elif face_geom == "parabola": + if face_f < 1e9 and face_f > 0.1: # 使用精确抛物面 + mesh = create_parabolic_surface(face_f) + else: # 使用简化圆锥 + bpy.ops.mesh.primitive_cone_add(vertices=32, radius1=0.75, radius2=0.05, depth=1.0) + mesh = bpy.context.active_object + elif face_geom == "hyperbola": + if abs(face_f) > 0.1 and abs(face_g) > 0.1: # 使用精确双曲面 + mesh = create_hyperbolic_surface(face_f, face_g) + else: # 使用简化环面 + bpy.ops.mesh.primitive_torus_add(major_radius=0.5, minor_radius=0.15) + mesh = bpy.context.active_object + else: + # 默认立方体 + bpy.ops.mesh.primitive_cube_add(size=0.5) + mesh = bpy.context.active_object + except Exception as e: + print(f"创建几何体时出错: {e}") + # 备用:创建简单立方体 + bpy.ops.mesh.primitive_cube_add(size=0.25) + mesh = bpy.context.active_object + + # 设置对象属性 + mesh.name = name + mesh.location = pos + mesh.rotation_mode = 'QUATERNION' + mesh.rotation_quaternion = mathutils.Quaternion(quat) + + # 设置材质 + if material_name == "metal": + mesh.data.materials.append(metal_mat) + elif material_name == "nothing": + mesh.data.materials.append(nothing_mat) + else: + mesh.data.materials.append(emissive_mat) + + return mesh + +# ==================== 光路可视化部分 ==================== + +def create_light_path_material(color=(1.0, 0.2, 0.2, 1.0)): + """创建光路材质""" + mat = bpy.data.materials.new(name="light_path") + mat.use_nodes = True + nodes = mat.node_tree.nodes + links = mat.node_tree.links + + # 清除默认节点 + nodes.clear() + + # 创建发光节点 + emission = nodes.new(type='ShaderNodeEmission') + emission.inputs['Color'].default_value = color + emission.inputs['Strength'].default_value = 2.0 # 增强发光强度 + + # 创建输出节点 + output = nodes.new(type='ShaderNodeOutputMaterial') + + # 连接节点 + links.new(emission.outputs['Emission'], output.inputs['Surface']) + + return mat + +def create_light_path_curve(points, name="light_path"): + """创建光路曲线""" + # 创建曲线数据 + curve_data = bpy.data.curves.new(name, type='CURVE') + curve_data.dimensions = '3D' + curve_data.resolution_u = 12 + curve_data.bevel_depth = 0.03 # 稍微增加厚度 + curve_data.bevel_resolution = 4 + + # 创建样条线 + spline = curve_data.splines.new('POLY') + spline.points.add(len(points) - 1) + + # 设置点坐标 + for i, point in enumerate(points): + spline.points[i].co = (point[0], point[1], point[2], 1.0) + + # 创建曲线对象 + curve_obj = bpy.data.objects.new(name, curve_data) + bpy.context.collection.objects.link(curve_obj) + + return curve_obj + +def create_light_paths(light_paths): + """创建所有光路""" + objects = [] + + # 颜色方案 + colors = [ + (1.0, 0.2, 0.2, 1.0), # 红色 + (0.2, 1.0, 0.2, 1.0), # 绿色 + (0.2, 0.2, 1.0, 1.0), # 蓝色 + (1.0, 1.0, 0.2, 1.0), # 黄色 + (1.0, 0.2, 1.0, 1.0), # 紫色 + (0.2, 1.0, 1.0, 1.0), # 青色 + (1.0, 0.6, 0.2, 1.0), # 橙色 + (0.8, 0.2, 0.8, 1.0), # 粉色 + ] + + # 限制光路数量以避免场景过于复杂 + max_paths = min(20, len(light_paths)) + print(f"创建前 {max_paths} 条光路(总共 {len(light_paths)} 条)") + + for i, path in enumerate(light_paths[:max_paths]): + if len(path) < 2: + continue + + # 选择颜色 + color = colors[i % len(colors)] + + # 创建材质 + material = create_light_path_material(color) + + # 创建光路对象 + obj = create_light_path_curve(path, f"light_path_{i}") + + # 应用材质 + obj.data.materials.append(material) + + objects.append(obj) + + print(f"创建光路 {i+1}: {len(path)} 个点") + + return objects + +# ==================== 主程序 ==================== + +def load_optical_system_data(json_path): + """加载光学系统数据""" + try: + with open(json_path, 'r', encoding='utf-8') as f: + data = json.load(f) + print(f"✅ 成功加载光学系统JSON文件:{json_path}") + print(f"包含 {len(data['children'])} 个光学对象") + return data + except FileNotFoundError: + print(f"❌ 错误:找不到光学系统JSON文件 {json_path}") + return None + except json.JSONDecodeError as e: + print(f"❌ 错误:光学系统JSON文件格式错误 {e}") + return None + except Exception as e: + print(f"❌ 错误:加载光学系统JSON文件时出错 {e}") + return None + +def load_light_path_data(json_path): + """加载光路数据""" + try: + with open(json_path, 'r', encoding='utf-8') as f: + data = json.load(f) + print(f"✅ 成功加载光路JSON文件:{json_path}") + print(f"包含 {len(data)} 条光路") + return data + except FileNotFoundError: + print(f"❌ 错误:找不到光路JSON文件 {json_path}") + return None + except json.JSONDecodeError as e: + print(f"❌ 错误:光路JSON文件格式错误 {e}") + return None + except Exception as e: + print(f"❌ 错误:加载光路JSON文件时出错 {e}") + return None + +def setup_scene(): + """设置场景""" + # 添加相机 + bpy.ops.object.camera_add(location=(20, -20, 15)) + camera = bpy.context.active_object + camera.rotation_euler = (1.0, 0, 0.785) + bpy.context.scene.camera = camera + + # 添加主灯光 + bpy.ops.object.light_add(type='SUN', location=(10, 10, 20)) + sun = bpy.context.active_object + sun.data.energy = 3.0 + + # 添加环境光 + bpy.ops.object.light_add(type='AREA', location=(-10, -10, 15)) + area = bpy.context.active_object + area.data.energy = 100.0 + area.data.size = 15.0 + + # 设置世界背景 + world = bpy.context.scene.world + if world is None: + world = bpy.data.worlds.new("World") + bpy.context.scene.world = world + + world.use_nodes = True + bg_node = world.node_tree.nodes['Background'] + bg_node.inputs['Color'].default_value = (0.02, 0.02, 0.05, 1.0) # 深蓝色背景 + bg_node.inputs['Strength'].default_value = 0.3 + +def export_model(optical_objects, light_path_objects): + """导出模型""" + print(f"准备导出 {len(optical_objects)} 个光学对象和 {len(light_path_objects)} 条光路...") + + all_objects = optical_objects + light_path_objects + + if not all_objects: + print("警告:没有创建任何对象,跳过导出") + return + + # 选择所有创建的对象 + bpy.ops.object.select_all(action='DESELECT') + for obj in all_objects: + if obj and obj.name in bpy.data.objects: + obj.select_set(True) + print(f"已选择对象: {obj.name}") + + try: + # 导出为OBJ格式 + obj_path = os.path.abspath("./fused_optical_system.obj") + bpy.ops.export_scene.obj(filepath=obj_path, use_selection=True, use_materials=True) + print(f"模型已导出为: {obj_path}") + except Exception as e: + print(f"OBJ导出失败: {e}") + + try: + # 导出为GLB格式(适合web展示) + glb_path = os.path.abspath("./fused_optical_system.glb") + bpy.ops.export_scene.gltf(filepath=glb_path, use_selection=True, export_materials='EXPORT') + print(f"模型已导出为: {glb_path}") + except Exception as e: + print(f"GLB导出失败: {e}") + + try: + # 保存Blender文件 + blend_path = os.path.abspath("./fused_optical_system.blend") + bpy.ops.wm.save_as_mainfile(filepath=blend_path) + print(f"Blender文件已保存为: {blend_path}") + except Exception as e: + print(f"Blender文件保存失败: {e}") + +def render_image(): + """渲染图像""" + try: + render_path = os.path.abspath("./fused_optical_system_render.png") + scene = bpy.context.scene + scene.render.filepath = render_path + scene.render.resolution_x = 1920 + scene.render.resolution_y = 1080 + scene.render.image_settings.file_format = 'PNG' + + print(f"开始渲染到: {render_path}") + bpy.ops.render.render(write_still=True) + print(f"渲染图像已保存为: {render_path}") + except Exception as e: + print(f"渲染失败: {e}") + import traceback + traceback.print_exc() + +def main(): + """主函数""" + print("🎨 融合光学系统脚本 - 几何体 + 光路可视化") + print("=" * 50) + + # 创建材质 + global metal_mat, nothing_mat, emissive_mat + metal_mat = create_metal_material() + nothing_mat = create_nothing_material() + emissive_mat = create_emissive_material() + + # 加载光学系统数据 + optical_data = load_optical_system_data(optical_json_path) + if not optical_data: + print("❌ 无法加载光学系统数据,退出") + return + + # 加载光路数据 + light_path_data = load_light_path_data(light_path_json_path) + if not light_path_data: + print("❌ 无法加载光路数据,退出") + return + + # 创建集合来组织对象 + optical_collection = bpy.data.collections.new("OpticalSystem") + light_path_collection = bpy.data.collections.new("LightPaths") + bpy.context.scene.collection.children.link(optical_collection) + bpy.context.scene.collection.children.link(light_path_collection) + + # 创建光学系统几何体 + print("\n🔧 创建光学系统几何体...") + optical_objects = [] + for i, child in enumerate(optical_data["children"]): + try: + obj = create_geometry(child) + optical_objects.append(obj) + + # 将对象移动到专用集合 + bpy.context.collection.objects.unlink(obj) + optical_collection.objects.link(obj) + + except Exception as e: + print(f"创建光学对象 {i} 时出错: {e}") + + print(f"成功创建了 {len(optical_objects)} 个光学对象") + + # 创建光路可视化 + print("\n💡 创建光路可视化...") + light_path_objects = create_light_paths(light_path_data) + + # 将光路对象移动到专用集合 + for obj in light_path_objects: + bpy.context.collection.objects.unlink(obj) + light_path_collection.objects.link(obj) + + print(f"成功创建了 {len(light_path_objects)} 条光路") + + # 设置场景 + print("\n🎬 设置场景...") + setup_scene() + + # 执行导出和渲染 + try: + print("\n📤 开始导出模型...") + export_model(optical_objects, light_path_objects) + + print("\n🎨 开始渲染图像...") + render_image() + + print("\n🎉 脚本执行完成!") + print("生成的文件:") + print("- fused_optical_system.obj (3D模型)") + print("- fused_optical_system.glb (Web友好格式)") + print("- fused_optical_system.blend (Blender工程文件)") + print("- fused_optical_system_render.png (渲染图像)") + print(f"\n场景统计:") + print(f"- 光学对象: {len(optical_objects)} 个") + print(f"- 光路: {len(light_path_objects)} 条") + + except Exception as e: + print(f"执行导出/渲染时出错: {e}") + import traceback + traceback.print_exc() + +if __name__ == "__main__": + main() diff --git a/fused_optical_system_render.png b/fused_optical_system_render.png new file mode 100644 index 0000000..97a6b61 Binary files /dev/null and b/fused_optical_system_render.png differ diff --git a/run_fused_system.py b/run_fused_system.py new file mode 100644 index 0000000..02320bd --- /dev/null +++ b/run_fused_system.py @@ -0,0 +1,132 @@ +#!/usr/bin/env python3 +""" +运行融合光学系统脚本的辅助脚本 +""" + +import subprocess +import sys +import os + +def run_fused_optical_system(): + """运行融合光学系统脚本""" + + # 检查Blender是否可用 + blender_cmd = None + + # 常见的Blender安装路径 + possible_paths = [ + "blender", # 如果在PATH中 + "/Applications/Blender.app/Contents/MacOS/Blender", # macOS + "/usr/bin/blender", # Linux + "C:\\Program Files\\Blender Foundation\\Blender\\blender.exe", # Windows + ] + + for path in possible_paths: + try: + result = subprocess.run([path, "--version"], + capture_output=True, text=True, timeout=10) + if result.returncode == 0: + blender_cmd = path + print(f"✅ 找到Blender: {path}") + break + except (subprocess.TimeoutExpired, FileNotFoundError, subprocess.SubprocessError): + continue + + if not blender_cmd: + print("❌ 错误:找不到Blender安装") + print("请确保Blender已安装并在PATH中,或者手动指定Blender路径") + return False + + # 检查必要的JSON文件 + optical_json = "./e8caffb4622e03b1495bbc1ed13fce13.json" + light_path_json = "./miao_light_path_tsingtao.json" + + missing_files = [] + if not os.path.exists(optical_json): + missing_files.append(optical_json) + if not os.path.exists(light_path_json): + missing_files.append(light_path_json) + + if missing_files: + print(f"❌ 错误:缺少必要的JSON文件:{missing_files}") + print("请确保以下文件存在:") + print(f" - {optical_json}") + print(f" - {light_path_json}") + return False + + # 检查融合脚本 + fused_script = "./fused_optical_system.py" + if not os.path.exists(fused_script): + print(f"❌ 错误:找不到融合脚本:{fused_script}") + return False + + print("🚀 开始运行融合光学系统脚本...") + print(f"光学系统数据:{optical_json}") + print(f"光路数据:{light_path_json}") + print(f"Blender命令:{blender_cmd}") + + try: + # 运行Blender命令 + cmd = [ + blender_cmd, + "--background", # 后台运行 + "--python", fused_script, + "--", # 分隔符 + optical_json, + light_path_json + ] + + print(f"执行命令:{' '.join(cmd)}") + + result = subprocess.run(cmd, + capture_output=True, + text=True, + timeout=300) # 5分钟超时 + + if result.returncode == 0: + print("✅ 融合光学系统脚本执行成功!") + print("\n输出文件:") + print("- fused_optical_system.blend") + print("- fused_optical_system.glb") + print("- fused_optical_system.obj") + print("- fused_optical_system_render.png") + + # 显示脚本输出 + if result.stdout: + print("\n脚本输出:") + print(result.stdout) + + return True + else: + print(f"❌ 融合光学系统脚本执行失败,返回码:{result.returncode}") + if result.stderr: + print("错误输出:") + print(result.stderr) + if result.stdout: + print("标准输出:") + print(result.stdout) + return False + + except subprocess.TimeoutExpired: + print("❌ 脚本执行超时(超过5分钟)") + return False + except Exception as e: + print(f"❌ 执行过程中出错:{e}") + return False + +def main(): + """主函数""" + print("🎨 融合光学系统脚本运行器") + print("=" * 40) + + success = run_fused_optical_system() + + if success: + print("\n🎉 任务完成!") + sys.exit(0) + else: + print("\n❌ 任务失败!") + sys.exit(1) + +if __name__ == "__main__": + main()