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