지우너

[한정현 컴퓨터 그래픽스] 4장 좌표계와 변환 본문

Programming/OpenGL

[한정현 컴퓨터 그래픽스] 4장 좌표계와 변환

지옹 2023. 12. 22. 11:34

본 글은 한정현 교수님의 "컴퓨터 그래픽스" 강의를 정리한 글입니다(강의에 사용된 ppt 링크).


4장에서는 세 가지 중요한 변환을 살펴본다.

① Scaling (축소/확대)

Rotation (회전)

③ Translation (이동)

 

 

Scaling (축소/확대)

[그림1]

2 차원 축소/확대 경우 축소/확대 인자(x 방향, y 방향) 사용

어떤 벡터 x좌표가 주어졌을때 그 앞에 Sx 를 곱하고, y 좌표가 주어졌을 때 Sy 를 곱하면 이것이 축소/확대된 벡터를 나타냄.

그래픽스에서는 이러한 변환을 모두 행렬의 곱셈으로 표현한다. 따라서 축소/확대 되어야 할 벡터를 그림 16의 오른쪽과 같이 column vector로 표현하고 축소 확대될 벡터를 주 대각선에 놓아서 2x2 행렬을 만들어 곱한다.

 

 

[그림2]

예를 들어 어떤 다각형 있을 때 다각형을 구성하는 모든 정점마다 이 행렬을 적용을 하면 다각형 자체가 축소 확대 된다.

 

 

예를 들어 축소 확대 인자가 모두 2인 경우를 살펴보자.

[그림3]

나머지 꼭지점에 대해서도 이렇게 x 방향 y 방향 모두 2배를 확대를 한 꼭지점을 새로 얻게 된다.

그 친구들을 모두 이으면 그림17의 중앙에 있는 것 같이 확대된 다각형을 얻을 수 있게 된다.

 

x축 방향, y축 방향 축소/확대 인자가 달라도 된다. 그림17의 오른쪽 그림의 경우 x축 방향으로 3/2, y축방향으로 1/2이 축소 확대 인자가 1보다 작다는 건 축소가 된다는 의미. 따라서 x방향으로는 확대가 되고, y방향으로는 축소가 된다는 의미.

 

 

 

Rotation (회전)

[그림4]

어떠한 벡터 p가 주어졌을 때, 이것을 θ만큼 회전해서 p를 다시 얻게 될 것이다.

p의 좌표(x, y)라고 하고, 회전각을 θ라고 했을 때, p'의 좌표(x', y')를 구해보자.

p벡터의 길이가 r이라고 한다면, p의 x좌표는 rcos∅, y좌표는 rsin∅가 된다. 

p'의 좌표는 (rcos(∅+θ), rsin(∅+θ)), 그림 20을 참고하면 그림 19의 풀이가 잘 이해 될 것!

[그림5] 삼각함수의 덧셈정리

 

 

 

 

[그림6]

 

 

여기서 본 것처럼 (2, 0)을 90도 회전하면 (0, 2)라는 좌표를 얻게 된다.

그러면은 왼쪽 회전 행렬의 θ에 다가 90도를 집어 넣으면 2x2 사이즈의 행렬을 얻을 수 있다(회전행렬도 2x2  행렬로 표현된다는 것). 이 행렬을 주어진 점 (2, 0)에 적용을 하면 (0, 2)가 나온다.

 

 

위의 회전(반시계 방향으로 90도 회전했을 때를 설명했다)은 기본적으로 반시계 방향의 회전을 표현한다. 

[그림7]

 

그런데 시계방향으로 90도 회전할 수도 있다. 시계방향 회전은 θ대신 -θ를 집어넣는다. 예를들어 시계방향으로 90도를 회전하고 싶으면 90도가 아니라 -90도를 회전행렬 공식에 집어넣으면 되는 것.

-90도를 대입해서 나온 행렬을 (2, 0)에다가 적용하면 (0, 2)를 얻게 된다.

