Post

[OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문] 4. 좌표계와 변환

이 글은 제 개인적인 공부를 위해 작성한 글입니다. 틀린 내용이 있을 수 있고, 피드백은 환영합니다.

[OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문] 4. 좌표계와 변환

개요


게임과 같은 3차원 가상 공간은 많은 물체들로 구성되어 있는데, 각 물체의 위치는 이동(translation)에 의해, 방향은 회전(rotation)에 의해 결정된다. 또한 각 물체는 축소확대(scaling)될 수도 있다. 이러한 이동, 회전, 축소확대를 총칭하여 변환(transform)이라고 한다. 이 장에서는 우선 2차원 공간에서의 변환을 소개하고 이들이 어떤 행렬로 표현되는지 기술한 후, 이를 3차원으로 확장한다.


4.1 2차원 변환의 행렬 표현



4.1.1 축소 확대

img 그림 4.1. 2차원 축소확대

2차원 축소확대는 다음과 같은 2X2 행렬로 표현된다.

\[S = \begin{pmatrix} S_x & 0 \\ 0 & S_y \\ \end{pmatrix} \tag{4.1}\]

여기서 $S_x$와 $S_y$는 각각 x축과 y축 방향의 축소확대 인자(scaling factor)이다. 그 값이 1보다 작으면 축소를, 1보다 크면 확대를 의미한다. 2차원 벡터 (x,y)는 행렬-벡터 곱셈을 통해 축소확대된다.

\[\begin{pmatrix} s_x & 0 \\ 0 & s_y \\ \end{pmatrix} \begin{pmatrix} x \\ y \\ \end{pmatrix} = \begin{pmatrix} s_x x \\ s_y y \\ \end{pmatrix} \tag{4.2}\]

다각형을 축소확대하려면 그 다각형의 모든 정점에 대해 식 (4.2) 연산을 수행하면 된다. 그림 4.1은 두 가지의 축소확대 예를 보여준다.


4.1.2 회전

img 그림 4.2. 벡터 p가 $\theta$만큼 회전되어 새로운 벡터 p’가 되었다.

그림 4.2에서 2차원 벡터는 원점을 기준으로 $\theta$만큼 회전하여 p’가 된다. 벡터 p의 길이가 r이라면, p의 좌표는 다음과 같다.

\[\begin{matrix} x = r cos \phi \\ y = r sin \phi \\ \end{matrix} \tag{4.3}\]

