Each tree of the first map's forest stands with its base on the ground all round, on any slope #19

Merged
agra merged 2 commits from task/3930-trees-on-hills-float-each-stands-with-it into master 2026-10-30 09:17:30 +02:00
Owner

Tracker: #3930

On hills each tree's root flare hung in the air on its downhill side. first_map_prefabs.py stood every tree with its origin on the ground under its centre, and a scanned tree's base is shaped for the flat ground it was scanned on.

What changes

  • assets/scenes/first_map_prefabs.py stands each tree with its origin at the lowest ground under its base: the vertices its prefab draws lower than 0.5 m above its origin, turned and scaled as the tree is. Its base then meets the ground all round, with its uphill side in the ground. Every tree keeps its place, turn and scale; only its height changes.
  • assets/scenes/first_map.blend has the script run over it again.
  • tests/first_map_world.sx checks every tree's base vertices (those lower than 0.5 m in its prefab). Under each one, the ground the tree stood on in its prefab may lie at most 3 cm above the map's own ground (the meshes the map draws as themselves), and under at least one of them at most 3 cm below it. So a base that hovers fails, and so does a tree sunk past where its base touches the ground. The ground is read by a ray down from above the map.
  • tests/pixels/forest-metal.png is the forest view regenerated: the near fir stands lower.
  • first_map.blend.md and the script's header say how the trees stand.

How the test reads the ground

The task's probe cast its ray down from each vertex itself, into the world file. For an uphill vertex that lies below the ground, that ray meets the tree's own trunk proxy, which reaches 1 m below the base. Its worst figures (0.84 m and 1.03 m) are those buried vertices. Read from above on the map's own ground, master's worst hovers are 0.52 m for a fir and 0.29 m for an island tree. Blender's own measurement of each tree against the terrain gives the same figures.

Evidence

  • Test at master's bake (a git archive of master, baked, with this test copied in): fails.

    • every fir_tree_01's base meets the ground, not 540 of 603: the worst hovers 0.519531 m
    • every island_tree_02's base meets the ground, not 230 of 297: the worst hovers 0.291107 m
  • Test at this head: passes. Every tree's highest base vertex lies within 0.000022 m of the ground, above or below (read with the bound set to 0 in a scratch copy of the test).

  • The render file compared with master's, decoded, with each texture taken by its content: the only change is the hulken y of the tree transforms. 603 firs are lowered by 1.8 mm to 0.520 m and 297 island trees by 1.8 mm to 0.291 m. Nothing else moves.

    • Rerunning master's script unchanged does reorder the render file's textures, because the libraries are relinked after the props'. It draws exactly what master draws, and its world file is byte-identical to master's.
  • Trunk proxies. In the world file, only the 900 proxies' 19,800 triangles move, each corner straight down by exactly its own tree's drop. So each proxy still stands round its trunk. The trunk walk in tests/first_map_world.sx passes, so a fir's trunk still blocks a player.

  • Mutants of the script's rule each fail the test. Each was run over a copy of the committed .blend in a git archive arm, then baked and tested:

    • every tree 10 cm below the lowest ground: all 603 firs and 297 island trees with their highest base vertex 0.100 m under the ground;
    • the footprint grown 2 times: 539 firs and 229 island trees buried, the deepest's highest base vertex 0.546 m and 0.272 m under the ground;
    • the footprint turned the wrong way: 65 firs hovering past 3 cm, worst 0.12 m, and 73 buried;
    • the footprint not scaled with the tree: 21 firs and 24 island trees hovering, worst 0.06 m, and 17 firs buried;
    • a base of only the lowest 5 cm: 235 firs, worst hover 0.48 m;
    • the median ground under the base instead of the lowest: 543 firs and 232 island trees, worst hover 0.48 m;
    • the origin on the ground under the centre, as on master: 540 firs and 230 island trees, worst hover 0.52 m.

    Rerunning the script unchanged over the committed .blend bakes a render file and a world file byte-identical to this head's.

  • Renders from 6 m down the slope, at master and at this head, are attached to #3930:

    • files 804 and 805: a fir on the north hill;
    • files 806 and 807: an island tree on the east hill.

    At master the root flare hangs in the air; here the trunk enters the ground.

