]> git.tdb.fi Git - libs/game.git/commitdiff
Use fresh parent state when propagating transforms
authorMikko Rasa <tdb@tdb.fi>
Thu, 17 Apr 2025 20:35:57 +0000 (23:35 +0300)
committerMikko Rasa <tdb@tdb.fi>
Thu, 17 Apr 2025 20:36:44 +0000 (23:36 +0300)
source/game/transform.cpp
source/game/transform.h
source/game/transformpropagator.cpp
source/game/transformpropagator.h

index a71479baf0b1fcf1cffe72d2c0ed31b4d33800c4..cb15c42311b61b05783335ff6c8a29dadc7af7ea 100644 (file)
@@ -55,7 +55,7 @@ void Transform::set_scale(const LinAl::Vector<float, 3> &s)
        d.values.scale = s;
 }
 
-void Transform::update_world_transform(const Transform *parent)
+const Geometry::AffineTransform<float, 3> &Transform::update_world_transform(const Geometry::AffineTransform<float, 3> *parent)
 {
        using Affine = Geometry::AffineTransform<float, 3>;
 
@@ -67,15 +67,17 @@ void Transform::update_world_transform(const Transform *parent)
                if(d.world_values)
                {
                        d.world_transform = d.local_transform;
-                       d.local_transform = invert(parent->get_world_transform())*d.world_transform;
+                       d.local_transform = invert(*parent)*d.world_transform;
                        d.values = TransformValues::from_matrix(d.local_transform);
                }
                else
-                       d.world_transform = parent->get_world_transform()*d.local_transform;
+                       d.world_transform = (*parent)*d.local_transform;
        }
        else
                d.world_transform = d.local_transform;
        d.world_values = false;
+
+       return d.world_transform;
 }
 
 } // namespace Msp::Game
index f44b55e27558dce58d6a77bd598895c16f6fc025..12bd8ab5f079986f055bead3c872e77ebf41872d 100644 (file)
@@ -53,7 +53,7 @@ public:
        const LinAl::Vector<float, 3> &get_scale() const { return read().values.scale; }
        const Geometry::AffineTransform<float, 3> &get_world_transform() const { return read().world_transform; }
 
-       void update_world_transform(const Transform *);
+       const Geometry::AffineTransform<float, 3> &update_world_transform(const Geometry::AffineTransform<float, 3> *);
 };
 
 } // namespace Msp::Game
index bb960f0f737dce6abef4f1a96ff560ed9319f982..8b2e1c751f5747807ac02bea180fc3afd72c3b70 100644 (file)
@@ -28,10 +28,16 @@ void TransformPropagator::commit(Mode mode)
                        update_children = transforms.size();
                }
 
+               vector<const Geometry::AffineTransform<float, 3> *> world_transforms(max_level);
+
                for(ParentedTransform &t: transforms)
                        if(t.transform->was_written() || update_children>0)
                        {
-                               t.transform->update_world_transform(t.parent.get());
+                               const Geometry::AffineTransform<float, 3> *parent_wt = (t.level>0 ? world_transforms[t.level-1] : nullptr);
+                               const Geometry::AffineTransform<float, 3> &wt = t.transform->update_world_transform(parent_wt);
+                               if(t.child_count>0)
+                                       world_transforms[t.level] = &wt;
+
                                if(t.child_count>update_children)
                                        update_children = t.child_count;
                                else if(update_children>0)
@@ -47,22 +53,25 @@ void TransformPropagator::rebuild_transform_order()
 {
        transforms_dirty = false;
        transforms.clear();
+       max_level = 0;
        for(Handle<Entity> c: stage.get_root()->get_children())
-               rebuild_transform_order(c, nullptr);
+               rebuild_transform_order(c, nullptr, 0);
 }
 
-void TransformPropagator::rebuild_transform_order(Handle<Entity> entity, Handle<Transform> parent_trans)
+void TransformPropagator::rebuild_transform_order(Handle<Entity> entity, Handle<Transform> parent_trans, unsigned level)
 {
        size_t index = static_cast<size_t>(-1);
        if(Handle<Transform> trans = entity->get_transform())
        {
+               max_level = max(level, max_level);
                index = transforms.size();
-               transforms.emplace_back(trans, parent_trans);
+               transforms.emplace_back(trans, parent_trans, level);
                parent_trans = trans;
+               ++level;
        }
 
        for(Handle<Entity> c: entity->get_children())
-               rebuild_transform_order(c, parent_trans);
+               rebuild_transform_order(c, parent_trans, level);
 
        if(index<transforms.size())
                transforms[index].child_count = transforms.size()-1-index;
index 1edb5c42b0b014e28495b79fc858b86c7ea6bdaf..dd17ce9a83ea9ca5351dcb84f346b0a3cfb03cc0 100644 (file)
@@ -18,11 +18,13 @@ private:
        {
                Handle<Transform> transform;
                Handle<Transform> parent;
+               unsigned level = 0;
                unsigned child_count = 0;
        };
 
        EventObserver observer;
        std::vector<ParentedTransform> transforms;
+       unsigned max_level = 0;
        bool transforms_dirty = true;
 
 public:
@@ -32,7 +34,7 @@ public:
 
 private:
        void rebuild_transform_order();
-       void rebuild_transform_order(Handle<Entity>, Handle<Transform>);
+       void rebuild_transform_order(Handle<Entity>, Handle<Transform>, unsigned);
 };
 
 } // namespace Msp::Game