블로그 이미지
자신의 단점을 메꾸는 것을 단(鍛)이라 하고 자신의 강점을 갈고 닦는 것을 련(鍊)이라 하여, 두가지를 합친 것을 단련이라고 부른다. 붕대마음

카테고리

전체목록 (666)
참고사이트 (8)
Goal (4)
Travel (10)
My Life (105)
Game (35)
Game Review (7)
Game Plan (0)
Books (5)
English (1)
Optimizing (12)
Study (217)
유용한 것들_etc (44)
유용한 것들_func (20)
Unity (48)
Unreal (87)
작업장 (54)
RenderMonkey (6)
정리요망 (1)
따라잡기 시리즈 (0)
링크용 (0)
Total343,756
Today5
Yesterday73

'SIN'에 해당되는 글 1건

  1. 2013.03.21 행렬

행렬

Study/M's Lecture / 2013.03.21 11:57
  
행렬이란 무었인가?
벡터를 움직이는 것.

행렬을 사용하면 벡터의 방향이나 크기를 바꿀 수 있다.

EX) x축 방향을 향하고 있는 벡터가 아래의 행렬을 통해 방향을 바꾸는 모습을 볼 수 있다.
[0, -1, 0]        [1]        [0*1 + -1*0 + 0*0]    [0]
[1,  0, 0]   *    [0]   =    [1*1 +  0*0 + 0*0] =  [1]
[0,  0, 1]         [0]        [0*1 +  0*0 + 1*0]    [0]
x축을 향하던 벡터가 행렬과 연산된 후 y축을 향하는 것을 볼 수 있다.

행렬의 내용은 대략 위의 사진과 같고 행과 열을 같을 경우 정방행렬이라고 한다.
정방행렬로 벡터를 변환하면 벡터의 차원이 변함없기 때문에 컴퓨터 그래픽에서 정방행렬을 많이 사용한다.

행렬을 사용하여 벡터를 움직이는 것은 행렬의 각 열을 벡터로 간주했을 경우 벡터의 내적처럼 계산된다.

위에서 언급했듯이 행렬은 벡터의 방향이나 크기를 바꿀 수 있는데 벡터를 움직이지 않는 행렬도 있다.
이 행렬을 단위행렬 이라고 하며 대각선상의 요소가 모두 1이고 나머지 요소는 0인 행렬을 말한다.
[1, 0, 0]
[0, 1, 0]
[0, 0, 1]
3x3 단위 행렬은 위와 같다.

[1, 0, 0, 0]
[0, 1, 0, 0]
[0, 0, 1, 0]
[0, 0, 0, 1]
4x4 단위 행렬은 위와 같다.




행렬을 나타내는 두가지 방법.

1. 열로 나열하는 3개의 좌표계축을 가지고(오른쪽, 위, 전방) 마지막 열은 각 축의 평행이동 구성요소를 가지는 것처럼 출력.
Right_x   Up_x    Forwaed_x    T_x
Right_y   Up_y    Forwaed_y    T_y
Right_z   Up_z    Forwaed_z    T_z
0            0          0                  1
이 포맷을 사용하면 벡터를 열처럼 취급할 수 있다.
이를 열 우선 포맷이라고 한다.
OpenGL에서도 이 방식을 사용한다.


2. 행으로 나열하는 3개의 좌표계축을 가진다.
Right_x         Right_y        Right_z       0
Up_x            Up_y           Up_z           0
Forwaed_x   Forwaed_y   Forwaed_z  0
T_x             T_y             T_z             1
이 포맷에서는 벡터를 행으로 취급한다.
그래서 행 우선 포맷이라고 한다.
dx에서도 이 방식을 사용한다.

world matrix는 object의 local 좌표계의 방향과 world 좌표계의 원점으로 부터의 위치를 담고 있다.


view matrix는 camera의 local 좌표계를 invert한 vector들로 기술되고
4번째 행에 있는 vector는 camera 위치 base로 한 inverse translation으로 되어 있다.
이 translation은 world의 원점을 공유하며 camera의 위치를 반영하는 위치로 vertex들을 이동시킬 것이다.

matrix의 첫번째 column에 있는 "Right Vector"는 camera local좌표계 상의 x축 방향을 기술한다.
두번째 column에 저장된 "Up Vector"는 Y축을, 세번쨰 column의 "Look Vector"는 Z축 방향을 각각 기술한다.

dx 행렬이나 opengl 행렬이나 결론은 하나다.
행렬은 벡터를 나열해서 만든 것이라는 것.


행렬 연산.

1.
덧셈


2.
뺄셈


3.
곱셈

왼쪽 행렬의 행과 오른쪽 열의 곱셈은 사실 내적과 같다.
 = a.i1*b.1i + a.i2*b.2i + a.i3*b.3i; 이 값은 사실 dot(a,b)와 같다.

행렬의 곱셈에는 사실 숨겨진 의미가 있는데 그것은 "벡터를 연속해서 움직인다"라는 것이다.
EX)
x축을  향하는 벡터 1,0,0을 y축을 향하는 벡터 0,1,0으로 움직이는 행렬 Rz
[0, -1, 0]   [1]    [0*1 + -1*0 + 0*0]  [0]
[1,  0, 0] * [0] = [1*1 +   0*0 + 0*0] = [1]
[0,  0, 1]    [0]   [0*1 +   0*0 + 1*0]   [0]

y축을 향하는 벡터 0,1,0을 z축을 향하는 벡터 0,0,1으로 움직이는 행렬   Rx
[1, 0, 0]     [0]   [0*0 + 0*1 +   0*0]   [0]
[0, 0, -1] * [1] = [0*0 + 0*1 + -1*0] = [0]
[0, 1, 0]     [0]   [0*0 + 1*1 +   0*0]   [1]

x축을 향하는 벡터를 y축으로 향하게 하는 행렬과 y축을 향하는 벡터를 z축으로 향하게 하는 행렬을
곱셈연산으로 하나로 만들면 이 행렬은 x축을 향하는 벡터를 z축으로 향하게 하는 행렬이 된다.
Rx * Rz = Rxz
[1, 0, 0]     [0, -1, 0]      [0, -1, 0]
[0, 0, -1] * [1,   0, 0]  =  [0, 0, -1]
[0, 1, 0]     [0,   0, 1]      [1, 0,  0]

이렇게 두번의 행렬을 곱할필요 없이 행렬끼리 미리 곱해서 벡터에 적용하면 한번에
원하는 결과를 얻을 수 있다.
Rx * Rz * Vtox = Rxz * V = Vtoz
[0, -1, 0]   [1]    [0*1 + -1*0 +  0*0]    [0]
[0, 0, -1] * [0] = [0*1 +  0*0 + -1*0] =  [0]
[1, 0,  0]    [0]   [1*1 +   0*0 +  0*0]    [1]

4. 스칼라 곱셈

 

스칼라 곱셈은 단순히 벡터의 길이를 조절할 수 있다.

회전행렬
회전행렬이란 벡터의 크기를 바꾸지 않고 방향만 바꾸는 행렬을 뜻한다.
위의 예에서 x축을 향하는 벡터를 y축이나 z축을 향하는 벡터로 바꾼것이 회전행렬이다.


x축을 향하는 벡터를 y축을 향하는 벡터로 만든 행렬을 생각해 보자.
[0, -1, 0]
[1, 0, 0]
[0, 0, 1]
이는 벡터를 z축을 중심으로 90도 만큼 돌린 회전행렬이며 위 사진의 Rz에 해당한다.
cos90도는 0, sin90도는 1을 뜻하므로 Rz에 값을 대입하면 위의 행렬이 나온다.


간단하게 cos값과 sin값을 정리해 보자.
cos0 = 1
cos60 = 0.5
cos90 = 0

sin값은 90-cos각도다.
cos0 = sin90 = 1
cos60 = sin30 = 0.5
cos90 = sin0 = 0

자세한 각도는 위의 그림을 보면 되지만 사실 0도와 90도 정도만 알아줘도 상관없다.

http://terms.naver.com/imageDetail.nhn?cid=200000000&docId=1107832&imageUrl=http%3A%2F%2Fdicimg.naver.com%2F100%2F800%2F1%2F8101.jpg&categoryId=200000451
위의 곡선을 보면 sin과 cos은 1~-1사이를 오가는데 sin은 90도일 때 1의 값을, cos은 0도일 때 1의 값을 같는 것을 알 수 있다.

그렇다면 z축으로 90도 회전해서 x축을 향하는 벡터를 y축을 향하는 벡터로 만들었으니
다시 y축을 향하는 벡터를 x축을 향하는 벡터로 만들려면 어떻게 해야 하는가?
z축으로 90도 회전한걸 다시 z축으로 -90도 회전하면 되는데 벡터는 행렬에 의해 움직일 수 있다고 했으니
다시 되돌리는 것도 행렬을 통해 되돌리 수 있다.
처음 회전한 것을 다시 되돌리는 행렬을 처음 회전한 행렬의 역행렬이라고 한다.

z축 중심회전 행렬인 Rz의 역행렬이 아래와 같을 때
| cosB  -sinB   0 |
| sinB   cosB   0 |
|      0        0    1 |

이 행렬의 역행렬은 각도값만 - 해주면 되는데
| cos(-B)  -sin(-B)  0 |
| sin(-B)   cos(-B)  0 |
|         0             0   1 |
그런데 위의 cos 곡선을 보면 0을 기준으로 좌우가 대칭이다.
즉, cosB와 cos(-B)와 값이 같다는 것을 알 수 있다.
sin곡선은 어떠한가? sin곡선은 0을 기준으로 위아래가 뒤집힌 모양이다.
즉, sinB값이 1이라면 sin(-B)는 -1이 되는 형태가 되며 결론적으로 sinB = - sin(B)가 되는 형태를 띈다.
그래서 이 특성을 이용하여 위의 역행렬을 고쳐주면 아래와 같다.
|  cos(B) sin(B) 0 |
| -sin(B) cos(B) 0 |
|         0         0  1 |

기존행렬 Rz와 이 행렬의 역행렬인 Rz-1과 다른점은 sin값의 부호 뿐이다.
이는 단순히 기존행렬에서 행과 열을 바꿔주는작업을 하는 것과 같다.
이렇게 행렬의 행과 열을 바꿔준 행렬을 전치행렬 이라고 한다.


그렇다면 역행렬의 다른말은 전치행렬이란 말인가?
그렇다면 참 좋겠지만 늘 그렇지는 않다.
전치행렬이 역행렬이 되는 것은 "회전행렬 특유"의 성질이다.

회전행렬의 역행렬은 그 행렬이 회전한 값의 반대값으로 다시 회전하면 된다고 하였다.
그렇다면 행렬의 확대 축소는 어떠한가?
[1, 0, 0]
[0, 1, 0]
[0, 0, 1]
벡터를 움직이지 않는 위와 같은 단위행렬에 특정한 수를 스칼라 곱으로 곱해준다고 생각해 보면
[2, 0, 0]
[0, 2, 0]
[0, 0, 2]
위와 같은데 이제 이 행렬은 더이상 단위행렬이 아니라 벡터의 길이를 두배로 늘려주는 확대행렬이 된다.
이 행렬의 역행렬은 회전행렬의 역행렬과 같이 개념은 "변화 준 것을 되돌린다"로 같지만 전치행렬로 표현할 순 없다.
전치행렬이 역행렬이 되는 것은 회전행렬의 특유의 성질이기 때문이다.
확대행렬의 역행렬은 축소행렬, 즉 확대한 만큼 축소하면 된다.
[1/2, 0, 0]
[0, 1/2, 0]
[0, 0, 1/2]
즉 1/확대률 해주는 것이 확대행렬의 역행렬 이다.

