]> git.tdb.fi Git - libs/gl.git/blob - source/pose.cpp
Add classes for armature-based deformation
[libs/gl.git] / source / pose.cpp
1 #include <msp/datafile/collection.h>
2 #include "armature.h"
3 #include "error.h"
4 #include "pose.h"
5
6 using namespace std;
7
8 namespace Msp {
9 namespace GL {
10
11 Pose::Pose():
12         armature(0)
13 { }
14
15 Pose::Pose(const Armature &a):
16         armature(0)
17 {
18         set_armature(a);
19 }
20
21 void Pose::set_armature(const Armature &a)
22 {
23         if(armature)
24                 throw invalid_operation("Pose::set_armature");
25         armature = &a;
26         links.resize(armature->get_max_link_index()+1);
27 }
28
29 void Pose::rotate_link(unsigned i, float angle, const Vector3 &axis)
30 {
31         if(i>=links.size())
32                 throw out_of_range("Pose::rotate_link");
33
34         const Armature::Link &arm_link = armature->get_link(i);
35         links[i].local_matrix.rotate(angle, axis);
36
37         // Keep the base point stationary
38         Vector3 base = arm_link.get_base();
39         Vector3 new_base = links[i].local_matrix*base;
40         links[i].local_matrix.translate(base.x-new_base.x, base.y-new_base.y, base.z-new_base.z);
41
42         if(const Armature::Link *parent = arm_link.get_parent())
43                 links[i].matrix = links[parent->get_index()].matrix*links[i].local_matrix;
44
45         // XXX apply matrix to descendants of the link
46 }
47
48 const Matrix &Pose::get_link_matrix(unsigned i) const
49 {
50         if(i>=links.size())
51                 throw out_of_range("Pose::get_link_matrix");
52         return links[i].matrix;
53 }
54
55
56 Pose::Loader::Loader(Pose &p, Collection &c):
57         DataFile::CollectionObjectLoader<Pose>(p, &c)
58 {
59         add("armature", &Pose::armature);
60         add("link",     &Loader::link);
61 }
62
63 void Pose::Loader::link(const string &n)
64 {
65         if(!obj.armature)
66                 error("Armature must be specified first");
67         LinkLoader ldr(obj, obj.armature->get_link(n).get_index());
68         load_sub_with(ldr);
69 }
70
71
72 Pose::LinkLoader::LinkLoader(Pose &p, unsigned l):
73         DataFile::ObjectLoader<Pose>(p),
74         link_index(l)
75 {
76         add("rotation", &LinkLoader::rotation);
77 }
78
79 void Pose::LinkLoader::rotation(float a, float x, float y, float z)
80 {
81         obj.rotate_link(link_index, a, Vector3(x, y, z));
82 }
83
84 } // namespace GL
85 } // namespace Msp