회전한 벡터 p’의 길이 역시 r이므로 p’의 x좌표는 다음과 같다. \(\begin{matrix} x' = r cos (\phi + \theta) \\ = r cos \phi + cos \theta - r sin \phi sin \theta \\ = x cos \theta - y sin \theta \\ \end{matrix} \tag{4.4}\)

마찬가지 방법으로 y좌표를 계산하면 다음과 같다.

\[\begin{matrix} y' = r sin (\phi + \theta) \\ = r cos \phi sin \theta + r sin \phi cos \theta \\ = x sin \theta + y cos \theta \\ \end{matrix} \tag{4.5}\]

식 (4.4)와 (4.5)는 하나의 행렬-벡터 곱셈으로 통합될 수 있다.

\[\begin{pmatrix} x' \\ y' \\ \end{pmatrix} = \begin{pmatrix} cos \theta & -sin \theta \\ sin \theta & cos \theta \\ \end{pmatrix} \begin{pmatrix} x \\ y \\ \end{pmatrix} \tag{4.6}\]

식 (4.6)의 2X2 행렬이 2차원 회전을 표현하는데, 이를 $R(\theta)$라고 표기하도록 하자.

그림 4.2에서 p는 반시계방향으로 회전되었는데, 시계방향으로의 회전 행렬을 얻으려면 $R(\theta)$에 $\theta$ 대신에 -$\theta$를 넣으면 된다. 예를 들어 시계방향 $90^\circ$ 회전은 다음과 같이 정의된다.

\[R(-90^\circ) = \begin{pmatrix} cos(-90^\circ) & -sin(-90^\circ) \\ sin(-90^\circ) & cos(-90^\circ) \\ \end{pmatrix} = \begin{pmatrix} 0 & 1 \\ -1 & 0 \\ \end{pmatrix} \tag{4.7}\]

한편, $\theta$만큼 회전은 2$\pi-\theta$만큼 회전하는 것과 동일하다. 예를 들어, 식 (4.7)의 $R(-90^\circ)$는 아래 보인 바와 같이 $R(270^\circ)$와 같다.

\[R(270^\circ) = \begin{pmatrix} cos(270^\circ) & -sin(270^\circ) \\ sin(270^\circ) & cos(270^\circ) \\ \end{pmatrix} = \begin{pmatrix} 0 & 1 \\ -1 & 0 \\ \end{pmatrix} \tag{4.8}\]


4.1.3 이동과 동차 좌표

위에서 배운 축소확대와 회전은 이른바 선형 변환(linear transform)이라는 범주에 속한다. 그런데, 축소확대와 회전 말고도 컴퓨터 그래픽스에서 자주 사용되는 또 다른 변환은 이동(translation)이다. 이는 (x, y)에 놓인 점을 (x + dx, y + dy)로 이동시키는데, (dx, dy)를 변위 벡터 (displacement vector)라고 부른다. 이동은 선형 변환의 범주에 속하지 않으며, 다음처럼 벡터 덧셈으로 구현된다.

\[\begin{pmatrix} x \\ y \\ \end{pmatrix} + \begin{pmatrix} d_x \\ d_y \\ \end{pmatrix} = \begin{pmatrix} x + d_x \\ y + d_y \\ \end{pmatrix} \tag{4.9}\]

이는 행렬 곱셈으로 구현되는 축소확대 및 회전과 다르다. 하지만, 이른바 동차 좌표(homogeneous coordinates)를 사용하면, 이동 역시 행렬 곱셈으로 구현될 수 있다. 한 점의 2차원 카테시안 좌표 (x,y)가 주어질 때 이에 대한 동차 좌표는 간단히 (x, y, 1)로 표현할 수 있다. 당분간, 마지막 원소 1은 아무 의미 없이 삽입된 것으로 생각해도 된다. 한편, 3x3 단위 행렬의 마지막 열에 아래처럼 (dx, dy)를 삽입하면, 이것이 바로 이동 행렬이 된다.

\[\begin{pmatrix} 1 & 0 & d_x \\ 0 & 1 & d_y \\ 0 & 0 & 1 \\ \end{pmatrix} \tag{4.10}\]

동차 좌표로 표현된 점에 이 행렬에 곱하자.

\[\begin{pmatrix} 1 & 0 & d_x \\ 0 & 1 & d_y \\ 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} x \\ y \\ 1 \\ \end{pmatrix} = \begin{pmatrix} x + d_x \\ y + d_y \\ 1 \\ \end{pmatrix} \tag{4.11}\]

식 (4.9)와 (4.11)의 결과는 같다. 다만, 식 (4.9)는 카테시안 좌표 (x + dx, y + dy)로, 식 (4.11)은 동차 좌표 (x + dx, y + dy, 1)로 이동 결과를 보여줄 뿐이다.


img 그림 4.3

카테시안 좌표 (2,3)을 w축을 따라 수직으로 끌어 올려서 w = 1로 표현된 평면에 놓았다고 하자. 이 점의 좌표는 (2, 3, 1)이 된다. 이 점과 원점을 지나는 직선은 무한히 많은 동차 좌표들의 집합이다. 하나의 동차 좌표를 카테시안 좌표로 바꾸려면 이 직선을 따라 w = 1 평면으로 투영(project) 시키면 된다.


이제 동차 좌표에 대해 조금 더 논의해 보자. 2차원 카테시안 좌표 (x, y)의 동차 좌표는 (x, y, 1)로 국한되지 않는다. 대신, (wx, wy, w)로 표현된다. 단, w는 0이 아니어야 한다. 예를 들어, (2, 3, 1), (4, 6, 2), (6, 9, 3), (20, 30, 10)은 모두 동일한 카테시안 좌표 (2,3)에 해당하는 동차 좌표들이다. 즉, (x, y, 1)은 카테시안 좌표 (x, y)에 해당하는 무한히 많은 동차 좌표들 중 하나일 뿐이다. 그림 4.3은 이러한 동차 좌표의 개념을 보여준다. 2차원을 구성하는 x축과 y축에 w축이 추가되어 3차원 공간을 만들었는데, 원점을 지나는 3차원 직선은 카테시안 좌표 (2, 3)에 해당하는 무한히 많은 동차 좌표들이 모인 것으로 보면 된다.

동차 좌표 (X, Y, w)가 주어졌을 때, 전체를 w로 나누면 (X/w, Y/w, 1)이 된다. 그림 4.3에서는, 3차원 직선 위의 한 점 (X, Y, w)를 직선을 따라 w = 1 평면으로 투영(project)시키는 것으로 이를 설명하고 있다. 이러한 투영 후에 (X/w, Y/w)를 취하면 바로 카테시안 좌표가 된다.

동차 좌표를 다루기 위해서는 축소확대 및 회전의 2*2 행렬 형태를 변경해야 한다. 예를 들어, 축소확대는 다음과 같은 3X3 행렬로 표현된다.

\[\begin{pmatrix} s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \tag{4.12}\]

왼쪽 위 2X2 행렬은 식 (4.1)을 그대로 복사한 것인데, 나머지 원소는 오른쪽 아래 1을 제외하고 모두 0으로 채워졌다. 같은 방식으로, 회전 행렬은 다음과 같이 표현된다.

\[\begin{pmatrix} cos \theta & -sin \theta & 0 \\ sin \theta & cos \theta & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \tag{4.13}\]


4.1.4 2차원 변환의 결합

한 물체는 여러 번의 변환을 거칠 수 있다. 그림 4.4.a의 오각형은 90도 회전한 후에 x축을 따라 7만큼 이동했다. 이 회전과 이동을 각각 R(90도) 및 T(7,0)으로 표현하자.

\[R(90^\circ) = \begin{pmatrix} cos(90^\circ) & -sin(90^\circ) & 0 \\ sin(90^\circ) & cos(90^\circ) & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} = \begin{pmatrix} 0 & -1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \tag{4.14}\] \[T(7,0) = \begin{pmatrix} 1 & 0 & 7 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \tag{4.15}\]

그림 4.4.a에서 (0,4) 좌표를 가진 점은 R(90도)에 의해 (-4,0)으로 옮겨진다.

\[\begin{pmatrix} 0 & -1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 0 \\ 4 \\ 1 \\ \end{pmatrix} = \begin{pmatrix} -4 \\ 0 \\ 1 \\ \end{pmatrix} \tag{4.16}\]

그 다음, (-4,0)은 T(7,0)에 의해 (3,0)으로 옮겨진다.

\[\begin{pmatrix} 1 & 0 & 7 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} -4 \\ 0 \\ 1 \\ \end{pmatrix} = \begin{pmatrix} 3 \\ 0 \\ 1 \\ \end{pmatrix} \tag{4.17}\]

img 그림 4.4.a. 다각형이 회전된 후 이동되었다.

img 그림 4.4.b. 다각형이 이동된 후 회전되었다. R(90도)는 원점 중심의 회전임을 상기하라.

img 그림 4.4.c. 식 (4.27)에 보인 바와 같이, (b)의 변환은 회전에 이은 이동으로도 표현될 수 있다.

R(90도)와 T(7,0) 모두 3X3 행렬이므로 하나로 결합될 수 있다.

\[T(7,0)R(90^\circ) = \begin{pmatrix} 1 & 0 & 7 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 0 & -1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} = \begin{pmatrix} 0 & -1 & 7 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \tag{4.18}\]

원래 (0,4)에 있던 점에 위 행렬을 적용하면 (3,0)으로 옮겨진다.

\[\begin{pmatrix} 0 & -1 & 7 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 0 \\ 4 \\ 1 \\ \end{pmatrix} = \begin{pmatrix} 3 \\ 0 \\ 1 \\ \end{pmatrix} \tag{4.19}\]


행렬 곱셈에서는 교환 법칙이 성립하지 않는다. 회전(R)에 이은 이동(T)은 다음과 같이 결합된다.

\[TR = \begin{pmatrix} 1 & 0 & d_x \\ 0 & 1 & d_y \\ 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} cos \theta & -sin \theta & 0 \\ sin \theta & cos \theta & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} = \begin{pmatrix} cos \theta & -sin \theta & d_x \\ sin \theta & cos \theta & d_y \\ 0 & 0 & 1 \\ \end{pmatrix} \tag{4.20}\]

한편, 순서를 바꿔 이동(T)에 이은 회전(R)은 다음과 같이 결합된다.

\[RT = \begin{pmatrix} cos \theta & -sin \theta & 0 \\ sin \theta & cos \theta & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 1 & 0 & d_x \\ 0 & 1 & d_y \\ 0 & 0 & 1 \\ \end{pmatrix} = \begin{pmatrix} cos \theta & -sin \theta & d_x cos \theta - d_y sin \theta \\ sin \theta & cos \theta & d_x sin \theta + d_y cos \theta \\ 0 & 0 & 1 \\ \end{pmatrix} \tag{4.21}\]

이 결과는 식 (4.20)과 다르다. 이는 그림 4.4.a와 4.4.b에서도 확인할 수 있다.


img 그림 4.5. 임의의 점을 중심으로 한 회전.

4.1.2 절에서 소개한 회전은 원점을 중심으로 한 것이었다. 이제 임의의 점을 중심으로 하는 회전에 대해 생각해 보자. 그림 4.5의 왼쪽에 보인 예에서, (5,2) 점은 원점 대신 (3,2) 점을 중심으로 90도 회전하여 (3,4)에 놓인다. 만약 우리가 (5,2)에 R(90도)를 적용하면 다음과 같이 틀린 결과를 얻게 될 것이다.

\[\begin{pmatrix} 0 & -1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 5 \\ 2 \\ 1 \\ \end{pmatrix} = \begin{pmatrix} -2 \\ 5 \\ 1 \\ \end{pmatrix} \tag{4.22}\]

임의의 점 (a, b)를 중심으로 (x, y)를 회전하는 것은 다음과 같은 세 단계로 나눠져 구현된다.

  1. (x,y)를 (-a,-b)만큼 이동
  2. 이동된 점 (x-a, y-b)를 원점 중심으로 회전
  3. 회전 결과를 (a,b)만큼 이동

그림 4.5는 이 과정을 보여주고 있다.

  1. (5,2)는 (-3,-2)만큼 이동하여 (2,0)이 되었는데, 이는 (2)단계에서 수행할 회전의 중심을 원점으로 바꾸는 효과를 가진다.
  2. 이제 (2,0)에 90도 회전을 적용할 것인데, 우리가 식 (4.6)에서 정의한 회전은 항상 원점을 중심으로 하므로, (2,0)은 (0,2)로 옮겨진다.
  3. 마지막으로 (0,2)를 (3,2)만큼 이동하여 (3,4)를 얻는다. 이러한 세 단계 행렬을 결합하면 아래와 같다.
\[\begin{pmatrix} 1 & 0 & 3 \\ 0 & 1 & 2 \\ 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 0 & -1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 1 & 0 & -3 \\ 0 & 1 & -2 \\ 0 & 0 & 1 \\ \end{pmatrix} = \begin{pmatrix} 0 & -1 & 5 \\ 1 & 0 & -1 \\ 0 & 0 & 1 \\ \end{pmatrix} \tag{4.23}\]

초기에 주어진 점 (5,2)에 이 행렬을 적용한 결과는 (3,4)가 된다.

