Pyrogenesis HEAD
Pyrogenesis, a RTS Engine
Matrix3D.h
Go to the documentation of this file.
1/* Copyright (C) 2022 Wildfire Games.
2 * This file is part of 0 A.D.
3 *
4 * 0 A.D. is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * 0 A.D. is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with 0 A.D. If not, see <http://www.gnu.org/licenses/>.
16 */
17
18/*
19 * A Matrix class used for holding and manipulating transformation
20 * info.
21 */
22
23#ifndef INCLUDED_MATRIX3D
24#define INCLUDED_MATRIX3D
25
26#include "maths/Vector3D.h"
27#include "maths/Vector4D.h"
28#include "ps/containers/Span.h"
29
30class CQuaternion;
31
32// CMatrix3D: a 4x4 matrix class for common operations in 3D
34{
35public:
36 // the matrix data itself - accessible as either longhand names
37 // or via a flat or 2d array
38 // NOTE: _xy means row x, column y in the mathematical notation of this matrix, so don't be
39 // fooled by the way they're listed below
40 union
41 {
42 struct
43 {
44 float _11, _21, _31, _41;
45 float _12, _22, _32, _42;
46 float _13, _23, _33, _43;
47 float _14, _24, _34, _44;
48 };
49 float _data[16];
50 float _data2d[4][4];
51 // (Be aware that m(0,2) == _data2d[2][0] == _13, etc. This is to be considered a feature.)
52 };
53
54public:
55 // constructors
57 {
58 }
59
61 float a11, float a12, float a13, float a14,
62 float a21, float a22, float a23, float a24,
63 float a31, float a32, float a33, float a34,
64 float a41, float a42, float a43, float a44) :
65 _11(a11), _12(a12), _13(a13), _14(a14),
66 _21(a21), _22(a22), _23(a23), _24(a24),
67 _31(a31), _32(a32), _33(a33), _34(a34),
68 _41(a41), _42(a42), _43(a43), _44(a44)
69 {
70 }
71
72 CMatrix3D(float data[]) :
73 _11(data[0]), _21(data[1]), _31(data[2]), _41(data[3]),
74 _12(data[4]), _22(data[5]), _32(data[6]), _42(data[7]),
75 _13(data[8]), _23(data[9]), _33(data[10]), _43(data[11]),
76 _14(data[12]), _24(data[13]), _34(data[14]), _44(data[15])
77 {
78 }
79
80 CMatrix3D(const float data[]) :
81 _11(data[0]), _21(data[1]), _31(data[2]), _41(data[3]),
82 _12(data[4]), _22(data[5]), _32(data[6]), _42(data[7]),
83 _13(data[8]), _23(data[9]), _33(data[10]), _43(data[11]),
84 _14(data[12]), _24(data[13]), _34(data[14]), _44(data[15])
85 {
86 }
87
88 // accessors to individual elements of matrix
89 // NOTE: in this function definition, 'col' and 'row' represent the column and row into the
90 // internal element matrix which is the transposed of the mathematical notation, so the first
91 // and second arguments here are actually the row and column into the mathematical notation.
92 float& operator()(int col, int row)
93 {
94 return _data[row*4+col];
95 }
96 const float& operator()(int col, int row) const
97 {
98 return _data[row*4+col];
99 }
100
101 float& operator[](int idx)
102 {
103 return _data[idx];
104 }
105 const float& operator[](int idx) const
106 {
107 return _data[idx];
108 }
109
110 // matrix multiplication
111 CMatrix3D operator*(const CMatrix3D &matrix) const
112 {
113 return CMatrix3D(
114 _11*matrix._11 + _12*matrix._21 + _13*matrix._31 + _14*matrix._41,
115 _11*matrix._12 + _12*matrix._22 + _13*matrix._32 + _14*matrix._42,
116 _11*matrix._13 + _12*matrix._23 + _13*matrix._33 + _14*matrix._43,
117 _11*matrix._14 + _12*matrix._24 + _13*matrix._34 + _14*matrix._44,
118
119 _21*matrix._11 + _22*matrix._21 + _23*matrix._31 + _24*matrix._41,
120 _21*matrix._12 + _22*matrix._22 + _23*matrix._32 + _24*matrix._42,
121 _21*matrix._13 + _22*matrix._23 + _23*matrix._33 + _24*matrix._43,
122 _21*matrix._14 + _22*matrix._24 + _23*matrix._34 + _24*matrix._44,
123
124 _31*matrix._11 + _32*matrix._21 + _33*matrix._31 + _34*matrix._41,
125 _31*matrix._12 + _32*matrix._22 + _33*matrix._32 + _34*matrix._42,
126 _31*matrix._13 + _32*matrix._23 + _33*matrix._33 + _34*matrix._43,
127 _31*matrix._14 + _32*matrix._24 + _33*matrix._34 + _34*matrix._44,
128
129 _41*matrix._11 + _42*matrix._21 + _43*matrix._31 + _44*matrix._41,
130 _41*matrix._12 + _42*matrix._22 + _43*matrix._32 + _44*matrix._42,
131 _41*matrix._13 + _42*matrix._23 + _43*matrix._33 + _44*matrix._43,
132 _41*matrix._14 + _42*matrix._24 + _43*matrix._34 + _44*matrix._44
133 );
134 }
135
136 // matrix multiplication/assignment
138 {
139 *this = *this * matrix;
140 return *this;
141 }
142
143 // matrix scaling
144 CMatrix3D operator*(float f) const
145 {
146 return CMatrix3D(
147 _11*f, _12*f, _13*f, _14*f,
148 _21*f, _22*f, _23*f, _24*f,
149 _31*f, _32*f, _33*f, _34*f,
150 _41*f, _42*f, _43*f, _44*f
151 );
152 }
153
154 // matrix addition
156 {
157 return CMatrix3D(
158 _11+m._11, _12+m._12, _13+m._13, _14+m._14,
159 _21+m._21, _22+m._22, _23+m._23, _24+m._24,
160 _31+m._31, _32+m._32, _33+m._33, _34+m._34,
161 _41+m._41, _42+m._42, _43+m._43, _44+m._44
162 );
163 }
164
165 // matrix addition/assignment
167 {
168 _11 += m._11; _21 += m._21; _31 += m._31; _41 += m._41;
169 _12 += m._12; _22 += m._22; _32 += m._32; _42 += m._42;
170 _13 += m._13; _23 += m._23; _33 += m._33; _43 += m._43;
171 _14 += m._14; _24 += m._24; _34 += m._34; _44 += m._44;
172 return *this;
173 }
174
175 // equality
176 bool operator==(const CMatrix3D &m) const
177 {
178 return _11 == m._11 && _21 == m._21 && _31 == m._31 && _41 == m._41 &&
179 _12 == m._12 && _22 == m._22 && _32 == m._32 && _42 == m._42 &&
180 _13 == m._13 && _23 == m._23 && _33 == m._33 && _43 == m._43 &&
181 _14 == m._14 && _24 == m._24 && _34 == m._34 && _44 == m._44;
182 }
183
184 // inequality
185 bool operator!=(const CMatrix3D& m) const
186 {
187 return !(*this == m);
188 }
189
190 // set this matrix to the identity matrix
191 void SetIdentity();
192 // set this matrix to the zero matrix
193 void SetZero();
194 // set this matrix to the orthogonal projection matrix
195 void SetOrtho(float left, float right, float bottom, float top, float near, float far);
196 // set this matrix to the perspective projection matrix
197 void SetPerspective(float fov, float aspect, float near, float far);
198 void SetPerspectiveTile(float fov, float aspect, float near, float far, int tiles, int tile_x, int tile_y);
199
200 // concatenate arbitrary matrix onto this matrix
201 void Concatenate(const CMatrix3D& m)
202 {
203 (*this) = m * (*this);
204 }
205
206 // blend matrix using only 4x3 subset
207 void Blend(const CMatrix3D& m, float f)
208 {
209 _11 = m._11*f; _21 = m._21*f; _31 = m._31*f;
210 _12 = m._12*f; _22 = m._22*f; _32 = m._32*f;
211 _13 = m._13*f; _23 = m._23*f; _33 = m._33*f;
212 _14 = m._14*f; _24 = m._24*f; _34 = m._34*f;
213 }
214
215 // blend matrix using only 4x3 and add onto existing blend
216 void AddBlend(const CMatrix3D& m, float f)
217 {
218 _11 += m._11*f; _21 += m._21*f; _31 += m._31*f;
219 _12 += m._12*f; _22 += m._22*f; _32 += m._32*f;
220 _13 += m._13*f; _23 += m._23*f; _33 += m._33*f;
221 _14 += m._14*f; _24 += m._24*f; _34 += m._34*f;
222 }
223
224 // set this matrix to a rotation matrix for a rotation about X axis of given angle
225 void SetXRotation(float angle);
226 // set this matrix to a rotation matrix for a rotation about Y axis of given angle
227 void SetYRotation(float angle);
228 // set this matrix to a rotation matrix for a rotation about Z axis of given angle
229 void SetZRotation(float angle);
230 // set this matrix to a rotation described by given quaternion
231 void SetRotation(const CQuaternion& quat);
232
233 // concatenate a rotation about the X axis onto this matrix
234 void RotateX(float angle);
235 // concatenate a rotation about the Y axis onto this matrix
236 void RotateY(float angle);
237 // concatenate a rotation about the Z axis onto this matrix
238 void RotateZ(float angle);
239 // concatenate a rotation described by given quaternion
240 void Rotate(const CQuaternion& quat);
241
242 // sets this matrix to the given translation matrix (any existing transformation will be overwritten)
243 void SetTranslation(float x, float y, float z);
244 void SetTranslation(const CVector3D& vector);
245
246 // concatenate given translation onto this matrix. Assumes the current
247 // matrix is an affine transformation (i.e. the bottom row is [0,0,0,1])
248 // as an optimisation.
249 void Translate(float x, float y, float z);
250 void Translate(const CVector3D& vector);
251
252 // apply translation after this matrix (M = M * T)
253 void PostTranslate(float x, float y, float z);
254
255 // set this matrix to the given scaling matrix
256 void SetScaling(float x_scale, float y_scale, float z_scale);
257
258 // concatenate given scaling matrix onto this matrix
259 void Scale(float x_scale, float y_scale, float z_scale);
260
261 // calculate the inverse of this matrix, store in dst
262 void GetInverse(CMatrix3D& dst) const;
263
264 // return the inverse of this matrix
265 CMatrix3D GetInverse() const;
266
267 // calculate the transpose of this matrix, store in dst
268 CMatrix3D GetTranspose() const;
269
270 // return the translation component of this matrix
272 // return left vector, derived from rotation
273 CVector3D GetLeft() const;
274 // return up vector, derived from rotation
275 CVector3D GetUp() const;
276 // return forward vector, derived from rotation
277 CVector3D GetIn() const;
278 // return a quaternion representing the matrix's rotation
279 CQuaternion GetRotation() const;
280 // return the angle of rotation around the Y axis in range [-pi,pi]
281 // (based on projecting the X axis onto the XZ plane)
282 float GetYRotation() const;
283
284 // transform a 3D vector by this matrix
285 CVector3D Transform(const CVector3D &vector) const
286 {
287 CVector3D result;
288 Transform(vector, result);
289 return result;
290 }
291
292 void Transform(const CVector3D& vector, CVector3D& result) const
293 {
294 result.X = _11*vector.X + _12*vector.Y + _13*vector.Z + _14;
295 result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z + _24;
296 result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z + _34;
297 }
298
299 // transform a 4D vector by this matrix
300 CVector4D Transform(const CVector4D &vector) const
301 {
302 CVector4D result;
303 Transform(vector, result);
304 return result;
305 }
306
307 void Transform(const CVector4D& vector, CVector4D& result) const
308 {
309 result.X = _11*vector.X + _12*vector.Y + _13*vector.Z + _14*vector.W;
310 result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z + _24*vector.W;
311 result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z + _34*vector.W;
312 result.W = _41*vector.X + _42*vector.Y + _43*vector.Z + _44*vector.W;
313 }
314
315 // rotate a vector by this matrix
316 CVector3D Rotate(const CVector3D& vector) const
317 {
318 CVector3D result;
319 Rotate(vector, result);
320 return result;
321 }
322
323 void Rotate(const CVector3D& vector, CVector3D& result) const
324 {
325 result.X = _11*vector.X + _12*vector.Y + _13*vector.Z;
326 result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z;
327 result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z;
328 }
329
330 // rotate a vector by the transpose of this matrix
331 void RotateTransposed(const CVector3D& vector,CVector3D& result) const;
332 CVector3D RotateTransposed(const CVector3D& vector) const;
333
334 // Returns 16 element array of floats, e.g. for mat4 uniforms.
336 {
337 // Additional check to prevent a weird compiler has a different
338 // alignement for an array and a class members.
339 static_assert(
340 sizeof(CMatrix3D) == sizeof(float) * 16u &&
341 offsetof(CMatrix3D, _data) == 0 &&
342 offsetof(CMatrix3D, _11) == 0 &&
343 offsetof(CMatrix3D, _44) == sizeof(float) * 15u,
344 "CMatrix3D should be properly layouted to use AsFloatArray");
345 return PS::span<const float>(_data, 16);
346 }
347};
348
349#endif // INCLUDED_MATRIX3D
Definition: Matrix3D.h:34
void RotateY(float angle)
Definition: Matrix3D.cpp:143
CVector3D GetIn() const
Definition: Matrix3D.cpp:279
float _43
Definition: Matrix3D.h:46
PS::span< const float > AsFloatArray() const
Definition: Matrix3D.h:335
CMatrix3D & operator+=(const CMatrix3D &m)
Definition: Matrix3D.h:166
void Transform(const CVector4D &vector, CVector4D &result) const
Definition: Matrix3D.h:307
float _34
Definition: Matrix3D.h:47
float _21
Definition: Matrix3D.h:44
void Concatenate(const CMatrix3D &m)
Definition: Matrix3D.h:201
void Scale(float x_scale, float y_scale, float z_scale)
Definition: Matrix3D.cpp:236
float _31
Definition: Matrix3D.h:44
CMatrix3D()
Definition: Matrix3D.h:56
float _11
Definition: Matrix3D.h:44
float _24
Definition: Matrix3D.h:47
float _42
Definition: Matrix3D.h:45
void RotateTransposed(const CVector3D &vector, CVector3D &result) const
Definition: Matrix3D.cpp:295
void SetTranslation(float x, float y, float z)
Definition: Matrix3D.cpp:184
void Blend(const CMatrix3D &m, float f)
Definition: Matrix3D.h:207
CQuaternion GetRotation() const
Definition: Matrix3D.cpp:386
CMatrix3D & operator*=(const CMatrix3D &matrix)
Definition: Matrix3D.h:137
const float & operator[](int idx) const
Definition: Matrix3D.h:105
CMatrix3D GetTranspose() const
Definition: Matrix3D.cpp:256
CMatrix3D(float a11, float a12, float a13, float a14, float a21, float a22, float a23, float a24, float a31, float a32, float a33, float a34, float a41, float a42, float a43, float a44)
Definition: Matrix3D.h:60
float _13
Definition: Matrix3D.h:46
CMatrix3D operator+(const CMatrix3D &m) const
Definition: Matrix3D.h:155
void PostTranslate(float x, float y, float z)
Definition: Matrix3D.cpp:212
void AddBlend(const CMatrix3D &m, float f)
Definition: Matrix3D.h:216
void SetRotation(const CQuaternion &quat)
Definition: Matrix3D.cpp:424
float & operator[](int idx)
Definition: Matrix3D.h:101
float _33
Definition: Matrix3D.h:46
void SetYRotation(float angle)
Definition: Matrix3D.cpp:98
CMatrix3D operator*(float f) const
Definition: Matrix3D.h:144
float _32
Definition: Matrix3D.h:45
void SetXRotation(float angle)
Definition: Matrix3D.cpp:87
CVector3D Rotate(const CVector3D &vector) const
Definition: Matrix3D.h:316
float _14
Definition: Matrix3D.h:47
float _data2d[4][4]
Definition: Matrix3D.h:50
void Rotate(const CQuaternion &quat)
Definition: Matrix3D.cpp:380
void SetScaling(float x_scale, float y_scale, float z_scale)
Definition: Matrix3D.cpp:227
float _data[16]
Definition: Matrix3D.h:49
CMatrix3D(const float data[])
Definition: Matrix3D.h:80
float GetYRotation() const
Definition: Matrix3D.cpp:429
void SetZero()
Definition: Matrix3D.cpp:39
CMatrix3D operator*(const CMatrix3D &matrix) const
Definition: Matrix3D.h:111
void SetPerspective(float fov, float aspect, float near, float far)
Definition: Matrix3D.cpp:61
void Rotate(const CVector3D &vector, CVector3D &result) const
Definition: Matrix3D.h:323
const float & operator()(int col, int row) const
Definition: Matrix3D.h:96
float & operator()(int col, int row)
Definition: Matrix3D.h:92
CVector3D GetUp() const
Definition: Matrix3D.cpp:273
CVector3D GetTranslation() const
Definition: Matrix3D.cpp:221
void SetPerspectiveTile(float fov, float aspect, float near, float far, int tiles, int tile_x, int tile_y)
Definition: Matrix3D.cpp:73
void RotateZ(float angle)
Definition: Matrix3D.cpp:163
float _23
Definition: Matrix3D.h:46
bool operator==(const CMatrix3D &m) const
Definition: Matrix3D.h:176
void Translate(float x, float y, float z)
Definition: Matrix3D.cpp:198
CVector3D GetLeft() const
Definition: Matrix3D.cpp:267
void SetIdentity()
Definition: Matrix3D.cpp:30
float _12
Definition: Matrix3D.h:45
void RotateX(float angle)
Definition: Matrix3D.cpp:123
void Transform(const CVector3D &vector, CVector3D &result) const
Definition: Matrix3D.h:292
float _41
Definition: Matrix3D.h:44
float _44
Definition: Matrix3D.h:47
void SetZRotation(float angle)
Definition: Matrix3D.cpp:109
CVector4D Transform(const CVector4D &vector) const
Definition: Matrix3D.h:300
CMatrix3D(float data[])
Definition: Matrix3D.h:72
void SetOrtho(float left, float right, float bottom, float top, float near, float far)
Definition: Matrix3D.cpp:47
CMatrix3D GetInverse() const
Definition: Matrix3D.cpp:373
float _22
Definition: Matrix3D.h:45
bool operator!=(const CMatrix3D &m) const
Definition: Matrix3D.h:185
CVector3D Transform(const CVector3D &vector) const
Definition: Matrix3D.h:285
Definition: Quaternion.h:26
Definition: Vector3D.h:31
float Z
Definition: Vector3D.h:33
float Y
Definition: Vector3D.h:33
float X
Definition: Vector3D.h:33
Definition: Vector4D.h:31
float Z
Definition: Vector4D.h:142
float X
Definition: Vector4D.h:142
float W
Definition: Vector4D.h:142
float Y
Definition: Vector4D.h:142
Simplifed version of std::span (C++20) as we don't support the original one yet.
Definition: Span.h:37