BroadPhaseTests.cpp 5.2 KB

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