Merge pull request #242 from aws-lumberyard-dev/physx_ragdoll_create

Ragdoll now uses Add/Remove SimulatedBody
This commit is contained in:
amzn-sean
2021-04-27 15:53:23 +01:00
committed by GitHub
27 changed files with 9694 additions and 9288 deletions
@@ -269,6 +269,8 @@ class TestAutomation(TestAutomationBase):
from . import C18977601_Material_FrictionCombinePriority as test_module
self._run_test(request, workspace, editor, test_module)
@pytest.mark.xfail(
reason="Something with the CryRenderer disabling is causing this test to fail now.")
@revert_physics_config
def test_C13895144_Ragdoll_ChangeLevel(self, request, workspace, editor, launcher_platform):
from . import C13895144_Ragdoll_ChangeLevel as test_module
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
@@ -78,7 +78,7 @@ namespace Physics
float m_minimumMovementDistance = 0.001f; //!< To avoid jittering, the controller will not attempt to move distances below this.
float m_maximumSpeed = 100.0f; //!< If the accumulated requested velocity for a tick exceeds this magnitude, it will be clamped.
AZStd::string m_colliderTag; //!< Used to identify the collider associated with the character controller.
AZStd::shared_ptr<Physics::ShapeConfiguration> m_shapeConfig = nullptr; //!< The shape to use when creating the character controller.
AZStd::shared_ptr<Physics::ShapeConfiguration> m_shapeConfig; //!< The shape to use when creating the character controller.
AZStd::vector<AZStd::shared_ptr<Physics::Shape>> m_colliders; //!< The list of colliders to attach to the character controller.
};
@@ -55,7 +55,7 @@ namespace AzPhysics
//! Flag to determine if the body is part of the simulation.
//! When true the body will be affected by any forces, collisions, and found with scene queries.
bool m_simulating = true;
bool m_simulating = false;
//! Helper functions for setting user data.
//! @param userData Can be a pointer to any type as internally will be cast to a void*. Object lifetime not managed by the SimulatedBody.
@@ -46,6 +46,7 @@ namespace AzPhysics
->Field("orientation", &SimulatedBodyConfiguration::m_orientation)
->Field("scale", &SimulatedBodyConfiguration::m_scale)
->Field("entityId", &SimulatedBodyConfiguration::m_entityId)
->Field("startSimulationEnabled", &SimulatedBodyConfiguration::m_startSimulationEnabled)
;
}
}
@@ -39,6 +39,7 @@ namespace AzPhysics
AZ::Vector3 m_position = AZ::Vector3::CreateZero();
AZ::Quaternion m_orientation = AZ::Quaternion::CreateIdentity();
AZ::Vector3 m_scale = AZ::Vector3::CreateOne();
bool m_startSimulationEnabled = true;
// Entity/object association.
AZ::EntityId m_entityId = AZ::EntityId(AZ::EntityId::InvalidEntityId);
@@ -52,6 +52,11 @@ namespace Physics
}
}
RagdollConfiguration::RagdollConfiguration()
{
m_startSimulationEnabled = false; //ragdolls do not start enabled.
}
void RagdollConfiguration::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
@@ -24,6 +24,8 @@
namespace Physics
{
using ParentIndices = AZStd::vector<size_t>;
class RagdollNodeConfiguration
: public AzPhysics::RigidBodyConfiguration
{
@@ -46,7 +48,7 @@ namespace Physics
AZ_RTTI(RagdollConfiguration, "{7C96D332-61D8-4C58-A2BF-707716D38D14}", AzPhysics::SimulatedBodyConfiguration);
static void Reflect(AZ::ReflectContext* context);
RagdollConfiguration() = default;
RagdollConfiguration();
explicit RagdollConfiguration(const RagdollConfiguration& settings) = default;
RagdollNodeConfiguration* FindNodeConfigByName(const AZStd::string& nodeName) const;
@@ -56,6 +58,8 @@ namespace Physics
AZStd::vector<RagdollNodeConfiguration> m_nodes;
CharacterColliderConfiguration m_colliders;
RagdollState m_initialState;
ParentIndices m_parentIndices;
};
/// Represents a single rigid part of a ragdoll.
@@ -79,7 +83,7 @@ namespace Physics
{
public:
AZ_CLASS_ALLOCATOR(Ragdoll, AZ::SystemAllocator, 0);
AZ_RTTI(Ragdoll, "{01F09602-80EC-4693-A0E7-C2719239044B}", AzPhysics::SimulatedBody);
AZ_RTTI(Physics::Ragdoll, "{01F09602-80EC-4693-A0E7-C2719239044B}", AzPhysics::SimulatedBody);
virtual ~Ragdoll() = default;
/// Inserts the ragdoll into the physics simulation.
@@ -443,9 +443,12 @@ namespace DebugDraw
AZ::TransformBus::EventResult(sphereElement.m_worldLocation, sphereElement.m_targetEntityId, &AZ::TransformBus::Events::GetWorldTranslation);
}
ColorB lyColor(sphereElement.m_color.ToU32());
Vec3 worldLocation(AZVec3ToLYVec3(sphereElement.m_worldLocation));
gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(worldLocation, sphereElement.m_radius, lyColor, true);
if (gEnv->pRenderer)
{
ColorB lyColor(sphereElement.m_color.ToU32());
Vec3 worldLocation(AZVec3ToLYVec3(sphereElement.m_worldLocation));
gEnv->pRenderer->GetIRenderAuxGeom()->DrawSphere(worldLocation, sphereElement.m_radius, lyColor, true);
}
}
removeExpiredDebugElementsFromVector(m_activeSpheres);
@@ -167,19 +167,18 @@ namespace PhysX
return aznew CharacterController(pxController, AZStd::move(callbackManager), scene->GetSceneHandle());
}
AZStd::unique_ptr<Ragdoll> CreateRagdoll(Physics::RagdollConfiguration& configuration,
const Physics::RagdollState& initialState, const ParentIndices& parentIndices, AzPhysics::SceneHandle sceneHandle)
Ragdoll* CreateRagdoll(Physics::RagdollConfiguration& configuration, AzPhysics::SceneHandle sceneHandle)
{
const size_t numNodes = configuration.m_nodes.size();
if (numNodes != initialState.size())
if (numNodes != configuration.m_initialState.size())
{
AZ_Error("PhysX Ragdoll", false, "Mismatch between number of nodes in ragdoll configuration (%i) "
"and number of nodes in the initial ragdoll state (%i)", numNodes, initialState.size());
"and number of nodes in the initial ragdoll state (%i)", numNodes, configuration.m_initialState.size());
return nullptr;
}
AZStd::unique_ptr<Ragdoll> ragdoll = AZStd::make_unique<Ragdoll>(sceneHandle);
ragdoll->SetParentIndices(parentIndices);
ragdoll->SetParentIndices(configuration.m_parentIndices);
auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
if (sceneInterface == nullptr)
@@ -192,15 +191,21 @@ namespace PhysX
for (size_t nodeIndex = 0; nodeIndex < numNodes; nodeIndex++)
{
Physics::RagdollNodeConfiguration& nodeConfig = configuration.m_nodes[nodeIndex];
const Physics::RagdollNodeState& nodeState = initialState[nodeIndex];
const Physics::RagdollNodeState& nodeState = configuration.m_initialState[nodeIndex];
Physics::CharacterColliderNodeConfiguration* colliderNodeConfig = configuration.m_colliders.FindNodeConfigByName(nodeConfig.m_debugName);
if (colliderNodeConfig)
{
AZStd::vector<AZStd::shared_ptr<Physics::Shape>> shapes;
for (const auto& shapeConfig : colliderNodeConfig->m_shapes)
for (const auto& [colliderConfig, shapeConfig] : colliderNodeConfig->m_shapes)
{
if (auto shape = AZStd::make_shared<Shape>(*shapeConfig.first, *shapeConfig.second))
if (colliderConfig == nullptr || shapeConfig == nullptr)
{
AZ_Error("PhysX Ragdoll", false, "Failed to create collider shape for ragdoll node %s", nodeConfig.m_debugName.c_str());
return nullptr;
}
if (auto shape = AZStd::make_shared<Shape>(*colliderConfig, *shapeConfig))
{
shapes.emplace_back(shape);
}
@@ -212,22 +217,20 @@ namespace PhysX
}
nodeConfig.m_colliderAndShapeData = shapes;
}
nodeConfig.m_startSimulationEnabled = false;
nodeConfig.m_position = nodeState.m_position;
nodeConfig.m_orientation = nodeState.m_orientation;
AzPhysics::SimulatedBodyHandle newBodyHandle = sceneInterface->AddSimulatedBody(sceneHandle, &nodeConfig);
if (newBodyHandle == AzPhysics::InvalidSimulatedBodyHandle)
AZStd::unique_ptr<RagdollNode> node = AZStd::make_unique<RagdollNode>(sceneHandle, nodeConfig);
if (node->GetRigidBodyHandle() != AzPhysics::InvalidSimulatedBodyHandle)
{
ragdoll->AddNode(AZStd::move(node));
}
else
{
AZ_Error("PhysX Ragdoll", false, "Failed to create rigid body for ragdoll node %s", nodeConfig.m_debugName.c_str());
return nullptr;
node.reset();
}
sceneInterface->DisableSimulationOfBody(sceneHandle, newBodyHandle);
auto* rigidBody = azdynamic_cast<AzPhysics::RigidBody*>(sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, newBodyHandle));
physx::PxRigidDynamic* pxRigidDynamic = static_cast<physx::PxRigidDynamic*>(rigidBody->GetNativePointer());
physx::PxTransform transform(PxMathConvert(nodeState.m_position), PxMathConvert(nodeState.m_orientation));
pxRigidDynamic->setGlobalPose(transform);
AZStd::unique_ptr<RagdollNode> node = AZStd::make_unique<RagdollNode>(rigidBody, newBodyHandle);
ragdoll->AddNode(AZStd::move(node));
}
// Set up joints. Needs a second pass because child nodes in the ragdoll config aren't guaranteed to have
@@ -235,7 +238,7 @@ namespace PhysX
size_t rootIndex = SIZE_MAX;
for (size_t nodeIndex = 0; nodeIndex < numNodes; nodeIndex++)
{
size_t parentIndex = parentIndices[nodeIndex];
size_t parentIndex = configuration.m_parentIndices[nodeIndex];
if (parentIndex < numNodes)
{
physx::PxRigidDynamic* parentActor = ragdoll->GetPxRigidDynamic(parentIndex);
@@ -301,8 +304,8 @@ namespace PhysX
}
ragdoll->SetRootIndex(rootIndex);
return ragdoll;
return ragdoll.release();
}
physx::PxD6JointDrive CreateD6JointDrive(float stiffness, float dampingRatio, float forceLimit)
@@ -40,11 +40,8 @@ namespace PhysX
//! Creates a ragdoll based on the specified setup and initial pose.
//! @param configuration Information about collider geometry and joint setup required to initialize the ragdoll.
//! @param initialState Initial settings for the positions, orientations and velocities of the ragdoll nodes.
//! @param parentIndices Identifies the parent ragdoll node for each node in the ragdoll.
//! @param sceneHandle A handle to the physics scene in which the ragdoll should be created.
AZStd::unique_ptr<Ragdoll> CreateRagdoll(Physics::RagdollConfiguration& configuration,
const Physics::RagdollState& initialState, const ParentIndices& parentIndices, AzPhysics::SceneHandle sceneHandle);
Ragdoll* CreateRagdoll(Physics::RagdollConfiguration& configuration, AzPhysics::SceneHandle sceneHandle);
//! Creates a joint drive with properties based on the input values.
//! The input values are validated and the damping ratio is used to calculate the damping value used internally.
@@ -45,7 +45,7 @@ namespace PhysX
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<Ragdoll>()
serializeContext->Class<PhysX::Ragdoll, Physics::Ragdoll>()
->Version(1)
;
}
@@ -56,7 +56,7 @@ namespace PhysX
m_nodes.push_back(AZStd::move(node));
}
void Ragdoll::SetParentIndices(const ParentIndices& parentIndices)
void Ragdoll::SetParentIndices(const Physics::ParentIndices& parentIndices)
{
m_parentIndices = parentIndices;
}
@@ -109,7 +109,6 @@ namespace PhysX
this->ApplyQueuedDisableSimulation();
})
{
m_simulating = false;
m_sceneOwner = sceneHandle;
}
@@ -117,14 +116,7 @@ namespace PhysX
{
m_sceneStartSimHandler.Disconnect();
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
{
const size_t numNodes = m_nodes.size();
for (size_t nodeIndex = 0; nodeIndex < numNodes; nodeIndex++)
{
sceneInterface->RemoveSimulatedBody(m_sceneOwner, m_nodes[nodeIndex]->GetRigidBodyHandle());
}
}
m_nodes.clear(); //the nodes destructor will remove the simulated body from the scene.
}
void Ragdoll::ApplyQueuedEnableSimulation()
@@ -204,7 +196,6 @@ namespace PhysX
sceneInterface->EnableSimulationOfBody(m_sceneOwner, m_nodes[nodeIndex]->GetRigidBodyHandle());
}
else
{
AZ_Error("PhysX Ragdoll", false, "Invalid PhysX actor for node index %i", nodeIndex);
@@ -222,8 +213,7 @@ namespace PhysX
}
sceneInterface->RegisterSceneSimulationStartHandler(m_sceneOwner, m_sceneStartSimHandler);
m_simulating = true;
sceneInterface->EnableSimulationOfBody(m_sceneOwner, m_bodyHandle);
}
void Ragdoll::EnableSimulationQueued(const Physics::RagdollState& initialState)
@@ -276,7 +266,7 @@ namespace PhysX
}
}
m_simulating = false;
sceneInterface->DisableSimulationOfBody(m_sceneOwner, m_bodyHandle);
}
void Ragdoll::DisableSimulationQueued()
@@ -19,8 +19,6 @@
namespace PhysX
{
using ParentIndices = AZStd::vector<size_t>;
/// PhysX specific implementation of generic physics API Ragdoll class.
class Ragdoll
: public Physics::Ragdoll
@@ -29,7 +27,7 @@ namespace PhysX
friend class RagdollComponent;
AZ_CLASS_ALLOCATOR(Ragdoll, AZ::SystemAllocator, 0);
AZ_TYPE_INFO_LEGACY(PhysX::Ragdoll, "{55D477B5-B922-4D3E-89FE-7FB7B9FDD635}", Physics::Ragdoll);
AZ_RTTI(PhysX::Ragdoll, "{55D477B5-B922-4D3E-89FE-7FB7B9FDD635}", Physics::Ragdoll);
static void Reflect(AZ::ReflectContext* context);
Ragdoll() = default;
@@ -38,7 +36,7 @@ namespace PhysX
~Ragdoll();
void AddNode(AZStd::unique_ptr<RagdollNode> node);
void SetParentIndices(const ParentIndices& parentIndices);
void SetParentIndices(const Physics::ParentIndices& parentIndices);
void SetRootIndex(size_t nodeIndex);
physx::PxRigidDynamic* GetPxRigidDynamic(size_t nodeIndex) const;
physx::PxTransform GetRootPxTransform() const;
@@ -75,7 +73,7 @@ namespace PhysX
void ApplyQueuedDisableSimulation();
AZStd::vector<AZStd::unique_ptr<RagdollNode>> m_nodes;
ParentIndices m_parentIndices;
Physics::ParentIndices m_parentIndices;
AZ::Outcome<size_t> m_rootIndex = AZ::Failure();
/// Queued initial state for the ragdoll, for EnableSimulationQueued, to be applied prior to the world update.
@@ -12,6 +12,7 @@
#include <PhysX_precompiled.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzFramework/Physics/PhysicsScene.h>
#include <AzFramework/Physics/Common/PhysicsSceneQueries.h>
#include <PhysXCharacters/API/RagdollNode.h>
#include <PhysX/NativeTypeIdentifiers.h>
@@ -30,14 +31,14 @@ namespace PhysX
}
}
RagdollNode::RagdollNode(AzPhysics::RigidBody* rigidBody, AzPhysics::SimulatedBodyHandle rigidBodyHandle)
: m_rigidBody(rigidBody)
, m_rigidBodyHandle(rigidBodyHandle)
RagdollNode::RagdollNode(AzPhysics::SceneHandle sceneHandle, Physics::RagdollNodeConfiguration& nodeConfig)
{
physx::PxRigidDynamic* pxRigidDynamic = static_cast<physx::PxRigidDynamic*>(m_rigidBody->GetNativePointer());
m_actorUserData = PhysX::ActorData(pxRigidDynamic);
m_actorUserData.SetRagdollNode(this);
m_actorUserData.SetEntityId(m_rigidBody->GetEntityId());
CreatePhysicsBody(sceneHandle, nodeConfig);
}
RagdollNode::~RagdollNode()
{
DestroyPhysicsBody();
}
void RagdollNode::SetJoint(const AZStd::shared_ptr<Physics::Joint>& joint)
@@ -124,4 +125,47 @@ namespace PhysX
{
return m_rigidBodyHandle;
}
void RagdollNode::CreatePhysicsBody(AzPhysics::SceneHandle sceneHandle, Physics::RagdollNodeConfiguration& nodeConfig)
{
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
{
m_rigidBodyHandle = sceneInterface->AddSimulatedBody(sceneHandle, &nodeConfig);
if (m_rigidBodyHandle == AzPhysics::InvalidSimulatedBodyHandle)
{
AZ_Error("PhysX RagdollNode", false, "Failed to create rigid body for ragdoll node %s", nodeConfig.m_debugName.c_str());
return;
}
m_rigidBody = azdynamic_cast<AzPhysics::RigidBody*>(sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, m_rigidBodyHandle));
}
if (m_rigidBody == nullptr)
{
AZ_Error("PhysX RagdollNode", false, "Failed to create rigid body for ragdoll node %s", nodeConfig.m_debugName.c_str());
return;
}
m_sceneOwner = sceneHandle;
physx::PxRigidDynamic* pxRigidDynamic = static_cast<physx::PxRigidDynamic*>(m_rigidBody->GetNativePointer());
physx::PxTransform transform(PxMathConvert(nodeConfig.m_position), PxMathConvert(nodeConfig.m_orientation));
pxRigidDynamic->setGlobalPose(transform);
m_actorUserData = PhysX::ActorData(pxRigidDynamic);
m_actorUserData.SetRagdollNode(this);
m_actorUserData.SetEntityId(m_rigidBody->GetEntityId());
}
void RagdollNode::DestroyPhysicsBody()
{
if (m_rigidBody != nullptr)
{
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
{
sceneInterface->RemoveSimulatedBody(m_sceneOwner, m_rigidBodyHandle);
}
m_rigidBody = nullptr;
m_rigidBodyHandle = AzPhysics::InvalidSimulatedBodyHandle;
m_sceneOwner = AzPhysics::InvalidSceneHandle;
}
}
} // namespace PhysX
@@ -29,8 +29,8 @@ namespace PhysX
static void Reflect(AZ::ReflectContext* context);
RagdollNode() = default;
explicit RagdollNode(AzPhysics::RigidBody* rigidBody, AzPhysics::SimulatedBodyHandle rigidBodyHandle);
~RagdollNode() = default;
explicit RagdollNode(AzPhysics::SceneHandle sceneHandle, Physics::RagdollNodeConfiguration& nodeConfig);
~RagdollNode();
void SetJoint(const AZStd::shared_ptr<Physics::Joint>& joint);
@@ -58,9 +58,13 @@ namespace PhysX
AzPhysics::SimulatedBodyHandle GetRigidBodyHandle() const;
private:
void CreatePhysicsBody(AzPhysics::SceneHandle sceneHandle, Physics::RagdollNodeConfiguration& nodeConfig);
void DestroyPhysicsBody();
AZStd::shared_ptr<Physics::Joint> m_joint;
AzPhysics::RigidBody* m_rigidBody;
AzPhysics::SimulatedBodyHandle m_rigidBodyHandle = AzPhysics::InvalidSimulatedBodyHandle;
AzPhysics::SceneHandle m_sceneOwner = AzPhysics::InvalidSceneHandle;
PhysX::ActorData m_actorUserData;
};
} // namespace PhysX
@@ -412,7 +412,6 @@ namespace PhysX
AZ::TransformBus::EventResult(entityTranslation, GetEntityId(), &AZ::TransformBus::Events::GetWorldTranslation);
m_characterConfig->m_position = entityTranslation;
AZ_Assert(m_controller == nullptr, "Calling create CharacterControllerComponent::CreateController() with an already created controller.");
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
{
AzPhysics::SimulatedBodyHandle bodyHandle = sceneInterface->AddSimulatedBody(defaultSceneHandle, m_characterConfig.get());
@@ -451,8 +450,8 @@ namespace PhysX
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
{
sceneInterface->RemoveSimulatedBody(m_controller->m_sceneOwner, m_controller->m_bodyHandle);
m_controller = nullptr;
}
m_controller = nullptr;
m_preSimulateHandler.Disconnect();
@@ -55,6 +55,16 @@ namespace PhysX
}
}
if (classElement.GetVersion() < 3)
{
int ragdollElementIndex = classElement.FindElement(AZ_CRC_CE("PhysXRagdoll"));
if (ragdollElementIndex >= 0)
{
classElement.RemoveElement(ragdollElementIndex);
}
}
return true;
}
@@ -66,8 +76,7 @@ namespace PhysX
if (serializeContext)
{
serializeContext->Class<RagdollComponent, AZ::Component>()
->Version(2, &VersionConverter)
->Field("PhysXRagdoll", &RagdollComponent::m_ragdoll)
->Version(3, &VersionConverter)
->Field("PositionIterations", &RagdollComponent::m_positionIterations)
->Field("VelocityIterations", &RagdollComponent::m_velocityIterations)
->Field("EnableJointProjection", &RagdollComponent::m_enableJointProjection)
@@ -187,7 +196,7 @@ namespace PhysX
Physics::Ragdoll* RagdollComponent::GetRagdoll()
{
return m_ragdoll.get();
return m_ragdoll;
}
void RagdollComponent::GetState(Physics::RagdollState& ragdollState) const
@@ -250,7 +259,7 @@ namespace PhysX
AzPhysics::SimulatedBody* RagdollComponent::GetWorldBody()
{
return m_ragdoll.get();
return GetRagdoll();
}
AzPhysics::SceneQueryHit RagdollComponent::RayCast(const AzPhysics::RayCastRequest& request)
@@ -283,8 +292,8 @@ namespace PhysX
return;
}
ParentIndices parentIndices;
parentIndices.resize(numNodes);
ragdollConfiguration.m_parentIndices.resize(numNodes);
for (size_t nodeIndex = 0; nodeIndex < numNodes; nodeIndex++)
{
AZStd::string parentName;
@@ -292,7 +301,7 @@ namespace PhysX
AzFramework::CharacterPhysicsDataRequestBus::EventResult(parentName, GetEntityId(),
&AzFramework::CharacterPhysicsDataRequests::GetParentNodeName, nodeName);
AZ::Outcome<size_t> parentIndex = Utils::Characters::GetNodeIndex(ragdollConfiguration, parentName);
parentIndices[nodeIndex] = parentIndex ? parentIndex.GetValue() : SIZE_MAX;
ragdollConfiguration.m_parentIndices[nodeIndex] = parentIndex ? parentIndex.GetValue() : SIZE_MAX;
ragdollConfiguration.m_nodes[nodeIndex].m_entityId = GetEntityId();
}
@@ -303,12 +312,17 @@ namespace PhysX
AZ::Transform entityTransform = AZ::Transform::CreateIdentity();
AZ::TransformBus::EventResult(entityTransform, GetEntityId(), &AZ::TransformBus::Events::GetWorldTM);
Physics::RagdollState bindPoseWorld = GetBindPoseWorld(bindPose, entityTransform);
ragdollConfiguration.m_initialState = GetBindPoseWorld(bindPose, entityTransform);
AzPhysics::SceneHandle defaultSceneHandle = AzPhysics::InvalidSceneHandle;
Physics::DefaultWorldBus::BroadcastResult(defaultSceneHandle, &Physics::DefaultWorldRequests::GetDefaultSceneHandle);
m_ragdoll = Utils::Characters::CreateRagdoll(ragdollConfiguration, bindPoseWorld, parentIndices, defaultSceneHandle);
if (!m_ragdoll)
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
{
AzPhysics::SimulatedBodyHandle bodyHandle = sceneInterface->AddSimulatedBody(defaultSceneHandle, &ragdollConfiguration);
m_ragdoll = azdynamic_cast<PhysX::Ragdoll*>(sceneInterface->GetSimulatedBodyFromHandle(defaultSceneHandle, bodyHandle));
}
if (m_ragdoll == nullptr)
{
AZ_Error("PhysX Ragdoll Component", false, "Failed to create ragdoll.");
return;
@@ -358,7 +372,11 @@ namespace PhysX
AzFramework::RagdollPhysicsNotificationBus::Event(GetEntityId(),
&AzFramework::RagdollPhysicsNotifications::OnRagdollDeactivated);
m_ragdoll.reset();
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
{
sceneInterface->RemoveSimulatedBody(m_ragdoll->m_sceneOwner, m_ragdoll->m_bodyHandle);
}
m_ragdoll = nullptr;
}
}
@@ -32,7 +32,7 @@ namespace PhysX
, public AzFramework::CharacterPhysicsDataNotificationBus::Handler
{
public:
AZ_COMPONENT(RagdollComponent, "{B89498F8-4718-42FE-A457-A377DD0D61A0}");
AZ_COMPONENT(PhysX::RagdollComponent, "{B89498F8-4718-42FE-A457-A377DD0D61A0}");
static void Reflect(AZ::ReflectContext* context);
@@ -105,7 +105,7 @@ namespace PhysX
bool IsJointProjectionVisible();
AZStd::unique_ptr<Ragdoll> m_ragdoll;
Ragdoll* m_ragdoll;
/// Minimum number of position iterations to perform in the PhysX solver.
/// Lower iteration counts are less expensive but may behave less realistically.
AZ::u32 m_positionIterations = 16;
+30 -6
View File
@@ -209,6 +209,13 @@ namespace PhysX
return controller;
}
AzPhysics::SimulatedBody* CreateRagdollBody(PhysXScene* scene,
const Physics::RagdollConfiguration* ragdollConfig)
{
return Utils::Characters::CreateRagdoll(const_cast<Physics::RagdollConfiguration&>(*ragdollConfig),
scene->GetSceneHandle());
}
//helper to perform a ray cast
AzPhysics::SceneQueryHits RayCast(const AzPhysics::RayCastRequest* raycastRequest,
AZStd::vector<physx::PxRaycastHit>& raycastBuffer,
@@ -622,6 +629,15 @@ namespace PhysX
{
newBody = Internal::CreateCharacterBody(this, azdynamic_cast<const Physics::CharacterConfiguration*>(simulatedBodyConfig));
}
else if (azrtti_istypeof<Physics::RagdollConfiguration>(simulatedBodyConfig))
{
newBody = Internal::CreateRagdollBody(this, azdynamic_cast<const Physics::RagdollConfiguration*>(simulatedBodyConfig));
}
else
{
AZ_Warning("PhysXScene", false, "Unknown SimulatedBodyConfiguration.");
return AzPhysics::InvalidSimulatedBodyHandle;
}
if (newBody != nullptr)
{
@@ -648,8 +664,11 @@ namespace PhysX
newBody->m_bodyHandle = newBodyHandle;
m_simulatedBodyAddedEvent.Signal(m_sceneHandle, newBodyHandle);
// Enable simulation by default (not signaling OnSimulationBodySimulationEnabled event)
EnableSimulationOfBodyInternal(*newBody);
// Enable simulation by default (not signaling OnSimulationBodySimulationEnabled event)
if (simulatedBodyConfig->m_startSimulationEnabled)
{
EnableSimulationOfBodyInternal(*newBody);
}
return newBodyHandle;
}
@@ -878,7 +897,8 @@ namespace PhysX
void PhysXScene::EnableSimulationOfBodyInternal(AzPhysics::SimulatedBody& body)
{
//character controller is a special actor and only needs the m_simulating flag set,
if (!azrtti_istypeof<PhysX::CharacterController>(body))
if (!azrtti_istypeof<PhysX::CharacterController>(body) &&
!azrtti_istypeof<PhysX::Ragdoll>(body))
{
auto pxActor = static_cast<physx::PxActor*>(body.GetNativePointer());
AZ_Assert(pxActor, "Simulated Body doesn't have a valid physx actor");
@@ -904,7 +924,8 @@ namespace PhysX
void PhysXScene::DisableSimulationOfBodyInternal(AzPhysics::SimulatedBody& body)
{
//character controller is a special actor and only needs the m_simulating flag set,
if (!azrtti_istypeof<PhysX::CharacterController>(body))
if (!azrtti_istypeof<PhysX::CharacterController>(body) &&
!azrtti_istypeof<PhysX::Ragdoll>(body))
{
auto pxActor = static_cast<physx::PxActor*>(body.GetNativePointer());
AZ_Assert(pxActor, "Simulated Body doesn't have a valid physx actor");
@@ -948,11 +969,14 @@ namespace PhysX
void PhysXScene::ClearDeferedDeletions()
{
for (auto& simulatedBody : m_deferredDeletions)
// swap the deletions in case the simulated body
// manages more bodies and removes them on destruction (ie. Ragdoll).
AZStd::vector<AzPhysics::SimulatedBody*> deletions;
deletions.swap(m_deferredDeletions);
for (auto* simulatedBody : deletions)
{
delete simulatedBody;
}
m_deferredDeletions.clear();
}
void PhysXScene::ProcessTriggerEvents()
@@ -125,19 +125,24 @@ namespace PhysX::Benchmarks
return GetTPose(AZ::Vector3::CreateZero(), simulationType);
}
AZStd::unique_ptr<PhysX::Ragdoll> CreateRagdoll(AzPhysics::SceneHandle sceneHandle)
PhysX::Ragdoll* CreateRagdoll(AzPhysics::SceneHandle sceneHandle)
{
Physics::RagdollConfiguration* configuration =
AZ::Utils::LoadObjectFromFile<Physics::RagdollConfiguration>(AZ::Test::GetEngineRootPath() + "/Gems/PhysX/Code/Tests/RagdollConfiguration.xml");
Physics::RagdollState initialState = GetTPose();
PhysX::ParentIndices parentIndices;
configuration->m_initialState = GetTPose();
configuration->m_parentIndices.reserve(configuration->m_nodes.size());
for (int i = 0; i < configuration->m_nodes.size(); i++)
{
parentIndices.push_back(RagdollTestData::ParentIndices[i]);
configuration->m_parentIndices.push_back(RagdollTestData::ParentIndices[i]);
}
return PhysX::Utils::Characters::CreateRagdoll(*configuration, initialState, parentIndices, sceneHandle);
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
{
AzPhysics::SimulatedBodyHandle bodyHandle = sceneInterface->AddSimulatedBody(sceneHandle, configuration);
return azdynamic_cast<Ragdoll*>(sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, bodyHandle));
}
return nullptr;
}
//! BM_Ragdoll_AtRest - This test just spawns the requested number of ragdolls and places them near the terrain
@@ -148,7 +153,7 @@ namespace PhysX::Benchmarks
const int numRagdolls = static_cast<const int>(state.range(0));
//create ragdolls
AZStd::vector<AZStd::unique_ptr<PhysX::Ragdoll>> ragdolls;
AZStd::vector<PhysX::Ragdoll*> ragdolls;
ragdolls.reserve(numRagdolls);
for (int i = 0; i < numRagdolls; i++)
{
@@ -218,7 +223,7 @@ namespace PhysX::Benchmarks
washingMachineCentre, RagdollConstants::WashingMachine::BladeRPM);
//create ragdolls
AZStd::vector<AZStd::unique_ptr<PhysX::Ragdoll>> ragdolls;
AZStd::vector<PhysX::Ragdoll*> ragdolls;
ragdolls.reserve(numRagdolls);
for (int i = 0; i < numRagdolls; i++)
{
+11 -6
View File
@@ -37,7 +37,7 @@ namespace PhysX
<Class name="AZ::Component" field="BaseClass1" type="{EDFCB2CF-F75D-43BE-B26B-F35821B29247}">
<Class name="AZ::u64" field="Id" value="0" type="{D6597933-47CD-4FC8-B911-63F3E2B0993A}"/>
</Class>
<Class name="AZStd::shared_ptr" field="PhysXRagdoll" type="{A3E470C6-D6E0-5A32-9E83-96C379D9E7FA}"/>
<Class name="PhysX::Ragdoll" field="PhysXRagdoll" type="{55D477B5-B922-4D3E-89FE-7FB7B9FDD635}"/>
</Class>
</ObjectStream>)DELIMITER";
@@ -63,19 +63,24 @@ namespace PhysX
return ragdollState;
}
AZStd::unique_ptr<Ragdoll> CreateRagdoll(AzPhysics::SceneHandle sceneHandle)
Ragdoll* CreateRagdoll(AzPhysics::SceneHandle sceneHandle)
{
Physics::RagdollConfiguration* configuration =
AZ::Utils::LoadObjectFromFile<Physics::RagdollConfiguration>(AZ::Test::GetCurrentExecutablePath() + "/Test.Assets/Gems/PhysX/Code/Tests/RagdollConfiguration.xml");
Physics::RagdollState initialState = GetTPose();
ParentIndices parentIndices;
configuration->m_initialState = GetTPose();
configuration->m_parentIndices.reserve(configuration->m_nodes.size());
for (int i = 0; i < configuration->m_nodes.size(); i++)
{
parentIndices.push_back(RagdollTestData::ParentIndices[i]);
configuration->m_parentIndices.push_back(RagdollTestData::ParentIndices[i]);
}
return Utils::Characters::CreateRagdoll(*configuration, initialState, parentIndices, sceneHandle);
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
{
AzPhysics::SimulatedBodyHandle bodyHandle = sceneInterface->AddSimulatedBody(sceneHandle, configuration);
return azdynamic_cast<Ragdoll*>(sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, bodyHandle));
}
return nullptr;
}
#if AZ_TRAIT_DISABLE_FAILED_PHYSICS_TESTS
@@ -511,13 +511,13 @@ namespace PhysXDebug
void SystemComponent::RenderBuffers()
{
if (gEnv && !m_linePoints.empty())
if (gEnv && gEnv->pRenderer && !m_linePoints.empty())
{
AZ_Assert(m_linePoints.size() == m_lineColors.size(), "Lines: Expected an equal number of points to colors.");
gEnv->pRenderer->GetIRenderAuxGeom()->DrawLines(m_linePoints.begin(), m_linePoints.size(), m_lineColors.begin(), 1.0f);
}
if (gEnv && !m_trianglePoints.empty())
if (gEnv && gEnv->pRenderer && !m_trianglePoints.empty())
{
AZ_Assert(m_trianglePoints.size() == m_triangleColors.size(), "Triangles: Expected an equal number of points to colors.");
gEnv->pRenderer->GetIRenderAuxGeom()->DrawTriangles(m_trianglePoints.begin(), m_trianglePoints.size(), m_triangleColors.begin());
@@ -829,7 +829,7 @@ namespace PhysXDebug
{
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::Physics);
if (m_settings.m_visualizationEnabled && m_culling.m_boxWireframe)
if (gEnv && gEnv->pRenderer && m_settings.m_visualizationEnabled && m_culling.m_boxWireframe)
{
ColorB wireframeColor = MapOriginalPhysXColorToUserDefinedValues(1);
AABB lyAABB(AZAabbToLyAABB(cullingBoxAabb));