-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathkeytime.cpp
More file actions
182 lines (144 loc) · 3.63 KB
/
keytime.cpp
File metadata and controls
182 lines (144 loc) · 3.63 KB
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
#include "keytime.h"
Keytimes::Keytimes( )
{
tvs.clear( );
}
Keytimes::~Keytimes( )
{
for( std::vector<struct TimeValue *>::iterator tvi = tvs.begin( ); tvi < tvs.end( ); tvi++ )
{
delete (*tvi);
}
}
void
Keytimes::AddTimeValue( float _time, float _value )
{
// if _time matches a previous time, just replace the value:
for( std::vector<struct TimeValue *>::iterator tvi = tvs.begin( ); tvi < tvs.end( ); tvi++ )
{
if( _time == (*tvi)->time )
{
(*tvi)->value = _value;
return;
}
}
// create the new struct to hold the time-value pair:
struct TimeValue * tv = new struct TimeValue;
tv->time = _time;
tv->value = _value;
// if the list is empty, just do a push_back():
if( tvs.empty( ) )
{
tvs.push_back( tv );
return;
}
// otherwise, insert the new time-value pair right before the next biggest time:
for( std::vector<struct TimeValue *>::iterator tvi = tvs.begin( ); tvi < tvs.end( ); tvi++ )
{
if( _time < (*tvi)->time )
{
tvs.insert( tvi, tv );
return;
}
}
// if it's not < any times in the vector, put it at the back:
tvs.push_back( tv );
}
float
Keytimes::GetFirstTime( )
{
return tvs.front( )->time;
}
float
Keytimes::GetLastTime( )
{
return tvs.back( )->time;
}
int
Keytimes::GetNumKeytimes( )
{
return tvs.size( );
}
float
Keytimes::GetValue( float _time )
{
// if empty, return zero:
if( tvs.empty( ) )
return 0.;
// if _time is outside the existing range, clamp to the existing range:
if( _time <= tvs.front( )->time )
return tvs.front( )->value;
if( _time >= tvs.back( )->time )
return tvs.back( )->value;
// find which pair of key-times we are between:
// (this is guaranteed to succeed)
int i0, i1;
float t0, t1;
float v0, v1;
for( int i = 0; i < (int)tvs.size()-1; i++ )
{
if( tvs[i]->time <= _time && _time <= tvs[i+1]->time )
{
i0 = i+0;
i1 = i+1;
t0 = tvs[i+0]->time;
t1 = tvs[i+1]->time;
v0 = tvs[i+0]->value;
v1 = tvs[i+1]->value;
break;
}
}
// fprintf( stderr, "_time = %8.3f: i0 = %3d, i1 = %3d, t0 = %8.2f, t1 = %8.3f\n", _time, i0, i1, t0, t1 );
float dvaluedtime0;
float dvaluedtime1;
if( i0 == 0 )
dvaluedtime0 = 0.;
else
dvaluedtime0 = ( v1 - tvs[i0-1]->value ) / ( t1 - tvs[i0-1]->time );
if( i1 == tvs.size( ) - 1 )
dvaluedtime1 = 0.;
else
dvaluedtime1 = ( tvs[i1+1]->value - v0 ) / ( tvs[i1+1]->time - t0 );
float dtimedt = ( t1 - t0 ) / ( 1.f - 0.f );
float dvaluedt0 = dvaluedtime0 * dtimedt;
float dvaluedt1 = dvaluedtime1 * dtimedt;
float a = 2.f*v0 - 2.f*v1 + dvaluedt0 + dvaluedt1;
float b = -3.f*v0 + 3.f*v1 -2.f*dvaluedt0 - dvaluedt1;
float c = dvaluedt0;
float d = v0;
float ttt = ( _time - t0 ) / ( t1 - t0 ); // 0. <= ttt <= 1.
// fprintf( stderr, "ttt = %8.3f\n", ttt );
float value = d + ttt * ( c + ttt * ( b + ttt*a ) );
return value;
}
void
Keytimes::PrintTimeValues( )
{
for( std::vector<struct TimeValue *>::iterator tvi = tvs.begin( ); tvi < tvs.end( ); tvi++ )
{
fprintf( stderr, "(%6.2f,%8.3f) ", (*tvi)->time, (*tvi)->value );
}
fprintf( stderr, "\n" );
}
#ifdef TEST
Keytimes xpos;
int
main( int argc, char *argv[ ] )
{
xpos.AddTimeValue( 0.0, 0.000 );
xpos.PrintTimeValues( );
xpos.AddTimeValue( 2.0, 0.333 );
xpos.PrintTimeValues( );
xpos.AddTimeValue( 1.0, 3.142 );
xpos.PrintTimeValues( );
xpos.AddTimeValue( 0.5, 2.718 );
xpos.PrintTimeValues( );
fprintf( stderr, "%d time-value pairs\n", xpos.GetNumKeytimes( ) );
fprintf( stderr, "Time runs from %8.3f to %8.3f\n", xpos.GetFirstTime( ), xpos.GetLastTime( ) );
for( float t = 0.; t <= 2.02; t += 0.1 )
{
float v = xpos.GetValue( t );
fprintf( stderr, "%8.3f\t%8.3f\n", t, v );
}
}
#endif