Gates

  • sak-gate fast at ed268b2: passed, 34 of 34 (run 1831's gate #1, tracker gate run 903).
  • sak-gate full at ed268b2: passed, 34 of 34 (run 1831's gate #2, tracker gate run 904).
  • sak-gate full at 4715171: passed, 34 of 34 (run 1840's gate #1, tracker gate run 909).
Tracker: [#3930](https://sak.swipelab.com/tasks/3930) On hills each tree's root flare hung in the air on its downhill side. `first_map_prefabs.py` stood every tree with its origin on the ground under its centre, and a scanned tree's base is shaped for the flat ground it was scanned on. ## What changes - `assets/scenes/first_map_prefabs.py` stands each tree with its origin at the lowest ground under its base: the vertices its prefab draws lower than 0.5 m above its origin, turned and scaled as the tree is. Its base then meets the ground all round, with its uphill side in the ground. Every tree keeps its place, turn and scale; only its height changes. - `assets/scenes/first_map.blend` has the script run over it again. - `tests/first_map_world.sx` checks every tree's base vertices (those lower than 0.5 m in its prefab). Under each one, the ground the tree stood on in its prefab may lie at most 3 cm above the map's own ground (the meshes the map draws as themselves), and under at least one of them at most 3 cm below it. So a base that hovers fails, and so does a tree sunk past where its base touches the ground. The ground is read by a ray down from above the map. - `tests/pixels/forest-metal.png` is the forest view regenerated: the near fir stands lower. - `first_map.blend.md` and the script's header say how the trees stand. ## How the test reads the ground The task's probe cast its ray down from each vertex itself, into the world file. For an uphill vertex that lies below the ground, that ray meets the tree's own trunk proxy, which reaches 1 m below the base. Its worst figures (0.84 m and 1.03 m) are those buried vertices. Read from above on the map's own ground, master's worst hovers are 0.52 m for a fir and 0.29 m for an island tree. Blender's own measurement of each tree against the terrain gives the same figures. ## Evidence - **Test at master's bake** (a `git archive` of master, baked, with this test copied in): fails. - `every fir_tree_01's base meets the ground, not 540 of 603: the worst hovers 0.519531 m` - `every island_tree_02's base meets the ground, not 230 of 297: the worst hovers 0.291107 m` - **Test at this head:** passes. Every tree's highest base vertex lies within 0.000022 m of the ground, above or below (read with the bound set to 0 in a scratch copy of the test). - **The render file compared with master's**, decoded, with each texture taken by its content: the only change is the hulken y of the tree transforms. 603 firs are lowered by 1.8 mm to 0.520 m and 297 island trees by 1.8 mm to 0.291 m. Nothing else moves. - Rerunning master's script unchanged does reorder the render file's textures, because the libraries are relinked after the props'. It draws exactly what master draws, and its world file is byte-identical to master's. - **Trunk proxies.** In the world file, only the 900 proxies' 19,800 triangles move, each corner straight down by exactly its own tree's drop. So each proxy still stands round its trunk. The trunk walk in `tests/first_map_world.sx` passes, so a fir's trunk still blocks a player. - **Mutants of the script's rule each fail the test.** Each was run over a copy of the committed `.blend` in a `git archive` arm, then baked and tested: - every tree 10 cm below the lowest ground: all 603 firs and 297 island trees with their highest base vertex 0.100 m under the ground; - the footprint grown 2 times: 539 firs and 229 island trees buried, the deepest's highest base vertex 0.546 m and 0.272 m under the ground; - the footprint turned the wrong way: 65 firs hovering past 3 cm, worst 0.12 m, and 73 buried; - the footprint not scaled with the tree: 21 firs and 24 island trees hovering, worst 0.06 m, and 17 firs buried; - a base of only the lowest 5 cm: 235 firs, worst hover 0.48 m; - the median ground under the base instead of the lowest: 543 firs and 232 island trees, worst hover 0.48 m; - the origin on the ground under the centre, as on master: 540 firs and 230 island trees, worst hover 0.52 m. Rerunning the script unchanged over the committed `.blend` bakes a render file and a world file byte-identical to this head's. - **Renders** from 6 m down the slope, at master and at this head, are attached to #3930: - files 804 and 805: a fir on the north hill; - files 806 and 807: an island tree on the east hill. At master the root flare hangs in the air; here the trunk enters the ground. ## Gates - `sak-gate fast` at ed268b2: passed, 34 of 34 (run 1831's gate #1, tracker gate run 903). - `sak-gate full` at ed268b2: passed, 34 of 34 (run 1831's gate #2, tracker gate run 904). - `sak-gate full` at 4715171: passed, 34 of 34 (run 1840's gate #1, tracker gate run 909).
agra merged commit 81c1a3eb52 into master 2026-10-30 09:17:30 +02:00
Sign in to join this conversation.
No reviewers
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
sx/hulken!19
No description provided.