Files
osmWorkflow/.trellis/tasks/08-03-material-export-contract/design.md

172 lines
5.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 技术设计Cesium 材质导出契约化
> 对应 `prd.md`。本文件定义边界、数据流、兼容策略和风险控制。
---
## 1. 当前边界
`catalog.py` 是纯 Python 层,只声明材质事实,不能 import `bpy``materials.py`
属于 bpy 层,负责把 catalog spec 变成真实 `bpy.types.Material``export_cesium.py`
打开 `.blend` 后只应消费场景里已有的材质信息。
因此正确边界是:
```
catalog.MATERIALS[*]["cesium"] # 纯数据
materials.from_spec() # bpy 层写 material["cesium_export"]
<area>.blend # 契约随场景文件保存
export_cesium.py # 优先读 material custom property
```
不采用:
```
export_cesium.py -> import catalog -> 按 material.name 反查
```
原因:这仍然依赖材质名字符串,而且旧 `.blend` 应该能在没有新 catalog contract 的情况下导出。
## 2. Contract Shape
材质自定义属性名固定为:
```python
CESIUM_EXPORT_PROPERTY = "cesium_export"
```
JSON payload 建议 shape
```json
{
"tint": [[0.92, 0.94, 0.92], 0.38],
"metallic": 0.0,
"base_color": [0.93, 0.94, 0.91],
"emission": [[0.93, 0.94, 0.91], 0.18]
}
```
字段语义:
| 字段 | 类型 | 语义 | 旧来源 |
|---|---|---|---|
| `tint` | `[[r,g,b], factor]` | diffuse 贴图导出前往目标颜色混合 | `EXPORT_TINTS` |
| `metallic` | number | 覆盖导出 PBR metallic | `EXPORT_METALLIC_OVERRIDES` |
| `base_color` | `[r,g,b]` | 直接覆盖导出材质 base color并禁用 diffuse/normal 图 | `EXPORT_BASE_COLOR_OVERRIDES` |
| `emission` | `[[r,g,b], strength]` | 设置导出材质自发光 | `EXPORT_EMISSION_OVERRIDES` |
缺失字段表示沿用源材质当前值或当前特殊路径。
## 3. Catalog Migration
把四张旧表中的有效条目迁入 `catalog.MATERIALS` 对应项:
- `Grass` -> `MATERIALS["grass"]["cesium"]`
- `Scrub Ground Cover` -> `MATERIALS["scrub"]["cesium"]`
- `Tree Crown*` -> 现有 `tree_crown*["cesium"]` 扩展到完整字段
- `Office White Plaster Facade` -> `building_default`
- `Office Light Flat Roof` -> `building_office_roof`
- `Industrial White Ribbed Facade` -> `building_industrial`
- `Factory Blue Metal Roof` -> `building_industrial_roof`
`Office White Metal Facade` 当前没有 catalog 材质,不迁入新契约。旧表可保留该 key 作为旧
`.blend` 回退兼容。
`catalog.CESIUM_EXPORT` 应消失或变成真实消费路径。优先方案:删除全局 `CESIUM_EXPORT`
把其中仍有效的内容迁入各自 `MATERIALS[*]["cesium"]`
## 4. Material Construction
`materials.py`
1. import `json`
2. 定义同名常量 `CESIUM_EXPORT_PROPERTY = "cesium_export"`,或一个私有 helper
3. `from_spec(spec)` 构造材质后调用:
```python
def apply_cesium_contract(material, spec):
contract = spec.get("cesium")
if contract is None:
material.pop(CESIUM_EXPORT_PROPERTY, None)
return
material[CESIUM_EXPORT_PROPERTY] = json.dumps(contract, sort_keys=True)
```
注意:
- `sort_keys=True``.blend` 摘要更稳定。
- 没有 `cesium` 的材质应清掉旧属性,避免同名材质复用时残留。
- `catalog.py` 仍不 import `bpy`
## 5. Export Consumption
`export_cesium.py`
1. 增加 `cesium_contract(material)`,读取并 `json.loads(material.get("cesium_export", "{}"))`
2. JSON 解析失败时返回 `{}` 并继续旧回退,避免坏旧文件直接崩溃
3. `make_export_material(material)` 开头读取一次 contract
```python
contract = cesium_contract(material)
```
4. 每个覆盖点改成 “contract 优先,旧表回退”:
```python
base_color = contract.get("base_color", EXPORT_BASE_COLOR_OVERRIDES.get(material.name, source_color(material)))
metallic = contract.get("metallic", EXPORT_METALLIC_OVERRIDES.get(...))
emission = contract.get("emission", EXPORT_EMISSION_OVERRIDES.get(material.name))
tint = contract.get("tint", EXPORT_TINTS.get(material.name))
```
5. `cesium_tinted_image()` 可以改为接收 `tint` 参数,避免函数内部再查旧表。
## 6. Foliage Special Case
Alpha cut-out foliage 不在本次 contract 化范围内,原因是它不只是普通材质覆盖,还包含:
- `source_alpha_clipped(material)`
- `alpha_dilated_image(..., gain=FOLIAGE_ALBEDO_GAIN, saturation=FOLIAGE_SATURATION)`
- diffuse texture 连接到 emission color
- `FOLIAGE_EMISSION`
这些逻辑保持原样。普通 contract 的 `emission` 只处理非 alpha-clipped 或程序化材质的平铺
emission overridealpha-clipped 分支仍使用 diffuse-as-emissive texture。
## 7. Validation Strategy
快速检查:
```bash
python3 -m unittest discover blender/tests
```
结构验证:
```bash
node scripts/parity.js capture material-contract-before
node scripts/parity.js capture material-contract-after
node scripts/parity.js compare material-contract-before material-contract-after
```
如果 before capture 已存在于实现前after 在实现后跑。若 compare 报差异:
- `.blend` 摘要多出材质自定义属性 `cesium_export` 是预期差异,但需要确认没有对象、网格、
材质槽顺序、GLB material PBR 参数等非预期变化。
- GLB 摘要应尽量全绿;若发生 PBR 参数变化,优先修实现而不是接受差异。
## 8. Rollback
回滚点明确:
- `catalog.py` 还原 `MATERIALS["cesium"]` 迁移和 `CESIUM_EXPORT` 处理。
- `materials.py` 删除 custom property 写入。
- `export_cesium.py` 恢复旧四张表直接读取。
- spec 更新随代码回滚。