Post

[OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문] 2. 수학 기초

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

[OpenGL ES를 이용한 3차원 컴퓨터 그래픽스 입문] 2. 수학 기초

개요


이 장은 컴퓨터 그래픽스 알고리즘의 이해에 필요한 최소한의 수학적인 내용을 직관적으로 기술할 것인데, 행렬과 벡터부터 시작하도록 하자.


2.1 행렬과 벡터


행렬은 이름 그대로 행(row)과 열(column)로 구성되는데, m개의 행과 n개의 열을 가진 행렬은 다음과 같이 표현된다.

\[\begin{pmatrix} a_{11} & a_{12} & \cdots & a_{1n} \\ a_{21} & a_{22} & \cdots & a_{2n} \\ \vdots & \vdots & \ddots & \vdots \\ a_{m1} & a_{m2} & \cdots & a_{mn} \end{pmatrix} \tag{2.1}\]

이 행렬의 크기는 m*n으로 표기되는데, m과 n이 같다면 정사각 행렬(square matrix)이라 한다. 행렬 각 원소의 아래첨자는 그 원소의 위치를 말한다. 예를 들어, $a_{12}$는 첫째 행과 둘째 열의 교차점에 놓인다. 두 개의 행렬 A와 B를 생각해 보자. A의 열과 B의 행이 같은 개수라면, A와 B는 아래처럼 곱해질 수 있다.

\[AB = \begin{pmatrix} a_{11} & a_{12} \\ a_{21} & a_{22} \\ a_{31} & a_{32} \end{pmatrix} \begin{pmatrix} b_{11} & b_{12} & b_{13} \\ b_{21} & b_{22} & b_{23} \end{pmatrix} = \begin{pmatrix} a_{11}b_{11} + a_{12}b_{21} & a_{11}b_{12} + a_{12}b_{22} & a_{11}b_{13} + a_{12}b_{23} \\ a_{21}b_{11} + a_{22}b_{21} & a_{21}b_{12} + a_{22}b_{22} & a_{21}b_{13} + a_{22}b_{23} \\ a_{31}b_{11} + a_{32}b_{21} & a_{31}b_{12} + a_{32}b_{22} & a_{31}b_{13} + a_{32}b_{23} \end{pmatrix} \tag{2.2}\]

A의 크기가 lm이고, B의 크기가 mn이라면, AB의 크기는 l*n이 된다.

2차원 벡터는 (x,y)로, 3차원 벡터는 (x,y,z)로 표기된다. 이렇게 표기된 벡터를 행벡터(row vector)라고 부른다. 이와 달리 열벡터 (column vector) 표기법을 쓸 수도 있다. 예를 들어, 2차원 열벡터는 다음과 같이 쓴다.

\[\begin{pmatrix} x \\ y \end{pmatrix} \tag{2.3}\]

벡터는 특수한 행렬이다. 식 (2.3)의 벡터는 한 개의 열을 가진 행렬이고, 그 크기는 21이다. 따라서 식 (2.2)의 행렬-행렬 곱셈 방법은 행렬-벡터 곱셈에 그대로 적용된다. 예를 들어, 32 행렬 M과 2차원 열벡터 v의 곱은 다음과 같다.

\[Mv = \begin{pmatrix} a & b \\ c & d \\ e & f \end{pmatrix} \begin{pmatrix} x \\ y \end{pmatrix} = \begin{pmatrix} ax + by \\ cx + dy \\ ex + fy \end{pmatrix} \tag{2.4}\]

어떤 행렬 M이 주어졌을 때, 그것의 행과 열을 바꿔 놓은 것을 전치 행렬(transpose)이라고 하며 $M^T$로 표기한다. 예를 들어, 식 (2.4)의 M의 전치행렬은 다음과 같다.

\[\begin{pmatrix} a & c & e \\ b & d & f \\ \end{pmatrix} \tag{2.5}\]

이는 벡터에 그대로 적용된다. 열벡터 v의 원소를 행벡터로 표현하면 $v^T$가 된다.

