Jest kilka ostrzeżeń dotyczących mojej odpowiedzi, które jako pierwsze usunę z drogi: dotyczy tylko nieobrotowych obwiedni. Zakłada się, że próbujesz poradzić sobie z problemami z tunelowaniem , tj. Problemami powodowanymi przez obiekty poruszające się z dużą prędkością.
Po zidentyfikowaniu MTV znasz normalną krawędź / powierzchnię, na której musisz przetestować. Znasz również wektor prędkości liniowej przenikającego się obiektu.
Po ustaleniu, że w pewnym momencie w ramce nastąpiło przecięcie, możesz następnie wykonać binarne operacje półetapowe, w oparciu o następujące punkty początkowe: Zidentyfikuj wierzchołek, który penetrował pierwszy podczas ramki:
vec3 vertex;
float mindot = FLT_MAX;
for ( vert : vertices )
{
if (dot(vert, MTV) < mindot)
{
mindot = dot(vert, MTV);
vertex = vert;
}
}
Po zidentyfikowaniu wierzchołka binarny pół krok staje się znacznie tańszy:
//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;
Jest to dość dokładne, ale zapewni tylko jeden punkt zderzenia, w jednym przypadku.
Chodzi o to, że zwykle można z wyprzedzeniem stwierdzić, czy obiekt porusza się wystarczająco szybko na klatkę, aby móc tunelować w ten sposób, dlatego najlepszą wskazówką jest zidentyfikowanie wiodących wierzchołków wzdłuż prędkości i wykonanie testu promieniowego wzdłuż wektora prędkości. W przypadku obracających się obiektów będziesz musiał wykonać binarny krokowy krok pośredni w celu zapewnienia prawidłowego punktu kontaktowego.
Jednak w większości przypadków można bezpiecznie założyć, że większość obiektów w twojej scenie nie porusza się wystarczająco szybko, aby przebić się tak daleko w jednej klatce, więc nie jest konieczne półskokowanie i wystarczające będzie wykrywanie kolizji dyskretnej. Obiekty o dużej prędkości, takie jak pociski, które poruszają się zbyt szybko, aby je zobaczyć, mogą być śledzone promieniami w punktach kontaktowych.
Co ciekawe, ta metoda halfstep może również dać (prawie) dokładny czas wystąpienia obiektu podczas kadru:
float collisionTime = frametimeSeconds * halfstep;
Jeśli wykonujesz jakąś rozdzielczość kolizji fizyki, możesz następnie poprawić pozycję A poprzez:
v - (v*halfstep)
wtedy możesz normalnie wykonywać swoją fizykę. Minusem jest to, że jeśli obiekt porusza się dość szybko, zobaczysz, że teleportuje się z powrotem wzdłuż wektora prędkości.