PhysicsTrigger.cpp 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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/Physics/PhysicsTrigger.h>
  6. #include <AnKi/Physics/PhysicsCollisionShape.h>
  7. #include <AnKi/Physics/PhysicsWorld.h>
  8. #include <AnKi/Util/Rtti.h>
  9. namespace anki
  10. {
  11. PhysicsTrigger::PhysicsTrigger(PhysicsWorld* world, PhysicsCollisionShapePtr shape)
  12. : PhysicsFilteredObject(CLASS_TYPE, world)
  13. {
  14. m_shape = shape;
  15. m_ghostShape.init();
  16. m_ghostShape->setWorldTransform(btTransform::getIdentity());
  17. m_ghostShape->setCollisionShape(shape->getBtShape(true));
  18. // If you don't have that bodies will bounce on the trigger
  19. m_ghostShape->setCollisionFlags(btCollisionObject::CF_NO_CONTACT_RESPONSE);
  20. m_ghostShape->setUserPointer(static_cast<PhysicsObject*>(this));
  21. setMaterialGroup(PhysicsMaterialBit::TRIGGER);
  22. setMaterialMask(PhysicsMaterialBit::ALL ^ PhysicsMaterialBit::STATIC_GEOMETRY);
  23. }
  24. PhysicsTrigger::~PhysicsTrigger()
  25. {
  26. for(PhysicsTriggerFilteredPair* pair : m_pairs)
  27. {
  28. ANKI_ASSERT(pair);
  29. pair->m_trigger = nullptr;
  30. if(pair->shouldDelete())
  31. {
  32. getAllocator().deleteInstance(pair);
  33. }
  34. }
  35. m_pairs.destroy(getAllocator());
  36. m_ghostShape.destroy();
  37. }
  38. void PhysicsTrigger::registerToWorld()
  39. {
  40. getWorld().getBtWorld().addCollisionObject(m_ghostShape.get());
  41. }
  42. void PhysicsTrigger::unregisterFromWorld()
  43. {
  44. getWorld().getBtWorld().removeCollisionObject(m_ghostShape.get());
  45. }
  46. void PhysicsTrigger::processContacts()
  47. {
  48. ++m_processContactsFrame;
  49. if(m_contactCallback == nullptr)
  50. {
  51. m_pairs.destroy(getAllocator());
  52. return;
  53. }
  54. // Gather the new pairs
  55. DynamicArrayAuto<PhysicsTriggerFilteredPair*> newPairs(getWorld().getTempAllocator());
  56. newPairs.resizeStorage(m_ghostShape->getOverlappingPairs().size());
  57. for(U32 i = 0; i < U32(m_ghostShape->getOverlappingPairs().size()); ++i)
  58. {
  59. btCollisionObject* bobj = m_ghostShape->getOverlappingPairs()[i];
  60. ANKI_ASSERT(bobj);
  61. PhysicsObject* aobj = static_cast<PhysicsObject*>(bobj->getUserPointer());
  62. ANKI_ASSERT(aobj);
  63. PhysicsFilteredObject* obj = dcast<PhysicsFilteredObject*>(aobj);
  64. Bool isNew;
  65. PhysicsTriggerFilteredPair* pair = getWorld().getOrCreatePhysicsTriggerFilteredPair(this, obj, isNew);
  66. if(pair)
  67. {
  68. ANKI_ASSERT(pair->isAlive());
  69. newPairs.emplaceBack(pair);
  70. if(isNew)
  71. {
  72. m_contactCallback->onTriggerEnter(*this, *obj);
  73. }
  74. else
  75. {
  76. m_contactCallback->onTriggerInside(*this, *obj);
  77. }
  78. pair->m_frame = m_processContactsFrame;
  79. }
  80. }
  81. // Remove stale pairs
  82. for(U32 i = 0; i < m_pairs.getSize(); ++i)
  83. {
  84. PhysicsTriggerFilteredPair* pair = m_pairs[i];
  85. ANKI_ASSERT(pair->m_trigger == this);
  86. if(pair->m_filteredObject == nullptr)
  87. {
  88. // Filtered object died while inside the tigger, destroy the pair
  89. getAllocator().deleteInstance(pair);
  90. }
  91. else if(pair->m_frame == m_processContactsFrame)
  92. {
  93. // Was updated this frame so don't touch it
  94. }
  95. else
  96. {
  97. // Was updated in some previous frame, notify and brake the link to the pair
  98. ANKI_ASSERT(pair->isAlive());
  99. ANKI_ASSERT(pair->m_frame < m_processContactsFrame);
  100. m_contactCallback->onTriggerExit(*this, *pair->m_filteredObject);
  101. pair->m_trigger = nullptr;
  102. }
  103. }
  104. // Store the new contacts
  105. m_pairs.resize(getAllocator(), newPairs.getSize());
  106. if(m_pairs.getSize())
  107. {
  108. memcpy(&m_pairs[0], &newPairs[0], m_pairs.getSizeInBytes());
  109. }
  110. }
  111. } // end namespace anki