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