Files
o3de/Code/Framework/AzFramework/AzFramework/Physics/ShapeConfiguration.cpp
T
Aaron Ruiz Mora 00e860f326 Physics material system for spectra launch
- Invalidate 'Physics Materials From Mesh' boolean from collider component
- Removed material library from material selector. Default material library will always be used instead.
- Marking failing automated test as xfail
- Added default material to physics configuration.
- Moved material library asset from physx configuration to physics configuration, as it doesn't need to be physx specific.
- Refactor physics material system having into account that there is only one material library in the project.
- Renaming code from DefaultMaterialLibrary to MaterialLibrary.
- All queries about physics materials unified under PhysicsMaterialRequests bus.
- PhysXSystem only manages the material library asset.
- Saving and reloading the same physics material asset with different content didn't trigger a events that the material library has changed.
- Changing Physics Material Request interface to use shared_ptr instead of weak_ptr to be simpler to handle the returned materials and having a more consistent code.
- Refactored Material Manager to improve its implementation. Still following the same approach of "creating materials on the fly as they are requested", but now it's doing it consistently across the interface, with private helpers functions FindOrCreateMaterial that simplify vastly the implementation.
- Material Manager now listens to change event of material library asset and default material configuration so it updates its materials accordingly.
- Complete Material move constructor and operator.
2021-05-28 20:16:25 +01:00

324 lines
14 KiB
C++

