]> git.tdb.fi Git - libs/gl.git/blobdiff - source/animation/pose.cpp
Rearrange soucre files into subdirectories
[libs/gl.git] / source / animation / pose.cpp
diff --git a/source/animation/pose.cpp b/source/animation/pose.cpp
new file mode 100644 (file)
index 0000000..99fa6bb
--- /dev/null
@@ -0,0 +1,90 @@
+#include <msp/datafile/collection.h>
+#include "armature.h"
+#include "error.h"
+#include "pose.h"
+
+using namespace std;
+
+namespace Msp {
+namespace GL {
+
+Pose::Pose():
+       armature(0)
+{ }
+
+Pose::Pose(const Armature &a):
+       armature(0)
+{
+       set_armature(a);
+}
+
+void Pose::set_armature(const Armature &a)
+{
+       if(armature)
+               throw invalid_operation("Pose::set_armature");
+       armature = &a;
+       links.resize(armature->get_max_link_index()+1);
+}
+
+void Pose::rotate_link(unsigned i, float angle, const Vector3 &axis)
+{
+       if(i>=links.size())
+               throw out_of_range("Pose::rotate_link");
+
+       const Armature::Link &arm_link = armature->get_link(i);
+       links[i].local_matrix.rotate(angle, axis);
+
+       // Keep the base point stationary
+       Vector3 base = arm_link.get_base();
+       Vector3 new_base = links[i].local_matrix*base;
+       links[i].local_matrix = Matrix::translation(base-new_base)*links[i].local_matrix;
+
+       if(const Armature::Link *parent = arm_link.get_parent())
+               links[i].matrix = links[parent->get_index()].matrix*links[i].local_matrix;
+
+       // XXX apply matrix to descendants of the link
+}
+
+const Matrix &Pose::get_link_matrix(unsigned i) const
+{
+       if(i>=links.size())
+               throw out_of_range("Pose::get_link_matrix");
+       return links[i].matrix;
+}
+
+
+Pose::Loader::Loader(Pose &p, Collection &c):
+       DataFile::CollectionObjectLoader<Pose>(p, &c)
+{
+       add("armature", &Loader::armature);
+       add("link",     &Loader::link);
+}
+
+void Pose::Loader::armature(const string &n)
+{
+       obj.set_armature(get_collection().get<Armature>(n));
+}
+
+void Pose::Loader::link(const string &n)
+{
+       if(!obj.armature)
+               throw logic_error("Armature must be specified first");
+       LinkLoader ldr(obj, obj.armature->get_link(n).get_index());
+       load_sub_with(ldr);
+}
+
+
+Pose::LinkLoader::LinkLoader(Pose &p, unsigned l):
+       DataFile::ObjectLoader<Pose>(p),
+       link_index(l)
+{
+       add("rotation", &LinkLoader::rotation);
+}
+
+void Pose::LinkLoader::rotation(float a, float x, float y, float z)
+{
+       obj.rotate_link(link_index, a, Vector3(x, y, z));
+}
+
+} // namespace GL
+} // namespace Msp