DX11

Box2D To Pixel 충돌

TIN9 2022. 1. 5.
반응형

빨간 사각형을 Box2D 파란 사각형을 Pixel Texture라고 가정

크게 3가지의 틀로 나누어서 이미지 구성을 하였음

자세한 내용은 코드로 확인

1 서로의 겹치는부분의 교집합을 구해서 사각형을 만든다
2. 교집합으로 구한 사각형을 픽셀의 LB값을 빼주어 상대적인 0,0지점의 좌표로 만들어준다.
3. 이미지의 경우 좌상단이 0, 0이기 때문에 이미지의 세로 크기에서 각각의 Top, Bottom을 빼준다.

// 박스 To 픽셀 충돌
bool CCollision::CollisionBox2DToPixel(CollisionResult& SrcResult, CollisionResult& DestResult, const Box2DInfo& Src, const PixelInfo& Dest)
{
	// 박스 To 박스가 있는지 먼저 판단을 해야한다.
	if (!CollisionBox2DToBox2D(SrcResult, DestResult, Src, Dest.Box))
		return false;

	// 교집합을 구한다.
	float Left = Src.Min.x < Dest.Min.x ? Dest.Min.x : Src.Min.x;
	float Right = Src.Max.x > Dest.Max.x ? Dest.Max.x : Src.Max.x;

	float Bottom = Src.Min.y < Dest.Min.y ? Dest.Min.y : Src.Min.y;
	float Top = Src.Max.y > Dest.Max.y ? Dest.Max.y : Src.Max.y;
	
	// 월드 공간에서의 좌 하단 좌표를 구한다.
	// 센터에서 절반의 x,y를 빼준다.
	Vector2 LB = Dest.Box.Center - Dest.Box.Length;

	// 원점에서의 상대 좌표를 구해준다.
	Left -= LB.x;
	Right -= LB.x;

	Bottom -= LB.y;
	Top -= LB.y;

	// Left와 Bottom은 절대로 0이 되어서는 안된다 예외처리
	Left = Left < 0.f ? 0.f : Left;
	Bottom = Bottom < 0.f ? 0.f : Bottom;

	// Right와 Top은 절대 픽셀이미지의 가로와 세로크기를 넘어서면 안된다.
	Right = Right >= (float)Dest.Width ? (float)Dest.Width - 1.f : Right;
	Top = Top >= (float)Dest.Height ? (float)Dest.Height - 1.f : Top;

	// 이미지는 좌상단부터 시작이기 때문에
	// 픽셀공간으로의 좌표를 구해준다.

	Top = Dest.Height - Top;
	Bottom = Dest.Height - Bottom;

	bool	Collision = false;

	// 교집합 구간을 반복한다.
	for (int y = (int)Top; y < (int)Bottom; ++y)
	{
		for (int x = (int)Left; x < (int)Right; ++x)
		{
			// 색상정보도 있기 때문에 * 4를 한다
			int Index = y * (int)Dest.Width * 4 + x * 4;

			// 현재 인덱스의 픽셀이 상대방 박스 안에 존재하는지를 판단한다.
			// 현재 픽셀을 월드공간에서의 위치를 구해준다.
			// y 가 뒤집혀 있기 때문에 다시 뒤집어서 월드공간에서의 픽셀 위치를 구해준다.
			Vector2	 PixelWorldPos = LB + Vector2((float)x, (float)Dest.Height - y);

			// 충돌이 안되었다면 continue해준다.
			// 픽셀이 박스 안에 들어왔는지 체크를 하는것
			if (!CollisionBox2DToPoint(SrcResult, DestResult, Src, PixelWorldPos))
				continue;
			
			// 통과해서 여기까지 왔다면 체크를 해야한다.
			switch (Dest.Type)
			{
			case PixelCollision_Type::Color_Ignore:
				// 픽셀 인덱스의 컬러와 데스트의 컬러색상이 동일하면 Ignore이니깐 continue를 한다
				if (Dest.Pixel[Index] == Dest.Color[0] &&
					Dest.Pixel[Index + 1] == Dest.Color[1] &&
					Dest.Pixel[Index + 2] == Dest.Color[2])
					continue;

				// 그게 아니라면 충돌이 된것이다.
				Collision = true;
				break;
			case PixelCollision_Type::Color_Confirm:
				// 픽셀 인덱스의 컬러와 데스트의 컬러색상이 동일하면 Copnfirm이니깐 Collision을 true한다
				if (Dest.Pixel[Index] == Dest.Color[0] &&
					Dest.Pixel[Index + 1] == Dest.Color[1] &&
					Dest.Pixel[Index + 2] == Dest.Color[2])
					Collision = true;
				break;
			case PixelCollision_Type::Alpha_Ignore:
				// 픽셀 인덱스의 알파와 데스트의 알파색상이 동일하면 Ignore이니깐 continue를 한다
				if (Dest.Pixel[Index + 3] == Dest.Color[3])
					continue;

				Collision = true;
				break;
			case PixelCollision_Type::Alpha_Confirm:
				// 픽셀 인덱스의 알파와 데스트의 알파색상이 동일하면 Copnfirm이니깐 Collision을 true한다
				if (Dest.Pixel[Index + 3] == Dest.Color[3])
					Collision = true;
				break;
			}

			if (Collision)
				break;
		}

		if (Collision)
			break;
	}

	return Collision;
}
반응형

'DX11' 카테고리의 다른 글

01 - 10 ~ 01 - 11 UI충돌 / Sound(FMOD)  (0) 2022.01.12
Box2D To Point 충돌  (0) 2022.01.05
원 충돌(코드)  (0) 2022.01.02
obb 충돌 관련(코드)  (0) 2022.01.02
2021-11-29 DX11 DInput관련  (0) 2021.11.29

댓글