Merge pull request #192 from aws-lumberyard-dev/physx_character_create
Character controller now uses Add/Remove Simulated Body API
This commit is contained in:
@@ -28,7 +28,7 @@ namespace Physics
|
||||
class CharacterColliderNodeConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(CharacterColliderNodeConfiguration, "{C16F3301-0979-400C-B734-692D83755C39}");
|
||||
AZ_RTTI(Physics::CharacterColliderNodeConfiguration, "{C16F3301-0979-400C-B734-692D83755C39}");
|
||||
AZ_CLASS_ALLOCATOR_DECL
|
||||
|
||||
virtual ~CharacterColliderNodeConfiguration() = default;
|
||||
@@ -42,7 +42,7 @@ namespace Physics
|
||||
class CharacterColliderConfiguration
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(CharacterColliderConfiguration, "{4DFF1434-DF5B-4ED5-BE0F-D3E66F9B331A}");
|
||||
AZ_RTTI(Physics::CharacterColliderConfiguration, "{4DFF1434-DF5B-4ED5-BE0F-D3E66F9B331A}");
|
||||
AZ_CLASS_ALLOCATOR_DECL
|
||||
|
||||
virtual ~CharacterColliderConfiguration() = default;
|
||||
@@ -63,21 +63,23 @@ namespace Physics
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(CharacterConfiguration, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(CharacterConfiguration, "{58D5A6CA-113B-4AC3-8D53-239DB0C4E240}", AzPhysics::SimulatedBodyConfiguration);
|
||||
AZ_RTTI(Physics::CharacterConfiguration, "{58D5A6CA-113B-4AC3-8D53-239DB0C4E240}", AzPhysics::SimulatedBodyConfiguration);
|
||||
|
||||
virtual ~CharacterConfiguration() = default;
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
AzPhysics::CollisionGroups::Id m_collisionGroupId; ///< Which layers does this character collide with.
|
||||
AzPhysics::CollisionLayer m_collisionLayer; ///< Which collision layer is this character on.
|
||||
MaterialSelection m_materialSelection; ///< Material selected from library for the body associated with the character.
|
||||
AZ::Vector3 m_upDirection = AZ::Vector3::CreateAxisZ(); ///< Up direction for character orientation and step behavior.
|
||||
float m_maximumSlopeAngle = 30.0f; ///< The maximum slope on which the character can move, in degrees.
|
||||
float m_stepHeight = 0.5f; ///< Affects what size steps the character can climb.
|
||||
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.
|
||||
AzPhysics::CollisionGroups::Id m_collisionGroupId; //!< Which layers does this character collide with.
|
||||
AzPhysics::CollisionLayer m_collisionLayer; //!< Which collision layer is this character on.
|
||||
MaterialSelection m_materialSelection; //!< Material selected from library for the body associated with the character.
|
||||
AZ::Vector3 m_upDirection = AZ::Vector3::CreateAxisZ(); //!< Up direction for character orientation and step behavior.
|
||||
float m_maximumSlopeAngle = 30.0f; //!< The maximum slope on which the character can move, in degrees.
|
||||
float m_stepHeight = 0.5f; //!< Affects what size steps the character can climb.
|
||||
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::vector<AZStd::shared_ptr<Physics::Shape>> m_colliders; //!< The list of colliders to attach to the character controller.
|
||||
};
|
||||
|
||||
/// Basic implementation of common character-style needs as a WorldBody. Is not a full-functional ship-ready
|
||||
@@ -88,7 +90,7 @@ namespace Physics
|
||||
{
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(Character, AZ::SystemAllocator, 0);
|
||||
AZ_RTTI(Character, "{962E37A1-3401-4672-B896-0A6157CFAC97}", AzPhysics::SimulatedBody);
|
||||
AZ_RTTI(Physics::Character, "{962E37A1-3401-4672-B896-0A6157CFAC97}", AzPhysics::SimulatedBody);
|
||||
|
||||
~Character() override = default;
|
||||
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ namespace AzPhysics
|
||||
struct SimulatedBodyConfiguration
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
AZ_RTTI(SimulatedBodyConfiguration, "{52844E3D-79C8-4F34-AF63-5C45ADE77F85}");
|
||||
AZ_RTTI(AzPhysics::SimulatedBodyConfiguration, "{52844E3D-79C8-4F34-AF63-5C45ADE77F85}");
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
SimulatedBodyConfiguration() = default;
|
||||
|
||||
@@ -246,26 +246,6 @@ namespace Physics
|
||||
using SystemRequests = System;
|
||||
using SystemRequestBus = AZ::EBus<SystemRequests, SystemRequestsTraits>;
|
||||
|
||||
/// Physics character system global requests.
|
||||
class CharacterSystemRequests
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
// EBusTraits
|
||||
// singleton pattern
|
||||
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
|
||||
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
|
||||
|
||||
virtual ~CharacterSystemRequests() = default;
|
||||
|
||||
/// Creates the physics representation used to handle basic character interactions (also known as a character
|
||||
/// controller).
|
||||
virtual AZStd::unique_ptr<Character> CreateCharacter(const CharacterConfiguration& characterConfig,
|
||||
const ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle& sceneHandle) = 0;
|
||||
};
|
||||
|
||||
typedef AZ::EBus<CharacterSystemRequests> CharacterSystemRequestBus;
|
||||
|
||||
/// Physics system global debug requests.
|
||||
class SystemDebugRequests
|
||||
: public AZ::EBusTraits
|
||||
|
||||
@@ -311,7 +311,10 @@ namespace PhysX
|
||||
CreateShadowBody(configuration);
|
||||
SetTag(configuration.m_colliderTag);
|
||||
|
||||
m_simulating = true;
|
||||
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
|
||||
{
|
||||
sceneInterface->EnableSimulationOfBody(m_sceneOwner, m_bodyHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterController::DisablePhysics()
|
||||
@@ -323,7 +326,11 @@ namespace PhysX
|
||||
|
||||
DestroyShadowBody();
|
||||
RemoveControllerFromScene();
|
||||
m_simulating = false;
|
||||
|
||||
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
|
||||
{
|
||||
sceneInterface->DisableSimulationOfBody(m_sceneOwner, m_bodyHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void CharacterController::DestroyShadowBody()
|
||||
|
||||
@@ -96,25 +96,17 @@ namespace PhysX
|
||||
}
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<CharacterController> CreateCharacterController(const Physics::CharacterConfiguration& characterConfig,
|
||||
const Physics::ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle sceneHandle)
|
||||
CharacterController* CreateCharacterController(PhysXScene* scene,
|
||||
const Physics::CharacterConfiguration& characterConfig)
|
||||
{
|
||||
physx::PxControllerManager* manager = nullptr;
|
||||
AzPhysics::Scene* scene = nullptr;
|
||||
PhysX::PhysXScene* physxScene = nullptr;
|
||||
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
|
||||
if (scene == nullptr)
|
||||
{
|
||||
scene = physicsSystem->GetScene(sceneHandle);
|
||||
if (scene)
|
||||
{
|
||||
physxScene = azrtti_cast<PhysX::PhysXScene*>(scene);
|
||||
if (physxScene)
|
||||
{
|
||||
manager = physxScene->GetOrCreateControllerManager();
|
||||
}
|
||||
}
|
||||
AZ_Error("PhysX Character Controller", false, "Failed to create character controller as the scene is null");
|
||||
return nullptr;
|
||||
}
|
||||
if (!manager || !scene)
|
||||
|
||||
physx::PxControllerManager* manager = scene->GetOrCreateControllerManager();
|
||||
if (manager == nullptr)
|
||||
{
|
||||
AZ_Error("PhysX Character Controller", false, "Could not retrieve character controller manager.");
|
||||
return nullptr;
|
||||
@@ -123,41 +115,47 @@ namespace PhysX
|
||||
auto callbackManager = AZStd::make_unique<CharacterControllerCallbackManager>();
|
||||
|
||||
physx::PxController* pxController = nullptr;
|
||||
auto* pxScene = static_cast<physx::PxScene*>(physxScene->GetNativePointer());
|
||||
auto* pxScene = static_cast<physx::PxScene*>(scene->GetNativePointer());
|
||||
|
||||
if (shapeConfig.GetShapeType() == Physics::ShapeType::Capsule)
|
||||
switch (characterConfig.m_shapeConfig->GetShapeType())
|
||||
{
|
||||
physx::PxCapsuleControllerDesc capsuleDesc;
|
||||
case Physics::ShapeType::Capsule:
|
||||
{
|
||||
physx::PxCapsuleControllerDesc capsuleDesc;
|
||||
|
||||
const Physics::CapsuleShapeConfiguration& capsuleConfig = static_cast<const Physics::CapsuleShapeConfiguration&>(shapeConfig);
|
||||
// LY height means total height, PhysX means height of straight section
|
||||
capsuleDesc.height = AZ::GetMax(epsilon, capsuleConfig.m_height - 2.0f * capsuleConfig.m_radius);
|
||||
capsuleDesc.radius = capsuleConfig.m_radius;
|
||||
capsuleDesc.climbingMode = physx::PxCapsuleClimbingMode::eCONSTRAINED;
|
||||
const Physics::CapsuleShapeConfiguration& capsuleConfig = static_cast<const Physics::CapsuleShapeConfiguration&>(*characterConfig.m_shapeConfig);
|
||||
// LY height means total height, PhysX means height of straight section
|
||||
capsuleDesc.height = AZ::GetMax(epsilon, capsuleConfig.m_height - 2.0f * capsuleConfig.m_radius);
|
||||
capsuleDesc.radius = capsuleConfig.m_radius;
|
||||
capsuleDesc.climbingMode = physx::PxCapsuleClimbingMode::eCONSTRAINED;
|
||||
|
||||
AppendShapeIndependentProperties(capsuleDesc, characterConfig, callbackManager.get());
|
||||
AppendPhysXSpecificProperties(capsuleDesc, characterConfig);
|
||||
PHYSX_SCENE_WRITE_LOCK(pxScene);
|
||||
pxController = manager->createController(capsuleDesc); // This internally adds the controller's actor to the scene
|
||||
}
|
||||
else if (shapeConfig.GetShapeType() == Physics::ShapeType::Box)
|
||||
{
|
||||
physx::PxBoxControllerDesc boxDesc;
|
||||
AppendShapeIndependentProperties(capsuleDesc, characterConfig, callbackManager.get());
|
||||
AppendPhysXSpecificProperties(capsuleDesc, characterConfig);
|
||||
PHYSX_SCENE_WRITE_LOCK(pxScene);
|
||||
pxController = manager->createController(capsuleDesc); // This internally adds the controller's actor to the scene
|
||||
}
|
||||
break;
|
||||
case Physics::ShapeType::Box:
|
||||
{
|
||||
physx::PxBoxControllerDesc boxDesc;
|
||||
|
||||
const Physics::BoxShapeConfiguration& boxConfig = static_cast<const Physics::BoxShapeConfiguration&>(shapeConfig);
|
||||
boxDesc.halfHeight = 0.5f * boxConfig.m_dimensions.GetZ();
|
||||
boxDesc.halfSideExtent = 0.5f * boxConfig.m_dimensions.GetY();
|
||||
boxDesc.halfForwardExtent = 0.5f * boxConfig.m_dimensions.GetX();
|
||||
const Physics::BoxShapeConfiguration& boxConfig = static_cast<const Physics::BoxShapeConfiguration&>(*characterConfig.m_shapeConfig);
|
||||
boxDesc.halfHeight = 0.5f * boxConfig.m_dimensions.GetZ();
|
||||
boxDesc.halfSideExtent = 0.5f * boxConfig.m_dimensions.GetY();
|
||||
boxDesc.halfForwardExtent = 0.5f * boxConfig.m_dimensions.GetX();
|
||||
|
||||
AppendShapeIndependentProperties(boxDesc, characterConfig, callbackManager.get());
|
||||
AppendPhysXSpecificProperties(boxDesc, characterConfig);
|
||||
PHYSX_SCENE_WRITE_LOCK(pxScene);
|
||||
pxController = manager->createController(boxDesc); // This internally adds the controller's actor to the scene
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Error("PhysX Character Controller", false, "PhysX only supports box and capsule shapes for character controllers.");
|
||||
return nullptr;
|
||||
AppendShapeIndependentProperties(boxDesc, characterConfig, callbackManager.get());
|
||||
AppendPhysXSpecificProperties(boxDesc, characterConfig);
|
||||
PHYSX_SCENE_WRITE_LOCK(pxScene);
|
||||
pxController = manager->createController(boxDesc); // This internally adds the controller's actor to the scene
|
||||
}
|
||||
break;
|
||||
default:
|
||||
{
|
||||
AZ_Error("PhysX Character Controller", false, "PhysX only supports box and capsule shapes for character controllers.");
|
||||
return nullptr;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (!pxController)
|
||||
@@ -166,8 +164,7 @@ namespace PhysX
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
auto controller = AZStd::make_unique<CharacterController>(pxController, AZStd::move(callbackManager), sceneHandle);
|
||||
return controller;
|
||||
return aznew CharacterController(pxController, AZStd::move(callbackManager), scene->GetSceneHandle());
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<Ragdoll> CreateRagdoll(Physics::RagdollConfiguration& configuration,
|
||||
|
||||
@@ -25,6 +25,7 @@ namespace Physics
|
||||
namespace PhysX
|
||||
{
|
||||
class CharacterController;
|
||||
class PhysXScene;
|
||||
|
||||
namespace Utils
|
||||
{
|
||||
@@ -33,10 +34,9 @@ namespace PhysX
|
||||
AZ::Outcome<size_t> GetNodeIndex(const Physics::RagdollConfiguration& configuration, const AZStd::string& nodeName);
|
||||
|
||||
//! Creates a character controller based on the supplied configuration in the specified world.
|
||||
//! @param configuration Information required to create the controller such as shape, slope behavior etc.
|
||||
//! @param sceneHandle A handle to the physics scene in which the character controller should be created.
|
||||
AZStd::unique_ptr<CharacterController> CreateCharacterController(const Physics::CharacterConfiguration&
|
||||
characterConfig, const Physics::ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle sceneHandle);
|
||||
//! @param scene The scene to add the character controller to.
|
||||
//! @param characterConfig Information required to create the controller such as shape, slope behavior etc.
|
||||
CharacterController* CreateCharacterController(PhysXScene* scene, const Physics::CharacterConfiguration& characterConfig);
|
||||
|
||||
//! 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.
|
||||
|
||||
+30
-37
@@ -67,7 +67,7 @@ namespace PhysX
|
||||
CharacterControllerComponent::CharacterControllerComponent() = default;
|
||||
|
||||
CharacterControllerComponent::CharacterControllerComponent(AZStd::unique_ptr<Physics::CharacterConfiguration> characterConfig,
|
||||
AZStd::unique_ptr<Physics::ShapeConfiguration> shapeConfig)
|
||||
AZStd::shared_ptr<Physics::ShapeConfiguration> shapeConfig)
|
||||
: m_characterConfig(AZStd::move(characterConfig))
|
||||
, m_shapeConfig(AZStd::move(shapeConfig))
|
||||
{
|
||||
@@ -188,7 +188,7 @@ namespace PhysX
|
||||
|
||||
Physics::Character* CharacterControllerComponent::GetCharacter()
|
||||
{
|
||||
return m_controller.get();
|
||||
return m_controller;
|
||||
}
|
||||
|
||||
void CharacterControllerComponent::EnablePhysics()
|
||||
@@ -217,7 +217,7 @@ namespace PhysX
|
||||
|
||||
AzPhysics::SimulatedBody* CharacterControllerComponent::GetWorldBody()
|
||||
{
|
||||
return m_controller.get();
|
||||
return GetCharacter();
|
||||
}
|
||||
|
||||
AzPhysics::SceneQueryHit CharacterControllerComponent::RayCast(const AzPhysics::RayCastRequest& request)
|
||||
@@ -382,7 +382,7 @@ namespace PhysX
|
||||
|
||||
void CharacterControllerComponent::CreateController()
|
||||
{
|
||||
if (m_controller)
|
||||
if (IsPhysicsEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -397,22 +397,33 @@ namespace PhysX
|
||||
|
||||
m_characterConfig->m_debugName = GetEntity()->GetName();
|
||||
m_characterConfig->m_entityId = GetEntityId();
|
||||
m_characterConfig->m_shapeConfig = m_shapeConfig;
|
||||
// get all the collider shapes and add it to the config
|
||||
PhysX::ColliderComponentRequestBus::EnumerateHandlersId(GetEntityId(), [this](PhysX::ColliderComponentRequests* handler)
|
||||
{
|
||||
auto shapes = handler->GetShapes();
|
||||
m_characterConfig->m_colliders.insert(m_characterConfig->m_colliders.end(), shapes.begin(), shapes.end());
|
||||
return true;
|
||||
});
|
||||
|
||||
m_controller = Utils::Characters::CreateCharacterController(*m_characterConfig, *m_shapeConfig, defaultSceneHandle);
|
||||
if (!m_controller)
|
||||
// It's usually more convenient to control the foot position rather than the centre of the capsule, so
|
||||
// make the foot position coincide with the entity position.
|
||||
AZ::Vector3 entityTranslation = AZ::Vector3::CreateZero();
|
||||
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());
|
||||
m_controller = azdynamic_cast<PhysX::CharacterController*>(sceneInterface->GetSimulatedBodyFromHandle(defaultSceneHandle, bodyHandle));
|
||||
}
|
||||
if (m_controller == nullptr)
|
||||
{
|
||||
AZ_Error("PhysX Character Controller Component", false, "Failed to create character controller.");
|
||||
return;
|
||||
}
|
||||
m_controller->EnablePhysics(*m_characterConfig);
|
||||
|
||||
AZ::Vector3 entityTranslation = AZ::Vector3::CreateZero();
|
||||
AZ::TransformBus::EventResult(entityTranslation, GetEntityId(), &AZ::TransformBus::Events::GetWorldTranslation);
|
||||
// It's usually more convenient to control the foot position rather than the centre of the capsule, so
|
||||
// make the foot position coincide with the entity position.
|
||||
m_controller->SetBasePosition(entityTranslation);
|
||||
AttachColliders(*m_controller);
|
||||
|
||||
|
||||
CharacterControllerRequestBus::Handler::BusConnect(GetEntityId());
|
||||
|
||||
m_preSimulateHandler = AzPhysics::SystemEvents::OnPresimulateEvent::Handler(
|
||||
@@ -426,26 +437,21 @@ namespace PhysX
|
||||
{
|
||||
physXSystem->RegisterPreSimulateEvent(m_preSimulateHandler);
|
||||
}
|
||||
|
||||
Physics::WorldBodyNotificationBus::Event(GetEntityId(), &Physics::WorldBodyNotifications::OnPhysicsEnabled);
|
||||
}
|
||||
|
||||
void CharacterControllerComponent::DestroyController()
|
||||
{
|
||||
if (!m_controller)
|
||||
if (!IsPhysicsEnabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
m_controller->DisablePhysics();
|
||||
|
||||
// The character is first removed from the scene, and then its deletion is deferred.
|
||||
// This ensures trigger exit events are raised correctly on deleted objects.
|
||||
if (auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get())
|
||||
{
|
||||
auto* scene = azdynamic_cast<PhysX::PhysXScene*>(m_controller->GetScene());
|
||||
AZ_Assert(scene, "Invalid PhysX scene");
|
||||
scene->DeferDelete(AZStd::move(m_controller));
|
||||
m_controller.reset();
|
||||
sceneInterface->RemoveSimulatedBody(m_controller->m_sceneOwner, m_controller->m_bodyHandle);
|
||||
m_controller = nullptr;
|
||||
}
|
||||
|
||||
m_preSimulateHandler.Disconnect();
|
||||
@@ -454,17 +460,4 @@ namespace PhysX
|
||||
|
||||
Physics::WorldBodyNotificationBus::Event(GetEntityId(), &Physics::WorldBodyNotifications::OnPhysicsDisabled);
|
||||
}
|
||||
|
||||
void CharacterControllerComponent::AttachColliders(Physics::Character& character)
|
||||
{
|
||||
PhysX::ColliderComponentRequestBus::EnumerateHandlersId(GetEntityId(), [&character](PhysX::ColliderComponentRequests* handler)
|
||||
{
|
||||
for (auto& shape : handler->GetShapes())
|
||||
{
|
||||
character.AttachShape(shape);
|
||||
}
|
||||
return true;
|
||||
});
|
||||
}
|
||||
|
||||
} // namespace PhysX
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace PhysX
|
||||
|
||||
CharacterControllerComponent();
|
||||
CharacterControllerComponent(AZStd::unique_ptr<Physics::CharacterConfiguration> characterConfig,
|
||||
AZStd::unique_ptr<Physics::ShapeConfiguration> shapeConfig);
|
||||
AZStd::shared_ptr<Physics::ShapeConfiguration> shapeConfig);
|
||||
~CharacterControllerComponent();
|
||||
|
||||
static void GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
@@ -131,12 +131,12 @@ namespace PhysX
|
||||
private:
|
||||
void CreateController();
|
||||
void DestroyController();
|
||||
void AttachColliders(Physics::Character& character);
|
||||
|
||||
void OnPreSimulate(float deltaTime);
|
||||
|
||||
AZStd::unique_ptr<Physics::CharacterConfiguration> m_characterConfig;
|
||||
AZStd::unique_ptr<Physics::ShapeConfiguration> m_shapeConfig;
|
||||
AZStd::unique_ptr<PhysX::CharacterController> m_controller;
|
||||
AZStd::shared_ptr<Physics::ShapeConfiguration> m_shapeConfig;
|
||||
PhysX::CharacterController* m_controller = nullptr;
|
||||
AzPhysics::SystemEvents::OnPresimulateEvent::Handler m_preSimulateHandler;
|
||||
};
|
||||
} // namespace PhysX
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
#include <AzCore/Debug/ProfilerBus.h>
|
||||
#include <AzCore/std/containers/variant.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzFramework/Physics/Character.h>
|
||||
#include <AzFramework/Physics/Collision/CollisionEvents.h>
|
||||
#include <AzFramework/Physics/Configuration/RigidBodyConfiguration.h>
|
||||
#include <AzFramework/Physics/Configuration/StaticRigidBodyConfiguration.h>
|
||||
@@ -27,6 +28,8 @@
|
||||
#include <Common/PhysXSceneQueryHelpers.h>
|
||||
#include <PhysX/PhysXLocks.h>
|
||||
#include <PhysX/Utils.h>
|
||||
#include <PhysXCharacters/API/CharacterController.h>
|
||||
#include <PhysXCharacters/API/CharacterUtils.h>
|
||||
#include <System/PhysXSystem.h>
|
||||
|
||||
namespace PhysX
|
||||
@@ -186,6 +189,26 @@ namespace PhysX
|
||||
return newBody;
|
||||
}
|
||||
|
||||
AzPhysics::SimulatedBody* CreateCharacterBody(PhysXScene* scene,
|
||||
const Physics::CharacterConfiguration* characterConfig)
|
||||
{
|
||||
CharacterController* controller = Utils::Characters::CreateCharacterController(scene, *characterConfig);
|
||||
if (controller == nullptr)
|
||||
{
|
||||
AZ_Error("PhysXScene", false, "Failed to create character controller.");
|
||||
return nullptr;
|
||||
}
|
||||
controller->EnablePhysics(*characterConfig);
|
||||
controller->SetBasePosition(characterConfig->m_position);
|
||||
|
||||
for (auto shape : characterConfig->m_colliders)
|
||||
{
|
||||
controller->AttachShape(shape);
|
||||
}
|
||||
|
||||
return controller;
|
||||
}
|
||||
|
||||
//helper to perform a ray cast
|
||||
AzPhysics::SceneQueryHits RayCast(const AzPhysics::RayCastRequest* raycastRequest,
|
||||
AZStd::vector<physx::PxRaycastHit>& raycastBuffer,
|
||||
@@ -595,6 +618,10 @@ namespace PhysX
|
||||
newBody = Internal::CreateSimulatedBody<StaticRigidBody, AzPhysics::StaticRigidBodyConfiguration>(
|
||||
azdynamic_cast<const AzPhysics::StaticRigidBodyConfiguration*>(simulatedBodyConfig), newBodyCrc);
|
||||
}
|
||||
else if (azrtti_istypeof<Physics::CharacterConfiguration>(simulatedBodyConfig))
|
||||
{
|
||||
newBody = Internal::CreateCharacterBody(this, azdynamic_cast<const Physics::CharacterConfiguration*>(simulatedBodyConfig));
|
||||
}
|
||||
|
||||
if (newBody != nullptr)
|
||||
{
|
||||
@@ -850,20 +877,24 @@ namespace PhysX
|
||||
|
||||
void PhysXScene::EnableSimulationOfBodyInternal(AzPhysics::SimulatedBody& body)
|
||||
{
|
||||
auto pxActor = static_cast<physx::PxActor*>(body.GetNativePointer());
|
||||
AZ_Assert(pxActor, "Simulated Body doesn't have a valid physx actor");
|
||||
|
||||
//character controller is a special actor and only needs the m_simulating flag set,
|
||||
if (!azrtti_istypeof<PhysX::CharacterController>(body))
|
||||
{
|
||||
PHYSX_SCENE_WRITE_LOCK(m_pxScene);
|
||||
m_pxScene->addActor(*pxActor);
|
||||
}
|
||||
auto pxActor = static_cast<physx::PxActor*>(body.GetNativePointer());
|
||||
AZ_Assert(pxActor, "Simulated Body doesn't have a valid physx actor");
|
||||
|
||||
if (azrtti_istypeof<PhysX::RigidBody>(body))
|
||||
{
|
||||
auto rigidBody = azdynamic_cast<PhysX::RigidBody*>(&body);
|
||||
if (rigidBody->ShouldStartAsleep())
|
||||
{
|
||||
rigidBody->ForceAsleep();
|
||||
PHYSX_SCENE_WRITE_LOCK(m_pxScene);
|
||||
m_pxScene->addActor(*pxActor);
|
||||
}
|
||||
|
||||
if (azrtti_istypeof<PhysX::RigidBody>(body))
|
||||
{
|
||||
auto rigidBody = azdynamic_cast<PhysX::RigidBody*>(&body);
|
||||
if (rigidBody->ShouldStartAsleep())
|
||||
{
|
||||
rigidBody->ForceAsleep();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -872,14 +903,17 @@ namespace PhysX
|
||||
|
||||
void PhysXScene::DisableSimulationOfBodyInternal(AzPhysics::SimulatedBody& body)
|
||||
{
|
||||
auto pxActor = static_cast<physx::PxActor*>(body.GetNativePointer());
|
||||
AZ_Assert(pxActor, "Simulated Body doesn't have a valid physx actor");
|
||||
|
||||
//character controller is a special actor and only needs the m_simulating flag set,
|
||||
if (!azrtti_istypeof<PhysX::CharacterController>(body))
|
||||
{
|
||||
PHYSX_SCENE_WRITE_LOCK(m_pxScene);
|
||||
m_pxScene->removeActor(*pxActor);
|
||||
}
|
||||
auto pxActor = static_cast<physx::PxActor*>(body.GetNativePointer());
|
||||
AZ_Assert(pxActor, "Simulated Body doesn't have a valid physx actor");
|
||||
|
||||
{
|
||||
PHYSX_SCENE_WRITE_LOCK(m_pxScene);
|
||||
m_pxScene->removeActor(*pxActor);
|
||||
}
|
||||
}
|
||||
body.m_simulating = false;
|
||||
}
|
||||
|
||||
@@ -907,11 +941,6 @@ namespace PhysX
|
||||
return m_controllerManager;
|
||||
}
|
||||
|
||||
void PhysXScene::DeferDelete(AZStd::unique_ptr<AzPhysics::SimulatedBody> worldBody)
|
||||
{
|
||||
m_deferredDeletions_uniquePtrs.push_back(AZStd::move(worldBody));
|
||||
}
|
||||
|
||||
void* PhysXScene::GetNativePointer() const
|
||||
{
|
||||
return m_pxScene;
|
||||
@@ -924,7 +953,6 @@ namespace PhysX
|
||||
delete simulatedBody;
|
||||
}
|
||||
m_deferredDeletions.clear();
|
||||
m_deferredDeletions_uniquePtrs.clear();
|
||||
}
|
||||
|
||||
void PhysXScene::ProcessTriggerEvents()
|
||||
|
||||
@@ -73,7 +73,6 @@ namespace PhysX
|
||||
void* GetNativePointer() const override;
|
||||
|
||||
physx::PxControllerManager* GetOrCreateControllerManager();
|
||||
void DeferDelete(AZStd::unique_ptr<AzPhysics::SimulatedBody> worldBody);
|
||||
|
||||
private:
|
||||
void EnableSimulationOfBodyInternal(AzPhysics::SimulatedBody& body);
|
||||
@@ -93,7 +92,6 @@ namespace PhysX
|
||||
|
||||
AZStd::vector<AZStd::pair<AZ::Crc32, AzPhysics::SimulatedBody*>> m_simulatedBodies; //this will become a SimulatedBody with LYN-1334
|
||||
AZStd::vector<AzPhysics::SimulatedBody*> m_deferredDeletions;
|
||||
AZStd::vector<AZStd::unique_ptr<AzPhysics::SimulatedBody>> m_deferredDeletions_uniquePtrs; // this is to support Character as it stores itself in a unique pointer currently.
|
||||
AZStd::queue<AzPhysics::SimulatedBodyIndex> m_freeSceneSlots;
|
||||
|
||||
AzPhysics::SystemEvents::OnConfigurationChangedEvent::Handler m_physicsSystemConfigChanged;
|
||||
|
||||
@@ -211,7 +211,6 @@ namespace PhysX
|
||||
Physics::SystemRequestBus::Handler::BusConnect();
|
||||
PhysX::SystemRequestsBus::Handler::BusConnect();
|
||||
Physics::CollisionRequestBus::Handler::BusConnect();
|
||||
Physics::CharacterSystemRequestBus::Handler::BusConnect();
|
||||
|
||||
ActivatePhysXSystem();
|
||||
}
|
||||
@@ -219,7 +218,6 @@ namespace PhysX
|
||||
void SystemComponent::Deactivate()
|
||||
{
|
||||
AZ::TickBus::Handler::BusDisconnect();
|
||||
Physics::CharacterSystemRequestBus::Handler::BusDisconnect();
|
||||
Physics::CollisionRequestBus::Handler::BusDisconnect();
|
||||
PhysX::SystemRequestsBus::Handler::BusDisconnect();
|
||||
Physics::SystemRequestBus::Handler::BusDisconnect();
|
||||
@@ -421,13 +419,6 @@ namespace PhysX
|
||||
}
|
||||
}
|
||||
|
||||
// Physics::CharacterSystemRequestBus
|
||||
AZStd::unique_ptr<Physics::Character> SystemComponent::CreateCharacter(const Physics::CharacterConfiguration&
|
||||
characterConfig, const Physics::ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle& sceneHandle)
|
||||
{
|
||||
return Utils::Characters::CreateCharacterController(characterConfig, shapeConfig, sceneHandle);
|
||||
}
|
||||
|
||||
AzPhysics::CollisionLayer SystemComponent::GetCollisionLayerByName(const AZStd::string& layerName)
|
||||
{
|
||||
return m_physXSystem->GetPhysXConfiguration().m_collisionConfig.m_collisionLayers.GetLayer(layerName);
|
||||
|
||||
@@ -57,7 +57,6 @@ namespace PhysX
|
||||
: public AZ::Component
|
||||
, public Physics::SystemRequestBus::Handler
|
||||
, public PhysX::SystemRequestsBus::Handler
|
||||
, public Physics::CharacterSystemRequestBus::Handler
|
||||
, private Physics::CollisionRequestBus::Handler
|
||||
, private AZ::TickBus::Handler
|
||||
{
|
||||
@@ -96,10 +95,6 @@ namespace PhysX
|
||||
physx::PxFilterData CreateFilterData(const AzPhysics::CollisionLayer& layer, const AzPhysics::CollisionGroup& group) override;
|
||||
physx::PxCooking* GetCooking() override;
|
||||
|
||||
// Physics::CharacterSystemRequestBus
|
||||
virtual AZStd::unique_ptr<Physics::Character> CreateCharacter(const Physics::CharacterConfiguration& characterConfig,
|
||||
const Physics::ShapeConfiguration& shapeConfig, AzPhysics::SceneHandle& sceneHandle) override;
|
||||
|
||||
// CollisionRequestBus
|
||||
AzPhysics::CollisionLayer GetCollisionLayerByName(const AZStd::string& layerName) override;
|
||||
AZStd::string GetCollisionLayerName(const AzPhysics::CollisionLayer& layer) override;
|
||||
|
||||
@@ -130,7 +130,9 @@ namespace PhysX::Benchmarks
|
||||
//! @param colliderType, the collider type to use
|
||||
//! @param scene, the scene to spawn the characters controller into
|
||||
//! @param genSpawnPosFuncPtr - [optional] function pointer to allow caller to pick the spawn position
|
||||
AZStd::vector<AZStd::unique_ptr<Physics::Character>> CreateCharacterControllers(int numCharacterControllers, CharacterConstants::CharacterSettings::ColliderType colliderType,
|
||||
AZStd::vector<Physics::Character*> CreateCharacterControllers(
|
||||
int numCharacterControllers,
|
||||
CharacterConstants::CharacterSettings::ColliderType colliderType,
|
||||
AzPhysics::SceneHandle& sceneHandle,
|
||||
GenerateSpawnPositionFuncPtr* genSpawnPosFuncPtr = nullptr)
|
||||
{
|
||||
@@ -139,12 +141,11 @@ namespace PhysX::Benchmarks
|
||||
characterConfig.m_maximumSlopeAngle = CharacterConstants::CharacterSettings::MaximumSlopeAngle;
|
||||
characterConfig.m_stepHeight = CharacterConstants::CharacterSettings::StepHeight;
|
||||
|
||||
Physics::ShapeConfiguration* shapeConfig = nullptr;
|
||||
switch (colliderType)
|
||||
{
|
||||
case CharacterConstants::CharacterSettings::ColliderType::Box:
|
||||
{
|
||||
shapeConfig = new Physics::BoxShapeConfiguration(
|
||||
characterConfig.m_shapeConfig = AZStd::make_shared<Physics::BoxShapeConfiguration>(
|
||||
AZ::Vector3(CharacterConstants::CharacterSettings::CharacterBoxWidth,
|
||||
CharacterConstants::CharacterSettings::CharacterBoxDepth,
|
||||
CharacterConstants::CharacterSettings::CharacterBoxHeight)
|
||||
@@ -155,26 +156,32 @@ namespace PhysX::Benchmarks
|
||||
case CharacterConstants::CharacterSettings::ColliderType::Capsule:
|
||||
default:
|
||||
{
|
||||
shapeConfig = new Physics::CapsuleShapeConfiguration(CharacterConstants::CharacterSettings::CharacterCylinderHeight,
|
||||
characterConfig.m_shapeConfig = AZStd::make_shared<Physics::CapsuleShapeConfiguration>(
|
||||
CharacterConstants::CharacterSettings::CharacterCylinderHeight,
|
||||
CharacterConstants::CharacterSettings::CharacterCylinderRadius);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
AZStd::vector<AZStd::unique_ptr<Physics::Character>> controllers;
|
||||
auto* sceneInterface = AZ::Interface<AzPhysics::SceneInterface>::Get();
|
||||
|
||||
AZStd::vector<Physics::Character*> controllers;
|
||||
controllers.reserve(numCharacterControllers);
|
||||
for (int i = 0; i < numCharacterControllers; i++)
|
||||
{
|
||||
AZStd::unique_ptr<Physics::Character> controller;
|
||||
Physics::CharacterSystemRequestBus::BroadcastResult(controller,
|
||||
&Physics::CharacterSystemRequests::CreateCharacter, characterConfig, *shapeConfig, sceneHandle);
|
||||
|
||||
const AZ::Vector3 spawnPosition = genSpawnPosFuncPtr != nullptr ? (*genSpawnPosFuncPtr)(i) : AZ::Vector3::CreateZero();
|
||||
controller->SetBasePosition(spawnPosition);
|
||||
|
||||
controllers.emplace_back(AZStd::move(controller));
|
||||
const AZ::Vector3 spawnPosition = genSpawnPosFuncPtr != nullptr ? (*genSpawnPosFuncPtr)(i) : AZ::Vector3::CreateZero();
|
||||
characterConfig.m_position = spawnPosition;
|
||||
AzPhysics::SimulatedBodyHandle newHandle = sceneInterface->AddSimulatedBody(sceneHandle, &characterConfig);
|
||||
if (newHandle != AzPhysics::InvalidSimulatedBodyHandle)
|
||||
{
|
||||
if (auto* characterPtr = azdynamic_cast<Physics::Character*>(
|
||||
sceneInterface->GetSimulatedBodyFromHandle(sceneHandle, newHandle)
|
||||
))
|
||||
{
|
||||
controllers.emplace_back(characterPtr);
|
||||
}
|
||||
}
|
||||
}
|
||||
delete shapeConfig;
|
||||
|
||||
return controllers;
|
||||
}
|
||||
@@ -206,7 +213,7 @@ namespace PhysX::Benchmarks
|
||||
}
|
||||
return AZ::Vector3(x, y, z);
|
||||
};
|
||||
AZStd::vector<AZStd::unique_ptr<Physics::Character>> controllers = Utils::CreateCharacterControllers(numCharacters,
|
||||
AZStd::vector<Physics::Character*> controllers = Utils::CreateCharacterControllers(numCharacters,
|
||||
static_cast<CharacterConstants::CharacterSettings::ColliderType>(state.range(1)), m_testSceneHandle, &posGenerator);
|
||||
|
||||
//setup the sub tick tracker
|
||||
@@ -262,7 +269,7 @@ namespace PhysX::Benchmarks
|
||||
}
|
||||
return AZ::Vector3(x, y, z);
|
||||
};
|
||||
AZStd::vector<AZStd::unique_ptr<Physics::Character>> controllers = Utils::CreateCharacterControllers(numCharacters,
|
||||
AZStd::vector<Physics::Character*> controllers = Utils::CreateCharacterControllers(numCharacters,
|
||||
static_cast<CharacterConstants::CharacterSettings::ColliderType>(state.range(1)), m_testSceneHandle, &posGenerator);
|
||||
|
||||
//setup the sub tick tracker
|
||||
@@ -320,15 +327,15 @@ namespace PhysX::Benchmarks
|
||||
const float z = 0.0f;
|
||||
return AZ::Vector3(x, y, z);
|
||||
};
|
||||
AZStd::vector<AZStd::unique_ptr<Physics::Character>> controllers = Utils::CreateCharacterControllers(numCharacters,
|
||||
AZStd::vector<Physics::Character*> controllers = Utils::CreateCharacterControllers(numCharacters,
|
||||
static_cast<CharacterConstants::CharacterSettings::ColliderType>(state.range(1)), m_testSceneHandle, &posGenerator);
|
||||
|
||||
//pair up each character controller with a movement vector
|
||||
using ControllerAndMovementDirPair = AZStd::pair<AZStd::unique_ptr<Physics::Character>, AZ::Vector3>;
|
||||
using ControllerAndMovementDirPair = AZStd::pair<Physics::Character*, AZ::Vector3>;
|
||||
AZStd::vector<ControllerAndMovementDirPair> targetMoveAndControllers;
|
||||
for (auto& controller : controllers)
|
||||
{
|
||||
targetMoveAndControllers.emplace_back(ControllerAndMovementDirPair(AZStd::move(controller), AZ::Vector3::CreateZero()));
|
||||
targetMoveAndControllers.emplace_back(ControllerAndMovementDirPair(controller, AZ::Vector3::CreateZero()));
|
||||
}
|
||||
|
||||
//setup the sub tick tracker
|
||||
|
||||
Reference in New Issue
Block a user