public ModelEntity CreateSphere(Vector3 position, float mass, float dimension) { Model model = Models[CollideType.Sphere]; float radius = dimension; RigidBody body = new RigidBody(position); body.LinearDamping = LinearDamping; body.AngularDamping = AngularDamping; body.Awake = true; body.Mass = mass; body.InertiaTensor = InertiaTensorFactory.Sphere(mass, radius); Sphere prim = new Sphere(body, Matrix.Identity, radius); EntityGeometryData geoData = new EntityGeometryData(); geoData.Prim = prim; geoData.BoundingSphere = new BoundingSphere(Vector3.Zero, prim.Radius); return new ModelEntity(model, body, geoData); }
public ModelEntity CreateDefaultFromModel(Model model, Vector3 pos) { AABBTree tree = AABBFactory.AABBTree(model); BoundingBox box = tree.Root.BBox; float radius = BoundingSphere.CreateFromBoundingBox(box).Radius; float mass = 1f; RigidBody body = new RigidBody(pos); body.LinearDamping = LinearDamping; body.AngularDamping = AngularDamping; body.Awake = true; body.Mass = mass; body.InertiaTensor = InertiaTensorFactory.Sphere(mass, radius); Sphere prim = new Sphere(body, Matrix.Identity, radius); EntityGeometryData geoData = new EntityGeometryData(); geoData.BoundingSphere = new BoundingSphere(Vector3.Zero, radius); geoData.Prim = prim; return new ModelEntity(model, body, geoData); }
public static int sphereAndSphere(Sphere one, Sphere two, CollisionData data) { //make sure we have contacts if (data.contactsLeft <= 0) return 0; // Cache the sphere positions Vector3 positionOne = one.Body.Position; Vector3 positionTwo = two.Body.Position; if (positionOne == positionTwo) { throw new ArgumentException("Two bodies with the same position are unsupported....TODO"); } // find the vector between the objects Vector3 midline = positionOne - positionTwo; float size = midline.Length(); //see if it is large enough if (size <= 0.0f || size > one.Radius + two.Radius) { return 0; } // we manually create the normal, because we have the size at hand; Vector3 normal = midline * (1f / size); Contact contact = new Contact(); contact.Normal = normal; contact.Point = positionTwo + midline * 0.5f; contact.Penetration = (one.Radius + two.Radius - size); //write the appropriate data contact.Bodies[0] = one.Body; contact.Bodies[1] = two.Body; contact.Restitution = data.restitution; contact.Friction = data.friction; data.contacts.Add(contact); return 1; }
public static void Render(Sphere sphere, RenderContext context, Color color) { BoundingSphere bs = new BoundingSphere(sphere.Body.Position, sphere.Radius); BoundingSphereRenderer.Render(bs, context, color); }
public static int boxAndSphere(Box box, Sphere sph, CollisionData data) { Vector3 center = sph.Body.Position; Vector3 relCenter = Vector3.Transform(center, Matrix.Invert(box.Transform)); double x = relCenter.X; double y = relCenter.Y; double z = relCenter.Z; if (Math.Abs(x) - sph.Radius > box.HalfSizes.X || Math.Abs(y) - sph.Radius > box.HalfSizes.Y || Math.Abs(z) - sph.Radius > box.HalfSizes.Z) { return 0; } Vector3 closest = Vector3.Zero; float dist; dist = relCenter.X; if (dist > box.HalfSizes.X) dist = box.HalfSizes.X; if (dist < -box.HalfSizes.X) dist = -box.HalfSizes.X; closest.X = dist; dist = relCenter.Y; if (dist > box.HalfSizes.Y) dist = box.HalfSizes.Y; if (dist < -box.HalfSizes.Y) dist = -box.HalfSizes.Y; closest.Y = dist; dist = relCenter.Z; if (dist > box.HalfSizes.Z) dist = box.HalfSizes.Z; if (dist < -box.HalfSizes.Z) dist = -box.HalfSizes.Z; closest.Z = dist; dist = (closest - relCenter).Length(); if (dist > sph.Radius && !TrickyMath.AlmostEquals(0f, dist - sph.Radius)) return 0; Vector3 closestWorld = Vector3.Transform(closest, box.Transform); Contact contact = new Contact(); Vector3 normal = closestWorld - center;// (center - closestWorld); normal.Normalize(); contact.Normal = normal; Debug.Sanity(contact.Normal); contact.Point = closestWorld; contact.Penetration = sph.Radius - dist;// (float)Math.Sqrt((float)dist); contact.Bodies[0] = box.Body; contact.Bodies[1] = sph.Body; contact.Restitution = data.restitution; contact.Friction = data.friction; data.contacts.Add(contact); return 1; }
public static int sphereAndHalfSpace(Sphere sphere, Plane plane, CollisionData data) { Vector3 pos = sphere.Body.Position; //d = p * L - l float ballDist = Vector3.Dot(plane.Normal, pos) - (sphere.Radius - plane.Offset); if (ballDist > 0) return 0; Contact contact = new Contact(); contact.Normal = plane.Normal; contact.Penetration = -ballDist; contact.Point = pos - (plane.Normal * (ballDist + sphere.Radius)); contact.Bodies[0] = sphere.Body; contact.Bodies[1] = null; contact.Restitution = data.restitution; contact.Friction = data.friction; data.contacts.Add(contact); return 1; }
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_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_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_SphereVsPlane() { Matrix sphereMatrix; float sphereRadius = 1f; Forever.Physics.Collide.Plane plane; Forever.Physics.Collide.Sphere sphere; CollisionData data; int contactsFound; Contact contact1; // plane is always the x-z plane for this test method Vector3 planeNormal = Vector3.Up; plane = new Forever.Physics.Collide.Plane(new NoBody(), Vector3.Zero, planeNormal); // unit sphere centered at y=1 (one point of surface touching) sphereMatrix = Matrix.CreateTranslation(Vector3.UnitY); sphere = new Sphere( new NoBody(sphereMatrix), Matrix.Identity, sphereRadius); data = new CollisionData(); contactsFound = IntersectionTests.sphereAndHalfSpace(sphere, plane, data); Assert.AreEqual(1, contactsFound); contact1 = data.contacts[0]; Assert.AreEqual(Vector3.Zero, contact1.Point); Assert.AreEqual(0f, contact1.Penetration); Assert.AreEqual(planeNormal, contact1.Normal); // unit sphere centered at y=0.9 (.1 penetration) sphereMatrix = Matrix.CreateTranslation(Vector3.UnitY * 0.9f); sphere = new Sphere(new NoBody(sphereMatrix), Matrix.Identity, sphereRadius); data = new CollisionData(); contactsFound = IntersectionTests.sphereAndHalfSpace(sphere, plane, data); Assert.AreEqual(1, contactsFound); contact1 = data.contacts[0]; Assert.AreEqual(Vector3.Zero, contact1.Point); Assert.True( TrickyMath.AlmostEquals(0.1f, contact1.Penetration) ); Assert.AreEqual(planeNormal, contact1.Normal); }
public void IntersectionTests_BoxVsSphere_NoIntersection() { float sphereRadius = 1f; CollisionData data; int contactsFound; Contact contact1; Forever.Physics.Collide.Sphere sphere; Forever.Physics.Collide.Box box; // no intersection sphere = new Sphere( new NoBody( Matrix.CreateTranslation(new Vector3(-10000f, -10000f, -10000f))), Matrix.Identity, sphereRadius ); box = new Box( new NoBody(Matrix.CreateTranslation(new Vector3(10000f, 10000f, 10000f))), Matrix.Identity, new Vector3(1f, 1f, 1f) ); data = new CollisionData(); contactsFound = IntersectionTests.boxAndSphere(box, sphere, data); Assert.AreEqual(0, contactsFound); }
public void IntersectionTests_BoxVsSphere_BoxFace() { //box face intersection float sphereRadius = 1f; CollisionData data; int contactsFound; Contact contact1; Forever.Physics.Collide.Sphere sphere; Forever.Physics.Collide.Box box; sphere = new Sphere( new NoBody(Matrix.CreateTranslation(Vector3.Up)), Matrix.Identity, sphereRadius); box = new Box( new NoBody(Matrix.CreateTranslation(Vector3.Down * 0.95f)), Matrix.Identity, new Vector3(1f, 1f, 1f)); data = new CollisionData(); contactsFound = IntersectionTests.boxAndSphere(box, sphere, data); Assert.AreEqual(1, contactsFound); contact1 = data.contacts[0]; Assert.True( TrickyMath.AlmostEquals(0.05f, contact1.Penetration) ); Assert.True( TrickyMath.CloseEnoughToBeSame(new Vector3(0f, 0.05f, 0f), contact1.Point) ); Assert.AreEqual(Vector3.Down, contact1.Normal); }
public void IntersectionTests_BoxVsSphere_BoxEdge_ZeroPenetration() { //box edge intersection float sphereRadius = 1f; CollisionData data; int contactsFound; Contact contact1; Forever.Physics.Collide.Sphere sphere; Forever.Physics.Collide.Box box; box = new Box( new NoBody(), //box centered at origin Matrix.Identity, new Vector3(1f, 1f, 1f) ); Vector3 spherePos = new Vector3(0f, 1f, 1f); spherePos.Normalize(); spherePos = new Vector3(0f, 1f, 1f) + spherePos; sphere = new Sphere( new NoBody( Matrix.CreateTranslation(spherePos) ), Matrix.Identity, sphereRadius); data = new CollisionData(); contactsFound = IntersectionTests.boxAndSphere(box, sphere, data); Assert.AreEqual(1, contactsFound); contact1 = data.contacts[0]; Assert.True( TrickyMath.AlmostEquals(0f, contact1.Penetration) ); Assert.AreEqual(new Vector3(0f, 1f, 1f), contact1.Point); Assert.True( TrickyMath.CloseEnoughToBeSame( new Vector3(0f, -0.7071068f, -0.7071068f), contact1.Normal) ); }