Pyrogenesis  trunk
Matrix3D.h
Go to the documentation of this file.
1 /* Copyright (C) 2010 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 
29 class CQuaternion;
30 
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  struct {
42  float _11, _21, _31, _41;
43  float _12, _22, _32, _42;
44  float _13, _23, _33, _43;
45  float _14, _24, _34, _44;
46  };
47  float _data[16];
48  float _data2d[4][4];
49  // (Be aware that m(0,2) == _data2d[2][0] == _13, etc. This is to be considered a feature.)
50  };
51 
52 public:
53  // constructors
55  {
56  }
57 
59  float a11, float a12, float a13, float a14,
60  float a21, float a22, float a23, float a24,
61  float a31, float a32, float a33, float a34,
62  float a41, float a42, float a43, float a44) :
63  _11(a11), _12(a12), _13(a13), _14(a14),
64  _21(a21), _22(a22), _23(a23), _24(a24),
65  _31(a31), _32(a32), _33(a33), _34(a34),
66  _41(a41), _42(a42), _43(a43), _44(a44)
67  {
68  }
69 
70  CMatrix3D(float data[]) :
71  _11(data[0]), _21(data[1]), _31(data[2]), _41(data[3]),
72  _12(data[4]), _22(data[5]), _32(data[6]), _42(data[7]),
73  _13(data[8]), _23(data[9]), _33(data[10]), _43(data[11]),
74  _14(data[12]), _24(data[13]), _34(data[14]), _44(data[15])
75  {
76  }
77 
78  // accessors to individual elements of matrix
79  // NOTE: in this function definition, 'col' and 'row' represent the column and row into the
80  // internal element matrix which is the transposed of the mathematical notation, so the first
81  // and second arguments here are actually the row and column into the mathematical notation.
82  float& operator()(int col, int row)
83  {
84  return _data[row*4+col];
85  }
86  const float& operator()(int col, int row) const
87  {
88  return _data[row*4+col];
89  }
90 
91  float& operator[](int idx)
92  {
93  return _data[idx];
94  }
95  const float& operator[](int idx) const
96  {
97  return _data[idx];
98  }
99 
100  // matrix multiplication
101  CMatrix3D operator*(const CMatrix3D &matrix) const
102  {
103  return CMatrix3D(
104  _11*matrix._11 + _12*matrix._21 + _13*matrix._31 + _14*matrix._41,
105  _11*matrix._12 + _12*matrix._22 + _13*matrix._32 + _14*matrix._42,
106  _11*matrix._13 + _12*matrix._23 + _13*matrix._33 + _14*matrix._43,
107  _11*matrix._14 + _12*matrix._24 + _13*matrix._34 + _14*matrix._44,
108 
109  _21*matrix._11 + _22*matrix._21 + _23*matrix._31 + _24*matrix._41,
110  _21*matrix._12 + _22*matrix._22 + _23*matrix._32 + _24*matrix._42,
111  _21*matrix._13 + _22*matrix._23 + _23*matrix._33 + _24*matrix._43,
112  _21*matrix._14 + _22*matrix._24 + _23*matrix._34 + _24*matrix._44,
113 
114  _31*matrix._11 + _32*matrix._21 + _33*matrix._31 + _34*matrix._41,
115  _31*matrix._12 + _32*matrix._22 + _33*matrix._32 + _34*matrix._42,
116  _31*matrix._13 + _32*matrix._23 + _33*matrix._33 + _34*matrix._43,
117  _31*matrix._14 + _32*matrix._24 + _33*matrix._34 + _34*matrix._44,
118 
119  _41*matrix._11 + _42*matrix._21 + _43*matrix._31 + _44*matrix._41,
120  _41*matrix._12 + _42*matrix._22 + _43*matrix._32 + _44*matrix._42,
121  _41*matrix._13 + _42*matrix._23 + _43*matrix._33 + _44*matrix._43,
122  _41*matrix._14 + _42*matrix._24 + _43*matrix._34 + _44*matrix._44
123  );
124  }
125 
126  // matrix multiplication/assignment
128  {
129  Concatenate(matrix);
130  return *this;
131  }
132 
133  // matrix scaling
134  CMatrix3D operator*(float f) const
135  {
136  return CMatrix3D(
137  _11*f, _12*f, _13*f, _14*f,
138  _21*f, _22*f, _23*f, _24*f,
139  _31*f, _32*f, _33*f, _34*f,
140  _41*f, _42*f, _43*f, _44*f
141  );
142  }
143 
144  // matrix addition
145  CMatrix3D operator+(const CMatrix3D &m) const
146  {
147  return CMatrix3D(
148  _11+m._11, _12+m._12, _13+m._13, _14+m._14,
149  _21+m._21, _22+m._22, _23+m._23, _24+m._24,
150  _31+m._31, _32+m._32, _33+m._33, _34+m._34,
151  _41+m._41, _42+m._42, _43+m._43, _44+m._44
152  );
153  }
154 
155  // matrix addition/assignment
157  {
158  _11 += m._11; _21 += m._21; _31 += m._31; _41 += m._41;
159  _12 += m._12; _22 += m._22; _32 += m._32; _42 += m._42;
160  _13 += m._13; _23 += m._23; _33 += m._33; _43 += m._43;
161  _14 += m._14; _24 += m._24; _34 += m._34; _44 += m._44;
162  return *this;
163  }
164 
165  // equality
166  bool operator==(const CMatrix3D &m) const
167  {
168  return _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  }
173 
174  // inequality
175  bool operator!=(const CMatrix3D& m) const
176  {
177  return !(*this == m);
178  }
179 
180  // set this matrix to the identity matrix
181  void SetIdentity();
182  // set this matrix to the zero matrix
183  void SetZero();
184  // set this matrix to the orthogonal projection matrix (as with glOrtho)
185  void SetOrtho(float l, float r, float b, float t, float n, float f);
186 
187  // concatenate arbitrary matrix onto this matrix
188  void Concatenate(const CMatrix3D& m)
189  {
190  (*this) = m * (*this);
191  }
192 
193  // blend matrix using only 4x3 subset
194  void Blend(const CMatrix3D& m, float f)
195  {
196  _11 = m._11*f; _21 = m._21*f; _31 = m._31*f;
197  _12 = m._12*f; _22 = m._22*f; _32 = m._32*f;
198  _13 = m._13*f; _23 = m._23*f; _33 = m._33*f;
199  _14 = m._14*f; _24 = m._24*f; _34 = m._34*f;
200  }
201 
202  // blend matrix using only 4x3 and add onto existing blend
203  void AddBlend(const CMatrix3D& m, float f)
204  {
205  _11 += m._11*f; _21 += m._21*f; _31 += m._31*f;
206  _12 += m._12*f; _22 += m._22*f; _32 += m._32*f;
207  _13 += m._13*f; _23 += m._23*f; _33 += m._33*f;
208  _14 += m._14*f; _24 += m._24*f; _34 += m._34*f;
209  }
210 
211  // set this matrix to a rotation matrix for a rotation about X axis of given angle
212  void SetXRotation(float angle);
213  // set this matrix to a rotation matrix for a rotation about Y axis of given angle
214  void SetYRotation(float angle);
215  // set this matrix to a rotation matrix for a rotation about Z axis of given angle
216  void SetZRotation(float angle);
217  // set this matrix to a rotation described by given quaternion
218  void SetRotation(const CQuaternion& quat);
219 
220  // concatenate a rotation about the X axis onto this matrix
221  void RotateX(float angle);
222  // concatenate a rotation about the Y axis onto this matrix
223  void RotateY(float angle);
224  // concatenate a rotation about the Z axis onto this matrix
225  void RotateZ(float angle);
226  // concatenate a rotation described by given quaternion
227  void Rotate(const CQuaternion& quat);
228 
229  // sets this matrix to the given translation matrix (any existing transformation will be overwritten)
230  void SetTranslation(float x, float y, float z);
231  void SetTranslation(const CVector3D& vector);
232 
233  // concatenate given translation onto this matrix. Assumes the current
234  // matrix is an affine transformation (i.e. the bottom row is [0,0,0,1])
235  // as an optimisation.
236  void Translate(float x, float y, float z);
237  void Translate(const CVector3D& vector);
238 
239  // apply translation after this matrix (M = M * T)
240  void PostTranslate(float x, float y, float z);
241 
242  // set this matrix to the given scaling matrix
243  void SetScaling(float x_scale, float y_scale, float z_scale);
244 
245  // concatenate given scaling matrix onto this matrix
246  void Scale(float x_scale, float y_scale, float z_scale);
247 
248  // calculate the inverse of this matrix, store in dst
249  void GetInverse(CMatrix3D& dst) const;
250 
251  // return the inverse of this matrix
252  CMatrix3D GetInverse() const;
253 
254  // calculate the transpose of this matrix, store in dst
255  CMatrix3D GetTranspose() const;
256 
257  // return the translation component of this matrix
258  CVector3D GetTranslation() const;
259  // return left vector, derived from rotation
260  CVector3D GetLeft() const;
261  // return up vector, derived from rotation
262  CVector3D GetUp() const;
263  // return forward vector, derived from rotation
264  CVector3D GetIn() const;
265  // return a quaternion representing the matrix's rotation
266  CQuaternion GetRotation() const;
267  // return the angle of rotation around the Y axis in range [-pi,pi]
268  // (based on projecting the X axis onto the XZ plane)
269  float GetYRotation() const;
270 
271  // transform a 3D vector by this matrix
272  CVector3D Transform(const CVector3D &vector) const
273  {
274  CVector3D result;
275  Transform(vector, result);
276  return result;
277  }
278 
279  void Transform(const CVector3D& vector, CVector3D& result) const
280  {
281  result.X = _11*vector.X + _12*vector.Y + _13*vector.Z + _14;
282  result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z + _24;
283  result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z + _34;
284  }
285 
286  // transform a 4D vector by this matrix
287  CVector4D Transform(const CVector4D &vector) const
288  {
289  CVector4D result;
290  Transform(vector, result);
291  return result;
292  }
293 
294  void Transform(const CVector4D& vector, CVector4D& result) const
295  {
296  result.X = _11*vector.X + _12*vector.Y + _13*vector.Z + _14*vector.W;
297  result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z + _24*vector.W;
298  result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z + _34*vector.W;
299  result.W = _41*vector.X + _42*vector.Y + _43*vector.Z + _44*vector.W;
300  }
301 
302  // rotate a vector by this matrix
303  CVector3D Rotate(const CVector3D& vector) const
304  {
305  CVector3D result;
306  Rotate(vector, result);
307  return result;
308  }
309 
310  void Rotate(const CVector3D& vector, CVector3D& result) const
311  {
312  result.X = _11*vector.X + _12*vector.Y + _13*vector.Z;
313  result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z;
314  result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z;
315  }
316 
317  // rotate a vector by the transpose of this matrix
318  void RotateTransposed(const CVector3D& vector,CVector3D& result) const;
319  CVector3D RotateTransposed(const CVector3D& vector) const;
320 };
321 
322 #endif
void Transform(const CVector4D &vector, CVector4D &result) const
Definition: Matrix3D.h:294
void Translate(float x, float y, float z)
Definition: Matrix3D.cpp:172
float _21
Definition: Matrix3D.h:42
void SetZRotation(float angle)
Definition: Matrix3D.cpp:83
float GetYRotation() const
Definition: Matrix3D.cpp:403
void SetTranslation(float x, float y, float z)
Definition: Matrix3D.cpp:158
CMatrix3D & operator+=(const CMatrix3D &m)
Definition: Matrix3D.h:156
float _22
Definition: Matrix3D.h:43
float _12
Definition: Matrix3D.h:43
CMatrix3D()
Definition: Matrix3D.h:54
float _44
Definition: Matrix3D.h:45
void SetYRotation(float angle)
Definition: Matrix3D.cpp:72
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:58
void SetZero()
Definition: Matrix3D.cpp:39
CMatrix3D operator*(const CMatrix3D &matrix) const
Definition: Matrix3D.h:101
float _43
Definition: Matrix3D.h:44
Definition: Vector3D.h:28
CVector3D Transform(const CVector3D &vector) const
Definition: Matrix3D.h:272
CVector3D Rotate(const CVector3D &vector) const
Definition: Matrix3D.h:303
CMatrix3D GetTranspose() const
Definition: Matrix3D.cpp:230
float _32
Definition: Matrix3D.h:43
float _11
Definition: Matrix3D.h:42
void Rotate(const CQuaternion &quat)
Definition: Matrix3D.cpp:354
float & operator[](int idx)
Definition: Matrix3D.h:91
CMatrix3D operator*(float f) const
Definition: Matrix3D.h:134
float Y
Definition: Vector4D.h:128
CMatrix3D operator+(const CMatrix3D &m) const
Definition: Matrix3D.h:145
CMatrix3D & operator*=(const CMatrix3D &matrix)
Definition: Matrix3D.h:127
Definition: Vector4D.h:28
bool operator==(const CMatrix3D &m) const
Definition: Matrix3D.h:166
void PostTranslate(float x, float y, float z)
Definition: Matrix3D.cpp:186
float _33
Definition: Matrix3D.h:44
Definition: Matrix3D.h:33
CVector3D GetIn() const
Definition: Matrix3D.cpp:253
void SetRotation(const CQuaternion &quat)
Definition: Matrix3D.cpp:398
void RotateY(float angle)
Definition: Matrix3D.cpp:117
bool operator!=(const CMatrix3D &m) const
Definition: Matrix3D.h:175
float Z
Definition: Vector4D.h:128
float X
Definition: Vector3D.h:31
float Y
Definition: Vector3D.h:31
float _13
Definition: Matrix3D.h:44
float _data2d[4][4]
Definition: Matrix3D.h:48
float _31
Definition: Matrix3D.h:42
void Scale(float x_scale, float y_scale, float z_scale)
Definition: Matrix3D.cpp:210
float & operator()(int col, int row)
Definition: Matrix3D.h:82
void SetIdentity()
Definition: Matrix3D.cpp:30
float _42
Definition: Matrix3D.h:43
void RotateTransposed(const CVector3D &vector, CVector3D &result) const
Definition: Matrix3D.cpp:269
const float & operator()(int col, int row) const
Definition: Matrix3D.h:86
float _24
Definition: Matrix3D.h:45
CMatrix3D(float data[])
Definition: Matrix3D.h:70
float _34
Definition: Matrix3D.h:45
CVector4D Transform(const CVector4D &vector) const
Definition: Matrix3D.h:287
void Rotate(const CVector3D &vector, CVector3D &result) const
Definition: Matrix3D.h:310
void Concatenate(const CMatrix3D &m)
Definition: Matrix3D.h:188
float W
Definition: Vector4D.h:128
Definition: Quaternion.h:24
float _23
Definition: Matrix3D.h:44
const float & operator[](int idx) const
Definition: Matrix3D.h:95
void SetScaling(float x_scale, float y_scale, float z_scale)
Definition: Matrix3D.cpp:201
float _data[16]
Definition: Matrix3D.h:47
void SetXRotation(float angle)
Definition: Matrix3D.cpp:61
CVector3D GetLeft() const
Definition: Matrix3D.cpp:241
float Z
Definition: Vector3D.h:31
void Transform(const CVector3D &vector, CVector3D &result) const
Definition: Matrix3D.h:279
CVector3D GetUp() const
Definition: Matrix3D.cpp:247
void SetOrtho(float l, float r, float b, float t, float n, float f)
Definition: Matrix3D.cpp:47
void Blend(const CMatrix3D &m, float f)
Definition: Matrix3D.h:194
CVector3D GetTranslation() const
Definition: Matrix3D.cpp:195
void RotateZ(float angle)
Definition: Matrix3D.cpp:137
float _41
Definition: Matrix3D.h:42
void AddBlend(const CMatrix3D &m, float f)
Definition: Matrix3D.h:203
void RotateX(float angle)
Definition: Matrix3D.cpp:97
CQuaternion GetRotation() const
Definition: Matrix3D.cpp:360
CMatrix3D GetInverse() const
Definition: Matrix3D.cpp:347
float X
Definition: Vector4D.h:128
float _14
Definition: Matrix3D.h:45