Fixes vertex attribute format mismatch for silhouette debug rendering.
[0ad.git] / source / maths / Matrix3D.h
blob16df365e52627a090fe9df7bf1cc2e2e5a72bcdf
1 /* Copyright (C) 2022 Wildfire Games.
2 * This file is part of 0 A.D.
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.
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.
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/>.
19 * A Matrix class used for holding and manipulating transformation
20 * info.
23 #ifndef INCLUDED_MATRIX3D
24 #define INCLUDED_MATRIX3D
26 #include "maths/Vector3D.h"
27 #include "maths/Vector4D.h"
28 #include "ps/containers/Span.h"
30 class CQuaternion;
32 // CMatrix3D: a 4x4 matrix class for common operations in 3D
33 class CMatrix3D
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
42 struct
44 float _11, _21, _31, _41;
45 float _12, _22, _32, _42;
46 float _13, _23, _33, _43;
47 float _14, _24, _34, _44;
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.)
54 public:
55 // constructors
56 CMatrix3D ()
60 CMatrix3D(
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)
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])
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)
86 return _data[row*4+col];
88 const float& operator()(int col, int row) const
90 return _data[row*4+col];
93 float& operator[](int idx)
95 return _data[idx];
97 const float& operator[](int idx) const
99 return _data[idx];
102 // matrix multiplication
103 CMatrix3D operator*(const CMatrix3D &matrix) const
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,
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,
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,
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
128 // matrix multiplication/assignment
129 CMatrix3D& operator*=(const CMatrix3D &matrix)
131 Concatenate(matrix);
132 return *this;
135 // matrix scaling
136 CMatrix3D operator*(float f) const
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
146 // matrix addition
147 CMatrix3D operator+(const CMatrix3D &m) const
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
157 // matrix addition/assignment
158 CMatrix3D& operator+=(const CMatrix3D &m)
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;
167 // equality
168 bool operator==(const CMatrix3D &m) const
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;
176 // inequality
177 bool operator!=(const CMatrix3D& m) const
179 return !(*this == m);
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);
192 // concatenate arbitrary matrix onto this matrix
193 void Concatenate(const CMatrix3D& m)
195 (*this) = m * (*this);
198 // blend matrix using only 4x3 subset
199 void Blend(const CMatrix3D& m, float f)
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;
207 // blend matrix using only 4x3 and add onto existing blend
208 void AddBlend(const CMatrix3D& m, float f)
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;
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);
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);
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);
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);
244 // apply translation after this matrix (M = M * T)
245 void PostTranslate(float x, float y, float z);
247 // set this matrix to the given scaling matrix
248 void SetScaling(float x_scale, float y_scale, float z_scale);
250 // concatenate given scaling matrix onto this matrix
251 void Scale(float x_scale, float y_scale, float z_scale);
253 // calculate the inverse of this matrix, store in dst
254 void GetInverse(CMatrix3D& dst) const;
256 // return the inverse of this matrix
257 CMatrix3D GetInverse() const;
259 // calculate the transpose of this matrix, store in dst
260 CMatrix3D GetTranspose() const;
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;
276 // transform a 3D vector by this matrix
277 CVector3D Transform(const CVector3D &vector) const
279 CVector3D result;
280 Transform(vector, result);
281 return result;
284 void Transform(const CVector3D& vector, CVector3D& result) const
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;
291 // transform a 4D vector by this matrix
292 CVector4D Transform(const CVector4D &vector) const
294 CVector4D result;
295 Transform(vector, result);
296 return result;
299 void Transform(const CVector4D& vector, CVector4D& result) const
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;
307 // rotate a vector by this matrix
308 CVector3D Rotate(const CVector3D& vector) const
310 CVector3D result;
311 Rotate(vector, result);
312 return result;
315 void Rotate(const CVector3D& vector, CVector3D& result) const
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;
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;
326 // Returns 16 element array of floats, e.g. for mat4 uniforms.
327 PS::span<const float> AsFloatArray() const
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);
341 #endif // INCLUDED_MATRIX3D