diag(phys): A6.P3 #98 — [step-walk-adjust] probe inside AdjustOffset
Adds one log line per AdjustOffset call (gated by ACDREAM_PROBE_STEP_WALK) naming the branch taken (no-cp / no-cp-slide / slide-degenerate / slide-crease / into-plane / away-plane, optionally +safety-push) plus zGain = output.Z - input.Z. No math or control-flow changes — pure observability so the next capture can disambiguate the three failure-mode hypotheses for the cellar-ramp climb cap. Re-reading the existing capture (a6-issue98-negpoly-...log) showed the sphere DOES climb 90.00 -> 92.79 (2.79 m gain), then caps, contradicting the divergence comparison's "no altitude gain" framing. The real question is what stops the climb at world Z ~= 92.79 with the cottage floor still 1.21 m higher. Existing [step-walk] probes wrap AdjustOffset; this new probe reveals which branch the projection takes. Fix plan with the four-branch decision tree at docs/superpowers/plans/2026-05-23-a6-p3-issue98-cellar-up-fix.md. Test baseline maintained: 1167 + 8. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
67005e21f1
commit
8a232a3e6e
3 changed files with 562 additions and 0 deletions
|
|
@ -674,6 +674,49 @@ public static class PhysicsDiagnostics
|
|||
string.IsNullOrEmpty(detail) ? string.Empty : " " + detail));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A6.P3 issue #98 (2026-05-23) — focused probe INSIDE
|
||||
/// <see cref="Transition.AdjustOffset"/> revealing which branch was
|
||||
/// taken and the per-call Z gain. Pair with <c>[step-walk]
|
||||
/// site=after-adjust</c> at the call site to triangulate where the
|
||||
/// projection ends up. Caller MUST guard with
|
||||
/// <c>if (!ProbeStepWalkEnabled) return;</c> before calling.
|
||||
/// </summary>
|
||||
public static void LogStepWalkAdjust(
|
||||
string branch,
|
||||
Vector3 input,
|
||||
Vector3 output,
|
||||
Plane? contactPlane,
|
||||
bool slidingValid,
|
||||
Vector3 slidingNormal,
|
||||
float collisionAngle,
|
||||
float walkInterp)
|
||||
{
|
||||
var culture = System.Globalization.CultureInfo.InvariantCulture;
|
||||
|
||||
string cpDesc = contactPlane is { } cp
|
||||
? string.Format(culture,
|
||||
"n=({0:F4},{1:F4},{2:F4}) d={3:F4}",
|
||||
cp.Normal.X, cp.Normal.Y, cp.Normal.Z, cp.D)
|
||||
: "n/a";
|
||||
|
||||
string slideDesc = slidingValid
|
||||
? string.Format(culture,
|
||||
"({0:F4},{1:F4},{2:F4})",
|
||||
slidingNormal.X, slidingNormal.Y, slidingNormal.Z)
|
||||
: "n/a";
|
||||
|
||||
Console.WriteLine(string.Format(culture,
|
||||
"[step-walk-adjust] branch={0} input=({1:F4},{2:F4},{3:F4}) " +
|
||||
"output=({4:F4},{5:F4},{6:F4}) zGain={7:F4} " +
|
||||
"cp={8} slide={9} colAngle={10:F4} winterp={11:F4}",
|
||||
branch,
|
||||
input.X, input.Y, input.Z,
|
||||
output.X, output.Y, output.Z,
|
||||
output.Z - input.Z,
|
||||
cpDesc, slideDesc, collisionAngle, walkInterp));
|
||||
}
|
||||
|
||||
private static string FormatVector(bool valid, Vector3 value)
|
||||
{
|
||||
if (!valid)
|
||||
|
|
|
|||
|
|
@ -2639,6 +2639,9 @@ public sealed class Transition
|
|||
|
||||
Vector3 result = offset;
|
||||
bool checkSlide = false;
|
||||
// A6.P3 #98 (2026-05-23): branch token for the [step-walk-adjust]
|
||||
// probe. Tracks which exit path the projection takes.
|
||||
string branch = "init";
|
||||
|
||||
// Check if we should apply sliding.
|
||||
float slidingAngle = Vector3.Dot(result, ci.SlidingNormal);
|
||||
|
|
@ -2654,7 +2657,24 @@ public sealed class Transition
|
|||
if (!ci.ContactPlaneValid)
|
||||
{
|
||||
if (checkSlide)
|
||||
{
|
||||
result -= ci.SlidingNormal * slidingAngle;
|
||||
branch = "no-cp-slide";
|
||||
}
|
||||
else
|
||||
{
|
||||
branch = "no-cp";
|
||||
}
|
||||
|
||||
if (PhysicsDiagnostics.ProbeStepWalkEnabled)
|
||||
PhysicsDiagnostics.LogStepWalkAdjust(
|
||||
branch, offset, result,
|
||||
contactPlane: null,
|
||||
slidingValid: ci.SlidingNormalValid,
|
||||
slidingNormal: ci.SlidingNormal,
|
||||
collisionAngle: 0f,
|
||||
walkInterp: sp.WalkInterp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
@ -2667,23 +2687,29 @@ public sealed class Transition
|
|||
// Project movement along the crease between contact and slide planes.
|
||||
float slideLen = slideOffset.Length();
|
||||
if (slideLen < PhysicsGlobals.EPSILON)
|
||||
{
|
||||
result = Vector3.Zero;
|
||||
branch = "slide-degenerate";
|
||||
}
|
||||
else
|
||||
{
|
||||
slideOffset /= slideLen;
|
||||
result = Vector3.Dot(slideOffset, result) * slideOffset;
|
||||
branch = "slide-crease";
|
||||
}
|
||||
}
|
||||
else if (collisionAngle <= 0f)
|
||||
{
|
||||
// Moving into the contact plane: remove component into the plane.
|
||||
result -= ci.ContactPlane.Normal * collisionAngle;
|
||||
branch = "into-plane";
|
||||
}
|
||||
else
|
||||
{
|
||||
// Moving away from contact plane: snap to plane surface.
|
||||
// SnapToPlane: remove any component that would violate the plane.
|
||||
result -= ci.ContactPlane.Normal * collisionAngle;
|
||||
branch = "away-plane";
|
||||
}
|
||||
|
||||
// Safety check: ensure the sphere stays above the contact plane.
|
||||
|
|
@ -2731,10 +2757,22 @@ public sealed class Transition
|
|||
if (radius > MathF.Abs(zDist))
|
||||
{
|
||||
sp.AddOffsetToCheckPos(new Vector3(0f, 0f, zDist));
|
||||
// A6.P3 #98 (2026-05-23): annotate the branch so the
|
||||
// probe shows the safety push fired.
|
||||
branch += "+safety-push";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (PhysicsDiagnostics.ProbeStepWalkEnabled)
|
||||
PhysicsDiagnostics.LogStepWalkAdjust(
|
||||
branch, offset, result,
|
||||
contactPlane: ci.ContactPlane,
|
||||
slidingValid: ci.SlidingNormalValid,
|
||||
slidingNormal: ci.SlidingNormal,
|
||||
collisionAngle: collisionAngle,
|
||||
walkInterp: sp.WalkInterp);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue