→ 이 글은 「이득우의 게임 수학」을 바탕으로 작성했습니다.
■ 3차원 공간
우리는 앞서 두 기저축$(x, y)$를 사용해서 2차원 평면 공간을 표현했다. 이제 3차원 공간을 표현하기 위해 새로운 축을 추가해야 하는데, 이를 어떻게 설정하느냐에 따라 공간의 체계가 달라진다.
- 나머지 한 축이 모니터가 바라보는 방향과 일치하는 체계를 오른손 좌표계(Right-handed coordinate system)이라 한다.
- 반대로 모니터 뒤편을 향하는 체계를 왼손 좌표계(Left-handed coordinate system)라 한다.
소프트웨어마다 사용하는 좌표계는 모두 다르다. 하지만 모두 직교 좌표계를 기반으로 하고, 서로 다른 건 단순히 어느 축을 Up/Forward로 쓰는지와 왼손/오른손 규칙 차이이다.
여기서는 z가 모니터와 같은 방향을 바라보는 오른손 좌표계를 기준으로 설명하겠다.
■ 3차원 트랜스폼
2차원 공간에서 이동 변환을 선형 변환으로 표현하기 위해 3차원 공간을 사용했듯이, 3차원 공간에서도 한 차원 더 늘어난 4차원 공간을 사용한다.
$$ S = \begin{bmatrix}s_1&0&0&0 \\ 0&s_2&0&0 \\ 0&0&s_3&0 \\ 0&0&0&1 \end{bmatrix} $$
[3차원 공간의 크기 변환 행렬]
$$ T = \begin{bmatrix}1&0&0&t_x \\ 0&1&0&t_y \\ 0&0&1&t_z \\ 0&0&0&1 \end{bmatrix} $$
[3차원 공간의 이동 변환 행렬]
크기와 이동 변환행렬은 기존 2차원 행렬에서 한 차원이 더 늘어난 형태이며 위와 같이 설계할 수 있다.
회전 변환의 경우 강체 변환(변환 후에도 크기와 모양을 유지)인데, 그러기 위해선 세 표준기저벡터가 동일한 크기와 직교성을 유지한 채 함께 움직여야 한다.
세 표준기저벡터값을 알 수 있다면 이를 열벡터로 만들어 회전 변환행렬$(R)$을 만들 수 있지만, 매번 3개의 변화된 표준기저값을 계산해야 한다.
따라서 회전을 지정할 땐, 회전하는 중심축과 각으로 표현된 회전량을 지정하는 방식을 사용했는데 3차원 공간은 무수히 많은 평면으로 구성되기 때문에 새로운 방식이 필요하다.
■ 오일러 각(Euler’s angle)
오일러 각은 3차원 공간에서 물체가 놓인 방향을 3개의 각을 사용해 표시하는 방법이다.
$$ (\theta_x, \theta_y, \theta_z) $$
표준기저벡터를 중심으로 회전하는 각의 크기로 지정되는데, 각 각의 값은 실수이기 때문에 3차원 벡터로 표현할 수 있다.
하지만 소프트웨어마다 축이 다 다르기 때문에, 회전의 움직임으로 회전 동작을 요(Yaw), 롤(Roll), 피치(Pitch)로 구분하고 각을 지정한다.
회전 | 방향 | 축 |
요(Yaw) | 위 | y |
롤(Roll) | 앞 | z |
피치(Pitch) | 오른쪽 | x |
오일러 각은 표준기저벡터를 중심으로 진행되는 세 번의 연속적인 회전을 의미한다. 예를 들어, x축 회전은 yz평면의 회전을 의미하는데, 이 경우 $x$값은 변하지 않는다.
$$ R_x = \begin{bmatrix} 1&0&0\\ 0&\cos\theta&-\sin\theta \\ 0&\sin\theta&\cos\theta \end{bmatrix} $$
그렇다면 회전 행렬 $R_x$는 위와 같이 설계할 수 있으니, 나머지 회전 행렬도 아래와 같이 설계된다.
$$ R_y = \begin{bmatrix} \cos\theta&0&\sin\theta\\ 0&1&0 \\ -\sin\theta&0&\cos\theta \end{bmatrix} $$
$$ R_z = \begin{bmatrix} \cos\theta&-\sin\theta&0\\ \sin\theta&\cos\theta&0 \\0&0&1\end{bmatrix} $$
[회전행렬의 설계]
$R_y$회전행렬은 좌측 하단의 $\sin$함수가 음의 부호를 가진다. 3차원 공간에서는 x→y→z→x→y의 순서로 3개의 축이 순한되기 때문에 $y$축에 직교하는 평면은 $zx$평면이다.
1. 회전행렬 유도
각 기저의 회전행렬을 구했으니, 순서대로 적용하여 최종 회전행렬을 만들어야 한다.
$$ R = R_{yaw}\cdot R_{pitch}\cdot R_{roll} $$
세 번의 연속적인 회전으로 구성된 오일러 각 회전방법은 6가지 경우가 발생하는데, 여기서는 z→x→y(롤, 피치, 요 순서)로 회전 행렬을 구현한다.
요, 피치, 롤 각의 값을 각각 $\alpha, \beta, \gamma$라 한다면, 오일러 각에 대응되는 회전행렬은 아래와 같이 계산된다.
$$ R_{\alpha} \cdot R_{\beta} \cdot R{_\gamma} = $$
\begin{bmatrix}\cos\alpha & 0 & \sin\alpha \\0 & 1 & 0 \\-\sin\alpha & 0 & \cos\alpha\end{bmatrix}\begin{bmatrix}1 & 0 & 0 \\0 & \cos\beta & -\sin\beta \\0 & \sin\beta & \cos\beta\end{bmatrix}\begin{bmatrix}\cos\gamma & -\sin\gamma & 0 \\\sin\gamma & \cos\gamma & 0 \\0 & 0 & 1\end{bmatrix}
$$ =\begin{bmatrix}\cos\alpha\cos\gamma + \sin\alpha\sin\beta\sin\gamma & -\cos\alpha\sin\gamma + \sin\alpha\sin\beta\cos\gamma & \sin\alpha\cos\beta \\\cos\beta\sin\gamma & \cos\beta\cos\gamma & -\sin\beta \\-\sin\alpha\cos\gamma + \cos\alpha\sin\beta\sin\gamma & \sin\alpha\sin\gamma + \cos\alpha\sin\beta\cos\gamma & \cos\alpha\cos\beta\end{bmatrix} $$
[오일러 각의 회전 행렬]
이렇게 계산된 회전행렬의 열벡터는 표준기저벡터가 회전 변환된 “로컬 축”을 의미한다. 오일러 각으로 변환된 로컬축은 아래와 같다.
$$ x_{\text{local}} = (\cos\alpha \cos\gamma + \sin\alpha \sin\beta \sin\gamma,\ \cos\beta \sin\gamma,\ -\sin\alpha \cos\gamma + \cos\alpha \sin\beta \sin\gamma)\\ y_{\text{local}} = (-\cos\alpha \sin\gamma + \sin\alpha \sin\beta \cos\gamma,\ \cos\beta \cos\gamma,\ \sin\alpha \sin\gamma + \cos\alpha \sin\beta \cos\gamma)\\ z_{\text{local}} = (\sin\alpha \cos\beta,\ -\sin\beta,\ \cos\alpha \cos\beta)\\ $$
[오일러 각으로 변환된 로컬 축]
위 계산식으로 얻어낸 로컬 축 벡터를 각각 $\vec x = (x_x, x_y,x_z), \ \vec y = (y_x, y_y,y_z) ,\ \vec z = (z_x, z_y,z_z)$로 지정하고, 이를 열벡터로 꽂아 넣어 만들어지는 3차원 공간의 회전행렬 $R$은 아래와 같다.
$$ R =\begin{bmatrix}x_x & y_x & z_x & 0 \\x_y & y_y & z_y & 0 \\x_z & y_z & z_z & 0 \\0 & 0 & 0 & 1\end{bmatrix} $$
2. 3차원 모델링 행렬
$$ M = T \cdot R \cdot S =\begin{bmatrix}x_x s_x & y_x s_y & z_x s_z & t_x \\x_y s_x & y_y s_y & z_y s_z & t_y \\x_z s_x & y_z s_y & z_z s_z & t_z \\0 & 0 & 0 & 1\end{bmatrix} $$
앞서 만든 3차원 행렬 3개를 $TRS$연산 순서에 따라 곱해 만든 모델링 행렬 $M$은 위와 같이 계산된다.
■ 카메라 공간
2차원 공간에서의 카메라는 이동 기능만 알아봤지만, 3차원 공간에서는 회전 기능까지 추가로 알아야 한다.
위와 같은 상황에서 카메라의 축으로 최종 화면을 생성한다고 했을 때, 우리가 보편적으로 인지하는 2차원 데카르트 좌표계와는 다르다.
따라서 위와 같이 뷰 공간을 $180^{\circ}$회전시키면 z 축은 카메라의 뒤를 항햐고, 뷰 공간에서 x축과 z축은 월드 공간의 x축과 z축의 반대 방향을 가지게 된다.
카메라는 크기 개념이 없기 때문에 회전과 이동 변환으로만 구성된다. 카메라의 위치값을 $t = (t_x, t_y, t_z)$로 지정하고, 로컬 축을 $x = (x_x, x_y,x_z), \ y = (y_x, y_y,y_z) ,\ z = (z_x, z_y,z_z)$로 지정하면,
$$ T =\begin{bmatrix}1 & 0 & 0 & t_x \\0 & 1 & 0 & t_y \\0 & 0 & 1 & t_z \\0 & 0 & 0 & 1\end{bmatrix}\\ R =\begin{bmatrix}x_x & y_x & z_x & 0 \\x_y & y_y & z_y & 0 \\x_z & y_z & z_z & 0 \\0 & 0 & 0 & 1\end{bmatrix} $$
와 같이 이동 행렬과 회전행렬을 만들 수 있다.
이제 뷰 행렬을 만들기 위해 이동 행렬의 역행렬 $T^{-1}$을 계산하면 모든 물체는 카메라를 중심으로 재배치된다.
$$ T^{-1} =\begin{bmatrix}1 & 0 & 0 & -t_x \\0 & 1 & 0 & -t_y \\0 & 0 & 1 & -t_z \\0 & 0 & 0 & 1\end{bmatrix} $$
[이동 변환행렬의 역행렬]
회전 변환 역시 이동 변환과 동일하게 역행렬을 적용시킨다. 회전행렬은 “직교행렬”이므로, 회전 행렬의 역행렬은 전치 행렬로 구할 수 있다.
$$ R^{-1} =\begin{bmatrix}x_x & x_y & x_z & 0 \\y_x & y_y & y_z & 0 \\z_x & z_y & z_z & 0 \\0 & 0 & 0 & 1\end{bmatrix} $$
[회전 변환행렬의 역행렬]
최종적으로 모델링 행렬을 구하기 위하기 위해선 모든 좌표를 카메라 중심으로 변환한 뒤, 회전의 역행렬을 적용하면 된다. (크기 변환 제외)
$$ M^{-1} = (T\cdot R)^{-1} = R^{-1} \cdot T^{-1} $$
$$ R^{-1} \cdot T^{-1} =\begin{bmatrix}x_x & x_y & x_z & -x \cdot t \\y_x & y_y & y_z & -y \cdot t \\z_x & z_y & z_z & -z \cdot t \\0 & 0 & 0 & 1\end{bmatrix} $$
두 행렬을 곱하고 마지막 4열을 내적을 사용해 정리하면 위와 같이 계산된다.
마지막으로 최종 뷰 좌표계는 $y$축으로 $180^{\circ}$회전한 구조를 가져야 하므로, $x$축 기저와 $z$축 기저를 반전시킨 최종 뷰 행렬은,
$$ V = R^{-1} \cdot T^{-1} =\begin{bmatrix}-x_x & -x_y & -x_z & x \cdot t \\y_x & y_y & y_z & -y \cdot t \\-z_x & -z_y & -z_z & z \cdot t \\0 & 0 & 0 & 1\end{bmatrix} $$
[뷰 행렬(View Matrix)]
위와 같이 완성된다. 따라서 뷰 좌표계에서 카메라 정면에 위치한 모든 물체의 $z$값은 음수가 된다.
'게임수학' 카테고리의 다른 글
[게임수학] 8-2. 오일러 각의 단점(짐벌락, 회전 보간) (0) | 2025.10.14 |
---|---|
[게임수학] 7. 게임 엔진 (0) | 2025.09.24 |
[게임수학] 6.삼각형(Mesh) (0) | 2025.09.20 |
[게임수학] 6-2. 투영 벡터 (0) | 2025.09.12 |
[게임수학] 6-1. 내적(Dot product) (0) | 2025.09.12 |