00001
00032
00033
00034
00035 #include "linden_common.h"
00036
00037 #include "llkeyframewalkmotion.h"
00038 #include "llcharacter.h"
00039 #include "llmath.h"
00040 #include "m3math.h"
00041 #include "llcriticaldamp.h"
00042
00043
00044
00045
00046 const F32 MAX_WALK_PLAYBACK_SPEED = 8.f;
00047
00048 const F32 MIN_WALK_SPEED = 0.1f;
00049 const F32 MAX_TIME_DELTA = 2.f;
00050 const F32 SPEED_ADJUST_MAX = 2.5f;
00051 const F32 SPEED_ADJUST_MAX_SEC = 3.f;
00052 const F32 DRIFT_COMP_MAX_TOTAL = 0.07f;
00053 const F32 DRIFT_COMP_MAX_SPEED = 4.f;
00054 const F32 MAX_ROLL = 0.6f;
00055
00056
00057
00058
00059
00060 LLKeyframeWalkMotion::LLKeyframeWalkMotion(const LLUUID &id) : LLKeyframeMotion(id)
00061 {
00062 mRealTimeLast = 0.0f;
00063 mAdjTimeLast = 0.0f;
00064 mCharacter = NULL;
00065 }
00066
00067
00068
00069
00070
00071
00072 LLKeyframeWalkMotion::~LLKeyframeWalkMotion()
00073 {
00074 }
00075
00076
00077
00078
00079
00080 LLMotion::LLMotionInitStatus LLKeyframeWalkMotion::onInitialize(LLCharacter *character)
00081 {
00082 mCharacter = character;
00083
00084 return LLKeyframeMotion::onInitialize(character);
00085 }
00086
00087
00088
00089
00090 BOOL LLKeyframeWalkMotion::onActivate()
00091 {
00092 mRealTimeLast = 0.0f;
00093 mAdjTimeLast = 0.0f;
00094
00095 return LLKeyframeMotion::onActivate();
00096 }
00097
00098
00099
00100
00101 void LLKeyframeWalkMotion::onDeactivate()
00102 {
00103 mCharacter->removeAnimationData("Down Foot");
00104 LLKeyframeMotion::onDeactivate();
00105 }
00106
00107
00108
00109
00110 BOOL LLKeyframeWalkMotion::onUpdate(F32 time, U8* joint_mask)
00111 {
00112
00113 F32 deltaTime = time - mRealTimeLast;
00114
00115 void* speed_ptr = mCharacter->getAnimationData("Walk Speed");
00116 F32 speed = (speed_ptr) ? *((F32 *)speed_ptr) : 1.f;
00117
00118
00119 F32 adjusted_time = mAdjTimeLast + (deltaTime * speed);
00120
00121
00122 mRealTimeLast = time;
00123 mAdjTimeLast = adjusted_time;
00124
00125
00126 if (adjusted_time < 0.0f)
00127 {
00128 adjusted_time = getDuration() + fmod(adjusted_time, getDuration());
00129 }
00130
00131
00132 return LLKeyframeMotion::onUpdate( adjusted_time, joint_mask );
00133 }
00134
00135
00136
00137
00138
00139
00140
00141
00142 LLWalkAdjustMotion::LLWalkAdjustMotion(const LLUUID &id) : LLMotion(id)
00143 {
00144 mLastTime = 0.f;
00145 mName = "walk_adjust";
00146 }
00147
00148
00149
00150
00151 LLMotion::LLMotionInitStatus LLWalkAdjustMotion::onInitialize(LLCharacter *character)
00152 {
00153 mCharacter = character;
00154 mLeftAnkleJoint = mCharacter->getJoint("mAnkleLeft");
00155 mRightAnkleJoint = mCharacter->getJoint("mAnkleRight");
00156
00157 mPelvisJoint = mCharacter->getJoint("mPelvis");
00158 mPelvisState.setJoint( mPelvisJoint );
00159 if ( !mPelvisJoint )
00160 {
00161 llwarns << getName() << ": Can't get pelvis joint." << llendl;
00162 return STATUS_FAILURE;
00163 }
00164
00165 mPelvisState.setUsage(LLJointState::POS);
00166 addJointState( &mPelvisState );
00167
00168 return STATUS_SUCCESS;
00169 }
00170
00171
00172
00173
00174 BOOL LLWalkAdjustMotion::onActivate()
00175 {
00176 mAvgCorrection = 0.f;
00177 mSpeedAdjust = 0.f;
00178 mAnimSpeed = 0.f;
00179 mAvgSpeed = 0.f;
00180 mRelativeDir = 1.f;
00181 mPelvisState.setPosition(LLVector3::zero);
00182
00183 mLastLeftAnklePos = mCharacter->getPosGlobalFromAgent(mLeftAnkleJoint->getWorldPosition());
00184 mLastRightAnklePos = mCharacter->getPosGlobalFromAgent(mRightAnkleJoint->getWorldPosition());
00185
00186 F32 leftAnkleOffset = (mLeftAnkleJoint->getWorldPosition() - mCharacter->getCharacterPosition()).magVec();
00187 F32 rightAnkleOffset = (mRightAnkleJoint->getWorldPosition() - mCharacter->getCharacterPosition()).magVec();
00188 mAnkleOffset = llmax(leftAnkleOffset, rightAnkleOffset);
00189
00190 return TRUE;
00191 }
00192
00193
00194
00195
00196 BOOL LLWalkAdjustMotion::onUpdate(F32 time, U8* joint_mask)
00197 {
00198 LLVector3 footCorrection;
00199 LLVector3 vel = mCharacter->getCharacterVelocity() * mCharacter->getTimeDilation();
00200 F32 deltaTime = llclamp(time - mLastTime, 0.f, MAX_TIME_DELTA);
00201 mLastTime = time;
00202
00203 LLQuaternion inv_rotation = ~mPelvisJoint->getWorldRotation();
00204
00205
00206 LLVector3 ang_vel = mCharacter->getCharacterAngularVelocity() * mCharacter->getTimeDilation();
00207 F32 speed = llmin(vel.normVec(), MAX_WALK_PLAYBACK_SPEED);
00208 mAvgSpeed = lerp(mAvgSpeed, speed, LLCriticalDamp::getInterpolant(0.2f));
00209
00210
00211
00212 LLVector3 localVel = vel * inv_rotation;
00213 if (localVel.mV[VX] > 0.f)
00214 {
00215 mRelativeDir = 1.f;
00216 }
00217 else if (localVel.mV[VX] < 0.f)
00218 {
00219 mRelativeDir = -1.f;
00220 }
00221
00222
00223 LLVector3 leftFootDelta;
00224 LLVector3 leftFootWorldPosition = mLeftAnkleJoint->getWorldPosition();
00225 LLVector3d leftFootGlobalPosition = mCharacter->getPosGlobalFromAgent(leftFootWorldPosition);
00226 leftFootDelta.setVec(mLastLeftAnklePos - leftFootGlobalPosition);
00227 mLastLeftAnklePos = leftFootGlobalPosition;
00228
00229 LLVector3 rightFootDelta;
00230 LLVector3 rightFootWorldPosition = mRightAnkleJoint->getWorldPosition();
00231 LLVector3d rightFootGlobalPosition = mCharacter->getPosGlobalFromAgent(rightFootWorldPosition);
00232 rightFootDelta.setVec(mLastRightAnklePos - rightFootGlobalPosition);
00233 mLastRightAnklePos = rightFootGlobalPosition;
00234
00235
00236 if (mAvgSpeed > 0.1)
00237 {
00238
00239 F32 leftFootDriftAmt = leftFootDelta * vel;
00240 F32 rightFootDriftAmt = rightFootDelta * vel;
00241
00242 if (rightFootDriftAmt > leftFootDriftAmt)
00243 {
00244 footCorrection = rightFootDelta;
00245 } else
00246 {
00247 footCorrection = leftFootDelta;
00248 }
00249 }
00250 else
00251 {
00252 mAvgSpeed = ang_vel.magVec() * mAnkleOffset;
00253 mRelativeDir = 1.f;
00254
00255
00256
00257 if (leftFootWorldPosition.mV[VZ] < rightFootWorldPosition.mV[VZ])
00258 {
00259
00260 footCorrection = leftFootDelta;
00261 }
00262 else
00263 {
00264
00265 footCorrection = rightFootDelta;
00266 }
00267 }
00268
00269
00270 footCorrection = footCorrection * inv_rotation;
00271
00272
00273
00274 mPelvisOffset = mPelvisState.getPosition() + lerp(LLVector3::zero, footCorrection, LLCriticalDamp::getInterpolant(0.2f));
00275
00276
00277 mAvgCorrection = lerp(mAvgCorrection, footCorrection.mV[VX] * mRelativeDir, LLCriticalDamp::getInterpolant(0.1f));
00278
00279
00280 F32 footSlipVelocity = (deltaTime != 0.f) ? (-mAvgCorrection / deltaTime) : 0.f;
00281
00282 F32 newSpeedAdjust = 0.f;
00283
00284
00285
00286
00287
00288 F32 directional_factor = localVel.mV[VX] * mRelativeDir;
00289 if (speed > 0.1f)
00290 {
00291
00292 newSpeedAdjust = llclamp(footSlipVelocity - mAvgSpeed * (1.f - directional_factor),
00293 -SPEED_ADJUST_MAX, SPEED_ADJUST_MAX);
00294 newSpeedAdjust = lerp(mSpeedAdjust, newSpeedAdjust, LLCriticalDamp::getInterpolant(0.2f));
00295
00296 F32 speedDelta = newSpeedAdjust - mSpeedAdjust;
00297 speedDelta = llclamp(speedDelta, -SPEED_ADJUST_MAX_SEC * deltaTime, SPEED_ADJUST_MAX_SEC * deltaTime);
00298
00299 mSpeedAdjust = mSpeedAdjust + speedDelta;
00300 }
00301 else
00302 {
00303 mSpeedAdjust = lerp(mSpeedAdjust, 0.f, LLCriticalDamp::getInterpolant(0.2f));
00304 }
00305
00306 mAnimSpeed = (mAvgSpeed + mSpeedAdjust) * mRelativeDir;
00307
00308
00309
00310
00311
00312
00313
00314
00315
00316 mCharacter->setAnimationData("Walk Speed", &mAnimSpeed);
00317
00318
00319 F32 drift_comp_max = llclamp(speed, 0.f, DRIFT_COMP_MAX_SPEED) / DRIFT_COMP_MAX_SPEED;
00320 drift_comp_max *= DRIFT_COMP_MAX_TOTAL;
00321
00322 LLVector3 currentPelvisPos = mPelvisState.getJoint()->getPosition();
00323
00324
00325
00326 mPelvisOffset.mV[VX] = llclamp( mPelvisOffset.mV[VX], -drift_comp_max - currentPelvisPos.mV[VX], drift_comp_max - currentPelvisPos.mV[VX] );
00327 mPelvisOffset.mV[VY] = llclamp( mPelvisOffset.mV[VY], -drift_comp_max - currentPelvisPos.mV[VY], drift_comp_max - currentPelvisPos.mV[VY]);
00328 mPelvisOffset.mV[VZ] = 0.f;
00329
00330
00331 mPelvisState.setPosition(mPelvisOffset);
00332
00333 mCharacter->setAnimationData("Pelvis Offset", &mPelvisOffset);
00334
00335 return TRUE;
00336 }
00337
00338
00339
00340
00341 void LLWalkAdjustMotion::onDeactivate()
00342 {
00343 mCharacter->removeAnimationData("Walk Speed");
00344 }
00345
00346
00347
00348
00349 LLMotion::LLMotionInitStatus LLFlyAdjustMotion::onInitialize(LLCharacter *character)
00350 {
00351 mCharacter = character;
00352
00353 LLJoint* pelvisJoint = mCharacter->getJoint("mPelvis");
00354 mPelvisState.setJoint( pelvisJoint );
00355 if ( !pelvisJoint )
00356 {
00357 llwarns << getName() << ": Can't get pelvis joint." << llendl;
00358 return STATUS_FAILURE;
00359 }
00360
00361 mPelvisState.setUsage(LLJointState::POS | LLJointState::ROT);
00362 addJointState( &mPelvisState );
00363
00364 return STATUS_SUCCESS;
00365 }
00366
00367
00368
00369
00370 BOOL LLFlyAdjustMotion::onActivate()
00371 {
00372 mPelvisState.setPosition(LLVector3::zero);
00373 mPelvisState.setRotation(LLQuaternion::DEFAULT);
00374 mRoll = 0.f;
00375 return TRUE;
00376 }
00377
00378
00379
00380
00381 BOOL LLFlyAdjustMotion::onUpdate(F32 time, U8* joint_mask)
00382 {
00383 LLVector3 ang_vel = mCharacter->getCharacterAngularVelocity() * mCharacter->getTimeDilation();
00384 F32 speed = mCharacter->getCharacterVelocity().magVec();
00385
00386 F32 roll_factor = clamp_rescale(speed, 7.f, 15.f, 0.f, -MAX_ROLL);
00387 F32 target_roll = llclamp(ang_vel.mV[VZ], -4.f, 4.f) * roll_factor;
00388
00389
00390 mRoll = lerp(mRoll, target_roll, LLCriticalDamp::getInterpolant(0.1f));
00391
00392
00393
00394 LLQuaternion roll(mRoll, LLVector3(0.f, 0.f, 1.f));
00395 mPelvisState.setRotation(roll);
00396
00397
00398
00399
00400
00401 return TRUE;
00402 }