WhiteBoxColliderComponent.cpp 7.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  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 "WhiteBoxColliderComponent.h"
  9. #include <AzCore/Component/Entity.h>
  10. #include <AzCore/Component/TransformBus.h>
  11. #include <AzCore/Serialization/SerializeContext.h>
  12. #include <AzFramework/Physics/PhysicsScene.h>
  13. #include <AzFramework/Physics/SimulatedBodies/RigidBody.h>
  14. #include <AzFramework/Physics/SystemBus.h>
  15. #include <AzFramework/Physics/Configuration/RigidBodyConfiguration.h>
  16. #include <AzFramework/Physics/Configuration/StaticRigidBodyConfiguration.h>
  17. namespace WhiteBox
  18. {
  19. void WhiteBoxColliderComponent::Reflect(AZ::ReflectContext* context)
  20. {
  21. WhiteBoxColliderConfiguration::Reflect(context);
  22. if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
  23. {
  24. serializeContext->Class<WhiteBoxColliderComponent, AZ::Component>()
  25. ->Version(1)
  26. ->Field("MeshData", &WhiteBoxColliderComponent::m_shapeConfiguration)
  27. ->Field("Configuration", &WhiteBoxColliderComponent::m_physicsColliderConfiguration)
  28. ->Field("WhiteBoxConfiguration", &WhiteBoxColliderComponent::m_whiteBoxColliderConfiguration);
  29. }
  30. }
  31. void WhiteBoxColliderComponent::GetProvidedServices([[maybe_unused]] AZ::ComponentDescriptor::DependencyArrayType& provided)
  32. {
  33. }
  34. void WhiteBoxColliderComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
  35. {
  36. required.push_back(AZ_CRC_CE("TransformService"));
  37. }
  38. void WhiteBoxColliderComponent::GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
  39. {
  40. incompatible.push_back(AZ_CRC_CE("NonUniformScaleService"));
  41. // Incompatible with other rigid bodies because it handles its own rigid body
  42. // internally and it would conflict if another rigid body is added to the entity.
  43. incompatible.push_back(AZ_CRC_CE("PhysicsRigidBodyService"));
  44. }
  45. WhiteBoxColliderComponent::WhiteBoxColliderComponent(
  46. const Physics::CookedMeshShapeConfiguration& shapeConfiguration,
  47. const Physics::ColliderConfiguration& physicsColliderConfiguration,
  48. const WhiteBoxColliderConfiguration& whiteBoxColliderConfiguration)
  49. : m_shapeConfiguration(shapeConfiguration)
  50. , m_physicsColliderConfiguration(physicsColliderConfiguration)
  51. , m_whiteBoxColliderConfiguration(whiteBoxColliderConfiguration)
  52. {
  53. }
  54. void WhiteBoxColliderComponent::Activate()
  55. {
  56. auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
  57. if (sceneInterface == nullptr)
  58. {
  59. AZ_Error("WhiteBox", false, "Missing Physics Scene Interface, unble to Activate WhiteBoxColliderComponent");
  60. return;
  61. }
  62. AzPhysics::SceneHandle defaultScene = sceneInterface->GetSceneHandle(AzPhysics::DefaultPhysicsSceneName);
  63. if (defaultScene == AzPhysics::InvalidSceneHandle)
  64. {
  65. AZ_Error("WhiteBox", false, "Missing Default Physics Scene, unble to Activate WhiteBoxColliderComponent");
  66. return;
  67. }
  68. const AZ::EntityId entityId = GetEntityId();
  69. AZ::Transform worldTransform = AZ::Transform::CreateIdentity();
  70. AZ::TransformBus::EventResult(worldTransform, entityId, &AZ::TransformInterface::GetWorldTM);
  71. // create shape
  72. AZStd::shared_ptr<Physics::Shape> shape;
  73. Physics::SystemRequestBus::BroadcastResult(
  74. shape, &Physics::SystemRequests::CreateShape, m_physicsColliderConfiguration, m_shapeConfiguration);
  75. // create rigid body
  76. switch (m_whiteBoxColliderConfiguration.m_bodyType)
  77. {
  78. case WhiteBoxBodyType::Kinematic:
  79. {
  80. AzPhysics::RigidBodyConfiguration bodyConfiguration;
  81. bodyConfiguration.m_debugName = GetEntity()->GetName().c_str();
  82. bodyConfiguration.m_entityId = entityId;
  83. bodyConfiguration.m_orientation = worldTransform.GetRotation();
  84. bodyConfiguration.m_position = worldTransform.GetTranslation();
  85. bodyConfiguration.m_kinematic = true; // note: this field is ignored in the WhiteBoxBodyType::Static case
  86. bodyConfiguration.m_colliderAndShapeData = shape;
  87. // Since the shape used is a triangle mesh the COM, Mass and Inertia
  88. // cannot be computed. Disable them to use default values.
  89. bodyConfiguration.m_computeCenterOfMass = false;
  90. bodyConfiguration.m_computeMass = false;
  91. bodyConfiguration.m_computeInertiaTensor = false;
  92. m_simulatedBodyHandle = sceneInterface->AddSimulatedBody(defaultScene, &bodyConfiguration);
  93. }
  94. break;
  95. case WhiteBoxBodyType::Static:
  96. {
  97. AzPhysics::StaticRigidBodyConfiguration staticBodyConfiguration;
  98. staticBodyConfiguration.m_debugName = GetEntity()->GetName().c_str();
  99. staticBodyConfiguration.m_entityId = entityId;
  100. staticBodyConfiguration.m_orientation = worldTransform.GetRotation();
  101. staticBodyConfiguration.m_position = worldTransform.GetTranslation();
  102. staticBodyConfiguration.m_colliderAndShapeData = shape;
  103. m_simulatedBodyHandle = sceneInterface->AddSimulatedBody(defaultScene, &staticBodyConfiguration);
  104. }
  105. break;
  106. default:
  107. AZ_Assert(
  108. false, "WhiteBoxBodyType %d not handled", static_cast<int>(m_whiteBoxColliderConfiguration.m_bodyType));
  109. break;
  110. }
  111. AZ::TransformNotificationBus::Handler::BusConnect(entityId);
  112. }
  113. void WhiteBoxColliderComponent::Deactivate()
  114. {
  115. AZ::TransformNotificationBus::Handler::BusDisconnect();
  116. if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
  117. {
  118. if (AzPhysics::SceneHandle defaultScene = sceneInterface->GetSceneHandle(AzPhysics::DefaultPhysicsSceneName);
  119. defaultScene != AzPhysics::InvalidSceneHandle)
  120. {
  121. sceneInterface->RemoveSimulatedBody(defaultScene, m_simulatedBodyHandle);
  122. }
  123. }
  124. }
  125. void WhiteBoxColliderComponent::OnTransformChanged(
  126. [[maybe_unused]] const AZ::Transform& local, const AZ::Transform& world)
  127. {
  128. const AZ::Transform worldTransformWithoutScale = [worldTransform = world]() mutable
  129. {
  130. worldTransform.SetUniformScale(1.0f);
  131. return worldTransform;
  132. }();
  133. if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
  134. {
  135. if (AzPhysics::SceneHandle defaultScene = sceneInterface->GetSceneHandle(AzPhysics::DefaultPhysicsSceneName);
  136. defaultScene != AzPhysics::InvalidSceneHandle)
  137. {
  138. //if this is a rigid body update the transform, otherwise its static for just warn
  139. if (auto* rigidBody = azdynamic_cast<AzPhysics::RigidBody*>(sceneInterface->GetSimulatedBodyFromHandle(defaultScene, m_simulatedBodyHandle)))
  140. {
  141. rigidBody->SetKinematicTarget(worldTransformWithoutScale);
  142. }
  143. else
  144. {
  145. AZ_WarningOnce(
  146. "WhiteBox", false,
  147. "The White Box Collider must be made Kinematic to respond to OnTransformChanged events");
  148. }
  149. }
  150. }
  151. }
  152. } // namespace WhiteBox