PhysicsTrigger.cpp 3.5 KB

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