vkmEngine 1.0.0
A C++ game engine · vkmengine.com
Loading...
Searching...
No Matches
rotation.h
1#pragma once
2
3#include <cmath>
4
5#include <glm/glm.hpp>
6#include <glm/gtc/quaternion.hpp>
7
8#include "core/math/axes.h"
9
10namespace Vkm::Engine::Math {
11
20inline glm::vec3 computeForward(const glm::quat& rotation) {
21 return glm::normalize(rotation * WORLD_FORWARD);
22}
23
30inline glm::vec3 computeUp(const glm::quat& rotation) {
31 return glm::normalize(rotation * WORLD_AXIS_Y);
32}
33
42inline glm::vec3 computeRight(const glm::quat& rotation) {
43 return glm::normalize(rotation * WORLD_RIGHT);
44}
45
56inline glm::quat worldRotationOf(const glm::mat4& worldMatrix) {
57 glm::mat3 basis(worldMatrix);
58 const bool mirrored = glm::determinant(basis) < 0.0f;
59
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);
63 }
64 // Otherwise quat_cast reads the reflection as a rotation.
65 if (mirrored) basis[0] = -basis[0];
66
67 for (int axis = 0; axis < 3; ++axis) {
68 if (glm::dot(basis[axis], basis[axis]) > 0.0f) continue;
69
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];
72 }
73
74 return glm::normalize(glm::quat_cast(basis));
75}
76
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);
87}
88
99inline glm::quat fromYawPitch(float yaw, float pitch) {
100 return glm::angleAxis(yaw, WORLD_AXIS_Y) * glm::angleAxis(pitch, WORLD_AXIS_X);
101}
102
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));
115 // Negated: yaw 0 is -Z, so the angle is measured from there.
116 yaw = std::atan2(-d.x, -d.z);
117}
118
119} // namespace Vkm::Engine::Math