예제 #1
0
        /// <summary>
        /// Detecta la colisión entre caja y plano
        /// </summary>
        /// <param name="box">Caja</param>
        /// <param name="plane">Plano</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 BoxAndHalfSpace(CollisionBox box, CollisionPlane plane, ref CollisionData data)
        {
            if (data.ContactsLeft <= 0)
            {
                // Si no hay más contactos disponibles se sale de la función.
                return(false);
            }

            // Comprobar la intersección
            if (!IntersectionTests.BoxAndHalfSpace(box, plane))
            {
                return(false);
            }

            // Hay intersección, ahora hay que encontrar los puntos de intersección.
            // Podemos hacerlo únicamente chequeando los vértices.
            // Si la caja está descansando sobre el plano o un eje, se reportarán cuatro o dos puntos de contacto.

            uint contactsUsed = 0;

            for (int i = 0; i < 8; i++)
            {
                // Calcular la positición de cada vértice
                Vector3 vertexPos = box.GetCorner(i);

                // Calcular la distancia al plano
                float vertexDistance = Vector3.Dot(vertexPos, plane.Normal);

                // Comparar las distancias
                if (vertexDistance <= plane.D)
                {
                    // Crear la información del contacto.

                    // El punto de contacto está a medio camino entre el vértice y el plano.
                    // Se obtiene multiplicando la dirección por la mitad de la distancia de separación, y añadiendo la posición del vértice.
                    Contact contact = data.CurrentContact;
                    contact.ContactPoint  = vertexPos;
                    contact.ContactNormal = plane.Normal;
                    contact.Penetration   = plane.D - vertexDistance;

                    // Establecer los datos del contacto
                    RigidBody one = box.Body;
                    RigidBody two = null;
                    contact.SetBodyData(ref one, ref two, data.Friction, data.Restitution);

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

                    contactsUsed++;
                    if (contactsUsed == data.ContactsLeft)
                    {
                        return(true);
                    }
                }
            }

            return(true);
        }
예제 #2
0
        /// <summary>
        /// Detecta la colisión entre caja y triángulo
        /// </summary>
        /// <param name="box">Caja</param>
        /// <param name="tri">Triángulo</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 BoxAndTriangle(CollisionBox box, Triangle tri, ref CollisionData data)
        {
            bool intersectionExists = false;

            if (data.ContactsLeft <= 0)
            {
                // Si no hay más contactos disponibles se sale de la función.
                return(false);
            }

            // Hay intersección, ahora hay que encontrar los puntos de intersección.
            // Podemos hacerlo únicamente chequeando los vértices.
            // Si la caja está descansando sobre el plano o un eje, se reportarán cuatro o dos puntos de contacto.
            for (int i = 0; i < 8; i++)
            {
                // Calcular la positición de cada vértice
                Vector3 vertexPos = box.GetCorner(i);

                // Calcular la distancia al plano
                float distanceToPlane = tri.Plane.Distance(vertexPos);
                if (distanceToPlane <= 0f)
                {
                    // Si la distancia es negativa está tras el plano. Si es 0, está en el plano

                    // Intersección entre línea y triángulo
                    Vector3 direction = Vector3.Normalize(box.Position - vertexPos);
                    Ray     r         = new Ray(vertexPos, direction);
                    if (IntersectionTests.TriAndRay(tri, r))
                    {
                        intersectionExists = true;

                        // Crear la información del contacto.

                        // El punto de contacto está a medio camino entre el vértice y el plano.
                        // Se obtiene multiplicando la dirección por la mitad de la distancia de separación, y añadiendo la posición del vértice.
                        Contact contact = data.CurrentContact;
                        contact.ContactPoint  = vertexPos;
                        contact.ContactNormal = tri.Plane.Normal;
                        contact.Penetration   = -distanceToPlane;

                        // Establecer los datos del contacto
                        RigidBody one = box;
                        RigidBody two = null;
                        contact.SetBodyData(ref one, ref two, data.Friction, data.Restitution);

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

                        if (data.ContactsLeft <= 0)
                        {
                            return(true);
                        }
                    }
                }
            }

            return(intersectionExists);
        }