한편 시계방향으로 90도 회전은 시계방향으로 270도 회전 하는 것과 같다. 270도를 회전 행렬 θ에 집어 넣으면 위와 같은 행렬을 얻을 수 있다.

 

[그림8]

이 행렬을 주어진 점 (2, 0) 더 집어 넣으면 (0, -2)가 산출된다. 당연히 시계방향으로 90도 돌린 결과와 반시계방향으로 270도 돌린 결과는 같다.

 

 

Scaling과 Rotation은 둘 다 2x2행렬로 정의가 되고, 변환이 이루어질 벡터와 곱해져서 적용한다.

 

 

 

 

Translation (이동)

세 번째 변환 Translation 주어진 점의 x, y를 dx, dy 만큼 이동시키는 것. 

[그림9]

그 과정은 변이 벡터를 원래 주어진 점에 더해서 벡터 덧셈으로서 표현. Scaling과 Rotation은 행렬곱으로 표현이 됐는데, Translation은 벡터 덧셈으로 표현이 된다. 동차좌표(Homogeneous coordinates)를 이용하면 Translation도 행렬곱셈으로 표현이 가능하다.

(Scaling과 Rotation이 행렬곱이니까 통일되는 편이 좋아서)

 

[그림10]

 

이차원 좌표(x, y)가 주어졌을 때 세 번째 좌표를 그냥 1로 넣는다 (x, y, 1). 그러면 이게 바로 동차좌표가 되는 것(동차 좌표계는 n차원 좌표를 n개 요소가 아닌 n+1개 요소로 표현).

그 다음에 우리는 단위행렬(identity matrix)을 안다. 주대각선이 1이고 나머지가 0으로 채워진 행렬. 여기의 세 번째 column에다가 변위 벡터 dx dy를 집어넣는다. 그러면 3x3사이즈의 행렬이 얻어진다.

 

[그림11]

동차좌표계로 표현한 (x, y, 1)에 3x3행렬을 곱하면 위와 같은 결과가 나온다. 결과 행렬의 마지막 원소 1은 (x, y, 1)을 만들 때 그냥 넣었던 것(그냥 넣는 건 아닌 것 같지만). 따라서 위의 두 원소만 보면 결국 벡터의 덧셈을 했던 것과 결과가 같아진다.

 

Scaling과 Rotation과 차이는 있다. 변환 벡터가 3x3사이즈라는 것.

 

아무튼 Homogeneous coordinates가 굉장히 유용하다. 앞에서는 2차원 좌표를 그대로 두고, 세번째 좌표로 1을 추가 했다.

하지만 2D 점 (x, y)가 주어졌을 때, 그 동차좌표는 (x, y, 1)이 아니라 0이 아닌 모든 w를 가진 (wx, wy, w)일 수 있다.

 

예를 들어 데카르트 좌표(Cartesian coordinates) (2,3)은 (2,3,1), (4,6,2), (6,9,3) 등의 여러 동차좌표로 변환할 수 있다.

이처럼 하나의 데카르트 좌표(Cartesian coordinates)가 주어졌을 때 그것에 해당하는 동차좌표는 무한하게 존재.

[그림12] 데카르트 좌표와 동차좌표계를 설명하는 그림

 

2차원 공간을 정의하는 x축, y축에 w축이 더해져서 3차원 공간을 만든다고 생각하면 된다. 

그리고 w좌표가 1인 곳에 하나의 평면을 생각을 할 수가 있다. 물론 이 평면의 공식은 w=1이다.

그래서 (2, 3)이라는 데카르트 좌표가 있을 때, 이 좌표를 평면 위로 끌어올린다. 그러면 동차좌표의 대표격인 (2, 3, 1)이 만들어진다.

그렇게 만들어진 점을 원점과 이으면 하나의 직선이 정의가 된다. 이 직선에 (2, 3)에 해당하는 모든 동차좌표들이 다 모여 있다.

 

동차좌표가 주어졌을 때, 데카르트 좌표계로 변환하는 법

3개의 좌표(wx, wy, w)를 모두 w로 나누면 된다. 그러면 3번째 좌표는 1이 되고, 앞의 2개가 데카르트 좌표계에 해당하는 결과가 된다.

 

그래픽스에서는 동차좌표를 굉장히 많이 사용하므로 이를 제대로 이해하는 것이 중요하다!

 

 

 

Scaling과 Rotation은 2x2행렬이다. 이것도 통일성을 줘야함. 모든 좌표는 (x, y, 1)로 표현될 것이기 때문이다.

[그림13] Scaling과  Rotation 행렬을 3x3으로 변환

3번째 행열에 001을 추가하여 3x3으로 만들 수 있다.

 

 

 

 

어떤 물체에 대한 변환이 여러 번 이루어질 수도 있다. 어떤 다각형을 90도 회전시킨 뒤 이동시킬 수도 있는 것.

[그림14]

 

90도 회전을 R(90도)로 표현.

반시계방향으로 90도 회전하는 거니까 중앙의 그림과 같은 결과가 나온다.

회전된 다각형을 (7, 0)만큼 이동시키면, (7, 0)이라고 하면 변이벡터를 따라(즉, x축을 따라) 7만큼 이동

 

이렇게 하나의 다각형의 2개의 변환을 연속적으로 정의할 수 있다.

우리는 R(90도)의 행렬을 알고 있다. 여기에 (0, 4, 1)을 넣으면 (-4, 0, 1)이라는 결과가 나온다. 이 행렬에 트렌스레이션 행렬을 다시 적용한다. 그럼 (3, 0, 1)이라는 값이 나온다.

 

 

 

Rotation과 Translation이 모두 3x3 행렬이라는 것에 주목(둘은 서로 결합이 가능)

[그림15]

Rotation이 먼저 되고, Translation이 나중에 되기 때문에 Rotation이 오른쪽에 쓰여져야 한다.

이렇게 두 연산을 행렬곱한 후, 그 결과를 원래의 점과 행렬곱하면 그림 29에서 연산했던 것과 같은 결과가 나온다.

이것을 Transform Composition이라고 한다.

 

 

 

행렬곱셈은 교환법칙이 성립하지 않는다.

[그림16]

TR은 Rotation을 먼저 적용한 후 Translation을 시킨 것이고, RT는 Translation을 먼저 적용한 후 Rotation을 적용한 것이다.

 

 

 

이제 배운 것을 한 단계 확장해보자.

지금까지 우리가 배운 Rotation은 원점을 중심으로 정의된 Rotation이었다. 임의의 점을 중심으로 Rotation을 정의해보자.

[그림17]

 

(5, 2)라는 점을 (3, 2)를 중심으로 반시계 방향 90도 회전. 직관적으로 (3, 4)가 나올 거라는 걸 알 수 있다.

Rotation 행렬에 90도를 집어넣어서 3x3 행렬을 만들었다. 여기에 (5, 2, 1)을 적용하면 결과는 (-2 5, 1)이 나온다(당연히 답과 다름). 

왜냐하면 그림34의 Rotation 행렬은 (3, 2)라는 임의의 점이 아니라 원점을 중심으로 반시계 방향 90도 회전을 표현했기 때문.

 

 

 

 

 

[그림18]

 

(3, 2)가 원점이면 좋겠다(그러면 위에 나온 로테이션 행렬을 적용시킬 수 있으니까) → (3, 2)를 원점으로 이동(Translation 적용)

변이 벡터는 (-3, -2)가 될 것이다. 회전 중심축만 원점으로 바뀌면 안 된다. 회전할 점도 같은 값에 의해 변해야 한다(-3, -2) Translation을 해야한다는 의미) → (5, 2)는 (2, 0)이 된다.

