fix #131 (root cause): look-in cells draw their emitters - the cell-particles pass was missing from the #124 sub-pass
The teleport capture pinned it: walking into the portal flipped pCell to 0xA9B4017A - the hall's PORCH EnvCell. The swirl emitter is owned by a static inside another building's cell. Outdoors the merge path runs the main per-cell pass incl. DrawCellParticles -> visible; under an interior root the #124 look-in sub-pass drew shells + statics but had no cell-particles call. Retail's nested DrawCells draws objects WITH their emitters (DrawObjCellForDummies pc:432878+). Fix: DrawBuildingLookIns pass 2 invokes DrawCellParticles per look-in cell with its static bucket. The owner-cone verdicts were geometrically correct all along (0xC0A9B462 = a porch torch); fixes 1-2 were real-but-adjacent (the unattached pass plugs an independent hole; the alpha deferral fixed #132). Suites: App 260+1skip / Core 1439+2skip / UI 420 / Net 294 green. Awaiting the swirl gate. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
a07279dfd1
commit
47f32cd45c
2 changed files with 49 additions and 10 deletions
|
|
@ -4635,15 +4635,27 @@ the landscape stage is now TWO phases per frame — EARLY per slice: sky,
|
||||||
terrain, outdoor static meshes (the look-in punches need their depth, the
|
terrain, outdoor static meshes (the look-in punches need their depth, the
|
||||||
#117 lesson); then the #124 look-ins; then LATE per slice: outside-stage
|
#117 lesson); then the #124 look-ins; then LATE per slice: outside-stage
|
||||||
dynamics' meshes + ALL attached scene particles + weather + the
|
dynamics' meshes + ALL attached scene particles + weather + the
|
||||||
unattached pass. Outdoor roots keep their existing order (no look-ins in
|
unattached pass. (This FIXED #132 indoors but not the portal.)
|
||||||
the stage; net order unchanged). Residual (documented, AP-34): under
|
|
||||||
OUTDOOR roots slice particles still draw before merged building
|
**ROOT CAUSE (fix 3 — the real one, pinned by the teleport capture):**
|
||||||
interiors (the outdoor sibling of this bug, unreported); building
|
walking into the portal flipped `pCell` to **0xA9B4017A — the hall's
|
||||||
exteriors' own translucent batches draw early.
|
porch EnvCell**. The portal's swirl emitter is owned by a STATIC inside
|
||||||
|
ANOTHER BUILDING'S CELL, not an outdoor entity at all. Outdoors the
|
||||||
|
hall's cells merge into the main frame and the per-cell object pass
|
||||||
|
runs `DrawCellParticles` → swirl visible. Under an interior root the
|
||||||
|
#124 look-in sub-pass drew the far cells' shells + statics but had NO
|
||||||
|
cell-particles call — retail's nested DrawCells draws objects WITH
|
||||||
|
their emitters (`DrawObjCellForDummies`). Every earlier suspect
|
||||||
|
(unattached pass, owner-cone verdicts, alpha ordering) was real-but-
|
||||||
|
adjacent; the cone math was correct all along (the 0xC0A9B462 flips
|
||||||
|
were a porch torch, geometrically defensible).
|
||||||
|
|
||||||
|
**Fix 3:** `DrawBuildingLookIns` pass 2 invokes `DrawCellParticles` per
|
||||||
|
look-in cell with its static bucket (same callback as the main per-cell
|
||||||
|
pass; no-clip slice when the cell has no slot).
|
||||||
|
|
||||||
**Gate:** stand inside, look out the doorway at the town portal — the
|
**Gate:** stand inside, look out the doorway at the town portal — the
|
||||||
swirl renders through the door; the candle flame (#132) stays visible
|
swirl renders through the door.
|
||||||
with the through-opening behind it.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -308,7 +308,10 @@ public sealed class RetailPViewRenderer
|
||||||
// repainted by the root's own shells after the depth clear, so over-draw
|
// repainted by the root's own shells after the depth clear, so over-draw
|
||||||
// here is color-safe; statics draw whole (the main viewcone has no entry
|
// here is color-safe; statics draw whole (the main viewcone has no entry
|
||||||
// for look-in cells; over-include is the safe direction).
|
// for look-in cells; over-include is the safe direction).
|
||||||
private void DrawBuildingLookIns(RetailPViewDrawContext ctx, InteriorEntityPartition.Result partition)
|
private void DrawBuildingLookIns(
|
||||||
|
RetailPViewDrawContext ctx,
|
||||||
|
ClipFrameAssembly clipAssembly,
|
||||||
|
InteriorEntityPartition.Result partition)
|
||||||
{
|
{
|
||||||
if (_lookInFrames.Count == 0)
|
if (_lookInFrames.Count == 0)
|
||||||
return;
|
return;
|
||||||
|
|
@ -355,6 +358,17 @@ public sealed class RetailPViewRenderer
|
||||||
_cellStaticScratch.Clear();
|
_cellStaticScratch.Clear();
|
||||||
_cellStaticScratch.AddRange(bucket);
|
_cellStaticScratch.AddRange(bucket);
|
||||||
DrawEntityBucket(ctx, _cellStaticScratch, _oneCell);
|
DrawEntityBucket(ctx, _cellStaticScratch, _oneCell);
|
||||||
|
|
||||||
|
// #131: the cell-particles pass for look-in cells — retail's
|
||||||
|
// nested DrawCells draws objects WITH their emitters
|
||||||
|
// (DrawObjCellForDummies, pc:432878+). Without this, an
|
||||||
|
// emitter owned by a far building's cell static (the
|
||||||
|
// Holtburg hall-porch portal swirl, cell 0x017A) drew ONLY
|
||||||
|
// when the viewer was outdoors (the merge path runs the
|
||||||
|
// main per-cell pass) — invisible from inside any cottage.
|
||||||
|
foreach (var slice in GetCellSlicesOrNoClip(clipAssembly, cellId))
|
||||||
|
ctx.DrawCellParticles?.Invoke(new RetailPViewCellSliceContext(
|
||||||
|
cellId, slice, _cellStaticScratch));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -410,7 +424,7 @@ public sealed class RetailPViewRenderer
|
||||||
// stage (their punches mark against the terrain/exterior depth just
|
// stage (their punches mark against the terrain/exterior depth just
|
||||||
// drawn), strictly BEFORE the depth clear + seals below, matching
|
// drawn), strictly BEFORE the depth clear + seals below, matching
|
||||||
// retail's LScape::draw placement (DrawCells pc:432719 vs 432732/432785).
|
// retail's LScape::draw placement (DrawCells pc:432719 vs 432732/432785).
|
||||||
DrawBuildingLookIns(ctx, partition);
|
DrawBuildingLookIns(ctx, clipAssembly, partition);
|
||||||
|
|
||||||
// LATE phase (per slice): outside-stage dynamics' meshes (#118 — drawn
|
// LATE phase (per slice): outside-stage dynamics' meshes (#118 — drawn
|
||||||
// pre-clear so the seal protects their aperture pixels; AFTER the
|
// pre-clear so the seal protects their aperture pixels; AFTER the
|
||||||
|
|
@ -429,8 +443,20 @@ public sealed class RetailPViewRenderer
|
||||||
foreach (var e in partition.OutdoorStatic)
|
foreach (var e in partition.OutdoorStatic)
|
||||||
{
|
{
|
||||||
EntitySphere(e, out var c, out float r);
|
EntitySphere(e, out var c, out float r);
|
||||||
if (viewcone.SphereVisibleInOutsideSlice(probeSliceIndex, c, r))
|
bool ownerPass = viewcone.SphereVisibleInOutsideSlice(probeSliceIndex, c, r);
|
||||||
|
if (ownerPass)
|
||||||
_lateParticleOwnerScratch.Add(e);
|
_lateParticleOwnerScratch.Add(e);
|
||||||
|
// #131 owner watchlist (throwaway): ACDREAM_DUMP_ENTITY ids
|
||||||
|
// double as an ENTITY-id watchlist here — one line per watched
|
||||||
|
// outdoor-static owner per CHANGE of its cone verdict.
|
||||||
|
if (AcDream.Core.Rendering.RenderingDiagnostics.ProbeOutStageEnabled
|
||||||
|
&& AcDream.Core.Rendering.RenderingDiagnostics.DumpEntitySourceIds.Contains(e.Id)
|
||||||
|
&& (!_outStageOwnerVerdicts.TryGetValue(e.Id, out bool prev) || prev != ownerPass))
|
||||||
|
{
|
||||||
|
_outStageOwnerVerdicts[e.Id] = ownerPass;
|
||||||
|
Console.WriteLine(System.FormattableString.Invariant(
|
||||||
|
$"[outstage-own] id=0x{e.Id:X8} src=0x{e.SourceGfxObjOrSetupId:X8} pos=({e.Position.X:F1},{e.Position.Y:F1},{e.Position.Z:F1}) c=({c.X:F1},{c.Y:F1},{c.Z:F1}) r={r:F1} slice={probeSliceIndex} {(ownerPass ? "PASS" : "CULL")}"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
foreach (var e in _outsideStageDynamics)
|
foreach (var e in _outsideStageDynamics)
|
||||||
{
|
{
|
||||||
|
|
@ -475,6 +501,7 @@ public sealed class RetailPViewRenderer
|
||||||
// which outdoor dynamics were routed to the outside stage and which
|
// which outdoor dynamics were routed to the outside stage and which
|
||||||
// survived the slice viewcone. Strip with the probe when #131 closes.
|
// survived the slice viewcone. Strip with the probe when #131 closes.
|
||||||
private string? _lastOutStageSig;
|
private string? _lastOutStageSig;
|
||||||
|
private readonly Dictionary<uint, bool> _outStageOwnerVerdicts = new();
|
||||||
|
|
||||||
private void EmitOutStageProbe(int sliceIndex, ViewconeCuller viewcone)
|
private void EmitOutStageProbe(int sliceIndex, ViewconeCuller viewcone)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue