-
Notifications
You must be signed in to change notification settings - Fork 7
/
Copy pathanimation.cpp
120 lines (98 loc) · 3.52 KB
/
animation.cpp
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
#include <Assert.h>
#include "animation.h"
using namespace pixl;
PassThroughAnimation::PassThroughAnimation(Visualization* viz, LEDs& leds)
: leds_(leds),
viz_(viz) {}
void PassThroughAnimation::init() {}
void PassThroughAnimation::update() {}
void PassThroughAnimation::draw(float interpolation) {
for(int i = 0; i < leds_.length(); i++) {
// TODO: tried by ratio to support different led length and viz length but
// got rounding errors and color spilled over to two pixels
leds_[i] = viz_->getColorByIndex(i);
}
}
ScaledAnimation::ScaledAnimation(Visualization* viz, LEDs& leds)
: leds_(leds),
viz_(viz) {}
void ScaledAnimation::init() {}
void ScaledAnimation::update() {}
// Linear upscale
void ScaledAnimation::upscale() {
int led_length = leds_.length();
int viz_length = viz_->getSize();
// Subtract one from the lengths to get scale because of fencepost problem
//
// Example: If there are 5 LEDs and 3 viz colors, the first color will be
// at 0, the last color at 4, and the other should be at 2. 0, 2, 4.
// Every 2 LEDs. (5 - 1) / (3 - 1) = 2
// LEDs: | | | | |
// Viz: + + +
//
// Example: If there are 10 LEDs and 4 viz colors, the first color will be
// at 0, the last color at 9, leaving the other two at 3 and 6. 0, 3, 6, 9.
// Every 3 LEDs. (10 - 1) / (4 - 1) = 3
// LEDs: | | | | | | | | | |
// Viz: + + + +
float scale = ((float)led_length - 1.0) / ((float)viz_length - 1.0);
// Set up start and end fence posts
leds_[0] = viz_->getColorByIndex(0);
leds_[led_length - 1] = viz_->getColorByIndex(viz_length - 1);
// Fill in the middle
for (int i = 1; i < led_length - 1; i++) {
// Where along the viz array this LED should get its color (decimal)
float index = (float)i / scale;
// Get the indices of the two viz colors this LED will blend
int index1 = (int)floor(index);
int index2 = index1 + 1;
// Get the two viz colors this LED is between
CRGB color1 = viz_->getColorByIndex(index1);
CRGB color2 = viz_->getColorByIndex(index2);
// Find how much of each viz color this LED should get
int ratio1 = 1.0 - fmod(index, 1.0);
int ratio2 = 1.0 - ratio1;
// Blend the two colors this LED is between
CRGB color = CRGB(
(color1.r * ratio1) + (color2.r * ratio2),
(color1.g * ratio1) + (color2.g * ratio2),
(color1.b * ratio1) + (color2.b * ratio2)
);
leds_[i] = color;
}
}
// Example: If there are 5 LEDs and 3 viz colors, the first color will be
// at 0, the last color at 4, and the other should be at 2. 0, 2, 4.
// Every 2 LEDs. (5 - 1) / (3 - 1) = 2
// LEDs: | | | | |
// Viz: + + +
//
// Example: If there are 10 LEDs and 4 viz colors, the first color will be
// at 0, the last color at 9, leaving the other two at 3 and 6. 0, 3, 6, 9.
// Every 3 LEDs. (10 - 1) / (4 - 1) = 3
// LEDs: | | | | | | | | | |
// Viz: + + + +
void ScaledAnimation::downscale() {
int led_length = leds_.length();
int viz_length = viz_->getSize();
float scale = ((float)viz_length - 1) / ((float)led_length - 1);
for(int i = 0; i < led_length; i++) {
leds_[i] = viz_->getColorByIndex((int)(i * scale));
}
}
void ScaledAnimation::draw(float interpolation) {
int led_length = leds_.length();
int viz_length = viz_->getSize();
// Upscale
if (led_length > viz_length) {
upscale();
}
// Downscale
if (led_length < viz_length) {
downscale();
}
// Pass through
for(int i = 0; i < led_length; i++) {
leds_[i] = viz_->getColorByIndex(i);
}
}