DirectX/DirectX 2D_(구)

DX_Collider [3 / 3] OBB 충돌

컴맹학자 2021. 1. 26. 23:22
728x90

OBB(Object Oriented Bounding Box) 의 이론과 설명 코드는 아래 사이트에서 참고 하면 되고

 

kwaksh2319.tistory.com/46

 

OBB(Object Oriented Bounding Box) Collision

OBB충돌을 이해하기 위해서 조금 시간이 걸리긴 했지만 외국 사이트 내용이 생각보다 쉽지 않아서 국내 블로그를 전전하다가 굉장히 설명이 잘되있는곳을 알게 되었습니다. 링크:http://www.gingaming

kwaksh2319.tistory.com

 

쓰는 목적은 다음과 같다

1. 실시간 그림 크기에 맞는 바인딩 박스

2. 회전하든 상관 없이 중심점과 중심점 기준으로 바인딩 박스 영역 충돌


코드

더보기

Collider.cpp 내용물 추가

//그림끼리 충돌 판정
bool Collider::Obb(Sprite * a, Sprite * b)
{
	ObbDesc A, B;
	D3DXVECTOR2 halfSize; //절반

	halfSize = D3DXVECTOR2(a->Scale().x * a->TextureSize().x, a->Scale().y * a->TextureSize().y) * 0.5f;
	halfSize = D3DXVECTOR2(b->Scale().x * b->TextureSize().x, b->Scale().y * b->TextureSize().y) * 0.5f;

	CreateObb(&A, halfSize, a->World());
	CreateObb(&B, halfSize, b->World());

	//거리 (중심점 - 중심점)
	D3DXVECTOR2 distance = a->Position() - b->Position();

	//A.Right축 검사
	float lengthA = D3DXVec2Length(&A.Length_Right);  // A 길이
	float lenghtB = SeparateAxis(A.Right, B.Length_Right, B.Length_Up); // B 길이
	float length = fabsf(D3DXVec2Dot(&A.Right, &distance)); //a의 오른쪽 정규화 백터와 distance 내적값
	if (length > lengthA + lenghtB) return false; //length 크면 충돌 x

	//A.Up축 검사
	lengthA = D3DXVec2Length(&A.Length_Up);
	lenghtB = SeparateAxis(A.Up, B.Length_Right, B.Length_Up);
	length = fabsf(D3DXVec2Dot(&A.Up, &distance));
	if (length > lengthA + lenghtB) return false;

	//B.Right축 검사
	lengthA = D3DXVec2Length(&B.Length_Right);
	lenghtB = SeparateAxis(B.Right, A.Length_Right, A.Length_Up);
	length = fabsf(D3DXVec2Dot(&B.Right, &distance));
	if (length > lengthA + lenghtB) return false;

	//B.Up축 검사
	lengthA = D3DXVec2Length(&B.Length_Up);
	lenghtB = SeparateAxis(B.Up, A.Length_Right, A.Length_Up);
	length = fabsf(D3DXVec2Dot(&B.Up, &distance));
	if (length > lengthA + lenghtB) return false;

	return true;
}

void Collider::CreateObb(ObbDesc * out, D3DXVECTOR2 & half, D3DXMATRIX & transform)
{
	D3DXVec2Normalize(&out->Right, &D3DXVECTOR2(transform._11, transform._12)); // x 방향 노멀 백터
	D3DXVec2Normalize(&out->Up, &D3DXVECTOR2(transform._21, transform._22));    // y 방향 노멀 백터

	out->HalfSize = half;
	out->Length_Right = out->Right * out->HalfSize.x; //x 정규화 * 오브젝트의 반 = 길이
	out->Length_Up = out->Up * out->HalfSize.y;
}

//갈라진 중심 선
float Collider::SeparateAxis(D3DXVECTOR2 & init, D3DXVECTOR2 & e1, D3DXVECTOR2 & e2)
{
	//실수형 절대값 (내적) + (내적)
	return fabsf(D3DXVec2Dot(&init, &e1)) + fabsf(D3DXVec2Dot(&init, &e2));
}

 

Collider.h 내용물 추가

private:
	struct ObbDesc
	{
		D3DXVECTOR2 HalfSize;

		D3DXVECTOR2 Right;
		D3DXVECTOR2 Up;

		D3DXVECTOR2 Length_Right;
		D3DXVECTOR2 Length_Up; 
	};

public:
	static bool Obb(Sprite* a, Sprite* b);

private:
	static void CreateObb(ObbDesc* out, D3DXVECTOR2& half, D3DXMATRIX& transform);
	static float SeparateAxis(D3DXVECTOR2& init, D3DXVECTOR2& e1, D3DXVECTOR2& e2);

해당 영역이 핵심 코드이고 이건 나름대로 각 변수 마다 왜 써야 하는지에 따른 나름 해석


OBB 관련 설명해주는 사이트 들어가도 사실 약간 이해가 안되지만 나름(?) 해석한걸로 대치해서 보니 조금씩

 

이해가 되는거 같다. 따로 실행 관련은 이전 게시글에서 AABB 충돌에서 OBB충돌로 바꿔주면 되기 때문에 올리지 않음

'DirectX > DirectX 2D_(구)' 카테고리의 다른 글

DX_Collider [2 / 3] AABB 충돌  (0) 2021.01.20
DX_Collider [1 / 3]  (0) 2021.01.18
DX_카메라 시점변환  (0) 2021.01.05
DX_Move  (0) 2020.12.23
DX_Keyboard  (0) 2020.12.21