Ports retail ACRender::polyClipFinish (0x006b6d00, pc:702749) near-eye
semantics into PortalProjection.ProjectToClip - the fundamental fix for
the in-plane portal clip family (climb strobes, tower-top roof/floor
flap while turning; live-corroborated this session: [viewer-diff]
0xAAB30108 strobing 27x mid-climb, whole interior dropping at the top).
Pseudocode: docs/research/2026-06-11-polyclipfinish-w0-clip-pseudocode.md.
Three legs, all decomp-driven:
1. ProjectToClip clips at w >= 0 EXACTLY (was EyePlaneW=1e-4), with
retail's any-negative-w gate. Boundary intersections land at w == 0
(homogeneous directions), so a portal the eye is CROSSING yields the
correct unbounded half-region that the bounded view-region clip cuts
to the screen. A w=0 vertex cannot survive a bounded region clip
into the divide (direction fails some edge of any bounded convex
region); the measure-zero corner case is guarded non-finite->empty.
2. CellView.CanonicalKey keys ALL-COLLINEAR (zero-area) views as their
snapped segment ("L:" + extremes) instead of rejecting them - retail
PROPAGATES degenerate views (ClipPortals decomp:433651-433711
forwards any count!=0 GetClip output, no area gate anywhere), keeping
the cell behind an exactly-in-plane portal in the draw list (cells
draw whole; onward floods die naturally). Rejection dropped the
whole chain for the frame - the parked-eye knife-edge band. Finite
key space unchanged -> dedup + strict-growth convergence intact.
3. The EyeInsidePortalOpening rescue is DELETED (the T2-documented
compensation for the 1e-4 divergence) along with EyeStandingPerpDist
+ PointInPoly2D. Empty clip = no flood, period (retail's rule).
CornerFloodReplay - the gate that REFUTED the previous deletion
attempt - passes WITHOUT the rescue under the W=0 port.
Harness criterion corrected to retail's rules (it codified the rescue):
cells fully BEHIND the camera are not required (all-behind portals clip
empty in retail); monotone area holds per root regime; the two
manufactured exact-on-plane steps assert root-only (boundary root pick
is ambiguous; the in-plane portal there is ~perpendicular to the gaze =
genuinely off-screen). Build_CollapsedInteriorPortalNearEye test
inverted to pin the retail empty-clip rule (it pinned the rescue).
New pins: eye-crossing portal -> w==0 boundary verts + half-region (not
sliver); gaze-along-plane degenerate view accepted + segment-key dedup;
non-finite guard. Replay harnesses (CornerFloodReplay, Issue120,
TowerAscent, HouseExit, Issue127) all green.
Suites: App 246+1skip / Core 1430+2skip / UI 420 / Net 294.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
5.2 KiB
ACRender::polyClipFinish — W=0 eye-plane clip pseudocode (the knife-edge port)
Source: ACRender::polyClipFinish at 0x006b6d00,
docs/research/named-retail/acclient_2013_pseudo_c.txt:702749-702988.
Read 2026-06-11 for the knife-edge in-plane portal clip port
(handoff docs/research/2026-06-11-tower-stairs-fundamental-handoff.md §5).
Signature (reconstructed)
polyClipFinish(view_vertex** inVerts, // arg1 — homogeneous clip-space verts (x,y,z,w)
int inCount, // arg2
Vec2Dscreen** outVerts, // arg3 — output vertex pointers
int* outCount, // arg4
int planeMask) // arg5 — per-edge skip mask (bit set = poly already
// fully inside that portal_view edge)
Part 1 — the W=0 eye-plane pass (0x006b6d5d–0x006b6f12)
scan = inCount - 1
while scan >= 0: # walk verts from the END
if inVerts[scan].w < 0: break # found a vertex BEHIND the eye plane → must clip
scan -= 1
if scan < 0: goto edge_clips # all w >= 0 → skip the W pass entirely
# homogeneous Sutherland-Hodgman against w = 0, intersections EMITTED:
out = []
prev = inVerts[0]; prevIn = (prev.w >= 0)
for cur in inVerts[last..0]: # retail iterates indices descending
curIn = (cur.w >= 0)
if curIn != prevIn:
t = prev.w / (prev.w - cur.w) # 0x006b6ea0: w0 / (w0 - w1)
emit(prev + t*(cur - prev)) # interpolates x, y, z, w → lands at w == 0 exactly
if curIn: emit(cur)
prev, prevIn = cur, curIn
if len(out) < 3: return # 0x006b6f00: reject — fewer than 3 survivors
inVerts = out # ping-pong to tempPtBuf
x87 flag-decode note (the BN polarity trap, feedback_bn_decomp_field_names):
the scan loop's test ah, 0x5 (C0|C2) breaks on w < 0, NOT w ≥ 0. Decoded by
case analysis: the all-behind polygon must reach the W pass and clip to empty
(reject), and the common all-in-front polygon must skip the pass — only the
break-on-negative decode yields both. The inside predicate in the clip pass
(test ah, 0x41, C0|C3) is inside ⇔ w ≥ 0 (emit-on-sign-change with
t = w0/(w0−w1) confirms: t∈[0,1] requires opposite signs).
Part 2 — portal_view edge clips (0x006b6d82–0x006b7030)
for each portal_view edge (vertex pair), mask-gated (planeMask bit set → skip):
# homogeneous 2D edge function for vertex P against edge (a → b):
# side(P) = (P.x − a.x·P.w)·(b.y − a.y) − (P.y − a.y·P.w)·(b.x − a.x)
# (0x006b6e05) — linear in (x, y, w): valid for w = 0 verts (directions).
Sutherland-Hodgman with intersection emission (t = s0/(s0 − s1), all 4 comps)
if survivors < 3: return # 0x006b6fe1
*outCount = survivors # 0x006b7006
The load-bearing semantics for acdream
- Clip at w ≥ 0 EXACTLY — boundary intersections land at w == 0. A w=0
vertex is a homogeneous DIRECTION; the polygon containing it represents the
unbounded screen region extending toward that direction. This is what makes
an eye-crossing portal (climbing through a stair opening) produce the
correct large half-region instead of a bounded sliver:
- At
w ≥ ε(our oldEyePlaneW = 1e-4), boundary verts are finite NDC points ~1e4 units out along the portal-plane horizon line; the polygon's screen intersection still APPROXIMATES the half-region, but the divide and the dedup/merge operate on degenerate near-collinear coordinates. - At
w = 0, the edge functions stay exact (linear in homogeneous coords) and no divide ever touches a w=0 vertex (see invariant below).
- At
- A w=0 vertex can never survive the region clip into the divide when the clip region is BOUNDED: for a bounded convex CCW region the edge directions wrap 360°, so a nonzero direction fails at least one edge's inside test. Our regions are always bounded (FullScreenQuad and its descendants), so the post-clip divide is safe by construction. The measure-zero exception (direction exactly on a region corner) is guarded by a non-finite check that returns empty — identical net behavior to retail's degenerate sliver.
- Empty is a verdict, not an error.
< 3 survivors → rejectat every stage; retail has NO eye-in-opening rescue anywhere in this path. The acdreamEyeInsidePortalOpeningrescue was the documented compensation for theEyePlaneW = 1e-4divergence (T2 ledger) and is deleted with this port.
What is NOT ported here
cdstW = 0.000199999995(pinned at0x007247d5) — consumed elsewhere (its consumer is still unmapped;landPolysDraw0x006b7040 uses the same 0.0002 inline for plane side tests).PortalSideEpsilon = 0.01stays as the documented root-lag tolerance (T2 refutation: retail's 0.0002 needs eye-exact viewer-cell tracking first).- The
planeMaskper-edge skip — a perf short-circuit; our ClipToRegion clips against every region edge unconditionally. - Retail's descending vertex iteration order — Sutherland-Hodgman output is order-invariant up to rotation; we keep ascending.