\[\begin{pmatrix} 0 & -1 & 5 \\ 1 & 0 & -1 \\ 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 5 \\ 2 \\ 1 \\ \end{pmatrix} = \begin{pmatrix} 3 \\ 4 \\ 1 \\ \end{pmatrix} \tag{4.24}\]


4.2 아핀 변환


축소확대, 회전, 이동의 세 변환 중 축소확대와 회전은 선형 변환 범주에 속하지만, 이동은 그렇지 않다. 선형변환과 이동을 포함하는 범주를 아핀 변환 (affine transform)이라 한다. 2차원 아핀 변환은 3X3 행렬로 표현되므로, 몇 개의 아핀 변환이 주어지건 이는 모두 하나의 행렬로 결합 가능하다. 앞서 식 (4.20)은 회전(R)에 이은 이동(T)이 결합된 행렬을 보여줬는데, 이를 TR이라고 표기했다. 여기에 축소확대(S)를 추가한 결과는 다음과 같다.

\[SRT = \begin{pmatrix} s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} cos \theta & -sin \theta & d_x cos \theta - d_y sin \theta \\ sin \theta & cos \theta & d_x sin \theta + d_y cos \theta \\ 0 & 0 & 1 \\ \end{pmatrix} = \begin{pmatrix} s_x cos \theta & -s_x sin \theta & s_x d_x cos \theta - s_x d_y sin \theta \\ s_y sin \theta & s_y cos \theta & s_y d_x sin \theta + s_y d_y cos \theta \\ 0 & 0 & 1 \\ \end{pmatrix} \tag{4.25}\]

식 (4.20), (4.21), (4.25)에서 모든 결과는 3X3 행렬이다. 그런데, 한 가지 눈여겨 볼 점은, 이들 행렬의 3번 행은 항상 (0 0 1)로 고정된다는 것 이다.

이렇게 고정불변인 3번 행을 무시하고 나머지 2X3 행렬을 [L|t]로 표기하자. L은 왼쪽의 2X2 행렬을, t는 3번 열을 말한다. 여러 개의 아핀 변환이 결합된 [L|t]에서, L은 ‘누적된 선형 변환’을, t는 ‘누적된 이동’을 표현한다. 식(4.20)과 (4.21)에서 L은 입력으로 주어진 R과 같음을 발견할 수 있는데, 이는 R이 행렬 결합에 사용된 유일한 선형 변환이기 때문이다. 이와 달리 식 (4.25)에서 L은 R과 S의 결합이다. L에는 어떠한 이동 요소도 포함되지 않는다. 식 (4.20), (4.21), (4.25)를 보면, 변위 벡터 원소인 dx와 dy가 L에 포함되어 있지 않음을 알 수 있다. 반면, [L|t]의 t는 입력으로 주어진 선형 변환을 포함할 수 있다. 식 (4.21)과 (4.25)를 보라.

그림 4.4.b를 예로 들어보자. 두 변환은 다음과 같이 결합된다.

\[R(90^\circ)T(7,0) = \begin{pmatrix} 0 & -1 & 0 \\ 1 & 0 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 1 & 0 & 7 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} = \begin{pmatrix} \color{red}{0} & \color{red}{-1} & \color{blue}{7} \\ \color{red}{1} & \color{red}{0} & \color{blue}{0} \\ 0 & 0 & 1 \\ \end{pmatrix} \tag{4.26}\]

L은 빨간색으로, t는 파란색으로 표시되었다. 결합 과정에서 사용된 유일한 선형 변환이 R(90도)이므로 R(90도)가 그대로 복사되어 L을 만든 반면, t는 입력으로 주어진 T(7,0)의 세 번째 열과 다름에 주의하자.

식 (4.21)과 (4.25)의 t는 약간 복잡해 보이기는 하지만 변위 벡터의 역할을 수행한다. 어떤 물체를 [L|t]로 변환하는 것은 개념적으로 해석하면, 그 물체에 L을 먼저 적용하고 그렇게 선형 변환된 물체에 t를 적용하는 것과 같다. 즉, 폴리곤 메시로 표현된 물체의 각 정점을 p라 할 때, Lp + t 방식으로 변환이 이뤄지는 것이다. 예를 들어, 식 (4.26)의 마지막 행렬이 적용되는 방식을 개념적으로 풀어쓰면 다음과 같다.

\[\begin{pmatrix} \color{red}{0} & \color{red}{-1} & \color{blue}{0} \\ \color{red}{1} & \color{red}{0} & \color{blue}{7} \\ 0 & 0 & 1 \\ \end{pmatrix} = \begin{pmatrix} 1 & 0 & \color{blue}{0} \\ 0 & 1 & \color{blue}{7} \\ 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} \color{red}{0} & \color{red}{-1} & 0 \\ \color{red}{1} & \color{red}{0} & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \tag{4.27}\]

그림 4.4.c는 이러한 개념적인 순서를 보여준다.

축소확대 없이 회전과 이동이 결합된 변환을 생각해 보자. 이 변환은 물체의 방향과 위치를 변경시킬 뿐 그 물체의 외양에는 영향을 미치지 못한다. 이런 점에서 이를 강체 변환(rigid-body motion 혹은 간단히 rigid motion)이라 부른다. 아무리 많은 수의 회전과 이동이 결합되어도, 최종 강체 변환 행렬은 [R|t]로 표현되는데, R은 ‘누적된 회전’을, t는 ‘누적된 이동’을 표현한다. 물론 R에는 어떠한 이동 요소도 포함되지 않는 반면, t는 입력으로 주어진 회전 변환을 포함할 수 있다. 어떤 물체를 [R|t]로 변환하는 것을 개념적으로 해석하면, 그 물체에 R을 먼저 적용하고 그렇게 회전된 물체에 t를 적용하는 것과 같다.


4.3 3차원 변환의 행렬 표현

이제까지 우리는 2차원 아핀 변환을 공부했다. 이제 이를 3차원으로 확장해 보자.


4.3.1 축소확대

3차원 축소확대는 다음과 같은 3X3 행렬로 표현된다.

\[\begin{pmatrix} s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0 & 0 & s_z \\ \end{pmatrix} \tag{4.28}\]

예전의 2차원 2X2 행렬에 추가된 $s_z$는 z축 방향 축소확대 인자이다. 3차원 벡터(x,y,z)는 행렬-벡터 곱셈을 통해 다음처럼 축소확대된다.

\[\begin{pmatrix} s_x & 0 & 0 \\ 0 & s_y & 0 \\ 0 & 0 & s_z \\ \end{pmatrix} \begin{pmatrix} x \\ y \\ z \\ \end{pmatrix} = \begin{pmatrix} s_x x \\ s_y y \\ s_z z \\ \end{pmatrix} \tag{4.29}\]

폴리곤 메시를 축소확대하려면 그 메시의 모든 정점에 대해 식 (4.29) 연산을 수행하면 된다. 그림 4.6은 축소확대의 두 가지 예를 보여주는데, 처음 경우와 같이 모든 축소확대 인자가 같으면 균등(uniform)하다고, 그렇지 않다면 비균등(non-uniform)하다고 부른다.

img 그림 4.6. 3차원 축소확대


4.3.2. 회전

회전중심(center of rotation)을 필요했던 2차원 회전과는 달리, 3차원 회전은 회전축(axis of rotation)을 필요로 한다. 먼저, z축을 중심으로 $\theta$만큼 회전하는 $R_z(\theta)$를 유도해 보자. $R_z(\theta)$에 의해 벡터 (x,y,z)가 (x’,y’,z’)로 변환된다고 하자. 이 벡터의 z좌표는 $R_z(\theta)$에 의해 바뀌지 않는다.

\[z' = z \tag{4.30}\]

반면, x와 y좌표는 각각 식 (4.4)와 (4.5)에 의하여 바뀐다. 식(4.4), (4.5), (4.30)을 하나의 행렬-벡터 곱셈으로 통합하면 다음과 같다.

\[\begin{pmatrix} x' \\ y' \\ z' \\ \end{pmatrix} = \begin{pmatrix} cos \theta & -sin \theta & 0 \\ sin \theta & cos \theta & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} x \\ y \\ z \\ \end{pmatrix} \tag{4.31}\]

위 행렬이 바로 $R_z(\theta)$이다. 한 물체를 z축 중심으로 $\theta$만큼 회전시키려면, 그 물체의 폴리곤 메시를 구성하는 모든 정점에 위 $R_z(\theta)$를 적용한다. 그림 4.7.a의 주전자는 $R_z(90^\circ)$에 의해 회전되었다.

img 그림 4.7. 주축 중심 회전. (a) $R_z(90^\circ)$, (b) $R_x(90^\circ)$, (c) $R_y(90^\circ)$

이제 그림 4.7.b에 보인 바와 같은 x축 중심 회전 $R_x(\theta)$를 유도해 보자. $R_x(\theta)$는 x좌표를 바꾸지 못한다.

\[x' = x \tag{4.32}\]

한편, 그림 4.7.b에서 오른손의 엄지 손가락을 회전축과 나란히 놓으면, 나머지 네 손가락은 y축에서 z축으로 움직인다. 다시 그림 4.7.a로 돌아가 보면, 네 손가락은 x축에서 y축으로 움직였다. 즉, 4.7.a의 x축의 역할이 그림 4.7.b에서 y축으로 교체되고, 그림 4.7.a의 y축은 그림 4.7.b에서 z축으로 교체된 것이다. 이러한 교체를 식 (4.4)와 (4.5)에 적용하면, 우리는 회전된 벡터의 y 및 z 좌표를 다음과 같이 정의할 수 있다.

\[y' = y cos \theta - z sin \theta \tag{4.33}\] \[z' = y sin \theta + z cos \theta \tag{4.34}\]

식 (4.32), (4.33), (4.34)를 하나의 행렬-벡터 곱셈으로 통합하면 $R_x(\theta)$를 얻을 수 있다.

\(R_x(\theta) = \begin{pmatrix} 1 & 0 & 0 \\ 0 & cos \theta & -sin \theta \\ 0 & sin \theta & cos \theta \\ \end{pmatrix} \tag{4.35}\) 이제 그림 4.7.b와 c에 대해 위와 동일한 논리를 적용하면 y축 중심 회전 $R_y(\theta)$을 유도할 수 있다.

\[R_y(\theta) = \begin{pmatrix} cos \theta & 0 & sin \theta \\ 0 & 1 & 0 \\ -sin \theta & 0 & cos \theta \\ \end{pmatrix} \tag{4.36}\]

img 그림 4.8. 중앙에 그려진 주전자를 y축을 중심으로 반시계 방향으로 90도 회전시킨 결과가 왼쪽에, 시계 방향으로 90도 회전시킨 결과가 오른쪽에 그려져 있다.

그림 4.8은 y축을 중심으로 한 반시계 방향 및 시계 방향 회전을 비교한다. 회전축이 우리 눈을 향하고 있을 때, 회전이 반시계 방향으로 이뤄지는 것으로 보이면 회전각도 $\theta$는 양수가 되고, 반대로 회전이 시계 방향으로 이뤄지면 $\theta$는 음수가 된다.


4.3.3. 이동과 동차 좌표

동차 좌표를 이용한 3차원 이동은 4X4 단위 행렬의 마지막 열에 (dx,dy,dz)를 삽입한 것으로 정의된다.

\[\begin{pmatrix} 1 & 0 & 0 & d_x \\ 0 & 1 & 0 & d_y \\ 0 & 0 & 1 & d_z \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \tag{4.37}\]

이를 3차원 점의 동차 좌표 (x,y,z,1)에 곱하면 다음과 같은 결과를 얻는다.

\[\begin{pmatrix} 1 & 0 & 0 & d_x \\ 0 & 1 & 0 & d_y \\ 0 & 0 & 1 & d_z \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} x \\ y \\ z \\ 1 \\ \end{pmatrix} = \begin{pmatrix} x + d_x \\ y + d_y \\ z + d_z \\ 1 \\ \end{pmatrix} \tag{4.38}\]

앞서 정의한 3차원 축소확대 및 회전 행렬도 동차 좌표계에서는 4X4 크기를 가지게 되는데, 축소확대의 예를 들면 다음과 같다.

\[\begin{pmatrix} s_x & 0 & 0 & 0 \\ 0 & s_y & 0 & 0 \\ 0 & 0 & s_z & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \tag{4.39}\]


4.4 월드 변환


img 그림 4.9. 자신의 오브젝트 공간에서 정의된 구와 주전자가 월드 공간으로 모아진다.

하나의 물체를 모델링하는 데 사용된 좌표계를 오브젝트 공간(object space)이라 부른다. 각자의 오브젝트 공간에서 정의된 물체들로 3차원 가상 환경을 구성하려면 이들을 하나의 좌표계로 통합해야 하는데, 이 좌표계를 월드 공간(world space)이라 부른다. 그림 4.9의 가상 환경은 구와 주전자로 구성되는데, 이들은 각각 나름의 월드 변환(world transform)을 통해 월드 공간으로 옮겨진다.

먼저, 구를 살펴보자. 오브젝트 공간에서 구의 반지름은 1이었다. 월드 공간에서 반지름이 2인 구를 만들고 싶다면, 구를 위한 월드 변환은 축소확대 인자를 모두 2로 가지는 균등 축소확대이다.

\[\begin{pmatrix} 2 & 0 & 0 & 0 \\ 0 & 2 & 0 & 0 \\ 0 & 0 & 2 & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \tag{4.40}\]

그림 4.9에서 구의 북극점은 오브젝트 공간에서 (0,1,0)의 좌표를 가졌지만, 식(4.40)의 변환에 의해 월드 공간에서는 (0,2,0)의 좌표를 가지게 된다.

\[\begin{pmatrix} 2 & 0 & 0 & 0 \\ 0 & 2 & 0 & 0 \\ 0 & 0 & 2 & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 0 \\ 1 \\ 0 \\ 1 \\ \end{pmatrix} = \begin{pmatrix} 0 \\ 2 \\ 0 \\ 1 \\ \end{pmatrix} \tag{4.41}\]

img 그림 4.10.a. 3차원 변환의 결합. 주전자가 회전된 후 이동되었다.

img 그림 4.10.b. 주전자가 이동된 후 회전되었다.

img 그림 4.10.c. 식 (4.48)에서 보인 바와 같이, (b)의 변환은 회전에 이은 이동으로 이해할 수 있다.

그림 4.9에서 주전자에 적용된 월드 변환은 y축 중심 90도 회전인 $R_y(90^\circ)$와 x축 방향 7만큼 이동인 T(7,0,0)으로 구성된다. 그림 4.10.a는 이 두 단계를 보여준다. $R_y(90^\circ)$는 식 (4.36)에 따라 아래처럼 정의된다(동차 좌표를 처리하기 위해 4X4 행렬을 사용했다).

\[R_y(90^\circ) = \begin{pmatrix} 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ -1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \tag{4.42}\]

원래 (0,2,3)에 있던 주전자의 주둥이 끝이 회전 후에는 (3,2,0)에 놓이게 된다.

\[\begin{pmatrix} 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ -1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 0 \\ 2 \\ 3 \\ 1 \\ \end{pmatrix} = \begin{pmatrix} 3 \\ 2 \\ 0 \\ 1 \\ \end{pmatrix} \tag{4.43}\]

T(7,0,0)은 다음과 같다.

\[T(7,0,0) = \begin{pmatrix} 1 & 0 & 0 & 7 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \tag{4.44}\]

(3,2,0)에 있던 주전자의 주둥이 끝은 이동 후 (10,2,0)에 놓이게 된다.

\[\begin{pmatrix} 1 & 0 & 0 & 7 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 3 \\ 2 \\ 0 \\ 1 \\ \end{pmatrix} = \begin{pmatrix} 10 \\ 2 \\ 0 \\ 1 \\ \end{pmatrix} \tag{4.45}\]

$R_y(90^\circ)$와 T(7,0,0)은 하나의 행렬로 합쳐질 수 있다.

\[T(7,0,0)R_y(90^\circ) = \begin{pmatrix} 1 & 0 & 0 & 7 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ -1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} = \begin{pmatrix} 0 & 0 & 1 & 7 \\ 0 & 1 & 0 & 0 \\ -1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \tag{4.46}\]

이것이 바로 주전자를 위한 월드 변환 행렬이다. 오브젝트 공간에서 (0,2,3)의 좌표를 가졌던 주전자 주둥이 끝은 이 행렬에 의해 월드 공간의 (10,2,0) 으로 옮겨진다.

\[\begin{pmatrix} 0 & 0 & 1 & 7 \\ 0 & 1 & 0 & 0 \\ -1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 0 \\ 2 \\ 3 \\ 1 \\ \end{pmatrix} = \begin{pmatrix} 10 \\ 2 \\ 0 \\ 1 \\ \end{pmatrix} \tag{4.47}\]

물론, 이 결과는 식 (4.45)와 동일하다.

우리가 4.2절에서 논의한 2차원 아핀 변환의 특성은 3차원에서도 그대로 유지된다. 우선 행렬 곱셈에서는 교환 법칙이 성립하지 않는다. 그림 4.10.a에서는 $R_y(90^\circ)$, T(7,0,0) 순서로, 그림 4.10.b에서는 T(7,0,0), $R_y(90^\circ)$ 순서로 변환이 이뤄졌는데, 그 결과는 다르다.

3차원 축소확대, 회전, 이동행렬들은 하나의 4X4 행렬로 결합 가능한데, 식 (4.46)에서 볼 수 있듯, 그 네 번째 행은 항상 (0 0 0 1)이다. 이렇게 고정불변인 네 번째 행을 제외한 나머지 3X4 행렬은 [L|t]로 표기되는데, 왼쪽의 3X3 행렬인 L은 ‘누적된 선형 변환’을 표현하고, 4번 열 t는 ‘누적된 이동’을 표현한다. 또한 L에는 어떠한 이동 요소도 포함되지 않지만, t는 입력으로 주어진 선형 변환을 포함할 수 있다. 어떤 물체를 [L|t]로 변환하는 것을 개념적으로 해석하면, 그 물체에 L을 먼저 적용하고 그렇게 선형 변환된 물체에 t를 적용하는 것과 같다. 그림 4.10.b의 변환을 개념적으로 풀어쓰면 다음과 같다.

\[R_y(90^\circ) T(7,0,0) = \begin{pmatrix} 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ -1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 1 & 0 & 0 & 7 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} = \begin{pmatrix} 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ -1 & 0 & 0 & -7 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & -7 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 0 & 0 & 1 & 0 \\ 0 & 1 & 0 & 0 \\ -1 & 0 & 0 & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \tag{4.48}\]

