1f9b284de2
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com> # Conflicts: # Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h # Code/Editor/Plugins/EditorCommon/EditorCommon_precompiled.h # Code/Editor/Plugins/EditorCommon/stdafx.cpp # Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin_precompiled.h # Code/Editor/Plugins/PerforcePlugin/PerforcePlugin_precompiled.h # Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsTool_precompiled.h # Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFramework_precompiled.h # Code/Tools/AssetProcessor/native/precompiled.h # Code/Tools/Standalone/StandaloneTools_precompiled.h # Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer_precompiled.h # Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageProcessing_precompiled.h # Gems/Atom/RHI/DX12/Code/Source/RHI/Atom_RHI_DX12_precompiled.h # Gems/Atom/RHI/Metal/Code/Include/Platform/Mac/Atom_RHI_Metal_precompiled_Platform.h # Gems/Atom/RHI/Metal/Code/Include/Platform/iOS/Atom_RHI_Metal_precompiled_Platform.h # Gems/Atom/RHI/Metal/Code/Source/Atom_RHI_Metal_precompiled.h # Gems/Atom/RHI/Metal/Code/atom_rhi_metal_common_files.cmake # Gems/Atom/RHI/Null/Code/Source/Atom_RHI_Null_precompiled.h # Gems/Atom/RHI/Null/Code/atom_rhi_null_common_files.cmake # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Android/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Linux/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Mac/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Include/Platform/Windows/Atom_RHI_Vulkan_precompiled_Platform.h # Gems/Atom/RHI/Vulkan/Code/Source/Atom_RHI_Vulkan_precompiled.h # Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp # Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_common_files.cmake # Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h # Gems/Blast/Code/Source/StdAfx.cpp # Gems/Camera/Code/Source/Camera_precompiled.h # Gems/EMotionFX/Code/Source/EMotionFX_precompiled.h # Gems/FastNoise/Code/Source/FastNoise_precompiled.h # Gems/Gestures/Code/Source/Gestures_precompiled.h # Gems/GradientSignal/Code/Source/GradientSignal_precompiled.h # Gems/GraphCanvas/Code/precompiled.h # Gems/ImGui/Code/Source/ImGui_precompiled.h # Gems/InAppPurchases/Code/Source/InAppPurchases_precompiled.h # Gems/LmbrCentral/Code/Source/LmbrCentral_precompiled.h # Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp # Gems/LyShine/Code/Editor/UiCanvasEditor_precompiled.h # Gems/LyShine/Code/Source/Animation/LyShine_precompiled.h # Gems/LyShine/Code/Source/LyShine_precompiled.h # Gems/LyShineExamples/Code/Source/LyShineExamples_precompiled.h # Gems/Maestro/Code/Source/Cinematics/Maestro_precompiled.h # Gems/Maestro/Code/Source/Maestro_precompiled.h # Gems/MessagePopup/Code/Source/MessagePopup_precompiled.h # Gems/Metastream/Code/Source/Metastream_precompiled.h # Gems/Microphone/Code/Source/Microphone_precompiled.h # Gems/Multiplayer/Code/Source/Multiplayer_precompiled.h # Gems/PhysX/Code/NumericalMethods/Source/NumericalMethods_precompiled.h # Gems/PhysX/Code/Source/PhysXUnsupported_precompiled.h # Gems/PhysX/Code/Source/PhysX_precompiled.h # Gems/PhysX/Code/physx_unsupported_files.cmake # Gems/PhysXDebug/Code/Source/PhysXDebugUnsupported_precompiled.h # Gems/PhysXDebug/Code/Source/PhysXDebug_precompiled.h # Gems/ScriptCanvas/Code/Editor/precompiled.h # Gems/ScriptCanvas/Code/Source/precompiled.h # Gems/ScriptCanvasDeveloper/Code/Source/precompiled.h # Gems/ScriptCanvasPhysics/Code/Source/ScriptCanvasPhysics_precompiled.h # Gems/ScriptEvents/Code/Source/precompiled.h # Gems/ScriptEvents/Code/Tests/Editor/EditorTests.cpp # Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweener_precompiled.h # Gems/SliceFavorites/Code/Source/SliceFavorites_precompiled.h # Gems/StartingPointCamera/Code/Source/StartingPointCamera_precompiled.h # Gems/StartingPointInput/Code/Source/StartingPointInput_precompiled.h # Gems/StartingPointMovement/Code/Source/StartingPointMovement_precompiled.h # Gems/SurfaceData/Code/Source/SurfaceData_precompiled.h # Gems/TextureAtlas/Code/Source/TextureAtlas_precompiled.h # Gems/TickBusOrderViewer/Code/Source/TickBusOrderViewer_precompiled.h # Gems/Twitch/Code/Source/Twitch_precompiled.h # Gems/VirtualGamepad/Code/Source/VirtualGamepad_precompiled.h # Gems/WhiteBox/Code/Source/WhiteBoxUnsupported_precompiled.h # Gems/WhiteBox/Code/Source/WhiteBox_precompiled.h
262 lines
9.4 KiB
C++
262 lines
9.4 KiB
C++
/*
|
|
* 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 <Source/ForceRegion.h>
|
|
|
|
#include <PhysX/ColliderShapeBus.h>
|
|
#include <PhysX/MeshAsset.h>
|
|
#include <Source/Utils.h>
|
|
|
|
#include <AzCore/Math/Color.h>
|
|
#include <AzFramework/Physics/ColliderComponentBus.h>
|
|
#include <AzFramework/Physics/RigidBodyBus.h>
|
|
|
|
namespace PhysX
|
|
{
|
|
/// Aggregates the AABB of all trigger collider components in an entity.
|
|
struct TriggerAabbAggregator
|
|
{
|
|
AZ::Aabb operator()(AZ::Aabb& lhs, const AZ::Aabb& rhs) const
|
|
{
|
|
if (rhs == AZ::Aabb::CreateNull()) // Ignore non-trigger colliders that may have null AABB.
|
|
{
|
|
return lhs;
|
|
}
|
|
else
|
|
{
|
|
lhs.AddAabb(rhs);
|
|
return lhs;
|
|
}
|
|
}
|
|
};
|
|
|
|
/// Aggregates points on trigger collider components in an entity.
|
|
struct TriggerRandomPointsAggregator
|
|
{
|
|
Utils::Geometry::PointList operator()(Utils::Geometry::PointList& left
|
|
, const Utils::Geometry::PointList& right) const
|
|
{
|
|
Utils::Geometry::PointList combinedPoints;
|
|
combinedPoints.reserve(left.size() + right.size());
|
|
combinedPoints.insert(combinedPoints.end(), left.begin(), left.end());
|
|
combinedPoints.insert(combinedPoints.end(), right.begin(), right.end());
|
|
return combinedPoints;
|
|
}
|
|
};
|
|
|
|
void ForceRegion::Reflect(AZ::ReflectContext* context)
|
|
{
|
|
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
|
{
|
|
BaseForce::Reflect(*serializeContext);
|
|
|
|
serializeContext->Class<ForceRegion>()
|
|
->Version(1)
|
|
->Field("Forces", &ForceRegion::m_forces)
|
|
;
|
|
|
|
if (auto editContext = serializeContext->GetEditContext())
|
|
{
|
|
editContext->Class<ForceRegion>(
|
|
"Force Region", "Applies forces on entities within a region")
|
|
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
|
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
|
->DataElement(AZ::Edit::UIHandlers::Default, &ForceRegion::m_forces, "Forces", "Forces acting in the region")
|
|
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
|
;
|
|
}
|
|
}
|
|
}
|
|
|
|
ForceRegion::ForceRegion(const ForceRegion& forceRegion)
|
|
{
|
|
// Force region must be deep copied as it contains pointers
|
|
AZ::SerializeContext* context;
|
|
AZ::ComponentApplicationBus::BroadcastResult(context, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
|
|
context->CloneObjectInplace<ForceRegion>(*this, &forceRegion);
|
|
}
|
|
|
|
void ForceRegion::Activate(AZ::EntityId entityId)
|
|
{
|
|
m_entityId = entityId;
|
|
m_regionParams = ForceRegionUtil::CreateRegionParams(m_entityId);
|
|
AZ::TransformNotificationBus::MultiHandler::BusConnect(m_entityId);
|
|
LmbrCentral::SplineComponentNotificationBus::Handler::BusConnect(m_entityId);
|
|
ForceRegionRequestBus::Handler::BusConnect(m_entityId);
|
|
Physics::ColliderComponentEventBus::Handler::BusConnect(m_entityId);
|
|
for (auto& force : m_forces)
|
|
{
|
|
force->Activate(m_entityId);
|
|
}
|
|
|
|
AZ::TransformBus::EventResult(m_worldTransform, m_entityId, &AZ::TransformBus::Events::GetWorldTM);
|
|
}
|
|
|
|
void ForceRegion::Deactivate()
|
|
{
|
|
m_entityId.SetInvalid();
|
|
for (auto& force : m_forces)
|
|
{
|
|
force->Deactivate();
|
|
}
|
|
Physics::ColliderComponentEventBus::Handler::BusDisconnect();
|
|
ForceRegionRequestBus::Handler::BusDisconnect();
|
|
LmbrCentral::SplineComponentNotificationBus::Handler::BusDisconnect();
|
|
AZ::TransformNotificationBus::MultiHandler::BusDisconnect();
|
|
}
|
|
|
|
AZ::Vector3 ForceRegion::CalculateNetForce(const EntityParams& entity) const
|
|
{
|
|
auto totalForce = AZ::Vector3::CreateZero();
|
|
for (auto& force : m_forces)
|
|
{
|
|
totalForce += force->CalculateForce(entity, m_regionParams);
|
|
}
|
|
PhysX::ForceRegionNotificationBus::Broadcast(&ForceRegionNotificationBus::Events::OnCalculateNetForce
|
|
, m_regionParams.m_id
|
|
, entity.m_id
|
|
, totalForce.GetNormalized()
|
|
, totalForce.GetLength());
|
|
return totalForce;
|
|
}
|
|
|
|
void ForceRegion::ClearForces()
|
|
{
|
|
for (auto& force : m_forces)
|
|
{
|
|
force->Deactivate();
|
|
}
|
|
m_forces.clear();
|
|
}
|
|
|
|
PhysX::RegionParams ForceRegion::GetRegionParams() const
|
|
{
|
|
return m_regionParams;
|
|
}
|
|
|
|
void ForceRegion::OnTransformChanged(const AZ::Transform& /*local*/, const AZ::Transform& world)
|
|
{
|
|
m_worldTransform = world;
|
|
m_regionParams.m_position = world.GetTranslation();
|
|
m_regionParams.m_scale = world.GetUniformScale();
|
|
m_regionParams.m_rotation = world.GetRotation();
|
|
AZ::EBusReduceResult<AZ::Aabb, PhysX::TriggerAabbAggregator> triggerAabb;
|
|
triggerAabb.value = AZ::Aabb::CreateNull();
|
|
|
|
ColliderShapeRequestBus::EventResult(triggerAabb
|
|
, m_entityId
|
|
, &ColliderShapeRequestBus::Events::GetColliderShapeAabb);
|
|
|
|
m_regionParams.m_aabb = triggerAabb.value;
|
|
}
|
|
|
|
void ForceRegion::OnColliderChanged()
|
|
{
|
|
m_regionParams = ForceRegionUtil::CreateRegionParams(m_entityId);
|
|
}
|
|
|
|
void ForceRegion::AddForceWorldSpace(const AZ::Vector3& direction, float magnitude)
|
|
{
|
|
AddAndActivateForce(AZStd::make_unique<ForceWorldSpace>(direction, magnitude));
|
|
}
|
|
|
|
void ForceRegion::AddForceLocalSpace(const AZ::Vector3& direction, float magnitude)
|
|
{
|
|
AddAndActivateForce(AZStd::make_unique<ForceLocalSpace>(direction, magnitude));
|
|
}
|
|
|
|
void ForceRegion::AddForcePoint(float magnitude)
|
|
{
|
|
AddAndActivateForce(AZStd::make_unique<ForcePoint>(magnitude));
|
|
}
|
|
|
|
void ForceRegion::AddForceSplineFollow(float dampingRatio, float frequency, float targetSpeed, float lookAhead)
|
|
{
|
|
AddAndActivateForce(AZStd::make_unique<ForceSplineFollow>(dampingRatio, frequency, targetSpeed, lookAhead));
|
|
}
|
|
|
|
void ForceRegion::AddForceSimpleDrag(float dragCoefficient, float volumeDensity)
|
|
{
|
|
AddAndActivateForce(AZStd::make_unique<ForceSimpleDrag>(dragCoefficient, volumeDensity));
|
|
}
|
|
|
|
void ForceRegion::AddForceLinearDamping(float damping)
|
|
{
|
|
AddAndActivateForce(AZStd::make_unique<ForceLinearDamping>(damping));
|
|
}
|
|
|
|
void ForceRegion::AddAndActivateForce(AZStd::unique_ptr<BaseForce> force)
|
|
{
|
|
AZ_Assert(force, "Failed to add and activate null force.");
|
|
if (nullptr == force)
|
|
{
|
|
return;
|
|
}
|
|
m_forces.push_back(AZStd::move(force));
|
|
m_forces.back()->Activate(m_entityId);
|
|
}
|
|
|
|
void ForceRegion::OnSplineChanged()
|
|
{
|
|
LmbrCentral::SplineComponentRequestBus::EventResult(m_regionParams.m_spline
|
|
, m_entityId
|
|
, &LmbrCentral::SplineComponentRequestBus::Events::GetSpline);
|
|
}
|
|
|
|
RegionParams ForceRegionUtil::CreateRegionParams(AZ::EntityId entityId)
|
|
{
|
|
RegionParams regionParams;
|
|
regionParams.m_id = entityId;
|
|
|
|
AZ::Transform worldTransform = AZ::Transform::CreateIdentity();
|
|
AZ::TransformBus::EventResult(worldTransform
|
|
, entityId
|
|
, &AZ::TransformBus::Events::GetWorldTM);
|
|
regionParams.m_position = worldTransform.GetTranslation();
|
|
regionParams.m_scale = worldTransform.GetUniformScale();
|
|
regionParams.m_rotation = worldTransform.GetRotation();
|
|
|
|
LmbrCentral::SplineComponentRequestBus::EventResult(regionParams.m_spline
|
|
, entityId
|
|
, &LmbrCentral::SplineComponentRequestBus::Events::GetSpline);
|
|
AZ::EBusReduceResult<AZ::Aabb, PhysX::TriggerAabbAggregator> triggerAabb;
|
|
triggerAabb.value = AZ::Aabb::CreateNull();
|
|
ColliderShapeRequestBus::EventResult(triggerAabb
|
|
, entityId
|
|
, &ColliderShapeRequestBus::Events::GetColliderShapeAabb);
|
|
regionParams.m_aabb = triggerAabb.value;
|
|
return regionParams;
|
|
}
|
|
|
|
EntityParams ForceRegionUtil::CreateEntityParams(AZ::EntityId entityId)
|
|
{
|
|
EntityParams entityParams;
|
|
entityParams.m_id = entityId;
|
|
AZ::TransformBus::EventResult(entityParams.m_position
|
|
, entityId
|
|
, &AZ::TransformBus::Events::GetWorldTranslation);
|
|
Physics::RigidBodyRequestBus::EventResultReverse(entityParams.m_velocity
|
|
, entityId
|
|
, &Physics::RigidBodyRequestBus::Events::GetLinearVelocity);
|
|
Physics::RigidBodyRequestBus::EventResultReverse(entityParams.m_mass
|
|
, entityId
|
|
, &Physics::RigidBodyRequestBus::Events::GetMass);
|
|
entityParams.m_aabb = GetForceRegionAabb(entityId);
|
|
return entityParams;
|
|
}
|
|
|
|
AZ::Aabb ForceRegionUtil::GetForceRegionAabb(AZ::EntityId entityId)
|
|
{
|
|
AZ::EBusReduceResult<AZ::Aabb, PhysX::TriggerAabbAggregator> triggerAabb;
|
|
triggerAabb.value = AZ::Aabb::CreateNull();
|
|
ColliderShapeRequestBus::EventResult(triggerAabb
|
|
, entityId
|
|
, &ColliderShapeRequestBus::Events::GetColliderShapeAabb);
|
|
return triggerAabb.value;
|
|
}
|
|
}
|