Ci sono un paio di avvertenze alla mia risposta, che mi toglierò di mezzo prima: si tratta solo di scatole di delimitazione non rotanti. Si presuppone che si stia tentando di affrontare i problemi di tunneling , ovvero i problemi causati da oggetti che si muovono ad alta velocità.
Una volta identificato l'MTV, conosci il bordo / superficie normale che devi testare. Conosci anche il vettore di velocità lineare dell'oggetto compenetrante.
Una volta stabilito che ad un certo punto durante il frame, si è verificata un'intersezione, è quindi possibile eseguire operazioni binarie di mezzo passo, in base ai seguenti punti di partenza: Identificare il vertice che è penetrato per primo durante il frame:
vec3 vertex;
float mindot = FLT_MAX;
for ( vert : vertices )
{
if (dot(vert, MTV) < mindot)
{
mindot = dot(vert, MTV);
vertex = vert;
}
}
Una volta identificato il vertice, il mezzo passo binario diventa molto meno 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;
Ciò è ragionevolmente accurato, ma fornirà un solo punto di collisione, in un singolo caso.
Il fatto è che di solito è possibile dire in anticipo se un oggetto si sposterà abbastanza velocemente per frame per poter tunnelare in questo modo, quindi il miglior consiglio è quello di identificare i vertici principali lungo la velocità ed eseguire un test del raggio lungo il vettore di velocità. Nel caso di oggetti rotanti, sarà necessario eseguire una sorta di slerp binario a mezzo passo per accertare il punto di contatto corretto.
Nella maggior parte dei casi, tuttavia, si può presumere che la maggior parte degli oggetti nella scena non si muoverà abbastanza velocemente da penetrare fino a quel punto in un singolo fotogramma, quindi non è necessario un mezzo passo e sarà sufficiente il rilevamento discreto delle collisioni. Oggetti ad alta velocità come proiettili, che si muovono troppo velocemente per essere visti, possono essere rintracciati per i punti di contatto.
È interessante notare che questo metodo halfstep può anche darti il tempo (quasi) esatto in cui l'oggetto si è verificato durante il frame:
float collisionTime = frametimeSeconds * halfstep;
Se si sta eseguendo una sorta di risoluzione della collisione fisica, è possibile correggere la posizione di A:
v - (v*halfstep)
allora puoi fare normalmente la tua fisica da lì. Il rovescio della medaglia è che se l'oggetto si muove ragionevolmente velocemente, lo vedrai teletrasportarsi lungo il suo vettore di velocità.