일반적으로 쓰이는 AABB collision에 대해서 공부해보려고 합니다
정확한 설명이 좋은 사이트들이 없어서 처음부터 하나하나 개념을 잡아보려합니다.
https://kishimotostudios.com/articles/aabb_collision/
AABB 2D Collision Detection
An example showing how to detect collision between two AABB (Axis-Aligned Bounding Box) in 2D (uses HTML5/JS).
kishimotostudios.com
AABB관한 괜찮은 시뮬레이터입니다 이걸 참고하면서 RECT와 같은 함수를 사용하는게 아니라 vertex들로 이용한
AABB 충돌처리에 대해서 이해해보려합니다.
첫번째 간단한 collsion은 우리가 사각형의 중점을 구하는것입니다.
먼저 앞서 우리는 3개 vertex로 삼각형을 구현할수 있습니다.
DeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
이후 우리는 총 6개의 vertex로 삼각형을 2개를 붙여서 사각형의 형태로 구현합니다. 만약 이부분에 대해서는 dIrect11x <device.cpp> 설명글에 올려두도록 하겠습니다.
앞서 AABB Collision에 간단 충돌처리와 연관된 원과 원의 충돌 처리에 대해서 알아보려합니다.
그 다음 그 두개의 중점 을 가지고 연결하는 방법은 우리가 잘알고는 수학공식인 좌표점의 거리계산입니다.
그렇다면 두점사이에 충돌이 나려면 거리값이 0이 되면 됩니다. 하지만 우리는 원의 충돌이기 때문에 원의 반지름을 기억한다면 두 원의 반지름의 합의 이하값일때 충돌이 발생한다는 사실을 알려주면됩니다.
중점간에 거리 계산 코드
float Distance_caculator(Vertex moveBox, Vertex stopBox) {
float distance_center_to_center;
distance_center_to_center = sqrt(powf(moveBox.Position.x - stopBox.Position.x, 2) + powf(moveBox.Position.y - stopBox.Position.y, 2));
return distance_center_to_center;
}
원이라고 했지만 사실상 사각형 두개에도 적용하면 적용이됩니다. 단지 일부 어느부분에선 닿지않아 충돌처리가 되지 않는 경우가 발생합니다.
아래는 점과점의 거리를 이용한 충돌처리 코드입니다
bool Point_to_Point_Collision_circle(Vertex moveBox, Vertex stopBox,float randomLocation_size, bool bCheck) {
//bool bChecksub = true;
float distance_center_to_center;
distance_center_to_center = Distance_caculator(moveBox, stopBox);//calculator center to center distance
if (distance_center_to_center <= 0.05 + randomLocation_size/2) {
bCheck= false;
}
return bCheck;
}
이제 사각형의 충돌처리를 위한 AABB collision인 vertex를 이용하는 방법에 대해서 해보려고 한다.
AABB 충돌은 각 사각형의 vertex 두점만 알고 있으면된다. 우리는 쉽게 생각해서 맨 왼쪽에 아래쪽에 점과 그리고 맨 오른쪽에 윗점만 알고 있으면된다.
Move박스와 Stop 박스의 회색으로 표시해둔 좌표값을 알아야한다.
Stop box를 기준으로 Stop X1값부터 Stop X2값까지가 바로 Stop box의 좌우의 범위이다. 그렇다면 우리 move box는 y좌표와는 관계없이 Move X1과 X2값을 stop box 좌우값 범위에 넣어주면된다.
그렇게되면 stop X1<= Move X1 <=stop x2 이때와 stop X1<= Move X2 <=stop x2 범위이다 즉 우리는 stop box의 왼쪽과 오른쪽으로 충돌에 대한 범위인 셈이다.
반대로 위 아래에 관한 범위는 stop y1<= Move Y1 <=stop Y2 이때와 stop Y1<= Move Y2 <=stop Y2 이다 그렇다면
이를 코드로 나타낸다면
bCheck &= stopBox[5].Position.x >= moveBox[0].Position.x && stopBox[0].Position.x <= moveBox[0].Position.x+0.1 ; //right collision stop right move left
bCheck &= stopBox[5].Position.y >= moveBox[0].Position.y && stopBox[0].Position.y <= moveBox[0].Position.y+0.1 ; //up collision stop up move down
bCheck &= stopBox[5].Position.x >= moveBox[5].Position.x && stopBox[0].Position.x <= moveBox[5].Position.x+0.1; //left collision stop left move right
bCheck &= stopBox[5].Position.y >= moveBox[5].Position.y && stopBox[0].Position.y <= moveBox[5].Position.y +0.1; //down collision stop down move up
그렇다면 우리는 아마 Stop box안에 Move box가 온전히 들어가야만 한다. 하지만 AABB Collision의 의미는 닿는 순간에 검출하는것이다.
마지막으로 우리가 온전히 들어가는게 아닌 Move box의 크기값을 넣어주면된다. 범위는 그대로 지정되며 크기가 0.1의 정사각혀일 경우 작은 경우에는 -0.1 큰경우에는 +0.1을 해준다면 박스가 온전히 들어가기 전 범위가 될것입니다.
bCheck &= stopBox[5].Position.x >= moveBox[0].Position.x-0.1 && stopBox[0].Position.x <= moveBox[0].Position.x+0.1 ; //right collision stop right move left
bCheck &= stopBox[5].Position.y >= moveBox[0].Position.y-0.1 && stopBox[0].Position.y <= moveBox[0].Position.y+0.1 ; //up collision stop up move down
bCheck &= stopBox[5].Position.x >= moveBox[5].Position.x-0.1 && stopBox[0].Position.x <= moveBox[5].Position.x+0.1; //left collision stop left move right
bCheck &= stopBox[5].Position.y >= moveBox[5].Position.y-0.1 && stopBox[0].Position.y <= moveBox[5].Position.y +0.1; //down collision stop down move up
완성된 AABB 충돌 코드입니다.
bool AABB_Collision_size_first(Vertex* moveBox, Vertex* stopBox, bool bCheck)
{
bCheck = true;
bCheck &= stopBox[5].Position.x >= moveBox[0].Position.x-0.1 && stopBox[0].Position.x <= moveBox[0].Position.x+0.1 ; //right collision stop right move left
bCheck &= stopBox[5].Position.y >= moveBox[0].Position.y-0.1 && stopBox[0].Position.y <= moveBox[0].Position.y+0.1 ; //up collision stop up move down
bCheck &= stopBox[5].Position.x >= moveBox[5].Position.x-0.1 && stopBox[0].Position.x <= moveBox[5].Position.x+0.1; //left collision stop left move right
bCheck &= stopBox[5].Position.y >= moveBox[5].Position.y-0.1 && stopBox[0].Position.y <= moveBox[5].Position.y +0.1; //down collision stop down move up
return bCheck;
}
'프로그래밍언어 > C++' 카테고리의 다른 글
마우스 좌표값 얻어오기 (0) | 2019.09.27 |
---|---|
Save data Text file (0) | 2019.09.20 |
OBB(Object Oriented Bounding Box) Collision (3) | 2019.09.10 |
Translation Matrix (0) | 2019.09.04 |
C++ <Random> (0) | 2019.08.17 |