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.
This commit is contained in:
Aaron Ruiz Mora
2021-05-28 20:16:25 +01:00
committed by GitHub
parent ff9a052ce6
commit 00e860f326
54 changed files with 859 additions and 943 deletions
@@ -42,6 +42,7 @@ class TestAutomation(TestAutomationBase):
self._run_test(request, workspace, editor, test_module)
@revert_physics_config
@fm.file_override('physxsystemconfiguration.setreg','C4044459_Material_DynamicFriction.setreg_override', 'AutomatedTesting/Registry')
def test_C4044459_Material_DynamicFriction(self, request, workspace, editor, launcher_platform):
from . import C4044459_Material_DynamicFriction as test_module
self._run_test(request, workspace, editor, test_module)
@@ -119,6 +119,9 @@
]
}
},
"DefaultMaterial": {
"SurfaceType": "Default_1"
},
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
@@ -0,0 +1,118 @@
{
"Amazon": {
"Gems": {
"PhysX": {
"PhysXSystemConfiguration": {
"CollisionConfig": {
"Layers": {
"LayerNames": [
"Default",
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
{},
"TouchBend"
]
},
"Groups": {
"GroupPresets": [
{
"Name": "All",
"ReadOnly": true
},
{
"Id": {
"GroupId": "{CDB6B8D8-5CD0-40A8-874D-839B00A92EBB}"
},
"Name": "None",
"Group": {
"Mask": 0
},
"ReadOnly": true
},
{
"Id": {
"GroupId": "{22769429-5D46-429B-829A-0115239D9AAA}"
},
"Name": "All_NoTouchBend",
"Group": {
"Mask": 9223372036854775807
},
"ReadOnly": true
}
]
}
},
"DefaultMaterial": {
"SurfaceType": "Default_1"
},
"MaterialLibrary": {
"assetId": {
"guid": "{6AA79EE4-7EC3-5717-87AE-EDD7D886FD7F}"
},
"loadBehavior": "QueueLoad",
"assetHint": "levels/physics/c4044459_material_dynamicfriction/dynamic_friction.physmaterial"
}
}
}
}
}
}
@@ -107,6 +107,9 @@
]
}
},
"DefaultMaterial": {
"SurfaceType": "Default_1"
},
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
@@ -119,6 +119,9 @@
]
}
},
"DefaultMaterial": {
"SurfaceType": "Default_1"
},
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
@@ -119,6 +119,9 @@
]
}
},
"DefaultMaterial": {
"SurfaceType": "Default_1"
},
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
@@ -119,6 +119,9 @@
]
}
},
"DefaultMaterial": {
"SurfaceType": "Default_1"
},
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
@@ -101,6 +101,9 @@
]
}
},
"DefaultMaterial": {
"SurfaceType": "Default_1"
},
"MaterialLibrary": {
"assetId": {
"guid": "{3A055A3F-8CB7-5FEE-B437-EB365FACD0D4}"
@@ -1,18 +1,19 @@
<ObjectStream version="3">
<Class name="MaterialLibraryAsset" version="2" type="{9E366D8C-33BB-4825-9A1F-FA3ADBE11D0F}">
<Class name="Physics::MaterialLibraryAsset" version="2" type="{9E366D8C-33BB-4825-9A1F-FA3ADBE11D0F}">
<Class name="AssetData" field="BaseClass1" version="1" type="{AF3F7D32-1536-422A-89F3-A11E1F5B5A9C}"/>
<Class name="AZStd::vector" field="Properties" type="{A8E59F8C-2F9A-525A-B549-A9E197EB9632}">
<Class name="MaterialFromAssetConfiguration" field="element" version="1" type="{FBD76628-DE57-435E-BE00-6FFAE64DDF1D}">
<Class name="MaterialConfiguration" field="Configuration" version="2" type="{8807CAA1-AD08-4238-8FDB-2154ADD084A1}">
<Class name="AZStd::string" field="SurfaceType" value="" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="Physics::MaterialFromAssetConfiguration" field="element" version="1" type="{FBD76628-DE57-435E-BE00-6FFAE64DDF1D}">
<Class name="Physics::MaterialConfiguration" field="Configuration" version="3" type="{8807CAA1-AD08-4238-8FDB-2154ADD084A1}">
<Class name="AZStd::string" field="SurfaceType" value="Debug" type="{03AAAB3F-5C47-5A66-9EBC-D5FA4DB353C9}"/>
<Class name="float" field="DynamicFriction" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
<Class name="float" field="StaticFriction" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
<Class name="float" field="Restitution" value="0.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
<Class name="unsigned char" field="FrictionCombine" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/>
<Class name="unsigned char" field="RestitutionCombine" value="0" type="{72B9409A-7D1A-4831-9CFE-FCB3FADD3426}"/>
<Class name="float" field="Density" value="1000.0000000" type="{EA2C3E90-AFBE-44D4-A90D-FAAF79BAF93D}"/>
<Class name="Color" field="DebugColor" value="1.0000000 1.0000000 1.0000000 1.0000000" type="{7894072A-9050-4F0F-901B-34B1A0D29417}"/>
</Class>
<Class name="MaterialId" field="UID" version="1" type="{744CCE6C-9F69-4E2F-B950-DAB8514F870B}">
<Class name="Physics::MaterialId" field="UID" version="1" type="{744CCE6C-9F69-4E2F-B950-DAB8514F870B}">
<Class name="AZ::Uuid" field="MaterialId" value="{B072A405-BAFA-4B0A-9164-B3A424E642A9}" type="{E152C105-A133-4D03-BBF8-3D4B2FBA3E2A}"/>
</Class>
</Class>
@@ -259,11 +259,18 @@ namespace Physics
if (success)
{
success = success && dataElement.RemoveElementByName(AZ_CRC("MaterialId", 0x9360e002));
dataElement.RemoveElementByName(AZ_CRC("MaterialId", 0x9360e002));
success = success && (dataElement.FindElement(AZ_CRC("MaterialId", 0x9360e002)) < 0);
success = success && dataElement.AddElementWithData(context, "MaterialIds", AZStd::vector<Physics::MaterialId> { materialId });
}
}
if (success && dataElement.GetVersion() <= 2)
{
dataElement.RemoveElementByName(AZ_CRC_CE("Material"));
success = success && (dataElement.FindElement(AZ_CRC_CE("Material")) < 0);
}
return success;
}
} // namespace ClassConverters
@@ -58,9 +58,18 @@ namespace AzPhysics
//! When triggered will send the handle to the old Scene (after this call, the Handle will be invalid).
using OnSceneRemovedEvent = AZ::Event<AzPhysics::SceneHandle>;
//! Event that triggers when the default material library changes.
//! Event that triggers when the material library changes.
//! When triggered the event will send the Asset Id of the new material library.
using OnDefaultMaterialLibraryChangedEvent = AZ::Event<const AZ::Data::AssetId&>;
using OnMaterialLibraryChangedEvent = AZ::Event<const AZ::Data::AssetId&>;
enum class MaterialLibraryLoadErrorType : uint8_t
{
InvalidId,
ErrorLoading
};
//! Event that triggers when the default material library has loaded with errors.
using OnMaterialLibraryLoadErrorEvent = AZ::Event<MaterialLibraryLoadErrorType>;
//! Event that triggers when the default scene configuration changes.
//! When triggered the event will send the new default scene configuration.
@@ -39,6 +39,8 @@ namespace AzPhysics
->Field("ShapecastBufferSize", &SystemConfiguration::m_shapecastBufferSize)
->Field("OverlapBufferSize", &SystemConfiguration::m_overlapBufferSize)
->Field("CollisionConfig", &SystemConfiguration::m_collisionConfig)
->Field("DefaultMaterial", &SystemConfiguration::m_defaultMaterialConfiguration)
->Field("MaterialLibrary", &SystemConfiguration::m_materialLibraryAsset)
;
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
@@ -79,7 +81,9 @@ namespace AzPhysics
m_overlapBufferSize == other.m_overlapBufferSize &&
AZ::IsClose(m_maxTimestep, other.m_maxTimestep) &&
AZ::IsClose(m_fixedTimestep, other.m_fixedTimestep) &&
m_collisionConfig == other.m_collisionConfig
m_collisionConfig == other.m_collisionConfig &&
m_defaultMaterialConfiguration == other.m_defaultMaterialConfiguration &&
m_materialLibraryAsset == other.m_materialLibraryAsset
;
}
@@ -13,6 +13,7 @@
#include <AzCore/RTTI/RTTI.h>
#include <AzFramework/Physics/Configuration/CollisionConfiguration.h>
#include <AzFramework/Physics/Material.h>
namespace AZ
{
@@ -45,6 +46,9 @@ namespace AzPhysics
//! Each Physics Scene uses this as a base and will override as needed.
CollisionConfiguration m_collisionConfig;
Physics::MaterialConfiguration m_defaultMaterialConfiguration; //!< Default material parameters for the project.
AZ::Data::Asset<Physics::MaterialLibraryAsset> m_materialLibraryAsset = AZ::Data::AssetLoadBehavior::NoLoad; //!< Material Library exposed by the system component SystemBus API.
//! Controls whether the Physics System will self register to the TickBus and call StartSimulation / FinishSimulation on each Scene.
//! Disable this to manually control Physics Scene simulation logic.
bool m_autoManageSimulationUpdate = true;
@@ -49,10 +49,7 @@ namespace Physics
{
materialSelection->SetMaterialSlots(Physics::MaterialSelection::SlotsArray());
}
if (materialSelection->IsDefaultMaterialLibraryAsset())
{
materialSelection->SyncSelectionToMaterialLibrary();
}
materialSelection->SyncSelectionToMaterialLibrary();
}
};
@@ -122,6 +119,24 @@ namespace Physics
}
}
bool MaterialConfiguration::operator==(const MaterialConfiguration& other) const
{
return m_surfaceType == other.m_surfaceType &&
AZ::IsClose(m_dynamicFriction, other.m_dynamicFriction) &&
AZ::IsClose(m_staticFriction, other.m_staticFriction) &&
AZ::IsClose(m_restitution, other.m_restitution) &&
AZ::IsClose(m_density, other.m_density) &&
m_restitutionCombine == other.m_restitutionCombine &&
m_frictionCombine == other.m_frictionCombine &&
m_debugColor == other.m_debugColor
;
}
bool MaterialConfiguration::operator!=(const MaterialConfiguration& other) const
{
return !(*this == other);
}
AZ::Color MaterialConfiguration::GenerateDebugColor(const char* materialName)
{
static const AZ::Color colors[] =
@@ -191,51 +206,25 @@ namespace Physics
//////////////////////////////////////////////////////////////////////////
void MaterialLibraryAssetReflectionWrapper::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<Physics::MaterialLibraryAssetReflectionWrapper>()
->Version(1)
->Field("Asset", &MaterialLibraryAssetReflectionWrapper::m_asset)
;
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<Physics::MaterialLibraryAssetReflectionWrapper>("", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, "")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialLibraryAssetReflectionWrapper::m_asset, "Physics Material Library", "Physics Material Library")
->Attribute("EditButton", "")
;
}
}
}
//////////////////////////////////////////////////////////////////////////
void DefaultMaterialLibraryAssetReflectionWrapper::Reflect(AZ::ReflectContext* context)
void MaterialInfoReflectionWrapper::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<Physics::DefaultMaterialLibraryAssetReflectionWrapper>()
serializeContext->Class<Physics::MaterialInfoReflectionWrapper>()
->Version(1)
->Field("Asset", &DefaultMaterialLibraryAssetReflectionWrapper::m_asset)
->Field("DefaultMaterial", &MaterialInfoReflectionWrapper::m_defaultMaterialConfiguration)
->Field("Asset", &MaterialInfoReflectionWrapper::m_materialLibraryAsset)
;
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<Physics::DefaultMaterialLibraryAssetReflectionWrapper>("", "")
editContext->Class<Physics::MaterialInfoReflectionWrapper>("Physics Materials", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, "")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(AZ::Edit::UIHandlers::Default, &DefaultMaterialLibraryAssetReflectionWrapper::m_asset, "Default Physics Material Library", "Library to use by default")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialInfoReflectionWrapper::m_defaultMaterialConfiguration, "Default Physics Material", "Material used by default")
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialInfoReflectionWrapper::m_materialLibraryAsset, "Physics Material Library", "Library to use for the project")
->Attribute(AZ::Edit::Attributes::AllowClearAsset, false)
->Attribute("EditButton", "")
;
@@ -269,6 +258,17 @@ namespace Physics
}
}
bool MaterialFromAssetConfiguration::operator==(const MaterialFromAssetConfiguration& other) const
{
return m_configuration == other.m_configuration &&
m_id == other.m_id;
}
bool MaterialFromAssetConfiguration::operator!=(const MaterialFromAssetConfiguration& other) const
{
return !(*this == other);
}
//////////////////////////////////////////////////////////////////////////
bool MaterialLibraryAsset::GetDataForMaterialId(const MaterialId& materialId, MaterialFromAssetConfiguration& configuration) const
@@ -370,9 +370,8 @@ namespace Physics
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<Physics::MaterialSelection>()
->Version(2, &ClassConverters::MaterialSelectionConverter)
->Version(3, &ClassConverters::MaterialSelectionConverter)
->EventHandler<MaterialSelectionEventHandler>()
->Field("Material", &MaterialSelection::m_materialLibrary)
->Field("MaterialIds", &MaterialSelection::m_materialIdsAssignedToSlots)
;
@@ -381,14 +380,8 @@ namespace Physics
editContext->Class<Physics::MaterialSelection>("Physics Material", "Select physics material library and which materials to use for the object")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialSelection::m_materialLibrary, "Library", "Physics material library to use for this object")
->Attribute(AZ::Edit::Attributes::ContainerCanBeModified, true)
->Attribute("EditButton", "")
->Attribute("EditDescription", "Open in Asset Editor")
->Attribute(AZ::Edit::Attributes::DefaultAsset, &MaterialSelection::GetDefaultMaterialLibraryId)
->Attribute(AZ::Edit::Attributes::ChangeNotify, &MaterialSelection::OnMaterialLibraryChanged)
->DataElement(AZ::Edit::UIHandlers::Default, &MaterialSelection::m_materialIdsAssignedToSlots, "Mesh Surfaces", "Specify which Physics Material to use for each element of this object")
->ElementAttribute(Attributes::MaterialLibraryAssetId, &MaterialSelection::GetMaterialLibraryAssetId)
->ElementAttribute(Attributes::MaterialLibraryAssetId, &MaterialSelection::GetMaterialLibraryId)
->Attribute(AZ::Edit::Attributes::IndexedChildNameLabelOverride, &MaterialSelection::GetMaterialSlotLabel)
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->ElementAttribute(AZ::Edit::Attributes::ReadOnly, &MaterialSelection::AreMaterialSlotsReadOnly)
@@ -398,12 +391,6 @@ namespace Physics
}
}
AZ::u32 MaterialSelection::OnMaterialLibraryChanged()
{
SyncSelectionToMaterialLibrary();
return AZ::Edit::PropertyRefreshLevels::EntireTree;
}
AZStd::string MaterialSelection::GetMaterialSlotLabel(int index)
{
if (index < m_materialSlots.size())
@@ -425,28 +412,9 @@ namespace Physics
}
}
AZ::Data::AssetId MaterialSelection::GetMaterialLibraryAssetId() const
void MaterialSelection::OnMaterialLibraryChanged([[maybe_unused]] const AZ::Data::AssetId& defaultMaterialLibraryId)
{
return GetMaterialLibraryAsset().GetId();
}
const Physics::MaterialLibraryAsset* MaterialSelection::GetMaterialLibraryAssetData() const
{
return GetMaterialLibraryAsset().Get();
}
const AZStd::string& MaterialSelection::GetMaterialLibraryAssetHint() const
{
return m_materialLibrary.GetHint();
}
void MaterialSelection::OnDefaultMaterialLibraryChanged(const AZ::Data::AssetId& defaultMaterialLibraryId)
{
AZ_UNUSED(defaultMaterialLibraryId);
if (IsDefaultMaterialLibraryAsset())
{
OnMaterialLibraryChanged();
}
SyncSelectionToMaterialLibrary();
}
void MaterialSelection::SetSlotsReadOnly(bool readOnly)
@@ -454,45 +422,6 @@ namespace Physics
m_slotsReadOnly = readOnly;
}
bool MaterialSelection::IsMaterialLibraryValid() const
{
if (GetMaterialLibraryAssetId().IsValid())
{
auto materialAsset = LoadAsset();
const auto& materialsData = materialAsset.Get()->GetMaterialsData();
if (materialsData.size() != 0)
{
return true;
}
}
return false;
}
bool MaterialSelection::GetMaterialConfiguration(Physics::MaterialFromAssetConfiguration& configuration, const Physics::MaterialId& materialId) const
{
if (IsMaterialLibraryValid())
{
auto materialAsset = LoadAsset();
if (materialAsset.Get())
{
return materialAsset.Get()->GetDataForMaterialId(materialId, configuration);
}
}
return false;
}
void MaterialSelection::SetMaterialLibrary(const AZ::Data::AssetId& assetId)
{
m_materialLibrary = AZ::Data::AssetManager::Instance().GetAsset<Physics::MaterialLibraryAsset>(assetId, m_materialLibrary.GetAutoLoadBehavior());
m_materialLibrary.BlockUntilLoadComplete();
}
void MaterialSelection::ResetToDefaultMaterialLibrary()
{
m_materialLibrary = {};
}
void MaterialSelection::SetMaterialSlots(const SlotsArray& slots)
{
if (slots.empty())
@@ -533,74 +462,45 @@ namespace Physics
m_materialIdsAssignedToSlots[slotIndex] = materialId;
}
AZ::Data::Asset<Physics::MaterialLibraryAsset> MaterialSelection::LoadAsset() const
{
AZ::Data::Asset<MaterialLibraryAsset> asset = AZ::Data::AssetManager::Instance()
.GetAsset<Physics::MaterialLibraryAsset>(GetMaterialLibraryAssetId(), AZ::Data::AssetLoadBehavior::Default);
asset.BlockUntilLoadComplete();
return asset;
}
void MaterialSelection::SyncSelectionToMaterialLibrary()
{
if (GetMaterialLibraryAssetId().IsValid())
auto* materialLibrary = GetMaterialLibrary().Get();
if (!materialLibrary)
{
auto materialLibraryAsset = AZ::Data::AssetManager::Instance().GetAsset<Physics::MaterialLibraryAsset>(GetMaterialLibraryAssetId(), AZ::Data::AssetLoadBehavior::Default);
return;
}
materialLibraryAsset.BlockUntilLoadComplete();
// We try to check whether existing selection matches any materials in the newly assigned library and do one of the following:
// 1. If previous MaterialId is invalid for this material library, and it is not the Default material, we set it to the Default material from the library.
// 2. If it's valid, or it is the Default material, we don't change it (useful when user accidentally re-assigns the same library: previous selection won't go away).
if (materialLibraryAsset.Get())
for (Physics::MaterialId& materialId : m_materialIdsAssignedToSlots)
{
// Leave nulls (default) unchanged.
if (materialId.IsNull())
{
for (Physics::MaterialId& materialId : m_materialIdsAssignedToSlots)
{
if (!materialLibraryAsset.Get()->HasDataForMaterialId(materialId)
&& !materialId.IsNull()) // Null materialId is the Default material.
{
materialId = MaterialId();
}
}
continue;
}
else
// If the material id is not present in the library anymore, set it to default
if (!materialLibrary->HasDataForMaterialId(materialId))
{
AZ_Warning("PhysX", false, "MaterialSelection: invalid material library");
materialId = MaterialId();
}
}
}
const AZ::Data::Asset<Physics::MaterialLibraryAsset>& MaterialSelection::GetMaterialLibraryAsset() const
{
if (IsDefaultMaterialLibraryAsset())
{
const AZ::Data::Asset<Physics::MaterialLibraryAsset>& defaultMaterialLibrary = GetDefaultMaterialLibrary();
return defaultMaterialLibrary;
}
return m_materialLibrary;
}
bool MaterialSelection::IsDefaultMaterialLibraryAsset() const
{
return !m_materialLibrary.GetId().IsValid();
}
const AZ::Data::Asset<Physics::MaterialLibraryAsset>& MaterialSelection::GetDefaultMaterialLibrary()
const AZ::Data::Asset<Physics::MaterialLibraryAsset>& MaterialSelection::GetMaterialLibrary()
{
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
{
return physicsSystem->GetDefaultMaterialLibrary();
if (const auto* physicsConfiguration = physicsSystem->GetConfiguration())
{
return physicsConfiguration->m_materialLibraryAsset;
}
}
return s_invalidMaterialLibrary;
}
const AZ::Data::AssetId& MaterialSelection::GetDefaultMaterialLibraryId()
const AZ::Data::AssetId& MaterialSelection::GetMaterialLibraryId()
{
return GetDefaultMaterialLibrary().GetId();
return GetMaterialLibrary().GetId();
}
bool MaterialSelection::AreMaterialSlotsReadOnly() const
@@ -29,7 +29,6 @@ namespace Physics
/// =========================
/// This is the interface to the wrapper around native material type (such as PxMaterial in PhysX gem)
/// that stores extra metadata, like Surface Type name.
/// To see more details about PhysX implementation please refer to PhysX::Material class
///
/// Usage example
/// -------------------------
@@ -37,14 +36,7 @@ namespace Physics
///
/// Physics::MaterialConfiguration materialProperties;
/// AZStd::shared_ptr<Physics::Material> newMaterial = AZ::Interface<Physics::System>::Get()->CreateMaterial(materialProperties);
///
/// To get PxMaterial use GetNativePointer function
///
/// physx::PxMaterial* material = static_cast<physx::PxMaterial*>(newMaterial->GetNativePointer());
///
/// You can use retrieved PxMaterial pointer on its own, provided you increment its reference count.
/// If this class goes out of scope, the PxMaterial pointer will be valid, but its userData
/// will be cleaned up to point to nullptr.
///
class Material
{
public:
@@ -63,9 +55,9 @@ namespace Physics
/// Returns AZ::Crc32 of the surface name.
virtual AZ::Crc32 GetSurfaceType() const = 0;
virtual void SetSurfaceType(AZ::Crc32 surfaceType) = 0;
virtual const AZStd::string& GetSurfaceTypeName() const = 0;
virtual void SetSurfaceTypeName(const AZStd::string& surfaceTypeName) = 0;
virtual float GetDynamicFriction() const = 0;
virtual void SetDynamicFriction(float dynamicFriction) = 0;
@@ -85,6 +77,9 @@ namespace Physics
virtual float GetDensity() const = 0;
virtual void SetDensity(float density) = 0;
virtual AZ::Color GetDebugColor() const = 0;
virtual void SetDebugColor(const AZ::Color& debugColor) = 0;
/// If the name of this material matches the name of one of the CrySurface types, it will return its CrySurface Id.\n
/// If there's no match it will return default CrySurface Id.\n
/// CrySurface types are defined in libs/materialeffects/surfacetypes.xml
@@ -122,6 +117,10 @@ namespace Physics
Material::CombineMode m_frictionCombine = Material::CombineMode::Average;
AZ::Color m_debugColor = AZ::Colors::White;
bool operator==(const MaterialConfiguration& other) const;
bool operator!=(const MaterialConfiguration& other) const;
private:
static bool VersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement);
static AZ::Color GenerateDebugColor(const char* materialName);
@@ -147,6 +146,7 @@ namespace Physics
static MaterialId FromUUID(const AZ::Uuid& uuid);
bool IsNull() const { return m_id.IsNull(); }
bool operator==(const MaterialId& other) const { return m_id == other.m_id; }
bool operator!=(const MaterialId& other) const { return !(*this == other); }
const AZ::Uuid& GetUuid() const { return m_id; }
private:
@@ -166,6 +166,9 @@ namespace Physics
MaterialConfiguration m_configuration;
MaterialId m_id;
bool operator==(const MaterialFromAssetConfiguration& other) const;
bool operator!=(const MaterialFromAssetConfiguration& other) const;
};
/// An asset that holds a list of materials to be edited and assigned in Open 3D Engine Editor
@@ -222,40 +225,27 @@ namespace Physics
AZStd::vector<MaterialFromAssetConfiguration> m_materialLibrary;
};
/// The class is used to expose a MaterialLibraryAsset to Edit Context
/// The class is used to expose a default material and material library asset to Edit Context
/// =======================================================================
///
/// Since AZ::Data::Asset doesn't reflect the data to EditContext
/// we have to have a wrapper doing it.
class MaterialLibraryAssetReflectionWrapper
class MaterialInfoReflectionWrapper
{
public:
AZ_CLASS_ALLOCATOR(MaterialLibraryAssetReflectionWrapper, AZ::SystemAllocator, 0);
AZ_TYPE_INFO(Physics::MaterialLibraryAssetReflectionWrapper, "{3D2EF5DF-EFD0-47EB-B88F-3E6FE1FEE5B0}");
AZ_CLASS_ALLOCATOR(MaterialInfoReflectionWrapper, AZ::SystemAllocator, 0);
AZ_TYPE_INFO(Physics::MaterialInfoReflectionWrapper, "{02AB8CBC-D35B-4E0F-89BA-A96D94DAD4F9}");
static void Reflect(AZ::ReflectContext* context);
AZ::Data::Asset<Physics::MaterialLibraryAsset> m_asset =
Physics::MaterialConfiguration m_defaultMaterialConfiguration;
AZ::Data::Asset<Physics::MaterialLibraryAsset> m_materialLibraryAsset =
AZ::Data::AssetLoadBehavior::NoLoad;
};
/// Customized material library for use as default material library
class DefaultMaterialLibraryAssetReflectionWrapper : public Physics::MaterialLibraryAssetReflectionWrapper
{
public:
AZ_CLASS_ALLOCATOR(MaterialLibraryAssetReflectionWrapper, AZ::SystemAllocator, 0);
AZ_TYPE_INFO(Physics::DefaultMaterialLibraryAssetReflectionWrapper, "{02AB8CBC-D35B-4E0F-89BA-A96D94DAD4F9}");
static void Reflect(AZ::ReflectContext* context);
AZ::Data::Asset<Physics::MaterialLibraryAsset> m_asset =
AZ::Data::AssetLoadBehavior::NoLoad;
};
/// The class is used to store a MaterialLibraryAsset and a vector of MaterialIds selected from the library
/// The class is used to store a vector of MaterialIds selected from the library
/// =======================================================================
///
/// This class is used to store a reference to the library asset and user's
/// selection of the materials from this library.\n
/// It also reflects UI controls for assigning MaterialLibraryAsset and selecting a material from it.
/// This class is used to store the user's selection of the materials from this library.
/// You can reflect this class in EditorContext to provide UI for selecting materials
/// on any custom component or QWidget.
class MaterialSelection
@@ -269,27 +259,6 @@ namespace Physics
static void Reflect(AZ::ReflectContext* context);
/// Returns whether MaterialLibraryAsset assigned to this selection exists and valid. Attempts to load
/// the library if it's not loaded yet.
/// @return true if MaterialLibraryAsset has a valid AssetId, loaded and isn't empty
bool IsMaterialLibraryValid() const;
/// Looks up MaterialLibraryAsset for MaterialFromAssetConfiguration with MaterialId that is stored intrenally.
/// @param configuration contains material data if there is a material selected by user
/// and if it exists in the MaterialLibraryAsset
/// @param materialId MaterialId to retrieve MaterialFromAssetConfiguration for
/// @return true if lookup was successful.
bool GetMaterialConfiguration(Physics::MaterialFromAssetConfiguration& configuration, const Physics::MaterialId& materialId) const;
/// Sets and loads MaterialLibraryAsset with specified AssetId.
/// It is used to construct MaterialSelection at runtime.
/// It is not a typical use case and mostly needed to convert legacy entities and auto-generate material libraries
/// @param assetId AssetId to create MaterialLibraryAsset with
void SetMaterialLibrary(const AZ::Data::AssetId& assetId);
/// Sets the material library to none, this will cause to use the project-wide default material library
void ResetToDefaultMaterialLibrary();
/// Sets an array of material slots to pick MaterialIds for. Having multiple slots is required for assigning multiple materials on a mesh
/// or heightfield object. SlotsArray can be empty and in this case Default slot will be created.
/// @param slots Array of names for slots. Can be empty, in this case Default slot will be created
@@ -298,48 +267,34 @@ namespace Physics
/// Returns a list of MaterialId that were assigned for each corresponding slot.
const AZStd::vector<Physics::MaterialId>& GetMaterialIdsAssignedToSlots() const;
/// Sets the MaterialId from MaterialLibraryAsset as the selected material at a specific slotIndex.
/// @param materialId MaterialId that user selected from the MaterialLibraryAsset
/// @param slotIndex index of the slot to set MaterialId for
/// Sets the MaterialId as the selected material at a specific slotIndex.
/// @param materialId MaterialId that user selected
/// @param slotIndex Index of the slot to set the MaterialId
void SetMaterialId(const Physics::MaterialId& materialId, int slotIndex = 0);
/// Returns the material library asset id.
AZ::Data::AssetId GetMaterialLibraryAssetId() const;
/// Returns the material id assigned to this selection at a specific slotIndex.
/// @param slotIndex index of the slot to retrieve MaterialId for
/// @param slotIndex Index of the slot to retrieve the MaterialId
Physics::MaterialId GetMaterialId(int slotIndex = 0) const;
/// Returns the material library asset.
const Physics::MaterialLibraryAsset* GetMaterialLibraryAssetData() const;
/// Returns the material library asset hint(UI display string)
const AZStd::string& GetMaterialLibraryAssetHint() const;
/// Called when the material library has changed
void OnDefaultMaterialLibraryChanged(const AZ::Data::AssetId& defaultMaterialLibraryId);
void OnMaterialLibraryChanged(const AZ::Data::AssetId& defaultMaterialLibraryId);
/// Set if the material slots are editable in the edit context
void SetSlotsReadOnly(bool readOnly);
private:
AZ::Data::Asset<Physics::MaterialLibraryAsset> m_materialLibrary { AZ::Data::AssetLoadBehavior::NoLoad };
AZStd::vector<Physics::MaterialId> m_materialIdsAssignedToSlots;
SlotsArray m_materialSlots;
bool m_slotsReadOnly = false;
const AZ::Data::Asset<Physics::MaterialLibraryAsset>& GetMaterialLibraryAsset() const;
AZ::Data::Asset<Physics::MaterialLibraryAsset> LoadAsset() const;
bool IsDefaultMaterialLibraryAsset() const;
void SyncSelectionToMaterialLibrary();
static const AZ::Data::Asset<Physics::MaterialLibraryAsset>& GetDefaultMaterialLibrary();
static const AZ::Data::AssetId& GetDefaultMaterialLibraryId();
static const AZ::Data::Asset<Physics::MaterialLibraryAsset>& GetMaterialLibrary();
static const AZ::Data::AssetId& GetMaterialLibraryId();
bool AreMaterialSlotsReadOnly() const;
// EditorContext callbacks
AZ::u32 OnMaterialLibraryChanged();
AZStd::string GetMaterialSlotLabel(int index);
};
@@ -25,21 +25,26 @@ namespace Physics
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single; // Implemented by sole owner of materials, e.g. class MaterialManager in PhysX gem.
/// Get default material
/// Get default material.
virtual AZStd::shared_ptr<Physics::Material> GetGenericDefaultMaterial() = 0;
/// Returns weak pointers to physics materials.
/// Connect to PhysicsMaterialNotifications::MaterialsReleased to be informed when material pointers are deleted by owner.
virtual void GetMaterials(const MaterialSelection& materialSelection
, AZStd::vector<AZStd::weak_ptr<Physics::Material>>& outMaterials) = 0;
, AZStd::vector<AZStd::shared_ptr<Physics::Material>>& outMaterials) = 0;
/// Returns a weak pointer to physics material with the given id.
virtual AZStd::shared_ptr<Physics::Material> GetMaterialById(Physics::MaterialId id) = 0;
/// Returns a weak pointer to physics material with the given name.
virtual AZStd::weak_ptr<Physics::Material> GetMaterialByName(const AZStd::string& name) = 0;
virtual AZStd::shared_ptr<Physics::Material> GetMaterialByName(const AZStd::string& name) = 0;
/// Returns index of the first selected material in MaterialSelection's material library.
/// A MaterialSelection can contain multiple material selections.
/// Returned index is 0-based where 0 is the Default material, and materials from the material library are 1 and onwards.
virtual AZ::u32 GetFirstSelectedMaterialIndex(const MaterialSelection& materialSelection) = 0;
/// Updates the material selection from the physics asset or sets it to default if there's no asset provided.
/// @param shapeConfiguration The shape information that contains the physics asset.
/// @param materialSelection The material selection to update.
virtual void UpdateMaterialSelectionFromPhysicsAsset(
const ShapeConfiguration& shapeConfiguration,
MaterialSelection& materialSelection) = 0;
};
using PhysicsMaterialRequestBus = AZ::EBus<PhysicsMaterialRequests>;
@@ -130,13 +130,6 @@ namespace AzPhysics
//! @param forceReinitialization Flag to force a reinitialization of the physics system. Default false.
virtual void UpdateConfiguration(const SystemConfiguration* newConfig, bool forceReinitialization = false) = 0;
//! Update the default material library.
//! @param materialLibrary The new material library asset to use.
virtual void UpdateDefaultMaterialLibrary(const AZ::Data::Asset<Physics::MaterialLibraryAsset>& materialLibrary) = 0;
//! Accessor to get the current Material Library. This is also available in the PhysXSystemConfiguration.
virtual const AZ::Data::Asset<Physics::MaterialLibraryAsset>& GetDefaultMaterialLibrary() const = 0;
//! Update the current default scene configuration.
//! This is the configuration used to to create scenes without a custom configuration.
//! @param sceneConfiguration The new configuration to apply.
@@ -169,9 +162,12 @@ namespace AzPhysics
//! Register to receive notifications when the SystemConfiguration changes.
//! @param handler The handler to receive the event.
void RegisterSystemConfigurationChangedEvent(SystemEvents::OnConfigurationChangedEvent::Handler& handler) { handler.Connect(m_configChangeEvent); }
//! Register a handler to receive an event when the default material library changes.
//! Register a handler to receive an event when the material library changes.
//! @param handler The handler to receive the event.
void RegisterOnDefaultMaterialLibraryChangedEventHandler(SystemEvents::OnDefaultMaterialLibraryChangedEvent::Handler& handler) { handler.Connect(m_onDefaultMaterialLibraryChangedEvent); }
void RegisterOnMaterialLibraryChangedEventHandler(SystemEvents::OnMaterialLibraryChangedEvent::Handler& handler) { handler.Connect(m_onMaterialLibraryChangedEvent); }
//! Register a handler to receive an event when the material library fails to load on startup.
//! @param handler The handler to receive the event.
void RegisterOnMaterialLibraryLoadErrorEventHandler(SystemEvents::OnMaterialLibraryLoadErrorEvent::Handler& handler) { handler.Connect(m_onMaterialLibraryLoadErrorEvent); }
//! Register a handler to receive an event when the default SceneConfiguration changes.
//! @param handler The handler to receive the event.
void RegisterOnDefaultSceneConfigurationChangedEventHandler(SystemEvents::OnDefaultSceneConfigurationChangedEvent::Handler& handler) { handler.Connect(m_onDefaultSceneConfigurationChangedEvent); }
@@ -185,7 +181,8 @@ namespace AzPhysics
SystemEvents::OnSceneAddedEvent m_sceneAddedEvent;
SystemEvents::OnSceneRemovedEvent m_sceneRemovedEvent;
SystemEvents::OnConfigurationChangedEvent m_configChangeEvent;
SystemEvents::OnDefaultMaterialLibraryChangedEvent m_onDefaultMaterialLibraryChangedEvent;
SystemEvents::OnMaterialLibraryChangedEvent m_onMaterialLibraryChangedEvent;
SystemEvents::OnMaterialLibraryLoadErrorEvent m_onMaterialLibraryLoadErrorEvent;
SystemEvents::OnDefaultSceneConfigurationChangedEvent m_onDefaultSceneConfigurationChangedEvent;
};
} // namespace AzPhysics
@@ -17,6 +17,21 @@
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))
@@ -166,10 +181,9 @@ namespace Physics
->RegisterGenericType<AZStd::shared_ptr<PhysicsAssetShapeConfiguration>>();
serializeContext->Class<PhysicsAssetShapeConfiguration, ShapeConfiguration>()
->Version(1)
->Version(2, &Internal::ShapeConfigurationVersionConverter)
->Field("PhysicsAsset", &PhysicsAssetShapeConfiguration::m_asset)
->Field("AssetScale", &PhysicsAssetShapeConfiguration::m_assetScale)
->Field("UseMaterialsFromAsset", &PhysicsAssetShapeConfiguration::m_useMaterialsFromAsset)
->Field("SubdivisionLevel", &PhysicsAssetShapeConfiguration::m_subdivisionLevel)
;
@@ -182,7 +196,6 @@ namespace Physics
->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)
->DataElement(AZ::Edit::UIHandlers::Default, &PhysicsAssetShapeConfiguration::m_useMaterialsFromAsset, "Physics Materials from Mesh", "Auto-set physics materials using Mesh's material surfaces names")
;
}
}
@@ -140,7 +140,7 @@ namespace Physics
AZ::Data::Asset<AZ::Data::AssetData> m_asset{ AZ::Data::AssetLoadBehavior::PreLoad };
AZ::Vector3 m_assetScale = AZ::Vector3::CreateOne();
bool m_useMaterialsFromAsset = true;
bool m_useMaterialsFromAsset = false; // Not reflected or exposed to the user until there is a way to auto-match mesh's materials with physics materials
AZ::u8 m_subdivisionLevel = 4; ///< The level of subdivision if a primitive shape is replaced with a convex mesh due to scaling.
};
@@ -142,24 +142,12 @@ namespace Physics
virtual AZStd::shared_ptr<Shape> CreateShape(const ColliderConfiguration& colliderConfiguration, const ShapeConfiguration& configuration) = 0;
virtual AZStd::shared_ptr<Material> CreateMaterial(const Physics::MaterialConfiguration& materialConfiguration) = 0;
/// Releases the mesh object created by the physics backend.
/// @param nativeMeshObject Pointer to the mesh object.
virtual void ReleaseNativeMeshObject(void* nativeMeshObject) = 0;
//////////////////////////////////////////////////////////////////////////
//// Physics Materials
virtual AZStd::shared_ptr<Material> CreateMaterial(const Physics::MaterialConfiguration& materialConfiguration) = 0;
virtual AZStd::shared_ptr<Material> GetDefaultMaterial() = 0;
virtual AZStd::vector<AZStd::shared_ptr<Material>> CreateMaterialsFromLibrary(const Physics::MaterialSelection& materialSelection) = 0;
/// Updates the collider material selection from the physics asset or sets it to default if there's no asset provided.
/// @param shapeConfiguration The shape information
/// @param colliderConfiguration The collider information
virtual bool UpdateMaterialSelection(const Physics::ShapeConfiguration& shapeConfiguration,
Physics::ColliderConfiguration& colliderConfiguration) = 0;
//////////////////////////////////////////////////////////////////////////
//// Joints
@@ -119,8 +119,7 @@ namespace Physics
AzPhysics::SceneConfiguration::Reflect(context);
MaterialConfiguration::Reflect(context);
MaterialLibraryAsset::Reflect(context);
MaterialLibraryAssetReflectionWrapper::Reflect(context);
DefaultMaterialLibraryAssetReflectionWrapper::Reflect(context);
MaterialInfoReflectionWrapper::Reflect(context);
JointLimitConfiguration::Reflect(context);
AzPhysics::SimulatedBodyConfiguration::Reflect(context);
AzPhysics::RigidBodyConfiguration::Reflect(context);
@@ -151,8 +151,6 @@ namespace Blast
colliderConfiguration.m_position = transform.GetTranslation();
colliderConfiguration.m_rotation = transform.GetRotation();
colliderConfiguration.m_isExclusive = true;
colliderConfiguration.m_materialSelection.SetMaterialLibrary(
AZ::Interface<AzPhysics::SystemInterface>::Get()->GetDefaultMaterialLibrary()->GetId());
colliderConfiguration.m_materialSelection.SetMaterialId(material);
colliderConfiguration.m_collisionGroupId = actorConfiguration.m_collisionGroupId;
colliderConfiguration.m_collisionLayer = actorConfiguration.m_collisionLayer;
@@ -21,6 +21,7 @@
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzFramework/Physics/PhysicsSystem.h>
#include <AzFramework/Physics/SystemBus.h>
#include <AzFramework/Physics/MaterialBus.h>
#include <AzFramework/Physics/Collision/CollisionEvents.h>
#include <AzFramework/Physics/Common/PhysicsTypes.h>
#include <Blast/BlastActor.h>
@@ -265,10 +266,23 @@ namespace Blast
auto solverPtr = Nv::Blast::ExtStressSolver::create(
const_cast<NvBlastFamily&>(*m_family->GetTkFamily()->getFamilyLL()), stressSolverSettings);
m_solver = physx::unique_ptr<Nv::Blast::ExtStressSolver>(solverPtr);
Physics::MaterialFromAssetConfiguration material;
AZ::Interface<AzPhysics::SystemInterface>::Get()->GetDefaultMaterialLibrary()->GetDataForMaterialId(
m_physicsMaterialId, material);
m_solver->setAllNodesInfoFromLL(material.m_configuration.m_density);
AZStd::shared_ptr<Physics::Material> physicsMaterial;
Physics::PhysicsMaterialRequestBus::BroadcastResult(
physicsMaterial,
&Physics::PhysicsMaterialRequestBus::Events::GetMaterialById,
m_physicsMaterialId);
if (!physicsMaterial)
{
AZ_Warning("BlastFamilyComponent", false, "Material Id %s was not found, using default material instead.",
m_physicsMaterialId.GetUuid().ToString<AZStd::string>().c_str());
Physics::PhysicsMaterialRequestBus::BroadcastResult(
physicsMaterial,
&Physics::PhysicsMaterialRequestBus::Events::GetGenericDefaultMaterial);
AZ_Assert(physicsMaterial, "BlastFamilyComponent: Invalid default physics material");
}
m_solver->setAllNodesInfoFromLL(physicsMaterial->GetDensity());
// Create damage and actor render managers
m_damageManager = AZStd::make_unique<DamageManager>(blastMaterial, m_family->GetActorTracker());
@@ -131,6 +131,6 @@ namespace Blast
AZ::Data::AssetId EditorBlastFamilyComponent::GetPhysicsMaterialLibraryAssetId() const
{
return AZ::Interface<AzPhysics::SystemInterface>::Get()->GetDefaultMaterialLibrary()->GetId();
return AZ::Interface<AzPhysics::SystemInterface>::Get()->GetConfiguration()->m_materialLibraryAsset.GetId();
}
} // namespace Blast
@@ -35,9 +35,6 @@ namespace Physics
MOCK_METHOD2(CreateShape, AZStd::shared_ptr<Physics::Shape>(const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& configuration));
MOCK_METHOD1(ReleaseNativeMeshObject, void(void* nativeMeshObject));
MOCK_METHOD1(CreateMaterial, AZStd::shared_ptr<Physics::Material>(const Physics::MaterialConfiguration& materialConfiguration));
MOCK_METHOD0(GetDefaultMaterial, AZStd::shared_ptr<Physics::Material>());
MOCK_METHOD1(CreateMaterialsFromLibrary, AZStd::vector<AZStd::shared_ptr<Physics::Material>>(const Physics::MaterialSelection& materialSelection));
MOCK_METHOD2(UpdateMaterialSelection, bool(const Physics::ShapeConfiguration& shapeConfiguration, Physics::ColliderConfiguration& colliderConfiguration));
MOCK_METHOD0(GetSupportedJointTypes, AZStd::vector<AZ::TypeId>());
MOCK_METHOD1(CreateJointLimitConfiguration, AZStd::shared_ptr<Physics::JointLimitConfiguration>(AZ::TypeId jointType));
MOCK_METHOD3(CreateJoint, AZStd::shared_ptr<Physics::Joint>(const AZStd::shared_ptr<Physics::JointLimitConfiguration>& configuration, AzPhysics::SimulatedBody* parentBody, AzPhysics::SimulatedBody* childBody));
@@ -59,7 +56,6 @@ namespace Physics
void Shutdown() override {}
void Simulate([[maybe_unused]] float deltaTime) override {}
void UpdateConfiguration([[maybe_unused]] const AzPhysics::SystemConfiguration* newConfig, [[maybe_unused]] bool forceReinitialization = false) override {}
void UpdateDefaultMaterialLibrary([[maybe_unused]] const AZ::Data::Asset<Physics::MaterialLibraryAsset>& materialLibrary) override {}
void UpdateDefaultSceneConfiguration([[maybe_unused]] const AzPhysics::SceneConfiguration& sceneConfiguration) override {}
void RemoveScene([[maybe_unused]] AzPhysics::SceneHandle handle) override {}
void RemoveScenes([[maybe_unused]] const AzPhysics::SceneHandleList& handles) override {}
@@ -73,7 +69,6 @@ namespace Physics
MOCK_METHOD0(GetAllScenes, AzPhysics::SceneList& ());
MOCK_METHOD1(FindAttachedBodyHandleFromEntityId, AZStd::pair<AzPhysics::SceneHandle, AzPhysics::SimulatedBodyHandle>(AZ::EntityId entityId));
MOCK_CONST_METHOD0(GetConfiguration, const AzPhysics::SystemConfiguration* ());
MOCK_CONST_METHOD0(GetDefaultMaterialLibrary, const AZ::Data::Asset<Physics::MaterialLibraryAsset>& ());
MOCK_CONST_METHOD0(GetDefaultSceneConfiguration, const AzPhysics::SceneConfiguration& ());
};
@@ -54,14 +54,11 @@ namespace EMotionFX
[[maybe_unused]] const AZ::Vector3& axis,
[[maybe_unused]] const AZStd::vector<AZ::Quaternion>& exampleLocalRotations)
{ return AZStd::make_unique<D6JointLimitConfiguration>(); });
EXPECT_CALL(m_physicsInterface, GetDefaultMaterialLibrary)
.WillRepeatedly(testing::ReturnRef(m_materialLibraryAsset));
}
private:
Physics::MockPhysicsSystem m_physicsSystem;
Physics::MockPhysicsInterface m_physicsInterface;
AZ::Data::Asset<Physics::MaterialLibraryAsset> m_materialLibraryAsset;
};
#if AZ_TRAIT_DISABLE_FAILED_EMOTION_FX_EDITOR_TESTS
@@ -59,9 +59,6 @@ namespace EMotionFX
.WillRepeatedly(testing::Return(AZStd::vector<AZ::TypeId>{azrtti_typeid<D6JointLimitConfiguration>()}));
EXPECT_CALL(physicsSystem, ComputeInitialJointLimitConfiguration(azrtti_typeid<D6JointLimitConfiguration>(), _, _, _, _))
.WillRepeatedly([]([[maybe_unused]] const AZ::TypeId& jointLimitTypeId, [[maybe_unused]] const AZ::Quaternion& parentWorldRotation, [[maybe_unused]] const AZ::Quaternion& childWorldRotation, [[maybe_unused]] const AZ::Vector3& axis, [[maybe_unused]] const AZStd::vector<AZ::Quaternion>& exampleLocalRotations) { return AZStd::make_unique<D6JointLimitConfiguration>(); });
AZ::Data::Asset<Physics::MaterialLibraryAsset> materialLibraryAsset;
EXPECT_CALL(physicsInterface, GetDefaultMaterialLibrary)
.WillRepeatedly(testing::ReturnRef(materialLibraryAsset));
AutoRegisteredActor actor {ActorFactory::CreateAndInit<SimpleJointChainActor>(4)};
+10 -5
View File
@@ -17,13 +17,13 @@
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/Component/TickBus.h>
#include <AzCore/Interface/Interface.h>
#include <AzFramework/Physics/MaterialBus.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <LyViewPaneNames.h>
#include <LmbrCentral/Geometry/GeometrySystemComponentBus.h>
#include <Source/Utils.h>
#include <PhysX/Configuration/PhysXConfiguration.h>
#include <System/PhysXSystem.h>
#include <PhysX/Debug/PhysXDebugInterface.h>
namespace PhysX
{
@@ -415,11 +415,16 @@ namespace PhysX
{
case GlobalCollisionDebugColorMode::MaterialColor:
{
Physics::MaterialFromAssetConfiguration materialConfiguration;
const Physics::MaterialId materialId = colliderConfig.m_materialSelection.GetMaterialId(elementDebugInfo.m_materialSlotIndex);
if (colliderConfig.m_materialSelection.GetMaterialConfiguration(materialConfiguration, materialId))
AZStd::shared_ptr<Physics::Material> physicsMaterial;
Physics::PhysicsMaterialRequestBus::BroadcastResult(
physicsMaterial,
&Physics::PhysicsMaterialRequestBus::Events::GetMaterialById,
materialId);
if (physicsMaterial)
{
debugColor = materialConfiguration.m_configuration.m_debugColor;
debugColor = physicsMaterial->GetDebugColor();
}
break;
}
+5 -3
View File
@@ -37,14 +37,15 @@ namespace PhysX
const Debug::DebugDisplayData& debugDisplayData)
{
m_physxSystemConfiguration = physxSystemConfiguration;
m_defaultPhysicsMaterialLibrary.m_asset = m_physxSystemConfiguration.m_defaultMaterialLibrary;
m_physicsMaterialInfo.m_defaultMaterialConfiguration = m_physxSystemConfiguration.m_defaultMaterialConfiguration;
m_physicsMaterialInfo.m_materialLibraryAsset = m_physxSystemConfiguration.m_materialLibraryAsset;
m_defaultSceneConfiguration = defaultSceneConfiguration;
m_debugDisplayData = debugDisplayData;
blockSignals(true);
m_propertyEditor->ClearInstances();
m_propertyEditor->AddInstance(&m_physxSystemConfiguration);
m_propertyEditor->AddInstance(&m_defaultPhysicsMaterialLibrary);
m_propertyEditor->AddInstance(&m_physicsMaterialInfo);
m_propertyEditor->AddInstance(&m_defaultSceneConfiguration);
m_propertyEditor->AddInstance(&m_debugDisplayData);
m_propertyEditor->AddInstance(&m_physxSystemConfiguration.m_windConfiguration);
@@ -88,7 +89,8 @@ namespace PhysX
void SettingsWidget::SetPropertyEditingComplete(AzToolsFramework::InstanceDataNode* /*node*/)
{
m_physxSystemConfiguration.m_defaultMaterialLibrary = m_defaultPhysicsMaterialLibrary.m_asset;
m_physxSystemConfiguration.m_defaultMaterialConfiguration = m_physicsMaterialInfo.m_defaultMaterialConfiguration;
m_physxSystemConfiguration.m_materialLibraryAsset = m_physicsMaterialInfo.m_materialLibraryAsset;
emit onValueChanged(m_physxSystemConfiguration,
m_defaultSceneConfiguration,
m_debugDisplayData
+1 -1
View File
@@ -56,7 +56,7 @@ namespace PhysX
AzToolsFramework::ReflectedPropertyEditor* m_propertyEditor;
DocumentationLinkWidget* m_documentationLinkWidget;
Physics::DefaultMaterialLibraryAssetReflectionWrapper m_defaultPhysicsMaterialLibrary;
Physics::MaterialInfoReflectionWrapper m_physicsMaterialInfo;
PhysX::PhysXSystemConfiguration m_physxSystemConfiguration;
AzPhysics::SceneConfiguration m_defaultSceneConfiguration;
Debug::DebugDisplayData m_debugDisplayData;
@@ -30,40 +30,45 @@
namespace PhysX
{
static bool CreateSurfaceTypeMaterialLibrary(const AZStd::string & targetFilePath)
constexpr const char* DefaultAssetFilename = "SurfaceTypeMaterialLibrary";
static AZStd::optional<AZ::Data::Asset<AZ::Data::AssetData>> CreateMaterialLibrary(const AZStd::string& fullTargetFilePath, const AZStd::string& relativePath)
{
auto assetType = AZ::AzTypeInfo<Physics::MaterialLibraryAsset>::Uuid();
// Create File
AZ::Data::Asset<AZ::Data::AssetData> newAsset = AZ::Data::AssetManager::Instance().CreateAsset(AZ::Uuid::CreateRandom(), assetType, AZ::Data::AssetLoadBehavior::Default);
AZ::IO::FileIOStream fileStream(targetFilePath.c_str(), AZ::IO::OpenMode::ModeWrite);
AZ::IO::FileIOStream fileStream(fullTargetFilePath.c_str(), AZ::IO::OpenMode::ModeWrite);
if (fileStream.IsOpen())
{
Physics::MaterialLibraryAsset* materialLibraryAsset = azrtti_cast<Physics::MaterialLibraryAsset*>(newAsset.GetData());
if (materialLibraryAsset)
const auto& assetType = AZ::AzTypeInfo<Physics::MaterialLibraryAsset>::Uuid();
AZ::Data::AssetId assetId;
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
assetId, &AZ::Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, relativePath.c_str(), assetType, true);
AZ::Data::Asset<AZ::Data::AssetData> newAsset =
AZ::Data::AssetManager::Instance().GetAsset(assetId, assetType, AZ::Data::AssetLoadBehavior::Default);
if (Physics::MaterialLibraryAsset* materialLibraryAsset = azrtti_cast<Physics::MaterialLibraryAsset*>(newAsset.GetData()))
{
// check it out in the source control system
AzToolsFramework::SourceControlCommandBus::Broadcast(
&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, targetFilePath.c_str(), true,
&AzToolsFramework::SourceControlCommandBus::Events::RequestEdit, fullTargetFilePath.c_str(), true,
[](bool /*success*/, const AzToolsFramework::SourceControlFileInfo& /*info*/) {});
// Save the material library asset into a file
auto assetHandler = const_cast<AZ::Data::AssetHandler*>(AZ::Data::AssetManager::Instance().GetHandler(assetType));
auto assetHandler = AZ::Data::AssetManager::Instance().GetHandler(assetType);
if (assetHandler->SaveAssetData(newAsset, &fileStream))
{
return true;
return newAsset;
}
else
{
AZ_Error("PhysX", false,
"CreateSurfaceTypeMaterialLibrary: Unable to save Surface Types Material Library Asset to %s",
targetFilePath.c_str());
fullTargetFilePath.c_str());
}
}
}
return false;
return AZStd::nullopt;
}
void EditorSystemComponent::Reflect(AZ::ReflectContext* context)
@@ -84,11 +89,26 @@ namespace PhysX
{
Physics::EditorWorldBus::Handler::BusConnect();
m_onMaterialLibraryLoadErrorEventHandler = AzPhysics::SystemEvents::OnMaterialLibraryLoadErrorEvent::Handler(
[this]([[maybe_unused]] AzPhysics::SystemEvents::MaterialLibraryLoadErrorType error)
{
// Attempt to set/create the default material library if there was an error
if (auto* physxSystem = GetPhysXSystem())
{
if (auto retrievedMaterialLibrary = RetrieveDefaultMaterialLibrary())
{
physxSystem->UpdateMaterialLibrary(retrievedMaterialLibrary.value());
}
}
}
);
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
{
AzPhysics::SceneConfiguration editorWorldConfiguration = physicsSystem->GetDefaultSceneConfiguration();
editorWorldConfiguration.m_sceneName = AzPhysics::EditorPhysicsSceneName;
m_editorWorldSceneHandle = physicsSystem->AddScene(editorWorldConfiguration);
physicsSystem->RegisterOnMaterialLibraryLoadErrorEventHandler(m_onMaterialLibraryLoadErrorEventHandler);
}
PhysX::RegisterConfigStringLineEditHandler(); // Register custom unique string line edit control
@@ -109,6 +129,8 @@ namespace PhysX
physicsSystem->RemoveScene(m_editorWorldSceneHandle);
}
m_editorWorldSceneHandle = AzPhysics::InvalidSceneHandle;
m_onMaterialLibraryLoadErrorEventHandler.Disconnect();
}
AzPhysics::SceneHandle EditorSystemComponent::GetEditorSceneHandle() const
@@ -148,7 +170,7 @@ namespace PhysX
PhysX::Editor::EditorWindow::RegisterViewClass();
}
AZ::Data::AssetId EditorSystemComponent::GenerateSurfaceTypesLibrary()
AZStd::optional<AZ::Data::Asset<AZ::Data::AssetData>> EditorSystemComponent::RetrieveDefaultMaterialLibrary()
{
AZ::Data::AssetId resultAssetId;
@@ -159,8 +181,6 @@ namespace PhysX
if (assetTypeExtensions.size() == 1)
{
const char* DefaultAssetFilename = "SurfaceTypeMaterialLibrary";
// Constructing the path to the library asset
const AZStd::string& assetExtension = assetTypeExtensions[0];
@@ -173,36 +193,39 @@ namespace PhysX
if (!resultAssetId.IsValid())
{
// No file for the default material library, create it
const char* assetRoot = AZ::IO::FileIOBase::GetInstance()->GetAlias("@devassets@");
AZStd::string fullPath;
AzFramework::StringFunc::Path::ConstructFull(assetRoot, DefaultAssetFilename, assetExtension.c_str(), fullPath);
if (CreateSurfaceTypeMaterialLibrary(fullPath))
if (auto materialLibraryOpt = CreateMaterialLibrary(fullPath, relativePath))
{
// Find out the asset ID for the material library we've just created
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
resultAssetId, &AZ::Data::AssetCatalogRequests::GetAssetIdByPath,
relativePath.c_str(),
azrtti_typeid<Physics::MaterialLibraryAsset>(), true);
return materialLibraryOpt;
}
else
{
AZ_Warning("PhysX", false,
"GenerateSurfaceTypesLibrary: Failed to create material library at %s. "
"CreateMaterialLibrary: Failed to create material library at %s. "
"Please check if the file is writable", fullPath.c_str());
}
}
else
{
AZ::Data::Asset<AZ::Data::AssetData> existingMaterialLibrary =
AZ::Data::AssetManager::Instance().GetAsset<Physics::MaterialLibraryAsset>(resultAssetId, AZ::Data::AssetLoadBehavior::NoLoad);
return existingMaterialLibrary;
}
}
else
{
AZ_Warning("PhysX", false,
"GenerateSurfaceTypesLibrary: Number of extensions for the physics material library asset is %u"
"RetrieveDefaultMaterialLibrary: Number of extensions for the physics material library asset is %u"
" but should be 1. Please check if the asset registered itself with the asset system correctly",
assetTypeExtensions.size())
}
return resultAssetId;
return AZStd::nullopt;
}
}
@@ -14,6 +14,7 @@
#include <AzCore/Component/Component.h>
#include <AzFramework/Physics/SystemBus.h>
#include <AzFramework/Physics/Common/PhysicsEvents.h>
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
namespace AzPhysics
@@ -65,8 +66,9 @@ namespace PhysX
void PopulateEditorGlobalContextMenu(QMenu* menu, const AZ::Vector2& point, int flags) override;
void NotifyRegisterViews() override;
AZ::Data::AssetId GenerateSurfaceTypesLibrary();
AZStd::optional<AZ::Data::Asset<AZ::Data::AssetData>> RetrieveDefaultMaterialLibrary();
AzPhysics::SystemEvents::OnMaterialLibraryLoadErrorEvent::Handler m_onMaterialLibraryLoadErrorEventHandler;
AzPhysics::SceneHandle m_editorWorldSceneHandle = AzPhysics::InvalidSceneHandle;
};
}
@@ -13,7 +13,6 @@
#pragma once
#include <AzCore/Asset/AssetCommon.h>
#include <AzCore/RTTI/RTTI.h>
#include <AzFramework/Physics/Material.h>
#include <AzFramework/Physics/Configuration/SystemConfiguration.h>
#include <PhysX/Debug/PhysXDebugConfiguration.h>
@@ -55,7 +54,6 @@ namespace PhysX
static PhysXSystemConfiguration CreateDefault();
WindConfiguration m_windConfiguration; //!< Wind configuration for PhysX.
AZ::Data::Asset<Physics::MaterialLibraryAsset> m_defaultMaterialLibrary = AZ::Data::AssetLoadBehavior::NoLoad; //!< Material Library exposed by the system component SystemBus API.
bool operator==(const PhysXSystemConfiguration& other) const;
bool operator!=(const PhysXSystemConfiguration& other) const;
@@ -38,10 +38,6 @@ namespace PhysX
/// @param id The asset ID to set it to.
virtual void SetMeshAsset(const AZ::Data::AssetId& id) = 0;
/// Sets the material library asset to the collider.
/// @param id The asset ID to set it to.
virtual void SetMaterialAsset(const AZ::Data::AssetId& id) = 0;
/// Sets the material id from the material library.
/// @param id The asset ID to set it to.
virtual void SetMaterialId(const Physics::MaterialId& id) = 0;
@@ -36,6 +36,18 @@ namespace PhysX
return configuration;
}
bool PhysXSystemConfigurationConverter([[maybe_unused]] AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& dataElement)
{
if (dataElement.GetVersion() <= 1)
{
dataElement.RemoveElementByName(AZ_CRC_CE("DefaultMaterialLibrary"));
AZ_Warning("PhysXSystemConfigurationConverter", false,
"Old version of PhysX Configuration data found. Physics material library will be reset to default.");
}
return true;
}
}
AZ_CLASS_ALLOCATOR_IMPL(WindConfiguration, AZ::SystemAllocator, 0);
@@ -89,9 +101,8 @@ namespace PhysX
if (auto* serializeContext = azdynamic_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<PhysX::PhysXSystemConfiguration, AzPhysics::SystemConfiguration>()
->Version(1)
->Version(2, &PhysXInternal::PhysXSystemConfigurationConverter)
->Field("WindConfiguration", &PhysXSystemConfiguration::m_windConfiguration)
->Field("MaterialLibrary", &PhysXSystemConfiguration::m_defaultMaterialLibrary)
;
if (AZ::EditContext* editContext = serializeContext->GetEditContext())
@@ -115,7 +126,6 @@ namespace PhysX
bool PhysXSystemConfiguration::operator==(const PhysXSystemConfiguration& other) const
{
return AzPhysics::SystemConfiguration::operator==(other) &&
m_defaultMaterialLibrary == other.m_defaultMaterialLibrary &&
m_windConfiguration == other.m_windConfiguration
;
}
@@ -17,7 +17,7 @@
#include <AzCore/std/smart_ptr/shared_ptr.h>
#include <AzFramework/Physics/ColliderComponentBus.h>
#include <AzFramework/Physics/SimulatedBodies/RigidBody.h>
#include <AzFramework/Physics/SystemBus.h>
#include <AzFramework/Physics/MaterialBus.h>
#include <AzFramework/Physics/Common/PhysicsSimulatedBody.h>
#include <AzFramework/Physics/Configuration/StaticRigidBodyConfiguration.h>
#include <AzFramework/Viewport/ViewportColors.h>
@@ -352,10 +352,13 @@ namespace PhysX
AzToolsFramework::PropertyModificationRefreshLevel::Refresh_AttributesAndValues);
});
m_onDefaultMaterialLibraryChangedEventHandler = AzPhysics::SystemEvents::OnDefaultMaterialLibraryChangedEvent::Handler(
m_onMaterialLibraryChangedEventHandler = AzPhysics::SystemEvents::OnMaterialLibraryChangedEvent::Handler(
[this](const AZ::Data::AssetId& defaultMaterialLibrary)
{
m_configuration.m_materialSelection.OnDefaultMaterialLibraryChanged(defaultMaterialLibrary);
m_configuration.m_materialSelection.OnMaterialLibraryChanged(defaultMaterialLibrary);
AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh,
AzToolsFramework::PropertyModificationRefreshLevel::Refresh_AttributesAndValues);
});
AzToolsFramework::Components::EditorComponentBase::Activate();
@@ -463,13 +466,13 @@ namespace PhysX
if (auto* physXSystem = GetPhysXSystem())
{
physXSystem->RegisterSystemConfigurationChangedEvent(m_physXConfigChangedHandler);
physXSystem->RegisterOnDefaultMaterialLibraryChangedEventHandler(m_onDefaultMaterialLibraryChangedEventHandler);
physXSystem->RegisterOnMaterialLibraryChangedEventHandler(m_onMaterialLibraryChangedEventHandler);
}
}
void EditorColliderComponent::OnDeselected()
{
m_onDefaultMaterialLibraryChangedEventHandler.Disconnect();
m_onMaterialLibraryChangedEventHandler.Disconnect();
m_physXConfigChangedHandler.Disconnect();
}
@@ -681,11 +684,6 @@ namespace PhysX
}
}
void EditorColliderComponent::SetMaterialAsset(const AZ::Data::AssetId& id)
{
m_configuration.m_materialSelection.SetMaterialLibrary(id);
}
void EditorColliderComponent::SetMaterialId(const Physics::MaterialId& id)
{
m_configuration.m_materialSelection.SetMaterialId(id);
@@ -693,8 +691,10 @@ namespace PhysX
void EditorColliderComponent::UpdateMaterialSlotsFromMeshAsset()
{
Physics::SystemRequestBus::Broadcast(&Physics::SystemRequests::UpdateMaterialSelection,
m_shapeConfiguration.GetCurrent(), m_configuration);
Physics::PhysicsMaterialRequestBus::Broadcast(
&Physics::PhysicsMaterialRequestBus::Events::UpdateMaterialSelectionFromPhysicsAsset,
m_shapeConfiguration.GetCurrent(),
m_configuration.m_materialSelection);
AzToolsFramework::ToolsApplicationEvents::Bus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree);
@@ -158,7 +158,6 @@ namespace PhysX
AZ::Data::Asset<Pipeline::MeshAsset> GetMeshAsset() const override;
Physics::MaterialId GetMaterialId() const override;
void SetMeshAsset(const AZ::Data::AssetId& id) override;
void SetMaterialAsset(const AZ::Data::AssetId& id) override;
void SetMaterialId(const Physics::MaterialId& id) override;
void UpdateMaterialSlotsFromMeshAsset();
@@ -251,7 +250,7 @@ namespace PhysX
DebugDraw::Collider m_colliderDebugDraw;
AzPhysics::SystemEvents::OnConfigurationChangedEvent::Handler m_physXConfigChangedHandler;
AzPhysics::SystemEvents::OnDefaultMaterialLibraryChangedEvent::Handler m_onDefaultMaterialLibraryChangedEventHandler;
AzPhysics::SystemEvents::OnMaterialLibraryChangedEvent::Handler m_onMaterialLibraryChangedEventHandler;
AZ::Transform m_cachedWorldTransform;
AZ::NonUniformScaleChangedEvent::Handler m_nonUniformScaleChangedHandler; //!< Responds to changes in non-uniform scale.
@@ -44,11 +44,14 @@ namespace PhysX
AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh,
AzToolsFramework::PropertyModificationRefreshLevel::Refresh_AttributesAndValues);
})
, m_onDefaultMaterialLibraryChangedEventHandler(
, m_onMaterialLibraryChangedEventHandler(
[this](const AZ::Data::AssetId& defaultMaterialLibrary)
{
m_colliderConfig.m_materialSelection.OnDefaultMaterialLibraryChanged(defaultMaterialLibrary);
m_colliderConfig.m_materialSelection.OnMaterialLibraryChanged(defaultMaterialLibrary);
Physics::ColliderComponentEventBus::Event(GetEntityId(), &Physics::ColliderComponentEvents::OnColliderChanged);
AzToolsFramework::PropertyEditorGUIMessages::Bus::Broadcast(&AzToolsFramework::PropertyEditorGUIMessages::RequestRefresh,
AzToolsFramework::PropertyModificationRefreshLevel::Refresh_AttributesAndValues);
})
, m_nonUniformScaleChangedHandler([this](const AZ::Vector3& scale) {OnNonUniformScaleChanged(scale);})
{
@@ -694,16 +697,16 @@ namespace PhysX
{
physXSystem->RegisterSystemConfigurationChangedEvent(m_physXConfigChangedHandler);
}
if (!m_onDefaultMaterialLibraryChangedEventHandler.IsConnected())
if (!m_onMaterialLibraryChangedEventHandler.IsConnected())
{
physXSystem->RegisterOnDefaultMaterialLibraryChangedEventHandler(m_onDefaultMaterialLibraryChangedEventHandler);
physXSystem->RegisterOnMaterialLibraryChangedEventHandler(m_onMaterialLibraryChangedEventHandler);
}
}
}
void EditorShapeColliderComponent::OnDeselected()
{
m_onDefaultMaterialLibraryChangedEventHandler.Disconnect();
m_onMaterialLibraryChangedEventHandler.Disconnect();
m_physXConfigChangedHandler.Disconnect();
}
@@ -155,7 +155,7 @@ namespace PhysX
mutable GeometryCache m_geometryCache; //!< Cached data for generating sample points inside the attached shape.
AzPhysics::SystemEvents::OnConfigurationChangedEvent::Handler m_physXConfigChangedHandler;
AzPhysics::SystemEvents::OnDefaultMaterialLibraryChangedEvent::Handler m_onDefaultMaterialLibraryChangedEventHandler;
AzPhysics::SystemEvents::OnMaterialLibraryChangedEvent::Handler m_onMaterialLibraryChangedEventHandler;
AZ::Transform m_cachedWorldTransform;
AZ::NonUniformScaleChangedEvent::Handler m_nonUniformScaleChangedHandler; //!< Responds to changes in non-uniform scale.
AZ::Vector3 m_currentNonUniformScale = AZ::Vector3::CreateOne(); //!< Caches the current non-uniform scale.
+278 -110
View File
@@ -15,6 +15,8 @@
#include "Material.h"
#include <AzCore/std/smart_ptr/make_shared.h>
#include <PxPhysicsAPI.h>
#include <AzFramework/Physics/PhysicsSystem.h>
#include <PhysX/MeshAsset.h>
namespace PhysX
{
@@ -22,6 +24,9 @@ namespace PhysX
: m_pxMaterial(AZStd::move(material.m_pxMaterial))
, m_surfaceType(material.m_surfaceType)
, m_surfaceString(AZStd::move(material.m_surfaceString))
, m_cryEngineSurfaceId(material.m_cryEngineSurfaceId)
, m_density(material.m_density)
, m_debugColor(AZStd::move(material.m_debugColor))
{
m_pxMaterial->userData = this;
}
@@ -31,6 +36,11 @@ namespace PhysX
m_pxMaterial = AZStd::move(material.m_pxMaterial);
m_surfaceType = material.m_surfaceType;
m_surfaceString = AZStd::move(material.m_surfaceString);
m_cryEngineSurfaceId = material.m_cryEngineSurfaceId;
m_density = material.m_density;
m_debugColor = AZStd::move(material.m_debugColor);
m_pxMaterial->userData = this;
return *this;
}
@@ -93,8 +103,10 @@ namespace PhysX
pxMaterial->userData = this;
m_pxMaterial = PxMaterialUniquePtr(pxMaterial, materialDestructor);
m_surfaceType = AZ::Crc32(materialConfiguration.m_surfaceType.c_str());
m_surfaceString = materialConfiguration.m_surfaceType;
SetSurfaceTypeName(materialConfiguration.m_surfaceType);
SetDebugColor(materialConfiguration.m_debugColor);
Physics::LegacySurfaceTypeRequestsBus::BroadcastResult(
m_cryEngineSurfaceId,
@@ -115,8 +127,9 @@ namespace PhysX
SetDensity(configuration.m_density);
m_surfaceType = AZ::Crc32(configuration.m_surfaceType.c_str());
m_surfaceString = configuration.m_surfaceType;
SetSurfaceTypeName(configuration.m_surfaceType);
SetDebugColor(configuration.m_debugColor);
Physics::LegacySurfaceTypeRequestsBus::BroadcastResult(
m_cryEngineSurfaceId,
@@ -134,9 +147,15 @@ namespace PhysX
return m_surfaceType;
}
void Material::SetSurfaceType(AZ::Crc32 surfaceType)
const AZStd::string& Material::GetSurfaceTypeName() const
{
m_surfaceType = surfaceType;
return m_surfaceString;
}
void Material::SetSurfaceTypeName(const AZStd::string& surfaceTypeName)
{
m_surfaceString = surfaceTypeName;
m_surfaceType = AZ::Crc32(m_surfaceString.c_str());
}
float Material::GetDynamicFriction() const
@@ -232,6 +251,16 @@ namespace PhysX
MaterialConfiguration::MinDensityLimit, MaterialConfiguration::MaxDensityLimit);
}
AZ::Color Material::GetDebugColor() const
{
return m_debugColor;
}
void Material::SetDebugColor(const AZ::Color& debugColor)
{
m_debugColor = debugColor;
}
AZ::u32 Material::GetCryEngineSurfaceId() const
{
return m_cryEngineSurfaceId;
@@ -243,6 +272,16 @@ namespace PhysX
}
MaterialsManager::MaterialsManager()
: m_physicsConfigChangedHandler(
[this](const AzPhysics::SystemConfiguration* config)
{
OnPhysicsConfigurationChanged(config);
})
, m_materialLibraryChangedHandler(
[this](const AZ::Data::AssetId& materialLibraryAssetId)
{
OnMaterialLibraryChanged(materialLibraryAssetId);
})
{
}
@@ -254,133 +293,152 @@ namespace PhysX
{
Physics::PhysicsMaterialRequestBus::Handler::BusConnect();
MaterialManagerRequestsBus::Handler::BusConnect();
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
{
physicsSystem->RegisterSystemConfigurationChangedEvent(m_physicsConfigChangedHandler);
physicsSystem->RegisterOnMaterialLibraryChangedEventHandler(m_materialLibraryChangedHandler);
}
}
void MaterialsManager::Disconnect()
{
m_materialLibraryChangedHandler.Disconnect();
m_physicsConfigChangedHandler.Disconnect();
MaterialManagerRequestsBus::Handler::BusDisconnect();
Physics::PhysicsMaterialRequestBus::Handler::BusDisconnect();
}
void MaterialsManager::GetMaterials(const Physics::MaterialSelection& materialSelection
, AZStd::vector<AZStd::weak_ptr<Physics::Material>>& outMaterials)
, AZStd::vector<AZStd::shared_ptr<Physics::Material>>& outMaterials)
{
outMaterials.clear();
outMaterials.reserve(materialSelection.GetMaterialIdsAssignedToSlots().size());
// Ensure PxMaterial instances are initialized if possible.
InitializeMaterials(materialSelection);
for (const auto& id : materialSelection.GetMaterialIdsAssignedToSlots())
const auto& materialIdsAssignedToSlots = materialSelection.GetMaterialIdsAssignedToSlots();
if (materialIdsAssignedToSlots.empty())
{
Physics::MaterialFromAssetConfiguration configuration;
if (materialSelection.GetMaterialConfiguration(configuration, id))
// The material selection doesn't have any slots, return empty list.
return;
}
// It is important to return exactly the amount of materials specified in materialSelection
// If a number of materials different to what was cooked is assigned on a physx mesh it will lead to undefined
// behavior and subtle bugs. Unfortunately, there's no warning or assertion on physx side at the shape creation time,
// nor mention of this in the documentation
outMaterials.resize(materialIdsAssignedToSlots.size(), GetDefaultMaterial());
for (size_t slotIndex = 0; slotIndex < materialIdsAssignedToSlots.size(); ++slotIndex)
{
const auto& materialId = materialIdsAssignedToSlots[slotIndex];
if (auto iterator = FindOrCreateMaterial(materialId);
iterator != m_materials.end())
{
auto iterator = m_materialsFromAssets.find(id.GetUuid());
if (iterator != m_materialsFromAssets.end())
{
outMaterials.push_back(iterator->second);
}
else
{
outMaterials.push_back(GetDefaultMaterial());
}
}
else
{
// It is important to return exactly the amount of materials specified in materialSelection
// If a number of materials different to what was cooked is assigned on a physx mesh it will lead to undefined
// behavior and subtle bugs. Unfortunately, there's no warning or assertion on physx side at the shape creation time,
// nor mention of this in the documentation
outMaterials.push_back(GetDefaultMaterial());
outMaterials[slotIndex] = iterator->second;
}
}
}
AZStd::weak_ptr<Physics::Material> MaterialsManager::GetMaterialByName(const AZStd::string& name)
AZStd::shared_ptr<Physics::Material> MaterialsManager::GetMaterialById(Physics::MaterialId id)
{
auto it = AZStd::find_if(m_materialsFromAssets.begin(), m_materialsFromAssets.end(),
[&name](const AZStd::pair<AZ::Uuid, AZStd::shared_ptr<Material>>& elem)
{
return elem.second.get()->GetSurfaceTypeName() == name;
});
if (it != m_materialsFromAssets.end())
if (auto it = FindOrCreateMaterial(id);
it != m_materials.end())
{
return it->second;
}
return {};
return nullptr;
}
AZ::u32 MaterialsManager::GetFirstSelectedMaterialIndex(const Physics::MaterialSelection& materialSelection)
AZStd::shared_ptr<Physics::Material> MaterialsManager::GetMaterialByName(const AZStd::string& name)
{
const AZ::u32 defaultMaterialIndex = 0;
if (!materialSelection.IsMaterialLibraryValid())
if (auto it = FindOrCreateMaterial(name);
it != m_materials.end())
{
return defaultMaterialIndex;
return it->second;
}
auto materialAsset = AZ::Data::AssetManager::Instance().GetAsset<Physics::MaterialLibraryAsset>(materialSelection.GetMaterialLibraryAssetId(), AZ::Data::AssetLoadBehavior::Default);
materialAsset.BlockUntilLoadComplete();
AZStd::vector<Physics::MaterialFromAssetConfiguration> materialList = materialAsset.Get()->GetMaterialsData();
const AZStd::vector<Physics::MaterialId>& selectedMaterials = materialSelection.GetMaterialIdsAssignedToSlots();
if (selectedMaterials.size() == 0)
{
return defaultMaterialIndex;
}
for (AZ::u32 i=0; i < materialList.size(); ++i)
{
if (materialList[i].m_id == selectedMaterials[0])
{
return i + 1; // Index 0 is reserved for Default material.
}
}
return defaultMaterialIndex;
return nullptr;
}
void MaterialsManager::GetPxMaterials(const Physics::MaterialSelection& materialSelection
, AZStd::vector<physx::PxMaterial*>& outMaterials)
{
outMaterials.clear();
if (materialSelection.GetMaterialIdsAssignedToSlots().empty())
AZStd::vector<AZStd::shared_ptr<Physics::Material>> materials;
GetMaterials(materialSelection, materials);
outMaterials.reserve(materials.size());
for (const auto& material : materials)
{
PhysX::Material* physxMaterial = azrtti_cast<PhysX::Material*>(material.get());
AZ_Assert(physxMaterial, "Invalid physx material");
outMaterials.emplace_back(physxMaterial->GetPxMaterial());
}
}
void MaterialsManager::UpdateMaterialSelectionFromPhysicsAsset(
const Physics::ShapeConfiguration& shapeConfiguration,
Physics::MaterialSelection& materialSelection)
{
if (shapeConfiguration.GetShapeType() != Physics::ShapeType::PhysicsAsset)
{
// if the materialSelection is invalid we still
// return a default material as a fallback behavior
outMaterials.push_back(GetDefaultMaterial()->GetPxMaterial());
return;
}
outMaterials.reserve(materialSelection.GetMaterialIdsAssignedToSlots().size());
// Ensure PxMaterial instances are initialized if possible.
InitializeMaterials(materialSelection);
const Physics::PhysicsAssetShapeConfiguration& assetConfiguration =
static_cast<const Physics::PhysicsAssetShapeConfiguration&>(shapeConfiguration);
for (const auto& id : materialSelection.GetMaterialIdsAssignedToSlots())
if (!assetConfiguration.m_asset.GetId().IsValid())
{
Physics::MaterialFromAssetConfiguration configuration;
if (materialSelection.GetMaterialConfiguration(configuration, id))
// Set the default selection if there's no physics asset.
materialSelection.SetMaterialSlots(Physics::MaterialSelection::SlotsArray());
return;
}
if (!assetConfiguration.m_asset.IsReady())
{
// The asset is valid but is still loading,
// Do not set the empty slots in this case to avoid the entity being in invalid state
return;
}
Pipeline::MeshAsset* meshAsset = assetConfiguration.m_asset.GetAs<Pipeline::MeshAsset>();
if (!meshAsset)
{
materialSelection.SetMaterialSlots(Physics::MaterialSelection::SlotsArray());
AZ_Warning("PhysX", false, "UpdateMaterialSelectionFromPhysicsAsset: MeshAsset is invalid");
return;
}
// Set the slots from the mesh asset
materialSelection.SetMaterialSlots(meshAsset->m_assetData.m_surfaceNames);
if (!assetConfiguration.m_useMaterialsFromAsset)
{
// Not using the materials from the asset. Nothing else to do.
return;
}
// Update material IDs in the selection for each slot
const AZStd::vector<AZStd::string>& meshMaterialNames = meshAsset->m_assetData.m_materialNames;
for (size_t slotIndex = 0; slotIndex < meshMaterialNames.size(); ++slotIndex)
{
const AZStd::string& physicsMaterialNameFromPhysicsAsset = meshMaterialNames[slotIndex];
if (physicsMaterialNameFromPhysicsAsset == DefaultPhysicsMaterialNameFromPhysicsAsset)
{
auto iterator = m_materialsFromAssets.find(id.GetUuid());
if (iterator != m_materialsFromAssets.end())
{
outMaterials.push_back(iterator->second->GetPxMaterial());
}
else
{
outMaterials.push_back(GetDefaultMaterial()->GetPxMaterial());
}
continue;
}
if (auto it = FindOrCreateMaterial(physicsMaterialNameFromPhysicsAsset);
it != m_materials.end())
{
materialSelection.SetMaterialId(Physics::MaterialId::FromUUID(it->first), slotIndex);
}
else
{
// It is important to return exactly the amount of materials specified in materialSelection
// If a number of materials different to what was cooked is assigned on a physx mesh it will lead to undefined
// behavior and subtle bugs. Unfortunately, there's no warning or assertion on physx side at the shape creation time,
// nor mention of this in the documentation
outMaterials.push_back(GetDefaultMaterial()->GetPxMaterial());
AZ_Warning("PhysX", false,
"UpdateMaterialSelectionFromPhysicsAsset: Physics material '%s' not found in the material library. Mesh surface '%s' will use the default material.",
physicsMaterialNameFromPhysicsAsset.c_str(),
meshAsset->m_assetData.m_surfaceNames[slotIndex].c_str());
}
}
}
@@ -390,11 +448,21 @@ namespace PhysX
return GetDefaultMaterial();
}
const AZStd::shared_ptr<Material>& MaterialsManager::GetDefaultMaterial()
AZStd::shared_ptr<Material> MaterialsManager::GetDefaultMaterial()
{
if (!m_defaultMaterial)
{
m_defaultMaterial = AZStd::make_shared<Material>(Physics::MaterialConfiguration());
// Get default material from physics configuration
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
{
m_defaultMaterialConfiguration = physicsSystem->GetConfiguration()->m_defaultMaterialConfiguration;
}
else
{
AZ_Warning("MaterialsManager", false, "Unable to get Physics System, default material will not be in sync with PhysX Configuration");
}
m_defaultMaterial = AZStd::make_shared<Material>(m_defaultMaterialConfiguration);
}
return m_defaultMaterial;
@@ -403,38 +471,138 @@ namespace PhysX
void MaterialsManager::ReleaseAllMaterials()
{
m_defaultMaterial = nullptr;
m_materialsFromAssets.clear();
m_materials.clear();
Physics::PhysicsMaterialNotificationsBus::Broadcast(&Physics::PhysicsMaterialNotificationsBus::Events::MaterialsReleased);
}
void MaterialsManager::InitializeMaterials(const Physics::MaterialSelection& materialSelection)
MaterialsManager::Materials::iterator MaterialsManager::FindOrCreateMaterial(Physics::MaterialId materialId)
{
const AZStd::vector<Physics::MaterialId>& materialIds = materialSelection.GetMaterialIdsAssignedToSlots();
for (const auto& id : materialIds)
if (materialId.IsNull())
{
Physics::MaterialFromAssetConfiguration configuration;
if (!materialSelection.GetMaterialConfiguration(configuration, id))
{
continue; // Default material skips code below.
}
auto materialId = configuration.m_id;
return m_materials.end();
}
if (auto it = m_materials.find(materialId.GetUuid());
it != m_materials.end())
{
return it;
}
else
{
auto* materialLibrary = GetMaterialLibrary();
if (!materialLibrary)
{
return m_materials.end();
}
Physics::MaterialFromAssetConfiguration configuration;
if (!materialLibrary->GetDataForMaterialId(materialId, configuration))
{
return m_materials.end();
}
auto newMaterial = AZStd::make_shared<Material>(configuration.m_configuration);
auto insertedPair = m_materials.emplace(materialId.GetUuid(), AZStd::move(newMaterial));
return insertedPair.first;
}
}
MaterialsManager::Materials::iterator MaterialsManager::FindOrCreateMaterial(const AZStd::string& materialName)
{
if (materialName.empty())
{
return m_materials.end();
}
auto it = AZStd::find_if(m_materials.begin(), m_materials.end(), [&materialName](const auto& data)
{
return data.second->GetSurfaceTypeName() == materialName;
});
if (it != m_materials.end())
{
return it;
}
else
{
auto* materialLibrary = GetMaterialLibrary();
if (!materialLibrary)
{
return m_materials.end();
}
Physics::MaterialFromAssetConfiguration configuration;
if (!materialLibrary->GetDataForMaterialName(materialName, configuration))
{
return m_materials.end();
}
auto newMaterial = AZStd::make_shared<Material>(configuration.m_configuration);
auto insertedPair = m_materials.emplace(configuration.m_id.GetUuid(), AZStd::move(newMaterial));
return insertedPair.first;
}
}
Physics::MaterialLibraryAsset* MaterialsManager::GetMaterialLibrary()
{
if (auto* physicsSystem = AZ::Interface<AzPhysics::SystemInterface>::Get())
{
if (const auto* physicsConfiguration = physicsSystem->GetConfiguration())
{
return physicsConfiguration->m_materialLibraryAsset.Get();
}
}
return nullptr;
}
void MaterialsManager::OnPhysicsConfigurationChanged(const AzPhysics::SystemConfiguration* config)
{
if (m_defaultMaterial &&
m_defaultMaterialConfiguration != config->m_defaultMaterialConfiguration)
{
m_defaultMaterialConfiguration = config->m_defaultMaterialConfiguration;
m_defaultMaterial->UpdateWithConfiguration(m_defaultMaterialConfiguration);
}
}
void MaterialsManager::OnMaterialLibraryChanged([[maybe_unused]] const AZ::Data::AssetId& materialLibraryAssetId)
{
auto* materialLibrary = GetMaterialLibrary();
if (!materialLibrary)
{
AZ_Warning("PhysX", false, "MaterialsManager: invalid material library");
return;
}
AZStd::vector<AZ::Uuid> materialsToRemove;
for (auto& idMaterialPair : m_materials)
{
const Physics::MaterialId materialId = Physics::MaterialId::FromUUID(idMaterialPair.first);
// Remove null materials
if (materialId.IsNull())
{
materialId = Physics::MaterialId::Create();
materialsToRemove.push_back(materialId.GetUuid());
continue;
}
auto iterator = m_materialsFromAssets.find(materialId.GetUuid());
if (iterator != m_materialsFromAssets.end())
Physics::MaterialFromAssetConfiguration configuration;
if (materialLibrary->GetDataForMaterialId(materialId, configuration))
{
iterator->second->UpdateWithConfiguration(configuration.m_configuration);
// Update materials found in the library.
idMaterialPair.second->UpdateWithConfiguration(configuration.m_configuration);
}
else
{
auto newMaterial = AZStd::make_shared<Material>(configuration.m_configuration);
m_materialsFromAssets.emplace(materialId.GetUuid(), newMaterial);
// Add for removal the materials not present in the library anymore.
materialsToRemove.push_back(materialId.GetUuid());
}
}
for (const auto& id : materialsToRemove)
{
m_materials.erase(id);
}
}
}
+60 -32
View File
@@ -15,11 +15,18 @@
#include <PxPhysicsAPI.h>
#include <AzFramework/Physics/Material.h>
#include <AzFramework/Physics/MaterialBus.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzFramework/Physics/ShapeConfiguration.h>
#include <AzFramework/Physics/Common/PhysicsEvents.h>
#include <AzCore/std/smart_ptr/enable_shared_from_this.h>
namespace PhysX
{
/// Name used by physx asset exporter to indicate that the default
/// physics material should be used for a mesh surface. The exporter
/// will use it as the fallback option when it's not possible to obtain
/// the surface information from the mesh material.
static const char* const DefaultPhysicsMaterialNameFromPhysicsAsset = "<Default>";
/// PhysX implementation of Physics::Material interface
/// ===================================================
///
@@ -58,9 +65,9 @@ namespace PhysX
// Physics::Material
AZ::Crc32 GetSurfaceType() const override;
void SetSurfaceType(AZ::Crc32 surfaceType) override;
const AZStd::string& GetSurfaceTypeName() const override { return m_surfaceString; }
const AZStd::string& GetSurfaceTypeName() const override;
void SetSurfaceTypeName(const AZStd::string& surfaceTypeName) override;
float GetDynamicFriction() const override;
void SetDynamicFriction(float dynamicFriction) override;
@@ -80,6 +87,9 @@ namespace PhysX
float GetDensity() const override;
void SetDensity(float density) override;
AZ::Color GetDebugColor() const override;
void SetDebugColor(const AZ::Color& debugColor) override;
AZ::u32 GetCryEngineSurfaceId() const override;
void* GetNativePointer() override;
@@ -92,6 +102,7 @@ namespace PhysX
AZ::u32 m_cryEngineSurfaceId = -1;
AZStd::string m_surfaceString;
float m_density = 1000.0f;
AZ::Color m_debugColor = AZ::Colors::White;
};
/// Bus with requests to MaterialsManager
@@ -108,9 +119,17 @@ namespace PhysX
static const AZ::EBusHandlerPolicy HandlerPolicy = AZ::EBusHandlerPolicy::Single;
static const AZ::EBusAddressPolicy AddressPolicy = AZ::EBusAddressPolicy::Single;
/// Returns weak pointers to physx::PxMaterial.
/// Equivalent to PhysicsMaterialRequests::GetMaterials but it returns physx::PxMaterial pointers instead.
/// @param materialSelection MaterialSelection instance to create or get materials for
/// @param outMaterials vector of pointers to physx::PxMaterial to fill with. The vector will be cleared inside the function.
virtual void GetPxMaterials(const Physics::MaterialSelection& materialSelection, AZStd::vector<physx::PxMaterial*>& outMaterials) = 0;
virtual const AZStd::shared_ptr<Material>& GetDefaultMaterial() = 0;
/// Returns default material
/// @return default PhysX::Material instance
virtual AZStd::shared_ptr<Material> GetDefaultMaterial() = 0;
/// Releases ownership of all materials created before.
virtual void ReleaseAllMaterials() = 0;
};
using MaterialManagerRequestsBus = AZ::EBus<MaterialManagerRequests>;
@@ -120,6 +139,9 @@ namespace PhysX
///
/// Material managers creates PhysX::Material instances from MaterialLibraryAsset and assumes their ownership.
/// Also keeps a reference to the default material.
///
/// Note: Materials will be created on the fly while doing queries and
/// they will be updated when the material library changes.
class MaterialsManager
: public MaterialManagerRequestsBus::Handler
, public Physics::PhysicsMaterialRequestBus::Handler
@@ -131,35 +153,19 @@ namespace PhysX
MaterialsManager();
~MaterialsManager() override;
/// Returns a vector of weak pointers to materials selected.
/// To be notified if the pointers are deleted, connect to PhysicsMaterialNotifications::MaterialsReleased().
/// @param materialSelection MaterialSelection instance to create or get materials for.
/// @param outMaterials Collection of material weak pointers corresponding to the material selection to be returned.
// PhysicsMaterialRequestBus::Handler overrides...
void GetMaterials(const Physics::MaterialSelection& materialSelection
, AZStd::vector<AZStd::weak_ptr<Physics::Material>>& outMaterials) override;
/// Returns a weak pointer to physics material with the given name.
AZStd::weak_ptr<Physics::Material> GetMaterialByName(const AZStd::string& name) override;
/// Returns index of selected material in its material library. 0 is the Default material.
/// @param materialSelection Selection of materials.
AZ::u32 GetFirstSelectedMaterialIndex(const Physics::MaterialSelection& materialSelection) override;
/// Slightly faster version of GetMaterials that returns physx::PxMaterial pointers instead. \n
/// The rest is equivalent to GetMaterials function.
/// @param materialSelection MaterialSelection instance to create or get materials for
/// @param outMaterials vector of pointers to physx::PxMaterial to fill with. The vector will be cleared inside the function.
void GetPxMaterials(const Physics::MaterialSelection& materialSelection, AZStd::vector<physx::PxMaterial*>& outMaterials) override;
/// Returns default material
/// @return default PhysX::Material instance
const AZStd::shared_ptr<Material>& GetDefaultMaterial() override;
/// Return default material
/// @return default Physics::Material instance
, AZStd::vector<AZStd::shared_ptr<Physics::Material>>& outMaterials) override;
AZStd::shared_ptr<Physics::Material> GetMaterialById(Physics::MaterialId id) override;
AZStd::shared_ptr<Physics::Material> GetMaterialByName(const AZStd::string& name) override;
void UpdateMaterialSelectionFromPhysicsAsset(
const Physics::ShapeConfiguration& shapeConfiguration,
Physics::MaterialSelection& materialSelection) override;
AZStd::shared_ptr<Physics::Material> GetGenericDefaultMaterial() override;
/// Releases ownership of all materials created before.
// MaterialManagerRequestsBus::Handler overrides...
void GetPxMaterials(const Physics::MaterialSelection& materialSelection, AZStd::vector<physx::PxMaterial*>& outMaterials) override;
AZStd::shared_ptr<Material> GetDefaultMaterial() override;
void ReleaseAllMaterials() override;
/// Connect to any necessary buses
@@ -169,9 +175,31 @@ namespace PhysX
void Disconnect();
private:
void InitializeMaterials(const Physics::MaterialSelection& materialSelection);
using Materials = AZStd::unordered_map<AZ::Uuid, AZStd::shared_ptr<Material>>;
AZStd::unordered_map<AZ::Uuid, AZStd::shared_ptr<Material>> m_materialsFromAssets;
/// Search a material by id, if it exists already it returns its iterator,
/// if it doesn't exist it tries to create it and add it to the list.
/// If the material id is null or not part of the material library then the
/// iterator returned is end of material list.
Materials::iterator FindOrCreateMaterial(Physics::MaterialId materialId);
/// Search a material by name, if it exists already it returns its iterator,
/// if it doesn't exist it tries to create it and add it to the list.
/// If the material id is null or not part of the material library then the
/// iterator returned is end of material list.
Materials::iterator FindOrCreateMaterial(const AZStd::string& materialName);
/// Returns the material library of the project.
Physics::MaterialLibraryAsset* GetMaterialLibrary();
void OnPhysicsConfigurationChanged(const AzPhysics::SystemConfiguration* config);
void OnMaterialLibraryChanged(const AZ::Data::AssetId& materialLibraryAssetId);
Materials m_materials;
AZStd::shared_ptr<Material> m_defaultMaterial;
Physics::MaterialConfiguration m_defaultMaterialConfiguration;
AzPhysics::SystemEvents::OnConfigurationChangedEvent::Handler m_physicsConfigChangedHandler;
AzPhysics::SystemEvents::OnMaterialLibraryChangedEvent::Handler m_materialLibraryChangedHandler;
};
}
@@ -16,7 +16,7 @@
#include <AzCore/Serialization/SerializeContext.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzFramework/Physics/SystemBus.h>
#include <AzFramework/Physics/MaterialBus.h>
#include <Source/MeshColliderComponent.h>
#include <Source/Utils.h>
@@ -85,11 +85,6 @@ namespace PhysX
UpdateMeshAsset();
}
void MeshColliderComponent::SetMaterialAsset(const AZ::Data::AssetId& id)
{
m_colliderConfiguration->m_materialSelection.SetMaterialLibrary(id);
}
void MeshColliderComponent::SetMaterialId(const Physics::MaterialId& id)
{
m_colliderConfiguration->m_materialSelection.SetMaterialId(id);
@@ -111,8 +106,10 @@ namespace PhysX
{
m_shapeConfiguration->m_asset = asset;
Physics::SystemRequestBus::Broadcast(&Physics::SystemRequests::UpdateMaterialSelection,
*m_shapeConfiguration, *m_colliderConfiguration);
Physics::PhysicsMaterialRequestBus::Broadcast(
&Physics::PhysicsMaterialRequestBus::Events::UpdateMaterialSelectionFromPhysicsAsset,
*m_shapeConfiguration,
m_colliderConfiguration->m_materialSelection);
}
}
@@ -122,8 +119,10 @@ namespace PhysX
{
m_shapeConfiguration->m_asset = asset;
Physics::SystemRequestBus::Broadcast(&Physics::SystemRequests::UpdateMaterialSelection,
*m_shapeConfiguration, *m_colliderConfiguration);
Physics::PhysicsMaterialRequestBus::Broadcast(
&Physics::PhysicsMaterialRequestBus::Events::UpdateMaterialSelectionFromPhysicsAsset,
*m_shapeConfiguration,
m_colliderConfiguration->m_materialSelection);
}
}
@@ -40,7 +40,6 @@ namespace PhysX
AZ::Data::Asset<Pipeline::MeshAsset> GetMeshAsset() const override;
Physics::MaterialId GetMaterialId() const override;
void SetMeshAsset(const AZ::Data::AssetId& id) override;
void SetMaterialAsset(const AZ::Data::AssetId& id) override;
void SetMaterialId(const Physics::MaterialId& id) override;
// BaseColliderComponent
@@ -15,9 +15,7 @@
#include <PhysXCharacters/API/CharacterController.h>
#include <PhysXCharacters/API/Ragdoll.h>
#include <AzCore/std/smart_ptr/make_shared.h>
#include <AzFramework/Physics/PhysicsScene.h>
#include <AzFramework/Physics/PhysicsSystem.h>
#include <AzFramework/Physics/SystemBus.h>
#include <AzFramework/Physics/MaterialBus.h>
#include <cfloat>
#include <PhysX/PhysXLocks.h>
#include <Source/RigidBody.h>
@@ -51,18 +49,32 @@ namespace PhysX
static void AppendShapeIndependentProperties(physx::PxControllerDesc& controllerDesc,
const Physics::CharacterConfiguration& characterConfig, CharacterControllerCallbackManager* callbackManager)
{
AZStd::vector<AZStd::shared_ptr<Physics::Material> > materials;
AZStd::vector<AZStd::shared_ptr<Physics::Material>> materials;
Physics::SystemRequestBus::BroadcastResult(
materials,
&Physics::SystemRequests::CreateMaterialsFromLibrary,
characterConfig.m_materialSelection
);
if (materials.empty())
if (characterConfig.m_materialSelection.GetMaterialIdsAssignedToSlots().empty())
{
AZ_Error("PhysX Character Controller", false, "Could not create character controller, material was invalid.");
return;
// If material selection has no slots, falling back to default material.
AZStd::shared_ptr<Physics::Material> defaultMaterial;
Physics::PhysicsMaterialRequestBus::BroadcastResult(defaultMaterial,
&Physics::PhysicsMaterialRequestBus::Events::GetGenericDefaultMaterial);
if (!defaultMaterial)
{
AZ_Error("PhysX Character Controller", false, "Invalid default material.");
return;
}
materials.push_back(AZStd::move(defaultMaterial));
}
else
{
Physics::PhysicsMaterialRequestBus::Broadcast(
&Physics::PhysicsMaterialRequestBus::Events::GetMaterials,
characterConfig.m_materialSelection,
materials);
if (materials.empty())
{
AZ_Error("PhysX Character Controller", false, "Could not create character controller, material list was empty.");
return;
}
}
physx::PxMaterial* pxMaterial = static_cast<physx::PxMaterial*>(materials.front()->GetNativePointer());
@@ -25,7 +25,7 @@
#include <SceneAPI/SceneCore/DataTypes/GraphData/IMaterialData.h>
#include <PhysX/MeshAsset.h>
#include <AzFramework/Physics/Material.h>
#include <Source/Material.h>
#include <Source/Pipeline/MeshAssetHandler.h>
#include <Source/Pipeline/MeshExporter.h>
#include <Source/Pipeline/PrimitiveShapeFitter/PrimitiveShapeFitter.h>
@@ -153,7 +153,7 @@ namespace PhysX
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<MeshExporter, AZ::SceneAPI::SceneCore::ExportingComponent>()->Version(3);
serializeContext->Class<MeshExporter, AZ::SceneAPI::SceneCore::ExportingComponent>()->Version(4);
}
}
@@ -215,7 +215,7 @@ namespace PhysX
if (nameAttribute)
{
AZStd::string materialName = nameAttribute->value();
AZStd::string surfaceTypeName = DefaultMaterialName;
AZStd::string surfaceTypeName = DefaultPhysicsMaterialNameFromPhysicsAsset;
AZ::rapidxml::xml_attribute<char>* surfaceTypeNode = materialNode->first_attribute("SurfaceType");
if (surfaceTypeNode && surfaceTypeNode->value_size() != 0)
@@ -268,7 +268,7 @@ namespace PhysX
}
else
{
materialName = DefaultMaterialName;
materialName = DefaultPhysicsMaterialNameFromPhysicsAsset;
}
materialNames.emplace_back(AZStd::move(materialName));
+50 -34
View File
@@ -40,8 +40,8 @@ namespace PhysX
}
#endif
PhysXSystem::MaterialLibraryAssetHelper::MaterialLibraryAssetHelper(PhysXSystem* physXSystem)
: m_physXSystem(physXSystem)
PhysXSystem::MaterialLibraryAssetHelper::MaterialLibraryAssetHelper(OnMaterialLibraryReloadedCallback callback)
: m_onMaterialLibraryReloadedCallback(callback)
{
}
@@ -62,16 +62,16 @@ namespace PhysX
void PhysXSystem::MaterialLibraryAssetHelper::OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset)
{
if (m_physXSystem == nullptr || m_physXSystem->GetDefaultMaterialLibrary() != asset)
{
return;
}
m_physXSystem->UpdateDefaultMaterialLibrary(asset);
m_onMaterialLibraryReloadedCallback(asset);
}
PhysXSystem::PhysXSystem(PhysXSettingsRegistryManager* registryManager, const physx::PxCookingParams& cookingParams)
: m_registryManager(*registryManager)
, m_materialLibraryAssetHelper(this)
, m_materialLibraryAssetHelper(
[this](const AZ::Data::Asset<Physics::MaterialLibraryAsset>& materialLibrary)
{
UpdateMaterialLibrary(materialLibrary);
})
, m_sceneInterface(this)
{
// Start PhysX allocator
@@ -127,7 +127,7 @@ namespace PhysX
m_materialLibraryAssetHelper.Disconnect();
// Clear the asset reference in deactivate. The asset system is shut down before destructors are called
// for system components, causing any hanging asset references to become crashes on shutdown in release builds.
m_systemConfig.m_defaultMaterialLibrary.Reset();
m_systemConfig.m_materialLibraryAsset.Reset();
m_accumulatedTime = 0.0f;
m_state = State::Shutdown;
@@ -369,8 +369,18 @@ namespace PhysX
void PhysXSystem::OnCatalogLoaded([[maybe_unused]]const char* catalogFile)
{
//now that assets can be resolved, lets load the default material library.
LoadDefaultMaterialLibrary();
// now that assets can be resolved, lets load the default material library.
if (!m_systemConfig.m_materialLibraryAsset.GetId().IsValid())
{
m_onMaterialLibraryLoadErrorEvent.Signal(AzPhysics::SystemEvents::MaterialLibraryLoadErrorType::InvalidId);
}
bool success = LoadMaterialLibrary();
if (!success)
{
m_onMaterialLibraryLoadErrorEvent.Signal(AzPhysics::SystemEvents::MaterialLibraryLoadErrorType::ErrorLoading);
}
}
void PhysXSystem::UpdateConfiguration(const AzPhysics::SystemConfiguration* newConfig, [[maybe_unused]] bool forceReinitialization /*= false*/)
@@ -378,7 +388,7 @@ namespace PhysX
if (const auto* physXConfig = azdynamic_cast<const PhysXSystemConfiguration*>(newConfig);
m_systemConfig != (*physXConfig))
{
const bool newMaterialLibrary = m_systemConfig.m_defaultMaterialLibrary != physXConfig->m_defaultMaterialLibrary;
const bool newMaterialLibrary = m_systemConfig.m_materialLibraryAsset != physXConfig->m_materialLibraryAsset;
m_systemConfig = (*physXConfig);
m_configChangeEvent.Signal(physXConfig);
@@ -386,9 +396,11 @@ namespace PhysX
if (newMaterialLibrary)
{
LoadDefaultMaterialLibrary();
m_onDefaultMaterialLibraryChangedEvent.Signal(m_systemConfig.m_defaultMaterialLibrary.GetId());
LoadMaterialLibrary();
m_onMaterialLibraryChangedEvent.Signal(m_systemConfig.m_materialLibraryAsset.GetId());
}
// This function is not called from reloading the material library asset,
// which means we don't need to check if the materials inside the library have been modified.
}
}
@@ -445,23 +457,6 @@ namespace PhysX
return m_systemConfig;
}
void PhysXSystem::UpdateDefaultMaterialLibrary(const AZ::Data::Asset<Physics::MaterialLibraryAsset>& materialLibrary)
{
if (m_systemConfig.m_defaultMaterialLibrary == materialLibrary)
{
return;
}
m_systemConfig.m_defaultMaterialLibrary = materialLibrary;
LoadDefaultMaterialLibrary();
m_onDefaultMaterialLibraryChangedEvent.Signal(materialLibrary.GetId());
}
const AZ::Data::Asset<Physics::MaterialLibraryAsset>& PhysXSystem::GetDefaultMaterialLibrary() const
{
return m_systemConfig.m_defaultMaterialLibrary;
}
void PhysXSystem::UpdateDefaultSceneConfiguration(const AzPhysics::SceneConfiguration& sceneConfiguration)
{
if (m_defaultSceneConfiguration != sceneConfiguration)
@@ -482,9 +477,30 @@ namespace PhysX
return m_registryManager;
}
bool PhysXSystem::LoadDefaultMaterialLibrary()
void PhysXSystem::UpdateMaterialLibrary(const AZ::Data::Asset<Physics::MaterialLibraryAsset>& materialLibrary)
{
AZ::Data::Asset<Physics::MaterialLibraryAsset>& materialLibrary = m_systemConfig.m_defaultMaterialLibrary;
if (m_systemConfig.m_materialLibraryAsset == materialLibrary)
{
// Same library asset, check if its data has changed.
if (m_systemConfig.m_materialLibraryAsset->GetMaterialsData() != materialLibrary->GetMaterialsData())
{
m_systemConfig.m_materialLibraryAsset = materialLibrary;
m_onMaterialLibraryChangedEvent.Signal(materialLibrary.GetId());
}
}
else
{
// New material library asset
m_systemConfig.m_materialLibraryAsset = materialLibrary;
LoadMaterialLibrary();
m_onMaterialLibraryChangedEvent.Signal(materialLibrary.GetId());
}
}
bool PhysXSystem::LoadMaterialLibrary()
{
AZ::Data::Asset<Physics::MaterialLibraryAsset>& materialLibrary = m_systemConfig.m_materialLibraryAsset;
const AZ::Data::AssetId& materialLibraryId = materialLibrary.GetId();
if (!materialLibraryId.IsValid())
{
@@ -503,7 +519,7 @@ namespace PhysX
AZ_Warning("PhysX", (materialLibrary.GetData() != nullptr),
"LoadDefaultMaterialLibrary: Default Material Library asset data is invalid.");
return materialLibrary.GetData() != nullptr;
return materialLibrary.GetData() != nullptr && !materialLibrary.IsError();
}
//TEMP -- until these are fully moved over here
+7 -5
View File
@@ -64,8 +64,6 @@ namespace PhysX
AZStd::pair<AzPhysics::SceneHandle, AzPhysics::SimulatedBodyHandle> FindAttachedBodyHandleFromEntityId(AZ::EntityId entityId) override;
const AzPhysics::SystemConfiguration* GetConfiguration() const override;
void UpdateConfiguration(const AzPhysics::SystemConfiguration* newConfig, bool forceReinitialization = false) override;
void UpdateDefaultMaterialLibrary(const AZ::Data::Asset<Physics::MaterialLibraryAsset>& materialLibrary) override;
const AZ::Data::Asset<Physics::MaterialLibraryAsset>& GetDefaultMaterialLibrary() const override;
void UpdateDefaultSceneConfiguration(const AzPhysics::SceneConfiguration& sceneConfiguration) override;
const AzPhysics::SceneConfiguration& GetDefaultSceneConfiguration() const override;
@@ -75,6 +73,8 @@ namespace PhysX
//! Accessor to get the Settings Registry Manager.
const PhysXSettingsRegistryManager& GetSettingsRegistryManager() const;
void UpdateMaterialLibrary(const AZ::Data::Asset<Physics::MaterialLibraryAsset>& materialLibrary);
//TEMP -- until these are fully moved over here
physx::PxPhysics* GetPxPhysics() { return m_physXSdk.m_physics; }
physx::PxCooking* GetPxCooking() { return m_physXSdk.m_cooking; }
@@ -92,7 +92,7 @@ namespace PhysX
//! @param cookingParams The cooking params to use when setting up PhysX cooking interface.
void InitializePhysXSdk(const physx::PxCookingParams& cookingParams);
void ShutdownPhysXSdk();
bool LoadDefaultMaterialLibrary();
bool LoadMaterialLibrary();
// AzFramework::AssetCatalogEventBus::Handler ...
void OnCatalogLoaded(const char* catalogFile) override;
@@ -133,7 +133,9 @@ namespace PhysX
: private AZ::Data::AssetBus::Handler
{
public:
MaterialLibraryAssetHelper(PhysXSystem* physXSystem);
using OnMaterialLibraryReloadedCallback = AZStd::function<void(const AZ::Data::Asset<Physics::MaterialLibraryAsset>& materialLibrary)>;
MaterialLibraryAssetHelper(OnMaterialLibraryReloadedCallback callback);
void Connect(const AZ::Data::AssetId& materialLibraryId);
void Disconnect();
@@ -142,7 +144,7 @@ namespace PhysX
// AZ::Data::AssetBus::Handler
void OnAssetReloaded(AZ::Data::Asset<AZ::Data::AssetData> asset) override;
PhysXSystem* m_physXSystem;
OnMaterialLibraryReloadedCallback m_onMaterialLibraryReloadedCallback;
};
MaterialLibraryAssetHelper m_materialLibraryAssetHelper;
};
-134
View File
@@ -347,27 +347,6 @@ namespace PhysX
return AZStd::make_shared<PhysX::Material>(materialConfiguration);
}
AZStd::vector<AZStd::shared_ptr<Physics::Material>> SystemComponent::CreateMaterialsFromLibrary(const Physics::MaterialSelection& materialSelection)
{
AZStd::vector<physx::PxMaterial*> pxMaterials;
m_materialManager.GetPxMaterials(materialSelection, pxMaterials);
AZStd::vector<AZStd::shared_ptr<Physics::Material>> genericMaterials;
genericMaterials.reserve(pxMaterials.size());
for (physx::PxMaterial* pxMaterial : pxMaterials)
{
genericMaterials.push_back(static_cast<PhysX::Material*>(pxMaterial->userData)->shared_from_this());
}
return genericMaterials;
}
AZStd::shared_ptr<Physics::Material> SystemComponent::GetDefaultMaterial()
{
return m_materialManager.GetDefaultMaterial();
}
AZStd::vector<AZ::TypeId> SystemComponent::GetSupportedJointTypes()
{
return JointUtils::GetSupportedJointTypes();
@@ -484,58 +463,6 @@ namespace PhysX
return m_physXSystem->GetPxCooking();
}
bool SystemComponent::UpdateMaterialSelection(const Physics::ShapeConfiguration& shapeConfiguration,
Physics::ColliderConfiguration& colliderConfiguration)
{
Physics::MaterialSelection& materialSelection = colliderConfiguration.m_materialSelection;
// If the material library is still not set, we can't update the material selection
if (!materialSelection.IsMaterialLibraryValid())
{
AZ_Warning("PhysX", false,
"UpdateMaterialSelection: Material Selection tried to use an invalid/non-existing Physics material library: \"%s\". "
"Please make sure the file exists or re-assign another library", materialSelection.GetMaterialLibraryAssetHint().c_str());
return false;
}
// If there's no material library data loaded, try to load it
if (materialSelection.GetMaterialLibraryAssetData() == nullptr)
{
AZ::Data::AssetId materialLibraryAssetId = materialSelection.GetMaterialLibraryAssetId();
materialSelection.SetMaterialLibrary(materialLibraryAssetId);
}
// If there's still not material library data, we can't update the material selection
if (materialSelection.GetMaterialLibraryAssetData() == nullptr)
{
AZ::Data::AssetId materialLibraryAssetId = materialSelection.GetMaterialLibraryAssetId();
auto materialLibraryAsset =
AZ::Data::AssetManager::Instance().GetAsset<Physics::MaterialLibraryAsset>(materialLibraryAssetId, AZ::Data::AssetLoadBehavior::Default);
materialLibraryAsset.BlockUntilLoadComplete();
// Log the asset path to help find out the incorrect library reference
AZStd::string assetPath = materialLibraryAsset.GetHint();
AZ_Warning("PhysX", false,
"UpdateMaterialSelection: Unable to load the material library for a material selection."
" Please check if the asset %s exists in the asset cache.", assetPath.c_str());
return false;
}
if (shapeConfiguration.GetShapeType() == Physics::ShapeType::PhysicsAsset)
{
const Physics::PhysicsAssetShapeConfiguration& assetConfiguration =
static_cast<const Physics::PhysicsAssetShapeConfiguration&>(shapeConfiguration);
// Use the materials data from the asset to update the collider data
return UpdateMaterialSelectionFromPhysicsAsset(assetConfiguration, colliderConfiguration);
}
return true;
}
void SystemComponent::OnTick(float deltaTime, [[maybe_unused]] AZ::ScriptTimePoint time)
{
if (m_physXSystem)
@@ -614,65 +541,4 @@ namespace PhysX
m_windProvider = AZStd::make_unique<WindProvider>();
}
bool SystemComponent::UpdateMaterialSelectionFromPhysicsAsset(
const Physics::PhysicsAssetShapeConfiguration& assetConfiguration,
Physics::ColliderConfiguration& colliderConfiguration)
{
Physics::MaterialSelection& materialSelection = colliderConfiguration.m_materialSelection;
if (!assetConfiguration.m_asset.GetId().IsValid())
{
// Set the default selection if there's no physics asset.
materialSelection.SetMaterialSlots(Physics::MaterialSelection::SlotsArray());
return false;
}
if (!assetConfiguration.m_asset.IsReady())
{
// The asset is valid but is still loading,
// Do not set the empty slots in this case to avoid the entity being in invalid state
return false;
}
Pipeline::MeshAsset* meshAsset = assetConfiguration.m_asset.GetAs<Pipeline::MeshAsset>();
if (!meshAsset)
{
materialSelection.SetMaterialSlots(Physics::MaterialSelection::SlotsArray());
AZ_Warning("PhysX", false, "UpdateMaterialSelectionFromPhysicsAsset: MeshAsset is invalid");
return false;
}
// Set the slots from the mesh asset
materialSelection.SetMaterialSlots(meshAsset->m_assetData.m_surfaceNames);
if (!assetConfiguration.m_useMaterialsFromAsset)
{
return false;
}
const Physics::MaterialLibraryAsset* materialLibrary = materialSelection.GetMaterialLibraryAssetData();
const AZStd::vector<AZStd::string>& meshMaterialNames = meshAsset->m_assetData.m_materialNames;
// Update material IDs in the selection for each slot
int slotIndex = 0;
for (const AZStd::string& meshMaterialName : meshMaterialNames)
{
Physics::MaterialFromAssetConfiguration materialData;
bool found = materialLibrary->GetDataForMaterialName(meshMaterialName, materialData);
AZ_Warning("PhysX", found,
"UpdateMaterialSelectionFromPhysicsAsset: No material found for surfaceType (%s) in the collider material library",
meshMaterialName.c_str());
if (found)
{
materialSelection.SetMaterialId(materialData.m_id, slotIndex);
}
slotIndex++;
}
return true;
}
} // namespace PhysX
-7
View File
@@ -114,8 +114,6 @@ namespace PhysX
// Physics::SystemRequestBus::Handler
AZStd::shared_ptr<Physics::Shape> CreateShape(const Physics::ColliderConfiguration& colliderConfiguration, const Physics::ShapeConfiguration& configuration) override;
AZStd::shared_ptr<Physics::Material> CreateMaterial(const Physics::MaterialConfiguration& materialConfiguration) override;
AZStd::shared_ptr<Physics::Material> GetDefaultMaterial() override;
AZStd::vector<AZStd::shared_ptr<Physics::Material>> CreateMaterialsFromLibrary(const Physics::MaterialSelection& materialSelection) override;
AZStd::vector<AZ::TypeId> GetSupportedJointTypes() override;
AZStd::shared_ptr<Physics::JointLimitConfiguration> CreateJointLimitConfiguration(AZ::TypeId jointType) override;
@@ -147,8 +145,6 @@ namespace PhysX
static bool VersionConverter(AZ::SerializeContext& context, AZ::SerializeContext::DataElementNode& classElement);
bool UpdateMaterialSelection(const Physics::ShapeConfiguration& shapeConfiguration,
Physics::ColliderConfiguration& colliderConfiguration) override;
private:
// AZ::TickBus::Handler ...
void OnTick(float deltaTime, AZ::ScriptTimePoint time) override;
@@ -157,9 +153,6 @@ namespace PhysX
void EnableAutoManagedPhysicsTick(bool shouldTick);
void ActivatePhysXSystem();
bool UpdateMaterialSelectionFromPhysicsAsset(
const Physics::PhysicsAssetShapeConfiguration& assetConfiguration,
Physics::ColliderConfiguration& colliderConfiguration);
bool m_enabled; ///< If false, this component will not activate itself in the Activate() function.
-42
View File
@@ -607,48 +607,6 @@ namespace PhysX
return true;
}
void GetMaterialList(
AZStd::vector<physx::PxMaterial*>& pxMaterials, const AZStd::vector<int>& terrainSurfaceIdIndexMapping,
const Physics::TerrainMaterialSurfaceIdMap& terrainMaterialsToSurfaceIds)
{
pxMaterials.reserve(terrainSurfaceIdIndexMapping.size());
AZStd::shared_ptr<Material> defaultMaterial;
MaterialManagerRequestsBus::BroadcastResult(defaultMaterial, &MaterialManagerRequestsBus::Events::GetDefaultMaterial);
if (terrainSurfaceIdIndexMapping.empty())
{
pxMaterials.push_back(defaultMaterial->GetPxMaterial());
return;
}
AZStd::vector<physx::PxMaterial*> materials;
for (auto& surfaceId : terrainSurfaceIdIndexMapping)
{
const auto& userAssignedMaterials = terrainMaterialsToSurfaceIds;
const auto& matSelectionIterator = userAssignedMaterials.find(surfaceId);
if (matSelectionIterator != userAssignedMaterials.end())
{
MaterialManagerRequestsBus::Broadcast(&MaterialManagerRequests::GetPxMaterials, matSelectionIterator->second, materials);
if (!materials.empty())
{
pxMaterials.push_back(materials.front());
}
else
{
AZ_Error("PhysX", false, "Creating materials: array with materials can't be empty");
pxMaterials.push_back(defaultMaterial->GetPxMaterial());
}
}
else
{
pxMaterials.push_back(defaultMaterial->GetPxMaterial());
}
}
}
AZStd::string ReplaceAll(AZStd::string str, const AZStd::string& fromString, const AZStd::string& toString) {
size_t positionBegin = 0;
while ((positionBegin = str.find(fromString, positionBegin)) != AZStd::string::npos)
-3
View File
@@ -115,9 +115,6 @@ namespace PhysX
bool MeshDataToPxGeometry(physx::PxBase* meshData, physx::PxGeometryHolder &pxGeometry, const AZ::Vector3& scale);
void GetMaterialList(
AZStd::vector<physx::PxMaterial*>& pxMaterials, const AZStd::vector<int>& materialIndexMapping,
const Physics::TerrainMaterialSurfaceIdMap& terrainMaterialsToSurfaceIds);
//! Returns all connected busIds of the specified type.
template<typename BusT>
AZStd::vector<typename BusT::BusIdType> FindConnectedBusIds()
@@ -1,181 +0,0 @@
/*
* 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 <PhysX_precompiled.h>
#include <AzTest/AzTest.h>
#include <PhysX/SystemComponentBus.h>
#include <AzCore/Asset/AssetManager.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/Interface/Interface.h>
#include <AzFramework/Physics/SystemBus.h>
#include <AzFramework/Physics/PhysicsSystem.h>
namespace PhysX
{
class MaterialLibraryTest_MockCatalog
: public AZ::Data::AssetCatalog
, public AZ::Data::AssetCatalogRequestBus::Handler
{
private:
AZ::Uuid m_randomUuid = AZ::Uuid::CreateRandom();
AZStd::vector<AZ::Data::AssetId> m_mockAssetIds;
public:
AZ_CLASS_ALLOCATOR(MaterialLibraryTest_MockCatalog, AZ::SystemAllocator, 0);
MaterialLibraryTest_MockCatalog()
{
AZ::Data::AssetCatalogRequestBus::Handler::BusConnect();
}
~MaterialLibraryTest_MockCatalog()
{
AZ::Data::AssetCatalogRequestBus::Handler::BusDisconnect();
}
AZ::Data::AssetId GenerateMockAssetId()
{
AZ::Data::AssetId assetId = AZ::Data::AssetId(AZ::Uuid::CreateRandom(), 0);
m_mockAssetIds.push_back(assetId);
return assetId;
}
//////////////////////////////////////////////////////////////////////////
// AssetCatalogRequestBus
AZ::Data::AssetInfo GetAssetInfoById(const AZ::Data::AssetId& id) override
{
AZ::Data::AssetInfo result;
result.m_assetType = AZ::AzTypeInfo<Physics::MaterialLibraryAsset>::Uuid();
auto foundId = AZStd::find(m_mockAssetIds.begin(), m_mockAssetIds.end(), id);
if (foundId != m_mockAssetIds.end())
{
result.m_assetId = *foundId;
}
return result;
}
//////////////////////////////////////////////////////////////////////////
AZ::Data::AssetStreamInfo GetStreamInfoForLoad(const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) override
{
EXPECT_TRUE(type == AZ::AzTypeInfo<Physics::MaterialLibraryAsset>::Uuid());
AZ::Data::AssetStreamInfo info;
info.m_dataOffset = 0;
info.m_streamFlags = AZ::IO::OpenMode::ModeRead;
for (int i = 0; i < m_mockAssetIds.size(); ++i)
{
if (m_mockAssetIds[i] == id)
{
info.m_streamName = AZStd::string::format("MaterialLibraryAssetName%d", i);
}
}
if (!info.m_streamName.empty())
{
// this ensures tha parallel running unit tests do not overlap their files that they use.
AZStd::string fullName = AZStd::string::format("%s-%s", m_randomUuid.ToString<AZStd::string>().c_str(), info.m_streamName.c_str());
info.m_streamName = fullName;
info.m_dataLen = static_cast<size_t>(AZ::IO::SystemFile::Length(info.m_streamName.c_str()));
}
else
{
info.m_dataLen = 0;
}
return info;
}
AZ::Data::AssetStreamInfo GetStreamInfoForSave(const AZ::Data::AssetId& id, const AZ::Data::AssetType& type) override
{
AZ::Data::AssetStreamInfo info;
info = GetStreamInfoForLoad(id, type);
info.m_streamFlags = AZ::IO::OpenMode::ModeWrite;
return info;
}
bool SaveAsset(AZ::Data::Asset<Physics::MaterialLibraryAsset>& asset)
{
volatile bool isDone = false;
volatile bool succeeded = false;
AZ::Data::AssetBusCallbacks callbacks;
callbacks.SetCallbacks(nullptr, nullptr, nullptr,
[&isDone, &succeeded](const AZ::Data::Asset<AZ::Data::AssetData>& /*asset*/, bool isSuccessful, AZ::Data::AssetBusCallbacks& /*callbacks*/)
{
isDone = true;
succeeded = isSuccessful;
}, nullptr, nullptr, nullptr);
callbacks.BusConnect(asset.GetId());
asset.Save();
while (!isDone)
{
AZ::Data::AssetManager::Instance().DispatchEvents();
}
return succeeded;
}
};
class DISABLED_PhysXMaterialLibraryTest
: public ::testing::Test
{
protected:
void SetUp() override
{
m_catalog = AZStd::make_unique<MaterialLibraryTest_MockCatalog>();
AZ::Data::AssetManager::Instance().RegisterCatalog(m_catalog.get(), AZ::AzTypeInfo<Physics::MaterialLibraryAsset>::Uuid());
}
void TearDown() override
{
AZ::Data::AssetManager::Instance().UnregisterCatalog(m_catalog.get());
}
AZStd::unique_ptr<MaterialLibraryTest_MockCatalog> m_catalog;
};
TEST_F(DISABLED_PhysXMaterialLibraryTest, DISABLED_DefaultMaterialLibrary_CorrectMaterialLibraryIsInferred)
{
AZ::Data::Asset<Physics::MaterialLibraryAsset> materialLibrary = AZ::Interface<AzPhysics::SystemInterface>::Get()->GetDefaultMaterialLibrary();
AZ::Data::AssetId dummyAssetId = AZ::Data::AssetId(AZ::Uuid::CreateName("DummyLibrary.physmaterial"));
AZ::Data::Asset<Physics::MaterialLibraryAsset> dummyMaterialLibAsset = AZ::Data::AssetManager::Instance().GetAsset<Physics::MaterialLibraryAsset>(dummyAssetId, AZ::Data::AssetLoadBehavior::Default);
materialLibrary = dummyMaterialLibAsset;
AZ::Interface<AzPhysics::SystemInterface>::Get()->UpdateDefaultMaterialLibrary(materialLibrary);
// We must have now a default material library setup
ASSERT_TRUE(materialLibrary.GetId().IsValid());
AZ::Data::AssetId otherDummyAssetId = AZ::Data::AssetId(AZ::Uuid::CreateName("OtherDummyLibrary.physmaterial"));
AZ::Data::Asset<Physics::MaterialLibraryAsset> otherDummyMaterialLibAsset = AZ::Data::AssetManager::Instance().GetAsset<Physics::MaterialLibraryAsset>(otherDummyAssetId, AZ::Data::AssetLoadBehavior::Default);
// Set selection's material library to a different one than default material library
Physics::MaterialSelection selectionTest;
selectionTest.SetMaterialLibrary(otherDummyAssetId);
ASSERT_TRUE(selectionTest.GetMaterialLibraryAssetId().IsValid());
ASSERT_EQ(selectionTest.GetMaterialLibraryAssetId(), selectionTest.GetMaterialLibraryAssetId());
ASSERT_NE(selectionTest.GetMaterialLibraryAssetId(), materialLibrary.GetId());
// By reseting the selection, now it should infer to the default material library set in the global configuration
selectionTest.ResetToDefaultMaterialLibrary();
ASSERT_TRUE(selectionTest.GetMaterialLibraryAssetId().IsValid());
ASSERT_EQ(selectionTest.GetMaterialLibraryAssetId(), materialLibrary.GetId());
// Release material library so we exit gracefully
materialLibrary = {};
AZ::Interface<AzPhysics::SystemInterface>::Get()->UpdateDefaultMaterialLibrary(materialLibrary);
}
}
-1
View File
@@ -23,7 +23,6 @@ set(FILES
Tests/PhysXGenericTest.cpp
Tests/PhysXSpecificTest.cpp
Tests/PhysXForceRegionTest.cpp
Tests/PhysXMaterialLibraryTest.cpp
Tests/PhysXCollisionFilteringTest.cpp
Tests/PhysXJointsTest.cpp
Tests/PhysXSceneTests.cpp
@@ -207,8 +207,8 @@ namespace ScriptCanvasPhysicsTests
{
public:
MOCK_CONST_METHOD0(GetSurfaceType, AZ::Crc32());
MOCK_METHOD1(SetSurfaceType, void(AZ::Crc32));
MOCK_CONST_METHOD0(GetSurfaceTypeName, const AZStd::string&());
MOCK_METHOD1(SetSurfaceTypeName, void(const AZStd::string&));
MOCK_CONST_METHOD0(GetDynamicFriction, float());
MOCK_METHOD1(SetDynamicFriction, void(float));
MOCK_CONST_METHOD0(GetStaticFriction, float());
@@ -223,6 +223,8 @@ namespace ScriptCanvasPhysicsTests
MOCK_METHOD0(GetNativePointer, void*());
MOCK_CONST_METHOD0(GetDensity, float());
MOCK_METHOD1(SetDensity, void(float));
MOCK_CONST_METHOD0(GetDebugColor, AZ::Color());
MOCK_METHOD1(SetDebugColor, void(const AZ::Color&));
};
class ScriptCanvasPhysicsTestEnvironment