Há algumas ressalvas na minha resposta, que vou sair primeiro do caminho: lida apenas com caixas delimitadoras não rotativas. Ele pressupõe que você está tentando lidar com problemas de encapsulamento , ou seja, problemas causados por objetos em movimento em alta velocidade.
Depois de identificar a MTV, você conhece a borda / superfície normal na qual precisa testar. Você também conhece o vetor de velocidade linear do objeto interpenetrante.
Depois de estabelecer que, em algum momento do quadro, ocorreu uma interseção, você poderá executar operações binárias de meio passo, com base nos seguintes pontos de partida: Identifique o vértice que penetrou primeiro durante o quadro:
vec3 vertex;
float mindot = FLT_MAX;
for ( vert : vertices )
{
if (dot(vert, MTV) < mindot)
{
mindot = dot(vert, MTV);
vertex = vert;
}
}
Depois de identificar o vértice, a meia etapa binária se torna muito mais barata:
//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;
Isso é razoavelmente preciso, mas fornecerá apenas um único ponto de colisão, em um único caso.
O problema é que geralmente é possível dizer com antecedência se um objeto se moverá rápido o suficiente por quadro para poder fazer um túnel como esse; portanto, o melhor conselho é identificar os vértices principais ao longo da velocidade e fazer um teste de raio ao longo do vetor de velocidade. No caso de objetos rotativos, você precisará executar algum tipo de slerp binário de meia etapa para garantir o ponto de contato correto.
Na maioria dos casos, porém, pode-se supor com segurança que a maioria dos objetos em sua cena não se move rápido o suficiente para penetrar tão longe em um único quadro; portanto, não é necessário meio passo e a detecção de colisão discreta será suficiente. Objetos de alta velocidade, como marcadores, que se movem muito rápido para ver, podem ser rastreados por raios para pontos de contato.
Curiosamente, esse método de meia etapa também pode fornecer o tempo (quase) exato em que o objeto ocorreu durante o quadro:
float collisionTime = frametimeSeconds * halfstep;
Se você estiver executando algum tipo de resolução de colisão física, poderá corrigir a posição de A:
v - (v*halfstep)
então você pode fazer sua física normalmente a partir daí. A desvantagem é que, se o objeto se mover razoavelmente rápido, você o verá se teletransportando de volta ao longo do vetor de velocidade.