1 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
2 /**
3  *	Contains code for 4x4 matrices.
4  *	\file		IceMatrix4x4.h
5  *	\author		Pierre Terdiman
6  *	\date		April, 4, 2000
7  */
8 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
9 
10 ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
11 // Include Guard
12 #ifndef __ICEMATRIX4X4_H__
13 #define __ICEMATRIX4X4_H__
14 
15 	// Forward declarations
16 	class PRS;
17 	class PR;
18 
19 	#define	MATRIX4X4_EPSILON		(1.0e-7f)
20 
21 	class ICEMATHS_API Matrix4x4
22 	{
23 //				void	LUBackwardSubstitution( sdword *indx, float* b );
24 //				void	LUDecomposition( sdword* indx, float* d );
25 
26 		public:
27 		//! Empty constructor.
Matrix4x4()28 		inline_						Matrix4x4()									{}
29 		//! Constructor from 16 values
Matrix4x4(float m00,float m01,float m02,float m03,float m10,float m11,float m12,float m13,float m20,float m21,float m22,float m23,float m30,float m31,float m32,float m33)30 		inline_						Matrix4x4(	float m00, float m01, float m02, float m03,
31 												float m10, float m11, float m12, float m13,
32 												float m20, float m21, float m22, float m23,
33 												float m30, float m31, float m32, float m33)
34 									{
35 										m[0][0] = m00;	m[0][1] = m01;	m[0][2] = m02;	m[0][3] = m03;
36 										m[1][0] = m10;	m[1][1] = m11;	m[1][2] = m12;	m[1][3] = m13;
37 										m[2][0] = m20;	m[2][1] = m21;	m[2][2] = m22;	m[2][3] = m23;
38 										m[3][0] = m30;	m[3][1] = m31;	m[3][2] = m32;	m[3][3] = m33;
39 									}
40 		//! Copy constructor
Matrix4x4(const Matrix4x4 & mat)41 		inline_						Matrix4x4(const Matrix4x4& mat)				{ CopyMemory(m, &mat.m, 16*sizeof(float));	}
42 		//! Destructor.
~Matrix4x4()43 		inline_						~Matrix4x4()								{}
44 
45 		//! Assign values (rotation only)
Set(float m00,float m01,float m02,float m10,float m11,float m12,float m20,float m21,float m22)46 		inline_	Matrix4x4&			Set(	float m00, float m01, float m02,
47 											float m10, float m11, float m12,
48 											float m20, float m21, float m22)
49 									{
50 										m[0][0] = m00;	m[0][1] = m01;	m[0][2] = m02;
51 										m[1][0] = m10;	m[1][1] = m11;	m[1][2] = m12;
52 										m[2][0] = m20;	m[2][1] = m21;	m[2][2] = m22;
53 										return *this;
54 									}
55 		//! Assign values
Set(float m00,float m01,float m02,float m03,float m10,float m11,float m12,float m13,float m20,float m21,float m22,float m23,float m30,float m31,float m32,float m33)56 		inline_	Matrix4x4&			Set(	float m00, float m01, float m02, float m03,
57 											float m10, float m11, float m12, float m13,
58 											float m20, float m21, float m22, float m23,
59 											float m30, float m31, float m32, float m33)
60 									{
61 										m[0][0] = m00;	m[0][1] = m01;	m[0][2] = m02;	m[0][3] = m03;
62 										m[1][0] = m10;	m[1][1] = m11;	m[1][2] = m12;	m[1][3] = m13;
63 										m[2][0] = m20;	m[2][1] = m21;	m[2][2] = m22;	m[2][3] = m23;
64 										m[3][0] = m30;	m[3][1] = m31;	m[3][2] = m32;	m[3][3] = m33;
65 										return *this;
66 									}
67 
68 		//! Copy from a Matrix4x4
Copy(const Matrix4x4 & source)69 		inline_	void				Copy(const Matrix4x4& source)				{ CopyMemory(m, source.m, 16*sizeof(float));	}
70 
71 		// Row-column access
72 		//! Returns a row.
GetRow(const udword r,HPoint & p)73 		inline_	void				GetRow(const udword r, HPoint& p)	const	{ p.x=m[r][0];	p.y=m[r][1];	p.z=m[r][2];	p.w=m[r][3];		}
74 		//! Returns a row.
GetRow(const udword r,Point & p)75 		inline_	void				GetRow(const udword r, Point& p)	const	{ p.x=m[r][0];	p.y=m[r][1];	p.z=m[r][2];						}
76 		//! Returns a row.
GetRow(const udword r)77 		inline_	const HPoint&		GetRow(const udword r)				const	{ return *(const HPoint*)&m[r][0];									}
78 		//! Returns a row.
GetRow(const udword r)79 		inline_	HPoint&				GetRow(const udword r)						{ return *(HPoint*)&m[r][0];										}
80 		//! Sets a row.
SetRow(const udword r,const HPoint & p)81 		inline_	void				SetRow(const udword r, const HPoint& p)		{ m[r][0]=p.x;	m[r][1]=p.y;	m[r][2]=p.z;	m[r][3]=p.w;		}
82 		//! Sets a row.
SetRow(const udword r,const Point & p)83 		inline_	void				SetRow(const udword r, const Point& p)		{ m[r][0]=p.x;	m[r][1]=p.y;	m[r][2]=p.z;	m[r][3]= (r!=3) ? 0.0f : 1.0f;		}
84 		//! Returns a column.
GetCol(const udword c,HPoint & p)85 		inline_	void				GetCol(const udword c, HPoint& p)	const	{ p.x=m[0][c];	p.y=m[1][c];	p.z=m[2][c];	p.w=m[3][c];		}
86 		//! Returns a column.
GetCol(const udword c,Point & p)87 		inline_	void				GetCol(const udword c, Point& p)	const	{ p.x=m[0][c];	p.y=m[1][c];	p.z=m[2][c];						}
88 		//! Sets a column.
SetCol(const udword c,const HPoint & p)89 		inline_	void				SetCol(const udword c, const HPoint& p)		{ m[0][c]=p.x;	m[1][c]=p.y;	m[2][c]=p.z;	m[3][c]=p.w;		}
90 		//! Sets a column.
SetCol(const udword c,const Point & p)91 		inline_	void				SetCol(const udword c, const Point& p)		{ m[0][c]=p.x;	m[1][c]=p.y;	m[2][c]=p.z;	m[3][c]= (c!=3) ? 0.0f : 1.0f;	}
92 
93 		// Translation
94 		//! Returns the translation part of the matrix.
GetTrans()95 		inline_	const HPoint&		GetTrans()							const	{ return GetRow(3);								}
96 		//! Gets the translation part of the matrix
GetTrans(Point & p)97 		inline_	void				GetTrans(Point& p)					const	{ p.x=m[3][0];	p.y=m[3][1];	p.z=m[3][2];	}
98 		//! Sets the translation part of the matrix, from a Point.
SetTrans(const Point & p)99 		inline_	void				SetTrans(const Point& p)					{ m[3][0]=p.x;	m[3][1]=p.y;	m[3][2]=p.z;	}
100 		//! Sets the translation part of the matrix, from a HPoint.
SetTrans(const HPoint & p)101 		inline_	void				SetTrans(const HPoint& p)					{ m[3][0]=p.x;	m[3][1]=p.y;	m[3][2]=p.z;	m[3][3]=p.w;	}
102 		//! Sets the translation part of the matrix, from floats.
SetTrans(float tx,float ty,float tz)103 		inline_	void				SetTrans(float tx, float ty, float tz)		{ m[3][0]=tx;	m[3][1]=ty;		m[3][2]=tz;		}
104 
105 		// Scale
106 		//! Sets the scale from a Point. The point is put on the diagonal.
SetScale(const Point & p)107 		inline_	void				SetScale(const Point& p)					{ m[0][0]=p.x;	m[1][1]=p.y;	m[2][2]=p.z;	}
108 		//! Sets the scale from floats. Values are put on the diagonal.
SetScale(float sx,float sy,float sz)109 		inline_	void				SetScale(float sx, float sy, float sz)		{ m[0][0]=sx;	m[1][1]=sy;		m[2][2]=sz;		}
110 		//! Scales from a Point. Each row is multiplied by a component.
Scale(const Point & p)111 				void				Scale(const Point& p)
112 									{
113 										m[0][0] *= p.x;	m[1][0] *= p.y;	m[2][0] *= p.z;
114 										m[0][1] *= p.x;	m[1][1] *= p.y;	m[2][1] *= p.z;
115 										m[0][2] *= p.x;	m[1][2] *= p.y;	m[2][2] *= p.z;
116 									}
117 		//! Scales from floats. Each row is multiplied by a value.
Scale(float sx,float sy,float sz)118 				void				Scale(float sx, float sy, float sz)
119 									{
120 										m[0][0] *= sx;	m[1][0] *= sy;	m[2][0] *= sz;
121 										m[0][1] *= sx;	m[1][1] *= sy;	m[2][1] *= sz;
122 										m[0][2] *= sx;	m[1][2] *= sy;	m[2][2] *= sz;
123 									}
124 /*
125 		//! Returns a row.
126 		inline_	HPoint		GetRow(const udword row)	const			{ return mRow[row];														}
127 		//! Sets a row.
128 		inline_	Matrix4x4&	SetRow(const udword row, const HPoint& p)	{ mRow[row] = p;	return *this;										}
129 		//! Sets a row.
130 						Matrix4x4&	SetRow(const udword row, const Point& p)
131 						{
132 							m[row][0] = p.x;
133 							m[row][1] = p.y;
134 							m[row][2] = p.z;
135 							m[row][3] = (row != 3) ? 0.0f : 1.0f;
136 							return	*this;
137 						}
138 		//! Returns a column.
139 						HPoint		GetCol(const udword col)		const
140 						{
141 							HPoint	Res;
142 							Res.x = m[0][col];
143 							Res.y = m[1][col];
144 							Res.z = m[2][col];
145 							Res.w = m[3][col];
146 							return	Res;
147 						}
148 		//! Sets a column.
149 						Matrix4x4&	SetCol(const udword col, const HPoint& p)
150 						{
151 							m[0][col] = p.x;
152 							m[1][col] = p.y;
153 							m[2][col] = p.z;
154 							m[3][col] = p.w;
155 							return	*this;
156 						}
157 		//! Sets a column.
158 						Matrix4x4&	SetCol(const udword col, const Point& p)
159 						{
160 							m[0][col] = p.x;
161 							m[1][col] = p.y;
162 							m[2][col] = p.z;
163 							m[3][col] = (col != 3) ? 0.0f : 1.0f;
164 							return	*this;
165 						}
166 */
167 		//! Computes the trace. The trace is the sum of the 4 diagonal components.
Trace()168 		inline_	float				Trace()			const			{ return m[0][0] + m[1][1] + m[2][2] + m[3][3];			}
169 		//! Computes the trace of the upper 3x3 matrix.
Trace3x3()170 		inline_	float				Trace3x3()		const			{ return m[0][0] + m[1][1] + m[2][2];					}
171 		//! Clears the matrix.
Zero()172 		inline_	void				Zero()							{ ZeroMemory(&m,  sizeof(m));							}
173 		//! Sets the identity matrix.
Identity()174 		inline_	void				Identity()						{ Zero(); m[0][0] = m[1][1] = m[2][2] = m[3][3] = 1.0f;	}
175 		//! Checks for identity
IsIdentity()176 		inline_	bool				IsIdentity()	const
177 									{
178 										if(IR(m[0][0])!=IEEE_1_0)	return false;
179 										if(IR(m[0][1])!=0)			return false;
180 										if(IR(m[0][2])!=0)			return false;
181 										if(IR(m[0][3])!=0)			return false;
182 
183 										if(IR(m[1][0])!=0)			return false;
184 										if(IR(m[1][1])!=IEEE_1_0)	return false;
185 										if(IR(m[1][2])!=0)			return false;
186 										if(IR(m[1][3])!=0)			return false;
187 
188 										if(IR(m[2][0])!=0)			return false;
189 										if(IR(m[2][1])!=0)			return false;
190 										if(IR(m[2][2])!=IEEE_1_0)	return false;
191 										if(IR(m[2][3])!=0)			return false;
192 
193 										if(IR(m[3][0])!=0)			return false;
194 										if(IR(m[3][1])!=0)			return false;
195 										if(IR(m[3][2])!=0)			return false;
196 										if(IR(m[3][3])!=IEEE_1_0)	return false;
197 										return true;
198 									}
199 
200 		//! Checks matrix validity
IsValid()201 		inline_	BOOL				IsValid()		const
202 									{
203 										for(udword j=0;j<4;j++)
204 										{
205 											for(udword i=0;i<4;i++)
206 											{
207 												if(!IsValidFloat(m[j][i]))	return FALSE;
208 											}
209 										}
210 										return TRUE;
211 									}
212 
213 		//! Sets a rotation matrix around the X axis.
RotX(float angle)214 				void				RotX(float angle)	{ float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[1][1] = m[2][2] = Cos; m[2][1] = -Sin;	m[1][2] = Sin;	}
215 		//! Sets a rotation matrix around the Y axis.
RotY(float angle)216 				void				RotY(float angle)	{ float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[2][2] = Cos; m[2][0] = Sin;	m[0][2] = -Sin;	}
217 		//! Sets a rotation matrix around the Z axis.
RotZ(float angle)218 				void				RotZ(float angle)	{ float Cos = cosf(angle), Sin = sinf(angle); Identity(); m[0][0] = m[1][1] = Cos; m[1][0] = -Sin;	m[0][1] = Sin;	}
219 
220 		//! Makes a rotation matrix about an arbitrary axis
221 				Matrix4x4&			Rot(float angle, Point& p1, Point& p2);
222 
223 		//! Transposes the matrix.
Transpose()224 				void				Transpose()
225 									{
226 										IR(m[1][0]) ^= IR(m[0][1]);		IR(m[0][1]) ^= IR(m[1][0]);		IR(m[1][0]) ^= IR(m[0][1]);
227 										IR(m[2][0]) ^= IR(m[0][2]);		IR(m[0][2]) ^= IR(m[2][0]);		IR(m[2][0]) ^= IR(m[0][2]);
228 										IR(m[3][0]) ^= IR(m[0][3]);		IR(m[0][3]) ^= IR(m[3][0]);		IR(m[3][0]) ^= IR(m[0][3]);
229 										IR(m[1][2]) ^= IR(m[2][1]);		IR(m[2][1]) ^= IR(m[1][2]);		IR(m[1][2]) ^= IR(m[2][1]);
230 										IR(m[1][3]) ^= IR(m[3][1]);		IR(m[3][1]) ^= IR(m[1][3]);		IR(m[1][3]) ^= IR(m[3][1]);
231 										IR(m[2][3]) ^= IR(m[3][2]);		IR(m[3][2]) ^= IR(m[2][3]);		IR(m[2][3]) ^= IR(m[3][2]);
232 									}
233 
234 		//! Computes a cofactor. Used for matrix inversion.
235 				float				CoFactor(udword row, udword col)	const;
236 		//! Computes the determinant of the matrix.
237 				float				Determinant()	const;
238 		//! Inverts the matrix. Determinant must be different from zero, else matrix can't be inverted.
239 				Matrix4x4&			Invert();
240 //				Matrix&	ComputeAxisMatrix(Point& axis, float angle);
241 
242 		// Cast operators
243 		//! Casts a Matrix4x4 to a Matrix3x3.
Matrix3x3()244 		inline_	operator			Matrix3x3()	const
245 									{
246 										return Matrix3x3(
247 										m[0][0],	m[0][1],	m[0][2],
248 										m[1][0],	m[1][1],	m[1][2],
249 										m[2][0],	m[2][1],	m[2][2]);
250 									}
251 		//! Casts a Matrix4x4 to a Quat.
252 				operator			Quat()	const;
253 		//! Casts a Matrix4x4 to a PR.
254 				operator			PR()	const;
255 
256 		// Arithmetic operators
257 		//! Operator for Matrix4x4 Plus = Matrix4x4 + Matrix4x4;
258 		inline_	Matrix4x4			operator+(const Matrix4x4& mat)	const
259 									{
260 										return Matrix4x4(
261 										m[0][0]+mat.m[0][0], m[0][1]+mat.m[0][1], m[0][2]+mat.m[0][2], m[0][3]+mat.m[0][3],
262 										m[1][0]+mat.m[1][0], m[1][1]+mat.m[1][1], m[1][2]+mat.m[1][2], m[1][3]+mat.m[1][3],
263 										m[2][0]+mat.m[2][0], m[2][1]+mat.m[2][1], m[2][2]+mat.m[2][2], m[2][3]+mat.m[2][3],
264 										m[3][0]+mat.m[3][0], m[3][1]+mat.m[3][1], m[3][2]+mat.m[3][2], m[3][3]+mat.m[3][3]);
265 									}
266 
267 		//! Operator for Matrix4x4 Minus = Matrix4x4 - Matrix4x4;
268 		inline_	Matrix4x4			operator-(const Matrix4x4& mat)	const
269 									{
270 										return Matrix4x4(
271 										m[0][0]-mat.m[0][0], m[0][1]-mat.m[0][1], m[0][2]-mat.m[0][2], m[0][3]-mat.m[0][3],
272 										m[1][0]-mat.m[1][0], m[1][1]-mat.m[1][1], m[1][2]-mat.m[1][2], m[1][3]-mat.m[1][3],
273 										m[2][0]-mat.m[2][0], m[2][1]-mat.m[2][1], m[2][2]-mat.m[2][2], m[2][3]-mat.m[2][3],
274 										m[3][0]-mat.m[3][0], m[3][1]-mat.m[3][1], m[3][2]-mat.m[3][2], m[3][3]-mat.m[3][3]);
275 									}
276 
277 		//! Operator for Matrix4x4 Mul = Matrix4x4 * Matrix4x4;
278 		inline_	Matrix4x4			operator*(const Matrix4x4& mat)	const
279 									{
280 										return Matrix4x4(
281 										m[0][0]*mat.m[0][0] + m[0][1]*mat.m[1][0] + m[0][2]*mat.m[2][0] + m[0][3]*mat.m[3][0],
282 										m[0][0]*mat.m[0][1] + m[0][1]*mat.m[1][1] + m[0][2]*mat.m[2][1] + m[0][3]*mat.m[3][1],
283 										m[0][0]*mat.m[0][2] + m[0][1]*mat.m[1][2] + m[0][2]*mat.m[2][2] + m[0][3]*mat.m[3][2],
284 										m[0][0]*mat.m[0][3] + m[0][1]*mat.m[1][3] + m[0][2]*mat.m[2][3] + m[0][3]*mat.m[3][3],
285 
286 										m[1][0]*mat.m[0][0] + m[1][1]*mat.m[1][0] + m[1][2]*mat.m[2][0] + m[1][3]*mat.m[3][0],
287 										m[1][0]*mat.m[0][1] + m[1][1]*mat.m[1][1] + m[1][2]*mat.m[2][1] + m[1][3]*mat.m[3][1],
288 										m[1][0]*mat.m[0][2] + m[1][1]*mat.m[1][2] + m[1][2]*mat.m[2][2] + m[1][3]*mat.m[3][2],
289 										m[1][0]*mat.m[0][3] + m[1][1]*mat.m[1][3] + m[1][2]*mat.m[2][3] + m[1][3]*mat.m[3][3],
290 
291 										m[2][0]*mat.m[0][0] + m[2][1]*mat.m[1][0] + m[2][2]*mat.m[2][0] + m[2][3]*mat.m[3][0],
292 										m[2][0]*mat.m[0][1] + m[2][1]*mat.m[1][1] + m[2][2]*mat.m[2][1] + m[2][3]*mat.m[3][1],
293 										m[2][0]*mat.m[0][2] + m[2][1]*mat.m[1][2] + m[2][2]*mat.m[2][2] + m[2][3]*mat.m[3][2],
294 										m[2][0]*mat.m[0][3] + m[2][1]*mat.m[1][3] + m[2][2]*mat.m[2][3] + m[2][3]*mat.m[3][3],
295 
296 										m[3][0]*mat.m[0][0] + m[3][1]*mat.m[1][0] + m[3][2]*mat.m[2][0] + m[3][3]*mat.m[3][0],
297 										m[3][0]*mat.m[0][1] + m[3][1]*mat.m[1][1] + m[3][2]*mat.m[2][1] + m[3][3]*mat.m[3][1],
298 										m[3][0]*mat.m[0][2] + m[3][1]*mat.m[1][2] + m[3][2]*mat.m[2][2] + m[3][3]*mat.m[3][2],
299 										m[3][0]*mat.m[0][3] + m[3][1]*mat.m[1][3] + m[3][2]*mat.m[2][3] + m[3][3]*mat.m[3][3]);
300 									}
301 
302 		//! Operator for HPoint Mul = Matrix4x4 * HPoint;
303 		inline_	HPoint				operator*(const HPoint& v)		const	{ return HPoint(GetRow(0)|v, GetRow(1)|v, GetRow(2)|v, GetRow(3)|v); }
304 
305 		//! Operator for Point Mul = Matrix4x4 * Point;
306 		inline_	Point				operator*(const Point& v)		const
307 									{
308 										return Point(	m[0][0]*v.x + m[0][1]*v.y + m[0][2]*v.z + m[0][3],
309 														m[1][0]*v.x + m[1][1]*v.y + m[1][2]*v.z + m[1][3],
310 														m[2][0]*v.x + m[2][1]*v.y + m[2][2]*v.z + m[2][3]	);
311 									}
312 
313 		//! Operator for Matrix4x4 Scale = Matrix4x4 * float;
314 		inline_	Matrix4x4			operator*(float s)				const
315 									{
316 										return Matrix4x4(
317 										m[0][0]*s,	m[0][1]*s,	m[0][2]*s,	m[0][3]*s,
318 										m[1][0]*s,	m[1][1]*s,	m[1][2]*s,	m[1][3]*s,
319 										m[2][0]*s,	m[2][1]*s,	m[2][2]*s,	m[2][3]*s,
320 										m[3][0]*s,	m[3][1]*s,	m[3][2]*s,	m[3][3]*s);
321 									}
322 
323 		//! Operator for Matrix4x4 Scale = float * Matrix4x4;
324 		inline_	friend Matrix4x4	operator*(float s, const Matrix4x4& mat)
325 									{
326 										return Matrix4x4(
327 										s*mat.m[0][0],	s*mat.m[0][1],	s*mat.m[0][2],	s*mat.m[0][3],
328 										s*mat.m[1][0],	s*mat.m[1][1],	s*mat.m[1][2],	s*mat.m[1][3],
329 										s*mat.m[2][0],	s*mat.m[2][1],	s*mat.m[2][2],	s*mat.m[2][3],
330 										s*mat.m[3][0],	s*mat.m[3][1],	s*mat.m[3][2],	s*mat.m[3][3]);
331 									}
332 
333 		//! Operator for Matrix4x4 Div = Matrix4x4 / float;
334 		inline_	Matrix4x4			operator/(float s)				const
335 									{
336 										if(s) s = 1.0f / s;
337 
338 										return Matrix4x4(
339 										m[0][0]*s,	m[0][1]*s,	m[0][2]*s,	m[0][3]*s,
340 										m[1][0]*s,	m[1][1]*s,	m[1][2]*s,	m[1][3]*s,
341 										m[2][0]*s,	m[2][1]*s,	m[2][2]*s,	m[2][3]*s,
342 										m[3][0]*s,	m[3][1]*s,	m[3][2]*s,	m[3][3]*s);
343 									}
344 
345 		//! Operator for Matrix4x4 Div = float / Matrix4x4;
346 		inline_	friend Matrix4x4	operator/(float s, const Matrix4x4& mat)
347 									{
348 										return Matrix4x4(
349 										s/mat.m[0][0],	s/mat.m[0][1],	s/mat.m[0][2],	s/mat.m[0][3],
350 										s/mat.m[1][0],	s/mat.m[1][1],	s/mat.m[1][2],	s/mat.m[1][3],
351 										s/mat.m[2][0],	s/mat.m[2][1],	s/mat.m[2][2],	s/mat.m[2][3],
352 										s/mat.m[3][0],	s/mat.m[3][1],	s/mat.m[3][2],	s/mat.m[3][3]);
353 									}
354 
355 		//! Operator for Matrix4x4 += Matrix4x4;
356 		inline_	Matrix4x4&			operator+=(const Matrix4x4& mat)
357 									{
358 										m[0][0]+=mat.m[0][0];	m[0][1]+=mat.m[0][1];	m[0][2]+=mat.m[0][2];	m[0][3]+=mat.m[0][3];
359 										m[1][0]+=mat.m[1][0];	m[1][1]+=mat.m[1][1];	m[1][2]+=mat.m[1][2];	m[1][3]+=mat.m[1][3];
360 										m[2][0]+=mat.m[2][0];	m[2][1]+=mat.m[2][1];	m[2][2]+=mat.m[2][2];	m[2][3]+=mat.m[2][3];
361 										m[3][0]+=mat.m[3][0];	m[3][1]+=mat.m[3][1];	m[3][2]+=mat.m[3][2];	m[3][3]+=mat.m[3][3];
362 										return	*this;
363 									}
364 
365 		//! Operator for Matrix4x4 -= Matrix4x4;
366 		inline_	Matrix4x4&			operator-=(const Matrix4x4& mat)
367 									{
368 										m[0][0]-=mat.m[0][0];	m[0][1]-=mat.m[0][1];	m[0][2]-=mat.m[0][2];	m[0][3]-=mat.m[0][3];
369 										m[1][0]-=mat.m[1][0];	m[1][1]-=mat.m[1][1];	m[1][2]-=mat.m[1][2];	m[1][3]-=mat.m[1][3];
370 										m[2][0]-=mat.m[2][0];	m[2][1]-=mat.m[2][1];	m[2][2]-=mat.m[2][2];	m[2][3]-=mat.m[2][3];
371 										m[3][0]-=mat.m[3][0];	m[3][1]-=mat.m[3][1];	m[3][2]-=mat.m[3][2];	m[3][3]-=mat.m[3][3];
372 										return	*this;
373 									}
374 
375 		//! Operator for Matrix4x4 *= Matrix4x4;
376 				Matrix4x4&			operator*=(const Matrix4x4& mat)
377 									{
378 										HPoint TempRow;
379 
380 										GetRow(0, TempRow);
381 										m[0][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
382 										m[0][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
383 										m[0][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
384 										m[0][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
385 
386 										GetRow(1, TempRow);
387 										m[1][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
388 										m[1][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
389 										m[1][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
390 										m[1][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
391 
392 										GetRow(2, TempRow);
393 										m[2][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
394 										m[2][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
395 										m[2][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
396 										m[2][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
397 
398 										GetRow(3, TempRow);
399 										m[3][0] = TempRow.x*mat.m[0][0] + TempRow.y*mat.m[1][0] + TempRow.z*mat.m[2][0] + TempRow.w*mat.m[3][0];
400 										m[3][1] = TempRow.x*mat.m[0][1] + TempRow.y*mat.m[1][1] + TempRow.z*mat.m[2][1] + TempRow.w*mat.m[3][1];
401 										m[3][2] = TempRow.x*mat.m[0][2] + TempRow.y*mat.m[1][2] + TempRow.z*mat.m[2][2] + TempRow.w*mat.m[3][2];
402 										m[3][3] = TempRow.x*mat.m[0][3] + TempRow.y*mat.m[1][3] + TempRow.z*mat.m[2][3] + TempRow.w*mat.m[3][3];
403 
404 										return	*this;
405 									}
406 
407 		//! Operator for Matrix4x4 *= float;
408 		inline_	Matrix4x4&		operator*=(float s)
409 								{
410 									m[0][0]*=s;	m[0][1]*=s;	m[0][2]*=s;	m[0][3]*=s;
411 									m[1][0]*=s;	m[1][1]*=s;	m[1][2]*=s;	m[1][3]*=s;
412 									m[2][0]*=s;	m[2][1]*=s;	m[2][2]*=s;	m[2][3]*=s;
413 									m[3][0]*=s;	m[3][1]*=s;	m[3][2]*=s;	m[3][3]*=s;
414 									return	*this;
415 								}
416 
417 		//! Operator for Matrix4x4 /= float;
418 		inline_	Matrix4x4&		operator/=(float s)
419 								{
420 									if(s)  s = 1.0f / s;
421 									m[0][0]*=s;	m[0][1]*=s;	m[0][2]*=s;	m[0][3]*=s;
422 									m[1][0]*=s;	m[1][1]*=s;	m[1][2]*=s;	m[1][3]*=s;
423 									m[2][0]*=s;	m[2][1]*=s;	m[2][2]*=s;	m[2][3]*=s;
424 									m[3][0]*=s;	m[3][1]*=s;	m[3][2]*=s;	m[3][3]*=s;
425 									return	*this;
426 								}
427 
428 		inline_	const HPoint&	operator[](int row)		const	{ return *(const HPoint*)&m[row][0];	}
429 		inline_	HPoint&			operator[](int row)				{ return *(HPoint*)&m[row][0];			}
430 
431 		public:
432 
433 				float			m[4][4];
434 	};
435 
436 	//! Quickly rotates & translates a vector, using the 4x3 part of a 4x4 matrix
TransformPoint4x3(Point & dest,const Point & source,const Matrix4x4 & rot)437 	inline_ void TransformPoint4x3(Point& dest, const Point& source, const Matrix4x4& rot)
438 	{
439 		dest.x = rot.m[3][0] + source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0];
440 		dest.y = rot.m[3][1] + source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1];
441 		dest.z = rot.m[3][2] + source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2];
442 	}
443 
444 	//! Quickly rotates a vector, using the 3x3 part of a 4x4 matrix
TransformPoint3x3(Point & dest,const Point & source,const Matrix4x4 & rot)445 	inline_ void TransformPoint3x3(Point& dest, const Point& source, const Matrix4x4& rot)
446 	{
447 		dest.x = source.x * rot.m[0][0] + source.y * rot.m[1][0] + source.z * rot.m[2][0];
448 		dest.y = source.x * rot.m[0][1] + source.y * rot.m[1][1] + source.z * rot.m[2][1];
449 		dest.z = source.x * rot.m[0][2] + source.y * rot.m[1][2] + source.z * rot.m[2][2];
450 	}
451 
452 	ICEMATHS_API void InvertPRMatrix(Matrix4x4& dest, const Matrix4x4& src);
453 
454 #endif // __ICEMATRIX4X4_H__
455 
456