식 (2.4)의 행렬-벡터 곱셈은 다른 방식으로 표현될 수 있다. 즉, 열벡터 $v$ 대신 행벡터 $v^T$를 사용하되, 이를 $M^T$의 왼쪽에 배치한다.

\[v^T M^T = \begin{pmatrix} x & y \end{pmatrix} \begin{pmatrix} a & c & e \\ b & d & f \\ \end{pmatrix} = \begin{pmatrix} ax + by & cx + dy & ex + fy \end{pmatrix} \tag{2.6}\]

이는 식 (2.4)의 결과와 같다. OpenGL은 열벡터를 사용하고 식 (2.4)처럼 행렬-벡터 곱셈을 표현하는 반면, Direct3D는 행벡터를 사용하고 식 (2.6)과 같은 방식을 사용한다.

단위 행렬(identity matrix)은 정사각행렬 중, 왼쪽 위 끝과 오른쪽 아래를 잇는 대각선에 놓인 원소는 모두 1이고 나머지 원소는 모두 0인 경우를 말한다. 이는 I로 표기한다. 임의의 행렬 M에 대해서, 다음과 같이 MI = IM = M이 성립한다.

\[\begin{pmatrix} a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \\ a_{31} & a_{32} & a_{33} \\ \end{pmatrix} \begin{pmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} = \begin{pmatrix} a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \\ a_{31} & a_{32} & a_{33} \\ \end{pmatrix} \tag{2.7}\] \[\begin{pmatrix} 1 & 0 & 0 \\ 0 & 1 & 0 \\ 0 & 0 & 1 \\ \end{pmatrix} \begin{pmatrix} a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \\ a_{31} & a_{32} & a_{33} \\ \end{pmatrix} = \begin{pmatrix} a_{11} & a_{12} & a_{13} \\ a_{21} & a_{22} & a_{23} \\ a_{31} & a_{32} & a_{33} \\ \end{pmatrix} \tag{2.8}\]

두 개의 정사각행렬 A와 B가 곱해져서 그 결과가 I가 된다면, 즉 AB = I라면, B는 A의 역행렬(inverse)이라고 부르며 $A^{-1}$로 표기한다. 마찬가지로, A는 B의 역행렬이다.

한편, AB와 $B^{-1}$ $A^{-1}$을 곱하면 그 결과는 다음과 같다.

$(AB)(B^{-1} A^{-1}) = A(BB^{-1})A^{-1} = AIA^{-1} = AA^{-1} = I$

이로부터 $(AB)^{-1} = B^{-1}A^{-1}$임을 알 수 있다. 이와 유사하게, $(AB)^T = B^TA^T$이다.

2차원 벡터 v의 좌표를 $(v_x, v_y)$로 표현할 때, v의 길이는 $\sqrt{v^2_x + v^2_y}$으로 정의되고 $\lVert \mathbf{v} \rVert$로 표기된다. 3차원 벡터 $v$의 길이는 $\sqrt{v^2_x + v^2_y + v^2_z}$이 된다. 벡터 v를 그 길이 $\lVert \mathbf{v} \rVert$로 나누는 과정을 정규화(normalization)라고 하는데, $v / \lVert \mathbf{v} \rVert $는 v와 같은 방향을 가지며 길이가 1인 벡터이다. 이를 단위 벡터(unit vector)라고 부른다.


2.2 좌표계와 기저


img 그림 2.1

그림 2.1.a의 2차원 좌표계에서, x축에 나란한 벡터 e1은 (1,0)이고, y축에 나란한 벡터 e2는 (0,1)이다. 2차원 공간의 모든 벡터는 e1과 e2의 선형 조합으로 표현 가능하다. 예를 들어, (3,5)는 $3e_1+ 5e_2$로 표현된다. 이런 점에서 ${e_1,e_2}$를 기저(basis)라고 부르는데, e1과 e2가 주축(principal axis)에 나란하므로, ${e_1,e_2}$를 특별히 표준 기저(standard basis)라고 한다. 한편, e1과 e2는 서로 직교하는 단위 벡터이므로 직교정규(orthonormal) 성질을 가진다고 말한다.

우리는 표준 기저 말고도 다양한 기저를 사용할 수 있다. 그림 2.1.b의 ${(1,1), (0,2)}$가 하나의 예이다. 표준 기저를 사용하면 (3,5)가 $3e_1 + 5e_2$로 표현되지만, ${(1,1), (0,2)}$를 사용하면 3(1,1) + 1(0,2)로 표현된다. 이처럼 (1,1)과 (0,2)를 선형조합하여 2차원 공간의 모든 벡터를 표현할 수 있다. 다만, ${(1,1), (0,2)}$는 직교정규 기저가 아니다. 반면, 그림 2.1.c는 표준 기저는 아니지만 직교정규 성질을 가진 기저 {u, v}를 보여준다. 이를 이용하면 (3,5)는 $4\sqrt{2}u+\sqrt{2}v$로 표현된다.

img 그림 2.2

그림 2.2는 3차원 공간에서의 표준 기저 ${e_1, e_2, e_3}$를 보여준다. 세 개의 주축에 나란한 e1, e2, e3는 각각 (1,0,0), (0,1,0), (0,0,1)이다. 물론 ${e_1, e_2, e_3}$는 직교정규 성질을 가진다. 지금부터 이 책은 2차원과 3차원 공간 모두에서 직교정규 기저만을 다룰 것이다.


2.3 내적


두 개의 n차원 벡터 a와 b를 각각 (a1, a2, … , an)과 (b1, b2, … , bn)로 표현한다면, a와 b의 내적 (inner product 또는 dot product)은 $a \cdot b$로 표기되고 다음과 같이 정의된다.

\[a \cdot b = \sum_{i=1}^n a_i b_i = a_1b_1 + a_2b_2 + ... + a_nb_n\]

img 그림 2.3. 두 벡터의 상대적인 방향에 따라 내적의 부호가 달라진다.

한편, 두 벡터 a와 b 사이의 각도를 $\theta$로 표기하면 $a \cdot b$는 기하학적으로 다음과 같이 정의된다.

\[a \cdot b = \lVert a \rVert \lVert b \rVert \cos \theta \tag{2.10}\]
  • a와 b가 서로 수직 : $\theta$ = $90^\circ$, $a \cdot b$ = 0
  • $\theta$ = 예각 (0 < $\theta$ < 90), $a \cdot b$ = 양수
  • $\theta$ = 둔각 (90 < $\theta$ < 180), $a \cdot b$ = 음수

이는 a와 b가 3차원 벡터일 경우에도 동일하게 발견되는 특성이다.

식 (2.10)으로 추론할 수 있는 것은, 하나의 단위 벡터를 자기 자신과 내적하면 1이 된다는 것이다. 즉, a가 단위 벡터라면, $a \cdot a$는 1이다. 이를 이용하여 직교정규 기저의 중요한 성질 한 가지를 살펴보자.

  • 2차원 표준 기저 ${e_1, e_2}$의 경우, $e_1 \cdot e_1$ = 1 이고, $e_2 \cdot e_2$ = 1
  • 서로 수직인 두 벡터의 내적은 0이므로, $e_1 \cdot e_2 = e_2 \cdot e_1$ = 0

즉, 하나의 직교정규 기저가 있을 때, 동일한 기저 벡터 간의 내적은 1이고, 다른 기저 벡터 간 내적은 0이다.

3차원 표준 기저 ${e_1, e_2, e_3}$에서도 마찬가지이다. 벡터 $e_i$와 $e_j$가 주어졌을 때, i와 j가 같다면 $e_i \cdot e_j$ = 1이고, i와 j가 다르다면 $e_i \cdot e_j$ = 0이다. 이는 모든 직교정규 기저가 가지는 성질이다.


2.4 벡터곱


