FastLED 3.9.15
Loading...
Searching...
No Matches
BilinearCompression.ino
Go to the documentation of this file.
1
2
3/*
4This demo is best viewed using the FastLED compiler.
5Install: pip install fastled
6Run: fastled <this sketch directory>
7This will compile and preview the sketch in the browser, and enable
8all the UI elements you see below.
9*/
10
11#include <Arduino.h>
12#include <FastLED.h>
13
14#include "fl/draw_visitor.h"
15#include "fl/math_macros.h"
16#include "fl/raster.h"
17#include "fl/time_alpha.h"
18#include "fl/ui.h"
19#include "fl/xypath.h"
20#include "fx/time.h"
21#include "fl/bilinear_compression.h"
22
23// Sketch.
24#include "src/wave.h"
25#include "src/xypaths.h"
26
27using namespace fl;
28
29#define HEIGHT 64
30#define WIDTH 64
31#define NUM_LEDS ((WIDTH) * (HEIGHT))
32#define TIME_ANIMATION 1000 // ms
33
35CRGB leds_downscaled[NUM_LEDS / 4]; // Downscaled buffer
36
38XYMap xyMap_Dst(WIDTH / 2, HEIGHT / 2, false); // Framebuffer is regular rectangle LED matrix.
39// XYPathPtr shape = XYPath::NewRosePath(WIDTH, HEIGHT);
40
41// Speed up writing to the super sampled waveFx by writing
42// to a raster. This will allow duplicate writes to be removed.
43
44WaveEffect wave_fx; // init in setup().
46
47
50
51XYPathPtr getShape(int which) {
52 int len = shapes.size();
53 which = which % len;
54 if (which < 0) {
55 which += len;
56 }
57 return shapes[which];
58}
59
61UITitle title("XYPath Demo");
62UIDescription description("Use a path on the WaveFx");
63UIButton trigger("Trigger");
64UISlider whichShape("Which Shape", 0.0f, 0.0f, shapes.size() - 1, 1.0f);
65UICheckbox useWaveFx("Use WaveFX", true);
66UISlider transition("Transition", 0.0f, 0.0f, 1.0f, 0.01f);
67
68UISlider scale("Scale", 1.0f, 0.0f, 1.0f, 0.01f);
69UISlider speed("Speed", 1.0f, -20.0f, 20.0f, 0.01f);
70UISlider numberOfSteps("Number of Steps", 32.0f, 1.0f, 100.0f, 1.0f);
71UISlider maxAnimation("Max Animation", 1.0f, 5.0f, 20.0f, 1.f);
72
74
76 speed.onChanged([](float value) { time_warp.setSpeed(speed.value()); });
77 maxAnimation.onChanged(
78 [](float value) { shapeProgress.set_max_clamp(maxAnimation.value()); });
79
80 trigger.onChanged([]() {
81 // shapeProgress.trigger(millis());
82 FASTLED_WARN("Trigger pressed");
83 });
84 useWaveFx.onChanged([](bool on) {
85 if (on) {
86 FASTLED_WARN("WaveFX enabled");
87 } else {
88 FASTLED_WARN("WaveFX disabled");
89 }
90 });
91}
92
93void setup() {
94 Serial.begin(115200);
95 auto screenmap = xyMap.toScreenMap();
96 screenmap.setDiameter(.2);
97 FastLED.addLeds<NEOPIXEL, 2>(leds, xyMap.getTotal()).setScreenMap(screenmap);
98 auto screenmap2 = xyMap_Dst.toScreenMap();
99 screenmap.setDiameter(.5);
100 screenmap2.addOffsetY(-HEIGHT / 2);
101 FastLED.addLeds<NEOPIXEL, 3>(leds_downscaled, xyMap_Dst.getTotal())
102 .setScreenMap(screenmap2);
104 // Initialize wave simulation. Please don't use static constructors, keep it
105 // in setup().
106 trigger.click();
108}
109
111
112float getAnimationTime(uint32_t now) {
113 float pointf = shapeProgress.updatef(now);
114 return pointf + transition.value();
115}
116
121
122void loop() {
123 // Your code here
124 clearLeds();
125 const uint32_t now = millis();
126 uint32_t now_warped = time_warp.update(now);
127
128 auto shape = getShape(whichShape.as<int>());
129 shape->setScale(scale.value());
130
131 float curr_alpha = getAnimationTime(now_warped);
132 static float s_prev_alpha = 0.0f;
133
134 // unconditionally apply the circle.
135 if (trigger) {
136 // trigger the transition
137 time_warp.reset(now);
138 now_warped = time_warp.update(now);
139 shapeProgress.trigger(now_warped);
140 FASTLED_WARN("Transition triggered on " << shape->name());
141 curr_alpha = getAnimationTime(now_warped);
142 s_prev_alpha = curr_alpha;
143 }
144
145 const bool is_active =
146 true || curr_alpha < maxAnimation.value() && curr_alpha > 0.0f;
147
148 static uint32_t frame = 0;
149 frame++;
150 clearLeds();
151 const CRGB purple = CRGB(255, 0, 255);
152 const int number_of_steps = numberOfSteps.value();
153 raster.reset();
154
155 float diff = curr_alpha - s_prev_alpha;
156 diff *= 1.0f;
157 float factor = MAX(s_prev_alpha - diff, 0.f);
158
159 for (int i = 0; i < number_of_steps; ++i) {
160 float a =
161 fl::map_range<float>(i, 0, number_of_steps - 1, factor, curr_alpha);
162 if (a < .04) {
163 // shorter tails at first.
164 a = map_range<float>(a, 0.0f, .04f, 0.0f, .04f);
165 }
166 float diff_max_alpha = maxAnimation.value() - curr_alpha;
167 if (diff_max_alpha < 0.94) {
168 // shorter tails at the end.
169 a = map_range<float>(a, curr_alpha, maxAnimation.value(),
170 curr_alpha, maxAnimation.value());
171 }
172 uint8_t alpha =
173 fl::map_range<uint8_t>(i, 0.0f, number_of_steps - 1, 64, 255);
174 if (!is_active) {
175 alpha = 0;
176 }
177 Tile2x2_u8 subpixel = shape->at_subpixel(a);
178 subpixel.scale(alpha);
179 // subpixels.push_back(subpixel);
180 raster.rasterize(subpixel);
181 }
182
183 s_prev_alpha = curr_alpha;
184
185
186 if (useWaveFx && is_active) {
187 DrawRasterToWaveSimulator draw_wave_fx(&wave_fx);
188 raster.draw(xyMap, draw_wave_fx);
189 } else {
190 raster.draw(purple, xyMap, leds);
191 }
192
193 int first = xyMap(1, 1);
194 int last = xyMap(WIDTH - 2, HEIGHT - 2);
195
196 leds[first] = CRGB(255, 0, 0);
197 leds[last] = CRGB(0, 255, 0);
198 if (useWaveFx) {
199 // fxBlend.draw(Fx::DrawContext(now, leds));
200 wave_fx.draw(Fx::DrawContext(now, leds));
201 }
202
203 // downscaleBilinear(leds, WIDTH, HEIGHT, leds_downscaled, WIDTH / 2,
204 // HEIGHT / 2);
205
207
208 // Print out the first 10 pixels of the original and downscaled
209 fl::vector_inlined<CRGB, 10> downscaled_pixels;
210 fl::vector_inlined<CRGB, 10> original_pixels;
211 for (int i = 0; i < 10; ++i) {
212 original_pixels.push_back(leds[i]);
213 downscaled_pixels.push_back(leds_downscaled[i]);
214 }
215
216 FastLED.show();
217}
CRGB leds[NUM_LEDS]
Definition Apa102.ino:11
#define NUM_LEDS
Definition Apa102.ino:6
UISlider transition("Transition", 0.0f, 0.0f, 1.0f, 0.01f)
#define WIDTH
UIDescription description("Use a path on the WaveFx")
void setup()
UISlider speed("Speed", 1.0f, -20.0f, 20.0f, 0.01f)
void clearLeds()
TimeClampedTransition shapeProgress(TIME_ANIMATION)
XYPathPtr getShape(int which)
UITitle title("XYPath Demo")
XYMap xyMap_Dst(WIDTH/2, HEIGHT/2, false)
XYMap xyMap(WIDTH, HEIGHT, false)
UICheckbox useWaveFx("Use WaveFX", true)
WaveEffect wave_fx
void setupUiCallbacks()
UISlider numberOfSteps("Number of Steps", 32.0f, 1.0f, 100.0f, 1.0f)
UISlider scale("Scale", 1.0f, 0.0f, 1.0f, 0.01f)
XYRaster raster(WIDTH, HEIGHT)
fl::vector< XYPathPtr > shapes
TimeWarp time_warp
float getAnimationTime(uint32_t now)
UISlider whichShape("Which Shape", 0.0f, 0.0f, shapes.size() - 1, 1.0f)
UISlider maxAnimation("Max Animation", 1.0f, 5.0f, 20.0f, 1.f)
#define TIME_ANIMATION
UIButton trigger("Trigger")
#define HEIGHT
CRGB leds_downscaled[NUM_LEDS/4]
void loop()
CFastLED FastLED
Global LED strip management instance.
Definition FastLED.cpp:58
central include file for FastLED, defines the CFastLED class/object
LED controller for WS2812 LEDs with GRB color order.
Definition FastLED.h:146
_DrawContext DrawContext
Definition fx.h:21
void push_back(const T &value)
Definition vector.h:919
void scale(uint8_t scale)
Definition tile2x2.cpp:24
WaveEffect NewWaveSimulation2D(const XYMap xymap)
Definition wave.cpp:42
#define MAX(a, b)
Definition math_macros.h:11
InlinedVector< T, INLINED_SIZE > vector_inlined
Definition vector.h:1034
XYRasterU8Sparse XYRaster
Definition raster.h:8
void clear(CRGB(&arr)[N])
Definition clear.h:8
void downscaleHalf(const CRGB *src, uint16_t srcWidth, uint16_t srcHeight, CRGB *dst)
Definition downscale.cpp:17
HeapVector< T > vector
Definition vector.h:1028
FASTLED_FORCE_INLINE U map_range(T value, T in_min, T in_max, U out_min, U out_max)
Definition map_range.h:26
Implements a simple red square effect for 2D LED grids.
Definition crgb.h:16
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:55
#define FASTLED_WARN
Definition warn.h:7
fl::vector< XYPathPtr > CreateXYPaths(int width, int height)
Definition xypaths.cpp:31