PageRenderTime 408ms CodeModel.GetById 121ms app.highlight 100ms RepoModel.GetById 182ms app.codeStats 0ms

/indra/llcharacter/lljoint.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 562 lines | 321 code | 88 blank | 153 comment | 37 complexity | 3e4df5466e602246ddef2933a4bb1013 MD5 | raw file
  1/** 
  2 * @file lljoint.cpp
  3 * @brief Implementation of LLJoint class.
  4 *
  5 * $LicenseInfo:firstyear=2001&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//-----------------------------------------------------------------------------
 28// Header Files
 29//-----------------------------------------------------------------------------
 30#include "linden_common.h"
 31
 32#include "lljoint.h"
 33
 34#include "llmath.h"
 35
 36S32 LLJoint::sNumUpdates = 0;
 37S32 LLJoint::sNumTouches = 0;
 38
 39//-----------------------------------------------------------------------------
 40// LLJoint()
 41// Class Constructor
 42//-----------------------------------------------------------------------------
 43LLJoint::LLJoint()
 44{
 45	mName = "unnamed";
 46	mParent = NULL;
 47	mXform.setScaleChildOffset(TRUE);
 48	mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
 49	mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY;
 50	mUpdateXform = TRUE;
 51	mJointNum = -1;
 52	touch();
 53	mResetAfterRestoreOldXform = false;
 54}
 55
 56
 57//-----------------------------------------------------------------------------
 58// LLJoint()
 59// Class Constructor
 60//-----------------------------------------------------------------------------
 61LLJoint::LLJoint(const std::string &name, LLJoint *parent)
 62{
 63	mName = "unnamed";
 64	mParent = NULL;
 65	mXform.setScaleChildOffset(TRUE);
 66	mXform.setScale(LLVector3(1.0f, 1.0f, 1.0f));
 67	mDirtyFlags = MATRIX_DIRTY | ROTATION_DIRTY | POSITION_DIRTY;
 68	mUpdateXform = FALSE;
 69	mJointNum = 0;
 70
 71	setName(name);
 72	if (parent)
 73	{
 74		parent->addChild( this );
 75	}
 76	touch();
 77}
 78
 79//-----------------------------------------------------------------------------
 80// ~LLJoint()
 81// Class Destructor
 82//-----------------------------------------------------------------------------
 83LLJoint::~LLJoint()
 84{
 85	if (mParent)
 86	{
 87		mParent->removeChild( this );
 88	}
 89	removeAllChildren();
 90}
 91
 92
 93//-----------------------------------------------------------------------------
 94// setup()
 95//-----------------------------------------------------------------------------
 96void LLJoint::setup(const std::string &name, LLJoint *parent)
 97{
 98	setName(name);
 99	if (parent)
100	{
101		parent->addChild( this );
102	}
103}
104
105//-----------------------------------------------------------------------------
106// touch()
107// Sets all dirty flags for all children, recursively.
108//-----------------------------------------------------------------------------
109void LLJoint::touch(U32 flags)
110{
111	if ((flags | mDirtyFlags) != mDirtyFlags)
112	{
113		sNumTouches++;
114		mDirtyFlags |= flags;
115		U32 child_flags = flags;
116		if (flags & ROTATION_DIRTY)
117		{
118			child_flags |= POSITION_DIRTY;
119		}
120
121		for (child_list_t::iterator iter = mChildren.begin();
122			 iter != mChildren.end(); ++iter)
123		{
124			LLJoint* joint = *iter;
125			joint->touch(child_flags);
126		}
127	}
128}
129
130//-----------------------------------------------------------------------------
131// getRoot()
132//-----------------------------------------------------------------------------
133LLJoint *LLJoint::getRoot()
134{
135	if ( getParent() == NULL )
136	{
137		return this;
138	}
139	return getParent()->getRoot();
140}
141
142
143//-----------------------------------------------------------------------------
144// findJoint()
145//-----------------------------------------------------------------------------
146LLJoint *LLJoint::findJoint( const std::string &name )
147{
148	if (name == getName())
149		return this;
150
151	for (child_list_t::iterator iter = mChildren.begin();
152		 iter != mChildren.end(); ++iter)
153	{
154		LLJoint* joint = *iter;
155		LLJoint *found = joint->findJoint(name);
156		if (found)
157		{
158			return found;
159		}
160	}
161
162	return NULL;	
163}
164
165
166//--------------------------------------------------------------------
167// addChild()
168//--------------------------------------------------------------------
169void LLJoint::addChild(LLJoint* joint)
170{
171	if (joint->mParent)
172		joint->mParent->removeChild(joint);
173
174	mChildren.push_back(joint);
175	joint->mXform.setParent(&mXform);
176	joint->mParent = this;	
177	joint->touch();
178}
179
180
181//--------------------------------------------------------------------
182// removeChild()
183//--------------------------------------------------------------------
184void LLJoint::removeChild(LLJoint* joint)
185{
186	child_list_t::iterator iter = std::find(mChildren.begin(), mChildren.end(), joint);
187	if (iter != mChildren.end())
188	{
189		mChildren.erase(iter);
190	
191		joint->mXform.setParent(NULL);
192		joint->mParent = NULL;
193		joint->touch();
194	}
195}
196
197
198//--------------------------------------------------------------------
199// removeAllChildren()
200//--------------------------------------------------------------------
201void LLJoint::removeAllChildren()
202{
203	for (child_list_t::iterator iter = mChildren.begin();
204		 iter != mChildren.end();)
205	{
206		child_list_t::iterator curiter = iter++;
207		LLJoint* joint = *curiter;
208		mChildren.erase(curiter);
209		joint->mXform.setParent(NULL);
210		joint->mParent = NULL;
211		joint->touch();
212	}
213}
214
215
216//--------------------------------------------------------------------
217// getPosition()
218//--------------------------------------------------------------------
219const LLVector3& LLJoint::getPosition()
220{
221	return mXform.getPosition();
222}
223
224
225//--------------------------------------------------------------------
226// setPosition()
227//--------------------------------------------------------------------
228void LLJoint::setPosition( const LLVector3& pos )
229{
230//	if (mXform.getPosition() != pos)
231	{
232		mXform.setPosition(pos);
233		touch(MATRIX_DIRTY | POSITION_DIRTY);
234	}
235}
236
237
238//--------------------------------------------------------------------
239// setPosition()
240//--------------------------------------------------------------------
241void LLJoint::setDefaultFromCurrentXform( void )
242{
243	mDefaultXform = mXform;
244	touch(MATRIX_DIRTY | POSITION_DIRTY);
245	
246}
247
248//--------------------------------------------------------------------
249// storeCurrentXform()
250//--------------------------------------------------------------------
251void LLJoint::storeCurrentXform( const LLVector3& pos )
252{
253	mOldXform = mXform;
254	mResetAfterRestoreOldXform = true;
255	setPosition( pos );
256}
257//--------------------------------------------------------------------
258// restoreOldXform()
259//--------------------------------------------------------------------
260void LLJoint::restoreOldXform( void )
261{
262	mResetAfterRestoreOldXform = false;
263	mXform = mOldXform;
264}
265//--------------------------------------------------------------------
266// restoreOldXform()
267//--------------------------------------------------------------------
268void LLJoint::restoreToDefaultXform( void )
269{	
270	mXform = mDefaultXform;
271	setPosition( mXform.getPosition() );	
272}
273
274//--------------------------------------------------------------------
275// getWorldPosition()
276//--------------------------------------------------------------------
277LLVector3 LLJoint::getWorldPosition()
278{
279	updateWorldPRSParent();
280	return mXform.getWorldPosition();
281}
282
283//-----------------------------------------------------------------------------
284// getLastWorldPosition()
285//-----------------------------------------------------------------------------
286LLVector3 LLJoint::getLastWorldPosition()
287{
288	return mXform.getWorldPosition();
289}
290
291
292//--------------------------------------------------------------------
293// setWorldPosition()
294//--------------------------------------------------------------------
295void LLJoint::setWorldPosition( const LLVector3& pos )
296{
297	if (mParent == NULL)
298	{
299		this->setPosition( pos );
300		return;
301	}
302
303	LLMatrix4 temp_matrix = getWorldMatrix();
304	temp_matrix.mMatrix[VW][VX] = pos.mV[VX];
305	temp_matrix.mMatrix[VW][VY] = pos.mV[VY];
306	temp_matrix.mMatrix[VW][VZ] = pos.mV[VZ];
307
308	LLMatrix4 parentWorldMatrix = mParent->getWorldMatrix();
309	LLMatrix4 invParentWorldMatrix = parentWorldMatrix.invert();
310
311	temp_matrix *= invParentWorldMatrix;
312
313	LLVector3 localPos(	temp_matrix.mMatrix[VW][VX],
314						temp_matrix.mMatrix[VW][VY],
315						temp_matrix.mMatrix[VW][VZ] );
316
317	setPosition( localPos );
318}
319
320
321//--------------------------------------------------------------------
322// mXform.getRotation()
323//--------------------------------------------------------------------
324const LLQuaternion& LLJoint::getRotation()
325{
326	return mXform.getRotation();
327}
328
329
330//--------------------------------------------------------------------
331// setRotation()
332//--------------------------------------------------------------------
333void LLJoint::setRotation( const LLQuaternion& rot )
334{
335	if (rot.isFinite())
336	{
337	//	if (mXform.getRotation() != rot)
338		{
339			mXform.setRotation(rot);
340			touch(MATRIX_DIRTY | ROTATION_DIRTY);
341		}
342	}
343}
344
345
346//--------------------------------------------------------------------
347// getWorldRotation()
348//--------------------------------------------------------------------
349LLQuaternion LLJoint::getWorldRotation()
350{
351	updateWorldPRSParent();
352
353	return mXform.getWorldRotation();
354}
355
356//-----------------------------------------------------------------------------
357// getLastWorldRotation()
358//-----------------------------------------------------------------------------
359LLQuaternion LLJoint::getLastWorldRotation()
360{
361	return mXform.getWorldRotation();
362}
363
364//--------------------------------------------------------------------
365// setWorldRotation()
366//--------------------------------------------------------------------
367void LLJoint::setWorldRotation( const LLQuaternion& rot )
368{
369	if (mParent == NULL)
370	{
371		this->setRotation( rot );
372		return;
373	}
374
375	LLMatrix4 temp_mat(rot);
376
377	LLMatrix4 parentWorldMatrix = mParent->getWorldMatrix();
378	parentWorldMatrix.mMatrix[VW][VX] = 0;
379	parentWorldMatrix.mMatrix[VW][VY] = 0;
380	parentWorldMatrix.mMatrix[VW][VZ] = 0;
381
382	LLMatrix4 invParentWorldMatrix = parentWorldMatrix.invert();
383
384	temp_mat *= invParentWorldMatrix;
385
386	setRotation(LLQuaternion(temp_mat));
387}
388
389
390//--------------------------------------------------------------------
391// getScale()
392//--------------------------------------------------------------------
393const LLVector3& LLJoint::getScale()
394{
395	return mXform.getScale();
396}
397
398//--------------------------------------------------------------------
399// setScale()
400//--------------------------------------------------------------------
401void LLJoint::setScale( const LLVector3& scale )
402{
403//	if (mXform.getScale() != scale)
404	{
405		mXform.setScale(scale);
406		touch();
407	}
408
409}
410
411
412
413//--------------------------------------------------------------------
414// getWorldMatrix()
415//--------------------------------------------------------------------
416const LLMatrix4 &LLJoint::getWorldMatrix()
417{
418	updateWorldMatrixParent();
419
420	return mXform.getWorldMatrix();
421}
422
423
424//--------------------------------------------------------------------
425// setWorldMatrix()
426//--------------------------------------------------------------------
427void LLJoint::setWorldMatrix( const LLMatrix4& mat )
428{
429llinfos << "WARNING: LLJoint::setWorldMatrix() not correctly implemented yet" << llendl;
430	// extract global translation
431	LLVector3 trans(	mat.mMatrix[VW][VX],
432						mat.mMatrix[VW][VY],
433						mat.mMatrix[VW][VZ] );
434
435	// extract global rotation
436	LLQuaternion rot( mat );
437
438	setWorldPosition( trans );
439	setWorldRotation( rot );
440}
441
442//-----------------------------------------------------------------------------
443// updateWorldMatrixParent()
444//-----------------------------------------------------------------------------
445void LLJoint::updateWorldMatrixParent()
446{
447	if (mDirtyFlags & MATRIX_DIRTY)
448	{
449		LLJoint *parent = getParent();
450		if (parent)
451		{
452			parent->updateWorldMatrixParent();
453		}
454		updateWorldMatrix();
455	}
456}
457
458//-----------------------------------------------------------------------------
459// updateWorldPRSParent()
460//-----------------------------------------------------------------------------
461void LLJoint::updateWorldPRSParent()
462{
463	if (mDirtyFlags & (ROTATION_DIRTY | POSITION_DIRTY))
464	{
465		LLJoint *parent = getParent();
466		if (parent)
467		{
468			parent->updateWorldPRSParent();
469		}
470
471		mXform.update();
472		mDirtyFlags &= ~(ROTATION_DIRTY | POSITION_DIRTY);
473	}
474}
475
476//-----------------------------------------------------------------------------
477// updateWorldMatrixChildren()
478//-----------------------------------------------------------------------------
479void LLJoint::updateWorldMatrixChildren()
480{	
481	if (!this->mUpdateXform) return;
482
483	if (mDirtyFlags & MATRIX_DIRTY)
484	{
485		updateWorldMatrix();
486	}
487	for (child_list_t::iterator iter = mChildren.begin();
488		 iter != mChildren.end(); ++iter)
489	{
490		LLJoint* joint = *iter;
491		joint->updateWorldMatrixChildren();
492	}
493}
494
495//-----------------------------------------------------------------------------
496// updateWorldMatrix()
497//-----------------------------------------------------------------------------
498void LLJoint::updateWorldMatrix()
499{
500	if (mDirtyFlags & MATRIX_DIRTY)
501	{
502		sNumUpdates++;
503		mXform.updateMatrix(FALSE);
504		mDirtyFlags = 0x0;
505	}
506}
507
508//--------------------------------------------------------------------
509// getSkinOffset()
510//--------------------------------------------------------------------
511const LLVector3 &LLJoint::getSkinOffset()
512{
513	return mSkinOffset;
514}
515
516
517//--------------------------------------------------------------------
518// setSkinOffset()
519//--------------------------------------------------------------------
520void LLJoint::setSkinOffset( const LLVector3& offset )
521{
522	mSkinOffset = offset;
523}
524
525
526//-----------------------------------------------------------------------------
527// clampRotation()
528//-----------------------------------------------------------------------------
529void LLJoint::clampRotation(LLQuaternion old_rot, LLQuaternion new_rot)
530{
531	LLVector3 main_axis(1.f, 0.f, 0.f);
532
533	for (child_list_t::iterator iter = mChildren.begin();
534		 iter != mChildren.end(); ++iter)
535	{
536		LLJoint* joint = *iter;
537		if (joint->isAnimatable())
538		{
539			main_axis = joint->getPosition();
540			main_axis.normVec();
541			// only care about first animatable child
542			break;
543		}
544	}
545
546	// 2003.03.26 - This code was just using up cpu cycles. AB
547
548//	LLVector3 old_axis = main_axis * old_rot;
549//	LLVector3 new_axis = main_axis * new_rot;
550
551//	for (S32 i = 0; i < mConstraintSilhouette.count() - 1; i++)
552//	{
553//		LLVector3 vert1 = mConstraintSilhouette[i];
554//		LLVector3 vert2 = mConstraintSilhouette[i + 1];
555
556		// figure out how to clamp rotation to line on 3-sphere
557
558//	}
559}
560
561// End
562