Compare commits

..

2 Commits

Author SHA1 Message Date
nicomacbookpro
5478efef6c Merge branch 'main' of https://nicowebgl.cn/macmini/gitea/nicolas/BL 2025-08-28 15:10:35 +08:00
nicomacbookpro
529384a8e6 修改 2025-08-28 15:10:09 +08:00
13 changed files with 18262 additions and 3 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

278
README_light_path.md Normal file
View File

@@ -0,0 +1,278 @@
# 光学系统光路可视化
本项目提供了多种方式来可视化光学系统的光路数据,使用 Blender 生成高质量的 3D 光路模型。
## 文件说明
### 数据文件
- `miao_light_path_tsingtao.json` - 光路数据文件,包含多条光路的 3D 坐标点
### 可视化脚本
#### 基础版本
- `light_path_blender.py` - 基础版 Blender 光路可视化脚本
- `run_light_path.py` - 运行基础版脚本的启动器
#### 增强版本
- `light_path_advanced.py` - 增强版 Blender 光路可视化脚本
- `run_light_path_advanced.py` - 运行增强版脚本的启动器
#### 其他工具
- `linemodel.py` - 使用 matplotlib 的 2D/3D 光路可视化脚本
## 功能特点
### 基础版本功能
- ✅ 3D 光路曲线可视化
- ✅ 不同颜色区分光路
- ✅ 发光材质效果
- ✅ 自动相机调整
- ✅ 导出 GLB 和 Blend 文件
- ✅ 渲染高质量图像
### 增强版本功能
- ✅ 所有基础版本功能
- ✅ 光路起点和终点标记(绿色/红色球体)
- ✅ 光路密度体积可视化
- ✅ 更高质量的光照和材质
- ✅ 更精确的相机控制
- ✅ 更丰富的渲染选项
## 使用方法
### 方法 1使用运行脚本推荐
#### 基础版本
```bash
python run_light_path.py
```
#### 增强版本
```bash
python run_light_path_advanced.py
```
### 方法 2直接在 Blender 中运行
1. 打开 Blender
2. 切换到 Scripting 工作区
3. 打开 `light_path_blender.py``light_path_advanced.py`
4. 点击运行脚本
### 方法 3命令行运行
```bash
blender --background --python light_path_blender.py
# 或
blender --background --python light_path_advanced.py
```
## 输出文件
### 基础版本输出
- `light_path_model.blend` - Blender 工程文件
- `light_path_model.glb` - Web 友好格式(可在浏览器中查看)
- `light_path_render.png` - 渲染图像
### 增强版本输出
- `light_path_advanced.blend` - Blender 工程文件
- `light_path_advanced.glb` - Web 友好格式
- `light_path_render.png` - 高质量渲染图像
## 系统要求
### 必需软件
- **Blender 3.0+** - 3D 建模和渲染软件
- 下载地址https://www.blender.org/download/
- **Python 3.7+** - 编程语言环境
### 推荐配置
- **操作系统**: Windows 10+, macOS 10.15+, Ubuntu 18.04+
- **内存**: 8GB+ RAM
- **显卡**: 支持 OpenGL 3.3+的显卡
- **存储**: 至少 2GB 可用空间
## 安装步骤
1. **安装 Blender**
```bash
# macOS (使用Homebrew)
brew install --cask blender
# Ubuntu/Debian
sudo apt update
sudo apt install blender
# Windows
# 从官网下载安装包
```
2. **验证安装**
```bash
blender --version
```
3. **运行脚本**
```bash
python run_light_path.py
```
## 故障排除
### 常见问题
#### 1. 找不到 Blender
```
❌ 错误未找到Blender安装
```
**解决方案**
- 确保 Blender 已正确安装
- 将 Blender 添加到系统 PATH
- 手动指定 Blender 路径
#### 2. 找不到数据文件
```
❌ 错误:未找到光路数据文件 miao_light_path_tsingtao.json
```
**解决方案**
- 确保数据文件在当前目录
- 检查文件名是否正确
#### 3. 渲染失败
```
❌ 渲染失败
```
**解决方案**
- 检查显卡驱动是否最新
- 降低渲染分辨率
- 使用 Eevee 渲染引擎替代 Cycles
#### 4. 内存不足
```
❌ 内存不足错误
```
**解决方案**
- 关闭其他应用程序
- 减少光路数量(修改脚本)
- 增加系统虚拟内存
### 性能优化
#### 提高渲染速度
1. 使用 Eevee 渲染引擎
2. 降低采样数量
3. 减少光路数量
4. 使用 GPU 渲染
#### 减少内存使用
1. 分批处理光路
2. 简化几何体
3. 优化材质设置
## 自定义配置
### 修改光路颜色
在脚本中修改 `base_colors` 列表:
```python
base_colors = [
(1.0, 0.2, 0.2, 1.0), # 红色
(0.2, 1.0, 0.2, 1.0), # 绿色
# 添加更多颜色...
]
```
### 调整光路粗细
修改 `thickness` 参数:
```python
obj = create_light_path_curve(path, f"light_path_{i}", thickness=0.05)
```
### 更改渲染质量
修改采样数量:
```python
scene.cycles.samples = 256 # 更高的采样数 = 更好的质量
```
## 技术细节
### 数据格式
光路数据采用 JSON 格式,结构如下:
```json
[
[
[x1, y1, z1],
[x2, y2, z2],
...
],
[
[x1, y1, z1],
[x2, y2, z2],
...
]
]
```
### 渲染引擎
- **Cycles**: 基于物理的渲染引擎,提供最真实的光照效果
- **Eevee**: 实时渲染引擎,速度更快但质量稍低
### 导出格式
- **GLB**: 二进制 GLTF 格式,适合 Web 展示
- **Blend**: Blender 原生格式,包含完整项目信息
## 许可证
本项目采用 MIT 许可证,详见 LICENSE 文件。
## 贡献
欢迎提交 Issue 和 Pull Request 来改进这个项目!
## 联系方式
如有问题或建议,请通过以下方式联系:
- 提交 GitHub Issue
- 发送邮件至项目维护者
---
**注意**: 确保在运行脚本前备份重要文件,脚本会生成新的文件并可能覆盖同名文件。

