Refactor Cesium material export contract
This commit is contained in:
@@ -78,8 +78,9 @@ catalog.MATERIALS 声明「是什么」 纯 Python,无 bpy
|
||||
2. 若 `kind` 是 `textured`,贴图放 `assets/textures/`(`materials.py:14` 的
|
||||
`TEXTURE_ROOT`)
|
||||
3. `generate_scene.py` 里用 `material_from_spec(catalog.MATERIALS["<key>"])` 取
|
||||
4. **若这个材质在 Cesium 里需要调色,去 `export_cesium.py` 的四张表加**——
|
||||
见下文,那边按材质名字符串匹配
|
||||
4. **若这个材质在 Cesium 里需要调色,把 `cesium` 子契约写在同一个
|
||||
`MATERIALS` 条目里**。`materials.from_spec()` 会把它序列化到
|
||||
`material["cesium_export"]`,导出器优先读这个属性
|
||||
|
||||
### 颜色是线性 RGB
|
||||
|
||||
@@ -160,18 +161,24 @@ tilt_y = TILT_JITTER * math.cos(index * 0.927295)
|
||||
模型保持在**局部 ENU 坐标系**(X 东、Y 北、Z 上),靠伴生 JSON 配合
|
||||
`Cesium.Transforms.eastNorthUpToFixedFrame` 摆放。
|
||||
|
||||
### 四张覆盖表(按材质名字符串)
|
||||
### Cesium contract
|
||||
|
||||
| 表 | 位置 | 作用 |
|
||||
|---|---|---|
|
||||
| `EXPORT_TINTS` | `:68` | 往某个颜色混合 |
|
||||
| `EXPORT_METALLIC_OVERRIDES` | `:80` | 平铺的金属度覆盖 |
|
||||
| `EXPORT_BASE_COLOR_OVERRIDES` | `:86` | 直接替换基色 |
|
||||
| `EXPORT_EMISSION_OVERRIDES` | `:95` | 自发光兜底 |
|
||||
新生成场景的 Cesium 导出调色写在 `catalog.MATERIALS[*]["cesium"]`,由
|
||||
`materials.from_spec()` 保存成材质自定义属性 `material["cesium_export"]`。导出器打开
|
||||
`.blend` 后优先读这个属性,不 import `catalog`。
|
||||
|
||||
⚠️ `export_cesium.py` **不 import `catalog`**,靠材质名字符串匹配。
|
||||
`catalog.CESIUM_EXPORT` 是**死代码**。改材质名前先读
|
||||
[模块结构](./module-structure.md#已知现状两个入口靠材质名字符串对接)。
|
||||
`cesium` 子契约字段:
|
||||
|
||||
| 字段 | 作用 |
|
||||
|---|---|
|
||||
| `tint` | diffuse 贴图导出前往目标颜色混合 |
|
||||
| `metallic` | 覆盖导出 PBR metallic |
|
||||
| `base_color` | 直接替换导出基色,并禁用 diffuse/normal 图 |
|
||||
| `emission` | 自发光兜底 |
|
||||
|
||||
`export_cesium.py` 仍保留 `EXPORT_TINTS`、`EXPORT_METALLIC_OVERRIDES`、
|
||||
`EXPORT_BASE_COLOR_OVERRIDES`、`EXPORT_EMISSION_OVERRIDES` 四张按材质名字符串匹配的表,
|
||||
但它们只是旧 `.blend` 兼容回退。新材质不要只写旧表。
|
||||
|
||||
### 为什么新资产总是"发黑"
|
||||
|
||||
@@ -181,8 +188,8 @@ tilt_y = TILT_JITTER * math.cos(index * 0.927295)
|
||||
> 带肋墙面往白混 86%、建筑自发光 0.18。一个没调过的新资产是唯一如实渲染的东西,
|
||||
> 放在旁边就显得发黑。
|
||||
|
||||
所以**加新资产时,"它在 Blender 里看着对"不代表在 Cesium 里对**,必须去四张表里
|
||||
给它配一份调校。
|
||||
所以**加新资产时,"它在 Blender 里看着对"不代表在 Cesium 里对**,必须在
|
||||
`catalog.MATERIALS[*]["cesium"]` 里给它配一份调校。
|
||||
|
||||
抠图植被走的是另一套(`FOLIAGE_ALBEDO_GAIN = 2.1` + `FOLIAGE_SATURATION = 1.75`,
|
||||
`:55, 66`),用**增益**而不是 tint——因为那是一张同时装着叶片、树皮、果实的图集,
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
| 新建模块、挪代码、加一种 OSM 要素 | [模块结构](./module-structure.md) ← **先确认放在哪一层** |
|
||||
| 改几何构建、材质、实例化、Cesium 调色 | [资产生成](./asset-generation.md) |
|
||||
| 改 `geom.py` / `osm.py` 或加纯函数 | [测试](./testing.md) |
|
||||
| 改材质名、动 `MATERIALS` 顺序 | [模块结构 · 材质名对接](./module-structure.md#已知现状两个入口靠材质名字符串对接) |
|
||||
| 改材质名、动 `MATERIALS` 顺序 | [模块结构 · 材质名对接](./module-structure.md#材质名对接新场景靠自定义属性旧场景靠回退表) |
|
||||
| 声称"纯重构,产物不变" | [产物一致性指南](../guides/artifact-parity-guide.md) |
|
||||
|
||||
---
|
||||
|
||||
@@ -135,31 +135,52 @@ argv = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
|
||||
|
||||
---
|
||||
|
||||
## ⚠️ 已知现状:两个入口靠材质名字符串对接
|
||||
## 材质名对接:新场景靠自定义属性,旧场景靠回退表
|
||||
|
||||
**这是当前实际状态,不是设计目标。改动材质名之前必读。**
|
||||
`export_cesium.py` **不 import `catalog`**,这是刻意边界:导出器消费 `.blend`
|
||||
里保存的材质事实,而不是用当前源码里的 catalog 按材质名反查。
|
||||
|
||||
`export_cesium.py` **不 import `catalog`**(它只 import
|
||||
`from osmassets.materials import link_alpha_clip`)。它自己维护四张以**材质名字符串**
|
||||
为键的覆盖表:
|
||||
新生成场景的数据流是:
|
||||
|
||||
```
|
||||
catalog.MATERIALS[*]["cesium"] # 纯 Python 数据,无 bpy
|
||||
↓
|
||||
materials.from_spec() # 写 material["cesium_export"] JSON 字符串
|
||||
↓
|
||||
<area>.blend # 契约随场景文件保存
|
||||
↓
|
||||
export_cesium.py # 优先读 material custom property
|
||||
```
|
||||
|
||||
`cesium` 子契约可携带:
|
||||
|
||||
| 字段 | 作用 |
|
||||
|---|---|
|
||||
| `tint` | diffuse 贴图导出前往目标颜色混合 |
|
||||
| `metallic` | 覆盖导出 PBR metallic |
|
||||
| `base_color` | 直接覆盖导出材质 base color,并禁用 diffuse/normal 图 |
|
||||
| `emission` | 设置导出材质自发光 |
|
||||
|
||||
为了兼容旧 `.blend`,`export_cesium.py` 仍保留四张以**材质名字符串**为键的回退表:
|
||||
|
||||
| 表 | 位置 |
|
||||
|---|---|
|
||||
| `EXPORT_TINTS` | `export_cesium.py:68` |
|
||||
| `EXPORT_METALLIC_OVERRIDES` | `:80` |
|
||||
| `EXPORT_BASE_COLOR_OVERRIDES` | `:86` |
|
||||
| `EXPORT_EMISSION_OVERRIDES` | `:95` |
|
||||
| `EXPORT_TINTS` | `export_cesium.py` |
|
||||
| `EXPORT_METALLIC_OVERRIDES` | `export_cesium.py` |
|
||||
| `EXPORT_BASE_COLOR_OVERRIDES` | `export_cesium.py` |
|
||||
| `EXPORT_EMISSION_OVERRIDES` | `export_cesium.py` |
|
||||
|
||||
后果:
|
||||
约束:
|
||||
|
||||
- **改 `catalog.MATERIALS` 里的 `name` 会静默断开这些覆盖**。没有任何校验,
|
||||
材质只是悄悄退回未调过的样子
|
||||
- `catalog.CESIUM_EXPORT`(`catalog.py:142`)**是死代码**——定义了但全仓无人引用。
|
||||
它是一次未完成的迁移,不要以为改它会生效
|
||||
- **新材质的 Cesium 调色写在 `catalog.MATERIALS[*]["cesium"]`,不要只加到四张回退表**。
|
||||
否则新生成的 `.blend` 不会自带契约
|
||||
- `catalog.py` 仍属纯 Python 层,不能 import `bpy`;序列化发生在 `materials.py`
|
||||
- `"Office White Metal Facade"` 在四张表里都有,但 `catalog` 里**已无此材质**
|
||||
(`docs/refactor-plan.md` 记为缺陷 D1,本轮只记录不修)
|
||||
(`docs/refactor-plan.md` 记为缺陷 D1)。它只能作为旧 `.blend` 回退兼容存在,
|
||||
不要迁回新契约源
|
||||
|
||||
**改材质名时**:四张表 + `catalog.MATERIALS` + `catalog.ROAD_LAYERS` 全部 grep 一遍。
|
||||
**改材质名时**:`catalog.MATERIALS` + `catalog.ROAD_LAYERS` + 四张旧回退表全部
|
||||
grep 一遍;新生成场景靠 `cesium_export` 属性,旧场景仍靠回退表。
|
||||
|
||||
---
|
||||
|
||||
@@ -172,8 +193,8 @@ argv = sys.argv[sys.argv.index("--") + 1:] if "--" in sys.argv else []
|
||||
| 删掉 `sys.path.insert` 样板或 `# noqa: E402` | Blender 里 import 不到 osmassets |
|
||||
| 要素模块假设 ring 已裁剪 | 越界几何进场景 |
|
||||
| 要素模块对退化输入抛异常 | 一个坏多边形中断整片区域 |
|
||||
| 改材质名只改一处 | Cesium 侧调色静默失效 |
|
||||
| 以为改 `catalog.CESIUM_EXPORT` 会影响导出 | 它是死代码 |
|
||||
| 改材质名只改一处 | 旧 `.blend` 的 Cesium 回退调色可能静默失效 |
|
||||
| 只改四张旧回退表,不改 `MATERIALS[*]["cesium"]` | 新 `.blend` 不会携带 Cesium 导出契约 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ capturedAt / durationMs / label
|
||||
|---|---|
|
||||
| 挪函数、拆模块、改导入 | **必须**——纯重构的定义就是产物不变 |
|
||||
| 调整 `ROAD_LAYERS` / `MATERIALS` 的**顺序** | **必须**——会平移 GLB 材质索引 |
|
||||
| 改材质名 | **必须**——可能静默断开 Cesium 侧的四张覆盖表 |
|
||||
| 改材质名 | **必须**——可能影响新 `.blend` 的 `cesium_export` 契约或旧 `.blend` 的回退表 |
|
||||
| 改几何构建、采样、实例化逻辑 | **必须** |
|
||||
| 改 stage 的 stdout 打印 | **必须**——标记本身是契约 |
|
||||
| 改 `.trellis/` 下的文档 | 不用 |
|
||||
@@ -164,13 +164,13 @@ capturedAt / durationMs / label
|
||||
| P0 | 抽纯函数到 `osmassets/{osm,geom}.py` | ✅ 已完成 |
|
||||
| P1 | `catalog.py` 单一定义源 + `check_layers` | ✅ 已完成 |
|
||||
| P2 | 要素注册表 | ⚠️ **部分**——`water/grass/scrub/tree.py` 已拆出,但**没有 `features/` 注册表**,`building` / `fountain` / `roads` 仍在 `generate_scene.py` 里 |
|
||||
| P3 | 材质契约化(自定义属性传递 spec) | ❌ **未做**——`export_cesium.py` 仍不 import `catalog`,靠四张材质名表;`catalog.CESIUM_EXPORT` 是死代码 |
|
||||
| P3 | 材质契约化(自定义属性传递 spec) | ✅ 已完成——`catalog.MATERIALS[*]["cesium"]` 经 `materials.from_spec()` 写入 `material["cesium_export"]`,`export_cesium.py` 优先读该属性;四张材质名表仅作旧 `.blend` 回退 |
|
||||
|
||||
### 已知缺陷(记录在案,本轮不修)
|
||||
|
||||
| # | 位置 | 现象 |
|
||||
|---|---|---|
|
||||
| D1 | `export_cesium.py:74,82,91,100` | `"Office White Metal Facade"` 四张表里都有,但 `catalog` 里已无此材质——死条目 |
|
||||
| D1 | `export_cesium.py` 旧回退表 | `"Office White Metal Facade"` 四张表里都有,但 `catalog` 里已无此材质——只作为旧 `.blend` 回退兼容保留 |
|
||||
| D2 | `scene-layers.js` vs `catalog.py` | 同一批图层的颜色两侧各自手调,无一致性保证(**这是刻意的**,见[图层表](../pipeline/layer-registry.md#为什么颜色刻意不同步)) |
|
||||
| D3 | `generate_scene.py` `tuft_density_wave` | 注释仍在跟已删除的 hedge banding 作对比 |
|
||||
|
||||
|
||||
@@ -55,8 +55,11 @@ Blender 高度与线性颜色。两侧靠 `catalog.check_layers()` 对账集合
|
||||
Blender 内材质声明集中在 `catalog.MATERIALS`(`catalog.py:56`)。
|
||||
真实 `bpy.types.Material` 由 `materials.from_spec()`(`materials.py:198`)构建。
|
||||
|
||||
注意当前有一个未完成迁移:`export_cesium.py:68`、`:80`、`:86`、`:95` 的四张表
|
||||
仍按材质名字符串匹配。改材质名时不能只改 `catalog`;必须全仓 grep 材质名。
|
||||
Cesium 导出调色也属于同一个材质声明:新场景把 `catalog.MATERIALS[*]["cesium"]`
|
||||
序列化到 `material["cesium_export"]`,`export_cesium.py` 优先读这个属性。四张
|
||||
`export_cesium.py` 材质名表仍存在,但只作为旧 `.blend` 的兼容回退。
|
||||
|
||||
改材质名时不能只改 `catalog`;必须全仓 grep 材质名,确认新契约和旧回退路径都合理。
|
||||
|
||||
---
|
||||
|
||||
@@ -155,4 +158,4 @@ Blender 内材质声明集中在 `catalog.MATERIALS`(`catalog.py:56`)。
|
||||
| 低层脚本直接读 `config/areas/*.json` | 两层配置边界失效 |
|
||||
| 只改一份 `parseArgs` 的语义 | 三个入口行为分裂 |
|
||||
| 把要素模块裁剪逻辑挪到调用方 | 不同要素的越界处理开始漂移 |
|
||||
| 只在 `catalog.CESIUM_EXPORT` 加导出覆盖 | 当前不会生效;导出器没读它 |
|
||||
| 只改 `export_cesium.py` 的旧回退表,不写 `MATERIALS[*]["cesium"]` | 新 `.blend` 不会携带 Cesium 导出契约 |
|
||||
|
||||
@@ -18,7 +18,7 @@ build-osm2streets-qgis.js Node + osm2streets WASM
|
||||
ogr2ogr / ogrinfo / QGIS Python GDAL/QGIS 运行时
|
||||
↓ ④ GeoJSON / GeoPackage 文件
|
||||
generate_scene.py Blender 内嵌 Python
|
||||
↓ ⑤ .blend 文件 + 材质名字符串
|
||||
↓ ⑤ .blend 文件 + 材质自定义属性
|
||||
export_cesium.py Blender 内嵌 Python
|
||||
↓ ⑥ GLB + JSON
|
||||
cesium-preview.js 浏览器
|
||||
@@ -30,7 +30,7 @@ cesium-preview.js 浏览器
|
||||
| ② | 两层配置 | 低层脚本读错配置源 |
|
||||
| ③ | Node → 外部进程 | 环境变量缺失、退出码与信号、0 字节产物 |
|
||||
| ④ | 文件交换 | 图层集合/顺序漂移、精度丢失 |
|
||||
| ⑤ | Python → Python | **材质名字符串**,无校验 |
|
||||
| ⑤ | Python → Python | 新场景靠 `material["cesium_export"]`,旧场景靠材质名回退表 |
|
||||
| ⑥ | Blender → 浏览器 | 坐标系约定、材质在两种光照下的差异 |
|
||||
|
||||
---
|
||||
@@ -65,7 +65,7 @@ cesium-preview.js 浏览器
|
||||
| 边界 | 靠什么连接 | 有没有校验 |
|
||||
|---|---|---|
|
||||
| `scene-layers.js` ↔ `catalog.py` | 图层 `id` 的集合与顺序 | ✅ `check_layers()`(warn) |
|
||||
| `generate_scene.py` ↔ `export_cesium.py` | **材质名字符串** | ❌ **无** |
|
||||
| `generate_scene.py` ↔ `export_cesium.py` | `.blend` 材质自定义属性 `cesium_export` | 部分(旧 `.blend` 仍靠材质名回退表) |
|
||||
| GeoJSON 文件名 ↔ 图层 id | `layerFile()` 拼 `<id>.geojson` | 部分(reimport 会检查 gpkg 图层是否齐全) |
|
||||
| stage stdout ↔ `parity.js` | `SCENE_DONE` / `CESIUM_EXPORT_DONE` 字面量 | ❌ 无 |
|
||||
| GLB 材质索引 ↔ `MATERIALS` 顺序 | 隐式的创建顺序 | ❌ 无(靠 parity 事后发现) |
|
||||
@@ -118,13 +118,17 @@ cesium-preview.js 浏览器
|
||||
|
||||
→ [资产生成](../blender/asset-generation.md#为什么新资产总是发黑)
|
||||
|
||||
### 坑 5:两个 Python 脚本靠字符串对接
|
||||
### 坑 5:新旧 `.blend` 的材质导出契约不同
|
||||
|
||||
`export_cesium.py` 不 import `catalog`,靠材质名字符串匹配四张覆盖表。
|
||||
改个材质名,Cesium 侧的调色**静默失效**。`catalog.CESIUM_EXPORT` 想解决这个问题,
|
||||
但迁移没做完,它现在是死代码。
|
||||
新生成场景把 Cesium 导出契约写进材质自定义属性 `material["cesium_export"]`:
|
||||
`catalog.MATERIALS[*]["cesium"]` → `materials.from_spec()` → `.blend` →
|
||||
`export_cesium.py`。导出器仍不 import `catalog`,这是为了让契约跟着 `.blend`
|
||||
走,而不是用当前源码按材质名反查。
|
||||
|
||||
**教训**:**字符串键的跨模块耦合必须配一个对账机制**,否则重命名就是定时炸弹。
|
||||
旧 `.blend` 没有这个属性,所以 `export_cesium.py` 仍保留四张材质名回退表。改材质名时,
|
||||
新场景和旧场景两条路都要想清楚。
|
||||
|
||||
**教训**:**跨阶段契约必须随产物保存;兼容旧产物的字符串回退也要被审查**。
|
||||
|
||||
---
|
||||
|
||||
@@ -141,7 +145,8 @@ cesium-preview.js 浏览器
|
||||
### 加一个材质
|
||||
|
||||
- [ ] `catalog.MATERIALS` **末尾**追加(中间插入会平移 GLB 材质索引)
|
||||
- [ ] 若在 Cesium 里需要调色,去 `export_cesium.py` 的四张表加
|
||||
- [ ] 若在 Cesium 里需要调色,写 `catalog.MATERIALS[*]["cesium"]`,不要只改旧回退表
|
||||
- [ ] 若要兼容旧 `.blend` 的同名材质,再审查 `export_cesium.py` 四张回退表
|
||||
- [ ] 跑 parity
|
||||
|
||||
### 加一个配置字段
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
|
||||
- [ ] 改 `scripts/lib/scene-layers.js:15` 的 `SCENE_LAYERS`
|
||||
- [ ] 改 `blender/osmassets/catalog.py:28` 的 `ROAD_LAYERS` 或 `catalog.py:56` 的 `MATERIALS`
|
||||
- [ ] 改 `blender/export_cesium.py:68` 等四张按材质名字符串匹配的覆盖表
|
||||
- [ ] 改 `catalog.MATERIALS[*]["cesium"]`、`material["cesium_export"]` 或
|
||||
`export_cesium.py` 的旧材质名回退表
|
||||
- [ ] 改 `build-area.js:74` 的 `normalizeAreaConfig()` 或 `config/examples/template.json`
|
||||
- [ ] 改任何 `execFileSync` / `spawnSync` 调起的脚本或参数
|
||||
- [ ] 改 `SCENE_DONE` / `CESIUM_EXPORT_DONE` 的 stdout 标记
|
||||
@@ -54,7 +55,9 @@ grep -rn "要改的值" scripts blender config
|
||||
|
||||
本仓库跨 JS、Blender Python、浏览器 JS 和 JSON,很多连接靠字符串或文件名约定。
|
||||
例如 `scene-layers.js` 与 `catalog.py` 只靠 `id` 集合和顺序对账;
|
||||
`generate_scene.py` 与 `export_cesium.py` 的材质覆盖目前靠材质名字符串,没有自动校验。
|
||||
`generate_scene.py` 与 `export_cesium.py` 的新材质导出契约靠 `.blend` 里的
|
||||
`material["cesium_export"]` 自定义属性,旧 `.blend` 仍靠 `export_cesium.py`
|
||||
的材质名回退表。
|
||||
|
||||
---
|
||||
|
||||
|
||||
Reference in New Issue
Block a user