SphereShapeTest.cpp 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include <AzTest/AzTest.h>
  9. #include <AZTestShared/Math/MathTestHelpers.h>
  10. #include <AZTestShared/Utils/Utils.h>
  11. #include <AzCore/Component/ComponentApplication.h>
  12. #include <AzCore/UnitTest/TestTypes.h>
  13. #include <AzFramework/Components/TransformComponent.h>
  14. #include <AzFramework/UnitTest/TestDebugDisplayRequests.h>
  15. #include <LmbrCentral/Shape/SphereShapeComponentBus.h>
  16. #include <Shape/SphereShapeComponent.h>
  17. #include <ShapeTestUtils.h>
  18. #include <ShapeThreadsafeTest.h>
  19. namespace Constants = AZ::Constants;
  20. namespace UnitTest
  21. {
  22. class SphereShapeTest
  23. : public LeakDetectionFixture
  24. {
  25. AZStd::unique_ptr<AZ::SerializeContext> m_serializeContext;
  26. AZStd::unique_ptr<AZ::ComponentDescriptor> m_transformShapeComponentDescriptor;
  27. AZStd::unique_ptr<AZ::ComponentDescriptor> m_sphereShapeComponentDescriptor;
  28. AZStd::unique_ptr<AZ::ComponentDescriptor> m_sphereShapeDebugDisplayComponentDescriptor;
  29. public:
  30. void SetUp() override
  31. {
  32. LeakDetectionFixture::SetUp();
  33. m_serializeContext = AZStd::make_unique<AZ::SerializeContext>();
  34. m_transformShapeComponentDescriptor.reset(AzFramework::TransformComponent::CreateDescriptor());
  35. m_transformShapeComponentDescriptor->Reflect(&(*m_serializeContext));
  36. m_sphereShapeComponentDescriptor.reset(LmbrCentral::SphereShapeComponent::CreateDescriptor());
  37. m_sphereShapeComponentDescriptor->Reflect(&(*m_serializeContext));
  38. m_sphereShapeDebugDisplayComponentDescriptor.reset(LmbrCentral::SphereShapeDebugDisplayComponent::CreateDescriptor());
  39. m_sphereShapeDebugDisplayComponentDescriptor->Reflect(&(*m_serializeContext));
  40. }
  41. void TearDown() override
  42. {
  43. m_transformShapeComponentDescriptor.reset();
  44. m_sphereShapeComponentDescriptor.reset();
  45. m_sphereShapeDebugDisplayComponentDescriptor.reset();
  46. m_serializeContext.reset();
  47. LeakDetectionFixture::TearDown();
  48. }
  49. };
  50. void CreateSphere(
  51. AZ::Entity& entity,
  52. const AZ::Transform& transform,
  53. const float radius,
  54. const AZ::Vector3& translationOffset = AZ::Vector3::CreateZero())
  55. {
  56. entity.CreateComponent<AzFramework::TransformComponent>();
  57. entity.CreateComponent<LmbrCentral::SphereShapeComponent>();
  58. entity.CreateComponent<LmbrCentral::SphereShapeDebugDisplayComponent>();
  59. entity.Init();
  60. entity.Activate();
  61. AZ::TransformBus::Event(entity.GetId(), &AZ::TransformBus::Events::SetWorldTM, transform);
  62. LmbrCentral::SphereShapeComponentRequestsBus::Event(entity.GetId(), &LmbrCentral::SphereShapeComponentRequests::SetRadius, radius);
  63. LmbrCentral::ShapeComponentRequestsBus::Event(
  64. entity.GetId(), &LmbrCentral::ShapeComponentRequestsBus::Events::SetTranslationOffset, translationOffset);
  65. }
  66. void CreateUnitSphere(const AZ::Vector3& position, AZ::Entity& entity)
  67. {
  68. CreateSphere(entity, AZ::Transform::CreateTranslation(position), 0.5f);
  69. }
  70. void CreateUnitSphereAtOrigin(AZ::Entity& entity)
  71. {
  72. CreateUnitSphere(AZ::Vector3::CreateZero(), entity);
  73. }
  74. /**
  75. * @brief Creates a point in a sphere using spherical coordinates
  76. * @radius The radial distance from the center of the sphere
  77. * @verticalAngle The angle around the sphere vertically - think top to bottom
  78. * @horizontalAngle The angle around the sphere horizontally- think left to right
  79. * @return A point represeting the coordinates in the sphere
  80. */
  81. AZ::Vector3 CreateSpherePoint(float radius, float verticalAngle, float horizontalAngle)
  82. {
  83. return AZ::Vector3(
  84. radius * sinf(verticalAngle) * cosf(horizontalAngle),
  85. radius * sinf(verticalAngle) * sinf(horizontalAngle),
  86. radius * cosf(verticalAngle));
  87. }
  88. TEST_F(SphereShapeTest, SetRadiusIsPropagatedToGetConfiguration)
  89. {
  90. AZ::Entity entity;
  91. CreateUnitSphereAtOrigin(entity);
  92. float newRadius = 123.456f;
  93. LmbrCentral::SphereShapeComponentRequestsBus::Event(entity.GetId(), &LmbrCentral::SphereShapeComponentRequestsBus::Events::SetRadius, newRadius);
  94. LmbrCentral::SphereShapeConfig config(-1.0f);
  95. LmbrCentral::SphereShapeComponentRequestsBus::EventResult(config, entity.GetId(), &LmbrCentral::SphereShapeComponentRequestsBus::Events::GetSphereConfiguration);
  96. EXPECT_FLOAT_EQ(newRadius, config.m_radius);
  97. }
  98. TEST_F(SphereShapeTest, GetPointInsideSphere)
  99. {
  100. AZ::Entity entity;
  101. const AZ::Vector3 center(1.0f, 2.0f, 3.0f);
  102. CreateUnitSphere(center, entity);
  103. AZ::Vector3 point = center + CreateSpherePoint(0.49f, AZ::Constants::Pi / 4.0f, AZ::Constants::Pi / 4.0f);
  104. bool isInside = false;
  105. LmbrCentral::ShapeComponentRequestsBus::EventResult(isInside, entity.GetId(), &LmbrCentral::ShapeComponentRequestsBus::Events::IsPointInside, point);
  106. EXPECT_TRUE(isInside);
  107. }
  108. TEST_F(SphereShapeTest, GetPointOutsideSphere)
  109. {
  110. AZ::Entity entity;
  111. const AZ::Vector3 center(1.0f, 2.0f, 3.0f);
  112. CreateUnitSphere(center, entity);
  113. AZ::Vector3 point = center + CreateSpherePoint(0.51f, AZ::Constants::Pi / 4.0f, AZ::Constants::Pi / 4.0f);
  114. bool isInside = true;
  115. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  116. isInside, entity.GetId(), &LmbrCentral::ShapeComponentRequestsBus::Events::IsPointInside, point);
  117. EXPECT_FALSE(isInside);
  118. }
  119. TEST_F(SphereShapeTest, GetRayIntersectSphereSuccess1)
  120. {
  121. AZ::Entity entity;
  122. CreateUnitSphere(AZ::Vector3(0.0f, 0.0f, 5.0f), entity);
  123. bool rayHit = false;
  124. float distance;
  125. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  126. rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
  127. AZ::Vector3(0.0f, 5.0f, 5.0f), AZ::Vector3(0.0f, -1.0f, 0.0f), distance);
  128. EXPECT_TRUE(rayHit);
  129. EXPECT_NEAR(distance, 4.5f, 1e-4f);
  130. }
  131. TEST_F(SphereShapeTest, GetRayIntersectSphereSuccess2)
  132. {
  133. AZ::Entity entity;
  134. CreateSphere(entity, AZ::Transform::CreateTranslation(AZ::Vector3(-10.0f, -10.0f, -10.0f)), 2.5f);
  135. bool rayHit = false;
  136. float distance;
  137. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  138. rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
  139. AZ::Vector3(-10.0f, -10.0f, 0.0f), AZ::Vector3(0.0f, 0.0f, -1.0f), distance);
  140. EXPECT_TRUE(rayHit);
  141. EXPECT_NEAR(distance, 7.5f, 1e-4f);
  142. }
  143. TEST_F(SphereShapeTest, GetRayIntersectSphereSuccess3)
  144. {
  145. AZ::Entity entity;
  146. CreateSphere(entity, AZ::Transform::CreateTranslation(AZ::Vector3(5.0f, 0.0f, 0.0f)), 1.0f);
  147. bool rayHit = false;
  148. float distance;
  149. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  150. rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
  151. AZ::Vector3(6.0f, 10.0f, 0.0f), AZ::Vector3(0.0f, -1.0f, 0.0f), distance);
  152. EXPECT_TRUE(rayHit);
  153. EXPECT_NEAR(distance, 10.0f, 1e-4f);
  154. }
  155. // transformed scaled
  156. TEST_F(SphereShapeTest, GetRayIntersectSphereSuccess4)
  157. {
  158. AZ::Entity entity;
  159. CreateSphere(
  160. entity, AZ::Transform::CreateTranslation(AZ::Vector3(-8.0f, -15.0f, 5.0f)) * AZ::Transform::CreateUniformScale(5.0f), 0.25f);
  161. bool rayHit = false;
  162. float distance;
  163. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  164. rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
  165. AZ::Vector3(-5.0f, -15.0f, 5.0f), AZ::Vector3(-1.0f, 0.0f, 0.0f), distance);
  166. EXPECT_TRUE(rayHit);
  167. EXPECT_NEAR(distance, 1.75f, 1e-4f);
  168. }
  169. TEST_F(SphereShapeTest, GetRayIntersectSphereFailure)
  170. {
  171. AZ::Entity entity;
  172. CreateSphere(entity, AZ::Transform::CreateTranslation(AZ::Vector3(0.0f, 0.0f, 0.0f)), 2.0f);
  173. bool rayHit = false;
  174. float distance;
  175. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  176. rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
  177. AZ::Vector3(3.0f, 0.0f, 0.0f), AZ::Vector3(0.0f, 0.0f, -1.0f), distance);
  178. EXPECT_FALSE(rayHit);
  179. }
  180. // not transformed
  181. TEST_F(SphereShapeTest, GetAabb1)
  182. {
  183. AZ::Entity entity;
  184. CreateSphere(entity, AZ::Transform::CreateTranslation(AZ::Vector3::CreateZero()), 2.0f);
  185. AZ::Aabb aabb;
  186. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  187. aabb, entity.GetId(), &LmbrCentral::ShapeComponentRequests::GetEncompassingAabb);
  188. EXPECT_TRUE(aabb.GetMin().IsClose(AZ::Vector3(-2.0f)));
  189. EXPECT_TRUE(aabb.GetMax().IsClose(AZ::Vector3(2.0f)));
  190. }
  191. // transformed
  192. TEST_F(SphereShapeTest, GetAabb2)
  193. {
  194. AZ::Entity entity;
  195. CreateSphere(entity, AZ::Transform::CreateTranslation(AZ::Vector3(200.0f, 150.0f, 60.0f)), 2.0f);
  196. AZ::Aabb aabb;
  197. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  198. aabb, entity.GetId(), &LmbrCentral::ShapeComponentRequests::GetEncompassingAabb);
  199. EXPECT_TRUE(aabb.GetMin().IsClose(AZ::Vector3(198.0f, 148.0f, 58.0f)));
  200. EXPECT_TRUE(aabb.GetMax().IsClose(AZ::Vector3(202.0f, 152.0f, 62.0f)));
  201. }
  202. // transform scaled
  203. TEST_F(SphereShapeTest, GetAabb3)
  204. {
  205. AZ::Entity entity;
  206. CreateSphere(
  207. entity, AZ::Transform::CreateTranslation(AZ::Vector3(100.0f, 200.0f, 300.0f)) * AZ::Transform::CreateUniformScale(2.5f), 0.5f);
  208. AZ::Aabb aabb;
  209. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  210. aabb, entity.GetId(), &LmbrCentral::ShapeComponentRequests::GetEncompassingAabb);
  211. EXPECT_TRUE(aabb.GetMin().IsClose(AZ::Vector3(98.75f, 198.75f, 298.75f)));
  212. EXPECT_TRUE(aabb.GetMax().IsClose(AZ::Vector3(101.25f, 201.25f, 301.25f)));
  213. }
  214. TEST_F(SphereShapeTest, GetTransformAndLocalBounds1)
  215. {
  216. AZ::Entity entity;
  217. AZ::Transform transformIn = AZ::Transform::CreateIdentity();
  218. CreateSphere(entity, transformIn, 2.0f);
  219. AZ::Transform transformOut;
  220. AZ::Aabb aabb;
  221. LmbrCentral::ShapeComponentRequestsBus::Event(entity.GetId(), &LmbrCentral::ShapeComponentRequests::GetTransformAndLocalBounds, transformOut, aabb);
  222. EXPECT_TRUE(transformOut.IsClose(transformIn));
  223. EXPECT_TRUE(aabb.GetMin().IsClose(AZ::Vector3(-2.0f, -2.0f, -2.0f)));
  224. EXPECT_TRUE(aabb.GetMax().IsClose(AZ::Vector3(2.0f, 2.0f, 2.0f)));
  225. }
  226. TEST_F(SphereShapeTest, GetTransformAndLocalBounds2)
  227. {
  228. AZ::Entity entity;
  229. AZ::Transform transformIn = AZ::Transform::CreateTranslation(AZ::Vector3(100.0f, 200.0f, 300.0f)) * AZ::Transform::CreateUniformScale(2.5f);
  230. CreateSphere(entity, transformIn, 2.0f);
  231. AZ::Transform transformOut;
  232. AZ::Aabb aabb;
  233. LmbrCentral::ShapeComponentRequestsBus::Event(entity.GetId(), &LmbrCentral::ShapeComponentRequests::GetTransformAndLocalBounds, transformOut, aabb);
  234. EXPECT_TRUE(transformOut.IsClose(transformIn));
  235. EXPECT_TRUE(aabb.GetMin().IsClose(AZ::Vector3(-2.0f, -2.0f, -2.0f)));
  236. EXPECT_TRUE(aabb.GetMax().IsClose(AZ::Vector3(2.0f, 2.0f, 2.0f)));
  237. }
  238. // point inside scaled
  239. TEST_F(SphereShapeTest, IsPointInsideSuccess1)
  240. {
  241. AZ::Entity entity;
  242. CreateSphere(
  243. entity, AZ::Transform::CreateTranslation(AZ::Vector3(-30.0f, -30.0f, 22.0f)) * AZ::Transform::CreateUniformScale(2.0f), 1.2f);
  244. bool inside;
  245. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  246. inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(-30.0f, -30.0f, 20.0f));
  247. EXPECT_TRUE(inside);
  248. }
  249. // point inside scaled
  250. TEST_F(SphereShapeTest, IsPointInsideSuccess2)
  251. {
  252. AZ::Entity entity;
  253. CreateSphere(
  254. entity, AZ::Transform::CreateTranslation(AZ::Vector3(-30.0f, -30.0f, 22.0f)) * AZ::Transform::CreateUniformScale(1.5f), 1.6f);
  255. bool inside;
  256. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  257. inside, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IsPointInside, AZ::Vector3(-31.0f, -32.0f, 21.2f));
  258. EXPECT_TRUE(inside);
  259. }
  260. // distance scaled
  261. TEST_F(SphereShapeTest, DistanceFromPoint1)
  262. {
  263. AZ::Entity entity;
  264. CreateSphere(
  265. entity, AZ::Transform::CreateTranslation(AZ::Vector3(19.0f, 34.0f, 37.0f)) * AZ::Transform::CreateUniformScale(2.0f), 1.0f);
  266. float distance;
  267. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  268. distance, entity.GetId(), &LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(13.0f, 34.0f, 37.2f));
  269. EXPECT_NEAR(distance, 4.0f, 1e-2f);
  270. }
  271. // distance scaled
  272. TEST_F(SphereShapeTest, DistanceFromPoint2)
  273. {
  274. AZ::Entity entity;
  275. CreateSphere(
  276. entity, AZ::Transform::CreateTranslation(AZ::Vector3(19.0f, 34.0f, 37.0f)) * AZ::Transform::CreateUniformScale(0.5f), 1.0f);
  277. float distance;
  278. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  279. distance, entity.GetId(), &LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(19.0f, 37.0f, 37.2f));
  280. EXPECT_NEAR(distance, 2.5f, 1e-2f);
  281. }
  282. TEST_F(SphereShapeTest, ShapeHasThreadsafeGetSetCalls)
  283. {
  284. // Verify that setting values from one thread and querying values from multiple other threads in parallel produces
  285. // correct, consistent results.
  286. // Create our sphere centered at 0 with half our height as the radius.
  287. AZ::Entity entity;
  288. CreateSphere(entity, AZ::Transform::CreateTranslation(AZ::Vector3::CreateZero()), ShapeThreadsafeTest::ShapeHeight / 2.0f);
  289. // Define the function for setting unimportant dimensions on the shape while queries take place.
  290. auto setDimensionFn = [](AZ::EntityId shapeEntityId, float minDimension, uint32_t dimensionVariance, [[maybe_unused]] float height)
  291. {
  292. [[maybe_unused]] float radius = minDimension + aznumeric_cast<float>(rand() % dimensionVariance);
  293. LmbrCentral::SphereShapeComponentRequestsBus::Event(
  294. shapeEntityId, &LmbrCentral::SphereShapeComponentRequestsBus::Events::SetRadius, height / 2.0f);
  295. };
  296. // Run the test, which will run multiple queries in parallel with each other and with the dimension-setting function.
  297. // The number of iterations is arbitrary - it's set high enough to catch most failures, but low enough to keep the test
  298. // time to a minimum.
  299. const int numIterations = 30000;
  300. ShapeThreadsafeTest::TestShapeGetSetCallsAreThreadsafe(entity, numIterations, setDimensionFn);
  301. }
  302. TEST_F(SphereShapeTest, GetRayIntersectSphereWithTranslationOffsetJustIntersecting)
  303. {
  304. AZ::Entity entity;
  305. CreateSphere(
  306. entity,
  307. AZ::Transform(AZ::Vector3(2.0f, 3.0f, 4.0f), AZ::Quaternion(0.12f, 0.24f, 0.08f, 0.96f), 2.0f),
  308. 0.5f,
  309. AZ::Vector3(3.0f, -6.0f, 3.0f));
  310. bool rayHit = false;
  311. float distance;
  312. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  313. rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
  314. AZ::Vector3(10.304f, -9.0f, 3.2608f), AZ::Vector3(0.0f, 1.0f, 0.0f), distance);
  315. EXPECT_TRUE(rayHit);
  316. EXPECT_NEAR(distance, 0.3344f, 1e-3f);
  317. }
  318. TEST_F(SphereShapeTest, GetRayIntersectSphereWithTranslationOffsetJustMissing)
  319. {
  320. AZ::Entity entity;
  321. CreateSphere(
  322. entity,
  323. AZ::Transform(AZ::Vector3(2.0f, 3.0f, 4.0f), AZ::Quaternion(0.12f, 0.24f, 0.08f, 0.96f), 2.0f),
  324. 0.5f,
  325. AZ::Vector3(3.0f, -6.0f, 3.0f));
  326. bool rayHit = false;
  327. float distance;
  328. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  329. rayHit, entity.GetId(), &LmbrCentral::ShapeComponentRequests::IntersectRay,
  330. AZ::Vector3(10.254f, -9.0f, 3.2608f), AZ::Vector3(0.0f, 1.0f, 0.0f), distance);
  331. EXPECT_FALSE(rayHit);
  332. }
  333. TEST_F(SphereShapeTest, GetAabbRotatedAndScaledWithTranslationOffset)
  334. {
  335. AZ::Entity entity;
  336. CreateSphere(
  337. entity,
  338. AZ::Transform(AZ::Vector3(-5.0f, 6.0f, -2.0f), AZ::Quaternion(0.7f, 0.1f, -0.1f, 0.7f), 0.8f),
  339. 1.5f,
  340. AZ::Vector3(2.0f, -2.0f, 7.0f));
  341. AZ::Aabb aabb;
  342. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  343. aabb, entity.GetId(), &LmbrCentral::ShapeComponentRequests::GetEncompassingAabb);
  344. EXPECT_THAT(aabb.GetMin(), IsClose(AZ::Vector3(-5.112f, -0.8f, -5.184f)));
  345. EXPECT_THAT(aabb.GetMax(), IsClose(AZ::Vector3(-2.712f, 1.6f, -2.784f)));
  346. }
  347. TEST_F(SphereShapeTest, GetTransformAndLocalBoundsWithTranslationOffset)
  348. {
  349. AZ::Entity entity;
  350. AZ::Transform transform(AZ::Vector3(1.0f, 2.0f, 5.0f), AZ::Quaternion(0.58f, 0.22f, 0.26f, 0.74f), 0.5f);
  351. CreateSphere(
  352. entity,
  353. transform,
  354. 2.5f,
  355. AZ::Vector3(4.0f, -3.0f, 3.0f));
  356. AZ::Transform transformOut;
  357. AZ::Aabb aabb;
  358. LmbrCentral::ShapeComponentRequestsBus::Event(entity.GetId(), &LmbrCentral::ShapeComponentRequests::GetTransformAndLocalBounds, transformOut, aabb);
  359. EXPECT_THAT(transformOut, IsClose(transform));
  360. EXPECT_THAT(aabb.GetMin(), IsClose(AZ::Vector3(1.5f, -5.5f, 0.5f)));
  361. EXPECT_THAT(aabb.GetMax(), IsClose(AZ::Vector3(6.5f, -0.5f, 5.5f)));
  362. }
  363. TEST_F(SphereShapeTest, IsPointInsideWithTranslationOffset)
  364. {
  365. AZ::Entity entity;
  366. CreateSphere(
  367. entity,
  368. AZ::Transform(AZ::Vector3(4.0f, 7.0f, 3.0f), AZ::Quaternion(-0.1f, -0.1f, 0.7f, 0.7f), 2.0f),
  369. 1.0f,
  370. AZ::Vector3(4.0f, -4.0f, 5.0f));
  371. // test some pairs of nearby points which should be just either side of the surface of the capsule
  372. EXPECT_TRUE(IsPointInside(entity, AZ::Vector3(6.9f, 15.0f, 15.0f)));
  373. EXPECT_FALSE(IsPointInside(entity, AZ::Vector3(6.8f, 15.0f, 15.0f)));
  374. EXPECT_TRUE(IsPointInside(entity, AZ::Vector3(9.0f, 16.9f, 15.0f)));
  375. EXPECT_FALSE(IsPointInside(entity, AZ::Vector3(9.0f, 17.0f, 15.0f)));
  376. EXPECT_TRUE(IsPointInside(entity, AZ::Vector3(9.0f, 15.0f, 16.8f)));
  377. EXPECT_FALSE(IsPointInside(entity, AZ::Vector3(9.0f, 15.0f, 16.9f)));
  378. }
  379. TEST_F(SphereShapeTest, DistanceFromPointWithTranslationOffset)
  380. {
  381. AZ::Entity entity;
  382. CreateSphere(
  383. entity,
  384. AZ::Transform(AZ::Vector3(2.0f, -5.0f, -4.0f), AZ::Quaternion(0.7f, -0.7f, 0.1f, 0.1f), 1.5f),
  385. 3.0f,
  386. AZ::Vector3(3.0f, 5.0f, 6.0f));
  387. float distance = AZ::Constants::FloatMax;
  388. // should be just inside
  389. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  390. distance, entity.GetId(), &LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(-9.9f, -11.84f, -11.38f));
  391. EXPECT_NEAR(distance, 0.0f, 1e-3f);
  392. // should be just outside
  393. LmbrCentral::ShapeComponentRequestsBus::EventResult(
  394. distance, entity.GetId(), &LmbrCentral::ShapeComponentRequests::DistanceFromPoint, AZ::Vector3(-10.1f, -11.84f, -11.38f));
  395. EXPECT_NEAR(distance, 0.1f, 1e-3f);
  396. }
  397. TEST_F(SphereShapeTest, DebugDrawWithTranslationOffset)
  398. {
  399. AZ::Entity entity;
  400. CreateSphere(
  401. entity,
  402. AZ::Transform(AZ::Vector3(5.0f, 4.0f, 1.0f), AZ::Quaternion(0.62f, 0.62f, 0.14f, 0.46f), 2.5f),
  403. 1.4f,
  404. AZ::Vector3(2.0f, 6.0f, -7.0f));
  405. UnitTest::TestDebugDisplayRequests testDebugDisplayRequests;
  406. LmbrCentral::ShapeComponentNotificationsBus::Event(
  407. entity.GetId(),
  408. &LmbrCentral::ShapeComponentNotificationsBus::Events::OnShapeChanged,
  409. LmbrCentral::ShapeComponentNotifications::ShapeChangeReasons::ShapeChanged);
  410. AzFramework::EntityDebugDisplayEventBus::Event(entity.GetId(), &AzFramework::EntityDebugDisplayEvents::DisplayEntityViewport,
  411. AzFramework::ViewportInfo{ 0 }, testDebugDisplayRequests);
  412. const AZStd::vector<AZ::Vector3>& points = testDebugDisplayRequests.GetPoints();
  413. const AZ::Aabb debugDrawAabb = points.size() > 0 ? AZ::Aabb::CreatePoints(points.data(), points.size()) : AZ::Aabb::CreateNull();
  414. // use quite low tolerance because the debug draw mesh is only an approximation to a perfect sphere
  415. EXPECT_THAT(debugDrawAabb.GetMin(), IsCloseTolerance(AZ::Vector3(-1.0f, 14.8f, 16.1f), 0.1f));
  416. EXPECT_THAT(debugDrawAabb.GetMax(), IsCloseTolerance(AZ::Vector3(6.0f, 21.8f, 23.1f), 0.1f));
  417. }
  418. } // namespace UnitTest