JointComponent.cpp 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151
  1. // Copyright (C) 2009-2021, 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. {
  11. ANKI_SCENE_COMPONENT_STATICS(JointComponent)
  12. class JointComponent::JointNode : public IntrusiveListEnabled<JointNode>
  13. {
  14. public:
  15. PhysicsJointPtr m_joint;
  16. SceneNode* m_parentNode = nullptr; ///< Keep track the node that is connected with this node through a joint.
  17. };
  18. JointComponent::~JointComponent()
  19. {
  20. removeAllJoints();
  21. }
  22. void JointComponent::removeAllJoints()
  23. {
  24. while(!m_jointList.isEmpty())
  25. {
  26. JointNode* node = &m_jointList.getFront();
  27. m_jointList.popFront();
  28. m_node->getAllocator().deleteInstance(node);
  29. }
  30. }
  31. Vec3 JointComponent::computeLocalPivotFromFactors(const PhysicsBodyPtr& body, const Vec3& factors)
  32. {
  33. btTransform identityTrf;
  34. identityTrf.setIdentity();
  35. btVector3 aabbmin, aabbmax, center;
  36. body->getBtBody()->getCollisionShape()->getAabb(identityTrf, aabbmin, aabbmax);
  37. center = (aabbmin + aabbmax) * 0.5f;
  38. Vec3 out;
  39. for(U i = 0; i < 3; ++i)
  40. {
  41. const F32 factor = factors[i];
  42. ANKI_ASSERT(factor >= -1.0f || factor <= 1.0f);
  43. const F32 dist = aabbmax[i] - center[i];
  44. out[i] = dist * factor + center[i];
  45. }
  46. return out;
  47. }
  48. template<typename TJoint, typename... TArgs>
  49. void JointComponent::newJoint(const Vec3& relPosFactor, F32 breakingImpulse, TArgs&&... args)
  50. {
  51. BodyComponent* bodyc = m_node->tryGetFirstComponentOfType<BodyComponent>();
  52. if(bodyc)
  53. {
  54. Vec3 relPos = computeLocalPivotFromFactors(bodyc->getPhysicsBody(), relPosFactor);
  55. PhysicsJointPtr joint = m_node->getSceneGraph().getPhysicsWorld().newInstance<TJoint>(
  56. bodyc->getPhysicsBody(), relPos, std::forward<TArgs>(args)...);
  57. joint->setBreakingImpulseThreshold(breakingImpulse);
  58. JointNode* newNode = m_node->getAllocator().newInstance<JointNode>();
  59. newNode->m_joint = joint;
  60. m_jointList.pushBack(newNode);
  61. }
  62. else
  63. {
  64. ANKI_SCENE_LOGW("Can't create new joint. The node is missing a BodyComponent");
  65. }
  66. }
  67. void JointComponent::newPoint2PointJoint(const Vec3& relPosFactor, F32 breakingImpulse)
  68. {
  69. newJoint<PhysicsPoint2PointJoint>(relPosFactor, breakingImpulse);
  70. }
  71. void JointComponent::newPoint2PointJoint2(const Vec3& relPosFactorA, const Vec3& relPosFactorB, F32 breakingImpulse)
  72. {
  73. BodyComponent* bodycA = m_node->tryGetFirstComponentOfType<BodyComponent>();
  74. BodyComponent* bodycB = nullptr;
  75. if(m_node->getParent())
  76. {
  77. bodycB = m_node->getParent()->tryGetFirstComponentOfType<BodyComponent>();
  78. }
  79. if(bodycA && bodycB)
  80. {
  81. Vec3 relPosA = computeLocalPivotFromFactors(bodycA->getPhysicsBody(), relPosFactorA);
  82. Vec3 relPosB = computeLocalPivotFromFactors(bodycB->getPhysicsBody(), relPosFactorB);
  83. PhysicsJointPtr joint = m_node->getSceneGraph().getPhysicsWorld().newInstance<PhysicsPoint2PointJoint>(
  84. bodycA->getPhysicsBody(), relPosA, bodycB->getPhysicsBody(), relPosB);
  85. joint->setBreakingImpulseThreshold(breakingImpulse);
  86. JointNode* newNode = m_node->getAllocator().newInstance<JointNode>();
  87. newNode->m_joint = joint;
  88. newNode->m_parentNode = m_node->getParent();
  89. m_jointList.pushBack(newNode);
  90. }
  91. else
  92. {
  93. ANKI_SCENE_LOGW("Can't create new joint. The node or its parent are missing a BodyComponent");
  94. }
  95. }
  96. void JointComponent::newHingeJoint(const Vec3& relPosFactor, const Vec3& axis, F32 breakingImpulse)
  97. {
  98. newJoint<PhysicsHingeJoint>(relPosFactor, breakingImpulse, axis);
  99. }
  100. Error JointComponent::update(SceneNode& node, Second prevTime, Second crntTime, Bool& updated)
  101. {
  102. ANKI_ASSERT(&node == m_node);
  103. // Iterate the joints and check if the connected scene node is not the parent of this node anymore.
  104. while(true)
  105. {
  106. Bool erasedOne = false;
  107. for(JointNode& otherNode : m_jointList)
  108. {
  109. if(otherNode.m_parentNode != node.getParent() || otherNode.m_joint->isBroken())
  110. {
  111. m_jointList.erase(&otherNode);
  112. node.getAllocator().deleteInstance(&otherNode);
  113. erasedOne = true;
  114. updated = true;
  115. break;
  116. }
  117. }
  118. if(!erasedOne)
  119. {
  120. break;
  121. }
  122. }
  123. return Error::NONE;
  124. }
  125. } // end namespace anki