-
Notifications
You must be signed in to change notification settings - Fork 0
/
Animation.h
140 lines (123 loc) · 3.58 KB
/
Animation.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
#ifndef Animation_h
#define Animation_h
#include <vector>
#include <algorithm>
#include <iostream>
#include <math.h>
#include <signal.h>
template<typename ValueType>
class Animation
{
public:
Animation():map() { }
Animation(ValueType val)
:map()
,values()
{
map.push_back(entry(0,val));
}
const ValueType& operator()(int t) const
{
return values.at(t);
}
const ValueType& operator()(double t) const
{
//this slows things down considerably.
//This should be changed to a map lookup instead of a vector eventually for motion blur
/*if(values.empty())
{
std::cerr << "attempting to access an empty (non preprocessed) animation" << std::endl;
}
double dummy;
if(std::modf(t, &dummy) == 0.0) //t is a whole integer use preprocessed map
{
if(values.size() < t)
{
std::cerr << "attempting to access an out of bounds entry" << t << std::endl;
exit(1);
}
*/
return values.at(t);
/* }
else
{
std::cerr << "adding floating point as a frame is not supported yet!" << std::endl;
exit(1);
}*/
}
void addFrame(double t, ValueType v)
{
map.push_back(entry(t,v));
}
void preprocess(int maxTime)
{
if(maxTime < 0) raise(6);
if(values.size() == (unsigned)maxTime+1) //don't double preprocess
return;
values.resize(maxTime+1);
for(int i = 0; i <= maxTime; i++)
{
auto item = std::find(map.begin(), map.end(), (double)i);
if(item != map.end())
values[i] = (*item).value;
else
values[i] = interpolatedValue(i);
}
}
ValueType interpolatedValue(double t)
{
auto a = justLess(t);
if(a.key == t) return a.value;
auto b = justMore(t);
if(b.key == t) return b.value;
if((b.key - a.key)==0) return a.value;
auto weight = (t - a.key)/(b.key - a.key);
return a.value * (1-weight) + b.value * weight;
}
bool isEmpty() const { return map.empty(); }
bool isEmpty2() const { return values.empty(); }
private:
struct entry
{
double key;
ValueType value;
entry(double key, ValueType value):key(key),value(value){}
bool operator<(entry e) const
{
return key < e.key;
}
bool operator==(double _key) const
{
return key == _key;
}
};
entry justLess(double t) const
{
std::vector<entry> less;
std::copy_if(
map.begin()
,map.end()
,std::back_inserter(less)
,[=](entry e){return e.key < t;});
std::sort(less.begin(),less.end());
if(!less.empty()) return less.back();
std::sort(map.begin(),map.end());
return map.front();
}
entry justMore(double t) const
{
std::vector<entry> more;
std::copy_if(
map.begin()
,map.end()
,std::back_inserter(more)
,[=](entry e){return e.key > t;});
std::sort(more.begin(),more.end());
if(!more.empty()) return more.front();
std::sort(map.begin(),map.end());
return map.back();
}
mutable std::vector<entry> map;
std::vector<ValueType> values;
};
#endif //Animation_h