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); }
/// <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> /// Does an intersection test on an arbitrarily aligned box and a /// half-space. /// /// The box is given as a transform matrix, including /// position, and a vector of half-sizes for the extend of the /// box along each local axis. /// /// The half-space is given as a direction (i.e. unit) vector and the /// offset of the limiting plane from the origin, along the given /// direction. /// </summary> public static bool BoxAndHalfSpace(CollisionBox box, CollisionPlane plane) { // Work out the projected radius of the box onto the plane direction float projectedRadius = TransformToAxis(box, plane.Normal); // Work out how far the box is from the origin float boxDistance = Vector3.Dot(plane.Normal, box.Position) - projectedRadius; // Check for the intersection if (boxDistance <= plane.D) { return(true); } return(false); }
/// <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); }
/// <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); }
/// <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); }
/// <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, CollisionPlane plane) { return(SphereAndPlane(sphere, plane.Normal, plane.D) == 0); }
/// <summary> /// Detecta la intersección entre una caja y un plano /// </summary> /// <param name="box">Caja</param> /// <param name="plane">Plano</param> /// <returns>Devuelve verdadero si hay intersección</returns> public static bool BoxAndPlane(CollisionBox box, CollisionPlane plane) { return(BoxAndPlane(box, plane.Normal, plane.D)); }