그림 4.10.c는 이렇게 L을 먼저 적용하고 그 다음에 t를 적용하는 순서를 보여준다.


4.5 회전과 오브젝트 공간 기저


오브젝트 공간에서 한 물체의 모델링이 완료되면, 그 물체는 자신의 오브젝트 공간과 일체가 된다. 즉, 물체를 움직이게 되면 그 오브젝트 공간도 따라서 같이 움직인다. 그림 4.11.a에서 {e1,e2,e3}는 월드 공간 기저를, {u,v,n}은 오브젝트 공간 기저를 나타낸다. 초기에 그 둘은 일치한다. 하지만, 물체가 회전하면, 오브젝트 공간 기저 {u,v,n}은 {e1,e2,e3}와 다르게 된다. 이 예에서 확인할 수 있듯, 회전 후 물체의 방향은 {u,v,n}으로 표현할 수 있다.

img 그림 4.11.a. 한 물체의 오브젝트 공간 기저는 그 물체의 방향을 표현한다. 주축 중심 회전

img 그림 4.11.b. 임의의 축 중심 회전

물체에 적용된 회전을 R이라 하자. 초기에 e1과 동일했던 u는 R에 의해 회전되어 e1과 다르게 된다. 그 관계는 다음과 같다.

\[Re_1 = R \begin{pmatrix} 1 \\ 0 \\ 0 \\ \end{pmatrix} = \begin{pmatrix} u_x \\ u_y \\ u_z \\ \end{pmatrix} \tag{4.49}\]

마찬가지로, e2와 v의 관계 및 e3와 n의 관계는 다음과 같다.

\[Re_2 = R \begin{pmatrix} 0 \\ 1 \\ 0 \\ \end{pmatrix} = \begin{pmatrix} v_x \\ v_y \\ v_z \\ \end{pmatrix} \tag{4.50}\] \[Re_3 = R \begin{pmatrix} 0 \\ 0 \\ 1 \\ \end{pmatrix} = \begin{pmatrix} n_x \\ n_y \\ n_z \\ \end{pmatrix} \tag{4.51}\]

