fix(render): FW4 slice 3 - the outside-stage predicate reads the walk flood
The cathedral falls persisted through the slice-2 seal fix; the probe already held the tell: the same two emitter entities (f4243/f4285) draw phase=pre on good frames and phase=post on bad ones. They are interior-parented, so DynamicDrawsInOutsideStage takes the indoor arm, whose first gate is flood membership - and that still read the OLD apparatus flood, which drops cells at the #456 seam band. On those frames the falls fell to the post-clear last pass and splatted across the cleared depth (terrain and water alike). Both predicate call sites (the frame product's BuildOutsideDynamicRoutes via BuildAndBorrow's input, and the renderer's own outside-stage classification) now receive the walk's VisitedCells on walk frames - root flood plus look-in floods, all of whose objects retail draws inside LScape::draw, pre-clear. drawableCells keeps its other roles. Also adds the probe-gated [walk-dyn] per-entity classification dump (parent cell, outside/cone verdicts) so a surviving repro pins the failing gate directly. Hermetic 6,762/0, Walk lane 213/1. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
parent
c40aecfc8c
commit
5f7ccdeab5
2 changed files with 40 additions and 13 deletions
|
|
@ -465,6 +465,18 @@ public sealed class RetailPViewRenderer
|
||||||
_candidateObserver?.BeginPViewFrame();
|
_candidateObserver?.BeginPViewFrame();
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
// FW4 slice 3: the outside-stage predicate's flood-membership set
|
||||||
|
// is THE WALK'S visited cells on walk frames (root flood +
|
||||||
|
// look-in floods — retail draws all of their objects inside
|
||||||
|
// LScape::draw, pre-clear). The old apparatus's drawableCells
|
||||||
|
// misses cells at the #456 seam band, dropping interior-parented
|
||||||
|
// outdoor emitters (the cathedral falls weenies) to the
|
||||||
|
// post-clear last pass, where the cleared depth lets them splat
|
||||||
|
// across terrain and water. drawableCells keeps its other roles
|
||||||
|
// (prepare filter, frame result) unchanged.
|
||||||
|
HashSet<uint> outsideStageFlood =
|
||||||
|
walkActive ? walkDriver!.VisitedCells : drawableCells;
|
||||||
|
|
||||||
if (_sceneFrameProduct is not null)
|
if (_sceneFrameProduct is not null)
|
||||||
{
|
{
|
||||||
frameView = _sceneFrameProduct.BuildAndBorrow(
|
frameView = _sceneFrameProduct.BuildAndBorrow(
|
||||||
|
|
@ -472,7 +484,7 @@ public sealed class RetailPViewRenderer
|
||||||
clipAssembly,
|
clipAssembly,
|
||||||
viewcone,
|
viewcone,
|
||||||
_lookInFrames,
|
_lookInFrames,
|
||||||
drawableCells,
|
outsideStageFlood,
|
||||||
ctx.Cells,
|
ctx.Cells,
|
||||||
ctx.AnimatedEntityIds,
|
ctx.AnimatedEntityIds,
|
||||||
ctx.RootCell.IsOutdoorNode);
|
ctx.RootCell.IsOutdoorNode);
|
||||||
|
|
@ -544,7 +556,11 @@ public sealed class RetailPViewRenderer
|
||||||
foreach (var e in partition.Dynamics)
|
foreach (var e in partition.Dynamics)
|
||||||
{
|
{
|
||||||
EntitySphere(e, out var c, out float r);
|
EntitySphere(e, out var c, out float r);
|
||||||
if (DynamicDrawsInOutsideStage(e.ParentCellId, c, r, drawableCells, ctx.Cells))
|
// FW4 slice 3: same walk-flood membership set as the
|
||||||
|
// frame product's BuildOutsideDynamicRoutes — the two
|
||||||
|
// predicate call sites must agree or routed and drawn
|
||||||
|
// stages diverge.
|
||||||
|
if (DynamicDrawsInOutsideStage(e.ParentCellId, c, r, outsideStageFlood, ctx.Cells))
|
||||||
_outsideStageDynamics.Add(e);
|
_outsideStageDynamics.Add(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1141,6 +1141,10 @@ internal sealed class RenderScenePViewFrameBuilder
|
||||||
private readonly Dictionary<RenderProjectionId, int>
|
private readonly Dictionary<RenderProjectionId, int>
|
||||||
_dynamicPositions = [];
|
_dynamicPositions = [];
|
||||||
private int _dynamicCount;
|
private int _dynamicCount;
|
||||||
|
|
||||||
|
// ACDREAM_PROBE_WALK_ROOT companion (throwaway): rate limiter for the
|
||||||
|
// [walk-dyn] outside-stage classification dump.
|
||||||
|
private uint _probeDynFrameCounter;
|
||||||
private int _dirtyCount;
|
private int _dirtyCount;
|
||||||
private RenderSceneGeneration _indexGeneration;
|
private RenderSceneGeneration _indexGeneration;
|
||||||
private ulong _indexRevision;
|
private ulong _indexRevision;
|
||||||
|
|
@ -1320,6 +1324,9 @@ internal sealed class RenderScenePViewFrameBuilder
|
||||||
return;
|
return;
|
||||||
|
|
||||||
int sliceCount = input.ClipAssembly.OutsideViewSlices.Length;
|
int sliceCount = input.ClipAssembly.OutsideViewSlices.Length;
|
||||||
|
bool probeDynamics =
|
||||||
|
AcDream.Core.Rendering.RenderingDiagnostics.ProbeWalkRootEnabled
|
||||||
|
&& ++_probeDynFrameCounter % 120 == 0;
|
||||||
for (int sliceIndex = 0; sliceIndex < sliceCount; sliceIndex++)
|
for (int sliceIndex = 0; sliceIndex < sliceCount; sliceIndex++)
|
||||||
{
|
{
|
||||||
int count = 0;
|
int count = 0;
|
||||||
|
|
@ -1328,19 +1335,23 @@ internal sealed class RenderScenePViewFrameBuilder
|
||||||
{
|
{
|
||||||
RenderProjectionRecord record = _dynamics[i];
|
RenderProjectionRecord record = _dynamics[i];
|
||||||
Sphere(in record, out Vector3 center, out float radius);
|
Sphere(in record, out Vector3 center, out float radius);
|
||||||
if (!RetailPViewRenderer.DynamicDrawsInOutsideStage(
|
bool outside = RetailPViewRenderer.DynamicDrawsInOutsideStage(
|
||||||
ParentCell(in record),
|
ParentCell(in record),
|
||||||
center,
|
center,
|
||||||
radius,
|
radius,
|
||||||
input.DrawableCells,
|
input.DrawableCells,
|
||||||
input.Cells)
|
input.Cells);
|
||||||
|| !input.Viewcone.SphereVisibleInOutsideSlice(
|
bool cone = input.Viewcone.SphereVisibleInOutsideSlice(
|
||||||
sliceIndex,
|
sliceIndex, in center, radius);
|
||||||
in center,
|
if (probeDynamics)
|
||||||
radius))
|
|
||||||
{
|
{
|
||||||
continue;
|
Console.WriteLine(
|
||||||
|
$"[walk-dyn] slice={sliceIndex} id={record.Source.LocalEntityId:x} "
|
||||||
|
+ $"parent={ParentCell(in record)?.ToString("x8") ?? "null"} "
|
||||||
|
+ $"r={radius:F1} outside={(outside ? 1 : 0)} cone={(cone ? 1 : 0)}");
|
||||||
}
|
}
|
||||||
|
if (!outside || !cone)
|
||||||
|
continue;
|
||||||
|
|
||||||
_survivors[count++] = record;
|
_survivors[count++] = record;
|
||||||
writer.AddDynamic(in record);
|
writer.AddDynamic(in record);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue