Forest density diagnosis, 16 September 2026
Read-only source investigation against native 20260916-022247-campaign/alps-01-pass0-view0.png and view1.png, both inspected. The forest remains a field of individually legible, separated silhouettes. This report changes no production source or asset and makes no native visual-acceptance claim.
Confirmed source mechanism
AlpineForestCanopy.Build first rejects candidate centres when density < .24 or a > density. Each scattered tree then calls Placement.TryPlace, which samples its own location, rejects density below .10 and rejects SiteRoll >= density, before applying the shared 4.5 m spacing registry. Thus smooth regions receive approximately D×D probability before spacing; it is not mathematically exactly D² because centre/site densities differ, the first noise value also offsets centre position, and accepted trees consume extra scatter RNG draws.
ChapterScenery.Groves independently has the same pattern (NextDouble > density*.95 followed by TryPlace). This experiment keeps that code unchanged and examines Canopy only. Low quality and winter are outside this bounded comparison.
Controlled reproduction
ArtSource/Alps/audit_forest_density.py extracts the current production canopy and placement C# into an external harness and executes it with the installed Unity Mono runtime, without starting Unity or a player. The original float expressions, noise, route resampling, candidate sorting, System.Random, mask, all-three-road clearances and 4.5 m occupancy check are retained. Only rendering calls are recorded and height is finite zero: this canopy path has no height/slope veto, and placement eligibility uses XZ.
Candidate counts match native exactly: 9,223 / 12,457. Prior Near/Grove/authored tree positions are not in the native log, so all alternatives begin with the same empty spacing registry. Native had 327 / 826 already registered sites. Controlled baseline is 88 / 176 trees above native, not an exact complete-scene replay. The differences are 0.11% / 0.16% of native canopy count. Mathf helpers are emulated with float-cast System.Math functions; bit-identical native math positions are not independently claimed.
| Stage | Native canopy | Controlled current | Single: TryPlace(p,0) equivalent |
Site probability .5+.5D |
|---|---|---|---|---|
| Alps01 | 77,545 | 77,633 | 84,672 (+9.07%) | 81,294 (+4.72%) |
| Alps02 | 107,855 | 108,031 | 118,702 (+9.88%) | 113,582 (+5.14%) |
All alternatives retain the original centre probability, density minimum, geological veto, and exact same spacing rule. The single alternative removes only the second probabilistic rejection. Because additional accepted trees consume the same production height/yaw random draws, later scattered positions can differ; this is the actual branch behaviour rather than an artificially fixed list of attempted positions.
The strongest source conclusion: 87.60% of selected Alps01 centres already have D≥.8 (Alps02:86.58%). In Alps01, accepted sites below D=.6 rise1,830→3,594 with the single probability, while D≥.8 rises71,055→75,154. The double probability noticeably thins edges and moderate cover, but it is not the main explanation for open-looking high-density forest interiors. Removing it raises overall stem count by about9–10%, while retaining existing species silhouettes, cluster radii, centre layout, source crown width and spacing. It cannot by itself establish a closed, photorealistic canopy.
Geometry, spacing and road limits
Every accepted pivot was rechecked offline. Minimum observed spacing across the six populations is 4.500006 m, satisfying the retained 4.5 m rule. Minimum distance to the same stored road samples used by the production clearance is 37.161 m in baseline Alps02; single-probability Alps02 is 38.911 m. This is sample distance, not road-triangle collision distance. The analytical centre58m minus scatter23.2m minus maximum billboard half-width5.46m leaves 29.34m before accounting for sample interpolation gaps. All pivots remain inside the existing terrain-map bounds. No road or terrain bounds are changed.
Each tree uses 4 vertices and 2 geometry triangles. Position+UV0+UV1 require 28 bytes/vertex; six 16-bit indices add12 bytes, giving124 bytes/tree before engine/object overhead. Approximate mesh buffers:
| Stage | Current | Single probability | Added geometry buffers |
|---|---|---|---|
| Alps01 | 9.181 MiB | 10.013 MiB | 0.832 MiB |
| Alps02 | 12.775 MiB | 14.037 MiB | 1.262 MiB |
Retained CPU plus GPU mesh copies roughly double those figures; transient construction lists, objects, alignment and atlas memory are excluded. No new atlas or material is needed. Extra alpha-tested overlap and Depth/Forward/Motion submissions still cost rendering time, so these byte/triangle figures do not constitute a frame-rate budget acceptance. The existing formal worst case of24,000 centres×24 attempts would be576,000 trees/1,152,000 triangles before rejection, much larger than any population observed here.
Decision
A single probability is a defensible semantic correction if the canonical mask is intended to represent final site density. It would primarily strengthen forest edges and moderate-cover patches. Do not present this as the substantial closed-forest improvement required by the native images; the existing high-density population is already large and the measured total gain is limited. Production remains unchanged pending the root decision.
Structured per-density-bin counts, all six populations, source hashes, road/spacing observations and limitations: Docs/QA/alpine-forest-density-audit.json. Reproducible source harness, counts and position buffers: ArtSource/Alps/ForestDensityAudit/. No GPU/Unity/player operation was performed.