356
light_path_blender.py Normal file
View File

@@ -0,0 +1,356 @@
#!/usr/bin/env python3
"""
光路可视化Blender脚本
读取miao_light_path_tsingtao.json文件并使用Blender绘制3D光路模型
使用方法:
1. 在Blender中运行此脚本
2. 或使用命令行: blender --background --python light_path_blender.py
输出文件:
- light_path_model.blend - Blender工程文件
- light_path_model.glb - Web友好格式
- light_path_render.png - 渲染图像
"""
import bpy
import json
import mathutils
import os
import bmesh
import numpy as np
from mathutils import Vector
# 清空场景
bpy.ops.wm.read_factory_settings(use_empty=True)
# 设置渲染引擎为Cycles更好的材质渲染
bpy.context.scene.render.engine = 'CYCLES'
def load_light_paths(filename):
"""加载光路数据"""
try:
with open(filename, 'r', encoding='utf-8') as f:
data = json.load(f)
print(f"成功加载光路文件: {filename}")
print(f"包含 {len(data)} 条光路")
return data
except Exception as e:
print(f"加载光路文件失败: {e}")
return []
def create_light_path_material(color=(1.0, 0.2, 0.2, 1.0), emission_strength=0.5):
"""创建光路材质"""
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 = emission_strength
# 创建输出节点
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.02 # 光路粗细
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_path_mesh(points, name="light_path"):
"""创建光路网格(圆柱体连接)"""
# 创建网格数据
mesh_data = bpy.data.meshes.new(name)
mesh_obj = bpy.data.objects.new(name, mesh_data)
bpy.context.collection.objects.link(mesh_obj)
# 创建bmesh
bm = bmesh.new()
# 为每段光路创建圆柱体
for i in range(len(points) - 1):
start_point = Vector(points[i])
end_point = Vector(points[i + 1])
# 计算圆柱体参数
direction = (end_point - start_point).normalized()
length = (end_point - start_point).length
radius = 0.02 # 光路半径
# 创建圆柱体
bmesh.ops.create_cone(
bm,
segments=8,
diameter1=radius,
diameter2=radius,
depth=length
)
# 获取刚创建的圆柱体
cylinder_verts = [v for v in bm.verts if v.select]
cylinder_faces = [f for f in bm.faces if f.select]
# 取消选择
for v in cylinder_verts:
v.select = False
for f in cylinder_faces:
f.select = False
# 计算旋转
up = Vector((0, 0, 1))
if abs(direction.dot(up)) > 0.99:
up = Vector((0, 1, 0))
rotation = direction.rotation_difference(up)
# 应用变换
center = (start_point + end_point) / 2
for v in cylinder_verts:
v.co = rotation @ v.co + center
# 转换为网格
bm.to_mesh(mesh_data)
bm.free()
return mesh_obj
def create_light_path_objects(light_paths):
"""创建所有光路对象"""
objects = []
# 创建材质
base_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.5, 0.2, 1.0), # 橙色
(0.5, 0.2, 1.0, 1.0), # 紫罗兰
]
for i, path in enumerate(light_paths):
if len(path) < 2:
continue
# 选择颜色
color = base_colors[i % len(base_colors)]
# 创建材质
material = create_light_path_material(color, emission_strength=0.3)
# 创建光路对象(使用曲线)
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 setup_scene():
"""设置场景(相机、灯光等)"""
# 添加相机
bpy.ops.object.camera_add(location=(10, -10, 8))
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=(5, 5, 10))
sun = bpy.context.active_object
sun.data.energy = 2.0
# 添加环境光
bpy.ops.object.light_add(type='AREA', location=(-5, -5, 8))
area = bpy.context.active_object
area.data.energy = 30.0
area.data.size = 8.0
# 设置世界背景为深色
world = bpy.context.scene.world
world.use_nodes = True
bg_node = world.node_tree.nodes['Background']
bg_node.inputs['Color'].default_value = (0.05, 0.05, 0.1, 1.0)
bg_node.inputs['Strength'].default_value = 0.5
def calculate_bounds(light_paths):
"""计算光路的边界框"""
if not light_paths:
return None
all_points = []
for path in light_paths:
all_points.extend(path)
all_points = np.array(all_points)
min_coords = all_points.min(axis=0)
max_coords = all_points.max(axis=0)
return min_coords, max_coords
def adjust_camera_to_bounds(min_coords, max_coords):
"""根据边界调整相机位置"""
center = (min_coords + max_coords) / 2
size = max_coords - min_coords
max_size = max(size)
# 计算相机距离
distance = max_size * 2.5
# 设置相机位置
camera = bpy.context.scene.camera
camera.location = center + Vector((distance, -distance, distance * 0.8))
# 让相机看向中心
direction = center - camera.location
rot_quat = direction.to_track_quat('-Z', 'Y')
camera.rotation_euler = rot_quat.to_euler()
def export_model(objects):
"""导出模型"""
if not objects:
print("警告:没有创建任何对象,跳过导出")
return
# 选择所有光路对象
bpy.ops.object.select_all(action='DESELECT')
for obj in objects:
if obj and obj.name in bpy.data.objects:
obj.select_set(True)
try:
# 导出为GLB格式
glb_path = os.path.abspath("./light_path_model.glb")
bpy.ops.export_scene.gltf(
filepath=glb_path,
use_selection=True,
export_materials='EXPORT',
export_lights=True
)
print(f"模型已导出为: {glb_path}")
except Exception as e:
print(f"GLB导出失败: {e}")
try:
# 保存Blender文件
blend_path = os.path.abspath("./light_path_model.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:
# 设置渲染参数
scene = bpy.context.scene
scene.render.resolution_x = 1920
scene.render.resolution_y = 1080
scene.render.image_settings.file_format = 'PNG'
scene.render.film_transparent = False
render_path = os.path.abspath("./light_path_render.png")
scene.render.filepath = render_path
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("=" * 40)
# 加载光路数据
light_paths = load_light_paths("miao_light_path_tsingtao.json")
if not light_paths:
print("❌ 无法加载光路数据")
return
# 分析数据
print(f"\n=== 光路数据分析 ===")
print(f"总光路数量: {len(light_paths)}")
# 统计每条光路的点数
path_lengths = [len(path) for path in light_paths]
print(f"光路点数统计:")
print(f" 最少点数: {min(path_lengths)}")
print(f" 最多点数: {max(path_lengths)}")
print(f" 平均点数: {np.mean(path_lengths):.2f}")
# 计算边界
bounds = calculate_bounds(light_paths)
if bounds:
min_coords, max_coords = bounds
print(f"\n坐标范围:")
print(f" X: [{min_coords[0]:.3f}, {max_coords[0]:.3f}]")
print(f" Y: [{min_coords[1]:.3f}, {max_coords[1]:.3f}]")
print(f" Z: [{min_coords[2]:.3f}, {max_coords[2]:.3f}]")
# 创建光路对象
print(f"\n正在创建光路对象...")
light_path_objects = create_light_path_objects(light_paths)
# 设置场景
print("正在设置场景...")
setup_scene()
# 调整相机
if bounds:
adjust_camera_to_bounds(bounds[0], bounds[1])
# 导出模型
print("正在导出模型...")
export_model(light_path_objects)
# 渲染图像
print("正在渲染图像...")
render_image()
print("\n🎉 任务完成!")
print("\n生成的文件:")
print("- light_path_model.blend: Blender工程文件")
print("- light_path_model.glb: Web友好格式")
print("- light_path_render.png: 渲染图像")
print(f"\n成功创建了 {len(light_path_objects)} 条光路")
if __name__ == "__main__":
main()

BIN
light_path_render.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

BIN
light_path_simple.blend Normal file

Binary file not shown.

BIN
light_path_simple.glb Normal file

Binary file not shown.

200
light_path_simple.py Normal file
View File

@@ -0,0 +1,200 @@
#!/usr/bin/env python3
"""
光路可视化Blender脚本
读取miao_light_path_tsingtao.json文件并使用Blender绘制3D光路模型
使用方法:
blender --background --python light_path_simple.py
输出文件:
- light_path_simple.blend - Blender工程文件
- light_path_simple.glb - Web友好格式
- light_path_simple_render.png - 渲染图像
"""
import bpy
import json
import os
import numpy as np
# 清空场景
bpy.ops.wm.read_factory_settings(use_empty=True)
def load_light_paths(filename):
"""加载光路数据"""
try:
with open(filename, 'r', encoding='utf-8') as f:
data = json.load(f)
print(f"成功加载光路文件: {filename}")
print(f"包含 {len(data)} 条光路")
return data
except Exception as e:
print(f"加载光路文件失败: {e}")
return []
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 = 1.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.02
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), # 紫色
]
for i, path in enumerate(light_paths[len(light_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 setup_scene():
"""设置场景"""
# 添加相机
bpy.ops.object.camera_add(location=(10, -10, 8))
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=(5, 5, 10))
sun = bpy.context.active_object
sun.data.energy = 2.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.05, 0.05, 0.1, 1.0)
bg_node.inputs['Strength'].default_value = 0.5
def save_files():
"""保存文件"""
try:
# 保存Blender文件
blend_path = os.path.abspath("./light_path_simple.blend")
bpy.ops.wm.save_as_mainfile(filepath=blend_path)
print(f"Blender文件已保存为: {blend_path}")
# 导出GLB文件
glb_path = os.path.abspath("./light_path_simple.glb")
bpy.ops.export_scene.gltf(
filepath=glb_path,
export_materials='EXPORT'
)
print(f"GLB文件已导出为: {glb_path}")
# 渲染图像
scene = bpy.context.scene
scene.render.resolution_x = 1280
scene.render.resolution_y = 720
scene.render.image_settings.file_format = 'PNG'
render_path = os.path.abspath("./light_path_simple_render.png")
scene.render.filepath = render_path
bpy.ops.render.render(write_still=True)
print(f"渲染图像已保存为: {render_path}")
return True
except Exception as e:
print(f"保存文件时出错: {e}")
return False
def main():
"""主函数"""
print("🎨 光学系统光路可视化 - 简化版")
print("=" * 40)
# 加载光路数据
light_paths = load_light_paths("miao_light_path_tsingtao.json")
if not light_paths:
print("❌ 无法加载光路数据")
return
print(f"处理前10条光路...")
# 创建光路对象
light_path_objects = create_light_paths(light_paths)
# 设置场景
setup_scene()
# 保存文件
if save_files():
print("\n🎉 任务完成!")
print(f"成功创建了 {len(light_path_objects)} 条光路")
else:
print("\n❌ 保存文件失败")
if __name__ == "__main__":
main()

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 MiB

17102
miao_light_path_tsingtao.json Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -4,6 +4,7 @@ charset-normalizer==3.4.2
Cython==3.1.2 Cython==3.1.2
idna==3.10 idna==3.10
mathutils==3.3.0 mathutils==3.3.0
matplotlib==3.8.4
numpy==1.26.4 numpy==1.26.4
requests==2.32.4 requests==2.32.4
urllib3==2.5.0 urllib3==2.5.0

155
run_light_path.py Normal file
View File

@@ -0,0 +1,155 @@
#!/usr/bin/env python3
"""
运行光路可视化脚本
使用Blender生成光学系统光路模型
使用方法:
1. 确保已安装Blender
2. 运行此脚本: python run_light_path.py
输出文件:
- light_path_model.blend - Blender工程文件
- light_path_model.glb - Web友好格式
- light_path_render.png - 渲染图像
"""
import subprocess
import sys
import os
import platform
def find_blender():
"""查找Blender可执行文件"""
system = platform.system()
common_paths = []
if system == "Windows":
common_paths = [
r"C:\Program Files\Blender Foundation\Blender 3.6\blender.exe",
r"C:\Program Files\Blender Foundation\Blender 4.0\blender.exe",
r"C:\Program Files\Blender Foundation\Blender 4.1\blender.exe",
r"C:\Program Files (x86)\Blender Foundation\Blender 3.6\blender.exe",
]
elif system == "Darwin": # macOS
common_paths = [
"/Applications/Blender.app/Contents/MacOS/Blender",
"/usr/local/bin/blender",
]
elif system == "Linux":
common_paths = [
"/usr/bin/blender",
"/usr/local/bin/blender",
"/snap/bin/blender",
]
# 首先尝试从PATH中找到blender
try:
result = subprocess.run(["which", "blender"], capture_output=True, text=True)
if result.returncode == 0:
return result.stdout.strip()
except:
pass
# 尝试常见路径
for path in common_paths:
if os.path.exists(path):
return path
return None
def run_light_path_script():
"""运行光路可视化Blender脚本"""
blender_path = find_blender()
if not blender_path:
print("❌ 错误未找到Blender安装")
print("\n请确保已安装Blender并且可以从命令行访问")
print("下载地址: https://www.blender.org/download/")
return False
print(f"✅ 找到Blender: {blender_path}")
# 检查必要文件
script_path = os.path.abspath("light_path_blender.py")
if not os.path.exists(script_path):
print(f"❌ 错误:未找到脚本文件 {script_path}")
return False
json_path = os.path.abspath("miao_light_path_tsingtao.json")
if not os.path.exists(json_path):
print(f"❌ 错误:未找到光路数据文件 {json_path}")
return False
print("🚀 开始运行光路可视化脚本...")
print("这可能需要几分钟时间,请耐心等待...")
try:
# 运行Blender脚本
cmd = [
blender_path,
"--background", # 后台运行
"--python", script_path
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=600) # 10分钟超时
if result.returncode == 0:
print("✅ 光路可视化脚本执行成功!")
print("\n输出信息:")
print(result.stdout)
# 检查生成的文件
expected_files = [
"light_path_model.blend",
"light_path_model.glb",
"light_path_render.png"
]
print("\n📁 生成的文件:")
for filename in expected_files:
if os.path.exists(filename):
size = os.path.getsize(filename)
print(f"{filename} ({size:,} bytes)")
else:
print(f"{filename} (未找到)")
return True
else:
print("❌ 光路可视化脚本执行失败")
print("错误输出:")
print(result.stderr)
if result.stdout:
print("标准输出:")
print(result.stdout)
return False
except subprocess.TimeoutExpired:
print("❌ 脚本执行超时超过10分钟")
return False
except Exception as e:
print(f"❌ 执行时出错: {e}")
return False
def main():
print("🎨 光学系统光路可视化")
print("=" * 40)
print("使用Blender生成3D光路模型")
print()
if run_light_path_script():
print("\n🎉 任务完成!")
print("\n您可以:")
print("1. 使用Blender打开 light_path_model.blend 文件进行编辑")
print("2. 在Web浏览器中查看 light_path_model.glb 文件")
print("3. 查看渲染图像 light_path_render.png")
print("\n光路模型特点:")
print("- 每条光路使用不同颜色区分")
print("- 发光材质效果,更真实的光线表现")
print("- 3D曲线表示支持多角度查看")
print("- 自动调整相机位置以最佳角度展示")
else:
print("\n❌ 任务失败,请检查错误信息")
sys.exit(1)
if __name__ == "__main__":
main()

169
run_light_path_advanced.py Normal file
View File

@@ -0,0 +1,169 @@
#!/usr/bin/env python3
"""
运行增强版光路可视化脚本
使用Blender生成光学系统高级光路模型
功能特点:
- 发光光路效果
- 光路起点和终点标记
- 光路密度可视化
- 高质量渲染
使用方法:
1. 确保已安装Blender
2. 运行此脚本: python run_light_path_advanced.py
输出文件:
- light_path_advanced.blend - Blender工程文件
- light_path_advanced.glb - Web友好格式
- light_path_render.png - 渲染图像
"""
import subprocess
import sys
import os
import platform
def find_blender():
"""查找Blender可执行文件"""
system = platform.system()
common_paths = []
if system == "Windows":
common_paths = [
r"C:\Program Files\Blender Foundation\Blender 3.6\blender.exe",
r"C:\Program Files\Blender Foundation\Blender 4.0\blender.exe",
r"C:\Program Files\Blender Foundation\Blender 4.1\blender.exe",
r"C:\Program Files (x86)\Blender Foundation\Blender 3.6\blender.exe",
]
elif system == "Darwin": # macOS
common_paths = [
"/Applications/Blender.app/Contents/MacOS/Blender",
"/usr/local/bin/blender",
]
elif system == "Linux":
common_paths = [
"/usr/bin/blender",
"/usr/local/bin/blender",
"/snap/bin/blender",
]
# 首先尝试从PATH中找到blender
try:
result = subprocess.run(["which", "blender"], capture_output=True, text=True)
if result.returncode == 0:
return result.stdout.strip()
except:
pass
# 尝试常见路径
for path in common_paths:
if os.path.exists(path):
return path
return None
def run_advanced_light_path_script():
"""运行增强版光路可视化Blender脚本"""
blender_path = find_blender()
if not blender_path:
print("❌ 错误未找到Blender安装")
print("\n请确保已安装Blender并且可以从命令行访问")
print("下载地址: https://www.blender.org/download/")
return False
print(f"✅ 找到Blender: {blender_path}")
# 检查必要文件
script_path = os.path.abspath("light_path_advanced.py")
if not os.path.exists(script_path):
print(f"❌ 错误:未找到脚本文件 {script_path}")
return False
json_path = os.path.abspath("miao_light_path_tsingtao.json")
if not os.path.exists(json_path):
print(f"❌ 错误:未找到光路数据文件 {json_path}")
return False
print("🚀 开始运行增强版光路可视化脚本...")
print("这可能需要较长时间,请耐心等待...")
print("增强版功能包括:")
print("- 发光光路效果")
print("- 起点和终点标记")
print("- 光路密度可视化")
print("- 高质量渲染")
try:
# 运行Blender脚本
cmd = [
blender_path,
"--background", # 后台运行
"--python", script_path
]
result = subprocess.run(cmd, capture_output=True, text=True, timeout=900) # 15分钟超时
if result.returncode == 0:
print("✅ 增强版光路可视化脚本执行成功!")
print("\n输出信息:")
print(result.stdout)
# 检查生成的文件
expected_files = [
"light_path_advanced.blend",
"light_path_advanced.glb",
"light_path_render.png"
]
print("\n📁 生成的文件:")
for filename in expected_files:
if os.path.exists(filename):
size = os.path.getsize(filename)
print(f"{filename} ({size:,} bytes)")
else:
print(f"{filename} (未找到)")
return True
else:
print("❌ 增强版光路可视化脚本执行失败")
print("错误输出:")
print(result.stderr)
if result.stdout:
print("标准输出:")
print(result.stdout)
return False
except subprocess.TimeoutExpired:
print("❌ 脚本执行超时超过15分钟")
return False
except Exception as e:
print(f"❌ 执行时出错: {e}")
return False
def main():
print("🎨 光学系统光路可视化 - 增强版")
print("=" * 50)
print("使用Blender生成高级3D光路模型")
print()
if run_advanced_light_path_script():
print("\n🎉 任务完成!")
print("\n您可以:")
print("1. 使用Blender打开 light_path_advanced.blend 文件进行编辑")
print("2. 在Web浏览器中查看 light_path_advanced.glb 文件")
print("3. 查看高质量渲染图像 light_path_render.png")
print("\n增强版光路模型特点:")
print("- 每条光路使用不同颜色和发光强度")
print("- 绿色球体标记光路起点")
print("- 红色球体标记光路终点")
print("- 光路密度体积可视化")
print("- 高质量Cycles渲染引擎")
print("- 自动优化相机角度和光照")
print("- 支持交互式3D查看")
else:
print("\n❌ 任务失败,请检查错误信息")
sys.exit(1)
if __name__ == "__main__":
main()

View File

@@ -68,8 +68,6 @@ def create_emissive_material():
mat = bpy.data.materials.new(name="emissive") mat = bpy.data.materials.new(name="emissive")
mat.use_nodes = True mat.use_nodes = True
bsdf = mat.node_tree.nodes["Principled BSDF"] bsdf = mat.node_tree.nodes["Principled BSDF"]
# 在Blender 4.0+中,发光属性可能位置不同
try: try:
if "Emission" in bsdf.inputs: if "Emission" in bsdf.inputs:
bsdf.inputs["Emission"].default_value = (1.0, 0.8, 0.2, 1.0) bsdf.inputs["Emission"].default_value = (1.0, 0.8, 0.2, 1.0)