diag(render/physics): flap root-caused to physics rest µm-jitter; refute prior diagnoses
Apparatus + handoff for the indoor flap. Confirmed (primary evidence): the flap is the portal-flood clip being µm-sensitive at the threshold, driven by a ~1-8µm jitter in the player RenderPosition (physics resting position not bit-stable; Lerp surfaces it). REFUTES the 2026-06-07 see-through/EnvCell/outdoor-node diagnosis (ModelId GfxObj 0x01000A2B IS the solid exterior) AND an enqueue-once attempt (retail propagates late slices via AddToCell; the existing PropagatesNewSlicesToExit test caught it; reverted). Adds: Build determinism test, A8CellAudit gfxobj dump, [pv-input] 6dp probe + [render-sig] outRoot/bshell fields. No functional fix shipped. Next: higher-precision physics rest trace -> port retail kill_velocity/contact rest-stability. Canonical: docs/research/2026-06-08-flap-rootcause-physics-rest-handoff.md Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d0b65c4170
commit
d6aa526dd3
6 changed files with 300 additions and 1 deletions
|
|
@ -7560,6 +7560,19 @@ public sealed class GameWindow : IDisposable
|
|||
clipAssembly = pviewResult.ClipAssembly;
|
||||
envCellShellFilter = pviewResult.DrawableCells;
|
||||
_interiorPartition = pviewResult.Partition;
|
||||
|
||||
// Flap root-cause apparatus (2026-06-07): per-frame, the EXACT Build inputs at 6 dp +
|
||||
// the resulting flood count. The live flap shows flood flipping 2↔6 at an eye/player
|
||||
// identical to cm; this answers whether the inputs differ sub-cm (jitter) or are
|
||||
// byte-identical (nondeterminism). See RenderingDiagnostics.ProbePvInputEnabled.
|
||||
if (AcDream.Core.Rendering.RenderingDiagnostics.ProbePvInputEnabled && pvFrame is not null)
|
||||
{
|
||||
var vp = envCellViewProj;
|
||||
char pvOutRoot = ReferenceEquals(clipRoot, _outdoorNode) ? 'Y' : 'n';
|
||||
Console.WriteLine(System.FormattableString.Invariant(
|
||||
$"[pv-input] outRoot={pvOutRoot} flood={pvFrame.OrderedVisibleCells.Count} eye=({camPos.X:F6},{camPos.Y:F6},{camPos.Z:F6}) player=({playerViewPos.X:F6},{playerViewPos.Y:F6},{playerViewPos.Z:F6}) vp=[{vp.M11:F6} {vp.M13:F6} {vp.M22:F6} {vp.M31:F6} {vp.M33:F6} {vp.M41:F6} {vp.M42:F6} {vp.M43:F6}]"));
|
||||
}
|
||||
|
||||
sigPvFrame = pviewResult.PortalFrame;
|
||||
sigClipAssembly = pviewResult.ClipAssembly;
|
||||
sigDrawableCells = pviewResult.DrawableCells;
|
||||
|
|
@ -9190,6 +9203,22 @@ public sealed class GameWindow : IDisposable
|
|||
sb.Append(" outdoorRootObjs=").Append(outdoorRootObjectCount);
|
||||
sb.Append(" liveDynDraw=").Append(liveDynamicDrawnCount);
|
||||
|
||||
// Diagnosis 2026-06-07: draw-vs-occlude probe for the see-through residual.
|
||||
// outRoot=Y means clipRoot is the synthetic outdoor node (eye outdoors). bshell=total/withMesh
|
||||
// counts the building ModelId exterior shells queued in partition.Outdoor for this frame — the
|
||||
// GfxObj exteriors that SHOULD draw the solid walls. Correlate with ids= (the flooded interior
|
||||
// cells): if bshell=N/N and ids=[node only] but the wall is still see-through, the exterior is
|
||||
// failing to rasterize (draw/clip bug, not EnvCell sidedness); if ids includes interior cells,
|
||||
// the outdoor flood is drawing interiors over the exterior.
|
||||
sb.Append(" outRoot=").Append(ReferenceEquals(clipRoot, _outdoorNode) ? 'Y' : 'n');
|
||||
if (partition is not null)
|
||||
{
|
||||
int shellTotal = 0, shellMesh = 0;
|
||||
foreach (var e in partition.Outdoor)
|
||||
if (e.IsBuildingShell) { shellTotal++; if (e.MeshRefs.Count > 0) shellMesh++; }
|
||||
sb.Append(" bshell=").Append(shellTotal).Append('/').Append(shellMesh);
|
||||
}
|
||||
|
||||
if (outdoorPortalDrawn || exteriorPvFrame is not null || exteriorClipAssembly is not null)
|
||||
{
|
||||
sb.Append(" extPortal=").Append(outdoorPortalDrawn ? 'Y' : 'n');
|
||||
|
|
|
|||
|
|
@ -129,6 +129,20 @@ public static class RenderingDiagnostics
|
|||
public static bool ProbeShellEnabled { get; set; } =
|
||||
Environment.GetEnvironmentVariable("ACDREAM_PROBE_SHELL") == "1";
|
||||
|
||||
/// <summary>
|
||||
/// Flap root-cause apparatus (2026-06-07). When true, the indoor render path emits ONE
|
||||
/// <c>[pv-input]</c> line per frame with the EXACT PortalVisibilityBuilder.Build inputs at HIGH
|
||||
/// precision (camera eye + player position to 6 dp, plus orientation-sensitive view-projection
|
||||
/// elements) alongside the resulting flood cell count. The live flap shows the flood set flipping
|
||||
/// 2↔6 at an eye/player that is identical to cm; this probe answers whether the Build INPUTS differ
|
||||
/// below cm precision (sub-cm view jitter → robustness fix) or are byte-identical while the output
|
||||
/// still flips (nondeterminism → surgical bug). Runs WITHOUT the heavy <c>[flap]</c>/<c>[render-sig]</c>
|
||||
/// spam so the log stays diffable. Throwaway apparatus — strip once the jitter source is pinned.
|
||||
/// Initial state from <c>ACDREAM_PROBE_PVINPUT=1</c>.
|
||||
/// </summary>
|
||||
public static bool ProbePvInputEnabled { get; set; } =
|
||||
Environment.GetEnvironmentVariable("ACDREAM_PROBE_PVINPUT") == "1";
|
||||
|
||||
// Cell-change gate for EmitVis. The probe fires once per distinct root cell
|
||||
// so launch.log stays readable under motion (the per-frame call is a no-op
|
||||
// when the root is unchanged). Sentinel 0 = "no root yet" — the first real
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue