/
bone.h
executable file
·160 lines (145 loc) · 5.12 KB
/
bone.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
#pragma once
// value_ptr for glm
#include <glm/gtc/type_ptr.hpp>
#include <glm/gtc/matrix_transform.hpp>
using namespace glm;
class keyframe
{
public:
quat quaternion;
vec3 translation;
long long timestamp_ms;
};
class animation_per_bone
{
public:
string name;
long long duration;
int frames;
string bone;
vector<keyframe> keyframes;
};
class all_animations
{
public:
vector<animation_per_bone> animations;
};
//**************************************************
class bone
{
public:
vector<animation_per_bone*> animation; //all the animations of the bone
string name;
vec3 pos;
quat q;
bone *parent = NULL;
vector<bone*> kids;
unsigned int index; //a unique number for each bone, at the same time index of the animatiom matrix array
mat4 *mat = NULL; //address of one lement from the animation matrix array
// searches for the animation and sets the animation matrix element to the recent matrix gained from the keyframe
void play_animation(float* keyframenumber, int ai1, int ai2, float t)
{
float kfn1;
float kfn2;
if (animation[ai1]->keyframes.size() == animation[ai2]->keyframes.size()) {
kfn1 = *keyframenumber;
kfn2 = *keyframenumber;
}
else {
float avgkfn = (animation[ai1]->keyframes.size() + animation[ai2]->keyframes.size()) /2;
//cast part to float
if (t < .000001) {
kfn1 = (*keyframenumber * (animation[ai1]->keyframes.size() / animation[ai1]->keyframes.size()));
kfn2 = (*keyframenumber * (animation[ai2]->keyframes.size() / animation[ai1]->keyframes.size()));
}
else if (t-1 < .000001){
kfn1 = (*keyframenumber * (animation[ai1]->keyframes.size() / animation[ai2]->keyframes.size()));
kfn2 = (*keyframenumber * (animation[ai2]->keyframes.size() / animation[ai2]->keyframes.size()));
}
else {
kfn1 = (*keyframenumber * (animation[ai1]->keyframes.size() / avgkfn));
kfn2 = (*keyframenumber * (animation[ai2]->keyframes.size() / avgkfn));
}
}
quat q;
vec3 tr;
if (!(animation[ai1]->keyframes.size() -2 > (int)kfn1 && animation[ai2]->keyframes.size() > (int)kfn2)) {
*keyframenumber = 0;
kfn1 = 0;
kfn2 = 0;
}
if (abs(t - 1) < .001 || t < .001) {
float kf = kfn1;
int i = ai1;
if (abs(t - 1) < .001) {
i = ai2;
kf = kfn2;
}
quat p = animation[i]->keyframes[(int)kf].quaternion;
quat c = animation[i]->keyframes[((int)kf + 1) % animation[i]->keyframes.size()].quaternion;
q = slerp(p, c, kf - (long)kf);
tr = (1 - (kf - (long)kf)) * animation[i]->keyframes[kf].translation
+ (kf - (long)kf) * animation[i]->keyframes[((int)kf + 1) % animation[i]->keyframes.size()].translation;
}
else {
quat p = animation[ai1]->keyframes[(int)kfn1].quaternion;
quat c = animation[ai1]->keyframes[((int)kfn1 + 1) % animation[ai1]->keyframes.size()].quaternion;
quat q1 = slerp(p,c,kfn1 - long(kfn1));
p = animation[ai2]->keyframes[(int)kfn2].quaternion;
c = animation[ai2]->keyframes[((int)kfn2 + 1) % animation[ai2]->keyframes.size()].quaternion;
quat q2 = slerp(p, c, kfn2 - long(kfn2));
q = slerp(q1, q2, t);
q = normalize(q);
vec3 tr1 = (1 - (kfn1 - (long)kfn1)) * animation[ai1]->keyframes[kfn1].translation
+ (kfn1 - (long)kfn1) * animation[ai1]->keyframes[((int)kfn1 + 1) % animation[ai1]->keyframes.size()].translation;
vec3 tr2 = (1 - (kfn2 - (long)kfn2)) * animation[ai2]->keyframes[kfn2].translation
+ (kfn2 - (long)kfn2) * animation[ai2]->keyframes[((int)kfn2 + 1) % animation[ai2]->keyframes.size()].translation;
tr = (1 - t) * tr1 + t * tr2;
//tr = (1 - t) * animation[ai1]->keyframes[kfn1].translation + t * animation[ai2]->keyframes[kfn2].translation;
}
if (name == "Humanoid:Hips")
tr = vec3(0, 0, 0);
mat4 M = mat4(q);
mat4 T = translate(mat4(1), tr);
M = T * M;
if (mat)
{
mat4 parentmat = mat4(1);
if (parent)
parentmat = *parent->mat;
*mat = parentmat * M;
}
else {
*mat = mat4(1);
}
for (int i = 0; i < kids.size(); i++)
kids[i]->play_animation(keyframenumber, ai1, ai2, t);
}
//writes into the segment positions and into the animation index VBO
void write_to_VBOs(vec3 origin, vector<vec3> &vpos, vector<unsigned int> &imat)
{
vpos.push_back(origin);
vec3 endp = origin + pos;
vpos.push_back(endp);
if(parent)
imat.push_back(parent->index);
else
imat.push_back(index);
imat.push_back(index);
for (int i = 0; i < kids.size(); i++)
kids[i]->write_to_VBOs(endp, vpos, imat);
}
//searches for the correct animations as well as sets the correct element from the animation matrix array
void set_animations(all_animations *all_anim,mat4 *matrices,int &animsize)
{
for (int ii = 0; ii < all_anim->animations.size(); ii++) {
if (all_anim->animations[ii].bone == name)
animation.push_back(&all_anim->animations[ii]);
}
mat = &matrices[index];
animsize++;
for (int i = 0; i < kids.size(); i++)
kids[i]->set_animations(all_anim, matrices, animsize);
}
};
int readtobone(string file,all_animations *all_animation, bone **proot,int flag);