summaryrefslogtreecommitdiffstats
path: root/core/math/angles.hh
blob: 174f320d49c7445047f0f3aac81bd545481f4b2f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#pragma once

#include "core/math/constexpr.hh"

constexpr float A180 = math::radians(180.0f);
constexpr float A360 = math::radians(360.0f);

namespace math
{
float wrap_180(float angle);
float wrap_360(float angle);
} // namespace math

namespace math
{
glm::fvec3 wrap_180(const glm::fvec3& angles);
glm::fvec3 wrap_360(const glm::fvec3& angles);
} // namespace math

namespace math
{
void vectors(const glm::fvec3& angles, glm::fvec3& forward);
void vectors(const glm::fvec3& angles, glm::fvec3* forward, glm::fvec3* right, glm::fvec3* up);
} // namespace math

inline float math::wrap_180(float angle)
{
    const auto result = std::fmod(angle + A180, A360);

    if(result < 0.0f) {
        return result + A180;
    }

    return result - A180;
}

inline float math::wrap_360(float angle)
{
    return std::fmod(std::fmod(angle, A360) + A360, A360);
}

inline glm::fvec3 math::wrap_180(const glm::fvec3& angles)
{
    return glm::fvec3 {
        math::wrap_180(angles.x),
        math::wrap_180(angles.y),
        math::wrap_180(angles.z),
    };
}

inline glm::fvec3 math::wrap_360(const glm::fvec3& angles)
{
    return glm::fvec3 {
        math::wrap_360(angles.x),
        math::wrap_360(angles.y),
        math::wrap_360(angles.z),
    };
}

inline void math::vectors(const glm::fvec3& angles, glm::fvec3& forward)
{
    const float cosp = std::cos(angles.x);
    const float cosy = std::cos(angles.y);
    const float sinp = std::sin(angles.x);
    const float siny = std::sin(angles.y);

    forward.x = cosp * siny * (-1.0f);
    forward.y = sinp;
    forward.z = cosp * cosy * (-1.0f);
}

inline void math::vectors(const glm::fvec3& angles, glm::fvec3* forward, glm::fvec3* right, glm::fvec3* up)
{
    if(!forward && !right && !up) {
        // There's no point in figuring out
        // direction vectors if nothing is passed
        // in the function to store that stuff in
        return;
    }

    const auto pcv = glm::cos(angles);
    const auto psv = glm::sin(angles);
    const auto ncv = pcv * (-1.0f);
    const auto nsv = psv * (-1.0f);

    if(forward) {
        forward->x = pcv.x * nsv.y;
        forward->y = psv.x;
        forward->z = pcv.x * ncv.y;
    }

    if(right) {
        right->x = pcv.z * pcv.y;
        right->y = psv.z * pcv.y;
        right->z = nsv.y;
    }

    if(up) {
        up->x = psv.x * psv.y * pcv.z + ncv.y * psv.z;
        up->y = pcv.x * pcv.z;
        up->z = nsv.x * ncv.y * pcv.z + psv.y * psv.z;
    }
}