관리 메뉴

드럼치는 프로그래머

[DirectX] 변환 / 변환행렬 본문

★─Programing/☆─DirectX

[DirectX] 변환 / 변환행렬

드럼치는한동이 2010. 2. 17. 14:03

변환 행렬

이동변환

이동변환은 점 p = ( p(x), p(y), p(z) )를 ( t(x), t(y), t(z) )만큼 이동하는 변환이다.

즉 점 p가 p' = ( p(x) + t(x) , p(y) + t(y) , p(z) + t(z) )로 변환된다.

이 변환에 대한 행렬을 아래의 코드로 얻을 수 있다.

 

D3DXMatrixTranslation(&T, tx, ty, tz);

 

이동변환 행렬은 다음과 같은 형식의 행렬이 된다.

 

T ( t(x), t(y), t(z) ) =   1  0  0  0

                               0  1  0  0

                               0  0  1  0

                               0  0  0  1

 

이동변환 행렬의 특성으로 T ( t(x), t(y), t(z) ) 의 역행렬이 T ( -t(x), -t(y), -t(z) )이다.

  

회전변환

회전변환을 위한 행렬을 쉽게 구할 수 있도록 여러 함수를 제공한다.

x축, y축, z축에 대한 회전변환 행렬은 아래의 코드로 얻을 수 있다.

모든 각도는 라디안(radian) 단위로 주어져야 한다. 회전 방향은 시계방향이다.

 

D3DXMatrixRotationX(&Rx, angle_x);

D3DXMatrixRotationY(&Ry, angle_y);

D3DXMatrixRotationZ(&Rz, angle_z);

 

회전변환 행렬은 아래와 같은 형식의 행렬이 된다.

 

Rx(Θ) =   1       0       0      0

              0   cosΘ   sinΘ   0

              0   -sinΘ  cosΘ  0

              0       0       0      1

 

Ry(Θ) =  cosΘ   0    -sinΘ  0

               0       1       0      0

              sinΘ   0     cosΘ  0

               0       0       0      1

 

Rz(Θ) =  cosΘ  sinΘ   0      0

             -sinΘ  cosΘ  0      0

               0       0        1      0

               0       0        0      1

 

회전변환 행렬의 특성으로 회전행렬 R의 역행렬이 R의 전치행렬과 같다.

이러한 특성의 행렬을 직교행렬(orthogonal matrix)이라고 한다.

 

직교행렬은 다음의 특성을 가지는 매우 유익한 형태의 행렬이다.

  - 직교행렬의 역행렬은 전치행렬과 같다.

  - 직교행렬의 행렬식은 1 또는 -1이다.

  - 한 직교행렬의 전치행렬도 직교행렬이다.

  - 임의의 두 직교행렬을 곱해도 직교행렬이다.

  - 임의의 두 벡터 사이의 거리와 각도는 두 벡터를 한 직교행렬로 변환한 후에도 동일하다.

 

직교행렬의 대표적인 예가 회전행렬이지만

대칭변환(reflection)을 위한 행렬도 직교행렬의 한 형태이다.

 

크기조정

크기조정은 각 축에 대해 주어진 인자를 곱하여 크기를 변환한다.

 

D3DXMatrixScaling(&S, sx, sy, sz);

 

크기 조정행렬은 아래와 같은 형식의 행렬이 된다.

 

S ( s(x), s(y), s(z) ) = s(x)   0     0     0

                                  0    s(y)   0     0

                                  0      0    s(z)  0

                                  0      0     0     1

크기조정행렬의 특성으로 S ( s(x), s(y), s(z) ) 역행렬은

S ( 1/s(x), 1/s(y), 1/s(z) ) 행렬과 같다. 

 

조합된 변환 행렬

여러 변환 행렬을 하나의 변환 행렬로 조합할 수 있다.

 

예를 들어 x축, y, z축에 각각 1/2, 2, 1/4 크기로 크기조정한 후에, y축으로 π/2만큼 회전한 후,

(3, 1, -1)만큼 이동하는 변환 M은 아래와 같다.

 

M = S(0.5, 2.0, 0.25) Ry(π/2) T(3, 1, -2)

 

이 행렬을 구하기 위해서는 아래와 같은 함수를 사용한다.

 

D3DXMATRIX S, Ry, T, M; // 구조체 선언, 이건 벡터니까 변수가 아니라 구조체.

D3DXMatrixScaling(&S, 0.5f, 2.0f, 0.25f); // 1/2, 2, 1/4 크기로 크기조정

D3DXMatrixRotationY(&Ry, (float)D3DX_PI / 2,0f); // y축으로 π/2만큼 회전

D3DXMatrixTranslation(&T, 3.0f, 1.0f, -2.0f); // 3, 1, -2만큼 이동

M = S * Ry * T;

 


변환 행렬을 적용하기

 

위치벡터를 변환

위치를 나타내는 한 벡터에 변환 행렬을 적용하면 변환 후의 벡터를 얻을 수 있다.

변환 행렬을 위치벡터에 적용하기 위한 함수들이 제공된다.

 

D3DXVec3Transform : 이 함수는 행렬 M으로부터 벡터 v = (x, y, z, 1)을 변환한다.

                                 입력은 항상 w = 1이므로 vin3 = (x, y, z)만 D3DXVECTOR3로 표현한다.

                                 변환결과는 동차좌표 vout4로 리턴된다.

 

D3DXVec3Transform(&vout4, &vin3, &M);

 

D3DXVec3TransformCoord : 이 함수는 행렬 M으로부터 벡터 v = (x, y, z, 1)을 변환한 다음

                                     그 결과를 w = 1이 되도록 한다.

                                     입력은 항상 w = 1이므로 vin3 = (x, y, z)만 D3DXVECTOR3로 표현한다.

                                     변환 결과도 항상 w = 1이므로 D3DXVECTOR3 타입의 vout3로 리턴된다.

 

D3DXVec3TransformCoord(&vout3, &vin3, &M);

 

 

예를 들어 점 (1, 2, 3)을 위의 행렬 M으로 변환한 점은 아래와 같이 구할 수 있다.

변환된 점은 (3.75, 7.0, -2,5)로 구해진다.

 

D3DXVECTOR3 p(1.0f, 2.0f, 3.0f);

D3DXVECTOR3 p2;

D3DXVector3TransformCoord(&p2, &p, &M);

 

벡터 하나가 아니라 여러 벡터들을 한꺼번에 변환하기 위한 함수인

D3DXVec3TransformArray 함수와 D3DXVec3TransformCoordArray 함수도 지원한다.

 
 

방향벡터를 변환

노말벡터의 변환을 위한 행렬은 위치벡터의 경우에서와 다르게 주어져야 한다.

변환을 위한 행렬은 이동(translation), 회전(rotation), 크기조정(scaling), 기울임변환(shear)등의

요소들을 포함한다.

노말벡터는 위치개념이 없다. 노말벡터의 변환에 대해서는 위치이동 요소가 적용되지 말아야한다.

  이는 노말벡터가 w = 0이므로 행렬의 위치이동 요소가 적용되지 않는다.

노말벡터의 변환에 있어서는 크기가 변하거나 기울어지지 않아야 한다.

  만약 위치벡터에서와 같은 방법으로 변환한다면 노말벡터가 틀리게 변환된다.

 

노말벡터의 변환을 위해서는 행렬 A의 역행렬의 전치행렬인 A^-T를 적용해야한다.

실제로 행렬 A에 대응하는 변환에 크기변환이나 기울임 변환 성분이 없다면,

행렬 A의 왼쪽 위의 3 X 3 부분행렬 A'에 대해서 A'와 A'^-T가 동일하게 된다.

 

위치벡터가 아닌 노말벡터를 변환하기 위해서는 D3DXVec3TransFormNormal을 사용하면 된다.

 

D3DXVec3TransFormNormal : 행렬 M으로 벡터 v = (x, y, z, 0)을 변환한다.

                                               입력은 항상 w = 0이므로 vin3 = (x, y, z)만 표현한다.

                                               변환 결과는 vout3로 리턴된다.

 

D3DXVec3TransformNormal(&vout3, &vin3, &M);


Comments