FastLED 3.9.15
Loading...
Searching...
No Matches
particles.cpp.hpp
Go to the documentation of this file.
2#include "fl/system/fastled.h"
3#include "fl/gfx/blur.h"
4#include "fl/stl/noexcept.h"
5
6namespace fl {
7
8Particles1d::Particles1d(u16 num_leds, u8 max_particles, u8 fade_rate)
9 : Fx1d(num_leds),
10 mFadeRate(fade_rate),
12 mSpeedMultiplier(1.0f),
13 mCyclical(true),
14 mParticles(max_particles) {
15}
16
18
20 if (context.leds.empty() || mNumLeds == 0) return;
21
22 u32 now = context.now;
23
24 // Overdraw loop: multiple updates per frame for smooth trails
25 for (int overdraw = 0; overdraw < mOverdrawCount; overdraw++) {
26 // Fade trails
27 for (u16 i = 0; i < mNumLeds; i++) {
28 context.leds[i].nscale8(255 - mFadeRate);
29 }
30
31 // Update and draw all particles
32 for (size_t i = 0; i < mParticles.size(); i++) {
34 mParticles[i].draw(context.leds, now, mNumLeds);
35 }
36 }
37
38 // Soften composite with blur
39 blur1d(context.leds, 64);
40}
41
43 // First, try to find an inactive particle
44 for (size_t i = 0; i < mParticles.size(); i++) {
45 if (!mParticles[i].active) {
46 mParticles[i].spawn(mNumLeds);
47 return;
48 }
49 }
50
51 // All slots full - find and reuse the oldest particle
52 size_t oldestIdx = 0;
53 u32 oldestTime = mParticles[0].birthTime;
54 for (size_t i = 1; i < mParticles.size(); i++) {
55 if (mParticles[i].birthTime < oldestTime) {
56 oldestTime = mParticles[i].birthTime;
57 oldestIdx = i;
58 }
59 }
60 mParticles[oldestIdx].spawn(mNumLeds);
61}
62
63void Particles1d::setLifetime(u16 lifetime_ms) {
64 mLifetimeMs = lifetime_ms;
65}
66
68 mOverdrawCount = count;
69}
70
74
76 mFadeRate = fade_rate;
77}
78
79void Particles1d::setCyclical(bool cyclical) {
80 mCyclical = cyclical;
81}
82
84 return "Particles1d";
85}
86
87// Particle methods
89
90float Particles1d::Particle::getPower(u32 now) const {
91 if (!active || !lifetime) return 0.0f;
92 float power = 1.0f - (float)(now - birthTime) / lifetime;
93 return fl::clamp(power, 0.0f, 1.0f);
94}
95
97 pos = random16(numLeds);
98 float speed = 0.02f + (random16(1000) / 1000.0f) * 0.13f;
99 baseVel = random8(2) ? speed : -speed;
100 baseColor = CHSV(random8(), random8(), 120 + random8(81));
101 lifetime = 4000 * (500 + random16(1000)) / 1000; // 2-6 seconds
103 active = true;
104}
105
107 this->pos = pos;
108 this->baseVel = baseVel;
109 this->baseColor = baseColor;
110 this->lifetime = lifetime;
111 this->birthTime = fl::millis();
112 this->active = true;
113}
114
115void Particles1d::Particle::update(u32 now, u16 numLeds, float speedMultiplier, bool cyclical) {
116 if (!active) return;
117 float power = getPower(now);
118 if (power <= 0.0f) {
119 active = false;
120 return;
121 }
122
123 pos += baseVel * power * speedMultiplier;
124
125 if (cyclical) {
126 // Wrap around (cyclical)
127 while (pos >= numLeds) pos -= numLeds;
128 while (pos < 0) pos += numLeds;
129 } else {
130 // Stop at edges
131 if (pos >= numLeds || pos < 0) {
132 active = false;
133 }
134 }
135}
136
138 if (!active) return;
139 float power = getPower(now);
140 if (power <= 0.0f) return;
141
142 // Power effects: slow down, saturate, dim
143 u8 sat = baseColor.sat + (1.0f - power) * (255 - baseColor.sat);
144 u8 val = baseColor.val * power;
145 CRGB color = CHSV(baseColor.hue, sat, val);
146
147 // Sub-pixel rendering
148 int i = (int)pos;
149 float frac = pos - i;
150 if (i >= 0 && i < (int)numLeds)
151 leds[i] += color.nscale8(255 * (1.0f - frac));
152 if (i + 1 >= 0 && i + 1 < (int)numLeds && frac > 0)
153 leds[i + 1] += color.nscale8(255 * frac);
154}
155
156} // namespace fl
fl::CRGB leds[NUM_LEDS]
uint16_t speed
Definition Noise.ino:66
Fx1d(u16 numLeds)
Definition fx1d.h:12
u16 mNumLeds
Definition fx.h:53
~Particles1d() FL_NOEXCEPT
void setSpeed(float speed)
Set speed multiplier (1.0 = normal, >1.0 = faster, <1.0 = slower)
fl::vector< Particle > mParticles
Particle pool (oldest particle reused when full)
Definition particles.h:137
void setCyclical(bool cyclical)
Set cyclical mode (true = wrap around, false = stop at edges)
u8 mFadeRate
Fade amount per frame (0-255, higher = shorter trails)
Definition particles.h:132
Particles1d(u16 num_leds, u8 max_particles=10, u8 fade_rate=2)
void setFadeRate(u8 fade_rate)
Set fade rate for trails (0-255, higher = shorter trails)
u8 mOverdrawCount
Number of update/draw cycles per frame (higher = smoother trails, more CPU)
Definition particles.h:134
u16 mLifetimeMs
Average particle lifetime in milliseconds.
Definition particles.h:133
void setOverdrawCount(u8 count)
Set overdraw count (higher = smoother trails, more CPU)
float mSpeedMultiplier
Global speed multiplier (1.0 = normal, >1.0 = faster, <1.0 = slower)
Definition particles.h:135
bool mCyclical
Wrap mode: true = wrap around, false = stop at edges.
Definition particles.h:136
void spawnRandomParticle()
Spawn a particle with random position, velocity, color, and lifetime.
fl::string fxName() const override
void draw(DrawContext context) override
Update and render all particles with overdraw technique.
void setLifetime(u16 lifetime_ms)
Set average particle lifetime in milliseconds.
Internal FastLED header for implementation files.
fl::hsv8 CHSV
Definition chsv.h:11
LIB8STATIC fl::u16 random16() FL_NOEXCEPT
Generate a 16-bit random number.
Definition random8.h:63
LIB8STATIC fl::u8 random8() FL_NOEXCEPT
Generate an 8-bit random number.
Definition random8.h:53
unsigned char u8
Definition stdint.h:131
fl::u32 millis()
Universal millisecond timer - returns milliseconds since system startup.
void blur1d(fl::span< CRGB > leds, fract8 blur_amount) FL_NOEXCEPT
Definition blur.h:150
constexpr enable_if< is_fixed_point< T >::value, T >::type clamp(T x, T lo, T hi) FL_NOEXCEPT
Base definition for an LED controller.
Definition crgb.hpp:179
#define FL_NOEXCEPT
CRGB & nscale8(u8 scaledown) FL_NOEXCEPT
Scale down a RGB to N/256ths of its current brightness, using "plain math" dimming rules.
Definition crgb.cpp.hpp:88
Representation of an 8-bit RGB pixel (Red, Green, Blue)
Definition crgb.h:38
void draw(fl::span< CRGB > leds, u32 now, u16 numLeds)
Render particle with sub-pixel accuracy and power-modulated color.
CHSV baseColor
Base color (HSV) - saturation increases with age.
Definition particles.h:105
void update(u32 now, u16 numLeds, float speedMultiplier, bool cyclical)
Update position based on velocity × power.
void spawn(u16 numLeds)
Spawn with random position, velocity, color, and lifetime.
float getPower(u32 now) const
bool active
Active flag (false = available for reuse)
Definition particles.h:108
float pos
Position (floating point for sub-pixel rendering)
Definition particles.h:103
float baseVel
Base velocity (actual velocity = baseVel × power)
Definition particles.h:104
u32 lifetime
Lifespan in milliseconds.
Definition particles.h:107
u32 birthTime
Spawn timestamp (ms)
Definition particles.h:106