카메라 컴포넌트의 설계

2020. 3. 28. 23:43개발일지

 - 카메라 구현 설계

카메라를 구현 전에 다음 두가지를 염두해 두고 방법들을 생각해 보았다.

1. 씬의 모든 액터들이 카메라의 위치를 알아야 렌더 위치 결정 가능.

2. 여러개의 카메라도 생성 가능하고 카메라 전환이 가능하게 구현.

 

생각난 방법은 다음 세가지였다.

  1. 컴포넌트로 플레이어가 가지게 하고, 플레이어의 카메라를 모든 액터들이 알게 한다.
    -> 플레이어가 없는 씬에 대한 예외처리가 들어가야 한다.

  2. 컴포넌트 하지 않고 씬이 가지게 있게 한다.
    -> 씬에 카메라가 하나라면 좋은 방법이지만, 맵의 카메라 등 카메라를 여러개 설치하려면 각각의 클래스에 모두 카메라 로직을 구현해야 한다.

  3. 컴포넌트로 씬이 가지게 있게 한다.
    -> 이렇게 하면 액터들은 씬의 카메라를 찾아서 일괄적으로 처리할 수 있고, 씬 이외에 맵 등 다른 카메라의 사용도 용이하다.

3번 방법이 가장 적절하다고 생각되었지만, 현재 프로젝트의 프레임워크에서 

씬이 액터를 생성/관리하고 액터는 컴포넌트를 생성/소유 할 수 있었기때문에 

소유하는 액터가 있어야만 하고 씬이 직접 생성하지 못하는 문제를 해결해야 했다.

  1. 카메라를 컴포넌트로 구현
    -> 소유하는 액터가 있어야만 하고 씬이 소유하지 못한다. 씬도 컴포넌트를 소유하고 관리하게 하면
    액터와의 기능이 중복되고 관리하기 까다로워 질 수 있다.

  2. 씬이 가질 수 있고 액터는 가지지 못하는 씬 컴포넌트 클래스를 만든다.
    -> 특정 액터를 기준으로 삼는 카메라를 만들 수 없다.

  3. 컴포넌트와 액터클래스를 하위클래스로 가지는 부모 클래스를 만들고 씬은 그 오브젝트를 생성하게 한다
    -> 액터와 컴포넌트 클래스들의 상속관계를 다시 구조해야 하고 상속관계가 깊어지므로 피하고 싶다.

위의 어느 방법도 좋은 방법으로는 보이지 않아 고민한 결과, 씬에는 적어도 카메라가 하나는 있어야 한다는 점을 생각해 씬이 소유하는 SceneCamera 오브젝트를 만들고 거기서 카메라 컴포넌트를 만들도록 설계했다. 이렇게 하면 씬 카메라 뿐만 아니라 씬이 아닌 액터에 종속된 카메라도 생성 가능하다. 

모든 액터들은 씬 카메라를 찾아서 렌더링 할 수 있는 일관성이 생기고, 카메라가 교체될땐 씬 카메라에서 소유한 카메라 컴포넌트의 포인터를 바꾸기만 하면 된다.

 

SceneCamera 오브젝트의 헤더.

//ASceneCamera.h
class ACameraComponent;
class ASceneCamera : public AGAMEACTOR
{
public:
	ASceneCamera(AGAMESCENEBASE* _ParentScene = nullptr);
	virtual ~ASceneCamera() {}

protected:
	//액터들이 현재 기준으로 삼을 씬 카메라 컴포넌트
    //씬의 모든 액터들은 이 카메라를 기준으로 렌더링 위치를 결정한다.
	ACameraComponent* CurrentCamera; 
    //카메라들을 저장해 놓을 해쉬맵. 카메라를 교체할때 포인터만 바꾸어 주면 된다.
	std::unordered_map<std::string, ACameraComponent*> CameraMap;

public:
	ACameraComponent* GetCurrentCamera() { return CurrentCamera; }
	AVECTOR GetWorldPos();
	AVECTOR GetRelativePos();
	void SetWorldPos(const AVECTOR& _NewPos);
	void SetRelativePos(const AVECTOR& _NewPos);
	void MoveCamera(const AVECTOR& _MoveVec);
	
    //카메라를 이름으로 찾아 스왑한다.
	ACameraComponent* SwapCamera(std::string _CameraName);
};

 

씬의 최상위 클래스가 ASceneCamera 포인터를 멤버로 가지게 했다.

해당 씬의 모든 액터들은 이 카메라에 접근해 렌더 위치를 결정할 수 있다.

//AGAMESCENEBASE.h
//...

class AGAMESCENEBASE
{
public:
	ASceneCamera* SceneCamera;
    
/////

 

모든 액터들은 카메라 전환에 따른 개별적인 처리 없이 씬 카메라에 접근해 렌더 위치를 결정할 수 있다.

//ARENDERBASE.h
AVECTOR ARENDERBASE::GetRenderCameraPos()
{
	AVECTOR CameraCoord = GetWorldPos() - m_OwnerActor->GetParentScene()->SceneCamera->GetWorldPos();
	AVECTOR Pos = HGAMEWINDOW::MainWindow()->WorldPosToWindowPos(CameraCoord);
	return { Pos.IX() - m_Size.HIX(), Pos.IY() - m_Size.HIY() };
}

'개발일지' 카테고리의 다른 글

랜덤 몬스터 스폰  (0) 2020.04.04
랜덤맵 제작 3  (0) 2020.04.03
랜덤맵 제작 2  (0) 2020.04.03
랜덤맵 제작 1  (0) 2020.04.01
명령패턴을 활용한 이동 구현  (0) 2020.03.29