Post Lists

2018년 6월 23일 토요일

The Mathematics of the 3D Rotation Matrix

http://www.fastgraph.com/makegames/3drotation/

특수한 직교하는 행렬의 집합은 닫힌 집합이다. 그것이 무엇을 의미하는가? 왜 우리가 신경써야 할까?

이러한 질문은 보통 upper-division set 이론 수업에서 다뤄진다. 그것은 이론적인 측면에서 수학을 전공하는 상위학년들을 위한 수업이다. 공학 도는 과학을위한 수학이 아니라,  수학 그 자체를 위한 수학이다. 너가 set theory 수업에 도착할 때 즈음에, 너는 모든 어려운 과목들을 지나왔다. 기하학, 삼각함수, 미적분 방정식이 너의 뒤에 있다. Terry Pratchett이 말할지도 모르듯이, 너는 수학을 겪었고 다른 쪽으로 나왔다.

한 upper division set theory 수업에서, 너는 "한 집합은 그것의 성분들을 포함한다"와 같은 수학적인 사실들을 고려할 것이다. 이 사실은 "The Baire Category Theorem" 같은 멋진 이름으로 주어질 것이고, 너는 그것을 증명하라고 요구되어질 것이다. 너가 따라하려는 습관이 있기 때문에 (또는 너는 수학을 통해 그것을 끝내지 않을 것이다.) 너는 정확히 무엇을 할지 안다. 너는 샤프펜을 꺼내고, 이전에 너에게 주어진 정확한 표기법을 사용하여, 너는 4 또는 5줄로 증명을 해낸다. 너는 평화로움과 자신감의 감정으로 가득찬다. 증거의 올바름이 크리스타처럼 개끗하듯이. 그러고나서 펜을 놓는다. 너는 너의 커피가 식기전에 너의 과제를 끝냈다.

한 편, Comp Sci과의 hall을 지나는 너의 친구들은 그들의 과제를 받고 있다 : 운영체제 작성하기. 밑바닥부터. 기한은 화요일까지. 그리고 그러한 녀석들은 내가 왜 수학을 전공했는지 궁금해하기 시작한다.

이 수업에서, 나는 너에게 Baire Category Theorem을 증명하라고 요구하지 않을 것이다. 또는 어떤 유사한 집합 이론 분야의 명백한 특징들의 관찰도. 우리는 믿음을 가지고 특수한 직교행렬들의 집합이 닫힌 집힙이라는 것을 이용할 것이다. 우리는 "why"라는 것보다 "what is it good for(무엇에 좋은지)"에 관심을 둘 것이다. 특수한 직교 행렬들의 닫힌 집합은 어떤 매우 강력한 것에 좋다고 판명이 나있다.

A Review of 3D Graphics Matrices
나는 너가 이미 3D 그래픽스 프로그래밍에 적용했을 때, 행렬을 안다고 가정할 것이다. 그렇지 않다면, 너는 다른 자료로부터 그 정보를 얻길 원할지도 모른다. 3D 행렬 수학의 기초에 대해 기꺼이 쓰려는 수 많은 사람들이 있다. 내가 여기에서 쓸 것은 중간의 것이다. 정확히 해서, 나는 회전 행렬의 흥미로운 특성들에 대해 말하고 싶다. (우연히 특수 직교행렬이 되는, 그리고 그 행렬들의 집합은 닫혀있다. 우리가 계속함에 따라 이것을 염두에 두어라.)

그래서, 리뷰하자면, 3D 기하학 체계에서 관점을 바꿀 때, 너는 각 점을 현재의 위치와 바라보고 있는 사람의 방향에 따라 각 점을 회전하고 평행이동 시킨다. 이것은 가끔 camera position 또는 point of view(POV)라고 불려진다. 너는 또한 3D 기하학 내에서, 유사한 기법을 사용하여, 객체들을 회전하고 평행이동 시킬 수 있다. 회전과 평행이동은 한 쌍의 행렬을 이용하여 보통 이루어진다. 우리는 그 회전 행렬을 (R)로 부르고, 평행이동 행렬을 (T)라고 부른다. 이러한 행렬들은 행렬 곱으로 Transform Matrix(Tr)을 만들기 위해 합쳐진다.  여기에서 그것이 수학적으로 어떻게 나타나지는지가 있다.

