Canonical Alpine tree placement
The actual QA/20260915-221352-campaign/alps-01-pass0-view0.png and view1.png were inspected. The new whole-tree rendering makes a separate location error conspicuous: mature dark trees stand on photographed limestone. The previous ChapterLandscape.Woodland used only DEM height, smoothed slope, noise and a large elliptical valley clearing. It ignored the later geology correction and the actual aerial woodland boundaries. At world X −2644.80 / Z 2330.69, it allowed density 0.9175 despite geology G 0.9376.
Independent source and geographic mapping
Tools/Art/build_alpine_tree_cover.py creates placement data independently of the live terrain material channels. Source inputs are the existing unchanged DEM, original forest-R baseline, current geology-G and attributed orthophoto. User reference ArtSource/References/Alps-User-20260915/reference-13.png supplies the visual composition target: connected wooded hillsides, limited meadow parcels, scattered near deciduous trees and exposed limestone.
The mask has 601 × 526 cells, matching the original 20 m DEM grid. X runs −6000 to 6000 m; Z runs −2000 to 8500 m. Data row zero is minimum world Z; source image rows are flipped once during preparation. Each cell contains two bytes:
- R: aerial-guided woodland footprint multiplied by the original ecological suitability, with bounded authored meadow parcels removed.
- G: a conservative neighbourhood maximum of the existing geology mask. The material image itself is not modified.
The old meadow ellipse is explicitly divided out of original forest R using its known 1 − meadow × 0.96 factor. The altitude/slope suitability remains. Aerial excess-green, luminance and local variation then guide the footprint; small holes are closed and boundaries feathered. This is an authored interpretation of existing source imagery, not a surveyed semantic forest classification. Three irregular valley parcels replace the oversized empty ellipse. Their exact world-coordinate vertices and every source hash are in ArtSource/Alps/TreeCover/tree-cover-build.json.
The first stricter aerial classification was reviewed and rejected because it fragmented real dark woodland into many tiny islands. It was never published. The revised mask retains connected forests on both valley sides and the upper wooded approaches. The preparer and a separate art agent inspected the technical overview and the unchanged orthophoto. That establishes a plausible source-level arrangement for the next native comparison, not visual acceptance of the game.
The compressed payload is 241,005 bytes, SHA256 0e1a20d14bffe5281343e2ab5024def88a9efa107d8eb4a3b7f238c1212e0b9a; decoded header plus cells is 632,280 bytes. The runtime data is embedded as AlpineTreeCoverData.cs and decoded once by AlpineTreeCover.cs. No runtime Texture2D, GPU readback or per-stage resource allocation is needed for sampling.
Common eligibility and spacing
AlpineTreeCover.Density bilinearly samples R and takes the maximum G over the four sample corners. Geology suppresses placement from G=0.25 to complete rejection at G=0.65. The source G preparation uses a 7-pixel maximum filter and nearest resampling, avoiding dilution of narrow rock gullies into false valid sites. Outside the bounded world map, density is zero.
AlpineForestCanopy checks this same density at candidate centres and again at every individual scattered tree. A deterministic position hash supplies the per-tree probability, so low-density edges no longer receive the same fixed number of accepted trees as forest interiors. A shared spatial registry enforces 7 m minimum centre spacing across Alpine near trees, groves and individual far trees. Near Alps and Groves placements use the same sampler and registry before choosing their existing broadleaf or fir models. The prior layout's road clearances remain in place.
The old distant winter atlas represents multiple trees in a single group image. Such a group is accepted only when a grid of sites across its complete roughly 50 m footprint remains at density ≥0.45. This is conservative footprint validation; it is not a claim that each baked tree is independently repositioned. Existing decorative village trees remain part of the village composition, outside forest scattering. Near tree colliders, where already supplied by the existing broadleaf helper, continue to accompany those trees; no collision or driving code was changed.
The work changes placement data and the specified Alps/Groves/forest methods. GroundDetails, terrain heights, terrain material images, routes, vehicle physics, controls and authored models/textures were not edited. The original material R contains grass mixing and B contains a road-distance rendering blend, so neither is reused directly as the tree-site mask.
Verification and native boundary
Tools/Art/verify_alpine_tree_cover.py compares the old and new candidate-centre rules on the same high-quality 31 m grid and existing Alps01 route, preserving clearances from all three Alpine roads. The CPU calculation uses double precision and reconstructed 100 m route samples, so threshold-boundary differences from native float arithmetic are possible.
| Comparable candidate-centre check | Before | After |
|---|---|---|
| Accepted Alps01 centres | 10,454 | 9,223 |
| Centres on original geology G ≥ 0.65 | 124 | 0 |
| Mean accepted site density | 0.8591 | 0.8755 |
An additional 100,000 uniformly distributed world points includes 3,449 strong-rock locations from the original material G. All reject tree placement. Both explicitly identified incorrect limestone sites now return zero, and out-of-map sampling returns zero. The report is ArtSource/Alps/TreeCover/placement-verification.json. These are candidate-centre/data checks, not actual rendered tree counts.
Managed compilation passes 97 Runtime + 22 Editor files, zero warnings/errors. The final technical overview is ArtSource/Alps/TreeCover/TreeCover_review.png; the effective scalar map is TreeCover_effective.png. No Unity/player or GPU process was started by this work. Root-owned native images must still confirm cohesive forest masses, credible meadow edges, clean limestone faces and stable road clearances. No AAA or gameplay-acceptance claim follows from the mask checks.
Source data, unchanged after preparation:
- DEM:
7f3fc34b74dc07448e973b7f9510f5a4898294fa811c4468eeff3865d6ed1414. - Summer material map:
8f214436fbcf4fb68bab779126387d662b229c4fc4cd16ed5968b501288624fe. - Winter material map:
21ceed5911dd1fd6a5dd646dea094de435cbf5fa5febe05da8d790f7639b3791. - Orthophoto:
cc217730bc4585dd45b79d3f0b3d04afdb59daa9d3d97491f204c54d7d87da20. - Alpine road source:
74b0668a096c1636c4db96242e89775e6b59ff2d041c290cdeff7c1f98af732c.
Orthophoto attribution: Datenquelle: basemap.at, CC BY 4.0. Existing DEM provenance remains in the Alpine source manifests. The new scalar mask is a derived placement aid; the source image is unchanged.
Follow-up after the 23:15 native build: summer interior density and ground coverage
Both actual images Docs/QA/20260915-231543-campaign/alps-01-pass0-view0.png and view1.png were inspected. Exposed-rock placements improved, but isolated crowns over bright meadow still read as an open plantation. The native log records 34,595 individual Alps01 far trees before this follow-up. This is an observed count for the preceding build, not the new density revision.
The imported Fir A is 18.98 m high and 6.40 × 6.13 m in overall plan bounds. At the existing alpha cutoff, most rows of the summer crown atlas are only 3.2–4.0 m wide at source height. The 12–21 m instances therefore have predominantly 2–4.4 m-wide visible crowns. Seven-metre centre spacing was too open for these narrow assets.
The shared registry now receives 4.5 m for summer and retains 7 m for winter. High-quality summer centres whose canonical density is at least 0.65 now attempt 24 trees within 700 m and 14 beyond 700 m, replacing 11 and 6 respectively. Winter and Low attempt counts remain unchanged. Candidate-centre rules, every per-tree eligibility test, rock veto, road exclusions, route ranges, model scale and GPU-quad rendering remain unchanged. No new assets, recolouring or shaders were added.
Summer material B is now derived from exactly the same compressed TreeCover payload and sampling rules as runtime placement. See ALPINE-SUMMER-FOUR-LAYERS.md for the formula, preserved-channel checks and manifest. The earlier statement that all material maps are unchanged applies to the initial TreeCover delivery; this explicit follow-up changes summer B only. R/G/A, the winter map, DEM and road data remain identical. TreeCover payload remains 0e1a20d14bffe5281343e2ab5024def88a9efa107d8eb4a3b7f238c1212e0b9a.
Managed compilation after the combined update: 97 Runtime + 22 Editor, zero warnings/errors. Actual visual improvement, native tree counts and memory behaviour remain for the parent-controlled build and image/memory check. Aerial canopy colour is still an approximation for the forest floor; this revision does not establish photorealistic forest quality.