3333namespace Diligent
3434{
3535
36+ DEFINE_FLAG_ENUM_OPERATORS (RadientSceneState::DIRTY_FLAGS);
37+
3638namespace
3739{
3840
@@ -183,7 +185,6 @@ RADIENT_STATUS RadientSceneState::GetWorldMatrix(RadientEntityID Entity, Radient
183185 return RADIENT_STATUS_NOT_FOUND;
184186 }
185187
186- UpdateWorldMatrix (E);
187188 Matrix = m_Registry.get <WorldTransformComponent>(E).Matrix ;
188189 return RADIENT_STATUS_OK;
189190}
@@ -258,8 +259,10 @@ RADIENT_STATUS RadientSceneState::CreateEntity(const RadientEntityDesc& Desc, Ra
258259 m_Registry.emplace <HierarchyComponent>(E);
259260 m_Registry.emplace <LocalTransformComponent>(E, LocalTransformComponent{Desc.Transform });
260261 m_Registry.emplace <WorldTransformComponent>(E);
262+ m_Registry.emplace <DirtyStateComponent>(E);
261263
262264 m_EntityMap.emplace (Entity, E);
265+ MarkDirty (E, DIRTY_FLAGS_REQUIRING_PROPAGATION);
263266
264267 if (Parent != entt::null)
265268 {
@@ -294,6 +297,7 @@ RADIENT_STATUS RadientSceneState::SetEntityFlags(RadientEntityID Entity, RADIENT
294297 return RADIENT_STATUS_NO_CHANGE;
295298
296299 State.Flags = Flags;
300+ MarkDirty (E, DIRTY_FLAG_VISIBILITY);
297301 Touch ();
298302 return RADIENT_STATUS_OK;
299303}
@@ -312,6 +316,7 @@ RADIENT_STATUS RadientSceneState::SetEntityOwnVisibility(RadientEntityID Entity,
312316 return RADIENT_STATUS_NO_CHANGE;
313317
314318 State.Flags = Flags;
319+ MarkDirty (E, DIRTY_FLAG_VISIBILITY);
315320 Touch ();
316321 return RADIENT_STATUS_OK;
317322}
@@ -340,13 +345,10 @@ RADIENT_STATUS RadientSceneState::SetParent(RadientEntityID Entity, RadientEntit
340345 RadientTransform LocalTransform = m_Registry.get <LocalTransformComponent>(E).Transform ;
341346 if (KeepWorldTransform)
342347 {
343- UpdateWorldMatrix (E);
344348 RadientMatrix4x4 LocalMatrix = m_Registry.get <WorldTransformComponent>(E).Matrix ;
345349
346350 if (NewParent != entt::null)
347351 {
348- UpdateWorldMatrix (NewParent);
349-
350352 RadientMatrix4x4 ParentWorldInverse;
351353 if (!RadientMath::TryInverseMatrix (m_Registry.get <WorldTransformComponent>(NewParent).Matrix , ParentWorldInverse))
352354 return RADIENT_STATUS_INVALID_OPERATION;
@@ -368,7 +370,7 @@ RADIENT_STATUS RadientSceneState::SetParent(RadientEntityID Entity, RadientEntit
368370 }
369371
370372 m_Registry.get <LocalTransformComponent>(E).Transform = LocalTransform;
371- MarkWorldMatrixDirty (E );
373+ MarkDirty (E, DIRTY_FLAGS_REQUIRING_PROPAGATION );
372374 Touch ();
373375 return RADIENT_STATUS_OK;
374376}
@@ -380,7 +382,7 @@ RADIENT_STATUS RadientSceneState::SetLocalTransform(RadientEntityID Entity, cons
380382 return RADIENT_STATUS_NOT_FOUND;
381383
382384 m_Registry.get <LocalTransformComponent>(E).Transform = Transform;
383- MarkWorldMatrixDirty (E );
385+ MarkDirty (E, DIRTY_FLAG_TRANSFORM );
384386 Touch ();
385387 return RADIENT_STATUS_OK;
386388}
@@ -491,6 +493,9 @@ RADIENT_STATUS RadientSceneState::RemoveComponent(RadientEntityID Entity, Radien
491493
492494RADIENT_STATUS RadientSceneState::CommitChanges ()
493495{
496+ PropagateDirtyFlags ();
497+ UpdateDirtyEntities ();
498+ m_DirtyEntities.clear ();
494499 return RADIENT_STATUS_OK;
495500}
496501
@@ -549,7 +554,7 @@ void RadientSceneState::DetachFromParent(entt::entity Entity)
549554
550555void RadientSceneState::DestroyEntitySubtree (entt::entity Entity)
551556{
552- const std::vector<RadientEntityID>& Children = m_Registry.get <HierarchyComponent>(Entity).Children ;
557+ const std::vector<RadientEntityID> Children = m_Registry.get <HierarchyComponent>(Entity).Children ;
553558 for (const RadientEntityID Child : Children)
554559 {
555560 const entt::entity ChildEntity = FindEntity (Child);
@@ -561,48 +566,97 @@ void RadientSceneState::DestroyEntitySubtree(entt::entity Entity)
561566 m_Registry.destroy (Entity);
562567}
563568
564- void RadientSceneState::MarkWorldMatrixDirty (entt::entity Entity)
569+ RadientSceneState::DIRTY_FLAGS RadientSceneState::MarkDirty (entt::entity Entity, DIRTY_FLAGS Flags )
565570{
566- m_Registry.get <WorldTransformComponent>(Entity).Dirty = true ;
571+ if (Flags == DIRTY_FLAG_NONE)
572+ return DIRTY_FLAG_NONE;
573+
574+ DirtyStateComponent& DirtyState = m_Registry.get <DirtyStateComponent>(Entity);
575+ const DIRTY_FLAGS AddedFlags = Flags & ~DirtyState.Flags ;
576+ if (DirtyState.Flags == DIRTY_FLAG_NONE)
577+ m_DirtyEntities.push_back (m_Registry.get <EntityComponent>(Entity).ID );
578+
579+ DirtyState.Flags |= Flags;
580+ return AddedFlags;
581+ }
582+
583+ void RadientSceneState::PropagateDirtyFlags ()
584+ {
585+ const size_t DirtyEntityCount = m_DirtyEntities.size ();
586+ for (size_t Index = 0 ; Index < DirtyEntityCount; ++Index)
587+ {
588+ const entt::entity Entity = FindEntity (m_DirtyEntities[Index]);
589+ if (Entity == entt::null)
590+ continue ;
567591
592+ const DirtyStateComponent& DirtyState = m_Registry.get <DirtyStateComponent>(Entity);
593+ const DIRTY_FLAGS FlagsToPropagate = DirtyState.Flags & DIRTY_FLAGS_REQUIRING_PROPAGATION;
594+ if (FlagsToPropagate == DIRTY_FLAG_NONE)
595+ continue ;
596+
597+ PropagateDirtyFlags (Entity, FlagsToPropagate);
598+ }
599+ }
600+
601+ void RadientSceneState::PropagateDirtyFlags (entt::entity Entity, DIRTY_FLAGS Flags)
602+ {
568603 const std::vector<RadientEntityID>& Children = m_Registry.get <HierarchyComponent>(Entity).Children ;
569604 for (const RadientEntityID Child : Children)
570605 {
571606 const entt::entity ChildEntity = FindEntity (Child);
572- if (ChildEntity != entt::null)
573- MarkWorldMatrixDirty (ChildEntity);
607+ if (ChildEntity == entt::null)
608+ continue ;
609+
610+ const DIRTY_FLAGS AddedFlags = MarkDirty (ChildEntity, Flags);
611+ if (AddedFlags != DIRTY_FLAG_NONE)
612+ PropagateDirtyFlags (ChildEntity, AddedFlags);
574613 }
575614}
576615
577- void RadientSceneState::UpdateWorldMatrix (entt::entity Entity) const
616+ void RadientSceneState::UpdateDirtyEntities ()
578617{
579- WorldTransformComponent& WorldTransform = m_Registry.get <WorldTransformComponent>(Entity);
580- if (!WorldTransform.Dirty )
581- return ;
618+ for (const RadientEntityID EntityID : m_DirtyEntities)
619+ {
620+ const entt::entity Entity = FindEntity (EntityID);
621+ if (Entity == entt::null)
622+ continue ;
582623
583- const LocalTransformComponent& LocalTransform = m_Registry.get <LocalTransformComponent>(Entity);
584- const HierarchyComponent& Hierarchy = m_Registry.get <HierarchyComponent>(Entity);
624+ DirtyStateComponent& DirtyState = m_Registry.get <DirtyStateComponent>(Entity);
625+ if ((DirtyState.Flags & DIRTY_FLAG_TRANSFORM) != DIRTY_FLAG_NONE)
626+ UpdateTransform (Entity);
585627
586- const RadientMatrix4x4 LocalMatrix = RadientMath::TransformToMatrix (LocalTransform.Transform );
587- if (Hierarchy.Parent == InvalidRadientEntityID)
588- {
589- WorldTransform.Matrix = LocalMatrix;
628+ DirtyState.Flags = DIRTY_FLAG_NONE;
590629 }
591- else
630+ }
631+
632+ void RadientSceneState::UpdateTransform (entt::entity Entity)
633+ {
634+ DirtyStateComponent& DirtyState = m_Registry.get <DirtyStateComponent>(Entity);
635+ if ((DirtyState.Flags & DIRTY_FLAG_TRANSFORM) == DIRTY_FLAG_NONE)
636+ return ;
637+
638+ const HierarchyComponent& Hierarchy = m_Registry.get <HierarchyComponent>(Entity);
639+
640+ const RadientMatrix4x4* pParentWorldMatrix = nullptr ;
641+ if (Hierarchy.Parent != InvalidRadientEntityID)
592642 {
593643 const entt::entity Parent = FindEntity (Hierarchy.Parent );
594644 if (Parent != entt::null)
595645 {
596- UpdateWorldMatrix (Parent);
597- WorldTransform.Matrix = RadientMath::MultiplyMatrices (LocalMatrix, m_Registry.get <WorldTransformComponent>(Parent).Matrix );
598- }
599- else
600- {
601- WorldTransform.Matrix = LocalMatrix;
646+ UpdateTransform (Parent);
647+ pParentWorldMatrix = &m_Registry.get <WorldTransformComponent>(Parent).Matrix ;
602648 }
603649 }
604650
605- WorldTransform.Dirty = false ;
651+ const LocalTransformComponent& LocalTransform = m_Registry.get <LocalTransformComponent>(Entity);
652+ const RadientMatrix4x4 LocalMatrix = RadientMath::TransformToMatrix (LocalTransform.Transform );
653+
654+ WorldTransformComponent& WorldTransform = m_Registry.get <WorldTransformComponent>(Entity);
655+ WorldTransform.Matrix = pParentWorldMatrix != nullptr ?
656+ RadientMath::MultiplyMatrices (LocalMatrix, *pParentWorldMatrix) :
657+ LocalMatrix;
658+
659+ DirtyState.Flags &= ~DIRTY_FLAG_TRANSFORM;
606660}
607661
608662void RadientSceneState::Touch ()
0 commit comments