충돌 검사 ( AABB, CC, CB )

묘르·2024년 9월 9일

물리엔진

목록 보기
1/3


1. AABB (회전되지 않은 사각형)

bool CollisionManager::AABB(Collider* _iCollider, Collider* _jCollider)
{
	Vector2 posi = _iCollider->getPosition();
	Vector2 posj = _jCollider->getPosition();
	float hieghti = _iCollider->getHalfHeight();
	float widthi = _iCollider->getHalfWidth();
	float hieghtj = _jCollider->getHalfHeight();
	float widthj = _jCollider->getHalfWidth();

	if (fabs(posi.x - posj.x) <= (widthi + widthj)
		&& fabs(posi.y - posj.y) <= (hieghti + hieghtj))
	{
		return true;
	}

	return false;
}

두 사각형의 y좌표가 같고, 사각형 i와 j 사이의 x축 상의 거리가 각각의 너비 절반을 더한 것과 같다고 했을 때의 모습은 두 사각형의 변이 딱 맞붙어있는 형태일 것이다. 여기서 서로의 거리가 더 가까워지면 겹쳐있는 형태가 될 것이고, 멀어진다면 서로 떨어져있는 형태가 될 것이다.
이 원리를 이용하면 꼭짓점의 좌표끼리 비교하는 방법에 비해 연산이 줄어들어 더 효율적으로 계산이 가능하다.


2. CC (원)

bool CollisionManager::CC(Collider* _iCollider, Collider* _jCollider)
{
	Vector2 posi = _iCollider->getPosition();
	Vector2 posj = _jCollider->getPosition();
	float ri = _iCollider->getRadius();
	float rj = _jCollider->getRadius();

	float distance = Distance(posi, posj);
	if (distance <= (ri + rj))
	{
		return true;
	}
	return false;
}

3. CB (원과 사각형)

bool CollisionManager::CB(Collider* _iCollider, Collider* _jCollider)
{
	//앞(i) : BOX, 뒤(j) : CIRCLE
	float radian = _iCollider->getRotation() * ((float)M_PI / 180.f);
	float r = _jCollider->getRadius(); //반지름
	Vector2 bCenter = _iCollider->getPosition();
	Vector2 cCenter = _jCollider->getPosition();
	float halfWidth = _iCollider->getHalfWidth();
	float halfHeight = _iCollider->getHalfHeight();


	//회전된 원의 좌표를 구한다
	cCenter = cCenter - bCenter;
	Vector2 origin = cCenter;
	cCenter.x = origin.x * cos(-radian) - origin.y * sin(-radian);
	cCenter.y = origin.x * sin(-radian) + origin.y * cos(-radian);
	cCenter = cCenter + bCenter;


	//자주 쓸 좌표를 저장해둔다.
	vector<float> xs = { //작은 것 -> 큰 것 순서로 저장.
		bCenter.x - halfWidth - r,
		bCenter.x - halfWidth,
		bCenter.x + halfWidth,
		bCenter.x + halfWidth + r
	};

	vector<float> ys = {
		bCenter.y - halfHeight - r,
		bCenter.y - halfHeight,
		bCenter.y + halfHeight,
		bCenter.y + halfHeight + r
	};
	
	// 사각형에 반지름을 더한 큰 영역안에 원이 있는지
	if(xs[0] <= cCenter.x && cCenter.x <= xs[3] && ys[0] <= cCenter.y && cCenter.y <= ys[3])
	{
		//4개의 양 끝점
		if(xs[0] <= cCenter.x && cCenter.x <= xs[1] //좌상단
			&& ys[0] <= cCenter.y && cCenter.y <= ys[1])
		{
			if(Distance(bCenter, Vector2(xs[1], ys[1])) <= r) return true;
		}
		else if(xs[2] <= cCenter.x && cCenter.x <= xs[3] //우상단
			&& ys[0] <= cCenter.y && cCenter.y <= ys[1])
		{
			if(Distance(bCenter, Vector2(xs[2], ys[1])) <= r) return true;
		}
		else if(xs[0] <= cCenter.x && cCenter.x <= xs[1] //좌하단
			&& ys[2] <= cCenter.y && cCenter.y <= ys[3])
		{
			if(Distance(bCenter, Vector2(xs[1], ys[2])) <= r) return true;
		}
		else if(xs[2] <= cCenter.x && cCenter.x <= xs[3] //우하단
			&& ys[2] <= cCenter.y && cCenter.y <= ys[3])
		{
			if(Distance(bCenter, Vector2(xs[2], ys[2])) <= r) return true;
		}
        else 
        {
        	return true;
		}
    }

	return false;
}


평면을 사각형을 기준으로 회전시켜서 회전되지 않은 사각형을 만든 뒤 계산하면 된다.

profile
안녕하세요 :)

0개의 댓글