]> git.tdb.fi Git - libs/game.git/commitdiff
Support setting transform values in world space
authorMikko Rasa <tdb@tdb.fi>
Mon, 14 Apr 2025 10:11:19 +0000 (13:11 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 14 Apr 2025 10:17:49 +0000 (13:17 +0300)
source/game/transform.cpp
source/game/transform.h

index b201a01bc3cc2410b9d8ab7d01a8ceb7caf0e33a..a71479baf0b1fcf1cffe72d2c0ed31b4d33800c4 100644 (file)
@@ -19,22 +19,40 @@ TransformValues TransformValues::from_matrix(const LinAl::Matrix<float, 4, 4> &m
 
 void Transform::set_values(const TransformValues &v)
 {
-       write().values = v;
+       Data &d = write();
+       d.values = v;
+       d.world_values = false;
+}
+
+void Transform::set_world_values(const TransformValues &v)
+{
+       Data &d = write();
+       d.values = v;
+       d.world_values = true;
 }
 
 void Transform::set_position(const LinAl::Vector<float, 3> &p)
 {
-       write().values.position = p;
+       Data &d = write();
+       if(d.world_values)
+               throw invalid_state("Transform::set_position");
+       d.values.position = p;
 }
 
 void Transform::set_rotation(const Geometry::Quaternion<float> &r)
 {
-       write().values.rotation = normalize(r);
+       Data &d = write();
+       if(d.world_values)
+               throw invalid_state("Transform::set_position");
+       d.values.rotation = normalize(r);
 }
 
 void Transform::set_scale(const LinAl::Vector<float, 3> &s)
 {
-       write().values.scale = s;
+       Data &d = write();
+       if(d.world_values)
+               throw invalid_state("Transform::set_position");
+       d.values.scale = s;
 }
 
 void Transform::update_world_transform(const Transform *parent)
@@ -45,9 +63,19 @@ void Transform::update_world_transform(const Transform *parent)
        d.local_transform = Affine::translation(d.values.position)*
                Affine::rotation(d.values.rotation)*Affine::scaling(d.values.scale);
        if(parent)
-               d.world_transform = parent->get_world_transform()*d.local_transform;
+       {
+               if(d.world_values)
+               {
+                       d.world_transform = d.local_transform;
+                       d.local_transform = invert(parent->get_world_transform())*d.world_transform;
+                       d.values = TransformValues::from_matrix(d.local_transform);
+               }
+               else
+                       d.world_transform = parent->get_world_transform()*d.local_transform;
+       }
        else
                d.world_transform = d.local_transform;
+       d.world_values = false;
 }
 
 } // namespace Msp::Game
index c8c93bde8ec4f0cc44963285c183b660eb3a07d2..f44b55e27558dce58d6a77bd598895c16f6fc025 100644 (file)
@@ -30,6 +30,7 @@ struct MSPGAME_API TransformValues
 struct TransformData
 {
        TransformValues values;
+       bool world_values = false;
        Geometry::AffineTransform<float, 3> local_transform;
        Geometry::AffineTransform<float, 3> world_transform;
 };
@@ -42,6 +43,7 @@ public:
        Transform(Handle<Entity> e): BufferedComponent(e) { }
 
        void set_values(const TransformValues &);
+       void set_world_values(const TransformValues &);
        void set_position(const LinAl::Vector<float, 3> &);
        void set_rotation(const Geometry::Quaternion<float> &);
        void set_scale(const LinAl::Vector<float, 3> &);