새소식

인기 검색어

게임 개발/그래픽스

DirectXMath(SimpleMath)

  • -

DirectXMath 를 직접 사용하기 보다는

directxtk/SimpleMath 를 통해서 간접적으로 DirectXMath를 사용하는 것을 권장.

simple math는 directxMath 의 wrapper이다.

참고로 쉐이더에서는 수학연산을 코딩 하는 방식이 또 다르다.

XMVECTOR vs XMFLOAT

XMVECTOR
SIMD 가속 사용

클래스 멤버로는 XMFLOAT2, 3, 4 사용
연산하기 전에 XMVECTOR로 변환
Type Usage Guidelines
https://learn.microsoft.com/en-us/windows/win32/dxmath/pg-xnamath-getting-started#type-usage-guidelines
요약
1. XMVECTOR: 지역 또는 전역 변수
2. XMFLOAT2, 3, 4: 클래스 멤버
3. XMStoreFloat2, 3, 4: XMVECTOR -> XMFLOAT2, 3, 4
4. XMVECTOR로 연산
5. 결과를 다시 XMFLOATN으로 저장

 

Getting started (DirectXMath) - Win32 apps

The DirectXMath Library implements an optimal and portable interface for arithmetic and linear algebra operations on single-precision floating-point vectors (2D, 3D, and 4D) or matrices (3×3 and 4×4).

learn.microsoft.com

 

왜 이렇게 번거러운 과정을 거치느냐?

-> SIMD 가속을 하기 위해, XMVECTOR는 SIMD 가속을 받기 좋은 구조.

https://en.wikipedia.org/wiki/Single_instruction,_multiple_data

 

Single instruction, multiple data - Wikipedia

From Wikipedia, the free encyclopedia Type of parallel processing This article's factual accuracy may be compromised due to out-of-date information. Please help update this article to reflect recent events or newly available information. (March 2017) Singl

en.wikipedia.org

// DirectXMath를 이용해서 벡터의 길이를 구하는 경우
XMFLOAT4 xfloat4 = {1.0f, 2.0f, 3.0f, 1.0f};
XMVECTOR xvector = XMLoadFloat4(&xfloat4);
xvector = XMVector3Length(xvector); // sqrt(1*1 + 2*2 + 3*3), 함수 이름이
                                    // XMVector 숫자3 Length() 입니다.

float length;
XMStoreFloat(&length, xvector);

사용 코드 예시

// SimpleMath
// vcpkg install directxtk:x64-windows
#include <DirectXMath.h>
#include <d3d11.h>
#include <directxtk/SimpleMath.h>
#include <iostream>

using namespace DirectX;
using namespace std;

ostream &operator<<(ostream &os, XMFLOAT4 m) {
    os << m.x << "\t" << m.y << "\t" << m.z << endl;
    return os;
}

ostream &operator<<(ostream &os, XMFLOAT4X4 m) {
    for (int i = 0; i < 4; ++i) {
        for (int j = 0; j < 4; ++j) {
            os << m.m[i][j] << "\t";
        }
        os << endl;
    }
    return os;
}

