llheadrotmotion.cpp

Go to the documentation of this file.
00001 
00032 //-----------------------------------------------------------------------------
00033 // Header Files
00034 //-----------------------------------------------------------------------------
00035 #include "linden_common.h"
00036 
00037 #include "llheadrotmotion.h"
00038 #include "llcharacter.h"
00039 #include "llrand.h"
00040 #include "m3math.h"
00041 #include "v3dmath.h"
00042 #include "llcriticaldamp.h"
00043 
00044 //-----------------------------------------------------------------------------
00045 // Constants
00046 //-----------------------------------------------------------------------------
00047 const F32 TORSO_LAG     = 0.35f;        // torso rotation factor
00048 const F32 NECK_LAG = 0.5f;              // neck rotation factor
00049 const F32 HEAD_LOOKAT_LAG_HALF_LIFE     = 0.15f;                // half-life of lookat targeting for head
00050 const F32 TORSO_LOOKAT_LAG_HALF_LIFE    = 0.27f;                // half-life of lookat targeting for torso
00051 const F32 EYE_LOOKAT_LAG_HALF_LIFE = 0.06f;             // half-life of lookat targeting for eye
00052 const F32 HEAD_ROTATION_CONSTRAINT = F_PI_BY_TWO * 0.8f;        // limit angle for head rotation
00053 
00054 const F32 MIN_HEAD_LOOKAT_DISTANCE = 0.3f;      // minimum distance from head before we turn to look at it
00055 const F32 MAX_TIME_DELTA = 2.f; //max two seconds a frame for calculating interpolation
00056 const F32 EYE_JITTER_MIN_TIME = 0.3f; // min amount of time between eye "jitter" motions
00057 const F32 EYE_JITTER_MAX_TIME = 2.5f; // max amount of time between eye "jitter" motions
00058 const F32 EYE_JITTER_MAX_YAW = 0.08f; // max yaw of eye jitter motion
00059 const F32 EYE_JITTER_MAX_PITCH = 0.015f; // max pitch of eye jitter motion
00060 const F32 EYE_LOOK_AWAY_MIN_TIME = 5.f; // min amount of time between eye "look away" motions
00061 const F32 EYE_LOOK_AWAY_MAX_TIME = 15.f; // max amount of time between eye "look away" motions
00062 const F32 EYE_LOOK_BACK_MIN_TIME = 1.f; // min amount of time before looking back after looking away
00063 const F32 EYE_LOOK_BACK_MAX_TIME = 5.f; // max amount of time before looking back after looking away
00064 const F32 EYE_LOOK_AWAY_MAX_YAW = 0.15f; // max yaw of eye look away motion
00065 const F32 EYE_LOOK_AWAY_MAX_PITCH = 0.12f; // max pitch of look away motion
00066 const F32 EYE_ROT_LIMIT_ANGLE = F_PI_BY_TWO * 0.3f; //max angle in radians for eye rotation
00067 
00068 const F32 EYE_BLINK_MIN_TIME = 0.5f; // minimum amount of time between blinks
00069 const F32 EYE_BLINK_MAX_TIME = 8.f;     // maximum amount of time between blinks
00070 const F32 EYE_BLINK_CLOSE_TIME = 0.03f; // how long the eye stays closed in a blink
00071 const F32 EYE_BLINK_SPEED = 0.015f;             // seconds it takes for a eye open/close movement
00072 const F32 EYE_BLINK_TIME_DELTA = 0.005f; // time between one eye starting a blink and the other following
00073 
00074 //-----------------------------------------------------------------------------
00075 // LLHeadRotMotion()
00076 // Class Constructor
00077 //-----------------------------------------------------------------------------
00078 LLHeadRotMotion::LLHeadRotMotion(const LLUUID &id) : 
00079         LLMotion(id),
00080         mCharacter(NULL),
00081         mTorsoJoint(NULL),
00082         mHeadJoint(NULL)
00083 {
00084         mName = "head_rot";
00085 
00086         mTorsoState = new LLJointState;
00087         mNeckState = new LLJointState;
00088         mHeadState = new LLJointState;
00089 }
00090 
00091 
00092 //-----------------------------------------------------------------------------
00093 // ~LLHeadRotMotion()
00094 // Class Destructor
00095 //-----------------------------------------------------------------------------
00096 LLHeadRotMotion::~LLHeadRotMotion()
00097 {
00098 }
00099 
00100 //-----------------------------------------------------------------------------
00101 // LLHeadRotMotion::onInitialize(LLCharacter *character)
00102 //-----------------------------------------------------------------------------
00103 LLMotion::LLMotionInitStatus LLHeadRotMotion::onInitialize(LLCharacter *character)
00104 {
00105         if (!character)
00106                 return STATUS_FAILURE;
00107         mCharacter = character;
00108 
00109         mPelvisJoint = character->getJoint("mPelvis");
00110         if ( ! mPelvisJoint )
00111         {
00112                 llinfos << getName() << ": Can't get pelvis joint." << llendl;
00113                 return STATUS_FAILURE;
00114         }
00115 
00116         mRootJoint = character->getJoint("mRoot");
00117         if ( ! mRootJoint )
00118         {
00119                 llinfos << getName() << ": Can't get root joint." << llendl;
00120                 return STATUS_FAILURE;
00121         }
00122 
00123         mTorsoJoint = character->getJoint("mTorso");
00124         if ( ! mTorsoJoint )
00125         {
00126                 llinfos << getName() << ": Can't get torso joint." << llendl;
00127                 return STATUS_FAILURE;
00128         }
00129 
00130         mHeadJoint = character->getJoint("mHead");
00131         if ( ! mHeadJoint )
00132         {
00133                 llinfos << getName() << ": Can't get head joint." << llendl;
00134                 return STATUS_FAILURE;
00135         }
00136 
00137         mTorsoState->setJoint( character->getJoint("mTorso") );
00138         if ( ! mTorsoState->getJoint() )
00139         {
00140                 llinfos << getName() << ": Can't get torso joint." << llendl;
00141                 return STATUS_FAILURE;
00142         }
00143 
00144         mNeckState->setJoint( character->getJoint("mNeck") );
00145         if ( ! mNeckState->getJoint() )
00146         {
00147                 llinfos << getName() << ": Can't get neck joint." << llendl;
00148                 return STATUS_FAILURE;
00149         }
00150 
00151         mHeadState->setJoint( character->getJoint("mHead") );
00152         if ( ! mHeadState->getJoint() )
00153         {
00154                 llinfos << getName() << ": Can't get head joint." << llendl;
00155                 return STATUS_FAILURE;
00156         }
00157 
00158         mTorsoState->setUsage(LLJointState::ROT);
00159         mNeckState->setUsage(LLJointState::ROT);
00160         mHeadState->setUsage(LLJointState::ROT);
00161 
00162         addJointState( mTorsoState );
00163         addJointState( mNeckState );
00164         addJointState( mHeadState );
00165 
00166         mLastHeadRot.loadIdentity();
00167 
00168         return STATUS_SUCCESS;
00169 }
00170 
00171 
00172 //-----------------------------------------------------------------------------
00173 // LLHeadRotMotion::onActivate()
00174 //-----------------------------------------------------------------------------
00175 BOOL LLHeadRotMotion::onActivate()
00176 {
00177         return TRUE;
00178 }
00179 
00180 
00181 //-----------------------------------------------------------------------------
00182 // LLHeadRotMotion::onUpdate()
00183 //-----------------------------------------------------------------------------
00184 BOOL LLHeadRotMotion::onUpdate(F32 time, U8* joint_mask)
00185 {
00186         LLQuaternion    targetHeadRotWorld;
00187         LLQuaternion    currentRootRotWorld = mRootJoint->getWorldRotation();
00188         LLQuaternion    currentInvRootRotWorld = ~currentRootRotWorld;
00189 
00190         F32 head_slerp_amt = LLCriticalDamp::getInterpolant(HEAD_LOOKAT_LAG_HALF_LIFE);
00191         F32 torso_slerp_amt = LLCriticalDamp::getInterpolant(TORSO_LOOKAT_LAG_HALF_LIFE);
00192 
00193         LLVector3* targetPos = (LLVector3*)mCharacter->getAnimationData("LookAtPoint");
00194 
00195         if (targetPos)
00196         {
00197                 LLVector3 headLookAt = *targetPos;
00198 
00199 //              llinfos << "Look At: " << headLookAt + mHeadJoint->getWorldPosition() << llendl;
00200 
00201                 F32 lookatDistance = headLookAt.normVec();
00202 
00203                 if (lookatDistance < MIN_HEAD_LOOKAT_DISTANCE)
00204                 {
00205                         targetHeadRotWorld = mPelvisJoint->getWorldRotation();
00206                 }
00207                 else
00208                 {
00209                         LLVector3 root_up = LLVector3(0.f, 0.f, 1.f) * currentRootRotWorld;
00210                         LLVector3 left(root_up % headLookAt);
00211                         // if look_at has zero length, fail
00212                         // if look_at and skyward are parallel, fail
00213                         //
00214                         // Test both of these conditions with a cross product.
00215 
00216                         if (left.magVecSquared() < 0.15f)
00217                         {
00218                                 LLVector3 root_at = LLVector3(1.f, 0.f, 0.f) * currentRootRotWorld;
00219                                 root_at.mV[VZ] = 0.f;
00220                                 root_at.normVec();
00221 
00222                                 headLookAt = lerp(headLookAt, root_at, 0.4f);
00223                                 headLookAt.normVec();
00224 
00225                                 left = root_up % headLookAt;
00226                         }
00227                         
00228                         // Make sure look_at and skyward and not parallel
00229                         // and neither are zero length
00230                         LLVector3 up(headLookAt % left);
00231 
00232                         targetHeadRotWorld = LLQuaternion(headLookAt, left, up);
00233                 }
00234         }
00235         else
00236         {
00237                 targetHeadRotWorld = currentRootRotWorld;
00238         }
00239 
00240         LLQuaternion head_rot_local = targetHeadRotWorld * currentInvRootRotWorld;
00241         head_rot_local.constrain(HEAD_ROTATION_CONSTRAINT);
00242 
00243         // set final torso rotation
00244         // Set torso target rotation such that it lags behind the head rotation
00245         // by a fixed amount.
00246         LLQuaternion torso_rot_local = nlerp(TORSO_LAG, LLQuaternion::DEFAULT, head_rot_local );
00247         mTorsoState->setRotation( nlerp(torso_slerp_amt, mTorsoState->getRotation(), torso_rot_local) );
00248 
00249         head_rot_local = nlerp(head_slerp_amt, mLastHeadRot, head_rot_local);
00250         mLastHeadRot = head_rot_local;
00251 
00252         // Set the head rotation.
00253         LLQuaternion torsoRotLocal =  mNeckState->getJoint()->getParent()->getWorldRotation() * currentInvRootRotWorld;
00254         head_rot_local = head_rot_local * ~torsoRotLocal;
00255         mNeckState->setRotation( nlerp(NECK_LAG, LLQuaternion::DEFAULT, head_rot_local) );
00256         mHeadState->setRotation( nlerp(1.f - NECK_LAG, LLQuaternion::DEFAULT, head_rot_local));
00257 
00258         return TRUE;
00259 }
00260 
00261 
00262 //-----------------------------------------------------------------------------
00263 // LLHeadRotMotion::onDeactivate()
00264 //-----------------------------------------------------------------------------
00265 void LLHeadRotMotion::onDeactivate()
00266 {
00267 }
00268 
00269 
00270 //-----------------------------------------------------------------------------
00271 // LLEyeMotion()
00272 // Class Constructor
00273 //-----------------------------------------------------------------------------
00274 LLEyeMotion::LLEyeMotion(const LLUUID &id) : LLMotion(id)
00275 {
00276         mCharacter = NULL;
00277         mEyeJitterTime = 0.f;
00278         mEyeJitterYaw = 0.f;
00279         mEyeJitterPitch = 0.f;
00280 
00281         mEyeLookAwayTime = 0.f;
00282         mEyeLookAwayYaw = 0.f;
00283         mEyeLookAwayPitch = 0.f;
00284 
00285         mEyeBlinkTime = 0.f;
00286         mEyesClosed = FALSE;
00287         
00288         mHeadJoint = NULL;
00289 
00290         mName = "eye_rot";
00291 
00292         mLeftEyeState = new LLJointState;
00293         mRightEyeState = new LLJointState;
00294 }
00295 
00296 
00297 //-----------------------------------------------------------------------------
00298 // ~LLEyeMotion()
00299 // Class Destructor
00300 //-----------------------------------------------------------------------------
00301 LLEyeMotion::~LLEyeMotion()
00302 {
00303 }
00304 
00305 //-----------------------------------------------------------------------------
00306 // LLEyeMotion::onInitialize(LLCharacter *character)
00307 //-----------------------------------------------------------------------------
00308 LLMotion::LLMotionInitStatus LLEyeMotion::onInitialize(LLCharacter *character)
00309 {
00310         mCharacter = character;
00311 
00312         mHeadJoint = character->getJoint("mHead");
00313         if ( ! mHeadJoint )
00314         {
00315                 llinfos << getName() << ": Can't get head joint." << llendl;
00316                 return STATUS_FAILURE;
00317         }
00318 
00319         mLeftEyeState->setJoint( character->getJoint("mEyeLeft") );
00320         if ( ! mLeftEyeState->getJoint() )
00321         {
00322                 llinfos << getName() << ": Can't get left eyeball joint." << llendl;
00323                 return STATUS_FAILURE;
00324         }
00325 
00326         mRightEyeState->setJoint( character->getJoint("mEyeRight") );
00327         if ( ! mRightEyeState->getJoint() )
00328         {
00329                 llinfos << getName() << ": Can't get Right eyeball joint." << llendl;
00330                 return STATUS_FAILURE;
00331         }
00332 
00333         mLeftEyeState->setUsage(LLJointState::ROT);
00334         mRightEyeState->setUsage(LLJointState::ROT);
00335 
00336         addJointState( mLeftEyeState );
00337         addJointState( mRightEyeState );
00338 
00339         return STATUS_SUCCESS;
00340 }
00341 
00342 
00343 //-----------------------------------------------------------------------------
00344 // LLEyeMotion::onActivate()
00345 //-----------------------------------------------------------------------------
00346 BOOL LLEyeMotion::onActivate()
00347 {
00348         return TRUE;
00349 }
00350 
00351 
00352 //-----------------------------------------------------------------------------
00353 // LLEyeMotion::onUpdate()
00354 //-----------------------------------------------------------------------------
00355 BOOL LLEyeMotion::onUpdate(F32 time, U8* joint_mask)
00356 {
00357         // Compute eye rotation.
00358         LLQuaternion    target_eye_rot;
00359         LLVector3               eye_look_at;
00360         F32                             vergence;
00361 
00362         //calculate jitter
00363         if (mEyeJitterTimer.getElapsedTimeF32() > mEyeJitterTime)
00364         {
00365                 mEyeJitterTime = EYE_JITTER_MIN_TIME + ll_frand(EYE_JITTER_MAX_TIME - EYE_JITTER_MIN_TIME);
00366                 mEyeJitterYaw = (ll_frand(2.f) - 1.f) * EYE_JITTER_MAX_YAW;
00367                 mEyeJitterPitch = (ll_frand(2.f) - 1.f) * EYE_JITTER_MAX_PITCH;
00368                 // make sure lookaway time count gets updated, because we're resetting the timer
00369                 mEyeLookAwayTime -= llmax(0.f, mEyeJitterTimer.getElapsedTimeF32());
00370                 mEyeJitterTimer.reset();
00371         } 
00372         else if (mEyeJitterTimer.getElapsedTimeF32() > mEyeLookAwayTime)
00373         {
00374                 if (ll_frand() > 0.1f)
00375                 {
00376                         // blink while moving eyes some percentage of the time
00377                         mEyeBlinkTime = mEyeBlinkTimer.getElapsedTimeF32();
00378                 }
00379                 if (mEyeLookAwayYaw == 0.f && mEyeLookAwayPitch == 0.f)
00380                 {
00381                         mEyeLookAwayYaw = (ll_frand(2.f) - 1.f) * EYE_LOOK_AWAY_MAX_YAW;
00382                         mEyeLookAwayPitch = (ll_frand(2.f) - 1.f) * EYE_LOOK_AWAY_MAX_PITCH;
00383                         mEyeLookAwayTime = EYE_LOOK_BACK_MIN_TIME + ll_frand(EYE_LOOK_BACK_MAX_TIME - EYE_LOOK_BACK_MIN_TIME);
00384                 }
00385                 else
00386                 {
00387                         mEyeLookAwayYaw = 0.f;
00388                         mEyeLookAwayPitch = 0.f;
00389                         mEyeLookAwayTime = EYE_LOOK_AWAY_MIN_TIME + ll_frand(EYE_LOOK_AWAY_MAX_TIME - EYE_LOOK_AWAY_MIN_TIME);
00390                 }
00391         }
00392 
00393         // do blinking
00394         if (!mEyesClosed && mEyeBlinkTimer.getElapsedTimeF32() >= mEyeBlinkTime)
00395         {
00396                 F32 leftEyeBlinkMorph = mEyeBlinkTimer.getElapsedTimeF32() - mEyeBlinkTime;
00397                 F32 rightEyeBlinkMorph = leftEyeBlinkMorph - EYE_BLINK_TIME_DELTA;
00398 
00399                 leftEyeBlinkMorph = llclamp(leftEyeBlinkMorph / EYE_BLINK_SPEED, 0.f, 1.f);
00400                 rightEyeBlinkMorph = llclamp(rightEyeBlinkMorph / EYE_BLINK_SPEED, 0.f, 1.f);
00401                 mCharacter->setVisualParamWeight("Blink_Left", leftEyeBlinkMorph);
00402                 mCharacter->setVisualParamWeight("Blink_Right", rightEyeBlinkMorph);
00403                 mCharacter->updateVisualParams();
00404 
00405                 if (rightEyeBlinkMorph == 1.f)
00406                 {
00407                         mEyesClosed = TRUE;
00408                         mEyeBlinkTime = EYE_BLINK_CLOSE_TIME;
00409                         mEyeBlinkTimer.reset();
00410                 }
00411         }
00412         else if (mEyesClosed)
00413         {
00414                 if (mEyeBlinkTimer.getElapsedTimeF32() >= mEyeBlinkTime)
00415                 {
00416                         F32 leftEyeBlinkMorph = mEyeBlinkTimer.getElapsedTimeF32() - mEyeBlinkTime;
00417                         F32 rightEyeBlinkMorph = leftEyeBlinkMorph - EYE_BLINK_TIME_DELTA;
00418 
00419                         leftEyeBlinkMorph = 1.f - llclamp(leftEyeBlinkMorph / EYE_BLINK_SPEED, 0.f, 1.f);
00420                         rightEyeBlinkMorph = 1.f - llclamp(rightEyeBlinkMorph / EYE_BLINK_SPEED, 0.f, 1.f);
00421                         mCharacter->setVisualParamWeight("Blink_Left", leftEyeBlinkMorph);
00422                         mCharacter->setVisualParamWeight("Blink_Right", rightEyeBlinkMorph);
00423                         mCharacter->updateVisualParams();
00424 
00425                         if (rightEyeBlinkMorph == 0.f)
00426                         {
00427                                 mEyesClosed = FALSE;
00428                                 mEyeBlinkTime = EYE_BLINK_MIN_TIME + ll_frand(EYE_BLINK_MAX_TIME - EYE_BLINK_MIN_TIME);
00429                                 mEyeBlinkTimer.reset();
00430                         }
00431                 }
00432         }
00433 
00434         BOOL has_eye_target = FALSE;
00435         LLVector3* targetPos = (LLVector3*)mCharacter->getAnimationData("LookAtPoint");
00436 
00437         if (targetPos)
00438         {
00439                 LLVector3               skyward(0.f, 0.f, 1.f);
00440                 LLVector3               left;
00441                 LLVector3               up;
00442 
00443                 eye_look_at = *targetPos;
00444                 has_eye_target = TRUE;
00445                 F32 lookAtDistance = eye_look_at.normVec();
00446 
00447                 left.setVec(skyward % eye_look_at);
00448                 up.setVec(eye_look_at % left);
00449 
00450                 target_eye_rot = LLQuaternion(eye_look_at, left, up);
00451                 // convert target rotation to head-local coordinates
00452                 target_eye_rot *= ~mHeadJoint->getWorldRotation();
00453                 // eliminate any Euler roll - we're lucky that roll is applied last.
00454                 F32 roll, pitch, yaw;
00455                 target_eye_rot.getEulerAngles(&roll, &pitch, &yaw);
00456                 target_eye_rot.setQuat(0.0f, pitch, yaw);
00457                 // constrain target orientation to be in front of avatar's face
00458                 target_eye_rot.constrain(EYE_ROT_LIMIT_ANGLE);
00459 
00460                 // calculate vergence
00461                 F32 interocular_dist = (mLeftEyeState->getJoint()->getWorldPosition() - mRightEyeState->getJoint()->getWorldPosition()).magVec();
00462                 vergence = -atan2((interocular_dist / 2.f), lookAtDistance);
00463                 llclamp(vergence, -F_PI_BY_TWO, 0.f);
00464         }
00465         else
00466         {
00467                 target_eye_rot = LLQuaternion::DEFAULT;
00468                 vergence = 0.f;
00469         }
00470 
00471         //RN: subtract 4 degrees to account for foveal angular offset relative to pupil
00472         vergence += 4.f * DEG_TO_RAD;
00473 
00474         // calculate eye jitter
00475         LLQuaternion eye_jitter_rot;
00476 
00477         // vergence not too high...
00478         if (vergence > -0.05f)
00479         {
00480                 //...go ahead and jitter
00481                 eye_jitter_rot.setQuat(0.f, mEyeJitterPitch + mEyeLookAwayPitch, mEyeJitterYaw + mEyeLookAwayYaw);
00482         }
00483         else
00484         {
00485                 //...or don't
00486                 eye_jitter_rot.loadIdentity();
00487         }
00488 
00489         // calculate vergence of eyes as an object gets closer to the avatar's head
00490         LLQuaternion vergence_quat;
00491                 
00492         if (has_eye_target)
00493         {
00494                 vergence_quat.setQuat(vergence, LLVector3(0.f, 0.f, 1.f));
00495         }
00496         else
00497         {
00498                 vergence_quat.loadIdentity();
00499         }
00500 
00501         // calculate eye rotations
00502         LLQuaternion left_eye_rot = target_eye_rot;
00503         left_eye_rot = vergence_quat * eye_jitter_rot * left_eye_rot;
00504 
00505         LLQuaternion right_eye_rot = target_eye_rot;
00506         vergence_quat.transQuat();
00507         right_eye_rot = vergence_quat * eye_jitter_rot * right_eye_rot;
00508 
00509         mLeftEyeState->setRotation( left_eye_rot );
00510         mRightEyeState->setRotation( right_eye_rot );
00511 
00512         return TRUE;
00513 }
00514 
00515 
00516 //-----------------------------------------------------------------------------
00517 // LLEyeMotion::onDeactivate()
00518 //-----------------------------------------------------------------------------
00519 void LLEyeMotion::onDeactivate()
00520 {
00521         LLJoint* joint = mLeftEyeState->getJoint();
00522         if (joint)
00523         {
00524                 joint->setRotation(LLQuaternion::DEFAULT);
00525         }
00526 
00527         joint = mRightEyeState->getJoint();
00528         if (joint)
00529         {
00530                 joint->setRotation(LLQuaternion::DEFAULT);
00531         }
00532 }
00533 
00534 // End

Generated on Fri May 16 08:31:57 2008 for SecondLife by  doxygen 1.5.5