Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 103 additions & 0 deletions wled00/FX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8958,6 +8958,108 @@ uint16_t mode_particleblobs(void) {
return FRAMETIME;
}
static const char _data_FX_MODE_PARTICLEBLOBS[] PROGMEM = "PS Blobs@Speed,Blobs,Size,Life,Blur,Wobble,Collide,Pulsate;;!;2v;sx=30,ix=64,c1=200,c2=130,c3=0,o3=1";

/*
Particle Galaxy, particles spiral like in a galaxy
Uses palette for particle color
by DedeHai (Damian Schneider)
*/
uint16_t mode_particlegalaxy(void) {
ParticleSystem2D *PartSys = nullptr;
PSsettings2D sourcesettings;
sourcesettings.asByte = 0b00001100; // PS settings for bounceY, bounceY used for source movement (it always bounces whereas particles do not)
if (SEGMENT.call == 0) { // initialization
if (!initParticleSystem2D(PartSys, 1, 0, true)) // init using 1 source and advanced particle settings
return mode_static(); // allocation failed or not 2D
PartSys->sources[0].source.vx = -4; // will collide with wall and get random bounce direction
PartSys->sources[0].source.x = PartSys->maxX >> 1; // start in the center
PartSys->sources[0].source.y = PartSys->maxY >> 1;
PartSys->sources[0].sourceFlags.perpetual = true; //source does not age
PartSys->sources[0].maxLife = 4000; // lifetime in frames
PartSys->sources[0].minLife = 800;
PartSys->sources[0].source.hue = hw_random16(); // start with random color
PartSys->setWallHardness(255); //bounce forever
PartSys->setWallRoughness(200); //randomize wall bounce
}
else {
PartSys = reinterpret_cast<ParticleSystem2D *>(SEGENV.data); // if not first call, just set the pointer to the PS
}
if (PartSys == nullptr)
return mode_static(); // something went wrong, no data!
// Particle System settings
PartSys->updateSystem(); // update system properties (dimensions and data pointers)
uint8_t particlesize = SEGMENT.custom1;
if(SEGMENT.check3)
particlesize = SEGMENT.custom1 ? 1 : 0; // set size to 0 (single pixel) or 1 (quad pixel) so motion blur works and adds streaks
PartSys->setParticleSize(particlesize); // set size globally
PartSys->setMotionBlur(250 * SEGMENT.check3); // adds trails to single/quad pixel particles, no effect if size > 1

if ((SEGMENT.call % ((33 - SEGMENT.custom3) >> 1)) == 0) // change hue of emitted particles
PartSys->sources[0].source.hue+=2;

if (hw_random8() < (10 + (SEGMENT.intensity >> 1))) // 5%-55% chance to emit a particle in this frame
PartSys->sprayEmit(PartSys->sources[0]);

if ((SEGMENT.call & 0x3) == 0) // every 4th frame, move the emitter
PartSys->particleMoveUpdate(PartSys->sources[0].source, PartSys->sources[0].sourceFlags, &sourcesettings);

// move alive particles in a spiral motion (or almost straight in fast starfield mode)
int32_t centerx = PartSys->maxX >> 1; // center of matrix in subpixel coordinates
int32_t centery = PartSys->maxY >> 1;
if (SEGMENT.check2) { // starfield mode
PartSys->setKillOutOfBounds(true);
PartSys->sources[0].var = 7; // emiting variation
PartSys->sources[0].source.x = centerx; // set emitter to center
PartSys->sources[0].source.y = centery;
}
else {
PartSys->setKillOutOfBounds(false);
PartSys->sources[0].var = 1; // emiting variation
}
for (uint32_t i = 0; i < PartSys->usedParticles; i++) { //check all particles
if (PartSys->particles[i].ttl == 0) continue; //skip dead particles
// (dx/dy): vector pointing from particle to center
int32_t dx = centerx - PartSys->particles[i].x;
int32_t dy = centery - PartSys->particles[i].y;
//speed towards center:
int32_t distance = sqrt32_bw(dx * dx + dy * dy); // absolute distance to center
if (distance < 20) distance = 20; // avoid division by zero, keep a minimum
int32_t speedfactor;
if (SEGMENT.check2) { // starfield mode
speedfactor = 1 + (1 + (SEGMENT.speed >> 1)) * distance; // speed increases towards edge
//apply velocity
PartSys->particles[i].x += (-speedfactor * dx) / 400000 - (dy >> 6);
PartSys->particles[i].y += (-speedfactor * dy) / 400000 + (dx >> 6);
}
else {
speedfactor = 2 + (((50 + SEGMENT.speed) << 6) / distance); // speed increases towards center
// rotate clockwise
int32_t tempVx = (-speedfactor * dy); // speed is orthogonal to center vector
int32_t tempVy = (speedfactor * dx);
//add speed towards center to make particles spiral in
int vxc = (dx << 9) / (distance - 19); // subtract value from distance to make the pull-in force a bit stronger (helps on faster speeds)
int vyc = (dy << 9) / (distance - 19);
//apply velocity
PartSys->particles[i].x += (tempVx + vxc) / 1024; // note: cannot use bit shift as that causes asymmetric rounding
PartSys->particles[i].y += (tempVy + vyc) / 1024;

if (distance < 128) { // close to center
if (PartSys->particles[i].ttl > 3)
PartSys->particles[i].ttl -= 4; //age fast
PartSys->particles[i].sat = distance << 1; // turn white towards center
}
}
if(SEGMENT.custom3 == 31) // color by age but mapped to 1024 as particles have a long life, since age is random, this gives more or less random colors
PartSys->particles[i].hue = PartSys->particles[i].ttl >> 2;
else if(SEGMENT.custom3 == 0) // color by distance
PartSys->particles[i].hue = map(distance, 20, (PartSys->maxX + PartSys->maxY) >> 2, 0, 180); // color by distance to center
}

PartSys->update(); // update and render
return FRAMETIME;
}
static const char _data_FX_MODE_PARTICLEGALAXY[] PROGMEM = "PS Galaxy@!,!,Size,,Color,,Starfield,Trace;;!;2;pal=59,sx=80,c1=2,c3=4";