이제 원점 중심으로 회전을 적용한다. 점은 (0, 2)가 된다.

(0, 2)에서 (3, 2) 방향으로 다시 이동시킨다(아까 (-3, -2)방향으로 이동시켰으니까) → (3, 4)가 됨

⇒ 우리가 원했던 결과와 동일한 결과가 나온다.

 

 

 

<실제 행렬을 만들어서 적용하기>

[그림19]

 

첫 번째 변환은 Translation (-3, -2)라는 변이벡터를 3번째 column에 집어넣는다. 그리고 여기에 (5, 2, 1)을 적용시킨다. 그 결과는 (2, 0, 1)이 나온다. 그리고 90도 회전변환행렬에 (2, 0, 1)을 적용시키면 (0, 2, 1)이 나온다. (0, 2, 1)에 원상복구시키기 위한 (3, 2) Translation 행렬을 적용시키면 (3, 4, 1)이라는 행렬이 나오는 것.

 

그런데 위의 3가지 변환 행렬은 모두 3x3이므로 (3번째 변환)(2번째 변환)(1번째 변환) 순으로 놓고 행렬곱을 하면 최종 3x3 변환 행렬이 나온다. 이 변환 행렬을 원래의 점 (5, 2, 1)에 적용시키면 (3, 4, 1)이 된다. 

 

 

지금까지 Scaling, Rotation, Translation에 대해 배웠다.

그 중에서 Scaling과 Rotation은 이른바 선형 변환(linear transformation)이라고 하는 커다란 범주에 들어간다(같은 카테고리라는 것 정도만 이해하기).

 

근데 Translation은 다른 범주 선형 변환과 Translation을 묶어서 아핀 변환(Affine Transform)이라고 부른다.

[그림20]

 

아핀 행렬이 몇 개 주어지더라도 행렬을 결합하여 하나의 행렬로 만들 수 있다. 일련의 아핀 변환을 연결하여 단일 3x3 행렬을 만들 때 세 번째 행은 항상 (0 0 1)이다(Homogeneous coordinates 때문에 들어간 것).

 

 

 

 

 

 

[그림21]

 

 

세 번째 행은 항상 0 0 1 이니까 무시하고, 첫 번째와 두 번째 행(2x3)만 보자. 그럼 그 중에서 처음 2개 2x2 행렬을 L이라고 약칭해서 부르고, 나머지 3번째 column을 t라고 약칭하여 2x3 요소를 [L|t]로 표시한다.

- L은 선형 변환(linear transform)이 결합되어 있는 곳을 나타내며, 여기에는 입력으로 주어진 Translation이 못 들어간다.

- 반대로, t는 결합된 '이동'을 나타내며, 입력된 선형 변환 요소가 포함될 수 있다. 선형 변환 요소가 어떤식으로 포함이 되었든 (x방향, y방향)으로 이동하라는 의미

 

 

[그림22]

 

TR: 회전 변환 R을 먼저 적용하고, Translation을 한 것.

선형 변환만 L자리에 들어갈 수 있다. 입력으로 주어진 것을 보면 선형 변환 중에서는 Rotation 하나만 들어가있다. 따라서 Rotation의 L부분이 결과에 그대로 들어가는 것.

 

RT: 그러면 RT를 보자. RT의 결과로 나온 행렬의 L부분에서도 입력으로 주어진 유일한 선형변환 Rotation의 L부분이 그대로 들어가 있다.

 

SRT: 마지막으로 RT에 Scaling까지 곱해보자. 입력으로 주어진 선형변환이 Rotation 뿐만 아니라 Scaling까지 있다. 둘의 원소들이 결합되어 결과의 L 부분이 들어간다. 여기에 포함되는 행렬이 많아질수록 L부분이 복잡해지지만, 사이즈는 여전히 2x2이고, 여기에는 입력으로 들어온 선형 변환만 들어간다는 것.

 

t라고 하는 3번째 column은 어떨까.

