PageRenderTime 28ms CodeModel.GetById 6ms app.highlight 17ms RepoModel.GetById 2ms app.codeStats 0ms

/indra/llmath/m4math.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 403 lines | 202 code | 67 blank | 134 comment | 24 complexity | 562c24543942fb453c5aaa0b507e4362 MD5 | raw file
  1/** 
  2 * @file m4math.h
  3 * @brief LLMatrix4 class header file.
  4 *
  5 * $LicenseInfo:firstyear=2000&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#ifndef LL_M4MATH_H
 28#define LL_M4MATH_H
 29
 30#include "v3math.h"
 31
 32class LLVector4;
 33class LLMatrix3;
 34class LLQuaternion;
 35
 36// NOTA BENE: Currently assuming a right-handed, x-forward, y-left, z-up universe
 37
 38// Us versus OpenGL:
 39
 40// Even though OpenGL uses column vectors and we use row vectors, we can plug our matrices
 41// directly into OpenGL.  This is because OpenGL numbers its matrices going columnwise:
 42//
 43// OpenGL indexing:          Our indexing:
 44// 0  4  8 12                [0][0] [0][1] [0][2] [0][3]
 45// 1  5  9 13                [1][0] [1][1] [1][2] [1][3]
 46// 2  6 10 14                [2][0] [2][1] [2][2] [2][3]
 47// 3  7 11 15                [3][0] [3][1] [3][2] [3][3]
 48//
 49// So when you're looking at OpenGL related matrices online, our matrices will be
 50// "transposed".  But our matrices can be plugged directly into OpenGL and work fine!
 51//
 52
 53// We're using row vectors - [vx, vy, vz, vw]
 54//
 55// There are several different ways of thinking of matrices, if you mix them up, you'll get very confused.
 56//
 57// One way to think about it is a matrix that takes the origin frame A
 58// and rotates it into B': i.e. A*M = B
 59//
 60//		Vectors:
 61//		f - forward axis of B expressed in A
 62//		l - left axis of B expressed in A
 63//		u - up axis of B expressed in A
 64//
 65//		|  0: fx  1: fy  2: fz  3:0 |
 66//  M = |  4: lx  5: ly  6: lz  7:0 |
 67//      |  8: ux  9: uy 10: uz 11:0 |
 68//      | 12: 0  13: 0  14:  0 15:1 |
 69//		
 70//
 71//
 72//
 73// Another way to think of matrices is matrix that takes a point p in frame A, and puts it into frame B:
 74// This is used most commonly for the modelview matrix.
 75//
 76// so p*M = p'
 77//
 78//		Vectors:
 79//      f - forward of frame B in frame A
 80//      l - left of frame B in frame A
 81//      u - up of frame B in frame A
 82//      o - origin of frame frame B in frame A
 83//
 84//		|  0: fx  1: lx  2: ux  3:0 |
 85//  M = |  4: fy  5: ly  6: uy  7:0 |
 86//      |  8: fz  9: lz 10: uz 11:0 |
 87//      | 12:-of 13:-ol 14:-ou 15:1 |
 88//
 89//		of, ol, and ou mean the component of the "global" origin o in the f axis, l axis, and u axis.
 90//
 91
 92static const U32 NUM_VALUES_IN_MAT4 = 4;
 93
 94class LLMatrix4
 95{
 96public:
 97	F32	mMatrix[NUM_VALUES_IN_MAT4][NUM_VALUES_IN_MAT4];
 98
 99	// Initializes Matrix to identity matrix
100	LLMatrix4()
101	{
102		setIdentity();
103	}
104	explicit LLMatrix4(const F32 *mat);								// Initializes Matrix to values in mat
105	explicit LLMatrix4(const LLMatrix3 &mat);						// Initializes Matrix to values in mat and sets position to (0,0,0)
106	explicit LLMatrix4(const LLQuaternion &q);						// Initializes Matrix with rotation q and sets position to (0,0,0)
107
108	LLMatrix4(const LLMatrix3 &mat, const LLVector4 &pos);	// Initializes Matrix to values in mat and pos
109
110	// These are really, really, inefficient as implemented! - djs
111	LLMatrix4(const LLQuaternion &q, const LLVector4 &pos);	// Initializes Matrix with rotation q and position pos
112	LLMatrix4(F32 angle,
113			  const LLVector4 &vec, 
114			  const LLVector4 &pos);						// Initializes Matrix with axis-angle and position
115	LLMatrix4(F32 angle, const LLVector4 &vec);				// Initializes Matrix with axis-angle and sets position to (0,0,0)
116	LLMatrix4(const F32 roll, const F32 pitch, const F32 yaw, 
117			  const LLVector4 &pos);						// Initializes Matrix with Euler angles
118	LLMatrix4(const F32 roll, const F32 pitch, const F32 yaw);				// Initializes Matrix with Euler angles
119
120	~LLMatrix4(void);										// Destructor
121
122	LLSD getValue() const;
123	void setValue(const LLSD&);
124
125	//////////////////////////////
126	//
127	// Matrix initializers - these replace any existing values in the matrix
128	//
129
130	void initRows(const LLVector4 &row0,
131				  const LLVector4 &row1,
132				  const LLVector4 &row2,
133				  const LLVector4 &row3);
134
135	// various useful matrix functions
136	const LLMatrix4& setIdentity();					// Load identity matrix
137	bool isIdentity() const;
138	const LLMatrix4& setZero();						// Clears matrix to all zeros.
139
140	const LLMatrix4& initRotation(const F32 angle, const F32 x, const F32 y, const F32 z);	// Calculate rotation matrix by rotating angle radians about (x, y, z)
141	const LLMatrix4& initRotation(const F32 angle, const LLVector4 &axis);	// Calculate rotation matrix for rotating angle radians about vec
142	const LLMatrix4& initRotation(const F32 roll, const F32 pitch, const F32 yaw);		// Calculate rotation matrix from Euler angles
143	const LLMatrix4& initRotation(const LLQuaternion &q);			// Set with Quaternion and position
144	
145	// Position Only
146	const LLMatrix4& initMatrix(const LLMatrix3 &mat); //
147	const LLMatrix4& initMatrix(const LLMatrix3 &mat, const LLVector4 &translation);
148
149	// These operation create a matrix that will rotate and translate by the
150	// specified amounts.
151	const LLMatrix4& initRotTrans(const F32 angle,
152								  const F32 rx, const F32 ry, const F32 rz,
153								  const F32 px, const F32 py, const F32 pz);
154
155	const LLMatrix4& initRotTrans(const F32 angle, const LLVector3 &axis, const LLVector3 &translation);	 // Rotation from axis angle + translation
156	const LLMatrix4& initRotTrans(const F32 roll, const F32 pitch, const F32 yaw, const LLVector4 &pos); // Rotation from Euler + translation
157	const LLMatrix4& initRotTrans(const LLQuaternion &q, const LLVector4 &pos);	// Set with Quaternion and position
158
159	const LLMatrix4& initScale(const LLVector3 &scale);
160
161	// Set all
162	const LLMatrix4& initAll(const LLVector3 &scale, const LLQuaternion &q, const LLVector3 &pos);	
163
164
165	///////////////////////////
166	//
167	// Matrix setters - set some properties without modifying others
168	//
169
170	const LLMatrix4& setTranslation(const F32 x, const F32 y, const F32 z);	// Sets matrix to translate by (x,y,z)
171
172	void setFwdRow(const LLVector3 &row);
173	void setLeftRow(const LLVector3 &row);
174	void setUpRow(const LLVector3 &row);
175
176	void setFwdCol(const LLVector3 &col);
177	void setLeftCol(const LLVector3 &col);
178	void setUpCol(const LLVector3 &col);
179
180	const LLMatrix4& setTranslation(const LLVector4 &translation);
181	const LLMatrix4& setTranslation(const LLVector3 &translation);
182
183	///////////////////////////
184	//
185	// Get properties of a matrix
186	//
187
188	F32			 determinant(void) const;						// Return determinant
189	LLQuaternion quaternion(void) const;			// Returns quaternion
190
191	LLVector4 getFwdRow4() const;
192	LLVector4 getLeftRow4() const;
193	LLVector4 getUpRow4() const;
194
195	LLMatrix3 getMat3() const;
196
197	const LLVector3& getTranslation() const { return *(LLVector3*)&mMatrix[3][0]; }
198
199	///////////////////////////
200	//
201	// Operations on an existing matrix
202	//
203
204	const LLMatrix4& transpose();						// Transpose LLMatrix4
205	const LLMatrix4& invert();						// Invert LLMatrix4
206
207	// Rotate existing matrix
208	// These are really, really, inefficient as implemented! - djs
209	const LLMatrix4& rotate(const F32 angle, const F32 x, const F32 y, const F32 z); 		// Rotate matrix by rotating angle radians about (x, y, z)
210	const LLMatrix4& rotate(const F32 angle, const LLVector4 &vec);		// Rotate matrix by rotating angle radians about vec
211	const LLMatrix4& rotate(const F32 roll, const F32 pitch, const F32 yaw);		// Rotate matrix by Euler angles
212	const LLMatrix4& rotate(const LLQuaternion &q);				// Rotate matrix by Quaternion
213
214	
215	// Translate existing matrix
216	const LLMatrix4& translate(const LLVector3 &vec);				// Translate matrix by (vec[VX], vec[VY], vec[VZ])
217	
218
219
220
221	///////////////////////
222	//
223	// Operators
224	//
225
226	//	friend inline LLMatrix4 operator*(const LLMatrix4 &a, const LLMatrix4 &b);		// Return a * b
227	friend LLVector4 operator*(const LLVector4 &a, const LLMatrix4 &b);		// Return transform of vector a by matrix b
228	friend const LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b);		// Return full transform of a by matrix b
229	friend LLVector4 rotate_vector(const LLVector4 &a, const LLMatrix4 &b);	// Rotates a but does not translate
230	friend LLVector3 rotate_vector(const LLVector3 &a, const LLMatrix4 &b);	// Rotates a but does not translate
231
232	friend bool operator==(const LLMatrix4 &a, const LLMatrix4 &b);			// Return a == b
233	friend bool operator!=(const LLMatrix4 &a, const LLMatrix4 &b);			// Return a != b
234	friend bool operator<(const LLMatrix4 &a, const LLMatrix4& b);			// Return a < b
235
236	friend const LLMatrix4& operator+=(LLMatrix4 &a, const LLMatrix4 &b);	// Return a + b
237	friend const LLMatrix4& operator-=(LLMatrix4 &a, const LLMatrix4 &b);	// Return a - b
238	friend const LLMatrix4& operator*=(LLMatrix4 &a, const LLMatrix4 &b);	// Return a * b
239	friend const LLMatrix4& operator*=(LLMatrix4 &a, const F32 &b);			// Return a * b
240
241	friend std::ostream&	 operator<<(std::ostream& s, const LLMatrix4 &a);	// Stream a
242};
243
244inline const LLMatrix4&	LLMatrix4::setIdentity()
245{
246	mMatrix[0][0] = 1.f;
247	mMatrix[0][1] = 0.f;
248	mMatrix[0][2] = 0.f;
249	mMatrix[0][3] = 0.f;
250
251	mMatrix[1][0] = 0.f;
252	mMatrix[1][1] = 1.f;
253	mMatrix[1][2] = 0.f;
254	mMatrix[1][3] = 0.f;
255
256	mMatrix[2][0] = 0.f;
257	mMatrix[2][1] = 0.f;
258	mMatrix[2][2] = 1.f;
259	mMatrix[2][3] = 0.f;
260
261	mMatrix[3][0] = 0.f;
262	mMatrix[3][1] = 0.f;
263	mMatrix[3][2] = 0.f;
264	mMatrix[3][3] = 1.f;
265	return (*this);
266}
267
268inline bool LLMatrix4::isIdentity() const
269{
270	return
271		mMatrix[0][0] == 1.f &&
272		mMatrix[0][1] == 0.f &&
273		mMatrix[0][2] == 0.f &&
274		mMatrix[0][3] == 0.f &&
275
276		mMatrix[1][0] == 0.f &&
277		mMatrix[1][1] == 1.f &&
278		mMatrix[1][2] == 0.f &&
279		mMatrix[1][3] == 0.f &&
280
281		mMatrix[2][0] == 0.f &&
282		mMatrix[2][1] == 0.f &&
283		mMatrix[2][2] == 1.f &&
284		mMatrix[2][3] == 0.f &&
285
286		mMatrix[3][0] == 0.f &&
287		mMatrix[3][1] == 0.f &&
288		mMatrix[3][2] == 0.f &&
289		mMatrix[3][3] == 1.f;
290}
291
292
293/*
294inline LLMatrix4 operator*(const LLMatrix4 &a, const LLMatrix4 &b)
295{
296	U32		i, j;
297	LLMatrix4	mat;
298	for (i = 0; i < NUM_VALUES_IN_MAT4; i++)
299	{
300		for (j = 0; j < NUM_VALUES_IN_MAT4; j++)
301		{
302			mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] + 
303							    a.mMatrix[j][1] * b.mMatrix[1][i] + 
304							    a.mMatrix[j][2] * b.mMatrix[2][i] +
305								a.mMatrix[j][3] * b.mMatrix[3][i];
306		}
307	}
308	return mat;
309}
310*/
311
312
313inline const LLMatrix4& operator*=(LLMatrix4 &a, const LLMatrix4 &b)
314{
315	U32		i, j;
316	LLMatrix4	mat;
317	for (i = 0; i < NUM_VALUES_IN_MAT4; i++)
318	{
319		for (j = 0; j < NUM_VALUES_IN_MAT4; j++)
320		{
321			mat.mMatrix[j][i] = a.mMatrix[j][0] * b.mMatrix[0][i] + 
322							    a.mMatrix[j][1] * b.mMatrix[1][i] + 
323							    a.mMatrix[j][2] * b.mMatrix[2][i] +
324								a.mMatrix[j][3] * b.mMatrix[3][i];
325		}
326	}
327	a = mat;
328	return a;
329}
330
331inline const LLMatrix4& operator*=(LLMatrix4 &a, const F32 &b)
332{
333	U32		i, j;
334	LLMatrix4	mat;
335	for (i = 0; i < NUM_VALUES_IN_MAT4; i++)
336	{
337		for (j = 0; j < NUM_VALUES_IN_MAT4; j++)
338		{
339			mat.mMatrix[j][i] = a.mMatrix[j][i] * b;
340		}
341	}
342	a = mat;
343	return a;
344}
345
346inline const LLMatrix4& operator+=(LLMatrix4 &a, const LLMatrix4 &b)
347{
348	LLMatrix4 mat;
349	U32		i, j;
350	for (i = 0; i < NUM_VALUES_IN_MAT4; i++)
351	{
352		for (j = 0; j < NUM_VALUES_IN_MAT4; j++)
353		{
354			mat.mMatrix[j][i] = a.mMatrix[j][i] + b.mMatrix[j][i];
355		}
356	}
357	a = mat;
358	return a;
359}
360
361inline const LLMatrix4& operator-=(LLMatrix4 &a, const LLMatrix4 &b)
362{
363	LLMatrix4 mat;
364	U32		i, j;
365	for (i = 0; i < NUM_VALUES_IN_MAT4; i++)
366	{
367		for (j = 0; j < NUM_VALUES_IN_MAT4; j++)
368		{
369			mat.mMatrix[j][i] = a.mMatrix[j][i] - b.mMatrix[j][i];
370		}
371	}
372	a = mat;
373	return a;
374}
375
376// Operates "to the left" on row-vector a
377//
378// When avatar vertex programs are off, this function is a hot spot in profiles
379// due to software skinning in LLViewerJointMesh::updateGeometry().  JC
380inline const LLVector3 operator*(const LLVector3 &a, const LLMatrix4 &b)
381{
382	// This is better than making a temporary LLVector3.  This eliminates an
383	// unnecessary LLVector3() constructor and also helps the compiler to
384	// realize that the output floats do not alias the input floats, hence
385	// eliminating redundant loads of a.mV[0], etc.  JC
386	return LLVector3(a.mV[VX] * b.mMatrix[VX][VX] + 
387					 a.mV[VY] * b.mMatrix[VY][VX] + 
388					 a.mV[VZ] * b.mMatrix[VZ][VX] +
389					 b.mMatrix[VW][VX],
390					 
391					 a.mV[VX] * b.mMatrix[VX][VY] + 
392					 a.mV[VY] * b.mMatrix[VY][VY] + 
393					 a.mV[VZ] * b.mMatrix[VZ][VY] +
394					 b.mMatrix[VW][VY],
395					 
396					 a.mV[VX] * b.mMatrix[VX][VZ] + 
397					 a.mV[VY] * b.mMatrix[VY][VZ] + 
398					 a.mV[VZ] * b.mMatrix[VZ][VZ] +
399					 b.mMatrix[VW][VZ]);
400}
401
402#endif
403