lleditingmotion.cpp 7.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  1. /**
  2. * @file lleditingmotion.cpp
  3. * @brief Implementation of LLEditingMotion 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 "lleditingmotion.h"
  34. #include "llcharacter.h"
  35. #include "llcriticaldamp.h"
  36. #include "llhandmotion.h"
  37. constexpr F32 TARGET_LAG_HALF_LIFE = 0.1f; // Half-life of IK targeting
  38. S32 LLEditingMotion::sHandPose = LLHandMotion::HAND_POSE_RELAXED_R;
  39. S32 LLEditingMotion::sHandPosePriority = 3;
  40. LLEditingMotion::LLEditingMotion(const LLUUID& id)
  41. : LLMotion(id),
  42. mCharacter(NULL),
  43. mParentState(new LLJointState),
  44. mShoulderState(new LLJointState),
  45. mElbowState(new LLJointState),
  46. mWristState(new LLJointState),
  47. mTorsoState(new LLJointState)
  48. {
  49. mName = "editing";
  50. // Create kinematic chain
  51. mParentJoint.addChild(&mShoulderJoint);
  52. mShoulderJoint.addChild(&mElbowJoint);
  53. mElbowJoint.addChild(&mWristJoint);
  54. }
  55. LLMotion::LLMotionInitStatus LLEditingMotion::onInitialize(LLCharacter* character)
  56. {
  57. mCharacter = character; // Save character for future use
  58. LLJoint* shoulder_left = mCharacter->getJoint(LL_JOINT_KEY_SHOULDERLEFT);
  59. LLJoint* elbow_left = mCharacter->getJoint(LL_JOINT_KEY_ELBOWLEFT);
  60. LLJoint* wrist_left = mCharacter->getJoint(LL_JOINT_KEY_WRISTLEFT);
  61. // Make sure character skeleton is copacetic
  62. if (!shoulder_left || !elbow_left || !wrist_left)
  63. {
  64. llwarns << "Invalid skeleton for editing motion !" << llendl;
  65. return STATUS_FAILURE;
  66. }
  67. // Get the shoulder, elbow, wrist joints from the character
  68. mParentState->setJoint(shoulder_left->getParent());
  69. mShoulderState->setJoint(shoulder_left);
  70. mElbowState->setJoint(elbow_left);
  71. mWristState->setJoint(wrist_left);
  72. mTorsoState->setJoint(mCharacter->getJoint(LL_JOINT_KEY_TORSO));
  73. if (!mParentState->getJoint())
  74. {
  75. llinfos << getName() << ": Can't get parent joint." << llendl;
  76. return STATUS_FAILURE;
  77. }
  78. mWristOffset = LLVector3(0.f, 0.2f, 0.f);
  79. // Add joint states to the pose
  80. mShoulderState->setUsage(LLJointState::ROT);
  81. mElbowState->setUsage(LLJointState::ROT);
  82. mTorsoState->setUsage(LLJointState::ROT);
  83. mWristState->setUsage(LLJointState::ROT);
  84. addJointState(mShoulderState);
  85. addJointState(mElbowState);
  86. addJointState(mTorsoState);
  87. addJointState(mWristState);
  88. // Propagate joint positions to kinematic chain
  89. mParentJoint.setPosition(mParentState->getJoint()->getWorldPosition());
  90. mShoulderJoint.setPosition(mShoulderState->getJoint()->getPosition());
  91. mElbowJoint.setPosition(mElbowState->getJoint()->getPosition());
  92. mWristJoint.setPosition(mWristState->getJoint()->getPosition() +
  93. mWristOffset);
  94. // Propagate current joint rotations to kinematic chain
  95. mParentJoint.setRotation(mParentState->getJoint()->getWorldRotation());
  96. mShoulderJoint.setRotation(mShoulderState->getJoint()->getRotation());
  97. mElbowJoint.setRotation(mElbowState->getJoint()->getRotation());
  98. // Connect the ikSolver to the chain
  99. mIKSolver.setPoleVector(LLVector3(-1.f, 1.f, 0.f));
  100. // Specifying the elbow's axis will prevent bad IK for the more
  101. // singular configurations, but the axis is limb-specific -- Leviathan
  102. mIKSolver.setBAxis(LLVector3(-0.682683f, 0.f, -0.730714f));
  103. mIKSolver.setupJoints(&mShoulderJoint, &mElbowJoint, &mWristJoint, &mTarget);
  104. return STATUS_SUCCESS;
  105. }
  106. bool LLEditingMotion::onActivate()
  107. {
  108. // Propagate joint positions to kinematic chain
  109. mParentJoint.setPosition(mParentState->getJoint()->getWorldPosition());
  110. mShoulderJoint.setPosition(mShoulderState->getJoint()->getPosition());
  111. mElbowJoint.setPosition(mElbowState->getJoint()->getPosition());
  112. mWristJoint.setPosition(mWristState->getJoint()->getPosition() +
  113. mWristOffset);
  114. // Propagate current joint rotations to kinematic chain
  115. mParentJoint.setRotation(mParentState->getJoint()->getWorldRotation());
  116. mShoulderJoint.setRotation(mShoulderState->getJoint()->getRotation());
  117. mElbowJoint.setRotation(mElbowState->getJoint()->getRotation());
  118. return true;
  119. }
  120. bool LLEditingMotion::onUpdate(F32, U8* joint_mask)
  121. {
  122. bool result = true;
  123. LLVector3 focus_pt;
  124. static const std::string point_at_point = "PointAtPoint";
  125. LLVector3* point_at_pt =
  126. (LLVector3*)mCharacter->getAnimationData(point_at_point);
  127. if (!point_at_pt)
  128. {
  129. focus_pt = mLastSelectPt;
  130. result = false;
  131. }
  132. else
  133. {
  134. focus_pt = *point_at_pt;
  135. mLastSelectPt = focus_pt;
  136. }
  137. focus_pt += mCharacter->getCharacterPosition();
  138. // Propagate joint positions to kinematic chain
  139. mParentJoint.setPosition(mParentState->getJoint()->getWorldPosition());
  140. mShoulderJoint.setPosition(mShoulderState->getJoint()->getPosition());
  141. mElbowJoint.setPosition(mElbowState->getJoint()->getPosition());
  142. mWristJoint.setPosition(mWristState->getJoint()->getPosition() +
  143. mWristOffset);
  144. // Propagate current joint rotations to kinematic chain
  145. mParentJoint.setRotation(mParentState->getJoint()->getWorldRotation());
  146. mShoulderJoint.setRotation(mShoulderState->getJoint()->getRotation());
  147. mElbowJoint.setRotation(mElbowState->getJoint()->getRotation());
  148. // Update target position from character
  149. LLVector3 target = focus_pt - mParentJoint.getPosition();
  150. F32 target_dist = target.normalize();
  151. LLVector3 edit_plane_normal(1.f / F_SQRT2, 1.f / F_SQRT2, 0.f);
  152. edit_plane_normal.normalize();
  153. edit_plane_normal.rotVec(mTorsoState->getJoint()->getWorldRotation());
  154. F32 dot = edit_plane_normal * target;
  155. if (dot < 0.f)
  156. {
  157. target = target + (edit_plane_normal * (dot * 2.f));
  158. target.mV[VZ] += clamp_rescale(dot, 0.f, -1.f, 0.f, 5.f);
  159. target.normalize();
  160. }
  161. target = target * target_dist;
  162. if (!target.isFinite())
  163. {
  164. llwarns << "Non finite target in editing motion with target distance of "
  165. << target_dist << " and focus point " << focus_pt << llendl;
  166. target.set(1.f, 1.f, 1.f);
  167. }
  168. mTarget.setPosition(target + mParentJoint.getPosition());
  169. #if 0
  170. llinfos << "Point at: " << mTarget.getPosition() << llendl;
  171. #endif
  172. // Update the ikSolver
  173. if (!mTarget.getPosition().isExactlyZero())
  174. {
  175. LLQuaternion shoulder_rot = mShoulderJoint.getRotation();
  176. LLQuaternion elbow_rot = mElbowJoint.getRotation();
  177. mIKSolver.solve();
  178. // Use blending...
  179. F32 slerp_amt = LLCriticalDamp::getInterpolant(TARGET_LAG_HALF_LIFE);
  180. shoulder_rot = slerp(slerp_amt, mShoulderJoint.getRotation(),
  181. shoulder_rot);
  182. elbow_rot = slerp(slerp_amt, mElbowJoint.getRotation(), elbow_rot);
  183. // Now put blended values back into joints
  184. llassert(shoulder_rot.isFinite());
  185. llassert(elbow_rot.isFinite());
  186. mShoulderState->setRotation(shoulder_rot);
  187. mElbowState->setRotation(elbow_rot);
  188. mWristState->setRotation(LLQuaternion::DEFAULT);
  189. }
  190. static const std::string hand_pose = "Hand Pose";
  191. static const std::string hand_pose_priority = "Hand Pose Priority";
  192. mCharacter->setAnimationData(hand_pose, &sHandPose);
  193. mCharacter->setAnimationData(hand_pose_priority, &sHandPosePriority);
  194. return result;
  195. }