TR의 t부분에는 입력으로 들어온 Translation 요소만 그대로 들어가 있다. 이는 특별한 경우.

RT, SRT를 보면 선현변환과 Translation 요소가 결합되어서 t에 들어가있다.

 

 

 

<예시>

TR의 경우

[그림23]

 

실제 이 경우를 보면 입력으로 주어진 선형변환이 Rotation 부분 뿐이다. 회전행렬의 L부분이 결과의 L부분에 그대로 들어가 있다.

t부분도 입력에 주어졌던 이동 변환 행렬의 t가 그대로 들어가 있다(특수한 경우)

 

 

 

 

두 변환의 순서를 바꿔 RT의 경우를 보자. 행렬의 경우 교환 법칙이 성립이 안 된다.

[그림24]
[그림25]

 

결과는 위와 같이 나온다. 일반식이 그림39 'RT=~' 부분과 같이 나왔다. 실제 데이터를 넣어서 보면, 선형변환은 회전 변환 밖에 없으니까 L 부분에 그대로 들어온다. 그런데 t는 입력의 t가 그대로 들어오지 않은 것을 알 수 있다.

 

이렇게 하여 아핀변환을 행렬의 형태로 [L|t]로 표현한다는 것을 배웠다. 그런데 이것을 어떻게 해석할까.

입력으로 1000개의 행렬을 곱하건 어찌 됐건 결과는 [L|t]이다. 단일한 하나의 행렬이 주어졌을 때 우린 2단계로 변환을 나눠서 생각할 수 있다. 

어떤 물체에 [L|t]를 적용한다는 것은 L을 먼저 적용해서, 그 물체를 선형변환 시키는 것. 그 다음에 선현변환된 물체를 t를 이용해서 Translation 시키는 것.

 

 

그림39 그림의 결과 와 그림40 그림의 결과가 같다는 것이 아주 중요한 포인트

 

 

얼마나 많은 아핀 행렬을 결합하든 상관없이 단일 행렬 [L|t]를 얻습니다. [L|t]가 점 p를 변환하는 방식은 Lp+t.

 

 

 

 

그래서 우리는 아핀 변환 (Affine Transformation)이 [L|t]로 표현이 된다. 그런데 여기에는 Scaling, Rotation, Translation이 들어간다는 것을 배웠다. 근데 이 중에서 Rotation, Translation만 생각해보자.

 

[그림26]

 

1. 회전과 이동만 조합한 경우, 즉 Scaling이 포함되지 않은 경우를 생각해보자.

1-1. 결합된 아핀 행렬을 객체에 적용하면 객체의 pose(위치 + 방향)는 변경되지만 모양은 변경되지 않습니다.

1-2. 이러한 의미에서 이 변환을 Rigid-body motion 또는 Rigid motion이라고 부른다. 물체가 변하지 않는다는 의미.

 

2. 얼마나 많은 회전과 이동을 결합하든 결과 행렬은 [R|t] 구조(2x3 행렬)입니다.

2-1. R은 회전을 나타내며, Scaling는 포함되지 않습니다. R은 2x2 행렬

2-2. t는 일반적으로 회전 항을 포함하는 '결합된' Translation 을 나타냅니다.

 

3. R|t]로 개체를 변환하는 것은 개념적으로 두 단계로 나뉩니다: R이 먼저 적용된 다음, 회전된 물체가 t에 의해 변환됩니다. 즉, [R|t]가 점 p를 변환하는 방식은 Rp+t입니다.

 

 

우리는 Scaling이 포함된 아핀 변환 [L|t]보다 Rotation과 Translation만으로 구성된 아핀변환[R|t]를 훨씬 많이 쓸 것이다.

 

 

 

 

<3차원으로 확장하기>

Scaling

2차원 Scaling에서는 (x, y)방향 Scaling 벡터를 이야기 했다. 3차원은 z축이 있으니까 (x, y, z)

[그림 27]

 

 

Rotation

