Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
1 2
3 4 5 6 7 8 9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30
Archives
Today
Total
관리 메뉴

codingfarm

2. 행렬 대수 본문

computer graphics/DX12 book

2. 행렬 대수

scarecrow1992 2020. 11. 21. 21:35

3차원 컴퓨터 그래픽에서 행렬(matrix)의 사용 목적은 주로 아래와 같다.

1. 비례나 회전, 이동 같은 기하학적 변환을 간결하게 서술

2. 점이나 벡터의 좌표를 한 기준계에서 다른 기준계로 변환

 

8. DirectXMath의 행렬

3차원 그래픽에서 점과 벡터를 변환할 때에는 $1 \times 4$ 행벡터와 $4 \times 4$ 행렬을 사용한다.

DirectXMath 라이브러리로 $4 \times 4$ 행렬을 표현할 때에는 XMMATRIX라는 형식을 사용한다.

struct XMMATRIX {
    union {
        XMVECTOR r[4];
        struct {
            float _11;
            float _12;
            float _13;
            float _14;
            float _21;
            float _22;
            float _23;
            float _24;
            float _31;
            float _32;
            float _33;
            float _34;
            float _41;
            float _42;
            float _43;
            float _44;
        };
        float    m[4][4];
    };
    XMVECTOR              r[4];
    void XMMATRIX();
    void XMMATRIX( const XMMATRIX& );
    XMMATRIX& noexcept  operator=( const XMMATRIX& M );
    XMMATRIX& operator=( const XMMATRIX& );
    void XMMATRIX( XMMATRIX&& );
    XMMATRIX& operator=( XMMATRIX&& );
    void XMMATRIX( FXMVECTOR R0, FXMVECTOR R1, FXMVECTOR R2, CXMVECTOR R3 );
    void XMMATRIX(
        float m00,
        float m01,
        float m02,
        float m03,
        float m10,
        float m11,
        float m12,
        float m13,
        float m20,
        float m21,
        float m22,
        float m23,
        float m30,
        float m31,
        float m32,
        float m33
    );
    void                  XMMATRIX( const float* pArray );
    float                 operator()( size_t Row, size_t Column );
    float& operator()( size_t Row, size_t Column );
    XMMATRIX              operator+();
    XMMATRIX              operator-();
    XMMATRIX& XM_CALLCONV operator+=( FXMMATRIX M );
    XMMATRIX& XM_CALLCONV operator-=( FXMMATRIX M );
    XMMATRIX& XM_CALLCONV operator*=( FXMMATRIX M );
    XMMATRIX& operator*=( float S );
    XMMATRIX& operator/=( float S );
    XMMATRIX XM_CALLCONV  operator+( FXMMATRIX M );
    XMMATRIX XM_CALLCONV  operator-( FXMMATRIX M );
    XMMATRIX XM_CALLCONV  operator*( FXMMATRIX M);
    XMMATRIX              operator*( float S );
    XMMATRIX              operator/( float S );
};

코드를 보면 XMMATRIX는 SIMD 활용을 위해 XMVECTOR 인스턴스 4개를 사용한다.

 

XMMATRIX의 생성자 외에, XMMatrixSet 이라는 함수로도 XMMATRIX 인스턴스를 생성할 수 있다.

XMMATRIX XM_CALLCONV XMMatrixSet(
    float m00, float m01, float m02, float m03, 
    float m10, float m11, float m12, float m13, 
    float m20, float m21, float m22, float m23, 
    float m30, float m31, float m32, float m33
);

 

벡터를 클래스에 저장할 때 자료 멤버이 형식으로 XMFLOAT2나 XMFLOAT3, XMFLOAT4를 쓰듯이

DirectXMath 문서화는 행렬을 클래스 자료 멤버에 저장할 때 XMFLOAT4X4 형식을 사용할것을 추천한다.

struct XMFLOAT4X4 {
    union {
        struct {
            float _11;
            float _12;
            float _13;
            float _14;
            float _21;
            float _22;
            float _23;
            float _24;
            float _31;
            float _32;
            float _33;
            float _34;
            float _41;
            float _42;
            float _43;
            float _44;
        };
        float m[4][4];
    };
    void         XMFLOAT4X4();
    void         XMFLOAT4X4( const XMFLOAT4X4& );
    XMFLOAT4X4& operator=( const XMFLOAT4X4& );
    void         XMFLOAT4X4( XMFLOAT4X4&& );
    XMFLOAT4X4& operator=( XMFLOAT4X4&& );
    XM_CONSTEXPR XMFLOAT4X4(
        float m00, float m01, float m02, float m03,
        float m10, float m11, float m12, float m13,
        float m20, float m21, float m22, float m23,
        float m30, float m31, float m32, float m33
    );
    void         XMFLOAT4X4( const float* pArray );
    float        operator()( size_t Row, size_t Column );
    float& operator()( size_t Row, size_t Column );
};

 

