81 lines
2.7 KiB
C++
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)
|