File: Matrix3D.h

package info (click to toggle)
0ad 0.0.17-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd
  • size: 51,248 kB
  • ctags: 46,933
  • sloc: cpp: 223,208; ansic: 31,240; python: 16,343; perl: 4,083; sh: 1,011; makefile: 915; xml: 733; java: 621; ruby: 229; erlang: 53; sql: 40
file content (322 lines) | stat: -rw-r--r-- 10,441 bytes parent folder | download | duplicates (5)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
/* Copyright (C) 2010 Wildfire Games.
 * This file is part of 0 A.D.
 *
 * 0 A.D. is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * 0 A.D. is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
 */

/*
 * A Matrix class used for holding and manipulating transformation
 * info.
 */

#ifndef INCLUDED_MATRIX3D
#define INCLUDED_MATRIX3D

#include "maths/Vector3D.h"
#include "maths/Vector4D.h"

class CQuaternion;

/////////////////////////////////////////////////////////////////////////
// CMatrix3D: a 4x4 matrix class for common operations in 3D
class CMatrix3D
{
public:
	// the matrix data itself - accessible as either longhand names
	// or via a flat or 2d array
	// NOTE: _xy means row x, column y in the mathematical notation of this matrix, so don't be 
	// fooled by the way they're listed below
	union {
		struct {
			float _11, _21, _31, _41;
			float _12, _22, _32, _42;
			float _13, _23, _33, _43;
			float _14, _24, _34, _44;
		};
		float _data[16];
		float _data2d[4][4];
		// (Be aware that m(0,2) == _data2d[2][0] == _13, etc. This is to be considered a feature.)
	};

public:
	// constructors
	CMatrix3D ()
	{
	}

	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) :
		_11(a11), _12(a12), _13(a13), _14(a14),
		_21(a21), _22(a22), _23(a23), _24(a24),
		_31(a31), _32(a32), _33(a33), _34(a34),
		_41(a41), _42(a42), _43(a43), _44(a44)
	{
	}

	CMatrix3D(float data[]) :
		_11(data[0]), _21(data[1]), _31(data[2]), _41(data[3]),
		_12(data[4]), _22(data[5]), _32(data[6]), _42(data[7]),
		_13(data[8]), _23(data[9]), _33(data[10]), _43(data[11]),
		_14(data[12]), _24(data[13]), _34(data[14]), _44(data[15])
	{
	}

	// accessors to individual elements of matrix
	// NOTE: in this function definition, 'col' and 'row' represent the column and row into the 
	// internal element matrix which is the transposed of the mathematical notation, so the first 
	// and second arguments here are actually the row and column into the mathematical notation.
	float& operator()(int col, int row)
	{
		return _data[row*4+col];
	}
	const float& operator()(int col, int row) const
	{
		return _data[row*4+col];
	}

	float& operator[](int idx)
	{
		return _data[idx];
	}
	const float& operator[](int idx) const
	{
		return _data[idx];
	}

	// matrix multiplication
	CMatrix3D operator*(const CMatrix3D &matrix) const
	{
		return CMatrix3D(
			_11*matrix._11 + _12*matrix._21 + _13*matrix._31 + _14*matrix._41,
			_11*matrix._12 + _12*matrix._22 + _13*matrix._32 + _14*matrix._42,
			_11*matrix._13 + _12*matrix._23 + _13*matrix._33 + _14*matrix._43,
			_11*matrix._14 + _12*matrix._24 + _13*matrix._34 + _14*matrix._44,

			_21*matrix._11 + _22*matrix._21 + _23*matrix._31 + _24*matrix._41,
			_21*matrix._12 + _22*matrix._22 + _23*matrix._32 + _24*matrix._42,
			_21*matrix._13 + _22*matrix._23 + _23*matrix._33 + _24*matrix._43,
			_21*matrix._14 + _22*matrix._24 + _23*matrix._34 + _24*matrix._44,

			_31*matrix._11 + _32*matrix._21 + _33*matrix._31 + _34*matrix._41,
			_31*matrix._12 + _32*matrix._22 + _33*matrix._32 + _34*matrix._42,
			_31*matrix._13 + _32*matrix._23 + _33*matrix._33 + _34*matrix._43,
			_31*matrix._14 + _32*matrix._24 + _33*matrix._34 + _34*matrix._44,

			_41*matrix._11 + _42*matrix._21 + _43*matrix._31 + _44*matrix._41,
			_41*matrix._12 + _42*matrix._22 + _43*matrix._32 + _44*matrix._42,
			_41*matrix._13 + _42*matrix._23 + _43*matrix._33 + _44*matrix._43,
			_41*matrix._14 + _42*matrix._24 + _43*matrix._34 + _44*matrix._44
		);
	}

	// matrix multiplication/assignment
	CMatrix3D& operator*=(const CMatrix3D &matrix)
	{
		Concatenate(matrix);
		return *this;
	}

	// matrix scaling
	CMatrix3D operator*(float f) const
	{
		return CMatrix3D(
			_11*f, _12*f, _13*f, _14*f,
			_21*f, _22*f, _23*f, _24*f,
			_31*f, _32*f, _33*f, _34*f,
			_41*f, _42*f, _43*f, _44*f
		);
	}

	// matrix addition
	CMatrix3D operator+(const CMatrix3D &m) const
	{
		return CMatrix3D(
			_11+m._11, _12+m._12, _13+m._13, _14+m._14,
			_21+m._21, _22+m._22, _23+m._23, _24+m._24,
			_31+m._31, _32+m._32, _33+m._33, _34+m._34,
			_41+m._41, _42+m._42, _43+m._43, _44+m._44
		);
	}

	// matrix addition/assignment
	CMatrix3D& operator+=(const CMatrix3D &m)
	{
		_11 += m._11; _21 += m._21; _31 += m._31; _41 += m._41;
		_12 += m._12; _22 += m._22; _32 += m._32; _42 += m._42;
		_13 += m._13; _23 += m._23; _33 += m._33; _43 += m._43;
		_14 += m._14; _24 += m._24; _34 += m._34; _44 += m._44;
		return *this;
	}

	// equality
	bool operator==(const CMatrix3D &m) const
	{
		return _11 == m._11 && _21 == m._21 && _31 == m._31 && _41 == m._41 &&
				 _12 == m._12 && _22 == m._22 && _32 == m._32 && _42 == m._42 &&
				 _13 == m._13 && _23 == m._23 && _33 == m._33 && _43 == m._43 &&
				 _14 == m._14 && _24 == m._24 && _34 == m._34 && _44 == m._44;
	}

	// inequality
	bool operator!=(const CMatrix3D& m) const
	{
		return !(*this == m);
	}

	// set this matrix to the identity matrix
	void SetIdentity();
	// set this matrix to the zero matrix
	void SetZero();
	// set this matrix to the orthogonal projection matrix (as with glOrtho)
	void SetOrtho(float l, float r, float b, float t, float n, float f);

	// concatenate arbitrary matrix onto this matrix
	void Concatenate(const CMatrix3D& m)
	{
		(*this) = m * (*this);
	}

	// blend matrix using only 4x3 subset
	void Blend(const CMatrix3D& m, float f)
	{
		_11 = m._11*f; _21 = m._21*f; _31 = m._31*f;
		_12 = m._12*f; _22 = m._22*f; _32 = m._32*f;
		_13 = m._13*f; _23 = m._23*f; _33 = m._33*f;
		_14 = m._14*f; _24 = m._24*f; _34 = m._34*f;
	}

	// blend matrix using only 4x3 and add onto existing blend
	void AddBlend(const CMatrix3D& m, float f)
	{
		_11 += m._11*f; _21 += m._21*f; _31 += m._31*f;
		_12 += m._12*f; _22 += m._22*f; _32 += m._32*f;
		_13 += m._13*f; _23 += m._23*f; _33 += m._33*f;
		_14 += m._14*f; _24 += m._24*f; _34 += m._34*f;
	}

	// set this matrix to a rotation matrix for a rotation about X axis of given angle
	void SetXRotation(float angle);
	// set this matrix to a rotation matrix for a rotation about Y axis of given angle
	void SetYRotation(float angle);
	// set this matrix to a rotation matrix for a rotation about Z axis of given angle
	void SetZRotation(float angle);
	// set this matrix to a rotation described by given quaternion
	void SetRotation(const CQuaternion& quat);

	// concatenate a rotation about the X axis onto this matrix
	void RotateX(float angle);
	// concatenate a rotation about the Y axis onto this matrix
	void RotateY(float angle);
	// concatenate a rotation about the Z axis onto this matrix
	void RotateZ(float angle);
	// concatenate a rotation described by given quaternion
	void Rotate(const CQuaternion& quat);

	// sets this matrix to the given translation matrix (any existing transformation will be overwritten)
	void SetTranslation(float x, float y, float z);
	void SetTranslation(const CVector3D& vector);

	// concatenate given translation onto this matrix. Assumes the current
	// matrix is an affine transformation (i.e. the bottom row is [0,0,0,1])
	// as an optimisation.
	void Translate(float x, float y, float z);
	void Translate(const CVector3D& vector);

	// apply translation after this matrix (M = M * T)
	void PostTranslate(float x, float y, float z);

	// set this matrix to the given scaling matrix
	void SetScaling(float x_scale, float y_scale, float z_scale);

	// concatenate given scaling matrix onto this matrix
	void Scale(float x_scale, float y_scale, float z_scale);

	// calculate the inverse of this matrix, store in dst
	void GetInverse(CMatrix3D& dst) const;

	// return the inverse of this matrix
	CMatrix3D GetInverse() const;

	// calculate the transpose of this matrix, store in dst
	CMatrix3D GetTranspose() const;

	// return the translation component of this matrix
	CVector3D GetTranslation() const;
	// return left vector, derived from rotation
	CVector3D GetLeft() const;
	// return up vector, derived from rotation
	CVector3D GetUp() const;
	// return forward vector, derived from rotation
	CVector3D GetIn() const;
	// return a quaternion representing the matrix's rotation
	CQuaternion GetRotation() const;
	// return the angle of rotation around the Y axis in range [-pi,pi]
	// (based on projecting the X axis onto the XZ plane)
	float GetYRotation() const;

	// transform a 3D vector by this matrix
	CVector3D Transform(const CVector3D &vector) const
	{
		CVector3D result;
		Transform(vector, result);
		return result;
	}

	void Transform(const CVector3D& vector, CVector3D& result) const
	{
		result.X = _11*vector.X + _12*vector.Y + _13*vector.Z + _14;
		result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z + _24;
		result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z + _34;
	}

	// transform a 4D vector by this matrix
	CVector4D Transform(const CVector4D &vector) const
	{
		CVector4D result;
		Transform(vector, result);
		return result;
	}

	void Transform(const CVector4D& vector, CVector4D& result) const
	{
		result.X = _11*vector.X + _12*vector.Y + _13*vector.Z + _14*vector.W;
		result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z + _24*vector.W;
		result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z + _34*vector.W;
		result.W = _41*vector.X + _42*vector.Y + _43*vector.Z + _44*vector.W;
	}

	// rotate a vector by this matrix
	CVector3D Rotate(const CVector3D& vector) const
	{
		CVector3D result;
		Rotate(vector, result);
		return result;
	}

	void Rotate(const CVector3D& vector, CVector3D& result) const
	{
		result.X = _11*vector.X + _12*vector.Y + _13*vector.Z;
		result.Y = _21*vector.X + _22*vector.Y + _23*vector.Z;
		result.Z = _31*vector.X + _32*vector.Y + _33*vector.Z;
	}

	// rotate a vector by the transpose of this matrix
	void RotateTransposed(const CVector3D& vector,CVector3D& result) const;
	CVector3D RotateTransposed(const CVector3D& vector) const;
};

#endif