식 (4.49), (4.50), (4.51)을 결합하면 다음을 얻을 수 있다.

\[R \begin{pmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} = \begin{pmatrix} u_x & v_x & n_x \\ u_y & v_y & n_y \\ u_z & v_z & n_z \\ \end{pmatrix} \tag{4.52}\]

위 식에서 R은 단위 행렬과 곱해지므로 다음과 같이 정리된다.

\[R = \begin{pmatrix} u_x & v_x & n_x \\ u_y & v_y & n_y \\ u_z & v_z & n_z \\ \end{pmatrix} \tag{4.53}\]

우리는 R의 세 열이 {u,v,n}으로 구성됨을 알아냈다. 그림 4.11.a의 R(90도)를 보자. R(90도)에 의해 u=(0,0,-1), v =(0,1,0), n =(1,0,0)이 되었음을 쉽게 이해할 수 있는데, 이 {u,v,n}은 R 행렬의 세 열을 구성하게 된다.

이 예에서 확인할 수 있듯, 회전된 물체의 오브젝트 공간 기저인 {u,v,n}이 주어졌다면, 그 회전 행렬을 즉각 정의할 수 있다. 즉, {u,v,n}으로 세 열을 채우면 된다. 거꾸로, 회전 행렬이 주어졌다면, 그 행렬의 세 열이 바로 물체의 오브젝트 공간 기저 {u,v,n}이 된다. 이는 모든 회전에 적용된다. 그림 4.11.b는 주축이 아닌 임의의 축을 중심으로 하는 회전을 보여주는데, 회전 후의 오브젝트 공간 기저가 {u,v,n}으로 주어졌다면 그 회전 행렬을 즉각 얻을 수 있고, 반대로 회전 행렬이 주어졌다면 회전 후 오브젝트 공간 기저 {u,v,n}을 즉각 얻을 수 있다.


4.6 역변환


컴퓨터 그래픽스에서 역변환(inverse transform)은 매우 자주 사용되는 중요한 개념이다. 변위 벡터가 (dx, dy, dz)인 이동 T의 역변환은 (-dx, -dy, -dz)만큼 이동하는 것이다. 그 행렬은 다음과 같다.

\[\begin{pmatrix} 1 & 0 & 0 & -d_x \\ 0 & 1 & 0 & -d_y \\ 0 & 0 & 1 & -d_z \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \tag{4.54}\]

이러한 T의 역변환을 $T^{-1}$이라고 표기하는데, $T^{-1}$는 실제로 T의 역행렬이 된다.

\[T^{-1} T = \begin{pmatrix} 1 & 0 & 0 & -d_x \\ 0 & 1 & 0 & -d_y \\ 0 & 0 & 1 & -d_z \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} 1 & 0 & 0 & d_x \\ 0 & 1 & 0 & d_y \\ 0 & 0 & 1 & d_z \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} = \begin{pmatrix} 1 & 0 & 0 & 0 \\ 0 & 1 & 0 & 0 \\ 0 & 0 & 1 & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} = I \tag{4.55}\]

한편, $(s_x, s_y, s_z)$를 축소확대 인자로 가지는 축소확대의 역변환은 다음과 같다.

\[\begin{pmatrix} \frac{1}{s_x} & 0 & 0 & 0 \\ 0 & \frac{1}{s_y} & 0 & 0 \\ 0 & 0 & \frac{1}{s_z} & 0 \\ 0 & 0 & 0 & 1 \\ \end{pmatrix} \tag{4.56}\]

이제 회전의 역변환을 정의해 보자. 우리는 항상 오브젝트 공간 기저 {u, v, n}이 직교정규 성질을 가진다고 가정한다. 따라서, 하나의 기저 벡터가 자신과 내적되었을 때 그 결과는 1이다. 즉, u $\cdot$ u = v $\cdot$ v = n $\cdot$ n = 1이다. 반면, 서로 다른 기저 벡터 간 내적은 0이 된다. 즉, u $\cdot$ v = v $\cdot$ n = n $\cdot$ u = 0이다. 이를 이용해서, 회전 행렬과 그 전치행렬의 곱을 정리하면 다음과 같다.

\[R^{T} R = \begin{pmatrix} u_x & u_y & u_z \\ v_x & v_y & v_z \\ n_x & n_y & n_z \\ \end{pmatrix} \begin{pmatrix} u_x & v_x & n_x \\ u_y & v_y & n_y \\ u_z & v_z & n_z \\ \end{pmatrix} = \begin{pmatrix} u \cdot u & u \cdot v & u \cdot n \\ v \cdot u & v \cdot v & v \cdot n \\ n \cdot u & n \cdot v & n \cdot n \\ \end{pmatrix} = \begin{pmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} = I \tag{4.57}\]

이는 바로 $R^T = R^{-1}$임을 말해 준다. 즉, 회전의 전치행렬을 취하면 바로 역변환을 얻게 된다. 회전 행렬에서는 {u,v,n}이 열을, 역회전 에서는 {u,v,n}이 행을 구성하게 된다. 그림 4.12를 보자.

img 그림 4.12. 역회전. (a) $R_y(90^\circ)$와 역회전, (b) 임의의 축 중심 회전과 그 역회전.


참고

This post is licensed under CC BY 4.0 by the author.