ProtoTracer  1.0
Real-time 3D rendering and animation engine
Loading...
Searching...
No Matches
KeyFrameTrack.tpp
Go to the documentation of this file.
1#pragma once
2
3//shift array from position
4template<size_t maxParameters, size_t maxKeyFrames>
5void KeyFrameTrack<maxParameters, maxKeyFrames>::ShiftKeyFrameArray(int position){
6 for(uint8_t i = position; i < currentFrames; i++){
7 keyFrames[i + 1] = keyFrames[i];
8 }
9}
10
11template<size_t maxParameters, size_t maxKeyFrames>
12KeyFrameTrack<maxParameters, maxKeyFrames>::KeyFrameTrack(float min, float max, InterpolationMethod interpMethod){
13 this->min = min;
14 this->max = max;
15 this->interpMethod = interpMethod;
16}
17
18template<size_t maxParameters, size_t maxKeyFrames>
19float KeyFrameTrack<maxParameters, maxKeyFrames>::GetCurrentTime(){
20 currentTime = fmod(millis() / 1000.0f + timeOffset, stopFrameTime - startFrameTime) + startFrameTime;//normalize time and add offset
21
22 return currentTime;
23}
24
25template<size_t maxParameters, size_t maxKeyFrames>
26void KeyFrameTrack<maxParameters, maxKeyFrames>::SetCurrentTime(float setTime){
27 float currentSecs = millis() / 1000.0f;
28
29 //Test case: current time = 1.32s, set time = 1.09s, 1.59s
30 timeOffset = setTime - currentSecs;//1.59 - 1.32 = 0.27, 1.09 - 1.32 = -0.23
31
32}
33
34template<size_t maxParameters, size_t maxKeyFrames>
35void KeyFrameTrack<maxParameters, maxKeyFrames>::Pause(){
36 isActive = false;
37}
38
39template<size_t maxParameters, size_t maxKeyFrames>
40void KeyFrameTrack<maxParameters, maxKeyFrames>::Play(){
41 isActive = true;
42}
43
44template<size_t maxParameters, size_t maxKeyFrames>
45void KeyFrameTrack<maxParameters, maxKeyFrames>::AddParameter(float* parameter){
46 if(currentParameters < maxParameters){
47 parameters[currentParameters] = parameter;
48 currentParameters++;
49 }
50}
51
52template<size_t maxParameters, size_t maxKeyFrames>
53void KeyFrameTrack<maxParameters, maxKeyFrames>::AddKeyFrame(float time, float value){
54 if (currentFrames < maxKeyFrames){
55 value = Mathematics::Constrain(value, min, max);
56
57 if(currentFrames == 0){
58 keyFrames[0].Set(time, value);
59 }
60 else if (time > this->stopFrameTime){
61 keyFrames[currentFrames].Set(time, value);
62 }
63 else{
64 for(int i = 0; i < currentFrames; i++){
65 if(time < keyFrames[i].Time){
66 ShiftKeyFrameArray(i);
67 keyFrames[i].Set(time, value);
68 break;
69 }
70 }
71 }
72
73 currentFrames++;
74
75 this->startFrameTime = time < this->startFrameTime ? time : this->startFrameTime;//set new min time if lesser than current
76 this->stopFrameTime = time > this->stopFrameTime ? time : this->stopFrameTime;//Set new max time if greater than current
77 }
78}
79
80template<size_t maxParameters, size_t maxKeyFrames>
81float KeyFrameTrack<maxParameters, maxKeyFrames>::GetParameterValue(){
82 return parameterValue;
83}
84
85template<size_t maxParameters, size_t maxKeyFrames>
86void KeyFrameTrack<maxParameters, maxKeyFrames>::Reset(){
87 for(int i = 0; i < currentParameters; i++){
88 *(this->parameters[i]) = min;
89 }
90}
91
92template<size_t maxParameters, size_t maxKeyFrames>
93float KeyFrameTrack<maxParameters, maxKeyFrames>::Update(){
94
95 GetCurrentTime();
96
97 byte previousFrame = 0, nextFrame = 0;
98
99 //find current time, find keyframe before and after
100 if(currentFrames > 0 && isActive){
101 for (uint8_t i = currentFrames - 1; i >= 0; i--){
102 if (currentTime >= keyFrames[i].Time){
103 previousFrame = i;
104 nextFrame = i + 1;
105
106 break;
107 }
108 }
109
110 float ratio = Mathematics::Map(currentTime, keyFrames[previousFrame].Time, keyFrames[nextFrame].Time, 0.0f, 1.0f);
111 float parameter = 0.0f;
112
113 switch(interpMethod){
114 case Cosine:
115 parameter = Mathematics::CosineInterpolation(keyFrames[previousFrame].Value, keyFrames[nextFrame].Value, ratio);
116 break;
117 case Step:
118 parameter = keyFrames[previousFrame].Value;
119 break;
120 default://Linear
121 parameter = Mathematics::Map(ratio, 0.0f, 1.0f, keyFrames[previousFrame].Value, keyFrames[nextFrame].Value);
122 break;
123
124 }
125
126 parameterValue = parameter;
127
128 if (currentParameters > 0){//Update if not parameters are linked
129 for(uint8_t i = 0; i < currentParameters; i++){
130 *(this->parameters[i]) = parameter;
131 }
132 }
133 }
134
135 return parameterValue;
136}