새소식

인기 검색어

게임 개발/그래픽스

행렬 (GLM)

  • -

참고자료: https://en.wikipedia.org/wiki/Row-_and_column-major_order

 

Row- and column-major order - Wikipedia

From Wikipedia, the free encyclopedia Array representation in computer memory Illustration of difference between row- and column-major ordering In computing, row-major order and column-major order are methods for storing multidimensional arrays in linear s

en.wikipedia.org

GLM(Opengl, Vulkan, WebGL)에서는 Column-major order를 사용한다.

DirectX 에서는 Row-major order를 사용

 

#include <glm/glm.hpp>
#include <glm/gtx/string_cast.hpp> // cout 출력을 위한 string_cast()

#include <glm/gtc/matrix_inverse.hpp> // inverseTranspose
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/transform.hpp> // translate, rotate, scale

#include <iostream>

// 일반적으로 .cpp 파일에서 using namespace를 사용하는 것은 괜찮습니다.
using namespace std; // cout, endl;
using namespace glm;

int main() {
    /*
     * glm 설치
     * vcpkg install glm:x64-windows
     */

    // glm::mat2 (2x2 column-major matrix)
    mat2 A = mat2(1, 2, 3, 4);

    cout << to_string(A) << endl;
    // mat2x2((1.000000, 2.000000),
    //        (3.000000, 4.000000))
    // 우리가 생각하는 행렬 (column-major)
    // |1 3|
    // |2 4|

    cout << to_string(transpose(A)) << endl;
    // mat2x2((1.000000, 3.000000),
    //        (2.000000, 4.000000))

    cout << to_string(A[1]) << endl;
    // vec2(3.000000, 4.000000)

    mat2 B = mat2(5, 6, 7, 8);

    mat2 C = A + B;

    cout << to_string(C) << endl;

    // mat2x2((6.000000, 8.000000),
    //	      (10.000000, 12.000000))

    cout << to_string(A * B) << endl;
    // mat2x2((23.000000, 34.000000), (31.000000, 46.000000))

    cout << to_string(B * A) << endl;
    // mat2x2((19.000000, 22.000000), (43.000000, 50.000000))

    // glm::mat4 (column-major)
    mat4 m = mat4(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
    // mat4x4((1.000000, 2.000000, 3.000000, 4.000000),
    //        (5.000000, 6.000000, 7.000000, 8.000000),
    //        (9.000000, 10.000000, 11.000000, 12.000000),
    //        (13.000000, 14.000000, 15.000000, 16.000000))
    // 우리가 생각하는 행렬 (column-major)
    // |1 5  9 13|
    // |2 6 10 14|
    // |3 7 11 15|
    // |4 8 12 16|

    m *= 10.0f;
    m = 2.0f * m + m;

    // x방향으로 1, y방향으로2, z방향으로3 이동하는 행렬 만듦
    mat4 translation = translate(vec3(1.0f, 2.0f, 3.0f));

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

    cout << to_string(translation) << endl;
    // mat4x4((1.000000, 0.000000, 0.000000, 0.000000),
    //        (0.000000, 1.000000, 0.000000, 0.000000),
    //        (0.000000, 0.000000, 1.000000, 0.000000),
    //        (1.000000, 2.000000, 3.000000, 1.000000))
    // Column-Major (GLM)
    // |1 0 0 1|
    // |0 1 0 2|
    // |0 0 1 3|
    // |0 0 0 1|
    // Row-Major (DX)
    // |1 0 0 0|
    // |0 1 0 0|
    // |0 0 1 0|
    // |1 2 3 1|

    vec4 myPoint = vec4(4, 5, 6, 1);
    vec4 myVector = vec4(4, 5, 6, 0);

    cout << to_string(translation * myPoint) << endl;
    // vec4(5.000000, 7.000000, 9.000000, 1.000000)

    // 벡터는 이동이 되지 않는다!
    cout << to_string(translation * myVector) << endl;
    // vec4(4.000000, 5.000000, 6.000000, 0.000000)

    cout << to_string(glm::inverse(translation)) << endl;
    // mat4x4((1.000000, -0.000000, 0.000000, -0.000000),
    //        (-0.000000, 1.000000, -0.000000, 0.000000),
    //        (0.000000, -0.000000, 1.000000, -0.000000),
    //        (-1.000000, -2.000000, -3.000000, 1.000000))

    // rotate 함수에 회전각도, 회전 축을 지정해주면 됨.
    mat4 rotationX = rotate(glm::pi<float>() / 3.0f, vec3(1.0f, 0.0f, 0.0f));
    cout << to_string(rotationX) << endl;
    // mat4x4((1.000000, 0.000000, 0.000000, 0.000000),
    //        (0.000000, 0.500000, 0.866025, 0.000000),
    //        (0.000000, -0.866025, 0.500000, 0.000000),
    //        (0.000000, 0.000000, 0.000000, 1.000000))
    // 1, 0,   0,   0
    // 0, cos, sin, 0
    // 0, -sin, cos, 0
    // 0, 0,    0,   1 => 이동 없음 0, 0, 0 임
    // 회전축이 1, 0, 0 이기 때문에 x축이 회전축인것임
    // 회전이 pi/3 만큼이라서 60도 회전인것임


    // 회전행렬은 그 특성상 Transpose 하면 역변환이다.
    // 즉, 연산량많은 inverse를 할 필요 없음
    cout << to_string(glm::transpose(rotationX)) << endl;
    // mat4x4((1.000000, 0.000000, 0.000000, 0.000000),
    //        (0.000000, 0.500000, -0.866025, 0.000000),
    //        (0.000000, 0.866025, 0.500000, 0.000000),
    //        (0.000000, 0.000000, 0.000000, 1.000000))
    // 같은 x축에대해 -60도 회전

    // 회전 행렬의 전치 행렬은 회전의 역행렬과 동일합니다.
    cout << to_string(glm::transpose(rotationX) * rotationX) << endl;
    // mat4x4((1.000000, 0.000000, 0.000000, 0.000000),
    //        (0.000000, 1.000000, 0.000000, 0.000000),
    //        (0.000000, 0.000000, 1.000000, 0.000000),
    //        (0.000000, 0.000000, 0.000000, 1.000000))
    // 두 행렬을 곱하면 identity matrix(단위행렬)가 나옴

    // 순서 주의: 회전 후 이동
    cout << to_string((translation * rotationX) * vec4(1.0f, 0.0f, 0.0f, 1.0f))
         << endl;
    // vec4(2.000000, 2.000000, 3.000000, 1.000000)
    // 참고로 변환 (translation * rotation) 을 먼저 연산하고 묶어서 gpu로 보내줘서 계산하는게 훨씬 빠름

    // 순서 주의: 이동 후 회전
    cout << to_string((rotationX * translation) * vec4(1.0f, 0.0f, 0.0f, 1.0f))
         << endl;
    // vec4(2.000000, -1.598076, 3.232051, 1.000000)

    // Transpose로 row-major로 변경가능
    cout << to_string(vec4(1.0f, 0.0f, 0.0f, 1.0f) *
                      glm::transpose(translation * rotationX))
         << endl;
    // vec4(2.000000, 2.000000, 3.000000, 1.000000)

    cout << to_string(glm::scale(vec3(0.5f, 1.0f, 2.0f))) << endl;
    // mat4x4((0.500000, 0.000000, 0.000000, 0.000000),
    //        (0.000000, 1.000000, 0.000000, 0.000000),
    //        (0.000000, 0.000000, 2.000000, 0.000000),
    //        (0.000000, 0.000000, 0.000000, 1.000000))
}

 

 

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

DirectXMath(SimpleMath)  (1) 2023.11.22
조명(GLM행렬), 노멀 벡터 변환  (1) 2023.11.22
좌표계 변환  (0) 2023.11.22
애파인 변환 (Affine Transformation)  (0) 2023.11.21
회전  (0) 2023.11.19
Contents

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

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