fix #108-residual (root cause): terrain drew DOUBLE-SIDED - port retail landPolysDraw eye-side gate as terrain backface cull
The cellar-ascent grass window was the UNDERSIDE of the z~94 grade sheet. Retail terrain is single-sided: ACRender::landPolysDraw (0x006b7040) draws each land triangle ONLY when the camera is on the POSITIVE (upper) side of its plane (Plane::which_side2 vs Render::FrameCurrent, zFightTerrainAdjust bias) - a below-grade eye gets NO terrain, so retail shows sky through the cellar door. We inherited WB's frame-global cull DISABLE (WB GameScene.cs:841 - an editor camera goes underground by design) and TerrainModernRenderer.Draw set no cull state of its own -> terrain rasterized both sides. From a below-grade eye every aperture sight-ray RISES, so the only 'terrain' it can see is the grade sheet's underside - which painted the exit-door aperture (the landscape slice's 2D NDC clip planes (nx,ny,0,dw) have no depth axis and cannot exclude between-eye-and-portal geometry) and slid off the door exactly as the eye crossed grade. Membership/viewer was exonerated by the harness in the previous commit. Fix: TerrainModernRenderer.Draw owns its cull state (the 7th self-contained-GL-state instance): Enable(CullFace) + CullFace(Back) + FrontFace(Ccw), set -> draw -> restore the frame-global CW + cull-off baseline. GL backface culling evaluates retail's per-triangle eye-side predicate at rasterization; no shader change. Pins: - LandblockMeshTests.Build_AllTriangles_WindCounterClockwiseInWorldXY: every emitted triangle CCW in world XY across both FSplitNESW split directions - the winding invariant culling depends on. - TerrainCullOrientationTests: under the production camera convention (LookAt up=+Z, Numerics perspective) an up-facing triangle winds CCW in window space from above (kept) and CW from below (culled) - guards FrontFace inversion, which would blank terrain from above. Oracle note: retail's through-portal clip has NO portal-face near plane (PView::GetClip / Render::set_view install edge planes only); nearer- than-portal exclusion comes from the eye-side cull + cell-level admission. No register row: this PORTS the retail mechanism, retiring an undocumented WB-heritage deviation. Gate pending: cellar climb (grass window gone) + outdoor sanity glance (terrain intact from above). Suites: App 263+1skip / Core 1443+2skip / UI 420 / Net 294. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
007af1391c
commit
96a425a9a5
4 changed files with 180 additions and 19 deletions
|
|
@ -3701,27 +3701,47 @@ Unverified. The likely culprits, ranked by suspected probability:
|
|||
|
||||
---
|
||||
|
||||
## #108 — Cellar↔main-floor transition: terrain (grass) sweeps across the upstairs door opening — [REOPENED 2026-06-11 · narrowed residual]
|
||||
## #108 — Cellar↔main-floor transition: terrain (grass) sweeps across the upstairs door opening — [FIX SHIPPED 2026-06-12 · awaiting cellar visual gate]
|
||||
|
||||
**Status:** REOPENED (narrowed) — the broad symptom is GONE (T5 +
|
||||
re-gate #2: "Yes, but…"), but a residual remains in ONE window: during
|
||||
the cellar ASCENT, while the eye is still below ground level, the
|
||||
upstairs exit-door opening is covered with grass — "like the ground
|
||||
level rose to the top of the door … as soon as my head pops up it falls
|
||||
back to ground level" (user, re-gate 2026-06-11). The original
|
||||
BR-2-era diagnosis stands: grass-sweep frames render through the
|
||||
OUTDOOR root (membership/viewer-cell flips outdoor mid-cellar), and the
|
||||
#117 depth-gated punch then correctly refuses to punch the aperture
|
||||
where terrain depth is NEARER than the door fan (eye below grade ⇒ the
|
||||
visible front-facing terrain can sit between the eye and the door in
|
||||
depth). The punch must STAY depth-gated (DO-NOT-RETRY) — the fix is on
|
||||
the membership/viewer side (why is the root outdoor while the eye is in
|
||||
the cellar stairwell below grade?). Apparatus shape: a vertical
|
||||
cellar-ascent variant of the #118 exit-walk harness (drive the eye up
|
||||
the stair path; log root resolution + the punch's mark-pass outcome per
|
||||
step). Prior history below.
|
||||
**Status:** FIX SHIPPED (desk-pinned) — root cause found 2026-06-12; the
|
||||
cellar-ascent visual gate is pending.
|
||||
|
||||
**ROOT CAUSE (2026-06-12): terrain was drawn DOUBLE-SIDED — the grass was
|
||||
the UNDERSIDE of the grade sheet.** Two steps:
|
||||
1. The membership/viewer re-diagnosis below is **REFUTED** by the vertical
|
||||
cellar-ascent harness (`Issue108CellarAscentViewerReplayTests`, dat-backed
|
||||
A9B4 corner-building cellar 0x0174→0x0175→0x0171, production
|
||||
FindCellList pick + the camera probe chain mirrored verbatim): 0
|
||||
outdoor/null viewer resolutions while the eye is below grade, 0 sweep
|
||||
failures, 0 fallback branches across boom distance {2.61, 5} × damping
|
||||
lag {0, 0.3}. The viewer enters 0x0171 at eye z 94.01 — exactly as the
|
||||
head pops above grade (the stairwell portal sits at grade), matching the
|
||||
user's wording. The root is INTERIOR the whole window.
|
||||
2. Retail terrain is SINGLE-SIDED: `ACRender::landPolysDraw` (0x006b7040)
|
||||
draws each land triangle ONLY when the camera is on the POSITIVE (upper)
|
||||
side of its plane (`Plane::which_side2` vs `Render::FrameCurrent`). A
|
||||
below-grade eye gets NO terrain — through the door retail shows sky.
|
||||
WB renders the world with face culling DISABLED frame-globally (WB
|
||||
`GameScene.cs:841` — editor heritage), and `TerrainModernRenderer.Draw`
|
||||
set no cull state of its own → terrain drew double-sided. From a
|
||||
below-grade eye every aperture sight-ray RISES, so the only "terrain" it
|
||||
can see is the underside of the z≈94 grade sheet — which painted the
|
||||
whole exit-door aperture (the landscape slice's 2D NDC clip planes
|
||||
`(nx,ny,0,dw)` have no depth axis and cannot exclude it) and slid down
|
||||
off the door exactly as the eye crossed grade.
|
||||
**Fix: port the landPolysDraw eye-side gate as terrain backface culling**
|
||||
— `TerrainModernRenderer.Draw` now owns Enable(CullFace) + Cull(Back) +
|
||||
FrontFace(Ccw) (set→draw→restore; 7th instance of the self-contained-GL-
|
||||
state rule). Pins: `LandblockMeshTests.Build_AllTriangles_WindCounter-
|
||||
ClockwiseInWorldXY` (every emitted triangle CCW in world XY — cull-safe
|
||||
winding) + `TerrainCullOrientationTests` (above-eye ⇒ CCW window winding
|
||||
kept / below-eye ⇒ CW culled under the production camera convention).
|
||||
**Gate:** climb out of the corner-building cellar — the grass window over
|
||||
the exit door must be gone (sky/world through the door instead); plus a
|
||||
general outdoor sanity glance (terrain intact from above — a wrong
|
||||
FrontFace would blank it).
|
||||
**Severity:** MEDIUM
|
||||
**Component:** ~~render / indoor PView~~ → **physics / membership** (cellar-transition root flip)
|
||||
**Component:** render / terrain (single-sidedness) — membership/viewer EXONERATED
|
||||
|
||||
During the cellar→main-floor ascent (Holtburg), the door opening visible on the main floor
|
||||
shows the outdoor GRASS texture sweeping over it — "like outdoor ground rising up from the
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue