Skip to content

fix(flame_3d): Invalidate the AABBs of nested components when an ancestor moves - #4167

Open
ufrshubham wants to merge 2 commits into
mainfrom
devkage/fix-3d-aabb-on-ancestor-move
Open

ufrshubham wants to merge 2 commits into
mainfrom
devkage/fix-3d-aabb-on-ancestor-move

Conversation

@ufrshubham

Copy link
Copy Markdown
Member

Description

When the transform of a Component3D changed, only the world transform dirty flag was propagated down to its descendants, while the AABB dirty flag was only propagated up. The descendants kept the AABB cached for their old world position, so they were frustum culled based on where they used to be. This affected regular MeshComponents and ModelComponents inside any group that moves.

This PR marks the AABB dirty together with the world transform when propagating down the subtree in _markWorldTransformDirty, and marks the parent's AABB dirty from _onTransformChanged (calling markAabbDirty() on the component itself would now return early, since the downward propagation already marked it).

The early return in _markWorldTransformDirty now only happens when both flags are already dirty, since the world transform and the AABB are recomputed independently and one can be dirty while the other is not. This relies on a recomputed AABB also refreshing the world transforms of its ancestors, which holds for every component with geometry. A component without geometry or children still uses its local position for its AABB (#4165), so it doesn't depend on its ancestors yet, and it will once that is fixed.

The tests cover a nested child, a deeply nested child and repeated moves where only the leaf is read in between, which exercises that early return. All of them fail without the fix. I also verified the fix with the repro from #4163 on Windows.

Checklist

  • I have followed the Contributor Guide when preparing my PR.
  • I have updated/added tests for ALL new/updated/fixed functionality.
  • I have updated/added relevant documentation in docs and added dartdoc comments with ///.
  • [-] I have updated/added relevant examples in examples or docs.

Breaking Change?

  • Yes, this PR is a breaking change.
  • No, this PR is not a breaking change.

Related Issues

Closes #4163

…stor moves

When a Component3D's transform changed, only the world transform dirty flag
was propagated down to its descendants, while the AABB dirty flag was only
propagated up. Descendants kept the AABB cached for their old world position
and were frustum culled based on it.

The AABB is now marked dirty together with the world transform when
propagating down the subtree, and the parent's AABB is marked dirty from the
component whose transform changed.
@ufrshubham ufrshubham self-assigned this Oct 29, 2026

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[flame_3d] Nested components are culled at their old position after an ancestor moves

1 participant