Compare commits

...

10 Commits

Author SHA1 Message Date
nicomacbookpro
e876518844 readmexiugai 2025-09-04 08:51:38 +08:00
nicolas
86544c4d9b scale 2025-09-02 18:34:43 +08:00
nicolas
04c0eb0b9a circle 2025-09-02 18:32:37 +08:00
nicolas
ba7b249f48 xiugai 2025-09-02 17:51:49 +08:00
nicolas
a09c20bba6 circle 2025-09-02 17:51:40 +08:00
nicolas
85f2e82e12 circle 2025-09-02 17:43:22 +08:00
nicomacbookpro
ed37d800c2 readme 2025-09-02 15:59:18 +08:00
nicomacbookpro
565bb02a28 案例 2025-09-02 15:58:31 +08:00
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
29 changed files with 19554 additions and 65 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

View File

@@ -13,22 +13,26 @@
## 📋 系统要求 ## 📋 系统要求
- **Blender 3.6+** (推荐 4.0+) - **Blender 3.6+** (推荐 4.0+)
- **Python 3.7+** - **Python 3.11+**
- **操作系统**: Windows, macOS, Linux - **操作系统**: Windows, macOS, Linux
## 🛠️ 安装 ## 🛠️ 安装
### 1. 安装 Blender ### 1. 安装 Blender
从官网下载并安装: https://www.blender.org/download/ 从官网下载并安装: https://www.blender.org/download/
### 2. 验证安装 ### 2. 验证安装
```bash ```bash
# 确保可以从命令行访问Blender # 确保可以从命令行访问Blender
blender --version blender --version
``` ```
### 3. 准备数据文件 ### 3. 准备数据文件
确保您的 JSON 数据文件格式正确,包含以下结构: 确保您的 JSON 数据文件格式正确,包含以下结构:
```json ```json
{ {
"p": [0.0, 0.0, 0.0], "p": [0.0, 0.0, 0.0],
@@ -51,28 +55,37 @@ blender --version
## 🎯 使用方法 ## 🎯 使用方法
---------------------阅读到此请直接阅读 use.md 以下暂时废弃----------------------------------
### 方法 1: 使用运行脚本(推荐) ### 方法 1: 使用运行脚本(推荐)
```bash ```bash
python run_blender.py -i jsonfile.json python run_blender.py -i jsonfile.json
``` ```
### 方法 2: 直接运行 Blender 脚本 ### 方法 2: 直接运行 Blender 脚本
```bash ```bash
blender --background --python toModel.py blender --background --python toModel.py
``` ```
### 方法 3: 在 Blender GUI 中运行 ### 方法 3: 在 Blender GUI 中运行
1. 打开 Blender 1. 打开 Blender
2. 切换到 Scripting 工作区 2. 切换到 Scripting 工作区
3. 打开 `toModel.py` 文件 3. 打开 `toModel.py` 文件
4. 点击运行按钮 4. 点击运行按钮
### 综合
✅ 融合光学系统脚本执行成功!
## 📁 输出文件 ## 📁 输出文件
运行成功后,将生成以下文件: 运行成功后,将生成以下文件:
| 文件名 | 格式 | 用途 | | 文件名 | 格式 | 用途 |
|--------|------|------| | --------------------------- | ------- | ------------------------------------------- |
| `optical_system.obj` | OBJ | 通用 3D 模型格式,可在大多数 3D 软件中打开 | | `optical_system.obj` | OBJ | 通用 3D 模型格式,可在大多数 3D 软件中打开 |
| `optical_system.glb` | GLB | Web 友好格式,适合在线展示 | | `optical_system.glb` | GLB | Web 友好格式,适合在线展示 |
| `optical_system.blend` | Blender | 完整的 Blender 工程文件,包含所有材质和设置 | | `optical_system.blend` | Blender | 完整的 Blender 工程文件,包含所有材质和设置 |
@@ -81,16 +94,19 @@ blender --background --python toModel.py
## ⚙️ 配置选项 ## ⚙️ 配置选项
### 几何体类型支持 ### 几何体类型支持
- **plane**: 平面镜/透镜 - **plane**: 平面镜/透镜
- **parabola**: 抛物面镜,使用 `face_f` 参数控制焦距 - **parabola**: 抛物面镜,使用 `face_f` 参数控制焦距
- **hyperbola**: 双曲面镜,使用 `face_f``face_g` 参数 - **hyperbola**: 双曲面镜,使用 `face_f``face_g` 参数
### 材质类型 ### 材质类型
- **metal**: 金属反射材质(淡蓝色) - **metal**: 金属反射材质(淡蓝色)
- **nothing**: 透明材质10%不透明度) - **nothing**: 透明材质10%不透明度)
- **其他**: 发光材质(橙色光) - **其他**: 发光材质(橙色光)
### 渲染设置 ### 渲染设置
- 分辨率: 1920x1080 - 分辨率: 1920x1080
- 引擎: Cycles支持高质量材质 - 引擎: Cycles支持高质量材质
- 格式: PNG - 格式: PNG
@@ -98,7 +114,9 @@ blender --background --python toModel.py
## 🔧 自定义 ## 🔧 自定义
### 修改材质 ### 修改材质
编辑 `toModel.py` 中的材质创建函数: 编辑 `toModel.py` 中的材质创建函数:
```python ```python
def create_metal_material(): def create_metal_material():
# 修改金属材质属性 # 修改金属材质属性
@@ -108,12 +126,15 @@ def create_metal_material():
``` ```
### 调整几何体精度 ### 调整几何体精度
修改分辨率参数: 修改分辨率参数:
```python ```python
mesh = create_parabolic_surface(face_f, size=2.0, resolution=64) # 更高精度 mesh = create_parabolic_surface(face_f, size=2.0, resolution=64) # 更高精度
``` ```
### 修改渲染设置 ### 修改渲染设置
```python ```python
scene.render.resolution_x = 3840 # 4K分辨率 scene.render.resolution_x = 3840 # 4K分辨率
scene.render.resolution_y = 2160 scene.render.resolution_y = 2160
@@ -124,21 +145,27 @@ scene.render.resolution_y = 2160
### 常见问题 ### 常见问题
**Q: 找不到 Blender** **Q: 找不到 Blender**
``` ```
❌ 错误未找到Blender安装 ❌ 错误未找到Blender安装
``` ```
A: 确保 Blender 已正确安装并添加到系统 PATH 中 A: 确保 Blender 已正确安装并添加到系统 PATH 中
**Q: 几何体创建失败** **Q: 几何体创建失败**
``` ```
创建几何体时出错: ... 创建几何体时出错: ...
``` ```
A: 检查 JSON 数据中的 `face_f``face_g` 参数是否为有效数值 A: 检查 JSON 数据中的 `face_f``face_g` 参数是否为有效数值
**Q: 导出失败** **Q: 导出失败**
``` ```
模型导出失败 模型导出失败
``` ```
A: 确保有写入权限,检查磁盘空间 A: 确保有写入权限,检查磁盘空间
### 调试技巧 ### 调试技巧
@@ -150,11 +177,13 @@ A: 确保有写入权限,检查磁盘空间
## 📈 性能优化 ## 📈 性能优化
### 大型数据集 ### 大型数据集
- 对于超过 100 个对象的数据集,考虑分批处理 - 对于超过 100 个对象的数据集,考虑分批处理
- 降低几何体分辨率以提高性能 - 降低几何体分辨率以提高性能
- 使用后台模式避免 GUI 开销 - 使用后台模式避免 GUI 开销
### 内存使用 ### 内存使用
- 大型模型可能需要 8GB+内存 - 大型模型可能需要 8GB+内存
- 监控内存使用,必要时重启 Blender - 监控内存使用,必要时重启 Blender

