lljointsolverrp3.cpp 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. /**
  2. * @file lljointsolverrp3.cpp
  3. * @brief Implementation of LLJointSolverRP3 class.
  4. * Joint solver in Real Projective 3D space (RP3).
  5. * See: https://en.wikipedia.org/wiki/Real_projective_space
  6. *
  7. * $LicenseInfo:firstyear=2001&license=viewergpl$
  8. *
  9. * Copyright (c) 2001-2009, Linden Research, Inc.
  10. *
  11. * Second Life Viewer Source Code
  12. * The source code in this file ("Source Code") is provided by Linden Lab
  13. * to you under the terms of the GNU General Public License, version 2.0
  14. * ("GPL"), unless you have obtained a separate licensing agreement
  15. * ("Other License"), formally executed by you and Linden Lab. Terms of
  16. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  17. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  18. *
  19. * There are special exceptions to the terms and conditions of the GPL as
  20. * it is applied to this Source Code. View the full text of the exception
  21. * in the file doc/FLOSS-exception.txt in this software distribution, or
  22. * online at
  23. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  24. *
  25. * By copying, modifying or distributing this software, you acknowledge
  26. * that you have read and understood your obligations described above,
  27. * and agree to abide by those obligations.
  28. *
  29. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  30. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  31. * COMPLETENESS OR PERFORMANCE.
  32. * $/LicenseInfo$
  33. */
  34. #include "linden_common.h"
  35. #include "lljointsolverrp3.h"
  36. #include "llmath.h"
  37. #define F_EPSILON 0.00001f
  38. LLJointSolverRP3::LLJointSolverRP3()
  39. : mJointA(NULL),
  40. mJointB(NULL),
  41. mJointC(NULL),
  42. mJointGoal(NULL),
  43. mLengthAB(1.f),
  44. mLengthBC(1.f),
  45. mUseBAxis(false),
  46. mTwist(0.f)
  47. {
  48. mPoleVector.set(1.f, 0.f, 0.f);
  49. }
  50. void LLJointSolverRP3::setupJoints(LLJoint* joint_a, LLJoint* joint_b,
  51. LLJoint* joint_c, LLJoint* joint_goal)
  52. {
  53. mJointA = joint_a;
  54. mJointB = joint_b;
  55. mJointC = joint_c;
  56. mJointGoal = joint_goal;
  57. mLengthAB = mJointB->getPosition().length();
  58. mLengthBC = mJointC->getPosition().length();
  59. mJointABaseRotation = joint_a->getRotation();
  60. mJointBBaseRotation = joint_b->getRotation();
  61. }
  62. void LLJointSolverRP3::solve()
  63. {
  64. // Setup joints in their base rotations
  65. mJointA->setRotation(mJointABaseRotation);
  66. mJointB->setRotation(mJointBBaseRotation);
  67. // Get joint positions in world space
  68. LLVector3 a_pos = mJointA->getWorldPosition();
  69. LLVector3 b_pos = mJointB->getWorldPosition();
  70. LLVector3 c_pos = mJointC->getWorldPosition();
  71. LLVector3 g_pos = mJointGoal->getWorldPosition();
  72. // Get the pole_vector in world space
  73. LLMatrix4 world_joint_a_parent_mat;
  74. if (mJointA->getParent())
  75. {
  76. world_joint_a_parent_mat = mJointA->getParent()->getWorldMatrix();
  77. }
  78. LLVector3 pole_vec = rotate_vector(mPoleVector, world_joint_a_parent_mat);
  79. LLVector3 ab_vec = b_pos - a_pos; // vector from A to B
  80. LLVector3 bc_vec = c_pos - b_pos; // vector from B to C
  81. LLVector3 ac_vec = c_pos - a_pos; // vector from A to C
  82. LLVector3 ag_vec = g_pos - a_pos; // vector from A to G (goal)
  83. // Compute needed lengths of those vectors
  84. F32 ab_len = ab_vec.length();
  85. F32 bc_len = bc_vec.length();
  86. F32 ag_len = ag_vec.length();
  87. // Compute component vector of (A->B) orthogonal to (A->C)
  88. LLVector3 abac_comp_ortho_vec = ab_vec - ac_vec * ((ab_vec * ac_vec) /
  89. (ac_vec * ac_vec));
  90. // Compute the normal of the original ABC plane (and store for later)
  91. LLVector3 abc_norm;
  92. if (!mUseBAxis)
  93. {
  94. if (are_parallel(ab_vec, bc_vec, 0.001f))
  95. {
  96. // The current solution is maxed out, so we use the axis that is
  97. // orthogonal to both pole_vec and A->B
  98. if (are_parallel(pole_vec, ab_vec, 0.001f))
  99. {
  100. // ACK ! The problem is singular
  101. if (are_parallel(pole_vec, ag_vec, 0.001f))
  102. {
  103. // The solution is also singular
  104. return;
  105. }
  106. else
  107. {
  108. abc_norm = pole_vec % ag_vec;
  109. }
  110. }
  111. else
  112. {
  113. abc_norm = pole_vec % ab_vec;
  114. }
  115. }
  116. else
  117. {
  118. abc_norm = ab_vec % bc_vec;
  119. }
  120. }
  121. else
  122. {
  123. abc_norm = mBAxis * mJointB->getWorldRotation();
  124. }
  125. // Compute rotation of B.
  126. // Angle between A->B and B->C
  127. F32 abbc_ang = angle_between(ab_vec, bc_vec);
  128. // Vector orthogonal to A->B and B->C
  129. LLVector3 abbc_ortho_vec = ab_vec % bc_vec;
  130. if (abbc_ortho_vec.lengthSquared() < 0.001f)
  131. {
  132. abbc_ortho_vec = pole_vec % ab_vec;
  133. abac_comp_ortho_vec = pole_vec;
  134. }
  135. abbc_ortho_vec.normalize();
  136. F32 ag_len_qq = ag_len * ag_len;
  137. // Angle arm for extension
  138. F32 cos_theta = (ag_len_qq - ab_len * ab_len - bc_len * bc_len) /
  139. (2.f * ab_len * bc_len);
  140. if (cos_theta > 1.f)
  141. {
  142. cos_theta = 1.f;
  143. }
  144. else if (cos_theta < -1.f)
  145. {
  146. cos_theta = -1.f;
  147. }
  148. F32 theta = acosf(cos_theta);
  149. LLQuaternion b_rot(theta - abbc_ang, abbc_ortho_vec);
  150. // Compute rotation that rotates new A->C to A->G
  151. bc_vec = bc_vec * b_rot; // rotate B->C by b_rot
  152. // Update A->C
  153. ac_vec = ab_vec + bc_vec;
  154. LLQuaternion cg_rot;
  155. cg_rot.shortestArc(ac_vec, ag_vec);
  156. // Update A->B and B->C with rotation from C to G
  157. ab_vec = ab_vec * cg_rot;
  158. bc_vec = bc_vec * cg_rot;
  159. abc_norm = abc_norm * cg_rot;
  160. ac_vec = ab_vec + bc_vec;
  161. // Compute the normal of the APG plane
  162. if (are_parallel(ag_vec, pole_vec, 0.001f))
  163. {
  164. // The solution plane is undefined ==> we are done
  165. return;
  166. }
  167. LLVector3 apg_norm = pole_vec % ag_vec;
  168. apg_norm.normalize();
  169. // Compute the normal of the new ABC plane (only necessary if we are NOT
  170. // using mBAxis
  171. if (!mUseBAxis)
  172. {
  173. if (!are_parallel(ab_vec, bc_vec, 0.001f))
  174. {
  175. abc_norm = ab_vec % bc_vec;
  176. }
  177. #if 0
  178. else
  179. {
  180. // G is either too close or too far away we will use the old
  181. // ABCnormal
  182. }
  183. #endif
  184. abc_norm.normalize();
  185. }
  186. // Calcuate plane rotation
  187. LLQuaternion p_rot;
  188. if (are_parallel(abc_norm, apg_norm, 0.001f))
  189. {
  190. if (abc_norm * apg_norm < 0.f)
  191. {
  192. // We must be PI radians off ==> rotate by PI around ag_vec
  193. p_rot.setAngleAxis(F_PI, ag_vec);
  194. }
  195. #if 0
  196. else
  197. {
  198. // We are done
  199. }
  200. #endif
  201. }
  202. else
  203. {
  204. p_rot.shortestArc(abc_norm, apg_norm);
  205. }
  206. // Compute twist rotation
  207. LLQuaternion twist_rot(mTwist, ag_vec);
  208. // Compute rotation of A
  209. LLQuaternion a_rot = cg_rot * p_rot * twist_rot;
  210. // Apply the rotations
  211. mJointB->setWorldRotation(mJointB->getWorldRotation() * b_rot);
  212. mJointA->setWorldRotation(mJointA->getWorldRotation() * a_rot);
  213. }