/// <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); }
/// <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); }