#endif //WLED_DISABLE_PARTICLESYSTEM2D
#endif // WLED_DISABLE_2D

Expand Down Expand Up @@ -10657,6 +10759,7 @@ void WS2812FX::setupEffectData() {
addEffect(FX_MODE_PARTICLECENTERGEQ, &mode_particlecenterGEQ, _data_FX_MODE_PARTICLECIRCULARGEQ);
addEffect(FX_MODE_PARTICLEGHOSTRIDER, &mode_particleghostrider, _data_FX_MODE_PARTICLEGHOSTRIDER);
addEffect(FX_MODE_PARTICLEBLOBS, &mode_particleblobs, _data_FX_MODE_PARTICLEBLOBS);
addEffect(FX_MODE_PARTICLEGALAXY, &mode_particlegalaxy, _data_FX_MODE_PARTICLEGALAXY);
#endif // WLED_DISABLE_PARTICLESYSTEM2D
#endif // WLED_DISABLE_2D

Expand Down
3 changes: 2 additions & 1 deletion wled00/FX.h
Original file line number Diff line number Diff line change
Expand Up @@ -353,7 +353,8 @@ extern byte realtimeMode; // used in getMappedPixelIndex()
#define FX_MODE_PS1DSONICSTREAM 214
#define FX_MODE_PS1DSONICBOOM 215
#define FX_MODE_PS1DSPRINGY 216
#define MODE_COUNT 217
#define FX_MODE_PARTICLEGALAXY 217
#define MODE_COUNT 218


#define BLEND_STYLE_FADE 0x00 // universal
Expand Down
Loading