public static ClosestPoints ( ISupportMappable support1, ISupportMappable support2, Jitter.LinearMath.JMatrix &orientation1, Jitter.LinearMath.JMatrix &orientation2, Jitter.LinearMath.JVector &position1, Jitter.LinearMath.JVector &position2, Jitter.LinearMath.JVector &p1, Jitter.LinearMath.JVector &p2, Jitter.LinearMath.JVector &normal ) : bool | ||
support1 | ISupportMappable | |
support2 | ISupportMappable | |
orientation1 | Jitter.LinearMath.JMatrix | |
orientation2 | Jitter.LinearMath.JMatrix | |
position1 | Jitter.LinearMath.JVector | |
position2 | Jitter.LinearMath.JVector | |
p1 | Jitter.LinearMath.JVector | |
p2 | Jitter.LinearMath.JVector | |
normal | Jitter.LinearMath.JVector | |
return | bool |
private void DetectRigidRigid(RigidBody body1, RigidBody body2) { bool b1IsMulti = (body1.Shape is Multishape); bool b2IsMulti = (body2.Shape is Multishape); bool speculative = speculativeContacts || (body1.EnableSpeculativeContacts || body2.EnableSpeculativeContacts); JVector point, normal; float penetration; if (!b1IsMulti && !b2IsMulti) { if (XenoCollide.Detect(body1.Shape, body2.Shape, ref body1.orientation, ref body2.orientation, ref body1.position, ref body2.position, out point, out normal, out penetration)) { JVector point1, point2; FindSupportPoints(body1, body2, body1.Shape, body2.Shape, ref point, ref normal, out point1, out point2); RaiseCollisionDetected(body1, body2, ref point1, ref point2, ref normal, penetration); } else if (speculative) { JVector hit1, hit2; if (GJKCollide.ClosestPoints(body1.Shape, body2.Shape, ref body1.orientation, ref body2.orientation, ref body1.position, ref body2.position, out hit1, out hit2, out normal)) { JVector delta = hit2 - hit1; if (delta.LengthSquared() < (body1.sweptDirection - body2.sweptDirection).LengthSquared()) { penetration = delta * normal; if (penetration < 0.0f) { RaiseCollisionDetected(body1, body2, ref hit1, ref hit2, ref normal, penetration); } } } } } else if (b1IsMulti && b2IsMulti) { Multishape ms1 = (body1.Shape as Multishape); Multishape ms2 = (body2.Shape as Multishape); ms1 = ms1.RequestWorkingClone(); ms2 = ms2.RequestWorkingClone(); JBBox transformedBoundingBox = body2.boundingBox; transformedBoundingBox.InverseTransform(ref body1.position, ref body1.orientation); int ms1Length = ms1.Prepare(ref transformedBoundingBox); transformedBoundingBox = body1.boundingBox; transformedBoundingBox.InverseTransform(ref body2.position, ref body2.orientation); int ms2Length = ms2.Prepare(ref transformedBoundingBox); if (ms1Length == 0 || ms2Length == 0) { ms1.ReturnWorkingClone(); ms2.ReturnWorkingClone(); return; } for (int i = 0; i < ms1Length; i++) { ms1.SetCurrentShape(i); for (int e = 0; e < ms2Length; e++) { ms2.SetCurrentShape(e); if (XenoCollide.Detect(ms1, ms2, ref body1.orientation, ref body2.orientation, ref body1.position, ref body2.position, out point, out normal, out penetration)) { JVector point1, point2; FindSupportPoints(body1, body2, ms1, ms2, ref point, ref normal, out point1, out point2); RaiseCollisionDetected(body1, body2, ref point1, ref point2, ref normal, penetration); } else if (speculative) { JVector hit1, hit2; if (GJKCollide.ClosestPoints(ms1, ms2, ref body1.orientation, ref body2.orientation, ref body1.position, ref body2.position, out hit1, out hit2, out normal)) { JVector delta = hit2 - hit1; if (delta.LengthSquared() < (body1.sweptDirection - body2.sweptDirection).LengthSquared()) { penetration = delta * normal; if (penetration < 0.0f) { RaiseCollisionDetected(body1, body2, ref hit1, ref hit2, ref normal, penetration); } } } } } } ms1.ReturnWorkingClone(); ms2.ReturnWorkingClone(); } else { RigidBody b1, b2; if (body2.Shape is Multishape) { b1 = body2; b2 = body1; } else { b2 = body2; b1 = body1; } Multishape ms = (b1.Shape as Multishape); ms = ms.RequestWorkingClone(); JBBox transformedBoundingBox = b2.boundingBox; transformedBoundingBox.InverseTransform(ref b1.position, ref b1.orientation); int msLength = ms.Prepare(ref transformedBoundingBox); if (msLength == 0) { ms.ReturnWorkingClone(); return; } for (int i = 0; i < msLength; i++) { ms.SetCurrentShape(i); if (XenoCollide.Detect(ms, b2.Shape, ref b1.orientation, ref b2.orientation, ref b1.position, ref b2.position, out point, out normal, out penetration)) { JVector point1, point2; FindSupportPoints(b1, b2, ms, b2.Shape, ref point, ref normal, out point1, out point2); if (useTerrainNormal && ms is TerrainShape) { (ms as TerrainShape).CollisionNormal(out normal); JVector.Transform(ref normal, ref b1.orientation, out normal); } else if (useTriangleMeshNormal && ms is TriangleMeshShape) { (ms as TriangleMeshShape).CollisionNormal(out normal); JVector.Transform(ref normal, ref b1.orientation, out normal); } RaiseCollisionDetected(b1, b2, ref point1, ref point2, ref normal, penetration); } else if (speculative) { JVector hit1, hit2; if (GJKCollide.ClosestPoints(ms, b2.Shape, ref b1.orientation, ref b2.orientation, ref b1.position, ref b2.position, out hit1, out hit2, out normal)) { JVector delta = hit2 - hit1; if (delta.LengthSquared() < (body1.sweptDirection - body2.sweptDirection).LengthSquared()) { penetration = delta * normal; if (penetration < 0.0f) { RaiseCollisionDetected(b1, b2, ref hit1, ref hit2, ref normal, penetration); } } } } } ms.ReturnWorkingClone(); } }
private void DetectRigidRigid(RigidBody body1, RigidBody body2) { // CUSTOM: Added custom detection callbacks (primarily to accommodate actor movement on surfaces). var callback1 = body1.ShouldGenerateContact; var callback2 = body2.ShouldGenerateContact; bool b1IsMulti = (body1.Shape is Multishape); bool b2IsMulti = (body2.Shape is Multishape); bool speculative = speculativeContacts || (body1.AreSpeculativeContactsEnabled || body2.AreSpeculativeContactsEnabled); JVector point, normal; float penetration; if (!b1IsMulti && !b2IsMulti) { // CUSTOM: Added these callbacks (two rigid bodies). if ((callback1 != null && !callback1(body2, null)) || (callback2 != null && !callback2(body1, null))) { return; } if (XenoCollide.Detect(body1.Shape, body2.Shape, ref body1.orientation, ref body2.orientation, ref body1.position, ref body2.position, out point, out normal, out penetration)) { JVector point1, point2; FindSupportPoints(body1, body2, body1.Shape, body2.Shape, ref point, ref normal, out point1, out point2); RaiseCollisionDetected(body1, body2, ref point1, ref point2, ref normal, penetration); } else if (speculative) { JVector hit1, hit2; if (GJKCollide.ClosestPoints(body1.Shape, body2.Shape, ref body1.orientation, ref body2.orientation, ref body1.position, ref body2.position, out hit1, out hit2, out normal)) { JVector delta = hit2 - hit1; if (delta.LengthSquared() < (body1.sweptDirection - body2.sweptDirection).LengthSquared()) { penetration = delta * normal; if (penetration < 0.0f) { RaiseCollisionDetected(body1, body2, ref hit1, ref hit2, ref normal, penetration); } } } } } else if (b1IsMulti && b2IsMulti) { Multishape ms1 = (body1.Shape as Multishape); Multishape ms2 = (body2.Shape as Multishape); ms1 = ms1.RequestWorkingClone(); ms2 = ms2.RequestWorkingClone(); JBBox transformedBoundingBox = body2.boundingBox; transformedBoundingBox.InverseTransform(ref body1.position, ref body1.orientation); int ms1Length = ms1.Prepare(ref transformedBoundingBox); transformedBoundingBox = body1.boundingBox; transformedBoundingBox.InverseTransform(ref body2.position, ref body2.orientation); int ms2Length = ms2.Prepare(ref transformedBoundingBox); if (ms1Length == 0 || ms2Length == 0) { ms1.ReturnWorkingClone(); ms2.ReturnWorkingClone(); return; } for (int i = 0; i < ms1Length; i++) { ms1.SetCurrentShape(i); for (int e = 0; e < ms2Length; e++) { ms2.SetCurrentShape(e); if (XenoCollide.Detect(ms1, ms2, ref body1.orientation, ref body2.orientation, ref body1.position, ref body2.position, out point, out normal, out penetration)) { JVector point1, point2; FindSupportPoints(body1, body2, ms1, ms2, ref point, ref normal, out point1, out point2); RaiseCollisionDetected(body1, body2, ref point1, ref point2, ref normal, penetration); } else if (speculative) { JVector hit1, hit2; if (GJKCollide.ClosestPoints(ms1, ms2, ref body1.orientation, ref body2.orientation, ref body1.position, ref body2.position, out hit1, out hit2, out normal)) { JVector delta = hit2 - hit1; if (delta.LengthSquared() < (body1.sweptDirection - body2.sweptDirection).LengthSquared()) { penetration = delta * normal; if (penetration < 0.0f) { RaiseCollisionDetected(body1, body2, ref hit1, ref hit2, ref normal, penetration); } } } } } } ms1.ReturnWorkingClone(); ms2.ReturnWorkingClone(); } else { RigidBody b1, b2; if (body2.Shape is Multishape) { // CUSTOM: Swapped callbacks here as well. b1 = body2; b2 = body1; // A proper swap here (using a temporary variable) isn't necessary since, by this point, the other // callback (attached to the static body) is intentionally not used. callback2 = callback1; } else { b2 = body2; b1 = body1; } Multishape ms = (b1.Shape as Multishape); ms = ms.RequestWorkingClone(); JBBox transformedBoundingBox = b2.boundingBox; transformedBoundingBox.InverseTransform(ref b1.position, ref b1.orientation); int msLength = ms.Prepare(ref transformedBoundingBox); if (msLength == 0) { ms.ReturnWorkingClone(); return; } for (int i = 0; i < msLength; i++) { ms.SetCurrentShape(i); // CUSTOM: Added this callback (to allow specific triangle collisions to be ignored). bool shouldCollideWith = ms is TriangleMeshShape tMesh && (callback2 == null || callback2(b1, tMesh.CurrentTriangle)); if (shouldCollideWith && XenoCollide.Detect(ms, b2.Shape, ref b1.orientation, ref b2.orientation, ref b1.position, ref b2.position, out point, out normal, out penetration)) { JVector[] triangle = null; FindSupportPoints(b1, b2, ms, b2.Shape, ref point, ref normal, out var point1, out var point2); if (useTerrainNormal && ms is TerrainShape) { (ms as TerrainShape).CollisionNormal(out normal); JVector.Transform(ref normal, ref b1.orientation, out normal); } else if (useTriangleMeshNormal) { tMesh = ms as TriangleMeshShape; triangle = tMesh.CurrentTriangle; tMesh.CollisionNormal(out normal); JVector.Transform(ref normal, ref b1.orientation, out normal); } RaiseCollisionDetected(b1, b2, ref point1, ref point2, ref normal, triangle, penetration); } else if (speculative) { JVector hit1, hit2; if (GJKCollide.ClosestPoints(ms, b2.Shape, ref b1.orientation, ref b2.orientation, ref b1.position, ref b2.position, out hit1, out hit2, out normal)) { JVector delta = hit2 - hit1; if (delta.LengthSquared() < (body1.sweptDirection - body2.sweptDirection).LengthSquared()) { penetration = delta * normal; if (penetration < 0.0f) { RaiseCollisionDetected(b1, b2, ref hit1, ref hit2, ref normal, penetration); } } } } } ms.ReturnWorkingClone(); } }