BlastActorImpl.cpp 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  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 <Actor/BlastActorImpl.h>
  9. #include <Actor/ShapesProvider.h>
  10. #include <AzCore/Component/TransformBus.h>
  11. #include <AzCore/Math/Transform.h>
  12. #include <AzFramework/Physics/PhysicsSystem.h>
  13. #include <AzFramework/Physics/RigidBodyBus.h>
  14. #include <AzFramework/Physics/Shape.h>
  15. #include <AzFramework/Physics/SystemBus.h>
  16. #include <AzFramework/Physics/Utils.h>
  17. #include <AzFramework/Physics/Material/PhysicsMaterialManager.h>
  18. #include <AzFramework/Physics/Components/SimulatedBodyComponentBus.h>
  19. #include <Blast/BlastActor.h>
  20. #include <Family/BlastFamily.h>
  21. #include <NvBlastExtPxAsset.h>
  22. #include <NvBlastTkActor.h>
  23. #include <NvBlastTkAsset.h>
  24. #include <NvBlastTypes.h>
  25. #include <PhysX/ColliderComponentBus.h>
  26. #include <PhysX/ComponentTypeIds.h>
  27. #include <PhysX/MathConversion.h>
  28. #include <PhysX/SystemComponentBus.h>
  29. namespace Blast
  30. {
  31. BlastActorImpl::BlastActorImpl(const BlastActorDesc& desc)
  32. : m_family(*desc.m_family)
  33. , m_tkActor(*desc.m_tkActor)
  34. , m_entity(desc.m_entity)
  35. , m_chunkIndices(desc.m_chunkIndices)
  36. , m_isLeafChunk(desc.m_isLeafChunk)
  37. , m_isStatic(desc.m_isStatic)
  38. , m_physicsMaterialId(desc.m_physicsMaterialId)
  39. , m_parentLinearVelocity(desc.m_parentLinearVelocity)
  40. , m_parentCenterOfMass(desc.m_parentCenterOfMass)
  41. , m_bodyConfiguration(desc.m_bodyConfiguration)
  42. , m_scale(desc.m_scale)
  43. {
  44. // Store pointer to ourselves in the blast toolkit actor's userData
  45. m_tkActor.userData = this;
  46. m_shapesProvider = AZStd::make_unique<ShapesProvider>(m_entity->GetId(), desc.m_bodyConfiguration);
  47. }
  48. BlastActorImpl::~BlastActorImpl()
  49. {
  50. m_tkActor.userData = nullptr;
  51. }
  52. void BlastActorImpl::Spawn()
  53. {
  54. // Get physics material from id
  55. AZStd::shared_ptr<Physics::Material> physicsMaterial = AZ::Interface<Physics::MaterialManager>::Get()->GetMaterial(m_physicsMaterialId);
  56. if (!physicsMaterial)
  57. {
  58. physicsMaterial = AZ::Interface<Physics::MaterialManager>::Get()->GetDefaultMaterial();
  59. }
  60. // Add shapes for each of the visible chunks
  61. AddShapes(m_chunkIndices, m_family.GetPxAsset(), physicsMaterial->GetMaterialAsset());
  62. m_entity->Init();
  63. m_entity->Activate();
  64. auto transform = AZ::Transform::CreateFromQuaternionAndTranslation(
  65. m_bodyConfiguration.m_orientation, m_bodyConfiguration.m_position);
  66. transform.MultiplyByUniformScale(m_scale);
  67. AZ::TransformBus::Event(m_entity->GetId(), &AZ::TransformInterface::SetWorldTM, transform);
  68. // Set initial velocities if we're not static
  69. if (!m_isStatic)
  70. {
  71. AzPhysics::RigidBody* rigidBody = nullptr;
  72. Physics::RigidBodyRequestBus::EventResult(
  73. rigidBody, m_entity->GetId(), &Physics::RigidBodyRequests::GetRigidBody);
  74. rigidBody->SetTransform(transform);
  75. const AZ::Vector3 com = rigidBody->GetTransform().TransformPoint(rigidBody->GetCenterOfMassLocal());
  76. const AZ::Vector3 linearVelocity =
  77. m_parentLinearVelocity + m_bodyConfiguration.m_initialAngularVelocity.Cross(com - m_parentCenterOfMass);
  78. Physics::RigidBodyRequestBus::Event(
  79. m_entity->GetId(), &Physics::RigidBodyRequests::SetLinearVelocity, linearVelocity);
  80. Physics::RigidBodyRequestBus::Event(
  81. m_entity->GetId(), &Physics::RigidBodyRequests::SetAngularVelocity,
  82. m_bodyConfiguration.m_initialAngularVelocity);
  83. }
  84. }
  85. void BlastActorImpl::AddShapes(
  86. const AZStd::vector<uint32_t>& chunkIndices, const Nv::Blast::ExtPxAsset& asset,
  87. const AZ::Data::Asset<Physics::MaterialAsset>& physicsMaterialAsset)
  88. {
  89. const Nv::Blast::ExtPxChunk* pxChunks = asset.getChunks();
  90. const Nv::Blast::ExtPxSubchunk* pxSubchunks = asset.getSubchunks();
  91. const uint32_t chunkCount = asset.getChunkCount();
  92. const uint32_t subchunkCount = asset.getSubchunkCount();
  93. AZ_Assert(pxChunks, "Received asset with a null chunk array.");
  94. AZ_Assert(pxSubchunks, "Received asset with a null subchunk array.");
  95. if (!pxChunks || !pxSubchunks)
  96. {
  97. return;
  98. }
  99. for (uint32_t chunkId : chunkIndices)
  100. {
  101. AZ_Assert(chunkId < chunkCount, "Out of bounds access to the BlastPxActor's PxChunks.");
  102. if (chunkId >= chunkCount)
  103. {
  104. continue;
  105. }
  106. const Nv::Blast::ExtPxChunk& chunk = pxChunks[chunkId];
  107. for (uint32_t i = 0; i < chunk.subchunkCount; i++)
  108. {
  109. const uint32_t subchunkIndex = chunk.firstSubchunkIndex + i;
  110. AZ_Assert(subchunkIndex < subchunkCount, "Out of bounds access to the BlastPxActor's PxSubchunks.");
  111. if (subchunkIndex >= subchunkCount)
  112. {
  113. continue;
  114. }
  115. auto& subchunk = pxSubchunks[subchunkIndex];
  116. AZ::Transform transform = PxMathConvert(subchunk.transform);
  117. auto colliderConfiguration = CalculateColliderConfiguration(transform, physicsMaterialAsset);
  118. Physics::NativeShapeConfiguration shapeConfiguration;
  119. shapeConfiguration.m_nativeShapePtr =
  120. reinterpret_cast<void*>(const_cast<physx::PxConvexMeshGeometry*>(&subchunk.geometry)->convexMesh);
  121. shapeConfiguration.m_nativeShapeScale = AZ::Vector3(m_scale);
  122. AZStd::shared_ptr<Physics::Shape> shape = AZ::Interface<Physics::SystemRequests>::Get()->CreateShape(
  123. colliderConfiguration, shapeConfiguration);
  124. AZ_Assert(shape, "Failed to create Shape for BlastActor");
  125. m_shapesProvider->AddShape(shape);
  126. }
  127. }
  128. }
  129. Physics::ColliderConfiguration BlastActorImpl::CalculateColliderConfiguration(
  130. const AZ::Transform& transform, const AZ::Data::Asset<Physics::MaterialAsset>& physicsMaterialAsset)
  131. {
  132. auto& actorConfiguration = m_family.GetActorConfiguration();
  133. Physics::ColliderConfiguration colliderConfiguration;
  134. colliderConfiguration.m_position = transform.GetTranslation();
  135. colliderConfiguration.m_rotation = transform.GetRotation();
  136. colliderConfiguration.m_isExclusive = true;
  137. colliderConfiguration.m_materialSlots.SetMaterialAsset(0, physicsMaterialAsset);
  138. colliderConfiguration.m_collisionGroupId = actorConfiguration.m_collisionGroupId;
  139. colliderConfiguration.m_collisionLayer = actorConfiguration.m_collisionLayer;
  140. colliderConfiguration.m_isInSceneQueries = actorConfiguration.m_isInSceneQueries;
  141. colliderConfiguration.m_isSimulated = actorConfiguration.m_isSimulated;
  142. colliderConfiguration.m_tag = actorConfiguration.m_tag;
  143. return colliderConfiguration;
  144. }
  145. AZ::Transform BlastActorImpl::GetTransform() const
  146. {
  147. return GetSimulatedBody()->GetTransform();
  148. }
  149. const BlastFamily& BlastActorImpl::GetFamily() const
  150. {
  151. return m_family;
  152. }
  153. const Nv::Blast::TkActor& BlastActorImpl::GetTkActor() const
  154. {
  155. return m_tkActor;
  156. }
  157. AzPhysics::SimulatedBody* BlastActorImpl::GetSimulatedBody()
  158. {
  159. AzPhysics::SimulatedBody* worldBody = nullptr;
  160. AzPhysics::SimulatedBodyComponentRequestsBus::EventResult(
  161. worldBody, m_entity->GetId(), &AzPhysics::SimulatedBodyComponentRequests::GetSimulatedBody);
  162. return worldBody;
  163. }
  164. const AzPhysics::SimulatedBody* BlastActorImpl::GetSimulatedBody() const
  165. {
  166. AzPhysics::SimulatedBody* worldBody = nullptr;
  167. AzPhysics::SimulatedBodyComponentRequestsBus::EventResult(
  168. worldBody, m_entity->GetId(), &AzPhysics::SimulatedBodyComponentRequests::GetSimulatedBody);
  169. return worldBody;
  170. }
  171. const AZStd::vector<uint32_t>& BlastActorImpl::GetChunkIndices() const
  172. {
  173. return m_chunkIndices;
  174. }
  175. bool BlastActorImpl::IsStatic() const
  176. {
  177. return m_isStatic;
  178. }
  179. const AZ::Entity* BlastActorImpl::GetEntity() const
  180. {
  181. return m_entity.get();
  182. }
  183. void BlastActorImpl::Damage(const NvBlastDamageProgram& program, NvBlastExtProgramParams* programParams)
  184. {
  185. m_tkActor.damage(program, programParams);
  186. }
  187. } // namespace Blast