IKEffector.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372
  1. //
  2. // Copyright (c) 2008-2016 the Urho3D project.
  3. //
  4. // Permission is hereby granted, free of charge, to any person obtaining a copy
  5. // of this software and associated documentation files (the "Software"), to deal
  6. // in the Software without restriction, including without limitation the rights
  7. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. // copies of the Software, and to permit persons to whom the Software is
  9. // furnished to do so, subject to the following conditions:
  10. //
  11. // The above copyright notice and this permission notice shall be included in
  12. // all copies or substantial portions of the Software.
  13. //
  14. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. // THE SOFTWARE.
  21. //
  22. #include "../Core/Context.h"
  23. #include "../Graphics/DebugRenderer.h"
  24. #include "../IK/IKConverters.h"
  25. #include "../IK/IKEffector.h"
  26. #include "../IK/IKEvents.h"
  27. #include "../IK/IKSolver.h"
  28. #include "../Scene/SceneEvents.h"
  29. #include "../IO/Log.h"
  30. #include <ik/node.h>
  31. #include <ik/effector.h>
  32. #include <ik/solver.h>
  33. #include <ik/util.h>
  34. namespace Atomic
  35. {
  36. extern const char* IK_CATEGORY;
  37. // ----------------------------------------------------------------------------
  38. IKEffector::IKEffector(Context* context) :
  39. Component(context),
  40. ikEffectorNode_(NULL),
  41. chainLength_(0),
  42. weight_(1.0f),
  43. rotationWeight_(1.0),
  44. rotationDecay_(0.25),
  45. features_(0)
  46. {
  47. ATOMIC_LOGDEBUG("IKEffector created");
  48. }
  49. // ----------------------------------------------------------------------------
  50. IKEffector::~IKEffector()
  51. {
  52. ATOMIC_LOGDEBUG("IKEffector destroyed");
  53. }
  54. // ----------------------------------------------------------------------------
  55. void IKEffector::RegisterObject(Context* context)
  56. {
  57. context->RegisterFactory<IKEffector>(IK_CATEGORY);
  58. ATOMIC_ACCESSOR_ATTRIBUTE("Target Node", GetTargetName, SetTargetName, String, String::EMPTY, AM_DEFAULT);
  59. ATOMIC_ACCESSOR_ATTRIBUTE("Chain Length", GetChainLength, SetChainLength, unsigned, 0, AM_DEFAULT);
  60. ATOMIC_ACCESSOR_ATTRIBUTE("Target Position", GetTargetPosition, SetTargetPosition, Vector3, Vector3::ZERO, AM_DEFAULT);
  61. ATOMIC_MIXED_ACCESSOR_ATTRIBUTE("Target Rotation", GetTargetRotationEuler, SetTargetRotationEuler, Vector3, Vector3::ZERO, AM_DEFAULT);
  62. ATOMIC_ACCESSOR_ATTRIBUTE("Weight", GetWeight, SetWeight, float, 1.0, AM_DEFAULT);
  63. ATOMIC_ACCESSOR_ATTRIBUTE("Rotation Weight", GetRotationWeight, SetRotationWeight, float, 1.0, AM_DEFAULT);
  64. ATOMIC_ACCESSOR_ATTRIBUTE("Rotation Decay", GetRotationDecay, SetRotationDecay, float, 0.25, AM_DEFAULT);
  65. ATOMIC_ACCESSOR_ATTRIBUTE("Nlerp Weight", WeightedNlerpEnabled, EnableWeightedNlerp, bool, false, AM_DEFAULT);
  66. ATOMIC_ACCESSOR_ATTRIBUTE("Inherit Parent Rotation", InheritParentRotationEnabled, EnableInheritParentRotation, bool, false, AM_DEFAULT);
  67. }
  68. // ----------------------------------------------------------------------------
  69. Node* IKEffector::GetTargetNode() const
  70. {
  71. return targetNode_;
  72. }
  73. // ----------------------------------------------------------------------------
  74. void IKEffector::SetTargetNode(Node* targetNode)
  75. {
  76. using namespace IKEffectorTargetChanged;
  77. VariantMap& eventData = GetEventDataMap();
  78. eventData[P_EFFECTORNODE] = node_; // The effector node that has changed targets
  79. eventData[P_TARGETNODE] = targetNode_; // The new target node. NOTE: Can be NULL (means no target)
  80. SendEvent(E_IKEFFECTORTARGETCHANGED, eventData);
  81. // Finally change the target node
  82. targetNode_ = targetNode;
  83. targetName_ = targetNode != NULL ? targetNode->GetName() : "";
  84. }
  85. // ----------------------------------------------------------------------------
  86. const String& IKEffector::GetTargetName() const
  87. {
  88. return targetName_;
  89. }
  90. // ----------------------------------------------------------------------------
  91. void IKEffector::SetTargetName(const String& nodeName)
  92. {
  93. targetName_ = nodeName;
  94. targetNode_ = NULL;
  95. }
  96. // ----------------------------------------------------------------------------
  97. const Vector3& IKEffector::GetTargetPosition() const
  98. {
  99. return targetPosition_;
  100. }
  101. // ----------------------------------------------------------------------------
  102. void IKEffector::SetTargetPosition(const Vector3& targetPosition)
  103. {
  104. targetPosition_ = targetPosition;
  105. if (ikEffectorNode_ != NULL)
  106. ikEffectorNode_->effector->target_position = Vec3Urho2IK(targetPosition);
  107. }
  108. // ----------------------------------------------------------------------------
  109. const Quaternion& IKEffector::GetTargetRotation() const
  110. {
  111. return targetRotation_;
  112. }
  113. // ----------------------------------------------------------------------------
  114. void IKEffector::SetTargetRotation(const Quaternion& targetRotation)
  115. {
  116. targetRotation_ = targetRotation;
  117. if (ikEffectorNode_)
  118. ikEffectorNode_->effector->target_rotation = QuatUrho2IK(targetRotation);
  119. }
  120. // ----------------------------------------------------------------------------
  121. Vector3 IKEffector::GetTargetRotationEuler() const
  122. {
  123. return targetRotation_.EulerAngles();
  124. }
  125. // ----------------------------------------------------------------------------
  126. void IKEffector::SetTargetRotationEuler(const Vector3& targetRotation)
  127. {
  128. SetTargetRotation(Quaternion(targetRotation.x_, targetRotation.y_, targetRotation.z_));
  129. }
  130. // ----------------------------------------------------------------------------
  131. unsigned int IKEffector::GetChainLength() const
  132. {
  133. return chainLength_;
  134. }
  135. // ----------------------------------------------------------------------------
  136. void IKEffector::SetChainLength(unsigned chainLength)
  137. {
  138. chainLength_ = chainLength;
  139. if (ikEffectorNode_ != NULL)
  140. {
  141. ikEffectorNode_->effector->chain_length = chainLength;
  142. solver_->MarkChainsNeedUpdating();
  143. }
  144. }
  145. // ----------------------------------------------------------------------------
  146. float IKEffector::GetWeight() const
  147. {
  148. return weight_;
  149. }
  150. // ----------------------------------------------------------------------------
  151. void IKEffector::SetWeight(float weight)
  152. {
  153. weight_ = Clamp(weight, 0.0f, 1.0f);
  154. if (ikEffectorNode_ != NULL)
  155. ikEffectorNode_->effector->weight = weight_;
  156. }
  157. // ----------------------------------------------------------------------------
  158. float IKEffector::GetRotationWeight() const
  159. {
  160. return rotationWeight_;
  161. }
  162. // ----------------------------------------------------------------------------
  163. void IKEffector::SetRotationWeight(float weight)
  164. {
  165. rotationWeight_ = Clamp(weight, 0.0f, 1.0f);
  166. if (ikEffectorNode_ != NULL)
  167. {
  168. ikEffectorNode_->rotation_weight = rotationWeight_;
  169. ik_calculate_rotation_weight_decays(&solver_->solver_->chain_tree);
  170. }
  171. }
  172. // ----------------------------------------------------------------------------
  173. float IKEffector::GetRotationDecay() const
  174. {
  175. return rotationDecay_;
  176. }
  177. // ----------------------------------------------------------------------------
  178. void IKEffector::SetRotationDecay(float decay)
  179. {
  180. rotationDecay_ = Clamp(decay, 0.0f, 1.0f);
  181. if (ikEffectorNode_ != NULL)
  182. {
  183. ikEffectorNode_->effector->rotation_decay = rotationDecay_;
  184. ik_calculate_rotation_weight_decays(&solver_->solver_->chain_tree);
  185. }
  186. }
  187. // ----------------------------------------------------------------------------
  188. void IKEffector::SetFeature(Feature feature, bool enable)
  189. {
  190. switch (feature)
  191. {
  192. case WEIGHT_NLERP:
  193. {
  194. if (ikEffectorNode_ != NULL)
  195. {
  196. ikEffectorNode_->effector->flags &= ~EFFECTOR_WEIGHT_NLERP;
  197. if (enable)
  198. ikEffectorNode_->effector->flags |= EFFECTOR_WEIGHT_NLERP;
  199. }
  200. } break;
  201. case INHERIT_PARENT_ROTATION:
  202. break;
  203. }
  204. features_ &= ~feature;
  205. if (enable)
  206. features_ |= feature;
  207. }
  208. // ----------------------------------------------------------------------------
  209. bool IKEffector::GetFeature(Feature feature) const
  210. {
  211. return (features_ & feature) != 0;
  212. }
  213. // ----------------------------------------------------------------------------
  214. void IKEffector::UpdateTargetNodePosition()
  215. {
  216. if (targetNode_ != NULL || targetName_.Empty())
  217. return;
  218. // Try to find a node with the same name as our target name
  219. SetTargetNode(node_->GetScene()->GetChild(targetName_, true));
  220. if (targetNode_ == NULL)
  221. return;
  222. SetTargetPosition(targetNode_->GetWorldPosition());
  223. SetTargetRotation(targetNode_->GetWorldRotation());
  224. }
  225. // ----------------------------------------------------------------------------
  226. void IKEffector::DrawDebugGeometry(bool depthTest)
  227. {
  228. DebugRenderer* debug = GetScene()->GetComponent<DebugRenderer>();
  229. if (debug)
  230. DrawDebugGeometry(debug, depthTest);
  231. }
  232. // ----------------------------------------------------------------------------
  233. void IKEffector::DrawDebugGeometry(DebugRenderer* debug, bool depthTest)
  234. {
  235. Node* terminationNode;
  236. if (solver_ == NULL)
  237. terminationNode = GetScene();
  238. else
  239. terminationNode = solver_->GetNode();
  240. // Calculate average length of all segments so we can determine the radius
  241. // of the debug spheres to draw
  242. int chainLength = chainLength_ == 0 ? -1 : chainLength_;
  243. Node* a = node_;
  244. float averageLength = 0.0f;
  245. unsigned numberOfSegments = 0;
  246. while (a && a != terminationNode->GetParent() && chainLength-- != 0)
  247. {
  248. averageLength += a->GetPosition().Length();
  249. ++numberOfSegments;
  250. a = a->GetParent();
  251. }
  252. averageLength /= numberOfSegments;
  253. // connect all chained nodes together with lines
  254. chainLength = chainLength_ == 0 ? -1 : chainLength_;
  255. a = node_;
  256. Node* b = a->GetParent();
  257. debug->AddSphere(
  258. Sphere(a->GetWorldPosition(), averageLength * 0.1f),
  259. Color::YELLOW,
  260. depthTest
  261. );
  262. while (b && b != terminationNode->GetParent() && chainLength-- != 0)
  263. {
  264. debug->AddLine(
  265. a->GetWorldPosition(),
  266. b->GetWorldPosition(),
  267. Color::WHITE,
  268. depthTest
  269. );
  270. debug->AddSphere(
  271. Sphere(b->GetWorldPosition(), averageLength * 0.1f),
  272. Color::YELLOW,
  273. depthTest
  274. );
  275. a = b;
  276. b = b->GetParent();
  277. }
  278. Vector3 direction = targetRotation_ * Vector3::FORWARD;
  279. direction = direction * averageLength + targetPosition_;
  280. debug->AddSphere(Sphere(targetPosition_, averageLength * 0.2f), Color(255, 128, 0), depthTest);
  281. debug->AddLine(targetPosition_, direction, Color(255, 128, 0), depthTest);
  282. }
  283. // ----------------------------------------------------------------------------
  284. void IKEffector::SetIKEffectorNode(ik_node_t* effectorNode)
  285. {
  286. ikEffectorNode_ = effectorNode;
  287. if (effectorNode)
  288. {
  289. ikEffectorNode_->effector->target_position = Vec3Urho2IK(targetPosition_);
  290. ikEffectorNode_->effector->target_rotation = QuatUrho2IK(targetRotation_);
  291. ikEffectorNode_->effector->weight = weight_;
  292. ikEffectorNode_->effector->rotation_weight = rotationWeight_;
  293. ikEffectorNode_->effector->rotation_decay = rotationDecay_;
  294. ikEffectorNode_->effector->chain_length = chainLength_;
  295. if (features_ & WEIGHT_NLERP)
  296. ikEffectorNode_->effector->flags |= EFFECTOR_WEIGHT_NLERP;
  297. }
  298. }
  299. // ----------------------------------------------------------------------------
  300. void IKEffector::SetIKSolver(IKSolver* solver)
  301. {
  302. solver_ = solver;
  303. }
  304. // ----------------------------------------------------------------------------
  305. // Need these wrapper functions flags of GetFeature/SetFeature can be correctly
  306. // exposed to the editor
  307. // ----------------------------------------------------------------------------
  308. #define DEF_FEATURE_GETTER(feature_name) \
  309. bool IKEffector::Get##feature_name() const \
  310. { \
  311. return GetFeature(feature_name); \
  312. }
  313. #define DEF_FEATURE_SETTER(feature_name) \
  314. void IKEffector::Set##feature_name(bool enable) \
  315. { \
  316. SetFeature(feature_name, enable); \
  317. }
  318. DEF_FEATURE_GETTER(WEIGHT_NLERP)
  319. DEF_FEATURE_GETTER(INHERIT_PARENT_ROTATION)
  320. DEF_FEATURE_SETTER(WEIGHT_NLERP)
  321. DEF_FEATURE_SETTER(INHERIT_PARENT_ROTATION)
  322. } // namespace Atomic