Pyrogenesis  13997
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
Matrix3D.cpp
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 #include "precompiled.h"
24 
25 #include "Matrix3D.h"
26 #include "Quaternion.h"
27 #include "Vector4D.h"
28 
29 //Sets the identity matrix
31 {
32  _11=1.0f; _12=0.0f; _13=0.0f; _14=0.0f;
33  _21=0.0f; _22=1.0f; _23=0.0f; _24=0.0f;
34  _31=0.0f; _32=0.0f; _33=1.0f; _34=0.0f;
35  _41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
36 }
37 
38 //Sets the zero matrix
40 {
41  _11=0.0f; _12=0.0f; _13=0.0f; _14=0.0f;
42  _21=0.0f; _22=0.0f; _23=0.0f; _24=0.0f;
43  _31=0.0f; _32=0.0f; _33=0.0f; _34=0.0f;
44  _41=0.0f; _42=0.0f; _43=0.0f; _44=0.0f;
45 }
46 
47 void CMatrix3D::SetOrtho (float l, float r, float b, float t, float n, float f)
48 {
49  // Based on OpenGL spec
50  *this = CMatrix3D(
51  2/(r-l), 0, 0, -(r+l)/(r-l),
52  0, 2/(t-b), 0, -(t+b)/(t-b),
53  0, 0, -2/(f-n), -(f+n)/(f-n),
54  0, 0, 0, 1
55  );
56 }
57 
58 //The following clear the matrix and set the
59 //rotation of each of the 3 axes
60 
61 void CMatrix3D::SetXRotation (float angle)
62 {
63  const float Cos = cosf (angle);
64  const float Sin = sinf (angle);
65 
66  _11=1.0f; _12=0.0f; _13=0.0f; _14=0.0f;
67  _21=0.0f; _22=Cos; _23=-Sin; _24=0.0f;
68  _31=0.0f; _32=Sin; _33=Cos; _34=0.0f;
69  _41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
70 }
71 
72 void CMatrix3D::SetYRotation (float angle)
73 {
74  const float Cos = cosf (angle);
75  const float Sin = sinf (angle);
76 
77  _11=Cos; _12=0.0f; _13=Sin; _14=0.0f;
78  _21=0.0f; _22=1.0f; _23=0.0f; _24=0.0f;
79  _31=-Sin; _32=0.0f; _33=Cos; _34=0.0f;
80  _41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
81 }
82 
83 void CMatrix3D::SetZRotation (float angle)
84 {
85  const float Cos = cosf (angle);
86  const float Sin = sinf (angle);
87 
88  _11=Cos; _12=-Sin; _13=0.0f; _14=0.0f;
89  _21=Sin; _22=Cos; _23=0.0f; _24=0.0f;
90  _31=0.0f; _32=0.0f; _33=1.0f; _34=0.0f;
91  _41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
92 }
93 
94 //The following apply a rotation to the matrix
95 //about each of the axes;
96 
97 void CMatrix3D::RotateX (float angle)
98 {
99  const float Cos = cosf (angle);
100  const float Sin = sinf (angle);
101  const float tmp_21 = _21;
102  const float tmp_22 = _22;
103  const float tmp_23 = _23;
104  const float tmp_24 = _24;
105 
106  _21 = Cos * _21 - Sin * _31;
107  _22 = Cos * _22 - Sin * _32;
108  _23 = Cos * _23 - Sin * _33;
109  _24 = Cos * _24 - Sin * _34;
110 
111  _31 = Sin * tmp_21 + Cos * _31;
112  _32 = Sin * tmp_22 + Cos * _32;
113  _33 = Sin * tmp_23 + Cos * _33;
114  _34 = Sin * tmp_24 + Cos * _34;
115 }
116 
117 void CMatrix3D::RotateY (float angle)
118 {
119  const float Cos = cosf (angle);
120  const float Sin = sinf (angle);
121  const float tmp_11 = _11;
122  const float tmp_12 = _12;
123  const float tmp_13 = _13;
124  const float tmp_14 = _14;
125 
126  _11 = Cos * _11 + Sin * _31;
127  _12 = Cos * _12 + Sin * _32;
128  _13 = Cos * _13 + Sin * _33;
129  _14 = Cos * _14 + Sin * _34;
130 
131  _31 = -Sin * tmp_11 + Cos * _31;
132  _32 = -Sin * tmp_12 + Cos * _32;
133  _33 = -Sin * tmp_13 + Cos * _33;
134  _34 = -Sin * tmp_14 + Cos * _34;
135 }
136 
137 void CMatrix3D::RotateZ (float angle)
138 {
139  const float Cos = cosf (angle);
140  const float Sin = sinf (angle);
141  const float tmp_11 = _11;
142  const float tmp_12 = _12;
143  const float tmp_13 = _13;
144  const float tmp_14 = _14;
145 
146  _11 = Cos * _11 - Sin * _21;
147  _12 = Cos * _12 - Sin * _22;
148  _13 = Cos * _13 - Sin * _23;
149  _14 = Cos * _14 - Sin * _24;
150 
151  _21 = Sin * tmp_11 + Cos * _21;
152  _22 = Sin * tmp_12 + Cos * _22;
153  _23 = Sin * tmp_13 + Cos * _23;
154  _24 = Sin * tmp_14 + Cos * _24;
155 }
156 
157 //Sets the translation of the matrix
158 void CMatrix3D::SetTranslation (float x, float y, float z)
159 {
160  _11=1.0f; _12=0.0f; _13=0.0f; _14=x;
161  _21=0.0f; _22=1.0f; _23=0.0f; _24=y;
162  _31=0.0f; _32=0.0f; _33=1.0f; _34=z;
163  _41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
164 }
165 
167 {
168  SetTranslation(vector.X, vector.Y, vector.Z);
169 }
170 
171 //Applies a translation to the matrix
172 void CMatrix3D::Translate(float x, float y, float z)
173 {
174  _14 += x;
175  _24 += y;
176  _34 += z;
177 }
178 
179 void CMatrix3D::Translate(const CVector3D &vector)
180 {
181  _14 += vector.X;
182  _24 += vector.Y;
183  _34 += vector.Z;
184 }
185 
186 void CMatrix3D::PostTranslate(float x, float y, float z)
187 {
188  // Equivalent to "m.SetTranslation(x, y, z); *this = *this * m;"
189  _14 += _11*x + _12*y + _13*z;
190  _24 += _21*x + _22*y + _23*z;
191  _34 += _31*x + _32*y + _33*z;
192  _44 += _41*x + _42*y + _43*z;
193 }
194 
196 {
197  return CVector3D(_14, _24, _34);
198 }
199 
200 //Clears and sets the scaling of the matrix
201 void CMatrix3D::SetScaling (float x_scale, float y_scale, float z_scale)
202 {
203  _11=x_scale; _12=0.0f; _13=0.0f; _14=0.0f;
204  _21=0.0f; _22=y_scale; _23=0.0f; _24=0.0f;
205  _31=0.0f; _32=0.0f; _33=z_scale; _34=0.0f;
206  _41=0.0f; _42=0.0f; _43=0.0f; _44=1.0f;
207 }
208 
209 //Scales the matrix
210 void CMatrix3D::Scale (float x_scale, float y_scale, float z_scale)
211 {
212  _11 *= x_scale;
213  _12 *= x_scale;
214  _13 *= x_scale;
215  _14 *= x_scale;
216 
217  _21 *= y_scale;
218  _22 *= y_scale;
219  _23 *= y_scale;
220  _24 *= y_scale;
221 
222  _31 *= z_scale;
223  _32 *= z_scale;
224  _33 *= z_scale;
225  _34 *= z_scale;
226 }
227 
228 //Returns the transpose of the matrix. For orthonormal
229 //matrices, this is the same is the inverse matrix
231 {
232  return CMatrix3D(
233  _11, _21, _31, _41,
234  _12, _22, _32, _42,
235  _13, _23, _33, _43,
236  _14, _24, _34, _44);
237 }
238 
239 
240 //Get a vector which points to the left of the matrix
242 {
243  return CVector3D(-_11, -_21, -_31);
244 }
245 
246 //Get a vector which points up from the matrix
248 {
249  return CVector3D(_12, _22, _32);
250 }
251 
252 //Get a vector which points to front of the matrix
254 {
255  return CVector3D(_13, _23, _33);
256 }
257 
258 ///////////////////////////////////////////////////////////////////////////////
259 // RotateTransposed: rotate a vector by the transpose of this matrix
261 {
262  CVector3D result;
263  RotateTransposed(vector,result);
264  return result;
265 }
266 
267 ///////////////////////////////////////////////////////////////////////////////
268 // RotateTransposed: rotate a vector by the transpose of this matrix
269 void CMatrix3D::RotateTransposed(const CVector3D& vector,CVector3D& result) const
270 {
271  result.X = _11*vector.X + _21*vector.Y + _31*vector.Z;
272  result.Y = _12*vector.X + _22*vector.Y + _32*vector.Z;
273  result.Z = _13*vector.X + _23*vector.Y + _33*vector.Z;
274 }
275 
276 
278 {
279  float tmp[12]; // temp array for pairs
280  float src[16]; // array of transpose source matrix
281  float det; // determinant
282 
283  // transpose matrix
284  for (int i = 0; i < 4; ++i) {
285  src[i] = _data[i*4];
286  src[i + 4] = _data[i*4 + 1];
287  src[i + 8] = _data[i*4 + 2];
288  src[i + 12] = _data[i*4 + 3];
289  }
290 
291  // calculate pairs for first 8 elements (cofactors)
292  tmp[0] = src[10] * src[15];
293  tmp[1] = src[11] * src[14];
294  tmp[2] = src[9] * src[15];
295  tmp[3] = src[11] * src[13];
296  tmp[4] = src[9] * src[14];
297  tmp[5] = src[10] * src[13];
298  tmp[6] = src[8] * src[15];
299  tmp[7] = src[11] * src[12];
300  tmp[8] = src[8] * src[14];
301  tmp[9] = src[10] * src[12];
302  tmp[10] = src[8] * src[13];
303  tmp[11] = src[9] * src[12];
304 
305  // calculate first 8 elements (cofactors)
306  dst._data[0] = (tmp[0]-tmp[1])*src[5] + (tmp[3]-tmp[2])*src[6] + (tmp[4]-tmp[5])*src[7];
307  dst._data[1] = (tmp[1]-tmp[0])*src[4] + (tmp[6]-tmp[7])*src[6] + (tmp[9]-tmp[8])*src[7];
308  dst._data[2] = (tmp[2]-tmp[3])*src[4] + (tmp[7]-tmp[6])*src[5] + (tmp[10]-tmp[11])*src[7];
309  dst._data[3] = (tmp[5]-tmp[4])*src[4] + (tmp[8]-tmp[9])*src[5] + (tmp[11]-tmp[10])*src[6];
310  dst._data[4] = (tmp[1]-tmp[0])*src[1] + (tmp[2]-tmp[3])*src[2] + (tmp[5]-tmp[4])*src[3];
311  dst._data[5] = (tmp[0]-tmp[1])*src[0] + (tmp[7]-tmp[6])*src[2] + (tmp[8]-tmp[9])*src[3];
312  dst._data[6] = (tmp[3]-tmp[2])*src[0] + (tmp[6]-tmp[7])*src[1] + (tmp[11]-tmp[10])*src[3];
313  dst._data[7] = (tmp[4]-tmp[5])*src[0] + (tmp[9]-tmp[8])*src[1] + (tmp[10]-tmp[11])*src[2];
314 
315  // calculate pairs for second 8 elements (cofactors)
316  tmp[0] = src[2]*src[7];
317  tmp[1] = src[3]*src[6];
318  tmp[2] = src[1]*src[7];
319  tmp[3] = src[3]*src[5];
320  tmp[4] = src[1]*src[6];
321  tmp[5] = src[2]*src[5];
322  tmp[6] = src[0]*src[7];
323  tmp[7] = src[3]*src[4];
324  tmp[8] = src[0]*src[6];
325  tmp[9] = src[2]*src[4];
326  tmp[10] = src[0]*src[5];
327  tmp[11] = src[1]*src[4];
328 
329  // calculate second 8 elements (cofactors)
330  dst._data[8] = (tmp[0]-tmp[1])*src[13] + (tmp[3]-tmp[2])*src[14] + (tmp[4]-tmp[5])*src[15];
331  dst._data[9] = (tmp[1]-tmp[0])*src[12] + (tmp[6]-tmp[7])*src[14] + (tmp[9]-tmp[8])*src[15];
332  dst._data[10] = (tmp[2]-tmp[3])*src[12] + (tmp[7]-tmp[6])*src[13] + (tmp[10]-tmp[11])*src[15];
333  dst._data[11] = (tmp[5]-tmp[4])*src[12] + (tmp[8]-tmp[9])*src[13] + (tmp[11]-tmp[10])*src[14];
334  dst._data[12] = (tmp[2]-tmp[3])*src[10] + (tmp[5]-tmp[4])*src[11] + (tmp[1]-tmp[0])*src[9];
335  dst._data[13] = (tmp[7]-tmp[6])*src[10] + (tmp[8]-tmp[9])*src[11] + (tmp[0]-tmp[1])*src[8];
336  dst._data[14] = (tmp[6]-tmp[7])*src[9] + (tmp[11]-tmp[10])*src[11] + (tmp[3]-tmp[2])*src[8];
337  dst._data[15] = (tmp[10]-tmp[11])*src[10] + (tmp[4]-tmp[5])*src[8] + (tmp[9]-tmp[8])*src[9];
338 
339  // calculate matrix inverse
340  det=src[0]*dst._data[0]+src[1]*dst._data[1]+src[2]*dst._data[2]+src[3]*dst._data[3];
341  det = 1/det;
342  for ( int j = 0; j < 16; j++) {
343  dst._data[j] *= det;
344  }
345 }
346 
348 {
349  CMatrix3D r;
350  GetInverse(r);
351  return r;
352 }
353 
355 {
356  CMatrix3D rotationMatrix=quat.ToMatrix();
357  Concatenate(rotationMatrix);
358 }
359 
361 {
362  float tr = _data2d[0][0] + _data2d[1][1] + _data2d[2][2];
363 
364  int next[] = { 1, 2, 0 };
365 
366  float quat[4];
367 
368  if (tr > 0.f)
369  {
370  float s = sqrtf(tr + 1.f);
371  quat[3] = s * 0.5f;
372  s = 0.5f / s;
373  quat[0] = (_data2d[1][2] - _data2d[2][1]) * s;
374  quat[1] = (_data2d[2][0] - _data2d[0][2]) * s;
375  quat[2] = (_data2d[0][1] - _data2d[1][0]) * s;
376  }
377  else
378  {
379  int i = 0;
380  if (_data2d[1][1] > _data2d[0][0]) i = 1;
381  if (_data2d[2][2] > _data2d[i][i]) i = 2;
382  int j = next[i];
383  int k = next[j];
384 
385  float s = sqrtf((_data2d[i][i] - (_data2d[j][j] + _data2d[k][k])) + 1.f);
386  quat[i] = s * 0.5f;
387 
388  if (s != 0.f) s = 0.5f / s;
389 
390  quat[3] = (_data2d[j][k] - _data2d[k][j]) * s;
391  quat[j] = (_data2d[i][j] + _data2d[j][i]) * s;
392  quat[k] = (_data2d[i][k] + _data2d[k][i]) * s;
393  }
394 
395  return CQuaternion(quat[0], quat[1], quat[2], quat[3]);
396 }
397 
399 {
400  quat.ToMatrix(*this);
401 }
402 
404 {
405  // Project the X axis vector onto the XZ plane
406  CVector3D axis = -GetLeft();
407  axis.Y = 0;
408 
409  // Normalise projected vector
410 
411  float len = axis.Length();
412  if (len < 0.0001f)
413  return 0.f;
414  axis *= 1.0f/len;
415 
416  // Negate the return angle to match the SetYRotation convention
417  return -atan2(axis.Z, axis.X);
418 }
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
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
void SetZero()
Definition: Matrix3D.cpp:39
float _43
Definition: Matrix3D.h:44
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
void PostTranslate(float x, float y, float z)
Definition: Matrix3D.cpp:186
float _33
Definition: Matrix3D.h:44
CVector3D GetIn() const
Definition: Matrix3D.cpp:253
void SetRotation(const CQuaternion &quat)
Definition: Matrix3D.cpp:398
void RotateY(float angle)
Definition: Matrix3D.cpp:117
float X
Definition: Vector3D.h:31
CMatrix3D ToMatrix() const
Definition: Quaternion.cpp:152
float Length() const
Definition: Vector3D.cpp:72
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
void SetIdentity()
Definition: Matrix3D.cpp:30
float _42
Definition: Matrix3D.h:43
void RotateTransposed(const CVector3D &vector, CVector3D &result) const
Definition: Matrix3D.cpp:269
float _24
Definition: Matrix3D.h:45
float _34
Definition: Matrix3D.h:45
void Concatenate(const CMatrix3D &m)
Definition: Matrix3D.h:188
float _23
Definition: Matrix3D.h:44
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
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
CVector3D GetTranslation() const
Definition: Matrix3D.cpp:195
void RotateZ(float angle)
Definition: Matrix3D.cpp:137
float _41
Definition: Matrix3D.h:42
void RotateX(float angle)
Definition: Matrix3D.cpp:97
CQuaternion GetRotation() const
Definition: Matrix3D.cpp:360
CMatrix3D GetInverse() const
Definition: Matrix3D.cpp:347
float _14
Definition: Matrix3D.h:45