/* * Copyright (c) Contributors to the Open 3D Engine Project. * For complete copyright and license terms please see the LICENSE at the root of this distribution. * * SPDX-License-Identifier: Apache-2.0 OR MIT * */ #include #include #include #include #include #include #include #include #include #include #include #include #include namespace PhysX { namespace Internal { AZStd::vector> GetCollisionShapes(AZ::Entity* entity) { AZStd::vector> allShapes; const bool hasNonUniformScaleComponent = (AZ::NonUniformScaleRequestBus::FindFirstHandler(entity->GetId()) != nullptr); const AZStd::vector colliders = entity->FindComponents(); for (const EditorColliderComponent* collider : colliders) { const EditorProxyShapeConfig& shapeConfigurationProxy = collider->GetShapeConfiguration(); if (shapeConfigurationProxy.IsAssetConfig() && !shapeConfigurationProxy.m_physicsAsset.m_configuration.m_asset.IsReady()) { continue; } const Physics::ColliderConfiguration colliderConfigurationScaled = collider->GetColliderConfigurationScaled(); const Physics::ColliderConfiguration colliderConfigurationUnscaled = collider->GetColliderConfiguration(); if (shapeConfigurationProxy.IsAssetConfig()) { AZStd::vector> shapes; Utils::GetShapesFromAsset(shapeConfigurationProxy.m_physicsAsset.m_configuration, colliderConfigurationUnscaled, hasNonUniformScaleComponent, shapeConfigurationProxy.m_subdivisionLevel, shapes); for (const auto& shape : shapes) { AZ_Assert(shape, "CreateEditorWorldRigidBody: Shape must not be null!"); allShapes.emplace_back(shape); } } else { const Physics::ShapeConfiguration& shapeConfiguration = shapeConfigurationProxy.GetCurrent(); if (!hasNonUniformScaleComponent) { AZStd::shared_ptr shape = AZ::Interface::Get()->CreateShape( colliderConfigurationScaled, shapeConfiguration); AZ_Assert(shape, "CreateEditorWorldRigidBody: Shape must not be null!"); if (shape) { allShapes.emplace_back(shape); } } else { auto convexConfig = Utils::CreateConvexFromPrimitive(colliderConfigurationUnscaled, shapeConfiguration, shapeConfigurationProxy.m_subdivisionLevel, shapeConfiguration.m_scale); auto colliderConfigurationNoOffset = colliderConfigurationUnscaled; colliderConfigurationNoOffset.m_rotation = AZ::Quaternion::CreateIdentity(); colliderConfigurationNoOffset.m_position = AZ::Vector3::CreateZero(); if (convexConfig.has_value()) { AZStd::shared_ptr shape = AZ::Interface::Get()->CreateShape( colliderConfigurationNoOffset, convexConfig.value()); allShapes.emplace_back(shape); } } } } const AZStd::vector shapeColliders = entity->FindComponents(); for (const EditorShapeColliderComponent* shapeCollider : shapeColliders) { const Physics::ColliderConfiguration& colliderConfig = shapeCollider->GetColliderConfiguration(); const AZStd::vector>& shapeConfigs = shapeCollider->GetShapeConfigurations(); for (const auto& shapeConfig : shapeConfigs) { AZStd::shared_ptr shape = AZ::Interface::Get()->CreateShape(colliderConfig, *shapeConfig); AZ_Assert(shape, "CreateEditorWorldRigidBody: Shape must not be null!"); allShapes.emplace_back(shape); } } return allShapes; } } // namespace Internal void EditorRigidBodyConfiguration::Reflect(AZ::ReflectContext* context) { auto serializeContext = azrtti_cast(context); if (serializeContext) { serializeContext->Class() ->Version(2, &ClassConverters::EditorRigidBodyConfigVersionConverter) ->Field("Debug Draw Center of Mass", &EditorRigidBodyConfiguration::m_centerOfMassDebugDraw) ; AZ::EditContext* editContext = serializeContext->GetEditContext(); if (editContext) { editContext->Class( "PhysX Rigid Body Configuration", "") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Category, "PhysX") ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) ->DataElement(AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_initialLinearVelocity, "Initial linear velocity", "Linear velocity applied when the rigid body is activated.") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetInitialVelocitiesVisibility) ->Attribute(AZ::Edit::Attributes::Suffix, " " + Physics::NameConstants::GetSpeedUnit()) ->DataElement(AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_initialAngularVelocity, "Initial angular velocity", "Angular velocity applied when the rigid body is activated (limited by maximum angular velocity).") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetInitialVelocitiesVisibility) ->Attribute(AZ::Edit::Attributes::Suffix, " " + Physics::NameConstants::GetAngularVelocityUnit()) ->DataElement(AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_linearDamping, "Linear damping", "The rate of decay over time for linear velocity even if no forces are acting on the rigid body.") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetDampingVisibility) ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->DataElement(AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_angularDamping, "Angular damping", "The rate of decay over time for angular velocity even if no forces are acting on the rigid body.") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetDampingVisibility) ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->DataElement(AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_sleepMinEnergy, "Sleep threshold", "The rigid body can go to sleep (settle) when kinetic energy per unit mass is persistently below this value.") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetSleepOptionsVisibility) ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Suffix, " " + Physics::NameConstants::GetSleepThresholdUnit()) ->DataElement(AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_startAsleep, "Start asleep", "When active, the rigid body will be asleep when spawned, and wake when the body is disturbed.") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetSleepOptionsVisibility) ->DataElement(AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_interpolateMotion, "Interpolate motion", "When active, simulation results are interpolated resulting in smoother motion.") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetInterpolationVisibility) ->DataElement(AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_gravityEnabled, "Gravity enabled", "When active, global gravity affects this rigid body.") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetGravityVisibility) ->DataElement(AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_kinematic, "Kinematic", "When active, the rigid body is not affected by gravity or other forces and is moved by script.") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetKinematicVisibility) // Linear axis locking properties ->ClassElement(AZ::Edit::ClassElements::Group, "Linear Axis Locking") ->Attribute(AZ::Edit::Attributes::AutoExpand, false) ->DataElement( AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockLinearX, "Lock X", "When active, forces won't create translation on the X axis of the rigid body.") ->DataElement( AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockLinearY, "Lock Y", "When active, forces won't create translation on the Y axis of the rigid body.") ->DataElement( AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockLinearZ, "Lock Z", "When active, forces won't create translation on the Z axis of the rigid body.") // Angular axis locking properties ->ClassElement(AZ::Edit::ClassElements::Group, "Angular Axis Locking") ->Attribute(AZ::Edit::Attributes::AutoExpand, false) ->DataElement( AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockAngularX, "Lock X", "When active, forces won't create rotation on the X axis of the rigid body.") ->DataElement( AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockAngularY, "Lock Y", "When active, forces won't create rotation on the Y axis of the rigid body.") ->DataElement( AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_lockAngularZ, "Lock Z", "When active, forces won't create rotation on the Z axis of the rigid body.") ->ClassElement(AZ::Edit::ClassElements::Group, "Continuous Collision Detection") ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetCCDVisibility) ->DataElement(AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_ccdEnabled, "CCD enabled", "When active, the rigid body has continuous collision detection (CCD). Use this to ensure accurate " "collision detection, particularly for fast moving rigid bodies. CCD must be activated in the global PhysX preferences.") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetCCDVisibility) ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) ->DataElement(AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_ccdMinAdvanceCoefficient, "Min advance coefficient", "Lower values reduce clipping but can affect simulation smoothness.") ->Attribute(AZ::Edit::Attributes::Min, 0.01f) ->Attribute(AZ::Edit::Attributes::Step, 0.01f) ->Attribute(AZ::Edit::Attributes::Max, 0.99f) ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::IsCCDEnabled) ->DataElement(AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_ccdFrictionEnabled, "CCD friction", "When active, friction is applied when continuous collision detection (CCD) collisions are resolved.") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::IsCCDEnabled) ->ClassElement(AZ::Edit::ClassElements::Group, "") // end previous group by starting new unnamed expanded group ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->DataElement(AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_maxAngularVelocity, "Maximum angular velocity", "Clamp angular velocities to this maximum value. " "This prevents rigid bodies from rotating at unrealistic velocities after collisions.") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetMaxVelocitiesVisibility) ->Attribute(AZ::Edit::Attributes::Suffix, " " + Physics::NameConstants::GetAngularVelocityUnit()) // Mass properties ->DataElement(AZ::Edit::UIHandlers::Default, &RigidBodyConfiguration::m_computeCenterOfMass, "Compute COM", "Compute the center of mass (COM) for this rigid body.") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetInertiaSettingsVisibility) ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) ->DataElement(AZ::Edit::UIHandlers::Default, &RigidBodyConfiguration::m_centerOfMassOffset, "COM offset", "Local space offset for the center of mass (COM).") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetCoMVisibility) ->Attribute(AZ::Edit::Attributes::Suffix, " " + Physics::NameConstants::GetLengthUnit()) ->DataElement(AZ::Edit::UIHandlers::Default, &RigidBodyConfiguration::m_computeMass, "Compute Mass", "When active, the mass of the rigid body is computed based on the volume and density values of its colliders.") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetInertiaSettingsVisibility) ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) ->DataElement(AZ::Edit::UIHandlers::Default, &AzPhysics::RigidBodyConfiguration::m_mass, "Mass", "The mass of the rigid body in kilograms. A value of 0 is treated as infinite. " "The trajectory of infinite mass bodies cannot be affected by any collisions or forces other than gravity.") ->Attribute(AZ::Edit::Attributes::Min, 0.0f) ->Attribute(AZ::Edit::Attributes::Suffix, " " + Physics::NameConstants::GetMassUnit()) ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetMassVisibility) ->DataElement(AZ::Edit::UIHandlers::Default, &RigidBodyConfiguration::m_computeInertiaTensor, "Compute inertia", "When active, inertia is computed based on the mass and shape of the rigid body.") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetInertiaSettingsVisibility) ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) ->DataElement(Editor::InertiaHandler, &AzPhysics::RigidBodyConfiguration::m_inertiaTensor, "Inertia diagonal", "Inertia diagonal elements that specify an inertia tensor; determines the " "torque required to rotate the rigid body on each axis.") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetInertiaVisibility) ->Attribute(AZ::Edit::Attributes::Suffix, " " + Physics::NameConstants::GetInertiaUnit()) ->DataElement(AZ::Edit::UIHandlers::Default, &RigidBodyConfiguration::m_includeAllShapesInMassCalculation, "Include non-simulated shapes in Mass", "When active, non-simulated shapes are included in the center of mass, inertia, and mass calculations.") ->Attribute(AZ::Edit::Attributes::Visibility, &AzPhysics::RigidBodyConfiguration::GetInertiaSettingsVisibility) ->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::EntireTree) ; editContext->Class( "PhysX Rigid Body Configuration", "") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Category, "PhysX") ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) ->DataElement(AZ::Edit::UIHandlers::Default, &EditorRigidBodyConfiguration::m_centerOfMassDebugDraw, "Debug draw COM", "Display the rigid body's center of mass (COM) in the viewport.") ; } } } void EditorRigidBodyComponent::Activate() { AzToolsFramework::Components::EditorComponentBase::Activate(); AzFramework::EntityDebugDisplayEventBus::Handler::BusConnect(GetEntityId()); AZ::TransformNotificationBus::Handler::BusConnect(GetEntityId()); Physics::ColliderComponentEventBus::Handler::BusConnect(GetEntityId()); if (auto* sceneInterface = AZ::Interface::Get()) { AzPhysics::SceneHandle editorSceneHandle = sceneInterface->GetSceneHandle(AzPhysics::EditorPhysicsSceneName); sceneInterface->RegisterSceneSimulationStartHandler(editorSceneHandle, m_sceneStartSimHandler); } m_nonUniformScaleChangedHandler = AZ::NonUniformScaleChangedEvent::Handler( [this](const AZ::Vector3& scale) {OnNonUniformScaleChanged(scale); }); AZ::NonUniformScaleRequestBus::Event(GetEntityId(), &AZ::NonUniformScaleRequests::RegisterScaleChangedEvent, m_nonUniformScaleChangedHandler); if (auto* physXDebug = AZ::Interface::Get()) { m_debugDisplayDataChangeHandler = Debug::DebugDisplayDataChangedEvent::Handler( [this](const Debug::DebugDisplayData& data) { this->UpdateDebugDrawSettings(data); }); physXDebug->RegisterDebugDisplayDataChangedEvent(m_debugDisplayDataChangeHandler); UpdateDebugDrawSettings(physXDebug->GetDebugDisplayData()); } CreateEditorWorldRigidBody(); PhysX::EditorColliderValidationRequestBus::Event( GetEntityId(), &PhysX::EditorColliderValidationRequestBus::Events::ValidateRigidBodyMeshGeometryType); AzPhysics::SimulatedBodyComponentRequestsBus::Handler::BusConnect(GetEntityId()); } void EditorRigidBodyComponent::Deactivate() { m_debugDisplayDataChangeHandler.Disconnect(); AzPhysics::SimulatedBodyComponentRequestsBus::Handler::BusDisconnect(); m_nonUniformScaleChangedHandler.Disconnect(); m_sceneStartSimHandler.Disconnect(); Physics::ColliderComponentEventBus::Handler::BusDisconnect(); AZ::TransformNotificationBus::Handler::BusDisconnect(); AzFramework::EntityDebugDisplayEventBus::Handler::BusDisconnect(); AzToolsFramework::Components::EditorComponentBase::Deactivate(); if (auto* sceneInterface = AZ::Interface::Get()) { sceneInterface->RemoveSimulatedBody(m_editorSceneHandle, m_editorRigidBodyHandle); } } void EditorRigidBodyComponent::OnConfigurationChanged() { CreateEditorWorldRigidBody(); // required in case the kinematic setting has changed PhysX::EditorColliderValidationRequestBus::Event( GetEntityId(), &PhysX::EditorColliderValidationRequestBus::Events::ValidateRigidBodyMeshGeometryType); } void EditorRigidBodyComponent::Reflect(AZ::ReflectContext* context) { EditorRigidBodyConfiguration::Reflect(context); auto serializeContext = azrtti_cast(context); if (serializeContext) { serializeContext->Class() ->Field("Configuration", &EditorRigidBodyComponent::m_config) ->Version(1) ; AZ::EditContext* editContext = serializeContext->GetEditContext(); if (editContext) { editContext->Class( "PhysX Rigid Body", "The entity behaves as a movable rigid object in PhysX.") ->ClassElement(AZ::Edit::ClassElements::EditorData, "") ->Attribute(AZ::Edit::Attributes::Category, "PhysX") ->Attribute(AZ::Edit::Attributes::Icon, "Icons/Components/PhysXRigidBody.svg") ->Attribute(AZ::Edit::Attributes::ViewportIcon, "Icons/Components/Viewport/PhysXRigidBody.svg") ->Attribute(AZ::Edit::Attributes::AppearsInAddComponentMenu, AZ_CRC("Game", 0x232b318c)) ->Attribute(AZ::Edit::Attributes::AutoExpand, true) ->Attribute(AZ::Edit::Attributes::HelpPageURL, "https://o3de.org/docs/user-guide/components/reference/physx/rigid-body-physics/") ->DataElement(0, &EditorRigidBodyComponent::m_config, "Configuration", "Configuration for rigid body physics.") ->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly) ->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorRigidBodyComponent::OnConfigurationChanged) ; } } } EditorRigidBodyComponent::EditorRigidBodyComponent() { InitPhysicsTickHandler(); } EditorRigidBodyComponent::EditorRigidBodyComponent(const EditorRigidBodyConfiguration& config) : m_config(config) { InitPhysicsTickHandler(); } void EditorRigidBodyComponent::BuildGameEntity(AZ::Entity* gameEntity) { // for now use Invalid scene which will fall back on default scene when entity is activated. // update to correct scene once multi-scene is fully supported. gameEntity->CreateComponent(m_config, AzPhysics::InvalidSceneHandle); } void EditorRigidBodyComponent::DisplayEntityViewport( [[maybe_unused]] const AzFramework::ViewportInfo& viewportInfo, AzFramework::DebugDisplayRequests& debugDisplay) { if (m_config.m_centerOfMassDebugDraw) { if (const AzPhysics::RigidBody* body = GetRigidBody()) { debugDisplay.DepthTestOff(); debugDisplay.SetColor(m_centerOfMassDebugColor); debugDisplay.DrawBall(body->GetCenterOfMassWorld(), m_centerOfMassDebugSize); debugDisplay.DepthTestOn(); } } } void EditorRigidBodyComponent::CreateEditorWorldRigidBody() { if (auto* sceneInterface = AZ::Interface::Get()) { m_editorSceneHandle = sceneInterface->GetSceneHandle(AzPhysics::EditorPhysicsSceneName); if (m_editorSceneHandle == AzPhysics::InvalidSceneHandle) { AZ_Assert(false, "Attempting to create an edit time rigid body without an editor scene."); return; } } AZ::Transform colliderTransform = GetWorldTM(); colliderTransform.ExtractUniformScale(); AzPhysics::RigidBodyConfiguration configuration = m_config; configuration.m_orientation = colliderTransform.GetRotation(); configuration.m_position = colliderTransform.GetTranslation(); configuration.m_entityId = GetEntityId(); configuration.m_debugName = GetEntity()->GetName(); configuration.m_startSimulationEnabled = false; configuration.m_colliderAndShapeData = Internal::GetCollisionShapes(GetEntity()); if (auto* sceneInterface = AZ::Interface::Get()) { m_editorRigidBodyHandle = sceneInterface->AddSimulatedBody(m_editorSceneHandle, &configuration); if (auto* body = azdynamic_cast( sceneInterface->GetSimulatedBodyFromHandle(m_editorSceneHandle, m_editorRigidBodyHandle) )) { // AddSimulatedBody may update mass / CoM / Inertia tensor based on the config, so grab the updated values. m_config.m_mass = body->GetMass(); m_config.m_centerOfMassOffset = body->GetCenterOfMassLocal(); m_config.m_inertiaTensor = body->GetInverseInertiaLocal(); } } AZ_Error("EditorRigidBodyComponent", m_editorRigidBodyHandle != AzPhysics::InvalidSimulatedBodyHandle, "Failed to create editor rigid body"); } void EditorRigidBodyComponent::OnColliderChanged() { //recreate the rigid body when collider changes SetShouldBeRecreated(); } void EditorRigidBodyComponent::OnTransformChanged([[maybe_unused]]const AZ::Transform& local, [[maybe_unused]]const AZ::Transform& world) { SetShouldBeRecreated(); } void EditorRigidBodyComponent::OnNonUniformScaleChanged([[maybe_unused]] const AZ::Vector3& scale) { SetShouldBeRecreated(); } void EditorRigidBodyComponent::InitPhysicsTickHandler() { m_sceneStartSimHandler = AzPhysics::SceneEvents::OnSceneSimulationStartHandler([this]( [[maybe_unused]] AzPhysics::SceneHandle sceneHandle, [[maybe_unused]] float fixedDeltatime ) { this->PrePhysicsTick(); }, aznumeric_cast(AzPhysics::SceneEvents::PhysicsStartFinishSimulationPriority::Components)); } void EditorRigidBodyComponent::PrePhysicsTick() { if (m_shouldBeRecreated) { if (auto* sceneInterface = AZ::Interface::Get()) { sceneInterface->RemoveSimulatedBody(m_editorSceneHandle, m_editorRigidBodyHandle); CreateEditorWorldRigidBody(); } m_shouldBeRecreated = false; } } void EditorRigidBodyComponent::EnablePhysics() { if (auto* sceneInterface = AZ::Interface::Get()) { sceneInterface->EnableSimulationOfBody(m_editorSceneHandle, m_editorRigidBodyHandle); } } void EditorRigidBodyComponent::DisablePhysics() { if (auto* sceneInterface = AZ::Interface::Get()) { sceneInterface->DisableSimulationOfBody(m_editorSceneHandle, m_editorRigidBodyHandle); } } bool EditorRigidBodyComponent::IsPhysicsEnabled() const { if (auto* sceneInterface = AZ::Interface::Get()) { if (AzPhysics::SimulatedBody* body = sceneInterface->GetSimulatedBodyFromHandle(m_editorSceneHandle, m_editorRigidBodyHandle)) { return body->m_simulating; } } return false; } AZ::Aabb EditorRigidBodyComponent::GetAabb() const { if (auto* sceneInterface = AZ::Interface::Get()) { if (AzPhysics::SimulatedBody* body = sceneInterface->GetSimulatedBodyFromHandle(m_editorSceneHandle, m_editorRigidBodyHandle)) { return body->GetAabb(); } } return AZ::Aabb::CreateNull(); } AzPhysics::SimulatedBody* EditorRigidBodyComponent::GetSimulatedBody() { if (auto* sceneInterface = AZ::Interface::Get()) { return sceneInterface->GetSimulatedBodyFromHandle(m_editorSceneHandle, m_editorRigidBodyHandle); } return nullptr; } AzPhysics::SimulatedBodyHandle EditorRigidBodyComponent::GetSimulatedBodyHandle() const { return m_editorRigidBodyHandle; } AzPhysics::SceneQueryHit EditorRigidBodyComponent::RayCast(const AzPhysics::RayCastRequest& request) { if (AzPhysics::SimulatedBody* body = GetSimulatedBody()) { return body->RayCast(request); } return AzPhysics::SceneQueryHit(); } void EditorRigidBodyComponent::UpdateDebugDrawSettings(const Debug::DebugDisplayData& data) { m_centerOfMassDebugColor = data.m_centerOfMassDebugColor; m_centerOfMassDebugSize = data.m_centerOfMassDebugSize; } const AzPhysics::RigidBody* EditorRigidBodyComponent::GetRigidBody() const { if (auto* sceneInterface = AZ::Interface::Get()) { return azdynamic_cast( sceneInterface->GetSimulatedBodyFromHandle(m_editorSceneHandle, m_editorRigidBodyHandle)); } return nullptr; } void EditorRigidBodyComponent::SetShouldBeRecreated() { if (!m_shouldBeRecreated) { m_shouldBeRecreated = true; } } } // namespace PhysX