You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

268 lines
11 KiB
C#

3 weeks ago
using UnityEngine;
namespace Fusion.Addons.SimpleKCC
{
internal static class KCCPhysicsUtility
{
public static bool ProjectOnGround(Vector3 groundNormal, Vector3 vector, out Vector3 projectedVector)
{
float num = Vector3.Dot(Vector3.up, groundNormal);
float num2 = 0f - Vector3.Dot(vector, groundNormal);
if (!num.IsAlmostZero(0.001f))
{
projectedVector = new Vector3(vector.x, vector.y + num2 / num, vector.z);
return true;
}
projectedVector = default(Vector3);
return false;
}
public static void ProjectVerticalPenetration(ref Vector3 direction, ref float distance)
{
Vector3 vector = direction * distance;
Vector3 vector2 = vector.OnlyXZ();
float num = Vector3.Magnitude(vector2);
if (num >= 1E-06f)
{
float num2 = vector.y * vector.y / num;
direction = vector2 / num;
distance = num + num2;
}
}
public static void ProjectHorizontalPenetration(ref Vector3 direction, ref float distance)
{
Vector3 vector = direction * distance;
direction = Vector3.up;
distance = 0f;
if (!(vector.y > -1E-06f) || !(vector.y < 1E-06f))
{
distance = vector.y + (vector.x * vector.x + vector.z * vector.z) / vector.y;
if (distance < 0f)
{
direction = -direction;
distance = 0f - distance;
}
}
}
public static bool CheckGround(Collider collider, Vector3 position, Collider groundCollider, Vector3 groundPosition, Quaternion groundRotation, float radius, float height, float extent, float minGroundDot, out Vector3 groundNormal, out float groundDistance, out bool isWithinExtent)
{
isWithinExtent = false;
if (groundCollider is MeshCollider || groundCollider is TerrainCollider)
{
if (Physics.ComputePenetration(collider, position - new Vector3(0f, extent, 0f), Quaternion.identity, groundCollider, groundPosition, groundRotation, out var direction, out var distance))
{
isWithinExtent = true;
float num = Vector3.Dot(direction, Vector3.up);
if (num >= minGroundDot)
{
Vector3 direction2 = direction;
float distance2 = distance;
ProjectHorizontalPenetration(ref direction2, ref distance2);
float num2 = Mathf.Max(0f, extent - distance2);
groundNormal = direction;
groundDistance = num2 * num;
return true;
}
}
}
else
{
float num3 = radius + extent;
float num4 = num3 * num3;
Vector3 vector = position + new Vector3(0f, radius, 0f);
Vector3 vector2 = Physics.ClosestPoint(vector, groundCollider, groundPosition, groundRotation) - vector;
if (vector2.OnlyXZ().sqrMagnitude <= num4)
{
if (vector2.y < 0f)
{
float num5 = Vector3.Magnitude(vector2);
if (num5 <= num3)
{
isWithinExtent = true;
Vector3 vector3 = -(vector2 / num5);
if (Vector3.Dot(vector3, Vector3.up) >= minGroundDot)
{
groundNormal = vector3;
groundDistance = Mathf.Max(0f, num5 - radius);
return true;
}
}
}
else if (vector2.y < height - radius * 2f)
{
isWithinExtent = true;
}
}
}
groundNormal = Vector3.up;
groundDistance = 0f;
return false;
}
public static Vector3 GetAcceleration(Vector3 velocity, Vector3 direction, Vector3 axis, float maxSpeed, bool clampSpeed, float inputAcceleration, float constantAcceleration, float relativeAcceleration, float proportionalAcceleration, float deltaTime)
{
if (inputAcceleration <= 0f)
{
return Vector3.zero;
}
if (constantAcceleration <= 0f && relativeAcceleration <= 0f && proportionalAcceleration <= 0f)
{
return Vector3.zero;
}
if (direction.IsZero())
{
return Vector3.zero;
}
float magnitude = new Vector3(velocity.x * axis.x, velocity.y * axis.y, velocity.z * axis.z).magnitude;
Vector3 normalized = new Vector3(direction.x * axis.x, direction.y * axis.y, direction.z * axis.z).normalized;
float num = Mathf.Max(0f, maxSpeed - magnitude);
if (constantAcceleration < 0f)
{
constantAcceleration = 0f;
}
if (relativeAcceleration < 0f)
{
relativeAcceleration = 0f;
}
if (proportionalAcceleration < 0f)
{
proportionalAcceleration = 0f;
}
constantAcceleration *= inputAcceleration;
relativeAcceleration *= inputAcceleration;
proportionalAcceleration *= inputAcceleration;
float num2 = (constantAcceleration + maxSpeed * relativeAcceleration + num * proportionalAcceleration) * deltaTime;
if (num2 <= 0f)
{
return Vector3.zero;
}
if (clampSpeed && num2 > num)
{
num2 = num;
}
return normalized.normalized * num2;
}
public static Vector3 GetAcceleration(Vector3 velocity, Vector3 direction, Vector3 axis, Vector3 normal, float targetSpeed, bool clampSpeed, float inputAcceleration, float constantAcceleration, float relativeAcceleration, float proportionalAcceleration, float deltaTime)
{
float num = 1f - Mathf.Clamp01(Vector3.Dot(direction.normalized, normal));
constantAcceleration *= num;
relativeAcceleration *= num;
proportionalAcceleration *= num;
return GetAcceleration(velocity, direction, axis, targetSpeed, clampSpeed, inputAcceleration, constantAcceleration, relativeAcceleration, proportionalAcceleration, deltaTime);
}
public static Vector3 GetFriction(Vector3 velocity, Vector3 direction, Vector3 axis, float maxSpeed, bool clampSpeed, float constantFriction, float relativeFriction, float proportionalFriction, float deltaTime)
{
if (constantFriction <= 0f && relativeFriction <= 0f && proportionalFriction <= 0f)
{
return Vector3.zero;
}
if (direction.IsZero())
{
return Vector3.zero;
}
float magnitude = new Vector3(velocity.x * axis.x, velocity.y * axis.y, velocity.z * axis.z).magnitude;
Vector3 normalized = new Vector3(direction.x * axis.x, direction.y * axis.y, direction.z * axis.z).normalized;
if (constantFriction < 0f)
{
constantFriction = 0f;
}
if (relativeFriction < 0f)
{
relativeFriction = 0f;
}
if (proportionalFriction < 0f)
{
proportionalFriction = 0f;
}
float num = (constantFriction + maxSpeed * relativeFriction + magnitude * proportionalFriction) * deltaTime;
if (num <= 0f)
{
return Vector3.zero;
}
if (clampSpeed && num > magnitude)
{
num = magnitude;
}
return -normalized * num;
}
public static Vector3 GetFriction(Vector3 velocity, Vector3 direction, Vector3 axis, Vector3 normal, float maxSpeed, bool clampSpeed, float constantFriction, float relativeFriction, float proportionalFriction, float deltaTime)
{
float num = 1f - Mathf.Clamp01(Vector3.Dot(direction.normalized, normal));
constantFriction *= num;
relativeFriction *= num;
proportionalFriction *= num;
return GetFriction(velocity, direction, axis, maxSpeed, clampSpeed, constantFriction, relativeFriction, proportionalFriction, deltaTime);
}
public static Vector3 CombineAccelerationAndFriction(Vector3 velocity, Vector3 acceleration, Vector3 friction)
{
velocity.x = CombineAxis(velocity.x, acceleration.x, friction.x);
velocity.y = CombineAxis(velocity.y, acceleration.y, friction.y);
velocity.z = CombineAxis(velocity.z, acceleration.z, friction.z);
return velocity;
static float CombineAxis(float axisVelocity, float axisAcceleration, float axisFriction)
{
float num = axisAcceleration + axisFriction;
if (Mathf.Abs(axisAcceleration) >= Mathf.Abs(axisFriction))
{
axisVelocity += num;
}
else if ((double)axisVelocity > 0.0)
{
axisVelocity = Mathf.Max(0f, axisVelocity + num);
}
else if ((double)axisVelocity < 0.0)
{
axisVelocity = Mathf.Min(axisVelocity + num, 0f);
}
return axisVelocity;
}
}
public static Vector3 AccumulatePenetrationCorrection(Vector3 accumulatedCorrection, Vector3 contactCorrectionDirection, float contactCorrectionMagnitude)
{
float num = Vector3.Magnitude(accumulatedCorrection);
Vector3 vector = ((num > 1E-10f) ? (accumulatedCorrection / num) : Vector3.zero);
float num2 = 0f;
Vector3 vector2 = Vector3.Cross(Vector3.Cross(vector, contactCorrectionDirection), vector).normalized;
float num3 = Vector3.Dot(contactCorrectionDirection, vector);
float num4 = 1f - num3 * num3;
if (num4 > 0.001f)
{
num2 = (contactCorrectionMagnitude - num * num3) / Mathf.Sqrt(num4);
}
else if (contactCorrectionMagnitude > num)
{
num2 = contactCorrectionMagnitude - num;
vector2 = vector;
}
accumulatedCorrection += vector2 * num2;
return accumulatedCorrection;
}
}
}