그림

 이것을 나타내는 다른 방법들이 있다. 평행이동 행렬은 가끔씩 한 벡터로 표현된다. 그것은 이전에 곱해지거나 또는 이후에 곱해질 수 있다. (오른손 좌표계와 왼손 좌표계 사이에서 바꿀 때) 가끔씩 transform matrix는 밑바닥에 평행이동 요소들을 가진다. 가끔씩 마지막 행은
완전히 없어진다. (코드에서 가끔씩 그렇다. 너가 그것들이 필요없기 때문에) 나는 이러한 방식으로 행렬을 썼다. 왜냐하면 정방 행렬을 곱하는 것이 편리하기 때문이다. 만약 너가 그것을 다른 방식으로 되는 것에 익숙하다면, 너는 문제 없이 마음속으로 변형을 할 수 있다.

Properties of the Transform Matrix
Tr의 두 가지 특징은 명백하다:

  • transform matrix에서 rotation matrix를 추출하는 것은 매우 쉽다.
  • transform matrix에서 translation matrix를 추출하는 것은 좀 더 까다롭다


실제로, transform matrix에서 translation matrix를 추출하는 것은 그렇게 어렵지 않다. 그냥 IT = T라는 것을 기억해라. I는 항등 행렬이다. 그리고 R^-1R = I이다, 그래서 R^-1RT = T이고, 그래서 R-1Tr = T 이다. 직교 행렬의 역행렬은 그것의 전치행렬이기 때문에(아래를 보아라), R^tTr = T이다. 다시 말해서, translate matrix를 얻기 위해 transform matrix에 회전 행렬의 전치행렬을 곱해라. 두 번째 생각에 대해서, 그것은 까다롭다. 할 필요가 없다면 하지 마라. 아마도 translation matrix를 복사본을 유지하는 것이 더욱 쉬울 것이다.

rotation matrix는 transform matrix로부터 얻기에 쉽지만, 유의해라. rotation matrix와 transform matrix를 혼동하지 말아라. 이것은 하기에 쉬운 실수이다. 우리가 rotation matrice들을 합치려 할 때, 너가 translation 정보를 포함하는 transform matrix의 마지막열을 포함하지 않도록 하는 것을 확실히 해라. 만약 너가 그 열을 포함한다면, 너의 행렬은 더이상 특수한 직교 행렬이 아닐 것이고, 이것은 닫힌 집합에 속한다는 것을 의미하지 않는다. 그리고 이것은 너가 우리가 발견하려는 멋진 결과를 만들기 위해서 그것을 믿을 수 없게 된다는 것을 의미한다.

Properties of the Rotation Matrix
또는, special orthogonal에 대해 무엇이 그렇게 특별한가?
너가 그것을 놓친 경우에, rotation matrix는 special orthogonal matrix이다. 정의에 의하면, 특수 orthogonal matrix는 이러한 특성을 갖는다.

AA^t = I

여기에서 A^t 는 A의 전치행렬이고 I는 항등행렬이고, det A = 1이다.

이것은 정말 도움이 되지 않는다. 좀 더 도움이 되는 특징들의 집합은 Michael E. Pique에 의해 Graphics Gems에서 제공된다. (Glassner, Academic Press, 1990):

  1. R은 normalized 된다. : 어느 행 또는 열에 있는 요소들의 제곱은 합이 1이다.
  2. R은 orthogonal 한다. : 행의 어떤 쌍이나 열의 어떤 쌍의 내적은 0이다.
  3. R의 행들은 회전된 공간의 좌표축들에 따라서 단위 행렬들의 원래 공간에서의 좌표를 나타낸다.
  4. R의 열들은 원래 공간의 좌표축들을 따라서 단위 행렬들의 회전된 공간의 좌표를 나타낸다.
Property 1과 2는 한 행렬이 rotation matrix라는 것을 입증하는데 유용하다. 만약 너가 한 행렬을 조작하고, 너가 여전히 회전 행렬을 갖는지를 확실히 하고 싶다면, 어떤 행 또는 열의 제곱을 합해라. 만약 그 결과가 1이 아니라면, 그러면 너는 확실히 잘못된 것을 한 것이다. 만약 결과가 1이라면, 너는 올바른 길에 있다는 가능성이 있다.

Property 3은 forward motion에 유용하다. 그것에 대해서는 나중에 하겠다. 우리는 rotation matrix의 공식적인 특성을 가졌으니, 전통적으로 3D 그래픽스 프로그래밍에 적용되는 특성들에 대해 말해보자.

Rotation Matrix Conventions
수학적으로 말하자면, 모든 특수한 직교하는 행렬들은 rotation matrices들로 사용될 수 있다. 그러나 전통적으로, 우리가 3D 그래픽스 프로그래밍을 할 때, 우리는 행과 열에 대해 특수한 특성을 지정한다.

특히, 우리는 회전 행렬의 3 행에 대해 이름들을 갖는다. Row 1은 Right라 불려지고, Row 2는 Up, Row 3은 Out, Forward 또는 View이다. 나는 그것을 "Out"이라 부르겠다. 왜냐하면 너의 눈으로 부터 바깥을 향하는 view를 나타내기 때문이다.

그것은 사실 너가 바라보는 방향을 묘사하는 단위 벡터이다.

그것이 어떻게 작동하는가?

 Figure1 The Out vector (Direct X 중심으로 +Z축이 화면 안이라는 것에 유의)

그림1을 보아라. 너의 관점(Pov, camera position, eye)은 원점에 있고, 너가 View라고 불려지는 정해지지 않은 길이의 한 벡터를 바라보고 있다고 가정하자. Out vector는 길이가 1인 한 벡터이다. 그리고 그것은 View 평행하다. Out을 X, Y, 그리고 Z축에 사영시키는 것은 회전 행렬의 세 번째 행이다. R31은 Out을 X축에 사영시키는 것이고, R32는 Out을 Y축에, R33는 Out을 Z축에 사영시키는 것이다.

너는 Out vector의 크기를 취하여 property 1을 입증할 수 있다:

||Out|| = R31^2 + R32^2 + R33^2 = 1

Out의 크기는 회전 행렬의 row 3의 제곱의 합이다. (일반적으로, 너는 한 벡터의 크기를 구할 때, 제곱의 합의 루트를 취한다. 이것은 물론 단위 벡터의 경우에 필수적이지 않다. 왜냐하면 우리는 크기가 항상 1이 될 것이라는 것을 알기 때문이다.)

그것은 회전행렬의 row3를 설명한다. 다른 행들은 무엇을 나타내는가? 매우 간단히도, 그것들은 다른 회전 좌표계의 다른 두 개의 축들을 나타낸다. Figure 2를 보아라.

 Figure2 The direction vectors of the rotated view

그림 2에서, Up 벡터와 Right 벡터가 보인다. 둘 다 Out벡터처럼 단위 벡터이다. Up을 x,y, z축에 사영시키는 것은 회전 행렬의 두 번째 행이다. 그림 2에서, Up projection은 R21, R22, R23으로 쓰여있다. Right의 사영은 회전 행렬의 첫 번째 행이다.

우리는 이제 꽤 많은 정보를 가진 것 처럼 보인다. 밑바닥부터 회전행렬을 구성하기에 충분한 정보인가? 거의 그렇다. 고려해야할 한가지 문제가 있다. 우리가 필요한 정보의 한 조각이.

Building a Rotation Matrix
여기에 일반적인 문제가 있다. 너가 한 게임에 있는 캐릭터이고, 너가 XZ 면에서 돌아다니고 있다고 가정하자. 너가 소음을 듣고 너는 멈춘다. 한 의심이 너의 마음속에서 생긴다. 어떤 것이 위에서 너에게로 급강하 하고 있다. 그것이 그럴 수 있는가? 너는 천천히 올려다 본다. 그 문제가 그림 3에 그려진다.

 Figure 3 Looking up slowly

Figure3는 XZ 면에서 점 P에 있는 POV를 보여준다. P'를 바라보면서. 너는 theta 각 만큼 위로 올려다 보길 원한다. 직관적으로, 너는 직선 L을 주변으로 회전하고 싶어한다. 그리고 그것은 원점에 중심을 갖는 점 P에서 원의 접선이다. 아마도 너는 심지어 Y축에 대한 회전은 안다, 그리고 그것을 yAngle이라고 부를지도 모른다. 그 sight vector의 직선 (LOS)를 묘사하기 위해 rotation matrix R을 형성하는데 충분한 정보인가?

아니 아직 아니다. 왜 그런지 보자면 이것을 고려해 보아라. LOS는 한 면에 수직인 벡터이다. 그 면은 너가 실제로 바라보고 있는 곳에 관심이 있다. 그것은 너의 컴퓨터 스크린에 수 많은 3D 객체들이 거기에 사용되는것 과 함께 나타날 면의 한 부분 집합이다.  한 면에 대한 normal은 그 면이 어디에 있는지와 그것이 어떤 방향으로 확장되는지를 말해주는 반면, 그것은 우리에게 그 면의 방향을 말해주지 않는다.

 Figure 4 Different view of the same plane