로테이션은 조금 생각할 게 있다. 2차원은 점 중심의 회전이었다. 3차원은 축 중심으로 회전을 이야기한다. 회전축이 필요.

가장 기본적인 게 x, y, z축을 중심으로 한 회전

 

z축 중심 회전

[그림28]

 

z축을 중심으로 90도 회전하면 주전자가 저런 식으로 바뀐다.

 

이제 3차원 회전을 정의하는 행렬을 만들어서 행렬을 저 주전자의 모든 정점마다 적용하면 회전된 주전자가 나온다.

3차원 공간에서 z축을 중심으로 𝜃만큼 회전시키면 z좌표에는 변화가 없다. 

x, y좌표는 이차원 회전에서 𝜃만큼 회전했던 값과 같다. 좌표가 2차원 평면에 있거나 3차원 공간에 떠있거나 x, y 좌표 자체는 동일.

이를 행렬로 표현한 것이 그림43 우측 하단의 행렬.

z축을 중심으로 𝜃만큼 회전하는 회전행렬 → R_z(𝜃)라고 표현함

 

x축 중심 회전

[그림29]

 

z축을 중심으로 회전할 때 z 자신이 z'와 같다는 것을 이야기 했었다.

그걸 떠올리면 x축 중심 회전에서 x와 x'가 같다는 것은 너무 당연한 사실.

y, z좌표를 알아내야 한다. 우리가 x축 방향에서 y, z축을 바라보고 있다고 생각했을 때, x축을 중심으로 90도 회전하면 y축이 z축을 향해 돌아간다고 생각할 수 있다(R_z에서 회전축을 바라봤을 때, z축을 중심으로 90도 회전하면 x축이 y축을 향해 회전하는 것처럼 보인다).

 

R_z에서는 x축이 y축 방향으로 회전하는데, R_x에서는 y축이 z축 으로 회전. x축→y축 에서 y축→z축으로 바뀐 것.

R_z에서 썼던 식에서 x를 y로 바꾸고, y를 z로 바꾸면, x축 중심 회전 행렬이 나오게 된다!!

 

 

 

y축 중심 회전

 

[그림30]

 

위에서 적용했던 트릭을 한 번 더 적용하면 그림45의 행렬을 얻을 수 있다.

 

2차원에서 점을 기준으로 회전했던 것과 달리 3차원은 축을 중심으로 회전하기 때문에 각 축을 중심으로 회전 행렬을 정의했다.

 

 

 

- 시계방향 vs. 반시계방향

[그림31]

 

2D 회전에서 양수 각도는 반시계 방향을 나타내고 음수 각도는 시계 방향을 나타낸다.
축을 중심으로 한 3D 회전의 경우 축이 내 눈을 향하고 있다고 가정.
회전이 반시계 방향인 경우 회전 각도는 양수, 회전이 시계 방향인 경우 해당 행렬은 음의 회전 각도로 정의됩니다.


엄지 손가락을 회전 축에 맞췄을 때, 회전이 나머지 네 손가락의 컬링 방향을 따라 이루어지면 회전 각도는 양수, 그렇지 않으면 음수 
θ에 의한 회전은 2π-θ에 의한 회전과 동일하다는 점에 유의.

 

 

Translation

[그림32]

 

2차원에서 했던 것처럼 3차원에서는 4x4 사이즈의 단위행렬을 사용한다. 4번째 column에 3차원 변이벡터를 넣어준다.

2차원에서 했던 것처럼 Scaling과 Rotatoin 또한 4x4 행렬로 확장해줘야 한다. Scaling, Rotation, Translation 모두 4x4 행렬로 표현되기 때문에 몇 번을 변환하든 4x4행렬로 표현가능.

 

 

 

 

 

[그림33]

 

구와 주전자로 구성이 된 3차원 공간을 보자. 구와 주전자는 처음 만들어졌을 때 어떤 좌표계를 기준으로 만들어졌을 것이고, 대개의 경우 원점 가까이 놓여있을 것이다. 

