2
0

ScriptCanvasPhysicsTest.cpp 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371
  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/GemTestEnvironment.h>
  9. #include <gmock/gmock.h>
  10. #include <AzCore/std/smart_ptr/make_shared.h>
  11. #include <AzFramework/Physics/PhysicsScene.h>
  12. #include <AzFramework/Physics/Shape.h>
  13. #include <AzFramework/Physics/ShapeConfiguration.h>
  14. #include <AzFramework/Physics/ShapeConfiguration.h>
  15. #include <AzFramework/Components/TransformComponent.h>
  16. #include <AzFramework/Physics/Collision/CollisionGroups.h>
  17. #include <AzFramework/Physics/Collision/CollisionLayers.h>
  18. #include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
  19. #include <AzFramework/Physics/Common/PhysicsTypes.h>
  20. #include <World.h>
  21. namespace ScriptCanvasPhysics
  22. {
  23. namespace WorldFunctions
  24. {
  25. extern Result RayCastWorldSpaceWithGroup(const AZ::Vector3& start,
  26. const AZ::Vector3& direction,
  27. float distance,
  28. const AZStd::string& collisionGroup,
  29. AZ::EntityId ignore);
  30. extern Result RayCastLocalSpaceWithGroup(const AZ::EntityId& fromEntityId,
  31. const AZ::Vector3& direction,
  32. float distance,
  33. const AZStd::string& collisionGroup,
  34. AZ::EntityId ignore);
  35. extern AZStd::vector<AzPhysics::SceneQueryHit> RayCastMultipleLocalSpaceWithGroup(const AZ::EntityId& fromEntityId,
  36. const AZ::Vector3& direction,
  37. float distance,
  38. const AZStd::string& collisionGroup,
  39. AZ::EntityId ignore);
  40. extern Result ShapecastQuery(float distance,
  41. const AZ::Transform& pose,
  42. const AZ::Vector3& direction,
  43. AZStd::shared_ptr<Physics::ShapeConfiguration> shape,
  44. const AZStd::string& collisionGroup,
  45. AZ::EntityId ignore);
  46. }
  47. }
  48. namespace ScriptCanvasPhysicsTests
  49. {
  50. using namespace ::testing;
  51. //Mocked of the AzPhysics Scene Interface. To keep things simple just mocked functions that have a return value OR required for a test.
  52. class MockPhysicsSceneInterface
  53. : AZ::Interface<AzPhysics::SceneInterface>::Registrar
  54. {
  55. public:
  56. void StartSimulation(
  57. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  58. [[maybe_unused]] float deltatime) override {}
  59. void FinishSimulation([[maybe_unused]] AzPhysics::SceneHandle sceneHandle) override {}
  60. void SetEnabled(
  61. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  62. [[maybe_unused]] bool enable) override {}
  63. void RemoveSimulatedBody(
  64. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  65. [[maybe_unused]] AzPhysics::SimulatedBodyHandle& bodyHandle) override {}
  66. void RemoveSimulatedBodies(
  67. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  68. [[maybe_unused]] AzPhysics::SimulatedBodyHandleList& bodyHandles) override {}
  69. void EnableSimulationOfBody(
  70. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  71. [[maybe_unused]] AzPhysics::SimulatedBodyHandle bodyHandle) override {}
  72. void DisableSimulationOfBody(
  73. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  74. [[maybe_unused]] AzPhysics::SimulatedBodyHandle bodyHandle) override {}
  75. void RemoveJoint(
  76. [[maybe_unused]]AzPhysics::SceneHandle sceneHandle,
  77. [[maybe_unused]] AzPhysics::JointHandle jointHandle) override {}
  78. void SuppressCollisionEvents(
  79. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  80. [[maybe_unused]] const AzPhysics::SimulatedBodyHandle& bodyHandleA,
  81. [[maybe_unused]] const AzPhysics::SimulatedBodyHandle& bodyHandleB) override {}
  82. void UnsuppressCollisionEvents(
  83. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  84. [[maybe_unused]] const AzPhysics::SimulatedBodyHandle& bodyHandleA,
  85. [[maybe_unused]] const AzPhysics::SimulatedBodyHandle& bodyHandleB) override {}
  86. void SetGravity(
  87. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  88. [[maybe_unused]] const AZ::Vector3& gravity) override {}
  89. void RegisterSceneConfigurationChangedEventHandler(
  90. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  91. [[maybe_unused]] AzPhysics::SceneEvents::OnSceneConfigurationChanged::Handler& handler) override {}
  92. void RegisterSimulationBodyAddedHandler(
  93. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  94. [[maybe_unused]] AzPhysics::SceneEvents::OnSimulationBodyAdded::Handler& handler) override {}
  95. void RegisterSimulationBodyRemovedHandler(
  96. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  97. [[maybe_unused]] AzPhysics::SceneEvents::OnSimulationBodyRemoved::Handler& handler) override {}
  98. void RegisterSimulationBodySimulationEnabledHandler(
  99. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  100. [[maybe_unused]] AzPhysics::SceneEvents::OnSimulationBodySimulationEnabled::Handler& handler) override {}
  101. void RegisterSimulationBodySimulationDisabledHandler(
  102. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  103. [[maybe_unused]] AzPhysics::SceneEvents::OnSimulationBodySimulationDisabled::Handler& handler) override {}
  104. void RegisterSceneSimulationStartHandler(
  105. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  106. [[maybe_unused]] AzPhysics::SceneEvents::OnSceneSimulationStartHandler& handler) override {}
  107. void RegisterSceneActiveSimulatedBodiesHandler(
  108. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  109. [[maybe_unused]] AzPhysics::SceneEvents::OnSceneActiveSimulatedBodiesEvent::Handler& handler) override {}
  110. void RegisterSceneCollisionEventHandler(
  111. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  112. [[maybe_unused]] AzPhysics::SceneEvents::OnSceneCollisionsEvent::Handler& handler) override {}
  113. void RegisterSceneTriggersEventHandler(
  114. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  115. [[maybe_unused]] AzPhysics::SceneEvents::OnSceneTriggersEvent::Handler& handler) override {}
  116. void RegisterSceneGravityChangedEvent(
  117. [[maybe_unused]] AzPhysics::SceneHandle sceneHandle,
  118. [[maybe_unused]] AzPhysics::SceneEvents::OnSceneGravityChangedEvent::Handler& handler) override {}
  119. MOCK_METHOD1(GetSceneHandle, AzPhysics::SceneHandle(const AZStd::string& sceneName));
  120. MOCK_METHOD1(GetScene, AzPhysics::Scene*(AzPhysics::SceneHandle));
  121. MOCK_CONST_METHOD1(IsEnabled, bool(AzPhysics::SceneHandle sceneHandle));
  122. MOCK_METHOD2(AddSimulatedBody, AzPhysics::SimulatedBodyHandle(AzPhysics::SceneHandle sceneHandle, const AzPhysics::SimulatedBodyConfiguration* simulatedBodyConfig));
  123. MOCK_METHOD2(AddSimulatedBodies, AzPhysics::SimulatedBodyHandleList(AzPhysics::SceneHandle sceneHandle, const AzPhysics::SimulatedBodyConfigurationList& simulatedBodyConfigs));
  124. MOCK_METHOD2(GetSimulatedBodyFromHandle, AzPhysics::SimulatedBody* (AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle bodyHandle));
  125. MOCK_METHOD2(GetSimulatedBodiesFromHandle, AzPhysics::SimulatedBodyList(AzPhysics::SceneHandle sceneHandle, const AzPhysics::SimulatedBodyHandleList& bodyHandles));
  126. MOCK_METHOD4(AddJoint, AzPhysics::JointHandle(AzPhysics::SceneHandle sceneHandle, const AzPhysics::JointConfiguration* jointConfig,
  127. AzPhysics::SimulatedBodyHandle parentBody, AzPhysics::SimulatedBodyHandle childBody));
  128. MOCK_METHOD2(
  129. GetJointFromHandle, AzPhysics::Joint*(AzPhysics::SceneHandle sceneHandle, AzPhysics::JointHandle jointHandle));
  130. MOCK_CONST_METHOD1(GetGravity, AZ::Vector3(AzPhysics::SceneHandle sceneHandle));
  131. MOCK_METHOD2(RegisterSceneSimulationFinishHandler, void(AzPhysics::SceneHandle sceneHandle, AzPhysics::SceneEvents::OnSceneSimulationFinishHandler& handler));
  132. MOCK_CONST_METHOD2(GetLegacyBody, AzPhysics::SimulatedBody* (AzPhysics::SceneHandle sceneHandle, AzPhysics::SimulatedBodyHandle handle));
  133. MOCK_METHOD2(QueryScene, AzPhysics::SceneQueryHits(AzPhysics::SceneHandle sceneHandle, const AzPhysics::SceneQueryRequest* request));
  134. MOCK_METHOD3(QueryScene, bool(AzPhysics::SceneHandle sceneHandle, const AzPhysics::SceneQueryRequest* request, AzPhysics::SceneQueryHits&));
  135. MOCK_METHOD2(QuerySceneBatch, AzPhysics::SceneQueryHitsList(AzPhysics::SceneHandle sceneHandle, const AzPhysics::SceneQueryRequests& requests));
  136. MOCK_METHOD4(QuerySceneAsync, bool(AzPhysics::SceneHandle sceneHandle, AzPhysics::SceneQuery::AsyncRequestId requestId,
  137. const AzPhysics::SceneQueryRequest* request, AzPhysics::SceneQuery::AsyncCallback callback));
  138. MOCK_METHOD4(QuerySceneAsyncBatch, bool(AzPhysics::SceneHandle sceneHandle, AzPhysics::SceneQuery::AsyncRequestId requestId,
  139. const AzPhysics::SceneQueryRequests& requests, AzPhysics::SceneQuery::AsyncBatchCallback callback));
  140. };
  141. class MockSimulatedBody
  142. : public AzPhysics::SimulatedBody
  143. {
  144. public:
  145. AZ_CLASS_ALLOCATOR(MockSimulatedBody, AZ::SystemAllocator)
  146. MOCK_CONST_METHOD0(GetEntityId, AZ::EntityId());
  147. MOCK_CONST_METHOD0(GetTransform, AZ::Transform());
  148. MOCK_METHOD1(SetTransform, void(const AZ::Transform& transform));
  149. MOCK_CONST_METHOD0(GetPosition, AZ::Vector3());
  150. MOCK_CONST_METHOD0(GetOrientation, AZ::Quaternion());
  151. MOCK_CONST_METHOD0(GetAabb, AZ::Aabb());
  152. MOCK_METHOD1(RayCast, AzPhysics::SceneQueryHit(const AzPhysics::RayCastRequest& request));
  153. MOCK_CONST_METHOD0(GetNativeType, AZ::Crc32());
  154. MOCK_CONST_METHOD0(GetNativePointer, void*());
  155. };
  156. class MockShape
  157. : public Physics::Shape
  158. {
  159. public:
  160. AZ_CLASS_ALLOCATOR(MockShape, AZ::SystemAllocator)
  161. MOCK_METHOD1(SetMaterial, void(const AZStd::shared_ptr<Physics::Material>& material));
  162. MOCK_CONST_METHOD0(GetMaterial, AZStd::shared_ptr<Physics::Material>());
  163. MOCK_CONST_METHOD0(GetMaterialId, Physics::MaterialId());
  164. MOCK_METHOD1(SetCollisionLayer, void(const AzPhysics::CollisionLayer& layer));
  165. MOCK_CONST_METHOD0(GetCollisionLayer, AzPhysics::CollisionLayer());
  166. MOCK_METHOD1(SetCollisionGroup, void(const AzPhysics::CollisionGroup& group));
  167. MOCK_CONST_METHOD0(GetCollisionGroup, AzPhysics::CollisionGroup());
  168. MOCK_METHOD1(SetName, void(const char* name));
  169. MOCK_METHOD2(SetLocalPose, void(const AZ::Vector3& offset, const AZ::Quaternion& rotation));
  170. MOCK_CONST_METHOD0(GetLocalPose, AZStd::pair<AZ::Vector3, AZ::Quaternion>());
  171. MOCK_METHOD0(GetNativePointer, void*());
  172. MOCK_CONST_METHOD0(GetNativePointer, const void*());
  173. MOCK_CONST_METHOD0(GetTag, AZ::Crc32());
  174. MOCK_METHOD1(AttachedToActor, void(void* actor));
  175. MOCK_METHOD0(DetachedFromActor, void());
  176. MOCK_METHOD2(RayCast, AzPhysics::SceneQueryHit(const AzPhysics::RayCastRequest& worldSpaceRequest, const AZ::Transform& worldTransform));
  177. MOCK_METHOD1(RayCastLocal, AzPhysics::SceneQueryHit(const AzPhysics::RayCastRequest& localSpaceRequest));
  178. MOCK_CONST_METHOD3(GetGeometry, void(AZStd::vector<AZ::Vector3>&, AZStd::vector<AZ::u32>&, const AZ::Aabb*));
  179. MOCK_CONST_METHOD1(GetAabb, AZ::Aabb(const AZ::Transform& worldTransform));
  180. MOCK_CONST_METHOD0(GetAabbLocal, AZ::Aabb());
  181. MOCK_CONST_METHOD0(GetRestOffset, float());
  182. MOCK_METHOD1(SetRestOffset, void(float));
  183. MOCK_CONST_METHOD0(GetContactOffset, float());
  184. MOCK_METHOD1(SetContactOffset, void(float));
  185. };
  186. class ScriptCanvasPhysicsTestEnvironment
  187. : public AZ::Test::GemTestEnvironment
  188. {
  189. void AddGemsAndComponents() override
  190. {
  191. AddComponentDescriptors({ AzFramework::TransformComponent::CreateDescriptor() });
  192. }
  193. };
  194. class ScriptCanvasPhysicsTest
  195. : public ::testing::Test
  196. {
  197. protected:
  198. void SetUp() override
  199. {
  200. ::testing::Test::SetUp();
  201. m_hit.m_position = AZ::Vector3(1.f, 2.f, 3.f);
  202. m_hit.m_distance = 2.5f;
  203. m_hit.m_normal = AZ::Vector3(-1.f, 3.5f, 0.5f);
  204. m_hit.m_shape = &m_shape;
  205. m_hit.m_physicsMaterialId = Physics::MaterialId::CreateName("Default");
  206. m_hit.m_resultFlags = AzPhysics::SceneQuery::ResultFlags::Position |
  207. AzPhysics::SceneQuery::ResultFlags::Distance |
  208. AzPhysics::SceneQuery::ResultFlags::Normal |
  209. AzPhysics::SceneQuery::ResultFlags::Shape |
  210. AzPhysics::SceneQuery::ResultFlags::Material;
  211. m_hitResult.m_hits.push_back(m_hit);
  212. }
  213. NiceMock<MockSimulatedBody> m_worldBody;
  214. NiceMock<MockShape> m_shape;
  215. NiceMock<MockPhysicsSceneInterface> m_sceneInterfaceMock;
  216. AzPhysics::SceneQueryHit m_hit;
  217. AzPhysics::SceneQueryHits m_hitResult;
  218. bool ResultIsEqualToHit(const ScriptCanvasPhysics::WorldFunctions::Result& result, const AzPhysics::SceneQueryHit& hit)
  219. {
  220. return
  221. AZStd::get<0>(result) == hit.IsValid() &&
  222. AZStd::get<1>(result) == hit.m_position &&
  223. AZStd::get<2>(result) == hit.m_normal &&
  224. AZStd::get<3>(result) == hit.m_distance &&
  225. AZStd::get<4>(result) == hit.m_entityId &&
  226. AZStd::get<5>(result) == AZ::Crc32(hit.m_physicsMaterialId.ToString<AZStd::string>())
  227. ;
  228. }
  229. };
  230. TEST_F(ScriptCanvasPhysicsTest, WorldNodes_RayCastWorldSpaceWithGroup_FT)
  231. {
  232. ON_CALL(m_sceneInterfaceMock, QueryScene(_, _))
  233. .WillByDefault(Return(m_hitResult));
  234. // given raycast data
  235. const AZ::Vector3 start = AZ::Vector3::CreateZero();
  236. const AZ::Vector3 direction = AZ::Vector3(0.f,1.f,0.f);
  237. const float distance = 1.f;
  238. const AZStd::string collisionGroup = "default";
  239. const AZ::EntityId ignoreEntityId;
  240. // when a raycast is performed
  241. auto result = ScriptCanvasPhysics::WorldFunctions::RayCastWorldSpaceWithGroup(
  242. start,
  243. direction,
  244. distance,
  245. collisionGroup,
  246. ignoreEntityId
  247. );
  248. // expect a valid hit is returned
  249. EXPECT_TRUE(ResultIsEqualToHit(result, m_hit));
  250. }
  251. TEST_F(ScriptCanvasPhysicsTest, WorldNodes_RayCastLocalSpaceWithGroup_FT)
  252. {
  253. ON_CALL(m_sceneInterfaceMock, QueryScene(_, _))
  254. .WillByDefault(Return(m_hitResult));
  255. // given raycast data
  256. const AZ::Vector3 direction = AZ::Vector3(0.f,1.f,0.f);
  257. const float distance = 1.f;
  258. const AZStd::string collisionGroup = "default";
  259. const AZ::EntityId ignoreEntityId;
  260. auto fromEntity = AZStd::make_unique<AZ::Entity>("Entity");
  261. fromEntity->CreateComponent<AzFramework::TransformComponent>()->SetWorldTM(AZ::Transform::Identity());
  262. fromEntity->Init();
  263. fromEntity->Activate();
  264. // when a raycast is performed
  265. auto result = ScriptCanvasPhysics::WorldFunctions::RayCastLocalSpaceWithGroup(
  266. fromEntity->GetId(),
  267. direction,
  268. distance,
  269. collisionGroup,
  270. fromEntity->GetId()
  271. );
  272. // expect a valid hit is returned
  273. EXPECT_TRUE(ResultIsEqualToHit(result, m_hit));
  274. }
  275. TEST_F(ScriptCanvasPhysicsTest, WorldNodes_RayCastMultipleLocalSpaceWithGroup_FT)
  276. {
  277. AZStd::vector<AzPhysics::SceneQueryHit> hits;
  278. hits.push_back(m_hit);
  279. ON_CALL(m_sceneInterfaceMock, QueryScene(_, _))
  280. .WillByDefault(Return(m_hitResult));
  281. // given raycast data
  282. const AZ::Vector3 direction = AZ::Vector3(0.f,1.f,0.f);
  283. const float distance = 1.f;
  284. const AZStd::string collisionGroup = "default";
  285. const AZ::EntityId ignoreEntityId;
  286. auto fromEntity = AZStd::make_unique<AZ::Entity>("Entity");
  287. fromEntity->CreateComponent<AzFramework::TransformComponent>()->SetWorldTM(AZ::Transform::Identity());
  288. fromEntity->Init();
  289. fromEntity->Activate();
  290. // when a raycast is performed
  291. auto results = ScriptCanvasPhysics::WorldFunctions::RayCastMultipleLocalSpaceWithGroup(
  292. fromEntity->GetId(),
  293. direction,
  294. distance,
  295. collisionGroup,
  296. fromEntity->GetId()
  297. );
  298. // expect valid hits are returned
  299. EXPECT_FALSE(results.empty());
  300. for (auto result : results)
  301. {
  302. EXPECT_EQ(result.m_distance, m_hit.m_distance);
  303. EXPECT_EQ(result.m_physicsMaterialId, m_hit.m_physicsMaterialId);
  304. EXPECT_EQ(result.m_normal, m_hit.m_normal);
  305. EXPECT_EQ(result.m_position, m_hit.m_position);
  306. EXPECT_EQ(result.m_shape, m_hit.m_shape);
  307. }
  308. }
  309. TEST_F(ScriptCanvasPhysicsTest, WorldNodes_ShapecastQuery_FT)
  310. {
  311. ON_CALL(m_sceneInterfaceMock, QueryScene(_, _))
  312. .WillByDefault(Return(m_hitResult));
  313. // given shapecast data
  314. const AZ::Vector3 direction = AZ::Vector3(0.f,1.f,0.f);
  315. const float distance = 1.f;
  316. const AZStd::string collisionGroup = "default";
  317. const AZ::EntityId ignoreEntityId;
  318. const AZ::Transform pose = AZ::Transform::CreateIdentity();
  319. // when a shapecast is performed
  320. auto result = ScriptCanvasPhysics::WorldFunctions::ShapecastQuery(
  321. distance,
  322. pose,
  323. direction,
  324. AZStd::make_shared<Physics::BoxShapeConfiguration>(),
  325. collisionGroup,
  326. ignoreEntityId
  327. );
  328. // expect a valid hit is returned
  329. EXPECT_TRUE(ResultIsEqualToHit(result, m_hit));
  330. }
  331. }
  332. AZ_UNIT_TEST_HOOK(new ScriptCanvasPhysicsTests::ScriptCanvasPhysicsTestEnvironment);