81 lines
2.7 KiB
C++

#pragma once
#if !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SCENE_TRANSFORM3D_HPP_INCLUDED)
#define SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SCENE_TRANSFORM3D_HPP_INCLUDED 1
#include <glm/mat4x4.hpp>
#include <glm/vec3.hpp>
#include <glm/gtc/matrix_transform.hpp>
#include <glm/gtx/euler_angles.hpp>
#include <glm/gtx/matrix_decompose.hpp>
namespace sdl_gpu_test
{
struct Transform3D
{
glm::mat4 matrix = glm::mat4(1);
[[nodiscard]] Transform3D inverse() const
{
return Transform3D {
.matrix = glm::inverse(matrix)
};
}
[[nodiscard]] Transform3D apply(const Transform3D& other) const
{
return Transform3D{
.matrix = matrix * other.matrix
};
}
template<typename T>
[[nodiscard]] T apply(const T& value) const
{
return matrix * value;
}
[[nodiscard]] glm::vec3 apply(const glm::vec3 value) const
{
return glm::vec3(matrix * glm::vec4(value, 1.f));
}
[[nodiscard]] glm::vec3 applyRotation(const glm::vec3 vec) const
{
// TODO: maybe find a better way to extract the rotation? this is really expensive
glm::vec3 scale;
glm::quat orientation;
glm::vec3 translation;
glm::vec3 skew;
glm::vec4 perspective;
glm::decompose(matrix, scale, orientation, translation, skew, perspective);
return orientation * vec;
}
[[nodiscard]] glm::vec3 getTranslation() const { return glm::vec3(matrix[3]); }
inline void setTranslation(const glm::vec3& translation);
void setLookAt(const glm::vec3& eye, const glm::vec3& target, const glm::vec3& up = glm::vec3(0.f, 1.f, 0.f)) {
matrix = glm::inverse(glm::lookAt(eye, target, up)); // glm lookAt() is for camera matrices, therefore basically inverted
}
[[nodiscard]] static inline Transform3D make(const glm::vec3& translation, const glm::quat& rotation = {}, const glm::vec3& scale = glm::vec3(1.f));
[[nodiscard]] static Transform3D makeLookAt(const glm::vec3& eye, const glm::vec3& target, const glm::vec3& up = glm::vec3(0.f, 1.f, 0.f)) {
return Transform3D{glm::inverse(glm::lookAt(eye, target, up))}; // glm lookAt() is for camera matrices, therefore basically inverted
}
};
inline Transform3D Transform3D::make(const glm::vec3& translation, const glm::quat& rotation, const glm::vec3& scale)
{
return Transform3D{glm::translate(glm::mat4_cast(rotation) * glm::scale(glm::mat4(1), scale), translation)};
}
void Transform3D::setTranslation(const glm::vec3& translation)
{
matrix[3] = glm::vec4(translation, 1.f);
}
} // namespace sdl_gpu_test
#endif // !defined(SDL_GPU_TEST_PRIVATE_SDL_GPU_TEST_SCENE_TRANSFORM3D_HPP_INCLUDED)