6#include <glm/gtc/quaternion.hpp>
8#include "core/math/axes.h"
10namespace Vkm::Engine::Math {
20inline glm::vec3 computeForward(
const glm::quat& rotation) {
21 return glm::normalize(rotation * WORLD_FORWARD);
30inline glm::vec3 computeUp(
const glm::quat& rotation) {
31 return glm::normalize(rotation * WORLD_AXIS_Y);
42inline glm::vec3 computeRight(
const glm::quat& rotation) {
43 return glm::normalize(rotation * WORLD_RIGHT);
56inline glm::quat worldRotationOf(
const glm::mat4& worldMatrix) {
57 glm::mat3 basis(worldMatrix);
58 const bool mirrored = glm::determinant(basis) < 0.0f;
60 for (
int axis = 0; axis < 3; ++axis) {
61 const float length = glm::length(basis[axis]);
62 basis[axis] = length != 0.0f ? basis[axis] / length : glm::vec3(0.0f);
65 if (mirrored) basis[0] = -basis[0];
67 for (
int axis = 0; axis < 3; ++axis) {
68 if (glm::dot(basis[axis], basis[axis]) > 0.0f)
continue;
70 const glm::vec3 implied = glm::cross(basis[(axis + 1) % 3], basis[(axis + 2) % 3]);
71 basis[axis] = glm::dot(implied, implied) > 0.0f ? implied : glm::mat3(1.0f)[axis];
74 return glm::normalize(glm::quat_cast(basis));
85inline glm::quat lookRotation(
const glm::vec3& direction,
const glm::vec3& up = {0.0f, 1.0f, 0.0f}) {
86 return glm::quatLookAt(glm::normalize(direction), up);
99inline glm::quat fromYawPitch(
float yaw,
float pitch) {
100 return glm::angleAxis(yaw, WORLD_AXIS_Y) * glm::angleAxis(pitch, WORLD_AXIS_X);
112inline void toYawPitch(
const glm::vec3& direction,
float& yaw,
float& pitch) {
113 const glm::vec3 d = glm::normalize(direction);
114 pitch = std::asin(glm::clamp(d.y, -1.0f, 1.0f));
116 yaw = std::atan2(-d.x, -d.z);