두 개의 3차원 벡터 a와 b의 벡터곱(cross product)은 a * b로 표기되는데, 이는 그림 2.4.a(1,2번째 그림)에서 보인 바와 같이 a와 b에 모두 수직인 또 다른 3차원 벡터이다. 벡터곱 a * b의 방향은 오른손 법칙(right hand rule)으로 결정된다. 즉, 오른손 네 손가락이 첫 번째 벡터 a에서 두 번째 벡터 b쪽으로 감싸며 움직일 때 엄지손가락이 ab의 방향을 가리키게 된다. 한편, ab의 길이는 a와 b에 의해서 만들어지는 평행사변형의 넓이와 같다.

\[\lVert a \times b \rVert = \lVert a \rVert \lVert b \rVert \sin \theta \tag{2.11}\]

img

오른손 법칙에 따르면 ba와 ab는 서로 반대 방향을 가진다. 즉, 그림 2.4.b(3번째 그림)처럼 ba = -(ab)가 된다. 이런 점에서 벡터곱을 반가환적(anti commutative)이라 부른다. 물론, ab와 ba의 길이는 같다. 두 벡터 a와 b를 각각 $(a_x, a_y, a_z)$와 $(b_x, b_y, b_z)$로 표현하면, a*b는 $(a_y b_z - a_z b_y, a_z b_x - a_x b_z, a_x b_y - a_y b_x)$가 된다.


2.5 직선 및 선형 보간


img 그림 2.6.a

img 그림 2.6.b

img 그림 2.6.c

그림 2.6.a에서 두 개의 점 p0과 p1을 지나는 직선을 생각해 보자. 이 직선은 p0, 그리고 p0과 p1을 잇는 벡터인 p1 - p0을 사용하여 다음과 같은 매개변수 방정식(parametric equation)으로 정의된다.

\[p(t) = p_0 + t(p_1 - p_0) \tag{2.16}\]

여기에서 t는 $[-\infty, \infty]$ 범위에 놓이는 매개변수인데, t가 0이면 p(t)는 p0가 되고, t가 1이면 p(t)는 p1이 되며, t가 0.5이면 p(t)는 p0과 p1의 중간점이 된다. 그림 2.6.a는 몇 개의 예를 더 보여주고 있다.

이렇게 t가 $[~\infty, \infty]$ 범위를 가지면, 식 (2.16)의 p(t)는 양쪽으로 무한히 뻗은 직선을 표현한다. 만약 t의 범위가 $[0, \infty]$라면, p(t)는 p0에서 시작해서 p1 - p0 방향으로 무한하게 뻗어나가는 광선(ray)이 된다. 반면, t의 범위가 유한하게 한정된다면, p(t)는 선분을 표현한다. 예를 들어, 그 범위가 [0, 1]이라면 p(t)는 p0와 p1을 잇는 선분이 된다.

식 (2.16)을 다시 쓰면 다음과 같다.

\[p(t) = (1 - t)p_0 + t p_1 \tag{2.17}\]

위 식에서 (1 - t)와 t를 각각 p0와 p1에 대한 가중치(weight)로 보면, p(t)는 p0와 p1의 가중치 합(weight sum)이 된다. 특히, t의 범위가 [0, 1]일 때, p(t)는 p0와 p1의 선형보간(linear interpolation)이라고 한다. 그림 2.6.b를 보자.

식 (2.17)의 함수 p(t)는 2차원 공간에서는 (x(t), y(t)), 3차원 공간에서는 (x(t), y(t), z(t))가 된다. p0과 p1의 3차원 좌표를 각각 (x0, y0, z0)와 (x1, y1, z1)이라고 할 때, 각 좌표값에 선형보간을 적용하여 p(t)의 좌표를 얻는다.

\[p(t) = \begin{pmatrix} x(t) \\ y(t) \\ z(t) \end{pmatrix} = \begin{pmatrix} (1 - t)x0 + tx1 \\ (1 - t)y0 + ty1 \\ (1 - t)z0 + tz1 \end{pmatrix} \tag{2.18}\]

