BodyComponent.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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/BodyComponent.h>
  6. #include <AnKi/Scene/Components/ModelComponent.h>
  7. #include <AnKi/Scene/SceneNode.h>
  8. #include <AnKi/Scene/SceneGraph.h>
  9. #include <AnKi/Resource/CpuMeshResource.h>
  10. #include <AnKi/Resource/ResourceManager.h>
  11. #include <AnKi/Physics/PhysicsWorld.h>
  12. #include <AnKi/Resource/ModelResource.h>
  13. namespace anki {
  14. BodyComponent::BodyComponent(SceneNode* node)
  15. : SceneComponent(node, kClassType)
  16. , m_node(node)
  17. {
  18. node->setIgnoreParentTransform(true);
  19. }
  20. BodyComponent::~BodyComponent()
  21. {
  22. }
  23. void BodyComponent::removeBody()
  24. {
  25. m_shapeType = ShapeType::kCount;
  26. m_body.reset(nullptr);
  27. m_teleported = false;
  28. m_force = Vec3(0.0f);
  29. m_mesh.reset(nullptr);
  30. m_collisionShape.reset(nullptr);
  31. }
  32. void BodyComponent::loadMeshResource(CString meshFilename)
  33. {
  34. CpuMeshResourcePtr rsrc;
  35. if(ResourceManager::getSingleton().loadResource(meshFilename, rsrc))
  36. {
  37. ANKI_SCENE_LOGE("Failed to load mesh");
  38. return;
  39. }
  40. removeBody();
  41. m_shapeType = ShapeType::kMesh;
  42. m_mesh = std::move(rsrc);
  43. }
  44. void BodyComponent::setMeshFromModelComponent(U32 patchIndex)
  45. {
  46. if(!ANKI_SCENE_ASSERT(m_modelc))
  47. {
  48. return;
  49. }
  50. if(!ANKI_SCENE_ASSERT(patchIndex < m_modelc->getModelResource()->getModelPatches().getSize()))
  51. {
  52. return;
  53. }
  54. loadMeshResource(m_modelc->getModelResource()->getModelPatches()[patchIndex].getMesh()->getFilename());
  55. }
  56. CString BodyComponent::getMeshResourceFilename() const
  57. {
  58. return (m_mesh.isCreated()) ? m_mesh->getFilename() : CString();
  59. }
  60. void BodyComponent::setBoxCollisionShape(const Vec3& extend)
  61. {
  62. if(ANKI_SCENE_ASSERT(extend > 0.0f))
  63. {
  64. removeBody();
  65. m_shapeType = ShapeType::kAabb;
  66. m_boxExtend = extend;
  67. m_collisionShape = PhysicsWorld::getSingleton().newInstance<PhysicsBox>(extend);
  68. }
  69. }
  70. void BodyComponent::setMass(F32 mass)
  71. {
  72. if(!ANKI_SCENE_ASSERT(mass >= 0.0f))
  73. {
  74. return;
  75. }
  76. if(m_mass != mass)
  77. {
  78. m_mass = mass;
  79. m_body.reset(nullptr);
  80. }
  81. }
  82. void BodyComponent::teleportTo(const Transform& trf)
  83. {
  84. m_teleportTrf = trf;
  85. m_teleported = true;
  86. m_node->setLocalTransform(trf); // Set that just to be sure
  87. }
  88. Error BodyComponent::update(SceneComponentUpdateInfo& info, Bool& updated)
  89. {
  90. if(m_shapeType == ShapeType::kCount)
  91. {
  92. return Error::kNone;
  93. }
  94. const Bool shapeDirty = !m_body.isCreated();
  95. if(shapeDirty)
  96. {
  97. updated = true;
  98. PhysicsBodyInitInfo init;
  99. init.m_mass = m_mass;
  100. init.m_transform = (m_teleported) ? m_teleportTrf : m_node->getWorldTransform();
  101. if(m_shapeType == ShapeType::kMesh)
  102. {
  103. init.m_shape = m_mesh->getOrCreateCollisionShape(m_mass == 0.0f);
  104. }
  105. else
  106. {
  107. init.m_shape = m_collisionShape;
  108. }
  109. m_body = PhysicsWorld::getSingleton().newInstance<PhysicsBody>(init);
  110. m_body->setUserData(this);
  111. m_teleported = false; // Cancel teleportation since the body was re-created
  112. }
  113. if(m_body && m_teleported)
  114. {
  115. updated = true;
  116. m_teleported = false;
  117. m_body->setTransform(m_teleportTrf);
  118. }
  119. if(m_body && m_body->getTransform() != info.m_node->getWorldTransform())
  120. {
  121. updated = true;
  122. info.m_node->setLocalTransform(m_body->getTransform());
  123. }
  124. if(m_force.getLengthSquared() > 0.0f)
  125. {
  126. if(m_body)
  127. {
  128. m_body->applyForce(m_force, m_forcePosition);
  129. }
  130. m_force = Vec3(0.0f);
  131. }
  132. return Error::kNone;
  133. }
  134. void BodyComponent::onOtherComponentRemovedOrAdded(SceneComponent* other, Bool added)
  135. {
  136. if(other->getType() != SceneComponentType::kModel)
  137. {
  138. return;
  139. }
  140. if(added && m_modelc == nullptr)
  141. {
  142. m_modelc = static_cast<ModelComponent*>(other);
  143. }
  144. else if(!added && m_modelc == other)
  145. {
  146. m_modelc = nullptr;
  147. }
  148. }
  149. } // end namespace anki