PageRenderTime 63ms CodeModel.GetById 27ms app.highlight 31ms RepoModel.GetById 2ms app.codeStats 0ms

/indra/llcharacter/llheadrotmotion.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 532 lines | 345 code | 88 blank | 99 comment | 38 complexity | ddf87e2edad01b83ac823a2a73cb892a MD5 | raw file
  1/** 
  2 * @file llheadrotmotion.cpp
  3 * @brief Implementation of LLHeadRotMotion 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 "llheadrotmotion.h"
 33#include "llcharacter.h"
 34#include "llrand.h"
 35#include "m3math.h"
 36#include "v3dmath.h"
 37#include "llcriticaldamp.h"
 38
 39//-----------------------------------------------------------------------------
 40// Constants
 41//-----------------------------------------------------------------------------
 42const F32 TORSO_LAG	= 0.35f;	// torso rotation factor
 43const F32 NECK_LAG = 0.5f;		// neck rotation factor
 44const F32 HEAD_LOOKAT_LAG_HALF_LIFE	= 0.15f;		// half-life of lookat targeting for head
 45const F32 TORSO_LOOKAT_LAG_HALF_LIFE	= 0.27f;		// half-life of lookat targeting for torso
 46const F32 EYE_LOOKAT_LAG_HALF_LIFE = 0.06f;		// half-life of lookat targeting for eye
 47const F32 HEAD_ROTATION_CONSTRAINT = F_PI_BY_TWO * 0.8f;	// limit angle for head rotation
 48
 49const F32 MIN_HEAD_LOOKAT_DISTANCE = 0.3f;	// minimum distance from head before we turn to look at it
 50const F32 MAX_TIME_DELTA = 2.f; //max two seconds a frame for calculating interpolation
 51const F32 EYE_JITTER_MIN_TIME = 0.3f; // min amount of time between eye "jitter" motions
 52const F32 EYE_JITTER_MAX_TIME = 2.5f; // max amount of time between eye "jitter" motions
 53const F32 EYE_JITTER_MAX_YAW = 0.08f; // max yaw of eye jitter motion
 54const F32 EYE_JITTER_MAX_PITCH = 0.015f; // max pitch of eye jitter motion
 55const F32 EYE_LOOK_AWAY_MIN_TIME = 5.f; // min amount of time between eye "look away" motions
 56const F32 EYE_LOOK_AWAY_MAX_TIME = 15.f; // max amount of time between eye "look away" motions
 57const F32 EYE_LOOK_BACK_MIN_TIME = 1.f; // min amount of time before looking back after looking away
 58const F32 EYE_LOOK_BACK_MAX_TIME = 5.f; // max amount of time before looking back after looking away
 59const F32 EYE_LOOK_AWAY_MAX_YAW = 0.15f; // max yaw of eye look away motion
 60const F32 EYE_LOOK_AWAY_MAX_PITCH = 0.12f; // max pitch of look away motion
 61const F32 EYE_ROT_LIMIT_ANGLE = F_PI_BY_TWO * 0.3f; //max angle in radians for eye rotation
 62
 63const F32 EYE_BLINK_MIN_TIME = 0.5f; // minimum amount of time between blinks
 64const F32 EYE_BLINK_MAX_TIME = 8.f;	// maximum amount of time between blinks
 65const F32 EYE_BLINK_CLOSE_TIME = 0.03f; // how long the eye stays closed in a blink
 66const F32 EYE_BLINK_SPEED = 0.015f;		// seconds it takes for a eye open/close movement
 67const F32 EYE_BLINK_TIME_DELTA = 0.005f; // time between one eye starting a blink and the other following
 68
 69//-----------------------------------------------------------------------------
 70// LLHeadRotMotion()
 71// Class Constructor
 72//-----------------------------------------------------------------------------
 73LLHeadRotMotion::LLHeadRotMotion(const LLUUID &id) : 
 74	LLMotion(id),
 75	mCharacter(NULL),
 76	mTorsoJoint(NULL),
 77	mHeadJoint(NULL)
 78{
 79	mName = "head_rot";
 80
 81	mTorsoState = new LLJointState;
 82	mNeckState = new LLJointState;
 83	mHeadState = new LLJointState;
 84}
 85
 86
 87//-----------------------------------------------------------------------------
 88// ~LLHeadRotMotion()
 89// Class Destructor
 90//-----------------------------------------------------------------------------
 91LLHeadRotMotion::~LLHeadRotMotion()
 92{
 93}
 94
 95//-----------------------------------------------------------------------------
 96// LLHeadRotMotion::onInitialize(LLCharacter *character)
 97//-----------------------------------------------------------------------------
 98LLMotion::LLMotionInitStatus LLHeadRotMotion::onInitialize(LLCharacter *character)
 99{
100	if (!character)
101		return STATUS_FAILURE;
102	mCharacter = character;
103
104	mPelvisJoint = character->getJoint("mPelvis");
105	if ( ! mPelvisJoint )
106	{
107		llinfos << getName() << ": Can't get pelvis joint." << llendl;
108		return STATUS_FAILURE;
109	}
110
111	mRootJoint = character->getJoint("mRoot");
112	if ( ! mRootJoint )
113	{
114		llinfos << getName() << ": Can't get root joint." << llendl;
115		return STATUS_FAILURE;
116	}
117
118	mTorsoJoint = character->getJoint("mTorso");
119	if ( ! mTorsoJoint )
120	{
121		llinfos << getName() << ": Can't get torso joint." << llendl;
122		return STATUS_FAILURE;
123	}
124
125	mHeadJoint = character->getJoint("mHead");
126	if ( ! mHeadJoint )
127	{
128		llinfos << getName() << ": Can't get head joint." << llendl;
129		return STATUS_FAILURE;
130	}
131
132	mTorsoState->setJoint( character->getJoint("mTorso") );
133	if ( ! mTorsoState->getJoint() )
134	{
135		llinfos << getName() << ": Can't get torso joint." << llendl;
136		return STATUS_FAILURE;
137	}
138
139	mNeckState->setJoint( character->getJoint("mNeck") );
140	if ( ! mNeckState->getJoint() )
141	{
142		llinfos << getName() << ": Can't get neck joint." << llendl;
143		return STATUS_FAILURE;
144	}
145
146	mHeadState->setJoint( character->getJoint("mHead") );
147	if ( ! mHeadState->getJoint() )
148	{
149		llinfos << getName() << ": Can't get head joint." << llendl;
150		return STATUS_FAILURE;
151	}
152
153	mTorsoState->setUsage(LLJointState::ROT);
154	mNeckState->setUsage(LLJointState::ROT);
155	mHeadState->setUsage(LLJointState::ROT);
156
157	addJointState( mTorsoState );
158	addJointState( mNeckState );
159	addJointState( mHeadState );
160
161	mLastHeadRot.loadIdentity();
162
163	return STATUS_SUCCESS;
164}
165
166
167//-----------------------------------------------------------------------------
168// LLHeadRotMotion::onActivate()
169//-----------------------------------------------------------------------------
170BOOL LLHeadRotMotion::onActivate()
171{
172	return TRUE;
173}
174
175
176//-----------------------------------------------------------------------------
177// LLHeadRotMotion::onUpdate()
178//-----------------------------------------------------------------------------
179BOOL LLHeadRotMotion::onUpdate(F32 time, U8* joint_mask)
180{
181	LLQuaternion	targetHeadRotWorld;
182	LLQuaternion	currentRootRotWorld = mRootJoint->getWorldRotation();
183	LLQuaternion	currentInvRootRotWorld = ~currentRootRotWorld;
184
185	F32 head_slerp_amt = LLCriticalDamp::getInterpolant(HEAD_LOOKAT_LAG_HALF_LIFE);
186	F32 torso_slerp_amt = LLCriticalDamp::getInterpolant(TORSO_LOOKAT_LAG_HALF_LIFE);
187
188	LLVector3* targetPos = (LLVector3*)mCharacter->getAnimationData("LookAtPoint");
189
190	if (targetPos)
191	{
192		LLVector3 headLookAt = *targetPos;
193
194//		llinfos << "Look At: " << headLookAt + mHeadJoint->getWorldPosition() << llendl;
195
196		F32 lookatDistance = headLookAt.normVec();
197
198		if (lookatDistance < MIN_HEAD_LOOKAT_DISTANCE)
199		{
200			targetHeadRotWorld = mPelvisJoint->getWorldRotation();
201		}
202		else
203		{
204			LLVector3 root_up = LLVector3(0.f, 0.f, 1.f) * currentRootRotWorld;
205			LLVector3 left(root_up % headLookAt);
206			// if look_at has zero length, fail
207			// if look_at and skyward are parallel, fail
208			//
209			// Test both of these conditions with a cross product.
210
211			if (left.magVecSquared() < 0.15f)
212			{
213				LLVector3 root_at = LLVector3(1.f, 0.f, 0.f) * currentRootRotWorld;
214				root_at.mV[VZ] = 0.f;
215				root_at.normVec();
216
217				headLookAt = lerp(headLookAt, root_at, 0.4f);
218				headLookAt.normVec();
219
220				left = root_up % headLookAt;
221			}
222			
223			// Make sure look_at and skyward and not parallel
224			// and neither are zero length
225			LLVector3 up(headLookAt % left);
226
227			targetHeadRotWorld = LLQuaternion(headLookAt, left, up);
228		}
229	}
230	else
231	{
232		targetHeadRotWorld = currentRootRotWorld;
233	}
234
235	LLQuaternion head_rot_local = targetHeadRotWorld * currentInvRootRotWorld;
236	head_rot_local.constrain(HEAD_ROTATION_CONSTRAINT);
237
238	// set final torso rotation
239	// Set torso target rotation such that it lags behind the head rotation
240	// by a fixed amount.
241	LLQuaternion torso_rot_local = nlerp(TORSO_LAG, LLQuaternion::DEFAULT, head_rot_local );
242	mTorsoState->setRotation( nlerp(torso_slerp_amt, mTorsoState->getRotation(), torso_rot_local) );
243
244	head_rot_local = nlerp(head_slerp_amt, mLastHeadRot, head_rot_local);
245	mLastHeadRot = head_rot_local;
246
247	// Set the head rotation.
248	if(mNeckState->getJoint() && mNeckState->getJoint()->getParent())
249	{
250		LLQuaternion torsoRotLocal =  mNeckState->getJoint()->getParent()->getWorldRotation() * currentInvRootRotWorld;
251		head_rot_local = head_rot_local * ~torsoRotLocal;
252		mNeckState->setRotation( nlerp(NECK_LAG, LLQuaternion::DEFAULT, head_rot_local) );
253		mHeadState->setRotation( nlerp(1.f - NECK_LAG, LLQuaternion::DEFAULT, head_rot_local));
254	}
255
256	return TRUE;
257}
258
259
260//-----------------------------------------------------------------------------
261// LLHeadRotMotion::onDeactivate()
262//-----------------------------------------------------------------------------
263void LLHeadRotMotion::onDeactivate()
264{
265}
266
267
268//-----------------------------------------------------------------------------
269// LLEyeMotion()
270// Class Constructor
271//-----------------------------------------------------------------------------
272LLEyeMotion::LLEyeMotion(const LLUUID &id) : LLMotion(id)
273{
274	mCharacter = NULL;
275	mEyeJitterTime = 0.f;
276	mEyeJitterYaw = 0.f;
277	mEyeJitterPitch = 0.f;
278
279	mEyeLookAwayTime = 0.f;
280	mEyeLookAwayYaw = 0.f;
281	mEyeLookAwayPitch = 0.f;
282
283	mEyeBlinkTime = 0.f;
284	mEyesClosed = FALSE;
285	
286	mHeadJoint = NULL;
287
288	mName = "eye_rot";
289
290	mLeftEyeState = new LLJointState;
291	mRightEyeState = new LLJointState;
292}
293
294
295//-----------------------------------------------------------------------------
296// ~LLEyeMotion()
297// Class Destructor
298//-----------------------------------------------------------------------------
299LLEyeMotion::~LLEyeMotion()
300{
301}
302
303//-----------------------------------------------------------------------------
304// LLEyeMotion::onInitialize(LLCharacter *character)
305//-----------------------------------------------------------------------------
306LLMotion::LLMotionInitStatus LLEyeMotion::onInitialize(LLCharacter *character)
307{
308	mCharacter = character;
309
310	mHeadJoint = character->getJoint("mHead");
311	if ( ! mHeadJoint )
312	{
313		llinfos << getName() << ": Can't get head joint." << llendl;
314		return STATUS_FAILURE;
315	}
316
317	mLeftEyeState->setJoint( character->getJoint("mEyeLeft") );
318	if ( ! mLeftEyeState->getJoint() )
319	{
320		llinfos << getName() << ": Can't get left eyeball joint." << llendl;
321		return STATUS_FAILURE;
322	}
323
324	mRightEyeState->setJoint( character->getJoint("mEyeRight") );
325	if ( ! mRightEyeState->getJoint() )
326	{
327		llinfos << getName() << ": Can't get Right eyeball joint." << llendl;
328		return STATUS_FAILURE;
329	}
330
331	mLeftEyeState->setUsage(LLJointState::ROT);
332	mRightEyeState->setUsage(LLJointState::ROT);
333
334	addJointState( mLeftEyeState );
335	addJointState( mRightEyeState );
336
337	return STATUS_SUCCESS;
338}
339
340
341//-----------------------------------------------------------------------------
342// LLEyeMotion::onActivate()
343//-----------------------------------------------------------------------------
344BOOL LLEyeMotion::onActivate()
345{
346	return TRUE;
347}
348
349
350//-----------------------------------------------------------------------------
351// LLEyeMotion::onUpdate()
352//-----------------------------------------------------------------------------
353BOOL LLEyeMotion::onUpdate(F32 time, U8* joint_mask)
354{
355	// Compute eye rotation.
356	LLQuaternion	target_eye_rot;
357	LLVector3		eye_look_at;
358	F32				vergence;
359
360	//calculate jitter
361	if (mEyeJitterTimer.getElapsedTimeF32() > mEyeJitterTime)
362	{
363		mEyeJitterTime = EYE_JITTER_MIN_TIME + ll_frand(EYE_JITTER_MAX_TIME - EYE_JITTER_MIN_TIME);
364		mEyeJitterYaw = (ll_frand(2.f) - 1.f) * EYE_JITTER_MAX_YAW;
365		mEyeJitterPitch = (ll_frand(2.f) - 1.f) * EYE_JITTER_MAX_PITCH;
366		// make sure lookaway time count gets updated, because we're resetting the timer
367		mEyeLookAwayTime -= llmax(0.f, mEyeJitterTimer.getElapsedTimeF32());
368		mEyeJitterTimer.reset();
369	} 
370	else if (mEyeJitterTimer.getElapsedTimeF32() > mEyeLookAwayTime)
371	{
372		if (ll_frand() > 0.1f)
373		{
374			// blink while moving eyes some percentage of the time
375			mEyeBlinkTime = mEyeBlinkTimer.getElapsedTimeF32();
376		}
377		if (mEyeLookAwayYaw == 0.f && mEyeLookAwayPitch == 0.f)
378		{
379			mEyeLookAwayYaw = (ll_frand(2.f) - 1.f) * EYE_LOOK_AWAY_MAX_YAW;
380			mEyeLookAwayPitch = (ll_frand(2.f) - 1.f) * EYE_LOOK_AWAY_MAX_PITCH;
381			mEyeLookAwayTime = EYE_LOOK_BACK_MIN_TIME + ll_frand(EYE_LOOK_BACK_MAX_TIME - EYE_LOOK_BACK_MIN_TIME);
382		}
383		else
384		{
385			mEyeLookAwayYaw = 0.f;
386			mEyeLookAwayPitch = 0.f;
387			mEyeLookAwayTime = EYE_LOOK_AWAY_MIN_TIME + ll_frand(EYE_LOOK_AWAY_MAX_TIME - EYE_LOOK_AWAY_MIN_TIME);
388		}
389	}
390
391	// do blinking
392	if (!mEyesClosed && mEyeBlinkTimer.getElapsedTimeF32() >= mEyeBlinkTime)
393	{
394		F32 leftEyeBlinkMorph = mEyeBlinkTimer.getElapsedTimeF32() - mEyeBlinkTime;
395		F32 rightEyeBlinkMorph = leftEyeBlinkMorph - EYE_BLINK_TIME_DELTA;
396
397		leftEyeBlinkMorph = llclamp(leftEyeBlinkMorph / EYE_BLINK_SPEED, 0.f, 1.f);
398		rightEyeBlinkMorph = llclamp(rightEyeBlinkMorph / EYE_BLINK_SPEED, 0.f, 1.f);
399		mCharacter->setVisualParamWeight("Blink_Left", leftEyeBlinkMorph);
400		mCharacter->setVisualParamWeight("Blink_Right", rightEyeBlinkMorph);
401		mCharacter->updateVisualParams();
402
403		if (rightEyeBlinkMorph == 1.f)
404		{
405			mEyesClosed = TRUE;
406			mEyeBlinkTime = EYE_BLINK_CLOSE_TIME;
407			mEyeBlinkTimer.reset();
408		}
409	}
410	else if (mEyesClosed)
411	{
412		if (mEyeBlinkTimer.getElapsedTimeF32() >= mEyeBlinkTime)
413		{
414			F32 leftEyeBlinkMorph = mEyeBlinkTimer.getElapsedTimeF32() - mEyeBlinkTime;
415			F32 rightEyeBlinkMorph = leftEyeBlinkMorph - EYE_BLINK_TIME_DELTA;
416
417			leftEyeBlinkMorph = 1.f - llclamp(leftEyeBlinkMorph / EYE_BLINK_SPEED, 0.f, 1.f);
418			rightEyeBlinkMorph = 1.f - llclamp(rightEyeBlinkMorph / EYE_BLINK_SPEED, 0.f, 1.f);
419			mCharacter->setVisualParamWeight("Blink_Left", leftEyeBlinkMorph);
420			mCharacter->setVisualParamWeight("Blink_Right", rightEyeBlinkMorph);
421			mCharacter->updateVisualParams();
422
423			if (rightEyeBlinkMorph == 0.f)
424			{
425				mEyesClosed = FALSE;
426				mEyeBlinkTime = EYE_BLINK_MIN_TIME + ll_frand(EYE_BLINK_MAX_TIME - EYE_BLINK_MIN_TIME);
427				mEyeBlinkTimer.reset();
428			}
429		}
430	}
431
432	BOOL has_eye_target = FALSE;
433	LLVector3* targetPos = (LLVector3*)mCharacter->getAnimationData("LookAtPoint");
434
435	if (targetPos)
436	{
437		LLVector3		skyward(0.f, 0.f, 1.f);
438		LLVector3		left;
439		LLVector3		up;
440
441		eye_look_at = *targetPos;
442		has_eye_target = TRUE;
443		F32 lookAtDistance = eye_look_at.normVec();
444
445		left.setVec(skyward % eye_look_at);
446		up.setVec(eye_look_at % left);
447
448		target_eye_rot = LLQuaternion(eye_look_at, left, up);
449		// convert target rotation to head-local coordinates
450		target_eye_rot *= ~mHeadJoint->getWorldRotation();
451		// eliminate any Euler roll - we're lucky that roll is applied last.
452		F32 roll, pitch, yaw;
453		target_eye_rot.getEulerAngles(&roll, &pitch, &yaw);
454		target_eye_rot.setQuat(0.0f, pitch, yaw);
455		// constrain target orientation to be in front of avatar's face
456		target_eye_rot.constrain(EYE_ROT_LIMIT_ANGLE);
457
458		// calculate vergence
459		F32 interocular_dist = (mLeftEyeState->getJoint()->getWorldPosition() - mRightEyeState->getJoint()->getWorldPosition()).magVec();
460		vergence = -atan2((interocular_dist / 2.f), lookAtDistance);
461		llclamp(vergence, -F_PI_BY_TWO, 0.f);
462	}
463	else
464	{
465		target_eye_rot = LLQuaternion::DEFAULT;
466		vergence = 0.f;
467	}
468
469	//RN: subtract 4 degrees to account for foveal angular offset relative to pupil
470	vergence += 4.f * DEG_TO_RAD;
471
472	// calculate eye jitter
473	LLQuaternion eye_jitter_rot;
474
475	// vergence not too high...
476	if (vergence > -0.05f)
477	{
478		//...go ahead and jitter
479		eye_jitter_rot.setQuat(0.f, mEyeJitterPitch + mEyeLookAwayPitch, mEyeJitterYaw + mEyeLookAwayYaw);
480	}
481	else
482	{
483		//...or don't
484		eye_jitter_rot.loadIdentity();
485	}
486
487	// calculate vergence of eyes as an object gets closer to the avatar's head
488	LLQuaternion vergence_quat;
489		
490	if (has_eye_target)
491	{
492		vergence_quat.setQuat(vergence, LLVector3(0.f, 0.f, 1.f));
493	}
494	else
495	{
496		vergence_quat.loadIdentity();
497	}
498
499	// calculate eye rotations
500	LLQuaternion left_eye_rot = target_eye_rot;
501	left_eye_rot = vergence_quat * eye_jitter_rot * left_eye_rot;
502
503	LLQuaternion right_eye_rot = target_eye_rot;
504	vergence_quat.transQuat();
505	right_eye_rot = vergence_quat * eye_jitter_rot * right_eye_rot;
506
507	mLeftEyeState->setRotation( left_eye_rot );
508	mRightEyeState->setRotation( right_eye_rot );
509
510	return TRUE;
511}
512
513
514//-----------------------------------------------------------------------------
515// LLEyeMotion::onDeactivate()
516//-----------------------------------------------------------------------------
517void LLEyeMotion::onDeactivate()
518{
519	LLJoint* joint = mLeftEyeState->getJoint();
520	if (joint)
521	{
522		joint->setRotation(LLQuaternion::DEFAULT);
523	}
524
525	joint = mRightEyeState->getJoint();
526	if (joint)
527	{
528		joint->setRotation(LLQuaternion::DEFAULT);
529	}
530}
531
532// End