public static int SphereAndTruePlane(CollisionSphere sphere, CollisionPlane plane, ref CollisionData data) { if (data.ContactsLeft <= 0) return 0; Vector3 position = sphere.GetAxis(3); float centreDistance = Vector3.Dot(plane.Normal, position) - plane.D; if (centreDistance * centreDistance > sphere.Radius * sphere.Radius) { return 0; } Vector3 normal = plane.Normal; float penetration = -centreDistance; if (centreDistance < 0) { normal *= -1; penetration = -penetration; } penetration += sphere.Radius; Contact contact = new Contact(); contact.ContactNormal = normal; contact.Penetration = penetration; contact.ContactPoint = position - plane.Normal * centreDistance; contact.SetData(sphere.Body, null, data.Friction, data.Restitution); data.Contacts.Add(contact); data.AddContacts(1); return 1; }
public static int SphereAndHalfSpace(CollisionSphere sphere, CollisionPlane plane, ref CollisionData data) { if (data.ContactsLeft <= 0) return 0; Vector3 position = sphere.GetAxis(3); float ballDistance = Vector3.Dot(plane.Normal, position) - sphere.Radius - plane.D; if (ballDistance >= 0) return 0; Contact contact = new Contact(); contact.ContactNormal = plane.Normal; contact.Penetration = -ballDistance; contact.ContactPoint = position - plane.Normal * (ballDistance + sphere.Radius); contact.SetData(sphere.Body, null, data.Friction, data.Restitution); data.Contacts.Add(contact); data.AddContacts(1); return 1; }
public static int SphereAndSphere(CollisionSphere one, CollisionSphere two, ref CollisionData data) { if (data.ContactsLeft <= 0) return 0; Vector3 positionOne = one.GetAxis(3); Vector3 positionTwo = two.GetAxis(3); Vector3 midline = positionOne - positionTwo; float size = midline.Magnitude; if (size <= 0.0f || size >= one.Radius + two.Radius) { return 0; } Vector3 normal = midline * ((1.0f) / size); Contact contact = new Contact(); contact.ContactNormal = normal; contact.ContactPoint = positionOne + midline * (float)0.5; contact.Penetration = (one.Radius + two.Radius - size); contact.SetData(one.Body, two.Body, data.Friction, data.Restitution); data.Contacts.Add(new Contact()); data.AddContacts(1); return 1; }
public static int BoxAndHalfSpace(CollisionBox box, CollisionPlane plane, ref CollisionData data) { if (data.ContactsLeft <= 0) return 0; if (!IntersectionTests.BoxAndHalfSpace(box, plane)) { return 0; } int contactsUsed = 0; for (int i = 0; i < 8; i++) { Vector3 vertexPos = new Vector3(mults[i, 0], mults[i, 1], mults[i, 2]); vertexPos *= (box.HalfSize); vertexPos = box.Transform.Transform(vertexPos); float vertexDistance = Vector3.Dot(vertexPos, plane.Normal); if (vertexDistance <= plane.D) { Contact contact = new Contact(); contact.ContactPoint = plane.Normal; contact.ContactPoint *= (vertexDistance - plane.D); contact.ContactPoint = vertexPos; contact.ContactNormal = plane.Normal; contact.Penetration = plane.D - vertexDistance; contact.SetData(box.Body, null, data.Friction, data.Restitution); data.Contacts.Add(contact); if (contactsUsed == data.ContactsLeft) return contactsUsed; } } data.AddContacts(contactsUsed); return contactsUsed; }
static void fillPointFaceBoxBox(CollisionBox one, CollisionBox two, Vector3 toCentre, CollisionData data, int best, float pen) { Contact contact = new Contact(); Vector3 normal = one.GetAxis(best); if (Vector3.Dot(one.GetAxis(best), toCentre) > 0) { normal = normal * -1.0f; } Vector3 vertex = two.HalfSize; if (Vector3.Dot(two.GetAxis(0), normal) < 0) vertex.X = -vertex.X; if (Vector3.Dot(two.GetAxis(1), normal) < 0) vertex.Y = -vertex.Y; if (Vector3.Dot(two.GetAxis(2), normal) < 0) vertex.Z = -vertex.Z; contact.ContactNormal = normal; contact.Penetration = pen; contact.ContactPoint = Vector3.Transform(vertex, two.Transform); contact.SetData(one.Body, two.Body, data.Friction, data.Restitution); data.Contacts.Add(contact); }
public static int BoxAndSphere(CollisionBox box, CollisionSphere sphere, ref CollisionData data) { Vector3 centre = sphere.GetAxis(3); Vector3 relCentre = box.Transform.TransformInverse(centre); if (MathHelper.Abs(relCentre.X) - sphere.Radius > box.HalfSize.X || MathHelper.Abs(relCentre.Y) - sphere.Radius > box.HalfSize.Y || MathHelper.Abs(relCentre.Z) - sphere.Radius > box.HalfSize.Z) { return 0; } Vector3 closestPt = new Vector3(); float dist; dist = relCentre.X; if (dist > box.HalfSize.X) dist = box.HalfSize.X; if (dist < -box.HalfSize.X) dist = -box.HalfSize.X; closestPt.X = dist; dist = relCentre.Y; if (dist > box.HalfSize.Y) dist = box.HalfSize.Y; if (dist < -box.HalfSize.Y) dist = -box.HalfSize.Y; closestPt.Y = dist; dist = relCentre.Z; if (dist > box.HalfSize.Z) dist = box.HalfSize.Z; if (dist < -box.HalfSize.Z) dist = -box.HalfSize.Z; closestPt.Z = dist; dist = (closestPt - relCentre).SquaredMagnitude; if (dist > sphere.Radius * sphere.Radius) return 0; Vector3 closestPtWorld = box.Transform.Transform(closestPt); Contact contact = new Contact(); contact.ContactNormal = (closestPtWorld - centre); contact.ContactNormal.Normalize(); contact.ContactPoint = closestPtWorld; contact.Penetration = sphere.Radius - MathHelper.Sqrt(dist); contact.SetData(box.Body, sphere.Body, data.Friction, data.Restitution); data.Contacts.Add(contact); data.AddContacts(1); return 1; }
public static int BoxAndPoint(CollisionBox box, Vector3 point, ref CollisionData data) { Vector3 relPt = box.Transform.TransformInverse(point); Vector3 normal = new Vector3(); float min_depth = box.HalfSize.X - MathHelper.Abs(relPt.X); if (min_depth < 0) return 0; normal = box.GetAxis(0) * ((relPt.X < 0) ? -1 : 1); float depth = box.HalfSize.Y - MathHelper.Abs(relPt.Y); if (depth < 0) return 0; else if (depth < min_depth) { min_depth = depth; normal = box.GetAxis(1) * ((relPt.Y < 0) ? -1 : 1); } depth = box.HalfSize.Z - MathHelper.Abs(relPt.Z); if (depth < 0) return 0; else if (depth < min_depth) { min_depth = depth; normal = box.GetAxis(2) * ((relPt.Z < 0) ? -1 : 1); } Contact contact = new Contact(); contact.ContactNormal = normal; contact.ContactPoint = point; contact.Penetration = min_depth; contact.SetData(box.Body, null, data.Friction, data.Restitution); data.Contacts.Add(contact); data.AddContacts(1); return 1; }
public static int BoxAndBox(CollisionBox one, CollisionBox two, ref CollisionData data) { Vector3 toCenter = two.GetAxis(3) - one.GetAxis(3); float pen = float.MaxValue; int best = 0xffffff; CHECK_OVERLAP(one.GetAxis(0), 0, one, two, toCenter, ref pen, ref best); CHECK_OVERLAP(one.GetAxis(1), 1, one, two, toCenter, ref pen, ref best); CHECK_OVERLAP(one.GetAxis(2), 2, one, two, toCenter, ref pen, ref best); CHECK_OVERLAP(one.GetAxis(0), 3, one, two, toCenter, ref pen, ref best); CHECK_OVERLAP(one.GetAxis(1), 4, one, two, toCenter, ref pen, ref best); CHECK_OVERLAP(one.GetAxis(2), 5, one, two, toCenter, ref pen, ref best); int bestSingleAxis = best; CHECK_OVERLAP(Vector3.Cross(one.GetAxis(0), two.GetAxis(0)), 6, one, two, toCenter, ref pen, ref best); CHECK_OVERLAP(Vector3.Cross(one.GetAxis(0), two.GetAxis(1)), 7, one, two, toCenter, ref pen, ref best); CHECK_OVERLAP(Vector3.Cross(one.GetAxis(0), two.GetAxis(2)), 8, one, two, toCenter, ref pen, ref best); CHECK_OVERLAP(Vector3.Cross(one.GetAxis(1), two.GetAxis(0)), 9, one, two, toCenter, ref pen, ref best); CHECK_OVERLAP(Vector3.Cross(one.GetAxis(1), two.GetAxis(1)), 10, one, two, toCenter, ref pen, ref best); CHECK_OVERLAP(Vector3.Cross(one.GetAxis(1), two.GetAxis(2)), 11, one, two, toCenter, ref pen, ref best); CHECK_OVERLAP(Vector3.Cross(one.GetAxis(2), two.GetAxis(0)), 12, one, two, toCenter, ref pen, ref best); CHECK_OVERLAP(Vector3.Cross(one.GetAxis(2), two.GetAxis(1)), 13, one, two, toCenter, ref pen, ref best); CHECK_OVERLAP(Vector3.Cross(one.GetAxis(2), two.GetAxis(2)), 14, one, two, toCenter, ref pen, ref best); if (best == 0xffffff) throw new Exception("same, same"); if (best < 3) { fillPointFaceBoxBox(one, two, toCenter, data, best, pen); data.AddContacts(1); } else if (best < 6) { fillPointFaceBoxBox(two, one, toCenter * -1.0f, data, best - 3, pen); data.AddContacts(1); return 1; } else { best -= 6; int oneAxisIndex = best / 3; int twoAxisIndex = best % 3; Vector3 oneAxis = one.GetAxis(oneAxisIndex); Vector3 twoAxis = two.GetAxis(twoAxisIndex); Vector3 axis = Vector3.Cross(oneAxis, twoAxis); axis.Normalize(); if (Vector3.Dot(axis, toCenter) > 0) axis = axis * -1.0f; Vector3 ptOnOneEdge = one.HalfSize; Vector3 ptOnTwoEdge = two.HalfSize; for (int i = 0; i < 3; i++) { if (i == oneAxisIndex) ptOnOneEdge[i] = 0; else if (Vector3.Dot(one.GetAxis(i), axis) > 0) ptOnOneEdge[i] = -ptOnOneEdge[i]; if (i == twoAxisIndex) ptOnTwoEdge[i] = 0; else if (Vector3.Dot(two.GetAxis(i), axis) < 0) ptOnTwoEdge[i] = -ptOnTwoEdge[i]; } ptOnOneEdge = Vector3.Transform(ptOnOneEdge, one.Transform); ptOnTwoEdge = Vector3.Transform(ptOnTwoEdge, two.Transform); Vector3 vertex = contactPoint( ptOnOneEdge, oneAxis, one.HalfSize[oneAxisIndex], ptOnTwoEdge, twoAxis, two.HalfSize[twoAxisIndex], bestSingleAxis > 2 ); Contact contact = new Contact(); contact.Penetration = pen; contact.ContactNormal = axis; contact.ContactPoint = vertex; contact.SetData(one.Body, two.Body, data.Friction, data.Restitution); data.Contacts.Add(contact); data.AddContacts(1); return 1; } return 0; }