llkeyframewalkmotion.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. /**
  2. * @file llkeyframewalkmotion.cpp
  3. * @brief Implementation of LLKeyframeWalkMotion class.
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "linden_common.h"
  33. #include "llkeyframewalkmotion.h"
  34. #include "llcharacter.h"
  35. #include "llcriticaldamp.h"
  36. #include "llmath.h"
  37. #include "llmatrix3.h"
  38. // Max speed (m/s) for which we adjust walk cycle speed
  39. constexpr F32 MAX_WALK_PLAYBACK_SPEED = 8.f;
  40. // Maximum two seconds a frame for calculating interpolation
  41. constexpr F32 MAX_TIME_DELTA = 2.f;
  42. // Maximum adjustment of walk animation playback speed
  43. constexpr F32 SPEED_ADJUST_MAX = 2.5f;
  44. // Maximum adjustment to walk animation playback speed for a second
  45. constexpr F32 SPEED_ADJUST_MAX_SEC = 3.f;
  46. // Final scaling for walk animation
  47. constexpr F32 SPEED_FINAL_SCALING = 0.5f;
  48. // Maximum drift compensation overall, in any direction
  49. constexpr F32 DRIFT_COMP_MAX_TOTAL = 0.07f; // 0.55f;
  50. // Speed at which drift compensation total maxes out
  51. constexpr F32 DRIFT_COMP_MAX_SPEED = 4.f;
  52. constexpr F32 MAX_ROLL = 0.6f;
  53. //-----------------------------------------------------------------------------
  54. // LLKeyframeWalkMotion() class
  55. //-----------------------------------------------------------------------------
  56. LLKeyframeWalkMotion::LLKeyframeWalkMotion(const LLUUID& id)
  57. : LLKeyframeMotion(id),
  58. mCharacter(NULL),
  59. mRealTimeLast(0.f),
  60. mAdjTimeLast(0.f)
  61. {
  62. }
  63. LLMotion::LLMotionInitStatus LLKeyframeWalkMotion::onInitialize(LLCharacter* character)
  64. {
  65. mCharacter = character;
  66. return LLKeyframeMotion::onInitialize(character);
  67. }
  68. bool LLKeyframeWalkMotion::onActivate()
  69. {
  70. mRealTimeLast = mAdjTimeLast = 0.f;
  71. return LLKeyframeMotion::onActivate();
  72. }
  73. void LLKeyframeWalkMotion::onDeactivate()
  74. {
  75. mCharacter->removeAnimationData("Down Foot");
  76. LLKeyframeMotion::onDeactivate();
  77. }
  78. bool LLKeyframeWalkMotion::onUpdate(F32 time, U8* joint_mask)
  79. {
  80. // compute time since last update
  81. F32 delta_time = time - mRealTimeLast;
  82. void* speed_ptr = mCharacter->getAnimationData("Walk Speed");
  83. F32 speed = speed_ptr ? *((F32*)speed_ptr) : 1.f;
  84. // Adjust the passage of time accordingly
  85. F32 adjusted_time = mAdjTimeLast + delta_time * speed;
  86. // Save time for next update
  87. mRealTimeLast = time;
  88. mAdjTimeLast = adjusted_time;
  89. // handle wrap around
  90. if (adjusted_time < 0.f)
  91. {
  92. adjusted_time = getDuration() + fmod(adjusted_time, getDuration());
  93. }
  94. // Let the base class update the cycle
  95. return LLKeyframeMotion::onUpdate(adjusted_time, joint_mask);
  96. }
  97. //-----------------------------------------------------------------------------
  98. // LLWalkAdjustMotion() class
  99. //-----------------------------------------------------------------------------
  100. LLWalkAdjustMotion::LLWalkAdjustMotion(const LLUUID& id)
  101. : LLMotion(id),
  102. mLastTime(0.f),
  103. mAvgCorrection(0.f),
  104. mSpeedAdjust(0.f),
  105. mAnimSpeed(0.f),
  106. mAvgSpeed(0.f),
  107. mRelativeDir(0.f),
  108. mAnkleOffset(0.f)
  109. {
  110. mName = "walk_adjust";
  111. mPelvisState = new LLJointState;
  112. }
  113. LLMotion::LLMotionInitStatus LLWalkAdjustMotion::onInitialize(LLCharacter* character)
  114. {
  115. mCharacter = character;
  116. mLeftAnkleJoint = mCharacter->getJoint(LL_JOINT_KEY_ANKLELEFT);
  117. mRightAnkleJoint = mCharacter->getJoint(LL_JOINT_KEY_ANKLERIGHT);
  118. mPelvisJoint = mCharacter->getJoint(LL_JOINT_KEY_PELVIS);
  119. mPelvisState->setJoint(mPelvisJoint);
  120. if (!mPelvisJoint)
  121. {
  122. llwarns << getName() << ": cannot get pelvis joint." << llendl;
  123. return STATUS_FAILURE;
  124. }
  125. mPelvisState->setUsage(LLJointState::POS);
  126. addJointState(mPelvisState);
  127. return STATUS_SUCCESS;
  128. }
  129. bool LLWalkAdjustMotion::onActivate()
  130. {
  131. mAvgCorrection = 0.f;
  132. mSpeedAdjust = 0.f;
  133. mAnimSpeed = 0.f;
  134. mAvgSpeed = 0.f;
  135. mRelativeDir = 1.f;
  136. mPelvisState->setPosition(LLVector3::zero);
  137. // store ankle positions for next frame
  138. mLastLeftAnklePos = mCharacter->getPosGlobalFromAgent(mLeftAnkleJoint->getWorldPosition());
  139. mLastRightAnklePos = mCharacter->getPosGlobalFromAgent(mRightAnkleJoint->getWorldPosition());
  140. F32 left_ankle_offset = (mLeftAnkleJoint->getWorldPosition() -
  141. mCharacter->getCharacterPosition()).length();
  142. F32 right_ankle_offset = (mRightAnkleJoint->getWorldPosition() -
  143. mCharacter->getCharacterPosition()).length();
  144. mAnkleOffset = llmax(left_ankle_offset, right_ankle_offset);
  145. return true;
  146. }
  147. bool LLWalkAdjustMotion::onUpdate(F32 time, U8* joint_mask)
  148. {
  149. LLVector3 foot_corr;
  150. LLVector3 vel = mCharacter->getCharacterVelocity() * mCharacter->getTimeDilation();
  151. F32 delta_time = llclamp(time - mLastTime, 0.f, MAX_TIME_DELTA);
  152. mLastTime = time;
  153. LLQuaternion inv_rotation = ~mPelvisJoint->getWorldRotation();
  154. // get speed and normalize velocity vector
  155. LLVector3 ang_vel = mCharacter->getCharacterAngularVelocity() *
  156. mCharacter->getTimeDilation();
  157. F32 speed = llmin(vel.normalize(), MAX_WALK_PLAYBACK_SPEED);
  158. mAvgSpeed = lerp(mAvgSpeed, speed, LLCriticalDamp::getInterpolant(0.2f));
  159. // calculate facing vector in pelvis-local space
  160. // (either straight forward or back, depending on velocity)
  161. LLVector3 local_vel = vel * inv_rotation;
  162. if (local_vel.mV[VX] > 0.f)
  163. {
  164. mRelativeDir = 1.f;
  165. }
  166. else if (local_vel.mV[VX] < 0.f)
  167. {
  168. mRelativeDir = -1.f;
  169. }
  170. // calculate world-space foot drift
  171. LLVector3 left_ft_world_pos = mLeftAnkleJoint->getWorldPosition();
  172. LLVector3d left_ft_global_pos = mCharacter->getPosGlobalFromAgent(left_ft_world_pos);
  173. LLVector3 left_ft_delta(mLastLeftAnklePos - left_ft_global_pos);
  174. mLastLeftAnklePos = left_ft_global_pos;
  175. LLVector3 right_ft_world_pos = mRightAnkleJoint->getWorldPosition();
  176. LLVector3d right_ft_global_pos = mCharacter->getPosGlobalFromAgent(right_ft_world_pos);
  177. LLVector3 right_ft_delta(mLastRightAnklePos - right_ft_global_pos);
  178. mLastRightAnklePos = right_ft_global_pos;
  179. // find foot drift along velocity vector
  180. if (mAvgSpeed > 0.1)
  181. {
  182. // walking/running
  183. F32 leftFootDriftAmt = left_ft_delta * vel;
  184. F32 rightFootDriftAmt = right_ft_delta * vel;
  185. if (rightFootDriftAmt > leftFootDriftAmt)
  186. {
  187. foot_corr = right_ft_delta;
  188. } else
  189. {
  190. foot_corr = left_ft_delta;
  191. }
  192. }
  193. else
  194. {
  195. mAvgSpeed = ang_vel.length() * mAnkleOffset;
  196. mRelativeDir = 1.f;
  197. // standing/turning; find the lower foot
  198. if (left_ft_world_pos.mV[VZ] < right_ft_world_pos.mV[VZ])
  199. {
  200. // pivot on left foot
  201. foot_corr = left_ft_delta;
  202. }
  203. else
  204. {
  205. // pivot on right foot
  206. foot_corr = right_ft_delta;
  207. }
  208. }
  209. // rotate into avatar coordinates
  210. foot_corr = foot_corr * inv_rotation;
  211. // calculate ideal pelvis offset so that foot is glued to ground and damp
  212. // towards it the amount of foot slippage this frame + the offset applied
  213. // last frame
  214. mPelvisOffset = mPelvisState->getPosition() +
  215. lerp(LLVector3::zero, foot_corr,
  216. LLCriticalDamp::getInterpolant(0.2f));
  217. // pelvis drift (along walk direction)
  218. mAvgCorrection = lerp(mAvgCorrection, foot_corr.mV[VX] * mRelativeDir,
  219. LLCriticalDamp::getInterpolant(0.1f));
  220. // calculate average velocity of foot slippage
  221. F32 foot_slip_velocity = delta_time != 0.f ? -mAvgCorrection / delta_time
  222. : 0.f;
  223. // Modulate speed by dot products of facing and velocity so that if we are
  224. // moving sideways, we slow down the animation and if we are moving
  225. // backward, we walk backward.
  226. F32 directional_factor = local_vel.mV[VX] * mRelativeDir;
  227. F32 new_speed_adj = 0.f;
  228. if (speed > 0.1f)
  229. {
  230. // calculate ratio of desired foot velocity to detected foot velocity
  231. new_speed_adj = llclamp(foot_slip_velocity -
  232. mAvgSpeed * (1.f - directional_factor),
  233. -SPEED_ADJUST_MAX, SPEED_ADJUST_MAX);
  234. new_speed_adj = lerp(mSpeedAdjust, new_speed_adj,
  235. LLCriticalDamp::getInterpolant(0.2f));
  236. F32 speed_delta = new_speed_adj - mSpeedAdjust;
  237. speed_delta = llclamp(speed_delta, -SPEED_ADJUST_MAX_SEC * delta_time,
  238. SPEED_ADJUST_MAX_SEC * delta_time);
  239. mSpeedAdjust = mSpeedAdjust + speed_delta;
  240. }
  241. else
  242. {
  243. mSpeedAdjust = lerp(mSpeedAdjust, 0.f,
  244. LLCriticalDamp::getInterpolant(0.2f));
  245. }
  246. mAnimSpeed = (mAvgSpeed + mSpeedAdjust) * mRelativeDir;
  247. mAnimSpeed = mAnimSpeed * SPEED_FINAL_SCALING;
  248. mCharacter->setAnimationData("Walk Speed", &mAnimSpeed);
  249. // clamp pelvis offset to a 90 degree arc behind the nominal position
  250. constexpr F32 drift_factor = DRIFT_COMP_MAX_TOTAL / DRIFT_COMP_MAX_SPEED;
  251. F32 drift_comp_max = drift_factor *
  252. llclamp(speed, 0.f, DRIFT_COMP_MAX_SPEED);
  253. LLVector3 currentPelvisPos = mPelvisState->getJoint()->getPosition();
  254. // NB: this is an ADDITIVE amount that is accumulated every frame, so
  255. // clamping it alone won't do the trick must clamp with absolute position
  256. // of pelvis in mind
  257. mPelvisOffset.mV[VX] = llclamp(mPelvisOffset.mV[VX],
  258. -drift_comp_max - currentPelvisPos.mV[VX],
  259. drift_comp_max - currentPelvisPos.mV[VX]);
  260. mPelvisOffset.mV[VY] = llclamp(mPelvisOffset.mV[VY],
  261. -drift_comp_max - currentPelvisPos.mV[VY],
  262. drift_comp_max - currentPelvisPos.mV[VY]);
  263. mPelvisOffset.mV[VZ] = 0.f;
  264. // set position
  265. mPelvisState->setPosition(mPelvisOffset);
  266. mCharacter->setAnimationData("Pelvis Offset", &mPelvisOffset);
  267. return true;
  268. }
  269. void LLWalkAdjustMotion::onDeactivate()
  270. {
  271. mCharacter->removeAnimationData("Walk Speed");
  272. }
  273. //-----------------------------------------------------------------------------
  274. // LLFlyAdjustMotion() class
  275. //-----------------------------------------------------------------------------
  276. LLFlyAdjustMotion::LLFlyAdjustMotion(const LLUUID& id)
  277. : LLMotion(id),
  278. mRoll(0.f)
  279. {
  280. mName = "fly_adjust";
  281. mPelvisState = new LLJointState;
  282. }
  283. LLMotion::LLMotionInitStatus LLFlyAdjustMotion::onInitialize(LLCharacter* character)
  284. {
  285. mCharacter = character;
  286. LLJoint* pelvisJoint = mCharacter->getJoint(LL_JOINT_KEY_PELVIS);
  287. mPelvisState->setJoint(pelvisJoint);
  288. if (!pelvisJoint)
  289. {
  290. llwarns << getName() << ": cannot get pelvis joint." << llendl;
  291. return STATUS_FAILURE;
  292. }
  293. mPelvisState->setUsage(LLJointState::POS | LLJointState::ROT);
  294. addJointState(mPelvisState);
  295. return STATUS_SUCCESS;
  296. }
  297. bool LLFlyAdjustMotion::onActivate()
  298. {
  299. mPelvisState->setPosition(LLVector3::zero);
  300. mPelvisState->setRotation(LLQuaternion::DEFAULT);
  301. mRoll = 0.f;
  302. return true;
  303. }
  304. bool LLFlyAdjustMotion::onUpdate(F32 time, U8* joint_mask)
  305. {
  306. LLVector3 ang_vel = mCharacter->getCharacterAngularVelocity() *
  307. mCharacter->getTimeDilation();
  308. F32 speed = mCharacter->getCharacterVelocity().length();
  309. F32 roll_factor = clamp_rescale(speed, 7.f, 15.f, 0.f, -MAX_ROLL);
  310. F32 target_roll = llclamp(ang_vel.mV[VZ], -4.f, 4.f) * roll_factor;
  311. // Roll is critically damped interpolation between current roll and angular
  312. // velocity-derived target roll
  313. mRoll = lerp(mRoll, target_roll, LLCriticalDamp::getInterpolant(0.1f));
  314. LLQuaternion roll(mRoll, LLVector3(0.f, 0.f, 1.f));
  315. mPelvisState->setRotation(roll);
  316. return true;
  317. }