aboutsummaryrefslogtreecommitdiff
path: root/mons_3d/src/transform.c
blob: c4435fcd24ff858703961b35fc74c7f0242671b5 (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
104
105
106
107
108
109
110
111
112
#include <math.h>
#include "transform.h"
#include "mons_math/vec3.h"
#include "mons_math/quat.h"
#include <stdio.h>

mons_mat4 translation_to_mat4(mons_vec3 translation) {
    mons_mat4 result = MONS_MAT4_IDENTITY;
    result.m1.w = translation.x;
    result.m2.w = translation.y;
    result.m3.w = translation.z;
    return result;
}

mons_mat4 scale_to_mat4(mons_vec3 scale) {
    mons_mat4 result = MONS_MAT4_IDENTITY;
    result.m1.x = scale.x;
    result.m2.y = scale.y;
    result.m3.z = scale.z;
    return result;
}

void mons_transform_translate(mons_transform *transform,
                              mons_vec3 translation) {
    mons_vec3_add_inplace(&transform->translation, translation);
}

void mons_transform_rotate(mons_transform *transform, mons_quat rotation) {
    mons_quat_mul_inplace(&transform->rotation, rotation);
}

void mons_transform_scale(mons_transform *transform, mons_vec3 scale) {
    mons_vec3_mul_memberwise_inplace(&transform->scale, scale);
}

mons_mat4 mons_transform_matrix(mons_transform transform) {
    mons_mat4 translation = translation_to_mat4(transform.translation);
    mons_mat4 result = translation;
    mons_mat4_mul_inplace(&result, mons_quat_to_mat4(transform.rotation));
    mons_mat4_mul_inplace(&result, scale_to_mat4(transform.scale));
    return result;
}

mons_vec3 mons_transform_forward(mons_transform transform) {
    return mons_quat_transform_vec3(transform.rotation, MONS_VEC3_Z);
}

mons_vec3 mons_transform_up(mons_transform transform) {
    return mons_quat_transform_vec3(transform.rotation, MONS_VEC3_Y);
}

mons_vec3 mons_transform_right(mons_transform transform) {
    return mons_quat_transform_vec3(transform.rotation, MONS_VEC3_X);
}

void mons_transform_look_at(mons_transform *transform, mons_vec3 point, mons_vec3 up) {
    mons_vec3 forward = mons_vec3_normalize(mons_vec3_sub(transform->translation, point));
    mons_vec3 right = mons_vec3_normalize(mons_vec3_cross(up, forward));
    mons_vec3 new_up = mons_vec3_cross(forward, right);
    float m00 = right.x;
    float m01 = right.y;
    float m02 = right.z;
    float m10 = new_up.x;
    float m11 = new_up.y;
    float m12 = new_up.z;
    float m20 = forward.x;
    float m21 = forward.y;
    float m22 = forward.z;

    float num8 = (m00 + m11) + m22;
    mons_quat quaternion = {0};
    if (num8 > 0.0f) {
        float num = sqrt(num8 + 1.0f);
        quaternion.w = num * 0.5f;
        num = 0.5f / num;
        quaternion.x = (m12 - m21) * num;
        quaternion.y = (m20 - m02) * num;
        quaternion.z = (m01 - m10) * num;
        transform->rotation = quaternion;
        return;
    }
    if ((m00 >= m11) && (m00 >= m22))
    {
        float num7 = (float)sqrt(((1.0f + m00) - m11) - m22);
        float num4 = 0.5f / num7;
        quaternion.x = 0.5f * num7;
        quaternion.y = (m01 + m10) * num4;
        quaternion.z = (m02 + m20) * num4;
        quaternion.w = (m12 - m21) * num4;
        transform->rotation = quaternion;
        return;
    }
    if (m11 > m22)
    {
        float num6 = (float)sqrt(((1.0f + m11) - m00) - m22);
        float num3 = 0.5f / num6;
        quaternion.x = (m10 + m01) * num3;
        quaternion.y = 0.5f * num6;
        quaternion.z = (m21 + m12) * num3;
        quaternion.w = (m20 - m02) * num3;
        transform->rotation = quaternion;
        return;
    }
    float num5 = (float)sqrt(((1.0f + m22) - m00) - m11);
    float num2 = 0.5f / num5;
    quaternion.x = (m20 + m02) * num2;
    quaternion.y = (m21 + m12) * num2;
    quaternion.z = 0.5f * num5;
    quaternion.w = (m01 - m10) * num2;
    transform->rotation = quaternion;
    return;
}