glm을 왼손 좌표계로 설정하기

2023. 11. 8. 14:25뚝딱뚝딱 만들기 Devlog/게임엔진 (Ramensoup)

assimp를 이용해 3D 모델을 읽어서 작업하던 중,

라이팅 작업에 들어가기에 앞서 카메라 컨트롤러를 만들고 있었습니다.

그런데 카메라 이동이 이상한겁니다.

 

z축과 y축 움직임은 괜찮은데, x축 움직임이 반대로 되고 있었습니다.

그것도, 카메라의 position은 정상적으로 변하는데 보이는건 뭔가 반대로 보이고 있는 것 같았습니다.

 

처음에는 View Matrix를 의심했고, 그래서 뭘 잘못하고있나 확인해봤습니다.

//...

glm::vec3 right = glm::cross(m_Up, m_Front);
if (Input::IsKeyPressed(RS_KEY_A))
    m_Position -= right * speed * Time::GetDeltaTime();
if (Input::IsKeyPressed(RS_KEY_D))
    m_Position += right * speed * Time::GetDeltaTime();
    
//...

m_Camera.SetView(glm::lookAt(m_Position, m_Position + m_Front, m_Up));

 

제 왼손을 이리저리 돌려가며 뭐가 잘못됐나 했는데, 식에는 아무리 봐도 문제가 없었습니다.

왼손을 돌리면서 생각해보니, 이거 설마 오른손 좌표계로 되고있는건가? 했더니.. 맞았습니다.

 

그런데 지금까지 모든 코드를 왼손 좌표계에 맞춰서 만들었고,

cross 같은 것들은 왼손 오른손 구분이 없어서 어디서 틀렸을까 하면서 여기저기 눌러보다가,

glm::lookAt을 누른 순간..

template<typename T, qualifier Q>
	GLM_FUNC_QUALIFIER mat<4, 4, T, Q> lookAt(vec<3, T, Q> const& eye, vec<3, T, Q> const& center, vec<3, T, Q> const& up)
	{
#       if (GLM_CONFIG_CLIP_CONTROL & GLM_CLIP_CONTROL_LH_BIT)
            return lookAtLH(eye, center, up);
#       else
            return lookAtRH(eye, center, up);
#       endif
	}

 

lookAt이 왼손 오른손에 따라 다르게 정의가 돼있었습니다!

 

이걸 보고나니 lookAt 행렬은 왼손이냐 오른손이냐에 따라 달라지겠다는 생각이 들었습니다.

파라미터로 forward 와 up을 주는데, right의 계산 방법이 다르기 때문입니다. (왼손은 up × forward, 오른손은 forward × up) 

 

그래서 전처리기들을 타고 가보니, 이런 부분이 있었습니다.

//setup.hpp
#ifdef GLM_FORCE_DEPTH_ZERO_TO_ONE
#	ifdef GLM_FORCE_LEFT_HANDED
#		define GLM_CONFIG_CLIP_CONTROL GLM_CLIP_CONTROL_LH_ZO
#	else
#		define GLM_CONFIG_CLIP_CONTROL GLM_CLIP_CONTROL_RH_ZO
#	endif
#else
#	ifdef GLM_FORCE_LEFT_HANDED
#		define GLM_CONFIG_CLIP_CONTROL GLM_CLIP_CONTROL_LH_NO
#	else
#		define GLM_CONFIG_CLIP_CONTROL GLM_CLIP_CONTROL_RH_NO
#	endif
#endif

//...

// Clip control, define GLM_FORCE_DEPTH_ZERO_TO_ONE before including GLM
// to use a clip space between 0 to 1.
// Coordinate system, define GLM_FORCE_LEFT_HANDED before including GLM
// to use left handed coordinate system by default.

#define GLM_CLIP_CONTROL_ZO_BIT		(1 << 0) // ZERO_TO_ONE
#define GLM_CLIP_CONTROL_NO_BIT		(1 << 1) // NEGATIVE_ONE_TO_ONE
#define GLM_CLIP_CONTROL_LH_BIT		(1 << 2) // LEFT_HANDED, For DirectX, Metal, Vulkan
#define GLM_CLIP_CONTROL_RH_BIT		(1 << 3) // RIGHT_HANDED, For OpenGL, default in GLM

 

GLM_FORCE_LEFT_HANDED를 정의해주지 않으면 기본값으로 오른손 좌표계를 사용하도록 돼있었고, 

이를 바꾸기 위해선 헤더를 include하기 전에 써주라는 말이었습니다.

 

그래서 premake에 해당 전처리기를 추가하고 실행하니..

 

 

너무 잘되네요!

glm은 왼손/오른손 좌표계랑 연관이 없을거라고 생각한게 패착이었습니다.

사실 상관 없긴 한데, lookAt 등 카메라 관련 헬퍼 함수들에는 연관이 있었음을 알아야 했었네요.

 

여담으로 저 모델이 뒤돌아있는건지 내가 뒤를 보고있는건지 헷갈렸는데,

저 모델을 만든 툴은 오른손 좌표계를 썼나봅니다 ㅎㅎ

반응형