157
README_fused_system.md Normal file
View File

@@ -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
## 许可证
本脚本遵循与原始脚本相同的许可证条款。

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
- 发送邮件至项目维护者
---
**注意**: 确保在运行脚本前备份重要文件,脚本会生成新的文件并可能覆盖同名文件。

View File

@@ -35,7 +35,7 @@
"p": [ "p": [
-6.0, -6.0,
0.0, 0.0,
0.0 -5.0
], ],
"q": [ "q": [
1.0, 1.0,
@@ -44,9 +44,10 @@
0.0 0.0
], ],
"name": "M00", "name": "M00",
"scale": 2,
"face_type": "symm", "face_type": "symm",
"face_geometry": "parabola", "face_geometry": "circle",
"face_f": 5.0, "face_f": 1e10,
"face_g": 1e10, "face_g": 1e10,
"draw_material": "metal" "draw_material": "metal"
}, },
@@ -63,8 +64,9 @@
0.0 0.0
], ],
"name": "M10", "name": "M10",
"scale": 2,
"face_type": "symm", "face_type": "symm",
"face_geometry": "parabola", "face_geometry": "circle",
"face_f": 1.0, "face_f": 1.0,
"face_g": 1e10, "face_g": 1e10,
"draw_material": "metal" "draw_material": "metal"
@@ -92,7 +94,7 @@
"p": [ "p": [
6.0, 6.0,
0.0, 0.0,
0.0 -1.0
], ],
"q": [ "q": [
0.0, 0.0,
@@ -111,7 +113,7 @@
"p": [ "p": [
6.0, 6.0,
0.0, 0.0,
0.0 -5.0
], ],
"q": [ "q": [
0.0, 0.0,
@@ -121,8 +123,9 @@
], ],
"name": "M01", "name": "M01",
"face_type": "symm", "face_type": "symm",
"face_geometry": "parabola", "face_geometry": "circle",
"face_f": 5.0, "scale": 2,
"face_f": 1e10,
"face_g": 1e10, "face_g": 1e10,
"draw_material": "metal" "draw_material": "metal"
}, },
@@ -140,7 +143,8 @@
], ],
"name": "M11", "name": "M11",
"face_type": "symm", "face_type": "symm",
"face_geometry": "parabola", "face_geometry": "circle",
"scale": 2,
"face_f": 1.0, "face_f": 1.0,
"face_g": 1e10, "face_g": 1e10,
"draw_material": "metal" "draw_material": "metal"
@@ -206,7 +210,7 @@
"p": [ "p": [
0.0, 0.0,
0.0, 0.0,
0.0 -5.0
], ],
"q": [ "q": [
1.0, 1.0,
@@ -216,17 +220,37 @@
], ],
"name": "M6", "name": "M6",
"face_type": "symm", "face_type": "symm",
"face_geometry": "parabola", "face_geometry": "circle",
"face_f": 5.0, "scale": 2.5,
"face_f": 1e10,
"face_g": 1e10, "face_g": 1e10,
"draw_material": "metal" "draw_material": "metal"
}, },
{ {
"p": [ "p": [
-6.0,
0.0,
-1.0
],
"q": [
1.0,
0.0, 0.0,
0.0, 0.0,
0.0 0.0
], ],
"name": "E0",
"face_type": "symm",
"face_geometry": "circle",
"face_f": 1e10,
"face_g": 1e10,
"draw_material": "nothing"
},
{
"p": [
0.0,
0.0,
-1.0
],
"q": [ "q": [
1.0, 1.0,
0.0, 0.0,
@@ -235,30 +259,11 @@
], ],
"name": "M7", "name": "M7",
"face_type": "symm", "face_type": "symm",
"face_geometry": "hyperbola", "face_geometry": "circle",
"face_f": 1.0, "face_f": 1.0,
"face_g": -6.875220831710909, "face_g": -6.875220831710909,
"draw_material": "metal" "draw_material": "metal"
}, },
{
"p": [
0.0,
0.0,
-7.875220831710909
],
"q": [
1.0,
0.0,
0.0,
0.0
],
"name": "D0",
"face_type": "symm",
"face_geometry": "circle",
"face_f": 1e10,
"face_g": 1e10,
"draw_material": "metal"
},
{ {
"p": [ "p": [
-1.9818052586129662, -1.9818052586129662,

339
circle.json.bak Normal file
View File

@@ -0,0 +1,339 @@
{
"p": [
0.0,
0.0,
0.0
],
"q": [
1.0,
0.0,
0.0,
0.0
],
"name": "",
"children": [
{
"p": [
-6.0,
0.0,
0.0
],
"q": [
1.0,
0.0,
0.0,
0.0
],
"name": "E0",
"face_type": "symm",
"face_geometry": "circle",
"face_f": 1e10,
"face_g": 1e10,
"draw_material": "nothing"
},
{
"p": [
-6.0,
0.0,
-5.0
],
"q": [
1.0,
0.0,
0.0,
0.0
],
"name": "M00",
"face_type": "symm",
"face_geometry": "circle",
"face_f": 1e10,
"face_g": 1e10,
"draw_material": "metal"
},
{
"p": [
-6.0,
0.0,
0.0
],
"q": [
1.0,
0.0,
0.0,
0.0
],
"name": "M10",
"face_type": "symm",
"face_geometry": "parabola",
"face_f": 1.0,
"face_g": 1e10,
"draw_material": "metal"
},
{
"p": [
-6.0,
0.0,
-5.974533048268448
],
"q": [
0.9238795325112867,
-0.0,
0.3826834323650898,
0.0
],
"name": "M20",
"face_type": "symm",
"face_geometry": "circle",
"face_f": 1e10,
"face_g": 1e10,
"draw_material": "metal"
},
{
"p": [
6.0,
0.0,
0.0
],
"q": [
0.0,
0.0,
0.0,
1.0
],
"name": "E1",
"face_type": "symm",
"face_geometry": "circle",
"face_f": 1e10,
"face_g": 1e10,
"draw_material": "nothing"
},
{
"p": [
6.0,
0.0,
0.0
],
"q": [
0.0,
0.0,
0.0,
1.0
],
"name": "M01",
"face_type": "symm",
"face_geometry": "parabola",
"face_f": 5.0,
"face_g": 1e10,
"draw_material": "metal"
},
{
"p": [
6.0,
0.0,
0.0
],
"q": [
0.0,
0.0,
0.0,
1.0
],
"name": "M11",
"face_type": "symm",
"face_geometry": "parabola",
"face_f": 1.0,
"face_g": 1e10,
"draw_material": "metal"
},
{
"p": [
6.0,
0.0,
-5.974533048268448
],
"q": [
0.0,
-0.3826834323650898,
0.0,
0.9238795325112867
],
"name": "M21",
"face_type": "symm",
"face_geometry": "circle",
"face_f": 1e10,
"face_g": 1e10,
"draw_material": "metal"
},
{
"p": [
-1.9818052586129662,
0.0,
-5.974533048268448
],
"q": [
0.9238795325112867,
0.0,
-0.3826834323650898,
0.0
],
"name": "M30",
"face_type": "symm",
"face_geometry": "circle",
"face_f": 1e10,
"face_g": 1e10,
"draw_material": "metal"
},
{
"p": [
1.9818052586129662,
0.0,
-5.974533048268448
],
"q": [
0.9238795325112867,
-0.0,
0.3826834323650898,
0.0
],
"name": "M31",
"face_type": "symm",
"face_geometry": "circle",
"face_f": 1e10,
"face_g": 1e10,
"draw_material": "metal"
},
{
"p": [
0.0,
0.0,
-5.0
],
"q": [
1.0,
0.0,
0.0,
0.0
],
"name": "M6",
"face_type": "symm",
"face_geometry": "parabola",
"face_f": 5.0,
"face_g": 1e10,
"draw_material": "metal"
},
{
"p": [
0.0,
0.0,
-2.0
],
"q": [
1.0,
0.0,
0.0,
0.0
],
"name": "M7",
"face_type": "symm",
"face_geometry": "hyperbola",
"face_f": 1.0,
"face_g": -6.875220831710909,
"draw_material": "metal"
},
{
"p": [
0.0,
0.0,
-7.875220831710909
],
"q": [
1.0,
0.0,
0.0,
0.0
],
"name": "D0",
"face_type": "symm",
"face_geometry": "circle",
"face_f": 1e10,
"face_g": 1e10,
"draw_material": "metal"
},
{
"p": [
-1.9818052586129662,
0.0,
0.0
],
"q": [
0.9238795325112867,
0.0,
-0.3826834323650898,
0.0
],
"name": "M40",
"face_type": "symm",
"face_geometry": "circle",
"face_f": 1e10,
"face_g": 1e10,
"draw_material": "metal"
},
{
"p": [
-1.0,
0.0,
0.0
],
"q": [
0.9238795325112867,
-0.0,
0.3826834323650898,
0.0
],
"name": "M50",
"face_type": "symm",
"face_geometry": "circle",
"face_f": 1e10,
"face_g": 1e10,
"draw_material": "metal"
},
{
"p": [
1.9818052586129662,
0.0,
0.0
],
"q": [
0.9238795325112867,
-0.0,
0.3826834323650898,
0.0
],
"name": "M41",
"face_type": "symm",
"face_geometry": "circle",
"face_f": 1e10,
"face_g": 1e10,
"draw_material": "metal"
},
{
"p": [
1.0,
0.0,
0.0
],
"q": [
0.9238795325112867,
0.0,
-0.3826834323650898,
0.0
],
"name": "M51",
"face_type": "symm",
"face_geometry": "circle",
"face_f": 1e10,
"face_g": 1e10,
"draw_material": "metal"
}
]
}

BIN
fused_optical_system.blend Normal file

Binary file not shown.

BIN
fused_optical_system.blend1 Normal file

Binary file not shown.

BIN
fused_optical_system.glb Normal file

Binary file not shown.

559
fused_optical_system.py Normal file
View File

@@ -0,0 +1,559 @@
#!/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)
scale = obj_data.get("scale", 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":
# 创建圆形平面
radius = 0.5 * scale
bpy.ops.mesh.primitive_circle_add(vertices=32, radius=radius)
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()

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 MiB

1
gl.json Normal file

File diff suppressed because one or more lines are too long

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

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1008 KiB

After

Width:  |  Height:  |  Size: 1008 KiB

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

132
run_fused_system.py Normal file
View File

@@ -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 = "./circle.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()

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)

8
use.md Normal file
View File

@@ -0,0 +1,8 @@
# 先看 README.md 安装 blender
然后(最好虚拟环境 python version >=3.11
pip install -r requirements.txt
python3 run_fused_system.py
fused_optical_system.glb 为最终产出