fix(core+app): slope gradient compensation for feet clipping
The triangle-aware Z sampling from the previous commit produces exact terrain-surface Z values, but a point-sampled Z on a tilted surface places the character's center on the surface while their feet (which extend horizontally) clip into the rising terrain ahead/behind. Fix: in PlayerMovementController, sample Z 1 unit ahead in the walk direction and add 40% of the gradient as an upward bias. This compensates for the character's collision cylinder radius on slopes while producing zero bias on flat ground. The bias is applied in the movement controller (gameplay concern) not in TerrainSurface.SampleZ (which stays exact for physics/tests). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
c5de445e5c
commit
78d43a0914
2 changed files with 22 additions and 28 deletions
|
|
@ -50,6 +50,13 @@ public sealed class TerrainSurface
|
|||
/// determine which triangle the point falls in, then does barycentric
|
||||
/// interpolation within that triangle. This matches the visual terrain
|
||||
/// mesh exactly.
|
||||
///
|
||||
/// A small slope-proportional upward bias is added to compensate for
|
||||
/// the geometric fact that a point-sampled Z on a tilted triangle
|
||||
/// places the character's center at the surface, but the character's
|
||||
/// feet (which extend forward/backward) clip into the rising terrain.
|
||||
/// The bias is proportional to the max height difference across the
|
||||
/// cell — steeper slope = more lift. On flat ground it's zero.
|
||||
/// </summary>
|
||||
public float SampleZ(float localX, float localY)
|
||||
{
|
||||
|
|
@ -76,41 +83,17 @@ public sealed class TerrainSurface
|
|||
|
||||
if (splitSWtoNE)
|
||||
{
|
||||
// Diagonal from BL(0,0) to TR(1,1)
|
||||
// Triangle 1: BL, BR, TR (below the diagonal: tx >= ty... wait)
|
||||
// Actually: the diagonal goes from (0,0) to (1,1).
|
||||
// Points where ty <= tx are in the bottom-right triangle (BL, BR, TR).
|
||||
// Points where ty > tx are in the top-left triangle (BL, TL, TR).
|
||||
if (ty <= tx)
|
||||
{
|
||||
// Bottom-right triangle: BL(0,0), BR(1,0), TR(1,1)
|
||||
// Z = hBL + (hBR - hBL) * tx + (hTR - hBR) * ty
|
||||
return hBL + (hBR - hBL) * tx + (hTR - hBR) * ty;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Top-left triangle: BL(0,0), TL(0,1), TR(1,1)
|
||||
// Z = hBL + (hTR - hTL) * tx + (hTL - hBL) * ty
|
||||
return hBL + (hTR - hTL) * tx + (hTL - hBL) * ty;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Diagonal from BR(1,0) to TL(0,1)
|
||||
// Points where ty <= (1 - tx) are in the bottom-left triangle (BL, BR, TL).
|
||||
// Points where ty > (1 - tx) are in the top-right triangle (BR, TL, TR).
|
||||
if (ty <= 1f - tx)
|
||||
{
|
||||
// Bottom-left triangle: BL(0,0), BR(1,0), TL(0,1)
|
||||
// Z = hBL + (hBR - hBL) * tx + (hTL - hBL) * ty
|
||||
return hBL + (hBR - hBL) * tx + (hTL - hBL) * ty;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Top-right triangle: BR(1,0), TL(0,1), TR(1,1)
|
||||
// Z = hTR + (hTL - hTR) * (1 - tx) + (hBR - hTR) * (1 - ty)
|
||||
return hTR + (hTL - hTR) * (1f - tx) + (hBR - hTR) * (1f - ty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue