/// <summary>
        /// Detecta la colisión entre una caja y una esfera
        /// </summary>
        /// <param name="box">Caja</param>
        /// <param name="sphere">Esfera</param>
        /// <param name="data">Datos de colisión a llenar</param>
        /// <returns>Devuelve verdadero si existe colisión, falso en el resto de los casos</returns>
        private static bool BoxAndSphere(CollisionBox box, CollisionSphere sphere, ref CollisionData data)
        {
            if (data.ContactsLeft <= 0)
            {
                // Si no hay más contactos disponibles se sale de la función.
                return(false);
            }

            // Obtener el punto de la caja más cercano al centro de la esfera
            Vector3 closestPoint = CollisionBox.ClosestPointInBox(box, sphere.Position);

            // Obtener la distancia entre los puntos
            float distance = Vector3.Distance(sphere.Position, closestPoint);

            if (distance <= sphere.Radius)
            {
                Vector3 normal = Vector3.Normalize(box.Position - closestPoint);

                Contact contact = data.CurrentContact;
                contact.ContactNormal = normal;
                contact.ContactPoint  = closestPoint;
                contact.Penetration   = sphere.Radius - distance;

                RigidBody one = box;
                RigidBody two = sphere;
                contact.SetBodyData(ref one, ref two, data.Friction, data.Restitution);

                data.AddContact();

                return(true);
            }

            return(false);
        }
        /// <summary>
        /// Detecta la colisión entre una esfera y una lista de triángulos
        /// </summary>
        /// <param name="sphere">Esfera</param>
        /// <param name="triangleList">Lista de triángulos</param>
        /// <param name="data">Datos de la colisión</param>
        /// <returns>Devuelve verdadero si hay colisión, o falso en el resto de los casos</returns>
        private static bool SphereAndTriangleList(CollisionSphere sphere, Triangle[] triangleList, ref CollisionData data)
        {
            bool contact = false;

            if (data.ContactsLeft > 0)
            {
                if (triangleList != null && triangleList.Length > 0)
                {
                    foreach (Triangle triangle in triangleList)
                    {
                        if (data.ContactsLeft > 0)
                        {
                            // Comprobar la intersección
                            if (CollisionDetector.SphereAndTriangle(sphere, triangle, ref data))
                            {
                                contact = true;
                            }
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }

            return(contact);
        }
        /// <summary>
        /// Detecta la colisión entre dos esferas
        /// </summary>
        /// <param name="one">Esfera uno</param>
        /// <param name="two">Esfera dos</param>
        /// <param name="data">Datos de la colisión</param>
        /// <returns>Devuelve verdadero si hay colisión, o falso en el resto de los casos</returns>
        public static bool SphereAndSphere(CollisionSphere one, CollisionSphere two, ref CollisionData data)
        {
            if (data.ContactsLeft <= 0)
            {
                // Si no hay más contactos disponibles se sale de la función.
                return(false);
            }

            // Almacenar las posiciones de las esferas
            Vector3 positionOne = one.Position;
            Vector3 positionTwo = two.Position;

            // Encontrar el vector entre los objetos
            Vector3 midline = positionOne - positionTwo;
            float   size    = midline.Length();

            if (size <= 0.0f || size >= one.Radius + two.Radius)
            {
                return(false);
            }

            // Obtener la normal de forma manual
            Vector3 normal = midline * (1.0f / size);

            Contact contact = data.CurrentContact;

            contact.ContactNormal = normal;
            contact.ContactPoint  = positionOne + midline * 0.5f;
            contact.Penetration   = (one.Radius + two.Radius - size);
            contact.SetBodyData(ref one.Body, ref two.Body, data.Friction, data.Restitution);

            data.AddContact();

            return(true);
        }
        /// <summary>
        /// Detecta la colisión entre una esfera y un triángulo
        /// </summary>
        /// <param name="sphere">Esfera</param>
        /// <param name="tri">Triángulo</param>
        /// <param name="data">Rellena los datos de colisión</param>
        /// <returns>Devuelve verdadero si hay colisión o falso en el resto de los casos</returns>
        private static bool SphereAndTriangle(CollisionSphere sphere, Triangle tri, ref CollisionData data)
        {
            if (data.ContactsLeft <= 0)
            {
                // Si no hay más contactos disponibles se sale de la función.
                return(false);
            }

            // Obtener el punto del triángulo más cercano al centro de la esfera
            Vector3 closestPoint = Triangle.ClosestPointInTriangle(tri, sphere.Position);

            // Obtener la distancia del punto obtenido al centro de la esfera
            float distance = Vector3.Distance(closestPoint, sphere.Position);

            if (distance <= sphere.Radius)
            {
                // Crear el contacto. Tiene una normal en la dirección del plano.
                Contact contact = data.CurrentContact;
                contact.ContactNormal = tri.Normal;
                contact.Penetration   = sphere.Radius - distance;
                contact.ContactPoint  = closestPoint;

                RigidBody one = sphere;
                RigidBody two = null;
                contact.SetBodyData(ref one, ref two, data.Friction, data.Restitution);

                data.AddContact();

                return(true);
            }
            else
            {
                return(false);
            }
        }
        /// <summary>
        /// Detecta la intersección entre dos esferas
        /// </summary>
        /// <param name="one">Esfera</param>
        /// <param name="two">Esfera</param>
        /// <returns>Devuelve verdadero si hay intersección</returns>
        public static bool SphereAndSphere(CollisionSphere one, CollisionSphere two)
        {
            // Vector entre ambas esferas
            Vector3 midline = one.Position - two.Position;

            // Si el vector es más largo que la suma de los radios, no hay intersección
            return(midline.LengthSquared() < (one.Radius + two.Radius) * (one.Radius + two.Radius));
        }
        public static bool SphereAndHalfSpace(CollisionSphere sphere, CollisionPlane plane)
        {
            // Find the distance from the origin
            float ballDistance = Vector3.Dot(plane.Normal, sphere.Position) - sphere.Radius;

            // Check for the intersection
            return(ballDistance <= plane.D);
        }
        public static bool SphereAndSphere(CollisionSphere one, CollisionSphere two)
        {
            // Find the vector between the objects
            Vector3 midline = one.Position - two.Position;

            // See if it is large enough.
            return(midline.LengthSquared() < (one.Radius + two.Radius) * (one.Radius + two.Radius));
        }
        /// <summary>
        /// Detecta la intersección entre una esfera y un triángulo
        /// </summary>
        /// <param name="sphere">Esfera</param>
        /// <param name="triangle">Triángulo</param>
        /// <param name="halfSpace">Indica si toma el triángulo como un HalfSpace, para tener en cuenta la dirección de la normal</param>
        /// <returns>Devuelve verdadero si hay intersección</returns>
        public static bool SphereAndTri(CollisionSphere sphere, Triangle triangle)
        {
            // Obtener el punto más cercano al triángulo desde el centro
            Vector3 point = Triangle.ClosestPointInTriangle(triangle, sphere.Position);

            float distance = Vector3.Distance(point, sphere.Position);

            if (distance > sphere.Radius)
            {
                return(false);
            }
            else
            {
                return(true);
            }
        }
        /// <summary>
        /// Detecta la colisión entre una esfera y un plano
        /// </summary>
        /// <param name="sphere">Esfera</param>
        /// <param name="plane">Plano</param>
        /// <param name="data">Rellena los datos de colisión</param>
        /// <returns>Devuelve verdadero si hay colisión o falso en el resto de los casos</returns>
        public static bool SphereAndTruePlane(CollisionSphere sphere, CollisionPlane plane, ref CollisionData data)
        {
            if (data.ContactsLeft <= 0)
            {
                // Si no hay más contactos disponibles se sale de la función.
                return(false);
            }

            // Almacenar la posición de la esfera
            Vector3 position = sphere.Position;

            // Encontrar la distancia al plano
            float centreDistance = Vector3.Dot(plane.Normal, position) - plane.D;

            if (centreDistance * centreDistance > sphere.Radius * sphere.Radius)
            {
                return(false);
            }

            // Chequear la cara del plano en la que estamos para calcular normal y penetración
            Vector3 normal      = plane.Normal;
            float   penetration = -centreDistance;

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

            // Crear el contacto. Tiene una normal en la dirección del plano.
            Contact contact = data.CurrentContact;

            contact.ContactNormal = normal;
            contact.Penetration   = penetration;
            contact.ContactPoint  = position - plane.Normal * centreDistance;

            RigidBody two = null;

            contact.SetBodyData(ref sphere.Body, ref two, data.Friction, data.Restitution);

            data.AddContact();

            return(true);
        }
Esempio n. 10
0
        /// <summary>
        /// Detecta la intersección entre una esfera y un plano
        /// </summary>
        /// <param name="sphere">Esfera</param>
        /// <param name="normal">Normal del plano</param>
        /// <param name="d">Distancia</param>
        /// <returns>Devuelve verdadero si hay intersección</returns>
        public static int SphereAndPlane(CollisionSphere sphere, Vector3 normal, float d)
        {
            // Buscar la distancia al origen
            float distance = Vector3.Dot(normal, sphere.Position) + d;

            // Si la distancia es menor hay intersección
            if (distance > sphere.Radius)
            {
                // La esfera está sobre el plano
                return(1);
            }
            else if (distance < -sphere.Radius)
            {
                // La esfera está bajo el plano
                return(-1);
            }
            else
            {
                // La esfera intersecta con el plano
                return(0);
            }
        }
Esempio n. 11
0
        /// <summary>
        /// Detecta la colisión entre una esfera y una lista de triángulos
        /// </summary>
        /// <param name="sphere">Esfera</param>
        /// <param name="triangleSoup">Lista de triángulos</param>
        /// <param name="data">Datos de la colisión</param>
        /// <returns>Devuelve verdadero si hay colisión, o falso en el resto de los casos</returns>
        public static bool SphereAndTriangleSoup(CollisionSphere sphere, CollisionTriangleSoup triangleSoup, ref CollisionData data)
        {
            if (data.ContactsLeft <= 0)
            {
                // Si no hay más contactos disponibles se sale de la función.
                return(false);
            }

            foreach (Triangle triangle in triangleSoup.Triangles)
            {
                // Comprobar la intersección
                if (IntersectionTests.SphereAndTri(sphere, triangle, true))
                {
                    // Informar la colisión
                    if (CollisionDetector.SphereAndHalfSpace(sphere, new CollisionPlane(triangle.Plane), ref data))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
Esempio n. 12
0
        /// <summary>
        /// Detecta la colisión entre una esfera y un plano
        /// </summary>
        /// <param name="sphere">Esfera</param>
        /// <param name="plane">Plano</param>
        /// <param name="data">Rellena los datos de colisión</param>
        /// <returns>Devuelve verdadero si hay colisión o falso en el resto de los casos</returns>
        private static bool SphereAndHalfSpace(CollisionSphere sphere, CollisionPlane plane, ref CollisionData data)
        {
            if (data.ContactsLeft <= 0)
            {
                // Si no hay más contactos disponibles se sale de la función.
                return(false);
            }

            // Distancia del centro al plano
            float centerToPlane = Math.Abs(Vector3.Dot(plane.Normal, sphere.Position) + plane.D);

            // Obtener la penetración de la esfera en el plano.
            float penetration = centerToPlane - sphere.Radius;

            if (penetration >= 0)
            {
                return(false);
            }

            // Crear el contacto. Tiene una normal en la dirección del plano.
            Contact contact = data.CurrentContact;

            contact.ContactNormal = plane.Normal;
            contact.Penetration   = -penetration;
            contact.ContactPoint  = sphere.Position - plane.Normal * centerToPlane;

            // No hay cuerpo para el plano. Se considera escenario.
            RigidBody one = sphere;
            RigidBody two = null;

            contact.SetBodyData(ref one, ref two, data.Friction, data.Restitution);

            // Añadir el contacto
            data.AddContact();

            return(true);
        }
Esempio n. 13
0
        /// <summary>
        /// Detecta la colisión entre una esfera y un plano
        /// </summary>
        /// <param name="sphere">Esfera</param>
        /// <param name="plane">Plano</param>
        /// <param name="data">Rellena los datos de colisión</param>
        /// <returns>Devuelve verdadero si hay colisión o falso en el resto de los casos</returns>
        public static bool SphereAndHalfSpace(CollisionSphere sphere, CollisionPlane plane, ref CollisionData data)
        {
            if (data.ContactsLeft <= 0)
            {
                // Si no hay más contactos disponibles se sale de la función.
                return(false);
            }

            // Almacenar la posición de la esfera
            Vector3 position = sphere.Position;

            // Obtener la distancia al plano.
            float ballDistance = Vector3.Dot(plane.Normal, position) - sphere.Radius - plane.D;

            if (ballDistance >= 0)
            {
                return(false);
            }

            // Crear el contacto. Tiene una normal en la dirección del plano.
            Contact contact = data.CurrentContact;

            contact.ContactNormal = plane.Normal;
            contact.Penetration   = -ballDistance;
            contact.ContactPoint  = position - plane.Normal * (ballDistance + sphere.Radius);

            // No hay cuerpo para el plano. Se considera escenario.
            RigidBody two = null;

            contact.SetBodyData(ref sphere.Body, ref two, data.Friction, data.Restitution);

            // Añadir el contacto
            data.AddContact();

            return(true);
        }
Esempio n. 14
0
 /// <summary>
 /// Detecta la intersección entre una esfera y un plano
 /// </summary>
 /// <param name="sphere">Esfera</param>
 /// <param name="plane">Plano</param>
 /// <returns>Devuelve verdadero si hay intersección</returns>
 public static bool SphereAndPlane(CollisionSphere sphere, Plane plane)
 {
     return(SphereAndPlane(sphere, plane.Normal, plane.D) == 0);
 }
Esempio n. 15
0
        /// <summary>
        /// Detecta la colisión entre una caja y una esfera
        /// </summary>
        /// <param name="box">Caja</param>
        /// <param name="sphere">Esfera</param>
        /// <param name="data">Datos de colisión a llenar</param>
        /// <returns>Devuelve verdadero si existe colisión, falso en el resto de los casos</returns>
        public static bool BoxAndSphere(CollisionBox box, CollisionSphere sphere, ref CollisionData data)
        {
            if (data.ContactsLeft <= 0)
            {
                // Si no hay más contactos disponibles se sale de la función.
                return(false);
            }

            // Transformar el cetro de la esfera
            Vector3 centre    = sphere.Position;
            Vector3 relCentre = Vector3.Transform(centre, Matrix.Invert(box.Transform));

            // Comprobar si se puede excluir el contacto
            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(false);
            }

            Vector3 closestPt = Vector3.Zero;

            float 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;

            // Comprobar si estamos en contacto.
            dist = (closestPt - relCentre).LengthSquared();
            if (dist > sphere.Radius * sphere.Radius)
            {
                return(false);
            }

            Vector3 closestPtWorld = Vector3.Transform(closestPt, box.Transform);

            //HACKBYME: Añadimos la velocidad de la esfera para calcular la normal
            Vector3 relativeVelocity = sphere.Body.Velocity + box.Body.Velocity;
            Vector3 normal           = Vector3.Normalize(closestPtWorld - centre + relativeVelocity);

            Contact contact = data.CurrentContact;

            contact.ContactNormal = normal;
            contact.ContactPoint  = closestPtWorld;
            contact.Penetration   = sphere.Radius - (float)Math.Sqrt(dist);
            contact.SetBodyData(ref box.Body, ref sphere.Body, data.Friction, data.Restitution);

            data.AddContact();

            return(true);
        }
Esempio n. 16
0
 /// <summary>
 /// Detecta la colisión entre una esfera y una lista de triángulos
 /// </summary>
 /// <param name="sphere">Esfera</param>
 /// <param name="triangleSoup">Lista de triángulos</param>
 /// <param name="data">Datos de la colisión</param>
 /// <returns>Devuelve verdadero si hay colisión, o falso en el resto de los casos</returns>
 private static bool SphereAndTriangleSoup(CollisionSphere sphere, CollisionTriangleSoup triangleSoup, ref CollisionData data)
 {
     return(SphereAndTriangleList(sphere, triangleSoup.Triangles, ref data));
 }
Esempio n. 17
0
        public static bool SphereAndTri(CollisionSphere sphere, Triangle triangle, bool halfSpace)
        {
            bool axisTest = true;

            if (!halfSpace)
            {
                // Find the distance from the origin
                float ballDistance = Math.Abs(Vector3.Dot(triangle.Plane.Normal, sphere.Position)) - sphere.Radius;

                // Check for the intersection
                if (ballDistance > triangle.Plane.D)
                {
                    axisTest = false;
                }
            }

            if (axisTest)
            {
                // Obtener los ejes del triángulo
                Vector3 edge0 = Vector3.Subtract(triangle.Point2, triangle.Point1);
                Vector3 edge1 = Vector3.Subtract(triangle.Point3, triangle.Point2);
                Vector3 edge2 = Vector3.Subtract(triangle.Point1, triangle.Point3);

                // Proyectar desde el punto 1
                Vector3 toPoint1    = sphere.Position - triangle.Point1;
                float   distanceTo1 = toPoint1.Length();
                toPoint1.Normalize();
                float f1a = Math.Abs(Vector3.Dot(edge0, toPoint1));
                float f1b = Math.Abs(Vector3.Dot(edge2, toPoint1));
                if (distanceTo1 > f1a + sphere.Radius)
                {
                    return(false);
                }
                if (distanceTo1 > f1a + sphere.Radius)
                {
                    return(false);
                }

                // Proyectar desde el punto 2
                Vector3 toPoint2    = sphere.Position - triangle.Point2;
                float   distanceTo2 = toPoint2.Length();
                toPoint2.Normalize();
                float f2a = Math.Abs(Vector3.Dot(edge0, toPoint2));
                float f2b = Math.Abs(Vector3.Dot(edge1, toPoint2));
                if (distanceTo2 > f2a + sphere.Radius)
                {
                    return(false);
                }
                if (distanceTo2 > f2a + sphere.Radius)
                {
                    return(false);
                }

                // Proyectar desde el punto 3
                Vector3 toPoint3    = sphere.Position - triangle.Point3;
                float   distanceTo3 = toPoint3.Length();
                toPoint3.Normalize();
                float f3a = Math.Abs(Vector3.Dot(edge1, toPoint3));
                float f3b = Math.Abs(Vector3.Dot(edge2, toPoint3));
                if (distanceTo3 > f3a + sphere.Radius)
                {
                    return(false);
                }
                if (distanceTo3 > f3a + sphere.Radius)
                {
                    return(false);
                }

                return(true);
            }

            return(false);
        }