예제 #1
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);
        }
예제 #2
0
        /// <summary>
        /// Obtiene si hay intersección entre el rayo y la lista de triángulos
        /// </summary>
        /// <param name="triangleList">Lista de triángulos</param>
        /// <param name="ray">Rayo</param>
        /// <param name="triangle">Devuelve el triángulo de intersección si existe</param>
        /// <param name="intersectionPoint">Devuelve el punto de intersección con el triángulo</param>
        /// <param name="distanceToPoint">Devuelve la distancia desde el origen del ray al punto de intersección</param>
        /// <param name="findNearest">Indica si se debe testear la intersección hasta encontrar el más cercano</param>
        /// <returns>Devuelve verdadero si hay intersección o falso en el resto de los casos</returns>
        public static bool TriangleListAndRay(Triangle[] triangleList, Ray ray, out Triangle?triangle, out Vector3?intersectionPoint, out float?distanceToPoint, bool findNearest)
        {
            triangle          = null;
            intersectionPoint = null;
            distanceToPoint   = null;

            // Indica si ha habido intersección
            bool intersectionOccur = false;

            // Variables para almacenar la interscción más cercana
            Triangle?closestTriangle          = null;
            Vector3? closestIntersectionPoint = null;
            float?   closestDistanceToPoint   = null;

            // Recorremos todos los triángulos de la lista realizando el test de intersección
            foreach (Triangle currentTriangle in triangleList)
            {
                // Variables para almacener la intersección actual
                Vector3?currentIntersectionPoint = null;
                float?  currentDistanceToPoint   = null;

                if (IntersectionTests.TriAndRay(currentTriangle, ray, out currentIntersectionPoint, out currentDistanceToPoint))
                {
                    bool update = false;

                    if (closestDistanceToPoint.HasValue)
                    {
                        // Comprobar si la distancia obtenida en la intersección es más cercana a la obtenida anteriormente
                        if (closestDistanceToPoint.Value > currentDistanceToPoint.Value)
                        {
                            // Actualizar la intersección más cercana
                            update = true;
                        }
                    }
                    else
                    {
                        // No hay intersección todavía, se debe actualizar la intersección más cercana con la obtenida
                        update = true;
                    }

                    if (update)
                    {
                        // Indicar que ha habido una intersección
                        intersectionOccur = true;

                        // Actualizar la información de intersección más cercana
                        closestTriangle          = currentTriangle;
                        closestIntersectionPoint = currentIntersectionPoint;
                        closestDistanceToPoint   = currentDistanceToPoint;

                        if (!findNearest)
                        {
                            // Salimos en la primera intersección
                            break;
                        }
                    }
                }
            }

            if (intersectionOccur)
            {
                // Si ha habido intersección se establece el resultado de la intersección más cercana
                triangle          = closestTriangle;
                intersectionPoint = closestIntersectionPoint;
                distanceToPoint   = closestDistanceToPoint;

                return(true);
            }

            return(false);
        }