/*
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
* its licensors.
*
* For complete copyright and license terms please see the LICENSE at the root of this
* distribution (the "License"). All use of this software is governed by the License,
* or, if provided, by the license below or the license accompanying this file. Do not
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
*
*/
#include <AzFramework/Physics/ShapeConfiguration.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzFramework/Physics/PropertyTypes.h>
#include <AzFramework/Physics/SystemBus.h>
namespace Physics
{
namespace Internal
{
bool ShapeConfigurationVersionConverter(
[[maybe_unused]] AZ::SerializeContext& context,
AZ::SerializeContext::DataElementNode& classElement)
{
if (classElement.GetVersion() <= 1)
{
classElement.RemoveElementByName(AZ_CRC_CE("UseMaterialsFromAsset"));
}
return true;
}
}
void ShapeConfiguration::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<ShapeConfiguration>()
->Version(1)
->Field("Scale", &ShapeConfiguration::m_scale)
;
}
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
#define REFLECT_SHAPETYPE_ENUM_VALUE(EnumValue) \
behaviorContext->EnumProperty<(int)Physics::ShapeType::EnumValue>("ShapeType_"#EnumValue) \
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation) \
->Attribute(AZ::Script::Attributes::Module, "physics");
// Note: Here we only expose the types that are available to the user in the editor
REFLECT_SHAPETYPE_ENUM_VALUE(Box);
REFLECT_SHAPETYPE_ENUM_VALUE(Sphere);
REFLECT_SHAPETYPE_ENUM_VALUE(Cylinder);
REFLECT_SHAPETYPE_ENUM_VALUE(PhysicsAsset);
#undef REFLECT_SHAPETYPE_ENUM_VALUE
}
}
void SphereShapeConfiguration::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext
->RegisterGenericType<AZStd::shared_ptr<SphereShapeConfiguration>>();
serializeContext->Class<SphereShapeConfiguration, ShapeConfiguration>()
->Version(1)
->Field("Radius", &SphereShapeConfiguration::m_radius)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<SphereShapeConfiguration>("SphereShapeConfiguration", "Configuration for sphere collider")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &SphereShapeConfiguration::m_radius, "Radius", "The radius of the sphere collider")
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
->Attribute(AZ::Edit::Attributes::Step, 0.01f)
;
}
}
}
SphereShapeConfiguration::SphereShapeConfiguration(float radius)
: m_radius(radius)
{
}
void BoxShapeConfiguration::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext
->RegisterGenericType<AZStd::shared_ptr<BoxShapeConfiguration>>();
serializeContext->Class<BoxShapeConfiguration, ShapeConfiguration>()
->Version(1)
->Field("Configuration", &BoxShapeConfiguration::m_dimensions)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<BoxShapeConfiguration>("BoxShapeConfiguration", "Configuration for box collider")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &BoxShapeConfiguration::m_dimensions, "Dimensions", "Lengths of the box sides")
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
->Attribute(AZ::Edit::Attributes::Step, 0.01f)
;
}
}
}
BoxShapeConfiguration::BoxShapeConfiguration(const AZ::Vector3& boxDimensions)
: m_dimensions(boxDimensions)
{
}
void CapsuleShapeConfiguration::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext
->RegisterGenericType<AZStd::shared_ptr<CapsuleShapeConfiguration>>();
serializeContext->Class<CapsuleShapeConfiguration, ShapeConfiguration>()
->Version(1)
->Field("Height", &CapsuleShapeConfiguration::m_height)
->Field("Radius", &CapsuleShapeConfiguration::m_radius)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<CapsuleShapeConfiguration>("CapsuleShapeConfiguration", "Configuration for capsule collider")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &CapsuleShapeConfiguration::m_height, "Height", "The height of the capsule, including caps at each end")
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
->Attribute(AZ::Edit::Attributes::Step, 0.01f)
->Attribute(AZ::Edit::Attributes::ChangeNotify, &CapsuleShapeConfiguration::OnHeightChanged)
->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::ValuesOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &CapsuleShapeConfiguration::m_radius, "Radius", "The radius of the capsule")
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
->Attribute(AZ::Edit::Attributes::Step, 0.01f)
->Attribute(AZ::Edit::Attributes::ChangeNotify, &CapsuleShapeConfiguration::OnRadiusChanged)
->Attribute(AZ::Edit::Attributes::ChangeNotify, AZ::Edit::PropertyRefreshLevels::ValuesOnly)
;
}
}
}
CapsuleShapeConfiguration::CapsuleShapeConfiguration(float height, float radius)
: m_height(height)
, m_radius(radius)
{
}
void CapsuleShapeConfiguration::OnHeightChanged()
{
// check that the height is greater than twice the radius
m_height = AZ::GetMax(m_height, 2 * m_radius + AZ::Constants::FloatEpsilon);
}
void CapsuleShapeConfiguration::OnRadiusChanged()
{
// check that the radius is less than half the height
m_radius = AZ::GetMin(m_radius, (0.5f - AZ::Constants::FloatEpsilon) * m_height);
}
void PhysicsAssetShapeConfiguration::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext
->RegisterGenericType<AZStd::shared_ptr<PhysicsAssetShapeConfiguration>>();
serializeContext->Class<PhysicsAssetShapeConfiguration, ShapeConfiguration>()
->Version(2, &Internal::ShapeConfigurationVersionConverter)
->Field("PhysicsAsset", &PhysicsAssetShapeConfiguration::m_asset)
->Field("AssetScale", &PhysicsAssetShapeConfiguration::m_assetScale)
->Field("SubdivisionLevel", &PhysicsAssetShapeConfiguration::m_subdivisionLevel)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<PhysicsAssetShapeConfiguration>("PhysicsAssetShapeConfiguration", "Configuration for asset shape collider")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &PhysicsAssetShapeConfiguration::m_assetScale, "Asset Scale", "The scale of the asset shape")
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
->Attribute(AZ::Edit::Attributes::Step, 0.01f)
;
}
}
}
Physics::ShapeType PhysicsAssetShapeConfiguration::GetShapeType() const
{
return ShapeType::PhysicsAsset;
}
void NativeShapeConfiguration::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext
->RegisterGenericType<AZStd::shared_ptr<NativeShapeConfiguration>>();
serializeContext->Class<NativeShapeConfiguration, ShapeConfiguration>()
->Version(1)
->Field("Scale", &NativeShapeConfiguration::m_nativeShapeScale)
;
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<NativeShapeConfiguration>("NativeShapeConfiguration", "Configuration for native shape collider")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &NativeShapeConfiguration::m_nativeShapeScale, "Scale", "The scale of the native shape")
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
->Attribute(AZ::Edit::Attributes::Step, 0.01f)
;
}
}
}
void CookedMeshShapeConfiguration::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext
->RegisterGenericType<AZStd::shared_ptr<CookedMeshShapeConfiguration>>();
serializeContext->Class<CookedMeshShapeConfiguration, ShapeConfiguration>()
->Version(1)
->Field("CookedData", &CookedMeshShapeConfiguration::m_cookedData)
->Field("Type", &CookedMeshShapeConfiguration::m_type)
;
}
}
CookedMeshShapeConfiguration::~CookedMeshShapeConfiguration()
{
ReleaseCachedNativeMesh();
}
CookedMeshShapeConfiguration::CookedMeshShapeConfiguration(const CookedMeshShapeConfiguration& other)
: ShapeConfiguration(other)
, m_cookedData(other.m_cookedData)
, m_type(other.m_type)
, m_cachedNativeMesh(nullptr)
{
}
CookedMeshShapeConfiguration& CookedMeshShapeConfiguration::operator=(const CookedMeshShapeConfiguration& other)
{
ShapeConfiguration::operator=(other);
m_cookedData = other.m_cookedData;
m_type = other.m_type;
// Prevent raw pointer from being copied
m_cachedNativeMesh = nullptr;
return *this;
}
ShapeType CookedMeshShapeConfiguration::GetShapeType() const
{
return ShapeType::CookedMesh;
}
void CookedMeshShapeConfiguration::SetCookedMeshData(const AZ::u8* cookedData,
size_t cookedDataSize, MeshType type)
{
// If the new cooked data is being set, make sure we clear the cached mesh
ReleaseCachedNativeMesh();
m_cookedData.clear();
m_cookedData.insert(m_cookedData.end(), cookedData, cookedData + cookedDataSize);
m_type = type;
}
const AZStd::vector<AZ::u8>& CookedMeshShapeConfiguration::GetCookedMeshData() const
{
return m_cookedData;
}
CookedMeshShapeConfiguration::MeshType CookedMeshShapeConfiguration::GetMeshType() const
{
return m_type;
}
void* CookedMeshShapeConfiguration::GetCachedNativeMesh() const
{
return m_cachedNativeMesh;
}
void CookedMeshShapeConfiguration::SetCachedNativeMesh(void* cachedNativeMesh) const
{
m_cachedNativeMesh = cachedNativeMesh;
}
void CookedMeshShapeConfiguration::ReleaseCachedNativeMesh()
{
if (m_cachedNativeMesh)
{
Physics::SystemRequestBus::Broadcast(
&Physics::SystemRequests::ReleaseNativeMeshObject, m_cachedNativeMesh);
m_cachedNativeMesh = nullptr;
}
}
}