PageRenderTime 29ms CodeModel.GetById 16ms RepoModel.GetById 0ms app.codeStats 0ms

/indra/llcharacter/llkeyframewalkmotion.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 392 lines | 192 code | 70 blank | 130 comment | 5 complexity | 8c05f29a14f77b68a16afed9b5e3c0a3 MD5 | raw file
Possible License(s): LGPL-2.1
  1. /**
  2. * @file llkeyframewalkmotion.cpp
  3. * @brief Implementation of LLKeyframeWalkMotion class.
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewerlgpl$
  6. * Second Life Viewer Source Code
  7. * Copyright (C) 2010, Linden Research, Inc.
  8. *
  9. * This library is free software; you can redistribute it and/or
  10. * modify it under the terms of the GNU Lesser General Public
  11. * License as published by the Free Software Foundation;
  12. * version 2.1 of the License only.
  13. *
  14. * This library is distributed in the hope that it will be useful,
  15. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  17. * Lesser General Public License for more details.
  18. *
  19. * You should have received a copy of the GNU Lesser General Public
  20. * License along with this library; if not, write to the Free Software
  21. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  22. *
  23. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  24. * $/LicenseInfo$
  25. */
  26. //-----------------------------------------------------------------------------
  27. // Header Files
  28. //-----------------------------------------------------------------------------
  29. #include "linden_common.h"
  30. #include "llkeyframewalkmotion.h"
  31. #include "llcharacter.h"
  32. #include "llmath.h"
  33. #include "m3math.h"
  34. #include "llcriticaldamp.h"
  35. //-----------------------------------------------------------------------------
  36. // Macros
  37. //-----------------------------------------------------------------------------
  38. const F32 MAX_WALK_PLAYBACK_SPEED = 8.f; // max m/s for which we adjust walk cycle speed
  39. const F32 MIN_WALK_SPEED = 0.1f; // minimum speed at which we use velocity for down foot detection
  40. const F32 TIME_EPSILON = 0.001f; // minumum frame time
  41. const F32 MAX_TIME_DELTA = 2.f; // max two seconds a frame for calculating interpolation
  42. F32 SPEED_ADJUST_MAX_SEC = 2.f; // maximum adjustment to walk animation playback speed for a second
  43. F32 ANIM_SPEED_MAX = 1.5f; // absolute upper limit on animation speed
  44. const F32 DRIFT_COMP_MAX_TOTAL = 0.1f; // maximum drift compensation overall, in any direction
  45. const F32 DRIFT_COMP_MAX_SPEED = 4.f; // speed at which drift compensation total maxes out
  46. const F32 MAX_ROLL = 0.6f;
  47. const F32 PELVIS_COMPENSATION_WIEGHT = 0.7f; // proportion of foot drift that is compensated by moving the avatar directly
  48. const F32 SPEED_ADJUST_TIME_CONSTANT = 0.1f; // time constant for speed adjustment interpolation
  49. //-----------------------------------------------------------------------------
  50. // LLKeyframeWalkMotion()
  51. // Class Constructor
  52. //-----------------------------------------------------------------------------
  53. LLKeyframeWalkMotion::LLKeyframeWalkMotion(const LLUUID &id)
  54. : LLKeyframeMotion(id),
  55. mCharacter(NULL),
  56. mCyclePhase(0.0f),
  57. mRealTimeLast(0.0f),
  58. mAdjTimeLast(0.0f),
  59. mDownFoot(0)
  60. {}
  61. //-----------------------------------------------------------------------------
  62. // ~LLKeyframeWalkMotion()
  63. // Class Destructor
  64. //-----------------------------------------------------------------------------
  65. LLKeyframeWalkMotion::~LLKeyframeWalkMotion()
  66. {}
  67. //-----------------------------------------------------------------------------
  68. // LLKeyframeWalkMotion::onInitialize()
  69. //-----------------------------------------------------------------------------
  70. LLMotion::LLMotionInitStatus LLKeyframeWalkMotion::onInitialize(LLCharacter *character)
  71. {
  72. mCharacter = character;
  73. return LLKeyframeMotion::onInitialize(character);
  74. }
  75. //-----------------------------------------------------------------------------
  76. // LLKeyframeWalkMotion::onActivate()
  77. //-----------------------------------------------------------------------------
  78. BOOL LLKeyframeWalkMotion::onActivate()
  79. {
  80. mRealTimeLast = 0.0f;
  81. mAdjTimeLast = 0.0f;
  82. return LLKeyframeMotion::onActivate();
  83. }
  84. //-----------------------------------------------------------------------------
  85. // LLKeyframeWalkMotion::onDeactivate()
  86. //-----------------------------------------------------------------------------
  87. void LLKeyframeWalkMotion::onDeactivate()
  88. {
  89. mCharacter->removeAnimationData("Down Foot");
  90. LLKeyframeMotion::onDeactivate();
  91. }
  92. //-----------------------------------------------------------------------------
  93. // LLKeyframeWalkMotion::onUpdate()
  94. //-----------------------------------------------------------------------------
  95. BOOL LLKeyframeWalkMotion::onUpdate(F32 time, U8* joint_mask)
  96. {
  97. // compute time since last update
  98. F32 deltaTime = time - mRealTimeLast;
  99. void* speed_ptr = mCharacter->getAnimationData("Walk Speed");
  100. F32 speed = (speed_ptr) ? *((F32 *)speed_ptr) : 1.f;
  101. // adjust the passage of time accordingly
  102. F32 adjusted_time = mAdjTimeLast + (deltaTime * speed);
  103. // save time for next update
  104. mRealTimeLast = time;
  105. mAdjTimeLast = adjusted_time;
  106. // handle wrap around
  107. if (adjusted_time < 0.0f)
  108. {
  109. adjusted_time = getDuration() + fmod(adjusted_time, getDuration());
  110. }
  111. // let the base class update the cycle
  112. return LLKeyframeMotion::onUpdate( adjusted_time, joint_mask );
  113. }
  114. // End
  115. //-----------------------------------------------------------------------------
  116. // LLWalkAdjustMotion()
  117. // Class Constructor
  118. //-----------------------------------------------------------------------------
  119. LLWalkAdjustMotion::LLWalkAdjustMotion(const LLUUID &id) :
  120. LLMotion(id),
  121. mLastTime(0.f),
  122. mAnimSpeed(0.f),
  123. mAdjustedSpeed(0.f),
  124. mRelativeDir(0.f),
  125. mAnkleOffset(0.f)
  126. {
  127. mName = "walk_adjust";
  128. mPelvisState = new LLJointState;
  129. }
  130. //-----------------------------------------------------------------------------
  131. // LLWalkAdjustMotion::onInitialize()
  132. //-----------------------------------------------------------------------------
  133. LLMotion::LLMotionInitStatus LLWalkAdjustMotion::onInitialize(LLCharacter *character)
  134. {
  135. mCharacter = character;
  136. mLeftAnkleJoint = mCharacter->getJoint("mAnkleLeft");
  137. mRightAnkleJoint = mCharacter->getJoint("mAnkleRight");
  138. mPelvisJoint = mCharacter->getJoint("mPelvis");
  139. mPelvisState->setJoint( mPelvisJoint );
  140. if ( !mPelvisJoint )
  141. {
  142. llwarns << getName() << ": Can't get pelvis joint." << llendl;
  143. return STATUS_FAILURE;
  144. }
  145. mPelvisState->setUsage(LLJointState::POS);
  146. addJointState( mPelvisState );
  147. return STATUS_SUCCESS;
  148. }
  149. //-----------------------------------------------------------------------------
  150. // LLWalkAdjustMotion::onActivate()
  151. //-----------------------------------------------------------------------------
  152. BOOL LLWalkAdjustMotion::onActivate()
  153. {
  154. mAnimSpeed = 0.f;
  155. mAdjustedSpeed = 0.f;
  156. mRelativeDir = 1.f;
  157. mPelvisState->setPosition(LLVector3::zero);
  158. // store ankle positions for next frame
  159. mLastLeftFootGlobalPos = mCharacter->getPosGlobalFromAgent(mLeftAnkleJoint->getWorldPosition());
  160. mLastLeftFootGlobalPos.mdV[VZ] = 0.0;
  161. mLastRightFootGlobalPos = mCharacter->getPosGlobalFromAgent(mRightAnkleJoint->getWorldPosition());
  162. mLastRightFootGlobalPos.mdV[VZ] = 0.0;
  163. F32 leftAnkleOffset = (mLeftAnkleJoint->getWorldPosition() - mCharacter->getCharacterPosition()).magVec();
  164. F32 rightAnkleOffset = (mRightAnkleJoint->getWorldPosition() - mCharacter->getCharacterPosition()).magVec();
  165. mAnkleOffset = llmax(leftAnkleOffset, rightAnkleOffset);
  166. return TRUE;
  167. }
  168. //-----------------------------------------------------------------------------
  169. // LLWalkAdjustMotion::onUpdate()
  170. //-----------------------------------------------------------------------------
  171. BOOL LLWalkAdjustMotion::onUpdate(F32 time, U8* joint_mask)
  172. {
  173. // delta_time is guaranteed to be non zero
  174. F32 delta_time = llclamp(time - mLastTime, TIME_EPSILON, MAX_TIME_DELTA);
  175. mLastTime = time;
  176. // find the avatar motion vector in the XY plane
  177. LLVector3 avatar_velocity = mCharacter->getCharacterVelocity() * mCharacter->getTimeDilation();
  178. avatar_velocity.mV[VZ] = 0.f;
  179. F32 speed = llclamp(avatar_velocity.magVec(), 0.f, MAX_WALK_PLAYBACK_SPEED);
  180. // grab avatar->world transforms
  181. LLQuaternion avatar_to_world_rot = mCharacter->getRootJoint()->getWorldRotation();
  182. LLQuaternion world_to_avatar_rot(avatar_to_world_rot);
  183. world_to_avatar_rot.conjugate();
  184. LLVector3 foot_slip_vector;
  185. // find foot drift along velocity vector
  186. if (speed > MIN_WALK_SPEED)
  187. { // walking/running
  188. // calculate world-space foot drift
  189. // use global coordinates to seamlessly handle region crossings
  190. LLVector3d leftFootGlobalPosition = mCharacter->getPosGlobalFromAgent(mLeftAnkleJoint->getWorldPosition());
  191. leftFootGlobalPosition.mdV[VZ] = 0.0;
  192. LLVector3 leftFootDelta(leftFootGlobalPosition - mLastLeftFootGlobalPos);
  193. mLastLeftFootGlobalPos = leftFootGlobalPosition;
  194. LLVector3d rightFootGlobalPosition = mCharacter->getPosGlobalFromAgent(mRightAnkleJoint->getWorldPosition());
  195. rightFootGlobalPosition.mdV[VZ] = 0.0;
  196. LLVector3 rightFootDelta(rightFootGlobalPosition - mLastRightFootGlobalPos);
  197. mLastRightFootGlobalPos = rightFootGlobalPosition;
  198. // get foot drift along avatar direction of motion
  199. F32 left_foot_slip_amt = leftFootDelta * avatar_velocity;
  200. F32 right_foot_slip_amt = rightFootDelta * avatar_velocity;
  201. // if right foot is pushing back faster than left foot...
  202. if (right_foot_slip_amt < left_foot_slip_amt)
  203. { //...use it to calculate optimal animation speed
  204. foot_slip_vector = rightFootDelta;
  205. }
  206. else
  207. { // otherwise use the left foot
  208. foot_slip_vector = leftFootDelta;
  209. }
  210. // calculate ideal pelvis offset so that foot is glued to ground and damp towards it
  211. // this will soak up transient slippage
  212. //
  213. // FIXME: this interacts poorly with speed adjustment
  214. // mPelvisOffset compensates for foot drift by moving the avatar pelvis in the opposite
  215. // direction of the drift, up to a certain limited distance
  216. // but this will cause the animation playback rate calculation below to
  217. // kick in too slowly and sometimes start playing the animation in reverse.
  218. //mPelvisOffset -= PELVIS_COMPENSATION_WIEGHT * (foot_slip_vector * world_to_avatar_rot);//lerp(LLVector3::zero, -1.f * (foot_slip_vector * world_to_avatar_rot), LLCriticalDamp::getInterpolant(0.1f));
  219. ////F32 drift_comp_max = DRIFT_COMP_MAX_TOTAL * (llclamp(speed, 0.f, DRIFT_COMP_MAX_SPEED) / DRIFT_COMP_MAX_SPEED);
  220. //F32 drift_comp_max = DRIFT_COMP_MAX_TOTAL;
  221. //// clamp pelvis offset to a 90 degree arc behind the nominal position
  222. //// NB: this is an ADDITIVE amount that is accumulated every frame, so clamping it alone won't do the trick
  223. //// must clamp with absolute position of pelvis in mind
  224. //LLVector3 currentPelvisPos = mPelvisState->getJoint()->getPosition();
  225. //mPelvisOffset.mV[VX] = llclamp( mPelvisOffset.mV[VX], -drift_comp_max, drift_comp_max );
  226. //mPelvisOffset.mV[VY] = llclamp( mPelvisOffset.mV[VY], -drift_comp_max, drift_comp_max );
  227. //mPelvisOffset.mV[VZ] = 0.f;
  228. //
  229. //mLastRightFootGlobalPos += LLVector3d(mPelvisOffset * avatar_to_world_rot);
  230. //mLastLeftFootGlobalPos += LLVector3d(mPelvisOffset * avatar_to_world_rot);
  231. //foot_slip_vector -= mPelvisOffset;
  232. LLVector3 avatar_movement_dir = avatar_velocity;
  233. avatar_movement_dir.normalize();
  234. // planted foot speed is avatar velocity - foot slip amount along avatar movement direction
  235. F32 foot_speed = speed - ((foot_slip_vector * avatar_movement_dir) / delta_time);
  236. // multiply animation playback rate so that foot speed matches avatar speed
  237. F32 min_speed_multiplier = clamp_rescale(speed, 0.f, 1.f, 0.f, 0.1f);
  238. F32 desired_speed_multiplier = llclamp(speed / foot_speed, min_speed_multiplier, ANIM_SPEED_MAX);
  239. // blend towards new speed adjustment value
  240. F32 new_speed_adjust = lerp(mAdjustedSpeed, desired_speed_multiplier, LLCriticalDamp::getInterpolant(SPEED_ADJUST_TIME_CONSTANT));
  241. // limit that rate at which the speed adjustment changes
  242. F32 speedDelta = llclamp(new_speed_adjust - mAdjustedSpeed, -SPEED_ADJUST_MAX_SEC * delta_time, SPEED_ADJUST_MAX_SEC * delta_time);
  243. mAdjustedSpeed += speedDelta;
  244. // modulate speed by dot products of facing and velocity
  245. // so that if we are moving sideways, we slow down the animation
  246. // and if we're moving backward, we walk backward
  247. // do this at the end to be more responsive to direction changes instead of in the above speed calculations
  248. F32 directional_factor = (avatar_movement_dir * world_to_avatar_rot).mV[VX];
  249. mAnimSpeed = mAdjustedSpeed * directional_factor;
  250. }
  251. else
  252. { // standing/turning
  253. // damp out speed adjustment to 0
  254. mAnimSpeed = lerp(mAnimSpeed, 1.f, LLCriticalDamp::getInterpolant(0.2f));
  255. //mPelvisOffset = lerp(mPelvisOffset, LLVector3::zero, LLCriticalDamp::getInterpolant(0.2f));
  256. }
  257. // broadcast walk speed change
  258. mCharacter->setAnimationData("Walk Speed", &mAnimSpeed);
  259. // set position
  260. // need to update *some* joint to keep this animation active
  261. mPelvisState->setPosition(mPelvisOffset);
  262. return TRUE;
  263. }
  264. //-----------------------------------------------------------------------------
  265. // LLWalkAdjustMotion::onDeactivate()
  266. //-----------------------------------------------------------------------------
  267. void LLWalkAdjustMotion::onDeactivate()
  268. {
  269. mCharacter->removeAnimationData("Walk Speed");
  270. }
  271. //-----------------------------------------------------------------------------
  272. // LLFlyAdjustMotion::LLFlyAdjustMotion()
  273. //-----------------------------------------------------------------------------
  274. LLFlyAdjustMotion::LLFlyAdjustMotion(const LLUUID &id)
  275. : LLMotion(id),
  276. mRoll(0.f)
  277. {
  278. mName = "fly_adjust";
  279. mPelvisState = new LLJointState;
  280. }
  281. //-----------------------------------------------------------------------------
  282. // LLFlyAdjustMotion::onInitialize()
  283. //-----------------------------------------------------------------------------
  284. LLMotion::LLMotionInitStatus LLFlyAdjustMotion::onInitialize(LLCharacter *character)
  285. {
  286. mCharacter = character;
  287. LLJoint* pelvisJoint = mCharacter->getJoint("mPelvis");
  288. mPelvisState->setJoint( pelvisJoint );
  289. if ( !pelvisJoint )
  290. {
  291. llwarns << getName() << ": Can't get pelvis joint." << llendl;
  292. return STATUS_FAILURE;
  293. }
  294. mPelvisState->setUsage(LLJointState::POS | LLJointState::ROT);
  295. addJointState( mPelvisState );
  296. return STATUS_SUCCESS;
  297. }
  298. //-----------------------------------------------------------------------------
  299. // LLFlyAdjustMotion::onActivate()
  300. //-----------------------------------------------------------------------------
  301. BOOL LLFlyAdjustMotion::onActivate()
  302. {
  303. mPelvisState->setPosition(LLVector3::zero);
  304. mPelvisState->setRotation(LLQuaternion::DEFAULT);
  305. mRoll = 0.f;
  306. return TRUE;
  307. }
  308. //-----------------------------------------------------------------------------
  309. // LLFlyAdjustMotion::onUpdate()
  310. //-----------------------------------------------------------------------------
  311. BOOL LLFlyAdjustMotion::onUpdate(F32 time, U8* joint_mask)
  312. {
  313. LLVector3 ang_vel = mCharacter->getCharacterAngularVelocity() * mCharacter->getTimeDilation();
  314. F32 speed = mCharacter->getCharacterVelocity().magVec();
  315. F32 roll_factor = clamp_rescale(speed, 7.f, 15.f, 0.f, -MAX_ROLL);
  316. F32 target_roll = llclamp(ang_vel.mV[VZ], -4.f, 4.f) * roll_factor;
  317. // roll is critically damped interpolation between current roll and angular velocity-derived target roll
  318. mRoll = lerp(mRoll, target_roll, LLCriticalDamp::getInterpolant(0.1f));
  319. LLQuaternion roll(mRoll, LLVector3(0.f, 0.f, 1.f));
  320. mPelvisState->setRotation(roll);
  321. return TRUE;
  322. }