public void IntersectionTests_BoxVsBox_Faces() { NoBody topBody = new NoBody(Matrix.CreateTranslation(new Vector3(1.5f, 2.0f, 0.25f))); Box top = new Box( topBody, Matrix.Identity, new Vector3(1f, 1f, 1f)); NoBody bottomBody = new NoBody(Matrix.CreateTranslation(new Vector3(0f, 0f, 0f))); Box bottom = new Box( bottomBody, Matrix.Identity, new Vector3(1f, 1f, 1f)); CollisionData data = new CollisionData(); int contactsFound = IntersectionTests.boxAndBox(top, bottom, data); Assert.AreEqual(1, contactsFound); Contact contact = data.contacts[0]; Assert.AreEqual(new Vector3(1f, 1f, 1f), contact.Point); Assert.AreEqual(Vector3.Up, contact.Normal); Assert.AreEqual(0f, contact.Penetration); }
public void IntersectionTests_BoxVsBox_NotTouching() { Vector3 leftPos = new Vector3(-100f, -100f, -100f); IRigidBody leftBody = new NoBody(Matrix.CreateTranslation(leftPos)); Box left = new Box(leftBody, Matrix.Identity, new Vector3(1f, 1f, 1f)); Vector3 rightPos = new Vector3(100f, 100f, 100f); IRigidBody rightBody = new NoBody(Matrix.CreateTranslation(rightPos)); Box right = new Box(rightBody, Matrix.Identity, new Vector3(1f, 1f, 1f)); CollisionData data = new CollisionData(); int contactsFound = IntersectionTests.boxAndBox(left, right, data); Assert.AreEqual(0, contactsFound); Assert.AreEqual(0, data.contacts.Count); }
public void Contact_XAxis() { NoBody bodyZero = new NoBody(Vector3.Right); bodyZero.Velocity = Vector3.Left; bodyZero.Mass = 1f; bodyZero.calculateDerivedData(); NoBody bodyOne = new NoBody(Vector3.Left * .9f); bodyOne.Velocity = Vector3.Right; bodyOne.Mass = 1f; bodyOne.calculateDerivedData(); Contact contact = new Contact(); contact.Bodies[0] = bodyZero; contact.Bodies[1] = bodyOne; contact.Point = Vector3.Zero; contact.Penetration = 0.1f; contact.Restitution = 1f; contact.Friction = 0f; contact.Normal = Vector3.Right; contact.ReCalc(1f); Assert.AreEqual(Vector3.Left, contact.CalcLocalVelocity(0, 1f)); Assert.AreEqual(Vector3.Right, contact.CalcLocalVelocity(1, 1f)); Assert.AreEqual(Vector3.Left, contact.RelativeContactPositions[0]); Assert.AreEqual(Vector3.Right * 0.9f, contact.RelativeContactPositions[1]); Assert.AreEqual(new Vector3(-2f, 0f, 0f), contact.ContactVelocity); // Position Change Vector3[] linearChange = new Vector3[2]; Vector3[] angularChange = new Vector3[2]; contact.ApplyPositionChange( ref linearChange, ref angularChange, contact.Penetration); Assert.AreEqual(Vector3.Zero, angularChange[0], "Zero angular change for object 0"); Assert.AreEqual(Vector3.Zero, angularChange[1], "Zero angular change for object 1"); Assert.AreEqual(new Vector3(0.05f, 0f, 0f), linearChange[0], "Body 0 is pushed right by half penetration"); Assert.AreEqual(new Vector3(-0.05f, 0f, 0f), linearChange[1], "Body 1 is pushed left by half penetration"); //Velocity Change Vector3[] velocityChange = new Vector3[2]; Vector3[] rotationChange = new Vector3[2]; contact.ApplyVelocityChange(ref velocityChange, ref rotationChange); Assert.AreEqual( Vector3.Zero, rotationChange[0], "Zero rotation change for object 0"); Assert.AreEqual( Vector3.Zero, rotationChange[1], "Zero rotation change for object 1"); Assert.AreEqual( Vector3.Right * 2f, velocityChange[0], "Counter velocity applied to body 0"); Assert.AreEqual( Vector3.Left * 2f, velocityChange[1], "Counter velocity applied to body 1"); Assert.AreEqual( Vector3.Right, bodyZero.Velocity); Assert.AreEqual(Vector3.Zero, bodyZero.Rotation); Assert.AreEqual( Vector3.Left, bodyOne.Velocity); Assert.AreEqual(Vector3.Zero, bodyOne.Rotation); }
public void Contact_BoxSpinningOnYAxisFallsOnToXZPlane() { // X-Z plane NoBody planeBody = new NoBody(Vector3.Zero); planeBody.InverseMass = 0f; //infinite mass Forever.Physics.Collide.Plane plane = new Forever.Physics.Collide.Plane(planeBody, Vector3.Zero, Vector3.Up); planeBody.calculateDerivedData(); // Spinning box colliding with the plane NoBody boxBody = new NoBody(Vector3.Up * 0.95f); boxBody.Mass = 1f; boxBody.Rotation = new Vector3(0f, 0.01f, 0f); boxBody.Velocity = new Vector3(0f, -1f, 0f); boxBody.calculateDerivedData(); Box box = new Box(boxBody, Matrix.Identity, new Vector3(1f, 1f, 1f)); Contact contact = new Contact(); contact.Bodies[0] = planeBody; contact.Bodies[1] = boxBody; contact.Point = Vector3.Zero; contact.Penetration = 0.05f; contact.Restitution = 1f; contact.Friction = 0f; contact.Normal = Vector3.Up; contact.ReCalc(1f); Assert.AreEqual(Vector3.Zero, contact.CalcLocalVelocity(0, 1f)); Assert.AreEqual(Vector3.Left, contact.CalcLocalVelocity(1, 1f)); Assert.AreEqual(Vector3.Zero, contact.RelativeContactPositions[0]); Assert.AreEqual(Vector3.Down * 0.95f, contact.RelativeContactPositions[1]); Assert.AreEqual(Vector3.Right, contact.ContactVelocity); // Position Change Vector3[] linearChange = new Vector3[2]; Vector3[] angularChange = new Vector3[2]; contact.ApplyPositionChange( ref linearChange, ref angularChange, contact.Penetration); Assert.AreEqual(Vector3.Zero, angularChange[0], "Zero angular change for object 0"); Assert.AreEqual(Vector3.Zero, angularChange[1], "Zero angular change for object 1"); Assert.AreEqual(new Vector3(0.0f, 0f, 0f), linearChange[0], "Body 0 is not pushed at all because it has infinite mass"); Assert.AreEqual(new Vector3(0f, -0.05f, 0f), linearChange[1], "Body 1 is pushed up (forward in contact direction) by half penetration"); //Velocity Change Vector3[] velocityChange = new Vector3[2]; Vector3[] rotationChange = new Vector3[2]; contact.ApplyVelocityChange(ref velocityChange, ref rotationChange); Assert.AreEqual( Vector3.Zero, rotationChange[0], "Zero rotation change for object 0"); Assert.AreEqual( Vector3.Zero, rotationChange[1], "Zero rotation change for object 1"); Assert.AreEqual( Vector3.Zero, velocityChange[0], "Zero velocity applied to body 0"); Assert.AreEqual( Vector3.Up * 2f, velocityChange[1], "Counter velocity applied to body 1"); }
public void IntersectionTests_SphereVsSphere_SurfaceCollision() { Vector3 sphereOnePosition = Vector3.Zero; IRigidBody sphereOneBody = new NoBody(Matrix.CreateTranslation(sphereOnePosition)); float sphereOneRadius = 0.5f; Matrix sphereOneMatrix = Matrix.Identity; Sphere sphereOne = new Sphere(sphereOneBody, sphereOneMatrix, sphereOneRadius); Vector3 sphereTwoPosition = Vector3.UnitX; IRigidBody sphereTwoBody = new NoBody(Matrix.CreateTranslation(sphereTwoPosition)); float sphereTwoRadius = 0.5f; Matrix sphereTwoMatrix = Matrix.Identity; Sphere sphereTwo = new Sphere(sphereTwoBody, sphereTwoMatrix, sphereTwoRadius); CollisionData data = new CollisionData(); Assert.AreEqual(1, IntersectionTests.sphereAndSphere(sphereOne, sphereTwo, data), "How many contacts?"); Contact contact; Assert.NotNull(data.contacts, "Contacts Container"); Assert.AreEqual(1, data.contacts.Count, "One Contact Expected"); contact = data.contacts[0]; Assert.AreEqual(0, contact.Friction, "0 friction"); Assert.AreEqual(1f, contact.Restitution, "1 restitution"); Assert.AreEqual(0, contact.Penetration, "0 penetration (surface collision)"); Assert.AreEqual(new Vector3(0.5f, 0f, 0f), contact.Point, "expected contact point"); Assert.AreEqual(-Vector3.UnitX, contact.Normal, "expected contact normal"); //Assymetric data = new CollisionData(); IntersectionTests.sphereAndSphere(sphereTwo, sphereOne, data); Assert.NotNull(data.contacts, "Contacts Container"); Assert.AreEqual(1, data.contacts.Count, "One Contact Expected"); contact = data.contacts[0]; Assert.AreEqual(0, contact.Friction, "0 friction"); Assert.AreEqual(1, contact.Restitution, "1 restitution"); Assert.AreEqual(0, contact.Penetration, "0 penetration (surface collision)"); Assert.AreEqual(new Vector3(0.5f, 0f, 0f), contact.Point, "expected contact point"); Assert.AreEqual(Vector3.UnitX, contact.Normal, "expected contact normal"); }
public void IntersectionTests_BoxVsPlane() { IRigidBody planeBody = new NoBody(); Box box; Forever.Physics.Collide.Plane plane; CollisionData data; Vector3 planeNormal = Vector3.Up; // Plane is x-z plane for all tests //////// unit box is sitting at {0,1,0} (surface touching) box = new Box(new NoBody( Matrix.CreateTranslation(new Vector3(0f, 1f, 0f))), Matrix.Identity, new Vector3(1f, 1f, 1f)); plane = new Forever.Physics.Collide.Plane(planeBody, Vector3.Zero, planeNormal); data = new CollisionData(); int contactsFound = IntersectionTests.boxAndPlane(box, plane, data); Assert.AreEqual(4, contactsFound); Contact contact1 = data.contacts[0]; Contact contact2 = data.contacts[1]; Contact contact3 = data.contacts[2]; Contact contact4 = data.contacts[3]; Assert.AreEqual(new Vector3(-1f, 0f, -1f), contact1.Point); Assert.AreEqual(planeNormal, contact1.Normal); Assert.AreEqual(0, contact1.Penetration); Assert.AreEqual(new Vector3(-1f, 0f, 1f), contact2.Point); Assert.AreEqual(planeNormal, contact2.Normal); Assert.AreEqual(0, contact2.Penetration); Assert.AreEqual(new Vector3(1f, 0f, -1f), contact3.Point); Assert.AreEqual(planeNormal, contact3.Normal); Assert.AreEqual(0, contact3.Penetration); Assert.AreEqual(new Vector3(1f, 0f, 1f), contact4.Point); Assert.AreEqual(planeNormal, contact4.Normal); Assert.AreEqual(0, contact4.Penetration); //////// unit box is centered at origin box = new Box(new NoBody(Matrix.CreateTranslation(new Vector3(0f, 0f, 0f))), Matrix.Identity, new Vector3(1f, 1f, 1f)); plane = new Forever.Physics.Collide.Plane(planeBody, Vector3.Zero, planeNormal); data = new CollisionData(); contactsFound = IntersectionTests.boxAndPlane(box, plane, data); Assert.AreEqual(4, contactsFound); contact1 = data.contacts[0]; contact2 = data.contacts[1]; contact3 = data.contacts[2]; contact4 = data.contacts[3]; Assert.AreEqual(new Vector3(-1f, 0f, -1f), contact1.Point); Assert.AreEqual(planeNormal, contact1.Normal); Assert.AreEqual(1f, contact1.Penetration); Assert.AreEqual(new Vector3(-1f, 0f, 1f), contact2.Point); Assert.AreEqual(planeNormal, contact2.Normal); Assert.AreEqual(1f, contact2.Penetration); Assert.AreEqual(new Vector3(1f, 0f, -1f), contact3.Point); Assert.AreEqual(planeNormal, contact3.Normal); Assert.AreEqual(1f, contact3.Penetration); Assert.AreEqual(new Vector3(1f, 0f, 1f), contact4.Point); Assert.AreEqual(planeNormal, contact4.Normal); Assert.AreEqual(1f, contact4.Penetration); //// unit box centered at y=1 and rotated 45 degrees on each axis float angle = (float)Math.PI * 0.25f; Matrix boxMatrix = Matrix.CreateFromYawPitchRoll(angle, angle, angle) * Matrix.CreateTranslation(new Vector3(0f, 1f, 0f)); box = new Box(new NoBody(boxMatrix), Matrix.Identity, new Vector3(1f, 1f, 1f)); plane = new Forever.Physics.Collide.Plane(planeBody, Vector3.Zero, planeNormal); data = new CollisionData(); contactsFound = IntersectionTests.boxAndPlane(box, plane, data); Assert.AreEqual(1, contactsFound); contact1 = data.contacts[0]; Assert.True( TrickyMath.AlmostEquals(0.7071067f, contact1.Penetration) ); Assert.True( TrickyMath.CloseEnoughToBeSame( new Vector3(-0.2071069f, 0f, -0.2071068f), contact1.Point)); ////unit box centered at y=sqrt(2) and rotated 45 degrees on each axis boxMatrix = Matrix.CreateFromYawPitchRoll(angle, angle, angle) * Matrix.CreateTranslation(new Vector3(0f, TrickyMath.Sqrt(2), 0f)); box = new Box(new NoBody(boxMatrix), Matrix.Identity, new Vector3(1f, 1f, 1f)); plane = new Forever.Physics.Collide.Plane(planeBody, Vector3.Zero, planeNormal); data = new CollisionData(); contactsFound = IntersectionTests.boxAndPlane(box, plane, data); Assert.AreEqual(1, contactsFound); contact1 = data.contacts[0]; Assert.True( TrickyMath.AlmostEquals(0.292893142f,contact1.Penetration) ); Assert.True( TrickyMath.CloseEnoughToBeSame( new Vector3(-0.2071069f, 0f, -0.2071068f), contact1.Point ) ); Assert.AreEqual(Vector3.UnitY, contact1.Normal); }
public void IntersectionTests_SphereVsSphere_NoIntersection() { IRigidBody sphereOneBody = new NoBody(Matrix.CreateTranslation(Vector3.UnitX * -2f)); float sphereOneRadius = 1f; Matrix sphereOneMatrix = Matrix.Identity; Sphere sphereOne = new Sphere(sphereOneBody, sphereOneMatrix, sphereOneRadius); IRigidBody sphereTwoBody = new NoBody(Matrix.CreateTranslation(Vector3.UnitX * 2f)); float sphereTwoRadius = 1f; Matrix sphereTwoMatrix = Matrix.Identity; Sphere sphereTwo = new Sphere(sphereTwoBody, sphereTwoMatrix, sphereTwoRadius); CollisionData data = new CollisionData(); Assert.AreEqual(0, IntersectionTests.sphereAndSphere(sphereOne, sphereTwo, data)); }
public void IntersectionTests_SphereVsSphere_BodyPointIntersection() { IRigidBody sphereOneBody = new NoBody(); float sphereOneRadius = 1f; Matrix sphereOneMatrix = Matrix.Identity; Sphere sphereOne = new Sphere(sphereOneBody, sphereOneMatrix, sphereOneRadius); IRigidBody sphereTwoBody = new NoBody(); float sphereTwoRadius = 1f; Matrix sphereTwoMatrix = Matrix.Identity; Sphere sphereTwo = new Sphere(sphereTwoBody, sphereTwoMatrix, sphereTwoRadius); CollisionData data = new CollisionData(); IntersectionTests.sphereAndSphere(sphereOne, sphereTwo, data); }
public void IntersectionTests_BoxVsPoint() { IRigidBody body = new NoBody(); Box box; Vector3 point; CollisionData data; Contact contact; box = new Box(body, Matrix.Identity, new Vector3(1f, 1f, 1f)); ////////////////////////// point@+,+,+ point = new Vector3(0.75f, 1f, 1f); data = new CollisionData(); data.contactsLeft = 1; Assert.AreEqual(1, IntersectionTests.boxAndPoint(box, point, data)); contact = data.contacts[0]; Assert.AreEqual(Vector3.Left, contact.Normal); Assert.AreEqual(0.25f, contact.Penetration); Assert.AreEqual(1, data.contacts.Count); Assert.AreEqual(point, contact.Point); Assert.Null(contact.Bodies[1]); ///////////////////////////// point@center when box is translated Vector3 translatedPos = Vector3.UnitY * 10f; body = new NoBody(Matrix.CreateTranslation(translatedPos)); box = new Box(body, Matrix.Identity, new Vector3(1f, 1f, 1f)); point = translatedPos; data = new CollisionData(); data.contactsLeft = 1; Assert.AreEqual(1, IntersectionTests.boxAndPoint(box, point, data)); contact = data.contacts[0]; Assert.AreEqual(1f, contact.Penetration); Assert.AreEqual(1, data.contacts.Count); Assert.AreEqual(point, contact.Point); Assert.AreEqual(Vector3.Right, contact.Normal); Assert.Null(contact.Bodies[1]); /////////////////////////////////////point@+,+,+ when box is translated point = translatedPos + Vector3.Right * 0.75f; data = new CollisionData(); data.contactsLeft = 1; Assert.AreEqual(1, IntersectionTests.boxAndPoint(box, point, data)); contact = data.contacts[0]; Assert.AreEqual(0.25f, contact.Penetration); Assert.AreEqual(1, data.contacts.Count); Assert.AreEqual(point, contact.Point); Vector3 normal = Vector3.Left; Assert.AreEqual(normal, contact.Normal); Assert.Null(contact.Bodies[1]); //////////////////////////////////////////point@tip(+,+,+) body = new NoBody(); box = new Box(body, Matrix.Identity, new Vector3(1f, 1f, 1f)); point = new Vector3(1f, 1f, 1f); data = new CollisionData(); data.contactsLeft = 1; Assert.AreEqual(1, IntersectionTests.boxAndPoint(box, point, data)); contact = data.contacts[0]; Assert.AreEqual(0f, contact.Penetration); Assert.AreEqual(1, data.contacts.Count); Assert.AreEqual(point, contact.Point); Assert.AreEqual(Vector3.Left, contact.Normal); Assert.Null(contact.Bodies[1]); /////////////////////////////////////////point@tip(-,-,-) point = new Vector3(-1f, -1f, -1f); data = new CollisionData(); data.contactsLeft = 1; Assert.AreEqual(1, IntersectionTests.boxAndPoint(box, point, data)); contact = data.contacts[0]; Assert.AreEqual(0f, contact.Penetration); Assert.AreEqual(1, data.contacts.Count); Assert.AreEqual(point, contact.Point); Assert.AreEqual(Vector3.Right, contact.Normal); Assert.Null(contact.Bodies[1]); /////////////////////////////////////////point@middle of nowhere point = new Vector3(10000f, 10000f, 10000f); data = new CollisionData(); data.contactsLeft = 1; Assert.AreEqual(0, IntersectionTests.boxAndPoint(box, point, data)); /////////////////////////////////////////point@+,0,0 after box is rotated float rotY = (float)Math.PI / 4f; //45 degrees point = new Vector3(1.001f, 0f, 0f); body = new NoBody(Matrix.CreateRotationY(rotY)); box = new Box(body, Matrix.Identity, new Vector3(1f, 1f, 1f)); data = new CollisionData(); Assert.AreEqual(1, IntersectionTests.boxAndPoint(box, point, data)); Assert.AreEqual(1, data.contacts.Count); contact = data.contacts[0]; Assert.True( TrickyMath.CloseEnoughToBeSame(contact.Normal, new Vector3(-0.7071068f, 0, 0.7071068f) ) ); /////////////////////////////////////////////////////point@+,0,0 after box is rotated other direction point = new Vector3(1.001f, 0f, 0f); body = new NoBody(Matrix.CreateRotationY(-rotY)); box = new Box(body, Matrix.Identity, new Vector3(1f, 1f, 1f)); data = new CollisionData(); Assert.AreEqual(1, IntersectionTests.boxAndPoint(box, point, data)); Assert.AreEqual(1, data.contacts.Count); contact = data.contacts[0]; Assert.True( TrickyMath.CloseEnoughToBeSame(contact.Normal, new Vector3(-0.7071068f, 0, -0.7071068f)) ); }