JointComponent.cpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #include <AnKi/Scene/Components/JointComponent.h>
  6. #include <AnKi/Scene/Components/BodyComponent.h>
  7. #include <AnKi/Scene/SceneGraph.h>
  8. #include <AnKi/Physics/PhysicsWorld.h>
  9. namespace anki {
  10. class JointComponent::JointNode : public IntrusiveListEnabled<JointNode>
  11. {
  12. public:
  13. PhysicsJointPtr m_joint;
  14. F32 m_breakingImpulse = 0.0f;
  15. class P2P
  16. {
  17. public:
  18. Vec3 m_relPosBody1 = Vec3(kMaxF32);
  19. Vec3 m_relPosBody2 = Vec3(kMaxF32);
  20. };
  21. class Hinge
  22. {
  23. public:
  24. Vec3 m_relPosBody1 = Vec3(kMaxF32);
  25. Vec3 m_relPosBody2 = Vec3(kMaxF32);
  26. Vec3 m_axis = Vec3(0.0f);
  27. };
  28. union
  29. {
  30. Hinge m_hinge = {};
  31. P2P m_p2p;
  32. };
  33. JointType m_type = JointType::kCount;
  34. JointNode() = default;
  35. };
  36. JointComponent::~JointComponent()
  37. {
  38. while(!m_jointList.isEmpty())
  39. {
  40. JointNode* jnode = &m_jointList.getFront();
  41. m_jointList.popFront();
  42. deleteInstance(SceneMemoryPool::getSingleton(), jnode);
  43. }
  44. }
  45. Vec3 JointComponent::computeLocalPivotFromFactors(const PhysicsBodyPtr& body, const Vec3& factors)
  46. {
  47. btTransform identityTrf;
  48. identityTrf.setIdentity();
  49. btVector3 aabbmin, aabbmax, center;
  50. body->getBtBody()->getCollisionShape()->getAabb(identityTrf, aabbmin, aabbmax);
  51. center = (aabbmin + aabbmax) * 0.5f;
  52. Vec3 out;
  53. for(U i = 0; i < 3; ++i)
  54. {
  55. const F32 factor = factors[i];
  56. ANKI_ASSERT(factor >= -1.0f || factor <= 1.0f);
  57. const F32 dist = aabbmax[i] - center[i];
  58. out[i] = dist * factor + center[i];
  59. }
  60. return out;
  61. }
  62. void JointComponent::newPoint2PointJoint(const Vec3& relPosFactor, F32 breakingImpulse)
  63. {
  64. JointNode* newNode = newInstance<JointNode>(SceneMemoryPool::getSingleton());
  65. newNode->m_type = JointType::kPoint;
  66. newNode->m_p2p.m_relPosBody1 = relPosFactor;
  67. newNode->m_breakingImpulse = breakingImpulse;
  68. m_jointList.pushBack(newNode);
  69. }
  70. void JointComponent::newPoint2PointJoint2(const Vec3& relPosFactorA, const Vec3& relPosFactorB, F32 breakingImpulse)
  71. {
  72. JointNode* newNode = newInstance<JointNode>(SceneMemoryPool::getSingleton());
  73. newNode->m_type = JointType::kPoint;
  74. newNode->m_p2p.m_relPosBody1 = relPosFactorA;
  75. newNode->m_p2p.m_relPosBody2 = relPosFactorB;
  76. newNode->m_breakingImpulse = breakingImpulse;
  77. m_jointList.pushBack(newNode);
  78. }
  79. void JointComponent::newHingeJoint(const Vec3& relPosFactor, const Vec3& axis, F32 breakingImpulse)
  80. {
  81. JointNode* newNode = newInstance<JointNode>(SceneMemoryPool::getSingleton());
  82. newNode->m_type = JointType::kHinge;
  83. newNode->m_hinge.m_relPosBody1 = relPosFactor;
  84. newNode->m_hinge.m_axis = axis;
  85. newNode->m_breakingImpulse = breakingImpulse;
  86. m_jointList.pushBack(newNode);
  87. }
  88. void JointComponent::newHingeJoint(const Vec3& relPosFactorA, const Vec3& relPosFactorB, const Vec3& axis, F32 breakingImpulse)
  89. {
  90. JointNode* newNode = newInstance<JointNode>(SceneMemoryPool::getSingleton());
  91. newNode->m_type = JointType::kHinge;
  92. newNode->m_hinge.m_relPosBody1 = relPosFactorA;
  93. newNode->m_hinge.m_relPosBody2 = relPosFactorB;
  94. newNode->m_hinge.m_axis = axis;
  95. newNode->m_breakingImpulse = breakingImpulse;
  96. m_jointList.pushBack(newNode);
  97. }
  98. Error JointComponent::update([[maybe_unused]] SceneComponentUpdateInfo& info, Bool& updated)
  99. {
  100. SceneNode* parent = m_node->getParent();
  101. BodyComponent* bodyc1 = (m_bodyc && m_bodyc->getPhysicsBody()) ? m_bodyc : nullptr;
  102. BodyComponent* bodyc2 = nullptr;
  103. if(parent)
  104. {
  105. bodyc2 = parent->tryGetFirstComponentOfType<BodyComponent>();
  106. bodyc2 = (bodyc2 && bodyc2->getPhysicsBody()) ? bodyc2 : nullptr;
  107. }
  108. auto resetJoints = [this]() -> Bool {
  109. U32 resetCount = 0;
  110. for(JointNode& node : m_jointList)
  111. {
  112. resetCount += !!(node.m_joint);
  113. node.m_joint.reset(nullptr);
  114. }
  115. return resetCount > 0;
  116. };
  117. if(!bodyc1)
  118. {
  119. // No body no joints
  120. if(resetJoints())
  121. {
  122. updated = true;
  123. }
  124. return Error::kNone;
  125. }
  126. const Bool parentChanged = parent && m_parentUuid != parent->getUuid();
  127. if(parentChanged)
  128. {
  129. // New parent, reset joints
  130. updated = true;
  131. m_parentUuid = parent->getUuid();
  132. resetJoints();
  133. }
  134. // Remove broken joints
  135. while(true)
  136. {
  137. Bool erasedOne = false;
  138. for(JointNode& node : m_jointList)
  139. {
  140. if(node.m_joint && node.m_joint->isBroken())
  141. {
  142. m_jointList.erase(&node);
  143. deleteInstance(SceneMemoryPool::getSingleton(), &node);
  144. erasedOne = true;
  145. updated = true;
  146. break;
  147. }
  148. }
  149. if(!erasedOne)
  150. {
  151. break;
  152. }
  153. }
  154. // Create new joints
  155. for(JointNode& node : m_jointList)
  156. {
  157. if(node.m_joint)
  158. {
  159. continue;
  160. }
  161. updated = true;
  162. switch(node.m_type)
  163. {
  164. case JointType::kPoint:
  165. {
  166. const Vec3 relPos1 = computeLocalPivotFromFactors(bodyc1->getPhysicsBody(), node.m_p2p.m_relPosBody1);
  167. if(node.m_p2p.m_relPosBody2 != Vec3(kMaxF32) && bodyc2)
  168. {
  169. const Vec3 relPos2 = computeLocalPivotFromFactors(bodyc2->getPhysicsBody(), node.m_p2p.m_relPosBody2);
  170. node.m_joint = PhysicsWorld::getSingleton().newInstance<PhysicsPoint2PointJoint>(bodyc1->getPhysicsBody(), relPos1,
  171. bodyc2->getPhysicsBody(), relPos2);
  172. }
  173. else
  174. {
  175. node.m_joint = PhysicsWorld::getSingleton().newInstance<PhysicsPoint2PointJoint>(bodyc1->getPhysicsBody(), relPos1);
  176. }
  177. break;
  178. }
  179. case JointType::kHinge:
  180. {
  181. const Vec3 relPos1 = computeLocalPivotFromFactors(bodyc1->getPhysicsBody(), node.m_hinge.m_relPosBody1);
  182. if(node.m_hinge.m_relPosBody2 != Vec3(kMaxF32) && bodyc2)
  183. {
  184. const Vec3 relPos2 = computeLocalPivotFromFactors(bodyc2->getPhysicsBody(), node.m_hinge.m_relPosBody2);
  185. node.m_joint = PhysicsWorld::getSingleton().newInstance<PhysicsHingeJoint>(bodyc1->getPhysicsBody(), relPos1, node.m_hinge.m_axis,
  186. bodyc2->getPhysicsBody(), relPos2, node.m_hinge.m_axis);
  187. }
  188. else
  189. {
  190. node.m_joint = PhysicsWorld::getSingleton().newInstance<PhysicsHingeJoint>(bodyc1->getPhysicsBody(), relPos1, node.m_hinge.m_axis);
  191. }
  192. break;
  193. }
  194. default:
  195. ANKI_ASSERT(0);
  196. }
  197. node.m_joint->setBreakingImpulseThreshold(node.m_breakingImpulse);
  198. }
  199. return Error::kNone;
  200. }
  201. void JointComponent::onOtherComponentRemovedOrAdded(SceneComponent* other, Bool added)
  202. {
  203. if(other->getType() != SceneComponentType::kBody)
  204. {
  205. return;
  206. }
  207. BodyComponent* bodyc = static_cast<BodyComponent*>(other);
  208. Bool jointListInvalid = false;
  209. if(added && m_bodyc == nullptr)
  210. {
  211. m_bodyc = bodyc;
  212. jointListInvalid = true;
  213. }
  214. else if(bodyc == m_bodyc)
  215. {
  216. m_bodyc = nullptr;
  217. jointListInvalid = true;
  218. }
  219. if(jointListInvalid)
  220. {
  221. onDestroy(*m_node);
  222. }
  223. }
  224. } // end namespace anki