Files
o3de/Gems/Blast/Code/Source/Common/BlastMaterial.cpp
T
Esteban Papp 1f9b284de2 Merge branch 'development' into cmake/SPEC-7179
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>

# Conflicts:
#	Code/Editor/Plugins/ComponentEntityEditorPlugin/ComponentEntityEditorPlugin_precompiled.h
#	Code/Editor/Plugins/EditorCommon/EditorCommon_precompiled.h
#	Code/Editor/Plugins/EditorCommon/stdafx.cpp
#	Code/Editor/Plugins/FFMPEGPlugin/FFMPEGPlugin_precompiled.h
#	Code/Editor/Plugins/PerforcePlugin/PerforcePlugin_precompiled.h
#	Code/Editor/Plugins/ProjectSettingsTool/ProjectSettingsTool_precompiled.h
#	Code/Framework/AzToolsFramework/AzToolsFramework/AzToolsFramework_precompiled.h
#	Code/Tools/AssetProcessor/native/precompiled.h
#	Code/Tools/Standalone/StandaloneTools_precompiled.h
#	Gems/AssetMemoryAnalyzer/Code/Source/AssetMemoryAnalyzer_precompiled.h
#	Gems/Atom/Asset/ImageProcessingAtom/Code/Source/ImageProcessing_precompiled.h
#	Gems/Atom/RHI/DX12/Code/Source/RHI/Atom_RHI_DX12_precompiled.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/Mac/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Include/Platform/iOS/Atom_RHI_Metal_precompiled_Platform.h
#	Gems/Atom/RHI/Metal/Code/Source/Atom_RHI_Metal_precompiled.h
#	Gems/Atom/RHI/Metal/Code/atom_rhi_metal_common_files.cmake
#	Gems/Atom/RHI/Null/Code/Source/Atom_RHI_Null_precompiled.h
#	Gems/Atom/RHI/Null/Code/atom_rhi_null_common_files.cmake
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Android/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Linux/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Mac/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Include/Platform/Windows/Atom_RHI_Vulkan_precompiled_Platform.h
#	Gems/Atom/RHI/Vulkan/Code/Source/Atom_RHI_Vulkan_precompiled.h
#	Gems/Atom/RHI/Vulkan/Code/Source/RHI/SwapChain.cpp
#	Gems/Atom/RHI/Vulkan/Code/atom_rhi_vulkan_common_files.cmake
#	Gems/AtomLyIntegration/AtomFont/Code/Include/AtomLyIntegration/AtomFont/AtomFont_precompiled.h
#	Gems/Blast/Code/Source/StdAfx.cpp
#	Gems/Camera/Code/Source/Camera_precompiled.h
#	Gems/EMotionFX/Code/Source/EMotionFX_precompiled.h
#	Gems/FastNoise/Code/Source/FastNoise_precompiled.h
#	Gems/Gestures/Code/Source/Gestures_precompiled.h
#	Gems/GradientSignal/Code/Source/GradientSignal_precompiled.h
#	Gems/GraphCanvas/Code/precompiled.h
#	Gems/ImGui/Code/Source/ImGui_precompiled.h
#	Gems/InAppPurchases/Code/Source/InAppPurchases_precompiled.h
#	Gems/LmbrCentral/Code/Source/LmbrCentral_precompiled.h
#	Gems/LmbrCentral/Code/Tests/ShapeGeometryUtilTest.cpp
#	Gems/LyShine/Code/Editor/UiCanvasEditor_precompiled.h
#	Gems/LyShine/Code/Source/Animation/LyShine_precompiled.h
#	Gems/LyShine/Code/Source/LyShine_precompiled.h
#	Gems/LyShineExamples/Code/Source/LyShineExamples_precompiled.h
#	Gems/Maestro/Code/Source/Cinematics/Maestro_precompiled.h
#	Gems/Maestro/Code/Source/Maestro_precompiled.h
#	Gems/MessagePopup/Code/Source/MessagePopup_precompiled.h
#	Gems/Metastream/Code/Source/Metastream_precompiled.h
#	Gems/Microphone/Code/Source/Microphone_precompiled.h
#	Gems/Multiplayer/Code/Source/Multiplayer_precompiled.h
#	Gems/PhysX/Code/NumericalMethods/Source/NumericalMethods_precompiled.h
#	Gems/PhysX/Code/Source/PhysXUnsupported_precompiled.h
#	Gems/PhysX/Code/Source/PhysX_precompiled.h
#	Gems/PhysX/Code/physx_unsupported_files.cmake
#	Gems/PhysXDebug/Code/Source/PhysXDebugUnsupported_precompiled.h
#	Gems/PhysXDebug/Code/Source/PhysXDebug_precompiled.h
#	Gems/ScriptCanvas/Code/Editor/precompiled.h
#	Gems/ScriptCanvas/Code/Source/precompiled.h
#	Gems/ScriptCanvasDeveloper/Code/Source/precompiled.h
#	Gems/ScriptCanvasPhysics/Code/Source/ScriptCanvasPhysics_precompiled.h
#	Gems/ScriptEvents/Code/Source/precompiled.h
#	Gems/ScriptEvents/Code/Tests/Editor/EditorTests.cpp
#	Gems/ScriptedEntityTweener/Code/Source/ScriptedEntityTweener_precompiled.h
#	Gems/SliceFavorites/Code/Source/SliceFavorites_precompiled.h
#	Gems/StartingPointCamera/Code/Source/StartingPointCamera_precompiled.h
#	Gems/StartingPointInput/Code/Source/StartingPointInput_precompiled.h
#	Gems/StartingPointMovement/Code/Source/StartingPointMovement_precompiled.h
#	Gems/SurfaceData/Code/Source/SurfaceData_precompiled.h
#	Gems/TextureAtlas/Code/Source/TextureAtlas_precompiled.h
#	Gems/TickBusOrderViewer/Code/Source/TickBusOrderViewer_precompiled.h
#	Gems/Twitch/Code/Source/Twitch_precompiled.h
#	Gems/VirtualGamepad/Code/Source/VirtualGamepad_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBoxUnsupported_precompiled.h
#	Gems/WhiteBox/Code/Source/WhiteBox_precompiled.h
2021-07-16 15:42:37 -07:00

336 lines
14 KiB
C++

/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/Serialization/EditContext.h>
#include <AzCore/Serialization/SerializeContext.h>
#include <Blast/BlastMaterial.h>
#include <NvBlastExtDamageShaders.h>
namespace
{
const AZ::Data::Asset<Blast::BlastMaterialLibraryAsset> s_invalidMaterialLibrary = {
AZ::Data::AssetLoadBehavior::NoLoad};
} // namespace
namespace Blast
{
class BlastMaterialLibraryAssetEventHandler : public AZ::SerializeContext::IEventHandler
{
void OnReadBegin(void* classPtr)
{
auto matAsset = static_cast<BlastMaterialLibraryAsset*>(classPtr);
matAsset->GenerateMissingIds();
}
};
void BlastMaterialConfiguration::Reflect(AZ::ReflectContext* context)
{
BlastMaterialId::Reflect(context);
BlastMaterialFromAssetConfiguration::Reflect(context);
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<BlastMaterialConfiguration>()
->Version(1)
->Field("MaterialName", &BlastMaterialConfiguration::m_materialName)
->Field("Health", &BlastMaterialConfiguration::m_health)
->Field("ForceDivider", &BlastMaterialConfiguration::m_forceDivider)
->Field("MinDamageThreshold", &BlastMaterialConfiguration::m_minDamageThreshold)
->Field("MaxDamageThreshold", &BlastMaterialConfiguration::m_maxDamageThreshold)
->Field("StressLinearFactor", &BlastMaterialConfiguration::m_stressLinearFactor)
->Field("StressAngularFactor", &BlastMaterialConfiguration::m_stressAngularFactor);
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<BlastMaterialConfiguration>("", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "Blast Material")
->DataElement(
AZ::Edit::UIHandlers::Default, &BlastMaterialConfiguration::m_materialName, "Material name",
"Name of the material")
->Attribute(AZ::Edit::Attributes::MaxLength, 64)
->DataElement(
AZ::Edit::UIHandlers::Default, &BlastMaterialConfiguration::m_health, "Health",
"All damage is subtracted from this value")
->Attribute(AZ::Edit::Attributes::Min, 0.f)
->DataElement(
AZ::Edit::UIHandlers::Default, &BlastMaterialConfiguration::m_forceDivider, "Force divider",
"All damage which originates with force is divided by this amount")
->Attribute(AZ::Edit::Attributes::Min, 0.f)
->DataElement(
AZ::Edit::UIHandlers::Default, &BlastMaterialConfiguration::m_minDamageThreshold,
"Minimum damage threshold", "Incoming damage is discarded if it is less than this value")
->Attribute(AZ::Edit::Attributes::Min, 0.f)
->DataElement(
AZ::Edit::UIHandlers::Default, &BlastMaterialConfiguration::m_maxDamageThreshold,
"Maximum damage threshold", "Incoming damage is capped at this value")
->Attribute(AZ::Edit::Attributes::Min, 0.f)
->DataElement(
AZ::Edit::UIHandlers::Default, &BlastMaterialConfiguration::m_stressLinearFactor,
"Stress linear factor",
"Factor with which linear stress such as gravity, direct impulse, collision is applied")
->Attribute(AZ::Edit::Attributes::Min, 0.f)
->DataElement(
AZ::Edit::UIHandlers::Default, &BlastMaterialConfiguration::m_stressAngularFactor,
"Stress angular factor", "Factor with which angular stress is applied")
->Attribute(AZ::Edit::Attributes::Min, 0.f);
}
}
}
void BlastMaterialLibraryAsset::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<BlastMaterialLibraryAsset>()
->Version(1)
->Attribute(AZ::Edit::Attributes::EnableForAssetEditor, true)
->EventHandler<BlastMaterialLibraryAssetEventHandler>()
->Field("Properties", &BlastMaterialLibraryAsset::m_materialLibrary);
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<BlastMaterialLibraryAsset>("", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(
AZ::Edit::UIHandlers::Default, &BlastMaterialLibraryAsset::m_materialLibrary, "Blast Materials",
"List of blast materials")
->Attribute("EditButton", "")
->Attribute(AZ::Edit::Attributes::ForceAutoExpand, true);
}
}
}
void BlastActorConfiguration::Reflect(AZ::ReflectContext* context)
{
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<BlastActorConfiguration>()
->Version(1)
->Field("CollisionLayer", &BlastActorConfiguration::m_collisionLayer)
->Field("CollisionGroupId", &BlastActorConfiguration::m_collisionGroupId)
->Field("Simulated", &BlastActorConfiguration::m_isSimulated)
->Field("InSceneQueries", &BlastActorConfiguration::m_isInSceneQueries)
->Field("CcdEnabled", &BlastActorConfiguration::m_isCcdEnabled)
->Field("ColliderTag", &BlastActorConfiguration::m_tag);
if (auto editContext = serializeContext->GetEditContext())
{
editContext->Class<BlastActorConfiguration>("BlastActorConfiguration", "Configuration for a collider")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->DataElement(
AZ::Edit::UIHandlers::Default, &BlastActorConfiguration::m_isSimulated, "Simulated",
"If set, this actor's collider will partake in collision in the physical simulation")
->DataElement(
AZ::Edit::UIHandlers::Default, &BlastActorConfiguration::m_isInSceneQueries, "In Scene Queries",
"If set, this actor's collider will be visible for scene queries")
->DataElement(
AZ::Edit::UIHandlers::Default, &BlastActorConfiguration::m_isCcdEnabled, "CCD Enabled",
"If set, actor's rigid body will have CCD enabled")
->DataElement(
AZ::Edit::UIHandlers::Default, &BlastActorConfiguration::m_collisionLayer, "Collision Layer",
"The collision layer assigned to the collider")
->DataElement(
AZ::Edit::UIHandlers::Default, &BlastActorConfiguration::m_collisionGroupId, "Collides With",
"The collision group containing the layers this collider collides with")
->DataElement(
AZ::Edit::UIHandlers::Default, &BlastActorConfiguration::m_tag, "Tag",
"Tag used to identify colliders from one another");
}
}
}
void BlastMaterialFromAssetConfiguration::Reflect(AZ::ReflectContext* context)
{
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<BlastMaterialFromAssetConfiguration>()
->Version(1)
->Field("Configuration", &BlastMaterialFromAssetConfiguration::m_configuration)
->Field("UID", &BlastMaterialFromAssetConfiguration::m_id);
AZ::EditContext* editContext = serializeContext->GetEditContext();
if (editContext)
{
editContext->Class<BlastMaterialFromAssetConfiguration>("", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(
AZ::Edit::UIHandlers::Default, &BlastMaterialFromAssetConfiguration::m_configuration,
"Blast Material", "Blast Material properties")
->Attribute(AZ::Edit::Attributes::ForceAutoExpand, true);
}
}
}
void BlastMaterialId::Reflect(AZ::ReflectContext* context)
{
if (AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<Blast::BlastMaterialId>()->Version(1)->Field(
"BlastMaterialId", &Blast::BlastMaterialId::m_id);
}
}
BlastMaterial::BlastMaterial(const BlastMaterialConfiguration& configuration)
{
m_health = configuration.m_health;
// This is not an error, health in ExtPxMaterial is actually damage divider and not health
m_material.health = configuration.m_forceDivider;
m_material.minDamageThreshold = configuration.m_minDamageThreshold;
m_material.maxDamageThreshold = configuration.m_maxDamageThreshold;
m_stressLinearFactor = configuration.m_stressLinearFactor;
m_stressAngularFactor = configuration.m_stressAngularFactor;
m_name = configuration.m_materialName;
}
const AZStd::string& BlastMaterial::GetMaterialName() const
{
return m_name;
}
float BlastMaterial::GetHealth() const
{
return m_health;
}
float BlastMaterial::GetForceDivider() const
{
return m_material.health;
}
float BlastMaterial::GetMinDamageThreshold() const
{
return m_material.minDamageThreshold;
}
float BlastMaterial::GetMaxDamageThreshold() const
{
return m_material.maxDamageThreshold;
}
float BlastMaterial::GetStressLinearFactor() const
{
return m_stressLinearFactor;
}
float BlastMaterial::GetStressAngularFactor() const
{
return m_stressAngularFactor;
}
float BlastMaterial::GetNormalizedDamage(const float damage) const
{
return m_material.getNormalizedDamage(damage * m_material.health);
}
Nv::Blast::ExtStressSolverSettings BlastMaterial::GetStressSolverSettings(uint32_t iterationsCount) const
{
auto settings = Nv::Blast::ExtStressSolverSettings();
settings.hardness = m_material.health;
settings.stressLinearFactor = m_stressLinearFactor;
settings.stressAngularFactor = m_stressAngularFactor;
settings.graphReductionLevel = 0;
settings.bondIterationsPerFrame = iterationsCount;
return settings;
}
void* BlastMaterial::GetNativePointer()
{
return &m_material;
}
bool BlastMaterialLibraryAsset::GetDataForMaterialId(
const BlastMaterialId& materialId, BlastMaterialFromAssetConfiguration& configuration) const
{
const auto foundMaterialConfiguration = AZStd::find_if(
m_materialLibrary.begin(), m_materialLibrary.end(),
[materialId](const auto& data)
{
return data.m_id == materialId;
});
if (foundMaterialConfiguration != m_materialLibrary.end())
{
configuration = *foundMaterialConfiguration;
return true;
}
return false;
}
bool BlastMaterialLibraryAsset::HasDataForMaterialId(const BlastMaterialId& materialId) const
{
auto foundMaterialConfiguration = AZStd::find_if(
m_materialLibrary.begin(), m_materialLibrary.end(),
[materialId](const auto& data)
{
return data.m_id == materialId;
});
return foundMaterialConfiguration != m_materialLibrary.end();
}
bool BlastMaterialLibraryAsset::GetDataForMaterialName(
const AZStd::string& materialName, BlastMaterialFromAssetConfiguration& configuration) const
{
auto foundMaterialConfiguration = AZStd::find_if(
m_materialLibrary.begin(), m_materialLibrary.end(),
[&materialName](const auto& data)
{
return data.m_configuration.m_materialName == materialName;
});
if (foundMaterialConfiguration != m_materialLibrary.end())
{
configuration = *foundMaterialConfiguration;
return true;
}
return false;
}
void BlastMaterialLibraryAsset::AddMaterialData(const BlastMaterialFromAssetConfiguration& data)
{
BlastMaterialFromAssetConfiguration existingConfiguration;
if (!data.m_id.IsNull() && GetDataForMaterialId(data.m_id, existingConfiguration))
{
AZ_Warning("BlastMaterialLibraryAsset", false, "Trying to add material that already exists");
return;
}
m_materialLibrary.push_back(data);
GenerateMissingIds();
}
void BlastMaterialLibraryAsset::GenerateMissingIds()
{
for (auto& materialData : m_materialLibrary)
{
if (materialData.m_id.IsNull())
{
materialData.m_id = BlastMaterialId::Create();
}
}
}
BlastMaterialId BlastMaterialId::Create()
{
BlastMaterialId id;
id.m_id = AZ::Uuid::Create();
return id;
}
} // namespace Blast