9. 행렬 함수

DirectXMath 라이브러리에는 아래와 같은 유용한 행렬 관련 함수들이 있다.

 

단위행렬 $I$를 반환한다.

XMMATRIX XM_CALLCONV XMMatrixIdentity();

 

$M$이 단위행렬인지의 여부를 돌려준다.

XMMATRIX XM_CALLCONV XMMatrixIdentity();

 

행렬 곱 $AB$를 반환한다.

XMMATRIX XM_CALLCONV XMMatrixMultiply( FXMMATRIX M1, CXMMATRIX M2 );

 

$M^T$를 반환한다.

XMMATRIX XM_CALLCONV XMMatrixTranspose( FXMMATRIX M );

 

벡터 $(det M, det M, det M, det M)$을 반환한다.

XMVECTOR XM_CALLCONV XMMatrixDeterminant( FXMMATRIX M );

 

$M^{-1}$을 반환한다.

XMMATRIX XM_CALLCONV XMMatrixInverse( XMVECTOR  *pDeterminant, FXMMATRIX M );

 

함수 XMMATRIX 매개변수 선언시에는 XMVECTOR 매개변수를 선언할때와 같은 규칙을 적용한다.

단, XMMATRIX 매개변수 하나가 XMVECTOR 매개변수 네개에 해당한다는 점이 다르다.

함수의 추가적인 FXVECTOR 매개변수가 둘 이하라 했을때, 첫 XMMATRIX 매개변수의 형식은 FXMMATRIX로 하고 나머지는 반드시 CXMATRIX로 해야한다.

생성자에서 XMMATRIX 형식의 인수를 받을 경우, CXMMATRIX를 사용할것을 권한다. 이경우 생성자에는 XM_CALLCONV 호출 규약 지시자를 사용하지 말아야 한다.

 

예제 프로그램

#include <windows.h> // for XMVerifyCPUSupport
#include <DirectXMath.h>
#include <DirectXPackedVector.h>
#include <iostream>
using namespace std;
using namespace DirectX;
using namespace DirectX::PackedVector;

// Overload the  "<<" operators so that we can use cout to 
// output XMVECTOR and XMMATRIX objects.
ostream& XM_CALLCONV operator << (ostream& os, FXMVECTOR v)
{
    XMFLOAT4 dest;
    XMStoreFloat4(&dest, v);

    os << "(" << dest.x << ", " << dest.y << ", " << dest.z << ", " << dest.w << ")";
    return os;
}

ostream& XM_CALLCONV operator << (ostream& os, FXMMATRIX m)
{
    for (int i = 0; i < 4; ++i)
    {
        os << XMVectorGetX(m.r[i]) << "\t";
        os << XMVectorGetY(m.r[i]) << "\t";
        os << XMVectorGetZ(m.r[i]) << "\t";
        os << XMVectorGetW(m.r[i]);
        os << endl;
    }
    return os;
}

int main()
{
    // Check support for SSE2 (Pentium4, AMD K8, and above).
    if (!XMVerifyCPUSupport())
    {
        cout << "directx math not supported" << endl;
        return 0;
    }

    XMMATRIX A(1.0f, 0.0f, 0.0f, 0.0f,
        0.0f, 2.0f, 0.0f, 0.0f,
        0.0f, 0.0f, 4.0f, 0.0f,
        1.0f, 2.0f, 3.0f, 1.0f);

    XMMATRIX B = XMMatrixIdentity();

    XMMATRIX C = A * B;

    XMMATRIX D = XMMatrixTranspose(A);

    XMVECTOR det = XMMatrixDeterminant(A);
    XMMATRIX E = XMMatrixInverse(&det, A);

    XMMATRIX F = A * E;

    cout << "A = " << endl << A << endl;
    cout << "B = " << endl << B << endl;
    cout << "C = A*B = " << endl << C << endl;
    cout << "D = transpose(A) = " << endl << D << endl;
    cout << "det = determinant(A) = " << det << endl << endl;
    cout << "E = inverse(A) = " << endl << E << endl;
    cout << "F = A*E = " << endl << F << endl;
 
    return 0;
}

 

 

 

 

 

 

 

Comments