PageRenderTime 38ms CodeModel.GetById 2ms app.highlight 31ms RepoModel.GetById 1ms app.codeStats 1ms

/indra/llmath/xform.h

https://bitbucket.org/lindenlab/viewer-beta/
C++ Header | 315 lines | 247 code | 36 blank | 32 comment | 26 complexity | 113f537a2b87c0845a39ece666bb0094 MD5 | raw file
  1/** 
  2 * @file xform.h
  3 *
  4 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  5 * Second Life Viewer Source Code
  6 * Copyright (C) 2010, Linden Research, Inc.
  7 * 
  8 * This library is free software; you can redistribute it and/or
  9 * modify it under the terms of the GNU Lesser General Public
 10 * License as published by the Free Software Foundation;
 11 * version 2.1 of the License only.
 12 * 
 13 * This library is distributed in the hope that it will be useful,
 14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16 * Lesser General Public License for more details.
 17 * 
 18 * You should have received a copy of the GNU Lesser General Public
 19 * License along with this library; if not, write to the Free Software
 20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 21 * 
 22 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 23 * $/LicenseInfo$
 24 */
 25
 26#ifndef LL_XFORM_H
 27#define LL_XFORM_H
 28
 29#include "v3math.h"
 30#include "m4math.h"
 31#include "llquaternion.h"
 32
 33const F32 MAX_OBJECT_Z 		= 4096.f; // should match REGION_HEIGHT_METERS, Pre-havok4: 768.f
 34const F32 MIN_OBJECT_Z 		= -256.f;
 35const F32 DEFAULT_MAX_PRIM_SCALE = 64.f;
 36const F32 DEFAULT_MAX_PRIM_SCALE_NO_MESH = 10.f;
 37const F32 MIN_PRIM_SCALE = 0.01f;
 38const F32 MAX_PRIM_SCALE = 65536.f;	// something very high but not near FLT_MAX
 39
 40class LLXform
 41{
 42protected:
 43	LLVector3	  mPosition;
 44	LLQuaternion  mRotation; 
 45	LLVector3	  mScale;
 46	
 47	//RN: TODO: move these world transform members to LLXformMatrix
 48	// as they are *never* updated or accessed in the base class
 49	LLVector3	  mWorldPosition;
 50	LLQuaternion  mWorldRotation;
 51
 52	LLXform*      mParent;
 53	U32			  mChanged;
 54
 55	BOOL		  mScaleChildOffset;
 56
 57public:
 58	typedef enum e_changed_flags
 59	{
 60		UNCHANGED  	= 0x00,
 61		TRANSLATED 	= 0x01,
 62		ROTATED		= 0x02,
 63		SCALED		= 0x04,
 64		SHIFTED		= 0x08,
 65		GEOMETRY	= 0x10,
 66		TEXTURE		= 0x20,
 67		MOVED       = TRANSLATED|ROTATED|SCALED,
 68		SILHOUETTE	= 0x40,
 69		ALL_CHANGED = 0x7f
 70	}EChangedFlags;
 71
 72	void init()
 73	{
 74		mParent  = NULL;
 75		mChanged = UNCHANGED;
 76		mPosition.setVec(0,0,0);
 77		mRotation.loadIdentity();
 78		mScale.   setVec(1,1,1);
 79		mWorldPosition.clearVec();
 80		mWorldRotation.loadIdentity();
 81		mScaleChildOffset = FALSE;
 82	}
 83
 84	 LLXform();
 85	virtual ~LLXform();
 86
 87	void getLocalMat4(LLMatrix4 &mat) const { mat.initAll(mScale, mRotation, mPosition); }
 88
 89	inline BOOL setParent(LLXform *parent);
 90
 91	inline void setPosition(const LLVector3& pos);
 92	inline void setPosition(const F32 x, const F32 y, const F32 z);
 93	inline void setPositionX(const F32 x);
 94	inline void setPositionY(const F32 y);
 95	inline void setPositionZ(const F32 z);
 96	inline void addPosition(const LLVector3& pos);
 97
 98
 99	inline void setScale(const LLVector3& scale);
100	inline void setScale(const F32 x, const F32 y, const F32 z);
101	inline void setRotation(const LLQuaternion& rot);
102	inline void setRotation(const F32 x, const F32 y, const F32 z);
103	inline void setRotation(const F32 x, const F32 y, const F32 z, const F32 s);
104
105	// Above functions must be inline for speed, but also
106	// need to emit warnings.  llwarns causes inline LLError::CallSite
107	// static objects that make more work for the linker.
108	// Avoid inline llwarns by calling this function.
109	void warn(const char* const msg);
110	
111	void 		setChanged(const U32 bits)					{ mChanged |= bits; }
112	BOOL		isChanged() const							{ return mChanged; }
113	BOOL 		isChanged(const U32 bits) const				{ return mChanged & bits; }
114	void 		clearChanged()								{ mChanged = 0; }
115	void        clearChanged(U32 bits)                      { mChanged &= ~bits; }
116
117	void		setScaleChildOffset(BOOL scale)				{ mScaleChildOffset = scale; }
118	BOOL		getScaleChildOffset()						{ return mScaleChildOffset; }
119
120	LLXform* getParent() const { return mParent; }
121	LLXform* getRoot() const;
122	virtual BOOL isRoot() const;
123	virtual BOOL isRootEdit() const;
124
125	const LLVector3&	getPosition()  const	    { return mPosition; }
126	const LLVector3&	getScale() const			{ return mScale; }
127	const LLQuaternion& getRotation() const			{ return mRotation; }
128	const LLVector3&	getPositionW() const		{ return mWorldPosition; }
129	const LLQuaternion& getWorldRotation() const	{ return mWorldRotation; }
130	const LLVector3&	getWorldPosition() const	{ return mWorldPosition; }
131};
132
133class LLXformMatrix : public LLXform
134{
135public:
136	LLXformMatrix() : LLXform() {};
137	virtual ~LLXformMatrix();
138
139	const LLMatrix4&    getWorldMatrix() const      { return mWorldMatrix; }
140	void setWorldMatrix (const LLMatrix4& mat)   { mWorldMatrix = mat; }
141
142	void init()
143	{
144		mWorldMatrix.setIdentity();
145		mMin.clearVec();
146		mMax.clearVec();
147
148		LLXform::init();
149	}
150
151	void update();
152	void updateMatrix(BOOL update_bounds = TRUE);
153	void getMinMax(LLVector3& min,LLVector3& max) const;
154
155protected:
156	LLMatrix4	mWorldMatrix;
157	LLVector3	mMin;
158	LLVector3	mMax;
159
160};
161
162BOOL LLXform::setParent(LLXform* parent)
163{
164	// Validate and make sure we're not creating a loop
165	if (parent == mParent)
166	{
167		return TRUE;
168	}
169	if (parent)
170	{
171		LLXform *cur_par = parent->mParent;
172		while (cur_par)
173		{
174			if (cur_par == this)
175			{
176				//warn("LLXform::setParent Creating loop when setting parent!");
177				return FALSE;
178			}
179			cur_par = cur_par->mParent;
180		}
181	}
182	mParent = parent;
183	return TRUE;
184}
185
186void LLXform::setPosition(const LLVector3& pos)			
187{
188	setChanged(TRANSLATED);
189	if (pos.isFinite())
190		mPosition = pos; 
191	else
192	{
193		mPosition.clearVec();
194		warn("Non Finite in LLXform::setPosition(LLVector3)");
195	}
196}
197
198void LLXform::setPosition(const F32 x, const F32 y, const F32 z)
199{
200	setChanged(TRANSLATED);
201	if (llfinite(x) && llfinite(y) && llfinite(z))
202		mPosition.setVec(x,y,z); 
203	else
204	{
205		mPosition.clearVec();
206		warn("Non Finite in LLXform::setPosition(F32,F32,F32)");
207	}
208}
209
210void LLXform::setPositionX(const F32 x)
211{ 
212	setChanged(TRANSLATED);
213	if (llfinite(x))
214		mPosition.mV[VX] = x; 
215	else
216	{
217		mPosition.mV[VX] = 0.f;
218		warn("Non Finite in LLXform::setPositionX");
219	}
220}
221
222void LLXform::setPositionY(const F32 y)
223{ 
224	setChanged(TRANSLATED);
225	if (llfinite(y))
226		mPosition.mV[VY] = y; 
227	else
228	{
229		mPosition.mV[VY] = 0.f;
230		warn("Non Finite in LLXform::setPositionY");
231	}
232}
233
234void LLXform::setPositionZ(const F32 z)
235{ 
236	setChanged(TRANSLATED);
237	if (llfinite(z))
238		mPosition.mV[VZ] = z; 
239	else
240	{
241		mPosition.mV[VZ] = 0.f;
242		warn("Non Finite in LLXform::setPositionZ");
243	}
244}
245
246void LLXform::addPosition(const LLVector3& pos)
247{ 
248	setChanged(TRANSLATED);
249	if (pos.isFinite())
250		mPosition += pos; 
251	else
252		warn("Non Finite in LLXform::addPosition");
253}
254
255void LLXform::setScale(const LLVector3& scale)
256{ 
257	setChanged(SCALED);
258	if (scale.isFinite())
259		mScale = scale; 
260	else
261	{
262		mScale.setVec(1.f, 1.f, 1.f);
263		warn("Non Finite in LLXform::setScale");
264	}
265}
266void LLXform::setScale(const F32 x, const F32 y, const F32 z)
267{ 
268	setChanged(SCALED);
269	if (llfinite(x) && llfinite(y) && llfinite(z))
270		mScale.setVec(x,y,z); 
271	else
272	{
273		mScale.setVec(1.f, 1.f, 1.f);
274		warn("Non Finite in LLXform::setScale");
275	}
276}
277void LLXform::setRotation(const LLQuaternion& rot)
278{ 
279	setChanged(ROTATED);
280	if (rot.isFinite())
281		mRotation = rot; 
282	else
283	{
284		mRotation.loadIdentity();
285		warn("Non Finite in LLXform::setRotation");
286	}
287}
288void LLXform::setRotation(const F32 x, const F32 y, const F32 z) 
289{ 
290	setChanged(ROTATED);
291	if (llfinite(x) && llfinite(y) && llfinite(z))
292	{
293		mRotation.setQuat(x,y,z); 
294	}
295	else
296	{
297		mRotation.loadIdentity();
298		warn("Non Finite in LLXform::setRotation");
299	}
300}
301void LLXform::setRotation(const F32 x, const F32 y, const F32 z, const F32 s) 
302{ 
303	setChanged(ROTATED);
304	if (llfinite(x) && llfinite(y) && llfinite(z) && llfinite(s))
305	{
306		mRotation.mQ[VX] = x; mRotation.mQ[VY] = y; mRotation.mQ[VZ] = z; mRotation.mQ[VS] = s; 
307	}
308	else
309	{
310		mRotation.loadIdentity();
311		warn("Non Finite in LLXform::setRotation");
312	}
313}
314
315#endif