FastLED 3.9.15
Loading...
Searching...
No Matches
Luminova.h
Go to the documentation of this file.
1#include <FastLED.h>
2
3// ===== matrix + LED config =====
4#define WIDTH 32
5#define HEIGHT 32
6#define NUM_LEDS (WIDTH * HEIGHT)
7
8#define DATA_PIN 3
9#define LED_TYPE WS2812B
10#define COLOR_ORDER GRB
11#define BRIGHTNESS 96
12
13using fl::u16;
14
15// Set to 1 if your panel is serpentine; 0 for progressive rows
16const bool kMatrixSerpentineLayout = true;
17// Scale down per-dot intensity to avoid blowout on small grids
18const uint8_t kPointGain = 128; // 50%
19
21
22// UI control for animation speed (telemetry + control)
23
24// Provide the XY() function FastLED expects (in fl namespace) so blur2d can map
25// properly.
26namespace fl {
27fl::u16 XY(fl::u16 x, fl::u16 y) {
28 if (x >= WIDTH || y >= HEIGHT)
29 return 0;
31 if (y & 1) {
32 // odd rows run right-to-left
33 return y * WIDTH + (WIDTH - 1 - x);
34 } else {
35 // even rows run left-to-right
36 return y * WIDTH + x;
37 }
38 } else {
39 return y * WIDTH + x;
40 }
41}
42} // namespace fl
43
44// ===== particle sim (Processing port) =====
45struct P {
46 float x, y; // position
47 float a; // angle
48 int f; // direction (+1 or -1)
49 int g; // group (I in the original)
50 float s; // "stroke weight" / intensity
51 bool alive; // quick guard in case we want to reuse slots
52};
53
54static uint32_t t = 0; // frame-ish counter
55static const int MAXP = 256; // fewer particles for small grids
57
58void resetParticle(P &p, uint32_t tt) {
59 // Original: x=360,y=360 (center), a=t*1.25 + noise(I)*W, f=t%2*2-1, g=I,
60 // s=5
61 int I = (int)(tt / 50);
62 p.x = (WIDTH - 1) / 2.0f;
63 p.y = (HEIGHT - 1) / 2.0f;
64
65 // noise(I)*W -> use 1D Perlin noise via inoise8
66 uint8_t n1 = inoise8(I * 19); // arbitrary scale
67 float noiseW = (n1 / 255.0f) * WIDTH;
68
69 p.a = tt * 1.25f + noiseW; // base angle component
70 p.f = (tt & 1) ? +1 : -1; // alternate direction
71 p.g = I;
72 p.s = 3.0f; // lower initial intensity for small grids
73 p.alive = true;
74}
75
76inline void plotDot(int x, int y, uint8_t v) {
78 return;
79 // Additive white (Processing used stroke(W), i.e., white) with gain control
80 leds[fl::XY((fl::u8)x, (fl::u8)y)] += CHSV(0, 0, scale8(v, kPointGain));
81}
82
83// draw a small disk ~ strokeWeight; 1..3 pixels radius
84void plotSoftDot(float fx, float fy, float s) {
85 // map s (decays from 5) to a pixel radius 1..3
86 float r = constrain(s * 0.5f, 1.0f, 3.0f);
87 int R = (int)ceilf(r);
88 int cx = (int)roundf(fx);
89 int cy = (int)roundf(fy);
90 float r2 = r * r;
91 for (int dy = -R; dy <= R; ++dy) {
92 for (int dx = -R; dx <= R; ++dx) {
93 float d2 = dx * dx + dy * dy;
94 if (d2 <= r2) {
95 // falloff toward edge
96 float fall = 1.0f - (d2 / (r2 + 0.0001f));
97 uint8_t v = (uint8_t)constrain(255.0f * fall, 0.0f, 255.0f);
98 plotDot(cx + dx, cy + dy, v);
99 }
100 }
101 }
102}
103
104void setup() {
107 FastLED.setBrightness(BRIGHTNESS);
108 FastLED.clear(true);
109 // When user adjusts UI, reflect into model speed
110 // Provide screen map to UI with a specific LED diameter
114 fl::ScreenMap screenmap = xy.toScreenMap();
115 screenmap.setDiameter(0.15f);
116 controller->setScreenMap(screenmap);
117 // init particles as "dead"
118 for (int i = 0; i < MAXP; ++i)
119 ps[i].alive = false;
120}
121
122
123
124// Needed for proper blur mapping.
125u16 xy_map_function(u16 x, u16 y, u16 width, u16 height) { return fl::XY(x, y); }
127
128void loop() {
129 // Processing does: background(0, t?9:!createCanvas(...)+W); filter(BLUR)
130 // We emulate a very light global fade + blur to leave trails.
131 // First a tiny global fade, then a mild Gaussian-ish blur.
132 fadeToBlackBy(leds, NUM_LEDS, 18); // stronger fade to prevent blowout
133 blur2d(leds, WIDTH, HEIGHT, 24, xymap); // slightly gentler blur for 32x32
134
135 // Spawn/overwrite one particle per frame, round-robin
136 resetParticle(ps[t % MAXP], t);
137
138 // Update & draw all particles
139 for (int i = 0; i < MAXP; ++i) {
140 if (!ps[i].alive)
141 continue;
142 P &p = ps[i];
143
144 // strokeWeight(p.s *= .997)
145 p.s *= 0.997f;
146 if (p.s < 0.5f) {
147 p.alive = false;
148 continue;
149 } // cheap cull
150
151 // a += (noise(t/99, p.g) - .5) / 9
152 // Use 2D noise: (t/99, g). inoise8 returns 0..255; center at ~128.
153 float tOver99 = (float)t / 99.0f;
154 uint8_t n2 = inoise8((uint16_t)(tOver99 * 4096), (uint16_t)(p.g * 37));
155 float n2c = ((int)n2 - 128) / 255.0f; // ~ -0.5 .. +0.5
156 p.a += (n2c) / 9.0f;
157
158 // x += cos((a)*f), y += sin(a*f) (original had (a+=...)*f inside cos)
159 float aa = p.a * (float)p.f;
160 p.x += cosf(aa);
161 p.y += sinf(aa);
162
163 // draw white point with softness according to s
164 plotSoftDot(p.x, p.y, p.s);
165 }
166
167 FastLED.show();
168 t++;
169 // Cap frame rate a bit like Processing's draw loop
170 FastLED.delay(16); // ~60 FPS
171}
172
173/*** Tips
174 * - Want sharper trails? Lower blur2d strength or raise fadeToBlackBy amount.
175 * - Too many or too few particles? Tweak MAXP.
176 * - Want color instead of white? Replace plotDot/plotSoftDot to use CHSV with
177 * hue based on p.g or p.a.
178 * - If your matrix isn't serpentine, set kMatrixSerpentineLayout=false.
179 */
CRGB leds[NUM_LEDS]
#define NUM_LEDS
#define DATA_PIN
int y
Definition simple.h:93
int x
Definition simple.h:92
XYMap xymap(WIDTH, HEIGHT, SERPENTINE)
#define BRIGHTNESS
Definition Blur.ino:8
FL_DISABLE_WARNING_PUSH FL_DISABLE_WARNING_GLOBAL_CONSTRUCTORS CFastLED FastLED
Global LED strip management instance.
Definition FastLED.cpp:74
central include file for FastLED, defines the CFastLED class/object
CLEDController * controller
#define kMatrixSerpentineLayout
unsigned int xy(unsigned int x, unsigned int y)
#define COLOR_ORDER
Definition advanced.h:42
#define WIDTH
Definition advanced.h:36
#define LED_TYPE
Definition advanced.h:41
#define HEIGHT
Definition advanced.h:37
Base definition for an LED controller.
void setDiameter(float diameter)
static XYMap constructWithUserFunction(u16 width, u16 height, XYFunction xyFunction, u16 offset=0)
Definition xymap.cpp:26
static XYMap constructSerpentine(u16 width, u16 height, u16 offset=0)
Definition xymap.cpp:52
static XYMap constructRectangularGrid(u16 width, u16 height, u16 offset=0)
Definition xymap.cpp:34
void fadeToBlackBy(CRGB *leds, fl::u16 num_leds, fl::u8 fadeBy)
void blur2d(CRGB *leds, fl::u8 width, fl::u8 height, fract8 blur_amount, const fl::XYMap &xymap)
Two-dimensional blur filter.
Definition blur.cpp:72
const uint8_t kPointGain
Definition Luminova.h:18
void plotSoftDot(float fx, float fy, float s)
Definition Luminova.h:84
u16 xy_map_function(u16 x, u16 y, u16 width, u16 height)
Definition Luminova.h:125
void setup()
Definition Luminova.h:104
void plotDot(int x, int y, uint8_t v)
Definition Luminova.h:76
void resetParticle(P &p, uint32_t tt)
Definition Luminova.h:58
static const int MAXP
Definition Luminova.h:55
static uint32_t t
Definition Luminova.h:54
P ps[MAXP]
Definition Luminova.h:56
void loop()
Definition Luminova.h:128
int g
Definition Luminova.h:49
int f
Definition Luminova.h:48
bool alive
Definition Luminova.h:51
float y
Definition Luminova.h:46
float s
Definition Luminova.h:50
float a
Definition Luminova.h:47
float x
Definition Luminova.h:46
Definition Luminova.h:45
uint8_t inoise8(uint16_t x, uint16_t y, uint16_t z)
8-Bit, fixed point implementation of Perlin's noise.
Definition noise.cpp:570
LIB8STATIC_ALWAYS_INLINE uint8_t scale8(uint8_t i, fract8 scale)
Scale one byte by a second one, which is treated as the numerator of a fraction whose denominator is ...
Definition scale8.h:44
unsigned char u8
Definition int.h:17
fl::u16 XY(fl::u8 x, fl::u8 y)
Definition blur.cpp:22
IMPORTANT!
Definition crgb.h:20
Representation of an RGB pixel (Red, Green, Blue)
Definition crgb.h:86
Representation of an HSV pixel (hue, saturation, value (aka brightness)).
Definition hsv.h:15