summaryrefslogtreecommitdiff
path: root/src/m4f-3dx.h
blob: 384641b8db76921e67614993ded5c79f36dfd3d5 (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
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
© All Rights Reserved