Skip to content

Proposal: Lazy mtxWorld Recalculation #71

Description

@plojo

Current State

  • Each Node has a mtxWorld matrix, and its ComponentTransform contains the mtxLocal matrix.
  • mtxWorld is updated once per frame during the render prepare loop, with a rudimentery dirty check on the involved matrices.
  • This makes it hard for creators/developers to access a fresh mtxWorld (after modifying mtxLocal or before the first render prepare cycle)

Proposed Idea

Introduce a lazy recomputation system for mtxWorld, inspired by Godot:

  1. Dirty flag per node

    • Each Node has a mtxWorldDirty flag.
  2. Selective invalidation

    • Changing ComponentTransform.mtxLocal marks the node dirty..
    • Recursively marks descendants dirty only if they are not already dirty, avoiding redundant work.
  3. Explicit update notification

    • Modifications to mtxLocal must be explicitly communicated (via setter or markDirty()), notifying the node and triggering invalidation.
  4. On-demand computation

    • Accessing a node’s mtxWorld checks the mtxWorldDirty flag.
    • If dirty, recompute using the parent’s mtxWorld; otherwise, return cached value.

Proposed Invalidation Workflow

  1. Assignment triggers invalidation

    • ComponentTransform.mtxLocal = matrix → calls ComponentTransform.markDirty().
  2. Component propagates to node

    • ComponentTransform.markDirty() → calls ComponentTransform.node.markDirty().
  3. Node invalidates subtree

    • Node.markDirty() → sets mtxWorldDirty and recursively marks descendants only if not already dirty.

Effects

  • Efficient lazy updates: Only recompute mtxWorld when needed.
  • First change → expensive (walk branch and mark descendants not already dirty).
  • Subsequent changes → cheap (skip already-invalid descendants).
  • Reads of mtxWorld → cheap (check dirty flag, recompute if needed).
  • Transparent for creators: simple assignment triggers updates automatically.
  • Predictable: explicit markDirty() ensures correctness for procedural or bulk updates.
  • Supports dynamic scenes: nodes added mid-frame compute transforms correctly on demand.

Considerations

  • Child traversal cost: Marking a node dirty requires subtree traversal, which can be expensive for large hierarchies.
  • Explicit dirty marking required: Developers must explicitly use the setter or markDirty(); otherwise, mtxWorld may become stale.
  • Potential developer mistakes: Forgetting to mark dirty can lead to subtle bugs.
  • Lazy recomputation trade-off: First read after a change may be expensive due to recomputation.
  • Integration with other systems: This mechanism would also have to be integrated with the mutation and animation sytem.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions