fix(physics): enforce retail step-down support radius (#273)

This commit is contained in:
Erik 2026-07-31 12:10:03 +02:00
parent 4dd40ad8fe
commit c24bc571cf
9 changed files with 2117 additions and 24 deletions

View file

@ -284,28 +284,46 @@ public static class BSPQuery
CollisionSphere sphere,
Vector3 up,
bool small)
=> CheckWalkableSupport(
poly.Plane,
poly.Vertices,
sphere.Center,
small ? sphere.Radius * 0.5f : sphere.Radius,
up);
/// <summary>
/// Retail <c>CPolygon::check_walkable</c> against an already resolved
/// polygon. The caller supplies the effective support radius; retail's
/// <c>SPHEREPATH::check_walkables</c> halves its saved sphere before
/// entering this routine.
/// </summary>
internal static bool CheckWalkableSupport(
Plane plane,
ReadOnlySpan<Vector3> vertices,
Vector3 center,
float supportRadius,
Vector3 up)
{
float angleUp = Vector3.Dot(poly.Plane.Normal, up);
float angleUp = Vector3.Dot(plane.Normal, up);
if (angleUp < PhysicsGlobals.EPSILON) return false;
float angle = (Vector3.Dot(poly.Plane.Normal, sphere.Center) + poly.Plane.D) / angleUp;
var center = sphere.Center - up * angle;
float angle = (Vector3.Dot(plane.Normal, center) + plane.D) / angleUp;
center -= up * angle;
float radsum = sphere.Radius * sphere.Radius;
if (small) radsum *= 0.25f;
float radsum = supportRadius * supportRadius;
int n = poly.Vertices.Length;
int n = vertices.Length;
int prevIdx = n - 1;
for (int i = 0; i < n; i++)
{
var v = poly.Vertices[i];
var lv = poly.Vertices[prevIdx];
var v = vertices[i];
var lv = vertices[prevIdx];
prevIdx = i;
var edge = v - lv;
var disp = center - lv;
var cross = Vector3.Cross(poly.Plane.Normal, edge);
var cross = Vector3.Cross(plane.Normal, edge);
float diff = Vector3.Dot(disp, cross);
if (diff < 0f)