fix(#186): render side-cull mis-sided thin connectors — use dat PortalSide bit, not AABB centroid
The indoor GREY flap at a top-floor connecting room. The render portal side-cull reconstructed each doorway's "interior side" (PortalClipPlane.InsideSide) from the cell's AABB CENTROID. For a THIN connector cell (0xF6820118, 5 render polys), the bounding-box center falls on the WRONG side of the 0118->0116 doorway, so the eye read as a back-portal and the forward room 0116 was culled -> the aperture showed the fog clear color = grey. Retail's PView::InitCell (0x005a4b70) and acdream's own PHYSICS path (CellTransit.cs:190) both read the explicit dat PortalSide bit ((Flags&2)==0) instead of guessing from geometry. Port the render path (GameWindow.BuildLoadedCell) to the same bit. Proven by a live retail cdb trace (retail draws 0116 from the 0118 root at the grey pose; tools/cdb/issue186-connector-decider.cdb) + an offline dat diagnostic (Issue186...PortalSide_CentroidVsDatBit_AtGreyEye): the dat bit matches the old centroid on every portal of these cells EXCEPT the one #186 breaks, so the switch is surgical. Full regression green (App 741 / Core 2631); the CornerFlood + Issue113 dat-loading helpers updated to the same bit confirm every real Holtburg/tower/hall cell floods identically. Touches neither PortalSideEpsilon nor the deleted EyeInsidePortalOpening rescue (the two DO-NOT-RETRY traps). Live-gated: user-confirmed no grey at any camera angle; probe shows 216 root=0118 frames, 0 still grey (0118->0116 now TRV, vis=4). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
9d35a9786f
commit
8257b9ba10
6 changed files with 164 additions and 13 deletions
|
|
@ -7390,9 +7390,6 @@ public sealed class GameWindow : IDisposable
|
|||
var clipPlanes = new List<PortalClipPlane>();
|
||||
var portalPolygons = new List<System.Numerics.Vector3[]>();
|
||||
|
||||
// Compute cell centroid in local space for InsideSide determination.
|
||||
var centroid = (boundsMin + boundsMax) * 0.5f;
|
||||
|
||||
foreach (var portal in envCell.CellPortals)
|
||||
{
|
||||
portals.Add(new CellPortalInfo(
|
||||
|
|
@ -7426,10 +7423,19 @@ public sealed class GameWindow : IDisposable
|
|||
System.Numerics.Vector3.Cross(p1 - p0, p2 - p0));
|
||||
float d = -System.Numerics.Vector3.Dot(normal, p0);
|
||||
|
||||
// Determine InsideSide: which side of the plane the cell centroid is on.
|
||||
// If centroid dot > 0 → inside is positive half-space (InsideSide=0).
|
||||
float centroidDot = System.Numerics.Vector3.Dot(normal, centroid) + d;
|
||||
int insideSide = centroidDot >= 0 ? 0 : 1;
|
||||
// InsideSide from the dat PortalSide bit — retail PView::InitCell
|
||||
// (0x005a4b70) gates traversal on `iVar9 != portals->portal_side`, and
|
||||
// acdream's own physics path uses the same bit (CellTransit.cs:190).
|
||||
// The former AABB-centroid reconstruction mis-derived the interior side
|
||||
// for THIN connector cells: the connector's bounding-box center falls on
|
||||
// the wrong side of a portal near the cell edge, so the eye read as a
|
||||
// back-portal and the forward room was culled — the #186 grey flap at
|
||||
// 0xF6820118→0116 (retail draws 0116 from that root; cdb-confirmed).
|
||||
// PortalSide (Flags&2)==0 → the portal polygon normal points INTO the
|
||||
// owning cell → interior is the negative half → InsideSide=1. Diagnostic
|
||||
// Issue186…PortalSide_CentroidVsDatBit_AtGreyEye: the dat bit matches the
|
||||
// centroid on every portal of these cells EXCEPT the one #186 breaks.
|
||||
int insideSide = ((ushort)portal.Flags & 0x2) == 0 ? 1 : 0;
|
||||
|
||||
clipPlanes.Add(new PortalClipPlane
|
||||
{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue