From b703669d1adc5ba2b421c82e650c0a0582e1ec7e Mon Sep 17 00:00:00 2001 From: assiduous Date: Sun, 19 Jan 2025 20:34:25 -0800 Subject: [PATCH] HnMesh: clear dirty flags during progressive geometry upload --- Hydrogent/interface/HnMesh.hpp | 3 ++ Hydrogent/src/HnMesh.cpp | 59 +++++++++++++++++++++++----------- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/Hydrogent/interface/HnMesh.hpp b/Hydrogent/interface/HnMesh.hpp index c5e14167..f9fc563d 100644 --- a/Hydrogent/interface/HnMesh.hpp +++ b/Hydrogent/interface/HnMesh.hpp @@ -249,6 +249,9 @@ class HnMesh final : public pxr::HdMesh void ProcessDrawItems(HandleDrawItemFuncType&& HandleDrawItem, HandleGeomSubsetDrawItemFuncType&& HandleGeomSubsetDrawItem); + void UpdateCullMode(const float4x4& Transform, + pxr::HdRenderParam* RenderParam); + void Invalidate(); private: diff --git a/Hydrogent/src/HnMesh.cpp b/Hydrogent/src/HnMesh.cpp index 725aa678..0a476ec4 100644 --- a/Hydrogent/src/HnMesh.cpp +++ b/Hydrogent/src/HnMesh.cpp @@ -168,6 +168,28 @@ void HnMesh::UpdateReprMaterials(pxr::HdSceneDelegate* SceneDelegate, }); } +void HnMesh::UpdateCullMode(const float4x4& Transform, + pxr::HdRenderParam* RenderParam) +{ + CULL_MODE CullMode = CULL_MODE_UNDEFINED; + if (m_IsDoubleSided) + { + CullMode = CULL_MODE_NONE; + } + else + { + const float Det = Transform.Determinant(); + // Do NOT use Delegate->GetTransform() as it is very expensive and we have the matrix already + //CullMode = Delegate->GetTransform(Id).IsRightHanded() ? CULL_MODE_BACK : CULL_MODE_FRONT; + CullMode = Det > 0 ? CULL_MODE_BACK : CULL_MODE_FRONT; + } + + if (m_CullMode != CullMode) + { + m_CullMode = CullMode; + static_cast(RenderParam)->MakeAttribDirty(HnRenderParam::GlobalAttrib::MeshCulling); + } +} void HnMesh::Sync(pxr::HdSceneDelegate* Delegate, pxr::HdRenderParam* RenderParam, @@ -188,14 +210,21 @@ void HnMesh::Sync(pxr::HdSceneDelegate* Delegate, SetMaterialId(MaterialId); } UpdateMaterials = true; + *DirtyBits &= ~pxr::HdChangeTracker::DirtyMaterialId; } - if (*DirtyBits & (pxr::HdChangeTracker::DirtyDisplayStyle | pxr::HdChangeTracker::NewRepr)) + if ((*DirtyBits & pxr::HdChangeTracker::DirtyDisplayStyle) != 0) { UpdateMaterials = true; + *DirtyBits &= ~pxr::HdChangeTracker::DirtyDisplayStyle; } - bool UpdateCullMode = pxr::HdChangeTracker::IsTransformDirty(*DirtyBits, Id) || m_CullMode == CULL_MODE_UNDEFINED; + const bool IsNewRepr = (*DirtyBits & pxr::HdChangeTracker::NewRepr) != 0; + // UpdateRepr() clears the NewRepr bit const bool ReprUpdated = UpdateRepr(*Delegate, RenderParam, *DirtyBits, ReprToken); + if (IsNewRepr && ReprUpdated) + { + UpdateMaterials = true; + } if (UpdateMaterials) { @@ -206,26 +235,15 @@ void HnMesh::Sync(pxr::HdSceneDelegate* Delegate, if (DirtyDoubleSided) { m_IsDoubleSided = Delegate->GetDoubleSided(Id); - UpdateCullMode = true; + *DirtyBits &= ~pxr::HdChangeTracker::DirtyDoubleSided; } - if (UpdateCullMode) + if (DirtyDoubleSided || m_CullMode == CULL_MODE_UNDEFINED) { - CULL_MODE CullMode = CULL_MODE_UNDEFINED; - if (m_IsDoubleSided) - { - CullMode = CULL_MODE_NONE; - } - else - { - CullMode = Delegate->GetTransform(Id).IsRightHanded() ? CULL_MODE_BACK : CULL_MODE_FRONT; - } - - if (m_CullMode != CullMode) - { - m_CullMode = CullMode; - static_cast(RenderParam)->MakeAttribDirty(HnRenderParam::GlobalAttrib::MeshCulling); - } + HnRenderDelegate* RenderDelegate = static_cast(Delegate->GetRenderIndex().GetRenderDelegate()); + entt::registry& Registry = RenderDelegate->GetEcsRegistry(); + const float4x4& Transform = Registry.get(m_Entity).Matrix; + UpdateCullMode(Transform, RenderParam); } if ((DirtyDoubleSided || UpdateMaterials) && RenderParam != nullptr) @@ -557,6 +575,8 @@ bool HnMesh::UpdateRepr(pxr::HdSceneDelegate& SceneDelegate, ++m_GeometryVersion; } + // Note that m_SkelLocalToPrimLocal is set by UpdateSkinningPrimvars, so transform + // should be updated after the primvars are synced. if (pxr::HdChangeTracker::IsTransformDirty(DirtyBits, Id)) { entt::registry& Registry = RenderDelegate->GetEcsRegistry(); @@ -570,6 +590,7 @@ bool HnMesh::UpdateRepr(pxr::HdSceneDelegate& SceneDelegate, { static_cast(RenderParam)->MakeAttribDirty(HnRenderParam::GlobalAttrib::MeshTransform); } + UpdateCullMode(Transform, RenderParam); } DirtyBits &= ~pxr::HdChangeTracker::DirtyTransform;