Пример #1
0
        public static void SphereAndSphere(CollisionSphere one, CollisionSphere two, CollisionData data)
        {
            // Make sure we have contacts
            if (data.NoMoreContacts())
            {
                return;
            }

            // Cache the sphere positions
            Vector3d positionOne = one.GetAxis(3);
            Vector3d positionTwo = two.GetAxis(3);

            // Find the vector between the objects
            Vector3d midline = positionOne - positionTwo;
            double   size    = midline.Magnitude;

            // See if it is large enough.
            if (size <= 0.0f || size >= one.Radius + two.Radius)
            {
                return;
            }

            // We manually create the normal, because we have the
            // size to hand.
            Vector3d normal = midline * (1.0 / size);

            var contact = data.GetContact();

            contact.ContactNormal = normal;
            contact.ContactPoint  = positionOne + midline * 0.5;
            contact.Penetration   = one.Radius + two.Radius - size;
            contact.SetBodyData(one.Body, two.Body, data.Friction, data.Restitution);
        }
Пример #2
0
        public static void SphereAndHalfSpace(CollisionSphere sphere, CollisionPlane plane, CollisionData data)
        {
            // Make sure we have contacts
            if (data.NoMoreContacts())
            {
                return;
            }

            // Cache the sphere position
            Vector3d position = sphere.GetAxis(3);

            // Find the distance from the plane
            double dist = Vector3d.Dot(plane.Direction, position) - sphere.Radius - plane.Offset;

            if (dist >= 0)
            {
                return;
            }

            // Create the contact - it has a normal in the plane direction.
            var contact = data.GetContact();

            contact.ContactNormal = plane.Direction;
            contact.Penetration   = -dist;
            contact.ContactPoint  = position - plane.Direction * (dist + sphere.Radius);
            contact.SetBodyData(sphere.Body, null, data.Friction, data.Restitution);
        }
Пример #3
0
        public static bool SphereAndSphere(CollisionSphere one, CollisionSphere two)
        {
            // Find the vector between the objects
            Vector3d midline = one.GetAxis(3) - two.GetAxis(3);

            // See if it is large enough.
            return(midline.SqrMagnitude < (one.Radius + two.Radius) * (one.Radius + two.Radius));
        }
Пример #4
0
        public static bool SphereAndHalfSpace(CollisionSphere sphere, CollisionPlane plane)
        {
            // Find the distance from the origin
            double ballDistance = Vector3d.Dot(plane.Direction, sphere.GetAxis(3)) - sphere.Radius;

            // Check for the intersection
            return(ballDistance <= plane.Offset);
        }
Пример #5
0
        public static void SphereAndTruePlane(CollisionSphere sphere, CollisionPlane plane, CollisionData data)
        {
            // Make sure we have contacts
            if (data.NoMoreContacts())
            {
                return;
            }

            // Cache the sphere position
            Vector3d position = sphere.GetAxis(3);

            // Find the distance from the plane
            double centreDistance = Vector3d.Dot(plane.Direction, position) - plane.Offset;

            // Check if we're within radius
            if (centreDistance * centreDistance > sphere.Radius * sphere.Radius)
            {
                return;
            }

            // Check which side of the plane we're on
            Vector3d normal      = plane.Direction;
            double   penetration = -centreDistance;

            if (centreDistance < 0)
            {
                normal     *= -1;
                penetration = -penetration;
            }
            penetration += sphere.Radius;

            // Create the contact - it has a normal in the plane direction.
            var contact = data.GetContact();

            contact.ContactNormal = normal;
            contact.Penetration   = penetration;
            contact.ContactPoint  = position - plane.Direction * centreDistance;
            contact.SetBodyData(sphere.Body, null, data.Friction, data.Restitution);
        }
Пример #6
0
        public static void BoxAndSphere(CollisionBox box, CollisionSphere sphere, CollisionData data)
        {
            // Make sure we have contacts
            if (data.NoMoreContacts())
            {
                return;
            }

            // Transform the centre of the sphere into box coordinates
            Vector3d centre    = sphere.GetAxis(3);
            Vector3d relCentre = box.Transform.TransformInverse(centre);

            // Early out check to see if we can exclude the contact
            if (Math.Abs(relCentre.x) - sphere.Radius > box.HalfSize.x ||
                Math.Abs(relCentre.y) - sphere.Radius > box.HalfSize.y ||
                Math.Abs(relCentre.z) - sphere.Radius > box.HalfSize.z)
            {
                return;
            }

            Vector3d closestPt = new Vector3d(0, 0, 0);
            double   dist;

            // Clamp each coordinate to the box.
            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;

            // Check we're in contact
            dist = (closestPt - relCentre).SqrMagnitude;
            if (dist > sphere.Radius * sphere.Radius)
            {
                return;
            }

            // Compile the contact
            Vector3d closestPtWorld = box.Transform.Transform(closestPt);

            var contact = data.GetContact();

            contact.ContactNormal = (closestPtWorld - centre).Normalized;
            contact.ContactPoint  = closestPtWorld;
            contact.Penetration   = sphere.Radius - Math.Sqrt(dist);
            contact.SetBodyData(box.Body, sphere.Body, data.Friction, data.Restitution);
        }