diag(phys): A6.P3 slice 4 — add [poly-dump] probe for #98 investigation
Adds a polygon-geometry dump probe that fires alongside [push-back]
whenever AdjustSphereToPlane lands a push-back. Gated by
ACDREAM_PROBE_POLY_DUMP=1.
Output format:
[poly-dump] cell=0xA9B40147 polyId=0x0042 numPts=4 sides=Single
n=(0.000,-0.719,0.695) d=-0.1007
verts=[(x1,y1,z1),(x2,y2,z2),(x3,y3,z3),(x4,y4,z4)]
Purpose: investigate #98 (cellar-up stuck at top step). The push-back
trace shows the player hitting a sloped surface n=(0,-0.719,0.695) at
the cellar stair top. Two possibilities:
1. The polygon really IS sloped 44° in the dat (genuine geometry).
2. Our dat-read produces wrong vertices → wrong normal → wrong plane.
The dump lets us:
- Identify which dat polygon was hit (cell + poly ID)
- Compare our extracted vertices against WorldBuilder's straight-from-
dat read for the same poly
- Or spawn the cell in ACViewer to visually verify the geometry
Changes:
- Added `ushort Id` property to ResolvedPolygon (defaults to 0 for test
fixtures that don't care; production code in PhysicsDataCache.cs +
BSPQuery.cs sets it from the dictionary key).
- Added ProbePolyDumpEnabled + LogPolyDump in PhysicsDiagnostics.
- Wired the dump into AdjustSphereToPlane's apply-branch (after the
existing push-back log; same gating pattern).
Test suite: 1148 pass + 8 pre-existing fail (baseline maintained).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ceeb06be7d
commit
0b449968a7
3 changed files with 64 additions and 0 deletions
|
|
@ -394,6 +394,14 @@ public static class BSPQuery
|
||||||
applied: true);
|
applied: true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (PhysicsDiagnostics.ProbePolyDumpEnabled)
|
||||||
|
{
|
||||||
|
// A6.P3 slice 4 (2026-05-22): dump the polygon geometry to
|
||||||
|
// cross-reference against WorldBuilder's straight-from-dat
|
||||||
|
// read. CellId taken from path.CheckCellId.
|
||||||
|
PhysicsDiagnostics.LogPolyDump(path.CheckCellId, poly);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -2212,6 +2220,7 @@ public static class BSPQuery
|
||||||
Plane = new Plane(normal, planeD),
|
Plane = new Plane(normal, planeD),
|
||||||
NumPoints = n,
|
NumPoints = n,
|
||||||
SidesType = poly.SidesType,
|
SidesType = poly.SidesType,
|
||||||
|
Id = id,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return resolved;
|
return resolved;
|
||||||
|
|
|
||||||
|
|
@ -289,6 +289,7 @@ public sealed class PhysicsDataCache
|
||||||
Plane = new Plane(normal, d),
|
Plane = new Plane(normal, d),
|
||||||
NumPoints = numVerts,
|
NumPoints = numVerts,
|
||||||
SidesType = poly.SidesType,
|
SidesType = poly.SidesType,
|
||||||
|
Id = id,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
return resolved;
|
return resolved;
|
||||||
|
|
@ -383,6 +384,15 @@ public sealed class ResolvedPolygon
|
||||||
public required Plane Plane { get; init; }
|
public required Plane Plane { get; init; }
|
||||||
public required int NumPoints { get; init; }
|
public required int NumPoints { get; init; }
|
||||||
public required CullMode SidesType { get; init; }
|
public required CullMode SidesType { get; init; }
|
||||||
|
/// <summary>
|
||||||
|
/// Polygon index within its parent (cell or GfxObj). Used by the
|
||||||
|
/// `ACDREAM_PROBE_POLY_DUMP` probe (A6.P3 slice 4 investigation,
|
||||||
|
/// 2026-05-22) to identify which dat polygon a push-back hit so we
|
||||||
|
/// can compare our extracted vertices/plane against WorldBuilder's
|
||||||
|
/// straight-from-dat read. Defaults to 0 for test fixtures that
|
||||||
|
/// don't care about polygon identity.
|
||||||
|
/// </summary>
|
||||||
|
public ushort Id { get; init; }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>Cached physics data for a single GfxObj part.</summary>
|
/// <summary>Cached physics data for a single GfxObj part.</summary>
|
||||||
|
|
|
||||||
|
|
@ -304,6 +304,51 @@ public static class PhysicsDiagnostics
|
||||||
public static bool ProbePushBackEnabled { get; set; } =
|
public static bool ProbePushBackEnabled { get; set; } =
|
||||||
Environment.GetEnvironmentVariable("ACDREAM_PROBE_PUSH_BACK") == "1";
|
Environment.GetEnvironmentVariable("ACDREAM_PROBE_PUSH_BACK") == "1";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A6.P3 slice 4 investigation (2026-05-22) — dumps the polygon's
|
||||||
|
/// vertices + plane + sidesType + cell id whenever a push-back fires.
|
||||||
|
/// Lets us compare our extracted polygon (from our cache) against
|
||||||
|
/// WorldBuilder's straight-from-dat read for the same poly index, to
|
||||||
|
/// falsify the "is our dat-read producing wrong polygon geometry?"
|
||||||
|
/// hypothesis for issue #98 (cellar-up stuck at top step).
|
||||||
|
///
|
||||||
|
/// <para>
|
||||||
|
/// Initial state from <c>ACDREAM_PROBE_POLY_DUMP=1</c>.
|
||||||
|
/// Heavy output (one dump per AdjustSphereToPlane call); use briefly
|
||||||
|
/// to capture a specific scenario, then turn off.
|
||||||
|
/// </para>
|
||||||
|
/// </summary>
|
||||||
|
public static bool ProbePolyDumpEnabled { get; set; } =
|
||||||
|
Environment.GetEnvironmentVariable("ACDREAM_PROBE_POLY_DUMP") == "1";
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Emit one <c>[poly-dump]</c> line with the full polygon geometry:
|
||||||
|
/// cell id, polygon index, num vertices, sides flag, plane normal+D,
|
||||||
|
/// and all vertex coordinates. Used in conjunction with the push-back
|
||||||
|
/// probe to identify which dat polygon a push-back hit so we can
|
||||||
|
/// cross-reference against WorldBuilder's straight-from-dat read.
|
||||||
|
///
|
||||||
|
/// <para>Caller MUST guard with <c>if (!ProbePolyDumpEnabled) return;</c>.</para>
|
||||||
|
/// </summary>
|
||||||
|
public static void LogPolyDump(uint cellId, ResolvedPolygon poly)
|
||||||
|
{
|
||||||
|
var ci = System.Globalization.CultureInfo.InvariantCulture;
|
||||||
|
var sb = new System.Text.StringBuilder(256);
|
||||||
|
sb.AppendFormat(ci,
|
||||||
|
"[poly-dump] cell=0x{0:X8} polyId=0x{1:X4} numPts={2} sides={3} " +
|
||||||
|
"n=({4:F6},{5:F6},{6:F6}) d={7:F6} verts=[",
|
||||||
|
cellId, poly.Id, poly.NumPoints, poly.SidesType,
|
||||||
|
poly.Plane.Normal.X, poly.Plane.Normal.Y, poly.Plane.Normal.Z, poly.Plane.D);
|
||||||
|
for (int i = 0; i < poly.Vertices.Length; i++)
|
||||||
|
{
|
||||||
|
if (i > 0) sb.Append(',');
|
||||||
|
sb.AppendFormat(ci, "({0:F6},{1:F6},{2:F6})",
|
||||||
|
poly.Vertices[i].X, poly.Vertices[i].Y, poly.Vertices[i].Z);
|
||||||
|
}
|
||||||
|
sb.Append(']');
|
||||||
|
Console.WriteLine(sb.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A6.P1 emission helper for the <c>AdjustSphereToPlane</c> site.
|
/// A6.P1 emission helper for the <c>AdjustSphereToPlane</c> site.
|
||||||
/// One line per call: input sphere center, plane geometry, push-back
|
/// One line per call: input sphere center, plane geometry, push-back
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue