과제에서 사용하지 말라는 GLM을 대체할 나만의 GLMath 라이브러리를 만들었다.
OpenGL을 배울 때 사용했던 코드들을 참고하면서 자주 쓰였고, 필요해 보이는 함수들로 구성했다. 이 안에서 대부분 해결할 수 있을 것 같지만, 프로젝트를 진행하면서 추가로 필요한 함수가 있으면 그때그때 새로 추가할 예정이다.
위 클래스들은 기본적으로 float 값을 사용한다. 기본적인 생성자, 복사 생성자, 복사 대입 연산자, +, -, *, [] 연산자 등을 구현해두었다. 추가로 상수 곱 연산과 mat4 * vec4 연산도 구현했다.
몇 번 써본 익숙한 함수들이라 구현 자체는 어렵지 않았다. 하지만 몇 가지 헷갈리는 부분도 있었다.
그 중 하나는 scale, translate, rotate는 변환 행렬을 반환하는지, 아니면 매개변수로 받은 행렬에 변환을 적용해 반환하는지에 대한 의문이었다. 이 의문을 해결하기 위해 실제 glm 함수를 실행해봤다. 그 결과 glm 함수들은 첫 번째 매개변수로 준 행렬 뒤에 변환 행렬을 곱해 반환해줬고, 이를 그대로 따라 구현했다.
rotate 함수의 변환 방식에 대해서도 한 번 찾아보았다. 내가 42 서울 과제 FDF에서 사용했던 오일러 변환이 아니라, 특정 축에 대해 theta만큼 회전하는 축-각 변환을 사용한다는 것을 알게 되었다. 오일러 변환은 짐벌락(Gimbal Lock) 문제가 발생할 수 있다는 점에서 잘 안 쓰이는 게 맞는 듯하다.
이렇게 나만의 GLM인 glmath 라이브러리를 만들어 보았다. 함수 구현을 하나 마치면 실제 GLM과 비교해 테스트해보고 다음 함수의 구현으로 넘어가는 과정을 거치며 차근 차근 라이브러리를 구현하였다. 지금 문제를 발견하지 않으면 나중에 더 큰 고생을 하게 될 수 있기 때문에, 귀찮지만 꼭 해야 하는 과정이었다.
강의를 들으며 glm 라이브러리를 사용할 때는 다 이해하며 사용한다 생각했는데, 직접 구현해보니 완전히 이해하지 못한 부분도 있었다. 확실히 직접 구현하면서 배우는 점이 많은 것 같다.
다음에는 텍스처를 어떻게 가져올 것인지에 대해 생각해보는 시간을 가져볼 것이다.
#ifndef GLMATH_H
# define GLMATH_H
# include <stdexcept>
# include <cmath>
namespace glmath{
constexpr float pi = 3.14159f;
class vec2 {
private:
public:
float x;
float y;
vec2();
vec2(float x);
vec2(float x, float y);
vec2(const vec2& copy);
vec2& operator=(const vec2& copy);
vec2 operator+(const vec2& rhs) const;
vec2 operator-(const vec2& rhs) const;
vec2 operator*(const vec2& rhs) const;
float& operator[](int idx);
float operator[](int idx) const;
};
class vec3 {
private:
public:
float x;
float y;
float z;
vec3();
vec3(float x);
vec3(float x, float y, float z);
vec3(const vec3& copy);
vec3& operator=(const vec3& copy);
vec3 operator+(const vec3& rhs) const;
vec3 operator-(const vec3& rhs) const;
vec3 operator*(const vec3& rhs) const;
float& operator[](int idx);
float operator[](int idx) const;
};
class vec4 {
private:
public:
float x;
float y;
float z;
float w;
vec4();
vec4(float x);
vec4(float x, float y, float z, float w);
vec4(const vec4& copy);
vec4& operator=(const vec4& copy);
vec4 operator+(const vec4& rhs) const;
vec4 operator-(const vec4& rhs) const;
vec4 operator*(const vec4& rhs) const;
float& operator[](int idx);
float operator[](int idx) const;
};
class mat4 {
private:
public:
vec4 data[4];
mat4();
mat4(float x);
mat4(const vec4& c1, const vec4& c2, const vec4& c3, const vec4& c4);
mat4(const mat4& copy);
mat4& operator=(const mat4& copy);
mat4 operator+(const mat4& rhs) const;
mat4 operator-(const mat4& rhs) const;
mat4 operator*(const mat4& rhs) const;
vec4& operator[](int idx);
vec4 operator[](int idx) const;
};
vec2 operator*(float scalar, const vec2& vector);
vec2 operator*(const vec2& vector, float scalar);
vec3 operator*(float scalar, const vec3& vector);
vec3 operator*(const vec3& vector, float scalar);
vec4 operator*(float scalar, const vec4& vector);
vec4 operator*(const vec4& vector, float scalar);
vec4 operator*(const mat4& matrix, const vec4& vector);
mat4 operator*(float scalar, const mat4& matrix);
mat4 operator*(const mat4& matrix, float scalar);
float* value_ptr(vec2& vector);
float* value_ptr(vec3& vector);
float* value_ptr(vec4& vector);
float* value_ptr(mat4& matrix);
float dot(const vec2& vector1, const vec2& vector2);
float dot(const vec3& vector1, const vec3& vector2);
float dot(const vec4& vector1, const vec4& vector2);
vec3 cross(const vec3& vector1, const vec3& vector2);
vec2 normalize(const vec2& vector);
vec3 normalize(const vec3& vector);
vec4 normalize(const vec4& vector);
float radians(float degree);
mat4 scale(const mat4& matrix, const vec3& vector);
mat4 translate(const mat4& matrix, const vec3& vector);
mat4 rotate(const mat4& matrix, float theta, const vec3& vector);
mat4 perspective(float fovy, float aspect, float zNear, float zFar);
mat4 lookAt(vec3 cameraPos, vec3 cameraTarget, vec3 cameraUp);
}
#endif
SCOP : 기능별 클래스로 리팩토링하기 - (6) (0) | 2024.09.23 |
---|---|
SCOP : BMP 이미지 파싱과 텍스처 매핑 구현 - (5) (0) | 2024.09.23 |
SCOP : 빌드 환경 설정 및 기본 구조 준비 - (3) (0) | 2024.09.19 |
SCOP : 프로젝트 진행 계획 - (2) (1) | 2024.09.18 |
SCOP : 3D 객체 렌더링의 기본 - (1) (2) | 2024.09.18 |