한편, p0와 p1에 특정한 값이 저장되어 있다면, 그 값들도 선형보간될 수 있다. 예를 들어, p0에 c0라는 색상이 저장되어 있고 그 원소를 (R0, G0, B0)라 하자. 마찬가지로, p1에 c1이라는 색상이 저장되어 있고 그 원소를 (R1, G1, B1)이라 하자. RGB 원소 각각은 대개 [0, 255] 범위의 정수값 혹은 [0, 1] 범위의 실수값을 가지는데, 선형보간된 색상 c(t)는 다음과 같이 정의된다.

\[c(t) = (1 - t)c_0 + tc_1 = \begin{pmatrix} (1 - t)R_0 + tR_1 \\ (1 - t)G_0 + tG_1 \\ (1 - t)B_0 + tB_1 \end{pmatrix} \tag{2.19}\]

그림 2.6.c는 색상 선형보간의 몇 가지 예를 보여주는데, t가 0이면 c(t)는 c0가 되고, t가 증가할수록 c(t)는 c1에 가까워지며, t가 1이 되면 c(t)는 c1이 된다.


연습문제


Q1) 3차원 직교정규 기저를 생각해 보자. 첫 번째 기저 벡터는 아래 그림과 같이 (3,4,0) 방향을 향하고, 두 번째는 하나의 주축을 향하며, 세 번째는 그 둘의 벡터곱으로 정의된다. 이 기저를 계산하라.

img

A1)

각각의 3차원 직교정규 기저를 (u, v, w)라고 하자.

직교정규 기저는 모든 축의 길이가 1이어야 한다. 첫 번째 기저 벡터 (3,4,0)을 단위 벡터로 만든다.

벡터의 크기 = $\sqrt{3^2 + 4^2 + 0^2}$ = $\sqrt{25}$ = 5. u는 방향 벡터를 크기로 나눈 값이다.

u = 1/5(3,4,0) = (3/5, 4/5, 0)

v는 하나의 주축을 향하므로 u와 수직이어야 한다. 즉, 내적 시 0이 나와야 한다.

  • x축 (1, 0, 0) : $u \cdot (1,0,0)$ != 0
  • y축 (0, 1, 0) : $u \cdot (0,1,0)$ != 0
  • z축 (0, 0, 1) : $u \cdot (0,0,1)$ = 0

v = (0, 0, 1)이고 이미 크기도 1이다.

w는 u와 v의 벡터곱으로 정의된다.

w = u*v = (4/5, -3/5, 0)

따라서 3차원 직교정규 기저는 {(3/5, 4/5, 0), (0, 0, 1), (4/5, -3/5, 0)}이다.


Q2) 두 개의 점 p0과 p1이 있다. p0의 좌표는 (2,0)이고 p1의 좌표는 (5,0)이다. p0에 벡터 (-1,2)가 저장되어 있고, p1에는 벡터 (2,5)가 저장되어 있다. p0와 p1을 잇는 선분을 따라 두 벡터를 선형보간할 때, 선분 위의 점 (4,0)에 놓일 벡터를 계산하라.

A2) 먼저 점(4,0)를 X라고 하고 X가 p0에서 p1으로 가는 경로 중 몇% 지점(t)에 있는지 구하자.

Y좌표가 모두 0이니, X좌표만 보고 직관적으로 구할 수 있다.

  • p0 = 2
  • p1 = 5
  • X = 4
  • 2에서 5까지의 길이는 3이고, 2에서 4까지 가려면 2만큼 이동했다. 전체 길이 중 2/3을 이동했다.
  • t = 2/3

t를 벡터 보간 공식에 대입하자.

\(v(t) = (1 - t)v0 + tv1\) -> \(v(2/3) = (1 - 2/3)(-1, 2) + (2/3)(2, 5) = 1/3(-1, 2) + 2/3(2, 5)\)

이제 구하고자 하는 벡터의 X 성분과 Y 성분을 각각 나누어 계산하자

  • X = 1/3(-1) + 2/32 = 1
  • Y = 1/32 + 2/35 = 4

선분 위의 점 (4,0)에 놓이게 될 보간된 벡터의 값은 (1,4)이다.


참고

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