diff --git a/engine/include/cubos/engine/transform/plugin.hpp b/engine/include/cubos/engine/transform/plugin.hpp index a3bee01b6b..a0b8f8c581 100644 --- a/engine/include/cubos/engine/transform/plugin.hpp +++ b/engine/include/cubos/engine/transform/plugin.hpp @@ -44,8 +44,10 @@ namespace cubos::engine /// Position, @ref Rotation or @ref Scale components. /// - `cubos.transform.missing` - the @ref Position, @ref Rotation, @ref Scale and possibly @ref LocalToParent /// components are added to entities with @ref LocalToWorld components. + /// - `cubos.transform.update.relative` - the @ref LocalToWorld or @ref LocalToParent components are updated with + /// the information from the @ref Position, @ref Rotation and @ref Scale components. /// - `cubos.transform.update` - the @ref LocalToWorld components are updated with the information from the @ref - /// Position, @ref Rotation and @ref Scale components. + /// LocalToParent component and the @ref LocalToWorld components of the parent. /// @brief Plugin entry function. /// @param cubos @b CUBOS. main class diff --git a/engine/src/cubos/engine/transform/plugin.cpp b/engine/src/cubos/engine/transform/plugin.cpp index 800d4b652e..66f3a12a15 100644 --- a/engine/src/cubos/engine/transform/plugin.cpp +++ b/engine/src/cubos/engine/transform/plugin.cpp @@ -1,5 +1,7 @@ #include +using cubos::core::ecs::Traversal; + void cubos::engine::transformPlugin(Cubos& cubos) { cubos.addComponent(); @@ -91,28 +93,39 @@ void cubos::engine::transformPlugin(Cubos& cubos) } }); - cubos.tag("cubos.transform.missing").before("cubos.transform.update"); + cubos.tag("cubos.transform.missing").before("cubos.transform.update.relative"); - cubos.system("update LocalToWorld") - .tagged("cubos.transform.update") - .call([](Query, Opt, Opt> query) { - for (auto [entity, localToWorld, position, rotation, scale] : query) + cubos.system("update relative transform matrix") + .tagged("cubos.transform.update.relative") + .before("cubos.transform.update") + .call([](Query, const Position&, const Rotation&, const Scale&> query) { + for (auto [localToWorld, localToParent, position, rotation, scale] : query) { - localToWorld.mat = glm::mat4(1.0F); - if (position) - { - localToWorld.mat = glm::translate(localToWorld.mat, position->vec); - } + auto mat = glm::scale(glm::translate(localToWorld.mat, position.vec) * glm::toMat4(rotation.quat), + glm::vec3(scale.factor)); - if (rotation) + if (localToParent) { - localToWorld.mat *= glm::toMat4(rotation->quat); + localToParent->mat = mat; } - - if (scale) + else { - localToWorld.mat = glm::scale(localToWorld.mat, glm::vec3(scale->factor)); + // No parent, so transform is relative to the world + localToWorld.mat = mat; } } }); + + cubos.system("update LocalToWorlds of children") + .tagged("cubos.transform.update") + .with() + .with() + .related(Traversal::Down) + .with() + .call([](Query query) { + for (auto [localToWorld, localToParent, parentLocalToWorld] : query) + { + localToWorld.mat = parentLocalToWorld.mat * localToParent.mat; + } + }); }