openMSX
gl_transform.hh
Go to the documentation of this file.
1#ifndef GL_TRANSFORM_HH
2#define GL_TRANSFORM_HH
3
4// openGL ES 2.0 removed functions like
5// glRotate(), glTranslate(), glScale(), ...
6// This code can be used to replace them.
7//
8// This code was inspired by the 'glm' library (though written from scratch).
9// Compared to glm this code is much simpler but offers much less functionality.
10// http://glm.g-truc.net
11
12#include "gl_mat.hh"
13#include "gl_vec.hh"
14
15namespace gl {
16
17// Returns a 4x4 scaling matrix for the given xyz scale factors.
18// Comparable to the glScale() function.
19[[nodiscard]] constexpr mat4 scale(const vec3& xyz)
20{
21 return mat4(vec4(xyz, 1.0f));
22}
23
24// Multiplies the given matrix by a scaling matrix. Equivalent to (but more
25// efficient than) 'A * scale(xyz)'.
26[[nodiscard]] constexpr mat4 scale(const mat4& A, const vec3& xyz)
27{
28 return {A[0] * xyz.x,
29 A[1] * xyz.y,
30 A[2] * xyz.z,
31 A[3]};
32}
33
34// Returns a 4x4 translation matrix for the given xyz translation vector.
35// Comparable to the glTranslate() function.
36[[nodiscard]] constexpr mat4 translate(const vec3& xyz)
37{
38 mat4 result;
39 result[3] = vec4(xyz, 1.0f);
40 return result;
41}
42
43// Multiplies the given matrix by a translation matrix. Equivalent to (but
44// more efficient than) 'A * translate(xyz)'.
45[[nodiscard]] constexpr mat4 translate(mat4& A, const vec3& xyz)
46{
47 return {A[0],
48 A[1],
49 A[2],
50 A[0] * xyz.x + A[1] * xyz.y + A[2] * xyz.z + A[3]};
51}
52
53// Returns a 4x4 rotation matrix for rotation of the given 'angle' around the
54// 'xyz' axis.
55// Comparable to the glRotate() function, but with these differences:
56// - 'angle' is in radians instead of degrees
57// - 'axis' must be a normalized vector
58[[nodiscard]] inline mat4 rotate(float angle, const vec3& axis)
59{
60 float s = sinf(angle);
61 float c = cosf(angle);
62 vec3 temp = (1.0f - c) * axis;
63
64 return {vec4(axis.x * temp.x + c,
65 axis.y * temp.x + s * axis.z,
66 axis.z * temp.x - s * axis.y,
67 0.0f),
68 vec4(axis.x * temp.y - s * axis.z,
69 axis.y * temp.y + c,
70 axis.z * temp.y + s * axis.x,
71 0.0f),
72 vec4(axis.x * temp.z + s * axis.y,
73 axis.y * temp.z - s * axis.x,
74 axis.z * temp.z + c,
75 0.0f),
76 vec4(0.0f,
77 0.0f,
78 0.0f,
79 1.0f)};
80}
81
82// Multiplies the given matrix by a rotation matrix. Equivalent to
83// 'A * rotate(angle, axis)'.
84[[nodiscard]] inline mat4 rotate(const mat4& A, float angle, const vec3& axis)
85{
86 // TODO this could be optimized (only a little), though it's rarely used
87 return A * rotate(angle, axis);
88}
89
90// Returns a 4x4 rotation matrix for rotation around the X-axis. Much more
91// efficient than calling the generic rotate() function with a vec3(1,0,0)
92// axis.
93[[nodiscard]] inline mat4 rotateX(float angle)
94{
95 float s = sinf(angle);
96 float c = cosf(angle);
97 return {vec4(1.0f, 0.0f, 0.0f, 0.0f),
98 vec4(0.0f, c , s , 0.0f),
99 vec4(0.0f, -s , c , 0.0f),
100 vec4(0.0f, 0.0f, 0.0f, 1.0f)};
101}
102
103// Multiplies the given matrix by a X-rotation matrix. Equivalent to (but more
104// efficient than) 'A * rotateX(angle)'.
105[[nodiscard]] inline mat4 rotateX(const mat4& A, float angle)
106{
107 float s = sinf(angle);
108 float c = cosf(angle);
109 return {A[0],
110 A[1] * c + A[2] * s,
111 A[2] * c - A[1] * s,
112 A[3]};
113}
114
115// Returns a 4x4 rotation matrix for rotation around the Y-axis. Much more
116// efficient than calling the generic rotate() function with a vec3(0,1,0)
117// axis.
118[[nodiscard]] inline mat4 rotateY(float angle)
119{
120 float s = sinf(angle);
121 float c = cosf(angle);
122 return {vec4( c , 0.0f, -s , 0.0f),
123 vec4(0.0f, 1.0f, 0.0f, 0.0f),
124 vec4( s , 0.0f, c , 0.0f),
125 vec4(0.0f, 0.0f, 0.0f, 1.0f)};
126}
127
128// Multiplies the given matrix by a Y-rotation matrix. Equivalent to (but more
129// efficient than) 'A * rotateY(angle)'.
130[[nodiscard]] inline mat4 rotateY(const mat4& A, float angle)
131{
132 float s = sinf(angle);
133 float c = cosf(angle);
134 return {A[0] * c - A[2] * s,
135 A[1],
136 A[2] * c + A[0] * s,
137 A[3]};
138}
139
140// Returns a 4x4 rotation matrix for rotation around the Z-axis. Much more
141// efficient than calling the generic rotate() function with a vec3(0,0,1)
142// axis.
143[[nodiscard]] inline mat4 rotateZ(float angle)
144{
145 float s = sinf(angle);
146 float c = cosf(angle);
147 return {vec4( c , s , 0.0f, 0.0f),
148 vec4(-s , c , 0.0f, 0.0f),
149 vec4(0.0f, 0.0f, 1.0f, 0.0f),
150 vec4(0.0f, 0.0f, 0.0f, 1.0f)};
151}
152
153// Multiplies the given matrix by a Z-rotation matrix. Equivalent to (but more
154// efficient than) 'A * rotateZ(angle)'.
155[[nodiscard]] inline mat4 rotateZ(const mat4& A, float angle)
156{
157 float s = sinf(angle);
158 float c = cosf(angle);
159 return {A[0] * c + A[1] * s,
160 A[1] * c - A[0] * s,
161 A[2],
162 A[3]};
163}
164
165// Note: Don't use "near" or "far" as names since those are macros on Windows.
166
167// Returns a 4x4 orthographic projection matrix. Comparable to
168// the glOrtho() function.
169[[nodiscard]] constexpr mat4 ortho(
170 float left, float right,
171 float bottom, float top,
172 float nearVal, float farVal)
173{
174 return {vec4(-2.0f / (left - right), 0.0f, 0.0f, 0.0f),
175 vec4( 0.0f, -2.0f / (bottom - top), 0.0f, 0.0f),
176 vec4( 0.0f, 0.0f, 2.0f / (nearVal - farVal), 0.0f),
177 vec4((left + right ) / (left - right ),
178 (bottom + top ) / (bottom - top ),
179 (nearVal + farVal) / (nearVal - farVal),
180 1.0f)};
181}
182
183// Equivalent to calling the above ortho() function with:
184// ortho(0.0f, width, height, 0.0f, -1.0f, 1.0f)
185// In other words setup an orthographic projection with "natural screen
186// coordinates", (0,0) the top-right corner.
187[[nodiscard]] constexpr mat4 ortho(float width, float height)
188{
189 return {vec4(2.0f / width, 0.0f, 0.0f, 0.0f),
190 vec4(0.0f, -2.0f / height, 0.0f, 0.0f),
191 vec4(0.0f, 0.0f, -1.0f, 0.0f),
192 vec4(-1.0f, 1.0f, 0.0f, 1.0f)};
193}
194
195// Returns a 4x4 frustum projection matrix. Comparable to
196// the glFrustum() function.
197[[nodiscard]] constexpr mat4 frustum(
198 float left, float right,
199 float bottom, float top,
200 float nearVal, float farVal)
201{
202 return {vec4((2.0f * nearVal) / (right - left), 0.0f, 0.0f, 0.0f),
203 vec4(0.0f, (2.0f * nearVal) / (top - bottom), 0.0f, 0.0f),
204 vec4((right + left ) / (right - left ),
205 (top + bottom) / (top - bottom),
206 (nearVal + farVal) / (nearVal - farVal),
207 -1.0f),
208 vec4(0.0f,
209 0.0f,
210 (2.0f * farVal * nearVal) / (nearVal - farVal),
211 0.0f)};
212}
213
214} // namespace gl
215
216#endif
Definition gl_mat.hh:23
mat4 rotateZ(float angle)
mat4 rotate(float angle, const vec3 &axis)
mat4 rotateY(float angle)
mat4 rotateX(float angle)
constexpr mat4 ortho(float left, float right, float bottom, float top, float nearVal, float farVal)
matMxN< 4, 4, float > mat4
Definition gl_mat.hh:127
vecN< 4, float > vec4
Definition gl_vec.hh:192
constexpr mat4 frustum(float left, float right, float bottom, float top, float nearVal, float farVal)
constexpr mat4 translate(const vec3 &xyz)
constexpr mat4 scale(const vec3 &xyz)