그림 4는 같은 문제의 다른 그림을 보여준다. 이러한 경우에, 너는 두 점 P0과 P1로 정의되는 LOS 벡터를 가진다. 너는 P1 의 끝점에 있는 이 벡터에 직교하는 면의 view에 관심이 있다. 너도 볼 수 있듯이, 너는 선택한 많은 view들을 가진다. 그 면에 있는 그 view들은 LOS를 중심으로 회전을 나타낸다. 너는 오직 하나의 view만을 사용할 수 있다. 확실히 너는 좀 더 정보를 필요로 한다. 어떻게 그것을 얻을 것인가?

The World Up Vector
위의 문제의 해결책은 꽤 간단한 걸로 판명된다. 너는 다른 벡터를 선택하고 그것을 참조의 틀로서 사용한다. 이 참조 벡터는 보통 Y축에 놓여있고 가끔씩 Up 또는 Down으로 불려진다. 이전에 묘사한 Up vector와의 혼동을 피하기 위해, 그리고 그것은 회전 좌표계의 한 축 을 정의 하는 단위 벡터인데, 나는 이 reference vector를 World Up 벡터로 부를 것인다. 이것은 꽤 표준적이다. 게다가, 나는 그 World Up vector를 (0,1,0)으로 정의할 것이다. 이 벡터에 대한 줄임말은 Upw이다.

여기에서 그것이 어떻게 작동하는지가 있다.

World Up 벡터는 Up 벡터와 Out 벡터와 동일 평면상에 있다. 일단 너가 너의 Out 벡터를 가지고 있다면 (위에서 LOS라고 묘사된), 너는 회전된 view 무한한 개수의 상응하는 무한한 Up vector들의 개수를 가진다. Up이 Out과 Upw와 공면이 되도록 하여, 너는 Up이 단일의 선택이 되도록 제한할 것이다.

기억해라, Up은 Out에 수직이라는 것을. Upw은 아마도 Up 또는 Out에 수직하지 않지만, 두 벡터와 동일 평면상에 놓인다. 그 문제를 다르게 봐보자. 그림 5를 보아라.

  Figure 5 The new coordinate axes

그림 5에서, 우리는 Out, Up, Right라고 불려지는 단위 벡터를 그린다. 이것들은 회전 좌표 축들과 일치한다. Out은 the line of sight와 평행한다. Right는 점 P에서 원의 접선과 평행한다. 원은 Upw에 수직한 면에 놓여있다. Up는 Out과 Right에 수직이다. 그리고 그것은 Out과 Upw와 함께 동일 평면에 있다. 이 정보를 이용하여, 우리는 우리의 Up vector의 좌표축 사영을 결정할 수 있다.

Direct3D 함수에서 D3Dutil SetViewMatrix()라는 함수가 있다. 이 함수는 위에서 주어진 정보로 transforma matrix를 구성한다. 너는 두 점을 넘기고(또는 벡터들, D3D는 그것들을 호출하는 것을 선호한다.), 그리고 너는 World Up vector를 넘긴다. 마이크로소프트가 World Up 벡터를 넘기는 것을 필수적으로 만든 것이 궁금하다. 명백히, 그들은 그 벡터가 바뀌는 것을 기대하고 있다. 나는 World Up 벡터를 바꾸는 좋은 이유를 생각할 수 없다. 한 view를 회전시키는 더욱 쉬운 방법들이 있다. World up 벡터를 넘기는 것은 code를 느리게 한다. 왜냐하면 함수가 호출 될 때 마다, 유효성 검사가 수행되어야 하기 때문이다. Fastgraph를 설계할 때, 나는 고정된 World up vector를 가정했다. 그것은 너가 그것을 바꿀 수 없다는 것을 의미하지 않는다. 그것은 fg_3Dupvector()를 호출하여 바뀔 수 있다. 그러나 나는 빈번하지 않게 호출될 그 함수를 기대하지 않는다. 사실, ~, 나는 그것을 바꿀 좋은 이유를 생각할 수 없다. 아마도 비행 시뮬레티어를 쓴 사람들은 World Up 벡터를 바꿀 한 이유를 가질 것이다. 지금, 나중의 이야기의 목적을 위해, 우리는 고정된 World Up vector를 가정할 것이다. 위에서 언급했듯이.


댓글 없음:

댓글 쓰기