diff --git a/samples/03_model_render/model_loader.cpp b/samples/03_model_render/model_loader.cpp index d42d010..fa1d6e4 100644 --- a/samples/03_model_render/model_loader.cpp +++ b/samples/03_model_render/model_loader.cpp @@ -542,14 +542,14 @@ ModelLoader::LoadModel(cstr path, cstr name, bool batched) const mat4 transform = translate(mat4(1.0f), nodeTranslation) * mat4_cast(nodeRotation) * scale(mat4(1.0f), nodeScale) * nodeMatrix; - const u32 nodeArrayIndex = nodes.Add(transform, parent); + const i32 nodeArrayIndex = Cast(nodes.Add(transform, parent)); if (node->mesh >= 0) { auto [start, count] = meshPrimRanges[node->mesh]; const auto end = start + count; for (usize i = start; i != end; ++i) { - meshPrimitives[i].m_TransformIdx = Cast(nodeArrayIndex); + meshPrimitives[i].m_TransformIdx = nodeArrayIndex; } } @@ -711,7 +711,7 @@ Model::operator=(Model &&other) noexcept m_NormalHandle = other.m_NormalHandle; m_TexCoord0Handle = other.m_TexCoord0Handle; m_VertexColorHandle = other.m_VertexColorHandle; - m_NodeHandle = std::move(other.m_NodeHandle); + m_NodeHandle = other.m_NodeHandle; m_IndexBuffer = other.m_IndexBuffer; m_MeshPrimitives = std::move(other.m_MeshPrimitives); return *this; diff --git a/samples/03_model_render/model_loader.h b/samples/03_model_render/model_loader.h index c43ba58..db78627 100644 --- a/samples/03_model_render/model_loader.h +++ b/samples/03_model_render/model_loader.h @@ -34,6 +34,7 @@ struct Nodes { eastl::vector m_Transforms; eastl::vector m_GlobalTransforms; + /// Parents are also used for bookkeeping eastl::vector m_Parents_; bool m_Dirty = true; @@ -42,10 +43,10 @@ struct Nodes constexpr static u32 PARENT_MASK = ~(ROOT_BIT | DIRTY_BIT); u32 - Add(const mat4& transform, i32 parent = -1) + Add(const mat4& transform, const i32 parent = -1) { m_Dirty = true; - u32 index = Count(); + const u32 index = Count(); m_Transforms.push_back(transform); m_GlobalTransforms.push_back(transform); const u32 parentVal = (parent < 0 ? ROOT_BIT : parent & PARENT_MASK) | DIRTY_BIT; @@ -113,22 +114,39 @@ struct Nodes while (parentIter != parentEnd) { - if (!(*parentIter & ROOT_BIT) && *parentIter & DIRTY_BIT) + const bool isRoot = *parentIter & ROOT_BIT; + const bool isDirty = *parentIter & DIRTY_BIT; + + if (isRoot) { - u32 parent = *parentIter & PARENT_MASK; - *globalTransformIter = m_GlobalTransforms[parent] * *transformIter; + if (isDirty) + { + // Copy-update if the root is dirty. + *globalTransformIter = *transformIter; + } } else { - *globalTransformIter = *transformIter; + const u32 parentIdx = *parentIter & PARENT_MASK; + const bool 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] * *transformIter; + m_Parents_[parentIdx] |= m_Dirty; // Set dirty to propagate the update. + } } - *parentIter &= ~DIRTY_BIT; ++parentIter; ++globalTransformIter; ++transformIter; } + for (u32 &parentValue : m_Parents_) + { + parentValue &= ~DIRTY_BIT; // Unset dirty. + } + m_Dirty = false; } };