Add a class to unify loading coordinate transforms
authorMikko Rasa <tdb@tdb.fi>
Tue, 4 Jun 2019 07:39:17 +0000 (10:39 +0300)
committerMikko Rasa <tdb@tdb.fi>
Tue, 4 Jun 2019 07:53:55 +0000 (10:53 +0300)
It will also be useful for animations.  Euler angles are not the ideal
way of storing rotations but they are relatively easy to understand and
work with.  Other rotation types will be added in the future.

source/animatedobject.cpp
source/animatedobject.h
source/keyframe.cpp
source/keyframe.h
source/transform.cpp [new file with mode: 0644]
source/transform.h [new file with mode: 0644]

index 257e1368def51c6c3a40fef4ebd5f04473320ff9..3a78110009bc2c47b8cf26e9ab7ee59013444b40 100644 (file)
@@ -6,6 +6,7 @@
 #include "programdata.h"
 #include "renderer.h"
 #include "technique.h"
+#include "transform.h"
 
 using namespace std;
 
@@ -79,6 +80,9 @@ void AnimatedObject::setup_render(Renderer &renderer, const Tag &) const
 AnimatedObject::Loader::Loader(AnimatedObject &o):
        DataFile::ObjectLoader<AnimatedObject>(o)
 {
+       add("transform", &Loader::transform);
+
+       // Deprecated; Use the transform statement instead
        add("position", &Loader::position);
        add("rotation", &Loader::rotation);
        add("scale", &Loader::scale);
@@ -105,5 +109,12 @@ void AnimatedObject::Loader::scale_uniform(float s)
        obj.matrix.scale(s);
 }
 
+void AnimatedObject::Loader::transform()
+{
+       Transform trn;
+       load_sub(trn);
+       obj.matrix = trn.to_matrix();
+}
+
 } // namespace GL
 } // namespace Msp
index 74e59fc8a76071196baf10da16a3ab7598ab14bf..73c39e2ca8b2a240e5647ef6d8b6ae02914a0609 100644 (file)
@@ -26,6 +26,7 @@ public:
                void rotation(float, float, float, float);
                void scale(float, float, float);
                void scale_uniform(float);
+               void transform();
        };
 
 private:
index dd4adf16611efb7c2c05312d0428d949de7c6df5..708fa22bc338e25a478ec11ccc969eccccf37589 100644 (file)
@@ -1,6 +1,7 @@
 #include <msp/datafile/collection.h>
 #include "keyframe.h"
 #include "pose.h"
+#include "transform.h"
 
 using namespace std;
 
@@ -52,11 +53,14 @@ void KeyFrame::Loader::init()
 {
        add("pose", &Loader::pose);
        add("pose", &Loader::pose_inline);
+       add("transform", &Loader::transform);
+       add("uniforms", &Loader::uniforms);
+
+       // Deprecated; use the transform statement instead
        add("position", &Loader::position);
        add("rotation", &Loader::rotation);
        add("scaling", &Loader::scaling_uniform);
        add("scaling", &Loader::scaling);
-       add("uniforms", &Loader::uniforms);
 }
 
 void KeyFrame::Loader::pose(const string &n)
@@ -92,6 +96,13 @@ void KeyFrame::Loader::scaling(float x, float y, float z)
        obj.matrix.scale(x, y, z);
 }
 
+void KeyFrame::Loader::transform()
+{
+       Transform trn;
+       load_sub(trn);
+       obj.matrix = trn.to_matrix();
+}
+
 void KeyFrame::Loader::uniforms()
 {
        UniformsLoader ldr(obj);
index 7854a928863c86ea7d2a30891d97a3687ac44b22..88e852149570cae1d6e32968a60d73ed9cd6a5b5 100644 (file)
@@ -30,6 +30,7 @@ public:
                void rotation(float, float, float, float);
                void scaling_uniform(float);
                void scaling(float, float, float);
+               void transform();
                void uniforms();
        };
 
