/
redgpu
/
ezEngine
Обзор
Документация
Войти
/
redgpu
/
ezEngine
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
Аналитика
Безопасность
dev
Code/EnginePlugins/JoltPlugin/Components/Implementation/JoltVisColMeshComponent.cpp
249 строк
8 KB
Jan Krassnigg
Fixed #1848: Broken collision mesh preview (#1849)
06 мар 2026, 11:29
Не верифицирован
06 мар 2026, 11:29
9d6f053
Код
Авторство
О чём код?
#include <JoltPlugin/JoltPluginPCH.h> #include <Core/WorldSerializer/WorldReader.h> #include <Core/WorldSerializer/WorldWriter.h> #include <JoltPlugin/Actors/JoltStaticActorComponent.h> #include <JoltPlugin/Components/JoltVisColMeshComponent.h> #include <JoltPlugin/Shapes/JoltShapeConvexHullComponent.h> #include <RendererCore/Meshes/CpuMeshResource.h> #include <RendererCore/Pipeline/RenderDataManager.h> // clang-format off EZ_BEGIN_COMPONENT_TYPE(ezJoltVisColMeshComponent, 1, ezComponentMode::Static) { EZ_BEGIN_PROPERTIES { EZ_RESOURCE_ACCESSOR_PROPERTY("CollisionMesh", GetMesh, SetMesh)->AddAttributes(new ezAssetBrowserAttribute("CompatibleAsset_Jolt_Colmesh_Triangle;CompatibleAsset_Jolt_Colmesh_Convex", ezDependencyFlags::Package)), } EZ_END_PROPERTIES; EZ_BEGIN_MESSAGEHANDLERS { EZ_MESSAGE_HANDLER(ezMsgExtractRenderData, OnMsgExtractRenderData), } EZ_END_MESSAGEHANDLERS; EZ_BEGIN_ATTRIBUTES { new ezCategoryAttribute("Physics/Jolt/Misc"), } EZ_END_ATTRIBUTES; } EZ_END_DYNAMIC_REFLECTED_TYPE; // clang-format on ezJoltVisColMeshComponent::ezJoltVisColMeshComponent() = default; ezJoltVisColMeshComponent::~ezJoltVisColMeshComponent() = default; void ezJoltVisColMeshComponent::SerializeComponent(ezWorldWriter& inout_stream) const { SUPER::SerializeComponent(inout_stream); auto& s = inout_stream.GetStream(); s << m_hCollisionMesh; } void ezJoltVisColMeshComponent::DeserializeComponent(ezWorldReader& inout_stream) { SUPER::DeserializeComponent(inout_stream); // const ezUInt32 uiVersion = inout_stream.GetComponentTypeVersion(GetStaticRTTI()); auto& s = inout_stream.GetStream(); s >> m_hCollisionMesh; GetWorld()->GetOrCreateComponentManager<ezJoltVisColMeshComponentManager>()->EnqueueUpdate(GetHandle()); } ezResult ezJoltVisColMeshComponent::GetLocalBounds(ezBoundingBoxSphere& ref_bounds, bool& ref_bAlwaysVisible, ezMsgUpdateLocalBounds& ref_msg) { // have to assume this isn't thread safe // CreateCollisionRenderMesh(); if (m_hMesh.IsValid()) { ezResourceLock<ezMeshResource> pMesh(m_hMesh, ezResourceAcquireMode::BlockTillLoaded); ref_bounds = pMesh->GetBounds(); return EZ_SUCCESS; } return EZ_FAILURE; } void ezJoltVisColMeshComponent::SetMesh(const ezJoltMeshResourceHandle& hMesh) { if (m_hCollisionMesh != hMesh) { m_hCollisionMesh = hMesh; m_hMesh.Invalidate(); GetWorld()->GetOrCreateComponentManager<ezJoltVisColMeshComponentManager>()->EnqueueUpdate(GetHandle()); } } void ezJoltVisColMeshComponent::CreateCollisionRenderMesh() { if (!m_hCollisionMesh.IsValid()) { ezJoltStaticActorComponent* pSibling = nullptr; if (GetOwner()->TryGetComponentOfBaseType(pSibling)) { m_hCollisionMesh = pSibling->GetMesh(); } } if (!m_hCollisionMesh.IsValid()) { ezJoltShapeConvexHullComponent* pSibling = nullptr; if (GetOwner()->TryGetComponentOfBaseType(pSibling)) { m_hCollisionMesh = pSibling->GetMesh(); } } if (!m_hCollisionMesh.IsValid()) return; ezResourceLock<ezJoltMeshResource> pMesh(m_hCollisionMesh, ezResourceAcquireMode::BlockTillLoaded); if (pMesh.GetAcquireResult() == ezResourceAcquireResult::MissingFallback) return; ezStringBuilder sColMeshName = pMesh->GetResourceID(); sColMeshName.AppendFormat("_{0}_JoltVisColMesh", pMesh->GetCurrentResourceChangeCounter()); // the change counter allows to react to resource updates m_hMesh = ezResourceManager::GetExistingResource<ezMeshResource>(sColMeshName); if (m_hMesh.IsValid()) { TriggerLocalBoundsUpdate(); return; } ezCpuMeshResourceHandle hCpuMesh = pMesh->ConvertToCpuMesh(); if (!hCpuMesh.IsValid()) return; ezResourceLock<ezCpuMeshResource> pCpuMesh(hCpuMesh, ezResourceAcquireMode::BlockTillLoaded); ezMeshResourceDescriptor md = pCpuMesh->GetDescriptor(); // replace all materials with the preview material // actually the existing materials here are the surfaces of the collision mesh // so this can't be used for rendering anyway for (ezUInt32 i = 0; i < md.GetMaterials().GetCount(); ++i) { md.SetMaterial(i, "Materials/Common/ColMesh.ezMaterial"); } m_hMesh = ezResourceManager::GetOrCreateResource<ezMeshResource>(sColMeshName, std::move(md), "Collision Mesh Visualization"); TriggerLocalBoundsUpdate(); } void ezJoltVisColMeshComponent::Initialize() { SUPER::Initialize(); GetWorld()->GetOrCreateComponentManager<ezJoltVisColMeshComponentManager>()->EnqueueUpdate(GetHandle()); } void ezJoltVisColMeshComponent::OnDeactivated() { ezRenderDataManager* pRenderDataManager = GetWorld()->GetModule<ezRenderDataManager>(); pRenderDataManager->DeleteInstanceData(m_InstanceDataOffset); SUPER::OnDeactivated(); } void ezJoltVisColMeshComponent::OnMsgExtractRenderData(ezMsgExtractRenderData& msg) const { if (!m_hMesh.IsValid()) return; const bool bDynamic = GetOwner()->IsDynamic(); auto hInstanceDataBuffer = msg.m_pRenderDataManager->GetOrCreateInstanceDataAndFill(*this, bDynamic, GetOwner()->GetGlobalTransform(), m_InstanceDataOffset, GetUniqueIdForRendering()); ezResourceLock<ezMeshResource> pMesh(m_hMesh, ezResourceAcquireMode::AllowLoadingFallback); ezArrayPtr<const ezMeshResourceDescriptor::SubMesh> parts = pMesh->GetSubMeshes(); for (ezUInt32 uiPartIndex = 0; uiPartIndex < parts.GetCount(); ++uiPartIndex) { const ezUInt32 uiMaterialIndex = parts[uiPartIndex].m_uiMaterialIndex; ezMaterialResourceHandle hMaterial = pMesh->GetMaterials()[uiMaterialIndex]; ezMeshRenderData* pRenderData = msg.m_pRenderDataManager->CreateRenderDataForThisFrame<ezMeshRenderData>(GetOwner()); pRenderData->SetFallbackGlobalBounds(GetOwner()->GetGlobalBounds()); pRenderData->Fill(m_InstanceDataOffset, hInstanceDataBuffer, hMaterial, m_hMesh, uiMaterialIndex, uiPartIndex); msg.AddRenderData(pRenderData, ezDefaultRenderDataCategories::LitOpaque, ezRenderData::Caching::IfStatic); } } ////////////////////////////////////////////////////////////////////////// void ezJoltVisColMeshComponentManager::Initialize() { SUPER::Initialize(); ezWorldModule::UpdateFunctionDesc desc = EZ_CREATE_MODULE_UPDATE_FUNCTION_DESC(ezJoltVisColMeshComponentManager::Update, this); desc.m_Phase = ezWorldUpdatePhase::PreAsync; RegisterUpdateFunction(desc); ezResourceManager::GetResourceEvents().AddEventHandler(ezMakeDelegate(&ezJoltVisColMeshComponentManager::ResourceEventHandler, this)); } void ezJoltVisColMeshComponentManager::Deinitialize() { EZ_LOCK(m_Mutex); ezResourceManager::GetResourceEvents().RemoveEventHandler(ezMakeDelegate(&ezJoltVisColMeshComponentManager::ResourceEventHandler, this)); SUPER::Deinitialize(); } void ezJoltVisColMeshComponentManager::Update(const ezWorldModule::UpdateContext& context) { ezDeque<ezComponentHandle> requireUpdate; m_RequireUpdate.Swap(requireUpdate); for (const auto& hComp : requireUpdate) { ezJoltVisColMeshComponent* pComp = nullptr; if (!TryGetComponent(hComp, pComp)) continue; pComp->CreateCollisionRenderMesh(); } } void ezJoltVisColMeshComponentManager::EnqueueUpdate(ezComponentHandle hComponent) { m_RequireUpdate.PushBack(hComponent); } void ezJoltVisColMeshComponentManager::ResourceEventHandler(const ezResourceEvent& e) { if ((e.m_Type == ezResourceEvent::Type::ResourceContentUnloading || e.m_Type == ezResourceEvent::Type::ResourceContentUpdated) && e.m_pResource->GetDynamicRTTI()->IsDerivedFrom<ezJoltMeshResource>()) { EZ_LOCK(m_Mutex); ezJoltMeshResourceHandle hResource((ezJoltMeshResource*)(e.m_pResource)); for (auto it = m_Components.GetIterator(); it.IsValid(); ++it) { const ezJoltVisColMeshComponent* pComponent = static_cast<ezJoltVisColMeshComponent*>(it.Value()); if (pComponent->GetMesh() == hResource) { m_RequireUpdate.PushBack(pComponent->GetHandle()); } } } } EZ_STATICLINK_FILE(JoltPlugin, JoltPlugin_Components_Implementation_JoltVisColMeshComponent);