fix(G.3): register portals-only connector cells for visibility (#133 ramp grey)
The grey "barrier" at a dungeon ramp was a one-cell registration gap. The ramp's connector cell (0x0007014D) is a portals-only pass-through — CellMesh.Build yields 0 drawable sub-meshes for it (you walk through it on adjacent floors). But the whole registration block — including the portal-VISIBILITY registration (BuildLoadedCell -> _cellVisibility) — was gated behind `if (cellSubMeshes.Count > 0)`. So that cell was never added to the visibility graph; the flood lookup-missed it (PortalVisibilityBuilder :369), couldn't traverse it to the room below, and the grey clear color showed through. Confirmed live via two added probes: [cellreg] registered=204/205 (only 0x014D missing) + [pv-trace] p4->0x0007014D skip=lookup-miss. After the fix: registered=205, hasRamp=True, skip=lookup-miss gone, the room below renders. Fix: compute the cell transforms and call BuildLoadedCell (visibility) for EVERY cell with a valid cellStruct, regardless of drawable sub-meshes — matching retail, which keeps the whole landblock cell array resident before the flood runs. Drawing (RegisterCell, _pendingCellMeshes) and the physics BSP (CacheCellStruct) stay gated on drawable geometry (a portals-only connector has nothing to draw and no collision surface). Not a regression from the FPS-collapse work — a pre-existing gate the now-navigable dungeon exposed (every ramp/stair/cellar mouth would show it). TEMP diagnostics retained for the residual angle-grey investigation (strip after): [cellreg] (GameWindow), the 0x0007 [pv-trace] gate widen + raw-NDC bbox (PortalVisibility- Builder). Three earlier render-math theories (portal_side, on-screen clip, near-eye projection) were each refuted by apparatus/probe before shipping — this is the verified one. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
7d8da99f79
commit
d90c5385d2
2 changed files with 77 additions and 33 deletions
|
|
@ -759,7 +759,13 @@ public static class PortalVisibilityBuilder
|
|||
|
||||
private static bool IsHoltburgIndoorProbeCell(uint cellId)
|
||||
{
|
||||
if ((cellId & 0xFFFF0000u) != 0xA9B40000u)
|
||||
uint lb = cellId & 0xFFFF0000u;
|
||||
// TEMP (#133 ramp-flood-collapse diagnosis): widen the [pv-trace] gate to the
|
||||
// 0x0007 Town Network dungeon so the per-portal skip= reason (lookup-miss /
|
||||
// clip-empty / reciprocal-empty / side) is emitted for the ramp neighbour.
|
||||
if (lb == 0x00070000u)
|
||||
return true;
|
||||
if (lb != 0xA9B40000u)
|
||||
return false;
|
||||
uint low = cellId & 0xFFFFu;
|
||||
return low >= 0x016F && low <= 0x0175;
|
||||
|
|
@ -821,6 +827,7 @@ public static class PortalVisibilityBuilder
|
|||
// genuinely off-screen; the ndc coords (post-clip, bounded) show where on screen it lands.
|
||||
int projN = -1, clipN = -1;
|
||||
string ndcText = "";
|
||||
string rawText = "";
|
||||
if (i < cameraCell.PortalPolygons.Count)
|
||||
{
|
||||
var poly = cameraCell.PortalPolygons[i];
|
||||
|
|
@ -830,6 +837,21 @@ public static class PortalVisibilityBuilder
|
|||
projN = clip.Length;
|
||||
if (clip.Length >= 3)
|
||||
{
|
||||
// Raw projected-NDC bbox (pre-screen-clip): WHERE the portal lands on screen,
|
||||
// even when ClipToRegion drops it to empty. A clip=0 portal whose raw bbox is
|
||||
// inside [-1,1] is on-screen-but-wrongly-dropped (the bug); a bbox outside
|
||||
// [-1,1] is genuinely off-screen (correct). Distinguishes the two.
|
||||
float rminX = float.MaxValue, rminY = float.MaxValue, rmaxX = -float.MaxValue, rmaxY = -float.MaxValue;
|
||||
foreach (var cv in clip)
|
||||
{
|
||||
if (cv.W <= 1e-6f) continue;
|
||||
float nx = cv.X / cv.W, ny = cv.Y / cv.W;
|
||||
rminX = MathF.Min(rminX, nx); rmaxX = MathF.Max(rmaxX, nx);
|
||||
rminY = MathF.Min(rminY, ny); rmaxY = MathF.Max(rmaxY, ny);
|
||||
}
|
||||
if (rminX <= rmaxX)
|
||||
rawText = FormattableString.Invariant($" raw=[{rminX:F1},{rminY:F1}..{rmaxX:F1},{rmaxY:F1}]");
|
||||
|
||||
var ndc = PortalProjection.ClipToRegion(clip, FullScreenQuad);
|
||||
clipN = ndc.Length;
|
||||
var ns = new System.Text.StringBuilder(48);
|
||||
|
|
@ -842,6 +864,7 @@ public static class PortalVisibilityBuilder
|
|||
sb.Append(" D=").Append(float.IsNaN(d) ? "na" : d.ToString("F2"));
|
||||
sb.Append(side ? " TRV" : " CULL");
|
||||
sb.Append(" proj=").Append(projN).Append(" clip=").Append(clipN);
|
||||
if (rawText.Length > 0) sb.Append(rawText);
|
||||
if (ndcText.Length > 0) sb.Append(" ndc=").Append(ndcText);
|
||||
}
|
||||
sb.Append(" || outPolys=").Append(frame.OutsideView.Polygons.Count);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue