I am at the moment making an attempt to construct a tender physique physics engine for enjoyable and I am struggling on the collision detection half. To date it is virtually there however I feel there are a couple of edge instances that I should be lacking as a result of typically the our bodies find yourself intersecting. I am fairly positive it is my CCD implementation and since I’ve by no means achieved CCD earlier than and I am not a computational physicist idk, find out how to repair it.
Here’s what I’ve up to now for my CCD Perform
public static bool CCD(Vector2 P0, Vector2 vP, Vector2 A0, Vector2 vA, Vector2 B0, Vector2 vB,
float dt, out float t, out float u, out Vector2 regular, out float normalSpeed)
{
t = float.PositiveInfinity;
u = float.PositiveInfinity;
regular = default;
normalSpeed = default;
var vAP = vA - vP;
var vBP = vB - vP;
var vE = vBP - vAP;
var E0 = B0 - A0;
var D0 = P0 - A0;
if (vE.LengthSquared() < Epsilon)
{
Vector2 n = new Vector2(-E0.Y, E0.X);
if (n.LengthSquared() < Epsilon) n = -vP;
if (n.LengthSquared() < Epsilon) return false;
n.Normalize();
float d0 = Vector2.Dot(P0 - A0, n);
float vd = Vector2.Dot(vP - vA, n);
if (MathF.Abs(vd) < Epsilon)
{
if (MathF.Abs(d0) < Epsilon)
{
t = 0;
}
else
{
return false;
}
}
else
}
else
{
float a = -Geometry.Cross(vAP, vE);
float b = Geometry.Cross(D0, vE) - Geometry.Cross(vAP, E0);
float c = Geometry.Cross(D0, E0);
if (Math.Abs(a) < Epsilon && Math.Abs(b) < Epsilon && Math.Abs(c) < Epsilon)
{
t = 0;
}
else if (SolveQuadratic(a, b, c, out float t1, out float t2))
{
var aT1 = A0 + (vA * t1);
var bT1 = B0 + (vB * t1);
var pT1 = P0 + (vP * t1);
var edgeL1 = (aT1 - bT1).Size();
var dist1 = (aT1 - pT1).Size();
if (edgeL1 < 1e-2f && dist1 > 1e-3f) t1 = -1;
var aT2 = A0 + (vA * t2);
var bT2 = B0 + (vB * t2);
var pT2 = P0 + (vP * t2);
var edgeL2 = (aT2 - bT2).Size();
var dist2 = (aT2 - pT2).Size();
if (edgeL2 < 1e-2f && dist2 > 1e-3f) t2 = -1;
if (!GetQuadraticSolution(t1, t2, 0f, dt, out t)) return false;
}
else return false;
}
Vector2 P = P0 + (vP * t);
Vector2 A = A0 + (vA * t);
Vector2 B = B0 + (vB * t);
Vector2 E = B - A;
u = E.LengthSquared() == 0 ? 0f : Vector2.Dot(P - A, E) / Vector2.Dot(E, E);
if (u >= 0 && u <= 1)
{
float uc = Math.Clamp(u, 0f, 1f);
Vector2 vEdge = vA + (uc * (vB - vA));
Vector2 vRel = vP - vEdge;
if (u <= 0.0f || u >= 1.0f)
{
Vector2 endpoint = (u <= 0.5f) ? A : B;
regular = P - endpoint;
if (regular.LengthSquared() > Epsilon)
{
regular.Normalize();
}
else
{
if (vRel.LengthSquared() > Epsilon)
regular = Vector2.Normalize(-vRel);
else
regular = Vector2.UnitY; // steady fallback
}
normalSpeed = Vector2.Dot(regular, vRel);
}
else
{
regular = new(-E.Y, E.X);
regular.Normalize();
normalSpeed = Vector2.Dot(regular, vRel);
if (normalSpeed > 0)
{
regular = -normal;
normalSpeed *= -1;
}
}
return normalSpeed < 0;
}
return false;
}
And the capabilities it makes use of:
public static bool SolveQuadratic(float a, float b, float c, out float t1, out float t2)
{
t1 = default;
t2 = default;
float eps = 1e-6f * (MathF.Abs(a) + MathF.Abs(b) + MathF.Abs(c));
if (MathF.Abs(a) < eps)
{
if (MathF.Abs(b) < eps) return false;
float t0 = -c / b;
t1 = t0;
t2 = t0;
return true;
}
float disc = (b * b) - (4f * a * c);
if (disc < 0f) return false;
float sqrtDisc = MathF.Sqrt(disc);
float inv = 1f / (2f * a);
t1 = (-b - sqrtDisc) * inv;
t2 = (-b + sqrtDisc) * inv;
return true;
}
public static bool GetQuadraticSolution(float t1, float t2, float lowerBound, float upperBound, out float t, bool preferBiggest = false)
{
t = default;
if (preferBiggest) (t1, t2) = (t2, t1);
if (t1 >= lowerBound && t1 <= upperBound)
{
t = Math.Clamp(t1, lowerBound, upperBound);
}
else if (t2 >= lowerBound && t2 <= upperBound)
{
t = Math.Clamp(t2, lowerBound, upperBound);
}
else
{
return false;
}
return true;
}
The principle concept is that it makes use of the place and velocity information of a degree and a section to search out the earliest time the purpose is on the section and from that calculates a traditional and a normalised place alongside the section "u". That is then fed again to another physics code to generate a response. I clearly nonetheless lacking some edge instances, however I have been engaged on this for ages and might’t get it to work correctly. Does anybody have any recommendation or see any points.