3차원 공간에서는 그런데 겹쳐있으면 안된다. 구 같은 경우 원래는 좀 작게 만들었는데, 크게 만들기도 하고 그래야 한다. 이런 것을 해결하기 위해 변환이 쓰인다. 우리가 좌표계(coordinate system)을 2가지로 구분

- object space: 처음 오브젝트가 만들어졌을 때 쓰는 좌표

- world space: 모든 폴리곤 메쉬로 표현된 물체가 배치되는 곳

 

구는 나름의 object 공간에서 만들어졌고, 주전자 역시 나름의 object 공간에서 만들어졌다. 둘을 단일한 게임 공간으로 옮겨야 한다.

object space→world space 이렇게 옮겨갈 때 transform이 필요하다. 

구는 object 공간에서 반지름이 1인 상태로 만들어졌는데, world space에서 크기를 키우고 싶다. 필요한 변환은 Scaling 하나.

world space에서 반지름이 2니까 2로 설정한 Scaling 행렬을 이용하여 변환하면 된다.

 

이렇게 object space에서 world space로 가는 변환은 world transform이라고 이야기 한다.

 

 

 

 

 

주전자는 Rotation과 Scaling, Translation 3가지가 모두 쓰였다.

[그림34]

 

 

 

먼저, y축 중심으로 반시계 방향 90도 회전을 한다. R_y(90도)라고 쓰고, 변환 행렬에 90도를 대입하여 행렬을 얻는다. 현재 좌표(0, 2, 3, 1)과 행렬곱하여 변환된 좌표(y축 중심 반시계90도 회전한 좌표) (3, 2, 0, 1)을 얻는다.

그리고 해당 좌표에서 (7, 0, 0)만큼  이동시키기 위해 Translation 행렬과 행렬곱을 하면 (10, 2, 0, 1)의 좌표를 얻을 수 있다.

 

이차원과 마찬가지로 모든 변환 행렬을 곱해서 최종변환(90도 회전 + (7, 0, 0) 이동) 행렬을 얻은 후, 현재 좌표와 행렬곱하여 (10, 2, 0, 1)을 얻을 수도 있다. 이차원에서와 마찬가지로 TR 순으로 행렬을 곱했을 때 Rotation후 Translation한 행렬이 나온다.

 

 

2차원에서 3x3행렬이 나왔었는데 마지막 행이 항상 (0, 0, 1)이었다.

3차원에서도 마찬가지다. 4x4 행렬에서 마지막행은 항상 (0, 0, 0, 1)이 되고, 마지막 행을 제외한 3x4 행렬의 3x3부분(그림35의 빨간색으로 표시된 부분)을 결합된 선형변환 L, 1x3 부분을 t라고 한다.

 

 

[그림36]

 

2차원에서와 마찬가지로 선형 변환 후 이동하도록 L, t행렬을 나눈 후 곱해도 결과는 동일하다(L을 적용한 후 t를 적용해도 같은 결과를 얻을 수 있다는 의미).

 

 

 

 

[그림 37]

 

객체가 생성되면 객체는 해당 객체의 object space에 만들어진다. 처음 만들어졌을 때는 object space와 world space가 동일하다.

obejct space basis는 {u, v, n}, world space basis는 {e1, e2, e3}로 표현하는 것이 관례

객체에 회전을 적용하면 객체의 방향이 변경되며, 이는 객체의 object space의 basis가 회전되었다고 설명할 수 있다.

 

 

오브젝트가 생성되었을 때 object space basis {u, v, n}

u는 x축이 1인 방향 (1, 0, 0), v는 y축이 1인 (0, 1, 0) 방향, n은 z가 1인(0, 0, 1)의 방향을 가리킨다.

 

위 그림37과 같이 회전(y축은 변하지 않았으니 y축을 중심으로 반시계 90도 회전인 것 같다)하면 

