2つのバウンディングボックスオブジェクトがあり、それぞれがボックス内の現在の頂点をベクトルに格納し、オブジェクトのすべての頂点が共通の軸に対して回転および変換されているとします。
ここに私の問題を説明するための画像があります:
2つのOBBがリンクをオーバーラップしている場合、どうすれば問題の解決策を説明するのに役立つのでしょうか。複雑すぎることはありません...
2つのバウンディングボックスオブジェクトがあり、それぞれがボックス内の現在の頂点をベクトルに格納し、オブジェクトのすべての頂点が共通の軸に対して回転および変換されているとします。
ここに私の問題を説明するための画像があります:
2つのOBBがリンクをオーバーラップしている場合、どうすれば問題の解決策を説明するのに役立つのでしょうか。複雑すぎることはありません...
回答:
OBBは凸包です。凸包は、表面に「割れ目」のない3D形状です。凸包のすべての「バンプ」(頂点)は外側に突き出ており、内側には突き出ていません。凸包を通る平面をスライスすると、(1つのみ)凸多角形が得られます。凸包の内側にいて、外側に向かってレーザーを発射すると、船体の表面を1回だけ(2回は)パンチしません。
軸分離定理テストを使用して、凸包の衝突を検出できます。SATテストは簡単です。2Dおよび3Dで動作します。以下の写真は2Dですが、3Dにも簡単に適用できます。
これは、SATで使用している重要な概念です。
1Dベクトルへの形状の「投影」は次のようになります(「クラッシュ」と呼びます)
赤い頂点のある形状と軸
「形状を軸に投影する」とは、形状の各点から垂線を落として軸に着地することを意味します。これは、すべてを集めて軸に垂直に押しつぶす手でポイントを「つぶす」と考えることができます。
残っているもの:軸上の点
2つの凸包を交差させるには、すべての軸で重なり合う必要があります(いずれかの形状のすべての法線が軸としてカウントされる必要があるため)。
次の2つの形を取ります。
交差していないので、オーバーラップが発生しなかったことを示すために、いくつかの軸を試してみましょう。
五角形の一番上の法線を試す:
これらはエクステントです。それらは重なります。
長方形の左側を試してください。現在、これらはこの軸でオーバーラップしていないため、交差はありません。
両方の形状の法線の各面に対して:
そしてそれは本当にそれです。SATを機能させるためのコードは非常に短くシンプルです。
以下は、SAT軸投影を行う方法を示すコードです。
void SATtest( const Vector3f& axis, const vector<Vector3f>& ptSet, float& minAlong, float& maxAlong )
{
minAlong=HUGE, maxAlong=-HUGE;
for( int i = 0 ; i < ptSet.size() ; i++ )
{
// just dot it to get the min/max along this axis.
float dotVal = ptSet[i].dot( axis ) ;
if( dotVal < minAlong ) minAlong=dotVal;
if( dotVal > maxAlong ) maxAlong=dotVal;
}
}
呼び出しコード:
// Shape1 and Shape2 must be CONVEX HULLS
bool intersects( Shape shape1, Shape shape2 )
{
// Get the normals for one of the shapes,
for( int i = 0 ; i < shape1.normals.size() ; i++ )
{
float shape1Min, shape1Max, shape2Min, shape2Max ;
SATtest( normals[i], shape1.corners, shape1Min, shape1Max ) ;
SATtest( normals[i], shape2.corners, shape2Min, shape2Max ) ;
if( !overlaps( shape1Min, shape1Max, shape2Min, shape2Max ) )
{
return 0 ; // NO INTERSECTION
}
// otherwise, go on with the next test
}
// TEST SHAPE2.normals as well
// if overlap occurred in ALL AXES, then they do intersect
return 1 ;
}
bool overlaps( float min1, float max1, float min2, float max2 )
{
return isBetweenOrdered( min2, min1, max1 ) || isBetweenOrdered( min1, min2, max2 ) ;
}
inline bool isBetweenOrdered( float val, float lowerBound, float upperBound ) {
return lowerBound <= val && val <= upperBound ;
}
その他のSATの記事。
このサイトの最後の記事には完全なコードが付属しています.FLASHにあると思いますが、私は知りませんが、SATを初めて使用する必要があったときにC ++に変換する際に問題がまったくありませんでした他の言語についても同じことを行います。追加する必要があるのは、各計算で変位ベクトルを保存することだけです(最小の場合はもちろん、SATについて学習するとこれを理解できます)。このチュートリアルのコードはそれを行いません。最終的に計算されたベクトルになります。
http://rocketmandevelopment.com/tag/separation-axis-theorem/
良い、古いNゲームチュートリアル。ウェブ上で最高のSAT理論。