2
0

World.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  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 "World.h"
  9. #include <AzCore/Component/TransformBus.h>
  10. #include <AzCore/Interface/Interface.h>
  11. #include <AzCore/std/smart_ptr/make_shared.h>
  12. #include <AzFramework/Components/CameraBus.h>
  13. #include <AzFramework/Physics/Collision/CollisionGroups.h>
  14. #include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
  15. #include <AzFramework/Physics/Material/PhysicsMaterialId.h>
  16. #include <AzFramework/Physics/PhysicsScene.h>
  17. #include <AzFramework/Physics/ShapeConfiguration.h>
  18. namespace ScriptCanvasPhysics
  19. {
  20. namespace WorldFunctions
  21. {
  22. Result RayCastWorldSpaceWithGroup(
  23. const AZ::Vector3& start,
  24. const AZ::Vector3& direction,
  25. float distance,
  26. const AZStd::string& collisionGroup,
  27. AZ::EntityId ignore)
  28. {
  29. AzPhysics::RayCastRequest request;
  30. request.m_start = start;
  31. request.m_direction = direction.GetNormalized();
  32. request.m_distance = distance;
  33. request.m_filterCallback = [ignore](const AzPhysics::SimulatedBody* body, [[maybe_unused]] const Physics::Shape* shape)
  34. {
  35. return body->GetEntityId() != ignore ? AzPhysics::SceneQuery::QueryHitType::Block
  36. : AzPhysics::SceneQuery::QueryHitType::None;
  37. };
  38. if (!collisionGroup.empty())
  39. {
  40. request.m_collisionGroup = AzPhysics::CollisionGroup(collisionGroup);
  41. }
  42. AzPhysics::SceneQueryHits result;
  43. if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
  44. {
  45. if (AzPhysics::SceneHandle sceneHandle = sceneInterface->GetSceneHandle(AzPhysics::DefaultPhysicsSceneName);
  46. sceneHandle != AzPhysics::InvalidSceneHandle)
  47. {
  48. result = sceneInterface->QueryScene(sceneHandle, &request);
  49. }
  50. }
  51. if (result)
  52. {
  53. const AZ::Crc32 surfaceType(result.m_hits[0].m_physicsMaterialId.ToString<AZStd::string>());
  54. return AZStd::make_tuple(
  55. result.m_hits[0].IsValid(), result.m_hits[0].m_position, result.m_hits[0].m_normal, result.m_hits[0].m_distance,
  56. result.m_hits[0].m_entityId, surfaceType);
  57. }
  58. return AZStd::make_tuple(false, AZ::Vector3::CreateZero(), AZ::Vector3::CreateZero(), 0.0f, AZ::EntityId(), AZ::Crc32());
  59. }
  60. Result RayCastFromScreenWithGroup(
  61. const AZ::Vector2& screenPosition, float distance, const AZStd::string& collisionGroup, AZ::EntityId ignore)
  62. {
  63. AZ::EntityId camera;
  64. Camera::CameraSystemRequestBus::BroadcastResult(camera, &Camera::CameraSystemRequestBus::Events::GetActiveCamera);
  65. if (camera.IsValid())
  66. {
  67. AZ::Vector3 origin = AZ::Vector3::CreateZero();
  68. Camera::CameraRequestBus::EventResult(
  69. origin, camera, &Camera::CameraRequestBus::Events::ScreenToWorld, screenPosition, 0.f);
  70. AZ::Vector3 offset = AZ::Vector3::CreateZero();
  71. Camera::CameraRequestBus::EventResult(
  72. offset, camera, &Camera::CameraRequestBus::Events::ScreenToWorld, screenPosition, 1.f);
  73. const AZ::Vector3 direction = (offset - origin).GetNormalized();
  74. return RayCastWorldSpaceWithGroup(origin, direction, distance, collisionGroup, ignore);
  75. }
  76. // fallback in the rare case there is no active camera
  77. return AZStd::make_tuple(false, AZ::Vector3::CreateZero(), AZ::Vector3::CreateZero(), 0.0f, AZ::EntityId(), AZ::Crc32());
  78. }
  79. Result RayCastLocalSpaceWithGroup(
  80. const AZ::EntityId& fromEntityId,
  81. const AZ::Vector3& direction,
  82. float distance,
  83. const AZStd::string& collisionGroup,
  84. AZ::EntityId ignore)
  85. {
  86. AZ::Transform worldSpaceTransform = AZ::Transform::CreateIdentity();
  87. AZ::TransformBus::EventResult(worldSpaceTransform, fromEntityId, &AZ::TransformInterface::GetWorldTM);
  88. return RayCastWorldSpaceWithGroup(
  89. worldSpaceTransform.GetTranslation(), worldSpaceTransform.TransformVector(direction.GetNormalized()), distance,
  90. collisionGroup, ignore);
  91. }
  92. AZStd::vector<AzPhysics::SceneQueryHit> RayCastMultipleLocalSpaceWithGroup(
  93. const AZ::EntityId& fromEntityId,
  94. const AZ::Vector3& direction,
  95. float distance,
  96. const AZStd::string& collisionGroup,
  97. AZ::EntityId ignore)
  98. {
  99. AZ::Transform worldSpaceTransform = AZ::Transform::CreateIdentity();
  100. AZ::TransformBus::EventResult(worldSpaceTransform, fromEntityId, &AZ::TransformInterface::GetWorldTM);
  101. AzPhysics::RayCastRequest request;
  102. request.m_start = worldSpaceTransform.GetTranslation();
  103. request.m_direction = worldSpaceTransform.TransformVector(direction.GetNormalized());
  104. request.m_distance = distance;
  105. request.m_reportMultipleHits = true;
  106. request.m_filterCallback = [ignore](const AzPhysics::SimulatedBody* body, [[maybe_unused]] const Physics::Shape* shape)
  107. {
  108. return body->GetEntityId() != ignore ? AzPhysics::SceneQuery::QueryHitType::Touch
  109. : AzPhysics::SceneQuery::QueryHitType::None;
  110. };
  111. if (!collisionGroup.empty())
  112. {
  113. request.m_collisionGroup = AzPhysics::CollisionGroup(collisionGroup);
  114. }
  115. AzPhysics::SceneQueryHits result;
  116. if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
  117. {
  118. if (AzPhysics::SceneHandle sceneHandle = sceneInterface->GetSceneHandle(AzPhysics::DefaultPhysicsSceneName);
  119. sceneHandle != AzPhysics::InvalidSceneHandle)
  120. {
  121. result = sceneInterface->QueryScene(sceneHandle, &request);
  122. }
  123. }
  124. return result.m_hits;
  125. }
  126. OverlapResult OverlapQuery(
  127. const AZ::Transform& pose,
  128. AZStd::shared_ptr<Physics::ShapeConfiguration> shape,
  129. const AZStd::string& collisionGroup,
  130. AZ::EntityId ignore)
  131. {
  132. AzPhysics::OverlapRequest request;
  133. request.m_pose = pose;
  134. request.m_shapeConfiguration = shape;
  135. request.m_filterCallback = [ignore](const AzPhysics::SimulatedBody* body, [[maybe_unused]] const Physics::Shape* shape)
  136. {
  137. return body->GetEntityId() != ignore;
  138. };
  139. if (!collisionGroup.empty())
  140. {
  141. request.m_collisionGroup = AzPhysics::CollisionGroup(collisionGroup);
  142. }
  143. AzPhysics::SceneQueryHits results;
  144. if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
  145. {
  146. if (AzPhysics::SceneHandle sceneHandle = sceneInterface->GetSceneHandle(AzPhysics::DefaultPhysicsSceneName);
  147. sceneHandle != AzPhysics::InvalidSceneHandle)
  148. {
  149. results = sceneInterface->QueryScene(sceneHandle, &request);
  150. }
  151. }
  152. AZStd::vector<AZ::EntityId> overlapIds;
  153. overlapIds.reserve(results.m_hits.size());
  154. AZStd::transform(
  155. results.m_hits.begin(), results.m_hits.end(), AZStd::back_inserter(overlapIds),
  156. [](const AzPhysics::SceneQueryHit& overlap)
  157. {
  158. return overlap.m_entityId;
  159. });
  160. return AZStd::make_tuple(!overlapIds.empty(), overlapIds);
  161. }
  162. OverlapResult OverlapSphereWithGroup(
  163. const AZ::Vector3& position, float radius, const AZStd::string& collisionGroup, AZ::EntityId ignore)
  164. {
  165. return OverlapQuery(
  166. AZ::Transform::CreateTranslation(position), AZStd::make_shared<Physics::SphereShapeConfiguration>(radius), collisionGroup,
  167. ignore);
  168. }
  169. OverlapResult OverlapBoxWithGroup(
  170. const AZ::Transform& pose, const AZ::Vector3& dimensions, const AZStd::string& collisionGroup, AZ::EntityId ignore)
  171. {
  172. return OverlapQuery(pose, AZStd::make_shared<Physics::BoxShapeConfiguration>(dimensions), collisionGroup, ignore);
  173. }
  174. OverlapResult OverlapCapsuleWithGroup(
  175. const AZ::Transform& pose, float height, float radius, const AZStd::string& collisionGroup, AZ::EntityId ignore)
  176. {
  177. return OverlapQuery(pose, AZStd::make_shared<Physics::CapsuleShapeConfiguration>(height, radius), collisionGroup, ignore);
  178. }
  179. Result ShapecastQuery(
  180. float distance,
  181. const AZ::Transform& pose,
  182. const AZ::Vector3& direction,
  183. AZStd::shared_ptr<Physics::ShapeConfiguration> shape,
  184. const AZStd::string& collisionGroup,
  185. AZ::EntityId ignore)
  186. {
  187. AzPhysics::ShapeCastRequest request;
  188. request.m_distance = distance;
  189. request.m_start = pose;
  190. request.m_direction = direction;
  191. request.m_shapeConfiguration = shape;
  192. request.m_filterCallback = [ignore](const AzPhysics::SimulatedBody* body, [[maybe_unused]] const Physics::Shape* shape)
  193. {
  194. return body->GetEntityId() != ignore ? AzPhysics::SceneQuery::QueryHitType::Block
  195. : AzPhysics::SceneQuery::QueryHitType::None;
  196. };
  197. if (!collisionGroup.empty())
  198. {
  199. request.m_collisionGroup = AzPhysics::CollisionGroup(collisionGroup);
  200. }
  201. AzPhysics::SceneQueryHits result;
  202. if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
  203. {
  204. if (AzPhysics::SceneHandle sceneHandle = sceneInterface->GetSceneHandle(AzPhysics::DefaultPhysicsSceneName);
  205. sceneHandle != AzPhysics::InvalidSceneHandle)
  206. {
  207. result = sceneInterface->QueryScene(sceneHandle, &request);
  208. }
  209. }
  210. if (result)
  211. {
  212. const AZ::Crc32 surfaceType(result.m_hits[0].m_physicsMaterialId.ToString<AZStd::string>());
  213. return AZStd::make_tuple(
  214. result.m_hits[0].IsValid(), result.m_hits[0].m_position, result.m_hits[0].m_normal, result.m_hits[0].m_distance,
  215. result.m_hits[0].m_entityId, surfaceType);
  216. }
  217. return AZStd::make_tuple(false, AZ::Vector3::CreateZero(), AZ::Vector3::CreateZero(), 0.0f, AZ::EntityId(), AZ::Crc32());
  218. }
  219. Result SphereCastWithGroup(
  220. float distance,
  221. const AZ::Transform& pose,
  222. const AZ::Vector3& direction,
  223. float radius,
  224. const AZStd::string& collisionGroup,
  225. AZ::EntityId ignore)
  226. {
  227. return ShapecastQuery(
  228. distance, pose, direction, AZStd::make_shared<Physics::SphereShapeConfiguration>(radius), collisionGroup, ignore);
  229. }
  230. Result BoxCastWithGroup(
  231. float distance,
  232. const AZ::Transform& pose,
  233. const AZ::Vector3& direction,
  234. const AZ::Vector3& dimensions,
  235. const AZStd::string& collisionGroup,
  236. AZ::EntityId ignore)
  237. {
  238. return ShapecastQuery(
  239. distance, pose, direction, AZStd::make_shared<Physics::BoxShapeConfiguration>(dimensions), collisionGroup, ignore);
  240. }
  241. Result CapsuleCastWithGroup(
  242. float distance,
  243. const AZ::Transform& pose,
  244. const AZ::Vector3& direction,
  245. float height,
  246. float radius,
  247. const AZStd::string& collisionGroup,
  248. AZ::EntityId ignore)
  249. {
  250. return ShapecastQuery(
  251. distance, pose, direction, AZStd::make_shared<Physics::CapsuleShapeConfiguration>(height, radius), collisionGroup, ignore);
  252. }
  253. } // namespace WorldFunctions
  254. } // namespace ScriptCanvasPhysics