JointComponent.cpp 4.1 KB

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