u는 z축의 반대(-1) 방향 (0, 0, -1), v는 y축이 1인 (0, 1, 0) 방향, n은 x가 1인(1, 0, 0)의 방향을 가리킨다.

 

basis 한국어로 하면 '기저'를 앞에서 배웠는데, 잘 기억이 안 난다.

지금 생각나는 건  두 벡터가 있고, 그 두 벡터 사이의 각도가 직각이면서 둘을 곱했을 때 1이 되면이었나...? 그러면 orthonormal하다고 배웠던 거 같다. 좌표계에서 basis라는 말이 나오는 것은 x, y, z축이 모두 서로 직각이기 때문에? 이런 말이 나오는 것 같다.

그래서 음... 복습을 한번 해야할 것 같긴 한데, basis≒축 이라는 정도로 이해하면서 강의를 듣고 있다.

 

 

 

[그림38]

u의 좌표는 초기에 (1, 0, 0)이고 R에 의해 회전되어 (u_x, u_y, u_z)가 된다(v(0, 1, 0), n(0, 0, 1)도 동일).

위의 3가지를 결합하면 R 행렬이 나온다.

R의 열은 u, v, n이며. '회전된' object-space basis {u, v, n}이 주어지면 회전 행렬이 즉시 결정된다. 반대로 회전행렬이 주어질 경우에도 object-space basis {u, v, n}이 즉시 결정된다.

 

R_y(90°)를 회전행렬에 대입하면 u, v, n 축이 실제로 그렇게 회전하는지 검산도 할 수 있다(그림38의 빨간 네모, u(0, 0, -1), v(0, 1, 0), n(1, 0, 0)).

 

 

[그림39]

 

x, y, z축 외에 임의의 축을 기준으로 회전할 수도 있다. u, v, n을 안다면 회전 행렬을 구할 수 있다.

 

 

 

 

역변환

Scaling, Rotation, Translation으로 변환한 것을 다시 원래 상태로 돌리는 것

 

- Translation

[그림40]

 

변환 행렬과 역변환행렬을 행렬곱 연산하면 단위행렬(I)가 나온다.

 

 

행렬곱에대해 기억이 안 나서 행렬 연산이 Translation은 왜 더하기 연산인 것 같고, Scaling은 왜 곱하기 연산인 것 같은지 이해가 안 됐다.

[그림41] 행렬곱:&nbsp;https://mathbang.net/562

 

 

 

 

- Rotation

역회전

[그림42]

어떤 회전행렬 R이 주어졌을 때, 회전행렬은 u, v, n(object space basis)이라고 하는 3개의 열로 이루어져있다고 배웠다.

그리고 basis vector는 orthonormal한 성질을 갖고 있다. 다시 말해 u, v, n은 단위벡터이면서, 셋 중 어느 쌍을 고르더라도 서로 수직이다. orthonormal basis vector는 자기자신과  내적했을 때 1이 나오고, 나머지 벡터와 내적하면 0이라는 성질을 갖고 있다고 배웠다.

 

R의 전치행렬(열과 행을 서로 바꾼 행렬!)과 R을 곱해보자. 전치R의 행과 R의 열은 둘 다 u. 따라서 ux*ux+uy*uy+uz*uz가 된다. 두 벡터의 성분끼리의 곱의 합이 내적(내적 개념 참고)이므로 u·u와 같고, 자기자신과의 내적은 1이므로 행렬의 첫 번째요소가 1이 되는 것.

나머지 요소의 연산도 위와 동일하게 진행된다(자기자신과 다른 벡터를 내적하면 0이 됨).

 

어떤한 회전행렬에 그의 전치행렬을 곱하면 단위행렬(I, identity matrix)이 나온다. 회전행렬의 역행렬은 전치행렬이라는 의미.

임의의 축을 중심으로 회전하더라도 우리는 회전 행렬을 통해 uvn의 방향을 알 수 있다.