Rotation Matrix

 

Rotation Matrix에 대해서 알아본다.

다이렉트 X는 왼손좌표계를 사용하고 Maxtrix는 행우선(row major), OpenGL은 열우선(column major)을
사용한다.
3DSMAX에서 볼수 있는 좌표가 Z-UP 오른손 좌표계이다.

오일러 회전에 대해 설명한다. 오른손 좌표계와 왼손 좌표계의  회전식을 서로 비교하여
왼속 좌표계와 오른손 좌표계의 Matrix 클래스를 만들어 본다.

X, Y, Z 축을 회전할 때, 회전 그림과 공식은 다음과 같다.

 

X 축 회전 ( YZ 평면 )

Y 축 회전 (  ZX 평면 )

Z 축 회전 ( XY 평면 )

X' = x
Y' = y cos θ - z sin θ
Z' = y sin θ + z cos θ

X' = z sin θ + x cos θ
Y' = y
Z' = z cos θ - x sin θ

X' = x cos θ - y sin θ
Y' = x sin θ + y cos θ
Z' = z

X축 회전과 Z축 회전은 고등학교때 자주 보던 오일러 방식의 회전 변환이다.
Y축의 경우는 ZX 평면으로 2D XY 평면 처럼 보이도록 할려면 시계방향으로 90도 회전해야 한다.
90도 하면, Z축이 X축 역할을 하고 X축이 Y축 역할을 한다. 그래서 식은 위와 같다.

오일러 방식의 회전 변환을 매트릭스 방식으로 변환하면 다음과 같다.

왼손 좌표계 오른손 좌표계
x Rotation

1

0

0

0

0

cos θ

sin θ

0

0

-sin θ

cos θ

0

0

0

0

1

y Rotation

cos θ

0

-sin θ

0

0

1

0

0

sin θ

0

cos θ

0

0

0

0

1

z Rotation

cos θ

sin θ

0

0

-sin θ

cos θ

0

0

0

0

1

0

0

0

0

1

x Rotation

1

0

0

0

0

cos θ

-sin θ

0

0

sin θ

cos θ

0

0

0

0

1

y Rotation

cos θ

0

sin θ

0

0

1

0

0

-sin θ

0

cos θ

0

0

0

0

1

z Rotation

cos θ

-sin θ

0

0

sin θ

cos θ

0

0

0

0

1

0

0

0

0

1

 

왼손 좌표계

오른손 좌표계

X Rotation의 행렬식이다

 

1

0

0

0

0

cos θ

sin θ

0

0

-sin θ

cos θ

0

0

0

0

1

[  x, y, z, 1 ]

 

X Rotation의 행렬식이다

1

0

0

0

0

cos θ

-sin θ

0

0

sin θ

cos θ

0

0

0

0

1

x

 

y

 

z

 

1

 
X Rotation X Rotation

x' = x
y' = ycosθ - zsinθ
z' = ysinθ + zcosθ

x' = x
y' = ycosθ - zsinθ
z' = ysinθ + zcosθ

Y Rotation Y Rotation

x' = xcosθ + zsinθ
y' = y
z' = -xsinθ + zcosθ = zcosθ - xsinθ

x' = xcosθ + zsinθ
y' = y
z' = -xsinθ + zcosθ = zcosθ - xsinθ

Z Rotation Z Rotation

x' = xcosθ - ysinθ
y' = xsinθ + ycosθ
z' = z

x' = xcosθ - ysinθ
y' = xsinθ + ycosθ
z' = z

행우선 matrix 클래스는 LMaxtrix 클래스

열우선 matrix 클래스는 RMatrix 클래스

실제 어떻게 사용되는지 보자 코드는 다음과 같다.
GetRightHandCoordinate()가 true이면 오른손 좌표계일때이다. 주석은 D3DXMATRIX로
처리 할때이다.

void CTestApp::Render()

{

    //m_cameraRef.fRotateX = -14.0f;

    //m_cameraRef.fRotateX = 0.0f;

    if( GetRightHandCoordinate() )

    {

#if  0

        D3DXMATRIX   matTranslation, matRot, matWorld;

        D3DXMatrixTranslation( &matTranslation, 0.0f, m_cameraRef.wheel * 2.0f, 0.0f);

        D3DXMatrixRotationYawPitchRoll( &matRot, 0.0f, D3DXToRadian(-m_cameraRef.fRotateY), D3DXToRadian(-m_cameraRef.fRotateX));

 

        IDirect3DDevice9 * pDevice = m_pGraphics->GetDevice();

 

        matWorld = matRot * matTranslation;

        pDevice->SetTransform( D3DTS_WORLD, &matWorld);

 

        m_pXFile->Draw();

#else   

        RMatrix matTranslation;

        matTranslation.Translate( 0.0f, m_cameraRef.wheel * 2.0f, 0.0f);

        RMatrix  matRot;

        matRot.YawPitchRoll( DEGTORAD(-m_cameraRef.fRotateX), DEGTORAD(-m_cameraRef.fRotateY), 0.0f );

        matRot = matTranslation * matRot;

        matRot.Transpose();

 

        IDirect3DDevice9 * pDevice = m_pGraphics->GetDevice();

        D3DXMATRIX matWorld = matRot;

        pDevice->SetTransform( D3DTS_WORLD, &matWorld);

 

        m_pXFile->Draw();

#endif

    }

    else

    {

#if  0

        D3DXMATRIX   matTranslation, matRot, matWorld;

        D3DXMatrixTranslation( &matTranslation, 0.0f, 0.0f, m_cameraRef.wheel * 2.0f);

        D3DXMatrixRotationYawPitchRoll( &matRot, D3DXToRadian(m_cameraRef.fRotateX), D3DXToRadian(m_cameraRef.fRotateY), 0.0f );

        IDirect3DDevice9 * pDevice = m_pGraphics->GetDevice();

 

        matWorld = matRot * matTranslation;

        pDevice->SetTransform( D3DTS_WORLD, &matWorld);

 

        m_pXFile->Draw();

#else

        LMatrix matTranslation;

        matTranslation.Translate(0.0f, 0.0f, m_cameraRef.wheel * 2.0f);

        LMatrix  matRot;

        matRot.YawPitchRoll( DEGTORAD(m_cameraRef.fRotateX), DEGTORAD(m_cameraRef.fRotateY), 0.0f );

        matRot = matRot * matTranslation;

        D3DXMATRIX matWorld = matRot;

 

        IDirect3DDevice9 * pDevice = m_pGraphics->GetDevice();

        pDevice->SetTransform( D3DTS_WORLD, &matWorld);

        m_pXFile->Draw();

 

        m_pXFile->Draw();

#endif

    }

}