diff --git a/source/transform.cpp b/source/transform.cpp
new file mode 100644 (file)
index 0000000..9660c2c
--- /dev/null
@@ -0,0 +1,80 @@
+#include "transform.h"
+
+namespace Msp {
+namespace GL {
+
+Transform::Transform():
+       position(0.0f, 0.0f, 0.0f),
+       euler(Angle::zero(), Angle::zero(), Angle::zero()),
+       scale(1.0f, 1.0f, 1.0f)
+{ }
+
+void Transform::set_position(const Vector3 &p)
+{
+       position = p;
+}
+
+void Transform::set_euler(const AngleVector3 &e)
+{
+       euler = e;
+}
+
+void Transform::set_scale(const Vector3 &s)
+{
+       scale = s;
+}
+
+Matrix Transform::to_matrix() const
+{
+       Matrix result;
+       result.translate(position);
+       result.rotate(euler.z, Vector3(0.0f, 0.0f, 1.0f));
+       result.rotate(euler.y, Vector3(0.0f, 1.0f, 0.0f));
+       result.rotate(euler.x, Vector3(1.0f, 0.0f, 0.0f));
+       result.scale(scale);
+       return result;
+}
+
+
+Transform::Loader::Loader(Transform &t):
+       DataFile::ObjectLoader<Transform>(t)
+{
+       add("position", &Loader::position);
+       add("euler", &Loader::euler);
+       add("rotation", &Loader::rotation);
+       add("scale_uniform", &Loader::scale_uniform);
+       add("scale", &Loader::scale);
+}
+
+void Transform::Loader::position(float x, float y, float z)
+{
+       obj.position = Vector3(x, y, z);
+}
+
+void Transform::Loader::euler(float x, float y, float z)
+{
+       obj.euler = AngleVector3(Angle::from_degrees(x), Angle::from_degrees(y), Angle::from_degrees(z));
+}
+
+void Transform::Loader::rotation(float a, float x, float y, float z)
+{
+       Matrix matrix = Matrix::rotation(Angle::from_degrees(a), Vector3(x, y, z));
+       obj.euler.z = Geometry::atan2<float>(matrix(1, 0), matrix(0, 0));
+       matrix = Matrix::rotation(-obj.euler.z, Vector3(0.0f, 0.0f, 1.0f))*matrix;
+       obj.euler.y = Geometry::atan2<float>(matrix(2, 0), matrix(0, 0));
+       matrix = Matrix::rotation(-obj.euler.y, Vector3(0.0f, 1.0f, 0.0f))*matrix;
+       obj.euler.x = Geometry::atan2<float>(matrix(2, 1), matrix(1, 1));
+}
+
+void Transform::Loader::scale_uniform(float s)
+{
+       obj.scale = Vector3(s, s, s);
+}
+
+void Transform::Loader::scale(float x, float y, float z)
+{
+       obj.scale = Vector3(x, y, z);
+}
+
+} // namespace GL
+} // namespace Msp
diff --git a/source/transform.h b/source/transform.h
new file mode 100644 (file)
index 0000000..ee821ce
--- /dev/null
@@ -0,0 +1,55 @@
+#ifndef MSP_GL_TRANSFORM_H_
+#define MSP_GL_TRANSFORM_H_
+
+#include <msp/datafile/objectloader.h>
+#include "matrix.h"
+
+namespace Msp {
+namespace GL {
+
+/**
+Stores a coordinate space transform as individual components.  Primarily
+intended for loading data from external sources.  At runtime transforms
+should generally be stored as matrices.
+*/
+class Transform
+{
+public:
+       class Loader: public DataFile::ObjectLoader<Transform>
+       {
+       public:
+               Loader(Transform &);
+
+       private:
+               void position(float, float, float);
+               void euler(float, float, float);
+               void rotation(float, float, float, float);
+               void scale_uniform(float);
+               void scale(float, float, float);
+       };
+
+       typedef Geometry::Angle<float> Angle;
+       typedef LinAl::Vector<Angle, 3> AngleVector3;
+
+private:
+       Vector3 position;
+       AngleVector3 euler;
+       Vector3 scale;
+
+public:
+       Transform();
+
+       void set_position(const Vector3 &);
+       void set_euler(const AngleVector3 &);
+       void set_scale(const Vector3 &);
+       const Vector3 &get_position() const { return position; }
+       const AngleVector3 &get_euler() const { return euler; }
+       const Vector3 &get_scale() const { return scale; }
+
+       Matrix to_matrix() const;
+};
+
+} // namespace GL
+} // namespace Msp
+
+#endif