]> git.tdb.fi Git - libs/gl.git/blob - source/pose.cpp
Tweak buffer logic a bit in Batch::draw
[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 = GL::Matrix::translation(base-new_base)*links[i].local_matrix;
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", &Loader::armature);
60         add("link",     &Loader::link);
61 }
62
63 void Pose::Loader::armature(const string &n)
64 {
65         obj.set_armature(get_collection().get<Armature>(n));
66 }
67
68 void Pose::Loader::link(const string &n)
69 {
70         if(!obj.armature)
71                 throw logic_error("Armature must be specified first");
72         LinkLoader ldr(obj, obj.armature->get_link(n).get_index());
73         load_sub_with(ldr);
74 }
75
76
77 Pose::LinkLoader::LinkLoader(Pose &p, unsigned l):
78         DataFile::ObjectLoader<Pose>(p),
79         link_index(l)
80 {
81         add("rotation", &LinkLoader::rotation);
82 }
83
84 void Pose::LinkLoader::rotation(float a, float x, float y, float z)
85 {
86         obj.rotate_link(link_index, a, Vector3(x, y, z));
87 }
88
89 } // namespace GL
90 } // namespace Msp