int main() {

    // DirectXMath programming guide 참고
    // https://learn.microsoft.com/en-us/windows/win32/dxmath/ovw-xnamath-progguide

    // X64에서는 기본
    // Enable Enhanced Instruction Set -> SSE2
    // https://github.com/weidai11/cryptopp/pull/446

    if (!XMVerifyCPUSupport()) {
        cout << "directx math not supported" << endl;
        return -1;
    }

    // XMVECTOR
    // SIMD 가속 사용

    // 클래스 멤버로는 XMFLOAT2, 3, 4 사용
    // 연산하기 전에 XMVECTOR로 변환
    // Type Usage Guidelines
    // https://learn.microsoft.com/en-us/windows/win32/dxmath/pg-xnamath-getting-started#type-usage-guidelines

    // 요약
    // 1. XMVECTOR: 지역 또는 전역 변수
    // 2. XMFLOAT2, 3, 4: 클래스 멤버
    // 3. XMStoreFloat2, 3, 4: XMVECTOR -> XMFLOAT2, 3, 4
    // 4. XMVECTOR로 연산
    // 5. 결과를 다시 XMFLOATN으로 저장

    // DirectXMath를 이용해서 벡터의 길이를 구하는 경우
    XMFLOAT4 xfloat4 = {1.0f, 2.0f, 3.0f, 1.0f};
    XMVECTOR xvector = XMLoadFloat4(&xfloat4);
    xvector = XMVector3Length(xvector); // sqrt(1*1 + 2*2 + 3*3), 함수 이름이
                                        // XMVector 숫자3 Length() 입니다.

    float length;
    XMStoreFloat(&length, xvector);

    // 행렬을 이용한 변환 예시

    XMMATRIX tr = XMMatrixTranslation(1.0f, 2.0f, 3.0f);

    XMFLOAT4X4 tr4;
    XMStoreFloat4x4(&tr4, tr);

    cout << tr4 << endl;
    // 1 0 0 0
    // 0 1 0 0
    // 0 0 1 0
    // 1 2 3 1

    XMFLOAT4 myPoint = {4.0f, 5.0f, 6.0f, 1.0f};
    XMFLOAT4 myVector = {4.0f, 5.0f, 6.0f, 0.0f};

    XMVECTOR temp = XMLoadFloat4(&myPoint);

    XMVECTOR result = XMVector3TransformCoord(temp, tr); // XMVector4Transform

    XMStoreFloat4(&myPoint, result);
    cout << myPoint << endl;
    // 5       7       9

    temp = XMLoadFloat4(&myVector);

    result = XMVector3TransformNormal(temp, tr); // XMVector4Transform

    XMStoreFloat4(&myVector, result);
    cout << myVector << endl;
    // 4       5       6

    // SimpleMath
    // vcpkg install directxtk:x64-windows
    // #include <directxtk/SimpleMath.h>
    {
        using namespace DirectX::SimpleMath;

        Matrix tr = Matrix::CreateTranslation(Vector3(1.0f, 2.0f, 3.0f));

        // 메모리에 어떤 순서로 저장되는지 확인
        // cout << "Transtion Matrix" << endl;
        // for (int i = 0; i < 16; i++) {
        //     cout << ((float *)&tr)[i] << " ";
        // }
        // cout << endl;
        // 출력결과: 1 0 0 0 0 1 0 0 0 0 1 0 1 2 3 1

        Vector4 myPoint(4.0f, 5.0f, 6.0f, 1.0f);
        Vector4 myVector(4.0f, 5.0f, 6.0f, 0.0f);

        myPoint = Vector4::Transform(myPoint, tr);
        myVector = Vector4::Transform(myVector, tr);

        cout << myPoint << endl;
        // 5       7       9

        cout << myVector << endl;
        // 4       5       6

        cout << tr << endl;
        // 1 0 0 0
        // 0 1 0 0
        // 0 0 1 0
        // 1 2 3 1

        tr.Translation(Vector3(0.0f));
        cout << tr << endl;

        // 1 0 0 0
        // 0 1 0 0
        // 0 0 1 0
        // 0 0 0 1

        // Matrix::CreateScale();
        // Matrix::CreateRotationY();
        // Matrix::CreateRotationX();
        // Matrix::CreateTranslation();
        // M.Translation(Vector3(0.0f));
        // M.Invert().Transpose();
        // Vector4::Transform(point, constants.modelMatrix);
        // n.Normalize();
    }

    return 0;
}

'게임 개발 > 그래픽스' 카테고리의 다른 글

Row-Major order vs Column-Major order  (1) 2023.11.23
조명(SimpleMath)  (0) 2023.11.23
조명(GLM행렬), 노멀 벡터 변환  (1) 2023.11.22
행렬 (GLM)  (1) 2023.11.22
좌표계 변환  (0) 2023.11.22
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.