Pyrogenesis  trunk
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 
30 class CQuaternion;
31 
32 // CMatrix3D: a 4x4 matrix class for common operations in 3D
33 class CMatrix3D
34 {
35 public:
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 
54 public:
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  // accessors to individual elements of matrix
81  // NOTE: in this function definition, 'col' and 'row' represent the column and row into the
82  // internal element matrix which is the transposed of the mathematical notation, so the first
83  // and second arguments here are actually the row and column into the mathematical notation.
84  float& operator()(int col, int row)
85  {
86  return _data[row*4+col];
87  }
88  const float& operator()(int col, int row) const
89  {
90  return _data[row*4+col];
91  }
92 
93  float& operator[](int idx)
94  {
95  return _data[idx];
96  }
97  const float& operator[](int idx) const
98  {
99  return _data[idx];
100  }
101 
102  // matrix multiplication
103  CMatrix3D operator*(const CMatrix3D &matrix) const
104  {
105  return CMatrix3D(
106  _11*matrix._11 + _12*matrix._21 + _13*matrix._31 + _14*matrix._41,
107  _11*matrix._12 + _12*matrix._22 + _13*matrix._32 + _14*matrix._42,
108  _11*matrix._13 + _12*matrix._23 + _13*matrix._33 + _14*matrix._43,
109  _11*matrix._14 + _12*matrix._24 + _13*matrix._34 + _14*matrix._44,
110 
111  _21*matrix._11 + _22*matrix._21 + _23*matrix._31 + _24*matrix._41,
112  _21*matrix._12 + _22*matrix._22 + _23*matrix._32 + _24*matrix._42,
113  _21*matrix._13 + _22*matrix._23 + _23*matrix._33 + _24*matrix._43,
114  _21*matrix._14 + _22*matrix._24 + _23*matrix._34 + _24*matrix._44,
115 
116  _31*matrix._11 + _32*matrix._21 + _33*matrix._31 + _34*matrix._41,
117  _31*matrix._12 + _32*matrix._22 + _33*matrix._32 + _34*matrix._42,
118  _31*matrix._13 + _32*matrix._23 + _33*matrix._33 + _34*matrix._43,
119  _31*matrix._14 + _32*matrix._24 + _33*matrix._34 + _34*matrix._44,
120 
121  _41*matrix._11 + _42*matrix._21 + _43*matrix._31 + _44*matrix._41,
122  _41*matrix._12 + _42*matrix._22 + _43*matrix._32 + _44*matrix._42,
123  _41*matrix._13 + _42*matrix._23 + _43*matrix._33 + _44*matrix._43,
124  _41*matrix._14 + _42*matrix._24 + _43*matrix._34 + _44*matrix._44
125  );
126  }
127 
128  // matrix multiplication/assignment
130  {
131  Concatenate(matrix);
132  return *this;
133  }
134 
135  // matrix scaling
136  CMatrix3D operator*(float f) const
137  {
138  return CMatrix3D(
139  _11*f, _12*f, _13*f, _14*f,
140  _21*f, _22*f, _23*f, _24*f,
141  _31*f, _32*f, _33*f, _34*f,
142  _41*f, _42*f, _43*f, _44*f
143  );
144  }
145 
146  // matrix addition
147  CMatrix3D operator+(const CMatrix3D &m) const
148  {
149  return CMatrix3D(
150  _11+m._11, _12+m._12, _13+m._13, _14+m._14,
151  _21+m._21, _22+m._22, _23+m._23, _24+m._24,
152  _31+m._31, _32+m._32, _33+m._33, _34+m._34,
153  _41+m._41, _42+m._42, _43+m._43, _44+m._44
154  );
155  }
156 
157  // matrix addition/assignment
159  {
160  _11 += m._11; _21 += m._21; _31 += m._31; _41 += m._41;
161  _12 += m._12; _22 += m._22; _32 += m._32; _42 += m._42;
162  _13 += m._13; _23 += m._23; _33 += m._33; _43 += m._43;
163  _14 += m._14; _24 += m._24; _34 += m._34; _44 += m._44;
164  return *this;
165  }
166 
167  // equality
168  bool operator==(const CMatrix3D &m) const
169  {
170  return _11 == m._11 && _21 == m._21 && _31 == m._31 && _41 == m._41 &&
171  _12 == m._12 && _22 == m._22 && _32 == m._32 && _42 == m._42 &&
172  _13 == m._13 && _23 == m._23 && _33 == m._33 && _43 == m._43 &&
173  _14 == m._14 && _24 == m._24 && _34 == m._34 && _44 == m._44;
174  }
175 
176  // inequality
177  bool operator!=(const CMatrix3D& m) const
178  {
179  return !(*this == m);
180  }
181 
182  // set this matrix to the identity matrix
183  void SetIdentity();
184  // set this matrix to the zero matrix
185  void SetZero();
186  // set this matrix to the orthogonal projection matrix
187  void SetOrtho(float left, float right, float bottom, float top, float near, float far);
188  // set this matrix to the perspective projection matrix
189  void SetPerspective(float fov, float aspect, float near, float far);
190  void SetPerspectiveTile(float fov, float aspect, float near, float far, int tiles, int tile_x, int tile_y);
191 
192  // concatenate arbitrary matrix onto this matrix
193  void Concatenate(const CMatrix3D& m)
194  {
195  (*this) = m * (*this);
196  }
197 
198  // blend matrix using only 4x3 subset
199  void Blend(const CMatrix3D& m, float f)
200  {
201  _11 = m._11*f; _21 = m._21*f; _31 = m._31*f;
202  _12 = m._12*f; _22 = m._22*f; _32 = m._32*f;
203  _13 = m._13*f; _23 = m._23*f; _33 = m._33*f;
204  _14 = m._14*f; _24 = m._24*f; _34 = m._34*f;
205  }
206 
207  // blend matrix using only 4x3 and add onto existing blend
208  void AddBlend(const CMatrix3D& m, float f)
209  {
210  _11 += m._11*f; _21 += m._21*f; _31 += m._31*f;
211  _12 += m._12*f; _22 += m._22*f; _32 += m._32*f;
212  _13 += m._13*f; _23 += m._23*f; _33 += m._33*f;
213  _14 += m._14*f; _24 += m._24*f; _34 += m._34*f;
214  }
215 
216  // set this matrix to a rotation matrix for a rotation about X axis of given angle
217  void SetXRotation(float angle);
218  // set this matrix to a rotation matrix for a rotation about Y axis of given angle
219  void SetYRotation(float angle);
220  // set this matrix to a rotation matrix for a rotation about Z axis of given angle
221  void SetZRotation(float angle);
222  // set this matrix to a rotation described by given quaternion
223  void SetRotation(const CQuaternion& quat);
224 
225  // concatenate a rotation about the X axis onto this matrix
226  void RotateX(float angle);
227  // concatenate a rotation about the Y axis onto this matrix
228  void RotateY(float angle);
229  // concatenate a rotation about the Z axis onto this matrix
230  void RotateZ(float angle);
231  // concatenate a rotation described by given quaternion
232  void Rotate(const CQuaternion& quat);
233 
234  // sets this matrix to the given translation matrix (any existing transformation will be overwritten)
235  void SetTranslation(float x, float y, float z);
236  void SetTranslation(const CVector3D& vector);
237 
238  // concatenate given translation onto this matrix. Assumes the current
239  // matrix is an affine transformation (i.e. the bottom row is [0,0,0,1])
240  // as an optimisation.
241  void Translate(float x, float y, float z);
242  void Translate(const CVector3D& vector);
243 
244  // apply translation after this matrix (M = M * T)
245  void PostTranslate(float x, float y, float z);
246 
247  // set this matrix to the given scaling matrix
248  void SetScaling(float x_scale, float y_scale, float z_scale);
249 
250  // concatenate given scaling matrix onto this matrix
251  void Scale(float x_scale, float y_scale, float z_scale);
252 
253  // calculate the inverse of this matrix, store in dst
254  void GetInverse(CMatrix3D& dst) const;
255 
256  // return the inverse of this matrix
257  CMatrix3D GetInverse() const;
258 
259  // calculate the transpose of this matrix, store in dst
260  CMatrix3D GetTranspose() const;
261 
262  // return the translation component of this matrix
263  CVector3D GetTranslation() const;
264  // return left vector, derived from rotation
265  CVector3D GetLeft() const;
266  // return up vector, derived from rotation
267  CVector3D GetUp() const;
268  // return forward vector, derived from rotation
269  CVector3D GetIn() const;
270  // return a quaternion representing the matrix's rotation
271  CQuaternion GetRotation() const;
272  // return the angle of rotation around the Y axis in range [-pi,pi]
273  // (based on projecting the X axis onto the XZ plane)
274  float GetYRotation() const;
275 
276  // transform a 3D vector by this matrix
277  CVector3D Transform(const CVector3D &vector) const
278  {
279  CVector3D result;
280  Transform(vector, result);
281  return result;
282  }
283 
284  void Transform(const CVector3D& vector, CVector3D& result) const
285  {
286  result.X = _11*vector.X + _12*vector.Y + _13*vector.Z + _14;
287  result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z + _24;
288  result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z + _34;
289  }
290 
291  // transform a 4D vector by this matrix
292  CVector4D Transform(const CVector4D &vector) const
293  {
294  CVector4D result;
295  Transform(vector, result);
296  return result;
297  }
298 
299  void Transform(const CVector4D& vector, CVector4D& result) const
300  {
301  result.X = _11*vector.X + _12*vector.Y + _13*vector.Z + _14*vector.W;
302  result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z + _24*vector.W;
303  result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z + _34*vector.W;
304  result.W = _41*vector.X + _42*vector.Y + _43*vector.Z + _44*vector.W;
305  }
306 
307  // rotate a vector by this matrix
308  CVector3D Rotate(const CVector3D& vector) const
309  {
310  CVector3D result;
311  Rotate(vector, result);
312  return result;
313  }
314 
315  void Rotate(const CVector3D& vector, CVector3D& result) const
316  {
317  result.X = _11*vector.X + _12*vector.Y + _13*vector.Z;
318  result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z;
319  result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z;
320  }
321 
322  // rotate a vector by the transpose of this matrix
323  void RotateTransposed(const CVector3D& vector,CVector3D& result) const;
324  CVector3D RotateTransposed(const CVector3D& vector) const;
325 
326  // Returns 16 element array of floats, e.g. for mat4 uniforms.
328  {
329  // Additional check to prevent a weird compiler has a different
330  // alignement for an array and a class members.
331  static_assert(
332  sizeof(CMatrix3D) == sizeof(float) * 16u &&
333  offsetof(CMatrix3D, _data) == 0 &&
334  offsetof(CMatrix3D, _11) == 0 &&
335  offsetof(CMatrix3D, _44) == sizeof(float) * 15u,
336  "CMatrix3D should be properly layouted to use AsFloatArray");
337  return PS::span<const float>(_data, 16);
338  }
339 };
340 
341 #endif // INCLUDED_MATRIX3D
CVector3D GetIn() const
Definition: Matrix3D.cpp:279
CMatrix3D GetInverse() const
Definition: Matrix3D.cpp:373
void Translate(float x, float y, float z)
Definition: Matrix3D.cpp:198
float _21
Definition: Matrix3D.h:44
void SetZRotation(float angle)
Definition: Matrix3D.cpp:109
void SetPerspectiveTile(float fov, float aspect, float near, float far, int tiles, int tile_x, int tile_y)
Definition: Matrix3D.cpp:73
CMatrix3D operator*(float f) const
Definition: Matrix3D.h:136
void RotateTransposed(const CVector3D &vector, CVector3D &result) const
Definition: Matrix3D.cpp:295
void SetTranslation(float x, float y, float z)
Definition: Matrix3D.cpp:184
CMatrix3D & operator+=(const CMatrix3D &m)
Definition: Matrix3D.h:158
void SetPerspective(float fov, float aspect, float near, float far)
Definition: Matrix3D.cpp:61
float _22
Definition: Matrix3D.h:45
float _12
Definition: Matrix3D.h:45
CVector3D GetLeft() const
Definition: Matrix3D.cpp:267
CMatrix3D()
Definition: Matrix3D.h:56
bool operator!=(const CMatrix3D &m) const
Definition: Matrix3D.h:177
float _44
Definition: Matrix3D.h:47
CMatrix3D operator*(const CMatrix3D &matrix) const
Definition: Matrix3D.h:103
void SetYRotation(float angle)
Definition: Matrix3D.cpp:98
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
CVector3D GetTranslation() const
Definition: Matrix3D.cpp:221
void SetZero()
Definition: Matrix3D.cpp:39
float _43
Definition: Matrix3D.h:46
CVector3D Rotate(const CVector3D &vector) const
Definition: Matrix3D.h:308
Definition: Vector3D.h:30
float _32
Definition: Matrix3D.h:45
float _11
Definition: Matrix3D.h:44
void Rotate(const CQuaternion &quat)
Definition: Matrix3D.cpp:380
float & operator[](int idx)
Definition: Matrix3D.h:93
CMatrix3D operator+(const CMatrix3D &m) const
Definition: Matrix3D.h:147
float Y
Definition: Vector4D.h:142
CMatrix3D & operator*=(const CMatrix3D &matrix)
Definition: Matrix3D.h:129
Definition: Vector4D.h:30
void PostTranslate(float x, float y, float z)
Definition: Matrix3D.cpp:212
float _33
Definition: Matrix3D.h:46
Definition: Matrix3D.h:33
void SetRotation(const CQuaternion &quat)
Definition: Matrix3D.cpp:424
void RotateY(float angle)
Definition: Matrix3D.cpp:143
float Z
Definition: Vector4D.h:142
void Rotate(const CVector3D &vector, CVector3D &result) const
Definition: Matrix3D.h:315
float X
Definition: Vector3D.h:33
float Y
Definition: Vector3D.h:33
float _13
Definition: Matrix3D.h:46
float _data2d[4][4]
Definition: Matrix3D.h:50
float _31
Definition: Matrix3D.h:44
CQuaternion GetRotation() const
Definition: Matrix3D.cpp:386
void Scale(float x_scale, float y_scale, float z_scale)
Definition: Matrix3D.cpp:236
float & operator()(int col, int row)
Definition: Matrix3D.h:84
void SetIdentity()
Definition: Matrix3D.cpp:30
void Transform(const CVector4D &vector, CVector4D &result) const
Definition: Matrix3D.h:299
float _42
Definition: Matrix3D.h:45
float _24
Definition: Matrix3D.h:47
PS::span< const float > AsFloatArray() const
Definition: Matrix3D.h:327
CMatrix3D(float data[])
Definition: Matrix3D.h:72
CVector3D GetUp() const
Definition: Matrix3D.cpp:273
CMatrix3D GetTranspose() const
Definition: Matrix3D.cpp:256
float _34
Definition: Matrix3D.h:47
void Concatenate(const CMatrix3D &m)
Definition: Matrix3D.h:193
bool operator==(const CMatrix3D &m) const
Definition: Matrix3D.h:168
float W
Definition: Vector4D.h:142
void Transform(const CVector3D &vector, CVector3D &result) const
Definition: Matrix3D.h:284
float GetYRotation() const
Definition: Matrix3D.cpp:429
Definition: Quaternion.h:25
float _23
Definition: Matrix3D.h:46
void SetScaling(float x_scale, float y_scale, float z_scale)
Definition: Matrix3D.cpp:227
float _data[16]
Definition: Matrix3D.h:49
void SetXRotation(float angle)
Definition: Matrix3D.cpp:87
const float & operator()(int col, int row) const
Definition: Matrix3D.h:88
float Z
Definition: Vector3D.h:33
const float & operator[](int idx) const
Definition: Matrix3D.h:97
void SetOrtho(float left, float right, float bottom, float top, float near, float far)
Definition: Matrix3D.cpp:47
void Blend(const CMatrix3D &m, float f)
Definition: Matrix3D.h:199
void RotateZ(float angle)
Definition: Matrix3D.cpp:163
float _41
Definition: Matrix3D.h:44
CVector4D Transform(const CVector4D &vector) const
Definition: Matrix3D.h:292
void AddBlend(const CMatrix3D &m, float f)
Definition: Matrix3D.h:208
void RotateX(float angle)
Definition: Matrix3D.cpp:123
CVector3D Transform(const CVector3D &vector) const
Definition: Matrix3D.h:277
Simplifed version of std::span (C++20) as we don&#39;t support the original one yet.
Definition: Span.h:36
float X
Definition: Vector4D.h:142
float _14
Definition: Matrix3D.h:47