Hay un par de advertencias en mi respuesta, que primero me saldré del camino: solo trata con cajas de límite no giratorias. Asume que está tratando de lidiar con problemas de túnel , es decir, problemas causados por objetos que se mueven a alta velocidad.
Una vez que haya identificado la MTV, sabrá el borde / superficie normal con la que debe probar. También conoce el vector de velocidad lineal del objeto interpenetrante.
Una vez que haya establecido que en algún momento durante el cuadro, se produjo una intersección, puede realizar operaciones binarias de medio paso, en base a los siguientes puntos de partida: Identifique el vértice que penetró primero durante el cuadro:
vec3 vertex;
float mindot = FLT_MAX;
for ( vert : vertices )
{
if (dot(vert, MTV) < mindot)
{
mindot = dot(vert, MTV);
vertex = vert;
}
}
Una vez que haya identificado el vértice, el medio paso binario se vuelve mucho menos costoso:
//mindistance is the where the reference edge/plane intersects it's own normal.
//The max dot product of all vertices in B along the MTV will get you this value.
halfstep = 1.0f;
vec3 cp = vertex;
vec3 v = A.velocity*framedurationSeconds;
float errorThreshold = 0.01f; //choose meaningful value here
//alternatively, set the while condition to be while halfstep > some minimum value
while (abs(dot(cp,normal)) > errorThreshold)
{
halfstep*=0.5f;
if (dot(cp,normal) < mindistance) //cp is inside the object, move backward
{
cp += v*(-1*halfstep);
}
else if ( dot(cp,normal) > mindistance) //cp is outside, move it forward
{
cp += v*(halfstep);
}
}
return cp;
Esto es razonablemente preciso, pero solo proporcionará un único punto de colisión, en un solo caso.
La cuestión es que, por lo general, es posible saber de antemano si un objeto se moverá lo suficientemente rápido por cuadro como para poder hacer un túnel como este, por lo que el mejor consejo es identificar los vértices principales a lo largo de la velocidad y hacer una prueba de rayos a lo largo del vector de velocidad. En el caso de objetos rotativos, tendrá que hacer algún tipo de slerp binario de medio paso para ensamblar el punto de contacto correcto.
Sin embargo, en la mayoría de los casos, se puede suponer con seguridad que la mayoría de los objetos en su escena no se moverán lo suficientemente rápido como para penetrar tan lejos en un solo cuadro, por lo que no es necesario medio paso, y la detección discreta de colisión será suficiente. Los objetos de alta velocidad como las balas, que se mueven demasiado rápido para ver, se pueden rastrear por puntos de contacto.
Curiosamente, este método de medio paso también puede darle el tiempo (casi) exacto en que ocurrió el objeto durante el marco:
float collisionTime = frametimeSeconds * halfstep;
Si está haciendo algún tipo de resolución de colisión física, puede corregir la posición de A:
v - (v*halfstep)
entonces puedes hacer tu física normalmente desde allí. La desventaja es que si el objeto se mueve razonablemente rápido, lo verá teletransportarse a lo largo de su vector de velocidad.