다음으로 살펴봐야 할 것은 평행 이동 행렬이다.
발상은 3차원 벡터를 확장해서 (x,y,z,1)처럼 생각하자~!! 이다.
위와같이 3차원을 4차원으로 확장해서 사용하는 이유는 이동,크기,회전을 모두
담을 수 있는 행렬이 4x4이기 때문이다.
그런데 행렬은 사실 벡터로 이루어 져 있으므로 벡터가 4차원으로 확장되야 한다.

          동차항
[1, 0, 0, 0] - x축
[0, 1, 0, 0] - y축
[0, 0, 1, 0] - z축
[0, 0, 0, 1] - 이동관련

4x4 행렬에서 보면 x,y,z, 그리고 이동에 관한 축이 있다.
동차항을 자세히 보면 각 방향을 나타내는 축들은 0의 동차항을 가지고
이동에 관한 값은 1의 동차항을 가진다.
즉, 0의 동차항을 가진다는 말은 방향을 의미하는 벡터, 1의 동차항을 가지는 벡터는
위치를 의미하는 벡터이다.
동차좌표는 투영행렬과의 연산에서 특별한 의미를 가지는데 이에관한 설명은 아래의
글들을 통해 쉽게 이해할 수 있다.
참고 : http://blog.naver.com/nt0083/20078644391
         http://scosco.com.ne.kr/ES20Html/basic_homogeneous.htm
         http://carstart.tistory.com/180
         http://geometricmind.wordpress.com/author/geometricmind/page/9/

행우선과 열우선.
http://www.gpgstudy.com/forum/viewtopic.php?t=995&view=next&sid=2e0cb9576fd820c9d3b9e9686c6aa6f8
manilee 말씀대로 직접 증명해보는 게 도움이 될 것이구요. 
용어 관련해서요.. 행우선, 열우선은 사실 행렬의 성분들을 색인으로 참조할 때
(수식 안에서 또는 배열 저장에서) 외에는 수학적으로 별 의미가 없습니다. 
행렬 자체는 그냥 격자 형태로 존재할 뿐이구요. 
또한 행렬이라는 말에서 알 수 있듯이 기본적으로는 행을 먼저 치는 것이 일반적입니다. 
m x n 은 m 행, n 열의 행렬이다.. 등등. 
차이가 나는 것은 행렬에 열벡터를 곱하느냐 행벡터에 행렬을 곱하느냐 문제이구요. 
제가 본 수학책이나 프로그래밍 문서에서, 한 점을 행렬로 변환한다고 할 때 
대부분은 행렬이 왼쪽에 오고 오른쪽에 열벡터가 오는 형태입니다. 
다만 프로그래밍의 편의 상 행벡터 곱하기 행렬이 쓰이기도 할 뿐... 
오른손 왼손 역시 행우선, 열우선과 별 관련이 없을 듯... 
위의 예에서 오른손과 왼손의 차이는 Nx, Ny, Nz의 부호의 차이일 뿐이니까요..
 


행우선과 열우선, 왼손과 오른손좌표 이야기






참고 :

책 : C++와 DirectX9을 이용한 실시간 3D 지형엔진
DirectX 9 셰이더 프로그래밍
벡터 : http://mgun.tistory.com/1143 

'Study > M's Lecture' 카테고리의 다른 글

피부는 왜 피부처럼 보이는가? 1  (0) 2013.12.02
Depth Of Field 2 (Advanced DOF)  (0) 2013.04.13
행렬  (0) 2013.03.21
Depth Of Field 1 (Simple DOF)  (1) 2013.03.18
Shader 개발을 위한 툴  (0) 2013.03.12
5. 왜 물은 물처럼 보이는 걸까?  (0) 2013.02.20
Posted by 붕대마음

댓글을 달아 주세요

최근에 달린 댓글

최근에 받은 트랙백

글 보관함