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
113
114
115
116
117
118
119
120
121
122
|
/*
* Copyright (C) 2018-2020 - Vito Caputo - <vcaputo@pengaru.com>
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef _M4F_3DX_H
#define _M4F_3DX_H
#include <math.h>
#include "m4f.h"
#include "v3f.h"
/* helpers for manipulating 3D transformation matrices */
/* XXX: note this is column-major */
/* adjust the matrix m to translate by v, returning the resulting matrix */
/* if m is NULL the identity vector is assumed */
static inline m4f_t m4f_translate(const m4f_t *m, const v3f_t *v)
{
m4f_t identity = m4f_identity();
m4f_t translate = m4f_identity();
if (!m)
m = &identity;
translate.m[3][0] = v->x;
translate.m[3][1] = v->y;
translate.m[3][2] = v->z;
return m4f_mult(m, &translate);
}
/* adjust the matrix m to scale by v, returning the resulting matrix */
/* if m is NULL the identity vector is assumed */
static inline m4f_t m4f_scale(const m4f_t *m, const v3f_t *v)
{
m4f_t identity = m4f_identity();
m4f_t scale = {};
if (!m)
m = &identity;
scale.m[0][0] = v->x;
scale.m[1][1] = v->y;
scale.m[2][2] = v->z;
scale.m[3][3] = 1.f;
return m4f_mult(m, &scale);
}
/* adjust the matrix m to rotate around the specified axis by radians, returning the resulting matrix */
/* axis is expected to be a unit vector */
/* if m is NULL the identity vector is assumed */
static inline m4f_t m4f_rotate(const m4f_t *m, const v3f_t *axis, float radians)
{
m4f_t identity = m4f_identity();
float cos_r = cosf(radians);
float sin_r = sinf(radians);
m4f_t rotate;
if (!m)
m = &identity;
rotate.m[0][0] = cos_r + axis->x * axis->x * (1.f - cos_r);
rotate.m[0][1] = axis->y * axis->x * (1.f - cos_r) + axis->z * sin_r;
rotate.m[0][2] = axis->z * axis->x * (1.f - cos_r) - axis->y * sin_r;
rotate.m[0][3] = 0.f;
rotate.m[1][0] = axis->x * axis->y * (1.f - cos_r) - axis->z * sin_r;
rotate.m[1][1] = cos_r + axis->y * axis->y * (1.f - cos_r);
rotate.m[1][2] = axis->z * axis->y * (1.f - cos_r) + axis->x * sin_r;
rotate.m[1][3] = 0.f;
rotate.m[2][0] = axis->x * axis->z * (1.f - cos_r) + axis->y * sin_r;
rotate.m[2][1] = axis->y * axis->z * (1.f - cos_r) - axis->x * sin_r;
rotate.m[2][2] = cos_r + axis->z * axis->z * (1.f - cos_r);
rotate.m[2][3] = 0.f;
rotate.m[3][0] = 0.f;
rotate.m[3][1] = 0.f;
rotate.m[3][2] = 0.f;
rotate.m[3][3] = 1.f;
return m4f_mult(m, &rotate);
}
/* this is a simple perpsective projection matrix taken from an opengl tutorial */
static inline m4f_t m4f_frustum(float bot, float top, float left, float right, float nnear, float ffar)
{
m4f_t m = {};
m.m[0][0] = 2 * nnear / (right - left);
m.m[1][1] = 2 * nnear / (top - bot);
m.m[2][0] = (right + left) / (right - left);;
m.m[2][1] = (top + bot) / (top - bot);
m.m[2][2] = -(ffar + nnear) / (ffar - nnear);
m.m[2][3] = -1;
m.m[3][2] = -2 * ffar * nnear / (ffar - nnear);
return m;
}
#endif
|