Adopt Shapespark vegetation assets
This commit is contained in:
@@ -105,26 +105,44 @@ catalog.MATERIALS 声明「是什么」 纯 Python,无 bpy
|
||||
不管源文件把原点放在哪(`tree.py:301-303`)
|
||||
|
||||
`assemble()` 返回种植数量,**0 表示模型缺失或 style 未知**,调用方据此回退到程序化
|
||||
树(`tree.py:277-279`)。
|
||||
树。
|
||||
|
||||
### 材质在本地重建,不沿用源文件
|
||||
### Shapespark 是当前模型树样式
|
||||
|
||||
`tree.py:12-16`:两个 vendored 模型的材质都不能直接用。apple 的贴图 57% 是透明的
|
||||
(那是叶片卡),没有 alpha-clip 设置的话整个树冠会渲染成一块。
|
||||
当前唯一模型树 style 是 `shapespark`,资产来自
|
||||
`assets/models/custom/shapespark_plants/tree-*/model.gltf`。该目录是从
|
||||
Shapespark low-poly plants kit 拆分出的单植物 glTF/bin,贴图共享在
|
||||
`assets/models/custom/shapespark_plants/textures/`。
|
||||
|
||||
**vendored 资产的材质一律重建**,不要 `append` 源文件的材质。
|
||||
`tree.py` 加载 12 个 tree 变体,每个变体 import 一次、bake 成共享 mesh datablock;
|
||||
OSM 树实例只 link 这些 mesh。变体选择必须确定性,当前用 stable instance index 经过
|
||||
golden-turn 序列选变体:
|
||||
|
||||
### 已删除的第三种 style 有记录
|
||||
```python
|
||||
variant = variants[int(((index * GOLDEN_TURN) % 1.0) * len(variants))]
|
||||
```
|
||||
|
||||
拆分 glTF 会让 Blender 生成 `branch-01.001`、`branch-01.002` 这类重复材质名;
|
||||
`tree.py` 必须按 base name 去重材质槽,否则 `export_cesium.py` 会为同一张贴图重复
|
||||
bake Cesium 材质。
|
||||
|
||||
### 已删除的模型树 style 有记录
|
||||
|
||||
`tree.py:18-25` 记着 `polyhaven` style 被删的原因(LOD1 对象不是整棵树,是给几何节点
|
||||
散布用的树枝和叶簇,直接种出来是一地树枝,连同 78MB 资产一起删了)。
|
||||
|
||||
`apple` 和 `fattree` style 已在 Shapespark 方案被用户接受后删除:apple 需要强抠图、
|
||||
法线和 Cesium 曝光补偿,远近观感不如 Shapespark 稳定;fattree 视觉风格不匹配。
|
||||
对应资产目录 `assets/models/speedtree/apple_low/` 和 `assets/models/lyrog/fattree/`
|
||||
也已删除。
|
||||
|
||||
**这类"试过、不行、为什么"的记录要保留。** 删掉它,下一个人会重新引入同一个资产。
|
||||
|
||||
## 灌木边缘实例有性能预算
|
||||
|
||||
`generate_scene.py` 的 scrub 不是只有贴地面:`natural=scrub` 会先生成
|
||||
`Scrub_<way_id>` 地面覆盖,再沿边界实例化 `assets/models/custom/bush/bush.glb`
|
||||
`Scrub_<way_id>` 地面覆盖,再沿边界实例化
|
||||
`assets/models/custom/shapespark_plants/bush-03/model.gltf`
|
||||
(`add_scrub_edge_bushes()`),并在大 scrub 面内部稀疏补树。
|
||||
|
||||
这些 bush 是共享 mesh 的多 node 实例。共享 mesh 能压 GLB 体积,但 Cesium 近景 Follow
|
||||
@@ -137,15 +155,15 @@ SCRUB_BUSH_SPACING = 1.8
|
||||
SCRUB_BUSH_LIMIT_PER_PATCH = 60
|
||||
```
|
||||
|
||||
在 nantaizi 上约 `266` 个 bush nodes,scrub 地面覆盖仍保留。当前默认资产仍是
|
||||
`assets/models/custom/bush/bush.glb`。`assets/models/custom/bush_low/bush_low.glb`
|
||||
曾作为低模实验验证过:几何从 `63,762` vertices / `67,536` indices 降到
|
||||
`4,044` / `4,050`,但用户实测视觉效果不理想,**不要直接把它设为默认**。
|
||||
在 nantaizi 上约 `266` 个 bush nodes,scrub 地面覆盖仍保留。旧高模 bush 和
|
||||
rejected `bush_low` 资产已删除:前者太重,后者几何从
|
||||
`63,762` vertices / `67,536` indices 降到
|
||||
`4,044` / `4,050`,但用户实测视觉效果不理想,不能作为默认方向。
|
||||
|
||||
不要只为了“更满”把间距调回 1m 以下;那是在把预览流畅度换成近景装饰密度。若确实
|
||||
需要更密的灌木,先做一个视觉可接受的低模 bush,或做显式 LOD / instancing 方案,再
|
||||
跑 nantaizi 的 Blender/Cesium/preview 验证。注意:`bush_low` 的文件仍有 `5.79 MB`,
|
||||
因为 6 张纹理没有同步压缩;继续压 GLB 总体体积应考虑纹理尺寸/KTX2,而不是只减面。
|
||||
跑 nantaizi 的 Blender/Cesium/preview 验证。继续压 GLB 总体体积应考虑贴图尺寸/KTX2,
|
||||
而不是只减面。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -114,7 +114,7 @@ cp config/examples/template.json config/areas/my-area.json
|
||||
|
||||
| 字段 | 默认 | 说明 |
|
||||
|---|---|---|
|
||||
| `treeStyle` | `"natural"` | 合法值见 `generate_scene.py:144` 的 `TREE_STYLES`(`natural`、`procedural`,加上 `tree.py` 注册的模型 style) |
|
||||
| `treeStyle` | `"natural"` | 合法值见 `generate_scene.py` 的 `TREE_STYLES`(`natural`、`procedural`、`shapespark`) |
|
||||
| `officeOverrides` | `""` | 旧名 `office_overrides` 仍被接受 |
|
||||
|
||||
### `outputs`(逃生舱)
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
|
||||
@@ -0,0 +1 @@
|
||||
{"_example": "Fill with {\"file\": \"<path>\", \"reason\": \"<why>\"}. Put spec/research files only — no code paths. Run `python3 .trellis/scripts/get_context.py --mode packages` to list available specs. Delete this line once real entries are added."}
|
||||
47
.trellis/tasks/08-03-test-shapespark-tree-variants/prd.md
Normal file
47
.trellis/tasks/08-03-test-shapespark-tree-variants/prd.md
Normal file
@@ -0,0 +1,47 @@
|
||||
# Test Shapespark tree variants
|
||||
|
||||
## Goal
|
||||
|
||||
Use the split Shapespark low-poly plant assets as tree, scrub bush, and lawn
|
||||
tuft variants, then validate `nantaizi-lake-innovation-valley`.
|
||||
|
||||
The user liked the Shapespark `bush-03` scrub replacement and wants to evaluate
|
||||
whether the same kit can replace the current tree asset. If multiple tree
|
||||
variants are not too expensive, the scene should use varied trees while staying
|
||||
deterministic for the same OSM input.
|
||||
|
||||
## Requirements
|
||||
|
||||
1. Prefer Shapespark tree assets from
|
||||
`assets/models/custom/shapespark_plants/tree-*/model.gltf`.
|
||||
2. Use deterministic variant selection based on stable tree instance ordering;
|
||||
do not use unseeded random or time-dependent randomness.
|
||||
3. Preserve existing tree placement count and route/road/building behavior.
|
||||
4. Preserve the existing scrub bush `bush-03` experiment.
|
||||
5. Replace the old Poly Haven `shrub_02` lawn tuft asset with suitable
|
||||
Shapespark grass assets.
|
||||
6. Evaluate the cost of loading multiple tree and lawn tuft variants:
|
||||
- number of shared tree meshes introduced
|
||||
- number of shared lawn tuft meshes introduced
|
||||
- texture/image/material counts
|
||||
- output GLB size
|
||||
- total nodes
|
||||
7. Rebuild only `nantaizi-lake-innovation-valley` stages
|
||||
`blender,cesium,preview`.
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
- [ ] Tree generation uses Shapespark tree variants deterministically.
|
||||
- [ ] Lawn tufts use Shapespark `grass-*` variants instead of `shrub_02`.
|
||||
- [ ] `python3 -m py_compile blender/generate_scene.py blender/osmassets/tree.py` passes.
|
||||
- [ ] `python3 -m unittest blender/tests/test_pure.py` passes.
|
||||
- [ ] nantaizi `blender,cesium,preview` rebuild passes.
|
||||
- [ ] GLB digest reports tree mesh/material/image/node cost.
|
||||
- [ ] User can open the local preview and compare visual result.
|
||||
|
||||
## Out Of Scope
|
||||
|
||||
- Runtime LOD.
|
||||
- hanyang validation.
|
||||
- Texture compression / KTX2.
|
||||
- Committing the experiment before user approval.
|
||||
99
.trellis/tasks/08-03-test-shapespark-tree-variants/report.md
Normal file
99
.trellis/tasks/08-03-test-shapespark-tree-variants/report.md
Normal file
@@ -0,0 +1,99 @@
|
||||
# Shapespark tree variant experiment report
|
||||
|
||||
## Current Trial
|
||||
|
||||
`nantaizi-lake-innovation-valley` now uses:
|
||||
|
||||
- scrub bush: `assets/models/custom/shapespark_plants/bush-03/model.gltf`
|
||||
- tree style: `shapespark`
|
||||
- Shapespark tree variants: 12 deterministic variants from
|
||||
`assets/models/custom/shapespark_plants/tree-*/model.gltf`
|
||||
- lawn tufts: 3 Shapespark grass variants from
|
||||
`assets/models/custom/shapespark_plants/grass-*/model.gltf`
|
||||
- Cesium export uses a gentler Shapespark foliage profile:
|
||||
`gain=1.12`, `saturation=1.0`, `emission=0.06`.
|
||||
|
||||
Variant selection is deterministic: it uses the stable tree instance index and
|
||||
the golden-turn sequence, not runtime random state.
|
||||
|
||||
## Validation
|
||||
|
||||
Commands run:
|
||||
|
||||
```bash
|
||||
python3 -m py_compile blender/generate_scene.py blender/osmassets/tree.py blender/export_cesium.py
|
||||
python3 -m unittest blender/tests/test_pure.py
|
||||
npm run build:area -- --config config/areas/nantaizi-lake-innovation-valley.json --stages blender,cesium,preview
|
||||
node scripts/glb-digest.js outputs/nantaizi-lake-innovation-valley/nantaizi-lake-innovation-valley.glb --out /tmp/nantaizi-shapespark-tree-glb-digest.json
|
||||
node scripts/glb-digest.js outputs/nantaizi-lake-innovation-valley/nantaizi-lake-innovation-valley.glb --out /tmp/nantaizi-shapespark-grass-glb-digest.json
|
||||
node scripts/glb-digest.js outputs/nantaizi-lake-innovation-valley/nantaizi-lake-innovation-valley.glb --out /tmp/nantaizi-shapespark-toned-glb-digest.json
|
||||
node scripts/glb-digest.js outputs/nantaizi-lake-innovation-valley/nantaizi-lake-innovation-valley.glb --out /tmp/nantaizi-shapespark-toned-rebuild.json
|
||||
node scripts/glb-digest.js outputs/nantaizi-lake-innovation-valley/nantaizi-lake-innovation-valley.glb --out /tmp/nantaizi-shapespark-cleanup.json
|
||||
python3 ./.trellis/scripts/task.py validate .trellis/tasks/08-03-test-shapespark-tree-variants
|
||||
```
|
||||
|
||||
Results:
|
||||
|
||||
- `SCENE_DONE.tree_style`: `shapespark`
|
||||
- Trees planted: `197`
|
||||
- Grass tufts planted: `270`
|
||||
- Scrub bush nodes: `266`
|
||||
- GLB nodes: `830`
|
||||
- GLB meshes: `113`
|
||||
- GLB materials: `32`
|
||||
- GLB images: `18`
|
||||
- GLB accessors after final rebuild: `675` (accessor count is a known glTF
|
||||
exporter fluctuation and is ignored by parity)
|
||||
- GLB size after color tuning: `20.50 MB`
|
||||
- Shapespark tree mesh datablocks: `12`
|
||||
- Shapespark tree materials: `7`
|
||||
- Shapespark tree images: `7`
|
||||
- Shapespark tree shared geometry: `6,255` vertices / `18,696` indices
|
||||
- Shapespark lawn tuft mesh datablocks: `3`
|
||||
- Shapespark lawn tuft materials: `2`
|
||||
- Shapespark lawn tuft images: `2`
|
||||
- Shapespark lawn tuft shared geometry: `84` vertices / `90` indices
|
||||
|
||||
## Assessment
|
||||
|
||||
The multi-tree cost is acceptable for this scene. Tree node count stays the
|
||||
same because the implementation links shared mesh datablocks per instance.
|
||||
The extra cost is only 11 more shared tree mesh datablocks than a single tree
|
||||
variant, plus 7 tree texture/material entries. The total GLB is still smaller
|
||||
than the previous apple-tree build because the Shapespark textures and meshes
|
||||
are lighter.
|
||||
|
||||
Replacing the former Poly Haven `shrub_02` lawn tuft with Shapespark
|
||||
`grass-01/02/03` further reduces shared tuft geometry from a high-detail plant
|
||||
asset to only 3 tiny grass-card variants. The lawn tuft instance count stays
|
||||
the same, so the visual density is comparable while the shared geometry cost is
|
||||
effectively negligible.
|
||||
|
||||
The color issue came from reusing the apple-tree export profile for every
|
||||
alpha-cut plant. Apple needs strong albedo gain / saturation / emission because
|
||||
its atlas is unusually dark. Shapespark foliage does not; using the apple
|
||||
profile made it read yellow-green and glowing. The final trial keeps the
|
||||
alpha-mask cleanup but uses much lower exposure and emission for Shapespark
|
||||
material names (`branch-*`, `shrubbery-*`, `high-grass-*`, `hedge-*`,
|
||||
`clover-*`, `flowers-*`).
|
||||
|
||||
Compared with the pre-Shapespark scrub-density baseline (`31.96 MB` GLB), this
|
||||
trial is about `11.46 MB` smaller while keeping the same object count budget:
|
||||
`830` nodes, `197` trees, `270` lawn tufts, and `266` scrub bush instances.
|
||||
The main savings come from replacing the original heavy scrub bush, the
|
||||
high-detail lawn tuft asset, and the apple tree atlas with lighter shared
|
||||
Shapespark assets.
|
||||
|
||||
## Cleanup
|
||||
|
||||
After user visual approval, the old vegetation assets and their runtime loaders
|
||||
were removed:
|
||||
|
||||
- retired tree styles: `apple`, `fattree`
|
||||
- removed assets: SpeedTree apple, Lyrog fattree, Poly Haven `shrub_02`,
|
||||
original `custom/bush`, rejected `custom/bush_low`
|
||||
- remaining model tree style: `shapespark`
|
||||
- remaining external plant asset root:
|
||||
`assets/models/custom/shapespark_plants/`
|
||||
- nantaizi rebuild after cleanup stayed at `20.50 MB`, `830` nodes, `113`
|
||||
meshes, `32` materials, `18` images
|
||||
26
.trellis/tasks/08-03-test-shapespark-tree-variants/task.json
Normal file
26
.trellis/tasks/08-03-test-shapespark-tree-variants/task.json
Normal file
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"id": "test-shapespark-tree-variants",
|
||||
"name": "test-shapespark-tree-variants",
|
||||
"title": "Test Shapespark tree variants",
|
||||
"description": "",
|
||||
"status": "in_progress",
|
||||
"dev_type": null,
|
||||
"scope": null,
|
||||
"package": null,
|
||||
"priority": "P2",
|
||||
"creator": "dingkang",
|
||||
"assignee": "dingkang",
|
||||
"createdAt": "2026-08-03",
|
||||
"completedAt": null,
|
||||
"branch": null,
|
||||
"base_branch": "main",
|
||||
"worktree_path": null,
|
||||
"commit": null,
|
||||
"pr_url": null,
|
||||
"subtasks": [],
|
||||
"children": [],
|
||||
"parent": null,
|
||||
"relatedFiles": [],
|
||||
"notes": "",
|
||||
"meta": {}
|
||||
}
|
||||
Reference in New Issue
Block a user