BroadPhaseTests.cpp 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113
  1. // SPDX-FileCopyrightText: 2021 Jorrit Rouwe
  2. // SPDX-License-Identifier: MIT
  3. #include "UnitTestFramework.h"
  4. #include <Physics/Collision/BroadPhase/BroadPhaseQuadTree.h>
  5. #include <Physics/Collision/Shape/BoxShape.h>
  6. #include <Physics/Collision/CollisionCollectorImpl.h>
  7. #include <Physics/Collision/RayCast.h>
  8. #include <Physics/Collision/CastResult.h>
  9. #include <Physics/Body/BodyManager.h>
  10. #include <Physics/Body/BodyCreationSettings.h>
  11. #include "Layers.h"
  12. TEST_SUITE("BroadPhaseTests")
  13. {
  14. TEST_CASE("TestBroadPhaseOptimize")
  15. {
  16. BPLayerInterfaceImpl broad_phase_layer_interface;
  17. // Create body manager
  18. BodyManager body_manager;
  19. body_manager.Init(1, 0, broad_phase_layer_interface);
  20. // Create quad tree
  21. BroadPhaseQuadTree broadphase;
  22. broadphase.Init(&body_manager, broad_phase_layer_interface);
  23. // Create a box
  24. BodyCreationSettings settings(new BoxShape(Vec3::sReplicate(1.0f)), Vec3::sZero(), Quat::sIdentity(), EMotionType::Static, Layers::NON_MOVING);
  25. Body &body = *body_manager.CreateBody(settings);
  26. // Add it to the broadphase
  27. BodyID id = body.GetID();
  28. BroadPhase::AddState add_state = broadphase.AddBodiesPrepare(&id, 1);
  29. broadphase.AddBodiesFinalize(&id, 1, add_state);
  30. // Test that we hit the box at its current location and not where we're going to move it to
  31. AllHitCollisionCollector<RayCastBodyCollector> collector;
  32. broadphase.CastRay({ Vec3(0, 2, 0), Vec3(0, -2, 0) }, collector, BroadPhaseLayerFilter(), ObjectLayerFilter());
  33. CHECK(collector.mHits.size() == 1);
  34. CHECK(collector.mHits[0].mBodyID == id);
  35. CHECK_APPROX_EQUAL(collector.mHits[0].mFraction, 0.5f);
  36. collector.Reset();
  37. broadphase.CastRay({ Vec3(2, 2, 0), Vec3(0, -2, 0) }, collector, BroadPhaseLayerFilter(), ObjectLayerFilter());
  38. CHECK(collector.mHits.empty());
  39. broadphase.CastRay({ Vec3(4, 2, 0), Vec3(0, -2, 0) }, collector, BroadPhaseLayerFilter(), ObjectLayerFilter());
  40. CHECK(collector.mHits.empty());
  41. // Move the body
  42. body.SetPositionAndRotationInternal(Vec3(2, 0, 0), Quat::sIdentity());
  43. broadphase.NotifyBodiesAABBChanged(&id, 1, true);
  44. // Test that we hit the box at its previous and current location
  45. broadphase.CastRay({ Vec3(0, 2, 0), Vec3(0, -2, 0) }, collector, BroadPhaseLayerFilter(), ObjectLayerFilter());
  46. CHECK(collector.mHits.size() == 1);
  47. CHECK(collector.mHits[0].mBodyID == id);
  48. CHECK_APPROX_EQUAL(collector.mHits[0].mFraction, 0.5f);
  49. collector.Reset();
  50. broadphase.CastRay({ Vec3(2, 2, 0), Vec3(0, -2, 0) }, collector, BroadPhaseLayerFilter(), ObjectLayerFilter());
  51. CHECK(collector.mHits.size() == 1);
  52. CHECK(collector.mHits[0].mBodyID == id);
  53. CHECK_APPROX_EQUAL(collector.mHits[0].mFraction, 0.5f);
  54. collector.Reset();
  55. broadphase.CastRay({ Vec3(4, 2, 0), Vec3(0, -2, 0) }, collector, BroadPhaseLayerFilter(), ObjectLayerFilter());
  56. CHECK(collector.mHits.empty());
  57. // Optimize the broadphase
  58. broadphase.Optimize();
  59. // Test that we hit the box only at the new location
  60. broadphase.CastRay({ Vec3(0, 2, 0), Vec3(0, -2, 0) }, collector, BroadPhaseLayerFilter(), ObjectLayerFilter());
  61. CHECK(collector.mHits.empty());
  62. broadphase.CastRay({ Vec3(2, 2, 0), Vec3(0, -2, 0) }, collector, BroadPhaseLayerFilter(), ObjectLayerFilter());
  63. CHECK(collector.mHits.size() == 1);
  64. CHECK(collector.mHits[0].mBodyID == id);
  65. CHECK_APPROX_EQUAL(collector.mHits[0].mFraction, 0.5f);
  66. collector.Reset();
  67. broadphase.CastRay({ Vec3(4, 2, 0), Vec3(0, -2, 0) }, collector, BroadPhaseLayerFilter(), ObjectLayerFilter());
  68. CHECK(collector.mHits.empty());
  69. // Move the body again (so that for the next optimize we'll have to discard a tree)
  70. body.SetPositionAndRotationInternal(Vec3(4, 0, 0), Quat::sIdentity());
  71. broadphase.NotifyBodiesAABBChanged(&id, 1, true);
  72. // Test that we hit the box at its previous and current location
  73. broadphase.CastRay({ Vec3(0, 2, 0), Vec3(0, -2, 0) }, collector, BroadPhaseLayerFilter(), ObjectLayerFilter());
  74. CHECK(collector.mHits.empty());
  75. broadphase.CastRay({ Vec3(2, 2, 0), Vec3(0, -2, 0) }, collector, BroadPhaseLayerFilter(), ObjectLayerFilter());
  76. CHECK(collector.mHits.size() == 1);
  77. CHECK(collector.mHits[0].mBodyID == id);
  78. CHECK_APPROX_EQUAL(collector.mHits[0].mFraction, 0.5f);
  79. collector.Reset();
  80. broadphase.CastRay({ Vec3(4, 2, 0), Vec3(0, -2, 0) }, collector, BroadPhaseLayerFilter(), ObjectLayerFilter());
  81. CHECK(collector.mHits.size() == 1);
  82. CHECK(collector.mHits[0].mBodyID == id);
  83. CHECK_APPROX_EQUAL(collector.mHits[0].mFraction, 0.5f);
  84. collector.Reset();
  85. // Optimize the broadphase (this will internally have to discard a tree)
  86. broadphase.Optimize();
  87. // Test that we hit the box only at the new location
  88. broadphase.CastRay({ Vec3(0, 2, 0), Vec3(0, -2, 0) }, collector, BroadPhaseLayerFilter(), ObjectLayerFilter());
  89. CHECK(collector.mHits.empty());
  90. broadphase.CastRay({ Vec3(2, 2, 0), Vec3(0, -2, 0) }, collector, BroadPhaseLayerFilter(), ObjectLayerFilter());
  91. CHECK(collector.mHits.empty());
  92. broadphase.CastRay({ Vec3(4, 2, 0), Vec3(0, -2, 0) }, collector, BroadPhaseLayerFilter(), ObjectLayerFilter());
  93. CHECK(collector.mHits.size() == 1);
  94. CHECK(collector.mHits[0].mBodyID == id);
  95. CHECK_APPROX_EQUAL(collector.mHits[0].mFraction, 0.5f);
  96. collector.Reset();
  97. }
  98. }