Một OBB là một thân tàu lồi. Một thân tàu lồi là một hình dạng 3D không có "vết nứt" trên bề mặt của nó. Mỗi "vết sưng" (đỉnh) trên thân lồi nhô ra ngoài , không bao giờ hướng vào trong. Nếu bạn cắt một mặt phẳng qua thân tàu lồi, bạn sẽ nhận được (chỉ một) đa giác lồi. Nếu bạn ở trong thân tàu lồi và bắn tia laser hướng ra ngoài, bạn sẽ chỉ đấm qua bề mặt thân tàu một lần (không bao giờ hai lần).
Phép thử Định lý trục tách có thể được sử dụng để phát hiện sự va chạm của vỏ lồi. Bài kiểm tra SAT rất đơn giản. Nó hoạt động trong 2D và 3D. Mặc dù các hình ảnh dưới đây sẽ ở dạng 2D, nhưng chúng có thể dễ dàng được áp dụng cho 3D.
Khái niệm
Đây là khái niệm chính bạn đang sử dụng với SAT:
- Hai hình chỉ giao nhau nếu chúng trùng nhau khi "chiếu" lên mọi trục bình thường của cả hai hình .
"Phép chiếu" của hình trên vectơ 1D trông như thế này (cái mà tôi gọi là "nghiền")
Một hình với các câu màu đỏ và một trục
"Chiếu hình tới trục" có nghĩa là thả vuông góc từ mỗi điểm trên hình chỉ để hạ cánh trên trục. Bạn có thể nghĩ về điều này như "nghiền nát" các điểm bằng một bàn tay tập hợp mọi thứ và vuông góc nghiền nó xuống trục.
Những gì bạn còn lại với: Điểm trên một trục
SAT nói:
Để 2 thân tàu lồi giao nhau, chúng phải chồng lên nhau trên mọi trục (trong đó mọi hình bình thường trên một trong hai hình đều được tính là một trục chúng ta phải kiểm tra).
Lấy 2 hình dạng sau:
Bạn thấy chúng không giao nhau, vì vậy hãy thử một vài trục để hiển thị là sự trùng lặp không xảy ra.
Cố gắng bình thường hàng đầu của hình ngũ giác:
Đây là những phạm vi. Họ làm chồng chéo lên nhau.
Hãy thử bên trái của hình chữ nhật. Bây giờ chúng không trùng nhau trong trục này, do đó KHÔNG CÓ TƯƠNG TÁC.
Thuật toán:
Đối với mỗi khuôn mặt bình thường trên cả hai hình dạng:
- Tìm phạm vi tối thiểu và tối đa (giá trị lớn nhất và nhỏ nhất) của hình chiếu của tất cả các điểm góc đỉnh của cả hai hình trên trục đó
- Nếu chúng không trùng nhau, không có giao lộ .
Và đó thực sự là nó. Mã để làm cho SAT hoạt động rất ngắn và đơn giản.
Dưới đây là một số mã trình bày cách thực hiện phép chiếu trục 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;
}
}
Mã gọi:
// 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 ;
}