Bir OBB dışbükey bir gövdedir. Dışbükey bir gövde, yüzeyinde "çatlak" bulunmayan 3D bir şekildir. Dışbükey gövdedeki her "çarpma" (tepe noktası) dışa doğru çıkıntı yapar , asla içe doğru uzanmaz. Bir düzlemi dışbükey bir gövdeden keserseniz, (sadece bir) dışbükey çokgen elde edersiniz. Dışbükey bir teknenin içindeyseniz ve dışa dönük bir lazer atarsanız, gövdenin yüzeyine sadece bir kez (asla iki kez) yumruk atacaksınız .
Ayırıcı Eksen Teoremi testi, dışbükey gövdelerin çarpışmasını tespit etmek için kullanılabilir. SAT testi basittir. 2D ve 3D olarak çalışır. Aşağıdaki resimler 2B olsa da, 3B'ye de kolayca uygulanabilir.
kavram
SAT ile kullandığınız anahtar kavram budur:
- İki şekil, yalnızca her iki şeklin her normal eksenine "yansıtıldığında" çakışırsa kesişir .
1D vektörüne bir şeklin "izdüşümü" şuna benzer (buna "ezilme" diyorum)
Kırmızı verts ve eksen içeren bir şekil
"Şekli eksene yansıtmak", şeklin üzerindeki her noktadan yalnızca eksene inmek için dikey olarak düşmek anlamına gelir. Bunu, her şeyi toplayan ve onu eksene dik olarak ezen bir el ile noktaları "ezmek" olarak düşünebilirsiniz.
Ne kaldı: Eksendeki noktalar
SAT diyor ki:
Kesişen 2 dışbükey gövde için, her eksende üst üste binmek zorundadırlar ( her iki şekildeki her normal, kontrol etmemiz gereken bir eksen olarak sayılır).
Şu 2 şekli al:
Kesişmediklerini görüyorsunuz, bu yüzden çakışma olmadığını göstermek için birkaç ekseni deneyelim .
Pentagonun en normalini denemek:
Bunlar uzantılar. Üst üste biniyorlar.
Dikdörtgenin sol tarafını deneyin. Şimdi bu eksende örtüşmüyorlar, bu nedenle KESİNTİSİZ YOK.
Algoritma:
Her iki şekil için normal olan her yüz için:
- Her iki şeklin tüm köşe köşe noktalarının o eksene yansıtılmasının minimum ve maksimum genişliklerini (en büyük ve en küçük değer) bulun
- Eğer üst üste binmezlerse, kesişme olmaz .
Ve bu gerçekten. SAT çalışmasını sağlayan kod çok kısa ve basittir.
Bir SAT ekseni projeksiyonu nasıl yapılacağını gösteren bazı kodlar:
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;
}
}
Telefon kodu:
// 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 ;
}