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 mPelvisState = new LLJointState;
00148 }
00149
00150
00151
00152
00153 LLMotion::LLMotionInitStatus LLWalkAdjustMotion::onInitialize(LLCharacter *character)
00154 {
00155 mCharacter = character;
00156 mLeftAnkleJoint = mCharacter->getJoint("mAnkleLeft");
00157 mRightAnkleJoint = mCharacter->getJoint("mAnkleRight");
00158
00159 mPelvisJoint = mCharacter->getJoint("mPelvis");
00160 mPelvisState->setJoint( mPelvisJoint );
00161 if ( !mPelvisJoint )
00162 {
00163 llwarns << getName() << ": Can't get pelvis joint." << llendl;
00164 return STATUS_FAILURE;
00165 }
00166
00167 mPelvisState->setUsage(LLJointState::POS);
00168 addJointState( mPelvisState );
00169
00170 return STATUS_SUCCESS;
00171 }
00172
00173
00174
00175
00176 BOOL LLWalkAdjustMotion::onActivate()
00177 {
00178 mAvgCorrection = 0.f;
00179 mSpeedAdjust = 0.f;
00180 mAnimSpeed = 0.f;
00181 mAvgSpeed = 0.f;
00182 mRelativeDir = 1.f;
00183 mPelvisState->setPosition(LLVector3::zero);
00184
00185 mLastLeftAnklePos = mCharacter->getPosGlobalFromAgent(mLeftAnkleJoint->getWorldPosition());
00186 mLastRightAnklePos = mCharacter->getPosGlobalFromAgent(mRightAnkleJoint->getWorldPosition());
00187
00188 F32 leftAnkleOffset = (mLeftAnkleJoint->getWorldPosition() - mCharacter->getCharacterPosition()).magVec();
00189 F32 rightAnkleOffset = (mRightAnkleJoint->getWorldPosition() - mCharacter->getCharacterPosition()).magVec();
00190 mAnkleOffset = llmax(leftAnkleOffset, rightAnkleOffset);
00191
00192 return TRUE;
00193 }
00194
00195
00196
00197
00198 BOOL LLWalkAdjustMotion::onUpdate(F32 time, U8* joint_mask)
00199 {
00200 LLVector3 footCorrection;
00201 LLVector3 vel = mCharacter->getCharacterVelocity() * mCharacter->getTimeDilation();
00202 F32 deltaTime = llclamp(time - mLastTime, 0.f, MAX_TIME_DELTA);
00203 mLastTime = time;
00204
00205 LLQuaternion inv_rotation = ~mPelvisJoint->getWorldRotation();
00206
00207
00208 LLVector3 ang_vel = mCharacter->getCharacterAngularVelocity() * mCharacter->getTimeDilation();
00209 F32 speed = llmin(vel.normVec(), MAX_WALK_PLAYBACK_SPEED);
00210 mAvgSpeed = lerp(mAvgSpeed, speed, LLCriticalDamp::getInterpolant(0.2f));
00211
00212
00213
00214 LLVector3 localVel = vel * inv_rotation;
00215 if (localVel.mV[VX] > 0.f)
00216 {
00217 mRelativeDir = 1.f;
00218 }
00219 else if (localVel.mV[VX] < 0.f)
00220 {
00221 mRelativeDir = -1.f;
00222 }
00223
00224
00225 LLVector3 leftFootDelta;
00226 LLVector3 leftFootWorldPosition = mLeftAnkleJoint->getWorldPosition();
00227 LLVector3d leftFootGlobalPosition = mCharacter->getPosGlobalFromAgent(leftFootWorldPosition);
00228 leftFootDelta.setVec(mLastLeftAnklePos - leftFootGlobalPosition);
00229 mLastLeftAnklePos = leftFootGlobalPosition;
00230
00231 LLVector3 rightFootDelta;
00232 LLVector3 rightFootWorldPosition = mRightAnkleJoint->getWorldPosition();
00233 LLVector3d rightFootGlobalPosition = mCharacter->getPosGlobalFromAgent(rightFootWorldPosition);
00234 rightFootDelta.setVec(mLastRightAnklePos - rightFootGlobalPosition);
00235 mLastRightAnklePos = rightFootGlobalPosition;
00236
00237
00238 if (mAvgSpeed > 0.1)
00239 {
00240
00241 F32 leftFootDriftAmt = leftFootDelta * vel;
00242 F32 rightFootDriftAmt = rightFootDelta * vel;
00243
00244 if (rightFootDriftAmt > leftFootDriftAmt)
00245 {
00246 footCorrection = rightFootDelta;
00247 } else
00248 {
00249 footCorrection = leftFootDelta;
00250 }
00251 }
00252 else
00253 {
00254 mAvgSpeed = ang_vel.magVec() * mAnkleOffset;
00255 mRelativeDir = 1.f;
00256
00257
00258
00259 if (leftFootWorldPosition.mV[VZ] < rightFootWorldPosition.mV[VZ])
00260 {
00261
00262 footCorrection = leftFootDelta;
00263 }
00264 else
00265 {
00266
00267 footCorrection = rightFootDelta;
00268 }
00269 }
00270
00271
00272 footCorrection = footCorrection * inv_rotation;
00273
00274
00275
00276 mPelvisOffset = mPelvisState->getPosition() + lerp(LLVector3::zero, footCorrection, LLCriticalDamp::getInterpolant(0.2f));
00277
00278
00279 mAvgCorrection = lerp(mAvgCorrection, footCorrection.mV[VX] * mRelativeDir, LLCriticalDamp::getInterpolant(0.1f));
00280
00281
00282 F32 footSlipVelocity = (deltaTime != 0.f) ? (-mAvgCorrection / deltaTime) : 0.f;
00283
00284 F32 newSpeedAdjust = 0.f;
00285
00286
00287
00288
00289
00290 F32 directional_factor = localVel.mV[VX] * mRelativeDir;
00291 if (speed > 0.1f)
00292 {
00293
00294 newSpeedAdjust = llclamp(footSlipVelocity - mAvgSpeed * (1.f - directional_factor),
00295 -SPEED_ADJUST_MAX, SPEED_ADJUST_MAX);
00296 newSpeedAdjust = lerp(mSpeedAdjust, newSpeedAdjust, LLCriticalDamp::getInterpolant(0.2f));
00297
00298 F32 speedDelta = newSpeedAdjust - mSpeedAdjust;
00299 speedDelta = llclamp(speedDelta, -SPEED_ADJUST_MAX_SEC * deltaTime, SPEED_ADJUST_MAX_SEC * deltaTime);
00300
00301 mSpeedAdjust = mSpeedAdjust + speedDelta;
00302 }
00303 else
00304 {
00305 mSpeedAdjust = lerp(mSpeedAdjust, 0.f, LLCriticalDamp::getInterpolant(0.2f));
00306 }
00307
00308 mAnimSpeed = (mAvgSpeed + mSpeedAdjust) * mRelativeDir;
00309
00310
00311
00312
00313
00314
00315
00316
00317
00318 mCharacter->setAnimationData("Walk Speed", &mAnimSpeed);
00319
00320
00321 F32 drift_comp_max = llclamp(speed, 0.f, DRIFT_COMP_MAX_SPEED) / DRIFT_COMP_MAX_SPEED;
00322 drift_comp_max *= DRIFT_COMP_MAX_TOTAL;
00323
00324 LLVector3 currentPelvisPos = mPelvisState->getJoint()->getPosition();
00325
00326
00327
00328 mPelvisOffset.mV[VX] = llclamp( mPelvisOffset.mV[VX], -drift_comp_max - currentPelvisPos.mV[VX], drift_comp_max - currentPelvisPos.mV[VX] );
00329 mPelvisOffset.mV[VY] = llclamp( mPelvisOffset.mV[VY], -drift_comp_max - currentPelvisPos.mV[VY], drift_comp_max - currentPelvisPos.mV[VY]);
00330 mPelvisOffset.mV[VZ] = 0.f;
00331
00332
00333 mPelvisState->setPosition(mPelvisOffset);
00334
00335 mCharacter->setAnimationData("Pelvis Offset", &mPelvisOffset);
00336
00337 return TRUE;
00338 }
00339
00340
00341
00342
00343 void LLWalkAdjustMotion::onDeactivate()
00344 {
00345 mCharacter->removeAnimationData("Walk Speed");
00346 }
00347
00348
00349
00350
00351 LLFlyAdjustMotion::LLFlyAdjustMotion(const LLUUID &id)
00352 : LLMotion(id)
00353 {
00354 mName = "fly_adjust";
00355
00356 mPelvisState = new LLJointState;
00357 }
00358
00359
00360
00361
00362 LLMotion::LLMotionInitStatus LLFlyAdjustMotion::onInitialize(LLCharacter *character)
00363 {
00364 mCharacter = character;
00365
00366 LLJoint* pelvisJoint = mCharacter->getJoint("mPelvis");
00367 mPelvisState->setJoint( pelvisJoint );
00368 if ( !pelvisJoint )
00369 {
00370 llwarns << getName() << ": Can't get pelvis joint." << llendl;
00371 return STATUS_FAILURE;
00372 }
00373
00374 mPelvisState->setUsage(LLJointState::POS | LLJointState::ROT);
00375 addJointState( mPelvisState );
00376
00377 return STATUS_SUCCESS;
00378 }
00379
00380
00381
00382
00383 BOOL LLFlyAdjustMotion::onActivate()
00384 {
00385 mPelvisState->setPosition(LLVector3::zero);
00386 mPelvisState->setRotation(LLQuaternion::DEFAULT);
00387 mRoll = 0.f;
00388 return TRUE;
00389 }
00390
00391
00392
00393
00394 BOOL LLFlyAdjustMotion::onUpdate(F32 time, U8* joint_mask)
00395 {
00396 LLVector3 ang_vel = mCharacter->getCharacterAngularVelocity() * mCharacter->getTimeDilation();
00397 F32 speed = mCharacter->getCharacterVelocity().magVec();
00398
00399 F32 roll_factor = clamp_rescale(speed, 7.f, 15.f, 0.f, -MAX_ROLL);
00400 F32 target_roll = llclamp(ang_vel.mV[VZ], -4.f, 4.f) * roll_factor;
00401
00402
00403 mRoll = lerp(mRoll, target_roll, LLCriticalDamp::getInterpolant(0.1f));
00404
00405
00406
00407 LLQuaternion roll(mRoll, LLVector3(0.f, 0.f, 1.f));
00408 mPelvisState->setRotation(roll);
00409
00410
00411
00412
00413
00414 return TRUE;
00415 }