私の答えにはいくつかの注意点があります。最初に邪魔にならないようにしましょう。非回転の境界ボックスのみを扱います。トンネルの問題、つまり高速で移動するオブジェクトに起因する問題に対処しようとしていることを前提としています。
MTVを特定したら、テストする必要があるエッジ/サーフェス法線がわかります。また、相互貫通オブジェクトの線速度ベクトルも知っています。
あなたがでていることを確立した後、いくつかのポイントフレームの間に、交差点が発生しました、あなたはその後、以下の出発点に基づいて、バイナリハーフステップの操作を実行できます。フレームの間に第1の浸透というの頂点を識別します。
vec3 vertex;
float mindot = FLT_MAX;
for ( vert : vertices )
{
if (dot(vert, MTV) < mindot)
{
mindot = dot(vert, MTV);
vertex = vert;
}
}
頂点を特定したら、バイナリハーフステップのコストははるかに低くなります。
//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;
これはかなり正確ですが、単一の場合に単一の衝突点のみを提供します。
問題は、通常、オブジェクトがこのようにトンネルを通過するのに十分な速度でフレームごとに移動するかどうかを事前に知ることができるため、最良のアドバイスは、速度に沿って先頭の頂点を特定し、速度ベクトルに沿って光線テストを行うことです。オブジェクトを回転させる場合、正しい接触点をアサートするには、何らかのバイナリハーフステップslerpを実行する必要があります。
ただし、ほとんどの場合、シーン内のほとんどのオブジェクトは単一フレームでそこまで浸透するのに十分な速度で移動しないため、ハーフステップは不要であり、個別の衝突検出で十分であると安全に想定できます。弾丸のように高速で見にくいオブジェクトは、接触点でレイトレースできます。
興味深いことに、このハーフステップメソッドは、フレーム中にオブジェクトが発生した(ほぼ)正確な時間も提供できます。
float collisionTime = frametimeSeconds * halfstep;
何らかの物理衝突解決を行っている場合は、次の方法でAの位置を修正できます。
v - (v*halfstep)
そこから普通に物理学を行うことができます。欠点は、オブジェクトが適度に高速で移動すると、速度ベクトルに沿ってテレポートして戻ることです。