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

Generated on Thu Jul 1 06:08:41 2010 for Second Life Viewer by  doxygen 1.4.7