// ============================================= // Aster: nodes.cpp // Copyright (c) 2020-2025 Anish Bhobe // ============================================= #include "nodes.h" u32 Nodes::Add(mat4 const &transform, i32 const parent) { m_Dirty = true; u32 const index = Count(); m_Transforms.push_back(transform); m_GlobalTransforms.emplace_back(transform); u32 const parentVal = (parent < 0 ? ROOT_BIT : parent & PARENT_MASK) | DIRTY_BIT; m_Parents_.push_back(parentVal); return index; } mat4 const & Nodes::Get(u32 const index) const { return m_Transforms[index]; } void Nodes::Set(u32 const index, mat4 const &transform) { m_Dirty = true; m_Transforms[index] = transform; m_Parents_[index] |= DIRTY_BIT; } mat4 const & Nodes::operator[](u32 const index) const { return m_Transforms[index]; } mat4 & Nodes::operator[](u32 const index) { m_Dirty = true; m_Parents_[index] |= DIRTY_BIT; return m_Transforms[index]; } u32 Nodes::Count() const { return static_cast(m_Transforms.size()); } usize Nodes::GetGlobalTransformByteSize() const { return m_GlobalTransforms.size() * sizeof m_GlobalTransforms[0]; } Nodes::Transform const * Nodes::GetGlobalTransformPtr() const { return m_GlobalTransforms.data(); } bool Nodes::Update() { if (!m_Dirty) return false; auto transformIter = m_Transforms.begin(); auto globalTransformIter = m_GlobalTransforms.begin(); auto parentIter = m_Parents_.begin(); auto const parentEnd = m_Parents_.end(); while (parentIter != parentEnd) { bool const isRoot = *parentIter & ROOT_BIT; bool const isDirty = *parentIter & DIRTY_BIT; if (isRoot) { if (isDirty) { // Copy-update if the root is dirty. *globalTransformIter = *transformIter; } } else { u32 const parentIdx = *parentIter & PARENT_MASK; bool const isParentDirty = m_Parents_[parentIdx] & DIRTY_BIT; if (isDirty || isParentDirty) { // Update w.r.t parent if either local or parent transforms updated. *globalTransformIter = m_GlobalTransforms[parentIdx].m_GlobalTransforms * *transformIter; m_Parents_[parentIdx] |= DIRTY_BIT; // Set dirty to propagate the update. } } ++parentIter; ++globalTransformIter; ++transformIter; } for (u32 &parentValue : m_Parents_) { parentValue &= ~DIRTY_BIT; // Unset dirty. } m_Dirty = false; return true; }